* Avoid flicker on the TRAB's VFD by synchronizing the enable with
authorwdenk <wdenk>
Fri, 14 Mar 2003 20:47:52 +0000 (20:47 +0000)
committerwdenk <wdenk>
Fri, 14 Mar 2003 20:47:52 +0000 (20:47 +0000)
  the HSYNC/VSYNC. Requires new CPLD code (Version 101 for Rev. 100
  boards, version 153 for Rev. 200 boards).

* Patch by Vladimir Gurevich, 12 Mar 2003:
  Fix relocation problem of statically initialized string pointers
  in common/cmd_pci.c

* Patch by Kai-Uwe Blöm, 12 Mar 2003:
  Cleanup & bug fixes for JFFS2 code:
  - the memory mangement was broken. It caused havoc on malloc by
    writing beyond the block boundaries.
  - the length calculation for files was wrong, sometimes resulting
    in short file reads.
  - data copying now optionally takes fragment version numbers into
    account, to avoid copying from older data.
  See doc/README.JFFS2 for details.

22 files changed:
CHANGELOG
board/csb226/csb226.c
board/emk/top860/config.mk
board/innokom/innokom.c
board/lubbock/flash.c
board/mpl/common/common_util.c
board/mpl/vcma9/cmd_vcma9.c
board/mpl/vcma9/vcma9.c
board/trab/vfd.c
common/cmd_pci.c
cpu/arm920t/interrupts.c
cpu/arm920t/start.S
doc/README.JFFS2
drivers/cs8900.c
drivers/cs8900.h
drivers/s3c24x0_i2c.c
fs/jffs2/jffs2_1pass.c
fs/jffs2/jffs2_private.h
include/asm-arm/global_data.h
include/asm-arm/io.h
include/configs/innokom.h
include/i2c.h

index 1b36b41a402a6b7fcaf504f5ecd19edc6708606d..18613a82a5b03bdab569b88561f667c4e8f921dd 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,6 +2,24 @@
 Changes since U-Boot 0.2.2:
 ======================================================================
 
+* Avoid flicker on the TRAB's VFD by synchronizing the enable with
+  the HSYNC/VSYNC. Requires new CPLD code (Version 101 for Rev. 100
+  boards, version 153 for Rev. 200 boards).
+
+* Patch by Vladimir Gurevich, 12 Mar 2003:
+  Fix relocation problem of statically initialized string pointers
+  in common/cmd_pci.c
+
+* Patch by Kai-Uwe Blöm, 12 Mar 2003:
+  Cleanup & bug fixes for JFFS2 code:
+  - the memory mangement was broken. It caused havoc on malloc by
+    writing beyond the block boundaries.
+  - the length calculation for files was wrong, sometimes resulting
+    in short file reads.
+  - data copying now optionally takes fragment version numbers into
+    account, to avoid copying from older data.
+  See doc/README.JFFS2 for details.
+
 * Patch by Josef Wagner, 12 Mar 2003:
   - 16/32 MB and 50/80 MHz support with auto-detection for IP860
   - ETH05 and BEDBUG support for CU824
index 11cab005c661b1338be5f80ef099404be8f29deb..a79d168e044cf9189827cb6eac0b18ab10d9772e 100644 (file)
 
 int misc_init_r(void)
 {
+#if 0  
        uchar *str;
        
        /* determine if the software update key is pressed during startup */
-#if 0  
        /* not ported yet... */
        if (GPLR0 & 0x00000800) {
                printf("using bootcmd_normal (sw-update button not pressed)\n");
index 95917a18b6ca90d3193f6c81b5750593ec9abe18..7b940cb81387c3071197e90f6e0953c8bbdbcae0 100644 (file)
@@ -21,4 +21,8 @@
 # MA 02111-1307 USA
 #
 
+#
+# TOP860 board
+#
+
 TEXT_BASE = 0x80000000
index 17f6353d2ef17f58448c690707dd995fbc0a171a..0176d9c2c336abd6dd53d0e0107ae8bea0d12b94 100644 (file)
@@ -39,7 +39,7 @@
  * The Innokom board has GPIO70 connected to SCLK which can be toggled
  * until all chips think that their current cycles are finished.
  */
-int i2c_init_board(void)
+void i2c_init_board(void)
 {
        int i;
 
@@ -53,8 +53,6 @@ int i2c_init_board(void)
        }
         /* set gpio pin to input */
         GPDR(70) &= ~GPIO_bit(70);
-
-       return 0;
 }
 
 
index a93875083b68953dad6051abf034d2a4d751e3f7..dcf829b2c55f4d2c149edaab89da73af19205c21 100644 (file)
@@ -28,7 +28,7 @@
 #include <linux/byteorder/swab.h>
 
 
-flash_info_t   flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips        */
+flash_info_t flash_info[CFG_MAX_FLASH_BANKS];  /* info for FLASH chips    */
 
 /* Board support for 1 or 2 flash devices */
 #define FLASH_PORT_WIDTH32
@@ -53,50 +53,47 @@ flash_info_t        flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips        */
  * Functions
  */
 static ulong flash_get_size (FPW *addr, flash_info_t *info);
-static int   write_data (flash_info_t *info, ulong dest, FPW data);
-static void  flash_get_offsets (ulong base, flash_info_t *info);
-void inline  spin_wheel(void);
+static int write_data (flash_info_t *info, ulong dest, FPW data);
+static void flash_get_offsets (ulong base, flash_info_t *info);
+void inline spin_wheel (void);
 
 /*-----------------------------------------------------------------------
  */
 
 unsigned long flash_init (void)
 {
-   int i;
-    ulong size = 0;
-
-    for (i = 0; i < CFG_MAX_FLASH_BANKS; i++)
-    {
-        switch (i)
-        {
-           case 0:
-            flash_get_size((FPW *)PHYS_FLASH_1, &flash_info[i]);
-                flash_get_offsets(PHYS_FLASH_1, &flash_info[i]);
-                break;
-           case 1:
-            flash_get_size((FPW *)PHYS_FLASH_2, &flash_info[i]);
-                flash_get_offsets(PHYS_FLASH_2, &flash_info[i]);
-                break;
-           default:
-               panic("configured to many flash banks!\n");
-                break;
-        }
-       size += flash_info[i].size;
-    }
-
-    /* Protect monitor and environment sectors
-     */
-    flash_protect(FLAG_PROTECT_SET,
-                 CFG_FLASH_BASE,
-                 CFG_FLASH_BASE + _armboot_end_data - _armboot_start,
-                 &flash_info[0]);
-
-    flash_protect(FLAG_PROTECT_SET,
-                 CFG_ENV_ADDR,
-                 CFG_ENV_ADDR + CFG_ENV_SIZE - 1,
-                 &flash_info[0]);
-
-    return size;
+       int i;
+       ulong size = 0;
+
+       for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) {
+               switch (i) {
+               case 0:
+                       flash_get_size ((FPW *) PHYS_FLASH_1, &flash_info[i]);
+                       flash_get_offsets (PHYS_FLASH_1, &flash_info[i]);
+                       break;
+               case 1:
+                       flash_get_size ((FPW *) PHYS_FLASH_2, &flash_info[i]);
+                       flash_get_offsets (PHYS_FLASH_2, &flash_info[i]);
+                       break;
+               default:
+                       panic ("configured to many flash banks!\n");
+                       break;
+               }
+               size += flash_info[i].size;
+       }
+
+       /* Protect monitor and environment sectors
+        */
+       flash_protect ( FLAG_PROTECT_SET,
+                       CFG_FLASH_BASE,
+                       CFG_FLASH_BASE + _armboot_end_data - _armboot_start,
+                       &flash_info[0] );
+
+       flash_protect ( FLAG_PROTECT_SET,
+                       CFG_ENV_ADDR,
+                       CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[0] );
+
+       return size;
 }
 
 /*-----------------------------------------------------------------------
@@ -119,39 +116,45 @@ static void flash_get_offsets (ulong base, flash_info_t *info)
 
 /*-----------------------------------------------------------------------
  */
-void flash_print_info  (flash_info_t *info)
+void flash_print_info (flash_info_t *info)
 {
        int i;
 
        if (info->flash_id == FLASH_UNKNOWN) {
                printf ("missing or unknown FLASH type\n");
                return;
-        }
+       }
 
        switch (info->flash_id & FLASH_VENDMASK) {
-               case FLASH_MAN_INTEL:   printf ("INTEL ");              break;
-               default:                printf ("Unknown Vendor ");     break;
+       case FLASH_MAN_INTEL:
+               printf ("INTEL ");
+               break;
+       default:
+               printf ("Unknown Vendor ");
+               break;
        }
 
        switch (info->flash_id & FLASH_TYPEMASK) {
-   case FLASH_28F128J3A:
-                               printf ("28F128J3A\n"); break;
-       default:                printf ("Unknown Chip Type\n"); break;
-        }
+       case FLASH_28F128J3A:
+               printf ("28F128J3A\n");
+               break;
+       default:
+               printf ("Unknown Chip Type\n");
+               break;
+       }
 
        printf ("  Size: %ld MB in %d Sectors\n",
-               info->size >> 20, info->sector_count);
+                       info->size >> 20, info->sector_count);
 
        printf ("  Sector Start Addresses:");
-       for (i=0; i<info->sector_count; ++i) {
-               if ((i % 5) == 0)
-               printf ("\n   ");
+       for (i = 0; i < info->sector_count; ++i) {
+               if ((i % 5) == 0)
+                       printf ("\n   ");
                printf (" %08lX%s",
                        info->start[i],
-                       info->protect[i] ? " (RO)" : "     "
-               );
-        }
-        printf ("\n");
+                       info->protect[i] ? " (RO)" : "     ");
+       }
+       printf ("\n");
        return;
 }
 
@@ -163,37 +166,37 @@ static ulong flash_get_size (FPW *addr, flash_info_t *info)
        volatile FPW value;
 
        /* Write auto select command: read Manufacturer ID */
-       addr[0x5555] = (FPW)0x00AA00AA;
-       addr[0x2AAA] = (FPW)0x00550055;
-       addr[0x5555] = (FPW)0x00900090;
+       addr[0x5555] = (FPW) 0x00AA00AA;
+       addr[0x2AAA] = (FPW) 0x00550055;
+       addr[0x5555] = (FPW) 0x00900090;
 
-   mb();
+       mb ();
        value = addr[0];
 
-   switch (value) {
+       switch (value) {
 
-   case (FPW)INTEL_MANUFACT:
-      info->flash_id = FLASH_MAN_INTEL;
-      break;
+       case (FPW) INTEL_MANUFACT:
+               info->flash_id = FLASH_MAN_INTEL;
+               break;
 
        default:
                info->flash_id = FLASH_UNKNOWN;
                info->sector_count = 0;
                info->size = 0;
-               addr[0] = (FPW)0x00FF00FF;      /* restore read mode */
-               return (0);                     /* no or unknown flash  */
+               addr[0] = (FPW) 0x00FF00FF;     /* restore read mode */
+               return (0);                     /* no or unknown flash  */
        }
 
-   mb();
-       value = addr[1];                        /* device ID            */
+       mb ();
+       value = addr[1];                        /* device ID        */
 
-   switch (value) {
+       switch (value) {
 
-   case (FPW)INTEL_ID_28F128J3A:
-      info->flash_id += FLASH_28F128J3A;
-      info->sector_count = 128;
-      info->size = 0x02000000;
-      break;            /* => 16 MB     */
+       case (FPW) INTEL_ID_28F128J3A:
+               info->flash_id += FLASH_28F128J3A;
+               info->sector_count = 128;
+               info->size = 0x02000000;
+               break;                          /* => 16 MB     */
 
        default:
                info->flash_id = FLASH_UNKNOWN;
@@ -204,9 +207,9 @@ static ulong flash_get_size (FPW *addr, flash_info_t *info)
                printf ("** ERROR: sector count %d > max (%d) **\n",
                        info->sector_count, CFG_MAX_FLASH_SECT);
                info->sector_count = CFG_MAX_FLASH_SECT;
-    }
+       }
 
-       addr[0] = (FPW)0x00FF00FF;      /* restore read mode */
+       addr[0] = (FPW) 0x00FF00FF;             /* restore read mode */
 
        return (info->size);
 }
@@ -215,34 +218,34 @@ static ulong flash_get_size (FPW *addr, flash_info_t *info)
 /*-----------------------------------------------------------------------
  */
 
