aboutsummaryrefslogtreecommitdiffstats
path: root/roms/u-boot/arch/arm/mach-bcm283x
diff options
context:
space:
mode:
Diffstat (limited to 'roms/u-boot/arch/arm/mach-bcm283x')
-rw-r--r--roms/u-boot/arch/arm/mach-bcm283x/Kconfig215
-rw-r--r--roms/u-boot/arch/arm/mach-bcm283x/Makefile6
-rw-r--r--roms/u-boot/arch/arm/mach-bcm283x/include/mach/base.h19
-rw-r--r--roms/u-boot/arch/arm/mach-bcm283x/include/mach/gpio.h63
-rw-r--r--roms/u-boot/arch/arm/mach-bcm283x/include/mach/mbox.h530
-rw-r--r--roms/u-boot/arch/arm/mach-bcm283x/include/mach/msg.h58
-rw-r--r--roms/u-boot/arch/arm/mach-bcm283x/include/mach/sdhci.h16
-rw-r--r--roms/u-boot/arch/arm/mach-bcm283x/include/mach/timer.h36
-rw-r--r--roms/u-boot/arch/arm/mach-bcm283x/include/mach/wdog.h28
-rw-r--r--roms/u-boot/arch/arm/mach-bcm283x/init.c175
-rw-r--r--roms/u-boot/arch/arm/mach-bcm283x/lowlevel_init.S11
-rw-r--r--roms/u-boot/arch/arm/mach-bcm283x/mbox.c168
-rw-r--r--roms/u-boot/arch/arm/mach-bcm283x/msg.c199
-rw-r--r--roms/u-boot/arch/arm/mach-bcm283x/phys2bus.c21
-rw-r--r--roms/u-boot/arch/arm/mach-bcm283x/reset.c94
15 files changed, 1639 insertions, 0 deletions
diff --git a/roms/u-boot/arch/arm/mach-bcm283x/Kconfig b/roms/u-boot/arch/arm/mach-bcm283x/Kconfig
new file mode 100644
index 000000000..b3287ce8b
--- /dev/null
+++ b/roms/u-boot/arch/arm/mach-bcm283x/Kconfig
@@ -0,0 +1,215 @@
+config BCM2835
+ bool "Broadcom BCM2835 SoC support"
+ depends on ARCH_BCM283X
+ select CPU_ARM1176
+
+config BCM2836
+ bool "Broadcom BCM2836 SoC support"
+ depends on ARCH_BCM283X
+ select ARMV7_LPAE
+ select CPU_V7A
+
+config BCM2837
+ bool "Broadcom BCM2837 SoC support"
+ depends on ARCH_BCM283X
+
+config BCM2837_32B
+ bool "Broadcom BCM2837 SoC 32-bit support"
+ depends on ARCH_BCM283X
+ select BCM2837
+ select ARMV7_LPAE
+ select CPU_V7A
+
+config BCM2837_64B
+ bool "Broadcom BCM2837 SoC 64-bit support"
+ depends on ARCH_BCM283X
+ select BCM2837
+ select ARM64
+
+config BCM2711
+ bool "Broadcom BCM2711 SoC support"
+ depends on ARCH_BCM283X
+
+config BCM2711_32B
+ bool "Broadcom BCM2711 SoC 32-bit support"
+ depends on ARCH_BCM283X
+ select BCM2711
+ select ARMV7_LPAE
+ select CPU_V7A
+ select PHYS_64BIT
+
+config BCM2711_64B
+ bool "Broadcom BCM2711 SoC 64-bit support"
+ depends on ARCH_BCM283X
+ select BCM2711
+ select ARM64
+
+menu "Broadcom BCM283X family"
+ depends on ARCH_BCM283X
+
+choice
+ prompt "Broadcom BCM283X board select"
+ optional
+
+config TARGET_RPI
+ bool "Raspberry Pi (all BCM2835 variants)"
+ help
+ Support for all ARM1176-/BCM2835-based Raspberry Pi variants, such as
+ the A, A+, B, B+, Compute Module, and Zero. This option cannot
+ support BCM2836/BCM2837-based Raspberry Pis such as the RPi 2 and
+ RPi 3 due to different peripheral address maps.
+
+ This option creates a build targeting the ARM1176 ISA.
+ select BCM2835
+
+config TARGET_RPI_0_W
+ bool "Raspberry Pi Zero W"
+ help
+ Support for all ARM1176-/BCM2835-based Raspberry Pi variants, such as
+ the RPi Zero model W.
+
+ This option assumes the VideoCore firmware is configured to use the
+ mini UART (rather than PL011) for the serial console. This is the
+ default on the RPi Zero W. To enable the UART console, the following
+ non-default option must be present in config.txt: enable_uart=1.
+ This is required for U-Boot to operate correctly, even if you only
+ care about the HDMI/usbkbd console.
+
+ This option creates a build targeting the ARMv7/AArch32 ISA.
+ select BCM2835
+
+config TARGET_RPI_2
+ bool "Raspberry Pi 2"
+ help
+ Support for all BCM2836-based Raspberry Pi variants, such as
+ the RPi 2 model B.
+
+ This option also supports BCM2837-based variants such as the RPi 3
+ Model B, when run in 32-bit mode, provided you have configured the
+ VideoCore firmware to select the PL011 UART for the console by:
+ a) config.txt should contain dtoverlay=pi3-miniuart-bt.
+ b) You should run the following to tell the VC FW to process DT when
+ booting, and copy u-boot.bin.img (rather than u-boot.bin) to the SD
+ card as the kernel image:
+
+ path/to/kernel/scripts/mkknlimg --dtok u-boot.bin u-boot.bin.img
+
+ This works as of firmware.git commit 046effa13ebc "firmware:
+ arm_loader: emmc clock depends on core clock See:
+ https://github.com/raspberrypi/firmware/issues/572".
+
+ This option creates a build targeting the ARMv7/AArch32 ISA.
+ select BCM2836
+
+config TARGET_RPI_3_32B
+ bool "Raspberry Pi 3 32-bit build"
+ help
+ Support for all BCM2837-based Raspberry Pi variants, such as
+ the RPi 3 model B, in AArch32 (32-bit) mode.
+
+ This option assumes the VideoCore firmware is configured to use the
+ mini UART (rather than PL011) for the serial console. This is the
+ default on the RPi 3. To enable the UART console, the following non-
+ default option must be present in config.txt: enable_uart=1. This is
+ required for U-Boot to operate correctly, even if you only care
+ about the HDMI/usbkbd console.
+
+ This option creates a build targeting the ARMv7/AArch32 ISA.
+ select BCM2837_32B
+
+config TARGET_RPI_3
+ bool "Raspberry Pi 3 64-bit build"
+ help
+ Support for all BCM2837-based Raspberry Pi variants, such as
+ the RPi 3 model B, in AArch64 (64-bit) mode.
+
+ This option assumes the VideoCore firmware is configured to use the
+ mini UART (rather than PL011) for the serial console. This is the
+ default on the RPi 3. To enable the UART console, the following non-
+ default option must be present in config.txt: enable_uart=1. This is
+ required for U-Boot to operate correctly, even if you only care
+ about the HDMI/usbkbd console.
+
+ At the time of writing, the VC FW requires a non-default option in
+ config.txt to request the ARM CPU boot in 64-bit mode:
+ arm_control=0x200
+
+ The VC FW typically provides ARM "stub" code to set up the CPU and
+ quiesce secondary SMP CPUs. This is not currently true in 64-bit
+ mode. In order to boot U-Boot before the VC FW is enhanced, please
+ see the commit description for the commit which added RPi3 support
+ for a workaround. Since the instructions are temporary, they are not
+ duplicated here. The VC FW enhancement is tracked in
+ https://github.com/raspberrypi/firmware/issues/579.
+
+ This option creates a build targeting the ARMv8/AArch64 ISA.
+ select BCM2837_64B
+
+config TARGET_RPI_4_32B
+ bool "Raspberry Pi 4 32-bit build"
+ help
+ Support for all BCM2711-based Raspberry Pi variants, such as
+ the RPi 4 model B, in AArch32 (32-bit) mode.
+
+ This option assumes the VideoCore firmware is configured to use the
+ mini UART (rather than PL011) for the serial console. This is the
+ default on the RPi 4. To enable the UART console, the following non-
+ default option must be present in config.txt: enable_uart=1. This is
+ required for U-Boot to operate correctly, even if you only care
+ about the HDMI/usbkbd console.
+
+ Due to hardware incompatibilities, this can't be used with
+ BCM283/5/6/7.
+
+ This option creates a build targeting the ARMv7/AArch32 ISA.
+ select BCM2711_32B
+
+config TARGET_RPI_4
+ bool "Raspberry Pi 4 64-bit build"
+ help
+ Support for all BCM2711-based Raspberry Pi variants, such as
+ the RPi 4 model B, in AArch64 (64-bit) mode.
+
+ This option assumes the VideoCore firmware is configured to use the
+ mini UART (rather than PL011) for the serial console. This is the
+ default on the RPi 4. To enable the UART console, the following non-
+ default option must be present in config.txt: enable_uart=1. This is
+ required for U-Boot to operate correctly, even if you only care
+ about the HDMI/usbkbd console.
+
+ Due to hardware incompatibilities, this can't be used with
+ BCM283/5/6/7.
+
+ Also, due to a bug in firmware, switching to 64bit mode doesn't
+ happen automatically based on the kernel's image filename. See
+ https://github.com/raspberrypi/firmware/issues/1193 for more details.
+ Until that is resolved, the configuration (config.txt) needs to
+ explicitly set: arm_64bit=1.
+
+ This option creates a build targeting the ARMv8/AArch64 ISA.
+ select BCM2711_64B
+
+config TARGET_RPI_ARM64
+ bool "Raspberry Pi one binary 64-bit build"
+ help
+ Support for all armv8 based Raspberry Pi variants, such as
+ the RPi 4 model B, in AArch64 (64-bit) mode.
+ select ARM64
+
+endchoice
+
+config SYS_BOARD
+ default "rpi"
+
+config SYS_VENDOR
+ default "raspberrypi"
+
+config SYS_SOC
+ default "bcm283x"
+
+config SYS_CONFIG_NAME
+ default "rpi"
+
+source "board/raspberrypi/rpi/Kconfig"
+
+endmenu
diff --git a/roms/u-boot/arch/arm/mach-bcm283x/Makefile b/roms/u-boot/arch/arm/mach-bcm283x/Makefile
new file mode 100644
index 000000000..7cd068832
--- /dev/null
+++ b/roms/u-boot/arch/arm/mach-bcm283x/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# (C) Copyright 2012 Stephen Warren
+
+obj-$(CONFIG_BCM2835) += lowlevel_init.o
+obj-y += init.o reset.o mbox.o msg.o phys2bus.o
diff --git a/roms/u-boot/arch/arm/mach-bcm283x/include/mach/base.h b/roms/u-boot/arch/arm/mach-bcm283x/include/mach/base.h
new file mode 100644
index 000000000..4ccaf6969
--- /dev/null
+++ b/roms/u-boot/arch/arm/mach-bcm283x/include/mach/base.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * (C) Copyright 2019 Matthias Brugger
+ */
+
+#ifndef _BCM283x_BASE_H_
+#define _BCM283x_BASE_H_
+
+extern unsigned long rpi_bcm283x_base;
+
+#ifdef CONFIG_ARMV7_LPAE
+#ifdef CONFIG_TARGET_RPI_4_32B
+#include <addr_map.h>
+#define phys_to_virt addrmap_phys_to_virt
+#define virt_to_phys addrmap_virt_to_phys
+#endif
+#endif
+
+#endif
diff --git a/roms/u-boot/arch/arm/mach-bcm283x/include/mach/gpio.h b/roms/u-boot/arch/arm/mach-bcm283x/include/mach/gpio.h
new file mode 100644
index 000000000..4aeb48eeb
--- /dev/null
+++ b/roms/u-boot/arch/arm/mach-bcm283x/include/mach/gpio.h
@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2012 Vikram Narayananan
+ * <vikram186@gmail.com>
+ * (C) Copyright 2012,2015 Stephen Warren
+ */
+
+#ifndef _BCM2835_GPIO_H_
+#define _BCM2835_GPIO_H_
+
+#define BCM2835_GPIO_COUNT 54
+
+#define BCM2835_GPIO_FSEL_MASK 0x7
+#define BCM2835_GPIO_INPUT 0x0
+#define BCM2835_GPIO_OUTPUT 0x1
+#define BCM2835_GPIO_ALT0 0x4
+#define BCM2835_GPIO_ALT1 0x5
+#define BCM2835_GPIO_ALT2 0x6
+#define BCM2835_GPIO_ALT3 0x7
+#define BCM2835_GPIO_ALT4 0x3
+#define BCM2835_GPIO_ALT5 0x2
+
+#define BCM2835_GPIO_COMMON_BANK(gpio) ((gpio < 32) ? 0 : 1)
+#define BCM2835_GPIO_COMMON_SHIFT(gpio) (gpio & 0x1f)
+
+#define BCM2835_GPIO_FSEL_BANK(gpio) (gpio / 10)
+#define BCM2835_GPIO_FSEL_SHIFT(gpio) ((gpio % 10) * 3)
+
+struct bcm2835_gpio_regs {
+ u32 gpfsel[6];
+ u32 reserved1;
+ u32 gpset[2];
+ u32 reserved2;
+ u32 gpclr[2];
+ u32 reserved3;
+ u32 gplev[2];
+ u32 reserved4;
+ u32 gpeds[2];
+ u32 reserved5;
+ u32 gpren[2];
+ u32 reserved6;
+ u32 gpfen[2];
+ u32 reserved7;
+ u32 gphen[2];
+ u32 reserved8;
+ u32 gplen[2];
+ u32 reserved9;
+ u32 gparen[2];
+ u32 reserved10;
+ u32 gppud;
+ u32 gppudclk[2];
+};
+
+/**
+ * struct bcm2835_gpio_plat - GPIO platform description
+ *
+ * @base: Base address of GPIO controller
+ */
+struct bcm2835_gpio_plat {
+ unsigned long base;
+};
+
+#endif /* _BCM2835_GPIO_H_ */
diff --git a/roms/u-boot/arch/arm/mach-bcm283x/include/mach/mbox.h b/roms/u-boot/arch/arm/mach-bcm283x/include/mach/mbox.h
new file mode 100644
index 000000000..2ae2d3d97
--- /dev/null
+++ b/roms/u-boot/arch/arm/mach-bcm283x/include/mach/mbox.h
@@ -0,0 +1,530 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2012,2015 Stephen Warren
+ */
+
+#ifndef _BCM2835_MBOX_H
+#define _BCM2835_MBOX_H
+
+#include <linux/compiler.h>
+#include <asm/arch/base.h>
+
+/*
+ * The BCM2835 SoC contains (at least) two CPUs; the VideoCore (a/k/a "GPU")
+ * and the ARM CPU. The ARM CPU is often thought of as the main CPU.
+ * However, the VideoCore actually controls the initial SoC boot, and hides
+ * much of the hardware behind a protocol. This protocol is transported
+ * using the SoC's mailbox hardware module.
+ *
+ * The mailbox hardware supports passing 32-bit values back and forth.
+ * Presumably by software convention of the firmware, the bottom 4 bits of the
+ * value are used to indicate a logical channel, and the upper 28 bits are the
+ * actual payload. Various channels exist using these simple raw messages. See
+ * https://github.com/raspberrypi/firmware/wiki/Mailboxes for a list. As an
+ * example, the messages on the power management channel are a bitmask of
+ * devices whose power should be enabled.
+ *
+ * The property mailbox channel passes messages that contain the (16-byte
+ * aligned) ARM physical address of a memory buffer. This buffer is passed to
+ * the VC for processing, is modified in-place by the VC, and the address then
+ * passed back to the ARM CPU as the response mailbox message to indicate
+ * request completion. The buffers have a generic and extensible format; each
+ * buffer contains a standard header, a list of "tags", and a terminating zero
+ * entry. Each tag contains an ID indicating its type, and length fields for
+ * generic parsing. With some limitations, an arbitrary set of tags may be
+ * combined together into a single message buffer. This file defines structs
+ * representing the header and many individual tag layouts and IDs.
+ */
+
+/* Raw mailbox HW */
+
+#define BCM2835_MBOX_PHYSADDR ({ BUG_ON(!rpi_bcm283x_base); \
+ rpi_bcm283x_base + 0x0000b880; })
+
+struct bcm2835_mbox_regs {
+ u32 read;
+ u32 rsvd0[5];
+ u32 mail0_status;
+ u32 mail0_config;
+ u32 write;
+ u32 rsvd1[5];
+ u32 mail1_status;
+ u32 mail1_config;
+};
+
+#define BCM2835_MBOX_STATUS_WR_FULL 0x80000000
+#define BCM2835_MBOX_STATUS_RD_EMPTY 0x40000000
+
+/* Lower 4-bits are channel ID */
+#define BCM2835_CHAN_MASK 0xf
+#define BCM2835_MBOX_PACK(chan, data) (((data) & (~BCM2835_CHAN_MASK)) | \
+ (chan & BCM2835_CHAN_MASK))
+#define BCM2835_MBOX_UNPACK_CHAN(val) ((val) & BCM2835_CHAN_MASK)
+#define BCM2835_MBOX_UNPACK_DATA(val) ((val) & (~BCM2835_CHAN_MASK))
+
+/* Property mailbox buffer structures */
+
+#define BCM2835_MBOX_PROP_CHAN 8
+
+/* All message buffers must start with this header */
+struct bcm2835_mbox_hdr {
+ u32 buf_size;
+ u32 code;
+};
+
+#define BCM2835_MBOX_REQ_CODE 0
+#define BCM2835_MBOX_RESP_CODE_SUCCESS 0x80000000
+
+#define BCM2835_MBOX_INIT_HDR(_m_) { \
+ memset((_m_), 0, sizeof(*(_m_))); \
+ (_m_)->hdr.buf_size = sizeof(*(_m_)); \
+ (_m_)->hdr.code = 0; \
+ (_m_)->end_tag = 0; \
+ }
+
+/*
+ * A message buffer contains a list of tags. Each tag must also start with
+ * a standardized header.
+ */
+struct bcm2835_mbox_tag_hdr {
+ u32 tag;
+ u32 val_buf_size;
+ u32 val_len;
+};
+
+#define BCM2835_MBOX_INIT_TAG(_t_, _id_) { \
+ (_t_)->tag_hdr.tag = BCM2835_MBOX_TAG_##_id_; \
+ (_t_)->tag_hdr.val_buf_size = sizeof((_t_)->body); \
+ (_t_)->tag_hdr.val_len = sizeof((_t_)->body.req); \
+ }
+
+#define BCM2835_MBOX_INIT_TAG_NO_REQ(_t_, _id_) { \
+ (_t_)->tag_hdr.tag = BCM2835_MBOX_TAG_##_id_; \
+ (_t_)->tag_hdr.val_buf_size = sizeof((_t_)->body); \
+ (_t_)->tag_hdr.val_len = 0; \
+ }
+
+/* When responding, the VC sets this bit in val_len to indicate a response */
+#define BCM2835_MBOX_TAG_VAL_LEN_RESPONSE 0x80000000
+
+/*
+ * Below we define the ID and struct for many possible tags. This header only
+ * defines individual tag structs, not entire message structs, since in
+ * general an arbitrary set of tags may be combined into a single message.
+ * Clients of the mbox API are expected to define their own overall message
+ * structures by combining the header, a set of tags, and a terminating
+ * entry. For example,
+ *
+ * struct msg {
+ * struct bcm2835_mbox_hdr hdr;
+ * struct bcm2835_mbox_tag_get_arm_mem get_arm_mem;
+ * ... perhaps other tags here ...
+ * u32 end_tag;
+ * };
+ */
+
+#define BCM2835_MBOX_TAG_GET_BOARD_REV 0x00010002
+
+struct bcm2835_mbox_tag_get_board_rev {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ } req;
+ struct {
+ u32 rev;
+ } resp;
+ } body;
+};
+
+#define BCM2835_MBOX_TAG_GET_MAC_ADDRESS 0x00010003
+
+struct bcm2835_mbox_tag_get_mac_address {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ } req;
+ struct {
+ u8 mac[6];
+ u8 pad[2];
+ } resp;
+ } body;
+};
+
+#define BCM2835_MBOX_TAG_GET_BOARD_SERIAL 0x00010004
+
+struct bcm2835_mbox_tag_get_board_serial {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct __packed {
+ u64 serial;
+ } resp;
+ } body;
+};
+
+#define BCM2835_MBOX_TAG_GET_ARM_MEMORY 0x00010005
+
+struct bcm2835_mbox_tag_get_arm_mem {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ } req;
+ struct {
+ u32 mem_base;
+ u32 mem_size;
+ } resp;
+ } body;
+};
+
+#define BCM2835_MBOX_POWER_DEVID_SDHCI 0
+#define BCM2835_MBOX_POWER_DEVID_UART0 1
+#define BCM2835_MBOX_POWER_DEVID_UART1 2
+#define BCM2835_MBOX_POWER_DEVID_USB_HCD 3
+#define BCM2835_MBOX_POWER_DEVID_I2C0 4
+#define BCM2835_MBOX_POWER_DEVID_I2C1 5
+#define BCM2835_MBOX_POWER_DEVID_I2C2 6
+#define BCM2835_MBOX_POWER_DEVID_SPI 7
+#define BCM2835_MBOX_POWER_DEVID_CCP2TX 8
+
+#define BCM2835_MBOX_POWER_STATE_RESP_ON (1 << 0)
+/* Device doesn't exist */
+#define BCM2835_MBOX_POWER_STATE_RESP_NODEV (1 << 1)
+
+#define BCM2835_MBOX_TAG_GET_POWER_STATE 0x00020001
+
+struct bcm2835_mbox_tag_get_power_state {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ u32 device_id;
+ } req;
+ struct {
+ u32 device_id;
+ u32 state;
+ } resp;
+ } body;
+};
+
+#define BCM2835_MBOX_TAG_SET_POWER_STATE 0x00028001
+
+#define BCM2835_MBOX_SET_POWER_STATE_REQ_ON (1 << 0)
+#define BCM2835_MBOX_SET_POWER_STATE_REQ_WAIT (1 << 1)
+
+struct bcm2835_mbox_tag_set_power_state {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ u32 device_id;
+ u32 state;
+ } req;
+ struct {
+ u32 device_id;
+ u32 state;
+ } resp;
+ } body;
+};
+
+#define BCM2835_MBOX_TAG_GET_CLOCK_RATE 0x00030002
+
+#define BCM2835_MBOX_CLOCK_ID_EMMC 1
+#define BCM2835_MBOX_CLOCK_ID_UART 2
+#define BCM2835_MBOX_CLOCK_ID_ARM 3
+#define BCM2835_MBOX_CLOCK_ID_CORE 4
+#define BCM2835_MBOX_CLOCK_ID_V3D 5
+#define BCM2835_MBOX_CLOCK_ID_H264 6
+#define BCM2835_MBOX_CLOCK_ID_ISP 7
+#define BCM2835_MBOX_CLOCK_ID_SDRAM 8
+#define BCM2835_MBOX_CLOCK_ID_PIXEL 9
+#define BCM2835_MBOX_CLOCK_ID_PWM 10
+#define BCM2835_MBOX_CLOCK_ID_EMMC2 12
+
+struct bcm2835_mbox_tag_get_clock_rate {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ u32 clock_id;
+ } req;
+ struct {
+ u32 clock_id;
+ u32 rate_hz;
+ } resp;
+ } body;
+};
+
+#define BCM2835_MBOX_TAG_ALLOCATE_BUFFER 0x00040001
+
+struct bcm2835_mbox_tag_allocate_buffer {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ u32 alignment;
+ } req;
+ struct {
+ u32 fb_address;
+ u32 fb_size;
+ } resp;
+ } body;
+};
+
+#define BCM2835_MBOX_TAG_RELEASE_BUFFER 0x00048001
+
+struct bcm2835_mbox_tag_release_buffer {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ } req;
+ struct {
+ } resp;
+ } body;
+};
+
+#define BCM2835_MBOX_TAG_BLANK_SCREEN 0x00040002
+
+struct bcm2835_mbox_tag_blank_screen {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ /* bit 0 means on, other bots reserved */
+ u32 state;
+ } req;
+ struct {
+ u32 state;
+ } resp;
+ } body;
+};
+
+/* Physical means output signal */
+#define BCM2835_MBOX_TAG_GET_PHYSICAL_W_H 0x00040003
+#define BCM2835_MBOX_TAG_TEST_PHYSICAL_W_H 0x00044003
+#define BCM2835_MBOX_TAG_SET_PHYSICAL_W_H 0x00048003
+
+struct bcm2835_mbox_tag_physical_w_h {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ /* req not used for get */
+ struct {
+ u32 width;
+ u32 height;
+ } req;
+ struct {
+ u32 width;
+ u32 height;
+ } resp;
+ } body;
+};
+
+/* Virtual means display buffer */
+#define BCM2835_MBOX_TAG_GET_VIRTUAL_W_H 0x00040004
+#define BCM2835_MBOX_TAG_TEST_VIRTUAL_W_H 0x00044004
+#define BCM2835_MBOX_TAG_SET_VIRTUAL_W_H 0x00048004
+
+struct bcm2835_mbox_tag_virtual_w_h {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ /* req not used for get */
+ struct {
+ u32 width;
+ u32 height;
+ } req;
+ struct {
+ u32 width;
+ u32 height;
+ } resp;
+ } body;
+};
+
+#define BCM2835_MBOX_TAG_GET_DEPTH 0x00040005
+#define BCM2835_MBOX_TAG_TEST_DEPTH 0x00044005
+#define BCM2835_MBOX_TAG_SET_DEPTH 0x00048005
+
+struct bcm2835_mbox_tag_depth {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ /* req not used for get */
+ struct {
+ u32 bpp;
+ } req;
+ struct {
+ u32 bpp;
+ } resp;
+ } body;
+};
+
+#define BCM2835_MBOX_TAG_GET_PIXEL_ORDER 0x00040006
+#define BCM2835_MBOX_TAG_TEST_PIXEL_ORDER 0x00044006
+#define BCM2835_MBOX_TAG_SET_PIXEL_ORDER 0x00048006
+
+#define BCM2835_MBOX_PIXEL_ORDER_BGR 0
+#define BCM2835_MBOX_PIXEL_ORDER_RGB 1
+
+struct bcm2835_mbox_tag_pixel_order {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ /* req not used for get */
+ struct {
+ u32 order;
+ } req;
+ struct {
+ u32 order;
+ } resp;
+ } body;
+};
+
+#define BCM2835_MBOX_TAG_GET_ALPHA_MODE 0x00040007
+#define BCM2835_MBOX_TAG_TEST_ALPHA_MODE 0x00044007
+#define BCM2835_MBOX_TAG_SET_ALPHA_MODE 0x00048007
+
+#define BCM2835_MBOX_ALPHA_MODE_0_OPAQUE 0
+#define BCM2835_MBOX_ALPHA_MODE_0_TRANSPARENT 1
+#define BCM2835_MBOX_ALPHA_MODE_IGNORED 2
+
+struct bcm2835_mbox_tag_alpha_mode {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ /* req not used for get */
+ struct {
+ u32 alpha;
+ } req;
+ struct {
+ u32 alpha;
+ } resp;
+ } body;
+};
+
+#define BCM2835_MBOX_TAG_GET_PITCH 0x00040008
+
+struct bcm2835_mbox_tag_pitch {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ } req;
+ struct {
+ u32 pitch;
+ } resp;
+ } body;
+};
+
+/* Offset of display window within buffer */
+#define BCM2835_MBOX_TAG_GET_VIRTUAL_OFFSET 0x00040009
+#define BCM2835_MBOX_TAG_TEST_VIRTUAL_OFFSET 0x00044009
+#define BCM2835_MBOX_TAG_SET_VIRTUAL_OFFSET 0x00048009
+
+struct bcm2835_mbox_tag_virtual_offset {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ /* req not used for get */
+ struct {
+ u32 x;
+ u32 y;
+ } req;
+ struct {
+ u32 x;
+ u32 y;
+ } resp;
+ } body;
+};
+
+#define BCM2835_MBOX_TAG_GET_OVERSCAN 0x0004000a
+#define BCM2835_MBOX_TAG_TEST_OVERSCAN 0x0004400a
+#define BCM2835_MBOX_TAG_SET_OVERSCAN 0x0004800a
+
+struct bcm2835_mbox_tag_overscan {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ /* req not used for get */
+ struct {
+ u32 top;
+ u32 bottom;
+ u32 left;
+ u32 right;
+ } req;
+ struct {
+ u32 top;
+ u32 bottom;
+ u32 left;
+ u32 right;
+ } resp;
+ } body;
+};
+
+#define BCM2835_MBOX_TAG_GET_PALETTE 0x0004000b
+
+struct bcm2835_mbox_tag_get_palette {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ } req;
+ struct {
+ u32 data[1024];
+ } resp;
+ } body;
+};
+
+#define BCM2835_MBOX_TAG_TEST_PALETTE 0x0004400b
+
+struct bcm2835_mbox_tag_test_palette {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ u32 offset;
+ u32 num_entries;
+ u32 data[256];
+ } req;
+ struct {
+ u32 is_invalid;
+ } resp;
+ } body;
+};
+
+#define BCM2835_MBOX_TAG_SET_PALETTE 0x0004800b
+
+struct bcm2835_mbox_tag_set_palette {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ u32 offset;
+ u32 num_entries;
+ u32 data[256];
+ } req;
+ struct {
+ u32 is_invalid;
+ } resp;
+ } body;
+};
+
+#define BCM2835_MBOX_TAG_NOTIFY_XHCI_RESET 0x00030058
+
+struct bcm2835_mbox_tag_pci_dev_addr {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ u32 dev_addr;
+ } req;
+ struct {
+ } resp;
+ } body;
+};
+
+/*
+ * Pass a raw u32 message to the VC, and receive a raw u32 back.
+ *
+ * Returns 0 for success, any other value for error.
+ */
+int bcm2835_mbox_call_raw(u32 chan, u32 send, u32 *recv);
+
+/*
+ * Pass a complete property-style buffer to the VC, and wait until it has
+ * been processed.
+ *
+ * This function expects a pointer to the mbox_hdr structure in an attempt
+ * to ensure some degree of type safety. However, some number of tags and
+ * a termination value are expected to immediately follow the header in
+ * memory, as required by the property protocol.
+ *
+ * Each struct bcm2835_mbox_hdr passed must be allocated with
+ * ALLOC_CACHE_ALIGN_BUFFER(x, y, z) to ensure proper cache flush/invalidate.
+ *
+ * Returns 0 for success, any other value for error.
+ */
+int bcm2835_mbox_call_prop(u32 chan, struct bcm2835_mbox_hdr *buffer);
+
+#endif
diff --git a/roms/u-boot/arch/arm/mach-bcm283x/include/mach/msg.h b/roms/u-boot/arch/arm/mach-bcm283x/include/mach/msg.h
new file mode 100644
index 000000000..e45c1bf01
--- /dev/null
+++ b/roms/u-boot/arch/arm/mach-bcm283x/include/mach/msg.h
@@ -0,0 +1,58 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2012,2015 Stephen Warren
+ */
+
+#ifndef _BCM2835_MSG_H
+#define _BCM2835_MSG_H
+
+/**
+ * bcm2835_power_on_module() - power on an SoC module
+ *
+ * @module: ID of module to power on (BCM2835_MBOX_POWER_DEVID_...)
+ * @return 0 if OK, -EIO on error
+ */
+int bcm2835_power_on_module(u32 module);
+
+/**
+ * bcm2835_get_mmc_clock() - get the frequency of the MMC clock
+ *
+ * @clock_id: ID of clock to get frequency for
+ * @return clock frequency, or -ve on error
+ */
+int bcm2835_get_mmc_clock(u32 clock_id);
+
+/**
+ * bcm2835_get_video_size() - get the current display size
+ *
+ * @widthp: Returns the width in pixels
+ * @heightp: Returns the height in pixels
+ * @return 0 if OK, -ve on error
+ */
+int bcm2835_get_video_size(int *widthp, int *heightp);
+
+/**
+ * bcm2835_set_video_params() - set the video parameters
+ *
+ * @widthp: Video width to request (returns the actual width selected)
+ * @heightp: Video height to request (returns the actual height selected)
+ * @depth_bpp: Requested bit depth
+ * @pixel_order: Pixel order to use (BCM2835_MBOX_PIXEL_ORDER_...)
+ * @alpha_mode: Alpha transparency mode to use (BCM2835_MBOX_ALPHA_MODE_...)
+ * @fb_basep: Returns base address of frame buffer
+ * @fb_sizep: Returns size of frame buffer
+ * @pitchp: Returns number of bytes in each frame buffer line
+ * @return 0 if OK, -ve on error
+ */
+int bcm2835_set_video_params(int *widthp, int *heightp, int depth_bpp,
+ int pixel_order, int alpha_mode, ulong *fb_basep,
+ ulong *fb_sizep, int *pitchp);
+
+/**
+ * bcm2711_load_vl805_firmware() - get vl805's firmware loaded
+ *
+ * @return 0 if OK, -EIO on error
+ */
+int bcm2711_notify_vl805_reset(void);
+
+#endif
diff --git a/roms/u-boot/arch/arm/mach-bcm283x/include/mach/sdhci.h b/roms/u-boot/arch/arm/mach-bcm283x/include/mach/sdhci.h
new file mode 100644
index 000000000..732369068
--- /dev/null
+++ b/roms/u-boot/arch/arm/mach-bcm283x/include/mach/sdhci.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * (C) Copyright 2012,2015 Stephen Warren
+ */
+
+#ifndef _BCM2835_SDHCI_H_
+#define _BCM2835_SDHCI_H_
+
+#include <asm/arch/base.h>
+
+#define BCM2835_SDHCI_PHYSADDR ({ BUG_ON(!rpi_bcm283x_base); \
+ rpi_bcm283x_base + 0x00300000; })
+
+int bcm2835_sdhci_init(u32 regbase, u32 emmc_freq);
+
+#endif
diff --git a/roms/u-boot/arch/arm/mach-bcm283x/include/mach/timer.h b/roms/u-boot/arch/arm/mach-bcm283x/include/mach/timer.h
new file mode 100644
index 000000000..5567dbd7f
--- /dev/null
+++ b/roms/u-boot/arch/arm/mach-bcm283x/include/mach/timer.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * (C) Copyright 2012,2015 Stephen Warren
+ */
+
+#ifndef _BCM2835_TIMER_H
+#define _BCM2835_TIMER_H
+
+#ifndef __ASSEMBLY__
+#include <asm/arch/base.h>
+#include <linux/bug.h>
+#endif
+
+#define BCM2835_TIMER_PHYSADDR ({ BUG_ON(!rpi_bcm283x_base); \
+ rpi_bcm283x_base + 0x00003000; })
+
+#define BCM2835_TIMER_CS_M3 (1 << 3)
+#define BCM2835_TIMER_CS_M2 (1 << 2)
+#define BCM2835_TIMER_CS_M1 (1 << 1)
+#define BCM2835_TIMER_CS_M0 (1 << 0)
+
+#ifndef __ASSEMBLY__
+#include <linux/types.h>
+
+struct bcm2835_timer_regs {
+ u32 cs;
+ u32 clo;
+ u32 chi;
+ u32 c0;
+ u32 c1;
+ u32 c2;
+ u32 c3;
+};
+#endif
+
+#endif
diff --git a/roms/u-boot/arch/arm/mach-bcm283x/include/mach/wdog.h b/roms/u-boot/arch/arm/mach-bcm283x/include/mach/wdog.h
new file mode 100644
index 000000000..994266672
--- /dev/null
+++ b/roms/u-boot/arch/arm/mach-bcm283x/include/mach/wdog.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * (C) Copyright 2012,2015 Stephen Warren
+ */
+
+#ifndef _BCM2835_WDOG_H
+#define _BCM2835_WDOG_H
+
+#include <asm/arch/base.h>
+
+#define BCM2835_WDOG_PHYSADDR ({ BUG_ON(!rpi_bcm283x_base); \
+ rpi_bcm283x_base + 0x00100000; })
+
+struct bcm2835_wdog_regs {
+ u32 unknown0[7];
+ u32 rstc;
+ u32 rsts;
+ u32 wdog;
+};
+
+#define BCM2835_WDOG_PASSWORD 0x5a000000
+
+#define BCM2835_WDOG_RSTC_WRCFG_MASK 0x00000030
+#define BCM2835_WDOG_RSTC_WRCFG_FULL_RESET 0x00000020
+
+#define BCM2835_WDOG_WDOG_TIMEOUT_MASK 0x0000ffff
+
+#endif
diff --git a/roms/u-boot/arch/arm/mach-bcm283x/init.c b/roms/u-boot/arch/arm/mach-bcm283x/init.c
new file mode 100644
index 000000000..49027ce0a
--- /dev/null
+++ b/roms/u-boot/arch/arm/mach-bcm283x/init.c
@@ -0,0 +1,175 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) Copyright 2012 Stephen Warren
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ */
+
+#include <common.h>
+#include <cpu_func.h>
+#include <init.h>
+#include <dm/device.h>
+#include <fdt_support.h>
+#include <asm/global_data.h>
+
+#define BCM2711_RPI4_PCIE_XHCI_MMIO_PHYS 0x600000000UL
+#define BCM2711_RPI4_PCIE_XHCI_MMIO_SIZE 0x800000UL
+
+#ifdef CONFIG_ARM64
+#include <asm/armv8/mmu.h>
+
+#define MEM_MAP_MAX_ENTRIES (4)
+
+static struct mm_region bcm283x_mem_map[MEM_MAP_MAX_ENTRIES] = {
+ {
+ .virt = 0x00000000UL,
+ .phys = 0x00000000UL,
+ .size = 0x3f000000UL,
+ .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+ PTE_BLOCK_INNER_SHARE
+ }, {
+ .virt = 0x3f000000UL,
+ .phys = 0x3f000000UL,
+ .size = 0x01000000UL,
+ .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+ PTE_BLOCK_NON_SHARE |
+ PTE_BLOCK_PXN | PTE_BLOCK_UXN
+ }, {
+ /* List terminator */
+ 0,
+ }
+};
+
+static struct mm_region bcm2711_mem_map[MEM_MAP_MAX_ENTRIES] = {
+ {
+ .virt = 0x00000000UL,
+ .phys = 0x00000000UL,
+ .size = 0xfc000000UL,
+ .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+ PTE_BLOCK_INNER_SHARE
+ }, {
+ .virt = 0xfc000000UL,
+ .phys = 0xfc000000UL,
+ .size = 0x03800000UL,
+ .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+ PTE_BLOCK_NON_SHARE |
+ PTE_BLOCK_PXN | PTE_BLOCK_UXN
+ }, {
+ .virt = BCM2711_RPI4_PCIE_XHCI_MMIO_PHYS,
+ .phys = BCM2711_RPI4_PCIE_XHCI_MMIO_PHYS,
+ .size = BCM2711_RPI4_PCIE_XHCI_MMIO_SIZE,
+ .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+ PTE_BLOCK_NON_SHARE |
+ PTE_BLOCK_PXN | PTE_BLOCK_UXN
+ }, {
+ /* List terminator */
+ 0,
+ }
+};
+
+struct mm_region *mem_map = bcm283x_mem_map;
+
+/*
+ * I/O address space varies on different chip versions.
+ * We set the base address by inspecting the DTB.
+ */
+static const struct udevice_id board_ids[] = {
+ { .compatible = "brcm,bcm2837", .data = (ulong)&bcm283x_mem_map},
+ { .compatible = "brcm,bcm2838", .data = (ulong)&bcm2711_mem_map},
+ { .compatible = "brcm,bcm2711", .data = (ulong)&bcm2711_mem_map},
+ { },
+};
+
+static void _rpi_update_mem_map(struct mm_region *pd)
+{
+ int i;
+
+ for (i = 0; i < MEM_MAP_MAX_ENTRIES; i++) {
+ mem_map[i].virt = pd[i].virt;
+ mem_map[i].phys = pd[i].phys;
+ mem_map[i].size = pd[i].size;
+ mem_map[i].attrs = pd[i].attrs;
+ }
+}
+
+static void rpi_update_mem_map(void)
+{
+ int ret;
+ struct mm_region *mm;
+ const struct udevice_id *of_match = board_ids;
+
+ while (of_match->compatible) {
+ ret = fdt_node_check_compatible(gd->fdt_blob, 0,
+ of_match->compatible);
+ if (!ret) {
+ mm = (struct mm_region *)of_match->data;
+ _rpi_update_mem_map(mm);
+ break;
+ }
+
+ of_match++;
+ }
+}
+#else
+static void rpi_update_mem_map(void) {}
+#endif
+
+unsigned long rpi_bcm283x_base = 0x3f000000;
+
+int arch_cpu_init(void)
+{
+ icache_enable();
+
+ return 0;
+}
+
+int mach_cpu_init(void)
+{
+ int ret, soc_offset;
+ u64 io_base, size;
+
+ rpi_update_mem_map();
+
+ /* Get IO base from device tree */
+ soc_offset = fdt_path_offset(gd->fdt_blob, "/soc");
+ if (soc_offset < 0)
+ return soc_offset;
+
+ ret = fdt_read_range((void *)gd->fdt_blob, soc_offset, 0, NULL,
+ &io_base, &size);
+ if (ret)
+ return ret;
+
+ rpi_bcm283x_base = io_base;
+
+ return 0;
+}
+
+#ifdef CONFIG_ARMV7_LPAE
+#ifdef CONFIG_TARGET_RPI_4_32B
+#define BCM2711_RPI4_PCIE_XHCI_MMIO_VIRT 0xff800000UL
+#include <addr_map.h>
+#include <asm/system.h>
+
+void init_addr_map(void)
+{
+ mmu_set_region_dcache_behaviour_phys(BCM2711_RPI4_PCIE_XHCI_MMIO_VIRT,
+ BCM2711_RPI4_PCIE_XHCI_MMIO_PHYS,
+ BCM2711_RPI4_PCIE_XHCI_MMIO_SIZE,
+ DCACHE_OFF);
+
+ /* identity mapping for 0..BCM2711_RPI4_PCIE_XHCI_MMIO_VIRT */
+ addrmap_set_entry(0, 0, BCM2711_RPI4_PCIE_XHCI_MMIO_VIRT, 0);
+ /* XHCI MMIO on PCIe at BCM2711_RPI4_PCIE_XHCI_MMIO_VIRT */
+ addrmap_set_entry(BCM2711_RPI4_PCIE_XHCI_MMIO_VIRT,
+ BCM2711_RPI4_PCIE_XHCI_MMIO_PHYS,
+ BCM2711_RPI4_PCIE_XHCI_MMIO_SIZE, 1);
+}
+#endif
+
+void enable_caches(void)
+{
+ dcache_enable();
+}
+#endif
diff --git a/roms/u-boot/arch/arm/mach-bcm283x/lowlevel_init.S b/roms/u-boot/arch/arm/mach-bcm283x/lowlevel_init.S
new file mode 100644
index 000000000..d29ff137e
--- /dev/null
+++ b/roms/u-boot/arch/arm/mach-bcm283x/lowlevel_init.S
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * (C) Copyright 2012 Stephen Warren
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ */
+
+.globl lowlevel_init
+lowlevel_init:
+ mov pc, lr
diff --git a/roms/u-boot/arch/arm/mach-bcm283x/mbox.c b/roms/u-boot/arch/arm/mach-bcm283x/mbox.c
new file mode 100644
index 000000000..da9faafe1
--- /dev/null
+++ b/roms/u-boot/arch/arm/mach-bcm283x/mbox.c
@@ -0,0 +1,168 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2012 Stephen Warren
+ */
+
+#include <common.h>
+#include <cpu_func.h>
+#include <log.h>
+#include <asm/cache.h>
+#include <asm/io.h>
+#include <asm/arch/base.h>
+#include <asm/arch/mbox.h>
+#include <phys2bus.h>
+
+#define TIMEOUT 1000 /* ms */
+
+int bcm2835_mbox_call_raw(u32 chan, u32 send, u32 *recv)
+{
+ struct bcm2835_mbox_regs *regs =
+ (struct bcm2835_mbox_regs *)BCM2835_MBOX_PHYSADDR;
+ ulong endtime = get_timer(0) + TIMEOUT;
+ u32 val;
+
+ debug("time: %lu timeout: %lu\n", get_timer(0), endtime);
+
+ if (send & BCM2835_CHAN_MASK) {
+ printf("mbox: Illegal mbox data 0x%08x\n", send);
+ return -1;
+ }
+
+ /* Drain any stale responses */
+
+ for (;;) {
+ val = readl(&regs->mail0_status);
+ if (val & BCM2835_MBOX_STATUS_RD_EMPTY)
+ break;
+ if (get_timer(0) >= endtime) {
+ printf("mbox: Timeout draining stale responses\n");
+ return -1;
+ }
+ val = readl(&regs->read);
+ }
+
+ /* Wait for space to send */
+
+ for (;;) {
+ val = readl(&regs->mail1_status);
+ if (!(val & BCM2835_MBOX_STATUS_WR_FULL))
+ break;
+ if (get_timer(0) >= endtime) {
+ printf("mbox: Timeout waiting for send space\n");
+ return -1;
+ }
+ }
+
+ /* Send the request */
+
+ val = BCM2835_MBOX_PACK(chan, send);
+ debug("mbox: TX raw: 0x%08x\n", val);
+ writel(val, &regs->write);
+
+ /* Wait for the response */
+
+ for (;;) {
+ val = readl(&regs->mail0_status);
+ if (!(val & BCM2835_MBOX_STATUS_RD_EMPTY))
+ break;
+ if (get_timer(0) >= endtime) {
+ printf("mbox: Timeout waiting for response\n");
+ return -1;
+ }
+ }
+
+ /* Read the response */
+
+ val = readl(&regs->read);
+ debug("mbox: RX raw: 0x%08x\n", val);
+
+ /* Validate the response */
+
+ if (BCM2835_MBOX_UNPACK_CHAN(val) != chan) {
+ printf("mbox: Response channel mismatch\n");
+ return -1;
+ }
+
+ *recv = BCM2835_MBOX_UNPACK_DATA(val);
+
+ return 0;
+}
+
+#ifdef DEBUG
+void dump_buf(struct bcm2835_mbox_hdr *buffer)
+{
+ u32 *p;
+ u32 words;
+ int i;
+
+ p = (u32 *)buffer;
+ words = buffer->buf_size / 4;
+ for (i = 0; i < words; i++)
+ printf(" 0x%04x: 0x%08x\n", i * 4, p[i]);
+}
+#endif
+
+int bcm2835_mbox_call_prop(u32 chan, struct bcm2835_mbox_hdr *buffer)
+{
+ int ret;
+ u32 rbuffer;
+ struct bcm2835_mbox_tag_hdr *tag;
+ int tag_index;
+
+#ifdef DEBUG
+ printf("mbox: TX buffer\n");
+ dump_buf(buffer);
+#endif
+
+ flush_dcache_range((unsigned long)buffer,
+ (unsigned long)((void *)buffer +
+ roundup(buffer->buf_size, ARCH_DMA_MINALIGN)));
+
+ ret = bcm2835_mbox_call_raw(chan,
+ phys_to_bus((unsigned long)buffer),
+ &rbuffer);
+ if (ret)
+ return ret;
+
+ invalidate_dcache_range((unsigned long)buffer,
+ (unsigned long)((void *)buffer +
+ roundup(buffer->buf_size, ARCH_DMA_MINALIGN)));
+
+ if (rbuffer != phys_to_bus((unsigned long)buffer)) {
+ printf("mbox: Response buffer mismatch\n");
+ return -1;
+ }
+
+#ifdef DEBUG
+ printf("mbox: RX buffer\n");
+ dump_buf(buffer);
+#endif
+
+ /* Validate overall response status */
+
+ if (buffer->code != BCM2835_MBOX_RESP_CODE_SUCCESS) {
+ printf("mbox: Header response code invalid\n");
+ return -1;
+ }
+
+ /* Validate each tag's response status */
+
+ tag = (void *)(buffer + 1);
+ tag_index = 0;
+ while (tag->tag) {
+ if (!(tag->val_len & BCM2835_MBOX_TAG_VAL_LEN_RESPONSE)) {
+ printf("mbox: Tag %d missing val_len response bit\n",
+ tag_index);
+ return -1;
+ }
+ /*
+ * Clear the reponse bit so clients can just look right at the
+ * length field without extra processing
+ */
+ tag->val_len &= ~BCM2835_MBOX_TAG_VAL_LEN_RESPONSE;
+ tag = (void *)(((u8 *)tag) + sizeof(*tag) + tag->val_buf_size);
+ tag_index++;
+ }
+
+ return 0;
+}
diff --git a/roms/u-boot/arch/arm/mach-bcm283x/msg.c b/roms/u-boot/arch/arm/mach-bcm283x/msg.c
new file mode 100644
index 000000000..347aece3c
--- /dev/null
+++ b/roms/u-boot/arch/arm/mach-bcm283x/msg.c
@@ -0,0 +1,199 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2012 Stephen Warren
+ */
+
+#include <common.h>
+#include <memalign.h>
+#include <phys2bus.h>
+#include <asm/arch/mbox.h>
+#include <linux/delay.h>
+
+struct msg_set_power_state {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_set_power_state set_power_state;
+ u32 end_tag;
+};
+
+struct msg_get_clock_rate {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_get_clock_rate get_clock_rate;
+ u32 end_tag;
+};
+
+struct msg_query {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_physical_w_h physical_w_h;
+ u32 end_tag;
+};
+
+struct msg_setup {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_physical_w_h physical_w_h;
+ struct bcm2835_mbox_tag_virtual_w_h virtual_w_h;
+ struct bcm2835_mbox_tag_depth depth;
+ struct bcm2835_mbox_tag_pixel_order pixel_order;
+ struct bcm2835_mbox_tag_alpha_mode alpha_mode;
+ struct bcm2835_mbox_tag_virtual_offset virtual_offset;
+ struct bcm2835_mbox_tag_overscan overscan;
+ struct bcm2835_mbox_tag_allocate_buffer allocate_buffer;
+ struct bcm2835_mbox_tag_pitch pitch;
+ u32 end_tag;
+};
+
+struct msg_notify_vl805_reset {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_pci_dev_addr dev_addr;
+ u32 end_tag;
+};
+
+int bcm2835_power_on_module(u32 module)
+{
+ ALLOC_CACHE_ALIGN_BUFFER(struct msg_set_power_state, msg_pwr, 1);
+ int ret;
+
+ BCM2835_MBOX_INIT_HDR(msg_pwr);
+ BCM2835_MBOX_INIT_TAG(&msg_pwr->set_power_state,
+ SET_POWER_STATE);
+ msg_pwr->set_power_state.body.req.device_id = module;
+ msg_pwr->set_power_state.body.req.state =
+ BCM2835_MBOX_SET_POWER_STATE_REQ_ON |
+ BCM2835_MBOX_SET_POWER_STATE_REQ_WAIT;
+
+ ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN,
+ &msg_pwr->hdr);
+ if (ret) {
+ printf("bcm2835: Could not set module %u power state\n",
+ module);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+int bcm2835_get_mmc_clock(u32 clock_id)
+{
+ ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_clock_rate, msg_clk, 1);
+ int ret;
+
+ ret = bcm2835_power_on_module(BCM2835_MBOX_POWER_DEVID_SDHCI);
+ if (ret)
+ return ret;
+
+ BCM2835_MBOX_INIT_HDR(msg_clk);
+ BCM2835_MBOX_INIT_TAG(&msg_clk->get_clock_rate, GET_CLOCK_RATE);
+ msg_clk->get_clock_rate.body.req.clock_id = clock_id;
+
+ ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg_clk->hdr);
+ if (ret) {
+ printf("bcm2835: Could not query eMMC clock rate\n");
+ return -EIO;
+ }
+
+ return msg_clk->get_clock_rate.body.resp.rate_hz;
+}
+
+int bcm2835_get_video_size(int *widthp, int *heightp)
+{
+ ALLOC_CACHE_ALIGN_BUFFER(struct msg_query, msg_query, 1);
+ int ret;
+
+ BCM2835_MBOX_INIT_HDR(msg_query);
+ BCM2835_MBOX_INIT_TAG_NO_REQ(&msg_query->physical_w_h,
+ GET_PHYSICAL_W_H);
+ ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg_query->hdr);
+ if (ret) {
+ printf("bcm2835: Could not query display resolution\n");
+ return ret;
+ }
+ *widthp = msg_query->physical_w_h.body.resp.width;
+ *heightp = msg_query->physical_w_h.body.resp.height;
+
+ return 0;
+}
+
+int bcm2835_set_video_params(int *widthp, int *heightp, int depth_bpp,
+ int pixel_order, int alpha_mode, ulong *fb_basep,
+ ulong *fb_sizep, int *pitchp)
+{
+ ALLOC_CACHE_ALIGN_BUFFER(struct msg_setup, msg_setup, 1);
+ int ret;
+
+ BCM2835_MBOX_INIT_HDR(msg_setup);
+ BCM2835_MBOX_INIT_TAG(&msg_setup->physical_w_h, SET_PHYSICAL_W_H);
+ msg_setup->physical_w_h.body.req.width = *widthp;
+ msg_setup->physical_w_h.body.req.height = *heightp;
+ BCM2835_MBOX_INIT_TAG(&msg_setup->virtual_w_h, SET_VIRTUAL_W_H);
+ msg_setup->virtual_w_h.body.req.width = *widthp;
+ msg_setup->virtual_w_h.body.req.height = *heightp;
+ BCM2835_MBOX_INIT_TAG(&msg_setup->depth, SET_DEPTH);
+ msg_setup->depth.body.req.bpp = 32;
+ BCM2835_MBOX_INIT_TAG(&msg_setup->pixel_order, SET_PIXEL_ORDER);
+ msg_setup->pixel_order.body.req.order = pixel_order;
+ BCM2835_MBOX_INIT_TAG(&msg_setup->alpha_mode, SET_ALPHA_MODE);
+ msg_setup->alpha_mode.body.req.alpha = alpha_mode;
+ BCM2835_MBOX_INIT_TAG(&msg_setup->virtual_offset, SET_VIRTUAL_OFFSET);
+ msg_setup->virtual_offset.body.req.x = 0;
+ msg_setup->virtual_offset.body.req.y = 0;
+ BCM2835_MBOX_INIT_TAG(&msg_setup->overscan, SET_OVERSCAN);
+ msg_setup->overscan.body.req.top = 0;
+ msg_setup->overscan.body.req.bottom = 0;
+ msg_setup->overscan.body.req.left = 0;
+ msg_setup->overscan.body.req.right = 0;
+ BCM2835_MBOX_INIT_TAG(&msg_setup->allocate_buffer, ALLOCATE_BUFFER);
+ msg_setup->allocate_buffer.body.req.alignment = 0x100;
+ BCM2835_MBOX_INIT_TAG_NO_REQ(&msg_setup->pitch, GET_PITCH);
+
+ ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg_setup->hdr);
+ if (ret) {
+ printf("bcm2835: Could not configure display\n");
+ return ret;
+ }
+ *widthp = msg_setup->physical_w_h.body.resp.width;
+ *heightp = msg_setup->physical_w_h.body.resp.height;
+ *pitchp = msg_setup->pitch.body.resp.pitch;
+ *fb_basep = bus_to_phys(
+ msg_setup->allocate_buffer.body.resp.fb_address);
+ *fb_sizep = msg_setup->allocate_buffer.body.resp.fb_size;
+
+ return 0;
+}
+
+/*
+ * On the Raspberry Pi 4, after a PCI reset, VL805's (the xHCI chip) firmware
+ * may either be loaded directly from an EEPROM or, if not present, by the
+ * SoC's VideoCore. This informs VideoCore that VL805 needs its firmware
+ * loaded.
+ */
+int bcm2711_notify_vl805_reset(void)
+{
+ ALLOC_CACHE_ALIGN_BUFFER(struct msg_notify_vl805_reset,
+ msg_notify_vl805_reset, 1);
+ int ret;
+
+ BCM2835_MBOX_INIT_HDR(msg_notify_vl805_reset);
+ BCM2835_MBOX_INIT_TAG(&msg_notify_vl805_reset->dev_addr,
+ NOTIFY_XHCI_RESET);
+
+ /*
+ * The pci device address is expected like this:
+ *
+ * PCI_BUS << 20 | PCI_SLOT << 15 | PCI_FUNC << 12
+ *
+ * But since RPi4's PCIe setup is hardwired, we know the address in
+ * advance.
+ */
+ msg_notify_vl805_reset->dev_addr.body.req.dev_addr = 0x100000;
+
+ ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN,
+ &msg_notify_vl805_reset->hdr);
+ if (ret) {
+ printf("bcm2711: Faild to load vl805's firmware, %d\n", ret);
+ return -EIO;
+ }
+
+ udelay(200);
+
+ return 0;
+}
+
diff --git a/roms/u-boot/arch/arm/mach-bcm283x/phys2bus.c b/roms/u-boot/arch/arm/mach-bcm283x/phys2bus.c
new file mode 100644
index 000000000..8e4318bf5
--- /dev/null
+++ b/roms/u-boot/arch/arm/mach-bcm283x/phys2bus.c
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2015 Stephen Warren
+ */
+
+#include <config.h>
+#include <phys2bus.h>
+
+unsigned long phys_to_bus(unsigned long phys)
+{
+#ifndef CONFIG_BCM2835
+ return 0xc0000000 | phys;
+#else
+ return 0x40000000 | phys;
+#endif
+}
+
+unsigned long bus_to_phys(unsigned long bus)
+{
+ return bus & ~0xc0000000;
+}
diff --git a/roms/u-boot/arch/arm/mach-bcm283x/reset.c b/roms/u-boot/arch/arm/mach-bcm283x/reset.c
new file mode 100644
index 000000000..f13ac0c63
--- /dev/null
+++ b/roms/u-boot/arch/arm/mach-bcm283x/reset.c
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) Copyright 2012 Stephen Warren
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ */
+
+#include <common.h>
+#include <cpu_func.h>
+#include <asm/io.h>
+#include <asm/arch/base.h>
+#include <asm/arch/wdog.h>
+#include <efi_loader.h>
+
+#define RESET_TIMEOUT 10
+
+/*
+ * The Raspberry Pi firmware uses the RSTS register to know which partiton
+ * to boot from. The partiton value is spread into bits 0, 2, 4, 6, 8, 10.
+ * Partiton 63 is a special partition used by the firmware to indicate halt.
+ */
+#define BCM2835_WDOG_RSTS_RASPBERRYPI_HALT 0x555
+
+/* max ticks timeout */
+#define BCM2835_WDOG_MAX_TIMEOUT 0x000fffff
+
+void hw_watchdog_disable(void) {}
+
+__efi_runtime_data struct bcm2835_wdog_regs *wdog_regs;
+
+static void __efi_runtime
+__reset_cpu(struct bcm2835_wdog_regs *wdog_regs, ulong ticks)
+{
+ uint32_t rstc, timeout;
+
+ if (ticks == 0) {
+ hw_watchdog_disable();
+ timeout = RESET_TIMEOUT;
+ } else
+ timeout = ticks & BCM2835_WDOG_MAX_TIMEOUT;
+
+ rstc = readl(&wdog_regs->rstc);
+ rstc &= ~BCM2835_WDOG_RSTC_WRCFG_MASK;
+ rstc |= BCM2835_WDOG_RSTC_WRCFG_FULL_RESET;
+
+ writel(BCM2835_WDOG_PASSWORD | timeout, &wdog_regs->wdog);
+ writel(BCM2835_WDOG_PASSWORD | rstc, &wdog_regs->rstc);
+}
+
+void reset_cpu(void)
+{
+ struct bcm2835_wdog_regs *regs =
+ (struct bcm2835_wdog_regs *)BCM2835_WDOG_PHYSADDR;
+
+ __reset_cpu(regs, 0);
+}
+
+#ifdef CONFIG_EFI_LOADER
+
+void __efi_runtime EFIAPI efi_reset_system(
+ enum efi_reset_type reset_type,
+ efi_status_t reset_status,
+ unsigned long data_size, void *reset_data)
+{
+ u32 val;
+
+ if (reset_type == EFI_RESET_COLD ||
+ reset_type == EFI_RESET_WARM ||
+ reset_type == EFI_RESET_PLATFORM_SPECIFIC) {
+ __reset_cpu(wdog_regs, 0);
+ } else if (reset_type == EFI_RESET_SHUTDOWN) {
+ /*
+ * We set the watchdog hard reset bit here to distinguish this reset
+ * from the normal (full) reset. bootcode.bin will not reboot after a
+ * hard reset.
+ */
+ val = readl(&wdog_regs->rsts);
+ val |= BCM2835_WDOG_PASSWORD;
+ val |= BCM2835_WDOG_RSTS_RASPBERRYPI_HALT;
+ writel(val, &wdog_regs->rsts);
+ __reset_cpu(wdog_regs, 0);
+ }
+
+ while (1) { }
+}
+
+efi_status_t efi_reset_system_init(void)
+{
+ wdog_regs = (struct bcm2835_wdog_regs *)BCM2835_WDOG_PHYSADDR;
+ return efi_add_runtime_mmio(&wdog_regs, sizeof(*wdog_regs));
+}
+
+#endif