]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - arch/arm/mach-shmobile/board-ap4evb.c
ARM: add DMA support to sh7372, enable DMA for SDHI
[mv-sheeva.git] / arch / arm / mach-shmobile / board-ap4evb.c
index 1c2ec96ce2610c88a9292b7edcf6adc1f390b808..5c41b958e022f618dec2b14cef08f70037f988ae 100644 (file)
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
+#include <linux/clk.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
+#include <linux/mfd/sh_mobile_sdhi.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
+#include <linux/i2c.h>
+#include <linux/i2c/tsc2007.h>
 #include <linux/io.h>
 #include <linux/smsc911x.h>
 #include <linux/gpio.h>
 #include <linux/input.h>
 #include <linux/input/sh_keysc.h>
+#include <linux/usb/r8a66597.h>
+
+#include <video/sh_mobile_lcdc.h>
+#include <video/sh_mipi_dsi.h>
+
 #include <mach/common.h>
+#include <mach/irqs.h>
 #include <mach/sh7372.h>
+
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
+#include <asm/mach/time.h>
 
 /*
  * Address     Interface               BusWidth        note
  */
 
 /*
- * KEYSC
+ * LCD / IRQ / KEYSC / IrDA
  *
- * SW43                KEYSC
- * -------------------------
- * ON          enable
- * OFF         disable
+ * IRQ = IRQ26 (TS), IRQ27 (VIO), IRQ28 (TouchScreen)
+ * LCD = 2nd LCDC
+ *
+ *             |               SW43                    |
+ * SW3         |       ON              |       OFF     |
+ * -------------+-----------------------+---------------+
+ * ON          | KEY / IrDA            | LCD           |
+ * OFF         | KEY / IrDA / IRQ      | IRQ           |
+ */
+
+/*
+ * USB
+ *
+ * J7 : 1-2  MAX3355E VBUS
+ *      2-3  DC 5.0V
+ *
+ * S39: bit2: off
  */
 
 /* MTD */
@@ -148,7 +173,7 @@ static struct resource smc911x_resources[] = {
                .end    = 0x16000000 - 1,
                .flags  = IORESOURCE_MEM,
        }, {
-               .start  = 6,
+               .start  = evt2irq(0x02c0) /* IRQ6A */,
                .flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
        },
 };
@@ -191,7 +216,7 @@ static struct resource keysc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = 79,
+               .start  = evt2irq(0x0be0), /* KEYSC_KEY */
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -207,6 +232,11 @@ static struct platform_device keysc_device = {
 };
 
 /* SDHI0 */
