eeprom driver for the h3x0 series, cleaned up the h1x0 series driver a bit, added debug entry for h3x0 that allows to write to the eeprom
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10597 a1c6a512-1295-4272-9138-f99709370657
diff --git a/apps/debug_menu.c b/apps/debug_menu.c
index 0141c77..1527e8a 100644
--- a/apps/debug_menu.c
+++ b/apps/debug_menu.c
@@ -1891,13 +1891,22 @@
fd = creat("/internal_eeprom.bin", O_WRONLY);
if (fd >= 0)
{
+ int old_irq_level;
char buf[EEPROM_SIZE];
-
- if (eeprom_24cxx_read(0, buf, sizeof buf))
- gui_syncsplash(HZ*3, true, "Eeprom read failure!");
+ int err;
+
+ old_irq_level = set_irq_level(HIGHEST_IRQ_LEVEL);
+
+ err = eeprom_24cxx_read(0, buf, sizeof buf);
+ if (err)
+ gui_syncsplash(HZ*3, true, "Eeprom read failure (%d)",err);
else
+ {
write(fd, buf, sizeof buf);
-
+ }
+
+ set_irq_level(old_irq_level);
+
close(fd);
}
#endif
@@ -1976,6 +1985,46 @@
}
#endif /* CONFIG_CPU == SH7034 || defined(CPU_COLDFIRE) */
+#if defined(HAVE_EEPROM) && !defined(HAVE_EEPROM_SETTINGS)
+bool dbg_write_eeprom(void)
+{
+ int fd;
+ int rc;
+ int old_irq_level;
+ char buf[EEPROM_SIZE];
+ int err;
+
+ fd = open("/internal_eeprom.bin", O_RDONLY);
+
+ if (fd >= 0)
+ {
+ rc = read(fd, buf, EEPROM_SIZE);
+
+ if(rc == EEPROM_SIZE)
+ {
+ old_irq_level = set_irq_level(HIGHEST_IRQ_LEVEL);
+
+ err = eeprom_24cxx_write(0, buf, sizeof buf);
+ if (err)
+ gui_syncsplash(HZ*3, true, "Eeprom write failure (%d)",err);
+
+ set_irq_level(old_irq_level);
+ }
+ else
+ {
+ gui_syncsplash(HZ*3, true, "File read error (%d)",rc);
+ }
+ close(fd);
+ }
+ else
+ {
+ gui_syncsplash(HZ*3, true, "Failed to open 'internal_eeprom.bin'");
+ }
+
+ return false;
+}
+#endif /* defined(HAVE_EEPROM) && !defined(HAVE_EEPROM_SETTINGS) */
+
bool debug_menu(void)
{
int m;
@@ -2023,6 +2072,9 @@
#ifdef CONFIG_TUNER
{ "FM Radio", dbg_fm_radio },
#endif
+#if defined(HAVE_EEPROM) && !defined(HAVE_EEPROM_SETTINGS)
+ { "Write back EEPROM", dbg_write_eeprom },
+#endif
#ifdef ROCKBOX_HAS_LOGF
{"logf", logfdisplay },
{"logfdump", logfdump },
diff --git a/apps/main.c b/apps/main.c
index c50af86..90bd13e 100644
--- a/apps/main.c
+++ b/apps/main.c
@@ -120,7 +120,7 @@
if (global_settings.dircache)
{
-# ifdef HAVE_EEPROM
+# ifdef HAVE_EEPROM_SETTINGS
if (firmware_settings.initialized && firmware_settings.disk_clean
&& preinit)
{
@@ -371,14 +371,14 @@
panicf("ata: %d", rc);
}
-#ifdef HAVE_EEPROM
+#ifdef HAVE_EEPROM_SETTINGS
eeprom_settings_init();
#endif
usb_start_monitoring();
while (usb_detect())
{
-#ifdef HAVE_EEPROM
+#ifdef HAVE_EEPROM_SETTINGS
firmware_settings.disk_clean = false;
#endif
/* enter USB mode early, before trying to mount */
@@ -444,7 +444,7 @@
init_dircache(false);
init_tagcache();
-#ifdef HAVE_EEPROM
+#ifdef HAVE_EEPROM_SETTINGS
if (firmware_settings.initialized)
{
/* In case we crash. */
diff --git a/apps/misc.c b/apps/misc.c
index ffacf7e..19cee60 100644
--- a/apps/misc.c
+++ b/apps/misc.c
@@ -507,7 +507,7 @@
callback(parameter);
system_flush();
-#ifdef HAVE_EEPROM
+#ifdef HAVE_EEPROM_SETTINGS
if (firmware_settings.initialized)
{
firmware_settings.disk_clean = true;
diff --git a/apps/tagcache.c b/apps/tagcache.c
index 179218a..191c245 100644
--- a/apps/tagcache.c
+++ b/apps/tagcache.c
@@ -153,7 +153,7 @@
int entry_count[TAG_COUNT]; /* Number of entries in the indices. */
};
-# ifdef HAVE_EEPROM
+# ifdef HAVE_EEPROM_SETTINGS
struct statefile_header {
struct ramcache_header *hdr;
struct tagcache_stat stat;
@@ -2829,7 +2829,7 @@
return true;
}
-# ifdef HAVE_EEPROM
+# ifdef HAVE_EEPROM_SETTINGS
static bool tagcache_dumpload(void)
{
struct statefile_header shdr;
@@ -3370,7 +3370,7 @@
free_tempbuf();
#ifdef HAVE_TC_RAMCACHE
-# ifdef HAVE_EEPROM
+# ifdef HAVE_EEPROM_SETTINGS
if (firmware_settings.initialized && firmware_settings.disk_clean)
check_done = tagcache_dumpload();
@@ -3462,7 +3462,7 @@
if (tagcache_get_commit_step() > 0)
return false;
-#ifdef HAVE_EEPROM
+#ifdef HAVE_EEPROM_SETTINGS
if (stat.ramcache)
tagcache_dumpsave();
#endif
diff --git a/apps/tree.c b/apps/tree.c
index 1bbb5f8..75562b3 100644
--- a/apps/tree.c
+++ b/apps/tree.c
@@ -1336,7 +1336,7 @@
if (global_settings.dircache)
{
global_settings.dircache_size = dircache_get_cache_size();
-# ifdef HAVE_EEPROM
+# ifdef HAVE_EEPROM_SETTINGS
if (dircache_is_enabled() && firmware_settings.initialized)
dircache_save(DIRCACHE_FILE);
# endif
@@ -1352,7 +1352,7 @@
void tree_restore(void)
{
-#ifdef HAVE_EEPROM
+#ifdef HAVE_EEPROM_SETTINGS
firmware_settings.disk_clean = false;
#endif
diff --git a/bootloader/main.c b/bootloader/main.c
index 0b05827..7c2b125 100644
--- a/bootloader/main.c
+++ b/bootloader/main.c
@@ -357,7 +357,7 @@
power_off();
}
-#ifdef HAVE_EEPROM
+#ifdef HAVE_EEPROM_SETTINGS
firmware_settings.initialized = false;
#endif
if (detect_flashed_rockbox())
@@ -365,7 +365,7 @@
bool load_from_flash;
load_from_flash = !rec_button;
-#ifdef HAVE_EEPROM
+#ifdef HAVE_EEPROM_SETTINGS
if (eeprom_settings_init())
{
/* If bootloader version has not been reset, disk might
@@ -389,7 +389,7 @@
lcd_update();
if (i == 0)
{
-#ifdef HAVE_EEPROM
+#ifdef HAVE_EEPROM_SETTINGS
eeprom_settings_store();
#endif
start_firmware();
@@ -457,7 +457,7 @@
sleep(HZ);
#endif
-#ifdef HAVE_EEPROM
+#ifdef HAVE_EEPROM_SETTINGS
if (firmware_settings.initialized)
{
firmware_settings.disk_clean = false;
@@ -503,7 +503,7 @@
printf("Result: %d", i);
lcd_update();
-#ifdef HAVE_EEPROM
+#ifdef HAVE_EEPROM_SETTINGS
if (firmware_settings.initialized)
eeprom_settings_store();
#endif
diff --git a/firmware/SOURCES b/firmware/SOURCES
index fda83ee..23da475 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -150,8 +150,10 @@
#endif
#ifdef HAVE_EEPROM
drivers/eeprom_24cxx.c
+#ifdef HAVE_EEPROM_SETTINGS
eeprom_settings.c
#endif
+#endif
#ifdef IPOD_ARCH
drivers/pcf50605.c
#endif
diff --git a/firmware/drivers/eeprom_24cxx.c b/firmware/drivers/eeprom_24cxx.c
index 9a8fa5d..66bc235 100644
--- a/firmware/drivers/eeprom_24cxx.c
+++ b/firmware/drivers/eeprom_24cxx.c
@@ -35,21 +35,24 @@
#define SW_I2C_WRITE 0
#define SW_I2C_READ 1
+/* h1x0 needs its own i2c driver,
+ h3x0 uses the pcf i2c driver */
+
+#ifdef IRIVER_H100_SERIES
+
/* cute little functions, atomic read-modify-write */
/* SCL is GPIO, 12 */
-#define SCL_LO and_l(~0x00001000, &GPIO_OUT) // and_b(~0x10, &PBDRL)
-#define SCL_HI or_l( 0x00001000, &GPIO_OUT) // or_b( 0x10, &PBDRL)
-#define SCL_INPUT and_l(~0x00001000, &GPIO_ENABLE) // and_b(~0x10, &PBIORL)
-#define SCL_OUTPUT or_l( 0x00001000, &GPIO_ENABLE) // or_b( 0x10, &PBIORL)
-#define SCL ( 0x00001000 & GPIO_READ) // (PBDR & 0x0010)
+#define SCL ( 0x00001000 & GPIO_READ)
+#define SCL_OUT_LO and_l(~0x00001000, &GPIO_OUT)
+#define SCL_LO or_l( 0x00001000, &GPIO_ENABLE)
+#define SCL_HI and_l(~0x00001000, &GPIO_ENABLE); while(!SCL);
/* SDA is GPIO1, 13 */
-#define SDA_LO and_l(~0x00002000, &GPIO1_OUT) // and_b(~0x02, &PBDRL)
-#define SDA_HI or_l( 0x00002000, &GPIO1_OUT) // or_b( 0x02, &PBDRL)
-#define SDA_INPUT and_l(~0x00002000, &GPIO1_ENABLE) // and_b(~0x02, &PBIORL)
-#define SDA_OUTPUT or_l( 0x00002000, &GPIO1_ENABLE) // or_b( 0x02, &PBIORL)
-#define SDA ( 0x00002000 & GPIO1_READ) // (PBDR & 0x0002)
+#define SDA ( 0x00002000 & GPIO1_READ)
+#define SDA_OUT_LO and_l(~0x00002000, &GPIO1_OUT)
+#define SDA_LO or_l( 0x00002000, &GPIO1_ENABLE)
+#define SDA_HI and_l(~0x00002000, &GPIO1_ENABLE)
/* delay loop to achieve 400kHz at 120MHz CPU frequency */
#define DELAY do { int _x; for(_x=0;_x<22;_x++);} while(0)
@@ -61,17 +64,15 @@
or_l(0x00002000, &GPIO1_FUNCTION);
SDA_HI;
SCL_HI;
- SDA_OUTPUT;
- SCL_OUTPUT;
+ SDA_OUT_LO;
+ SCL_OUT_LO;
}
static void sw_i2c_start(void)
{
SCL_LO;
- SCL_OUTPUT;
DELAY;
SDA_HI;
- SDA_OUTPUT;
DELAY;
SCL_HI;
DELAY;
@@ -88,7 +89,6 @@
DELAY;
}
-
static void sw_i2c_ack(void)
{
SCL_LO;
@@ -105,7 +105,7 @@
int count = 10;
SCL_LO;
- SDA_INPUT; /* And set to input */
+ SDA_HI; /* sets to input */
DELAY;
SCL_HI;
DELAY;
@@ -118,10 +118,8 @@
ret = false;
SCL_LO;
- SCL_OUTPUT;
DELAY;
SDA_LO;
- SDA_OUTPUT;
return ret;
}
@@ -143,8 +141,6 @@
SCL_HI;
DELAY;
}
-
- // SDA_LO;
}
static unsigned char sw_i2c_inb(void)
@@ -152,7 +148,7 @@
int i;
unsigned char byte = 0;
- SDA_INPUT; /* And set to input */
+ SDA_HI; /* sets to input */
/* clock in each bit, MSB first */
for ( i=0x80; i; i>>=1 )
@@ -165,13 +161,26 @@
DELAY;
}
- SDA_OUTPUT;
-
sw_i2c_ack();
return byte;
}
+#else
+
+#include "pcf50606.h"
+
+#define sw_i2c_init() /* no extra init required */
+#define sw_i2c_start() pcf50606_i2c_start()
+#define sw_i2c_stop() pcf50606_i2c_stop()
+#define sw_i2c_ack() pcf50606_i2c_ack(true)
+#define sw_i2c_getack() pcf50606_i2c_getack()
+#define sw_i2c_outb(x) pcf50606_i2c_outb(x)
+#define sw_i2c_inb() pcf50606_i2c_inb(false)
+
+#endif /* IRIVER_H100_SERIES */
+
+
int sw_i2c_write(int location, const unsigned char* buf, int count)
{
int i;
diff --git a/firmware/drivers/pcf50606.c b/firmware/drivers/pcf50606.c
index 0f2d736..28df295 100644
--- a/firmware/drivers/pcf50606.c
+++ b/firmware/drivers/pcf50606.c
@@ -52,7 +52,7 @@
i2c_delay = MAX(cpu_clock / (400000*2*3) - 7, 1);
}
-static inline void pcf50606_i2c_start(void)
+inline void pcf50606_i2c_start(void)
{
#ifdef USE_ASM
asm (
@@ -101,7 +101,7 @@
#endif
}
-static inline void pcf50606_i2c_stop(void)
+inline void pcf50606_i2c_stop(void)
{
#ifdef USE_ASM
asm (
@@ -141,7 +141,7 @@
#endif
}
-static inline void pcf50606_i2c_ack(bool ack)
+inline void pcf50606_i2c_ack(bool ack)
{
#ifdef USE_ASM
asm (
@@ -193,7 +193,7 @@
#endif
}
-static inline bool pcf50606_i2c_getack(void)
+inline bool pcf50606_i2c_getack(void)
{
bool ret;
@@ -251,7 +251,7 @@
return ret;
}
-static void pcf50606_i2c_outb(unsigned char byte)
+void pcf50606_i2c_outb(unsigned char byte)
{
#ifdef USE_ASM
asm volatile (
@@ -321,7 +321,7 @@
#endif
}
-static unsigned char pcf50606_i2c_inb(bool ack)
+unsigned char pcf50606_i2c_inb(bool ack)
{
unsigned char byte = 0;
diff --git a/firmware/export/config-h100.h b/firmware/export/config-h100.h
index 88108c7..38f26c1 100644
--- a/firmware/export/config-h100.h
+++ b/firmware/export/config-h100.h
@@ -129,7 +129,7 @@
/* Define this if there is an EEPROM chip */
/* Someone with H100 and BDM, please verify if this works. */
-// #define HAVE_EEPROM
+/* #define HAVE_EEPROM */
#endif /* !SIMULATOR */
diff --git a/firmware/export/config-h120.h b/firmware/export/config-h120.h
index ca61813..a9b0ed3 100644
--- a/firmware/export/config-h120.h
+++ b/firmware/export/config-h120.h
@@ -125,6 +125,9 @@
/* Define this if there is an EEPROM chip */
#define HAVE_EEPROM
+/* Define this if the EEPROM chip is used */
+#define HAVE_EEPROM_SETTINGS
+
#endif /* !SIMULATOR */
/* Define this for S/PDIF input available */
diff --git a/firmware/export/config-h300.h b/firmware/export/config-h300.h
index f3ba076..2a174bc 100644
--- a/firmware/export/config-h300.h
+++ b/firmware/export/config-h300.h
@@ -133,4 +133,7 @@
/* define this if the unit can be powered or charged via USB */
#define HAVE_USB_POWER
+/* Define this if there is an EEPROM chip */
+#define HAVE_EEPROM
+
#endif /* SIMULATOR */
diff --git a/firmware/export/eeprom_24cxx.h b/firmware/export/eeprom_24cxx.h
index bc0f444..c52dd83 100644
--- a/firmware/export/eeprom_24cxx.h
+++ b/firmware/export/eeprom_24cxx.h
@@ -20,8 +20,13 @@
#ifndef _EEPROM_24CXX_H
#define _EEPROM_24CXX_H
+#ifdef IRIVER_H300_SERIES
+#define EEPROM_ADDR 0xA2
+#define EEPROM_SIZE 256
+#else
#define EEPROM_ADDR 0xA0
#define EEPROM_SIZE 128
+#endif
void eeprom_24cxx_init(void);
int eeprom_24cxx_read_byte(unsigned int address, char *c);
diff --git a/firmware/export/pcf50606.h b/firmware/export/pcf50606.h
index d9f44bb..3e567c9 100644
--- a/firmware/export/pcf50606.h
+++ b/firmware/export/pcf50606.h
@@ -26,4 +26,12 @@
int pcf50606_read_multiple(int address, unsigned char* buf, int count);
int pcf50606_read(int address);
+/* internal low level calls used by the eeprom driver for h300 */
+void pcf50606_i2c_start(void);
+void pcf50606_i2c_stop(void);
+void pcf50606_i2c_ack(bool ack);
+bool pcf50606_i2c_getack(void);
+void pcf50606_i2c_outb(unsigned char byte);
+unsigned char pcf50606_i2c_inb(bool ack);
+
#endif