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