Merge branch 'topic/asoc' into for-linus
[sfrench/cifs-2.6.git] / arch / arm / mach-orion5x / ts78xx-setup.c
index 778b11860ee660fecd2f730db16e2835407dd2b5..9a6b397f972d533908c096468958bdf6629c997c 100644 (file)
@@ -15,6 +15,8 @@
 #include <linux/mv643xx_eth.h>
 #include <linux/ata_platform.h>
 #include <linux/m48t86.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -75,7 +77,6 @@ static struct mv_sata_platform_data ts78xx_sata_data = {
 /*****************************************************************************
  * RTC M48T86 - nicked^Wborrowed from arch/arm/mach-ep93xx/ts72xx.c
  ****************************************************************************/
-#ifdef CONFIG_RTC_DRV_M48T86
 #define TS_RTC_CTRL    (TS78XX_FPGA_REGS_VIRT_BASE | 0x808)
 #define TS_RTC_DATA    (TS78XX_FPGA_REGS_VIRT_BASE | 0x80c)
 
@@ -150,16 +151,123 @@ static void ts78xx_ts_rtc_unload(void)
 {
        platform_device_del(&ts78xx_ts_rtc_device);
 }
-#else
-static int ts78xx_ts_rtc_load(void)
+
+/*****************************************************************************
+ * NAND Flash
+ ****************************************************************************/
+#define TS_NAND_CTRL   (TS78XX_FPGA_REGS_VIRT_BASE | 0x800)    /* VIRT */
+#define TS_NAND_DATA   (TS78XX_FPGA_REGS_PHYS_BASE | 0x804)    /* PHYS */
+
+/*
+ * hardware specific access to control-lines
+ *
+ * ctrl:
+ * NAND_NCE: bit 0 -> bit 2
+ * NAND_CLE: bit 1 -> bit 1
+ * NAND_ALE: bit 2 -> bit 0
+ */
+static void ts78xx_ts_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
+                       unsigned int ctrl)
 {
-       return -ENODEV;
+       struct nand_chip *this = mtd->priv;
+
+       if (ctrl & NAND_CTRL_CHANGE) {
+               unsigned char bits;
+
+               bits = (ctrl & NAND_NCE) << 2;
+               bits |= ctrl & NAND_CLE;
+               bits |= (ctrl & NAND_ALE) >> 2;
+
+               writeb((readb(TS_NAND_CTRL) & ~0x7) | bits, TS_NAND_CTRL);
+       }
+
+       if (cmd != NAND_CMD_NONE)
+               writeb(cmd, this->IO_ADDR_W);
 }
 
