diff options
author | Juuso Oikarinen <juuso.oikarinen@nokia.com> | 2009-10-08 14:56:23 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-10-27 16:47:49 -0400 |
commit | 545f1da8ef0f20923feb500bcfaf0e2fb6068fb4 (patch) | |
tree | b245ba9ed9abffa9f53de1cd33f7c3108eb8fa6a | |
parent | c3fea1994ac34dafa3ebb40d4f95354b2782af31 (diff) |
wl1271: Implementation for SPI busy word checking
This patch adds implementation for checking for SPI busy words - i.e.
honoring a delay request from the WLAN chipset upon reading
registers/memory.
To optimized the average SPI ready by 32 bits, also configure the number
of busywords to one to disable the "fixed-busy-word" functionality.
Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Vidhya Govindan <vidhya.govindan@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271.h | 10 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_spi.c | 69 |
2 files changed, 75 insertions, 4 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index c455dcbae524..957da8c0d9cb 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h | |||
@@ -107,7 +107,13 @@ enum { | |||
107 | #define WL1271_FW_NAME "wl1271-fw.bin" | 107 | #define WL1271_FW_NAME "wl1271-fw.bin" |
108 | #define WL1271_NVS_NAME "wl1271-nvs.bin" | 108 | #define WL1271_NVS_NAME "wl1271-nvs.bin" |
109 | 109 | ||
110 | #define WL1271_BUSY_WORD_LEN 8 | 110 | /* |
111 | * FIXME: for the wl1271, a busy word count of 1 here will result in a more | ||
112 | * optimal SPI interface. There is some SPI bug however, causing RXS time outs | ||
113 | * with this mode occasionally on boot, so lets have two for now. | ||
114 | */ | ||
115 | #define WL1271_BUSY_WORD_CNT 2 | ||
116 | #define WL1271_BUSY_WORD_LEN (WL1271_BUSY_WORD_CNT * sizeof(u32)) | ||
111 | 117 | ||
112 | #define WL1271_ELP_HW_STATE_ASLEEP 0 | 118 | #define WL1271_ELP_HW_STATE_ASLEEP 0 |
113 | #define WL1271_ELP_HW_STATE_IRQ 1 | 119 | #define WL1271_ELP_HW_STATE_IRQ 1 |
@@ -389,7 +395,7 @@ struct wl1271 { | |||
389 | 395 | ||
390 | u32 buffer_32; | 396 | u32 buffer_32; |
391 | u32 buffer_cmd; | 397 | u32 buffer_cmd; |
392 | u8 buffer_busyword[WL1271_BUSY_WORD_LEN]; | 398 | u32 buffer_busyword[WL1271_BUSY_WORD_CNT]; |
393 | struct wl1271_rx_descriptor *rx_descriptor; | 399 | struct wl1271_rx_descriptor *rx_descriptor; |
394 | 400 | ||
395 | struct wl1271_fw_status *fw_status; | 401 | struct wl1271_fw_status *fw_status; |
diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c index 4a12880c16a8..504991acb052 100644 --- a/drivers/net/wireless/wl12xx/wl1271_spi.c +++ b/drivers/net/wireless/wl12xx/wl1271_spi.c | |||
@@ -244,12 +244,75 @@ int wl1271_set_partition(struct wl1271 *wl, | |||
244 | return 0; | 244 | return 0; |
245 | } | 245 | } |
246 | 246 | ||
247 | #define WL1271_BUSY_WORD_TIMEOUT 1000 | ||
248 | |||
249 | void wl1271_spi_read_busy(struct wl1271 *wl, void *buf, size_t len) | ||
250 | { | ||
251 | struct spi_transfer t[1]; | ||
252 | struct spi_message m; | ||
253 | u32 *busy_buf; | ||
254 | int num_busy_bytes = 0; | ||
255 | |||
256 | wl1271_info("spi read BUSY!"); | ||
257 | |||
258 | /* | ||
259 | * Look for the non-busy word in the read buffer, and if found, | ||
260 | * read in the remaining data into the buffer. | ||
261 | */ | ||
262 | busy_buf = (u32 *)buf; | ||
263 | for (; (u32)busy_buf < (u32)buf + len; busy_buf++) { | ||
264 | num_busy_bytes += sizeof(u32); | ||
265 | if (*busy_buf & 0x1) { | ||
266 | spi_message_init(&m); | ||
267 | memset(t, 0, sizeof(t)); | ||
268 | memmove(buf, busy_buf, len - num_busy_bytes); | ||
269 | t[0].rx_buf = buf + (len - num_busy_bytes); | ||
270 | t[0].len = num_busy_bytes; | ||
271 | spi_message_add_tail(&t[0], &m); | ||
272 | spi_sync(wl->spi, &m); | ||
273 | return; | ||
274 | } | ||
275 | } | ||
276 | |||
277 | /* | ||
278 | * Read further busy words from SPI until a non-busy word is | ||
279 | * encountered, then read the data itself into the buffer. | ||
280 | */ | ||
281 | wl1271_info("spi read BUSY-polling needed!"); | ||
282 | |||
283 | num_busy_bytes = WL1271_BUSY_WORD_TIMEOUT; | ||
284 | busy_buf = wl->buffer_busyword; | ||
285 | while (num_busy_bytes) { | ||
286 | num_busy_bytes--; | ||
287 | spi_message_init(&m); | ||
288 | memset(t, 0, sizeof(t)); | ||
289 | t[0].rx_buf = busy_buf; | ||
290 | t[0].len = sizeof(u32); | ||
291 | spi_message_add_tail(&t[0], &m); | ||
292 | spi_sync(wl->spi, &m); | ||
293 | |||
294 | if (*busy_buf & 0x1) { | ||
295 | spi_message_init(&m); | ||
296 | memset(t, 0, sizeof(t)); | ||
297 | t[0].rx_buf = buf; | ||
298 | t[0].len = len; | ||
299 | spi_message_add_tail(&t[0], &m); | ||
300 | spi_sync(wl->spi, &m); | ||
301 | return; | ||
302 | } | ||
303 | } | ||
304 | |||
305 | /* The SPI bus is unresponsive, the read failed. */ | ||
306 | memset(buf, 0, len); | ||
307 | wl1271_error("SPI read busy-word timeout!\n"); | ||
308 | } | ||
309 | |||
247 | void wl1271_spi_read(struct wl1271 *wl, int addr, void *buf, | 310 | void wl1271_spi_read(struct wl1271 *wl, int addr, void *buf, |
248 | size_t len, bool fixed) | 311 | size_t len, bool fixed) |
249 | { | 312 | { |
250 | struct spi_transfer t[3]; | 313 | struct spi_transfer t[3]; |
251 | struct spi_message m; | 314 | struct spi_message m; |
252 | u8 *busy_buf; | 315 | u32 *busy_buf; |
253 | u32 *cmd; | 316 | u32 *cmd; |
254 | 317 | ||
255 | cmd = &wl->buffer_cmd; | 318 | cmd = &wl->buffer_cmd; |
@@ -281,7 +344,9 @@ void wl1271_spi_read(struct wl1271 *wl, int addr, void *buf, | |||
281 | 344 | ||
282 | spi_sync(wl->spi, &m); | 345 | spi_sync(wl->spi, &m); |
283 | 346 | ||
284 | /* FIXME: check busy words */ | 347 | /* Check busy words */ |
348 | if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1)) | ||
349 | wl1271_spi_read_busy(wl, buf, len); | ||
285 | 350 | ||
286 | wl1271_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd)); | 351 | wl1271_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd)); |
287 | wl1271_dump(DEBUG_SPI, "spi_read buf <- ", buf, len); | 352 | wl1271_dump(DEBUG_SPI, "spi_read buf <- ", buf, len); |