qlcnic: 83xx adpater flash interface routines
83xx adapter flash memory map, data structures and interface routines Signed-off-by: Himanshu Madhani <himanshu.madhani@qlogic.com> Signed-off-by: Sony Chacko <sony.chacko@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
319ecf121e
commit
d865ebb479
3 changed files with 443 additions and 0 deletions
|
@ -204,6 +204,7 @@ struct uni_data_desc{
|
||||||
|
|
||||||
/* Flash Defines and Structures */
|
/* Flash Defines and Structures */
|
||||||
#define QLCNIC_FLT_LOCATION 0x3F1000
|
#define QLCNIC_FLT_LOCATION 0x3F1000
|
||||||
|
#define QLCNIC_FDT_LOCATION 0x3F0000
|
||||||
#define QLCNIC_B0_FW_IMAGE_REGION 0x74
|
#define QLCNIC_B0_FW_IMAGE_REGION 0x74
|
||||||
#define QLCNIC_C0_FW_IMAGE_REGION 0x97
|
#define QLCNIC_C0_FW_IMAGE_REGION 0x97
|
||||||
#define QLCNIC_BOOTLD_REGION 0X72
|
#define QLCNIC_BOOTLD_REGION 0X72
|
||||||
|
@ -224,6 +225,36 @@ struct qlcnic_flt_entry {
|
||||||
u32 end_addr;
|
u32 end_addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Flash Descriptor Table */
|
||||||
|
struct qlcnic_fdt {
|
||||||
|
u32 valid;
|
||||||
|
u16 ver;
|
||||||
|
u16 len;
|
||||||
|
u16 cksum;
|
||||||
|
u16 unused;
|
||||||
|
u8 model[16];
|
||||||
|
u16 mfg_id;
|
||||||
|
u16 id;
|
||||||
|
u8 flag;
|
||||||
|
u8 erase_cmd;
|
||||||
|
u8 alt_erase_cmd;
|
||||||
|
u8 write_enable_cmd;
|
||||||
|
u8 write_enable_bits;
|
||||||
|
u8 write_statusreg_cmd;
|
||||||
|
u8 unprotected_sec_cmd;
|
||||||
|
u8 read_manuf_cmd;
|
||||||
|
u32 block_size;
|
||||||
|
u32 alt_block_size;
|
||||||
|
u32 flash_size;
|
||||||
|
u32 write_enable_data;
|
||||||
|
u8 readid_addr_len;
|
||||||
|
u8 write_disable_bits;
|
||||||
|
u8 read_dev_id_len;
|
||||||
|
u8 chip_erase_cmd;
|
||||||
|
u16 read_timeo;
|
||||||
|
u8 protected_sec_cmd;
|
||||||
|
u8 resvd[65];
|
||||||
|
};
|
||||||
/* Magic number to let user know flash is programmed */
|
/* Magic number to let user know flash is programmed */
|
||||||
#define QLCNIC_BDINFO_MAGIC 0x12345678
|
#define QLCNIC_BDINFO_MAGIC 0x12345678
|
||||||
|
|
||||||
|
@ -404,6 +435,7 @@ struct qlcnic_hardware_context {
|
||||||
struct qlcnic_hardware_ops *hw_ops;
|
struct qlcnic_hardware_ops *hw_ops;
|
||||||
struct qlcnic_nic_intr_coalesce coal;
|
struct qlcnic_nic_intr_coalesce coal;
|
||||||
struct qlcnic_fw_dump fw_dump;
|
struct qlcnic_fw_dump fw_dump;
|
||||||
|
struct qlcnic_fdt fdt;
|
||||||
struct qlcnic_intrpt_config *intr_tbl;
|
struct qlcnic_intrpt_config *intr_tbl;
|
||||||
u32 *reg_tbl;
|
u32 *reg_tbl;
|
||||||
u32 *ext_reg_tbl;
|
u32 *ext_reg_tbl;
|
||||||
|
@ -972,6 +1004,7 @@ struct qlcnic_adapter {
|
||||||
u64 dev_rst_time;
|
u64 dev_rst_time;
|
||||||
u8 mac_learn;
|
u8 mac_learn;
|
||||||
unsigned long vlans[BITS_TO_LONGS(VLAN_N_VID)];
|
unsigned long vlans[BITS_TO_LONGS(VLAN_N_VID)];
|
||||||
|
u8 flash_mfg_id;
|
||||||
struct qlcnic_npar_info *npars;
|
struct qlcnic_npar_info *npars;
|
||||||
struct qlcnic_eswitch *eswitch;
|
struct qlcnic_eswitch *eswitch;
|
||||||
struct qlcnic_nic_template *nic_ops;
|
struct qlcnic_nic_template *nic_ops;
|
||||||
|
|
|
@ -1782,3 +1782,363 @@ out:
|
||||||
qlcnic_free_mbx_args(&cmd);
|
qlcnic_free_mbx_args(&cmd);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int qlcnic_83xx_lock_flash(struct qlcnic_adapter *adapter)
|
||||||
|
{
|
||||||
|
int id, timeout = 0;
|
||||||
|
u32 status = 0;
|
||||||
|
|
||||||
|
while (status == 0) {
|
||||||
|
status = QLC_SHARED_REG_RD32(adapter, QLCNIC_FLASH_LOCK);
|
||||||
|
if (status)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (++timeout >= QLC_83XX_FLASH_LOCK_TIMEOUT) {
|
||||||
|
id = QLC_SHARED_REG_RD32(adapter,
|
||||||
|
QLCNIC_FLASH_LOCK_OWNER);
|
||||||
|
dev_err(&adapter->pdev->dev,
|
||||||
|
"%s: failed, lock held by %d\n", __func__, id);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
usleep_range(1000, 2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
QLC_SHARED_REG_WR32(adapter, QLCNIC_FLASH_LOCK_OWNER, adapter->portnum);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void qlcnic_83xx_unlock_flash(struct qlcnic_adapter *adapter)
|
||||||
|
{
|
||||||
|
QLC_SHARED_REG_RD32(adapter, QLCNIC_FLASH_UNLOCK);
|
||||||
|
QLC_SHARED_REG_WR32(adapter, QLCNIC_FLASH_LOCK_OWNER, 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int qlcnic_83xx_lockless_flash_read32(struct qlcnic_adapter *adapter,
|
||||||
|
u32 flash_addr, u8 *p_data,
|
||||||
|
int count)
|
||||||
|
{
|
||||||
|
int i, ret;
|
||||||
|
u32 word, range, flash_offset, addr = flash_addr;
|
||||||
|
ulong indirect_add, direct_window;
|
||||||
|
|
||||||
|
flash_offset = addr & (QLCNIC_FLASH_SECTOR_SIZE - 1);
|
||||||
|
if (addr & 0x3) {
|
||||||
|
dev_err(&adapter->pdev->dev, "Illegal addr = 0x%x\n", addr);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_DIRECT_WINDOW,
|
||||||
|
(addr));
|
||||||
|
|
||||||
|
range = flash_offset + (count * sizeof(u32));
|
||||||
|
/* Check if data is spread across multiple sectors */
|
||||||
|
if (range > (QLCNIC_FLASH_SECTOR_SIZE - 1)) {
|
||||||
|
|
||||||
|
/* Multi sector read */
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
indirect_add = QLC_83XX_FLASH_DIRECT_DATA(addr);
|
||||||
|
ret = qlcnic_83xx_rd_reg_indirect(adapter,
|
||||||
|
indirect_add);
|
||||||
|
if (ret == -EIO)
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
word = ret;
|
||||||
|
*(u32 *)p_data = word;
|
||||||
|
p_data = p_data + 4;
|
||||||
|
addr = addr + 4;
|
||||||
|
flash_offset = flash_offset + 4;
|
||||||
|
|
||||||
|
if (flash_offset > (QLCNIC_FLASH_SECTOR_SIZE - 1)) {
|
||||||
|
direct_window = QLC_83XX_FLASH_DIRECT_WINDOW;
|
||||||
|
/* This write is needed once for each sector */
|
||||||
|
qlcnic_83xx_wrt_reg_indirect(adapter,
|
||||||
|
direct_window,
|
||||||
|
(addr));
|
||||||
|
flash_offset = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Single sector read */
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
indirect_add = QLC_83XX_FLASH_DIRECT_DATA(addr);
|
||||||
|
ret = qlcnic_83xx_rd_reg_indirect(adapter,
|
||||||
|
indirect_add);
|
||||||
|
if (ret == -EIO)
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
word = ret;
|
||||||
|
*(u32 *)p_data = word;
|
||||||
|
p_data = p_data + 4;
|
||||||
|
addr = addr + 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int qlcnic_83xx_poll_flash_status_reg(struct qlcnic_adapter *adapter)
|
||||||
|
{
|
||||||
|
u32 status;
|
||||||
|
int retries = QLC_83XX_FLASH_READ_RETRY_COUNT;
|
||||||
|
|
||||||
|
do {
|
||||||
|
status = qlcnic_83xx_rd_reg_indirect(adapter,
|
||||||
|
QLC_83XX_FLASH_STATUS);
|
||||||
|
if ((status & QLC_83XX_FLASH_STATUS_READY) ==
|
||||||
|
QLC_83XX_FLASH_STATUS_READY)
|
||||||
|
break;
|
||||||
|
|
||||||
|
msleep(QLC_83XX_FLASH_STATUS_REG_POLL_DELAY);
|
||||||
|
} while (--retries);
|
||||||
|
|
||||||
|
if (!retries)
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int qlcnic_83xx_enable_flash_write_op(struct qlcnic_adapter *adapter)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
u32 cmd;
|
||||||
|
cmd = adapter->ahw->fdt.write_statusreg_cmd;
|
||||||
|
qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
|
||||||
|
(QLC_83XX_FLASH_FDT_WRITE_DEF_SIG | cmd));
|
||||||
|
qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA,
|
||||||
|
adapter->ahw->fdt.write_enable_bits);
|
||||||
|
qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
|
||||||
|
QLC_83XX_FLASH_SECOND_ERASE_MS_VAL);
|
||||||
|
ret = qlcnic_83xx_poll_flash_status_reg(adapter);
|
||||||
|
if (ret)
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int qlcnic_83xx_disable_flash_write_op(struct qlcnic_adapter *adapter)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
|
||||||
|
(QLC_83XX_FLASH_FDT_WRITE_DEF_SIG |
|
||||||
|
adapter->ahw->fdt.write_statusreg_cmd));
|
||||||
|
qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA,
|
||||||
|
adapter->ahw->fdt.write_disable_bits);
|
||||||
|
qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
|
||||||
|
QLC_83XX_FLASH_SECOND_ERASE_MS_VAL);
|
||||||
|
ret = qlcnic_83xx_poll_flash_status_reg(adapter);
|
||||||
|
if (ret)
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int qlcnic_83xx_read_flash_mfg_id(struct qlcnic_adapter *adapter)
|
||||||
|
{
|
||||||
|
int ret, mfg_id;
|
||||||
|
|
||||||
|
if (qlcnic_83xx_lock_flash(adapter))
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
|
||||||
|
QLC_83XX_FLASH_FDT_READ_MFG_ID_VAL);
|
||||||
|
qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
|
||||||
|
QLC_83XX_FLASH_READ_CTRL);
|
||||||
|
ret = qlcnic_83xx_poll_flash_status_reg(adapter);
|
||||||
|
if (ret) {
|
||||||
|
qlcnic_83xx_unlock_flash(adapter);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
mfg_id = qlcnic_83xx_rd_reg_indirect(adapter, QLC_83XX_FLASH_RDDATA);
|
||||||
|
if (mfg_id == -EIO)
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
adapter->flash_mfg_id = (mfg_id & 0xFF);
|
||||||
|
qlcnic_83xx_unlock_flash(adapter);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int qlcnic_83xx_read_flash_descriptor_table(struct qlcnic_adapter *adapter)
|
||||||
|
{
|
||||||
|
int count, fdt_size, ret = 0;
|
||||||
|
|
||||||
|
fdt_size = sizeof(struct qlcnic_fdt);
|
||||||
|
count = fdt_size / sizeof(u32);
|
||||||
|
|
||||||
|
if (qlcnic_83xx_lock_flash(adapter))
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
memset(&adapter->ahw->fdt, 0, fdt_size);
|
||||||
|
ret = qlcnic_83xx_lockless_flash_read32(adapter, QLCNIC_FDT_LOCATION,
|
||||||
|
(u8 *)&adapter->ahw->fdt,
|
||||||
|
count);
|
||||||
|
|
||||||
|
qlcnic_83xx_unlock_flash(adapter);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int qlcnic_83xx_erase_flash_sector(struct qlcnic_adapter *adapter,
|
||||||
|
u32 sector_start_addr)
|
||||||
|
{
|
||||||
|
u32 reversed_addr, addr1, addr2, cmd;
|
||||||
|
int ret = -EIO;
|
||||||
|
|
||||||
|
if (qlcnic_83xx_lock_flash(adapter) != 0)
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id) {
|
||||||
|
ret = qlcnic_83xx_enable_flash_write_op(adapter);
|
||||||
|
if (ret) {
|
||||||
|
qlcnic_83xx_unlock_flash(adapter);
|
||||||
|
dev_err(&adapter->pdev->dev,
|
||||||
|
"%s failed at %d\n",
|
||||||
|
__func__, __LINE__);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = qlcnic_83xx_poll_flash_status_reg(adapter);
|
||||||
|
if (ret) {
|
||||||
|
qlcnic_83xx_unlock_flash(adapter);
|
||||||
|
dev_err(&adapter->pdev->dev,
|
||||||
|
"%s: failed at %d\n", __func__, __LINE__);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr1 = (sector_start_addr & 0xFF) << 16;
|
||||||
|
addr2 = (sector_start_addr & 0xFF0000) >> 16;
|
||||||
|
reversed_addr = addr1 | addr2;
|
||||||
|
|
||||||
|
qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA,
|
||||||
|
reversed_addr);
|
||||||
|
cmd = QLC_83XX_FLASH_FDT_ERASE_DEF_SIG | adapter->ahw->fdt.erase_cmd;
|
||||||
|
if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id)
|
||||||
|
qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR, cmd);
|
||||||
|
else
|
||||||
|
qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
|
||||||
|
QLC_83XX_FLASH_OEM_ERASE_SIG);
|
||||||
|
qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
|
||||||
|
QLC_83XX_FLASH_LAST_ERASE_MS_VAL);
|
||||||
|
|
||||||
|
ret = qlcnic_83xx_poll_flash_status_reg(adapter);
|
||||||
|
if (ret) {
|
||||||
|
qlcnic_83xx_unlock_flash(adapter);
|
||||||
|
dev_err(&adapter->pdev->dev,
|
||||||
|
"%s: failed at %d\n", __func__, __LINE__);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id) {
|
||||||
|
ret = qlcnic_83xx_disable_flash_write_op(adapter);
|
||||||
|
if (ret) {
|
||||||
|
qlcnic_83xx_unlock_flash(adapter);
|
||||||
|
dev_err(&adapter->pdev->dev,
|
||||||
|
"%s: failed at %d\n", __func__, __LINE__);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qlcnic_83xx_unlock_flash(adapter);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int qlcnic_83xx_flash_write32(struct qlcnic_adapter *adapter, u32 addr,
|
||||||
|
u32 *p_data)
|
||||||
|
{
|
||||||
|
int ret = -EIO;
|
||||||
|
u32 addr1 = 0x00800000 | (addr >> 2);
|
||||||
|
|
||||||
|
qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR, addr1);
|
||||||
|
qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA, *p_data);
|
||||||
|
qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
|
||||||
|
QLC_83XX_FLASH_LAST_ERASE_MS_VAL);
|
||||||
|
ret = qlcnic_83xx_poll_flash_status_reg(adapter);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(&adapter->pdev->dev,
|
||||||
|
"%s: failed at %d\n", __func__, __LINE__);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int qlcnic_83xx_flash_bulk_write(struct qlcnic_adapter *adapter, u32 addr,
|
||||||
|
u32 *p_data, int count)
|
||||||
|
{
|
||||||
|
u32 temp;
|
||||||
|
int ret = -EIO;
|
||||||
|
|
||||||
|
if ((count < QLC_83XX_FLASH_BULK_WRITE_MIN) ||
|
||||||
|
(count > QLC_83XX_FLASH_BULK_WRITE_MAX)) {
|
||||||
|
dev_err(&adapter->pdev->dev,
|
||||||
|
"%s: Invalid word count\n", __func__);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
temp = qlcnic_83xx_rd_reg_indirect(adapter,
|
||||||
|
QLC_83XX_FLASH_SPI_CONTROL);
|
||||||
|
qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_SPI_CONTROL,
|
||||||
|
(temp | QLC_83XX_FLASH_SPI_CTRL));
|
||||||
|
qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
|
||||||
|
QLC_83XX_FLASH_ADDR_TEMP_VAL);
|
||||||
|
|
||||||
|
/* First DWORD write */
|
||||||
|
qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA, *p_data++);
|
||||||
|
qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
|
||||||
|
QLC_83XX_FLASH_FIRST_MS_PATTERN);
|
||||||
|
ret = qlcnic_83xx_poll_flash_status_reg(adapter);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(&adapter->pdev->dev,
|
||||||
|
"%s: failed at %d\n", __func__, __LINE__);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
count--;
|
||||||
|
qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
|
||||||
|
QLC_83XX_FLASH_ADDR_SECOND_TEMP_VAL);
|
||||||
|
/* Second to N-1 DWORD writes */
|
||||||
|
while (count != 1) {
|
||||||
|
qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA,
|
||||||
|
*p_data++);
|
||||||
|
qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
|
||||||
|
QLC_83XX_FLASH_SECOND_MS_PATTERN);
|
||||||
|
ret = qlcnic_83xx_poll_flash_status_reg(adapter);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(&adapter->pdev->dev,
|
||||||
|
"%s: failed at %d\n", __func__, __LINE__);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
count--;
|
||||||
|
}
|
||||||
|
|
||||||
|
qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
|
||||||
|
QLC_83XX_FLASH_ADDR_TEMP_VAL |
|
||||||
|
(addr >> 2));
|
||||||
|
/* Last DWORD write */
|
||||||
|
qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA, *p_data++);
|
||||||
|
qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
|
||||||
|
QLC_83XX_FLASH_LAST_MS_PATTERN);
|
||||||
|
ret = qlcnic_83xx_poll_flash_status_reg(adapter);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(&adapter->pdev->dev,
|
||||||
|
"%s: failed at %d\n", __func__, __LINE__);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = qlcnic_83xx_rd_reg_indirect(adapter, QLC_83XX_FLASH_SPI_STATUS);
|
||||||
|
if ((ret & QLC_83XX_FLASH_SPI_CTRL) == QLC_83XX_FLASH_SPI_CTRL) {
|
||||||
|
dev_err(&adapter->pdev->dev, "%s: failed at %d\n",
|
||||||
|
__func__, __LINE__);
|
||||||
|
/* Operation failed, clear error bit */
|
||||||
|
temp = qlcnic_83xx_rd_reg_indirect(adapter,
|
||||||
|
QLC_83XX_FLASH_SPI_CONTROL);
|
||||||
|
qlcnic_83xx_wrt_reg_indirect(adapter,
|
||||||
|
QLC_83XX_FLASH_SPI_CONTROL,
|
||||||
|
(temp | QLC_83XX_FLASH_SPI_CTRL));
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -134,6 +134,46 @@ struct qlcnic_macvlan_mbx {
|
||||||
#define QLC_83XX_DEFAULT_MODE 0x0
|
#define QLC_83XX_DEFAULT_MODE 0x0
|
||||||
#define QLCNIC_BRDTYPE_83XX_10G 0x0083
|
#define QLCNIC_BRDTYPE_83XX_10G 0x0083
|
||||||
|
|
||||||
|
#define QLC_83XX_FLASH_SPI_STATUS 0x2808E010
|
||||||
|
#define QLC_83XX_FLASH_SPI_CONTROL 0x2808E014
|
||||||
|
#define QLC_83XX_FLASH_STATUS 0x42100004
|
||||||
|
#define QLC_83XX_FLASH_CONTROL 0x42110004
|
||||||
|
#define QLC_83XX_FLASH_ADDR 0x42110008
|
||||||
|
#define QLC_83XX_FLASH_WRDATA 0x4211000C
|
||||||
|
#define QLC_83XX_FLASH_RDDATA 0x42110018
|
||||||
|
#define QLC_83XX_FLASH_DIRECT_WINDOW 0x42110030
|
||||||
|
#define QLC_83XX_FLASH_DIRECT_DATA(DATA) (0x42150000 | (0x0000FFFF&DATA))
|
||||||
|
#define QLC_83XX_FLASH_SECTOR_ERASE_CMD 0xdeadbeef
|
||||||
|
#define QLC_83XX_FLASH_WRITE_CMD 0xdacdacda
|
||||||
|
#define QLC_83XX_FLASH_BULK_WRITE_CMD 0xcadcadca
|
||||||
|
#define QLC_83XX_FLASH_READ_RETRY_COUNT 5000
|
||||||
|
#define QLC_83XX_FLASH_STATUS_READY 0x6
|
||||||
|
#define QLC_83XX_FLASH_BULK_WRITE_MIN 2
|
||||||
|
#define QLC_83XX_FLASH_BULK_WRITE_MAX 64
|
||||||
|
#define QLC_83XX_FLASH_STATUS_REG_POLL_DELAY 1
|
||||||
|
#define QLC_83XX_ERASE_MODE 1
|
||||||
|
#define QLC_83XX_WRITE_MODE 2
|
||||||
|
#define QLC_83XX_BULK_WRITE_MODE 3
|
||||||
|
#define QLC_83XX_FLASH_FDT_WRITE_DEF_SIG 0xFD0100
|
||||||
|
#define QLC_83XX_FLASH_FDT_ERASE_DEF_SIG 0xFD0300
|
||||||
|
#define QLC_83XX_FLASH_FDT_READ_MFG_ID_VAL 0xFD009F
|
||||||
|
#define QLC_83XX_FLASH_OEM_ERASE_SIG 0xFD03D8
|
||||||
|
#define QLC_83XX_FLASH_OEM_WRITE_SIG 0xFD0101
|
||||||
|
#define QLC_83XX_FLASH_OEM_READ_SIG 0xFD0005
|
||||||
|
#define QLC_83XX_FLASH_ADDR_TEMP_VAL 0x00800000
|
||||||
|
#define QLC_83XX_FLASH_ADDR_SECOND_TEMP_VAL 0x00800001
|
||||||
|
#define QLC_83XX_FLASH_WRDATA_DEF 0x0
|
||||||
|
#define QLC_83XX_FLASH_READ_CTRL 0x3F
|
||||||
|
#define QLC_83XX_FLASH_SPI_CTRL 0x4
|
||||||
|
#define QLC_83XX_FLASH_FIRST_ERASE_MS_VAL 0x2
|
||||||
|
#define QLC_83XX_FLASH_SECOND_ERASE_MS_VAL 0x5
|
||||||
|
#define QLC_83XX_FLASH_LAST_ERASE_MS_VAL 0x3D
|
||||||
|
#define QLC_83XX_FLASH_FIRST_MS_PATTERN 0x43
|
||||||
|
#define QLC_83XX_FLASH_SECOND_MS_PATTERN 0x7F
|
||||||
|
#define QLC_83XX_FLASH_LAST_MS_PATTERN 0x7D
|
||||||
|
#define QLC_83xx_FLASH_MAX_WAIT_USEC 100
|
||||||
|
#define QLC_83XX_FLASH_LOCK_TIMEOUT 10000
|
||||||
|
|
||||||
/* Additional registers in 83xx */
|
/* Additional registers in 83xx */
|
||||||
enum qlc_83xx_ext_regs {
|
enum qlc_83xx_ext_regs {
|
||||||
QLCNIC_GLOBAL_RESET = 0,
|
QLCNIC_GLOBAL_RESET = 0,
|
||||||
|
@ -253,4 +293,14 @@ void qlcnic_83xx_free_mbx_intr(struct qlcnic_adapter *);
|
||||||
void qlcnic_83xx_register_map(struct qlcnic_hardware_context *);
|
void qlcnic_83xx_register_map(struct qlcnic_hardware_context *);
|
||||||
void qlcnic_83xx_idc_aen_work(struct work_struct *);
|
void qlcnic_83xx_idc_aen_work(struct work_struct *);
|
||||||
void qlcnic_83xx_config_ipaddr(struct qlcnic_adapter *, __be32, int);
|
void qlcnic_83xx_config_ipaddr(struct qlcnic_adapter *, __be32, int);
|
||||||
|
|
||||||
|
int qlcnic_83xx_erase_flash_sector(struct qlcnic_adapter *, u32);
|
||||||
|
int qlcnic_83xx_flash_bulk_write(struct qlcnic_adapter *, u32, u32 *, int);
|
||||||
|
int qlcnic_83xx_flash_write32(struct qlcnic_adapter *, u32, u32 *);
|
||||||
|
int qlcnic_83xx_lock_flash(struct qlcnic_adapter *);
|
||||||
|
void qlcnic_83xx_unlock_flash(struct qlcnic_adapter *);
|
||||||
|
int qlcnic_83xx_save_flash_status(struct qlcnic_adapter *);
|
||||||
|
int qlcnic_83xx_restore_flash_status(struct qlcnic_adapter *, int);
|
||||||
|
int qlcnic_83xx_read_flash_mfg_id(struct qlcnic_adapter *);
|
||||||
|
int qlcnic_83xx_read_flash_descriptor_table(struct qlcnic_adapter *);
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue