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