diff options
author | Ivo van Doorn <ivdoorn@gmail.com> | 2010-07-11 06:30:37 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-07-12 16:05:37 -0400 |
commit | f31c9a8c1380e20e95d06925f2e42baf61af4db7 (patch) | |
tree | 266ad6eb4cfe9fcd5951d9ed5bdeae958c904486 | |
parent | ab8966ddc2f7fa3e631efa7478ea2c76d6c9942f (diff) |
rt2x00: Move common firmware loading into rt2800lib
Large parts of the firmware initialization are shared
between rt2800pci and rt2800usb. Move this code into
rt2800lib.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800lib.c | 155 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800lib.h | 15 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800pci.c | 101 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800usb.c | 119 |
4 files changed, 179 insertions, 211 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 9587236b5d51..b66e0fd8f0fa 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c | |||
@@ -33,6 +33,7 @@ | |||
33 | Abstract: rt2800 generic device routines. | 33 | Abstract: rt2800 generic device routines. |
34 | */ | 34 | */ |
35 | 35 | ||
36 | #include <linux/crc-ccitt.h> | ||
36 | #include <linux/kernel.h> | 37 | #include <linux/kernel.h> |
37 | #include <linux/module.h> | 38 | #include <linux/module.h> |
38 | #include <linux/slab.h> | 39 | #include <linux/slab.h> |
@@ -272,6 +273,160 @@ int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev) | |||
272 | } | 273 | } |
273 | EXPORT_SYMBOL_GPL(rt2800_wait_wpdma_ready); | 274 | EXPORT_SYMBOL_GPL(rt2800_wait_wpdma_ready); |
274 | 275 | ||
276 | static bool rt2800_check_firmware_crc(const u8 *data, const size_t len) | ||
277 | { | ||
278 | u16 fw_crc; | ||
279 | u16 crc; | ||
280 | |||
281 | /* | ||
282 | * The last 2 bytes in the firmware array are the crc checksum itself, | ||
283 | * this means that we should never pass those 2 bytes to the crc | ||
284 | * algorithm. | ||
285 | */ | ||
286 | fw_crc = (data[len - 2] << 8 | data[len - 1]); | ||
287 | |||
288 | /* | ||
289 | * Use the crc ccitt algorithm. | ||
290 | * This will return the same value as the legacy driver which | ||
291 | * used bit ordering reversion on the both the firmware bytes | ||
292 | * before input input as well as on the final output. | ||
293 | * Obviously using crc ccitt directly is much more efficient. | ||
294 | */ | ||
295 | crc = crc_ccitt(~0, data, len - 2); | ||
296 | |||
297 | /* | ||
298 | * There is a small difference between the crc-itu-t + bitrev and | ||
299 | * the crc-ccitt crc calculation. In the latter method the 2 bytes | ||
300 | * will be swapped, use swab16 to convert the crc to the correct | ||
301 | * value. | ||
302 | */ | ||
303 | crc = swab16(crc); | ||
304 | |||
305 | return fw_crc == crc; | ||
306 | } | ||
307 | |||
308 | int rt2800_check_firmware(struct rt2x00_dev *rt2x00dev, | ||
309 | const u8 *data, const size_t len) | ||
310 | { | ||
311 | size_t offset = 0; | ||
312 | size_t fw_len; | ||
313 | bool multiple; | ||
314 | |||
315 | /* | ||
316 | * PCI(e) & SOC devices require firmware with a length | ||
317 | * of 8kb. USB devices require firmware files with a length | ||
318 | * of 4kb. Certain USB chipsets however require different firmware, | ||
319 | * which Ralink only provides attached to the original firmware | ||
320 | * file. Thus for USB devices, firmware files have a length | ||
321 | * which is a multiple of 4kb. | ||
322 | */ | ||
323 | if (rt2x00_is_usb(rt2x00dev)) { | ||
324 | fw_len = 4096; | ||
325 | multiple = true; | ||
326 | } else { | ||
327 | fw_len = 8192; | ||
328 | multiple = true; | ||
329 | } | ||
330 | |||
331 | /* | ||
332 | * Validate the firmware length | ||
333 | */ | ||
334 | if (len != fw_len && (!multiple || (len % fw_len) != 0)) | ||
335 | return FW_BAD_LENGTH; | ||
336 | |||
337 | /* | ||
338 | * Check if the chipset requires one of the upper parts | ||
339 | * of the firmware. | ||
340 | */ | ||
341 | if (rt2x00_is_usb(rt2x00dev) && | ||
342 | !rt2x00_rt(rt2x00dev, RT2860) && | ||
343 | !rt2x00_rt(rt2x00dev, RT2872) && | ||
344 | !rt2x00_rt(rt2x00dev, RT3070) && | ||
345 | ((len / fw_len) == 1)) | ||
346 | return FW_BAD_VERSION; | ||
347 | |||
348 | /* | ||
349 | * 8kb firmware files must be checked as if it were | ||
350 | * 2 separate firmware files. | ||
351 | */ | ||
352 | while (offset < len) { | ||
353 | if (!rt2800_check_firmware_crc(data + offset, fw_len)) | ||
354 | return FW_BAD_CRC; | ||
355 | |||
356 | offset += fw_len; | ||
357 | } | ||
358 | |||
359 | return FW_OK; | ||
360 | } | ||
361 | EXPORT_SYMBOL_GPL(rt2800_check_firmware); | ||
362 | |||
363 | int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev, | ||
364 | const u8 *data, const size_t len) | ||
365 | { | ||
366 | unsigned int i; | ||
367 | u32 reg; | ||
368 | |||
369 | /* | ||
370 | * Wait for stable hardware. | ||
371 | */ | ||
372 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | ||
373 | rt2800_register_read(rt2x00dev, MAC_CSR0, ®); | ||
374 | if (reg && reg != ~0) | ||
375 | break; | ||
376 | msleep(1); | ||
377 | } | ||
378 | |||
379 | if (i == REGISTER_BUSY_COUNT) { | ||
380 | ERROR(rt2x00dev, "Unstable hardware.\n"); | ||
381 | return -EBUSY; | ||
382 | } | ||
383 | |||
384 | if (rt2x00_is_pci(rt2x00dev)) | ||
385 | rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000002); | ||
386 | |||
387 | /* | ||
388 | * Disable DMA, will be reenabled later when enabling | ||
389 | * the radio. | ||
390 | */ | ||
391 | rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); | ||
392 | rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); | ||
393 | rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_DMA_BUSY, 0); | ||
394 | rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); | ||
395 | rt2x00_set_field32(®, WPDMA_GLO_CFG_RX_DMA_BUSY, 0); | ||
396 | rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); | ||
397 | rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); | ||
398 | |||
399 | /* | ||
400 | * Write firmware to the device. | ||
401 | */ | ||
402 | rt2800_drv_write_firmware(rt2x00dev, data, len); | ||
403 | |||
404 | /* | ||
405 | * Wait for device to stabilize. | ||
406 | */ | ||
407 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | ||
408 | rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, ®); | ||
409 | if (rt2x00_get_field32(reg, PBF_SYS_CTRL_READY)) | ||
410 | break; | ||
411 | msleep(1); | ||
412 | } | ||
413 | |||
414 | if (i == REGISTER_BUSY_COUNT) { | ||
415 | ERROR(rt2x00dev, "PBF system register not ready.\n"); | ||
416 | return -EBUSY; | ||
417 | } | ||
418 | |||
419 | /* | ||
420 | * Initialize firmware. | ||
421 | */ | ||
422 | rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0); | ||
423 | rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); | ||
424 | msleep(1); | ||
425 | |||
426 | return 0; | ||
427 | } | ||
428 | EXPORT_SYMBOL_GPL(rt2800_load_firmware); | ||
429 | |||
275 | void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc) | 430 | void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc) |
276 | { | 431 | { |
277 | u32 word; | 432 | u32 word; |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h index 10f8f2f8d65b..cecbd3abc35b 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/rt2x00/rt2800lib.h | |||
@@ -41,6 +41,8 @@ struct rt2800_ops { | |||
41 | const unsigned int offset, | 41 | const unsigned int offset, |
42 | const struct rt2x00_field32 field, u32 *reg); | 42 | const struct rt2x00_field32 field, u32 *reg); |
43 | 43 | ||
44 | int (*drv_write_firmware)(struct rt2x00_dev *rt2x00dev, | ||
45 | const u8 *data, const size_t len); | ||
44 | int (*drv_init_registers)(struct rt2x00_dev *rt2x00dev); | 46 | int (*drv_init_registers)(struct rt2x00_dev *rt2x00dev); |
45 | }; | 47 | }; |
46 | 48 | ||
@@ -109,6 +111,14 @@ static inline int rt2800_regbusy_read(struct rt2x00_dev *rt2x00dev, | |||
109 | return rt2800ops->regbusy_read(rt2x00dev, offset, field, reg); | 111 | return rt2800ops->regbusy_read(rt2x00dev, offset, field, reg); |
110 | } | 112 | } |
111 | 113 | ||
114 | static inline int rt2800_drv_write_firmware(struct rt2x00_dev *rt2x00dev, | ||
115 | const u8 *data, const size_t len) | ||
116 | { | ||
117 | const struct rt2800_ops *rt2800ops = rt2x00dev->priv; | ||
118 | |||
119 | return rt2800ops->drv_write_firmware(rt2x00dev, data, len); | ||
120 | } | ||
121 | |||
112 | static inline int rt2800_drv_init_registers(struct rt2x00_dev *rt2x00dev) | 122 | static inline int rt2800_drv_init_registers(struct rt2x00_dev *rt2x00dev) |
113 | { | 123 | { |
114 | const struct rt2800_ops *rt2800ops = rt2x00dev->priv; | 124 | const struct rt2800_ops *rt2800ops = rt2x00dev->priv; |
@@ -120,6 +130,11 @@ void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev, | |||
120 | const u8 command, const u8 token, | 130 | const u8 command, const u8 token, |
121 | const u8 arg0, const u8 arg1); | 131 | const u8 arg0, const u8 arg1); |
122 | 132 | ||
133 | int rt2800_check_firmware(struct rt2x00_dev *rt2x00dev, | ||
134 | const u8 *data, const size_t len); | ||
135 | int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev, | ||
136 | const u8 *data, const size_t len); | ||
137 | |||
123 | void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc); | 138 | void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc); |
124 | void rt2800_process_rxwi(struct queue_entry *entry, struct rxdone_entry_desc *txdesc); | 139 | void rt2800_process_rxwi(struct queue_entry *entry, struct rxdone_entry_desc *txdesc); |
125 | 140 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 520236d0dc78..0fdd58b9dece 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c | |||
@@ -31,7 +31,6 @@ | |||
31 | Supported chipsets: RT2800E & RT2800ED. | 31 | Supported chipsets: RT2800E & RT2800ED. |
32 | */ | 32 | */ |
33 | 33 | ||
34 | #include <linux/crc-ccitt.h> | ||
35 | #include <linux/delay.h> | 34 | #include <linux/delay.h> |
36 | #include <linux/etherdevice.h> | 35 | #include <linux/etherdevice.h> |
37 | #include <linux/init.h> | 36 | #include <linux/init.h> |
@@ -192,82 +191,14 @@ static char *rt2800pci_get_firmware_name(struct rt2x00_dev *rt2x00dev) | |||
192 | return FIRMWARE_RT2860; | 191 | return FIRMWARE_RT2860; |
193 | } | 192 | } |
194 | 193 | ||
195 | static int rt2800pci_check_firmware(struct rt2x00_dev *rt2x00dev, | 194 | static int rt2800pci_write_firmware(struct rt2x00_dev *rt2x00dev, |
196 | const u8 *data, const size_t len) | 195 | const u8 *data, const size_t len) |
197 | { | 196 | { |
198 | u16 fw_crc; | ||
199 | u16 crc; | ||
200 | |||
201 | /* | ||
202 | * Only support 8kb firmware files. | ||
203 | */ | ||
204 | if (len != 8192) | ||
205 | return FW_BAD_LENGTH; | ||
206 | |||
207 | /* | ||
208 | * The last 2 bytes in the firmware array are the crc checksum itself, | ||
209 | * this means that we should never pass those 2 bytes to the crc | ||
210 | * algorithm. | ||
211 | */ | ||
212 | fw_crc = (data[len - 2] << 8 | data[len - 1]); | ||
213 | |||
214 | /* | ||
215 | * Use the crc ccitt algorithm. | ||
216 | * This will return the same value as the legacy driver which | ||
217 | * used bit ordering reversion on the both the firmware bytes | ||
218 | * before input input as well as on the final output. | ||
219 | * Obviously using crc ccitt directly is much more efficient. | ||
220 | */ | ||
221 | crc = crc_ccitt(~0, data, len - 2); | ||
222 | |||
223 | /* | ||
224 | * There is a small difference between the crc-itu-t + bitrev and | ||
225 | * the crc-ccitt crc calculation. In the latter method the 2 bytes | ||
226 | * will be swapped, use swab16 to convert the crc to the correct | ||
227 | * value. | ||
228 | */ | ||
229 | crc = swab16(crc); | ||
230 | |||
231 | return (fw_crc == crc) ? FW_OK : FW_BAD_CRC; | ||
232 | } | ||
233 | |||
234 | static int rt2800pci_load_firmware(struct rt2x00_dev *rt2x00dev, | ||
235 | const u8 *data, const size_t len) | ||
236 | { | ||
237 | unsigned int i; | ||
238 | u32 reg; | 197 | u32 reg; |
239 | 198 | ||
240 | /* | ||
241 | * Wait for stable hardware. | ||
242 | */ | ||
243 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | ||
244 | rt2800_register_read(rt2x00dev, MAC_CSR0, ®); | ||
245 | if (reg && reg != ~0) | ||
246 | break; | ||
247 | msleep(1); | ||
248 | } | ||
249 | |||
250 | if (i == REGISTER_BUSY_COUNT) { | ||
251 | ERROR(rt2x00dev, "Unstable hardware.\n"); | ||
252 | return -EBUSY; | ||
253 | } | ||
254 | |||
255 | rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000002); | ||
256 | rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0x00000000); | 199 | rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0x00000000); |
257 | 200 | ||
258 | /* | 201 | /* |
259 | * Disable DMA, will be reenabled later when enabling | ||
260 | * the radio. | ||
261 | */ | ||
262 | rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); | ||
263 | rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); | ||
264 | rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_DMA_BUSY, 0); | ||
265 | rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); | ||
266 | rt2x00_set_field32(®, WPDMA_GLO_CFG_RX_DMA_BUSY, 0); | ||
267 | rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); | ||
268 | rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); | ||
269 | |||
270 | /* | ||
271 | * enable Host program ram write selection | 202 | * enable Host program ram write selection |
272 | */ | 203 | */ |
273 | reg = 0; | 204 | reg = 0; |
@@ -278,34 +209,11 @@ static int rt2800pci_load_firmware(struct rt2x00_dev *rt2x00dev, | |||
278 | * Write firmware to device. | 209 | * Write firmware to device. |
279 | */ | 210 | */ |
280 | rt2800_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, | 211 | rt2800_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, |
281 | data, len); | 212 | data, len); |
282 | 213 | ||
283 | rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000); | 214 | rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000); |
284 | rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001); | 215 | rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001); |
285 | 216 | ||
286 | /* | ||
287 | * Wait for device to stabilize. | ||
288 | */ | ||
289 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | ||
290 | rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, ®); | ||
291 | if (rt2x00_get_field32(reg, PBF_SYS_CTRL_READY)) | ||
292 | break; | ||
293 | msleep(1); | ||
294 | } | ||
295 | |||
296 | if (i == REGISTER_BUSY_COUNT) { | ||
297 | ERROR(rt2x00dev, "PBF system register not ready.\n"); | ||
298 | return -EBUSY; | ||
299 | } | ||
300 | |||
301 | /* | ||
302 | * Disable interrupts | ||
303 | */ | ||
304 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_IRQ_OFF); | ||
305 | |||
306 | /* | ||
307 | * Initialize BBP R/W access agent | ||
308 | */ | ||
309 | rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0); | 217 | rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0); |
310 | rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); | 218 | rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); |
311 | 219 | ||
@@ -1029,6 +937,7 @@ static const struct rt2800_ops rt2800pci_rt2800_ops = { | |||
1029 | 937 | ||
1030 | .regbusy_read = rt2x00pci_regbusy_read, | 938 | .regbusy_read = rt2x00pci_regbusy_read, |
1031 | 939 | ||
940 | .drv_write_firmware = rt2800pci_write_firmware, | ||
1032 | .drv_init_registers = rt2800pci_init_registers, | 941 | .drv_init_registers = rt2800pci_init_registers, |
1033 | }; | 942 | }; |
1034 | 943 | ||
@@ -1114,8 +1023,8 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { | |||
1114 | .irq_handler_thread = rt2800pci_interrupt_thread, | 1023 | .irq_handler_thread = rt2800pci_interrupt_thread, |
1115 | .probe_hw = rt2800pci_probe_hw, | 1024 | .probe_hw = rt2800pci_probe_hw, |
1116 | .get_firmware_name = rt2800pci_get_firmware_name, | 1025 | .get_firmware_name = rt2800pci_get_firmware_name, |
1117 | .check_firmware = rt2800pci_check_firmware, | 1026 | .check_firmware = rt2800_check_firmware, |
1118 | .load_firmware = rt2800pci_load_firmware, | 1027 | .load_firmware = rt2800_load_firmware, |
1119 | .initialize = rt2x00pci_initialize, | 1028 | .initialize = rt2x00pci_initialize, |
1120 | .uninitialize = rt2x00pci_uninitialize, | 1029 | .uninitialize = rt2x00pci_uninitialize, |
1121 | .get_entry_state = rt2800pci_get_entry_state, | 1030 | .get_entry_state = rt2800pci_get_entry_state, |
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index f8eb6d776d99..7b8d51f58038 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c | |||
@@ -28,7 +28,6 @@ | |||
28 | Supported chipsets: RT2800U. | 28 | Supported chipsets: RT2800U. |
29 | */ | 29 | */ |
30 | 30 | ||
31 | #include <linux/crc-ccitt.h> | ||
32 | #include <linux/delay.h> | 31 | #include <linux/delay.h> |
33 | #include <linux/etherdevice.h> | 32 | #include <linux/etherdevice.h> |
34 | #include <linux/init.h> | 33 | #include <linux/init.h> |
@@ -57,84 +56,10 @@ static char *rt2800usb_get_firmware_name(struct rt2x00_dev *rt2x00dev) | |||
57 | return FIRMWARE_RT2870; | 56 | return FIRMWARE_RT2870; |
58 | } | 57 | } |
59 | 58 | ||
60 | static bool rt2800usb_check_crc(const u8 *data, const size_t len) | 59 | static int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev, |
61 | { | ||
62 | u16 fw_crc; | ||
63 | u16 crc; | ||
64 | |||
65 | /* | ||
66 | * The last 2 bytes in the firmware array are the crc checksum itself, | ||
67 | * this means that we should never pass those 2 bytes to the crc | ||
68 | * algorithm. | ||
69 | */ | ||
70 | fw_crc = (data[len - 2] << 8 | data[len - 1]); | ||
71 | |||
72 | /* | ||
73 | * Use the crc ccitt algorithm. | ||
74 | * This will return the same value as the legacy driver which | ||
75 | * used bit ordering reversion on the both the firmware bytes | ||
76 | * before input input as well as on the final output. | ||
77 | * Obviously using crc ccitt directly is much more efficient. | ||
78 | */ | ||
79 | crc = crc_ccitt(~0, data, len - 2); | ||
80 | |||
81 | /* | ||
82 | * There is a small difference between the crc-itu-t + bitrev and | ||
83 | * the crc-ccitt crc calculation. In the latter method the 2 bytes | ||
84 | * will be swapped, use swab16 to convert the crc to the correct | ||
85 | * value. | ||
86 | */ | ||
87 | crc = swab16(crc); | ||
88 | |||
89 | return fw_crc == crc; | ||
90 | } | ||
91 | |||
92 | static int rt2800usb_check_firmware(struct rt2x00_dev *rt2x00dev, | ||
93 | const u8 *data, const size_t len) | 60 | const u8 *data, const size_t len) |
94 | { | 61 | { |
95 | size_t offset = 0; | ||
96 | |||
97 | /* | ||
98 | * Firmware files: | ||
99 | * There are 2 variations of the rt2870 firmware. | ||
100 | * a) size: 4kb | ||
101 | * b) size: 8kb | ||
102 | * Note that (b) contains 2 separate firmware blobs of 4k | ||
103 | * within the file. The first blob is the same firmware as (a), | ||
104 | * but the second blob is for the additional chipsets. | ||
105 | */ | ||
106 | if (len != 4096 && len != 8192) | ||
107 | return FW_BAD_LENGTH; | ||
108 | |||
109 | /* | ||
110 | * Check if we need the upper 4kb firmware data or not. | ||
111 | */ | ||
112 | if ((len == 4096) && | ||
113 | !rt2x00_rt(rt2x00dev, RT2860) && | ||
114 | !rt2x00_rt(rt2x00dev, RT2872) && | ||
115 | !rt2x00_rt(rt2x00dev, RT3070)) | ||
116 | return FW_BAD_VERSION; | ||
117 | |||
118 | /* | ||
119 | * 8kb firmware files must be checked as if it were | ||
120 | * 2 separate firmware files. | ||
121 | */ | ||
122 | while (offset < len) { | ||
123 | if (!rt2800usb_check_crc(data + offset, 4096)) | ||
124 | return FW_BAD_CRC; | ||
125 | |||
126 | offset += 4096; | ||
127 | } | ||
128 | |||
129 | return FW_OK; | ||
130 | } | ||
131 | |||
132 | static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev, | ||
133 | const u8 *data, const size_t len) | ||
134 | { | ||
135 | unsigned int i; | ||
136 | int status; | 62 | int status; |
137 | u32 reg; | ||
138 | u32 offset; | 63 | u32 offset; |
139 | u32 length; | 64 | u32 length; |
140 | 65 | ||
@@ -152,21 +77,6 @@ static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev, | |||
152 | } | 77 | } |
153 | 78 | ||
154 | /* | 79 | /* |
155 | * Wait for stable hardware. | ||
156 | */ | ||
157 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | ||
158 | rt2800_register_read(rt2x00dev, MAC_CSR0, ®); | ||
159 | if (reg && reg != ~0) | ||
160 | break; | ||
161 | msleep(1); | ||
162 | } | ||
163 | |||
164 | if (i == REGISTER_BUSY_COUNT) { | ||
165 | ERROR(rt2x00dev, "Unstable hardware.\n"); | ||
166 | return -EBUSY; | ||
167 | } | ||
168 | |||
169 | /* | ||
170 | * Write firmware to device. | 80 | * Write firmware to device. |
171 | */ | 81 | */ |
172 | rt2800_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, | 82 | rt2800_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, |
@@ -203,28 +113,6 @@ static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev, | |||
203 | udelay(10); | 113 | udelay(10); |
204 | } | 114 | } |
205 | 115 | ||
206 | /* | ||
207 | * Wait for device to stabilize. | ||
208 | */ | ||
209 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | ||
210 | rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, ®); | ||
211 | if (rt2x00_get_field32(reg, PBF_SYS_CTRL_READY)) | ||
212 | break; | ||
213 | msleep(1); | ||
214 | } | ||
215 | |||
216 | if (i == REGISTER_BUSY_COUNT) { | ||
217 | ERROR(rt2x00dev, "PBF system register not ready.\n"); | ||
218 | return -EBUSY; | ||
219 | } | ||
220 | |||
221 | /* | ||
222 | * Initialize firmware. | ||
223 | */ | ||
224 | rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0); | ||
225 | rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); | ||
226 | msleep(1); | ||
227 | |||
228 | return 0; | 116 | return 0; |
229 | } | 117 | } |
230 | 118 | ||
@@ -593,6 +481,7 @@ static const struct rt2800_ops rt2800usb_rt2800_ops = { | |||
593 | 481 | ||
594 | .regbusy_read = rt2x00usb_regbusy_read, | 482 | .regbusy_read = rt2x00usb_regbusy_read, |
595 | 483 | ||
484 | .drv_write_firmware = rt2800usb_write_firmware, | ||
596 | .drv_init_registers = rt2800usb_init_registers, | 485 | .drv_init_registers = rt2800usb_init_registers, |
597 | }; | 486 | }; |
598 | 487 | ||
@@ -670,8 +559,8 @@ static const struct ieee80211_ops rt2800usb_mac80211_ops = { | |||
670 | static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { | 559 | static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { |
671 | .probe_hw = rt2800usb_probe_hw, | 560 | .probe_hw = rt2800usb_probe_hw, |
672 | .get_firmware_name = rt2800usb_get_firmware_name, | 561 | .get_firmware_name = rt2800usb_get_firmware_name, |
673 | .check_firmware = rt2800usb_check_firmware, | 562 | .check_firmware = rt2800_check_firmware, |
674 | .load_firmware = rt2800usb_load_firmware, | 563 | .load_firmware = rt2800_load_firmware, |
675 | .initialize = rt2x00usb_initialize, | 564 | .initialize = rt2x00usb_initialize, |
676 | .uninitialize = rt2x00usb_uninitialize, | 565 | .uninitialize = rt2x00usb_uninitialize, |
677 | .clear_entry = rt2x00usb_clear_entry, | 566 | .clear_entry = rt2x00usb_clear_entry, |