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