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