[PATCH 16/20] ARM: k3: Add initial r5 support
Sascha Hauer
s.hauer at pengutronix.de
Fri Nov 29 03:44:31 PST 2024
K3 SoCs initially boot from a Cortex-R5 processor. This patch adds
initial support for this processor along with a dtsi file to make some
adjustments to the regular device trees needed to describe the
differences between the A53 and the R5 processors.
Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
arch/arm/Kconfig | 2 -
arch/arm/dts/k3-am625-r5.dtsi | 103 ++++++++++++++++
arch/arm/mach-k3/Kconfig | 21 ++++
arch/arm/mach-k3/Makefile | 1 +
arch/arm/mach-k3/r5.c | 270 ++++++++++++++++++++++++++++++++++++++++++
include/mach/k3/r5.h | 9 ++
6 files changed, 404 insertions(+), 2 deletions(-)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 0251f2dcef..1d2533b016 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -160,8 +160,6 @@ config ARCH_IMX
config ARCH_K3
bool "Texas Instruments Inc. K3 multicore SoC architecture"
- depends on 64BIT
- select CPU_V8
select GPIOLIB
select COMMON_CLK
select HAS_DEBUG_LL
diff --git a/arch/arm/dts/k3-am625-r5.dtsi b/arch/arm/dts/k3-am625-r5.dtsi
new file mode 100644
index 0000000000..e6e9d135b4
--- /dev/null
+++ b/arch/arm/dts/k3-am625-r5.dtsi
@@ -0,0 +1,103 @@
+
+&a53_timer0 {
+ status = "disabled";
+};
+
+&main_timer0 {
+ /delete-property/ assigned-clocks;
+ /delete-property/ assigned-clock-parents;
+};
+
+&main_timer1 {
+ /delete-property/ assigned-clocks;
+ /delete-property/ assigned-clock-parents;
+};
+
+&main_timer2 {
+ /delete-property/ assigned-clocks;
+ /delete-property/ assigned-clock-parents;
+};
+
+&main_timer3 {
+ /delete-property/ assigned-clocks;
+ /delete-property/ assigned-clock-parents;
+};
+
+&main_timer4 {
+ /delete-property/ assigned-clocks;
+ /delete-property/ assigned-clock-parents;
+};
+
+&main_timer5 {
+ /delete-property/ assigned-clocks;
+ /delete-property/ assigned-clock-parents;
+};
+
+&main_timer6 {
+ /delete-property/ assigned-clocks;
+ /delete-property/ assigned-clock-parents;
+};
+
+&main_timer7 {
+ /delete-property/ assigned-clocks;
+ /delete-property/ assigned-clock-parents;
+};
+
+&cbass_main {
+ sysctrler: sysctrler {
+ compatible = "ti,am654-system-controller";
+ mboxes= <&secure_proxy_main 1>, <&secure_proxy_main 0>, <&secure_proxy_sa3 0>;
+ mbox-names = "tx", "rx", "boot_notify";
+ };
+};
+
+&secure_proxy_sa3 {
+ /* We require this for boot handshake */
+ status = "okay";
+};
+
+/ {
+ a53_0: a53 at 0 {
+ compatible = "ti,am654-rproc";
+ reg = <0x00 0x00a90000 0x00 0x10>;
+ power-domains = <&k3_pds 61 TI_SCI_PD_EXCLUSIVE>,
+ <&k3_pds 135 TI_SCI_PD_EXCLUSIVE>;
+ resets = <&k3_reset 135 0>;
+ clocks = <&k3_clks 61 0>, <&k3_clks 135 0>;
+ clock-names = "gtc", "core";
+ assigned-clocks = <&k3_clks 61 0>, <&k3_clks 135 0>;
+ assigned-clock-parents = <&k3_clks 61 2>;
+ assigned-clock-rates = <200000000>, <1250000000>;
+ ti,sci = <&dmsc>;
+ ti,sci-proc-id = <32>;
+ ti,sci-host-id = <10>;
+ };
+
+ dm_tifs: dm-tifs {
+ compatible = "ti,j721e-dm-sci";
+ ti,host-id = <36>;
+ ti,secure-host;
+ mbox-names = "rx", "tx";
+ mboxes= <&secure_proxy_main 22>,
+ <&secure_proxy_main 23>;
+ };
+};
+
+&dmsc {
+ mboxes = <&secure_proxy_main 0>,
+ <&secure_proxy_main 1>,
+ <&secure_proxy_main 0>;
+ mbox-names = "rx", "tx", "notify";
+ ti,host-id = <35>;
+ ti,secure-host;
+};
+
+&sdhci2 {
+ /* Doesn't work currently, no clocks defined */
+ status = "disabled";
+};
+
+&dss_vp1_clk {
+ /* Doesn't work, no support for input clock */
+ status = "disabled";
+};
diff --git a/arch/arm/mach-k3/Kconfig b/arch/arm/mach-k3/Kconfig
index 152d231a56..2ea9f32696 100644
--- a/arch/arm/mach-k3/Kconfig
+++ b/arch/arm/mach-k3/Kconfig
@@ -3,6 +3,27 @@
menu "K3 boards"
depends on ARCH_K3
+config MACH_K3_CORTEX_R5
+ bool
+ select CPU_V7
+ select CLOCKSOURCE_TI_DM
+ select REMOTEPROC
+ select REMOTEPROC_TI_K3_ARM64
+ select REMOTEPROC_K3_SYSTEM_CONTROLLER
+ select PM_GENERIC_DOMAINS
+ select TI_K3_PM_DOMAINS
+ select ARMV7R_MPU
+ select ELF
+ select K3_DDRSS
+ depends on 32BIT
+ default y
+
+config MACH_K3_CORTEX_A
+ bool
+ select CPU_V8
+ depends on 64BIT
+ default y
+
config MACH_BEAGLEPLAY
bool "BeagleBoard BeaglePlay"
help
diff --git a/arch/arm/mach-k3/Makefile b/arch/arm/mach-k3/Makefile
index f95691b59a..0efc1e0239 100644
--- a/arch/arm/mach-k3/Makefile
+++ b/arch/arm/mach-k3/Makefile
@@ -1 +1,2 @@
obj-y += common.o
+obj-pbl-$(CONFIG_MACH_K3_CORTEX_R5) += r5.o
diff --git a/arch/arm/mach-k3/r5.c b/arch/arm/mach-k3/r5.c
new file mode 100644
index 0000000000..114dc9ee08
--- /dev/null
+++ b/arch/arm/mach-k3/r5.c
@@ -0,0 +1,270 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <io.h>
+#include <linux/kernel.h>
+#include <mach/k3/r5.h>
+#include <asm/armv7r-mpu.h>
+#include <init.h>
+#include <libfile.h>
+#include <fs.h>
+#include <firmware.h>
+#include <linux/remoteproc.h>
+#include <soc/ti/ti_sci_protocol.h>
+#include <linux/clk.h>
+#include <elf.h>
+#include <asm/cache.h>
+#include <linux/sizes.h>
+#include <barebox.h>
+
+#define CTRLMMR_LOCK_KICK0_UNLOCK_VAL 0x68ef3490
+#define CTRLMMR_LOCK_KICK1_UNLOCK_VAL 0xd172bc5a
+#define CTRLMMR_LOCK_KICK0 0x1008
+#define CTRLMMR_LOCK_KICK1 0x100c
+#define CTRL_MMR0_PARTITION_SIZE 0x4000
+#define WKUP_CTRL_MMR0_BASE 0x43000000
+#define CTRL_MMR0_BASE 0x00100000
+#define MCU_CTRL_MMR0_BASE 0x04500000
+#define PADCFG_MMR0_BASE 0x04080000
+#define PADCFG_MMR1_BASE 0x000f0000
+
+static void mmr_unlock(uintptr_t base, u32 partition)
+{
+ /* Translate the base address */
+ uintptr_t part_base = base + partition * CTRL_MMR0_PARTITION_SIZE;
+
+ /* Unlock the requested partition if locked using two-step sequence */
+ writel(CTRLMMR_LOCK_KICK0_UNLOCK_VAL, part_base + CTRLMMR_LOCK_KICK0);
+ writel(CTRLMMR_LOCK_KICK1_UNLOCK_VAL, part_base + CTRLMMR_LOCK_KICK1);
+}
+
+void k3_ctrl_mmr_unlock(void)
+{
+ /* Unlock all WKUP_CTRL_MMR0 module registers */
+ mmr_unlock(WKUP_CTRL_MMR0_BASE, 0);
+ mmr_unlock(WKUP_CTRL_MMR0_BASE, 1);
+ mmr_unlock(WKUP_CTRL_MMR0_BASE, 2);
+ mmr_unlock(WKUP_CTRL_MMR0_BASE, 3);
+ mmr_unlock(WKUP_CTRL_MMR0_BASE, 4);
+ mmr_unlock(WKUP_CTRL_MMR0_BASE, 5);
+ mmr_unlock(WKUP_CTRL_MMR0_BASE, 6);
+ mmr_unlock(WKUP_CTRL_MMR0_BASE, 7);
+
+ /* Unlock all CTRL_MMR0 module registers */
+ mmr_unlock(CTRL_MMR0_BASE, 0);
+ mmr_unlock(CTRL_MMR0_BASE, 1);
+ mmr_unlock(CTRL_MMR0_BASE, 2);
+ mmr_unlock(CTRL_MMR0_BASE, 4);
+ mmr_unlock(CTRL_MMR0_BASE, 6);
+
+ /* Unlock all MCU_CTRL_MMR0 module registers */
+ mmr_unlock(MCU_CTRL_MMR0_BASE, 0);
+ mmr_unlock(MCU_CTRL_MMR0_BASE, 1);
+ mmr_unlock(MCU_CTRL_MMR0_BASE, 2);
+ mmr_unlock(MCU_CTRL_MMR0_BASE, 3);
+ mmr_unlock(MCU_CTRL_MMR0_BASE, 4);
+ mmr_unlock(MCU_CTRL_MMR0_BASE, 6);
+
+ /* Unlock PADCFG_CTRL_MMR padconf registers */
+ mmr_unlock(PADCFG_MMR0_BASE, 1);
+ mmr_unlock(PADCFG_MMR1_BASE, 1);
+}
+
+#define CONFIG_SPL_TEXT_BASE 0x43c00000 /* FIXME */
+#define CFG_SYS_SDRAM_BASE 0x80000000 /* FIXME */
+
+static struct mpu_region_config k3_mpu_regions[16] = {
+ /*
+ * Make all 4GB as Device Memory and not executable. We are overriding
+ * it with next region for any requirement.
+ */
+ {0x00000000, REGION_0, XN_EN, PRIV_RW_USR_RW, SHARED_WRITE_BUFFERED,
+ REGION_4GB},
+
+ /* SPL code area marking it as WB and Write allocate. */
+ {CONFIG_SPL_TEXT_BASE, REGION_1, XN_DIS, PRIV_RW_USR_RW,
+ O_I_WB_RD_WR_ALLOC, REGION_8MB},
+
+ /* U-Boot's code area marking it as WB and Write allocate */
+ {CFG_SYS_SDRAM_BASE, REGION_2, XN_DIS, PRIV_RW_USR_RW,
+ O_I_WB_RD_WR_ALLOC, REGION_2GB},
+ /* mcu_r5fss0_core0 BTCM area marking it as WB and Write allocate. */
+ {0x41010000, 3, XN_DIS, PRIV_RW_USR_RW, O_I_WB_RD_WR_ALLOC,
+ REGION_8MB},
+ {0x0, 4, 0x0, 0x0, 0x0, 0x0},
+ {0x0, 5, 0x0, 0x0, 0x0, 0x0},
+ {0x0, 6, 0x0, 0x0, 0x0, 0x0},
+ {0x0, 7, 0x0, 0x0, 0x0, 0x0},
+ {0x0, 8, 0x0, 0x0, 0x0, 0x0},
+ {0x0, 9, 0x0, 0x0, 0x0, 0x0},
+ {0x0, 10, 0x0, 0x0, 0x0, 0x0},
+ {0x0, 11, 0x0, 0x0, 0x0, 0x0},
+ {0x0, 12, 0x0, 0x0, 0x0, 0x0},
+ {0x0, 13, 0x0, 0x0, 0x0, 0x0},
+ {0x0, 14, 0x0, 0x0, 0x0, 0x0},
+ {0x0, 15, 0x0, 0x0, 0x0, 0x0},
+};
+
+void k3_mpu_setup_regions(void)
+{
+ armv7r_mpu_setup_regions(k3_mpu_regions, ARRAY_SIZE(k3_mpu_regions));
+}
+
+#include <soc/k3/clk.h>
+
+#define PSC_PTCMD 0x120
+#define PSC_PTCMD_H 0x124
+#define PSC_PTSTAT 0x128
+#define PSC_PTSTAT_H 0x12C
+#define PSC_PDSTAT 0x200
+#define PSC_PDCTL 0x300
+#define PSC_MDSTAT 0x800
+#define PSC_MDCTL 0xa00
+
+#define MDSTAT_STATE_MASK 0x3f
+#define MDSTAT_BUSY_MASK 0x30
+#define MDSTAT_STATE_SWRSTDISABLE 0x0
+#define MDSTAT_STATE_ENABLE 0x3
+
+static void ti_pd_wait(void __iomem *base, int id)
+{
+ u32 pdoffset = 0;
+ u32 ptstatreg = PSC_PTSTAT;
+
+ if (id > 31) {
+ pdoffset = 32;
+ ptstatreg = PSC_PTSTAT_H;
+ }
+
+ while (readl(base + ptstatreg) & BIT(id - pdoffset));
+}
+
+void am625_early_init(void)
+{
+ void __iomem *pd_base = (void *)0x400000;
+ u32 val;
+ volatile int i;
+
+ ti_k3_pll_init((void *)0x68c000);
+
+ /* hsdiv0_16fft_main_12_hsdivout0_clk divide by 2 */
+ val = readl(0x68c080);
+ val &= ~0xff;
+ val |= 1;
+ writel(val, 0x68c080);
+
+ /* PLL needs a rest, barebox would hang during PLL setup without this delay */
+ for (i = 0; i < 1000000; i++);
+
+ /*
+ * configure PLL to 800MHz, with the above divider DDR frequency
+ * results in 400MHz.
+ */
+ ti_k3_pll_set_rate((void *)0x68c000, 800000000, 25000000);
+
+ /* Enable DDR controller power domains */
+ writel(0x103, pd_base + 0x00000a24);
+ writel(0x1, pd_base + 0x00000120);
+ ti_pd_wait(pd_base, 0);
+ writel(0x103, pd_base + 0x00000a28);
+ writel(0x1, pd_base + 0x00000120);
+ ti_pd_wait(pd_base, 0);
+ writel(0x103, pd_base + 0x00000a2c);
+ writel(0x1, pd_base + 0x00000120);
+ ti_pd_wait(pd_base, 0);
+}
+
+static int k3_r5_start_image(void)
+{
+ int err;
+ void *ti_dm_buf;
+ ssize_t size;
+ struct firmware fw;
+ const struct ti_sci_handle *ti_sci;
+ void *bl31 = (void *)0x80000000;
+ void *barebox = (void *)0x80080000;
+ void *optee = (void *)0x9e800000;
+ struct elf_image *elf;
+ void __noreturn (*ti_dm)(void);
+ struct rproc *arm64_rproc;
+
+ ti_sci = ti_sci_get_handle(NULL);
+ if (IS_ERR(ti_sci))
+ return -EINVAL;
+
+ arm64_rproc = ti_k3_am64_get_handle();
+ if (!arm64_rproc) {
+ pr_err("Cannot get rproc handle\n");
+ return -EINVAL;
+ }
+
+ size = read_file_into_buf("/boot/optee.bin", optee, SZ_32M);
+ if (size < 0) {
+ pr_err("Cannot load optee.bin: %pe\n", ERR_PTR(size));
+ return size;
+ }
+ pr_debug("Loaded optee.bin (size %u) to 0x%p\n", size, optee);
+
+ size = read_file_into_buf("/boot/barebox.bin", barebox, optee - barebox);
+ if (size < 0) {
+ pr_err("Cannot load barebox.bin: %pe\n", ERR_PTR(size));
+ return size;
+ }
+ pr_debug("Loaded barebox.bin (size %u) to 0x%p\n", size, barebox);
+
+ size = read_file_into_buf("/boot/bl31.bin", bl31, barebox - optee);
+ if (size < 0) {
+ pr_err("Cannot load bl31.bin: %pe\n", ERR_PTR(size));
+ return size;
+ }
+ pr_debug("Loaded bl31.bin (size %u) to 0x%p\n", size, bl31);
+
+ err = read_file_2("/boot/ti-dm.bin", &size, &ti_dm_buf, FILESIZE_MAX);
+ if (err) {
+ pr_err("Cannot load ti-dm.bin: %pe\n", ERR_PTR(err));
+ return err;
+ }
+ pr_debug("Loaded ti-dm.bin (size %u)\n", size);
+
+ elf = elf_open_binary(ti_dm_buf);
+ if (IS_ERR(elf)) {
+ pr_err("Cannot open ELF image %pe\n", elf);
+ return PTR_ERR(elf);
+ }
+
+ err = elf_load(elf);
+ if (err) {
+ pr_err("Cannot load ELF image %pe\n", ERR_PTR(err));
+ elf_close(elf);
+ }
+
+ free(ti_dm_buf);
+
+ fw.data = bl31;
+
+ /* Release all the exclusive devices held by SPL before starting ATF */
+ pr_info("Starting TF-A on A53 core\n");
+
+ ti_sci->ops.dev_ops.release_exclusive_devices(ti_sci);
+ arm64_rproc->ops->load(arm64_rproc, &fw);
+ arm64_rproc->ops->start(arm64_rproc);
+
+ pr_debug("Starting ti-dm at 0x%08llx\n", elf->entry);
+
+ sync_caches_for_execution();
+
+ ti_dm = (void *)(unsigned long)elf->entry;
+
+ ti_dm();
+}
+
+static int xload(void)
+{
+ int ret;
+
+ ret = k3_r5_start_image();
+
+ pr_crit("Starting image failed with: %pe\n", ERR_PTR(ret));
+ pr_crit("Nothing left to do\n");
+
+ hang();
+}
+postenvironment_initcall(xload);
diff --git a/include/mach/k3/r5.h b/include/mach/k3/r5.h
new file mode 100644
index 0000000000..f40639ed5b
--- /dev/null
+++ b/include/mach/k3/r5.h
@@ -0,0 +1,9 @@
+#ifndef __MACH_K3_R5_H
+#define __MACH_K3_R5_H
+
+void k3_ctrl_mmr_unlock(void);
+void k3_mpu_setup_regions(void);
+void am625_early_init(void);
+struct rproc *ti_k3_am64_get_handle(void);
+
+#endif /* __MACH_K3_R5_H */
--
2.39.5
More information about the barebox
mailing list