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