diff options
Diffstat (limited to 'drivers/net/wireless/libertas/if_spi.c')
-rw-r--r-- | drivers/net/wireless/libertas/if_spi.c | 150 |
1 files changed, 73 insertions, 77 deletions
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c index fe3f08028eb..79bcb4e5d2c 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); |
@@ -800,14 +795,16 @@ static int lbs_spi_thread(void *data) | |||
800 | goto err; | 795 | goto err; |
801 | } | 796 | } |
802 | 797 | ||
803 | if (hiStatus & IF_SPI_HIST_CMD_UPLOAD_RDY) | 798 | if (hiStatus & IF_SPI_HIST_CMD_UPLOAD_RDY) { |
804 | err = if_spi_c2h_cmd(card); | 799 | err = if_spi_c2h_cmd(card); |
805 | if (err) | 800 | if (err) |
806 | goto err; | 801 | goto err; |
807 | if (hiStatus & IF_SPI_HIST_RX_UPLOAD_RDY) | 802 | } |
803 | if (hiStatus & IF_SPI_HIST_RX_UPLOAD_RDY) { | ||
808 | err = if_spi_c2h_data(card); | 804 | err = if_spi_c2h_data(card); |
809 | if (err) | 805 | if (err) |
810 | goto err; | 806 | goto err; |
807 | } | ||
811 | 808 | ||
812 | /* workaround: in PS mode, the card does not set the Command | 809 | /* workaround: in PS mode, the card does not set the Command |
813 | * Download Ready bit, but it sets TX Download Ready. */ | 810 | * Download Ready bit, but it sets TX Download Ready. */ |
@@ -886,37 +883,16 @@ static irqreturn_t if_spi_host_interrupt(int irq, void *dev_id) | |||
886 | * SPI callbacks | 883 | * SPI callbacks |
887 | */ | 884 | */ |
888 | 885 | ||
889 | static int if_spi_calculate_fw_names(u16 card_id, | ||
890 | char *helper_fw, char *main_fw) | ||
891 | { | ||
892 | int i; | ||
893 | for (i = 0; i < ARRAY_SIZE(chip_id_to_device_name); ++i) { | ||
894 | if (card_id == chip_id_to_device_name[i].chip_id) | ||
895 | break; | ||
896 | } | ||
897 | if (i == ARRAY_SIZE(chip_id_to_device_name)) { | ||
898 | lbs_pr_err("Unsupported chip_id: 0x%02x\n", card_id); | ||
899 | return -EAFNOSUPPORT; | ||
900 | } | ||
901 | snprintf(helper_fw, IF_SPI_FW_NAME_MAX, "libertas/gspi%d_hlp.bin", | ||
902 | chip_id_to_device_name[i].name); | ||
903 | snprintf(main_fw, IF_SPI_FW_NAME_MAX, "libertas/gspi%d.bin", | ||
904 | chip_id_to_device_name[i].name); | ||
905 | return 0; | ||
906 | } | ||
907 | MODULE_FIRMWARE("libertas/gspi8385_hlp.bin"); | ||
908 | MODULE_FIRMWARE("libertas/gspi8385.bin"); | ||
909 | MODULE_FIRMWARE("libertas/gspi8686_hlp.bin"); | ||
910 | MODULE_FIRMWARE("libertas/gspi8686.bin"); | ||
911 | |||
912 | static int __devinit if_spi_probe(struct spi_device *spi) | 886 | static int __devinit if_spi_probe(struct spi_device *spi) |
913 | { | 887 | { |
914 | struct if_spi_card *card; | 888 | struct if_spi_card *card; |
915 | struct lbs_private *priv = NULL; | 889 | struct lbs_private *priv = NULL; |
916 | struct libertas_spi_platform_data *pdata = spi->dev.platform_data; | 890 | struct libertas_spi_platform_data *pdata = spi->dev.platform_data; |
917 | int err = 0; | 891 | int err = 0, i; |
918 | u32 scratch; | 892 | u32 scratch; |
919 | 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; | ||
920 | 896 | ||
921 | lbs_deb_enter(LBS_DEB_SPI); | 897 | lbs_deb_enter(LBS_DEB_SPI); |
922 | 898 | ||
@@ -961,10 +937,25 @@ static int __devinit if_spi_probe(struct spi_device *spi) | |||
961 | lbs_deb_spi("Firmware is already loaded for " | 937 | lbs_deb_spi("Firmware is already loaded for " |
962 | "Marvell WLAN 802.11 adapter\n"); | 938 | "Marvell WLAN 802.11 adapter\n"); |
963 | else { | 939 | else { |
964 | err = if_spi_calculate_fw_names(card->card_id, | 940 | /* Check if we support this card */ |
965 | card->helper_fw_name, card->main_fw_name); | 941 | for (i = 0; i < ARRAY_SIZE(fw_table); i++) { |
966 | 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; | ||
967 | 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 | } | ||
968 | 959 | ||
969 | lbs_deb_spi("Initializing FW for Marvell WLAN 802.11 adapter " | 960 | lbs_deb_spi("Initializing FW for Marvell WLAN 802.11 adapter " |
970 | "(chip_id = 0x%04x, chip_rev = 0x%02x) " | 961 | "(chip_id = 0x%04x, chip_rev = 0x%02x) " |
@@ -973,10 +964,10 @@ static int __devinit if_spi_probe(struct spi_device *spi) | |||
973 | card->card_id, card->card_rev, | 964 | card->card_id, card->card_rev, |
974 | spi->master->bus_num, spi->chip_select, | 965 | spi->master->bus_num, spi->chip_select, |
975 | spi->max_speed_hz); | 966 | spi->max_speed_hz); |
976 | err = if_spi_prog_helper_firmware(card); | 967 | err = if_spi_prog_helper_firmware(card, helper); |
977 | if (err) | 968 | if (err) |
978 | goto free_card; | 969 | goto free_card; |
979 | err = if_spi_prog_main_firmware(card); | 970 | err = if_spi_prog_main_firmware(card, mainfw); |
980 | if (err) | 971 | if (err) |
981 | goto free_card; | 972 | goto free_card; |
982 | 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"); |
@@ -1044,6 +1035,11 @@ remove_card: | |||
1044 | free_card: | 1035 | free_card: |
1045 | free_if_spi_card(card); | 1036 | free_if_spi_card(card); |
1046 | out: | 1037 | out: |
1038 | if (helper) | ||
1039 | release_firmware(helper); | ||
1040 | if (mainfw) | ||
1041 | release_firmware(mainfw); | ||
1042 | |||
1047 | lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err); | 1043 | lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err); |
1048 | return err; | 1044 | return err; |
1049 | } | 1045 | } |