diff options
author | Haavard Skinnemoen <hskinnemoen@atmel.com> | 2007-02-16 13:56:11 +0100 |
---|---|---|
committer | Haavard Skinnemoen <hskinnemoen@atmel.com> | 2007-02-16 14:01:40 +0100 |
commit | 41d8ca452f523b9245704c7dd8ef290fa7b78e6b (patch) | |
tree | 41d84a6d1a1f20e7e74893eb76bf9a2c4de5c709 | |
parent | [AVR32] Warn, don't BUG if clk_disable is called too many times (diff) | |
download | linux-41d8ca452f523b9245704c7dd8ef290fa7b78e6b.tar.xz linux-41d8ca452f523b9245704c7dd8ef290fa7b78e6b.zip |
[AVR32] Use per-controller spi_board_info structures
Set up one spi_board_info array per controller and pass this to
at32_add_device_spi so that it can set up any GPIO pins for chip
selects based on this information.
Extracted from a patch by David Brownell and adapted slightly.
Signed-off-by: Haavard Skinnemoen <hskinnemoen@atmel.com>
-rw-r--r-- | arch/avr32/boards/atstk1000/atstk1002.c | 9 | ||||
-rw-r--r-- | arch/avr32/mach-at32ap/at32ap7000.c | 55 | ||||
-rw-r--r-- | include/asm-avr32/arch-at32ap/board.h | 4 |
3 files changed, 44 insertions, 24 deletions
diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c index d47e39f0e971..5974768a59e5 100644 --- a/arch/avr32/boards/atstk1000/atstk1002.c +++ b/arch/avr32/boards/atstk1000/atstk1002.c @@ -8,7 +8,6 @@ * published by the Free Software Foundation. */ #include <linux/clk.h> -#include <linux/device.h> #include <linux/etherdevice.h> #include <linux/init.h> #include <linux/kernel.h> @@ -36,12 +35,11 @@ static struct eth_addr __initdata hw_addr[2]; static struct eth_platform_data __initdata eth_data[2]; extern struct lcdc_platform_data atstk1000_fb0_data; -static struct spi_board_info spi_board_info[] __initdata = { +static struct spi_board_info spi0_board_info[] __initdata = { { + /* QVGA display */ .modalias = "ltv350qv", - .controller_data = (void *)GPIO_PIN_PA(4), .max_speed_hz = 16000000, - .bus_num = 0, .chip_select = 1, }, }; @@ -149,8 +147,7 @@ static int __init atstk1002_init(void) set_hw_addr(at32_add_device_eth(0, ð_data[0])); - spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info)); - at32_add_device_spi(0); + at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info)); at32_add_device_lcdc(0, &atstk1000_fb0_data); return 0; diff --git a/arch/avr32/mach-at32ap/at32ap7000.c b/arch/avr32/mach-at32ap/at32ap7000.c index a5037aa102fb..bc235507c5c7 100644 --- a/arch/avr32/mach-at32ap/at32ap7000.c +++ b/arch/avr32/mach-at32ap/at32ap7000.c @@ -8,6 +8,7 @@ #include <linux/clk.h> #include <linux/init.h> #include <linux/platform_device.h> +#include <linux/spi/spi.h> #include <asm/io.h> @@ -751,8 +752,41 @@ static struct resource atmel_spi1_resource[] = { DEFINE_DEV(atmel_spi, 1); DEV_CLK(spi_clk, atmel_spi1, pba, 1); -struct platform_device *__init at32_add_device_spi(unsigned int id) +static void +at32_spi_setup_slaves(unsigned int bus_num, struct spi_board_info *b, + unsigned int n, const u8 *pins) { + unsigned int pin, mode; + + for (; n; n--, b++) { + b->bus_num = bus_num; + if (b->chip_select >= 4) + continue; + pin = (unsigned)b->controller_data; + if (!pin) { + pin = pins[b->chip_select]; + b->controller_data = (void *)pin; + } + mode = AT32_GPIOF_OUTPUT; + if (!(b->mode & SPI_CS_HIGH)) + mode |= AT32_GPIOF_HIGH; + at32_select_gpio(pin, mode); + } +} + +struct platform_device *__init +at32_add_device_spi(unsigned int id, struct spi_board_info *b, unsigned int n) +{ + /* + * Manage the chipselects as GPIOs, normally using the same pins + * the SPI controller expects; but boards can use other pins. + */ + static u8 __initdata spi0_pins[] = + { GPIO_PIN_PA(3), GPIO_PIN_PA(4), + GPIO_PIN_PA(5), GPIO_PIN_PA(20), }; + static u8 __initdata spi1_pins[] = + { GPIO_PIN_PB(2), GPIO_PIN_PB(3), + GPIO_PIN_PB(4), GPIO_PIN_PA(27), }; struct platform_device *pdev; switch (id) { @@ -761,14 +795,7 @@ struct platform_device *__init at32_add_device_spi(unsigned int id) select_peripheral(PA(0), PERIPH_A, 0); /* MISO */ select_peripheral(PA(1), PERIPH_A, 0); /* MOSI */ select_peripheral(PA(2), PERIPH_A, 0); /* SCK */ - - /* NPCS[2:0] */ - at32_select_gpio(GPIO_PIN_PA(3), - AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH); - at32_select_gpio(GPIO_PIN_PA(4), - AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH); - at32_select_gpio(GPIO_PIN_PA(5), - AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH); + at32_spi_setup_slaves(0, b, n, spi0_pins); break; case 1: @@ -776,20 +803,14 @@ struct platform_device *__init at32_add_device_spi(unsigned int id) select_peripheral(PB(0), PERIPH_B, 0); /* MISO */ select_peripheral(PB(1), PERIPH_B, 0); /* MOSI */ select_peripheral(PB(5), PERIPH_B, 0); /* SCK */ - - /* NPCS[2:0] */ - at32_select_gpio(GPIO_PIN_PB(2), - AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH); - at32_select_gpio(GPIO_PIN_PB(3), - AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH); - at32_select_gpio(GPIO_PIN_PB(4), - AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH); + at32_spi_setup_slaves(1, b, n, spi1_pins); break; default: return NULL; } + spi_register_board_info(b, n); platform_device_register(pdev); return pdev; } diff --git a/include/asm-avr32/arch-at32ap/board.h b/include/asm-avr32/arch-at32ap/board.h index b120ee030c86..1a7b07d436ff 100644 --- a/include/asm-avr32/arch-at32ap/board.h +++ b/include/asm-avr32/arch-at32ap/board.h @@ -26,7 +26,9 @@ struct eth_platform_data { struct platform_device * at32_add_device_eth(unsigned int id, struct eth_platform_data *data); -struct platform_device *at32_add_device_spi(unsigned int id); +struct spi_board_info; +struct platform_device * +at32_add_device_spi(unsigned int id, struct spi_board_info *b, unsigned int n); struct lcdc_platform_data { unsigned long fbmem_start; |