diff options
Diffstat (limited to 'drivers/net/cxgb4/t4_hw.c')
-rw-r--r-- | drivers/net/cxgb4/t4_hw.c | 75 |
1 files changed, 54 insertions, 21 deletions
diff --git a/drivers/net/cxgb4/t4_hw.c b/drivers/net/cxgb4/t4_hw.c index da272a98fdbc..5c81c558ce62 100644 --- a/drivers/net/cxgb4/t4_hw.c +++ b/drivers/net/cxgb4/t4_hw.c | |||
@@ -449,12 +449,10 @@ enum { | |||
449 | SF_RD_STATUS = 5, /* read status register */ | 449 | SF_RD_STATUS = 5, /* read status register */ |
450 | SF_WR_ENABLE = 6, /* enable writes */ | 450 | SF_WR_ENABLE = 6, /* enable writes */ |
451 | SF_RD_DATA_FAST = 0xb, /* read flash */ | 451 | SF_RD_DATA_FAST = 0xb, /* read flash */ |
452 | SF_RD_ID = 0x9f, /* read ID */ | ||
452 | SF_ERASE_SECTOR = 0xd8, /* erase sector */ | 453 | SF_ERASE_SECTOR = 0xd8, /* erase sector */ |
453 | 454 | ||
454 | FW_START_SEC = 8, /* first flash sector for FW */ | 455 | FW_MAX_SIZE = 512 * 1024, |
455 | FW_END_SEC = 15, /* last flash sector for FW */ | ||
456 | FW_IMG_START = FW_START_SEC * SF_SEC_SIZE, | ||
457 | FW_MAX_SIZE = (FW_END_SEC - FW_START_SEC + 1) * SF_SEC_SIZE, | ||
458 | }; | 456 | }; |
459 | 457 | ||
460 | /** | 458 | /** |
@@ -558,7 +556,7 @@ static int t4_read_flash(struct adapter *adapter, unsigned int addr, | |||
558 | { | 556 | { |
559 | int ret; | 557 | int ret; |
560 | 558 | ||
561 | if (addr + nwords * sizeof(u32) > SF_SIZE || (addr & 3)) | 559 | if (addr + nwords * sizeof(u32) > adapter->params.sf_size || (addr & 3)) |
562 | return -EINVAL; | 560 | return -EINVAL; |
563 | 561 | ||
564 | addr = swab32(addr) | SF_RD_DATA_FAST; | 562 | addr = swab32(addr) | SF_RD_DATA_FAST; |
@@ -596,7 +594,7 @@ static int t4_write_flash(struct adapter *adapter, unsigned int addr, | |||
596 | u32 buf[64]; | 594 | u32 buf[64]; |
597 | unsigned int i, c, left, val, offset = addr & 0xff; | 595 | unsigned int i, c, left, val, offset = addr & 0xff; |
598 | 596 | ||
599 | if (addr >= SF_SIZE || offset + n > SF_PAGE_SIZE) | 597 | if (addr >= adapter->params.sf_size || offset + n > SF_PAGE_SIZE) |
600 | return -EINVAL; | 598 | return -EINVAL; |
601 | 599 | ||
602 | val = swab32(addr) | SF_PROG_PAGE; | 600 | val = swab32(addr) | SF_PROG_PAGE; |
@@ -614,7 +612,7 @@ static int t4_write_flash(struct adapter *adapter, unsigned int addr, | |||
614 | if (ret) | 612 | if (ret) |
615 | goto unlock; | 613 | goto unlock; |
616 | } | 614 | } |
617 | ret = flash_wait_op(adapter, 5, 1); | 615 | ret = flash_wait_op(adapter, 8, 1); |
618 | if (ret) | 616 | if (ret) |
619 | goto unlock; | 617 | goto unlock; |
620 | 618 | ||
@@ -647,9 +645,8 @@ unlock: | |||
647 | */ | 645 | */ |
648 | static int get_fw_version(struct adapter *adapter, u32 *vers) | 646 | static int get_fw_version(struct adapter *adapter, u32 *vers) |
649 | { | 647 | { |
650 | return t4_read_flash(adapter, | 648 | return t4_read_flash(adapter, adapter->params.sf_fw_start + |
651 | FW_IMG_START + offsetof(struct fw_hdr, fw_ver), 1, | 649 | offsetof(struct fw_hdr, fw_ver), 1, vers, 0); |
652 | vers, 0); | ||
653 | } | 650 | } |
654 | 651 | ||
655 | /** | 652 | /** |
@@ -661,8 +658,8 @@ static int get_fw_version(struct adapter *adapter, u32 *vers) | |||
661 | */ | 658 | */ |
662 | static int get_tp_version(struct adapter *adapter, u32 *vers) | 659 | static int get_tp_version(struct adapter *adapter, u32 *vers) |
663 | { | 660 | { |
664 | return t4_read_flash(adapter, FW_IMG_START + offsetof(struct fw_hdr, | 661 | return t4_read_flash(adapter, adapter->params.sf_fw_start + |
665 | tp_microcode_ver), | 662 | offsetof(struct fw_hdr, tp_microcode_ver), |
666 | 1, vers, 0); | 663 | 1, vers, 0); |
667 | } | 664 | } |
668 | 665 | ||
@@ -684,9 +681,9 @@ int t4_check_fw_version(struct adapter *adapter) | |||
684 | if (!ret) | 681 | if (!ret) |
685 | ret = get_tp_version(adapter, &adapter->params.tp_vers); | 682 | ret = get_tp_version(adapter, &adapter->params.tp_vers); |
686 | if (!ret) | 683 | if (!ret) |
687 | ret = t4_read_flash(adapter, | 684 | ret = t4_read_flash(adapter, adapter->params.sf_fw_start + |
688 | FW_IMG_START + offsetof(struct fw_hdr, intfver_nic), | 685 | offsetof(struct fw_hdr, intfver_nic), |
689 | 2, api_vers, 1); | 686 | 2, api_vers, 1); |
690 | if (ret) | 687 | if (ret) |
691 | return ret; | 688 | return ret; |
692 | 689 | ||
@@ -726,7 +723,7 @@ static int t4_flash_erase_sectors(struct adapter *adapter, int start, int end) | |||
726 | if ((ret = sf1_write(adapter, 1, 0, 1, SF_WR_ENABLE)) != 0 || | 723 | if ((ret = sf1_write(adapter, 1, 0, 1, SF_WR_ENABLE)) != 0 || |
727 | (ret = sf1_write(adapter, 4, 0, 1, | 724 | (ret = sf1_write(adapter, 4, 0, 1, |
728 | SF_ERASE_SECTOR | (start << 8))) != 0 || | 725 | SF_ERASE_SECTOR | (start << 8))) != 0 || |
729 | (ret = flash_wait_op(adapter, 5, 500)) != 0) { | 726 | (ret = flash_wait_op(adapter, 14, 500)) != 0) { |
730 | dev_err(adapter->pdev_dev, | 727 | dev_err(adapter->pdev_dev, |
731 | "erase of flash sector %d failed, error %d\n", | 728 | "erase of flash sector %d failed, error %d\n", |
732 | start, ret); | 729 | start, ret); |
@@ -754,6 +751,9 @@ int t4_load_fw(struct adapter *adap, const u8 *fw_data, unsigned int size) | |||
754 | u8 first_page[SF_PAGE_SIZE]; | 751 | u8 first_page[SF_PAGE_SIZE]; |
755 | const u32 *p = (const u32 *)fw_data; | 752 | const u32 *p = (const u32 *)fw_data; |
756 | const struct fw_hdr *hdr = (const struct fw_hdr *)fw_data; | 753 | const struct fw_hdr *hdr = (const struct fw_hdr *)fw_data; |
754 | unsigned int sf_sec_size = adap->params.sf_size / adap->params.sf_nsec; | ||
755 | unsigned int fw_img_start = adap->params.sf_fw_start; | ||
756 | unsigned int fw_start_sec = fw_img_start / sf_sec_size; | ||
757 | 757 | ||
758 | if (!size) { | 758 | if (!size) { |
759 | dev_err(adap->pdev_dev, "FW image has no data\n"); | 759 | dev_err(adap->pdev_dev, "FW image has no data\n"); |
@@ -784,8 +784,8 @@ int t4_load_fw(struct adapter *adap, const u8 *fw_data, unsigned int size) | |||
784 | return -EINVAL; | 784 | return -EINVAL; |
785 | } | 785 | } |
786 | 786 | ||
787 | i = DIV_ROUND_UP(size, SF_SEC_SIZE); /* # of sectors spanned */ | 787 | i = DIV_ROUND_UP(size, sf_sec_size); /* # of sectors spanned */ |
788 | ret = t4_flash_erase_sectors(adap, FW_START_SEC, FW_START_SEC + i - 1); | 788 | ret = t4_flash_erase_sectors(adap, fw_start_sec, fw_start_sec + i - 1); |
789 | if (ret) | 789 | if (ret) |
790 | goto out; | 790 | goto out; |
791 | 791 | ||
@@ -796,11 +796,11 @@ int t4_load_fw(struct adapter *adap, const u8 *fw_data, unsigned int size) | |||
796 | */ | 796 | */ |
797 | memcpy(first_page, fw_data, SF_PAGE_SIZE); | 797 | memcpy(first_page, fw_data, SF_PAGE_SIZE); |
798 | ((struct fw_hdr *)first_page)->fw_ver = htonl(0xffffffff); | 798 | ((struct fw_hdr *)first_page)->fw_ver = htonl(0xffffffff); |
799 | ret = t4_write_flash(adap, FW_IMG_START, SF_PAGE_SIZE, first_page); | 799 | ret = t4_write_flash(adap, fw_img_start, SF_PAGE_SIZE, first_page); |
800 | if (ret) | 800 | if (ret) |
801 | goto out; | 801 | goto out; |
802 | 802 | ||
803 | addr = FW_IMG_START; | 803 | addr = fw_img_start; |
804 | for (size -= SF_PAGE_SIZE; size; size -= SF_PAGE_SIZE) { | 804 | for (size -= SF_PAGE_SIZE; size; size -= SF_PAGE_SIZE) { |
805 | addr += SF_PAGE_SIZE; | 805 | addr += SF_PAGE_SIZE; |
806 | fw_data += SF_PAGE_SIZE; | 806 | fw_data += SF_PAGE_SIZE; |
@@ -810,7 +810,7 @@ int t4_load_fw(struct adapter *adap, const u8 *fw_data, unsigned int size) | |||
810 | } | 810 | } |
811 | 811 | ||
812 | ret = t4_write_flash(adap, | 812 | ret = t4_write_flash(adap, |
813 | FW_IMG_START + offsetof(struct fw_hdr, fw_ver), | 813 | fw_img_start + offsetof(struct fw_hdr, fw_ver), |
814 | sizeof(hdr->fw_ver), (const u8 *)&hdr->fw_ver); | 814 | sizeof(hdr->fw_ver), (const u8 *)&hdr->fw_ver); |
815 | out: | 815 | out: |
816 | if (ret) | 816 | if (ret) |
@@ -3053,6 +3053,33 @@ static int __devinit wait_dev_ready(struct adapter *adap) | |||
3053 | return t4_read_reg(adap, PL_WHOAMI) != 0xffffffff ? 0 : -EIO; | 3053 | return t4_read_reg(adap, PL_WHOAMI) != 0xffffffff ? 0 : -EIO; |
3054 | } | 3054 | } |
3055 | 3055 | ||
3056 | static int __devinit get_flash_params(struct adapter *adap) | ||
3057 | { | ||
3058 | int ret; | ||
3059 | u32 info; | ||
3060 | |||
3061 | ret = sf1_write(adap, 1, 1, 0, SF_RD_ID); | ||
3062 | if (!ret) | ||
3063 | ret = sf1_read(adap, 3, 0, 1, &info); | ||
3064 | t4_write_reg(adap, SF_OP, 0); /* unlock SF */ | ||
3065 | if (ret) | ||
3066 | return ret; | ||
3067 | |||
3068 | if ((info & 0xff) != 0x20) /* not a Numonix flash */ | ||
3069 | return -EINVAL; | ||
3070 | info >>= 16; /* log2 of size */ | ||
3071 | if (info >= 0x14 && info < 0x18) | ||
3072 | adap->params.sf_nsec = 1 << (info - 16); | ||
3073 | else if (info == 0x18) | ||
3074 | adap->params.sf_nsec = 64; | ||
3075 | else | ||
3076 | return -EINVAL; | ||
3077 | adap->params.sf_size = 1 << info; | ||
3078 | adap->params.sf_fw_start = | ||
3079 | t4_read_reg(adap, CIM_BOOT_CFG) & BOOTADDR_MASK; | ||
3080 | return 0; | ||
3081 | } | ||
3082 | |||
3056 | /** | 3083 | /** |
3057 | * t4_prep_adapter - prepare SW and HW for operation | 3084 | * t4_prep_adapter - prepare SW and HW for operation |
3058 | * @adapter: the adapter | 3085 | * @adapter: the adapter |
@@ -3073,6 +3100,12 @@ int __devinit t4_prep_adapter(struct adapter *adapter) | |||
3073 | get_pci_mode(adapter, &adapter->params.pci); | 3100 | get_pci_mode(adapter, &adapter->params.pci); |
3074 | adapter->params.rev = t4_read_reg(adapter, PL_REV); | 3101 | adapter->params.rev = t4_read_reg(adapter, PL_REV); |
3075 | 3102 | ||
3103 | ret = get_flash_params(adapter); | ||
3104 | if (ret < 0) { | ||
3105 | dev_err(adapter->pdev_dev, "error %d identifying flash\n", ret); | ||
3106 | return ret; | ||
3107 | } | ||
3108 | |||
3076 | ret = get_vpd_params(adapter, &adapter->params.vpd); | 3109 | ret = get_vpd_params(adapter, &adapter->params.vpd); |
3077 | if (ret < 0) | 3110 | if (ret < 0) |
3078 | return ret; | 3111 | return ret; |