ARM: shmobile: r8a7779: add HPB-DMAC support
[firefly-linux-kernel-4.4.55.git] / arch / arm / mach-shmobile / setup-r8a7779.c
index 41bab625341e0318392c3bc778b662f2014a31ee..eacb2f783693e079e74caffbbb3fc091810b2a5b 100644 (file)
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/arm-gic.h>
 #include <linux/of_platform.h>
+#include <linux/platform_data/dma-rcar-hpbdma.h>
 #include <linux/platform_data/gpio-rcar.h>
+#include <linux/platform_data/irq-renesas-intc-irqpin.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/input.h>
 #include <linux/io.h>
 #include <linux/serial_sci.h>
-#include <linux/sh_intc.h>
 #include <linux/sh_timer.h>
 #include <linux/dma-mapping.h>
 #include <linux/usb/otg.h>
@@ -37,7 +40,6 @@
 #include <linux/usb/ehci_pdriver.h>
 #include <linux/usb/ohci_pdriver.h>
 #include <linux/pm_runtime.h>
-#include <mach/hardware.h>
 #include <mach/irqs.h>
 #include <mach/r8a7779.h>
 #include <mach/common.h>
@@ -69,6 +71,60 @@ void __init r8a7779_map_io(void)
        iotable_init(r8a7779_io_desc, ARRAY_SIZE(r8a7779_io_desc));
 }
 
+/* IRQ */
+#define INT2SMSKCR0 IOMEM(0xfe7822a0)
+#define INT2SMSKCR1 IOMEM(0xfe7822a4)
+#define INT2SMSKCR2 IOMEM(0xfe7822a8)
+#define INT2SMSKCR3 IOMEM(0xfe7822ac)
+#define INT2SMSKCR4 IOMEM(0xfe7822b0)
+
+#define INT2NTSR0 IOMEM(0xfe700060)
+#define INT2NTSR1 IOMEM(0xfe700064)
+
+static struct renesas_intc_irqpin_config irqpin0_platform_data __initdata = {
+       .irq_base = irq_pin(0), /* IRQ0 -> IRQ3 */
+       .sense_bitfield_width = 2,
+};
+
+static struct resource irqpin0_resources[] __initdata = {
+       DEFINE_RES_MEM(0xfe78001c, 4), /* ICR1 */
+       DEFINE_RES_MEM(0xfe780010, 4), /* INTPRI */
+       DEFINE_RES_MEM(0xfe780024, 4), /* INTREQ */
+       DEFINE_RES_MEM(0xfe780044, 4), /* INTMSK0 */
+       DEFINE_RES_MEM(0xfe780064, 4), /* INTMSKCLR0 */
+       DEFINE_RES_IRQ(gic_spi(27)), /* IRQ0 */
+       DEFINE_RES_IRQ(gic_spi(28)), /* IRQ1 */
+       DEFINE_RES_IRQ(gic_spi(29)), /* IRQ2 */
+       DEFINE_RES_IRQ(gic_spi(30)), /* IRQ3 */
+};
+
+void __init r8a7779_init_irq_extpin(int irlm)
+{
+       void __iomem *icr0 = ioremap_nocache(0xfe780000, PAGE_SIZE);
+       u32 tmp;
+
+       if (!icr0) {
+               pr_warn("r8a7779: unable to setup external irq pin mode\n");
+               return;
+       }
+
+       tmp = ioread32(icr0);
+       if (irlm)
+               tmp |= 1 << 23; /* IRQ0 -> IRQ3 as individual pins */
+       else
+               tmp &= ~(1 << 23); /* IRL mode - not supported */
+       tmp |= (1 << 21); /* LVLMODE = 1 */
+       iowrite32(tmp, icr0);
+       iounmap(icr0);
+
+       if (irlm)
+               platform_device_register_resndata(
+                       &platform_bus, "renesas_intc_irqpin", -1,
+                       irqpin0_resources, ARRAY_SIZE(irqpin0_resources),
+                       &irqpin0_platform_data, sizeof(irqpin0_platform_data));
+}
+
+/* PFC/GPIO */
 static struct resource r8a7779_pfc_resources[] = {
        DEFINE_RES_MEM(0xfffc0000, 0x023c),
 };
