uboot/board/gth2/ee_access.c
<<
>>
Prefs
   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}
 348