]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/mips/txx9/generic/setup.c
MIPS: TXx9: Add mtd support
[linux-2.6-omap-h63xx.git] / arch / mips / txx9 / generic / setup.c
index dc5dbcc53a913c449e09bd5f8e65d963bdea794a..cfa3ccf493bb1d36a645d582c74d12d93ca5761d 100644 (file)
 #include <linux/gpio.h>
 #include <linux/platform_device.h>
 #include <linux/serial_core.h>
+#include <linux/mtd/physmap.h>
 #include <asm/bootinfo.h>
 #include <asm/time.h>
 #include <asm/reboot.h>
+#include <asm/r4kcache.h>
 #include <asm/txx9/generic.h>
 #include <asm/txx9/pci.h>
 #ifdef CONFIG_CPU_TX49XX
@@ -67,7 +69,12 @@ unsigned int txx9_master_clock;
 unsigned int txx9_cpu_clock;
 unsigned int txx9_gbus_clock;
 
+#ifdef CONFIG_CPU_TX39XX
+/* don't enable by default - see errata */
+int txx9_ccfg_toeon __initdata;
+#else
 int txx9_ccfg_toeon __initdata = 1;
+#endif
 
 /* Minimum CLK support */
 
@@ -186,6 +193,110 @@ static void __init prom_init_cmdline(void)
        }
 }
 
+static int txx9_ic_disable __initdata;
+static int txx9_dc_disable __initdata;
+
+#if defined(CONFIG_CPU_TX49XX)
+/* flush all cache on very early stage (before 4k_cache_init) */
+static void __init early_flush_dcache(void)
+{
+       unsigned int conf = read_c0_config();
+       unsigned int dc_size = 1 << (12 + ((conf & CONF_DC) >> 6));
+       unsigned int linesz = 32;
+       unsigned long addr, end;
+
+       end = INDEX_BASE + dc_size / 4;
+       /* 4way, waybit=0 */
+       for (addr = INDEX_BASE; addr < end; addr += linesz) {
+               cache_op(Index_Writeback_Inv_D, addr | 0);
+               cache_op(Index_Writeback_Inv_D, addr | 1);
+               cache_op(Index_Writeback_Inv_D, addr | 2);
+               cache_op(Index_Writeback_Inv_D, addr | 3);
+       }
+}
+
+static void __init txx9_cache_fixup(void)
+{
+       unsigned int conf;
+
+       conf = read_c0_config();
+       /* flush and disable */
+       if (txx9_ic_disable) {
+               conf |= TX49_CONF_IC;
+               write_c0_config(conf);
+       }
+       if (txx9_dc_disable) {
+               early_flush_dcache();
+               conf |= TX49_CONF_DC;
+               write_c0_config(conf);
+       }
+
+       /* enable cache */
+       conf = read_c0_config();
+       if (!txx9_ic_disable)
+               conf &= ~TX49_CONF_IC;
+       if (!txx9_dc_disable)
+               conf &= ~TX49_CONF_DC;
+       write_c0_config(conf);
+
+       if (conf & TX49_CONF_IC)
+               pr_info("TX49XX I-Cache disabled.\n");
+       if (conf & TX49_CONF_DC)
+               pr_info("TX49XX D-Cache disabled.\n");
+}
+#elif defined(CONFIG_CPU_TX39XX)
+/* flush all cache on very early stage (before tx39_cache_init) */
+static void __init early_flush_dcache(void)
+{
+       unsigned int conf = read_c0_config();
+       unsigned int dc_size = 1 << (10 + ((conf & TX39_CONF_DCS_MASK) >>
+                                          TX39_CONF_DCS_SHIFT));
+       unsigned int linesz = 16;
+       unsigned long addr, end;
+
+       end = INDEX_BASE + dc_size / 2;
+       /* 2way, waybit=0 */
+       for (addr = INDEX_BASE; addr < end; addr += linesz) {
+               cache_op(Index_Writeback_Inv_D, addr | 0);
+               cache_op(Index_Writeback_Inv_D, addr | 1);
+       }
+}
+
+static void __init txx9_cache_fixup(void)
+{
+       unsigned int conf;
+
+       conf = read_c0_config();
+       /* flush and disable */
+       if (txx9_ic_disable) {
+               conf &= ~TX39_CONF_ICE;
+               write_c0_config(conf);
+       }
+       if (txx9_dc_disable) {
+               early_flush_dcache();
+               conf &= ~TX39_CONF_DCE;
+               write_c0_config(conf);
+       }
+
+       /* enable cache */
+       conf = read_c0_config();
+       if (!txx9_ic_disable)
+               conf |= TX39_CONF_ICE;
+       if (!txx9_dc_disable)
+               conf |= TX39_CONF_DCE;
+       write_c0_config(conf);
+
+       if (!(conf & TX39_CONF_ICE))
+               pr_info("TX39XX I-Cache disabled.\n");
+       if (!(conf & TX39_CONF_DCE))
+               pr_info("TX39XX D-Cache disabled.\n");
+}
+#else
+static inline void txx9_cache_fixup(void)
+{
+}
+#endif
+
 static void __init preprocess_cmdline(void)
 {
        char cmdline[CL_SIZE];
@@ -204,11 +315,25 @@ static void __init preprocess_cmdline(void)
                        if (strict_strtoul(str + 10, 10, &val) == 0)
                                txx9_master_clock = val;
                        continue;
+               } else if (strcmp(str, "icdisable") == 0) {
+                       txx9_ic_disable = 1;
+                       continue;
+               } else if (strcmp(str, "dcdisable") == 0) {
+                       txx9_dc_disable = 1;
+                       continue;
+               } else if (strcmp(str, "toeoff") == 0) {
+                       txx9_ccfg_toeon = 0;
+                       continue;
+               } else if (strcmp(str, "toeon") == 0) {
+                       txx9_ccfg_toeon = 1;
+                       continue;
                }
                if (arcs_cmdline[0])
                        strcat(arcs_cmdline, " ");
                strcat(arcs_cmdline, str);
        }
