Commit 915a824e authored by Dan Williams's avatar Dan Williams Committed by John W. Linville

libertas: [spi] use common firmware request helper and new firmware locations

linux-firmware puts libertas firmware in /libertas.  Fix the driver to
look there first, but fall back to the old firmware names if the new
ones don't exist.  Add preference for newer firmware versions too.
Signed-off-by: default avatarDan Williams <dcbw@redhat.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 3d32a58b
...@@ -39,9 +39,6 @@ struct if_spi_card { ...@@ -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) ...@@ -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[] = { #define MODEL_8385 0x04
{ .chip_id = 0x04, .name = 8385 }, #define MODEL_8686 0x0b
{ .chip_id = 0x0b, .name = 8686 }, #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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, /* Check if we support this card */
card->helper_fw_name, card->main_fw_name); for (i = 0; i < ARRAY_SIZE(fw_table); i++) {
if (err) 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) ...@@ -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 @@ static int __devinit if_spi_probe(struct spi_device *spi) ...@@ -1046,6 +1035,11 @@ static int __devinit if_spi_probe(struct spi_device *spi)
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;
} }
......
...@@ -25,11 +25,6 @@ ...@@ -25,11 +25,6 @@
#define IF_SPI_FW_NAME_MAX 30 #define IF_SPI_FW_NAME_MAX 30
struct chip_ident {
u16 chip_id;
u16 name;
};
#define MAX_MAIN_FW_LOAD_CRC_ERR 10 #define MAX_MAIN_FW_LOAD_CRC_ERR 10
/* Chunk size when loading the helper firmware */ /* Chunk size when loading the helper firmware */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment