xref: /rk3399_ARM-atf/drivers/marvell/mci.c (revision 031542fc24ba48c2f38cb40ab008afb9943aaa74)
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