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