diff options
Diffstat (limited to 'arch/arm/mach-at91/at91rm9200_devices.c')
-rw-r--r-- | arch/arm/mach-at91/at91rm9200_devices.c | 350 |
1 files changed, 295 insertions, 55 deletions
diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c index 9296833f91cc..ef6aeb86e980 100644 --- a/arch/arm/mach-at91/at91rm9200_devices.c +++ b/arch/arm/mach-at91/at91rm9200_devices.c @@ -13,6 +13,7 @@ #include <asm/mach/arch.h> #include <asm/mach/map.h> +#include <linux/dma-mapping.h> #include <linux/platform_device.h> #include <linux/i2c-gpio.h> @@ -29,7 +30,7 @@ * -------------------------------------------------------------------- */ #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) -static u64 ohci_dmamask = 0xffffffffUL; +static u64 ohci_dmamask = DMA_BIT_MASK(32); static struct at91_usbh_data usbh_data; static struct resource usbh_resources[] = { @@ -50,7 +51,7 @@ static struct platform_device at91rm9200_usbh_device = { .id = -1, .dev = { .dma_mask = &ohci_dmamask, - .coherent_dma_mask = 0xffffffff, + .coherent_dma_mask = DMA_BIT_MASK(32), .platform_data = &usbh_data, }, .resource = usbh_resources, @@ -125,7 +126,7 @@ void __init at91_add_device_udc(struct at91_udc_data *data) {} * -------------------------------------------------------------------- */ #if defined(CONFIG_ARM_AT91_ETHER) || defined(CONFIG_ARM_AT91_ETHER_MODULE) -static u64 eth_dmamask = 0xffffffffUL; +static u64 eth_dmamask = DMA_BIT_MASK(32); static struct at91_eth_data eth_data; static struct resource eth_resources[] = { @@ -146,7 +147,7 @@ static struct platform_device at91rm9200_eth_device = { .id = -1, .dev = { .dma_mask = ð_dmamask, - .coherent_dma_mask = 0xffffffff, + .coherent_dma_mask = DMA_BIT_MASK(32), .platform_data = ð_data, }, .resource = eth_resources, @@ -285,7 +286,7 @@ void __init at91_add_device_cf(struct at91_cf_data *data) {} * -------------------------------------------------------------------- */ #if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE) -static u64 mmc_dmamask = 0xffffffffUL; +static u64 mmc_dmamask = DMA_BIT_MASK(32); static struct at91_mmc_data mmc_data; static struct resource mmc_resources[] = { @@ -306,7 +307,7 @@ static struct platform_device at91rm9200_mmc_device = { .id = -1, .dev = { .dma_mask = &mmc_dmamask, - .coherent_dma_mask = 0xffffffff, + .coherent_dma_mask = DMA_BIT_MASK(32), .platform_data = &mmc_data, }, .resource = mmc_resources, @@ -375,7 +376,7 @@ static struct at91_nand_data nand_data; static struct resource nand_resources[] = { { .start = NAND_BASE, - .end = NAND_BASE + SZ_8M - 1, + .end = NAND_BASE + SZ_256M - 1, .flags = IORESOURCE_MEM, } }; @@ -513,7 +514,7 @@ void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices) * -------------------------------------------------------------------- */ #if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE) -static u64 spi_dmamask = 0xffffffffUL; +static u64 spi_dmamask = DMA_BIT_MASK(32); static struct resource spi_resources[] = { [0] = { @@ -533,7 +534,7 @@ static struct platform_device at91rm9200_spi_device = { .id = 0, .dev = { .dma_mask = &spi_dmamask, - .coherent_dma_mask = 0xffffffff, + .coherent_dma_mask = DMA_BIT_MASK(32), }, .resource = spi_resources, .num_resources = ARRAY_SIZE(spi_resources), @@ -557,8 +558,11 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) else cs_pin = spi_standard_cs[devices[i].chip_select]; - /* enable chip-select pin */ - at91_set_gpio_output(cs_pin, 1); + if (devices[i].chip_select == 0) /* for CS0 errata */ + at91_set_A_periph(cs_pin, 0); + else + at91_set_gpio_output(cs_pin, 1); + /* pass chip-select pin to driver */ devices[i].controller_data = (void *) cs_pin; @@ -613,24 +617,175 @@ static void __init at91_add_device_watchdog(void) {} /* -------------------------------------------------------------------- - * LEDs + * SSC -- Synchronous Serial Controller * -------------------------------------------------------------------- */ -#if defined(CONFIG_LEDS) -u8 at91_leds_cpu; -u8 at91_leds_timer; +#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 = AT91RM9200_BASE_SSC0, + .end = AT91RM9200_BASE_SSC0 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91RM9200_ID_SSC0, + .end = AT91RM9200_ID_SSC0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91rm9200_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_PB0, 1); + if (pins & ATMEL_SSC_TK) + at91_set_A_periph(AT91_PIN_PB1, 1); + if (pins & ATMEL_SSC_TD) + at91_set_A_periph(AT91_PIN_PB2, 1); + if (pins & ATMEL_SSC_RD) + at91_set_A_periph(AT91_PIN_PB3, 1); + if (pins & ATMEL_SSC_RK) + at91_set_A_periph(AT91_PIN_PB4, 1); + if (pins & ATMEL_SSC_RF) + at91_set_A_periph(AT91_PIN_PB5, 1); +} + +static u64 ssc1_dmamask = DMA_BIT_MASK(32); + +static struct resource ssc1_resources[] = { + [0] = { + .start = AT91RM9200_BASE_SSC1, + .end = AT91RM9200_BASE_SSC1 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91RM9200_ID_SSC1, + .end = AT91RM9200_ID_SSC1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91rm9200_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_A_periph(AT91_PIN_PB6, 1); + if (pins & ATMEL_SSC_TK) + at91_set_A_periph(AT91_PIN_PB7, 1); + if (pins & ATMEL_SSC_TD) + at91_set_A_periph(AT91_PIN_PB8, 1); + if (pins & ATMEL_SSC_RD) + at91_set_A_periph(AT91_PIN_PB9, 1); + if (pins & ATMEL_SSC_RK) + at91_set_A_periph(AT91_PIN_PB10, 1); + if (pins & ATMEL_SSC_RF) + at91_set_A_periph(AT91_PIN_PB11, 1); +} + +static u64 ssc2_dmamask = DMA_BIT_MASK(32); + +static struct resource ssc2_resources[] = { + [0] = { + .start = AT91RM9200_BASE_SSC2, + .end = AT91RM9200_BASE_SSC2 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91RM9200_ID_SSC2, + .end = AT91RM9200_ID_SSC2, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91rm9200_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_A_periph(AT91_PIN_PB12, 1); + if (pins & ATMEL_SSC_TK) + at91_set_A_periph(AT91_PIN_PB13, 1); + if (pins & ATMEL_SSC_TD) + at91_set_A_periph(AT91_PIN_PB14, 1); + if (pins & ATMEL_SSC_RD) + at91_set_A_periph(AT91_PIN_PB15, 1); + if (pins & ATMEL_SSC_RK) + at91_set_A_periph(AT91_PIN_PB16, 1); + if (pins & ATMEL_SSC_RF) + at91_set_A_periph(AT91_PIN_PB17, 1); +} -void __init at91_init_leds(u8 cpu_led, u8 timer_led) +/* + * 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) { - /* Enable GPIO to access the LEDs */ - at91_set_gpio_output(cpu_led, 1); - at91_set_gpio_output(timer_led, 1); + struct platform_device *pdev; - at91_leds_cpu = cpu_led; - at91_leds_timer = timer_led; + /* + * NOTE: caller is responsible for passing information matching + * "pins" to whatever will be using each particular controller. + */ + switch (id) { + case AT91RM9200_ID_SSC0: + pdev = &at91rm9200_ssc0_device; + configure_ssc0_pins(pins); + at91_clock_associate("ssc0_clk", &pdev->dev, "ssc"); + break; + case AT91RM9200_ID_SSC1: + pdev = &at91rm9200_ssc1_device; + configure_ssc1_pins(pins); + at91_clock_associate("ssc1_clk", &pdev->dev, "ssc"); + break; + case AT91RM9200_ID_SSC2: + pdev = &at91rm9200_ssc2_device; + configure_ssc2_pins(pins); + at91_clock_associate("ssc2_clk", &pdev->dev, "ssc"); + break; + default: + return; + } + + platform_device_register(pdev); } + #else -void __init at91_init_leds(u8 cpu_led, u8 timer_led) {} +void __init at91_add_device_ssc(unsigned id, unsigned pins) {} #endif @@ -658,12 +813,15 @@ static struct atmel_uart_data dbgu_data = { .regs = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU), }; +static u64 dbgu_dmamask = DMA_BIT_MASK(32); + static struct platform_device at91rm9200_dbgu_device = { .name = "atmel_usart", .id = 0, .dev = { - .platform_data = &dbgu_data, - .coherent_dma_mask = 0xffffffff, + .dma_mask = &dbgu_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &dbgu_data, }, .resource = dbgu_resources, .num_resources = ARRAY_SIZE(dbgu_resources), @@ -693,28 +851,35 @@ static struct atmel_uart_data uart0_data = { .use_dma_rx = 1, }; +static u64 uart0_dmamask = DMA_BIT_MASK(32); + static struct platform_device at91rm9200_uart0_device = { .name = "atmel_usart", .id = 1, .dev = { - .platform_data = &uart0_data, - .coherent_dma_mask = 0xffffffff, + .dma_mask = &uart0_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &uart0_data, }, .resource = uart0_resources, .num_resources = ARRAY_SIZE(uart0_resources), }; -static inline void configure_usart0_pins(void) +static inline void configure_usart0_pins(unsigned pins) { at91_set_A_periph(AT91_PIN_PA17, 1); /* TXD0 */ at91_set_A_periph(AT91_PIN_PA18, 0); /* RXD0 */ - at91_set_A_periph(AT91_PIN_PA20, 0); /* CTS0 */ - /* - * AT91RM9200 Errata #39 - RTS0 is not internally connected to PA21. - * We need to drive the pin manually. Default is off (RTS is active low). - */ - at91_set_gpio_output(AT91_PIN_PA21, 1); + if (pins & ATMEL_UART_CTS) + at91_set_A_periph(AT91_PIN_PA20, 0); /* CTS0 */ + + if (pins & ATMEL_UART_RTS) { + /* + * AT91RM9200 Errata #39 - RTS0 is not internally connected to PA21. + * We need to drive the pin manually. Default is off (RTS is active low). + */ + at91_set_gpio_output(AT91_PIN_PA21, 1); + } } static struct resource uart1_resources[] = { @@ -735,27 +900,37 @@ static struct atmel_uart_data uart1_data = { .use_dma_rx = 1, }; +static u64 uart1_dmamask = DMA_BIT_MASK(32); + static struct platform_device at91rm9200_uart1_device = { .name = "atmel_usart", .id = 2, .dev = { - .platform_data = &uart1_data, - .coherent_dma_mask = 0xffffffff, + .dma_mask = &uart1_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &uart1_data, }, .resource = uart1_resources, .num_resources = ARRAY_SIZE(uart1_resources), }; -static inline void configure_usart1_pins(void) +static inline void configure_usart1_pins(unsigned pins) { - at91_set_A_periph(AT91_PIN_PB18, 0); /* RI1 */ - at91_set_A_periph(AT91_PIN_PB19, 0); /* DTR1 */ at91_set_A_periph(AT91_PIN_PB20, 1); /* TXD1 */ at91_set_A_periph(AT91_PIN_PB21, 0); /* RXD1 */ - at91_set_A_periph(AT91_PIN_PB23, 0); /* DCD1 */ - at91_set_A_periph(AT91_PIN_PB24, 0); /* CTS1 */ - at91_set_A_periph(AT91_PIN_PB25, 0); /* DSR1 */ - at91_set_A_periph(AT91_PIN_PB26, 0); /* RTS1 */ + + if (pins & ATMEL_UART_RI) + at91_set_A_periph(AT91_PIN_PB18, 0); /* RI1 */ + if (pins & ATMEL_UART_DTR) + at91_set_A_periph(AT91_PIN_PB19, 0); /* DTR1 */ + if (pins & ATMEL_UART_DCD) + at91_set_A_periph(AT91_PIN_PB23, 0); /* DCD1 */ + if (pins & ATMEL_UART_CTS) + at91_set_A_periph(AT91_PIN_PB24, 0); /* CTS1 */ + if (pins & ATMEL_UART_DSR) + at91_set_A_periph(AT91_PIN_PB25, 0); /* DSR1 */ + if (pins & ATMEL_UART_RTS) + at91_set_A_periph(AT91_PIN_PB26, 0); /* RTS1 */ } static struct resource uart2_resources[] = { @@ -776,21 +951,29 @@ static struct atmel_uart_data uart2_data = { .use_dma_rx = 1, }; +static u64 uart2_dmamask = DMA_BIT_MASK(32); + static struct platform_device at91rm9200_uart2_device = { .name = "atmel_usart", .id = 3, .dev = { - .platform_data = &uart2_data, - .coherent_dma_mask = 0xffffffff, + .dma_mask = &uart2_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &uart2_data, }, .resource = uart2_resources, .num_resources = ARRAY_SIZE(uart2_resources), }; -static inline void configure_usart2_pins(void) +static inline void configure_usart2_pins(unsigned pins) { at91_set_A_periph(AT91_PIN_PA22, 0); /* RXD2 */ at91_set_A_periph(AT91_PIN_PA23, 1); /* TXD2 */ + + if (pins & ATMEL_UART_CTS) + at91_set_B_periph(AT91_PIN_PA30, 0); /* CTS2 */ + if (pins & ATMEL_UART_RTS) + at91_set_B_periph(AT91_PIN_PA31, 0); /* RTS2 */ } static struct resource uart3_resources[] = { @@ -811,27 +994,35 @@ static struct atmel_uart_data uart3_data = { .use_dma_rx = 1, }; +static u64 uart3_dmamask = DMA_BIT_MASK(32); + static struct platform_device at91rm9200_uart3_device = { .name = "atmel_usart", .id = 4, .dev = { - .platform_data = &uart3_data, - .coherent_dma_mask = 0xffffffff, + .dma_mask = &uart3_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &uart3_data, }, .resource = uart3_resources, .num_resources = ARRAY_SIZE(uart3_resources), }; -static inline void configure_usart3_pins(void) +static inline void configure_usart3_pins(unsigned pins) { at91_set_B_periph(AT91_PIN_PA5, 1); /* TXD3 */ at91_set_B_periph(AT91_PIN_PA6, 0); /* RXD3 */ + + if (pins & ATMEL_UART_CTS) + at91_set_B_periph(AT91_PIN_PB1, 0); /* CTS3 */ + if (pins & ATMEL_UART_RTS) + at91_set_B_periph(AT91_PIN_PB0, 0); /* RTS3 */ } -struct platform_device *at91_uarts[ATMEL_MAX_UART]; /* the UARTs to use */ +static struct platform_device *at91_uarts[ATMEL_MAX_UART]; /* the UARTs to use */ struct platform_device *atmel_default_console_device; /* the serial console device */ -void __init at91_init_serial(struct at91_uart_config *config) +void __init __deprecated at91_init_serial(struct at91_uart_config *config) { int i; @@ -839,22 +1030,22 @@ void __init at91_init_serial(struct at91_uart_config *config) for (i = 0; i < config->nr_tty; i++) { switch (config->tty_map[i]) { case 0: - configure_usart0_pins(); + configure_usart0_pins(ATMEL_UART_CTS | ATMEL_UART_RTS); at91_uarts[i] = &at91rm9200_uart0_device; at91_clock_associate("usart0_clk", &at91rm9200_uart0_device.dev, "usart"); break; case 1: - configure_usart1_pins(); + configure_usart1_pins(ATMEL_UART_CTS | ATMEL_UART_RTS | ATMEL_UART_DSR | ATMEL_UART_DTR | ATMEL_UART_DCD | ATMEL_UART_RI); at91_uarts[i] = &at91rm9200_uart1_device; at91_clock_associate("usart1_clk", &at91rm9200_uart1_device.dev, "usart"); break; case 2: - configure_usart2_pins(); + configure_usart2_pins(0); at91_uarts[i] = &at91rm9200_uart2_device; at91_clock_associate("usart2_clk", &at91rm9200_uart2_device.dev, "usart"); break; case 3: - configure_usart3_pins(); + configure_usart3_pins(0); at91_uarts[i] = &at91rm9200_uart3_device; at91_clock_associate("usart3_clk", &at91rm9200_uart3_device.dev, "usart"); break; @@ -876,6 +1067,53 @@ void __init at91_init_serial(struct at91_uart_config *config) printk(KERN_INFO "AT91: No default serial console defined.\n"); } +void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) +{ + struct platform_device *pdev; + + switch (id) { + case 0: /* DBGU */ + pdev = &at91rm9200_dbgu_device; + configure_dbgu_pins(); + at91_clock_associate("mck", &pdev->dev, "usart"); + break; + case AT91RM9200_ID_US0: + pdev = &at91rm9200_uart0_device; + configure_usart0_pins(pins); + at91_clock_associate("usart0_clk", &pdev->dev, "usart"); + break; + case AT91RM9200_ID_US1: + pdev = &at91rm9200_uart1_device; + configure_usart1_pins(pins); + at91_clock_associate("usart1_clk", &pdev->dev, "usart"); + break; + case AT91RM9200_ID_US2: + pdev = &at91rm9200_uart2_device; + configure_usart2_pins(pins); + at91_clock_associate("usart2_clk", &pdev->dev, "usart"); + break; + case AT91RM9200_ID_US3: + pdev = &at91rm9200_uart3_device; + configure_usart3_pins(pins); + at91_clock_associate("usart3_clk", &pdev->dev, "usart"); + break; + default: + return; + } + pdev->id = portnr; /* update to mapped ID */ + + if (portnr < ATMEL_MAX_UART) + at91_uarts[portnr] = pdev; +} + +void __init at91_set_serial_console(unsigned portnr) +{ + if (portnr < ATMEL_MAX_UART) + atmel_default_console_device = at91_uarts[portnr]; + if (!atmel_default_console_device) + printk(KERN_INFO "AT91: No default serial console defined.\n"); +} + void __init at91_add_device_serial(void) { int i; @@ -886,7 +1124,9 @@ void __init at91_add_device_serial(void) } } #else -void __init at91_init_serial(struct at91_uart_config *config) {} +void __init __deprecated at91_init_serial(struct at91_uart_config *config) {} +void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {} +void __init at91_set_serial_console(unsigned portnr) {} void __init at91_add_device_serial(void) {} #endif |