diff options
author | Teemu Paasikivi <ext-teemu.3.paasikivi@nokia.com> | 2010-02-18 06:25:54 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-02-19 15:52:47 -0500 |
commit | 521a5b2137cc15430e3b1ea4c148663d1dbe077f (patch) | |
tree | 35a7f3ef2c8c66f9e9c0a9799ec729cd3be567fe | |
parent | c8c90873520ef4c201cfd03b4892ca8bbf551e2e (diff) |
wl1271: Moved common IO functions from wl271_spi.c to wl1271_io.c
In prepraration for integration of SDIO implementation moved some IO
functions common for SPI and SDIO to separate file.
Signed-off-by: Teemu Paasikivi <ext-teemu.3.paasikivi@nokia.com>
Reviewed-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/wl12xx/Makefile | 3 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_io.c | 203 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_io.h | 37 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_spi.c | 157 |
4 files changed, 242 insertions, 158 deletions
diff --git a/drivers/net/wireless/wl12xx/Makefile b/drivers/net/wireless/wl12xx/Makefile index d089b5d6a513..f47ec94c16dc 100644 --- a/drivers/net/wireless/wl12xx/Makefile +++ b/drivers/net/wireless/wl12xx/Makefile | |||
@@ -10,6 +10,7 @@ obj-$(CONFIG_WL1251_SDIO) += wl1251_sdio.o | |||
10 | wl1271-objs = wl1271_main.o wl1271_spi.o wl1271_cmd.o \ | 10 | wl1271-objs = wl1271_main.o wl1271_spi.o wl1271_cmd.o \ |
11 | wl1271_event.o wl1271_tx.o wl1271_rx.o \ | 11 | wl1271_event.o wl1271_tx.o wl1271_rx.o \ |
12 | wl1271_ps.o wl1271_acx.o wl1271_boot.o \ | 12 | wl1271_ps.o wl1271_acx.o wl1271_boot.o \ |
13 | wl1271_init.o wl1271_debugfs.o | 13 | wl1271_init.o wl1271_debugfs.o wl1271_io.o |
14 | |||
14 | wl1271-$(CONFIG_NL80211_TESTMODE) += wl1271_testmode.o | 15 | wl1271-$(CONFIG_NL80211_TESTMODE) += wl1271_testmode.o |
15 | obj-$(CONFIG_WL1271) += wl1271.o | 16 | obj-$(CONFIG_WL1271) += wl1271.o |
diff --git a/drivers/net/wireless/wl12xx/wl1271_io.c b/drivers/net/wireless/wl12xx/wl1271_io.c new file mode 100644 index 000000000000..dcb588b4670d --- /dev/null +++ b/drivers/net/wireless/wl12xx/wl1271_io.c | |||
@@ -0,0 +1,203 @@ | |||
1 | /* | ||
2 | * This file is part of wl1271 | ||
3 | * | ||
4 | * Copyright (C) 2008-2010 Nokia Corporation | ||
5 | * | ||
6 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * version 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
20 | * 02110-1301 USA | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #include <linux/module.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/crc7.h> | ||
27 | #include <linux/spi/spi.h> | ||
28 | |||
29 | #include "wl1271.h" | ||
30 | #include "wl12xx_80211.h" | ||
31 | #include "wl1271_spi.h" | ||
32 | #include "wl1271_io.h" | ||
33 | |||
34 | static int wl1271_translate_addr(struct wl1271 *wl, int addr) | ||
35 | { | ||
36 | /* | ||
37 | * To translate, first check to which window of addresses the | ||
38 | * particular address belongs. Then subtract the starting address | ||
39 | * of that window from the address. Then, add offset of the | ||
40 | * translated region. | ||
41 | * | ||
42 | * The translated regions occur next to each other in physical device | ||
43 | * memory, so just add the sizes of the preceeding address regions to | ||
44 | * get the offset to the new region. | ||
45 | * | ||
46 | * Currently, only the two first regions are addressed, and the | ||
47 | * assumption is that all addresses will fall into either of those | ||
48 | * two. | ||
49 | */ | ||
50 | if ((addr >= wl->part.reg.start) && | ||
51 | (addr < wl->part.reg.start + wl->part.reg.size)) | ||
52 | return addr - wl->part.reg.start + wl->part.mem.size; | ||
53 | else | ||
54 | return addr - wl->part.mem.start; | ||
55 | } | ||
56 | |||
57 | /* Set the SPI partitions to access the chip addresses | ||
58 | * | ||
59 | * To simplify driver code, a fixed (virtual) memory map is defined for | ||
60 | * register and memory addresses. Because in the chipset, in different stages | ||
61 | * of operation, those addresses will move around, an address translation | ||
62 | * mechanism is required. | ||
63 | * | ||
64 | * There are four partitions (three memory and one register partition), | ||
65 | * which are mapped to two different areas of the hardware memory. | ||
66 | * | ||
67 | * Virtual address | ||
68 | * space | ||
69 | * | ||
70 | * | | | ||
71 | * ...+----+--> mem.start | ||
72 | * Physical address ... | | | ||
73 | * space ... | | [PART_0] | ||
74 | * ... | | | ||
75 | * 00000000 <--+----+... ...+----+--> mem.start + mem.size | ||
76 | * | | ... | | | ||
77 | * |MEM | ... | | | ||
78 | * | | ... | | | ||
79 | * mem.size <--+----+... | | {unused area) | ||
80 | * | | ... | | | ||
81 | * |REG | ... | | | ||
82 | * mem.size | | ... | | | ||
83 | * + <--+----+... ...+----+--> reg.start | ||
84 | * reg.size | | ... | | | ||
85 | * |MEM2| ... | | [PART_1] | ||
86 | * | | ... | | | ||
87 | * ...+----+--> reg.start + reg.size | ||
88 | * | | | ||
89 | * | ||
90 | */ | ||
91 | int wl1271_set_partition(struct wl1271 *wl, | ||
92 | struct wl1271_partition_set *p) | ||
93 | { | ||
94 | /* copy partition info */ | ||
95 | memcpy(&wl->part, p, sizeof(*p)); | ||
96 | |||
97 | wl1271_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", | ||
98 | p->mem.start, p->mem.size); | ||
99 | wl1271_debug(DEBUG_SPI, "reg_start %08X reg_size %08X", | ||
100 | p->reg.start, p->reg.size); | ||
101 | wl1271_debug(DEBUG_SPI, "mem2_start %08X mem2_size %08X", | ||
102 | p->mem2.start, p->mem2.size); | ||
103 | wl1271_debug(DEBUG_SPI, "mem3_start %08X mem3_size %08X", | ||
104 | p->mem3.start, p->mem3.size); | ||
105 | |||
106 | /* write partition info to the chipset */ | ||
107 | wl1271_raw_write32(wl, HW_PART0_START_ADDR, p->mem.start); | ||
108 | wl1271_raw_write32(wl, HW_PART0_SIZE_ADDR, p->mem.size); | ||
109 | wl1271_raw_write32(wl, HW_PART1_START_ADDR, p->reg.start); | ||
110 | wl1271_raw_write32(wl, HW_PART1_SIZE_ADDR, p->reg.size); | ||
111 | wl1271_raw_write32(wl, HW_PART2_START_ADDR, p->mem2.start); | ||
112 | wl1271_raw_write32(wl, HW_PART2_SIZE_ADDR, p->mem2.size); | ||
113 | wl1271_raw_write32(wl, HW_PART3_START_ADDR, p->mem3.start); | ||
114 | |||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf, | ||
119 | size_t len, bool fixed) | ||
120 | { | ||
121 | wl1271_spi_raw_write(wl, addr, buf, len, fixed); | ||
122 | } | ||
123 | |||
124 | void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf, | ||
125 | size_t len, bool fixed) | ||
126 | { | ||
127 | wl1271_spi_read(wl, addr, buf, len, fixed); | ||
128 | } | ||
129 | |||
130 | void wl1271_spi_read(struct wl1271 *wl, int addr, void *buf, size_t len, | ||
131 | bool fixed) | ||
132 | { | ||
133 | int physical; | ||
134 | |||
135 | physical = wl1271_translate_addr(wl, addr); | ||
136 | |||
137 | wl1271_spi_raw_read(wl, physical, buf, len, fixed); | ||
138 | } | ||
139 | |||
140 | void wl1271_spi_write(struct wl1271 *wl, int addr, void *buf, size_t len, | ||
141 | bool fixed) | ||
142 | { | ||
143 | int physical; | ||
144 | |||
145 | physical = wl1271_translate_addr(wl, addr); | ||
146 | |||
147 | wl1271_spi_raw_write(wl, physical, buf, len, fixed); | ||
148 | } | ||
149 | |||
150 | u32 wl1271_spi_read32(struct wl1271 *wl, int addr) | ||
151 | { | ||
152 | return wl1271_raw_read32(wl, wl1271_translate_addr(wl, addr)); | ||
153 | } | ||
154 | |||
155 | void wl1271_spi_write32(struct wl1271 *wl, int addr, u32 val) | ||
156 | { | ||
157 | wl1271_raw_write32(wl, wl1271_translate_addr(wl, addr), val); | ||
158 | } | ||
159 | |||
160 | void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val) | ||
161 | { | ||
162 | /* write address >> 1 + 0x30000 to OCP_POR_CTR */ | ||
163 | addr = (addr >> 1) + 0x30000; | ||
164 | wl1271_spi_write32(wl, OCP_POR_CTR, addr); | ||
165 | |||
166 | /* write value to OCP_POR_WDATA */ | ||
167 | wl1271_spi_write32(wl, OCP_DATA_WRITE, val); | ||
168 | |||
169 | /* write 1 to OCP_CMD */ | ||
170 | wl1271_spi_write32(wl, OCP_CMD, OCP_CMD_WRITE); | ||
171 | } | ||
172 | |||
173 | u16 wl1271_top_reg_read(struct wl1271 *wl, int addr) | ||
174 | { | ||
175 | u32 val; | ||
176 | int timeout = OCP_CMD_LOOP; | ||
177 | |||
178 | /* write address >> 1 + 0x30000 to OCP_POR_CTR */ | ||
179 | addr = (addr >> 1) + 0x30000; | ||
180 | wl1271_spi_write32(wl, OCP_POR_CTR, addr); | ||
181 | |||
182 | /* write 2 to OCP_CMD */ | ||
183 | wl1271_spi_write32(wl, OCP_CMD, OCP_CMD_READ); | ||
184 | |||
185 | /* poll for data ready */ | ||
186 | do { | ||
187 | val = wl1271_spi_read32(wl, OCP_DATA_READ); | ||
188 | } while (!(val & OCP_READY_MASK) && --timeout); | ||
189 | |||
190 | if (!timeout) { | ||
191 | wl1271_warning("Top register access timed out."); | ||
192 | return 0xffff; | ||
193 | } | ||
194 | |||
195 | /* check data status and return if OK */ | ||
196 | if ((val & OCP_STATUS_MASK) == OCP_STATUS_OK) | ||
197 | return val & 0xffff; | ||
198 | else { | ||
199 | wl1271_warning("Top register access returned error."); | ||
200 | return 0xffff; | ||
201 | } | ||
202 | } | ||
203 | |||
diff --git a/drivers/net/wireless/wl12xx/wl1271_io.h b/drivers/net/wireless/wl12xx/wl1271_io.h new file mode 100644 index 000000000000..2dc6abbe4dd5 --- /dev/null +++ b/drivers/net/wireless/wl12xx/wl1271_io.h | |||
@@ -0,0 +1,37 @@ | |||
1 | /* | ||
2 | * This file is part of wl1271 | ||
3 | * | ||
4 | * Copyright (C) 1998-2009 Texas Instruments. All rights reserved. | ||
5 | * Copyright (C) 2008-2010 Nokia Corporation | ||
6 | * | ||
7 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * version 2 as published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
21 | * 02110-1301 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #ifndef __WL1271_IO_H__ | ||
26 | #define __WL1271_IO_H__ | ||
27 | |||
28 | struct wl1271; | ||
29 | |||
30 | |||
31 | /* Raw target IO, address is not translated */ | ||
32 | void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf, | ||
33 | size_t len, bool fixed); | ||
34 | void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf, | ||
35 | size_t len, bool fixed); | ||
36 | |||
37 | #endif | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c index ee9564aa6ecc..67a82934f36e 100644 --- a/drivers/net/wireless/wl12xx/wl1271_spi.c +++ b/drivers/net/wireless/wl12xx/wl1271_spi.c | |||
@@ -30,28 +30,6 @@ | |||
30 | #include "wl12xx_80211.h" | 30 | #include "wl12xx_80211.h" |
31 | #include "wl1271_spi.h" | 31 | #include "wl1271_spi.h" |
32 | 32 | ||
33 | static int wl1271_translate_addr(struct wl1271 *wl, int addr) | ||
34 | { | ||
35 | /* | ||
36 | * To translate, first check to which window of addresses the | ||
37 | * particular address belongs. Then subtract the starting address | ||
38 | * of that window from the address. Then, add offset of the | ||
39 | * translated region. | ||
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; | ||
54 | } | ||
55 | 33 | ||
56 | void wl1271_spi_reset(struct wl1271 *wl) | 34 | void wl1271_spi_reset(struct wl1271 *wl) |
57 | { | 35 | { |
@@ -133,67 +111,6 @@ void wl1271_spi_init(struct wl1271 *wl) | |||
133 | wl1271_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN); | 111 | wl1271_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN); |
134 | } | 112 | } |
135 | 113 | ||
136 | /* Set the SPI partitions to access the chip addresses | ||
137 | * | ||
138 | * To simplify driver code, a fixed (virtual) memory map is defined for | ||
139 | * register and memory addresses. Because in the chipset, in different stages | ||
140 | * of operation, those addresses will move around, an address translation | ||
141 | * mechanism is required. | ||
142 | * | ||
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 | ||
147 | * space | ||
148 | * | ||
149 | * | | | ||
150 | * ...+----+--> mem.start | ||
151 | * Physical address ... | | | ||
152 | * space ... | | [PART_0] | ||
153 | * ... | | | ||
154 | * 00000000 <--+----+... ...+----+--> mem.start + mem.size | ||
155 | * | | ... | | | ||
156 | * |MEM | ... | | | ||
157 | * | | ... | | | ||
158 | * mem.size <--+----+... | | {unused area) | ||
159 | * | | ... | | | ||
160 | * |REG | ... | | | ||
161 | * mem.size | | ... | | | ||
162 | * + <--+----+... ...+----+--> reg.start | ||
163 | * reg.size | | ... | | | ||
164 | * |MEM2| ... | | [PART_1] | ||
165 | * | | ... | | | ||
166 | * ...+----+--> reg.start + reg.size | ||
167 | * | | | ||
168 | * | ||
169 | */ | ||
170 | int wl1271_set_partition(struct wl1271 *wl, | ||
171 | struct wl1271_partition_set *p) | ||
172 | { | ||
173 | /* copy partition info */ | ||
174 | memcpy(&wl->part, p, sizeof(*p)); | ||
175 | |||
176 | wl1271_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", | ||
177 | p->mem.start, p->mem.size); | ||
178 | wl1271_debug(DEBUG_SPI, "reg_start %08X reg_size %08X", | ||
179 | p->reg.start, p->reg.size); | ||
180 | wl1271_debug(DEBUG_SPI, "mem2_start %08X mem2_size %08X", | ||
181 | p->mem2.start, p->mem2.size); | ||
182 | wl1271_debug(DEBUG_SPI, "mem3_start %08X mem3_size %08X", | ||
183 | p->mem3.start, p->mem3.size); | ||
184 | |||
185 | /* write partition info to the chipset */ | ||
186 | wl1271_raw_write32(wl, HW_PART0_START_ADDR, p->mem.start); | ||
187 | wl1271_raw_write32(wl, HW_PART0_SIZE_ADDR, p->mem.size); | ||
188 | wl1271_raw_write32(wl, HW_PART1_START_ADDR, p->reg.start); | ||
189 | wl1271_raw_write32(wl, HW_PART1_SIZE_ADDR, p->reg.size); | ||
190 | wl1271_raw_write32(wl, HW_PART2_START_ADDR, p->mem2.start); | ||
191 | wl1271_raw_write32(wl, HW_PART2_SIZE_ADDR, p->mem2.size); | ||
192 | wl1271_raw_write32(wl, HW_PART3_START_ADDR, p->mem3.start); | ||
193 | |||
194 | return 0; | ||
195 | } | ||
196 | |||
197 | #define WL1271_BUSY_WORD_TIMEOUT 1000 | 114 | #define WL1271_BUSY_WORD_TIMEOUT 1000 |
198 | 115 | ||
199 | /* FIXME: Check busy words, removed due to SPI bug */ | 116 | /* FIXME: Check busy words, removed due to SPI bug */ |
@@ -338,77 +255,3 @@ void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf, | |||
338 | wl1271_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd)); | 255 | wl1271_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd)); |
339 | wl1271_dump(DEBUG_SPI, "spi_write buf -> ", buf, len); | 256 | wl1271_dump(DEBUG_SPI, "spi_write buf -> ", buf, len); |
340 | } | 257 | } |
341 | |||
342 | void wl1271_spi_read(struct wl1271 *wl, int addr, void *buf, size_t len, | ||
343 | bool fixed) | ||
344 | { | ||
345 | int physical; | ||
346 | |||
347 | physical = wl1271_translate_addr(wl, addr); | ||
348 | |||
349 | wl1271_spi_raw_read(wl, physical, buf, len, fixed); | ||
350 | } | ||
351 | |||
352 | void wl1271_spi_write(struct wl1271 *wl, int addr, void *buf, size_t len, | ||
353 | bool fixed) | ||
354 | { | ||
355 | int physical; | ||
356 | |||
357 | physical = wl1271_translate_addr(wl, addr); | ||
358 | |||
359 | wl1271_spi_raw_write(wl, physical, buf, len, fixed); | ||
360 | } | ||
361 | |||
362 | u32 wl1271_spi_read32(struct wl1271 *wl, int addr) | ||
363 | { | ||
364 | return wl1271_raw_read32(wl, wl1271_translate_addr(wl, addr)); | ||
365 | } | ||
366 | |||
367 | void wl1271_spi_write32(struct wl1271 *wl, int addr, u32 val) | ||
368 | { | ||
369 | wl1271_raw_write32(wl, wl1271_translate_addr(wl, addr), val); | ||
370 | } | ||
371 | |||
372 | void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val) | ||
373 | { | ||
374 | /* write address >> 1 + 0x30000 to OCP_POR_CTR */ | ||
375 | addr = (addr >> 1) + 0x30000; | ||
376 | wl1271_spi_write32(wl, OCP_POR_CTR, addr); | ||
377 | |||
378 | /* write value to OCP_POR_WDATA */ | ||
379 | wl1271_spi_write32(wl, OCP_DATA_WRITE, val); | ||
380 | |||
381 | /* write 1 to OCP_CMD */ | ||
382 | wl1271_spi_write32(wl, OCP_CMD, OCP_CMD_WRITE); | ||
383 | } | ||
384 | |||
385 | u16 wl1271_top_reg_read(struct wl1271 *wl, int addr) | ||
386 | { | ||
387 | u32 val; | ||
388 | int timeout = OCP_CMD_LOOP; | ||
389 | |||
390 | /* write address >> 1 + 0x30000 to OCP_POR_CTR */ | ||
391 | addr = (addr >> 1) + 0x30000; | ||
392 | wl1271_spi_write32(wl, OCP_POR_CTR, addr); | ||
393 | |||
394 | /* write 2 to OCP_CMD */ | ||
395 | wl1271_spi_write32(wl, OCP_CMD, OCP_CMD_READ); | ||
396 | |||
397 | /* poll for data ready */ | ||
398 | do { | ||
399 | val = wl1271_spi_read32(wl, OCP_DATA_READ); | ||
400 | } while (!(val & OCP_READY_MASK) && --timeout); | ||
401 | |||
402 | if (!timeout) { | ||
403 | wl1271_warning("Top register access timed out."); | ||
404 | return 0xffff; | ||
405 | } | ||
406 | |||
407 | /* check data status and return if OK */ | ||
408 | if ((val & OCP_STATUS_MASK) == OCP_STATUS_OK) | ||
409 | return val & 0xffff; | ||
410 | else { | ||
411 | wl1271_warning("Top register access returned error."); | ||
412 | return 0xffff; | ||
413 | } | ||
414 | } | ||