diff options
author | Linus Walleij <linus.walleij@stericsson.com> | 2009-08-14 05:59:05 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2009-08-15 10:36:29 -0400 |
commit | c7c8c78fdf6e9bd65d8ee879115dc2cd5d9fd0dc (patch) | |
tree | 91f59159fed1c22277c72e2529317561778657b9 | |
parent | df1e0520f9434b5b771c854a13dd928727d8673a (diff) |
ARM: 5667/3: U300 SSP/SPI board setup and test
This adds a U300 board configuration for the PL022 SSP/SPI
PrimeCell driver recently merged to the 2.6.31-rc series.
Further it adds a dummy loopback SPI chip that can be used
for testing the SPI functionality on a running system using
the loopback mode of PL022.
Signed-off-by: Linus Walleij <linus.walleij@stericsson.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r-- | arch/arm/mach-u300/Kconfig | 12 | ||||
-rw-r--r-- | arch/arm/mach-u300/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/mach-u300/core.c | 6 | ||||
-rw-r--r-- | arch/arm/mach-u300/dummyspichip.c | 290 | ||||
-rw-r--r-- | arch/arm/mach-u300/spi.c | 124 | ||||
-rw-r--r-- | arch/arm/mach-u300/spi.h | 26 |
6 files changed, 460 insertions, 0 deletions
diff --git a/arch/arm/mach-u300/Kconfig b/arch/arm/mach-u300/Kconfig index 337b9aabce49..801b21e7f677 100644 --- a/arch/arm/mach-u300/Kconfig +++ b/arch/arm/mach-u300/Kconfig | |||
@@ -81,6 +81,18 @@ config MACH_U300_SEMI_IS_SHARED | |||
81 | Memory Interface) from both from access and application | 81 | Memory Interface) from both from access and application |
82 | side. | 82 | side. |
83 | 83 | ||
84 | config MACH_U300_SPIDUMMY | ||
85 | bool "SSP/SPI dummy chip" | ||
86 | select SPI | ||
87 | select SPI_MASTER | ||
88 | select SPI_PL022 | ||
89 | help | ||
90 | This creates a small kernel module that creates a dummy | ||
91 | SPI device to be used for loopback tests. Regularly used | ||
92 | to test reference designs. If you're not testing SPI, | ||
93 | you don't need it. Selecting this will activate the | ||
94 | SPI framework and ARM PL022 support. | ||
95 | |||
84 | comment "All the settings below must match the bootloader's settings" | 96 | comment "All the settings below must match the bootloader's settings" |
85 | 97 | ||
86 | config MACH_U300_ACCESS_MEM_SIZE | 98 | config MACH_U300_ACCESS_MEM_SIZE |
diff --git a/arch/arm/mach-u300/Makefile b/arch/arm/mach-u300/Makefile index 24950e0df4b4..4941f89ea798 100644 --- a/arch/arm/mach-u300/Makefile +++ b/arch/arm/mach-u300/Makefile | |||
@@ -9,3 +9,5 @@ obj- := | |||
9 | 9 | ||
10 | obj-$(CONFIG_ARCH_U300) += u300.o | 10 | obj-$(CONFIG_ARCH_U300) += u300.o |
11 | obj-$(CONFIG_MMC) += mmc.o | 11 | obj-$(CONFIG_MMC) += mmc.o |
12 | obj-$(CONFIG_SPI_PL022) += spi.o | ||
13 | obj-$(CONFIG_MACH_U300_SPIDUMMY) += dummyspichip.o | ||
diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c index 89b3ccf35e1b..38d08a1c25d0 100644 --- a/arch/arm/mach-u300/core.c +++ b/arch/arm/mach-u300/core.c | |||
@@ -32,6 +32,7 @@ | |||
32 | 32 | ||
33 | #include "clock.h" | 33 | #include "clock.h" |
34 | #include "mmc.h" | 34 | #include "mmc.h" |
35 | #include "spi.h" | ||
35 | 36 | ||
36 | /* | 37 | /* |
37 | * Static I/O mappings that are needed for booting the U300 platforms. The | 38 | * Static I/O mappings that are needed for booting the U300 platforms. The |
@@ -611,6 +612,8 @@ void __init u300_init_devices(void) | |||
611 | /* Wait for the PLL208 to lock if not locked in yet */ | 612 | /* Wait for the PLL208 to lock if not locked in yet */ |
612 | while (!(readw(U300_SYSCON_VBASE + U300_SYSCON_CSR) & | 613 | while (!(readw(U300_SYSCON_VBASE + U300_SYSCON_CSR) & |
613 | U300_SYSCON_CSR_PLL208_LOCK_IND)); | 614 | U300_SYSCON_CSR_PLL208_LOCK_IND)); |
615 | /* Initialize SPI device with some board specifics */ | ||
616 | u300_spi_init(&pl022_device); | ||
614 | 617 | ||
615 | /* Register the AMBA devices in the AMBA bus abstraction layer */ | 618 | /* Register the AMBA devices in the AMBA bus abstraction layer */ |
616 | u300_clock_primecells(); | 619 | u300_clock_primecells(); |
@@ -622,6 +625,9 @@ void __init u300_init_devices(void) | |||
622 | 625 | ||
623 | u300_assign_physmem(); | 626 | u300_assign_physmem(); |
624 | 627 | ||
628 | /* Register subdevices on the SPI bus */ | ||
629 | u300_spi_register_board_devices(); | ||
630 | |||
625 | /* Register the platform devices */ | 631 | /* Register the platform devices */ |
626 | platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs)); | 632 | platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs)); |
627 | 633 | ||
diff --git a/arch/arm/mach-u300/dummyspichip.c b/arch/arm/mach-u300/dummyspichip.c new file mode 100644 index 000000000000..962f9de454de --- /dev/null +++ b/arch/arm/mach-u300/dummyspichip.c | |||
@@ -0,0 +1,290 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-u300/dummyspichip.c | ||
3 | * | ||
4 | * Copyright (C) 2007-2009 ST-Ericsson AB | ||
5 | * License terms: GNU General Public License (GPL) version 2 | ||
6 | * This is a dummy loopback SPI "chip" used for testing SPI. | ||
7 | * Author: Linus Walleij <linus.walleij@stericsson.com> | ||
8 | */ | ||
9 | #include <linux/init.h> | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/device.h> | ||
13 | #include <linux/err.h> | ||
14 | #include <linux/sysfs.h> | ||
15 | #include <linux/mutex.h> | ||
16 | #include <linux/spi/spi.h> | ||
17 | #include <linux/dma-mapping.h> | ||
18 | /* | ||
19 | * WARNING! Do not include this pl022-specific controller header | ||
20 | * for any generic driver. It is only done in this dummy chip | ||
21 | * because we alter the chip configuration in order to test some | ||
22 | * different settings on the loopback device. Normal chip configs | ||
23 | * shall be STATIC and not altered by the driver! | ||
24 | */ | ||
25 | #include <linux/amba/pl022.h> | ||
26 | |||
27 | struct dummy { | ||
28 | struct device *dev; | ||
29 | struct mutex lock; | ||
30 | }; | ||
31 | |||
32 | #define DMA_TEST_SIZE 2048 | ||
33 | |||
34 | /* When we cat /sys/bus/spi/devices/spi0.0/looptest this will be triggered */ | ||
35 | static ssize_t dummy_looptest(struct device *dev, | ||
36 | struct device_attribute *attr, char *buf) | ||
37 | { | ||
38 | struct spi_device *spi = to_spi_device(dev); | ||
39 | struct dummy *p_dummy = dev_get_drvdata(&spi->dev); | ||
40 | |||
41 | /* | ||
42 | * WARNING! Do not dereference the chip-specific data in any normal | ||
43 | * driver for a chip. It is usually STATIC and shall not be read | ||
44 | * or written to. Your chip driver should NOT depend on fields in this | ||
45 | * struct, this is just used here to alter the behaviour of the chip | ||
46 | * in order to perform tests. | ||
47 | */ | ||
48 | struct pl022_config_chip *chip_info = spi->controller_data; | ||
49 | int status; | ||
50 | u8 txbuf[14] = {0xDE, 0xAD, 0xBE, 0xEF, 0x2B, 0xAD, | ||
51 | 0xCA, 0xFE, 0xBA, 0xBE, 0xB1, 0x05, | ||
52 | 0xF0, 0x0D}; | ||
53 | u8 rxbuf[14]; | ||
54 | u8 *bigtxbuf_virtual; | ||
55 | u8 *bigrxbuf_virtual; | ||
56 | |||
57 | if (mutex_lock_interruptible(&p_dummy->lock)) | ||
58 | return -ERESTARTSYS; | ||
59 | |||
60 | bigtxbuf_virtual = kmalloc(DMA_TEST_SIZE, GFP_KERNEL); | ||
61 | if (bigtxbuf_virtual == NULL) { | ||
62 | status = -ENOMEM; | ||
63 | goto out; | ||
64 | } | ||
65 | bigrxbuf_virtual = kmalloc(DMA_TEST_SIZE, GFP_KERNEL); | ||
66 | |||
67 | /* Fill TXBUF with some happy pattern */ | ||
68 | memset(bigtxbuf_virtual, 0xAA, DMA_TEST_SIZE); | ||
69 | |||
70 | /* | ||
71 | * Force chip to 8 bit mode | ||
72 | * WARNING: NEVER DO THIS IN REAL DRIVER CODE, THIS SHOULD BE STATIC! | ||
73 | */ | ||
74 | chip_info->data_size = SSP_DATA_BITS_8; | ||
75 | /* You should NOT DO THIS EITHER */ | ||
76 | spi->master->setup(spi); | ||
77 | |||
78 | /* Now run the tests for 8bit mode */ | ||
79 | pr_info("Simple test 1: write 0xAA byte, read back garbage byte " | ||
80 | "in 8bit mode\n"); | ||
81 | status = spi_w8r8(spi, 0xAA); | ||
82 | if (status < 0) | ||
83 | pr_warning("Siple test 1: FAILURE: spi_write_then_read " | ||
84 | "failed with status %d\n", status); | ||
85 | else | ||
86 | pr_info("Simple test 1: SUCCESS!\n"); | ||
87 | |||
88 | pr_info("Simple test 2: write 8 bytes, read back 8 bytes garbage " | ||
89 | "in 8bit mode (full FIFO)\n"); | ||
90 | status = spi_write_then_read(spi, &txbuf[0], 8, &rxbuf[0], 8); | ||
91 | if (status < 0) | ||
92 | pr_warning("Simple test 2: FAILURE: spi_write_then_read() " | ||
93 | "failed with status %d\n", status); | ||
94 | else | ||
95 | pr_info("Simple test 2: SUCCESS!\n"); | ||
96 | |||
97 | pr_info("Simple test 3: write 14 bytes, read back 14 bytes garbage " | ||
98 | "in 8bit mode (see if we overflow FIFO)\n"); | ||
99 | status = spi_write_then_read(spi, &txbuf[0], 14, &rxbuf[0], 14); | ||
100 | if (status < 0) | ||
101 | pr_warning("Simple test 3: FAILURE: failed with status %d " | ||
102 | "(probably FIFO overrun)\n", status); | ||
103 | else | ||
104 | pr_info("Simple test 3: SUCCESS!\n"); | ||
105 | |||
106 | pr_info("Simple test 4: write 8 bytes with spi_write(), read 8 " | ||
107 | "bytes garbage with spi_read() in 8bit mode\n"); | ||
108 | status = spi_write(spi, &txbuf[0], 8); | ||
109 | if (status < 0) | ||
110 | pr_warning("Simple test 4 step 1: FAILURE: spi_write() " | ||
111 | "failed with status %d\n", status); | ||
112 | else | ||
113 | pr_info("Simple test 4 step 1: SUCCESS!\n"); | ||
114 | status = spi_read(spi, &rxbuf[0], 8); | ||
115 | if (status < 0) | ||
116 | pr_warning("Simple test 4 step 2: FAILURE: spi_read() " | ||
117 | "failed with status %d\n", status); | ||
118 | else | ||
119 | pr_info("Simple test 4 step 2: SUCCESS!\n"); | ||
120 | |||
121 | pr_info("Simple test 5: write 14 bytes with spi_write(), read " | ||
122 | "14 bytes garbage with spi_read() in 8bit mode\n"); | ||
123 | status = spi_write(spi, &txbuf[0], 14); | ||
124 | if (status < 0) | ||
125 | pr_warning("Simple test 5 step 1: FAILURE: spi_write() " | ||
126 | "failed with status %d (probably FIFO overrun)\n", | ||
127 | status); | ||
128 | else | ||
129 | pr_info("Simple test 5 step 1: SUCCESS!\n"); | ||
130 | status = spi_read(spi, &rxbuf[0], 14); | ||
131 | if (status < 0) | ||
132 | pr_warning("Simple test 5 step 2: FAILURE: spi_read() " | ||
133 | "failed with status %d (probably FIFO overrun)\n", | ||
134 | status); | ||
135 | else | ||
136 | pr_info("Simple test 5: SUCCESS!\n"); | ||
137 | |||
138 | pr_info("Simple test 6: write %d bytes with spi_write(), " | ||
139 | "read %d bytes garbage with spi_read() in 8bit mode\n", | ||
140 | DMA_TEST_SIZE, DMA_TEST_SIZE); | ||
141 | status = spi_write(spi, &bigtxbuf_virtual[0], DMA_TEST_SIZE); | ||
142 | if (status < 0) | ||
143 | pr_warning("Simple test 6 step 1: FAILURE: spi_write() " | ||
144 | "failed with status %d (probably FIFO overrun)\n", | ||
145 | status); | ||
146 | else | ||
147 | pr_info("Simple test 6 step 1: SUCCESS!\n"); | ||
148 | status = spi_read(spi, &bigrxbuf_virtual[0], DMA_TEST_SIZE); | ||
149 | if (status < 0) | ||
150 | pr_warning("Simple test 6 step 2: FAILURE: spi_read() " | ||
151 | "failed with status %d (probably FIFO overrun)\n", | ||
152 | status); | ||
153 | else | ||
154 | pr_info("Simple test 6: SUCCESS!\n"); | ||
155 | |||
156 | |||
157 | /* | ||
158 | * Force chip to 16 bit mode | ||
159 | * WARNING: NEVER DO THIS IN REAL DRIVER CODE, THIS SHOULD BE STATIC! | ||
160 | */ | ||
161 | chip_info->data_size = SSP_DATA_BITS_16; | ||
162 | /* You should NOT DO THIS EITHER */ | ||
163 | spi->master->setup(spi); | ||
164 | |||
165 | pr_info("Simple test 7: write 0xAA byte, read back garbage byte " | ||
166 | "in 16bit bus mode\n"); | ||
167 | status = spi_w8r8(spi, 0xAA); | ||
168 | if (status == -EIO) | ||
169 | pr_info("Simple test 7: SUCCESS! (expected failure with " | ||
170 | "status EIO)\n"); | ||
171 | else if (status < 0) | ||
172 | pr_warning("Siple test 7: FAILURE: spi_write_then_read " | ||
173 | "failed with status %d\n", status); | ||
174 | else | ||
175 | pr_warning("Siple test 7: FAILURE: spi_write_then_read " | ||
176 | "succeeded but it was expected to fail!\n"); | ||
177 | |||
178 | pr_info("Simple test 8: write 8 bytes, read back 8 bytes garbage " | ||
179 | "in 16bit mode (full FIFO)\n"); | ||
180 | status = spi_write_then_read(spi, &txbuf[0], 8, &rxbuf[0], 8); | ||
181 | if (status < 0) | ||
182 | pr_warning("Simple test 8: FAILURE: spi_write_then_read() " | ||
183 | "failed with status %d\n", status); | ||
184 | else | ||
185 | pr_info("Simple test 8: SUCCESS!\n"); | ||
186 | |||
187 | pr_info("Simple test 9: write 14 bytes, read back 14 bytes garbage " | ||
188 | "in 16bit mode (see if we overflow FIFO)\n"); | ||
189 | status = spi_write_then_read(spi, &txbuf[0], 14, &rxbuf[0], 14); | ||
190 | if (status < 0) | ||
191 | pr_warning("Simple test 9: FAILURE: failed with status %d " | ||
192 | "(probably FIFO overrun)\n", status); | ||
193 | else | ||
194 | pr_info("Simple test 9: SUCCESS!\n"); | ||
195 | |||
196 | pr_info("Simple test 10: write %d bytes with spi_write(), " | ||
197 | "read %d bytes garbage with spi_read() in 16bit mode\n", | ||
198 | DMA_TEST_SIZE, DMA_TEST_SIZE); | ||
199 | status = spi_write(spi, &bigtxbuf_virtual[0], DMA_TEST_SIZE); | ||
200 | if (status < 0) | ||
201 | pr_warning("Simple test 10 step 1: FAILURE: spi_write() " | ||
202 | "failed with status %d (probably FIFO overrun)\n", | ||
203 | status); | ||
204 | else | ||
205 | pr_info("Simple test 10 step 1: SUCCESS!\n"); | ||
206 | |||
207 | status = spi_read(spi, &bigrxbuf_virtual[0], DMA_TEST_SIZE); | ||
208 | if (status < 0) | ||
209 | pr_warning("Simple test 10 step 2: FAILURE: spi_read() " | ||
210 | "failed with status %d (probably FIFO overrun)\n", | ||
211 | status); | ||
212 | else | ||
213 | pr_info("Simple test 10: SUCCESS!\n"); | ||
214 | |||
215 | status = sprintf(buf, "loop test complete\n"); | ||
216 | kfree(bigrxbuf_virtual); | ||
217 | kfree(bigtxbuf_virtual); | ||
218 | out: | ||
219 | mutex_unlock(&p_dummy->lock); | ||
220 | return status; | ||
221 | } | ||
222 | |||
223 | static DEVICE_ATTR(looptest, S_IRUGO, dummy_looptest, NULL); | ||
224 | |||
225 | static int __devinit pl022_dummy_probe(struct spi_device *spi) | ||
226 | { | ||
227 | struct dummy *p_dummy; | ||
228 | int status; | ||
229 | |||
230 | dev_info(&spi->dev, "probing dummy SPI device\n"); | ||
231 | |||
232 | p_dummy = kzalloc(sizeof *p_dummy, GFP_KERNEL); | ||
233 | if (!p_dummy) | ||
234 | return -ENOMEM; | ||
235 | |||
236 | dev_set_drvdata(&spi->dev, p_dummy); | ||
237 | mutex_init(&p_dummy->lock); | ||
238 | |||
239 | /* sysfs hook */ | ||
240 | status = device_create_file(&spi->dev, &dev_attr_looptest); | ||
241 | if (status) { | ||
242 | dev_dbg(&spi->dev, "device_create_file looptest failure.\n"); | ||
243 | goto out_dev_create_looptest_failed; | ||
244 | } | ||
245 | |||
246 | return 0; | ||
247 | |||
248 | out_dev_create_looptest_failed: | ||
249 | dev_set_drvdata(&spi->dev, NULL); | ||
250 | kfree(p_dummy); | ||
251 | return status; | ||
252 | } | ||
253 | |||
254 | static int __devexit pl022_dummy_remove(struct spi_device *spi) | ||
255 | { | ||
256 | struct dummy *p_dummy = dev_get_drvdata(&spi->dev); | ||
257 | |||
258 | dev_info(&spi->dev, "removing dummy SPI device\n"); | ||
259 | device_remove_file(&spi->dev, &dev_attr_looptest); | ||
260 | dev_set_drvdata(&spi->dev, NULL); | ||
261 | kfree(p_dummy); | ||
262 | |||
263 | return 0; | ||
264 | } | ||
265 | |||
266 | static struct spi_driver pl022_dummy_driver = { | ||
267 | .driver = { | ||
268 | .name = "spi-dummy", | ||
269 | .owner = THIS_MODULE, | ||
270 | }, | ||
271 | .probe = pl022_dummy_probe, | ||
272 | .remove = __devexit_p(pl022_dummy_remove), | ||
273 | }; | ||
274 | |||
275 | static int __init pl022_init_dummy(void) | ||
276 | { | ||
277 | return spi_register_driver(&pl022_dummy_driver); | ||
278 | } | ||
279 | |||
280 | static void __exit pl022_exit_dummy(void) | ||
281 | { | ||
282 | spi_unregister_driver(&pl022_dummy_driver); | ||
283 | } | ||
284 | |||
285 | module_init(pl022_init_dummy); | ||
286 | module_exit(pl022_exit_dummy); | ||
287 | |||
288 | MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>"); | ||
289 | MODULE_DESCRIPTION("PL022 SSP/SPI DUMMY Linux driver"); | ||
290 | MODULE_LICENSE("GPL"); | ||
diff --git a/arch/arm/mach-u300/spi.c b/arch/arm/mach-u300/spi.c new file mode 100644 index 000000000000..307d007ea7f3 --- /dev/null +++ b/arch/arm/mach-u300/spi.c | |||
@@ -0,0 +1,124 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-u300/spi.c | ||
3 | * | ||
4 | * Copyright (C) 2009 ST-Ericsson AB | ||
5 | * License terms: GNU General Public License (GPL) version 2 | ||
6 | * | ||
7 | * Author: Linus Walleij <linus.walleij@stericsson.com> | ||
8 | */ | ||
9 | #include <linux/device.h> | ||
10 | #include <linux/amba/bus.h> | ||
11 | #include <linux/spi/spi.h> | ||
12 | #include <linux/amba/pl022.h> | ||
13 | #include <linux/err.h> | ||
14 | #include "padmux.h" | ||
15 | |||
16 | /* | ||
17 | * The following is for the actual devices on the SSP/SPI bus | ||
18 | */ | ||
19 | #ifdef CONFIG_MACH_U300_SPIDUMMY | ||
20 | static void select_dummy_chip(u32 chipselect) | ||
21 | { | ||
22 | pr_debug("CORE: %s called with CS=0x%x (%s)\n", | ||
23 | __func__, | ||
24 | chipselect, | ||
25 | chipselect ? "unselect chip" : "select chip"); | ||
26 | /* | ||
27 | * Here you would write the chip select value to the GPIO pins if | ||
28 | * this was a real chip (but this is a loopback dummy). | ||
29 | */ | ||
30 | } | ||
31 | |||
32 | struct pl022_config_chip dummy_chip_info = { | ||
33 | /* Nominally this is LOOPBACK_DISABLED, but this is our dummy chip! */ | ||
34 | .lbm = LOOPBACK_ENABLED, | ||
35 | /* | ||
36 | * available POLLING_TRANSFER and INTERRUPT_TRANSFER, | ||
37 | * DMA_TRANSFER does not work | ||
38 | */ | ||
39 | .com_mode = INTERRUPT_TRANSFER, | ||
40 | .iface = SSP_INTERFACE_MOTOROLA_SPI, | ||
41 | /* We can only act as master but SSP_SLAVE is possible in theory */ | ||
42 | .hierarchy = SSP_MASTER, | ||
43 | /* 0 = drive TX even as slave, 1 = do not drive TX as slave */ | ||
44 | .slave_tx_disable = 0, | ||
45 | /* LSB first */ | ||
46 | .endian_tx = SSP_TX_LSB, | ||
47 | .endian_rx = SSP_RX_LSB, | ||
48 | .data_size = SSP_DATA_BITS_8, /* used to be 12 in some default */ | ||
49 | .rx_lev_trig = SSP_RX_1_OR_MORE_ELEM, | ||
50 | .tx_lev_trig = SSP_TX_1_OR_MORE_EMPTY_LOC, | ||
51 | .clk_phase = SSP_CLK_FALLING_EDGE, | ||
52 | .clk_pol = SSP_CLK_POL_IDLE_LOW, | ||
53 | .ctrl_len = SSP_BITS_12, | ||
54 | .wait_state = SSP_MWIRE_WAIT_ZERO, | ||
55 | .duplex = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX, | ||
56 | /* | ||
57 | * This is where you insert a call to a function to enable CS | ||
58 | * (usually GPIO) for a certain chip. | ||
59 | */ | ||
60 | .cs_control = select_dummy_chip, | ||
61 | }; | ||
62 | #endif | ||
63 | |||
64 | static struct spi_board_info u300_spi_devices[] = { | ||
65 | #ifdef CONFIG_MACH_U300_SPIDUMMY | ||
66 | { | ||
67 | /* A dummy chip used for loopback tests */ | ||
68 | .modalias = "spi-dummy", | ||
69 | /* Really dummy, pass in additional chip config here */ | ||
70 | .platform_data = NULL, | ||
71 | /* This defines how the controller shall handle the device */ | ||
72 | .controller_data = &dummy_chip_info, | ||
73 | /* .irq - no external IRQ routed from this device */ | ||
74 | .max_speed_hz = 1000000, | ||
75 | .bus_num = 0, /* Only one bus on this chip */ | ||
76 | .chip_select = 0, | ||
77 | /* Means SPI_CS_HIGH, change if e.g low CS */ | ||
78 | .mode = 0, | ||
79 | }, | ||
80 | #endif | ||
81 | }; | ||
82 | |||
83 | static struct pl022_ssp_controller ssp_platform_data = { | ||
84 | /* If you have several SPI buses this varies, we have only bus 0 */ | ||
85 | .bus_id = 0, | ||
86 | /* Set this to 1 when we think we got DMA working */ | ||
87 | .enable_dma = 0, | ||
88 | /* | ||
89 | * On the APP CPU GPIO 4, 5 and 6 are connected as generic | ||
90 | * chip selects for SPI. (Same on U330, U335 and U365.) | ||
91 | * TODO: make sure the GPIO driver can select these properly | ||
92 | * and do padmuxing accordingly too. | ||
93 | */ | ||
94 | .num_chipselect = 3, | ||
95 | }; | ||
96 | |||
97 | |||
98 | void __init u300_spi_init(struct amba_device *adev) | ||
99 | { | ||
100 | struct pmx *pmx; | ||
101 | |||
102 | adev->dev.platform_data = &ssp_platform_data; | ||
103 | /* | ||
104 | * Setup padmuxing for SPI. Since this must always be | ||
105 | * compiled into the kernel, pmx is never released. | ||
106 | */ | ||
107 | pmx = pmx_get(&adev->dev, U300_APP_PMX_SPI_SETTING); | ||
108 | |||
109 | if (IS_ERR(pmx)) | ||
110 | dev_warn(&adev->dev, "Could not get padmux handle\n"); | ||
111 | else { | ||
112 | int ret; | ||
113 | |||
114 | ret = pmx_activate(&adev->dev, pmx); | ||
115 | if (IS_ERR_VALUE(ret)) | ||
116 | dev_warn(&adev->dev, "Could not activate padmuxing\n"); | ||
117 | } | ||
118 | |||
119 | } | ||
120 | void __init u300_spi_register_board_devices(void) | ||
121 | { | ||
122 | /* Register any SPI devices */ | ||
123 | spi_register_board_info(u300_spi_devices, ARRAY_SIZE(u300_spi_devices)); | ||
124 | } | ||
diff --git a/arch/arm/mach-u300/spi.h b/arch/arm/mach-u300/spi.h new file mode 100644 index 000000000000..bd3d867e240f --- /dev/null +++ b/arch/arm/mach-u300/spi.h | |||
@@ -0,0 +1,26 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-u300/spi.h | ||
3 | * | ||
4 | * Copyright (C) 2009 ST-Ericsson AB | ||
5 | * License terms: GNU General Public License (GPL) version 2 | ||
6 | * | ||
7 | * Author: Linus Walleij <linus.walleij@stericsson.com> | ||
8 | */ | ||
9 | #ifndef SPI_H | ||
10 | #define SPI_H | ||
11 | #include <linux/amba/bus.h> | ||
12 | |||
13 | #ifdef CONFIG_SPI_PL022 | ||
14 | void __init u300_spi_init(struct amba_device *adev); | ||
15 | void __init u300_spi_register_board_devices(void); | ||
16 | #else | ||
17 | /* Compile out SPI support if PL022 is not selected */ | ||
18 | static inline void __init u300_spi_init(struct amba_device *adev) | ||
19 | { | ||
20 | } | ||
21 | static inline void __init u300_spi_register_board_devices(void) | ||
22 | { | ||
23 | } | ||
24 | #endif | ||
25 | |||
26 | #endif | ||