|
@@ -39,9 +39,6 @@ struct if_spi_card {
|
|
struct lbs_private *priv;
|
|
struct lbs_private *priv;
|
|
struct libertas_spi_platform_data *pdata;
|
|
struct libertas_spi_platform_data *pdata;
|
|
|
|
|
|
- char helper_fw_name[IF_SPI_FW_NAME_MAX];
|
|
|
|
- char main_fw_name[IF_SPI_FW_NAME_MAX];
|
|
|
|
-
|
|
|
|
/* The card ID and card revision, as reported by the hardware. */
|
|
/* The card ID and card revision, as reported by the hardware. */
|
|
u16 card_id;
|
|
u16 card_id;
|
|
u8 card_rev;
|
|
u8 card_rev;
|
|
@@ -70,10 +67,28 @@ static void free_if_spi_card(struct if_spi_card *card)
|
|
kfree(card);
|
|
kfree(card);
|
|
}
|
|
}
|
|
|
|
|
|
-static struct chip_ident chip_id_to_device_name[] = {
|
|
|
|
- { .chip_id = 0x04, .name = 8385 },
|
|
|
|
- { .chip_id = 0x0b, .name = 8686 },
|
|
|
|
|
|
+#define MODEL_8385 0x04
|
|
|
|
+#define MODEL_8686 0x0b
|
|
|
|
+#define MODEL_8688 0x10
|
|
|
|
+
|
|
|
|
+static const struct lbs_fw_table fw_table[] = {
|
|
|
|
+ { MODEL_8385, "libertas/gspi8385_helper.bin", "libertas/gspi8385.bin" },
|
|
|
|
+ { MODEL_8385, "libertas/gspi8385_hlp.bin", "libertas/gspi8385.bin" },
|
|
|
|
+ { MODEL_8686, "libertas/gspi8686_v9_helper.bin", "libertas/gspi8686_v9.bin" },
|
|
|
|
+ { MODEL_8686, "libertas/gspi8686_hlp.bin", "libertas/gspi8686.bin" },
|
|
|
|
+ { MODEL_8688, "libertas/gspi8688_helper.bin", "libertas/gspi8688.bin" },
|
|
|
|
+ { 0, NULL, NULL }
|
|
};
|
|
};
|
|
|
|
+MODULE_FIRMWARE("libertas/gspi8385_helper.bin");
|
|
|
|
+MODULE_FIRMWARE("libertas/gspi8385_hlp.bin");
|
|
|
|
+MODULE_FIRMWARE("libertas/gspi8385.bin");
|
|
|
|
+MODULE_FIRMWARE("libertas/gspi8686_v9_helper.bin");
|
|
|
|
+MODULE_FIRMWARE("libertas/gspi8686_v9.bin");
|
|
|
|
+MODULE_FIRMWARE("libertas/gspi8686_hlp.bin");
|
|
|
|
+MODULE_FIRMWARE("libertas/gspi8686.bin");
|
|
|
|
+MODULE_FIRMWARE("libertas/gspi8688_helper.bin");
|
|
|
|
+MODULE_FIRMWARE("libertas/gspi8688.bin");
|
|
|
|
+
|
|
|
|
|
|
/*
|
|
/*
|
|
* SPI Interface Unit Routines
|
|
* SPI Interface Unit Routines
|
|
@@ -399,26 +414,20 @@ static int spu_init(struct if_spi_card *card, int use_dummy_writes)
|
|
* Firmware Loading
|
|
* Firmware Loading
|
|
*/
|
|
*/
|
|
|
|
|
|
-static int if_spi_prog_helper_firmware(struct if_spi_card *card)
|
|
|
|
|
|
+static int if_spi_prog_helper_firmware(struct if_spi_card *card,
|
|
|
|
+ const struct firmware *firmware)
|
|
{
|
|
{
|
|
int err = 0;
|
|
int err = 0;
|
|
- const struct firmware *firmware = NULL;
|
|
|
|
int bytes_remaining;
|
|
int bytes_remaining;
|
|
const u8 *fw;
|
|
const u8 *fw;
|
|
u8 temp[HELPER_FW_LOAD_CHUNK_SZ];
|
|
u8 temp[HELPER_FW_LOAD_CHUNK_SZ];
|
|
- struct spi_device *spi = card->spi;
|
|
|
|
|
|
|
|
lbs_deb_enter(LBS_DEB_SPI);
|
|
lbs_deb_enter(LBS_DEB_SPI);
|
|
|
|
|
|
err = spu_set_interrupt_mode(card, 1, 0);
|
|
err = spu_set_interrupt_mode(card, 1, 0);
|
|
if (err)
|
|
if (err)
|
|
goto out;
|
|
goto out;
|
|
- /* Get helper firmware image */
|
|
|
|
- err = request_firmware(&firmware, card->helper_fw_name, &spi->dev);
|
|
|
|
- if (err) {
|
|
|
|
- lbs_pr_err("request_firmware failed with err = %d\n", err);
|
|
|
|
- goto out;
|
|
|
|
- }
|
|
|
|
|
|
+
|
|
bytes_remaining = firmware->size;
|
|
bytes_remaining = firmware->size;
|
|
fw = firmware->data;
|
|
fw = firmware->data;
|
|
|
|
|
|
@@ -429,13 +438,13 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card)
|
|
err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG,
|
|
err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG,
|
|
HELPER_FW_LOAD_CHUNK_SZ);
|
|
HELPER_FW_LOAD_CHUNK_SZ);
|
|
if (err)
|
|
if (err)
|
|
- goto release_firmware;
|
|
|
|
|
|
+ goto out;
|
|
|
|
|
|
err = spu_wait_for_u16(card, IF_SPI_HOST_INT_STATUS_REG,
|
|
err = spu_wait_for_u16(card, IF_SPI_HOST_INT_STATUS_REG,
|
|
IF_SPI_HIST_CMD_DOWNLOAD_RDY,
|
|
IF_SPI_HIST_CMD_DOWNLOAD_RDY,
|
|
IF_SPI_HIST_CMD_DOWNLOAD_RDY);
|
|
IF_SPI_HIST_CMD_DOWNLOAD_RDY);
|
|
if (err)
|
|
if (err)
|
|
- goto release_firmware;
|
|
|
|
|
|
+ goto out;
|
|
|
|
|
|
/* Feed the data into the command read/write port reg
|
|
/* Feed the data into the command read/write port reg
|
|
* in chunks of 64 bytes */
|
|
* in chunks of 64 bytes */
|
|
@@ -446,16 +455,16 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card)
|
|
err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG,
|
|
err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG,
|
|
temp, HELPER_FW_LOAD_CHUNK_SZ);
|
|
temp, HELPER_FW_LOAD_CHUNK_SZ);
|
|
if (err)
|
|
if (err)
|
|
- goto release_firmware;
|
|
|
|
|
|
+ goto out;
|
|
|
|
|
|
/* Interrupt the boot code */
|
|
/* Interrupt the boot code */
|
|
err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0);
|
|
err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0);
|
|
if (err)
|
|
if (err)
|
|
- goto release_firmware;
|
|
|
|
|
|
+ goto out;
|
|
err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG,
|
|
err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG,
|
|
IF_SPI_CIC_CMD_DOWNLOAD_OVER);
|
|
IF_SPI_CIC_CMD_DOWNLOAD_OVER);
|
|
if (err)
|
|
if (err)
|
|
- goto release_firmware;
|
|
|
|
|
|
+ goto out;
|
|
bytes_remaining -= HELPER_FW_LOAD_CHUNK_SZ;
|
|
bytes_remaining -= HELPER_FW_LOAD_CHUNK_SZ;
|
|
fw += HELPER_FW_LOAD_CHUNK_SZ;
|
|
fw += HELPER_FW_LOAD_CHUNK_SZ;
|
|
}
|
|
}
|
|
@@ -465,18 +474,16 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card)
|
|
* bootloader. This completes the helper download. */
|
|
* bootloader. This completes the helper download. */
|
|
err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG, FIRMWARE_DNLD_OK);
|
|
err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG, FIRMWARE_DNLD_OK);
|
|
if (err)
|
|
if (err)
|
|
- goto release_firmware;
|
|
|
|
|
|
+ goto out;
|
|
err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0);
|
|
err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0);
|
|
if (err)
|
|
if (err)
|
|
- goto release_firmware;
|
|
|
|
|
|
+ goto out;
|
|
err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG,
|
|
err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG,
|
|
IF_SPI_CIC_CMD_DOWNLOAD_OVER);
|
|
IF_SPI_CIC_CMD_DOWNLOAD_OVER);
|
|
- goto release_firmware;
|
|
|
|
|
|
+ goto out;
|
|
|
|
|
|
lbs_deb_spi("waiting for helper to boot...\n");
|
|
lbs_deb_spi("waiting for helper to boot...\n");
|
|
|
|
|
|
-release_firmware:
|
|
|
|
- release_firmware(firmware);
|
|
|
|
out:
|
|
out:
|
|
if (err)
|
|
if (err)
|
|
lbs_pr_err("failed to load helper firmware (err=%d)\n", err);
|
|
lbs_pr_err("failed to load helper firmware (err=%d)\n", err);
|
|
@@ -523,13 +530,12 @@ static int if_spi_prog_main_firmware_check_len(struct if_spi_card *card,
|
|
return len;
|
|
return len;
|
|
}
|
|
}
|
|
|
|
|
|
-static int if_spi_prog_main_firmware(struct if_spi_card *card)
|
|
|
|
|
|
+static int if_spi_prog_main_firmware(struct if_spi_card *card,
|
|
|
|
+ const struct firmware *firmware)
|
|
{
|
|
{
|
|
int len, prev_len;
|
|
int len, prev_len;
|
|
int bytes, crc_err = 0, err = 0;
|
|
int bytes, crc_err = 0, err = 0;
|
|
- const struct firmware *firmware = NULL;
|
|
|
|
const u8 *fw;
|
|
const u8 *fw;
|
|
- struct spi_device *spi = card->spi;
|
|
|
|
u16 num_crc_errs;
|
|
u16 num_crc_errs;
|
|
|
|
|
|
lbs_deb_enter(LBS_DEB_SPI);
|
|
lbs_deb_enter(LBS_DEB_SPI);
|
|
@@ -538,19 +544,11 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card)
|
|
if (err)
|
|
if (err)
|
|
goto out;
|
|
goto out;
|
|
|
|
|
|
- /* Get firmware image */
|
|
|
|
- err = request_firmware(&firmware, card->main_fw_name, &spi->dev);
|
|
|
|
- if (err) {
|
|
|
|
- lbs_pr_err("%s: can't get firmware '%s' from kernel. "
|
|
|
|
- "err = %d\n", __func__, card->main_fw_name, err);
|
|
|
|
- goto out;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
err = spu_wait_for_u16(card, IF_SPI_SCRATCH_1_REG, 0, 0);
|
|
err = spu_wait_for_u16(card, IF_SPI_SCRATCH_1_REG, 0, 0);
|
|
if (err) {
|
|
if (err) {
|
|
lbs_pr_err("%s: timed out waiting for initial "
|
|
lbs_pr_err("%s: timed out waiting for initial "
|
|
"scratch reg = 0\n", __func__);
|
|
"scratch reg = 0\n", __func__);
|
|
- goto release_firmware;
|
|
|
|
|
|
+ goto out;
|
|
}
|
|
}
|
|
|
|
|
|
num_crc_errs = 0;
|
|
num_crc_errs = 0;
|
|
@@ -560,7 +558,7 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card)
|
|
while ((len = if_spi_prog_main_firmware_check_len(card, &crc_err))) {
|
|
while ((len = if_spi_prog_main_firmware_check_len(card, &crc_err))) {
|
|
if (len < 0) {
|
|
if (len < 0) {
|
|
err = len;
|
|
err = len;
|
|
- goto release_firmware;
|
|
|
|
|
|
+ goto out;
|
|
}
|
|
}
|
|
if (bytes < 0) {
|
|
if (bytes < 0) {
|
|
/* If there are no more bytes left, we would normally
|
|
/* If there are no more bytes left, we would normally
|
|
@@ -575,7 +573,7 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card)
|
|
lbs_pr_err("Too many CRC errors encountered "
|
|
lbs_pr_err("Too many CRC errors encountered "
|
|
"in firmware load.\n");
|
|
"in firmware load.\n");
|
|
err = -EIO;
|
|
err = -EIO;
|
|
- goto release_firmware;
|
|
|
|
|
|
+ goto out;
|
|
}
|
|
}
|
|
} else {
|
|
} else {
|
|
/* Previous transfer succeeded. Advance counters. */
|
|
/* Previous transfer succeeded. Advance counters. */
|
|
@@ -590,15 +588,15 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card)
|
|
|
|
|
|
err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0);
|
|
err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0);
|
|
if (err)
|
|
if (err)
|
|
- goto release_firmware;
|
|
|
|
|
|
+ goto out;
|
|
err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG,
|
|
err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG,
|
|
card->cmd_buffer, len);
|
|
card->cmd_buffer, len);
|
|
if (err)
|
|
if (err)
|
|
- goto release_firmware;
|
|
|
|
|
|
+ goto out;
|
|
err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG ,
|
|
err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG ,
|
|
IF_SPI_CIC_CMD_DOWNLOAD_OVER);
|
|
IF_SPI_CIC_CMD_DOWNLOAD_OVER);
|
|
if (err)
|
|
if (err)
|
|
- goto release_firmware;
|
|
|
|
|
|
+ goto out;
|
|
prev_len = len;
|
|
prev_len = len;
|
|
}
|
|
}
|
|
if (bytes > prev_len) {
|
|
if (bytes > prev_len) {
|
|
@@ -611,12 +609,9 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card)
|
|
SUCCESSFUL_FW_DOWNLOAD_MAGIC);
|
|
SUCCESSFUL_FW_DOWNLOAD_MAGIC);
|
|
if (err) {
|
|
if (err) {
|
|
lbs_pr_err("failed to confirm the firmware download\n");
|
|
lbs_pr_err("failed to confirm the firmware download\n");
|
|
- goto release_firmware;
|
|
|
|
|
|
+ goto out;
|
|
}
|
|
}
|
|
|
|
|
|
-release_firmware:
|
|
|
|
- release_firmware(firmware);
|
|
|
|
-
|
|
|
|
out:
|
|
out:
|
|
if (err)
|
|
if (err)
|
|
lbs_pr_err("failed to load firmware (err=%d)\n", err);
|
|
lbs_pr_err("failed to load firmware (err=%d)\n", err);
|
|
@@ -888,37 +883,16 @@ static irqreturn_t if_spi_host_interrupt(int irq, void *dev_id)
|
|
* SPI callbacks
|
|
* SPI callbacks
|
|
*/
|
|
*/
|
|
|
|
|
|
-static int if_spi_calculate_fw_names(u16 card_id,
|
|
|
|
- char *helper_fw, char *main_fw)
|
|
|
|
-{
|
|
|
|
- int i;
|
|
|
|
- for (i = 0; i < ARRAY_SIZE(chip_id_to_device_name); ++i) {
|
|
|
|
- if (card_id == chip_id_to_device_name[i].chip_id)
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- if (i == ARRAY_SIZE(chip_id_to_device_name)) {
|
|
|
|
- lbs_pr_err("Unsupported chip_id: 0x%02x\n", card_id);
|
|
|
|
- return -EAFNOSUPPORT;
|
|
|
|
- }
|
|
|
|
- snprintf(helper_fw, IF_SPI_FW_NAME_MAX, "libertas/gspi%d_hlp.bin",
|
|
|
|
- chip_id_to_device_name[i].name);
|
|
|
|
- snprintf(main_fw, IF_SPI_FW_NAME_MAX, "libertas/gspi%d.bin",
|
|
|
|
- chip_id_to_device_name[i].name);
|
|
|
|
- return 0;
|
|
|
|
-}
|
|
|
|
-MODULE_FIRMWARE("libertas/gspi8385_hlp.bin");
|
|
|
|
-MODULE_FIRMWARE("libertas/gspi8385.bin");
|
|
|
|
-MODULE_FIRMWARE("libertas/gspi8686_hlp.bin");
|
|
|
|
-MODULE_FIRMWARE("libertas/gspi8686.bin");
|
|
|
|
-
|
|
|
|
static int __devinit if_spi_probe(struct spi_device *spi)
|
|
static int __devinit if_spi_probe(struct spi_device *spi)
|
|
{
|
|
{
|
|
struct if_spi_card *card;
|
|
struct if_spi_card *card;
|
|
struct lbs_private *priv = NULL;
|
|
struct lbs_private *priv = NULL;
|
|
struct libertas_spi_platform_data *pdata = spi->dev.platform_data;
|
|
struct libertas_spi_platform_data *pdata = spi->dev.platform_data;
|
|
- int err = 0;
|
|
|
|
|
|
+ int err = 0, i;
|
|
u32 scratch;
|
|
u32 scratch;
|
|
struct sched_param param = { .sched_priority = 1 };
|
|
struct sched_param param = { .sched_priority = 1 };
|
|
|
|
+ const struct firmware *helper = NULL;
|
|
|
|
+ const struct firmware *mainfw = NULL;
|
|
|
|
|
|
lbs_deb_enter(LBS_DEB_SPI);
|
|
lbs_deb_enter(LBS_DEB_SPI);
|
|
|
|
|
|
@@ -963,10 +937,25 @@ static int __devinit if_spi_probe(struct spi_device *spi)
|
|
lbs_deb_spi("Firmware is already loaded for "
|
|
lbs_deb_spi("Firmware is already loaded for "
|
|
"Marvell WLAN 802.11 adapter\n");
|
|
"Marvell WLAN 802.11 adapter\n");
|
|
else {
|
|
else {
|
|
- err = if_spi_calculate_fw_names(card->card_id,
|
|
|
|
- card->helper_fw_name, card->main_fw_name);
|
|
|
|
- if (err)
|
|
|
|
|
|
+ /* Check if we support this card */
|
|
|
|
+ for (i = 0; i < ARRAY_SIZE(fw_table); i++) {
|
|
|
|
+ if (card->card_id == fw_table[i].model)
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ if (i == ARRAY_SIZE(fw_table)) {
|
|
|
|
+ lbs_pr_err("Unsupported chip_id: 0x%02x\n",
|
|
|
|
+ card->card_id);
|
|
|
|
+ err = -ENODEV;
|
|
goto free_card;
|
|
goto free_card;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ err = lbs_get_firmware(&card->spi->dev, NULL, NULL,
|
|
|
|
+ card->card_id, &fw_table[0], &helper,
|
|
|
|
+ &mainfw);
|
|
|
|
+ if (err) {
|
|
|
|
+ lbs_pr_err("failed to find firmware (%d)\n", err);
|
|
|
|
+ goto free_card;
|
|
|
|
+ }
|
|
|
|
|
|
lbs_deb_spi("Initializing FW for Marvell WLAN 802.11 adapter "
|
|
lbs_deb_spi("Initializing FW for Marvell WLAN 802.11 adapter "
|
|
"(chip_id = 0x%04x, chip_rev = 0x%02x) "
|
|
"(chip_id = 0x%04x, chip_rev = 0x%02x) "
|
|
@@ -975,10 +964,10 @@ static int __devinit if_spi_probe(struct spi_device *spi)
|
|
card->card_id, card->card_rev,
|
|
card->card_id, card->card_rev,
|
|
spi->master->bus_num, spi->chip_select,
|
|
spi->master->bus_num, spi->chip_select,
|
|
spi->max_speed_hz);
|
|
spi->max_speed_hz);
|
|
- err = if_spi_prog_helper_firmware(card);
|
|
|
|
|
|
+ err = if_spi_prog_helper_firmware(card, helper);
|
|
if (err)
|
|
if (err)
|
|
goto free_card;
|
|
goto free_card;
|
|
- err = if_spi_prog_main_firmware(card);
|
|
|
|
|
|
+ err = if_spi_prog_main_firmware(card, mainfw);
|
|
if (err)
|
|
if (err)
|
|
goto free_card;
|
|
goto free_card;
|
|
lbs_deb_spi("loaded FW for Marvell WLAN 802.11 adapter\n");
|
|
lbs_deb_spi("loaded FW for Marvell WLAN 802.11 adapter\n");
|
|
@@ -1046,6 +1035,11 @@ remove_card:
|
|
free_card:
|
|
free_card:
|
|
free_if_spi_card(card);
|
|
free_if_spi_card(card);
|
|
out:
|
|
out:
|
|
|
|
+ if (helper)
|
|
|
|
+ release_firmware(helper);
|
|
|
|
+ if (mainfw)
|
|
|
|
+ release_firmware(mainfw);
|
|
|
|
+
|
|
lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err);
|
|
lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err);
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|