@@ -388,15 +444,6 @@ static struct platform_device sata_device = {
        },
 };
 
-/* USB PHY */
-static struct resource usb_phy_resources[] __initdata = {
-       [0] = {
-               .start          = 0xffe70800,
-               .end            = 0xffe70900 - 1,
-               .flags          = IORESOURCE_MEM,
-       },
-};
-
 /* USB */
 static struct usb_phy *phy;
 
@@ -548,7 +595,7 @@ static struct platform_device ohci1_device = {
 };
 
 /* Ether */
-static struct resource ether_resources[] = {
+static struct resource ether_resources[] __initdata = {
        {
                .start  = 0xfde00000,
                .end    = 0xfde003ff,
@@ -586,6 +633,158 @@ static struct platform_device_info *vin_info_table[] __initdata = {
        &vin3_info,
 };
 
+/* HPB-DMA */
+
+/* Asynchronous mode register bits */
+#define HPB_DMAE_ASYNCMDR_ASMD43_MASK          BIT(23) /* MMC1 */
+#define HPB_DMAE_ASYNCMDR_ASMD43_SINGLE                BIT(23) /* MMC1 */
+#define HPB_DMAE_ASYNCMDR_ASMD43_MULTI         0       /* MMC1 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD43_MASK                BIT(22) /* MMC1 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD43_BURST       BIT(22) /* MMC1 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD43_NBURST      0       /* MMC1 */
+#define HPB_DMAE_ASYNCMDR_ASMD24_MASK          BIT(21) /* MMC0 */
+#define HPB_DMAE_ASYNCMDR_ASMD24_SINGLE                BIT(21) /* MMC0 */
+#define HPB_DMAE_ASYNCMDR_ASMD24_MULTI         0       /* MMC0 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD24_MASK                BIT(20) /* MMC0 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD24_BURST       BIT(20) /* MMC0 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD24_NBURST      0       /* MMC0 */
+#define HPB_DMAE_ASYNCMDR_ASMD41_MASK          BIT(19) /* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASMD41_SINGLE                BIT(19) /* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASMD41_MULTI         0       /* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD41_MASK                BIT(18) /* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD41_BURST       BIT(18) /* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD41_NBURST      0       /* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASMD40_MASK          BIT(17) /* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASMD40_SINGLE                BIT(17) /* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASMD40_MULTI         0       /* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD40_MASK                BIT(16) /* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD40_BURST       BIT(16) /* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD40_NBURST      0       /* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASMD39_MASK          BIT(15) /* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASMD39_SINGLE                BIT(15) /* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASMD39_MULTI         0       /* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD39_MASK                BIT(14) /* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD39_BURST       BIT(14) /* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD39_NBURST      0       /* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASMD27_MASK          BIT(13) /* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASMD27_SINGLE                BIT(13) /* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASMD27_MULTI         0       /* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD27_MASK                BIT(12) /* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD27_BURST       BIT(12) /* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD27_NBURST      0       /* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASMD26_MASK          BIT(11) /* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASMD26_SINGLE                BIT(11) /* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASMD26_MULTI         0       /* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD26_MASK                BIT(10) /* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD26_BURST       BIT(10) /* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD26_NBURST      0       /* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASMD25_MASK          BIT(9)  /* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASMD25_SINGLE                BIT(9)  /* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASMD25_MULTI         0       /* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD25_MASK                BIT(8)  /* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD25_BURST       BIT(8)  /* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD25_NBURST      0       /* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASMD23_MASK          BIT(7)  /* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASMD23_SINGLE                BIT(7)  /* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASMD23_MULTI         0       /* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD23_MASK                BIT(6)  /* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD23_BURST       BIT(6)  /* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD23_NBURST      0       /* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASMD22_MASK          BIT(5)  /* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASMD22_SINGLE                BIT(5)  /* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASMD22_MULTI         0       /* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD22_MASK                BIT(4)  /* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD22_BURST       BIT(4)  /* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD22_NBURST      0       /* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASMD21_MASK          BIT(3)  /* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASMD21_SINGLE                BIT(3)  /* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASMD21_MULTI         0       /* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD21_MASK                BIT(2)  /* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD21_BURST       BIT(2)  /* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD21_NBURST      0       /* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASMD20_MASK          BIT(1)  /* SDHI1 */
+#define HPB_DMAE_ASYNCMDR_ASMD20_SINGLE                BIT(1)  /* SDHI1 */
+#define HPB_DMAE_ASYNCMDR_ASMD20_MULTI         0       /* SDHI1 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD20_MASK                BIT(0)  /* SDHI1 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD20_BURST       BIT(0)  /* SDHI1 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD20_NBURST      0       /* SDHI1 */
+
+static const struct hpb_dmae_slave_config hpb_dmae_slaves[] = {
+       {
+               .id     = HPBDMA_SLAVE_SDHI0_TX,
+               .addr   = 0xffe4c000 + 0x30,
+               .dcr    = HPB_DMAE_DCR_SPDS_16BIT |
+                         HPB_DMAE_DCR_DMDL |
+                         HPB_DMAE_DCR_DPDS_16BIT,
+               .rstr   = HPB_DMAE_ASYNCRSTR_ASRST21 |
+                         HPB_DMAE_ASYNCRSTR_ASRST22 |
+                         HPB_DMAE_ASYNCRSTR_ASRST23,
+               .mdr    = HPB_DMAE_ASYNCMDR_ASMD21_SINGLE |
+                         HPB_DMAE_ASYNCMDR_ASBTMD21_NBURST,
+               .mdm    = HPB_DMAE_ASYNCMDR_ASMD21_MASK |
+                         HPB_DMAE_ASYNCMDR_ASBTMD21_MASK,
+               .port   = 0x0D0C,
+               .flags  = HPB_DMAE_SET_ASYNC_RESET | HPB_DMAE_SET_ASYNC_MODE,
+               .dma_ch = 21,
+       }, {
+               .id     = HPBDMA_SLAVE_SDHI0_RX,
+               .addr   = 0xffe4c000 + 0x30,
+               .dcr    = HPB_DMAE_DCR_SMDL |
+                         HPB_DMAE_DCR_SPDS_16BIT |
+                         HPB_DMAE_DCR_DPDS_16BIT,
+               .rstr   = HPB_DMAE_ASYNCRSTR_ASRST21 |
+                         HPB_DMAE_ASYNCRSTR_ASRST22 |
+                         HPB_DMAE_ASYNCRSTR_ASRST23,
+               .mdr    = HPB_DMAE_ASYNCMDR_ASMD22_SINGLE |
+                         HPB_DMAE_ASYNCMDR_ASBTMD22_NBURST,
+               .mdm    = HPB_DMAE_ASYNCMDR_ASMD22_MASK |
+                         HPB_DMAE_ASYNCMDR_ASBTMD22_MASK,
+               .port   = 0x0D0C,
+               .flags  = HPB_DMAE_SET_ASYNC_RESET | HPB_DMAE_SET_ASYNC_MODE,
+               .dma_ch = 22,
+       },
+};
+
+static const struct hpb_dmae_channel hpb_dmae_channels[] = {
+       HPB_DMAE_CHANNEL(0x93, HPBDMA_SLAVE_SDHI0_TX), /* ch. 21 */
+       HPB_DMAE_CHANNEL(0x93, HPBDMA_SLAVE_SDHI0_RX), /* ch. 22 */
+};
+
+static struct hpb_dmae_pdata dma_platform_data __initdata = {
+       .slaves                 = hpb_dmae_slaves,
+       .num_slaves             = ARRAY_SIZE(hpb_dmae_slaves),
+       .channels               = hpb_dmae_channels,
+       .num_channels           = ARRAY_SIZE(hpb_dmae_channels),
+       .ts_shift               = {
+               [XMIT_SZ_8BIT]  = 0,
+               [XMIT_SZ_16BIT] = 1,
+               [XMIT_SZ_32BIT] = 2,
+       },
+       .num_hw_channels        = 44,
+};
+
+static struct resource hpb_dmae_resources[] __initdata = {
+       /* Channel registers */
+       DEFINE_RES_MEM(0xffc08000, 0x1000),
+       /* Common registers */
+       DEFINE_RES_MEM(0xffc09000, 0x170),
+       /* Asynchronous reset registers */
+       DEFINE_RES_MEM(0xffc00300, 4),
+       /* Asynchronous mode registers */
+       DEFINE_RES_MEM(0xffc00400, 4),
+       /* IRQ for DMA channels */
+       DEFINE_RES_NAMED(gic_iid(0x8e), 12, NULL, IORESOURCE_IRQ),
+};
+
+static void __init r8a7779_register_hpb_dmae(void)
+{
+       platform_device_register_resndata(&platform_bus, "hpb-dma-engine", -1,
+                                         hpb_dmae_resources,
+                                         ARRAY_SIZE(hpb_dmae_resources),
+                                         &dma_platform_data,
+                                         sizeof(dma_platform_data));
+}
+
 static struct platform_device *r8a7779_devices_dt[] __initdata = {
        &scif0_device,
        &scif1_device,
@@ -619,6 +818,7 @@ void __init r8a7779_add_standard_devices(void)
                            ARRAY_SIZE(r8a7779_devices_dt));
        platform_add_devices(r8a7779_standard_devices,
                            ARRAY_SIZE(r8a7779_standard_devices));
+       r8a7779_register_hpb_dmae();
 }
 
 void __init r8a7779_add_ether_device(struct sh_eth_plat_data *pdata)
@@ -629,14 +829,6 @@ void __init r8a7779_add_ether_device(struct sh_eth_plat_data *pdata)
                                          pdata, sizeof(*pdata));
 }
 
-void __init r8a7779_add_usb_phy_device(struct rcar_phy_platform_data *pdata)
-{
-       platform_device_register_resndata(&platform_bus, "rcar_usb_phy", -1,
-                                         usb_phy_resources,
-                                         ARRAY_SIZE(usb_phy_resources),
-                                         pdata, sizeof(*pdata));
-}
-
 void __init r8a7779_add_vin_device(int id, struct rcar_vin_platform_data *pdata)
 {
        BUG_ON(id < 0 || id > 3);
@@ -653,8 +845,8 @@ void __init __weak r8a7779_register_twd(void) { }
 void __init r8a7779_earlytimer_init(void)
 {
        r8a7779_clock_init();
-       shmobile_earlytimer_init();
        r8a7779_register_twd();
+       shmobile_earlytimer_init();
 }
 
 void __init r8a7779_add_early_devices(void)
@@ -697,6 +889,29 @@ void __init r8a7779_init_late(void)
 }
 
 #ifdef CONFIG_USE_OF
+static int r8a7779_set_wake(struct irq_data *data, unsigned int on)
+{
+       return 0; /* always allow wakeup */
+}
+
+void __init r8a7779_init_irq_dt(void)
+{
+       gic_arch_extn.irq_set_wake = r8a7779_set_wake;
+
+       irqchip_init();
+
+       /* route all interrupts to ARM */
+       __raw_writel(0xffffffff, INT2NTSR0);
+       __raw_writel(0x3fffffff, INT2NTSR1);
+
+       /* unmask all known interrupts in INTCS2 */
+       __raw_writel(0xfffffff0, INT2SMSKCR0);
+       __raw_writel(0xfff7ffff, INT2SMSKCR1);
+       __raw_writel(0xfffbffdf, INT2SMSKCR2);
+       __raw_writel(0xbffffffc, INT2SMSKCR3);
+       __raw_writel(0x003fee3f, INT2SMSKCR4);
+}
+
 void __init r8a7779_init_delay(void)
 {
        shmobile_setup_delay(1000, 2, 4); /* Cortex-A9 @ 1000MHz */
@@ -723,7 +938,6 @@ DT_MACHINE_START(R8A7779_DT, "Generic R8A7779 (Flattened Device Tree)")
        .nr_irqs        = NR_IRQS_LEGACY,
        .init_irq       = r8a7779_init_irq_dt,
        .init_machine   = r8a7779_add_standard_devices_dt,
-       .init_time      = shmobile_timer_init,
        .init_late      = r8a7779_init_late,
        .dt_compat      = r8a7779_compat_dt,
 MACHINE_END