]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/gth/ee_access.c
imported Freescale specific U-Boot additions for i.MX28,... release L2.6.31_10.08.01
[karo-tx-uboot.git] / board / gth / ee_access.c
1 /* 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 */
11
12 #include <common.h>
13 #include <config.h>
14 #include <mpc8xx.h>
15
16 #include <../board/gth/ee_dev.h>
17
18 /* We dont have kernel functions */
19 #define printk printf
20 #define KERN_DEBUG
21 #define KERN_ERR
22 #define EIO 1
23
24 static int Debug = 0;
25
26 #ifndef TRUE
27 #define TRUE 1
28 #endif
29 #ifndef FALSE
30 #define FALSE 0
31 #endif
32
33 /*
34  * lookup table ripped from DS app note 17, understanding and using
35  * cyclic redundancy checks...
36  */
37
38 static u8 crc_lookup[256] = {
39         0,      94,     188,    226,    97,     63,     221,    131,
40         194,    156,    126,    32,     163,    253,    31,     65,
41         157,    195,    33,     127,    252,    162,    64,     30,
42         95,     1,      227,    189,    62,     96,     130,    220,
43         35,     125,    159,    193,    66,     28,     254,    160,
44         225,    191,    93,     3,      128,    222,    60,     98,
45         190,    224,    2,      92,     223,    129,    99,     61,
46         124,    34,     192,    158,    29,     67,     161,    255,
47         70,     24,     250,    164,    39,     121,    155,    197,
48         132,    218,    56,     102,    229,    187,    89,     7,
49         219,    133,    103,    57,     186,    228,    6,      88,
50         25,     71,     165,    251,    120,    38,     196,    154,
51         101,    59,     217,    135,    4,      90,     184,    230,
52         167,    249,    27,     69,     198,    152,    122,    36,
53         248,    166,    68,     26,     153,    199,    37,     123,
54         58,     100,    134,    216,    91,     5,      231,    185,
55         140,    210,    48,     110,    237,    179,    81,     15,
56         78,     16,     242,    172,    47,     113,    147,    205,
57         17,     79,     173,    243,    112,    46,     204,    146,
58         211,    141,    111,    49,     178,    236,    14,     80,
59         175,    241,    19,     77,     206,    144,    114,    44,
60         109,    51,     209,    143,    12,     82,     176,    238,
61         50,     108,    142,    208,    83,     13,     239,    177,
62         240,    174,    76,     18,     145,    207,    45,     115,
63         202,    148,    118,    40,     171,    245,    23,     73,
64         8,      86,     180,    234,    105,    55,     213,    139,
65         87,     9,      235,    181,    54,     104,    138,    212,
66         149,    203,    41,     119,    244,    170,    72,     22,
67         233,    183,    85,     11,     136,    214,    52,     106,
68         43,     117,    151,    201,    74,     20,     246,    168,
69         116,    42,     200,    150,    21,     75,     169,    247,
70         182,    232,    10,     84,     215,    137,    107,    53
71 };
72
73 static u8 make_new_crc( u8 Old_crc, u8 New_value ){
74   /* Compute a new checksum with new byte, using previous checksum as input
75      See DS app note 17, understanding and using cyclic redundancy checks...
76      Also see DS2438, page 11 */
77   return( crc_lookup[Old_crc ^ New_value ]);
78 }
79
80 int ee_crc_ok( u8 *Buffer, int Len, u8 Crc ){
81   /* Check if the checksum for this buffer is correct */
82   u8 Curr_crc=0;
83   int i;
84   u8 *Curr_byte = Buffer;
85
86   for(i=0;i<Len;i++){
87     Curr_crc = make_new_crc( Curr_crc, *Curr_byte);
88     Curr_byte++;
89   }
90   E_DEBUG("Calculated CRC = 0x%x, read = 0x%x\n", Curr_crc, Crc);
91
92   if(Curr_crc == Crc){
93     /* Good */
94     return(TRUE);
95   }
96   printk(KERN_ERR"EE checksum error, Calculated CRC = 0x%x, read = 0x%x\n",
97         Curr_crc, Crc);
98   return(FALSE);
99 }
100
101 static void
102 set_idle(void){
103   /* Send idle and keep start time
104      Continous 1 is idle */
105   WRITE_PORT(1);
106 }
107
108 static int
109 do_reset(void){
110   /* Release reset and verify that chip responds with presence pulse */
111   int Retries = 0;
112   while(Retries<5){
113     udelay(RESET_LOW_TIME);
114
115     /* Send reset */
116     WRITE_PORT(0);
117     udelay(RESET_LOW_TIME);
118
119     /* Release reset */
120     WRITE_PORT(1);
121
122     /* Wait for EEPROM to drive output */
123     udelay(PRESENCE_TIMEOUT);
124     if(!READ_PORT){
125       /* Ok, EEPROM is driving a 0 */
126       E_DEBUG("Presence detected\n");
127       if(Retries){
128         E_DEBUG("Retries %d\n",Retries);
129       }
130       /* Make sure chip releases pin */
131       udelay(PRESENCE_LOW_TIME);
132       return 0;
133     }
134     Retries++;
135   }
136
137   printk(KERN_ERR"EEPROM did not respond when releasing reset\n");
138
139     /* Make sure chip releases pin */
140   udelay(PRESENCE_LOW_TIME);
141
142   /* Set to idle again */
143   set_idle();
144
145   return(-EIO);
146 }
147
148 static u8
149 read_byte(void){
150   /* Read a single byte from EEPROM
151      Read LSb first */
152   int i;
153   int Value;
154   u8 Result=0;
155 #ifndef CONFIG_SYS_IMMR
156   u32 Flags;
157 #endif
158
159   E_DEBUG("Reading byte\n");
160
161   for(i=0;i<8;i++){
162     /* Small delay between pulses */
163     udelay(1);
164
165 #ifndef CONFIG_SYS_IMMR
166     /* Disable irq */
167     save_flags(Flags);
168     cli();
169 #endif
170
171     /* Pull down pin short time to start read
172        See page 26 in data sheet */
173
174     WRITE_PORT(0);
175     udelay(READ_LOW);
176     WRITE_PORT(1);
177
178     /* Wait for chip to drive pin */
179     udelay(READ_TIMEOUT);
180
181     Value = READ_PORT;
182     if(Value)
183       Value=1;
184
185 #ifndef CONFIG_SYS_IMMR
186     /* Enable irq */
187     restore_flags(Flags);
188 #endif
189
190     /* Wait for chip to release pin */
191     udelay(TOTAL_READ_LOW-READ_TIMEOUT);
192
193     /* LSb first */
194     Result|=Value<<i;
195   }
196
197   E_DEBUG("Read byte 0x%x\n",Result);
198
199   return(Result);
200 }
201
202 static void
203 write_byte(u8 Byte){
204   /* Write a single byte to EEPROM
205      Write LSb first */
206   int i;
207   int Value;
208 #ifndef CONFIG_SYS_IMMR
209   u32 Flags;
210 #endif
211
212   E_DEBUG("Writing byte 0x%x\n",Byte);
213
214   for(i=0;i<8;i++){
215     /* Small delay between pulses */
216     udelay(1);
217     Value = Byte&1;
218
219 #ifndef CONFIG_SYS_IMMR
220     /* Disable irq */
221     save_flags(Flags);
222     cli();
223 #endif
224
225     /* Pull down pin short time for a 1, long time for a 0
226        See page 26 in data sheet */
227
228     WRITE_PORT(0);
229     if(Value){
230       /* Write a 1 */
231       udelay(WRITE_1_LOW);
232     }
233     else{
234       /* Write a 0 */
235       udelay(WRITE_0_LOW);
236     }
237
238     WRITE_PORT(1);
239
240 #ifndef CONFIG_SYS_IMMR
241     /* Enable irq */
242     restore_flags(Flags);
243 #endif
244
245     if(Value)
246       /* Wait for chip to read the 1 */
247       udelay(TOTAL_WRITE_LOW-WRITE_1_LOW);
248     Byte>>=1;
249   }
250 }
251
252 int ee_do_command( u8 *Tx, int Tx_len, u8 *Rx, int Rx_len, int Send_skip ){
253   /* Execute this command string, including
254      giving reset and setting to idle after command
255      if Rx_len is set, we read out data from EEPROM */
256   int i;
257
258   E_DEBUG("Command, Tx_len %d, Rx_len %d\n", Tx_len, Rx_len );
259
260   if(do_reset()){
261     /* Failed! */
262     return(-EIO);
263   }
264
265   if(Send_skip)
266     /* Always send SKIP_ROM first to tell chip we are sending a command,
267        except when we read out rom data for chip */
268     write_byte(SKIP_ROM);
269
270   /* Always have Tx data */
271   for(i=0;i<Tx_len;i++){
272     write_byte(Tx[i]);
273   }
274
275   if(Rx_len){
276     for(i=0;i<Rx_len;i++){
277       Rx[i]=read_byte();
278     }
279   }
280
281   set_idle();
282
283   E_DEBUG("Command done\n");
284
285   return(0);
286 }
287
288 int ee_init_data(void){
289   int i;
290   u8 Tx[10];
291   int tmp;
292   volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
293
294   while(0){
295     tmp = 1-tmp;
296     if(tmp)
297       immap->im_ioport.iop_padat &= ~PA_FRONT_LED;
298     else
299       immap->im_ioport.iop_padat |= PA_FRONT_LED;
300     udelay(1);
301   }
302
303   /* Set port to open drain to be able to read data from
304      port without setting it to input */
305   PORT_B_PAR &= ~PB_EEPROM;
306   PORT_B_ODR |= PB_EEPROM;
307   SET_PORT_B_OUTPUT(PB_EEPROM);
308
309   /* Set idle mode */
310   set_idle();
311
312   /* Copy all User EEPROM data to scratchpad */
313   for(i=0;i<USER_PAGES;i++){
314     Tx[0]=RECALL_MEMORY;
315     Tx[1]=EE_USER_PAGE_0+i;
316     if(ee_do_command(Tx,2,NULL,0,TRUE)) return(-EIO);
317   }
318
319   /* Make sure chip doesnt store measurements in NVRAM */
320   Tx[0]=WRITE_SCRATCHPAD;
321   Tx[1]=0; /* Page */
322   Tx[2]=9;
323   if(ee_do_command(Tx,3,NULL,0,TRUE)) return(-EIO);
324
325   Tx[0]=COPY_SCRATCHPAD;
326   if(ee_do_command(Tx,2,NULL,0,TRUE)) return(-EIO);
327
328   /* FIXME check status bit instead
329      Could take 10 ms to store in EEPROM */
330   for(i=0;i<10;i++){
331     udelay(1000);
332   }
333
334   return(0);
335 }