[PATCH 31/74] ST SPEAr: Adding support for SSP PL022
From: Viresh KUMAR <hidden>
Date: 2010-08-30 10:38:55
Subsystem:
arm port, the rest · Maintainers:
Russell King, Linus Torvalds
Signed-off-by: Viresh Kumar <redacted> Signed-off-by: Rajeev Kumar <redacted> Signed-off-by: shiraz hashim <redacted> --- arch/arm/mach-spear13xx/clock.c | 2 +- arch/arm/mach-spear13xx/include/mach/generic.h | 1 + arch/arm/mach-spear13xx/spear1300_evb.c | 47 ++++++++++++++ arch/arm/mach-spear13xx/spear13xx.c | 31 ++++++++++ arch/arm/mach-spear3xx/clock.c | 4 +- arch/arm/mach-spear3xx/include/mach/generic.h | 2 + arch/arm/mach-spear3xx/spear300_evb.c | 50 +++++++++++++++ arch/arm/mach-spear3xx/spear310_evb.c | 42 +++++++++++++ arch/arm/mach-spear3xx/spear320.c | 42 +++++++++++++ arch/arm/mach-spear3xx/spear320_evb.c | 46 ++++++++++++++ arch/arm/mach-spear3xx/spear3xx.c | 31 ++++++++++ arch/arm/mach-spear6xx/clock.c | 6 +- arch/arm/mach-spear6xx/include/mach/generic.h | 1 + arch/arm/mach-spear6xx/include/mach/spear.h | 4 +- arch/arm/mach-spear6xx/spear600_evb.c | 51 ++++++++++++++++ arch/arm/mach-spear6xx/spear6xx.c | 68 +++++++++++++++++++++ arch/arm/plat-spear/include/plat/spi.h | 77 ++++++++++++++++++++++++ 17 files changed, 497 insertions(+), 8 deletions(-) create mode 100644 arch/arm/plat-spear/include/plat/spi.h
diff --git a/arch/arm/mach-spear13xx/clock.c b/arch/arm/mach-spear13xx/clock.c
index 8658d48..8399c15 100644
--- a/arch/arm/mach-spear13xx/clock.c
+++ b/arch/arm/mach-spear13xx/clock.c@@ -799,7 +799,7 @@ static struct clk_lookup spear_clk_lookups[] = { {.dev_id = "i2s0", .clk = &i2s0_clk}, {.dev_id = "i2s1", .clk = &i2s1_clk}, {.dev_id = "adc", .clk = &adc_clk}, - {.dev_id = "ssp", .clk = &ssp_clk}, + {.dev_id = "ssp-pl022", .clk = &ssp_clk}, {.dev_id = "gpio0", .clk = &gpio0_clk}, {.dev_id = "gpio1", .clk = &gpio1_clk}, {.dev_id = "keyboard", .clk = &kbd_clk},
diff --git a/arch/arm/mach-spear13xx/include/mach/generic.h b/arch/arm/mach-spear13xx/include/mach/generic.h
index b884359..967e96e 100644
--- a/arch/arm/mach-spear13xx/include/mach/generic.h
+++ b/arch/arm/mach-spear13xx/include/mach/generic.h@@ -30,6 +30,7 @@ /* Add spear13xx family device structure declarations here */ extern struct amba_device gpio_device[]; +extern struct amba_device ssp_device; extern struct amba_device uart_device; extern struct platform_device ehci0_device; extern struct platform_device ehci1_device;
diff --git a/arch/arm/mach-spear13xx/spear1300_evb.c b/arch/arm/mach-spear13xx/spear1300_evb.c
index c5ac2fb..6aaae5a 100644
--- a/arch/arm/mach-spear13xx/spear1300_evb.c
+++ b/arch/arm/mach-spear13xx/spear1300_evb.c@@ -12,7 +12,10 @@ */ #include <linux/types.h> +#include <linux/gpio.h> #include <linux/mtd/nand.h> +#include <linux/spi/flash.h> +#include <linux/spi/spi.h> #include <asm/mach/arch.h> #include <asm/mach-types.h> #include <mach/generic.h>
@@ -21,10 +24,12 @@ #include <plat/keyboard.h> #include <plat/nand.h> #include <plat/smi.h> +#include <plat/spi.h> static struct amba_device *amba_devs[] __initdata = { &gpio_device[0], &gpio_device[1], + &ssp_device, &uart_device, };
@@ -49,6 +54,46 @@ static struct kbd_platform_data kbd_data = { .rep = 1, }; +/* Currently no gpios are free on eval board so it is kept commented */ +#if 0 +/* spi board information */ +/* spi0 flash Chip Select Control function, controlled by gpio pin mentioned */ +DECLARE_SPI_CS_CONTROL(0, flash, /* mention gpio number here */); +/* spi0 flash Chip Info structure */ +DECLARE_SPI_CHIP_INFO(0, flash, spi0_flash_cs_control); + +/* spi0 spidev Chip Select Control function, controlled by gpio pin mentioned */ +DECLARE_SPI_CS_CONTROL(0, dev, /* mention gpio number here */); +/* spi0 spidev Chip Info structure */ +DECLARE_SPI_CHIP_INFO(0, dev, spi0_dev_cs_control); +#endif + +static struct spi_board_info __initdata spi_board_info[] = { +#if 0 + /* spi0 board info */ + { + .modalias = "spidev", + .controller_data = &spi0_dev_chip_info, + .max_speed_hz = 10000000, + .bus_num = 0, + .chip_select = 0, + .mode = 0, + }, { + .modalias = "m25p80", + .controller_data = &spi0_flash_chip_info, + .max_speed_hz = 1000000, + .bus_num = 0, + .chip_select = 1, + .mode = 0, + } +#endif +}; + +static void __init spi_init(void) +{ + spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info)); +} + #ifdef CONFIG_PCIEPORTBUS /* this function is needed for PCIE host and device driver. Same * controller can not be programmed as host as well as device. So host
@@ -106,6 +151,8 @@ static void __init spear1300_evb_init(void) /* Add Amba Devices */ for (i = 0; i < ARRAY_SIZE(amba_devs); i++) amba_device_register(amba_devs[i], &iomem_resource); + + spi_init(); } MACHINE_START(SPEAR1300, "ST-SPEAR1300-EVB")
diff --git a/arch/arm/mach-spear13xx/spear13xx.c b/arch/arm/mach-spear13xx/spear13xx.c
index c5a0a0c..9e4a673 100644
--- a/arch/arm/mach-spear13xx/spear13xx.c
+++ b/arch/arm/mach-spear13xx/spear13xx.c@@ -12,6 +12,7 @@ */ #include <linux/types.h> +#include <linux/amba/pl022.h> #include <linux/amba/pl061.h> #include <linux/ptrace.h> #include <linux/io.h>
@@ -64,6 +65,36 @@ struct amba_device gpio_device[] = { } }; +/* ssp device registeration */ +static struct pl022_ssp_controller ssp_platform_data = { + .bus_id = 0, + .enable_dma = 0, + /* + * This is number of spi devices that can be connected to spi. There are + * two type of chipselects on which slave devices can work. One is chip + * select provided by spi masters other is controlled through external + * gpio's. We can't use chipselect provided from spi master (because as + * soon as FIFO becomes empty, CS is disabled and transfer ends). So + * this number now depends on number of gpios available for spi. each + * slave on each master requires a separate gpio pin. + */ + .num_chipselect = 2, +}; + +struct amba_device ssp_device = { + .dev = { + .coherent_dma_mask = ~0, + .init_name = "ssp-pl022", + .platform_data = &ssp_platform_data, + }, + .res = { + .start = SPEAR13XX_SSP_BASE, + .end = SPEAR13XX_SSP_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + .irq = {IRQ_SSP, NO_IRQ}, +}; + /* uart device registeration */ struct amba_device uart_device = { .dev = {
diff --git a/arch/arm/mach-spear3xx/clock.c b/arch/arm/mach-spear3xx/clock.c
index 93c5fd9..f7dedc6 100644
--- a/arch/arm/mach-spear3xx/clock.c
+++ b/arch/arm/mach-spear3xx/clock.c@@ -444,7 +444,7 @@ static struct clk adc_clk = { }; /* ssp clock */ -static struct clk ssp_clk = { +static struct clk ssp0_clk = { .pclk = &apb_clk, .en_reg = PERIP1_CLK_ENB, .en_reg_bit = SSP_CLK_ENB,
@@ -543,7 +543,7 @@ static struct clk_lookup spear_clk_lookups[] = { { .dev_id = "c3", .clk = &c3_clk}, /* clock derived from apb clk */ { .dev_id = "adc", .clk = &adc_clk}, - { .dev_id = "ssp", .clk = &ssp_clk}, + { .dev_id = "ssp-pl022.0", .clk = &ssp0_clk}, { .dev_id = "gpio", .clk = &gpio_clk}, #if defined(CONFIG_MACH_SPEAR300) || defined(CONFIG_MACH_SPEAR310) || \ defined(CONFIG_MACH_SPEAR320)
diff --git a/arch/arm/mach-spear3xx/include/mach/generic.h b/arch/arm/mach-spear3xx/include/mach/generic.h
index 6aac229..04ce870 100644
--- a/arch/arm/mach-spear3xx/include/mach/generic.h
+++ b/arch/arm/mach-spear3xx/include/mach/generic.h@@ -32,6 +32,7 @@ /* Add spear3xx family device structure declarations here */ extern struct amba_device gpio_device; +extern struct amba_device ssp0_device; extern struct amba_device uart_device; extern struct amba_device wdt_device; extern struct platform_device ehci_device;
@@ -176,6 +177,7 @@ void __init spear310_init(void); #elif defined(CONFIG_MACH_SPEAR320) /* Add spear320 machine device structure declarations here */ extern struct amba_device clcd_device; +extern struct amba_device ssp_device[]; extern struct platform_device i2c1_device; extern struct platform_device nand_device; extern struct platform_device plgpio_device;
diff --git a/arch/arm/mach-spear3xx/spear300_evb.c b/arch/arm/mach-spear3xx/spear300_evb.c
index 895f7b7..653adec 100644
--- a/arch/arm/mach-spear3xx/spear300_evb.c
+++ b/arch/arm/mach-spear3xx/spear300_evb.c@@ -14,11 +14,15 @@ #include <linux/mtd/nand.h> #include <asm/mach/arch.h> #include <asm/mach-types.h> +#include <linux/spi/flash.h> +#include <linux/spi/spi.h> #include <mach/generic.h> +#include <mach/gpio.h> #include <mach/spear.h> #include <plat/keyboard.h> #include <plat/nand.h> #include <plat/smi.h> +#include <plat/spi.h> /* padmux devices to enable */ static struct pmx_dev *pmx_devs[] = {
@@ -39,6 +43,7 @@ static struct pmx_dev *pmx_devs[] = { static struct amba_device *amba_devs[] __initdata = { /* spear3xx specific devices */ &gpio_device, + &ssp0_device, &uart_device, &wdt_device,
@@ -70,6 +75,49 @@ static struct kbd_platform_data kbd_data = { .rep = 1, }; +/* spi board information */ +/* spi0 flash Chip Select Control function, controlled by gpio pin mentioned */ +DECLARE_SPI_CS_CONTROL(0, flash, RAS_GPIO_3); +/* spi0 flash Chip Info structure */ +DECLARE_SPI_CHIP_INFO(0, flash, spi0_flash_cs_control); + +/* + * Chip select of spidev, currently no gpio is free on eval board so it is kept + * commented + */ +#if 0 +/* spi0 spidev Chip Select Control function, controlled by gpio pin mentioned */ +DECLARE_SPI_CS_CONTROL(0, dev, /* mention gpio number here */); +/* spi0 spidev Chip Info structure */ +DECLARE_SPI_CHIP_INFO(0, dev, spi0_dev_cs_control); +#endif + +static struct spi_board_info __initdata spi_board_info[] = { + /* spi0 board info */ + { +#if 0 + .modalias = "spidev", + .controller_data = &spi0_dev_chip_info, + .max_speed_hz = 10000000, + .bus_num = 0, + .chip_select = 0, + .mode = 0, + }, { +#endif + .modalias = "m25p80", + .controller_data = &spi0_flash_chip_info, + .max_speed_hz = 400000, + .bus_num = 0, + .chip_select = 1, + .mode = 0, + } +}; + +static void __init spi_init(void) +{ + spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info)); +} + static void __init spear300_evb_init(void) { unsigned int i;
@@ -101,6 +149,8 @@ static void __init spear300_evb_init(void) /* Add Amba Devices */ for (i = 0; i < ARRAY_SIZE(amba_devs); i++) amba_device_register(amba_devs[i], &iomem_resource); + + spi_init(); } MACHINE_START(SPEAR300, "ST-SPEAR300-EVB")
diff --git a/arch/arm/mach-spear3xx/spear310_evb.c b/arch/arm/mach-spear3xx/spear310_evb.c
index 8f17362..663e78e 100644
--- a/arch/arm/mach-spear3xx/spear310_evb.c
+++ b/arch/arm/mach-spear3xx/spear310_evb.c@@ -14,10 +14,14 @@ #include <linux/mtd/nand.h> #include <asm/mach/arch.h> #include <asm/mach-types.h> +#include <linux/spi/flash.h> +#include <linux/spi/spi.h> #include <mach/generic.h> +#include <mach/gpio.h> #include <mach/spear.h> #include <plat/nand.h> #include <plat/smi.h> +#include <plat/spi.h> /* padmux devices to enable */ static struct pmx_dev *pmx_devs[] = {
@@ -46,6 +50,7 @@ static struct pmx_dev *pmx_devs[] = { static struct amba_device *amba_devs[] __initdata = { /* spear3xx specific devices */ &gpio_device, + &ssp0_device, &uart_device, &wdt_device,
@@ -66,6 +71,41 @@ static struct platform_device *plat_devs[] __initdata = { &plgpio_device, }; +/* spi board information */ +/* spi0 flash Chip Select Control function, controlled by gpio pin mentioned */ +DECLARE_SPI_CS_CONTROL(0, flash, BASIC_GPIO_3); +/* spi0 flash Chip Info structure */ +DECLARE_SPI_CHIP_INFO(0, flash, spi0_flash_cs_control); + +/* spi0 spidev Chip Select Control function, controlled by gpio pin mentioned */ +DECLARE_SPI_CS_CONTROL(0, dev, BASIC_GPIO_4); +/* spi0 spidev Chip Info structure */ +DECLARE_SPI_CHIP_INFO(0, dev, spi0_dev_cs_control); + +static struct spi_board_info __initdata spi_board_info[] = { + /* spi0 board info */ + { + .modalias = "spidev", + .controller_data = &spi0_dev_chip_info, + .max_speed_hz = 10000000, + .bus_num = 0, + .chip_select = 0, + .mode = 0, + }, { + .modalias = "m25p80", + .controller_data = &spi0_flash_chip_info, + .max_speed_hz = 400000, + .bus_num = 0, + .chip_select = 1, + .mode = 0, + } +}; + +static void __init spi_init(void) +{ + spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info)); +} + static void __init spear310_evb_init(void) { unsigned int i;
@@ -94,6 +134,8 @@ static void __init spear310_evb_init(void) /* Add Amba Devices */ for (i = 0; i < ARRAY_SIZE(amba_devs); i++) amba_device_register(amba_devs[i], &iomem_resource); + + spi_init(); } MACHINE_START(SPEAR310, "ST-SPEAR310-EVB")
diff --git a/arch/arm/mach-spear3xx/spear320.c b/arch/arm/mach-spear3xx/spear320.c
index 2ac838b..9c3d75f 100644
--- a/arch/arm/mach-spear3xx/spear320.c
+++ b/arch/arm/mach-spear3xx/spear320.c@@ -11,6 +11,7 @@ * warranty of any kind, whether express or implied. */ +#include <linux/amba/pl022.h> #include <linux/ptrace.h> #include <asm/irq.h> #include <mach/generic.h>
@@ -403,6 +404,47 @@ struct amba_device clcd_device = { .irq = {VIRQ_CLCD, NO_IRQ}, }; +/* ssp device registeration */ +static struct pl022_ssp_controller ssp_platform_data[] = { + { + .bus_id = 1, + .enable_dma = 0, + .num_chipselect = 2, + }, { + .bus_id = 2, + .enable_dma = 0, + .num_chipselect = 2, + } +}; + +struct amba_device ssp_device[] = { + { + .dev = { + .coherent_dma_mask = ~0, + .init_name = "ssp-pl022.1", + .platform_data = &ssp_platform_data[0], + }, + .res = { + .start = SPEAR320_SSP0_BASE, + .end = SPEAR320_SSP0_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + .irq = {VIRQ_SSP1, NO_IRQ}, + }, { + .dev = { + .coherent_dma_mask = ~0, + .init_name = "ssp-pl022.2", + .platform_data = &ssp_platform_data[1], + }, + .res = { + .start = SPEAR320_SSP1_BASE, + .end = SPEAR320_SSP1_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + .irq = {VIRQ_SSP2, NO_IRQ}, + } +}; + /* plgpio device registeration */ static struct plgpio_platform_data plgpio_plat_data = { .gpio_base = 8,
diff --git a/arch/arm/mach-spear3xx/spear320_evb.c b/arch/arm/mach-spear3xx/spear320_evb.c
index d693877..99ae3ba 100644
--- a/arch/arm/mach-spear3xx/spear320_evb.c
+++ b/arch/arm/mach-spear3xx/spear320_evb.c@@ -14,10 +14,14 @@ #include <linux/mtd/nand.h> #include <asm/mach/arch.h> #include <asm/mach-types.h> +#include <linux/spi/flash.h> +#include <linux/spi/spi.h> #include <mach/generic.h> +#include <mach/gpio.h> #include <mach/spear.h> #include <plat/nand.h> #include <plat/smi.h> +#include <plat/spi.h> /* padmux devices to enable */ static struct pmx_dev *pmx_devs[] = {
@@ -66,6 +70,46 @@ static struct platform_device *plat_devs[] __initdata = { &pwm_device, }; +/* Currently no gpios are free on eval board so it is kept commented */ +#if 0 +/* spi board information */ +/* spi0 flash Chip Select Control function, controlled by gpio pin mentioned */ +DECLARE_SPI_CS_CONTROL(0, flash, /* mention gpio number here */); +/* spi0 flash Chip Info structure */ +DECLARE_SPI_CHIP_INFO(0, flash, spi0_flash_cs_control); + +/* spi0 spidev Chip Select Control function, controlled by gpio pin mentioned */ +DECLARE_SPI_CS_CONTROL(0, dev, /* mention gpio number here */); +/* spi0 spidev Chip Info structure */ +DECLARE_SPI_CHIP_INFO(0, dev, spi0_dev_cs_control); +#endif + +static struct spi_board_info __initdata spi_board_info[] = { +#if 0 + /* spi0 board info */ + { + .modalias = "spidev", + .controller_data = &spi0_dev_chip_info, + .max_speed_hz = 10000000, + .bus_num = 0, + .chip_select = 0, + .mode = 0, + }, { + .modalias = "m25p80", + .controller_data = &spi0_flash_chip_info, + .max_speed_hz = 400000, + .bus_num = 0, + .chip_select = 1, + .mode = 0, + } +#endif +}; + +static void __init spi_init(void) +{ + spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info)); +} + static void __init spear320_evb_init(void) { unsigned int i;
@@ -94,6 +138,8 @@ static void __init spear320_evb_init(void) /* Add Amba Devices */ for (i = 0; i < ARRAY_SIZE(amba_devs); i++) amba_device_register(amba_devs[i], &iomem_resource); + + spi_init(); } MACHINE_START(SPEAR320, "ST-SPEAR320-EVB")
diff --git a/arch/arm/mach-spear3xx/spear3xx.c b/arch/arm/mach-spear3xx/spear3xx.c
index b15fd27..fdb4fa8 100644
--- a/arch/arm/mach-spear3xx/spear3xx.c
+++ b/arch/arm/mach-spear3xx/spear3xx.c@@ -12,6 +12,7 @@ */ #include <linux/types.h> +#include <linux/amba/pl022.h> #include <linux/amba/pl061.h> #include <linux/ptrace.h> #include <linux/io.h>
@@ -41,6 +42,36 @@ struct amba_device gpio_device = { .irq = {IRQ_BASIC_GPIO, NO_IRQ}, }; +/* ssp device registeration */ +static struct pl022_ssp_controller ssp_platform_data = { + .bus_id = 0, + .enable_dma = 0, + /* + * This is number of spi devices that can be connected to spi. There are + * two type of chipselects on which slave devices can work. One is chip + * select provided by spi masters other is controlled through external + * gpio's. We can't use chipselect provided from spi master (because as + * soon as FIFO becomes empty, CS is disabled and transfer ends). So + * this number now depends on number of gpios available for spi. each + * slave on each master requires a separate gpio pin. + */ + .num_chipselect = 2, +}; + +struct amba_device ssp0_device = { + .dev = { + .coherent_dma_mask = ~0, + .init_name = "ssp-pl022.0", + .platform_data = &ssp_platform_data, + }, + .res = { + .start = SPEAR3XX_ICM1_SSP_BASE, + .end = SPEAR3XX_ICM1_SSP_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + .irq = {IRQ_SSP, NO_IRQ}, +}; + /* uart device registeration */ struct amba_device uart_device = { .dev = {
diff --git a/arch/arm/mach-spear6xx/clock.c b/arch/arm/mach-spear6xx/clock.c
index 91f1f3f..52d5bff 100644
--- a/arch/arm/mach-spear6xx/clock.c
+++ b/arch/arm/mach-spear6xx/clock.c@@ -605,9 +605,9 @@ static struct clk_lookup spear_clk_lookups[] = { { .con_id = "fsmc", .clk = &fsmc_clk}, /* clock derived from apb clk */ { .dev_id = "adc", .clk = &adc_clk}, - { .dev_id = "ssp0", .clk = &ssp0_clk}, - { .dev_id = "ssp1", .clk = &ssp1_clk}, - { .dev_id = "ssp2", .clk = &ssp2_clk}, + { .dev_id = "ssp-pl022.0", .clk = &ssp0_clk}, + { .dev_id = "ssp-pl022.1", .clk = &ssp1_clk}, + { .dev_id = "ssp-pl022.2", .clk = &ssp2_clk}, { .dev_id = "gpio0", .clk = &gpio0_clk}, { .dev_id = "gpio1", .clk = &gpio1_clk}, { .dev_id = "gpio2", .clk = &gpio2_clk},
diff --git a/arch/arm/mach-spear6xx/include/mach/generic.h b/arch/arm/mach-spear6xx/include/mach/generic.h
index ff90419..dd29298 100644
--- a/arch/arm/mach-spear6xx/include/mach/generic.h
+++ b/arch/arm/mach-spear6xx/include/mach/generic.h@@ -31,6 +31,7 @@ /* Add spear6xx family device structure declarations here */ extern struct amba_device clcd_device; extern struct amba_device gpio_device[]; +extern struct amba_device ssp_device[]; extern struct amba_device uart_device[]; extern struct amba_device wdt_device; extern struct platform_device ehci0_device;
diff --git a/arch/arm/mach-spear6xx/include/mach/spear.h b/arch/arm/mach-spear6xx/include/mach/spear.h
index a835f5b..31486e5 100644
--- a/arch/arm/mach-spear6xx/include/mach/spear.h
+++ b/arch/arm/mach-spear6xx/include/mach/spear.h@@ -68,8 +68,8 @@ #define SPEAR6XX_ICM2_GPIO_BASE 0xD8100000 #define SPEAR6XX_ICM2_GPIO_SIZE 0x00080000 -#define SPEAR6XX_ICM2_SPI2_BASE 0xD8180000 -#define SPEAR6XX_ICM2_SPI2_SIZE 0x00080000 +#define SPEAR6XX_ICM2_SSP2_BASE 0xD8180000 +#define SPEAR6XX_ICM2_SSP2_SIZE 0x00080000 #define SPEAR6XX_ICM2_ADC_BASE 0xD8200000 #define SPEAR6XX_ICM2_ADC_SIZE 0x00080000
diff --git a/arch/arm/mach-spear6xx/spear600_evb.c b/arch/arm/mach-spear6xx/spear600_evb.c
index cf86efc..ae1055a 100644
--- a/arch/arm/mach-spear6xx/spear600_evb.c
+++ b/arch/arm/mach-spear6xx/spear600_evb.c@@ -14,16 +14,24 @@ #include <linux/mtd/nand.h> #include <asm/mach/arch.h> #include <asm/mach-types.h> +#include <linux/gpio.h> +#include <linux/spi/flash.h> +#include <linux/spi/spi.h> #include <mach/generic.h> +#include <mach/gpio.h> #include <mach/spear.h> #include <plat/nand.h> #include <plat/smi.h> +#include <plat/spi.h> static struct amba_device *amba_devs[] __initdata = { &clcd_device, &gpio_device[0], &gpio_device[1], &gpio_device[2], + &ssp_device[0], + &ssp_device[1], + &ssp_device[2], &uart_device[0], &uart_device[1], &wdt_device,
@@ -40,6 +48,47 @@ static struct platform_device *plat_devs[] __initdata = { &smi_device, }; +/* Currently no gpios are free on eval board so it is kept commented */ +#if 0 +/* spi board information */ +/* spi0 flash Chip Select Control function, controlled by gpio pin mentioned */ +DECLARE_SPI_CS_CONTROL(0, flash, /* mention gpio number here */); +/* spi0 flash Chip Info structure */ +DECLARE_SPI_CHIP_INFO(0, flash, spi0_flash_cs_control); + +/* spi0 spidev Chip Select Control function, controlled by gpio pin mentioned */ +DECLARE_SPI_CS_CONTROL(0, dev, /* mention gpio number here */); +/* spi0 spidev Chip Info structure */ +DECLARE_SPI_CHIP_INFO(0, dev, spi0_dev_cs_control); +#endif + +static struct spi_board_info __initdata spi_board_info[] = { +#if 0 + /* spi0 board info */ + { + .modalias = "spidev", + .controller_data = &spi0_dev_chip_info, + .max_speed_hz = 10000000, + .bus_num = 0, + .chip_select = 0, + .mode = 0, + }, { + .modalias = "m25p80", + .controller_data = &spi0_flash_chip_info, + .max_speed_hz = 400000, + .bus_num = 0, + .chip_select = 1, + .mode = 0, + } +#endif + /* Similarly can be done for other spi masters */ +}; + +static void __init spi_init(void) +{ + spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info)); +} + static void __init spear600_evb_init(void) { unsigned int i;
@@ -63,6 +112,8 @@ static void __init spear600_evb_init(void) /* Add Amba Devices */ for (i = 0; i < ARRAY_SIZE(amba_devs); i++) amba_device_register(amba_devs[i], &iomem_resource); + + spi_init(); }
diff --git a/arch/arm/mach-spear6xx/spear6xx.c b/arch/arm/mach-spear6xx/spear6xx.c
index 2296d0f..876692e 100644
--- a/arch/arm/mach-spear6xx/spear6xx.c
+++ b/arch/arm/mach-spear6xx/spear6xx.c@@ -12,6 +12,7 @@ */ #include <linux/types.h> +#include <linux/amba/pl022.h> #include <linux/amba/pl061.h> #include <linux/ptrace.h> #include <linux/io.h>
@@ -41,6 +42,73 @@ struct amba_device clcd_device = { .irq = {IRQ_BASIC_CLCD, NO_IRQ}, }; +/* ssp device registeration */ +static struct pl022_ssp_controller ssp_platform_data[] = { + { + .bus_id = 0, + .enable_dma = 0, + /* + * This is number of spi devices that can be connected to spi. + * There are two type of chipselects on which slave devices can + * work. One is chip select provided by spi masters other is + * controlled through external gpio's. We can't use chipselect + * provided from spi master (because as soon as FIFO becomes + * empty, CS is disabled and transfer ends). So this number now + * depends on number of gpios available for spi. each slave on + * each master requires a separate gpio pin. + */ + .num_chipselect = 2, + }, { + .bus_id = 1, + .enable_dma = 0, + .num_chipselect = 2, + }, { + .bus_id = 2, + .enable_dma = 0, + .num_chipselect = 2, + } +}; + +struct amba_device ssp_device[] = { + { + .dev = { + .coherent_dma_mask = ~0, + .init_name = "ssp-pl022.0", + .platform_data = &ssp_platform_data[0], + }, + .res = { + .start = SPEAR6XX_ICM1_SSP0_BASE, + .end = SPEAR6XX_ICM1_SSP0_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + .irq = {IRQ_SSP_1, NO_IRQ}, + }, { + .dev = { + .coherent_dma_mask = ~0, + .init_name = "ssp-pl022.1", + .platform_data = &ssp_platform_data[1], + }, + .res = { + .start = SPEAR6XX_ICM1_SSP1_BASE, + .end = SPEAR6XX_ICM1_SSP1_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + .irq = {IRQ_SSP_2, NO_IRQ}, + }, { + .dev = { + .coherent_dma_mask = ~0, + .init_name = "ssp-pl022.2", + .platform_data = &ssp_platform_data[2], + }, + .res = { + .start = SPEAR6XX_ICM2_SSP2_BASE, + .end = SPEAR6XX_ICM2_SSP2_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + .irq = {IRQ_APPL_SSP, NO_IRQ}, + } +}; + /* uart device registeration */ struct amba_device uart_device[] = { {
diff --git a/arch/arm/plat-spear/include/plat/spi.h b/arch/arm/plat-spear/include/plat/spi.h
new file mode 100644
index 0000000..a2c53f3
--- /dev/null
+++ b/arch/arm/plat-spear/include/plat/spi.h@@ -0,0 +1,77 @@ +/* + * arch/arm/plat-spear/include/plat/spi.h + * + * SPI board specific definitions common to multiple boards on multiple + * machines. + * + * Copyright (C) 2010 ST Microelectronics + * Viresh Kumar<viresh.kumar@st.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __PLAT_SPI_H +#define __PLAT_SPI_H + +#include <linux/amba/pl022.h> +#include <linux/gpio.h> + +/* spi board information */ +static inline int spi_cs_gpio_request(u32 gpio_pin) +{ + int ret; + + ret = gpio_request(gpio_pin, "SPI_CS"); + if (ret < 0) { + printk(KERN_ERR "SPI: gpio:%d request fail\n", gpio_pin); + return ret; + } else { + ret = gpio_direction_output(gpio_pin, 1); + if (ret) { + printk(KERN_ERR "SPI: gpio:%d direction set fail\n", + gpio_pin); + return ret; + } + } + return 0; +} + +/* This will define cs_control function for a specific spi slave */ +#define DECLARE_SPI_CS_CONTROL(id, type, gpio) \ +static void spi##id##_##type##_cs_control(u32 control) \ +{ \ + static int count, ret; \ + \ + if (unlikely(!count)) { \ + count++; \ + ret = spi_cs_gpio_request(gpio); \ + } \ + \ + if (!ret) \ + gpio_set_value(gpio, control); \ +} + +/* This will define CHIP_INFO structure for a specific spi slave */ +#define DECLARE_SPI_CHIP_INFO(id, type, chip_select_control) \ +struct pl022_config_chip spi##id##_##type##_chip_info = { \ + .lbm = LOOPBACK_DISABLED, \ + .iface = SSP_INTERFACE_MOTOROLA_SPI, \ + .hierarchy = SSP_MASTER, \ + .slave_tx_disable = 0, \ + .endian_tx = SSP_TX_LSB, \ + .endian_rx = SSP_RX_LSB, \ + .data_size = SSP_DATA_BITS_8, \ + .com_mode = INTERRUPT_TRANSFER, \ + .rx_lev_trig = SSP_RX_1_OR_MORE_ELEM, \ + .tx_lev_trig = SSP_TX_1_OR_MORE_EMPTY_LOC, \ + .clk_phase = SSP_CLK_SECOND_EDGE, \ + .clk_pol = SSP_CLK_POL_IDLE_LOW, \ + .cs_control = chip_select_control, \ +}; + +#define DECLARE_SPI_CHIP_INFO_NULL_ID(chip_select_control) \ +DECLARE_SPI_CHIP_INFO(, chip_select_control) + +#endif /* __PLAT_SPI_H */
--
1.7.2.2