1255736Sdavidch/*- 2255736Sdavidch * Copyright (c) 2007-2013 Broadcom Corporation. All rights reserved. 3255736Sdavidch * 4255736Sdavidch * Eric Davis <edavis@broadcom.com> 5255736Sdavidch * David Christensen <davidch@broadcom.com> 6255736Sdavidch * Gary Zambrano <zambrano@broadcom.com> 7255736Sdavidch * 8255736Sdavidch * Redistribution and use in source and binary forms, with or without 9255736Sdavidch * modification, are permitted provided that the following conditions 10255736Sdavidch * are met: 11255736Sdavidch * 12255736Sdavidch * 1. Redistributions of source code must retain the above copyright 13255736Sdavidch * notice, this list of conditions and the following disclaimer. 14255736Sdavidch * 2. Redistributions in binary form must reproduce the above copyright 15255736Sdavidch * notice, this list of conditions and the following disclaimer in the 16255736Sdavidch * documentation and/or other materials provided with the distribution. 17255736Sdavidch * 3. Neither the name of Broadcom Corporation nor the name of its contributors 18255736Sdavidch * may be used to endorse or promote products derived from this software 19255736Sdavidch * without specific prior written consent. 20255736Sdavidch * 21255736Sdavidch * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS' 22255736Sdavidch * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23255736Sdavidch * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24255736Sdavidch * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 25255736Sdavidch * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26255736Sdavidch * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27255736Sdavidch * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28255736Sdavidch * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29255736Sdavidch * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30255736Sdavidch * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 31255736Sdavidch * THE POSSIBILITY OF SUCH DAMAGE. 32255736Sdavidch */ 33255736Sdavidch 34255736Sdavidch#include <sys/cdefs.h> 35255736Sdavidch__FBSDID("$FreeBSD$"); 36255736Sdavidch 37255736Sdavidch#ifndef ECORE_INIT_OPS_H 38255736Sdavidch#define ECORE_INIT_OPS_H 39255736Sdavidch 40255736Sdavidch 41255736Sdavidch 42255736Sdavidch 43255736Sdavidch 44255736Sdavidch 45255736Sdavidch 46255736Sdavidch 47255736Sdavidch 48255736Sdavidch 49255736Sdavidchstatic int ecore_gunzip(struct bxe_softc *sc, const uint8_t *zbuf, int len); 50255736Sdavidchstatic void ecore_reg_wr_ind(struct bxe_softc *sc, uint32_t addr, uint32_t val); 51255736Sdavidchstatic void ecore_write_dmae_phys_len(struct bxe_softc *sc, 52255736Sdavidch ecore_dma_addr_t phys_addr, uint32_t addr, 53255736Sdavidch uint32_t len); 54255736Sdavidch 55255736Sdavidchstatic void ecore_init_str_wr(struct bxe_softc *sc, uint32_t addr, 56255736Sdavidch const uint32_t *data, uint32_t len) 57255736Sdavidch{ 58255736Sdavidch uint32_t i; 59255736Sdavidch 60255736Sdavidch for (i = 0; i < len; i++) 61255736Sdavidch REG_WR(sc, addr + i*4, data[i]); 62255736Sdavidch} 63255736Sdavidch 64255736Sdavidchstatic void ecore_init_ind_wr(struct bxe_softc *sc, uint32_t addr, 65255736Sdavidch const uint32_t *data, uint32_t len) 66255736Sdavidch{ 67255736Sdavidch uint32_t i; 68255736Sdavidch 69255736Sdavidch for (i = 0; i < len; i++) 70255736Sdavidch ecore_reg_wr_ind(sc, addr + i*4, data[i]); 71255736Sdavidch} 72255736Sdavidch 73255736Sdavidchstatic void ecore_write_big_buf(struct bxe_softc *sc, uint32_t addr, uint32_t len, 74255736Sdavidch uint8_t wb) 75255736Sdavidch{ 76255736Sdavidch if (DMAE_READY(sc)) 77255736Sdavidch ecore_write_dmae_phys_len(sc, GUNZIP_PHYS(sc), addr, len); 78255736Sdavidch 79255736Sdavidch /* in E1 chips BIOS initiated ZLR may interrupt widebus writes */ 80255736Sdavidch else if (wb && CHIP_IS_E1(sc)) 81255736Sdavidch ecore_init_ind_wr(sc, addr, GUNZIP_BUF(sc), len); 82255736Sdavidch 83255736Sdavidch /* in later chips PXP root complex handles BIOS ZLR w/o interrupting */ 84255736Sdavidch else 85255736Sdavidch ecore_init_str_wr(sc, addr, GUNZIP_BUF(sc), len); 86255736Sdavidch} 87255736Sdavidch 88255736Sdavidchstatic void ecore_init_fill(struct bxe_softc *sc, uint32_t addr, int fill, 89255736Sdavidch uint32_t len, uint8_t wb) 90255736Sdavidch{ 91255736Sdavidch uint32_t buf_len = (((len*4) > FW_BUF_SIZE) ? FW_BUF_SIZE : (len*4)); 92255736Sdavidch uint32_t buf_len32 = buf_len/4; 93255736Sdavidch uint32_t i; 94255736Sdavidch 95255736Sdavidch ECORE_MEMSET(GUNZIP_BUF(sc), (uint8_t)fill, buf_len); 96255736Sdavidch 97255736Sdavidch for (i = 0; i < len; i += buf_len32) { 98255736Sdavidch uint32_t cur_len = min(buf_len32, len - i); 99255736Sdavidch 100255736Sdavidch ecore_write_big_buf(sc, addr + i*4, cur_len, wb); 101255736Sdavidch } 102255736Sdavidch} 103255736Sdavidch 104255736Sdavidchstatic void ecore_write_big_buf_wb(struct bxe_softc *sc, uint32_t addr, uint32_t len) 105255736Sdavidch{ 106255736Sdavidch if (DMAE_READY(sc)) 107255736Sdavidch ecore_write_dmae_phys_len(sc, GUNZIP_PHYS(sc), addr, len); 108255736Sdavidch 109255736Sdavidch /* in E1 chips BIOS initiated ZLR may interrupt widebus writes */ 110255736Sdavidch else if (CHIP_IS_E1(sc)) 111255736Sdavidch ecore_init_ind_wr(sc, addr, GUNZIP_BUF(sc), len); 112255736Sdavidch 113255736Sdavidch /* in later chips PXP root complex handles BIOS ZLR w/o interrupting */ 114255736Sdavidch else 115255736Sdavidch ecore_init_str_wr(sc, addr, GUNZIP_BUF(sc), len); 116255736Sdavidch} 117255736Sdavidch 118255736Sdavidchstatic void ecore_init_wr_64(struct bxe_softc *sc, uint32_t addr, 119255736Sdavidch const uint32_t *data, uint32_t len64) 120255736Sdavidch{ 121255736Sdavidch uint32_t buf_len32 = FW_BUF_SIZE/4; 122255736Sdavidch uint32_t len = len64*2; 123255736Sdavidch uint64_t data64 = 0; 124255736Sdavidch uint32_t i; 125255736Sdavidch 126255736Sdavidch /* 64 bit value is in a blob: first low DWORD, then high DWORD */ 127255736Sdavidch data64 = HILO_U64((*(data + 1)), (*data)); 128255736Sdavidch 129255736Sdavidch len64 = min((uint32_t)(FW_BUF_SIZE/8), len64); 130255736Sdavidch for (i = 0; i < len64; i++) { 131255736Sdavidch uint64_t *pdata = ((uint64_t *)(GUNZIP_BUF(sc))) + i; 132255736Sdavidch 133255736Sdavidch *pdata = data64; 134255736Sdavidch } 135255736Sdavidch 136255736Sdavidch for (i = 0; i < len; i += buf_len32) { 137255736Sdavidch uint32_t cur_len = min(buf_len32, len - i); 138255736Sdavidch 139255736Sdavidch ecore_write_big_buf_wb(sc, addr + i*4, cur_len); 140255736Sdavidch } 141255736Sdavidch} 142255736Sdavidch 143255736Sdavidch/********************************************************* 144255736Sdavidch There are different blobs for each PRAM section. 145255736Sdavidch In addition, each blob write operation is divided into a few operations 146255736Sdavidch in order to decrease the amount of phys. contiguous buffer needed. 147255736Sdavidch Thus, when we select a blob the address may be with some offset 148255736Sdavidch from the beginning of PRAM section. 149255736Sdavidch The same holds for the INT_TABLE sections. 150255736Sdavidch**********************************************************/ 151255736Sdavidch#define IF_IS_INT_TABLE_ADDR(base, addr) \ 152255736Sdavidch if (((base) <= (addr)) && ((base) + 0x400 >= (addr))) 153255736Sdavidch 154255736Sdavidch#define IF_IS_PRAM_ADDR(base, addr) \ 155255736Sdavidch if (((base) <= (addr)) && ((base) + 0x40000 >= (addr))) 156255736Sdavidch 157255736Sdavidchstatic const uint8_t *ecore_sel_blob(struct bxe_softc *sc, uint32_t addr, 158255736Sdavidch const uint8_t *data) 159255736Sdavidch{ 160255736Sdavidch IF_IS_INT_TABLE_ADDR(TSEM_REG_INT_TABLE, addr) 161255736Sdavidch data = INIT_TSEM_INT_TABLE_DATA(sc); 162255736Sdavidch else 163255736Sdavidch IF_IS_INT_TABLE_ADDR(CSEM_REG_INT_TABLE, addr) 164255736Sdavidch data = INIT_CSEM_INT_TABLE_DATA(sc); 165255736Sdavidch else 166255736Sdavidch IF_IS_INT_TABLE_ADDR(USEM_REG_INT_TABLE, addr) 167255736Sdavidch data = INIT_USEM_INT_TABLE_DATA(sc); 168255736Sdavidch else 169255736Sdavidch IF_IS_INT_TABLE_ADDR(XSEM_REG_INT_TABLE, addr) 170255736Sdavidch data = INIT_XSEM_INT_TABLE_DATA(sc); 171255736Sdavidch else 172255736Sdavidch IF_IS_PRAM_ADDR(TSEM_REG_PRAM, addr) 173255736Sdavidch data = INIT_TSEM_PRAM_DATA(sc); 174255736Sdavidch else 175255736Sdavidch IF_IS_PRAM_ADDR(CSEM_REG_PRAM, addr) 176255736Sdavidch data = INIT_CSEM_PRAM_DATA(sc); 177255736Sdavidch else 178255736Sdavidch IF_IS_PRAM_ADDR(USEM_REG_PRAM, addr) 179255736Sdavidch data = INIT_USEM_PRAM_DATA(sc); 180255736Sdavidch else 181255736Sdavidch IF_IS_PRAM_ADDR(XSEM_REG_PRAM, addr) 182255736Sdavidch data = INIT_XSEM_PRAM_DATA(sc); 183255736Sdavidch 184255736Sdavidch return data; 185255736Sdavidch} 186255736Sdavidch 187255736Sdavidchstatic void ecore_init_wr_wb(struct bxe_softc *sc, uint32_t addr, 188255736Sdavidch const uint32_t *data, uint32_t len) 189255736Sdavidch{ 190255736Sdavidch if (DMAE_READY(sc)) 191255736Sdavidch VIRT_WR_DMAE_LEN(sc, data, addr, len, 0); 192255736Sdavidch 193255736Sdavidch /* in E1 chips BIOS initiated ZLR may interrupt widebus writes */ 194255736Sdavidch else if (CHIP_IS_E1(sc)) 195255736Sdavidch ecore_init_ind_wr(sc, addr, data, len); 196255736Sdavidch 197255736Sdavidch /* in later chips PXP root complex handles BIOS ZLR w/o interrupting */ 198255736Sdavidch else 199255736Sdavidch ecore_init_str_wr(sc, addr, data, len); 200255736Sdavidch} 201255736Sdavidch 202255736Sdavidch#ifndef FW_ZIP_SUPPORT 203255736Sdavidchstatic void ecore_init_fw(struct bxe_softc *sc, uint32_t addr, uint32_t len) 204255736Sdavidch{ 205255736Sdavidch const uint8_t *data = NULL; 206255736Sdavidch 207255736Sdavidch data = ecore_sel_blob(sc, addr, (const uint8_t *)data); 208255736Sdavidch 209255736Sdavidch if (DMAE_READY(sc)) 210255736Sdavidch VIRT_WR_DMAE_LEN(sc, data, addr, len, 1); 211255736Sdavidch 212255736Sdavidch /* in E1 BIOS initiated ZLR may interrupt widebus writes */ 213255736Sdavidch else if (CHIP_IS_E1(sc)) 214255736Sdavidch ecore_init_ind_wr(sc, addr, (const uint32_t *)data, len); 215255736Sdavidch 216255736Sdavidch /* in later chips PXP root complex handles BIOS ZLR w/o interrupting */ 217255736Sdavidch else 218255736Sdavidch ecore_init_str_wr(sc, addr, (const uint32_t *)data, len); 219255736Sdavidch} 220255736Sdavidch 221255736Sdavidch#endif 222255736Sdavidch 223255736Sdavidchstatic void ecore_wr_64(struct bxe_softc *sc, uint32_t reg, uint32_t val_lo, 224255736Sdavidch uint32_t val_hi) 225255736Sdavidch{ 226255736Sdavidch uint32_t wb_write[2]; 227255736Sdavidch 228255736Sdavidch wb_write[0] = val_lo; 229255736Sdavidch wb_write[1] = val_hi; 230255736Sdavidch REG_WR_DMAE_LEN(sc, reg, wb_write, 2); 231255736Sdavidch} 232255736Sdavidch 233255736Sdavidchstatic void ecore_init_wr_zp(struct bxe_softc *sc, uint32_t addr, uint32_t len, 234255736Sdavidch uint32_t blob_off) 235255736Sdavidch{ 236255736Sdavidch const uint8_t *data = NULL; 237255736Sdavidch int rc; 238255736Sdavidch uint32_t i; 239255736Sdavidch 240255736Sdavidch data = ecore_sel_blob(sc, addr, data) + blob_off*4; 241255736Sdavidch 242255736Sdavidch rc = ecore_gunzip(sc, data, len); 243255736Sdavidch if (rc) 244255736Sdavidch return; 245255736Sdavidch 246255736Sdavidch /* gunzip_outlen is in dwords */ 247255736Sdavidch len = GUNZIP_OUTLEN(sc); 248255736Sdavidch for (i = 0; i < len; i++) 249255736Sdavidch ((uint32_t *)GUNZIP_BUF(sc))[i] = (uint32_t) 250255736Sdavidch ECORE_CPU_TO_LE32(((uint32_t *)GUNZIP_BUF(sc))[i]); 251255736Sdavidch 252255736Sdavidch ecore_write_big_buf_wb(sc, addr, len); 253255736Sdavidch} 254255736Sdavidch 255255736Sdavidchstatic void ecore_init_block(struct bxe_softc *sc, uint32_t block, uint32_t stage) 256255736Sdavidch{ 257255736Sdavidch uint16_t op_start = 258255736Sdavidch INIT_OPS_OFFSETS(sc)[BLOCK_OPS_IDX(block, stage, 259255736Sdavidch STAGE_START)]; 260255736Sdavidch uint16_t op_end = 261255736Sdavidch INIT_OPS_OFFSETS(sc)[BLOCK_OPS_IDX(block, stage, 262255736Sdavidch STAGE_END)]; 263255736Sdavidch const union init_op *op; 264255736Sdavidch uint32_t op_idx, op_type, addr, len; 265255736Sdavidch const uint32_t *data, *data_base; 266255736Sdavidch 267255736Sdavidch /* If empty block */ 268255736Sdavidch if (op_start == op_end) 269255736Sdavidch return; 270255736Sdavidch 271255736Sdavidch data_base = INIT_DATA(sc); 272255736Sdavidch 273255736Sdavidch for (op_idx = op_start; op_idx < op_end; op_idx++) { 274255736Sdavidch 275255736Sdavidch op = (const union init_op *)&(INIT_OPS(sc)[op_idx]); 276255736Sdavidch /* Get generic data */ 277255736Sdavidch op_type = op->raw.op; 278255736Sdavidch addr = op->raw.offset; 279255736Sdavidch /* Get data that's used for OP_SW, OP_WB, OP_FW, OP_ZP and 280255736Sdavidch * OP_WR64 (we assume that op_arr_write and op_write have the 281255736Sdavidch * same structure). 282255736Sdavidch */ 283255736Sdavidch len = op->arr_wr.data_len; 284255736Sdavidch data = data_base + op->arr_wr.data_off; 285255736Sdavidch 286255736Sdavidch switch (op_type) { 287255736Sdavidch case OP_RD: 288255736Sdavidch REG_RD(sc, addr); 289255736Sdavidch break; 290255736Sdavidch case OP_WR: 291255736Sdavidch REG_WR(sc, addr, op->write.val); 292255736Sdavidch break; 293255736Sdavidch case OP_SW: 294255736Sdavidch ecore_init_str_wr(sc, addr, data, len); 295255736Sdavidch break; 296255736Sdavidch case OP_WB: 297255736Sdavidch ecore_init_wr_wb(sc, addr, data, len); 298255736Sdavidch break; 299255736Sdavidch#ifndef FW_ZIP_SUPPORT 300255736Sdavidch case OP_FW: 301255736Sdavidch ecore_init_fw(sc, addr, len); 302255736Sdavidch break; 303255736Sdavidch#endif 304255736Sdavidch case OP_ZR: 305255736Sdavidch ecore_init_fill(sc, addr, 0, op->zero.len, 0); 306255736Sdavidch break; 307255736Sdavidch case OP_WB_ZR: 308255736Sdavidch ecore_init_fill(sc, addr, 0, op->zero.len, 1); 309255736Sdavidch break; 310255736Sdavidch case OP_ZP: 311255736Sdavidch ecore_init_wr_zp(sc, addr, len, 312255736Sdavidch op->arr_wr.data_off); 313255736Sdavidch break; 314255736Sdavidch case OP_WR_64: 315255736Sdavidch ecore_init_wr_64(sc, addr, data, len); 316255736Sdavidch break; 317255736Sdavidch case OP_IF_MODE_AND: 318255736Sdavidch /* if any of the flags doesn't match, skip the 319255736Sdavidch * conditional block. 320255736Sdavidch */ 321255736Sdavidch if ((INIT_MODE_FLAGS(sc) & 322255736Sdavidch op->if_mode.mode_bit_map) != 323255736Sdavidch op->if_mode.mode_bit_map) 324255736Sdavidch op_idx += op->if_mode.cmd_offset; 325255736Sdavidch break; 326255736Sdavidch case OP_IF_MODE_OR: 327255736Sdavidch /* if all the flags don't match, skip the conditional 328255736Sdavidch * block. 329255736Sdavidch */ 330255736Sdavidch if ((INIT_MODE_FLAGS(sc) & 331255736Sdavidch op->if_mode.mode_bit_map) == 0) 332255736Sdavidch op_idx += op->if_mode.cmd_offset; 333255736Sdavidch break; 334255736Sdavidch /* the following opcodes are unused at the moment. */ 335255736Sdavidch case OP_IF_PHASE: 336255736Sdavidch case OP_RT: 337255736Sdavidch case OP_DELAY: 338255736Sdavidch case OP_VERIFY: 339255736Sdavidch default: 340255736Sdavidch /* Should never get here! */ 341255736Sdavidch 342255736Sdavidch break; 343255736Sdavidch } 344255736Sdavidch } 345255736Sdavidch} 346255736Sdavidch 347255736Sdavidch 348255736Sdavidch/**************************************************************************** 349255736Sdavidch* PXP Arbiter 350255736Sdavidch****************************************************************************/ 351255736Sdavidch/* 352255736Sdavidch * This code configures the PCI read/write arbiter 353255736Sdavidch * which implements a weighted round robin 354255736Sdavidch * between the virtual queues in the chip. 355255736Sdavidch * 356255736Sdavidch * The values were derived for each PCI max payload and max request size. 357255736Sdavidch * since max payload and max request size are only known at run time, 358255736Sdavidch * this is done as a separate init stage. 359255736Sdavidch */ 360255736Sdavidch 361255736Sdavidch#define NUM_WR_Q 13 362255736Sdavidch#define NUM_RD_Q 29 363255736Sdavidch#define MAX_RD_ORD 3 364255736Sdavidch#define MAX_WR_ORD 2 365255736Sdavidch 366255736Sdavidch/* configuration for one arbiter queue */ 367255736Sdavidchstruct arb_line { 368255736Sdavidch int l; 369255736Sdavidch int add; 370255736Sdavidch int ubound; 371255736Sdavidch}; 372255736Sdavidch 373255736Sdavidch/* derived configuration for each read queue for each max request size */ 374255736Sdavidchstatic const struct arb_line read_arb_data[NUM_RD_Q][MAX_RD_ORD + 1] = { 375255736Sdavidch/* 1 */ { {8, 64, 25}, {16, 64, 25}, {32, 64, 25}, {64, 64, 41} }, 376255736Sdavidch { {4, 8, 4}, {4, 8, 4}, {4, 8, 4}, {4, 8, 4} }, 377255736Sdavidch { {4, 3, 3}, {4, 3, 3}, {4, 3, 3}, {4, 3, 3} }, 378255736Sdavidch { {8, 3, 6}, {16, 3, 11}, {16, 3, 11}, {16, 3, 11} }, 379255736Sdavidch { {8, 64, 25}, {16, 64, 25}, {32, 64, 25}, {64, 64, 41} }, 380255736Sdavidch { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {64, 3, 41} }, 381255736Sdavidch { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {64, 3, 41} }, 382255736Sdavidch { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {64, 3, 41} }, 383255736Sdavidch { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {64, 3, 41} }, 384255736Sdavidch/* 10 */{ {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, 385255736Sdavidch { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, 386255736Sdavidch { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, 387255736Sdavidch { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, 388255736Sdavidch { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, 389255736Sdavidch { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, 390255736Sdavidch { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, 391255736Sdavidch { {8, 64, 6}, {16, 64, 11}, {32, 64, 21}, {32, 64, 21} }, 392255736Sdavidch { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, 393255736Sdavidch { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, 394255736Sdavidch/* 20 */{ {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, 395255736Sdavidch { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, 396255736Sdavidch { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, 397255736Sdavidch { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, 398255736Sdavidch { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, 399255736Sdavidch { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, 400255736Sdavidch { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, 401255736Sdavidch { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, 402255736Sdavidch { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, 403255736Sdavidch { {8, 64, 25}, {16, 64, 41}, {32, 64, 81}, {64, 64, 120} } 404255736Sdavidch}; 405255736Sdavidch 406255736Sdavidch/* derived configuration for each write queue for each max request size */ 407255736Sdavidchstatic const struct arb_line write_arb_data[NUM_WR_Q][MAX_WR_ORD + 1] = { 408255736Sdavidch/* 1 */ { {4, 6, 3}, {4, 6, 3}, {4, 6, 3} }, 409255736Sdavidch { {4, 2, 3}, {4, 2, 3}, {4, 2, 3} }, 410255736Sdavidch { {8, 2, 6}, {16, 2, 11}, {16, 2, 11} }, 411255736Sdavidch { {8, 2, 6}, {16, 2, 11}, {32, 2, 21} }, 412255736Sdavidch { {8, 2, 6}, {16, 2, 11}, {32, 2, 21} }, 413255736Sdavidch { {8, 2, 6}, {16, 2, 11}, {32, 2, 21} }, 414255736Sdavidch { {8, 64, 25}, {16, 64, 25}, {32, 64, 25} }, 415255736Sdavidch { {8, 2, 6}, {16, 2, 11}, {16, 2, 11} }, 416255736Sdavidch { {8, 2, 6}, {16, 2, 11}, {16, 2, 11} }, 417255736Sdavidch/* 10 */{ {8, 9, 6}, {16, 9, 11}, {32, 9, 21} }, 418255736Sdavidch { {8, 47, 19}, {16, 47, 19}, {32, 47, 21} }, 419255736Sdavidch { {8, 9, 6}, {16, 9, 11}, {16, 9, 11} }, 420255736Sdavidch { {8, 64, 25}, {16, 64, 41}, {32, 64, 81} } 421255736Sdavidch}; 422255736Sdavidch 423255736Sdavidch/* register addresses for read queues */ 424255736Sdavidchstatic const struct arb_line read_arb_addr[NUM_RD_Q-1] = { 425255736Sdavidch/* 1 */ {PXP2_REG_RQ_BW_RD_L0, PXP2_REG_RQ_BW_RD_ADD0, 426255736Sdavidch PXP2_REG_RQ_BW_RD_UBOUND0}, 427255736Sdavidch {PXP2_REG_PSWRQ_BW_L1, PXP2_REG_PSWRQ_BW_ADD1, 428255736Sdavidch PXP2_REG_PSWRQ_BW_UB1}, 429255736Sdavidch {PXP2_REG_PSWRQ_BW_L2, PXP2_REG_PSWRQ_BW_ADD2, 430255736Sdavidch PXP2_REG_PSWRQ_BW_UB2}, 431255736Sdavidch {PXP2_REG_PSWRQ_BW_L3, PXP2_REG_PSWRQ_BW_ADD3, 432255736Sdavidch PXP2_REG_PSWRQ_BW_UB3}, 433255736Sdavidch {PXP2_REG_RQ_BW_RD_L4, PXP2_REG_RQ_BW_RD_ADD4, 434255736Sdavidch PXP2_REG_RQ_BW_RD_UBOUND4}, 435255736Sdavidch {PXP2_REG_RQ_BW_RD_L5, PXP2_REG_RQ_BW_RD_ADD5, 436255736Sdavidch PXP2_REG_RQ_BW_RD_UBOUND5}, 437255736Sdavidch {PXP2_REG_PSWRQ_BW_L6, PXP2_REG_PSWRQ_BW_ADD6, 438255736Sdavidch PXP2_REG_PSWRQ_BW_UB6}, 439255736Sdavidch {PXP2_REG_PSWRQ_BW_L7, PXP2_REG_PSWRQ_BW_ADD7, 440255736Sdavidch PXP2_REG_PSWRQ_BW_UB7}, 441255736Sdavidch {PXP2_REG_PSWRQ_BW_L8, PXP2_REG_PSWRQ_BW_ADD8, 442255736Sdavidch PXP2_REG_PSWRQ_BW_UB8}, 443255736Sdavidch/* 10 */{PXP2_REG_PSWRQ_BW_L9, PXP2_REG_PSWRQ_BW_ADD9, 444255736Sdavidch PXP2_REG_PSWRQ_BW_UB9}, 445255736Sdavidch {PXP2_REG_PSWRQ_BW_L10, PXP2_REG_PSWRQ_BW_ADD10, 446255736Sdavidch PXP2_REG_PSWRQ_BW_UB10}, 447255736Sdavidch {PXP2_REG_PSWRQ_BW_L11, PXP2_REG_PSWRQ_BW_ADD11, 448255736Sdavidch PXP2_REG_PSWRQ_BW_UB11}, 449255736Sdavidch {PXP2_REG_RQ_BW_RD_L12, PXP2_REG_RQ_BW_RD_ADD12, 450255736Sdavidch PXP2_REG_RQ_BW_RD_UBOUND12}, 451255736Sdavidch {PXP2_REG_RQ_BW_RD_L13, PXP2_REG_RQ_BW_RD_ADD13, 452255736Sdavidch PXP2_REG_RQ_BW_RD_UBOUND13}, 453255736Sdavidch {PXP2_REG_RQ_BW_RD_L14, PXP2_REG_RQ_BW_RD_ADD14, 454255736Sdavidch PXP2_REG_RQ_BW_RD_UBOUND14}, 455255736Sdavidch {PXP2_REG_RQ_BW_RD_L15, PXP2_REG_RQ_BW_RD_ADD15, 456255736Sdavidch PXP2_REG_RQ_BW_RD_UBOUND15}, 457255736Sdavidch {PXP2_REG_RQ_BW_RD_L16, PXP2_REG_RQ_BW_RD_ADD16, 458255736Sdavidch PXP2_REG_RQ_BW_RD_UBOUND16}, 459255736Sdavidch {PXP2_REG_RQ_BW_RD_L17, PXP2_REG_RQ_BW_RD_ADD17, 460255736Sdavidch PXP2_REG_RQ_BW_RD_UBOUND17}, 461255736Sdavidch {PXP2_REG_RQ_BW_RD_L18, PXP2_REG_RQ_BW_RD_ADD18, 462255736Sdavidch PXP2_REG_RQ_BW_RD_UBOUND18}, 463255736Sdavidch/* 20 */{PXP2_REG_RQ_BW_RD_L19, PXP2_REG_RQ_BW_RD_ADD19, 464255736Sdavidch PXP2_REG_RQ_BW_RD_UBOUND19}, 465255736Sdavidch {PXP2_REG_RQ_BW_RD_L20, PXP2_REG_RQ_BW_RD_ADD20, 466255736Sdavidch PXP2_REG_RQ_BW_RD_UBOUND20}, 467255736Sdavidch {PXP2_REG_RQ_BW_RD_L22, PXP2_REG_RQ_BW_RD_ADD22, 468255736Sdavidch PXP2_REG_RQ_BW_RD_UBOUND22}, 469255736Sdavidch {PXP2_REG_RQ_BW_RD_L23, PXP2_REG_RQ_BW_RD_ADD23, 470255736Sdavidch PXP2_REG_RQ_BW_RD_UBOUND23}, 471255736Sdavidch {PXP2_REG_RQ_BW_RD_L24, PXP2_REG_RQ_BW_RD_ADD24, 472255736Sdavidch PXP2_REG_RQ_BW_RD_UBOUND24}, 473255736Sdavidch {PXP2_REG_RQ_BW_RD_L25, PXP2_REG_RQ_BW_RD_ADD25, 474255736Sdavidch PXP2_REG_RQ_BW_RD_UBOUND25}, 475255736Sdavidch {PXP2_REG_RQ_BW_RD_L26, PXP2_REG_RQ_BW_RD_ADD26, 476255736Sdavidch PXP2_REG_RQ_BW_RD_UBOUND26}, 477255736Sdavidch {PXP2_REG_RQ_BW_RD_L27, PXP2_REG_RQ_BW_RD_ADD27, 478255736Sdavidch PXP2_REG_RQ_BW_RD_UBOUND27}, 479255736Sdavidch {PXP2_REG_PSWRQ_BW_L28, PXP2_REG_PSWRQ_BW_ADD28, 480255736Sdavidch PXP2_REG_PSWRQ_BW_UB28} 481255736Sdavidch}; 482255736Sdavidch 483255736Sdavidch/* register addresses for write queues */ 484255736Sdavidchstatic const struct arb_line write_arb_addr[NUM_WR_Q-1] = { 485255736Sdavidch/* 1 */ {PXP2_REG_PSWRQ_BW_L1, PXP2_REG_PSWRQ_BW_ADD1, 486255736Sdavidch PXP2_REG_PSWRQ_BW_UB1}, 487255736Sdavidch {PXP2_REG_PSWRQ_BW_L2, PXP2_REG_PSWRQ_BW_ADD2, 488255736Sdavidch PXP2_REG_PSWRQ_BW_UB2}, 489255736Sdavidch {PXP2_REG_PSWRQ_BW_L3, PXP2_REG_PSWRQ_BW_ADD3, 490255736Sdavidch PXP2_REG_PSWRQ_BW_UB3}, 491255736Sdavidch {PXP2_REG_PSWRQ_BW_L6, PXP2_REG_PSWRQ_BW_ADD6, 492255736Sdavidch PXP2_REG_PSWRQ_BW_UB6}, 493255736Sdavidch {PXP2_REG_PSWRQ_BW_L7, PXP2_REG_PSWRQ_BW_ADD7, 494255736Sdavidch PXP2_REG_PSWRQ_BW_UB7}, 495255736Sdavidch {PXP2_REG_PSWRQ_BW_L8, PXP2_REG_PSWRQ_BW_ADD8, 496255736Sdavidch PXP2_REG_PSWRQ_BW_UB8}, 497255736Sdavidch {PXP2_REG_PSWRQ_BW_L9, PXP2_REG_PSWRQ_BW_ADD9, 498255736Sdavidch PXP2_REG_PSWRQ_BW_UB9}, 499255736Sdavidch {PXP2_REG_PSWRQ_BW_L10, PXP2_REG_PSWRQ_BW_ADD10, 500255736Sdavidch PXP2_REG_PSWRQ_BW_UB10}, 501255736Sdavidch {PXP2_REG_PSWRQ_BW_L11, PXP2_REG_PSWRQ_BW_ADD11, 502255736Sdavidch PXP2_REG_PSWRQ_BW_UB11}, 503255736Sdavidch/* 10 */{PXP2_REG_PSWRQ_BW_L28, PXP2_REG_PSWRQ_BW_ADD28, 504255736Sdavidch PXP2_REG_PSWRQ_BW_UB28}, 505255736Sdavidch {PXP2_REG_RQ_BW_WR_L29, PXP2_REG_RQ_BW_WR_ADD29, 506255736Sdavidch PXP2_REG_RQ_BW_WR_UBOUND29}, 507255736Sdavidch {PXP2_REG_RQ_BW_WR_L30, PXP2_REG_RQ_BW_WR_ADD30, 508255736Sdavidch PXP2_REG_RQ_BW_WR_UBOUND30} 509255736Sdavidch}; 510255736Sdavidch 511255736Sdavidchstatic void ecore_init_pxp_arb(struct bxe_softc *sc, int r_order, 512255736Sdavidch int w_order) 513255736Sdavidch{ 514255736Sdavidch uint32_t val, i; 515255736Sdavidch 516255736Sdavidch if (r_order > MAX_RD_ORD) { 517255736Sdavidch ECORE_MSG(sc, "read order of %d order adjusted to %d\n", 518255736Sdavidch r_order, MAX_RD_ORD); 519255736Sdavidch r_order = MAX_RD_ORD; 520255736Sdavidch } 521255736Sdavidch if (w_order > MAX_WR_ORD) { 522255736Sdavidch ECORE_MSG(sc, "write order of %d order adjusted to %d\n", 523255736Sdavidch w_order, MAX_WR_ORD); 524255736Sdavidch w_order = MAX_WR_ORD; 525255736Sdavidch } 526255736Sdavidch if (CHIP_REV_IS_FPGA(sc)) { 527255736Sdavidch ECORE_MSG(sc, "write order adjusted to 1 for FPGA\n"); 528255736Sdavidch w_order = 0; 529255736Sdavidch } 530255736Sdavidch ECORE_MSG(sc, "read order %d write order %d\n", r_order, w_order); 531255736Sdavidch 532255736Sdavidch for (i = 0; i < NUM_RD_Q-1; i++) { 533255736Sdavidch REG_WR(sc, read_arb_addr[i].l, read_arb_data[i][r_order].l); 534255736Sdavidch REG_WR(sc, read_arb_addr[i].add, 535255736Sdavidch read_arb_data[i][r_order].add); 536255736Sdavidch REG_WR(sc, read_arb_addr[i].ubound, 537255736Sdavidch read_arb_data[i][r_order].ubound); 538255736Sdavidch } 539255736Sdavidch 540255736Sdavidch for (i = 0; i < NUM_WR_Q-1; i++) { 541255736Sdavidch if ((write_arb_addr[i].l == PXP2_REG_RQ_BW_WR_L29) || 542255736Sdavidch (write_arb_addr[i].l == PXP2_REG_RQ_BW_WR_L30)) { 543255736Sdavidch 544255736Sdavidch REG_WR(sc, write_arb_addr[i].l, 545255736Sdavidch write_arb_data[i][w_order].l); 546255736Sdavidch 547255736Sdavidch REG_WR(sc, write_arb_addr[i].add, 548255736Sdavidch write_arb_data[i][w_order].add); 549255736Sdavidch 550255736Sdavidch REG_WR(sc, write_arb_addr[i].ubound, 551255736Sdavidch write_arb_data[i][w_order].ubound); 552255736Sdavidch } else { 553255736Sdavidch 554255736Sdavidch val = REG_RD(sc, write_arb_addr[i].l); 555255736Sdavidch REG_WR(sc, write_arb_addr[i].l, 556255736Sdavidch val | (write_arb_data[i][w_order].l << 10)); 557255736Sdavidch 558255736Sdavidch val = REG_RD(sc, write_arb_addr[i].add); 559255736Sdavidch REG_WR(sc, write_arb_addr[i].add, 560255736Sdavidch val | (write_arb_data[i][w_order].add << 10)); 561255736Sdavidch 562255736Sdavidch val = REG_RD(sc, write_arb_addr[i].ubound); 563255736Sdavidch REG_WR(sc, write_arb_addr[i].ubound, 564255736Sdavidch val | (write_arb_data[i][w_order].ubound << 7)); 565255736Sdavidch } 566255736Sdavidch } 567255736Sdavidch 568255736Sdavidch val = write_arb_data[NUM_WR_Q-1][w_order].add; 569255736Sdavidch val += write_arb_data[NUM_WR_Q-1][w_order].ubound << 10; 570255736Sdavidch val += write_arb_data[NUM_WR_Q-1][w_order].l << 17; 571255736Sdavidch REG_WR(sc, PXP2_REG_PSWRQ_BW_RD, val); 572255736Sdavidch 573255736Sdavidch val = read_arb_data[NUM_RD_Q-1][r_order].add; 574255736Sdavidch val += read_arb_data[NUM_RD_Q-1][r_order].ubound << 10; 575255736Sdavidch val += read_arb_data[NUM_RD_Q-1][r_order].l << 17; 576255736Sdavidch REG_WR(sc, PXP2_REG_PSWRQ_BW_WR, val); 577255736Sdavidch 578255736Sdavidch REG_WR(sc, PXP2_REG_RQ_WR_MBS0, w_order); 579255736Sdavidch REG_WR(sc, PXP2_REG_RQ_WR_MBS1, w_order); 580255736Sdavidch REG_WR(sc, PXP2_REG_RQ_RD_MBS0, r_order); 581255736Sdavidch REG_WR(sc, PXP2_REG_RQ_RD_MBS1, r_order); 582255736Sdavidch 583255736Sdavidch if ((CHIP_IS_E1(sc) || CHIP_IS_E1H(sc)) && (r_order == MAX_RD_ORD)) 584255736Sdavidch REG_WR(sc, PXP2_REG_RQ_PDR_LIMIT, 0xe00); 585255736Sdavidch 586255736Sdavidch if (CHIP_IS_E3(sc)) 587255736Sdavidch REG_WR(sc, PXP2_REG_WR_USDMDP_TH, (0x4 << w_order)); 588255736Sdavidch else if (CHIP_IS_E2(sc)) 589255736Sdavidch REG_WR(sc, PXP2_REG_WR_USDMDP_TH, (0x8 << w_order)); 590255736Sdavidch else 591255736Sdavidch REG_WR(sc, PXP2_REG_WR_USDMDP_TH, (0x18 << w_order)); 592255736Sdavidch 593255736Sdavidch if (!CHIP_IS_E1(sc)) { 594255736Sdavidch /* MPS w_order optimal TH presently TH 595255736Sdavidch * 128 0 0 2 596255736Sdavidch * 256 1 1 3 597255736Sdavidch * >=512 2 2 3 598255736Sdavidch */ 599255736Sdavidch /* DMAE is special */ 600255736Sdavidch if (!CHIP_IS_E1H(sc)) { 601255736Sdavidch /* E2 can use optimal TH */ 602255736Sdavidch val = w_order; 603255736Sdavidch REG_WR(sc, PXP2_REG_WR_DMAE_MPS, val); 604255736Sdavidch } else { 605255736Sdavidch val = ((w_order == 0) ? 2 : 3); 606255736Sdavidch REG_WR(sc, PXP2_REG_WR_DMAE_MPS, 2); 607255736Sdavidch } 608255736Sdavidch 609255736Sdavidch REG_WR(sc, PXP2_REG_WR_HC_MPS, val); 610255736Sdavidch REG_WR(sc, PXP2_REG_WR_USDM_MPS, val); 611255736Sdavidch REG_WR(sc, PXP2_REG_WR_CSDM_MPS, val); 612255736Sdavidch REG_WR(sc, PXP2_REG_WR_TSDM_MPS, val); 613255736Sdavidch REG_WR(sc, PXP2_REG_WR_XSDM_MPS, val); 614255736Sdavidch REG_WR(sc, PXP2_REG_WR_QM_MPS, val); 615255736Sdavidch REG_WR(sc, PXP2_REG_WR_TM_MPS, val); 616255736Sdavidch REG_WR(sc, PXP2_REG_WR_SRC_MPS, val); 617255736Sdavidch REG_WR(sc, PXP2_REG_WR_DBG_MPS, val); 618255736Sdavidch REG_WR(sc, PXP2_REG_WR_CDU_MPS, val); 619255736Sdavidch } 620255736Sdavidch 621255736Sdavidch /* Validate number of tags suppoted by device */ 622255736Sdavidch#define PCIE_REG_PCIER_TL_HDR_FC_ST 0x2980 623255736Sdavidch val = REG_RD(sc, PCIE_REG_PCIER_TL_HDR_FC_ST); 624255736Sdavidch val &= 0xFF; 625255736Sdavidch if (val <= 0x20) 626255736Sdavidch REG_WR(sc, PXP2_REG_PGL_TAGS_LIMIT, 0x20); 627255736Sdavidch} 628255736Sdavidch 629255736Sdavidch/**************************************************************************** 630255736Sdavidch* ILT management 631255736Sdavidch****************************************************************************/ 632255736Sdavidch/* 633255736Sdavidch * This codes hides the low level HW interaction for ILT management and 634255736Sdavidch * configuration. The API consists of a shadow ILT table which is set by the 635255736Sdavidch * driver and a set of routines to use it to configure the HW. 636255736Sdavidch * 637255736Sdavidch */ 638255736Sdavidch 639255736Sdavidch/* ILT HW init operations */ 640255736Sdavidch 641255736Sdavidch/* ILT memory management operations */ 642255736Sdavidch#define ILT_MEMOP_ALLOC 0 643255736Sdavidch#define ILT_MEMOP_FREE 1 644255736Sdavidch 645255736Sdavidch/* the phys address is shifted right 12 bits and has an added 646255736Sdavidch * 1=valid bit added to the 53rd bit 647255736Sdavidch * then since this is a wide register(TM) 648255736Sdavidch * we split it into two 32 bit writes 649255736Sdavidch */ 650255736Sdavidch#define ILT_ADDR1(x) ((uint32_t)(((uint64_t)x >> 12) & 0xFFFFFFFF)) 651255736Sdavidch#define ILT_ADDR2(x) ((uint32_t)((1 << 20) | ((uint64_t)x >> 44))) 652255736Sdavidch#define ILT_RANGE(f, l) (((l) << 10) | f) 653255736Sdavidch 654255736Sdavidchstatic int ecore_ilt_line_mem_op(struct bxe_softc *sc, 655255736Sdavidch struct ilt_line *line, uint32_t size, uint8_t memop) 656255736Sdavidch{ 657255736Sdavidch if (memop == ILT_MEMOP_FREE) { 658255736Sdavidch ECORE_ILT_FREE(line->page, line->page_mapping, line->size); 659255736Sdavidch return 0; 660255736Sdavidch } 661255736Sdavidch ECORE_ILT_ZALLOC(line->page, &line->page_mapping, size); 662255736Sdavidch if (!line->page) 663255736Sdavidch return -1; 664255736Sdavidch line->size = size; 665255736Sdavidch return 0; 666255736Sdavidch} 667255736Sdavidch 668255736Sdavidch 669255736Sdavidchstatic int ecore_ilt_client_mem_op(struct bxe_softc *sc, int cli_num, 670255736Sdavidch uint8_t memop) 671255736Sdavidch{ 672255736Sdavidch int i, rc; 673255736Sdavidch struct ecore_ilt *ilt = SC_ILT(sc); 674255736Sdavidch struct ilt_client_info *ilt_cli = &ilt->clients[cli_num]; 675255736Sdavidch 676255736Sdavidch if (!ilt || !ilt->lines) 677255736Sdavidch return -1; 678255736Sdavidch 679255736Sdavidch if (ilt_cli->flags & (ILT_CLIENT_SKIP_INIT | ILT_CLIENT_SKIP_MEM)) 680255736Sdavidch return 0; 681255736Sdavidch 682255736Sdavidch for (rc = 0, i = ilt_cli->start; i <= ilt_cli->end && !rc; i++) { 683255736Sdavidch rc = ecore_ilt_line_mem_op(sc, &ilt->lines[i], 684255736Sdavidch ilt_cli->page_size, memop); 685255736Sdavidch } 686255736Sdavidch return rc; 687255736Sdavidch} 688255736Sdavidch 689255736Sdavidchstatic inline int ecore_ilt_mem_op_cnic(struct bxe_softc *sc, uint8_t memop) 690255736Sdavidch{ 691255736Sdavidch int rc = 0; 692255736Sdavidch 693255736Sdavidch if (CONFIGURE_NIC_MODE(sc)) 694255736Sdavidch rc = ecore_ilt_client_mem_op(sc, ILT_CLIENT_SRC, memop); 695255736Sdavidch if (!rc) 696255736Sdavidch rc = ecore_ilt_client_mem_op(sc, ILT_CLIENT_TM, memop); 697255736Sdavidch 698255736Sdavidch return rc; 699255736Sdavidch} 700255736Sdavidch 701255736Sdavidchstatic int ecore_ilt_mem_op(struct bxe_softc *sc, uint8_t memop) 702255736Sdavidch{ 703255736Sdavidch int rc = ecore_ilt_client_mem_op(sc, ILT_CLIENT_CDU, memop); 704255736Sdavidch if (!rc) 705255736Sdavidch rc = ecore_ilt_client_mem_op(sc, ILT_CLIENT_QM, memop); 706255736Sdavidch if (!rc && CNIC_SUPPORT(sc) && !CONFIGURE_NIC_MODE(sc)) 707255736Sdavidch rc = ecore_ilt_client_mem_op(sc, ILT_CLIENT_SRC, memop); 708255736Sdavidch 709255736Sdavidch return rc; 710255736Sdavidch} 711255736Sdavidch 712255736Sdavidchstatic void ecore_ilt_line_wr(struct bxe_softc *sc, int abs_idx, 713255736Sdavidch ecore_dma_addr_t page_mapping) 714255736Sdavidch{ 715255736Sdavidch uint32_t reg; 716255736Sdavidch 717255736Sdavidch if (CHIP_IS_E1(sc)) 718255736Sdavidch reg = PXP2_REG_RQ_ONCHIP_AT + abs_idx*8; 719255736Sdavidch else 720255736Sdavidch reg = PXP2_REG_RQ_ONCHIP_AT_B0 + abs_idx*8; 721255736Sdavidch 722255736Sdavidch ecore_wr_64(sc, reg, ILT_ADDR1(page_mapping), ILT_ADDR2(page_mapping)); 723255736Sdavidch} 724255736Sdavidch 725255736Sdavidchstatic void ecore_ilt_line_init_op(struct bxe_softc *sc, 726255736Sdavidch struct ecore_ilt *ilt, int idx, uint8_t initop) 727255736Sdavidch{ 728255736Sdavidch ecore_dma_addr_t null_mapping; 729255736Sdavidch int abs_idx = ilt->start_line + idx; 730255736Sdavidch 731255736Sdavidch 732255736Sdavidch switch (initop) { 733255736Sdavidch case INITOP_INIT: 734255736Sdavidch /* set in the init-value array */ 735255736Sdavidch case INITOP_SET: 736255736Sdavidch ecore_ilt_line_wr(sc, abs_idx, ilt->lines[idx].page_mapping); 737255736Sdavidch break; 738255736Sdavidch case INITOP_CLEAR: 739255736Sdavidch null_mapping = 0; 740255736Sdavidch ecore_ilt_line_wr(sc, abs_idx, null_mapping); 741255736Sdavidch break; 742255736Sdavidch } 743255736Sdavidch} 744255736Sdavidch 745255736Sdavidchstatic void ecore_ilt_boundry_init_op(struct bxe_softc *sc, 746255736Sdavidch struct ilt_client_info *ilt_cli, 747255736Sdavidch uint32_t ilt_start, uint8_t initop) 748255736Sdavidch{ 749255736Sdavidch uint32_t start_reg = 0; 750255736Sdavidch uint32_t end_reg = 0; 751255736Sdavidch 752255736Sdavidch /* The boundary is either SET or INIT, 753255736Sdavidch CLEAR => SET and for now SET ~~ INIT */ 754255736Sdavidch 755255736Sdavidch /* find the appropriate regs */ 756255736Sdavidch if (CHIP_IS_E1(sc)) { 757255736Sdavidch switch (ilt_cli->client_num) { 758255736Sdavidch case ILT_CLIENT_CDU: 759255736Sdavidch start_reg = PXP2_REG_PSWRQ_CDU0_L2P; 760255736Sdavidch break; 761255736Sdavidch case ILT_CLIENT_QM: 762255736Sdavidch start_reg = PXP2_REG_PSWRQ_QM0_L2P; 763255736Sdavidch break; 764255736Sdavidch case ILT_CLIENT_SRC: 765255736Sdavidch start_reg = PXP2_REG_PSWRQ_SRC0_L2P; 766255736Sdavidch break; 767255736Sdavidch case ILT_CLIENT_TM: 768255736Sdavidch start_reg = PXP2_REG_PSWRQ_TM0_L2P; 769255736Sdavidch break; 770255736Sdavidch } 771255736Sdavidch REG_WR(sc, start_reg + SC_FUNC(sc)*4, 772255736Sdavidch ILT_RANGE((ilt_start + ilt_cli->start), 773255736Sdavidch (ilt_start + ilt_cli->end))); 774255736Sdavidch } else { 775255736Sdavidch switch (ilt_cli->client_num) { 776255736Sdavidch case ILT_CLIENT_CDU: 777255736Sdavidch start_reg = PXP2_REG_RQ_CDU_FIRST_ILT; 778255736Sdavidch end_reg = PXP2_REG_RQ_CDU_LAST_ILT; 779255736Sdavidch break; 780255736Sdavidch case ILT_CLIENT_QM: 781255736Sdavidch start_reg = PXP2_REG_RQ_QM_FIRST_ILT; 782255736Sdavidch end_reg = PXP2_REG_RQ_QM_LAST_ILT; 783255736Sdavidch break; 784255736Sdavidch case ILT_CLIENT_SRC: 785255736Sdavidch start_reg = PXP2_REG_RQ_SRC_FIRST_ILT; 786255736Sdavidch end_reg = PXP2_REG_RQ_SRC_LAST_ILT; 787255736Sdavidch break; 788255736Sdavidch case ILT_CLIENT_TM: 789255736Sdavidch start_reg = PXP2_REG_RQ_TM_FIRST_ILT; 790255736Sdavidch end_reg = PXP2_REG_RQ_TM_LAST_ILT; 791255736Sdavidch break; 792255736Sdavidch } 793255736Sdavidch REG_WR(sc, start_reg, (ilt_start + ilt_cli->start)); 794255736Sdavidch REG_WR(sc, end_reg, (ilt_start + ilt_cli->end)); 795255736Sdavidch } 796255736Sdavidch} 797255736Sdavidch 798255736Sdavidchstatic void ecore_ilt_client_init_op_ilt(struct bxe_softc *sc, 799255736Sdavidch struct ecore_ilt *ilt, 800255736Sdavidch struct ilt_client_info *ilt_cli, 801255736Sdavidch uint8_t initop) 802255736Sdavidch{ 803255736Sdavidch int i; 804255736Sdavidch 805255736Sdavidch if (ilt_cli->flags & ILT_CLIENT_SKIP_INIT) 806255736Sdavidch return; 807255736Sdavidch 808255736Sdavidch for (i = ilt_cli->start; i <= ilt_cli->end; i++) 809255736Sdavidch ecore_ilt_line_init_op(sc, ilt, i, initop); 810255736Sdavidch 811255736Sdavidch /* init/clear the ILT boundries */ 812255736Sdavidch ecore_ilt_boundry_init_op(sc, ilt_cli, ilt->start_line, initop); 813255736Sdavidch} 814255736Sdavidch 815255736Sdavidchstatic void ecore_ilt_client_init_op(struct bxe_softc *sc, 816255736Sdavidch struct ilt_client_info *ilt_cli, uint8_t initop) 817255736Sdavidch{ 818255736Sdavidch struct ecore_ilt *ilt = SC_ILT(sc); 819255736Sdavidch 820255736Sdavidch ecore_ilt_client_init_op_ilt(sc, ilt, ilt_cli, initop); 821255736Sdavidch} 822255736Sdavidch 823255736Sdavidchstatic void ecore_ilt_client_id_init_op(struct bxe_softc *sc, 824255736Sdavidch int cli_num, uint8_t initop) 825255736Sdavidch{ 826255736Sdavidch struct ecore_ilt *ilt = SC_ILT(sc); 827255736Sdavidch struct ilt_client_info *ilt_cli = &ilt->clients[cli_num]; 828255736Sdavidch 829255736Sdavidch ecore_ilt_client_init_op(sc, ilt_cli, initop); 830255736Sdavidch} 831255736Sdavidch 832255736Sdavidchstatic inline void ecore_ilt_init_op_cnic(struct bxe_softc *sc, uint8_t initop) 833255736Sdavidch{ 834255736Sdavidch if (CONFIGURE_NIC_MODE(sc)) 835255736Sdavidch ecore_ilt_client_id_init_op(sc, ILT_CLIENT_SRC, initop); 836255736Sdavidch ecore_ilt_client_id_init_op(sc, ILT_CLIENT_TM, initop); 837255736Sdavidch} 838255736Sdavidch 839255736Sdavidchstatic void ecore_ilt_init_op(struct bxe_softc *sc, uint8_t initop) 840255736Sdavidch{ 841255736Sdavidch ecore_ilt_client_id_init_op(sc, ILT_CLIENT_CDU, initop); 842255736Sdavidch ecore_ilt_client_id_init_op(sc, ILT_CLIENT_QM, initop); 843255736Sdavidch if (CNIC_SUPPORT(sc) && !CONFIGURE_NIC_MODE(sc)) 844255736Sdavidch ecore_ilt_client_id_init_op(sc, ILT_CLIENT_SRC, initop); 845255736Sdavidch} 846255736Sdavidch 847255736Sdavidchstatic void ecore_ilt_init_client_psz(struct bxe_softc *sc, int cli_num, 848255736Sdavidch uint32_t psz_reg, uint8_t initop) 849255736Sdavidch{ 850255736Sdavidch struct ecore_ilt *ilt = SC_ILT(sc); 851255736Sdavidch struct ilt_client_info *ilt_cli = &ilt->clients[cli_num]; 852255736Sdavidch 853255736Sdavidch if (ilt_cli->flags & ILT_CLIENT_SKIP_INIT) 854255736Sdavidch return; 855255736Sdavidch 856255736Sdavidch switch (initop) { 857255736Sdavidch case INITOP_INIT: 858255736Sdavidch /* set in the init-value array */ 859255736Sdavidch case INITOP_SET: 860255736Sdavidch REG_WR(sc, psz_reg, ILOG2(ilt_cli->page_size >> 12)); 861255736Sdavidch break; 862255736Sdavidch case INITOP_CLEAR: 863255736Sdavidch break; 864255736Sdavidch } 865255736Sdavidch} 866255736Sdavidch 867255736Sdavidch/* 868255736Sdavidch * called during init common stage, ilt clients should be initialized 869255736Sdavidch * prioir to calling this function 870255736Sdavidch */ 871255736Sdavidchstatic void ecore_ilt_init_page_size(struct bxe_softc *sc, uint8_t initop) 872255736Sdavidch{ 873255736Sdavidch ecore_ilt_init_client_psz(sc, ILT_CLIENT_CDU, 874255736Sdavidch PXP2_REG_RQ_CDU_P_SIZE, initop); 875255736Sdavidch ecore_ilt_init_client_psz(sc, ILT_CLIENT_QM, 876255736Sdavidch PXP2_REG_RQ_QM_P_SIZE, initop); 877255736Sdavidch ecore_ilt_init_client_psz(sc, ILT_CLIENT_SRC, 878255736Sdavidch PXP2_REG_RQ_SRC_P_SIZE, initop); 879255736Sdavidch ecore_ilt_init_client_psz(sc, ILT_CLIENT_TM, 880255736Sdavidch PXP2_REG_RQ_TM_P_SIZE, initop); 881255736Sdavidch} 882255736Sdavidch 883255736Sdavidch/**************************************************************************** 884255736Sdavidch* QM initializations 885255736Sdavidch****************************************************************************/ 886255736Sdavidch#define QM_QUEUES_PER_FUNC 16 /* E1 has 32, but only 16 are used */ 887255736Sdavidch#define QM_INIT_MIN_CID_COUNT 31 888255736Sdavidch#define QM_INIT(cid_cnt) (cid_cnt > QM_INIT_MIN_CID_COUNT) 889255736Sdavidch 890255736Sdavidch/* called during init port stage */ 891255736Sdavidchstatic void ecore_qm_init_cid_count(struct bxe_softc *sc, int qm_cid_count, 892255736Sdavidch uint8_t initop) 893255736Sdavidch{ 894255736Sdavidch int port = SC_PORT(sc); 895255736Sdavidch 896255736Sdavidch if (QM_INIT(qm_cid_count)) { 897255736Sdavidch switch (initop) { 898255736Sdavidch case INITOP_INIT: 899255736Sdavidch /* set in the init-value array */ 900255736Sdavidch case INITOP_SET: 901255736Sdavidch REG_WR(sc, QM_REG_CONNNUM_0 + port*4, 902255736Sdavidch qm_cid_count/16 - 1); 903255736Sdavidch break; 904255736Sdavidch case INITOP_CLEAR: 905255736Sdavidch break; 906255736Sdavidch } 907255736Sdavidch } 908255736Sdavidch} 909255736Sdavidch 910255736Sdavidchstatic void ecore_qm_set_ptr_table(struct bxe_softc *sc, int qm_cid_count, 911255736Sdavidch uint32_t base_reg, uint32_t reg) 912255736Sdavidch{ 913255736Sdavidch int i; 914255736Sdavidch uint32_t wb_data[2] = {0, 0}; 915255736Sdavidch for (i = 0; i < 4 * QM_QUEUES_PER_FUNC; i++) { 916255736Sdavidch REG_WR(sc, base_reg + i*4, 917255736Sdavidch qm_cid_count * 4 * (i % QM_QUEUES_PER_FUNC)); 918255736Sdavidch ecore_init_wr_wb(sc, reg + i*8, 919255736Sdavidch wb_data, 2); 920255736Sdavidch } 921255736Sdavidch} 922255736Sdavidch 923255736Sdavidch/* called during init common stage */ 924255736Sdavidchstatic void ecore_qm_init_ptr_table(struct bxe_softc *sc, int qm_cid_count, 925255736Sdavidch uint8_t initop) 926255736Sdavidch{ 927255736Sdavidch if (!QM_INIT(qm_cid_count)) 928255736Sdavidch return; 929255736Sdavidch 930255736Sdavidch switch (initop) { 931255736Sdavidch case INITOP_INIT: 932255736Sdavidch /* set in the init-value array */ 933255736Sdavidch case INITOP_SET: 934255736Sdavidch ecore_qm_set_ptr_table(sc, qm_cid_count, 935255736Sdavidch QM_REG_BASEADDR, QM_REG_PTRTBL); 936255736Sdavidch if (CHIP_IS_E1H(sc)) 937255736Sdavidch ecore_qm_set_ptr_table(sc, qm_cid_count, 938255736Sdavidch QM_REG_BASEADDR_EXT_A, 939255736Sdavidch QM_REG_PTRTBL_EXT_A); 940255736Sdavidch break; 941255736Sdavidch case INITOP_CLEAR: 942255736Sdavidch break; 943255736Sdavidch } 944255736Sdavidch} 945255736Sdavidch 946255736Sdavidch/**************************************************************************** 947255736Sdavidch* SRC initializations 948255736Sdavidch****************************************************************************/ 949255736Sdavidch#ifdef ECORE_L5 950255736Sdavidch/* called during init func stage */ 951255736Sdavidchstatic void ecore_src_init_t2(struct bxe_softc *sc, struct src_ent *t2, 952255736Sdavidch ecore_dma_addr_t t2_mapping, int src_cid_count) 953255736Sdavidch{ 954255736Sdavidch int i; 955255736Sdavidch int port = SC_PORT(sc); 956255736Sdavidch 957255736Sdavidch /* Initialize T2 */ 958255736Sdavidch for (i = 0; i < src_cid_count-1; i++) 959255736Sdavidch t2[i].next = (uint64_t)(t2_mapping + 960255736Sdavidch (i+1)*sizeof(struct src_ent)); 961255736Sdavidch 962255736Sdavidch /* tell the searcher where the T2 table is */ 963255736Sdavidch REG_WR(sc, SRC_REG_COUNTFREE0 + port*4, src_cid_count); 964255736Sdavidch 965255736Sdavidch ecore_wr_64(sc, SRC_REG_FIRSTFREE0 + port*16, 966255736Sdavidch U64_LO(t2_mapping), U64_HI(t2_mapping)); 967255736Sdavidch 968255736Sdavidch ecore_wr_64(sc, SRC_REG_LASTFREE0 + port*16, 969255736Sdavidch U64_LO((uint64_t)t2_mapping + 970255736Sdavidch (src_cid_count-1) * sizeof(struct src_ent)), 971255736Sdavidch U64_HI((uint64_t)t2_mapping + 972255736Sdavidch (src_cid_count-1) * sizeof(struct src_ent))); 973255736Sdavidch} 974255736Sdavidch#endif 975255736Sdavidch#endif /* ECORE_INIT_OPS_H */ 976