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 <[email protected]>
---
 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

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 1b474a346bf..af582e91383 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -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"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index de975fc9368..2131e92a6a4 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -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))
diff --git a/arch/arm/include/asm/arch-rp2xxx/rp2350.h 
b/arch/arm/include/asm/arch-rp2xxx/rp2350.h
new file mode 100644
index 00000000000..738fa20be96
--- /dev/null
+++ b/arch/arm/include/asm/arch-rp2xxx/rp2350.h
@@ -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_ */
diff --git a/arch/arm/mach-rp2xxx/Kconfig b/arch/arm/mach-rp2xxx/Kconfig
new file mode 100644
index 00000000000..c914cf7a521
--- /dev/null
+++ b/arch/arm/mach-rp2xxx/Kconfig
@@ -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
diff --git a/arch/arm/mach-rp2xxx/Makefile b/arch/arm/mach-rp2xxx/Makefile
new file mode 100644
index 00000000000..7da1928d6bb
--- /dev/null
+++ b/arch/arm/mach-rp2xxx/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+obj-y  += rp2350.o
+obj-y   += image_def.o
diff --git a/arch/arm/mach-rp2xxx/image_def.S b/arch/arm/mach-rp2xxx/image_def.S
new file mode 100644
index 00000000000..7854d94f6ea
--- /dev/null
+++ b/arch/arm/mach-rp2xxx/image_def.S
@@ -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:
diff --git a/arch/arm/mach-rp2xxx/rp2350.c b/arch/arm/mach-rp2xxx/rp2350.c
new file mode 100644
index 00000000000..69ef2daa89b
--- /dev/null
+++ b/arch/arm/mach-rp2xxx/rp2350.c
@@ -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();
+}
diff --git a/arch/arm/mach-rp2xxx/u-boot.lds b/arch/arm/mach-rp2xxx/u-boot.lds
new file mode 100644
index 00000000000..200c37d6a13
--- /dev/null
+++ b/arch/arm/mach-rp2xxx/u-boot.lds
@@ -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");
-- 
2.43.0

Reply via email to