blob: 2620530e03fb7bf0adb3b068074982a4413688ba [file] [log] [blame]
Kever Yangbb337732019-07-22 20:02:01 +08001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * (C) Copyright 2019 Rockchip Electronics Co., Ltd.
4 */
5#include <common.h>
6#include <clk.h>
Simon Glass1d91ba72019-11-14 12:57:37 -07007#include <cpu_func.h>
Kever Yangbb337732019-07-22 20:02:01 +08008#include <dm.h>
Sughosh Ganuc1b8e8b2022-11-10 14:49:15 +05309#include <efi_loader.h>
Roman Kovalivskyi1bb13422020-07-28 23:35:32 +030010#include <fastboot.h>
Simon Glassa7b51302019-11-14 12:57:46 -070011#include <init.h>
Simon Glass0f2af882020-05-10 11:40:05 -060012#include <log.h>
Sughosh Ganuc1b8e8b2022-11-10 14:49:15 +053013#include <mmc.h>
14#include <part.h>
Kever Yangbb337732019-07-22 20:02:01 +080015#include <ram.h>
16#include <syscon.h>
Sughosh Ganuc1b8e8b2022-11-10 14:49:15 +053017#include <uuid.h>
Simon Glass274e0b02020-05-10 11:39:56 -060018#include <asm/cache.h>
Kever Yangbb337732019-07-22 20:02:01 +080019#include <asm/io.h>
20#include <asm/arch-rockchip/boot_mode.h>
21#include <asm/arch-rockchip/clock.h>
22#include <asm/arch-rockchip/periph.h>
Rohan Gargcfdc1922019-08-12 17:04:34 +020023#include <asm/arch-rockchip/misc.h>
Kever Yangbb337732019-07-22 20:02:01 +080024#include <power/regulator.h>
25
Sughosh Ganuc1b8e8b2022-11-10 14:49:15 +053026#if defined(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) && defined(CONFIG_EFI_PARTITION)
27
28#define DFU_ALT_BUF_LEN SZ_1K
29
30static struct efi_fw_image *fw_images;
31
32static bool updatable_image(struct disk_partition *info)
33{
34 int i;
35 bool ret = false;
36 efi_guid_t image_type_guid;
37
38 uuid_str_to_bin(info->type_guid, image_type_guid.b,
39 UUID_STR_FORMAT_GUID);
40
Masahisa Kojima5d2438b2023-06-07 14:41:51 +090041 for (i = 0; i < update_info.num_images; i++) {
Sughosh Ganuc1b8e8b2022-11-10 14:49:15 +053042 if (!guidcmp(&fw_images[i].image_type_id, &image_type_guid)) {
43 ret = true;
44 break;
45 }
46 }
47
48 return ret;
49}
50
51static void set_image_index(struct disk_partition *info, int index)
52{
53 int i;
54 efi_guid_t image_type_guid;
55
56 uuid_str_to_bin(info->type_guid, image_type_guid.b,
57 UUID_STR_FORMAT_GUID);
58
Masahisa Kojima5d2438b2023-06-07 14:41:51 +090059 for (i = 0; i < update_info.num_images; i++) {
Sughosh Ganuc1b8e8b2022-11-10 14:49:15 +053060 if (!guidcmp(&fw_images[i].image_type_id, &image_type_guid)) {
61 fw_images[i].image_index = index;
62 break;
63 }
64 }
65}
66
67static int get_mmc_desc(struct blk_desc **desc)
68{
69 int ret;
70 struct mmc *mmc;
71 struct udevice *dev;
72
73 /*
74 * For now the firmware images are assumed to
75 * be on the SD card
76 */
77 ret = uclass_get_device(UCLASS_MMC, 1, &dev);
78 if (ret)
79 return -1;
80
81 mmc = mmc_get_mmc_dev(dev);
82 if (!mmc)
83 return -ENODEV;
84
85 if ((ret = mmc_init(mmc)))
86 return ret;
87
88 *desc = mmc_get_blk_desc(mmc);
89 if (!*desc)
90 return -1;
91
92 return 0;
93}
94
95void set_dfu_alt_info(char *interface, char *devstr)
96{
97 const char *name;
98 bool first = true;
99 int p, len, devnum, ret;
100 char buf[DFU_ALT_BUF_LEN];
101 struct disk_partition info;
102 struct blk_desc *desc = NULL;
103
104 ret = get_mmc_desc(&desc);
105 if (ret) {
106 log_err("Unable to get mmc desc\n");
107 return;
108 }
109
110 memset(buf, 0, sizeof(buf));
111 name = blk_get_uclass_name(desc->uclass_id);
112 devnum = desc->devnum;
113 len = strlen(buf);
114
115 len += snprintf(buf + len, DFU_ALT_BUF_LEN - len,
116 "%s %d=", name, devnum);
117
118 for (p = 1; p <= MAX_SEARCH_PARTITIONS; p++) {
119 if (part_get_info(desc, p, &info))
120 continue;
121
122 /* Add entry to dfu_alt_info only for updatable images */
123 if (updatable_image(&info)) {
124 if (!first)
125 len += snprintf(buf + len,
126 DFU_ALT_BUF_LEN - len, ";");
127
128 len += snprintf(buf + len, DFU_ALT_BUF_LEN - len,
129 "%s%d_%s part %d %d",
130 name, devnum, info.name, devnum, p);
131 first = false;
132 }
133 }
134
135 log_debug("dfu_alt_info => %s\n", buf);
136 env_set("dfu_alt_info", buf);
137}
138
139static void gpt_capsule_update_setup(void)
140{
141 int p, i, ret;
142 struct disk_partition info;
143 struct blk_desc *desc = NULL;
144
145 fw_images = update_info.images;
146 rockchip_capsule_update_board_setup();
147
148 ret = get_mmc_desc(&desc);
149 if (ret) {
150 log_err("Unable to get mmc desc\n");
151 return;
152 }
153
154 for (p = 1, i = 1; p <= MAX_SEARCH_PARTITIONS; p++) {
155 if (part_get_info(desc, p, &info))
156 continue;
157
158 /*
159 * Since we have a GPT partitioned device, the updatable
160 * images could be stored in any order. Populate the
161 * image_index at runtime.
162 */
163 if (updatable_image(&info)) {
164 set_image_index(&info, i);
165 i++;
166 }
167 }
168}
169#endif /* CONFIG_EFI_HAVE_CAPSULE_SUPPORT && CONFIG_EFI_PARTITION */
170
Kever Yangbb337732019-07-22 20:02:01 +0800171__weak int rk_board_late_init(void)
172{
Sughosh Ganuc1b8e8b2022-11-10 14:49:15 +0530173#if defined(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) && defined(CONFIG_EFI_PARTITION)
174 gpt_capsule_update_setup();
175#endif
176
Kever Yangbb337732019-07-22 20:02:01 +0800177 return 0;
178}
179
180int board_late_init(void)
181{
182 setup_boot_mode();
183
184 return rk_board_late_init();
185}
186
187int board_init(void)
188{
189 int ret;
190
191#ifdef CONFIG_DM_REGULATOR
192 ret = regulators_enable_boot_on(false);
193 if (ret)
194 debug("%s: Cannot enable boot on regulator\n", __func__);
195#endif
196
197 return 0;
198}
199
200#if !defined(CONFIG_SYS_DCACHE_OFF) && !defined(CONFIG_ARM64)
201void enable_caches(void)
202{
203 /* Enable D-cache. I-cache is already enabled in start.S */
204 dcache_enable();
205}
206#endif
207
Jonas Karlman08293182023-11-12 17:48:58 +0000208#if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG)
Kever Yangbb337732019-07-22 20:02:01 +0800209#include <usb.h>
John Keepinga47bf332023-04-12 12:52:52 +0100210#include <linux/usb/otg.h>
Kever Yangbb337732019-07-22 20:02:01 +0800211#include <usb/dwc2_udc.h>
212
213static struct dwc2_plat_otg_data otg_data = {
214 .rx_fifo_sz = 512,
215 .np_tx_fifo_sz = 16,
216 .tx_fifo_sz = 128,
217};
218
219int board_usb_init(int index, enum usb_init_type init)
220{
Kever Yang45bda032019-10-16 17:13:31 +0800221 ofnode node;
Kever Yangbb337732019-07-22 20:02:01 +0800222 bool matched = false;
Kever Yangbb337732019-07-22 20:02:01 +0800223
224 /* find the usb_otg node */
Kever Yang45bda032019-10-16 17:13:31 +0800225 node = ofnode_by_compatible(ofnode_null(), "snps,dwc2");
226 while (ofnode_valid(node)) {
John Keepinga47bf332023-04-12 12:52:52 +0100227 switch (usb_get_dr_mode(node)) {
228 case USB_DR_MODE_OTG:
John Keeping3a0269b2023-04-12 12:52:53 +0100229 case USB_DR_MODE_PERIPHERAL:
Kever Yangbb337732019-07-22 20:02:01 +0800230 matched = true;
231 break;
John Keepinga47bf332023-04-12 12:52:52 +0100232
233 default:
234 break;
Kever Yangbb337732019-07-22 20:02:01 +0800235 }
236
John Keepinga47bf332023-04-12 12:52:52 +0100237 if (matched)
238 break;
239
Kever Yang45bda032019-10-16 17:13:31 +0800240 node = ofnode_by_compatible(node, "snps,dwc2");
Kever Yangbb337732019-07-22 20:02:01 +0800241 }
242 if (!matched) {
243 debug("Not found usb_otg device\n");
244 return -ENODEV;
245 }
Kever Yang45bda032019-10-16 17:13:31 +0800246 otg_data.regs_otg = ofnode_get_addr(node);
Kever Yangbb337732019-07-22 20:02:01 +0800247
Johan Jonkeraa65f3d2022-04-29 23:40:07 +0200248#ifdef CONFIG_ROCKCHIP_USB2_PHY
Kever Yang6169a0d2019-10-16 17:13:32 +0800249 int ret;
250 u32 phandle, offset;
251 ofnode phy_node;
252
253 ret = ofnode_read_u32(node, "phys", &phandle);
254 if (ret)
255 return ret;
256
257 node = ofnode_get_by_phandle(phandle);
258 if (!ofnode_valid(node)) {
259 debug("Not found usb phy device\n");
260 return -ENODEV;
261 }
262
263 phy_node = ofnode_get_parent(node);
264 if (!ofnode_valid(node)) {
265 debug("Not found usb phy device\n");
266 return -ENODEV;
267 }
268
269 otg_data.phy_of_node = phy_node;
270 ret = ofnode_read_u32(node, "reg", &offset);
271 if (ret)
272 return ret;
273 otg_data.regs_phy = offset +
274 (u32)syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
275#endif
Kever Yangbb337732019-07-22 20:02:01 +0800276 return dwc2_udc_probe(&otg_data);
277}
278
279int board_usb_cleanup(int index, enum usb_init_type init)
280{
281 return 0;
282}
Jagan Teki886ecb22019-11-19 13:56:22 +0530283#endif /* CONFIG_USB_GADGET_DWC2_OTG */
284
Simon Glass96c0d2b2023-02-05 17:54:10 -0700285#if IS_ENABLED(CONFIG_FASTBOOT)
Roman Kovalivskyi1bb13422020-07-28 23:35:32 +0300286int fastboot_set_reboot_flag(enum fastboot_reboot_reason reason)
Kever Yangbb337732019-07-22 20:02:01 +0800287{
Roman Kovalivskyi1bb13422020-07-28 23:35:32 +0300288 if (reason != FASTBOOT_REBOOT_REASON_BOOTLOADER)
289 return -ENOTSUPP;
290
Kever Yangbb337732019-07-22 20:02:01 +0800291 printf("Setting reboot to fastboot flag ...\n");
292 /* Set boot mode to fastboot */
293 writel(BOOT_FASTBOOT, CONFIG_ROCKCHIP_BOOT_MODE_REG);
294
295 return 0;
296}
297#endif
Rohan Gargcfdc1922019-08-12 17:04:34 +0200298
299#ifdef CONFIG_MISC_INIT_R
300__weak int misc_init_r(void)
301{
Jonas Karlmanbe56bb52023-02-22 22:44:41 +0000302 const u32 cpuid_offset = CFG_CPUID_OFFSET;
Rohan Gargcfdc1922019-08-12 17:04:34 +0200303 const u32 cpuid_length = 0x10;
304 u8 cpuid[cpuid_length];
305 int ret;
306
307 ret = rockchip_cpuid_from_efuse(cpuid_offset, cpuid_length, cpuid);
308 if (ret)
309 return ret;
310
311 ret = rockchip_cpuid_set(cpuid, cpuid_length);
312 if (ret)
313 return ret;
314
315 ret = rockchip_setup_macaddr();
316
317 return ret;
318}
319#endif
Chris Morganea8e9632024-01-02 09:46:52 -0600320
321#if IS_ENABLED(CONFIG_BOARD_RNG_SEED) && IS_ENABLED(CONFIG_RNG_ROCKCHIP)
322#include <rng.h>
323
324/* Use hardware rng to seed Linux random. */
325__weak int board_rng_seed(struct abuf *buf)
326{
327 struct udevice *dev;
328 size_t len = 0x8;
329 u64 *data;
330
331 data = malloc(len);
332 if (!data) {
333 printf("Out of memory\n");
334 return -ENOMEM;
335 }
336
337 if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
338 printf("No RNG device\n");
339 return -ENODEV;
340 }
341
342 if (dm_rng_read(dev, data, len)) {
343 printf("Reading RNG failed\n");
344 return -EIO;
345 }
346
347 abuf_init_set(buf, data, len);
348
349 return 0;
350}
351#endif