blob: 9e5b647e2555437f0f9dd059d8114063e173fadb [file] [log] [blame]
Stefan Roese6a905952015-04-20 09:31:27 +02001/*
2 * Copyright (C) Marvell International Ltd. and its affiliates
3 *
4 * SPDX-License-Identifier: GPL-2.0
5 */
6
7#include <common.h>
8#include <spl.h>
9#include <asm/io.h>
10#include <asm/arch/cpu.h>
11#include <asm/arch/soc.h>
12
13#include "ctrl_pex.h"
14#include "sys_env_lib.h"
15
Mario Sixa3d18342017-01-11 16:00:47 +010016__weak void board_pex_config(void)
17{
18 /* nothing in this weak default implementation */
19}
20
Kevin Smith6406d432015-10-23 17:53:19 +000021int hws_pex_config(const struct serdes_map *serdes_map, u8 count)
Stefan Roese6a905952015-04-20 09:31:27 +020022{
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;
Kevin Smith6406d432015-10-23 17:53:19 +000026 u32 idx;
Stefan Roese6a905952015-04-20 09:31:27 +020027
28 DEBUG_INIT_FULL_S("\n### hws_pex_config ###\n");
29
Kevin Smith6406d432015-10-23 17:53:19 +000030 for (idx = 0; idx < count; idx++) {
Stefan Roese6a905952015-04-20 09:31:27 +020031 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))
35 continue;
36
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 */
41 continue;
42 }
43
44 pex_idx = serdes_type - PEX0;
45 tmp = reg_read(PEX_CAPABILITIES_REG(pex_idx));
46 tmp &= ~(0xf << 20);
47 tmp |= (0x4 << 20);
48 reg_write(PEX_CAPABILITIES_REG(pex_idx), tmp);
49 }
50
51 tmp = reg_read(SOC_CTRL_REG);
52 tmp &= ~0x03;
53
Kevin Smith6406d432015-10-23 17:53:19 +000054 for (idx = 0; idx < count; idx++) {
Stefan Roese6a905952015-04-20 09:31:27 +020055 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 */
60 continue;
61 }
62
63 switch (serdes_type) {
64 case PEX0:
65 tmp |= 0x1 << PCIE0_ENABLE_OFFS;
66 break;
67 case PEX1:
68 tmp |= 0x1 << PCIE1_ENABLE_OFFS;
69 break;
70 case PEX2:
71 tmp |= 0x1 << PCIE2_ENABLE_OFFS;
72 break;
73 case PEX3:
74 tmp |= 0x1 << PCIE3_ENABLE_OFFS;
75 break;
76 default:
77 break;
78 }
79 }
80
81 reg_write(SOC_CTRL_REG, tmp);
82
83 /* Support gen1/gen2 */
84 DEBUG_INIT_FULL_S("Support gen1/gen2\n");
Mario Sixa3d18342017-01-11 16:00:47 +010085
86 board_pex_config();
87
Stefan Roese6a905952015-04-20 09:31:27 +020088 next_busno = 0;
89 mdelay(150);
90
Kevin Smith6406d432015-10-23 17:53:19 +000091 for (idx = 0; idx < count; idx++) {
Stefan Roese6a905952015-04-20 09:31:27 +020092 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");
99
100 /* Configuration for PEX only */
101 if ((serdes_type != PEX0) && (serdes_type != PEX1) &&
102 (serdes_type != PEX2) && (serdes_type != PEX3))
103 continue;
104
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 */
109 continue;
110 }
111
112 pex_idx = serdes_type - PEX0;
113 tmp = reg_read(PEX_DBG_STATUS_REG(pex_idx));
114
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");
120 continue;
121 }
122
123 next_busno++;
124 temp_pex_reg = reg_read((PEX_CFG_DIRECT_ACCESS
125 (pex_idx, PEX_LINK_CAPABILITY_REG)));
126 temp_pex_reg &= 0xf;
127 if (temp_pex_reg != 0x2)
128 continue;
129
130 temp_reg = (reg_read(PEX_CFG_DIRECT_ACCESS(
131 pex_idx,
132 PEX_LINK_CTRL_STAT_REG)) &
133 0xf0000) >> 16;
134
135 /* Check if the link established is GEN1 */
136 DEBUG_INIT_FULL_S
137 ("Checking if the link established is gen1\n");
138 if (temp_reg != 0x1)
139 continue;
140
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);
145
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);
150 if (addr == 0xff) {
151 DEBUG_INIT_FULL_C
152 ("pex_config_read: return 0xff -->PCIe (%d): Detected No Link.",
153 pex_idx, 1);
154 continue;
155 }
156
157 while ((pex_config_read(pex_idx, first_busno, 0, 0, addr)
158 & 0xff) != 0x10) {
159 addr = (pex_config_read(pex_idx, first_busno, 0,
160 0, addr) & 0xff00) >> 8;
161 }
162
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");
169 continue;
170 }
171
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));
175 tmp |= 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);
179
180 tmp = reg_read(PEX_CTRL_REG(pex_idx));
181 DEBUG_RD_REG(PEX_CTRL_REG(pex_idx), tmp);
182 tmp |= BIT(10);
183 reg_write(PEX_CTRL_REG(pex_idx), tmp);
184 DEBUG_WR_REG(PEX_CTRL_REG(pex_idx), tmp);
185
186 /*
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
189 */
190 mdelay(10);
191
192 DEBUG_INIT_S("PCIe, Idx ");
193 DEBUG_INIT_D(pex_idx, 1);
194 DEBUG_INIT_S
Chris Packham26898db2016-08-23 12:07:39 +1200195 (": Link upgraded to Gen2 based on client capabilities\n");
Stefan Roese6a905952015-04-20 09:31:27 +0200196 }
197
198 /* Update pex DEVICE ID */
199 ctrl_mode = sys_env_model_get();
200
Kevin Smith6406d432015-10-23 17:53:19 +0000201 for (idx = 0; idx < count; idx++) {
Stefan Roese6a905952015-04-20 09:31:27 +0200202 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))
206 continue;
207
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 */
212 continue;
213 }
214
215 pex_idx = serdes_type - PEX0;
216 dev_id = reg_read(PEX_CFG_DIRECT_ACCESS
217 (pex_idx, PEX_DEVICE_AND_VENDOR_ID));
218 dev_id &= 0xffff;
219 dev_id |= ((ctrl_mode << 16) & 0xffff0000);
220 reg_write(PEX_CFG_DIRECT_ACCESS
221 (pex_idx, PEX_DEVICE_AND_VENDOR_ID), dev_id);
222 }
223 DEBUG_INIT_FULL_C("Update PEX Device ID ", ctrl_mode, 4);
224
225 return MV_OK;
226}
227
228int pex_local_bus_num_set(u32 pex_if, u32 bus_num)
229{
230 u32 pex_status;
231
232 DEBUG_INIT_FULL_S("\n### pex_local_bus_num_set ###\n");
233
234 if (bus_num >= MAX_PEX_BUSSES) {
235 DEBUG_INIT_C("pex_local_bus_num_set: Illegal bus number %d\n",
236 bus_num, 4);
237 return MV_BAD_PARAM;
238 }
239
240 pex_status = reg_read(PEX_STATUS_REG(pex_if));
241 pex_status &= ~PXSR_PEX_BUS_NUM_MASK;
242 pex_status |=
243 (bus_num << PXSR_PEX_BUS_NUM_OFFS) & PXSR_PEX_BUS_NUM_MASK;
244 reg_write(PEX_STATUS_REG(pex_if), pex_status);
245
246 return MV_OK;
247}
248
249int pex_local_dev_num_set(u32 pex_if, u32 dev_num)
250{
251 u32 pex_status;
252
253 DEBUG_INIT_FULL_S("\n### pex_local_dev_num_set ###\n");
254
255 pex_status = reg_read(PEX_STATUS_REG(pex_if));
256 pex_status &= ~PXSR_PEX_DEV_NUM_MASK;
257 pex_status |=
258 (dev_num << PXSR_PEX_DEV_NUM_OFFS) & PXSR_PEX_DEV_NUM_MASK;
259 reg_write(PEX_STATUS_REG(pex_if), pex_status);
260
261 return MV_OK;
262}
263
264/*
265 * pex_config_read - Read from configuration space
266 *
267 * DESCRIPTION:
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).
273 *
274 * INPUT:
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.
280 *
281 * OUTPUT:
282 * None.
283 *
284 * RETURN:
285 * 32bit register data, 0xffffffff on error
286 */
287u32 pex_config_read(u32 pex_if, u32 bus, u32 dev, u32 func, u32 reg_off)
288{
289 u32 pex_data = 0;
290 u32 local_dev, local_bus;
291 u32 pex_status;
292
293 pex_status = reg_read(PEX_STATUS_REG(pex_if));
294 local_dev =
295 ((pex_status & PXSR_PEX_DEV_NUM_MASK) >> PXSR_PEX_DEV_NUM_OFFS);
296 local_bus =
297 ((pex_status & PXSR_PEX_BUS_NUM_MASK) >> PXSR_PEX_BUS_NUM_OFFS);
298
299 /*
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
304 */
305 if (bus == local_bus) {
306 if (local_dev == 0) {
307 /*
308 * if local dev is 0 then the first number we encounter
309 * after 0 is 1
310 */
311 if ((dev != 1) && (dev != local_dev))
312 return MV_ERROR;
313 } else {
314 /*
315 * if local dev is not 0 then the first number we
316 * encounter is 0
317 */
318 if ((dev != 0) && (dev != local_dev))
319 return MV_ERROR;
320 }
321 }
322
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;
333
334 /* Write the address to the PEX configuration address register */
335 reg_write(PEX_CFG_ADDR_REG(pex_if), pex_data);
336
337 /*
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
341 */
342 if (pex_data != reg_read(PEX_CFG_ADDR_REG(pex_if)))
343 return MV_ERROR;
344
345 /* Cleaning Master Abort */
346 reg_bit_set(PEX_CFG_DIRECT_ACCESS(pex_if, PEX_STATUS_AND_COMMAND),
347 PXSAC_MABORT);
348 /* Read the Data returned in the PEX Data register */
349 pex_data = reg_read(PEX_CFG_DATA_REG(pex_if));
350
351 DEBUG_INIT_FULL_C(" --> ", pex_data, 4);
352
353 return pex_data;
354}