Merge branch 'linux-next' of git://git.infradead.org/~dedekind/ubi-2.6
[pandora-kernel.git] / arch / avr32 / mach-at32ap / at32ap700x.c
index b65d3e0..351e1b4 100644 (file)
@@ -7,6 +7,7 @@
  */
 #include <linux/clk.h>
 #include <linux/delay.h>
+#include <linux/dw_dmac.h>
 #include <linux/fb.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>
 #include <linux/usb/atmel_usba_udc.h>
 
+#include <asm/atmel-mci.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 
 #include <asm/arch/at32ap700x.h>
 #include <asm/arch/board.h>
 #include <asm/arch/portmux.h>
+#include <asm/arch/sram.h>
 
 #include <video/atmel_lcdc.h>
 
@@ -93,19 +96,12 @@ static struct clk devname##_##_name = {                             \
 
 static DEFINE_SPINLOCK(pm_lock);
 
-unsigned long at32ap7000_osc_rates[3] = {
-       [0] = 32768,
-       /* FIXME: these are ATSTK1002-specific */
-       [1] = 20000000,
-       [2] = 12000000,
-};
-
 static struct clk osc0;
 static struct clk osc1;
 
 static unsigned long osc_get_rate(struct clk *clk)
 {
-       return at32ap7000_osc_rates[clk->index];
+       return at32_board_osc_rates[clk->index];
 }
 
 static unsigned long pll_get_rate(struct clk *clk, unsigned long control)
@@ -599,6 +595,17 @@ static void __init genclk_init_parent(struct clk *clk)
        clk->parent = parent;
 }
 
+static struct dw_dma_platform_data dw_dmac0_data = {
+       .nr_channels    = 3,
+};
+
+static struct resource dw_dmac0_resource[] = {
+       PBMEM(0xff200000),
+       IRQ(2),
+};
+DEFINE_DEV_DATA(dw_dmac, 0);
+DEV_CLK(hclk, dw_dmac0, hsb, 10);
+
 /* --------------------------------------------------------------------
  *  System peripherals
  * -------------------------------------------------------------------- */
@@ -682,6 +689,14 @@ static struct clk hramc_clk = {
        .users          = 1,
        .index          = 3,
 };
+static struct clk sdramc_clk = {
+       .name           = "sdramc_clk",
+       .parent         = &pbb_clk,
+       .mode           = pbb_clk_mode,
+       .get_rate       = pbb_clk_get_rate,
+       .users          = 1,
+       .index          = 14,
+};
 
 static struct resource smc0_resource[] = {
        PBMEM(0xfff03400),
@@ -705,17 +720,6 @@ static struct clk pico_clk = {
        .users          = 1,
 };
 
-static struct resource dmaca0_resource[] = {
-       {
-               .start  = 0xff200000,
-               .end    = 0xff20ffff,
-               .flags  = IORESOURCE_MEM,
-       },
-       IRQ(2),
-};
-DEFINE_DEV(dmaca, 0);
-DEV_CLK(hclk, dmaca0, hsb, 10);
-
 /* --------------------------------------------------------------------
  * HMATRIX
  * -------------------------------------------------------------------- */
@@ -828,7 +832,7 @@ void __init at32_add_system_devices(void)
        platform_device_register(&at32_eic0_device);
        platform_device_register(&smc0_device);
        platform_device_register(&pdc_device);
-       platform_device_register(&dmaca0_device);
+       platform_device_register(&dw_dmac0_device);
 
        platform_device_register(&at32_tcb0_device);
        platform_device_register(&at32_tcb1_device);
@@ -840,6 +844,81 @@ void __init at32_add_system_devices(void)
        platform_device_register(&pio4_device);
 }
 
+/* --------------------------------------------------------------------
+ *  PSIF
+ * -------------------------------------------------------------------- */
+static struct resource atmel_psif0_resource[] __initdata = {
+       {
+               .start  = 0xffe03c00,
+               .end    = 0xffe03cff,
+               .flags  = IORESOURCE_MEM,
+       },
+       IRQ(18),
+};
+static struct clk atmel_psif0_pclk = {
+       .name           = "pclk",
+       .parent         = &pba_clk,
+       .mode           = pba_clk_mode,
+       .get_rate       = pba_clk_get_rate,
+       .index          = 15,
+};
+
+static struct resource atmel_psif1_resource[] __initdata = {
+       {
+               .start  = 0xffe03d00,
+               .end    = 0xffe03dff,
+               .flags  = IORESOURCE_MEM,
+       },
+       IRQ(18),
+};
+static struct clk atmel_psif1_pclk = {
+       .name           = "pclk",
+       .parent         = &pba_clk,
+       .mode           = pba_clk_mode,
+       .get_rate       = pba_clk_get_rate,
+       .index          = 15,
+};
+
+struct platform_device *__init at32_add_device_psif(unsigned int id)
+{
+       struct platform_device *pdev;
+
+       if (!(id == 0 || id == 1))
+               return NULL;
+
+       pdev = platform_device_alloc("atmel_psif", id);
+       if (!pdev)
+               return NULL;
+
+       switch (id) {
+       case 0:
+               if (platform_device_add_resources(pdev, atmel_psif0_resource,
+                                       ARRAY_SIZE(atmel_psif0_resource)))
+                       goto err_add_resources;
+               atmel_psif0_pclk.dev = &pdev->dev;
+               select_peripheral(PA(8), PERIPH_A, 0); /* CLOCK */
+               select_peripheral(PA(9), PERIPH_A, 0); /* DATA  */
+               break;
+       case 1:
+               if (platform_device_add_resources(pdev, atmel_psif1_resource,
+                                       ARRAY_SIZE(atmel_psif1_resource)))
+                       goto err_add_resources;
+               atmel_psif1_pclk.dev = &pdev->dev;
+               select_peripheral(PB(11), PERIPH_A, 0); /* CLOCK */
+               select_peripheral(PB(12), PERIPH_A, 0); /* DATA  */
+               break;
+       default:
+               return NULL;
+       }
+
+       platform_device_add(pdev);
+       return pdev;
+
+err_add_resources:
+       platform_device_put(pdev);
+       return NULL;
+}
+
 /* --------------------------------------------------------------------
  *  USART
  * -------------------------------------------------------------------- */
@@ -1113,7 +1192,8 @@ at32_add_device_spi(unsigned int id, struct spi_board_info *b, unsigned int n)
        switch (id) {
        case 0:
                pdev = &atmel_spi0_device;
-               select_peripheral(PA(0),  PERIPH_A, 0); /* MISO  */
+               /* pullup MISO so a level is always defined */
+               select_peripheral(PA(0),  PERIPH_A, AT32_GPIOF_PULLUP);
                select_peripheral(PA(1),  PERIPH_A, 0); /* MOSI  */
                select_peripheral(PA(2),  PERIPH_A, 0); /* SCK   */
                at32_spi_setup_slaves(0, b, n, spi0_pins);
@@ -1121,7 +1201,8 @@ at32_add_device_spi(unsigned int id, struct spi_board_info *b, unsigned int n)
 
        case 1:
                pdev = &atmel_spi1_device;
-               select_peripheral(PB(0),  PERIPH_B, 0); /* MISO  */
+               /* pullup MISO so a level is always defined */
+               select_peripheral(PB(0),  PERIPH_B, AT32_GPIOF_PULLUP);
                select_peripheral(PB(1),  PERIPH_B, 0); /* MOSI  */
                select_peripheral(PB(5),  PERIPH_B, 0); /* SCK   */
                at32_spi_setup_slaves(1, b, n, spi1_pins);
@@ -1199,20 +1280,32 @@ static struct clk atmel_mci0_pclk = {
        .index          = 9,
 };
 
-struct platform_device *__init at32_add_device_mci(unsigned int id)
+struct platform_device *__init
+at32_add_device_mci(unsigned int id, struct mci_platform_data *data)
 {
-       struct platform_device *pdev;
+       struct mci_platform_data        _data;
+       struct platform_device          *pdev;
+       struct dw_dma_slave             *dws;
 
        if (id != 0)
                return NULL;
 
        pdev = platform_device_alloc("atmel_mci", id);
        if (!pdev)
-               return NULL;
+               goto fail;
 
        if (platform_device_add_resources(pdev, atmel_mci0_resource,
                                ARRAY_SIZE(atmel_mci0_resource)))
-               goto err_add_resources;
+               goto fail;
+
+       if (!data) {
+               data = &_data;
+               memset(data, 0, sizeof(struct mci_platform_data));
+       }
+
+       if (platform_device_add_data(pdev, data,
+                               sizeof(struct mci_platform_data)))
+               goto fail;
 
        select_peripheral(PA(10), PERIPH_A, 0); /* CLK   */
        select_peripheral(PA(11), PERIPH_A, 0); /* CMD   */
@@ -1221,12 +1314,19 @@ struct platform_device *__init at32_add_device_mci(unsigned int id)
        select_peripheral(PA(14), PERIPH_A, 0); /* DATA2 */
        select_peripheral(PA(15), PERIPH_A, 0); /* DATA3 */
 
+       if (data) {
+               if (data->detect_pin != GPIO_PIN_NONE)
+                       at32_select_gpio(data->detect_pin, 0);
+               if (data->wp_pin != GPIO_PIN_NONE)
+                       at32_select_gpio(data->wp_pin, 0);
+       }
+
        atmel_mci0_pclk.dev = &pdev->dev;
 
        platform_device_add(pdev);
        return pdev;
 
-err_add_resources:
+fail:
        platform_device_put(pdev);
        return NULL;
 }
@@ -1264,7 +1364,8 @@ static struct clk atmel_lcdfb0_pixclk = {
 
 struct platform_device *__init
 at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data,
-                    unsigned long fbmem_start, unsigned long fbmem_len)
+                    unsigned long fbmem_start, unsigned long fbmem_len,
+                    unsigned int pin_config)
 {
        struct platform_device *pdev;
        struct atmel_lcdfb_info *info;
@@ -1291,37 +1392,77 @@ at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data,
        switch (id) {
        case 0:
                pdev = &atmel_lcdfb0_device;
-               select_peripheral(PC(19), PERIPH_A, 0); /* CC     */
-               select_peripheral(PC(20), PERIPH_A, 0); /* HSYNC  */
-               select_peripheral(PC(21), PERIPH_A, 0); /* PCLK   */
-               select_peripheral(PC(22), PERIPH_A, 0); /* VSYNC  */
-               select_peripheral(PC(23), PERIPH_A, 0); /* DVAL   */
-               select_peripheral(PC(24), PERIPH_A, 0); /* MODE   */
-               select_peripheral(PC(25), PERIPH_A, 0); /* PWR    */
-               select_peripheral(PC(26), PERIPH_A, 0); /* DATA0  */
-               select_peripheral(PC(27), PERIPH_A, 0); /* DATA1  */
-               select_peripheral(PC(28), PERIPH_A, 0); /* DATA2  */
-               select_peripheral(PC(29), PERIPH_A, 0); /* DATA3  */
-               select_peripheral(PC(30), PERIPH_A, 0); /* DATA4  */
-               select_peripheral(PC(31), PERIPH_A, 0); /* DATA5  */
-               select_peripheral(PD(0),  PERIPH_A, 0); /* DATA6  */
-               select_peripheral(PD(1),  PERIPH_A, 0); /* DATA7  */
-               select_peripheral(PD(2),  PERIPH_A, 0); /* DATA8  */
-               select_peripheral(PD(3),  PERIPH_A, 0); /* DATA9  */
-               select_peripheral(PD(4),  PERIPH_A, 0); /* DATA10 */
-               select_peripheral(PD(5),  PERIPH_A, 0); /* DATA11 */
-               select_peripheral(PD(6),  PERIPH_A, 0); /* DATA12 */
-               select_peripheral(PD(7),  PERIPH_A, 0); /* DATA13 */
-               select_peripheral(PD(8),  PERIPH_A, 0); /* DATA14 */
-               select_peripheral(PD(9),  PERIPH_A, 0); /* DATA15 */
-               select_peripheral(PD(10), PERIPH_A, 0); /* DATA16 */
-               select_peripheral(PD(11), PERIPH_A, 0); /* DATA17 */
-               select_peripheral(PD(12), PERIPH_A, 0); /* DATA18 */
-               select_peripheral(PD(13), PERIPH_A, 0); /* DATA19 */
-               select_peripheral(PD(14), PERIPH_A, 0); /* DATA20 */
-               select_peripheral(PD(15), PERIPH_A, 0); /* DATA21 */
-               select_peripheral(PD(16), PERIPH_A, 0); /* DATA22 */
-               select_peripheral(PD(17), PERIPH_A, 0); /* DATA23 */
+
+               switch (pin_config) {
+               case 0:
+                       select_peripheral(PC(19), PERIPH_A, 0); /* CC     */
+                       select_peripheral(PC(20), PERIPH_A, 0); /* HSYNC  */
+                       select_peripheral(PC(21), PERIPH_A, 0); /* PCLK   */
+                       select_peripheral(PC(22), PERIPH_A, 0); /* VSYNC  */
+                       select_peripheral(PC(23), PERIPH_A, 0); /* DVAL   */
+                       select_peripheral(PC(24), PERIPH_A, 0); /* MODE   */
+                       select_peripheral(PC(25), PERIPH_A, 0); /* PWR    */
+                       select_peripheral(PC(26), PERIPH_A, 0); /* DATA0  */
+                       select_peripheral(PC(27), PERIPH_A, 0); /* DATA1  */
+                       select_peripheral(PC(28), PERIPH_A, 0); /* DATA2  */
+                       select_peripheral(PC(29), PERIPH_A, 0); /* DATA3  */
+                       select_peripheral(PC(30), PERIPH_A, 0); /* DATA4  */
+                       select_peripheral(PC(31), PERIPH_A, 0); /* DATA5  */
+                       select_peripheral(PD(0),  PERIPH_A, 0); /* DATA6  */
+                       select_peripheral(PD(1),  PERIPH_A, 0); /* DATA7  */
+                       select_peripheral(PD(2),  PERIPH_A, 0); /* DATA8  */
+                       select_peripheral(PD(3),  PERIPH_A, 0); /* DATA9  */
+                       select_peripheral(PD(4),  PERIPH_A, 0); /* DATA10 */
+                       select_peripheral(PD(5),  PERIPH_A, 0); /* DATA11 */
+                       select_peripheral(PD(6),  PERIPH_A, 0); /* DATA12 */
+                       select_peripheral(PD(7),  PERIPH_A, 0); /* DATA13 */
+                       select_peripheral(PD(8),  PERIPH_A, 0); /* DATA14 */
+                       select_peripheral(PD(9),  PERIPH_A, 0); /* DATA15 */
+                       select_peripheral(PD(10), PERIPH_A, 0); /* DATA16 */
+                       select_peripheral(PD(11), PERIPH_A, 0); /* DATA17 */
+                       select_peripheral(PD(12), PERIPH_A, 0); /* DATA18 */
+                       select_peripheral(PD(13), PERIPH_A, 0); /* DATA19 */
+                       select_peripheral(PD(14), PERIPH_A, 0); /* DATA20 */
+                       select_peripheral(PD(15), PERIPH_A, 0); /* DATA21 */
+                       select_peripheral(PD(16), PERIPH_A, 0); /* DATA22 */
+                       select_peripheral(PD(17), PERIPH_A, 0); /* DATA23 */
+                       break;
+               case 1:
+                       select_peripheral(PE(0),  PERIPH_B, 0); /* CC     */
+                       select_peripheral(PC(20), PERIPH_A, 0); /* HSYNC  */
+                       select_peripheral(PC(21), PERIPH_A, 0); /* PCLK   */
+                       select_peripheral(PC(22), PERIPH_A, 0); /* VSYNC  */
+                       select_peripheral(PE(1),  PERIPH_B, 0); /* DVAL   */
+                       select_peripheral(PE(2),  PERIPH_B, 0); /* MODE   */
+                       select_peripheral(PC(25), PERIPH_A, 0); /* PWR    */
+                       select_peripheral(PE(3),  PERIPH_B, 0); /* DATA0  */
+                       select_peripheral(PE(4),  PERIPH_B, 0); /* DATA1  */
+                       select_peripheral(PE(5),  PERIPH_B, 0); /* DATA2  */
+                       select_peripheral(PE(6),  PERIPH_B, 0); /* DATA3  */
+                       select_peripheral(PE(7),  PERIPH_B, 0); /* DATA4  */
+                       select_peripheral(PC(31), PERIPH_A, 0); /* DATA5  */
+                       select_peripheral(PD(0),  PERIPH_A, 0); /* DATA6  */
+                       select_peripheral(PD(1),  PERIPH_A, 0); /* DATA7  */
+                       select_peripheral(PE(8),  PERIPH_B, 0); /* DATA8  */
+                       select_peripheral(PE(9),  PERIPH_B, 0); /* DATA9  */
+                       select_peripheral(PE(10), PERIPH_B, 0); /* DATA10 */
+                       select_peripheral(PE(11), PERIPH_B, 0); /* DATA11 */
+                       select_peripheral(PE(12), PERIPH_B, 0); /* DATA12 */
+                       select_peripheral(PD(7),  PERIPH_A, 0); /* DATA13 */
+                       select_peripheral(PD(8),  PERIPH_A, 0); /* DATA14 */
+                       select_peripheral(PD(9),  PERIPH_A, 0); /* DATA15 */
+                       select_peripheral(PE(13), PERIPH_B, 0); /* DATA16 */
+                       select_peripheral(PE(14), PERIPH_B, 0); /* DATA17 */
+                       select_peripheral(PE(15), PERIPH_B, 0); /* DATA18 */
+                       select_peripheral(PE(16), PERIPH_B, 0); /* DATA19 */
+                       select_peripheral(PE(17), PERIPH_B, 0); /* DATA20 */
+                       select_peripheral(PE(18), PERIPH_B, 0); /* DATA21 */
+                       select_peripheral(PD(16), PERIPH_A, 0); /* DATA22 */
+                       select_peripheral(PD(17), PERIPH_A, 0); /* DATA23 */
+                       break;
+               default:
+                       goto err_invalid_id;
+               }
 
                clk_set_parent(&atmel_lcdfb0_pixclk, &pll0);
                clk_set_rate(&atmel_lcdfb0_pixclk, clk_get_rate(&pll0));
@@ -1360,7 +1501,7 @@ static struct resource atmel_pwm0_resource[] __initdata = {
        IRQ(24),
 };
 static struct clk atmel_pwm0_mck = {
-       .name           = "mck",
+       .name           = "pwm_clk",
        .parent         = &pbb_clk,
        .mode           = pbb_clk_mode,
        .get_rate       = pbb_clk_get_rate,
@@ -1939,11 +2080,12 @@ struct clk *at32_clock_list[] = {
        &hmatrix_clk,
        &ebi_clk,
        &hramc_clk,
+       &sdramc_clk,
        &smc0_pclk,
        &smc0_mck,
        &pdc_hclk,
        &pdc_pclk,
-       &dmaca0_hclk,
+       &dw_dmac0_hclk,
        &pico_clk,
        &pio0_mck,
        &pio1_mck,
@@ -1952,6 +2094,8 @@ struct clk *at32_clock_list[] = {
        &pio4_mck,
        &at32_tcb0_t0_clk,
        &at32_tcb1_t0_clk,
+       &atmel_psif0_pclk,
+       &atmel_psif1_pclk,
        &atmel_usart0_usart,
        &atmel_usart1_usart,
        &atmel_usart2_usart,
@@ -1987,16 +2131,7 @@ struct clk *at32_clock_list[] = {
 };
 unsigned int at32_nr_clocks = ARRAY_SIZE(at32_clock_list);
 
-void __init at32_portmux_init(void)
-{
-       at32_init_pio(&pio0_device);
-       at32_init_pio(&pio1_device);
-       at32_init_pio(&pio2_device);
-       at32_init_pio(&pio3_device);
-       at32_init_pio(&pio4_device);
-}
-
-void __init at32_clock_init(void)
+void __init setup_platform(void)
 {
        u32 cpu_mask = 0, hsb_mask = 0, pba_mask = 0, pbb_mask = 0;
        int i;
@@ -2051,4 +2186,36 @@ void __init at32_clock_init(void)
        pm_writel(HSB_MASK, hsb_mask);
        pm_writel(PBA_MASK, pba_mask);
        pm_writel(PBB_MASK, pbb_mask);
+
+       /* Initialize the port muxes */
+       at32_init_pio(&pio0_device);
+       at32_init_pio(&pio1_device);
+       at32_init_pio(&pio2_device);
+       at32_init_pio(&pio3_device);
+       at32_init_pio(&pio4_device);
+}
+
+struct gen_pool *sram_pool;
+
+static int __init sram_init(void)
+{
+       struct gen_pool *pool;
+
+       /* 1KiB granularity */
+       pool = gen_pool_create(10, -1);
+       if (!pool)
+               goto fail;
+
+       if (gen_pool_add(pool, 0x24000000, 0x8000, -1))
+               goto err_pool_add;
+
+       sram_pool = pool;
+       return 0;
+
+err_pool_add:
+       gen_pool_destroy(pool);
+fail:
+       pr_err("Failed to create SRAM pool\n");
+       return -ENOMEM;
 }
+core_initcall(sram_init);