aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/wl12xx/wl1271_spi.c
diff options
context:
space:
mode:
authorJuuso Oikarinen <juuso.oikarinen@nokia.com>2009-10-12 08:08:46 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-10-27 16:48:03 -0400
commit451de97adb4d0f101f3befc881a548adb47c467a (patch)
tree6d40eb04db29f66983a6dd98e8bfff7eb654935b /drivers/net/wireless/wl12xx/wl1271_spi.c
parent37079a831d8194e138c03663b7cab281ab1dc181 (diff)
wl1271: Update memory mapping for firmware revision 6.1.0.0.241
Update the memory regions and memory mapping to support firmware revision 6.1.0.0.241. Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com> Reviewed-by: Luciano Coelho <luciano.coelho@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.c178
1 files changed, 64 insertions, 114 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c
index 504991acb052..367f2d3319ac 100644
--- a/drivers/net/wireless/wl12xx/wl1271_spi.c
+++ b/drivers/net/wireless/wl12xx/wl1271_spi.c
@@ -30,17 +30,29 @@
30#include "wl12xx_80211.h" 30#include "wl12xx_80211.h"
31#include "wl1271_spi.h" 31#include "wl1271_spi.h"
32 32
33static int wl1271_translate_reg_addr(struct wl1271 *wl, int addr) 33static int wl1271_translate_addr(struct wl1271 *wl, int addr)
34{ 34{
35 return addr - wl->physical_reg_addr + wl->virtual_reg_addr; 35 /*
36} 36 * To translate, first check to which window of addresses the
37 37 * particular address belongs. Then subtract the starting address
38static int wl1271_translate_mem_addr(struct wl1271 *wl, int addr) 38 * of that window from the address. Then, add offset of the
39{ 39 * translated region.
40 return addr - wl->physical_mem_addr + wl->virtual_mem_addr; 40 *
41 * The translated regions occur next to each other in physical device
42 * memory, so just add the sizes of the preceeding address regions to
43 * get the offset to the new region.
44 *
45 * Currently, only the two first regions are addressed, and the
46 * assumption is that all addresses will fall into either of those
47 * two.
48 */
49 if ((addr >= wl->part.reg.start) &&
50 (addr < wl->part.reg.start + wl->part.reg.size))
51 return addr - wl->part.reg.start + wl->part.mem.size;
52 else
53 return addr - wl->part.mem.start;
41} 54}
42 55
43
44void wl1271_spi_reset(struct wl1271 *wl) 56void wl1271_spi_reset(struct wl1271 *wl)
45{ 57{
46 u8 *cmd; 58 u8 *cmd;
@@ -123,123 +135,61 @@ void wl1271_spi_init(struct wl1271 *wl)
123 135
124/* Set the SPI partitions to access the chip addresses 136/* Set the SPI partitions to access the chip addresses
125 * 137 *
126 * There are two VIRTUAL (SPI) partitions (the memory partition and the 138 * To simplify driver code, a fixed (virtual) memory map is defined for
127 * registers partition), which are mapped to two different areas of the 139 * register and memory addresses. Because in the chipset, in different stages
128 * PHYSICAL (hardware) memory. This function also makes other checks to 140 * of operation, those addresses will move around, an address translation
129 * ensure that the partitions are not overlapping. In the diagram below, the 141 * mechanism is required.
130 * memory partition comes before the register partition, but the opposite is
131 * also supported.
132 * 142 *
133 * PHYSICAL address 143 * There are four partitions (three memory and one register partition),
144 * which are mapped to two different areas of the hardware memory.
145 *
146 * Virtual address
134 * space 147 * space
135 * 148 *
136 * | | 149 * | |
137 * ...+----+--> mem_start 150 * ...+----+--> mem.start
138 * VIRTUAL address ... | | 151 * Physical address ... | |
139 * space ... | | [PART_0] 152 * space ... | | [PART_0]
140 * ... | | 153 * ... | |
141 * 0x00000000 <--+----+... ...+----+--> mem_start + mem_size 154 * 00000000 <--+----+... ...+----+--> mem.start + mem.size
142 * | | ... | | 155 * | | ... | |
143 * |MEM | ... | | 156 * |MEM | ... | |
144 * | | ... | | 157 * | | ... | |
145 * part_size <--+----+... | | {unused area) 158 * mem.size <--+----+... | | {unused area)
146 * | | ... | | 159 * | | ... | |
147 * |REG | ... | | 160 * |REG | ... | |
148 * part_size | | ... | | 161 * mem.size | | ... | |
149 * + <--+----+... ...+----+--> reg_start 162 * + <--+----+... ...+----+--> reg.start
150 * reg_size ... | | 163 * reg.size | | ... | |
151 * ... | | [PART_1] 164 * |MEM2| ... | | [PART_1]
152 * ... | | 165 * | | ... | |
153 * ...+----+--> reg_start + reg_size 166 * ...+----+--> reg.start + reg.size
154 * | | 167 * | |
155 * 168 *
156 */ 169 */
157int wl1271_set_partition(struct wl1271 *wl, 170int wl1271_set_partition(struct wl1271 *wl,
158 u32 mem_start, u32 mem_size, 171 struct wl1271_partition_set *p)
159 u32 reg_start, u32 reg_size)
160{ 172{
161 struct wl1271_partition *partition; 173 /* copy partition info */
162 struct spi_transfer t; 174 memcpy(&wl->part, p, sizeof(*p));
163 struct spi_message m;
164 size_t len, cmd_len;
165 u32 *cmd;
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
176 partition = (struct wl1271_partition *) (cmd + 1);
177 addr = HW_ACCESS_PART0_SIZE_ADDR;
178 len = 2 * sizeof(struct wl1271_partition);
179
180 *cmd |= WSPI_CMD_WRITE;
181 *cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH;
182 *cmd |= addr & WSPI_CMD_BYTE_ADDR;
183 175
184 wl1271_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", 176 wl1271_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
185 mem_start, mem_size); 177 p->mem.start, p->mem.size);
186 wl1271_debug(DEBUG_SPI, "reg_start %08X reg_size %08X", 178 wl1271_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
187 reg_start, reg_size); 179 p->reg.start, p->reg.size);
188 180 wl1271_debug(DEBUG_SPI, "mem2_start %08X mem2_size %08X",
189 /* Make sure that the two partitions together don't exceed the 181 p->mem2.start, p->mem2.size);
190 * address range */ 182 wl1271_debug(DEBUG_SPI, "mem3_start %08X mem3_size %08X",
191 if ((mem_size + reg_size) > HW_ACCESS_MEMORY_MAX_RANGE) { 183 p->mem3.start, p->mem3.size);
192 wl1271_debug(DEBUG_SPI, "Total size exceeds maximum virtual" 184
193 " address range. Truncating partition[0]."); 185 /* write partition info to the chipset */
194 mem_size = HW_ACCESS_MEMORY_MAX_RANGE - reg_size; 186 wl1271_write32(wl, HW_PART0_START_ADDR, p->mem.start);
195 wl1271_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", 187 wl1271_write32(wl, HW_PART0_SIZE_ADDR, p->mem.size);
196 mem_start, mem_size); 188 wl1271_write32(wl, HW_PART1_START_ADDR, p->reg.start);
197 wl1271_debug(DEBUG_SPI, "reg_start %08X reg_size %08X", 189 wl1271_write32(wl, HW_PART1_SIZE_ADDR, p->reg.size);
198 reg_start, reg_size); 190 wl1271_write32(wl, HW_PART2_START_ADDR, p->mem2.start);
199 } 191 wl1271_write32(wl, HW_PART2_SIZE_ADDR, p->mem2.size);
200 192 wl1271_write32(wl, HW_PART3_START_ADDR, p->mem3.start);
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 }
224
225 partition[0].start = mem_start;
226 partition[0].size = mem_size;
227 partition[1].start = reg_start;
228 partition[1].size = reg_size;
229
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
242 kfree(cmd);
243 193
244 return 0; 194 return 0;
245} 195}
@@ -391,7 +341,7 @@ void wl1271_spi_mem_read(struct wl1271 *wl, int addr, void *buf,
391{ 341{
392 int physical; 342 int physical;
393 343
394 physical = wl1271_translate_mem_addr(wl, addr); 344 physical = wl1271_translate_addr(wl, addr);
395 345
396 wl1271_spi_read(wl, physical, buf, len, false); 346 wl1271_spi_read(wl, physical, buf, len, false);
397} 347}
@@ -401,7 +351,7 @@ void wl1271_spi_mem_write(struct wl1271 *wl, int addr, void *buf,
401{ 351{
402 int physical; 352 int physical;
403 353
404 physical = wl1271_translate_mem_addr(wl, addr); 354 physical = wl1271_translate_addr(wl, addr);
405 355
406 wl1271_spi_write(wl, physical, buf, len, false); 356 wl1271_spi_write(wl, physical, buf, len, false);
407} 357}
@@ -411,7 +361,7 @@ void wl1271_spi_reg_read(struct wl1271 *wl, int addr, void *buf, size_t len,
411{ 361{
412 int physical; 362 int physical;
413 363
414 physical = wl1271_translate_reg_addr(wl, addr); 364 physical = wl1271_translate_addr(wl, addr);
415 365
416 wl1271_spi_read(wl, physical, buf, len, fixed); 366 wl1271_spi_read(wl, physical, buf, len, fixed);
417} 367}
@@ -421,27 +371,27 @@ void wl1271_spi_reg_write(struct wl1271 *wl, int addr, void *buf, size_t len,
421{ 371{
422 int physical; 372 int physical;
423 373
424 physical = wl1271_translate_reg_addr(wl, addr); 374 physical = wl1271_translate_addr(wl, addr);
425 375
426 wl1271_spi_write(wl, physical, buf, len, fixed); 376 wl1271_spi_write(wl, physical, buf, len, fixed);
427} 377}
428 378
429u32 wl1271_mem_read32(struct wl1271 *wl, int addr) 379u32 wl1271_mem_read32(struct wl1271 *wl, int addr)
430{ 380{
431 return wl1271_read32(wl, wl1271_translate_mem_addr(wl, addr)); 381 return wl1271_read32(wl, wl1271_translate_addr(wl, addr));
432} 382}
433 383
434void wl1271_mem_write32(struct wl1271 *wl, int addr, u32 val) 384void wl1271_mem_write32(struct wl1271 *wl, int addr, u32 val)
435{ 385{
436 wl1271_write32(wl, wl1271_translate_mem_addr(wl, addr), val); 386 wl1271_write32(wl, wl1271_translate_addr(wl, addr), val);
437} 387}
438 388
439u32 wl1271_reg_read32(struct wl1271 *wl, int addr) 389u32 wl1271_reg_read32(struct wl1271 *wl, int addr)
440{ 390{
441 return wl1271_read32(wl, wl1271_translate_reg_addr(wl, addr)); 391 return wl1271_read32(wl, wl1271_translate_addr(wl, addr));
442} 392}
443 393
444void wl1271_reg_write32(struct wl1271 *wl, int addr, u32 val) 394void wl1271_reg_write32(struct wl1271 *wl, int addr, u32 val)
445{ 395{
446 wl1271_write32(wl, wl1271_translate_reg_addr(wl, addr), val); 396 wl1271_write32(wl, wl1271_translate_addr(wl, addr), val);
447} 397}