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>
This commit is contained in:
committed by
John W. Linville
parent
ab8966ddc2
commit
f31c9a8c13
@@ -28,7 +28,6 @@
|
||||
Supported chipsets: RT2800U.
|
||||
*/
|
||||
|
||||
#include <linux/crc-ccitt.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/init.h>
|
||||
@@ -57,84 +56,10 @@ static char *rt2800usb_get_firmware_name(struct rt2x00_dev *rt2x00dev)
|
||||
return FIRMWARE_RT2870;
|
||||
}
|
||||
|
||||
static bool rt2800usb_check_crc(const u8 *data, const size_t len)
|
||||
{
|
||||
u16 fw_crc;
|
||||
u16 crc;
|
||||
|
||||
/*
|
||||
* The last 2 bytes in the firmware array are the crc checksum itself,
|
||||
* this means that we should never pass those 2 bytes to the crc
|
||||
* algorithm.
|
||||
*/
|
||||
fw_crc = (data[len - 2] << 8 | data[len - 1]);
|
||||
|
||||
/*
|
||||
* Use the crc ccitt algorithm.
|
||||
* This will return the same value as the legacy driver which
|
||||
* used bit ordering reversion on the both the firmware bytes
|
||||
* before input input as well as on the final output.
|
||||
* Obviously using crc ccitt directly is much more efficient.
|
||||
*/
|
||||
crc = crc_ccitt(~0, data, len - 2);
|
||||
|
||||
/*
|
||||
* There is a small difference between the crc-itu-t + bitrev and
|
||||
* the crc-ccitt crc calculation. In the latter method the 2 bytes
|
||||
* will be swapped, use swab16 to convert the crc to the correct
|
||||
* value.
|
||||
*/
|
||||
crc = swab16(crc);
|
||||
|
||||
return fw_crc == crc;
|
||||
}
|
||||
|
||||
static int rt2800usb_check_firmware(struct rt2x00_dev *rt2x00dev,
|
||||
static int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev,
|
||||
const u8 *data, const size_t len)
|
||||
{
|
||||
size_t offset = 0;
|
||||
|
||||
/*
|
||||
* Firmware files:
|
||||
* There are 2 variations of the rt2870 firmware.
|
||||
* a) size: 4kb
|
||||
* b) size: 8kb
|
||||
* Note that (b) contains 2 separate firmware blobs of 4k
|
||||
* within the file. The first blob is the same firmware as (a),
|
||||
* but the second blob is for the additional chipsets.
|
||||
*/
|
||||
if (len != 4096 && len != 8192)
|
||||
return FW_BAD_LENGTH;
|
||||
|
||||
/*
|
||||
* Check if we need the upper 4kb firmware data or not.
|
||||
*/
|
||||
if ((len == 4096) &&
|
||||
!rt2x00_rt(rt2x00dev, RT2860) &&
|
||||
!rt2x00_rt(rt2x00dev, RT2872) &&
|
||||
!rt2x00_rt(rt2x00dev, RT3070))
|
||||
return FW_BAD_VERSION;
|
||||
|
||||
/*
|
||||
* 8kb firmware files must be checked as if it were
|
||||
* 2 separate firmware files.
|
||||
*/
|
||||
while (offset < len) {
|
||||
if (!rt2800usb_check_crc(data + offset, 4096))
|
||||
return FW_BAD_CRC;
|
||||
|
||||
offset += 4096;
|
||||
}
|
||||
|
||||
return FW_OK;
|
||||
}
|
||||
|
||||
static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev,
|
||||
const u8 *data, const size_t len)
|
||||
{
|
||||
unsigned int i;
|
||||
int status;
|
||||
u32 reg;
|
||||
u32 offset;
|
||||
u32 length;
|
||||
|
||||
@@ -151,21 +76,6 @@ static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev,
|
||||
length = 4096;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait for stable hardware.
|
||||
*/
|
||||
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
|
||||
rt2800_register_read(rt2x00dev, MAC_CSR0, ®);
|
||||
if (reg && reg != ~0)
|
||||
break;
|
||||
msleep(1);
|
||||
}
|
||||
|
||||
if (i == REGISTER_BUSY_COUNT) {
|
||||
ERROR(rt2x00dev, "Unstable hardware.\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write firmware to device.
|
||||
*/
|
||||
@@ -203,28 +113,6 @@ static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev,
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait for device to stabilize.
|
||||
*/
|
||||
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
|
||||
rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, ®);
|
||||
if (rt2x00_get_field32(reg, PBF_SYS_CTRL_READY))
|
||||
break;
|
||||
msleep(1);
|
||||
}
|
||||
|
||||
if (i == REGISTER_BUSY_COUNT) {
|
||||
ERROR(rt2x00dev, "PBF system register not ready.\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize firmware.
|
||||
*/
|
||||
rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
|
||||
rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
|
||||
msleep(1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -593,6 +481,7 @@ static const struct rt2800_ops rt2800usb_rt2800_ops = {
|
||||
|
||||
.regbusy_read = rt2x00usb_regbusy_read,
|
||||
|
||||
.drv_write_firmware = rt2800usb_write_firmware,
|
||||
.drv_init_registers = rt2800usb_init_registers,
|
||||
};
|
||||
|
||||
@@ -670,8 +559,8 @@ static const struct ieee80211_ops rt2800usb_mac80211_ops = {
|
||||
static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
|
||||
.probe_hw = rt2800usb_probe_hw,
|
||||
.get_firmware_name = rt2800usb_get_firmware_name,
|
||||
.check_firmware = rt2800usb_check_firmware,
|
||||
.load_firmware = rt2800usb_load_firmware,
|
||||
.check_firmware = rt2800_check_firmware,
|
||||
.load_firmware = rt2800_load_firmware,
|
||||
.initialize = rt2x00usb_initialize,
|
||||
.uninitialize = rt2x00usb_uninitialize,
|
||||
.clear_entry = rt2x00usb_clear_entry,
|
||||
|
Reference in New Issue
Block a user