xref: /openbmc/u-boot/board/raspberrypi/rpi/rpi.c (revision 500ad54e)
183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0
29316e144SStephen Warren /*
3f031f501SStephen Warren  * (C) Copyright 2012-2016 Stephen Warren
49316e144SStephen Warren  */
59316e144SStephen Warren 
69316e144SStephen Warren #include <common.h>
79316e144SStephen Warren #include <config.h>
89316e144SStephen Warren #include <dm.h>
99925f1dbSAlex Kiernan #include <environment.h>
101bcf7a30SAlexander Graf #include <efi_loader.h>
119316e144SStephen Warren #include <fdt_support.h>
12033167c4SNikita Kiryanov #include <fdt_simplefb.h>
139316e144SStephen Warren #include <lcd.h>
14cf92e05cSSimon Glass #include <memalign.h>
159316e144SStephen Warren #include <mmc.h>
169316e144SStephen Warren #include <asm/gpio.h>
179316e144SStephen Warren #include <asm/arch/mbox.h>
1870997d88SSimon Glass #include <asm/arch/msg.h>
199316e144SStephen Warren #include <asm/arch/sdhci.h>
209316e144SStephen Warren #include <asm/global_data.h>
21f031f501SStephen Warren #include <dm/platform_data/serial_bcm283x_mu.h>
22d22a7657SStephen Warren #ifdef CONFIG_ARM64
23d22a7657SStephen Warren #include <asm/armv8/mmu.h>
24d22a7657SStephen Warren #endif
2545a6d231SPaolo Pisati #include <watchdog.h>
26caf2233bSAlexander Graf #include <dm/pinctrl.h>
279316e144SStephen Warren 
289316e144SStephen Warren DECLARE_GLOBAL_DATA_PTR;
299316e144SStephen Warren 
30ade243a2SCédric Schieli /* From lowlevel_init.S */
31ade243a2SCédric Schieli extern unsigned long fw_dtb_pointer;
32ade243a2SCédric Schieli 
333e16705dSSimon Glass /* TODO(sjg@chromium.org): Move these to the msg.c file */
349316e144SStephen Warren struct msg_get_arm_mem {
359316e144SStephen Warren 	struct bcm2835_mbox_hdr hdr;
369316e144SStephen Warren 	struct bcm2835_mbox_tag_get_arm_mem get_arm_mem;
379316e144SStephen Warren 	u32 end_tag;
389316e144SStephen Warren };
399316e144SStephen Warren 
409316e144SStephen Warren struct msg_get_board_rev {
419316e144SStephen Warren 	struct bcm2835_mbox_hdr hdr;
429316e144SStephen Warren 	struct bcm2835_mbox_tag_get_board_rev get_board_rev;
439316e144SStephen Warren 	u32 end_tag;
449316e144SStephen Warren };
459316e144SStephen Warren 
46757cd149SLubomir Rintel struct msg_get_board_serial {
47757cd149SLubomir Rintel 	struct bcm2835_mbox_hdr hdr;
48757cd149SLubomir Rintel 	struct bcm2835_mbox_tag_get_board_serial get_board_serial;
49757cd149SLubomir Rintel 	u32 end_tag;
50757cd149SLubomir Rintel };
51757cd149SLubomir Rintel 
529316e144SStephen Warren struct msg_get_mac_address {
539316e144SStephen Warren 	struct bcm2835_mbox_hdr hdr;
549316e144SStephen Warren 	struct bcm2835_mbox_tag_get_mac_address get_mac_address;
559316e144SStephen Warren 	u32 end_tag;
569316e144SStephen Warren };
579316e144SStephen Warren 
589316e144SStephen Warren struct msg_get_clock_rate {
599316e144SStephen Warren 	struct bcm2835_mbox_hdr hdr;
609316e144SStephen Warren 	struct bcm2835_mbox_tag_get_clock_rate get_clock_rate;
619316e144SStephen Warren 	u32 end_tag;
629316e144SStephen Warren };
639316e144SStephen Warren 
645d3c4ba1STuomas Tynkkynen #ifdef CONFIG_ARM64
655d3c4ba1STuomas Tynkkynen #define DTB_DIR "broadcom/"
665d3c4ba1STuomas Tynkkynen #else
675d3c4ba1STuomas Tynkkynen #define DTB_DIR ""
685d3c4ba1STuomas Tynkkynen #endif
695d3c4ba1STuomas Tynkkynen 
70dbe6f1ebSStephen Warren /*
71cb3f9471SJonathan Gray  * https://www.raspberrypi.org/documentation/hardware/raspberrypi/revision-codes/README.md
72dbe6f1ebSStephen Warren  */
73c4ea1edbSStephen Warren struct rpi_model {
749316e144SStephen Warren 	const char *name;
759316e144SStephen Warren 	const char *fdtfile;
763207d8fcSStephen Warren 	bool has_onboard_eth;
77c4ea1edbSStephen Warren };
78c4ea1edbSStephen Warren 
79c4ea1edbSStephen Warren static const struct rpi_model rpi_model_unknown = {
80914627feSStephen Warren 	"Unknown model",
815d3c4ba1STuomas Tynkkynen 	DTB_DIR "bcm283x-rpi-other.dtb",
82914627feSStephen Warren 	false,
83c4ea1edbSStephen Warren };
84c4ea1edbSStephen Warren 
85c4ea1edbSStephen Warren static const struct rpi_model rpi_models_new_scheme[] = {
8691e1bc53SJonathan Gray 	[0x0] = {
8791e1bc53SJonathan Gray 		"Model A",
8891e1bc53SJonathan Gray 		DTB_DIR "bcm2835-rpi-a.dtb",
8991e1bc53SJonathan Gray 		false,
9091e1bc53SJonathan Gray 	},
9191e1bc53SJonathan Gray 	[0x1] = {
9291e1bc53SJonathan Gray 		"Model B",
9391e1bc53SJonathan Gray 		DTB_DIR "bcm2835-rpi-b.dtb",
9491e1bc53SJonathan Gray 		true,
9591e1bc53SJonathan Gray 	},
9691e1bc53SJonathan Gray 	[0x2] = {
9791e1bc53SJonathan Gray 		"Model A+",
9891e1bc53SJonathan Gray 		DTB_DIR "bcm2835-rpi-a-plus.dtb",
9991e1bc53SJonathan Gray 		false,
10091e1bc53SJonathan Gray 	},
10191e1bc53SJonathan Gray 	[0x3] = {
10291e1bc53SJonathan Gray 		"Model B+",
10391e1bc53SJonathan Gray 		DTB_DIR "bcm2835-rpi-b-plus.dtb",
10491e1bc53SJonathan Gray 		true,
10591e1bc53SJonathan Gray 	},
106dbe6f1ebSStephen Warren 	[0x4] = {
10746414296SStephen Warren 		"2 Model B",
1085d3c4ba1STuomas Tynkkynen 		DTB_DIR "bcm2836-rpi-2-b.dtb",
10946414296SStephen Warren 		true,
11046414296SStephen Warren 	},
11191e1bc53SJonathan Gray 	[0x6] = {
11291e1bc53SJonathan Gray 		"Compute Module",
11391e1bc53SJonathan Gray 		DTB_DIR "bcm2835-rpi-cm.dtb",
11491e1bc53SJonathan Gray 		false,
11591e1bc53SJonathan Gray 	},
1167233fb31SStephen Warren 	[0x8] = {
1177233fb31SStephen Warren 		"3 Model B",
1185d3c4ba1STuomas Tynkkynen 		DTB_DIR "bcm2837-rpi-3-b.dtb",
1197233fb31SStephen Warren 		true,
1207233fb31SStephen Warren 	},
121af7c03eaSStephen Warren 	[0x9] = {
122af7c03eaSStephen Warren 		"Zero",
1235d3c4ba1STuomas Tynkkynen 		DTB_DIR "bcm2835-rpi-zero.dtb",
124af7c03eaSStephen Warren 		false,
125af7c03eaSStephen Warren 	},
12691e1bc53SJonathan Gray 	[0xA] = {
12791e1bc53SJonathan Gray 		"Compute Module 3",
12891e1bc53SJonathan Gray 		DTB_DIR "bcm2837-rpi-cm3.dtb",
12991e1bc53SJonathan Gray 		false,
13091e1bc53SJonathan Gray 	},
1318993056fSDmitry Korunov 	[0xC] = {
1328993056fSDmitry Korunov 		"Zero W",
1338993056fSDmitry Korunov 		DTB_DIR "bcm2835-rpi-zero-w.dtb",
1348993056fSDmitry Korunov 		false,
1358993056fSDmitry Korunov 	},
1367fe77226SAlexander Graf 	[0xD] = {
1377fe77226SAlexander Graf 		"3 Model B+",
1387fe77226SAlexander Graf 		DTB_DIR "bcm2837-rpi-3-b-plus.dtb",
1397fe77226SAlexander Graf 		true,
1407fe77226SAlexander Graf 	},
141d61cf138SJonathan Gray 	[0xE] = {
142d61cf138SJonathan Gray 		"3 Model A+",
143d61cf138SJonathan Gray 		DTB_DIR "bcm2837-rpi-3-a-plus.dtb",
144d61cf138SJonathan Gray 		false,
145d61cf138SJonathan Gray 	},
146*7e2ae620SJonathan Gray 	[0x10] = {
147*7e2ae620SJonathan Gray 		"Compute Module 3+",
148*7e2ae620SJonathan Gray 		DTB_DIR "bcm2837-rpi-cm3.dtb",
149*7e2ae620SJonathan Gray 		false,
150*7e2ae620SJonathan Gray 	},
151c4ea1edbSStephen Warren };
152c4ea1edbSStephen Warren 
153c4ea1edbSStephen Warren static const struct rpi_model rpi_models_old_scheme[] = {
154dbe6f1ebSStephen Warren 	[0x2] = {
1557443a9c4SLubomir Rintel 		"Model B",
1565d3c4ba1STuomas Tynkkynen 		DTB_DIR "bcm2835-rpi-b.dtb",
1573207d8fcSStephen Warren 		true,
1589316e144SStephen Warren 	},
159dbe6f1ebSStephen Warren 	[0x3] = {
1607443a9c4SLubomir Rintel 		"Model B",
1615d3c4ba1STuomas Tynkkynen 		DTB_DIR "bcm2835-rpi-b.dtb",
1623207d8fcSStephen Warren 		true,
1639316e144SStephen Warren 	},
164dbe6f1ebSStephen Warren 	[0x4] = {
1657443a9c4SLubomir Rintel 		"Model B rev2",
1665d3c4ba1STuomas Tynkkynen 		DTB_DIR "bcm2835-rpi-b-rev2.dtb",
1673207d8fcSStephen Warren 		true,
1689316e144SStephen Warren 	},
169dbe6f1ebSStephen Warren 	[0x5] = {
1707443a9c4SLubomir Rintel 		"Model B rev2",
1715d3c4ba1STuomas Tynkkynen 		DTB_DIR "bcm2835-rpi-b-rev2.dtb",
1723207d8fcSStephen Warren 		true,
1739316e144SStephen Warren 	},
174dbe6f1ebSStephen Warren 	[0x6] = {
1757443a9c4SLubomir Rintel 		"Model B rev2",
1765d3c4ba1STuomas Tynkkynen 		DTB_DIR "bcm2835-rpi-b-rev2.dtb",
1773207d8fcSStephen Warren 		true,
1789316e144SStephen Warren 	},
179dbe6f1ebSStephen Warren 	[0x7] = {
1809316e144SStephen Warren 		"Model A",
1815d3c4ba1STuomas Tynkkynen 		DTB_DIR "bcm2835-rpi-a.dtb",
1823207d8fcSStephen Warren 		false,
1839316e144SStephen Warren 	},
184dbe6f1ebSStephen Warren 	[0x8] = {
1859316e144SStephen Warren 		"Model A",
1865d3c4ba1STuomas Tynkkynen 		DTB_DIR "bcm2835-rpi-a.dtb",
1873207d8fcSStephen Warren 		false,
1889316e144SStephen Warren 	},
189dbe6f1ebSStephen Warren 	[0x9] = {
1909316e144SStephen Warren 		"Model A",
1915d3c4ba1STuomas Tynkkynen 		DTB_DIR "bcm2835-rpi-a.dtb",
1923207d8fcSStephen Warren 		false,
1939316e144SStephen Warren 	},
194dbe6f1ebSStephen Warren 	[0xd] = {
1959316e144SStephen Warren 		"Model B rev2",
1965d3c4ba1STuomas Tynkkynen 		DTB_DIR "bcm2835-rpi-b-rev2.dtb",
1973207d8fcSStephen Warren 		true,
1989316e144SStephen Warren 	},
199dbe6f1ebSStephen Warren 	[0xe] = {
2009316e144SStephen Warren 		"Model B rev2",
2015d3c4ba1STuomas Tynkkynen 		DTB_DIR "bcm2835-rpi-b-rev2.dtb",
2023207d8fcSStephen Warren 		true,
2039316e144SStephen Warren 	},
204dbe6f1ebSStephen Warren 	[0xf] = {
2059316e144SStephen Warren 		"Model B rev2",
2065d3c4ba1STuomas Tynkkynen 		DTB_DIR "bcm2835-rpi-b-rev2.dtb",
2073207d8fcSStephen Warren 		true,
2089316e144SStephen Warren 	},
209dbe6f1ebSStephen Warren 	[0x10] = {
2109316e144SStephen Warren 		"Model B+",
2115d3c4ba1STuomas Tynkkynen 		DTB_DIR "bcm2835-rpi-b-plus.dtb",
2123207d8fcSStephen Warren 		true,
2139316e144SStephen Warren 	},
214dbe6f1ebSStephen Warren 	[0x11] = {
2159316e144SStephen Warren 		"Compute Module",
2165d3c4ba1STuomas Tynkkynen 		DTB_DIR "bcm2835-rpi-cm.dtb",
2173207d8fcSStephen Warren 		false,
2189316e144SStephen Warren 	},
219dbe6f1ebSStephen Warren 	[0x12] = {
22047705effSStephen Warren 		"Model A+",
2215d3c4ba1STuomas Tynkkynen 		DTB_DIR "bcm2835-rpi-a-plus.dtb",
22247705effSStephen Warren 		false,
22347705effSStephen Warren 	},
224dbe6f1ebSStephen Warren 	[0x13] = {
225787affb4SStephen Warren 		"Model B+",
2265d3c4ba1STuomas Tynkkynen 		DTB_DIR "bcm2835-rpi-b-plus.dtb",
227787affb4SStephen Warren 		true,
228787affb4SStephen Warren 	},
229dbe6f1ebSStephen Warren 	[0x14] = {
230787affb4SStephen Warren 		"Compute Module",
2315d3c4ba1STuomas Tynkkynen 		DTB_DIR "bcm2835-rpi-cm.dtb",
232787affb4SStephen Warren 		false,
233787affb4SStephen Warren 	},
234dbe6f1ebSStephen Warren 	[0x15] = {
23579ad5cefSLubomir Rintel 		"Model A+",
2365d3c4ba1STuomas Tynkkynen 		DTB_DIR "bcm2835-rpi-a-plus.dtb",
23779ad5cefSLubomir Rintel 		false,
23879ad5cefSLubomir Rintel 	},
2399316e144SStephen Warren };
2409316e144SStephen Warren 
241c4ea1edbSStephen Warren static uint32_t revision;
242c4ea1edbSStephen Warren static uint32_t rev_scheme;
243c4ea1edbSStephen Warren static uint32_t rev_type;
244c4ea1edbSStephen Warren static const struct rpi_model *model;
2459316e144SStephen Warren 
246d22a7657SStephen Warren #ifdef CONFIG_ARM64
247d22a7657SStephen Warren static struct mm_region bcm2837_mem_map[] = {
248d22a7657SStephen Warren 	{
249cd4b0c5fSYork Sun 		.virt = 0x00000000UL,
250cd4b0c5fSYork Sun 		.phys = 0x00000000UL,
251d22a7657SStephen Warren 		.size = 0x3f000000UL,
252d22a7657SStephen Warren 		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
253d22a7657SStephen Warren 			 PTE_BLOCK_INNER_SHARE
254d22a7657SStephen Warren 	}, {
255cd4b0c5fSYork Sun 		.virt = 0x3f000000UL,
256cd4b0c5fSYork Sun 		.phys = 0x3f000000UL,
257d22a7657SStephen Warren 		.size = 0x01000000UL,
258d22a7657SStephen Warren 		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
259d22a7657SStephen Warren 			 PTE_BLOCK_NON_SHARE |
260d22a7657SStephen Warren 			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
261d22a7657SStephen Warren 	}, {
262d22a7657SStephen Warren 		/* List terminator */
263d22a7657SStephen Warren 		0,
264d22a7657SStephen Warren 	}
265d22a7657SStephen Warren };
266d22a7657SStephen Warren 
267d22a7657SStephen Warren struct mm_region *mem_map = bcm2837_mem_map;
268d22a7657SStephen Warren #endif
269d22a7657SStephen Warren 
dram_init(void)2709316e144SStephen Warren int dram_init(void)
2719316e144SStephen Warren {
272927753aeSAlexander Stein 	ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_arm_mem, msg, 1);
2739316e144SStephen Warren 	int ret;
2749316e144SStephen Warren 
2759316e144SStephen Warren 	BCM2835_MBOX_INIT_HDR(msg);
2769316e144SStephen Warren 	BCM2835_MBOX_INIT_TAG(&msg->get_arm_mem, GET_ARM_MEMORY);
2779316e144SStephen Warren 
2789316e144SStephen Warren 	ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr);
2799316e144SStephen Warren 	if (ret) {
2809316e144SStephen Warren 		printf("bcm2835: Could not query ARM memory size\n");
2819316e144SStephen Warren 		return -1;
2829316e144SStephen Warren 	}
2839316e144SStephen Warren 
2849316e144SStephen Warren 	gd->ram_size = msg->get_arm_mem.body.resp.mem_size;
2859316e144SStephen Warren 
2869316e144SStephen Warren 	return 0;
2879316e144SStephen Warren }
2889316e144SStephen Warren 
set_fdtfile(void)2899316e144SStephen Warren static void set_fdtfile(void)
2909316e144SStephen Warren {
2919316e144SStephen Warren 	const char *fdtfile;
2929316e144SStephen Warren 
29300caae6dSSimon Glass 	if (env_get("fdtfile"))
2949316e144SStephen Warren 		return;
2959316e144SStephen Warren 
296c4ea1edbSStephen Warren 	fdtfile = model->fdtfile;
297382bee57SSimon Glass 	env_set("fdtfile", fdtfile);
2989316e144SStephen Warren }
2999316e144SStephen Warren 
300ade243a2SCédric Schieli /*
301ade243a2SCédric Schieli  * If the firmware provided a valid FDT at boot time, let's expose it in
302ade243a2SCédric Schieli  * ${fdt_addr} so it may be passed unmodified to the kernel.
303ade243a2SCédric Schieli  */
set_fdt_addr(void)304ade243a2SCédric Schieli static void set_fdt_addr(void)
305ade243a2SCédric Schieli {
30600caae6dSSimon Glass 	if (env_get("fdt_addr"))
307ade243a2SCédric Schieli 		return;
308ade243a2SCédric Schieli 
309ade243a2SCédric Schieli 	if (fdt_magic(fw_dtb_pointer) != FDT_MAGIC)
310ade243a2SCédric Schieli 		return;
311ade243a2SCédric Schieli 
312018f5303SSimon Glass 	env_set_hex("fdt_addr", fw_dtb_pointer);
313ade243a2SCédric Schieli }
314ade243a2SCédric Schieli 
315ade243a2SCédric Schieli /*
316ade243a2SCédric Schieli  * Prevent relocation from stomping on a firmware provided FDT blob.
317ade243a2SCédric Schieli  */
board_get_usable_ram_top(unsigned long total_size)318ade243a2SCédric Schieli unsigned long board_get_usable_ram_top(unsigned long total_size)
319ade243a2SCédric Schieli {
320ade243a2SCédric Schieli 	if ((gd->ram_top - fw_dtb_pointer) > SZ_64M)
321ade243a2SCédric Schieli 		return gd->ram_top;
322ade243a2SCédric Schieli 	return fw_dtb_pointer & ~0xffff;
323ade243a2SCédric Schieli }
324ade243a2SCédric Schieli 
set_usbethaddr(void)3259316e144SStephen Warren static void set_usbethaddr(void)
3269316e144SStephen Warren {
327927753aeSAlexander Stein 	ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_mac_address, msg, 1);
3289316e144SStephen Warren 	int ret;
3299316e144SStephen Warren 
330c4ea1edbSStephen Warren 	if (!model->has_onboard_eth)
3313207d8fcSStephen Warren 		return;
3323207d8fcSStephen Warren 
33300caae6dSSimon Glass 	if (env_get("usbethaddr"))
3349316e144SStephen Warren 		return;
3359316e144SStephen Warren 
3369316e144SStephen Warren 	BCM2835_MBOX_INIT_HDR(msg);
3379316e144SStephen Warren 	BCM2835_MBOX_INIT_TAG(&msg->get_mac_address, GET_MAC_ADDRESS);
3389316e144SStephen Warren 
3399316e144SStephen Warren 	ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr);
3409316e144SStephen Warren 	if (ret) {
3419316e144SStephen Warren 		printf("bcm2835: Could not query MAC address\n");
3429316e144SStephen Warren 		/* Ignore error; not critical */
3439316e144SStephen Warren 		return;
3449316e144SStephen Warren 	}
3459316e144SStephen Warren 
346fd1e959eSSimon Glass 	eth_env_set_enetaddr("usbethaddr", msg->get_mac_address.body.resp.mac);
3479316e144SStephen Warren 
34800caae6dSSimon Glass 	if (!env_get("ethaddr"))
34900caae6dSSimon Glass 		env_set("ethaddr", env_get("usbethaddr"));
350859f1437SLubomir Rintel 
3519316e144SStephen Warren 	return;
3529316e144SStephen Warren }
3539316e144SStephen Warren 
354bff78567SGuillaume GARDET #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
set_board_info(void)355bff78567SGuillaume GARDET static void set_board_info(void)
356bff78567SGuillaume GARDET {
357c4ea1edbSStephen Warren 	char s[11];
358c4ea1edbSStephen Warren 
359c4ea1edbSStephen Warren 	snprintf(s, sizeof(s), "0x%X", revision);
360382bee57SSimon Glass 	env_set("board_revision", s);
361c4ea1edbSStephen Warren 	snprintf(s, sizeof(s), "%d", rev_scheme);
362382bee57SSimon Glass 	env_set("board_rev_scheme", s);
363c4ea1edbSStephen Warren 	/* Can't rename this to board_rev_type since it's an ABI for scripts */
364c4ea1edbSStephen Warren 	snprintf(s, sizeof(s), "0x%X", rev_type);
365382bee57SSimon Glass 	env_set("board_rev", s);
366382bee57SSimon Glass 	env_set("board_name", model->name);
367bff78567SGuillaume GARDET }
368bff78567SGuillaume GARDET #endif /* CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG */
369bff78567SGuillaume GARDET 
set_serial_number(void)370757cd149SLubomir Rintel static void set_serial_number(void)
371757cd149SLubomir Rintel {
372757cd149SLubomir Rintel 	ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_board_serial, msg, 1);
373757cd149SLubomir Rintel 	int ret;
374757cd149SLubomir Rintel 	char serial_string[17] = { 0 };
375757cd149SLubomir Rintel 
37600caae6dSSimon Glass 	if (env_get("serial#"))
377757cd149SLubomir Rintel 		return;
378757cd149SLubomir Rintel 
379757cd149SLubomir Rintel 	BCM2835_MBOX_INIT_HDR(msg);
380757cd149SLubomir Rintel 	BCM2835_MBOX_INIT_TAG_NO_REQ(&msg->get_board_serial, GET_BOARD_SERIAL);
381757cd149SLubomir Rintel 
382757cd149SLubomir Rintel 	ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr);
383757cd149SLubomir Rintel 	if (ret) {
384757cd149SLubomir Rintel 		printf("bcm2835: Could not query board serial\n");
385757cd149SLubomir Rintel 		/* Ignore error; not critical */
386757cd149SLubomir Rintel 		return;
387757cd149SLubomir Rintel 	}
388757cd149SLubomir Rintel 
389dee37fc9SMasahiro Yamada 	snprintf(serial_string, sizeof(serial_string), "%016llx",
390757cd149SLubomir Rintel 		 msg->get_board_serial.body.resp.serial);
391382bee57SSimon Glass 	env_set("serial#", serial_string);
392757cd149SLubomir Rintel }
393757cd149SLubomir Rintel 
misc_init_r(void)3949316e144SStephen Warren int misc_init_r(void)
3959316e144SStephen Warren {
396ade243a2SCédric Schieli 	set_fdt_addr();
3979316e144SStephen Warren 	set_fdtfile();
3989316e144SStephen Warren 	set_usbethaddr();
399bff78567SGuillaume GARDET #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
400bff78567SGuillaume GARDET 	set_board_info();
401bff78567SGuillaume GARDET #endif
402757cd149SLubomir Rintel 	set_serial_number();
403757cd149SLubomir Rintel 
4049316e144SStephen Warren 	return 0;
4059316e144SStephen Warren }
4069316e144SStephen Warren 
get_board_rev(void)4079316e144SStephen Warren static void get_board_rev(void)
4089316e144SStephen Warren {
409927753aeSAlexander Stein 	ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_board_rev, msg, 1);
4109316e144SStephen Warren 	int ret;
411c4ea1edbSStephen Warren 	const struct rpi_model *models;
412c4ea1edbSStephen Warren 	uint32_t models_count;
4139316e144SStephen Warren 
4149316e144SStephen Warren 	BCM2835_MBOX_INIT_HDR(msg);
4159316e144SStephen Warren 	BCM2835_MBOX_INIT_TAG(&msg->get_board_rev, GET_BOARD_REV);
4169316e144SStephen Warren 
4179316e144SStephen Warren 	ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr);
4189316e144SStephen Warren 	if (ret) {
4199316e144SStephen Warren 		printf("bcm2835: Could not query board revision\n");
4209316e144SStephen Warren 		/* Ignore error; not critical */
4219316e144SStephen Warren 		return;
4229316e144SStephen Warren 	}
4239316e144SStephen Warren 
42446414296SStephen Warren 	/*
42546414296SStephen Warren 	 * For details of old-vs-new scheme, see:
42646414296SStephen Warren 	 * https://github.com/pimoroni/RPi.version/blob/master/RPi/version.py
42746414296SStephen Warren 	 * http://www.raspberrypi.org/forums/viewtopic.php?f=63&t=99293&p=690282
42846414296SStephen Warren 	 * (a few posts down)
42995b4f112SStephen Warren 	 *
43095b4f112SStephen Warren 	 * For the RPi 1, bit 24 is the "warranty bit", so we mask off just the
43195b4f112SStephen Warren 	 * lower byte to use as the board rev:
43295b4f112SStephen Warren 	 * http://www.raspberrypi.org/forums/viewtopic.php?f=63&t=98367&start=250
43395b4f112SStephen Warren 	 * http://www.raspberrypi.org/forums/viewtopic.php?f=31&t=20594
43446414296SStephen Warren 	 */
435c4ea1edbSStephen Warren 	revision = msg->get_board_rev.body.resp.rev;
436c4ea1edbSStephen Warren 	if (revision & 0x800000) {
437c4ea1edbSStephen Warren 		rev_scheme = 1;
438c4ea1edbSStephen Warren 		rev_type = (revision >> 4) & 0xff;
439c4ea1edbSStephen Warren 		models = rpi_models_new_scheme;
440c4ea1edbSStephen Warren 		models_count = ARRAY_SIZE(rpi_models_new_scheme);
441c4ea1edbSStephen Warren 	} else {
442c4ea1edbSStephen Warren 		rev_scheme = 0;
443c4ea1edbSStephen Warren 		rev_type = revision & 0xff;
444c4ea1edbSStephen Warren 		models = rpi_models_old_scheme;
445c4ea1edbSStephen Warren 		models_count = ARRAY_SIZE(rpi_models_old_scheme);
44647705effSStephen Warren 	}
447c4ea1edbSStephen Warren 	if (rev_type >= models_count) {
448c4ea1edbSStephen Warren 		printf("RPI: Board rev 0x%x outside known range\n", rev_type);
449c4ea1edbSStephen Warren 		model = &rpi_model_unknown;
450c4ea1edbSStephen Warren 	} else if (!models[rev_type].name) {
451c4ea1edbSStephen Warren 		printf("RPI: Board rev 0x%x unknown\n", rev_type);
452c4ea1edbSStephen Warren 		model = &rpi_model_unknown;
453c4ea1edbSStephen Warren 	} else {
454c4ea1edbSStephen Warren 		model = &models[rev_type];
455914627feSStephen Warren 	}
4569316e144SStephen Warren 
457c4ea1edbSStephen Warren 	printf("RPI %s (0x%x)\n", model->name, revision);
4589316e144SStephen Warren }
4599316e144SStephen Warren 
board_init(void)460d8396a32SFabian Vogt int board_init(void)
461601147b0SAlexander Graf {
46245a6d231SPaolo Pisati #ifdef CONFIG_HW_WATCHDOG
46345a6d231SPaolo Pisati 	hw_watchdog_init();
46445a6d231SPaolo Pisati #endif
465601147b0SAlexander Graf 
466d8396a32SFabian Vogt 	get_board_rev();
467d8396a32SFabian Vogt 
468d8396a32SFabian Vogt 	gd->bd->bi_boot_params = 0x100;
469d8396a32SFabian Vogt 
47070997d88SSimon Glass 	return bcm2835_power_on_module(BCM2835_MBOX_POWER_DEVID_USB_HCD);
471601147b0SAlexander Graf }
472601147b0SAlexander Graf 
47382f766d1SAlex Deymo /*
47482f766d1SAlex Deymo  * If the firmware passed a device tree use it for U-Boot.
47582f766d1SAlex Deymo  */
board_fdt_blob_setup(void)47682f766d1SAlex Deymo void *board_fdt_blob_setup(void)
47782f766d1SAlex Deymo {
47882f766d1SAlex Deymo 	if (fdt_magic(fw_dtb_pointer) != FDT_MAGIC)
47982f766d1SAlex Deymo 		return NULL;
48082f766d1SAlex Deymo 	return (void *)fw_dtb_pointer;
48182f766d1SAlex Deymo }
48282f766d1SAlex Deymo 
ft_board_setup(void * blob,bd_t * bd)4839316e144SStephen Warren int ft_board_setup(void *blob, bd_t *bd)
4849316e144SStephen Warren {
4859316e144SStephen Warren 	/*
4869316e144SStephen Warren 	 * For now, we simply always add the simplefb DT node. Later, we
4879316e144SStephen Warren 	 * should be more intelligent, and e.g. only do this if no enabled DT
4889316e144SStephen Warren 	 * node exists for the "real" graphics driver.
4899316e144SStephen Warren 	 */
4909316e144SStephen Warren 	lcd_dt_simplefb_add_node(blob);
4919316e144SStephen Warren 
4921bcf7a30SAlexander Graf #ifdef CONFIG_EFI_LOADER
4931bcf7a30SAlexander Graf 	/* Reserve the spin table */
4941bcf7a30SAlexander Graf 	efi_add_memory_map(0, 1, EFI_RESERVED_MEMORY_TYPE, 0);
4951bcf7a30SAlexander Graf #endif
4961bcf7a30SAlexander Graf 
4979316e144SStephen Warren 	return 0;
4989316e144SStephen Warren }
499