-static void ts78xx_ts_rtc_unload(void)
+static int ts78xx_ts_nand_dev_ready(struct mtd_info *mtd)
+{
+       return readb(TS_NAND_CTRL) & 0x20;
+}
+
+const char *ts_nand_part_probes[] = { "cmdlinepart", NULL };
+
+static struct mtd_partition ts78xx_ts_nand_parts[] = {
+       {
+               .name           = "mbr",
+               .offset         = 0,
+               .size           = SZ_128K,
+               .mask_flags     = MTD_WRITEABLE,
+       }, {
+               .name           = "kernel",
+               .offset         = MTDPART_OFS_APPEND,
+               .size           = SZ_4M,
+       }, {
+               .name           = "initrd",
+               .offset         = MTDPART_OFS_APPEND,
+               .size           = SZ_4M,
+       }, {
+               .name           = "rootfs",
+               .offset         = MTDPART_OFS_APPEND,
+               .size           = MTDPART_SIZ_FULL,
+       }
+};
+
+static struct platform_nand_data ts78xx_ts_nand_data = {
+       .chip   = {
+               .part_probe_types       = ts_nand_part_probes,
+               .partitions             = ts78xx_ts_nand_parts,
+               .nr_partitions          = ARRAY_SIZE(ts78xx_ts_nand_parts),
+               .chip_delay             = 15,
+               .options                = NAND_USE_FLASH_BBT,
+       },
+       .ctrl   = {
+               /*
+                * The HW ECC offloading functions, used to give about a 9%
+                * performance increase for 'dd if=/dev/mtdblockX' and 5% for
+                * nanddump.  This all however was changed by git commit
+                * e6cf5df1838c28bb060ac45b5585e48e71bbc740 so now there is
+                * no performance advantage to be had so we no longer bother
+                */
+               .cmd_ctrl               = ts78xx_ts_nand_cmd_ctrl,
+               .dev_ready              = ts78xx_ts_nand_dev_ready,
+       },
+};
+
+static struct resource ts78xx_ts_nand_resources = {
+       .start          = TS_NAND_DATA,
+       .end            = TS_NAND_DATA + 4,
+       .flags          = IORESOURCE_IO,
+};
+
+static struct platform_device ts78xx_ts_nand_device = {
+       .name           = "gen_nand",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = &ts78xx_ts_nand_data,
+       },
+       .resource       = &ts78xx_ts_nand_resources,
+       .num_resources  = 1,
+};
+
+static int ts78xx_ts_nand_load(void)
 {
+       int rc;
+
+       if (ts78xx_fpga.supports.ts_nand.init == 0) {
+               rc = platform_device_register(&ts78xx_ts_nand_device);
+               if (!rc)
+                       ts78xx_fpga.supports.ts_nand.init = 1;
+       } else
+               rc = platform_device_add(&ts78xx_ts_nand_device);
+
+       return rc;
+};
+
+static void ts78xx_ts_nand_unload(void)
+{
+       platform_device_del(&ts78xx_ts_nand_device);
 }
-#endif
 
 /*****************************************************************************
  * FPGA 'hotplug' support code
@@ -167,17 +275,24 @@ static void ts78xx_ts_rtc_unload(void)
 static void ts78xx_fpga_devices_zero_init(void)
 {
        ts78xx_fpga.supports.ts_rtc.init = 0;
+       ts78xx_fpga.supports.ts_nand.init = 0;
 }
 
 static void ts78xx_fpga_supports(void)
 {
        /* TODO: put this 'table' into ts78xx-fpga.h */
        switch (ts78xx_fpga.id) {
-       case TS7800_REV_B:
+       case TS7800_REV_1:
+       case TS7800_REV_2:
+       case TS7800_REV_3:
+       case TS7800_REV_4:
+       case TS7800_REV_5:
                ts78xx_fpga.supports.ts_rtc.present = 1;
+               ts78xx_fpga.supports.ts_nand.present = 1;
                break;
        default:
                ts78xx_fpga.supports.ts_rtc.present = 0;
+               ts78xx_fpga.supports.ts_nand.present = 0;
        }
 }
 
@@ -188,12 +303,19 @@ static int ts78xx_fpga_load_devices(void)
        if (ts78xx_fpga.supports.ts_rtc.present == 1) {
                tmp = ts78xx_ts_rtc_load();
                if (tmp) {
-                       printk(KERN_INFO "TS-78xx RTC"
-                                       " not detected or enabled\n");
+                       printk(KERN_INFO "TS-78xx: RTC not registered\n");
                        ts78xx_fpga.supports.ts_rtc.present = 0;
                }
                ret |= tmp;
        }
+       if (ts78xx_fpga.supports.ts_nand.present == 1) {
+               tmp = ts78xx_ts_nand_load();
+               if (tmp) {
+                       printk(KERN_INFO "TS-78xx: NAND not registered\n");
+                       ts78xx_fpga.supports.ts_nand.present = 0;
+               }
+               ret |= tmp;
+       }
 
        return ret;
 }
@@ -204,6 +326,8 @@ static int ts78xx_fpga_unload_devices(void)
 
        if (ts78xx_fpga.supports.ts_rtc.present == 1)
                ts78xx_ts_rtc_unload();
+       if (ts78xx_fpga.supports.ts_nand.present == 1)
+               ts78xx_ts_nand_unload();
 
        return ret;
 }