#include "lm5706.h"
lm_status_t
lm_set_mac_addr(
lm_device_t *pdev,
u32_t addr_idx,
u8_t *mac_addr)
{
u32_t val;
if(addr_idx >= 16)
{
DbgBreakMsg("Invalid mac address index.\n");
return LM_STATUS_FAILURE;
}
val = (mac_addr[0]<<8) | mac_addr[1];
REG_WR(pdev, emac.emac_mac_match[addr_idx*2], val);
val = (mac_addr[2]<<24) | (mac_addr[3]<<16) |
(mac_addr[4]<<8) | mac_addr[5];
REG_WR(pdev, emac.emac_mac_match[addr_idx*2+1], val);
return LM_STATUS_SUCCESS;
}
void
lm_reg_rd_ind(
lm_device_t *pdev,
u32_t offset,
u32_t *ret)
{
mm_acquire_ind_reg_lock(pdev);
REG_WR(pdev, pci_config.pcicfg_reg_window_address, offset);
REG_RD(pdev, pci_config.pcicfg_reg_window, ret);
mm_release_ind_reg_lock(pdev);
}
void
lm_reg_wr_ind(
lm_device_t *pdev,
u32_t offset,
u32_t val)
{
DbgBreakIf(offset & 0x3);
mm_acquire_ind_reg_lock(pdev);
REG_WR(pdev, pci_config.pcicfg_reg_window_address, offset);
REG_WR(pdev, pci_config.pcicfg_reg_window, val);
mm_release_ind_reg_lock(pdev);
}
void
lm_ctx_wr(
lm_device_t *pdev,
u32_t cid_addr,
u32_t offset,
u32_t val)
{
u32_t retry_cnt;
u32_t idx;
DbgBreakIf(cid_addr > MAX_CID_ADDR || offset & 0x3 || cid_addr & CTX_MASK);
offset += cid_addr;
if(CHIP_NUM(pdev) == CHIP_NUM_5709)
{
if (CHIP_REV(pdev) == CHIP_REV_IKOS)
{
retry_cnt = 2000;
}
else
{
retry_cnt = 250;
}
REG_WR(pdev, context.ctx_ctx_data, val);
REG_WR(pdev, context.ctx_ctx_ctrl, offset | CTX_CTX_CTRL_WRITE_REQ);
for(idx=0; idx < retry_cnt; idx++)
{
REG_RD(pdev, context.ctx_ctx_ctrl, &val);
if((val & CTX_CTX_CTRL_WRITE_REQ) == 0)
{
break;
}
mm_wait(pdev, 10);
}
DbgBreakIf(idx == retry_cnt);
}
else
{
REG_WR(pdev, context.ctx_data_adr, offset);
REG_WR(pdev, context.ctx_data, val);
}
}
u32_t
lm_ctx_rd(
lm_device_t *pdev,
u32_t cid_addr,
u32_t offset)
{
u32_t retry_cnt;
u32_t val;
u32_t idx;
DbgBreakIf(cid_addr > MAX_CID_ADDR || offset & 0x3 || cid_addr & CTX_MASK);
offset += cid_addr;
if(CHIP_NUM(pdev) == CHIP_NUM_5709)
{
if(CHIP_REV(pdev) == CHIP_REV_IKOS)
{
retry_cnt = 1000;
}
else
{
retry_cnt = 25;
}
REG_WR(pdev, context.ctx_ctx_ctrl, offset | CTX_CTX_CTRL_READ_REQ);
for(idx = 0; idx < retry_cnt; idx++)
{
REG_RD(pdev, context.ctx_ctx_ctrl, &val);
if((val & CTX_CTX_CTRL_READ_REQ) == 0)
{
break;
}
mm_wait(pdev, 5);
}
DbgBreakIf(idx == retry_cnt);
REG_RD(pdev, context.ctx_ctx_data, &val);
}
else
{
REG_WR(pdev, context.ctx_data_adr, offset);
REG_RD(pdev, context.ctx_data, &val);
}
return val;
}
void
lm_disable_int(
lm_device_t *pdev)
{
u32_t sb_idx;
u32_t val;
switch(CHIP_NUM(pdev))
{
case CHIP_NUM_5706:
case CHIP_NUM_5708:
REG_RD(pdev, pci_config.pcicfg_int_ack_cmd, &val);
val |= PCICFG_INT_ACK_CMD_MASK_INT;
REG_WR(pdev, pci_config.pcicfg_int_ack_cmd, val);
break;
case CHIP_NUM_5709:
for(sb_idx = 0; sb_idx < 9; sb_idx++)
{
val = PCICFG_INT_ACK_CMD_MASK_INT | (sb_idx << 24);
REG_WR(pdev, pci_config.pcicfg_int_ack_cmd, val);
}
break;
default:
DbgBreakMsg("Unsupported chip.\n");
break;
}
}
void
lm_enable_int(
lm_device_t *pdev)
{
u32_t val;
switch(CHIP_NUM(pdev))
{
case CHIP_NUM_5706:
case CHIP_NUM_5708:
REG_RD(pdev, pci_config.pcicfg_int_ack_cmd, &val);
val &= ~PCICFG_INT_ACK_CMD_MASK_INT;
REG_WR(pdev, pci_config.pcicfg_int_ack_cmd, val);
break;
case CHIP_NUM_5709:
REG_RD(pdev, hc.hc_config, &val);
val |= HC_CONFIG_UNMASK_ALL;
REG_WR(pdev, hc.hc_config, val);
break;
default:
DbgBreakMsg("Unsupported chip.\n");
break;
}
}
void
lm_reg_rd_blk(
lm_device_t *pdev,
u32_t reg_offset,
u32_t *buf_ptr,
u32_t u32t_cnt)
{
u32_t grc_win_offset;
u32_t grc_win_base;
DbgBreakIf(reg_offset & 0x3);
grc_win_offset = reg_offset & (GRC_WINDOW_SIZE - 1);
grc_win_base = reg_offset & ~(GRC_WINDOW_SIZE - 1);
REG_WR(pdev, pci.pci_grc_window_addr, grc_win_base);
while(u32t_cnt)
{
if(grc_win_offset >= GRC_WINDOW_SIZE)
{
grc_win_offset = 0;
grc_win_base += GRC_WINDOW_SIZE;
REG_WR(pdev, pci.pci_grc_window_addr, grc_win_base);
}
REG_RD_OFFSET(pdev, GRC_WINDOW_BASE + grc_win_offset, buf_ptr);
buf_ptr++;
u32t_cnt--;
grc_win_offset += 4;
}
REG_WR(pdev, pci.pci_grc_window_addr, pdev->hw_info.shmem_base & ~0x7fff);
}
void
lm_reg_rd_blk_ind(
lm_device_t *pdev,
u32_t reg_offset,
u32_t *buf_ptr,
u32_t u32t_cnt)
{
DbgBreakIf(reg_offset & 0x3);
mm_acquire_ind_reg_lock(pdev);
while(u32t_cnt)
{
REG_WR(pdev, pci_config.pcicfg_reg_window_address, reg_offset);
REG_RD(pdev, pci_config.pcicfg_reg_window, buf_ptr);
buf_ptr++;
u32t_cnt--;
reg_offset += 4;
}
mm_release_ind_reg_lock(pdev);
}
void
lm_reg_wr_blk(
lm_device_t *pdev,
u32_t reg_offset,
u32_t *data_ptr,
u32_t u32t_cnt)
{
u32_t grc_win_offset;
u32_t grc_win_base;
u32_t grc_win_size;
DbgBreakIf(reg_offset & 0x3);
if (CHIP_NUM(pdev) == CHIP_NUM_5709)
{
grc_win_size = GRC_WINDOW_SIZE / 4;
}
else
{
grc_win_size = GRC_WINDOW_SIZE;
}
grc_win_offset = reg_offset & (grc_win_size - 1);
grc_win_base = reg_offset & ~(grc_win_size - 1);
REG_WR(pdev, pci.pci_grc_window_addr, grc_win_base);
while(u32t_cnt)
{
if(grc_win_offset >= grc_win_size)
{
grc_win_offset = 0;
grc_win_base += grc_win_size;
REG_WR(pdev, pci.pci_grc_window_addr, grc_win_base);
}
REG_WR_OFFSET(pdev, GRC_WINDOW_BASE + grc_win_offset, *data_ptr);
data_ptr++;
u32t_cnt--;
grc_win_offset += 4;
}
REG_WR(pdev, pci.pci_grc_window_addr, pdev->hw_info.shmem_base & ~0x7fff);
}
void
lm_reg_wr_blk_ind(
lm_device_t *pdev,
u32_t reg_offset,
u32_t *data_ptr,
u32_t u32t_cnt)
{
DbgBreakIf(reg_offset & 0x3);
mm_acquire_ind_reg_lock(pdev);
while(u32t_cnt)
{
REG_WR(pdev, pci_config.pcicfg_reg_window_address, reg_offset);
REG_WR(pdev, pci_config.pcicfg_reg_window, *data_ptr);
data_ptr++;
u32t_cnt--;
reg_offset += 4;
}
mm_release_ind_reg_lock(pdev);
}
lm_status_t
lm_submit_fw_cmd(
lm_device_t *pdev,
u32_t drv_msg)
{
u32_t val;
if(pdev->vars.fw_timed_out)
{
DbgMessage(pdev, WARN, "fw timed out.\n");
return LM_STATUS_FAILURE;
}
DbgBreakIf(drv_msg & 0xffff);
REG_RD_IND(
pdev,
pdev->hw_info.shmem_base + OFFSETOF(shmem_region_t, drv_fw_mb.fw_mb),
&val);
if((val & FW_MSG_ACK) != (pdev->vars.fw_wr_seq & DRV_MSG_SEQ))
{
DbgMessage(pdev, WARN, "command pending.\n");
return LM_STATUS_FAILURE;
}
pdev->vars.fw_wr_seq++;
drv_msg |= (pdev->vars.fw_wr_seq & DRV_MSG_SEQ);
REG_WR_IND(
pdev,
pdev->hw_info.shmem_base +
OFFSETOF(shmem_region_t, drv_fw_mb.drv_mb),
drv_msg);
return LM_STATUS_SUCCESS;
}
lm_status_t
lm_last_fw_cmd_status(
lm_device_t *pdev)
{
u32_t val;
if(pdev->vars.fw_timed_out)
{
DbgMessage(pdev, WARN, "fw timed out.\n");
return LM_STATUS_TIMEOUT;
}
REG_RD_IND(
pdev,
pdev->hw_info.shmem_base +
OFFSETOF(shmem_region_t, drv_fw_mb.fw_mb),
&val);
if((val & FW_MSG_ACK) != (pdev->vars.fw_wr_seq & DRV_MSG_SEQ))
{
return LM_STATUS_BUSY;
}
if((val & FW_MSG_STATUS_MASK) != FW_MSG_STATUS_OK)
{
return LM_STATUS_FAILURE;
}
return LM_STATUS_SUCCESS;
}
u32_t
lm_mb_get_cid_addr(
lm_device_t *pdev,
u32_t cid)
{
u32_t mq_offset;
DbgBreakIf(pdev->params.bin_mq_mode && CHIP_NUM(pdev) != CHIP_NUM_5709);
if(cid < 256 || pdev->params.bin_mq_mode == FALSE)
{
mq_offset = 0x10000 + (cid << MB_KERNEL_CTX_SHIFT);
}
else
{
DbgBreakIf(cid < pdev->hw_info.first_l4_l5_bin);
mq_offset = 0x10000 +
((((cid - pdev->hw_info.first_l4_l5_bin) /
pdev->hw_info.bin_size) + 256) << MB_KERNEL_CTX_SHIFT);
}
DbgBreakIf(mq_offset > pdev->hw_info.bar_size);
return mq_offset;
}
u32_t
lm_mb_get_bypass_addr(
lm_device_t *pdev,
u32_t cid)
{
u32_t mq_offset;
DbgBreakIf(pdev->params.bin_mq_mode && CHIP_NUM(pdev) != CHIP_NUM_5709);
if(cid < 256 || pdev->params.bin_mq_mode == FALSE)
{
mq_offset = 0x10000 +
MB_KERNEL_CTX_SIZE * MAX_CID_CNT +
cid * LM_PAGE_SIZE;
}
else
{
DbgBreakIf(cid < pdev->hw_info.first_l4_l5_bin);
mq_offset = 0x10000 +
MB_KERNEL_CTX_SIZE * MAX_CID_CNT +
(((cid - pdev->hw_info.first_l4_l5_bin) /
pdev->hw_info.bin_size) + 256) * LM_PAGE_SIZE;
}
DbgBreakIf(mq_offset > pdev->hw_info.bar_size);
return mq_offset;
}