-int    flash_erase (flash_info_t *info, int s_first, int s_last)
+int flash_erase (flash_info_t *info, int s_first, int s_last)
 {
-    int flag, prot, sect;
-       ulong type, start, now, last;
+       int flag, prot, sect;
+       ulong type, start, last;
        int rcode = 0;
 
-    if ((s_first < 0) || (s_first > s_last)) {
+       if ((s_first < 0) || (s_first > s_last)) {
                if (info->flash_id == FLASH_UNKNOWN) {
                        printf ("- missing\n");
                } else {
                        printf ("- no sectors to erase\n");
                }
                return 1;
-    }
+       }
 
        type = (info->flash_id & FLASH_VENDMASK);
        if ((type != FLASH_MAN_INTEL)) {
                printf ("Can't erase unknown flash type %08lx - aborted\n",
                        info->flash_id);
                return 1;
-    }
+       }
 
-    prot = 0;
-    for (sect=s_first; sect<=s_last; ++sect) {
-       if (info->protect[sect]) {
-           prot++;
+       prot = 0;
+       for (sect = s_first; sect <= s_last; ++sect) {
+               if (info->protect[sect]) {
+                       prot++;
+               }
        }
-    }
 
        if (prot) {
                printf ("- Warning: %d protected sectors will not be erased!\n",
@@ -252,42 +255,42 @@ int       flash_erase (flash_info_t *info, int s_first, int s_last)
        }
 
        start = get_timer (0);
-       last  = start;
+       last = start;
 
-   /* Disable interrupts which might cause a timeout here */
-    flag = disable_interrupts();
+       /* Disable interrupts which might cause a timeout here */
+       flag = disable_interrupts ();
 
-    /* Start erase on unprotected sectors */
-       for (sect = s_first; sect<=s_last; sect++) {
+       /* Start erase on unprotected sectors */
+       for (sect = s_first; sect <= s_last; sect++) {
                if (info->protect[sect] == 0) { /* not protected */
-                       FPWV *addr = (FPWV *)(info->start[sect]);
+                       FPWV *addr = (FPWV *) (info->start[sect]);
                        FPW status;
 
-       printf("Erasing sector %2d ... ", sect);
+                       printf ("Erasing sector %2d ... ", sect);
 
-       /* arm simple, non interrupt dependent timer */
-       reset_timer_masked();
+                       /* arm simple, non interrupt dependent timer */
+                       reset_timer_masked ();
 
-                       *addr = (FPW)0x00500050;        /* clear status register */
-                       *addr = (FPW)0x00200020;        /* erase setup */
-                       *addr = (FPW)0x00D000D0;        /* erase confirm */
+                       *addr = (FPW) 0x00500050;       /* clear status register */
+                       *addr = (FPW) 0x00200020;       /* erase setup */
+                       *addr = (FPW) 0x00D000D0;       /* erase confirm */
 
-                       while (((status = *addr) & (FPW)0x00800080) != (FPW)0x00800080) {
-               if (get_timer_masked() > CFG_FLASH_ERASE_TOUT) {
+                       while (((status = *addr) & (FPW) 0x00800080) != (FPW) 0x00800080) {
+                               if (get_timer_masked () > CFG_FLASH_ERASE_TOUT) {
                                        printf ("Timeout\n");
-                                       *addr = (FPW)0x00B000B0; /* suspend erase         */
-                                       *addr = (FPW)0x00FF00FF; /* reset to read mode */
+                                       *addr = (FPW) 0x00B000B0;       /* suspend erase     */
+                                       *addr = (FPW) 0x00FF00FF;       /* reset to read mode */
                                        rcode = 1;
                                        break;
-       }
-    }
+                               }
+                       }
 
-                       *addr = 0x00500050; /* clear status register cmd.   */
-                       *addr = 0x00FF00FF; /* resest to read mode          */
+                       *addr = 0x00500050;     /* clear status register cmd.   */
+                       *addr = 0x00FF00FF;     /* resest to read mode          */
 
                        printf (" done\n");
-        }
-        }
+               }
+       }
        return rcode;
 }
 
