[ARM] orion5x: add sram support for crypto
[safe/jmp/linux-2.6] / arch / arm / mach-orion5x / common.c
index b44f26d..eafcc49 100644 (file)
@@ -18,6 +18,8 @@
 #include <linux/mv643xx_eth.h>
 #include <linux/mv643xx_i2c.h>
 #include <linux/ata_platform.h>
+#include <linux/spi/orion_spi.h>
+#include <net/dsa.h>
 #include <asm/page.h>
 #include <asm/setup.h>
 #include <asm/timex.h>
@@ -27,7 +29,9 @@
 #include <mach/hardware.h>
 #include <mach/orion5x.h>
 #include <plat/ehci-orion.h>
+#include <plat/mv_xor.h>
 #include <plat/orion_nand.h>
+#include <plat/orion_wdt.h>
 #include <plat/time.h>
 #include "common.h"
 
@@ -69,6 +73,7 @@ void __init orion5x_map_io(void)
  ****************************************************************************/
 static struct orion_ehci_data orion5x_ehci_data = {
        .dram           = &orion5x_mbus_dram_info,
+       .phy_version    = EHCI_PHY_ORION,
 };
 
 static u64 ehci_dmamask = 0xffffffffUL;
@@ -145,7 +150,6 @@ void __init orion5x_ehci1_init(void)
  ****************************************************************************/
 struct mv643xx_eth_shared_platform_data orion5x_eth_shared_data = {
        .dram           = &orion5x_mbus_dram_info,
-       .t_clk          = ORION5X_TCLK,
 };
 
 static struct resource orion5x_eth_shared_resources[] = {
@@ -153,6 +157,10 @@ static struct resource orion5x_eth_shared_resources[] = {
                .start  = ORION5X_ETH_PHYS_BASE + 0x2000,
                .end    = ORION5X_ETH_PHYS_BASE + 0x3fff,
                .flags  = IORESOURCE_MEM,
+       }, {
+               .start  = IRQ_ORION5X_ETH_ERR,
+               .end    = IRQ_ORION5X_ETH_ERR,
+               .flags  = IORESOURCE_IRQ,
        },
 };
 
@@ -162,7 +170,7 @@ static struct platform_device orion5x_eth_shared = {
        .dev            = {
                .platform_data  = &orion5x_eth_shared_data,
        },
-       .num_resources  = 1,
+       .num_resources  = ARRAY_SIZE(orion5x_eth_shared_resources),
        .resource       = orion5x_eth_shared_resources,
 };
 
@@ -180,6 +188,9 @@ static struct platform_device orion5x_eth = {
        .id             = 0,
        .num_resources  = 1,
        .resource       = orion5x_eth_resources,
+       .dev            = {
+               .coherent_dma_mask      = 0xffffffff,
+       },
 };
 
 void __init orion5x_eth_init(struct mv643xx_eth_platform_data *eth_data)
