diff options
150 files changed, 1988 insertions, 566 deletions
diff --git a/arch/arm/dts/sama5d2.dtsi b/arch/arm/dts/sama5d2.dtsi index 819564fdd5..7b62fffb4f 100644 --- a/arch/arm/dts/sama5d2.dtsi +++ b/arch/arm/dts/sama5d2.dtsi @@ -34,6 +34,15 @@ #size-cells = <1>; bootph-all; + nfc_sram: sram@100000 { + compatible = "mmio-sram"; + no-memory-wc; + reg = <0x00100000 0x2400>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x00100000 0x2400>; + }; + usb1: ohci@400000 { compatible = "atmel,at91rm9200-ohci", "usb-ohci"; reg = <0x00400000 0x100000>; @@ -50,6 +59,32 @@ status = "disabled"; }; + ebi: ebi@10000000 { + compatible = "atmel,sama5d3-ebi"; + #address-cells = <2>; + #size-cells = <1>; + atmel,smc = <&hsmc>; + reg = <0x10000000 0x10000000 + 0x60000000 0x30000000>; + ranges = <0x0 0x0 0x10000000 0x10000000 + 0x1 0x0 0x60000000 0x10000000 + 0x2 0x0 0x70000000 0x10000000 + 0x3 0x0 0x80000000 0x10000000>; + clocks = <&h32ck>; + status = "disabled"; + + nand_controller: nand-controller { + compatible = "atmel,sama5d3-nand-controller"; + atmel,nfc-sram = <&nfc_sram>; + atmel,nfc-io = <&nfc_io>; + ecc-engine = <&pmecc>; + #address-cells = <2>; + #size-cells = <1>; + ranges; + status = "disabled"; + }; + }; + sdmmc0: sdio-host@a0000000 { compatible = "atmel,sama5d2-sdhci"; reg = <0xa0000000 0x300>; @@ -66,6 +101,11 @@ status = "disabled"; }; + nfc_io: nfc-io@c0000000 { + compatible = "atmel,sama5d3-nfc-io", "syscon"; + reg = <0xc0000000 0x8000000>; + }; + apb { compatible = "simple-bus"; #address-cells = <1>; @@ -79,7 +119,7 @@ status = "disabled"; }; - pmc: pmc@f0014000 { + pmc: clock-controller@f0014000 { compatible = "atmel,sama5d2-pmc", "syscon"; reg = <0xf0014000 0x160>; #address-cells = <1>; @@ -657,6 +697,22 @@ }; }; + hsmc: hsmc@f8014000 { + compatible = "atmel,sama5d2-smc", "syscon", "simple-mfd"; + reg = <0xf8014000 0x1000>; + interrupts = <17 IRQ_TYPE_LEVEL_HIGH 6>; + clocks = <&hsmc_clk>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + pmecc: ecc-engine@f8014070 { + compatible = "atmel,sama5d2-pmecc"; + reg = <0xf8014070 0x490>, + <0xf8014500 0x200>; + }; + }; + uart0: serial@f801c000 { compatible = "atmel,at91sam9260-usart"; reg = <0xf801c000 0x100>; @@ -698,13 +754,18 @@ status = "disabled"; }; - rstc@f8048000 { + sfr: sfr@f8030000 { + compatible = "atmel,sama5d2-sfr", "syscon"; + reg = <0xf8030000 0x98>; + }; + + reset_controller: reset-controller@f8048000 { compatible = "atmel,sama5d3-rstc"; reg = <0xf8048000 0x10>; clocks = <&clk32k>; }; - shdwc@f8048010 { + shutdown_controller: poweroff@f8048010 { compatible = "atmel,sama5d2-shdwc"; reg = <0xf8048010 0x10>; clocks = <&clk32k>; @@ -719,18 +780,13 @@ clocks = <&h32ck>; }; - watchdog@f8048040 { + watchdog: watchdog@f8048040 { compatible = "atmel,sama5d4-wdt"; reg = <0xf8048040 0x10>; clocks = <&clk32k>; status = "disabled"; }; - sfr: sfr@f8030000 { - compatible = "atmel,sama5d2-sfr", "syscon"; - reg = <0xf8030000 0x98>; - }; - sckc@f8048050 { compatible = "atmel,at91sam9x5-sckc"; reg = <0xf8048050 0x4>; diff --git a/arch/arm/mach-rockchip/rk3288/rk3288.c b/arch/arm/mach-rockchip/rk3288/rk3288.c index 26c7e41cd8..d9f782e342 100644 --- a/arch/arm/mach-rockchip/rk3288/rk3288.c +++ b/arch/arm/mach-rockchip/rk3288/rk3288.c @@ -184,8 +184,6 @@ static int do_clock(struct cmd_tbl *cmdtp, int flag, int argc, rate = clk_get_rate(&clk); printf("%s: %lu\n", clks[i].name, rate); - - clk_free(&clk); } return 0; diff --git a/arch/arm/mach-socfpga/clock_manager_agilex.c b/arch/arm/mach-socfpga/clock_manager_agilex.c index e035c09aae..28f593b60e 100644 --- a/arch/arm/mach-socfpga/clock_manager_agilex.c +++ b/arch/arm/mach-socfpga/clock_manager_agilex.c @@ -37,8 +37,6 @@ static ulong cm_get_rate_dm(u32 id) rate = clk_get_rate(&clk); - clk_free(&clk); - if ((rate == (unsigned long)-ENOSYS) || (rate == (unsigned long)-ENXIO) || (rate == (unsigned long)-EIO)) { diff --git a/arch/arm/mach-socfpga/clock_manager_arria10.c b/arch/arm/mach-socfpga/clock_manager_arria10.c index b48a2b47bc..8ab18f6b72 100644 --- a/arch/arm/mach-socfpga/clock_manager_arria10.c +++ b/arch/arm/mach-socfpga/clock_manager_arria10.c @@ -962,7 +962,6 @@ static u32 cm_get_rate_dm(char *name) struct uclass *uc; struct udevice *dev = NULL; struct clk clk = { 0 }; - ulong rate; int ret; /* Device addresses start at 1 */ @@ -982,11 +981,7 @@ static u32 cm_get_rate_dm(char *name) if (ret) return 0; - rate = clk_get_rate(&clk); - - clk_free(&clk); - - return rate; + return clk_get_rate(&clk); } static u32 cm_get_rate_dm_khz(char *name) diff --git a/arch/arm/mach-socfpga/clock_manager_n5x.c b/arch/arm/mach-socfpga/clock_manager_n5x.c index 4f098533e7..0ed480de67 100644 --- a/arch/arm/mach-socfpga/clock_manager_n5x.c +++ b/arch/arm/mach-socfpga/clock_manager_n5x.c @@ -36,8 +36,6 @@ static ulong cm_get_rate_dm(u32 id) rate = clk_get_rate(&clk); - clk_free(&clk); - if ((rate == (unsigned long)-ENXIO) || (rate == (unsigned long)-EIO)) { debug("%s id %u: clk_get_rate err: %ld\n", diff --git a/arch/arm/mach-zynq/clk.c b/arch/arm/mach-zynq/clk.c index e6a67326dd..5e1ba8d43e 100644 --- a/arch/arm/mach-zynq/clk.c +++ b/arch/arm/mach-zynq/clk.c @@ -44,8 +44,6 @@ int set_cpu_clk_info(void) gd->bd->bi_arm_freq = rate; gd->cpu_clk = clk_get_rate(&clk); } - - clk_free(&clk); } gd->bd->bi_dsp_freq = 0; diff --git a/arch/mips/mach-pic32/cpu.c b/arch/mips/mach-pic32/cpu.c index 3181a946a2..668adbbda6 100644 --- a/arch/mips/mach-pic32/cpu.c +++ b/arch/mips/mach-pic32/cpu.c @@ -30,7 +30,6 @@ static ulong rate(int id) int ret; struct udevice *dev; struct clk clk; - ulong rate; ret = uclass_get_device(UCLASS_CLK, 0, &dev); if (ret) { @@ -43,11 +42,7 @@ static ulong rate(int id) if (ret < 0) return ret; - rate = clk_get_rate(&clk); - - clk_free(&clk); - - return rate; + return clk_get_rate(&clk); } static ulong clk_get_cpu_rate(void) diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index 67126d96af..ac52c5e6da 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -14,6 +14,9 @@ config TARGET_ANDES_AE350 config TARGET_MICROCHIP_ICICLE bool "Support Microchip PolarFire-SoC Icicle Board" +config TARGET_MILKV_DUO + bool "Support Milk-v Duo Board" + config TARGET_OPENPITON_RISCV64 bool "Support RISC-V cores on OpenPiton SoC" @@ -83,6 +86,7 @@ source "board/openpiton/riscv64/Kconfig" source "board/sifive/unleashed/Kconfig" source "board/sifive/unmatched/Kconfig" source "board/sipeed/maix/Kconfig" +source "board/sophgo/milkv_duo/Kconfig" source "board/starfive/visionfive2/Kconfig" source "board/thead/th1520_lpi4a/Kconfig" source "board/xilinx/mbv/Kconfig" diff --git a/arch/riscv/config.mk b/arch/riscv/config.mk index 9cf2aef0a4..9f16dda92a 100644 --- a/arch/riscv/config.mk +++ b/arch/riscv/config.mk @@ -25,7 +25,7 @@ EFI_LDS := elf_riscv64_efi.lds PLATFORM_ELFFLAGS += -B riscv -O elf64-littleriscv endif -PLATFORM_CPPFLAGS += -ffixed-gp -fpic +PLATFORM_CPPFLAGS += -ffixed-x3 -fpic PLATFORM_RELFLAGS += -fno-common -ffunction-sections -fdata-sections LDFLAGS_u-boot += --gc-sections -static -pie diff --git a/arch/riscv/dts/Makefile b/arch/riscv/dts/Makefile index b05bb5607f..17cda483e1 100644 --- a/arch/riscv/dts/Makefile +++ b/arch/riscv/dts/Makefile @@ -2,6 +2,7 @@ dtb-$(CONFIG_TARGET_ANDES_AE350) += ae350_32.dtb ae350_64.dtb dtb-$(CONFIG_TARGET_MICROCHIP_ICICLE) += mpfs-icicle-kit.dtb +dtb-$(CONFIG_TARGET_MILKV_DUO) += cv1800b-milkv-duo.dtb dtb-$(CONFIG_TARGET_QEMU_VIRT) += qemu-virt32.dtb qemu-virt64.dtb dtb-$(CONFIG_TARGET_OPENPITON_RISCV64) += openpiton-riscv64.dtb dtb-$(CONFIG_TARGET_SIFIVE_UNLEASHED) += hifive-unleashed-a00.dtb diff --git a/arch/riscv/dts/cv1800b-milkv-duo.dts b/arch/riscv/dts/cv1800b-milkv-duo.dts new file mode 100644 index 0000000000..3af9e34b3b --- /dev/null +++ b/arch/riscv/dts/cv1800b-milkv-duo.dts @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2023 Jisheng Zhang <jszhang@kernel.org> + */ + +/dts-v1/; + +#include "cv1800b.dtsi" + +/ { + model = "Milk-V Duo"; + compatible = "milkv,duo", "sophgo,cv1800b"; + + aliases { + serial0 = &uart0; + serial1 = &uart1; + serial2 = &uart2; + serial3 = &uart3; + serial4 = &uart4; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x80000000 0x3f40000>; + }; +}; + +&osc { + clock-frequency = <25000000>; +}; + +&uart0 { + status = "okay"; +}; diff --git a/arch/riscv/dts/cv1800b.dtsi b/arch/riscv/dts/cv1800b.dtsi new file mode 100644 index 0000000000..165e9e320a --- /dev/null +++ b/arch/riscv/dts/cv1800b.dtsi @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2023 Jisheng Zhang <jszhang@kernel.org> + */ + +#include "cv18xx.dtsi" + +/ { + compatible = "sophgo,cv1800b"; +}; + +&plic { + compatible = "sophgo,cv1800b-plic", "thead,c900-plic"; +}; + +&clint { + compatible = "sophgo,cv1800b-clint", "thead,c900-clint"; +}; diff --git a/arch/riscv/dts/cv18xx.dtsi b/arch/riscv/dts/cv18xx.dtsi new file mode 100644 index 0000000000..2d6f4a4b1e --- /dev/null +++ b/arch/riscv/dts/cv18xx.dtsi @@ -0,0 +1,192 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2023 Jisheng Zhang <jszhang@kernel.org> + * Copyright (C) 2023 Inochi Amaoto <inochiama@outlook.com> + */ + +#include <dt-bindings/interrupt-controller/irq.h> + +/ { + #address-cells = <1>; + #size-cells = <1>; + + cpus: cpus { + #address-cells = <1>; + #size-cells = <0>; + timebase-frequency = <25000000>; + + cpu0: cpu@0 { + compatible = "thead,c906", "riscv"; + device_type = "cpu"; + reg = <0>; + d-cache-block-size = <64>; + d-cache-sets = <512>; + d-cache-size = <65536>; + i-cache-block-size = <64>; + i-cache-sets = <128>; + i-cache-size = <32768>; + mmu-type = "riscv,sv39"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "zicntr", "zicsr", + "zifencei", "zihpm"; + + cpu0_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + }; + + osc: oscillator { + compatible = "fixed-clock"; + clock-output-names = "osc_25m"; + #clock-cells = <0>; + }; + + soc { + compatible = "simple-bus"; + interrupt-parent = <&plic>; + #address-cells = <1>; + #size-cells = <1>; + dma-noncoherent; + ranges; + + gpio0: gpio@3020000 { + compatible = "snps,dw-apb-gpio"; + reg = <0x3020000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + + porta: gpio-controller@0 { + compatible = "snps,dw-apb-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <32>; + reg = <0>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = <60 IRQ_TYPE_LEVEL_HIGH>; + }; + }; + + gpio1: gpio@3021000 { + compatible = "snps,dw-apb-gpio"; + reg = <0x3021000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + + portb: gpio-controller@0 { + compatible = "snps,dw-apb-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <32>; + reg = <0>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = <61 IRQ_TYPE_LEVEL_HIGH>; + }; + }; + + gpio2: gpio@3022000 { + compatible = "snps,dw-apb-gpio"; + reg = <0x3022000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + + portc: gpio-controller@0 { + compatible = "snps,dw-apb-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <32>; + reg = <0>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = <62 IRQ_TYPE_LEVEL_HIGH>; + }; + }; + + gpio3: gpio@3023000 { + compatible = "snps,dw-apb-gpio"; + reg = <0x3023000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + + portd: gpio-controller@0 { + compatible = "snps,dw-apb-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <32>; + reg = <0>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = <63 IRQ_TYPE_LEVEL_HIGH>; + }; + }; + + uart0: serial@4140000 { + compatible = "snps,dw-apb-uart"; + reg = <0x04140000 0x100>; + interrupts = <44 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&osc>; + reg-shift = <2>; + reg-io-width = <4>; + status = "disabled"; + }; + + uart1: serial@4150000 { + compatible = "snps,dw-apb-uart"; + reg = <0x04150000 0x100>; + interrupts = <45 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&osc>; + reg-shift = <2>; + reg-io-width = <4>; + status = "disabled"; + }; + + uart2: serial@4160000 { + compatible = "snps,dw-apb-uart"; + reg = <0x04160000 0x100>; + interrupts = <46 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&osc>; + reg-shift = <2>; + reg-io-width = <4>; + status = "disabled"; + }; + + uart3: serial@4170000 { + compatible = "snps,dw-apb-uart"; + reg = <0x04170000 0x100>; + interrupts = <47 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&osc>; + reg-shift = <2>; + reg-io-width = <4>; + status = "disabled"; + }; + + uart4: serial@41c0000 { + compatible = "snps,dw-apb-uart"; + reg = <0x041c0000 0x100>; + interrupts = <48 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&osc>; + reg-shift = <2>; + reg-io-width = <4>; + status = "disabled"; + }; + + plic: interrupt-controller@70000000 { + reg = <0x70000000 0x4000000>; + interrupts-extended = <&cpu0_intc 11>, <&cpu0_intc 9>; + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <2>; + riscv,ndev = <101>; + }; + + clint: timer@74000000 { + reg = <0x74000000 0x10000>; + interrupts-extended = <&cpu0_intc 3>, <&cpu0_intc 7>; + }; + }; +}; diff --git a/arch/riscv/dts/jh7110-starfive-visionfive-2.dtsi b/arch/riscv/dts/jh7110-starfive-visionfive-2.dtsi index e94f9fe826..f2c6bec929 100644 --- a/arch/riscv/dts/jh7110-starfive-visionfive-2.dtsi +++ b/arch/riscv/dts/jh7110-starfive-visionfive-2.dtsi @@ -127,6 +127,11 @@ pinctrl-0 = <&i2c5_pins>; status = "okay"; + pmic@36 { + compatible = "x-powers,axp15060"; + reg = <0x36>; + }; + eeprom@50 { compatible = "atmel,24c04"; reg = <0x50>; diff --git a/arch/riscv/dts/jh7110.dtsi b/arch/riscv/dts/jh7110.dtsi index 6d2675d6ce..2cdc683d49 100644 --- a/arch/riscv/dts/jh7110.dtsi +++ b/arch/riscv/dts/jh7110.dtsi @@ -473,6 +473,12 @@ status = "disabled"; }; + power-controller@17030000 { + compatible = "starfive,jh7110-pmu"; + reg = <0x0 0x17030000 0x0 0x10000>; + interrupts = <111>; + }; + qspi: spi@13010000 { compatible = "cdns,qspi-nor"; reg = <0x0 0x13010000 0x0 0x10000 diff --git a/arch/riscv/include/asm/arch-fu740/eeprom.h b/arch/riscv/include/asm/arch-fu740/eeprom.h new file mode 100644 index 0000000000..aaa02c6d2b --- /dev/null +++ b/arch/riscv/include/asm/arch-fu740/eeprom.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2024 SiFive, Inc. + * + * Zong Li <zong.li@sifve.com> + */ + +#ifndef _ASM_RISCV_EEPROM_H +#define _ASM_RISCV_EEPROM_H + +#define PCB_REVISION_REV3 0x3 + +u8 get_pcb_revision_from_eeprom(void); + +#endif /* _ASM_RISCV_EEPROM_H */ diff --git a/arch/riscv/include/asm/sbi.h b/arch/riscv/include/asm/sbi.h index bf4c9af622..d1113f3d70 100644 --- a/arch/riscv/include/asm/sbi.h +++ b/arch/riscv/include/asm/sbi.h @@ -33,6 +33,7 @@ enum sbi_ext_id { SBI_EXT_CPPC = 0x43505043, SBI_EXT_NACL = 0x4E41434C, SBI_EXT_STA = 0x535441, + SBI_EXT_DBTR = 0x44425452, }; enum sbi_ext_base_fid { diff --git a/arch/sandbox/include/asm/clk.h b/arch/sandbox/include/asm/clk.h index d4e04ad148..37fe49c7fc 100644 --- a/arch/sandbox/include/asm/clk.h +++ b/arch/sandbox/include/asm/clk.h @@ -182,14 +182,6 @@ int sandbox_clk_test_disable(struct udevice *dev, int id); */ int sandbox_clk_test_disable_bulk(struct udevice *dev); /** - * sandbox_clk_test_free - Ask the sandbox clock test device to free its - * clocks. - * - * @dev: The sandbox clock test (client) device. - * @return: 0 if OK, or a negative error code. - */ -int sandbox_clk_test_free(struct udevice *dev); -/** * sandbox_clk_test_release_bulk - Ask the sandbox clock test device to release * all clocks in it's clock bulk struct. * diff --git a/board/AndesTech/ae350/ae350.c b/board/AndesTech/ae350/ae350.c index 4e53fee5d2..62b93b4ecb 100644 --- a/board/AndesTech/ae350/ae350.c +++ b/board/AndesTech/ae350/ae350.c @@ -21,8 +21,6 @@ #include <fdtdec.h> #include <dm.h> #include <spl.h> -#include <mapmem.h> -#include <hang.h> DECLARE_GLOBAL_DATA_PTR; @@ -51,29 +49,6 @@ int misc_init_r(void) } #endif -#if CONFIG_IS_ENABLED(LOAD_FIT) || CONFIG_IS_ENABLED(LOAD_FIT_FULL) -#define ANDES_SPL_FDT_ADDR (CONFIG_TEXT_BASE - 0x100000) -void spl_perform_fixups(struct spl_image_info *spl_image) -{ - /* - * Originally, u-boot-spl will place DTB directly after the kernel, - * but the size of the kernel did not include the BSS section, which - * means u-boot-spl will place the DTB in the kernel BSS section - * causing the DTB to be cleared by kernel BSS initializtion. - * Moving DTB in front of the kernel can avoid the error. - */ - if (ANDES_SPL_FDT_ADDR < 0) { - printf("%s: CONFIG_TEXT_BASE needs to be larger than 0x100000\n", - __func__); - hang(); - } - - memcpy((void *)ANDES_SPL_FDT_ADDR, spl_image->fdt_addr, - fdt_totalsize(spl_image->fdt_addr)); - spl_image->fdt_addr = map_sysmem(ANDES_SPL_FDT_ADDR, 0); -} -#endif - int board_init(void) { gd->bd->bi_boot_params = PHYS_SDRAM_0 + 0x400; diff --git a/board/microchip/pic32mzda/pic32mzda.c b/board/microchip/pic32mzda/pic32mzda.c index e7337deea7..3c2203d220 100644 --- a/board/microchip/pic32mzda/pic32mzda.c +++ b/board/microchip/pic32mzda/pic32mzda.c @@ -36,8 +36,6 @@ int checkboard(void) rate = clk_get_rate(&clk); printf("CPU Speed: %lu MHz\n", rate / 1000000); - clk_free(&clk); - return 0; } #endif diff --git a/board/sifive/unmatched/spl.c b/board/sifive/unmatched/spl.c index 7c0beedc08..e69bed9d99 100644 --- a/board/sifive/unmatched/spl.c +++ b/board/sifive/unmatched/spl.c @@ -15,6 +15,29 @@ #include <asm/gpio.h> #include <asm/arch/gpio.h> #include <asm/arch/spl.h> +#include <linux/io.h> +#include <asm/arch/eeprom.h> + +struct pwm_sifive_regs { + unsigned int cfg; /* PWM configuration register */ + unsigned int pad0; /* Reserved */ + unsigned int cnt; /* PWM count register */ + unsigned int pad1; /* Reserved */ + unsigned int pwms; /* Scaled PWM count register */ + unsigned int pad2; /* Reserved */ + unsigned int pad3; /* Reserved */ + unsigned int pad4; /* Reserved */ + unsigned int cmp0; /* PWM 0 compare register */ + unsigned int cmp1; /* PWM 1 compare register */ + unsigned int cmp2; /* PWM 2 compare register */ + unsigned int cmp3; /* PWM 3 compare register */ +}; + +#define PWM0_BASE 0x10020000 +#define PWM1_BASE 0x10021000 +#define PWM_CFG_INIT 0x1000 +#define PWM_CMP_ENABLE_VAL 0x0 +#define PWM_CMP_DISABLE_VAL 0xffff #define UBRDG_RESET SIFIVE_GENERIC_GPIO_NR(0, 7) #define ULPI_RESET SIFIVE_GENERIC_GPIO_NR(0, 9) @@ -26,6 +49,33 @@ #define MODE_SELECT_SD 0xb #define MODE_SELECT_MASK GENMASK(3, 0) +void spl_pwm_device_init(void) +{ + struct pwm_sifive_regs *pwm0, *pwm1; + + pwm0 = (struct pwm_sifive_regs *)PWM0_BASE; + pwm1 = (struct pwm_sifive_regs *)PWM1_BASE; + writel(PWM_CMP_DISABLE_VAL, (void *)&pwm0->cmp0); + + /* Set the 3-color PWM LEDs to yellow in SPL */ + writel(PWM_CMP_ENABLE_VAL, (void *)&pwm0->cmp1); + writel(PWM_CMP_ENABLE_VAL, (void *)&pwm0->cmp2); + writel(PWM_CMP_DISABLE_VAL, (void *)&pwm0->cmp3); + writel(PWM_CFG_INIT, (void *)&pwm0->cfg); + + /* Turn on all the fans, (J21), (J23) and (J24), on the unmatched board */ + /* The SoC fan(J21) on the rev3 board cannot be controlled by PWM_COMP0, + * so here sets the initial value of PWM_COMP0 as DISABLE */ + if (get_pcb_revision_from_eeprom() == PCB_REVISION_REV3) + writel(PWM_CMP_DISABLE_VAL, (void *)&pwm1->cmp1); + else + writel(PWM_CMP_ENABLE_VAL, (void *)&pwm1->cmp1); + + writel(PWM_CMP_ENABLE_VAL, (void *)&pwm1->cmp2); + writel(PWM_CMP_ENABLE_VAL, (void *)&pwm1->cmp3); + writel(PWM_CFG_INIT, (void *)&pwm1->cfg); +} + static inline int spl_reset_device_by_gpio(const char *label, int pin, int low_width) { int ret; @@ -90,6 +140,8 @@ int spl_board_init_f(void) goto end; } + spl_pwm_device_init(); + ret = spl_gemgxl_init(); if (ret) { debug("Gigabit ethernet PHY (VSC8541) init failed: %d\n", ret); diff --git a/board/sipeed/maix/maix.c b/board/sipeed/maix/maix.c index 79e492f0a8..06653b5a87 100644 --- a/board/sipeed/maix/maix.c +++ b/board/sipeed/maix/maix.c @@ -32,7 +32,6 @@ static int sram_init(void) continue; ret = clk_enable(&clk); - clk_free(&clk); if (ret) return ret; } diff --git a/board/sophgo/milkv_duo/Kconfig b/board/sophgo/milkv_duo/Kconfig new file mode 100644 index 0000000000..2a458f291c --- /dev/null +++ b/board/sophgo/milkv_duo/Kconfig @@ -0,0 +1,28 @@ +if TARGET_MILKV_DUO + +config SYS_BOARD + default "milkv_duo" + +config SYS_VENDOR + default "sophgo" + +config SYS_CPU + default "generic" + +config SYS_CONFIG_NAME + default "milkv_duo" + +config TEXT_BASE + default 0x80200000 + +config ENV_SIZE + default 0x20000 + +config ENV_SECT_SIZE + default 0x40000 + +config BOARD_SPECIFIC_OPTIONS + def_bool y + select GENERIC_RISCV + +endif diff --git a/board/sophgo/milkv_duo/MAINTAINERS b/board/sophgo/milkv_duo/MAINTAINERS new file mode 100644 index 0000000000..651a0592f7 --- /dev/null +++ b/board/sophgo/milkv_duo/MAINTAINERS @@ -0,0 +1,6 @@ +Milk-V Duo +M: Kongyang Liu <seashell11234455@gmail.com> +S: Maintained +F: board/sophgo/milkv_duo/ +F: configs/milkv_duo_defconfig +F: doc/board/sophgo/milkv_duo.rst diff --git a/board/sophgo/milkv_duo/Makefile b/board/sophgo/milkv_duo/Makefile new file mode 100644 index 0000000000..a087013f5c --- /dev/null +++ b/board/sophgo/milkv_duo/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (c) 2024, Kongyang Liu <seashell11234455@gmail.com> + +obj-y := board.o diff --git a/board/sophgo/milkv_duo/board.c b/board/sophgo/milkv_duo/board.c new file mode 100644 index 0000000000..eaa47be173 --- /dev/null +++ b/board/sophgo/milkv_duo/board.c @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2024, Kongyang Liu <seashell11234455@gmail.com> + */ + +int board_init(void) +{ + return 0; +} diff --git a/board/starfive/visionfive2/spl.c b/board/starfive/visionfive2/spl.c index 336f0cdfc9..1b49945d11 100644 --- a/board/starfive/visionfive2/spl.c +++ b/board/starfive/visionfive2/spl.c @@ -45,6 +45,10 @@ static const struct starfive_vf2_pro starfive_verb[] = { {"/soc/ethernet@16030000/mdio/ethernet-phy@0", "motorcomm,tx-clk-1000-inverted", NULL}, {"/soc/ethernet@16030000/mdio/ethernet-phy@0", + "motorcomm,rx-clk-drv-microamp", "3970"}, + {"/soc/ethernet@16030000/mdio/ethernet-phy@0", + "motorcomm,rx-data-drv-microamp", "2910"}, + {"/soc/ethernet@16030000/mdio/ethernet-phy@0", "rx-internal-delay-ps", "1900"}, {"/soc/ethernet@16030000/mdio/ethernet-phy@0", "tx-internal-delay-ps", "1500"}, @@ -54,6 +58,10 @@ static const struct starfive_vf2_pro starfive_verb[] = { { "/soc/ethernet@16040000/mdio/ethernet-phy@1", "motorcomm,tx-clk-100-inverted", NULL}, {"/soc/ethernet@16040000/mdio/ethernet-phy@1", + "motorcomm,rx-clk-drv-microamp", "3970"}, + {"/soc/ethernet@16040000/mdio/ethernet-phy@1", + "motorcomm,rx-data-drv-microamp", "2910"}, + {"/soc/ethernet@16040000/mdio/ethernet-phy@1", "rx-internal-delay-ps", "0"}, {"/soc/ethernet@16040000/mdio/ethernet-phy@1", "tx-internal-delay-ps", "0"}, @@ -61,11 +69,13 @@ static const struct starfive_vf2_pro starfive_verb[] = { void spl_fdt_fixup_version_a(void *fdt) { + static const char compat[] = "starfive,visionfive-2-v1.2a\0starfive,jh7110"; u32 phandle; u8 i; int offset; int ret; + fdt_setprop(fdt, fdt_path_offset(fdt, "/"), "compatible", compat, sizeof(compat)); fdt_setprop_string(fdt, fdt_path_offset(fdt, "/"), "model", "StarFive VisionFive 2 v1.2A"); @@ -106,11 +116,13 @@ void spl_fdt_fixup_version_a(void *fdt) void spl_fdt_fixup_version_b(void *fdt) { + static const char compat[] = "starfive,visionfive-2-v1.3b\0starfive,jh7110"; u32 phandle; u8 i; int offset; int ret; + fdt_setprop(fdt, fdt_path_offset(fdt, "/"), "compatible", compat, sizeof(compat)); fdt_setprop_string(fdt, fdt_path_offset(fdt, "/"), "model", "StarFive VisionFive 2 v1.3B"); diff --git a/board/synopsys/hsdk/clk-lib.c b/board/synopsys/hsdk/clk-lib.c index be76d6c8f4..a9614e9080 100644 --- a/board/synopsys/hsdk/clk-lib.c +++ b/board/synopsys/hsdk/clk-lib.c @@ -56,8 +56,6 @@ int soc_clk_ctl(const char *name, ulong *rate, enum clk_ctl_ops ctl) priv_rate = clk_get_rate(&clk); - clk_free(&clk); - mhz_rate = ceil(priv_rate, HZ_IN_MHZ); if (ctl & CLK_MHZ) diff --git a/cmd/riscv/sbi.c b/cmd/riscv/sbi.c index 940d9bc168..9daf0e247a 100644 --- a/cmd/riscv/sbi.c +++ b/cmd/riscv/sbi.c @@ -53,6 +53,7 @@ static struct sbi_ext extensions[] = { { SBI_EXT_CPPC, "Collaborative Processor Performance Control Extension" }, { SBI_EXT_NACL, "Nested Acceleration Extension" }, { SBI_EXT_STA, "Steal-time Accounting Extension" }, + { SBI_EXT_DBTR, "Debug Trigger Extension" }, }; static int do_sbi(struct cmd_tbl *cmdtp, int flag, int argc, diff --git a/common/spl/Kconfig b/common/spl/Kconfig index 6a4772eea9..8805dd33fe 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -1113,7 +1113,7 @@ config SPL_OS_BOOT config SPL_PAYLOAD_ARGS_ADDR hex "Address in memory to load 'args' file for Falcon Mode to" - depends on SPL_OS_BOOT + depends on SPL_OS_BOOT || SPL_LOAD_FIT_OPENSBI_OS_BOOT default 0x88000000 if ARCH_OMAP2PLUS help Address in memory where the 'args' file, typically a device tree diff --git a/common/spl/spl_opensbi.c b/common/spl/spl_opensbi.c index 9801d38c0b..8127ebc946 100644 --- a/common/spl/spl_opensbi.c +++ b/common/spl/spl_opensbi.c @@ -16,6 +16,7 @@ #include <opensbi.h> #include <linux/libfdt.h> #include <linux/printk.h> +#include <mapmem.h> DECLARE_GLOBAL_DATA_PTR; @@ -58,6 +59,20 @@ void __noreturn spl_invoke_opensbi(struct spl_image_info *spl_image) } /* + * Originally, u-boot-spl will place DTB directly after the kernel, + * but the size of the kernel did not include the BSS section, which + * means u-boot-spl will place the DTB in the kernel BSS section + * causing the DTB to be cleared by kernel BSS initializtion. + * Moving DTB in front of the kernel can avoid the error. + */ +#if CONFIG_IS_ENABLED(LOAD_FIT_OPENSBI_OS_BOOT) && \ + CONFIG_IS_ENABLED(PAYLOAD_ARGS_ADDR) + memcpy((void *)CONFIG_SPL_PAYLOAD_ARGS_ADDR, spl_image->fdt_addr, + fdt_totalsize(spl_image->fdt_addr)); + spl_image->fdt_addr = map_sysmem(CONFIG_SPL_PAYLOAD_ARGS_ADDR, 0); +#endif + + /* * Find next os image in /fit-images * The next os image default is u-boot proper, once enable * OpenSBI OS boot mode, the OS image should be linux. diff --git a/configs/ae350_rv32_defconfig b/configs/ae350_rv32_defconfig index 3bfa3e9f8e..35ad62c845 100644 --- a/configs/ae350_rv32_defconfig +++ b/configs/ae350_rv32_defconfig @@ -23,6 +23,7 @@ CONFIG_SYS_PROMPT="RISC-V # " CONFIG_CMD_IMLS=y CONFIG_CMD_MMC=y CONFIG_CMD_SF_TEST=y +CONFIG_CMD_WDT=y # CONFIG_CMD_SETEXPR is not set CONFIG_BOOTP_PREFER_SERVERIP=y CONFIG_CMD_CACHE=y @@ -49,3 +50,6 @@ CONFIG_BAUDRATE=38400 CONFIG_SYS_NS16550=y CONFIG_SPI=y CONFIG_ATCSPI200_SPI=y +# CONFIG_WATCHDOG_AUTOSTART is not set +CONFIG_WDT=y +CONFIG_WDT_ATCWDT200=y diff --git a/configs/ae350_rv32_falcon_defconfig b/configs/ae350_rv32_falcon_defconfig index abf7dd4f4d..f81471087b 100644 --- a/configs/ae350_rv32_falcon_defconfig +++ b/configs/ae350_rv32_falcon_defconfig @@ -14,6 +14,7 @@ CONFIG_TARGET_ANDES_AE350=y CONFIG_RISCV_SMODE=y # CONFIG_AVAILABLE_HARTS is not set CONFIG_SPL_LOAD_FIT_OPENSBI_OS_BOOT=y +CONFIG_SPL_PAYLOAD_ARGS_ADDR=0x01700000 CONFIG_SYS_MONITOR_BASE=0x88000000 CONFIG_FIT=y CONFIG_SPL_LOAD_FIT_ADDRESS=0x10000000 diff --git a/configs/ae350_rv32_falcon_xip_defconfig b/configs/ae350_rv32_falcon_xip_defconfig index 5166ab7a93..50e164c4d2 100644 --- a/configs/ae350_rv32_falcon_xip_defconfig +++ b/configs/ae350_rv32_falcon_xip_defconfig @@ -15,6 +15,7 @@ CONFIG_TARGET_ANDES_AE350=y CONFIG_RISCV_SMODE=y CONFIG_SPL_XIP=y CONFIG_SPL_LOAD_FIT_OPENSBI_OS_BOOT=y +CONFIG_SPL_PAYLOAD_ARGS_ADDR=0x01700000 CONFIG_SYS_MONITOR_BASE=0x88000000 CONFIG_FIT=y CONFIG_SPL_LOAD_FIT_ADDRESS=0x80010000 diff --git a/configs/ae350_rv32_spl_defconfig b/configs/ae350_rv32_spl_defconfig index aeb50206d2..41cd457bc3 100644 --- a/configs/ae350_rv32_spl_defconfig +++ b/configs/ae350_rv32_spl_defconfig @@ -33,6 +33,7 @@ CONFIG_SYS_PROMPT="RISC-V # " CONFIG_CMD_IMLS=y CONFIG_CMD_MMC=y CONFIG_CMD_SF_TEST=y +CONFIG_CMD_WDT=y # CONFIG_CMD_SETEXPR is not set CONFIG_BOOTP_PREFER_SERVERIP=y CONFIG_CMD_CACHE=y @@ -58,3 +59,6 @@ CONFIG_SYS_NS16550=y CONFIG_SPI=y CONFIG_ATCSPI200_SPI=y # CONFIG_BINMAN_FDT is not set +# CONFIG_WATCHDOG_AUTOSTART is not set +CONFIG_WDT=y +CONFIG_WDT_ATCWDT200=y diff --git a/configs/ae350_rv32_spl_xip_defconfig b/configs/ae350_rv32_spl_xip_defconfig index f15ec301ce..954e2f2de7 100644 --- a/configs/ae350_rv32_spl_xip_defconfig +++ b/configs/ae350_rv32_spl_xip_defconfig @@ -34,6 +34,7 @@ CONFIG_SYS_PROMPT="RISC-V # " CONFIG_CMD_IMLS=y CONFIG_CMD_MMC=y CONFIG_CMD_SF_TEST=y +CONFIG_CMD_WDT=y # CONFIG_CMD_SETEXPR is not set CONFIG_BOOTP_PREFER_SERVERIP=y CONFIG_CMD_CACHE=y @@ -59,3 +60,6 @@ CONFIG_SYS_NS16550=y CONFIG_SPI=y CONFIG_ATCSPI200_SPI=y # CONFIG_BINMAN_FDT is not set +# CONFIG_WATCHDOG_AUTOSTART is not set +CONFIG_WDT=y +CONFIG_WDT_ATCWDT200=y diff --git a/configs/ae350_rv32_xip_defconfig b/configs/ae350_rv32_xip_defconfig index c40eb043c5..95863595d2 100644 --- a/configs/ae350_rv32_xip_defconfig +++ b/configs/ae350_rv32_xip_defconfig @@ -24,6 +24,7 @@ CONFIG_SYS_PROMPT="RISC-V # " CONFIG_CMD_IMLS=y CONFIG_CMD_MMC=y CONFIG_CMD_SF_TEST=y +CONFIG_CMD_WDT=y # CONFIG_CMD_SETEXPR is not set CONFIG_BOOTP_PREFER_SERVERIP=y CONFIG_CMD_CACHE=y @@ -50,3 +51,6 @@ CONFIG_BAUDRATE=38400 CONFIG_SYS_NS16550=y CONFIG_SPI=y CONFIG_ATCSPI200_SPI=y +# CONFIG_WATCHDOG_AUTOSTART is not set +CONFIG_WDT=y +CONFIG_WDT_ATCWDT200=y diff --git a/configs/ae350_rv64_defconfig b/configs/ae350_rv64_defconfig index 7ae938aeb2..988214285a 100644 --- a/configs/ae350_rv64_defconfig +++ b/configs/ae350_rv64_defconfig @@ -23,6 +23,7 @@ CONFIG_SYS_PROMPT="RISC-V # " CONFIG_CMD_IMLS=y CONFIG_CMD_MMC=y CONFIG_CMD_SF_TEST=y +CONFIG_CMD_WDT=y # CONFIG_CMD_SETEXPR is not set CONFIG_BOOTP_PREFER_SERVERIP=y CONFIG_CMD_CACHE=y @@ -49,3 +50,6 @@ CONFIG_BAUDRATE=38400 CONFIG_SYS_NS16550=y CONFIG_SPI=y CONFIG_ATCSPI200_SPI=y +# CONFIG_WATCHDOG_AUTOSTART is not set +CONFIG_WDT=y +CONFIG_WDT_ATCWDT200=y diff --git a/configs/ae350_rv64_falcon_defconfig b/configs/ae350_rv64_falcon_defconfig index 1289238708..b0b7ae597e 100644 --- a/configs/ae350_rv64_falcon_defconfig +++ b/configs/ae350_rv64_falcon_defconfig @@ -14,6 +14,7 @@ CONFIG_ARCH_RV64I=y CONFIG_RISCV_SMODE=y # CONFIG_AVAILABLE_HARTS is not set CONFIG_SPL_LOAD_FIT_OPENSBI_OS_BOOT=y +CONFIG_SPL_PAYLOAD_ARGS_ADDR=0x01700000 CONFIG_SYS_MONITOR_BASE=0x88000000 CONFIG_FIT=y CONFIG_SPL_LOAD_FIT_ADDRESS=0x10000000 diff --git a/configs/ae350_rv64_falcon_xip_defconfig b/configs/ae350_rv64_falcon_xip_defconfig index 18e2dafe7f..cac315d97b 100644 --- a/configs/ae350_rv64_falcon_xip_defconfig +++ b/configs/ae350_rv64_falcon_xip_defconfig @@ -15,6 +15,7 @@ CONFIG_ARCH_RV64I=y CONFIG_RISCV_SMODE=y CONFIG_SPL_XIP=y CONFIG_SPL_LOAD_FIT_OPENSBI_OS_BOOT=y +CONFIG_SPL_PAYLOAD_ARGS_ADDR=0x01700000 CONFIG_SYS_MONITOR_BASE=0x88000000 CONFIG_FIT=y CONFIG_SPL_LOAD_FIT_ADDRESS=0x80010000 diff --git a/configs/ae350_rv64_spl_defconfig b/configs/ae350_rv64_spl_defconfig index 68ac4325ab..e929320433 100644 --- a/configs/ae350_rv64_spl_defconfig +++ b/configs/ae350_rv64_spl_defconfig @@ -33,6 +33,7 @@ CONFIG_SYS_PROMPT="RISC-V # " CONFIG_CMD_IMLS=y CONFIG_CMD_MMC=y CONFIG_CMD_SF_TEST=y +CONFIG_CMD_WDT=y # CONFIG_CMD_SETEXPR is not set CONFIG_BOOTP_PREFER_SERVERIP=y CONFIG_CMD_CACHE=y @@ -58,3 +59,6 @@ CONFIG_SYS_NS16550=y CONFIG_SPI=y CONFIG_ATCSPI200_SPI=y # CONFIG_BINMAN_FDT is not set +# CONFIG_WATCHDOG_AUTOSTART is not set +CONFIG_WDT=y +CONFIG_WDT_ATCWDT200=y diff --git a/configs/ae350_rv64_spl_xip_defconfig b/configs/ae350_rv64_spl_xip_defconfig index 839ca335d4..3f92643b07 100644 --- a/configs/ae350_rv64_spl_xip_defconfig +++ b/configs/ae350_rv64_spl_xip_defconfig @@ -34,6 +34,7 @@ CONFIG_SYS_PROMPT="RISC-V # " CONFIG_CMD_IMLS=y CONFIG_CMD_MMC=y CONFIG_CMD_SF_TEST=y +CONFIG_CMD_WDT=y # CONFIG_CMD_SETEXPR is not set CONFIG_BOOTP_PREFER_SERVERIP=y CONFIG_CMD_CACHE=y @@ -59,3 +60,6 @@ CONFIG_SYS_NS16550=y CONFIG_SPI=y CONFIG_ATCSPI200_SPI=y # CONFIG_BINMAN_FDT is not set +# CONFIG_WATCHDOG_AUTOSTART is not set +CONFIG_WDT=y +CONFIG_WDT_ATCWDT200=y diff --git a/configs/ae350_rv64_xip_defconfig b/configs/ae350_rv64_xip_defconfig index 5432b6d6d7..835f020990 100644 --- a/configs/ae350_rv64_xip_defconfig +++ b/configs/ae350_rv64_xip_defconfig @@ -24,6 +24,7 @@ CONFIG_SYS_PROMPT="RISC-V # " CONFIG_CMD_IMLS=y CONFIG_CMD_MMC=y CONFIG_CMD_SF_TEST=y +CONFIG_CMD_WDT=y # CONFIG_CMD_SETEXPR is not set CONFIG_BOOTP_PREFER_SERVERIP=y CONFIG_CMD_CACHE=y @@ -50,3 +51,6 @@ CONFIG_BAUDRATE=38400 CONFIG_SYS_NS16550=y CONFIG_SPI=y CONFIG_ATCSPI200_SPI=y +# CONFIG_WATCHDOG_AUTOSTART is not set +CONFIG_WDT=y +CONFIG_WDT_ATCWDT200=y diff --git a/configs/milkv_duo_defconfig b/configs/milkv_duo_defconfig new file mode 100644 index 0000000000..9eca6abfbc --- /dev/null +++ b/configs/milkv_duo_defconfig @@ -0,0 +1,23 @@ +CONFIG_RISCV=y +CONFIG_SYS_MALLOC_LEN=0x820000 +CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_NR_DRAM_BANKS=1 +CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y +CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x82300000 +CONFIG_DEFAULT_DEVICE_TREE="cv1800b-milkv-duo" +CONFIG_IDENT_STRING="milkv_duo" +CONFIG_SYS_LOAD_ADDR=0x80080000 +CONFIG_TARGET_MILKV_DUO=y +CONFIG_ARCH_RV64I=y +CONFIG_RISCV_SMODE=y +CONFIG_FIT=y +CONFIG_SUPPORT_RAW_INITRD=y +CONFIG_HUSH_PARSER=y +CONFIG_SYS_PROMPT="milkv_duo# " +CONFIG_SYS_MAXARGS=64 +CONFIG_SYS_CBSIZE=512 +CONFIG_SYS_PBSIZE=544 +CONFIG_SYS_BOOTM_LEN=0x4000000 +CONFIG_ENV_OVERWRITE=y +CONFIG_SYS_NS16550=y +CONFIG_SYS_NS16550_MEM32=y diff --git a/configs/starfive_visionfive2_defconfig b/configs/starfive_visionfive2_defconfig index 1b7d57bac7..c68f3c2def 100644 --- a/configs/starfive_visionfive2_defconfig +++ b/configs/starfive_visionfive2_defconfig @@ -77,7 +77,6 @@ CONFIG_CMD_TFTPPUT=y CONFIG_CMD_BOOTSTAGE=y CONFIG_OF_BOARD=y CONFIG_ENV_OVERWRITE=y -CONFIG_ENV_IS_NOWHERE=y CONFIG_ENV_IS_IN_SPI_FLASH=y CONFIG_ENV_SECT_SIZE_AUTO=y CONFIG_SYS_RELOC_GD_ENV_ADDR=y diff --git a/doc/board/index.rst b/doc/board/index.rst index c96e5fda28..d0f9f355d2 100644 --- a/doc/board/index.rst +++ b/doc/board/index.rst @@ -46,6 +46,7 @@ Board-specific doc sifive/index sipeed/index socionext/index + sophgo/index st/index starfive/index ste/index diff --git a/doc/board/sophgo/index.rst b/doc/board/sophgo/index.rst new file mode 100644 index 0000000000..e097afdac6 --- /dev/null +++ b/doc/board/sophgo/index.rst @@ -0,0 +1,8 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Sophgo +====== +.. toctree:: + :maxdepth: 1 + + milkv_duo diff --git a/doc/board/sophgo/milkv_duo.rst b/doc/board/sophgo/milkv_duo.rst new file mode 100644 index 0000000000..cb2ed1ad98 --- /dev/null +++ b/doc/board/sophgo/milkv_duo.rst @@ -0,0 +1,64 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Milk-V Duo +========== + +CV1800B RISC-V SoC +------------------ +The CV1800B is a high-performance, low-power 1+1 64-bit RISC-V SoC from Sophgo. + +Mainline support +---------------- +The support for following drivers are already enabled: +1. ns16550 UART Driver. + +Building +~~~~~~~~ +1. Add the RISC-V toolchain to your PATH. +2. Setup ARCH & cross compilation environment variable: + +.. code-block:: console + + export CROSS_COMPILE=<riscv64 toolchain prefix> + cd <U-Boot-dir> + make milkv_duo_defconfig + make + +This will generate u-boot-dtb.bin + +Booting +~~~~~~~ +Currently, we rely on vendor FSBL(First Stage Boot Loader) to initialize the +clock and load the u-boot image, then bootup from it. + +Alternatively, to run u-boot-dtb.bin on top of FSBL, follow these steps: + +1. Use the vendor-provided tool to create a unified fip.bin file containing + FSBL, OpenSBI, and U-Boot. + +2. Place the generated fip.bin file into the FAT partition of the SD card. + +3. Insert the SD card into the board and power it on. + +The board will automatically execute the FSBL from the fip.bin file. +Subsequently, it will transition to OpenSBI, and finally, OpenSBI will invoke +U-Boot. + + +Sample boot log from Milk-V Duo board +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.. code-block:: none + + U-Boot 2024.01-rc5-00010-g51965baa36 (Dec 28 2023 - 13:15:53 +0800)milkv_duo + + DRAM: 63.3 MiB + Core: 10 devices, 8 uclasses, devicetree: separate + Loading Environment from nowhere... OK + In: serial@4140000 + Out: serial@4140000 + Err: serial@4140000 + Net: No ethernet found. + milkv_duo# cpu detail + 0: cpu@0 rv64imafdc + ID = 0, freq = 0 Hz: L1 cache, MMU + milkv_duo# diff --git a/doc/develop/falcon.rst b/doc/develop/falcon.rst index 8a46c0efa1..244b4ccb5c 100644 --- a/doc/develop/falcon.rst +++ b/doc/develop/falcon.rst @@ -256,3 +256,161 @@ the following command: Falcon Mode was presented at the RMLL 2012. Slides are available at: http://schedule2012.rmll.info/IMG/pdf/LSM2012_UbootFalconMode_Babic.pdf + +Falcon Mode Boot on RISC-V +-------------------------- + +Introduction +~~~~~~~~~~~~ + +In the RISC-V environment, OpenSBI is required to enable a supervisor mode +binary to execute certain privileged operations. The typical boot sequence on +RISC-V is SPL -> OpenSBI -> U-Boot -> Linux kernel. SPL will load and start +the OpenSBI initializations, then OpenSBI will bring up the next image, U-Boot +proper. The OpenSBI binary must be prepared in advance of the U-Boot build +process and it will be packed together with U-Boot into a file called +u-boot.itb. + +The Falcon Mode on RISC-V platforms is a distinct boot sequence. Borrowing +ideas from the U-Boot Falcon Mode on ARM, it skips the U-Boot proper phase +in the normal boot process and allows OpenSBI to load and start the Linux +kernel. Its boot sequence is SPL -> OpenSBI -> Linux kernel. The OpenSBI +binary and Linux kernel binary must be prepared prior to the U-Boot build +process and they will be packed together as a FIT image named linux.itb in +this process. + +CONFIG_SPL_LOAD_FIT_OPENSBI_OS_BOOT enables the Falcon Mode boot on RISC-V. +This configuration setting tells OpenSBI that Linux kernel is its next OS +image and makes it load and start the kernel afterwards. + +Note that the Falcon Mode boot bypasses a lot of initializations by U-Boot. +If the Linux kernel expects hardware initializations by U-Boot, make sure to +port the relevant code to the SPL build process. + +Configuration +~~~~~~~~~~~~~ + +CONFIG_SPL_LOAD_FIT_ADDRESS + Specifies the address to load u-boot.itb in a normal boot. When the Falcon + Mode boot is enabled, it specifies the load address of linux.itb. + +CONFIG_SYS_TEXT_BASE + Specifies the address of the text section for a u-boot proper in a normal + boot. When the Falcon Mode boot is enabled, it specifies the text section + address for the Linux kernel image. + +CONFIG_SPL_PAYLOAD_ARGS_ADDR + The address in the RAM to which the FDT blob is to be moved by the SPL. + SPL places the FDT blob right after the kernel. As the kernel does not + include the BSS section in its size calculation, SPL ends up placing + the FDT blob within the BSS section of the kernel. This may cause the + FDT blob to be cleared during kernel BSS initialization. To avoid the + issue, be sure to move the FDT blob out of the kernel first. + +CONFIG_SPL_LOAD_FIT_OPENSBI_OS_BOOT + Activates the Falcon Mode boot on RISC-V. + +Example for Andes AE350 Board +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A FDT blob is required to boot the Linux kernel from the SPL. Andes AE350 +platforms generally come with a builtin dtb. To load a custom DTB, follow +these steps: + +1. Load the custom DTB to SDRAM:: + + => fatload mmc 0:1 0x20000000 user_custom.dtb + +2. Set the SPI speed:: + + => sf probe 0:0 50000000 0 + +3. Erase sectors from the SPI Flash:: + + => sf erase 0xf0000 0x10000 + +4. Write the FDT blob to the erased sectors of the Flash:: + + => sf write 0x20000000 0xf0000 0x10000 + +Console Log of AE350 Falcon Mode Boot +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + U-Boot SPL 2023.01-00031-g777ecdea66 (Oct 31 2023 - 18:41:36 +0800) + Trying to boot from RAM + + OpenSBI v1.2-51-g7304e42 + ____ _____ ____ _____ + / __ \ / ____| _ \_ _| + | | | |_ __ ___ _ __ | (___ | |_) || | + | | | | '_ \ / _ \ '_ \ \___ \| _ < | | + | |__| | |_) | __/ | | |____) | |_) || |_ + \____/| .__/ \___|_| |_|_____/|____/_____| + | | + |_| + + Platform Name : andestech,ax25 + Platform Features : medeleg + Platform HART Count : 1 + Platform IPI Device : andes_plicsw + Platform Timer Device : andes_plmt @ 60000000Hz + Platform Console Device : uart8250 + Platform HSM Device : andes_smu + Platform PMU Device : andes_pmu + Platform Reboot Device : atcwdt200 + Platform Shutdown Device : --- + Firmware Base : 0x0 + Firmware Size : 196 KB + Runtime SBI Version : 1.0 + + Domain0 Name : root + Domain0 Boot HART : 0 + Domain0 HARTs : 0* + Domain0 Region00 : 0x0000000000000000-0x000000000003ffff () + Domain0 Region01 : 0x00000000e6000000-0x00000000e60fffff (I,R) + Domain0 Region02 : 0x00000000e6400000-0x00000000e67fffff (I) + Domain0 Region03 : 0x0000000000000000-0xffffffffffffffff (R,W,X) + Domain0 Next Address : 0x0000000001800000 + Domain0 Next Arg1 : 0x0000000001700000 + Domain0 Next Mode : S-mode + Domain0 SysReset : yes + + Boot HART ID : 0 + Boot HART Domain : root + Boot HART Priv Version : v1.11 + Boot HART Base ISA : rv64imafdcx + Boot HART ISA Extensions : none + Boot HART PMP Count : 8 + Boot HART PMP Granularity : 4 + Boot HART PMP Address Bits: 31 + Boot HART MHPM Count : 4 + Boot HART MHPM Bits : 64 + Boot HART MIDELEG : 0x0000000000000222 + Boot HART MEDELEG : 0x000000000000b109 + [ 0.000000] Linux version 6.1.47-09019-g0584b09ad862-dirty + [ 0.000000] OF: fdt: Ignoring memory range 0x0 - 0x1800000 + [ 0.000000] Machine model: andestech,ax25 + [ 0.000000] earlycon: sbi0 at I/O port 0x0 (options '') + [ 0.000000] printk: bootconsole [sbi0] enabled + [ 0.000000] Disabled 4-level and 5-level paging + [ 0.000000] efi: UEFI not found. + [ 0.000000] Zone ranges: + [ 0.000000] DMA32 [mem 0x0000000001800000-0x000000003fffffff] + [ 0.000000] Normal empty + [ 0.000000] Movable zone start for each node + [ 0.000000] Early memory node ranges + [ 0.000000] node 0: [mem 0x0000000001800000-0x000000003fffffff] + [ 0.000000] Initmem setup node 0 [mem 0x0000000001800000-0x000000003fffffff] + [ 0.000000] SBI specification v1.0 detected + [ 0.000000] SBI implementation ID=0x1 Version=0x10002 + [ 0.000000] SBI TIME extension detected + [ 0.000000] SBI IPI extension detected + [ 0.000000] SBI RFENCE extension detected + [ 0.000000] SBI SRST extension detected + [ 0.000000] SBI HSM extension detected + [ 0.000000] riscv: base ISA extensions acim + [ 0.000000] riscv: ELF capabilities acim + [ 0.000000] percpu: Embedded 18 pages/cpu s35000 r8192 d30536 u73728 + [ 0.000000] Built 1 zonelists, mobility grouping on. Total pages: 252500 diff --git a/drivers/clk/aspeed/clk_ast2600.c b/drivers/clk/aspeed/clk_ast2600.c index eecfacd7fc..a15909329b 100644 --- a/drivers/clk/aspeed/clk_ast2600.c +++ b/drivers/clk/aspeed/clk_ast2600.c @@ -1143,8 +1143,6 @@ static void ast2600_clk_dump(struct udevice *dev) ret = clk_get_rate(&clk); rate = ret; - clk_free(&clk); - if (ret == -EINVAL) { printf("clk ID %lu not supported yet\n", aspeed_clk_names[i].id); diff --git a/drivers/clk/at91/compat.c b/drivers/clk/at91/compat.c index 2fdc2fbd55..ee67093c60 100644 --- a/drivers/clk/at91/compat.c +++ b/drivers/clk/at91/compat.c @@ -516,7 +516,6 @@ static ulong periph_get_rate(struct clk *clk) { struct udevice *dev; struct clk clk_dev; - ulong clk_rate; int ret; dev = dev_get_parent(clk->dev); @@ -525,11 +524,7 @@ static ulong periph_get_rate(struct clk *clk) if (ret) return ret; - clk_rate = clk_get_rate(&clk_dev); - - clk_free(&clk_dev); - - return clk_rate; + return clk_get_rate(&clk_dev); } static struct clk_ops periph_clk_ops = { @@ -762,7 +757,6 @@ static ulong generic_clk_get_rate(struct clk *clk) struct pmc_plat *plat = dev_get_plat(clk->dev); struct at91_pmc *pmc = plat->reg_base; struct clk parent; - ulong clk_rate; u32 tmp, gckdiv; u8 clock_source, parent_index; int ret; @@ -778,11 +772,7 @@ static ulong generic_clk_get_rate(struct clk *clk) if (ret) return 0; - clk_rate = clk_get_rate(&parent) / (gckdiv + 1); - - clk_free(&parent); - - return clk_rate; + return clk_get_rate(&parent) / (gckdiv + 1); } static ulong generic_clk_set_rate(struct clk *clk, ulong rate) diff --git a/drivers/clk/clk-gpio.c b/drivers/clk/clk-gpio.c index 26d795b978..4ed1430657 100644 --- a/drivers/clk/clk-gpio.c +++ b/drivers/clk/clk-gpio.c @@ -3,19 +3,23 @@ * Copyright (C) 2023 Marek Vasut <marek.vasut+renesas@mailbox.org> */ -#include <asm/gpio.h> -#include <common.h> +#include <clk.h> #include <clk-uclass.h> #include <dm.h> +#include <linux/clk-provider.h> + +#include <asm/gpio.h> struct clk_gpio_priv { - struct gpio_desc enable; + struct gpio_desc enable; /* GPIO, controlling the gate */ + struct clk *clk; /* Gated clock */ }; static int clk_gpio_enable(struct clk *clk) { struct clk_gpio_priv *priv = dev_get_priv(clk->dev); + clk_enable(priv->clk); dm_gpio_set_value(&priv->enable, 1); return 0; @@ -26,21 +30,45 @@ static int clk_gpio_disable(struct clk *clk) struct clk_gpio_priv *priv = dev_get_priv(clk->dev); dm_gpio_set_value(&priv->enable, 0); + clk_disable(priv->clk); return 0; } +static ulong clk_gpio_get_rate(struct clk *clk) +{ + struct clk_gpio_priv *priv = dev_get_priv(clk->dev); + + return clk_get_rate(priv->clk); +} + const struct clk_ops clk_gpio_ops = { .enable = clk_gpio_enable, .disable = clk_gpio_disable, + .get_rate = clk_gpio_get_rate, }; static int clk_gpio_probe(struct udevice *dev) { struct clk_gpio_priv *priv = dev_get_priv(dev); + int ret; + + priv->clk = devm_clk_get(dev, NULL); + if (IS_ERR(priv->clk)) { + log_debug("%s: Could not get gated clock: %ld\n", + __func__, PTR_ERR(priv->clk)); + return PTR_ERR(priv->clk); + } - return gpio_request_by_name(dev, "enable-gpios", 0, - &priv->enable, GPIOD_IS_OUT); + ret = gpio_request_by_name(dev, "enable-gpios", 0, + &priv->enable, GPIOD_IS_OUT); + if (ret) { + log_debug("%s: Could not decode enable-gpios (%d)\n", + __func__, ret); + return ret; + } + + return 0; } /* diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c index 3e9d68feb3..ed6e60bc48 100644 --- a/drivers/clk/clk-uclass.c +++ b/drivers/clk/clk-uclass.c @@ -437,8 +437,6 @@ int clk_release_all(struct clk *clk, unsigned int count) ret = clk_disable(&clk[i]); if (ret && ret != -ENOSYS) return ret; - - clk_free(&clk[i]); } return 0; @@ -461,24 +459,9 @@ int clk_request(struct udevice *dev, struct clk *clk) return ops->request(clk); } -void clk_free(struct clk *clk) -{ - const struct clk_ops *ops; - - debug("%s(clk=%p)\n", __func__, clk); - if (!clk_valid(clk)) - return; - ops = clk_dev_ops(clk->dev); - - if (ops->rfree) - ops->rfree(clk); - return; -} - ulong clk_get_rate(struct clk *clk) { const struct clk_ops *ops; - ulong ret; debug("%s(clk=%p)\n", __func__, clk); if (!clk_valid(clk)) @@ -488,11 +471,7 @@ ulong clk_get_rate(struct clk *clk) if (!ops->get_rate) return -ENOSYS; - ret = ops->get_rate(clk); - if (ret) - return log_ret(ret); - - return 0; + return ops->get_rate(clk); } struct clk *clk_get_parent(struct clk *clk) @@ -791,22 +770,12 @@ bool clk_is_match(const struct clk *p, const struct clk *q) return false; } -static void devm_clk_release(struct udevice *dev, void *res) -{ - clk_free(res); -} - -static int devm_clk_match(struct udevice *dev, void *res, void *data) -{ - return res == data; -} - struct clk *devm_clk_get(struct udevice *dev, const char *id) { int rc; struct clk *clk; - clk = devres_alloc(devm_clk_release, sizeof(struct clk), __GFP_ZERO); + clk = devm_kzalloc(dev, sizeof(*clk), GFP_KERNEL); if (unlikely(!clk)) return ERR_PTR(-ENOMEM); @@ -814,21 +783,9 @@ struct clk *devm_clk_get(struct udevice *dev, const char *id) if (rc) return ERR_PTR(rc); - devres_add(dev, clk); return clk; } -void devm_clk_put(struct udevice *dev, struct clk *clk) -{ - int rc; - - if (!clk) - return; - - rc = devres_release(dev, devm_clk_release, devm_clk_match, clk); - WARN_ON(rc); -} - int clk_uclass_post_probe(struct udevice *dev) { /* diff --git a/drivers/clk/clk-xlnx-clock-wizard.c b/drivers/clk/clk-xlnx-clock-wizard.c index 70ee3af107..a10a843f11 100644 --- a/drivers/clk/clk-xlnx-clock-wizard.c +++ b/drivers/clk/clk-xlnx-clock-wizard.c @@ -137,7 +137,6 @@ static int clk_wzrd_probe(struct udevice *dev) ret = clk_enable(&clk_in1); if (ret) { dev_err(dev, "failed to enable clock\n"); - clk_free(&clk_in1); return ret; } diff --git a/drivers/clk/clk_sandbox.c b/drivers/clk/clk_sandbox.c index 636914db8c..73d943f9e0 100644 --- a/drivers/clk/clk_sandbox.c +++ b/drivers/clk/clk_sandbox.c @@ -101,17 +101,6 @@ static int sandbox_clk_request(struct clk *clk) return 0; } -static void sandbox_clk_free(struct clk *clk) -{ - struct sandbox_clk_priv *priv = dev_get_priv(clk->dev); - - if (clk->id >= SANDBOX_CLK_ID_COUNT) - return; - - priv->requested[clk->id] = false; - return; -} - static struct clk_ops sandbox_clk_ops = { .round_rate = sandbox_clk_round_rate, .get_rate = sandbox_clk_get_rate, @@ -119,7 +108,6 @@ static struct clk_ops sandbox_clk_ops = { .enable = sandbox_clk_enable, .disable = sandbox_clk_disable, .request = sandbox_clk_request, - .rfree = sandbox_clk_free, }; static int sandbox_clk_probe(struct udevice *dev) diff --git a/drivers/clk/clk_sandbox_test.c b/drivers/clk/clk_sandbox_test.c index c695b69321..c224dc1d2c 100644 --- a/drivers/clk/clk_sandbox_test.c +++ b/drivers/clk/clk_sandbox_test.c @@ -135,18 +135,6 @@ int sandbox_clk_test_disable_bulk(struct udevice *dev) return clk_disable_bulk(&sbct->bulk); } -int sandbox_clk_test_free(struct udevice *dev) -{ - struct sandbox_clk_test *sbct = dev_get_priv(dev); - int i; - - devm_clk_put(dev, sbct->clkps[SANDBOX_CLK_TEST_ID_DEVM1]); - for (i = 0; i < SANDBOX_CLK_TEST_NON_DEVM_COUNT; i++) - clk_free(&sbct->clks[i]); - - return 0; -} - int sandbox_clk_test_release_bulk(struct udevice *dev) { struct sandbox_clk_test *sbct = dev_get_priv(dev); diff --git a/drivers/clk/clk_versaclock.c b/drivers/clk/clk_versaclock.c index 699df3cf3e..bbe7225603 100644 --- a/drivers/clk/clk_versaclock.c +++ b/drivers/clk/clk_versaclock.c @@ -1000,26 +1000,18 @@ int versaclock_probe(struct udevice *dev) return 0; free_out: - for (n = 1; n < vc5->chip_info->clk_out_cnt; n++) { - clk_free(&vc5->clk_out[n].hw); + for (n = 1; n < vc5->chip_info->clk_out_cnt; n++) free(out_name[n]); - } free_selb: - clk_free(&vc5->clk_out[0].hw); free(outsel_name); free_fod: - for (n = 0; n < vc5->chip_info->clk_fod_cnt; n++) { - clk_free(&vc5->clk_fod[n].hw); + for (n = 0; n < vc5->chip_info->clk_fod_cnt; n++) free(fod_name[n]); - } free_pll: - clk_free(&vc5->clk_pll.hw); free(pll_name); free_pfd: - clk_free(&vc5->clk_pfd); free(pfd_name); free_mux: - clk_free(&vc5->clk_mux); free(mux_name); return ret; diff --git a/drivers/clk/clk_zynq.c b/drivers/clk/clk_zynq.c index 34f964d72a..e3cefe2e0c 100644 --- a/drivers/clk/clk_zynq.c +++ b/drivers/clk/clk_zynq.c @@ -491,8 +491,6 @@ static void zynq_clk_dump(struct udevice *dev) rate = clk_get_rate(&clk); - clk_free(&clk); - if ((rate == (unsigned long)-ENOSYS) || (rate == (unsigned long)-ENXIO)) printf("%10s%20s\n", name, "unknown"); diff --git a/drivers/clk/clk_zynqmp.c b/drivers/clk/clk_zynqmp.c index 0ffac194a1..e23f7da3f9 100644 --- a/drivers/clk/clk_zynqmp.c +++ b/drivers/clk/clk_zynqmp.c @@ -757,8 +757,6 @@ static void zynqmp_clk_dump(struct udevice *dev) rate = clk_get_rate(&clk); - clk_free(&clk); - if ((rate == (unsigned long)-ENOSYS) || (rate == (unsigned long)-ENXIO) || (rate == (unsigned long)-EIO)) diff --git a/drivers/clk/imx/clk-imx8.c b/drivers/clk/imx/clk-imx8.c index 9600672e07..d39b87b2e2 100644 --- a/drivers/clk/imx/clk-imx8.c +++ b/drivers/clk/imx/clk-imx8.c @@ -62,8 +62,6 @@ static void imx8_clk_dump(struct udevice *dev) ret = clk_get_rate(&clk); rate = ret; - clk_free(&clk); - if (ret == -EINVAL) { printf("clk ID %lu not supported yet\n", imx8_clk_names[i].id); diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig index cdc9d6f76c..ee33c61140 100644 --- a/drivers/clk/meson/Kconfig +++ b/drivers/clk/meson/Kconfig @@ -29,3 +29,13 @@ config CLK_MESON_A1 help Enable clock support for the Amlogic A1 SoC family, such as the A113L + +config CLK_MESON_MSR + bool "Enable clock measure driver for Amlogic SoCs" + depends on CLK && ARCH_MESON + depends on CMD_CLK + default ARCH_MESON + help + Enable measuring a set of internal Amlogic SoC clock frequencies + using the Hardware Clock Measure registers and print them using + the clk dump command. diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile index d975f07aab..c7a446e86c 100644 --- a/drivers/clk/meson/Makefile +++ b/drivers/clk/meson/Makefile @@ -9,3 +9,4 @@ obj-$(CONFIG_CLK_MESON_AXG) += axg-ao.o obj-$(CONFIG_CLK_MESON_G12A) += g12a.o obj-$(CONFIG_CLK_MESON_G12A) += g12a-ao.o obj-$(CONFIG_CLK_MESON_A1) += a1.o +obj-$(CONFIG_CLK_MESON_MSR) += clk-measure.o diff --git a/drivers/clk/meson/clk-measure.c b/drivers/clk/meson/clk-measure.c new file mode 100644 index 0000000000..f653fc6355 --- /dev/null +++ b/drivers/clk/meson/clk-measure.c @@ -0,0 +1,634 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Based on Linux driver from: + * (C) Copyright 2018 - BayLibre, SAS + * Author: Neil Armstrong <narmstrong@baylibre.com> + * (C) Copyright 2023 - Neil Armstrong <neil.armstrong@linaro.org> + */ + +#include <log.h> +#include <clk-uclass.h> +#include <div64.h> +#include <dm.h> +#include <time.h> +#include <regmap.h> +#include <syscon.h> +#include <linux/bitops.h> +#include <linux/bitfield.h> +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/kernel.h> + +#define MSR_CLK_DUTY 0x0 +#define MSR_CLK_REG0 0x4 +#define MSR_CLK_REG1 0x8 +#define MSR_CLK_REG2 0xc + +#define MSR_DURATION GENMASK(15, 0) +#define MSR_ENABLE BIT(16) +#define MSR_CONT BIT(17) /* continuous measurement */ +#define MSR_INTR BIT(18) /* interrupts */ +#define MSR_RUN BIT(19) +#define MSR_CLK_SRC GENMASK(26, 20) +#define MSR_BUSY BIT(31) + +#define MSR_VAL_MASK GENMASK(15, 0) + +#define DIV_MIN 32 +#define DIV_STEP 32 +#define DIV_MAX 640 + +#define CLK_MSR_MAX 128 + +struct meson_msr_id { + unsigned int id; + const char *name; +}; + +struct meson_msr { + struct regmap *regmap; + struct meson_msr_id *msr_table; +}; + +#define CLK_MSR_ID(__id, __name) \ + [__id] = {.id = __id, .name = __name,} + +static struct meson_msr_id clk_msr_m8[CLK_MSR_MAX] = { + CLK_MSR_ID(0, "ring_osc_out_ee0"), + CLK_MSR_ID(1, "ring_osc_out_ee1"), + CLK_MSR_ID(2, "ring_osc_out_ee2"), + CLK_MSR_ID(3, "a9_ring_osck"), + CLK_MSR_ID(6, "vid_pll"), + CLK_MSR_ID(7, "clk81"), + CLK_MSR_ID(8, "encp"), + CLK_MSR_ID(9, "encl"), + CLK_MSR_ID(11, "eth_rmii"), + CLK_MSR_ID(13, "amclk"), + CLK_MSR_ID(14, "fec_clk_0"), + CLK_MSR_ID(15, "fec_clk_1"), + CLK_MSR_ID(16, "fec_clk_2"), + CLK_MSR_ID(18, "a9_clk_div16"), + CLK_MSR_ID(19, "hdmi_sys"), + CLK_MSR_ID(20, "rtc_osc_clk_out"), + CLK_MSR_ID(21, "i2s_clk_in_src0"), + CLK_MSR_ID(22, "clk_rmii_from_pad"), + CLK_MSR_ID(23, "hdmi_ch0_tmds"), + CLK_MSR_ID(24, "lvds_fifo"), + CLK_MSR_ID(26, "sc_clk_int"), + CLK_MSR_ID(28, "sar_adc"), + CLK_MSR_ID(30, "mpll_clk_test_out"), + CLK_MSR_ID(31, "audac_clkpi"), + CLK_MSR_ID(32, "vdac"), + CLK_MSR_ID(33, "sdhc_rx"), + CLK_MSR_ID(34, "sdhc_sd"), + CLK_MSR_ID(35, "mali"), + CLK_MSR_ID(36, "hdmi_tx_pixel"), + CLK_MSR_ID(38, "vdin_meas"), + CLK_MSR_ID(39, "pcm_sclk"), + CLK_MSR_ID(40, "pcm_mclk"), + CLK_MSR_ID(41, "eth_rx_tx"), + CLK_MSR_ID(42, "pwm_d"), + CLK_MSR_ID(43, "pwm_c"), + CLK_MSR_ID(44, "pwm_b"), + CLK_MSR_ID(45, "pwm_a"), + CLK_MSR_ID(46, "pcm2_sclk"), + CLK_MSR_ID(47, "ddr_dpll_pt"), + CLK_MSR_ID(48, "pwm_f"), + CLK_MSR_ID(49, "pwm_e"), + CLK_MSR_ID(59, "hcodec"), + CLK_MSR_ID(60, "usb_32k_alt"), + CLK_MSR_ID(61, "gpio"), + CLK_MSR_ID(62, "vid2_pll"), + CLK_MSR_ID(63, "mipi_csi_cfg"), +}; + +static struct meson_msr_id clk_msr_gx[CLK_MSR_MAX] = { + CLK_MSR_ID(0, "ring_osc_out_ee_0"), + CLK_MSR_ID(1, "ring_osc_out_ee_1"), + CLK_MSR_ID(2, "ring_osc_out_ee_2"), + CLK_MSR_ID(3, "a53_ring_osc"), + CLK_MSR_ID(4, "gp0_pll"), + CLK_MSR_ID(6, "enci"), + CLK_MSR_ID(7, "clk81"), + CLK_MSR_ID(8, "encp"), + CLK_MSR_ID(9, "encl"), + CLK_MSR_ID(10, "vdac"), + CLK_MSR_ID(11, "rgmii_tx"), + CLK_MSR_ID(12, "pdm"), + CLK_MSR_ID(13, "amclk"), + CLK_MSR_ID(14, "fec_0"), + CLK_MSR_ID(15, "fec_1"), + CLK_MSR_ID(16, "fec_2"), + CLK_MSR_ID(17, "sys_pll_div16"), + CLK_MSR_ID(18, "sys_cpu_div16"), + CLK_MSR_ID(19, "hdmitx_sys"), + CLK_MSR_ID(20, "rtc_osc_out"), + CLK_MSR_ID(21, "i2s_in_src0"), + CLK_MSR_ID(22, "eth_phy_ref"), + CLK_MSR_ID(23, "hdmi_todig"), + CLK_MSR_ID(26, "sc_int"), + CLK_MSR_ID(28, "sar_adc"), + CLK_MSR_ID(31, "mpll_test_out"), + CLK_MSR_ID(32, "vdec"), + CLK_MSR_ID(35, "mali"), + CLK_MSR_ID(36, "hdmi_tx_pixel"), + CLK_MSR_ID(37, "i958"), + CLK_MSR_ID(38, "vdin_meas"), + CLK_MSR_ID(39, "pcm_sclk"), + CLK_MSR_ID(40, "pcm_mclk"), + CLK_MSR_ID(41, "eth_rx_or_rmii"), + CLK_MSR_ID(42, "mp0_out"), + CLK_MSR_ID(43, "fclk_div5"), + CLK_MSR_ID(44, "pwm_b"), + CLK_MSR_ID(45, "pwm_a"), + CLK_MSR_ID(46, "vpu"), + CLK_MSR_ID(47, "ddr_dpll_pt"), + CLK_MSR_ID(48, "mp1_out"), + CLK_MSR_ID(49, "mp2_out"), + CLK_MSR_ID(50, "mp3_out"), + CLK_MSR_ID(51, "nand_core"), + CLK_MSR_ID(52, "sd_emmc_b"), + CLK_MSR_ID(53, "sd_emmc_a"), + CLK_MSR_ID(55, "vid_pll_div_out"), + CLK_MSR_ID(56, "cci"), + CLK_MSR_ID(57, "wave420l_c"), + CLK_MSR_ID(58, "wave420l_b"), + CLK_MSR_ID(59, "hcodec"), + CLK_MSR_ID(60, "alt_32k"), + CLK_MSR_ID(61, "gpio_msr"), + CLK_MSR_ID(62, "hevc"), + CLK_MSR_ID(66, "vid_lock"), + CLK_MSR_ID(70, "pwm_f"), + CLK_MSR_ID(71, "pwm_e"), + CLK_MSR_ID(72, "pwm_d"), + CLK_MSR_ID(73, "pwm_c"), + CLK_MSR_ID(75, "aoclkx2_int"), + CLK_MSR_ID(76, "aoclk_int"), + CLK_MSR_ID(77, "rng_ring_osc_0"), + CLK_MSR_ID(78, "rng_ring_osc_1"), + CLK_MSR_ID(79, "rng_ring_osc_2"), + CLK_MSR_ID(80, "rng_ring_osc_3"), + CLK_MSR_ID(81, "vapb"), + CLK_MSR_ID(82, "ge2d"), +}; + +static struct meson_msr_id clk_msr_axg[CLK_MSR_MAX] = { + CLK_MSR_ID(0, "ring_osc_out_ee_0"), + CLK_MSR_ID(1, "ring_osc_out_ee_1"), + CLK_MSR_ID(2, "ring_osc_out_ee_2"), + CLK_MSR_ID(3, "a53_ring_osc"), + CLK_MSR_ID(4, "gp0_pll"), + CLK_MSR_ID(5, "gp1_pll"), + CLK_MSR_ID(7, "clk81"), + CLK_MSR_ID(9, "encl"), + CLK_MSR_ID(17, "sys_pll_div16"), + CLK_MSR_ID(18, "sys_cpu_div16"), + CLK_MSR_ID(20, "rtc_osc_out"), + CLK_MSR_ID(23, "mmc_clk"), + CLK_MSR_ID(28, "sar_adc"), + CLK_MSR_ID(31, "mpll_test_out"), + CLK_MSR_ID(40, "mod_eth_tx_clk"), + CLK_MSR_ID(41, "mod_eth_rx_clk_rmii"), + CLK_MSR_ID(42, "mp0_out"), + CLK_MSR_ID(43, "fclk_div5"), + CLK_MSR_ID(44, "pwm_b"), + CLK_MSR_ID(45, "pwm_a"), + CLK_MSR_ID(46, "vpu"), + CLK_MSR_ID(47, "ddr_dpll_pt"), + CLK_MSR_ID(48, "mp1_out"), + CLK_MSR_ID(49, "mp2_out"), + CLK_MSR_ID(50, "mp3_out"), + CLK_MSR_ID(51, "sd_emmm_c"), + CLK_MSR_ID(52, "sd_emmc_b"), + CLK_MSR_ID(61, "gpio_msr"), + CLK_MSR_ID(66, "audio_slv_lrclk_c"), + CLK_MSR_ID(67, "audio_slv_lrclk_b"), + CLK_MSR_ID(68, "audio_slv_lrclk_a"), + CLK_MSR_ID(69, "audio_slv_sclk_c"), + CLK_MSR_ID(70, "audio_slv_sclk_b"), + CLK_MSR_ID(71, "audio_slv_sclk_a"), + CLK_MSR_ID(72, "pwm_d"), + CLK_MSR_ID(73, "pwm_c"), + CLK_MSR_ID(74, "wifi_beacon"), + CLK_MSR_ID(75, "tdmin_lb_lrcl"), + CLK_MSR_ID(76, "tdmin_lb_sclk"), + CLK_MSR_ID(77, "rng_ring_osc_0"), + CLK_MSR_ID(78, "rng_ring_osc_1"), + CLK_MSR_ID(79, "rng_ring_osc_2"), + CLK_MSR_ID(80, "rng_ring_osc_3"), + CLK_MSR_ID(81, "vapb"), + CLK_MSR_ID(82, "ge2d"), + CLK_MSR_ID(84, "audio_resample"), + CLK_MSR_ID(85, "audio_pdm_sys"), + CLK_MSR_ID(86, "audio_spdifout"), + CLK_MSR_ID(87, "audio_spdifin"), + CLK_MSR_ID(88, "audio_lrclk_f"), + CLK_MSR_ID(89, "audio_lrclk_e"), + CLK_MSR_ID(90, "audio_lrclk_d"), + CLK_MSR_ID(91, "audio_lrclk_c"), + CLK_MSR_ID(92, "audio_lrclk_b"), + CLK_MSR_ID(93, "audio_lrclk_a"), + CLK_MSR_ID(94, "audio_sclk_f"), + CLK_MSR_ID(95, "audio_sclk_e"), + CLK_MSR_ID(96, "audio_sclk_d"), + CLK_MSR_ID(97, "audio_sclk_c"), + CLK_MSR_ID(98, "audio_sclk_b"), + CLK_MSR_ID(99, "audio_sclk_a"), + CLK_MSR_ID(100, "audio_mclk_f"), + CLK_MSR_ID(101, "audio_mclk_e"), + CLK_MSR_ID(102, "audio_mclk_d"), + CLK_MSR_ID(103, "audio_mclk_c"), + CLK_MSR_ID(104, "audio_mclk_b"), + CLK_MSR_ID(105, "audio_mclk_a"), + CLK_MSR_ID(106, "pcie_refclk_n"), + CLK_MSR_ID(107, "pcie_refclk_p"), + CLK_MSR_ID(108, "audio_locker_out"), + CLK_MSR_ID(109, "audio_locker_in"), +}; + +static struct meson_msr_id clk_msr_g12a[CLK_MSR_MAX] = { + CLK_MSR_ID(0, "ring_osc_out_ee_0"), + CLK_MSR_ID(1, "ring_osc_out_ee_1"), + CLK_MSR_ID(2, "ring_osc_out_ee_2"), + CLK_MSR_ID(3, "sys_cpu_ring_osc"), + CLK_MSR_ID(4, "gp0_pll"), + CLK_MSR_ID(6, "enci"), + CLK_MSR_ID(7, "clk81"), + CLK_MSR_ID(8, "encp"), + CLK_MSR_ID(9, "encl"), + CLK_MSR_ID(10, "vdac"), + CLK_MSR_ID(11, "eth_tx"), + CLK_MSR_ID(12, "hifi_pll"), + CLK_MSR_ID(13, "mod_tcon"), + CLK_MSR_ID(14, "fec_0"), + CLK_MSR_ID(15, "fec_1"), + CLK_MSR_ID(16, "fec_2"), + CLK_MSR_ID(17, "sys_pll_div16"), + CLK_MSR_ID(18, "sys_cpu_div16"), + CLK_MSR_ID(19, "lcd_an_ph2"), + CLK_MSR_ID(20, "rtc_osc_out"), + CLK_MSR_ID(21, "lcd_an_ph3"), + CLK_MSR_ID(22, "eth_phy_ref"), + CLK_MSR_ID(23, "mpll_50m"), + CLK_MSR_ID(24, "eth_125m"), + CLK_MSR_ID(25, "eth_rmii"), + CLK_MSR_ID(26, "sc_int"), + CLK_MSR_ID(27, "in_mac"), + CLK_MSR_ID(28, "sar_adc"), + CLK_MSR_ID(29, "pcie_inp"), + CLK_MSR_ID(30, "pcie_inn"), + CLK_MSR_ID(31, "mpll_test_out"), + CLK_MSR_ID(32, "vdec"), + CLK_MSR_ID(33, "sys_cpu_ring_osc_1"), + CLK_MSR_ID(34, "eth_mpll_50m"), + CLK_MSR_ID(35, "mali"), + CLK_MSR_ID(36, "hdmi_tx_pixel"), + CLK_MSR_ID(37, "cdac"), + CLK_MSR_ID(38, "vdin_meas"), + CLK_MSR_ID(39, "bt656"), + CLK_MSR_ID(41, "eth_rx_or_rmii"), + CLK_MSR_ID(42, "mp0_out"), + CLK_MSR_ID(43, "fclk_div5"), + CLK_MSR_ID(44, "pwm_b"), + CLK_MSR_ID(45, "pwm_a"), + CLK_MSR_ID(46, "vpu"), + CLK_MSR_ID(47, "ddr_dpll_pt"), + CLK_MSR_ID(48, "mp1_out"), + CLK_MSR_ID(49, "mp2_out"), + CLK_MSR_ID(50, "mp3_out"), + CLK_MSR_ID(51, "sd_emmc_c"), + CLK_MSR_ID(52, "sd_emmc_b"), + CLK_MSR_ID(53, "sd_emmc_a"), + CLK_MSR_ID(54, "vpu_clkc"), + CLK_MSR_ID(55, "vid_pll_div_out"), + CLK_MSR_ID(56, "wave420l_a"), + CLK_MSR_ID(57, "wave420l_c"), + CLK_MSR_ID(58, "wave420l_b"), + CLK_MSR_ID(59, "hcodec"), + CLK_MSR_ID(61, "gpio_msr"), + CLK_MSR_ID(62, "hevcb"), + CLK_MSR_ID(63, "dsi_meas"), + CLK_MSR_ID(64, "spicc_1"), + CLK_MSR_ID(65, "spicc_0"), + CLK_MSR_ID(66, "vid_lock"), + CLK_MSR_ID(67, "dsi_phy"), + CLK_MSR_ID(68, "hdcp22_esm"), + CLK_MSR_ID(69, "hdcp22_skp"), + CLK_MSR_ID(70, "pwm_f"), + CLK_MSR_ID(71, "pwm_e"), + CLK_MSR_ID(72, "pwm_d"), + CLK_MSR_ID(73, "pwm_c"), + CLK_MSR_ID(75, "hevcf"), + CLK_MSR_ID(77, "rng_ring_osc_0"), + CLK_MSR_ID(78, "rng_ring_osc_1"), + CLK_MSR_ID(79, "rng_ring_osc_2"), + CLK_MSR_ID(80, "rng_ring_osc_3"), + CLK_MSR_ID(81, "vapb"), + CLK_MSR_ID(82, "ge2d"), + CLK_MSR_ID(83, "co_rx"), + CLK_MSR_ID(84, "co_tx"), + CLK_MSR_ID(89, "hdmi_todig"), + CLK_MSR_ID(90, "hdmitx_sys"), + CLK_MSR_ID(91, "sys_cpub_div16"), + CLK_MSR_ID(92, "sys_pll_cpub_div16"), + CLK_MSR_ID(94, "eth_phy_rx"), + CLK_MSR_ID(95, "eth_phy_pll"), + CLK_MSR_ID(96, "vpu_b"), + CLK_MSR_ID(97, "cpu_b_tmp"), + CLK_MSR_ID(98, "ts"), + CLK_MSR_ID(99, "ring_osc_out_ee_3"), + CLK_MSR_ID(100, "ring_osc_out_ee_4"), + CLK_MSR_ID(101, "ring_osc_out_ee_5"), + CLK_MSR_ID(102, "ring_osc_out_ee_6"), + CLK_MSR_ID(103, "ring_osc_out_ee_7"), + CLK_MSR_ID(104, "ring_osc_out_ee_8"), + CLK_MSR_ID(105, "ring_osc_out_ee_9"), + CLK_MSR_ID(106, "ephy_test"), + CLK_MSR_ID(107, "au_dac_g128x"), + CLK_MSR_ID(108, "audio_locker_out"), + CLK_MSR_ID(109, "audio_locker_in"), + CLK_MSR_ID(110, "audio_tdmout_c_sclk"), + CLK_MSR_ID(111, "audio_tdmout_b_sclk"), + CLK_MSR_ID(112, "audio_tdmout_a_sclk"), + CLK_MSR_ID(113, "audio_tdmin_lb_sclk"), + CLK_MSR_ID(114, "audio_tdmin_c_sclk"), + CLK_MSR_ID(115, "audio_tdmin_b_sclk"), + CLK_MSR_ID(116, "audio_tdmin_a_sclk"), + CLK_MSR_ID(117, "audio_resample"), + CLK_MSR_ID(118, "audio_pdm_sys"), + CLK_MSR_ID(119, "audio_spdifout_b"), + CLK_MSR_ID(120, "audio_spdifout"), + CLK_MSR_ID(121, "audio_spdifin"), + CLK_MSR_ID(122, "audio_pdm_dclk"), +}; + +static struct meson_msr_id clk_msr_sm1[CLK_MSR_MAX] = { + CLK_MSR_ID(0, "ring_osc_out_ee_0"), + CLK_MSR_ID(1, "ring_osc_out_ee_1"), + CLK_MSR_ID(2, "ring_osc_out_ee_2"), + CLK_MSR_ID(3, "ring_osc_out_ee_3"), + CLK_MSR_ID(4, "gp0_pll"), + CLK_MSR_ID(5, "gp1_pll"), + CLK_MSR_ID(6, "enci"), + CLK_MSR_ID(7, "clk81"), + CLK_MSR_ID(8, "encp"), + CLK_MSR_ID(9, "encl"), + CLK_MSR_ID(10, "vdac"), + CLK_MSR_ID(11, "eth_tx"), + CLK_MSR_ID(12, "hifi_pll"), + CLK_MSR_ID(13, "mod_tcon"), + CLK_MSR_ID(14, "fec_0"), + CLK_MSR_ID(15, "fec_1"), + CLK_MSR_ID(16, "fec_2"), + CLK_MSR_ID(17, "sys_pll_div16"), + CLK_MSR_ID(18, "sys_cpu_div16"), + CLK_MSR_ID(19, "lcd_an_ph2"), + CLK_MSR_ID(20, "rtc_osc_out"), + CLK_MSR_ID(21, "lcd_an_ph3"), + CLK_MSR_ID(22, "eth_phy_ref"), + CLK_MSR_ID(23, "mpll_50m"), + CLK_MSR_ID(24, "eth_125m"), + CLK_MSR_ID(25, "eth_rmii"), + CLK_MSR_ID(26, "sc_int"), + CLK_MSR_ID(27, "in_mac"), + CLK_MSR_ID(28, "sar_adc"), + CLK_MSR_ID(29, "pcie_inp"), + CLK_MSR_ID(30, "pcie_inn"), + CLK_MSR_ID(31, "mpll_test_out"), + CLK_MSR_ID(32, "vdec"), + CLK_MSR_ID(34, "eth_mpll_50m"), + CLK_MSR_ID(35, "mali"), + CLK_MSR_ID(36, "hdmi_tx_pixel"), + CLK_MSR_ID(37, "cdac"), + CLK_MSR_ID(38, "vdin_meas"), + CLK_MSR_ID(39, "bt656"), + CLK_MSR_ID(40, "arm_ring_osc_out_4"), + CLK_MSR_ID(41, "eth_rx_or_rmii"), + CLK_MSR_ID(42, "mp0_out"), + CLK_MSR_ID(43, "fclk_div5"), + CLK_MSR_ID(44, "pwm_b"), + CLK_MSR_ID(45, "pwm_a"), + CLK_MSR_ID(46, "vpu"), + CLK_MSR_ID(47, "ddr_dpll_pt"), + CLK_MSR_ID(48, "mp1_out"), + CLK_MSR_ID(49, "mp2_out"), + CLK_MSR_ID(50, "mp3_out"), + CLK_MSR_ID(51, "sd_emmc_c"), + CLK_MSR_ID(52, "sd_emmc_b"), + CLK_MSR_ID(53, "sd_emmc_a"), + CLK_MSR_ID(54, "vpu_clkc"), + CLK_MSR_ID(55, "vid_pll_div_out"), + CLK_MSR_ID(56, "wave420l_a"), + CLK_MSR_ID(57, "wave420l_c"), + CLK_MSR_ID(58, "wave420l_b"), + CLK_MSR_ID(59, "hcodec"), + CLK_MSR_ID(60, "arm_ring_osc_out_5"), + CLK_MSR_ID(61, "gpio_msr"), + CLK_MSR_ID(62, "hevcb"), + CLK_MSR_ID(63, "dsi_meas"), + CLK_MSR_ID(64, "spicc_1"), + CLK_MSR_ID(65, "spicc_0"), + CLK_MSR_ID(66, "vid_lock"), + CLK_MSR_ID(67, "dsi_phy"), + CLK_MSR_ID(68, "hdcp22_esm"), + CLK_MSR_ID(69, "hdcp22_skp"), + CLK_MSR_ID(70, "pwm_f"), + CLK_MSR_ID(71, "pwm_e"), + CLK_MSR_ID(72, "pwm_d"), + CLK_MSR_ID(73, "pwm_c"), + CLK_MSR_ID(74, "arm_ring_osc_out_6"), + CLK_MSR_ID(75, "hevcf"), + CLK_MSR_ID(76, "arm_ring_osc_out_7"), + CLK_MSR_ID(77, "rng_ring_osc_0"), + CLK_MSR_ID(78, "rng_ring_osc_1"), + CLK_MSR_ID(79, "rng_ring_osc_2"), + CLK_MSR_ID(80, "rng_ring_osc_3"), + CLK_MSR_ID(81, "vapb"), + CLK_MSR_ID(82, "ge2d"), + CLK_MSR_ID(83, "co_rx"), + CLK_MSR_ID(84, "co_tx"), + CLK_MSR_ID(85, "arm_ring_osc_out_8"), + CLK_MSR_ID(86, "arm_ring_osc_out_9"), + CLK_MSR_ID(87, "mipi_dsi_phy"), + CLK_MSR_ID(88, "cis2_adapt"), + CLK_MSR_ID(89, "hdmi_todig"), + CLK_MSR_ID(90, "hdmitx_sys"), + CLK_MSR_ID(91, "nna_core"), + CLK_MSR_ID(92, "nna_axi"), + CLK_MSR_ID(93, "vad"), + CLK_MSR_ID(94, "eth_phy_rx"), + CLK_MSR_ID(95, "eth_phy_pll"), + CLK_MSR_ID(96, "vpu_b"), + CLK_MSR_ID(97, "cpu_b_tmp"), + CLK_MSR_ID(98, "ts"), + CLK_MSR_ID(99, "arm_ring_osc_out_10"), + CLK_MSR_ID(100, "arm_ring_osc_out_11"), + CLK_MSR_ID(101, "arm_ring_osc_out_12"), + CLK_MSR_ID(102, "arm_ring_osc_out_13"), + CLK_MSR_ID(103, "arm_ring_osc_out_14"), + CLK_MSR_ID(104, "arm_ring_osc_out_15"), + CLK_MSR_ID(105, "arm_ring_osc_out_16"), + CLK_MSR_ID(106, "ephy_test"), + CLK_MSR_ID(107, "au_dac_g128x"), + CLK_MSR_ID(108, "audio_locker_out"), + CLK_MSR_ID(109, "audio_locker_in"), + CLK_MSR_ID(110, "audio_tdmout_c_sclk"), + CLK_MSR_ID(111, "audio_tdmout_b_sclk"), + CLK_MSR_ID(112, "audio_tdmout_a_sclk"), + CLK_MSR_ID(113, "audio_tdmin_lb_sclk"), + CLK_MSR_ID(114, "audio_tdmin_c_sclk"), + CLK_MSR_ID(115, "audio_tdmin_b_sclk"), + CLK_MSR_ID(116, "audio_tdmin_a_sclk"), + CLK_MSR_ID(117, "audio_resample"), + CLK_MSR_ID(118, "audio_pdm_sys"), + CLK_MSR_ID(119, "audio_spdifout_b"), + CLK_MSR_ID(120, "audio_spdifout"), + CLK_MSR_ID(121, "audio_spdifin"), + CLK_MSR_ID(122, "audio_pdm_dclk"), + CLK_MSR_ID(123, "audio_resampled"), + CLK_MSR_ID(124, "earcrx_pll"), + CLK_MSR_ID(125, "earcrx_pll_test"), + CLK_MSR_ID(126, "csi_phy0"), + CLK_MSR_ID(127, "csi2_data"), +}; + +static int meson_clk_msr_measure_id(struct meson_msr *priv, unsigned int id, + unsigned int duration) +{ + unsigned int val; + int ret; + + regmap_write(priv->regmap, MSR_CLK_REG0, 0); + + /* Set measurement duration */ + regmap_update_bits(priv->regmap, MSR_CLK_REG0, MSR_DURATION, + FIELD_PREP(MSR_DURATION, duration - 1)); + + /* Set ID */ + regmap_update_bits(priv->regmap, MSR_CLK_REG0, MSR_CLK_SRC, + FIELD_PREP(MSR_CLK_SRC, id)); + + /* Enable & Start */ + regmap_update_bits(priv->regmap, MSR_CLK_REG0, + MSR_RUN | MSR_ENABLE, + MSR_RUN | MSR_ENABLE); + + ret = regmap_read_poll_timeout(priv->regmap, MSR_CLK_REG0, + val, !(val & MSR_BUSY), 10, 10000); + if (ret) + return ret; + + /* Disable */ + regmap_update_bits(priv->regmap, MSR_CLK_REG0, MSR_ENABLE, 0); + + /* Get the value in multiple of gate time counts */ + regmap_read(priv->regmap, MSR_CLK_REG2, &val); + + if (val >= MSR_VAL_MASK) + return -EINVAL; + + return DIV_ROUND_CLOSEST_ULL((val & MSR_VAL_MASK) * 1000000ULL, + duration); +} + +static int meson_clk_msr_best_id(struct meson_msr *priv, unsigned int id, + unsigned int *precision) +{ + unsigned int duration = DIV_MAX; + int ret; + + /* Start from max duration and down to min duration */ + do { + ret = meson_clk_msr_measure_id(priv, id, duration); + if (ret >= 0) + *precision = (2 * 1000000) / duration; + else + duration -= DIV_STEP; + } while (duration >= DIV_MIN && ret == -EINVAL); + + return ret; +} + +static void meson_clk_msr_dump(struct udevice *dev) +{ + struct meson_msr *priv = dev_get_priv(dev); + unsigned int precision = 0; + int val, i; + + printf(" clock rate precision\n"); + printf("---------------------------------------------\n"); + + for (i = 0 ; i < CLK_MSR_MAX ; ++i) { + if (!priv->msr_table[i].name) + continue; + + val = meson_clk_msr_best_id(priv, i, &precision); + if (val < 0) + return; + + printf(" %-20s %10d +/-%dHz\n", + priv->msr_table[i].name, val, precision); + } +} + +static int meson_clk_msr_xlate(struct clk *clk, struct ofnode_phandle_args *args) +{ + /* This driver doesn't expose any clocks */ + return -EINVAL; +} + +static int meson_clk_msr_probe(struct udevice *dev) +{ + struct meson_msr *priv = dev_get_priv(dev); + int ret; + + priv->msr_table = (struct meson_msr_id *)dev_get_driver_data(dev); + + ret = regmap_init_mem(dev_ofnode(dev), &priv->regmap); + if (ret) + return ret; + + return 0; +} + +static struct clk_ops meson_clk_msr_ops = { + .of_xlate = meson_clk_msr_xlate, + .dump = meson_clk_msr_dump, +}; + +static const struct udevice_id meson_clk_msr_ids[] = { + { + .compatible = "amlogic,meson-gx-clk-measure", + .data = (ulong)clk_msr_gx, + }, + { + .compatible = "amlogic,meson8-clk-measure", + .data = (ulong)clk_msr_m8, + }, + { + .compatible = "amlogic,meson8b-clk-measure", + .data = (ulong)clk_msr_m8, + }, + { + .compatible = "amlogic,meson-axg-clk-measure", + .data = (ulong)clk_msr_axg, + }, + { + .compatible = "amlogic,meson-g12a-clk-measure", + .data = (ulong)clk_msr_g12a, + }, + { + .compatible = "amlogic,meson-sm1-clk-measure", + .data = (ulong)clk_msr_sm1, + }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(meson_clk_msr) = { + .name = "meson_clk_msr", + .id = UCLASS_CLK, + .of_match = meson_clk_msr_ids, + .priv_auto = sizeof(struct meson_msr), + .ops = &meson_clk_msr_ops, + .probe = meson_clk_msr_probe, +}; diff --git a/drivers/clk/mvebu/armada-37xx-periph.c b/drivers/clk/mvebu/armada-37xx-periph.c index 1a7097029a..f5c9bd735c 100644 --- a/drivers/clk/mvebu/armada-37xx-periph.c +++ b/drivers/clk/mvebu/armada-37xx-periph.c @@ -454,7 +454,6 @@ static int armada_37xx_periph_clk_set_parent(struct clk *clk, if (parent->dev != check_parent.dev) ret = -EINVAL; - clk_free(&check_parent); if (ret < 0) return ret; @@ -596,7 +595,6 @@ static int armada_37xx_periph_clk_probe(struct udevice *dev) } priv->parents[i] = clk_get_rate(&clk); - clk_free(&clk); } return 0; diff --git a/drivers/cpu/riscv_cpu.c b/drivers/cpu/riscv_cpu.c index 034b9b49c0..a9b253719f 100644 --- a/drivers/cpu/riscv_cpu.c +++ b/drivers/cpu/riscv_cpu.c @@ -45,7 +45,6 @@ static int riscv_cpu_get_info(const struct udevice *dev, struct cpu_info *info) ret = clk_get_rate(&clk); if (!IS_ERR_VALUE(ret)) info->cpu_freq = ret; - clk_free(&clk); } if (!info->cpu_freq) @@ -145,7 +144,6 @@ static int riscv_cpu_probe(struct udevice *dev) return 0; ret = clk_enable(&clk); - clk_free(&clk); if (ret == -ENOSYS || ret == -ENOTSUPP) return 0; else diff --git a/drivers/dma/bcm6348-iudma.c b/drivers/dma/bcm6348-iudma.c index d4cfe0c186..33c7b98141 100644 --- a/drivers/dma/bcm6348-iudma.c +++ b/drivers/dma/bcm6348-iudma.c @@ -596,8 +596,6 @@ static int bcm6348_iudma_probe(struct udevice *dev) pr_err("error enabling clock %d\n", i); return ret; } - - clk_free(&clk); } /* try to perform resets */ diff --git a/drivers/gpio/at91_gpio.c b/drivers/gpio/at91_gpio.c index 1409db5dc1..f80f4afd24 100644 --- a/drivers/gpio/at91_gpio.c +++ b/drivers/gpio/at91_gpio.c @@ -603,8 +603,6 @@ static int at91_gpio_probe(struct udevice *dev) if (ret) return ret; - clk_free(&clk); - #if CONFIG_IS_ENABLED(OF_CONTROL) plat->base_addr = dev_read_addr(dev); #endif diff --git a/drivers/gpio/atmel_pio4.c b/drivers/gpio/atmel_pio4.c index 47ed297981..be1dd752bf 100644 --- a/drivers/gpio/atmel_pio4.c +++ b/drivers/gpio/atmel_pio4.c @@ -310,8 +310,6 @@ static int atmel_pio4_probe(struct udevice *dev) if (ret) return ret; - clk_free(&clk); - addr_base = dev_read_addr(dev); if (addr_base == FDT_ADDR_T_NONE) return -EINVAL; diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c index d6cfbd231a..7077850123 100644 --- a/drivers/gpio/gpio-rcar.c +++ b/drivers/gpio/gpio-rcar.c @@ -165,7 +165,6 @@ static int rcar_gpio_probe(struct udevice *dev) } ret = clk_enable(&clk); - clk_free(&clk); if (ret) { dev_err(dev, "Failed to enable GPIO bank clock\n"); return ret; diff --git a/drivers/hwspinlock/stm32_hwspinlock.c b/drivers/hwspinlock/stm32_hwspinlock.c index 46ed64655a..346b138e98 100644 --- a/drivers/hwspinlock/stm32_hwspinlock.c +++ b/drivers/hwspinlock/stm32_hwspinlock.c @@ -69,11 +69,7 @@ static int stm32mp1_hwspinlock_probe(struct udevice *dev) if (ret) return ret; - ret = clk_enable(&clk); - if (ret) - clk_free(&clk); - - return ret; + return clk_enable(&clk); } static const struct hwspinlock_ops stm32mp1_hwspinlock_ops = { diff --git a/drivers/i2c/at91_i2c.c b/drivers/i2c/at91_i2c.c index e743d2a849..b7a25885e6 100644 --- a/drivers/i2c/at91_i2c.c +++ b/drivers/i2c/at91_i2c.c @@ -201,8 +201,6 @@ static int at91_i2c_enable_clk(struct udevice *dev) bus->bus_clk_rate = clk_rate; - clk_free(&clk); - return 0; } diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c index 215ce010cb..29cf63375c 100644 --- a/drivers/i2c/designware_i2c.c +++ b/drivers/i2c/designware_i2c.c @@ -770,7 +770,6 @@ int designware_i2c_of_to_plat(struct udevice *bus) ret = clk_enable(&priv->clk); if (ret && ret != -ENOSYS && ret != -ENOTSUPP) { - clk_free(&priv->clk); dev_err(bus, "failed to enable clock\n"); return ret; } @@ -803,7 +802,6 @@ int designware_i2c_remove(struct udevice *dev) #if CONFIG_IS_ENABLED(CLK) clk_disable(&priv->clk); - clk_free(&priv->clk); #endif return reset_release_bulk(&priv->resets); diff --git a/drivers/i2c/i2c-microchip.c b/drivers/i2c/i2c-microchip.c index d82b80f535..d453e243d6 100644 --- a/drivers/i2c/i2c-microchip.c +++ b/drivers/i2c/i2c-microchip.c @@ -183,8 +183,6 @@ static int mpfs_i2c_init(struct mpfs_i2c_bus *bus, struct udevice *dev) if (!clk_rate) return -EINVAL; - clk_free(&bus->i2c_clk); - divisor = clk_rate / bus->clk_rate; ctrl = readl(bus->base + MPFS_I2C_CTRL); diff --git a/drivers/i2c/npcm_i2c.c b/drivers/i2c/npcm_i2c.c index b867b6c8e9..c64752e146 100644 --- a/drivers/i2c/npcm_i2c.c +++ b/drivers/i2c/npcm_i2c.c @@ -570,7 +570,6 @@ static int npcm_i2c_probe(struct udevice *dev) printf("%s: fail to get rate\n", __func__); return -EINVAL; } - clk_free(&clk); bus->num = dev->seq_; bus->reg = dev_read_addr_ptr(dev); diff --git a/drivers/i2c/ocores_i2c.c b/drivers/i2c/ocores_i2c.c index 3b19ba78fa..fff85118d0 100644 --- a/drivers/i2c/ocores_i2c.c +++ b/drivers/i2c/ocores_i2c.c @@ -396,8 +396,6 @@ static int ocores_i2c_enable_clk(struct udevice *dev) bus->ip_clk_khz = clk_rate / 1000; - clk_free(&bus->clk); - return 0; } diff --git a/drivers/i2c/stm32f7_i2c.c b/drivers/i2c/stm32f7_i2c.c index eaa1d69289..f42e08a641 100644 --- a/drivers/i2c/stm32f7_i2c.c +++ b/drivers/i2c/stm32f7_i2c.c @@ -890,7 +890,7 @@ static int stm32_i2c_probe(struct udevice *dev) ret = clk_enable(&i2c_priv->clk); if (ret) - goto clk_free; + return ret; ret = reset_get_by_index(dev, 0, &reset_ctl); if (ret) @@ -904,8 +904,6 @@ static int stm32_i2c_probe(struct udevice *dev) clk_disable: clk_disable(&i2c_priv->clk); -clk_free: - clk_free(&i2c_priv->clk); return ret; } diff --git a/drivers/mailbox/stm32-ipcc.c b/drivers/mailbox/stm32-ipcc.c index 69c86e059f..046e1a8aca 100644 --- a/drivers/mailbox/stm32-ipcc.c +++ b/drivers/mailbox/stm32-ipcc.c @@ -134,18 +134,13 @@ static int stm32_ipcc_probe(struct udevice *dev) ret = clk_enable(&clk); if (ret) - goto clk_free; + return ret; /* get channel number */ ipcc->n_chans = readl(ipcc->reg_base + IPCC_HWCFGR); ipcc->n_chans &= IPCFGR_CHAN_MASK; return 0; - -clk_free: - clk_free(&clk); - - return ret; } static const struct udevice_id stm32_ipcc_ids[] = { diff --git a/drivers/misc/ls2_sfp.c b/drivers/misc/ls2_sfp.c index 2a81bc7de5..5351c7ed34 100644 --- a/drivers/misc/ls2_sfp.c +++ b/drivers/misc/ls2_sfp.c @@ -249,7 +249,6 @@ static int ls2_sfp_probe(struct udevice *dev) } rate = clk_get_rate(&clk); - clk_free(&clk); if (!rate || IS_ERR_VALUE(rate)) { ret = rate ? rate : -ENOENT; dev_dbg(dev, "could not get clock rate (err %d)\n", diff --git a/drivers/mmc/arm_pl180_mmci.c b/drivers/mmc/arm_pl180_mmci.c index 9c5d48e90c..5cf5502ed5 100644 --- a/drivers/mmc/arm_pl180_mmci.c +++ b/drivers/mmc/arm_pl180_mmci.c @@ -447,7 +447,6 @@ static int arm_pl180_mmc_probe(struct udevice *dev) ret = clk_enable(&clk); if (ret) { - clk_free(&clk); dev_err(dev, "failed to enable clock\n"); return ret; } diff --git a/drivers/mmc/aspeed_sdhci.c b/drivers/mmc/aspeed_sdhci.c index 9d79bf58cc..c9626c6beb 100644 --- a/drivers/mmc/aspeed_sdhci.c +++ b/drivers/mmc/aspeed_sdhci.c @@ -35,7 +35,7 @@ static int aspeed_sdhci_probe(struct udevice *dev) ret = clk_enable(&clk); if (ret) { debug("%s: clock enable failed %d\n", __func__, ret); - goto free; + return ret; } host->name = dev->name; @@ -66,8 +66,6 @@ static int aspeed_sdhci_probe(struct udevice *dev) err: clk_disable(&clk); -free: - clk_free(&clk); return ret; } diff --git a/drivers/mmc/atmel_sdhci.c b/drivers/mmc/atmel_sdhci.c index 5347ba9043..d92bad97b7 100644 --- a/drivers/mmc/atmel_sdhci.c +++ b/drivers/mmc/atmel_sdhci.c @@ -147,8 +147,6 @@ static int atmel_sdhci_probe(struct udevice *dev) host->ops = &atmel_sdhci_ops; upriv->mmc = host->mmc; - clk_free(&clk); - ret = sdhci_probe(dev); if (ret) return ret; diff --git a/drivers/mmc/gen_atmel_mci.c b/drivers/mmc/gen_atmel_mci.c index d91819acfd..3ee99558f6 100644 --- a/drivers/mmc/gen_atmel_mci.c +++ b/drivers/mmc/gen_atmel_mci.c @@ -559,27 +559,20 @@ static int atmel_mci_enable_clk(struct udevice *dev) int ret = 0; ret = clk_get_by_index(dev, 0, &clk); - if (ret) { - ret = -EINVAL; - goto failed; - } + if (ret) + return -EINVAL; ret = clk_enable(&clk); if (ret) - goto failed; + return ret; clk_rate = clk_get_rate(&clk); - if (!clk_rate) { - ret = -EINVAL; - goto failed; - } + if (!clk_rate) + return -EINVAL; priv->bus_clk_rate = clk_rate; -failed: - clk_free(&clk); - - return ret; + return 0; } static int atmel_mci_probe(struct udevice *dev) diff --git a/drivers/mmc/msm_sdhci.c b/drivers/mmc/msm_sdhci.c index 604f9c3ff9..fe1e754bfd 100644 --- a/drivers/mmc/msm_sdhci.c +++ b/drivers/mmc/msm_sdhci.c @@ -81,7 +81,6 @@ static int msm_sdc_clk_init(struct udevice *dev) return ret; ret = clk_set_rate(&clk, clk_rate); - clk_free(&clk); if (ret < 0) return ret; diff --git a/drivers/mmc/pic32_sdhci.c b/drivers/mmc/pic32_sdhci.c index fe555106a1..7a8e33dbc7 100644 --- a/drivers/mmc/pic32_sdhci.c +++ b/drivers/mmc/pic32_sdhci.c @@ -32,7 +32,6 @@ static int pic32_sdhci_probe(struct udevice *dev) return ret; clk_rate = clk_get_rate(&clk); - clk_free(&clk); if (IS_ERR_VALUE(clk_rate)) return clk_rate; diff --git a/drivers/mmc/renesas-sdhi.c b/drivers/mmc/renesas-sdhi.c index 97aaf1e4ec..a74559ca68 100644 --- a/drivers/mmc/renesas-sdhi.c +++ b/drivers/mmc/renesas-sdhi.c @@ -979,19 +979,19 @@ static int rzg2l_sdhi_setup(struct udevice *dev) ret = clk_get_by_name(dev, "cd", &imclk2); if (ret < 0) { dev_err(dev, "failed to get imclk2 (chip detect clk)\n"); - goto err_get_imclk2; + return ret; } ret = clk_get_by_name(dev, "aclk", &aclk); if (ret < 0) { dev_err(dev, "failed to get aclk\n"); - goto err_get_aclk; + return ret; } ret = clk_enable(&imclk2); if (ret < 0) { dev_err(dev, "failed to enable imclk2 (chip detect clk)\n"); - goto err_imclk2; + return ret; } ret = clk_enable(&aclk); @@ -1026,11 +1026,6 @@ err_get_reset: clk_disable(&aclk); err_aclk: clk_disable(&imclk2); -err_imclk2: - clk_free(&aclk); -err_get_aclk: - clk_free(&imclk2); -err_get_imclk2: return ret; } @@ -1071,7 +1066,7 @@ static int renesas_sdhi_probe(struct udevice *dev) ret = clk_set_rate(&priv->clkh, 800000000); if (ret < 0) { dev_err(dev, "failed to set rate for SDnH clock (%d)\n", ret); - goto err_clk; + return ret; } } @@ -1079,13 +1074,13 @@ static int renesas_sdhi_probe(struct udevice *dev) ret = clk_set_rate(&priv->clk, 200000000); if (ret < 0) { dev_err(dev, "failed to set rate for SDn clock (%d)\n", ret); - goto err_clkh; + return ret; } ret = clk_enable(&priv->clk); if (ret) { dev_err(dev, "failed to enable SDn clock (%d)\n", ret); - goto err_clkh; + return ret; } if (device_is_compatible(dev, "renesas,sdhi-r9a07g044")) @@ -1107,10 +1102,6 @@ static int renesas_sdhi_probe(struct udevice *dev) err_tmio_probe: clk_disable(&priv->clk); -err_clkh: - clk_free(&priv->clkh); -err_clk: - clk_free(&priv->clk); return ret; } diff --git a/drivers/mmc/snps_dw_mmc.c b/drivers/mmc/snps_dw_mmc.c index 50a8805e73..0134399e39 100644 --- a/drivers/mmc/snps_dw_mmc.c +++ b/drivers/mmc/snps_dw_mmc.c @@ -46,7 +46,7 @@ static int snps_dwmmc_clk_setup(struct udevice *dev) ret = clk_enable(&clk_ciu); if (ret && ret != -ENOSYS && ret != -ENOTSUPP) - goto clk_err_ciu; + goto clk_err; host->bus_hz = clk_get_rate(&clk_ciu); if (host->bus_hz < CLOCK_MIN) { @@ -60,16 +60,12 @@ static int snps_dwmmc_clk_setup(struct udevice *dev) ret = clk_enable(&clk_biu); if (ret && ret != -ENOSYS && ret != -ENOTSUPP) - goto clk_err_biu; + goto clk_err_ciu_dis; return 0; -clk_err_biu: - clk_free(&clk_biu); clk_err_ciu_dis: clk_disable(&clk_ciu); -clk_err_ciu: - clk_free(&clk_ciu); clk_err: dev_err(dev, "failed to setup clocks, ret %d\n", ret); diff --git a/drivers/mmc/socfpga_dw_mmc.c b/drivers/mmc/socfpga_dw_mmc.c index be3d8bfb3d..387cb8b6b5 100644 --- a/drivers/mmc/socfpga_dw_mmc.c +++ b/drivers/mmc/socfpga_dw_mmc.c @@ -99,7 +99,6 @@ static int socfpga_dwmmc_get_clk_rate(struct udevice *dev) host->bus_hz = clk_get_rate(&clk); - clk_free(&clk); #else /* Fixed clock divide by 4 which due to the SDMMC wrapper */ host->bus_hz = cm_get_mmc_controller_clk_hz(); diff --git a/drivers/mmc/stm32_sdmmc2.c b/drivers/mmc/stm32_sdmmc2.c index 5ff5e1a4d8..a2b111a843 100644 --- a/drivers/mmc/stm32_sdmmc2.c +++ b/drivers/mmc/stm32_sdmmc2.c @@ -766,10 +766,8 @@ static int stm32_sdmmc2_probe(struct udevice *dev) int ret; ret = clk_enable(&plat->clk); - if (ret) { - clk_free(&plat->clk); + if (ret) return ret; - } upriv->mmc = &plat->mmc; diff --git a/drivers/mmc/uniphier-sd.c b/drivers/mmc/uniphier-sd.c index 75003a0113..8cde4308aa 100644 --- a/drivers/mmc/uniphier-sd.c +++ b/drivers/mmc/uniphier-sd.c @@ -64,7 +64,6 @@ static int uniphier_sd_probe(struct udevice *dev) ret = clk_set_rate(&priv->clk, ULONG_MAX); if (ret < 0) { dev_err(dev, "failed to set rate for host clock\n"); - clk_free(&priv->clk); return ret; } diff --git a/drivers/mtd/nand/raw/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c index a2151f9849..0e0441472b 100644 --- a/drivers/mtd/nand/raw/atmel/nand-controller.c +++ b/drivers/mtd/nand/raw/atmel/nand-controller.c @@ -1999,10 +1999,8 @@ atmel_hsmc_nand_controller_remove(struct atmel_nand_controller *nc) hsmc_nc = container_of(nc, struct atmel_hsmc_nand_controller, base); - if (hsmc_nc->clk) { + if (hsmc_nc->clk) clk_disable_unprepare(hsmc_nc->clk); - devm_clk_put(nc->dev, hsmc_nc->clk); - } return 0; } diff --git a/drivers/mtd/nand/raw/atmel/pmecc.c b/drivers/mtd/nand/raw/atmel/pmecc.c index e2e3f1ee6b..51f6bd2e65 100644 --- a/drivers/mtd/nand/raw/atmel/pmecc.c +++ b/drivers/mtd/nand/raw/atmel/pmecc.c @@ -816,9 +816,6 @@ int atmel_pmecc_wait_rdy(struct atmel_pmecc_user *user) } EXPORT_SYMBOL_GPL(atmel_pmecc_wait_rdy); -#define ATMEL_BASE_PMECC 0xffffe000 -#define ATMEL_BASE_PMERRLOC 0xffffe600 - static struct atmel_pmecc * atmel_pmecc_create(struct udevice *dev, const struct atmel_pmecc_caps *caps, diff --git a/drivers/mtd/renesas_rpc_hf.c b/drivers/mtd/renesas_rpc_hf.c index aca7a6cdd2..979b64d4a2 100644 --- a/drivers/mtd/renesas_rpc_hf.c +++ b/drivers/mtd/renesas_rpc_hf.c @@ -370,7 +370,6 @@ static int rpc_hf_probe(struct udevice *dev) } ret = clk_enable(&clk); - clk_free(&clk); if (ret) { dev_err(dev, "Failed to enable RPC clock\n"); return ret; diff --git a/drivers/net/bcm6348-eth.c b/drivers/net/bcm6348-eth.c index 72dcd07d30..15a94f6ce9 100644 --- a/drivers/net/bcm6348-eth.c +++ b/drivers/net/bcm6348-eth.c @@ -457,8 +457,6 @@ static int bcm6348_eth_probe(struct udevice *dev) pr_err("%s: error enabling clock %d\n", __func__, i); return ret; } - - clk_free(&clk); } /* try to perform resets */ diff --git a/drivers/net/bcm6368-eth.c b/drivers/net/bcm6368-eth.c index fdd938ce0d..9679a45b07 100644 --- a/drivers/net/bcm6368-eth.c +++ b/drivers/net/bcm6368-eth.c @@ -546,8 +546,6 @@ static int bcm6368_eth_probe(struct udevice *dev) pr_err("%s: error enabling clock %d\n", __func__, i); return ret; } - - clk_free(&clk); } /* try to perform resets */ diff --git a/drivers/net/designware.c b/drivers/net/designware.c index a174344b3e..c8696358d6 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -702,7 +702,6 @@ int designware_eth_probe(struct udevice *dev) err = clk_enable(&priv->clocks[i]); if (err && err != -ENOSYS && err != -ENOTSUPP) { pr_err("failed to enable clock %d\n", i); - clk_free(&priv->clocks[i]); goto clk_err; } priv->clock_count++; diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c index e40e399c80..9b3bce1dc8 100644 --- a/drivers/net/dwc_eth_qos.c +++ b/drivers/net/dwc_eth_qos.c @@ -1382,38 +1382,30 @@ static int eqos_probe_resources_tegra186(struct udevice *dev) ret = clk_get_by_name(dev, "master_bus", &eqos->clk_master_bus); if (ret) { pr_err("clk_get_by_name(master_bus) failed: %d", ret); - goto err_free_clk_slave_bus; + goto err_free_gpio_phy_reset; } ret = clk_get_by_name(dev, "rx", &eqos->clk_rx); if (ret) { pr_err("clk_get_by_name(rx) failed: %d", ret); - goto err_free_clk_master_bus; + goto err_free_gpio_phy_reset; } ret = clk_get_by_name(dev, "ptp_ref", &eqos->clk_ptp_ref); if (ret) { pr_err("clk_get_by_name(ptp_ref) failed: %d", ret); - goto err_free_clk_rx; + goto err_free_gpio_phy_reset; } ret = clk_get_by_name(dev, "tx", &eqos->clk_tx); if (ret) { pr_err("clk_get_by_name(tx) failed: %d", ret); - goto err_free_clk_ptp_ref; + goto err_free_gpio_phy_reset; } debug("%s: OK\n", __func__); return 0; -err_free_clk_ptp_ref: - clk_free(&eqos->clk_ptp_ref); -err_free_clk_rx: - clk_free(&eqos->clk_rx); -err_free_clk_master_bus: - clk_free(&eqos->clk_master_bus); -err_free_clk_slave_bus: - clk_free(&eqos->clk_slave_bus); err_free_gpio_phy_reset: dm_gpio_free(dev, &eqos->phy_reset_gpio); err_free_reset_eqos: @@ -1451,13 +1443,13 @@ static int eqos_probe_resources_stm32(struct udevice *dev) ret = clk_get_by_name(dev, "mac-clk-rx", &eqos->clk_rx); if (ret) { pr_err("clk_get_by_name(rx) failed: %d", ret); - goto err_free_clk_master_bus; + goto err_probe; } ret = clk_get_by_name(dev, "mac-clk-tx", &eqos->clk_tx); if (ret) { pr_err("clk_get_by_name(tx) failed: %d", ret); - goto err_free_clk_rx; + goto err_probe; } /* Get ETH_CLK clocks (optional) */ @@ -1468,10 +1460,6 @@ static int eqos_probe_resources_stm32(struct udevice *dev) debug("%s: OK\n", __func__); return 0; -err_free_clk_rx: - clk_free(&eqos->clk_rx); -err_free_clk_master_bus: - clk_free(&eqos->clk_master_bus); err_probe: debug("%s: returns %d\n", __func__, ret); @@ -1489,13 +1477,6 @@ static int eqos_remove_resources_tegra186(struct udevice *dev) debug("%s(dev=%p):\n", __func__, dev); -#ifdef CONFIG_CLK - clk_free(&eqos->clk_tx); - clk_free(&eqos->clk_ptp_ref); - clk_free(&eqos->clk_rx); - clk_free(&eqos->clk_slave_bus); - clk_free(&eqos->clk_master_bus); -#endif dm_gpio_free(dev, &eqos->phy_reset_gpio); reset_free(&eqos->reset_ctl); @@ -1505,19 +1486,7 @@ static int eqos_remove_resources_tegra186(struct udevice *dev) static int eqos_remove_resources_stm32(struct udevice *dev) { - struct eqos_priv * __maybe_unused eqos = dev_get_priv(dev); - debug("%s(dev=%p):\n", __func__, dev); - -#ifdef CONFIG_CLK - clk_free(&eqos->clk_tx); - clk_free(&eqos->clk_rx); - clk_free(&eqos->clk_master_bus); - if (clk_valid(&eqos->clk_ck)) - clk_free(&eqos->clk_ck); -#endif - - debug("%s: OK\n", __func__); return 0; } diff --git a/drivers/net/dwc_eth_qos_imx.c b/drivers/net/dwc_eth_qos_imx.c index e3f55dd981..9c4e390441 100644 --- a/drivers/net/dwc_eth_qos_imx.c +++ b/drivers/net/dwc_eth_qos_imx.c @@ -70,30 +70,24 @@ static int eqos_probe_resources_imx(struct udevice *dev) ret = clk_get_by_name(dev, "ptp_ref", &eqos->clk_ptp_ref); if (ret) { dev_dbg(dev, "clk_get_by_name(ptp_ref) failed: %d", ret); - goto err_free_clk_master_bus; + goto err_probe; } ret = clk_get_by_name(dev, "tx", &eqos->clk_tx); if (ret) { dev_dbg(dev, "clk_get_by_name(tx) failed: %d", ret); - goto err_free_clk_ptp_ref; + goto err_probe; } ret = clk_get_by_name(dev, "pclk", &eqos->clk_ck); if (ret) { dev_dbg(dev, "clk_get_by_name(pclk) failed: %d", ret); - goto err_free_clk_tx; + goto err_probe; } debug("%s: OK\n", __func__); return 0; -err_free_clk_tx: - clk_free(&eqos->clk_tx); -err_free_clk_ptp_ref: - clk_free(&eqos->clk_ptp_ref); -err_free_clk_master_bus: - clk_free(&eqos->clk_master_bus); err_probe: debug("%s: returns %d\n", __func__, ret); @@ -102,16 +96,7 @@ err_probe: static int eqos_remove_resources_imx(struct udevice *dev) { - struct eqos_priv *eqos = dev_get_priv(dev); - debug("%s(dev=%p):\n", __func__, dev); - - clk_free(&eqos->clk_ck); - clk_free(&eqos->clk_tx); - clk_free(&eqos->clk_ptp_ref); - clk_free(&eqos->clk_master_bus); - - debug("%s: OK\n", __func__); return 0; } diff --git a/drivers/net/dwc_eth_qos_qcom.c b/drivers/net/dwc_eth_qos_qcom.c index df83f1c5f9..8178138fc6 100644 --- a/drivers/net/dwc_eth_qos_qcom.c +++ b/drivers/net/dwc_eth_qos_qcom.c @@ -575,7 +575,6 @@ static int eqos_remove_resources_qcom(struct udevice *dev) debug("%s(dev=%p):\n", __func__, dev); - clk_free(&eqos->clk_tx); dm_gpio_free(dev, &eqos->phy_reset_gpio); reset_free(&eqos->reset_ctl); diff --git a/drivers/net/dwc_eth_qos_rockchip.c b/drivers/net/dwc_eth_qos_rockchip.c index 834307a447..fa9e513fae 100644 --- a/drivers/net/dwc_eth_qos_rockchip.c +++ b/drivers/net/dwc_eth_qos_rockchip.c @@ -372,7 +372,7 @@ static int eqos_probe_resources_rk(struct udevice *dev) ret = clk_get_by_name(dev, "clk_mac_speed", &eqos->clk_tx); if (ret) { dev_dbg(dev, "clk_get_by_name(clk_mac_speed) failed: %d", ret); - goto err_free_clk_master_bus; + goto err_release_resets; } } @@ -393,8 +393,6 @@ static int eqos_probe_resources_rk(struct udevice *dev) return 0; -err_free_clk_master_bus: - clk_free(&eqos->clk_master_bus); err_release_resets: reset_release_bulk(&data->resets); err_free: @@ -412,8 +410,6 @@ static int eqos_remove_resources_rk(struct udevice *dev) if (dm_gpio_is_valid(&eqos->phy_reset_gpio)) dm_gpio_free(dev, &eqos->phy_reset_gpio); - clk_free(&eqos->clk_tx); - clk_free(&eqos->clk_master_bus); reset_release_bulk(&data->resets); free(data); diff --git a/drivers/net/phy/motorcomm.c b/drivers/net/phy/motorcomm.c index 8635a960d6..a2c763c879 100644 --- a/drivers/net/phy/motorcomm.c +++ b/drivers/net/phy/motorcomm.c @@ -23,6 +23,12 @@ #define YTPHY_SYNCE_CFG_REG 0xA012 +#define YT8531_PAD_DRIVE_STRENGTH_CFG_REG 0xA010 +#define YT8531_RGMII_RXC_DS_MASK GENMASK(15, 13) +#define YT8531_RGMII_RXD_DS_HI_MASK BIT(12) /* Bit 2 of rxd_ds */ +#define YT8531_RGMII_RXD_DS_LOW_MASK GENMASK(5, 4) /* Bit 1/0 of rxd_ds */ +#define YT8531_RGMII_RX_DS_DEFAULT 0x3 + #define YTPHY_DTS_OUTPUT_CLK_DIS 0 #define YTPHY_DTS_OUTPUT_CLK_25M 25000000 #define YTPHY_DTS_OUTPUT_CLK_125M 125000000 @@ -114,6 +120,10 @@ #define YT8531_CCR_RXC_DLY_EN BIT(8) #define YT8531_CCR_RXC_DLY_1_900_NS 1900 +#define YT8531_CCR_CFG_LDO_MASK GENMASK(5, 4) +#define YT8531_CCR_CFG_LDO_3V3 0x0 +#define YT8531_CCR_CFG_LDO_1V8 0x2 + /* bits in struct ytphy_plat_priv->flag */ #define TX_CLK_ADJ_ENABLED BIT(0) #define AUTO_SLEEP_DISABLED BIT(1) @@ -224,6 +234,17 @@ static int ytphy_modify_ext(struct phy_device *phydev, u16 regnum, u16 mask, return phy_modify(phydev, MDIO_DEVAD_NONE, YTPHY_PAGE_DATA, mask, set); } +static int ytphy_read_ext(struct phy_device *phydev, u16 regnum) +{ + int ret; + + ret = phy_write(phydev, MDIO_DEVAD_NONE, YTPHY_PAGE_SELECT, regnum); + if (ret < 0) + return ret; + + return phy_read(phydev, MDIO_DEVAD_NONE, YTPHY_PAGE_DATA); +} + static int ytphy_rgmii_clk_delay_config(struct phy_device *phydev) { struct ytphy_plat_priv *priv = phydev->priv; @@ -425,6 +446,111 @@ static int yt8511_config(struct phy_device *phydev) return 0; } +/** + * struct ytphy_ldo_vol_map - map a current value to a register value + * @vol: ldo voltage + * @ds: value in the register + * @cur: value in device configuration + */ +struct ytphy_ldo_vol_map { + u32 vol; + u32 ds; + u32 cur; +}; + +static const struct ytphy_ldo_vol_map yt8531_ldo_vol[] = { + {.vol = YT8531_CCR_CFG_LDO_1V8, .ds = 0, .cur = 1200}, + {.vol = YT8531_CCR_CFG_LDO_1V8, .ds = 1, .cur = 2100}, + {.vol = YT8531_CCR_CFG_LDO_1V8, .ds = 2, .cur = 2700}, + {.vol = YT8531_CCR_CFG_LDO_1V8, .ds = 3, .cur = 2910}, + {.vol = YT8531_CCR_CFG_LDO_1V8, .ds = 4, .cur = 3110}, + {.vol = YT8531_CCR_CFG_LDO_1V8, .ds = 5, .cur = 3600}, + {.vol = YT8531_CCR_CFG_LDO_1V8, .ds = 6, .cur = 3970}, + {.vol = YT8531_CCR_CFG_LDO_1V8, .ds = 7, .cur = 4350}, + {.vol = YT8531_CCR_CFG_LDO_3V3, .ds = 0, .cur = 3070}, + {.vol = YT8531_CCR_CFG_LDO_3V3, .ds = 1, .cur = 4080}, + {.vol = YT8531_CCR_CFG_LDO_3V3, .ds = 2, .cur = 4370}, + {.vol = YT8531_CCR_CFG_LDO_3V3, .ds = 3, .cur = 4680}, + {.vol = YT8531_CCR_CFG_LDO_3V3, .ds = 4, .cur = 5020}, + {.vol = YT8531_CCR_CFG_LDO_3V3, .ds = 5, .cur = 5450}, + {.vol = YT8531_CCR_CFG_LDO_3V3, .ds = 6, .cur = 5740}, + {.vol = YT8531_CCR_CFG_LDO_3V3, .ds = 7, .cur = 6140}, +}; + +static u32 yt8531_get_ldo_vol(struct phy_device *phydev) +{ + u32 val; + + val = ytphy_read_ext(phydev, YT8531_CHIP_CONFIG_REG); + val = FIELD_GET(YT8531_CCR_CFG_LDO_MASK, val); + + return val <= YT8531_CCR_CFG_LDO_1V8 ? val : YT8531_CCR_CFG_LDO_1V8; +} + +static int yt8531_get_ds_map(struct phy_device *phydev, u32 cur) +{ + u32 vol; + int i; + + vol = yt8531_get_ldo_vol(phydev); + for (i = 0; i < ARRAY_SIZE(yt8531_ldo_vol); i++) { + if (yt8531_ldo_vol[i].vol == vol && yt8531_ldo_vol[i].cur == cur) + return yt8531_ldo_vol[i].ds; + } + + return -EINVAL; +} + +static int yt8531_set_ds(struct phy_device *phydev) +{ + u32 ds_field_low, ds_field_hi, val; + int ret, ds; + + /* set rgmii rx clk driver strength */ + if (!ofnode_read_u32(phydev->node, "motorcomm,rx-clk-drv-microamp", &val)) { + ds = yt8531_get_ds_map(phydev, val); + if (ds < 0) { + pr_warn("No matching current value was found."); + return -EINVAL; + } + } else { + ds = YT8531_RGMII_RX_DS_DEFAULT; + } + + ret = ytphy_modify_ext(phydev, + YT8531_PAD_DRIVE_STRENGTH_CFG_REG, + YT8531_RGMII_RXC_DS_MASK, + FIELD_PREP(YT8531_RGMII_RXC_DS_MASK, ds)); + if (ret < 0) + return ret; + + /* set rgmii rx data driver strength */ + if (!ofnode_read_u32(phydev->node, "motorcomm,rx-data-drv-microamp", &val)) { + ds = yt8531_get_ds_map(phydev, val); + if (ds < 0) { + pr_warn("No matching current value was found."); + return -EINVAL; + } + } else { + ds = YT8531_RGMII_RX_DS_DEFAULT; + } + + ds_field_hi = FIELD_GET(BIT(2), ds); + ds_field_hi = FIELD_PREP(YT8531_RGMII_RXD_DS_HI_MASK, ds_field_hi); + + ds_field_low = FIELD_GET(GENMASK(1, 0), ds); + ds_field_low = FIELD_PREP(YT8531_RGMII_RXD_DS_LOW_MASK, ds_field_low); + + ret = ytphy_modify_ext(phydev, + YT8531_PAD_DRIVE_STRENGTH_CFG_REG, + YT8531_RGMII_RXD_DS_LOW_MASK | YT8531_RGMII_RXD_DS_HI_MASK, + ds_field_low | ds_field_hi); + if (ret < 0) + return ret; + + return 0; +} + static int yt8531_config(struct phy_device *phydev) { struct ytphy_plat_priv *priv = phydev->priv; @@ -487,6 +613,10 @@ static int yt8531_config(struct phy_device *phydev) return ret; } + ret = yt8531_set_ds(phydev); + if (ret < 0) + return ret; + return 0; } diff --git a/drivers/net/sni_ave.c b/drivers/net/sni_ave.c index 8eeecbc4cf..a265ce9df5 100644 --- a/drivers/net/sni_ave.c +++ b/drivers/net/sni_ave.c @@ -777,7 +777,7 @@ static int ave_of_to_plat(struct udevice *dev) if (ret) { dev_err(dev, "Failed to get clocks property: %d\n", ret); - goto out_clk_free; + return ret; } priv->nclks++; } @@ -823,9 +823,6 @@ static int ave_of_to_plat(struct udevice *dev) out_reset_free: while (--nr >= 0) reset_free(&priv->rst[nr]); -out_clk_free: - while (--nc >= 0) - clk_free(&priv->clk[nc]); return ret; } diff --git a/drivers/net/ti/am65-cpsw-nuss.c b/drivers/net/ti/am65-cpsw-nuss.c index 18a33c4c0e..6da018c0f9 100644 --- a/drivers/net/ti/am65-cpsw-nuss.c +++ b/drivers/net/ti/am65-cpsw-nuss.c @@ -948,7 +948,6 @@ static int am65_cpsw_probe_nuss(struct udevice *dev) cpsw_common->bus_freq); out: - clk_free(&cpsw_common->fclk); power_domain_free(&cpsw_common->pwrdmn); return ret; } diff --git a/drivers/phy/bcm6318-usbh-phy.c b/drivers/phy/bcm6318-usbh-phy.c index 1c10853940..a2fa446cb1 100644 --- a/drivers/phy/bcm6318-usbh-phy.c +++ b/drivers/phy/bcm6318-usbh-phy.c @@ -98,8 +98,6 @@ static int bcm6318_usbh_probe(struct udevice *dev) if (ret < 0) return ret; - clk_free(&clk); - /* enable power domain */ ret = power_domain_get(dev, &pwr_dom); if (ret < 0) diff --git a/drivers/phy/bcm6348-usbh-phy.c b/drivers/phy/bcm6348-usbh-phy.c index ce6be3d7da..857fb575ef 100644 --- a/drivers/phy/bcm6348-usbh-phy.c +++ b/drivers/phy/bcm6348-usbh-phy.c @@ -62,8 +62,6 @@ static int bcm6348_usbh_probe(struct udevice *dev) if (ret < 0) return ret; - clk_free(&clk); - /* perform reset */ ret = reset_get_by_index(dev, 0, &rst_ctl); if (ret < 0) diff --git a/drivers/phy/bcm6368-usbh-phy.c b/drivers/phy/bcm6368-usbh-phy.c index d057f1f52e..1a2870d514 100644 --- a/drivers/phy/bcm6368-usbh-phy.c +++ b/drivers/phy/bcm6368-usbh-phy.c @@ -137,8 +137,6 @@ static int bcm6368_usbh_probe(struct udevice *dev) if (ret < 0) return ret; - clk_free(&clk); - #if defined(CONFIG_POWER_DOMAIN) /* enable power domain */ ret = power_domain_get(dev, &pwr_dom); @@ -173,8 +171,6 @@ static int bcm6368_usbh_probe(struct udevice *dev) ret = clk_enable(&clk); if (ret < 0) return ret; - - clk_free(&clk); } mdelay(100); diff --git a/drivers/phy/meson-axg-mipi-dphy.c b/drivers/phy/meson-axg-mipi-dphy.c index a69b6c9759..faa1d9d6d3 100644 --- a/drivers/phy/meson-axg-mipi-dphy.c +++ b/drivers/phy/meson-axg-mipi-dphy.c @@ -369,7 +369,6 @@ int meson_axg_mipi_dphy_probe(struct udevice *dev) ret = clk_enable(&priv->clk); if (ret && ret != -ENOSYS && ret != -ENOTSUPP) { pr_err("failed to enable PHY clock\n"); - clk_free(&priv->clk); return ret; } #endif diff --git a/drivers/phy/meson-g12a-usb3-pcie.c b/drivers/phy/meson-g12a-usb3-pcie.c index 40a5da948d..1eaff410ef 100644 --- a/drivers/phy/meson-g12a-usb3-pcie.c +++ b/drivers/phy/meson-g12a-usb3-pcie.c @@ -398,7 +398,6 @@ int meson_g12a_usb3_pcie_phy_probe(struct udevice *dev) ret = clk_enable(&priv->clk); if (ret && ret != -ENOENT && ret != -ENOTSUPP) { pr_err("failed to enable PHY clock\n"); - clk_free(&priv->clk); return ret; } #endif diff --git a/drivers/phy/meson-gxl-usb2.c b/drivers/phy/meson-gxl-usb2.c index 8f5e4a4366..d633effa40 100644 --- a/drivers/phy/meson-gxl-usb2.c +++ b/drivers/phy/meson-gxl-usb2.c @@ -203,7 +203,6 @@ int meson_gxl_usb2_phy_probe(struct udevice *dev) ret = clk_enable(&priv->clk); if (ret && ret != -ENOSYS && ret != -ENOTSUPP) { pr_err("failed to enable PHY clock\n"); - clk_free(&priv->clk); return ret; } #endif diff --git a/drivers/phy/phy-rcar-gen2.c b/drivers/phy/phy-rcar-gen2.c index 1794095924..e528c4ec57 100644 --- a/drivers/phy/phy-rcar-gen2.c +++ b/drivers/phy/phy-rcar-gen2.c @@ -172,7 +172,6 @@ static int rcar_gen2_phy_remove(struct udevice *dev) struct rcar_gen2_phy *priv = dev_get_priv(dev); clk_disable(&priv->clk); - clk_free(&priv->clk); return 0; } diff --git a/drivers/phy/phy-rcar-gen3.c b/drivers/phy/phy-rcar-gen3.c index 7159e7e871..03c747b373 100644 --- a/drivers/phy/phy-rcar-gen3.c +++ b/drivers/phy/phy-rcar-gen3.c @@ -142,7 +142,6 @@ static int rcar_gen3_phy_remove(struct udevice *dev) struct rcar_gen3_phy *priv = dev_get_priv(dev); clk_disable(&priv->clk); - clk_free(&priv->clk); return 0; } diff --git a/drivers/pinctrl/pinctrl-k210.c b/drivers/pinctrl/pinctrl-k210.c index 13f0a34268..ee35dfe142 100644 --- a/drivers/pinctrl/pinctrl-k210.c +++ b/drivers/pinctrl/pinctrl-k210.c @@ -691,23 +691,19 @@ static int k210_pc_probe(struct udevice *dev) ret = clk_enable(&priv->clk); if (ret && ret != -ENOSYS && ret != -ENOTSUPP) - goto err; + return ret; ret = dev_read_phandle_with_args(dev, "canaan,k210-sysctl-power", NULL, 1, 0, &args); if (ret) - goto err; + return ret; - if (args.args_count != 1) { - ret = -EINVAL; - goto err; - } + if (args.args_count != 1) + return -EINVAL; priv->sysctl = syscon_node_to_regmap(args.node); - if (IS_ERR(priv->sysctl)) { - ret = PTR_ERR(priv->sysctl); - goto err; - } + if (IS_ERR(priv->sysctl)) + return PTR_ERR(priv->sysctl); priv->power_offset = args.args[0]; @@ -728,10 +724,6 @@ static int k210_pc_probe(struct udevice *dev) } return 0; - -err: - clk_free(&priv->clk); - return ret; } static const struct udevice_id k210_pc_ids[] = { diff --git a/drivers/power/domain/imx8mp-hsiomix.c b/drivers/power/domain/imx8mp-hsiomix.c index 6a721a934a..e2d772c5ec 100644 --- a/drivers/power/domain/imx8mp-hsiomix.c +++ b/drivers/power/domain/imx8mp-hsiomix.c @@ -111,7 +111,7 @@ static int imx8mp_hsiomix_probe(struct udevice *dev) ret = power_domain_get_by_name(dev, &priv->pd_bus, "bus"); if (ret < 0) - goto err_pd_bus; + return ret; ret = power_domain_get_by_name(dev, &priv->pd_usb, "usb"); if (ret < 0) @@ -133,8 +133,6 @@ err_pd_usb_phy1: power_domain_free(&priv->pd_usb); err_pd_usb: power_domain_free(&priv->pd_bus); -err_pd_bus: - clk_free(&priv->clk_usb); return ret; } diff --git a/drivers/rtc/stm32_rtc.c b/drivers/rtc/stm32_rtc.c index 1753283460..ec7584c3d7 100644 --- a/drivers/rtc/stm32_rtc.c +++ b/drivers/rtc/stm32_rtc.c @@ -223,10 +223,8 @@ static int stm32_rtc_init(struct udevice *dev) return ret; ret = clk_enable(&clk); - if (ret) { - clk_free(&clk); + if (ret) return ret; - } rate = clk_get_rate(&clk); @@ -275,10 +273,8 @@ static int stm32_rtc_init(struct udevice *dev) unlock: stm32_rtc_lock(dev); - if (ret) { + if (ret) clk_disable(&clk); - clk_free(&clk); - } return ret; } @@ -298,17 +294,13 @@ static int stm32_rtc_probe(struct udevice *dev) return ret; ret = clk_enable(&clk); - if (ret) { - clk_free(&clk); + if (ret) return ret; - } ret = stm32_rtc_init(dev); - if (ret) { + if (ret) clk_disable(&clk); - clk_free(&clk); - } return ret; } diff --git a/drivers/serial/atmel_usart.c b/drivers/serial/atmel_usart.c index 9853f49c94..9827c006fa 100644 --- a/drivers/serial/atmel_usart.c +++ b/drivers/serial/atmel_usart.c @@ -253,8 +253,6 @@ static int atmel_serial_enable_clk(struct udevice *dev) priv->usart_clk_rate = clk_rate; - clk_free(&clk); - return 0; } #endif diff --git a/drivers/serial/serial_bcm6345.c b/drivers/serial/serial_bcm6345.c index 2359656a23..13bc51725c 100644 --- a/drivers/serial/serial_bcm6345.c +++ b/drivers/serial/serial_bcm6345.c @@ -239,7 +239,6 @@ static int bcm6345_serial_probe(struct udevice *dev) if (ret < 0) return ret; priv->uartclk = clk_get_rate(&clk); - clk_free(&clk); /* initialize serial */ return bcm6345_serial_init(priv->base, priv->uartclk, CONFIG_BAUDRATE); diff --git a/drivers/serial/serial_msm.c b/drivers/serial/serial_msm.c index a22623c316..f4d96313b9 100644 --- a/drivers/serial/serial_msm.c +++ b/drivers/serial/serial_msm.c @@ -185,7 +185,6 @@ static int msm_uart_clk_init(struct udevice *dev) return ret; ret = clk_set_rate(&clk, clk_rate); - clk_free(&clk); if (ret < 0) return ret; diff --git a/drivers/serial/serial_pic32.c b/drivers/serial/serial_pic32.c index 3c5d37ce0a..0a03a9a254 100644 --- a/drivers/serial/serial_pic32.c +++ b/drivers/serial/serial_pic32.c @@ -155,7 +155,6 @@ static int pic32_uart_probe(struct udevice *dev) if (ret < 0) return ret; priv->uartclk = clk_get_rate(&clk); - clk_free(&clk); /* initialize serial */ return pic32_serial_init(priv->base, priv->uartclk, CONFIG_BAUDRATE); diff --git a/drivers/spi/atcspi200_spi.c b/drivers/spi/atcspi200_spi.c index de9c14837c..70cb242cd3 100644 --- a/drivers/spi/atcspi200_spi.c +++ b/drivers/spi/atcspi200_spi.c @@ -362,7 +362,6 @@ static int atcspi200_spi_get_clk(struct udevice *bus) return -EINVAL; ns->clock = clk_rate; - clk_free(&clk); return 0; } diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c index cb64119f97..bd73e4fddf 100644 --- a/drivers/spi/atmel-quadspi.c +++ b/drivers/spi/atmel-quadspi.c @@ -877,7 +877,6 @@ static int atmel_qspi_set_gclk(struct udevice *bus, uint hz) ret = clk_enable(&gclk); if (ret) dev_err(bus, "Failed to enable QSPI generic clock\n"); - clk_free(&gclk); return ret; } @@ -1000,7 +999,7 @@ static int atmel_qspi_enable_clk(struct udevice *dev) ret = clk_enable(&pclk); if (ret) { dev_err(dev, "Failed to enable QSPI peripheral clock\n"); - goto free_pclk; + return ret; } if (aq->caps->has_qspick) { @@ -1008,32 +1007,27 @@ static int atmel_qspi_enable_clk(struct udevice *dev) ret = clk_get_by_name(dev, "qspick", &qspick); if (ret) { dev_err(dev, "Missing QSPI peripheral clock\n"); - goto free_pclk; + return ret; } ret = clk_enable(&qspick); if (ret) dev_err(dev, "Failed to enable QSPI system clock\n"); - clk_free(&qspick); } else if (aq->caps->has_gclk) { ret = clk_get_by_name(dev, "gclk", &gclk); if (ret) { dev_err(dev, "Missing QSPI generic clock\n"); - goto free_pclk; + return ret; } ret = clk_enable(&gclk); if (ret) dev_err(dev, "Failed to enable QSPI system clock\n"); - clk_free(&gclk); } aq->bus_clk_rate = clk_get_rate(&pclk); if (!aq->bus_clk_rate) - ret = -EINVAL; - -free_pclk: - clk_free(&pclk); + return -EINVAL; return ret; } diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c index aec6f4eca9..d4f0c4c448 100644 --- a/drivers/spi/atmel_spi.c +++ b/drivers/spi/atmel_spi.c @@ -338,8 +338,6 @@ static int atmel_spi_enable_clk(struct udevice *bus) priv->bus_clk_rate = clk_rate; - clk_free(&clk); - return 0; } diff --git a/drivers/spi/bcm63xx_hsspi.c b/drivers/spi/bcm63xx_hsspi.c index 19d9a5ae23..23ac5bb76c 100644 --- a/drivers/spi/bcm63xx_hsspi.c +++ b/drivers/spi/bcm63xx_hsspi.c @@ -581,8 +581,6 @@ static int bcm63xx_hsspi_probe(struct udevice *dev) if (ret < 0 && ret != -ENOSYS) return ret; - clk_free(&clk); - /* get clock rate */ ret = clk_get_by_name(dev, "pll", &clk); if (ret < 0 && ret != -ENOSYS) @@ -590,8 +588,6 @@ static int bcm63xx_hsspi_probe(struct udevice *dev) priv->clk_rate = clk_get_rate(&clk); - clk_free(&clk); - /* perform reset */ ret = reset_get_by_index(dev, 0, &rst_ctl); if (ret >= 0) { diff --git a/drivers/spi/bcm63xx_spi.c b/drivers/spi/bcm63xx_spi.c index 0600d56c69..889ac1f966 100644 --- a/drivers/spi/bcm63xx_spi.c +++ b/drivers/spi/bcm63xx_spi.c @@ -391,8 +391,6 @@ static int bcm63xx_spi_probe(struct udevice *dev) if (ret < 0) return ret; - clk_free(&clk); - /* perform reset */ ret = reset_get_by_index(dev, 0, &rst_ctl); if (ret < 0) diff --git a/drivers/spi/bcmbca_hsspi.c b/drivers/spi/bcmbca_hsspi.c index fbe315a7d4..af45882db0 100644 --- a/drivers/spi/bcmbca_hsspi.c +++ b/drivers/spi/bcmbca_hsspi.c @@ -375,8 +375,6 @@ static int bcmbca_hsspi_probe(struct udevice *dev) if (ret < 0 && ret != -ENOSYS) return ret; - clk_free(&clk); - /* get clock rate */ ret = clk_get_by_name(dev, "pll", &clk); if (ret < 0 && ret != -ENOSYS) @@ -384,8 +382,6 @@ static int bcmbca_hsspi_probe(struct udevice *dev) priv->clk_rate = clk_get_rate(&clk); - clk_free(&clk); - /* initialize hardware */ writel(0, priv->regs + SPI_IR_MASK_REG); diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c index dfc74c882d..f4593c47b8 100644 --- a/drivers/spi/cadence_qspi.c +++ b/drivers/spi/cadence_qspi.c @@ -236,7 +236,6 @@ static int cadence_spi_probe(struct udevice *bus) #endif } else { priv->ref_clk_hz = clk_get_rate(&clk); - clk_free(&clk); if (IS_ERR_VALUE(priv->ref_clk_hz)) return priv->ref_clk_hz; } diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c index 98908c5217..22a79da233 100644 --- a/drivers/spi/designware_spi.c +++ b/drivers/spi/designware_spi.c @@ -319,7 +319,6 @@ __weak int dw_spi_get_clk(struct udevice *bus, ulong *rate) err_rate: clk_disable(&priv->clk); - clk_free(&priv->clk); return -EINVAL; } @@ -743,10 +742,6 @@ static int dw_spi_remove(struct udevice *bus) ret = clk_disable(&priv->clk); if (ret) return ret; - - clk_free(&priv->clk); - if (ret) - return ret; #endif return 0; } diff --git a/drivers/spi/meson_spifc_a1.c b/drivers/spi/meson_spifc_a1.c index cca4debb41..943bf6986f 100644 --- a/drivers/spi/meson_spifc_a1.c +++ b/drivers/spi/meson_spifc_a1.c @@ -343,15 +343,6 @@ static int amlogic_spifc_a1_probe(struct udevice *dev) return 0; } -static int amlogic_spifc_a1_remove(struct udevice *dev) -{ - struct amlogic_spifc_a1 *spifc = dev_get_priv(dev); - - clk_free(&spifc->clk); - - return 0; -} - static const struct udevice_id meson_spifc_ids[] = { { .compatible = "amlogic,a1-spifc", }, { } @@ -379,6 +370,5 @@ U_BOOT_DRIVER(meson_spifc_a1) = { .of_match = meson_spifc_ids, .ops = &amlogic_spifc_a1_ops, .probe = amlogic_spifc_a1_probe, - .remove = amlogic_spifc_a1_remove, .priv_auto = sizeof(struct amlogic_spifc_a1), }; diff --git a/drivers/spi/mvebu_a3700_spi.c b/drivers/spi/mvebu_a3700_spi.c index 52882e8b26..bba2383a11 100644 --- a/drivers/spi/mvebu_a3700_spi.c +++ b/drivers/spi/mvebu_a3700_spi.c @@ -296,15 +296,6 @@ static int mvebu_spi_of_to_plat(struct udevice *bus) return 0; } -static int mvebu_spi_remove(struct udevice *bus) -{ - struct mvebu_spi_plat *plat = dev_get_plat(bus); - - clk_free(&plat->clk); - - return 0; -} - static const struct dm_spi_ops mvebu_spi_ops = { .xfer = mvebu_spi_xfer, .set_speed = mvebu_spi_set_speed, @@ -328,5 +319,4 @@ U_BOOT_DRIVER(mvebu_spi) = { .of_to_plat = mvebu_spi_of_to_plat, .plat_auto = sizeof(struct mvebu_spi_plat), .probe = mvebu_spi_probe, - .remove = mvebu_spi_remove, }; diff --git a/drivers/spi/spi-aspeed-smc.c b/drivers/spi/spi-aspeed-smc.c index 3962031021..7d5f101a76 100644 --- a/drivers/spi/spi-aspeed-smc.c +++ b/drivers/spi/spi-aspeed-smc.c @@ -1148,7 +1148,6 @@ static int apseed_spi_of_to_plat(struct udevice *bus) } plat->hclk_rate = clk_get_rate(&hclk); - clk_free(&hclk); dev_dbg(bus, "ctrl_base = 0x%x, ahb_base = 0x%p, size = 0x%llx\n", (u32)priv->regs, plat->ahb_base, (fdt64_t)plat->ahb_sz); diff --git a/drivers/spi/stm32_spi.c b/drivers/spi/stm32_spi.c index 82f6ed783f..ddb410a94c 100644 --- a/drivers/spi/stm32_spi.c +++ b/drivers/spi/stm32_spi.c @@ -526,22 +526,16 @@ static int stm32_spi_of_to_plat(struct udevice *dev) ret = reset_get_by_index(dev, 0, &plat->rst_ctl); if (ret < 0) - goto clk_err; + return ret; ret = gpio_request_list_by_name(dev, "cs-gpios", plat->cs_gpios, ARRAY_SIZE(plat->cs_gpios), 0); if (ret < 0) { dev_err(dev, "Can't get %s cs gpios: %d", dev->name, ret); - ret = -ENOENT; - goto clk_err; + return -ENOENT; } return 0; - -clk_err: - clk_free(&plat->clk); - - return ret; } static int stm32_spi_probe(struct udevice *dev) @@ -610,7 +604,6 @@ static int stm32_spi_probe(struct udevice *dev) clk_err: clk_disable(&plat->clk); - clk_free(&plat->clk); return ret; }; @@ -630,13 +623,7 @@ static int stm32_spi_remove(struct udevice *dev) reset_free(&plat->rst_ctl); - ret = clk_disable(&plat->clk); - if (ret < 0) - return ret; - - clk_free(&plat->clk); - - return ret; + return clk_disable(&plat->clk); }; static const struct dm_spi_ops stm32_spi_ops = { diff --git a/drivers/timer/dw-apb-timer.c b/drivers/timer/dw-apb-timer.c index 6cd25251f9..0607f751ca 100644 --- a/drivers/timer/dw-apb-timer.c +++ b/drivers/timer/dw-apb-timer.c @@ -74,8 +74,6 @@ static int dw_apb_timer_probe(struct udevice *dev) return ret; uc_priv->clock_rate = clk_get_rate(&clk); - - clk_free(&clk); } /* init timer */ diff --git a/drivers/timer/ostm_timer.c b/drivers/timer/ostm_timer.c index 3ec729d2c4..3bf0d4647b 100644 --- a/drivers/timer/ostm_timer.c +++ b/drivers/timer/ostm_timer.c @@ -49,8 +49,6 @@ static int ostm_probe(struct udevice *dev) return ret; uc_priv->clock_rate = clk_get_rate(&clk); - - clk_free(&clk); #else uc_priv->clock_rate = get_board_sys_clk() / 2; #endif diff --git a/drivers/usb/dwc3/dwc3-meson-g12a.c b/drivers/usb/dwc3/dwc3-meson-g12a.c index 196035215a..1a3e9350c4 100644 --- a/drivers/usb/dwc3/dwc3-meson-g12a.c +++ b/drivers/usb/dwc3/dwc3-meson-g12a.c @@ -361,10 +361,8 @@ static int dwc3_meson_g12a_clk_init(struct dwc3_meson_g12a *priv) #if CONFIG_IS_ENABLED(CLK) ret = clk_enable(&priv->clk); - if (ret) { - clk_free(&priv->clk); + if (ret) return ret; - } #endif return 0; diff --git a/drivers/usb/dwc3/dwc3-meson-gxl.c b/drivers/usb/dwc3/dwc3-meson-gxl.c index cbe8aaa005..2ce915701a 100644 --- a/drivers/usb/dwc3/dwc3-meson-gxl.c +++ b/drivers/usb/dwc3/dwc3-meson-gxl.c @@ -284,10 +284,8 @@ static int dwc3_meson_gxl_clk_init(struct dwc3_meson_gxl *priv) #if CONFIG_IS_ENABLED(CLK) ret = clk_enable(&priv->clk); - if (ret) { - clk_free(&priv->clk); + if (ret) return ret; - } #endif return 0; diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c index fba3595e10..c6d50fd455 100644 --- a/drivers/usb/host/ehci-atmel.c +++ b/drivers/usb/host/ehci-atmel.c @@ -70,13 +70,7 @@ static int ehci_atmel_enable_clk(struct udevice *dev) if (ret) return -EINVAL; - ret = clk_enable(&clk); - if (ret) - return ret; - - clk_free(&clk); - - return 0; + return clk_enable(&clk); } static int ehci_atmel_probe(struct udevice *dev) diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c index 33c4a911a0..d3d73d2384 100644 --- a/drivers/usb/host/ohci-da8xx.c +++ b/drivers/usb/host/ohci-da8xx.c @@ -115,7 +115,6 @@ static int ohci_da8xx_probe(struct udevice *dev) err = clk_enable(&priv->clocks[i]); if (err) { dev_err(dev, "failed to enable clock %d\n", i); - clk_free(&priv->clocks[i]); goto clk_err; } priv->clock_count++; diff --git a/drivers/usb/host/xhci-rcar.c b/drivers/usb/host/xhci-rcar.c index 5fc7afb7d2..fedcf78692 100644 --- a/drivers/usb/host/xhci-rcar.c +++ b/drivers/usb/host/xhci-rcar.c @@ -90,7 +90,7 @@ static int xhci_rcar_probe(struct udevice *dev) ret = clk_enable(&plat->clk); if (ret) { dev_err(dev, "Failed to enable USB3 clock\n"); - goto err_clk; + return ret; } ctx->hcd = (struct xhci_hccr *)plat->hcd_base; @@ -114,8 +114,6 @@ static int xhci_rcar_probe(struct udevice *dev) err_fw: clk_disable(&plat->clk); -err_clk: - clk_free(&plat->clk); return ret; } @@ -127,7 +125,6 @@ static int xhci_rcar_deregister(struct udevice *dev) ret = xhci_deregister(dev); clk_disable(&plat->clk); - clk_free(&plat->clk); return ret; } diff --git a/drivers/video/atmel_hlcdfb.c b/drivers/video/atmel_hlcdfb.c index 2bf19a6684..652ba14180 100644 --- a/drivers/video/atmel_hlcdfb.c +++ b/drivers/video/atmel_hlcdfb.c @@ -62,8 +62,6 @@ static int at91_hlcdc_enable_clk(struct udevice *dev) priv->clk_rate = clk_rate; - clk_free(&clk); - return 0; } diff --git a/drivers/video/mali_dp.c b/drivers/video/mali_dp.c index cbcdb99e1f..dbb2f53861 100644 --- a/drivers/video/mali_dp.c +++ b/drivers/video/mali_dp.c @@ -360,25 +360,18 @@ static int malidp_probe(struct udevice *dev) err = malidp_setup_mode(priv, &timings); if (err) - goto fail_timings; + return err; malidp_setup_layer(priv, &timings, MALIDP_LAYER_LV1, (phys_addr_t)uc_plat->base); err = malidp_leave_config(priv); if (err) - goto fail_timings; + return err; malidp_set_configvalid(priv); return 0; - -fail_timings: - clk_free(&priv->aclk); -fail_aclk: - clk_free(&priv->pxlclk); - - return err; } static int malidp_bind(struct udevice *dev) diff --git a/drivers/video/rockchip/rk3288_hdmi.c b/drivers/video/rockchip/rk3288_hdmi.c index 327ae78712..8bedee55ad 100644 --- a/drivers/video/rockchip/rk3288_hdmi.c +++ b/drivers/video/rockchip/rk3288_hdmi.c @@ -67,10 +67,8 @@ static int rk3288_clk_config(struct udevice *dev) * monitor wants */ ret = clk_get_by_index(uc_plat->src_dev, 0, &clk); - if (ret >= 0) { + if (ret >= 0) ret = clk_set_rate(&clk, 384000000); - clk_free(&clk); - } if (ret < 0) { debug("%s: Failed to set clock in source device '%s': ret=%d\n", __func__, uc_plat->src_dev->name, ret); diff --git a/drivers/video/rockchip/rk_edp.c b/drivers/video/rockchip/rk_edp.c index 3697d58251..dbd70ad583 100644 --- a/drivers/video/rockchip/rk_edp.c +++ b/drivers/video/rockchip/rk_edp.c @@ -1095,20 +1095,16 @@ static int rk_edp_probe(struct udevice *dev) if (edp_data->chip_type == RK3288_DP) { ret = clk_get_by_index(dev, 1, &clk); - if (ret >= 0) { + if (ret >= 0) ret = clk_set_rate(&clk, 0); - clk_free(&clk); - } if (ret) { debug("%s: Failed to set EDP clock: ret=%d\n", __func__, ret); return ret; } } ret = clk_get_by_index(uc_plat->src_dev, 0, &clk); - if (ret >= 0) { + if (ret >= 0) ret = clk_set_rate(&clk, 192000000); - clk_free(&clk); - } if (ret < 0) { debug("%s: Failed to set clock in source device '%s': ret=%d\n", __func__, uc_plat->src_dev->name, ret); diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 569726119c..8318fd77a3 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -130,6 +130,12 @@ config WDT_AT91 Select this to enable Microchip watchdog timer, which can be found on some AT91 devices. +config WDT_ATCWDT200 + bool "Andes watchdog timer support" + depends on WDT + help + Select this to enable Andes ATCWDT200 watchdog timer + config WDT_BCM6345 bool "BCM6345 watchdog timer support" depends on WDT && (ARCH_BMIPS || BCM6856 || \ diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 5520d3d9ae..7b39adcf0f 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_WDT_ARM_SMC) += arm_smc_wdt.o obj-$(CONFIG_WDT_ARMADA_37XX) += armada-37xx-wdt.o obj-$(CONFIG_WDT_ASPEED) += ast_wdt.o obj-$(CONFIG_WDT_AST2600) += ast2600_wdt.o +obj-$(CONFIG_WDT_ATCWDT200) += atcwdt200_wdt.o obj-$(CONFIG_WDT_BCM2835) += bcm2835_wdt.o obj-$(CONFIG_WDT_BCM6345) += bcm6345_wdt.o obj-$(CONFIG_WDT_BOOKE) += booke_wdt.o diff --git a/drivers/watchdog/atcwdt200_wdt.c b/drivers/watchdog/atcwdt200_wdt.c new file mode 100644 index 0000000000..a29b42d607 --- /dev/null +++ b/drivers/watchdog/atcwdt200_wdt.c @@ -0,0 +1,220 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2023 Andes Technology Corporation. + * + */ + +#include <asm/io.h> +#include <dm.h> +#include <hang.h> +#include <linux/bitops.h> +#include <wdt.h> + +#define NODE_NOT_FOUND 0xFFFFFFFF + +#define WDT_WP_MAGIC 0x5aa5 +#define WDT_RESTART_MAGIC 0xcafe + +/* Control Register */ +#define REG_WDT_ID 0x00 +#define REG_WDT_CFG 0x10 +#define REG_WDT_RS 0x14 +#define REG_WDT_WE 0x18 +#define REG_WDT_STA 0x1C + +#define RST_TIME_OFF 8 +#define RST_TIME_MSK (0x7 << RST_TIME_OFF) +#define RST_CLK_128 (0 << RST_TIME_OFF) +#define RST_CLK_256 (1 << RST_TIME_OFF) +#define RST_CLK_512 (2 << RST_TIME_OFF) +#define RST_CLK_1024 (3 << RST_TIME_OFF) +#define INT_TIME_OFF 4 +#define INT_TIME_MSK (0xf << INT_TIME_OFF) +#define INT_CLK_2_6 (0 << INT_TIME_OFF) /* clk period*2^6 */ +#define INT_CLK_2_8 (1 << INT_TIME_OFF) /* clk period*2^8 */ +#define INT_CLK_2_10 (2 << INT_TIME_OFF) /* clk period*2^10 */ +#define INT_CLK_2_11 (3 << INT_TIME_OFF) /* clk period*2^11 */ +#define INT_CLK_2_12 (4 << INT_TIME_OFF) /* clk period*2^12 */ +#define INT_CLK_2_13 (5 << INT_TIME_OFF) /* clk period*2^13 */ +#define INT_CLK_2_14 (6 << INT_TIME_OFF) /* clk period*2^14 */ +#define INT_CLK_2_15 (7 << INT_TIME_OFF) /* clk period*2^15 */ +#define INT_CLK_2_17 (8 << INT_TIME_OFF) /* clk period*2^17 */ +#define INT_CLK_2_19 (9 << INT_TIME_OFF) /* clk period*2^19 */ +#define INT_CLK_2_21 (10 << INT_TIME_OFF) /* clk period*2^21 */ +#define INT_CLK_2_23 (11 << INT_TIME_OFF) /* clk period*2^23 */ +#define INT_CLK_2_25 (12 << INT_TIME_OFF) /* clk period*2^25 */ +#define INT_CLK_2_27 (13 << INT_TIME_OFF) /* clk period*2^27 */ +#define INT_CLK_2_29 (14 << INT_TIME_OFF) /* clk period*2^29 */ +#define INT_CLK_2_31 (15 << INT_TIME_OFF) /* clk period*2^31 */ +#define INT_CLK_MIN 0x0 +#define INT_CLK_MAX_16B 0x7 +#define INT_CLK_MAX_32B 0xF +#define RST_EN BIT(3) +#define INT_EN BIT(2) +#define CLK_PCLK BIT(1) +#define WDT_EN BIT(0) +#define INT_EXPIRED BIT(0) + +#define INT_TIME_ARRAY 16 +#define RST_TIME_ARRAY 8 + +struct wdt_priv { + void __iomem *base; + u32 wdt_clk_src; + u32 clk_freq; + u8 max_clk; +}; + +static inline u8 atcwdt_get_2_power_of_n(u8 index, u8 type) +{ + const u8 div_int[INT_TIME_ARRAY] = {6, 8, 10, 11, 12, 13, 14, 15, + 17, 19, 21, 23, 25, 27, 29, 31}; + const u8 div_rst[RST_TIME_ARRAY] = {7, 8, 9, 10, 11, 12, 13, 14}; + const u8 *pdiv; + + if (type == RST_TIME_ARRAY) + pdiv = div_rst; + else + pdiv = div_int; + + if (index >= type) + index = type - 1; + + return pdiv[index]; +} + +static u8 atcwdt_search_msb(u64 freq_ms, u8 type) +{ + u64 result; + u64 freq_sec; + u8 index; + + freq_sec = freq_ms / 1000; + for (index = 0; index < type; index++) { + result = freq_sec >> atcwdt_get_2_power_of_n(index, type); + + if (result <= 1) + break; + } + + return index; +} + +static int atcwdt_wdt_start(struct udevice *dev, u64 timeout, ulong flags) +{ + struct wdt_priv *priv = dev_get_priv(dev); + u64 rst_max_count; + u32 rst_max_time_ms; + u64 rst_time_ms; + u64 int_time_ms; + u8 rst_time; + u8 int_time; + + rst_max_count = 1 << atcwdt_get_2_power_of_n(RST_TIME_ARRAY, RST_TIME_ARRAY); + rst_max_time_ms = (rst_max_count * 1000) / priv->clk_freq; + + if (timeout > rst_max_time_ms) { + int_time_ms = timeout - rst_max_time_ms; + rst_time_ms = rst_max_time_ms; + } else { + int_time_ms = 0; + rst_time_ms = timeout; + } + + rst_time = atcwdt_search_msb(rst_time_ms * priv->clk_freq, RST_TIME_ARRAY); + + if (int_time_ms) { + int_time = atcwdt_search_msb(int_time_ms * priv->clk_freq, INT_TIME_ARRAY); + if (int_time > priv->max_clk) + int_time = priv->max_clk; + } else { + int_time = 0; + } + + writel(WDT_WP_MAGIC, priv->base + REG_WDT_WE); + writel(((rst_time << RST_TIME_OFF) & RST_TIME_MSK) | ((int_time << INT_TIME_OFF) & + INT_TIME_MSK) | INT_EN | RST_EN | priv->wdt_clk_src | WDT_EN, + priv->base + REG_WDT_CFG); + + return 0; +} + +static int atcwdt_wdt_stop(struct udevice *dev) +{ + struct wdt_priv *priv = dev_get_priv(dev); + + writel(WDT_WP_MAGIC, priv->base + REG_WDT_WE); + writel(0, priv->base + REG_WDT_CFG); + + return 0; +} + +static int atcwdt_wdt_restart(struct udevice *dev) +{ + struct wdt_priv *priv = dev_get_priv(dev); + + writel(WDT_WP_MAGIC, priv->base + REG_WDT_WE); + writel(WDT_RESTART_MAGIC, priv->base + REG_WDT_RS); + setbits_le32(priv->base + REG_WDT_STA, INT_EXPIRED); + + return 0; +} + +static int atcwdt_wdt_expire_now(struct udevice *dev, ulong flags) +{ + atcwdt_wdt_start(dev, 0, 0); + hang(); + + return 0; +} + +static int atcwdt_wdt_probe(struct udevice *dev) +{ + struct wdt_priv *priv = dev_get_priv(dev); + int timer_16bit; + + priv->base = dev_remap_addr_index(dev, 0); + if (!priv->base) + return -EFAULT; + + priv->wdt_clk_src = dev_read_u32_default(dev, "clock-source", NODE_NOT_FOUND); + if (priv->wdt_clk_src == NODE_NOT_FOUND || priv->wdt_clk_src > 1) + priv->wdt_clk_src = CLK_PCLK; + + timer_16bit = dev_read_u32_default(dev, "16bit_timer", NODE_NOT_FOUND); + if (timer_16bit == 1 || timer_16bit == NODE_NOT_FOUND) + priv->max_clk = INT_CLK_MAX_16B; + else + priv->max_clk = INT_CLK_MAX_32B; + + priv->clk_freq = dev_read_u32_default(dev, "clock-frequency", NODE_NOT_FOUND); + if (priv->clk_freq == NODE_NOT_FOUND) { + printf("atcwdt200: Please provide a valid \"clock-frequency\" in DTB\n"); + return -EINVAL; + } + + atcwdt_wdt_stop(dev); + + return 0; +} + +static const struct wdt_ops atcwdt_wdt_ops = { + .start = atcwdt_wdt_start, + .reset = atcwdt_wdt_restart, + .stop = atcwdt_wdt_stop, + .expire_now = atcwdt_wdt_expire_now, +}; + +static const struct udevice_id atcwdt_wdt_ids[] = { + {.compatible = "andestech,atcwdt200"}, + {} +}; + +U_BOOT_DRIVER(atcwdt) = { + .name = "atcwdt200", + .id = UCLASS_WDT, + .probe = atcwdt_wdt_probe, + .of_match = atcwdt_wdt_ids, + .ops = &atcwdt_wdt_ops, + .priv_auto = sizeof(struct wdt_priv), +}; diff --git a/drivers/watchdog/designware_wdt.c b/drivers/watchdog/designware_wdt.c index 447a22d3b3..b22e0ee06a 100644 --- a/drivers/watchdog/designware_wdt.c +++ b/drivers/watchdog/designware_wdt.c @@ -124,13 +124,11 @@ static int designware_wdt_probe(struct udevice *dev) ret = clk_enable(&clk); if (ret) - goto err; + return ret; priv->clk_khz = clk_get_rate(&clk) / 1000; - if (!priv->clk_khz) { - ret = -EINVAL; - goto err; - } + if (!priv->clk_khz) + return -EINVAL; #else priv->clk_khz = CFG_DW_WDT_CLOCK_KHZ; #endif @@ -139,21 +137,15 @@ static int designware_wdt_probe(struct udevice *dev) ofnode_read_prop(dev_ofnode(dev), "resets", &ret)) { ret = reset_get_bulk(dev, &priv->resets); if (ret) - goto err; + return ret; ret = reset_deassert_bulk(&priv->resets); if (ret) - goto err; + return ret; } /* reset to disable the watchdog */ return designware_wdt_stop(dev); - -err: -#if CONFIG_IS_ENABLED(CLK) - clk_free(&clk); -#endif - return ret; } static const struct wdt_ops designware_wdt_ops = { diff --git a/drivers/watchdog/meson_gxbb_wdt.c b/drivers/watchdog/meson_gxbb_wdt.c index 6ab005813f..01a35b3ab3 100644 --- a/drivers/watchdog/meson_gxbb_wdt.c +++ b/drivers/watchdog/meson_gxbb_wdt.c @@ -98,10 +98,8 @@ static int amlogic_wdt_probe(struct udevice *dev) return ret; ret = clk_enable(&clk); - if (ret) { - clk_free(&clk); + if (ret) return ret; - } /* Setup with 1ms timebase */ writel(((clk_get_rate(&clk) / 1000) & GXBB_WDT_CTRL_DIV_MASK) | diff --git a/include/clk-uclass.h b/include/clk-uclass.h index cd62848bec..8c07e723cf 100644 --- a/include/clk-uclass.h +++ b/include/clk-uclass.h @@ -18,7 +18,6 @@ struct ofnode_phandle_args; * struct clk_ops - The functions that a clock driver must implement. * @of_xlate: Translate a client's device-tree (OF) clock specifier. * @request: Request a translated clock. - * @rfree: Free a previously requested clock. * @round_rate: Adjust a rate to the exact rate a clock can provide. * @get_rate: Get current clock rate. * @set_rate: Set current clock rate. @@ -33,7 +32,6 @@ struct clk_ops { int (*of_xlate)(struct clk *clock, struct ofnode_phandle_args *args); int (*request)(struct clk *clock); - void (*rfree)(struct clk *clock); ulong (*round_rate)(struct clk *clk, ulong rate); ulong (*get_rate)(struct clk *clk); ulong (*set_rate)(struct clk *clk, ulong rate); @@ -58,11 +56,20 @@ struct clk_ops { * default implementation, which assumes #clock-cells = <1>, and that * the DT cell contains a simple integer clock ID. * + * This function should be a simple translation of @args into @clock->id and + * (optionally) @clock->data. All other processing, allocation, or error + * checking should take place in request(). + * * At present, the clock API solely supports device-tree. If this * changes, other xxx_xlate() functions may be added to support those * other mechanisms. * - * Return: 0 if OK, or a negative error code. + * Return: + * * 0 on success + * * -%EINVAL if @args does not have the correct format. For example, it could + * have too many/few arguments. + * * -%ENOENT if @args has the correct format but cannot be translated. This can + * happen if translation involves a table lookup and @args is not present. */ int of_xlate(struct clk *clock, struct ofnode_phandle_args *args); @@ -77,24 +84,36 @@ int of_xlate(struct clk *clock, struct ofnode_phandle_args *args); * xxx_xlate() call, or as the only step in implementing a client's * clk_request() call. * - * Return: 0 if OK, or a negative error code. - */ -int request(struct clk *clock); - -/** - * rfree() - Free a previously requested clock. - * @clock: The clock to free. + * This is the right place to do bounds checking (rejecting invalid or + * unimplemented clocks), allocate resources, or perform other setup not done + * during driver probe(). Most clock drivers should allocate resources in their + * probe() function, but it is possible to lazily initialize something here. * - * Free any resources allocated in request(). + * Return: + * * 0 on success + * * -%ENOENT, if there is no clock corresponding to @clock->id and + * @clock->data. */ -void rfree(struct clk *clock); +int request(struct clk *clock); /** * round_rate() - Adjust a rate to the exact rate a clock can provide. - * @clk: The clock to manipulate. - * @rate: Desidered clock rate in Hz. + * @clk: The clock to query. + * @rate: Desired clock rate in Hz. + * + * This function returns a new rate which can be provided to set_rate(). This + * new rate should be the closest rate to @rate which can be set without + * rounding. The following pseudo-code should hold:: * - * Return: rounded rate in Hz, or -ve error code. + * for all rate in range(ULONG_MAX): + * rounded = round_rate(clk, rate) + * new_rate = set_rate(clk, rate) + * assert(IS_ERR_VALUE(new_rate) || new_rate == rounded) + * + * Return: + * * The rounded rate in Hz on success + * * A negative error value from another API (such as clk_get_rate()). This + * function must not return an error for any other reason. */ ulong round_rate(struct clk *clk, ulong rate); @@ -102,7 +121,22 @@ ulong round_rate(struct clk *clk, ulong rate); * get_rate() - Get current clock rate. * @clk: The clock to query. * - * Return: clock rate in Hz, or -ve error code + * This returns the current rate of a clock. If the clock is disabled, it + * returns the rate at which the clock would run if it was enabled. The + * following pseudo-code should hold:: + * + * disable(clk) + * rate = get_rate(clk) + * enable(clk) + * assert(get_rate(clk) == rate) + * + * Return: + * * The rate of @clk + * * -%ENOSYS if this function is not implemented for @clk + * * -%ENOENT if @clk->id is invalid. Prefer using an assert instead, and doing + * this check in request(). + * * Another negative error value (such as %EIO or %ECOMM) if the rate could + * not be determined due to a bus error. */ ulong get_rate(struct clk *clk); @@ -111,7 +145,27 @@ ulong get_rate(struct clk *clk); * @clk: The clock to manipulate. * @rate: New clock rate in Hz. * - * Return: new rate, or -ve error code. + * Set the rate of @clk to @rate. The actual rate may be rounded. However, + * excessive rounding should be avoided. It is left to the driver author's + * discretion when this function should attempt to round and when it should + * return an error. For example, a dividing clock might use the following + * pseudo-logic when implemening this function:: + * + * divisor = parent_rate / rate + * if divisor < min || divisor > max: + * return -EINVAL + * + * If there is any concern about rounding, prefer to let consumers make the + * decision by calling round_rate(). + * + * Return: + * * The new rate on success + * * -%ENOSYS if this function is not implemented for @clk + * * -%ENOENT if @clk->id is invalid. Prefer using an assert instead, and doing + * this check in request(). + * * -%EINVAL if @rate is not valid for @clk. + * * Another negative error value (such as %EIO or %ECOMM) if the rate could + * not be set due to a bus error. */ ulong set_rate(struct clk *clk, ulong rate); @@ -120,7 +174,19 @@ ulong set_rate(struct clk *clk, ulong rate); * @clk: The clock to manipulate. * @parent: New clock parent. * - * Return: zero on success, or -ve error code. + * Set the current parent of @clk to @parent. The rate of the clock may be + * modified by this call. If @clk was enabled before this function, it should + * remain enabled after this function, although it may be temporarily disabled + * if necessary. + * + * Return: + * * 0 on success + * * -%ENOSYS if this function is not implemented for @clk + * * -%ENOENT if @clk->id or @parent->id is invalid. Prefer using an assert + * instead, and doing this check in request(). + * * -%EINVAL if @parent is not a valid parent for @clk. + * * Another negative error value (such as %EIO or %ECOMM) if the parent could + * not be set due to a bus error. */ int set_parent(struct clk *clk, struct clk *parent); @@ -128,7 +194,16 @@ int set_parent(struct clk *clk, struct clk *parent); * enable() - Enable a clock. * @clk: The clock to manipulate. * - * Return: zero on success, or -ve error code. + * Enable (un-gate) the clock. This function should not modify the rate of the + * clock (see get_rate() for details). + * + * Return: + * * 0 on success + * * -%ENOSYS if this function is not implemented for @clk + * * -%ENOENT if @clk->id is invalid. Prefer using an assert instead, and doing + * this check in request(). + * * Another negative error value (such as %EIO or %ECOMM) if the clock could + * not be enabled due to a bus error. */ int enable(struct clk *clk); @@ -136,7 +211,15 @@ int enable(struct clk *clk); * disable() - Disable a clock. * @clk: The clock to manipulate. * - * Return: zero on success, or -ve error code. + * Disable (gate) the clock. This function should not modify the rate of the + * clock (see get_rate() for details). + * + * * 0 on success + * * -%ENOSYS if this function is not implemented for @clk + * * -%ENOENT if @clk->id is invalid. Prefer using an assert instead, and doing + * this check in request(). + * * Another negative error value (such as %EIO or %ECOMM) if the clock could + * not be disabled due to a bus error. */ int disable(struct clk *clk); diff --git a/include/clk.h b/include/clk.h index 3d6394477b..af23e4f347 100644 --- a/include/clk.h +++ b/include/clk.h @@ -247,19 +247,6 @@ static inline struct clk *devm_clk_get_optional(struct udevice *dev, */ int clk_release_all(struct clk *clk, unsigned int count); -/** - * devm_clk_put - "free" a managed clock source - * @dev: device used to acquire the clock - * @clk: clock source acquired with devm_clk_get() - * - * Note: drivers must ensure that all clk_enable calls made on this - * clock source are balanced by clk_disable calls prior to calling - * this function. - * - * clk_put should not be called from within interrupt context. - */ -void devm_clk_put(struct udevice *dev, struct clk *clk); - #else static inline int clk_get_by_phandle(struct udevice *dev, const @@ -313,10 +300,6 @@ static inline int clk_release_all(struct clk *clk, unsigned int count) { return -ENOSYS; } - -static inline void devm_clk_put(struct udevice *dev, struct clk *clk) -{ -} #endif /** @@ -442,15 +425,6 @@ static inline int clk_release_bulk(struct clk_bulk *bulk) int clk_request(struct udevice *dev, struct clk *clk); /** - * clk_free() - Free a previously requested clock. - * @clk: A clock struct that was previously successfully requested by - * clk_request/get_by_*(). - * - * Free resources allocated by clk_request() (or any clk_get_* function). - */ -void clk_free(struct clk *clk); - -/** * clk_get_rate() - Get current clock rate. * @clk: A clock struct that was previously successfully requested by * clk_request/get_by_*(). @@ -594,11 +568,6 @@ static inline int clk_request(struct udevice *dev, struct clk *clk) return -ENOSYS; } -static inline void clk_free(struct clk *clk) -{ - return; -} - static inline ulong clk_get_rate(struct clk *clk) { return -ENOSYS; diff --git a/include/configs/milkv_duo.h b/include/configs/milkv_duo.h new file mode 100644 index 0000000000..0b4109dc1f --- /dev/null +++ b/include/configs/milkv_duo.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2024, Kongyang Liu <seashell11234455@gmail.com> + * + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +#define CFG_SYS_SDRAM_BASE 0x80000000 + +#endif /* __CONFIG_H */ diff --git a/include/configs/qemu-riscv.h b/include/configs/qemu-riscv.h index 584559cfa3..2f594bfcfd 100644 --- a/include/configs/qemu-riscv.h +++ b/include/configs/qemu-riscv.h @@ -23,6 +23,7 @@ #define BOOT_TARGET_DEVICES(func) \ func(VIRTIO, virtio, 0) \ + func(VIRTIO, virtio, 1) \ func(SCSI, scsi, 0) \ func(DHCP, dhcp, na) diff --git a/test/dm/clk.c b/test/dm/clk.c index 01417fbd82..57fabbdce0 100644 --- a/test/dm/clk.c +++ b/test/dm/clk.c @@ -182,19 +182,10 @@ static int dm_test_clk(struct unit_test_state *uts) SANDBOX_CLK_ID_I2C)); ut_asserteq(1, sandbox_clk_query_requested(dev_clk, SANDBOX_CLK_ID_UART2)); - ut_assertok(sandbox_clk_test_free(dev_test)); - ut_asserteq(0, sandbox_clk_query_requested(dev_clk, - SANDBOX_CLK_ID_SPI)); - ut_asserteq(0, sandbox_clk_query_requested(dev_clk, - SANDBOX_CLK_ID_I2C)); - ut_asserteq(0, sandbox_clk_query_requested(dev_clk, - SANDBOX_CLK_ID_UART2)); ut_asserteq(1, sandbox_clk_query_requested(dev_clk, SANDBOX_CLK_ID_UART1)); ut_assertok(device_remove(dev_test, DM_REMOVE_NORMAL)); - ut_asserteq(0, sandbox_clk_query_requested(dev_clk, - SANDBOX_CLK_ID_UART1)); return 0; } DM_TEST(dm_test_clk, UT_TESTF_SCAN_FDT); |