initial commit
[kugel-rb.git] / firmware / drivers / eeprom_24cxx.c
blob5d26bd8eaf99a89e44957be778f28a24879f3b3b
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2006 by Miika Pekkarinen
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include "logf.h"
23 #include "string.h"
24 #include "inttypes.h"
26 #include "sw_i2c.h"
28 #include "eeprom_24cxx.h"
30 /* Use cache to speedup writing to the chip. */
31 static char data_cache[EEPROM_SIZE];
32 static uint8_t cached_bitfield[EEPROM_SIZE/8];
34 #define IS_CACHED(addr) (cached_bitfield[addr/8] & (1 << (addr % 8)))
35 #define SET_CACHED(addr) (cached_bitfield[addr/8] |= 1 << (addr % 8))
37 void eeprom_24cxx_init(void)
39 sw_i2c_init();
40 memset(cached_bitfield, 0, sizeof cached_bitfield);
43 static int eeprom_24cxx_read_byte(unsigned int address, char *c)
45 int ret;
46 char byte;
47 int count = 0;
49 if (address >= EEPROM_SIZE)
51 logf("EEPROM address: %d", address);
52 return -9;
55 /* Check from cache. */
56 if (IS_CACHED(address))
58 logf("EEPROM RCached: %d", address);
59 *c = data_cache[address];
60 return 0;
63 *c = 0;
66 ret = sw_i2c_read(EEPROM_ADDR, address, &byte, 1);
67 } while (ret < 0 && count++ < 200);
69 if (ret < 0)
71 logf("EEPROM RFail: %d/%d/%d", ret, address, count);
72 return ret;
75 if (count)
77 /* keep between {} as logf is whitespace in normal builds */
78 logf("EEPROM rOK: %d retries", count);
81 /* Cache the byte. */
82 data_cache[address] = byte;
83 SET_CACHED(address);
85 *c = byte;
86 return 0;
89 static int eeprom_24cxx_write_byte(unsigned int address, char c)
91 int ret;
92 int count = 0;
94 if (address >= EEPROM_SIZE)
96 logf("EEPROM address: %d", address);
97 return -9;
100 /* Check from cache. */
101 if (IS_CACHED(address) && data_cache[address] == c)
103 logf("EEPROM WCached: %d", address);
104 return 0;
109 ret = sw_i2c_write(EEPROM_ADDR, address, &c, 1);
110 } while (ret < 0 && count++ < 200) ;
112 if (ret < 0)
114 logf("EEPROM WFail: %d/%d", ret, address);
115 return ret;
118 if (count)
120 /* keep between {} as logf is whitespace in normal builds */
121 logf("EEPROM wOK: %d retries", count);
124 SET_CACHED(address);
125 data_cache[address] = c;
127 return 0;
130 int eeprom_24cxx_read(unsigned char address, void *dest, int length)
132 char *buf = (char *)dest;
133 int ret = 0;
134 int i;
136 for (i = 0; i < length; i++)
138 ret = eeprom_24cxx_read_byte(address+i, &buf[i]);
139 if (ret < 0)
140 return ret;
143 return ret;
146 int eeprom_24cxx_write(unsigned char address, const void *src, int length)
148 const char *buf = (const char *)src;
149 int i;
151 for (i = 0; i < length; i++)
153 if (eeprom_24cxx_write_byte(address+i, buf[i]) < 0)
154 return -1;
157 return 0;