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