blob: d4798c4ba3fe9a3a419a45dd6ea5f907ca267b3e [file] [log] [blame]
Wolfgang Denk39c76422006-06-16 17:32:31 +02001/* Module for handling DALLAS DS2438, smart battery monitor
2 Chip can store up to 40 bytes of user data in EEPROM,
3 perform temp, voltage and current measurements.
4 Chip also contains a unique serial number.
5
6 Always read/write LSb first
7
8 For documentaion, see data sheet for DS2438, 2438.pdf
9
10 By Thomas.Lange@corelatus.com 001025
Wolfgang Denkba940932006-07-19 13:50:38 +020011
Wolfgang Denk39c76422006-06-16 17:32:31 +020012 Copyright (C) 2000-2005 Corelatus AB */
13
14/* This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License as
16 * published by the Free Software Foundation; either version 2 of
17 * the License, or (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
27 * MA 02111-1307 USA
28 */
29
30#include <common.h>
31#include <command.h>
32#include <asm/au1x00.h>
33#include <asm/io.h>
34#include "ee_dev.h"
35#include "ee_access.h"
36
37/* static int Debug = 1; */
38#undef E_DEBUG
39#define E_DEBUG(fmt,args...) /* */
40/* #define E_DEBUG(fmt,args...) printk("EEA:"fmt,##args); */
41
42/* We dont have kernel functions */
43#define printk printf
44#define KERN_DEBUG
45#define KERN_ERR
46#define EIO 1
47
48#ifndef TRUE
49#define TRUE 1
50#endif
51#ifndef FALSE
52#define FALSE 0
53#endif
54
55/* lookup table ripped from DS app note 17, understanding and using cyclic redundancy checks... */
56
57static u8 crc_lookup[256] = {
58 0, 94, 188, 226, 97, 63, 221, 131,
59 194, 156, 126, 32, 163, 253, 31, 65,
60 157, 195, 33, 127, 252, 162, 64, 30,
61 95, 1, 227, 189, 62, 96, 130, 220,
62 35, 125, 159, 193, 66, 28, 254, 160,
63 225, 191, 93, 3, 128, 222, 60, 98,
64 190, 224, 2, 92, 223, 129, 99, 61,
65 124, 34, 192, 158, 29, 67, 161, 255,
66 70, 24, 250, 164, 39, 121, 155, 197,
67 132, 218, 56, 102, 229, 187, 89, 7,
68 219, 133, 103, 57, 186, 228, 6, 88,
69 25, 71, 165, 251, 120, 38, 196, 154,
70 101, 59, 217, 135, 4, 90, 184, 230,
71 167, 249, 27, 69, 198, 152, 122, 36,
72 248, 166, 68, 26, 153, 199, 37, 123,
73 58, 100, 134, 216, 91, 5, 231, 185,
74 140, 210, 48, 110, 237, 179, 81, 15,
75 78, 16, 242, 172, 47, 113, 147, 205,
76 17, 79, 173, 243, 112, 46, 204, 146,
77 211, 141, 111, 49, 178, 236, 14, 80,
78 175, 241, 19, 77, 206, 144, 114, 44,
79 109, 51, 209, 143, 12, 82, 176, 238,
80 50, 108, 142, 208, 83, 13, 239, 177,
81 240, 174, 76, 18, 145, 207, 45, 115,
82 202, 148, 118, 40, 171, 245, 23, 73,
83 8, 86, 180, 234, 105, 55, 213, 139,
84 87, 9, 235, 181, 54, 104, 138, 212,
85 149, 203, 41, 119, 244, 170, 72, 22,
86 233, 183, 85, 11, 136, 214, 52, 106,
87 43, 117, 151, 201, 74, 20, 246, 168,
88 116, 42, 200, 150, 21, 75, 169, 247,
89 182, 232, 10, 84, 215, 137, 107, 53
90};
91
92static void
93write_gpio_data(int value ){
94 if(value){
95 /* Tristate */
96 gpio_tristate(GPIO_EEDQ);
97 }
98 else{
99 /* Drive 0 */
100 gpio_clear(GPIO_EEDQ);
101 }
102}
103
104static u8 make_new_crc( u8 Old_crc, u8 New_value ){
105 /* Compute a new checksum with new byte, using previous checksum as input
106 See DS app note 17, understanding and using cyclic redundancy checks...
107 Also see DS2438, page 11 */
Wolfgang Denkba940932006-07-19 13:50:38 +0200108 return( crc_lookup[Old_crc ^ New_value ]);
Wolfgang Denk39c76422006-06-16 17:32:31 +0200109}
110
111int ee_crc_ok( u8 *Buffer, int Len, u8 Crc ){
112 /* Check if the checksum for this buffer is correct */
113 u8 Curr_crc=0;
114 int i;
115 u8 *Curr_byte = Buffer;
116
117 for(i=0;i<Len;i++){
118 Curr_crc = make_new_crc( Curr_crc, *Curr_byte);
119 Curr_byte++;
120 }
121 E_DEBUG("Calculated CRC = 0x%x, read = 0x%x\n", Curr_crc, Crc);
Wolfgang Denkba940932006-07-19 13:50:38 +0200122
Wolfgang Denk39c76422006-06-16 17:32:31 +0200123 if(Curr_crc == Crc){
Wolfgang Denkba940932006-07-19 13:50:38 +0200124 /* Good */
Wolfgang Denk39c76422006-06-16 17:32:31 +0200125 return(TRUE);
126 }
127 printk(KERN_ERR"EE checksum error, Calculated CRC = 0x%x, read = 0x%x\n", Curr_crc, Crc);
128 return(FALSE);
129}
130
Wolfgang Denkba940932006-07-19 13:50:38 +0200131static void
Wolfgang Denk39c76422006-06-16 17:32:31 +0200132set_idle(void){
133 /* Send idle and keep start time
134 Continous 1 is idle */
135 WRITE_PORT(1);
136}
137
138
Wolfgang Denkba940932006-07-19 13:50:38 +0200139static int
Wolfgang Denk39c76422006-06-16 17:32:31 +0200140do_cpu_reset(void){
141 /* Release reset and verify that chip responds with presence pulse */
142 int Retries=0;
143 while(Retries<15){
144 udelay(RESET_LOW_TIME);
145
146 /* Send reset */
147 WRITE_PORT(0);
148 udelay(RESET_LOW_TIME);
Wolfgang Denkba940932006-07-19 13:50:38 +0200149
Wolfgang Denk39c76422006-06-16 17:32:31 +0200150 /* Release reset */
151 WRITE_PORT(1);
Wolfgang Denkba940932006-07-19 13:50:38 +0200152
Wolfgang Denk39c76422006-06-16 17:32:31 +0200153 /* Wait for EEPROM to drive output */
154 udelay(PRESENCE_TIMEOUT);
155 if(!READ_PORT){
156 /* Ok, EEPROM is driving a 0 */
157 E_DEBUG("Presence detected\n");
158 if(Retries){
159 E_DEBUG("Retries %d\n",Retries);
160 }
161 /* Make sure chip releases pin */
162 udelay(PRESENCE_LOW_TIME);
163 return 0;
164 }
165 Retries++;
166 }
167
168 printk(KERN_ERR"eeprom did not respond when releasing reset\n");
Wolfgang Denkba940932006-07-19 13:50:38 +0200169
Wolfgang Denk39c76422006-06-16 17:32:31 +0200170 /* Make sure chip releases pin */
171 udelay(PRESENCE_LOW_TIME);
172
173 /* Set to idle again */
174 set_idle();
Wolfgang Denkba940932006-07-19 13:50:38 +0200175
Wolfgang Denk39c76422006-06-16 17:32:31 +0200176 return(-EIO);
177}
178
Wolfgang Denkba940932006-07-19 13:50:38 +0200179static u8
Wolfgang Denk39c76422006-06-16 17:32:31 +0200180read_cpu_byte(void){
181 /* Read a single byte from EEPROM
182 Read LSb first */
183 int i;
184 int Value;
185 u8 Result=0;
186 u32 Flags;
187
188 E_DEBUG("Reading byte\n");
Wolfgang Denkba940932006-07-19 13:50:38 +0200189
Wolfgang Denk39c76422006-06-16 17:32:31 +0200190 for(i=0;i<8;i++){
191 /* Small delay between pulses */
192 udelay(1);
193
Wolfgang Denkba940932006-07-19 13:50:38 +0200194#ifdef __KERNEL__
195 /* Disable irq */
Wolfgang Denk39c76422006-06-16 17:32:31 +0200196 save_flags(Flags);
197 cli();
Wolfgang Denkba940932006-07-19 13:50:38 +0200198#endif
Wolfgang Denk39c76422006-06-16 17:32:31 +0200199
200 /* Pull down pin short time to start read
201 See page 26 in data sheet */
Wolfgang Denkba940932006-07-19 13:50:38 +0200202
Wolfgang Denk39c76422006-06-16 17:32:31 +0200203 WRITE_PORT(0);
204 udelay(READ_LOW);
205 WRITE_PORT(1);
Wolfgang Denkba940932006-07-19 13:50:38 +0200206
Wolfgang Denk39c76422006-06-16 17:32:31 +0200207 /* Wait for chip to drive pin */
208 udelay(READ_TIMEOUT);
Wolfgang Denkba940932006-07-19 13:50:38 +0200209
Wolfgang Denk39c76422006-06-16 17:32:31 +0200210 Value = READ_PORT;
211 if(Value)
212 Value=1;
213
214#ifdef __KERNEL__
Wolfgang Denkba940932006-07-19 13:50:38 +0200215 /* Enable irq */
Wolfgang Denk39c76422006-06-16 17:32:31 +0200216 restore_flags(Flags);
217#endif
Wolfgang Denkba940932006-07-19 13:50:38 +0200218
Wolfgang Denk39c76422006-06-16 17:32:31 +0200219 /* Wait for chip to release pin */
220 udelay(TOTAL_READ_LOW-READ_TIMEOUT);
221
222 /* LSb first */
223 Result|=Value<<i;
224 /* E_DEBUG("Read %d\n",Value); */
225
226 }
227
228 E_DEBUG("Read byte 0x%x\n",Result);
229
230 return(Result);
231}
232
Wolfgang Denkba940932006-07-19 13:50:38 +0200233static void
Wolfgang Denk39c76422006-06-16 17:32:31 +0200234write_cpu_byte(u8 Byte){
235 /* Write a single byte to EEPROM
236 Write LSb first */
237 int i;
238 int Value;
239 u32 Flags;
Wolfgang Denkba940932006-07-19 13:50:38 +0200240
Wolfgang Denk39c76422006-06-16 17:32:31 +0200241 E_DEBUG("Writing byte 0x%x\n",Byte);
Wolfgang Denkba940932006-07-19 13:50:38 +0200242
Wolfgang Denk39c76422006-06-16 17:32:31 +0200243 for(i=0;i<8;i++){
244 /* Small delay between pulses */
245 udelay(1);
246 Value = Byte&1;
Wolfgang Denkba940932006-07-19 13:50:38 +0200247
Wolfgang Denk39c76422006-06-16 17:32:31 +0200248#ifdef __KERNEL__
Wolfgang Denkba940932006-07-19 13:50:38 +0200249 /* Disable irq */
Wolfgang Denk39c76422006-06-16 17:32:31 +0200250 save_flags(Flags);
251 cli();
Wolfgang Denkba940932006-07-19 13:50:38 +0200252#endif
Wolfgang Denk39c76422006-06-16 17:32:31 +0200253
254 /* Pull down pin short time for a 1, long time for a 0
255 See page 26 in data sheet */
Wolfgang Denkba940932006-07-19 13:50:38 +0200256
Wolfgang Denk39c76422006-06-16 17:32:31 +0200257 WRITE_PORT(0);
258 if(Value){
259 /* Write a 1 */
260 udelay(WRITE_1_LOW);
261 }
262 else{
263 /* Write a 0 */
264 udelay(WRITE_0_LOW);
265 }
266
267 WRITE_PORT(1);
268
269#ifdef __KERNEL__
Wolfgang Denkba940932006-07-19 13:50:38 +0200270 /* Enable irq */
Wolfgang Denk39c76422006-06-16 17:32:31 +0200271 restore_flags(Flags);
272#endif
273
274 if(Value)
275 /* Wait for chip to read the 1 */
276 udelay(TOTAL_WRITE_LOW-WRITE_1_LOW);
Wolfgang Denkba940932006-07-19 13:50:38 +0200277
Wolfgang Denk39c76422006-06-16 17:32:31 +0200278 /* E_DEBUG("Wrote %d\n",Value); */
279 Byte>>=1;
280 }
281}
282
283int ee_do_cpu_command( u8 *Tx, int Tx_len, u8 *Rx, int Rx_len, int Send_skip ){
Wolfgang Denkba940932006-07-19 13:50:38 +0200284 /* Execute this command string, including
Wolfgang Denk39c76422006-06-16 17:32:31 +0200285 giving reset and setting to idle after command
Wolfgang Denkba940932006-07-19 13:50:38 +0200286 if Rx_len is set, we read out data from EEPROM */
Wolfgang Denk39c76422006-06-16 17:32:31 +0200287 int i;
288
289 E_DEBUG("Command, Tx_len %d, Rx_len %d\n", Tx_len, Rx_len );
Wolfgang Denkba940932006-07-19 13:50:38 +0200290
Wolfgang Denk39c76422006-06-16 17:32:31 +0200291 if(do_cpu_reset()){
292 /* Failed! */
293 return(-EIO);
294 }
295
296 if(Send_skip)
Wolfgang Denkba940932006-07-19 13:50:38 +0200297 /* Always send SKIP_ROM first to tell chip we are sending a command,
Wolfgang Denk39c76422006-06-16 17:32:31 +0200298 except when we read out rom data for chip */
299 write_cpu_byte(SKIP_ROM);
Wolfgang Denkba940932006-07-19 13:50:38 +0200300
Wolfgang Denk39c76422006-06-16 17:32:31 +0200301 /* Always have Tx data */
302 for(i=0;i<Tx_len;i++){
303 write_cpu_byte(Tx[i]);
304 }
Wolfgang Denkba940932006-07-19 13:50:38 +0200305
Wolfgang Denk39c76422006-06-16 17:32:31 +0200306 if(Rx_len){
307 for(i=0;i<Rx_len;i++){
308 Rx[i]=read_cpu_byte();
309 }
310 }
Wolfgang Denkba940932006-07-19 13:50:38 +0200311
Wolfgang Denk39c76422006-06-16 17:32:31 +0200312 set_idle();
313
314 E_DEBUG("Command done\n");
315
316 return(0);
Wolfgang Denkba940932006-07-19 13:50:38 +0200317}
Wolfgang Denk39c76422006-06-16 17:32:31 +0200318
319int ee_init_cpu_data(void){
320 int i;
321 u8 Tx[10];
322
323 /* Leave it floting since altera is driving the same pin */
324 set_idle();
325
Wolfgang Denkba940932006-07-19 13:50:38 +0200326 /* Copy all User EEPROM data to scratchpad */
Wolfgang Denk39c76422006-06-16 17:32:31 +0200327 for(i=0;i<USER_PAGES;i++){
328 Tx[0]=RECALL_MEMORY;
329 Tx[1]=EE_USER_PAGE_0+i;
330 if(ee_do_cpu_command(Tx,2,NULL,0,TRUE)) return(-EIO);
331 }
332
333 /* Make sure chip doesnt store measurements in NVRAM */
334 Tx[0]=WRITE_SCRATCHPAD;
Wolfgang Denkba940932006-07-19 13:50:38 +0200335 Tx[1]=0; /* Page */
Wolfgang Denk39c76422006-06-16 17:32:31 +0200336 Tx[2]=9;
337 if(ee_do_cpu_command(Tx,3,NULL,0,TRUE)) return(-EIO);
338
339 Tx[0]=COPY_SCRATCHPAD;
340 if(ee_do_cpu_command(Tx,2,NULL,0,TRUE)) return(-EIO);
Wolfgang Denkba940932006-07-19 13:50:38 +0200341
Wolfgang Denk39c76422006-06-16 17:32:31 +0200342 for(i=0;i<10;i++){
343 udelay(1000);
344 }
Wolfgang Denkba940932006-07-19 13:50:38 +0200345
Wolfgang Denk39c76422006-06-16 17:32:31 +0200346 return(0);
347}