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 ®_d230);
624*3942d3a8SSheetal Tigadoli paxb_pmi_read(core_idx,
625*3942d3a8SSheetal Tigadoli PMI_ADDR_LANE0(DSC_SM_CTL22),
626*3942d3a8SSheetal Tigadoli ®_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 ®_d230);
643*3942d3a8SSheetal Tigadoli paxb_pmi_read(core_idx,
644*3942d3a8SSheetal Tigadoli PMI_ADDR_LANE1(DSC_SM_CTL22),
645*3942d3a8SSheetal Tigadoli ®_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