summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/boards/bcm2835.rst17
-rw-r--r--arch/arm/Kconfig10
-rw-r--r--arch/arm/boards/raspberry-pi/Makefile1
-rw-r--r--arch/arm/boards/raspberry-pi/lowlevel.c129
-rw-r--r--arch/arm/boards/raspberry-pi/lowlevel.h5
-rw-r--r--arch/arm/boards/raspberry-pi/mbox-helpers.c73
-rw-r--r--arch/arm/boards/raspberry-pi/rpi-common.c310
-rw-r--r--arch/arm/configs/rpi_defconfig3
-rw-r--r--arch/arm/configs/rpi_v8a_defconfig112
-rw-r--r--arch/arm/cpu/Kconfig7
-rw-r--r--arch/arm/dts/Makefile1
-rw-r--r--arch/arm/dts/bcm2711-rpi-4.dts18
-rw-r--r--arch/arm/include/asm/cputype.h22
-rw-r--r--arch/arm/include/asm/dma.h5
-rw-r--r--arch/arm/include/asm/system_info.h6
-rw-r--r--arch/arm/mach-bcm283x/Kconfig29
-rw-r--r--arch/arm/mach-bcm283x/Makefile2
-rw-r--r--arch/arm/mach-bcm283x/core.c57
-rw-r--r--arch/arm/mach-bcm283x/include/mach/core.h23
-rw-r--r--arch/arm/mach-bcm283x/include/mach/debug_ll.h26
-rw-r--r--arch/arm/mach-bcm283x/include/mach/mbox.h4
-rw-r--r--arch/arm/mach-bcm283x/include/mach/platform.h5
-rw-r--r--arch/arm/mach-bcm283x/mbox.c26
-rw-r--r--arch/arm/mach-imx/Kconfig2
-rw-r--r--arch/arm/mach-layerscape/Kconfig2
-rw-r--r--arch/arm/mach-rockchip/Kconfig2
-rw-r--r--arch/kvx/include/asm/dma.h2
-rw-r--r--arch/mips/include/asm/dma-mapping.h2
-rw-r--r--arch/sandbox/include/asm/dma.h5
-rw-r--r--arch/x86/include/asm/dma.h4
-rw-r--r--common/Kconfig7
-rw-r--r--drivers/clk/clk-rpi.c42
-rw-r--r--drivers/clocksource/bcm2835.c3
-rw-r--r--drivers/i2c/busses/Kconfig4
-rw-r--r--drivers/i2c/busses/Makefile1
-rw-r--r--drivers/i2c/busses/i2c-bcm283x.c327
-rw-r--r--drivers/mci/mci-bcm2835.c4
-rw-r--r--drivers/serial/serial_ns16550.c4
-rw-r--r--drivers/watchdog/bcm2835_wdt.c23
-rw-r--r--images/Makefile.bcm283x10
-rw-r--r--include/dma.h34
-rw-r--r--include/soc/bcm283x/wdt.h40
42 files changed, 1143 insertions, 266 deletions
diff --git a/Documentation/boards/bcm2835.rst b/Documentation/boards/bcm2835.rst
index 0b5299a340..f6df3e9e80 100644
--- a/Documentation/boards/bcm2835.rst
+++ b/Documentation/boards/bcm2835.rst
@@ -4,9 +4,14 @@ Broadcom BCM283x
Raspberry Pi
------------
+barebox supports has support for BCM283x-based Raspberry Pi single board
+computers. Support is most extensive for BCM283[567]. For the newer BCM2711
+used in the Raspberry Pi 4, only basic support is currently available
+(Serial Port, Pinctrl/GPIO, SD-Card).
+
1. Prepare an SD or microSD card with a FAT filesystem of at least 30 MB in size.
- 2. Download the `Raspberry Pi firmware`_ (120 MB), unzip it, and copy the
+ 2. Download the `Raspberry Pi firmware`_ (195 MB), unzip it, and copy the
contents of the ``boot/`` folder to your card.
3. Use ``make rpi_defconfig; make`` to build barebox. This will create the following images:
@@ -15,14 +20,14 @@ Raspberry Pi
- ``images/barebox-raspberry-pi-2.img`` for the BCM2836/CORTEX-A7 (Raspberry Pi 2)
- ``images/barebox-raspberry-pi-3.img`` for the BCM2837/CORTEX-A53 (Raspberry Pi 3)
- ``images/barebox-raspberry-pi-cm3.img`` for the BCM2837/CORTEX-A53 (Raspberry Pi CM3)
+ - ``images/barebox-raspberry-pi.img``, which is a super set of all the other images
Copy the respective image for your model to your SD card and name it
``barebox.img``.
- Alternatively, ``images/barebox-dt-2nd.img`` can be used as single bootloader for all
- supported 32-bit boards. In this case the device tree supplied by the video core
- is directly used by barebox to probe. The device trees in ``arch/arm/dts/*.dtb``
- will need to be renamed for alignment with the naming scheme expected by the videocore.
+ The ``images/barebox-raspberry-pi.img`` is expected to replace the other images
+ in the future. It contains the device trees of all supported (and enabled) variants
+ and determines at runtime what board it runs on and does the right thing.
4. Create a text file ``config.txt`` on the SD card with the following content::
@@ -53,5 +58,5 @@ The original command-line from VideoCore device tree is available to the Barebox
global linux.bootargs.vc="$global.vc.bootargs"
-.. _Raspberry Pi firmware: https://codeload.github.com/raspberrypi/firmware/zip/80e1fbeb78f9df06701d28c0ed3a3060a3f557ef
+.. _Raspberry Pi firmware: https://github.com/raspberrypi/firmware/archive/refs/tags/1.20220331.zip
.. _documentation for config.txt: https://www.raspberrypi.org/documentation/configuration/config-txt/
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 8a1d75c19b..59fce0c601 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -60,6 +60,8 @@ config ARCH_BCM283X
select OFTREE
select OFDEVICE
select HAVE_PBL_MULTI_IMAGES
+ select CPU_SUPPORTS_32BIT_KERNEL
+ select CPU_SUPPORTS_64BIT_KERNEL
config ARCH_CLPS711X
bool "Cirrus Logic EP711x/EP721x/EP731x"
@@ -276,7 +278,7 @@ config ARCH_ZYNQMP
select OFDEVICE
select OFTREE
select RELOCATABLE
- select SYS_SUPPORTS_64BIT_KERNEL
+ select CPU_SUPPORTS_64BIT_KERNEL
select HAS_MACB
config ARCH_ARM64_VIRT
@@ -286,7 +288,7 @@ config ARCH_ARM64_VIRT
select OFDEVICE
select OFTREE
select RELOCATABLE
- select SYS_SUPPORTS_64BIT_KERNEL
+ select CPU_SUPPORTS_64BIT_KERNEL
select ARM_AMBA
select BOARD_ARM_VIRT
select HW_HAS_PCI
@@ -397,13 +399,13 @@ choice
config 32BIT
bool "32-bit barebox"
- depends on CPU_SUPPORTS_32BIT_KERNEL && SYS_SUPPORTS_32BIT_KERNEL
+ depends on CPU_SUPPORTS_32BIT_KERNEL
help
Select this option if you want to build a 32-bit barebox.
config 64BIT
bool "64-bit barebox"
- depends on CPU_SUPPORTS_64BIT_KERNEL && SYS_SUPPORTS_64BIT_KERNEL
+ depends on CPU_SUPPORTS_64BIT_KERNEL
select ARCH_DMA_ADDR_T_64BIT
help
Select this option if you want to build a 64-bit barebox.
diff --git a/arch/arm/boards/raspberry-pi/Makefile b/arch/arm/boards/raspberry-pi/Makefile
index 6f995b5640..e4f91b4979 100644
--- a/arch/arm/boards/raspberry-pi/Makefile
+++ b/arch/arm/boards/raspberry-pi/Makefile
@@ -2,4 +2,5 @@
obj-$(CONFIG_MACH_RPI_COMMON) += rpi-common.o
lwl-y += lowlevel.o
+obj-pbl-y += mbox-helpers.o
bbenv-y += defaultenv-rpi
diff --git a/arch/arm/boards/raspberry-pi/lowlevel.c b/arch/arm/boards/raspberry-pi/lowlevel.c
index 7b9809b86c..5ead895767 100644
--- a/arch/arm/boards/raspberry-pi/lowlevel.c
+++ b/arch/arm/boards/raspberry-pi/lowlevel.c
@@ -4,7 +4,10 @@
#include <asm/cache.h>
#include <common.h>
#include <linux/sizes.h>
+#include <asm/unaligned.h>
#include <mach/platform.h>
+#include <debug_ll.h>
+#include <mach/mbox.h>
#include <of.h>
#include "lowlevel.h"
@@ -33,7 +36,7 @@ static void copy_vc_fdt(void *dest, void *src, unsigned long max_size)
memmove(dest, src, size);
}
-/* A pointer to the FDT created by VideoCore was passed to us in r2. We
+/* A pointer to the FDT created by VideoCore was passed to us in x0/r2. We
* reserve some memory just above the region used for Barebox and copy
* this FDT there. We fetch it from there later in rpi_devices_init().
*/
@@ -45,8 +48,6 @@ static inline void start_raspberry_pi(unsigned long memsize, void *fdt,
{
unsigned long endmem = rpi_stack_top(memsize);
- arm_cpu_lowlevel_init();
-
copy_vc_fdt((void *)endmem, vc_fdt, VIDEOCORE_FDT_SZ);
fdt += get_runtime_offset();
@@ -54,29 +55,123 @@ static inline void start_raspberry_pi(unsigned long memsize, void *fdt,
barebox_arm_entry(BCM2835_SDRAM_BASE, endmem - BCM2835_SDRAM_BASE, fdt);
}
-#define RPI_ENTRY_FUNCTION(name, memsize, r2) \
- ENTRY_FUNCTION_WITHSTACK(name, rpi_stack_top(memsize), __r0, __r1, r2)
+#ifdef CONFIG_CPU_V8
+#define RPI_ENTRY_FUNCTION(name, memsize, fdt) \
+ ENTRY_FUNCTION_WITHSTACK(name, rpi_stack_top(memsize), fdt, __x1, __x2)
+#else
+#define RPI_ENTRY_FUNCTION(name, memsize, fdt) \
+ ENTRY_FUNCTION_WITHSTACK(name, rpi_stack_top(memsize), __r0, __r1, fdt)
+#endif
+
+extern char __dtb_z_bcm2835_rpi_start[];
+extern char __dtb_z_bcm2836_rpi_2_start[];
+extern char __dtb_z_bcm2837_rpi_3_start[];
+extern char __dtb_z_bcm2837_rpi_cm3_start[];
+extern char __dtb_z_bcm2711_rpi_4_start[];
+
+RPI_ENTRY_FUNCTION(start_raspberry_pi1, SZ_128M, fdt)
+{
+ arm_cpu_lowlevel_init();
+
+ start_raspberry_pi(SZ_128M, __dtb_z_bcm2835_rpi_start, (void *)fdt);
+}
+
+RPI_ENTRY_FUNCTION(start_raspberry_pi2, SZ_512M, fdt)
+{
+ arm_cpu_lowlevel_init();
+
+ start_raspberry_pi(SZ_512M, __dtb_z_bcm2836_rpi_2_start, (void *)fdt);
+}
-extern char __dtb_bcm2835_rpi_start[];
-RPI_ENTRY_FUNCTION(start_raspberry_pi1, SZ_128M, r2)
+RPI_ENTRY_FUNCTION(start_raspberry_pi3, SZ_512M, fdt)
{
- start_raspberry_pi(SZ_128M, __dtb_bcm2835_rpi_start, (void *)r2);
+ arm_cpu_lowlevel_init();
+
+ start_raspberry_pi(SZ_512M, __dtb_z_bcm2837_rpi_3_start, (void *)fdt);
}
-extern char __dtb_bcm2836_rpi_2_start[];
-RPI_ENTRY_FUNCTION(start_raspberry_pi2, SZ_512M, r2)
+RPI_ENTRY_FUNCTION(start_raspberry_pi_cm3, SZ_512M, fdt)
{
- start_raspberry_pi(SZ_512M, __dtb_bcm2836_rpi_2_start, (void *)r2);
+ arm_cpu_lowlevel_init();
+
+ start_raspberry_pi(SZ_512M, __dtb_z_bcm2837_rpi_cm3_start, (void *)fdt);
}
-extern char __dtb_bcm2837_rpi_3_start[];
-RPI_ENTRY_FUNCTION(start_raspberry_pi3, SZ_512M, r2)
+#define DT_IF_ENABLED(dt, cfg) \
+ (IS_ENABLED(cfg) ? (dt) : NULL)
+
+static void *rpi_get_board_fdt(int rev)
{
- start_raspberry_pi(SZ_512M, __dtb_bcm2837_rpi_3_start, (void *)r2);
+ if (!(rev & 0x800000))
+ return DT_IF_ENABLED(__dtb_z_bcm2835_rpi_start, CONFIG_MACH_RPI);
+
+ switch (((rev >> 4) & 0xff)) {
+ case BCM2835_BOARD_REV_A:
+ case BCM2835_BOARD_REV_B:
+ case BCM2835_BOARD_REV_A_PLUS:
+ case BCM2835_BOARD_REV_B_PLUS:
+ case BCM2835_BOARD_REV_CM1:
+ case BCM2835_BOARD_REV_ZERO:
+ case BCM2835_BOARD_REV_ZERO_W:
+ return DT_IF_ENABLED(__dtb_z_bcm2835_rpi_start, CONFIG_MACH_RPI);
+
+ case BCM2836_BOARD_REV_2_B:
+ return DT_IF_ENABLED(__dtb_z_bcm2836_rpi_2_start, CONFIG_MACH_RPI2);
+
+ case BCM2837_BOARD_REV_3_B:
+ case BCM2837B0_BOARD_REV_3B_PLUS:
+ case BCM2837B0_BOARD_REV_3A_PLUS:
+ case BCM2837B0_BOARD_REV_ZERO_2:
+ return DT_IF_ENABLED(__dtb_z_bcm2837_rpi_3_start, CONFIG_MACH_RPI3);
+
+ case BCM2837_BOARD_REV_CM3:
+ case BCM2837B0_BOARD_REV_CM3_PLUS:
+ return DT_IF_ENABLED(__dtb_z_bcm2837_rpi_cm3_start, CONFIG_MACH_RPI_CM3);
+
+ case BCM2711_BOARD_REV_4_B:
+ case BCM2711_BOARD_REV_400:
+ case BCM2711_BOARD_REV_CM4:
+ return DT_IF_ENABLED(__dtb_z_bcm2711_rpi_4_start, CONFIG_MACH_RPI4);
+ }
+
+ return NULL;
}
-extern char __dtb_bcm2837_rpi_cm3_start[];
-RPI_ENTRY_FUNCTION(start_raspberry_pi_cm3, SZ_512M, r2)
+RPI_ENTRY_FUNCTION(start_raspberry_pi_generic, SZ_128M, vc_fdt)
{
- start_raspberry_pi(SZ_512M, __dtb_bcm2837_rpi_cm3_start, (void *)r2);
+ void *fdt = NULL;
+ ssize_t memsize;
+ int rev;
+
+ arm_cpu_lowlevel_init();
+
+ debug_ll_init();
+
+ putc_ll('>');
+
+ relocate_to_current_adr();
+ setup_c();
+
+ memsize = rpi_get_arm_mem();
+ if (memsize < 0) {
+ pr_warn("mbox: failed to query ARM memory size. 128M assumed.\n");
+ memsize = SZ_128M;
+ }
+
+ rev = rpi_get_board_rev();
+ if (rev >= 0) {
+ pr_debug("Detected revision %08x\n", rev);
+ fdt = rpi_get_board_fdt(rev);
+ }
+
+ if (!fdt) {
+ fdt = (void *)vc_fdt;
+
+ pr_warn("Unknown Rpi board with rev %08x.\n", rev);
+
+ if (get_unaligned_be32(fdt) != 0xd00dfeed)
+ panic("No suitable built-in or videocore-supplied DT\n");
+ }
+
+ start_raspberry_pi(memsize, fdt, (void *)vc_fdt);
}
diff --git a/arch/arm/boards/raspberry-pi/lowlevel.h b/arch/arm/boards/raspberry-pi/lowlevel.h
index eacf973fb6..a29860d607 100644
--- a/arch/arm/boards/raspberry-pi/lowlevel.h
+++ b/arch/arm/boards/raspberry-pi/lowlevel.h
@@ -3,9 +3,14 @@
#ifndef __ARCH_ARM_BOARDS_LOWLEVEL_H__
#define __ARCH_ARM_BOARDS_LOWLEVEL_H__
+#include <linux/types.h>
#include <linux/sizes.h>
#define VIDEOCORE_FDT_SZ SZ_1M
#define VIDEOCORE_FDT_ERROR 0xdeadfeed
+ssize_t rpi_get_arm_mem(void);
+int rpi_get_usbethaddr(u8 mac[6]);
+int rpi_get_board_rev(void);
+
#endif /* __ARCH_ARM_BOARDS_LOWLEVEL_H__ */
diff --git a/arch/arm/boards/raspberry-pi/mbox-helpers.c b/arch/arm/boards/raspberry-pi/mbox-helpers.c
new file mode 100644
index 0000000000..9f252c68ff
--- /dev/null
+++ b/arch/arm/boards/raspberry-pi/mbox-helpers.c
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2009 Carlo Caione <carlo@carlocaione.org>
+
+#include <mach/mbox.h>
+#include "lowlevel.h"
+
+struct msg_get_arm_mem {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_get_arm_mem get_arm_mem;
+ u32 end_tag;
+};
+
+struct msg_get_board_rev {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_get_board_rev get_board_rev;
+ u32 end_tag;
+};
+
+struct msg_get_mac_address {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_get_mac_address get_mac_address;
+ u32 end_tag;
+};
+
+ssize_t rpi_get_arm_mem(void)
+{
+ BCM2835_MBOX_STACK_ALIGN(struct msg_get_arm_mem, msg);
+ int ret;
+
+ BCM2835_MBOX_INIT_HDR(msg);
+ BCM2835_MBOX_INIT_TAG(&msg->get_arm_mem, GET_ARM_MEMORY);
+
+ ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr);
+ if (ret)
+ return ret;
+
+ return msg->get_arm_mem.body.resp.mem_size;
+}
+
+int rpi_get_usbethaddr(u8 mac[6])
+{
+ BCM2835_MBOX_STACK_ALIGN(struct msg_get_mac_address, msg);
+ int ret;
+
+ BCM2835_MBOX_INIT_HDR(msg);
+ BCM2835_MBOX_INIT_TAG(&msg->get_mac_address, GET_MAC_ADDRESS);
+
+ ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr);
+ if (ret) {
+ pr_info("bcm2835: Could not query MAC address\n");
+ return ret;
+ }
+
+ memcpy(mac, msg->get_mac_address.body.resp.mac, 6);
+ return 0;
+}
+
+int rpi_get_board_rev(void)
+{
+ int ret;
+
+ BCM2835_MBOX_STACK_ALIGN(struct msg_get_board_rev, msg);
+ BCM2835_MBOX_INIT_HDR(msg);
+ BCM2835_MBOX_INIT_TAG(&msg->get_board_rev, GET_BOARD_REV);
+
+ ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr);
+ if (ret) {
+ pr_err("Could not query board revision\n");
+ return ret;
+ }
+
+ return msg->get_board_rev.body.resp.rev;
+}
diff --git a/arch/arm/boards/raspberry-pi/rpi-common.c b/arch/arm/boards/raspberry-pi/rpi-common.c
index 05d59ae6bf..77935e5c88 100644
--- a/arch/arm/boards/raspberry-pi/rpi-common.c
+++ b/arch/arm/boards/raspberry-pi/rpi-common.c
@@ -23,13 +23,28 @@
#include <linux/sizes.h>
#include <globalvar.h>
#include <asm/system_info.h>
+#include <reset_source.h>
#include <mach/core.h>
#include <mach/mbox.h>
#include <mach/platform.h>
+#include <soc/bcm283x/wdt.h>
+
#include "lowlevel.h"
+//https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#BOOT_ORDER
+static const char * const boot_mode_names[] = {
+ [0x0] = "unknown",
+ [0x1] = "sd",
+ [0x2] = "net",
+ [0x3] = "rpiboot",
+ [0x4] = "usbmsd",
+ [0x5] = "usbc",
+ [0x6] = "nvme",
+ [0x7] = "http",
+};
+
struct rpi_priv;
struct rpi_machine_data {
int (*init)(struct rpi_priv *priv);
@@ -45,57 +60,14 @@ struct rpi_priv {
const char *name;
};
-struct msg_get_arm_mem {
- struct bcm2835_mbox_hdr hdr;
- struct bcm2835_mbox_tag_get_arm_mem get_arm_mem;
- u32 end_tag;
-};
-
-struct msg_get_board_rev {
- struct bcm2835_mbox_hdr hdr;
- struct bcm2835_mbox_tag_get_board_rev get_board_rev;
- u32 end_tag;
-};
-
-struct msg_get_mac_address {
- struct bcm2835_mbox_hdr hdr;
- struct bcm2835_mbox_tag_get_mac_address get_mac_address;
- u32 end_tag;
-};
-
-static int rpi_get_arm_mem(u32 *size)
-{
- BCM2835_MBOX_STACK_ALIGN(struct msg_get_arm_mem, msg);
- int ret;
-
- BCM2835_MBOX_INIT_HDR(msg);
- BCM2835_MBOX_INIT_TAG(&msg->get_arm_mem, GET_ARM_MEMORY);
-
- ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr);
- if (ret)
- return ret;
-
- *size = msg->get_arm_mem.body.resp.mem_size;
-
- return 0;
-}
-
static void rpi_set_usbethaddr(void)
{
- BCM2835_MBOX_STACK_ALIGN(struct msg_get_mac_address, msg);
- int ret;
+ u8 mac[ETH_ALEN];
- BCM2835_MBOX_INIT_HDR(msg);
- BCM2835_MBOX_INIT_TAG(&msg->get_mac_address, GET_MAC_ADDRESS);
+ if (rpi_get_usbethaddr(mac))
+ return; /* Ignore error; not critical */
- ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr);
- if (ret) {
- printf("bcm2835: Could not query MAC address\n");
- /* Ignore error; not critical */
- return;
- }
-
- eth_register_ethaddr(0, msg->get_mac_address.body.resp.mac);
+ eth_register_ethaddr(0, mac);
}
static void rpi_set_usbotg(const char *alias)
@@ -185,48 +157,19 @@ static int rpi_0_w_init(struct rpi_priv *priv)
return of_device_disable_by_alias("serial0");
}
-static int rpi_get_board_rev(struct rpi_priv *priv)
-{
- int ret;
-
- BCM2835_MBOX_STACK_ALIGN(struct msg_get_board_rev, msg);
- BCM2835_MBOX_INIT_HDR(msg);
- BCM2835_MBOX_INIT_TAG(&msg->get_board_rev, GET_BOARD_REV);
-
- ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr);
- if (ret) {
- dev_err(priv->dev, "Could not query board revision\n");
- return ret;
- }
-
- /* Comments from u-boot:
- * For details of old-vs-new scheme, see:
- * https://github.com/pimoroni/RPi.version/blob/master/RPi/version.py
- * http://www.raspberrypi.org/forums/viewtopic.php?f=63&t=99293&p=690282
- * (a few posts down)
- *
- * For the RPi 1, bit 24 is the "warranty bit", so we mask off just the
- * lower byte to use as the board rev:
- * http://www.raspberrypi.org/forums/viewtopic.php?f=63&t=98367&start=250
- * http://www.raspberrypi.org/forums/viewtopic.php?f=31&t=20594
- */
- priv->hw_id = msg->get_board_rev.body.resp.rev;
-
- return 0;
-}
-
static int rpi_mem_init(void)
{
- u32 size = 0;
- int ret;
+ ssize_t size;
- ret = rpi_get_arm_mem(&size);
- if (ret)
+ size = rpi_get_arm_mem();
+ if (size < 0) {
printf("could not query ARM memory size\n");
+ size = get_ram_size((ulong *) BCM2835_SDRAM_BASE, SZ_128M);
+ }
bcm2835_add_device_sdram(size);
- return ret;
+ return 0;
}
mem_initcall(rpi_mem_init);
@@ -258,54 +201,133 @@ static int rpi_env_init(void)
return 0;
}
-/* Extract /chosen/bootargs from the VideoCore FDT into vc.bootargs
- * global variable. */
-static int rpi_vc_fdt_bootargs(void *fdt)
+/* Some string properties in fdt passed to us from vc may be
+ * malformed by not being null terminated, so just create and
+ * return a fixed copy.
+ */
+static char *of_read_vc_string(struct device_node *node,
+ const char *prop_name)
+{
+ int len;
+ const char *str;
+
+ str = of_get_property(node, prop_name, &len);
+ if (!str) {
+ pr_warn("no property '%s' found in vc fdt's '%s' node\n",
+ prop_name, node->full_name);
+ return NULL;
+ }
+ return xstrndup(str, len);
+}
+
+static enum reset_src_type rpi_decode_pm_rsts(struct device_node *chosen,
+ struct device_node *bootloader)
{
- int ret = 0;
- struct device_node *root = NULL, *node;
- const char *cmdline;
+ u32 pm_rsts;
+ int ret;
+
+ ret = of_property_read_u32(chosen, "pm_rsts", &pm_rsts);
+ if (ret && bootloader)
+ ret = of_property_read_u32(bootloader, "rsts", &pm_rsts);
+
+ if (ret) {
+ pr_warn("'pm_rsts' value not found in vc fdt\n");
+ return RESET_UKWN;
+ }
+ /*
+ * https://github.com/raspberrypi/linux/issues/932#issuecomment-93989581
+ */
+
+ if (pm_rsts & PM_RSTS_HADPOR_SET)
+ return RESET_POR;
+ if (pm_rsts & PM_RSTS_HADDR_SET)
+ return RESET_JTAG;
+ if (pm_rsts & PM_RSTS_HADWR_SET)
+ return RESET_WDG;
+ if (pm_rsts & PM_RSTS_HADSR_SET)
+ return RESET_RST;
+
+ return RESET_UKWN;
+}
+
+static u32 rpi_boot_mode, rpi_boot_part;
+/* Extract useful information from the VideoCore FDT we got.
+ * Some parameters are defined here:
+ * https://www.raspberrypi.com/documentation/computers/configuration.html#part4
+ */
+static void rpi_vc_fdt_parse(void *fdt)
+{
+ int ret;
+ struct device_node *root, *chosen, *bootloader;
+ char *str;
root = of_unflatten_dtb(fdt, INT_MAX);
- if (IS_ERR(root)) {
- ret = PTR_ERR(root);
- root = NULL;
- goto out;
+ if (IS_ERR(root))
+ return;
+
+ str = of_read_vc_string(root, "serial-number");
+ if (str) {
+ barebox_set_serial_number(str);
+ free(str);
}
- node = of_find_node_by_path_from(root, "/chosen");
- if (!node) {
- pr_err("no /chosen node\n");
- ret = -ENOENT;
- goto out;
+ str = of_read_vc_string(root, "model");
+ if (str) {
+ barebox_set_model(str);
+ free(str);
}
- cmdline = of_get_property(node, "bootargs", NULL);
- if (!cmdline) {
- pr_err("no bootargs property in the /chosen node\n");
- ret = -ENOENT;
+ chosen = of_find_node_by_path_from(root, "/chosen");
+ if (!chosen) {
+ pr_err("no '/chosen' node found in vc fdt\n");
goto out;
}
- globalvar_add_simple("vc.bootargs", cmdline);
+ bootloader = of_find_node_by_name(chosen, "bootloader");
- switch(cpu_architecture()) {
- case CPU_ARCH_ARMv6:
- globalvar_add_simple("vc.kernel", "kernel.img");
- break;
- case CPU_ARCH_ARMv7:
- globalvar_add_simple("vc.kernel", "kernel7.img");
- break;
- case CPU_ARCH_ARMv8:
- globalvar_add_simple("vc.kernel", "kernel7l.img");
- break;
+ str = of_read_vc_string(chosen, "bootargs");
+ if (str) {
+ globalvar_add_simple("vc.bootargs", str);
+ free(str);
}
+ str = of_read_vc_string(chosen, "overlay_prefix");
+ if (str) {
+ globalvar_add_simple("vc.overlay_prefix", str);
+ free(str);
+ }
+
+ str = of_read_vc_string(chosen, "os_prefix");
+ if (str) {
+ globalvar_add_simple("vc.os_prefix", str);
+ free(str);
+ }
+
+ ret = of_property_read_u32(chosen, "boot-mode", &rpi_boot_mode);
+ if (ret && bootloader)
+ ret = of_property_read_u32(bootloader, "boot-mode", &rpi_boot_mode);
+ if (ret)
+ pr_debug("'boot-mode' property not found in vc fdt\n");
+ else
+ globalvar_add_simple_enum("vc.boot_mode", &rpi_boot_mode,
+ boot_mode_names,
+ ARRAY_SIZE(boot_mode_names));
+
+ ret = of_property_read_u32(chosen, "partition", &rpi_boot_part);
+ if (ret && bootloader)
+ ret = of_property_read_u32(bootloader, "partition", &rpi_boot_part);
+ if (ret)
+ pr_debug("'partition' property not found in vc fdt\n");
+ else
+ globalvar_add_simple_int("vc.boot_partition", &rpi_boot_part, "%u");
+
+ if (IS_ENABLED(CONFIG_RESET_SOURCE))
+ reset_source_set(rpi_decode_pm_rsts(chosen, bootloader));
+
out:
if (root)
of_delete_node(root);
-
- return ret;
+ return;
}
static void rpi_vc_fdt(void)
@@ -313,7 +335,6 @@ static void rpi_vc_fdt(void)
void *saved_vc_fdt;
struct fdt_header *oftree;
unsigned long magic, size;
- int ret;
/* VideoCore FDT was copied in PBL just above Barebox memory */
saved_vc_fdt = (void *)(arm_mem_endmem_get());
@@ -332,16 +353,23 @@ static void rpi_vc_fdt(void)
return;
size = be32_to_cpu(oftree->totalsize);
- if (write_file("/vc.dtb", saved_vc_fdt, size)) {
+ if (write_file("/vc.dtb", saved_vc_fdt, size))
pr_err("failed to save videocore fdt to a file\n");
- return;
- }
- ret = rpi_vc_fdt_bootargs(saved_vc_fdt);
- if (ret) {
- pr_err("failed to extract bootargs from videocore fdt: %d\n",
- ret);
- return;
+ rpi_vc_fdt_parse(saved_vc_fdt);
+}
+
+static void rpi_set_kernel_name(void) {
+ switch(cpu_architecture()) {
+ case CPU_ARCH_ARMv6:
+ globalvar_add_simple("vc.kernel", "kernel.img");
+ break;
+ case CPU_ARCH_ARMv7:
+ globalvar_add_simple("vc.kernel", "kernel7.img");
+ break;
+ case CPU_ARCH_ARMv8:
+ globalvar_add_simple("vc.kernel", "kernel8.img");
+ break;
}
}
@@ -355,6 +383,18 @@ static const struct rpi_machine_data *rpi_get_dcfg(struct rpi_priv *priv)
return NULL;
}
+ /* Comments from u-boot:
+ * For details of old-vs-new scheme, see:
+ * https://github.com/pimoroni/RPi.version/blob/master/RPi/version.py
+ * http://www.raspberrypi.org/forums/viewtopic.php?f=63&t=99293&p=690282
+ * (a few posts down)
+ *
+ * For the RPi 1, bit 24 is the "warranty bit", so we mask off just the
+ * lower byte to use as the board rev:
+ * http://www.raspberrypi.org/forums/viewtopic.php?f=63&t=98367&start=250
+ * http://www.raspberrypi.org/forums/viewtopic.php?f=31&t=20594
+ */
+
for (; dcfg->hw_id != U8_MAX; dcfg++) {
if (priv->hw_id & 0x800000) {
if (dcfg->hw_id != ((priv->hw_id >> 4) & 0xff))
@@ -386,10 +426,12 @@ static int rpi_devices_probe(struct device_d *dev)
priv = xzalloc(sizeof(*priv));
priv->dev = dev;
- ret = rpi_get_board_rev(priv);
- if (ret)
+ ret = rpi_get_board_rev();
+ if (ret < 0)
goto free_priv;
+ priv->hw_id = ret;
+
dcfg = rpi_get_dcfg(priv);
if (IS_ERR(dcfg))
goto free_priv;
@@ -406,6 +448,7 @@ static int rpi_devices_probe(struct device_d *dev)
armlinux_set_architecture(MACH_TYPE_BCM2708);
rpi_env_init();
rpi_vc_fdt();
+ rpi_set_kernel_name();
if (dcfg && dcfg->init)
dcfg->init(priv);
@@ -532,6 +575,18 @@ static const struct rpi_machine_data rpi_3_ids[] = {
},
};
+static const struct rpi_machine_data rpi_4_ids[] = {
+ {
+ .hw_id = BCM2711_BOARD_REV_4_B,
+ }, {
+ .hw_id = BCM2711_BOARD_REV_400,
+ }, {
+ .hw_id = BCM2711_BOARD_REV_CM4,
+ }, {
+ .hw_id = U8_MAX
+ },
+};
+
static const struct of_device_id rpi_of_match[] = {
/* BCM2835 based Boards */
{ .compatible = "raspberrypi,model-a", .data = rpi_1_ids },
@@ -556,6 +611,11 @@ static const struct of_device_id rpi_of_match[] = {
{ .compatible = "raspberrypi,3-compute-module", .data = rpi_3_ids },
{ .compatible = "raspberrypi,3-compute-module-lite", .data = rpi_3_ids },
+ /* BCM2711 based Boards */
+ { .compatible = "raspberrypi,4-model-b", .data = rpi_4_ids },
+ { .compatible = "raspberrypi,4-compute-module", .data = rpi_4_ids },
+ { .compatible = "raspberrypi,400", .data = rpi_4_ids },
+
{ /* sentinel */ },
};
BAREBOX_DEEP_PROBE_ENABLE(rpi_of_match);
diff --git a/arch/arm/configs/rpi_defconfig b/arch/arm/configs/rpi_defconfig
index e0e1497481..e7d695f8ae 100644
--- a/arch/arm/configs/rpi_defconfig
+++ b/arch/arm/configs/rpi_defconfig
@@ -24,7 +24,6 @@ CONFIG_BOOTM_OFTREE=y
CONFIG_BLSPEC=y
CONFIG_CONSOLE_ALLOW_COLOR=y
CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y
-CONFIG_DEFAULT_ENVIRONMENT_PATH=""
CONFIG_CMD_DMESG=y
CONFIG_LONGHELP=y
CONFIG_CMD_IOMEM=y
@@ -83,6 +82,8 @@ CONFIG_SERIAL_AMBA_PL011=y
CONFIG_DRIVER_SERIAL_NS16550=y
CONFIG_NET_USB=y
CONFIG_NET_USB_SMSC95XX=y
+CONFIG_I2C=y
+CONFIG_I2C_BCM283X=y
CONFIG_USB_HOST=y
CONFIG_USB_DWC2_HOST=y
CONFIG_MCI=y
diff --git a/arch/arm/configs/rpi_v8a_defconfig b/arch/arm/configs/rpi_v8a_defconfig
new file mode 100644
index 0000000000..e218311a72
--- /dev/null
+++ b/arch/arm/configs/rpi_v8a_defconfig
@@ -0,0 +1,112 @@
+CONFIG_ARCH_BCM283X=y
+CONFIG_MACH_RPI3=y
+CONFIG_MACH_RPI_CM3=y
+CONFIG_MACH_RPI4=y
+CONFIG_64BIT=y
+CONFIG_IMAGE_COMPRESSION_NONE=y
+CONFIG_MMU=y
+# CONFIG_MMU_EARLY is not set
+CONFIG_MALLOC_SIZE=0x0
+CONFIG_MALLOC_TLSF=y
+CONFIG_KALLSYMS=y
+CONFIG_PROMPT="R-Pi> "
+CONFIG_HUSH_FANCY_PROMPT=y
+CONFIG_CMDLINE_EDITING=y
+CONFIG_AUTO_COMPLETE=y
+CONFIG_MENU=y
+CONFIG_BOOTM_SHOW_TYPE=y
+CONFIG_BOOTM_VERBOSE=y
+CONFIG_BOOTM_INITRD=y
+CONFIG_BOOTM_OFTREE=y
+CONFIG_BLSPEC=y
+CONFIG_CONSOLE_ACTIVATE_ALL=y
+CONFIG_CONSOLE_ALLOW_COLOR=y
+CONFIG_PBL_CONSOLE=y
+CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y
+CONFIG_CMD_DMESG=y
+CONFIG_LONGHELP=y
+CONFIG_CMD_IOMEM=y
+CONFIG_CMD_IMD=y
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_REGULATOR=y
+CONFIG_CMD_GO=y
+CONFIG_CMD_LOADB=y
+CONFIG_CMD_LOADY=y
+CONFIG_CMD_RESET=y
+CONFIG_CMD_UIMAGE=y
+CONFIG_CMD_PARTITION=y
+CONFIG_CMD_EXPORT=y
+CONFIG_CMD_DEFAULTENV=y
+CONFIG_CMD_LOADENV=y
+CONFIG_CMD_PRINTENV=y
+CONFIG_CMD_MAGICVAR=y
+CONFIG_CMD_MAGICVAR_HELP=y
+CONFIG_CMD_SAVEENV=y
+CONFIG_CMD_CMP=y
+CONFIG_CMD_FILETYPE=y
+CONFIG_CMD_LN=y
+CONFIG_CMD_MD5SUM=y
+CONFIG_CMD_SHA1SUM=y
+CONFIG_CMD_SHA256SUM=y
+CONFIG_CMD_UNCOMPRESS=y
+CONFIG_CMD_LET=y
+CONFIG_CMD_MSLEEP=y
+CONFIG_CMD_SLEEP=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MIITOOL=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_ECHO_E=y
+CONFIG_CMD_EDIT=y
+CONFIG_CMD_LOGIN=y
+CONFIG_CMD_MENU=y
+CONFIG_CMD_MENU_MANAGEMENT=y
+CONFIG_CMD_PASSWD=y
+CONFIG_CMD_READLINE=y
+CONFIG_CMD_TIMEOUT=y
+CONFIG_CMD_CRC=y
+CONFIG_CMD_CRC_CMP=y
+CONFIG_CMD_MM=y
+CONFIG_CMD_CLK=y
+CONFIG_CMD_DETECT=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_LED=y
+CONFIG_CMD_LED_TRIGGER=y
+CONFIG_CMD_WD=y
+CONFIG_CMD_OF_NODE=y
+CONFIG_CMD_OF_PROPERTY=y
+CONFIG_CMD_OFTREE=y
+CONFIG_CMD_TIME=y
+CONFIG_NET=y
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_DRIVER_SERIAL_NS16550=y
+CONFIG_NET_USB=y
+CONFIG_NET_USB_SMSC95XX=y
+CONFIG_I2C=y
+CONFIG_I2C_BCM283X=y
+CONFIG_USB_HOST=y
+CONFIG_USB_DWC2_HOST=y
+CONFIG_USB_DWC2_GADGET=y
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_AUTOSTART is not set
+CONFIG_MCI=y
+CONFIG_MCI_BCM283X=y
+CONFIG_MCI_BCM283X_SDHOST=y
+CONFIG_LED=y
+CONFIG_LED_GPIO=y
+CONFIG_LED_GPIO_OF=y
+CONFIG_LED_TRIGGERS=y
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_BCM2835=y
+CONFIG_GPIO_RASPBERRYPI_EXP=y
+CONFIG_PINCTRL_BCM283X=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED=y
+CONFIG_GENERIC_PHY=y
+CONFIG_USB_NOP_XCEIV=y
+CONFIG_FS_EXT4=y
+CONFIG_FS_TFTP=y
+CONFIG_FS_NFS=y
+CONFIG_FS_FAT=y
+CONFIG_FS_FAT_WRITE=y
+CONFIG_FS_FAT_LFN=y
+CONFIG_ZLIB=y
diff --git a/arch/arm/cpu/Kconfig b/arch/arm/cpu/Kconfig
index 0a493754a4..9b5a833abf 100644
--- a/arch/arm/cpu/Kconfig
+++ b/arch/arm/cpu/Kconfig
@@ -87,7 +87,6 @@ config CPU_V7
config CPU_V8
bool
select CPU_64v8
- select CPU_SUPPORTS_64BIT_KERNEL
select ARM_EXCEPTIONS
select GENERIC_FIND_NEXT_BIT
select ARCH_HAS_STACK_DUMP
@@ -156,12 +155,6 @@ config CACHE_L2X0
bool "Enable L2x0 PrimeCell"
depends on MMU && ARCH_HAS_L2X0
-config SYS_SUPPORTS_32BIT_KERNEL
- bool
-
-config SYS_SUPPORTS_64BIT_KERNEL
- bool
-
config CPU_SUPPORTS_32BIT_KERNEL
bool
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 723bd2a123..0c7e43e226 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -114,6 +114,7 @@ lwl-$(CONFIG_MACH_RPI) += bcm2835-rpi.dtb.o
lwl-$(CONFIG_MACH_RPI2) += bcm2836-rpi-2.dtb.o
lwl-$(CONFIG_MACH_RPI3) += bcm2837-rpi-3.dtb.o
lwl-$(CONFIG_MACH_RPI_CM3) += bcm2837-rpi-cm3.dtb.o
+lwl-$(CONFIG_MACH_RPI4) += bcm2711-rpi-4.dtb.o
lwl-$(CONFIG_MACH_SABRELITE) += imx6q-sabrelite.dtb.o imx6dl-sabrelite.dtb.o
lwl-$(CONFIG_MACH_SABRESD) += imx6q-sabresd.dtb.o imx6qp-sabresd.dtb.o
lwl-$(CONFIG_MACH_FREESCALE_IMX6SX_SABRESDB) += imx6sx-sdb.dtb.o
diff --git a/arch/arm/dts/bcm2711-rpi-4.dts b/arch/arm/dts/bcm2711-rpi-4.dts
new file mode 100644
index 0000000000..3c0caa73f8
--- /dev/null
+++ b/arch/arm/dts/bcm2711-rpi-4.dts
@@ -0,0 +1,18 @@
+#include <arm64/broadcom/bcm2711-rpi-4-b.dts>
+
+&{/memory@0} {
+ reg = <0x0 0x0 0x0>;
+};
+
+&sdhci {
+ /* no use for SDIO WiFi in barebox */
+ status = "disabled";
+};
+
+&uart1 {
+ /* VPU core clock is reported at 200MHz, but needs to be 500Mhz
+ * for ns16550 driver to set correct baudrate. Until that's
+ * figured out, hardcode clock frequency to the expected value
+ */
+ clock-frequency = <500000000>;
+};
diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h
index 7dc027c174..c3fc057650 100644
--- a/arch/arm/include/asm/cputype.h
+++ b/arch/arm/include/asm/cputype.h
@@ -6,6 +6,23 @@
#include <linux/stringify.h>
#include <linux/kernel.h>
+#ifdef CONFIG_CPU_64v8
+
+#define CPUID_ID midr_el1
+#define CPUID_CACHETYPE ctr_el0
+#define CPUID_MPIDR mpidr_el1
+
+#define read_cpuid(reg) \
+ ({ \
+ unsigned int __val; \
+ asm("mrs %0, " __stringify(reg) \
+ : "=r" (__val) \
+ : \
+ : "cc"); \
+ __val; \
+ })
+#else
+
#define CPUID_ID 0
#define CPUID_CACHETYPE 1
#define CPUID_TCM 2
@@ -27,8 +44,6 @@
#define CPUID_EXT_ISAR4 "c2, 4"
#define CPUID_EXT_ISAR5 "c2, 5"
-extern unsigned int processor_id;
-
#define read_cpuid(reg) \
({ \
unsigned int __val; \
@@ -47,6 +62,9 @@ extern unsigned int processor_id;
: "cc"); \
__val; \
})
+#endif
+
+extern unsigned int processor_id;
/*
* The CPU ID never changes at run time, so we might as well tell the
diff --git a/arch/arm/include/asm/dma.h b/arch/arm/include/asm/dma.h
index 226b1c1464..75a6c1ad86 100644
--- a/arch/arm/include/asm/dma.h
+++ b/arch/arm/include/asm/dma.h
@@ -10,6 +10,7 @@ static inline void *dma_alloc(size_t size)
}
#ifndef CONFIG_MMU
+#define dma_alloc_coherent dma_alloc_coherent
static inline void *dma_alloc_coherent(size_t size, dma_addr_t *dma_handle)
{
void *ret = xmemalign(4096, size);
@@ -21,22 +22,26 @@ static inline void *dma_alloc_coherent(size_t size, dma_addr_t *dma_handle)
return ret;
}
+#define dma_alloc_writecombine dma_alloc_writecombine
static inline void *dma_alloc_writecombine(size_t size, dma_addr_t *dma_handle)
{
return dma_alloc_coherent(size, dma_handle);
}
+#define dma_free_coherent dma_free_coherent
static inline void dma_free_coherent(void *mem, dma_addr_t dma_handle,
size_t size)
{
free(mem);
}
+#define dma_sync_single_for_cpu dma_sync_single_for_cpu
static inline void dma_sync_single_for_cpu(dma_addr_t address, size_t size,
enum dma_data_direction dir)
{
}
+#define dma_sync_single_for_device dma_sync_single_for_device
static inline void dma_sync_single_for_device(dma_addr_t address, size_t size,
enum dma_data_direction dir)
{
diff --git a/arch/arm/include/asm/system_info.h b/arch/arm/include/asm/system_info.h
index c7f9987748..5a84fde75b 100644
--- a/arch/arm/include/asm/system_info.h
+++ b/arch/arm/include/asm/system_info.h
@@ -44,6 +44,12 @@
#define CPU_IS_CORTEX_A15 0x410fc0f0
#define CPU_IS_CORTEX_A15_MASK 0xff0ffff0
+#define CPU_IS_CORTEX_A53 0x410fd030
+#define CPU_IS_CORTEX_A53_MASK 0xff0ffff0
+
+#define CPU_IS_CORTEX_A72 0x410fd080
+#define CPU_IS_CORTEX_A72_MASK 0xff0ffff0
+
#define CPU_IS_PXA250 0x69052100
#define CPU_IS_PXA250_MASK 0xfffff7f0
diff --git a/arch/arm/mach-bcm283x/Kconfig b/arch/arm/mach-bcm283x/Kconfig
index 75acee8dad..48209fb5c6 100644
--- a/arch/arm/mach-bcm283x/Kconfig
+++ b/arch/arm/mach-bcm283x/Kconfig
@@ -8,30 +8,51 @@ config ARCH_TEXT_BASE
config MACH_RPI_COMMON
bool
+ select ARM_USE_COMPRESSED_DTB
+
+config MACH_RPI_AARCH_32_64
+ select MACH_RPI_COMMON
+ select CPU_V7 if 32BIT
+ select ARM_SECURE_MONITOR if 32BIT
+ select CPU_V8 if 64BIT
+ select BOARD_ARM_GENERIC_DT if 64BIT
+ bool
+ help
+ Select this from CPUs that support both AArch32 and AArch64
+ execution modes. barebox can be compiled for only one of
+ these states, depending on the value of
+ CONFIG_32BIT/CONFIG_64BIT.
menu "select Broadcom BCM283X boards to be built"
config MACH_RPI
bool "RaspberryPi (BCM2835/ARM1176JZF-S)"
+ depends on 32BIT
select CPU_V6
select MACH_RPI_COMMON
config MACH_RPI2
bool "RaspberryPi 2 (BCM2836/CORTEX-A7)"
+ depends on 32BIT
select CPU_V7
select MACH_RPI_COMMON
config MACH_RPI3
bool "RaspberryPi 3 (BCM2837/CORTEX-A53)"
- select CPU_V7
+ select MACH_RPI_AARCH_32_64
select MACH_RPI_COMMON
- select ARM_SECURE_MONITOR
+ depends on 32BIT || (64BIT && !MMU_EARLY)
config MACH_RPI_CM3
bool "RaspberryPi Compute Module 3 (BCM2837/CORTEX-A53)"
- select CPU_V7
+ select MACH_RPI_AARCH_32_64
+ select MACH_RPI_COMMON
+ depends on 32BIT || (64BIT && !MMU_EARLY)
+
+config MACH_RPI4
+ bool "RaspberryPi 4 (BCM2711/CORTEX-A72)"
+ select MACH_RPI_AARCH_32_64
select MACH_RPI_COMMON
- select ARM_SECURE_MONITOR
endmenu
diff --git a/arch/arm/mach-bcm283x/Makefile b/arch/arm/mach-bcm283x/Makefile
index e5ef78af97..53343cec8c 100644
--- a/arch/arm/mach-bcm283x/Makefile
+++ b/arch/arm/mach-bcm283x/Makefile
@@ -1,3 +1,3 @@
# SPDX-License-Identifier: GPL-2.0-only
-obj-y += core.o mbox.o
+obj-pbl-y += mbox.o core.o
diff --git a/arch/arm/mach-bcm283x/core.c b/arch/arm/mach-bcm283x/core.c
index f2528cf1f1..40882fb6d6 100644
--- a/arch/arm/mach-bcm283x/core.c
+++ b/arch/arm/mach-bcm283x/core.c
@@ -1,40 +1,29 @@
-/*
- * Author: Carlo Caione <carlo@carlocaione.org>
- *
- * Based on mach-nomadik
- * Copyright (C) 2009 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
+// SPDX-License-Identifier: GPL-2.0-only
-#include <common.h>
-#include <init.h>
-
-#include <linux/clk.h>
-#include <linux/clkdev.h>
-#include <linux/err.h>
-
-#include <io.h>
-#include <asm/armlinux.h>
-#include <linux/sizes.h>
-
-#include <mach/platform.h>
+#include <linux/types.h>
#include <mach/core.h>
-#include <linux/amba/bus.h>
+#include <asm/system_info.h>
-void bcm2835_add_device_sdram(u32 size)
+void __iomem *bcm2835_get_mmio_base_by_cpuid(void)
{
- if (!size)
- size = get_ram_size((ulong *) BCM2835_SDRAM_BASE, SZ_128M);
+ static u32 cpuid;
+
+ if (!cpuid) {
+ cpuid = read_cpuid_id();
+ pr_debug("ARM CPUID: %08x\n", cpuid);
+ }
+
+ /* We know ARM1167, Cortex A-7, A-53 and A-72 CPUID mask is identical */
+ switch(cpuid & CPU_IS_ARM1176_MASK) {
+ case CPU_IS_ARM1176: /* bcm2835 */
+ return IOMEM(0x20000000);
+ case CPU_IS_CORTEX_A7: /* bcm2836 */
+ case CPU_IS_CORTEX_A53: /* bcm2837 */
+ return IOMEM(0x3f000000);
+ case CPU_IS_CORTEX_A72: /* bcm2711 */
+ return IOMEM(0xfe000000);
+ }
- arm_add_mem_device("ram0", BCM2835_SDRAM_BASE, size);
+ pr_err("Couldn't determine rpi by CPUID %08x\n", cpuid);
+ return NULL;
}
diff --git a/arch/arm/mach-bcm283x/include/mach/core.h b/arch/arm/mach-bcm283x/include/mach/core.h
index a1c47f9154..c8547351a3 100644
--- a/arch/arm/mach-bcm283x/include/mach/core.h
+++ b/arch/arm/mach-bcm283x/include/mach/core.h
@@ -1,28 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2009 Carlo Caione <carlo@carlocaione.org>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
*/
#ifndef __BCM2835_CORE_H__
#define __BCM2835_CORE_H__
+#include <common.h>
+#include <linux/types.h>
+#include <linux/sizes.h>
+#include <asm/memory.h>
#include <mach/platform.h>
-void bcm2835_add_device_sdram(u32 size);
+static void inline bcm2835_add_device_sdram(u32 size)
+{
+ arm_add_mem_device("ram0", BCM2835_SDRAM_BASE, size);
+}
static void inline bcm2835_register_fb(void)
{
add_generic_device("bcm2835_fb", 0, NULL, 0, 0, 0, NULL);
}
+void __iomem *bcm2835_get_mmio_base_by_cpuid(void);
+
#endif
diff --git a/arch/arm/mach-bcm283x/include/mach/debug_ll.h b/arch/arm/mach-bcm283x/include/mach/debug_ll.h
index 4bfa5abc7c..fdb63b4f5a 100644
--- a/arch/arm/mach-bcm283x/include/mach/debug_ll.h
+++ b/arch/arm/mach-bcm283x/include/mach/debug_ll.h
@@ -18,6 +18,7 @@
#define __MACH_BCM2835_DEBUG_LL_H__
#include <mach/platform.h>
+#include <io.h>
#ifdef CONFIG_DEBUG_RPI1_UART
@@ -66,6 +67,31 @@ static inline void debug_ll_init(void)
debug_ll_ns16550_init(divisor);
}
+#elif defined CONFIG_DEBUG_RPI4_MINI_UART
+
+static inline uint8_t debug_ll_read_reg(int reg)
+{
+ return readb(BCM2711_MINIUART_BASE + (reg << 2));
+}
+
+static inline void debug_ll_write_reg(int reg, uint8_t val)
+{
+ writeb(val, BCM2711_MINIUART_BASE + (reg << 2));
+}
+
+#include <debug_ll/ns16550.h>
+
+static inline void debug_ll_init(void)
+{
+ /* Configured by ROM */
+}
+
+#else
+
+static inline void debug_ll_init(void)
+{
+}
+
#endif
#endif /* __MACH_BCM2835_DEBUG_LL_H__ */
diff --git a/arch/arm/mach-bcm283x/include/mach/mbox.h b/arch/arm/mach-bcm283x/include/mach/mbox.h
index a9f06512bc..92cadba62c 100644
--- a/arch/arm/mach-bcm283x/include/mach/mbox.h
+++ b/arch/arm/mach-bcm283x/include/mach/mbox.h
@@ -171,7 +171,10 @@ struct bcm2835_mbox_tag_hdr {
#define BCM2837B0_BOARD_REV_3B_PLUS 0x0d
#define BCM2837B0_BOARD_REV_3A_PLUS 0x0e
#define BCM2837B0_BOARD_REV_CM3_PLUS 0x10
+#define BCM2711_BOARD_REV_4_B 0x11
#define BCM2837B0_BOARD_REV_ZERO_2 0x12
+#define BCM2711_BOARD_REV_400 0x13
+#define BCM2711_BOARD_REV_CM4 0x14
struct bcm2835_mbox_tag_get_board_rev {
struct bcm2835_mbox_tag_hdr tag_hdr;
@@ -273,6 +276,7 @@ struct bcm2835_mbox_tag_set_power_state {
#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;
diff --git a/arch/arm/mach-bcm283x/include/mach/platform.h b/arch/arm/mach-bcm283x/include/mach/platform.h
index 310f2463f2..b957ac8de3 100644
--- a/arch/arm/mach-bcm283x/include/mach/platform.h
+++ b/arch/arm/mach-bcm283x/include/mach/platform.h
@@ -31,9 +31,10 @@
#define BCM2835_CACHELINE_SIZE 64
#define BCM2835_PL011_BASE 0x20201000
-#define BCM2836_PL011_BASE 0x3f201000
+#define BCM2836_PL011_BASE 0x3f201000UL
#define BCM2835_MINIUART_BASE 0x20215040
-#define BCM2836_MINIUART_BASE 0x3f215040
+#define BCM2836_MINIUART_BASE 0x3f215040UL
+#define BCM2711_MINIUART_BASE 0xfe215040UL
#endif
diff --git a/arch/arm/mach-bcm283x/mbox.c b/arch/arm/mach-bcm283x/mbox.c
index 4b14afcfe4..4959a1a652 100644
--- a/arch/arm/mach-bcm283x/mbox.c
+++ b/arch/arm/mach-bcm283x/mbox.c
@@ -14,13 +14,20 @@
#include <init.h>
#include <io.h>
#include <of_address.h>
+#include <pbl.h>
#include <mach/mbox.h>
+#include <mach/core.h>
#define TIMEOUT (MSECOND * 1000)
static void __iomem *mbox_base;
+#ifdef __PBL__
+#define is_timeout_non_interruptible(start, timeout) ((void)start, 0)
+#define get_time_ns() 0
+#endif
+
static int bcm2835_mbox_call_raw(u32 chan, struct bcm2835_mbox_hdr *buffer,
u32 *recv)
{
@@ -109,19 +116,20 @@ static void dump_buf(struct bcm2835_mbox_hdr *buffer)
}
#endif
-static int bcm2835_mbox_probe(void)
+static void __iomem *bcm2835_mbox_probe(void)
{
struct device_node *mbox_node;
+ if (IN_PBL)
+ return bcm2835_get_mmio_base_by_cpuid() + 0xb880;
+
mbox_node = of_find_compatible_node(NULL, NULL, "brcm,bcm2835-mbox");
if (!mbox_node) {
pr_err("Missing mbox node\n");
- return -ENOENT;
+ return NULL;
}
- mbox_base = of_iomap(mbox_node, 0);
-
- return 0;
+ return of_iomap(mbox_node, 0);
}
int bcm2835_mbox_call_prop(u32 chan, struct bcm2835_mbox_hdr *buffer)
@@ -132,9 +140,9 @@ int bcm2835_mbox_call_prop(u32 chan, struct bcm2835_mbox_hdr *buffer)
int tag_index;
if (!mbox_base) {
- ret = bcm2835_mbox_probe();
- if (ret)
- return ret;
+ mbox_base = bcm2835_mbox_probe();
+ if (!mbox_base)
+ return -ENOENT;
}
pr_debug("mbox: TX buffer\n");
@@ -143,7 +151,7 @@ int bcm2835_mbox_call_prop(u32 chan, struct bcm2835_mbox_hdr *buffer)
ret = bcm2835_mbox_call_raw(chan, buffer, &rbuffer);
if (ret)
return ret;
- if (rbuffer != (u32)buffer) {
+ if (rbuffer != (uintptr_t)buffer) {
pr_err("mbox: Response buffer mismatch\n");
return -EIO;
}
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 6b962dcf7e..9ff549ac83 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -177,7 +177,7 @@ config ARCH_IMX8M
select CPU_V8
select PINCTRL_IMX_IOMUX_V3
select OFTREE
- select SYS_SUPPORTS_64BIT_KERNEL
+ select CPU_SUPPORTS_64BIT_KERNEL
select COMMON_CLK_OF_PROVIDER
select ARCH_HAS_FEC_IMX
select HW_HAS_PCI
diff --git a/arch/arm/mach-layerscape/Kconfig b/arch/arm/mach-layerscape/Kconfig
index bdd7d0dbfe..943a474808 100644
--- a/arch/arm/mach-layerscape/Kconfig
+++ b/arch/arm/mach-layerscape/Kconfig
@@ -17,7 +17,7 @@ config ARCH_LAYERSCAPE_PPA
config ARCH_LS1046
select CPU_V8
- select SYS_SUPPORTS_64BIT_KERNEL
+ select CPU_SUPPORTS_64BIT_KERNEL
bool
config MACH_LS1046ARDB
diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig
index 4b6dfd2c17..1f3ba706ee 100644
--- a/arch/arm/mach-rockchip/Kconfig
+++ b/arch/arm/mach-rockchip/Kconfig
@@ -30,7 +30,7 @@ config ARCH_RK3288
config ARCH_ROCKCHIP_V8
bool
select CPU_V8
- select SYS_SUPPORTS_64BIT_KERNEL
+ select CPU_SUPPORTS_64BIT_KERNEL
select ARM_ATF
select RELOCATABLE
diff --git a/arch/kvx/include/asm/dma.h b/arch/kvx/include/asm/dma.h
index a7ecf279a9..5bf601307e 100644
--- a/arch/kvx/include/asm/dma.h
+++ b/arch/kvx/include/asm/dma.h
@@ -16,6 +16,7 @@ static inline void *dma_alloc(size_t size)
return xmemalign(64, ALIGN(size, 64));
}
+#define dma_alloc_coherent dma_alloc_coherent
static inline void *dma_alloc_coherent(size_t size, dma_addr_t *dma_handle)
{
BUILD_BUG_ON_MSG(1, "dma_alloc_coherent not supported: "
@@ -23,6 +24,7 @@ static inline void *dma_alloc_coherent(size_t size, dma_addr_t *dma_handle)
return NULL;
}
+#define dma_free_coherent dma_free_coherent
static inline void dma_free_coherent(void *mem, dma_addr_t dma_handle,
size_t size)
{
diff --git a/arch/mips/include/asm/dma-mapping.h b/arch/mips/include/asm/dma-mapping.h
index 19d5b3f7bc..8e6ea08168 100644
--- a/arch/mips/include/asm/dma-mapping.h
+++ b/arch/mips/include/asm/dma-mapping.h
@@ -10,6 +10,7 @@
#include <malloc.h>
#include <asm/io.h>
+#define dma_alloc_coherent dma_alloc_coherent
static inline void *dma_alloc_coherent(size_t size, dma_addr_t *dma_handle)
{
void *ret;
@@ -26,6 +27,7 @@ static inline void *dma_alloc_coherent(size_t size, dma_addr_t *dma_handle)
return (void *)CKSEG1ADDR(ret);
}
+#define dma_free_coherent dma_free_coherent
static inline void dma_free_coherent(void *vaddr, dma_addr_t dma_handle,
size_t size)
{
diff --git a/arch/sandbox/include/asm/dma.h b/arch/sandbox/include/asm/dma.h
index 34c0fc5190..958d10e2a1 100644
--- a/arch/sandbox/include/asm/dma.h
+++ b/arch/sandbox/include/asm/dma.h
@@ -18,6 +18,7 @@ static inline void *dma_alloc(size_t size)
return xmemalign(64, ALIGN(size, 64));
}
+#define dma_alloc_coherent dma_alloc_coherent
static inline void *dma_alloc_coherent(size_t size, dma_addr_t *dma_handle)
{
void *ret = xmemalign(4096, size);
@@ -29,22 +30,26 @@ static inline void *dma_alloc_coherent(size_t size, dma_addr_t *dma_handle)
return ret;
}
+#define dma_alloc_writecombine dma_alloc_writecombine
static inline void *dma_alloc_writecombine(size_t size, dma_addr_t *dma_handle)
{
return dma_alloc_coherent(size, dma_handle);
}
+#define dma_free_coherent dma_free_coherent
static inline void dma_free_coherent(void *mem, dma_addr_t dma_handle,
size_t size)
{
free(mem);
}
+#define dma_sync_single_for_cpu dma_sync_single_for_cpu
static inline void dma_sync_single_for_cpu(dma_addr_t address, size_t size,
enum dma_data_direction dir)
{
}
+#define dma_sync_single_for_device dma_sync_single_for_device
static inline void dma_sync_single_for_device(dma_addr_t address, size_t size,
enum dma_data_direction dir)
{
diff --git a/arch/x86/include/asm/dma.h b/arch/x86/include/asm/dma.h
index 8a3b044f3a..90791ecf3e 100644
--- a/arch/x86/include/asm/dma.h
+++ b/arch/x86/include/asm/dma.h
@@ -13,6 +13,7 @@
* x86 is cache coherent, so we need not do anything special here
*/
+#define dma_alloc_coherent dma_alloc_coherent
static inline void *dma_alloc_coherent(size_t size, dma_addr_t *dma_handle)
{
void *ret = xmemalign(4096, size);
@@ -24,17 +25,20 @@ static inline void *dma_alloc_coherent(size_t size, dma_addr_t *dma_handle)
return ret;
}
+#define dma_free_coherent dma_free_coherent
static inline void dma_free_coherent(void *mem, dma_addr_t dma_handle,
size_t size)
{
free(mem);
}
+#define dma_sync_single_for_cpu dma_sync_single_for_cpu
static inline void dma_sync_single_for_cpu(dma_addr_t address, size_t size,
enum dma_data_direction dir)
{
}
+#define dma_sync_single_for_device dma_sync_single_for_device
static inline void dma_sync_single_for_device(dma_addr_t address, size_t size,
enum dma_data_direction dir)
{
diff --git a/common/Kconfig b/common/Kconfig
index 3ff45d6c9d..2292e7bcea 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -1418,6 +1418,13 @@ config DEBUG_RPI3_MINI_UART
Say Y here if you want low-level debugging support on
RaspberryPi 3 board mini UART.
+config DEBUG_RPI4_MINI_UART
+ bool "RaspberryPi 4 mini UART"
+ depends on ARCH_BCM283X
+ help
+ Say Y here if you want low-level debugging support on
+ RaspberryPi 4 board mini UART.
+
config DEBUG_ERIZO
bool "Erizo ns16550 port"
depends on SOC_ERIZO
diff --git a/drivers/clk/clk-rpi.c b/drivers/clk/clk-rpi.c
index 59ae8e59ba..71badc04c0 100644
--- a/drivers/clk/clk-rpi.c
+++ b/drivers/clk/clk-rpi.c
@@ -40,10 +40,29 @@ static struct clk *rpi_register_firmware_clock(u32 clock_id, const char *name)
return clk_fixed(name, msg->get_clock_rate.body.resp.rate_hz);
}
-static int bcm2835_cprman_probe(struct device_d *dev)
+static int bcm2835_cprman_init(struct device_d *dev)
{
struct clk *clk_cs;
+ clk_cs = clk_fixed("bcm2835-cs", 1 * 1000 * 1000);
+ clk_register_clkdev(clk_cs, NULL, "bcm2835-cs");
+
+ return 0;
+}
+
+static int rpi_cprman_probe(struct device_d *dev)
+{
+ int (*init)(struct device_d *dev);
+
+ init = device_get_match_data(dev);
+ if (init) {
+ int ret;
+
+ ret = init(dev);
+ if (ret)
+ return ret;
+ }
+
clks[BCM2835_CLOCK_EMMC] =
rpi_register_firmware_clock(BCM2835_MBOX_CLOCK_ID_EMMC,
"bcm2835_mci0");
@@ -56,12 +75,15 @@ static int bcm2835_cprman_probe(struct device_d *dev)
if (IS_ERR(clks[BCM2835_CLOCK_VPU]))
return PTR_ERR(clks[BCM2835_CLOCK_VPU]);
+ clks[BCM2711_CLOCK_EMMC2] =
+ rpi_register_firmware_clock(BCM2835_MBOX_CLOCK_ID_EMMC2,
+ "bcm2711_emmc2");
+ if (IS_ERR(clks[BCM2711_CLOCK_EMMC2]))
+ return PTR_ERR(clks[BCM2711_CLOCK_EMMC2]);
+
clks[BCM2835_CLOCK_UART] = clk_fixed("uart0-pl0110", 48 * 1000 * 1000);
clk_register_clkdev(clks[BCM2835_CLOCK_UART], NULL, "uart0-pl0110");
- clk_cs = clk_fixed("bcm2835-cs", 1 * 1000 * 1000);
- clk_register_clkdev(clk_cs, NULL, "bcm2835-cs");
-
clk_data.clks = clks;
clk_data.clk_num = BCM2711_CLOCK_END;
of_clk_add_provider(dev->device_node, of_clk_src_onecell_get, &clk_data);
@@ -70,16 +92,14 @@ static int bcm2835_cprman_probe(struct device_d *dev)
}
static __maybe_unused struct of_device_id bcm2835_cprman_dt_ids[] = {
- {
- .compatible = "brcm,bcm2835-cprman",
- }, {
- /* sentinel */
- }
+ { .compatible = "brcm,bcm2835-cprman", .data = bcm2835_cprman_init },
+ { .compatible = "brcm,bcm2711-cprman" },
+ { /* sentinel */ }
};
static struct driver_d bcm2835_cprman_driver = {
- .probe = bcm2835_cprman_probe,
- .name = "bcm2835-cprman",
+ .probe = rpi_cprman_probe,
+ .name = "raspberrypi-cprman",
.of_compatible = DRV_OF_COMPAT(bcm2835_cprman_dt_ids),
};
core_platform_driver(bcm2835_cprman_driver);
diff --git a/drivers/clocksource/bcm2835.c b/drivers/clocksource/bcm2835.c
index d84341fc40..d5d3e3477d 100644
--- a/drivers/clocksource/bcm2835.c
+++ b/drivers/clocksource/bcm2835.c
@@ -28,7 +28,8 @@ static uint64_t stc_read_cycles(void)
static struct clocksource bcm2835_stc = {
.read = stc_read_cycles,
.mask = CLOCKSOURCE_MASK(32),
- .priority = 80,
+ /* Give the architected timer precedence on AArch64 */
+ .priority = IS_ENABLED(CONFIG_CPU_V8) ? 60 : 80,
};
static int bcm2835_cs_probe(struct device_d *dev)
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 58f8656067..766aa5edfa 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -17,6 +17,10 @@ config I2C_AT91
bool "AT91 I2C Master driver"
depends on ARCH_AT91
+config I2C_BCM283X
+ bool "BCM283X I2C Master driver"
+ depends on ARCH_BCM283X || COMPILE_TEST
+
config I2C_IMX
bool "MPC85xx/MPC5200/i.MX I2C Master driver"
depends on ARCH_IMX || ARCH_MPC85XX || ARCH_MPC5200 || ARCH_LAYERSCAPE
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index a8661f605e..a1ab46fb28 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -1,5 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_I2C_AT91) += i2c-at91.o
+obj-$(CONFIG_I2C_BCM283X) += i2c-bcm283x.o
obj-$(CONFIG_I2C_GPIO) += i2c-gpio.o
obj-$(CONFIG_I2C_IMX) += i2c-imx.o
lwl-$(CONFIG_I2C_IMX_EARLY) += i2c-imx-early.o
diff --git a/drivers/i2c/busses/i2c-bcm283x.c b/drivers/i2c/busses/i2c-bcm283x.c
new file mode 100644
index 0000000000..097f73d983
--- /dev/null
+++ b/drivers/i2c/busses/i2c-bcm283x.c
@@ -0,0 +1,327 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * I2C bus driver for the BSC peripheral on Broadcom's bcm283x family of SoCs
+ *
+ * Based on documentation published by Raspberry Pi foundation and the kernel
+ * driver written by Stephen Warren.
+ *
+ * Copyright (C) Stephen Warren
+ * Copyright (C) 2022 Daniel BrĂ¡t
+ */
+
+#include <common.h>
+#include <driver.h>
+#include <malloc.h>
+#include <i2c/i2c.h>
+#include <i2c/i2c-algo-bit.h>
+#include <linux/iopoll.h>
+#include <linux/clk.h>
+#include <init.h>
+#include <of_address.h>
+
+// BSC C (Control) register
+#define BSC_C_READ BIT(0)
+#define BSC_C_CLEAR1 BIT(4)
+#define BSC_C_CLEAR2 BIT(5)
+#define BSC_C_ST BIT(7)
+#define BSC_C_INTD BIT(8)
+#define BSC_C_INTT BIT(9)
+#define BSC_C_INTR BIT(10)
+#define BSC_C_I2CEN BIT(15)
+
+// BSC S (Status) register
+#define BSC_S_TA BIT(0)
+#define BSC_S_DONE BIT(1)
+#define BSC_S_TXW BIT(2)
+#define BSC_S_RXR BIT(3)
+#define BSC_S_TXD BIT(4)
+#define BSC_S_RXD BIT(5)
+#define BSC_S_TXE BIT(6)
+#define BSC_S_RXF BIT(7)
+#define BSC_S_ERR BIT(8)
+#define BSC_S_CLKT BIT(9)
+
+// BSC A (Address) register
+#define BSC_A_MASK 0x7f
+
+// Constants
+#define BSC_CDIV_MIN 0x0002
+#define BSC_CDIV_MAX 0xfffe
+#define BSC_FIFO_SIZE 16U
+
+struct __packed bcm283x_i2c_regs {
+ u32 c;
+ u32 s;
+ u32 dlen;
+ u32 a;
+ u32 fifo;
+ u32 div;
+ u32 del;
+ u32 clkt;
+};
+
+struct bcm283x_i2c {
+ struct i2c_adapter adapter;
+ struct clk *mclk;
+ struct bcm283x_i2c_regs __iomem *regs;
+ u32 bitrate;
+};
+
+static inline struct bcm283x_i2c *to_bcm283x_i2c(struct i2c_adapter *adapter)
+{
+ return container_of(adapter, struct bcm283x_i2c, adapter);
+}
+
+static inline int bcm283x_i2c_init(struct bcm283x_i2c *bcm_i2c)
+{
+ struct device_d *dev = &bcm_i2c->adapter.dev;
+ u32 mclk_rate, cdiv, redl, fedl;
+
+ /*
+ * Reset control reg, flush FIFO, clear all flags and disable
+ * clock stretching
+ */
+ writel(0UL, &bcm_i2c->regs->c);
+ writel(BSC_C_CLEAR1, &bcm_i2c->regs->c);
+ writel(BSC_S_DONE | BSC_S_ERR | BSC_S_CLKT, &bcm_i2c->regs->s);
+ writel(0UL, &bcm_i2c->regs->clkt);
+
+ /*
+ * Set the divider based on the master clock frequency and the
+ * requested i2c bitrate
+ */
+ mclk_rate = clk_get_rate(bcm_i2c->mclk);
+ cdiv = DIV_ROUND_UP(mclk_rate, bcm_i2c->bitrate);
+ dev_dbg(dev, "bcm283x_i2c_init: mclk_rate=%u, cdiv=%08x\n",
+ mclk_rate, cdiv);
+ /* Note from kernel driver:
+ * Per the datasheet, the register is always interpreted as an even
+ * number, by rounding down. In other words, the LSB is ignored. So,
+ * if the LSB is set, increment the divider to avoid any issue.
+ */
+ if (cdiv & 1)
+ cdiv++;
+ if ((cdiv < BSC_CDIV_MIN) || (cdiv > BSC_CDIV_MAX)) {
+ dev_err(dev, "failed to calculate valid clock divider value\n");
+ return -EINVAL;
+ }
+ dev_dbg(dev, "bcm283x_i2c_init: cdiv adjusted to %04x\n", cdiv);
+ fedl = max(cdiv / 16, 1U);
+ redl = max(cdiv / 4, 1U);
+ dev_dbg(dev, "bcm283x_i2c_init: fedl=%04x, redl=%04x\n", fedl, redl);
+ writel(cdiv & 0xffff, &bcm_i2c->regs->div);
+ writel((fedl << 16) | redl, &bcm_i2c->regs->del);
+ dev_dbg(dev, "bcm283x_i2c_init: regs->div=%08x, regs->del=%08x\n",
+ readl(&bcm_i2c->regs->div), readl(&bcm_i2c->regs->del));
+
+ return 0;
+}
+
+/*
+ * Macro to calculate generous timeout for given bitrate and number of bytes
+ */
+#define calc_byte_timeout_us(bitrate) \
+ (3 * 9 * DIV_ROUND_UP(1000000, bitrate))
+#define calc_msg_timeout_us(bitrate, bytes) \
+ ((bytes + 1) * calc_byte_timeout_us(bitrate))
+
+static int bcm283x_i2c_msg_xfer(struct bcm283x_i2c *bcm_i2c,
+ struct i2c_msg *msg)
+{
+ int ret;
+ u32 reg_c, reg_s, reg_dlen, timeout;
+ struct device_d *dev = &bcm_i2c->adapter.dev;
+ bool msg_read = (msg->flags & I2C_M_RD) > 0;
+ bool msg_10bit = (msg->flags & I2C_M_TEN) > 0;
+ u16 buf_pos = 0;
+ u32 bytes_left = reg_dlen = msg->len;
+
+ if (msg_10bit && msg_read) {
+ timeout = calc_byte_timeout_us(bcm_i2c->bitrate);
+ writel(1UL, &bcm_i2c->regs->dlen);
+ writel(msg->addr & 0xff, &bcm_i2c->regs->fifo);
+ writel(((msg->addr >> 8) | 0x78) & BSC_A_MASK, &bcm_i2c->regs->a);
+ writel(BSC_C_ST | BSC_C_I2CEN, &bcm_i2c->regs->c);
+ ret = readl_poll_timeout(&bcm_i2c->regs->s, reg_s,
+ reg_s & (BSC_S_TA | BSC_S_ERR), timeout);
+
+ if (ret) {
+ dev_err(dev, "timeout: 10bit read initilization\n");
+ return ret;
+ }
+ if (reg_s & BSC_S_ERR)
+ goto nack;
+
+ } else if (msg_10bit) {
+ reg_dlen++;
+ writel(msg->addr & 0xff, &bcm_i2c->regs->fifo);
+ writel(((msg->addr >> 8) | 0x78) & BSC_A_MASK, &bcm_i2c->regs->a);
+ } else {
+ writel(msg->addr & BSC_A_MASK, &bcm_i2c->regs->a);
+ }
+
+ writel(reg_dlen, &bcm_i2c->regs->dlen);
+ reg_c = BSC_C_ST | BSC_C_I2CEN;
+ if (msg_read)
+ reg_c |= BSC_C_READ;
+ writel(reg_c, &bcm_i2c->regs->c);
+
+ if (msg_read) {
+ /*
+ * Read out data from FIFO as soon as it is available
+ */
+ timeout = calc_byte_timeout_us(bcm_i2c->bitrate);
+ for (; bytes_left; bytes_left--) {
+ ret = readl_poll_timeout(&bcm_i2c->regs->s, reg_s,
+ reg_s & (BSC_S_RXD | BSC_S_ERR),
+ timeout);
+
+ if (ret) {
+ dev_err(dev, "timeout: waiting for data in FIFO\n");
+ return ret;
+ }
+ if (reg_s & BSC_S_ERR)
+ goto nack;
+
+ msg->buf[buf_pos++] = (u8) readl(&bcm_i2c->regs->fifo);
+ }
+ } else {
+ timeout = calc_byte_timeout_us(bcm_i2c->bitrate);
+ /*
+ * Feed data to FIFO as soon as there is space for them
+ */
+ for (; bytes_left; bytes_left--) {
+ ret = readl_poll_timeout(&bcm_i2c->regs->s, reg_s,
+ reg_s & (BSC_S_TXD | BSC_S_ERR),
+ timeout);
+
+ if (ret) {
+ dev_err(dev, "timeout: waiting for space in FIFO\n");
+ return ret;
+ }
+ if (reg_s & BSC_S_ERR)
+ goto nack;
+
+ writel(msg->buf[buf_pos++], &bcm_i2c->regs->fifo);
+ }
+ }
+
+ /*
+ * Wait for the current transfer to finish and then flush FIFO
+ * and clear any flags so that we are ready for next msg
+ */
+ timeout = calc_msg_timeout_us(bcm_i2c->bitrate, reg_dlen);
+ ret = readl_poll_timeout(&bcm_i2c->regs->s, reg_s,
+ reg_s & (BSC_S_DONE | BSC_S_ERR), timeout);
+
+ if (ret) {
+ dev_err(dev, "timeout: waiting for transfer to end\n");
+ return ret;
+ }
+ if (reg_s & BSC_S_ERR)
+ goto nack;
+ writel(BSC_S_DONE | BSC_S_ERR | BSC_S_CLKT, &bcm_i2c->regs->s);
+ writel(BSC_C_CLEAR1 | BSC_C_I2CEN, &bcm_i2c->regs->c);
+ return 0;
+nack:
+ dev_dbg(dev, "device with addr %x didn't ACK\n", msg->addr);
+ return -EREMOTEIO;
+}
+
+static int bcm283x_i2c_xfer(struct i2c_adapter *adapter,
+ struct i2c_msg *msgs, int count)
+{
+ int ret, i;
+ struct i2c_msg *msg;
+ struct bcm283x_i2c *bcm_i2c = to_bcm283x_i2c(adapter);
+
+ /*
+ * Reset control reg, flush FIFO, clear flags and enable the BSC
+ */
+ writel(0UL, &bcm_i2c->regs->c);
+ writel(BSC_C_CLEAR1, &bcm_i2c->regs->c);
+ writel(BSC_S_DONE | BSC_S_ERR | BSC_S_CLKT, &bcm_i2c->regs->s);
+ writel(BSC_C_I2CEN, &bcm_i2c->regs->c);
+
+ for (i = 0; i < count; i++) {
+ msg = &msgs[i];
+ ret = bcm283x_i2c_msg_xfer(bcm_i2c, msg);
+ if (ret)
+ goto out;
+ }
+
+ writel(0UL, &bcm_i2c->regs->c);
+ return count;
+out:
+ writel(0UL, &bcm_i2c->regs->c);
+ writel(BSC_C_CLEAR1, &bcm_i2c->regs->c);
+ writel(BSC_S_DONE | BSC_S_ERR | BSC_S_CLKT, &bcm_i2c->regs->s);
+ return ret;
+}
+
+static int bcm283x_i2c_probe(struct device_d *dev)
+{
+ int ret;
+ struct resource *iores;
+ struct bcm283x_i2c *bcm_i2c;
+ struct device_node *np = dev->device_node;
+
+ bcm_i2c = xzalloc(sizeof(*bcm_i2c));
+
+ if (!np) {
+ ret = -ENXIO;
+ goto err;
+ }
+
+ iores = dev_request_mem_resource(dev, 0);
+ if (IS_ERR(iores)) {
+ dev_err(dev, "could not get iomem region\n");
+ ret = PTR_ERR(iores);
+ goto err;
+ }
+ bcm_i2c->regs = IOMEM(iores->start);
+
+ bcm_i2c->mclk = clk_get(dev, NULL);
+ if (IS_ERR(bcm_i2c->mclk)) {
+ dev_err(dev, "could not acquire clock\n");
+ ret = PTR_ERR(bcm_i2c->mclk);
+ goto err;
+ }
+ clk_enable(bcm_i2c->mclk);
+
+ bcm_i2c->bitrate = I2C_MAX_STANDARD_MODE_FREQ;
+ of_property_read_u32(np, "clock-frequency", &bcm_i2c->bitrate);
+ if (bcm_i2c->bitrate > I2C_MAX_FAST_MODE_FREQ) {
+ dev_err(dev, "clock frequency of %u is not supported\n",
+ bcm_i2c->bitrate);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ bcm_i2c->adapter.master_xfer = bcm283x_i2c_xfer;
+ bcm_i2c->adapter.nr = dev->id;
+ bcm_i2c->adapter.dev.parent = dev;
+ bcm_i2c->adapter.dev.device_node = np;
+
+ ret = bcm283x_i2c_init(bcm_i2c);
+ if (ret)
+ goto err;
+
+ return i2c_add_numbered_adapter(&bcm_i2c->adapter);
+err:
+ free(bcm_i2c);
+ return ret;
+}
+
+static struct of_device_id bcm283x_i2c_dt_ids[] = {
+ { .compatible = "brcm,bcm2835-i2c", },
+ { .compatible = "brcm,bcm2711-i2c", },
+ { /* sentinel */ }
+};
+
+static struct driver_d bcm283x_i2c_driver = {
+ .name = "i2c-bcm283x",
+ .probe = bcm283x_i2c_probe,
+ .of_compatible = DRV_OF_COMPAT(bcm283x_i2c_dt_ids),
+};
+device_platform_driver(bcm283x_i2c_driver);
diff --git a/drivers/mci/mci-bcm2835.c b/drivers/mci/mci-bcm2835.c
index 3380fa2afc..f092156f9a 100644
--- a/drivers/mci/mci-bcm2835.c
+++ b/drivers/mci/mci-bcm2835.c
@@ -324,7 +324,7 @@ static int bcm2835_mci_reset(struct mci_host *mci, struct device_d *mci_dev)
sdhci_write32(&host->sdhci,
SDHCI_HOST_CONTROL__POWER_CONTROL__BLOCK_GAP_CONTROL,
- 0x00);
+ (SDHCI_BUS_VOLTAGE_330 | SDHCI_BUS_POWER_EN) << 8);
sdhci_write32(&host->sdhci, SDHCI_ACMD12_ERR__HOST_CONTROL2,
0x00);
sdhci_write32(&host->sdhci,
@@ -424,6 +424,8 @@ static __maybe_unused struct of_device_id bcm2835_mci_compatible[] = {
{
.compatible = "brcm,bcm2835-sdhci",
}, {
+ .compatible = "brcm,bcm2711-emmc2",
+ }, {
/* sentinel */
}
};
diff --git a/drivers/serial/serial_ns16550.c b/drivers/serial/serial_ns16550.c
index f7cab8db4b..07f951e535 100644
--- a/drivers/serial/serial_ns16550.c
+++ b/drivers/serial/serial_ns16550.c
@@ -242,14 +242,10 @@ static void ns16550_jz_init_port(struct console_device *cdev)
ns16550_serial_init_port(cdev);
}
-#define BCM2836_AUX_CLOCK_ENB 0x3f215004 /* BCM2835 AUX Clock enable register */
-#define BCM2836_AUX_CLOCK_EN_UART BIT(0) /* Bit 0 enables the Miniuart */
-
static void rpi_init_port(struct console_device *cdev)
{
struct ns16550_priv *priv = to_ns16550_priv(cdev);
- writeb(BCM2836_AUX_CLOCK_EN_UART, BCM2836_AUX_CLOCK_ENB);
priv->plat.shift = 2;
/*
* We double the clock rate since the 16550 will divide by 16
diff --git a/drivers/watchdog/bcm2835_wdt.c b/drivers/watchdog/bcm2835_wdt.c
index ece80837b5..c6e6a289f2 100644
--- a/drivers/watchdog/bcm2835_wdt.c
+++ b/drivers/watchdog/bcm2835_wdt.c
@@ -10,28 +10,7 @@
#include <restart.h>
#include <watchdog.h>
-#define PM_RSTC 0x1c
-#define PM_RSTS 0x20
-#define PM_WDOG 0x24
-
-#define PM_WDOG_RESET 0000000000
-#define PM_PASSWORD 0x5a000000
-#define PM_WDOG_TIME_SET 0x000fffff
-#define PM_RSTC_WRCFG_CLR 0xffffffcf
-#define PM_RSTC_WRCFG_SET 0x00000030
-#define PM_RSTC_WRCFG_FULL_RESET 0x00000020
-#define PM_RSTC_RESET 0x00000102
-
-#define PM_RSTS_HADPOR_SET 0x00001000
-#define PM_RSTS_HADSRH_SET 0x00000400
-#define PM_RSTS_HADSRF_SET 0x00000200
-#define PM_RSTS_HADSRQ_SET 0x00000100
-#define PM_RSTS_HADWRH_SET 0x00000040
-#define PM_RSTS_HADWRF_SET 0x00000020
-#define PM_RSTS_HADWRQ_SET 0x00000010
-#define PM_RSTS_HADDRH_SET 0x00000004
-#define PM_RSTS_HADDRF_SET 0x00000002
-#define PM_RSTS_HADDRQ_SET 0x00000001
+#include <soc/bcm283x/wdt.h>
#define SECS_TO_WDOG_TICKS(x) ((x) << 16)
diff --git a/images/Makefile.bcm283x b/images/Makefile.bcm283x
index 82787f972c..f4ef7f447c 100644
--- a/images/Makefile.bcm283x
+++ b/images/Makefile.bcm283x
@@ -3,6 +3,10 @@
# barebox image generation Makefile for BCM283x images
#
+# New boards use board-dt-2nd.img as common binary
+# and have the videocore pass the correct DT.
+ifeq ($(CONFIG_32BIT),y)
+
pblb-$(CONFIG_MACH_RPI) += start_raspberry_pi1
FILE_barebox-raspberry-pi-1.img = start_raspberry_pi1.pblb
image-$(CONFIG_MACH_RPI) += barebox-raspberry-pi-1.img
@@ -18,3 +22,9 @@ image-$(CONFIG_MACH_RPI3) += barebox-raspberry-pi-3.img
pblb-$(CONFIG_MACH_RPI_CM3) += start_raspberry_pi_cm3
FILE_barebox-raspberry-pi-cm3.img = start_raspberry_pi_cm3.pblb
image-$(CONFIG_MACH_RPI_CM3) += barebox-raspberry-pi-cm3.img
+
+endif
+
+pblb-$(CONFIG_MACH_RPI_COMMON) += start_raspberry_pi_generic
+FILE_barebox-raspberry-pi.img = start_raspberry_pi_generic.pblb
+image-$(CONFIG_MACH_RPI_COMMON) += barebox-raspberry-pi.img
diff --git a/include/dma.h b/include/dma.h
index 90f9254ea8..2c4bdfc98f 100644
--- a/include/dma.h
+++ b/include/dma.h
@@ -56,15 +56,49 @@ static inline int dma_mapping_error(struct device_d *dev, dma_addr_t dma_addr)
(dev->dma_mask && dma_addr > dev->dma_mask);
}
+#ifndef __PBL__
/* streaming DMA - implement the below calls to support HAS_DMA */
+#ifndef dma_sync_single_for_cpu
void dma_sync_single_for_cpu(dma_addr_t address, size_t size,
enum dma_data_direction dir);
+#endif
+#ifndef dma_sync_single_for_device
void dma_sync_single_for_device(dma_addr_t address, size_t size,
enum dma_data_direction dir);
+#endif
+#else
+#ifndef dma_sync_single_for_cpu
+/*
+ * assumes buffers are in coherent/uncached memory, e.g. because
+ * MMU is only enabled in barebox_arm_entry which hasn't run yet.
+ */
+static inline void dma_sync_single_for_cpu(dma_addr_t address, size_t size,
+ enum dma_data_direction dir)
+{
+ barrier_data((void *)address);
+}
+#endif
+#ifndef dma_sync_single_for_device
+static inline void dma_sync_single_for_device(dma_addr_t address, size_t size,
+ enum dma_data_direction dir)
+{
+ barrier_data((void *)address);
+}
+#endif
+#endif
+
+#ifndef dma_alloc_coherent
void *dma_alloc_coherent(size_t size, dma_addr_t *dma_handle);
+#endif
+
+#ifndef dma_free_coherent
void dma_free_coherent(void *mem, dma_addr_t dma_handle, size_t size);
+#endif
+
+#ifndef dma_alloc_writecombine
void *dma_alloc_writecombine(size_t size, dma_addr_t *dma_handle);
+#endif
#endif /* __DMA_H */
diff --git a/include/soc/bcm283x/wdt.h b/include/soc/bcm283x/wdt.h
new file mode 100644
index 0000000000..ce97b1eb5d
--- /dev/null
+++ b/include/soc/bcm283x/wdt.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2017 Pengutronix, Lucas Stach <l.stach@pengutronix.de>
+ *
+ * Based on code from Carlo Caione <carlo@carlocaione.org>
+ */
+
+#ifndef __BCM2835_WDT_H
+#define __BCM2835_WDT_H
+
+#define PM_RSTC 0x1c
+#define PM_RSTS 0x20
+#define PM_WDOG 0x24
+
+#define PM_WDOG_RESET 0000000000
+#define PM_PASSWORD 0x5a000000
+#define PM_WDOG_TIME_SET 0x000fffff
+#define PM_RSTC_WRCFG_CLR 0xffffffcf
+#define PM_RSTC_WRCFG_SET 0x00000030
+#define PM_RSTC_WRCFG_FULL_RESET 0x00000020
+#define PM_RSTC_RESET 0x00000102
+
+#define PM_RSTS_HADPOR_SET 0x00001000
+#define PM_RSTS_HADSRH_SET 0x00000400
+#define PM_RSTS_HADSRF_SET 0x00000200
+#define PM_RSTS_HADSRQ_SET 0x00000100
+#define PM_RSTS_HADWRH_SET 0x00000040
+#define PM_RSTS_HADWRF_SET 0x00000020
+#define PM_RSTS_HADWRQ_SET 0x00000010
+#define PM_RSTS_HADDRH_SET 0x00000004
+#define PM_RSTS_HADDRF_SET 0x00000002
+#define PM_RSTS_HADDRQ_SET 0x00000001
+
+#define PM_RSTS_HADDR_SET \
+ (PM_RSTS_HADDRQ_SET | PM_RSTS_HADDRF_SET | PM_RSTS_HADDRH_SET)
+#define PM_RSTS_HADWR_SET \
+ (PM_RSTS_HADWRQ_SET | PM_RSTS_HADWRF_SET | PM_RSTS_HADWRH_SET)
+#define PM_RSTS_HADSR_SET \
+ (PM_RSTS_HADSRQ_SET | PM_RSTS_HADSRF_SET | PM_RSTS_HADSRH_SET)
+
+#endif