aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/cxgb4
diff options
context:
space:
mode:
authorDimitris Michailidis <dm@chelsio.com>2010-06-18 06:05:27 -0400
committerDavid S. Miller <davem@davemloft.net>2010-06-19 01:08:34 -0400
commit900a659687aa6349e52f7b1e3f922b77afe89b90 (patch)
tree5617d9684ec5d826a4c868398f62786081108467 /drivers/net/cxgb4
parentbb9c03d8a6893517737b16fdbeb54be3c73b3023 (diff)
cxgb4: dynamically determine flash size and FW image location
Handle the larger flash memories on newer boards: - get the size and number of sectors by probing the flash - writes and erases can take longer, adjust the timeouts for these operations - the FW image can be at different locations depending on flash size, find its location dynamically as well. Signed-off-by: Dimitris Michailidis <dm@chelsio.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/cxgb4')
-rw-r--r--drivers/net/cxgb4/cxgb4.h4
-rw-r--r--drivers/net/cxgb4/t4_hw.c75
-rw-r--r--drivers/net/cxgb4/t4_hw.h2
-rw-r--r--drivers/net/cxgb4/t4_regs.h3
4 files changed, 61 insertions, 23 deletions
diff --git a/drivers/net/cxgb4/cxgb4.h b/drivers/net/cxgb4/cxgb4.h
index dd1770e075e6..bfa136622f10 100644
--- a/drivers/net/cxgb4/cxgb4.h
+++ b/drivers/net/cxgb4/cxgb4.h
@@ -219,6 +219,10 @@ struct adapter_params {
219 struct vpd_params vpd; 219 struct vpd_params vpd;
220 struct pci_params pci; 220 struct pci_params pci;
221 221
222 unsigned int sf_size; /* serial flash size in bytes */
223 unsigned int sf_nsec; /* # of flash sectors */
224 unsigned int sf_fw_start; /* start of FW image in flash */
225
222 unsigned int fw_vers; 226 unsigned int fw_vers;
223 unsigned int tp_vers; 227 unsigned int tp_vers;
224 u8 api_vers[7]; 228 u8 api_vers[7];
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 */
648static int get_fw_version(struct adapter *adapter, u32 *vers) 646static 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 */
662static int get_tp_version(struct adapter *adapter, u32 *vers) 659static 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);
815out: 815out:
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
3056static 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;
diff --git a/drivers/net/cxgb4/t4_hw.h b/drivers/net/cxgb4/t4_hw.h
index 025623285c93..f886677b93ec 100644
--- a/drivers/net/cxgb4/t4_hw.h
+++ b/drivers/net/cxgb4/t4_hw.h
@@ -57,8 +57,6 @@ enum {
57 57
58enum { 58enum {
59 SF_PAGE_SIZE = 256, /* serial flash page size */ 59 SF_PAGE_SIZE = 256, /* serial flash page size */
60 SF_SEC_SIZE = 64 * 1024, /* serial flash sector size */
61 SF_SIZE = SF_SEC_SIZE * 16, /* serial flash size */
62}; 60};
63 61
64enum { RSP_TYPE_FLBUF, RSP_TYPE_CPL, RSP_TYPE_INTR }; /* response entry types */ 62enum { RSP_TYPE_FLBUF, RSP_TYPE_CPL, RSP_TYPE_INTR }; /* response entry types */
diff --git a/drivers/net/cxgb4/t4_regs.h b/drivers/net/cxgb4/t4_regs.h
index 5ed56483cbc2..8fed46df886c 100644
--- a/drivers/net/cxgb4/t4_regs.h
+++ b/drivers/net/cxgb4/t4_regs.h
@@ -326,6 +326,9 @@
326 326
327#define EDC_1_BASE_ADDR 0x7980 327#define EDC_1_BASE_ADDR 0x7980
328 328
329#define CIM_BOOT_CFG 0x7b00
330#define BOOTADDR_MASK 0xffffff00U
331
329#define CIM_PF_MAILBOX_DATA 0x240 332#define CIM_PF_MAILBOX_DATA 0x240
330#define CIM_PF_MAILBOX_CTRL 0x280 333#define CIM_PF_MAILBOX_CTRL 0x280
331#define MBMSGVALID 0x00000008U 334#define MBMSGVALID 0x00000008U