blob: 1b49945d11b0b4f44848c08dabbd219e66f74dbe [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
30static const struct starfive_vf2_pro starfive_vera[] = {
31 {"/soc/ethernet@16030000/mdio/ethernet-phy@0", "rx-internal-delay-ps",
32 "1900"},
33 {"/soc/ethernet@16030000/mdio/ethernet-phy@0", "tx-internal-delay-ps",
34 "1350"}
35};
36
37static const struct starfive_vf2_pro starfive_verb[] = {
38 {"/soc/ethernet@16030000", "starfive,tx-use-rgmii-clk", NULL},
39 {"/soc/ethernet@16040000", "starfive,tx-use-rgmii-clk", NULL},
40
41 {"/soc/ethernet@16030000/mdio/ethernet-phy@0",
42 "motorcomm,tx-clk-adj-enabled", NULL},
43 {"/soc/ethernet@16030000/mdio/ethernet-phy@0",
44 "motorcomm,tx-clk-100-inverted", NULL},
45 {"/soc/ethernet@16030000/mdio/ethernet-phy@0",
46 "motorcomm,tx-clk-1000-inverted", NULL},
47 {"/soc/ethernet@16030000/mdio/ethernet-phy@0",
Lukasz Tekielia99605d2024-01-28 20:22:48 +010048 "motorcomm,rx-clk-drv-microamp", "3970"},
49 {"/soc/ethernet@16030000/mdio/ethernet-phy@0",
50 "motorcomm,rx-data-drv-microamp", "2910"},
51 {"/soc/ethernet@16030000/mdio/ethernet-phy@0",
Yanhong Wang4e321fa2023-06-15 17:36:52 +080052 "rx-internal-delay-ps", "1900"},
53 {"/soc/ethernet@16030000/mdio/ethernet-phy@0",
54 "tx-internal-delay-ps", "1500"},
55
56 {"/soc/ethernet@16040000/mdio/ethernet-phy@1",
57 "motorcomm,tx-clk-adj-enabled", NULL},
58 { "/soc/ethernet@16040000/mdio/ethernet-phy@1",
59 "motorcomm,tx-clk-100-inverted", NULL},
60 {"/soc/ethernet@16040000/mdio/ethernet-phy@1",
Lukasz Tekielia99605d2024-01-28 20:22:48 +010061 "motorcomm,rx-clk-drv-microamp", "3970"},
62 {"/soc/ethernet@16040000/mdio/ethernet-phy@1",
63 "motorcomm,rx-data-drv-microamp", "2910"},
64 {"/soc/ethernet@16040000/mdio/ethernet-phy@1",
Yanhong Wang4e321fa2023-06-15 17:36:52 +080065 "rx-internal-delay-ps", "0"},
66 {"/soc/ethernet@16040000/mdio/ethernet-phy@1",
67 "tx-internal-delay-ps", "0"},
68};
69
70void spl_fdt_fixup_version_a(void *fdt)
71{
Aurelien Jarno5acb7c12024-01-10 21:17:44 +010072 static const char compat[] = "starfive,visionfive-2-v1.2a\0starfive,jh7110";
Yanhong Wang4e321fa2023-06-15 17:36:52 +080073 u32 phandle;
74 u8 i;
75 int offset;
76 int ret;
77
Aurelien Jarno5acb7c12024-01-10 21:17:44 +010078 fdt_setprop(fdt, fdt_path_offset(fdt, "/"), "compatible", compat, sizeof(compat));
Yanhong Wang4e321fa2023-06-15 17:36:52 +080079 fdt_setprop_string(fdt, fdt_path_offset(fdt, "/"), "model",
80 "StarFive VisionFive 2 v1.2A");
81
82 offset = fdt_path_offset(fdt, "/soc/clock-controller@13020000");
83 phandle = fdt_get_phandle(fdt, offset);
84 offset = fdt_path_offset(fdt, "/soc/ethernet@16040000");
85
86 fdt_setprop_u32(fdt, offset, "assigned-clocks", phandle);
87 fdt_appendprop_u32(fdt, offset, "assigned-clocks", JH7110_SYSCLK_GMAC1_TX);
88 fdt_appendprop_u32(fdt, offset, "assigned-clocks", phandle);
89 fdt_appendprop_u32(fdt, offset, "assigned-clocks", JH7110_SYSCLK_GMAC1_RX);
90
91 fdt_setprop_u32(fdt, offset, "assigned-clock-parents", phandle);
92 fdt_appendprop_u32(fdt, offset, "assigned-clock-parents",
93 JH7110_SYSCLK_GMAC1_RMII_RTX);
94 fdt_appendprop_u32(fdt, offset, "assigned-clock-parents", phandle);
95 fdt_appendprop_u32(fdt, offset, "assigned-clock-parents",
96 JH7110_SYSCLK_GMAC1_RMII_RTX);
97
98 fdt_setprop_string(fdt, fdt_path_offset(fdt, "/soc/ethernet@16040000"),
99 "phy-mode", "rmii");
100
101 for (i = 0; i < ARRAY_SIZE(starfive_vera); i++) {
102 offset = fdt_path_offset(fdt, starfive_vera[i].path);
103
104 if (starfive_vera[i].value)
105 ret = fdt_setprop_u32(fdt, offset, starfive_vera[i].name,
106 dectoul(starfive_vera[i].value, NULL));
107 else
108 ret = fdt_setprop_empty(fdt, offset, starfive_vera[i].name);
109
110 if (ret) {
111 pr_err("%s set prop %s fail.\n", __func__, starfive_vera[i].name);
112 break;
113 }
114 }
115}
116
117void spl_fdt_fixup_version_b(void *fdt)
118{
Aurelien Jarno5acb7c12024-01-10 21:17:44 +0100119 static const char compat[] = "starfive,visionfive-2-v1.3b\0starfive,jh7110";
Yanhong Wang4e321fa2023-06-15 17:36:52 +0800120 u32 phandle;
121 u8 i;
122 int offset;
123 int ret;
124
Aurelien Jarno5acb7c12024-01-10 21:17:44 +0100125 fdt_setprop(fdt, fdt_path_offset(fdt, "/"), "compatible", compat, sizeof(compat));
Yanhong Wang4e321fa2023-06-15 17:36:52 +0800126 fdt_setprop_string(fdt, fdt_path_offset(fdt, "/"), "model",
127 "StarFive VisionFive 2 v1.3B");
128
129 /* gmac0 */
130 offset = fdt_path_offset(fdt, "/soc/clock-controller@17000000");
131 phandle = fdt_get_phandle(fdt, offset);
132 offset = fdt_path_offset(fdt, "/soc/ethernet@16030000");
133
134 fdt_setprop_u32(fdt, offset, "assigned-clocks", phandle);
135 fdt_appendprop_u32(fdt, offset, "assigned-clocks", JH7110_AONCLK_GMAC0_TX);
136 fdt_setprop_u32(fdt, offset, "assigned-clock-parents", phandle);
137 fdt_appendprop_u32(fdt, offset, "assigned-clock-parents",
138 JH7110_AONCLK_GMAC0_RMII_RTX);
139
140 /* gmac1 */
141 offset = fdt_path_offset(fdt, "/soc/clock-controller@13020000");
142 phandle = fdt_get_phandle(fdt, offset);
143 offset = fdt_path_offset(fdt, "/soc/ethernet@16040000");
144
145 fdt_setprop_u32(fdt, offset, "assigned-clocks", phandle);
146 fdt_appendprop_u32(fdt, offset, "assigned-clocks", JH7110_SYSCLK_GMAC1_TX);
147 fdt_setprop_u32(fdt, offset, "assigned-clock-parents", phandle);
148 fdt_appendprop_u32(fdt, offset, "assigned-clock-parents",
149 JH7110_SYSCLK_GMAC1_RMII_RTX);
150
151 for (i = 0; i < ARRAY_SIZE(starfive_verb); i++) {
152 offset = fdt_path_offset(fdt, starfive_verb[i].path);
153
154 if (starfive_verb[i].value)
155 ret = fdt_setprop_u32(fdt, offset, starfive_verb[i].name,
156 dectoul(starfive_verb[i].value, NULL));
157 else
158 ret = fdt_setprop_empty(fdt, offset, starfive_verb[i].name);
159
160 if (ret) {
161 pr_err("%s set prop %s fail.\n", __func__, starfive_verb[i].name);
162 break;
163 }
164 }
165}
166
167void spl_perform_fixups(struct spl_image_info *spl_image)
168{
169 u8 version;
170
171 version = get_pcb_revision_from_eeprom();
172 switch (version) {
173 case 'a':
174 case 'A':
175 spl_fdt_fixup_version_a(spl_image->fdt_addr);
176 break;
177
178 case 'b':
179 case 'B':
180 default:
181 spl_fdt_fixup_version_b(spl_image->fdt_addr);
182 break;
183 };
184
185 /* Update the memory size which read form eeprom or DT */
186 fdt_fixup_memory(spl_image->fdt_addr, 0x40000000, gd->ram_size);
187}
Chanho Park9ca68c92023-10-31 17:56:00 +0900188
189static void jh7110_jtag_init(void)
190{
191 /* nTRST: GPIO36 */
192 SYS_IOMUX_DOEN(36, HIGH);
193 SYS_IOMUX_DIN(36, 4);
194 /* TDI: GPIO61 */
195 SYS_IOMUX_DOEN(61, HIGH);
196 SYS_IOMUX_DIN(61, 19);
197 /* TMS: GPIO63 */
198 SYS_IOMUX_DOEN(63, HIGH);
199 SYS_IOMUX_DIN(63, 20);
200 /* TCK: GPIO60 */
201 SYS_IOMUX_DOEN(60, HIGH);
202 SYS_IOMUX_DIN(60, 29);
203 /* TDO: GPIO44 */
204 SYS_IOMUX_DOEN(44, 8);
205 SYS_IOMUX_DOUT(44, 22);
206}
207
Yanhong Wang6a5a45d2023-03-29 11:42:17 +0800208int spl_board_init_f(void)
209{
210 int ret;
211
Chanho Park9ca68c92023-10-31 17:56:00 +0900212 jh7110_jtag_init();
213
Yanhong Wang6a5a45d2023-03-29 11:42:17 +0800214 ret = spl_soc_init();
215 if (ret) {
216 debug("JH7110 SPL init failed: %d\n", ret);
217 return ret;
218 }
219
220 return 0;
221}
222
223u32 spl_boot_device(void)
224{
225 u32 mode;
226
227 mode = in_le32(JH7110_BOOT_MODE_SELECT_REG)
228 & JH7110_BOOT_MODE_SELECT_MASK;
229 switch (mode) {
230 case 0:
231 return BOOT_DEVICE_SPI;
232
233 case 1:
234 return BOOT_DEVICE_MMC2;
235
236 case 2:
237 return BOOT_DEVICE_MMC1;
238
239 case 3:
240 return BOOT_DEVICE_UART;
241
242 default:
243 debug("Unsupported boot device 0x%x.\n", mode);
244 return BOOT_DEVICE_NONE;
245 }
246}
247
248void board_init_f(ulong dummy)
249{
250 int ret;
251
252 ret = spl_early_init();
253 if (ret)
254 panic("spl_early_init() failed: %d\n", ret);
255
Simon Glassb8357c12023-08-21 21:16:56 -0600256 riscv_cpu_setup();
Yanhong Wang6a5a45d2023-03-29 11:42:17 +0800257 preloader_console_init();
258
259 /* Set the parent clock of cpu_root clock to pll0,
260 * it must be initialized here
261 */
262 clrsetbits_le32(JH7110_SYS_CRG + JH7110_CLK_CPU_ROOT_OFFSET,
263 JH7110_CLK_CPU_ROOT_MASK,
264 BIT(JH7110_CLK_CPU_ROOT_SHIFT));
265
266 ret = spl_board_init_f();
267 if (ret) {
268 debug("spl_board_init_f init failed: %d\n", ret);
269 return;
270 }
271}
272
273#if CONFIG_IS_ENABLED(SPL_LOAD_FIT)
274int board_fit_config_name_match(const char *name)
275{
276 /* boot using first FIT config */
277 return 0;
278}
279#endif