@@ -301,7 +304,7 @@ int flash_erase (flash_info_t *info, int s_first, int s_last)
 
 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
 {
-    ulong cp, wp;
+       ulong cp, wp;
        FPW data;
        int count, i, l, rc, port_width;
 
@@ -317,67 +320,66 @@ int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
        port_width = 4;
 #endif
 
-    /*
-     * handle unaligned start bytes
-     */
-    if ((l = addr - wp) != 0) {
-       data = 0;
-       for (i=0, cp=wp; i<l; ++i, ++cp) {
-                       data = (data << 8) | (*(uchar *)cp);
-       }
-               for (; i<port_width && cnt>0; ++i) {
+       /*
+        * handle unaligned start bytes
+        */
+       if ((l = addr - wp) != 0) {
+               data = 0;
+               for (i = 0, cp = wp; i < l; ++i, ++cp) {
+                       data = (data << 8) | (*(uchar *) cp);
+               }
+               for (; i < port_width && cnt > 0; ++i) {
                        data = (data << 8) | *src++;
-           --cnt;
-           ++cp;
-       }
-               for (; cnt==0 && i<port_width; ++i, ++cp) {
-                       data = (data << 8) | (*(uchar *)cp);
-       }
+                       --cnt;
+                       ++cp;
+               }
+               for (; cnt == 0 && i < port_width; ++i, ++cp) {
+                       data = (data << 8) | (*(uchar *) cp);
+               }
 
-               if ((rc = write_data(info, wp, SWAP(data))) != 0) {
-           return (rc);
-       }
+               if ((rc = write_data (info, wp, SWAP (data))) != 0) {
+                       return (rc);
+               }
                wp += port_width;
-    }
+       }
 
-    /*
-     * handle word aligned part
-     */
+       /*
+        * handle word aligned part
+        */
        count = 0;
        while (cnt >= port_width) {
                data = 0;
-               for (i=0; i<port_width; ++i) {
+               for (i = 0; i < port_width; ++i) {
                        data = (data << 8) | *src++;
                }
-               if ((rc = write_data(info, wp, SWAP(data))) != 0) {
-           return (rc);
-       }
-               wp  += port_width;
+               if ((rc = write_data (info, wp, SWAP (data))) != 0) {
+                       return (rc);
+               }
+               wp += port_width;
                cnt -= port_width;
-               if (count++ > 0x800)
-               {
-         spin_wheel();
+               if (count++ > 0x800) {
+                       spin_wheel ();
                        count = 0;
                }
-    }
+       }
 
-    if (cnt == 0) {
+       if (cnt == 0) {
                return (0);
-    }
+       }
 
-    /*
-     * handle unaligned tail bytes
-     */
-    data = 0;
-       for (i=0, cp=wp; i<port_width && cnt>0; ++i, ++cp) {
+       /*
+        * handle unaligned tail bytes
+        */
+       data = 0;
+       for (i = 0, cp = wp; i < port_width && cnt > 0; ++i, ++cp) {
                data = (data << 8) | *src++;
-       --cnt;
-    }
-       for (; i<port_width; ++i, ++cp) {
-               data = (data << 8) | (*(uchar *)cp);
+               --cnt;
+       }
+       for (; i < port_width; ++i, ++cp) {
+               data = (data << 8) | (*(uchar *) cp);
        }
 
-       return (write_data(info, wp, SWAP(data)));
+       return (write_data (info, wp, SWAP (data)));
 }
 
 /*-----------------------------------------------------------------------
@@ -388,45 +390,42 @@ int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
  */
 static int write_data (flash_info_t *info, ulong dest, FPW data)
 {
-       FPWV *addr = (FPWV *)dest;
+       FPWV *addr = (FPWV *) dest;
        ulong status;
-       ulong start;
        int flag;
 
        /* Check if Flash is (sufficiently) erased */
        if ((*addr & data) != data) {
-               printf("not erased at %08lx (%x)\n",(ulong)addr,*addr);
+               printf ("not erased at %08lx (%lx)\n", (ulong) addr, *addr);
                return (2);
        }
        /* Disable interrupts which might cause a timeout here */
-       flag = disable_interrupts();
+       flag = disable_interrupts ();
 
-       *addr = (FPW)0x00400040;                /* write setup */
+       *addr = (FPW) 0x00400040;       /* write setup */
        *addr = data;
 
        /* arm simple, non interrupt dependent timer */
-       reset_timer_masked();
+       reset_timer_masked ();
 
        /* wait while polling the status register */
-       while (((status = *addr) & (FPW)0x00800080) != (FPW)0x00800080) {
-               if (get_timer_masked() > CFG_FLASH_WRITE_TOUT) {
-                       *addr = (FPW)0x00FF00FF;        /* restore read mode */
+       while (((status = *addr) & (FPW) 0x00800080) != (FPW) 0x00800080) {
+               if (get_timer_masked () > CFG_FLASH_WRITE_TOUT) {
+                       *addr = (FPW) 0x00FF00FF;       /* restore read mode */
                        return (1);
                }
-    }
+       }
 
-       *addr = (FPW)0x00FF00FF;        /* restore read mode */
+       *addr = (FPW) 0x00FF00FF;       /* restore read mode */
 
        return (0);
 }
 
-void inline
-spin_wheel(void)
+void inline spin_wheel (void)
 {
-   static int r=0,p=0;
-   static char w[] = "\\/-";
+       static int p = 0;
+       static char w[] = "\\/-";
 
-   printf("\010%c", w[p]);
-   (++p == 3) ? (p = 0) : 0;
+       printf ("\010%c", w[p]);
+       (++p == 3) ? (p = 0) : 0;
 }
-
index 0a67090feaa9851e85974c51ddef8e7827c0a9bc..19ead331b878cc2a100e4337ff3530e9f09b828a 100644 (file)
@@ -49,7 +49,9 @@ int mpl_prg(unsigned long src,unsigned long size)
        unsigned long start;
        flash_info_t *info;
        int i,rc;
+#if defined(CONFIG_PIP405) || defined(CONFIG_MIP405)
        unsigned long *magic = (unsigned long *)src;
+#endif
 
        info = &flash_info[0];
 
index cdafc50d654c663f2b9f6df3332f110e84227ac4..80bb61b2bee051898913b9c1642c582ff51d7b38 100644 (file)
@@ -102,7 +102,7 @@ int do_vcma9(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
                                printf("\nplease defined 'ethaddr'\n");
                        }
                } else if (strcmp(argv[2], "dump") == 0) {
-                       uchar addr, endaddr, csum; ushort data;
+                       uchar addr = 0, endaddr, csum; ushort data;
 
                        printf("Dump of CS8900 config device: ");
                        cs8900_e2prom_read(addr, &data);
index 8e3552e2b3256a16db7cad68b9b7bd18d6806001..e452a7b2827fdbd8eb53c70f0fc82e0ac15cc12a 100644 (file)
@@ -183,7 +183,6 @@ static uchar Get_Board_PCB(void)
 int checkboard(void)
 {
        unsigned char s[50];
-       unsigned char bc, var, rc;
        int i;
        backup_t *b = (backup_t *) s;
 
index 894e3157d68bd702b89b02c0575aa0e7b884294d..9b61f6eb617e2403f235517c3df1156dd608e199 100644 (file)
 #define        FRAME_BUF_SIZE  ((256*4*56)/8)
 #define frame_buf_offs 4
 
+/* defines for starting Timer3 as CPLD-Clk */
+#define START3                 (1 << 16)
+#define UPDATE3                        (1 << 17)
+#define INVERT3                        (1 << 18)
+#define RELOAD3                        (1 << 19)
+
+/* CPLD-Register for controlling vfd-blank-signal */
+#define VFD_DISABLE    (*(volatile uchar *)0x04038000=0x0000)
+#define VFD_ENABLE     (*(volatile uchar *)0x04038000=0x0001)
+
 /* Supported VFD Types */
 #define        VFD_TYPE_T119C          1       /* Noritake T119C VFD */
 #define        VFD_TYPE_MN11236        2
 
+/*#define NEW_CPLD_CLK*/
+
+int vfd_board_id;
+
 /* taken from armboot/common/vfd.c */
 unsigned long adr_vfd_table[112][18][2][4][2];
 unsigned char bit_vfd_table[112][18][2][4][2];
@@ -80,9 +94,7 @@ void init_grid_ctrl(void)
        /*
         * clear frame buffer (logical clear => set to "black")
         */
-       memset ((void *)(gd->fb_base),
-               gd->vfd_inv_data ? 0xFF : 0,
-               FRAME_BUF_SIZE);
+       memset ((void *)(gd->fb_base), 0, FRAME_BUF_SIZE);
 
        switch (gd->vfd_type) {
        case VFD_TYPE_T119C:
@@ -98,10 +110,7 @@ void init_grid_ctrl(void)
                        bit_nr = bit % 8;
                        bit_nr = (bit_nr > 3) ? bit_nr-4 : bit_nr+4;
                        temp=(*(volatile unsigned char*)(adr));
-                       if (gd->vfd_inv_data)
-                               temp &= ~(1<<bit_nr);
-                       else
-                               temp |=  (1<<bit_nr);
+                       temp |=  (1<<bit_nr);
                        (*(volatile unsigned char*)(adr))=temp;
 
                        if(grid_cycle<55)
@@ -115,10 +124,7 @@ void init_grid_ctrl(void)
                        bit_nr = bit%8;
                        bit_nr = (bit_nr>3)?bit_nr-4:bit_nr+4;
                        temp=(*(volatile unsigned char*)(adr));
-                       if (gd->vfd_inv_data)
-                               temp &= ~(1<<bit_nr);
-                       else
-                               temp |=  (1<<bit_nr);
+                       temp |=  (1<<bit_nr);
                        (*(volatile unsigned char*)(adr))=temp;
                }
            }
@@ -136,10 +142,7 @@ void init_grid_ctrl(void)
                        bit_nr = bit % 8;
                        bit_nr = (bit_nr > 3) ? bit_nr-4 : bit_nr+4;
                        temp=(*(volatile unsigned char*)(adr));
-                       if (gd->vfd_inv_data)
-                               temp &= ~(1<<bit_nr);
-                       else
-                               temp |=  (1<<bit_nr);
+                       temp |=  (1<<bit_nr);
                        (*(volatile unsigned char*)(adr))=temp;
 
                        if(grid_cycle<37)
@@ -152,10 +155,7 @@ void init_grid_ctrl(void)
                        bit_nr = bit%8;
                        bit_nr = (bit_nr>3)?bit_nr-4:bit_nr+4;
                        temp=(*(volatile unsigned char*)(adr));
-                       if (gd->vfd_inv_data)
-                               temp &= ~(1<<bit_nr);
-                       else
-                               temp |=  (1<<bit_nr);
+                       temp |=  (1<<bit_nr);
                        (*(volatile unsigned char*)(adr))=temp;
                }
            }
@@ -250,7 +250,7 @@ void create_vfd_table(void)
                        for(entry=0;entry<2;entry++) {
                            unsigned long adr  = gd->fb_base;
                            unsigned int bit_nr = 0;
-                           
+
                            if (vfd_table[x][y][color][display][entry]) {
 
                                pixel  = vfd_table[x][y][color][display][entry] + frame_buf_offs;
@@ -295,18 +295,11 @@ void set_vfd_pixel(unsigned char x, unsigned char y,
        bit_nr = bit_vfd_table[x][y][color][display][0];
        temp=(*(volatile unsigned char*)(adr));
 
-       if (gd->vfd_inv_data) {
-               if (value)
-                       temp &= ~(1<<bit_nr);
-               else
-                       temp |=  (1<<bit_nr);
-       } else {
-               if (value)
-                       temp |=  (1<<bit_nr);
-               else
-                       temp &= ~(1<<bit_nr);
-       }
-       
+       if (value)
+               temp |=  (1<<bit_nr);
+       else
+               temp &= ~(1<<bit_nr);
+
        (*(volatile unsigned char*)(adr))=temp;
 }
 
@@ -363,22 +356,59 @@ void transfer_pic(int display, unsigned char *adr, int height, int width)
  * This function initializes VFD clock that is needed for the CPLD that
  * manages the keyboard.
  */
-int vfd_init_clocks(void)
+int vfd_init_clocks (void)
 {
-       /* Port-Pins als LCD-Ausgang */
-       rPCCON =   (rPCCON & 0xFFFFFF00)| 0x000000AA;
-       /* Port-Pins als LCD-Ausgang */
-       rPDCON =   (rPDCON & 0xFFFFFF03)| 0x000000A8;
-#ifdef CFG_WITH_VFRAME
-       /* mit VFRAME zum Messen */
-       rPDCON =   (rPDCON & 0xFFFFFF00)| 0x000000AA;
-#endif
 
-       rLCDCON2 = 0x000DC000;
-       rLCDCON3 = 0x0051000A;
-       rLCDCON4 = 0x00000001;
-       rLCDCON5 = 0x00000440;
+       /* try to determine display type from the value
+        * defined by pull-ups
+        */
+       rPCUP = (rPCUP & 0xFFF0);       /* activate  GPC0...GPC3 pullups */
+       rPCCON = (rPCCON & 0xFFFFFF00); /* configure GPC0...GPC3 as inputs */
+       udelay (10);                            /* allow signals to settle */
+       vfd_board_id = (~rPCDAT) & 0x000F;      /* read GPC0...GPC3 port pins */
+
+       VFD_DISABLE;                            /* activate blank for the vfd */
+
+#define        NEW_CPLD_CLK
+
+#ifdef NEW_CPLD_CLK
+       if (vfd_board_id) {
+               /* If new board revision, then use PWM 3 as cpld-clock */
+               /* Enable 500 Hz timer for fill level sensor to operate properly */
+               /* Configure TOUT3 as functional pin, disable pull-up */
+               rPDCON &= ~0x30000;
+               rPDCON |= 0x20000;
+               rPDUP |= (1 << 8);
+
+               /* Configure the prescaler */
+               rTCFG0 &= ~0xff00;
+               rTCFG0 |= 0x0f00;
+
+               /* Select MUX input (divider) for timer3 (1/16) */
+               rTCFG1 &= ~0xf000;
+               rTCFG1 |= 0x3000;
+
+               /* Enable autoreload and set the counter and compare
+                * registers to values for the 500 Hz clock
+                * (for a given  prescaler (15) and divider (16)):
+                * counter = (66000000 / 500) >> 9;
+                */
+               rTCNTB3 = 0x101;
+               rTCMPB3 = 0x101 / 2;
+
+               /* Start timer */
+               rTCON = (rTCON | UPDATE3 | RELOAD3) & ~INVERT3;
+               rTCON = (rTCON | START3) & ~UPDATE3;
+       }
+#endif
+       /* If old board revision, then use vm-signal as cpld-clock */
+       rLCDCON2 = 0x00FFC000;
+       rLCDCON3 = 0x0007FF00;
+       rLCDCON4 = 0x00000000;
+       rLCDCON5 = 0x00000400;
        rLCDCON1 = 0x00000B75;
+       /* VM (GPD1) is used as clock for the CPLD */
+       rPDCON = (rPDCON & 0xFFFFFFF3) | 0x00000008;
 
        return 0;
 }
@@ -397,7 +427,7 @@ int drv_vfd_init(void)
        char *tmp;
        ulong palette;
        static int vfd_init_done = 0;
-       int vfd_id;
+       int vfd_inv_data = 0;
 
        DECLARE_GLOBAL_DATA_PTR;
 
@@ -405,17 +435,9 @@ int drv_vfd_init(void)
                return (0);
        vfd_init_done = 1;
 
-       /* try to determine display type from the value
-        * defined by pull-ups
-        */
-       rPCUP  = (rPCUP & 0xFFF0);      /* activate  GPC0...GPC3 pullups */
-       rPCCON = (rPCCON & 0xFFFFFF00); /* configure GPC0...GPC3 as inputs */
-       udelay(10);                     /* allow signals to settle */
-
-       vfd_id = (~rPCDAT) & 0x000F;    /* read GPC0...GPC3 port pins */
-       debug("Detecting Revison of WA4-VFD: ID=0x%X\n", vfd_id);
+       debug("Detecting Revison of WA4-VFD: ID=0x%X\n", vfd_board_id);
 
-       switch (vfd_id) {
+       switch (vfd_board_id) {
        case 0:                 /* board revision < Rev.200 */
                if ((tmp = getenv ("vfd_type")) == NULL) {
                        break;
@@ -428,19 +450,18 @@ int drv_vfd_init(void)
                        /* cannot use printf for a warning here */
                        gd->vfd_type = 0;       /* unknown */
                }
-               gd->vfd_inv_data = 0;
 
                break;
        default:                /* default to MN11236, data inverted */
                gd->vfd_type = VFD_TYPE_MN11236;
-               gd->vfd_inv_data = 1;
+               vfd_inv_data = 1;
                setenv ("vfd_type", "MN11236");
        }
        debug ("VFD type: %s%s\n",
                (gd->vfd_type == VFD_TYPE_T119C)   ? "T119C" :
                (gd->vfd_type == VFD_TYPE_MN11236) ? "MN11236" :
                "unknown",
-               gd->vfd_inv_data ? ", inverted data" : "");
+               vfd_inv_data ? ", inverted data" : "");
 
        gd->fb_base = gd->fb_base;
        create_vfd_table();
@@ -458,11 +479,33 @@ int drv_vfd_init(void)
         * (wrap around)
         * see manual S3C2400
         */
+       /* Stopp LCD-Controller */
+       rLCDCON1 = 0x00000000;
        /* frame buffer startadr */
        rLCDSADDR1 = gd->fb_base >> 1;
        /* frame buffer endadr */
        rLCDSADDR2 = (gd->fb_base + FRAME_BUF_SIZE) >> 1;
        rLCDSADDR3 = ((256/4));
+       rLCDCON2 = 0x000DC000;
+       rLCDCON3 = 0x0051000A;
+       rLCDCON4 = 0x00000001;
+       if (gd->vfd_type && vfd_inv_data)
+               rLCDCON5 = 0x000004C0;
+       else
+               rLCDCON5 = 0x00000440;
+
+       /* Port pins as LCD output */
+       rPCCON =   (rPCCON & 0xFFFFFF00)| 0x000000AA;
+       rPDCON =   (rPDCON & 0xFFFFFF03)| 0x000000A8;
+
+       /* Synchronize VFD enable with LCD controller to avoid flicker  */
+       rLCDCON1 = 0x00000B75;                  /* Start LCD-Controller */
+       while((rLCDCON5 & 0x180000)!=0x100000); /* Wait for end of VSYNC */
+       while((rLCDCON5 & 0x060000)!=0x040000); /* Wait for next HSYNC  */
+       while((rLCDCON5 & 0x060000)==0x040000);
+       while((rLCDCON5 & 0x060000)!=0x000000);
+       if(gd->vfd_type)
+               VFD_ENABLE;
 
        debug ("LCDSADDR1: %lX\n", rLCDSADDR1);
        debug ("LCDSADDR2: %lX\n", rLCDSADDR2);
@@ -471,6 +514,17 @@ int drv_vfd_init(void)
        return 0;
 }
 
+/*
+ * Disable VFD: should be run before resetting the system:
+ * disable VM, enable pull-up
+ */
+void disable_vfd (void)
+{
+       VFD_DISABLE;
+       rPDCON &= ~0xC;
+       rPDUP  &= ~0x2;
+}
+
 /************************************************************************/
 /* ** ROM capable initialization part - needed to reserve FB memory    */
 /************************************************************************/
index 5a3b5574ee995c5ee33c3e2303b46ec8d8488e48..a26deddcd36b91de3ddc06b4e701011a8b8eb3e9 100644 (file)
@@ -115,28 +115,65 @@ void pciinfo(int BusNum, int ShortPCIListing)
 
 char* pci_classes_str(u8 class)
 {
-       static char *pci_classes[] = {
-               "Build before PCI Rev2.0",
-               "Mass storage controller",
-               "Network controller     ",
-               "Display controller     ",
-               "Multimedia device      ",
-               "Memory controller      ",
-               "Bridge device          ",
-               "Simple comm. controller",
-               "Base system peripheral ",
-               "Input device           ",
-               "Docking station        ",
-               "Processor              ",
-               "Serial bus controller  ",
-               "Reserved entry         ",
-               "Does not fit any class "
-       };
-
-       if (class < (sizeof pci_classes / sizeof *pci_classes))
-               return pci_classes[(int) class];
-
+       switch (class) {
+        case PCI_CLASS_NOT_DEFINED:
+                return "Build before PCI Rev2.0";
+                break;
+        case PCI_BASE_CLASS_STORAGE:
+                return "Mass storage controller";
+                break;
+        case PCI_BASE_CLASS_NETWORK:
+                return "Network controller     ";
+                break;
+        case PCI_BASE_CLASS_DISPLAY:
+                return "Display controller     ";
+                break;
+        case PCI_BASE_CLASS_MULTIMEDIA:
+                return "Multimedia device      ";
+                break;
+        case PCI_BASE_CLASS_MEMORY:
+                return "Memory controller      ";
+                break;
+        case PCI_BASE_CLASS_BRIDGE:
+                return "Bridge device          ";
+                break;
+        case PCI_BASE_CLASS_COMMUNICATION:
+                return "Simple comm. controller";
+                break;
+        case PCI_BASE_CLASS_SYSTEM:
+                return "Base system peripheral ";
+                break;
+        case PCI_BASE_CLASS_INPUT:
+                return "Input device           ";
+                break;
+        case PCI_BASE_CLASS_DOCKING:
+                return "Docking station        ";
+                break;
+        case PCI_BASE_CLASS_PROCESSOR:
+                return "Processor              ";
+                break;
+        case PCI_BASE_CLASS_SERIAL:
+                return "Serial bus controller  ";
+                break;
+        case PCI_BASE_CLASS_INTELLIGENT:
+                return "Intelligent controller ";
+                break;
+        case PCI_BASE_CLASS_SATELLITE:
+                return "Satellite controller   ";
+                break;
+        case PCI_BASE_CLASS_CRYPT:
+                return "Cryptographic device   ";
+                break;
+        case PCI_BASE_CLASS_SIGNAL_PROCESSING:
+                return "DSP                    ";
+                break;
+        case PCI_CLASS_OTHERS:
+                return "Does not fit any class ";
+                break;
+        default:
        return  "???                    ";
+                break;
+       };
 }
 
 /*
index 963ccbd2a35dcbeaee79ce2b92dac5ac38296b8b..195fb01477ab0173716f852094d358499da9b2c5 100644 (file)
@@ -199,9 +199,9 @@ int interrupt_init (void)
        /* load value for 10 ms timeout */
        lastdec = rTCNTB4 = timer_load_val;
        /* auto load, manual update of Timer 4 */
-       rTCON = 0x600000;
+       rTCON = (rTCON & ~0x0700000) | 0x600000;
        /* auto load, start Timer 4 */
-       rTCON = 0x500000;
+       rTCON = (rTCON & ~0x0700000) | 0x500000;
        timestamp = 0;
 
        return (0);
@@ -296,8 +296,10 @@ ulong get_tbclk (void)
 
 #if defined(CONFIG_SMDK2400) || defined(CONFIG_TRAB)
        tbclk = timer_load_val * 100;
-#elif defined(CONFIG_SMDK2410)
+#elif defined(CONFIG_SMDK2410) || defined(CONFIG_VCMA9)
        tbclk = CFG_HZ;
+#else
+#      error "tbclk not configured"
 #endif
 
        return tbclk;
index a858dfa05eb80e0b4a4436da8ed0b443d611f482..4a4825ab36af5bca9253a708c54ecf83f148af55 100644 (file)
@@ -446,6 +446,9 @@ fiq:
 reset_cpu:
 #ifdef CONFIG_S3C2400
        bl      disable_interrupts
+# ifdef CONFIG_TRAB
+       bl      disable_vfd
+# endif
        ldr     r1, _rWTCON
        ldr     r2, _rWTCNT
        /* Disable watchdog */
index 0d39c46453a8489a61403a3bb09e9b8cd77a4fcb..3243895150b649e25b7c81c3b6d4a65ed30b7365 100644 (file)
@@ -9,6 +9,14 @@ fsload  - load binary file from a file system image
 fsinfo  - print information about file systems
 ls      - list files in a directory
 
+If you boot from a partition which is mounted writable, and you
+update your boot environment by replacing single files on that
+partition, you should also define CFG_JFFS2_SORT_FRAGMENTS. Scanning
+the JFFS2 filesystem takes *much* longer with this feature, though.
+Sorting is done while inserting into the fragment list, which is
+more or less a bubble sort. That algorithm is known to be O(n^2),
+thus you should really consider if you can avoid it!
+
 
 There is two ways for JFFS2 to find the disk. The default way uses
 the flash_info structure to find the start of a JFFS2 disk (called
index b9fac8c54b100ed02dc50f620a7ea4a509b50490..d35332c83020fa84c26446c8e368cf2733f87baa 100644 (file)
@@ -296,7 +296,7 @@ int cs8900_e2prom_read(unsigned char addr, unsigned short *value)
 /* write a 16-bit word into the EEPROM                     */
 /***********************************************************/
 
-void cs8900_e2prom_write(unsigned char addr, unsigned short value)
+int cs8900_e2prom_write(unsigned char addr, unsigned short value)
 {
        cs8900_e2prom_ready();
        put_reg(PP_EECMD, EEPROM_WRITE_EN);
@@ -307,7 +307,7 @@ void cs8900_e2prom_write(unsigned char addr, unsigned short value)
        put_reg(PP_EECMD, EEPROM_WRITE_DIS);
        cs8900_e2prom_ready();
 
-       return;
+       return 0;
 }
 
 #endif /* COMMANDS & CFG_NET */
index dbfda3c15ba15dc416d94930be23241e9f829a14..d772cad667a01db9f9a5be602083f8f6d6ae8661 100644 (file)
 #define EEPROM_ERASE_CMD       0x0300
 
 extern int cs8900_e2prom_read(uchar, ushort *);
-extern void cs8900_e2prom_write(uchar, ushort);
+extern int cs8900_e2prom_write(uchar, ushort);
 
 #endif /* CONFIG_DRIVER_CS8900 */
index bf435c9839ad60891ce179917f41ebf8d20ccbcb..b50176118ad22b97364379e0fbc78d421b56de71 100644 (file)
@@ -64,10 +64,12 @@ static int GetIICSDA(void)
        return (rGPEDAT & 0x8000) >> 15;
 }
 
+#if 0
 static void SetIICSDA(int x)
 {
        rGPEDAT = (rGPEDAT & ~0x8000) | (x&1) << 15;
 }
+#endif
 
 static void SetIICSCL(int x)
 {
index bacec8e30cdbfe64294f751dd6dabc53418cc2a8..a5d9583596ca269e2d6a395b4e7e6f3d7de71d4b 100644 (file)
@@ -1,3 +1,4 @@
+/* vi: set sw=4 ts=4: */
 /*
 -------------------------------------------------------------------------
  * Filename:      jffs2.c
  *
  */
 
+/*
+ * Bugfixing by Kai-Uwe Bloem <kai-uwe.bloem@auerswald.de>, (C) Mar/2003
+ *
+ * - overhaul of the memory management. Removed much of the "paper-bagging"
+ *   in that part of the code, fixed several bugs, now frees memory when
+ *   partition is changed.
+ *   It's still ugly :-(
+ * - fixed a bug in jffs2_1pass_read_inode where the file length calculation
+ *   was incorrect. Removed a bit of the paper-bagging as well.
+ * - removed double crc calculation for fragment headers in jffs2_private.h
+ *   for speedup.
+ * - scan_empty rewritten in a more "standard" manner (non-paperbag, that is).
+ * - spinning wheel now spins depending on how much memory has been scanned
+ * - lots of small changes all over the place to "improve" readability.
+ * - implemented fragment sorting to ensure that the newest data is copied
+ *   if there are multiple copies of fragments for a certain file offset.
+ *
+ * The fragment sorting feature must be enabled by CFG_JFFS2_SORT_FRAGMENTS.
+ * Sorting is done while adding fragments to the lists, which is more or less a
+ * bubble sort. This takes a lot of time, and is most probably not an issue if
+ * the boot filesystem is always mounted readonly.
+ *
+ * You should define it if the boot filesystem is mounted writable, and updates
+ * to the boot files are done by copying files to that filesystem.
+ *
+ *
+ * There's a big issue left: endianess is completely ignored in this code. Duh!
+ *
+ *
+ * You still should have paper bags at hand :-(. The code lacks more or less
+ * any comment, and is still arcane and difficult to read in places. As this
+ * is incompatible with any new code from the jffs2 maintainers anyway, it
+ * should probably be dumped and replaced by something like jffs2reader!
+ */
+
+
 #include <common.h>
 #include <config.h>
 #include <malloc.h>
 
 #include "jffs2_private.h"
 
-/* Compression names */
-static char *compr_names[] = {
-        "NONE",
-        "ZERO",
-        "RTIME",
-        "RUBINMIPS",
-        "COPY",
-        "DYNRUBIN",
-        "ZLIB" };
 
-static char spinner[] = { '|', '\\', '-', '/' };
+#define        NODE_CHUNK      1024    /* size of memory allocation chunk in b_nodes */
+#define        SPIN_BLKSIZE    18      /* spin after having scanned 1<<BLKSIZE bytes */
+
+/* Debugging switches */
+#undef DEBUG_DIRENTS           /* print directory entry list after scan */
+#undef DEBUG_FRAGMENTS         /* print fragment list after scan */
+#undef DEBUG                           /* enable debugging messages */
+
 
-#define DEBUG
 #ifdef  DEBUG
 # define DEBUGF(fmt,args...)   printf(fmt ,##args)
 #else
 # define DEBUGF(fmt,args...)
 #endif
 
-#define MALLOC_CHUNK (10*1024)
 
+/* Compression names */
+static char *compr_names[] = {
+       "NONE",
+       "ZERO",
+       "RTIME",
+       "RUBINMIPS",
+       "COPY",
+       "DYNRUBIN",
+       "ZLIB"
+};
+
+/* Spinning wheel */
+static char spinner[] = { '|', '/', '-', '\\' };
+
+/* Memory management */
+struct mem_block {
+       u32     index;
+       struct mem_block *next;
+       struct b_node nodes[NODE_CHUNK];
+};
+
+
+static void
+free_nodes(struct b_list *list)
+{
+       while (list->listMemBase != NULL) {
+               struct mem_block *next = list->listMemBase->next;
+               free( list->listMemBase );
+               list->listMemBase = next;
+       }
+}
 
 static struct b_node *
-add_node(struct b_node *tail, u32 * count, u32 * memBase)
+add_node(struct b_list *list)
 {
-       u32 index;
-       u32 memLimit;
+       u32 index = 0;
+       struct mem_block *memBase;
        struct b_node *b;
 
-       index = (*count) * sizeof(struct b_node) % MALLOC_CHUNK;
-       memLimit = MALLOC_CHUNK;
-
+       memBase = list->listMemBase;
+       if (memBase != NULL)
+               index = memBase->index;
 #if 0
        putLabeledWord("add_node: index = ", index);
-       putLabeledWord("add_node: memLimit = ", memLimit);
-       putLabeledWord("add_node: memBase = ", *memBase);
+       putLabeledWord("add_node: memBase = ", list->listMemBase);
 #endif
 
-       /* we need not keep a list of bases since we'll never free the */
-       /* memory, just jump the the kernel */
-       if ((index == 0) || (index > memLimit)) {       /* we need mode space before we continue */
-               if ((*memBase = (u32) mmalloc(MALLOC_CHUNK)) == (u32) NULL) {
+       if (memBase == NULL || index >= NODE_CHUNK) {
+               /* we need more space before we continue */
+               memBase = mmalloc(sizeof(struct mem_block));
+               if (memBase == NULL) {
                        putstr("add_node: malloc failed\n");
                        return NULL;
                }
+               memBase->next = list->listMemBase;
+               index = 0;
 #if 0
                putLabeledWord("add_node: alloced a new membase at ", *memBase);
 #endif
 
        }
        /* now we have room to add it. */
-       b = (struct b_node *) (*memBase + index);
-
-       /* null on first call */
-       if (tail)
-               tail->next = b;
+       b = &memBase->nodes[index];
+       index ++;
 
-#if 0
-       putLabeledWord("add_node: tail = ", (u32) tail);
-       if (tail)
-               putLabeledWord("add_node: tail->next = ", (u32) tail->next);
+       memBase->index = index;
+       list->listMemBase = memBase;
+       list->listCount++;
+       return b;
+}
 
+static struct b_node *
+insert_node(struct b_list *list, u32 offset)
+{
+       struct b_node *new;
+#ifdef CFG_JFFS2_SORT_FRAGMENTS
+       struct b_node *b, *prev;
 #endif
 
-#if 0
-       putLabeledWord("add_node: mb+i = ", (u32) (*memBase + index));
-       putLabeledWord("add_node: b = ", (u32) b);
+       if (!(new = add_node(list))) {
+               putstr("add_node failed!\r\n");
+               return NULL;
+       }
+       new->offset = offset;
+
+#ifdef CFG_JFFS2_SORT_FRAGMENTS
+       if (list->listTail != NULL && list->listCompare(new, list->listTail))
+               prev = list->listTail;
+       else if (list->listLast != NULL && list->listCompare(new, list->listLast))
+               prev = list->listLast;
+       else
+               prev = NULL;
+
+       for (b = (prev ? prev->next : list->listHead);
+            b != NULL && list->listCompare(new, b);
+            prev = b, b = b->next) {
+               list->listLoops++;
+       }
+       if (b != NULL)
+               list->listLast = prev;
+
+       if (b != NULL) {
+               new->next = b;
+               if (prev != NULL)
+                       prev->next = new;
+               else
+                       list->listHead = new;
+       } else
 #endif
-       (*count)++;
-       b->next = (struct b_node *) NULL;
-       return b;
+       {
+               new->next = (struct b_node *) NULL;
+               if (list->listTail != NULL) {
+                       list->listTail->next = new;
+                       list->listTail = new;
+               } else {
+                       list->listTail = list->listHead = new;
+               }
+       }
 
+       return new;
 }
 
-/* we know we have empties at the start offset so we will hop */
-/* t points that would be non F if there were a node here to speed this up. */
-struct jffs2_empty_node {
-       u32 first;
-       u32 second;
-};
+#ifdef CFG_JFFS2_SORT_FRAGMENTS
+static int compare_inodes(struct b_node *new, struct b_node *old)
+{
+       struct jffs2_raw_inode *jNew = (struct jffs2_raw_inode *)new->offset;
+       struct jffs2_raw_inode *jOld = (struct jffs2_raw_inode *)old->offset;
+
+       return jNew->version < jOld->version;
+}
+
+static int compare_dirents(struct b_node *new, struct b_node *old)
+{
+       struct jffs2_raw_dirent *jNew = (struct jffs2_raw_dirent *)new->offset;
+       struct jffs2_raw_dirent *jOld = (struct jffs2_raw_dirent *)old->offset;
+
+       return jNew->version > jOld->version;
+}
+#endif
 
 static u32
 jffs2_scan_empty(u32 start_offset, struct part_info *part)
 {
-       u32 max = part->size - sizeof(struct jffs2_raw_inode);
+       char *max = part->offset + part->size - sizeof(struct jffs2_raw_inode);
+       char *offset = part->offset + start_offset;
 
-       /* this would be either dir node_crc or frag isize */
-       u32 offset = start_offset + 32;
-       struct jffs2_empty_node *node;
-
-       start_offset += 4;
-       while (offset < max) {
-               node = (struct jffs2_empty_node *) (part->offset + offset);
-               if ((node->first == 0xFFFFFFFF) && (node->second == 0xFFFFFFFF)) {
-                       /* we presume that there were no nodes in between and advance in a hop */
-                       /* putLabeledWord("\t\tjffs2_scan_empty: empty at offset=",offset); */
-                       start_offset = offset + 4;
-                       offset = start_offset + 32;     /* orig 32 + 4 bytes for the second==0xfffff */
-               } else {
-                       return start_offset;
-               }
+       while (offset < max && *(u32 *)offset == 0xFFFFFFFF) {
+               offset += sizeof(u32);
+               /* return if spinning is due */
+               if (((u32)offset & ((1 << SPIN_BLKSIZE)-1)) == 0) break;
        }
-       return start_offset;
+
+       return offset - part->offset;
 }
 
 static u32
 jffs_init_1pass_list(struct part_info *part)
 {
-       if ( 0 != ( part->jffs2_priv=malloc(sizeof(struct b_lists)))){
-               struct b_lists *pL =(struct b_lists *)part->jffs2_priv;
+       struct b_lists *pL;
 
-               pL->dirListHead = pL->dirListTail = NULL;
-               pL->fragListHead = pL->fragListTail = NULL;
-               pL->dirListCount = 0;
-               pL->dirListMemBase = 0;
-               pL->fragListCount = 0;
-               pL->fragListMemBase = 0;
-               pL->partOffset = 0x0;
+       if (part->jffs2_priv != NULL) {
+               pL = (struct b_lists *)part->jffs2_priv;
+               free_nodes(&pL->frag);
+               free_nodes(&pL->dir);
+               free(pL);
+       }
+       if (NULL != (part->jffs2_priv = malloc(sizeof(struct b_lists)))) {
+               pL = (struct b_lists *)part->jffs2_priv;
+
+               memset(pL, 0, sizeof(*pL));
+#ifdef CFG_JFFS2_SORT_FRAGMENTS
+               pL->dir.listCompare = compare_dirents;
+               pL->frag.listCompare = compare_inodes;
+#endif
        }
        return 0;
 }
@@ -216,21 +326,18 @@ jffs2_1pass_read_inode(struct b_lists *pL, u32 inode, char *dest)
 {
        struct b_node *b;
        struct jffs2_raw_inode *jNode;
-       u32 totalSize = 1;
-       u32 oldTotalSize = 0;
-       u32 size = 0;
-       char *lDest = (char *) dest;
+       u32 totalSize = 0;
+       u16 latestVersion = 0;
+       char *lDest;
        char *src;
        long ret;
        int i;
        u32 counter = 0;
-       char totalSizeSet = 0;
 
-#if 0
-       b = pL->fragListHead;
-       while (b) {
+       for (b = pL->frag.listHead; b != NULL; b = b->next) {
                jNode = (struct jffs2_raw_inode *) (b->offset);
                if ((inode == jNode->ino)) {
+#if 0
                        putLabeledWord("\r\n\r\nread_inode: totlen = ", jNode->totlen);
                        putLabeledWord("read_inode: inode = ", jNode->ino);
                        putLabeledWord("read_inode: version = ", jNode->version);
@@ -241,58 +348,26 @@ jffs2_1pass_read_inode(struct b_lists *pL, u32 inode, char *dest)
                        putLabeledWord("read_inode: compr = ", jNode->compr);
                        putLabeledWord("read_inode: usercompr = ", jNode->usercompr);
                        putLabeledWord("read_inode: flags = ", jNode->flags);
-               }
-
-               b = b->next;
-       }
-
 #endif
-
-#if 1
-       b = pL->fragListHead;
-       while (b && (size < totalSize)) {
-               jNode = (struct jffs2_raw_inode *) (b->offset);
-               if ((inode == jNode->ino)) {
-                       if ((jNode->isize == oldTotalSize) && (jNode->isize > totalSize)) {
-                               /* 2 consecutive isizes indicate file length */
+                       /* get actual file length from the newest node */
+                       if (jNode->version >= latestVersion) {
                                totalSize = jNode->isize;
-                               totalSizeSet = 1;
-                       } else if (!totalSizeSet) {
-                               totalSize = size + jNode->dsize + 1;
+                               latestVersion = jNode->version;
                        }
-                       oldTotalSize = jNode->isize;
 
                        if(dest) {
                                src = ((char *) jNode) + sizeof(struct jffs2_raw_inode);
-                               /* lDest = (char *) (dest + (jNode->offset & ~3)); */
+                               /* ignore data behind latest known EOF */
+                               if (jNode->offset > totalSize)
+                                       continue;
+
                                lDest = (char *) (dest + jNode->offset);
 #if 0
-                               putLabeledWord("\r\n\r\nread_inode: src = ", src);
+                               putLabeledWord("read_inode: src = ", src);
                                putLabeledWord("read_inode: dest = ", lDest);
-                               putLabeledWord("read_inode: dsize = ", jNode->dsize);
-                               putLabeledWord("read_inode: csize = ", jNode->csize);
-                               putLabeledWord("read_inode: version = ", jNode->version);
-                               putLabeledWord("read_inode: isize = ", jNode->isize);
-                               putLabeledWord("read_inode: offset = ", jNode->offset);
-                               putLabeledWord("read_inode: compr = ", jNode->compr);
-                               putLabeledWord("read_inode: flags = ", jNode->flags);
 #endif
                                switch (jNode->compr) {
                                case JFFS2_COMPR_NONE:
-#if 0
-                                       {
-                                               int i;
-
-                                               if ((dest > 0xc0092ff0) && (dest < 0xc0093000))
-                                                       for (i = 0; i < first->length; i++) {
-                                                               putLabeledWord("\tCOMPR_NONE: src =", src + i);
-                                                               putLabeledWord("\tCOMPR_NONE: length =", first->length);
-                                                               putLabeledWord("\tCOMPR_NONE: dest =", dest + i);
-                                                               putLabeledWord("\tCOMPR_NONE: data =", (unsigned char) *(src + i));
-                                                       }
-                                       }
-#endif
-
                                        ret = (unsigned long) ldr_memcpy(lDest, src, jNode->dsize);
                                        break;
                                case JFFS2_COMPR_ZERO:
@@ -320,22 +395,18 @@ jffs2_1pass_read_inode(struct b_lists *pL, u32 inode, char *dest)
                                }
                        }
 
-                       size += jNode->dsize;
 #if 0
-                       putLabeledWord("read_inode: size = ", size);
                        putLabeledWord("read_inode: totalSize = ", totalSize);
                        putLabeledWord("read_inode: compr ret = ", ret);
 #endif
                }
-               b = b->next;
                counter++;
        }
-#endif
 
 #if 0
-       putLabeledWord("read_inode: returning = ", size);
+       putLabeledWord("read_inode: returning = ", totalSize);
 #endif
-       return size;
+       return totalSize;
 }
 
 /* find the inode from the slashless name given a parent */
@@ -354,18 +425,19 @@ jffs2_1pass_find_inode(struct b_lists * pL, const char *name, u32 pino)
 
        counter = 0;
        /* we need to search all and return the inode with the highest version */
-       for(b = pL->dirListHead;b;b=b->next,counter++) {
+       for(b = pL->dir.listHead; b; b = b->next, counter++) {
                jDir = (struct jffs2_raw_dirent *) (b->offset);
-               if ((pino == jDir->pino) && (len == jDir->nsize) && (jDir->ino) &&      /* 0 for unlink */
+               if ((pino == jDir->pino) && (len == jDir->nsize) &&
+                   (jDir->ino) &&      /* 0 for unlink */
                    (!strncmp(jDir->name, name, len))) {        /* a match */
                        if (jDir->version < version) continue;
 
-                       if(jDir->version==0) {
+                       if(jDir->version == 0) {
                                /* Is this legal? */
                                putstr(" ** WARNING ** ");
                                putnstr(jDir->name, jDir->nsize);
                                putstr(" is version 0 (in find, ignoring)\r\n");
-                       } else if(jDir->version==version) {
+                       } else if(jDir->version == version) {
                                /* Im pretty sure this isn't ... */
                                putstr(" ** ERROR ** ");
                                putnstr(jDir->name, jDir->nsize);
@@ -389,53 +461,53 @@ jffs2_1pass_find_inode(struct b_lists * pL, const char *name, u32 pino)
 
 static char *mkmodestr(unsigned long mode, char *str)
 {
-    static const char *l="xwr";
-    int mask=1, i;
-    char c;
-
-    switch (mode & S_IFMT) {
-        case S_IFDIR:    str[0]='d'; break;
-        case S_IFBLK:    str[0]='b'; break;
-        case S_IFCHR:    str[0]='c'; break;
-        case S_IFIFO:    str[0]='f'; break;
-        case S_IFLNK:    str[0]='l'; break;
-        case S_IFSOCK:   str[0]='s'; break;
-        case S_IFREG:    str[0]='-'; break;
-        default:        str[0]='?';
-    }
-
-    for(i=0;i<9;i++) {
-        c=l[i%3];
-        str[9-i]=(mode & mask)?c:'-';
-        mask=mask<<1;
-    }
-
-    if(mode & S_ISUID) str[3]=(mode & S_IXUSR)?'s':'S';
-    if(mode & S_ISGID) str[6]=(mode & S_IXGRP)?'s':'S';
-    if(mode & S_ISVTX) str[9]=(mode & S_IXOTH)?'t':'T';
-    str[10]='\0';
-    return str;
+       static const char *l = "xwr";
+       int mask = 1, i;
+       char c;
+
+       switch (mode & S_IFMT) {
+               case S_IFDIR:    str[0] = 'd'; break;
+               case S_IFBLK:    str[0] = 'b'; break;
+               case S_IFCHR:    str[0] = 'c'; break;
+               case S_IFIFO:    str[0] = 'f'; break;
+               case S_IFLNK:    str[0] = 'l'; break;
+               case S_IFSOCK:   str[0] = 's'; break;
+               case S_IFREG:    str[0] = '-'; break;
+               default:         str[0] = '?';
+       }
+
+       for(i = 0; i < 9; i++) {
+               c = l[i%3];
+               str[9-i] = (mode & mask)?c:'-';
+               mask = mask<<1;
+       }
+
+       if(mode & S_ISUID) str[3] = (mode & S_IXUSR)?'s':'S';
+       if(mode & S_ISGID) str[6] = (mode & S_IXGRP)?'s':'S';
+       if(mode & S_ISVTX) str[9] = (mode & S_IXOTH)?'t':'T';
+       str[10] = '\0';
+       return str;
 }
 
 static inline void dump_stat(struct stat *st, const char *name)
 {
-    char str[20];
-    char s[64], *p;
+       char str[20];
+       char s[64], *p;
 
-    if (st->st_mtime == (time_t)(-1))  /* some ctimes really hate -1 */
-        st->st_mtime = 1;
+       if (st->st_mtime == (time_t)(-1)) /* some ctimes really hate -1 */
+               st->st_mtime = 1;
 
-    ctime_r(&st->st_mtime, s/*, 64*/);   /* newlib ctime doesn't have buflen */
+       ctime_r(&st->st_mtime, s/*,64*/); /* newlib ctime doesn't have buflen */
 
-    if((p=strchr(s,'\n'))!=NULL) *p='\0';
-    if((p=strchr(s,'\r'))!=NULL) *p='\0';
+       if ((p = strchr(s,'\n')) != NULL) *p = '\0';
+       if ((p = strchr(s,'\r')) != NULL) *p = '\0';
 
 /*
-    printf("%6lo %s %8ld %s %s\n", st->st_mode, mkmodestr(st->st_mode, str),
-        st->st_size, s, name);
+       printf("%6lo %s %8ld %s %s\n", st->st_mode, mkmodestr(st->st_mode, str),
+               st->st_size, s, name);
 */
 
-    printf(" %s %8ld %s %s", mkmodestr(st->st_mode,str), st->st_size, s, name);
+       printf(" %s %8ld %s %s", mkmodestr(st->st_mode,str), st->st_size, s, name);
 }
 
 static inline u32 dump_inode(struct b_lists * pL, struct jffs2_raw_dirent *d, struct jffs2_raw_inode *i)
@@ -446,16 +518,16 @@ static inline u32 dump_inode(struct b_lists * pL, struct jffs2_raw_dirent *d, st
        if(!d || !i) return -1;
 
        strncpy(fname, d->name, d->nsize);
-       fname[d->nsize]='\0';
+       fname[d->nsize] = '\0';
 
        memset(&st,0,sizeof(st));
 
-       st.st_mtime=i->mtime;
-       st.st_mode=i->mode;
-       st.st_ino=i->ino;
+       st.st_mtime = i->mtime;
+       st.st_mode = i->mode;
+       st.st_ino = i->ino;
 
        /* neither dsize nor isize help us.. do it the long way */
-       st.st_size=jffs2_1pass_read_inode(pL, i->ino, NULL);
+       st.st_size = jffs2_1pass_read_inode(pL, i->ino, NULL);
 
        dump_stat(&st, fname);
 
@@ -477,18 +549,18 @@ jffs2_1pass_list_inodes(struct b_lists * pL, u32 pino)
        struct b_node *b;
        struct jffs2_raw_dirent *jDir;
 
-       for(b = pL->dirListHead;b;b=b->next) {
+       for (b = pL->dir.listHead; b; b = b->next) {
                jDir = (struct jffs2_raw_dirent *) (b->offset);
-               if ((pino == jDir->pino) && (jDir->ino)) {      /* 0 inode for unlink */
-                       u32 i_version=0;
-                       struct jffs2_raw_inode *jNode, *i=NULL;
-                       struct b_node *b2 = pL->fragListHead;
+               if ((pino == jDir->pino) && (jDir->ino)) { /* ino=0 -> unlink */
+                       u32 i_version = 0;
+                       struct jffs2_raw_inode *jNode, *i = NULL;
+                       struct b_node *b2 = pL->frag.listHead;
 
                        while (b2) {
                                jNode = (struct jffs2_raw_inode *) (b2->offset);
                                if (jNode->ino == jDir->ino
-                                   && jNode->version>=i_version)
-                                       i=jNode;
+                                   && jNode->version >= i_version)
+                                       i = jNode;
                                b2 = b2->next;
                        }
 
@@ -568,7 +640,7 @@ jffs2_1pass_resolve_inode(struct b_lists * pL, u32 ino)
        unsigned char *src;
 
        /* we need to search all and return the inode with the highest version */
-       for(b = pL->dirListHead; b; b=b->next) {
+       for(b = pL->dir.listHead; b; b = b->next) {
                jDir = (struct jffs2_raw_dirent *) (b->offset);
                if (ino == jDir->ino) {
                        if(jDir->version < version) continue;
@@ -593,8 +665,9 @@ jffs2_1pass_resolve_inode(struct b_lists * pL, u32 ino)
        /* now we found the right entry again. (shoulda returned inode*) */
        if (jDirFound->type != DT_LNK)
                return jDirFound->ino;
-       /* so its a soft link so we follow it again. */
-       b2 = pL->fragListHead;
+
+       /* it's a soft link so we follow it again. */
+       b2 = pL->frag.listHead;
        while (b2) {
                jNode = (struct jffs2_raw_inode *) (b2->offset);
                if (jNode->ino == jDirFound->ino) {
@@ -644,7 +717,8 @@ jffs2_1pass_search_list_inodes(struct b_lists * pL, const char *fname, u32 pino)
                        tmp[i] = c[i + 1];
                tmp[i] = '\0';
                /* only a failure if we arent looking at top level */
-               if (!(pino = jffs2_1pass_find_inode(pL, working_tmp, pino)) && (working_tmp[0])) {
+               if (!(pino = jffs2_1pass_find_inode(pL, working_tmp, pino)) &&
+                   (working_tmp[0])) {
                        putstr("find_inode failed for name=");
                        putstr(working_tmp);
                        putstr("\r\n");
@@ -674,29 +748,30 @@ jffs2_1pass_rescan_needed(struct part_info *part)
 {
        struct b_node *b;
        struct jffs2_unknown_node *node;
-       struct b_lists *pL=(struct b_lists *)part->jffs2_priv;
+       struct b_lists *pL = (struct b_lists *)part->jffs2_priv;
 
        if (part->jffs2_priv == 0){
                DEBUGF ("rescan: First time in use\n");
                return 1;
        }
        /* if we have no list, we need to rescan */
-       if (pL->fragListCount == 0) {
+       if (pL->frag.listCount == 0) {
                DEBUGF ("rescan: fraglist zero\n");
                return 1;
        }
 
-       /* or if we are scanninga new partition */
+       /* or if we are scanning a new partition */
        if (pL->partOffset != part->offset) {
                DEBUGF ("rescan: different partition\n");
                return 1;
        }
-       /* but suppose someone reflashed the root partition at the same offset... */
-       b = pL->dirListHead;
+       /* but suppose someone reflashed a partition at the same offset... */
+       b = pL->dir.listHead;
        while (b) {
                node = (struct jffs2_unknown_node *) (b->offset);
                if (node->nodetype != JFFS2_NODETYPE_DIRENT) {
-                       DEBUGF ("rescan: fs changed beneath me? (%lx)\n", (unsigned long) b->offset);
+                       DEBUGF ("rescan: fs changed beneath me? (%lx)\n",
+                                       (unsigned long) b->offset);
                        return 1;
                }
                b = b->next;
@@ -704,12 +779,71 @@ jffs2_1pass_rescan_needed(struct part_info *part)
        return 0;
 }
 
+#ifdef DEBUG_FRAGMENTS
+static void
+dump_fragments(struct b_lists *pL)
+{
+       struct b_node *b;
+       struct jffs2_raw_inode *jNode;
+
+       putstr("\r\n\r\n******The fragment Entries******\r\n");
+       b = pL->frag.listHead;
+       while (b) {
+               jNode = (struct jffs2_raw_inode *) (b->offset);
+               putLabeledWord("\r\n\tbuild_list: FLASH_OFFSET = ", b->offset);
+               putLabeledWord("\tbuild_list: totlen = ", jNode->totlen);
+               putLabeledWord("\tbuild_list: inode = ", jNode->ino);
+               putLabeledWord("\tbuild_list: version = ", jNode->version);
+               putLabeledWord("\tbuild_list: isize = ", jNode->isize);
+               putLabeledWord("\tbuild_list: atime = ", jNode->atime);
+               putLabeledWord("\tbuild_list: offset = ", jNode->offset);
+               putLabeledWord("\tbuild_list: csize = ", jNode->csize);
+               putLabeledWord("\tbuild_list: dsize = ", jNode->dsize);
+               putLabeledWord("\tbuild_list: compr = ", jNode->compr);
+               putLabeledWord("\tbuild_list: usercompr = ", jNode->usercompr);
+               putLabeledWord("\tbuild_list: flags = ", jNode->flags);
+               putLabeledWord("\tbuild_list: offset = ", b->offset);   // FIXME: ? [RS]
+               b = b->next;
+       }
+}
+#endif
+
+#ifdef DEBUG_DIRENTS
+static void
+dump_dirents(struct b_lists *pL)
+{
+       struct b_node *b;
+       struct jffs2_raw_dirent *jDir;
+
+       putstr("\r\n\r\n******The directory Entries******\r\n");
+       b = pL->dir.listHead;
+       while (b) {
+               jDir = (struct jffs2_raw_dirent *) (b->offset);
+               putstr("\r\n");
+               putnstr(jDir->name, jDir->nsize);
+               putLabeledWord("\r\n\tbuild_list: magic = ", jDir->magic);
+               putLabeledWord("\tbuild_list: nodetype = ", jDir->nodetype);
+               putLabeledWord("\tbuild_list: hdr_crc = ", jDir->hdr_crc);
+               putLabeledWord("\tbuild_list: pino = ", jDir->pino);
+               putLabeledWord("\tbuild_list: version = ", jDir->version);
+               putLabeledWord("\tbuild_list: ino = ", jDir->ino);
+               putLabeledWord("\tbuild_list: mctime = ", jDir->mctime);
+               putLabeledWord("\tbuild_list: nsize = ", jDir->nsize);
+               putLabeledWord("\tbuild_list: type = ", jDir->type);
+               putLabeledWord("\tbuild_list: node_crc = ", jDir->node_crc);
+               putLabeledWord("\tbuild_list: name_crc = ", jDir->name_crc);
+               putLabeledWord("\tbuild_list: offset = ", b->offset);   // FIXME: ? [RS]
+               b = b->next;
+       }
+}
+#endif
+
 static u32
 jffs2_1pass_build_lists(struct part_info * part)
 {
        struct b_lists *pL;
        struct jffs2_unknown_node *node;
-       u32 offset;
+       u32 offset, oldoffset = 0;
        u32 max = part->size - sizeof(struct jffs2_raw_inode);
        u32 counter = 0;
        u32 counter4 = 0;
@@ -722,71 +856,52 @@ jffs2_1pass_build_lists(struct part_info * part)
        /* lcd_off(); */
 
        /* if we are building a list we need to refresh the cache. */
-       /* note that since we don't free our memory, eventually this will be bad. */
-       /* but we're a bootldr so what the hell. */
        jffs_init_1pass_list(part);
-       pL=(struct b_lists *)part->jffs2_priv;
+       pL = (struct b_lists *)part->jffs2_priv;
        pL->partOffset = part->offset;
        offset = 0;
        printf("Scanning JFFS2 FS:   ");
 
        /* start at the beginning of the partition */
        while (offset < max) {
-               if (! (++counter%10000))
-                       printf("\b\b%c ", spinner[(counter / 10000) % 4]);
+               if ((oldoffset >> SPIN_BLKSIZE) != (offset >> SPIN_BLKSIZE)) {
+                       printf("\b\b%c ", spinner[counter++ % sizeof(spinner)]);
+                       oldoffset = offset;
+               }
 
                node = (struct jffs2_unknown_node *) (part->offset + offset);
                if (node->magic == JFFS2_MAGIC_BITMASK && hdr_crc(node)) {
                        /* if its a fragment add it */
-                       if (node->nodetype == JFFS2_NODETYPE_INODE && inode_crc((struct jffs2_raw_inode *) node)) {
-                               if (!(pL->fragListTail = add_node(pL->fragListTail, &(pL->fragListCount),
-                                                                 &(pL->fragListMemBase)))) {
-                                       putstr("add_node failed!\r\n");
+                       if (node->nodetype == JFFS2_NODETYPE_INODE &&
+                                   inode_crc((struct jffs2_raw_inode *) node)) {
+                               if (insert_node(&pL->frag, (u32) part->offset +
+                                                               offset) == NULL)
                                        return 0;
-                               }
-                               pL->fragListTail->offset = (u32) (part->offset + offset);
-                               if (!pL->fragListHead)
-                                       pL->fragListHead = pL->fragListTail;
                        } else if (node->nodetype == JFFS2_NODETYPE_DIRENT &&
                                   dirent_crc((struct jffs2_raw_dirent *) node)  &&
                                   dirent_name_crc((struct jffs2_raw_dirent *) node)) {
                                if (! (counterN%100))
                                        printf("\b\b.  ");
-#if 0
-                               printf("Found DIRENT @ 0x%lx\n", offset);
-                               putstr("\r\nbuild_lists:p&l ->");
-                               putnstr(((struct jffs2_raw_dirent *) node)->name, ((struct jffs2_raw_dirent *) node)->nsize);
-                               putstr("\r\n");
-                               putLabeledWord("\tpino = ", ((struct jffs2_raw_dirent *) node)->pino);
-                               putLabeledWord("\tnsize = ", ((struct jffs2_raw_dirent *) node)->nsize);
-#endif
-
-                               if (!(pL->dirListTail = add_node(pL->dirListTail, &(pL->dirListCount), &(pL->dirListMemBase)))) {
-                                       putstr("add_node failed!\r\n");
+                               if (insert_node(&pL->dir, (u32) part->offset +
+                                                               offset) == NULL)
                                        return 0;
-                               }
-                               pL->dirListTail->offset = (u32) (part->offset + offset);
-#if 0
-                               putLabeledWord("\ttail = ", (u32) pL->dirListTail);
-                               putstr("\ttailName ->");
-                               putnstr(((struct jffs2_raw_dirent *) (pL->dirListTail->offset))->name,
-                                       ((struct jffs2_raw_dirent *) (pL->dirListTail->offset))->nsize);
-                               putstr("\r\n");
-#endif
-                               if (!pL->dirListHead)
-                                       pL->dirListHead = pL->dirListTail;
                                counterN++;
                        } else if (node->nodetype == JFFS2_NODETYPE_CLEANMARKER) {
                                if (node->totlen != sizeof(struct jffs2_unknown_node))
-                                       printf("OOPS Cleanmarker has bad size %d != %d\n", node->totlen, sizeof(struct jffs2_unknown_node));
+                                       printf("OOPS Cleanmarker has bad size "
+                                               "%d != %d\n", node->totlen,
+                                               sizeof(struct jffs2_unknown_node));
                        } else {
-                               printf("Unknown node type: %x len %d offset 0x%x\n", node->nodetype, node->totlen, offset);
+                               printf("Unknown node type: %x len %d "
+                                       "offset 0x%x\n", node->nodetype,
+                                       node->totlen, offset);
                        }
                        offset += ((node->totlen + 3) & ~3);
                        counterF++;
-               } else if (node->magic == JFFS2_EMPTY_BITMASK && node->nodetype == JFFS2_EMPTY_BITMASK) {
+               } else if (node->magic == JFFS2_EMPTY_BITMASK &&
+                          node->nodetype == JFFS2_EMPTY_BITMASK) {
                        offset = jffs2_scan_empty(offset, part);
-               } else {        /* if we know nothing of the filesystem, we just step and look. */
+               } else {        /* if we know nothing, we just step and look. */
                        offset += 4;
                        counter4++;
                }
@@ -799,66 +914,21 @@ jffs2_1pass_build_lists(struct part_info * part)
        /* splash(); */
 
 #if 0
-       putLabeledWord("dir entries = ", pL->dirListCount);
-       putLabeledWord("frag entries = ", pL->fragListCount);
+       putLabeledWord("dir entries = ", pL->dir.listCount);
+       putLabeledWord("frag entries = ", pL->frag.listCount);
        putLabeledWord("+4 increments = ", counter4);
        putLabeledWord("+file_offset increments = ", counterF);
 
 #endif
 
-#undef SHOW_ALL
-#undef SHOW_ALL_FRAGMENTS
-
-#ifdef SHOW_ALL
-       {
-               struct b_node *b;
-               struct b_node *b2;
-               struct jffs2_raw_dirent *jDir;
-               struct jffs2_raw_inode *jNode;
-
-               putstr("\r\n\r\n******The directory Entries******\r\n");
-               b = pL->dirListHead;
-               while (b) {
-                       jDir = (struct jffs2_raw_dirent *) (b->offset);
-                       putstr("\r\n");
-                       putnstr(jDir->name, jDir->nsize);
-                       putLabeledWord("\r\n\tbuild_list: magic = ", jDir->magic);
-                       putLabeledWord("\tbuild_list: nodetype = ", jDir->nodetype);
-                       putLabeledWord("\tbuild_list: hdr_crc = ", jDir->hdr_crc);
-                       putLabeledWord("\tbuild_list: pino = ", jDir->pino);
-                       putLabeledWord("\tbuild_list: version = ", jDir->version);
-                       putLabeledWord("\tbuild_list: ino = ", jDir->ino);
-                       putLabeledWord("\tbuild_list: mctime = ", jDir->mctime);
-                       putLabeledWord("\tbuild_list: nsize = ", jDir->nsize);
-                       putLabeledWord("\tbuild_list: type = ", jDir->type);
-                       putLabeledWord("\tbuild_list: node_crc = ", jDir->node_crc);
-                       putLabeledWord("\tbuild_list: name_crc = ", jDir->name_crc);
-                       b = b->next;
-               }
+#ifdef DEBUG_DIRENTS
+       dump_dirents(pL);
+#endif
 
-#ifdef SHOW_ALL_FRAGMENTS
-               putstr("\r\n\r\n******The fragment Entries******\r\n");
-               b = pL->fragListHead;
-               while (b) {
-                       jNode = (struct jffs2_raw_inode *) (b->offset);
-                       putLabeledWord("\r\n\tbuild_list: FLASH_OFFSET = ", b->offset);
-                       putLabeledWord("\tbuild_list: totlen = ", jNode->totlen);
-                       putLabeledWord("\tbuild_list: inode = ", jNode->ino);
-                       putLabeledWord("\tbuild_list: version = ", jNode->version);
-                       putLabeledWord("\tbuild_list: isize = ", jNode->isize);
-                       putLabeledWord("\tbuild_list: atime = ", jNode->atime);
-                       putLabeledWord("\tbuild_list: offset = ", jNode->offset);
-                       putLabeledWord("\tbuild_list: csize = ", jNode->csize);
-                       putLabeledWord("\tbuild_list: dsize = ", jNode->dsize);
-                       putLabeledWord("\tbuild_list: compr = ", jNode->compr);
-                       putLabeledWord("\tbuild_list: usercompr = ", jNode->usercompr);
-                       putLabeledWord("\tbuild_list: flags = ", jNode->flags);
-                       b = b->next;
-               }
-#endif /* SHOW_ALL_FRAGMENTS */
-       }
+#ifdef DEBUG_FRAGMENTS
+       dump_fragments(pL);
+#endif
 
-#endif /* SHOW_ALL */
        /* give visual feedback that we are done scanning the flash */
        led_blink(0x0, 0x0, 0x1, 0x1);  /* off, forever, on 100ms, off 100ms */
        return 1;
@@ -875,13 +945,13 @@ jffs2_1pass_fill_info(struct b_lists * pL, struct b_jffs2_info * piL)
        struct jffs2_raw_inode *jNode;
        int i;
 
-       b = pL->fragListHead;
        for (i = 0; i < JFFS2_NUM_COMPR; i++) {
                piL->compr_info[i].num_frags = 0;
                piL->compr_info[i].compr_sum = 0;
                piL->compr_info[i].decompr_sum = 0;
        }
 
+       b = pL->frag.listHead;
        while (b) {
                jNode = (struct jffs2_raw_inode *) (b->offset);
                if (jNode->compr < JFFS2_NUM_COMPR) {
@@ -917,7 +987,7 @@ jffs2_1pass_ls(struct part_info * part, const char *fname)
        long ret = 0;
        u32 inode;
 
-       if (! (pl  = jffs2_get_list(part, "ls")))
+       if (! (pl = jffs2_get_list(part, "ls")))
                return 0;
 
        if (! (inode = jffs2_1pass_search_list_inodes(pl, fname, 1))) {
@@ -983,7 +1053,7 @@ jffs2_1pass_info(struct part_info * part)
                return 0;
 
        jffs2_1pass_fill_info(pl, &info);
-       for (i=0; i < JFFS2_NUM_COMPR; i++) {
+       for (i = 0; i < JFFS2_NUM_COMPR; i++) {
                printf("Compression: %s\n", compr_names[i]);
                printf("\tfrag count: %d\n", info.compr_info[i].num_frags);
                printf("\tcompressed sum: %d\n", info.compr_info[i].compr_sum);
index ca0af1f9a4be64c1d90ebce05f836ce5ae360dc5..c6d5fe360325307f5754838630f9a643671681ef 100644 (file)
@@ -3,23 +3,31 @@
 
 #include <jffs2/jffs2.h>
 
+
 struct b_node {
        u32 offset;
        struct b_node *next;
 };
 
+struct b_list {
+       struct b_node *listTail;
+       struct b_node *listHead;
+#ifdef CFG_JFFS2_SORT_FRAGMENTS
+       struct b_node *listLast;
+       int (*listCompare)(struct b_node *new, struct b_node *node);
+       u32 listLoops;
+#endif
+       u32 listCount;
+       struct mem_block *listMemBase;
+};
+
 struct b_lists {
        char *partOffset;
-       struct b_node *dirListTail;
-       struct b_node *dirListHead;
-       u32 dirListCount;
-       u32 dirListMemBase;
-       struct b_node *fragListTail;
-       struct b_node *fragListHead;
-       u32 fragListCount;
-       u32 fragListMemBase;
+       struct b_list dir;
+       struct b_list frag;
 
 };
+
 struct b_compr_info {
        u32 num_frags;
        u32 compr_sum;
@@ -33,11 +41,14 @@ struct b_jffs2_info {
 static inline int
 hdr_crc(struct jffs2_unknown_node *node)
 {
+#if 1
         u32 crc = crc32_no_comp(0, (unsigned char *)node, sizeof(struct jffs2_unknown_node) - 4);
-        u32 crc_blah = crc32_no_comp(~0, (unsigned char *)node, sizeof(struct jffs2_unknown_node) - 4);
-
-        crc_blah ^= ~0;
+#else
+       /* what's the semantics of this? why is this here? */
+        u32 crc = crc32_no_comp(~0, (unsigned char *)node, sizeof(struct jffs2_unknown_node) - 4);
 
+        crc ^= ~0;
+#endif
         if (node->hdr_crc != crc) {
                 return 0;
         } else {
index e0a95e081b4dc2f4a18061b1fb78dbe2cf0c3955..892710df40578cf75734e8fccb3da42e6429f02a 100644 (file)
@@ -44,7 +44,6 @@ typedef       struct  global_data {
 #ifdef CONFIG_VFD
        unsigned long   fb_base;        /* base address of frame buffer */
        unsigned char   vfd_type;       /* display type */
-       unsigned char   vfd_inv_data;   /* inverted data lines ? */
 #endif
 #if 0
        unsigned long   cpu_clk;        /* CPU clock in Hz!             */
index 0d55ca25b46ee3ca01ca249a40c518c9e5f7d2c7..122419f1e6b81184ce77ce242dd7d7fc4764f80e 100644 (file)
@@ -71,22 +71,37 @@ extern void __raw_readsl(unsigned int addr, void *data, int longlen);
 #include <asm/arch/io.h>
 
 /*
- * IO definitions.  We define {out,in,outs,ins}[bwl] if __io is defined
- * by the machine.  Otherwise, these definitions are left for the machine
- * specific header files to pick up.
+ *  IO port access primitives
+ *  -------------------------
+ *
+ * The ARM doesn't have special IO access instructions; all IO is memory
+ * mapped.  Note that these are defined to perform little endian accesses
+ * only.  Their primary purpose is to access PCI and ISA peripherals.
+ *
+ * Note that for a big endian machine, this implies that the following
+ * big endian mode connectivity is in place, as described by numerious
+ * ARM documents:
+ *
+ *    PCI:  D0-D7   D8-D15 D16-D23 D24-D31
+ *    ARM: D24-D31 D16-D23  D8-D15  D0-D7
+ *
+ * The machine specific io.h include defines __io to translate an "IO"
+ * address to a memory address.
  *
  * Note that we prevent GCC re-ordering or caching values in expressions
  * by introducing sequence points into the in*() definitions.  Note that
  * __raw_* do not guarantee this behaviour.
+ *
+ * The {in,out}[bwl] macros are for emulating x86-style PCI/ISA IO space.
  */
 #ifdef __io
 #define outb(v,p)                      __raw_writeb(v,__io(p))
-#define outw(v,p)                      __raw_writew(v,__io(p))
-#define outl(v,p)                      __raw_writel(v,__io(p))
+#define outw(v,p)                      __raw_writew(cpu_to_le16(v),__io(p))
+#define outl(v,p)                      __raw_writel(cpu_to_le32(v),__io(p))
 
-#define inb(p)         ({ unsigned int __v = __raw_readb(__io(p)); __v; })
-#define inw(p)         ({ unsigned int __v = __raw_readw(__io(p)); __v; })
-#define inl(p)         ({ unsigned int __v = __raw_readl(__io(p)); __v; })
+#define inb(p) ({ unsigned int __v = __raw_readb(__io(p)); __v; })
+#define inw(p) ({ unsigned int __v = le16_to_cpu(__raw_readw(__io(p))); __v; })
+#define inl(p) ({ unsigned int __v = le32_to_cpu(__raw_readl(__io(p))); __v; })
 
 #define outsb(p,d,l)                   __raw_writesb(__io(p),d,l)
 #define outsw(p,d,l)                   __raw_writesw(__io(p),d,l)
@@ -171,20 +186,20 @@ extern void __readwrite_bug(const char *fn);
  */
 #ifdef __mem_pci
 
-#define readb(addr) ({ unsigned int __v = __raw_readb(__mem_pci(addr)); __v; })
-#define readw(addr) ({ unsigned int __v = __raw_readw(__mem_pci(addr)); __v; })
-#define readl(addr) ({ unsigned int __v = __raw_readl(__mem_pci(addr)); __v; })
+#define readb(c) ({ unsigned int __v = __raw_readb(__mem_pci(c)); __v; })
+#define readw(c) ({ unsigned int __v = le16_to_cpu(__raw_readw(__mem_pci(c))); __v; })
+#define readl(c) ({ unsigned int __v = le32_to_cpu(__raw_readl(__mem_pci(c))); __v; })
 
-#define writeb(val,addr)               __raw_writeb(val,__mem_pci(addr))
-#define writew(val,addr)               __raw_writew(val,__mem_pci(addr))
-#define writel(val,addr)               __raw_writel(val,__mem_pci(addr))
+#define writeb(v,c)            __raw_writeb(v,__mem_pci(c))
+#define writew(v,c)            __raw_writew(cpu_to_le16(v),__mem_pci(c))
+#define writel(v,c)            __raw_writel(cpu_to_le32(v),__mem_pci(c))
 
-#define memset_io(a,b,c)               _memset_io(__mem_pci(a),(b),(c))
-#define memcpy_fromio(a,b,c)           _memcpy_fromio((a),__mem_pci(b),(c))
-#define memcpy_toio(a,b,c)             _memcpy_toio(__mem_pci(a),(b),(c))
+#define memset_io(c,v,l)               _memset_io(__mem_pci(c),(v),(l))
+#define memcpy_fromio(a,c,l)           _memcpy_fromio((a),__mem_pci(c),(l))
+#define memcpy_toio(c,a,l)             _memcpy_toio(__mem_pci(c),(a),(l))
 
-#define eth_io_copy_and_sum(a,b,c,d) \
-                               eth_copy_and_sum((a),__mem_pci(b),(c),(d))
+#define eth_io_copy_and_sum(s,c,l,b) \
+                               eth_copy_and_sum((s),__mem_pci(c),(l),(b))
 
 static inline int
 check_signature(unsigned long io_addr, const unsigned char *signature,
@@ -218,14 +233,6 @@ out:
 
 #endif /* __mem_pci */
 
-/*
- * remap a physical address `phys' of size `size' with page protection `prot'
- * into virtual address `from'
- */
-#define io_remap_page_range(from,phys,size,prot) \
-               remap_page_range(from,phys,size,prot)
-
-
 /*
  * If this architecture has ISA IO, then define the isa_read/isa_write
  * macros.
@@ -245,6 +252,10 @@ out:
 #define isa_eth_io_copy_and_sum(a,b,c,d) \
                                eth_copy_and_sum((a),__mem_isa(b),(c),(d))
 
+#ifndef PCI_MEMORY_VADDR       /* XXX problem not understood -- wd */
+#define        PCI_MEMORY_VADDR        0
+#endif /* XXX */
+
 static inline int
 isa_check_signature(unsigned long io_addr, const unsigned char *signature,
                    int length)
index a8ee99ae00366552da7e1b726efde8521ba70761..c2267bd86d44b4f76fc7cf955a70d3555c473ecf 100644 (file)
@@ -60,9 +60,9 @@
 #define CONFIG_ENV_OVERWRITE
 
 #define CONFIG_BAUDRATE                19200
+#define CONFIG_MISC_INIT_R     1       /* we have a misc_init_r() function */
 
-#define CONFIG_COMMANDS                ((CONFIG_CMD_DFL | CFG_CMD_I2C | CFG_CMD_EEPROM) & ~CFG_CMD_NET)
-
+#define CONFIG_COMMANDS (CONFIG_CMD_DFL|CFG_CMD_I2C|CFG_CMD_EEPROM|CFG_CMD_NET|CFG_CMD_JFFS2|CFG_CMD_DHCP)
 /* this must be included AFTER the definition of CONFIG_COMMANDS (if any)   */
 #include <cmd_confdefs.h>
 
 /*
  * Size of malloc() pool; this lives below the uppermost 128 KiB which are
  * used for the RAM copy of the uboot code
+ *
  */
-/* #define CFG_MALLOC_LEN      (CFG_ENV_SIZE + 128*1024) */
-#define CFG_MALLOC_LEN         (128*1024)
+#define CFG_MALLOC_LEN         (256*1024)
 
 #define CFG_LONGHELP                           /* undef to save memory         */
 #define CFG_PROMPT             "uboot> "       /* Monitor Command Prompt       */
-#define CFG_CBSIZE             128             /* Console I/O Buffer Size      */
+#define CFG_CBSIZE             256             /* Console I/O Buffer Size      */
 #define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
 #define CFG_MAXARGS            16              /* max number of command args   */
 #define CFG_BARGSIZE           CFG_CBSIZE      /* Boot Argument Buffer Size    */
 
 #undef  CFG_CLKS_IN_HZ          /* everything, incl board info, in Hz */
 
-#define CFG_LOAD_ADDR           0xa7fe0000      /* default load address */
-                                               /* RS: where is this documented? */
-                                               /* RS: is this where U-Boot is  */
-                                               /* RS: relocated to in RAM?      */
+#define CFG_LOAD_ADDR           0xa3000000      /* load kernel to this address   */
 
 #define CFG_HZ                  3686400         /* incrementer freq: 3.6864 MHz */
                                                /* RS: the oscillator is actually 3680130?? */
 /*
  * I2C bus
  */
-#define CONFIG_HARD_I2C 1
-#define CFG_I2C_SPEED 50000
-#define CFG_I2C_SLAVE 0xfe
+#define CONFIG_HARD_I2C                1
+#define CFG_I2C_SPEED                  50000
+#define CFG_I2C_SLAVE                  0xfe
 
 #define CFG_ENV_IS_IN_EEPROM           1
 
 #define CFG_ENV_SIZE                   1024    /* 1 KiB                    */
 #define CFG_I2C_EEPROM_ADDR            0x50    /* A0 = 0 (hardwired)       */
 #define CFG_EEPROM_PAGE_WRITE_BITS     5       /* 5 bits = 32 octets       */
-#define CFG_EEPROM_PAGE_WRITE_DELAY_MS 10      /* between stop and start   */
+#define CFG_EEPROM_PAGE_WRITE_DELAY_MS 15      /* between stop and start   */
 #define CFG_I2C_EEPROM_ADDR_LEN                2       /* length of address        */
 #define CFG_EEPROM_SIZE                        4096    /* size in bytes            */
+#define CFG_I2C_INIT_BOARD             1       /* board has it's own init  */
+
+/*
+ * SMSC91C111 Network Card
+ */
+#define CONFIG_DRIVER_SMC91111         1
+#define CONFIG_SMC91111_BASE           0x14000000 /* chip select 5         */
+#undef  CONFIG_SMC_USE_32_BIT                     /* 16 bit bus access     */
+#undef  CONFIG_SMC_91111_EXT_PHY                  /* we use internal phy   */
+#undef  CONFIG_SHOW_ACTIVITY
+#define CONFIG_NET_RETRY_COUNT         10         /* # of retries          */
 
 /*
  * Stack sizes
 
 #define CFG_FLASH_BASE          PHYS_FLASH_1
 
+
 /*
- * GPIO settings;
+ * JFFS2 Partitions
  */
+#define CFG_JFFS_CUSTOM_PART   1               /* see board/innokom/flash.c */
+#define CONFIG_MTD_INNOKOM_16MB 1              /* development flash         */ 
+#undef  CONFIG_MTD_INNOKOM_64MB                        /* production flash          */
 
-/* GP15 == nCS1      is 1
+
+/*
+ * GPIO settings; see BDI2000 config file for details
+ *
+ * GP15 == nCS1      is 1
  * GP24 == SFRM      is 1
  * GP25 == TXD       is 1
  * GP33 == nCS5      is 1
 #define CFG_GAFR2_L_VAL     0xA0000000
 #define CFG_GAFR2_U_VAL     0x00000002
 
+
 /* FIXME: set GPIO_RER/FER */
 
 /* RDH = 1
 
 /*
  * Memory settings
- */
-
-/* This is the configuration for nCS0/1 -> flash banks
+ *
+ * This is the configuration for nCS0/1 -> flash banks
  * configuration for nCS1:
  * [31]    0    - Slower Device
  * [30:28] 010  - CS deselect to CS time: 2*(2*MemClk) = 40 ns
  * [03]    1    - 16 Bit bus width
  * [02:00] 100  - variable latency I/O
  */
-#define CFG_MSC1_VAL           0x132C593C /* TDM switch, DSP               */
+#define CFG_MSC1_VAL           0x123C593C /* TDM switch, DSP               */
 
 /* This is the configuration for nCS4/5 -> ExtBus, LAN Controller
  *
  * [03]    1    - 16 Bit bus width
  * [02:00] 100  - variable latency I/O
  */
-#define CFG_MSC2_VAL           0x132C6CDC /* extra bus, LAN controller     */
+#define CFG_MSC2_VAL           0x123C6CDC /* extra bus, LAN controller     */
 
 /* MDCNFG: SDRAM Configuration Register
  *
  * [12]      1  - SA1111 compatiblity mode
  * [11]      1   - latch return data with return clock
  * [10]      0   - no alternate addressing for pair 0/1
- * [09:08]   01  - tRP=2*MemClk; CL=2; tRCD=2*MemClk; tRAS=5*MemClk; tRC=8*MemClk
+ * [09:08]   01  - tRP=2*MemClk CL=2 tRCD=2*MemClk tRAS=5*MemClk tRC=8*MemClk
  * [7]       1   - 4 internal banks in lower partition pair
  * [06:05]   10  - 13 row address bits for partition 0/1
  * [04:03]   01  - 9 column address bits for partition 0/1
  * [02]      0   - SDRAM partition 0/1 width is 32 bit
  * [01]      0   - disable SDRAM partition 1
  * [00]      1   - enable  SDRAM partition 0
- *
- * use the configuration above but disable partition 0
  */
+/* use the configuration above but disable partition 0 */
 #define CFG_MDCNFG_VAL         0x000019c8
 
 /* MDREFR: SDRAM Refresh Control Register
 #define CFG_FLASH_ERASE_TOUT    (2*CFG_HZ) /* Timeout for Flash Erase       */
 #define CFG_FLASH_WRITE_TOUT    (2*CFG_HZ) /* Timeout for Flash Write       */
 
-#if 0
-#define CFG_ENV_IS_IN_FLASH    1
-#define CFG_ENV_ADDR            (PHYS_FLASH_1 + 0x1C000)
-                                        /* Addr of Environment Sector       */
-#define CFG_ENV_SIZE            0x4000  /* Total Size of Environment Sector */
-#endif
-
 #endif  /* __CONFIG_H */
index 43d76fd818550d48c3679e489850580cb7547b2b..6d39080d8f5584d9f094d16b2627d483fcda5631 100644 (file)
@@ -51,6 +51,9 @@
  * repeatedly to change the speed and slave addresses.
  */
 void i2c_init(int speed, int slaveaddr);
+#ifdef CFG_I2C_INIT_BOARD
+void i2c_init_board(void);
+#endif
 
 /*
  * Probe the given I2C chip address.  Returns 0 if a chip responded,