2 * Copyright (C) Marvell International Ltd. and its affiliates
4 * SPDX-License-Identifier: GPL-2.0
10 #include <asm/arch/cpu.h>
11 #include <asm/arch/soc.h>
14 #include "sys_env_lib.h"
16 __weak void board_pex_config(void)
18 /* nothing in this weak default implementation */
21 int hws_pex_config(const struct serdes_map *serdes_map, u8 count)
23 u32 pex_idx, tmp, next_busno, first_busno, temp_pex_reg,
24 temp_reg, addr, dev_id, ctrl_mode;
25 enum serdes_type serdes_type;
28 DEBUG_INIT_FULL_S("\n### hws_pex_config ###\n");
30 for (idx = 0; idx < count; idx++) {
31 serdes_type = serdes_map[idx].serdes_type;
32 /* configuration for PEX only */
33 if ((serdes_type != PEX0) && (serdes_type != PEX1) &&
34 (serdes_type != PEX2) && (serdes_type != PEX3))
37 if ((serdes_type != PEX0) &&
38 ((serdes_map[idx].serdes_mode == PEX_ROOT_COMPLEX_X4) ||
39 (serdes_map[idx].serdes_mode == PEX_END_POINT_X4))) {
40 /* for PEX by4 - relevant for the first port only */
44 pex_idx = serdes_type - PEX0;
45 tmp = reg_read(PEX_CAPABILITIES_REG(pex_idx));
48 reg_write(PEX_CAPABILITIES_REG(pex_idx), tmp);
51 tmp = reg_read(SOC_CTRL_REG);
54 for (idx = 0; idx < count; idx++) {
55 serdes_type = serdes_map[idx].serdes_type;
56 if ((serdes_type != PEX0) &&
57 ((serdes_map[idx].serdes_mode == PEX_ROOT_COMPLEX_X4) ||
58 (serdes_map[idx].serdes_mode == PEX_END_POINT_X4))) {
59 /* for PEX by4 - relevant for the first port only */
63 switch (serdes_type) {
65 tmp |= 0x1 << PCIE0_ENABLE_OFFS;
68 tmp |= 0x1 << PCIE1_ENABLE_OFFS;
71 tmp |= 0x1 << PCIE2_ENABLE_OFFS;
74 tmp |= 0x1 << PCIE3_ENABLE_OFFS;
81 reg_write(SOC_CTRL_REG, tmp);
83 /* Support gen1/gen2 */
84 DEBUG_INIT_FULL_S("Support gen1/gen2\n");
91 for (idx = 0; idx < count; idx++) {
92 serdes_type = serdes_map[idx].serdes_type;
93 DEBUG_INIT_FULL_S(" serdes_type=0x");
94 DEBUG_INIT_FULL_D(serdes_type, 8);
95 DEBUG_INIT_FULL_S("\n");
96 DEBUG_INIT_FULL_S(" idx=0x");
97 DEBUG_INIT_FULL_D(idx, 8);
98 DEBUG_INIT_FULL_S("\n");
100 /* Configuration for PEX only */
101 if ((serdes_type != PEX0) && (serdes_type != PEX1) &&
102 (serdes_type != PEX2) && (serdes_type != PEX3))
105 if ((serdes_type != PEX0) &&
106 ((serdes_map[idx].serdes_mode == PEX_ROOT_COMPLEX_X4) ||
107 (serdes_map[idx].serdes_mode == PEX_END_POINT_X4))) {
108 /* for PEX by4 - relevant for the first port only */
112 pex_idx = serdes_type - PEX0;
113 tmp = reg_read(PEX_DBG_STATUS_REG(pex_idx));
115 first_busno = next_busno;
116 if ((tmp & 0x7f) != 0x7e) {
117 DEBUG_INIT_S("PCIe, Idx ");
118 DEBUG_INIT_D(pex_idx, 1);
119 DEBUG_INIT_S(": detected no link\n");
124 temp_pex_reg = reg_read((PEX_CFG_DIRECT_ACCESS
125 (pex_idx, PEX_LINK_CAPABILITY_REG)));
127 if (temp_pex_reg != 0x2)
130 temp_reg = (reg_read(PEX_CFG_DIRECT_ACCESS(
132 PEX_LINK_CTRL_STAT_REG)) &
135 /* Check if the link established is GEN1 */
137 ("Checking if the link established is gen1\n");
141 pex_local_bus_num_set(pex_idx, first_busno);
142 pex_local_dev_num_set(pex_idx, 1);
143 DEBUG_INIT_FULL_S("PCIe, Idx ");
144 DEBUG_INIT_FULL_D(pex_idx, 1);
146 DEBUG_INIT_S(":** Link is Gen1, check the EP capability\n");
147 /* link is Gen1, check the EP capability */
148 addr = pex_config_read(pex_idx, first_busno, 0, 0, 0x34) & 0xff;
149 DEBUG_INIT_FULL_C("pex_config_read: return addr=0x%x", addr, 4);
152 ("pex_config_read: return 0xff -->PCIe (%d): Detected No Link.",
157 while ((pex_config_read(pex_idx, first_busno, 0, 0, addr)
159 addr = (pex_config_read(pex_idx, first_busno, 0,
160 0, addr) & 0xff00) >> 8;
163 /* Check for Gen2 and above */
164 if ((pex_config_read(pex_idx, first_busno, 0, 0,
165 addr + 0xc) & 0xf) < 0x2) {
166 DEBUG_INIT_S("PCIe, Idx ");
167 DEBUG_INIT_D(pex_idx, 1);
168 DEBUG_INIT_S(": remains Gen1\n");
172 tmp = reg_read(PEX_LINK_CTRL_STATUS2_REG(pex_idx));
173 DEBUG_RD_REG(PEX_LINK_CTRL_STATUS2_REG(pex_idx), tmp);
174 tmp &= ~(BIT(0) | BIT(1));
176 tmp |= BIT(6); /* Select Deemphasize (-3.5d_b) */
177 reg_write(PEX_LINK_CTRL_STATUS2_REG(pex_idx), tmp);
178 DEBUG_WR_REG(PEX_LINK_CTRL_STATUS2_REG(pex_idx), tmp);
180 tmp = reg_read(PEX_CTRL_REG(pex_idx));
181 DEBUG_RD_REG(PEX_CTRL_REG(pex_idx), tmp);
183 reg_write(PEX_CTRL_REG(pex_idx), tmp);
184 DEBUG_WR_REG(PEX_CTRL_REG(pex_idx), tmp);
187 * We need to wait 10ms before reading the PEX_DBG_STATUS_REG
188 * in order not to read the status of the former state
192 DEBUG_INIT_S("PCIe, Idx ");
193 DEBUG_INIT_D(pex_idx, 1);
195 (": Link upgraded to Gen2 based on client capabilities\n");
198 /* Update pex DEVICE ID */
199 ctrl_mode = sys_env_model_get();
201 for (idx = 0; idx < count; idx++) {
202 serdes_type = serdes_map[idx].serdes_type;
203 /* configuration for PEX only */
204 if ((serdes_type != PEX0) && (serdes_type != PEX1) &&
205 (serdes_type != PEX2) && (serdes_type != PEX3))
208 if ((serdes_type != PEX0) &&
209 ((serdes_map[idx].serdes_mode == PEX_ROOT_COMPLEX_X4) ||
210 (serdes_map[idx].serdes_mode == PEX_END_POINT_X4))) {
211 /* for PEX by4 - relevant for the first port only */
215 pex_idx = serdes_type - PEX0;
216 dev_id = reg_read(PEX_CFG_DIRECT_ACCESS
217 (pex_idx, PEX_DEVICE_AND_VENDOR_ID));
219 dev_id |= ((ctrl_mode << 16) & 0xffff0000);
220 reg_write(PEX_CFG_DIRECT_ACCESS
221 (pex_idx, PEX_DEVICE_AND_VENDOR_ID), dev_id);
223 DEBUG_INIT_FULL_C("Update PEX Device ID ", ctrl_mode, 4);
228 int pex_local_bus_num_set(u32 pex_if, u32 bus_num)
232 DEBUG_INIT_FULL_S("\n### pex_local_bus_num_set ###\n");
234 if (bus_num >= MAX_PEX_BUSSES) {
235 DEBUG_INIT_C("pex_local_bus_num_set: Illegal bus number %d\n",
240 pex_status = reg_read(PEX_STATUS_REG(pex_if));
241 pex_status &= ~PXSR_PEX_BUS_NUM_MASK;
243 (bus_num << PXSR_PEX_BUS_NUM_OFFS) & PXSR_PEX_BUS_NUM_MASK;
244 reg_write(PEX_STATUS_REG(pex_if), pex_status);
249 int pex_local_dev_num_set(u32 pex_if, u32 dev_num)
253 DEBUG_INIT_FULL_S("\n### pex_local_dev_num_set ###\n");
255 pex_status = reg_read(PEX_STATUS_REG(pex_if));
256 pex_status &= ~PXSR_PEX_DEV_NUM_MASK;
258 (dev_num << PXSR_PEX_DEV_NUM_OFFS) & PXSR_PEX_DEV_NUM_MASK;
259 reg_write(PEX_STATUS_REG(pex_if), pex_status);
265 * pex_config_read - Read from configuration space
268 * This function performs a 32 bit read from PEX configuration space.
269 * It supports both type 0 and type 1 of Configuration Transactions
270 * (local and over bridge). In order to read from local bus segment, use
271 * bus number retrieved from pex_local_bus_num_get(). Other bus numbers
272 * will result configuration transaction of type 1 (over bridge).
275 * pex_if - PEX interface number.
276 * bus - PEX segment bus number.
277 * dev - PEX device number.
278 * func - Function number.
279 * reg_offs - Register offset.
285 * 32bit register data, 0xffffffff on error
287 u32 pex_config_read(u32 pex_if, u32 bus, u32 dev, u32 func, u32 reg_off)
290 u32 local_dev, local_bus;
293 pex_status = reg_read(PEX_STATUS_REG(pex_if));
295 ((pex_status & PXSR_PEX_DEV_NUM_MASK) >> PXSR_PEX_DEV_NUM_OFFS);
297 ((pex_status & PXSR_PEX_BUS_NUM_MASK) >> PXSR_PEX_BUS_NUM_OFFS);
300 * In PCI Express we have only one device number
301 * and this number is the first number we encounter
302 * else that the local_dev
303 * spec pex define return on config read/write on any device
305 if (bus == local_bus) {
306 if (local_dev == 0) {
308 * if local dev is 0 then the first number we encounter
311 if ((dev != 1) && (dev != local_dev))
315 * if local dev is not 0 then the first number we
318 if ((dev != 0) && (dev != local_dev))
323 /* Creating PEX address to be passed */
324 pex_data = (bus << PXCAR_BUS_NUM_OFFS);
325 pex_data |= (dev << PXCAR_DEVICE_NUM_OFFS);
326 pex_data |= (func << PXCAR_FUNC_NUM_OFFS);
327 /* Legacy register space */
328 pex_data |= (reg_off & PXCAR_REG_NUM_MASK);
329 /* Extended register space */
330 pex_data |= (((reg_off & PXCAR_REAL_EXT_REG_NUM_MASK) >>
331 PXCAR_REAL_EXT_REG_NUM_OFFS) << PXCAR_EXT_REG_NUM_OFFS);
332 pex_data |= PXCAR_CONFIG_EN;
334 /* Write the address to the PEX configuration address register */
335 reg_write(PEX_CFG_ADDR_REG(pex_if), pex_data);
338 * In order to let the PEX controller absorbed the address
339 * of the read transaction we perform a validity check that
340 * the address was written
342 if (pex_data != reg_read(PEX_CFG_ADDR_REG(pex_if)))
345 /* Cleaning Master Abort */
346 reg_bit_set(PEX_CFG_DIRECT_ACCESS(pex_if, PEX_STATUS_AND_COMMAND),
348 /* Read the Data returned in the PEX Data register */
349 pex_data = reg_read(PEX_CFG_DATA_REG(pex_if));
351 DEBUG_INIT_FULL_C(" --> ", pex_data, 4);