+static struct sh_mobile_sdhi_info sdhi0_info = {
+       .dma_slave_tx = SHDMA_SLAVE_SDHI0_TX,
+       .dma_slave_rx = SHDMA_SLAVE_SDHI0_RX,
+};
+
 static struct resource sdhi0_resources[] = {
        [0] = {
                .name   = "SDHI0",
@@ -215,7 +245,7 @@ static struct resource sdhi0_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = 96,
+               .start  = evt2irq(0x0e00) /* SDHI0 */,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -225,6 +255,122 @@ static struct platform_device sdhi0_device = {
        .num_resources  = ARRAY_SIZE(sdhi0_resources),
        .resource       = sdhi0_resources,
        .id             = 0,
+       .dev    = {
+               .platform_data  = &sdhi0_info,
+       },
+};
+
+/* USB1 */
+void usb1_host_port_power(int port, int power)
+{
+       if (!power) /* only power-on supported for now */
+               return;
+
+       /* set VBOUT/PWEN and EXTLP1 in DVSTCTR */
+       __raw_writew(__raw_readw(0xE68B0008) | 0x600, 0xE68B0008);
+}
+
+static struct r8a66597_platdata usb1_host_data = {
+       .on_chip        = 1,
+       .port_power     = usb1_host_port_power,
+};
+
+static struct resource usb1_host_resources[] = {
+       [0] = {
+               .name   = "USBHS",
+               .start  = 0xE68B0000,
+               .end    = 0xE68B00E6 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = evt2irq(0x1ce0) /* USB1_USB1I0 */,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device usb1_host_device = {
+       .name   = "r8a66597_hcd",
+       .id     = 1,
+       .dev = {
+               .dma_mask               = NULL,         /*  not use dma */
+               .coherent_dma_mask      = 0xffffffff,
+               .platform_data          = &usb1_host_data,
+       },
+       .num_resources  = ARRAY_SIZE(usb1_host_resources),
+       .resource       = usb1_host_resources,
+};
+
+static struct sh_mobile_lcdc_info sh_mobile_lcdc_info = {
+       .clock_source = LCDC_CLK_PERIPHERAL, /* One of interface clocks */
+       .ch[0] = {
+               .chan = LCDC_CHAN_MAINLCD,
+               .bpp = 16,
+               .interface_type = RGB24,
+               .clock_divider = 1,
+               .flags = LCDC_FLAGS_DWPOL,
+               .lcd_cfg = {
+                       .name = "R63302(QHD)",
+                       .xres = 544,
+                       .yres = 961,
+                       .left_margin = 72,
+                       .right_margin = 600,
+                       .hsync_len = 16,
+                       .upper_margin = 8,
+                       .lower_margin = 8,
+                       .vsync_len = 2,
+                       .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
+               },
+               .lcd_size_cfg = {
+                       .width = 44,
+                       .height = 79,
+               },
+       }
+};
+
+static struct resource lcdc_resources[] = {
+       [0] = {
+               .name   = "LCDC",
+               .start  = 0xfe940000, /* P4-only space */
+               .end    = 0xfe943fff,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = intcs_evt2irq(0x580),
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device lcdc_device = {
+       .name           = "sh_mobile_lcdc_fb",
+       .num_resources  = ARRAY_SIZE(lcdc_resources),
+       .resource       = lcdc_resources,
+       .dev    = {
+               .platform_data  = &sh_mobile_lcdc_info,
+               .coherent_dma_mask = ~0,
+       },
+};
+
+static struct resource mipidsi0_resources[] = {
+       [0] = {
+               .start  = 0xffc60000,
+               .end    = 0xffc68fff,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct sh_mipi_dsi_info mipidsi0_info = {
+       .data_format    = MIPI_RGB888,
+       .lcd_chan       = &sh_mobile_lcdc_info.ch[0],
+};
+
+static struct platform_device mipidsi0_device = {
+       .name           = "sh-mipi-dsi",
+       .num_resources  = ARRAY_SIZE(mipidsi0_resources),
+       .resource       = mipidsi0_resources,
+       .id             = 0,
+       .dev    = {
+               .platform_data  = &mipidsi0_info,
+       },
 };
 
 static struct platform_device *ap4evb_devices[] __initdata = {
@@ -232,6 +378,29 @@ static struct platform_device *ap4evb_devices[] __initdata = {
        &smc911x_device,
        &keysc_device,
        &sdhi0_device,
+       &usb1_host_device,
+       &lcdc_device,
+       &mipidsi0_device,
+};
+
+/* TouchScreen (Needs SW3 set to OFF) */
+#define IRQ28  evt2irq(0x3380) /* IRQ28A */
+struct tsc2007_platform_data tsc2007_info = {
+       .model                  = 2007,
+       .x_plate_ohms           = 180,
+};
+
+/* I2C */
+static struct i2c_board_info i2c1_devices[] = {
+       {
+               I2C_BOARD_INFO("r2025sd", 0x32),
+       },
+       {
+               I2C_BOARD_INFO("tsc2007", 0x48),
+               .type           = "tsc2007",
+               .platform_data  = &tsc2007_info,
+               .irq            = IRQ28,
+       },
 };
 
 static struct map_desc ap4evb_io_desc[] __initdata = {
@@ -250,12 +419,50 @@ static void __init ap4evb_map_io(void)
 {
        iotable_init(ap4evb_io_desc, ARRAY_SIZE(ap4evb_io_desc));
 
-       /* setup early devices, clocks and console here as well */
+       /* setup early devices and console here as well */
        sh7372_add_early_devices();
-       sh7367_clock_init(); /* use g3 clocks for now */
        shmobile_setup_console();
 }
 
+/* This function will disappear when we switch to (runtime) PM */
+static int __init ap4evb_init_display_clk(void)
+{
+       struct clk *lcdc_clk;
+       struct clk *dsitx_clk;
+       int ret;
+
+       lcdc_clk = clk_get(&lcdc_device.dev, "sh_mobile_lcdc_fb.0");
+       if (IS_ERR(lcdc_clk))
+               return PTR_ERR(lcdc_clk);
+
+       dsitx_clk = clk_get(&mipidsi0_device.dev, "sh-mipi-dsi.0");
+       if (IS_ERR(dsitx_clk)) {
+               ret = PTR_ERR(dsitx_clk);
+               goto eclkdsitxget;
+       }
+
+       ret = clk_enable(lcdc_clk);
+       if (ret < 0)
+               goto eclklcdcon;
+
+       ret = clk_enable(dsitx_clk);
+       if (ret < 0)
+               goto eclkdsitxon;
+
+       return 0;
+
+eclkdsitxon:
+       clk_disable(lcdc_clk);
+eclklcdcon:
+       clk_put(dsitx_clk);
+eclkdsitxget:
+       clk_put(lcdc_clk);
+
+       return ret;
+}
+
+device_initcall(ap4evb_init_display_clk);
+
 static void __init ap4evb_init(void)
 {
        sh7372_pinmux_init();
@@ -318,16 +525,44 @@ static void __init ap4evb_init(void)
        gpio_request(GPIO_FN_SDHID0_1, NULL);
        gpio_request(GPIO_FN_SDHID0_0, NULL);
 
+       /* enable TouchScreen */
+       gpio_request(GPIO_FN_IRQ28_123, NULL);
+       set_irq_type(IRQ28, IRQ_TYPE_LEVEL_LOW);
+
+       i2c_register_board_info(1, i2c1_devices,
+                               ARRAY_SIZE(i2c1_devices));
+
+       /* USB enable */
+       gpio_request(GPIO_FN_VBUS0_1,    NULL);
+       gpio_request(GPIO_FN_IDIN_1_18,  NULL);
+       gpio_request(GPIO_FN_PWEN_1_115, NULL);
+       gpio_request(GPIO_FN_OVCN_1_114, NULL);
+       gpio_request(GPIO_FN_EXTLP_1,    NULL);
+       gpio_request(GPIO_FN_OVCN2_1,    NULL);
+
+       /* setup USB phy */
+       __raw_writew(0x8a0a, 0xE6058130);       /* USBCR2 */
+
        sh7372_add_standard_devices();
 
        platform_add_devices(ap4evb_devices, ARRAY_SIZE(ap4evb_devices));
 }
 
+static void __init ap4evb_timer_init(void)
+{
+       sh7372_clock_init();
+       shmobile_timer.init();
+}
+
+static struct sys_timer ap4evb_timer = {
+       .init           = ap4evb_timer_init,
+};
+
 MACHINE_START(AP4EVB, "ap4evb")
        .phys_io        = 0xe6000000,
        .io_pg_offst    = ((0xe6000000) >> 18) & 0xfffc,
        .map_io         = ap4evb_map_io,
        .init_irq       = sh7372_init_irq,
        .init_machine   = ap4evb_init,
-       .timer          = &shmobile_timer,
+       .timer          = &ap4evb_timer,
 MACHINE_END