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 /drivers/net/wireless/wl12xx/wl1271_spi.c | |
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>
Diffstat (limited to 'drivers/net/wireless/wl12xx/wl1271_spi.c')
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_spi.c | 69 |
1 files changed, 67 insertions, 2 deletions
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); |