Merge tag 'u-boot-imx-20200825' of https://gitlab.denx.de/u-boot/custodians/u-boot-imx
[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 <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
29 DECLARE_GLOBAL_DATA_PTR;
30
31 void 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
42 void 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
60 void 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
88 int board_early_init_r(void)
89 {
90         pci_init();
91         return 0;
92 }
93
94 int board_init(void)
95 {
96         return 0;
97 }
98
99 int timer_init(void)
100 {
101         return 0;
102 }
103
104 int 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
114 void 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  */
135 int 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  */
189 int checkboard(void)
190 {
191         printf("Board: %s\n", fdt_get_board_model());
192
193         return 0;
194 }
195
196 void 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
215 int last_stage_init(void)
216 {
217         (void)smc_flsf_fw_booted();
218         return 0;
219 }
220
221 static 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
245 U_BOOT_CMD(go_uboot, 2, 0, do_go_uboot,
246            "Start U-Boot from RAM (pass FDT via x1 register)",
247            "");