Merge tag 'xilinx-for-v2021.04-rc3' of https://gitlab.denx.de/u-boot/custodians/u...
[platform/kernel/u-boot.git] / board / Marvell / octeontx2 / board.c
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
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
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
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
89 int board_early_init_r(void)
90 {
91         pci_init();
92         return 0;
93 }
94
95 int board_init(void)
96 {
97         return 0;
98 }
99
100 int timer_init(void)
101 {
102         return 0;
103 }
104
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
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  */
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  */
190 int checkboard(void)
191 {
192         printf("Board: %s\n", fdt_get_board_model());
193
194         return 0;
195 }
196
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
216 int last_stage_init(void)
217 {
218         (void)smc_flsf_fw_booted();
219         return 0;
220 }
221
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            "");