[rdc] add preliminary support for the bifferboard, patch from bifferos
authorFlorian Fainelli <florian@openwrt.org>
Sat, 12 Dec 2009 17:17:00 +0000 (17:17 +0000)
committerFlorian Fainelli <florian@openwrt.org>
Sat, 12 Dec 2009 17:17:00 +0000 (17:17 +0000)
SVN-Revision: 18766

target/linux/rdc/Makefile
target/linux/rdc/bifferboard/config-2.6.30 [new file with mode: 0644]
target/linux/rdc/bifferboard/target.mk [new file with mode: 0644]
target/linux/rdc/files/drivers/mtd/maps/bifferboard-flash.c [new file with mode: 0644]
target/linux/rdc/image/mkimg_bifferboard.py [new file with mode: 0755]

index 141e86e8fe6a7497cddcf567ca8a6076c0603b44..a8ca8f856af75e9a8dbc30b982cab50cdd5b2544 100644 (file)
@@ -11,7 +11,7 @@ BOARD:=rdc
 BOARDNAME:=RDC 321x
 FEATURES:=squashfs jffs2 pci usb pcmcia
 CFLAGS:=-Os -pipe -march=i486 -funit-at-a-time
-SUBTARGETS:=amit ar525w r8610 dir-450 sitecom
+SUBTARGETS:=amit ar525w r8610 dir-450 sitecom bifferboard
 
 LINUX_VERSION:=2.6.30.10
 
