aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-u300/dummyspichip.c
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@stericsson.com>2009-08-14 05:59:05 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2009-08-15 10:36:29 -0400
commitc7c8c78fdf6e9bd65d8ee879115dc2cd5d9fd0dc (patch)
tree91f59159fed1c22277c72e2529317561778657b9 /arch/arm/mach-u300/dummyspichip.c
parentdf1e0520f9434b5b771c854a13dd928727d8673a (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>
Diffstat (limited to 'arch/arm/mach-u300/dummyspichip.c')
-rw-r--r--arch/arm/mach-u300/dummyspichip.c290
1 files changed, 290 insertions, 0 deletions
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
27struct 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 */
35static 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
223static DEVICE_ATTR(looptest, S_IRUGO, dummy_looptest, NULL);
224
225static 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
248out_dev_create_looptest_failed:
249 dev_set_drvdata(&spi->dev, NULL);
250 kfree(p_dummy);
251 return status;
252}
253
254static 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
266static 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
275static int __init pl022_init_dummy(void)
276{
277 return spi_register_driver(&pl022_dummy_driver);
278}
279
280static void __exit pl022_exit_dummy(void)
281{
282 spi_unregister_driver(&pl022_dummy_driver);
283}
284
285module_init(pl022_init_dummy);
286module_exit(pl022_exit_dummy);
287
288MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>");
289MODULE_DESCRIPTION("PL022 SSP/SPI DUMMY Linux driver");
290MODULE_LICENSE("GPL");