rockbox/firmware/drivers/eeprom_24cxx.c
Daniel Stenberg 2acc0ac542 Updated our source code header to explicitly mention that we are GPL v2 or
later. We still need to hunt down snippets used that are not. 1324 modified
files...
http://www.rockbox.org/mail/archive/rockbox-dev-archive-2008-06/0060.shtml


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@17847 a1c6a512-1295-4272-9138-f99709370657
2008-06-28 18:10:04 +00:00

159 lines
3.7 KiB
C

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2006 by Miika Pekkarinen
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "logf.h"
#include "string.h"
#include "inttypes.h"
#include "sw_i2c.h"
#include "eeprom_24cxx.h"
/* Use cache to speedup writing to the chip. */
static char data_cache[EEPROM_SIZE];
static uint8_t cached_bitfield[EEPROM_SIZE/8];
#define IS_CACHED(addr) (cached_bitfield[addr/8] & (1 << (addr % 8)))
#define SET_CACHED(addr) (cached_bitfield[addr/8] |= 1 << (addr % 8))
void eeprom_24cxx_init(void)
{
sw_i2c_init();
memset(cached_bitfield, 0, sizeof cached_bitfield);
}
int eeprom_24cxx_read_byte(unsigned int address, char *c)
{
int ret;
char byte;
int count = 0;
if (address >= EEPROM_SIZE)
{
logf("EEPROM address: %d", address);
return -9;
}
/* Check from cache. */
if (IS_CACHED(address))
{
logf("EEPROM RCached: %d", address);
*c = data_cache[address];
return 0;
}
*c = 0;
do
{
ret = sw_i2c_read(EEPROM_ADDR, address, &byte, 1);
} while (ret < 0 && count++ < 200);
if (ret < 0)
{
logf("EEPROM RFail: %d/%d/%d", ret, address, count);
return ret;
}
if (count)
{
/* keep between {} as logf is whitespace in normal builds */
logf("EEPROM rOK: %d retries", count);
}
/* Cache the byte. */
data_cache[address] = byte;
SET_CACHED(address);
*c = byte;
return 0;
}
int eeprom_24cxx_write_byte(unsigned int address, char c)
{
int ret;
int count = 0;
if (address >= EEPROM_SIZE)
{
logf("EEPROM address: %d", address);
return -9;
}
/* Check from cache. */
if (IS_CACHED(address) && data_cache[address] == c)
{
logf("EEPROM WCached: %d", address);
return 0;
}
do
{
ret = sw_i2c_write(EEPROM_ADDR, address, &c, 1);
} while (ret < 0 && count++ < 200) ;
if (ret < 0)
{
logf("EEPROM WFail: %d/%d", ret, address);
return ret;
}
if (count)
{
/* keep between {} as logf is whitespace in normal builds */
logf("EEPROM wOK: %d retries", count);
}
SET_CACHED(address);
data_cache[address] = c;
return 0;
}
int eeprom_24cxx_read(unsigned char address, void *dest, int length)
{
char *buf = (char *)dest;
int ret = 0;
int i;
for (i = 0; i < length; i++)
{
ret = eeprom_24cxx_read_byte(address+i, &buf[i]);
if (ret < 0)
return ret;
}
return ret;
}
int eeprom_24cxx_write(unsigned char address, const void *src, int length)
{
const char *buf = (const char *)src;
int i;
for (i = 0; i < length; i++)
{
if (eeprom_24cxx_write_byte(address+i, buf[i]) < 0)
return -1;
}
return 0;
}