diff --git a/target/linux/rdc/bifferboard/config-2.6.30 b/target/linux/rdc/bifferboard/config-2.6.30
new file mode 100644 (file)
index 0000000..e37e74c
--- /dev/null
@@ -0,0 +1,8 @@
+CONFIG_CMDLINE="console=ttyS0,115200 rootfstype=squashfs,jffs2"
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_RDC3210=y
+CONFIG_MTD_RDC3210_ALLOW_JFFS2=y
+CONFIG_MTD_RDC3210_BUSWIDTH=2
+# CONFIG_MTD_RDC3210_FACTORY_PRESENT is not set
+CONFIG_MTD_RDC3210_SIZE=0x800000
+# CONFIG_MTD_RDC3210_STATIC_MAP is not set
diff --git a/target/linux/rdc/bifferboard/target.mk b/target/linux/rdc/bifferboard/target.mk
new file mode 100644 (file)
index 0000000..24dd13f
--- /dev/null
@@ -0,0 +1 @@
+BOARDNAME:=Bifferboard
diff --git a/target/linux/rdc/files/drivers/mtd/maps/bifferboard-flash.c b/target/linux/rdc/files/drivers/mtd/maps/bifferboard-flash.c
new file mode 100644 (file)
index 0000000..e732334
--- /dev/null
@@ -0,0 +1,243 @@
+/* Flash mapping for Bifferboard, (c) bifferos@yahoo.co.uk 
+ * Works with 1, 4 and 8MB flash versions
+ */
+
+#include <linux/delay.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+
+#define DRV "bifferboard-flash: "
+
+static struct mtd_info *bb_mtd = NULL;
+
+#define SIZE_BIFFBOOT 0x10000
+#define SIZE_SECTOR   0x10000
+#define SIZE_CONFIG   0x02000
+#define SIZE_1MB 0x00100000
+#define SIZE_4MB 0x00400000
+#define SIZE_8MB 0x00800000
+
+#define BASE_1MB 0xfff00000
+#define BASE_4MB 0xffc00000
+#define BASE_8MB 0xff800000
+
+#define OFFS_KERNEL 0x6000
+#define OFFS_CONFIG 0x4000
+
+/*
+ * Flash detection code.  This is needed because the cfi_probe doesn't probe
+ * for the size correctly.  You actually have to know the flash size before you
+ * call it, or so it seems.  It does work correctly if you map the entire flash
+ * chip, but unsure of the implications for mapping more mem than exists.
+ */
+
+static unsigned char ReadFlash(void* base, u32 addr)
+{
+       unsigned char val = *(volatile unsigned char *)(base+addr);  
+       udelay(1);
+       return val;
+}
+
+static void WriteFlash(void* base, u32 addr, unsigned short data)
+{
+       *(volatile unsigned short *)(base+addr) = data;
+}
+
+static DEFINE_SPINLOCK(flash_lock);
+
+static u32 bb_detect(void)
+{
+       u32 ret = 0;  
+       ulong flags;
+  
+       /* for detection, map in just the 1MB device, 1st 64k is enough */
+       void* base = ioremap_nocache(BASE_1MB, 0x10000);
+    
+       if (!base)
+       {
+               pr_err(DRV "Failed to map flash for probing\n");
+               return 0;
+       }
+  
+       spin_lock_irqsave(&flash_lock, flags);  
+  
+       /* put flash in auto-detect mode */
+       WriteFlash(base, 0xaaaa, 0xaaaa);
+       WriteFlash(base, 0x5554, 0x5555);
+       WriteFlash(base, 0xaaaa, 0x9090);
+
+       /* Read the auto-config data - 4 values in total */
+       ret = ReadFlash(base, 0x0000);  ret <<= 8;
+       ret |= ReadFlash(base, 0x0200);  ret <<= 8;
+       ret |= ReadFlash(base, 0x0003);  ret <<= 8;
+       ret |= ReadFlash(base, 0x0002);
+  
+       /* exit the autodetect state */
+       WriteFlash(base, 0x0000, 0xf0f0);
+  
+       spin_unlock_irqrestore(&flash_lock, flags);
+  
+       /* unmap it, it'll be re-mapped based on the detection */
+       iounmap(base);
+  
+       return ret;
+}
+
+
+static struct map_info bb_map;
+
+/* Update the map, using the detected flash signature. */
+static int bb_adjust_map(unsigned long sig, struct map_info* m)
+{
+       m->bankwidth = 2;
+       switch (sig)
+       {
+               case 0x7f1c225b :
+                       m->name = "ENLV800B";
+                       m->phys = BASE_1MB;
+                       m->size = SIZE_1MB;
+                       break;
+               case 0x7f1c22f9 :
+                       m->name = "ENLV320B";
+                       m->phys = BASE_4MB;
+                       m->size = SIZE_4MB;
+                       break;
+               case 0x7f1c22cb :
+                       m->name = "ENLV640B";
+                       m->phys = BASE_8MB;
+                       m->size = SIZE_8MB;
+                       break;
+               default:
+                       return -ENXIO;
+       }
+       return 0;
+}
+
+
+/* adjust partition sizes, prior to adding the partition
+ * Values not specified by defines here are subject to replacement based on 
+ * the real flash size. (0x00000000 being the exception, of course) */
+
+static struct mtd_partition bb_parts[] = 
+{
+/* 0 */        { name: "kernel",   offset: 0x00000000,         size: 0x000fa000 },
+/* 1 */        { name: "rootfs",   offset: MTDPART_OFS_APPEND, size: 0x002F0000 },
+/* 2 */        { name: "biffboot", offset: MTDPART_OFS_APPEND, size: MTDPART_SIZ_FULL, mask_flags: MTD_WRITEABLE },
+};
+
+
+/* returns the count of partitions to be used */
+static ulong bb_adjust_partitions(struct map_info* m)
+{
+       /* Read the kernel offset value, 1036 bytes into the config block. */
+       u16 km_units = *((u16*)(m->virt + OFFS_CONFIG + 1036));
+       u32 kernelmax = 0x200000;  /* Biffboot 2.7 or earlier default */
+       
+       /* special-case 1MB devices, because there are fewer partitions */
+       if (m->size == SIZE_1MB)
+       {
+               bb_parts[0].size   = SIZE_1MB - SIZE_BIFFBOOT;  /* kernel */
+               bb_parts[1].name   = "biffboot";                /* biffboot */
+               bb_parts[1].offset = MTDPART_OFS_APPEND;        /* biffboot */
+               bb_parts[1].size   = MTDPART_SIZ_FULL;          /* biffboot */
+               bb_parts[1].mask_flags = MTD_WRITEABLE;
+               return 2;   /* because there's no rootfs now */
+       }
+       
+       /* sanity check */
+       if (km_units > ((m->size-SIZE_BIFFBOOT)/SIZE_SECTOR))
+       {
+               pr_err(DRV "config block has invalid kernelmax\n");
+               return 0;
+       }
+       
+       kernelmax = km_units * SIZE_SECTOR;
+       
+       /* Kernel */
+       bb_parts[0].size = kernelmax;
+       
+       /* rootfs */
+       bb_parts[1].size   = m->size - kernelmax - SIZE_BIFFBOOT;
+               
+       return 3;  /* 3 partitions */
+}
+
+
+static int __init init_bb_map(void)
+{
+       int ret;
+       ulong signature = bb_detect();
+       ulong part_len;
+       
+       if (!signature)
+       {
+               pr_err(DRV "Undetected flash chip");
+               return -ENXIO;
+       }
+       
+       ret = bb_adjust_map(signature, &bb_map);
+       
+       if (ret)
+       {
+               pr_err(DRV "Unrecognised flash chip (signature: 0x%lx)\n", signature);
+               return ret;
+       }
+       
+       bb_map.virt = ioremap_nocache(bb_map.phys, bb_map.size);
+       if (!bb_map.virt) 
+       {
+               pr_err(DRV "ioremap\n");
+               return -EIO;
+       }
+       
+       bb_mtd = do_map_probe("cfi_probe", &bb_map);
+       if (!bb_mtd)
+       {
+               /* cfi_probe fails here for 1MB devices */
+               pr_err(DRV "cfi_probe\n");
+               ret = -ENXIO;
+               goto err;
+       }
+
+       part_len = bb_adjust_partitions(&bb_map);
+       if (!part_len)
+       {
+               pr_err(DRV "no partitions established");
+               ret = -ENXIO;
+               goto err2;
+       }
+       
+       bb_mtd->owner = THIS_MODULE;
+       ret = add_mtd_partitions(bb_mtd, bb_parts, part_len);
+       if (ret) 
+       {
+               pr_err(DRV "add_mtd_partitions\n");
+               ret = -ENXIO;
+               goto err2;
+       }
+       
+       return 0;
+       
+err2:
+       map_destroy(bb_mtd);
+err:
+       iounmap(bb_map.virt);
+
+       return ret;
+}
+
+static void __exit exit_bb_map(void)
+{
+       del_mtd_partitions(bb_mtd);
+       map_destroy(bb_mtd);    
+       iounmap(bb_map.virt);
+}
+
+module_init(init_bb_map);
+module_exit(exit_bb_map);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Bifferos <bifferos@yahoo.co.uk>");
+MODULE_DESCRIPTION("MTD map driver for Bifferboard");
+
diff --git a/target/linux/rdc/image/mkimg_bifferboard.py b/target/linux/rdc/image/mkimg_bifferboard.py
new file mode 100755 (executable)
index 0000000..040c462
--- /dev/null
@@ -0,0 +1,40 @@
+#!/usr/bin/env python
+
+"""
+   Create firmware for 8MB Bifferboards
+   Firmware does not include the config blocks
+   Firmware starts just after config
+"""
+
+import struct, sys
+
+kernel_extent = 0x200000
+config = 0x6000
+
+if __name__ == "__main__":
+
+  if len(sys.argv) != 4:
+    print  "usage: mkimg_bifferboard.py <kernel> <64k JFFS> <output file>"
+    sys.exit(0)
+    
+  bzimage = sys.argv[1]
+  rootfs = sys.argv[2]
+  target = sys.argv[3]
+
+  # Kernel first
+  fw = file(bzimage).read()
+  if len(fw) > (kernel_extent - config):
+    raise IOError("Kernel too large")
+
+  # Pad up to 0x200000
+  while len(fw) < (kernel_extent - config):
+    fw += "\xff"
+
+  fw += file(rootfs).read()
+
+  # Check length of total
+  if len(fw) > (0x800000 - 0x10000 - 0x6000):
+    raise IOError("Rootfs too large")
+
+  file(target,"wb").write(fw)
+  print "Firmware written to '%s'" % target