source: SVN/rincon/u-boot/board/gth2/ee_access.c @ 55

Last change on this file since 55 was 55, checked in by Tim Harvey, 22 months ago

rincon: added latest u-boot source

restored form server backup

Signed-off-by: Tim Harvey <tharvey@…>

File size: 7.5 KB
Line 
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   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 */
108        return( crc_lookup[Old_crc ^ New_value ]);
109}
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);
122
123        if(Curr_crc == Crc){
124                /* Good */
125                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
131static void
132set_idle(void){
133        /* Send idle and keep start time
134           Continous 1 is idle */
135        WRITE_PORT(1);
136}
137
138
139static int
140do_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);
149
150                /* Release reset */
151                WRITE_PORT(1);
152
153                /* 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");
169
170        /* Make sure chip releases pin */
171        udelay(PRESENCE_LOW_TIME);
172
173        /* Set to idle again */
174        set_idle();
175
176        return(-EIO);
177}
178
179static u8
180read_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");
189
190        for(i=0;i<8;i++){
191                /* Small delay between pulses */
192                udelay(1);
193
194#ifdef __KERNEL__
195                /* Disable irq */
196                save_flags(Flags);
197                cli();
198#endif
199
200                /* Pull down pin short time to start read
201                   See page 26 in data sheet */
202
203                WRITE_PORT(0);
204                udelay(READ_LOW);
205                WRITE_PORT(1);
206
207                /* Wait for chip to drive pin */
208                udelay(READ_TIMEOUT);
209
210                Value = READ_PORT;
211                if(Value)
212                        Value=1;
213
214#ifdef __KERNEL__
215                /* Enable irq */
216                restore_flags(Flags);
217#endif
218
219                /* 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
233static void
234write_cpu_byte(u8 Byte){
235        /* Write a single byte to EEPROM
236           Write LSb first */
237        int i;
238        int Value;
239        u32 Flags;
240
241        E_DEBUG("Writing byte 0x%x\n",Byte);
242
243        for(i=0;i<8;i++){
244                /* Small delay between pulses */
245                udelay(1);
246                Value = Byte&1;
247
248#ifdef __KERNEL__
249                /* Disable irq */
250                save_flags(Flags);
251                cli();
252#endif
253
254                /* Pull down pin short time for a 1, long time for a 0
255                   See page 26 in data sheet */
256
257                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__
270                /* Enable irq */
271                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);
277
278                /* 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 ){
284        /* Execute this command string, including
285           giving reset and setting to idle after command
286           if Rx_len is set, we read out data from EEPROM */
287        int i;
288
289        E_DEBUG("Command, Tx_len %d, Rx_len %d\n", Tx_len, Rx_len );
290
291        if(do_cpu_reset()){
292                /* Failed! */
293                return(-EIO);
294        }
295
296        if(Send_skip)
297                /* Always send SKIP_ROM first to tell chip we are sending a command,
298                   except when we read out rom data for chip */
299                write_cpu_byte(SKIP_ROM);
300
301        /* Always have Tx data */
302        for(i=0;i<Tx_len;i++){
303                write_cpu_byte(Tx[i]);
304        }
305
306        if(Rx_len){
307                for(i=0;i<Rx_len;i++){
308                        Rx[i]=read_cpu_byte();
309                }
310        }
311
312        set_idle();
313
314        E_DEBUG("Command done\n");
315
316        return(0);
317}
318
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
326        /* Copy all User EEPROM data to scratchpad */
327        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;
335        Tx[1]=0; /* Page */
336        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);
341
342        for(i=0;i<10;i++){
343                udelay(1000);
344        }
345
346        return(0);
347}
Note: See TracBrowser for help on using the repository browser.