diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/net/wireless/wl12xx/wl1271_spi.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/net/wireless/wl12xx/wl1271_spi.c')
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_spi.c | 254 |
1 files changed, 65 insertions, 189 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c index 4a12880c16a8..053c84aceb49 100644 --- a/drivers/net/wireless/wl12xx/wl1271_spi.c +++ b/drivers/net/wireless/wl12xx/wl1271_spi.c | |||
@@ -25,21 +25,12 @@ | |||
25 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
26 | #include <linux/crc7.h> | 26 | #include <linux/crc7.h> |
27 | #include <linux/spi/spi.h> | 27 | #include <linux/spi/spi.h> |
28 | #include <linux/slab.h> | ||
28 | 29 | ||
29 | #include "wl1271.h" | 30 | #include "wl1271.h" |
30 | #include "wl12xx_80211.h" | 31 | #include "wl12xx_80211.h" |
31 | #include "wl1271_spi.h" | 32 | #include "wl1271_spi.h" |
32 | 33 | ||
33 | static int wl1271_translate_reg_addr(struct wl1271 *wl, int addr) | ||
34 | { | ||
35 | return addr - wl->physical_reg_addr + wl->virtual_reg_addr; | ||
36 | } | ||
37 | |||
38 | static int wl1271_translate_mem_addr(struct wl1271 *wl, int addr) | ||
39 | { | ||
40 | return addr - wl->physical_mem_addr + wl->virtual_mem_addr; | ||
41 | } | ||
42 | |||
43 | 34 | ||
44 | void wl1271_spi_reset(struct wl1271 *wl) | 35 | void wl1271_spi_reset(struct wl1271 *wl) |
45 | { | 36 | { |
@@ -121,135 +112,78 @@ void wl1271_spi_init(struct wl1271 *wl) | |||
121 | wl1271_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN); | 112 | wl1271_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN); |
122 | } | 113 | } |
123 | 114 | ||
124 | /* Set the SPI partitions to access the chip addresses | 115 | #define WL1271_BUSY_WORD_TIMEOUT 1000 |
125 | * | 116 | |
126 | * There are two VIRTUAL (SPI) partitions (the memory partition and the | 117 | /* FIXME: Check busy words, removed due to SPI bug */ |
127 | * registers partition), which are mapped to two different areas of the | 118 | #if 0 |
128 | * PHYSICAL (hardware) memory. This function also makes other checks to | 119 | static void wl1271_spi_read_busy(struct wl1271 *wl, void *buf, size_t len) |
129 | * ensure that the partitions are not overlapping. In the diagram below, the | ||
130 | * memory partition comes before the register partition, but the opposite is | ||
131 | * also supported. | ||
132 | * | ||
133 | * PHYSICAL address | ||
134 | * space | ||
135 | * | ||
136 | * | | | ||
137 | * ...+----+--> mem_start | ||
138 | * VIRTUAL address ... | | | ||
139 | * space ... | | [PART_0] | ||
140 | * ... | | | ||
141 | * 0x00000000 <--+----+... ...+----+--> mem_start + mem_size | ||
142 | * | | ... | | | ||
143 | * |MEM | ... | | | ||
144 | * | | ... | | | ||
145 | * part_size <--+----+... | | {unused area) | ||
146 | * | | ... | | | ||
147 | * |REG | ... | | | ||
148 | * part_size | | ... | | | ||
149 | * + <--+----+... ...+----+--> reg_start | ||
150 | * reg_size ... | | | ||
151 | * ... | | [PART_1] | ||
152 | * ... | | | ||
153 | * ...+----+--> reg_start + reg_size | ||
154 | * | | | ||
155 | * | ||
156 | */ | ||
157 | int wl1271_set_partition(struct wl1271 *wl, | ||
158 | u32 mem_start, u32 mem_size, | ||
159 | u32 reg_start, u32 reg_size) | ||
160 | { | 120 | { |
161 | struct wl1271_partition *partition; | 121 | struct spi_transfer t[1]; |
162 | struct spi_transfer t; | ||
163 | struct spi_message m; | 122 | struct spi_message m; |
164 | size_t len, cmd_len; | 123 | u32 *busy_buf; |
165 | u32 *cmd; | 124 | int num_busy_bytes = 0; |
166 | int addr; | ||
167 | |||
168 | cmd_len = sizeof(u32) + 2 * sizeof(struct wl1271_partition); | ||
169 | cmd = kzalloc(cmd_len, GFP_KERNEL); | ||
170 | if (!cmd) | ||
171 | return -ENOMEM; | ||
172 | |||
173 | spi_message_init(&m); | ||
174 | memset(&t, 0, sizeof(t)); | ||
175 | 125 | ||
176 | partition = (struct wl1271_partition *) (cmd + 1); | 126 | wl1271_info("spi read BUSY!"); |
177 | addr = HW_ACCESS_PART0_SIZE_ADDR; | ||
178 | len = 2 * sizeof(struct wl1271_partition); | ||
179 | 127 | ||
180 | *cmd |= WSPI_CMD_WRITE; | 128 | /* |
181 | *cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH; | 129 | * Look for the non-busy word in the read buffer, and if found, |
182 | *cmd |= addr & WSPI_CMD_BYTE_ADDR; | 130 | * read in the remaining data into the buffer. |
183 | 131 | */ | |
184 | wl1271_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", | 132 | busy_buf = (u32 *)buf; |
185 | mem_start, mem_size); | 133 | for (; (u32)busy_buf < (u32)buf + len; busy_buf++) { |
186 | wl1271_debug(DEBUG_SPI, "reg_start %08X reg_size %08X", | 134 | num_busy_bytes += sizeof(u32); |
187 | reg_start, reg_size); | 135 | if (*busy_buf & 0x1) { |
188 | 136 | spi_message_init(&m); | |
189 | /* Make sure that the two partitions together don't exceed the | 137 | memset(t, 0, sizeof(t)); |
190 | * address range */ | 138 | memmove(buf, busy_buf, len - num_busy_bytes); |
191 | if ((mem_size + reg_size) > HW_ACCESS_MEMORY_MAX_RANGE) { | 139 | t[0].rx_buf = buf + (len - num_busy_bytes); |
192 | wl1271_debug(DEBUG_SPI, "Total size exceeds maximum virtual" | 140 | t[0].len = num_busy_bytes; |
193 | " address range. Truncating partition[0]."); | 141 | spi_message_add_tail(&t[0], &m); |
194 | mem_size = HW_ACCESS_MEMORY_MAX_RANGE - reg_size; | 142 | spi_sync(wl->spi, &m); |
195 | wl1271_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", | 143 | return; |
196 | mem_start, mem_size); | 144 | } |
197 | wl1271_debug(DEBUG_SPI, "reg_start %08X reg_size %08X", | ||
198 | reg_start, reg_size); | ||
199 | } | ||
200 | |||
201 | if ((mem_start < reg_start) && | ||
202 | ((mem_start + mem_size) > reg_start)) { | ||
203 | /* Guarantee that the memory partition doesn't overlap the | ||
204 | * registers partition */ | ||
205 | wl1271_debug(DEBUG_SPI, "End of partition[0] is " | ||
206 | "overlapping partition[1]. Adjusted."); | ||
207 | mem_size = reg_start - mem_start; | ||
208 | wl1271_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", | ||
209 | mem_start, mem_size); | ||
210 | wl1271_debug(DEBUG_SPI, "reg_start %08X reg_size %08X", | ||
211 | reg_start, reg_size); | ||
212 | } else if ((reg_start < mem_start) && | ||
213 | ((reg_start + reg_size) > mem_start)) { | ||
214 | /* Guarantee that the register partition doesn't overlap the | ||
215 | * memory partition */ | ||
216 | wl1271_debug(DEBUG_SPI, "End of partition[1] is" | ||
217 | " overlapping partition[0]. Adjusted."); | ||
218 | reg_size = mem_start - reg_start; | ||
219 | wl1271_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", | ||
220 | mem_start, mem_size); | ||
221 | wl1271_debug(DEBUG_SPI, "reg_start %08X reg_size %08X", | ||
222 | reg_start, reg_size); | ||
223 | } | 145 | } |
224 | 146 | ||
225 | partition[0].start = mem_start; | 147 | /* |
226 | partition[0].size = mem_size; | 148 | * Read further busy words from SPI until a non-busy word is |
227 | partition[1].start = reg_start; | 149 | * encountered, then read the data itself into the buffer. |
228 | partition[1].size = reg_size; | 150 | */ |
229 | 151 | wl1271_info("spi read BUSY-polling needed!"); | |
230 | wl->physical_mem_addr = mem_start; | ||
231 | wl->physical_reg_addr = reg_start; | ||
232 | |||
233 | wl->virtual_mem_addr = 0; | ||
234 | wl->virtual_reg_addr = mem_size; | ||
235 | |||
236 | t.tx_buf = cmd; | ||
237 | t.len = cmd_len; | ||
238 | spi_message_add_tail(&t, &m); | ||
239 | |||
240 | spi_sync(wl->spi, &m); | ||
241 | 152 | ||
242 | kfree(cmd); | 153 | num_busy_bytes = WL1271_BUSY_WORD_TIMEOUT; |
154 | busy_buf = wl->buffer_busyword; | ||
155 | while (num_busy_bytes) { | ||
156 | num_busy_bytes--; | ||
157 | spi_message_init(&m); | ||
158 | memset(t, 0, sizeof(t)); | ||
159 | t[0].rx_buf = busy_buf; | ||
160 | t[0].len = sizeof(u32); | ||
161 | spi_message_add_tail(&t[0], &m); | ||
162 | spi_sync(wl->spi, &m); | ||
163 | |||
164 | if (*busy_buf & 0x1) { | ||
165 | spi_message_init(&m); | ||
166 | memset(t, 0, sizeof(t)); | ||
167 | t[0].rx_buf = buf; | ||
168 | t[0].len = len; | ||
169 | spi_message_add_tail(&t[0], &m); | ||
170 | spi_sync(wl->spi, &m); | ||
171 | return; | ||
172 | } | ||
173 | } | ||
243 | 174 | ||
244 | return 0; | 175 | /* The SPI bus is unresponsive, the read failed. */ |
176 | memset(buf, 0, len); | ||
177 | wl1271_error("SPI read busy-word timeout!\n"); | ||
245 | } | 178 | } |
179 | #endif | ||
246 | 180 | ||
247 | void wl1271_spi_read(struct wl1271 *wl, int addr, void *buf, | 181 | void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, |
248 | size_t len, bool fixed) | 182 | size_t len, bool fixed) |
249 | { | 183 | { |
250 | struct spi_transfer t[3]; | 184 | struct spi_transfer t[3]; |
251 | struct spi_message m; | 185 | struct spi_message m; |
252 | u8 *busy_buf; | 186 | u32 *busy_buf; |
253 | u32 *cmd; | 187 | u32 *cmd; |
254 | 188 | ||
255 | cmd = &wl->buffer_cmd; | 189 | cmd = &wl->buffer_cmd; |
@@ -281,14 +215,16 @@ void wl1271_spi_read(struct wl1271 *wl, int addr, void *buf, | |||
281 | 215 | ||
282 | spi_sync(wl->spi, &m); | 216 | spi_sync(wl->spi, &m); |
283 | 217 | ||
284 | /* FIXME: check busy words */ | 218 | /* FIXME: Check busy words, removed due to SPI bug */ |
219 | /* if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1)) | ||
220 | wl1271_spi_read_busy(wl, buf, len); */ | ||
285 | 221 | ||
286 | wl1271_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd)); | 222 | wl1271_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd)); |
287 | wl1271_dump(DEBUG_SPI, "spi_read buf <- ", buf, len); | 223 | wl1271_dump(DEBUG_SPI, "spi_read buf <- ", buf, len); |
288 | } | 224 | } |
289 | 225 | ||
290 | void wl1271_spi_write(struct wl1271 *wl, int addr, void *buf, | 226 | void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf, |
291 | size_t len, bool fixed) | 227 | size_t len, bool fixed) |
292 | { | 228 | { |
293 | struct spi_transfer t[2]; | 229 | struct spi_transfer t[2]; |
294 | struct spi_message m; | 230 | struct spi_message m; |
@@ -320,63 +256,3 @@ void wl1271_spi_write(struct wl1271 *wl, int addr, void *buf, | |||
320 | wl1271_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd)); | 256 | wl1271_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd)); |
321 | wl1271_dump(DEBUG_SPI, "spi_write buf -> ", buf, len); | 257 | wl1271_dump(DEBUG_SPI, "spi_write buf -> ", buf, len); |
322 | } | 258 | } |
323 | |||
324 | void wl1271_spi_mem_read(struct wl1271 *wl, int addr, void *buf, | ||
325 | size_t len) | ||
326 | { | ||
327 | int physical; | ||
328 | |||
329 | physical = wl1271_translate_mem_addr(wl, addr); | ||
330 | |||
331 | wl1271_spi_read(wl, physical, buf, len, false); | ||
332 | } | ||
333 | |||
334 | void wl1271_spi_mem_write(struct wl1271 *wl, int addr, void *buf, | ||
335 | size_t len) | ||
336 | { | ||
337 | int physical; | ||
338 | |||
339 | physical = wl1271_translate_mem_addr(wl, addr); | ||
340 | |||
341 | wl1271_spi_write(wl, physical, buf, len, false); | ||
342 | } | ||
343 | |||
344 | void wl1271_spi_reg_read(struct wl1271 *wl, int addr, void *buf, size_t len, | ||
345 | bool fixed) | ||
346 | { | ||
347 | int physical; | ||
348 | |||
349 | physical = wl1271_translate_reg_addr(wl, addr); | ||
350 | |||
351 | wl1271_spi_read(wl, physical, buf, len, fixed); | ||
352 | } | ||
353 | |||
354 | void wl1271_spi_reg_write(struct wl1271 *wl, int addr, void *buf, size_t len, | ||
355 | bool fixed) | ||
356 | { | ||
357 | int physical; | ||
358 | |||
359 | physical = wl1271_translate_reg_addr(wl, addr); | ||
360 | |||
361 | wl1271_spi_write(wl, physical, buf, len, fixed); | ||
362 | } | ||
363 | |||
364 | u32 wl1271_mem_read32(struct wl1271 *wl, int addr) | ||
365 | { | ||
366 | return wl1271_read32(wl, wl1271_translate_mem_addr(wl, addr)); | ||
367 | } | ||
368 | |||
369 | void wl1271_mem_write32(struct wl1271 *wl, int addr, u32 val) | ||
370 | { | ||
371 | wl1271_write32(wl, wl1271_translate_mem_addr(wl, addr), val); | ||
372 | } | ||
373 | |||
374 | u32 wl1271_reg_read32(struct wl1271 *wl, int addr) | ||
375 | { | ||
376 | return wl1271_read32(wl, wl1271_translate_reg_addr(wl, addr)); | ||
377 | } | ||
378 | |||
379 | void wl1271_reg_write32(struct wl1271 *wl, int addr, u32 val) | ||
380 | { | ||
381 | wl1271_write32(wl, wl1271_translate_reg_addr(wl, addr), val); | ||
382 | } | ||