blob: 974e9eb82001c24eb1d1ba70c4ac16e3224f8f39 [file] [log] [blame]
Suneel Garapati0a668f62019-10-19 18:47:37 -07001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2018 Marvell International Ltd.
4 *
5 * https://spdx.org/licenses
6 */
7
8#include <command.h>
9#include <console.h>
10#include <cpu_func.h>
11#include <dm.h>
Simon Glass401d1c42020-10-30 21:38:53 -060012#include <asm/global_data.h>
Suneel Garapati0a668f62019-10-19 18:47:37 -070013#include <dm/uclass-internal.h>
14#include <env.h>
Simon Glass91caa3b2023-08-21 21:17:01 -060015#include <event.h>
Suneel Garapati0a668f62019-10-19 18:47:37 -070016#include <init.h>
17#include <malloc.h>
18#include <net.h>
19#include <pci_ids.h>
20#include <errno.h>
21#include <asm/io.h>
22#include <linux/compiler.h>
23#include <linux/delay.h>
24#include <linux/libfdt.h>
25#include <fdt_support.h>
26#include <asm/arch/smc.h>
27#include <asm/arch/soc.h>
28#include <asm/arch/board.h>
29#include <dm/util.h>
30
31DECLARE_GLOBAL_DATA_PTR;
32
33void cleanup_env_ethaddr(void)
34{
35 char ename[32];
36
37 for (int i = 0; i < 20; i++) {
38 sprintf(ename, i ? "eth%daddr" : "ethaddr", i);
39 if (env_get(ename))
40 env_set(ename, NULL);
41 }
42}
43
44void octeontx2_board_get_mac_addr(u8 index, u8 *mac_addr)
45{
46 u64 tmp_mac, board_mac_addr = fdt_get_board_mac_addr();
47 static int board_mac_num;
48
49 board_mac_num = fdt_get_board_mac_cnt();
50 if ((!is_zero_ethaddr((u8 *)&board_mac_addr)) && board_mac_num) {
51 tmp_mac = board_mac_addr;
52 tmp_mac += index;
53 tmp_mac = swab64(tmp_mac) >> 16;
54 memcpy(mac_addr, (u8 *)&tmp_mac, ARP_HLEN);
55 board_mac_num--;
56 } else {
57 memset(mac_addr, 0, ARP_HLEN);
58 }
59 debug("%s mac %pM\n", __func__, mac_addr);
60}
61
62void board_quiesce_devices(void)
63{
64 struct uclass *uc_dev;
65 int ret;
66
67 /* Removes all RVU PF devices */
68 ret = uclass_get(UCLASS_ETH, &uc_dev);
69 if (uc_dev)
70 ret = uclass_destroy(uc_dev);
71 if (ret)
72 printf("couldn't remove rvu pf devices\n");
73
74 if (IS_ENABLED(CONFIG_OCTEONTX2_CGX_INTF)) {
75 /* Bring down all cgx lmac links */
76 cgx_intf_shutdown();
77 }
78
79 /* Removes all CGX and RVU AF devices */
80 ret = uclass_get(UCLASS_MISC, &uc_dev);
81 if (uc_dev)
82 ret = uclass_destroy(uc_dev);
83 if (ret)
84 printf("couldn't remove misc (cgx/rvu_af) devices\n");
85
86 /* SMC call - removes all LF<->PF mappings */
87 smc_disable_rvu_lfs(0);
88}
89
90int board_early_init_r(void)
91{
92 pci_init();
93 return 0;
94}
95
96int board_init(void)
97{
98 return 0;
99}
100
101int timer_init(void)
102{
103 return 0;
104}
105
106int dram_init(void)
107{
108 gd->ram_size = smc_dram_size(0);
Tom Riniaa6e94d2022-11-16 13:10:37 -0500109 gd->ram_size -= CFG_SYS_SDRAM_BASE;
Suneel Garapati0a668f62019-10-19 18:47:37 -0700110
111 mem_map_fill();
112
113 return 0;
114}
115
116void board_late_probe_devices(void)
117{
118 struct udevice *dev;
119 int err, cgx_cnt = 3, i;
120
121 /* Probe MAC(CGX) and NIC AF devices before Network stack init */
122 for (i = 0; i < cgx_cnt; i++) {
123 err = dm_pci_find_device(PCI_VENDOR_ID_CAVIUM,
124 PCI_DEVICE_ID_CAVIUM_CGX, i, &dev);
125 if (err)
126 debug("%s CGX%d device not found\n", __func__, i);
127 }
128 err = dm_pci_find_device(PCI_VENDOR_ID_CAVIUM,
129 PCI_DEVICE_ID_CAVIUM_RVU_AF, 0, &dev);
130 if (err)
131 debug("NIC AF device not found\n");
132}
133
134/**
135 * Board late initialization routine.
136 */
137int board_late_init(void)
138{
139 char boardname[32];
140 char boardserial[150], boardrev[150];
141 long val;
142 bool save_env = false;
143 const char *str;
144
145 debug("%s()\n", __func__);
146
147 /*
148 * Now that pci_init initializes env device.
149 * Try to cleanup ethaddr env variables, this is needed
150 * as with each boot, configuration of QLM can change.
151 */
152 cleanup_env_ethaddr();
153
154 snprintf(boardname, sizeof(boardname), "%s> ", fdt_get_board_model());
155 env_set("prompt", boardname);
156 set_working_fdt_addr(env_get_hex("fdtcontroladdr", fdt_base_addr));
157
158 str = fdt_get_board_revision();
159 if (str) {
160 snprintf(boardrev, sizeof(boardrev), "%s", str);
161 if (env_get("boardrev") &&
162 strcmp(boardrev, env_get("boardrev")))
163 save_env = true;
164 env_set("boardrev", boardrev);
165 }
166
167 str = fdt_get_board_serial();
168 if (str) {
169 snprintf(boardserial, sizeof(boardserial), "%s", str);
170 if (env_get("serial#") &&
171 strcmp(boardserial, env_get("serial#")))
172 save_env = true;
173 env_set("serial#", boardserial);
174 }
175
176 val = env_get_hex("disable_ooo", 0);
177 smc_configure_ooo(val);
178
179 if (IS_ENABLED(CONFIG_NET_OCTEONTX2))
180 board_late_probe_devices();
181
182 if (save_env)
183 env_save();
184
185 return 0;
186}
187
188/*
189 * Invoked before relocation, so limit to stack variables.
190 */
191int checkboard(void)
192{
193 printf("Board: %s\n", fdt_get_board_model());
194
195 return 0;
196}
197
198void board_acquire_flash_arb(bool acquire)
199{
200 union cpc_boot_ownerx ownerx;
201
202 if (!acquire) {
203 ownerx.u = readl(CPC_BOOT_OWNERX(3));
204 ownerx.s.boot_req = 0;
205 writel(ownerx.u, CPC_BOOT_OWNERX(3));
206 } else {
207 ownerx.u = 0;
208 ownerx.s.boot_req = 1;
209 writel(ownerx.u, CPC_BOOT_OWNERX(3));
210 udelay(1);
211 do {
212 ownerx.u = readl(CPC_BOOT_OWNERX(3));
213 } while (ownerx.s.boot_wait);
214 }
215}
216
Simon Glass91caa3b2023-08-21 21:17:01 -0600217static int last_stage_init(void)
Suneel Garapati0a668f62019-10-19 18:47:37 -0700218{
219 (void)smc_flsf_fw_booted();
220 return 0;
221}
Simon Glass91caa3b2023-08-21 21:17:01 -0600222EVENT_SPY_SIMPLE(EVT_LAST_STAGE_INIT, last_stage_init);
Suneel Garapati0a668f62019-10-19 18:47:37 -0700223
224static int do_go_uboot(struct cmd_tbl *cmdtp, int flag, int argc,
225 char *const argv[])
226{
227 typedef void __noreturn (*uboot_entry_t)(ulong, void *);
228 uboot_entry_t entry;
229 ulong addr;
230 void *fdt;
Ilias Apalodimase7fb7892021-10-26 09:12:33 +0300231 int err;
Suneel Garapati0a668f62019-10-19 18:47:37 -0700232
233 if (argc < 2)
234 return CMD_RET_USAGE;
235
Simon Glass7e5f4602021-07-24 09:03:29 -0600236 addr = hextoul(argv[1], NULL);
Ilias Apalodimase7fb7892021-10-26 09:12:33 +0300237 fdt = board_fdt_blob_setup(&err);
Suneel Garapati0a668f62019-10-19 18:47:37 -0700238 entry = (uboot_entry_t)addr;
239 flush_cache((ulong)addr, 1 << 20); /* 1MiB should be enough */
240 dcache_disable();
241
242 printf("## Starting U-Boot at %p (FDT at %p)...\n", entry, fdt);
243
244 entry(0, fdt);
245
246 return 0;
247}
248
249U_BOOT_CMD(go_uboot, 2, 0, do_go_uboot,
250 "Start U-Boot from RAM (pass FDT via x1 register)",
251 "");