Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / arch / arm / mach-s3c64xx / pl080.c
diff --git a/kernel/arch/arm/mach-s3c64xx/pl080.c b/kernel/arch/arm/mach-s3c64xx/pl080.c
new file mode 100644 (file)
index 0000000..901a984
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ * Samsung's S3C64XX generic DMA support using amba-pl08x driver.
+ *
+ * Copyright (c) 2013 Tomasz Figa <tomasz.figa@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/pl080.h>
+#include <linux/amba/pl08x.h>
+#include <linux/of.h>
+
+#include <mach/irqs.h>
+#include <mach/map.h>
+
+#include "regs-sys.h"
+
+static int pl08x_get_xfer_signal(const struct pl08x_channel_data *cd)
+{
+       return cd->min_signal;
+}
+
+static void pl08x_put_xfer_signal(const struct pl08x_channel_data *cd, int ch)
+{
+}
+
+/*
+ * DMA0
+ */
+
+static struct pl08x_channel_data s3c64xx_dma0_info[] = {
+       {
+               .bus_id = "uart0_tx",
+               .min_signal = 0,
+               .max_signal = 0,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "uart0_rx",
+               .min_signal = 1,
+               .max_signal = 1,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "uart1_tx",
+               .min_signal = 2,
+               .max_signal = 2,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "uart1_rx",
+               .min_signal = 3,
+               .max_signal = 3,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "uart2_tx",
+               .min_signal = 4,
+               .max_signal = 4,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "uart2_rx",
+               .min_signal = 5,
+               .max_signal = 5,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "uart3_tx",
+               .min_signal = 6,
+               .max_signal = 6,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "uart3_rx",
+               .min_signal = 7,
+               .max_signal = 7,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "pcm0_tx",
+               .min_signal = 8,
+               .max_signal = 8,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "pcm0_rx",
+               .min_signal = 9,
+               .max_signal = 9,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "i2s0_tx",
+               .min_signal = 10,
+               .max_signal = 10,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "i2s0_rx",
+               .min_signal = 11,
+               .max_signal = 11,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "spi0_tx",
+               .min_signal = 12,
+               .max_signal = 12,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "spi0_rx",
+               .min_signal = 13,
+               .max_signal = 13,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "i2s2_tx",
+               .min_signal = 14,
+               .max_signal = 14,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "i2s2_rx",
+               .min_signal = 15,
+               .max_signal = 15,
+               .periph_buses = PL08X_AHB2,
+       }
+};
+
+struct pl08x_platform_data s3c64xx_dma0_plat_data = {
+       .memcpy_channel = {
+               .bus_id = "memcpy",
+               .cctl_memcpy =
+                       (PL080_BSIZE_4 << PL080_CONTROL_SB_SIZE_SHIFT |
+                       PL080_BSIZE_4 << PL080_CONTROL_DB_SIZE_SHIFT |
+                       PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT |
+                       PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT |
+                       PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE |
+                       PL080_CONTROL_PROT_SYS),
+       },
+       .lli_buses = PL08X_AHB1,
+       .mem_buses = PL08X_AHB1,
+       .get_xfer_signal = pl08x_get_xfer_signal,
+       .put_xfer_signal = pl08x_put_xfer_signal,
+       .slave_channels = s3c64xx_dma0_info,
+       .num_slave_channels = ARRAY_SIZE(s3c64xx_dma0_info),
+};
+
+static AMBA_AHB_DEVICE(s3c64xx_dma0, "dma-pl080s.0", 0,
+                       0x75000000, {IRQ_DMA0}, &s3c64xx_dma0_plat_data);
+
+/*
+ * DMA1
+ */
+
+static struct pl08x_channel_data s3c64xx_dma1_info[] = {
+       {
+               .bus_id = "pcm1_tx",
+               .min_signal = 0,
+               .max_signal = 0,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "pcm1_rx",
+               .min_signal = 1,
+               .max_signal = 1,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "i2s1_tx",
+               .min_signal = 2,
+               .max_signal = 2,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "i2s1_rx",
+               .min_signal = 3,
+               .max_signal = 3,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "spi1_tx",
+               .min_signal = 4,
+               .max_signal = 4,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "spi1_rx",
+               .min_signal = 5,
+               .max_signal = 5,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "ac97_out",
+               .min_signal = 6,
+               .max_signal = 6,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "ac97_in",
+               .min_signal = 7,
+               .max_signal = 7,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "ac97_mic",
+               .min_signal = 8,
+               .max_signal = 8,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "pwm",
+               .min_signal = 9,
+               .max_signal = 9,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "irda",
+               .min_signal = 10,
+               .max_signal = 10,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "external",
+               .min_signal = 11,
+               .max_signal = 11,
+               .periph_buses = PL08X_AHB2,
+       },
+};
+
+struct pl08x_platform_data s3c64xx_dma1_plat_data = {
+       .memcpy_channel = {
+               .bus_id = "memcpy",
+               .cctl_memcpy =
+                       (PL080_BSIZE_4 << PL080_CONTROL_SB_SIZE_SHIFT |
+                       PL080_BSIZE_4 << PL080_CONTROL_DB_SIZE_SHIFT |
+                       PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT |
+                       PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT |
+                       PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE |
+                       PL080_CONTROL_PROT_SYS),
+       },
+       .lli_buses = PL08X_AHB1,
+       .mem_buses = PL08X_AHB1,
+       .get_xfer_signal = pl08x_get_xfer_signal,
+       .put_xfer_signal = pl08x_put_xfer_signal,
+       .slave_channels = s3c64xx_dma1_info,
+       .num_slave_channels = ARRAY_SIZE(s3c64xx_dma1_info),
+};
+
+static AMBA_AHB_DEVICE(s3c64xx_dma1, "dma-pl080s.1", 0,
+                       0x75100000, {IRQ_DMA1}, &s3c64xx_dma1_plat_data);
+
+static int __init s3c64xx_pl080_init(void)
+{
+       /* Set all DMA configuration to be DMA, not SDMA */
+       writel(0xffffff, S3C64XX_SDMA_SEL);
+
+       if (of_have_populated_dt())
+               return 0;
+
+       amba_device_register(&s3c64xx_dma0_device, &iomem_resource);
+       amba_device_register(&s3c64xx_dma1_device, &iomem_resource);
+
+       return 0;
+}
+arch_initcall(s3c64xx_pl080_init);