diff options
author | Colin McCabe <colin@cozybit.com> | 2009-01-09 17:58:09 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-01-29 16:00:19 -0500 |
commit | d2b21f191753abd12c4063776cb1a3d635397509 (patch) | |
tree | a31c00ffff1cc05e5ec00a048e3de4e0dc3f54be | |
parent | 3cd08b383b2efe163272045afc415c75afc9e9c5 (diff) |
libertas: if_spi, driver for libertas GSPI devices
Add initial support for libertas devices using a GSPI interface. This has
been tested with the 8686.
GSPI is intended to be used on embedded systems. Board-specific parameters are
required (see libertas_spi.h).
Thanks to everyone who took a look at the earlier versions of the patch.
Signed-off-by: Colin McCabe <colin@cozybit.com>
Signed-off-by: Andrey Yurovsky <andrey@cozybit.com>
Acked-by: Dan Williams <dcbw@redhat.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/Kconfig | 6 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/Makefile | 2 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/defs.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/if_spi.c | 1203 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/if_spi.h | 208 | ||||
-rw-r--r-- | include/linux/spi/libertas_spi.h | 25 |
6 files changed, 1446 insertions, 0 deletions
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index e4f9f747de88..2dddbd012a99 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig | |||
@@ -151,6 +151,12 @@ config LIBERTAS_SDIO | |||
151 | ---help--- | 151 | ---help--- |
152 | A driver for Marvell Libertas 8385 and 8686 SDIO devices. | 152 | A driver for Marvell Libertas 8385 and 8686 SDIO devices. |
153 | 153 | ||
154 | config LIBERTAS_SPI | ||
155 | tristate "Marvell Libertas 8686 SPI 802.11b/g cards" | ||
156 | depends on LIBERTAS && SPI && GENERIC_GPIO | ||
157 | ---help--- | ||
158 | A driver for Marvell Libertas 8686 SPI devices. | ||
159 | |||
154 | config LIBERTAS_DEBUG | 160 | config LIBERTAS_DEBUG |
155 | bool "Enable full debugging output in the Libertas module." | 161 | bool "Enable full debugging output in the Libertas module." |
156 | depends on LIBERTAS | 162 | depends on LIBERTAS |
diff --git a/drivers/net/wireless/libertas/Makefile b/drivers/net/wireless/libertas/Makefile index 02080a3682a9..0b6918584503 100644 --- a/drivers/net/wireless/libertas/Makefile +++ b/drivers/net/wireless/libertas/Makefile | |||
@@ -4,8 +4,10 @@ libertas-objs := main.o wext.o rx.o tx.o cmd.o cmdresp.o scan.o 11d.o \ | |||
4 | usb8xxx-objs += if_usb.o | 4 | usb8xxx-objs += if_usb.o |
5 | libertas_cs-objs += if_cs.o | 5 | libertas_cs-objs += if_cs.o |
6 | libertas_sdio-objs += if_sdio.o | 6 | libertas_sdio-objs += if_sdio.o |
7 | libertas_spi-objs += if_spi.o | ||
7 | 8 | ||
8 | obj-$(CONFIG_LIBERTAS) += libertas.o | 9 | obj-$(CONFIG_LIBERTAS) += libertas.o |
9 | obj-$(CONFIG_LIBERTAS_USB) += usb8xxx.o | 10 | obj-$(CONFIG_LIBERTAS_USB) += usb8xxx.o |
10 | obj-$(CONFIG_LIBERTAS_CS) += libertas_cs.o | 11 | obj-$(CONFIG_LIBERTAS_CS) += libertas_cs.o |
11 | obj-$(CONFIG_LIBERTAS_SDIO) += libertas_sdio.o | 12 | obj-$(CONFIG_LIBERTAS_SDIO) += libertas_sdio.o |
13 | obj-$(CONFIG_LIBERTAS_SPI) += libertas_spi.o | ||
diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h index c364e4c01d1b..6388b05df4fc 100644 --- a/drivers/net/wireless/libertas/defs.h +++ b/drivers/net/wireless/libertas/defs.h | |||
@@ -41,6 +41,7 @@ | |||
41 | #define LBS_DEB_HEX 0x00200000 | 41 | #define LBS_DEB_HEX 0x00200000 |
42 | #define LBS_DEB_SDIO 0x00400000 | 42 | #define LBS_DEB_SDIO 0x00400000 |
43 | #define LBS_DEB_SYSFS 0x00800000 | 43 | #define LBS_DEB_SYSFS 0x00800000 |
44 | #define LBS_DEB_SPI 0x01000000 | ||
44 | 45 | ||
45 | extern unsigned int lbs_debug; | 46 | extern unsigned int lbs_debug; |
46 | 47 | ||
@@ -84,6 +85,7 @@ do { if ((lbs_debug & (grp)) == (grp)) \ | |||
84 | #define lbs_deb_thread(fmt, args...) LBS_DEB_LL(LBS_DEB_THREAD, " thread", fmt, ##args) | 85 | #define lbs_deb_thread(fmt, args...) LBS_DEB_LL(LBS_DEB_THREAD, " thread", fmt, ##args) |
85 | #define lbs_deb_sdio(fmt, args...) LBS_DEB_LL(LBS_DEB_SDIO, " sdio", fmt, ##args) | 86 | #define lbs_deb_sdio(fmt, args...) LBS_DEB_LL(LBS_DEB_SDIO, " sdio", fmt, ##args) |
86 | #define lbs_deb_sysfs(fmt, args...) LBS_DEB_LL(LBS_DEB_SYSFS, " sysfs", fmt, ##args) | 87 | #define lbs_deb_sysfs(fmt, args...) LBS_DEB_LL(LBS_DEB_SYSFS, " sysfs", fmt, ##args) |
88 | #define lbs_deb_spi(fmt, args...) LBS_DEB_LL(LBS_DEB_SPI, " spi", fmt, ##args) | ||
87 | 89 | ||
88 | #define lbs_pr_info(format, args...) \ | 90 | #define lbs_pr_info(format, args...) \ |
89 | printk(KERN_INFO DRV_NAME": " format, ## args) | 91 | printk(KERN_INFO DRV_NAME": " format, ## args) |
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c new file mode 100644 index 000000000000..7c02ea314fd1 --- /dev/null +++ b/drivers/net/wireless/libertas/if_spi.c | |||
@@ -0,0 +1,1203 @@ | |||
1 | /* | ||
2 | * linux/drivers/net/wireless/libertas/if_spi.c | ||
3 | * | ||
4 | * Driver for Marvell SPI WLAN cards. | ||
5 | * | ||
6 | * Copyright 2008 Analog Devices Inc. | ||
7 | * | ||
8 | * Authors: | ||
9 | * Andrey Yurovsky <andrey@cozybit.com> | ||
10 | * Colin McCabe <colin@cozybit.com> | ||
11 | * | ||
12 | * Inspired by if_sdio.c, Copyright 2007-2008 Pierre Ossman | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License as published by | ||
16 | * the Free Software Foundation; either version 2 of the License, or | ||
17 | * (at your option) any later version. | ||
18 | */ | ||
19 | |||
20 | #include <linux/moduleparam.h> | ||
21 | #include <linux/firmware.h> | ||
22 | #include <linux/gpio.h> | ||
23 | #include <linux/jiffies.h> | ||
24 | #include <linux/kthread.h> | ||
25 | #include <linux/list.h> | ||
26 | #include <linux/netdevice.h> | ||
27 | #include <linux/spi/libertas_spi.h> | ||
28 | #include <linux/spi/spi.h> | ||
29 | |||
30 | #include "host.h" | ||
31 | #include "decl.h" | ||
32 | #include "defs.h" | ||
33 | #include "dev.h" | ||
34 | #include "if_spi.h" | ||
35 | |||
36 | struct if_spi_packet { | ||
37 | struct list_head list; | ||
38 | u16 blen; | ||
39 | u8 buffer[0] __attribute__((aligned(4))); | ||
40 | }; | ||
41 | |||
42 | struct if_spi_card { | ||
43 | struct spi_device *spi; | ||
44 | struct lbs_private *priv; | ||
45 | |||
46 | char helper_fw_name[FIRMWARE_NAME_MAX]; | ||
47 | char main_fw_name[FIRMWARE_NAME_MAX]; | ||
48 | |||
49 | /* The card ID and card revision, as reported by the hardware. */ | ||
50 | u16 card_id; | ||
51 | u8 card_rev; | ||
52 | |||
53 | /* Pin number for our GPIO chip-select. */ | ||
54 | /* TODO: Once the generic SPI layer has some additional features, we | ||
55 | * should take this out and use the normal chip select here. | ||
56 | * We need support for chip select delays, and not dropping chipselect | ||
57 | * after each word. */ | ||
58 | int gpio_cs; | ||
59 | |||
60 | /* The last time that we initiated an SPU operation */ | ||
61 | unsigned long prev_xfer_time; | ||
62 | |||
63 | int use_dummy_writes; | ||
64 | unsigned long spu_port_delay; | ||
65 | unsigned long spu_reg_delay; | ||
66 | |||
67 | /* Handles all SPI communication (except for FW load) */ | ||
68 | struct task_struct *spi_thread; | ||
69 | int run_thread; | ||
70 | |||
71 | /* Used to wake up the spi_thread */ | ||
72 | struct semaphore spi_ready; | ||
73 | struct semaphore spi_thread_terminated; | ||
74 | |||
75 | u8 cmd_buffer[IF_SPI_CMD_BUF_SIZE]; | ||
76 | |||
77 | /* A buffer of incoming packets from libertas core. | ||
78 | * Since we can't sleep in hw_host_to_card, we have to buffer | ||
79 | * them. */ | ||
80 | struct list_head cmd_packet_list; | ||
81 | struct list_head data_packet_list; | ||
82 | |||
83 | /* Protects cmd_packet_list and data_packet_list */ | ||
84 | spinlock_t buffer_lock; | ||
85 | }; | ||
86 | |||
87 | static void free_if_spi_card(struct if_spi_card *card) | ||
88 | { | ||
89 | struct list_head *cursor, *next; | ||
90 | struct if_spi_packet *packet; | ||
91 | |||
92 | BUG_ON(card->run_thread); | ||
93 | list_for_each_safe(cursor, next, &card->cmd_packet_list) { | ||
94 | packet = container_of(cursor, struct if_spi_packet, list); | ||
95 | list_del(&packet->list); | ||
96 | kfree(packet); | ||
97 | } | ||
98 | list_for_each_safe(cursor, next, &card->data_packet_list) { | ||
99 | packet = container_of(cursor, struct if_spi_packet, list); | ||
100 | list_del(&packet->list); | ||
101 | kfree(packet); | ||
102 | } | ||
103 | spi_set_drvdata(card->spi, NULL); | ||
104 | kfree(card); | ||
105 | } | ||
106 | |||
107 | static struct chip_ident chip_id_to_device_name[] = { | ||
108 | { .chip_id = 0x04, .name = 8385 }, | ||
109 | { .chip_id = 0x0b, .name = 8686 }, | ||
110 | }; | ||
111 | |||
112 | /* | ||
113 | * SPI Interface Unit Routines | ||
114 | * | ||
115 | * The SPU sits between the host and the WLAN module. | ||
116 | * All communication with the firmware is through SPU transactions. | ||
117 | * | ||
118 | * First we have to put a SPU register name on the bus. Then we can | ||
119 | * either read from or write to that register. | ||
120 | * | ||
121 | * For 16-bit transactions, byte order on the bus is big-endian. | ||
122 | * We don't have to worry about that here, though. | ||
123 | * The translation takes place in the SPI routines. | ||
124 | */ | ||
125 | |||
126 | static void spu_transaction_init(struct if_spi_card *card) | ||
127 | { | ||
128 | if (!time_after(jiffies, card->prev_xfer_time + 1)) { | ||
129 | /* Unfortunately, the SPU requires a delay between successive | ||
130 | * transactions. If our last transaction was more than a jiffy | ||
131 | * ago, we have obviously already delayed enough. | ||
132 | * If not, we have to busy-wait to be on the safe side. */ | ||
133 | ndelay(400); | ||
134 | } | ||
135 | gpio_set_value(card->gpio_cs, 0); /* assert CS */ | ||
136 | } | ||
137 | |||
138 | static void spu_transaction_finish(struct if_spi_card *card) | ||
139 | { | ||
140 | gpio_set_value(card->gpio_cs, 1); /* drop CS */ | ||
141 | card->prev_xfer_time = jiffies; | ||
142 | } | ||
143 | |||
144 | /* Write out a byte buffer to an SPI register, | ||
145 | * using a series of 16-bit transfers. */ | ||
146 | static int spu_write(struct if_spi_card *card, u16 reg, const u8 *buf, int len) | ||
147 | { | ||
148 | int err = 0; | ||
149 | u16 reg_out = reg | IF_SPI_WRITE_OPERATION_MASK; | ||
150 | |||
151 | /* You must give an even number of bytes to the SPU, even if it | ||
152 | * doesn't care about the last one. */ | ||
153 | BUG_ON(len & 0x1); | ||
154 | |||
155 | spu_transaction_init(card); | ||
156 | |||
157 | /* write SPU register index */ | ||
158 | err = spi_write(card->spi, (u8 *)®_out, sizeof(u16)); | ||
159 | if (err) | ||
160 | goto out; | ||
161 | |||
162 | err = spi_write(card->spi, buf, len); | ||
163 | |||
164 | out: | ||
165 | spu_transaction_finish(card); | ||
166 | return err; | ||
167 | } | ||
168 | |||
169 | static inline int spu_write_u16(struct if_spi_card *card, u16 reg, u16 val) | ||
170 | { | ||
171 | return spu_write(card, reg, (u8 *)&val, sizeof(u16)); | ||
172 | } | ||
173 | |||
174 | static inline int spu_write_u32(struct if_spi_card *card, u16 reg, u32 val) | ||
175 | { | ||
176 | /* The lower 16 bits are written first. */ | ||
177 | u16 out[2]; | ||
178 | out[0] = val & 0xffff; | ||
179 | out[1] = (val & 0xffff0000) >> 16; | ||
180 | return spu_write(card, reg, (u8 *)&out, sizeof(u32)); | ||
181 | } | ||
182 | |||
183 | static inline int spu_reg_is_port_reg(u16 reg) | ||
184 | { | ||
185 | switch (reg) { | ||
186 | case IF_SPI_IO_RDWRPORT_REG: | ||
187 | case IF_SPI_CMD_RDWRPORT_REG: | ||
188 | case IF_SPI_DATA_RDWRPORT_REG: | ||
189 | return 1; | ||
190 | default: | ||
191 | return 0; | ||
192 | } | ||
193 | } | ||
194 | |||
195 | static int spu_read(struct if_spi_card *card, u16 reg, u8 *buf, int len) | ||
196 | { | ||
197 | unsigned int i, delay; | ||
198 | int err = 0; | ||
199 | u16 zero = 0; | ||
200 | u16 reg_out = reg | IF_SPI_READ_OPERATION_MASK; | ||
201 | |||
202 | /* You must take an even number of bytes from the SPU, even if you | ||
203 | * don't care about the last one. */ | ||
204 | BUG_ON(len & 0x1); | ||
205 | |||
206 | spu_transaction_init(card); | ||
207 | |||
208 | /* write SPU register index */ | ||
209 | err = spi_write(card->spi, (u8 *)®_out, sizeof(u16)); | ||
210 | if (err) | ||
211 | goto out; | ||
212 | |||
213 | delay = spu_reg_is_port_reg(reg) ? card->spu_port_delay : | ||
214 | card->spu_reg_delay; | ||
215 | if (card->use_dummy_writes) { | ||
216 | /* Clock in dummy cycles while the SPU fills the FIFO */ | ||
217 | for (i = 0; i < delay / 16; ++i) { | ||
218 | err = spi_write(card->spi, (u8 *)&zero, sizeof(u16)); | ||
219 | if (err) | ||
220 | return err; | ||
221 | } | ||
222 | } else { | ||
223 | /* Busy-wait while the SPU fills the FIFO */ | ||
224 | ndelay(100 + (delay * 10)); | ||
225 | } | ||
226 | |||
227 | /* read in data */ | ||
228 | err = spi_read(card->spi, buf, len); | ||
229 | |||
230 | out: | ||
231 | spu_transaction_finish(card); | ||
232 | return err; | ||
233 | } | ||
234 | |||
235 | /* Read 16 bits from an SPI register */ | ||
236 | static inline int spu_read_u16(struct if_spi_card *card, u16 reg, u16 *val) | ||
237 | { | ||
238 | return spu_read(card, reg, (u8 *)val, sizeof(u16)); | ||
239 | } | ||
240 | |||
241 | /* Read 32 bits from an SPI register. | ||
242 | * The low 16 bits are read first. */ | ||
243 | static int spu_read_u32(struct if_spi_card *card, u16 reg, u32 *val) | ||
244 | { | ||
245 | u16 buf[2]; | ||
246 | int err; | ||
247 | err = spu_read(card, reg, (u8 *)buf, sizeof(u32)); | ||
248 | if (!err) | ||
249 | *val = buf[0] | (buf[1] << 16); | ||
250 | return err; | ||
251 | } | ||
252 | |||
253 | /* Keep reading 16 bits from an SPI register until you get the correct result. | ||
254 | * | ||
255 | * If mask = 0, the correct result is any non-zero number. | ||
256 | * If mask != 0, the correct result is any number where | ||
257 | * number & target_mask == target | ||
258 | * | ||
259 | * Returns -ETIMEDOUT if a second passes without the correct result. */ | ||
260 | static int spu_wait_for_u16(struct if_spi_card *card, u16 reg, | ||
261 | u16 target_mask, u16 target) | ||
262 | { | ||
263 | int err; | ||
264 | unsigned long timeout = jiffies + 5*HZ; | ||
265 | while (1) { | ||
266 | u16 val; | ||
267 | err = spu_read_u16(card, reg, &val); | ||
268 | if (err) | ||
269 | return err; | ||
270 | if (target_mask) { | ||
271 | if ((val & target_mask) == target) | ||
272 | return 0; | ||
273 | } else { | ||
274 | if (val) | ||
275 | return 0; | ||
276 | } | ||
277 | udelay(100); | ||
278 | if (time_after(jiffies, timeout)) { | ||
279 | lbs_pr_err("%s: timeout with val=%02x, " | ||
280 | "target_mask=%02x, target=%02x\n", | ||
281 | __func__, val, target_mask, target); | ||
282 | return -ETIMEDOUT; | ||
283 | } | ||
284 | } | ||
285 | } | ||
286 | |||
287 | /* Read 16 bits from an SPI register until you receive a specific value. | ||
288 | * Returns -ETIMEDOUT if a 4 tries pass without success. */ | ||
289 | static int spu_wait_for_u32(struct if_spi_card *card, u32 reg, u32 target) | ||
290 | { | ||
291 | int err, try; | ||
292 | for (try = 0; try < 4; ++try) { | ||
293 | u32 val = 0; | ||
294 | err = spu_read_u32(card, reg, &val); | ||
295 | if (err) | ||
296 | return err; | ||
297 | if (val == target) | ||
298 | return 0; | ||
299 | mdelay(100); | ||
300 | } | ||
301 | return -ETIMEDOUT; | ||
302 | } | ||
303 | |||
304 | static int spu_set_interrupt_mode(struct if_spi_card *card, | ||
305 | int suppress_host_int, | ||
306 | int auto_int) | ||
307 | { | ||
308 | int err = 0; | ||
309 | |||
310 | /* We can suppress a host interrupt by clearing the appropriate | ||
311 | * bit in the "host interrupt status mask" register */ | ||
312 | if (suppress_host_int) { | ||
313 | err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_MASK_REG, 0); | ||
314 | if (err) | ||
315 | return err; | ||
316 | } else { | ||
317 | err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_MASK_REG, | ||
318 | IF_SPI_HISM_TX_DOWNLOAD_RDY | | ||
319 | IF_SPI_HISM_RX_UPLOAD_RDY | | ||
320 | IF_SPI_HISM_CMD_DOWNLOAD_RDY | | ||
321 | IF_SPI_HISM_CARDEVENT | | ||
322 | IF_SPI_HISM_CMD_UPLOAD_RDY); | ||
323 | if (err) | ||
324 | return err; | ||
325 | } | ||
326 | |||
327 | /* If auto-interrupts are on, the completion of certain transactions | ||
328 | * will trigger an interrupt automatically. If auto-interrupts | ||
329 | * are off, we need to set the "Card Interrupt Cause" register to | ||
330 | * trigger a card interrupt. */ | ||
331 | if (auto_int) { | ||
332 | err = spu_write_u16(card, IF_SPI_HOST_INT_CTRL_REG, | ||
333 | IF_SPI_HICT_TX_DOWNLOAD_OVER_AUTO | | ||
334 | IF_SPI_HICT_RX_UPLOAD_OVER_AUTO | | ||
335 | IF_SPI_HICT_CMD_DOWNLOAD_OVER_AUTO | | ||
336 | IF_SPI_HICT_CMD_UPLOAD_OVER_AUTO); | ||
337 | if (err) | ||
338 | return err; | ||
339 | } else { | ||
340 | err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_MASK_REG, 0); | ||
341 | if (err) | ||
342 | return err; | ||
343 | } | ||
344 | return err; | ||
345 | } | ||
346 | |||
347 | static int spu_get_chip_revision(struct if_spi_card *card, | ||
348 | u16 *card_id, u8 *card_rev) | ||
349 | { | ||
350 | int err = 0; | ||
351 | u32 dev_ctrl; | ||
352 | err = spu_read_u32(card, IF_SPI_DEVICEID_CTRL_REG, &dev_ctrl); | ||
353 | if (err) | ||
354 | return err; | ||
355 | *card_id = IF_SPI_DEVICEID_CTRL_REG_TO_CARD_ID(dev_ctrl); | ||
356 | *card_rev = IF_SPI_DEVICEID_CTRL_REG_TO_CARD_REV(dev_ctrl); | ||
357 | return err; | ||
358 | } | ||
359 | |||
360 | static int spu_set_bus_mode(struct if_spi_card *card, u16 mode) | ||
361 | { | ||
362 | int err = 0; | ||
363 | u16 rval; | ||
364 | /* set bus mode */ | ||
365 | err = spu_write_u16(card, IF_SPI_SPU_BUS_MODE_REG, mode); | ||
366 | if (err) | ||
367 | return err; | ||
368 | /* Check that we were able to read back what we just wrote. */ | ||
369 | err = spu_read_u16(card, IF_SPI_SPU_BUS_MODE_REG, &rval); | ||
370 | if (err) | ||
371 | return err; | ||
372 | if (rval != mode) { | ||
373 | lbs_pr_err("Can't read bus mode register.\n"); | ||
374 | return -EIO; | ||
375 | } | ||
376 | return 0; | ||
377 | } | ||
378 | |||
379 | static int spu_init(struct if_spi_card *card, int use_dummy_writes) | ||
380 | { | ||
381 | int err = 0; | ||
382 | u32 delay; | ||
383 | |||
384 | /* We have to start up in timed delay mode so that we can safely | ||
385 | * read the Delay Read Register. */ | ||
386 | card->use_dummy_writes = 0; | ||
387 | err = spu_set_bus_mode(card, | ||
388 | IF_SPI_BUS_MODE_SPI_CLOCK_PHASE_RISING | | ||
389 | IF_SPI_BUS_MODE_DELAY_METHOD_TIMED | | ||
390 | IF_SPI_BUS_MODE_16_BIT_ADDRESS_16_BIT_DATA); | ||
391 | if (err) | ||
392 | return err; | ||
393 | card->spu_port_delay = 1000; | ||
394 | card->spu_reg_delay = 1000; | ||
395 | err = spu_read_u32(card, IF_SPI_DELAY_READ_REG, &delay); | ||
396 | if (err) | ||
397 | return err; | ||
398 | card->spu_port_delay = delay & 0x0000ffff; | ||
399 | card->spu_reg_delay = (delay & 0xffff0000) >> 16; | ||
400 | |||
401 | /* If dummy clock delay mode has been requested, switch to it now */ | ||
402 | if (use_dummy_writes) { | ||
403 | card->use_dummy_writes = 1; | ||
404 | err = spu_set_bus_mode(card, | ||
405 | IF_SPI_BUS_MODE_SPI_CLOCK_PHASE_RISING | | ||
406 | IF_SPI_BUS_MODE_DELAY_METHOD_DUMMY_CLOCK | | ||
407 | IF_SPI_BUS_MODE_16_BIT_ADDRESS_16_BIT_DATA); | ||
408 | if (err) | ||
409 | return err; | ||
410 | } | ||
411 | |||
412 | lbs_deb_spi("Initialized SPU unit. " | ||
413 | "spu_port_delay=0x%04lx, spu_reg_delay=0x%04lx\n", | ||
414 | card->spu_port_delay, card->spu_reg_delay); | ||
415 | return err; | ||
416 | } | ||
417 | |||
418 | /* | ||
419 | * Firmware Loading | ||
420 | */ | ||
421 | |||
422 | static int if_spi_prog_helper_firmware(struct if_spi_card *card) | ||
423 | { | ||
424 | int err = 0; | ||
425 | const struct firmware *firmware = NULL; | ||
426 | int bytes_remaining; | ||
427 | const u8 *fw; | ||
428 | u8 temp[HELPER_FW_LOAD_CHUNK_SZ]; | ||
429 | struct spi_device *spi = card->spi; | ||
430 | |||
431 | lbs_deb_enter(LBS_DEB_SPI); | ||
432 | |||
433 | err = spu_set_interrupt_mode(card, 1, 0); | ||
434 | if (err) | ||
435 | goto out; | ||
436 | /* Get helper firmware image */ | ||
437 | err = request_firmware(&firmware, card->helper_fw_name, &spi->dev); | ||
438 | if (err) { | ||
439 | lbs_pr_err("request_firmware failed with err = %d\n", err); | ||
440 | goto out; | ||
441 | } | ||
442 | bytes_remaining = firmware->size; | ||
443 | fw = firmware->data; | ||
444 | |||
445 | /* Load helper firmware image */ | ||
446 | while (bytes_remaining > 0) { | ||
447 | /* Scratch pad 1 should contain the number of bytes we | ||
448 | * want to download to the firmware */ | ||
449 | err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG, | ||
450 | HELPER_FW_LOAD_CHUNK_SZ); | ||
451 | if (err) | ||
452 | goto release_firmware; | ||
453 | |||
454 | err = spu_wait_for_u16(card, IF_SPI_HOST_INT_STATUS_REG, | ||
455 | IF_SPI_HIST_CMD_DOWNLOAD_RDY, | ||
456 | IF_SPI_HIST_CMD_DOWNLOAD_RDY); | ||
457 | if (err) | ||
458 | goto release_firmware; | ||
459 | |||
460 | /* Feed the data into the command read/write port reg | ||
461 | * in chunks of 64 bytes */ | ||
462 | memset(temp, 0, sizeof(temp)); | ||
463 | memcpy(temp, fw, | ||
464 | min(bytes_remaining, HELPER_FW_LOAD_CHUNK_SZ)); | ||
465 | mdelay(10); | ||
466 | err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG, | ||
467 | temp, HELPER_FW_LOAD_CHUNK_SZ); | ||
468 | if (err) | ||
469 | goto release_firmware; | ||
470 | |||
471 | /* Interrupt the boot code */ | ||
472 | err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0); | ||
473 | if (err) | ||
474 | goto release_firmware; | ||
475 | err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG, | ||
476 | IF_SPI_CIC_CMD_DOWNLOAD_OVER); | ||
477 | if (err) | ||
478 | goto release_firmware; | ||
479 | bytes_remaining -= HELPER_FW_LOAD_CHUNK_SZ; | ||
480 | fw += HELPER_FW_LOAD_CHUNK_SZ; | ||
481 | } | ||
482 | |||
483 | /* Once the helper / single stage firmware download is complete, | ||
484 | * write 0 to scratch pad 1 and interrupt the | ||
485 | * bootloader. This completes the helper download. */ | ||
486 | err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG, FIRMWARE_DNLD_OK); | ||
487 | if (err) | ||
488 | goto release_firmware; | ||
489 | err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0); | ||
490 | if (err) | ||
491 | goto release_firmware; | ||
492 | err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG, | ||
493 | IF_SPI_CIC_CMD_DOWNLOAD_OVER); | ||
494 | goto release_firmware; | ||
495 | |||
496 | lbs_deb_spi("waiting for helper to boot...\n"); | ||
497 | |||
498 | release_firmware: | ||
499 | release_firmware(firmware); | ||
500 | out: | ||
501 | if (err) | ||
502 | lbs_pr_err("failed to load helper firmware (err=%d)\n", err); | ||
503 | lbs_deb_leave_args(LBS_DEB_SPI, "err %d", err); | ||
504 | return err; | ||
505 | } | ||
506 | |||
507 | /* Returns the length of the next packet the firmware expects us to send | ||
508 | * Sets crc_err if the previous transfer had a CRC error. */ | ||
509 | static int if_spi_prog_main_firmware_check_len(struct if_spi_card *card, | ||
510 | int *crc_err) | ||
511 | { | ||
512 | u16 len; | ||
513 | int err = 0; | ||
514 | |||
515 | /* wait until the host interrupt status register indicates | ||
516 | * that we are ready to download */ | ||
517 | err = spu_wait_for_u16(card, IF_SPI_HOST_INT_STATUS_REG, | ||
518 | IF_SPI_HIST_CMD_DOWNLOAD_RDY, | ||
519 | IF_SPI_HIST_CMD_DOWNLOAD_RDY); | ||
520 | if (err) { | ||
521 | lbs_pr_err("timed out waiting for host_int_status\n"); | ||
522 | return err; | ||
523 | } | ||
524 | |||
525 | /* Ask the device how many bytes of firmware it wants. */ | ||
526 | err = spu_read_u16(card, IF_SPI_SCRATCH_1_REG, &len); | ||
527 | if (err) | ||
528 | return err; | ||
529 | |||
530 | if (len > IF_SPI_CMD_BUF_SIZE) { | ||
531 | lbs_pr_err("firmware load device requested a larger " | ||
532 | "tranfer than we are prepared to " | ||
533 | "handle. (len = %d)\n", len); | ||
534 | return -EIO; | ||
535 | } | ||
536 | if (len & 0x1) { | ||
537 | lbs_deb_spi("%s: crc error\n", __func__); | ||
538 | len &= ~0x1; | ||
539 | *crc_err = 1; | ||
540 | } else | ||
541 | *crc_err = 0; | ||
542 | |||
543 | return len; | ||
544 | } | ||
545 | |||
546 | static int if_spi_prog_main_firmware(struct if_spi_card *card) | ||
547 | { | ||
548 | int len, prev_len; | ||
549 | int bytes, crc_err = 0, err = 0; | ||
550 | const struct firmware *firmware = NULL; | ||
551 | const u8 *fw; | ||
552 | struct spi_device *spi = card->spi; | ||
553 | u16 num_crc_errs; | ||
554 | |||
555 | lbs_deb_enter(LBS_DEB_SPI); | ||
556 | |||
557 | err = spu_set_interrupt_mode(card, 1, 0); | ||
558 | if (err) | ||
559 | goto out; | ||
560 | |||
561 | /* Get firmware image */ | ||
562 | err = request_firmware(&firmware, card->main_fw_name, &spi->dev); | ||
563 | if (err) { | ||
564 | lbs_pr_err("%s: can't get firmware '%s' from kernel. " | ||
565 | "err = %d\n", __func__, card->main_fw_name, err); | ||
566 | goto out; | ||
567 | } | ||
568 | |||
569 | err = spu_wait_for_u16(card, IF_SPI_SCRATCH_1_REG, 0, 0); | ||
570 | if (err) { | ||
571 | lbs_pr_err("%s: timed out waiting for initial " | ||
572 | "scratch reg = 0\n", __func__); | ||
573 | goto release_firmware; | ||
574 | } | ||
575 | |||
576 | num_crc_errs = 0; | ||
577 | prev_len = 0; | ||
578 | bytes = firmware->size; | ||
579 | fw = firmware->data; | ||
580 | while ((len = if_spi_prog_main_firmware_check_len(card, &crc_err))) { | ||
581 | if (len < 0) { | ||
582 | err = len; | ||
583 | goto release_firmware; | ||
584 | } | ||
585 | if (bytes < 0) { | ||
586 | /* If there are no more bytes left, we would normally | ||
587 | * expect to have terminated with len = 0 */ | ||
588 | lbs_pr_err("Firmware load wants more bytes " | ||
589 | "than we have to offer.\n"); | ||
590 | break; | ||
591 | } | ||
592 | if (crc_err) { | ||
593 | /* Previous transfer failed. */ | ||
594 | if (++num_crc_errs > MAX_MAIN_FW_LOAD_CRC_ERR) { | ||
595 | lbs_pr_err("Too many CRC errors encountered " | ||
596 | "in firmware load.\n"); | ||
597 | err = -EIO; | ||
598 | goto release_firmware; | ||
599 | } | ||
600 | } else { | ||
601 | /* Previous transfer succeeded. Advance counters. */ | ||
602 | bytes -= prev_len; | ||
603 | fw += prev_len; | ||
604 | } | ||
605 | if (bytes < len) { | ||
606 | memset(card->cmd_buffer, 0, len); | ||
607 | memcpy(card->cmd_buffer, fw, bytes); | ||
608 | } else | ||
609 | memcpy(card->cmd_buffer, fw, len); | ||
610 | |||
611 | err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0); | ||
612 | if (err) | ||
613 | goto release_firmware; | ||
614 | err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG, | ||
615 | card->cmd_buffer, len); | ||
616 | if (err) | ||
617 | goto release_firmware; | ||
618 | err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG , | ||
619 | IF_SPI_CIC_CMD_DOWNLOAD_OVER); | ||
620 | if (err) | ||
621 | goto release_firmware; | ||
622 | prev_len = len; | ||
623 | } | ||
624 | if (bytes > prev_len) { | ||
625 | lbs_pr_err("firmware load wants fewer bytes than " | ||
626 | "we have to offer.\n"); | ||
627 | } | ||
628 | |||
629 | /* Confirm firmware download */ | ||
630 | err = spu_wait_for_u32(card, IF_SPI_SCRATCH_4_REG, | ||
631 | SUCCESSFUL_FW_DOWNLOAD_MAGIC); | ||
632 | if (err) { | ||
633 | lbs_pr_err("failed to confirm the firmware download\n"); | ||
634 | goto release_firmware; | ||
635 | } | ||
636 | |||
637 | release_firmware: | ||
638 | release_firmware(firmware); | ||
639 | |||
640 | out: | ||
641 | if (err) | ||
642 | lbs_pr_err("failed to load firmware (err=%d)\n", err); | ||
643 | lbs_deb_leave_args(LBS_DEB_SPI, "err %d", err); | ||
644 | return err; | ||
645 | } | ||
646 | |||
647 | /* | ||
648 | * SPI Transfer Thread | ||
649 | * | ||
650 | * The SPI thread handles all SPI transfers, so there is no need for a lock. | ||
651 | */ | ||
652 | |||
653 | /* Move a command from the card to the host */ | ||
654 | static int if_spi_c2h_cmd(struct if_spi_card *card) | ||
655 | { | ||
656 | struct lbs_private *priv = card->priv; | ||
657 | unsigned long flags; | ||
658 | int err = 0; | ||
659 | u16 len; | ||
660 | u8 i; | ||
661 | |||
662 | /* We need a buffer big enough to handle whatever people send to | ||
663 | * hw_host_to_card */ | ||
664 | BUILD_BUG_ON(IF_SPI_CMD_BUF_SIZE < LBS_CMD_BUFFER_SIZE); | ||
665 | BUILD_BUG_ON(IF_SPI_CMD_BUF_SIZE < LBS_UPLD_SIZE); | ||
666 | |||
667 | /* It's just annoying if the buffer size isn't a multiple of 4, because | ||
668 | * then we might have len < IF_SPI_CMD_BUF_SIZE but | ||
669 | * ALIGN(len, 4) > IF_SPI_CMD_BUF_SIZE */ | ||
670 | BUILD_BUG_ON(IF_SPI_CMD_BUF_SIZE % 4 != 0); | ||
671 | |||
672 | lbs_deb_enter(LBS_DEB_SPI); | ||
673 | |||
674 | /* How many bytes are there to read? */ | ||
675 | err = spu_read_u16(card, IF_SPI_SCRATCH_2_REG, &len); | ||
676 | if (err) | ||
677 | goto out; | ||
678 | if (!len) { | ||
679 | lbs_pr_err("%s: error: card has no data for host\n", | ||
680 | __func__); | ||
681 | err = -EINVAL; | ||
682 | goto out; | ||
683 | } else if (len > IF_SPI_CMD_BUF_SIZE) { | ||
684 | lbs_pr_err("%s: error: response packet too large: " | ||
685 | "%d bytes, but maximum is %d\n", | ||
686 | __func__, len, IF_SPI_CMD_BUF_SIZE); | ||
687 | err = -EINVAL; | ||
688 | goto out; | ||
689 | } | ||
690 | |||
691 | /* Read the data from the WLAN module into our command buffer */ | ||
692 | err = spu_read(card, IF_SPI_CMD_RDWRPORT_REG, | ||
693 | card->cmd_buffer, ALIGN(len, 4)); | ||
694 | if (err) | ||
695 | goto out; | ||
696 | |||
697 | spin_lock_irqsave(&priv->driver_lock, flags); | ||
698 | i = (priv->resp_idx == 0) ? 1 : 0; | ||
699 | BUG_ON(priv->resp_len[i]); | ||
700 | priv->resp_len[i] = len; | ||
701 | memcpy(priv->resp_buf[i], card->cmd_buffer, len); | ||
702 | lbs_notify_command_response(priv, i); | ||
703 | spin_unlock_irqrestore(&priv->driver_lock, flags); | ||
704 | |||
705 | out: | ||
706 | if (err) | ||
707 | lbs_pr_err("%s: err=%d\n", __func__, err); | ||
708 | lbs_deb_leave(LBS_DEB_SPI); | ||
709 | return err; | ||
710 | } | ||
711 | |||
712 | /* Move data from the card to the host */ | ||
713 | static int if_spi_c2h_data(struct if_spi_card *card) | ||
714 | { | ||
715 | struct sk_buff *skb; | ||
716 | char *data; | ||
717 | u16 len; | ||
718 | int err = 0; | ||
719 | |||
720 | lbs_deb_enter(LBS_DEB_SPI); | ||
721 | |||
722 | /* How many bytes are there to read? */ | ||
723 | err = spu_read_u16(card, IF_SPI_SCRATCH_1_REG, &len); | ||
724 | if (err) | ||
725 | goto out; | ||
726 | if (!len) { | ||
727 | lbs_pr_err("%s: error: card has no data for host\n", | ||
728 | __func__); | ||
729 | err = -EINVAL; | ||
730 | goto out; | ||
731 | } else if (len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) { | ||
732 | lbs_pr_err("%s: error: card has %d bytes of data, but " | ||
733 | "our maximum skb size is %u\n", | ||
734 | __func__, len, MRVDRV_ETH_RX_PACKET_BUFFER_SIZE); | ||
735 | err = -EINVAL; | ||
736 | goto out; | ||
737 | } | ||
738 | |||
739 | /* TODO: should we allocate a smaller skb if we have less data? */ | ||
740 | skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE); | ||
741 | if (!skb) { | ||
742 | err = -ENOBUFS; | ||
743 | goto out; | ||
744 | } | ||
745 | skb_reserve(skb, IPFIELD_ALIGN_OFFSET); | ||
746 | data = skb_put(skb, len); | ||
747 | |||
748 | /* Read the data from the WLAN module into our skb... */ | ||
749 | err = spu_read(card, IF_SPI_DATA_RDWRPORT_REG, data, ALIGN(len, 4)); | ||
750 | if (err) | ||
751 | goto free_skb; | ||
752 | |||
753 | /* pass the SKB to libertas */ | ||
754 | err = lbs_process_rxed_packet(card->priv, skb); | ||
755 | if (err) | ||
756 | goto free_skb; | ||
757 | |||
758 | /* success */ | ||
759 | goto out; | ||
760 | |||
761 | free_skb: | ||
762 | dev_kfree_skb(skb); | ||
763 | out: | ||
764 | if (err) | ||
765 | lbs_pr_err("%s: err=%d\n", __func__, err); | ||
766 | lbs_deb_leave(LBS_DEB_SPI); | ||
767 | return err; | ||
768 | } | ||
769 | |||
770 | /* Move data or a command from the host to the card. */ | ||
771 | static void if_spi_h2c(struct if_spi_card *card, | ||
772 | struct if_spi_packet *packet, int type) | ||
773 | { | ||
774 | int err = 0; | ||
775 | u16 int_type, port_reg; | ||
776 | |||
777 | switch (type) { | ||
778 | case MVMS_DAT: | ||
779 | int_type = IF_SPI_CIC_TX_DOWNLOAD_OVER; | ||
780 | port_reg = IF_SPI_DATA_RDWRPORT_REG; | ||
781 | break; | ||
782 | case MVMS_CMD: | ||
783 | int_type = IF_SPI_CIC_CMD_DOWNLOAD_OVER; | ||
784 | port_reg = IF_SPI_CMD_RDWRPORT_REG; | ||
785 | break; | ||
786 | default: | ||
787 | lbs_pr_err("can't transfer buffer of type %d\n", type); | ||
788 | err = -EINVAL; | ||
789 | goto out; | ||
790 | } | ||
791 | |||
792 | /* Write the data to the card */ | ||
793 | err = spu_write(card, port_reg, packet->buffer, packet->blen); | ||
794 | if (err) | ||
795 | goto out; | ||
796 | |||
797 | out: | ||
798 | kfree(packet); | ||
799 | |||
800 | if (err) | ||
801 | lbs_pr_err("%s: error %d\n", __func__, err); | ||
802 | } | ||
803 | |||
804 | /* Inform the host about a card event */ | ||
805 | static void if_spi_e2h(struct if_spi_card *card) | ||
806 | { | ||
807 | int err = 0; | ||
808 | unsigned long flags; | ||
809 | u32 cause; | ||
810 | struct lbs_private *priv = card->priv; | ||
811 | |||
812 | err = spu_read_u32(card, IF_SPI_SCRATCH_3_REG, &cause); | ||
813 | if (err) | ||
814 | goto out; | ||
815 | |||
816 | spin_lock_irqsave(&priv->driver_lock, flags); | ||
817 | lbs_queue_event(priv, cause & 0xff); | ||
818 | spin_unlock_irqrestore(&priv->driver_lock, flags); | ||
819 | |||
820 | out: | ||
821 | if (err) | ||
822 | lbs_pr_err("%s: error %d\n", __func__, err); | ||
823 | } | ||
824 | |||
825 | static int lbs_spi_thread(void *data) | ||
826 | { | ||
827 | int err; | ||
828 | struct if_spi_card *card = data; | ||
829 | u16 hiStatus; | ||
830 | unsigned long flags; | ||
831 | struct if_spi_packet *packet; | ||
832 | |||
833 | while (1) { | ||
834 | /* Wait to be woken up by one of two things. First, our ISR | ||
835 | * could tell us that something happened on the WLAN. | ||
836 | * Secondly, libertas could call hw_host_to_card with more | ||
837 | * data, which we might be able to send. | ||
838 | */ | ||
839 | do { | ||
840 | err = down_interruptible(&card->spi_ready); | ||
841 | if (!card->run_thread) { | ||
842 | up(&card->spi_thread_terminated); | ||
843 | do_exit(0); | ||
844 | } | ||
845 | } while (err == EINTR); | ||
846 | |||
847 | /* Read the host interrupt status register to see what we | ||
848 | * can do. */ | ||
849 | err = spu_read_u16(card, IF_SPI_HOST_INT_STATUS_REG, | ||
850 | &hiStatus); | ||
851 | if (err) { | ||
852 | lbs_pr_err("I/O error\n"); | ||
853 | goto err; | ||
854 | } | ||
855 | |||
856 | if (hiStatus & IF_SPI_HIST_CMD_UPLOAD_RDY) | ||
857 | err = if_spi_c2h_cmd(card); | ||
858 | if (err) | ||
859 | goto err; | ||
860 | if (hiStatus & IF_SPI_HIST_RX_UPLOAD_RDY) | ||
861 | err = if_spi_c2h_data(card); | ||
862 | if (err) | ||
863 | goto err; | ||
864 | if (hiStatus & IF_SPI_HIST_CMD_DOWNLOAD_RDY) { | ||
865 | /* This means two things. First of all, | ||
866 | * if there was a previous command sent, the card has | ||
867 | * successfully received it. | ||
868 | * Secondly, it is now ready to download another | ||
869 | * command. | ||
870 | */ | ||
871 | lbs_host_to_card_done(card->priv); | ||
872 | |||
873 | /* Do we have any command packets from the host to | ||
874 | * send? */ | ||
875 | packet = NULL; | ||
876 | spin_lock_irqsave(&card->buffer_lock, flags); | ||
877 | if (!list_empty(&card->cmd_packet_list)) { | ||
878 | packet = (struct if_spi_packet *)(card-> | ||
879 | cmd_packet_list.next); | ||
880 | list_del(&packet->list); | ||
881 | } | ||
882 | spin_unlock_irqrestore(&card->buffer_lock, flags); | ||
883 | |||
884 | if (packet) | ||
885 | if_spi_h2c(card, packet, MVMS_CMD); | ||
886 | } | ||
887 | if (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY) { | ||
888 | /* Do we have any data packets from the host to | ||
889 | * send? */ | ||
890 | packet = NULL; | ||
891 | spin_lock_irqsave(&card->buffer_lock, flags); | ||
892 | if (!list_empty(&card->data_packet_list)) { | ||
893 | packet = (struct if_spi_packet *)(card-> | ||
894 | data_packet_list.next); | ||
895 | list_del(&packet->list); | ||
896 | } | ||
897 | spin_unlock_irqrestore(&card->buffer_lock, flags); | ||
898 | |||
899 | if (packet) | ||
900 | if_spi_h2c(card, packet, MVMS_DAT); | ||
901 | } | ||
902 | if (hiStatus & IF_SPI_HIST_CARD_EVENT) | ||
903 | if_spi_e2h(card); | ||
904 | |||
905 | err: | ||
906 | if (err) | ||
907 | lbs_pr_err("%s: got error %d\n", __func__, err); | ||
908 | } | ||
909 | } | ||
910 | |||
911 | /* Block until lbs_spi_thread thread has terminated */ | ||
912 | static void if_spi_terminate_spi_thread(struct if_spi_card *card) | ||
913 | { | ||
914 | /* It would be nice to use kthread_stop here, but that function | ||
915 | * can't wake threads waiting for a semaphore. */ | ||
916 | card->run_thread = 0; | ||
917 | up(&card->spi_ready); | ||
918 | down(&card->spi_thread_terminated); | ||
919 | } | ||
920 | |||
921 | /* | ||
922 | * Host to Card | ||
923 | * | ||
924 | * Called from Libertas to transfer some data to the WLAN device | ||
925 | * We can't sleep here. */ | ||
926 | static int if_spi_host_to_card(struct lbs_private *priv, | ||
927 | u8 type, u8 *buf, u16 nb) | ||
928 | { | ||
929 | int err = 0; | ||
930 | unsigned long flags; | ||
931 | struct if_spi_card *card = priv->card; | ||
932 | struct if_spi_packet *packet; | ||
933 | u16 blen; | ||
934 | |||
935 | lbs_deb_enter_args(LBS_DEB_SPI, "type %d, bytes %d", type, nb); | ||
936 | |||
937 | if (nb == 0) { | ||
938 | lbs_pr_err("%s: invalid size requested: %d\n", __func__, nb); | ||
939 | err = -EINVAL; | ||
940 | goto out; | ||
941 | } | ||
942 | blen = ALIGN(nb, 4); | ||
943 | packet = kzalloc(sizeof(struct if_spi_packet) + blen, GFP_ATOMIC); | ||
944 | if (!packet) { | ||
945 | err = -ENOMEM; | ||
946 | goto out; | ||
947 | } | ||
948 | packet->blen = blen; | ||
949 | memcpy(packet->buffer, buf, nb); | ||
950 | memset(packet->buffer + nb, 0, blen - nb); | ||
951 | |||
952 | switch (type) { | ||
953 | case MVMS_CMD: | ||
954 | priv->dnld_sent = DNLD_CMD_SENT; | ||
955 | spin_lock_irqsave(&card->buffer_lock, flags); | ||
956 | list_add_tail(&packet->list, &card->cmd_packet_list); | ||
957 | spin_unlock_irqrestore(&card->buffer_lock, flags); | ||
958 | break; | ||
959 | case MVMS_DAT: | ||
960 | priv->dnld_sent = DNLD_DATA_SENT; | ||
961 | spin_lock_irqsave(&card->buffer_lock, flags); | ||
962 | list_add_tail(&packet->list, &card->data_packet_list); | ||
963 | spin_unlock_irqrestore(&card->buffer_lock, flags); | ||
964 | break; | ||
965 | default: | ||
966 | lbs_pr_err("can't transfer buffer of type %d", type); | ||
967 | err = -EINVAL; | ||
968 | break; | ||
969 | } | ||
970 | |||
971 | /* Wake up the spi thread */ | ||
972 | up(&card->spi_ready); | ||
973 | out: | ||
974 | lbs_deb_leave_args(LBS_DEB_SPI, "err=%d", err); | ||
975 | return err; | ||
976 | } | ||
977 | |||
978 | /* | ||
979 | * Host Interrupts | ||
980 | * | ||
981 | * Service incoming interrupts from the WLAN device. We can't sleep here, so | ||
982 | * don't try to talk on the SPI bus, just wake up the SPI thread. | ||
983 | */ | ||
984 | static irqreturn_t if_spi_host_interrupt(int irq, void *dev_id) | ||
985 | { | ||
986 | struct if_spi_card *card = dev_id; | ||
987 | |||
988 | up(&card->spi_ready); | ||
989 | return IRQ_HANDLED; | ||
990 | } | ||
991 | |||
992 | /* | ||
993 | * SPI callbacks | ||
994 | */ | ||
995 | |||
996 | static int if_spi_calculate_fw_names(u16 card_id, | ||
997 | char *helper_fw, char *main_fw) | ||
998 | { | ||
999 | int i; | ||
1000 | for (i = 0; i < ARRAY_SIZE(chip_id_to_device_name); ++i) { | ||
1001 | if (card_id == chip_id_to_device_name[i].chip_id) | ||
1002 | break; | ||
1003 | } | ||
1004 | if (i == ARRAY_SIZE(chip_id_to_device_name)) { | ||
1005 | lbs_pr_err("Unsupported chip_id: 0x%02x\n", card_id); | ||
1006 | return -EAFNOSUPPORT; | ||
1007 | } | ||
1008 | snprintf(helper_fw, FIRMWARE_NAME_MAX, "libertas/gspi%d_hlp.bin", | ||
1009 | chip_id_to_device_name[i].name); | ||
1010 | snprintf(main_fw, FIRMWARE_NAME_MAX, "libertas/gspi%d.bin", | ||
1011 | chip_id_to_device_name[i].name); | ||
1012 | return 0; | ||
1013 | } | ||
1014 | |||
1015 | static int __devinit if_spi_probe(struct spi_device *spi) | ||
1016 | { | ||
1017 | struct if_spi_card *card; | ||
1018 | struct lbs_private *priv = NULL; | ||
1019 | struct libertas_spi_platform_data *pdata = spi->dev.platform_data; | ||
1020 | int err = 0; | ||
1021 | u32 scratch; | ||
1022 | |||
1023 | lbs_deb_enter(LBS_DEB_SPI); | ||
1024 | |||
1025 | /* Allocate card structure to represent this specific device */ | ||
1026 | card = kzalloc(sizeof(struct if_spi_card), GFP_KERNEL); | ||
1027 | if (!card) { | ||
1028 | err = -ENOMEM; | ||
1029 | goto out; | ||
1030 | } | ||
1031 | spi_set_drvdata(spi, card); | ||
1032 | card->spi = spi; | ||
1033 | card->gpio_cs = pdata->gpio_cs; | ||
1034 | card->prev_xfer_time = jiffies; | ||
1035 | |||
1036 | sema_init(&card->spi_ready, 0); | ||
1037 | sema_init(&card->spi_thread_terminated, 0); | ||
1038 | INIT_LIST_HEAD(&card->cmd_packet_list); | ||
1039 | INIT_LIST_HEAD(&card->data_packet_list); | ||
1040 | spin_lock_init(&card->buffer_lock); | ||
1041 | |||
1042 | /* set up GPIO CS line. TODO: use regular CS line */ | ||
1043 | err = gpio_request(card->gpio_cs, "if_spi_gpio_chip_select"); | ||
1044 | if (err) | ||
1045 | goto free_card; | ||
1046 | err = gpio_direction_output(card->gpio_cs, 1); | ||
1047 | if (err) | ||
1048 | goto free_gpio; | ||
1049 | |||
1050 | /* Initialize the SPI Interface Unit */ | ||
1051 | err = spu_init(card, pdata->use_dummy_writes); | ||
1052 | if (err) | ||
1053 | goto free_gpio; | ||
1054 | err = spu_get_chip_revision(card, &card->card_id, &card->card_rev); | ||
1055 | if (err) | ||
1056 | goto free_gpio; | ||
1057 | |||
1058 | /* Firmware load */ | ||
1059 | err = spu_read_u32(card, IF_SPI_SCRATCH_4_REG, &scratch); | ||
1060 | if (err) | ||
1061 | goto free_gpio; | ||
1062 | if (scratch == SUCCESSFUL_FW_DOWNLOAD_MAGIC) | ||
1063 | lbs_deb_spi("Firmware is already loaded for " | ||
1064 | "Marvell WLAN 802.11 adapter\n"); | ||
1065 | else { | ||
1066 | err = if_spi_calculate_fw_names(card->card_id, | ||
1067 | card->helper_fw_name, card->main_fw_name); | ||
1068 | if (err) | ||
1069 | goto free_gpio; | ||
1070 | |||
1071 | lbs_deb_spi("Initializing FW for Marvell WLAN 802.11 adapter " | ||
1072 | "(chip_id = 0x%04x, chip_rev = 0x%02x) " | ||
1073 | "attached to SPI bus_num %d, chip_select %d. " | ||
1074 | "spi->max_speed_hz=%d\n", | ||
1075 | card->card_id, card->card_rev, | ||
1076 | spi->master->bus_num, spi->chip_select, | ||
1077 | spi->max_speed_hz); | ||
1078 | err = if_spi_prog_helper_firmware(card); | ||
1079 | if (err) | ||
1080 | goto free_gpio; | ||
1081 | err = if_spi_prog_main_firmware(card); | ||
1082 | if (err) | ||
1083 | goto free_gpio; | ||
1084 | lbs_deb_spi("loaded FW for Marvell WLAN 802.11 adapter\n"); | ||
1085 | } | ||
1086 | |||
1087 | err = spu_set_interrupt_mode(card, 0, 1); | ||
1088 | if (err) | ||
1089 | goto free_gpio; | ||
1090 | |||
1091 | /* Register our card with libertas. | ||
1092 | * This will call alloc_etherdev */ | ||
1093 | priv = lbs_add_card(card, &spi->dev); | ||
1094 | if (!priv) { | ||
1095 | err = -ENOMEM; | ||
1096 | goto free_gpio; | ||
1097 | } | ||
1098 | card->priv = priv; | ||
1099 | priv->card = card; | ||
1100 | priv->hw_host_to_card = if_spi_host_to_card; | ||
1101 | priv->fw_ready = 1; | ||
1102 | priv->ps_supported = 1; | ||
1103 | |||
1104 | /* Initialize interrupt handling stuff. */ | ||
1105 | card->run_thread = 1; | ||
1106 | card->spi_thread = kthread_run(lbs_spi_thread, card, "lbs_spi_thread"); | ||
1107 | if (IS_ERR(card->spi_thread)) { | ||
1108 | card->run_thread = 0; | ||
1109 | err = PTR_ERR(card->spi_thread); | ||
1110 | lbs_pr_err("error creating SPI thread: err=%d\n", err); | ||
1111 | goto remove_card; | ||
1112 | } | ||
1113 | err = request_irq(spi->irq, if_spi_host_interrupt, | ||
1114 | IRQF_TRIGGER_FALLING, "libertas_spi", card); | ||
1115 | if (err) { | ||
1116 | lbs_pr_err("can't get host irq line-- request_irq failed\n"); | ||
1117 | goto terminate_thread; | ||
1118 | } | ||
1119 | |||
1120 | /* Start the card. | ||
1121 | * This will call register_netdev, and we'll start | ||
1122 | * getting interrupts... */ | ||
1123 | err = lbs_start_card(priv); | ||
1124 | if (err) | ||
1125 | goto release_irq; | ||
1126 | |||
1127 | lbs_deb_spi("Finished initializing WLAN module.\n"); | ||
1128 | |||
1129 | /* successful exit */ | ||
1130 | goto out; | ||
1131 | |||
1132 | release_irq: | ||
1133 | free_irq(spi->irq, card); | ||
1134 | terminate_thread: | ||
1135 | if_spi_terminate_spi_thread(card); | ||
1136 | remove_card: | ||
1137 | lbs_remove_card(priv); /* will call free_netdev */ | ||
1138 | free_gpio: | ||
1139 | gpio_free(card->gpio_cs); | ||
1140 | free_card: | ||
1141 | free_if_spi_card(card); | ||
1142 | out: | ||
1143 | lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err); | ||
1144 | return err; | ||
1145 | } | ||
1146 | |||
1147 | static int __devexit libertas_spi_remove(struct spi_device *spi) | ||
1148 | { | ||
1149 | struct if_spi_card *card = spi_get_drvdata(spi); | ||
1150 | struct lbs_private *priv = card->priv; | ||
1151 | |||
1152 | lbs_deb_spi("libertas_spi_remove\n"); | ||
1153 | lbs_deb_enter(LBS_DEB_SPI); | ||
1154 | priv->surpriseremoved = 1; | ||
1155 | |||
1156 | lbs_stop_card(priv); | ||
1157 | free_irq(spi->irq, card); | ||
1158 | if_spi_terminate_spi_thread(card); | ||
1159 | lbs_remove_card(priv); /* will call free_netdev */ | ||
1160 | gpio_free(card->gpio_cs); | ||
1161 | free_if_spi_card(card); | ||
1162 | lbs_deb_leave(LBS_DEB_SPI); | ||
1163 | return 0; | ||
1164 | } | ||
1165 | |||
1166 | static struct spi_driver libertas_spi_driver = { | ||
1167 | .probe = if_spi_probe, | ||
1168 | .remove = __devexit_p(libertas_spi_remove), | ||
1169 | .driver = { | ||
1170 | .name = "libertas_spi", | ||
1171 | .bus = &spi_bus_type, | ||
1172 | .owner = THIS_MODULE, | ||
1173 | }, | ||
1174 | }; | ||
1175 | |||
1176 | /* | ||
1177 | * Module functions | ||
1178 | */ | ||
1179 | |||
1180 | static int __init if_spi_init_module(void) | ||
1181 | { | ||
1182 | int ret = 0; | ||
1183 | lbs_deb_enter(LBS_DEB_SPI); | ||
1184 | printk(KERN_INFO "libertas_spi: Libertas SPI driver\n"); | ||
1185 | ret = spi_register_driver(&libertas_spi_driver); | ||
1186 | lbs_deb_leave(LBS_DEB_SPI); | ||
1187 | return ret; | ||
1188 | } | ||
1189 | |||
1190 | static void __exit if_spi_exit_module(void) | ||
1191 | { | ||
1192 | lbs_deb_enter(LBS_DEB_SPI); | ||
1193 | spi_unregister_driver(&libertas_spi_driver); | ||
1194 | lbs_deb_leave(LBS_DEB_SPI); | ||
1195 | } | ||
1196 | |||
1197 | module_init(if_spi_init_module); | ||
1198 | module_exit(if_spi_exit_module); | ||
1199 | |||
1200 | MODULE_DESCRIPTION("Libertas SPI WLAN Driver"); | ||
1201 | MODULE_AUTHOR("Andrey Yurovsky <andrey@cozybit.com>, " | ||
1202 | "Colin McCabe <colin@cozybit.com>"); | ||
1203 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/net/wireless/libertas/if_spi.h b/drivers/net/wireless/libertas/if_spi.h new file mode 100644 index 000000000000..2103869cc5b0 --- /dev/null +++ b/drivers/net/wireless/libertas/if_spi.h | |||
@@ -0,0 +1,208 @@ | |||
1 | /* | ||
2 | * linux/drivers/net/wireless/libertas/if_spi.c | ||
3 | * | ||
4 | * Driver for Marvell SPI WLAN cards. | ||
5 | * | ||
6 | * Copyright 2008 Analog Devices Inc. | ||
7 | * | ||
8 | * Authors: | ||
9 | * Andrey Yurovsky <andrey@cozybit.com> | ||
10 | * Colin McCabe <colin@cozybit.com> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or (at | ||
15 | * your option) any later version. | ||
16 | */ | ||
17 | |||
18 | #ifndef _LBS_IF_SPI_H_ | ||
19 | #define _LBS_IF_SPI_H_ | ||
20 | |||
21 | #define IPFIELD_ALIGN_OFFSET 2 | ||
22 | #define IF_SPI_CMD_BUF_SIZE 2400 | ||
23 | |||
24 | /***************** Firmware *****************/ | ||
25 | struct chip_ident { | ||
26 | u16 chip_id; | ||
27 | u16 name; | ||
28 | }; | ||
29 | |||
30 | #define MAX_MAIN_FW_LOAD_CRC_ERR 10 | ||
31 | |||
32 | /* Chunk size when loading the helper firmware */ | ||
33 | #define HELPER_FW_LOAD_CHUNK_SZ 64 | ||
34 | |||
35 | /* Value to write to indicate end of helper firmware dnld */ | ||
36 | #define FIRMWARE_DNLD_OK 0x0000 | ||
37 | |||
38 | /* Value to check once the main firmware is downloaded */ | ||
39 | #define SUCCESSFUL_FW_DOWNLOAD_MAGIC 0x88888888 | ||
40 | |||
41 | /***************** SPI Interface Unit *****************/ | ||
42 | /* Masks used in SPI register read/write operations */ | ||
43 | #define IF_SPI_READ_OPERATION_MASK 0x0 | ||
44 | #define IF_SPI_WRITE_OPERATION_MASK 0x8000 | ||
45 | |||
46 | /* SPI register offsets. 4-byte aligned. */ | ||
47 | #define IF_SPI_DEVICEID_CTRL_REG 0x00 /* DeviceID controller reg */ | ||
48 | #define IF_SPI_IO_READBASE_REG 0x04 /* Read I/O base reg */ | ||
49 | #define IF_SPI_IO_WRITEBASE_REG 0x08 /* Write I/O base reg */ | ||
50 | #define IF_SPI_IO_RDWRPORT_REG 0x0C /* Read/Write I/O port reg */ | ||
51 | |||
52 | #define IF_SPI_CMD_READBASE_REG 0x10 /* Read command base reg */ | ||
53 | #define IF_SPI_CMD_WRITEBASE_REG 0x14 /* Write command base reg */ | ||
54 | #define IF_SPI_CMD_RDWRPORT_REG 0x18 /* Read/Write command port reg */ | ||
55 | |||
56 | #define IF_SPI_DATA_READBASE_REG 0x1C /* Read data base reg */ | ||
57 | #define IF_SPI_DATA_WRITEBASE_REG 0x20 /* Write data base reg */ | ||
58 | #define IF_SPI_DATA_RDWRPORT_REG 0x24 /* Read/Write data port reg */ | ||
59 | |||
60 | #define IF_SPI_SCRATCH_1_REG 0x28 /* Scratch reg 1 */ | ||
61 | #define IF_SPI_SCRATCH_2_REG 0x2C /* Scratch reg 2 */ | ||
62 | #define IF_SPI_SCRATCH_3_REG 0x30 /* Scratch reg 3 */ | ||
63 | #define IF_SPI_SCRATCH_4_REG 0x34 /* Scratch reg 4 */ | ||
64 | |||
65 | #define IF_SPI_TX_FRAME_SEQ_NUM_REG 0x38 /* Tx frame sequence number reg */ | ||
66 | #define IF_SPI_TX_FRAME_STATUS_REG 0x3C /* Tx frame status reg */ | ||
67 | |||
68 | #define IF_SPI_HOST_INT_CTRL_REG 0x40 /* Host interrupt controller reg */ | ||
69 | |||
70 | #define IF_SPI_CARD_INT_CAUSE_REG 0x44 /* Card interrupt cause reg */ | ||
71 | #define IF_SPI_CARD_INT_STATUS_REG 0x48 /* Card interupt status reg */ | ||
72 | #define IF_SPI_CARD_INT_EVENT_MASK_REG 0x4C /* Card interrupt event mask */ | ||
73 | #define IF_SPI_CARD_INT_STATUS_MASK_REG 0x50 /* Card interrupt status mask */ | ||
74 | |||
75 | #define IF_SPI_CARD_INT_RESET_SELECT_REG 0x54 /* Card interrupt reset select */ | ||
76 | |||
77 | #define IF_SPI_HOST_INT_CAUSE_REG 0x58 /* Host interrupt cause reg */ | ||
78 | #define IF_SPI_HOST_INT_STATUS_REG 0x5C /* Host interrupt status reg */ | ||
79 | #define IF_SPI_HOST_INT_EVENT_MASK_REG 0x60 /* Host interrupt event mask */ | ||
80 | #define IF_SPI_HOST_INT_STATUS_MASK_REG 0x64 /* Host interrupt status mask */ | ||
81 | #define IF_SPI_HOST_INT_RESET_SELECT_REG 0x68 /* Host interrupt reset select */ | ||
82 | |||
83 | #define IF_SPI_DELAY_READ_REG 0x6C /* Delay read reg */ | ||
84 | #define IF_SPI_SPU_BUS_MODE_REG 0x70 /* SPU BUS mode reg */ | ||
85 | |||
86 | /***************** IF_SPI_DEVICEID_CTRL_REG *****************/ | ||
87 | #define IF_SPI_DEVICEID_CTRL_REG_TO_CARD_ID(dc) ((dc & 0xffff0000)>>16) | ||
88 | #define IF_SPI_DEVICEID_CTRL_REG_TO_CARD_REV(dc) (dc & 0x000000ff) | ||
89 | |||
90 | /***************** IF_SPI_HOST_INT_CTRL_REG *****************/ | ||
91 | /** Host Interrupt Control bit : Wake up */ | ||
92 | #define IF_SPI_HICT_WAKE_UP (1<<0) | ||
93 | /** Host Interrupt Control bit : WLAN ready */ | ||
94 | #define IF_SPI_HICT_WLAN_READY (1<<1) | ||
95 | /*#define IF_SPI_HICT_FIFO_FIRST_HALF_EMPTY (1<<2) */ | ||
96 | /*#define IF_SPI_HICT_FIFO_SECOND_HALF_EMPTY (1<<3) */ | ||
97 | /*#define IF_SPI_HICT_IRQSRC_WLAN (1<<4) */ | ||
98 | /** Host Interrupt Control bit : Tx auto download */ | ||
99 | #define IF_SPI_HICT_TX_DOWNLOAD_OVER_AUTO (1<<5) | ||
100 | /** Host Interrupt Control bit : Rx auto upload */ | ||
101 | #define IF_SPI_HICT_RX_UPLOAD_OVER_AUTO (1<<6) | ||
102 | /** Host Interrupt Control bit : Command auto download */ | ||
103 | #define IF_SPI_HICT_CMD_DOWNLOAD_OVER_AUTO (1<<7) | ||
104 | /** Host Interrupt Control bit : Command auto upload */ | ||
105 | #define IF_SPI_HICT_CMD_UPLOAD_OVER_AUTO (1<<8) | ||
106 | |||
107 | /***************** IF_SPI_CARD_INT_CAUSE_REG *****************/ | ||
108 | /** Card Interrupt Case bit : Tx download over */ | ||
109 | #define IF_SPI_CIC_TX_DOWNLOAD_OVER (1<<0) | ||
110 | /** Card Interrupt Case bit : Rx upload over */ | ||
111 | #define IF_SPI_CIC_RX_UPLOAD_OVER (1<<1) | ||
112 | /** Card Interrupt Case bit : Command download over */ | ||
113 | #define IF_SPI_CIC_CMD_DOWNLOAD_OVER (1<<2) | ||
114 | /** Card Interrupt Case bit : Host event */ | ||
115 | #define IF_SPI_CIC_HOST_EVENT (1<<3) | ||
116 | /** Card Interrupt Case bit : Command upload over */ | ||
117 | #define IF_SPI_CIC_CMD_UPLOAD_OVER (1<<4) | ||
118 | /** Card Interrupt Case bit : Power down */ | ||
119 | #define IF_SPI_CIC_POWER_DOWN (1<<5) | ||
120 | |||
121 | /***************** IF_SPI_CARD_INT_STATUS_REG *****************/ | ||
122 | #define IF_SPI_CIS_TX_DOWNLOAD_OVER (1<<0) | ||
123 | #define IF_SPI_CIS_RX_UPLOAD_OVER (1<<1) | ||
124 | #define IF_SPI_CIS_CMD_DOWNLOAD_OVER (1<<2) | ||
125 | #define IF_SPI_CIS_HOST_EVENT (1<<3) | ||
126 | #define IF_SPI_CIS_CMD_UPLOAD_OVER (1<<4) | ||
127 | #define IF_SPI_CIS_POWER_DOWN (1<<5) | ||
128 | |||
129 | /***************** IF_SPI_HOST_INT_CAUSE_REG *****************/ | ||
130 | #define IF_SPI_HICU_TX_DOWNLOAD_RDY (1<<0) | ||
131 | #define IF_SPI_HICU_RX_UPLOAD_RDY (1<<1) | ||
132 | #define IF_SPI_HICU_CMD_DOWNLOAD_RDY (1<<2) | ||
133 | #define IF_SPI_HICU_CARD_EVENT (1<<3) | ||
134 | #define IF_SPI_HICU_CMD_UPLOAD_RDY (1<<4) | ||
135 | #define IF_SPI_HICU_IO_WR_FIFO_OVERFLOW (1<<5) | ||
136 | #define IF_SPI_HICU_IO_RD_FIFO_UNDERFLOW (1<<6) | ||
137 | #define IF_SPI_HICU_DATA_WR_FIFO_OVERFLOW (1<<7) | ||
138 | #define IF_SPI_HICU_DATA_RD_FIFO_UNDERFLOW (1<<8) | ||
139 | #define IF_SPI_HICU_CMD_WR_FIFO_OVERFLOW (1<<9) | ||
140 | #define IF_SPI_HICU_CMD_RD_FIFO_UNDERFLOW (1<<10) | ||
141 | |||
142 | /***************** IF_SPI_HOST_INT_STATUS_REG *****************/ | ||
143 | /** Host Interrupt Status bit : Tx download ready */ | ||
144 | #define IF_SPI_HIST_TX_DOWNLOAD_RDY (1<<0) | ||
145 | /** Host Interrupt Status bit : Rx upload ready */ | ||
146 | #define IF_SPI_HIST_RX_UPLOAD_RDY (1<<1) | ||
147 | /** Host Interrupt Status bit : Command download ready */ | ||
148 | #define IF_SPI_HIST_CMD_DOWNLOAD_RDY (1<<2) | ||
149 | /** Host Interrupt Status bit : Card event */ | ||
150 | #define IF_SPI_HIST_CARD_EVENT (1<<3) | ||
151 | /** Host Interrupt Status bit : Command upload ready */ | ||
152 | #define IF_SPI_HIST_CMD_UPLOAD_RDY (1<<4) | ||
153 | /** Host Interrupt Status bit : I/O write FIFO overflow */ | ||
154 | #define IF_SPI_HIST_IO_WR_FIFO_OVERFLOW (1<<5) | ||
155 | /** Host Interrupt Status bit : I/O read FIFO underflow */ | ||
156 | #define IF_SPI_HIST_IO_RD_FIFO_UNDRFLOW (1<<6) | ||
157 | /** Host Interrupt Status bit : Data write FIFO overflow */ | ||
158 | #define IF_SPI_HIST_DATA_WR_FIFO_OVERFLOW (1<<7) | ||
159 | /** Host Interrupt Status bit : Data read FIFO underflow */ | ||
160 | #define IF_SPI_HIST_DATA_RD_FIFO_UNDERFLOW (1<<8) | ||
161 | /** Host Interrupt Status bit : Command write FIFO overflow */ | ||
162 | #define IF_SPI_HIST_CMD_WR_FIFO_OVERFLOW (1<<9) | ||
163 | /** Host Interrupt Status bit : Command read FIFO underflow */ | ||
164 | #define IF_SPI_HIST_CMD_RD_FIFO_UNDERFLOW (1<<10) | ||
165 | |||
166 | /***************** IF_SPI_HOST_INT_STATUS_MASK_REG *****************/ | ||
167 | /** Host Interrupt Status Mask bit : Tx download ready */ | ||
168 | #define IF_SPI_HISM_TX_DOWNLOAD_RDY (1<<0) | ||
169 | /** Host Interrupt Status Mask bit : Rx upload ready */ | ||
170 | #define IF_SPI_HISM_RX_UPLOAD_RDY (1<<1) | ||
171 | /** Host Interrupt Status Mask bit : Command download ready */ | ||
172 | #define IF_SPI_HISM_CMD_DOWNLOAD_RDY (1<<2) | ||
173 | /** Host Interrupt Status Mask bit : Card event */ | ||
174 | #define IF_SPI_HISM_CARDEVENT (1<<3) | ||
175 | /** Host Interrupt Status Mask bit : Command upload ready */ | ||
176 | #define IF_SPI_HISM_CMD_UPLOAD_RDY (1<<4) | ||
177 | /** Host Interrupt Status Mask bit : I/O write FIFO overflow */ | ||
178 | #define IF_SPI_HISM_IO_WR_FIFO_OVERFLOW (1<<5) | ||
179 | /** Host Interrupt Status Mask bit : I/O read FIFO underflow */ | ||
180 | #define IF_SPI_HISM_IO_RD_FIFO_UNDERFLOW (1<<6) | ||
181 | /** Host Interrupt Status Mask bit : Data write FIFO overflow */ | ||
182 | #define IF_SPI_HISM_DATA_WR_FIFO_OVERFLOW (1<<7) | ||
183 | /** Host Interrupt Status Mask bit : Data write FIFO underflow */ | ||
184 | #define IF_SPI_HISM_DATA_RD_FIFO_UNDERFLOW (1<<8) | ||
185 | /** Host Interrupt Status Mask bit : Command write FIFO overflow */ | ||
186 | #define IF_SPI_HISM_CMD_WR_FIFO_OVERFLOW (1<<9) | ||
187 | /** Host Interrupt Status Mask bit : Command write FIFO underflow */ | ||
188 | #define IF_SPI_HISM_CMD_RD_FIFO_UNDERFLOW (1<<10) | ||
189 | |||
190 | /***************** IF_SPI_SPU_BUS_MODE_REG *****************/ | ||
191 | /* SCK edge on which the WLAN module outputs data on MISO */ | ||
192 | #define IF_SPI_BUS_MODE_SPI_CLOCK_PHASE_FALLING 0x8 | ||
193 | #define IF_SPI_BUS_MODE_SPI_CLOCK_PHASE_RISING 0x0 | ||
194 | |||
195 | /* In a SPU read operation, there is a delay between writing the SPU | ||
196 | * register name and getting back data from the WLAN module. | ||
197 | * This can be specified in terms of nanoseconds or in terms of dummy | ||
198 | * clock cycles which the master must output before receiving a response. */ | ||
199 | #define IF_SPI_BUS_MODE_DELAY_METHOD_DUMMY_CLOCK 0x4 | ||
200 | #define IF_SPI_BUS_MODE_DELAY_METHOD_TIMED 0x0 | ||
201 | |||
202 | /* Some different modes of SPI operation */ | ||
203 | #define IF_SPI_BUS_MODE_8_BIT_ADDRESS_16_BIT_DATA 0x00 | ||
204 | #define IF_SPI_BUS_MODE_8_BIT_ADDRESS_32_BIT_DATA 0x01 | ||
205 | #define IF_SPI_BUS_MODE_16_BIT_ADDRESS_16_BIT_DATA 0x02 | ||
206 | #define IF_SPI_BUS_MODE_16_BIT_ADDRESS_32_BIT_DATA 0x03 | ||
207 | |||
208 | #endif | ||
diff --git a/include/linux/spi/libertas_spi.h b/include/linux/spi/libertas_spi.h new file mode 100644 index 000000000000..ada71b4f3788 --- /dev/null +++ b/include/linux/spi/libertas_spi.h | |||
@@ -0,0 +1,25 @@ | |||
1 | /* | ||
2 | * board-specific data for the libertas_spi driver. | ||
3 | * | ||
4 | * Copyright 2008 Analog Devices Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or (at | ||
9 | * your option) any later version. | ||
10 | */ | ||
11 | #ifndef _LIBERTAS_SPI_H_ | ||
12 | #define _LIBERTAS_SPI_H_ | ||
13 | struct libertas_spi_platform_data { | ||
14 | /* There are two ways to read data from the WLAN module's SPI | ||
15 | * interface. Setting 0 or 1 here controls which one is used. | ||
16 | * | ||
17 | * Usually you want to set use_dummy_writes = 1. | ||
18 | * However, if that doesn't work or if you are using a slow SPI clock | ||
19 | * speed, you may want to use 0 here. */ | ||
20 | u16 use_dummy_writes; | ||
21 | |||
22 | /* GPIO number to use as chip select */ | ||
23 | u16 gpio_cs; | ||
24 | }; | ||
25 | #endif | ||