Commit 900a6596 authored by Dimitris Michailidis's avatar Dimitris Michailidis Committed by David S. Miller

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: default avatarDimitris Michailidis <dm@chelsio.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent bb9c03d8
...@@ -219,6 +219,10 @@ struct adapter_params { ...@@ -219,6 +219,10 @@ struct adapter_params {
struct vpd_params vpd; struct vpd_params vpd;
struct pci_params pci; struct pci_params pci;
unsigned int sf_size; /* serial flash size in bytes */
unsigned int sf_nsec; /* # of flash sectors */
unsigned int sf_fw_start; /* start of FW image in flash */
unsigned int fw_vers; unsigned int fw_vers;
unsigned int tp_vers; unsigned int tp_vers;
u8 api_vers[7]; u8 api_vers[7];
......
...@@ -449,12 +449,10 @@ enum { ...@@ -449,12 +449,10 @@ enum {
SF_RD_STATUS = 5, /* read status register */ SF_RD_STATUS = 5, /* read status register */
SF_WR_ENABLE = 6, /* enable writes */ SF_WR_ENABLE = 6, /* enable writes */
SF_RD_DATA_FAST = 0xb, /* read flash */ SF_RD_DATA_FAST = 0xb, /* read flash */
SF_RD_ID = 0x9f, /* read ID */
SF_ERASE_SECTOR = 0xd8, /* erase sector */ SF_ERASE_SECTOR = 0xd8, /* erase sector */
FW_START_SEC = 8, /* first flash sector for FW */ FW_MAX_SIZE = 512 * 1024,
FW_END_SEC = 15, /* last flash sector for FW */
FW_IMG_START = FW_START_SEC * SF_SEC_SIZE,
FW_MAX_SIZE = (FW_END_SEC - FW_START_SEC + 1) * SF_SEC_SIZE,
}; };
/** /**
...@@ -558,7 +556,7 @@ static int t4_read_flash(struct adapter *adapter, unsigned int addr, ...@@ -558,7 +556,7 @@ static int t4_read_flash(struct adapter *adapter, unsigned int addr,
{ {
int ret; int ret;
if (addr + nwords * sizeof(u32) > SF_SIZE || (addr & 3)) if (addr + nwords * sizeof(u32) > adapter->params.sf_size || (addr & 3))
return -EINVAL; return -EINVAL;
addr = swab32(addr) | SF_RD_DATA_FAST; addr = swab32(addr) | SF_RD_DATA_FAST;
...@@ -596,7 +594,7 @@ static int t4_write_flash(struct adapter *adapter, unsigned int addr, ...@@ -596,7 +594,7 @@ static int t4_write_flash(struct adapter *adapter, unsigned int addr,
u32 buf[64]; u32 buf[64];
unsigned int i, c, left, val, offset = addr & 0xff; unsigned int i, c, left, val, offset = addr & 0xff;
if (addr >= SF_SIZE || offset + n > SF_PAGE_SIZE) if (addr >= adapter->params.sf_size || offset + n > SF_PAGE_SIZE)
return -EINVAL; return -EINVAL;
val = swab32(addr) | SF_PROG_PAGE; val = swab32(addr) | SF_PROG_PAGE;
...@@ -614,7 +612,7 @@ static int t4_write_flash(struct adapter *adapter, unsigned int addr, ...@@ -614,7 +612,7 @@ static int t4_write_flash(struct adapter *adapter, unsigned int addr,
if (ret) if (ret)
goto unlock; goto unlock;
} }
ret = flash_wait_op(adapter, 5, 1); ret = flash_wait_op(adapter, 8, 1);
if (ret) if (ret)
goto unlock; goto unlock;
...@@ -647,9 +645,8 @@ static int t4_write_flash(struct adapter *adapter, unsigned int addr, ...@@ -647,9 +645,8 @@ static int t4_write_flash(struct adapter *adapter, unsigned int addr,
*/ */
static int get_fw_version(struct adapter *adapter, u32 *vers) static int get_fw_version(struct adapter *adapter, u32 *vers)
{ {
return t4_read_flash(adapter, return t4_read_flash(adapter, adapter->params.sf_fw_start +
FW_IMG_START + offsetof(struct fw_hdr, fw_ver), 1, offsetof(struct fw_hdr, fw_ver), 1, vers, 0);
vers, 0);
} }
/** /**
...@@ -661,8 +658,8 @@ static int get_fw_version(struct adapter *adapter, u32 *vers) ...@@ -661,8 +658,8 @@ static int get_fw_version(struct adapter *adapter, u32 *vers)
*/ */
static int get_tp_version(struct adapter *adapter, u32 *vers) static int get_tp_version(struct adapter *adapter, u32 *vers)
{ {
return t4_read_flash(adapter, FW_IMG_START + offsetof(struct fw_hdr, return t4_read_flash(adapter, adapter->params.sf_fw_start +
tp_microcode_ver), offsetof(struct fw_hdr, tp_microcode_ver),
1, vers, 0); 1, vers, 0);
} }
...@@ -684,9 +681,9 @@ int t4_check_fw_version(struct adapter *adapter) ...@@ -684,9 +681,9 @@ int t4_check_fw_version(struct adapter *adapter)
if (!ret) if (!ret)
ret = get_tp_version(adapter, &adapter->params.tp_vers); ret = get_tp_version(adapter, &adapter->params.tp_vers);
if (!ret) if (!ret)
ret = t4_read_flash(adapter, ret = t4_read_flash(adapter, adapter->params.sf_fw_start +
FW_IMG_START + offsetof(struct fw_hdr, intfver_nic), offsetof(struct fw_hdr, intfver_nic),
2, api_vers, 1); 2, api_vers, 1);
if (ret) if (ret)
return ret; return ret;
...@@ -726,7 +723,7 @@ static int t4_flash_erase_sectors(struct adapter *adapter, int start, int end) ...@@ -726,7 +723,7 @@ static int t4_flash_erase_sectors(struct adapter *adapter, int start, int end)
if ((ret = sf1_write(adapter, 1, 0, 1, SF_WR_ENABLE)) != 0 || if ((ret = sf1_write(adapter, 1, 0, 1, SF_WR_ENABLE)) != 0 ||
(ret = sf1_write(adapter, 4, 0, 1, (ret = sf1_write(adapter, 4, 0, 1,
SF_ERASE_SECTOR | (start << 8))) != 0 || SF_ERASE_SECTOR | (start << 8))) != 0 ||
(ret = flash_wait_op(adapter, 5, 500)) != 0) { (ret = flash_wait_op(adapter, 14, 500)) != 0) {
dev_err(adapter->pdev_dev, dev_err(adapter->pdev_dev,
"erase of flash sector %d failed, error %d\n", "erase of flash sector %d failed, error %d\n",
start, ret); start, ret);
...@@ -754,6 +751,9 @@ int t4_load_fw(struct adapter *adap, const u8 *fw_data, unsigned int size) ...@@ -754,6 +751,9 @@ int t4_load_fw(struct adapter *adap, const u8 *fw_data, unsigned int size)
u8 first_page[SF_PAGE_SIZE]; u8 first_page[SF_PAGE_SIZE];
const u32 *p = (const u32 *)fw_data; const u32 *p = (const u32 *)fw_data;
const struct fw_hdr *hdr = (const struct fw_hdr *)fw_data; const struct fw_hdr *hdr = (const struct fw_hdr *)fw_data;
unsigned int sf_sec_size = adap->params.sf_size / adap->params.sf_nsec;
unsigned int fw_img_start = adap->params.sf_fw_start;
unsigned int fw_start_sec = fw_img_start / sf_sec_size;
if (!size) { if (!size) {
dev_err(adap->pdev_dev, "FW image has no data\n"); 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,8 +784,8 @@ int t4_load_fw(struct adapter *adap, const u8 *fw_data, unsigned int size)
return -EINVAL; return -EINVAL;
} }
i = DIV_ROUND_UP(size, SF_SEC_SIZE); /* # of sectors spanned */ i = DIV_ROUND_UP(size, sf_sec_size); /* # of sectors spanned */
ret = t4_flash_erase_sectors(adap, FW_START_SEC, FW_START_SEC + i - 1); ret = t4_flash_erase_sectors(adap, fw_start_sec, fw_start_sec + i - 1);
if (ret) if (ret)
goto out; goto out;
...@@ -796,11 +796,11 @@ int t4_load_fw(struct adapter *adap, const u8 *fw_data, unsigned int size) ...@@ -796,11 +796,11 @@ int t4_load_fw(struct adapter *adap, const u8 *fw_data, unsigned int size)
*/ */
memcpy(first_page, fw_data, SF_PAGE_SIZE); memcpy(first_page, fw_data, SF_PAGE_SIZE);
((struct fw_hdr *)first_page)->fw_ver = htonl(0xffffffff); ((struct fw_hdr *)first_page)->fw_ver = htonl(0xffffffff);
ret = t4_write_flash(adap, FW_IMG_START, SF_PAGE_SIZE, first_page); ret = t4_write_flash(adap, fw_img_start, SF_PAGE_SIZE, first_page);
if (ret) if (ret)
goto out; goto out;
addr = FW_IMG_START; addr = fw_img_start;
for (size -= SF_PAGE_SIZE; size; size -= SF_PAGE_SIZE) { for (size -= SF_PAGE_SIZE; size; size -= SF_PAGE_SIZE) {
addr += SF_PAGE_SIZE; addr += SF_PAGE_SIZE;
fw_data += SF_PAGE_SIZE; fw_data += SF_PAGE_SIZE;
...@@ -810,7 +810,7 @@ int t4_load_fw(struct adapter *adap, const u8 *fw_data, unsigned int size) ...@@ -810,7 +810,7 @@ int t4_load_fw(struct adapter *adap, const u8 *fw_data, unsigned int size)
} }
ret = t4_write_flash(adap, ret = t4_write_flash(adap,
FW_IMG_START + offsetof(struct fw_hdr, fw_ver), fw_img_start + offsetof(struct fw_hdr, fw_ver),
sizeof(hdr->fw_ver), (const u8 *)&hdr->fw_ver); sizeof(hdr->fw_ver), (const u8 *)&hdr->fw_ver);
out: out:
if (ret) if (ret)
...@@ -3053,6 +3053,33 @@ static int __devinit wait_dev_ready(struct adapter *adap) ...@@ -3053,6 +3053,33 @@ static int __devinit wait_dev_ready(struct adapter *adap)
return t4_read_reg(adap, PL_WHOAMI) != 0xffffffff ? 0 : -EIO; return t4_read_reg(adap, PL_WHOAMI) != 0xffffffff ? 0 : -EIO;
} }
static int __devinit get_flash_params(struct adapter *adap)
{
int ret;
u32 info;
ret = sf1_write(adap, 1, 1, 0, SF_RD_ID);
if (!ret)
ret = sf1_read(adap, 3, 0, 1, &info);
t4_write_reg(adap, SF_OP, 0); /* unlock SF */
if (ret)
return ret;
if ((info & 0xff) != 0x20) /* not a Numonix flash */
return -EINVAL;
info >>= 16; /* log2 of size */
if (info >= 0x14 && info < 0x18)
adap->params.sf_nsec = 1 << (info - 16);
else if (info == 0x18)
adap->params.sf_nsec = 64;
else
return -EINVAL;
adap->params.sf_size = 1 << info;
adap->params.sf_fw_start =
t4_read_reg(adap, CIM_BOOT_CFG) & BOOTADDR_MASK;
return 0;
}
/** /**
* t4_prep_adapter - prepare SW and HW for operation * t4_prep_adapter - prepare SW and HW for operation
* @adapter: the adapter * @adapter: the adapter
...@@ -3073,6 +3100,12 @@ int __devinit t4_prep_adapter(struct adapter *adapter) ...@@ -3073,6 +3100,12 @@ int __devinit t4_prep_adapter(struct adapter *adapter)
get_pci_mode(adapter, &adapter->params.pci); get_pci_mode(adapter, &adapter->params.pci);
adapter->params.rev = t4_read_reg(adapter, PL_REV); adapter->params.rev = t4_read_reg(adapter, PL_REV);
ret = get_flash_params(adapter);
if (ret < 0) {
dev_err(adapter->pdev_dev, "error %d identifying flash\n", ret);
return ret;
}
ret = get_vpd_params(adapter, &adapter->params.vpd); ret = get_vpd_params(adapter, &adapter->params.vpd);
if (ret < 0) if (ret < 0)
return ret; return ret;
......
...@@ -57,8 +57,6 @@ enum { ...@@ -57,8 +57,6 @@ enum {
enum { enum {
SF_PAGE_SIZE = 256, /* serial flash page size */ SF_PAGE_SIZE = 256, /* serial flash page size */
SF_SEC_SIZE = 64 * 1024, /* serial flash sector size */
SF_SIZE = SF_SEC_SIZE * 16, /* serial flash size */
}; };
enum { RSP_TYPE_FLBUF, RSP_TYPE_CPL, RSP_TYPE_INTR }; /* response entry types */ enum { RSP_TYPE_FLBUF, RSP_TYPE_CPL, RSP_TYPE_INTR }; /* response entry types */
......
...@@ -326,6 +326,9 @@ ...@@ -326,6 +326,9 @@
#define EDC_1_BASE_ADDR 0x7980 #define EDC_1_BASE_ADDR 0x7980
#define CIM_BOOT_CFG 0x7b00
#define BOOTADDR_MASK 0xffffff00U
#define CIM_PF_MAILBOX_DATA 0x240 #define CIM_PF_MAILBOX_DATA 0x240
#define CIM_PF_MAILBOX_CTRL 0x280 #define CIM_PF_MAILBOX_CTRL 0x280
#define MBMSGVALID 0x00000008U #define MBMSGVALID 0x00000008U
......
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