+
+       txx9_cache_fixup();
 }
 
 static void __init select_board(void)
@@ -469,3 +594,43 @@ static unsigned long __swizzle_addr_none(unsigned long port)
 unsigned long (*__swizzle_addr_b)(unsigned long port) = __swizzle_addr_none;
 EXPORT_SYMBOL(__swizzle_addr_b);
 #endif
+
+void __init txx9_physmap_flash_init(int no, unsigned long addr,
+                                   unsigned long size,
+                                   const struct physmap_flash_data *pdata)
+{
+#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
+       struct resource res = {
+               .start = addr,
+               .end = addr + size - 1,
+               .flags = IORESOURCE_MEM,
+       };
+       struct platform_device *pdev;
+#ifdef CONFIG_MTD_PARTITIONS
+       static struct mtd_partition parts[2];
+       struct physmap_flash_data pdata_part;
+
+       /* If this area contained boot area, make separate partition */
+       if (pdata->nr_parts == 0 && !pdata->parts &&
+           addr < 0x1fc00000 && addr + size > 0x1fc00000 &&
+           !parts[0].name) {
+               parts[0].name = "boot";
+               parts[0].offset = 0x1fc00000 - addr;
+               parts[0].size = addr + size - 0x1fc00000;
+               parts[1].name = "user";
+               parts[1].offset = 0;
+               parts[1].size = 0x1fc00000 - addr;
+               pdata_part = *pdata;
+               pdata_part.nr_parts = ARRAY_SIZE(parts);
+               pdata_part.parts = parts;
+               pdata = &pdata_part;
+       }
+#endif
+       pdev = platform_device_alloc("physmap-flash", no);
+       if (!pdev ||
+           platform_device_add_resources(pdev, &res, 1) ||
+           platform_device_add_data(pdev, pdata, sizeof(*pdata)) ||
+           platform_device_add(pdev))
+               platform_device_put(pdev);
+#endif
+}