blob: bc9332cb74a394e4ef78880c7251e63b596e6c8b [file] [log] [blame]
Stefan Roeseede2c662021-04-07 09:12:38 +02001// SPDX-License-Identifier: GPL-2.0+
2/*
Stefan Roese03f13af2022-04-07 09:11:54 +02003 * Copyright (C) 2021-2022 Stefan Roese <sr@denx.de>
Stefan Roeseede2c662021-04-07 09:12:38 +02004 */
5
Aaron Williamsd64d7e32022-09-02 13:57:52 +02006#include <cyclic.h>
Stefan Roeseede2c662021-04-07 09:12:38 +02007#include <dm.h>
Simon Glass1cedca12023-08-21 21:17:01 -06008#include <event.h>
Stefan Roeseede2c662021-04-07 09:12:38 +02009#include <ram.h>
Aaron Williamsd64d7e32022-09-02 13:57:52 +020010#include <time.h>
Stefan Roese03f13af2022-04-07 09:11:54 +020011#include <asm/gpio.h>
Stefan Roeseede2c662021-04-07 09:12:38 +020012
13#include <mach/octeon_ddr.h>
14#include <mach/cvmx-qlm.h>
15#include <mach/octeon_qlm.h>
16#include <mach/octeon_fdt.h>
17#include <mach/cvmx-helper.h>
18#include <mach/cvmx-helper-cfg.h>
19#include <mach/cvmx-helper-util.h>
20#include <mach/cvmx-bgxx-defs.h>
Aaron Williamsd64d7e32022-09-02 13:57:52 +020021#include <mach/cvmx-dtx-defs.h>
Stefan Roeseede2c662021-04-07 09:12:38 +020022
23#include "board_ddr.h"
24
Aaron Williamsd64d7e32022-09-02 13:57:52 +020025/**
26 * cvmx_spem#_cfg_rd
27 *
28 * This register allows read access to the configuration in the PCIe core.
29 *
30 */
31union cvmx_spemx_cfg_rd {
32 u64 u64;
33 struct cvmx_spemx_cfg_rd_s {
34 u64 data : 32;
35 u64 addr : 32;
36 } s;
37 struct cvmx_spemx_cfg_rd_s cn73xx;
38};
39
40/**
41 * cvmx_spem#_cfg_wr
42 *
43 * This register allows write access to the configuration in the PCIe core.
44 *
45 */
46union cvmx_spemx_cfg_wr {
47 u64 u64;
48 struct cvmx_spemx_cfg_wr_s {
49 u64 data : 32;
50 u64 addr : 32;
51 } s;
52 struct cvmx_spemx_cfg_wr_s cn73xx;
53};
54
55/**
56 * cvmx_spem#_flr_pf_stopreq
57 *
58 * PF function level reset stop outbound requests register.
59 * Hardware automatically sets the STOPREQ bit for the PF when it enters a
60 * function level reset (FLR). Software is responsible for clearing the STOPREQ
61 * bit but must not do so prior to hardware taking down the FLR, which could be
62 * as long as 100ms. It may be appropriate for software to wait longer before clearing
63 * STOPREQ, software may need to drain deep DPI queues for example.
64 * Whenever SPEM receives a PF or child VF request mastered by CNXXXX over S2M (i.e. P or NP),
65 * when STOPREQ is set for the function, SPEM will discard the outgoing request
66 * before sending it to the PCIe core. If a NP, SPEM will schedule an immediate
67 * SWI_RSP_ERROR completion for the request - no timeout is required.
68 * In both cases, SPEM()_DBG_PF()_INFO[P()_BMD_E] will be set and a error
69 * interrupt is generated.
70 *
71 * STOPREQ mimics the behavior of PCIEEP()_CFG001[ME] for outbound requests that will
72 * master the PCIe bus (P and NP).
73 *
74 * STOPREQ will have no effect on completions returned by CNXXXX over the S2M,
75 * nor on M2S traffic.
76 *
77 * When a PF()_STOPREQ is set, none of the associated
78 * PEM()_FLR_PF()_VF_STOPREQ[VF_STOPREQ] will be set.
79 *
80 * STOPREQ is reset when the MAC is reset, and is not reset after a chip soft reset.
81 */
82union cvmx_spemx_flr_pf_stopreq {
83 u64 u64;
84 struct cvmx_spemx_flr_pf_stopreq_s {
85 u64 reserved_3_63 : 61;
86 u64 pf2_stopreq : 1;
87 u64 pf1_stopreq : 1;
88 u64 pf0_stopreq : 1;
89 } s;
90 struct cvmx_spemx_flr_pf_stopreq_s cn73xx;
91};
92
93#define CVMX_SPEMX_CFG_WR(offset) 0x00011800C0000028ull
94#define CVMX_SPEMX_CFG_RD(offset) 0x00011800C0000030ull
95#define CVMX_SPEMX_FLR_PF_STOPREQ(offset) 0x00011800C0000218ull
96
97#define DTX_SELECT_LTSSM 0x0
98#define DTX_SELECT_LTSSM_ENA 0x3ff
99#define LTSSM_L0 0x11
100
Stefan Roeseede2c662021-04-07 09:12:38 +0200101#define NIC23_DEF_DRAM_FREQ 800
102
Aaron Williamsd64d7e32022-09-02 13:57:52 +0200103static u32 pci_cfgspace_reg0[2] = { 0, 0 };
104
Stefan Roeseede2c662021-04-07 09:12:38 +0200105static u8 octeon_nic23_cfg0_spd_values[512] = {
106 OCTEON_NIC23_CFG0_SPD_VALUES
107};
108
109static struct ddr_conf board_ddr_conf[] = {
110 OCTEON_NIC23_DDR_CONFIGURATION
111};
112
113struct ddr_conf *octeon_ddr_conf_table_get(int *count, int *def_ddr_freq)
114{
115 *count = ARRAY_SIZE(board_ddr_conf);
116 *def_ddr_freq = NIC23_DEF_DRAM_FREQ;
117
118 return board_ddr_conf;
119}
120
121int board_fix_fdt(void *fdt)
122{
123 u32 range_data[5 * 8];
124 bool rev4;
125 int node;
126 int rc;
127
128 /*
129 * ToDo:
130 * Read rev4 info from EEPROM or where the original U-Boot does
131 * and don't hard-code it here.
132 */
133 rev4 = true;
134
135 debug("%s() rev4: %s\n", __func__, rev4 ? "true" : "false");
136 /* Patch the PHY configuration based on board revision */
137 rc = octeon_fdt_patch_rename(fdt,
138 rev4 ? "4,nor-flash" : "4,no-nor-flash",
139 "cavium,board-trim", false, NULL, NULL);
140 if (!rev4) {
141 /* Modify the ranges for CS 0 */
142 node = fdt_node_offset_by_compatible(fdt, -1,
143 "cavium,octeon-3860-bootbus");
144 if (node < 0) {
145 printf("%s: Error: cannot find boot bus in device tree!\n",
146 __func__);
147 return -1;
148 }
149
150 rc = fdtdec_get_int_array(fdt, node, "ranges",
151 range_data, 5 * 8);
152 if (rc) {
153 printf("%s: Error reading ranges from boot bus FDT\n",
154 __func__);
155 return -1;
156 }
157 range_data[2] = cpu_to_fdt32(0x10000);
158 range_data[3] = 0;
159 range_data[4] = 0;
160 rc = fdt_setprop(fdt, node, "ranges", range_data,
161 sizeof(range_data));
162 if (rc) {
163 printf("%s: Error updating boot bus ranges in fdt\n",
164 __func__);
165 }
166 }
167 return rc;
168}
169
Stefan Roese03f13af2022-04-07 09:11:54 +0200170int board_early_init_f(void)
171{
172 struct gpio_desc gpio = {};
173 ofnode node;
174
175 /* Initial GPIO configuration */
176
177 /* GPIO 7: Vitesse reset */
178 node = ofnode_by_compatible(ofnode_null(), "vitesse,vsc7224");
179 if (ofnode_valid(node)) {
180 gpio_request_by_name_nodev(node, "los", 0, &gpio, GPIOD_IS_IN);
181 dm_gpio_free(gpio.dev, &gpio);
182 gpio_request_by_name_nodev(node, "reset", 0, &gpio,
183 GPIOD_IS_OUT);
184 if (dm_gpio_is_valid(&gpio)) {
185 /* Vitesse reset */
186 debug("%s: Setting GPIO 7 to 1\n", __func__);
187 dm_gpio_set_value(&gpio, 1);
188 }
189 dm_gpio_free(gpio.dev, &gpio);
190 }
191
192 /* SFP+ transmitters */
193 ofnode_for_each_compatible_node(node, "ethernet,sfp-slot") {
194 gpio_request_by_name_nodev(node, "tx_disable", 0,
195 &gpio, GPIOD_IS_OUT);
196 if (dm_gpio_is_valid(&gpio)) {
197 debug("%s: Setting GPIO %d to 1\n", __func__,
198 gpio.offset);
199 dm_gpio_set_value(&gpio, 1);
200 }
201 dm_gpio_free(gpio.dev, &gpio);
202 gpio_request_by_name_nodev(node, "mod_abs", 0, &gpio,
203 GPIOD_IS_IN);
204 dm_gpio_free(gpio.dev, &gpio);
205 gpio_request_by_name_nodev(node, "tx_error", 0, &gpio,
206 GPIOD_IS_IN);
207 dm_gpio_free(gpio.dev, &gpio);
208 gpio_request_by_name_nodev(node, "rx_los", 0, &gpio,
209 GPIOD_IS_IN);
210 dm_gpio_free(gpio.dev, &gpio);
211 }
212
213 return 0;
214}
215
Stefan Roeseede2c662021-04-07 09:12:38 +0200216void board_configure_qlms(void)
217{
218 octeon_configure_qlm(4, 3000, CVMX_QLM_MODE_SATA_2X1, 0, 0, 0, 0);
219 octeon_configure_qlm(5, 103125, CVMX_QLM_MODE_XFI_1X2, 0, 0, 2, 0);
220 /* Apply amplitude tuning to 10G interface */
221 octeon_qlm_tune_v3(0, 4, 3000, -1, -1, 7, -1);
222 octeon_qlm_tune_v3(0, 5, 103125, 0x19, 0x0, -1, -1);
223 octeon_qlm_set_channel_v3(0, 5, 0);
224 octeon_qlm_dfe_disable(0, 5, -1, 103125, CVMX_QLM_MODE_XFI_1X2);
225 debug("QLM 4 reference clock: %d\n"
226 "DLM 5 reference clock: %d\n",
227 cvmx_qlm_measure_clock(4), cvmx_qlm_measure_clock(5));
228}
229
Aaron Williamsd64d7e32022-09-02 13:57:52 +0200230/**
231 * If there is a PF FLR then the PCI EEPROM is not re-read. In this case
232 * we need to re-program the vendor and device ID immediately after hardware
233 * completes FLR.
234 *
235 * PCI spec requires FLR to be completed within 100ms. The user who triggered
236 * FLR expects hardware to finish FLR within 100ms, otherwise the user will
237 * end up reading DEVICE_ID incorrectly from the reset value.
238 * CN23XX exits FLR at any point between 66 and 99ms, so U-Boot has to wait
239 * 99ms to let hardware finish its part, then finish reprogramming the
240 * correct device ID before the end of 100ms.
241 *
242 * Note: this solution only works properly when there is no other activity
243 * within U-Boot for 100ms from the time FLR is triggered.
244 *
245 * This function gets called every 100usec. If FLR happens during any
246 * other activity like bootloader/image update then it is possible that
247 * this function does not get called for more than the FLR period which will
248 * cause the PF device ID restore to happen after whoever initiated the FLR to
249 * read the incorrect device ID 0x9700 (reset value) instead of 0x9702
250 * (restored value).
251 */
252static void octeon_board_restore_pf(void *ctx)
253{
254 union cvmx_spemx_flr_pf_stopreq stopreq;
255 static bool start_initialized[2] = {false, false};
256 bool pf0_flag, pf1_flag;
257 u64 ltssm_bits;
258 const u64 pf_flr_wait_usecs = 99700;
259 u64 elapsed_usecs;
260 union cvmx_spemx_cfg_wr cfg_wr;
261 union cvmx_spemx_cfg_rd cfg_rd;
262 static u64 start_us[2];
263 int pf_num;
264
265 csr_wr(CVMX_DTX_SPEM_SELX(0), DTX_SELECT_LTSSM);
266 csr_rd(CVMX_DTX_SPEM_SELX(0));
267 csr_wr(CVMX_DTX_SPEM_ENAX(0), DTX_SELECT_LTSSM_ENA);
268 csr_rd(CVMX_DTX_SPEM_ENAX(0));
269 ltssm_bits = csr_rd(CVMX_DTX_SPEM_DATX(0));
270 if (((ltssm_bits >> 3) & 0x3f) != LTSSM_L0)
271 return;
272
273 stopreq.u64 = csr_rd(CVMX_SPEMX_FLR_PF_STOPREQ(0));
274 pf0_flag = stopreq.s.pf0_stopreq;
275 pf1_flag = stopreq.s.pf1_stopreq;
276 /* See if PF interrupt happened */
277 if (!(pf0_flag || pf1_flag))
278 return;
279
280 if (pf0_flag && !start_initialized[0]) {
281 start_initialized[0] = true;
282 start_us[0] = get_timer_us(0);
283 }
284
285 /* Store programmed PCIe DevID SPEM0 PF0 */
286 if (pf0_flag && !pci_cfgspace_reg0[0]) {
287 cfg_rd.s.addr = (0 << 24) | 0x0;
288 csr_wr(CVMX_SPEMX_CFG_RD(0), cfg_rd.u64);
289 cfg_rd.u64 = csr_rd(CVMX_SPEMX_CFG_RD(0));
290 pci_cfgspace_reg0[0] = cfg_rd.s.data;
291 }
292
293 if (pf1_flag && !start_initialized[1]) {
294 start_initialized[1] = true;
295 start_us[1] = get_timer_us(0);
296 }
297
298 /* Store programmed PCIe DevID SPEM0 PF1 */
299 if (pf1_flag && !pci_cfgspace_reg0[1]) {
300 cfg_rd.s.addr = (1 << 24) | 0x0;
301 csr_wr(CVMX_SPEMX_CFG_RD(0), cfg_rd.u64);
302 cfg_rd.u64 = csr_rd(CVMX_SPEMX_CFG_RD(0));
303 pci_cfgspace_reg0[1] = cfg_rd.s.data;
304 }
305
306 /* For PF, rewrite pci config space reg 0 */
307 for (pf_num = 0; pf_num < 2; pf_num++) {
308 if (!start_initialized[pf_num])
309 continue;
310
311 elapsed_usecs = get_timer_us(0) - start_us[pf_num];
312
313 if (elapsed_usecs > pf_flr_wait_usecs) {
314 /* Here, our measured FLR duration has passed;
315 * check if device ID has been reset,
316 * which indicates FLR completion (per MA team).
317 */
318 cfg_rd.s.addr = (pf_num << 24) | 0x0;
319 csr_wr(CVMX_SPEMX_CFG_RD(0), cfg_rd.u64);
320 cfg_rd.u64 = csr_rd(CVMX_SPEMX_CFG_RD(0));
321 /* if DevID has NOT been reset, FLR is not yet
322 * complete
323 */
324 if (cfg_rd.s.data != pci_cfgspace_reg0[pf_num]) {
325 stopreq.s.pf0_stopreq = (pf_num == 0) ? 1 : 0;
326 stopreq.s.pf1_stopreq = (pf_num == 1) ? 1 : 0;
327 csr_wr(CVMX_SPEMX_FLR_PF_STOPREQ(0), stopreq.u64);
328
329 cfg_wr.u64 = 0;
330 cfg_wr.s.addr = (pf_num << 24) | 0;
331 cfg_wr.s.data = pci_cfgspace_reg0[pf_num];
332 csr_wr(CVMX_SPEMX_CFG_WR(0), cfg_wr.u64);
333 start_initialized[pf_num] = false;
334 }
335 }
336 }
337}
338
Stefan Roeseede2c662021-04-07 09:12:38 +0200339int board_late_init(void)
340{
Aaron Williamsd64d7e32022-09-02 13:57:52 +0200341 struct cyclic_info *cyclic;
Stefan Roese03f13af2022-04-07 09:11:54 +0200342 struct gpio_desc gpio = {};
343 ofnode node;
344
345 /* Turn on SFP+ transmitters */
346 ofnode_for_each_compatible_node(node, "ethernet,sfp-slot") {
347 gpio_request_by_name_nodev(node, "tx_disable", 0,
348 &gpio, GPIOD_IS_OUT);
349 if (dm_gpio_is_valid(&gpio)) {
350 debug("%s: Setting GPIO %d to 0\n", __func__,
351 gpio.offset);
352 dm_gpio_set_value(&gpio, 0);
353 }
354 dm_gpio_free(gpio.dev, &gpio);
355 }
356
Stefan Roeseede2c662021-04-07 09:12:38 +0200357 board_configure_qlms();
358
Aaron Williamsd64d7e32022-09-02 13:57:52 +0200359 /* Register cyclic function for PCIe FLR fixup */
360 cyclic = cyclic_register(octeon_board_restore_pf, 100,
361 "pcie_flr_fix", NULL);
362 if (!cyclic)
363 printf("Registering of cyclic function failed\n");
364
Stefan Roeseede2c662021-04-07 09:12:38 +0200365 return 0;
366}
Stefan Roese03f13af2022-04-07 09:11:54 +0200367
Simon Glass1cedca12023-08-21 21:17:01 -0600368static int last_stage_init(void)
Stefan Roese03f13af2022-04-07 09:11:54 +0200369{
370 struct gpio_desc gpio = {};
371 ofnode node;
372
373 node = ofnode_by_compatible(ofnode_null(), "vitesse,vsc7224");
374 if (!ofnode_valid(node)) {
375 printf("Vitesse SPF DT node not found!");
376 return 0;
377 }
378
379 gpio_request_by_name_nodev(node, "reset", 0, &gpio, GPIOD_IS_OUT);
380 if (dm_gpio_is_valid(&gpio)) {
381 /* Take Vitesse retimer out of reset */
382 debug("%s: Setting GPIO 7 to 0\n", __func__);
383 dm_gpio_set_value(&gpio, 0);
384 mdelay(50);
385 }
386 dm_gpio_free(gpio.dev, &gpio);
387
388 return 0;
389}
Simon Glass1cedca12023-08-21 21:17:01 -0600390EVENT_SPY_SIMPLE(EVT_LAST_STAGE_INIT, last_stage_init);