From bfbc32663d4846039f88c0eccc1956587d89c042 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Wed, 23 Jan 2008 09:18:06 +0100 Subject: [ARM] 4754/1: [AT91] SSC library support Core support of the Atmel SSC library for all Atmel AT91 processors. Based on David Brownell's initial patch for the AT91RM9200. Signed-off-by: Andrew Victor Acked-by: David Brownell Signed-off-by: Russell King --- arch/arm/mach-at91/at91sam9261_devices.c | 173 +++++++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) (limited to 'arch/arm/mach-at91/at91sam9261_devices.c') diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c index f7f02d15045..266ccf01be5 100644 --- a/arch/arm/mach-at91/at91sam9261_devices.c +++ b/arch/arm/mach-at91/at91sam9261_devices.c @@ -618,6 +618,179 @@ void __init at91_init_leds(u8 cpu_led, u8 timer_led) {} #endif +/* -------------------------------------------------------------------- + * SSC -- Synchronous Serial Controller + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_ATMEL_SSC) || defined(CONFIG_ATMEL_SSC_MODULE) +static u64 ssc0_dmamask = DMA_BIT_MASK(32); + +static struct resource ssc0_resources[] = { + [0] = { + .start = AT91SAM9261_BASE_SSC0, + .end = AT91SAM9261_BASE_SSC0 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9261_ID_SSC0, + .end = AT91SAM9261_ID_SSC0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9261_ssc0_device = { + .name = "ssc", + .id = 0, + .dev = { + .dma_mask = &ssc0_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .resource = ssc0_resources, + .num_resources = ARRAY_SIZE(ssc0_resources), +}; + +static inline void configure_ssc0_pins(unsigned pins) +{ + if (pins & ATMEL_SSC_TF) + at91_set_A_periph(AT91_PIN_PB21, 1); + if (pins & ATMEL_SSC_TK) + at91_set_A_periph(AT91_PIN_PB22, 1); + if (pins & ATMEL_SSC_TD) + at91_set_A_periph(AT91_PIN_PB23, 1); + if (pins & ATMEL_SSC_RD) + at91_set_A_periph(AT91_PIN_PB24, 1); + if (pins & ATMEL_SSC_RK) + at91_set_A_periph(AT91_PIN_PB25, 1); + if (pins & ATMEL_SSC_RF) + at91_set_A_periph(AT91_PIN_PB26, 1); +} + +static u64 ssc1_dmamask = DMA_BIT_MASK(32); + +static struct resource ssc1_resources[] = { + [0] = { + .start = AT91SAM9261_BASE_SSC1, + .end = AT91SAM9261_BASE_SSC1 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9261_ID_SSC1, + .end = AT91SAM9261_ID_SSC1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9261_ssc1_device = { + .name = "ssc", + .id = 1, + .dev = { + .dma_mask = &ssc1_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .resource = ssc1_resources, + .num_resources = ARRAY_SIZE(ssc1_resources), +}; + +static inline void configure_ssc1_pins(unsigned pins) +{ + if (pins & ATMEL_SSC_TF) + at91_set_B_periph(AT91_PIN_PA17, 1); + if (pins & ATMEL_SSC_TK) + at91_set_B_periph(AT91_PIN_PA18, 1); + if (pins & ATMEL_SSC_TD) + at91_set_B_periph(AT91_PIN_PA19, 1); + if (pins & ATMEL_SSC_RD) + at91_set_B_periph(AT91_PIN_PA20, 1); + if (pins & ATMEL_SSC_RK) + at91_set_B_periph(AT91_PIN_PA21, 1); + if (pins & ATMEL_SSC_RF) + at91_set_B_periph(AT91_PIN_PA22, 1); +} + +static u64 ssc2_dmamask = DMA_BIT_MASK(32); + +static struct resource ssc2_resources[] = { + [0] = { + .start = AT91SAM9261_BASE_SSC2, + .end = AT91SAM9261_BASE_SSC2 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9261_ID_SSC2, + .end = AT91SAM9261_ID_SSC2, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9261_ssc2_device = { + .name = "ssc", + .id = 2, + .dev = { + .dma_mask = &ssc2_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .resource = ssc2_resources, + .num_resources = ARRAY_SIZE(ssc2_resources), +}; + +static inline void configure_ssc2_pins(unsigned pins) +{ + if (pins & ATMEL_SSC_TF) + at91_set_B_periph(AT91_PIN_PC25, 1); + if (pins & ATMEL_SSC_TK) + at91_set_B_periph(AT91_PIN_PC26, 1); + if (pins & ATMEL_SSC_TD) + at91_set_B_periph(AT91_PIN_PC27, 1); + if (pins & ATMEL_SSC_RD) + at91_set_B_periph(AT91_PIN_PC28, 1); + if (pins & ATMEL_SSC_RK) + at91_set_B_periph(AT91_PIN_PC29, 1); + if (pins & ATMEL_SSC_RF) + at91_set_B_periph(AT91_PIN_PC30, 1); +} + +/* + * SSC controllers are accessed through library code, instead of any + * kind of all-singing/all-dancing driver. For example one could be + * used by a particular I2S audio codec's driver, while another one + * on the same system might be used by a custom data capture driver. + */ +void __init at91_add_device_ssc(unsigned id, unsigned pins) +{ + struct platform_device *pdev; + + /* + * NOTE: caller is responsible for passing information matching + * "pins" to whatever will be using each particular controller. + */ + switch (id) { + case AT91SAM9261_ID_SSC0: + pdev = &at91sam9261_ssc0_device; + configure_ssc0_pins(pins); + at91_clock_associate("ssc0_clk", &pdev->dev, "pclk"); + break; + case AT91SAM9261_ID_SSC1: + pdev = &at91sam9261_ssc1_device; + configure_ssc1_pins(pins); + at91_clock_associate("ssc1_clk", &pdev->dev, "pclk"); + break; + case AT91SAM9261_ID_SSC2: + pdev = &at91sam9261_ssc2_device; + configure_ssc2_pins(pins); + at91_clock_associate("ssc2_clk", &pdev->dev, "pclk"); + break; + default: + return; + } + + platform_device_register(pdev); +} + +#else +void __init at91_add_device_ssc(unsigned id, unsigned pins) {} +#endif + + /* -------------------------------------------------------------------- * UART * -------------------------------------------------------------------- */ -- cgit v1.2.2