diff options
Diffstat (limited to 'drivers/net/wireless/wl12xx/wl1271_boot.c')
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_boot.c | 251 |
1 files changed, 131 insertions, 120 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c index 8228ef474a7e..024356263065 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.c +++ b/drivers/net/wireless/wl12xx/wl1271_boot.c | |||
@@ -22,11 +22,13 @@ | |||
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <linux/gpio.h> | 24 | #include <linux/gpio.h> |
25 | #include <linux/slab.h> | ||
25 | 26 | ||
26 | #include "wl1271_acx.h" | 27 | #include "wl1271_acx.h" |
27 | #include "wl1271_reg.h" | 28 | #include "wl1271_reg.h" |
28 | #include "wl1271_boot.h" | 29 | #include "wl1271_boot.h" |
29 | #include "wl1271_spi.h" | 30 | #include "wl1271_spi.h" |
31 | #include "wl1271_io.h" | ||
30 | #include "wl1271_event.h" | 32 | #include "wl1271_event.h" |
31 | 33 | ||
32 | static struct wl1271_partition_set part_table[PART_TABLE_LEN] = { | 34 | static struct wl1271_partition_set part_table[PART_TABLE_LEN] = { |
@@ -39,6 +41,14 @@ static struct wl1271_partition_set part_table[PART_TABLE_LEN] = { | |||
39 | .start = REGISTERS_BASE, | 41 | .start = REGISTERS_BASE, |
40 | .size = 0x00008800 | 42 | .size = 0x00008800 |
41 | }, | 43 | }, |
44 | .mem2 = { | ||
45 | .start = 0x00000000, | ||
46 | .size = 0x00000000 | ||
47 | }, | ||
48 | .mem3 = { | ||
49 | .start = 0x00000000, | ||
50 | .size = 0x00000000 | ||
51 | }, | ||
42 | }, | 52 | }, |
43 | 53 | ||
44 | [PART_WORK] = { | 54 | [PART_WORK] = { |
@@ -48,7 +58,15 @@ static struct wl1271_partition_set part_table[PART_TABLE_LEN] = { | |||
48 | }, | 58 | }, |
49 | .reg = { | 59 | .reg = { |
50 | .start = REGISTERS_BASE, | 60 | .start = REGISTERS_BASE, |
51 | .size = 0x0000b000 | 61 | .size = 0x0000a000 |
62 | }, | ||
63 | .mem2 = { | ||
64 | .start = 0x003004f8, | ||
65 | .size = 0x00000004 | ||
66 | }, | ||
67 | .mem3 = { | ||
68 | .start = 0x00040404, | ||
69 | .size = 0x00000000 | ||
52 | }, | 70 | }, |
53 | }, | 71 | }, |
54 | 72 | ||
@@ -60,6 +78,14 @@ static struct wl1271_partition_set part_table[PART_TABLE_LEN] = { | |||
60 | .reg = { | 78 | .reg = { |
61 | .start = DRPW_BASE, | 79 | .start = DRPW_BASE, |
62 | .size = 0x00006000 | 80 | .size = 0x00006000 |
81 | }, | ||
82 | .mem2 = { | ||
83 | .start = 0x00000000, | ||
84 | .size = 0x00000000 | ||
85 | }, | ||
86 | .mem3 = { | ||
87 | .start = 0x00000000, | ||
88 | .size = 0x00000000 | ||
63 | } | 89 | } |
64 | } | 90 | } |
65 | }; | 91 | }; |
@@ -69,19 +95,19 @@ static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag) | |||
69 | u32 cpu_ctrl; | 95 | u32 cpu_ctrl; |
70 | 96 | ||
71 | /* 10.5.0 run the firmware (I) */ | 97 | /* 10.5.0 run the firmware (I) */ |
72 | cpu_ctrl = wl1271_reg_read32(wl, ACX_REG_ECPU_CONTROL); | 98 | cpu_ctrl = wl1271_read32(wl, ACX_REG_ECPU_CONTROL); |
73 | 99 | ||
74 | /* 10.5.1 run the firmware (II) */ | 100 | /* 10.5.1 run the firmware (II) */ |
75 | cpu_ctrl |= flag; | 101 | cpu_ctrl |= flag; |
76 | wl1271_reg_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl); | 102 | wl1271_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl); |
77 | } | 103 | } |
78 | 104 | ||
79 | static void wl1271_boot_fw_version(struct wl1271 *wl) | 105 | static void wl1271_boot_fw_version(struct wl1271 *wl) |
80 | { | 106 | { |
81 | struct wl1271_static_data static_data; | 107 | struct wl1271_static_data static_data; |
82 | 108 | ||
83 | wl1271_spi_mem_read(wl, wl->cmd_box_addr, | 109 | wl1271_read(wl, wl->cmd_box_addr, &static_data, sizeof(static_data), |
84 | &static_data, sizeof(static_data)); | 110 | false); |
85 | 111 | ||
86 | strncpy(wl->chip.fw_ver, static_data.fw_version, | 112 | strncpy(wl->chip.fw_ver, static_data.fw_version, |
87 | sizeof(wl->chip.fw_ver)); | 113 | sizeof(wl->chip.fw_ver)); |
@@ -93,8 +119,9 @@ static void wl1271_boot_fw_version(struct wl1271 *wl) | |||
93 | static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, | 119 | static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, |
94 | size_t fw_data_len, u32 dest) | 120 | size_t fw_data_len, u32 dest) |
95 | { | 121 | { |
122 | struct wl1271_partition_set partition; | ||
96 | int addr, chunk_num, partition_limit; | 123 | int addr, chunk_num, partition_limit; |
97 | u8 *p; | 124 | u8 *p, *chunk; |
98 | 125 | ||
99 | /* whal_FwCtrl_LoadFwImageSm() */ | 126 | /* whal_FwCtrl_LoadFwImageSm() */ |
100 | 127 | ||
@@ -103,16 +130,20 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, | |||
103 | wl1271_debug(DEBUG_BOOT, "fw_data_len %zd chunk_size %d", | 130 | wl1271_debug(DEBUG_BOOT, "fw_data_len %zd chunk_size %d", |
104 | fw_data_len, CHUNK_SIZE); | 131 | fw_data_len, CHUNK_SIZE); |
105 | 132 | ||
106 | |||
107 | if ((fw_data_len % 4) != 0) { | 133 | if ((fw_data_len % 4) != 0) { |
108 | wl1271_error("firmware length not multiple of four"); | 134 | wl1271_error("firmware length not multiple of four"); |
109 | return -EIO; | 135 | return -EIO; |
110 | } | 136 | } |
111 | 137 | ||
112 | wl1271_set_partition(wl, dest, | 138 | chunk = kmalloc(CHUNK_SIZE, GFP_KERNEL); |
113 | part_table[PART_DOWN].mem.size, | 139 | if (!chunk) { |
114 | part_table[PART_DOWN].reg.start, | 140 | wl1271_error("allocation for firmware upload chunk failed"); |
115 | part_table[PART_DOWN].reg.size); | 141 | return -ENOMEM; |
142 | } | ||
143 | |||
144 | memcpy(&partition, &part_table[PART_DOWN], sizeof(partition)); | ||
145 | partition.mem.start = dest; | ||
146 | wl1271_set_partition(wl, &partition); | ||
116 | 147 | ||
117 | /* 10.1 set partition limit and chunk num */ | 148 | /* 10.1 set partition limit and chunk num */ |
118 | chunk_num = 0; | 149 | chunk_num = 0; |
@@ -125,21 +156,17 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, | |||
125 | addr = dest + chunk_num * CHUNK_SIZE; | 156 | addr = dest + chunk_num * CHUNK_SIZE; |
126 | partition_limit = chunk_num * CHUNK_SIZE + | 157 | partition_limit = chunk_num * CHUNK_SIZE + |
127 | part_table[PART_DOWN].mem.size; | 158 | part_table[PART_DOWN].mem.size; |
128 | 159 | partition.mem.start = addr; | |
129 | /* FIXME: Over 80 chars! */ | 160 | wl1271_set_partition(wl, &partition); |
130 | wl1271_set_partition(wl, | ||
131 | addr, | ||
132 | part_table[PART_DOWN].mem.size, | ||
133 | part_table[PART_DOWN].reg.start, | ||
134 | part_table[PART_DOWN].reg.size); | ||
135 | } | 161 | } |
136 | 162 | ||
137 | /* 10.3 upload the chunk */ | 163 | /* 10.3 upload the chunk */ |
138 | addr = dest + chunk_num * CHUNK_SIZE; | 164 | addr = dest + chunk_num * CHUNK_SIZE; |
139 | p = buf + chunk_num * CHUNK_SIZE; | 165 | p = buf + chunk_num * CHUNK_SIZE; |
166 | memcpy(chunk, p, CHUNK_SIZE); | ||
140 | wl1271_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x", | 167 | wl1271_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x", |
141 | p, addr); | 168 | p, addr); |
142 | wl1271_spi_mem_write(wl, addr, p, CHUNK_SIZE); | 169 | wl1271_write(wl, addr, chunk, CHUNK_SIZE, false); |
143 | 170 | ||
144 | chunk_num++; | 171 | chunk_num++; |
145 | } | 172 | } |
@@ -147,28 +174,31 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, | |||
147 | /* 10.4 upload the last chunk */ | 174 | /* 10.4 upload the last chunk */ |
148 | addr = dest + chunk_num * CHUNK_SIZE; | 175 | addr = dest + chunk_num * CHUNK_SIZE; |
149 | p = buf + chunk_num * CHUNK_SIZE; | 176 | p = buf + chunk_num * CHUNK_SIZE; |
177 | memcpy(chunk, p, fw_data_len % CHUNK_SIZE); | ||
150 | wl1271_debug(DEBUG_BOOT, "uploading fw last chunk (%zd B) 0x%p to 0x%x", | 178 | wl1271_debug(DEBUG_BOOT, "uploading fw last chunk (%zd B) 0x%p to 0x%x", |
151 | fw_data_len % CHUNK_SIZE, p, addr); | 179 | fw_data_len % CHUNK_SIZE, p, addr); |
152 | wl1271_spi_mem_write(wl, addr, p, fw_data_len % CHUNK_SIZE); | 180 | wl1271_write(wl, addr, chunk, fw_data_len % CHUNK_SIZE, false); |
153 | 181 | ||
182 | kfree(chunk); | ||
154 | return 0; | 183 | return 0; |
155 | } | 184 | } |
156 | 185 | ||
157 | static int wl1271_boot_upload_firmware(struct wl1271 *wl) | 186 | static int wl1271_boot_upload_firmware(struct wl1271 *wl) |
158 | { | 187 | { |
159 | u32 chunks, addr, len; | 188 | u32 chunks, addr, len; |
189 | int ret = 0; | ||
160 | u8 *fw; | 190 | u8 *fw; |
161 | 191 | ||
162 | fw = wl->fw; | 192 | fw = wl->fw; |
163 | chunks = be32_to_cpup((u32 *) fw); | 193 | chunks = be32_to_cpup((__be32 *) fw); |
164 | fw += sizeof(u32); | 194 | fw += sizeof(u32); |
165 | 195 | ||
166 | wl1271_debug(DEBUG_BOOT, "firmware chunks to be uploaded: %u", chunks); | 196 | wl1271_debug(DEBUG_BOOT, "firmware chunks to be uploaded: %u", chunks); |
167 | 197 | ||
168 | while (chunks--) { | 198 | while (chunks--) { |
169 | addr = be32_to_cpup((u32 *) fw); | 199 | addr = be32_to_cpup((__be32 *) fw); |
170 | fw += sizeof(u32); | 200 | fw += sizeof(u32); |
171 | len = be32_to_cpup((u32 *) fw); | 201 | len = be32_to_cpup((__be32 *) fw); |
172 | fw += sizeof(u32); | 202 | fw += sizeof(u32); |
173 | 203 | ||
174 | if (len > 300000) { | 204 | if (len > 300000) { |
@@ -177,11 +207,13 @@ static int wl1271_boot_upload_firmware(struct wl1271 *wl) | |||
177 | } | 207 | } |
178 | wl1271_debug(DEBUG_BOOT, "chunk %d addr 0x%x len %u", | 208 | wl1271_debug(DEBUG_BOOT, "chunk %d addr 0x%x len %u", |
179 | chunks, addr, len); | 209 | chunks, addr, len); |
180 | wl1271_boot_upload_firmware_chunk(wl, fw, len, addr); | 210 | ret = wl1271_boot_upload_firmware_chunk(wl, fw, len, addr); |
211 | if (ret != 0) | ||
212 | break; | ||
181 | fw += len; | 213 | fw += len; |
182 | } | 214 | } |
183 | 215 | ||
184 | return 0; | 216 | return ret; |
185 | } | 217 | } |
186 | 218 | ||
187 | static int wl1271_boot_upload_nvs(struct wl1271 *wl) | 219 | static int wl1271_boot_upload_nvs(struct wl1271 *wl) |
@@ -189,23 +221,14 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) | |||
189 | size_t nvs_len, burst_len; | 221 | size_t nvs_len, burst_len; |
190 | int i; | 222 | int i; |
191 | u32 dest_addr, val; | 223 | u32 dest_addr, val; |
192 | u8 *nvs_ptr, *nvs, *nvs_aligned; | 224 | u8 *nvs_ptr, *nvs_aligned; |
193 | 225 | ||
194 | nvs = wl->nvs; | 226 | if (wl->nvs == NULL) |
195 | if (nvs == NULL) | ||
196 | return -ENODEV; | 227 | return -ENODEV; |
197 | 228 | ||
198 | nvs_ptr = nvs; | 229 | /* only the first part of the NVS needs to be uploaded */ |
199 | 230 | nvs_len = sizeof(wl->nvs->nvs); | |
200 | nvs_len = wl->nvs_len; | 231 | nvs_ptr = (u8 *)wl->nvs->nvs; |
201 | |||
202 | /* Update the device MAC address into the nvs */ | ||
203 | nvs[11] = wl->mac_addr[0]; | ||
204 | nvs[10] = wl->mac_addr[1]; | ||
205 | nvs[6] = wl->mac_addr[2]; | ||
206 | nvs[5] = wl->mac_addr[3]; | ||
207 | nvs[4] = wl->mac_addr[4]; | ||
208 | nvs[3] = wl->mac_addr[5]; | ||
209 | 232 | ||
210 | /* | 233 | /* |
211 | * Layout before the actual NVS tables: | 234 | * Layout before the actual NVS tables: |
@@ -235,7 +258,7 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) | |||
235 | wl1271_debug(DEBUG_BOOT, | 258 | wl1271_debug(DEBUG_BOOT, |
236 | "nvs burst write 0x%x: 0x%x", | 259 | "nvs burst write 0x%x: 0x%x", |
237 | dest_addr, val); | 260 | dest_addr, val); |
238 | wl1271_reg_write32(wl, dest_addr, val); | 261 | wl1271_write32(wl, dest_addr, val); |
239 | 262 | ||
240 | nvs_ptr += 4; | 263 | nvs_ptr += 4; |
241 | dest_addr += 4; | 264 | dest_addr += 4; |
@@ -247,26 +270,29 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) | |||
247 | * is 7 bytes further. | 270 | * is 7 bytes further. |
248 | */ | 271 | */ |
249 | nvs_ptr += 7; | 272 | nvs_ptr += 7; |
250 | nvs_len -= nvs_ptr - nvs; | 273 | nvs_len -= nvs_ptr - (u8 *)wl->nvs->nvs; |
251 | nvs_len = ALIGN(nvs_len, 4); | 274 | nvs_len = ALIGN(nvs_len, 4); |
252 | 275 | ||
253 | /* FIXME: The driver sets the partition here, but this is not needed, | 276 | /* FIXME: The driver sets the partition here, but this is not needed, |
254 | since it sets to the same one as currently in use */ | 277 | since it sets to the same one as currently in use */ |
255 | /* Now we must set the partition correctly */ | 278 | /* Now we must set the partition correctly */ |
256 | wl1271_set_partition(wl, | 279 | wl1271_set_partition(wl, &part_table[PART_WORK]); |
257 | part_table[PART_WORK].mem.start, | ||
258 | part_table[PART_WORK].mem.size, | ||
259 | part_table[PART_WORK].reg.start, | ||
260 | part_table[PART_WORK].reg.size); | ||
261 | 280 | ||
262 | /* Copy the NVS tables to a new block to ensure alignment */ | 281 | /* Copy the NVS tables to a new block to ensure alignment */ |
263 | nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL); | 282 | /* FIXME: We jump 3 more bytes before uploading the NVS. It seems |
283 | that our NVS files have three extra zeros here. I'm not sure whether | ||
284 | the problem is in our NVS generation or we should really jumpt these | ||
285 | 3 bytes here */ | ||
286 | nvs_ptr += 3; | ||
287 | |||
288 | nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL); if | ||
289 | (!nvs_aligned) return -ENOMEM; | ||
264 | 290 | ||
265 | /* And finally we upload the NVS tables */ | 291 | /* And finally we upload the NVS tables */ |
266 | /* FIXME: In wl1271, we upload everything at once. | 292 | /* FIXME: In wl1271, we upload everything at once. |
267 | No endianness handling needed here?! The ref driver doesn't do | 293 | No endianness handling needed here?! The ref driver doesn't do |
268 | anything about it at this point */ | 294 | anything about it at this point */ |
269 | wl1271_spi_mem_write(wl, CMD_MBOX_ADDRESS, nvs_aligned, nvs_len); | 295 | wl1271_write(wl, CMD_MBOX_ADDRESS, nvs_aligned, nvs_len, false); |
270 | 296 | ||
271 | kfree(nvs_aligned); | 297 | kfree(nvs_aligned); |
272 | return 0; | 298 | return 0; |
@@ -275,9 +301,9 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) | |||
275 | static void wl1271_boot_enable_interrupts(struct wl1271 *wl) | 301 | static void wl1271_boot_enable_interrupts(struct wl1271 *wl) |
276 | { | 302 | { |
277 | enable_irq(wl->irq); | 303 | enable_irq(wl->irq); |
278 | wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK, | 304 | wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, |
279 | WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK)); | 305 | WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK)); |
280 | wl1271_reg_write32(wl, HI_CFG, HI_CFG_DEF_VAL); | 306 | wl1271_write32(wl, HI_CFG, HI_CFG_DEF_VAL); |
281 | } | 307 | } |
282 | 308 | ||
283 | static int wl1271_boot_soft_reset(struct wl1271 *wl) | 309 | static int wl1271_boot_soft_reset(struct wl1271 *wl) |
@@ -286,12 +312,12 @@ static int wl1271_boot_soft_reset(struct wl1271 *wl) | |||
286 | u32 boot_data; | 312 | u32 boot_data; |
287 | 313 | ||
288 | /* perform soft reset */ | 314 | /* perform soft reset */ |
289 | wl1271_reg_write32(wl, ACX_REG_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT); | 315 | wl1271_write32(wl, ACX_REG_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT); |
290 | 316 | ||
291 | /* SOFT_RESET is self clearing */ | 317 | /* SOFT_RESET is self clearing */ |
292 | timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME); | 318 | timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME); |
293 | while (1) { | 319 | while (1) { |
294 | boot_data = wl1271_reg_read32(wl, ACX_REG_SLV_SOFT_RESET); | 320 | boot_data = wl1271_read32(wl, ACX_REG_SLV_SOFT_RESET); |
295 | wl1271_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data); | 321 | wl1271_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data); |
296 | if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0) | 322 | if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0) |
297 | break; | 323 | break; |
@@ -307,10 +333,10 @@ static int wl1271_boot_soft_reset(struct wl1271 *wl) | |||
307 | } | 333 | } |
308 | 334 | ||
309 | /* disable Rx/Tx */ | 335 | /* disable Rx/Tx */ |
310 | wl1271_reg_write32(wl, ENABLE, 0x0); | 336 | wl1271_write32(wl, ENABLE, 0x0); |
311 | 337 | ||
312 | /* disable auto calibration on start*/ | 338 | /* disable auto calibration on start*/ |
313 | wl1271_reg_write32(wl, SPARE_A2, 0xffff); | 339 | wl1271_write32(wl, SPARE_A2, 0xffff); |
314 | 340 | ||
315 | return 0; | 341 | return 0; |
316 | } | 342 | } |
@@ -322,7 +348,7 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) | |||
322 | 348 | ||
323 | wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT); | 349 | wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT); |
324 | 350 | ||
325 | chip_id = wl1271_reg_read32(wl, CHIP_ID_B); | 351 | chip_id = wl1271_read32(wl, CHIP_ID_B); |
326 | 352 | ||
327 | wl1271_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id); | 353 | wl1271_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id); |
328 | 354 | ||
@@ -335,7 +361,7 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) | |||
335 | loop = 0; | 361 | loop = 0; |
336 | while (loop++ < INIT_LOOP) { | 362 | while (loop++ < INIT_LOOP) { |
337 | udelay(INIT_LOOP_DELAY); | 363 | udelay(INIT_LOOP_DELAY); |
338 | interrupt = wl1271_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); | 364 | interrupt = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); |
339 | 365 | ||
340 | if (interrupt == 0xffffffff) { | 366 | if (interrupt == 0xffffffff) { |
341 | wl1271_error("error reading hardware complete " | 367 | wl1271_error("error reading hardware complete " |
@@ -344,30 +370,26 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) | |||
344 | } | 370 | } |
345 | /* check that ACX_INTR_INIT_COMPLETE is enabled */ | 371 | /* check that ACX_INTR_INIT_COMPLETE is enabled */ |
346 | else if (interrupt & WL1271_ACX_INTR_INIT_COMPLETE) { | 372 | else if (interrupt & WL1271_ACX_INTR_INIT_COMPLETE) { |
347 | wl1271_reg_write32(wl, ACX_REG_INTERRUPT_ACK, | 373 | wl1271_write32(wl, ACX_REG_INTERRUPT_ACK, |
348 | WL1271_ACX_INTR_INIT_COMPLETE); | 374 | WL1271_ACX_INTR_INIT_COMPLETE); |
349 | break; | 375 | break; |
350 | } | 376 | } |
351 | } | 377 | } |
352 | 378 | ||
353 | if (loop >= INIT_LOOP) { | 379 | if (loop > INIT_LOOP) { |
354 | wl1271_error("timeout waiting for the hardware to " | 380 | wl1271_error("timeout waiting for the hardware to " |
355 | "complete initialization"); | 381 | "complete initialization"); |
356 | return -EIO; | 382 | return -EIO; |
357 | } | 383 | } |
358 | 384 | ||
359 | /* get hardware config command mail box */ | 385 | /* get hardware config command mail box */ |
360 | wl->cmd_box_addr = wl1271_reg_read32(wl, REG_COMMAND_MAILBOX_PTR); | 386 | wl->cmd_box_addr = wl1271_read32(wl, REG_COMMAND_MAILBOX_PTR); |
361 | 387 | ||
362 | /* get hardware config event mail box */ | 388 | /* get hardware config event mail box */ |
363 | wl->event_box_addr = wl1271_reg_read32(wl, REG_EVENT_MAILBOX_PTR); | 389 | wl->event_box_addr = wl1271_read32(wl, REG_EVENT_MAILBOX_PTR); |
364 | 390 | ||
365 | /* set the working partition to its "running" mode offset */ | 391 | /* set the working partition to its "running" mode offset */ |
366 | wl1271_set_partition(wl, | 392 | wl1271_set_partition(wl, &part_table[PART_WORK]); |
367 | part_table[PART_WORK].mem.start, | ||
368 | part_table[PART_WORK].mem.size, | ||
369 | part_table[PART_WORK].reg.start, | ||
370 | part_table[PART_WORK].reg.size); | ||
371 | 393 | ||
372 | wl1271_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x event_box_addr 0x%x", | 394 | wl1271_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x event_box_addr 0x%x", |
373 | wl->cmd_box_addr, wl->event_box_addr); | 395 | wl->cmd_box_addr, wl->event_box_addr); |
@@ -379,11 +401,10 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) | |||
379 | * ready to receive event from the command mailbox | 401 | * ready to receive event from the command mailbox |
380 | */ | 402 | */ |
381 | 403 | ||
382 | /* enable gpio interrupts */ | 404 | /* unmask required mbox events */ |
383 | wl1271_boot_enable_interrupts(wl); | 405 | wl->event_mask = BSS_LOSE_EVENT_ID | |
384 | 406 | SCAN_COMPLETE_EVENT_ID | | |
385 | /* unmask all mbox events */ | 407 | PS_REPORT_EVENT_ID; |
386 | wl->event_mask = 0xffffffff; | ||
387 | 408 | ||
388 | ret = wl1271_event_unmask(wl); | 409 | ret = wl1271_event_unmask(wl); |
389 | if (ret < 0) { | 410 | if (ret < 0) { |
@@ -399,34 +420,13 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) | |||
399 | 420 | ||
400 | static int wl1271_boot_write_irq_polarity(struct wl1271 *wl) | 421 | static int wl1271_boot_write_irq_polarity(struct wl1271 *wl) |
401 | { | 422 | { |
402 | u32 polarity, status, i; | 423 | u32 polarity; |
403 | |||
404 | wl1271_reg_write32(wl, OCP_POR_CTR, OCP_REG_POLARITY); | ||
405 | wl1271_reg_write32(wl, OCP_CMD, OCP_CMD_READ); | ||
406 | |||
407 | /* Wait until the command is complete (ie. bit 18 is set) */ | ||
408 | for (i = 0; i < OCP_CMD_LOOP; i++) { | ||
409 | polarity = wl1271_reg_read32(wl, OCP_DATA_READ); | ||
410 | if (polarity & OCP_READY_MASK) | ||
411 | break; | ||
412 | } | ||
413 | if (i == OCP_CMD_LOOP) { | ||
414 | wl1271_error("OCP command timeout!"); | ||
415 | return -EIO; | ||
416 | } | ||
417 | 424 | ||
418 | status = polarity & OCP_STATUS_MASK; | 425 | polarity = wl1271_top_reg_read(wl, OCP_REG_POLARITY); |
419 | if (status != OCP_STATUS_OK) { | ||
420 | wl1271_error("OCP command failed (%d)", status); | ||
421 | return -EIO; | ||
422 | } | ||
423 | 426 | ||
424 | /* We use HIGH polarity, so unset the LOW bit */ | 427 | /* We use HIGH polarity, so unset the LOW bit */ |
425 | polarity &= ~POLARITY_LOW; | 428 | polarity &= ~POLARITY_LOW; |
426 | 429 | wl1271_top_reg_write(wl, OCP_REG_POLARITY, polarity); | |
427 | wl1271_reg_write32(wl, OCP_POR_CTR, OCP_REG_POLARITY); | ||
428 | wl1271_reg_write32(wl, OCP_DATA_WRITE, polarity); | ||
429 | wl1271_reg_write32(wl, OCP_CMD, OCP_CMD_WRITE); | ||
430 | 430 | ||
431 | return 0; | 431 | return 0; |
432 | } | 432 | } |
@@ -436,16 +436,32 @@ int wl1271_boot(struct wl1271 *wl) | |||
436 | int ret = 0; | 436 | int ret = 0; |
437 | u32 tmp, clk, pause; | 437 | u32 tmp, clk, pause; |
438 | 438 | ||
439 | if (REF_CLOCK == 0 || REF_CLOCK == 2) | 439 | if (REF_CLOCK == 0 || REF_CLOCK == 2 || REF_CLOCK == 4) |
440 | /* ref clk: 19.2/38.4 */ | 440 | /* ref clk: 19.2/38.4/38.4-XTAL */ |
441 | clk = 0x3; | 441 | clk = 0x3; |
442 | else if (REF_CLOCK == 1 || REF_CLOCK == 3) | 442 | else if (REF_CLOCK == 1 || REF_CLOCK == 3) |
443 | /* ref clk: 26/52 */ | 443 | /* ref clk: 26/52 */ |
444 | clk = 0x5; | 444 | clk = 0x5; |
445 | 445 | ||
446 | wl1271_reg_write32(wl, PLL_PARAMETERS, clk); | 446 | if (REF_CLOCK != 0) { |
447 | u16 val; | ||
448 | /* Set clock type */ | ||
449 | val = wl1271_top_reg_read(wl, OCP_REG_CLK_TYPE); | ||
450 | val &= FREF_CLK_TYPE_BITS; | ||
451 | val |= CLK_REQ_PRCM; | ||
452 | wl1271_top_reg_write(wl, OCP_REG_CLK_TYPE, val); | ||
453 | } else { | ||
454 | u16 val; | ||
455 | /* Set clock polarity */ | ||
456 | val = wl1271_top_reg_read(wl, OCP_REG_CLK_POLARITY); | ||
457 | val &= FREF_CLK_POLARITY_BITS; | ||
458 | val |= CLK_REQ_OUTN_SEL; | ||
459 | wl1271_top_reg_write(wl, OCP_REG_CLK_POLARITY, val); | ||
460 | } | ||
461 | |||
462 | wl1271_write32(wl, PLL_PARAMETERS, clk); | ||
447 | 463 | ||
448 | pause = wl1271_reg_read32(wl, PLL_PARAMETERS); | 464 | pause = wl1271_read32(wl, PLL_PARAMETERS); |
449 | 465 | ||
450 | wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause); | 466 | wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause); |
451 | 467 | ||
@@ -454,39 +470,31 @@ int wl1271_boot(struct wl1271 *wl) | |||
454 | * 0x3ff (magic number ). How does | 470 | * 0x3ff (magic number ). How does |
455 | * this work?! */ | 471 | * this work?! */ |
456 | pause |= WU_COUNTER_PAUSE_VAL; | 472 | pause |= WU_COUNTER_PAUSE_VAL; |
457 | wl1271_reg_write32(wl, WU_COUNTER_PAUSE, pause); | 473 | wl1271_write32(wl, WU_COUNTER_PAUSE, pause); |
458 | 474 | ||
459 | /* Continue the ELP wake up sequence */ | 475 | /* Continue the ELP wake up sequence */ |
460 | wl1271_reg_write32(wl, WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); | 476 | wl1271_write32(wl, WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); |
461 | udelay(500); | 477 | udelay(500); |
462 | 478 | ||
463 | wl1271_set_partition(wl, | 479 | wl1271_set_partition(wl, &part_table[PART_DRPW]); |
464 | part_table[PART_DRPW].mem.start, | ||
465 | part_table[PART_DRPW].mem.size, | ||
466 | part_table[PART_DRPW].reg.start, | ||
467 | part_table[PART_DRPW].reg.size); | ||
468 | 480 | ||
469 | /* Read-modify-write DRPW_SCRATCH_START register (see next state) | 481 | /* Read-modify-write DRPW_SCRATCH_START register (see next state) |
470 | to be used by DRPw FW. The RTRIM value will be added by the FW | 482 | to be used by DRPw FW. The RTRIM value will be added by the FW |
471 | before taking DRPw out of reset */ | 483 | before taking DRPw out of reset */ |
472 | 484 | ||
473 | wl1271_debug(DEBUG_BOOT, "DRPW_SCRATCH_START %08x", DRPW_SCRATCH_START); | 485 | wl1271_debug(DEBUG_BOOT, "DRPW_SCRATCH_START %08x", DRPW_SCRATCH_START); |
474 | clk = wl1271_reg_read32(wl, DRPW_SCRATCH_START); | 486 | clk = wl1271_read32(wl, DRPW_SCRATCH_START); |
475 | 487 | ||
476 | wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk); | 488 | wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk); |
477 | 489 | ||
478 | /* 2 */ | 490 | /* 2 */ |
479 | clk |= (REF_CLOCK << 1) << 4; | 491 | clk |= (REF_CLOCK << 1) << 4; |
480 | wl1271_reg_write32(wl, DRPW_SCRATCH_START, clk); | 492 | wl1271_write32(wl, DRPW_SCRATCH_START, clk); |
481 | 493 | ||
482 | wl1271_set_partition(wl, | 494 | wl1271_set_partition(wl, &part_table[PART_WORK]); |
483 | part_table[PART_WORK].mem.start, | ||
484 | part_table[PART_WORK].mem.size, | ||
485 | part_table[PART_WORK].reg.start, | ||
486 | part_table[PART_WORK].reg.size); | ||
487 | 495 | ||
488 | /* Disable interrupts */ | 496 | /* Disable interrupts */ |
489 | wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); | 497 | wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); |
490 | 498 | ||
491 | ret = wl1271_boot_soft_reset(wl); | 499 | ret = wl1271_boot_soft_reset(wl); |
492 | if (ret < 0) | 500 | if (ret < 0) |
@@ -501,22 +509,22 @@ int wl1271_boot(struct wl1271 *wl) | |||
501 | * ACX_EEPROMLESS_IND_REG */ | 509 | * ACX_EEPROMLESS_IND_REG */ |
502 | wl1271_debug(DEBUG_BOOT, "ACX_EEPROMLESS_IND_REG"); | 510 | wl1271_debug(DEBUG_BOOT, "ACX_EEPROMLESS_IND_REG"); |
503 | 511 | ||
504 | wl1271_reg_write32(wl, ACX_EEPROMLESS_IND_REG, ACX_EEPROMLESS_IND_REG); | 512 | wl1271_write32(wl, ACX_EEPROMLESS_IND_REG, ACX_EEPROMLESS_IND_REG); |
505 | 513 | ||
506 | tmp = wl1271_reg_read32(wl, CHIP_ID_B); | 514 | tmp = wl1271_read32(wl, CHIP_ID_B); |
507 | 515 | ||
508 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp); | 516 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp); |
509 | 517 | ||
510 | /* 6. read the EEPROM parameters */ | 518 | /* 6. read the EEPROM parameters */ |
511 | tmp = wl1271_reg_read32(wl, SCR_PAD2); | 519 | tmp = wl1271_read32(wl, SCR_PAD2); |
512 | 520 | ||
513 | ret = wl1271_boot_write_irq_polarity(wl); | 521 | ret = wl1271_boot_write_irq_polarity(wl); |
514 | if (ret < 0) | 522 | if (ret < 0) |
515 | goto out; | 523 | goto out; |
516 | 524 | ||
517 | /* FIXME: Need to check whether this is really what we want */ | 525 | /* FIXME: Need to check whether this is really what we want */ |
518 | wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK, | 526 | wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, |
519 | WL1271_ACX_ALL_EVENTS_VECTOR); | 527 | WL1271_ACX_ALL_EVENTS_VECTOR); |
520 | 528 | ||
521 | /* WL1271: The reference driver skips steps 7 to 10 (jumps directly | 529 | /* WL1271: The reference driver skips steps 7 to 10 (jumps directly |
522 | * to upload_fw) */ | 530 | * to upload_fw) */ |
@@ -530,6 +538,9 @@ int wl1271_boot(struct wl1271 *wl) | |||
530 | if (ret < 0) | 538 | if (ret < 0) |
531 | goto out; | 539 | goto out; |
532 | 540 | ||
541 | /* Enable firmware interrupts now */ | ||
542 | wl1271_boot_enable_interrupts(wl); | ||
543 | |||
533 | /* set the wl1271 default filters */ | 544 | /* set the wl1271 default filters */ |
534 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; | 545 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; |
535 | wl->rx_filter = WL1271_DEFAULT_RX_FILTER; | 546 | wl->rx_filter = WL1271_DEFAULT_RX_FILTER; |