diff options
117 files changed, 7281 insertions, 1564 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index e5b2a2e373c..323b1b172b1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -81,7 +81,7 @@ M: Mattijs Korpershoek <[email protected]> R: Igor Opaniuk <[email protected]> R: Sam Protsenko <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-dfu.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-dfu.git F: boot/android_ab.c F: doc/android/ab.rst F: include/android_ab.h @@ -91,7 +91,7 @@ ANDROID AVB M: Mattijs Korpershoek <[email protected]> R: Igor Opaniuk <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-dfu.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-dfu.git F: cmd/avb.c F: common/avb_verify.c F: doc/android/avb2.rst @@ -104,7 +104,7 @@ M: Alexey Brodkin <[email protected]> M: Eugeniy Paltsev <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-arc.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-arc.git F: arch/arc/ F: board/synopsys/ @@ -162,7 +162,7 @@ ARM M: Tom Rini <[email protected]> M: Ilias Apalodimas <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-arm.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-arm.git F: arch/arm/ F: arch/arm/dts/Makefile F: cmd/arm/ @@ -172,7 +172,7 @@ M: Marek Vasut <[email protected]> M: Simon Goldschmidt <[email protected]> M: Tien Fong Chee <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-socfpga.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-socfpga.git F: arch/arm/dts/socfpga_* F: arch/arm/mach-socfpga/ F: board/intel/agilex-socdk/ @@ -185,7 +185,7 @@ ARM AMLOGIC SOC SUPPORT M: Neil Armstrong <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-amlogic.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-amlogic.git F: arch/arm/mach-meson/ F: arch/arm/include/asm/arch-meson/ F: cmd/meson/ @@ -251,7 +251,7 @@ F: include/dm/platform_data/serial_bcm283x_mu.h F: include/dt-bindings/pinctrl/bcm2835.h F: drivers/pinctrl/broadcom/ F: configs/rpi_* -T: git https://source.denx.de/u-boot/custodians/u-boot-arm.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-arm.git ARM BROADCOM BCMBCA M: Anand Gore <[email protected]> @@ -314,7 +314,7 @@ M: Stefano Babic <[email protected]> M: Fabio Estevam <[email protected]> R: NXP i.MX U-Boot Team <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-imx.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-imx.git N: imx N: mxc N: nxp @@ -365,7 +365,7 @@ F: drivers/misc/ls2_sfp.c ARM MARVELL KIRKWOOD ARMADA-XP ARMADA-38X ARMADA-37XX ARMADA-7K/8K M: Stefan Roese <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-marvell.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-marvell.git F: arch/arm/mach-kirkwood/ F: arch/arm/mach-mvebu/ F: drivers/ata/ahci_generic.c @@ -388,7 +388,7 @@ F: include/configs/mv-common.h ARM MARVELL PCIE CONTROLLER DRIVERS M: Stefan Roese <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-marvell.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-marvell.git F: drivers/pci/pci-aardvark.c F: drivers/pci/pci_mvebu.c @@ -404,7 +404,7 @@ ARM MARVELL SERIAL DRIVERS M: Pali Rohár <[email protected]> M: Stefan Roese <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-marvell.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-marvell.git F: drivers/serial/serial_mvebu_a3700.c ARM MEDIATEK @@ -415,7 +415,7 @@ M: Igor Belwon <[email protected]> M: David Lechner <[email protected]> M: Julien Stephan <[email protected]> R: GSS_MTK_Uboot_upstream <[email protected]> -T: git https://source.denx.de/u-boot/custodians/u-boot-mediatek.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-mediatek.git S: Maintained F: arch/arm/dts/mt* F: arch/arm/mach-mediatek/ @@ -470,7 +470,7 @@ F: configs/uDPU_defconfig ARM MICROCHIP/ATMEL AT91 M: Eugen Hristev <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-at91.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-at91.git F: arch/arm/dts/at91* F: arch/arm/dts/sam* F: arch/arm/mach-at91/ @@ -530,7 +530,7 @@ ARM RENESAS RMOBILE/R-CAR M: Nobuhiro Iwamatsu <[email protected]> M: Marek Vasut <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-sh.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-sh.git F: arch/arm/mach-renesas/ F: drivers/clk/renesas/ F: drivers/gpio/gpio-rcar.c @@ -558,7 +558,7 @@ M: Simon Glass <[email protected]> M: Quentin Schulz <[email protected]> M: Kever Yang <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-rockchip.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-rockchip.git # Exclude from N: px5 matches X: configs/kmsupx5_defconfig N: px30 @@ -588,7 +588,7 @@ F: tools/rkspi.c ARM SAMSUNG M: Minkyu Kang <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-samsung.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-samsung.git F: arch/arm/mach-exynos/ F: arch/arm/mach-s5pc1xx/ F: arch/arm/cpu/armv7/s5p-common/ @@ -661,7 +661,7 @@ M: Neil Armstrong <[email protected]> R: Sumit Garg <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-snapdragon.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-snapdragon.git F: configs/qcm6490_defconfig F: configs/qcs9100_defconfig F: drivers/*/*/pm8???-* @@ -681,7 +681,7 @@ N: qualcomm ARM STI M: Patrice Chotard <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-stm.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-stm.git F: arch/arm/mach-sti/ F: arch/arm/include/asm/arch-sti*/ F: drivers/phy/sti_usb_phy.c @@ -700,7 +700,7 @@ ARM STM STM32MP M: Patrick Delaunay <[email protected]> M: Patrice Chotard <[email protected]> L: [email protected] (moderated for non-subscribers) -T: git https://source.denx.de/u-boot/custodians/u-boot-stm.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-stm.git S: Maintained F: arch/arm/mach-stm32mp/ F: doc/board/st/ @@ -746,7 +746,7 @@ N: stm32 ARM SUNXI M: Andre Przywara <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-sunxi.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-sunxi.git F: arch/arm/cpu/armv7/sunxi/ F: arch/arm/include/asm/arch-sunxi/ F: arch/arm/mach-sunxi/ @@ -761,7 +761,7 @@ ARM TEGRA M: Thierry Reding <[email protected]> M: Svyatoslav Ryhel <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-tegra.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-tegra.git F: arch/arm/dts/tegra* F: arch/arm/include/asm/arch-tegra*/ F: arch/arm/mach-tegra/ @@ -771,7 +771,7 @@ F: drivers/*/tegra*/ ARM TI M: Tom Rini <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-ti.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-ti.git F: arch/arm/dts/am57xx* F: arch/arm/dts/dra7* F: arch/arm/mach-davinci/ @@ -848,7 +848,7 @@ N: uniphier ARM VERSAL NET M: Michal Simek <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-microblaze.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-microblaze.git F: arch/arm/mach-versal-net/ F: drivers/soc/soc_xilinx_versal_net.c N: (?<!uni)versal-net @@ -856,7 +856,7 @@ N: (?<!uni)versal-net ARM VERSAL M: Michal Simek <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-microblaze.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-microblaze.git F: arch/arm/mach-versal/ F: drivers/net/xilinx_axi_mrmac.* F: drivers/soc/soc_xilinx_versal.c @@ -875,7 +875,7 @@ ARM ZYNQ and ZYNQMP M: Michal Simek <[email protected]> M: Michal Simek <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-microblaze.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-microblaze.git F: doc/board/xilinx/ F: doc/device-tree-bindings/video/syncoam,seps525.txt F: drivers/gpio/gpio_slg7xl45106.c @@ -893,7 +893,7 @@ N: zynq ARM ZYNQMP R5 M: Michal Simek <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-microblaze.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-microblaze.git F: arch/arm/mach-zynqmp-r5/ ARM PHYTIUM @@ -956,7 +956,7 @@ F: test/boot/ BOOTMETH_ANDROID M: Mattijs Korpershoek <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-dfu.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-dfu.git F: boot/bootmeth_android.c F: boot/bootmeth_android.h F: doc/develop/bootstd/android.rst @@ -990,14 +990,14 @@ F: cmd/cat.c CFI FLASH M: Stefan Roese <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-cfi-flash.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-cfi-flash.git F: drivers/mtd/cfi_flash.c F: drivers/mtd/jedec_flash.c CLOCK M: Lukasz Majewski <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-clk.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-clk.git F: drivers/clk/ F: drivers/clk/imx/ @@ -1025,7 +1025,7 @@ DFU M: Lukasz Majewski <[email protected]> M: Mattijs Korpershoek <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-dfu.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-dfu.git F: cmd/dfu.c F: cmd/usb_*.c F: common/dfu.c @@ -1043,7 +1043,7 @@ F: include/linux/usb/gadget.h DRIVER MODEL M: Simon Glass <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-dm.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-dm.git F: doc/driver-model/ F: drivers/core/ F: include/dm/ @@ -1067,7 +1067,7 @@ EFI LOADER M: Heinrich Schuchardt <[email protected]> M: Ilias Apalodimas <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-efi.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-efi.git F: arch/arm/lib/*_efi.* F: cmd/bootefi.c F: cmd/eficonfig.c @@ -1146,7 +1146,7 @@ F: include/extension_board.h FASTBOOT M: Mattijs Korpershoek <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-dfu.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-dfu.git F: cmd/fastboot.c F: doc/android/fastboot*.rst F: include/fastboot.h @@ -1162,7 +1162,7 @@ F: test/dm/fastboot.c FPGA M: Michal Simek <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-microblaze.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-microblaze.git F: drivers/fpga/ F: cmd/fpga.c F: include/fpga.h @@ -1171,7 +1171,7 @@ F: test/dm/fpga.c FLATTENED DEVICE TREE M: Simon Glass <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-fdt.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-fdt.git F: lib/fdtdec* F: lib/libfdt/ F: include/fdt* @@ -1183,12 +1183,12 @@ F: scripts/dtc-version.sh FREEBSD M: Rafal Jaworowski <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-freebsd.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-freebsd.git FREESCALE QORIQ M: Peng Fan <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-fsl-qoriq.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-fsl-qoriq.git F: drivers/watchdog/sp805_wdt.c F: drivers/watchdog/sbsa_gwdt.c @@ -1196,7 +1196,7 @@ FWU Multi Bank Update M: Sughosh Ganu <[email protected]> M: Kory Maincent <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-efi.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-efi.git F: doc/fwumdata.1 F: doc/mkfwumdata.1 F: lib/fwu_updates/* @@ -1226,7 +1226,7 @@ F: include/goldfish_timer.h INTERCONNECT M: Neil Armstrong <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/u-boot.git +T: git https://git.u-boot-project.org/u-boot/u-boot.git F: arch/sandbox/include/asm/interconnect.h F: doc/api/interconnect.rst F: drivers/interconnect/ @@ -1237,13 +1237,13 @@ F: test/dm/interconnect.c I2C M: Heiko Schocher <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-i2c.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-i2c.git F: drivers/i2c/ I3C M: Dinesh <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/u-boot.git +T: git https://git.u-boot-project.org/u-boot/u-boot.git F: cmd/i3c.c F: drivers/i3c/ @@ -1257,7 +1257,7 @@ M: Pali Rohár <[email protected]> M: Marek Behún <[email protected]> M: Stefan Roese <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-marvell.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-marvell.git F: doc/README.kwbimage F: doc/kwboot.1 F: tools/kwb* @@ -1265,7 +1265,7 @@ F: tools/kwb* LOGGING M: Simon Glass <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/u-boot.git +T: git https://git.u-boot-project.org/u-boot/u-boot.git F: common/log* F: cmd/log.c F: doc/develop/logging.rst @@ -1284,7 +1284,7 @@ M68K M: Angelo Dureghello <[email protected]> M: Kuan-Wei Chiu <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-coldfire.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-coldfire.git F: arch/m68k/ F: doc/arch/m68k.rst F: drivers/watchdog/mcf_wdt.c @@ -1304,14 +1304,14 @@ F: lib/mbedtls/ MEMBUF M: Simon Glass <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/u-boot.git +T: git https://git.u-boot-project.org/u-boot/u-boot.git F: include/membuf.h F: lib/membuf.c MICROBLAZE M: Michal Simek <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-microblaze.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-microblaze.git F: arch/microblaze/ F: cmd/mfsl.c F: drivers/gpio/xilinx_gpio.c @@ -1327,7 +1327,7 @@ N: xilinx MIPS M: Daniel Schwierzeck <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-mips.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-mips.git F: arch/mips/ MIPS CORTINA ACCESS CAxxxx @@ -1351,7 +1351,7 @@ M: Weijie Gao <[email protected]> M: David Lechner <[email protected]> M: Julien Stephan <[email protected]> R: GSS_MTK_Uboot_upstream <[email protected]> -T: git https://source.denx.de/u-boot/custodians/u-boot-mediatek.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-mediatek.git S: Maintained F: arch/mips/mach-mtmips/ F: arch/mips/dts/mt7620.dtsi @@ -1416,14 +1416,14 @@ MMC M: Peng Fan <[email protected]> M: Jaehoon Chung <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-mmc.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-mmc.git F: drivers/mmc/ N: mmc NETWORK M: Jerome Forissier <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-net.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-net.git F: drivers/net/ F: include/net.h F: net/ @@ -1431,7 +1431,7 @@ F: net/ NETWORK (LWIP) M: Jerome Forissier <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-net.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-net.git F: cmd/lwip/ F: cmd/net-lwip.c F: configs/qemu_arm64_lwip_defconfig @@ -1444,7 +1444,7 @@ F: net/lwip/ NIOS M: Thomas Chou <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-nios.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-nios.git F: arch/nios2/ NVMe @@ -1480,7 +1480,7 @@ F: drivers/net/phy/nxp-c45-tja11xx.c ONENAND #M: Lukasz Majewski <[email protected]> S: Orphaned (Since 2017-01) -T: git https://source.denx.de/u-boot/custodians/u-boot-onenand.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-onenand.git F: drivers/mtd/onenand/ OUT4-IMX6ULL-NANO BOARD @@ -1551,7 +1551,7 @@ POWER M: Jaehoon Chung <[email protected]> M: Peng Fan <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-pmic.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-pmic.git F: drivers/power/ F: include/power/ @@ -1562,13 +1562,13 @@ F: arch/powerpc/ POWERPC MPC8XX M: Christophe Leroy <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-mpc8xx.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-mpc8xx.git F: arch/powerpc/cpu/mpc8xx/ POWERPC MPC83XX M: Mario Six <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-mpc83xx.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-mpc83xx.git F: drivers/ram/mpc83xx_sdram.c F: include/dt-bindings/memory/mpc83xx-sdram.h F: drivers/sysreset/sysreset_mpc83xx.c @@ -1586,7 +1586,7 @@ F: arch/powerpc/include/asm/arch-mpc83xx/ POWERPC MPC85XX M: Marek Behún <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-mpc85xx.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-mpc85xx.git F: arch/powerpc/cpu/mpc85xx/ PWM LED @@ -1604,14 +1604,14 @@ RAW NAND M: Dario Binacchi <[email protected]> M: Michael Trimarchi <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-nand-flash.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-nand-flash.git F: drivers/mtd/nand/raw/ RISC-V -M: Rick Chen <[email protected]> -M: Leo <[email protected]> +M: Tim Ouyang <[email protected]> +M: Leo Liang <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-riscv.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-riscv.git F: arch/riscv/ F: cmd/riscv/ F: doc/arch/riscv.rst @@ -1700,7 +1700,7 @@ SH M: Marek Vasut <[email protected]> M: Nobuhiro Iwamatsu <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-sh.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-sh.git F: arch/sh/ SL28CLPD @@ -1740,7 +1740,7 @@ F: drivers/rng/smccc_trng.c SPI S: Orphaned -T: git https://source.denx.de/u-boot/custodians/u-boot-spi.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-spi.git F: drivers/spi/ F: include/spi* @@ -1749,7 +1749,7 @@ M: Dario Binacchi <[email protected]> M: Michael Trimarchi <[email protected]> R: Frieder Schrempf <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-nand-flash.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-nand-flash.git F: drivers/mtd/nand/spi/ SPI-NOR @@ -1838,7 +1838,7 @@ F: configs/k2l_hs_evm_defconfig TPM DRIVERS M: Ilias Apalodimas <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-tpm.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-tpm.git F: cmd/tpm* F: drivers/tpm/ F: include/tpm* @@ -1857,7 +1857,7 @@ F: include/env/tq/* TEE M: Jens Wiklander <[email protected]> M: Ilias Apalodimas <[email protected]> -T: git https://source.denx.de/u-boot/custodians/u-boot-tpm.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-tpm.git S: Maintained F: cmd/optee* F: doc/README.tee @@ -1881,7 +1881,7 @@ UBI M: Kyungmin Park <[email protected]> M: Heiko Schocher <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-ubi.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-ubi.git F: drivers/mtd/ubi/ UFETCH @@ -1900,7 +1900,7 @@ F: drivers/ufs/ UPL M: Simon Glass <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-dm.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-dm.git F: boot/upl* F: cmd/upl.c F: common/spl/spl_upl.c @@ -1913,7 +1913,7 @@ F: test/py/tests/test_upl.py USB M: Marek Vasut <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-usb.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-usb.git F: drivers/usb/ F: common/usb.c F: common/usb_kbd.c @@ -1932,7 +1932,7 @@ F: include/usb/tcpm.h USB xHCI M: Bin Meng <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-usb.git topic-xhci +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-usb.git topic-xhci F: drivers/usb/host/xhci* F: include/usb/xhci.h @@ -1960,7 +1960,7 @@ F: include/vbe.h VIDEO M: Anatolij Gustschin <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-video.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-video.git F: drivers/video/ F: include/video*.h @@ -1979,7 +1979,7 @@ F: doc/develop/driver-model/virtio.rst WATCHDOG M: Stefan Roese <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-watchdog.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-watchdog.git F: cmd/wdt.c F: drivers/watchdog/ F: include/watchdog*.h @@ -1988,7 +1988,7 @@ X86 M: Simon Glass <[email protected]> M: Bin Meng <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-x86.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-x86.git F: arch/x86/ F: cmd/x86/ @@ -2022,10 +2022,10 @@ F: test/py/tests/test_xxd/ THE REST M: Tom Rini <[email protected]> Q: http://patchwork.ozlabs.org/project/uboot/list/ S: Maintained -T: git https://source.denx.de/u-boot/u-boot.git +T: git https://git.u-boot-project.org/u-boot/u-boot.git F: configs/tools-only_defconfig F: * F: */ @@ -45,17 +45,17 @@ Where to get help: In case you have questions about, problems with or contributions for U-Boot, you should send a message to the U-Boot mailing list at -<[email protected]>. There is also an archive of previous traffic +<[email protected]>. There is also an archive of previous traffic on the mailing list - please search the archive before asking FAQ's. -Please see https://lists.denx.de/pipermail/u-boot and +Please see https://lists.u-boot-project.org/pipermail/u-boot and https://marc.info/?l=u-boot Where to get source code: ========================= The U-Boot source code is maintained in the Git repository at -https://source.denx.de/u-boot/u-boot.git ; you can browse it online at -https://source.denx.de/u-boot/u-boot +https://git.u-boot-project.org/u-boot/u-boot.git ; you can browse it online at +https://git.u-boot-project.org/u-boot/u-boot The "Tags" links on this page allow you to download tarballs of any version you might be interested in. Official releases are also diff --git a/arch/arm/dts/armada-3720-turris-mox.dts b/arch/arm/dts/armada-3720-turris-mox.dts index 595b4b5abba..1123a81a1a4 100644 --- a/arch/arm/dts/armada-3720-turris-mox.dts +++ b/arch/arm/dts/armada-3720-turris-mox.dts @@ -147,12 +147,12 @@ * for IO and the rest 112 MB (64+32+16) for MEM. Controller supports 32-bit IO mapping. * This bug is not present in U-Boot ports for other Armada 3700 devices and is fixed in * U-Boot version 2021.07. See relevant U-Boot commits (the last one contains fix): - * https://source.denx.de/u-boot/u-boot/-/commit/cb2ddb291ee6fcbddd6d8f4ff49089dfe580f5d7 - * https://source.denx.de/u-boot/u-boot/-/commit/c64ac3b3185aeb3846297ad7391fc6df8ecd73bf - * https://source.denx.de/u-boot/u-boot/-/commit/4a82fca8e330157081fc132a591ebd99ba02ee33 + * https://git.u-boot-project.org/u-boot/u-boot/-/commit/cb2ddb291ee6fcbddd6d8f4ff49089dfe580f5d7 + * https://git.u-boot-project.org/u-boot/u-boot/-/commit/c64ac3b3185aeb3846297ad7391fc6df8ecd73bf + * https://git.u-boot-project.org/u-boot/u-boot/-/commit/4a82fca8e330157081fc132a591ebd99ba02ee33 * Bug related to requirement of same child and parent addresses for first range is fixed * in U-Boot version 2022.04 by following commit: - * https://source.denx.de/u-boot/u-boot/-/commit/1fd54253bca7d43d046bba4853fe5fafd034bc17 + * https://git.u-boot-project.org/u-boot/u-boot/-/commit/1fd54253bca7d43d046bba4853fe5fafd034bc17 */ #address-cells = <3>; #size-cells = <2>; diff --git a/arch/arm/mach-k3/Kconfig b/arch/arm/mach-k3/Kconfig index 1b6678e72b7..a32ed3a9683 100644 --- a/arch/arm/mach-k3/Kconfig +++ b/arch/arm/mach-k3/Kconfig @@ -165,27 +165,6 @@ config K3_DM_FW bootloader, it makes RM and PM services not being available during R5 SPL execution time. -config K3_DM_FW_RESERVED_ADDR - hex "Start address of DM firmware reserved memory region" - depends on !SOC_K3_AM642 && !SOC_K3_AM654 - default 0x9c900000 if SOC_K3_AM62A7 || SOC_K3_AM62P5 - default 0x9db00000 if SOC_K3_AM625 - default 0xa0100000 if SOC_K3_J721E || SOC_K3_J7200 || SOC_K3_J721S2 || SOC_K3_J722S || SOC_K3_J784S4 - help - Start address of the DDR region reserved for DM firmware at runtime. - Used only to fixup the kernel device-tree reserved-memory node. - -config K3_DM_FW_RESERVED_SIZE - hex "Reserved memory size for DM firmware" - depends on !SOC_K3_AM642 && !SOC_K3_AM654 - default 0x1f00000 if SOC_K3_AM62A7 - default 0xc00000 if SOC_K3_AM625 - default 0x1e00000 if TARGET_VERDIN_AM62P_A53 || TARGET_VERDIN_AM62P_R5 - default 0xf00000 if SOC_K3_AM62P5 || SOC_K3_J721E || SOC_K3_J7200 || SOC_K3_J721S2 || SOC_K3_J722S || SOC_K3_J784S4 - help - The runtime memory size reserved for DM firmware. This is the total - DDR span needed for the DM firmware binary. - config K3_X509_SWRV int "SWRV for X509 certificate used for boot images" default 1 diff --git a/arch/arm/mach-k3/am62ax/Kconfig b/arch/arm/mach-k3/am62ax/Kconfig index e7c2a2de9be..6a3969343ec 100644 --- a/arch/arm/mach-k3/am62ax/Kconfig +++ b/arch/arm/mach-k3/am62ax/Kconfig @@ -54,7 +54,6 @@ config TARGET_AM62D2_A53_EVM bool "TI K3 based AM62D2 EVM running on A53" select ARM64 select BINMAN - select OF_SYSTEM_SETUP imply BOARD imply SPL_BOARD imply TI_I2C_BOARD_DETECT diff --git a/arch/arm/mach-k3/common_fdt.c b/arch/arm/mach-k3/common_fdt.c index 18f30e9d052..39cb00c3f43 100644 --- a/arch/arm/mach-k3/common_fdt.c +++ b/arch/arm/mach-k3/common_fdt.c @@ -119,6 +119,7 @@ static int fdt_fixup_reserved_memory(void *blob, const char *name, unsigned int new_size) { int nodeoffset, subnode; + int ret; struct fdt_memory carveout = { .start = new_address, }; @@ -128,27 +129,43 @@ static int fdt_fixup_reserved_memory(void *blob, const char *name, if (nodeoffset < 0) goto add_carveout; - /* Find existing matching subnode and update it in place */ + /* Find existing matching subnode and remove it */ fdt_for_each_subnode(subnode, blob, nodeoffset) { const char *node_name; - u64 reg[2]; + fdt_addr_t addr; + fdt_size_t size; /* Name matching */ node_name = fdt_get_name(blob, subnode, NULL); if (!name) return -EINVAL; if (!strncmp(node_name, name, strlen(name))) { - /* Update the reg property in place */ - reg[0] = cpu_to_fdt64(new_address); - reg[1] = cpu_to_fdt64(new_size); - return fdt_setprop(blob, subnode, "reg", reg, sizeof(reg)); + /* Read out old size first */ + addr = fdtdec_get_addr_size_auto_parent( + blob, nodeoffset, subnode, "reg", 0, &size, + false); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + new_size = size; + + /* Delete node */ + ret = fdt_del_node(blob, subnode); + if (ret < 0) + return ret; + + /* Only one matching node */ + break; } } add_carveout: carveout.end = new_address + new_size - 1; - return fdtdec_add_reserved_memory(blob, name, &carveout, NULL, 0, NULL, + ret = fdtdec_add_reserved_memory(blob, name, &carveout, NULL, 0, NULL, FDTDEC_RESERVED_MEMORY_NO_MAP); + if (ret < 0) + return ret; + + return 0; } int fdt_fixup_reserved(void *blob) @@ -160,23 +177,9 @@ int fdt_fixup_reserved(void *blob) if (ret) return ret; - ret = fdt_fixup_reserved_memory(blob, "optee", - CONFIG_K3_OPTEE_LOAD_ADDR, - CONFIG_K3_OPTEE_RESERVED_SIZE); - - if (ret) - return ret; - -#if defined(CONFIG_K3_DM_FW_RESERVED_ADDR) && defined(CONFIG_K3_DM_FW_RESERVED_SIZE) - ret = fdt_fixup_reserved_memory(blob, "dm", - CONFIG_K3_DM_FW_RESERVED_ADDR, - CONFIG_K3_DM_FW_RESERVED_SIZE); - - if (ret) - return ret; -#endif - - return 0; + return fdt_fixup_reserved_memory(blob, "optee", + CONFIG_K3_OPTEE_LOAD_ADDR, + CONFIG_K3_OPTEE_RESERVED_SIZE); } static int fdt_fixup_critical_trips(void *blob, int zoneoffset, int maxc) diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index ad7589123c6..485067ed266 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -14,9 +14,6 @@ config TARGET_ANDES_AE350 config TARGET_ANDES_VOYAGER bool "Support Andes Voyager Board" -config TARGET_BANANAPI_F3 - bool "Support BananaPi F3 Board" - config TARGET_BEAGLEBOARD_BEAGLEVFIRE bool "Support BeagleBoard BeagleV-Fire Board (based on Microchip MPFS)" @@ -50,6 +47,9 @@ config TARGET_SIPEED_MAIX bool "Support Sipeed Maix Board" select SYS_CACHE_SHIFT_6 +config TARGET_SPACEMIT_K1 + bool "Support Spacemit K1 SoC" + config TARGET_STARFIVE_VISIONFIVE2 bool "Support StarFive VisionFive2 Board" select BOARD_LATE_INIT @@ -119,7 +119,7 @@ source "board/sifive/unmatched/Kconfig" source "board/sipeed/maix/Kconfig" source "board/sophgo/milkv_duo/Kconfig" source "board/sophgo/licheerv_nano/Kconfig" -source "board/spacemit/bananapi-f3/Kconfig" +source "board/spacemit/k1/Kconfig" source "board/starfive/visionfive2/Kconfig" source "board/thead/th1520_lpi4a/Kconfig" source "board/xilinx/mbv/Kconfig" diff --git a/arch/riscv/cpu/k1/Kconfig b/arch/riscv/cpu/k1/Kconfig index 14201df80f2..b155535658d 100644 --- a/arch/riscv/cpu/k1/Kconfig +++ b/arch/riscv/cpu/k1/Kconfig @@ -1,12 +1,16 @@ # SPDX-License-Identifier: GPL-2.0-or-later # # Copyright (C) 2024, Kongyang Liu <[email protected]> +# Copyright (C) 2025-2026, RISCstar Ltd. + +if TARGET_SPACEMIT_K1 config SPACEMIT_K1 bool select BINMAN select ARCH_EARLY_INIT_R select SYS_CACHE_SHIFT_6 + select SUPPORT_SPL imply CPU imply CPU_RISCV imply RISCV_TIMER if (RISCV_SMODE || SPL_RISCV_SMODE) @@ -17,3 +21,5 @@ config SPACEMIT_K1 imply SPL_CPU imply SPL_OPENSBI imply SPL_LOAD_FIT + +endif diff --git a/arch/riscv/dts/Makefile b/arch/riscv/dts/Makefile index 8e591cb7aa9..71c5c13d221 100644 --- a/arch/riscv/dts/Makefile +++ b/arch/riscv/dts/Makefile @@ -2,7 +2,6 @@ dtb-$(CONFIG_TARGET_ANDES_AE350) += ae350_32.dtb ae350_64.dtb dtb-$(CONFIG_TARGET_ANDES_VOYAGER) += qilai-voyager.dtb -dtb-$(CONFIG_TARGET_BANANAPI_F3) += k1-bananapi-f3.dtb dtb-$(CONFIG_TARGET_K230_CANMV) += k230-canmv.dtb dtb-$(CONFIG_TARGET_MICROCHIP_ICICLE) += mpfs-icicle-kit.dtb dtb-$(CONFIG_TARGET_MILKV_DUO) += cv1800b-milkv-duo.dtb diff --git a/arch/riscv/dts/binman.dtsi b/arch/riscv/dts/binman.dtsi index b518560bb94..84c261c6849 100644 --- a/arch/riscv/dts/binman.dtsi +++ b/arch/riscv/dts/binman.dtsi @@ -93,9 +93,7 @@ configurations { -#ifndef CONFIG_MULTI_DTB_FIT default = "conf-1"; -#endif #if !defined(CONFIG_OF_BOARD) || defined(CONFIG_MULTI_DTB_FIT) @conf-SEQ { diff --git a/arch/riscv/dts/k1-bananapi-f3-u-boot.dtsi b/arch/riscv/dts/k1-bananapi-f3-u-boot.dtsi new file mode 100644 index 00000000000..7f9443d6951 --- /dev/null +++ b/arch/riscv/dts/k1-bananapi-f3-u-boot.dtsi @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: GPL-2.0+ OR MIT +/* + * Copyright (C) 2026 RISCstar Ltd. + */ + +#include "binman.dtsi" + +/ { + memory@0 { + device_type = "memory"; + reg = <0x00000000 0x00000000 0x00000000 0x80000000>; + }; +}; + +&uart0 { + bootph-pre-ram; +}; + +&osc_32k { + bootph-pre-ram; +}; + +&vctcxo_1m { + bootph-pre-ram; +}; + +&vctcxo_3m { + bootph-pre-ram; +}; + +&vctcxo_24m { + bootph-pre-ram; +}; + +&syscon_mpmu { + bootph-pre-ram; +}; + +&pll { + bootph-pre-ram; +}; + +&syscon_apmu { + bootph-pre-ram; +}; + +&syscon_apbc { + bootph-pre-ram; +}; + +&i2c2 { + bootph-pre-ram; + resets = <&syscon_apbc RESET_TWSI2>; + + eeprom@50 { + bootph-pre-ram; + }; +}; + +/* + * The kernel pmic@41 nodes use the standard regulator-* properties only; + * U-Boot's regulator framework looks up suppliers by `regulator-name`. + * Carry the U-Boot-specific names (vdd_core / vdd_1v8 / vdd_1v8_mmc) here + * so SPL can program the bucks that DDR training depends on. + */ +&i2c8 { + bootph-pre-ram; + resets = <&syscon_apbc RESET_TWSI8>; + + pmic@41 { + bootph-pre-ram; + + regulators { + buck1 { + regulator-name = "vdd_core"; + bootph-pre-ram; + }; + + buck3 { + regulator-name = "vdd_1v8"; + bootph-pre-ram; + }; + + aldo1 { + regulator-name = "vdd_1v8_mmc"; + bootph-pre-ram; + }; + }; + }; +}; + +&binman { + u-boot-spl-ddr { + type = "section"; + filename = "u-boot-spl-ddr.bin"; + pad-byte = <0xff>; + + u-boot-spl { + }; + + ddr-fw { + type = "blob"; + filename = "ddr_fw.bin"; + align = <64>; + }; + + u-boot-any { + type = "section"; + size = <0>; + offset = <0>; + }; + }; +}; diff --git a/arch/riscv/dts/k1-bananapi-f3.dts b/arch/riscv/dts/k1-bananapi-f3.dts deleted file mode 100644 index 6b5b83bcdb9..00000000000 --- a/arch/riscv/dts/k1-bananapi-f3.dts +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -/* - * Copyright (C) 2024 Yangyu Chen <[email protected]> - */ - -#include "k1.dtsi" -#include "binman.dtsi" -#include "k1-pinctrl.dtsi" - -/ { - model = "Banana Pi BPI-F3"; - compatible = "bananapi,bpi-f3", "spacemit,k1"; - - chosen { - stdout-path = "serial0"; - }; - - memory@0 { - device_type = "memory"; - reg = <0x00000000 0x00000000 0x00000000 0x80000000>; - }; -}; - -&uart0 { - pinctrl-names = "default"; - pinctrl-0 = <&uart0_2_cfg>; - status = "okay"; -}; diff --git a/arch/riscv/dts/k1-musepi-pro-u-boot.dtsi b/arch/riscv/dts/k1-musepi-pro-u-boot.dtsi new file mode 100644 index 00000000000..8a9a2a09de9 --- /dev/null +++ b/arch/riscv/dts/k1-musepi-pro-u-boot.dtsi @@ -0,0 +1,273 @@ +// SPDX-License-Identifier: GPL-2.0+ OR MIT +/* + * Copyright (C) 2026 RISCstar Ltd. + */ + +#include <dt-bindings/clock/spacemit,k1-syscon.h> +#include "binman.dtsi" + +/ { + aliases { + console = &uart0; + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@0 { + device_type = "memory"; + reg = <0x00000000 0x00000000 0x00000000 0x80000000>; + }; +}; + +&syscon_mpmu { + clocks = <&osc_32k>, <&vctcxo_1m>, <&vctcxo_3m>, <&vctcxo_24m>, + <&pll CLK_PLL1_D4>; + clock-names = "osc", "vctcxo_1m", "vctcxo_3m", "vctcxo_24m", + "pll1_d4"; +}; + +&syscon_apbc { + clocks = <&osc_32k>, <&vctcxo_1m>, <&vctcxo_3m>, <&vctcxo_24m>, + <&pll CLK_PLL1_D4>, + <&syscon_mpmu CLK_PLL1_31P5>, + <&syscon_apmu CLK_PMUA_ACLK>; + clock-names = "osc", "vctcxo_1m", "vctcxo_3m", "vctcxo_24m", + "pll1_d4", "pll1_d78_31p5", "pmua_aclk"; +}; + +&uart0 { + bootph-pre-ram; +}; + +&osc_32k { + bootph-pre-ram; +}; + +&vctcxo_1m { + bootph-pre-ram; +}; + +&vctcxo_3m { + bootph-pre-ram; +}; + +&vctcxo_24m { + bootph-pre-ram; +}; + +&syscon_mpmu { + bootph-pre-ram; +}; + +&pll { + bootph-pre-ram; +}; + +&syscon_apmu { + bootph-pre-ram; +}; + +&syscon_apbc { + bootph-pre-ram; +}; + +&i2c2 { + bootph-pre-ram; + status = "okay"; + pinctrl-0 = <&i2c2_0_cfg>; + pinctrl-names = "default"; + resets = <&syscon_apbc RESET_TWSI2>; + + eeprom@50 { + bootph-pre-ram; + status = "okay"; + compatible = "atmel,24c02"; + reg = <0x50>; + vcc-supply = <&buck3_1v8>; /* EEPROM_VCC1V8 */ + pagesize = <16>; + read-only; + size = <256>; + + nvmem-layout { + compatible = "onie,tlv-layout"; + + mac-address { + #nvmem-cell-cells = <1>; + }; + + num-macs { + }; + + serial-number { + }; + }; + }; +}; + +&i2c8 { + bootph-pre-ram; + pinctrl-0 = <&i2c8_cfg>; + pinctrl-names = "default"; + resets = <&syscon_apbc RESET_TWSI8>; + status = "okay"; + + pmic@41 { + bootph-pre-ram; + compatible = "spacemit,p1"; + reg = <0x41>; + interrupts = <64>; + status = "okay"; + + regulators { + buck1 { + bootph-pre-ram; + regulator-name = "vdd_core"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <3450000>; + regulator-ramp-delay = <5000>; + regulator-always-on; + }; + + buck2 { + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <3450000>; + regulator-ramp-delay = <5000>; + regulator-always-on; + }; + + buck3_1v8: buck3 { + bootph-pre-ram; + regulator-name = "vdd_1v8"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1800000>; + regulator-ramp-delay = <5000>; + regulator-always-on; + }; + + buck4 { + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <3300000>; + regulator-ramp-delay = <5000>; + regulator-always-on; + }; + + buck5 { + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <3450000>; + regulator-ramp-delay = <5000>; + regulator-always-on; + }; + + buck6 { + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <3450000>; + regulator-ramp-delay = <5000>; + regulator-always-on; + }; + + aldo1 { + bootph-pre-ram; + regulator-name = "vdd_1v8_mmc"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <3400000>; + regulator-boot-on; + }; + + aldo2 { + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <3400000>; + }; + + aldo3 { + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <3400000>; + }; + + aldo4 { + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <3400000>; + }; + + dldo1 { + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <3400000>; + regulator-boot-on; + }; + + dldo2 { + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <3400000>; + }; + + dldo3 { + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <3400000>; + }; + + dldo4 { + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <3400000>; + regulator-always-on; + }; + + dldo5 { + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <3400000>; + }; + + dldo6 { + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <3400000>; + regulator-always-on; + }; + + dldo7 { + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <3400000>; + }; + }; + }; +}; + +&qspi { + bootph-pre-ram; + pinctrl-names = "default"; + pinctrl-0 = <&qspi_cfg>; + status = "okay"; + + flash@0 { + bootph-pre-ram; + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <26500000>; + m25p,fast-read; + broken-flash-reset; + status = "okay"; + }; +}; + +&binman { + u-boot-spl-ddr { + type = "section"; + filename = "u-boot-spl-ddr.bin"; + pad-byte = <0xff>; + + u-boot-spl { + }; + + ddr-fw { + type = "blob"; + filename = "ddr_fw.bin"; + align = <64>; + }; + + u-boot-any { + type = "section"; + size = <0>; + offset = <0>; + }; + }; +}; diff --git a/arch/riscv/dts/k1-pinctrl.dtsi b/arch/riscv/dts/k1-pinctrl.dtsi deleted file mode 100644 index 14e7096fbcf..00000000000 --- a/arch/riscv/dts/k1-pinctrl.dtsi +++ /dev/null @@ -1,19 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0 OR MIT) -/* - * Copyright (C) 2022 Spacemit Inc. - * Copyright (C) 2025 Yixun Lan <[email protected]> - */ - -#define K1_PADCONF(pin, func) (((pin) << 16) | (func)) - -&pinctrl { - uart0_2_cfg: uart0-2-cfg { - uart0-2-pins { - pinmux = <K1_PADCONF(68, 2)>, - <K1_PADCONF(69, 2)>; - - bias-pull-up = <0>; - drive-strength = <32>; - }; - }; -}; diff --git a/arch/riscv/dts/k1.dtsi b/arch/riscv/dts/k1.dtsi deleted file mode 100644 index a633e43da32..00000000000 --- a/arch/riscv/dts/k1.dtsi +++ /dev/null @@ -1,480 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -/* - * Copyright (C) 2024 Yangyu Chen <[email protected]> - */ - -/dts-v1/; -/ { - #address-cells = <2>; - #size-cells = <2>; - model = "SpacemiT K1"; - compatible = "spacemit,k1"; - - aliases { - serial0 = &uart0; - serial1 = &uart2; - serial2 = &uart3; - serial3 = &uart4; - serial4 = &uart5; - serial5 = &uart6; - serial6 = &uart7; - serial7 = &uart8; - serial8 = &uart9; - }; - - cpus { - #address-cells = <1>; - #size-cells = <0>; - timebase-frequency = <24000000>; - - cpu-map { - cluster0 { - core0 { - cpu = <&cpu_0>; - }; - core1 { - cpu = <&cpu_1>; - }; - core2 { - cpu = <&cpu_2>; - }; - core3 { - cpu = <&cpu_3>; - }; - }; - - cluster1 { - core0 { - cpu = <&cpu_4>; - }; - core1 { - cpu = <&cpu_5>; - }; - core2 { - cpu = <&cpu_6>; - }; - core3 { - cpu = <&cpu_7>; - }; - }; - }; - - cpu_0: cpu@0 { - compatible = "spacemit,x60", "riscv"; - device_type = "cpu"; - reg = <0>; - riscv,isa = "rv64imafdcv_zicbom_zicbop_zicboz_zicntr_zicond_zicsr_zifencei_zihintpause_zihpm_zfh_zba_zbb_zbc_zbs_zkt_zvfh_zvkt_sscofpmf_sstc_svinval_svnapot_svpbmt"; - riscv,isa-base = "rv64i"; - riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "zicbom", - "zicbop", "zicboz", "zicntr", "zicond", "zicsr", - "zifencei", "zihintpause", "zihpm", "zfh", "zba", - "zbb", "zbc", "zbs", "zkt", "zvfh", "zvkt", - "sscofpmf", "sstc", "svinval", "svnapot", "svpbmt"; - riscv,cbom-block-size = <64>; - riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - i-cache-block-size = <64>; - i-cache-size = <32768>; - i-cache-sets = <128>; - d-cache-block-size = <64>; - d-cache-size = <32768>; - d-cache-sets = <128>; - next-level-cache = <&cluster0_l2_cache>; - mmu-type = "riscv,sv39"; - - cpu0_intc: interrupt-controller { - compatible = "riscv,cpu-intc"; - interrupt-controller; - #interrupt-cells = <1>; - }; - }; - - cpu_1: cpu@1 { - compatible = "spacemit,x60", "riscv"; - device_type = "cpu"; - reg = <1>; - riscv,isa = "rv64imafdcv_zicbom_zicbop_zicboz_zicntr_zicond_zicsr_zifencei_zihintpause_zihpm_zfh_zba_zbb_zbc_zbs_zkt_zvfh_zvkt_sscofpmf_sstc_svinval_svnapot_svpbmt"; - riscv,isa-base = "rv64i"; - riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "zicbom", - "zicbop", "zicboz", "zicntr", "zicond", "zicsr", - "zifencei", "zihintpause", "zihpm", "zfh", "zba", - "zbb", "zbc", "zbs", "zkt", "zvfh", "zvkt", - "sscofpmf", "sstc", "svinval", "svnapot", "svpbmt"; - riscv,cbom-block-size = <64>; - riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - i-cache-block-size = <64>; - i-cache-size = <32768>; - i-cache-sets = <128>; - d-cache-block-size = <64>; - d-cache-size = <32768>; - d-cache-sets = <128>; - next-level-cache = <&cluster0_l2_cache>; - mmu-type = "riscv,sv39"; - - cpu1_intc: interrupt-controller { - compatible = "riscv,cpu-intc"; - interrupt-controller; - #interrupt-cells = <1>; - }; - }; - - cpu_2: cpu@2 { - compatible = "spacemit,x60", "riscv"; - device_type = "cpu"; - reg = <2>; - riscv,isa = "rv64imafdcv_zicbom_zicbop_zicboz_zicntr_zicond_zicsr_zifencei_zihintpause_zihpm_zfh_zba_zbb_zbc_zbs_zkt_zvfh_zvkt_sscofpmf_sstc_svinval_svnapot_svpbmt"; - riscv,isa-base = "rv64i"; - riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "zicbom", - "zicbop", "zicboz", "zicntr", "zicond", "zicsr", - "zifencei", "zihintpause", "zihpm", "zfh", "zba", - "zbb", "zbc", "zbs", "zkt", "zvfh", "zvkt", - "sscofpmf", "sstc", "svinval", "svnapot", "svpbmt"; - riscv,cbom-block-size = <64>; - riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - i-cache-block-size = <64>; - i-cache-size = <32768>; - i-cache-sets = <128>; - d-cache-block-size = <64>; - d-cache-size = <32768>; - d-cache-sets = <128>; - next-level-cache = <&cluster0_l2_cache>; - mmu-type = "riscv,sv39"; - - cpu2_intc: interrupt-controller { - compatible = "riscv,cpu-intc"; - interrupt-controller; - #interrupt-cells = <1>; - }; - }; - - cpu_3: cpu@3 { - compatible = "spacemit,x60", "riscv"; - device_type = "cpu"; - reg = <3>; - riscv,isa = "rv64imafdcv_zicbom_zicbop_zicboz_zicntr_zicond_zicsr_zifencei_zihintpause_zihpm_zfh_zba_zbb_zbc_zbs_zkt_zvfh_zvkt_sscofpmf_sstc_svinval_svnapot_svpbmt"; - riscv,isa-base = "rv64i"; - riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "zicbom", - "zicbop", "zicboz", "zicntr", "zicond", "zicsr", - "zifencei", "zihintpause", "zihpm", "zfh", "zba", - "zbb", "zbc", "zbs", "zkt", "zvfh", "zvkt", - "sscofpmf", "sstc", "svinval", "svnapot", "svpbmt"; - riscv,cbom-block-size = <64>; - riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - i-cache-block-size = <64>; - i-cache-size = <32768>; - i-cache-sets = <128>; - d-cache-block-size = <64>; - d-cache-size = <32768>; - d-cache-sets = <128>; - next-level-cache = <&cluster0_l2_cache>; - mmu-type = "riscv,sv39"; - - cpu3_intc: interrupt-controller { - compatible = "riscv,cpu-intc"; - interrupt-controller; - #interrupt-cells = <1>; - }; - }; - - cpu_4: cpu@4 { - compatible = "spacemit,x60", "riscv"; - device_type = "cpu"; - reg = <4>; - riscv,isa = "rv64imafdcv_zicbom_zicbop_zicboz_zicntr_zicond_zicsr_zifencei_zihintpause_zihpm_zfh_zba_zbb_zbc_zbs_zkt_zvfh_zvkt_sscofpmf_sstc_svinval_svnapot_svpbmt"; - riscv,isa-base = "rv64i"; - riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "zicbom", - "zicbop", "zicboz", "zicntr", "zicond", "zicsr", - "zifencei", "zihintpause", "zihpm", "zfh", "zba", - "zbb", "zbc", "zbs", "zkt", "zvfh", "zvkt", - "sscofpmf", "sstc", "svinval", "svnapot", "svpbmt"; - riscv,cbom-block-size = <64>; - riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - i-cache-block-size = <64>; - i-cache-size = <32768>; - i-cache-sets = <128>; - d-cache-block-size = <64>; - d-cache-size = <32768>; - d-cache-sets = <128>; - next-level-cache = <&cluster1_l2_cache>; - mmu-type = "riscv,sv39"; - - cpu4_intc: interrupt-controller { - compatible = "riscv,cpu-intc"; - interrupt-controller; - #interrupt-cells = <1>; - }; - }; - - cpu_5: cpu@5 { - compatible = "spacemit,x60", "riscv"; - device_type = "cpu"; - reg = <5>; - riscv,isa = "rv64imafdcv_zicbom_zicbop_zicboz_zicntr_zicond_zicsr_zifencei_zihintpause_zihpm_zfh_zba_zbb_zbc_zbs_zkt_zvfh_zvkt_sscofpmf_sstc_svinval_svnapot_svpbmt"; - riscv,isa-base = "rv64i"; - riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "zicbom", - "zicbop", "zicboz", "zicntr", "zicond", "zicsr", - "zifencei", "zihintpause", "zihpm", "zfh", "zba", - "zbb", "zbc", "zbs", "zkt", "zvfh", "zvkt", - "sscofpmf", "sstc", "svinval", "svnapot", "svpbmt"; - riscv,cbom-block-size = <64>; - riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - i-cache-block-size = <64>; - i-cache-size = <32768>; - i-cache-sets = <128>; - d-cache-block-size = <64>; - d-cache-size = <32768>; - d-cache-sets = <128>; - next-level-cache = <&cluster1_l2_cache>; - mmu-type = "riscv,sv39"; - - cpu5_intc: interrupt-controller { - compatible = "riscv,cpu-intc"; - interrupt-controller; - #interrupt-cells = <1>; - }; - }; - - cpu_6: cpu@6 { - compatible = "spacemit,x60", "riscv"; - device_type = "cpu"; - reg = <6>; - riscv,isa = "rv64imafdcv_zicbom_zicbop_zicboz_zicntr_zicond_zicsr_zifencei_zihintpause_zihpm_zfh_zba_zbb_zbc_zbs_zkt_zvfh_zvkt_sscofpmf_sstc_svinval_svnapot_svpbmt"; - riscv,isa-base = "rv64i"; - riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "zicbom", - "zicbop", "zicboz", "zicntr", "zicond", "zicsr", - "zifencei", "zihintpause", "zihpm", "zfh", "zba", - "zbb", "zbc", "zbs", "zkt", "zvfh", "zvkt", - "sscofpmf", "sstc", "svinval", "svnapot", "svpbmt"; - riscv,cbom-block-size = <64>; - riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - i-cache-block-size = <64>; - i-cache-size = <32768>; - i-cache-sets = <128>; - d-cache-block-size = <64>; - d-cache-size = <32768>; - d-cache-sets = <128>; - next-level-cache = <&cluster1_l2_cache>; - mmu-type = "riscv,sv39"; - - cpu6_intc: interrupt-controller { - compatible = "riscv,cpu-intc"; - interrupt-controller; - #interrupt-cells = <1>; - }; - }; - - cpu_7: cpu@7 { - compatible = "spacemit,x60", "riscv"; - device_type = "cpu"; - reg = <7>; - riscv,isa = "rv64imafdcv_zicbom_zicbop_zicboz_zicntr_zicond_zicsr_zifencei_zihintpause_zihpm_zfh_zba_zbb_zbc_zbs_zkt_zvfh_zvkt_sscofpmf_sstc_svinval_svnapot_svpbmt"; - riscv,isa-base = "rv64i"; - riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "zicbom", - "zicbop", "zicboz", "zicntr", "zicond", "zicsr", - "zifencei", "zihintpause", "zihpm", "zfh", "zba", - "zbb", "zbc", "zbs", "zkt", "zvfh", "zvkt", - "sscofpmf", "sstc", "svinval", "svnapot", "svpbmt"; - riscv,cbom-block-size = <64>; - riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - i-cache-block-size = <64>; - i-cache-size = <32768>; - i-cache-sets = <128>; - d-cache-block-size = <64>; - d-cache-size = <32768>; - d-cache-sets = <128>; - next-level-cache = <&cluster1_l2_cache>; - mmu-type = "riscv,sv39"; - - cpu7_intc: interrupt-controller { - compatible = "riscv,cpu-intc"; - interrupt-controller; - #interrupt-cells = <1>; - }; - }; - - cluster0_l2_cache: l2-cache0 { - compatible = "cache"; - cache-block-size = <64>; - cache-level = <2>; - cache-size = <524288>; - cache-sets = <512>; - cache-unified; - }; - - cluster1_l2_cache: l2-cache1 { - compatible = "cache"; - cache-block-size = <64>; - cache-level = <2>; - cache-size = <524288>; - cache-sets = <512>; - cache-unified; - }; - }; - - soc { - compatible = "simple-bus"; - interrupt-parent = <&plic>; - #address-cells = <2>; - #size-cells = <2>; - dma-noncoherent; - ranges; - - uart0: serial@d4017000 { - compatible = "spacemit,k1-uart", "intel,xscale-uart"; - reg = <0x0 0xd4017000 0x0 0x100>; - interrupts = <42>; - clock-frequency = <14857000>; - reg-shift = <2>; - reg-io-width = <4>; - status = "disabled"; - }; - - uart2: serial@d4017100 { - compatible = "spacemit,k1-uart", "intel,xscale-uart"; - reg = <0x0 0xd4017100 0x0 0x100>; - interrupts = <44>; - clock-frequency = <14857000>; - reg-shift = <2>; - reg-io-width = <4>; - status = "disabled"; - }; - - uart3: serial@d4017200 { - compatible = "spacemit,k1-uart", "intel,xscale-uart"; - reg = <0x0 0xd4017200 0x0 0x100>; - interrupts = <45>; - clock-frequency = <14857000>; - reg-shift = <2>; - reg-io-width = <4>; - status = "disabled"; - }; - - uart4: serial@d4017300 { - compatible = "spacemit,k1-uart", "intel,xscale-uart"; - reg = <0x0 0xd4017300 0x0 0x100>; - interrupts = <46>; - clock-frequency = <14857000>; - reg-shift = <2>; - reg-io-width = <4>; - status = "disabled"; - }; - - uart5: serial@d4017400 { - compatible = "spacemit,k1-uart", "intel,xscale-uart"; - reg = <0x0 0xd4017400 0x0 0x100>; - interrupts = <47>; - clock-frequency = <14857000>; - reg-shift = <2>; - reg-io-width = <4>; - status = "disabled"; - }; - - uart6: serial@d4017500 { - compatible = "spacemit,k1-uart", "intel,xscale-uart"; - reg = <0x0 0xd4017500 0x0 0x100>; - interrupts = <48>; - clock-frequency = <14857000>; - reg-shift = <2>; - reg-io-width = <4>; - status = "disabled"; - }; - - uart7: serial@d4017600 { - compatible = "spacemit,k1-uart", "intel,xscale-uart"; - reg = <0x0 0xd4017600 0x0 0x100>; - interrupts = <49>; - clock-frequency = <14857000>; - reg-shift = <2>; - reg-io-width = <4>; - status = "disabled"; - }; - - uart8: serial@d4017700 { - compatible = "spacemit,k1-uart", "intel,xscale-uart"; - reg = <0x0 0xd4017700 0x0 0x100>; - interrupts = <50>; - clock-frequency = <14857000>; - reg-shift = <2>; - reg-io-width = <4>; - status = "disabled"; - }; - - uart9: serial@d4017800 { - compatible = "spacemit,k1-uart", "intel,xscale-uart"; - reg = <0x0 0xd4017800 0x0 0x100>; - interrupts = <51>; - clock-frequency = <14857000>; - reg-shift = <2>; - reg-io-width = <4>; - status = "disabled"; - }; - - plic: interrupt-controller@e0000000 { - compatible = "spacemit,k1-plic", "sifive,plic-1.0.0"; - reg = <0x0 0xe0000000 0x0 0x4000000>; - interrupts-extended = <&cpu0_intc 11>, <&cpu0_intc 9>, - <&cpu1_intc 11>, <&cpu1_intc 9>, - <&cpu2_intc 11>, <&cpu2_intc 9>, - <&cpu3_intc 11>, <&cpu3_intc 9>, - <&cpu4_intc 11>, <&cpu4_intc 9>, - <&cpu5_intc 11>, <&cpu5_intc 9>, - <&cpu6_intc 11>, <&cpu6_intc 9>, - <&cpu7_intc 11>, <&cpu7_intc 9>; - interrupt-controller; - #address-cells = <0>; - #interrupt-cells = <1>; - riscv,ndev = <159>; - }; - - clint: timer@e4000000 { - compatible = "spacemit,k1-clint", "sifive,clint0"; - reg = <0x0 0xe4000000 0x0 0x10000>; - interrupts-extended = <&cpu0_intc 3>, <&cpu0_intc 7>, - <&cpu1_intc 3>, <&cpu1_intc 7>, - <&cpu2_intc 3>, <&cpu2_intc 7>, - <&cpu3_intc 3>, <&cpu3_intc 7>, - <&cpu4_intc 3>, <&cpu4_intc 7>, - <&cpu5_intc 3>, <&cpu5_intc 7>, - <&cpu6_intc 3>, <&cpu6_intc 7>, - <&cpu7_intc 3>, <&cpu7_intc 7>; - }; - - sec_uart1: serial@f0612000 { - compatible = "spacemit,k1-uart", "intel,xscale-uart"; - reg = <0x0 0xf0612000 0x0 0x100>; - interrupts = <43>; - clock-frequency = <14857000>; - reg-shift = <2>; - reg-io-width = <4>; - status = "reserved"; /* for TEE usage */ - }; - - reset: reset-controller@d4050000 { - compatible = "spacemit,k1-reset"; - reg = <0x0 0xd4050000 0x0 0x209c>, - <0x0 0xd4282800 0x0 0x400>, - <0x0 0xd4015000 0x0 0x1000>, - <0x0 0xd4090000 0x0 0x1000>, - <0x0 0xd4282c00 0x0 0x400>, - <0x0 0xd8440000 0x0 0x98>, - <0x0 0xc0000000 0x0 0x4280>, - <0x0 0xf0610000 0x0 0x20>; - reg-names = "mpmu", "apmu", "apbc", "apbs", "ciu", "dciu", "ddrc", "apbc2"; - #reset-cells = <1>; - status = "disabled"; - }; - - pinctrl: pinctrl@d401e000 { - compatible = "spacemit,k1-pinctrl", "pinctrl-single"; - reg = <0x0 0xd401e000 0x0 0x400>; - pinctrl-single,register-width = <32>; - }; - }; -}; diff --git a/arch/sh/include/asm/string.h b/arch/sh/include/asm/string.h index 999febcb6b7..12a9a8f796c 100644 --- a/arch/sh/include/asm/string.h +++ b/arch/sh/include/asm/string.h @@ -8,8 +8,6 @@ * from linux kernel code. */ -#ifdef __KERNEL__ /* only set these up for kernel code */ - #define __HAVE_ARCH_STRCPY static inline char *strcpy(char *__dest, const char *__src) { @@ -81,53 +79,4 @@ static inline int strcmp(const char *__cs, const char *__ct) return __res; } -#undef __HAVE_ARCH_STRNCMP -extern int strncmp(const char *__cs, const char *__ct, size_t __n); - -#undef __HAVE_ARCH_MEMSET -extern void *memset(void *__s, int __c, size_t __count); - -#undef __HAVE_ARCH_MEMCPY -extern void *memcpy(void *__to, __const__ void *__from, size_t __n); - -#undef __HAVE_ARCH_MEMMOVE -extern void *memmove(void *__dest, __const__ void *__src, size_t __n); - -#undef __HAVE_ARCH_MEMCHR -extern void *memchr(const void *__s, int __c, size_t __n); - -#undef __HAVE_ARCH_STRLEN -extern size_t strlen(const char *); - -/* arch/sh/lib/strcasecmp.c */ -extern int strcasecmp(const char *, const char *); - -#else /* KERNEL */ - -/* - * let user libraries deal with these, - * IMHO the kernel has no place defining these functions for user apps - */ - -#define __HAVE_ARCH_STRCPY 1 -#define __HAVE_ARCH_STRNCPY 1 -#define __HAVE_ARCH_STRCAT 1 -#define __HAVE_ARCH_STRNCAT 1 -#define __HAVE_ARCH_STRCMP 1 -#define __HAVE_ARCH_STRNCMP 1 -#define __HAVE_ARCH_STRNICMP 1 -#define __HAVE_ARCH_STRCHR 1 -#define __HAVE_ARCH_STRRCHR 1 -#define __HAVE_ARCH_STRSTR 1 -#define __HAVE_ARCH_STRLEN 1 -#define __HAVE_ARCH_STRNLEN 1 -#define __HAVE_ARCH_MEMSET 1 -#define __HAVE_ARCH_MEMCPY 1 -#define __HAVE_ARCH_MEMMOVE 1 -#define __HAVE_ARCH_MEMSCAN 1 -#define __HAVE_ARCH_MEMCMP 1 -#define __HAVE_ARCH_MEMCHR 1 -#define __HAVE_ARCH_STRTOK 1 - -#endif /* KERNEL */ #endif /* __ASM_SH_STRING_H */ diff --git a/board/spacemit/bananapi-f3/MAINTAINERS b/board/spacemit/bananapi-f3/MAINTAINERS deleted file mode 100644 index 131bad03181..00000000000 --- a/board/spacemit/bananapi-f3/MAINTAINERS +++ /dev/null @@ -1,6 +0,0 @@ -BananaPi F3 -M: Huan Zhou <pericycle.cc@@gmail.com> -S: Maintained -F: board/spacemit/bananapi-f3/ -F: configs/bananapi-f3_defconfig -F: doc/board/spacemit/bananapi-f3.rst diff --git a/board/spacemit/bananapi-f3/Makefile b/board/spacemit/bananapi-f3/Makefile deleted file mode 100644 index 2168698402b..00000000000 --- a/board/spacemit/bananapi-f3/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-or-later -# -# Copyright (c) 2024, Kongyang Liu <[email protected]> - -obj-y := board.o diff --git a/board/spacemit/bananapi-f3/Kconfig b/board/spacemit/k1/Kconfig index f89fa9af2c7..1c615f89b64 100644 --- a/board/spacemit/bananapi-f3/Kconfig +++ b/board/spacemit/k1/Kconfig @@ -1,7 +1,7 @@ -if TARGET_BANANAPI_F3 +if TARGET_SPACEMIT_K1 config SYS_BOARD - default "bananapi-f3" + default "k1" config SYS_VENDOR default "spacemit" @@ -10,7 +10,7 @@ config SYS_CPU default "k1" config SYS_CONFIG_NAME - default "bananapi-f3" + default "k1" config TEXT_BASE default 0x00200000 diff --git a/board/spacemit/k1/MAINTAINERS b/board/spacemit/k1/MAINTAINERS new file mode 100644 index 00000000000..32d47ecc8f1 --- /dev/null +++ b/board/spacemit/k1/MAINTAINERS @@ -0,0 +1,14 @@ +BananaPi F3 +M: Huan Zhou <[email protected]> +M: Guodong Xu <[email protected]> +S: Maintained +F: arch/riscv/dts/k1-*-u-boot.dtsi +F: board/spacemit/k1/ +F: configs/spacemit_k1_defconfig +F: doc/board/spacemit/bananapi-f3.rst +F: drivers/gpio/spacemit_gpio.c +F: drivers/i2c/k1_i2c.c +F: drivers/pinctrl/spacemit/ +F: drivers/power/pmic/pmic_spacemit_p1.c +F: drivers/power/regulator/spacemit_p1_regulator.c diff --git a/board/spacemit/k1/Makefile b/board/spacemit/k1/Makefile new file mode 100644 index 00000000000..a57af2e1f08 --- /dev/null +++ b/board/spacemit/k1/Makefile @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Copyright (c) 2024, Kongyang Liu <[email protected]> +# Copyright (c) 2025-2026, RISCstar Ltd. + +obj-y := board.o +obj-$(CONFIG_SPL_BUILD) += spl.o + +DDR_FW_SRC ?= $(DDR_FW_FILE) +FW_TARGET = $(objtree)/ddr_fw.bin + +$(obj)/spl.o: $(FW_TARGET) + +$(FW_TARGET): FORCE + @if [ -n "$(DDR_FW_SRC)" ] && [ -f "$(DDR_FW_SRC)" ]; then \ + if ! cmp -s "$(DDR_FW_SRC)" $@ 2>/dev/null; then \ + echo " Copying DDR firmware from: $(DDR_FW_SRC)"; \ + cp "$(DDR_FW_SRC)" $@; \ + fi; \ + elif [ -s $@ ]; then \ + : ; \ + else \ + echo " Note: No DDR firmware found, creating empty placeholder"; \ + echo " (Set DDR_FW_FILE to specify firmware location)"; \ + touch $@; \ + fi + +clean-files += $(FW_TARGET) diff --git a/board/spacemit/bananapi-f3/board.c b/board/spacemit/k1/board.c index ea416621544..ea416621544 100644 --- a/board/spacemit/bananapi-f3/board.c +++ b/board/spacemit/k1/board.c diff --git a/board/spacemit/k1/spl.c b/board/spacemit/k1/spl.c new file mode 100644 index 00000000000..d749e21a2d5 --- /dev/null +++ b/board/spacemit/k1/spl.c @@ -0,0 +1,391 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2025-2026, RISCstar Ltd. + */ + +#include <asm/io.h> +#include <binman.h> +#include <binman_sym.h> +#include <clk.h> +#include <clk-uclass.h> +#include <cpu_func.h> +#include <configs/k1.h> +#include <dm/device.h> +#include <dm/uclass.h> +#include <i2c.h> +#include <linux/ctype.h> +#include <linux/delay.h> +#include <log.h> +#include <power/regulator.h> +#include <spi_flash.h> +#include <spl.h> +#include <tlv_eeprom.h> +#include "tlv_codes.h" + +#define MUX_MODE4 4 +#define EDGE_NONE BIT(6) +#define PULL_UP (6 << 13) /* bit[15:13] 110 */ +#define PAD_DS_MEDIUM BIT(12) +#define PAD_1V8_DS2 PAD_DS_MEDIUM +#define I2C_PIN_CONFIG(x) ((x) | EDGE_NONE | PULL_UP | PAD_1V8_DS2) +#define I2C_BUF_SIZE 64 + +#define MFP_GPIO_84 0xd401e154 +#define MFP_GPIO_85 0xd401e158 + +#define DDR_FIRMWARE_BASE 0xc082d000 + +#define DDR_DEFAULT_CS_NUM 2 +#define DDR_DEFAULT_TYPE "LPDDR4X" +#define DDR_DEFAULT_TX_ODT 80 +#define DDR_DEFAULT_DATA_RATE 2400 + +#define MAGIC_NUM 0xaa55aa55 + +typedef void (*puts_func_t)(const char *s); +typedef int (*ddr_init_func_t)(u64 ddr_base, u32 cs_num, u32 data_rate, + puts_func_t puts); + +struct ddr_cfg { + u32 data_rate; + u32 cs_num; + u32 tx_odt; + u8 type[I2C_BUF_SIZE]; +}; + +binman_sym_declare(ulong, ddr_fw, image_pos); +binman_sym_declare(ulong, ddr_fw, size); + +char product_name[I2C_BUF_SIZE] = "k1"; + +static void i2c_early_init(void) +{ + struct udevice *bus; + + // eeprom: I2C2, pin group(GPIO_84, GPIO_85) + writel(I2C_PIN_CONFIG(MUX_MODE4), (void __iomem *)MFP_GPIO_84); + writel(I2C_PIN_CONFIG(MUX_MODE4), (void __iomem *)MFP_GPIO_85); + udelay(100); + uclass_first_device(UCLASS_I2C, &bus); + while (bus) { + uclass_next_device(&bus); + if (!bus) + break; + } +} + +int read_product_name(char *name, int size) +{ + u8 eeprom_data[TLV_TOTAL_LEN_MAX], *p; + struct tlvinfo_header *tlv_hdr; + struct tlvinfo_tlv *tlv_entry; + int ret, i = 0; + u32 entry_size; + + if (!name || size <= 0) + return -EINVAL; + ret = read_tlvinfo_tlv_eeprom(eeprom_data, &tlv_hdr, + &tlv_entry, i); + if (ret) + return ret; + p = (u8 *)tlv_entry; + for (i = 0; i < tlv_hdr->totallen; ) { + if (tlv_entry->type == TLV_CODE_PRODUCT_NAME) { + if (tlv_entry->length < size) + size = tlv_entry->length; + memset(name, 0, size); + memcpy(name, &tlv_entry->value[0], size); + return 0; + } + if (tlv_entry->type == TLV_CODE_CRC_32) + return -ENOENT; + entry_size = tlv_entry->length + sizeof(struct tlvinfo_tlv); + i += entry_size; + p += entry_size; + tlv_entry = (struct tlvinfo_tlv *)p; + } + return -ENOENT; +} + +static void clk_early_init(void) +{ + struct udevice *dev; + int ret; + + ret = uclass_get_device_by_name(UCLASS_CLK, "clock-controller@d4090000", &dev); + if (ret) + panic("Fail to detect clock-controller@d4090000\n"); + ret = uclass_get_device_by_name(UCLASS_CLK, "system-controller@d4050000", &dev); + if (ret) + panic("Fail to detect system-controller@d4050000\n"); + ret = uclass_get_device_by_name(UCLASS_CLK, "system-controller@d4282800", &dev); + if (ret) + panic("Fail to detect system-controller@d4282800\n"); + ret = uclass_get_device_by_name(UCLASS_CLK, "system-controller@d4015000", &dev); + if (ret) + panic("Fail to detect system-controller@d4015000\n"); + + if (device_active(dev)) + log_debug("clk: device is active\n"); + else + log_debug("clk: device not active, probing...\n"); +} + +void serial_early_init(void) +{ + struct udevice *dev; + int ret; + + ret = uclass_get_device(UCLASS_SERIAL, 0, &dev); + if (ret) + panic("Serial uclass init failed: %d\n", ret); +} + +static void set_vdd_core(void) +{ + struct udevice *dev; + int ret; + + ret = regulator_get_by_platname("vdd_core", &dev); + if (ret) + panic("Fail to detect vdd_core (%d)\n", ret); + ret = regulator_set_enable(dev, true); + if (ret) + log_warning("Fail to enable vdd_core (%d)\n", ret); + ret = regulator_get_value(dev); + if (ret < 0) + log_warning("Fail to read vdd_core (%d)\n", ret); + log_info("vdd_core, value:%d\n", ret); +} + +static void set_vdd_1v8(void) +{ + struct udevice *dev; + int ret; + + ret = regulator_get_by_platname("vdd_1v8", &dev); + if (ret) + panic("Fail to detect vdd_1v8 (%d)\n", ret); + ret = regulator_set_value(dev, 1800000); + if (ret) + log_warning("Fail to set vdd_1v8 as 1800000 (%d)\n", ret); + ret = regulator_set_enable(dev, true); + if (ret) + log_warning("Fail to enable vdd_1v8 (%d)\n", ret); + ret = regulator_get_value(dev); + if (ret < 0) + log_warning("Fail to read vdd_1v8 (%d)\n", ret); + log_info("vdd_1v8, value:%d\n", ret); +} + +static void set_vdd_mmc(void) +{ + struct udevice *dev; + int ret; + + ret = regulator_get_by_platname("vdd_1v8_mmc", &dev); + if (ret) + panic("Fail to detect vdd_1v8_mmc (%d)\n", ret); + ret = regulator_set_value(dev, 1800000); + if (ret) + log_warning("Fail to set vdd_1v8_mmc as 1800000 (%d)\n", ret); + ret = regulator_set_enable(dev, true); + if (ret) + log_warning("Fail to enable vdd_1v8_mmc (%d)\n", ret); + ret = regulator_get_value(dev); + if (ret < 0) + log_warning("Fail to read vdd_1v8_mmc (%d)\n", ret); + log_info("vdd_1v8_mmc, value:%d\n", ret); +} + +void pmic_init(void) +{ + struct udevice *pmic_dev; + int ret; + + ret = uclass_get_device(UCLASS_PMIC, 0, &pmic_dev); + if (ret) + panic("Fail to detect PMIC (%d)\n", ret); + set_vdd_core(); + set_vdd_1v8(); + set_vdd_mmc(); +} + +/* Set default value for DDR chips */ +static void ddr_cfg_init(struct ddr_cfg *cfg) +{ + memset(cfg, 0, sizeof(struct ddr_cfg)); + cfg->data_rate = DDR_DEFAULT_DATA_RATE; + cfg->cs_num = DDR_DEFAULT_CS_NUM; + cfg->tx_odt = DDR_DEFAULT_TX_ODT; + strcpy(cfg->type, DDR_DEFAULT_TYPE); +} + +int read_ddr_info(struct ddr_cfg *cfg) +{ + u8 eeprom_data[TLV_TOTAL_LEN_MAX], *p; + struct tlvinfo_header *tlv_hdr; + struct tlvinfo_tlv *tlv_entry; + u32 size, entry_size; + int ret, i; + bool found = false; + + if (!cfg) + return -EINVAL; + ddr_cfg_init(cfg); + ret = read_tlvinfo_tlv_eeprom(eeprom_data, &tlv_hdr, + &tlv_entry, i); + if (ret) + return ret; + p = (u8 *)tlv_entry; + for (i = 0; i < tlv_hdr->totallen; ) { + switch (tlv_entry->type) { + case TLV_CODE_DDR_CSNUM: + memcpy(&cfg->cs_num, &tlv_entry->value[0], 1); + found = true; + break; + case TLV_CODE_DDR_TYPE: + size = min((u32)tlv_entry->length, (u32)I2C_BUF_SIZE); + memcpy(&cfg->type[0], &tlv_entry->value[0], size); + found = true; + break; + case TLV_CODE_DDR_DATARATE: + memcpy(&cfg->data_rate, &tlv_entry->value[0], 2); + found = true; + break; + case TLV_CODE_DDR_TX_ODT: + memcpy(&cfg->tx_odt, &tlv_entry->value[0], 1); + found = true; + break; + case TLV_CODE_CRC_32: + if (!found) + return -ENOENT; + return 0; + } + entry_size = tlv_entry->length + sizeof(struct tlvinfo_tlv); + i += entry_size; + p += entry_size; + tlv_entry = (struct tlvinfo_tlv *)p; + } + if (!found) + return -ENOENT; + return 0; +} + +void ddr_early_init(void) +{ + void __iomem *src, *dst; + ulong pos, size; + struct ddr_cfg cfg; + ddr_init_func_t ddr_init; + + pos = binman_sym(ulong, ddr_fw, image_pos); + size = binman_sym(ulong, ddr_fw, size); + src = (void __iomem *)pos; + dst = (void __iomem *)(DDR_FIRMWARE_BASE); + log_info("DDR firmware: [0x%lx]:0x%x, size:0x%lx\n", pos, readl(src), size); + memcpy((u8 *)dst, (u8 *)src, size); + size = round_up(size, 64); + /* + * Ensure the just-written DDR firmware bytes are observable in the + * instruction stream. RISC-V's fence.i alone is sufficient for the + * single-hart SPL case; skip flush_dcache_range as cbo.flush may + * trap on our current privilege state. + */ + asm volatile ("fence.i" ::: "memory"); + + read_ddr_info(&cfg); + ddr_init = (ddr_init_func_t)DDR_FIRMWARE_BASE; +#ifdef DEBUG + ddr_init(0xc0000000, cfg.cs_num, cfg.data_rate, puts); +#else + ddr_init(0xc0000000, cfg.cs_num, cfg.data_rate, NULL); +#endif + writel(MAGIC_NUM, (void __iomem *)0x00000000); + flush_dcache_range(0, 64); + invalidate_dcache_range(0, 64); + if (readl((void __iomem *)0x00000000) == MAGIC_NUM) + log_info("DDR is ready\n"); + else + log_info("DDR is not ready\n"); +} + +void nor_early_init(void) +{ + struct udevice *dev; + int ret; + + ret = uclass_get_device(UCLASS_SPI, 0, &dev); + if (ret) + panic("Fail to detect spi controller.\n"); + udelay(10); + ret = uclass_get_device(UCLASS_SPI_FLASH, 0, &dev); + if (ret) + log_info("Fail to detect spi nor flash.\n"); + udelay(10); +} + +void board_init_f(ulong dummy) +{ + int ret; + + ret = spl_early_init(); + if (ret) + panic("spl_early_init() failed:%d\n", ret); + + riscv_cpu_setup(); + + clk_early_init(); + serial_early_init(); + + preloader_console_init(); + + i2c_early_init(); + ret = read_product_name(product_name, I2C_BUF_SIZE); + if (ret) + log_info("Fail to detect board:%d\n", ret); + else + log_info("Get board name:%s\n", product_name); + pmic_init(); + + ddr_early_init(); + nor_early_init(); +} + +u32 spl_boot_device(void) +{ + return BOOT_DEVICE_SPI; +} + +void spl_board_init(void) +{ +} + +int board_fit_config_name_match(const char *name) +{ + char fdt_name[I2C_BUF_SIZE]; + int i; + + memset(fdt_name, 0, I2C_BUF_SIZE); + if (!strncmp(product_name, "k1-x_", 5)) { + snprintf(fdt_name, I2C_BUF_SIZE, "%s-%s", "k1", + &product_name[5]); + } + if (fdt_name[0] == '\0') { + /* set default board name */ + sprintf(fdt_name, "k1-musepi-pro"); + } + for (i = 0; i < I2C_BUF_SIZE; i++) { + if (fdt_name[i] == '\0') + break; + fdt_name[i] = tolower(fdt_name[i]); + } + if (!strcmp(name, fdt_name)) + return 0; + return -ENOENT; +} + +void *board_spl_fit_buffer_addr(ulong fit_size, int sectors, int bl_len) +{ + return (void *)CONFIG_SPL_LOAD_FIT_ADDRESS; +} diff --git a/board/spacemit/k1/tlv_codes.h b/board/spacemit/k1/tlv_codes.h new file mode 100644 index 00000000000..e40fbdcee6d --- /dev/null +++ b/board/spacemit/k1/tlv_codes.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2025-2026 RISCstar Ltd. + */ + +#ifndef __TLV_CODES_H +#define __TLV_CODES_H + +#define TLV_CODE_SDK_VERSION 0x40 +#define TLV_CODE_DDR_CSNUM 0x41 +#define TLV_CODE_DDR_TYPE 0x42 +#define TLV_CODE_DDR_DATARATE 0x43 +#define TLV_CODE_DDR_TX_ODT 0x44 + +#define TLV_CODE_WIFI_MAC_ADDR 0x60 +#define TLV_CODE_BLUETOOTH_ADDR 0x61 + +#define TLV_CODE_PMIC_TYPE 0x80 +#define TLV_CODE_EEPROM_I2C_INDEX 0x81 +#define TLV_CODE_EEPROM_PIN_GROUP 0x82 + +#endif /* __TLV_CODES_H */ diff --git a/board/st/common/MAINTAINERS b/board/st/common/MAINTAINERS index 0c6db547725..e87284c6a8b 100644 --- a/board/st/common/MAINTAINERS +++ b/board/st/common/MAINTAINERS @@ -1,6 +1,6 @@ ST BOARDS M: Patrick Delaunay <[email protected]> L: [email protected] (moderated for non-subscribers) -T: git https://source.denx.de/u-boot/custodians/u-boot-stm.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-stm.git S: Maintained F: board/st/common/ diff --git a/board/st/stm32mp1/MAINTAINERS b/board/st/stm32mp1/MAINTAINERS index f924e61b3c0..f488361ab47 100644 --- a/board/st/stm32mp1/MAINTAINERS +++ b/board/st/stm32mp1/MAINTAINERS @@ -2,7 +2,7 @@ STM32MP1 BOARD M: Patrick Delaunay <[email protected]> M: Patrice Chotard <[email protected]> L: [email protected] (moderated for non-subscribers) -T: git https://source.denx.de/u-boot/custodians/u-boot-stm.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-stm.git S: Maintained F: arch/arm/dts/stm32mp13* F: arch/arm/dts/stm32mp15* diff --git a/board/xilinx/microblaze-generic/MAINTAINERS b/board/xilinx/microblaze-generic/MAINTAINERS index 29ed32f78f9..5220a51a5ea 100644 --- a/board/xilinx/microblaze-generic/MAINTAINERS +++ b/board/xilinx/microblaze-generic/MAINTAINERS @@ -1,7 +1,7 @@ MICROBLAZE-GENERIC BOARD M: Michal Simek <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-microblaze.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-microblaze.git F: board/xilinx/microblaze-generic/ F: include/configs/microblaze-generic.h F: configs/microblaze-generic_defconfig diff --git a/board/xilinx/versal/MAINTAINERS b/board/xilinx/versal/MAINTAINERS index a13b6566164..07173ee916f 100644 --- a/board/xilinx/versal/MAINTAINERS +++ b/board/xilinx/versal/MAINTAINERS @@ -1,7 +1,7 @@ XILINX_VERSAL BOARDS M: Michal Simek <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-microblaze.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-microblaze.git F: arch/arm/dts/versal* F: board/xilinx/versal/ F: include/configs/xilinx_versal* diff --git a/board/xilinx/zynq/MAINTAINERS b/board/xilinx/zynq/MAINTAINERS index b5b9e2fe40a..3eb1a451b58 100644 --- a/board/xilinx/zynq/MAINTAINERS +++ b/board/xilinx/zynq/MAINTAINERS @@ -1,7 +1,7 @@ ZYNQ BOARD M: Michal Simek <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-microblaze.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-microblaze.git F: arch/arm/dts/zynq-* F: board/xilinx/zynq/ F: include/configs/zynq*.h diff --git a/board/xilinx/zynqmp/MAINTAINERS b/board/xilinx/zynqmp/MAINTAINERS index a4527f8959a..3db240782f4 100644 --- a/board/xilinx/zynqmp/MAINTAINERS +++ b/board/xilinx/zynqmp/MAINTAINERS @@ -1,7 +1,7 @@ XILINX_ZYNQMP BOARDS M: Michal Simek <[email protected]> S: Maintained -T: git https://source.denx.de/u-boot/custodians/u-boot-microblaze.git +T: git https://git.u-boot-project.org/u-boot/custodians/u-boot-microblaze.git F: arch/arm/dts/zynqmp-* F: arch/arm/dts/avnet-ultra96* F: board/xilinx/common/ diff --git a/cmd/config.c b/cmd/config.c index f0d2033c61f..22115e9b1da 100644 --- a/cmd/config.c +++ b/cmd/config.c @@ -6,6 +6,7 @@ #include <command.h> #include <gzip.h> #include <malloc.h> +#include <linux/string.h> #include "config_data_gz.h" #include "config_data_size.h" @@ -29,7 +30,23 @@ static int do_config(struct cmd_tbl *cmdtp, int flag, int argc, } dst[data_size] = 0; - puts(dst); + if (argc > 1) { + const char *s = argv[1]; + char *b = dst, *e = dst + data_size, *n; + + while (b < e) { + n = strchrnul(b, '\n'); + *n = '\0'; + + if (strcasestr(b, s)) { + puts(b); + puts("\n"); + } + b = n + 1; + } + } else { + puts(dst); + } free: free(dst); @@ -38,7 +55,10 @@ free: } U_BOOT_CMD( - config, 1, 1, do_config, + config, 2, 1, do_config, "print .config", - "" + "[str]\n" + "\n" + "When the optional argument is given, only lines containing\n" + "that string are printed. Matching is case-insensitive." ); diff --git a/cmd/read.c b/cmd/read.c index 8e21f004423..efc255ce85d 100644 --- a/cmd/read.c +++ b/cmd/read.c @@ -46,7 +46,7 @@ do_rw(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) limit = ~0; } - if (cnt + blk > limit) { + if (blk > limit || cnt > limit - blk) { printf("%s out of range\n", cmdtp->name); unmap_sysmem(ptr); return 1; diff --git a/common/bloblist.c b/common/bloblist.c index 51ae9cc50a5..846c8047f74 100644 --- a/common/bloblist.c +++ b/common/bloblist.c @@ -448,7 +448,7 @@ int bloblist_new(ulong addr, uint size, uint flags, uint align_log2) hdr->align_log2 = align_log2 ? align_log2 : BLOBLIST_BLOB_ALIGN_LOG2; hdr->chksum = 0; gd->bloblist = hdr; - gd->flags |= GD_FLG_BLOBLIST_READY; + gd->flags |= GD_FLG_BLOBLIST_HANDOFF; return 0; } @@ -476,7 +476,7 @@ int bloblist_check(ulong addr, uint size) return log_msg_ret("Bad checksum", -EIO); } gd->bloblist = hdr; - gd->flags |= GD_FLG_BLOBLIST_READY; + gd->flags |= GD_FLG_BLOBLIST_HANDOFF; return 0; } @@ -627,7 +627,7 @@ int bloblist_init(void) int ret; ulong addr = 0, size = CONFIG_BLOBLIST_SIZE; - if (gd->flags & GD_FLG_BLOBLIST_READY) { + if (gd->flags & GD_FLG_BLOBLIST_HANDOFF) { log_debug("Found existing bloblist size %x at %p\n", gd->bloblist->total_size, gd->bloblist); return 0; @@ -689,7 +689,7 @@ int bloblist_check_reg_conv(ulong rfdt, ulong rzero, ulong rsig, ulong xlist) if (rfdt != (ulong)bloblist_find(BLOBLISTT_CONTROL_FDT, 0)) { /* Remove this bloblist from gd */ gd->bloblist = NULL; - gd->flags &= ~GD_FLG_BLOBLIST_READY; + gd->flags &= ~GD_FLG_BLOBLIST_HANDOFF; return -EIO; } diff --git a/common/cyclic.c b/common/cyclic.c index ec952a01ee1..573e715587d 100644 --- a/common/cyclic.c +++ b/common/cyclic.c @@ -41,7 +41,7 @@ static bool cyclic_is_registered(const struct cyclic_info *cyclic) } void cyclic_register(struct cyclic_info *cyclic, cyclic_func_t func, - uint64_t delay_us, const char *name) + u64 delay_us, const char *name) { cyclic_unregister(cyclic); @@ -67,26 +67,28 @@ static void cyclic_run(void) { struct cyclic_info *cyclic; struct hlist_node *tmp; - uint64_t now, cpu_time; + u64 now, after, cpu_time; /* Prevent recursion */ if (gd->flags & GD_FLG_CYCLIC_RUNNING) return; gd->flags |= GD_FLG_CYCLIC_RUNNING; + now = get_timer_us(0); hlist_for_each_entry_safe(cyclic, tmp, cyclic_get_list(), list) { /* * Check if this cyclic function needs to get called, e.g. * do not call the cyclic func too often */ - now = get_timer_us(0); if (time_after_eq64(now, cyclic->next_call)) { /* Call cyclic function and account it's cpu-time */ cyclic->next_call = now + cyclic->delay_us; cyclic->func(cyclic); + after = get_timer_us(0); cyclic->run_cnt++; - cpu_time = get_timer_us(0) - now; + cpu_time = after - now; cyclic->cpu_time_us += cpu_time; + now = after; /* Check if cpu-time exceeds max allowed time */ if ((cpu_time > CONFIG_CYCLIC_MAX_CPU_TIME_US) && diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index d89384449b3..18bff7b8d4a 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -204,6 +204,9 @@ static int get_aligned_image_size(struct spl_load_info *info, int data_size, * If the FIT node does not contain a "load" (address) property, * the image gets loaded to the address pointed to by the * load_addr member in this struct, if load_addr is not 0 + * @max_size: maximum number of bytes that may be written to the + * destination; an image whose data exceeds this is rejected + * before it is read from the device * * Return: 0 on success, -EBADSLT if this image is not the correct phase * (for CONFIG_BOOTMETH_VBE_SIMPLE_FW), or another negative error number on @@ -211,7 +214,7 @@ static int get_aligned_image_size(struct spl_load_info *info, int data_size, */ static int load_simple_fit(struct spl_load_info *info, ulong fit_offset, const struct spl_fit_info *ctx, int node, - struct spl_image_info *image_info) + struct spl_image_info *image_info, ulong max_size) { int offset; size_t length; @@ -291,6 +294,23 @@ static int load_simple_fit(struct spl_load_info *info, ulong fit_offset, return 0; } + /* + * data-size is excluded from the configuration signature (it + * is in exc_prop[] in image-fit-sig.c), so it stays attacker + * controlled even after fit_config_verify() succeeds. The + * image hash is only verified after the device read below, so + * an oversized value has to be rejected here. + * + * Bail out before get_aligned_image_size() runs on a hostile + * len: that helper does its arithmetic in int and would + * invoke signed-integer overflow on a value close to or above + * INT_MAX. The block-aligned check further down is the + * mathematically binding one, since size is len rounded up to + * the device block length. + */ + if ((ulong)len > max_size) + goto too_big; + if (spl_decompression_enabled() && (image_comp == IH_COMP_GZIP || image_comp == IH_COMP_LZMA)) src_ptr = map_sysmem(ALIGN(CONFIG_SYS_LOAD_ADDR, ARCH_DMA_MINALIGN), len); @@ -302,6 +322,15 @@ static int load_simple_fit(struct spl_load_info *info, ulong fit_offset, size = get_aligned_image_size(info, length, offset); read_offset = fit_offset + get_aligned_image_offset(info, offset); + + /* + * info->read() transfers the block-aligned size into the + * destination, so this is the bound that actually matters; + * len was rejected above only to keep this computation safe. + */ + if (size > max_size) + goto too_big; + log_debug("reading from offset %x / %lx size %lx to %p: ", offset, read_offset, size, src_ptr); @@ -372,6 +401,11 @@ static int load_simple_fit(struct spl_load_info *info, ulong fit_offset, upl_add_image(fit, node, load_addr, length); return 0; + +too_big: + printf("%s: FIT image too large (data-size %u, max %lu)\n", + __func__, (u32)len, max_size); + return -EFBIG; } static bool os_takes_devicetree(uint8_t os) @@ -427,7 +461,8 @@ static int spl_fit_append_fdt(struct spl_image_info *spl_image, spl_image->fdt_addr = map_sysmem(image_info.load_addr, size); memcpy(spl_image->fdt_addr, gd->fdt_blob, size); } else { - ret = load_simple_fit(info, offset, ctx, node, &image_info); + ret = load_simple_fit(info, offset, ctx, node, &image_info, + CONFIG_SYS_BOOTM_LEN); if (ret < 0) return ret; @@ -479,7 +514,8 @@ static int spl_fit_append_fdt(struct spl_image_info *spl_image, } image_info.load_addr = (ulong)tmpbuffer; ret = load_simple_fit(info, offset, ctx, node, - &image_info); + &image_info, + CONFIG_SPL_LOAD_FIT_APPLY_OVERLAY_BUF_SZ); if (ret == -EBADSLT) continue; else if (ret < 0) @@ -687,7 +723,8 @@ static int spl_fit_load_fpga(struct spl_fit_info *ctx, warn_deprecated("'fpga' property in config node. Use 'loadables'"); /* Load the image and set up the fpga_image structure */ - ret = load_simple_fit(info, offset, ctx, node, &fpga_image); + ret = load_simple_fit(info, offset, ctx, node, &fpga_image, + CONFIG_SYS_BOOTM_LEN); if (ret) { printf("%s: Cannot load the FPGA: %i\n", __func__, ret); return ret; @@ -849,7 +886,8 @@ int spl_load_simple_fit(struct spl_image_info *spl_image, } /* Load the image and set up the spl_image structure */ - ret = load_simple_fit(info, offset, &ctx, node, spl_image); + ret = load_simple_fit(info, offset, &ctx, node, spl_image, + CONFIG_SYS_BOOTM_LEN); if (ret) return ret; @@ -890,7 +928,8 @@ int spl_load_simple_fit(struct spl_image_info *spl_image, continue; image_info.load_addr = 0; - ret = load_simple_fit(info, offset, &ctx, node, &image_info); + ret = load_simple_fit(info, offset, &ctx, node, &image_info, + CONFIG_SYS_BOOTM_LEN); if (ret < 0 && ret != -EBADSLT) { printf("%s: can't load image loadables index %d (ret = %d)\n", __func__, index, ret); diff --git a/configs/bananapi-f3_defconfig b/configs/bananapi-f3_defconfig deleted file mode 100644 index a726ce84775..00000000000 --- a/configs/bananapi-f3_defconfig +++ /dev/null @@ -1,24 +0,0 @@ -CONFIG_RISCV=y -CONFIG_SYS_MALLOC_LEN=0x1000000 -CONFIG_NR_DRAM_BANKS=2 -CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y -CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x1000000 -CONFIG_DEFAULT_DEVICE_TREE="k1-bananapi-f3" -CONFIG_SYS_BOOTM_LEN=0xa000000 -CONFIG_SYS_LOAD_ADDR=0x200000 -CONFIG_TARGET_BANANAPI_F3=y -CONFIG_ARCH_RV64I=y -CONFIG_RISCV_SMODE=y -CONFIG_FIT=y -CONFIG_SUPPORT_RAW_INITRD=y -CONFIG_OF_BOARD_SETUP=y -CONFIG_SYS_CBSIZE=256 -CONFIG_SYS_PBSIZE=276 -# CONFIG_BOARD_INIT is not set -CONFIG_HUSH_PARSER=y -CONFIG_ENV_OVERWRITE=y -CONFIG_PINCTRL=y -CONFIG_PINCTRL_SINGLE=y -CONFIG_RESET_SPACEMIT_K1=y -CONFIG_SYS_NS16550=y -CONFIG_SYS_NS16550_MEM32=y diff --git a/configs/spacemit_k1_defconfig b/configs/spacemit_k1_defconfig new file mode 100644 index 00000000000..0604c2feefc --- /dev/null +++ b/configs/spacemit_k1_defconfig @@ -0,0 +1,95 @@ +CONFIG_RISCV=y +CONFIG_SYS_MALLOC_LEN=0x1000000 +CONFIG_SYS_MALLOC_F_LEN=0x10000 +CONFIG_NR_DRAM_BANKS=2 +CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y +CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x1000000 +CONFIG_DEFAULT_DEVICE_TREE="spacemit/k1-musepi-pro" +CONFIG_OF_LIST="spacemit/k1-bananapi-f3 spacemit/k1-musepi-pro" +CONFIG_SPL_SYS_MALLOC_F_LEN=0x4000 +CONFIG_SPL_STACK=0xc083fb00 +CONFIG_SPL_TEXT_BASE=0xc0801000 +CONFIG_SPL_BSS_START_ADDR=0xc083fc00 +CONFIG_SPL_BSS_MAX_SIZE=0x400 +CONFIG_SPL_STACK_R=y +CONFIG_SPL_STACK_R_ADDR=0xc00000 +CONFIG_SPL_SYS_MALLOC_SIMPLE=y +CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x100000 +CONFIG_SYS_BOOTM_LEN=0xa000000 +CONFIG_SYS_LOAD_ADDR=0x200000 +CONFIG_SPL_SIZE_LIMIT=0x31000 +CONFIG_SPL=y +CONFIG_DEBUG_UART_BASE=0xd4017000 +CONFIG_DEBUG_UART_CLOCK=14700000 +CONFIG_TARGET_SPACEMIT_K1=y +CONFIG_ARCH_RV64I=y +CONFIG_RISCV_SMODE=y +CONFIG_SPL_RISCV_MMODE=y +# CONFIG_SPL_SMP is not set +CONFIG_STACK_SIZE=0x100000 +CONFIG_FIT=y +CONFIG_MULTI_DTB_FIT=y +CONFIG_SPL_HAS_LOAD_FIT_ADDRESS=y +CONFIG_SPL_LOAD_FIT_ADDRESS=0x08000000 +CONFIG_SUPPORT_RAW_INITRD=y +CONFIG_OF_BOARD_SETUP=y +CONFIG_SYS_CBSIZE=256 +CONFIG_SYS_PBSIZE=276 +# CONFIG_BOARD_INIT is not set +CONFIG_SPL_MAX_SIZE=0x33000 +# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set +CONFIG_SPL_HAVE_INIT_STACK=y +CONFIG_SPL_I2C=y +CONFIG_SPL_DM_RESET=y +CONFIG_SPL_POWER=y +CONFIG_HUSH_PARSER=y +CONFIG_CMD_TLV_EEPROM=y +CONFIG_SPL_CMD_TLV_EEPROM=y +CONFIG_OF_UPSTREAM=y +CONFIG_ENV_OVERWRITE=y +CONFIG_SPL_REGMAP=y +CONFIG_SPL_SYSCON=y +CONFIG_CLK=y +CONFIG_CLK_CCF=y +CONFIG_SPL_CLK=y +CONFIG_SPL_CLK_CCF=y +CONFIG_CLK_SPACEMIT=y +CONFIG_CLK_SPACEMIT_K1=y +CONFIG_DM_I2C=y +CONFIG_SYS_I2C_SPACEMIT_K1=y +CONFIG_MISC=y +CONFIG_I2C_EEPROM=y +CONFIG_SPL_I2C_EEPROM=y +CONFIG_PINCTRL=y +CONFIG_PINCTRL_SPACEMIT_K1=y +CONFIG_GPIO=y +CONFIG_DM_GPIO=y +CONFIG_CMD_GPIO=y +CONFIG_SPACEMIT_GPIO=y +CONFIG_DM_PMIC=y +CONFIG_PMIC_SPACEMIT_P1=y +CONFIG_DM_REGULATOR=y +CONFIG_SPL_DM_REGULATOR=y +CONFIG_DM_REGULATOR_SPACEMIT_P1=y +CONFIG_DEBUG_UART_NS16550=y +CONFIG_DEBUG_UART_SHIFT=2 +CONFIG_DEBUG_UART_ANNOUNCE=y +CONFIG_SYS_NS16550=y +CONFIG_SYS_NS16550_MEM32=y +CONFIG_TIMER_EARLY=y +CONFIG_SPL_LIB_RATIONAL=y +CONFIG_SPI=y +CONFIG_DM_SPI=y +CONFIG_DM_SPI_FLASH=y +CONFIG_FSL_QSPI=y +CONFIG_SPI_FLASH=y +CONFIG_SPI_FLASH_WINBOND=y +CONFIG_SPI_MEM=y +CONFIG_SYS_SPI_U_BOOT_OFFS=0x000a0000 +CONFIG_CMD_SPI=y +CONFIG_SPL_SPI=y +CONFIG_SPL_DM_SPI=y +CONFIG_SPL_DM_SPI_FLASH=y +CONFIG_SPL_SPI_LOAD=y +CONFIG_SPL_SPI_FLASH_TINY=y +CONFIG_SPL_SPI_FLASH_SUPPORT=y diff --git a/doc/CONTRIBUTE.rst b/doc/CONTRIBUTE.rst index e8fa595ed4a..a95b9c98263 100644 --- a/doc/CONTRIBUTE.rst +++ b/doc/CONTRIBUTE.rst @@ -19,7 +19,7 @@ projects available to review if you are unsure of expectations. Repository ---------- -The official U-Boot repository is located at https://source.denx.de/u-boot/u-boot +The official U-Boot repository is located at https://git.u-boot-project.org/u-boot/u-boot Further more detailed documentation can be found at the following link: :doc:`/index`. @@ -28,7 +28,7 @@ Contributions Contributions to the project are welcome. The U-Boot project uses a fairly traditional Linux style development work-flow using git and `a mailing list -<https://lists.denx.de/listinfo/u-boot>`_. +<https://lists.u-boot-project.org/listinfo/u-boot>`_. Patches should be sent to the mailing list using ``git send-email`` or the equivalent commands using ``b4`` or ``patman`` with appropriate sign-off and @@ -41,7 +41,7 @@ The b4 tool automates a number of components mentioned above. Code is not the only thing you can contribute to the project. As most open-source projects, the U-Boot project suffers from a lack of reviewers. Consider spending some time reading patches on `the mailing list archive -<https://lists.denx.de/pipermail/u-boot/>`_ and providing feedback to +<https://lists.u-boot-project.org/pipermail/u-boot/>`_ and providing feedback to contributors when something could be improved or if you have questions. Contrary to what's most often believed, you do not need to be an expert to review patches and the project will benefit from people with different skillsets and experience diff --git a/doc/board/intel/slimbootloader.rst b/doc/board/intel/slimbootloader.rst index 87d71a55bdc..a1d9102859b 100644 --- a/doc/board/intel/slimbootloader.rst +++ b/doc/board/intel/slimbootloader.rst @@ -170,7 +170,7 @@ Build Instruction to use ELF U-Boot $ python BuildLoader.py build <qemu or apl> -p "OsLoader.efi:LLDR:Lz4;u-boot:U-BT:Lzma" -.. _U-Boot: https://source.denx.de/ +.. _U-Boot: https://git.u-boot-project.org/ .. _`Slim Bootloader`: https://github.com/slimbootloader/ .. _`Intel FSP`: https://github.com/IntelFsp/ .. _`Getting Started`: https://slimbootloader.github.io/getting-started/ diff --git a/doc/board/renesas/rzn1.rst b/doc/board/renesas/rzn1.rst index 5f054e8c674..24ce7709dd7 100644 --- a/doc/board/renesas/rzn1.rst +++ b/doc/board/renesas/rzn1.rst @@ -17,7 +17,7 @@ Clone the U-Boot repository and build it as follows: .. code-block:: bash - git clone --depth 1 https://source.denx.de/u-boot/u-boot.git + git clone --depth 1 https://git.u-boot-project.org/u-boot/u-boot.git cd u-boot make rzn1_snarc_defconfig make CROSS_COMPILE=arm-linux-gnu- diff --git a/doc/board/rockchip/rockchip.rst b/doc/board/rockchip/rockchip.rst index f77f1e78f38..9351a5b8eae 100644 --- a/doc/board/rockchip/rockchip.rst +++ b/doc/board/rockchip/rockchip.rst @@ -228,7 +228,7 @@ U-Boot .. code-block:: bash - git clone --depth 1 https://source.denx.de/u-boot/u-boot.git + git clone --depth 1 https://git.u-boot-project.org/u-boot/u-boot.git cd u-boot To build px30 boards: diff --git a/doc/board/spacemit/bananapi-f3.rst b/doc/board/spacemit/bananapi-f3.rst index f2220950a3a..1ece2ce9d02 100644 --- a/doc/board/spacemit/bananapi-f3.rst +++ b/doc/board/spacemit/bananapi-f3.rst @@ -29,7 +29,7 @@ built for SpacemiT K1 SoC as below: .. code-block:: console cd <U-Boot-dir> - make bananapi-f3_defconfig + make spacemit_k1_defconfig make OPENSBI=<OpenSBI-dir>/build/platform/generic/firmware/fw_dynamic.bin This will generate u-boot.itb diff --git a/doc/board/spacemit/index.rst b/doc/board/spacemit/index.rst index e7d3d94e459..a5e35ee12ab 100644 --- a/doc/board/spacemit/index.rst +++ b/doc/board/spacemit/index.rst @@ -6,4 +6,5 @@ SpacemiT :maxdepth: 1 bananapi-f3 + k1-spl diff --git a/doc/board/spacemit/k1-spl.rst b/doc/board/spacemit/k1-spl.rst new file mode 100644 index 00000000000..187eed56e8e --- /dev/null +++ b/doc/board/spacemit/k1-spl.rst @@ -0,0 +1,243 @@ +.. SPDX-License-Identifier: GPL-2.0-or-later + +SpacemiT K1 SPL Build and Test Guide +===================================== + +This guide explains how to build and test U-Boot SPL on SpacemiT K1 based +boards. It covers building SPL with DDR initialization, generating the signed +FSBL image, and deploying via USB fastboot. + +Tested boards: Banana Pi BPI-F3, MusePi Pro. + +.. note:: + + The procedure described here loads SPL into SRAM via USB fastboot and + does not modify the on-board flash, so a power cycle restores the + board's normal boot path. + + At this stage of the patchset, SPL initializes DDR and then halts with + "SPL: Unsupported Boot Device!" because SPI NOR storage support is not + yet available in U-Boot proper. This document will be updated when + U-Boot stage support is ready. + +Prerequisites +~~~~~~~~~~~~~ + +- A SpacemiT K1 board with USB Type-C and UART access +- USB-to-UART adapter (3.3V TTL) +- ``minicom`` or equivalent serial terminal, configured at 115200 8N1 +- ``fastboot`` tool on the host + +Hardware Setup +~~~~~~~~~~~~~~ + +**1. UART Connection** + +Remove all other cables first, then attach UART. Connect a 3.3V +USB-to-UART cable to the board's UART header (J25 on the BPI-F3):: + + BPI-F3 top view + +--------------------------------------------------+ + | | + | J15: USB-C [====] [FDL] [PWR] [RST] | + | | + | | + | J25 (UART header) | + | [TXD] [RXD] [GND] | + +--------------------------------------------------+ + +After UART is connected, attach the USB Type-C cable to the OTG port +(J15 on BPI-F3) to power on. + +**2. Serial Console** + +.. code-block:: console + + $ minicom -D /dev/ttyUSB0 + +Default baudrate: 115200. + +Building U-Boot SPL +~~~~~~~~~~~~~~~~~~~~ + +**1. Obtain the DDR training firmware** + +The DDR training firmware is a proprietary binary provided by SpacemiT. It is +not included in U-Boot and must be downloaded separately from: + +https://github.com/spacemit-com/spacemit-firmware/tree/master/k1/v0.2 + +Download ``ddr_fw.bin`` from that directory. + +This binary is integrated into the SPL image at build time via the binman +framework. When the SPL image is loaded to SRAM (e.g., via USB fastboot), +the SPL executes the DDR firmware from SRAM to perform DDR initialization. + +**2. Obtain OpenSBI fw_dynamic.bin** + +Any pre-built ``fw_dynamic.bin`` is sufficient. Upstream OpenSBI +sources are at https://github.com/riscv-software-src/opensbi if you +need to build one. + +At this stage of the patchset, SPL halts before invoking OpenSBI, +but U-Boot's binman still packages ``fw_dynamic.bin`` into +``u-boot.itb`` and the build fails if it is missing. + +**3. Build SPL** + +.. code-block:: console + + $ export CROSS_COMPILE=riscv64-linux-gnu- + $ export ARCH=riscv + $ export DDR_FW_FILE=$(pwd)/ddr_fw.bin + $ export OPENSBI=/path/to/fw_dynamic.bin + $ make spacemit_k1_defconfig + $ make + +Output: ``u-boot-spl-ddr.bin`` in the build directory. This image contains the +SPL code and the DDR firmware blob packaged together via binman. + +.. note:: + + If ``DDR_FW_FILE`` is not set, the build completes with an empty + placeholder. The resulting SPL will boot but cannot initialize DDR. + +**4. Generate signed FSBL image** + +The K1 BootROM requires a signed first-stage bootloader (FSBL). The signing +tool (``tools/build_binary_file.py``) is in SpacemiT's vendor U-Boot repository: + +.. code-block:: console + + $ git clone -b k1-bl-v2.2.y https://gitee.com/spacemit-buildroot/uboot-2022.10 + +The script uses ``fsbl_ddr.json`` which may not exist by default. If +``fsbl_ddr.json`` does not exist in +``uboot-2022.10/board/spacemit/k1-x/configs/``, +create it by copying ``fsbl.json`` and replacing the reference to +``u-boot-spl.bin`` with ``u-boot-spl-ddr.bin``: + +.. code-block:: console + + $ cd uboot-2022.10/board/spacemit/k1-x/configs + $ cp fsbl.json fsbl_ddr.json + $ sed -i 's/u-boot-spl\.bin/u-boot-spl-ddr.bin/g' fsbl_ddr.json + +Create the ``fsbl.sh`` script below in the ``uboot-2022.10`` directory. +Update the path variables to match your local setup: + +.. code-block:: bash + + #!/bin/sh + MAINLINE_UBOOT_IMG_PATH="{your path}/u-boot" + MAINLINE_SPL_IMG_PATH="{your path}/u-boot/spl" + FSBL_PATH="{your path}/uboot-2022.10/spl_bin" + KEY_TOOL_PATH="{your path}/uboot-2022.10/tools" + CONFIG_PATH="{your path}/uboot-2022.10/board/spacemit/k1-x/configs" + + mkdir -p ${FSBL_PATH} + echo "Clean binaries in ${FSBL_PATH}" + rm -f ${FSBL_PATH}/u-boot-spl-ddr.bin + rm -f ${FSBL_PATH}/u-boot-spl.bin + + if [ ! -d ${MAINLINE_SPL_IMG_PATH} ]; then + MAINLINE_UBOOT_IMG_PATH="{your path}/build" + MAINLINE_SPL_IMG_PATH="{your path}/build/spl" + fi + + # The signing tool reads u-boot-spl-ddr.bin from the path declared in + # fsbl_ddr.json's "source" field, which is resolved relative to the + # JSON file's directory -- i.e. one level up from CONFIG_PATH, not + # FSBL_PATH. Stage the unsigned binary there before signing. + cp ${MAINLINE_UBOOT_IMG_PATH}/u-boot-spl-ddr.bin ${CONFIG_PATH}/../ + python3 ${KEY_TOOL_PATH}/build_binary_file.py \ + -c ${CONFIG_PATH}/fsbl_ddr.json \ + -o ${FSBL_PATH}/FSBL.bin + +Then run: + +.. code-block:: console + + $ chmod +x fsbl.sh + $ ./fsbl.sh + +Output: ``FSBL.bin`` in the ``spl_bin`` directory, ready for deployment. + +Deploying via USB Fastboot +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To enter BootROM fastboot mode: + +1. Power off the board by unplugging its power supply. +2. **Press and hold** the FDL button (called "Boot Key" on some boards; + see the board layout above for the BPI-F3). +3. While holding the button, use a USB cable to connect the OTG port to + your host. This cable is also used by fastboot to upload the firmware. +4. Release the button. + +On the host, ``fastboot devices`` should list the board:: + + dfu-device DFU download + +The serial console shows the BootROM's USB download handler trace, +including a line like:: + + usb2d_initialize : enter + +This indicates the board is ready to accept an image via USB. + +.. tip:: + + If you are worried about insufficient USB power, you can first plug + in the power, then release the button, and then plug in the USB + cable. + +On the host: + +.. code-block:: console + + $ sudo fastboot stage FSBL.bin + $ sudo fastboot continue + +Expected Output +~~~~~~~~~~~~~~~~ + +During successful SPL boot with DDR initialization, the serial console +shows output like:: + + <debug_uart> + + U-Boot SPL 2026.04-rc4-00430-g8b84b1ed8ea9 (May 08 2026 - 09:08:27 -0400) + Fail to detect board:-19 + vdd_core, value:900000 + vdd_1v8, value:1800000 + vdd_1v8_mmc, value:1800000 + DDR firmware: [0xc0815840]:0xf0227179, size:0x8d98 + DDR is ready + SPL: Unsupported Boot Device! + SPL: failed to boot from all boot devices + ### ERROR ### Please RESET the board ### + +To walk through the key lines: + +- ``DDR firmware: [...], size:0x8d98`` - DDR firmware loaded successfully +- ``DDR is ready`` - DDR initialization completed +- ``SPL: failed to boot from all boot devices`` - expected at this stage, + confirms that SPL with DDR init is working correctly + +If SPL hangs before printing DDR messages, verify that ``DDR_FW_FILE`` was set +during build and that ``ddr_fw.bin`` is not empty. + +.. tip:: + + To see verbose DDR training output from the DDR firmware (per-phase + training pass/fail logs), add ``#define DEBUG`` at the top of + ``board/spacemit/k1/spl.c`` and rebuild. SPL then passes ``puts`` as + the firmware's log callback; otherwise the callback is ``NULL`` and + the firmware runs silently. + +References +~~~~~~~~~~~ + +- `DDR firmware repository <https://github.com/spacemit-com/spacemit-firmware>`_ +- `SpacemiT vendor U-Boot (signing tool) <https://gitee.com/spacemit-buildroot/uboot-2022.10>`_ diff --git a/doc/board/starfive/jh7110_common.rst b/doc/board/starfive/jh7110_common.rst index e9c0ed5b022..013bab50045 100644 --- a/doc/board/starfive/jh7110_common.rst +++ b/doc/board/starfive/jh7110_common.rst @@ -170,7 +170,7 @@ Build U-Boot .. code-block:: console - git clone https://source.denx.de/u-boot/u-boot.git u-boot.git + git clone https://git.u-boot-project.org/u-boot/u-boot.git u-boot.git make -C u-boot.git O=u-boot starfive_visionfive2_defconfig make -C u-boot.git O=u-boot OPENSBI=opensbi/platform/generic/firmware/fw_dynamic.bin diff --git a/doc/board/ti/k3.rst b/doc/board/ti/k3.rst index 21973d53b15..d3ecaf59909 100644 --- a/doc/board/ti/k3.rst +++ b/doc/board/ti/k3.rst @@ -170,7 +170,7 @@ online * **Das U-Boot** - | **source:** https://source.denx.de/u-boot/u-boot.git + | **source:** https://git.u-boot-project.org/u-boot/u-boot.git | **branch:** master * **Trusted Firmware-A (TF-A)** diff --git a/doc/build/source.rst b/doc/build/source.rst index d21ee055f33..8407945a13f 100644 --- a/doc/build/source.rst +++ b/doc/build/source.rst @@ -7,7 +7,7 @@ You can download the source via .. code-block:: bash - git clone https://source.denx.de/u-boot/u-boot.git + git clone https://git.u-boot-project.org/u-boot/u-boot.git A mirror of the source is maintained on Github diff --git a/doc/develop/pytest/usage.rst b/doc/develop/pytest/usage.rst index 6002244d608..a9b8b8bd610 100644 --- a/doc/develop/pytest/usage.rst +++ b/doc/develop/pytest/usage.rst @@ -411,7 +411,7 @@ The board can be switched off now. Examples '''''''' -https://source.denx.de/u-boot/u-boot-test-hooks contains some working example hook +https://git.u-boot-project.org/u-boot/u-boot-test-hooks contains some working example hook scripts, and may be useful as a reference when implementing hook scripts for your platform. These scripts are not considered part of U-Boot itself. diff --git a/doc/develop/release_cycle.rst b/doc/develop/release_cycle.rst index a454d343676..ee77e8827df 100644 --- a/doc/develop/release_cycle.rst +++ b/doc/develop/release_cycle.rst @@ -96,7 +96,7 @@ Previous Releases ----------------- Note: these statistics are generated by our fork of `gitdm -<https://source.denx.de/u-boot/gitdm>`_, which was originally created by +<https://git.u-boot-project.org/u-boot/gitdm>`_, which was originally created by Jonathan Corbet. * :doc:`statistics/u-boot-stats-v2026.07` which was released on 06 July 2026. diff --git a/doc/develop/security.rst b/doc/develop/security.rst index 84b130646f3..ed652ec756e 100644 --- a/doc/develop/security.rst +++ b/doc/develop/security.rst @@ -11,7 +11,7 @@ Contact ------- The preferred initial point of contact is to send email to -`[email protected]` and use `scripts/get_maintainers.pl` to also include any +`[email protected]` and use `scripts/get_maintainers.pl` to also include any relevant custodians. In addition, Tom Rini should be contacted at diff --git a/doc/develop/sending_patches.rst b/doc/develop/sending_patches.rst index c3e0ef27824..8172dc55183 100644 --- a/doc/develop/sending_patches.rst +++ b/doc/develop/sending_patches.rst @@ -5,7 +5,7 @@ Sending patches *Before you begin* to implement any new ideas or concepts it is always a good idea to present your plans on the `U-Boot mailing list -<https://lists.denx.de/listinfo/u-boot>`_. U-Boot supports a huge amount of +<https://lists.u-boot-project.org/listinfo/u-boot>`_. U-Boot supports a huge amount of very different systems, and it is often impossible for the individual developer to oversee the consequences of a specific change to all architectures. Discussing concepts early can help you to avoid spending effort on code which, @@ -25,7 +25,7 @@ Using b4 Use the `b4 <https://b4.docs.kernel.org/en/latest/>`__ tool to prepare and send your patches. b4 has become the preferred tool to sending patches for many Linux kernel contributors, and U-Boot ships with a ready-to-use ``.b4-config`` that -targets ``[email protected]`` and integrates with ``scripts/get_maintainer.pl`` +targets ``[email protected]`` and integrates with ``scripts/get_maintainer.pl`` for recipient discovery. Start a topical series with ``b4 prep`` and keep the commits organised with @@ -51,7 +51,7 @@ additional runs. When the series is ready, use ``b4 send``. Begin with ``--dry-run`` to review the generated emails and ``--reflect`` to copy yourself for records before -dispatching to ``[email protected]``. +dispatching to ``[email protected]``. .. code-block:: bash @@ -86,8 +86,8 @@ patman now lives outside the U-Boot tree; install it with General Patch Submission Rules ------------------------------ -* All patches must be sent to the `[email protected] - <https://lists.denx.de/listinfo/u-boot>`_ mailing list. +* All patches must be sent to the `[email protected] + <https://lists.u-boot-project.org/listinfo/u-boot>`_ mailing list. * If your patch affects the code maintained by one of the :ref:`custodians`, CC them when emailing your patch. The easiest way to make sure you don't forget @@ -134,7 +134,7 @@ General Patch Submission Rules patches is by using the ``git format-patch`` command. For a patch that is fixing a bug or regression of some sort, please use the ``master`` branch of the mainline U-Boot git repository located at - https://source.denx.de/u-boot/u-boot.git as reference. For new features, if + https://git.u-boot-project.org/u-boot/u-boot.git as reference. For new features, if the ``next`` branch has been opened (which happens with the release of ``-rc2``) that branch should be used, otherwise ``master`` is acceptable. @@ -145,7 +145,7 @@ General Patch Submission Rules If you believe you need to use a mailing list for testing (instead of any regular mail address you own), we have a special test list for such purposes. It would be best to subscribe to the list for the duration of your tests to - avoid repeated moderation - see https://lists.denx.de/listinfo/test + avoid repeated moderation - see https://lists.u-boot-project.org/listinfo/test * Choose a meaningful Subject: - keep in mind that the Subject will also be visible as headline of your commit message. Make sure the subject does not diff --git a/doc/git-mailrc b/doc/git-mailrc index 65626d89eac..f0ba30a5c74 100644 --- a/doc/git-mailrc +++ b/doc/git-mailrc @@ -5,7 +5,7 @@ # Then when sending patches, you can use: # git send-email --to u-boot --cc i2c ... -alias uboot [email protected] +alias uboot [email protected] alias u-boot uboot # Maintainer aliases. Use the same alias here as patchwork to keep diff --git a/doc/index.rst b/doc/index.rst index 5d732ff7a54..6fe8ca0788b 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -9,7 +9,7 @@ This is the top level of the U-Boot's documentation tree. U-Boot documentation, like the U-Boot itself, is very much a work in progress; that is especially true as we work to integrate our many scattered documents into a coherent whole. Please note that improvements to the -documentation are welcome; join the U-Boot list at http://lists.denx.de +documentation are welcome; join the U-Boot list at http://lists.u-boot-project.org if you want to help out. .. toctree:: diff --git a/doc/usage/cmd/config.rst b/doc/usage/cmd/config.rst new file mode 100644 index 00000000000..bd8aa65ddbc --- /dev/null +++ b/doc/usage/cmd/config.rst @@ -0,0 +1,40 @@ +.. SPDX-License-Identifier: GPL-2.0 + +.. index:: + single: config (command) + +config command +============== + +Synopsis +-------- + +:: + + config [<str>] + +Description +----------- + +The config command prints the `.config` file used when building U-Boot +to the console. Note that the `.config` file is usually several 1000 +lines long. + +If the optional argument is given, only lines containing that string +(case insensitively) are printed. That can be useful if one wants to +check whether a specific option is enabled, or just to limit the +output to the subsystem of interest. + +The `.config` file is stored inside the U-Boot binary in +gzip-compressed format. + +Examples +-------- + +.. code-block:: bash + + # Print the entire .config + config + + # Print all lines related to pinctrl + config pinctrl diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index e69b0543817..145e4cfa2de 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -277,11 +277,12 @@ source "drivers/clk/mvebu/Kconfig" source "drivers/clk/owl/Kconfig" source "drivers/clk/qcom/Kconfig" source "drivers/clk/renesas/Kconfig" -source "drivers/clk/sophgo/Kconfig" -source "drivers/clk/sunxi/Kconfig" source "drivers/clk/sifive/Kconfig" +source "drivers/clk/sophgo/Kconfig" +source "drivers/clk/spacemit/Kconfig" source "drivers/clk/starfive/Kconfig" source "drivers/clk/stm32/Kconfig" +source "drivers/clk/sunxi/Kconfig" source "drivers/clk/tegra/Kconfig" source "drivers/clk/ti/Kconfig" source "drivers/clk/thead/Kconfig" diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index c37ef75d420..2bfa789e48a 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -48,6 +48,7 @@ obj-$(CONFIG_CLK_RENESAS) += renesas/ obj-$(CONFIG_$(PHASE_)CLK_SCMI) += clk_scmi.o obj-$(CONFIG_CLK_SIFIVE) += sifive/ obj-$(CONFIG_CLK_SOPHGO) += sophgo/ +obj-$(CONFIG_CLK_SPACEMIT) += spacemit/ obj-$(CONFIG_CLK_SUNXI) += sunxi/ obj-$(CONFIG_CLK_UNIPHIER) += uniphier/ obj-$(CONFIG_CLK_VERSACLOCK) += clk_versaclock.o diff --git a/drivers/clk/airoha/clk-airoha.c b/drivers/clk/airoha/clk-airoha.c index 49dbca82135..89a8b4cb1cf 100644 --- a/drivers/clk/airoha/clk-airoha.c +++ b/drivers/clk/airoha/clk-airoha.c @@ -327,7 +327,7 @@ static int airoha_clk_enable(struct clk *clk) struct airoha_clk_soc_data *data = priv->data; int id = clk->id; - if (id > data->num_clocks) + if (id >= data->num_clocks) return -EINVAL; return 0; @@ -349,7 +349,7 @@ static ulong airoha_clk_get_rate(struct clk *clk) ulong rate; int ret; - if (id > data->num_clocks) { + if (id >= data->num_clocks) { dev_err(clk->dev, "Invalid clk ID %d\n", id); return 0; } @@ -412,7 +412,7 @@ static ulong airoha_clk_set_rate(struct clk *clk, ulong rate) int div; int ret; - if (id > data->num_clocks) { + if (id >= data->num_clocks) { dev_err(clk->dev, "Invalid clk ID %d\n", id); return 0; } diff --git a/drivers/clk/spacemit/Kconfig b/drivers/clk/spacemit/Kconfig new file mode 100644 index 00000000000..25a3c1e4a45 --- /dev/null +++ b/drivers/clk/spacemit/Kconfig @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Copyright (c) 2025, Junhui Liu <[email protected]> + +config CLK_SPACEMIT + bool "Clock support for SpacemiT SoCs" + depends on CLK || COMPILE_TEST + select REGMAP + select LIB_RATIONAL + help + This enables support clock driver for Spacemit SoC + family. + +if CLK_SPACEMIT + +config CLK_SPACEMIT_K1 + bool "SpacemiT K1 clock support" + select CLK_CCF + help + This enables support clock driver for Spacemit K1 SoC. + It's based on Common Clock Framework. + +endif diff --git a/drivers/clk/spacemit/Makefile b/drivers/clk/spacemit/Makefile new file mode 100644 index 00000000000..824e94d1f74 --- /dev/null +++ b/drivers/clk/spacemit/Makefile @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Copyright (C) 2025 Junhui Liu <[email protected]> + +obj-$(CONFIG_CLK_SPACEMIT) += clk_ddn.o clk_mix.o clk_pll.o + +obj-$(CONFIG_CLK_SPACEMIT_K1) += clk-k1.o diff --git a/drivers/clk/spacemit/clk-k1.c b/drivers/clk/spacemit/clk-k1.c new file mode 100644 index 00000000000..07adc126ee3 --- /dev/null +++ b/drivers/clk/spacemit/clk-k1.c @@ -0,0 +1,1878 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2024 SpacemiT Technology Co. Ltd + * Copyright (c) 2024-2025 Haylen Chu <[email protected]> + * Copyright (c) 2025 Junhui Liu <[email protected]> + * Copyright (c) 2025-2026 RISCstar Ltd. + * + * Authors: Haylen Chu <[email protected]> + */ + +#include <dm.h> +#include <dm/device_compat.h> +#include <dm/lists.h> +#include <regmap.h> +#include <linux/clk-provider.h> +#include <soc/spacemit/k1-reset.h> +#include <soc/spacemit/k1-syscon.h> + +#include "clk_common.h" +#include "clk_ddn.h" +#include "clk_mix.h" +#include "clk_pll.h" + +#include <dt-bindings/clock/spacemit,k1-syscon.h> + +#define K1_PLL_ID 100 +#define K1_MPMU_ID 200 +#define K1_APBC_ID 300 +#define K1_APMU_ID 400 + +struct spacemit_ccu_data { + struct clk **clks; + size_t num; + unsigned long offset; +}; + +/* APBS clocks start, APBS region contains and only contains all PLL clocks */ + +/* + * PLL{1,2} must run at fixed frequencies to provide clocks in correct rates for + * peripherals. + */ +static const struct ccu_pll_rate_tbl pll1_rate_tbl[] = { + CCU_PLL_RATE(2457600000UL, 0x0050dd64, 0x330ccccd), +}; + +#if IS_ENABLED(CONFIG_SPL_BUILD) +CCU_PLL_DEFINE(CLK_PLL1, pll1, pll1, "clock-24m", pll1_rate_tbl, + APBS_PLL1_SWCR1, APBS_PLL1_SWCR3, MPMU_POSR, POSR_PLL1_LOCK, + CLK_SET_RATE_GATE); + +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_D4, pll1_d4, pll1_d4, "pll1", APBS_PLL1_SWCR2, + BIT(3), 4, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_D6, pll1_d6, pll1_d6, "pll1", APBS_PLL1_SWCR2, + BIT(5), 6, 1); +CCU_FACTOR_GATE_FLAGS_DEFINE(CLK_PLL1_D8, pll1_d8, pll1_d8, "pll1", + APBS_PLL1_SWCR2, BIT(7), 8, 1, CLK_IS_CRITICAL); +#else +static const struct ccu_pll_rate_tbl pll2_rate_tbl[] = { + CCU_PLL_RATE(3000000000UL, 0x0050dd66, 0x3fe00000), +}; + +static const struct ccu_pll_rate_tbl pll3_rate_tbl[] = { + CCU_PLL_RATE(1600000000UL, 0x0050cd61, 0x43eaaaab), + CCU_PLL_RATE(1800000000UL, 0x0050cd61, 0x4b000000), + CCU_PLL_RATE(2000000000UL, 0x0050dd62, 0x2aeaaaab), + CCU_PLL_RATE(2457600000UL, 0x0050dd64, 0x330ccccd), + CCU_PLL_RATE(3000000000UL, 0x0050dd66, 0x3fe00000), + CCU_PLL_RATE(3200000000UL, 0x0050dd67, 0x43eaaaab), +}; + +CCU_PLL_DEFINE(CLK_PLL1, pll1, pll1, "clock-24m", pll1_rate_tbl, + APBS_PLL1_SWCR1, APBS_PLL1_SWCR3, MPMU_POSR, POSR_PLL1_LOCK, + CLK_SET_RATE_GATE); +CCU_PLL_DEFINE(CLK_PLL2, pll2, pll2, "clock-24m", pll2_rate_tbl, + APBS_PLL2_SWCR1, APBS_PLL2_SWCR3, MPMU_POSR, POSR_PLL2_LOCK, + CLK_SET_RATE_GATE); +CCU_PLL_DEFINE(CLK_PLL3, pll3, pll3, "clock-24m", pll3_rate_tbl, + APBS_PLL3_SWCR1, APBS_PLL3_SWCR3, MPMU_POSR, POSR_PLL3_LOCK, + CLK_SET_RATE_GATE); + +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_D2, pll1_d2, pll1_d2, "pll1", APBS_PLL1_SWCR2, + BIT(1), 2, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_D3, pll1_d3, pll1_d3, "pll1", APBS_PLL1_SWCR2, + BIT(2), 3, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_D4, pll1_d4, pll1_d4, "pll1", APBS_PLL1_SWCR2, + BIT(3), 4, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_D5, pll1_d5, pll1_d5, "pll1", APBS_PLL1_SWCR2, + BIT(4), 5, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_D6, pll1_d6, pll1_d6, "pll1", APBS_PLL1_SWCR2, + BIT(5), 6, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_D7, pll1_d7, pll1_d7, "pll1", APBS_PLL1_SWCR2, + BIT(6), 7, 1); +CCU_FACTOR_GATE_FLAGS_DEFINE(CLK_PLL1_D8, pll1_d8, pll1_d8, "pll1", + APBS_PLL1_SWCR2, BIT(7), 8, 1, CLK_IS_CRITICAL); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_D11, pll1_d11_223p4, pll1_d11_223p4, "pll1", + APBS_PLL1_SWCR2, BIT(15), 11, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_D13, pll1_d13_189, pll1_d13_189, "pll1", + APBS_PLL1_SWCR2, BIT(16), 13, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_D23, pll1_d23_106p8, pll1_d23_106p8, "pll1", + APBS_PLL1_SWCR2, BIT(20), 23, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_D64, pll1_d64_38p4, pll1_d64_38p4, "pll1", + APBS_PLL1_SWCR2, BIT(0), 64, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_D10_AUD, pll1_aud_245p7, pll1_aud_245p7, "pll1", + APBS_PLL1_SWCR2, BIT(10), 10, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_D100_AUD, pll1_aud_24p5, pll1_aud_24p5, "pll1", + APBS_PLL1_SWCR2, BIT(11), 100, 1); + +CCU_FACTOR_GATE_DEFINE(CLK_PLL2_D1, pll2_d1, pll2_d1, "pll2", APBS_PLL2_SWCR2, + BIT(0), 1, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL2_D2, pll2_d2, pll2_d2, "pll2", APBS_PLL2_SWCR2, + BIT(1), 2, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL2_D3, pll2_d3, pll2_d3, "pll2", APBS_PLL2_SWCR2, + BIT(2), 3, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL2_D4, pll2_d4, pll2_d4, "pll2", APBS_PLL2_SWCR2, + BIT(3), 4, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL2_D5, pll2_d5, pll2_d5, "pll2", APBS_PLL2_SWCR2, + BIT(4), 5, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL2_D6, pll2_d6, pll2_d6, "pll2", APBS_PLL2_SWCR2, + BIT(5), 6, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL2_D7, pll2_d7, pll2_d7, "pll2", APBS_PLL2_SWCR2, + BIT(6), 7, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL2_D8, pll2_d8, pll2_d8, "pll2", APBS_PLL2_SWCR2, + BIT(7), 8, 1); + +CCU_FACTOR_GATE_DEFINE(CLK_PLL3_D1, pll3_d1, pll3_d1, "pll3", APBS_PLL3_SWCR2, + BIT(0), 1, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL3_D2, pll3_d2, pll3_d2, "pll3", APBS_PLL3_SWCR2, + BIT(1), 2, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL3_D3, pll3_d3, pll3_d3, "pll3", APBS_PLL3_SWCR2, + BIT(2), 3, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL3_D4, pll3_d4, pll3_d4, "pll3", APBS_PLL3_SWCR2, + BIT(3), 4, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL3_D5, pll3_d5, pll3_d5, "pll3", APBS_PLL3_SWCR2, + BIT(4), 5, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL3_D6, pll3_d6, pll3_d6, "pll3", APBS_PLL3_SWCR2, + BIT(5), 6, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL3_D7, pll3_d7, pll3_d7, "pll3", APBS_PLL3_SWCR2, + BIT(6), 7, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL3_D8, pll3_d8, pll3_d8, "pll3", APBS_PLL3_SWCR2, + BIT(7), 8, 1); + +CCU_FACTOR_DEFINE(CLK_PLL3_20, pll3_20, pll3_20, "pll3_d8", 20, 1); +CCU_FACTOR_DEFINE(CLK_PLL3_40, pll3_40, pll3_40, "pll3_d8", 10, 1); +CCU_FACTOR_DEFINE(CLK_PLL3_80, pll3_80, pll3_80, "pll3_d8", 5, 1); +#endif +/* APBS clocks end */ + +/* MPMU clocks start */ +#if IS_ENABLED(CONFIG_SPL_BUILD) +CCU_GATE_DEFINE(CLK_PLL1_614, pll1_d4_614p4, pll1_d4_614p4, "pll1_d4", + MPMU_ACGR, BIT(15), 0); +CCU_GATE_DEFINE(CLK_PLL1_409P6, pll1_d6_409p6, pll1_d6_409p6, "pll1_d6", + MPMU_ACGR, BIT(0), 0); +CCU_GATE_DEFINE(CLK_PLL1_307P2, pll1_d8_307p2, pll1_d8_307p2, "pll1_d8", + MPMU_ACGR, BIT(13), 0); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_31P5, pll1_d78_31p5, pll1_d78_31p5, + "pll1_d4", MPMU_ACGR, BIT(6), 39, 2); +CCU_DDN_DEFINE(CLK_SLOW_UART2, slow_uart2_48, slow_uart2_48, + "pll1_d4_614p4", MPMU_SUCCR_1, + CCU_DDN_MASK(16, 13), 16, CCU_DDN_MASK(0, 13), 0, 2, 0); +#else +CCU_GATE_DEFINE(CLK_PLL1_307P2, pll1_d8_307p2, pll1_d8_307p2, "pll1_d8", + MPMU_ACGR, BIT(13), 0); + +CCU_FACTOR_DEFINE(CLK_PLL1_76P8, pll1_d32_76p8, pll1_d32_76p8, "pll1_d8_307p2", + 4, 1); + +CCU_FACTOR_DEFINE(CLK_PLL1_61P44, pll1_d40_61p44, pll1_d40_61p44, + "pll1_d8_307p2", 5, 1); + +CCU_FACTOR_DEFINE(CLK_PLL1_153P6, pll1_d16_153p6, pll1_d16_153p6, + "pll1_d8", 2, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_102P4, pll1_d24_102p4, pll1_d24_102p4, + "pll1_d8", MPMU_ACGR, BIT(12), 3, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_51P2, pll1_d48_51p2, pll1_d48_51p2, + "pll1_d8", MPMU_ACGR, BIT(7), 6, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_51P2_AP, pll1_d48_51p2_ap, pll1_d48_51p2_ap, + "pll1_d8", MPMU_ACGR, BIT(11), 6, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_57P6, pll1_m3d128_57p6, pll1_m3d128_57p6, + "pll1_d8", MPMU_ACGR, BIT(8), 16, 3); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_25P6, pll1_d96_25p6, pll1_d96_25p6, + "pll1_d8", MPMU_ACGR, BIT(4), 12, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_12P8, pll1_d192_12p8, pll1_d192_12p8, + "pll1_d8", MPMU_ACGR, BIT(3), 24, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_12P8_WDT, pll1_d192_12p8_wdt, pll1_d192_12p8_wdt, + "pll1_d8", MPMU_ACGR, BIT(19), 24, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_6P4, pll1_d384_6p4, pll1_d384_6p4, + "pll1_d8", MPMU_ACGR, BIT(2), 48, 1); + +CCU_FACTOR_DEFINE(CLK_PLL1_3P2, pll1_d768_3p2, pll1_d768_3p2, + "pll1_d384_6p4", 2, 1); +CCU_FACTOR_DEFINE(CLK_PLL1_1P6, pll1_d1536_1p6, pll1_d1536_1p6, + "pll1_d384_6p4", 4, 1); +CCU_FACTOR_DEFINE(CLK_PLL1_0P8, pll1_d3072_0p8, pll1_d3072_0p8, + "pll1_d384_6p4", 8, 1); + +CCU_GATE_DEFINE(CLK_PLL1_409P6, pll1_d6_409p6, pll1_d6_409p6, "pll1_d6", + MPMU_ACGR, BIT(0), 0); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_204P8, pll1_d12_204p8, pll1_d12_204p8, + "pll1_d6", MPMU_ACGR, BIT(5), 2, 1); + +CCU_GATE_DEFINE(CLK_PLL1_491, pll1_d5_491p52, pll1_d5_491p52, "pll1_d5", + MPMU_ACGR, BIT(21), 0); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_245P76, pll1_d10_245p76, pll1_d10_245p76, + "pll1_d5", MPMU_ACGR, BIT(18), 2, 1); + +CCU_GATE_DEFINE(CLK_PLL1_614, pll1_d4_614p4, pll1_d4_614p4, "pll1_d4", + MPMU_ACGR, BIT(15), 0); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_47P26, pll1_d52_47p26, pll1_d52_47p26, + "pll1_d4", MPMU_ACGR, BIT(10), 13, 1); +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_31P5, pll1_d78_31p5, pll1_d78_31p5, + "pll1_d4", MPMU_ACGR, BIT(6), 39, 2); + +CCU_GATE_DEFINE(CLK_PLL1_819, pll1_d3_819p2, pll1_d3_819p2, "pll1_d3", + MPMU_ACGR, BIT(14), 0); + +CCU_GATE_DEFINE(CLK_PLL1_1228, pll1_d2_1228p8, pll1_d2_1228p8, "pll1_d2", + MPMU_ACGR, BIT(16), 0); + +CCU_GATE_DEFINE(CLK_SLOW_UART, slow_uart, slow_uart, "clock-32k", MPMU_ACGR, + BIT(1), CLK_IGNORE_UNUSED); +CCU_DDN_DEFINE(CLK_SLOW_UART1, slow_uart1_14p74, slow_uart1_14p74, + "pll1_d16_153p6", MPMU_SUCCR, + CCU_DDN_MASK(16, 13), 16, CCU_DDN_MASK(0, 13), 0, 2, 0); +CCU_DDN_DEFINE(CLK_SLOW_UART2, slow_uart2_48, slow_uart2_48, + "pll1_d4_614p4", MPMU_SUCCR_1, + CCU_DDN_MASK(16, 13), 16, CCU_DDN_MASK(0, 13), 0, 2, 0); + +CCU_GATE_DEFINE(CLK_WDT, wdt_clk, wdt_clk, "pll1_d96_25p6", MPMU_WDTPCR, + BIT(1), 0); + +CCU_FACTOR_DEFINE(CLK_I2S_153P6, i2s_153p6, i2s_153p6, "pll1_d8_307p2", 2, 1); + +static const char * const i2s_153p6_base_parents[] = { + "i2s_153p6", + "pll1_d8_307p2", +}; + +CCU_MUX_DEFINE(CLK_I2S_153P6_BASE, i2s_153p6_base, i2s_153p6_base, + i2s_153p6_base_parents, ARRAY_SIZE(i2s_153p6_base_parents), + MPMU_FCCR, 29, 1, 0); + +static const char * const i2s_sysclk_src_parents[] = { + "pll1_d96_25p6", + "i2s_153p6_base" +}; + +CCU_MUX_GATE_DEFINE(CLK_I2S_SYSCLK_SRC, i2s_sysclk_src, i2s_sysclk_src, + i2s_sysclk_src_parents, ARRAY_SIZE(i2s_sysclk_src_parents), + MPMU_ISCCR, 30, 1, BIT(31), 0); + +CCU_DDN_DEFINE(CLK_I2S_SYSCLK, i2s_sysclk, i2s_sysclk, "i2s_sysclk_src", + MPMU_ISCCR, CCU_DDN_MASK(0, 15), 0, CCU_DDN_MASK(15, 12), + 15, 1, 0); + +CCU_FACTOR_DEFINE(CLK_I2S_BCLK_FACTOR, i2s_bclk_factor, i2s_bclk_factor, + "i2s_sysclk", 2, 1); +/* + * Divider of i2s_bclk always implies a 1/2 factor, which is + * described by i2s_bclk_factor. + */ +CCU_DIV_GATE_DEFINE(CLK_I2S_BCLK, i2s_bclk, i2s_bclk, "i2s_bclk_factor", + MPMU_ISCCR, 27, 2, BIT(29), 0); + +static const char * const apb_parents[] = { + "pll1_d96_25p6", + "pll1_d48_51p2", + "pll1_d96_25p6", + "pll1_d24_102p4", +}; + +CCU_MUX_DEFINE(CLK_APB, apb_clk, apb_clk, apb_parents, ARRAY_SIZE(apb_parents), + MPMU_APBCSCR, 0, 2, 0); + +CCU_GATE_DEFINE(CLK_WDT_BUS, wdt_bus_clk, wdt_bus_clk, "apb_clk", MPMU_WDTPCR, + BIT(0), 0); + +CCU_GATE_DEFINE(CLK_RIPC, ripc_clk, ripc_clk, "apb_clk", MPMU_RIPCCR, 0x1, 0); +#endif +/* MPMU clocks end */ + +/* APBC clocks start */ +#if IS_ENABLED(CONFIG_SPL_BUILD) +static const char * const uart_clk_parents[] = { + "clock-dummy", + "clock-dummy", + "slow_uart2_48", +}; + +CCU_MUX_GATE_DEFINE(CLK_UART0, uart0_clk, uart0_clk, uart_clk_parents, + ARRAY_SIZE(uart_clk_parents), APBC_UART1_CLK_RST, + 4, 3, BIT(1) | BIT(0), 0); + +static const char * const twsi_parents[] = { + "pll1_d78_31p5", +}; + +CCU_MUX_GATE_DEFINE(CLK_TWSI2, twsi2_clk, twsi2_clk, twsi_parents, + ARRAY_SIZE(twsi_parents), APBC_TWSI2_CLK_RST, + 4, 3, BIT(1) | BIT(0), 0); +/* + * APBC_TWSI8_CLK_RST has a quirk that reading always results in zero. + * Combine functional and bus bits together as a gate to avoid sharing the + * write-only register between different clock hardwares. + */ +CCU_GATE_DEFINE(CLK_TWSI8, twsi8_clk, twsi8_clk, "pll1_d78_31p5", + APBC_TWSI8_CLK_RST, BIT(1) | BIT(0), 0); + +#else +static const char * const uart_clk_parents[] = { + "pll1_m3d128_57p6", + "slow_uart1_14p74", + "slow_uart2_48", +}; + +CCU_MUX_GATE_DEFINE(CLK_UART0, uart0_clk, uart0_clk, uart_clk_parents, + ARRAY_SIZE(uart_clk_parents), APBC_UART1_CLK_RST, + 4, 3, BIT(1) | BIT(0), 0); + +static const char * const twsi_parents[] = { + "pll1_d78_31p5", + "pll1_d48_51p2", + "pll1_d40_61p44", +}; + +CCU_MUX_GATE_DEFINE(CLK_TWSI2, twsi2_clk, twsi2_clk, twsi_parents, + ARRAY_SIZE(twsi_parents), APBC_TWSI2_CLK_RST, + 4, 3, BIT(1) | BIT(0), 0); +/* + * APBC_TWSI8_CLK_RST has a quirk that reading always results in zero. + * Combine functional and bus bits together as a gate to avoid sharing the + * write-only register between different clock hardwares. + */ +CCU_GATE_DEFINE(CLK_TWSI8, twsi8_clk, twsi8_clk, "pll1_d78_31p5", + APBC_TWSI8_CLK_RST, BIT(1) | BIT(0), 0); + +CCU_MUX_GATE_DEFINE(CLK_UART2, uart2_clk, uart2_clk, uart_clk_parents, + ARRAY_SIZE(uart_clk_parents), APBC_UART2_CLK_RST, + 4, 3, BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_UART3, uart3_clk, uart3_clk, uart_clk_parents, + ARRAY_SIZE(uart_clk_parents), APBC_UART3_CLK_RST, + 4, 3, BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_UART4, uart4_clk, uart4_clk, uart_clk_parents, + ARRAY_SIZE(uart_clk_parents), APBC_UART4_CLK_RST, + 4, 3, BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_UART5, uart5_clk, uart5_clk, uart_clk_parents, + ARRAY_SIZE(uart_clk_parents), APBC_UART5_CLK_RST, + 4, 3, BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_UART6, uart6_clk, uart6_clk, uart_clk_parents, + ARRAY_SIZE(uart_clk_parents), APBC_UART6_CLK_RST, + 4, 3, BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_UART7, uart7_clk, uart7_clk, uart_clk_parents, + ARRAY_SIZE(uart_clk_parents), APBC_UART7_CLK_RST, + 4, 3, BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_UART8, uart8_clk, uart8_clk, uart_clk_parents, + ARRAY_SIZE(uart_clk_parents), APBC_UART8_CLK_RST, + 4, 3, BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_UART9, uart9_clk, uart9_clk, uart_clk_parents, + ARRAY_SIZE(uart_clk_parents), APBC_UART9_CLK_RST, + 4, 3, BIT(1) | BIT(0), 0); + +CCU_GATE_DEFINE(CLK_GPIO, gpio_clk, gpio_clk, "clock-24m", APBC_GPIO_CLK_RST, + BIT(1) | BIT(0), 0); + +static const char * const pwm_parents[] = { + "pll1_d192_12p8", + "clock-32k", +}; + +CCU_MUX_GATE_DEFINE(CLK_PWM0, pwm0_clk, pwm0_clk, pwm_parents, + ARRAY_SIZE(pwm_parents), APBC_PWM0_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_PWM1, pwm1_clk, pwm1_clk, pwm_parents, + ARRAY_SIZE(pwm_parents), APBC_PWM1_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_PWM2, pwm2_clk, pwm2_clk, pwm_parents, + ARRAY_SIZE(pwm_parents), APBC_PWM2_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_PWM3, pwm3_clk, pwm3_clk, pwm_parents, + ARRAY_SIZE(pwm_parents), APBC_PWM3_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_PWM4, pwm4_clk, pwm4_clk, pwm_parents, + ARRAY_SIZE(pwm_parents), APBC_PWM4_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_PWM5, pwm5_clk, pwm5_clk, pwm_parents, + ARRAY_SIZE(pwm_parents), APBC_PWM5_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_PWM6, pwm6_clk, pwm6_clk, pwm_parents, + ARRAY_SIZE(pwm_parents), APBC_PWM6_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_PWM7, pwm7_clk, pwm7_clk, pwm_parents, + ARRAY_SIZE(pwm_parents), APBC_PWM7_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_PWM8, pwm8_clk, pwm8_clk, pwm_parents, + ARRAY_SIZE(pwm_parents), APBC_PWM8_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_PWM9, pwm9_clk, pwm9_clk, pwm_parents, + ARRAY_SIZE(pwm_parents), APBC_PWM9_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_PWM10, pwm10_clk, pwm10_clk, pwm_parents, + ARRAY_SIZE(pwm_parents), APBC_PWM10_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_PWM11, pwm11_clk, pwm11_clk, pwm_parents, + ARRAY_SIZE(pwm_parents), APBC_PWM11_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_PWM12, pwm12_clk, pwm12_clk, pwm_parents, + ARRAY_SIZE(pwm_parents), APBC_PWM12_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_PWM13, pwm13_clk, pwm13_clk, pwm_parents, + ARRAY_SIZE(pwm_parents), APBC_PWM13_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_PWM14, pwm14_clk, pwm14_clk, pwm_parents, + ARRAY_SIZE(pwm_parents), APBC_PWM14_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_PWM15, pwm15_clk, pwm15_clk, pwm_parents, + ARRAY_SIZE(pwm_parents), APBC_PWM15_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_PWM16, pwm16_clk, pwm16_clk, pwm_parents, + ARRAY_SIZE(pwm_parents), APBC_PWM16_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_PWM17, pwm17_clk, pwm17_clk, pwm_parents, + ARRAY_SIZE(pwm_parents), APBC_PWM17_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_PWM18, pwm18_clk, pwm18_clk, pwm_parents, + ARRAY_SIZE(pwm_parents), APBC_PWM18_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_PWM19, pwm19_clk, pwm19_clk, pwm_parents, + ARRAY_SIZE(pwm_parents), APBC_PWM19_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); + +static const char * const ssp_parents[] = { + "pll1_d384_6p4", + "pll1_d192_12p8", + "pll1_d96_25p6", + "pll1_d48_51p2", + "pll1_d768_3p2", + "pll1_d1536_1p6", + "pll1_d3072_0p8", +}; + +CCU_MUX_GATE_DEFINE(CLK_SSP3, ssp3_clk, ssp3_clk, ssp_parents, + ARRAY_SIZE(ssp_parents), APBC_SSP3_CLK_RST, 4, 3, + BIT(1), 0); + +CCU_GATE_DEFINE(CLK_RTC, rtc_clk, rtc_clk, "clock-32k", APBC_RTC_CLK_RST, + BIT(7) | BIT(1) | BIT(0), 0); + +CCU_MUX_GATE_DEFINE(CLK_TWSI0, twsi0_clk, twsi0_clk, twsi_parents, + ARRAY_SIZE(twsi_parents), APBC_TWSI0_CLK_RST, + 4, 3, BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_TWSI1, twsi1_clk, twsi1_clk, twsi_parents, + ARRAY_SIZE(twsi_parents), APBC_TWSI1_CLK_RST, + 4, 3, BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_TWSI4, twsi4_clk, twsi4_clk, twsi_parents, + ARRAY_SIZE(twsi_parents), APBC_TWSI4_CLK_RST, + 4, 3, BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_TWSI5, twsi5_clk, twsi5_clk, twsi_parents, + ARRAY_SIZE(twsi_parents), APBC_TWSI5_CLK_RST, + 4, 3, BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_TWSI6, twsi6_clk, twsi6_clk, twsi_parents, + ARRAY_SIZE(twsi_parents), APBC_TWSI6_CLK_RST, + 4, 3, BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_TWSI7, twsi7_clk, twsi7_clk, twsi_parents, + ARRAY_SIZE(twsi_parents), APBC_TWSI7_CLK_RST, + 4, 3, BIT(1) | BIT(0), 0); + +static const char * const timer_parents[] = { + "pll1_d192_12p8", + "clock-32k", + "pll1_d384_6p4", + "clock-3m", + "clock-1m", +}; + +CCU_MUX_GATE_DEFINE(CLK_TIMERS1, timers1_clk, timers1_clk, timer_parents, + ARRAY_SIZE(timer_parents), APBC_TIMERS1_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); +CCU_MUX_GATE_DEFINE(CLK_TIMERS2, timers2_clk, timers2_clk, timer_parents, + ARRAY_SIZE(timer_parents), APBC_TIMERS2_CLK_RST, 4, 3, + BIT(1) | BIT(0), 0); + +CCU_GATE_DEFINE(CLK_AIB, aib_clk, aib_clk, "clock-24m", APBC_AIB_CLK_RST, + BIT(1) | BIT(0), 0); + +CCU_GATE_DEFINE(CLK_ONEWIRE, onewire_clk, onewire_clk, "clock-24m", + APBC_ONEWIRE_CLK_RST, BIT(1) | BIT(0), 0); + +/* + * When i2s_bclk is selected as the parent clock of sspa, + * the hardware requires bit3 to be set + */ +CCU_GATE_DEFINE(CLK_SSPA0_I2S_BCLK, sspa0_i2s_bclk, sspa0_i2s_bclk, "i2s_bclk", + APBC_SSPA0_CLK_RST, BIT(3), 0); +CCU_GATE_DEFINE(CLK_SSPA1_I2S_BCLK, sspa1_i2s_bclk, sspa1_i2s_bclk, "i2s_bclk", + APBC_SSPA1_CLK_RST, BIT(3), 0); + +static const char * const sspa0_parents[] = { + "pll1_d384_6p4", + "pll1_d192_12p8", + "pll1_d96_25p6", + "pll1_d48_51p2", + "pll1_d768_3p2", + "pll1_d1536_1p6", + "pll1_d3072_0p8", + "sspa0_i2s_bclk", +}; + +CCU_MUX_GATE_DEFINE(CLK_SSPA0, sspa0_clk, sspa0_clk, sspa0_parents, + ARRAY_SIZE(sspa0_parents), APBC_SSPA0_CLK_RST, 4, 3, + BIT(1), 0); + +static const char * const sspa1_parents[] = { + "pll1_d384_6p4", + "pll1_d192_12p8", + "pll1_d96_25p6", + "pll1_d48_51p2", + "pll1_d768_3p2", + "pll1_d1536_1p6", + "pll1_d3072_0p8", + "sspa1_i2s_bclk", +}; + +CCU_MUX_GATE_DEFINE(CLK_SSPA1, sspa1_clk, sspa1_clk, sspa1_parents, + ARRAY_SIZE(sspa1_parents), APBC_SSPA1_CLK_RST, 4, 3, + BIT(1), 0); + +CCU_GATE_DEFINE(CLK_DRO, dro_clk, dro_clk, "apb_clk", APBC_DRO_CLK_RST, + BIT(1) | BIT(0), 0); +CCU_GATE_DEFINE(CLK_IR, ir_clk, ir_clk, "apb_clk", APBC_IR_CLK_RST, + BIT(1) | BIT(0), 0); +CCU_GATE_DEFINE(CLK_TSEN, tsen_clk, tsen_clk, "apb_clk", APBC_TSEN_CLK_RST, + BIT(1) | BIT(0), 0); +CCU_GATE_DEFINE(CLK_IPC_AP2AUD, ipc_ap2aud_clk, ipc_ap2aud_clk, "apb_clk", + APBC_IPC_AP2AUD_CLK_RST, BIT(1) | BIT(0), 0); + +static const char * const can_parents[] = { + "pll3_20", + "pll3_40", + "pll3_80", +}; + +CCU_MUX_GATE_DEFINE(CLK_CAN0, can0_clk, can0_clk, can_parents, + ARRAY_SIZE(can_parents), APBC_CAN0_CLK_RST, 4, 3, + BIT(1), 0); +CCU_GATE_DEFINE(CLK_CAN0_BUS, can0_bus_clk, can0_bus_clk, "clock-24m", + APBC_CAN0_CLK_RST, BIT(0), 0); + +CCU_GATE_DEFINE(CLK_UART0_BUS, uart0_bus_clk, uart0_bus_clk, "apb_clk", + APBC_UART1_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_UART2_BUS, uart2_bus_clk, uart2_bus_clk, "apb_clk", + APBC_UART2_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_UART3_BUS, uart3_bus_clk, uart3_bus_clk, "apb_clk", + APBC_UART3_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_UART4_BUS, uart4_bus_clk, uart4_bus_clk, "apb_clk", + APBC_UART4_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_UART5_BUS, uart5_bus_clk, uart5_bus_clk, "apb_clk", + APBC_UART5_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_UART6_BUS, uart6_bus_clk, uart6_bus_clk, "apb_clk", + APBC_UART6_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_UART7_BUS, uart7_bus_clk, uart7_bus_clk, "apb_clk", + APBC_UART7_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_UART8_BUS, uart8_bus_clk, uart8_bus_clk, "apb_clk", + APBC_UART8_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_UART9_BUS, uart9_bus_clk, uart9_bus_clk, "apb_clk", + APBC_UART9_CLK_RST, BIT(0), 0); + +CCU_GATE_DEFINE(CLK_GPIO_BUS, gpio_bus_clk, gpio_bus_clk, "apb_clk", + APBC_GPIO_CLK_RST, BIT(0), 0); + +CCU_GATE_DEFINE(CLK_PWM0_BUS, pwm0_bus_clk, pwm0_bus_clk, "apb_clk", + APBC_PWM0_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_PWM1_BUS, pwm1_bus_clk, pwm1_bus_clk, "apb_clk", + APBC_PWM1_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_PWM2_BUS, pwm2_bus_clk, pwm2_bus_clk, "apb_clk", + APBC_PWM2_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_PWM3_BUS, pwm3_bus_clk, pwm3_bus_clk, "apb_clk", + APBC_PWM3_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_PWM4_BUS, pwm4_bus_clk, pwm4_bus_clk, "apb_clk", + APBC_PWM4_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_PWM5_BUS, pwm5_bus_clk, pwm5_bus_clk, "apb_clk", + APBC_PWM5_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_PWM6_BUS, pwm6_bus_clk, pwm6_bus_clk, "apb_clk", + APBC_PWM6_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_PWM7_BUS, pwm7_bus_clk, pwm7_bus_clk, "apb_clk", + APBC_PWM7_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_PWM8_BUS, pwm8_bus_clk, pwm8_bus_clk, "apb_clk", + APBC_PWM8_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_PWM9_BUS, pwm9_bus_clk, pwm9_bus_clk, "apb_clk", + APBC_PWM9_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_PWM10_BUS, pwm10_bus_clk, pwm10_bus_clk, "apb_clk", + APBC_PWM10_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_PWM11_BUS, pwm11_bus_clk, pwm11_bus_clk, "apb_clk", + APBC_PWM11_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_PWM12_BUS, pwm12_bus_clk, pwm12_bus_clk, "apb_clk", + APBC_PWM12_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_PWM13_BUS, pwm13_bus_clk, pwm13_bus_clk, "apb_clk", + APBC_PWM13_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_PWM14_BUS, pwm14_bus_clk, pwm14_bus_clk, "apb_clk", + APBC_PWM14_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_PWM15_BUS, pwm15_bus_clk, pwm15_bus_clk, "apb_clk", + APBC_PWM15_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_PWM16_BUS, pwm16_bus_clk, pwm16_bus_clk, "apb_clk", + APBC_PWM16_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_PWM17_BUS, pwm17_bus_clk, pwm17_bus_clk, "apb_clk", + APBC_PWM17_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_PWM18_BUS, pwm18_bus_clk, pwm18_bus_clk, "apb_clk", + APBC_PWM18_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_PWM19_BUS, pwm19_bus_clk, pwm19_bus_clk, "apb_clk", + APBC_PWM19_CLK_RST, BIT(0), 0); + +CCU_GATE_DEFINE(CLK_SSP3_BUS, ssp3_bus_clk, ssp3_bus_clk, "apb_clk", + APBC_SSP3_CLK_RST, BIT(0), 0); + +CCU_GATE_DEFINE(CLK_RTC_BUS, rtc_bus_clk, rtc_bus_clk, "apb_clk", + APBC_RTC_CLK_RST, BIT(0), 0); + +CCU_GATE_DEFINE(CLK_TWSI0_BUS, twsi0_bus_clk, twsi0_bus_clk, "apb_clk", + APBC_TWSI0_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_TWSI1_BUS, twsi1_bus_clk, twsi1_bus_clk, "apb_clk", + APBC_TWSI1_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_TWSI2_BUS, twsi2_bus_clk, twsi2_bus_clk, "apb_clk", + APBC_TWSI2_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_TWSI4_BUS, twsi4_bus_clk, twsi4_bus_clk, "apb_clk", + APBC_TWSI4_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_TWSI5_BUS, twsi5_bus_clk, twsi5_bus_clk, "apb_clk", + APBC_TWSI5_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_TWSI6_BUS, twsi6_bus_clk, twsi6_bus_clk, "apb_clk", + APBC_TWSI6_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_TWSI7_BUS, twsi7_bus_clk, twsi7_bus_clk, "apb_clk", + APBC_TWSI7_CLK_RST, BIT(0), 0); +CCU_FACTOR_DEFINE(CLK_TWSI8_BUS, twsi8_bus_clk, twsi8_bus_clk, "apb_clk", 1, 1); + +CCU_GATE_DEFINE(CLK_TIMERS1_BUS, timers1_bus_clk, timers1_bus_clk, "apb_clk", + APBC_TIMERS1_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_TIMERS2_BUS, timers2_bus_clk, timers2_bus_clk, "apb_clk", + APBC_TIMERS2_CLK_RST, BIT(0), 0); + +CCU_GATE_DEFINE(CLK_AIB_BUS, aib_bus_clk, aib_bus_clk, "apb_clk", + APBC_AIB_CLK_RST, BIT(0), 0); + +CCU_GATE_DEFINE(CLK_ONEWIRE_BUS, onewire_bus_clk, onewire_bus_clk, "apb_clk", + APBC_ONEWIRE_CLK_RST, BIT(0), 0); + +CCU_GATE_DEFINE(CLK_SSPA0_BUS, sspa0_bus_clk, sspa0_bus_clk, "apb_clk", + APBC_SSPA0_CLK_RST, BIT(0), 0); +CCU_GATE_DEFINE(CLK_SSPA1_BUS, sspa1_bus_clk, sspa1_bus_clk, "apb_clk", + APBC_SSPA1_CLK_RST, BIT(0), 0); + +CCU_GATE_DEFINE(CLK_TSEN_BUS, tsen_bus_clk, tsen_bus_clk, "apb_clk", + APBC_TSEN_CLK_RST, BIT(0), 0); + +CCU_GATE_DEFINE(CLK_IPC_AP2AUD_BUS, ipc_ap2aud_bus_clk, ipc_ap2aud_bus_clk, + "apb_clk", APBC_IPC_AP2AUD_CLK_RST, BIT(0), 0); +#endif +/* APBC clocks end */ + +/* APMU clocks start */ +#if IS_ENABLED(CONFIG_SPL_BUILD) +static const char * const pmua_aclk_parents[] = { + "clock-dummy", + "pll1_d8_307p2", +}; + +CCU_MUX_DIV_FC_DEFINE(CLK_PMUA_ACLK, pmua_aclk, pmua_aclk, pmua_aclk_parents, + ARRAY_SIZE(pmua_aclk_parents), + APMU_ACLK_CLK_CTRL, APMU_ACLK_CLK_CTRL, 1, 2, BIT(4), + 0, 1, 0); + +CCU_GATE_DEFINE(CLK_SDH_AXI, sdh_axi_aclk, sdh_axi_aclk, "pmua_aclk", + APMU_SDH0_CLK_RES_CTRL, BIT(3), 0); + +static const char * const sdh01_parents[] = { + "pll1_d6_409p6", +}; + +CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_SDH0, sdh0_clk, sdh0_clk, sdh01_parents, + ARRAY_SIZE(sdh01_parents), + APMU_SDH0_CLK_RES_CTRL, + APMU_SDH0_CLK_RES_CTRL, 8, 3, BIT(11), 5, 3, + BIT(4), 0); + +static const char * const sdh2_parents[] = { + "pll1_d6_409p6", +}; + +CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_SDH2, sdh2_clk, sdh2_clk, sdh2_parents, + ARRAY_SIZE(sdh2_parents), + APMU_SDH2_CLK_RES_CTRL, + APMU_SDH2_CLK_RES_CTRL, 8, 3, BIT(11), 5, 3, + BIT(4), 0); +#else +static const char * const pmua_aclk_parents[] = { + "pll1_d10_245p76", + "pll1_d8_307p2", +}; + +CCU_MUX_DIV_FC_DEFINE(CLK_PMUA_ACLK, pmua_aclk, pmua_aclk, pmua_aclk_parents, + ARRAY_SIZE(pmua_aclk_parents), + APMU_ACLK_CLK_CTRL, APMU_ACLK_CLK_CTRL, 1, 2, BIT(4), + 0, 1, 0); + +static const char * const emmc_parents[] = { + "pll1_d6_409p6", + "pll1_d4_614p4", + "pll1_d52_47p26", + "pll1_d3_819p2", +}; + +CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_EMMC, emmc_clk, emmc_clk, emmc_parents, + ARRAY_SIZE(emmc_parents), + APMU_PMUA_EM_CLK_RES_CTRL, + APMU_PMUA_EM_CLK_RES_CTRL, 8, 3, BIT(11), + 6, 2, BIT(4), 0); +CCU_DIV_GATE_DEFINE(CLK_EMMC_X, emmc_x_clk, emmc_x_clk, "pll1_d2_1228p8", + APMU_PMUA_EM_CLK_RES_CTRL, 12, + 3, BIT(15), 0); + +CCU_GATE_DEFINE(CLK_EMMC_BUS, emmc_bus_clk, emmc_bus_clk, "pmua_aclk", + APMU_PMUA_EM_CLK_RES_CTRL, BIT(3), 0); + +static const char * const cci550_clk_parents[] = { + "pll1_d5_491p52", + "pll1_d4_614p4", + "pll1_d3_819p2", + "pll2_d3", +}; + +CCU_MUX_DIV_FC_DEFINE(CLK_CCI550, cci550_clk, cci550_clk, cci550_clk_parents, + ARRAY_SIZE(cci550_clk_parents), + APMU_CCI550_CLK_CTRL, APMU_CCI550_CLK_CTRL, 8, 3, + BIT(12), 0, 2, CLK_IS_CRITICAL); + +static const char * const cpu_c0_hi_clk_parents[] = { + "pll3_d2", + "pll3_d1", +}; + +CCU_MUX_DEFINE(CLK_CPU_C0_HI, cpu_c0_hi_clk, cpu_c0_hi_clk, + cpu_c0_hi_clk_parents, ARRAY_SIZE(cpu_c0_hi_clk_parents), + APMU_CPU_C0_CLK_CTRL, 13, 1, 0); +static const char * const cpu_c0_clk_parents[] = { + "pll1_d4_614p4", + "pll1_d3_819p2", + "pll1_d6_409p6", + "pll1_d5_491p52", + "pll1_d2_1228p8", + "pll3_d3", + "pll2_d3", + "cpu_c0_hi_clk", +}; + +CCU_MUX_FC_DEFINE(CLK_CPU_C0_CORE, cpu_c0_core_clk, cpu_c0_core_clk, + cpu_c0_clk_parents, ARRAY_SIZE(cpu_c0_clk_parents), + APMU_CPU_C0_CLK_CTRL, APMU_CPU_C0_CLK_CTRL, + BIT(12), 0, 3, CLK_IS_CRITICAL); +CCU_DIV_DEFINE(CLK_CPU_C0_ACE, cpu_c0_ace_clk, cpu_c0_ace_clk, + "cpu_c0_core_clk", APMU_CPU_C0_CLK_CTRL, 6, 3, CLK_IS_CRITICAL); +CCU_DIV_DEFINE(CLK_CPU_C0_TCM, cpu_c0_tcm_clk, cpu_c0_tcm_clk, + "cpu_c0_core_clk", APMU_CPU_C0_CLK_CTRL, 9, 3, CLK_IS_CRITICAL); + +static const char * const cpu_c1_hi_clk_parents[] = { + "pll3_d2", + "pll3_d1", +}; + +CCU_MUX_DEFINE(CLK_CPU_C1_HI, cpu_c1_hi_clk, cpu_c1_hi_clk, + cpu_c1_hi_clk_parents, ARRAY_SIZE(cpu_c1_hi_clk_parents), + APMU_CPU_C1_CLK_CTRL, 13, 1, 0); +static const char * const cpu_c1_clk_parents[] = { + "pll1_d4_614p4", + "pll1_d3_819p2", + "pll1_d6_409p6", + "pll1_d5_491p52", + "pll1_d2_1228p8", + "pll3_d3", + "pll2_d3", + "cpu_c1_hi_clk", +}; + +CCU_MUX_FC_DEFINE(CLK_CPU_C1_CORE, cpu_c1_core_clk, cpu_c1_core_clk, + cpu_c1_clk_parents, ARRAY_SIZE(cpu_c1_clk_parents), + APMU_CPU_C1_CLK_CTRL, APMU_CPU_C1_CLK_CTRL, + BIT(12), 0, 3, CLK_IS_CRITICAL); +CCU_DIV_DEFINE(CLK_CPU_C1_ACE, cpu_c1_ace_clk, cpu_c1_ace_clk, + "cpu_c1_core_clk", APMU_CPU_C1_CLK_CTRL, 6, 3, CLK_IS_CRITICAL); + +static const char * const jpg_parents[] = { + "pll1_d4_614p4", + "pll1_d6_409p6", + "pll1_d5_491p52", + "pll1_d3_819p2", + "pll1_d2_1228p8", + "pll2_d4", + "pll2_d3", +}; + +CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_JPG, jpg_clk, jpg_clk, jpg_parents, + ARRAY_SIZE(jpg_parents), + APMU_JPG_CLK_RES_CTRL, + APMU_JPG_CLK_RES_CTRL, + 5, 3, BIT(15), 2, 3, BIT(1), 0); + +static const char * const ccic2phy_parents[] = { + "pll1_d24_102p4", + "pll1_d48_51p2_ap", +}; + +CCU_MUX_GATE_DEFINE(CLK_CCIC2PHY, ccic2phy_clk, ccic2phy_clk, ccic2phy_parents, + ARRAY_SIZE(ccic2phy_parents), APMU_CSI_CCIC2_CLK_RES_CTRL, + 7, 1, BIT(5), 0); + +static const char * const ccic3phy_parents[] = { + "pll1_d24_102p4", + "pll1_d48_51p2_ap", +}; + +CCU_MUX_GATE_DEFINE(CLK_CCIC3PHY, ccic3phy_clk, ccic3phy_clk, ccic3phy_parents, + ARRAY_SIZE(ccic3phy_parents), APMU_CSI_CCIC2_CLK_RES_CTRL, + 31, 1, BIT(30), 0); + +static const char * const csi_parents[] = { + "pll1_d5_491p52", + "pll1_d6_409p6", + "pll1_d4_614p4", + "pll1_d3_819p2", + "pll2_d2", + "pll2_d3", + "pll2_d4", + "pll1_d2_1228p8", +}; + +CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_CSI, csi_clk, csi_clk, csi_parents, + ARRAY_SIZE(csi_parents), + APMU_CSI_CCIC2_CLK_RES_CTRL, + APMU_CSI_CCIC2_CLK_RES_CTRL, 20, 3, BIT(15), + 16, 3, BIT(4), 0); + +static const char * const camm_parents[] = { + "pll1_d8_307p2", + "pll2_d5", + "pll1_d6_409p6", + "clock-24m", +}; + +CCU_MUX_DIV_GATE_DEFINE(CLK_CAMM0, camm0_clk, camm0_clk, camm_parents, + ARRAY_SIZE(camm_parents), + APMU_CSI_CCIC2_CLK_RES_CTRL, 23, 4, 8, 2, + BIT(28), 0); +CCU_MUX_DIV_GATE_DEFINE(CLK_CAMM1, camm1_clk, camm1_clk, camm_parents, + ARRAY_SIZE(camm_parents), + APMU_CSI_CCIC2_CLK_RES_CTRL, 23, 4, 8, 2, + BIT(6), 0); +CCU_MUX_DIV_GATE_DEFINE(CLK_CAMM2, camm2_clk, camm2_clk, camm_parents, + ARRAY_SIZE(camm_parents), + APMU_CSI_CCIC2_CLK_RES_CTRL, 23, 4, 8, 2, + BIT(3), 0); + +static const char * const isp_cpp_parents[] = { + "pll1_d8_307p2", + "pll1_d6_409p6", +}; + +CCU_MUX_DIV_GATE_DEFINE(CLK_ISP_CPP, isp_cpp_clk, isp_cpp_clk, isp_cpp_parents, + ARRAY_SIZE(isp_cpp_parents), + APMU_ISP_CLK_RES_CTRL, 24, 2, 26, 1, + BIT(28), 0); +static const char * const isp_bus_parents[] = { + "pll1_d6_409p6", + "pll1_d5_491p52", + "pll1_d8_307p2", + "pll1_d10_245p76", +}; + +CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_ISP_BUS, isp_bus_clk, isp_bus_clk, + isp_bus_parents, ARRAY_SIZE(isp_cpp_parents), + APMU_ISP_CLK_RES_CTRL, + APMU_ISP_CLK_RES_CTRL, 18, 3, BIT(23), + 21, 2, BIT(17), 0); +static const char * const isp_parents[] = { + "pll1_d6_409p6", + "pll1_d5_491p52", + "pll1_d4_614p4", + "pll1_d8_307p2", +}; + +CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_ISP, isp_clk, isp_clk, isp_parents, + ARRAY_SIZE(isp_parents), + APMU_ISP_CLK_RES_CTRL, + APMU_ISP_CLK_RES_CTRL, + 4, 3, BIT(7), 8, 2, BIT(1), 0); + +static const char * const dpumclk_parents[] = { + "pll1_d6_409p6", + "pll1_d5_491p52", + "pll1_d4_614p4", + "pll1_d8_307p2", +}; + +CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_DPU_MCLK, dpu_mclk, dpu_mclk, + dpumclk_parents, ARRAY_SIZE(dpumclk_parents), + APMU_LCD_CLK_RES_CTRL2, APMU_LCD_CLK_RES_CTRL1, + 1, 4, BIT(29), 5, 3, BIT(0), 0); + +static const char * const dpuesc_parents[] = { + "pll1_d48_51p2_ap", + "pll1_d52_47p26", + "pll1_d96_25p6", + "pll1_d32_76p8", +}; + +CCU_MUX_GATE_DEFINE(CLK_DPU_ESC, dpu_esc_clk, dpu_esc_clk, dpuesc_parents, + ARRAY_SIZE(dpuesc_parents), APMU_LCD_CLK_RES_CTRL1, 0, 2, + BIT(2), 0); + +static const char * const dpubit_parents[] = { + "pll1_d3_819p2", + "pll2_d2", + "pll2_d3", + "pll1_d2_1228p8", + "pll2_d4", + "pll2_d5", + "pll2_d7", + "pll2_d8", +}; + +CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_DPU_BIT, dpu_bit_clk, dpu_bit_clk, + dpubit_parents, ARRAY_SIZE(dpubit_parents), + APMU_LCD_CLK_RES_CTRL1, + APMU_LCD_CLK_RES_CTRL1, 17, 3, BIT(31), + 20, 3, BIT(16), 0); + +static const char * const dpupx_parents[] = { + "pll1_d6_409p6", + "pll1_d5_491p52", + "pll1_d4_614p4", + "pll1_d8_307p2", + "pll2_d7", + "pll2_d8", +}; + +CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_DPU_PXCLK, dpu_pxclk, dpu_pxclk, + dpupx_parents, ARRAY_SIZE(dpupx_parents), + APMU_LCD_CLK_RES_CTRL2, APMU_LCD_CLK_RES_CTRL1, + 17, 4, BIT(30), 21, 3, BIT(16), 0); + +CCU_GATE_DEFINE(CLK_DPU_HCLK, dpu_hclk, dpu_hclk, "pmua_aclk", + APMU_LCD_CLK_RES_CTRL1, BIT(5), 0); + +static const char * const dpu_spi_parents[] = { + "pll1_d8_307p2", + "pll1_d6_409p6", + "pll1_d10_245p76", + "pll1_d11_223p4", + "pll1_d13_189", + "pll1_d23_106p8", + "pll2_d3", + "pll2_d5", +}; + +CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_DPU_SPI, dpu_spi_clk, dpu_spi_clk, + dpu_spi_parents, ARRAY_SIZE(dpu_spi_parents), + APMU_LCD_SPI_CLK_RES_CTRL, + APMU_LCD_SPI_CLK_RES_CTRL, 8, 3, + BIT(7), 12, 3, BIT(1), 0); +CCU_GATE_DEFINE(CLK_DPU_SPI_HBUS, dpu_spi_hbus_clk, dpu_spi_hbus_clk, + "pmua_aclk", APMU_LCD_SPI_CLK_RES_CTRL, BIT(3), 0); +CCU_GATE_DEFINE(CLK_DPU_SPIBUS, dpu_spi_bus_clk, dpu_spi_bus_clk, + "pmua_aclk", APMU_LCD_SPI_CLK_RES_CTRL, BIT(5), 0); +CCU_GATE_DEFINE(CLK_DPU_SPI_ACLK, dpu_spi_aclk, dpu_spi_aclk, + "pmua_aclk", APMU_LCD_SPI_CLK_RES_CTRL, BIT(6), 0); + +static const char * const v2d_parents[] = { + "pll1_d5_491p52", + "pll1_d6_409p6", + "pll1_d8_307p2", + "pll1_d4_614p4", +}; + +CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_V2D, v2d_clk, v2d_clk, v2d_parents, + ARRAY_SIZE(v2d_parents), + APMU_LCD_CLK_RES_CTRL1, + APMU_LCD_CLK_RES_CTRL1, 9, 3, BIT(28), 12, 2, + BIT(8), 0); + +static const char * const ccic_4x_parents[] = { + "pll1_d5_491p52", + "pll1_d6_409p6", + "pll1_d4_614p4", + "pll1_d3_819p2", + "pll2_d2", + "pll2_d3", + "pll2_d4", + "pll1_d2_1228p8", +}; + +CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_CCIC_4X, ccic_4x_clk, ccic_4x_clk, + ccic_4x_parents, ARRAY_SIZE(ccic_4x_parents), + APMU_CCIC_CLK_RES_CTRL, + APMU_CCIC_CLK_RES_CTRL, 18, 3, + BIT(15), 23, 2, BIT(4), 0); + +static const char * const ccic1phy_parents[] = { + "pll1_d24_102p4", + "pll1_d48_51p2_ap", +}; + +CCU_MUX_GATE_DEFINE(CLK_CCIC1PHY, ccic1phy_clk, ccic1phy_clk, ccic1phy_parents, + ARRAY_SIZE(ccic1phy_parents), APMU_CCIC_CLK_RES_CTRL, 7, 1, + BIT(5), 0); + +CCU_GATE_DEFINE(CLK_SDH_AXI, sdh_axi_aclk, sdh_axi_aclk, "pmua_aclk", + APMU_SDH0_CLK_RES_CTRL, BIT(3), 0); +static const char * const sdh01_parents[] = { + "pll1_d6_409p6", + "pll1_d4_614p4", + "pll2_d8", + "pll2_d5", + "pll1_d11_223p4", + "pll1_d13_189", + "pll1_d23_106p8", +}; + +CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_SDH0, sdh0_clk, sdh0_clk, sdh01_parents, + ARRAY_SIZE(sdh01_parents), + APMU_SDH0_CLK_RES_CTRL, + APMU_SDH0_CLK_RES_CTRL, 8, 3, BIT(11), 5, 3, + BIT(4), 0); +CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_SDH1, sdh1_clk, sdh1_clk, sdh01_parents, + ARRAY_SIZE(sdh01_parents), + APMU_SDH1_CLK_RES_CTRL, + APMU_SDH1_CLK_RES_CTRL, 8, 3, BIT(11), 5, 3, + BIT(4), 0); +static const char * const sdh2_parents[] = { + "pll1_d6_409p6", + "pll1_d4_614p4", + "pll2_d8", + "pll1_d3_819p2", + "pll1_d11_223p4", + "pll1_d13_189", + "pll1_d23_106p8", +}; + +CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_SDH2, sdh2_clk, sdh2_clk, sdh2_parents, + ARRAY_SIZE(sdh2_parents), + APMU_SDH2_CLK_RES_CTRL, + APMU_SDH2_CLK_RES_CTRL, 8, 3, BIT(11), 5, 3, + BIT(4), 0); + +CCU_GATE_DEFINE(CLK_USB_AXI, usb_axi_clk, usb_axi_clk, "pmua_aclk", + APMU_USB_CLK_RES_CTRL, BIT(1), 0); +CCU_GATE_DEFINE(CLK_USB_P1, usb_p1_aclk, usb_p1_aclk, "pmua_aclk", + APMU_USB_CLK_RES_CTRL, BIT(5), 0); +CCU_GATE_DEFINE(CLK_USB30, usb30_clk, usb30_clk, "pmua_aclk", + APMU_USB_CLK_RES_CTRL, BIT(8), 0); + +static const char * const qspi_parents[] = { + "pll1_d6_409p6", + "pll2_d8", + "pll1_d8_307p2", + "pll1_d10_245p76", + "pll1_d11_223p4", + "pll1_d23_106p8", + "pll1_d5_491p52", + "pll1_d13_189", +}; + +CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_QSPI, qspi_clk, qspi_clk, qspi_parents, + ARRAY_SIZE(qspi_parents), + APMU_QSPI_CLK_RES_CTRL, + APMU_QSPI_CLK_RES_CTRL, 9, 3, BIT(12), 6, 3, + BIT(4), 0); +CCU_GATE_DEFINE(CLK_QSPI_BUS, qspi_bus_clk, qspi_bus_clk, "pmua_aclk", + APMU_QSPI_CLK_RES_CTRL, BIT(3), 0); +CCU_GATE_DEFINE(CLK_DMA, dma_clk, dma_clk, "pmua_aclk", APMU_DMA_CLK_RES_CTRL, + BIT(3), 0); + +static const char * const aes_parents[] = { + "pll1_d12_204p8", + "pll1_d24_102p4", +}; + +CCU_MUX_GATE_DEFINE(CLK_AES, aes_clk, aes_clk, aes_parents, + ARRAY_SIZE(aes_parents), APMU_AES_CLK_RES_CTRL, 6, 1, + BIT(5), 0); + +static const char * const vpu_parents[] = { + "pll1_d4_614p4", + "pll1_d5_491p52", + "pll1_d3_819p2", + "pll1_d6_409p6", + "pll3_d6", + "pll2_d3", + "pll2_d4", + "pll2_d5", +}; + +CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_VPU, vpu_clk, vpu_clk, vpu_parents, + ARRAY_SIZE(vpu_parents), APMU_VPU_CLK_RES_CTRL, + APMU_VPU_CLK_RES_CTRL, 13, 3, BIT(21), 10, 3, + BIT(3), 0); + +static const char * const gpu_parents[] = { + "pll1_d4_614p4", + "pll1_d5_491p52", + "pll1_d3_819p2", + "pll1_d6_409p6", + "pll3_d6", + "pll2_d3", + "pll2_d4", + "pll2_d5", +}; + +CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_GPU, gpu_clk, gpu_clk, gpu_parents, + ARRAY_SIZE(gpu_parents), APMU_GPU_CLK_RES_CTRL, + APMU_GPU_CLK_RES_CTRL, 12, 3, BIT(15), 18, 3, + BIT(4), 0); + +static const char * const audio_parents[] = { + "pll1_aud_245p7", + "pll1_d8_307p2", + "pll1_d6_409p6", +}; + +CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_AUDIO, audio_clk, audio_clk, audio_parents, + ARRAY_SIZE(audio_parents), + APMU_AUDIO_CLK_RES_CTRL, + APMU_AUDIO_CLK_RES_CTRL, 4, 3, BIT(15), + 7, 3, BIT(12), 0); + +static const char * const hdmi_parents[] = { + "pll1_d6_409p6", + "pll1_d5_491p52", + "pll1_d4_614p4", + "pll1_d8_307p2", +}; + +CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_HDMI, hdmi_mclk, hdmi_mclk, hdmi_parents, + ARRAY_SIZE(hdmi_parents), + APMU_HDMI_CLK_RES_CTRL, + APMU_HDMI_CLK_RES_CTRL, 1, 4, BIT(29), 5, + 3, BIT(0), 0); + +CCU_GATE_DEFINE(CLK_PCIE0_MASTER, pcie0_master_clk, pcie0_master_clk, + "pmua_aclk", APMU_PCIE_CLK_RES_CTRL_0, BIT(2), 0); +CCU_GATE_DEFINE(CLK_PCIE0_SLAVE, pcie0_slave_clk, pcie0_slave_clk, "pmua_aclk", + APMU_PCIE_CLK_RES_CTRL_0, BIT(1), 0); +CCU_GATE_DEFINE(CLK_PCIE0_DBI, pcie0_dbi_clk, pcie0_dbi_clk, "pmua_aclk", + APMU_PCIE_CLK_RES_CTRL_0, BIT(0), 0); + +CCU_GATE_DEFINE(CLK_PCIE1_MASTER, pcie1_master_clk, pcie1_master_clk, + "pmua_aclk", APMU_PCIE_CLK_RES_CTRL_1, BIT(2), 0); +CCU_GATE_DEFINE(CLK_PCIE1_SLAVE, pcie1_slave_clk, pcie1_slave_clk, "pmua_aclk", + APMU_PCIE_CLK_RES_CTRL_1, BIT(1), 0); +CCU_GATE_DEFINE(CLK_PCIE1_DBI, pcie1_dbi_clk, pcie1_dbi_clk, "pmua_aclk", + APMU_PCIE_CLK_RES_CTRL_1, BIT(0), 0); + +CCU_GATE_DEFINE(CLK_PCIE2_MASTER, pcie2_master_clk, pcie2_master_clk, + "pmua_aclk", APMU_PCIE_CLK_RES_CTRL_2, BIT(2), 0); +CCU_GATE_DEFINE(CLK_PCIE2_SLAVE, pcie2_slave_clk, pcie2_slave_clk, "pmua_aclk", + APMU_PCIE_CLK_RES_CTRL_2, BIT(1), 0); +CCU_GATE_DEFINE(CLK_PCIE2_DBI, pcie2_dbi_clk, pcie2_dbi_clk, "pmua_aclk", + APMU_PCIE_CLK_RES_CTRL_2, BIT(0), 0); + +CCU_GATE_DEFINE(CLK_EMAC0_BUS, emac0_bus_clk, emac0_bus_clk, "pmua_aclk", + APMU_EMAC0_CLK_RES_CTRL, BIT(0), 0); +CCU_GATE_DEFINE(CLK_EMAC0_PTP, emac0_ptp_clk, emac0_ptp_clk, "pll2_d6", + APMU_EMAC0_CLK_RES_CTRL, BIT(15), 0); +CCU_GATE_DEFINE(CLK_EMAC1_BUS, emac1_bus_clk, emac1_bus_clk, "pmua_aclk", + APMU_EMAC1_CLK_RES_CTRL, BIT(0), 0); +CCU_GATE_DEFINE(CLK_EMAC1_PTP, emac1_ptp_clk, emac1_ptp_clk, "pll2_d6", + APMU_EMAC1_CLK_RES_CTRL, BIT(15), 0); + +#endif +/* APMU clocks end */ + +#if IS_ENABLED(CONFIG_SPL_BUILD) +static struct clk *k1_ccu_pll_clks[] = { + &pll1.common.clk, + &pll1_d4.common.clk, + &pll1_d6.common.clk, + &pll1_d8.common.clk, +}; +#else +static struct clk *k1_ccu_pll_clks[] = { + &pll1.common.clk, + &pll2.common.clk, + &pll3.common.clk, + &pll1_d2.common.clk, + &pll1_d3.common.clk, + &pll1_d4.common.clk, + &pll1_d5.common.clk, + &pll1_d6.common.clk, + &pll1_d7.common.clk, + &pll1_d8.common.clk, + &pll1_d11_223p4.common.clk, + &pll1_d13_189.common.clk, + &pll1_d23_106p8.common.clk, + &pll1_d64_38p4.common.clk, + &pll1_aud_245p7.common.clk, + &pll1_aud_24p5.common.clk, + &pll2_d1.common.clk, + &pll2_d2.common.clk, + &pll2_d3.common.clk, + &pll2_d4.common.clk, + &pll2_d5.common.clk, + &pll2_d6.common.clk, + &pll2_d7.common.clk, + &pll2_d8.common.clk, + &pll3_d1.common.clk, + &pll3_d2.common.clk, + &pll3_d3.common.clk, + &pll3_d4.common.clk, + &pll3_d5.common.clk, + &pll3_d6.common.clk, + &pll3_d7.common.clk, + &pll3_d8.common.clk, + &pll3_80.common.clk, + &pll3_40.common.clk, + &pll3_20.common.clk, +}; +#endif + +static const struct spacemit_ccu_data k1_ccu_pll_data = { + .clks = k1_ccu_pll_clks, + .num = ARRAY_SIZE(k1_ccu_pll_clks), + .offset = K1_PLL_ID, +}; + +#if IS_ENABLED(CONFIG_SPL_BUILD) +static struct clk *k1_ccu_mpmu_clks[] = { + &pll1_d4_614p4.common.clk, + &pll1_d6_409p6.common.clk, + &pll1_d8_307p2.common.clk, + &pll1_d78_31p5.common.clk, + &slow_uart2_48.common.clk, +}; +#else +static struct clk *k1_ccu_mpmu_clks[] = { + &pll1_d8_307p2.common.clk, + &pll1_d32_76p8.common.clk, + &pll1_d40_61p44.common.clk, + &pll1_d16_153p6.common.clk, + &pll1_d24_102p4.common.clk, + &pll1_d48_51p2.common.clk, + &pll1_d48_51p2_ap.common.clk, + &pll1_m3d128_57p6.common.clk, + &pll1_d96_25p6.common.clk, + &pll1_d192_12p8.common.clk, + &pll1_d192_12p8_wdt.common.clk, + &pll1_d384_6p4.common.clk, + &pll1_d768_3p2.common.clk, + &pll1_d1536_1p6.common.clk, + &pll1_d3072_0p8.common.clk, + &pll1_d6_409p6.common.clk, + &pll1_d12_204p8.common.clk, + &pll1_d5_491p52.common.clk, + &pll1_d10_245p76.common.clk, + &pll1_d4_614p4.common.clk, + &pll1_d52_47p26.common.clk, + &pll1_d78_31p5.common.clk, + &pll1_d3_819p2.common.clk, + &pll1_d2_1228p8.common.clk, + &slow_uart.common.clk, + &slow_uart1_14p74.common.clk, + &slow_uart2_48.common.clk, + &wdt_clk.common.clk, + &apb_clk.common.clk, + &ripc_clk.common.clk, + &i2s_153p6.common.clk, + &i2s_153p6_base.common.clk, + &i2s_sysclk_src.common.clk, + &i2s_sysclk.common.clk, + &i2s_bclk_factor.common.clk, + &i2s_bclk.common.clk, + &wdt_bus_clk.common.clk, +}; +#endif + +static const struct spacemit_ccu_data k1_ccu_mpmu_data = { + .clks = k1_ccu_mpmu_clks, + .num = ARRAY_SIZE(k1_ccu_mpmu_clks), + .offset = K1_MPMU_ID, +}; + +#if IS_ENABLED(CONFIG_SPL_BUILD) +static struct clk *k1_ccu_apbc_clks[] = { + &uart0_clk.common.clk, + &twsi2_clk.common.clk, + &twsi8_clk.common.clk, +}; +#else +static struct clk *k1_ccu_apbc_clks[] = { + &uart0_clk.common.clk, + &uart2_clk.common.clk, + &uart3_clk.common.clk, + &uart4_clk.common.clk, + &uart5_clk.common.clk, + &uart6_clk.common.clk, + &uart7_clk.common.clk, + &uart8_clk.common.clk, + &uart9_clk.common.clk, + &gpio_clk.common.clk, + &pwm0_clk.common.clk, + &pwm1_clk.common.clk, + &pwm2_clk.common.clk, + &pwm3_clk.common.clk, + &pwm4_clk.common.clk, + &pwm5_clk.common.clk, + &pwm6_clk.common.clk, + &pwm7_clk.common.clk, + &pwm8_clk.common.clk, + &pwm9_clk.common.clk, + &pwm10_clk.common.clk, + &pwm11_clk.common.clk, + &pwm12_clk.common.clk, + &pwm13_clk.common.clk, + &pwm14_clk.common.clk, + &pwm15_clk.common.clk, + &pwm16_clk.common.clk, + &pwm17_clk.common.clk, + &pwm18_clk.common.clk, + &pwm19_clk.common.clk, + &ssp3_clk.common.clk, + &rtc_clk.common.clk, + &twsi0_clk.common.clk, + &twsi1_clk.common.clk, + &twsi2_clk.common.clk, + &twsi4_clk.common.clk, + &twsi5_clk.common.clk, + &twsi6_clk.common.clk, + &twsi7_clk.common.clk, + &twsi8_clk.common.clk, + &timers1_clk.common.clk, + &timers2_clk.common.clk, + &aib_clk.common.clk, + &onewire_clk.common.clk, + &sspa0_clk.common.clk, + &sspa1_clk.common.clk, + &dro_clk.common.clk, + &ir_clk.common.clk, + &tsen_clk.common.clk, + &ipc_ap2aud_clk.common.clk, + &can0_clk.common.clk, + &can0_bus_clk.common.clk, + &uart0_bus_clk.common.clk, + &uart2_bus_clk.common.clk, + &uart3_bus_clk.common.clk, + &uart4_bus_clk.common.clk, + &uart5_bus_clk.common.clk, + &uart6_bus_clk.common.clk, + &uart7_bus_clk.common.clk, + &uart8_bus_clk.common.clk, + &uart9_bus_clk.common.clk, + &gpio_bus_clk.common.clk, + &pwm0_bus_clk.common.clk, + &pwm1_bus_clk.common.clk, + &pwm2_bus_clk.common.clk, + &pwm3_bus_clk.common.clk, + &pwm4_bus_clk.common.clk, + &pwm5_bus_clk.common.clk, + &pwm6_bus_clk.common.clk, + &pwm7_bus_clk.common.clk, + &pwm8_bus_clk.common.clk, + &pwm9_bus_clk.common.clk, + &pwm10_bus_clk.common.clk, + &pwm11_bus_clk.common.clk, + &pwm12_bus_clk.common.clk, + &pwm13_bus_clk.common.clk, + &pwm14_bus_clk.common.clk, + &pwm15_bus_clk.common.clk, + &pwm16_bus_clk.common.clk, + &pwm17_bus_clk.common.clk, + &pwm18_bus_clk.common.clk, + &pwm19_bus_clk.common.clk, + &ssp3_bus_clk.common.clk, + &rtc_bus_clk.common.clk, + &twsi0_bus_clk.common.clk, + &twsi1_bus_clk.common.clk, + &twsi2_bus_clk.common.clk, + &twsi4_bus_clk.common.clk, + &twsi5_bus_clk.common.clk, + &twsi6_bus_clk.common.clk, + &twsi7_bus_clk.common.clk, + &twsi8_bus_clk.common.clk, + &timers1_bus_clk.common.clk, + &timers2_bus_clk.common.clk, + &aib_bus_clk.common.clk, + &onewire_bus_clk.common.clk, + &sspa0_bus_clk.common.clk, + &sspa1_bus_clk.common.clk, + &tsen_bus_clk.common.clk, + &ipc_ap2aud_bus_clk.common.clk, + &sspa0_i2s_bclk.common.clk, + &sspa1_i2s_bclk.common.clk, +}; +#endif + +static const struct spacemit_ccu_data k1_ccu_apbc_data = { + .clks = k1_ccu_apbc_clks, + .num = ARRAY_SIZE(k1_ccu_apbc_clks), + .offset = K1_APBC_ID, +}; + +#if IS_ENABLED(CONFIG_SPL_BUILD) +static struct clk *k1_ccu_apmu_clks[] = { + &pmua_aclk.common.clk, + &sdh_axi_aclk.common.clk, + &sdh0_clk.common.clk, + &sdh2_clk.common.clk, +}; +#else +static struct clk *k1_ccu_apmu_clks[] = { + &cci550_clk.common.clk, + &cpu_c0_hi_clk.common.clk, + &cpu_c0_core_clk.common.clk, + &cpu_c0_ace_clk.common.clk, + &cpu_c0_tcm_clk.common.clk, + &cpu_c1_hi_clk.common.clk, + &cpu_c1_core_clk.common.clk, + &cpu_c1_ace_clk.common.clk, + &ccic_4x_clk.common.clk, + &ccic1phy_clk.common.clk, + &pmua_aclk.common.clk, + &sdh_axi_aclk.common.clk, + &sdh0_clk.common.clk, + &sdh1_clk.common.clk, + &sdh2_clk.common.clk, + &usb_p1_aclk.common.clk, + &usb_axi_clk.common.clk, + &usb30_clk.common.clk, + &qspi_clk.common.clk, + &qspi_bus_clk.common.clk, + &dma_clk.common.clk, + &aes_clk.common.clk, + &vpu_clk.common.clk, + &gpu_clk.common.clk, + &emmc_clk.common.clk, + &emmc_x_clk.common.clk, + &audio_clk.common.clk, + &hdmi_mclk.common.clk, + &pcie0_master_clk.common.clk, + &pcie0_slave_clk.common.clk, + &pcie0_dbi_clk.common.clk, + &pcie1_master_clk.common.clk, + &pcie1_slave_clk.common.clk, + &pcie1_dbi_clk.common.clk, + &pcie2_master_clk.common.clk, + &pcie2_slave_clk.common.clk, + &pcie2_dbi_clk.common.clk, + &emac0_bus_clk.common.clk, + &emac0_ptp_clk.common.clk, + &emac1_bus_clk.common.clk, + &emac1_ptp_clk.common.clk, + &jpg_clk.common.clk, + &ccic2phy_clk.common.clk, + &ccic3phy_clk.common.clk, + &csi_clk.common.clk, + &camm0_clk.common.clk, + &camm1_clk.common.clk, + &camm2_clk.common.clk, + &isp_cpp_clk.common.clk, + &isp_bus_clk.common.clk, + &isp_clk.common.clk, + &dpu_mclk.common.clk, + &dpu_esc_clk.common.clk, + &dpu_bit_clk.common.clk, + &dpu_pxclk.common.clk, + &dpu_hclk.common.clk, + &dpu_spi_clk.common.clk, + &dpu_spi_hbus_clk.common.clk, + &dpu_spi_bus_clk.common.clk, + &dpu_spi_aclk.common.clk, + &v2d_clk.common.clk, + &emmc_bus_clk.common.clk, +}; +#endif + +static int clk_k1_enable(struct clk *clk) +{ + const struct spacemit_ccu_data *data; + struct clk *c; + struct clk *pclk; + int ret, i; + + data = (struct spacemit_ccu_data *)dev_get_driver_data(clk->dev); + for (i = 0; i < data->num; i++) { + if (clk->id == data->clks[i]->id) { + c = data->clks[i]; + break; + } + } + if (i == data->num) + c = clk; + + pclk = clk_get_parent(c); + if (!IS_ERR_OR_NULL(pclk)) { + ret = ccf_clk_enable(pclk); + if (ret) + return ret; + } + ret = ccu_gate_enable(c); + return ret; +} + +static int clk_k1_disable(struct clk *clk) +{ + const struct spacemit_ccu_data *data; + struct clk *c; + struct clk *pclk; + int ret, i; + + data = (struct spacemit_ccu_data *)dev_get_driver_data(clk->dev); + for (i = 0; i < data->num; i++) { + if (clk->id == data->clks[i]->id) { + c = data->clks[i]; + break; + } + } + if (i == data->num) + c = clk; + + pclk = clk_get_parent(c); + if (!IS_ERR_OR_NULL(pclk)) { + ret = ccf_clk_disable(pclk); + if (ret) + return ret; + } + ret = ccu_gate_disable(c); + return ret; +} + +#define K1_CLK_OPS(name) \ +static const struct clk_ops k1_##name##_clk_ops = { \ + .set_rate = ccf_clk_set_rate, \ + .get_rate = ccf_clk_get_rate, \ + .enable = clk_k1_enable, \ + .disable = clk_k1_disable, \ + .set_parent = ccf_clk_set_parent, \ + .of_xlate = k1_##name##_clk_of_xlate, \ +} + +static const struct spacemit_ccu_data k1_ccu_apmu_data = { + .clks = k1_ccu_apmu_clks, + .num = ARRAY_SIZE(k1_ccu_apmu_clks), + .offset = K1_APMU_ID, +}; + +/* + * The K1 clock providers are split across separate syscon devices (PLL, + * MPMU, APMU, APBC) whose clocks parent across device boundaries. U-Boot's + * CCF resolves a parent by name at registration time and silently binds an + * orphan if the parent is not registered yet, so a controller must not + * register its clocks before the controllers owning its parents have probed. + * Force the parent controller to probe by its driver: this is robust against + * device tree node/phandle ordering and needs no helper "clocks" wiring in + * the syscon nodes. + */ +static int k1_clk_force_probe(const struct driver *drv) +{ + struct udevice *dev; + + return uclass_get_device_by_driver(UCLASS_CLK, drv, &dev); +} + +static int k1_clk_register(struct udevice *dev, struct regmap *regmap, + struct regmap *lock_regmap, + const struct spacemit_ccu_data *data) +{ + int i, ret; + + for (i = 0; i < data->num; i++) { + struct clk *clk = data->clks[i]; + struct ccu_common *common; + + if (!clk) + continue; + + common = clk_to_ccu_common(clk); + common->regmap = regmap; + common->lock_regmap = lock_regmap; + + if (common->clk.id < K1_PLL_ID) + clk->id = common->clk.id + data->offset; + else + clk->id = common->clk.id; + + ret = common->init(common); + if (ret) + return ret; + } + + return 0; +} + +static int k1_pll_clk_probe(struct udevice *dev) +{ + struct regmap *base_regmap, *lock_regmap = NULL; + const struct spacemit_ccu_data *data; + int ret; + + clk_register_fixed_rate(NULL, "clock-dummy", 0); + + ret = regmap_init_mem(dev_ofnode(dev), &base_regmap); + if (ret) + return ret; + + /* + * The lock status of PLLs locate in MPMU region, while PLLs themselves + * are in APBS region. Reference to MPMU syscon is required to check PLL + * status. + */ + if (device_is_compatible(dev, "spacemit,k1-pll")) { + struct ofnode_phandle_args mpmu_args; + + ret = dev_read_phandle_with_args(dev, "spacemit,mpmu", NULL, 0, 0, + &mpmu_args); + if (ret) + return ret; + + ret = regmap_init_mem(mpmu_args.node, &lock_regmap); + if (ret) + return ret; + } + + data = (struct spacemit_ccu_data *)dev_get_driver_data(dev); + + ret = k1_clk_register(dev, base_regmap, lock_regmap, data); + if (ret) + return -EPROBE_DEFER; + + return 0; +} + +static int k1_mpmu_clk_probe(struct udevice *dev) +{ + struct regmap *base_regmap, *lock_regmap = NULL; + const struct spacemit_ccu_data *data; + int ret; + + /* MPMU clocks parent off the PLL controller */ + ret = k1_clk_force_probe(DM_DRIVER_GET(k1_pll_clk)); + if (ret) + return ret; + + ret = regmap_init_mem(dev_ofnode(dev), &base_regmap); + if (ret) + return ret; + + data = (struct spacemit_ccu_data *)dev_get_driver_data(dev); + + ret = k1_clk_register(dev, base_regmap, lock_regmap, data); + if (ret) + return -EPROBE_DEFER; + + return 0; +} + +static int k1_apmu_clk_probe(struct udevice *dev) +{ + struct regmap *base_regmap, *lock_regmap = NULL; + const struct spacemit_ccu_data *data; + int ret; + + /* APMU clocks parent off the PLL and MPMU controllers */ + ret = k1_clk_force_probe(DM_DRIVER_GET(k1_pll_clk)); + if (ret) + return ret; + ret = k1_clk_force_probe(DM_DRIVER_GET(k1_mpmu_clk)); + if (ret) + return ret; + + ret = regmap_init_mem(dev_ofnode(dev), &base_regmap); + if (ret) + return ret; + + data = (struct spacemit_ccu_data *)dev_get_driver_data(dev); + + ret = k1_clk_register(dev, base_regmap, lock_regmap, data); + if (ret) + return -EPROBE_DEFER; + + return 0; +} + +static int k1_apbc_clk_probe(struct udevice *dev) +{ + struct regmap *base_regmap, *lock_regmap = NULL; + const struct spacemit_ccu_data *data; + int ret; + + /* APBC clocks parent off the PLL, MPMU and APMU controllers */ + ret = k1_clk_force_probe(DM_DRIVER_GET(k1_pll_clk)); + if (ret) + return ret; + ret = k1_clk_force_probe(DM_DRIVER_GET(k1_mpmu_clk)); + if (ret) + return ret; + ret = k1_clk_force_probe(DM_DRIVER_GET(k1_apmu_clk)); + if (ret) + return ret; + + ret = regmap_init_mem(dev_ofnode(dev), &base_regmap); + if (ret) + return ret; + + data = (struct spacemit_ccu_data *)dev_get_driver_data(dev); + + ret = k1_clk_register(dev, base_regmap, lock_regmap, data); + if (ret) + return -EPROBE_DEFER; + + return 0; +} + +static int k1_pll_clk_of_xlate(struct clk *clk, struct ofnode_phandle_args *args) +{ + if (args->args_count > 1) { + debug("Invalid args_count: %d\n", args->args_count); + return -EINVAL; + } + + if (args->args_count) + clk->id = K1_PLL_ID + args->args[0]; + else + clk->id = K1_PLL_ID; + + return 0; +} + +static int k1_mpmu_clk_of_xlate(struct clk *clk, struct ofnode_phandle_args *args) +{ + if (args->args_count > 1) { + debug("Invalid args_count: %d\n", args->args_count); + return -EINVAL; + } + + if (args->args_count) + clk->id = K1_MPMU_ID + args->args[0]; + else + clk->id = K1_MPMU_ID; + + return 0; +} + +static int k1_apbc_clk_of_xlate(struct clk *clk, struct ofnode_phandle_args *args) +{ + if (args->args_count > 1) { + debug("Invalid args_count: %d\n", args->args_count); + return -EINVAL; + } + + if (args->args_count) + clk->id = K1_APBC_ID + args->args[0]; + else + clk->id = K1_APBC_ID; + + return 0; +} + +static int k1_apmu_clk_of_xlate(struct clk *clk, struct ofnode_phandle_args *args) +{ + if (args->args_count > 1) { + debug("Invalid args_count: %d\n", args->args_count); + return -EINVAL; + } + + if (args->args_count) + clk->id = K1_APMU_ID + args->args[0]; + else + clk->id = K1_APMU_ID; + + return 0; +} + +static const struct udevice_id k1_pll_clk_match[] = { + { .compatible = "spacemit,k1-pll", + .data = (ulong)&k1_ccu_pll_data }, + { /* sentinel */ }, +}; + +K1_CLK_OPS(pll); + +U_BOOT_DRIVER(k1_pll_clk) = { + .name = "k1_pll_clk", + .id = UCLASS_CLK, + .of_match = k1_pll_clk_match, + .probe = k1_pll_clk_probe, + .ops = &k1_pll_clk_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +static int k1_mpmu_clk_bind(struct udevice *dev) +{ + return spacemit_k1_reset_bind(dev, SPACEMIT_K1_RESET_MPMU); +} + +static int k1_apbc_clk_bind(struct udevice *dev) +{ + return spacemit_k1_reset_bind(dev, SPACEMIT_K1_RESET_APBC); +} + +static int k1_apmu_clk_bind(struct udevice *dev) +{ + return spacemit_k1_reset_bind(dev, SPACEMIT_K1_RESET_APMU); +} + +static int k1_apbc2_clk_bind(struct udevice *dev) +{ + return spacemit_k1_reset_bind(dev, SPACEMIT_K1_RESET_APBC2); +} + +static const struct udevice_id k1_mpmu_clk_match[] = { + { .compatible = "spacemit,k1-syscon-mpmu", + .data = (ulong)&k1_ccu_mpmu_data }, + { /* sentinel */ }, +}; + +K1_CLK_OPS(mpmu); + +U_BOOT_DRIVER(k1_mpmu_clk) = { + .name = "k1_mpmu_clk", + .id = UCLASS_CLK, + .of_match = k1_mpmu_clk_match, + .bind = k1_mpmu_clk_bind, + .probe = k1_mpmu_clk_probe, + .ops = &k1_mpmu_clk_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +static const struct udevice_id k1_apbc_clk_match[] = { + { .compatible = "spacemit,k1-syscon-apbc", + .data = (ulong)&k1_ccu_apbc_data }, + { /* sentinel */ }, +}; + +K1_CLK_OPS(apbc); + +U_BOOT_DRIVER(k1_apbc_clk) = { + .name = "k1_apbc_clk", + .id = UCLASS_CLK, + .of_match = k1_apbc_clk_match, + .bind = k1_apbc_clk_bind, + .probe = k1_apbc_clk_probe, + .ops = &k1_apbc_clk_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +static const struct udevice_id k1_apmu_clk_match[] = { + { .compatible = "spacemit,k1-syscon-apmu", + .data = (ulong)&k1_ccu_apmu_data }, + { /* sentinel */ }, +}; + +K1_CLK_OPS(apmu); + +U_BOOT_DRIVER(k1_apmu_clk) = { + .name = "k1_apmu_clk", + .id = UCLASS_CLK, + .of_match = k1_apmu_clk_match, + .bind = k1_apmu_clk_bind, + .probe = k1_apmu_clk_probe, + .ops = &k1_apmu_clk_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +static const struct udevice_id k1_apbc2_clk_match[] = { + { .compatible = "spacemit,k1-syscon-apbc2" }, + { /* sentinel */ }, +}; + +U_BOOT_DRIVER(k1_apbc2_clk) = { + .name = "k1_apbc2_clk", + .id = UCLASS_CLK, + .of_match = k1_apbc2_clk_match, + .bind = k1_apbc2_clk_bind, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/drivers/clk/spacemit/clk_common.h b/drivers/clk/spacemit/clk_common.h new file mode 100644 index 00000000000..ea5ebf57784 --- /dev/null +++ b/drivers/clk/spacemit/clk_common.h @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2024 SpacemiT Technology Co. Ltd + * Copyright (c) 2024-2025 Haylen Chu <[email protected]> + * Copyright (c) 2025 Junhui Liu <[email protected]> + * Copyright (c) 2025-2026 RISCstar Ltd. + * + * Authors: Haylen Chu <[email protected]> + */ + +#ifndef _CLK_COMMON_H_ +#define _CLK_COMMON_H_ + +#include <linux/clk-provider.h> + +struct ccu_common; + +typedef int (*ccu_init_fn)(struct ccu_common *common); + +struct ccu_common { + struct regmap *regmap; + struct regmap *lock_regmap; + const char *name; + const char * const *parents; + size_t num_parents; + ccu_init_fn init; + + union { + /* For DDN and MIX */ + struct { + u32 reg_ctrl; + u32 reg_fc; + u32 mask_fc; + }; + + /* For PLL */ + struct { + u32 reg_swcr1; + u32 reg_swcr3; + }; + }; + + struct clk clk; +}; + +#define CCU_COMMON(_id, _name, _parent, _init, _flags) \ + .name = #_name, \ + .parents = (const char *[]) { _parent }, \ + .num_parents = 1, \ + .init = _init, \ + .clk = { .flags = _flags, .id = _id, } \ + +#define CCU_COMMON_PARENTS(_id, _name, _parents, _num_p, _init, _flags) \ + .name = #_name, \ + .parents = _parents, \ + .num_parents = _num_p, \ + .init = _init, \ + .clk = { .flags = _flags, .id = _id, } \ + +static inline struct ccu_common *clk_to_ccu_common(struct clk *clk) +{ + return container_of(clk, struct ccu_common, clk); +} + +#define ccu_read(c, reg) \ + ({ \ + struct ccu_common * const __ccu = (c); \ + u32 tmp; \ + regmap_read(__ccu->regmap, __ccu->reg_##reg, &tmp); \ + tmp; \ + }) +#define ccu_update(c, reg, mask, val) \ + ({ \ + struct ccu_common * const __ccu = (c); \ + regmap_update_bits(__ccu->regmap, __ccu->reg_##reg, \ + mask, val); \ + }) + +#endif /* _CLK_COMMON_H_ */ diff --git a/drivers/clk/spacemit/clk_ddn.c b/drivers/clk/spacemit/clk_ddn.c new file mode 100644 index 00000000000..7b93f30d5c3 --- /dev/null +++ b/drivers/clk/spacemit/clk_ddn.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2024 SpacemiT Technology Co. Ltd + * Copyright (c) 2024-2025 Haylen Chu <[email protected]> + * Copyright (c) 2025 Junhui Liu <[email protected]> + * Authors: Haylen Chu <[email protected]> + * + * DDN stands for "Divider Denominator Numerator", it's M/N clock with a + * constant x2 factor. This clock hardware follows the equation below, + * + * numerator Fin + * 2 * ------------- = ------- + * denominator Fout + * + * Thus, Fout could be calculated with, + * + * Fin denominator + * Fout = ----- * ------------- + * 2 numerator + */ + +#include <dm/device.h> +#include <regmap.h> +#include <linux/clk-provider.h> +#include <linux/rational.h> + +#include "clk_ddn.h" + +#define UBOOT_DM_SPACEMIT_CLK_DDN "spacemit_clk_ddn" + +static unsigned long ccu_ddn_calc_rate(unsigned long prate, unsigned long num, + unsigned long den, unsigned int pre_div) +{ + return prate * den / pre_div / num; +} + +static unsigned long ccu_ddn_calc_best_rate(struct ccu_ddn *ddn, + unsigned long rate, unsigned long prate, + unsigned long *num, unsigned long *den) +{ + rational_best_approximation(rate, prate / ddn->pre_div, + ddn->den_mask >> ddn->den_shift, + ddn->num_mask >> ddn->num_shift, + den, num); + return ccu_ddn_calc_rate(prate, *num, *den, ddn->pre_div); +} + +static unsigned long ccu_ddn_recalc_rate(struct clk *clk) +{ + struct ccu_ddn *ddn = clk_to_ccu_ddn(clk); + unsigned int val, num, den; + + val = ccu_read(&ddn->common, ctrl); + + num = (val & ddn->num_mask) >> ddn->num_shift; + den = (val & ddn->den_mask) >> ddn->den_shift; + + return ccu_ddn_calc_rate(clk_get_parent_rate(clk), num, den, ddn->pre_div); +} + +static unsigned long ccu_ddn_set_rate(struct clk *clk, unsigned long rate) +{ + struct ccu_ddn *ddn = clk_to_ccu_ddn(clk); + unsigned long num, den; + + ccu_ddn_calc_best_rate(ddn, rate, clk_get_parent_rate(clk), &num, &den); + + ccu_update(&ddn->common, ctrl, + ddn->num_mask | ddn->den_mask, + (num << ddn->num_shift) | (den << ddn->den_shift)); + + return 0; +} + +static const struct clk_ops spacemit_clk_ddn_ops = { + .get_rate = ccu_ddn_recalc_rate, + .set_rate = ccu_ddn_set_rate, +}; + +int spacemit_ddn_init(struct ccu_common *common) +{ + struct clk *clk = &common->clk; + + return clk_register(clk, UBOOT_DM_SPACEMIT_CLK_DDN, + common->name, common->parents[0]); +} + +U_BOOT_DRIVER(spacemit_clk_ddn) = { + .name = UBOOT_DM_SPACEMIT_CLK_DDN, + .id = UCLASS_CLK, + .ops = &spacemit_clk_ddn_ops, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/drivers/clk/spacemit/clk_ddn.h b/drivers/clk/spacemit/clk_ddn.h new file mode 100644 index 00000000000..1330ced23b1 --- /dev/null +++ b/drivers/clk/spacemit/clk_ddn.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2024 SpacemiT Technology Co. Ltd + * Copyright (c) 2024-2025 Haylen Chu <[email protected]> + * Copyright (c) 2025 Junhui Liu <[email protected]> + * Copyright (c) 2025-2026 RISCstar Ltd. + * + * Authors: Haylen Chu <[email protected]> + */ + +#ifndef _CLK_DDN_H_ +#define _CLK_DDN_H_ + +#include <linux/clk-provider.h> + +#include "clk_common.h" + +struct ccu_ddn { + struct ccu_common common; + unsigned int num_mask; + unsigned int num_shift; + unsigned int den_mask; + unsigned int den_shift; + unsigned int pre_div; +}; + +#define CCU_DDN_MASK(_num_shift, _num_width) \ + GENMASK((_num_shift) + (_num_width) - 1, _num_shift) + +#define CCU_DDN_DEFINE(_id, _var, _name, _parent, _reg_ctrl, _num_mask, \ + _num_shift, _den_mask, _den_shift, _pre_div, _flags) \ +static struct ccu_ddn _var = { \ + .common = { \ + .reg_ctrl = _reg_ctrl, \ + CCU_COMMON(_id, _name, _parent, spacemit_ddn_init, _flags) \ + }, \ + .num_mask = _num_mask, \ + .num_shift = _num_shift, \ + .den_mask = _den_mask, \ + .den_shift = _den_shift, \ + .pre_div = _pre_div, \ +} + +static inline struct ccu_ddn *clk_to_ccu_ddn(struct clk *clk) +{ + struct ccu_common *common = clk_to_ccu_common(clk); + + return container_of(common, struct ccu_ddn, common); +} + +int spacemit_ddn_init(struct ccu_common *common); + +#endif /* _CLK_DDN_H_ */ diff --git a/drivers/clk/spacemit/clk_mix.c b/drivers/clk/spacemit/clk_mix.c new file mode 100644 index 00000000000..a1158512a92 --- /dev/null +++ b/drivers/clk/spacemit/clk_mix.c @@ -0,0 +1,403 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2024 SpacemiT Technology Co. Ltd + * Copyright (c) 2024-2025 Haylen Chu <[email protected]> + * Copyright (c) 2025 Junhui Liu <[email protected]> + * Authors: Haylen Chu <[email protected]> + * + * MIX clock type is the combination of mux, factor or divider, and gate + */ + +#include <dm/device.h> +#include <dm/uclass.h> +#include <div64.h> +#include <regmap.h> +#include <linux/clk-provider.h> +#include <linux/kernel.h> + +#include "clk_mix.h" + +#define UBOOT_DM_SPACEMIT_CLK_GATE "spacemit_clk_gate" +#define UBOOT_DM_SPACEMIT_CLK_FACTOR "spacemit_clk_factor" +#define UBOOT_DM_SPACEMIT_CLK_MUX "spacemit_clk_mux" +#define UBOOT_DM_SPACEMIT_CLK_DIV "spacemit_clk_div" +#define UBOOT_DM_SPACEMIT_CLK_FACTOR_GATE "spacemit_clk_factor_gate" +#define UBOOT_DM_SPACEMIT_CLK_MUX_GATE "spacemit_clk_mux_gate" +#define UBOOT_DM_SPACEMIT_CLK_DIV_GATE "spacemit_clk_div_gate" +#define UBOOT_DM_SPACEMIT_CLK_MUX_DIV "spacemit_clk_mux_div" +#define UBOOT_DM_SPACEMIT_CLK_MUX_DIV_GATE "spacemit_clk_mux_div_gate" + +#define MIX_FC_TIMEOUT_US 10000 +#define MIX_FC_DELAY_US 5 + +int ccu_gate_disable(struct clk *clk) +{ + struct ccu_mix *mix = clk_to_ccu_mix(clk); + + ccu_update(&mix->common, ctrl, mix->gate.mask, 0); + + return 0; +} + +int ccu_gate_enable(struct clk *clk) +{ + struct ccu_mix *mix = clk_to_ccu_mix(clk); + struct ccu_gate_config *gate = &mix->gate; + + ccu_update(&mix->common, ctrl, gate->mask, gate->mask); + + return 0; +} + +static unsigned long ccu_factor_recalc_rate(struct clk *clk) +{ + struct ccu_mix *mix = clk_to_ccu_mix(clk); + + return clk_get_parent_rate(clk) * mix->factor.mul / mix->factor.div; +} + +static unsigned long ccu_div_recalc_rate(struct clk *clk) +{ + struct ccu_mix *mix = clk_to_ccu_mix(clk); + struct ccu_div_config *div = &mix->div; + unsigned long val; + + val = ccu_read(&mix->common, ctrl) >> div->shift; + val &= (1 << div->width) - 1; + + return divider_recalc_rate(clk, clk_get_parent_rate(clk), val, NULL, 0, div->width); +} + +/* + * Some clocks require a "FC" (frequency change) bit to be set after changing + * their rates or reparenting. This bit will be automatically cleared by + * hardware in MIX_FC_TIMEOUT_US, which indicates the operation is completed. + */ +static int ccu_mix_trigger_fc(struct clk *clk) +{ + struct ccu_common *common = clk_to_ccu_common(clk); + unsigned int val; + + if (common->reg_fc) + return 0; + + ccu_update(common, fc, common->mask_fc, common->mask_fc); + + return regmap_read_poll_timeout(common->regmap, common->reg_fc, + val, !(val & common->mask_fc), + MIX_FC_DELAY_US, + MIX_FC_TIMEOUT_US); +} + +static unsigned long +ccu_mix_calc_best_rate(struct clk *clk, unsigned long rate, + struct clk **best_parent, + unsigned long *best_parent_rate, + u32 *div_val) +{ + struct ccu_common *common = clk_to_ccu_common(clk); + struct ccu_mix *mix = clk_to_ccu_mix(clk); + unsigned int parent_num = common->num_parents; + struct ccu_div_config *div = &mix->div; + u32 div_max = 1 << div->width; + unsigned long best_rate = 0; + + for (int i = 0; i < parent_num; i++) { + struct udevice *parent_dev; + unsigned long parent_rate; + struct clk *parent; + + if (uclass_get_device_by_name(UCLASS_CLK, common->parents[i], + &parent_dev)) + continue; + parent = dev_get_clk_ptr(parent_dev); + if (!parent) + continue; + + parent_rate = clk_get_rate(parent); + + for (int j = 1; j <= div_max; j++) { + unsigned long tmp = DIV_ROUND_CLOSEST_ULL(parent_rate, j); + + if (abs(tmp - rate) < abs(best_rate - rate)) { + best_rate = tmp; + + if (div_val) + *div_val = j - 1; + + if (best_parent) { + *best_parent = parent; + *best_parent_rate = parent_rate; + } + } + } + } + + return best_rate; +} + +static unsigned long ccu_mix_set_rate(struct clk *clk, unsigned long rate) +{ + struct ccu_mix *mix = clk_to_ccu_mix(clk); + struct ccu_common *common = &mix->common; + struct ccu_div_config *div = &mix->div; + u32 current_div, target_div, mask; + + ccu_mix_calc_best_rate(clk, rate, NULL, NULL, &target_div); + + current_div = ccu_read(common, ctrl) >> div->shift; + current_div &= (1 << div->width) - 1; + + if (current_div == target_div) + return 0; + + mask = GENMASK(div->width + div->shift - 1, div->shift); + + ccu_update(common, ctrl, mask, target_div << div->shift); + + return ccu_mix_trigger_fc(clk); +} + +static u8 ccu_mux_get_parent(struct clk *clk) +{ + struct ccu_mix *mix = clk_to_ccu_mix(clk); + struct ccu_mux_config *mux = &mix->mux; + u8 parent; + + parent = ccu_read(&mix->common, ctrl) >> mux->shift; + parent &= (1 << mux->width) - 1; + + return parent; +} + +static int ccu_mux_set_parent(struct clk *clk, struct clk *parent) +{ + struct ccu_common *common = clk_to_ccu_common(clk); + struct ccu_mix *mix = clk_to_ccu_mix(clk); + struct ccu_mux_config *mux = &mix->mux; + u32 mask; + int i = 0; + + mask = GENMASK(mux->width + mux->shift - 1, mux->shift); + + for (i = 0; i < common->num_parents; i++) { + if (!strcmp(parent->dev->name, common->parents[i])) + break; + } + + if (i == common->num_parents) + return -EINVAL; + + ccu_update(&mix->common, ctrl, mask, i << mux->shift); + + return ccu_mix_trigger_fc(clk); +} + +int spacemit_gate_init(struct ccu_common *common) +{ + struct clk *clk = &common->clk; + + return clk_register(clk, UBOOT_DM_SPACEMIT_CLK_GATE, + common->name, common->parents[0]); +} + +static const struct clk_ops spacemit_clk_gate_ops = { + .disable = ccu_gate_disable, + .enable = ccu_gate_enable, + .get_rate = clk_generic_get_rate, +}; + +U_BOOT_DRIVER(spacemit_clk_gate) = { + .name = UBOOT_DM_SPACEMIT_CLK_GATE, + .id = UCLASS_CLK, + .ops = &spacemit_clk_gate_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +int spacemit_factor_init(struct ccu_common *common) +{ + struct clk *clk = &common->clk; + + return clk_register(clk, UBOOT_DM_SPACEMIT_CLK_FACTOR, + common->name, common->parents[0]); +} + +static const struct clk_ops spacemit_clk_factor_ops = { + .get_rate = ccu_factor_recalc_rate, +}; + +U_BOOT_DRIVER(spacemit_clk_factor) = { + .name = UBOOT_DM_SPACEMIT_CLK_FACTOR, + .id = UCLASS_CLK, + .ops = &spacemit_clk_factor_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +int spacemit_mux_init(struct ccu_common *common) +{ + struct clk *clk = &common->clk; + u8 index; + + index = ccu_mux_get_parent(clk); + if (index >= common->num_parents) + index = 0; + + return clk_register(clk, UBOOT_DM_SPACEMIT_CLK_MUX, + common->name, common->parents[index]); +} + +static const struct clk_ops spacemit_clk_mux_ops = { + .set_parent = ccu_mux_set_parent, + .get_rate = clk_generic_get_rate, +}; + +U_BOOT_DRIVER(spacemit_clk_mux) = { + .name = UBOOT_DM_SPACEMIT_CLK_MUX, + .id = UCLASS_CLK, + .ops = &spacemit_clk_mux_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +int spacemit_div_init(struct ccu_common *common) +{ + struct clk *clk = &common->clk; + + return clk_register(clk, UBOOT_DM_SPACEMIT_CLK_DIV, + common->name, common->parents[0]); +} + +static const struct clk_ops spacemit_clk_div_ops = { + .get_rate = ccu_div_recalc_rate, + .set_rate = ccu_mix_set_rate, +}; + +U_BOOT_DRIVER(spacemit_clk_div) = { + .name = UBOOT_DM_SPACEMIT_CLK_DIV, + .id = UCLASS_CLK, + .ops = &spacemit_clk_div_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +int spacemit_factor_gate_init(struct ccu_common *common) +{ + struct clk *clk = &common->clk; + + return clk_register(clk, UBOOT_DM_SPACEMIT_CLK_FACTOR_GATE, + common->name, common->parents[0]); +} + +static const struct clk_ops spacemit_clk_factor_gate_ops = { + .disable = ccu_gate_disable, + .enable = ccu_gate_enable, + .get_rate = ccu_factor_recalc_rate, +}; + +U_BOOT_DRIVER(spacemit_clk_factor_gate) = { + .name = UBOOT_DM_SPACEMIT_CLK_FACTOR_GATE, + .id = UCLASS_CLK, + .ops = &spacemit_clk_factor_gate_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +int spacemit_mux_gate_init(struct ccu_common *common) +{ + struct clk *clk = &common->clk; + u8 index; + + index = ccu_mux_get_parent(clk); + if (index >= common->num_parents) + index = 0; + + return clk_register(clk, UBOOT_DM_SPACEMIT_CLK_MUX_GATE, + common->name, common->parents[index]); +} + +static const struct clk_ops spacemit_clk_mux_gate_ops = { + .disable = ccu_gate_disable, + .enable = ccu_gate_enable, + .set_parent = ccu_mux_set_parent, + .get_rate = clk_generic_get_rate, +}; + +U_BOOT_DRIVER(spacemit_clk_mux_gate) = { + .name = UBOOT_DM_SPACEMIT_CLK_MUX_GATE, + .id = UCLASS_CLK, + .ops = &spacemit_clk_mux_gate_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +int spacemit_div_gate_init(struct ccu_common *common) +{ + struct clk *clk = &common->clk; + + return clk_register(clk, UBOOT_DM_SPACEMIT_CLK_DIV_GATE, + common->name, common->parents[0]); +} + +static const struct clk_ops spacemit_clk_div_gate_ops = { + .disable = ccu_gate_disable, + .enable = ccu_gate_enable, + .get_rate = ccu_div_recalc_rate, + .set_rate = ccu_mix_set_rate, +}; + +U_BOOT_DRIVER(spacemit_clk_div_gate) = { + .name = UBOOT_DM_SPACEMIT_CLK_DIV_GATE, + .id = UCLASS_CLK, + .ops = &spacemit_clk_div_gate_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +int spacemit_mux_div_init(struct ccu_common *common) +{ + struct clk *clk = &common->clk; + u8 index; + + index = ccu_mux_get_parent(clk); + if (index >= common->num_parents) + index = 0; + + return clk_register(clk, UBOOT_DM_SPACEMIT_CLK_MUX_DIV, + common->name, common->parents[index]); +} + +static const struct clk_ops spacemit_clk_mux_div_ops = { + .set_parent = ccu_mux_set_parent, + .get_rate = ccu_div_recalc_rate, + .set_rate = ccu_mix_set_rate, +}; + +U_BOOT_DRIVER(spacemit_clk_mux_div) = { + .name = UBOOT_DM_SPACEMIT_CLK_MUX_DIV, + .id = UCLASS_CLK, + .ops = &spacemit_clk_mux_div_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +int spacemit_mux_div_gate_init(struct ccu_common *common) +{ + struct clk *clk = &common->clk; + u8 index; + + index = ccu_mux_get_parent(clk); + if (index >= common->num_parents) + index = 0; + + return clk_register(clk, UBOOT_DM_SPACEMIT_CLK_MUX_DIV_GATE, + common->name, common->parents[index]); +} + +static const struct clk_ops spacemit_clk_mux_div_gate_ops = { + .disable = ccu_gate_disable, + .enable = ccu_gate_enable, + .set_parent = ccu_mux_set_parent, + .get_rate = ccu_div_recalc_rate, + .set_rate = ccu_mix_set_rate, +}; + +U_BOOT_DRIVER(spacemit_clk_mux_div_gate) = { + .name = UBOOT_DM_SPACEMIT_CLK_MUX_DIV_GATE, + .id = UCLASS_CLK, + .ops = &spacemit_clk_mux_div_gate_ops, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/drivers/clk/spacemit/clk_mix.h b/drivers/clk/spacemit/clk_mix.h new file mode 100644 index 00000000000..26a12cedd0d --- /dev/null +++ b/drivers/clk/spacemit/clk_mix.h @@ -0,0 +1,224 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2024 SpacemiT Technology Co. Ltd + * Copyright (c) 2024-2025 Haylen Chu <[email protected]> + * Copyright (c) 2025 Junhui Liu <[email protected]> + * Copyright (c) 2025-2026 RISCstar Ltd. + * + * Authors: Haylen Chu <[email protected]> + */ + +#ifndef _CLK_MIX_H_ +#define _CLK_MIX_H_ + +#include <linux/clk-provider.h> + +#include "clk_common.h" + +/** + * struct ccu_gate_config - Gate configuration + * + * @mask: Mask to enable the gate. Some clocks may have more than one bit + * set in this field. + */ +struct ccu_gate_config { + u32 mask; +}; + +struct ccu_factor_config { + u32 div; + u32 mul; +}; + +struct ccu_mux_config { + u8 shift; + u8 width; +}; + +struct ccu_div_config { + u8 shift; + u8 width; +}; + +struct ccu_mix { + struct ccu_factor_config factor; + struct ccu_gate_config gate; + struct ccu_div_config div; + struct ccu_mux_config mux; + struct ccu_common common; +}; + +#define CCU_GATE_INIT(_mask) { .mask = _mask } +#define CCU_FACTOR_INIT(_div, _mul) { .div = _div, .mul = _mul } +#define CCU_MUX_INIT(_shift, _width) { .shift = _shift, .width = _width } +#define CCU_DIV_INIT(_shift, _width) { .shift = _shift, .width = _width } + +#define CCU_GATE_DEFINE(_id, _var, _name, _parent, _reg_ctrl, \ + _mask_gate, _flags) \ +static struct ccu_mix _var = { \ + .gate = CCU_GATE_INIT(_mask_gate), \ + .common = { \ + .reg_ctrl = _reg_ctrl, \ + CCU_COMMON(_id, _name, _parent, spacemit_gate_init, \ + _flags) \ + } \ +} + +#define CCU_FACTOR_DEFINE(_id, _var, _name, _parent, _div, _mul) \ +static struct ccu_mix _var = { \ + .factor = CCU_FACTOR_INIT(_div, _mul), \ + .common = { \ + CCU_COMMON(_id, _name, _parent, spacemit_factor_init, \ + 0) \ + } \ +} + +#define CCU_MUX_DEFINE(_id, _var, _name, _parents, _num_p, _reg_ctrl, \ + _shift, _width, _flags) \ +static struct ccu_mix _var = { \ + .mux = CCU_MUX_INIT(_shift, _width), \ + .common = { \ + .reg_ctrl = _reg_ctrl, \ + CCU_COMMON_PARENTS(_id, _name, _parents, _num_p, \ + spacemit_mux_init, _flags) \ + } \ +} + +#define CCU_DIV_DEFINE(_id, _var, _name, _parent, _reg_ctrl, _shift, \ + _width, _flags) \ +static struct ccu_mix _var = { \ + .div = CCU_DIV_INIT(_shift, _width), \ + .common = { \ + .reg_ctrl = _reg_ctrl, \ + CCU_COMMON(_id, _name, _parent, spacemit_div_init, \ + _flags) \ + } \ +} + +#define CCU_FACTOR_GATE_FLAGS_DEFINE(_id, _var, _name, _parent, \ + _reg_ctrl, _mask_gate, _div, _mul, \ + _flags) \ +static struct ccu_mix _var = { \ + .gate = CCU_GATE_INIT(_mask_gate), \ + .factor = CCU_FACTOR_INIT(_div, _mul), \ + .common = { \ + .reg_ctrl = _reg_ctrl, \ + CCU_COMMON(_id, _name, _parent, \ + spacemit_factor_gate_init, _flags) \ + } \ +} + +#define CCU_FACTOR_GATE_DEFINE(_id, _var, _name, _parent, _reg_ctrl, \ + _mask_gate, _div, _mul) \ + CCU_FACTOR_GATE_FLAGS_DEFINE(_id, _var, _name, _parent, \ + _reg_ctrl, _mask_gate, _div, _mul, \ + 0) + +#define CCU_MUX_GATE_DEFINE(_id, _var, _name, _parents, _num_p, \ + _reg_ctrl, _shift, _width, _mask_gate, \ + _flags) \ +static struct ccu_mix _var = { \ + .gate = CCU_GATE_INIT(_mask_gate), \ + .mux = CCU_MUX_INIT(_shift, _width), \ + .common = { \ + .reg_ctrl = _reg_ctrl, \ + CCU_COMMON_PARENTS(_id, _name, _parents, _num_p, \ + spacemit_mux_gate_init, _flags) \ + } \ +} + +#define CCU_DIV_GATE_DEFINE(_id, _var, _name, _parent, _reg_ctrl, \ + _shift, _width, _mask_gate, _flags) \ +static struct ccu_mix _var = { \ + .gate = CCU_GATE_INIT(_mask_gate), \ + .div = CCU_DIV_INIT(_shift, _width), \ + .common = { \ + .reg_ctrl = _reg_ctrl, \ + CCU_COMMON(_id, _name, _parent, \ + spacemit_div_gate_init, _flags) \ + } \ +} + +#define CCU_MUX_DIV_GATE_DEFINE(_id, _var, _name, _parents, _num_p, \ + _reg_ctrl, _mshift, _mwidth, _muxshift, \ + _muxwidth, _mask_gate, _flags) \ +static struct ccu_mix _var = { \ + .gate = CCU_GATE_INIT(_mask_gate), \ + .div = CCU_DIV_INIT(_mshift, _mwidth), \ + .mux = CCU_MUX_INIT(_muxshift, _muxwidth), \ + .common = { \ + .reg_ctrl = _reg_ctrl, \ + CCU_COMMON_PARENTS(_id, _name, _parents, _num_p, \ + spacemit_mux_div_gate_init, _flags) \ + }, \ +} + +#define CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(_id, _var, _name, _parents, \ + _num_p, _reg_ctrl, _reg_fc, \ + _mshift, _mwidth, _mask_fc, \ + _muxshift, _muxwidth, \ + _mask_gate, _flags) \ +static struct ccu_mix _var = { \ + .gate = CCU_GATE_INIT(_mask_gate), \ + .div = CCU_DIV_INIT(_mshift, _mwidth), \ + .mux = CCU_MUX_INIT(_muxshift, _muxwidth), \ + .common = { \ + .reg_ctrl = _reg_ctrl, \ + .reg_fc = _reg_fc, \ + .mask_fc = _mask_fc, \ + CCU_COMMON_PARENTS(_id, _name, _parents, _num_p, \ + spacemit_mux_div_gate_init, _flags) \ + }, \ +} + +#define CCU_MUX_DIV_FC_DEFINE(_id, _var, _name, _parents, _num_p, \ + _reg_ctrl, _reg_fc, _mshift, _mwidth, \ + _mask_fc, _muxshift, _muxwidth, _flags) \ +static struct ccu_mix _var = { \ + .div = CCU_DIV_INIT(_mshift, _mwidth), \ + .mux = CCU_MUX_INIT(_muxshift, _muxwidth), \ + .common = { \ + .reg_ctrl = _reg_ctrl, \ + .reg_fc = _reg_fc, \ + .mask_fc = _mask_fc, \ + CCU_COMMON_PARENTS(_id, _name, _parents, _num_p, \ + spacemit_mux_div_init, _flags) \ + }, \ +} + +#define CCU_MUX_FC_DEFINE(_id, _var, _name, _parents, _num_p, \ + _reg_ctrl, _reg_fc, _mask_fc, _muxshift, \ + _muxwidth, _flags) \ +static struct ccu_mix _var = { \ + .mux = CCU_MUX_INIT(_muxshift, _muxwidth), \ + .common = { \ + .reg_ctrl = _reg_ctrl, \ + .reg_fc = _reg_fc, \ + .mask_fc = _mask_fc, \ + CCU_COMMON_PARENTS(_id, _name, _parents, _num_p, \ + spacemit_mux_init, \ + _flags) \ + }, \ +} + +static inline struct ccu_mix *clk_to_ccu_mix(struct clk *clk) +{ + struct ccu_common *common = clk_to_ccu_common(clk); + + return container_of(common, struct ccu_mix, common); +} + +int ccu_gate_enable(struct clk *clk); +int ccu_gate_disable(struct clk *clk); + +int spacemit_gate_init(struct ccu_common *common); +int spacemit_factor_init(struct ccu_common *common); +int spacemit_mux_init(struct ccu_common *common); +int spacemit_div_init(struct ccu_common *common); +int spacemit_factor_gate_init(struct ccu_common *common); +int spacemit_div_gate_init(struct ccu_common *common); +int spacemit_mux_gate_init(struct ccu_common *common); +int spacemit_mux_div_init(struct ccu_common *common); +int spacemit_mux_div_gate_init(struct ccu_common *common); + +#endif /* _CLK_MIX_H_ */ diff --git a/drivers/clk/spacemit/clk_pll.c b/drivers/clk/spacemit/clk_pll.c new file mode 100644 index 00000000000..56da70af58a --- /dev/null +++ b/drivers/clk/spacemit/clk_pll.c @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2024 SpacemiT Technology Co. Ltd + * Copyright (c) 2024-2025 Haylen Chu <[email protected]> + * Copyright (c) 2025 Junhui Liu <[email protected]> + * Authors: Haylen Chu <[email protected]> + */ + +#include <dm/device.h> +#include <regmap.h> +#include <linux/bug.h> +#include <linux/clk-provider.h> + +#include "clk_pll.h" + +#define UBOOT_DM_SPACEMIT_CLK_PLL "spacemit_clk_pll" + +#define PLL_TIMEOUT_US 3000 +#define PLL_DELAY_US 5 + +#define PLL_SWCR3_EN ((u32)BIT(31)) +#define PLL_SWCR3_MASK GENMASK(30, 0) + +static const struct ccu_pll_rate_tbl *ccu_pll_lookup_best_rate(struct ccu_pll *pll, + unsigned long rate) +{ + struct ccu_pll_config *config = &pll->config; + const struct ccu_pll_rate_tbl *best_entry; + unsigned long best_delta = ULONG_MAX; + int i; + + for (i = 0; i < config->tbl_num; i++) { + const struct ccu_pll_rate_tbl *entry = &config->rate_tbl[i]; + unsigned long delta = abs(entry->rate - rate); + + if (delta < best_delta) { + best_delta = delta; + best_entry = entry; + } + } + + return best_entry; +} + +static const struct ccu_pll_rate_tbl *ccu_pll_lookup_matched_entry(struct ccu_pll *pll) +{ + struct ccu_pll_config *config = &pll->config; + u32 swcr1, swcr3; + int i; + + swcr1 = ccu_read(&pll->common, swcr1); + swcr3 = ccu_read(&pll->common, swcr3); + swcr3 &= PLL_SWCR3_MASK; + + for (i = 0; i < config->tbl_num; i++) { + const struct ccu_pll_rate_tbl *entry = &config->rate_tbl[i]; + + if (swcr1 == entry->swcr1 && swcr3 == entry->swcr3) + return entry; + } + + return NULL; +} + +static void ccu_pll_update_param(struct ccu_pll *pll, const struct ccu_pll_rate_tbl *entry) +{ + struct ccu_common *common = &pll->common; + + regmap_write(common->regmap, common->reg_swcr1, entry->swcr1); + ccu_update(common, swcr3, PLL_SWCR3_MASK, entry->swcr3); +} + +static int ccu_pll_enable(struct clk *clk) +{ + struct ccu_pll *pll = clk_to_ccu_pll(clk); + struct ccu_common *common = &pll->common; + unsigned int tmp; + + ccu_update(common, swcr3, PLL_SWCR3_EN, PLL_SWCR3_EN); + + /* check lock status */ + return regmap_read_poll_timeout(common->lock_regmap, + pll->config.reg_lock, + tmp, + tmp & pll->config.mask_lock, + PLL_DELAY_US, PLL_TIMEOUT_US); +} + +static int ccu_pll_disable(struct clk *clk) +{ + struct ccu_common *common = clk_to_ccu_common(clk); + + ccu_update(common, swcr3, PLL_SWCR3_EN, 0); + + return 0; +} + +/* + * PLLs must be gated before changing rate, which is ensured by + * flag CLK_SET_RATE_GATE. + */ +static unsigned long ccu_pll_set_rate(struct clk *clk, unsigned long rate) +{ + struct ccu_pll *pll = clk_to_ccu_pll(clk); + const struct ccu_pll_rate_tbl *entry; + + entry = ccu_pll_lookup_best_rate(pll, rate); + ccu_pll_update_param(pll, entry); + + return 0; +} + +static unsigned long ccu_pll_recalc_rate(struct clk *clk) +{ + struct ccu_pll *pll = clk_to_ccu_pll(clk); + const struct ccu_pll_rate_tbl *entry; + + entry = ccu_pll_lookup_matched_entry(pll); + + WARN_ON_ONCE(!entry); + + return entry ? entry->rate : 0; +} + +static const struct clk_ops spacemit_clk_pll_ops = { + .enable = ccu_pll_enable, + .disable = ccu_pll_disable, + .set_rate = ccu_pll_set_rate, + .get_rate = ccu_pll_recalc_rate, +}; + +int spacemit_pll_init(struct ccu_common *common) +{ + struct clk *clk = &common->clk; + struct ccu_pll *pll = clk_to_ccu_pll(clk); + int ret; + + ret = clk_register(clk, UBOOT_DM_SPACEMIT_CLK_PLL, + common->name, common->parents[0]); + if (ret) + return ret; + + if (ccu_pll_lookup_matched_entry(pll)) + return 0; + + ccu_pll_disable(clk); + ccu_pll_update_param(pll, &pll->config.rate_tbl[0]); + + return 0; +} + +U_BOOT_DRIVER(spacemit_clk_pll) = { + .name = UBOOT_DM_SPACEMIT_CLK_PLL, + .id = UCLASS_CLK, + .ops = &spacemit_clk_pll_ops, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/drivers/clk/spacemit/clk_pll.h b/drivers/clk/spacemit/clk_pll.h new file mode 100644 index 00000000000..3987cc1141b --- /dev/null +++ b/drivers/clk/spacemit/clk_pll.h @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2024 SpacemiT Technology Co. Ltd + * Copyright (c) 2024-2025 Haylen Chu <[email protected]> + * Copyright (c) 2025 Junhui Liu <[email protected]> + * Copyright (c) 2025-2026 RISCstar Ltd. + * + * Authors: Haylen Chu <[email protected]> + */ + +#ifndef _CLK_PLL_H_ +#define _CLK_PLL_H_ + +#include <linux/clk-provider.h> + +#include "clk_common.h" + +/** + * struct ccu_pll_rate_tbl - Structure mapping between PLL rate and register + * configuration. + * + * @rate: PLL rate + * @swcr1: Register value of PLLX_SW1_CTRL (PLLx_SWCR1). + * @swcr3: Register value of the PLLx_SW3_CTRL's lowest 31 bits of + * PLLx_SW3_CTRL (PLLx_SWCR3). This highest bit is for enabling + * the PLL and not contained in this field. + */ +struct ccu_pll_rate_tbl { + unsigned long rate; + u32 swcr1; + u32 swcr3; +}; + +#define CCU_PLL_RATE(_rate, _swcr1, _swcr3) \ + { \ + .rate = _rate, \ + .swcr1 = _swcr1, \ + .swcr3 = _swcr3, \ + } + +struct ccu_pll_config { + const struct ccu_pll_rate_tbl *rate_tbl; + u32 tbl_num; + u32 reg_lock; + u32 mask_lock; +}; + +struct ccu_pll { + struct ccu_common common; + struct ccu_pll_config config; +}; + +#define CCU_PLL_CONFIG(_table, _reg_lock, _mask_lock) \ + { \ + .rate_tbl = (_table), \ + .tbl_num = sizeof(_table) / sizeof((_table)[0]), \ + .reg_lock = (_reg_lock), \ + .mask_lock = (_mask_lock), \ + } + +#define CCU_PLL_DEFINE(_id, _var, _name, _parent, _table, _reg_swcr1, \ + _reg_swcr3, _reg_lock, _mask_lock, _flags) \ +static struct ccu_pll _var = { \ + .config = CCU_PLL_CONFIG(_table, _reg_lock, _mask_lock), \ + .common = { \ + .reg_swcr1 = _reg_swcr1, \ + .reg_swcr3 = _reg_swcr3, \ + CCU_COMMON(_id, _name, _parent, spacemit_pll_init, _flags) \ + } \ +} + +static inline struct ccu_pll *clk_to_ccu_pll(struct clk *clk) +{ + struct ccu_common *common = clk_to_ccu_common(clk); + + return container_of(common, struct ccu_pll, common); +} + +int spacemit_pll_init(struct ccu_common *common); + +#endif /* _CLK_PLL_H_ */ diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 75b35fbc5be..a11f3043670 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -449,6 +449,14 @@ config SANDBOX_GPIO_COUNT of 'anonymous' GPIOs that do not belong to any device or bank. Select a suitable value depending on your needs. +config SPACEMIT_GPIO + bool "Spacemit K1 GPIO driver" + depends on DM_GPIO && TARGET_SPACEMIT_K1 + help + Support the GPIO device in Spacemit SoCs. The GPIOs are arranged + into a number of banks (different for each SoC type) each with 32 + GPIOs. + config SUNXI_GPIO bool "Allwinner GPIO driver" depends on ARCH_SUNXI diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 863557e45ce..020e23c7252 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -66,6 +66,7 @@ obj-$(CONFIG_MVEBU_GPIO) += mvebu_gpio.o obj-$(CONFIG_MSM_GPIO) += msm_gpio.o obj-$(CONFIG_$(PHASE_)PCF8575_GPIO) += pcf8575_gpio.o obj-$(CONFIG_$(PHASE_)QCOM_PMIC_GPIO) += qcom_pmic_gpio.o qcom_spmi_gpio.o +obj-$(CONFIG_$(PHASE_)SPACEMIT_GPIO) += spacemit_gpio.o obj-$(CONFIG_MT7620_GPIO) += mt7620_gpio.o obj-$(CONFIG_MT7621_GPIO) += mt7621_gpio.o obj-$(CONFIG_MSCC_SGPIO) += mscc_sgpio.o diff --git a/drivers/gpio/spacemit_gpio.c b/drivers/gpio/spacemit_gpio.c new file mode 100644 index 00000000000..de71880df15 --- /dev/null +++ b/drivers/gpio/spacemit_gpio.c @@ -0,0 +1,253 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2025-2026 RISCstar Ltd. + */ + +#include <asm/gpio.h> +#include <clk.h> +#include <dm/device.h> +#include <dm/device_compat.h> +#include <dm/pinctrl.h> +#include <dm/read.h> +#include <dm/uclass.h> +#include <linux/bitops.h> +#include <linux/errno.h> +#include <linux/io.h> +#include <log.h> + +#define GPIO_BANK_SIZE 32 +#define GPIO_TO_BANK(pin) ((pin) / GPIO_BANK_SIZE) +#define GPIO_TO_BIT(pin) ((pin) % GPIO_BANK_SIZE) + +static inline int gpio_to_reg_offset(unsigned int pin) +{ + unsigned int bank = GPIO_TO_BANK(pin); + + if (bank == 0) + return 0; + else if (bank == 1) + return 4; + else if (bank == 2) + return 8; + else if (bank == 3) + return 0x100; + log_warning("Use default GPIO bank for an invalid GPIO[%d].\n", pin); + return 0; +} + +#define REG_PLR(pin) (0x00 + gpio_to_reg_offset(pin)) +#define REG_PDR(pin) (0x0c + gpio_to_reg_offset(pin)) +#define REG_PSR(pin) (0x18 + gpio_to_reg_offset(pin)) +#define REG_PCR(pin) (0x24 + gpio_to_reg_offset(pin)) +#define REG_SDR(pin) (0x54 + gpio_to_reg_offset(pin)) +#define REG_CDR(pin) (0x60 + gpio_to_reg_offset(pin)) + +struct spacemit_gpio_data { + u16 gpio_base; + u16 gpio_count; + u8 num_banks; +}; + +struct spacemit_gpio_priv { + void __iomem *regs; +}; + +static int spacemit_gpio_xlate(struct udevice *dev, struct gpio_desc *desc, + struct ofnode_phandle_args *args) +{ + struct spacemit_gpio_data *data; + u32 bank, offset, flags; + + data = (struct spacemit_gpio_data *)dev_get_driver_data(dev); + if (args->args_count < 3) { + dev_err(dev, "Invalid args count: %d, expected 3\n", + args->args_count); + return -EINVAL; + } + bank = args->args[0]; + offset = args->args[1]; + flags = args->args[2]; + + if (bank >= data->num_banks) { + dev_err(dev, "Invalid gpio bank: %u (max %u)\n", + bank, data->num_banks - 1); + return -EINVAL; + } + if (offset >= GPIO_BANK_SIZE) { + dev_err(dev, "Invalid offset: %u (max 31)\n", offset); + return -EINVAL; + } + desc->offset = bank * GPIO_BANK_SIZE + offset; + desc->flags = gpio_flags_xlate(flags); + return 0; +} + +static int spacemit_gpio_get_value(struct udevice *dev, unsigned int offset) +{ + struct spacemit_gpio_priv *priv = dev_get_priv(dev); + void __iomem *addr; + u32 value, mask; + + addr = priv->regs + REG_PLR(offset); + value = readl(addr); + mask = 1 << GPIO_TO_BIT(offset); + return !!(value & mask); +} + +static int spacemit_gpio_get_function(struct udevice *dev, unsigned int offset) +{ + struct spacemit_gpio_priv *priv = dev_get_priv(dev); + void __iomem *addr; + u32 value, mask; + + addr = priv->regs + REG_PDR(offset); + value = readl(addr); + mask = 1 << GPIO_TO_BIT(offset); + if (value & mask) + return GPIOF_OUTPUT; + return GPIOF_INPUT; +} + +static int spacemit_gpio_get_flags(struct udevice *dev, unsigned int offset, + ulong *flagsp) +{ + ulong flags = 0; + u32 dir; + + dir = spacemit_gpio_get_function(dev, offset); + if (dir) { + flags |= GPIOD_IS_OUT; + if (spacemit_gpio_get_value(dev, offset)) + flags |= GPIOD_IS_OUT_ACTIVE; + } else { + flags |= GPIOD_IS_IN; + } + *flagsp = flags; + return 0; +} + +static int spacemit_gpio_set_flags(struct udevice *dev, unsigned int offset, + ulong flags) +{ + struct spacemit_gpio_priv *priv = dev_get_priv(dev); + void __iomem *addr; + int value; + + value = (flags & GPIOD_IS_OUT_ACTIVE) ? 1 : 0; + if (flags & GPIOD_IS_IN) { + addr = priv->regs + REG_CDR(offset); + writel(1 << GPIO_TO_BIT(offset), addr); + } + if (flags & GPIOD_IS_OUT) { + if (value) { + addr = priv->regs + REG_PSR(offset); + writel(1 << GPIO_TO_BIT(offset), addr); + } else { + addr = priv->regs + REG_PCR(offset); + writel(1 << GPIO_TO_BIT(offset), addr); + } + addr = priv->regs + REG_SDR(offset); + writel(1 << GPIO_TO_BIT(offset), addr); + } + return 0; +} + +static int spacemit_gpio_request(struct udevice *dev, unsigned int offset, + const char *label) +{ + const struct pinctrl_ops *ops; + struct udevice *pctldev; + int ret; + + ret = uclass_first_device_err(UCLASS_PINCTRL, &pctldev); + if (ret) + return ret; + + ops = pinctrl_get_ops(pctldev); + if (!ops->gpio_request_enable) + return -ENOSYS; + + return ops->gpio_request_enable(pctldev, offset); +} + +static int spacemit_gpio_rfree(struct udevice *dev, unsigned int offset) +{ + const struct pinctrl_ops *ops; + struct udevice *pctldev; + int ret; + + ret = uclass_first_device_err(UCLASS_PINCTRL, &pctldev); + if (ret) + return ret; + + ops = pinctrl_get_ops(pctldev); + if (!ops->gpio_disable_free) + return -ENOSYS; + + return ops->gpio_disable_free(pctldev, offset); +} + +static const struct dm_gpio_ops spacemit_gpio_ops = { + .request = spacemit_gpio_request, + .rfree = spacemit_gpio_rfree, + .xlate = spacemit_gpio_xlate, + .get_value = spacemit_gpio_get_value, + .get_function = spacemit_gpio_get_function, + .get_flags = spacemit_gpio_get_flags, + .set_flags = spacemit_gpio_set_flags, +}; + +static int spacemit_gpio_probe(struct udevice *dev) +{ + struct spacemit_gpio_priv *priv; + struct spacemit_gpio_data *data; + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); + struct clk_bulk clks; + int ret; + + data = (struct spacemit_gpio_data *)dev_get_driver_data(dev); + priv = dev_get_priv(dev); + priv->regs = dev_read_addr_ptr(dev); + if (!priv->regs) { + dev_err(dev, "Fail to get base address\n"); + return -EINVAL; + } + uc_priv->bank_name = "GPIO"; + uc_priv->gpio_count = data->gpio_count; + uc_priv->gpio_base = data->gpio_base; + + ret = clk_get_bulk(dev, &clks); + if (ret) { + dev_err(dev, "Fail to get bulk clks\n"); + return ret; + } + ret = clk_enable_bulk(&clks); + if (ret) { + dev_err(dev, "Fail to enable bulk clks\n"); + goto out; + } + return 0; +out: + clk_release_bulk(&clks); + return ret; +} + +static const struct spacemit_gpio_data k1_gpio_data = { + .num_banks = 4, + .gpio_count = 128, + .gpio_base = 0, +}; + +static const struct udevice_id spacemit_gpio_ids[] = { + { .compatible = "spacemit,k1-gpio", .data = (uintptr_t)&k1_gpio_data, }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(k1_gpio) = { + .name = "spacemit_k1_gpio", + .id = UCLASS_GPIO, + .of_match = spacemit_gpio_ids, + .ops = &spacemit_gpio_ops, + .priv_auto = sizeof(struct spacemit_gpio_priv), + .probe = spacemit_gpio_probe, +}; diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index 5f6586c78ba..0e8b2408376 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -797,6 +797,13 @@ config SYS_I2C_IHS help Support for gdsys IHS I2C driver on FPGA bus. +config SYS_I2C_SPACEMIT_K1 + bool "Spacemit K1 I2C driver" + depends on DM_I2C + help + Support for Spacemit I2C controller. It's based on + Driver Model. + source "drivers/i2c/muxes/Kconfig" endif diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index 2da649e97d3..0e3a0f9fb5f 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -47,6 +47,7 @@ obj-$(CONFIG_SYS_I2C_RZ_RIIC) += rz_riic.o obj-$(CONFIG_SYS_I2C_S3C24X0) += s3c24x0_i2c.o exynos_hs_i2c.o obj-$(CONFIG_SYS_I2C_SANDBOX) += sandbox_i2c.o i2c-emul-uclass.o obj-$(CONFIG_SYS_I2C_SH) += sh_i2c.o +obj-$(CONFIG_SYS_I2C_SPACEMIT_K1) += k1_i2c.o obj-$(CONFIG_SYS_I2C_STM32F7) += stm32f7_i2c.o obj-$(CONFIG_SYS_I2C_SUN6I_P2WI) += sun6i_p2wi.o obj-$(CONFIG_SYS_I2C_SUN8I_RSB) += sun8i_rsb.o diff --git a/drivers/i2c/k1_i2c.c b/drivers/i2c/k1_i2c.c new file mode 100644 index 00000000000..a08ff15803d --- /dev/null +++ b/drivers/i2c/k1_i2c.c @@ -0,0 +1,523 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2023-2026 Spacemit, Inc + * Copyright (C) 2025-2026 RISCstar Ltd. + */ + +#include <asm/io.h> +#include <clk.h> +#include <dm.h> +#include <dm/device_compat.h> +#include <i2c.h> +#include <linux/delay.h> +#include <linux/iopoll.h> +#include <reset.h> +#include "k1_i2c.h" + +#define ICR_OFFSET 0x00 +#define ISR_OFFSET 0x04 +#define ISAR_OFFSET 0x08 +#define IDBR_OFFSET 0x0c +#define ILCR_OFFSET 0x10 +#define IWCR_OFFSET 0x14 +#define IRCR_OFFSET 0x18 +#define IBMR_OFFSET 0x1c +#define WFIFO_OFFSET 0x20 +#define WFIFO_WPTR_OFFSET 0x24 +#define WFIFO_RPTR_OFFSET 0x28 +#define RFIFO_OFFSET 0x2c +#define RFIFO_WPTR_OFFSET 0x30 +#define RFIFO_RPTR_OFFSET 0x34 + +/* All transfers are described by this data structure */ +struct k1_i2c_msg { + u8 condition; + u8 acknack; + u8 direction; + u8 data; +}; + +struct k1_i2c { + u32 icr; + u32 isr; + u32 isar; + u32 idbr; + u32 ilcr; + u32 iwcr; + u32 irst_cyc; + u32 ibmr; +}; + +struct k1_i2c_priv { + int id; + void __iomem *base; + struct clk clk; + u32 clk_rate; +}; + +/* + * i2c_reset: - reset the host controller + * + */ +static void i2c_reset(void __iomem *base) +{ + u32 icr_mode; + u32 val; + + /* Save bus mode (standard or fast speed) for later use */ + icr_mode = readl(base + ICR_OFFSET) & ICR_MODE_MASK; + /* disable unit */ + val = readl(base + ICR_OFFSET); + writel(val & ~ICR_IUE, base + ICR_OFFSET); + udelay(10); + /* reset the unit */ + val = readl(base + ICR_OFFSET); + val |= ICR_UR; + writel(val, base + ICR_OFFSET); + udelay(100); + /* disable unit */ + val = readl(base + ICR_OFFSET); + writel(val & ~ICR_IUE, base + ICR_OFFSET); + + /* set slave address */ + writel(0x00, base + ISR_OFFSET); + /* set control reg values */ + writel(I2C_ICR_INIT | icr_mode, base + ICR_OFFSET); + writel(I2C_ISR_INIT, base + ISR_OFFSET); /* set clear interrupt bits */ + val = readl(base + ICR_OFFSET); + val |= ICR_IUE; + writel(val, base + ICR_OFFSET); /* enable unit */ + udelay(100); +} + +static inline bool is_isr_set_or_clr(unsigned long isr, unsigned long set_mask, + unsigned long clr_mask) +{ + return ((isr & set_mask) == set_mask) && ((isr & clr_mask) == 0); +} + +/* + * i2c_isr_set_cleared: - wait until certain bits of the I2C status register + * are set and cleared + * + * @return: 0 on success or -ETIMEDOUT. + */ +static int i2c_isr_set_cleared(void __iomem *base, unsigned long set_mask, + unsigned long clr_mask) +{ + int cnt = 1000, delay = 10, isr, ret; + + ret = read_poll_timeout(readl, isr, + is_isr_set_or_clr(isr, set_mask, clr_mask), + delay, delay * cnt, base + ISR_OFFSET); + return ret; +} + +/* + * i2c_transfer: - Transfer one byte over the i2c bus + * + * This function can transfer a byte over the i2c bus in both directions. + * It is used by the public API functions. + * + * @return: 0: transfer successful or error code + */ +static int i2c_transfer(void __iomem *base, struct k1_i2c_msg *msg) +{ + int ret; + u32 val; + + if (!msg) + goto transfer_error_msg_empty; + + switch (msg->direction) { + case I2C_WRITE: + /* check if bus is not busy */ + if (i2c_isr_set_cleared(base, 0, ISR_IBB)) + goto transfer_error_bus_busy; + + /* start transmission */ + val = readl(base + ICR_OFFSET); + val &= ~ICR_START; + writel(val, base + ICR_OFFSET); + val = readl(base + ICR_OFFSET); + val &= ~ICR_STOP; + writel(val, base + ICR_OFFSET); + writel(msg->data, base + IDBR_OFFSET); + if (msg->condition == I2C_COND_START) { + val = readl(base + ICR_OFFSET); + val |= ICR_START; + writel(val, base + ICR_OFFSET); + } + if (msg->condition == I2C_COND_STOP) { + val = readl(base + ICR_OFFSET); + val |= ICR_STOP; + writel(val, base + ICR_OFFSET); + } + if (msg->acknack == I2C_ACKNAK_SENDNAK) { + val = readl(base + ICR_OFFSET); + val |= ICR_ACKNAK; + writel(val, base + ICR_OFFSET); + } + if (msg->acknack == I2C_ACKNAK_SENDACK) { + val = readl(base + ICR_OFFSET); + val &= ~ICR_ACKNAK; + writel(val, base + ICR_OFFSET); + } + val = readl(base + ICR_OFFSET); + val &= ~ICR_ALDIE; + writel(val, base + ICR_OFFSET); + val = readl(base + ICR_OFFSET); + val |= ICR_TB; + writel(val, base + ICR_OFFSET); + + /* transmit register empty? */ + if (i2c_isr_set_cleared(base, ISR_ITE, 0)) + goto transfer_error_transmit_timeout; + + /* clear 'transmit empty' state */ + val = readl(base + ISR_OFFSET); + val |= ISR_ITE; + writel(val, base + ISR_OFFSET); + + /* wait for ACK from slave */ + if (msg->acknack == I2C_ACKNAK_WAITACK) + if (i2c_isr_set_cleared(base, 0, ISR_ACKNAK)) + goto transfer_error_ack_missing; + break; + + case I2C_READ: + /* check if bus is not busy */ + if (i2c_isr_set_cleared(base, 0, ISR_IBB)) + goto transfer_error_bus_busy; + + /* start receive */ + val = readl(base + ICR_OFFSET); + val &= ~ICR_START; + writel(val, base + ICR_OFFSET); + val = readl(base + ICR_OFFSET); + val &= ~ICR_STOP; + writel(val, base + ICR_OFFSET); + if (msg->condition == I2C_COND_START) { + val = readl(base + ICR_OFFSET); + val |= ICR_START; + writel(val, base + ICR_OFFSET); + } + if (msg->condition == I2C_COND_STOP) { + val = readl(base + ICR_OFFSET); + val |= ICR_STOP; + writel(val, base + ICR_OFFSET); + } + if (msg->acknack == I2C_ACKNAK_SENDNAK) { + val = readl(base + ICR_OFFSET); + val |= ICR_ACKNAK; + writel(val, base + ICR_OFFSET); + } + if (msg->acknack == I2C_ACKNAK_SENDACK) { + val = readl(base + ICR_OFFSET); + val &= ~ICR_ACKNAK; + writel(val, base + ICR_OFFSET); + } + val = readl(base + ICR_OFFSET); + val &= ~ICR_ALDIE; + writel(val, base + ICR_OFFSET); + val = readl(base + ICR_OFFSET); + val |= ICR_TB; + writel(val, base + ICR_OFFSET); + + /* receive register full? */ + if (i2c_isr_set_cleared(base, ISR_IRF, 0)) + goto transfer_error_receive_timeout; + + msg->data = readl(base + IDBR_OFFSET); + + /* clear 'receive empty' state */ + val = readl(base + ISR_OFFSET); + val |= ISR_IRF; + writel(val, base + ISR_OFFSET); + break; + default: + goto transfer_error_illegal_param; + } + + return 0; + +transfer_error_msg_empty: + debug("%s: error: 'msg' is empty\n", __func__); + ret = -EINVAL; + goto i2c_transfer_finish; + +transfer_error_transmit_timeout: + debug("%s: error: transmit timeout\n", __func__); + ret = -ETIMEDOUT; + goto i2c_transfer_finish; + +transfer_error_ack_missing: + debug("%s: error: ACK missing\n", __func__); + ret = -EREMOTEIO; + goto i2c_transfer_finish; + +transfer_error_receive_timeout: + debug("%s: error: receive timeout\n", __func__); + ret = -ETIMEDOUT; + goto i2c_transfer_finish; + +transfer_error_illegal_param: + debug("%s: error: illegal parameters\n", __func__); + ret = -EINVAL; + goto i2c_transfer_finish; + +transfer_error_bus_busy: + debug("%s: error: bus is busy\n", __func__); + ret = -EIO; + goto i2c_transfer_finish; + +i2c_transfer_finish: + debug("%s: ISR: 0x%04x\n", __func__, readl(base + ISR_OFFSET)); + i2c_reset(base); + return ret; +} + +static int __i2c_read(void __iomem *base, uchar chip, u8 *addr, int alen, + uchar *buffer, int len) +{ + struct k1_i2c_msg msg; + int ret; + + debug("%s(chip=0x%02x, addr=0x%02x, alen=0x%02x, len=0x%02x)\n", + __func__, chip, *addr, alen, len); + + if (len == 0) { + pr_err("reading zero byte is invalid\n"); + return -EINVAL; + } + + i2c_reset(base); + + /* dummy chip address write */ + debug("%s: dummy chip address write\n", __func__); + msg.condition = I2C_COND_START; + msg.acknack = I2C_ACKNAK_WAITACK; + msg.direction = I2C_WRITE; + msg.data = (chip << 1); + msg.data &= 0xFE; + ret = i2c_transfer(base, &msg); + if (ret) + return ret; + + /* + * send memory address bytes; + * alen defines how much bytes we have to send. + */ + while (--alen >= 0) { + debug("%s: send address byte %02x (alen=%d)\n", + __func__, *addr, alen); + msg.condition = I2C_COND_NORMAL; + msg.acknack = I2C_ACKNAK_WAITACK; + msg.direction = I2C_WRITE; + msg.data = addr[alen]; + ret = i2c_transfer(base, &msg); + if (ret) + return ret; + } + + /* start read sequence */ + debug("%s: start read sequence\n", __func__); + msg.condition = I2C_COND_START; + msg.acknack = I2C_ACKNAK_WAITACK; + msg.direction = I2C_WRITE; + msg.data = (chip << 1); + msg.data |= 0x01; + ret = i2c_transfer(base, &msg); + if (ret) + return ret; + + /* read bytes; send NACK at last byte */ + while (len--) { + if (len == 0) { + msg.condition = I2C_COND_STOP; + msg.acknack = I2C_ACKNAK_SENDNAK; + } else { + msg.condition = I2C_COND_NORMAL; + msg.acknack = I2C_ACKNAK_SENDACK; + } + + msg.direction = I2C_READ; + msg.data = 0x00; + ret = i2c_transfer(base, &msg); + if (ret) + return ret; + + *buffer = msg.data; + debug("%s: reading byte (%p)=0x%02x\n", + __func__, buffer, *buffer); + buffer++; + } + + i2c_reset(base); + + return 0; +} + +static int __i2c_write(struct k1_i2c *base, uchar chip, u8 *addr, int alen, + uchar *buffer, int len) +{ + struct k1_i2c_msg msg; + int ret; + + debug("%s(chip=0x%02x, addr=0x%02x, alen=0x%02x, len=0x%02x)\n", + __func__, chip, *addr, alen, len); + + i2c_reset(base); + + /* chip address write */ + debug("%s: chip address write\n", __func__); + msg.condition = I2C_COND_START; + msg.acknack = I2C_ACKNAK_WAITACK; + msg.direction = I2C_WRITE; + msg.data = (chip << 1); + msg.data &= 0xFE; + ret = i2c_transfer(base, &msg); + if (ret) + return ret; + + /* + * send memory address bytes; + * alen defines how much bytes we have to send. + */ + while (--alen >= 0) { + debug("%s: send address byte %02x (alen=%d)\n", + __func__, *addr, alen); + msg.condition = I2C_COND_NORMAL; + msg.acknack = I2C_ACKNAK_WAITACK; + msg.direction = I2C_WRITE; + msg.data = addr[alen]; + ret = i2c_transfer(base, &msg); + if (ret) + return ret; + } + + /* write bytes; send NACK at last byte */ + while (len--) { + debug("%s: writing byte (%p)=0x%02x\n", + __func__, buffer, *buffer); + + if (len == 0) + msg.condition = I2C_COND_STOP; + else + msg.condition = I2C_COND_NORMAL; + + msg.acknack = I2C_ACKNAK_WAITACK; + msg.direction = I2C_WRITE; + msg.data = *(buffer++); + + ret = i2c_transfer(base, &msg); + if (ret) + return ret; + } + + i2c_reset(base); + + return 0; +} + +static int k1_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs) +{ + struct k1_i2c_priv *i2c = dev_get_priv(bus); + struct i2c_msg *dmsg, *omsg, dummy; + + memset(&dummy, 0, sizeof(struct i2c_msg)); + + /* + * We expect either two messages (one with an offset and one with the + * actual data) or one message (just data or offset/data combined) + */ + if (nmsgs > 2 || nmsgs == 0) { + debug("%s: Only one or two messages are supported.", __func__); + return -EINVAL; + } + + omsg = nmsgs == 1 ? &dummy : msg; + dmsg = nmsgs == 1 ? msg : msg + 1; + + if (dmsg->flags & I2C_M_RD) + return __i2c_read(i2c->base, dmsg->addr, omsg->buf, + omsg->len, dmsg->buf, dmsg->len); + else + return __i2c_write(i2c->base, dmsg->addr, omsg->buf, + omsg->len, dmsg->buf, dmsg->len); +} + +static int k1_i2c_set_bus_speed(struct udevice *bus, unsigned int speed) +{ + struct k1_i2c_priv *priv = dev_get_priv(bus); + void __iomem *base = priv->base; + u32 val; + + if (speed > I2C_SPEED_STANDARD_RATE) + val = ICR_FM; + else + val = ICR_SM; + clrsetbits_le32(base + ICR_OFFSET, ICR_MODE_MASK, val); + + return 0; +} + +static int k1_i2c_probe(struct udevice *bus) +{ + struct k1_i2c_priv *priv = dev_get_priv(bus); + struct reset_ctl reset; + int ret; + + priv->id = dev_seq(bus); + + /* + * The upstream K1 dts intentionally omits the 'resets' property + * on i2c nodes — the apbc clock-enable path performs the + * controller reset internally as part of clock gating. Treat the + * reset lookup as optional so we work on the kernel-mainline DT. + */ + ret = reset_get_by_index(bus, 0, &reset); + if (!ret) { + reset_assert(&reset); + udelay(10); + reset_deassert(&reset); + udelay(10); + } else if (ret != -ENOENT && ret != -ENODATA) { + dev_err(bus, "%s: reset lookup failed (%d)\n", __func__, ret); + return ret; + } + + ret = clk_get_by_index(bus, 0, &priv->clk); + if (ret) + return ret; + + ret = clk_enable(&priv->clk); + if (ret && ret != -ENOSYS && ret != -EOPNOTSUPP) { + debug("%s: failed to enable clock\n", __func__); + return ret; + } + priv->clk_rate = clk_get_rate(&priv->clk); + + priv->base = (void *)devfdt_get_addr_ptr(bus); + k1_i2c_set_bus_speed(bus, priv->clk_rate); + return 0; +} + +static const struct dm_i2c_ops k1_i2c_ops = { + .xfer = k1_i2c_xfer, + .set_bus_speed = k1_i2c_set_bus_speed, +}; + +static const struct udevice_id k1_i2c_ids[] = { + { .compatible = "spacemit,k1-i2c" }, + { } +}; + +U_BOOT_DRIVER(i2c_spacemit) = { + .name = "i2c_spacemit", + .id = UCLASS_I2C, + .of_match = k1_i2c_ids, + .probe = k1_i2c_probe, + .priv_auto = sizeof(struct k1_i2c_priv), + .ops = &k1_i2c_ops, +}; diff --git a/drivers/i2c/k1_i2c.h b/drivers/i2c/k1_i2c.h new file mode 100644 index 00000000000..856947aa43b --- /dev/null +++ b/drivers/i2c/k1_i2c.h @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2023-2026 Spacemit Ltd. + * Copyright (C) 2025-2026 RISCstar Ltd. + */ + +#ifndef __SPACEMIT_I2C_H +#define __SPACEMIT_I2C_H + +/* Shall the current transfer have a start/stop condition? */ +#define I2C_COND_NORMAL 0 +#define I2C_COND_START 1 +#define I2C_COND_STOP 2 + +/* Shall the current transfer be ack/nacked or being waited for it? */ +#define I2C_ACKNAK_WAITACK 1 +#define I2C_ACKNAK_SENDACK 2 +#define I2C_ACKNAK_SENDNAK 4 + +/* Specify who shall transfer the data (master or slave) */ +#define I2C_READ 0 +#define I2C_WRITE 1 + +#if (CONFIG_SYS_I2C_SPEED == 400000) +#define I2C_ICR_INIT (ICR_FM | ICR_BEIE | ICR_IRFIE | ICR_ITEIE | \ + ICR_GCD | ICR_SCLE) +#else +#define I2C_ICR_INIT (ICR_BEIE | ICR_IRFIE | ICR_ITEIE | ICR_GCD | \ + ICR_SCLE) +#endif + +/* ----- Control register bits ---------------------------------------- */ + +#define ICR_START 0x1 /* start bit */ +#define ICR_STOP 0x2 /* stop bit */ +#define ICR_ACKNAK 0x4 /* send ACK(0) or NAK(1) */ +#define ICR_TB 0x8 /* transfer byte bit */ +#define ICR_MA BIT(12) /* master abort */ +#define ICR_SCLE BIT(13) /* master clock enable, mona SCLEA */ +#define ICR_IUE BIT(14) /* unit enable */ +#define ICR_GCD BIT(21) /* general call disable */ +#define ICR_ITEIE BIT(19) /* enable tx interrupts */ +#define ICR_IRFIE BIT(20) /* enable rx interrupts, mona: DRFIE */ +#define ICR_BEIE BIT(22) /* enable bus error ints */ +#define ICR_SSDIE BIT(24) /* slave STOP detected int enable */ +#define ICR_ALDIE BIT(18) /* enable arbitration interrupt */ +#define ICR_SADIE BIT(23) /* slave address detected int enable */ +#define ICR_UR BIT(10) /* unit reset */ +#define ICR_SM (0x0) /* Standard Mode */ +#define ICR_FM BIT(8) /* Fast Mode */ +#define ICR_MODE_MASK (0x300) /* Mode mask */ + +/* ----- Status register bits ----------------------------------------- */ + +#define ISR_RWM BIT(13) /* read/write mode */ +#define ISR_ACKNAK BIT(14) /* ack/nak status */ +#define ISR_UB BIT(15) /* unit busy */ +#define ISR_IBB BIT(16) /* bus busy */ +#define ISR_SSD BIT(24) /* slave stop detected */ +#define ISR_ALD BIT(18) /* arbitration loss detected */ +#define ISR_ITE BIT(19) /* tx buffer empty */ +#define ISR_IRF BIT(20) /* rx buffer full */ +#define ISR_GCAD BIT(21) /* general call address detected */ +#define ISR_SAD BIT(23) /* slave address detected */ +#define ISR_BED BIT(22) /* bus error no ACK/NAK */ + +#define I2C_ISR_INIT 0x1FDE000 + +#endif diff --git a/drivers/mtd/spi/Makefile b/drivers/mtd/spi/Makefile index 44e67cd913a..9a96be11e6d 100644 --- a/drivers/mtd/spi/Makefile +++ b/drivers/mtd/spi/Makefile @@ -8,14 +8,13 @@ spi-nor-y := sf_probe.o spi-nor-ids.o ifdef CONFIG_XPL_BUILD obj-$(CONFIG_SPL_SPI_BOOT) += fsl_espi_spl.o +endif + ifeq ($(CONFIG_$(PHASE_)SPI_FLASH_TINY),y) spi-nor-y += spi-nor-tiny.o else spi-nor-y += spi-nor-core.o endif -else -spi-nor-y += spi-nor-core.o -endif obj-$(CONFIG_SPI_FLASH) += spi-nor.o obj-$(CONFIG_SPI_FLASH_DATAFLASH) += sf_dataflash.o diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c index 7100b64bf22..dee03662d45 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -229,9 +229,11 @@ static int spi_flash_std_remove(struct udevice *dev) spi_mem_dirmap_destroy(flash->dirmap.rdesc); } - ret = spi_nor_remove(flash); - if (ret) - return ret; + if (CONFIG_IS_ENABLED(SPI_FLASH_SOFT_RESET)) { + ret = spi_nor_remove(flash); + if (ret) + return ret; + } if (CONFIG_IS_ENABLED(SPI_FLASH_MTD)) spi_flash_mtd_unregister(flash); diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 69ee9155a01..fd30aaeeaa8 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -440,6 +440,7 @@ source "drivers/pinctrl/nxp/Kconfig" source "drivers/pinctrl/qcom/Kconfig" source "drivers/pinctrl/renesas/Kconfig" source "drivers/pinctrl/rockchip/Kconfig" +source "drivers/pinctrl/spacemit/Kconfig" source "drivers/pinctrl/sunxi/Kconfig" source "drivers/pinctrl/tegra/Kconfig" source "drivers/pinctrl/uniphier/Kconfig" diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index 6c6e8b59122..91149796bb5 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -32,6 +32,7 @@ obj-$(CONFIG_$(PHASE_)PINCTRL_ROCKCHIP) += rockchip/ obj-$(CONFIG_PINCTRL_SANDBOX) += pinctrl-sandbox.o obj-$(CONFIG_PINCTRL_SCMI) += pinctrl-scmi.o obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o +obj-$(CONFIG_$(PHASE_)PINCTRL_SPACEMIT_K1) += spacemit/ obj-$(CONFIG_PINCTRL_STARFIVE) += starfive/ obj-$(CONFIG_PINCTRL_STI) += pinctrl-sti.o obj-$(CONFIG_PINCTRL_STM32) += pinctrl_stm32.o diff --git a/drivers/pinctrl/spacemit/Kconfig b/drivers/pinctrl/spacemit/Kconfig new file mode 100644 index 00000000000..6aab89e160c --- /dev/null +++ b/drivers/pinctrl/spacemit/Kconfig @@ -0,0 +1,9 @@ +config PINCTRL_SPACEMIT_K1 + bool "Spacemit K1 SoC pinctrl driver" + depends on PINCTRL_GENERIC && DM + help + Supports pin multiplexing control on Spacemit K1 SoCs. + + The driver is controlled by a device tree node which contains both + the GPIO definitions and pin control functions for each available + multiplex function. diff --git a/drivers/pinctrl/spacemit/Makefile b/drivers/pinctrl/spacemit/Makefile new file mode 100644 index 00000000000..0dc43c72cb1 --- /dev/null +++ b/drivers/pinctrl/spacemit/Makefile @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0 +obj-y += pinctrl-k1.o diff --git a/drivers/pinctrl/spacemit/pinctrl-k1.c b/drivers/pinctrl/spacemit/pinctrl-k1.c new file mode 100644 index 00000000000..a6a22eacac7 --- /dev/null +++ b/drivers/pinctrl/spacemit/pinctrl-k1.c @@ -0,0 +1,550 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2024 Yixun Lan <[email protected]> + * Copyright (c) 2025-2026 RISCstar Ltd. + */ + +#include <clk.h> +#include <dm/device.h> +#include <dm/device_compat.h> +#include <dm/pinctrl.h> +#include <dm/read.h> +#include <linux/bitops.h> +#include <linux/errno.h> +#include <linux/io.h> + +/* + * +---------+----------+-----------+--------+--------+----------+--------+ + * | pull | drive | schmitter | slew | edge | strong | mux | + * | up/down | strength | trigger | rate | detect | pull | mode | + * +---------+----------+-----------+--------+--------+----------+--------+ + * 3 bits 3 bits 2 bits 1 bit 3 bits 1 bit 3 bits + */ + +#define PAD_MUX GENMASK(2, 0) +#define PAD_STRONG_PULL BIT(3) +#define PAD_EDGE_RISE BIT(4) +#define PAD_EDGE_FALL BIT(5) +#define PAD_EDGE_CLEAR BIT(6) +#define PAD_SLEW_RATE GENMASK(12, 11) +#define PAD_SLEW_RATE_EN BIT(7) +#define PAD_SCHMITT GENMASK(9, 8) +#define PAD_DRIVE GENMASK(12, 10) +#define PAD_PULLDOWN BIT(13) +#define PAD_PULLUP BIT(14) +#define PAD_PULL_EN BIT(15) + +#define PIN_POWER_STATE_1V8 1800 +#define PIN_POWER_STATE_3V3 3300 + +enum spacemit_pin_io_type { + IO_TYPE_NONE = 0, + IO_TYPE_1V8, + IO_TYPE_3V3, + IO_TYPE_EXTERNAL, +}; + +struct spacemit_pin_io { + unsigned int pin : 12; // 0~4095 + unsigned int io_type : 4; // 0~15 + unsigned int ds : 8; // 0~255 + unsigned int reserved : 8; +}; + +struct spacemit_pinctrl_data { + struct spacemit_pin_io *io_pins; + int nr_io_pins; + + void __iomem * (*pin_to_reg)(struct udevice *dev, unsigned int pin); + int (*get_gpio_mux)(struct udevice *dev, unsigned int pin); + int (*get_pins)(struct udevice *dev); + int (*get_functions)(struct udevice *dev); + int (*get_io_type)(struct udevice *dev, unsigned int pin); +}; + +struct spacemit_pinctrl_priv { + void __iomem *regs; + struct spacemit_pin_io *io_pins; + int nr_io_pins; +}; + +struct spacemit_pin_mux_config { + const struct spacemit_pin *pin; + u32 config; +}; + +struct spacemit_pin_drv_strength { + unsigned int val : 8; + unsigned int ma : 16; + unsigned int reserved : 8; +}; + +static char pin_name[PINNAME_SIZE]; + +/* External: IO voltage via external source, can be 1.8V or 3.3V */ +static struct spacemit_pin_io k1_io_pins[] = { + { 47, IO_TYPE_EXTERNAL, 0, }, + { 48, IO_TYPE_EXTERNAL, 0, }, + { 49, IO_TYPE_EXTERNAL, 0, }, + { 50, IO_TYPE_EXTERNAL, 0, }, + { 51, IO_TYPE_EXTERNAL, 0, }, + { 52, IO_TYPE_EXTERNAL, 0, }, + { 75, IO_TYPE_EXTERNAL, 0, }, + { 76, IO_TYPE_EXTERNAL, 0, }, + { 77, IO_TYPE_EXTERNAL, 0, }, + { 78, IO_TYPE_EXTERNAL, 0, }, + { 79, IO_TYPE_EXTERNAL, 0, }, + { 80, IO_TYPE_EXTERNAL, 0, }, + { 98, IO_TYPE_EXTERNAL, 0, }, + { 99, IO_TYPE_EXTERNAL, 0, }, + { 100, IO_TYPE_EXTERNAL, 0, }, + { 101, IO_TYPE_EXTERNAL, 0, }, + { 102, IO_TYPE_EXTERNAL, 0, }, + { 103, IO_TYPE_EXTERNAL, 0, }, + { 104, IO_TYPE_EXTERNAL, 0, }, + { 105, IO_TYPE_EXTERNAL, 0, }, + { 106, IO_TYPE_EXTERNAL, 0, }, + { 107, IO_TYPE_EXTERNAL, 0, }, + { 108, IO_TYPE_EXTERNAL, 0, }, + { 109, IO_TYPE_EXTERNAL, 0, }, +}; + +static inline int k1_get_pins(struct udevice *dev) +{ + return 128; +} + +static inline int k1_get_functions(struct udevice *dev) +{ + return 7; +} + +// The pin number equals to the gpio number. +static void __iomem *k1_pin_to_reg(struct udevice *dev, unsigned int pin) +{ + struct spacemit_pinctrl_priv *priv = dev_get_priv(dev); + unsigned int offset = 1; + + if (pin < 86) { + offset += pin; + } else if (pin < 93) { + offset += pin + 36; + } else if (pin < 98) { + offset += pin + 23; + } else if (pin == 98) { // QSPI_DAT3 + offset += 92; + } else if (pin == 99) { // QSPI_DAT2 + offset += 91; + } else if (pin == 100) { // QSPI_DAT1 + offset += 90; + } else if (pin == 101) { // QSPI_DAT0 + offset += 89; + } else if (pin == 102) { // QSPI_CLK + offset += 94; + } else if (pin == 103) { // QSPI_CS1 + offset += 93; + } else if (pin < 111) { + offset += pin + 5; + } else if (pin < 128) { + offset += pin + 19; + } else { + dev_err(dev, "Invalid pin (%u)\n", pin); + return NULL; + } + return priv->regs + (offset << 2); +} + +static int k1_get_gpio_mux(struct udevice *dev, unsigned int selector) +{ + u32 mux = 0; + + if (selector < 70) { + mux = 0; + } else if (selector < 74) { + mux = 1; + } else if (selector < 93) { + mux = 0; + } else if (selector < 104) { + mux = 1; + } else if (selector < 110) { + mux = 4; + } else if (selector < 128) { + mux = 0; + } else { + dev_err(dev, "Invalid pin (%u)\n", selector); + return -EINVAL; + } + return mux; +} + +static int k1_get_io_type(struct udevice *dev, unsigned int selector) +{ + if (selector < 47) + return IO_TYPE_1V8; + else if (selector < 53) + return IO_TYPE_EXTERNAL; + else if (selector < 75) + return IO_TYPE_1V8; + else if (selector < 81) + return IO_TYPE_EXTERNAL; + else if (selector < 98) + return IO_TYPE_1V8; + else if (selector < 110) + return IO_TYPE_EXTERNAL; + else if (selector < 128) + return IO_TYPE_1V8; + return -EINVAL; +} + +/* use IO high level output current as the table */ +static struct spacemit_pin_drv_strength spacemit_ds_1v8_tbl[4] = { + { 0, 11 }, + { 2, 21 }, + { 4, 32 }, + { 6, 42 }, +}; + +static struct spacemit_pin_drv_strength spacemit_ds_3v3_tbl[8] = { + { 0, 7 }, + { 2, 10 }, + { 4, 13 }, + { 6, 16 }, + { 1, 19 }, + { 3, 23 }, + { 5, 26 }, + { 7, 29 }, +}; + +static inline u8 spacemit_get_ds_value(struct spacemit_pin_drv_strength *tbl, + u32 num, u32 ma) +{ + int i; + + for (i = 0; i < num; i++) + if (ma <= tbl[i].ma) + return tbl[i].val; + + return tbl[num - 1].val; +} + +static inline u32 spacemit_get_ds_ma(struct spacemit_pin_drv_strength *tbl, + u32 num, u32 val) +{ + int i; + + for (i = 0; i < num; i++) + if (val == tbl[i].val) + return tbl[i].ma; + + return 0; +} + +static inline u8 spacemit_get_drive_strength(enum spacemit_pin_io_type type, + u32 ma) +{ + switch (type) { + case IO_TYPE_1V8: + return spacemit_get_ds_value(spacemit_ds_1v8_tbl, + ARRAY_SIZE(spacemit_ds_1v8_tbl), + ma); + case IO_TYPE_3V3: + return spacemit_get_ds_value(spacemit_ds_3v3_tbl, + ARRAY_SIZE(spacemit_ds_3v3_tbl), + ma); + default: + return 0; + } +} + +static inline u32 spacemit_get_drive_strength_ma(enum spacemit_pin_io_type type, + u32 value) +{ + switch (type) { + case IO_TYPE_1V8: + return spacemit_get_ds_ma(spacemit_ds_1v8_tbl, + ARRAY_SIZE(spacemit_ds_1v8_tbl), + value & 0x6); + case IO_TYPE_3V3: + return spacemit_get_ds_ma(spacemit_ds_3v3_tbl, + ARRAY_SIZE(spacemit_ds_3v3_tbl), + value); + default: + return 0; + } +} + +static inline u16 spacemit_dt_get_pin(u32 value) +{ + return value >> 16; +} + +static inline u16 spacemit_dt_get_pin_mux(u32 value) +{ + return value & GENMASK(15, 0); +} + +static int spacemit_get_pins_count(struct udevice *dev) +{ + struct spacemit_pinctrl_data *data; + + data = (struct spacemit_pinctrl_data *)dev_get_driver_data(dev); + if (!data || !data->get_pins) + return -EINVAL; + return data->get_pins(dev); +} + +static const char *spacemit_get_pin_name(struct udevice *dev, + unsigned int selector) +{ + struct spacemit_pinctrl_data *data; + unsigned int npins; + + data = (struct spacemit_pinctrl_data *)dev_get_driver_data(dev); + if (!data || !data->get_pins) + return NULL; + npins = data->get_pins(dev); + + if (selector >= npins) + snprintf(pin_name, PINNAME_SIZE, "Error"); + else + snprintf(pin_name, PINNAME_SIZE, "PIN%u", selector); + + return pin_name; +} + +static int spacemit_get_functions_count(struct udevice *dev) +{ + struct spacemit_pinctrl_data *data; + + data = (struct spacemit_pinctrl_data *)dev_get_driver_data(dev); + if (!data || !data->get_functions) + return -EINVAL; + return data->get_functions(dev); +} + +static int spacemit_get_pin_muxing(struct udevice *dev, unsigned int pin, + char *buf, int size) +{ + struct spacemit_pinctrl_data *data; + void __iomem *addr; + u32 mux, val; + + data = (struct spacemit_pinctrl_data *)dev_get_driver_data(dev); + if (!data || !data->pin_to_reg) + return -EINVAL; + + addr = data->pin_to_reg(dev, pin); + if (!addr) + return -EINVAL; + + val = readl(addr); + mux = val & PAD_MUX; + snprintf(buf, size, "[%p] 0x%08x MUX%d", addr, val, mux); + return 0; +} + +static int spacemit_pinctrl_request_gpio(struct udevice *dev, + unsigned int selector) +{ + struct spacemit_pinctrl_data *data; + void __iomem *addr; + int mux; + + data = (struct spacemit_pinctrl_data *)dev_get_driver_data(dev); + if (!data || !data->pin_to_reg || !data->get_gpio_mux) + return -EINVAL; + addr = data->pin_to_reg(dev, selector); + mux = data->get_gpio_mux(dev, selector); + if (mux < 0) { + dev_err(dev, "Invalid pin (%d)\n", selector); + return -EINVAL; + } + clrsetbits_le32(addr, PAD_MUX, mux & PAD_MUX); + return 0; +} + +static int spacemit_pinctrl_free_gpio(struct udevice *dev, + unsigned int selector) +{ + return 0; +} + +static int spacemit_pinmux_set(struct udevice *dev, unsigned int pin, + unsigned int mux) +{ + struct spacemit_pinctrl_data *data; + void __iomem *addr; + + data = (struct spacemit_pinctrl_data *)dev_get_driver_data(dev); + if (!data || !data->pin_to_reg) + return -EINVAL; + addr = data->pin_to_reg(dev, pin); + clrsetbits_le32(addr, PAD_MUX, mux & PAD_MUX); + return 0; +} + +static int spacemit_pinmux_property_set(struct udevice *dev, u32 pinmux_group) +{ + u32 pin, mux; + + pin = spacemit_dt_get_pin(pinmux_group); + mux = spacemit_dt_get_pin_mux(pinmux_group); + return spacemit_pinmux_set(dev, pin, mux); +} + +static const struct pinconf_param spacemit_pinconf_params[] = { + { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 }, + { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 }, + { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 }, + { "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, U32_MAX }, + { "power-source", PIN_CONFIG_POWER_SOURCE, U32_MAX }, +}; + +static int spacemit_pinconf_set(struct udevice *dev, unsigned int pin_selector, + unsigned int param, unsigned int argument) +{ + struct spacemit_pinctrl_data *data; + struct spacemit_pinctrl_priv *priv = dev_get_priv(dev); + void __iomem *addr; + u32 mask = 0; + unsigned int io_type; + u8 ds; + bool found; + int i; + + data = (struct spacemit_pinctrl_data *)dev_get_driver_data(dev); + if (!data || !data->pin_to_reg) + return -EINVAL; + addr = data->pin_to_reg(dev, pin_selector); + switch (param) { + case PIN_CONFIG_BIAS_DISABLE: + clrbits_le32(addr, PAD_PULLUP | PAD_PULLDOWN | PAD_PULL_EN); + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + mask = PAD_PULLDOWN | PAD_PULLUP | PAD_PULL_EN; + clrsetbits_le32(addr, mask, PAD_PULLDOWN | PAD_PULL_EN); + break; + case PIN_CONFIG_BIAS_PULL_UP: + mask = PAD_PULLDOWN | PAD_PULLUP | PAD_PULL_EN; + clrsetbits_le32(addr, mask, PAD_PULLUP | PAD_PULL_EN); + break; + case PIN_CONFIG_DRIVE_STRENGTH: + io_type = IO_TYPE_1V8; + for (i = 0; i < priv->nr_io_pins; i++) { + if (priv->io_pins[i].pin != pin_selector) + continue; + io_type = priv->io_pins[i].io_type; + break; + } + if (io_type != IO_TYPE_3V3 && io_type != IO_TYPE_1V8) { + dev_err(dev, "Invalid IO type (%d)\n", io_type); + return -EINVAL; + } + ds = spacemit_get_drive_strength(io_type, argument); + clrsetbits_le32(addr, PAD_DRIVE, ds); + break; + case PIN_CONFIG_POWER_SOURCE: + for (i = 0, found = false; i < priv->nr_io_pins; i++) { + if (priv->io_pins[i].pin != pin_selector) + continue; + if (argument == PIN_POWER_STATE_3V3) { + priv->io_pins[i].io_type = IO_TYPE_3V3; + found = true; + } else if (argument == PIN_POWER_STATE_1V8) { + priv->io_pins[i].io_type = IO_TYPE_1V8; + found = true; + } + break; + } + if (!found && argument != PIN_POWER_STATE_1V8) { + dev_err(dev, "Invalid power source (%d)\n", argument); + return -EINVAL; + } + break; + default: + return -EOPNOTSUPP; + } + return 0; +} + +static int spacemit_pinctrl_probe(struct udevice *dev) +{ + struct spacemit_pinctrl_data *data; + struct spacemit_pinctrl_priv *priv; + struct clk_bulk clks; + size_t size; + int ret; + + data = (struct spacemit_pinctrl_data *)dev_get_driver_data(dev); + priv = dev_get_priv(dev); + priv->regs = dev_read_addr_ptr(dev); + if (!priv->regs) { + dev_err(dev, "Fail to get base address\n"); + return -EINVAL; + } + priv->nr_io_pins = data->nr_io_pins; + size = priv->nr_io_pins * sizeof(struct spacemit_pin_io); + priv->io_pins = (struct spacemit_pin_io *)memdup(data->io_pins, size); + if (!priv->io_pins) { + dev_err(dev, "Fail to allocate memory\n"); + return -ENOMEM; + } + + ret = clk_get_bulk(dev, &clks); + if (ret) { + dev_err(dev, "Fail to get bulk clks\n"); + goto out_get_clk; + } + ret = clk_enable_bulk(&clks); + if (ret) { + dev_err(dev, "Fail to enable bulk clks\n"); + goto out_clks; + } + return 0; +out_clks: + clk_release_bulk(&clks); +out_get_clk: + free(priv->io_pins); + return ret; +} + +static const struct spacemit_pinctrl_data k1_pinctrl_data = { + .io_pins = k1_io_pins, + .nr_io_pins = ARRAY_SIZE(k1_io_pins), + .pin_to_reg = k1_pin_to_reg, + .get_gpio_mux = k1_get_gpio_mux, + .get_pins = k1_get_pins, + .get_functions = k1_get_functions, + .get_io_type = k1_get_io_type, +}; + +static const struct udevice_id spacemit_pinctrl_ids[] = { + { + .compatible = "spacemit,k1-pinctrl", + .data = (uintptr_t)&k1_pinctrl_data, + }, { /* sentinel */ } +}; + +static const struct pinctrl_ops spacemit_pinctrl_ops = { + .get_pins_count = spacemit_get_pins_count, + .get_pin_name = spacemit_get_pin_name, + .get_functions_count = spacemit_get_functions_count, + .get_pin_muxing = spacemit_get_pin_muxing, + .set_state = pinctrl_generic_set_state, + .gpio_request_enable = spacemit_pinctrl_request_gpio, + .gpio_disable_free = spacemit_pinctrl_free_gpio, + .pinmux_set = spacemit_pinmux_set, + .pinmux_property_set = spacemit_pinmux_property_set, + .pinconf_num_params = ARRAY_SIZE(spacemit_pinconf_params), + .pinconf_params = spacemit_pinconf_params, + .pinconf_set = spacemit_pinconf_set, +}; + +U_BOOT_DRIVER(spacemit_pinctrl) = { + .name = "spacemit_pinctrl", + .id = UCLASS_PINCTRL, + .of_match = spacemit_pinctrl_ids, + .ops = &spacemit_pinctrl_ops, + .priv_auto = sizeof(struct spacemit_pinctrl_priv), + .probe = spacemit_pinctrl_probe, +}; diff --git a/drivers/power/pmic/Kconfig b/drivers/power/pmic/Kconfig index 4bd9b4e1940..d45869cb30f 100644 --- a/drivers/power/pmic/Kconfig +++ b/drivers/power/pmic/Kconfig @@ -434,6 +434,14 @@ config PMIC_RAA215300 allows register access and will bind the sysreset driver (CONFIG_SYSRESET_RAA215300) if it is enabled. +config PMIC_SPACEMIT_P1 + bool "Enable driver for Spacemit P1 power management chip" + depends on DM_PMIC + help + The P1 PMIC integrates multiple functions including + voltage regulators, a watchdog timer, GPIO interfaces, and a + real-time clock. + config DM_PMIC_MTK_PWRAP bool "Enable driver for MediaTek PMIC Wrapper Support" help diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile index 2cda5a892fd..0ac92084221 100644 --- a/drivers/power/pmic/Makefile +++ b/drivers/power/pmic/Makefile @@ -32,6 +32,7 @@ obj-$(CONFIG_$(PHASE_)DM_PMIC_TPS80031) += tps80031.o obj-$(CONFIG_$(PHASE_)PMIC_PALMAS) += palmas.o obj-$(CONFIG_$(PHASE_)PMIC_LP873X) += lp873x.o obj-$(CONFIG_$(PHASE_)PMIC_LP87565) += lp87565.o +obj-$(CONFIG_PMIC_SPACEMIT_P1) += pmic_spacemit_p1.o obj-$(CONFIG_PMIC_STPMIC1) += stpmic1.o obj-$(CONFIG_PMIC_TPS65217) += pmic_tps65217.o obj-$(CONFIG_PMIC_TPS65219) += tps65219.o diff --git a/drivers/power/pmic/pmic_spacemit_p1.c b/drivers/power/pmic/pmic_spacemit_p1.c new file mode 100644 index 00000000000..46c5926874c --- /dev/null +++ b/drivers/power/pmic/pmic_spacemit_p1.c @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2025-2026 RISCstar Ltd. + */ + +#include <dm.h> +#include <power/pmic.h> +#include <power/spacemit_p1.h> + +static int pmic_p1_reg_count(struct udevice *dev) +{ + return P1_MAX_REGS; +} + +static int pmic_p1_write(struct udevice *dev, uint reg, const u8 *buffer, + int len) +{ + int ret; + + ret = dm_i2c_write(dev, reg, buffer, len); + if (ret) + pr_err("%s write error on register %02x\n", dev->name, reg); + + return ret; +} + +static int pmic_p1_read(struct udevice *dev, uint reg, u8 *buffer, + int len) +{ + int ret; + + ret = dm_i2c_read(dev, reg, buffer, len); + if (ret) + pr_err("%s read error on register %02x\n", dev->name, reg); + + return ret; +} + +static const struct pmic_child_info p1_children_info[] = { + { .prefix = "buck", .driver = P1_BUCK_DRIVER }, + { .prefix = "aldo", .driver = P1_ALDO_DRIVER }, + { .prefix = "dldo", .driver = P1_DLDO_DRIVER }, + { }, +}; + +static int pmic_p1_bind(struct udevice *dev) +{ + const struct pmic_child_info *p1_children_info = + (struct pmic_child_info *)dev_get_driver_data(dev); + ofnode regulators_node; + int children; + + regulators_node = dev_read_subnode(dev, "regulators"); + if (!ofnode_valid(regulators_node)) { + debug("%s regulators subnode not found\n", dev->name); + return -EINVAL; + } + + children = pmic_bind_children(dev, regulators_node, + p1_children_info); + if (!children) + debug("%s has no children (regulators)\n", dev->name); + + return 0; +} + +static int pmic_p1_probe(struct udevice *dev) +{ + return 0; +} + +static struct dm_pmic_ops pmic_p1_ops = { + .reg_count = pmic_p1_reg_count, + .read = pmic_p1_read, + .write = pmic_p1_write, +}; + +static const struct udevice_id pmic_p1_match[] = { + { + .compatible = "spacemit,p1", + .data = (ulong)&p1_children_info, + }, { + /* sentinel */ + } +}; + +U_BOOT_DRIVER(pmic_p1) = { + .name = "pmic_p1", + .id = UCLASS_PMIC, + .of_match = pmic_p1_match, + .bind = pmic_p1_bind, + .probe = pmic_p1_probe, + .ops = &pmic_p1_ops, +}; diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig index 9f80bb953e8..c3dc5d6f97b 100644 --- a/drivers/power/regulator/Kconfig +++ b/drivers/power/regulator/Kconfig @@ -600,3 +600,10 @@ config SANDBOX_PMBUS (DM_REGULATOR_PMBUS_GENERIC) and the pmbus CLI command can be exercised by the dm unit tests with no real hardware. Only useful for testing; say N on real boards. + +config DM_REGULATOR_SPACEMIT_P1 + bool "Enable driver for Spacemit P1 PMIC regulators" + depends on DM_REGULATOR && PMIC_SPACEMIT_P1 + help + Enable implementation of driver-model regulator uclass features + for regulator P1. The driver supports BUCKs, LDOs and SWITCHes. diff --git a/drivers/power/regulator/Makefile b/drivers/power/regulator/Makefile index b8599ea7fd9..3a148545387 100644 --- a/drivers/power/regulator/Makefile +++ b/drivers/power/regulator/Makefile @@ -29,6 +29,7 @@ obj-$(CONFIG_$(PHASE_)REGULATOR_RK8XX) += rk8xx.o obj-$(CONFIG_DM_REGULATOR_S2MPS11) += s2mps11_regulator.o obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o obj-$(CONFIG_DM_REGULATOR_SANDBOX) += sandbox.o +obj-$(CONFIG_DM_REGULATOR_SPACEMIT_P1) += spacemit_p1_regulator.o obj-$(CONFIG_REGULATOR_TPS65090) += tps65090_regulator.o obj-$(CONFIG_$(PHASE_)DM_REGULATOR_PALMAS) += palmas_regulator.o obj-$(CONFIG_$(PHASE_)DM_REGULATOR_PBIAS) += pbias_regulator.o diff --git a/drivers/power/regulator/spacemit_p1_regulator.c b/drivers/power/regulator/spacemit_p1_regulator.c new file mode 100644 index 00000000000..7b5eb710edf --- /dev/null +++ b/drivers/power/regulator/spacemit_p1_regulator.c @@ -0,0 +1,464 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2025-2026 RISCstar Ltd. + */ + +#include <dm.h> +#include <dm/lists.h> +#include <errno.h> +#include <log.h> +#include <power/pmic.h> +#include <power/regulator.h> +#include <power/spacemit_p1.h> + +struct p1_reg_info { + uint min_uv; + uint step_uv; + u8 vsel_reg; + u8 vsel_sleep_reg; + u8 config_reg; + u8 vsel_mask; + u8 min_sel; + u8 max_sel; +}; + +static const struct p1_reg_info p1_bucks[] = { + /* BUCK 1 */ + { 500000, 5000, P1_BUCK_VSEL(1), P1_BUCK_SVSEL(1), P1_BUCK_CTRL(1), + BUCK_VSEL_MASK, 0x00, 0xaa }, + { 1375000, 25000, P1_BUCK_VSEL(1), P1_BUCK_SVSEL(1), P1_BUCK_CTRL(1), + BUCK_VSEL_MASK, 0xab, 0xfe }, + /* BUCK 2 */ + { 500000, 5000, P1_BUCK_VSEL(2), P1_BUCK_SVSEL(2), P1_BUCK_CTRL(2), + BUCK_VSEL_MASK, 0x00, 0xaa }, + { 1375000, 25000, P1_BUCK_VSEL(2), P1_BUCK_SVSEL(2), P1_BUCK_CTRL(2), + BUCK_VSEL_MASK, 0xab, 0xfe }, + /* BUCK 3 */ + { 500000, 5000, P1_BUCK_VSEL(3), P1_BUCK_SVSEL(3), P1_BUCK_CTRL(3), + BUCK_VSEL_MASK, 0x00, 0xaa }, + { 1375000, 25000, P1_BUCK_VSEL(3), P1_BUCK_SVSEL(3), P1_BUCK_CTRL(3), + BUCK_VSEL_MASK, 0xab, 0xfe }, + /* BUCK 4 */ + { 500000, 5000, P1_BUCK_VSEL(4), P1_BUCK_SVSEL(4), P1_BUCK_CTRL(4), + BUCK_VSEL_MASK, 0x00, 0xaa }, + { 1375000, 25000, P1_BUCK_VSEL(4), P1_BUCK_SVSEL(4), P1_BUCK_CTRL(4), + BUCK_VSEL_MASK, 0xab, 0xfe }, + /* BUCK 5 */ + { 500000, 5000, P1_BUCK_VSEL(5), P1_BUCK_SVSEL(5), P1_BUCK_CTRL(5), + BUCK_VSEL_MASK, 0x00, 0xaa }, + { 1375000, 25000, P1_BUCK_VSEL(5), P1_BUCK_SVSEL(5), P1_BUCK_CTRL(5), + BUCK_VSEL_MASK, 0xab, 0xfe }, + /* BUCK 6 */ + { 500000, 5000, P1_BUCK_VSEL(6), P1_BUCK_SVSEL(6), P1_BUCK_CTRL(6), + BUCK_VSEL_MASK, 0x00, 0xaa }, + { 1375000, 25000, P1_BUCK_VSEL(6), P1_BUCK_SVSEL(6), P1_BUCK_CTRL(6), + BUCK_VSEL_MASK, 0xab, 0xfe }, +}; + +static const struct p1_reg_info p1_aldos[] = { + /* ALDO 1 */ + { 500000, 25000, P1_ALDO_VOLT(1), P1_ALDO_SVOLT(1), P1_ALDO_CTRL(1), + ALDO_VSEL_MASK, 0x0b, 0x7f }, + /* ALDO 2 */ + { 500000, 25000, P1_ALDO_VOLT(2), P1_ALDO_SVOLT(2), P1_ALDO_CTRL(2), + ALDO_VSEL_MASK, 0x0b, 0x7f }, + /* ALDO 3 */ + { 500000, 25000, P1_ALDO_VOLT(3), P1_ALDO_SVOLT(3), P1_ALDO_CTRL(3), + ALDO_VSEL_MASK, 0x0b, 0x7f }, + /* ALDO 4 */ + { 500000, 25000, P1_ALDO_VOLT(4), P1_ALDO_SVOLT(4), P1_ALDO_CTRL(4), + ALDO_VSEL_MASK, 0x0b, 0x7f }, +}; + +static const struct p1_reg_info p1_dldos[] = { + /* DLDO 1 */ + { 500000, 25000, P1_DLDO_VOLT(1), P1_DLDO_SVOLT(1), P1_DLDO_CTRL(1), + ALDO_VSEL_MASK, 0x0b, 0x7f }, + /* DLDO 2 */ + { 500000, 25000, P1_DLDO_VOLT(2), P1_DLDO_SVOLT(2), P1_DLDO_CTRL(2), + ALDO_VSEL_MASK, 0x0b, 0x7f }, + /* DLDO 3 */ + { 500000, 25000, P1_DLDO_VOLT(3), P1_DLDO_SVOLT(3), P1_DLDO_CTRL(3), + ALDO_VSEL_MASK, 0x0b, 0x7f }, + /* DLDO 4 */ + { 500000, 25000, P1_DLDO_VOLT(4), P1_DLDO_SVOLT(4), P1_DLDO_CTRL(4), + ALDO_VSEL_MASK, 0x0b, 0x7f }, + /* DLDO 5 */ + { 500000, 25000, P1_DLDO_VOLT(5), P1_DLDO_SVOLT(5), P1_DLDO_CTRL(5), + ALDO_VSEL_MASK, 0x0b, 0x7f }, + /* DLDO 6 */ + { 500000, 25000, P1_DLDO_VOLT(6), P1_DLDO_SVOLT(6), P1_DLDO_CTRL(6), + ALDO_VSEL_MASK, 0x0b, 0x7f }, + /* DLDO 7 */ + { 500000, 25000, P1_DLDO_VOLT(7), P1_DLDO_SVOLT(7), P1_DLDO_CTRL(7), + ALDO_VSEL_MASK, 0x0b, 0x7f }, +}; + +static const struct p1_reg_info *get_buck_reg(struct udevice *pmic, + int idx, int uvolt) +{ + if (idx < 0) + return NULL; + if (uvolt < 1375000) + return &p1_bucks[(idx - 1) * 2 + 0]; + return &p1_bucks[(idx - 1) * 2 + 1]; +} + +static const struct p1_reg_info *get_aldo_reg(struct udevice *pmic, + int idx, int uvolt) +{ + if (idx < 1 || idx > ARRAY_SIZE(p1_aldos)) + return NULL; + return &p1_aldos[idx - 1]; +} + +static const struct p1_reg_info *get_dldo_reg(struct udevice *pmic, + int idx, int uvolt) +{ + if (idx < 1 || idx > ARRAY_SIZE(p1_dldos)) + return NULL; + return &p1_dldos[idx - 1]; +} + +static int buck_get_value(struct udevice *dev) +{ + const struct dm_pmic_ops *ops = device_get_ops(dev->parent); + const struct p1_reg_info *info; + uint val; + int ret; + + if (!ops || !ops->read) + return -ENOSYS; + + info = get_buck_reg(dev->parent, dev->driver_data, 0); + if (!info) + return -ENOENT; + ret = pmic_reg_read(dev->parent, info->vsel_reg); + if (ret < 0) + return ret; + val = ret & info->vsel_mask; + while (val > info->max_sel) + info++; + + return info->min_uv + (val - info->min_sel) * info->step_uv; +} + +static int buck_set_value(struct udevice *dev, int uvolt) +{ + const struct dm_pmic_ops *ops = device_get_ops(dev->parent); + const struct p1_reg_info *info; + uint val; + int ret; + + if (!ops || !ops->write) + return -ENOSYS; + + info = get_buck_reg(dev->parent, dev->driver_data, uvolt); + if (!info) + return -ENOENT; + val = (uvolt - info->min_uv); + val = val / info->step_uv; + val += info->min_sel; + ret = pmic_reg_write(dev->parent, info->vsel_reg, val); + if (ret < 0) + return ret; + return 0; +} + +static int buck_get_enable(struct udevice *dev) +{ + const struct p1_reg_info *info; + int ret; + + info = get_buck_reg(dev->parent, dev->driver_data, 0); + if (!info) + return -ENOENT; + + ret = pmic_reg_read(dev->parent, info->config_reg); + if (ret < 0) + return ret; + return ret & BUCK_EN_MASK; +} + +static int buck_set_enable(struct udevice *dev, bool enable) +{ + const struct p1_reg_info *info; + uint val; + int ret; + + info = get_buck_reg(dev->parent, dev->driver_data, 0); + if (!info) + return -ENOENT; + + ret = pmic_reg_read(dev->parent, info->config_reg); + if (ret < 0) + return ret; + val = (unsigned int)ret; + val &= BUCK_EN_MASK; + + if (enable == val) + return 0; + + val = enable; + ret = pmic_clrsetbits(dev->parent, info->config_reg, BUCK_EN_MASK, val); + if (ret < 0) + return ret; + + return 0; +} + +static const struct dm_regulator_ops p1_buck_ops = { + .get_value = buck_get_value, + .set_value = buck_set_value, + .get_enable = buck_get_enable, + .set_enable = buck_set_enable, +}; + +static int p1_buck_probe(struct udevice *dev) +{ + struct dm_regulator_uclass_plat *uc_pdata; + + uc_pdata = dev_get_uclass_plat(dev); + + uc_pdata->type = REGULATOR_TYPE_BUCK; + uc_pdata->mode_count = 0; + + return 0; +} + +U_BOOT_DRIVER(p1_buck) = { + .name = P1_BUCK_DRIVER, + .id = UCLASS_REGULATOR, + .ops = &p1_buck_ops, + .probe = p1_buck_probe, +}; + +static int aldo_get_value(struct udevice *dev) +{ + const struct dm_pmic_ops *ops = device_get_ops(dev->parent); + const struct p1_reg_info *info; + uint val; + int ret; + + if (!ops || !ops->read) + return -ENOSYS; + + info = get_aldo_reg(dev->parent, dev->driver_data, 0); + if (!info) + return -ENOENT; + + ret = pmic_reg_read(dev->parent, info->vsel_reg); + if (ret < 0) + return ret; + + val = ret & info->vsel_mask; + while (val > info->max_sel) + info++; + + return info->min_uv + (val - info->min_sel) * info->step_uv; +} + +static int aldo_set_value(struct udevice *dev, int uvolt) +{ + const struct dm_pmic_ops *ops = device_get_ops(dev->parent); + const struct p1_reg_info *info; + uint val; + int ret; + + if (!ops || !ops->write) + return -ENOSYS; + + info = get_aldo_reg(dev->parent, dev->driver_data, uvolt); + if (!info) + return -ENOENT; + val = (uvolt - info->min_uv); + val = val / info->step_uv; + val += info->min_sel; + ret = pmic_reg_write(dev->parent, info->vsel_reg, val); + if (ret < 0) + return ret; + return 0; +} + +static int aldo_get_enable(struct udevice *dev) +{ + const struct p1_reg_info *info; + int ret; + + info = get_aldo_reg(dev->parent, dev->driver_data, 0); + if (!info) + return -ENOENT; + + ret = pmic_reg_read(dev->parent, info->config_reg); + if (ret < 0) + return ret; + return ret & ALDO_EN_MASK; +} + +static int aldo_set_enable(struct udevice *dev, bool enable) +{ + const struct p1_reg_info *info; + uint val; + int ret; + + info = get_aldo_reg(dev->parent, dev->driver_data, 0); + if (!info) + return -ENOENT; + + ret = pmic_reg_read(dev->parent, info->config_reg); + if (ret < 0) + return ret; + val = (unsigned int)ret; + val &= ALDO_EN_MASK; + + if (enable == val) + return 0; + + val = enable; + ret = pmic_clrsetbits(dev->parent, info->config_reg, ALDO_EN_MASK, val); + if (ret < 0) + return ret; + + return 0; +} + +static const struct dm_regulator_ops p1_aldo_ops = { + .get_value = aldo_get_value, + .set_value = aldo_set_value, + .get_enable = aldo_get_enable, + .set_enable = aldo_set_enable, +}; + +static int p1_aldo_probe(struct udevice *dev) +{ + struct dm_regulator_uclass_plat *uc_pdata; + + uc_pdata = dev_get_uclass_plat(dev); + + uc_pdata->type = REGULATOR_TYPE_LDO; + uc_pdata->mode_count = 0; + + return 0; +} + +U_BOOT_DRIVER(p1_aldo) = { + .name = P1_ALDO_DRIVER, + .id = UCLASS_REGULATOR, + .ops = &p1_aldo_ops, + .probe = p1_aldo_probe, +}; + +static int dldo_get_value(struct udevice *dev) +{ + const struct dm_pmic_ops *ops = device_get_ops(dev->parent); + const struct p1_reg_info *info; + uint val; + int ret; + + if (!ops || !ops->read) + return -ENOSYS; + + info = get_dldo_reg(dev->parent, dev->driver_data, 0); + if (!info) + return -ENOENT; + + ret = pmic_reg_read(dev->parent, info->vsel_reg); + if (ret < 0) + return ret; + + val = ret & info->vsel_mask; + while (val > info->max_sel) + info++; + + return info->min_uv + (val - info->min_sel) * info->step_uv; +} + +static int dldo_set_value(struct udevice *dev, int uvolt) +{ + const struct dm_pmic_ops *ops = device_get_ops(dev->parent); + const struct p1_reg_info *info; + uint val; + int ret; + + if (!ops || !ops->write) + return -ENOSYS; + + info = get_dldo_reg(dev->parent, dev->driver_data, uvolt); + if (!info) + return -ENOENT; + val = (uvolt - info->min_uv); + val = val / info->step_uv; + val += info->min_sel; + ret = pmic_reg_write(dev->parent, info->vsel_reg, val); + if (ret < 0) + return ret; + return 0; +} + +static int dldo_get_enable(struct udevice *dev) +{ + const struct p1_reg_info *info; + int ret; + + info = get_dldo_reg(dev->parent, dev->driver_data, 0); + if (!info) + return -ENOENT; + + ret = pmic_reg_read(dev->parent, info->config_reg); + if (ret < 0) + return ret; + return ret & DLDO_EN_MASK; +} + +static int dldo_set_enable(struct udevice *dev, bool enable) +{ + const struct p1_reg_info *info; + uint val; + int ret; + + info = get_dldo_reg(dev->parent, dev->driver_data, 0); + if (!info) + return -ENOENT; + + ret = pmic_reg_read(dev->parent, info->config_reg); + if (ret < 0) + return ret; + val = (unsigned int)ret; + val &= DLDO_EN_MASK; + + if (enable == val) + return 0; + + val = enable; + ret = pmic_clrsetbits(dev->parent, info->config_reg, DLDO_EN_MASK, val); + if (ret < 0) + return ret; + + return 0; +} + +static const struct dm_regulator_ops p1_dldo_ops = { + .get_value = dldo_get_value, + .set_value = dldo_set_value, + .get_enable = dldo_get_enable, + .set_enable = dldo_set_enable, +}; + +static int p1_dldo_probe(struct udevice *dev) +{ + struct dm_regulator_uclass_plat *uc_pdata; + + uc_pdata = dev_get_uclass_plat(dev); + + uc_pdata->type = REGULATOR_TYPE_LDO; + uc_pdata->mode_count = 0; + + return 0; +} + +U_BOOT_DRIVER(p1_dldo) = { + .name = P1_DLDO_DRIVER, + .id = UCLASS_REGULATOR, + .ops = &p1_dldo_ops, + .probe = p1_dldo_probe, +}; diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index c851354c7a5..db764ed5ace 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -279,12 +279,5 @@ config RESET_RZG2L_USBPHY_CTRL RZ/G2L SoC. This is required for USB 2.0 functionality to work on this SoC. -config RESET_SPACEMIT_K1 - bool "Support for SPACEMIT's K1 Reset driver" - depends on DM_RESET - help - Support for SPACEMIT's K1 Reset system. Basic Assert/Deassert - is supported. - source "drivers/reset/stm32/Kconfig" endmenu diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index 3fce96509cd..384f4336331 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -37,7 +37,7 @@ obj-$(CONFIG_RESET_DRA7) += reset-dra7.o obj-$(CONFIG_RESET_AT91) += reset-at91.o obj-$(CONFIG_$(PHASE_)RESET_JH7110) += reset-jh7110.o obj-$(CONFIG_RESET_RZG2L_USBPHY_CTRL) += reset-rzg2l-usbphy-ctrl.o -obj-$(CONFIG_RESET_SPACEMIT_K1) += reset-spacemit-k1.o +obj-$(CONFIG_CLK_SPACEMIT_K1) += spacemit/ obj-$(CONFIG_ARCH_STM32) += stm32/ obj-$(CONFIG_ARCH_STM32MP) += stm32/ diff --git a/drivers/reset/reset-spacemit-k1.c b/drivers/reset/reset-spacemit-k1.c deleted file mode 100644 index 613e002fc4f..00000000000 --- a/drivers/reset/reset-spacemit-k1.c +++ /dev/null @@ -1,548 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (C) 2022 Spacemit Inc. - * Copyright (C) 2025 Huan Zhou <[email protected]> - */ - -#include <asm/io.h> -#include <config.h> -#include <dm.h> -#include <dm/device_compat.h> -#include <dm/device-internal.h> -#include <dm/lists.h> -#include <dt-bindings/reset/spacemit-k1-reset.h> -#include <linux/bitops.h> -#include <reset-uclass.h> - -/* APBC register offset */ -#define APBC_UART1_CLK_RST 0x0 -#define APBC_UART2_CLK_RST 0x4 -#define APBC_GPIO_CLK_RST 0x8 -#define APBC_PWM0_CLK_RST 0xc -#define APBC_PWM1_CLK_RST 0x10 -#define APBC_PWM2_CLK_RST 0x14 -#define APBC_PWM3_CLK_RST 0x18 -#define APBC_TWSI8_CLK_RST 0x20 -#define APBC_UART3_CLK_RST 0x24 -#define APBC_RTC_CLK_RST 0x28 -#define APBC_TWSI0_CLK_RST 0x2c -#define APBC_TWSI1_CLK_RST 0x30 -#define APBC_TIMERS1_CLK_RST 0x34 -#define APBC_TWSI2_CLK_RST 0x38 -#define APBC_AIB_CLK_RST 0x3c -#define APBC_TWSI4_CLK_RST 0x40 -#define APBC_TIMERS2_CLK_RST 0x44 -#define APBC_ONEWIRE_CLK_RST 0x48 -#define APBC_TWSI5_CLK_RST 0x4c -#define APBC_DRO_CLK_RST 0x58 -#define APBC_IR_CLK_RST 0x5c -#define APBC_TWSI6_CLK_RST 0x60 -#define APBC_TWSI7_CLK_RST 0x68 -#define APBC_TSEN_CLK_RST 0x6c - -#define APBC_UART4_CLK_RST 0x70 -#define APBC_UART5_CLK_RST 0x74 -#define APBC_UART6_CLK_RST 0x78 -#define APBC_SSP3_CLK_RST 0x7c - -#define APBC_SSPA0_CLK_RST 0x80 -#define APBC_SSPA1_CLK_RST 0x84 - -#define APBC_IPC_AP2AUD_CLK_RST 0x90 -#define APBC_UART7_CLK_RST 0x94 -#define APBC_UART8_CLK_RST 0x98 -#define APBC_UART9_CLK_RST 0x9c - -#define APBC_CAN0_CLK_RST 0xa0 -#define APBC_PWM4_CLK_RST 0xa8 -#define APBC_PWM5_CLK_RST 0xac -#define APBC_PWM6_CLK_RST 0xb0 -#define APBC_PWM7_CLK_RST 0xb4 -#define APBC_PWM8_CLK_RST 0xb8 -#define APBC_PWM9_CLK_RST 0xbc -#define APBC_PWM10_CLK_RST 0xc0 -#define APBC_PWM11_CLK_RST 0xc4 -#define APBC_PWM12_CLK_RST 0xc8 -#define APBC_PWM13_CLK_RST 0xcc -#define APBC_PWM14_CLK_RST 0xd0 -#define APBC_PWM15_CLK_RST 0xd4 -#define APBC_PWM16_CLK_RST 0xd8 -#define APBC_PWM17_CLK_RST 0xdc -#define APBC_PWM18_CLK_RST 0xe0 -#define APBC_PWM19_CLK_RST 0xe4 -/* end of APBC register offset */ - -/* MPMU register offset */ -#define MPMU_WDTPCR 0x200 -/* end of MPMU register offset */ - -/* APMU register offset */ -#define APMU_JPG_CLK_RES_CTRL 0x20 -#define APMU_CSI_CCIC2_CLK_RES_CTRL 0x24 -#define APMU_ISP_CLK_RES_CTRL 0x38 -#define APMU_LCD_CLK_RES_CTRL1 0x44 -#define APMU_LCD_SPI_CLK_RES_CTRL 0x48 -#define APMU_LCD_CLK_RES_CTRL2 0x4c -#define APMU_CCIC_CLK_RES_CTRL 0x50 -#define APMU_SDH0_CLK_RES_CTRL 0x54 -#define APMU_SDH1_CLK_RES_CTRL 0x58 -#define APMU_USB_CLK_RES_CTRL 0x5c -#define APMU_QSPI_CLK_RES_CTRL 0x60 -#define APMU_USB_CLK_RES_CTRL 0x5c -#define APMU_DMA_CLK_RES_CTRL 0x64 -#define APMU_AES_CLK_RES_CTRL 0x68 -#define APMU_VPU_CLK_RES_CTRL 0xa4 -#define APMU_GPU_CLK_RES_CTRL 0xcc -#define APMU_SDH2_CLK_RES_CTRL 0xe0 -#define APMU_PMUA_MC_CTRL 0xe8 -#define APMU_PMU_CC2_AP 0x100 -#define APMU_PMUA_EM_CLK_RES_CTRL 0x104 - -#define APMU_AUDIO_CLK_RES_CTRL 0x14c -#define APMU_HDMI_CLK_RES_CTRL 0x1B8 - -#define APMU_PCIE_CLK_RES_CTRL_0 0x3cc -#define APMU_PCIE_CLK_RES_CTRL_1 0x3d4 -#define APMU_PCIE_CLK_RES_CTRL_2 0x3dc - -#define APMU_EMAC0_CLK_RES_CTRL 0x3e4 -#define APMU_EMAC1_CLK_RES_CTRL 0x3ec -/* end of APMU register offset */ - -/* APBC2 register offset */ -#define APBC2_UART1_CLK_RST 0x00 -#define APBC2_SSP2_CLK_RST 0x04 -#define APBC2_TWSI3_CLK_RST 0x08 -#define APBC2_RTC_CLK_RST 0x0c -#define APBC2_TIMERS0_CLK_RST 0x10 -#define APBC2_KPC_CLK_RST 0x14 -#define APBC2_GPIO_CLK_RST 0x1c -/* end of APBC2 register offset */ - -enum spacemit_reset_base_type { - RST_BASE_TYPE_MPMU = 0, - RST_BASE_TYPE_APMU = 1, - RST_BASE_TYPE_APBC = 2, - RST_BASE_TYPE_APBS = 3, - RST_BASE_TYPE_CIU = 4, - RST_BASE_TYPE_DCIU = 5, - RST_BASE_TYPE_DDRC = 6, - RST_BASE_TYPE_AUDC = 7, - RST_BASE_TYPE_APBC2 = 8, -}; - -struct spacemit_reset_signal { - u32 offset; - u32 mask; - u32 deassert_val; - u32 assert_val; - enum spacemit_reset_base_type type; -}; - -struct spacemit_reset_base { - void __iomem *mpmu_base; - void __iomem *apmu_base; - void __iomem *apbc_base; - void __iomem *apbs_base; - void __iomem *ciu_base; - void __iomem *dciu_base; - void __iomem *ddrc_base; - void __iomem *audio_ctrl_base; - void __iomem *apbc2_base; -}; - -struct spacemit_reset { - struct spacemit_reset_base io_base; - const struct spacemit_reset_signal *signals; -}; - -enum { - RESET_TWSI6_SPL = 0, - RESET_TWSI8_SPL, - RESET_SDH_AXI_SPL, - RESET_SDH0_SPL, - RESET_USB_AXI_SPL, - RESET_USBP1_AXI_SPL, - RESET_USB3_0_SPL, - RESET_QSPI_SPL, - RESET_QSPI_BUS_SPL, - RESET_AES_SPL, - RESET_SDH2_SPL, - RESET_NUMBER_SPL -}; - -static const struct spacemit_reset_signal - k1_reset_signals[RESET_NUMBER] = { - [RESET_UART1] = { APBC_UART1_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_UART2] = { APBC_UART2_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_GPIO] = { APBC_GPIO_CLK_RST, BIT(2), 0, - BIT(2), - RST_BASE_TYPE_APBC }, - [RESET_PWM0] = { APBC_PWM0_CLK_RST, - BIT(2) | BIT(0), - BIT(0), - BIT(2), - RST_BASE_TYPE_APBC }, - [RESET_PWM1] = { APBC_PWM1_CLK_RST, - BIT(2) | BIT(0), - BIT(0), - BIT(2), - RST_BASE_TYPE_APBC }, - [RESET_PWM2] = { APBC_PWM2_CLK_RST, - BIT(2) | BIT(0), - BIT(0), - BIT(2), - RST_BASE_TYPE_APBC }, - [RESET_PWM3] = { APBC_PWM3_CLK_RST, - BIT(2) | BIT(0), - BIT(0), - BIT(2), - RST_BASE_TYPE_APBC }, - [RESET_PWM4] = { APBC_PWM4_CLK_RST, - BIT(2) | BIT(0), - BIT(0), - BIT(2), - RST_BASE_TYPE_APBC }, - [RESET_PWM5] = { APBC_PWM5_CLK_RST, - BIT(2) | BIT(0), - BIT(0), - BIT(2), - RST_BASE_TYPE_APBC }, - [RESET_PWM6] = { APBC_PWM6_CLK_RST, - BIT(2) | BIT(0), - BIT(0), - BIT(2), - RST_BASE_TYPE_APBC }, - [RESET_PWM7] = { APBC_PWM7_CLK_RST, - BIT(2) | BIT(0), - BIT(0), - BIT(2), - RST_BASE_TYPE_APBC }, - [RESET_PWM8] = { APBC_PWM8_CLK_RST, - BIT(2) | BIT(0), - BIT(0), - BIT(2), - RST_BASE_TYPE_APBC }, - [RESET_PWM9] = { APBC_PWM9_CLK_RST, - BIT(2) | BIT(0), - BIT(0), - BIT(2), - RST_BASE_TYPE_APBC }, - [RESET_PWM10] = { APBC_PWM10_CLK_RST, - BIT(2) | BIT(0), - BIT(0), - BIT(2), - RST_BASE_TYPE_APBC }, - [RESET_PWM11] = { APBC_PWM11_CLK_RST, - BIT(2) | BIT(0), - BIT(0), - BIT(2), - RST_BASE_TYPE_APBC }, - [RESET_PWM12] = { APBC_PWM12_CLK_RST, - BIT(2) | BIT(0), - BIT(0), - BIT(2), - RST_BASE_TYPE_APBC }, - [RESET_PWM13] = { APBC_PWM13_CLK_RST, - BIT(2) | BIT(0), - BIT(0), - BIT(2), - RST_BASE_TYPE_APBC }, - [RESET_PWM14] = { APBC_PWM14_CLK_RST, - BIT(2) | BIT(0), - BIT(0), - BIT(2), - RST_BASE_TYPE_APBC }, - [RESET_PWM15] = { APBC_PWM15_CLK_RST, - BIT(2) | BIT(0), - BIT(0), - BIT(2), - RST_BASE_TYPE_APBC }, - [RESET_PWM16] = { APBC_PWM16_CLK_RST, - BIT(2) | BIT(0), - BIT(0), - BIT(2), - RST_BASE_TYPE_APBC }, - [RESET_PWM17] = { APBC_PWM17_CLK_RST, - BIT(2) | BIT(0), - BIT(0), - BIT(2), - RST_BASE_TYPE_APBC }, - [RESET_PWM18] = { APBC_PWM18_CLK_RST, - BIT(2) | BIT(0), - BIT(0), - BIT(2), - RST_BASE_TYPE_APBC }, - [RESET_PWM19] = { APBC_PWM19_CLK_RST, - BIT(2) | BIT(0), - BIT(0), - BIT(2), - RST_BASE_TYPE_APBC }, - [RESET_SSP3] = { APBC_SSP3_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_UART3] = { APBC_UART3_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_RTC] = { APBC_RTC_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_TWSI0] = { APBC_TWSI0_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_TIMERS1] = { APBC_TIMERS1_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_AIB] = { APBC_AIB_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_TIMERS2] = { APBC_TIMERS2_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_ONEWIRE] = { APBC_ONEWIRE_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_SSPA0] = { APBC_SSPA0_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_SSPA1] = { APBC_SSPA1_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_DRO] = { APBC_DRO_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_IR] = { APBC_IR_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_TWSI1] = { APBC_TWSI1_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_TSEN] = { APBC_TSEN_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_TWSI2] = { APBC_TWSI2_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_TWSI4] = { APBC_TWSI4_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_TWSI5] = { APBC_TWSI5_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_TWSI6] = { APBC_TWSI6_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_TWSI7] = { APBC_TWSI7_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_TWSI8] = { APBC_TWSI8_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_IPC_AP2AUD] = { APBC_IPC_AP2AUD_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_UART4] = { APBC_UART4_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_UART5] = { APBC_UART5_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_UART6] = { APBC_UART6_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_UART7] = { APBC_UART7_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_UART8] = { APBC_UART8_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_UART9] = { APBC_UART9_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_CAN0] = { APBC_CAN0_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - /* MPMU */ - [RESET_WDT] = { MPMU_WDTPCR, BIT(2), 0, BIT(2), RST_BASE_TYPE_MPMU }, - /* APMU */ - [RESET_JPG] = { APMU_JPG_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU }, - [RESET_CSI] = { APMU_CSI_CCIC2_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU }, - [RESET_CCIC2_PHY] = { APMU_CSI_CCIC2_CLK_RES_CTRL, - BIT(2), - BIT(2), - 0, - RST_BASE_TYPE_APMU }, - [RESET_CCIC3_PHY] = { APMU_CSI_CCIC2_CLK_RES_CTRL, - BIT(29), - BIT(29), - 0, - RST_BASE_TYPE_APMU }, - [RESET_ISP] = { APMU_ISP_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU }, - [RESET_ISP_AHB] = { APMU_ISP_CLK_RES_CTRL, BIT(3), BIT(3), 0, RST_BASE_TYPE_APMU }, - [RESET_ISP_CI] = { APMU_ISP_CLK_RES_CTRL, BIT(16), BIT(16), 0, RST_BASE_TYPE_APMU }, - [RESET_ISP_CPP] = { APMU_ISP_CLK_RES_CTRL, BIT(27), BIT(27), 0, RST_BASE_TYPE_APMU }, - [RESET_LCD] = { APMU_LCD_CLK_RES_CTRL1, BIT(4), BIT(4), 0, RST_BASE_TYPE_APMU }, - [RESET_DSI_ESC] = { APMU_LCD_CLK_RES_CTRL1, BIT(3), BIT(3), 0, RST_BASE_TYPE_APMU }, - [RESET_V2D] = { APMU_LCD_CLK_RES_CTRL1, BIT(27), BIT(27), 0, RST_BASE_TYPE_APMU }, - [RESET_MIPI] = { APMU_LCD_CLK_RES_CTRL1, BIT(15), BIT(15), 0, RST_BASE_TYPE_APMU }, - [RESET_LCD_SPI] = { APMU_LCD_SPI_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU }, - [RESET_LCD_SPI_BUS] = { APMU_LCD_SPI_CLK_RES_CTRL, - BIT(4), - BIT(4), - 0, - RST_BASE_TYPE_APMU }, - [RESET_LCD_SPI_HBUS] = { APMU_LCD_SPI_CLK_RES_CTRL, - BIT(2), - BIT(2), - 0, - RST_BASE_TYPE_APMU }, - [RESET_LCD_MCLK] = { APMU_LCD_CLK_RES_CTRL2, BIT(9), BIT(9), 0, RST_BASE_TYPE_APMU }, - [RESET_CCIC_4X] = { APMU_CCIC_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU }, - [RESET_CCIC1_PHY] = { APMU_CCIC_CLK_RES_CTRL, BIT(2), BIT(2), 0, RST_BASE_TYPE_APMU }, - [RESET_SDH_AXI] = { APMU_SDH0_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU }, - [RESET_SDH0] = { APMU_SDH0_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU }, - [RESET_SDH1] = { APMU_SDH1_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU }, - [RESET_USB_AXI] = { APMU_USB_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU }, - [RESET_USBP1_AXI] = { APMU_USB_CLK_RES_CTRL, BIT(4), BIT(4), 0, RST_BASE_TYPE_APMU }, - [RESET_USB3_0] = { APMU_USB_CLK_RES_CTRL, - BIT(9) | BIT(10) | BIT(11), - BIT(9) | BIT(10) | BIT(11), - 0, - RST_BASE_TYPE_APMU }, - [RESET_QSPI] = { APMU_QSPI_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU }, - [RESET_QSPI_BUS] = { APMU_QSPI_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU }, - [RESET_DMA] = { APMU_DMA_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU }, - [RESET_AES] = { APMU_AES_CLK_RES_CTRL, BIT(4), BIT(4), 0, RST_BASE_TYPE_APMU }, - [RESET_VPU] = { APMU_VPU_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU }, - [RESET_GPU] = { APMU_GPU_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU }, - [RESET_SDH2] = { APMU_SDH2_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU }, - [RESET_MC] = { APMU_PMUA_MC_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU }, - [RESET_EM_AXI] = { APMU_PMUA_EM_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU }, - [RESET_EM] = { APMU_PMUA_EM_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU }, - [RESET_AUDIO_SYS] = { APMU_AUDIO_CLK_RES_CTRL, - BIT(0) | BIT(2) | BIT(3), - BIT(0) | BIT(2) | BIT(3), - 0, - RST_BASE_TYPE_APMU }, - [RESET_HDMI] = { APMU_HDMI_CLK_RES_CTRL, BIT(9), BIT(9), 0, RST_BASE_TYPE_APMU }, - [RESET_PCIE0] = { APMU_PCIE_CLK_RES_CTRL_0, - BIT(3) | BIT(4) | BIT(5) | BIT(8), - BIT(3) | BIT(4) | BIT(5), - BIT(8), - RST_BASE_TYPE_APMU }, - [RESET_PCIE1] = { APMU_PCIE_CLK_RES_CTRL_1, - BIT(3) | BIT(4) | BIT(5) | BIT(8), - BIT(3) | BIT(4) | BIT(5), - BIT(8), - RST_BASE_TYPE_APMU }, - [RESET_PCIE2] = { APMU_PCIE_CLK_RES_CTRL_2, 0x138, 0x38, 0x100, RST_BASE_TYPE_APMU }, - [RESET_EMAC0] = { APMU_EMAC0_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU }, - [RESET_EMAC1] = { APMU_EMAC1_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU }, - [RESET_SEC_UART1] = { APBC2_UART1_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 }, - [RESET_SEC_SSP2] = { APBC2_SSP2_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 }, - [RESET_SEC_TWSI3] = { APBC2_TWSI3_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 }, - [RESET_SEC_RTC] = { APBC2_RTC_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 }, - [RESET_SEC_TIMERS0] = { APBC2_TIMERS0_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 }, - [RESET_SEC_KPC] = { APBC2_KPC_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 }, - [RESET_SEC_GPIO] = { APBC2_GPIO_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 }, - }; - -static u32 spacemit_reset_read(struct spacemit_reset *reset, u32 id) -{ - void __iomem *base; - - switch (reset->signals[id].type) { - case RST_BASE_TYPE_APMU: - base = reset->io_base.apmu_base; - break; - case RST_BASE_TYPE_APBC: - base = reset->io_base.apbc_base; - break; - default: - base = reset->io_base.apbc_base; - break; - } - - return readl(base + reset->signals[id].offset); -} - -static void spacemit_reset_write(struct spacemit_reset *reset, u32 value, u32 id) -{ - void __iomem *base; - - switch (reset->signals[id].type) { - case RST_BASE_TYPE_APMU: - base = reset->io_base.apmu_base; - break; - case RST_BASE_TYPE_APBC: - base = reset->io_base.apbc_base; - break; - default: - base = reset->io_base.apbc_base; - break; - } - - writel(value, base + reset->signals[id].offset); -} - -static void spacemit_reset_set(struct reset_ctl *rst, u32 id, bool assert) -{ - u32 value; - struct spacemit_reset *reset = dev_get_priv(rst->dev); - - value = spacemit_reset_read(reset, id); - - if (assert) { - value &= ~reset->signals[id].mask; - value |= reset->signals[id].assert_val; - } else { - value &= ~reset->signals[id].mask; - value |= reset->signals[id].deassert_val; - } - - spacemit_reset_write(reset, value, id); -} - -static int spacemit_reset_update(struct reset_ctl *rst, bool assert) -{ - if (rst->id < RESET_UART1 || rst->id >= RESET_NUMBER) - return 0; - - /* can not write to twsi8 */ - if (rst->id == RESET_TWSI8) - return 0; - - spacemit_reset_set(rst, rst->id, assert); - return 0; -} - -static int spacemit_reset_assert(struct reset_ctl *rst) -{ - return spacemit_reset_update(rst, true); -} - -static int spacemit_reset_deassert(struct reset_ctl *rst) -{ - return spacemit_reset_update(rst, false); -} - -static int spacemit_k1_reset_probe(struct udevice *dev) -{ - struct spacemit_reset *reset = dev_get_priv(dev); - - reset->io_base.mpmu_base = (void *)dev_remap_addr_index(dev, 0); - if (!reset->io_base.mpmu_base) { - pr_err("failed to map mpmu registers\n"); - goto out; - } - - reset->io_base.apmu_base = (void *)dev_remap_addr_index(dev, 1); - if (!reset->io_base.apmu_base) { - pr_err("failed to map apmu registers\n"); - goto out; - } - - reset->io_base.apbc_base = (void *)dev_remap_addr_index(dev, 2); - if (!reset->io_base.apbc_base) { - pr_err("failed to map apbc registers\n"); - goto out; - } - - reset->io_base.apbs_base = (void *)dev_remap_addr_index(dev, 3); - if (!reset->io_base.apbs_base) { - pr_err("failed to map apbs registers\n"); - goto out; - } - - reset->io_base.ciu_base = (void *)dev_remap_addr_index(dev, 4); - if (!reset->io_base.ciu_base) { - pr_err("failed to map ciu registers\n"); - goto out; - } - - reset->io_base.dciu_base = (void *)dev_remap_addr_index(dev, 5); - if (!reset->io_base.dciu_base) { - pr_err("failed to map dragon ciu registers\n"); - goto out; - } - - reset->io_base.ddrc_base = (void *)dev_remap_addr_index(dev, 6); - if (!reset->io_base.ddrc_base) { - pr_err("failed to map ddrc registers\n"); - goto out; - } - - reset->io_base.apbc2_base = (void *)dev_remap_addr_index(dev, 7); - if (!reset->io_base.apbc2_base) { - pr_err("failed to map apbc2 registers\n"); - goto out; - } - - reset->signals = k1_reset_signals; - -out: - return 0; -} - -const struct reset_ops k1_reset_ops = { - .rst_assert = spacemit_reset_assert, - .rst_deassert = spacemit_reset_deassert, -}; - -static const struct udevice_id k1_reset_ids[] = { - { .compatible = "spacemit,k1-reset", }, - {}, -}; - -U_BOOT_DRIVER(k1_reset) = { - .name = "spacemit,k1-reset", - .id = UCLASS_RESET, - .ops = &k1_reset_ops, - .of_match = k1_reset_ids, - .probe = spacemit_k1_reset_probe, - .priv_auto = sizeof(struct spacemit_reset), -}; diff --git a/drivers/reset/spacemit/Makefile b/drivers/reset/spacemit/Makefile new file mode 100644 index 00000000000..16722c68954 --- /dev/null +++ b/drivers/reset/spacemit/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# SpacemiT reset drivers + +obj-y += reset-spacemit-k1.o diff --git a/drivers/reset/spacemit/reset-spacemit-k1.c b/drivers/reset/spacemit/reset-spacemit-k1.c new file mode 100644 index 00000000000..129e1cc96f1 --- /dev/null +++ b/drivers/reset/spacemit/reset-spacemit-k1.c @@ -0,0 +1,289 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * SpacemiT K1 reset driver (syscon-bound). + * + * Copyright (C) 2022 Spacemit Inc. + * Copyright (C) 2025 Huan Zhou <[email protected]> + * Copyright (C) 2026 RISCstar Ltd. + */ + +#include <asm/io.h> +#include <dm.h> +#include <dm/device-internal.h> +#include <dm/lists.h> +#include <dt-bindings/clock/spacemit,k1-syscon.h> +#include <linux/bitops.h> +#include <malloc.h> +#include <reset-uclass.h> +#include <soc/spacemit/k1-reset.h> +#include <soc/spacemit/k1-syscon.h> + +/* =================================================================== + * Per-syscon reset signal tables. + * + * Indexed by the kernel-side per-syscon-local IDs from + * <dt-bindings/clock/spacemit,k1-syscon.h>. Each entry is + * (offset, assert_mask, deassert_mask): bits in assert_mask are set + * when the reset line is asserted; bits in deassert_mask are set when + * deasserted; the union (assert_mask | deassert_mask) is the set of + * bits the controller will overwrite on each transition. + * + * Layout mirrors the kernel-side K1 reset driver. + * =================================================================== + */ + +struct spacemit_k1_reset_data { + u32 offset; + u32 assert_mask; + u32 deassert_mask; +}; + +#define RESET_DATA(o, a, d) { \ + .offset = (o), .assert_mask = (a), .deassert_mask = (d) \ +} + +static const struct spacemit_k1_reset_data k1_mpmu_resets[] = { + [RESET_WDT] = RESET_DATA(MPMU_WDTPCR, BIT(2), 0), +}; + +static const struct spacemit_k1_reset_data k1_apbc_resets[] = { + [RESET_UART0] = RESET_DATA(APBC_UART1_CLK_RST, BIT(2), 0), + [RESET_UART2] = RESET_DATA(APBC_UART2_CLK_RST, BIT(2), 0), + [RESET_UART3] = RESET_DATA(APBC_UART3_CLK_RST, BIT(2), 0), + [RESET_UART4] = RESET_DATA(APBC_UART4_CLK_RST, BIT(2), 0), + [RESET_UART5] = RESET_DATA(APBC_UART5_CLK_RST, BIT(2), 0), + [RESET_UART6] = RESET_DATA(APBC_UART6_CLK_RST, BIT(2), 0), + [RESET_UART7] = RESET_DATA(APBC_UART7_CLK_RST, BIT(2), 0), + [RESET_UART8] = RESET_DATA(APBC_UART8_CLK_RST, BIT(2), 0), + [RESET_UART9] = RESET_DATA(APBC_UART9_CLK_RST, BIT(2), 0), + [RESET_GPIO] = RESET_DATA(APBC_GPIO_CLK_RST, BIT(2), 0), + [RESET_PWM0] = RESET_DATA(APBC_PWM0_CLK_RST, BIT(2), BIT(0)), + [RESET_PWM1] = RESET_DATA(APBC_PWM1_CLK_RST, BIT(2), BIT(0)), + [RESET_PWM2] = RESET_DATA(APBC_PWM2_CLK_RST, BIT(2), BIT(0)), + [RESET_PWM3] = RESET_DATA(APBC_PWM3_CLK_RST, BIT(2), BIT(0)), + [RESET_PWM4] = RESET_DATA(APBC_PWM4_CLK_RST, BIT(2), BIT(0)), + [RESET_PWM5] = RESET_DATA(APBC_PWM5_CLK_RST, BIT(2), BIT(0)), + [RESET_PWM6] = RESET_DATA(APBC_PWM6_CLK_RST, BIT(2), BIT(0)), + [RESET_PWM7] = RESET_DATA(APBC_PWM7_CLK_RST, BIT(2), BIT(0)), + [RESET_PWM8] = RESET_DATA(APBC_PWM8_CLK_RST, BIT(2), BIT(0)), + [RESET_PWM9] = RESET_DATA(APBC_PWM9_CLK_RST, BIT(2), BIT(0)), + [RESET_PWM10] = RESET_DATA(APBC_PWM10_CLK_RST, BIT(2), BIT(0)), + [RESET_PWM11] = RESET_DATA(APBC_PWM11_CLK_RST, BIT(2), BIT(0)), + [RESET_PWM12] = RESET_DATA(APBC_PWM12_CLK_RST, BIT(2), BIT(0)), + [RESET_PWM13] = RESET_DATA(APBC_PWM13_CLK_RST, BIT(2), BIT(0)), + [RESET_PWM14] = RESET_DATA(APBC_PWM14_CLK_RST, BIT(2), BIT(0)), + [RESET_PWM15] = RESET_DATA(APBC_PWM15_CLK_RST, BIT(2), BIT(0)), + [RESET_PWM16] = RESET_DATA(APBC_PWM16_CLK_RST, BIT(2), BIT(0)), + [RESET_PWM17] = RESET_DATA(APBC_PWM17_CLK_RST, BIT(2), BIT(0)), + [RESET_PWM18] = RESET_DATA(APBC_PWM18_CLK_RST, BIT(2), BIT(0)), + [RESET_PWM19] = RESET_DATA(APBC_PWM19_CLK_RST, BIT(2), BIT(0)), + [RESET_SSP3] = RESET_DATA(APBC_SSP3_CLK_RST, BIT(2), 0), + [RESET_RTC] = RESET_DATA(APBC_RTC_CLK_RST, BIT(2), 0), + [RESET_TWSI0] = RESET_DATA(APBC_TWSI0_CLK_RST, BIT(2), 0), + [RESET_TWSI1] = RESET_DATA(APBC_TWSI1_CLK_RST, BIT(2), 0), + [RESET_TWSI2] = RESET_DATA(APBC_TWSI2_CLK_RST, BIT(2), 0), + [RESET_TWSI4] = RESET_DATA(APBC_TWSI4_CLK_RST, BIT(2), 0), + [RESET_TWSI5] = RESET_DATA(APBC_TWSI5_CLK_RST, BIT(2), 0), + [RESET_TWSI6] = RESET_DATA(APBC_TWSI6_CLK_RST, BIT(2), 0), + [RESET_TWSI7] = RESET_DATA(APBC_TWSI7_CLK_RST, BIT(2), 0), + [RESET_TWSI8] = RESET_DATA(APBC_TWSI8_CLK_RST, BIT(2), 0), + [RESET_TIMERS1] = RESET_DATA(APBC_TIMERS1_CLK_RST, BIT(2), 0), + [RESET_TIMERS2] = RESET_DATA(APBC_TIMERS2_CLK_RST, BIT(2), 0), + [RESET_AIB] = RESET_DATA(APBC_AIB_CLK_RST, BIT(2), 0), + [RESET_ONEWIRE] = RESET_DATA(APBC_ONEWIRE_CLK_RST, BIT(2), 0), + [RESET_SSPA0] = RESET_DATA(APBC_SSPA0_CLK_RST, BIT(2), 0), + [RESET_SSPA1] = RESET_DATA(APBC_SSPA1_CLK_RST, BIT(2), 0), + [RESET_DRO] = RESET_DATA(APBC_DRO_CLK_RST, BIT(2), 0), + [RESET_IR] = RESET_DATA(APBC_IR_CLK_RST, BIT(2), 0), + [RESET_TSEN] = RESET_DATA(APBC_TSEN_CLK_RST, BIT(2), 0), + [RESET_IPC_AP2AUD] = RESET_DATA(APBC_IPC_AP2AUD_CLK_RST, BIT(2), 0), + [RESET_CAN0] = RESET_DATA(APBC_CAN0_CLK_RST, BIT(2), 0), +}; + +static const struct spacemit_k1_reset_data k1_apmu_resets[] = { + [RESET_CCIC_4X] = RESET_DATA(APMU_CCIC_CLK_RES_CTRL, 0, BIT(1)), + [RESET_CCIC1_PHY] = RESET_DATA(APMU_CCIC_CLK_RES_CTRL, 0, BIT(2)), + [RESET_SDH_AXI] = RESET_DATA(APMU_SDH0_CLK_RES_CTRL, 0, BIT(0)), + [RESET_SDH0] = RESET_DATA(APMU_SDH0_CLK_RES_CTRL, 0, BIT(1)), + [RESET_SDH1] = RESET_DATA(APMU_SDH1_CLK_RES_CTRL, 0, BIT(1)), + [RESET_SDH2] = RESET_DATA(APMU_SDH2_CLK_RES_CTRL, 0, BIT(1)), + [RESET_USBP1_AXI] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(4)), + [RESET_USB_AXI] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(0)), + [RESET_USB30_AHB] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(9)), + [RESET_USB30_VCC] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(10)), + [RESET_USB30_PHY] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(11)), + [RESET_QSPI] = RESET_DATA(APMU_QSPI_CLK_RES_CTRL, 0, BIT(1)), + [RESET_QSPI_BUS] = RESET_DATA(APMU_QSPI_CLK_RES_CTRL, 0, BIT(0)), + [RESET_DMA] = RESET_DATA(APMU_DMA_CLK_RES_CTRL, 0, BIT(0)), + [RESET_AES] = RESET_DATA(APMU_AES_CLK_RES_CTRL, 0, BIT(4)), + [RESET_VPU] = RESET_DATA(APMU_VPU_CLK_RES_CTRL, 0, BIT(0)), + [RESET_GPU] = RESET_DATA(APMU_GPU_CLK_RES_CTRL, 0, BIT(1)), + [RESET_EMMC] = RESET_DATA(APMU_PMUA_EM_CLK_RES_CTRL, 0, BIT(1)), + [RESET_EMMC_X] = RESET_DATA(APMU_PMUA_EM_CLK_RES_CTRL, 0, BIT(0)), + [RESET_AUDIO_SYS] = RESET_DATA(APMU_AUDIO_CLK_RES_CTRL, 0, BIT(0)), + [RESET_AUDIO_MCU] = RESET_DATA(APMU_AUDIO_CLK_RES_CTRL, 0, BIT(2)), + [RESET_AUDIO_APMU] = RESET_DATA(APMU_AUDIO_CLK_RES_CTRL, 0, BIT(3)), + [RESET_HDMI] = RESET_DATA(APMU_HDMI_CLK_RES_CTRL, 0, BIT(9)), + [RESET_PCIE0_DBI] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_0, 0, BIT(3)), + [RESET_PCIE0_SLAVE] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_0, 0, BIT(4)), + [RESET_PCIE0_MASTER] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_0, 0, BIT(5)), + [RESET_PCIE0_GLOBAL] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_0, BIT(8), 0), + [RESET_PCIE1_DBI] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_1, 0, BIT(3)), + [RESET_PCIE1_SLAVE] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_1, 0, BIT(4)), + [RESET_PCIE1_MASTER] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_1, 0, BIT(5)), + [RESET_PCIE1_GLOBAL] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_1, BIT(8), 0), + [RESET_PCIE2_DBI] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_2, 0, BIT(3)), + [RESET_PCIE2_SLAVE] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_2, 0, BIT(4)), + [RESET_PCIE2_MASTER] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_2, 0, BIT(5)), + [RESET_PCIE2_GLOBAL] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_2, BIT(8), 0), + [RESET_EMAC0] = RESET_DATA(APMU_EMAC0_CLK_RES_CTRL, 0, BIT(1)), + [RESET_EMAC1] = RESET_DATA(APMU_EMAC1_CLK_RES_CTRL, 0, BIT(1)), + [RESET_JPG] = RESET_DATA(APMU_JPG_CLK_RES_CTRL, 0, BIT(0)), + [RESET_CCIC2PHY] = RESET_DATA(APMU_CSI_CCIC2_CLK_RES_CTRL, 0, BIT(2)), + [RESET_CCIC3PHY] = RESET_DATA(APMU_CSI_CCIC2_CLK_RES_CTRL, 0, BIT(29)), + [RESET_CSI] = RESET_DATA(APMU_CSI_CCIC2_CLK_RES_CTRL, 0, BIT(1)), + [RESET_ISP] = RESET_DATA(APMU_ISP_CLK_RES_CTRL, 0, BIT(0)), + [RESET_ISP_CPP] = RESET_DATA(APMU_ISP_CLK_RES_CTRL, 0, BIT(27)), + [RESET_ISP_BUS] = RESET_DATA(APMU_ISP_CLK_RES_CTRL, 0, BIT(3)), + [RESET_ISP_CI] = RESET_DATA(APMU_ISP_CLK_RES_CTRL, 0, BIT(16)), + [RESET_DPU_MCLK] = RESET_DATA(APMU_LCD_CLK_RES_CTRL2, 0, BIT(9)), + [RESET_DPU_ESC] = RESET_DATA(APMU_LCD_CLK_RES_CTRL1, 0, BIT(3)), + [RESET_DPU_HCLK] = RESET_DATA(APMU_LCD_CLK_RES_CTRL1, 0, BIT(4)), + [RESET_DPU_SPIBUS] = RESET_DATA(APMU_LCD_SPI_CLK_RES_CTRL, 0, BIT(4)), + [RESET_DPU_SPI_HBUS] = RESET_DATA(APMU_LCD_SPI_CLK_RES_CTRL, 0, BIT(2)), + [RESET_V2D] = RESET_DATA(APMU_LCD_CLK_RES_CTRL1, 0, BIT(27)), + [RESET_MIPI] = RESET_DATA(APMU_LCD_CLK_RES_CTRL1, 0, BIT(15)), + [RESET_MC] = RESET_DATA(APMU_PMUA_MC_CTRL, 0, BIT(0)), +}; + +static const struct spacemit_k1_reset_data k1_apbc2_resets[] = { + [RESET_APBC2_UART1] = RESET_DATA(APBC2_UART1_CLK_RST, BIT(2), 0), + [RESET_APBC2_SSP2] = RESET_DATA(APBC2_SSP2_CLK_RST, BIT(2), 0), + [RESET_APBC2_TWSI3] = RESET_DATA(APBC2_TWSI3_CLK_RST, BIT(2), 0), + [RESET_APBC2_RTC] = RESET_DATA(APBC2_RTC_CLK_RST, BIT(2), 0), + [RESET_APBC2_TIMERS0] = RESET_DATA(APBC2_TIMERS0_CLK_RST, BIT(2), 0), + [RESET_APBC2_KPC] = RESET_DATA(APBC2_KPC_CLK_RST, BIT(2), 0), + [RESET_APBC2_GPIO] = RESET_DATA(APBC2_GPIO_CLK_RST, BIT(2), 0), +}; + +/* =================================================================== + * Driver + * =================================================================== + */ + +struct spacemit_k1_reset_priv { + void __iomem *base; + const struct spacemit_k1_reset_data *table; + size_t table_size; +}; + +static int spacemit_k1_reset_xfer(struct reset_ctl *rst, bool assert) +{ + struct spacemit_k1_reset_priv *priv = dev_get_priv(rst->dev); + const struct spacemit_k1_reset_data *e; + u32 v; + + if (rst->id >= priv->table_size) + return -EINVAL; + + e = &priv->table[rst->id]; + if (e->assert_mask == 0 && e->deassert_mask == 0) + return -EINVAL; /* not owned by this syscon */ + + v = readl(priv->base + e->offset); + v &= ~(e->assert_mask | e->deassert_mask); + v |= assert ? e->assert_mask : e->deassert_mask; + writel(v, priv->base + e->offset); + + return 0; +} + +static int spacemit_k1_reset_assert(struct reset_ctl *rst) +{ + return spacemit_k1_reset_xfer(rst, true); +} + +static int spacemit_k1_reset_deassert(struct reset_ctl *rst) +{ + return spacemit_k1_reset_xfer(rst, false); +} + +static int spacemit_k1_reset_request(struct reset_ctl *rst) +{ + struct spacemit_k1_reset_priv *priv = dev_get_priv(rst->dev); + + return rst->id < priv->table_size ? 0 : -EINVAL; +} + +static const struct reset_ops spacemit_k1_reset_ops = { + .request = spacemit_k1_reset_request, + .rst_assert = spacemit_k1_reset_assert, + .rst_deassert = spacemit_k1_reset_deassert, +}; + +static int spacemit_k1_reset_probe(struct udevice *dev) +{ + struct spacemit_k1_reset_priv *priv = dev_get_priv(dev); + + priv->base = (void __iomem *)dev_remap_addr(dev); + if (!priv->base) + return -ENODEV; + + return 0; +} + +U_BOOT_DRIVER(spacemit_k1_reset) = { + .name = "spacemit_k1_reset", + .id = UCLASS_RESET, + .ops = &spacemit_k1_reset_ops, + .probe = spacemit_k1_reset_probe, + .priv_auto = sizeof(struct spacemit_k1_reset_priv), + .flags = DM_FLAG_PRE_RELOC, +}; + +int spacemit_k1_reset_bind(struct udevice *parent, + enum spacemit_k1_reset_syscon syscon) +{ + struct spacemit_k1_reset_priv *priv; + struct udevice *rst_dev; + const struct spacemit_k1_reset_data *table; + size_t table_size; + int ret; + + switch (syscon) { + case SPACEMIT_K1_RESET_MPMU: + table = k1_mpmu_resets; + table_size = ARRAY_SIZE(k1_mpmu_resets); + break; + case SPACEMIT_K1_RESET_APMU: + table = k1_apmu_resets; + table_size = ARRAY_SIZE(k1_apmu_resets); + break; + case SPACEMIT_K1_RESET_APBC: + table = k1_apbc_resets; + table_size = ARRAY_SIZE(k1_apbc_resets); + break; + case SPACEMIT_K1_RESET_APBC2: + table = k1_apbc2_resets; + table_size = ARRAY_SIZE(k1_apbc2_resets); + break; + default: + return -EINVAL; + } + + ret = device_bind_driver_to_node(parent, "spacemit_k1_reset", "reset", + dev_ofnode(parent), &rst_dev); + if (ret) + return ret; + + priv = malloc(sizeof(*priv)); + if (!priv) { + device_unbind(rst_dev); + return -ENOMEM; + } + priv->table = table; + priv->table_size = table_size; + dev_set_priv(rst_dev, priv); + + return 0; +} diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c index b520c727900..0df9a4f5abd 100644 --- a/drivers/spi/designware_spi.c +++ b/drivers/spi/designware_spi.c @@ -497,6 +497,7 @@ static int dw_spi_xfer(struct udevice *dev, unsigned int bitlen, { struct udevice *bus = dev->parent; struct dw_spi_priv *priv = dev_get_priv(bus); + struct spi_slave *slave = dev_get_parent_priv(dev); const u8 *tx = dout; u8 *rx = din; int ret = 0; @@ -504,6 +505,17 @@ static int dw_spi_xfer(struct udevice *dev, unsigned int bitlen, u32 val; u32 cs; + /* Get bits_per_word from slave (set by device driver) */ + if (slave->bits_per_word >= 4 && slave->bits_per_word <= priv->max_xfer) { + priv->bits_per_word = slave->bits_per_word; + } else if (slave->bits_per_word == 0) { + priv->bits_per_word = 8; /* Default if not set */ + } else { + dev_warn(dev, "Invalid bits_per_word %u, using 8\n", + slave->bits_per_word); + priv->bits_per_word = 8; + } + /* spi core configured to do 8 bit transfers */ if (bitlen % 8) { dev_err(dev, "Non byte aligned SPI transfer.\n"); diff --git a/drivers/spi/fsl_qspi.c b/drivers/spi/fsl_qspi.c index 65ab3e306d7..5692510a558 100644 --- a/drivers/spi/fsl_qspi.c +++ b/drivers/spi/fsl_qspi.c @@ -267,6 +267,14 @@ static const struct fsl_qspi_devtype_data ls2080a_data = { .little_endian = true, }; +static const struct fsl_qspi_devtype_data spacemit_k1_data = { + .rxfifo = SZ_128, + .txfifo = SZ_256, + .ahb_buf_size = SZ_128, + .quirks = QUADSPI_QUIRK_TKT253890, + .little_endian = true, +}; + struct fsl_qspi { struct udevice *dev; void __iomem *iobase; @@ -870,6 +878,7 @@ static const struct udevice_id fsl_qspi_ids[] = { { .compatible = "fsl,ls1021a-qspi", .data = (ulong)&ls1021a_data, }, { .compatible = "fsl,ls1088a-qspi", .data = (ulong)&ls2080a_data, }, { .compatible = "fsl,ls2080a-qspi", .data = (ulong)&ls2080a_data, }, + { .compatible = "spacemit,k1-qspi", .data = (ulong)&spacemit_k1_data, }, { } }; diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h index ad7ebb1bbc9..fd116b0cebf 100644 --- a/include/asm-generic/global_data.h +++ b/include/asm-generic/global_data.h @@ -697,9 +697,9 @@ enum gd_flags { */ GD_FLG_DM_DEAD = 0x400000, /** - * @GD_FLG_BLOBLIST_READY: bloblist is ready for use + * @GD_FLG_BLOBLIST_HANDOFF: bloblist has been found. */ - GD_FLG_BLOBLIST_READY = 0x800000, + GD_FLG_BLOBLIST_HANDOFF = 0x800000, /** * @GD_FLG_HUSH_OLD_PARSER: Use hush old parser. */ diff --git a/include/bloblist.h b/include/bloblist.h index 4c578772965..fcd290eeb16 100644 --- a/include/bloblist.h +++ b/include/bloblist.h @@ -516,7 +516,7 @@ bool bloblist_exists(void); * If CONFIG_BLOBLIST_PASSAGE_MANDATORY is selected, bloblist in the incoming * standard passage is mandatorily required. * - * Sets GD_FLG_BLOBLIST_READY in global_data flags on success + * Sets GD_FLG_BLOBLIST_HANDOFF in global_data flags on success * * Return: 0 if OK, -ve on error */ diff --git a/include/configs/bananapi-f3.h b/include/configs/bananapi-f3.h deleted file mode 100644 index 97cf4d72df0..00000000000 --- a/include/configs/bananapi-f3.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (c) 2024, Kongyang Liu <[email protected]> - * - */ - -#ifndef __CONFIG_H -#define __CONFIG_H - -#define CFG_SYS_SDRAM_BASE 0x0 -#define CFG_SYS_NS16550_IER 0x40 /* UART Unit Enable */ - -#endif /* __CONFIG_H */ diff --git a/include/configs/k1.h b/include/configs/k1.h new file mode 100644 index 00000000000..e09c3594905 --- /dev/null +++ b/include/configs/k1.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (c) 2024, Kongyang Liu <[email protected]> + * Copyright (C) 2025-2026, RISCstar Ltd. + * + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +#define CFG_SYS_NS16550_CLK 14700000 +#define CFG_SYS_NS16550_IER 0x40 /* UART Unit Enable */ +#define CFG_SYS_SDRAM_BASE 0x0 + +#define RISCV_MMODE_TIMERBASE 0xe4000000 +#define RISCV_MMODE_TIMEROFF 0xbff8 +#define RISCV_MMODE_TIMER_FREQ 24000000 +#define RISCV_SMODE_TIMER_FREQ 24000000 + +#endif /* __CONFIG_H */ diff --git a/include/dt-bindings/reset/spacemit-k1-reset.h b/include/dt-bindings/reset/spacemit-k1-reset.h deleted file mode 100644 index 74db58b27ef..00000000000 --- a/include/dt-bindings/reset/spacemit-k1-reset.h +++ /dev/null @@ -1,118 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (C) 2022 Spacemit Inc. - * Copyright (C) 2025 Huan Zhou <[email protected]> - */ - -#ifndef __DT_BINDINGS_RESET_SAPCEMIT_K1_H__ -#define __DT_BINDINGS_RESET_SAPCEMIT_K1_H__ -/* APBC */ -#define RESET_UART1 1 -#define RESET_UART2 2 -#define RESET_GPIO 3 -#define RESET_PWM0 4 -#define RESET_PWM1 5 -#define RESET_PWM2 6 -#define RESET_PWM3 7 -#define RESET_PWM4 8 -#define RESET_PWM5 9 -#define RESET_PWM6 10 -#define RESET_PWM7 11 -#define RESET_PWM8 12 -#define RESET_PWM9 13 -#define RESET_PWM10 14 -#define RESET_PWM11 15 -#define RESET_PWM12 16 -#define RESET_PWM13 17 -#define RESET_PWM14 18 -#define RESET_PWM15 19 -#define RESET_PWM16 20 -#define RESET_PWM17 21 -#define RESET_PWM18 22 -#define RESET_PWM19 23 -#define RESET_SSP3 24 -#define RESET_UART3 25 -#define RESET_RTC 26 -#define RESET_TWSI0 27 -#define RESET_TIMERS1 28 -#define RESET_AIB 29 -#define RESET_TIMERS2 30 -#define RESET_ONEWIRE 31 -#define RESET_SSPA0 32 -#define RESET_SSPA1 33 -#define RESET_DRO 34 -#define RESET_IR 35 -#define RESET_TWSI1 36 -#define RESET_TSEN 37 -#define RESET_TWSI2 38 -#define RESET_TWSI4 39 -#define RESET_TWSI5 40 -#define RESET_TWSI6 41 -#define RESET_TWSI7 42 -#define RESET_TWSI8 43 -#define RESET_IPC_AP2AUD 44 -#define RESET_UART4 45 -#define RESET_UART5 46 -#define RESET_UART6 47 -#define RESET_UART7 48 -#define RESET_UART8 49 -#define RESET_UART9 50 -#define RESET_CAN0 51 - -/* MPMU */ -#define RESET_WDT 52 - -/* APMU */ -#define RESET_JPG 53 -#define RESET_CSI 54 -#define RESET_CCIC2_PHY 55 -#define RESET_CCIC3_PHY 56 -#define RESET_ISP 57 -#define RESET_ISP_AHB 58 -#define RESET_ISP_CI 59 -#define RESET_ISP_CPP 60 -#define RESET_LCD 61 -#define RESET_DSI_ESC 62 -#define RESET_V2D 63 -#define RESET_MIPI 64 -#define RESET_LCD_SPI 65 -#define RESET_LCD_SPI_BUS 66 -#define RESET_LCD_SPI_HBUS 67 -#define RESET_LCD_MCLK 68 -#define RESET_CCIC_4X 69 -#define RESET_CCIC1_PHY 70 -#define RESET_SDH_AXI 71 -#define RESET_SDH0 72 -#define RESET_SDH1 73 -#define RESET_USB_AXI 74 -#define RESET_USBP1_AXI 75 -#define RESET_USB3_0 76 -#define RESET_QSPI 77 -#define RESET_QSPI_BUS 78 -#define RESET_DMA 79 -#define RESET_AES 80 -#define RESET_VPU 81 -#define RESET_GPU 82 -#define RESET_SDH2 83 -#define RESET_MC 84 -#define RESET_EM_AXI 85 -#define RESET_EM 86 -#define RESET_AUDIO_SYS 87 -#define RESET_HDMI 88 -#define RESET_PCIE0 89 -#define RESET_PCIE1 90 -#define RESET_PCIE2 91 -#define RESET_EMAC0 92 -#define RESET_EMAC1 93 - -/* APBC2 */ -#define RESET_SEC_UART1 94 -#define RESET_SEC_SSP2 95 -#define RESET_SEC_TWSI3 96 -#define RESET_SEC_RTC 97 -#define RESET_SEC_TIMERS0 98 -#define RESET_SEC_KPC 99 -#define RESET_SEC_GPIO 100 -#define RESET_NUMBER 101 - -#endif diff --git a/include/linux/string.h b/include/linux/string.h index 850356d7c3f..986499dfc70 100644 --- a/include/linux/string.h +++ b/include/linux/string.h @@ -43,12 +43,8 @@ extern int strcmp(const char *,const char *); #ifndef __HAVE_ARCH_STRNCMP extern int strncmp(const char *,const char *,__kernel_size_t); #endif -#ifndef __HAVE_ARCH_STRCASECMP int strcasecmp(const char *s1, const char *s2); -#endif -#ifndef __HAVE_ARCH_STRNCASECMP -extern int strncasecmp(const char *s1, const char *s2, __kernel_size_t len); -#endif +int strncasecmp(const char *s1, const char *s2, __kernel_size_t len); #ifndef __HAVE_ARCH_STRCHR extern char * strchr(const char *,int); #endif @@ -63,7 +59,7 @@ extern char * strchr(const char *,int); * @c: character to search for * Return: position of @c in @s, or end of @s if not found */ -const char *strchrnul(const char *s, int c); +char *strchrnul(const char *s, int c); #ifndef __HAVE_ARCH_STRRCHR extern char * strrchr(const char *,int); @@ -75,6 +71,7 @@ extern char * strstr(const char *,const char *); #ifndef __HAVE_ARCH_STRNSTR extern char *strnstr(const char *, const char *, size_t); #endif +char *strcasestr(const char *, const char *); #ifndef __HAVE_ARCH_STRLEN extern __kernel_size_t strlen(const char *); #endif @@ -107,10 +104,6 @@ extern char * strndup(const char *, size_t); extern const char *strdup_const(const char *s); extern void kfree_const(const void *x); -#ifndef __HAVE_ARCH_STRSWAB -extern char * strswab(const char *); -#endif - #ifndef __HAVE_ARCH_MEMSET extern void * memset(void *,int,__kernel_size_t); #endif diff --git a/include/power/spacemit_p1.h b/include/power/spacemit_p1.h new file mode 100644 index 00000000000..ef5a45e8cec --- /dev/null +++ b/include/power/spacemit_p1.h @@ -0,0 +1,163 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2025-2026 RISCstar Ltd. + */ + +#ifndef __SPACEMIT_P1_H_ +#define __SPACEMIT_P1_H_ + +#define P1_MAX_REGS 0xA8 + +#define P1_REG_ID 0x0 + +#define P1_ID 0x2 + +#define P1_REG_BUCK1_CTRL 0x47 +#define P1_REG_BUCK2_CTRL 0x4a +#define P1_REG_BUCK3_CTRL 0x4d +#define P1_REG_BUCK4_CTRL 0x50 +#define P1_REG_BUCK5_CTRL 0x53 +#define P1_REG_BUCK6_CTRL 0x56 + +#define P1_REG_BUCK1_VSEL 0x48 +#define P1_REG_BUCK2_VSEL 0x4b +#define P1_REG_BUCK3_VSEL 0x4e +#define P1_REG_BUCK4_VSEL 0x51 +#define P1_REG_BUCK5_VSEL 0x54 +#define P1_REG_BUCK6_VSEL 0x57 + +#define P1_REG_BUCK1_SVSEL 0x49 +#define P1_REG_BUCK2_SVSEL 0x4c +#define P1_REG_BUCK3_SVSEL 0x4f +#define P1_REG_BUCK4_SVSEL 0x52 +#define P1_REG_BUCK5_SVSEL 0x55 +#define P1_REG_BUCK6_SVSEL 0x58 + +#define P1_BUCK_CTRL(x) (0x47 + ((x) - 1) * 3) +#define P1_BUCK_VSEL(x) (0x48 + ((x) - 1) * 3) +#define P1_BUCK_SVSEL(x) (0x49 + ((x) - 1) * 3) + +#define BUCK_VSEL_MASK 0xff +#define BUCK_EN_MASK 0x1 +#define BUCK_SVSEL_MASK 0xff + +#define P1_REG_ALDO1_CTRL 0x5b +#define P1_REG_ALDO2_CTRL 0x5e +#define P1_REG_ALDO3_CTRL 0x61 +#define P1_REG_ALDO4_CTRL 0x64 + +#define P1_REG_ALDO1_VOLT 0x5c +#define P1_REG_ALDO2_VOLT 0x5f +#define P1_REG_ALDO3_VOLT 0x62 +#define P1_REG_ALDO4_VOLT 0x65 + +#define P1_REG_ALDO1_SVOLT 0x5d +#define P1_REG_ALDO2_SVOLT 0x60 +#define P1_REG_ALDO3_SVOLT 0x63 +#define P1_REG_ALDO4_SVOLT 0x66 + +#define P1_ALDO_CTRL(x) (0x5b + ((x) - 1) * 3) +#define P1_ALDO_VOLT(x) (0x5c + ((x) - 1) * 3) +#define P1_ALDO_SVOLT(x) (0x5d + ((x) - 1) * 3) + +#define ALDO_SVSEL_MASK 0x7f +#define ALDO_EN_MASK 0x1 +#define ALDO_VSEL_MASK 0x7f + +#define P1_REG_DLDO1_CTRL 0x67 +#define P1_REG_DLDO2_CTRL 0x6a +#define P1_REG_DLDO3_CTRL 0x6d +#define P1_REG_DLDO4_CTRL 0x70 +#define P1_REG_DLDO5_CTRL 0x73 +#define P1_REG_DLDO6_CTRL 0x76 +#define P1_REG_DLDO7_CTRL 0x79 + +#define P1_REG_DLDO1_VOLT 0x68 +#define P1_REG_DLDO2_VOLT 0x6b +#define P1_REG_DLDO3_VOLT 0x6e +#define P1_REG_DLDO4_VOLT 0x71 +#define P1_REG_DLDO5_VOLT 0x74 +#define P1_REG_DLDO6_VOLT 0x77 +#define P1_REG_DLDO7_VOLT 0x7a + +#define P1_REG_DLDO1_SVOLT 0x69 +#define P1_REG_DLDO2_SVOLT 0x6c +#define P1_REG_DLDO3_SVOLT 0x6f +#define P1_REG_DLDO4_SVOLT 0x72 +#define P1_REG_DLDO5_SVOLT 0x75 +#define P1_REG_DLDO6_SVOLT 0x78 +#define P1_REG_DLDO7_SVOLT 0x7b + +#define P1_DLDO_CTRL(x) (0x67 + ((x) - 1) * 3) +#define P1_DLDO_VOLT(x) (0x68 + ((x) - 1) * 3) +#define P1_DLDO_SVOLT(x) (0x69 + ((x) - 1) * 3) + +#define DLDO_SVSEL_MASK 0x7f +#define DLDO_EN_MASK 0x1 +#define DLDO_VSEL_MASK 0x7f + +#define P1_REG_SWITCH_CTRL 0x59 +#define P1_SWTICH_EN_MASK 0x1 + +#define P1_REG_SWITCH_PWRKEY_EVENT_CTRL 0x97 +#define P1_SWITCH_PWRKEY_EVENT_EN_MSK 0xf + +#define P1_REG_SWITCH_PWRKEY_INIT_CTRL 0x9e +#define P1_SWITCH_PWRKEY_INT_EN_MSK 0xf + +/* Watchdog Timer Registers */ +#define P1_WDT_CTRL 0x44 +#define P1_PWR_CTRL0 0x7C +#define P1_PWR_CTRL2 0x7E +#define P1_PWR_CTRL2_MSK 0xff + +/* Watchdog Timer Control Bits */ +#define P1_WDT_CLEAR_STATUS 0x1 +#define P1_SW_RST 0x2 +#define P1_WDT_RESET_ENABLE 0x80 +#define P1_WDT_ENABLE 0x8 +#define P1_WDT_TIMEOUT_1S 0x0 +#define P1_WDT_TIMEOUT_4S 0x1 +#define P1_WDT_TIMEOUT_8S 0x2 +#define P1_WDT_TIMEOUT_16S 0x3 + +#define P1_RTC_TICK_CTRL 0x1d +#define P1_RTC_TICK_CTRL_MSK 0x7f + +#define P1_RTC_TICK_EVENT 0x92 +#define P1_RTC_TICK_EVENT_MSK 0x3f + +#define P1_RTC_TICK_IRQ 0x99 +#define P1_RTC_TICK_IRQ_MSK 0x3f + +#define P1_REG_ALIVE 0xab +#define P1_ALIVE_MSK 0x7 +#define SYS_REBOOT_FLAG_BIT 0x2 + +/* SWITCH ID */ +enum { + P1_ID_SWITCH1, + P1_ID_SWITCH1_PWRKEY_EVENT, + P1_ID_SWITCH1_PWRKEY_INT, + P1_ID_SWITCH_RTC_TICK_CTRL, + P1_ID_SWITCH_RTC_TICK_EVENT, + P1_ID_SWITCH_RTC_TCK_IRQ, + P1_ID_SWITCH_POWER_DOWN, + P1_ID_SWITCH_CHARGING_FLAG, +}; + +/* POWERKEY events */ +enum { + PWRKEY_RISING_EVENT = 1, + PWRKEY_FAILING_EVENT = 2, + PWRKEY_SHORT_PRESS_EVENT = 4, + PWRKEY_LONG_PRESS_EVENT = 8, +}; + +#define P1_BUCK_DRIVER "p1_buck" +#define P1_ALDO_DRIVER "p1_aldo" +#define P1_DLDO_DRIVER "p1_dldo" +#define P1_SWITCH_DRIVER "p1_switch" +#define P1_WDT_DRIVER "p1_wdt" + +#endif /* __SPACEMIT_P1_H_ */ diff --git a/include/soc/spacemit/k1-reset.h b/include/soc/spacemit/k1-reset.h new file mode 100644 index 00000000000..1dbfd6b1cb0 --- /dev/null +++ b/include/soc/spacemit/k1-reset.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * SpacemiT K1 reset driver — header interface. + * + * Copyright (C) 2026 RISCstar Ltd. + */ + +#ifndef _SOC_SPACEMIT_K1_RESET_H +#define _SOC_SPACEMIT_K1_RESET_H + +struct udevice; + +enum spacemit_k1_reset_syscon { + SPACEMIT_K1_RESET_MPMU, + SPACEMIT_K1_RESET_APMU, + SPACEMIT_K1_RESET_APBC, + SPACEMIT_K1_RESET_APBC2, +}; + +int spacemit_k1_reset_bind(struct udevice *parent, + enum spacemit_k1_reset_syscon syscon); + +#endif /* _SOC_SPACEMIT_K1_RESET_H */ diff --git a/include/soc/spacemit/k1-syscon.h b/include/soc/spacemit/k1-syscon.h new file mode 100644 index 00000000000..331cc1d35bb --- /dev/null +++ b/include/soc/spacemit/k1-syscon.h @@ -0,0 +1,149 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* SpacemiT clock and reset driver definitions for the K1 SoC */ + +#ifndef __SOC_K1_SYSCON_H__ +#define __SOC_K1_SYSCON_H__ + +/* APBS register offset */ +#define APBS_PLL1_SWCR1 0x100 +#define APBS_PLL1_SWCR2 0x104 +#define APBS_PLL1_SWCR3 0x108 +#define APBS_PLL2_SWCR1 0x118 +#define APBS_PLL2_SWCR2 0x11c +#define APBS_PLL2_SWCR3 0x120 +#define APBS_PLL3_SWCR1 0x124 +#define APBS_PLL3_SWCR2 0x128 +#define APBS_PLL3_SWCR3 0x12c + +/* MPMU register offset */ +#define MPMU_POSR 0x0010 +#define MPMU_FCCR 0x0008 +#define POSR_PLL1_LOCK BIT(27) +#define POSR_PLL2_LOCK BIT(28) +#define POSR_PLL3_LOCK BIT(29) +#define MPMU_SUCCR 0x0014 +#define MPMU_ISCCR 0x0044 +#define MPMU_WDTPCR 0x0200 +#define MPMU_RIPCCR 0x0210 +#define MPMU_ACGR 0x1024 +#define MPMU_APBCSCR 0x1050 +#define MPMU_SUCCR_1 0x10b0 + +/* APBC register offset */ +#define APBC_UART1_CLK_RST 0x00 +#define APBC_UART2_CLK_RST 0x04 +#define APBC_GPIO_CLK_RST 0x08 +#define APBC_PWM0_CLK_RST 0x0c +#define APBC_PWM1_CLK_RST 0x10 +#define APBC_PWM2_CLK_RST 0x14 +#define APBC_PWM3_CLK_RST 0x18 +#define APBC_TWSI8_CLK_RST 0x20 +#define APBC_UART3_CLK_RST 0x24 +#define APBC_RTC_CLK_RST 0x28 +#define APBC_TWSI0_CLK_RST 0x2c +#define APBC_TWSI1_CLK_RST 0x30 +#define APBC_TIMERS1_CLK_RST 0x34 +#define APBC_TWSI2_CLK_RST 0x38 +#define APBC_AIB_CLK_RST 0x3c +#define APBC_TWSI4_CLK_RST 0x40 +#define APBC_TIMERS2_CLK_RST 0x44 +#define APBC_ONEWIRE_CLK_RST 0x48 +#define APBC_TWSI5_CLK_RST 0x4c +#define APBC_DRO_CLK_RST 0x58 +#define APBC_IR_CLK_RST 0x5c +#define APBC_TWSI6_CLK_RST 0x60 +#define APBC_COUNTER_CLK_SEL 0x64 +#define APBC_TWSI7_CLK_RST 0x68 +#define APBC_TSEN_CLK_RST 0x6c +#define APBC_UART4_CLK_RST 0x70 +#define APBC_UART5_CLK_RST 0x74 +#define APBC_UART6_CLK_RST 0x78 +#define APBC_SSP3_CLK_RST 0x7c +#define APBC_SSPA0_CLK_RST 0x80 +#define APBC_SSPA1_CLK_RST 0x84 +#define APBC_IPC_AP2AUD_CLK_RST 0x90 +#define APBC_UART7_CLK_RST 0x94 +#define APBC_UART8_CLK_RST 0x98 +#define APBC_UART9_CLK_RST 0x9c +#define APBC_CAN0_CLK_RST 0xa0 +#define APBC_PWM4_CLK_RST 0xa8 +#define APBC_PWM5_CLK_RST 0xac +#define APBC_PWM6_CLK_RST 0xb0 +#define APBC_PWM7_CLK_RST 0xb4 +#define APBC_PWM8_CLK_RST 0xb8 +#define APBC_PWM9_CLK_RST 0xbc +#define APBC_PWM10_CLK_RST 0xc0 +#define APBC_PWM11_CLK_RST 0xc4 +#define APBC_PWM12_CLK_RST 0xc8 +#define APBC_PWM13_CLK_RST 0xcc +#define APBC_PWM14_CLK_RST 0xd0 +#define APBC_PWM15_CLK_RST 0xd4 +#define APBC_PWM16_CLK_RST 0xd8 +#define APBC_PWM17_CLK_RST 0xdc +#define APBC_PWM18_CLK_RST 0xe0 +#define APBC_PWM19_CLK_RST 0xe4 + +/* APMU register offset */ +#define APMU_JPG_CLK_RES_CTRL 0x020 +#define APMU_CSI_CCIC2_CLK_RES_CTRL 0x024 +#define APMU_ISP_CLK_RES_CTRL 0x038 +#define APMU_LCD_CLK_RES_CTRL1 0x044 +#define APMU_LCD_SPI_CLK_RES_CTRL 0x048 +#define APMU_LCD_CLK_RES_CTRL2 0x04c +#define APMU_CCIC_CLK_RES_CTRL 0x050 +#define APMU_SDH0_CLK_RES_CTRL 0x054 +#define APMU_SDH1_CLK_RES_CTRL 0x058 +#define APMU_USB_CLK_RES_CTRL 0x05c +#define APMU_QSPI_CLK_RES_CTRL 0x060 +#define APMU_DMA_CLK_RES_CTRL 0x064 +#define APMU_AES_CLK_RES_CTRL 0x068 +#define APMU_VPU_CLK_RES_CTRL 0x0a4 +#define APMU_GPU_CLK_RES_CTRL 0x0cc +#define APMU_SDH2_CLK_RES_CTRL 0x0e0 +#define APMU_PMUA_MC_CTRL 0x0e8 +#define APMU_PMU_CC2_AP 0x100 +#define APMU_PMUA_EM_CLK_RES_CTRL 0x104 +#define APMU_AUDIO_CLK_RES_CTRL 0x14c +#define APMU_HDMI_CLK_RES_CTRL 0x1b8 +#define APMU_CCI550_CLK_CTRL 0x300 +#define APMU_ACLK_CLK_CTRL 0x388 +#define APMU_CPU_C0_CLK_CTRL 0x38C +#define APMU_CPU_C1_CLK_CTRL 0x390 +#define APMU_PCIE_CLK_RES_CTRL_0 0x3cc +#define APMU_PCIE_CLK_RES_CTRL_1 0x3d4 +#define APMU_PCIE_CLK_RES_CTRL_2 0x3dc +#define APMU_EMAC0_CLK_RES_CTRL 0x3e4 +#define APMU_EMAC1_CLK_RES_CTRL 0x3ec + +/* RCPU register offsets */ +#define RCPU_SSP0_CLK_RST 0x0028 +#define RCPU_I2C0_CLK_RST 0x0030 +#define RCPU_UART1_CLK_RST 0x003c +#define RCPU_CAN_CLK_RST 0x0048 +#define RCPU_IR_CLK_RST 0x004c +#define RCPU_UART0_CLK_RST 0x00d8 +#define AUDIO_HDMI_CLK_CTRL 0x2044 + +/* RCPU2 register offsets */ +#define RCPU2_PWM0_CLK_RST 0x0000 +#define RCPU2_PWM1_CLK_RST 0x0004 +#define RCPU2_PWM2_CLK_RST 0x0008 +#define RCPU2_PWM3_CLK_RST 0x000c +#define RCPU2_PWM4_CLK_RST 0x0010 +#define RCPU2_PWM5_CLK_RST 0x0014 +#define RCPU2_PWM6_CLK_RST 0x0018 +#define RCPU2_PWM7_CLK_RST 0x001c +#define RCPU2_PWM8_CLK_RST 0x0020 +#define RCPU2_PWM9_CLK_RST 0x0024 + +/* APBC2 register offsets */ +#define APBC2_UART1_CLK_RST 0x0000 +#define APBC2_SSP2_CLK_RST 0x0004 +#define APBC2_TWSI3_CLK_RST 0x0008 +#define APBC2_RTC_CLK_RST 0x000c +#define APBC2_TIMERS0_CLK_RST 0x0010 +#define APBC2_KPC_CLK_RST 0x0014 +#define APBC2_GPIO_CLK_RST 0x001c + +#endif /* __SOC_K1_SYSCON_H__ */ diff --git a/include/spi.h b/include/spi.h index 7eaf0aa69b8..97096a77526 100644 --- a/include/spi.h +++ b/include/spi.h @@ -161,6 +161,7 @@ struct spi_slave { unsigned int max_write_size; void *memory_map; + u8 bits_per_word; u8 flags; #define SPI_XFER_BEGIN BIT(0) /* Assert CS before transfer */ #define SPI_XFER_END BIT(1) /* Deassert CS after transfer */ diff --git a/lib/string.c b/lib/string.c index 37ea8c29561..dbf2ce340df 100644 --- a/lib/string.c +++ b/lib/string.c @@ -263,12 +263,12 @@ char * strchr(const char * s, int c) } #endif -const char *strchrnul(const char *s, int c) +char *strchrnul(const char *s, int c) { for (; *s != (char)c; ++s) if (*s == '\0') break; - return s; + return (char *)s; } #ifndef __HAVE_ARCH_STRRCHR @@ -399,7 +399,6 @@ void kfree_const(const void *x) } -#ifndef __HAVE_ARCH_STRSPN /** * strspn - Calculate the length of the initial substring of @s which only * contain letters in @accept @@ -424,9 +423,7 @@ size_t strspn(const char *s, const char *accept) return count; } -#endif -#ifndef __HAVE_ARCH_STRPBRK /** * strpbrk - Find the first occurrence of a set of characters * @cs: The string to be searched @@ -444,9 +441,7 @@ char * strpbrk(const char * cs,const char * ct) } return NULL; } -#endif -#ifndef __HAVE_ARCH_STRTOK /** * strtok - Split a string into tokens * @s: The string to be searched @@ -473,9 +468,7 @@ char * strtok(char * s,const char * ct) ___strtok = send; return (sbegin); } -#endif -#ifndef __HAVE_ARCH_STRSEP /** * strsep - Split a string into tokens * @s: The string to be searched @@ -501,35 +494,6 @@ char * strsep(char **s, const char *ct) return sbegin; } -#endif - -#ifndef __HAVE_ARCH_STRSWAB -/** - * strswab - swap adjacent even and odd bytes in %NUL-terminated string - * s: address of the string - * - * returns the address of the swapped string or NULL on error. If - * string length is odd, last byte is untouched. - */ -char *strswab(const char *s) -{ - char *p, *q; - - if ((NULL == s) || ('\0' == *s)) { - return (NULL); - } - - for (p=(char *)s, q=p+1; (*p != '\0') && (*q != '\0'); p+=2, q+=2) { - char tmp; - - tmp = *p; - *p = *q; - *q = tmp; - } - - return (char *) s; -} -#endif #ifndef __HAVE_ARCH_MEMSET /** @@ -702,7 +666,7 @@ void *memdup(const void *src, size_t len) * * @s1: string to be searched * @s2: string to search for - * @len: maximum number of characters in s2 to consider + * @len: maximum number of characters in s1 to consider * * Return: pointer to the first occurrence or NULL */ @@ -728,7 +692,6 @@ char *strnstr(const char *s1, const char *s2, size_t len) * * @s1: string to be searched * @s2: string to search for - * @len: maximum number of characters in s2 to consider * * Return: pointer to the first occurrence or NULL */ @@ -738,6 +701,33 @@ char *strstr(const char *s1, const char *s2) } #endif +/** + * strcasestr() - Case insensitive substring search + * + * @haystack: string to be searched + * @needle: string to search for + * + * Return: pointer to the first occurrence or NULL + * + * The case of both strings are ignored. + */ +char *strcasestr(const char *haystack, const char *needle) +{ + size_t l1, l2; + + l1 = strlen(haystack); + l2 = strlen(needle); + + while (l1 >= l2) { + if (!strncasecmp(haystack, needle, l2)) + return (char *)haystack; + haystack++; + l1--; + } + + return NULL; +} + #ifndef __HAVE_ARCH_MEMCHR /** * memchr - Find a character in an area of memory. diff --git a/test/cmd/Makefile b/test/cmd/Makefile index 8d6932f1176..8d36463879d 100644 --- a/test/cmd/Makefile +++ b/test/cmd/Makefile @@ -17,6 +17,7 @@ ifdef CONFIG_CONSOLE_RECORD obj-$(CONFIG_CMD_ACPI) += acpi.o endif obj-$(CONFIG_CMD_BDI) += bdinfo.o +obj-$(CONFIG_CMD_CONFIG) += config.o obj-$(CONFIG_COREBOOT_SYSINFO) += coreboot.o obj-$(CONFIG_CMD_FDT) += fdt.o obj-$(CONFIG_CMD_HASH) += hash.o diff --git a/test/cmd/config.c b/test/cmd/config.c new file mode 100644 index 00000000000..5a48060801f --- /dev/null +++ b/test/cmd/config.c @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Tests for config command + */ + +#include <console.h> +#include <test/cmd.h> +#include <test/ut.h> + +static int cmd_test_config(struct unit_test_state *uts) +{ + ut_assertok(run_command("config", 0)); + ut_assert_skip_to_line("# Automatically generated file; DO NOT EDIT."); + ut_assert_skip_to_linen("# Compiler:"); + ut_assert_skip_to_line("CONFIG_CMD_CONFIG=y"); + + console_record_reset_enable(); + + ut_assertok(run_command("config cmd_config=y", 0)); + ut_assert_nextline("CONFIG_CMD_CONFIG=y"); + ut_assert_console_end(); + + ut_assertok(run_command("config 'this string never appears in .config'", 0)); + ut_assert_console_end(); + + return 0; +} +CMD_TEST(cmd_test_config, UTF_CONSOLE); diff --git a/test/image/spl_load.c b/test/image/spl_load.c index 3b6206955d3..c43c977f784 100644 --- a/test/image/spl_load.c +++ b/test/image/spl_load.c @@ -368,6 +368,55 @@ SPL_IMG_TEST(spl_test_image, FIT_INTERNAL, 0); SPL_IMG_TEST(spl_test_image, FIT_EXTERNAL, 0); /* + * A FIT image's data-size property is not covered by the configuration + * signature, so it is untrusted input. load_simple_fit() must reject a + * data-size larger than the destination rather than overrun it, because the + * device read happens before the image hash is verified. + */ +static int spl_test_fit_external_oversize(struct unit_test_state *uts) +{ + size_t img_size, img_data, data_size = SPL_TEST_DATA_SIZE; + struct spl_image_info info_write = { + .name = "oversize", + .size = data_size, + }, info_read = { }; + struct spl_load_info load; + void *img; + int node; + + if (!image_supported(FIT_EXTERNAL)) + return -EAGAIN; + + img_size = create_image(NULL, FIT_EXTERNAL, &info_write, &img_data); + ut_assert(img_size); + img = calloc(img_size, 1); + ut_assertnonnull(img); + + generate_data(img + img_data, data_size, "oversize"); + ut_asserteq(img_size, create_image(img, FIT_EXTERNAL, &info_write, + NULL)); + + /* + * Inflate data-size far beyond the image buffer and any plausible + * load region. Without a bounds check, load_simple_fit() reads this + * many bytes off the "device" before the hash is checked. + */ + node = fdt_path_offset(img, FIT_IMAGES_PATH); + ut_assert(node >= 0); + node = fdt_first_subnode(img, node); + ut_assert(node >= 0); + ut_assertok(fdt_setprop_inplace_u32(img, node, FIT_DATA_SIZE_PROP, + 0x40000000)); + + spl_load_init(&load, spl_test_read, img, 1); + ut_asserteq(-EFBIG, spl_load_simple_fit(&info_read, &load, 0, img)); + + free(img); + return 0; +} +SPL_TEST(spl_test_fit_external_oversize, 0); + +/* * LZMA is too complex to generate on the fly, so let's use some data I put in * the oven^H^H^H^H compressed earlier */ diff --git a/test/lib/string.c b/test/lib/string.c index db6f28dbfdf..d418a40c4d4 100644 --- a/test/lib/string.c +++ b/test/lib/string.c @@ -284,18 +284,36 @@ static int lib_strstr(struct unit_test_state *uts) { const char *s1 = "Itsy Bitsy Teenie Weenie"; const char *s2 = "eenie"; - const char *s3 = "easy"; + const char *s3 = "bits"; ut_asserteq_ptr(&s1[12], strstr(s1, s2)); ut_asserteq_ptr(&s1[13], strstr(&s1[3], &s2[1])); ut_assertnull(strstr(s1, s3)); - ut_asserteq_ptr(&s1[2], strstr(s1, &s3[2])); - ut_asserteq_ptr(&s1[8], strstr(&s1[5], &s3[2])); + ut_asserteq_ptr(&s1[1], strstr(s1, &s3[2])); + ut_asserteq_ptr(&s1[7], strstr(&s1[5], &s3[2])); return 0; } LIB_TEST(lib_strstr, 0); +/** lib_strcasestr() - unit test for strcasestr() */ +static int lib_strcasestr(struct unit_test_state *uts) +{ + const char *s1 = "Itsy Bitsy Teenie Weenie"; + const char *s2 = "eenie"; + const char *s3 = "bits"; + + ut_asserteq_ptr(&s1[12], strcasestr(s1, s2)); + ut_asserteq_ptr(&s1[13], strcasestr(&s1[3], &s2[1])); + ut_asserteq_ptr(&s1[5], strcasestr(s1, s3)); + ut_asserteq_ptr(&s1[1], strcasestr(s1, &s3[2])); + ut_asserteq_ptr(&s1[7], strcasestr(&s1[5], &s3[2])); + ut_assertnull(strcasestr(&s1[6], s3)); + + return 0; +} +LIB_TEST(lib_strcasestr, 0); + static int lib_strim(struct unit_test_state *uts) { char buf[BUFLEN], *p; diff --git a/tools/binman/btool/mkeficapsule.py b/tools/binman/btool/mkeficapsule.py index 7638c941a8e..3d3ceb009c1 100644 --- a/tools/binman/btool/mkeficapsule.py +++ b/tools/binman/btool/mkeficapsule.py @@ -126,7 +126,7 @@ class Bintoolmkeficapsule(bintool.Bintool): cmd = ['tools-only_defconfig', 'tools'] result = self.build_from_git( - 'https://source.denx.de/u-boot/u-boot.git', + 'https://git.u-boot-project.org/u-boot/u-boot.git', cmd, 'tools/mkeficapsule') return result diff --git a/tools/binman/pyproject.toml b/tools/binman/pyproject.toml index fd43a71b02b..46204f477ca 100644 --- a/tools/binman/pyproject.toml +++ b/tools/binman/pyproject.toml @@ -20,7 +20,7 @@ classifiers = [ [project.urls] "Homepage" = "https://docs.u-boot-project.org/en/latest/develop/package/index.html" -"Bug Tracker" = "https://source.denx.de/groups/u-boot/-/issues" +"Bug Tracker" = "https://git.u-boot-project.org/groups/u-boot/-/issues" [project.scripts] binman = "binman.main:start_binman" diff --git a/tools/buildman/pyproject.toml b/tools/buildman/pyproject.toml index 5f5c405afbf..8a27bbaf167 100644 --- a/tools/buildman/pyproject.toml +++ b/tools/buildman/pyproject.toml @@ -24,7 +24,7 @@ classifiers = [ [project.urls] "Homepage" = "https://docs.u-boot-project.org/en/latest/build/buildman.html" -"Bug Tracker" = "https://source.denx.de/groups/u-boot/-/issues" +"Bug Tracker" = "https://git.u-boot-project.org/groups/u-boot/-/issues" [project.scripts] buildman = "buildman.main:run_buildman" diff --git a/tools/docker/Dockerfile b/tools/docker/Dockerfile index a91a1060cc4..ebb679a5f46 100644 --- a/tools/docker/Dockerfile +++ b/tools/docker/Dockerfile @@ -358,11 +358,11 @@ USER uboot:uboot # Populate the cache for pip to use. Get these via wget as the # COPY / ADD directives don't work as we need them to. -RUN wget -O /tmp/pytest-requirements.txt https://source.denx.de/u-boot/u-boot/-/raw/master/test/py/requirements.txt -RUN wget -O /tmp/sphinx-requirements.txt https://source.denx.de/u-boot/u-boot/-/raw/master/doc/sphinx/requirements.txt -RUN wget -O /tmp/binman-requirements.txt https://source.denx.de/u-boot/u-boot/-/raw/master/tools/binman/requirements.txt -RUN wget -O /tmp/buildman-requirements.txt https://source.denx.de/u-boot/u-boot/-/raw/master/tools/buildman/requirements.txt -RUN wget -O /tmp/u_boot_pylib-requirements.txt https://source.denx.de/u-boot/u-boot/-/raw/master/tools/u_boot_pylib/requirements.txt +RUN wget -O /tmp/pytest-requirements.txt https://git.u-boot-project.org/u-boot/u-boot/-/raw/master/test/py/requirements.txt +RUN wget -O /tmp/sphinx-requirements.txt https://git.u-boot-project.org/u-boot/u-boot/-/raw/master/doc/sphinx/requirements.txt +RUN wget -O /tmp/binman-requirements.txt https://git.u-boot-project.org/u-boot/u-boot/-/raw/master/tools/binman/requirements.txt +RUN wget -O /tmp/buildman-requirements.txt https://git.u-boot-project.org/u-boot/u-boot/-/raw/master/tools/buildman/requirements.txt +RUN wget -O /tmp/u_boot_pylib-requirements.txt https://git.u-boot-project.org/u-boot/u-boot/-/raw/master/tools/u_boot_pylib/requirements.txt RUN python3 -m venv /tmp/venv && \ . /tmp/venv/bin/activate && \ pip install -r /tmp/pytest-requirements.txt \ diff --git a/tools/dtoc/pyproject.toml b/tools/dtoc/pyproject.toml index 53b09dba885..895bdc9b763 100644 --- a/tools/dtoc/pyproject.toml +++ b/tools/dtoc/pyproject.toml @@ -20,7 +20,7 @@ classifiers = [ [project.urls] "Homepage" = "https://docs.u-boot-project.org/en/latest/develop/driver-model/of-plat.html" -"Bug Tracker" = "https://source.denx.de/groups/u-boot/-/issues" +"Bug Tracker" = "https://git.u-boot-project.org/groups/u-boot/-/issues" [project.scripts] dtoc = "dtoc.main:run_dtoc" diff --git a/tools/patman/settings.py b/tools/patman/settings.py index 17229e0d823..fe65b1d3fb7 100644 --- a/tools/patman/settings.py +++ b/tools/patman/settings.py @@ -162,7 +162,7 @@ class _ProjectConfigParser(ConfigParser.ConfigParser): def ReadGitAliases(fname): """Read a git alias file. This is in the form used by git: - alias uboot [email protected] + alias uboot [email protected] alias wd Wolfgang Denk <[email protected]> Args: diff --git a/tools/u_boot_pylib/gitutil.py b/tools/u_boot_pylib/gitutil.py index 34b4dbb4839..59688aa7147 100644 --- a/tools/u_boot_pylib/gitutil.py +++ b/tools/u_boot_pylib/gitutil.py @@ -528,7 +528,7 @@ send --cc-cmd cc-fname" cover p1 p2' "Please add something like this to a commit\n" "Series-to: Fred Bloggs <[email protected]>\n" "Or do something like this\n" - "git config sendemail.to [email protected]") + "git config sendemail.to [email protected]") return None cc = build_email_list(list(set(series.get('cc')) - set(series.get('to'))), alias, '--cc', warn_on_error) diff --git a/tools/u_boot_pylib/pyproject.toml b/tools/u_boot_pylib/pyproject.toml index 1c6a023ee4b..300d14441c8 100644 --- a/tools/u_boot_pylib/pyproject.toml +++ b/tools/u_boot_pylib/pyproject.toml @@ -19,7 +19,7 @@ classifiers = [ [project.urls] "Homepage" = "https://docs.u-boot-project.org" -"Bug Tracker" = "https://source.denx.de/groups/u-boot/-/issues" +"Bug Tracker" = "https://git.u-boot-project.org/groups/u-boot/-/issues" [tool.setuptools] packages = ["u_boot_pylib"] |
