xref: /rk3399_ARM-atf/plat/brcm/board/stingray/src/sr_paxb_phy.c (revision 926cd70a0cc3a0cbf209a87765a8dc0b869798e3)
1*3942d3a8SSheetal Tigadoli /*
2*3942d3a8SSheetal Tigadoli  * Copyright (c) 2019-2020, Broadcom
3*3942d3a8SSheetal Tigadoli  *
4*3942d3a8SSheetal Tigadoli  * SPDX-License-Identifier: BSD-3-Clause
5*3942d3a8SSheetal Tigadoli  */
6*3942d3a8SSheetal Tigadoli 
7*3942d3a8SSheetal Tigadoli #include <errno.h>
8*3942d3a8SSheetal Tigadoli #include <stdbool.h>
9*3942d3a8SSheetal Tigadoli 
10*3942d3a8SSheetal Tigadoli #include <common/debug.h>
11*3942d3a8SSheetal Tigadoli #include <drivers/delay_timer.h>
12*3942d3a8SSheetal Tigadoli #include <lib/mmio.h>
13*3942d3a8SSheetal Tigadoli 
14*3942d3a8SSheetal Tigadoli #include <paxb.h>
15*3942d3a8SSheetal Tigadoli #include <sr_def.h>
16*3942d3a8SSheetal Tigadoli #include <sr_utils.h>
17*3942d3a8SSheetal Tigadoli 
18*3942d3a8SSheetal Tigadoli /* total number of PCIe Phys */
19*3942d3a8SSheetal Tigadoli #define NUM_OF_PCIE_SERDES            8
20*3942d3a8SSheetal Tigadoli 
21*3942d3a8SSheetal Tigadoli #define CFG_RC_PMI_ADDR               0x1130
22*3942d3a8SSheetal Tigadoli #define PMI_RX_TERM_SEQ               ((0x1 << 27) | (0x1ff << 16) | (0xd090))
23*3942d3a8SSheetal Tigadoli #define PMI_RX_TERM_VAL               0x4c00
24*3942d3a8SSheetal Tigadoli #define PMI_PLL_CTRL_4                0xd0b4
25*3942d3a8SSheetal Tigadoli #define PMI_SERDES_CLK_ENABLE         (1 << 12)
26*3942d3a8SSheetal Tigadoli 
27*3942d3a8SSheetal Tigadoli #define WAR_PLX_PRESET_PARITY_FAIL
28*3942d3a8SSheetal Tigadoli 
29*3942d3a8SSheetal Tigadoli #define CFG_RC_REG_PHY_CTL_10         0x1838
30*3942d3a8SSheetal Tigadoli #define PHY_CTL_10_GEN3_MATCH_PARITY  (1 << 15)
31*3942d3a8SSheetal Tigadoli 
32*3942d3a8SSheetal Tigadoli #define PMI_X8_CORE0_7_PATCH_SEQ      ((0x1 << 27) | (0x1ff << 16) | (0xd2a5))
33*3942d3a8SSheetal Tigadoli #define PMI_X8_CORE0_7_PATCH_VAL      0xd864
34*3942d3a8SSheetal Tigadoli 
35*3942d3a8SSheetal Tigadoli #define PMI_ADDR_BCAST(addr)          ((0x1 << 27) | (0x1ff << 16) | (addr))
36*3942d3a8SSheetal Tigadoli #define PMI_ADDR_LANE0(addr)          ((0x1 << 27) | (addr))
37*3942d3a8SSheetal Tigadoli #define PMI_ADDR_LANE1(addr)          ((0x1 << 27) | (0x1 << 16) | (addr))
38*3942d3a8SSheetal Tigadoli 
39*3942d3a8SSheetal Tigadoli #define MERLIN16_PCIE_BLK2_PWRMGMT_7	((0x1 << 27) | (0x1ff << 16) | 0x1208)
40*3942d3a8SSheetal Tigadoli #define MERLIN16_PCIE_BLK2_PWRMGMT_8	((0x1 << 27) | (0x1ff << 16) | 0x1209)
41*3942d3a8SSheetal Tigadoli #define MERLIN16_AMS_TX_CTRL_5		((0x1 << 27) | (0x1ff << 16) | 0xd0a5)
42*3942d3a8SSheetal Tigadoli #define MERLIN16_AMS_TX_CTRL_5_VAL	\
43*3942d3a8SSheetal Tigadoli 		((1 << 13) | (1 << 12) | (1 << 11) | (1 << 10))
44*3942d3a8SSheetal Tigadoli #define MERLIN16_PCIE_BLK2_PWRMGMT_7_VAL   0x96
45*3942d3a8SSheetal Tigadoli #define MERLIN16_PCIE_BLK2_PWRMGMT_8_VAL   0x12c
46*3942d3a8SSheetal Tigadoli 
47*3942d3a8SSheetal Tigadoli #define CFG_RC_PMI_WDATA              0x1134
48*3942d3a8SSheetal Tigadoli #define CFG_RC_WCMD_SHIFT             31
49*3942d3a8SSheetal Tigadoli #define CFG_RC_WCMD_MASK              ((uint32_t)1U << CFG_RC_WCMD_SHIFT)
50*3942d3a8SSheetal Tigadoli #define CFG_RC_RCMD_SHIFT             30
51*3942d3a8SSheetal Tigadoli #define CFG_RC_RCMD_MASK              ((uint32_t)1U << CFG_RC_RCMD_SHIFT)
52*3942d3a8SSheetal Tigadoli #define CFG_RC_RWCMD_MASK             (CFG_RC_RCMD_MASK | CFG_RC_WCMD_MASK)
53*3942d3a8SSheetal Tigadoli #define CFG_RC_PMI_RDATA              0x1138
54*3942d3a8SSheetal Tigadoli #define CFG_RC_RACK_SHIFT             31
55*3942d3a8SSheetal Tigadoli #define CFG_RC_RACK_MASK              ((uint32_t)1U << CFG_RC_RACK_SHIFT)
56*3942d3a8SSheetal Tigadoli 
57*3942d3a8SSheetal Tigadoli /* allow up to 5 ms for PMI write to finish */
58*3942d3a8SSheetal Tigadoli #define PMI_TIMEOUT_MS                5
59*3942d3a8SSheetal Tigadoli 
60*3942d3a8SSheetal Tigadoli /* in 2x8 RC mode, one needs to patch up Serdes 3 and 7 for link to come up */
61*3942d3a8SSheetal Tigadoli #define SERDES_PATCH_PIPEMUX_INDEX    0x3
62*3942d3a8SSheetal Tigadoli #define SERDES_PATCH_INDEX            0x8
63*3942d3a8SSheetal Tigadoli 
64*3942d3a8SSheetal Tigadoli #define DSC_UC_CTRL                   0xd00d
65*3942d3a8SSheetal Tigadoli #define DSC_UC_CTRL_RDY_CMD           (1 << 7)
66*3942d3a8SSheetal Tigadoli #define LANE_DBG_RST_CTRL             0xd164
67*3942d3a8SSheetal Tigadoli #define UC_A_CLK_CTRL0                0xd200
68*3942d3a8SSheetal Tigadoli #define UC_A_RST_CTRL0                0xd201
69*3942d3a8SSheetal Tigadoli #define UC_A_AHB_CTRL0                0xd202
70*3942d3a8SSheetal Tigadoli #define UC_A_AHB_STAT0                0xd203
71*3942d3a8SSheetal Tigadoli #define UC_A_AHB_WADDR_LSW            0xd204
72*3942d3a8SSheetal Tigadoli #define UC_A_AHB_WADDR_MSW            0xd205
73*3942d3a8SSheetal Tigadoli #define UC_A_AHB_WDATA_LSW            0xd206
74*3942d3a8SSheetal Tigadoli #define UC_A_AHB_WDATA_MSW            0xd207
75*3942d3a8SSheetal Tigadoli #define UC_A_AHB_RADDR_LSW            0xd208
76*3942d3a8SSheetal Tigadoli #define UC_A_AHB_RADDR_MSW            0xd209
77*3942d3a8SSheetal Tigadoli #define UC_A_AHB_RDATA_LSW            0xd20a
78*3942d3a8SSheetal Tigadoli #define UC_A_AHB_RDATA_MSW            0xd20b
79*3942d3a8SSheetal Tigadoli #define UC_VERSION_NUM                0xd230
80*3942d3a8SSheetal Tigadoli #define DSC_SM_CTL22                  0xd267
81*3942d3a8SSheetal Tigadoli #define UC_DBG1                       0xd251
82*3942d3a8SSheetal Tigadoli 
83*3942d3a8SSheetal Tigadoli #define LOAD_UC_CHECK                 0
84*3942d3a8SSheetal Tigadoli #define UC_RAM_INIT_TIMEOUT           100
85*3942d3a8SSheetal Tigadoli #define UC_RAM_CONTROL                0xd225
86*3942d3a8SSheetal Tigadoli #define UC_INIT_TIMEOUT               100
87*3942d3a8SSheetal Tigadoli #define SIZE_ALIGN(x, a)              (((x) + (a) - 1) & ~((a) - 1))
88*3942d3a8SSheetal Tigadoli #define SZ_4                          4
89*3942d3a8SSheetal Tigadoli #define GET_2_BYTES(p, i)             ((uint16_t)p[i] | (uint16_t)p[i+1] << 8)
90*3942d3a8SSheetal Tigadoli 
91*3942d3a8SSheetal Tigadoli /*
92*3942d3a8SSheetal Tigadoli  * List of PCIe LCPLL related registers
93*3942d3a8SSheetal Tigadoli  *
94*3942d3a8SSheetal Tigadoli  * LCPLL channel 0 provides the Serdes pad clock when running in RC mode
95*3942d3a8SSheetal Tigadoli  */
96*3942d3a8SSheetal Tigadoli #define PCIE_LCPLL_BASE             0x40000000
97*3942d3a8SSheetal Tigadoli 
98*3942d3a8SSheetal Tigadoli #define PCIE_LCPLL_CTRL0_OFFSET     0x00
99*3942d3a8SSheetal Tigadoli #define PCIE_LCPLL_RESETB_SHIFT     31
100*3942d3a8SSheetal Tigadoli #define PCIE_LCPLL_RESETB_MASK      BIT(PCIE_LCPLL_RESETB_SHIFT)
101*3942d3a8SSheetal Tigadoli #define PCIE_LCPLL_P_RESETB_SHIFT   30
102*3942d3a8SSheetal Tigadoli #define PCIE_LCPLL_P_RESETB_MASK    BIT(PCIE_LCPLL_P_RESETB_SHIFT)
103*3942d3a8SSheetal Tigadoli 
104*3942d3a8SSheetal Tigadoli #define PCIE_LCPLL_CTRL3_OFFSET     0x0c
105*3942d3a8SSheetal Tigadoli #define PCIE_LCPLL_EN_CTRL_SHIFT    16
106*3942d3a8SSheetal Tigadoli #define PCIE_LCPLL_CM_ENA           0x1a
107*3942d3a8SSheetal Tigadoli #define PCIE_LCPLL_CM_BUF_ENA       0x18
108*3942d3a8SSheetal Tigadoli #define PCIE_LCPLL_D2C2_ENA         0x2
109*3942d3a8SSheetal Tigadoli #define PCIE_LCPLL_REF_CLK_SHIFT    1
110*3942d3a8SSheetal Tigadoli #define PCIE_LCPLL_REF_CLK_MASK     BIT(PCIE_LCPLL_REF_CLK_SHIFT)
111*3942d3a8SSheetal Tigadoli #define PCIE_LCPLL_CTRL13_OFFSET    0x34
112*3942d3a8SSheetal Tigadoli #define PCIE_LCPLL_D2C2_CTRL_SHIFT  16
113*3942d3a8SSheetal Tigadoli #define PCIE_LCPLL_D2C2_TERM_DISC   0xe0
114*3942d3a8SSheetal Tigadoli 
115*3942d3a8SSheetal Tigadoli #define PCIE_LCPLL_STATUS_OFFSET    0x40
116*3942d3a8SSheetal Tigadoli #define PCIE_LCPLL_LOCK_SHIFT       12
117*3942d3a8SSheetal Tigadoli #define PCIE_LCPLL_LOCK_MASK        BIT(PCIE_LCPLL_LOCK_SHIFT)
118*3942d3a8SSheetal Tigadoli 
119*3942d3a8SSheetal Tigadoli #define PCIE_PIPE_MUX_RC_MODE_OVERRIDE_CFG  0x114
120*3942d3a8SSheetal Tigadoli #define PCIE_TX_CLKMASTER_CTRL_OVERRIDE_CFG 0x11c
121*3942d3a8SSheetal Tigadoli 
122*3942d3a8SSheetal Tigadoli /* wait 500 microseconds for PCIe LCPLL to power up */
123*3942d3a8SSheetal Tigadoli #define PCIE_LCPLL_DELAY_US         500
124*3942d3a8SSheetal Tigadoli 
125*3942d3a8SSheetal Tigadoli /* allow up to 5 ms for PCIe LCPLL VCO to lock */
126*3942d3a8SSheetal Tigadoli #define PCIE_LCPLL_TIMEOUT_MS       5
127*3942d3a8SSheetal Tigadoli 
128*3942d3a8SSheetal Tigadoli #define PCIE_PIPE_MUX_CONFIGURATION_CFG  0x4000010c
129*3942d3a8SSheetal Tigadoli 
130*3942d3a8SSheetal Tigadoli #define PCIE_PIPEMUX_SHIFT        19
131*3942d3a8SSheetal Tigadoli #define PCIE_PIPEMUX_MASK         0xf
132*3942d3a8SSheetal Tigadoli 
133*3942d3a8SSheetal Tigadoli /* keep track of PIPEMUX index to use */
134*3942d3a8SSheetal Tigadoli static unsigned int pipemux_idx;
135*3942d3a8SSheetal Tigadoli 
136*3942d3a8SSheetal Tigadoli /*
137*3942d3a8SSheetal Tigadoli  * PCIe PIPEMUX lookup table
138*3942d3a8SSheetal Tigadoli  *
139*3942d3a8SSheetal Tigadoli  * Each array index represents a PIPEMUX strap setting
140*3942d3a8SSheetal Tigadoli  * The array element represents a bitmap where a set bit means the PCIe core
141*3942d3a8SSheetal Tigadoli  * needs to be enabled as RC
142*3942d3a8SSheetal Tigadoli  */
143*3942d3a8SSheetal Tigadoli static uint8_t pipemux_table[] = {
144*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 0, EP 1x16 */
145*3942d3a8SSheetal Tigadoli 	0x00,
146*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 1, EP 1x8 + RC 1x8, core 7 */
147*3942d3a8SSheetal Tigadoli 	0x80,
148*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 2, EP 4x4 */
149*3942d3a8SSheetal Tigadoli 	0x00,
150*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 3, RC 2x8, cores 0, 7 */
151*3942d3a8SSheetal Tigadoli 	0x81,
152*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 4, RC 4x4, cores 0, 1, 6, 7 */
153*3942d3a8SSheetal Tigadoli 	0xc3,
154*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 5, RC 8x2, all 8 cores */
155*3942d3a8SSheetal Tigadoli 	0xff,
156*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 6, RC 3x4 + 2x2, cores 0, 2, 3, 6, 7 */
157*3942d3a8SSheetal Tigadoli 	0xcd,
158*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 7, RC 1x4 + 6x2, cores 0, 2, 3, 4, 5, 6, 7 */
159*3942d3a8SSheetal Tigadoli 	0xfd,
160*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 8, EP 1x8 + RC 4x2, cores 4, 5, 6, 7 */
161*3942d3a8SSheetal Tigadoli 	0xf0,
162*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 9, EP 1x8 + RC 2x4, cores 6, 7 */
163*3942d3a8SSheetal Tigadoli 	0xc0,
164*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 10, EP 2x4 + RC 2x4, cores 1, 6 */
165*3942d3a8SSheetal Tigadoli 	0x42,
166*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 11, EP 2x4 + RC 4x2, cores 2, 3, 4, 5 */
167*3942d3a8SSheetal Tigadoli 	0x3c,
168*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 12, EP 1x4 + RC 6x2, cores 2, 3, 4, 5, 6, 7 */
169*3942d3a8SSheetal Tigadoli 	0xfc,
170*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 13, RC 2x4 + RC 1x4 + 2x2, cores 2, 3, 6 */
171*3942d3a8SSheetal Tigadoli 	0x4c,
172*3942d3a8SSheetal Tigadoli };
173*3942d3a8SSheetal Tigadoli 
174*3942d3a8SSheetal Tigadoli /*
175*3942d3a8SSheetal Tigadoli  * Return 1 if pipemux strap is supported
176*3942d3a8SSheetal Tigadoli  */
pipemux_strap_is_valid(uint32_t pipemux)177*3942d3a8SSheetal Tigadoli static int pipemux_strap_is_valid(uint32_t pipemux)
178*3942d3a8SSheetal Tigadoli {
179*3942d3a8SSheetal Tigadoli 	if (pipemux < ARRAY_SIZE(pipemux_table))
180*3942d3a8SSheetal Tigadoli 		return 1;
181*3942d3a8SSheetal Tigadoli 	else
182*3942d3a8SSheetal Tigadoli 		return 0;
183*3942d3a8SSheetal Tigadoli }
184*3942d3a8SSheetal Tigadoli 
185*3942d3a8SSheetal Tigadoli /*
186*3942d3a8SSheetal Tigadoli  * Read the PCIe PIPEMUX from strap
187*3942d3a8SSheetal Tigadoli  */
pipemux_strap_read(void)188*3942d3a8SSheetal Tigadoli static uint32_t pipemux_strap_read(void)
189*3942d3a8SSheetal Tigadoli {
190*3942d3a8SSheetal Tigadoli 	uint32_t pipemux;
191*3942d3a8SSheetal Tigadoli 
192*3942d3a8SSheetal Tigadoli 	pipemux = mmio_read_32(PCIE_PIPE_MUX_CONFIGURATION_CFG);
193*3942d3a8SSheetal Tigadoli 	pipemux &= PCIE_PIPEMUX_MASK;
194*3942d3a8SSheetal Tigadoli 	if (pipemux == PCIE_PIPEMUX_MASK) {
195*3942d3a8SSheetal Tigadoli 		/* read the PCIe PIPEMUX strap setting */
196*3942d3a8SSheetal Tigadoli 		pipemux = mmio_read_32(CDRU_CHIP_STRAP_DATA_LSW);
197*3942d3a8SSheetal Tigadoli 		pipemux >>= PCIE_PIPEMUX_SHIFT;
198*3942d3a8SSheetal Tigadoli 		pipemux &= PCIE_PIPEMUX_MASK;
199*3942d3a8SSheetal Tigadoli 	}
200*3942d3a8SSheetal Tigadoli 
201*3942d3a8SSheetal Tigadoli 	return pipemux;
202*3942d3a8SSheetal Tigadoli }
203*3942d3a8SSheetal Tigadoli 
204*3942d3a8SSheetal Tigadoli /*
205*3942d3a8SSheetal Tigadoli  * Store the PIPEMUX index (set for each boot)
206*3942d3a8SSheetal Tigadoli  */
pipemux_save_index(unsigned int idx)207*3942d3a8SSheetal Tigadoli static void pipemux_save_index(unsigned int idx)
208*3942d3a8SSheetal Tigadoli {
209*3942d3a8SSheetal Tigadoli 	pipemux_idx = idx;
210*3942d3a8SSheetal Tigadoli }
211*3942d3a8SSheetal Tigadoli 
paxb_sr_core_needs_enable(unsigned int core_idx)212*3942d3a8SSheetal Tigadoli static int paxb_sr_core_needs_enable(unsigned int core_idx)
213*3942d3a8SSheetal Tigadoli {
214*3942d3a8SSheetal Tigadoli 	return !!((pipemux_table[pipemux_idx] >> core_idx) & 0x1);
215*3942d3a8SSheetal Tigadoli }
216*3942d3a8SSheetal Tigadoli 
pipemux_sr_init(void)217*3942d3a8SSheetal Tigadoli static int pipemux_sr_init(void)
218*3942d3a8SSheetal Tigadoli {
219*3942d3a8SSheetal Tigadoli 	uint32_t pipemux;
220*3942d3a8SSheetal Tigadoli 
221*3942d3a8SSheetal Tigadoli 	/* read the PCIe PIPEMUX strap setting */
222*3942d3a8SSheetal Tigadoli 	pipemux = pipemux_strap_read();
223*3942d3a8SSheetal Tigadoli 	if (!pipemux_strap_is_valid(pipemux)) {
224*3942d3a8SSheetal Tigadoli 		ERROR("Invalid PCIe PIPEMUX strap %u\n", pipemux);
225*3942d3a8SSheetal Tigadoli 		return -EIO;
226*3942d3a8SSheetal Tigadoli 	}
227*3942d3a8SSheetal Tigadoli 
228*3942d3a8SSheetal Tigadoli 	/* no PCIe RC is needed */
229*3942d3a8SSheetal Tigadoli 	if (!pipemux_table[pipemux]) {
230*3942d3a8SSheetal Tigadoli 		WARN("PIPEMUX indicates no PCIe RC required\n");
231*3942d3a8SSheetal Tigadoli 		return -ENODEV;
232*3942d3a8SSheetal Tigadoli 	}
233*3942d3a8SSheetal Tigadoli 
234*3942d3a8SSheetal Tigadoli 	/* save the PIPEMUX strap */
235*3942d3a8SSheetal Tigadoli 	pipemux_save_index(pipemux);
236*3942d3a8SSheetal Tigadoli 
237*3942d3a8SSheetal Tigadoli 	return 0;
238*3942d3a8SSheetal Tigadoli }
239*3942d3a8SSheetal Tigadoli 
240*3942d3a8SSheetal Tigadoli /*
241*3942d3a8SSheetal Tigadoli  * PCIe RC serdes link width
242*3942d3a8SSheetal Tigadoli  *
243*3942d3a8SSheetal Tigadoli  * The array is first organized in rows as indexed by the PIPEMUX setting.
244*3942d3a8SSheetal Tigadoli  * Within each row, eight lane width entries are specified -- one entry
245*3942d3a8SSheetal Tigadoli  * per PCIe core, from 0 to 7.
246*3942d3a8SSheetal Tigadoli  *
247*3942d3a8SSheetal Tigadoli  * Note: The EP lanes/cores are not mapped in this table!  EP cores are
248*3942d3a8SSheetal Tigadoli  *       controlled and thus configured by Nitro.
249*3942d3a8SSheetal Tigadoli  */
250*3942d3a8SSheetal Tigadoli static uint8_t link_width_table[][NUM_OF_SR_PCIE_CORES] = {
251*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 0, EP 1x16 */
252*3942d3a8SSheetal Tigadoli 	{0, 0, 0, 0, 0, 0, 0, 0},
253*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 1, EP 1x8 + RC 1x8, core 7 */
254*3942d3a8SSheetal Tigadoli 	{0, 0, 0, 0, 0, 0, 0, 8},
255*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 2, EP 4x4 */
256*3942d3a8SSheetal Tigadoli 	{0, 0, 0, 0, 0, 0, 0, 0},
257*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 3, RC 2x8, cores 0, 7 */
258*3942d3a8SSheetal Tigadoli 	{8, 0, 0, 0, 0, 0, 0, 8},
259*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 4, RC 4x4, cores 0, 1, 6, 7 */
260*3942d3a8SSheetal Tigadoli 	{4, 4, 0, 0, 0, 0, 4, 4},
261*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 5, RC 8x2, all 8 cores */
262*3942d3a8SSheetal Tigadoli 	{2, 2, 2, 2, 2, 2, 2, 2},
263*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 6, RC 3x4 (cores 0, 6, 7), RC 2x2 (cores 2, 3) */
264*3942d3a8SSheetal Tigadoli 	{4, 0, 2, 2, 0, 0, 4, 4},
265*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 7, RC 1x4 (core 0), RC 6x2 (cores 2, 3, 4, 5, 6, 7 */
266*3942d3a8SSheetal Tigadoli 	{4, 0, 2, 2, 2, 2, 2, 2},
267*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 8, EP 1x8 + RC 4x2 (cores 4, 5, 6, 7) */
268*3942d3a8SSheetal Tigadoli 	{0, 0, 0, 0, 2, 2, 2, 2},
269*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 9, EP 1x8 + RC 2x4 (cores 6, 7) */
270*3942d3a8SSheetal Tigadoli 	{0, 0, 0, 0, 0, 0, 4, 4},
271*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 10, EP 2x4 + RC 2x4 (cores 1, 6) */
272*3942d3a8SSheetal Tigadoli 	{0, 4, 0, 0, 0, 0, 4, 0},
273*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 11, EP 2x4 + RC 4x2 (cores 2, 3, 4, 5) */
274*3942d3a8SSheetal Tigadoli 	{0, 0, 2, 2, 2, 2, 0, 0},
275*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 12, EP 1x4 + RC 6x2 (cores 2, 3, 4, 5, 6, 7) */
276*3942d3a8SSheetal Tigadoli 	{0, 0, 2, 2, 2, 2, 2, 2},
277*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 13, EP 2x4 + RC 1x4 (core 6) + RC 2x2 (cores 2, 3) */
278*3942d3a8SSheetal Tigadoli 	{0, 0, 2, 2, 0, 0, 4, 0}
279*3942d3a8SSheetal Tigadoli };
280*3942d3a8SSheetal Tigadoli 
281*3942d3a8SSheetal Tigadoli /*
282*3942d3a8SSheetal Tigadoli  * function for writes to the Serdes registers through the PMI interface
283*3942d3a8SSheetal Tigadoli  */
paxb_pmi_write(unsigned int core_idx,uint32_t pmi,uint32_t val)284*3942d3a8SSheetal Tigadoli static int paxb_pmi_write(unsigned int core_idx, uint32_t pmi, uint32_t val)
285*3942d3a8SSheetal Tigadoli {
286*3942d3a8SSheetal Tigadoli 	uint32_t status;
287*3942d3a8SSheetal Tigadoli 	unsigned int timeout = PMI_TIMEOUT_MS;
288*3942d3a8SSheetal Tigadoli 
289*3942d3a8SSheetal Tigadoli 	paxb_rc_cfg_write(core_idx, CFG_RC_PMI_ADDR, pmi);
290*3942d3a8SSheetal Tigadoli 
291*3942d3a8SSheetal Tigadoli 	val &= ~CFG_RC_RWCMD_MASK;
292*3942d3a8SSheetal Tigadoli 	val |= CFG_RC_WCMD_MASK;
293*3942d3a8SSheetal Tigadoli 	paxb_rc_cfg_write(core_idx, CFG_RC_PMI_WDATA, val);
294*3942d3a8SSheetal Tigadoli 
295*3942d3a8SSheetal Tigadoli 	do {
296*3942d3a8SSheetal Tigadoli 		status = paxb_rc_cfg_read(core_idx, CFG_RC_PMI_WDATA);
297*3942d3a8SSheetal Tigadoli 
298*3942d3a8SSheetal Tigadoli 		/* wait for write command bit to clear */
299*3942d3a8SSheetal Tigadoli 		if ((status & CFG_RC_WCMD_MASK) == 0)
300*3942d3a8SSheetal Tigadoli 			return 0;
301*3942d3a8SSheetal Tigadoli 	} while (--timeout);
302*3942d3a8SSheetal Tigadoli 
303*3942d3a8SSheetal Tigadoli 	return -EIO;
304*3942d3a8SSheetal Tigadoli }
305*3942d3a8SSheetal Tigadoli 
306*3942d3a8SSheetal Tigadoli /*
307*3942d3a8SSheetal Tigadoli  * function for reads from the Serdes registers through the PMI interface
308*3942d3a8SSheetal Tigadoli  */
paxb_pmi_read(unsigned int core_idx,uint32_t pmi,uint32_t * val)309*3942d3a8SSheetal Tigadoli static int paxb_pmi_read(unsigned int core_idx, uint32_t pmi, uint32_t *val)
310*3942d3a8SSheetal Tigadoli {
311*3942d3a8SSheetal Tigadoli 	uint32_t status;
312*3942d3a8SSheetal Tigadoli 	unsigned int timeout = PMI_TIMEOUT_MS;
313*3942d3a8SSheetal Tigadoli 
314*3942d3a8SSheetal Tigadoli 	paxb_rc_cfg_write(core_idx, CFG_RC_PMI_ADDR, pmi);
315*3942d3a8SSheetal Tigadoli 
316*3942d3a8SSheetal Tigadoli 	paxb_rc_cfg_write(core_idx, CFG_RC_PMI_WDATA, CFG_RC_RCMD_MASK);
317*3942d3a8SSheetal Tigadoli 
318*3942d3a8SSheetal Tigadoli 	do {
319*3942d3a8SSheetal Tigadoli 		status = paxb_rc_cfg_read(core_idx, CFG_RC_PMI_RDATA);
320*3942d3a8SSheetal Tigadoli 
321*3942d3a8SSheetal Tigadoli 		/* wait for read ack bit set */
322*3942d3a8SSheetal Tigadoli 		if ((status & CFG_RC_RACK_MASK)) {
323*3942d3a8SSheetal Tigadoli 			*val = paxb_rc_cfg_read(core_idx, CFG_RC_PMI_RDATA);
324*3942d3a8SSheetal Tigadoli 			return 0;
325*3942d3a8SSheetal Tigadoli 		}
326*3942d3a8SSheetal Tigadoli 	} while (--timeout);
327*3942d3a8SSheetal Tigadoli 
328*3942d3a8SSheetal Tigadoli 	return -EIO;
329*3942d3a8SSheetal Tigadoli }
330*3942d3a8SSheetal Tigadoli 
331*3942d3a8SSheetal Tigadoli 
332*3942d3a8SSheetal Tigadoli #ifndef BOARD_PCIE_EXT_CLK
333*3942d3a8SSheetal Tigadoli /*
334*3942d3a8SSheetal Tigadoli  * PCIe Override clock lookup table
335*3942d3a8SSheetal Tigadoli  *
336*3942d3a8SSheetal Tigadoli  * Each array index represents pcie override clock has been done
337*3942d3a8SSheetal Tigadoli  * by CFW or not.
338*3942d3a8SSheetal Tigadoli  */
339*3942d3a8SSheetal Tigadoli static uint8_t pcie_override_clk_table[] = {
340*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 0, EP 1x16 */
341*3942d3a8SSheetal Tigadoli 	0x0,
342*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 1, EP 1x8 + RC 1x8, core 7 */
343*3942d3a8SSheetal Tigadoli 	0x1,
344*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 2, EP 4x4 */
345*3942d3a8SSheetal Tigadoli 	0x0,
346*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 3, RC 2x8, cores 0, 7 */
347*3942d3a8SSheetal Tigadoli 	0x0,
348*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 4, RC 4x4, cores 0, 1, 6, 7 */
349*3942d3a8SSheetal Tigadoli 	0x0,
350*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 5, RC 8x2, all 8 cores */
351*3942d3a8SSheetal Tigadoli 	0x0,
352*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 6, RC 3x4 + 2x2, cores 0, 2, 3, 6, 7 */
353*3942d3a8SSheetal Tigadoli 	0x0,
354*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 7, RC 1x4 + 6x2, cores 0, 2, 3, 4, 5, 6, 7 */
355*3942d3a8SSheetal Tigadoli 	0x0,
356*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 8, EP 1x8 + RC 4x2, cores 4, 5, 6, 7 */
357*3942d3a8SSheetal Tigadoli 	0x0,
358*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 9, EP 1x8 + RC 2x4, cores 6, 7 */
359*3942d3a8SSheetal Tigadoli 	0x0,
360*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 10, EP 2x4 + RC 2x4, cores 1, 6 */
361*3942d3a8SSheetal Tigadoli 	0x0,
362*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 11, EP 2x4 + RC 4x2, cores 2, 3, 4, 5 */
363*3942d3a8SSheetal Tigadoli 	0x0,
364*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 12, EP 1x4 + RC 6x2, cores 2, 3, 4, 5, 6, 7 */
365*3942d3a8SSheetal Tigadoli 	0x0,
366*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 13, RC 2x4 + RC 1x4 + 2x2, cores 2, 3, 6 */
367*3942d3a8SSheetal Tigadoli 	0x0,
368*3942d3a8SSheetal Tigadoli };
369*3942d3a8SSheetal Tigadoli 
370*3942d3a8SSheetal Tigadoli /*
371*3942d3a8SSheetal Tigadoli  * Bring up LCPLL channel 0 reference clock for PCIe serdes used in RC mode
372*3942d3a8SSheetal Tigadoli  */
pcie_lcpll_init(void)373*3942d3a8SSheetal Tigadoli static int pcie_lcpll_init(void)
374*3942d3a8SSheetal Tigadoli {
375*3942d3a8SSheetal Tigadoli 	uintptr_t reg;
376*3942d3a8SSheetal Tigadoli 	unsigned int timeout = PCIE_LCPLL_TIMEOUT_MS;
377*3942d3a8SSheetal Tigadoli 	uint32_t val;
378*3942d3a8SSheetal Tigadoli 
379*3942d3a8SSheetal Tigadoli 	if (pcie_override_clk_table[pipemux_idx]) {
380*3942d3a8SSheetal Tigadoli 		/*
381*3942d3a8SSheetal Tigadoli 		 * Check rc_mode_override again to avoid halt
382*3942d3a8SSheetal Tigadoli 		 * because of cfw uninitialized lcpll.
383*3942d3a8SSheetal Tigadoli 		 */
384*3942d3a8SSheetal Tigadoli 		reg = (uintptr_t)(PCIE_LCPLL_BASE +
385*3942d3a8SSheetal Tigadoli 				  PCIE_PIPE_MUX_RC_MODE_OVERRIDE_CFG);
386*3942d3a8SSheetal Tigadoli 		val = mmio_read_32(reg);
387*3942d3a8SSheetal Tigadoli 		if (val & 0x1)
388*3942d3a8SSheetal Tigadoli 			return 0;
389*3942d3a8SSheetal Tigadoli 		else
390*3942d3a8SSheetal Tigadoli 			return -ENODEV;
391*3942d3a8SSheetal Tigadoli 	}
392*3942d3a8SSheetal Tigadoli 
393*3942d3a8SSheetal Tigadoli 	/* power on PCIe LCPLL and its LDO */
394*3942d3a8SSheetal Tigadoli 	reg = (uintptr_t)CRMU_AON_CTRL1;
395*3942d3a8SSheetal Tigadoli 	mmio_setbits_32(reg, CRMU_PCIE_LCPLL_PWR_ON_MASK |
396*3942d3a8SSheetal Tigadoli 			     CRMU_PCIE_LCPLL_PWRON_LDO_MASK);
397*3942d3a8SSheetal Tigadoli 	udelay(PCIE_LCPLL_DELAY_US);
398*3942d3a8SSheetal Tigadoli 
399*3942d3a8SSheetal Tigadoli 	/* remove isolation */
400*3942d3a8SSheetal Tigadoli 	mmio_clrbits_32(reg, CRMU_PCIE_LCPLL_ISO_IN_MASK);
401*3942d3a8SSheetal Tigadoli 	udelay(PCIE_LCPLL_DELAY_US);
402*3942d3a8SSheetal Tigadoli 
403*3942d3a8SSheetal Tigadoli 	/* disconnect termination */
404*3942d3a8SSheetal Tigadoli 	reg = (uintptr_t)(PCIE_LCPLL_BASE + PCIE_LCPLL_CTRL13_OFFSET);
405*3942d3a8SSheetal Tigadoli 	mmio_setbits_32(reg, PCIE_LCPLL_D2C2_TERM_DISC <<
406*3942d3a8SSheetal Tigadoli 			PCIE_LCPLL_D2C2_CTRL_SHIFT);
407*3942d3a8SSheetal Tigadoli 
408*3942d3a8SSheetal Tigadoli 	/* enable CML buf1/2 and D2C2 */
409*3942d3a8SSheetal Tigadoli 	reg = (uintptr_t)(PCIE_LCPLL_BASE + PCIE_LCPLL_CTRL3_OFFSET);
410*3942d3a8SSheetal Tigadoli 	mmio_setbits_32(reg, PCIE_LCPLL_CM_ENA << PCIE_LCPLL_EN_CTRL_SHIFT);
411*3942d3a8SSheetal Tigadoli 
412*3942d3a8SSheetal Tigadoli 	/* select diff clock mux out as ref clock */
413*3942d3a8SSheetal Tigadoli 	mmio_clrbits_32(reg, PCIE_LCPLL_REF_CLK_MASK);
414*3942d3a8SSheetal Tigadoli 
415*3942d3a8SSheetal Tigadoli 	/* delay for 500 microseconds per ASIC spec for PCIe LCPLL */
416*3942d3a8SSheetal Tigadoli 	udelay(PCIE_LCPLL_DELAY_US);
417*3942d3a8SSheetal Tigadoli 
418*3942d3a8SSheetal Tigadoli 	/* now bring PCIe LCPLL out of reset */
419*3942d3a8SSheetal Tigadoli 	reg = (uintptr_t)(PCIE_LCPLL_BASE + PCIE_LCPLL_CTRL0_OFFSET);
420*3942d3a8SSheetal Tigadoli 	mmio_setbits_32(reg, PCIE_LCPLL_RESETB_MASK);
421*3942d3a8SSheetal Tigadoli 
422*3942d3a8SSheetal Tigadoli 	/* wait for PLL to lock */
423*3942d3a8SSheetal Tigadoli 	reg = (uintptr_t)(PCIE_LCPLL_BASE + PCIE_LCPLL_STATUS_OFFSET);
424*3942d3a8SSheetal Tigadoli 	do {
425*3942d3a8SSheetal Tigadoli 		val = mmio_read_32(reg);
426*3942d3a8SSheetal Tigadoli 		if ((val & PCIE_LCPLL_LOCK_MASK) == PCIE_LCPLL_LOCK_MASK) {
427*3942d3a8SSheetal Tigadoli 			/* now bring the post divider out of reset */
428*3942d3a8SSheetal Tigadoli 			reg = (uintptr_t)(PCIE_LCPLL_BASE +
429*3942d3a8SSheetal Tigadoli 					  PCIE_LCPLL_CTRL0_OFFSET);
430*3942d3a8SSheetal Tigadoli 			mmio_setbits_32(reg, PCIE_LCPLL_P_RESETB_MASK);
431*3942d3a8SSheetal Tigadoli 			VERBOSE("PCIe LCPLL locked\n");
432*3942d3a8SSheetal Tigadoli 			return 0;
433*3942d3a8SSheetal Tigadoli 		}
434*3942d3a8SSheetal Tigadoli 		mdelay(1);
435*3942d3a8SSheetal Tigadoli 	} while (--timeout);
436*3942d3a8SSheetal Tigadoli 
437*3942d3a8SSheetal Tigadoli 	ERROR("PCIe LCPLL failed to lock\n");
438*3942d3a8SSheetal Tigadoli 	return -EIO;
439*3942d3a8SSheetal Tigadoli }
440*3942d3a8SSheetal Tigadoli #else
441*3942d3a8SSheetal Tigadoli /*
442*3942d3a8SSheetal Tigadoli  * Bring up EXT CLK reference clock for PCIe serdes used in RC mode
443*3942d3a8SSheetal Tigadoli  * XTAL_BYPASS		(3 << 0)
444*3942d3a8SSheetal Tigadoli  * INTR_LC_REF		(5 << 0)
445*3942d3a8SSheetal Tigadoli  * PD_CML_LC_REF_OUT	(1 << 4)
446*3942d3a8SSheetal Tigadoli  * PD_CML_REF_CH_OUT	(1 << 8)
447*3942d3a8SSheetal Tigadoli  * CLK_MASTER_SEL	(1 << 11)
448*3942d3a8SSheetal Tigadoli  * CLK_MASTER_CTRL_A	(1 << 12)
449*3942d3a8SSheetal Tigadoli  * CLK_MASTER_CTRL_B	(2 << 14)
450*3942d3a8SSheetal Tigadoli  */
451*3942d3a8SSheetal Tigadoli static const uint16_t pcie_ext_clk[][NUM_OF_PCIE_SERDES] = {
452*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 0, EP 1x16 */
453*3942d3a8SSheetal Tigadoli 	{0},
454*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 1, EP 1x8 + RC 1x8, core 7 */
455*3942d3a8SSheetal Tigadoli 	{0},
456*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 2, EP 4x4 */
457*3942d3a8SSheetal Tigadoli 	{0},
458*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 3, RC 2x8, cores 0, 7 */
459*3942d3a8SSheetal Tigadoli 	{0x8803, 0x9115, 0x9115, 0x1115, 0x8803, 0x9115, 0x9115, 0x1115},
460*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 4, RC 4x4, cores 0, 1, 6, 7 */
461*3942d3a8SSheetal Tigadoli 	{0x8803, 0x1115, 0x8915, 0x1115, 0x8803, 0x1115, 0x8915, 0x1115,},
462*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 5, RC 8x2, all 8 cores */
463*3942d3a8SSheetal Tigadoli 	{0x0803, 0x0915, 0x0915, 0x0915, 0x0803, 0x0915, 0x0915, 0x0915,},
464*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 6, RC 3x4 + 2x2, cores 0, 2, 3, 6, 7 */
465*3942d3a8SSheetal Tigadoli 	{0},
466*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 7, RC 1x4 + 6x2, cores 0, 2, 3, 4, 5, 6, 7 */
467*3942d3a8SSheetal Tigadoli 	{0},
468*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 8, EP 1x8 + RC 4x2, cores 4, 5, 6, 7 */
469*3942d3a8SSheetal Tigadoli 	{0},
470*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 9, EP 1x8 + RC 2x4, cores 6, 7 */
471*3942d3a8SSheetal Tigadoli 	{0},
472*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 10, EP 2x4 + RC 2x4, cores 1, 6 */
473*3942d3a8SSheetal Tigadoli 	{0},
474*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 11, EP 2x4 + RC 4x2, cores 2, 3, 4, 5 */
475*3942d3a8SSheetal Tigadoli 	{0},
476*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 12, EP 1x4 + RC 6x2, cores 2, 3, 4, 5, 6, 7 */
477*3942d3a8SSheetal Tigadoli 	{0},
478*3942d3a8SSheetal Tigadoli 	/* PIPEMUX = 13, RC 2x4 + RC 1x4 + 2x2, cores 2, 3, 6 */
479*3942d3a8SSheetal Tigadoli 	{0},
480*3942d3a8SSheetal Tigadoli };
481*3942d3a8SSheetal Tigadoli 
pcie_ext_clk_init(void)482*3942d3a8SSheetal Tigadoli static void pcie_ext_clk_init(void)
483*3942d3a8SSheetal Tigadoli {
484*3942d3a8SSheetal Tigadoli 	unsigned int serdes;
485*3942d3a8SSheetal Tigadoli 	uint32_t val;
486*3942d3a8SSheetal Tigadoli 
487*3942d3a8SSheetal Tigadoli 	for (serdes = 0; serdes < NUM_OF_PCIE_SERDES; serdes++) {
488*3942d3a8SSheetal Tigadoli 		val = pcie_ext_clk[pipemux_idx][serdes];
489*3942d3a8SSheetal Tigadoli 		if (!val)
490*3942d3a8SSheetal Tigadoli 			return;
491*3942d3a8SSheetal Tigadoli 		mmio_write_32(PCIE_CORE_RESERVED_CFG +
492*3942d3a8SSheetal Tigadoli 			      serdes * PCIE_CORE_PWR_OFFSET, val);
493*3942d3a8SSheetal Tigadoli 	}
494*3942d3a8SSheetal Tigadoli 	/* disable CML buf1/2 and enable D2C2 */
495*3942d3a8SSheetal Tigadoli 	mmio_clrsetbits_32((PCIE_LCPLL_BASE + PCIE_LCPLL_CTRL3_OFFSET),
496*3942d3a8SSheetal Tigadoli 			PCIE_LCPLL_CM_BUF_ENA << PCIE_LCPLL_EN_CTRL_SHIFT,
497*3942d3a8SSheetal Tigadoli 			PCIE_LCPLL_D2C2_ENA << PCIE_LCPLL_EN_CTRL_SHIFT);
498*3942d3a8SSheetal Tigadoli 	mmio_write_32(PCIE_LCPLL_BASE + PCIE_TX_CLKMASTER_CTRL_OVERRIDE_CFG, 1);
499*3942d3a8SSheetal Tigadoli 	INFO("Overriding Clocking - using REF clock from PAD...\n");
500*3942d3a8SSheetal Tigadoli }
501*3942d3a8SSheetal Tigadoli #endif
502*3942d3a8SSheetal Tigadoli 
load_uc(unsigned int core_idx)503*3942d3a8SSheetal Tigadoli static int load_uc(unsigned int core_idx)
504*3942d3a8SSheetal Tigadoli {
505*3942d3a8SSheetal Tigadoli 	return 0;
506*3942d3a8SSheetal Tigadoli }
507*3942d3a8SSheetal Tigadoli 
paxb_serdes_gate_clock(unsigned int core_idx,int gate_clk)508*3942d3a8SSheetal Tigadoli static int paxb_serdes_gate_clock(unsigned int core_idx, int gate_clk)
509*3942d3a8SSheetal Tigadoli {
510*3942d3a8SSheetal Tigadoli 	unsigned int link_width, serdes, nr_serdes;
511*3942d3a8SSheetal Tigadoli 	uintptr_t pmi_base;
512*3942d3a8SSheetal Tigadoli 	unsigned int rdata;
513*3942d3a8SSheetal Tigadoli 	uint32_t core_offset = core_idx * PCIE_CORE_PWR_OFFSET;
514*3942d3a8SSheetal Tigadoli 
515*3942d3a8SSheetal Tigadoli 	link_width = paxb->get_link_width(core_idx);
516*3942d3a8SSheetal Tigadoli 	if (!link_width) {
517*3942d3a8SSheetal Tigadoli 		ERROR("Unsupported PIPEMUX\n");
518*3942d3a8SSheetal Tigadoli 		return -EOPNOTSUPP;
519*3942d3a8SSheetal Tigadoli 	}
520*3942d3a8SSheetal Tigadoli 
521*3942d3a8SSheetal Tigadoli 	nr_serdes = link_width / 2;
522*3942d3a8SSheetal Tigadoli 	pmi_base = (uintptr_t)(PCIE_CORE_PMI_CFG_BASE + core_offset);
523*3942d3a8SSheetal Tigadoli 
524*3942d3a8SSheetal Tigadoli 	for (serdes = 0; serdes < nr_serdes; serdes++) {
525*3942d3a8SSheetal Tigadoli 		mmio_write_32(pmi_base, serdes);
526*3942d3a8SSheetal Tigadoli 		paxb_pmi_read(core_idx, PMI_ADDR_LANE0(PMI_PLL_CTRL_4), &rdata);
527*3942d3a8SSheetal Tigadoli 		if (!gate_clk)
528*3942d3a8SSheetal Tigadoli 			rdata |= PMI_SERDES_CLK_ENABLE;
529*3942d3a8SSheetal Tigadoli 		else
530*3942d3a8SSheetal Tigadoli 			rdata &= ~PMI_SERDES_CLK_ENABLE;
531*3942d3a8SSheetal Tigadoli 		paxb_pmi_write(core_idx, PMI_ADDR_BCAST(PMI_PLL_CTRL_4), rdata);
532*3942d3a8SSheetal Tigadoli 	}
533*3942d3a8SSheetal Tigadoli 	return 0;
534*3942d3a8SSheetal Tigadoli }
535*3942d3a8SSheetal Tigadoli 
paxb_gen3_serdes_init(unsigned int core_idx,uint32_t nSerdes)536*3942d3a8SSheetal Tigadoli static int paxb_gen3_serdes_init(unsigned int core_idx, uint32_t nSerdes)
537*3942d3a8SSheetal Tigadoli {
538*3942d3a8SSheetal Tigadoli 	uint32_t rdata;
539*3942d3a8SSheetal Tigadoli 	int serdes;
540*3942d3a8SSheetal Tigadoli 	uintptr_t pmi_base;
541*3942d3a8SSheetal Tigadoli 	unsigned int timeout;
542*3942d3a8SSheetal Tigadoli 	unsigned int reg_d230, reg_d267;
543*3942d3a8SSheetal Tigadoli 
544*3942d3a8SSheetal Tigadoli 
545*3942d3a8SSheetal Tigadoli 	pmi_base = (uintptr_t)(PCIE_CORE_PMI_CFG_BASE +
546*3942d3a8SSheetal Tigadoli 			(core_idx * PCIE_CORE_PWR_OFFSET));
547*3942d3a8SSheetal Tigadoli 
548*3942d3a8SSheetal Tigadoli 	for (serdes = 0; serdes < nSerdes; serdes++) {
549*3942d3a8SSheetal Tigadoli 		/* select the PMI interface */
550*3942d3a8SSheetal Tigadoli 		mmio_write_32(pmi_base, serdes);
551*3942d3a8SSheetal Tigadoli 
552*3942d3a8SSheetal Tigadoli 		/* Clock enable */
553*3942d3a8SSheetal Tigadoli 		paxb_pmi_write(core_idx, PMI_ADDR_BCAST(UC_A_CLK_CTRL0),
554*3942d3a8SSheetal Tigadoli 				0x3);
555*3942d3a8SSheetal Tigadoli 
556*3942d3a8SSheetal Tigadoli 		/* Release reset of master */
557*3942d3a8SSheetal Tigadoli 		paxb_pmi_write(core_idx, PMI_ADDR_BCAST(UC_A_RST_CTRL0),
558*3942d3a8SSheetal Tigadoli 				0x1);
559*3942d3a8SSheetal Tigadoli 
560*3942d3a8SSheetal Tigadoli 		/* clearing PRAM memory */
561*3942d3a8SSheetal Tigadoli 		paxb_pmi_write(core_idx, PMI_ADDR_BCAST(UC_A_AHB_CTRL0),
562*3942d3a8SSheetal Tigadoli 				0x100);
563*3942d3a8SSheetal Tigadoli 
564*3942d3a8SSheetal Tigadoli 		timeout = UC_RAM_INIT_TIMEOUT;
565*3942d3a8SSheetal Tigadoli 		do {
566*3942d3a8SSheetal Tigadoli 			paxb_pmi_read(core_idx,
567*3942d3a8SSheetal Tigadoli 					PMI_ADDR_LANE0(UC_A_AHB_STAT0),
568*3942d3a8SSheetal Tigadoli 					&rdata);
569*3942d3a8SSheetal Tigadoli 		} while ((rdata & 0x01) == 0 && timeout--);
570*3942d3a8SSheetal Tigadoli 
571*3942d3a8SSheetal Tigadoli 		if (!timeout)
572*3942d3a8SSheetal Tigadoli 			return -EIO;
573*3942d3a8SSheetal Tigadoli 
574*3942d3a8SSheetal Tigadoli 		timeout = UC_RAM_INIT_TIMEOUT;
575*3942d3a8SSheetal Tigadoli 		do {
576*3942d3a8SSheetal Tigadoli 			paxb_pmi_read(core_idx,
577*3942d3a8SSheetal Tigadoli 					PMI_ADDR_LANE1(UC_A_AHB_STAT0),
578*3942d3a8SSheetal Tigadoli 					&rdata);
579*3942d3a8SSheetal Tigadoli 		} while ((rdata & 0x01) == 0 && timeout--);
580*3942d3a8SSheetal Tigadoli 
581*3942d3a8SSheetal Tigadoli 		if (!timeout)
582*3942d3a8SSheetal Tigadoli 			return -EIO;
583*3942d3a8SSheetal Tigadoli 
584*3942d3a8SSheetal Tigadoli 		/* clearing PRAM memory */
585*3942d3a8SSheetal Tigadoli 		paxb_pmi_write(core_idx, PMI_ADDR_BCAST(UC_A_AHB_CTRL0),
586*3942d3a8SSheetal Tigadoli 				0);
587*3942d3a8SSheetal Tigadoli 
588*3942d3a8SSheetal Tigadoli 		/* to identify 2 lane serdes */
589*3942d3a8SSheetal Tigadoli 		paxb_pmi_write(core_idx, PMI_ADDR_BCAST(UC_DBG1), 0x1);
590*3942d3a8SSheetal Tigadoli 
591*3942d3a8SSheetal Tigadoli 		/* De-Assert Pram & master resets */
592*3942d3a8SSheetal Tigadoli 		paxb_pmi_write(core_idx, PMI_ADDR_BCAST(UC_A_RST_CTRL0),
593*3942d3a8SSheetal Tigadoli 				0x9);
594*3942d3a8SSheetal Tigadoli 
595*3942d3a8SSheetal Tigadoli 		if (load_uc(core_idx))
596*3942d3a8SSheetal Tigadoli 			return -EIO;
597*3942d3a8SSheetal Tigadoli 
598*3942d3a8SSheetal Tigadoli 		/* UC UC ready for command */
599*3942d3a8SSheetal Tigadoli 		paxb_pmi_read(core_idx, PMI_ADDR_LANE0(DSC_UC_CTRL),
600*3942d3a8SSheetal Tigadoli 				&rdata);
601*3942d3a8SSheetal Tigadoli 		rdata |= DSC_UC_CTRL_RDY_CMD;
602*3942d3a8SSheetal Tigadoli 		paxb_pmi_write(core_idx, PMI_ADDR_LANE0(DSC_UC_CTRL),
603*3942d3a8SSheetal Tigadoli 				rdata);
604*3942d3a8SSheetal Tigadoli 
605*3942d3a8SSheetal Tigadoli 		paxb_pmi_read(core_idx, PMI_ADDR_LANE1(DSC_UC_CTRL),
606*3942d3a8SSheetal Tigadoli 				&rdata);
607*3942d3a8SSheetal Tigadoli 		rdata |= DSC_UC_CTRL_RDY_CMD;
608*3942d3a8SSheetal Tigadoli 		paxb_pmi_write(core_idx, PMI_ADDR_LANE1(DSC_UC_CTRL),
609*3942d3a8SSheetal Tigadoli 				rdata);
610*3942d3a8SSheetal Tigadoli 
611*3942d3a8SSheetal Tigadoli 		/* Lane reset */
612*3942d3a8SSheetal Tigadoli 		paxb_pmi_write(core_idx,
613*3942d3a8SSheetal Tigadoli 				PMI_ADDR_BCAST(LANE_DBG_RST_CTRL), 0x3);
614*3942d3a8SSheetal Tigadoli 
615*3942d3a8SSheetal Tigadoli 		/* De-Assert Core and Master resets */
616*3942d3a8SSheetal Tigadoli 		paxb_pmi_write(core_idx, PMI_ADDR_BCAST(UC_A_RST_CTRL0),
617*3942d3a8SSheetal Tigadoli 				0x3);
618*3942d3a8SSheetal Tigadoli 
619*3942d3a8SSheetal Tigadoli 		timeout = UC_INIT_TIMEOUT;
620*3942d3a8SSheetal Tigadoli 		while (timeout--) {
621*3942d3a8SSheetal Tigadoli 			paxb_pmi_read(core_idx,
622*3942d3a8SSheetal Tigadoli 					PMI_ADDR_LANE0(UC_VERSION_NUM),
623*3942d3a8SSheetal Tigadoli 					&reg_d230);
624*3942d3a8SSheetal Tigadoli 			paxb_pmi_read(core_idx,
625*3942d3a8SSheetal Tigadoli 					PMI_ADDR_LANE0(DSC_SM_CTL22),
626*3942d3a8SSheetal Tigadoli 					&reg_d267);
627*3942d3a8SSheetal Tigadoli 
628*3942d3a8SSheetal Tigadoli 			if (((reg_d230 & 0xffff) != 0) &
629*3942d3a8SSheetal Tigadoli 					((reg_d267 & 0xc000) == 0xc000)) {
630*3942d3a8SSheetal Tigadoli 				break;
631*3942d3a8SSheetal Tigadoli 			}
632*3942d3a8SSheetal Tigadoli 			mdelay(1);
633*3942d3a8SSheetal Tigadoli 		}
634*3942d3a8SSheetal Tigadoli 
635*3942d3a8SSheetal Tigadoli 		if (!timeout)
636*3942d3a8SSheetal Tigadoli 			return -EIO;
637*3942d3a8SSheetal Tigadoli 
638*3942d3a8SSheetal Tigadoli 		timeout = UC_INIT_TIMEOUT;
639*3942d3a8SSheetal Tigadoli 		while (timeout--) {
640*3942d3a8SSheetal Tigadoli 			paxb_pmi_read(core_idx,
641*3942d3a8SSheetal Tigadoli 					PMI_ADDR_LANE1(UC_VERSION_NUM),
642*3942d3a8SSheetal Tigadoli 					&reg_d230);
643*3942d3a8SSheetal Tigadoli 			paxb_pmi_read(core_idx,
644*3942d3a8SSheetal Tigadoli 					PMI_ADDR_LANE1(DSC_SM_CTL22),
645*3942d3a8SSheetal Tigadoli 					&reg_d267);
646*3942d3a8SSheetal Tigadoli 
647*3942d3a8SSheetal Tigadoli 			if (((reg_d230 & 0xffff) != 0) &
648*3942d3a8SSheetal Tigadoli 					((reg_d267 & 0xc000) == 0xc000)) {
649*3942d3a8SSheetal Tigadoli 				break;
650*3942d3a8SSheetal Tigadoli 			}
651*3942d3a8SSheetal Tigadoli 			mdelay(1);
652*3942d3a8SSheetal Tigadoli 		}
653*3942d3a8SSheetal Tigadoli 
654*3942d3a8SSheetal Tigadoli 		if (!timeout)
655*3942d3a8SSheetal Tigadoli 			return -EIO;
656*3942d3a8SSheetal Tigadoli 	}
657*3942d3a8SSheetal Tigadoli 	return 0;
658*3942d3a8SSheetal Tigadoli }
659*3942d3a8SSheetal Tigadoli 
pcie_serdes_requires_patch(unsigned int serdes_idx)660*3942d3a8SSheetal Tigadoli static int pcie_serdes_requires_patch(unsigned int serdes_idx)
661*3942d3a8SSheetal Tigadoli {
662*3942d3a8SSheetal Tigadoli 	if (pipemux_idx != SERDES_PATCH_PIPEMUX_INDEX)
663*3942d3a8SSheetal Tigadoli 		return 0;
664*3942d3a8SSheetal Tigadoli 
665*3942d3a8SSheetal Tigadoli 	return !!((SERDES_PATCH_INDEX >> serdes_idx) & 0x1);
666*3942d3a8SSheetal Tigadoli }
667*3942d3a8SSheetal Tigadoli 
pcie_tx_coeff_p7(unsigned int core_idx)668*3942d3a8SSheetal Tigadoli static void pcie_tx_coeff_p7(unsigned int core_idx)
669*3942d3a8SSheetal Tigadoli {
670*3942d3a8SSheetal Tigadoli 	paxb_pmi_write(core_idx, PMI_ADDR_BCAST(0xd11b), 0x00aa);
671*3942d3a8SSheetal Tigadoli 	paxb_pmi_write(core_idx, PMI_ADDR_BCAST(0xd11c), 0x1155);
672*3942d3a8SSheetal Tigadoli 	paxb_pmi_write(core_idx, PMI_ADDR_BCAST(0xd11d), 0x2449);
673*3942d3a8SSheetal Tigadoli 	paxb_pmi_write(core_idx, PMI_ADDR_BCAST(0xd11e), 0x000f);
674*3942d3a8SSheetal Tigadoli 	paxb_pmi_write(core_idx, PMI_ADDR_BCAST(0xd307), 0x0001);
675*3942d3a8SSheetal Tigadoli }
676*3942d3a8SSheetal Tigadoli 
677*3942d3a8SSheetal Tigadoli 
paxb_sr_get_rc_link_width(unsigned int core_idx)678*3942d3a8SSheetal Tigadoli static unsigned int paxb_sr_get_rc_link_width(unsigned int core_idx)
679*3942d3a8SSheetal Tigadoli {
680*3942d3a8SSheetal Tigadoli 	return link_width_table[pipemux_idx][core_idx];
681*3942d3a8SSheetal Tigadoli }
682*3942d3a8SSheetal Tigadoli 
paxb_sr_get_rc_link_speed(void)683*3942d3a8SSheetal Tigadoli static uint32_t paxb_sr_get_rc_link_speed(void)
684*3942d3a8SSheetal Tigadoli {
685*3942d3a8SSheetal Tigadoli 	return GEN3_LINK_SPEED;
686*3942d3a8SSheetal Tigadoli }
687*3942d3a8SSheetal Tigadoli 
688*3942d3a8SSheetal Tigadoli 
paxb_serdes_init(unsigned int core_idx,unsigned int nr_serdes)689*3942d3a8SSheetal Tigadoli static int paxb_serdes_init(unsigned int core_idx, unsigned int nr_serdes)
690*3942d3a8SSheetal Tigadoli {
691*3942d3a8SSheetal Tigadoli 	uint32_t core_offset = core_idx * PCIE_CORE_PWR_OFFSET;
692*3942d3a8SSheetal Tigadoli 	unsigned int serdes;
693*3942d3a8SSheetal Tigadoli 	uintptr_t pmi_base;
694*3942d3a8SSheetal Tigadoli 	int ret;
695*3942d3a8SSheetal Tigadoli 
696*3942d3a8SSheetal Tigadoli 	/*
697*3942d3a8SSheetal Tigadoli 	 * Each serdes has a x2 link width
698*3942d3a8SSheetal Tigadoli 	 *
699*3942d3a8SSheetal Tigadoli 	 * Use PAXB to patch the serdes for proper RX termination through the
700*3942d3a8SSheetal Tigadoli 	 * PMI interface
701*3942d3a8SSheetal Tigadoli 	 */
702*3942d3a8SSheetal Tigadoli 	pmi_base = (uintptr_t)(PCIE_CORE_PMI_CFG_BASE + core_offset);
703*3942d3a8SSheetal Tigadoli 	for (serdes = 0; serdes < nr_serdes; serdes++) {
704*3942d3a8SSheetal Tigadoli 		/* select the PMI interface */
705*3942d3a8SSheetal Tigadoli 		mmio_write_32(pmi_base, serdes);
706*3942d3a8SSheetal Tigadoli 
707*3942d3a8SSheetal Tigadoli 		/* patch Serdes for RX termination */
708*3942d3a8SSheetal Tigadoli 		ret = paxb_pmi_write(core_idx, PMI_RX_TERM_SEQ,
709*3942d3a8SSheetal Tigadoli 				     PMI_RX_TERM_VAL);
710*3942d3a8SSheetal Tigadoli 		if (ret)
711*3942d3a8SSheetal Tigadoli 			goto err_pmi;
712*3942d3a8SSheetal Tigadoli 
713*3942d3a8SSheetal Tigadoli 		ret = paxb_pmi_write(core_idx, MERLIN16_PCIE_BLK2_PWRMGMT_7,
714*3942d3a8SSheetal Tigadoli 				     MERLIN16_PCIE_BLK2_PWRMGMT_7_VAL);
715*3942d3a8SSheetal Tigadoli 		if (ret)
716*3942d3a8SSheetal Tigadoli 			goto err_pmi;
717*3942d3a8SSheetal Tigadoli 
718*3942d3a8SSheetal Tigadoli 		ret = paxb_pmi_write(core_idx, MERLIN16_PCIE_BLK2_PWRMGMT_8,
719*3942d3a8SSheetal Tigadoli 				     MERLIN16_PCIE_BLK2_PWRMGMT_8_VAL);
720*3942d3a8SSheetal Tigadoli 		if (ret)
721*3942d3a8SSheetal Tigadoli 			goto err_pmi;
722*3942d3a8SSheetal Tigadoli 
723*3942d3a8SSheetal Tigadoli 		ret = paxb_pmi_write(core_idx, MERLIN16_AMS_TX_CTRL_5,
724*3942d3a8SSheetal Tigadoli 				     MERLIN16_AMS_TX_CTRL_5_VAL);
725*3942d3a8SSheetal Tigadoli 		if (ret)
726*3942d3a8SSheetal Tigadoli 			goto err_pmi;
727*3942d3a8SSheetal Tigadoli 
728*3942d3a8SSheetal Tigadoli 		pcie_tx_coeff_p7(core_idx);
729*3942d3a8SSheetal Tigadoli 
730*3942d3a8SSheetal Tigadoli 		if (pcie_serdes_requires_patch(serdes)) {
731*3942d3a8SSheetal Tigadoli 			if (((core_idx == 0) || (core_idx == 7))) {
732*3942d3a8SSheetal Tigadoli 				ret = paxb_pmi_write(core_idx,
733*3942d3a8SSheetal Tigadoli 						PMI_X8_CORE0_7_PATCH_SEQ,
734*3942d3a8SSheetal Tigadoli 						PMI_X8_CORE0_7_PATCH_VAL);
735*3942d3a8SSheetal Tigadoli 				if (ret)
736*3942d3a8SSheetal Tigadoli 					goto err_pmi;
737*3942d3a8SSheetal Tigadoli 			}
738*3942d3a8SSheetal Tigadoli 		}
739*3942d3a8SSheetal Tigadoli 	}
740*3942d3a8SSheetal Tigadoli 
741*3942d3a8SSheetal Tigadoli 	return 0;
742*3942d3a8SSheetal Tigadoli 
743*3942d3a8SSheetal Tigadoli err_pmi:
744*3942d3a8SSheetal Tigadoli 	ERROR("PCIe PMI write failed\n");
745*3942d3a8SSheetal Tigadoli 	return ret;
746*3942d3a8SSheetal Tigadoli }
747*3942d3a8SSheetal Tigadoli 
paxb_sr_phy_init(void)748*3942d3a8SSheetal Tigadoli static int paxb_sr_phy_init(void)
749*3942d3a8SSheetal Tigadoli {
750*3942d3a8SSheetal Tigadoli 	int ret;
751*3942d3a8SSheetal Tigadoli 	unsigned int core_idx;
752*3942d3a8SSheetal Tigadoli 
753*3942d3a8SSheetal Tigadoli #ifndef BOARD_PCIE_EXT_CLK
754*3942d3a8SSheetal Tigadoli 	ret = pcie_lcpll_init();
755*3942d3a8SSheetal Tigadoli 	if (ret)
756*3942d3a8SSheetal Tigadoli 		return ret;
757*3942d3a8SSheetal Tigadoli #else
758*3942d3a8SSheetal Tigadoli 	pcie_ext_clk_init();
759*3942d3a8SSheetal Tigadoli #endif
760*3942d3a8SSheetal Tigadoli 
761*3942d3a8SSheetal Tigadoli 	for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
762*3942d3a8SSheetal Tigadoli 		if (!pcie_core_needs_enable(core_idx))
763*3942d3a8SSheetal Tigadoli 			continue;
764*3942d3a8SSheetal Tigadoli 		unsigned int link_width;
765*3942d3a8SSheetal Tigadoli 
766*3942d3a8SSheetal Tigadoli 		paxb_serdes_gate_clock(core_idx, 0);
767*3942d3a8SSheetal Tigadoli 
768*3942d3a8SSheetal Tigadoli 		link_width = paxb->get_link_width(core_idx);
769*3942d3a8SSheetal Tigadoli 		if (!link_width) {
770*3942d3a8SSheetal Tigadoli 			ERROR("Unsupported PIPEMUX\n");
771*3942d3a8SSheetal Tigadoli 			return -EOPNOTSUPP;
772*3942d3a8SSheetal Tigadoli 		}
773*3942d3a8SSheetal Tigadoli 
774*3942d3a8SSheetal Tigadoli 		ret = paxb_serdes_init(core_idx, link_width / 2);
775*3942d3a8SSheetal Tigadoli 		if (ret) {
776*3942d3a8SSheetal Tigadoli 			ERROR("PCIe serdes initialization failed for core %u\n",
777*3942d3a8SSheetal Tigadoli 			      core_idx);
778*3942d3a8SSheetal Tigadoli 			return ret;
779*3942d3a8SSheetal Tigadoli 		}
780*3942d3a8SSheetal Tigadoli 
781*3942d3a8SSheetal Tigadoli 
782*3942d3a8SSheetal Tigadoli 		ret = paxb_gen3_serdes_init(core_idx, link_width / 2);
783*3942d3a8SSheetal Tigadoli 		if (ret) {
784*3942d3a8SSheetal Tigadoli 			ERROR("PCIe GEN3 serdes initialization failed\n");
785*3942d3a8SSheetal Tigadoli 			return ret;
786*3942d3a8SSheetal Tigadoli 		}
787*3942d3a8SSheetal Tigadoli 
788*3942d3a8SSheetal Tigadoli 	}
789*3942d3a8SSheetal Tigadoli 	return 0;
790*3942d3a8SSheetal Tigadoli }
791*3942d3a8SSheetal Tigadoli 
792*3942d3a8SSheetal Tigadoli const paxb_cfg sr_paxb_cfg = {
793*3942d3a8SSheetal Tigadoli 	.type = PAXB_SR,
794*3942d3a8SSheetal Tigadoli 	.device_id = SR_B0_DEVICE_ID,
795*3942d3a8SSheetal Tigadoli 	.pipemux_init = pipemux_sr_init,
796*3942d3a8SSheetal Tigadoli 	.phy_init = paxb_sr_phy_init,
797*3942d3a8SSheetal Tigadoli 	.core_needs_enable = paxb_sr_core_needs_enable,
798*3942d3a8SSheetal Tigadoli 	.num_cores = NUM_OF_SR_PCIE_CORES,
799*3942d3a8SSheetal Tigadoli 	.get_link_width = paxb_sr_get_rc_link_width,
800*3942d3a8SSheetal Tigadoli 	.get_link_speed = paxb_sr_get_rc_link_speed,
801*3942d3a8SSheetal Tigadoli };
802*3942d3a8SSheetal Tigadoli 
paxb_get_sr_config(void)803*3942d3a8SSheetal Tigadoli const paxb_cfg *paxb_get_sr_config(void)
804*3942d3a8SSheetal Tigadoli {
805*3942d3a8SSheetal Tigadoli 	return &sr_paxb_cfg;
806*3942d3a8SSheetal Tigadoli }
807