blob: e8f97d963a03bb15def2883398e5089c65bb20ef [file] [log] [blame]
Yanhong Wang6a5a45d2023-03-29 11:42:17 +08001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2022 StarFive Technology Co., Ltd.
4 * Author: Yanhong Wang<yanhong.wang@starfivetech.com>
5 */
6
7#include <common.h>
Yanhong Wang4e321fa2023-06-15 17:36:52 +08008#include <asm/arch/eeprom.h>
Chanho Park9ca68c92023-10-31 17:56:00 +09009#include <asm/arch/gpio.h>
Yanhong Wang6a5a45d2023-03-29 11:42:17 +080010#include <asm/arch/regs.h>
11#include <asm/arch/spl.h>
12#include <asm/io.h>
Yanhong Wang4e321fa2023-06-15 17:36:52 +080013#include <dt-bindings/clock/starfive,jh7110-crg.h>
14#include <fdt_support.h>
15#include <linux/libfdt.h>
Yanhong Wang6a5a45d2023-03-29 11:42:17 +080016#include <log.h>
17#include <spl.h>
18
Yanhong Wang4e321fa2023-06-15 17:36:52 +080019DECLARE_GLOBAL_DATA_PTR;
Yanhong Wang6a5a45d2023-03-29 11:42:17 +080020#define JH7110_CLK_CPU_ROOT_OFFSET 0x0U
21#define JH7110_CLK_CPU_ROOT_SHIFT 24
22#define JH7110_CLK_CPU_ROOT_MASK GENMASK(29, 24)
23
Yanhong Wang4e321fa2023-06-15 17:36:52 +080024struct starfive_vf2_pro {
25 const char *path;
26 const char *name;
27 const char *value;
28};
29
Heinrich Schuchardtf8841732024-04-02 10:49:10 +020030static const struct starfive_vf2_pro milk_v_mars[] = {
31 {"/soc/ethernet@16030000", "starfive,tx-use-rgmii-clk", NULL},
32 {"/soc/ethernet@16040000", "starfive,tx-use-rgmii-clk", NULL},
33
34 {"/soc/ethernet@16030000/mdio/ethernet-phy@0",
35 "motorcomm,tx-clk-adj-enabled", NULL},
36 {"/soc/ethernet@16030000/mdio/ethernet-phy@0",
37 "motorcomm,tx-clk-100-inverted", NULL},
38 {"/soc/ethernet@16030000/mdio/ethernet-phy@0",
39 "motorcomm,tx-clk-1000-inverted", NULL},
40 {"/soc/ethernet@16030000/mdio/ethernet-phy@0",
41 "motorcomm,rx-clk-drv-microamp", "3970"},
42 {"/soc/ethernet@16030000/mdio/ethernet-phy@0",
43 "motorcomm,rx-data-drv-microamp", "2910"},
44 {"/soc/ethernet@16030000/mdio/ethernet-phy@0",
45 "rx-internal-delay-ps", "1900"},
46 {"/soc/ethernet@16030000/mdio/ethernet-phy@0",
47 "tx-internal-delay-ps", "1500"},
48};
49
Yanhong Wang4e321fa2023-06-15 17:36:52 +080050static const struct starfive_vf2_pro starfive_vera[] = {
51 {"/soc/ethernet@16030000/mdio/ethernet-phy@0", "rx-internal-delay-ps",
52 "1900"},
53 {"/soc/ethernet@16030000/mdio/ethernet-phy@0", "tx-internal-delay-ps",
54 "1350"}
55};
56
57static const struct starfive_vf2_pro starfive_verb[] = {
58 {"/soc/ethernet@16030000", "starfive,tx-use-rgmii-clk", NULL},
59 {"/soc/ethernet@16040000", "starfive,tx-use-rgmii-clk", NULL},
60
61 {"/soc/ethernet@16030000/mdio/ethernet-phy@0",
62 "motorcomm,tx-clk-adj-enabled", NULL},
63 {"/soc/ethernet@16030000/mdio/ethernet-phy@0",
64 "motorcomm,tx-clk-100-inverted", NULL},
65 {"/soc/ethernet@16030000/mdio/ethernet-phy@0",
66 "motorcomm,tx-clk-1000-inverted", NULL},
67 {"/soc/ethernet@16030000/mdio/ethernet-phy@0",
Lukasz Tekielia99605d2024-01-28 20:22:48 +010068 "motorcomm,rx-clk-drv-microamp", "3970"},
69 {"/soc/ethernet@16030000/mdio/ethernet-phy@0",
70 "motorcomm,rx-data-drv-microamp", "2910"},
71 {"/soc/ethernet@16030000/mdio/ethernet-phy@0",
Yanhong Wang4e321fa2023-06-15 17:36:52 +080072 "rx-internal-delay-ps", "1900"},
73 {"/soc/ethernet@16030000/mdio/ethernet-phy@0",
74 "tx-internal-delay-ps", "1500"},
75
76 {"/soc/ethernet@16040000/mdio/ethernet-phy@1",
77 "motorcomm,tx-clk-adj-enabled", NULL},
78 { "/soc/ethernet@16040000/mdio/ethernet-phy@1",
79 "motorcomm,tx-clk-100-inverted", NULL},
80 {"/soc/ethernet@16040000/mdio/ethernet-phy@1",
Lukasz Tekielia99605d2024-01-28 20:22:48 +010081 "motorcomm,rx-clk-drv-microamp", "3970"},
82 {"/soc/ethernet@16040000/mdio/ethernet-phy@1",
83 "motorcomm,rx-data-drv-microamp", "2910"},
84 {"/soc/ethernet@16040000/mdio/ethernet-phy@1",
Yanhong Wang4e321fa2023-06-15 17:36:52 +080085 "rx-internal-delay-ps", "0"},
86 {"/soc/ethernet@16040000/mdio/ethernet-phy@1",
87 "tx-internal-delay-ps", "0"},
88};
89
Heinrich Schuchardtf8841732024-04-02 10:49:10 +020090void spl_fdt_fixup_mars(void *fdt)
91{
92 static const char compat[] = "milkv,mars\0starfive,jh7110";
93 u32 phandle;
94 u8 i;
95 int offset;
96 int ret;
97
98 fdt_setprop(fdt, fdt_path_offset(fdt, "/"), "compatible", compat, sizeof(compat));
99 fdt_setprop_string(fdt, fdt_path_offset(fdt, "/"), "model",
100 "Milk-V Mars");
101
102 /* gmac0 */
103 offset = fdt_path_offset(fdt, "/soc/clock-controller@17000000");
104 phandle = fdt_get_phandle(fdt, offset);
105 offset = fdt_path_offset(fdt, "/soc/ethernet@16030000");
106
107 fdt_setprop_u32(fdt, offset, "assigned-clocks", phandle);
108 fdt_appendprop_u32(fdt, offset, "assigned-clocks", JH7110_AONCLK_GMAC0_TX);
109 fdt_setprop_u32(fdt, offset, "assigned-clock-parents", phandle);
110 fdt_appendprop_u32(fdt, offset, "assigned-clock-parents",
111 JH7110_AONCLK_GMAC0_RMII_RTX);
112
113 /* gmac1 */
114 fdt_setprop_string(fdt, fdt_path_offset(fdt, "/soc/ethernet@16040000"),
115 "status", "disabled");
116
117 for (i = 0; i < ARRAY_SIZE(milk_v_mars); i++) {
118 offset = fdt_path_offset(fdt, milk_v_mars[i].path);
119
120 if (milk_v_mars[i].value)
121 ret = fdt_setprop_u32(fdt, offset, milk_v_mars[i].name,
122 dectoul(milk_v_mars[i].value, NULL));
123 else
124 ret = fdt_setprop_empty(fdt, offset, milk_v_mars[i].name);
125
126 if (ret) {
127 pr_err("%s set prop %s fail.\n", __func__, milk_v_mars[i].name);
128 break;
129 }
130 }
131}
132
Yanhong Wang4e321fa2023-06-15 17:36:52 +0800133void spl_fdt_fixup_version_a(void *fdt)
134{
Aurelien Jarno5acb7c12024-01-10 21:17:44 +0100135 static const char compat[] = "starfive,visionfive-2-v1.2a\0starfive,jh7110";
Yanhong Wang4e321fa2023-06-15 17:36:52 +0800136 u32 phandle;
137 u8 i;
138 int offset;
139 int ret;
140
Aurelien Jarno5acb7c12024-01-10 21:17:44 +0100141 fdt_setprop(fdt, fdt_path_offset(fdt, "/"), "compatible", compat, sizeof(compat));
Yanhong Wang4e321fa2023-06-15 17:36:52 +0800142 fdt_setprop_string(fdt, fdt_path_offset(fdt, "/"), "model",
143 "StarFive VisionFive 2 v1.2A");
144
145 offset = fdt_path_offset(fdt, "/soc/clock-controller@13020000");
146 phandle = fdt_get_phandle(fdt, offset);
147 offset = fdt_path_offset(fdt, "/soc/ethernet@16040000");
148
149 fdt_setprop_u32(fdt, offset, "assigned-clocks", phandle);
150 fdt_appendprop_u32(fdt, offset, "assigned-clocks", JH7110_SYSCLK_GMAC1_TX);
151 fdt_appendprop_u32(fdt, offset, "assigned-clocks", phandle);
152 fdt_appendprop_u32(fdt, offset, "assigned-clocks", JH7110_SYSCLK_GMAC1_RX);
153
154 fdt_setprop_u32(fdt, offset, "assigned-clock-parents", phandle);
155 fdt_appendprop_u32(fdt, offset, "assigned-clock-parents",
156 JH7110_SYSCLK_GMAC1_RMII_RTX);
157 fdt_appendprop_u32(fdt, offset, "assigned-clock-parents", phandle);
158 fdt_appendprop_u32(fdt, offset, "assigned-clock-parents",
159 JH7110_SYSCLK_GMAC1_RMII_RTX);
160
161 fdt_setprop_string(fdt, fdt_path_offset(fdt, "/soc/ethernet@16040000"),
162 "phy-mode", "rmii");
163
164 for (i = 0; i < ARRAY_SIZE(starfive_vera); i++) {
165 offset = fdt_path_offset(fdt, starfive_vera[i].path);
166
167 if (starfive_vera[i].value)
168 ret = fdt_setprop_u32(fdt, offset, starfive_vera[i].name,
169 dectoul(starfive_vera[i].value, NULL));
170 else
171 ret = fdt_setprop_empty(fdt, offset, starfive_vera[i].name);
172
173 if (ret) {
174 pr_err("%s set prop %s fail.\n", __func__, starfive_vera[i].name);
175 break;
176 }
177 }
178}
179
180void spl_fdt_fixup_version_b(void *fdt)
181{
Aurelien Jarno5acb7c12024-01-10 21:17:44 +0100182 static const char compat[] = "starfive,visionfive-2-v1.3b\0starfive,jh7110";
Yanhong Wang4e321fa2023-06-15 17:36:52 +0800183 u32 phandle;
184 u8 i;
185 int offset;
186 int ret;
187
Aurelien Jarno5acb7c12024-01-10 21:17:44 +0100188 fdt_setprop(fdt, fdt_path_offset(fdt, "/"), "compatible", compat, sizeof(compat));
Yanhong Wang4e321fa2023-06-15 17:36:52 +0800189 fdt_setprop_string(fdt, fdt_path_offset(fdt, "/"), "model",
190 "StarFive VisionFive 2 v1.3B");
191
192 /* gmac0 */
193 offset = fdt_path_offset(fdt, "/soc/clock-controller@17000000");
194 phandle = fdt_get_phandle(fdt, offset);
195 offset = fdt_path_offset(fdt, "/soc/ethernet@16030000");
196
197 fdt_setprop_u32(fdt, offset, "assigned-clocks", phandle);
198 fdt_appendprop_u32(fdt, offset, "assigned-clocks", JH7110_AONCLK_GMAC0_TX);
199 fdt_setprop_u32(fdt, offset, "assigned-clock-parents", phandle);
200 fdt_appendprop_u32(fdt, offset, "assigned-clock-parents",
201 JH7110_AONCLK_GMAC0_RMII_RTX);
202
203 /* gmac1 */
204 offset = fdt_path_offset(fdt, "/soc/clock-controller@13020000");
205 phandle = fdt_get_phandle(fdt, offset);
206 offset = fdt_path_offset(fdt, "/soc/ethernet@16040000");
207
208 fdt_setprop_u32(fdt, offset, "assigned-clocks", phandle);
209 fdt_appendprop_u32(fdt, offset, "assigned-clocks", JH7110_SYSCLK_GMAC1_TX);
210 fdt_setprop_u32(fdt, offset, "assigned-clock-parents", phandle);
211 fdt_appendprop_u32(fdt, offset, "assigned-clock-parents",
212 JH7110_SYSCLK_GMAC1_RMII_RTX);
213
214 for (i = 0; i < ARRAY_SIZE(starfive_verb); i++) {
215 offset = fdt_path_offset(fdt, starfive_verb[i].path);
216
217 if (starfive_verb[i].value)
218 ret = fdt_setprop_u32(fdt, offset, starfive_verb[i].name,
219 dectoul(starfive_verb[i].value, NULL));
220 else
221 ret = fdt_setprop_empty(fdt, offset, starfive_verb[i].name);
222
223 if (ret) {
224 pr_err("%s set prop %s fail.\n", __func__, starfive_verb[i].name);
225 break;
226 }
227 }
228}
229
230void spl_perform_fixups(struct spl_image_info *spl_image)
231{
232 u8 version;
Heinrich Schuchardtf8841732024-04-02 10:49:10 +0200233 const char *product_id;
Yanhong Wang4e321fa2023-06-15 17:36:52 +0800234
Heinrich Schuchardtf8841732024-04-02 10:49:10 +0200235 product_id = get_product_id_from_eeprom();
236 if (!product_id) {
237 pr_err("Can't read EEPROM\n");
238 return;
239 }
240 if (!strncmp(product_id, "MARS", 4)) {
241 spl_fdt_fixup_mars(spl_image->fdt_addr);
242 } else if (!strncmp(product_id, "VF7110", 6)) {
243 version = get_pcb_revision_from_eeprom();
244 switch (version) {
245 case 'a':
246 case 'A':
247 spl_fdt_fixup_version_a(spl_image->fdt_addr);
248 break;
Yanhong Wang4e321fa2023-06-15 17:36:52 +0800249
Heinrich Schuchardtf8841732024-04-02 10:49:10 +0200250 case 'b':
251 case 'B':
252 default:
253 spl_fdt_fixup_version_b(spl_image->fdt_addr);
Yanhong Wang4e321fa2023-06-15 17:36:52 +0800254 break;
Heinrich Schuchardtf8841732024-04-02 10:49:10 +0200255 };
256 } else {
257 pr_err("Unknown product %s\n", product_id);
Yanhong Wang4e321fa2023-06-15 17:36:52 +0800258 };
259
Heinrich Schuchardtf8841732024-04-02 10:49:10 +0200260 /* Update the memory size which read from eeprom or DT */
Yanhong Wang4e321fa2023-06-15 17:36:52 +0800261 fdt_fixup_memory(spl_image->fdt_addr, 0x40000000, gd->ram_size);
262}
Chanho Park9ca68c92023-10-31 17:56:00 +0900263
264static void jh7110_jtag_init(void)
265{
266 /* nTRST: GPIO36 */
267 SYS_IOMUX_DOEN(36, HIGH);
268 SYS_IOMUX_DIN(36, 4);
269 /* TDI: GPIO61 */
270 SYS_IOMUX_DOEN(61, HIGH);
271 SYS_IOMUX_DIN(61, 19);
272 /* TMS: GPIO63 */
273 SYS_IOMUX_DOEN(63, HIGH);
274 SYS_IOMUX_DIN(63, 20);
275 /* TCK: GPIO60 */
276 SYS_IOMUX_DOEN(60, HIGH);
277 SYS_IOMUX_DIN(60, 29);
278 /* TDO: GPIO44 */
279 SYS_IOMUX_DOEN(44, 8);
280 SYS_IOMUX_DOUT(44, 22);
281}
282
Yanhong Wang6a5a45d2023-03-29 11:42:17 +0800283int spl_board_init_f(void)
284{
285 int ret;
286
Chanho Park9ca68c92023-10-31 17:56:00 +0900287 jh7110_jtag_init();
288
Yanhong Wang6a5a45d2023-03-29 11:42:17 +0800289 ret = spl_soc_init();
290 if (ret) {
291 debug("JH7110 SPL init failed: %d\n", ret);
292 return ret;
293 }
294
295 return 0;
296}
297
298u32 spl_boot_device(void)
299{
300 u32 mode;
301
302 mode = in_le32(JH7110_BOOT_MODE_SELECT_REG)
303 & JH7110_BOOT_MODE_SELECT_MASK;
304 switch (mode) {
305 case 0:
306 return BOOT_DEVICE_SPI;
307
308 case 1:
309 return BOOT_DEVICE_MMC2;
310
311 case 2:
312 return BOOT_DEVICE_MMC1;
313
314 case 3:
315 return BOOT_DEVICE_UART;
316
317 default:
318 debug("Unsupported boot device 0x%x.\n", mode);
319 return BOOT_DEVICE_NONE;
320 }
321}
322
323void board_init_f(ulong dummy)
324{
325 int ret;
326
327 ret = spl_early_init();
328 if (ret)
329 panic("spl_early_init() failed: %d\n", ret);
330
Simon Glassb8357c12023-08-21 21:16:56 -0600331 riscv_cpu_setup();
Yanhong Wang6a5a45d2023-03-29 11:42:17 +0800332 preloader_console_init();
333
334 /* Set the parent clock of cpu_root clock to pll0,
335 * it must be initialized here
336 */
337 clrsetbits_le32(JH7110_SYS_CRG + JH7110_CLK_CPU_ROOT_OFFSET,
338 JH7110_CLK_CPU_ROOT_MASK,
339 BIT(JH7110_CLK_CPU_ROOT_SHIFT));
340
341 ret = spl_board_init_f();
342 if (ret) {
343 debug("spl_board_init_f init failed: %d\n", ret);
344 return;
345 }
346}
347
348#if CONFIG_IS_ENABLED(SPL_LOAD_FIT)
349int board_fit_config_name_match(const char *name)
350{
351 /* boot using first FIT config */
352 return 0;
353}
354#endif