@@ -193,6 +204,43 @@ void __init orion5x_eth_init(struct mv643xx_eth_platform_data *eth_data)
 
 
 /*****************************************************************************
+ * Ethernet switch
+ ****************************************************************************/
+static struct resource orion5x_switch_resources[] = {
+       {
+               .start  = 0,
+               .end    = 0,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device orion5x_switch_device = {
+       .name           = "dsa",
+       .id             = 0,
+       .num_resources  = 0,
+       .resource       = orion5x_switch_resources,
+};
+
+void __init orion5x_eth_switch_init(struct dsa_platform_data *d, int irq)
+{
+       int i;
+
+       if (irq != NO_IRQ) {
+               orion5x_switch_resources[0].start = irq;
+               orion5x_switch_resources[0].end = irq;
+               orion5x_switch_device.num_resources = 1;
+       }
+
+       d->netdev = &orion5x_eth.dev;
+       for (i = 0; i < d->nr_chips; i++)
+               d->chip[i].mii_bus = &orion5x_eth_shared.dev;
+       orion5x_switch_device.dev.platform_data = d;
+
+       platform_device_register(&orion5x_switch_device);
+}
+
+
+/*****************************************************************************
  * I2C
  ****************************************************************************/
 static struct mv64xxx_i2c_pdata orion5x_i2c_pdata = {
@@ -203,12 +251,10 @@ static struct mv64xxx_i2c_pdata orion5x_i2c_pdata = {
 
 static struct resource orion5x_i2c_resources[] = {
        {
-               .name   = "i2c base",
                .start  = I2C_PHYS_BASE,
                .end    = I2C_PHYS_BASE + 0x1f,
                .flags  = IORESOURCE_MEM,
        }, {
-               .name   = "i2c irq",
                .start  = IRQ_ORION5X_I2C,
                .end    = IRQ_ORION5X_I2C,
                .flags  = IORESOURCE_IRQ,
@@ -267,6 +313,39 @@ void __init orion5x_sata_init(struct mv_sata_platform_data *sata_data)
 
 
 /*****************************************************************************
+ * SPI
+ ****************************************************************************/
+static struct orion_spi_info orion5x_spi_plat_data = {
+       .tclk                   = 0,
+       .enable_clock_fix       = 1,
+};
+
+static struct resource orion5x_spi_resources[] = {
+       {
+               .name   = "spi base",
+               .start  = SPI_PHYS_BASE,
+               .end    = SPI_PHYS_BASE + 0x1f,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device orion5x_spi = {
+       .name           = "orion_spi",
+       .id             = 0,
+       .dev            = {
+               .platform_data  = &orion5x_spi_plat_data,
+       },
+       .num_resources  = ARRAY_SIZE(orion5x_spi_resources),
+       .resource       = orion5x_spi_resources,
+};
+
+void __init orion5x_spi_init()
+{
+       platform_device_register(&orion5x_spi);
+}
+
+
+/*****************************************************************************
  * UART0
  ****************************************************************************/
 static struct plat_serial8250_port orion5x_uart0_data[] = {
@@ -277,7 +356,7 @@ static struct plat_serial8250_port orion5x_uart0_data[] = {
                .flags          = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
                .iotype         = UPIO_MEM,
                .regshift       = 2,
-               .uartclk        = ORION5X_TCLK,
+               .uartclk        = 0,
        }, {
        },
 };
@@ -321,7 +400,7 @@ static struct plat_serial8250_port orion5x_uart1_data[] = {
                .flags          = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
                .iotype         = UPIO_MEM,
                .regshift       = 2,
-               .uartclk        = ORION5X_TCLK,
+               .uartclk        = 0,
        }, {
        },
 };
@@ -355,11 +434,189 @@ void __init orion5x_uart1_init(void)
 
 
 /*****************************************************************************
+ * XOR engine
+ ****************************************************************************/
+struct mv_xor_platform_shared_data orion5x_xor_shared_data = {
+       .dram           = &orion5x_mbus_dram_info,
+};
+
+static struct resource orion5x_xor_shared_resources[] = {
+       {
+               .name   = "xor low",
+               .start  = ORION5X_XOR_PHYS_BASE,
+               .end    = ORION5X_XOR_PHYS_BASE + 0xff,
+               .flags  = IORESOURCE_MEM,
+       }, {
+               .name   = "xor high",
+               .start  = ORION5X_XOR_PHYS_BASE + 0x200,
+               .end    = ORION5X_XOR_PHYS_BASE + 0x2ff,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device orion5x_xor_shared = {
+       .name           = MV_XOR_SHARED_NAME,
+       .id             = 0,
+       .dev            = {
+               .platform_data  = &orion5x_xor_shared_data,
+       },
+       .num_resources  = ARRAY_SIZE(orion5x_xor_shared_resources),
+       .resource       = orion5x_xor_shared_resources,
+};
+
+static u64 orion5x_xor_dmamask = DMA_BIT_MASK(32);
+
+static struct resource orion5x_xor0_resources[] = {
+       [0] = {
+               .start  = IRQ_ORION5X_XOR0,
+               .end    = IRQ_ORION5X_XOR0,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct mv_xor_platform_data orion5x_xor0_data = {
+       .shared         = &orion5x_xor_shared,
+       .hw_id          = 0,
+       .pool_size      = PAGE_SIZE,
+};
+
+static struct platform_device orion5x_xor0_channel = {
+       .name           = MV_XOR_NAME,
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(orion5x_xor0_resources),
+       .resource       = orion5x_xor0_resources,
+       .dev            = {
+               .dma_mask               = &orion5x_xor_dmamask,
+               .coherent_dma_mask      = DMA_BIT_MASK(64),
+               .platform_data          = (void *)&orion5x_xor0_data,
+       },
+};
+
+static struct resource orion5x_xor1_resources[] = {
+       [0] = {
+               .start  = IRQ_ORION5X_XOR1,
+               .end    = IRQ_ORION5X_XOR1,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct mv_xor_platform_data orion5x_xor1_data = {
+       .shared         = &orion5x_xor_shared,
+       .hw_id          = 1,
+       .pool_size      = PAGE_SIZE,
+};
+
+static struct platform_device orion5x_xor1_channel = {
+       .name           = MV_XOR_NAME,
+       .id             = 1,
+       .num_resources  = ARRAY_SIZE(orion5x_xor1_resources),
+       .resource       = orion5x_xor1_resources,
+       .dev            = {
+               .dma_mask               = &orion5x_xor_dmamask,
+               .coherent_dma_mask      = DMA_BIT_MASK(64),
+               .platform_data          = (void *)&orion5x_xor1_data,
+       },
+};
+
+void __init orion5x_xor_init(void)
+{
+       platform_device_register(&orion5x_xor_shared);
+
+       /*
+        * two engines can't do memset simultaneously, this limitation
+        * satisfied by removing memset support from one of the engines.
+        */
+       dma_cap_set(DMA_MEMCPY, orion5x_xor0_data.cap_mask);
+       dma_cap_set(DMA_XOR, orion5x_xor0_data.cap_mask);
+       platform_device_register(&orion5x_xor0_channel);
+
+       dma_cap_set(DMA_MEMCPY, orion5x_xor1_data.cap_mask);
+       dma_cap_set(DMA_MEMSET, orion5x_xor1_data.cap_mask);
+       dma_cap_set(DMA_XOR, orion5x_xor1_data.cap_mask);
+       platform_device_register(&orion5x_xor1_channel);
+}
+
+static struct resource orion5x_crypto_res[] = {
+       {
+               .name   = "regs",
+               .start  = ORION5X_CRYPTO_PHYS_BASE,
+               .end    = ORION5X_CRYPTO_PHYS_BASE + 0xffff,
+               .flags  = IORESOURCE_MEM,
+       }, {
+               .name   = "sram",
+               .start  = ORION5X_SRAM_PHYS_BASE,
+               .end    = ORION5X_SRAM_PHYS_BASE + SZ_8K - 1,
+               .flags  = IORESOURCE_MEM,
+       }, {
+               .name   = "crypto interrupt",
+               .start  = IRQ_ORION5X_CESA,
+               .end    = IRQ_ORION5X_CESA,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device orion5x_crypto_device = {
+       .name           = "mv_crypto",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(orion5x_crypto_res),
+       .resource       = orion5x_crypto_res,
+};
+
+int __init orion5x_crypto_init(void)
+{
+       int ret;
+
+       ret = orion5x_setup_sram_win();
+       if (ret)
+               return ret;
+
+       return platform_device_register(&orion5x_crypto_device);
+}
+
+/*****************************************************************************
+ * Watchdog
+ ****************************************************************************/
+static struct orion_wdt_platform_data orion5x_wdt_data = {
+       .tclk                   = 0,
+};
+
+static struct platform_device orion5x_wdt_device = {
+       .name           = "orion_wdt",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = &orion5x_wdt_data,
+       },
+       .num_resources  = 0,
+};
+
+void __init orion5x_wdt_init(void)
+{
+       orion5x_wdt_data.tclk = orion5x_tclk;
+       platform_device_register(&orion5x_wdt_device);
+}
+
+
+/*****************************************************************************
  * Time handling
  ****************************************************************************/
+int orion5x_tclk;
+
+int __init orion5x_find_tclk(void)
+{
+       u32 dev, rev;
+
+       orion5x_pcie_id(&dev, &rev);
+       if (dev == MV88F6183_DEV_ID &&
+           (readl(MPP_RESET_SAMPLE) & 0x00000200) == 0)
+               return 133333333;
+
+       return 166666667;
+}
+
 static void orion5x_timer_init(void)
 {
-       orion_time_init(IRQ_ORION5X_BRIDGE, ORION5X_TCLK);
+       orion5x_tclk = orion5x_find_tclk();
+       orion_time_init(IRQ_ORION5X_BRIDGE, orion5x_tclk);
 }
 
 struct sys_timer orion5x_timer = {
@@ -382,6 +639,8 @@ static void __init orion5x_id(u32 *dev, u32 *rev, char **dev_name)
                        *dev_name = "MV88F5281-D2";
                } else if (*rev == MV88F5281_REV_D1) {
                        *dev_name = "MV88F5281-D1";
+               } else if (*rev == MV88F5281_REV_D0) {
+                       *dev_name = "MV88F5281-D0";
                } else {
                        *dev_name = "MV88F5281-Rev-Unsupported";
                }
@@ -399,6 +658,12 @@ static void __init orion5x_id(u32 *dev, u32 *rev, char **dev_name)
                } else {
                        *dev_name = "MV88F5181(L)-Rev-Unsupported";
                }
+       } else if (*dev == MV88F6183_DEV_ID) {
+               if (*rev == MV88F6183_REV_B0) {
+                       *dev_name = "MV88F6183-Rev-B0";
+               } else {
+                       *dev_name = "MV88F6183-Rev-Unsupported";
+               }
        } else {
                *dev_name = "Device-Unknown";
        }
@@ -410,12 +675,31 @@ void __init orion5x_init(void)
        u32 dev, rev;
 
        orion5x_id(&dev, &rev, &dev_name);
-       printk(KERN_INFO "Orion ID: %s. TCLK=%d.\n", dev_name, ORION5X_TCLK);
+       printk(KERN_INFO "Orion ID: %s. TCLK=%d.\n", dev_name, orion5x_tclk);
+
+       orion5x_eth_shared_data.t_clk = orion5x_tclk;
+       orion5x_spi_plat_data.tclk = orion5x_tclk;
+       orion5x_uart0_data[0].uartclk = orion5x_tclk;
+       orion5x_uart1_data[0].uartclk = orion5x_tclk;
 
        /*
         * Setup Orion address map
         */
        orion5x_setup_cpu_mbus_bridge();
+
+       /*
+        * Don't issue "Wait for Interrupt" instruction if we are
+        * running on D0 5281 silicon.
+        */
+       if (dev == MV88F5281_DEV_ID && rev == MV88F5281_REV_D0) {
+               printk(KERN_INFO "Orion: Applying 5281 D0 WFI workaround.\n");
+               disable_hlt();
+       }
+
+       /*
+        * Register watchdog driver
+        */
+       orion5x_wdt_init();
 }
 
 /*