1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (C) 2018 Marvell International Ltd. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu * https://spdx.org/licenses 6*91f16700Schasinglulu */ 7*91f16700Schasinglulu 8*91f16700Schasinglulu /* MCI bus driver for Marvell ARMADA 8K and 8K+ SoCs */ 9*91f16700Schasinglulu 10*91f16700Schasinglulu #include <common/debug.h> 11*91f16700Schasinglulu #include <drivers/delay_timer.h> 12*91f16700Schasinglulu #include <drivers/marvell/mci.h> 13*91f16700Schasinglulu #include <lib/mmio.h> 14*91f16700Schasinglulu 15*91f16700Schasinglulu #include <mvebu.h> 16*91f16700Schasinglulu #include <mvebu_def.h> 17*91f16700Schasinglulu #include <plat_marvell.h> 18*91f16700Schasinglulu 19*91f16700Schasinglulu /* /HB /Units /Direct_regs /Direct regs 20*91f16700Schasinglulu * /Configuration Register Write/Read Data Register 21*91f16700Schasinglulu */ 22*91f16700Schasinglulu #define MCI_WRITE_READ_DATA_REG(mci_index) \ 23*91f16700Schasinglulu MVEBU_MCI_REG_BASE_REMAP(mci_index) 24*91f16700Schasinglulu /* /HB /Units /Direct_regs /Direct regs 25*91f16700Schasinglulu * /Configuration Register Access Command Register 26*91f16700Schasinglulu */ 27*91f16700Schasinglulu #define MCI_ACCESS_CMD_REG(mci_index) \ 28*91f16700Schasinglulu (MVEBU_MCI_REG_BASE_REMAP(mci_index) + 0x4) 29*91f16700Schasinglulu 30*91f16700Schasinglulu /* Access Command fields : 31*91f16700Schasinglulu * bit[3:0] - Sub command: 1 => Peripheral Config Register Read, 32*91f16700Schasinglulu * 0 => Peripheral Config Register Write, 33*91f16700Schasinglulu * 2 => Peripheral Assign ID request, 34*91f16700Schasinglulu * 3 => Circular Config Write 35*91f16700Schasinglulu * bit[5] - 1 => Local (same chip access) 0 => Remote 36*91f16700Schasinglulu * bit[15:8] - Destination hop ID. Put Global ID (GID) here (see scheme below). 37*91f16700Schasinglulu * bit[23:22] - 0x3 IHB PHY REG address space, 0x0 IHB Controller space 38*91f16700Schasinglulu * bit[21:16] - Low 6 bits of offset. Hight 2 bits are taken from bit[28:27] 39*91f16700Schasinglulu * of IHB_PHY_CTRL 40*91f16700Schasinglulu * (must be set before any PHY register access occurs): 41*91f16700Schasinglulu * /IHB_REG /IHB_REGInterchip Hopping Bus Registers 42*91f16700Schasinglulu * /IHB Version Control Register 43*91f16700Schasinglulu * 44*91f16700Schasinglulu * ixi_ihb_top IHB PHY 45*91f16700Schasinglulu * AXI ----------------------------- ------------- 46*91f16700Schasinglulu * <--| axi_hb_top | ihb_pipe_top |-->| | 47*91f16700Schasinglulu * -->| GID=1 | GID=0 |<--| | 48*91f16700Schasinglulu * ----------------------------- ------------- 49*91f16700Schasinglulu */ 50*91f16700Schasinglulu #define MCI_INDIRECT_CTRL_READ_CMD 0x1 51*91f16700Schasinglulu #define MCI_INDIRECT_CTRL_ASSIGN_CMD 0x2 52*91f16700Schasinglulu #define MCI_INDIRECT_CTRL_CIRCULAR_CMD 0x3 53*91f16700Schasinglulu #define MCI_INDIRECT_CTRL_LOCAL_PKT (1 << 5) 54*91f16700Schasinglulu #define MCI_INDIRECT_CTRL_CMD_DONE_OFFSET 6 55*91f16700Schasinglulu #define MCI_INDIRECT_CTRL_CMD_DONE \ 56*91f16700Schasinglulu (1 << MCI_INDIRECT_CTRL_CMD_DONE_OFFSET) 57*91f16700Schasinglulu #define MCI_INDIRECT_CTRL_DATA_READY_OFFSET 7 58*91f16700Schasinglulu #define MCI_INDIRECT_CTRL_DATA_READY \ 59*91f16700Schasinglulu (1 << MCI_INDIRECT_CTRL_DATA_READY_OFFSET) 60*91f16700Schasinglulu #define MCI_INDIRECT_CTRL_HOPID_OFFSET 8 61*91f16700Schasinglulu #define MCI_INDIRECT_CTRL_HOPID(id) \ 62*91f16700Schasinglulu (((id) & 0xFF) << MCI_INDIRECT_CTRL_HOPID_OFFSET) 63*91f16700Schasinglulu #define MCI_INDIRECT_CTRL_REG_CHIPID_OFFSET 16 64*91f16700Schasinglulu #define MCI_INDIRECT_REG_CTRL_ADDR(reg_num) \ 65*91f16700Schasinglulu (reg_num << MCI_INDIRECT_CTRL_REG_CHIPID_OFFSET) 66*91f16700Schasinglulu 67*91f16700Schasinglulu /* Hop ID values */ 68*91f16700Schasinglulu #define GID_IHB_PIPE 0 69*91f16700Schasinglulu #define GID_AXI_HB 1 70*91f16700Schasinglulu #define GID_IHB_EXT 2 71*91f16700Schasinglulu 72*91f16700Schasinglulu #define MCI_DID_GLOBAL_ASSIGNMENT_REQUEST_REG 0x2 73*91f16700Schasinglulu /* Target MCi Local ID (LID, which is = self DID) */ 74*91f16700Schasinglulu #define MCI_DID_GLOBAL_ASSIGN_REQ_MCI_LOCAL_ID(val) (((val) & 0xFF) << 16) 75*91f16700Schasinglulu /* Bits [15:8]: Number of MCis on chip of target MCi */ 76*91f16700Schasinglulu #define MCI_DID_GLOBAL_ASSIGN_REQ_MCI_COUNT(val) (((val) & 0xFF) << 8) 77*91f16700Schasinglulu /* Bits [7:0]: Number of hops on chip of target MCi */ 78*91f16700Schasinglulu #define MCI_DID_GLOBAL_ASSIGN_REQ_HOPS_NUM(val) (((val) & 0xFF) << 0) 79*91f16700Schasinglulu 80*91f16700Schasinglulu /* IHB_REG domain registers */ 81*91f16700Schasinglulu /* /HB /Units /IHB_REG /IHB_REGInterchip Hopping Bus Registers/ 82*91f16700Schasinglulu * Rx Memory Configuration Register (RX_MEM_CFG) 83*91f16700Schasinglulu */ 84*91f16700Schasinglulu #define MCI_CTRL_RX_MEM_CFG_REG_NUM 0x0 85*91f16700Schasinglulu #define MCI_CTRL_RX_TX_MEM_CFG_RQ_THRESH(val) (((val) & 0xFF) << 24) 86*91f16700Schasinglulu #define MCI_CTRL_RX_TX_MEM_CFG_PQ_THRESH(val) (((val) & 0xFF) << 16) 87*91f16700Schasinglulu #define MCI_CTRL_RX_TX_MEM_CFG_NQ_THRESH(val) (((val) & 0xFF) << 8) 88*91f16700Schasinglulu #define MCI_CTRL_RX_TX_MEM_CFG_DELTA_THRESH(val) (((val) & 0xF) << 4) 89*91f16700Schasinglulu #define MCI_CTRL_RX_TX_MEM_CFG_RTC(val) (((val) & 0x3) << 2) 90*91f16700Schasinglulu #define MCI_CTRL_RX_TX_MEM_CFG_WTC(val) (((val) & 0x3) << 0) 91*91f16700Schasinglulu #define MCI_CTRL_RX_MEM_CFG_REG_DEF_CP_VAL \ 92*91f16700Schasinglulu (MCI_CTRL_RX_TX_MEM_CFG_RQ_THRESH(0x07) | \ 93*91f16700Schasinglulu MCI_CTRL_RX_TX_MEM_CFG_PQ_THRESH(0x3f) | \ 94*91f16700Schasinglulu MCI_CTRL_RX_TX_MEM_CFG_NQ_THRESH(0x3f) | \ 95*91f16700Schasinglulu MCI_CTRL_RX_TX_MEM_CFG_DELTA_THRESH(0xf) | \ 96*91f16700Schasinglulu MCI_CTRL_RX_TX_MEM_CFG_RTC(1) | \ 97*91f16700Schasinglulu MCI_CTRL_RX_TX_MEM_CFG_WTC(1)) 98*91f16700Schasinglulu 99*91f16700Schasinglulu #define MCI_CTRL_RX_MEM_CFG_REG_DEF_AP_VAL \ 100*91f16700Schasinglulu (MCI_CTRL_RX_TX_MEM_CFG_RQ_THRESH(0x3f) | \ 101*91f16700Schasinglulu MCI_CTRL_RX_TX_MEM_CFG_PQ_THRESH(0x03) | \ 102*91f16700Schasinglulu MCI_CTRL_RX_TX_MEM_CFG_NQ_THRESH(0x3f) | \ 103*91f16700Schasinglulu MCI_CTRL_RX_TX_MEM_CFG_DELTA_THRESH(0xf) | \ 104*91f16700Schasinglulu MCI_CTRL_RX_TX_MEM_CFG_RTC(1) | \ 105*91f16700Schasinglulu MCI_CTRL_RX_TX_MEM_CFG_WTC(1)) 106*91f16700Schasinglulu 107*91f16700Schasinglulu 108*91f16700Schasinglulu /* /HB /Units /IHB_REG /IHB_REGInterchip Hopping Bus Registers/ 109*91f16700Schasinglulu * Tx Memory Configuration Register (TX_MEM_CFG) 110*91f16700Schasinglulu */ 111*91f16700Schasinglulu #define MCI_CTRL_TX_MEM_CFG_REG_NUM 0x1 112*91f16700Schasinglulu /* field mapping for TX mem config register 113*91f16700Schasinglulu * are the same as for RX register - see register above 114*91f16700Schasinglulu */ 115*91f16700Schasinglulu #define MCI_CTRL_TX_MEM_CFG_REG_DEF_VAL \ 116*91f16700Schasinglulu (MCI_CTRL_RX_TX_MEM_CFG_RQ_THRESH(0x20) | \ 117*91f16700Schasinglulu MCI_CTRL_RX_TX_MEM_CFG_PQ_THRESH(0x20) | \ 118*91f16700Schasinglulu MCI_CTRL_RX_TX_MEM_CFG_NQ_THRESH(0x20) | \ 119*91f16700Schasinglulu MCI_CTRL_RX_TX_MEM_CFG_DELTA_THRESH(2) | \ 120*91f16700Schasinglulu MCI_CTRL_RX_TX_MEM_CFG_RTC(1) | \ 121*91f16700Schasinglulu MCI_CTRL_RX_TX_MEM_CFG_WTC(1)) 122*91f16700Schasinglulu 123*91f16700Schasinglulu /* /HB /Units /IHB_REG /IHB_REGInterchip Hopping Bus Registers 124*91f16700Schasinglulu * /IHB Link CRC Control 125*91f16700Schasinglulu */ 126*91f16700Schasinglulu /* MCi Link CRC Control Register (MCi_CRC_CTRL) */ 127*91f16700Schasinglulu #define MCI_LINK_CRC_CTRL_REG_NUM 0x4 128*91f16700Schasinglulu 129*91f16700Schasinglulu /* /HB /Units /IHB_REG /IHB_REGInterchip Hopping Bus Registers 130*91f16700Schasinglulu * /IHB Status Register 131*91f16700Schasinglulu */ 132*91f16700Schasinglulu /* MCi Status Register (MCi_STS) */ 133*91f16700Schasinglulu #define MCI_CTRL_STATUS_REG_NUM 0x5 134*91f16700Schasinglulu #define MCI_CTRL_STATUS_REG_PHY_READY (1 << 12) 135*91f16700Schasinglulu #define MCI_CTRL_STATUS_REG_LINK_PRESENT (1 << 15) 136*91f16700Schasinglulu #define MCI_CTRL_STATUS_REG_PHY_CID_VIO_OFFSET 24 137*91f16700Schasinglulu #define MCI_CTRL_STATUS_REG_PHY_CID_VIO_MASK \ 138*91f16700Schasinglulu (0xF << MCI_CTRL_STATUS_REG_PHY_CID_VIO_OFFSET) 139*91f16700Schasinglulu /* Expected successful Link result, including reserved bit */ 140*91f16700Schasinglulu #define MCI_CTRL_PHY_READY (MCI_CTRL_STATUS_REG_PHY_READY | \ 141*91f16700Schasinglulu MCI_CTRL_STATUS_REG_LINK_PRESENT | \ 142*91f16700Schasinglulu MCI_CTRL_STATUS_REG_PHY_CID_VIO_MASK) 143*91f16700Schasinglulu 144*91f16700Schasinglulu /* /HB /Units /IHB_REG /IHB_REGInterchip Hopping Bus Registers/ 145*91f16700Schasinglulu * MCi PHY Speed Settings Register (MCi_PHY_SETTING) 146*91f16700Schasinglulu */ 147*91f16700Schasinglulu #define MCI_CTRL_MCI_PHY_SETTINGS_REG_NUM 0x8 148*91f16700Schasinglulu #define MCI_CTRL_MCI_PHY_SET_DLO_FIFO_FULL_TRESH(val) (((val) & 0xF) << 28) 149*91f16700Schasinglulu #define MCI_CTRL_MCI_PHY_SET_PHY_MAX_SPEED(val) (((val) & 0xF) << 12) 150*91f16700Schasinglulu #define MCI_CTRL_MCI_PHY_SET_PHYCLK_SEL(val) (((val) & 0xF) << 8) 151*91f16700Schasinglulu #define MCI_CTRL_MCI_PHY_SET_REFCLK_FREQ_SEL(val) (((val) & 0xF) << 4) 152*91f16700Schasinglulu #define MCI_CTRL_MCI_PHY_SET_AUTO_LINK_EN(val) (((val) & 0x1) << 1) 153*91f16700Schasinglulu #define MCI_CTRL_MCI_PHY_SET_REG_DEF_VAL \ 154*91f16700Schasinglulu (MCI_CTRL_MCI_PHY_SET_DLO_FIFO_FULL_TRESH(0x3) | \ 155*91f16700Schasinglulu MCI_CTRL_MCI_PHY_SET_PHY_MAX_SPEED(0x3) | \ 156*91f16700Schasinglulu MCI_CTRL_MCI_PHY_SET_PHYCLK_SEL(0x2) | \ 157*91f16700Schasinglulu MCI_CTRL_MCI_PHY_SET_REFCLK_FREQ_SEL(0x1)) 158*91f16700Schasinglulu #define MCI_CTRL_MCI_PHY_SET_REG_DEF_VAL2 \ 159*91f16700Schasinglulu (MCI_CTRL_MCI_PHY_SET_DLO_FIFO_FULL_TRESH(0x3) | \ 160*91f16700Schasinglulu MCI_CTRL_MCI_PHY_SET_PHY_MAX_SPEED(0x3) | \ 161*91f16700Schasinglulu MCI_CTRL_MCI_PHY_SET_PHYCLK_SEL(0x5) | \ 162*91f16700Schasinglulu MCI_CTRL_MCI_PHY_SET_REFCLK_FREQ_SEL(0x1)) 163*91f16700Schasinglulu 164*91f16700Schasinglulu /* /HB /Units /IHB_REG /IHB_REGInterchip Hopping Bus Registers 165*91f16700Schasinglulu * /IHB Mode Config 166*91f16700Schasinglulu */ 167*91f16700Schasinglulu #define MCI_CTRL_IHB_MODE_CFG_REG_NUM 0x25 168*91f16700Schasinglulu #define MCI_CTRL_IHB_MODE_HBCLK_DIV(val) ((val) & 0xFF) 169*91f16700Schasinglulu #define MCI_CTRL_IHB_MODE_CHUNK_MOD_OFFSET 8 170*91f16700Schasinglulu #define MCI_CTRL_IHB_MODE_CHUNK_MOD \ 171*91f16700Schasinglulu (1 << MCI_CTRL_IHB_MODE_CHUNK_MOD_OFFSET) 172*91f16700Schasinglulu #define MCI_CTRL_IHB_MODE_FWD_MOD_OFFSET 9 173*91f16700Schasinglulu #define MCI_CTRL_IHB_MODE_FWD_MOD \ 174*91f16700Schasinglulu (1 << MCI_CTRL_IHB_MODE_FWD_MOD_OFFSET) 175*91f16700Schasinglulu #define MCI_CTRL_IHB_MODE_SEQFF_FINE_MOD(val) (((val) & 0xF) << 12) 176*91f16700Schasinglulu #define MCI_CTRL_IHB_MODE_RX_COMB_THRESH(val) (((val) & 0xFF) << 16) 177*91f16700Schasinglulu #define MCI_CTRL_IHB_MODE_TX_COMB_THRESH(val) (((val) & 0xFF) << 24) 178*91f16700Schasinglulu 179*91f16700Schasinglulu #define MCI_CTRL_IHB_MODE_CFG_REG_DEF_VAL \ 180*91f16700Schasinglulu (MCI_CTRL_IHB_MODE_HBCLK_DIV(6) | \ 181*91f16700Schasinglulu MCI_CTRL_IHB_MODE_FWD_MOD | \ 182*91f16700Schasinglulu MCI_CTRL_IHB_MODE_SEQFF_FINE_MOD(0xF) | \ 183*91f16700Schasinglulu MCI_CTRL_IHB_MODE_RX_COMB_THRESH(0x3f) | \ 184*91f16700Schasinglulu MCI_CTRL_IHB_MODE_TX_COMB_THRESH(0x40)) 185*91f16700Schasinglulu /* AXI_HB registers */ 186*91f16700Schasinglulu #define MCI_AXI_ACCESS_DATA_REG_NUM 0x0 187*91f16700Schasinglulu #define MCI_AXI_ACCESS_PCIE_MODE 1 188*91f16700Schasinglulu #define MCI_AXI_ACCESS_CACHE_CHECK_OFFSET 5 189*91f16700Schasinglulu #define MCI_AXI_ACCESS_CACHE_CHECK \ 190*91f16700Schasinglulu (1 << MCI_AXI_ACCESS_CACHE_CHECK_OFFSET) 191*91f16700Schasinglulu #define MCI_AXI_ACCESS_FORCE_POST_WR_OFFSET 6 192*91f16700Schasinglulu #define MCI_AXI_ACCESS_FORCE_POST_WR \ 193*91f16700Schasinglulu (1 << MCI_AXI_ACCESS_FORCE_POST_WR_OFFSET) 194*91f16700Schasinglulu #define MCI_AXI_ACCESS_DISABLE_CLK_GATING_OFFSET 9 195*91f16700Schasinglulu #define MCI_AXI_ACCESS_DISABLE_CLK_GATING \ 196*91f16700Schasinglulu (1 << MCI_AXI_ACCESS_DISABLE_CLK_GATING_OFFSET) 197*91f16700Schasinglulu 198*91f16700Schasinglulu /* /HB /Units /HB_REG /HB_REGHopping Bus Registers 199*91f16700Schasinglulu * /Window 0 Address Mask Register 200*91f16700Schasinglulu */ 201*91f16700Schasinglulu #define MCI_HB_CTRL_WIN0_ADDRESS_MASK_REG_NUM 0x2 202*91f16700Schasinglulu 203*91f16700Schasinglulu /* /HB /Units /HB_REG /HB_REGHopping Bus Registers 204*91f16700Schasinglulu * /Window 0 Destination Register 205*91f16700Schasinglulu */ 206*91f16700Schasinglulu #define MCI_HB_CTRL_WIN0_DESTINATION_REG_NUM 0x3 207*91f16700Schasinglulu #define MCI_HB_CTRL_WIN0_DEST_VALID_FLAG(val) (((val) & 0x1) << 16) 208*91f16700Schasinglulu #define MCI_HB_CTRL_WIN0_DEST_ID(val) (((val) & 0xFF) << 0) 209*91f16700Schasinglulu 210*91f16700Schasinglulu /* /HB /Units /HB_REG /HB_REGHopping Bus Registers /Tx Control Register */ 211*91f16700Schasinglulu #define MCI_HB_CTRL_TX_CTRL_REG_NUM 0xD 212*91f16700Schasinglulu #define MCI_HB_CTRL_TX_CTRL_PCIE_MODE_OFFSET 24 213*91f16700Schasinglulu #define MCI_HB_CTRL_TX_CTRL_PCIE_MODE \ 214*91f16700Schasinglulu (1 << MCI_HB_CTRL_TX_CTRL_PCIE_MODE_OFFSET) 215*91f16700Schasinglulu #define MCI_HB_CTRL_TX_CTRL_PRI_TH_QOS(val) (((val) & 0xF) << 12) 216*91f16700Schasinglulu #define MCI_HB_CTRL_TX_CTRL_MAX_RD_CNT(val) (((val) & 0x1F) << 6) 217*91f16700Schasinglulu #define MCI_HB_CTRL_TX_CTRL_MAX_WR_CNT(val) (((val) & 0x1F) << 0) 218*91f16700Schasinglulu 219*91f16700Schasinglulu /* /HB /Units /IHB_REG /IHB_REGInterchip Hopping Bus Registers 220*91f16700Schasinglulu * /IHB Version Control Register 221*91f16700Schasinglulu */ 222*91f16700Schasinglulu #define MCI_PHY_CTRL_REG_NUM 0x7 223*91f16700Schasinglulu #define MCI_PHY_CTRL_MCI_MINOR 0x8 /* BITS [3:0] */ 224*91f16700Schasinglulu #define MCI_PHY_CTRL_MCI_MAJOR_OFFSET 4 225*91f16700Schasinglulu #define MCI_PHY_CTRL_MCI_MAJOR \ 226*91f16700Schasinglulu (1 << MCI_PHY_CTRL_MCI_MAJOR_OFFSET) 227*91f16700Schasinglulu #define MCI_PHY_CTRL_MCI_SLEEP_REQ_OFFSET 11 228*91f16700Schasinglulu #define MCI_PHY_CTRL_MCI_SLEEP_REQ \ 229*91f16700Schasinglulu (1 << MCI_PHY_CTRL_MCI_SLEEP_REQ_OFFSET) 230*91f16700Schasinglulu /* Host=1 / Device=0 PHY mode */ 231*91f16700Schasinglulu #define MCI_PHY_CTRL_MCI_PHY_MODE_OFFSET 24 232*91f16700Schasinglulu #define MCI_PHY_CTRL_MCI_PHY_MODE_HOST \ 233*91f16700Schasinglulu (1 << MCI_PHY_CTRL_MCI_PHY_MODE_OFFSET) 234*91f16700Schasinglulu /* Register=1 / PWM=0 interface */ 235*91f16700Schasinglulu #define MCI_PHY_CTRL_MCI_PHY_REG_IF_MODE_OFFSET 25 236*91f16700Schasinglulu #define MCI_PHY_CTRL_MCI_PHY_REG_IF_MODE \ 237*91f16700Schasinglulu (1 << MCI_PHY_CTRL_MCI_PHY_REG_IF_MODE_OFFSET) 238*91f16700Schasinglulu /* PHY code InReset=1 */ 239*91f16700Schasinglulu #define MCI_PHY_CTRL_MCI_PHY_RESET_CORE_OFFSET 26 240*91f16700Schasinglulu #define MCI_PHY_CTRL_MCI_PHY_RESET_CORE \ 241*91f16700Schasinglulu (1 << MCI_PHY_CTRL_MCI_PHY_RESET_CORE_OFFSET) 242*91f16700Schasinglulu #define MCI_PHY_CTRL_PHY_ADDR_MSB_OFFSET 27 243*91f16700Schasinglulu #define MCI_PHY_CTRL_PHY_ADDR_MSB(addr) \ 244*91f16700Schasinglulu (((addr) & 0x3) << \ 245*91f16700Schasinglulu MCI_PHY_CTRL_PHY_ADDR_MSB_OFFSET) 246*91f16700Schasinglulu #define MCI_PHY_CTRL_PIDI_MODE_OFFSET 31 247*91f16700Schasinglulu #define MCI_PHY_CTRL_PIDI_MODE \ 248*91f16700Schasinglulu (1U << MCI_PHY_CTRL_PIDI_MODE_OFFSET) 249*91f16700Schasinglulu 250*91f16700Schasinglulu /* Number of times to wait for the MCI link ready after MCI configurations 251*91f16700Schasinglulu * Normally takes 34-35 successive reads 252*91f16700Schasinglulu */ 253*91f16700Schasinglulu #define LINK_READY_TIMEOUT 100 254*91f16700Schasinglulu 255*91f16700Schasinglulu enum mci_register_type { 256*91f16700Schasinglulu MCI_REG_TYPE_PHY = 0, 257*91f16700Schasinglulu MCI_REG_TYPE_CTRL, 258*91f16700Schasinglulu }; 259*91f16700Schasinglulu 260*91f16700Schasinglulu enum { 261*91f16700Schasinglulu MCI_CMD_WRITE, 262*91f16700Schasinglulu MCI_CMD_READ 263*91f16700Schasinglulu }; 264*91f16700Schasinglulu 265*91f16700Schasinglulu /* Write wrapper callback for debug: 266*91f16700Schasinglulu * will print written data in case LOG_LEVEL >= 40 267*91f16700Schasinglulu */ 268*91f16700Schasinglulu static void mci_mmio_write_32(uintptr_t addr, uint32_t value) 269*91f16700Schasinglulu { 270*91f16700Schasinglulu VERBOSE("Write:\t0x%x = 0x%x\n", (uint32_t)addr, value); 271*91f16700Schasinglulu mmio_write_32(addr, value); 272*91f16700Schasinglulu } 273*91f16700Schasinglulu /* Read wrapper callback for debug: 274*91f16700Schasinglulu * will print read data in case LOG_LEVEL >= 40 275*91f16700Schasinglulu */ 276*91f16700Schasinglulu static uint32_t mci_mmio_read_32(uintptr_t addr) 277*91f16700Schasinglulu { 278*91f16700Schasinglulu uint32_t value; 279*91f16700Schasinglulu 280*91f16700Schasinglulu value = mmio_read_32(addr); 281*91f16700Schasinglulu VERBOSE("Read:\t0x%x = 0x%x\n", (uint32_t)addr, value); 282*91f16700Schasinglulu return value; 283*91f16700Schasinglulu } 284*91f16700Schasinglulu 285*91f16700Schasinglulu /* MCI indirect access command completion polling: 286*91f16700Schasinglulu * Each write/read command done via MCI indirect registers must be polled 287*91f16700Schasinglulu * for command completions status. 288*91f16700Schasinglulu * 289*91f16700Schasinglulu * Returns 1 in case of error 290*91f16700Schasinglulu * Returns 0 in case of command completed successfully. 291*91f16700Schasinglulu */ 292*91f16700Schasinglulu static int mci_poll_command_completion(int mci_index, int command_type) 293*91f16700Schasinglulu { 294*91f16700Schasinglulu uint32_t mci_cmd_value = 0, retry_count = 100, ret = 0; 295*91f16700Schasinglulu uint32_t completion_flags = MCI_INDIRECT_CTRL_CMD_DONE; 296*91f16700Schasinglulu 297*91f16700Schasinglulu debug_enter(); 298*91f16700Schasinglulu /* Read commands require validating that requested data is ready */ 299*91f16700Schasinglulu if (command_type == MCI_CMD_READ) 300*91f16700Schasinglulu completion_flags |= MCI_INDIRECT_CTRL_DATA_READY; 301*91f16700Schasinglulu 302*91f16700Schasinglulu do { 303*91f16700Schasinglulu /* wait 1 ms before each polling */ 304*91f16700Schasinglulu mdelay(1); 305*91f16700Schasinglulu mci_cmd_value = mci_mmio_read_32(MCI_ACCESS_CMD_REG(mci_index)); 306*91f16700Schasinglulu } while (((mci_cmd_value & completion_flags) != completion_flags) && 307*91f16700Schasinglulu (retry_count-- > 0)); 308*91f16700Schasinglulu 309*91f16700Schasinglulu if (retry_count == 0) { 310*91f16700Schasinglulu ERROR("%s: MCI command timeout (command status = 0x%x)\n", 311*91f16700Schasinglulu __func__, mci_cmd_value); 312*91f16700Schasinglulu ret = 1; 313*91f16700Schasinglulu } 314*91f16700Schasinglulu 315*91f16700Schasinglulu debug_exit(); 316*91f16700Schasinglulu return ret; 317*91f16700Schasinglulu } 318*91f16700Schasinglulu 319*91f16700Schasinglulu int mci_read(int mci_idx, uint32_t cmd, uint32_t *value) 320*91f16700Schasinglulu { 321*91f16700Schasinglulu int rval; 322*91f16700Schasinglulu 323*91f16700Schasinglulu mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_idx), cmd); 324*91f16700Schasinglulu 325*91f16700Schasinglulu rval = mci_poll_command_completion(mci_idx, MCI_CMD_READ); 326*91f16700Schasinglulu 327*91f16700Schasinglulu *value = mci_mmio_read_32(MCI_WRITE_READ_DATA_REG(mci_idx)); 328*91f16700Schasinglulu 329*91f16700Schasinglulu return rval; 330*91f16700Schasinglulu } 331*91f16700Schasinglulu 332*91f16700Schasinglulu int mci_write(int mci_idx, uint32_t cmd, uint32_t data) 333*91f16700Schasinglulu { 334*91f16700Schasinglulu mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_idx), data); 335*91f16700Schasinglulu mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_idx), cmd); 336*91f16700Schasinglulu 337*91f16700Schasinglulu return mci_poll_command_completion(mci_idx, MCI_CMD_WRITE); 338*91f16700Schasinglulu } 339*91f16700Schasinglulu 340*91f16700Schasinglulu /* Perform 3 configurations in one command: PCI mode, 341*91f16700Schasinglulu * queues separation and cache bit 342*91f16700Schasinglulu */ 343*91f16700Schasinglulu static int mci_axi_set_pcie_mode(int mci_index) 344*91f16700Schasinglulu { 345*91f16700Schasinglulu uint32_t reg_data, ret = 1; 346*91f16700Schasinglulu 347*91f16700Schasinglulu debug_enter(); 348*91f16700Schasinglulu /* This configuration makes MCI IP behave consistently with AXI protocol 349*91f16700Schasinglulu * It should be configured at one side only (for example locally at AP). 350*91f16700Schasinglulu * The IP takes care of performing the same configurations at MCI on 351*91f16700Schasinglulu * another side (for example remotely at CP). 352*91f16700Schasinglulu */ 353*91f16700Schasinglulu mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), 354*91f16700Schasinglulu MCI_AXI_ACCESS_PCIE_MODE | 355*91f16700Schasinglulu MCI_AXI_ACCESS_CACHE_CHECK | 356*91f16700Schasinglulu MCI_AXI_ACCESS_FORCE_POST_WR | 357*91f16700Schasinglulu MCI_AXI_ACCESS_DISABLE_CLK_GATING); 358*91f16700Schasinglulu mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), 359*91f16700Schasinglulu MCI_INDIRECT_REG_CTRL_ADDR( 360*91f16700Schasinglulu MCI_AXI_ACCESS_DATA_REG_NUM) | 361*91f16700Schasinglulu MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB) | 362*91f16700Schasinglulu MCI_INDIRECT_CTRL_LOCAL_PKT | 363*91f16700Schasinglulu MCI_INDIRECT_CTRL_CIRCULAR_CMD); 364*91f16700Schasinglulu 365*91f16700Schasinglulu /* if Write command was successful, verify PCIe mode */ 366*91f16700Schasinglulu if (mci_poll_command_completion(mci_index, MCI_CMD_WRITE) == 0) { 367*91f16700Schasinglulu /* Verify the PCIe mode selected */ 368*91f16700Schasinglulu mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), 369*91f16700Schasinglulu MCI_INDIRECT_REG_CTRL_ADDR( 370*91f16700Schasinglulu MCI_HB_CTRL_TX_CTRL_REG_NUM) | 371*91f16700Schasinglulu MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB) | 372*91f16700Schasinglulu MCI_INDIRECT_CTRL_LOCAL_PKT | 373*91f16700Schasinglulu MCI_INDIRECT_CTRL_READ_CMD); 374*91f16700Schasinglulu /* if read was completed, verify PCIe mode */ 375*91f16700Schasinglulu if (mci_poll_command_completion(mci_index, MCI_CMD_READ) == 0) { 376*91f16700Schasinglulu reg_data = mci_mmio_read_32( 377*91f16700Schasinglulu MCI_WRITE_READ_DATA_REG(mci_index)); 378*91f16700Schasinglulu if (reg_data & MCI_HB_CTRL_TX_CTRL_PCIE_MODE) 379*91f16700Schasinglulu ret = 0; 380*91f16700Schasinglulu } 381*91f16700Schasinglulu } 382*91f16700Schasinglulu 383*91f16700Schasinglulu debug_exit(); 384*91f16700Schasinglulu return ret; 385*91f16700Schasinglulu } 386*91f16700Schasinglulu 387*91f16700Schasinglulu /* Reduce sequence FIFO timer expiration threshold */ 388*91f16700Schasinglulu static int mci_axi_set_fifo_thresh(int mci_index) 389*91f16700Schasinglulu { 390*91f16700Schasinglulu uint32_t reg_data, ret = 0; 391*91f16700Schasinglulu 392*91f16700Schasinglulu debug_enter(); 393*91f16700Schasinglulu /* This configuration reduces sequence FIFO timer expiration threshold 394*91f16700Schasinglulu * (to 0x7 instead of 0xA). 395*91f16700Schasinglulu * In MCI 1.6 version this configuration prevents possible functional 396*91f16700Schasinglulu * issues. 397*91f16700Schasinglulu * In version 1.82 the configuration prevents performance degradation 398*91f16700Schasinglulu */ 399*91f16700Schasinglulu 400*91f16700Schasinglulu /* Configure local AP side */ 401*91f16700Schasinglulu reg_data = MCI_PHY_CTRL_PIDI_MODE | 402*91f16700Schasinglulu MCI_PHY_CTRL_MCI_PHY_REG_IF_MODE | 403*91f16700Schasinglulu MCI_PHY_CTRL_MCI_PHY_MODE_HOST | 404*91f16700Schasinglulu MCI_PHY_CTRL_MCI_MAJOR | 405*91f16700Schasinglulu MCI_PHY_CTRL_MCI_MINOR; 406*91f16700Schasinglulu mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), reg_data); 407*91f16700Schasinglulu mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), 408*91f16700Schasinglulu MCI_INDIRECT_REG_CTRL_ADDR(MCI_PHY_CTRL_REG_NUM) | 409*91f16700Schasinglulu MCI_INDIRECT_CTRL_LOCAL_PKT); 410*91f16700Schasinglulu ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); 411*91f16700Schasinglulu 412*91f16700Schasinglulu /* Reduce the threshold */ 413*91f16700Schasinglulu mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), 414*91f16700Schasinglulu MCI_CTRL_IHB_MODE_CFG_REG_DEF_VAL); 415*91f16700Schasinglulu 416*91f16700Schasinglulu mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), 417*91f16700Schasinglulu MCI_INDIRECT_REG_CTRL_ADDR( 418*91f16700Schasinglulu MCI_CTRL_IHB_MODE_CFG_REG_NUM) | 419*91f16700Schasinglulu MCI_INDIRECT_CTRL_LOCAL_PKT); 420*91f16700Schasinglulu ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); 421*91f16700Schasinglulu 422*91f16700Schasinglulu /* Exit PIDI mode */ 423*91f16700Schasinglulu reg_data = MCI_PHY_CTRL_MCI_PHY_REG_IF_MODE | 424*91f16700Schasinglulu MCI_PHY_CTRL_MCI_PHY_MODE_HOST | 425*91f16700Schasinglulu MCI_PHY_CTRL_MCI_MAJOR | 426*91f16700Schasinglulu MCI_PHY_CTRL_MCI_MINOR; 427*91f16700Schasinglulu mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), reg_data); 428*91f16700Schasinglulu mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), 429*91f16700Schasinglulu MCI_INDIRECT_REG_CTRL_ADDR(MCI_PHY_CTRL_REG_NUM) | 430*91f16700Schasinglulu MCI_INDIRECT_CTRL_LOCAL_PKT); 431*91f16700Schasinglulu ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); 432*91f16700Schasinglulu 433*91f16700Schasinglulu /* Configure remote CP side */ 434*91f16700Schasinglulu reg_data = MCI_PHY_CTRL_PIDI_MODE | 435*91f16700Schasinglulu MCI_PHY_CTRL_MCI_MAJOR | 436*91f16700Schasinglulu MCI_PHY_CTRL_MCI_MINOR | 437*91f16700Schasinglulu MCI_PHY_CTRL_MCI_PHY_REG_IF_MODE; 438*91f16700Schasinglulu mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), reg_data); 439*91f16700Schasinglulu mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), 440*91f16700Schasinglulu MCI_INDIRECT_REG_CTRL_ADDR(MCI_PHY_CTRL_REG_NUM) | 441*91f16700Schasinglulu MCI_CTRL_IHB_MODE_FWD_MOD); 442*91f16700Schasinglulu ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); 443*91f16700Schasinglulu 444*91f16700Schasinglulu /* Reduce the threshold */ 445*91f16700Schasinglulu mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), 446*91f16700Schasinglulu MCI_CTRL_IHB_MODE_CFG_REG_DEF_VAL); 447*91f16700Schasinglulu mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), 448*91f16700Schasinglulu MCI_INDIRECT_REG_CTRL_ADDR( 449*91f16700Schasinglulu MCI_CTRL_IHB_MODE_CFG_REG_NUM) | 450*91f16700Schasinglulu MCI_INDIRECT_CTRL_HOPID(GID_IHB_EXT)); 451*91f16700Schasinglulu ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); 452*91f16700Schasinglulu 453*91f16700Schasinglulu /* Exit PIDI mode */ 454*91f16700Schasinglulu reg_data = MCI_PHY_CTRL_MCI_MAJOR | 455*91f16700Schasinglulu MCI_PHY_CTRL_MCI_MINOR | 456*91f16700Schasinglulu MCI_PHY_CTRL_MCI_PHY_REG_IF_MODE; 457*91f16700Schasinglulu mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), reg_data); 458*91f16700Schasinglulu mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), 459*91f16700Schasinglulu MCI_INDIRECT_REG_CTRL_ADDR(MCI_PHY_CTRL_REG_NUM) | 460*91f16700Schasinglulu MCI_CTRL_IHB_MODE_FWD_MOD); 461*91f16700Schasinglulu 462*91f16700Schasinglulu ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); 463*91f16700Schasinglulu 464*91f16700Schasinglulu debug_exit(); 465*91f16700Schasinglulu return ret; 466*91f16700Schasinglulu } 467*91f16700Schasinglulu 468*91f16700Schasinglulu /* Configure: 469*91f16700Schasinglulu * 1. AP & CP TX thresholds and delta configurations 470*91f16700Schasinglulu * 2. DLO & DLI FIFO full threshold 471*91f16700Schasinglulu * 3. RX thresholds and delta configurations 472*91f16700Schasinglulu * 4. CP AR and AW outstanding 473*91f16700Schasinglulu * 5. AP AR and AW outstanding 474*91f16700Schasinglulu */ 475*91f16700Schasinglulu static int mci_axi_set_fifo_rx_tx_thresh(int mci_index) 476*91f16700Schasinglulu { 477*91f16700Schasinglulu uint32_t ret = 0; 478*91f16700Schasinglulu 479*91f16700Schasinglulu debug_enter(); 480*91f16700Schasinglulu /* AP TX thresholds and delta configurations (IHB_reg 0x1) */ 481*91f16700Schasinglulu mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), 482*91f16700Schasinglulu MCI_CTRL_TX_MEM_CFG_REG_DEF_VAL); 483*91f16700Schasinglulu mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), 484*91f16700Schasinglulu MCI_INDIRECT_REG_CTRL_ADDR( 485*91f16700Schasinglulu MCI_CTRL_TX_MEM_CFG_REG_NUM) | 486*91f16700Schasinglulu MCI_INDIRECT_CTRL_LOCAL_PKT); 487*91f16700Schasinglulu ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); 488*91f16700Schasinglulu 489*91f16700Schasinglulu /* CP TX thresholds and delta configurations (IHB_reg 0x1) */ 490*91f16700Schasinglulu mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), 491*91f16700Schasinglulu MCI_CTRL_TX_MEM_CFG_REG_DEF_VAL); 492*91f16700Schasinglulu mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), 493*91f16700Schasinglulu MCI_INDIRECT_REG_CTRL_ADDR( 494*91f16700Schasinglulu MCI_CTRL_TX_MEM_CFG_REG_NUM) | 495*91f16700Schasinglulu MCI_INDIRECT_CTRL_HOPID(GID_IHB_EXT)); 496*91f16700Schasinglulu ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); 497*91f16700Schasinglulu 498*91f16700Schasinglulu /* AP DLO & DLI FIFO full threshold & Auto-Link enable (IHB_reg 0x8) */ 499*91f16700Schasinglulu mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), 500*91f16700Schasinglulu MCI_CTRL_MCI_PHY_SET_REG_DEF_VAL | 501*91f16700Schasinglulu MCI_CTRL_MCI_PHY_SET_AUTO_LINK_EN(1)); 502*91f16700Schasinglulu mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), 503*91f16700Schasinglulu MCI_INDIRECT_REG_CTRL_ADDR( 504*91f16700Schasinglulu MCI_CTRL_MCI_PHY_SETTINGS_REG_NUM) | 505*91f16700Schasinglulu MCI_INDIRECT_CTRL_LOCAL_PKT); 506*91f16700Schasinglulu ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); 507*91f16700Schasinglulu 508*91f16700Schasinglulu /* CP DLO & DLI FIFO full threshold (IHB_reg 0x8) */ 509*91f16700Schasinglulu mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), 510*91f16700Schasinglulu MCI_CTRL_MCI_PHY_SET_REG_DEF_VAL); 511*91f16700Schasinglulu mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), 512*91f16700Schasinglulu MCI_INDIRECT_REG_CTRL_ADDR( 513*91f16700Schasinglulu MCI_CTRL_MCI_PHY_SETTINGS_REG_NUM) | 514*91f16700Schasinglulu MCI_INDIRECT_CTRL_HOPID(GID_IHB_EXT)); 515*91f16700Schasinglulu ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); 516*91f16700Schasinglulu 517*91f16700Schasinglulu /* AP RX thresholds and delta configurations (IHB_reg 0x0) */ 518*91f16700Schasinglulu mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), 519*91f16700Schasinglulu MCI_CTRL_RX_MEM_CFG_REG_DEF_AP_VAL); 520*91f16700Schasinglulu mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), 521*91f16700Schasinglulu MCI_INDIRECT_REG_CTRL_ADDR( 522*91f16700Schasinglulu MCI_CTRL_RX_MEM_CFG_REG_NUM) | 523*91f16700Schasinglulu MCI_INDIRECT_CTRL_LOCAL_PKT); 524*91f16700Schasinglulu ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); 525*91f16700Schasinglulu 526*91f16700Schasinglulu /* CP RX thresholds and delta configurations (IHB_reg 0x0) */ 527*91f16700Schasinglulu mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), 528*91f16700Schasinglulu MCI_CTRL_RX_MEM_CFG_REG_DEF_CP_VAL); 529*91f16700Schasinglulu mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), 530*91f16700Schasinglulu MCI_INDIRECT_REG_CTRL_ADDR( 531*91f16700Schasinglulu MCI_CTRL_RX_MEM_CFG_REG_NUM) | 532*91f16700Schasinglulu MCI_INDIRECT_CTRL_HOPID(GID_IHB_EXT)); 533*91f16700Schasinglulu ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); 534*91f16700Schasinglulu 535*91f16700Schasinglulu /* AP AR & AW maximum AXI outstanding request cfg (HB_reg 0xd) */ 536*91f16700Schasinglulu mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), 537*91f16700Schasinglulu MCI_HB_CTRL_TX_CTRL_PRI_TH_QOS(8) | 538*91f16700Schasinglulu MCI_HB_CTRL_TX_CTRL_MAX_RD_CNT(3) | 539*91f16700Schasinglulu MCI_HB_CTRL_TX_CTRL_MAX_WR_CNT(3)); 540*91f16700Schasinglulu mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), 541*91f16700Schasinglulu MCI_INDIRECT_REG_CTRL_ADDR( 542*91f16700Schasinglulu MCI_HB_CTRL_TX_CTRL_REG_NUM) | 543*91f16700Schasinglulu MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB) | 544*91f16700Schasinglulu MCI_INDIRECT_CTRL_LOCAL_PKT); 545*91f16700Schasinglulu ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); 546*91f16700Schasinglulu 547*91f16700Schasinglulu /* CP AR & AW maximum AXI outstanding request cfg (HB_reg 0xd) */ 548*91f16700Schasinglulu mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), 549*91f16700Schasinglulu MCI_HB_CTRL_TX_CTRL_PRI_TH_QOS(8) | 550*91f16700Schasinglulu MCI_HB_CTRL_TX_CTRL_MAX_RD_CNT(0xB) | 551*91f16700Schasinglulu MCI_HB_CTRL_TX_CTRL_MAX_WR_CNT(0x11)); 552*91f16700Schasinglulu mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), 553*91f16700Schasinglulu MCI_INDIRECT_REG_CTRL_ADDR( 554*91f16700Schasinglulu MCI_HB_CTRL_TX_CTRL_REG_NUM) | 555*91f16700Schasinglulu MCI_INDIRECT_CTRL_HOPID(GID_IHB_EXT) | 556*91f16700Schasinglulu MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB)); 557*91f16700Schasinglulu ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); 558*91f16700Schasinglulu 559*91f16700Schasinglulu debug_exit(); 560*91f16700Schasinglulu return ret; 561*91f16700Schasinglulu } 562*91f16700Schasinglulu 563*91f16700Schasinglulu /* configure MCI to allow read & write transactions to arrive at the same time. 564*91f16700Schasinglulu * Without the below configuration, MCI won't sent response to CPU for 565*91f16700Schasinglulu * transactions which arrived simultaneously and will lead to CPU hang. 566*91f16700Schasinglulu * The below will configure MCI to be able to pass transactions from/to CP/AP. 567*91f16700Schasinglulu */ 568*91f16700Schasinglulu static int mci_enable_simultaneous_transactions(int mci_index) 569*91f16700Schasinglulu { 570*91f16700Schasinglulu uint32_t ret = 0; 571*91f16700Schasinglulu 572*91f16700Schasinglulu debug_enter(); 573*91f16700Schasinglulu /* ID assignment (assigning global ID offset to CP) */ 574*91f16700Schasinglulu mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), 575*91f16700Schasinglulu MCI_DID_GLOBAL_ASSIGN_REQ_MCI_LOCAL_ID(2) | 576*91f16700Schasinglulu MCI_DID_GLOBAL_ASSIGN_REQ_MCI_COUNT(2) | 577*91f16700Schasinglulu MCI_DID_GLOBAL_ASSIGN_REQ_HOPS_NUM(2)); 578*91f16700Schasinglulu mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), 579*91f16700Schasinglulu MCI_INDIRECT_REG_CTRL_ADDR( 580*91f16700Schasinglulu MCI_DID_GLOBAL_ASSIGNMENT_REQUEST_REG) | 581*91f16700Schasinglulu MCI_INDIRECT_CTRL_ASSIGN_CMD); 582*91f16700Schasinglulu ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); 583*91f16700Schasinglulu 584*91f16700Schasinglulu /* Assigning dest. ID=3 to all transactions entering from AXI at AP */ 585*91f16700Schasinglulu mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), 586*91f16700Schasinglulu MCI_HB_CTRL_WIN0_DEST_VALID_FLAG(1) | 587*91f16700Schasinglulu MCI_HB_CTRL_WIN0_DEST_ID(3)); 588*91f16700Schasinglulu mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), 589*91f16700Schasinglulu MCI_INDIRECT_REG_CTRL_ADDR( 590*91f16700Schasinglulu MCI_HB_CTRL_WIN0_DESTINATION_REG_NUM) | 591*91f16700Schasinglulu MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB) | 592*91f16700Schasinglulu MCI_INDIRECT_CTRL_LOCAL_PKT); 593*91f16700Schasinglulu ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); 594*91f16700Schasinglulu 595*91f16700Schasinglulu /* Assigning dest. ID=1 to all transactions entering from AXI at CP */ 596*91f16700Schasinglulu mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), 597*91f16700Schasinglulu MCI_HB_CTRL_WIN0_DEST_VALID_FLAG(1) | 598*91f16700Schasinglulu MCI_HB_CTRL_WIN0_DEST_ID(1)); 599*91f16700Schasinglulu mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), 600*91f16700Schasinglulu MCI_INDIRECT_REG_CTRL_ADDR( 601*91f16700Schasinglulu MCI_HB_CTRL_WIN0_DESTINATION_REG_NUM) | 602*91f16700Schasinglulu MCI_INDIRECT_CTRL_HOPID(GID_IHB_EXT) | 603*91f16700Schasinglulu MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB)); 604*91f16700Schasinglulu ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); 605*91f16700Schasinglulu 606*91f16700Schasinglulu /* End address to all transactions entering from AXI at AP. 607*91f16700Schasinglulu * This will lead to get match for any AXI address 608*91f16700Schasinglulu * and receive destination ID=3 609*91f16700Schasinglulu */ 610*91f16700Schasinglulu mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), 0xffffffff); 611*91f16700Schasinglulu mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), 612*91f16700Schasinglulu MCI_INDIRECT_REG_CTRL_ADDR( 613*91f16700Schasinglulu MCI_HB_CTRL_WIN0_ADDRESS_MASK_REG_NUM) | 614*91f16700Schasinglulu MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB) | 615*91f16700Schasinglulu MCI_INDIRECT_CTRL_LOCAL_PKT); 616*91f16700Schasinglulu ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); 617*91f16700Schasinglulu 618*91f16700Schasinglulu /* End address to all transactions entering from AXI at CP. 619*91f16700Schasinglulu * This will lead to get match for any AXI address 620*91f16700Schasinglulu * and receive destination ID=1 621*91f16700Schasinglulu */ 622*91f16700Schasinglulu mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), 0xffffffff); 623*91f16700Schasinglulu mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), 624*91f16700Schasinglulu MCI_INDIRECT_REG_CTRL_ADDR( 625*91f16700Schasinglulu MCI_HB_CTRL_WIN0_ADDRESS_MASK_REG_NUM) | 626*91f16700Schasinglulu MCI_INDIRECT_CTRL_HOPID(GID_IHB_EXT) | 627*91f16700Schasinglulu MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB)); 628*91f16700Schasinglulu ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); 629*91f16700Schasinglulu 630*91f16700Schasinglulu debug_exit(); 631*91f16700Schasinglulu return ret; 632*91f16700Schasinglulu } 633*91f16700Schasinglulu 634*91f16700Schasinglulu /* Check if MCI simultaneous transaction was already enabled. 635*91f16700Schasinglulu * Currently bootrom does this mci configuration only when the boot source is 636*91f16700Schasinglulu * SAR_MCIX4, in other cases it should be done at this stage. 637*91f16700Schasinglulu * It is worth noticing that in case of booting from uart, the bootrom 638*91f16700Schasinglulu * flow is different and this mci initialization is skipped even if boot 639*91f16700Schasinglulu * source is SAR_MCIX4. Therefore new verification bases on appropriate mci's 640*91f16700Schasinglulu * register content: if the appropriate reg contains 0x0 it means that the 641*91f16700Schasinglulu * bootrom didn't perform required mci configuration. 642*91f16700Schasinglulu * 643*91f16700Schasinglulu * Returns: 644*91f16700Schasinglulu * 0 - configuration already done 645*91f16700Schasinglulu * 1 - configuration missing 646*91f16700Schasinglulu */ 647*91f16700Schasinglulu static _Bool mci_simulatenous_trans_missing(int mci_index) 648*91f16700Schasinglulu { 649*91f16700Schasinglulu uint32_t reg, ret; 650*91f16700Schasinglulu 651*91f16700Schasinglulu /* read 'Window 0 Destination ID assignment' from HB register 0x3 652*91f16700Schasinglulu * (TX_CFG_W0_DST_ID) to check whether ID assignment was already 653*91f16700Schasinglulu * performed by BootROM. 654*91f16700Schasinglulu */ 655*91f16700Schasinglulu debug_enter(); 656*91f16700Schasinglulu mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), 657*91f16700Schasinglulu MCI_INDIRECT_REG_CTRL_ADDR( 658*91f16700Schasinglulu MCI_HB_CTRL_WIN0_DESTINATION_REG_NUM) | 659*91f16700Schasinglulu MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB) | 660*91f16700Schasinglulu MCI_INDIRECT_CTRL_LOCAL_PKT | 661*91f16700Schasinglulu MCI_INDIRECT_CTRL_READ_CMD); 662*91f16700Schasinglulu ret = mci_poll_command_completion(mci_index, MCI_CMD_READ); 663*91f16700Schasinglulu 664*91f16700Schasinglulu reg = mci_mmio_read_32(MCI_WRITE_READ_DATA_REG(mci_index)); 665*91f16700Schasinglulu 666*91f16700Schasinglulu if (ret) 667*91f16700Schasinglulu ERROR("Failed to verify MCI simultaneous read/write status\n"); 668*91f16700Schasinglulu 669*91f16700Schasinglulu debug_exit(); 670*91f16700Schasinglulu /* default ID assignment is 0, so if register doesn't contain zeros 671*91f16700Schasinglulu * it means that bootrom already performed required configuration. 672*91f16700Schasinglulu */ 673*91f16700Schasinglulu if (reg != 0) 674*91f16700Schasinglulu return 0; 675*91f16700Schasinglulu 676*91f16700Schasinglulu return 1; 677*91f16700Schasinglulu } 678*91f16700Schasinglulu 679*91f16700Schasinglulu /* For A1 revision, configure the MCI link for performance improvement: 680*91f16700Schasinglulu * - set MCI to support read/write transactions to arrive at the same time 681*91f16700Schasinglulu * - Switch AXI to PCIe mode 682*91f16700Schasinglulu * - Reduce sequence FIFO threshold 683*91f16700Schasinglulu * - Configure RX/TX FIFO thresholds 684*91f16700Schasinglulu * 685*91f16700Schasinglulu * Note: 686*91f16700Schasinglulu * We don't exit on error code from any sub routine, to try (best effort) to 687*91f16700Schasinglulu * complete the MCI configuration. 688*91f16700Schasinglulu * (If we exit - Bootloader will surely fail to boot) 689*91f16700Schasinglulu */ 690*91f16700Schasinglulu int mci_configure(int mci_index) 691*91f16700Schasinglulu { 692*91f16700Schasinglulu int rval; 693*91f16700Schasinglulu 694*91f16700Schasinglulu debug_enter(); 695*91f16700Schasinglulu /* According to design guidelines the MCI simultaneous transaction 696*91f16700Schasinglulu * shouldn't be enabled more then once - therefore make sure that it 697*91f16700Schasinglulu * wasn't already enabled in bootrom. 698*91f16700Schasinglulu */ 699*91f16700Schasinglulu if (mci_simulatenous_trans_missing(mci_index)) { 700*91f16700Schasinglulu VERBOSE("Enabling MCI simultaneous transaction for mci%d\n", 701*91f16700Schasinglulu mci_index); 702*91f16700Schasinglulu /* set MCI to support read/write transactions 703*91f16700Schasinglulu * to arrive at the same time 704*91f16700Schasinglulu */ 705*91f16700Schasinglulu rval = mci_enable_simultaneous_transactions(mci_index); 706*91f16700Schasinglulu if (rval) 707*91f16700Schasinglulu ERROR("Failed to set MCI simultaneous read/write\n"); 708*91f16700Schasinglulu } else 709*91f16700Schasinglulu VERBOSE("Skip MCI ID assignment - already done by bootrom\n"); 710*91f16700Schasinglulu 711*91f16700Schasinglulu /* Configure MCI for more consistent behavior with AXI protocol */ 712*91f16700Schasinglulu rval = mci_axi_set_pcie_mode(mci_index); 713*91f16700Schasinglulu if (rval) 714*91f16700Schasinglulu ERROR("Failed to set MCI to AXI PCIe mode\n"); 715*91f16700Schasinglulu 716*91f16700Schasinglulu /* reduce FIFO global threshold */ 717*91f16700Schasinglulu rval = mci_axi_set_fifo_thresh(mci_index); 718*91f16700Schasinglulu if (rval) 719*91f16700Schasinglulu ERROR("Failed to set MCI FIFO global threshold\n"); 720*91f16700Schasinglulu 721*91f16700Schasinglulu /* configure RX/TX FIFO thresholds */ 722*91f16700Schasinglulu rval = mci_axi_set_fifo_rx_tx_thresh(mci_index); 723*91f16700Schasinglulu if (rval) 724*91f16700Schasinglulu ERROR("Failed to set MCI RX/TX FIFO threshold\n"); 725*91f16700Schasinglulu 726*91f16700Schasinglulu debug_exit(); 727*91f16700Schasinglulu return 1; 728*91f16700Schasinglulu } 729*91f16700Schasinglulu 730*91f16700Schasinglulu int mci_get_link_status(void) 731*91f16700Schasinglulu { 732*91f16700Schasinglulu uint32_t cmd, data; 733*91f16700Schasinglulu 734*91f16700Schasinglulu cmd = (MCI_INDIRECT_REG_CTRL_ADDR(MCI_CTRL_STATUS_REG_NUM) | 735*91f16700Schasinglulu MCI_INDIRECT_CTRL_LOCAL_PKT | MCI_INDIRECT_CTRL_READ_CMD); 736*91f16700Schasinglulu if (mci_read(0, cmd, &data)) { 737*91f16700Schasinglulu ERROR("Failed to read status register\n"); 738*91f16700Schasinglulu return -1; 739*91f16700Schasinglulu } 740*91f16700Schasinglulu 741*91f16700Schasinglulu /* Check if the link is ready */ 742*91f16700Schasinglulu if (data != MCI_CTRL_PHY_READY) { 743*91f16700Schasinglulu ERROR("Bad link status %x\n", data); 744*91f16700Schasinglulu return -1; 745*91f16700Schasinglulu } 746*91f16700Schasinglulu 747*91f16700Schasinglulu return 0; 748*91f16700Schasinglulu } 749*91f16700Schasinglulu 750*91f16700Schasinglulu void mci_turn_link_down(void) 751*91f16700Schasinglulu { 752*91f16700Schasinglulu uint32_t cmd, data; 753*91f16700Schasinglulu int rval = 0; 754*91f16700Schasinglulu 755*91f16700Schasinglulu debug_enter(); 756*91f16700Schasinglulu 757*91f16700Schasinglulu /* Turn off auto-link */ 758*91f16700Schasinglulu cmd = (MCI_INDIRECT_REG_CTRL_ADDR(MCI_CTRL_MCI_PHY_SETTINGS_REG_NUM) | 759*91f16700Schasinglulu MCI_INDIRECT_CTRL_LOCAL_PKT); 760*91f16700Schasinglulu data = (MCI_CTRL_MCI_PHY_SET_REG_DEF_VAL2 | 761*91f16700Schasinglulu MCI_CTRL_MCI_PHY_SET_AUTO_LINK_EN(0)); 762*91f16700Schasinglulu rval = mci_write(0, cmd, data); 763*91f16700Schasinglulu if (rval) 764*91f16700Schasinglulu ERROR("Failed to turn off auto-link\n"); 765*91f16700Schasinglulu 766*91f16700Schasinglulu /* Reset AP PHY */ 767*91f16700Schasinglulu cmd = (MCI_INDIRECT_REG_CTRL_ADDR(MCI_PHY_CTRL_REG_NUM) | 768*91f16700Schasinglulu MCI_INDIRECT_CTRL_LOCAL_PKT); 769*91f16700Schasinglulu data = (MCI_PHY_CTRL_MCI_MINOR | 770*91f16700Schasinglulu MCI_PHY_CTRL_MCI_MAJOR | 771*91f16700Schasinglulu MCI_PHY_CTRL_MCI_PHY_MODE_HOST | 772*91f16700Schasinglulu MCI_PHY_CTRL_MCI_PHY_RESET_CORE); 773*91f16700Schasinglulu rval = mci_write(0, cmd, data); 774*91f16700Schasinglulu if (rval) 775*91f16700Schasinglulu ERROR("Failed to reset AP PHY\n"); 776*91f16700Schasinglulu 777*91f16700Schasinglulu /* Clear all status & CRC values */ 778*91f16700Schasinglulu cmd = (MCI_INDIRECT_REG_CTRL_ADDR(MCI_LINK_CRC_CTRL_REG_NUM) | 779*91f16700Schasinglulu MCI_INDIRECT_CTRL_LOCAL_PKT); 780*91f16700Schasinglulu data = 0x0; 781*91f16700Schasinglulu mci_write(0, cmd, data); 782*91f16700Schasinglulu cmd = (MCI_INDIRECT_REG_CTRL_ADDR(MCI_CTRL_STATUS_REG_NUM) | 783*91f16700Schasinglulu MCI_INDIRECT_CTRL_LOCAL_PKT); 784*91f16700Schasinglulu data = 0x0; 785*91f16700Schasinglulu rval = mci_write(0, cmd, data); 786*91f16700Schasinglulu if (rval) 787*91f16700Schasinglulu ERROR("Failed to reset AP PHY\n"); 788*91f16700Schasinglulu 789*91f16700Schasinglulu /* Wait 5ms before un-reset the PHY */ 790*91f16700Schasinglulu mdelay(5); 791*91f16700Schasinglulu 792*91f16700Schasinglulu /* Un-reset AP PHY */ 793*91f16700Schasinglulu cmd = (MCI_INDIRECT_REG_CTRL_ADDR(MCI_PHY_CTRL_REG_NUM) | 794*91f16700Schasinglulu MCI_INDIRECT_CTRL_LOCAL_PKT); 795*91f16700Schasinglulu data = (MCI_PHY_CTRL_MCI_MINOR | MCI_PHY_CTRL_MCI_MAJOR | 796*91f16700Schasinglulu MCI_PHY_CTRL_MCI_PHY_MODE_HOST); 797*91f16700Schasinglulu rval = mci_write(0, cmd, data); 798*91f16700Schasinglulu if (rval) 799*91f16700Schasinglulu ERROR("Failed to un-reset AP PHY\n"); 800*91f16700Schasinglulu 801*91f16700Schasinglulu debug_exit(); 802*91f16700Schasinglulu } 803*91f16700Schasinglulu 804*91f16700Schasinglulu void mci_turn_link_on(void) 805*91f16700Schasinglulu { 806*91f16700Schasinglulu uint32_t cmd, data; 807*91f16700Schasinglulu int rval = 0; 808*91f16700Schasinglulu 809*91f16700Schasinglulu debug_enter(); 810*91f16700Schasinglulu /* Turn on auto-link */ 811*91f16700Schasinglulu cmd = (MCI_INDIRECT_REG_CTRL_ADDR(MCI_CTRL_MCI_PHY_SETTINGS_REG_NUM) | 812*91f16700Schasinglulu MCI_INDIRECT_CTRL_LOCAL_PKT); 813*91f16700Schasinglulu data = (MCI_CTRL_MCI_PHY_SET_REG_DEF_VAL2 | 814*91f16700Schasinglulu MCI_CTRL_MCI_PHY_SET_AUTO_LINK_EN(1)); 815*91f16700Schasinglulu rval = mci_write(0, cmd, data); 816*91f16700Schasinglulu if (rval) 817*91f16700Schasinglulu ERROR("Failed to turn on auto-link\n"); 818*91f16700Schasinglulu 819*91f16700Schasinglulu debug_exit(); 820*91f16700Schasinglulu } 821*91f16700Schasinglulu 822*91f16700Schasinglulu /* Initialize MCI for performance improvements */ 823*91f16700Schasinglulu int mci_link_tune(int mci_index) 824*91f16700Schasinglulu { 825*91f16700Schasinglulu int ret; 826*91f16700Schasinglulu 827*91f16700Schasinglulu debug_enter(); 828*91f16700Schasinglulu INFO("MCI%d initialization:\n", mci_index); 829*91f16700Schasinglulu 830*91f16700Schasinglulu ret = mci_configure(mci_index); 831*91f16700Schasinglulu 832*91f16700Schasinglulu debug_exit(); 833*91f16700Schasinglulu return ret; 834*91f16700Schasinglulu } 835