blob: c771da61a6861c8ca4639603d9430f662e921772 [file] [log] [blame]
Aaron Williamsb2ea8182020-06-30 12:08:56 +02001// SPDX-License-Identifier: GPL-2.0+
2/*
Stefan Roese957317e2022-04-07 09:11:47 +02003 * Copyright (C) 2020-2022 Marvell International Ltd.
Aaron Williamsb2ea8182020-06-30 12:08:56 +02004 */
5
Stefan Roese469171b2021-04-07 09:12:32 +02006#include <dm.h>
7#include <dm/uclass.h>
8#include <env.h>
9#include <iomux.h>
Aaron Williamsb2ea8182020-06-30 12:08:56 +020010#include <asm/global_data.h>
11#include <linux/bitfield.h>
12#include <linux/bitops.h>
13#include <linux/compat.h>
14#include <linux/io.h>
15#include <mach/clock.h>
16#include <mach/cavm-reg.h>
Stefan Roese469171b2021-04-07 09:12:32 +020017#include <mach/cvmx-bootmem.h>
Stefan Roese9e9bcb02021-04-07 09:12:33 +020018#include <mach/cvmx-regs.h>
19#include <mach/cvmx-sata-defs.h>
Stefan Roese957317e2022-04-07 09:11:47 +020020#include <mach/octeon-model.h>
21#include <mach/octeon-feature.h>
Aaron Williamsb2ea8182020-06-30 12:08:56 +020022
23DECLARE_GLOBAL_DATA_PTR;
24
Stefan Roese72a49ef2020-08-24 13:04:39 +020025/*
Stefan Roese469171b2021-04-07 09:12:32 +020026 * Important:
27 * This address cannot be changed as the PCI console tool relies on exactly
28 * this value!
29 */
30#define BOOTLOADER_BOOTMEM_DESC_ADDR 0x6c100
31#define BOOTLOADER_BOOTMEM_DESC_SPACE (BOOTLOADER_BOOTMEM_DESC_ADDR + 0x8)
32
33#define OCTEON_RESERVED_LOW_BOOT_MEM_SIZE (1024 * 1024)
34
35#define BOOTCMD_NAME "pci-bootcmd"
36#define CONSOLE_NAME "pci-console@0"
37#define OCTEON_BOOTLOADER_LOAD_MEM_NAME "__tmp_load"
38
39/*
Stefan Roese72a49ef2020-08-24 13:04:39 +020040 * TRUE for devices having registers with little-endian byte
41 * order, FALSE for registers with native-endian byte order.
42 * PCI mandates little-endian, USB and SATA are configurable,
43 * but we chose little-endian for these.
44 *
45 * This table will be referened in the Octeon platform specific
46 * mangle-port.h header.
47 */
48const bool octeon_should_swizzle_table[256] = {
49 [0x00] = true, /* bootbus/CF */
50 [0x1b] = true, /* PCI mmio window */
51 [0x1c] = true, /* PCI mmio window */
52 [0x1d] = true, /* PCI mmio window */
53 [0x1e] = true, /* PCI mmio window */
54 [0x68] = true, /* OCTEON III USB */
55 [0x69] = true, /* OCTEON III USB */
Stefan Roese72a49ef2020-08-24 13:04:39 +020056 [0x6f] = true, /* OCTEON II USB */
57};
58
Aaron Williamsb2ea8182020-06-30 12:08:56 +020059static int get_clocks(void)
60{
61 const u64 ref_clock = PLL_REF_CLK;
62 void __iomem *rst_boot;
63 u64 val;
64
65 rst_boot = ioremap(CAVM_RST_BOOT, 0);
66 val = ioread64(rst_boot);
67 gd->cpu_clk = ref_clock * FIELD_GET(RST_BOOT_C_MUL, val);
68 gd->bus_clk = ref_clock * FIELD_GET(RST_BOOT_PNR_MUL, val);
69
Simon Glassf782d542024-08-21 10:19:15 -060070 debug("%s: cpu: %lu, bus: %u\n", __func__, gd->cpu_clk, gd->bus_clk);
Aaron Williamsb2ea8182020-06-30 12:08:56 +020071
72 return 0;
73}
74
75/* Early mach init code run from flash */
76int mach_cpu_init(void)
77{
78 void __iomem *mio_boot_reg_cfg0;
79
80 /* Remap boot-bus 0x1fc0.0000 -> 0x1f40.0000 */
81 /* ToDo: Move this to an early running bus (bootbus) DM driver */
82 mio_boot_reg_cfg0 = ioremap(CAVM_MIO_BOOT_REG_CFG0, 0);
83 clrsetbits_be64(mio_boot_reg_cfg0, 0xffff, 0x1f40);
84
85 /* Get clocks and store them in GD */
86 get_clocks();
87
88 return 0;
89}
90
91/**
92 * Returns number of cores
93 *
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +010094 * Return: number of CPU cores for the specified node
Aaron Williamsb2ea8182020-06-30 12:08:56 +020095 */
96static int cavm_octeon_num_cores(void)
97{
98 void __iomem *ciu_fuse;
99
100 ciu_fuse = ioremap(CAVM_CIU_FUSE, 0);
101 return fls64(ioread64(ciu_fuse) & 0xffffffffffff);
102}
103
104int print_cpuinfo(void)
105{
106 printf("SoC: Octeon CN73xx (%d cores)\n", cavm_octeon_num_cores());
107
108 return 0;
109}
Stefan Roese469171b2021-04-07 09:12:32 +0200110
111static int octeon_bootmem_init(void)
112{
113 int ret;
114
115 /* Call old single-node func: it uses only gd->ram_size */
116 ret = cvmx_bootmem_phy_mem_list_init(gd->ram_size,
117 OCTEON_RESERVED_LOW_BOOT_MEM_SIZE,
118 (void *)CKSEG0ADDR(BOOTLOADER_BOOTMEM_DESC_SPACE));
119 if (!ret) {
120 printf("FATAL: Error initializing bootmem list\n");
121 return -ENOSPC;
122 }
123
124 /*
125 * Put bootmem descriptor address in known location for host.
126 * Make sure it is not in kseg0, as we want physical address
127 */
128 writeq((u64)__cvmx_bootmem_internal_get_desc_ptr() & 0x7fffffffull,
129 (void *)CKSEG0ADDR(BOOTLOADER_BOOTMEM_DESC_ADDR));
130
131 debug("Reserving first 1MB of memory\n");
132 ret = cvmx_bootmem_reserve_memory(0, OCTEON_RESERVED_LOW_BOOT_MEM_SIZE,
133 "__low_reserved", 0);
134 if (!ret)
135 puts("Error reserving low 1MB of memory\n");
136
137#ifdef DEBUG
138 cvmx_bootmem_phy_list_print();
139#endif
140
141 return 0;
142}
143
144static int octeon_configure_load_memory(void)
145{
146 char *eptr;
147 u32 addr;
148 u32 size;
149 int ret;
150
151 eptr = env_get("octeon_reserved_mem_load_size");
152 if (!eptr || !strcmp("auto", eptr)) {
153 /*
154 * Pick a size that we think is appropriate.
155 * Please note that for small memory boards this guess
156 * will likely not be ideal.
157 * Please pick a specific size for boards/applications
158 * that require it.
159 */
160 if (gd->ram_size <= (256 << 20)) {
161 size = min_t(u64, (128 << 20),
162 ((gd->ram_size * 2) / 5) & ~0xFFFFF);
163 } else {
164 size = min_t(u64, (256 << 20),
165 ((gd->ram_size - (256 << 20)) / 3) & ~0xFFFFF);
166 }
167 } else {
168 size = simple_strtol(eptr, NULL, 16);
169 debug("octeon_reserved_mem_load_size=0x%08x\n", size);
170 }
171
172 if (size) {
173 debug("Linux reserved load size 0x%08x\n", size);
174 eptr = env_get("octeon_reserved_mem_load_base");
175 if (!eptr || !strcmp("auto", eptr)) {
176 u64 mem_top;
177 /*
178 * Leave some room for previous allocations that
179 * are made starting at the top of the low
180 * 256 Mbytes of DRAM
181 */
182 int adjust = (1 << 20);
183
184 if (gd->ram_size <= (512 << 20))
185 adjust = (17 << 20);
186
187 /* Put block at the top of DDR0, or bottom of DDR2 */
188 if ((gd->ram_size <= (256 << 20)) ||
189 (size > (gd->ram_size - (256 << 20)))) {
190 mem_top = min_t(u64, gd->ram_size - adjust,
191 (256 << 20) - adjust);
192 } else if ((gd->ram_size <= (512 << 20)) ||
193 (size > (gd->ram_size - (512 << 20)))) {
194 mem_top = min_t(u64, gd->ram_size - adjust,
195 (512 << 20) - adjust);
196 } else {
197 /*
198 * We have enough room, so set
199 * mem_top so that the block is
200 * at the base of the DDR2
201 * segment
202 */
203 mem_top = (512 << 20) + size;
204 }
205
206 /*
207 * Adjust for boot bus memory hole on OCTEON II
208 * and later.
209 */
210 if ((gd->ram_size > (256 << 20)))
211 mem_top += (256 << 20);
212
213 debug("Adjusted memory top is 0x%llx\n", mem_top);
214 addr = mem_top - size;
215 if (addr > (512 << 20))
216 addr = (512 << 20);
217 if ((addr >= (256 << 20)) && addr < (512 << 20)) {
218 /*
219 * The address landed in the boot-bus
220 * memory hole. Dig it out of the hole.
221 */
222 addr = (512 << 20);
223 }
224 } else {
225 addr = simple_strtol(eptr, NULL, 16);
226 }
227
228 ret = cvmx_bootmem_phy_named_block_alloc(size, addr,
229 addr + size, 0,
230 OCTEON_BOOTLOADER_LOAD_MEM_NAME,
231 0);
232 if (ret < 0) {
233 printf("ERROR: Unable to allocate bootloader reserved memory (addr: 0x%x, size: 0x%x).\n",
234 addr, size);
235 } else {
236 /*
237 * Set default load address to base of memory
238 * reserved for loading. The setting of the
239 * env. variable also sets the load_addr global
240 * variable.
241 * This environment variable is overridden each
242 * boot if a reserved block is created.
243 */
244 char str[20];
245
246 snprintf(str, sizeof(str), "0x%x", addr);
247 env_set("loadaddr", str);
248 debug("Setting load address to 0x%08x, size 0x%x\n",
249 addr, size);
250 }
251 return 0;
252 }
253
254 printf("WARNING: No reserved memory for image loading.\n");
255 return -1;
256}
257
258static int init_pcie_console(void)
259{
260 char *stdinname = env_get("stdin");
261 char *stdoutname = env_get("stdout");
262 char *stderrname = env_get("stderr");
263 struct udevice *pcie_console_dev = NULL;
264 bool stdin_set, stdout_set, stderr_set;
265 char iomux_name[128];
266 int ret = 0;
267
268 debug("%s: stdin: %s, stdout: %s, stderr: %s\n", __func__, stdinname,
269 stdoutname, stderrname);
270 if (!stdinname) {
271 env_set("stdin", "serial");
272 stdinname = env_get("stdin");
273 }
274 if (!stdoutname) {
275 env_set("stdout", "serial");
276 stdoutname = env_get("stdout");
277 }
278 if (!stderrname) {
279 env_set("stderr", "serial");
280 stderrname = env_get("stderr");
281 }
282
283 if (!stdinname || !stdoutname || !stderrname) {
284 printf("%s: Error setting environment variables for serial\n",
285 __func__);
286 return -1;
287 }
288
289 stdin_set = !!strstr(stdinname, CONSOLE_NAME);
290 stdout_set = !!strstr(stdoutname, CONSOLE_NAME);
291 stderr_set = !!strstr(stderrname, CONSOLE_NAME);
292
293 log_debug("stdin: %d, \"%s\", stdout: %d, \"%s\", stderr: %d, \"%s\"\n",
294 stdin_set, stdinname, stdout_set, stdoutname,
295 stderr_set, stderrname);
296 ret = uclass_get_device_by_name(UCLASS_SERIAL, CONSOLE_NAME,
297 &pcie_console_dev);
298 if (ret || !pcie_console_dev) {
299 debug("%s: No PCI console device %s found\n", __func__,
300 CONSOLE_NAME);
301 return 0;
302 }
303
304 if (stdin_set)
305 strncpy(iomux_name, stdinname, sizeof(iomux_name));
306 else
307 snprintf(iomux_name, sizeof(iomux_name), "%s,%s",
308 stdinname, pcie_console_dev->name);
309
310 ret = iomux_doenv(stdin, iomux_name);
311 if (ret) {
312 log_err("%s: Error setting I/O stdin MUX to %s\n",
313 __func__, iomux_name);
314 return ret;
315 }
316
317 if (!stdin_set)
318 env_set("stdin", iomux_name);
319
320 if (stdout_set)
321 strncpy(iomux_name, stdoutname, sizeof(iomux_name));
322 else
323 snprintf(iomux_name, sizeof(iomux_name), "%s,%s", stdoutname,
324 pcie_console_dev->name);
325
326 ret = iomux_doenv(stdout, iomux_name);
327 if (ret) {
328 log_err("%s: Error setting I/O stdout MUX to %s\n",
329 __func__, iomux_name);
330 return ret;
331 }
332 if (!stdout_set)
333 env_set("stdout", iomux_name);
334
335 if (stderr_set)
336 strncpy(iomux_name, stderrname, sizeof(iomux_name));
337 else
338 snprintf(iomux_name, sizeof(iomux_name), "%s,%s", stderrname,
339 pcie_console_dev->name);
340
341 ret = iomux_doenv(stderr, iomux_name);
342 if (ret) {
343 log_err("%s: Error setting I/O stderr MUX to %s\n",
344 __func__, iomux_name);
345 return ret;
346 }
347
348 if (!stderr_set)
349 env_set("stderr", iomux_name);
350
351 debug("%s: stdin: %s, stdout: %s, stderr: %s, ret: %d\n",
352 __func__, env_get("stdin"), env_get("stdout"),
353 env_get("stderr"), ret);
354
355 return ret;
356}
357
358static int init_bootcmd_console(void)
359{
360 char *stdinname = env_get("stdin");
361 struct udevice *bootcmd_dev = NULL;
362 bool stdin_set;
363 char iomux_name[128];
364 int ret = 0;
365
366 debug("%s: stdin before: %s\n", __func__,
367 stdinname ? stdinname : "NONE");
368 if (!stdinname) {
369 env_set("stdin", "serial");
370 stdinname = env_get("stdin");
371 }
372 stdin_set = !!strstr(stdinname, BOOTCMD_NAME);
373 ret = uclass_get_device_by_driver(UCLASS_SERIAL,
374 DM_DRIVER_GET(octeon_bootcmd),
375 &bootcmd_dev);
376 if (ret) {
377 log_err("%s: Error getting %s serial class\n", __func__,
378 BOOTCMD_NAME);
379 } else if (bootcmd_dev) {
380 if (stdin_set)
381 strncpy(iomux_name, stdinname, sizeof(iomux_name));
382 else
383 snprintf(iomux_name, sizeof(iomux_name), "%s,%s",
384 stdinname, bootcmd_dev->name);
385 ret = iomux_doenv(stdin, iomux_name);
386 if (ret)
387 log_err("%s: Error %d enabling the PCI bootcmd input console \"%s\"\n",
388 __func__, ret, iomux_name);
389 if (!stdin_set)
390 env_set("stdin", iomux_name);
391 }
392
393 debug("%s: Set iomux and stdin to %s (ret: %d)\n",
394 __func__, iomux_name, ret);
395 return ret;
396}
397
Stefan Roese957317e2022-04-07 09:11:47 +0200398static void configure_lmtdma_window(void)
399{
400 u64 tmp;
401 u64 addr;
402 u64 end_addr;
403
404 CVMX_MF_CVM_MEM_CTL(tmp);
405 tmp &= ~0x1ffull;
406 tmp |= 0x104ull;
407
408 /* enable LMTDMA */
409 tmp |= (1ull << 51);
410 /* configure scratch line 2 for LMT */
411 /* TODO: reserve this scratch line, so that others will not use it */
412 /* TODO: store LMTLINE in global var */
413 tmp |= (CVMX_PKO_LMTLINE << 45);
414 /* clear LMTLINE in scratch */
415 addr = CVMX_PKO_LMTLINE * CVMX_CACHE_LINE_SIZE;
416 end_addr = addr + CVMX_CACHE_LINE_SIZE;
417
418 while (addr < end_addr) {
419 *CASTPTR(volatile u64, addr + CVMX_SCRATCH_BASE) = (u64)0;
420 addr += 8;
421 }
422 CVMX_MT_CVM_MEM_CTL(tmp);
423}
424
Stefan Roese59735ef2022-04-07 09:11:46 +0200425int arch_early_init_r(void)
Stefan Roese469171b2021-04-07 09:12:32 +0200426{
427 int ret;
428
Stefan Roese59735ef2022-04-07 09:11:46 +0200429 /*
430 * Needs to be called pretty early, so that e.g. networking etc
431 * can access the bootmem infrastructure
432 */
Stefan Roese469171b2021-04-07 09:12:32 +0200433 ret = octeon_bootmem_init();
434 if (ret)
435 return ret;
436
Stefan Roese957317e2022-04-07 09:11:47 +0200437 if (octeon_has_feature(OCTEON_FEATURE_PKO3))
438 configure_lmtdma_window();
439
Stefan Roese59735ef2022-04-07 09:11:46 +0200440 return 0;
441}
442
443int arch_misc_init(void)
444{
445 int ret;
446
Stefan Roese469171b2021-04-07 09:12:32 +0200447 ret = octeon_configure_load_memory();
448 if (ret)
449 return ret;
450
Simon Glass2f8f8662023-02-05 15:40:23 -0700451 if (IS_ENABLED(CONFIG_OCTEON_SERIAL_PCIE_CONSOLE))
Stefan Roese469171b2021-04-07 09:12:32 +0200452 init_pcie_console();
453
Simon Glassbaf3bab2023-02-05 15:40:22 -0700454 if (IS_ENABLED(CONFIG_OCTEON_SERIAL_BOOTCMD))
Stefan Roese469171b2021-04-07 09:12:32 +0200455 init_bootcmd_console();
456
457 return 0;
458}
Stefan Roese9e9bcb02021-04-07 09:12:33 +0200459
460int board_ahci_enable(void)
461{
462 cvmx_sata_uctl_shim_cfg_t shim_cfg;
463
464 /*
465 * Configure proper endian swapping for the AHCI port so that the
466 * common AHCI code can be used
467 */
468 shim_cfg.u64 = csr_rd(CVMX_SATA_UCTL_SHIM_CFG);
469 shim_cfg.s.dma_endian_mode = 1;
470 /* Use 1 for LE mode when running BE, or 3 for BE mode running BE */
471 shim_cfg.s.csr_endian_mode = 3; /* Don't byte swap */
472 shim_cfg.s.dma_read_cmd = 1; /* No allocate L2C */
473 csr_wr(CVMX_SATA_UCTL_SHIM_CFG, shim_cfg.u64);
474
475 return 0;
476}