#include "csio_hw.h"
#include "csio_init.h"
static int
csio_t5_set_mem_win(struct csio_hw *hw, uint32_t win)
{
u32 mem_win_base;
mem_win_base = MEMWIN_BASE;
csio_wr_reg32(hw, mem_win_base | BIR_V(0) |
WINDOW_V(ilog2(MEMWIN_APERTURE) - 10),
PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN_A, win));
csio_rd_reg32(hw,
PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN_A, win));
return 0;
}
static void
csio_t5_pcie_intr_handler(struct csio_hw *hw)
{
static struct intr_info pcie_intr_info[] = {
{ MSTGRPPERR_F, "Master Response Read Queue parity error",
-1, 1 },
{ MSTTIMEOUTPERR_F, "Master Timeout FIFO parity error", -1, 1 },
{ MSIXSTIPERR_F, "MSI-X STI SRAM parity error", -1, 1 },
{ MSIXADDRLPERR_F, "MSI-X AddrL parity error", -1, 1 },
{ MSIXADDRHPERR_F, "MSI-X AddrH parity error", -1, 1 },
{ MSIXDATAPERR_F, "MSI-X data parity error", -1, 1 },
{ MSIXDIPERR_F, "MSI-X DI parity error", -1, 1 },
{ PIOCPLGRPPERR_F, "PCI PIO completion Group FIFO parity error",
-1, 1 },
{ PIOREQGRPPERR_F, "PCI PIO request Group FIFO parity error",
-1, 1 },
{ TARTAGPERR_F, "PCI PCI target tag FIFO parity error", -1, 1 },
{ MSTTAGQPERR_F, "PCI master tag queue parity error", -1, 1 },
{ CREQPERR_F, "PCI CMD channel request parity error", -1, 1 },
{ CRSPPERR_F, "PCI CMD channel response parity error", -1, 1 },
{ DREQWRPERR_F, "PCI DMA channel write request parity error",
-1, 1 },
{ DREQPERR_F, "PCI DMA channel request parity error", -1, 1 },
{ DRSPPERR_F, "PCI DMA channel response parity error", -1, 1 },
{ HREQWRPERR_F, "PCI HMA channel count parity error", -1, 1 },
{ HREQPERR_F, "PCI HMA channel request parity error", -1, 1 },
{ HRSPPERR_F, "PCI HMA channel response parity error", -1, 1 },
{ CFGSNPPERR_F, "PCI config snoop FIFO parity error", -1, 1 },
{ FIDPERR_F, "PCI FID parity error", -1, 1 },
{ VFIDPERR_F, "PCI INTx clear parity error", -1, 1 },
{ MAGRPPERR_F, "PCI MA group FIFO parity error", -1, 1 },
{ PIOTAGPERR_F, "PCI PIO tag parity error", -1, 1 },
{ IPRXHDRGRPPERR_F, "PCI IP Rx header group parity error",
-1, 1 },
{ IPRXDATAGRPPERR_F, "PCI IP Rx data group parity error",
-1, 1 },
{ RPLPERR_F, "PCI IP replay buffer parity error", -1, 1 },
{ IPSOTPERR_F, "PCI IP SOT buffer parity error", -1, 1 },
{ TRGT1GRPPERR_F, "PCI TRGT1 group FIFOs parity error", -1, 1 },
{ READRSPERR_F, "Outbound read error", -1, 0 },
{ 0, NULL, 0, 0 }
};
int fat;
fat = csio_handle_intr_status(hw, PCIE_INT_CAUSE_A, pcie_intr_info);
if (fat)
csio_hw_fatal_err(hw);
}
static unsigned int
csio_t5_flash_cfg_addr(struct csio_hw *hw)
{
return FLASH_CFG_START;
}
static int
csio_t5_mc_read(struct csio_hw *hw, int idx, uint32_t addr, __be32 *data,
uint64_t *ecc)
{
int i;
uint32_t mc_bist_cmd_reg, mc_bist_cmd_addr_reg, mc_bist_cmd_len_reg;
uint32_t mc_bist_data_pattern_reg;
mc_bist_cmd_reg = MC_REG(MC_P_BIST_CMD_A, idx);
mc_bist_cmd_addr_reg = MC_REG(MC_P_BIST_CMD_ADDR_A, idx);
mc_bist_cmd_len_reg = MC_REG(MC_P_BIST_CMD_LEN_A, idx);
mc_bist_data_pattern_reg = MC_REG(MC_P_BIST_DATA_PATTERN_A, idx);
if (csio_rd_reg32(hw, mc_bist_cmd_reg) & START_BIST_F)
return -EBUSY;
csio_wr_reg32(hw, addr & ~0x3fU, mc_bist_cmd_addr_reg);
csio_wr_reg32(hw, 64, mc_bist_cmd_len_reg);
csio_wr_reg32(hw, 0xc, mc_bist_data_pattern_reg);
csio_wr_reg32(hw, BIST_OPCODE_V(1) | START_BIST_F | BIST_CMD_GAP_V(1),
mc_bist_cmd_reg);
i = csio_hw_wait_op_done_val(hw, mc_bist_cmd_reg, START_BIST_F,
0, 10, 1, NULL);
if (i)
return i;
#define MC_DATA(i) MC_BIST_STATUS_REG(MC_BIST_STATUS_RDATA_A, i)
for (i = 15; i >= 0; i--)
*data++ = htonl(csio_rd_reg32(hw, MC_DATA(i)));
if (ecc)
*ecc = csio_rd_reg64(hw, MC_DATA(16));
#undef MC_DATA
return 0;
}
static int
csio_t5_edc_read(struct csio_hw *hw, int idx, uint32_t addr, __be32 *data,
uint64_t *ecc)
{
int i;
uint32_t edc_bist_cmd_reg, edc_bist_cmd_addr_reg, edc_bist_cmd_len_reg;
uint32_t edc_bist_cmd_data_pattern;
#define EDC_STRIDE_T5 (EDC_T51_BASE_ADDR - EDC_T50_BASE_ADDR)
#define EDC_REG_T5(reg, idx) (reg + EDC_STRIDE_T5 * idx)
edc_bist_cmd_reg = EDC_REG_T5(EDC_H_BIST_CMD_A, idx);
edc_bist_cmd_addr_reg = EDC_REG_T5(EDC_H_BIST_CMD_ADDR_A, idx);
edc_bist_cmd_len_reg = EDC_REG_T5(EDC_H_BIST_CMD_LEN_A, idx);
edc_bist_cmd_data_pattern = EDC_REG_T5(EDC_H_BIST_DATA_PATTERN_A, idx);
#undef EDC_REG_T5
#undef EDC_STRIDE_T5
if (csio_rd_reg32(hw, edc_bist_cmd_reg) & START_BIST_F)
return -EBUSY;
csio_wr_reg32(hw, addr & ~0x3fU, edc_bist_cmd_addr_reg);
csio_wr_reg32(hw, 64, edc_bist_cmd_len_reg);
csio_wr_reg32(hw, 0xc, edc_bist_cmd_data_pattern);
csio_wr_reg32(hw, BIST_OPCODE_V(1) | START_BIST_F | BIST_CMD_GAP_V(1),
edc_bist_cmd_reg);
i = csio_hw_wait_op_done_val(hw, edc_bist_cmd_reg, START_BIST_F,
0, 10, 1, NULL);
if (i)
return i;
#define EDC_DATA(i) (EDC_BIST_STATUS_REG(EDC_BIST_STATUS_RDATA_A, i) + idx)
for (i = 15; i >= 0; i--)
*data++ = htonl(csio_rd_reg32(hw, EDC_DATA(i)));
if (ecc)
*ecc = csio_rd_reg64(hw, EDC_DATA(16));
#undef EDC_DATA
return 0;
}
static int
csio_t5_memory_rw(struct csio_hw *hw, u32 win, int mtype, u32 addr,
u32 len, uint32_t *buf, int dir)
{
u32 pos, start, offset, memoffset;
u32 edc_size, mc_size, win_pf, mem_reg, mem_aperture, mem_base;
if ((addr & 0x3) || (len & 0x3))
return -EINVAL;
edc_size = EDRAM0_SIZE_G(csio_rd_reg32(hw, MA_EDRAM0_BAR_A));
if (mtype != MEM_MC1)
memoffset = (mtype * (edc_size * 1024 * 1024));
else {
mc_size = EXT_MEM_SIZE_G(csio_rd_reg32(hw,
MA_EXT_MEMORY_BAR_A));
memoffset = (MEM_MC0 * edc_size + mc_size) * 1024 * 1024;
}
addr = addr + memoffset;
mem_reg = csio_rd_reg32(hw,
PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN_A, win));
mem_aperture = 1 << (WINDOW_V(mem_reg) + 10);
mem_base = PCIEOFST_G(mem_reg) << 10;
start = addr & ~(mem_aperture-1);
offset = addr - start;
win_pf = PFNUM_V(hw->pfn);
csio_dbg(hw, "csio_t5_memory_rw: mem_reg: 0x%x, mem_aperture: 0x%x\n",
mem_reg, mem_aperture);
csio_dbg(hw, "csio_t5_memory_rw: mem_base: 0x%x, mem_offset: 0x%x\n",
mem_base, memoffset);
csio_dbg(hw, "csio_t5_memory_rw: start:0x%x, offset:0x%x, win_pf:%d\n",
start, offset, win_pf);
csio_dbg(hw, "csio_t5_memory_rw: mtype: %d, addr: 0x%x, len: %d\n",
mtype, addr, len);
for (pos = start; len > 0; pos += mem_aperture, offset = 0) {
csio_wr_reg32(hw, pos | win_pf,
PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_OFFSET_A, win));
csio_rd_reg32(hw,
PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_OFFSET_A, win));
while (offset < mem_aperture && len > 0) {
if (dir)
*buf++ = csio_rd_reg32(hw, mem_base + offset);
else
csio_wr_reg32(hw, *buf++, mem_base + offset);
offset += sizeof(__be32);
len -= sizeof(__be32);
}
}
return 0;
}
static void
csio_t5_dfs_create_ext_mem(struct csio_hw *hw)
{
u32 size;
int i = csio_rd_reg32(hw, MA_TARGET_MEM_ENABLE_A);
if (i & EXT_MEM_ENABLE_F) {
size = csio_rd_reg32(hw, MA_EXT_MEMORY_BAR_A);
csio_add_debugfs_mem(hw, "mc0", MEM_MC0,
EXT_MEM_SIZE_G(size));
}
if (i & EXT_MEM1_ENABLE_F) {
size = csio_rd_reg32(hw, MA_EXT_MEMORY1_BAR_A);
csio_add_debugfs_mem(hw, "mc1", MEM_MC1,
EXT_MEM_SIZE_G(size));
}
}
struct csio_hw_chip_ops t5_ops = {
.chip_set_mem_win = csio_t5_set_mem_win,
.chip_pcie_intr_handler = csio_t5_pcie_intr_handler,
.chip_flash_cfg_addr = csio_t5_flash_cfg_addr,
.chip_mc_read = csio_t5_mc_read,
.chip_edc_read = csio_t5_edc_read,
.chip_memory_rw = csio_t5_memory_rw,
.chip_dfs_create_ext_mem = csio_t5_dfs_create_ext_mem,
}