X-Git-Url: https://git.ti.com/gitweb?p=sitara-epos%2Fsitara-epos-kernel.git;a=blobdiff_plain;f=arch%2Farm%2Fmach-omap2%2Fdevices.c;h=984bc62f7d74ed498d5aa30b791d8687f452b7fe;hp=bcb66309aceac6960c1d202c76508f9f38bad0f7;hb=40c844f096868ddca4855ea5522607d79532a933;hpb=c20f3c0c2db445fabb2dd007fce179092d217c2d diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index bcb66309acea..984bc62f7d74 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -28,6 +28,10 @@ #include #include +#ifdef CONFIG_OMAP3_EDMA +#include +#endif + #include #include #include @@ -698,6 +702,248 @@ static void omap_init_vout(void) static inline void omap_init_vout(void) {} #endif +#if defined(CONFIG_SOC_OMAPAM33XX) && defined(CONFIG_OMAP3_EDMA) + +#define AM33XX_TPCC_BASE 0x49000000 +#define AM33XX_TPTC0_BASE 0x49800000 +#define AM33XX_TPTC1_BASE 0x49900000 +#define AM33XX_TPTC2_BASE 0x49a00000 + +#define AM33XX_SCM_BASE_EDMA 0x00000f90 + +static struct resource am33xx_edma_resources[] = { + { + .name = "edma_cc0", + .start = AM33XX_TPCC_BASE, + .end = AM33XX_TPCC_BASE + SZ_32K - 1, + .flags = IORESOURCE_MEM, + }, + { + .name = "edma_tc0", + .start = AM33XX_TPTC0_BASE, + .end = AM33XX_TPTC0_BASE + SZ_1K - 1, + .flags = IORESOURCE_MEM, + }, + { + .name = "edma_tc1", + .start = AM33XX_TPTC1_BASE, + .end = AM33XX_TPTC1_BASE + SZ_1K - 1, + .flags = IORESOURCE_MEM, + }, + { + .name = "edma_tc2", + .start = AM33XX_TPTC2_BASE, + .end = AM33XX_TPTC2_BASE + SZ_1K - 1, + .flags = IORESOURCE_MEM, + }, + { + .name = "edma0", + .start = AM33XX_IRQ_TPCC0_INT_PO0, + .flags = IORESOURCE_IRQ, + }, + { + .name = "edma0_err", + .start = AM33XX_IRQ_TPCC0_ERRINT_PO, + .flags = IORESOURCE_IRQ, + }, +}; + +static const s16 am33xx_dma_rsv_chans[][2] = { + /* (offset, number) */ + {0, 2}, + {14, 2}, + {26, 6}, + {48, 4}, + {56, 8}, + {-1, -1} +}; + +static const s16 am33xx_dma_rsv_slots[][2] = { + /* (offset, number) */ + {0, 2}, + {14, 2}, + {26, 6}, + {48, 4}, + {56, 8}, + {64, 127}, + {-1, -1} +}; + +/* Three Transfer Controllers on AM33XX */ +static const s8 am33xx_queue_tc_mapping[][2] = { + /* {event queue no, TC no} */ + {0, 0}, + {1, 1}, + {2, 2}, + {-1, -1} +}; + +static const s8 am33xx_queue_priority_mapping[][2] = { + /* {event queue no, Priority} */ + {0, 0}, + {1, 1}, + {2, 2}, + {-1, -1} +}; + +static struct event_to_channel_map am33xx_xbar_event_mapping[] = { + /* {xbar event no, Channel} */ + {1, 12}, /* SDTXEVT1 -> MMCHS2 */ + {2, 13}, /* SDRXEVT1 -> MMCHS2 */ + {3, -1}, + {4, -1}, + {5, -1}, + {6, -1}, + {7, -1}, + {8, -1}, + {9, -1}, + {10, -1}, + {11, -1}, + {12, -1}, + {13, -1}, + {14, -1}, + {15, -1}, + {16, -1}, + {17, -1}, + {18, -1}, + {19, -1}, + {20, -1}, + {21, -1}, + {22, -1}, + {23, -1}, + {24, -1}, + {25, -1}, + {26, -1}, + {27, -1}, + {28, -1}, + {29, -1}, + {30, -1}, + {31, -1}, + {-1, -1} +}; + +/** + * map_xbar_event_to_channel - maps a crossbar event to a DMA channel + * according to the configuration provided + * @event: the event number for which mapping is required + * @channel: channel being activated + * @xbar_event_mapping: array that has the event to channel map + * + * Events that are routed by default are not mapped. Only events that + * are crossbar mapped are routed to available channels according to + * the configuration provided + * + * Returns zero on success, else negative errno. + */ +int map_xbar_event_to_channel(unsigned int event, unsigned int *channel, + struct event_to_channel_map *xbar_event_mapping) +{ + unsigned int ctrl = 0; + unsigned int xbar_evt_no = 0; + unsigned int val = 0; + unsigned int offset = 0; + unsigned int mask = 0; + + ctrl = EDMA_CTLR(event); + xbar_evt_no = event - (edma_info[ctrl]->num_channels); + + if (event < edma_info[ctrl]->num_channels) { + *channel = event; + } else if (event < edma_info[ctrl]->num_events) { + *channel = xbar_event_mapping[xbar_evt_no].channel_no; + /* confirm the range */ + if (*channel < EDMA_MAX_DMACH) + clear_bit(*channel, edma_info[ctrl]->edma_unused); + mask = (*channel)%4; + offset = (*channel)/4; + offset *= 4; + offset += mask; + val = (unsigned int)__raw_readl(AM33XX_CTRL_REGADDR( + AM33XX_SCM_BASE_EDMA + offset)); + val = val & (~(0xFF)); + val = val | (xbar_event_mapping[xbar_evt_no].xbar_event_no); + __raw_writel(val, + AM33XX_CTRL_REGADDR(AM33XX_SCM_BASE_EDMA + offset)); + return 0; + } else { + return -EINVAL; + } + + return 0; +} + +static struct edma_soc_info am33xx_edma_info[] = { + { + .n_channel = 64, + .n_region = 4, + .n_slot = 256, + .n_tc = 3, + .n_cc = 1, + .rsv_chans = am33xx_dma_rsv_chans, + .rsv_slots = am33xx_dma_rsv_slots, + .queue_tc_mapping = am33xx_queue_tc_mapping, + .queue_priority_mapping = am33xx_queue_priority_mapping, + .is_xbar = 1, + .n_events = 95, + .xbar_event_mapping = am33xx_xbar_event_mapping, + .map_xbar_channel = map_xbar_event_to_channel, + }, +}; + +static struct platform_device am33xx_edma_device = { + .name = "edma", + .id = -1, + .dev = { + .platform_data = am33xx_edma_info, + }, + .num_resources = ARRAY_SIZE(am33xx_edma_resources), + .resource = am33xx_edma_resources, +}; + +int __init am33xx_register_edma(void) +{ + struct platform_device *pdev; + static struct clk *edma_clk; + + if (cpu_is_am33xx()) + pdev = &am33xx_edma_device; + else { + pr_err("%s: platform not supported\n", __func__); + return -ENODEV; + } + + edma_clk = clk_get(NULL, "tpcc_ick"); + if (IS_ERR(edma_clk)) { + printk(KERN_ERR "EDMA: Failed to get clock\n"); + return -EBUSY; + } + clk_enable(edma_clk); + edma_clk = clk_get(NULL, "tptc0_ick"); + if (IS_ERR(edma_clk)) { + printk(KERN_ERR "EDMA: Failed to get clock\n"); + return -EBUSY; + } + clk_enable(edma_clk); + edma_clk = clk_get(NULL, "tptc1_ick"); + if (IS_ERR(edma_clk)) { + printk(KERN_ERR "EDMA: Failed to get clock\n"); + return -EBUSY; + } + clk_enable(edma_clk); + edma_clk = clk_get(NULL, "tptc2_ick"); + if (IS_ERR(edma_clk)) { + printk(KERN_ERR "EDMA: Failed to get clock\n"); + return -EBUSY; + } + clk_enable(edma_clk); + + return platform_device_register(pdev); +} + +#else +static inline void am33xx_register_edma(void) {} +#endif + /*-------------------------------------------------------------------------*/ static int __init omap2_init_devices(void) @@ -719,6 +965,7 @@ static int __init omap2_init_devices(void) omap_init_aes(); omap_init_vout(); am33xx_cpsw_init(); + am33xx_register_edma(); return 0; }