]>
Commit | Line | Data |
---|---|---|
5ecf9b0b YW |
1 | // 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 | ||
c9745365 | 7 | #include <asm/arch/eeprom.h> |
b8a902b8 | 8 | #include <asm/arch/gpio.h> |
5ecf9b0b YW |
9 | #include <asm/arch/regs.h> |
10 | #include <asm/arch/spl.h> | |
11 | #include <asm/io.h> | |
c9745365 YW |
12 | #include <dt-bindings/clock/starfive,jh7110-crg.h> |
13 | #include <fdt_support.h> | |
14 | #include <linux/libfdt.h> | |
5ecf9b0b YW |
15 | #include <log.h> |
16 | #include <spl.h> | |
17 | ||
c9745365 | 18 | DECLARE_GLOBAL_DATA_PTR; |
5ecf9b0b YW |
19 | #define JH7110_CLK_CPU_ROOT_OFFSET 0x0U |
20 | #define JH7110_CLK_CPU_ROOT_SHIFT 24 | |
21 | #define JH7110_CLK_CPU_ROOT_MASK GENMASK(29, 24) | |
22 | ||
c9745365 YW |
23 | struct starfive_vf2_pro { |
24 | const char *path; | |
25 | const char *name; | |
26 | const char *value; | |
27 | }; | |
28 | ||
92db23f7 HS |
29 | static const struct starfive_vf2_pro milk_v_mars[] = { |
30 | {"/soc/ethernet@16030000", "starfive,tx-use-rgmii-clk", NULL}, | |
31 | {"/soc/ethernet@16040000", "starfive,tx-use-rgmii-clk", NULL}, | |
32 | ||
33 | {"/soc/ethernet@16030000/mdio/ethernet-phy@0", | |
34 | "motorcomm,tx-clk-adj-enabled", NULL}, | |
35 | {"/soc/ethernet@16030000/mdio/ethernet-phy@0", | |
36 | "motorcomm,tx-clk-100-inverted", NULL}, | |
37 | {"/soc/ethernet@16030000/mdio/ethernet-phy@0", | |
38 | "motorcomm,tx-clk-1000-inverted", NULL}, | |
39 | {"/soc/ethernet@16030000/mdio/ethernet-phy@0", | |
40 | "motorcomm,rx-clk-drv-microamp", "3970"}, | |
41 | {"/soc/ethernet@16030000/mdio/ethernet-phy@0", | |
42 | "motorcomm,rx-data-drv-microamp", "2910"}, | |
43 | {"/soc/ethernet@16030000/mdio/ethernet-phy@0", | |
44 | "rx-internal-delay-ps", "1900"}, | |
45 | {"/soc/ethernet@16030000/mdio/ethernet-phy@0", | |
46 | "tx-internal-delay-ps", "1500"}, | |
47 | }; | |
48 | ||
c9745365 YW |
49 | static const struct starfive_vf2_pro starfive_vera[] = { |
50 | {"/soc/ethernet@16030000/mdio/ethernet-phy@0", "rx-internal-delay-ps", | |
51 | "1900"}, | |
52 | {"/soc/ethernet@16030000/mdio/ethernet-phy@0", "tx-internal-delay-ps", | |
53 | "1350"} | |
54 | }; | |
55 | ||
56 | static const struct starfive_vf2_pro starfive_verb[] = { | |
57 | {"/soc/ethernet@16030000", "starfive,tx-use-rgmii-clk", NULL}, | |
58 | {"/soc/ethernet@16040000", "starfive,tx-use-rgmii-clk", NULL}, | |
59 | ||
60 | {"/soc/ethernet@16030000/mdio/ethernet-phy@0", | |
61 | "motorcomm,tx-clk-adj-enabled", NULL}, | |
62 | {"/soc/ethernet@16030000/mdio/ethernet-phy@0", | |
63 | "motorcomm,tx-clk-100-inverted", NULL}, | |
64 | {"/soc/ethernet@16030000/mdio/ethernet-phy@0", | |
65 | "motorcomm,tx-clk-1000-inverted", NULL}, | |
70f15075 LT |
66 | {"/soc/ethernet@16030000/mdio/ethernet-phy@0", |
67 | "motorcomm,rx-clk-drv-microamp", "3970"}, | |
68 | {"/soc/ethernet@16030000/mdio/ethernet-phy@0", | |
69 | "motorcomm,rx-data-drv-microamp", "2910"}, | |
c9745365 YW |
70 | {"/soc/ethernet@16030000/mdio/ethernet-phy@0", |
71 | "rx-internal-delay-ps", "1900"}, | |
72 | {"/soc/ethernet@16030000/mdio/ethernet-phy@0", | |
73 | "tx-internal-delay-ps", "1500"}, | |
74 | ||
75 | {"/soc/ethernet@16040000/mdio/ethernet-phy@1", | |
76 | "motorcomm,tx-clk-adj-enabled", NULL}, | |
77 | { "/soc/ethernet@16040000/mdio/ethernet-phy@1", | |
78 | "motorcomm,tx-clk-100-inverted", NULL}, | |
70f15075 LT |
79 | {"/soc/ethernet@16040000/mdio/ethernet-phy@1", |
80 | "motorcomm,rx-clk-drv-microamp", "3970"}, | |
81 | {"/soc/ethernet@16040000/mdio/ethernet-phy@1", | |
82 | "motorcomm,rx-data-drv-microamp", "2910"}, | |
c9745365 YW |
83 | {"/soc/ethernet@16040000/mdio/ethernet-phy@1", |
84 | "rx-internal-delay-ps", "0"}, | |
85 | {"/soc/ethernet@16040000/mdio/ethernet-phy@1", | |
86 | "tx-internal-delay-ps", "0"}, | |
87 | }; | |
88 | ||
92db23f7 HS |
89 | void spl_fdt_fixup_mars(void *fdt) |
90 | { | |
91 | static const char compat[] = "milkv,mars\0starfive,jh7110"; | |
92 | u32 phandle; | |
93 | u8 i; | |
94 | int offset; | |
95 | int ret; | |
96 | ||
97 | fdt_setprop(fdt, fdt_path_offset(fdt, "/"), "compatible", compat, sizeof(compat)); | |
98 | fdt_setprop_string(fdt, fdt_path_offset(fdt, "/"), "model", | |
99 | "Milk-V Mars"); | |
100 | ||
101 | /* gmac0 */ | |
102 | offset = fdt_path_offset(fdt, "/soc/clock-controller@17000000"); | |
103 | phandle = fdt_get_phandle(fdt, offset); | |
104 | offset = fdt_path_offset(fdt, "/soc/ethernet@16030000"); | |
105 | ||
106 | fdt_setprop_u32(fdt, offset, "assigned-clocks", phandle); | |
107 | fdt_appendprop_u32(fdt, offset, "assigned-clocks", JH7110_AONCLK_GMAC0_TX); | |
108 | fdt_setprop_u32(fdt, offset, "assigned-clock-parents", phandle); | |
109 | fdt_appendprop_u32(fdt, offset, "assigned-clock-parents", | |
110 | JH7110_AONCLK_GMAC0_RMII_RTX); | |
111 | ||
112 | /* gmac1 */ | |
113 | fdt_setprop_string(fdt, fdt_path_offset(fdt, "/soc/ethernet@16040000"), | |
114 | "status", "disabled"); | |
115 | ||
116 | for (i = 0; i < ARRAY_SIZE(milk_v_mars); i++) { | |
117 | offset = fdt_path_offset(fdt, milk_v_mars[i].path); | |
118 | ||
119 | if (milk_v_mars[i].value) | |
120 | ret = fdt_setprop_u32(fdt, offset, milk_v_mars[i].name, | |
121 | dectoul(milk_v_mars[i].value, NULL)); | |
122 | else | |
123 | ret = fdt_setprop_empty(fdt, offset, milk_v_mars[i].name); | |
124 | ||
125 | if (ret) { | |
126 | pr_err("%s set prop %s fail.\n", __func__, milk_v_mars[i].name); | |
127 | break; | |
128 | } | |
129 | } | |
130 | } | |
131 | ||
de322959 HS |
132 | void spl_fdt_fixup_mars_cm(void *fdt) |
133 | { | |
134 | const char *compat; | |
135 | const char *model; | |
136 | ||
137 | spl_fdt_fixup_mars(fdt); | |
138 | ||
139 | if (!get_mmc_size_from_eeprom()) { | |
140 | int offset; | |
141 | ||
142 | model = "Milk-V Mars CM Lite"; | |
143 | compat = "milkv,mars-cm-lite\0starfive,jh7110"; | |
144 | ||
145 | offset = fdt_path_offset(fdt, "/soc/pinctrl/mmc0-pins/mmc0-pins-rest"); | |
146 | /* GPIOMUX(22, GPOUT_SYS_SDIO0_RST, GPOEN_ENABLE, GPI_NONE) */ | |
147 | fdt_setprop_u32(fdt, offset, "pinmux", 0xff130016); | |
148 | } else { | |
149 | model = "Milk-V Mars CM"; | |
150 | compat = "milkv,mars-cm\0starfive,jh7110"; | |
151 | } | |
152 | fdt_setprop(fdt, fdt_path_offset(fdt, "/"), "compatible", compat, sizeof(compat)); | |
153 | fdt_setprop_string(fdt, fdt_path_offset(fdt, "/"), "model", model); | |
154 | } | |
155 | ||
c9745365 YW |
156 | void spl_fdt_fixup_version_a(void *fdt) |
157 | { | |
465e7e6d | 158 | static const char compat[] = "starfive,visionfive-2-v1.2a\0starfive,jh7110"; |
c9745365 YW |
159 | u32 phandle; |
160 | u8 i; | |
161 | int offset; | |
162 | int ret; | |
163 | ||
465e7e6d | 164 | fdt_setprop(fdt, fdt_path_offset(fdt, "/"), "compatible", compat, sizeof(compat)); |
c9745365 YW |
165 | fdt_setprop_string(fdt, fdt_path_offset(fdt, "/"), "model", |
166 | "StarFive VisionFive 2 v1.2A"); | |
167 | ||
168 | offset = fdt_path_offset(fdt, "/soc/clock-controller@13020000"); | |
169 | phandle = fdt_get_phandle(fdt, offset); | |
170 | offset = fdt_path_offset(fdt, "/soc/ethernet@16040000"); | |
171 | ||
172 | fdt_setprop_u32(fdt, offset, "assigned-clocks", phandle); | |
173 | fdt_appendprop_u32(fdt, offset, "assigned-clocks", JH7110_SYSCLK_GMAC1_TX); | |
174 | fdt_appendprop_u32(fdt, offset, "assigned-clocks", phandle); | |
175 | fdt_appendprop_u32(fdt, offset, "assigned-clocks", JH7110_SYSCLK_GMAC1_RX); | |
176 | ||
177 | fdt_setprop_u32(fdt, offset, "assigned-clock-parents", phandle); | |
178 | fdt_appendprop_u32(fdt, offset, "assigned-clock-parents", | |
179 | JH7110_SYSCLK_GMAC1_RMII_RTX); | |
180 | fdt_appendprop_u32(fdt, offset, "assigned-clock-parents", phandle); | |
181 | fdt_appendprop_u32(fdt, offset, "assigned-clock-parents", | |
182 | JH7110_SYSCLK_GMAC1_RMII_RTX); | |
183 | ||
184 | fdt_setprop_string(fdt, fdt_path_offset(fdt, "/soc/ethernet@16040000"), | |
185 | "phy-mode", "rmii"); | |
186 | ||
187 | for (i = 0; i < ARRAY_SIZE(starfive_vera); i++) { | |
188 | offset = fdt_path_offset(fdt, starfive_vera[i].path); | |
189 | ||
190 | if (starfive_vera[i].value) | |
191 | ret = fdt_setprop_u32(fdt, offset, starfive_vera[i].name, | |
192 | dectoul(starfive_vera[i].value, NULL)); | |
193 | else | |
194 | ret = fdt_setprop_empty(fdt, offset, starfive_vera[i].name); | |
195 | ||
196 | if (ret) { | |
197 | pr_err("%s set prop %s fail.\n", __func__, starfive_vera[i].name); | |
198 | break; | |
199 | } | |
200 | } | |
201 | } | |
202 | ||
203 | void spl_fdt_fixup_version_b(void *fdt) | |
204 | { | |
465e7e6d | 205 | static const char compat[] = "starfive,visionfive-2-v1.3b\0starfive,jh7110"; |
c9745365 YW |
206 | u32 phandle; |
207 | u8 i; | |
208 | int offset; | |
209 | int ret; | |
210 | ||
465e7e6d | 211 | fdt_setprop(fdt, fdt_path_offset(fdt, "/"), "compatible", compat, sizeof(compat)); |
c9745365 YW |
212 | fdt_setprop_string(fdt, fdt_path_offset(fdt, "/"), "model", |
213 | "StarFive VisionFive 2 v1.3B"); | |
214 | ||
215 | /* gmac0 */ | |
216 | offset = fdt_path_offset(fdt, "/soc/clock-controller@17000000"); | |
217 | phandle = fdt_get_phandle(fdt, offset); | |
218 | offset = fdt_path_offset(fdt, "/soc/ethernet@16030000"); | |
219 | ||
220 | fdt_setprop_u32(fdt, offset, "assigned-clocks", phandle); | |
221 | fdt_appendprop_u32(fdt, offset, "assigned-clocks", JH7110_AONCLK_GMAC0_TX); | |
222 | fdt_setprop_u32(fdt, offset, "assigned-clock-parents", phandle); | |
223 | fdt_appendprop_u32(fdt, offset, "assigned-clock-parents", | |
224 | JH7110_AONCLK_GMAC0_RMII_RTX); | |
225 | ||
226 | /* gmac1 */ | |
227 | offset = fdt_path_offset(fdt, "/soc/clock-controller@13020000"); | |
228 | phandle = fdt_get_phandle(fdt, offset); | |
229 | offset = fdt_path_offset(fdt, "/soc/ethernet@16040000"); | |
230 | ||
231 | fdt_setprop_u32(fdt, offset, "assigned-clocks", phandle); | |
232 | fdt_appendprop_u32(fdt, offset, "assigned-clocks", JH7110_SYSCLK_GMAC1_TX); | |
233 | fdt_setprop_u32(fdt, offset, "assigned-clock-parents", phandle); | |
234 | fdt_appendprop_u32(fdt, offset, "assigned-clock-parents", | |
235 | JH7110_SYSCLK_GMAC1_RMII_RTX); | |
236 | ||
237 | for (i = 0; i < ARRAY_SIZE(starfive_verb); i++) { | |
238 | offset = fdt_path_offset(fdt, starfive_verb[i].path); | |
239 | ||
240 | if (starfive_verb[i].value) | |
241 | ret = fdt_setprop_u32(fdt, offset, starfive_verb[i].name, | |
242 | dectoul(starfive_verb[i].value, NULL)); | |
243 | else | |
244 | ret = fdt_setprop_empty(fdt, offset, starfive_verb[i].name); | |
245 | ||
246 | if (ret) { | |
247 | pr_err("%s set prop %s fail.\n", __func__, starfive_verb[i].name); | |
248 | break; | |
249 | } | |
250 | } | |
251 | } | |
252 | ||
253 | void spl_perform_fixups(struct spl_image_info *spl_image) | |
254 | { | |
255 | u8 version; | |
92db23f7 | 256 | const char *product_id; |
c9745365 | 257 | |
92db23f7 HS |
258 | product_id = get_product_id_from_eeprom(); |
259 | if (!product_id) { | |
260 | pr_err("Can't read EEPROM\n"); | |
261 | return; | |
262 | } | |
de322959 HS |
263 | if (!strncmp(product_id, "MARC", 4)) { |
264 | spl_fdt_fixup_mars_cm(spl_image->fdt_addr); | |
265 | } else if (!strncmp(product_id, "MARS", 4)) { | |
92db23f7 HS |
266 | spl_fdt_fixup_mars(spl_image->fdt_addr); |
267 | } else if (!strncmp(product_id, "VF7110", 6)) { | |
268 | version = get_pcb_revision_from_eeprom(); | |
269 | switch (version) { | |
270 | case 'a': | |
271 | case 'A': | |
272 | spl_fdt_fixup_version_a(spl_image->fdt_addr); | |
273 | break; | |
274 | ||
275 | case 'b': | |
276 | case 'B': | |
277 | default: | |
278 | spl_fdt_fixup_version_b(spl_image->fdt_addr); | |
c9745365 | 279 | break; |
92db23f7 HS |
280 | }; |
281 | } else { | |
282 | pr_err("Unknown product %s\n", product_id); | |
c9745365 YW |
283 | }; |
284 | ||
92db23f7 | 285 | /* Update the memory size which read from eeprom or DT */ |
c9745365 YW |
286 | fdt_fixup_memory(spl_image->fdt_addr, 0x40000000, gd->ram_size); |
287 | } | |
b8a902b8 CP |
288 | |
289 | static void jh7110_jtag_init(void) | |
290 | { | |
291 | /* nTRST: GPIO36 */ | |
292 | SYS_IOMUX_DOEN(36, HIGH); | |
293 | SYS_IOMUX_DIN(36, 4); | |
294 | /* TDI: GPIO61 */ | |
295 | SYS_IOMUX_DOEN(61, HIGH); | |
296 | SYS_IOMUX_DIN(61, 19); | |
297 | /* TMS: GPIO63 */ | |
298 | SYS_IOMUX_DOEN(63, HIGH); | |
299 | SYS_IOMUX_DIN(63, 20); | |
300 | /* TCK: GPIO60 */ | |
301 | SYS_IOMUX_DOEN(60, HIGH); | |
302 | SYS_IOMUX_DIN(60, 29); | |
303 | /* TDO: GPIO44 */ | |
304 | SYS_IOMUX_DOEN(44, 8); | |
305 | SYS_IOMUX_DOUT(44, 22); | |
306 | } | |
307 | ||
5ecf9b0b YW |
308 | int spl_board_init_f(void) |
309 | { | |
310 | int ret; | |
311 | ||
b8a902b8 CP |
312 | jh7110_jtag_init(); |
313 | ||
19b762cf | 314 | ret = spl_dram_init(); |
5ecf9b0b | 315 | if (ret) { |
19b762cf | 316 | debug("JH7110 DRAM init failed: %d\n", ret); |
5ecf9b0b YW |
317 | return ret; |
318 | } | |
319 | ||
320 | return 0; | |
321 | } | |
322 | ||
323 | u32 spl_boot_device(void) | |
324 | { | |
325 | u32 mode; | |
326 | ||
327 | mode = in_le32(JH7110_BOOT_MODE_SELECT_REG) | |
328 | & JH7110_BOOT_MODE_SELECT_MASK; | |
329 | switch (mode) { | |
330 | case 0: | |
331 | return BOOT_DEVICE_SPI; | |
332 | ||
333 | case 1: | |
334 | return BOOT_DEVICE_MMC2; | |
335 | ||
336 | case 2: | |
337 | return BOOT_DEVICE_MMC1; | |
338 | ||
339 | case 3: | |
340 | return BOOT_DEVICE_UART; | |
341 | ||
342 | default: | |
343 | debug("Unsupported boot device 0x%x.\n", mode); | |
344 | return BOOT_DEVICE_NONE; | |
345 | } | |
346 | } | |
347 | ||
348 | void board_init_f(ulong dummy) | |
349 | { | |
350 | int ret; | |
351 | ||
352 | ret = spl_early_init(); | |
353 | if (ret) | |
354 | panic("spl_early_init() failed: %d\n", ret); | |
355 | ||
f72d0d4a | 356 | riscv_cpu_setup(); |
5ecf9b0b YW |
357 | preloader_console_init(); |
358 | ||
359 | /* Set the parent clock of cpu_root clock to pll0, | |
360 | * it must be initialized here | |
361 | */ | |
362 | clrsetbits_le32(JH7110_SYS_CRG + JH7110_CLK_CPU_ROOT_OFFSET, | |
363 | JH7110_CLK_CPU_ROOT_MASK, | |
364 | BIT(JH7110_CLK_CPU_ROOT_SHIFT)); | |
365 | ||
366 | ret = spl_board_init_f(); | |
367 | if (ret) { | |
368 | debug("spl_board_init_f init failed: %d\n", ret); | |
369 | return; | |
370 | } | |
371 | } | |
372 | ||
373 | #if CONFIG_IS_ENABLED(SPL_LOAD_FIT) | |
374 | int board_fit_config_name_match(const char *name) | |
375 | { | |
376 | /* boot using first FIT config */ | |
377 | return 0; | |
378 | } | |
379 | #endif |