diff options
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 |