[ARM] orion5x: add sram support for crypto
[safe/jmp/linux-2.6] / arch / arm / mach-orion5x / common.c
index fa4be3c..eafcc49 100644 (file)
 #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>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
-#include <asm/arch/hardware.h>
-#include <asm/arch/orion5x.h>
-#include <asm/plat-orion/ehci-orion.h>
-#include <asm/plat-orion/orion_nand.h>
-#include <asm/plat-orion/time.h>
+#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"
 
 /*****************************************************************************
@@ -63,65 +67,21 @@ void __init orion5x_map_io(void)
        iotable_init(orion5x_io_desc, ARRAY_SIZE(orion5x_io_desc));
 }
 
+
 /*****************************************************************************
- * UART
+ * EHCI
  ****************************************************************************/
-
-static struct resource orion5x_uart_resources[] = {
-       {
-               .start          = UART0_PHYS_BASE,
-               .end            = UART0_PHYS_BASE + 0xff,
-               .flags          = IORESOURCE_MEM,
-       }, {
-               .start          = IRQ_ORION5X_UART0,
-               .end            = IRQ_ORION5X_UART0,
-               .flags          = IORESOURCE_IRQ,
-       }, {
-               .start          = UART1_PHYS_BASE,
-               .end            = UART1_PHYS_BASE + 0xff,
-               .flags          = IORESOURCE_MEM,
-       }, {
-               .start          = IRQ_ORION5X_UART1,
-               .end            = IRQ_ORION5X_UART1,
-               .flags          = IORESOURCE_IRQ,
-       },
-};
-
-static struct plat_serial8250_port orion5x_uart_data[] = {
-       {
-               .mapbase        = UART0_PHYS_BASE,
-               .membase        = (char *)UART0_VIRT_BASE,
-               .irq            = IRQ_ORION5X_UART0,
-               .flags          = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
-               .iotype         = UPIO_MEM,
-               .regshift       = 2,
-               .uartclk        = ORION5X_TCLK,
-       }, {
-               .mapbase        = UART1_PHYS_BASE,
-               .membase        = (char *)UART1_VIRT_BASE,
-               .irq            = IRQ_ORION5X_UART1,
-               .flags          = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
-               .iotype         = UPIO_MEM,
-               .regshift       = 2,
-               .uartclk        = ORION5X_TCLK,
-       }, {
-       },
+static struct orion_ehci_data orion5x_ehci_data = {
+       .dram           = &orion5x_mbus_dram_info,
+       .phy_version    = EHCI_PHY_ORION,
 };
 
-static struct platform_device orion5x_uart = {
-       .name                   = "serial8250",
-       .id                     = PLAT8250_DEV_PLATFORM,
-       .dev                    = {
-               .platform_data  = orion5x_uart_data,
-       },
-       .resource               = orion5x_uart_resources,
-       .num_resources          = ARRAY_SIZE(orion5x_uart_resources),
-};
+static u64 ehci_dmamask = 0xffffffffUL;
 
-/*******************************************************************************
- * USB Controller - 2 interfaces
- ******************************************************************************/
 
+/*****************************************************************************
+ * EHCI0
+ ****************************************************************************/
 static struct resource orion5x_ehci0_resources[] = {
        {
                .start  = ORION5X_USB0_PHYS_BASE,
@@ -134,24 +94,6 @@ static struct resource orion5x_ehci0_resources[] = {
        },
 };
 
-static struct resource orion5x_ehci1_resources[] = {
-       {
-               .start  = ORION5X_USB1_PHYS_BASE,
-               .end    = ORION5X_USB1_PHYS_BASE + SZ_4K - 1,
-               .flags  = IORESOURCE_MEM,
-       }, {
-               .start  = IRQ_ORION5X_USB1_CTRL,
-               .end    = IRQ_ORION5X_USB1_CTRL,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct orion_ehci_data orion5x_ehci_data = {
-       .dram           = &orion5x_mbus_dram_info,
-};
-
-static u64 ehci_dmamask = 0xffffffffUL;
-
 static struct platform_device orion5x_ehci0 = {
        .name           = "orion-ehci",
        .id             = 0,
@@ -164,6 +106,27 @@ static struct platform_device orion5x_ehci0 = {
        .num_resources  = ARRAY_SIZE(orion5x_ehci0_resources),
 };
 
+void __init orion5x_ehci0_init(void)
+{
+       platform_device_register(&orion5x_ehci0);
+}
+
+
+/*****************************************************************************
+ * EHCI1
+ ****************************************************************************/
+static struct resource orion5x_ehci1_resources[] = {
+       {
+               .start  = ORION5X_USB1_PHYS_BASE,
+               .end    = ORION5X_USB1_PHYS_BASE + SZ_4K - 1,
+               .flags  = IORESOURCE_MEM,
+       }, {
+               .start  = IRQ_ORION5X_USB1_CTRL,
+               .end    = IRQ_ORION5X_USB1_CTRL,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
 static struct platform_device orion5x_ehci1 = {
        .name           = "orion-ehci",
        .id             = 1,
@@ -176,14 +139,17 @@ static struct platform_device orion5x_ehci1 = {
        .num_resources  = ARRAY_SIZE(orion5x_ehci1_resources),
 };
 
+void __init orion5x_ehci1_init(void)
+{
+       platform_device_register(&orion5x_ehci1);
+}
+
+
 /*****************************************************************************
- * Gigabit Ethernet port
- * (The Orion and Discovery (MV643xx) families use the same Ethernet driver)
+ * GigE
  ****************************************************************************/
-
 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[] = {
@@ -191,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,
        },
 };
 
@@ -200,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,
 };
 
@@ -218,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)
@@ -229,11 +202,47 @@ void __init orion5x_eth_init(struct mv643xx_eth_platform_data *eth_data)
        platform_device_register(&orion5x_eth);
 }
 
+
 /*****************************************************************************
- * I2C controller
- * (The Orion and Discovery (MV643xx) families share the same I2C controller)
+ * 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 = {
        .freq_m         = 8, /* assumes 166 MHz TCLK */
        .freq_n         = 3,
@@ -242,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 + 0x20 -1,
+               .end    = I2C_PHYS_BASE + 0x1f,
                .flags  = IORESOURCE_MEM,
        }, {
-               .name   = "i2c irq",
                .start  = IRQ_ORION5X_I2C,
                .end    = IRQ_ORION5X_I2C,
                .flags  = IORESOURCE_IRQ,
@@ -264,8 +271,14 @@ static struct platform_device orion5x_i2c = {
        },
 };
 
+void __init orion5x_i2c_init(void)
+{
+       platform_device_register(&orion5x_i2c);
+}
+
+
 /*****************************************************************************
- * Sata port
+ * SATA
  ****************************************************************************/
 static struct resource orion5x_sata_resources[] = {
        {
@@ -298,23 +311,322 @@ void __init orion5x_sata_init(struct mv_sata_platform_data *sata_data)
        platform_device_register(&orion5x_sata);
 }
 
+
+/*****************************************************************************
+ * 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[] = {
+       {
+               .mapbase        = UART0_PHYS_BASE,
+               .membase        = (char *)UART0_VIRT_BASE,
+               .irq            = IRQ_ORION5X_UART0,
+               .flags          = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
+               .iotype         = UPIO_MEM,
+               .regshift       = 2,
+               .uartclk        = 0,
+       }, {
+       },
+};
+
+static struct resource orion5x_uart0_resources[] = {
+       {
+               .start          = UART0_PHYS_BASE,
+               .end            = UART0_PHYS_BASE + 0xff,
+               .flags          = IORESOURCE_MEM,
+       }, {
+               .start          = IRQ_ORION5X_UART0,
+               .end            = IRQ_ORION5X_UART0,
+               .flags          = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device orion5x_uart0 = {
+       .name                   = "serial8250",
+       .id                     = PLAT8250_DEV_PLATFORM,
+       .dev                    = {
+               .platform_data  = orion5x_uart0_data,
+       },
+       .resource               = orion5x_uart0_resources,
+       .num_resources          = ARRAY_SIZE(orion5x_uart0_resources),
+};
+
+void __init orion5x_uart0_init(void)
+{
+       platform_device_register(&orion5x_uart0);
+}
+
+
+/*****************************************************************************
+ * UART1
+ ****************************************************************************/
+static struct plat_serial8250_port orion5x_uart1_data[] = {
+       {
+               .mapbase        = UART1_PHYS_BASE,
+               .membase        = (char *)UART1_VIRT_BASE,
+               .irq            = IRQ_ORION5X_UART1,
+               .flags          = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
+               .iotype         = UPIO_MEM,
+               .regshift       = 2,
+               .uartclk        = 0,
+       }, {
+       },
+};
+
+static struct resource orion5x_uart1_resources[] = {
+       {
+               .start          = UART1_PHYS_BASE,
+               .end            = UART1_PHYS_BASE + 0xff,
+               .flags          = IORESOURCE_MEM,
+       }, {
+               .start          = IRQ_ORION5X_UART1,
+               .end            = IRQ_ORION5X_UART1,
+               .flags          = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device orion5x_uart1 = {
+       .name                   = "serial8250",
+       .id                     = PLAT8250_DEV_PLATFORM1,
+       .dev                    = {
+               .platform_data  = orion5x_uart1_data,
+       },
+       .resource               = orion5x_uart1_resources,
+       .num_resources          = ARRAY_SIZE(orion5x_uart1_resources),
+};
+
+void __init orion5x_uart1_init(void)
+{
+       platform_device_register(&orion5x_uart1);
+}
+
+
+/*****************************************************************************
+ * 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 = {
        .init = orion5x_timer_init,
 };
 
+
 /*****************************************************************************
  * General
  ****************************************************************************/
-
 /*
  * Identify device ID and rev from PCIe configuration header space '0'.
  */
@@ -327,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";
                }
@@ -339,8 +653,16 @@ static void __init orion5x_id(u32 *dev, u32 *rev, char **dev_name)
        } else if (*dev == MV88F5181_DEV_ID) {
                if (*rev == MV88F5181_REV_B1) {
                        *dev_name = "MV88F5181-Rev-B1";
+               } else if (*rev == MV88F5181L_REV_A1) {
+                       *dev_name = "MV88F5181L-Rev-A1";
                } else {
-                       *dev_name = "MV88F5181-Rev-Unsupported";
+                       *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";
@@ -353,7 +675,12 @@ 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
@@ -361,13 +688,18 @@ void __init orion5x_init(void)
        orion5x_setup_cpu_mbus_bridge();
 
        /*
-        * Register devices.
+        * Don't issue "Wait for Interrupt" instruction if we are
+        * running on D0 5281 silicon.
         */
-       platform_device_register(&orion5x_uart);
-       platform_device_register(&orion5x_ehci0);
-       if (dev == MV88F5182_DEV_ID)
-               platform_device_register(&orion5x_ehci1);
-       platform_device_register(&orion5x_i2c);
+       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();
 }
 
 /*