@@ -2033,6 +2033,10 @@ config ARCH_STM32
select DM_SERIAL
imply CMD_DM
+config ARCH_RP2XXX
+ bool "Raspberry Pi RP2xxx SoCs"
+ select CPU_V7M
+
config ARCH_STI
bool "Support STMicroelectronics SoCs"
select CPU_V7A
@@ -2293,6 +2297,9 @@ config SYS_KWD_CONFIG
Path within the source directory to the kwbimage.cfg file to use
when packaging the U-Boot image for use.
+
+source "arch/arm/mach-rp2xxx/Kconfig"
+
source "arch/arm/mach-airoha/Kconfig"
source "arch/arm/mach-apple/Kconfig"
@@ -101,6 +101,8 @@ machine-$(CONFIG_ARCH_ZYNQMP_R5) += zynqmp-r5
machine-$(CONFIG_MACH_IMX) += imx
+machine-$(CONFIG_ARCH_RP2XXX) += rp2xxx
+
machdirs := $(patsubst %,arch/arm/mach-%/,$(machine-y))
PLATFORM_CPPFLAGS += $(patsubst %,-I$(srctree)/%include,$(machdirs))
new file mode 100644
@@ -0,0 +1,352 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#ifndef _MACH_RP2350_H_
+#define _MACH_RP2350_H_
+
+/*
+ * RP2350 Memory Map from RP2350 Datasheet. Datasheet sections are
+ * mentioned against the respective ranges.
+ *
+ * 0x00000000 - 0x00007fff Boot ROM (32KB), sec 3.8.2.2
+ * 0x10000000 - 0x11FFFFFF XIP QSPI interface range (up to 32MB), sec 2.2.2.
+ * 0x20000000 - 0x20081FFF SRAM (520KB), sec 4.2.
+ * 0x40000000 APB Peripherals base, sec 2.2.4.
+ * 0x50000000 AHB Peripherals base, sec 2.2.5.
+ * 0xD0000000 Core-local peripherals (SIO) base, sec 2.2.6.
+ * 0xE0000000 Cortex-M33 Private Peripheral Bus, sec 2.2.7.
+ */
+
+/* Flash XIP base - U-Boot should start from here */
+#define RP2350_FLASH_XIP_BASE 0x10000000
+#define RP2350_FLASH_XIP_SIZE (32 * 1024 * 1024) /* 32MB, override in board files */
+
+/* SRAM - 520KB across 10 banks */
+#define RP2350_SRAM_BASE 0x20000000
+#define RP2350_SRAM_SIZE (520 * 1024) /* 520KB */
+
+#define RP2350_SRAM_TOP (RP2350_SRAM_BASE + RP2350_SRAM_SIZE)
+
+/*
+ * APB Peripheral Base Addresses
+ */
+#define RP2350_APB_BASE 0x40000000
+#define RP2350_SYSINFO_BASE 0x40000000
+#define RP2350_SYSCFG_BASE 0x40008000
+#define RP2350_CLOCKS_BASE 0x40010000
+#define RP2350_PSM_BASE 0x40018000
+#define RP2350_RESETS_BASE 0x40020000
+#define RP2350_IO_BANK0_BASE 0x40028000
+#define RP2350_IO_QSPI_BASE 0x40030000
+#define RP2350_PADS_BANK0_BASE 0x40038000
+#define RP2350_PADS_QSPI_BASE 0x40040000
+#define RP2350_XOSC_BASE 0x40048000
+#define RP2350_PLL_SYS_BASE 0x40050000
+#define RP2350_PLL_USB_BASE 0x40058000
+#define RP2350_ACCESSCTRL_BASE 0x40060000
+#define RP2350_BUSCTRL_BASE 0x40068000
+#define RP2350_UART0_BASE 0x40070000
+#define RP2350_UART1_BASE 0x40078000
+#define RP2350_SPI0_BASE 0x40080000
+#define RP2350_SPI1_BASE 0x40088000
+#define RP2350_I2C0_BASE 0x40090000
+#define RP2350_I2C1_BASE 0x40098000
+#define RP2350_ADC_BASE 0x400a0000
+#define RP2350_PWM_BASE 0x400a8000
+#define RP2350_TIMER0_BASE 0x400b0000
+#define RP2350_TIMER1_BASE 0x400b8000
+#define RP2350_HSTX_CTRL_BASE 0x400c0000
+#define RP2350_XIP_CTRL_BASE 0x400c8000
+#define RP2350_XIP_QMI_BASE 0x400d0000
+#define RP2350_WATCHDOG_BASE 0x400d8000
+#define RP2350_BOOTRAM_BASE 0x400e0000
+#define RP2350_ROSC_BASE 0x400e8000
+#define RP2350_TRNG_BASE 0x400f0000
+#define RP2350_SHA256_BASE 0x400f8000
+#define RP2350_POWMAN_BASE 0x40100000
+#define RP2350_TICKS_BASE 0x40108000
+#define RP2350_OTP_BASE 0x40120000
+#define RP2350_OTP_DATA_BASE 0x40130000
+#define RP2350_OTP_DATA_RAW_BASE 0x40134000
+#define RP2350_OTP_DATA_GUARDED_BASE 0x40138000
+#define RP2350_OTP_DATA_RAW_GUARDED_BASE 0x4013c000
+#define RP2350_CORESIGHT_PERIPH_BASE 0x40140000
+#define RP2350_CORESIGHT_ROMTABLE_BASE 0x40140000
+#define RP2350_CORESIGHT_AHB_AP_CORE0_BASE 0x40142000
+#define RP2350_CORESIGHT_AHB_AP_CORE1_BASE 0x40144000
+#define RP2350_CORESIGHT_TIMESTAMP_GEN_BASE 0x40146000
+#define RP2350_CORESIGHT_ATB_FUNNEL_BASE 0x40147000
+#define RP2350_CORESIGHT_TPIU_BASE 0x40148000
+#define RP2350_CORESIGHT_CTI_BASE 0x40149000
+#define RP2350_CORESIGHT_APB_AP_RISCV_BASE 0x4014a000
+#define RP2350_GLITCH_DETECTOR_BASE 0x40158000
+#define RP2350_TBMAN_BASE 0x40160000
+
+/*
+ * AHB Peripheral Base Addresses
+ */
+#define RP2350_AHB_BASE 0x50000000
+#define RP2350_DMA_BASE 0x50000000
+#define RP2350_USBCTRL_BASE 0x50100000
+#define RP2350_USBCTRL_DPRAM_BASE 0x50100000
+#define RP2350_USBCTRL_REGS_BASE 0x50110000
+#define RP2350_PIO0_BASE 0x50200000
+#define RP2350_PIO1_BASE 0x50300000
+#define RP2350_PIO2_BASE 0x50400000
+#define RP2350_XIP_AUX_BASE 0x50500000
+#define RP2350_HSTX_FIFO_BASE 0x50600000
+#define RP2350_CORESIGHT_TRACE_BASE 0x50700000
+
+/* SIO (Core-local peripherals) Base Address */
+#define RP2350_SIO_BASE 0xd0000000
+#define RP2350_SIO_NONSEC_BASE 0xd0020000
+
+/* One universal macro to handle every single block and offset */
+#define RP2350_REG(base, offset) ((base) + (offset))
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+
+/*
+ * RESETS peripheral register map
+ * Used to hold peripherals in reset and release them
+ */
+struct rp2350_resets_regs {
+ u32 reset; /* 0x00 - Reset control */
+ u32 wdsel; /* 0x04 - Watchdog select */
+ u32 reset_done; /* 0x08 - Reset done status */
+};
+
+#define RP2350_RESETS ((struct rp2350_resets_regs *)RP2350_RESETS_BASE)
+
+/* Reset bits for peripherals we care about */
+#define RESETS_RESET_UART0 BIT(26)
+#define RESETS_RESET_UART1 BIT(27)
+#define RESETS_RESET_PLL_SYS BIT(14)
+#define RESETS_RESET_PLL_USB BIT(15)
+
+/*
+ * XOSC (Crystal Oscillator) register map
+ * RP2350 uses a 12MHz crystal
+ */
+struct rp2350_xosc_regs {
+ u32 ctrl; /* 0x00 - Crystal oscillator control */
+ u32 status; /* 0x04 - Crystal oscillator status */
+ u32 dormant; /* 0x08 - Dormant control */
+ u32 startup; /* 0x0C - Startup delay */
+ u32 count; /* 0x10 - Counter */
+};
+
+#define RP2350_XOSC ((struct rp2350_xosc_regs *)RP2350_XOSC_BASE)
+
+#define XOSC_CTRL_ENABLE 0xFAB000 /* Magic enable value, disable is 0xD1E */
+#define XOSC_CTRL_FREQ_RANGE_1_15MHZ 0xAA0
+#define XOSC_STATUS_STABLE BIT(31)
+#define XOSC_STARTUP_DELAY 47 /* ~1ms at 12MHz, ref sec 8.2.4. */
+
+/*
+ * PLL register map
+ * Both PLL_SYS and PLL_USB use same layout
+ */
+struct rp2350_pll_regs {
+ u32 cs; /* 0x00 - Control and status */
+ u32 pwr; /* 0x04 - Power control */
+ u32 fbdiv_int; /* 0x08 - Feedback divisor integer */
+ u32 prim; /* 0x0C - Post divisors */
+};
+
+#define RP2350_PLL_SYS ((struct rp2350_pll_regs *)RP2350_PLL_SYS_BASE)
+#define RP2350_PLL_USB ((struct rp2350_pll_regs *)RP2350_PLL_USB_BASE)
+
+/* PLL CS register bits */
+#define PLL_CS_LOCK BIT(31)
+#define PLL_CS_BYPASS BIT(8)
+#define PLL_CS_REFDIV_SHIFT 0
+#define PLL_CS_REFDIV_MASK 0x3F
+
+/* PLL PWR register bits */
+#define PLL_PWR_PD BIT(0) /* Main power down */
+#define PLL_PWR_DSMPD BIT(2) /* DSM power down */
+#define PLL_PWR_POSTDIVPD BIT(3) /* Post divider power down */
+#define PLL_PWR_VCOPD BIT(5) /* VCO power down */
+
+/* PLL PRIM register */
+#define PLL_PRIM_POSTDIV1_SHIFT 16
+#define PLL_PRIM_POSTDIV2_SHIFT 12
+
+/*
+ * CLOCKS register map
+ * Complete layout for the RP2350 CLOCKS block as defined in the datasheet.
+ * Each clock source has CTRL/DIV/SELECTED registers;
+ * As mentioned in Datasheet section 8.1.7 List of registers
+ */
+struct rp2350_clocks_regs {
+ u32 clk_gpout0_ctrl; /* 0x00 */
+ u32 clk_gpout0_div; /* 0x04 */
+ u32 clk_gpout0_selected; /* 0x08 */
+ u32 clk_gpout1_ctrl; /* 0x0C */
+ u32 clk_gpout1_div; /* 0x10 */
+ u32 clk_gpout1_selected; /* 0x14 */
+ u32 clk_gpout2_ctrl; /* 0x18 */
+ u32 clk_gpout2_div; /* 0x1C */
+ u32 clk_gpout2_selected; /* 0x20 */
+ u32 clk_gpout3_ctrl; /* 0x24 */
+ u32 clk_gpout3_div; /* 0x28 */
+ u32 clk_gpout3_selected; /* 0x2C */
+ u32 clk_ref_ctrl; /* 0x30 */
+ u32 clk_ref_div; /* 0x34 */
+ u32 clk_ref_selected; /* 0x38 */
+ u32 clk_sys_ctrl; /* 0x3C */
+ u32 clk_sys_div; /* 0x40 */
+ u32 clk_sys_selected; /* 0x44 */
+ u32 clk_peri_ctrl; /* 0x48 */
+ u32 clk_peri_div; /* 0x4C */
+ u32 clk_peri_selected; /* 0x50 */
+ u32 clk_hstx_ctrl; /* 0x54 */
+ u32 clk_hstx_div; /* 0x58 */
+ u32 clk_hstx_selected; /* 0x5C */
+ u32 clk_usb_ctrl; /* 0x60 */
+ u32 clk_usb_div; /* 0x64 */
+ u32 clk_usb_selected; /* 0x68 */
+ u32 clk_adc_ctrl; /* 0x6C */
+ u32 clk_adc_div; /* 0x70 */
+ u32 clk_adc_selected; /* 0x74 */
+ u32 dftclk_xosc_ctrl; /* 0x78 */
+ u32 dftclk_rosc_ctrl; /* 0x7C */
+ u32 dftclk_lposc_ctrl; /* 0x80 */
+ u32 clk_sys_resus_ctrl; /* 0x84 */
+ u32 clk_sys_resus_status; /* 0x88 */
+ u32 fc0_ref_khz; /* 0x8C */
+ u32 fc0_min_khz; /* 0x90 */
+ u32 fc0_max_khz; /* 0x94 */
+ u32 fc0_delay; /* 0x98 */
+ u32 fc0_interval; /* 0x9C */
+ u32 fc0_src; /* 0xA0 */
+ u32 fc0_status; /* 0xA4 */
+ u32 fc0_result; /* 0xA8 */
+ u32 wake_en0; /* 0xAC */
+ u32 wake_en1; /* 0xB0 */
+ u32 sleep_en0; /* 0xB4 */
+ u32 sleep_en1; /* 0xB8 */
+ u32 enabled0; /* 0xBC */
+ u32 enabled1; /* 0xC0 */
+ u32 intr; /* 0xC4 */
+ u32 inte; /* 0xC8 */
+ u32 intf; /* 0xCC */
+ u32 ints; /* 0xD0 */
+};
+
+#define RP2350_CLOCKS ((struct rp2350_clocks_regs *)RP2350_CLOCKS_BASE)
+
+/* Clock source selections */
+#define CLK_REF_SRC_XOSC 0x2
+#define CLK_SYS_SRC_PLL_SYS 0x0
+#define CLK_PERI_SRC_CLK_SYS 0x0
+#define CLK_SYS_SRC_AUX 0x1
+
+/*
+ * UART register map (PL011 compatible)
+ * This is standard ARM PL011 - same as used in many ARM SoCs
+ */
+struct rp2350_uart_regs {
+ u32 dr; /* 0x00 - Data register */
+ u32 rsr; /* 0x04 - Receive status / error clear */
+ u32 reserved0[4];
+ u32 fr; /* 0x18 - Flag register */
+ u32 reserved1;
+ u32 ilpr; /* 0x20 - IrDA low-power counter */
+ u32 ibrd; /* 0x24 - Integer baud rate divisor */
+ u32 fbrd; /* 0x28 - Fractional baud rate divisor */
+ u32 lcr_h; /* 0x2C - Line control */
+ u32 cr; /* 0x30 - Control */
+ u32 ifls; /* 0x34 - Interrupt FIFO level select */
+ u32 imsc; /* 0x38 - Interrupt mask set/clear */
+ u32 ris; /* 0x3C - Raw interrupt status */
+ u32 mis; /* 0x40 - Masked interrupt status */
+ u32 icr; /* 0x44 - Interrupt clear */
+ u32 dmacr; /* 0x48 - DMA control */
+};
+
+#define RP2350_UART0 ((struct rp2350_uart_regs *)RP2350_UART0_BASE)
+#define RP2350_UART1 ((struct rp2350_uart_regs *)RP2350_UART1_BASE)
+
+/* UART Flag register bits */
+#define UART_FR_TXFF BIT(5) /* TX FIFO full */
+#define UART_FR_RXFE BIT(4) /* RX FIFO empty */
+#define UART_FR_BUSY BIT(3) /* UART busy */
+#define UART_FR_TXFE BIT(7) /* TX FIFO empty */
+
+/* UART Line Control bits */
+#define UART_LCR_H_WLEN_8 (0x3 << 5) /* 8 bit word length */
+#define UART_LCR_H_FEN BIT(4) /* FIFO enable */
+
+/* UART Control bits */
+#define UART_CR_UARTEN BIT(0) /* UART enable */
+#define UART_CR_TXE BIT(8) /* TX enable */
+#define UART_CR_RXE BIT(9) /* RX enable */
+
+#define RP2350_IO_BANK0_GPIO_CTRL(n) RP2350_REG(RP2350_IO_BANK0_BASE, 0x04 + (n) * 0x08)
+#define RP2350_PADS_BANK0_GPIO(n) RP2350_REG(RP2350_PADS_BANK0_BASE, 0x04 + (n) * 0x04)
+
+/* GPIO function selections */
+#define RP2350_GPIO_FUNC_UART 2
+#define RP2350_PAD_IE BIT(6)
+#define RP2350_PAD_OD BIT(7)
+#define RP2350_PAD_ISO BIT(8)
+#define RESETS_RESET_IO_BANK0 BIT(6)
+#define RESETS_RESET_PADS_BANK0 BIT(9)
+
+/* Peripheral pointer, selected at compile time */
+#if CONFIG_RP2350_EARLY_UART_PORT == 0
+# define RP2350_EARLY_UART RP2350_UART0
+# define RESETS_RESET_EARLY_UART RESETS_RESET_UART0
+#elif CONFIG_RP2350_EARLY_UART_PORT == 1
+# define RP2350_EARLY_UART RP2350_UART1
+# define RESETS_RESET_EARLY_UART RESETS_RESET_UART1
+#else
+# error "CONFIG_RP2350_EARLY_UART_PORT must be 0 or 1"
+#endif
+
+/*
+ * System clock frequency after PLL init
+ * RP2350 default: 12MHz XOSC -> PLL -> 150MHz system clock
+ *
+ * PLL config for 150MHz:
+ * Same as SDK
+ * REFDIV=1, FBDIV=125, POSTDIV1=5, POSTDIV2=2
+ * VCO = 12MHz * 125 = 1500MHz
+ * SYS = 1500MHz / 5 / 2 = 150MHz
+ */
+#define RP2350_XOSC_HZ 12000000
+#define RP2350_SYS_CLK_HZ 150000000
+#define RP2350_PERI_CLK_HZ RP2350_SYS_CLK_HZ
+
+/* UART baud rate calculation
+ * BAUDDIV = CLK / (16 * BAUD)
+ * After PLL init CLK_PERI sources from clk_sys which is PLL (150MHz):
+ * BAUDDIV = 150000000 / (16 * 115200) = 81.3802
+ * IBRD = 81, FBRD = round(0.3802 * 64) = 24
+ */
+#define RP2350_UART_IBRD_115200 81
+#define RP2350_UART_FBRD_115200 24
+
+/*
+ * Atomic register access
+ * RP2350 (like RP2040) provides atomic set/clear/xor aliases
+ * for all peripheral registers via address offsets
+ */
+#define RP2350_ATOMIC_XOR_OFFSET 0x1000
+#define RP2350_ATOMIC_SET_OFFSET 0x2000
+#define RP2350_ATOMIC_CLR_OFFSET 0x3000
+
+#define rp2350_reg_set(addr, val) \
+ writel(val, (void *)((unsigned long)(addr) + RP2350_ATOMIC_SET_OFFSET))
+#define rp2350_reg_clr(addr, val) \
+ writel(val, (void *)((unsigned long)(addr) + RP2350_ATOMIC_CLR_OFFSET))
+
+void rp2350_soc_init(void);
+void rp2350_uart_early_init(void);
+
+#endif /* ! __ASSEMBLY__ */
+
+#endif /* _MACH_RP2350_H_ */
new file mode 100644
@@ -0,0 +1,58 @@
+if ARCH_RP2XXX
+
+config RP2350
+ bool "RP2350 SoC"
+ help
+ Raspberry Pi RP2350 SoC.
+ Dual-core ARM Cortex-M33 with TrustZone,
+ 520KB SRAM, supports up to 16MB XIP QSPI flash.
+
+if RP2350
+
+config RP2350_EARLY_UART
+ bool "Enable early UART init for RP2350"
+ default y
+ help
+ Initialises a UART very early in boot (before driver model) for
+ low-level debug output. The peripheral clocks, pad control, and
+ GPIO mux are configured here from fixed compile-time settings.
+
+if RP2350_EARLY_UART
+
+config RP2350_EARLY_UART_PORT
+ int "Early UART port number (0 or 1)"
+ range 0 1
+ default 1
+ help
+ Select which UART peripheral to use for early debug output.
+ 0 = UART0 (default; TX=GPIO0, RX=GPIO1)
+ 1 = UART1 (TX=GPIO4, RX=GPIO5)
+
+config RP2350_EARLY_UART_TX_GPIO
+ int "Early UART TX GPIO number"
+ default 0 if RP2350_EARLY_UART_PORT = 0
+ default 4 if RP2350_EARLY_UART_PORT = 1
+ help
+ GPIO pin for UART TX. Must match the UART port chosen above and
+ must be a pin that the RP2350 can route that UART function to.
+ Overrideable for non-standard board layouts.
+
+config RP2350_EARLY_UART_RX_GPIO
+ int "Early UART RX GPIO number"
+ default 1 if RP2350_EARLY_UART_PORT = 0
+ default 5 if RP2350_EARLY_UART_PORT = 1
+ help
+ GPIO pin for UART RX. Must match the UART port chosen above.
+
+endif # RP2350_EARLY_UART
+
+config TARGET_RPI_PICO2
+ bool "Raspberry Pi Pico 2"
+ help
+ Raspberry Pi Pico 2 board based on RP2350 SoC.
+
+source "board/raspberrypi/pico2/Kconfig"
+
+endif # RP2350
+
+endif # ARCH_RP2XXX
new file mode 100644
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+obj-y += rp2350.o
+obj-y += image_def.o
new file mode 100644
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* RP2350 PICOBIN metadata block - placed after the stored vector table */
+
+ .section .image_def, "a"
+ .align 4
+ .global rp2350_image_def
+
+rp2350_image_def:
+ .word 0xffffded3 /* PICOBIN_BLOCK_MARKER_START */
+
+ /* IMAGE_TYPE: EXE | Secure | Arm | RP2350. */
+ .byte 0x42
+ .byte 0x01
+ .hword 0x1021
+
+rp2350_image_def_end_items:
+ .byte 0xff /* PICOBIN_BLOCK_ITEM_2BS_LAST */
+ .hword (rp2350_image_def_end - rp2350_image_def - 16) / 4
+ .byte 0x00
+
+ .word 0x00000000 /* Relative pointer to next block: self-loop */
+ .word 0xab123579 /* PICOBIN_BLOCK_MARKER_END */
+rp2350_image_def_end:
new file mode 100644
@@ -0,0 +1,213 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <init.h>
+#include <hang.h>
+#include <asm/io.h>
+#include <asm/armv7_mpu.h>
+#include <asm/arch/rp2350.h>
+
+#define RP2350_RESET_WAIT_LOOPS 1000000U
+
+static void rp2350_wait_reset_done(u32 mask)
+{
+ unsigned int loops = RP2350_RESET_WAIT_LOOPS;
+
+ while (loops--) {
+ if ((readl(&RP2350_RESETS->reset_done) & mask) == mask)
+ return;
+ }
+ /* something is very wrong */
+ hang();
+}
+
+int print_cpuinfo(void)
+{
+ printf("CPU: Raspberry Pi RP2350\n");
+ return 0;
+}
+
+/*
+ * rp2350_xosc_init() - Start the 12MHz crystal oscillator
+ *
+ * The XOSC must be stable before we can configure the PLLs.
+ * RP2350 uses a 12MHz crystal on XIN/XOUT pins.
+ */
+static void rp2350_xosc_init(void)
+{
+ struct rp2350_xosc_regs *xosc = RP2350_XOSC;
+
+ /* Set frequency range (1-15MHz) and startup delay (~1ms) */
+ writel(XOSC_CTRL_FREQ_RANGE_1_15MHZ, &xosc->ctrl);
+ writel(XOSC_STARTUP_DELAY, &xosc->startup);
+
+ /* Enable the oscillator */
+ writel(XOSC_CTRL_FREQ_RANGE_1_15MHZ | XOSC_CTRL_ENABLE, &xosc->ctrl);
+
+ /* Wait for XOSC to become stable */
+ while (!(readl(&xosc->status) & XOSC_STATUS_STABLE))
+ ;
+}
+
+/*
+ * rp2350_pll_init() - Configure PLL_SYS for 150MHz
+ *
+ * Target: 150MHz system clock
+ * XOSC = 12MHz
+ * VCO = 12MHz * 125 = 1500MHz (FBDIV=125, REFDIV=1)
+ * SYS = 1500MHz / 5 / 2 = 150MHz (POSTDIV1=5, POSTDIV2=2)
+ */
+static void rp2350_pll_sys_init(void)
+{
+ struct rp2350_pll_regs *pll = RP2350_PLL_SYS;
+ struct rp2350_resets_regs *resets = RP2350_RESETS;
+
+ /* Reset PLL */
+ rp2350_reg_set(&resets->reset, RESETS_RESET_PLL_SYS);
+ rp2350_reg_clr(&resets->reset, RESETS_RESET_PLL_SYS);
+ rp2350_wait_reset_done(RESETS_RESET_PLL_SYS);
+
+ /* Configure: REFDIV=1 */
+ writel(1, &pll->cs);
+
+ /* Power up only VCO and set feedback divisor */
+ writel(PLL_PWR_POSTDIVPD | PLL_PWR_DSMPD, &pll->pwr);
+
+ writel(125, &pll->fbdiv_int); /* VCO = 12 * 125 = 1500MHz */
+
+ /* Wait for VCO lock */
+ while (!(readl(&pll->cs) & PLL_CS_LOCK))
+ ;
+
+ /* Set post dividers: POSTDIV1=5, POSTDIV2=2 -> 150MHz */
+ writel((5 << PLL_PRIM_POSTDIV1_SHIFT) | (2 << PLL_PRIM_POSTDIV2_SHIFT),
+ &pll->prim);
+
+ /* Power up post dividers except DSM */
+ writel(PLL_PWR_DSMPD, &pll->pwr);
+}
+
+/*
+ * rp2350_clocks_init() - Switch system clock to PLL_SYS (150MHz)
+ *
+ * After PLL is locked:
+ * 1. Switch CLK_REF to XOSC
+ * 2. Switch CLK_SYS to PLL_SYS
+ * 3. Enable CLK_PERI from CLK_SYS (for UART etc)
+ */
+static void rp2350_clocks_init(void)
+{
+ struct rp2350_clocks_regs *clocks = RP2350_CLOCKS;
+
+ /*
+ * CLK_REF → XOSC
+ * SRC field [1:0] selects the glitchless mux input directly.
+ */
+ clrsetbits_le32(&clocks->clk_ref_ctrl, 0x3, CLK_REF_SRC_XOSC);
+ while (!(readl(&clocks->clk_ref_selected) & BIT(CLK_REF_SRC_XOSC)))
+ ;
+
+ /*
+ * CLK_SYS → PLL_SYS
+ */
+ /* set AUXSRC = PLL_SYS, leave SRC unchanged */
+ clrsetbits_le32(&clocks->clk_sys_ctrl, (0x7 << 5),
+ (CLK_SYS_SRC_PLL_SYS << 5));
+
+ /* switch glitchless mux to aux */
+ clrsetbits_le32(&clocks->clk_sys_ctrl, 0x3, 0x1);
+ clrsetbits_le32(&clocks->clk_sys_ctrl, 0x3, CLK_SYS_SRC_AUX);
+
+ /* Wait for CLK_SYS to settle on the aux source (bit 1) */
+ while (!(readl(&clocks->clk_sys_selected) & BIT(1)))
+ ;
+
+ /*
+ * CLK_PERI → CLK_SYS (150MHz)
+ * bit 11 = ENABLE
+ * bits [7:5] = AUXSRC: clk_sys
+ */
+ writel(BIT(11) | (CLK_PERI_SRC_CLK_SYS << 5), &clocks->clk_peri_ctrl);
+}
+
+/*
+ * rp2350_uart_early_init() - Minimal UART init for early console
+ *
+ * Called before driver model is up. Sets up UART1 at 115200 8N1.
+ * GPIO pins for UART1: TX=GPIO4, RX=GPIO5
+ * Clock source: CLK_SYS == CLK_PERI == 150MHz
+ */
+void rp2350_uart_early_init(void)
+{
+ struct rp2350_uart_regs *uart = RP2350_EARLY_UART;
+ struct rp2350_resets_regs *resets = RP2350_RESETS;
+ u32 pad;
+ unsigned int tx = CONFIG_RP2350_EARLY_UART_TX_GPIO;
+ unsigned int rx = CONFIG_RP2350_EARLY_UART_RX_GPIO;
+
+ /* Ensure IO_BANK0/PADS_BANK0 and UART1 are all out of reset. */
+ rp2350_reg_clr(&resets->reset,
+ RESETS_RESET_IO_BANK0 |
+ RESETS_RESET_PADS_BANK0);
+
+ rp2350_wait_reset_done(RESETS_RESET_IO_BANK0 |
+ RESETS_RESET_PADS_BANK0);
+
+ /*
+ * Match SDK gpio_set_function() behavior for UART pins.
+ */
+ pad = readl((void *)RP2350_PADS_BANK0_GPIO(tx));
+ pad &= ~(RP2350_PAD_OD | RP2350_PAD_ISO);
+ pad |= RP2350_PAD_IE;
+ writel(pad, (void *)RP2350_PADS_BANK0_GPIO(tx));
+
+ pad = readl((void *)RP2350_PADS_BANK0_GPIO(rx));
+ pad &= ~(RP2350_PAD_OD | RP2350_PAD_ISO);
+ pad |= RP2350_PAD_IE;
+ writel(pad, (void *)RP2350_PADS_BANK0_GPIO(rx));
+
+ writel(RP2350_GPIO_FUNC_UART, (void *)RP2350_IO_BANK0_GPIO_CTRL(tx));
+ writel(RP2350_GPIO_FUNC_UART, (void *)RP2350_IO_BANK0_GPIO_CTRL(rx));
+
+ /* Release UART from reset */
+ rp2350_reg_set(&resets->reset, RESETS_RESET_EARLY_UART);
+ rp2350_reg_clr(&resets->reset, RESETS_RESET_EARLY_UART);
+ rp2350_wait_reset_done(RESETS_RESET_EARLY_UART);
+
+ /* Disable UART before configuration */
+ writel(0, &uart->cr);
+
+ /* Set baud rate: 115200 at 150MHz CLK_SYS/CLK_PERI
+ * BAUDDIV = 150000000 / (16 * 115200) = 81.3802
+ * IBRD = 81, FBRD = round(0.3802 * 64) = 24
+ */
+ writel(RP2350_UART_IBRD_115200, &uart->ibrd);
+ writel(RP2350_UART_FBRD_115200, &uart->fbrd);
+
+ /* 8N1, FIFO enabled */
+ writel(UART_LCR_H_WLEN_8 | UART_LCR_H_FEN, &uart->lcr_h);
+
+ /* Enable UART, TX, RX */
+ writel(UART_CR_UARTEN | UART_CR_TXE | UART_CR_RXE, &uart->cr);
+}
+
+/*
+ * rp2350_soc_init() - Full SoC initialization sequence
+ *
+ * Called from board_init_f() early path.
+ * Order matters:
+ * 1. XOSC - stable reference clock
+ * 2. PLL - multiply up to 150MHz
+ * 3. Clocks - switch system to PLL
+ * 4. UART - console ready
+ */
+void rp2350_soc_init(void)
+{
+ /* Start XOSC (12MHz crystal) for a stable, precise clock */
+ rp2350_xosc_init();
+ /* Setup PLL */
+ rp2350_pll_sys_init();
+ /* Setup clocks to use PLL and set 150MHz for clk_sys/clk_peri */
+ rp2350_clocks_init();
+ /* Now init UART - it will source clk_peri from clk_sys */
+ rp2350_uart_early_init();
+}
new file mode 100644
@@ -0,0 +1,94 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * RP2350 U-Boot linker script
+ *
+ * Based on arch/arm/cpu/u-boot.lds
+ * Modified to include RP2350 IMAGE_DEF block after vector table
+ */
+
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+ . = 0x00000000;
+
+ . = ALIGN(4);
+ __image_copy_start = ADDR(.text);
+ .text :
+ {
+ *(.vectors) /* Cortex-M33 vector table at image start */
+ KEEP(*(.image_def)) /* RP2350 IMAGE_DEF block loop */
+ arch/arm/cpu/armv7m/start.o (.text*)
+ }
+
+ .efi_runtime : {
+ __efi_runtime_start = .;
+ *(.text.efi_runtime*)
+ *(.rodata.efi_runtime*)
+ *(.data.efi_runtime*)
+ __efi_runtime_stop = .;
+ }
+
+ .text_rest :
+ {
+ *(.text*)
+ }
+
+ . = ALIGN(4);
+ .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
+
+ . = ALIGN(4);
+ .data : {
+ *(.data*)
+ }
+
+ . = ALIGN(4);
+ . = .;
+ . = ALIGN(4);
+
+ __u_boot_list : {
+ KEEP(*(SORT(__u_boot_list*)));
+ }
+
+ .efi_runtime_rel : {
+ __efi_runtime_rel_start = .;
+ *(.rel*.efi_runtime)
+ *(.rel*.efi_runtime.*)
+ __efi_runtime_rel_stop = .;
+ }
+
+ . = ALIGN(8);
+ __image_copy_end = .;
+
+ .rel.dyn ALIGN(8) : {
+ __rel_dyn_start = .;
+ *(.rel*)
+ __rel_dyn_end = .;
+ . = ALIGN(8);
+ }
+
+ _end = .;
+ _image_binary_end = .;
+
+ .bss ADDR(.rel.dyn) (OVERLAY): {
+ __bss_start = .;
+ *(.bss*)
+ . = ALIGN(4);
+ __bss_end = .;
+ }
+
+ /DISCARD/ : { *(.dynsym) }
+ /DISCARD/ : { *(.dynbss) }
+ /DISCARD/ : { *(.dynstr*) }
+ /DISCARD/ : { *(.dynamic*) }
+ /DISCARD/ : { *(.plt*) }
+ /DISCARD/ : { *(.interp*) }
+ /DISCARD/ : { *(.gnu.hash) }
+ /DISCARD/ : { *(.gnu*) }
+ /DISCARD/ : { *(.ARM.exidx*) }
+ /DISCARD/ : { *(.gnu.linkonce.armexidx.*) }
+}
+
+ASSERT(_image_binary_end % 8 == 0, \
+ "_image_binary_end must be 8-byte aligned for device tree");
Add initial U-Boot architecture support for the RP2350 SoC. RP2350 specs: - CPU: Dual-core Arm Cortex-M33 or dual-core RISC-V Hazard3 @ 150MHz. - Memory: 520 KB on-chip SRAM, 4 MB on-board QSPI flash. Only Arm core support is added here. The architecture is added under arch/arm/mach-rp2xxx/. This patch implements early SoC bring-up: - XOSC (12MHz crystal) startup - PLL_SYS configuration to 150MHz - CLK_REF/CLK_SYS/CLK_PERI clock switching - UART1 early console init (115200 8N1) Cortex-M33 is an Armv8-M core, but U-Boot does not yet have a CPU_V8M architecture variant. Currently there is no arch_cpu_init() setup for this architecture. Signed-off-by: Bhargav Das <bhargavdas100@gmail.com> --- arch/arm/Kconfig | 7 + arch/arm/Makefile | 2 + arch/arm/include/asm/arch-rp2xxx/rp2350.h | 352 ++++++++++++++++++++++ arch/arm/mach-rp2xxx/Kconfig | 58 ++++ arch/arm/mach-rp2xxx/Makefile | 4 + arch/arm/mach-rp2xxx/image_def.S | 23 ++ arch/arm/mach-rp2xxx/rp2350.c | 213 +++++++++++++ arch/arm/mach-rp2xxx/u-boot.lds | 94 ++++++ 8 files changed, 753 insertions(+) create mode 100644 arch/arm/include/asm/arch-rp2xxx/rp2350.h create mode 100644 arch/arm/mach-rp2xxx/Kconfig create mode 100644 arch/arm/mach-rp2xxx/Makefile create mode 100644 arch/arm/mach-rp2xxx/image_def.S create mode 100644 arch/arm/mach-rp2xxx/rp2350.c create mode 100644 arch/arm/mach-rp2xxx/u-boot.lds