1edb47025SStefan Roese /*
2edb47025SStefan Roese * Copyright (C) Marvell International Ltd. and its affiliates
3edb47025SStefan Roese *
4edb47025SStefan Roese * SPDX-License-Identifier: GPL-2.0
5edb47025SStefan Roese */
6edb47025SStefan Roese
7edb47025SStefan Roese #include <common.h>
8edb47025SStefan Roese #include <spl.h>
9edb47025SStefan Roese #include <asm/io.h>
10edb47025SStefan Roese #include <asm/arch/cpu.h>
11edb47025SStefan Roese #include <asm/arch/soc.h>
12edb47025SStefan Roese
13edb47025SStefan Roese #include "ctrl_pex.h"
14edb47025SStefan Roese #include "sys_env_lib.h"
15edb47025SStefan Roese
board_pex_config(void)16*2ad43094SMario Six __weak void board_pex_config(void)
17*2ad43094SMario Six {
18*2ad43094SMario Six /* nothing in this weak default implementation */
19*2ad43094SMario Six }
20*2ad43094SMario Six
hws_pex_config(const struct serdes_map * serdes_map,u8 count)21490753acSKevin Smith int hws_pex_config(const struct serdes_map *serdes_map, u8 count)
22edb47025SStefan Roese {
23edb47025SStefan Roese u32 pex_idx, tmp, next_busno, first_busno, temp_pex_reg,
24edb47025SStefan Roese temp_reg, addr, dev_id, ctrl_mode;
25edb47025SStefan Roese enum serdes_type serdes_type;
26490753acSKevin Smith u32 idx;
27edb47025SStefan Roese
28edb47025SStefan Roese DEBUG_INIT_FULL_S("\n### hws_pex_config ###\n");
29edb47025SStefan Roese
30490753acSKevin Smith for (idx = 0; idx < count; idx++) {
31edb47025SStefan Roese serdes_type = serdes_map[idx].serdes_type;
32edb47025SStefan Roese /* configuration for PEX only */
33edb47025SStefan Roese if ((serdes_type != PEX0) && (serdes_type != PEX1) &&
34edb47025SStefan Roese (serdes_type != PEX2) && (serdes_type != PEX3))
35edb47025SStefan Roese continue;
36edb47025SStefan Roese
37edb47025SStefan Roese if ((serdes_type != PEX0) &&
38edb47025SStefan Roese ((serdes_map[idx].serdes_mode == PEX_ROOT_COMPLEX_X4) ||
39edb47025SStefan Roese (serdes_map[idx].serdes_mode == PEX_END_POINT_X4))) {
40edb47025SStefan Roese /* for PEX by4 - relevant for the first port only */
41edb47025SStefan Roese continue;
42edb47025SStefan Roese }
43edb47025SStefan Roese
44edb47025SStefan Roese pex_idx = serdes_type - PEX0;
45edb47025SStefan Roese tmp = reg_read(PEX_CAPABILITIES_REG(pex_idx));
46edb47025SStefan Roese tmp &= ~(0xf << 20);
47edb47025SStefan Roese tmp |= (0x4 << 20);
48edb47025SStefan Roese reg_write(PEX_CAPABILITIES_REG(pex_idx), tmp);
49edb47025SStefan Roese }
50edb47025SStefan Roese
51edb47025SStefan Roese tmp = reg_read(SOC_CTRL_REG);
52edb47025SStefan Roese tmp &= ~0x03;
53edb47025SStefan Roese
54490753acSKevin Smith for (idx = 0; idx < count; idx++) {
55edb47025SStefan Roese serdes_type = serdes_map[idx].serdes_type;
56edb47025SStefan Roese if ((serdes_type != PEX0) &&
57edb47025SStefan Roese ((serdes_map[idx].serdes_mode == PEX_ROOT_COMPLEX_X4) ||
58edb47025SStefan Roese (serdes_map[idx].serdes_mode == PEX_END_POINT_X4))) {
59edb47025SStefan Roese /* for PEX by4 - relevant for the first port only */
60edb47025SStefan Roese continue;
61edb47025SStefan Roese }
62edb47025SStefan Roese
63edb47025SStefan Roese switch (serdes_type) {
64edb47025SStefan Roese case PEX0:
65edb47025SStefan Roese tmp |= 0x1 << PCIE0_ENABLE_OFFS;
66edb47025SStefan Roese break;
67edb47025SStefan Roese case PEX1:
68edb47025SStefan Roese tmp |= 0x1 << PCIE1_ENABLE_OFFS;
69edb47025SStefan Roese break;
70edb47025SStefan Roese case PEX2:
71edb47025SStefan Roese tmp |= 0x1 << PCIE2_ENABLE_OFFS;
72edb47025SStefan Roese break;
73edb47025SStefan Roese case PEX3:
74edb47025SStefan Roese tmp |= 0x1 << PCIE3_ENABLE_OFFS;
75edb47025SStefan Roese break;
76edb47025SStefan Roese default:
77edb47025SStefan Roese break;
78edb47025SStefan Roese }
79edb47025SStefan Roese }
80edb47025SStefan Roese
81edb47025SStefan Roese reg_write(SOC_CTRL_REG, tmp);
82edb47025SStefan Roese
83edb47025SStefan Roese /* Support gen1/gen2 */
84edb47025SStefan Roese DEBUG_INIT_FULL_S("Support gen1/gen2\n");
85*2ad43094SMario Six
86*2ad43094SMario Six board_pex_config();
87*2ad43094SMario Six
88edb47025SStefan Roese next_busno = 0;
89edb47025SStefan Roese mdelay(150);
90edb47025SStefan Roese
91490753acSKevin Smith for (idx = 0; idx < count; idx++) {
92edb47025SStefan Roese serdes_type = serdes_map[idx].serdes_type;
93edb47025SStefan Roese DEBUG_INIT_FULL_S(" serdes_type=0x");
94edb47025SStefan Roese DEBUG_INIT_FULL_D(serdes_type, 8);
95edb47025SStefan Roese DEBUG_INIT_FULL_S("\n");
96edb47025SStefan Roese DEBUG_INIT_FULL_S(" idx=0x");
97edb47025SStefan Roese DEBUG_INIT_FULL_D(idx, 8);
98edb47025SStefan Roese DEBUG_INIT_FULL_S("\n");
99edb47025SStefan Roese
100edb47025SStefan Roese /* Configuration for PEX only */
101edb47025SStefan Roese if ((serdes_type != PEX0) && (serdes_type != PEX1) &&
102edb47025SStefan Roese (serdes_type != PEX2) && (serdes_type != PEX3))
103edb47025SStefan Roese continue;
104edb47025SStefan Roese
105edb47025SStefan Roese if ((serdes_type != PEX0) &&
106edb47025SStefan Roese ((serdes_map[idx].serdes_mode == PEX_ROOT_COMPLEX_X4) ||
107edb47025SStefan Roese (serdes_map[idx].serdes_mode == PEX_END_POINT_X4))) {
108edb47025SStefan Roese /* for PEX by4 - relevant for the first port only */
109edb47025SStefan Roese continue;
110edb47025SStefan Roese }
111edb47025SStefan Roese
112edb47025SStefan Roese pex_idx = serdes_type - PEX0;
113edb47025SStefan Roese tmp = reg_read(PEX_DBG_STATUS_REG(pex_idx));
114edb47025SStefan Roese
115edb47025SStefan Roese first_busno = next_busno;
116edb47025SStefan Roese if ((tmp & 0x7f) != 0x7e) {
117edb47025SStefan Roese DEBUG_INIT_S("PCIe, Idx ");
118edb47025SStefan Roese DEBUG_INIT_D(pex_idx, 1);
119edb47025SStefan Roese DEBUG_INIT_S(": detected no link\n");
120edb47025SStefan Roese continue;
121edb47025SStefan Roese }
122edb47025SStefan Roese
123edb47025SStefan Roese next_busno++;
124edb47025SStefan Roese temp_pex_reg = reg_read((PEX_CFG_DIRECT_ACCESS
125edb47025SStefan Roese (pex_idx, PEX_LINK_CAPABILITY_REG)));
126edb47025SStefan Roese temp_pex_reg &= 0xf;
127edb47025SStefan Roese if (temp_pex_reg != 0x2)
128edb47025SStefan Roese continue;
129edb47025SStefan Roese
130edb47025SStefan Roese temp_reg = (reg_read(PEX_CFG_DIRECT_ACCESS(
131edb47025SStefan Roese pex_idx,
132edb47025SStefan Roese PEX_LINK_CTRL_STAT_REG)) &
133edb47025SStefan Roese 0xf0000) >> 16;
134edb47025SStefan Roese
135edb47025SStefan Roese /* Check if the link established is GEN1 */
136edb47025SStefan Roese DEBUG_INIT_FULL_S
137edb47025SStefan Roese ("Checking if the link established is gen1\n");
138edb47025SStefan Roese if (temp_reg != 0x1)
139edb47025SStefan Roese continue;
140edb47025SStefan Roese
141edb47025SStefan Roese pex_local_bus_num_set(pex_idx, first_busno);
142edb47025SStefan Roese pex_local_dev_num_set(pex_idx, 1);
143edb47025SStefan Roese DEBUG_INIT_FULL_S("PCIe, Idx ");
144edb47025SStefan Roese DEBUG_INIT_FULL_D(pex_idx, 1);
145edb47025SStefan Roese
146edb47025SStefan Roese DEBUG_INIT_S(":** Link is Gen1, check the EP capability\n");
147edb47025SStefan Roese /* link is Gen1, check the EP capability */
148edb47025SStefan Roese addr = pex_config_read(pex_idx, first_busno, 0, 0, 0x34) & 0xff;
149edb47025SStefan Roese DEBUG_INIT_FULL_C("pex_config_read: return addr=0x%x", addr, 4);
150edb47025SStefan Roese if (addr == 0xff) {
151edb47025SStefan Roese DEBUG_INIT_FULL_C
152edb47025SStefan Roese ("pex_config_read: return 0xff -->PCIe (%d): Detected No Link.",
153edb47025SStefan Roese pex_idx, 1);
154edb47025SStefan Roese continue;
155edb47025SStefan Roese }
156edb47025SStefan Roese
157edb47025SStefan Roese while ((pex_config_read(pex_idx, first_busno, 0, 0, addr)
158edb47025SStefan Roese & 0xff) != 0x10) {
159edb47025SStefan Roese addr = (pex_config_read(pex_idx, first_busno, 0,
160edb47025SStefan Roese 0, addr) & 0xff00) >> 8;
161edb47025SStefan Roese }
162edb47025SStefan Roese
163edb47025SStefan Roese /* Check for Gen2 and above */
164edb47025SStefan Roese if ((pex_config_read(pex_idx, first_busno, 0, 0,
165edb47025SStefan Roese addr + 0xc) & 0xf) < 0x2) {
166edb47025SStefan Roese DEBUG_INIT_S("PCIe, Idx ");
167edb47025SStefan Roese DEBUG_INIT_D(pex_idx, 1);
168edb47025SStefan Roese DEBUG_INIT_S(": remains Gen1\n");
169edb47025SStefan Roese continue;
170edb47025SStefan Roese }
171edb47025SStefan Roese
172edb47025SStefan Roese tmp = reg_read(PEX_LINK_CTRL_STATUS2_REG(pex_idx));
173edb47025SStefan Roese DEBUG_RD_REG(PEX_LINK_CTRL_STATUS2_REG(pex_idx), tmp);
174edb47025SStefan Roese tmp &= ~(BIT(0) | BIT(1));
175edb47025SStefan Roese tmp |= BIT(1);
176edb47025SStefan Roese tmp |= BIT(6); /* Select Deemphasize (-3.5d_b) */
177edb47025SStefan Roese reg_write(PEX_LINK_CTRL_STATUS2_REG(pex_idx), tmp);
178edb47025SStefan Roese DEBUG_WR_REG(PEX_LINK_CTRL_STATUS2_REG(pex_idx), tmp);
179edb47025SStefan Roese
180edb47025SStefan Roese tmp = reg_read(PEX_CTRL_REG(pex_idx));
181edb47025SStefan Roese DEBUG_RD_REG(PEX_CTRL_REG(pex_idx), tmp);
182edb47025SStefan Roese tmp |= BIT(10);
183edb47025SStefan Roese reg_write(PEX_CTRL_REG(pex_idx), tmp);
184edb47025SStefan Roese DEBUG_WR_REG(PEX_CTRL_REG(pex_idx), tmp);
185edb47025SStefan Roese
186edb47025SStefan Roese /*
187edb47025SStefan Roese * We need to wait 10ms before reading the PEX_DBG_STATUS_REG
188edb47025SStefan Roese * in order not to read the status of the former state
189edb47025SStefan Roese */
190edb47025SStefan Roese mdelay(10);
191edb47025SStefan Roese
192edb47025SStefan Roese DEBUG_INIT_S("PCIe, Idx ");
193edb47025SStefan Roese DEBUG_INIT_D(pex_idx, 1);
194edb47025SStefan Roese DEBUG_INIT_S
195c90d7ab6SChris Packham (": Link upgraded to Gen2 based on client capabilities\n");
196edb47025SStefan Roese }
197edb47025SStefan Roese
198edb47025SStefan Roese /* Update pex DEVICE ID */
199edb47025SStefan Roese ctrl_mode = sys_env_model_get();
200edb47025SStefan Roese
201490753acSKevin Smith for (idx = 0; idx < count; idx++) {
202edb47025SStefan Roese serdes_type = serdes_map[idx].serdes_type;
203edb47025SStefan Roese /* configuration for PEX only */
204edb47025SStefan Roese if ((serdes_type != PEX0) && (serdes_type != PEX1) &&
205edb47025SStefan Roese (serdes_type != PEX2) && (serdes_type != PEX3))
206edb47025SStefan Roese continue;
207edb47025SStefan Roese
208edb47025SStefan Roese if ((serdes_type != PEX0) &&
209edb47025SStefan Roese ((serdes_map[idx].serdes_mode == PEX_ROOT_COMPLEX_X4) ||
210edb47025SStefan Roese (serdes_map[idx].serdes_mode == PEX_END_POINT_X4))) {
211edb47025SStefan Roese /* for PEX by4 - relevant for the first port only */
212edb47025SStefan Roese continue;
213edb47025SStefan Roese }
214edb47025SStefan Roese
215edb47025SStefan Roese pex_idx = serdes_type - PEX0;
216edb47025SStefan Roese dev_id = reg_read(PEX_CFG_DIRECT_ACCESS
217edb47025SStefan Roese (pex_idx, PEX_DEVICE_AND_VENDOR_ID));
218edb47025SStefan Roese dev_id &= 0xffff;
219edb47025SStefan Roese dev_id |= ((ctrl_mode << 16) & 0xffff0000);
220edb47025SStefan Roese reg_write(PEX_CFG_DIRECT_ACCESS
221edb47025SStefan Roese (pex_idx, PEX_DEVICE_AND_VENDOR_ID), dev_id);
222edb47025SStefan Roese }
223edb47025SStefan Roese DEBUG_INIT_FULL_C("Update PEX Device ID ", ctrl_mode, 4);
224edb47025SStefan Roese
225edb47025SStefan Roese return MV_OK;
226edb47025SStefan Roese }
227edb47025SStefan Roese
pex_local_bus_num_set(u32 pex_if,u32 bus_num)228edb47025SStefan Roese int pex_local_bus_num_set(u32 pex_if, u32 bus_num)
229edb47025SStefan Roese {
230edb47025SStefan Roese u32 pex_status;
231edb47025SStefan Roese
232edb47025SStefan Roese DEBUG_INIT_FULL_S("\n### pex_local_bus_num_set ###\n");
233edb47025SStefan Roese
234edb47025SStefan Roese if (bus_num >= MAX_PEX_BUSSES) {
235edb47025SStefan Roese DEBUG_INIT_C("pex_local_bus_num_set: Illegal bus number %d\n",
236edb47025SStefan Roese bus_num, 4);
237edb47025SStefan Roese return MV_BAD_PARAM;
238edb47025SStefan Roese }
239edb47025SStefan Roese
240edb47025SStefan Roese pex_status = reg_read(PEX_STATUS_REG(pex_if));
241edb47025SStefan Roese pex_status &= ~PXSR_PEX_BUS_NUM_MASK;
242edb47025SStefan Roese pex_status |=
243edb47025SStefan Roese (bus_num << PXSR_PEX_BUS_NUM_OFFS) & PXSR_PEX_BUS_NUM_MASK;
244edb47025SStefan Roese reg_write(PEX_STATUS_REG(pex_if), pex_status);
245edb47025SStefan Roese
246edb47025SStefan Roese return MV_OK;
247edb47025SStefan Roese }
248edb47025SStefan Roese
pex_local_dev_num_set(u32 pex_if,u32 dev_num)249edb47025SStefan Roese int pex_local_dev_num_set(u32 pex_if, u32 dev_num)
250edb47025SStefan Roese {
251edb47025SStefan Roese u32 pex_status;
252edb47025SStefan Roese
253edb47025SStefan Roese DEBUG_INIT_FULL_S("\n### pex_local_dev_num_set ###\n");
254edb47025SStefan Roese
255edb47025SStefan Roese pex_status = reg_read(PEX_STATUS_REG(pex_if));
256edb47025SStefan Roese pex_status &= ~PXSR_PEX_DEV_NUM_MASK;
257edb47025SStefan Roese pex_status |=
258edb47025SStefan Roese (dev_num << PXSR_PEX_DEV_NUM_OFFS) & PXSR_PEX_DEV_NUM_MASK;
259edb47025SStefan Roese reg_write(PEX_STATUS_REG(pex_if), pex_status);
260edb47025SStefan Roese
261edb47025SStefan Roese return MV_OK;
262edb47025SStefan Roese }
263edb47025SStefan Roese
264edb47025SStefan Roese /*
265edb47025SStefan Roese * pex_config_read - Read from configuration space
266edb47025SStefan Roese *
267edb47025SStefan Roese * DESCRIPTION:
268edb47025SStefan Roese * This function performs a 32 bit read from PEX configuration space.
269edb47025SStefan Roese * It supports both type 0 and type 1 of Configuration Transactions
270edb47025SStefan Roese * (local and over bridge). In order to read from local bus segment, use
271edb47025SStefan Roese * bus number retrieved from pex_local_bus_num_get(). Other bus numbers
272edb47025SStefan Roese * will result configuration transaction of type 1 (over bridge).
273edb47025SStefan Roese *
274edb47025SStefan Roese * INPUT:
275edb47025SStefan Roese * pex_if - PEX interface number.
276edb47025SStefan Roese * bus - PEX segment bus number.
277edb47025SStefan Roese * dev - PEX device number.
278edb47025SStefan Roese * func - Function number.
279edb47025SStefan Roese * reg_offs - Register offset.
280edb47025SStefan Roese *
281edb47025SStefan Roese * OUTPUT:
282edb47025SStefan Roese * None.
283edb47025SStefan Roese *
284edb47025SStefan Roese * RETURN:
285edb47025SStefan Roese * 32bit register data, 0xffffffff on error
286edb47025SStefan Roese */
pex_config_read(u32 pex_if,u32 bus,u32 dev,u32 func,u32 reg_off)287edb47025SStefan Roese u32 pex_config_read(u32 pex_if, u32 bus, u32 dev, u32 func, u32 reg_off)
288edb47025SStefan Roese {
289edb47025SStefan Roese u32 pex_data = 0;
290edb47025SStefan Roese u32 local_dev, local_bus;
291edb47025SStefan Roese u32 pex_status;
292edb47025SStefan Roese
293edb47025SStefan Roese pex_status = reg_read(PEX_STATUS_REG(pex_if));
294edb47025SStefan Roese local_dev =
295edb47025SStefan Roese ((pex_status & PXSR_PEX_DEV_NUM_MASK) >> PXSR_PEX_DEV_NUM_OFFS);
296edb47025SStefan Roese local_bus =
297edb47025SStefan Roese ((pex_status & PXSR_PEX_BUS_NUM_MASK) >> PXSR_PEX_BUS_NUM_OFFS);
298edb47025SStefan Roese
299edb47025SStefan Roese /*
300edb47025SStefan Roese * In PCI Express we have only one device number
301edb47025SStefan Roese * and this number is the first number we encounter
302edb47025SStefan Roese * else that the local_dev
303edb47025SStefan Roese * spec pex define return on config read/write on any device
304edb47025SStefan Roese */
305edb47025SStefan Roese if (bus == local_bus) {
306edb47025SStefan Roese if (local_dev == 0) {
307edb47025SStefan Roese /*
308edb47025SStefan Roese * if local dev is 0 then the first number we encounter
309edb47025SStefan Roese * after 0 is 1
310edb47025SStefan Roese */
311edb47025SStefan Roese if ((dev != 1) && (dev != local_dev))
312edb47025SStefan Roese return MV_ERROR;
313edb47025SStefan Roese } else {
314edb47025SStefan Roese /*
315edb47025SStefan Roese * if local dev is not 0 then the first number we
316edb47025SStefan Roese * encounter is 0
317edb47025SStefan Roese */
318edb47025SStefan Roese if ((dev != 0) && (dev != local_dev))
319edb47025SStefan Roese return MV_ERROR;
320edb47025SStefan Roese }
321edb47025SStefan Roese }
322edb47025SStefan Roese
323edb47025SStefan Roese /* Creating PEX address to be passed */
324edb47025SStefan Roese pex_data = (bus << PXCAR_BUS_NUM_OFFS);
325edb47025SStefan Roese pex_data |= (dev << PXCAR_DEVICE_NUM_OFFS);
326edb47025SStefan Roese pex_data |= (func << PXCAR_FUNC_NUM_OFFS);
327edb47025SStefan Roese /* Legacy register space */
328edb47025SStefan Roese pex_data |= (reg_off & PXCAR_REG_NUM_MASK);
329edb47025SStefan Roese /* Extended register space */
330edb47025SStefan Roese pex_data |= (((reg_off & PXCAR_REAL_EXT_REG_NUM_MASK) >>
331edb47025SStefan Roese PXCAR_REAL_EXT_REG_NUM_OFFS) << PXCAR_EXT_REG_NUM_OFFS);
332edb47025SStefan Roese pex_data |= PXCAR_CONFIG_EN;
333edb47025SStefan Roese
334edb47025SStefan Roese /* Write the address to the PEX configuration address register */
335edb47025SStefan Roese reg_write(PEX_CFG_ADDR_REG(pex_if), pex_data);
336edb47025SStefan Roese
337edb47025SStefan Roese /*
338edb47025SStefan Roese * In order to let the PEX controller absorbed the address
339edb47025SStefan Roese * of the read transaction we perform a validity check that
340edb47025SStefan Roese * the address was written
341edb47025SStefan Roese */
342edb47025SStefan Roese if (pex_data != reg_read(PEX_CFG_ADDR_REG(pex_if)))
343edb47025SStefan Roese return MV_ERROR;
344edb47025SStefan Roese
345edb47025SStefan Roese /* Cleaning Master Abort */
346edb47025SStefan Roese reg_bit_set(PEX_CFG_DIRECT_ACCESS(pex_if, PEX_STATUS_AND_COMMAND),
347edb47025SStefan Roese PXSAC_MABORT);
348edb47025SStefan Roese /* Read the Data returned in the PEX Data register */
349edb47025SStefan Roese pex_data = reg_read(PEX_CFG_DATA_REG(pex_if));
350edb47025SStefan Roese
351edb47025SStefan Roese DEBUG_INIT_FULL_C(" --> ", pex_data, 4);
352edb47025SStefan Roese
353edb47025SStefan Roese return pex_data;
354edb47025SStefan Roese }
355