diff options
author | Dan Williams <dcbw@redhat.com> | 2010-08-07 22:16:30 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-08-16 15:26:43 -0400 |
commit | 915a824e30c503157c38115eb6a85f60bb653738 (patch) | |
tree | da7a9072ae156c0c969ab6a7c9587f42cd187139 /drivers/net | |
parent | 3d32a58b87cd251b50842f93b87d5458061c0cfc (diff) |
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: Dan Williams <dcbw@redhat.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/libertas/if_spi.c | 144 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/if_spi.h | 5 |
2 files changed, 69 insertions, 80 deletions
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c index 3965c6cf504a..79bcb4e5d2ca 100644 --- a/drivers/net/wireless/libertas/if_spi.c +++ b/drivers/net/wireless/libertas/if_spi.c | |||
@@ -39,9 +39,6 @@ struct if_spi_card { | |||
39 | struct lbs_private *priv; | 39 | struct lbs_private *priv; |
40 | struct libertas_spi_platform_data *pdata; | 40 | struct libertas_spi_platform_data *pdata; |
41 | 41 | ||
42 | char helper_fw_name[IF_SPI_FW_NAME_MAX]; | ||
43 | char main_fw_name[IF_SPI_FW_NAME_MAX]; | ||
44 | |||
45 | /* The card ID and card revision, as reported by the hardware. */ | 42 | /* The card ID and card revision, as reported by the hardware. */ |
46 | u16 card_id; | 43 | u16 card_id; |
47 | u8 card_rev; | 44 | u8 card_rev; |
@@ -70,10 +67,28 @@ static void free_if_spi_card(struct if_spi_card *card) | |||
70 | kfree(card); | 67 | kfree(card); |
71 | } | 68 | } |
72 | 69 | ||
73 | static struct chip_ident chip_id_to_device_name[] = { | 70 | #define MODEL_8385 0x04 |
74 | { .chip_id = 0x04, .name = 8385 }, | 71 | #define MODEL_8686 0x0b |
75 | { .chip_id = 0x0b, .name = 8686 }, | 72 | #define MODEL_8688 0x10 |
73 | |||
74 | static const struct lbs_fw_table fw_table[] = { | ||
75 | { MODEL_8385, "libertas/gspi8385_helper.bin", "libertas/gspi8385.bin" }, | ||
76 | { MODEL_8385, "libertas/gspi8385_hlp.bin", "libertas/gspi8385.bin" }, | ||
77 | { MODEL_8686, "libertas/gspi8686_v9_helper.bin", "libertas/gspi8686_v9.bin" }, | ||
78 | { MODEL_8686, "libertas/gspi8686_hlp.bin", "libertas/gspi8686.bin" }, | ||
79 | { MODEL_8688, "libertas/gspi8688_helper.bin", "libertas/gspi8688.bin" }, | ||
80 | { 0, NULL, NULL } | ||
76 | }; | 81 | }; |
82 | MODULE_FIRMWARE("libertas/gspi8385_helper.bin"); | ||
83 | MODULE_FIRMWARE("libertas/gspi8385_hlp.bin"); | ||
84 | MODULE_FIRMWARE("libertas/gspi8385.bin"); | ||
85 | MODULE_FIRMWARE("libertas/gspi8686_v9_helper.bin"); | ||
86 | MODULE_FIRMWARE("libertas/gspi8686_v9.bin"); | ||
87 | MODULE_FIRMWARE("libertas/gspi8686_hlp.bin"); | ||
88 | MODULE_FIRMWARE("libertas/gspi8686.bin"); | ||
89 | MODULE_FIRMWARE("libertas/gspi8688_helper.bin"); | ||
90 | MODULE_FIRMWARE("libertas/gspi8688.bin"); | ||
91 | |||
77 | 92 | ||
78 | /* | 93 | /* |
79 | * SPI Interface Unit Routines | 94 | * SPI Interface Unit Routines |
@@ -399,26 +414,20 @@ static int spu_init(struct if_spi_card *card, int use_dummy_writes) | |||
399 | * Firmware Loading | 414 | * Firmware Loading |
400 | */ | 415 | */ |
401 | 416 | ||
402 | static int if_spi_prog_helper_firmware(struct if_spi_card *card) | 417 | static int if_spi_prog_helper_firmware(struct if_spi_card *card, |
418 | const struct firmware *firmware) | ||
403 | { | 419 | { |
404 | int err = 0; | 420 | int err = 0; |
405 | const struct firmware *firmware = NULL; | ||
406 | int bytes_remaining; | 421 | int bytes_remaining; |
407 | const u8 *fw; | 422 | const u8 *fw; |
408 | u8 temp[HELPER_FW_LOAD_CHUNK_SZ]; | 423 | u8 temp[HELPER_FW_LOAD_CHUNK_SZ]; |
409 | struct spi_device *spi = card->spi; | ||
410 | 424 | ||
411 | lbs_deb_enter(LBS_DEB_SPI); | 425 | lbs_deb_enter(LBS_DEB_SPI); |
412 | 426 | ||
413 | err = spu_set_interrupt_mode(card, 1, 0); | 427 | err = spu_set_interrupt_mode(card, 1, 0); |
414 | if (err) | 428 | if (err) |
415 | goto out; | 429 | goto out; |
416 | /* Get helper firmware image */ | 430 | |
417 | err = request_firmware(&firmware, card->helper_fw_name, &spi->dev); | ||
418 | if (err) { | ||
419 | lbs_pr_err("request_firmware failed with err = %d\n", err); | ||
420 | goto out; | ||
421 | } | ||
422 | bytes_remaining = firmware->size; | 431 | bytes_remaining = firmware->size; |
423 | fw = firmware->data; | 432 | fw = firmware->data; |
424 | 433 | ||
@@ -429,13 +438,13 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card) | |||
429 | err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG, | 438 | err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG, |
430 | HELPER_FW_LOAD_CHUNK_SZ); | 439 | HELPER_FW_LOAD_CHUNK_SZ); |
431 | if (err) | 440 | if (err) |
432 | goto release_firmware; | 441 | goto out; |
433 | 442 | ||
434 | err = spu_wait_for_u16(card, IF_SPI_HOST_INT_STATUS_REG, | 443 | err = spu_wait_for_u16(card, IF_SPI_HOST_INT_STATUS_REG, |
435 | IF_SPI_HIST_CMD_DOWNLOAD_RDY, | 444 | IF_SPI_HIST_CMD_DOWNLOAD_RDY, |
436 | IF_SPI_HIST_CMD_DOWNLOAD_RDY); | 445 | IF_SPI_HIST_CMD_DOWNLOAD_RDY); |
437 | if (err) | 446 | if (err) |
438 | goto release_firmware; | 447 | goto out; |
439 | 448 | ||
440 | /* Feed the data into the command read/write port reg | 449 | /* Feed the data into the command read/write port reg |
441 | * in chunks of 64 bytes */ | 450 | * in chunks of 64 bytes */ |
@@ -446,16 +455,16 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card) | |||
446 | err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG, | 455 | err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG, |
447 | temp, HELPER_FW_LOAD_CHUNK_SZ); | 456 | temp, HELPER_FW_LOAD_CHUNK_SZ); |
448 | if (err) | 457 | if (err) |
449 | goto release_firmware; | 458 | goto out; |
450 | 459 | ||
451 | /* Interrupt the boot code */ | 460 | /* Interrupt the boot code */ |
452 | err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0); | 461 | err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0); |
453 | if (err) | 462 | if (err) |
454 | goto release_firmware; | 463 | goto out; |
455 | err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG, | 464 | err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG, |
456 | IF_SPI_CIC_CMD_DOWNLOAD_OVER); | 465 | IF_SPI_CIC_CMD_DOWNLOAD_OVER); |
457 | if (err) | 466 | if (err) |
458 | goto release_firmware; | 467 | goto out; |
459 | bytes_remaining -= HELPER_FW_LOAD_CHUNK_SZ; | 468 | bytes_remaining -= HELPER_FW_LOAD_CHUNK_SZ; |
460 | fw += HELPER_FW_LOAD_CHUNK_SZ; | 469 | fw += HELPER_FW_LOAD_CHUNK_SZ; |
461 | } | 470 | } |
@@ -465,18 +474,16 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card) | |||
465 | * bootloader. This completes the helper download. */ | 474 | * bootloader. This completes the helper download. */ |
466 | err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG, FIRMWARE_DNLD_OK); | 475 | err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG, FIRMWARE_DNLD_OK); |
467 | if (err) | 476 | if (err) |
468 | goto release_firmware; | 477 | goto out; |
469 | err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0); | 478 | err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0); |
470 | if (err) | 479 | if (err) |
471 | goto release_firmware; | 480 | goto out; |
472 | err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG, | 481 | err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG, |
473 | IF_SPI_CIC_CMD_DOWNLOAD_OVER); | 482 | IF_SPI_CIC_CMD_DOWNLOAD_OVER); |
474 | goto release_firmware; | 483 | goto out; |
475 | 484 | ||
476 | lbs_deb_spi("waiting for helper to boot...\n"); | 485 | lbs_deb_spi("waiting for helper to boot...\n"); |
477 | 486 | ||
478 | release_firmware: | ||
479 | release_firmware(firmware); | ||
480 | out: | 487 | out: |
481 | if (err) | 488 | if (err) |
482 | lbs_pr_err("failed to load helper firmware (err=%d)\n", err); | 489 | 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 | return len; | 530 | return len; |
524 | } | 531 | } |
525 | 532 | ||
526 | static int if_spi_prog_main_firmware(struct if_spi_card *card) | 533 | static int if_spi_prog_main_firmware(struct if_spi_card *card, |
534 | const struct firmware *firmware) | ||
527 | { | 535 | { |
528 | int len, prev_len; | 536 | int len, prev_len; |
529 | int bytes, crc_err = 0, err = 0; | 537 | int bytes, crc_err = 0, err = 0; |
530 | const struct firmware *firmware = NULL; | ||
531 | const u8 *fw; | 538 | const u8 *fw; |
532 | struct spi_device *spi = card->spi; | ||
533 | u16 num_crc_errs; | 539 | u16 num_crc_errs; |
534 | 540 | ||
535 | lbs_deb_enter(LBS_DEB_SPI); | 541 | lbs_deb_enter(LBS_DEB_SPI); |
@@ -538,19 +544,11 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card) | |||
538 | if (err) | 544 | if (err) |
539 | goto out; | 545 | goto out; |
540 | 546 | ||
541 | /* Get firmware image */ | ||
542 | err = request_firmware(&firmware, card->main_fw_name, &spi->dev); | ||
543 | if (err) { | ||
544 | lbs_pr_err("%s: can't get firmware '%s' from kernel. " | ||
545 | "err = %d\n", __func__, card->main_fw_name, err); | ||
546 | goto out; | ||
547 | } | ||
548 | |||
549 | err = spu_wait_for_u16(card, IF_SPI_SCRATCH_1_REG, 0, 0); | 547 | err = spu_wait_for_u16(card, IF_SPI_SCRATCH_1_REG, 0, 0); |
550 | if (err) { | 548 | if (err) { |
551 | lbs_pr_err("%s: timed out waiting for initial " | 549 | lbs_pr_err("%s: timed out waiting for initial " |
552 | "scratch reg = 0\n", __func__); | 550 | "scratch reg = 0\n", __func__); |
553 | goto release_firmware; | 551 | goto out; |
554 | } | 552 | } |
555 | 553 | ||
556 | num_crc_errs = 0; | 554 | num_crc_errs = 0; |
@@ -560,7 +558,7 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card) | |||
560 | while ((len = if_spi_prog_main_firmware_check_len(card, &crc_err))) { | 558 | while ((len = if_spi_prog_main_firmware_check_len(card, &crc_err))) { |
561 | if (len < 0) { | 559 | if (len < 0) { |
562 | err = len; | 560 | err = len; |
563 | goto release_firmware; | 561 | goto out; |
564 | } | 562 | } |
565 | if (bytes < 0) { | 563 | if (bytes < 0) { |
566 | /* If there are no more bytes left, we would normally | 564 | /* 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 | lbs_pr_err("Too many CRC errors encountered " | 573 | lbs_pr_err("Too many CRC errors encountered " |
576 | "in firmware load.\n"); | 574 | "in firmware load.\n"); |
577 | err = -EIO; | 575 | err = -EIO; |
578 | goto release_firmware; | 576 | goto out; |
579 | } | 577 | } |
580 | } else { | 578 | } else { |
581 | /* Previous transfer succeeded. Advance counters. */ | 579 | /* Previous transfer succeeded. Advance counters. */ |
@@ -590,15 +588,15 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card) | |||
590 | 588 | ||
591 | err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0); | 589 | err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0); |
592 | if (err) | 590 | if (err) |
593 | goto release_firmware; | 591 | goto out; |
594 | err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG, | 592 | err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG, |
595 | card->cmd_buffer, len); | 593 | card->cmd_buffer, len); |
596 | if (err) | 594 | if (err) |
597 | goto release_firmware; | 595 | goto out; |
598 | err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG , | 596 | err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG , |
599 | IF_SPI_CIC_CMD_DOWNLOAD_OVER); | 597 | IF_SPI_CIC_CMD_DOWNLOAD_OVER); |
600 | if (err) | 598 | if (err) |
601 | goto release_firmware; | 599 | goto out; |
602 | prev_len = len; | 600 | prev_len = len; |
603 | } | 601 | } |
604 | if (bytes > prev_len) { | 602 | if (bytes > prev_len) { |
@@ -611,12 +609,9 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card) | |||
611 | SUCCESSFUL_FW_DOWNLOAD_MAGIC); | 609 | SUCCESSFUL_FW_DOWNLOAD_MAGIC); |
612 | if (err) { | 610 | if (err) { |
613 | lbs_pr_err("failed to confirm the firmware download\n"); | 611 | lbs_pr_err("failed to confirm the firmware download\n"); |
614 | goto release_firmware; | 612 | goto out; |
615 | } | 613 | } |
616 | 614 | ||
617 | release_firmware: | ||
618 | release_firmware(firmware); | ||
619 | |||
620 | out: | 615 | out: |
621 | if (err) | 616 | if (err) |
622 | lbs_pr_err("failed to load firmware (err=%d)\n", err); | 617 | 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 | * SPI callbacks | 883 | * SPI callbacks |
889 | */ | 884 | */ |
890 | 885 | ||
891 | static int if_spi_calculate_fw_names(u16 card_id, | ||
892 | char *helper_fw, char *main_fw) | ||
893 | { | ||
894 | int i; | ||
895 | for (i = 0; i < ARRAY_SIZE(chip_id_to_device_name); ++i) { | ||
896 | if (card_id == chip_id_to_device_name[i].chip_id) | ||
897 | break; | ||
898 | } | ||
899 | if (i == ARRAY_SIZE(chip_id_to_device_name)) { | ||
900 | lbs_pr_err("Unsupported chip_id: 0x%02x\n", card_id); | ||
901 | return -EAFNOSUPPORT; | ||
902 | } | ||
903 | snprintf(helper_fw, IF_SPI_FW_NAME_MAX, "libertas/gspi%d_hlp.bin", | ||
904 | chip_id_to_device_name[i].name); | ||
905 | snprintf(main_fw, IF_SPI_FW_NAME_MAX, "libertas/gspi%d.bin", | ||
906 | chip_id_to_device_name[i].name); | ||
907 | return 0; | ||
908 | } | ||
909 | MODULE_FIRMWARE("libertas/gspi8385_hlp.bin"); | ||
910 | MODULE_FIRMWARE("libertas/gspi8385.bin"); | ||
911 | MODULE_FIRMWARE("libertas/gspi8686_hlp.bin"); | ||
912 | MODULE_FIRMWARE("libertas/gspi8686.bin"); | ||
913 | |||
914 | static int __devinit if_spi_probe(struct spi_device *spi) | 886 | static int __devinit if_spi_probe(struct spi_device *spi) |
915 | { | 887 | { |
916 | struct if_spi_card *card; | 888 | struct if_spi_card *card; |
917 | struct lbs_private *priv = NULL; | 889 | struct lbs_private *priv = NULL; |
918 | struct libertas_spi_platform_data *pdata = spi->dev.platform_data; | 890 | struct libertas_spi_platform_data *pdata = spi->dev.platform_data; |
919 | int err = 0; | 891 | int err = 0, i; |
920 | u32 scratch; | 892 | u32 scratch; |
921 | struct sched_param param = { .sched_priority = 1 }; | 893 | struct sched_param param = { .sched_priority = 1 }; |
894 | const struct firmware *helper = NULL; | ||
895 | const struct firmware *mainfw = NULL; | ||
922 | 896 | ||
923 | lbs_deb_enter(LBS_DEB_SPI); | 897 | lbs_deb_enter(LBS_DEB_SPI); |
924 | 898 | ||
@@ -963,10 +937,25 @@ static int __devinit if_spi_probe(struct spi_device *spi) | |||
963 | lbs_deb_spi("Firmware is already loaded for " | 937 | lbs_deb_spi("Firmware is already loaded for " |
964 | "Marvell WLAN 802.11 adapter\n"); | 938 | "Marvell WLAN 802.11 adapter\n"); |
965 | else { | 939 | else { |
966 | err = if_spi_calculate_fw_names(card->card_id, | 940 | /* Check if we support this card */ |
967 | card->helper_fw_name, card->main_fw_name); | 941 | for (i = 0; i < ARRAY_SIZE(fw_table); i++) { |
968 | if (err) | 942 | if (card->card_id == fw_table[i].model) |
943 | break; | ||
944 | } | ||
945 | if (i == ARRAY_SIZE(fw_table)) { | ||
946 | lbs_pr_err("Unsupported chip_id: 0x%02x\n", | ||
947 | card->card_id); | ||
948 | err = -ENODEV; | ||
969 | goto free_card; | 949 | goto free_card; |
950 | } | ||
951 | |||
952 | err = lbs_get_firmware(&card->spi->dev, NULL, NULL, | ||
953 | card->card_id, &fw_table[0], &helper, | ||
954 | &mainfw); | ||
955 | if (err) { | ||
956 | lbs_pr_err("failed to find firmware (%d)\n", err); | ||
957 | goto free_card; | ||
958 | } | ||
970 | 959 | ||
971 | lbs_deb_spi("Initializing FW for Marvell WLAN 802.11 adapter " | 960 | lbs_deb_spi("Initializing FW for Marvell WLAN 802.11 adapter " |
972 | "(chip_id = 0x%04x, chip_rev = 0x%02x) " | 961 | "(chip_id = 0x%04x, chip_rev = 0x%02x) " |
@@ -975,10 +964,10 @@ static int __devinit if_spi_probe(struct spi_device *spi) | |||
975 | card->card_id, card->card_rev, | 964 | card->card_id, card->card_rev, |
976 | spi->master->bus_num, spi->chip_select, | 965 | spi->master->bus_num, spi->chip_select, |
977 | spi->max_speed_hz); | 966 | spi->max_speed_hz); |
978 | err = if_spi_prog_helper_firmware(card); | 967 | err = if_spi_prog_helper_firmware(card, helper); |
979 | if (err) | 968 | if (err) |
980 | goto free_card; | 969 | goto free_card; |
981 | err = if_spi_prog_main_firmware(card); | 970 | err = if_spi_prog_main_firmware(card, mainfw); |
982 | if (err) | 971 | if (err) |
983 | goto free_card; | 972 | goto free_card; |
984 | lbs_deb_spi("loaded FW for Marvell WLAN 802.11 adapter\n"); | 973 | lbs_deb_spi("loaded FW for Marvell WLAN 802.11 adapter\n"); |
@@ -1046,6 +1035,11 @@ remove_card: | |||
1046 | free_card: | 1035 | free_card: |
1047 | free_if_spi_card(card); | 1036 | free_if_spi_card(card); |
1048 | out: | 1037 | out: |
1038 | if (helper) | ||
1039 | release_firmware(helper); | ||
1040 | if (mainfw) | ||
1041 | release_firmware(mainfw); | ||
1042 | |||
1049 | lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err); | 1043 | lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err); |
1050 | return err; | 1044 | return err; |
1051 | } | 1045 | } |
diff --git a/drivers/net/wireless/libertas/if_spi.h b/drivers/net/wireless/libertas/if_spi.h index f87eec410848..8b1417d3b71b 100644 --- a/drivers/net/wireless/libertas/if_spi.h +++ b/drivers/net/wireless/libertas/if_spi.h | |||
@@ -25,11 +25,6 @@ | |||
25 | 25 | ||
26 | #define IF_SPI_FW_NAME_MAX 30 | 26 | #define IF_SPI_FW_NAME_MAX 30 |
27 | 27 | ||
28 | struct chip_ident { | ||
29 | u16 chip_id; | ||
30 | u16 name; | ||
31 | }; | ||
32 | |||
33 | #define MAX_MAIN_FW_LOAD_CRC_ERR 10 | 28 | #define MAX_MAIN_FW_LOAD_CRC_ERR 10 |
34 | 29 | ||
35 | /* Chunk size when loading the helper firmware */ | 30 | /* Chunk size when loading the helper firmware */ |