From 84335544ead850efa80139cf9aa8e83eb6bfdfb4 Mon Sep 17 00:00:00 2001 From: Jim Liu Date: Tue, 19 Apr 2022 13:32:19 +0800 Subject: [PATCH 01/13] arm: nuvoton: Add support for Nuvoton NPCM750 BMC Add basic support for the Nuvoton NPCM750 EVB (Poleg). Signed-off-by: Jim Liu --- arch/arm/Kconfig | 8 + arch/arm/Makefile | 1 + arch/arm/dts/Makefile | 1 + arch/arm/dts/nuvoton-common-npcm7xx.dtsi | 1120 +++++++++++++++++ arch/arm/dts/nuvoton-npcm750-evb.dts | 405 ++++++ arch/arm/dts/nuvoton-npcm750-pincfg-evb.dtsi | 157 +++ arch/arm/dts/nuvoton-npcm750.dtsi | 62 + arch/arm/include/asm/arch-npcm7xx/gcr.h | 65 + arch/arm/mach-npcm/Kconfig | 26 + arch/arm/mach-npcm/Makefile | 1 + arch/arm/mach-npcm/npcm7xx/Kconfig | 22 + arch/arm/mach-npcm/npcm7xx/Makefile | 1 + arch/arm/mach-npcm/npcm7xx/cpu.c | 66 + arch/arm/mach-npcm/npcm7xx/l2_cache_pl310.c | 29 + .../mach-npcm/npcm7xx/l2_cache_pl310_init.S | 71 ++ board/nuvoton/poleg_evb/Kconfig | 25 + board/nuvoton/poleg_evb/MAINTAINERS | 7 + board/nuvoton/poleg_evb/Makefile | 1 + board/nuvoton/poleg_evb/poleg_evb.c | 48 + configs/poleg_evb_defconfig | 40 + include/configs/poleg.h | 44 + .../dt-bindings/reset/nuvoton,npcm7xx-reset.h | 91 ++ 22 files changed, 2291 insertions(+) create mode 100644 arch/arm/dts/nuvoton-common-npcm7xx.dtsi create mode 100644 arch/arm/dts/nuvoton-npcm750-evb.dts create mode 100644 arch/arm/dts/nuvoton-npcm750-pincfg-evb.dtsi create mode 100644 arch/arm/dts/nuvoton-npcm750.dtsi create mode 100644 arch/arm/include/asm/arch-npcm7xx/gcr.h create mode 100644 arch/arm/mach-npcm/Kconfig create mode 100644 arch/arm/mach-npcm/Makefile create mode 100644 arch/arm/mach-npcm/npcm7xx/Kconfig create mode 100644 arch/arm/mach-npcm/npcm7xx/Makefile create mode 100644 arch/arm/mach-npcm/npcm7xx/cpu.c create mode 100644 arch/arm/mach-npcm/npcm7xx/l2_cache_pl310.c create mode 100644 arch/arm/mach-npcm/npcm7xx/l2_cache_pl310_init.S create mode 100644 board/nuvoton/poleg_evb/Kconfig create mode 100644 board/nuvoton/poleg_evb/MAINTAINERS create mode 100644 board/nuvoton/poleg_evb/Makefile create mode 100644 board/nuvoton/poleg_evb/poleg_evb.c create mode 100644 configs/poleg_evb_defconfig create mode 100644 include/configs/poleg.h create mode 100644 include/dt-bindings/reset/nuvoton,npcm7xx-reset.h diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 57946f61fab..0afec5155b1 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1004,6 +1004,12 @@ config ARCH_NEXELL select DM select GPIO_EXTRA_HEADER +config ARCH_NPCM + bool "Support Nuvoton SoCs" + select DM + select OF_CONTROL + imply CMD_DM + config ARCH_APPLE bool "Apple SoCs" select ARM64 @@ -2279,6 +2285,8 @@ source "arch/arm/mach-imx/Kconfig" source "arch/arm/mach-nexell/Kconfig" +source "arch/arm/mach-npcm/Kconfig" + source "board/armltd/total_compute/Kconfig" source "board/bosch/shc/Kconfig" diff --git a/arch/arm/Makefile b/arch/arm/Makefile index ad757e982e3..85c23bcf775 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -72,6 +72,7 @@ machine-$(CONFIG_ARCH_MEDIATEK) += mediatek machine-$(CONFIG_ARCH_MESON) += meson machine-$(CONFIG_ARCH_MVEBU) += mvebu machine-$(CONFIG_ARCH_NEXELL) += nexell +machine-$(CONFIG_ARCH_NPCM) += npcm machine-$(CONFIG_ARCH_OMAP2PLUS) += omap2 machine-$(CONFIG_ARCH_ORION5X) += orion5x machine-$(CONFIG_ARCH_OWL) += owl diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index ab2d0da192c..83630af4f67 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -1184,6 +1184,7 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += \ mt8516-pumpkin.dtb \ mt8518-ap1-emmc.dtb +dtb-$(CONFIG_ARCH_NPCM7xx) += nuvoton-npcm750-evb.dtb dtb-$(CONFIG_XEN) += xenguest-arm64.dtb dtb-$(CONFIG_ARCH_OCTEONTX) += octeontx.dtb diff --git a/arch/arm/dts/nuvoton-common-npcm7xx.dtsi b/arch/arm/dts/nuvoton-common-npcm7xx.dtsi new file mode 100644 index 00000000000..02ee4d78e25 --- /dev/null +++ b/arch/arm/dts/nuvoton-common-npcm7xx.dtsi @@ -0,0 +1,1120 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include + +/ { + #address-cells = <1>; + #size-cells = <1>; + interrupt-parent = <&gic>; + + /* external reference clock */ + clk_refclk: clk_refclk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <25000000>; + clock-output-names = "refclk"; + }; + + /* external reference clock for cpu. float in normal operation */ + clk_sysbypck: clk_sysbypck { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <800000000>; + clock-output-names = "sysbypck"; + }; + + /* external reference clock for MC. float in normal operation */ + clk_mcbypck: clk_mcbypck { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <800000000>; + clock-output-names = "mcbypck"; + }; + + /* external clock signal rg1refck, supplied by the phy */ + clk_rg1refck: clk_rg1refck { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <125000000>; + clock-output-names = "clk_rg1refck"; + }; + + /* external clock signal rg2refck, supplied by the phy */ + clk_rg2refck: clk_rg2refck { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <125000000>; + clock-output-names = "clk_rg2refck"; + }; + + clk_xin: clk_xin { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <50000000>; + clock-output-names = "clk_xin"; + }; + + soc { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + interrupt-parent = <&gic>; + ranges = <0x0 0xf0000000 0x00900000>; + + scu: scu@3fe000 { + compatible = "arm,cortex-a9-scu"; + reg = <0x3fe000 0x1000>; + }; + + l2: cache-controller@3fc000 { + compatible = "arm,pl310-cache"; + reg = <0x3fc000 0x1000>; + interrupts = ; + cache-unified; + cache-level = <2>; + clocks = <&clk NPCM7XX_CLK_AXI>; + arm,shared-override; + }; + + gic: interrupt-controller@3ff000 { + compatible = "arm,cortex-a9-gic"; + interrupt-controller; + #interrupt-cells = <3>; + reg = <0x3ff000 0x1000>, + <0x3fe100 0x100>; + }; + + gcr: gcr@800000 { + compatible = "nuvoton,npcm750-gcr", "syscon", "simple-mfd"; + reg = <0x800000 0x1000>; + }; + + rst: rst@801000 { + compatible = "nuvoton,npcm750-rst", "syscon", "simple-mfd"; + reg = <0x801000 0x6C>; + }; + }; + + ahb { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + interrupt-parent = <&gic>; + ranges; + + rstc: rstc@f0801000 { + compatible = "nuvoton,npcm750-reset"; + reg = <0xf0801000 0x70>; + #reset-cells = <2>; + }; + + clk: clock-controller@f0801000 { + compatible = "nuvoton,npcm750-clk", "syscon"; + #clock-cells = <1>; + clock-controller; + reg = <0xf0801000 0x1000>; + clock-names = "refclk", "sysbypck", "mcbypck"; + clocks = <&clk_refclk>, <&clk_sysbypck>, <&clk_mcbypck>; + }; + + gmac0: eth@f0802000 { + device_type = "network"; + compatible = "nuvoton,npcm-dwmac"; + reg = <0xf0802000 0x2000>; + interrupts = ; + interrupt-names = "macirq"; + ethernet = <0>; + clocks = <&clk_rg1refck>, <&clk NPCM7XX_CLK_AHB>; + clock-names = "stmmaceth", "clk_gmac"; + pinctrl-names = "default"; + pinctrl-0 = <&rg1_pins + &rg1mdio_pins>; + status = "disabled"; + }; + + ehci1: usb@f0806000 { + compatible = "nuvoton,npcm750-ehci"; + reg = <0xf0806000 0x1000>; + interrupts = ; + status = "disabled"; + }; + + fiu0: spi@fb000000 { + compatible = "nuvoton,npcm750-fiu"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0xfb000000 0x1000>; + reg-names = "control", "memory"; + clocks = <&clk NPCM7XX_CLK_SPI0>; + clock-names = "clk_spi0"; + status = "disabled"; + }; + + fiu3: spi@c0000000 { + compatible = "nuvoton,npcm750-fiu"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0xc0000000 0x1000>; + reg-names = "control", "memory"; + clocks = <&clk NPCM7XX_CLK_SPI3>; + clock-names = "clk_spi3"; + pinctrl-names = "default"; + pinctrl-0 = <&spi3_pins>; + status = "disabled"; + }; + + fiux: spi@fb001000 { + compatible = "nuvoton,npcm750-fiu"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0xfb001000 0x1000>; + reg-names = "control", "memory"; + clocks = <&clk NPCM7XX_CLK_SPIX>; + clock-names = "clk_spix"; + status = "disabled"; + }; + + apb { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + interrupt-parent = <&gic>; + ranges = <0x0 0xf0000000 0x00300000>; + + lpc_kcs: lpc_kcs@7000 { + compatible = "nuvoton,npcm750-lpc-kcs", "simple-mfd", "syscon"; + reg = <0x7000 0x40>; + reg-io-width = <1>; + + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x7000 0x40>; + + kcs1: kcs1@0 { + compatible = "nuvoton,npcm750-kcs-bmc"; + reg = <0x0 0x40>; + interrupts = ; + kcs_chan = <1>; + status = "disabled"; + }; + + kcs2: kcs2@0 { + compatible = "nuvoton,npcm750-kcs-bmc"; + reg = <0x0 0x40>; + interrupts = ; + kcs_chan = <2>; + status = "disabled"; + }; + + kcs3: kcs3@0 { + compatible = "nuvoton,npcm750-kcs-bmc"; + reg = <0x0 0x40>; + interrupts = ; + kcs_chan = <3>; + status = "disabled"; + }; + }; + + spi0: spi@200000 { + compatible = "nuvoton,npcm750-pspi"; + reg = <0x200000 0x1000>; + pinctrl-names = "default"; + pinctrl-0 = <&pspi1_pins>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&clk NPCM7XX_CLK_APB5>; + clock-names = "clk_apb5"; + resets = <&rstc NPCM7XX_RESET_IPSRST2 NPCM7XX_RESET_PSPI1>; + status = "disabled"; + }; + + spi1: spi@201000 { + compatible = "nuvoton,npcm750-pspi"; + reg = <0x201000 0x1000>; + pinctrl-names = "default"; + pinctrl-0 = <&pspi2_pins>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&clk NPCM7XX_CLK_APB5>; + clock-names = "clk_apb5"; + resets = <&rstc NPCM7XX_RESET_IPSRST2 NPCM7XX_RESET_PSPI2>; + status = "disabled"; + }; + + timer0: timer@8000 { + compatible = "nuvoton,npcm750-timer"; + interrupts = ; + reg = <0x8000 0x1C>; + clocks = <&clk NPCM7XX_CLK_TIMER>; + }; + + watchdog0: watchdog@801C { + compatible = "nuvoton,npcm750-wdt"; + interrupts = ; + reg = <0x801C 0x4>; + status = "disabled"; + clocks = <&clk NPCM7XX_CLK_TIMER>; + }; + + watchdog1: watchdog@901C { + compatible = "nuvoton,npcm750-wdt"; + interrupts = ; + reg = <0x901C 0x4>; + status = "disabled"; + clocks = <&clk NPCM7XX_CLK_TIMER>; + }; + + watchdog2: watchdog@a01C { + compatible = "nuvoton,npcm750-wdt"; + interrupts = ; + reg = <0xa01C 0x4>; + status = "disabled"; + clocks = <&clk NPCM7XX_CLK_TIMER>; + }; + + serial0: serial@1000 { + compatible = "nuvoton,npcm750-uart"; + reg = <0x1000 0x1000>; + clocks = <&clk NPCM7XX_CLK_UART>, <&clk NPCM7XX_CLK_PLL2DIV2>; + interrupts = ; + reg-shift = <2>; + status = "disabled"; + }; + + serial1: serial@2000 { + compatible = "nuvoton,npcm750-uart"; + reg = <0x2000 0x1000>; + clocks = <&clk NPCM7XX_CLK_UART>, <&clk NPCM7XX_CLK_PLL2DIV2>; + interrupts = ; + reg-shift = <2>; + status = "disabled"; + }; + + serial2: serial@3000 { + compatible = "nuvoton,npcm750-uart"; + reg = <0x3000 0x1000>; + clocks = <&clk NPCM7XX_CLK_UART>, <&clk NPCM7XX_CLK_PLL2DIV2>; + interrupts = ; + reg-shift = <2>; + status = "disabled"; + }; + + serial3: serial@4000 { + compatible = "nuvoton,npcm750-uart"; + reg = <0x4000 0x1000>; + clocks = <&clk NPCM7XX_CLK_UART>, <&clk NPCM7XX_CLK_PLL2DIV2>; + interrupts = ; + reg-shift = <2>; + status = "disabled"; + }; + + rng: rng@b000 { + compatible = "nuvoton,npcm750-rng"; + reg = <0xb000 0x8>; + status = "disabled"; + }; + + adc: adc@c000 { + compatible = "nuvoton,npcm750-adc"; + reg = <0xc000 0x8>; + interrupts = ; + clocks = <&clk NPCM7XX_CLK_ADC>; + resets = <&rstc NPCM7XX_RESET_IPSRST1 NPCM7XX_RESET_ADC>; + status = "disabled"; + }; + + pwm_fan: pwm-fan-controller@103000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "nuvoton,npcm750-pwm-fan"; + reg = <0x103000 0x2000>, <0x180000 0x8000>; + reg-names = "pwm", "fan"; + clocks = <&clk NPCM7XX_CLK_APB3>, + <&clk NPCM7XX_CLK_APB4>; + clock-names = "pwm","fan"; + interrupts = , + , + , + , + , + , + , + ; + pinctrl-names = "default"; + pinctrl-0 = <&pwm0_pins &pwm1_pins + &pwm2_pins &pwm3_pins + &pwm4_pins &pwm5_pins + &pwm6_pins &pwm7_pins + &fanin0_pins &fanin1_pins + &fanin2_pins &fanin3_pins + &fanin4_pins &fanin5_pins + &fanin6_pins &fanin7_pins + &fanin8_pins &fanin9_pins + &fanin10_pins &fanin11_pins + &fanin12_pins &fanin13_pins + &fanin14_pins &fanin15_pins>; + status = "disabled"; + }; + + i2c0: i2c@80000 { + reg = <0x80000 0x1000>; + compatible = "nuvoton,npcm750-i2c"; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clk NPCM7XX_CLK_APB2>; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&smb0_pins>; + status = "disabled"; + }; + + i2c1: i2c@81000 { + reg = <0x81000 0x1000>; + compatible = "nuvoton,npcm750-i2c"; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clk NPCM7XX_CLK_APB2>; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&smb1_pins>; + status = "disabled"; + }; + + i2c2: i2c@82000 { + reg = <0x82000 0x1000>; + compatible = "nuvoton,npcm750-i2c"; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clk NPCM7XX_CLK_APB2>; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&smb2_pins>; + status = "disabled"; + }; + + i2c3: i2c@83000 { + reg = <0x83000 0x1000>; + compatible = "nuvoton,npcm750-i2c"; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clk NPCM7XX_CLK_APB2>; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&smb3_pins>; + status = "disabled"; + }; + + i2c4: i2c@84000 { + reg = <0x84000 0x1000>; + compatible = "nuvoton,npcm750-i2c"; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clk NPCM7XX_CLK_APB2>; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&smb4_pins>; + status = "disabled"; + }; + + i2c5: i2c@85000 { + reg = <0x85000 0x1000>; + compatible = "nuvoton,npcm750-i2c"; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clk NPCM7XX_CLK_APB2>; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&smb5_pins>; + status = "disabled"; + }; + + i2c6: i2c@86000 { + reg = <0x86000 0x1000>; + compatible = "nuvoton,npcm750-i2c"; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clk NPCM7XX_CLK_APB2>; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&smb6_pins>; + status = "disabled"; + }; + + i2c7: i2c@87000 { + reg = <0x87000 0x1000>; + compatible = "nuvoton,npcm750-i2c"; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clk NPCM7XX_CLK_APB2>; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&smb7_pins>; + status = "disabled"; + }; + + i2c8: i2c@88000 { + reg = <0x88000 0x1000>; + compatible = "nuvoton,npcm750-i2c"; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clk NPCM7XX_CLK_APB2>; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&smb8_pins>; + status = "disabled"; + }; + + i2c9: i2c@89000 { + reg = <0x89000 0x1000>; + compatible = "nuvoton,npcm750-i2c"; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clk NPCM7XX_CLK_APB2>; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&smb9_pins>; + status = "disabled"; + }; + + i2c10: i2c@8a000 { + reg = <0x8a000 0x1000>; + compatible = "nuvoton,npcm750-i2c"; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clk NPCM7XX_CLK_APB2>; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&smb10_pins>; + status = "disabled"; + }; + + i2c11: i2c@8b000 { + reg = <0x8b000 0x1000>; + compatible = "nuvoton,npcm750-i2c"; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clk NPCM7XX_CLK_APB2>; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&smb11_pins>; + status = "disabled"; + }; + + i2c12: i2c@8c000 { + reg = <0x8c000 0x1000>; + compatible = "nuvoton,npcm750-i2c"; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clk NPCM7XX_CLK_APB2>; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&smb12_pins>; + status = "disabled"; + }; + + i2c13: i2c@8d000 { + reg = <0x8d000 0x1000>; + compatible = "nuvoton,npcm750-i2c"; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clk NPCM7XX_CLK_APB2>; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&smb13_pins>; + status = "disabled"; + }; + + i2c14: i2c@8e000 { + reg = <0x8e000 0x1000>; + compatible = "nuvoton,npcm750-i2c"; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clk NPCM7XX_CLK_APB2>; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&smb14_pins>; + status = "disabled"; + }; + + i2c15: i2c@8f000 { + reg = <0x8f000 0x1000>; + compatible = "nuvoton,npcm750-i2c"; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clk NPCM7XX_CLK_APB2>; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&smb15_pins>; + status = "disabled"; + }; + }; + }; + + pinctrl: pinctrl@f0800000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "nuvoton,npcm750-pinctrl", "syscon", "simple-mfd"; + ranges = <0 0xf0010000 0x8000>; + gpio0: gpio@f0010000 { + gpio-controller; + #gpio-cells = <2>; + reg = <0x0 0x80>; + interrupts = ; + gpio-ranges = <&pinctrl 0 0 32>; + }; + gpio1: gpio@f0011000 { + gpio-controller; + #gpio-cells = <2>; + reg = <0x1000 0x80>; + interrupts = ; + gpio-ranges = <&pinctrl 0 32 32>; + }; + gpio2: gpio@f0012000 { + gpio-controller; + #gpio-cells = <2>; + reg = <0x2000 0x80>; + interrupts = ; + gpio-ranges = <&pinctrl 0 64 32>; + }; + gpio3: gpio@f0013000 { + gpio-controller; + #gpio-cells = <2>; + reg = <0x3000 0x80>; + interrupts = ; + gpio-ranges = <&pinctrl 0 96 32>; + }; + gpio4: gpio@f0014000 { + gpio-controller; + #gpio-cells = <2>; + reg = <0x4000 0x80>; + interrupts = ; + gpio-ranges = <&pinctrl 0 128 32>; + }; + gpio5: gpio@f0015000 { + gpio-controller; + #gpio-cells = <2>; + reg = <0x5000 0x80>; + interrupts = ; + gpio-ranges = <&pinctrl 0 160 32>; + }; + gpio6: gpio@f0016000 { + gpio-controller; + #gpio-cells = <2>; + reg = <0x6000 0x80>; + interrupts = ; + gpio-ranges = <&pinctrl 0 192 32>; + }; + gpio7: gpio@f0017000 { + gpio-controller; + #gpio-cells = <2>; + reg = <0x7000 0x80>; + interrupts = ; + gpio-ranges = <&pinctrl 0 224 32>; + }; + + iox1_pins: iox1-pins { + groups = "iox1"; + function = "iox1"; + }; + iox2_pins: iox2-pins { + groups = "iox2"; + function = "iox2"; + }; + smb1d_pins: smb1d-pins { + groups = "smb1d"; + function = "smb1d"; + }; + smb2d_pins: smb2d-pins { + groups = "smb2d"; + function = "smb2d"; + }; + lkgpo1_pins: lkgpo1-pins { + groups = "lkgpo1"; + function = "lkgpo1"; + }; + lkgpo2_pins: lkgpo2-pins { + groups = "lkgpo2"; + function = "lkgpo2"; + }; + ioxh_pins: ioxh-pins { + groups = "ioxh"; + function = "ioxh"; + }; + gspi_pins: gspi-pins { + groups = "gspi"; + function = "gspi"; + }; + smb5b_pins: smb5b-pins { + groups = "smb5b"; + function = "smb5b"; + }; + smb5c_pins: smb5c-pins { + groups = "smb5c"; + function = "smb5c"; + }; + lkgpo0_pins: lkgpo0-pins { + groups = "lkgpo0"; + function = "lkgpo0"; + }; + pspi2_pins: pspi2-pins { + groups = "pspi2"; + function = "pspi2"; + }; + smb4den_pins: smb4den-pins { + groups = "smb4den"; + function = "smb4den"; + }; + smb4b_pins: smb4b-pins { + groups = "smb4b"; + function = "smb4b"; + }; + smb4c_pins: smb4c-pins { + groups = "smb4c"; + function = "smb4c"; + }; + smb15_pins: smb15-pins { + groups = "smb15"; + function = "smb15"; + }; + smb4d_pins: smb4d-pins { + groups = "smb4d"; + function = "smb4d"; + }; + smb14_pins: smb14-pins { + groups = "smb14"; + function = "smb14"; + }; + smb5_pins: smb5-pins { + groups = "smb5"; + function = "smb5"; + }; + smb4_pins: smb4-pins { + groups = "smb4"; + function = "smb4"; + }; + smb3_pins: smb3-pins { + groups = "smb3"; + function = "smb3"; + }; + spi0cs1_pins: spi0cs1-pins { + groups = "spi0cs1"; + function = "spi0cs1"; + }; + spi0cs2_pins: spi0cs2-pins { + groups = "spi0cs2"; + function = "spi0cs2"; + }; + spi0cs3_pins: spi0cs3-pins { + groups = "spi0cs3"; + function = "spi0cs3"; + }; + smb3c_pins: smb3c-pins { + groups = "smb3c"; + function = "smb3c"; + }; + smb3b_pins: smb3b-pins { + groups = "smb3b"; + function = "smb3b"; + }; + bmcuart0a_pins: bmcuart0a-pins { + groups = "bmcuart0a"; + function = "bmcuart0a"; + }; + uart1_pins: uart1-pins { + groups = "uart1"; + function = "uart1"; + }; + jtag2_pins: jtag2-pins { + groups = "jtag2"; + function = "jtag2"; + }; + bmcuart1_pins: bmcuart1-pins { + groups = "bmcuart1"; + function = "bmcuart1"; + }; + uart2_pins: uart2-pins { + groups = "uart2"; + function = "uart2"; + }; + bmcuart0b_pins: bmcuart0b-pins { + groups = "bmcuart0b"; + function = "bmcuart0b"; + }; + r1err_pins: r1err-pins { + groups = "r1err"; + function = "r1err"; + }; + r1md_pins: r1md-pins { + groups = "r1md"; + function = "r1md"; + }; + smb3d_pins: smb3d-pins { + groups = "smb3d"; + function = "smb3d"; + }; + fanin0_pins: fanin0-pins { + groups = "fanin0"; + function = "fanin0"; + }; + fanin1_pins: fanin1-pins { + groups = "fanin1"; + function = "fanin1"; + }; + fanin2_pins: fanin2-pins { + groups = "fanin2"; + function = "fanin2"; + }; + fanin3_pins: fanin3-pins { + groups = "fanin3"; + function = "fanin3"; + }; + fanin4_pins: fanin4-pins { + groups = "fanin4"; + function = "fanin4"; + }; + fanin5_pins: fanin5-pins { + groups = "fanin5"; + function = "fanin5"; + }; + fanin6_pins: fanin6-pins { + groups = "fanin6"; + function = "fanin6"; + }; + fanin7_pins: fanin7-pins { + groups = "fanin7"; + function = "fanin7"; + }; + fanin8_pins: fanin8-pins { + groups = "fanin8"; + function = "fanin8"; + }; + fanin9_pins: fanin9-pins { + groups = "fanin9"; + function = "fanin9"; + }; + fanin10_pins: fanin10-pins { + groups = "fanin10"; + function = "fanin10"; + }; + fanin11_pins: fanin11-pins { + groups = "fanin11"; + function = "fanin11"; + }; + fanin12_pins: fanin12-pins { + groups = "fanin12"; + function = "fanin12"; + }; + fanin13_pins: fanin13-pins { + groups = "fanin13"; + function = "fanin13"; + }; + fanin14_pins: fanin14-pins { + groups = "fanin14"; + function = "fanin14"; + }; + fanin15_pins: fanin15-pins { + groups = "fanin15"; + function = "fanin15"; + }; + pwm0_pins: pwm0-pins { + groups = "pwm0"; + function = "pwm0"; + }; + pwm1_pins: pwm1-pins { + groups = "pwm1"; + function = "pwm1"; + }; + pwm2_pins: pwm2-pins { + groups = "pwm2"; + function = "pwm2"; + }; + pwm3_pins: pwm3-pins { + groups = "pwm3"; + function = "pwm3"; + }; + r2_pins: r2-pins { + groups = "r2"; + function = "r2"; + }; + r2err_pins: r2err-pins { + groups = "r2err"; + function = "r2err"; + }; + r2md_pins: r2md-pins { + groups = "r2md"; + function = "r2md"; + }; + ga20kbc_pins: ga20kbc-pins { + groups = "ga20kbc"; + function = "ga20kbc"; + }; + smb5d_pins: smb5d-pins { + groups = "smb5d"; + function = "smb5d"; + }; + lpc_pins: lpc-pins { + groups = "lpc"; + function = "lpc"; + }; + espi_pins: espi-pins { + groups = "espi"; + function = "espi"; + }; + rg1_pins: rg1-pins { + groups = "rg1"; + function = "rg1"; + }; + rg1mdio_pins: rg1mdio-pins { + groups = "rg1mdio"; + function = "rg1mdio"; + }; + rg2_pins: rg2-pins { + groups = "rg2"; + function = "rg2"; + }; + ddr_pins: ddr-pins { + groups = "ddr"; + function = "ddr"; + }; + smb0_pins: smb0-pins { + groups = "smb0"; + function = "smb0"; + }; + smb1_pins: smb1-pins { + groups = "smb1"; + function = "smb1"; + }; + smb2_pins: smb2-pins { + groups = "smb2"; + function = "smb2"; + }; + smb2c_pins: smb2c-pins { + groups = "smb2c"; + function = "smb2c"; + }; + smb2b_pins: smb2b-pins { + groups = "smb2b"; + function = "smb2b"; + }; + smb1c_pins: smb1c-pins { + groups = "smb1c"; + function = "smb1c"; + }; + smb1b_pins: smb1b-pins { + groups = "smb1b"; + function = "smb1b"; + }; + smb8_pins: smb8-pins { + groups = "smb8"; + function = "smb8"; + }; + smb9_pins: smb9-pins { + groups = "smb9"; + function = "smb9"; + }; + smb10_pins: smb10-pins { + groups = "smb10"; + function = "smb10"; + }; + smb11_pins: smb11-pins { + groups = "smb11"; + function = "smb11"; + }; + sd1_pins: sd1-pins { + groups = "sd1"; + function = "sd1"; + }; + sd1pwr_pins: sd1pwr-pins { + groups = "sd1pwr"; + function = "sd1pwr"; + }; + pwm4_pins: pwm4-pins { + groups = "pwm4"; + function = "pwm4"; + }; + pwm5_pins: pwm5-pins { + groups = "pwm5"; + function = "pwm5"; + }; + pwm6_pins: pwm6-pins { + groups = "pwm6"; + function = "pwm6"; + }; + pwm7_pins: pwm7-pins { + groups = "pwm7"; + function = "pwm7"; + }; + mmc8_pins: mmc8-pins { + groups = "mmc8"; + function = "mmc8"; + }; + mmc_pins: mmc-pins { + groups = "mmc"; + function = "mmc"; + }; + mmcwp_pins: mmcwp-pins { + groups = "mmcwp"; + function = "mmcwp"; + }; + mmccd_pins: mmccd-pins { + groups = "mmccd"; + function = "mmccd"; + }; + mmcrst_pins: mmcrst-pins { + groups = "mmcrst"; + function = "mmcrst"; + }; + clkout_pins: clkout-pins { + groups = "clkout"; + function = "clkout"; + }; + serirq_pins: serirq-pins { + groups = "serirq"; + function = "serirq"; + }; + lpcclk_pins: lpcclk-pins { + groups = "lpcclk"; + function = "lpcclk"; + }; + scipme_pins: scipme-pins { + groups = "scipme"; + function = "scipme"; + }; + sci_pins: sci-pins { + groups = "sci"; + function = "sci"; + }; + smb6_pins: smb6-pins { + groups = "smb6"; + function = "smb6"; + }; + smb7_pins: smb7-pins { + groups = "smb7"; + function = "smb7"; + }; + pspi1_pins: pspi1-pins { + groups = "pspi1"; + function = "pspi1"; + }; + faninx_pins: faninx-pins { + groups = "faninx"; + function = "faninx"; + }; + r1_pins: r1-pins { + groups = "r1"; + function = "r1"; + }; + spi3_pins: spi3-pins { + groups = "spi3"; + function = "spi3"; + }; + spi3cs1_pins: spi3cs1-pins { + groups = "spi3cs1"; + function = "spi3cs1"; + }; + spi3quad_pins: spi3quad-pins { + groups = "spi3quad"; + function = "spi3quad"; + }; + spi3cs2_pins: spi3cs2-pins { + groups = "spi3cs2"; + function = "spi3cs2"; + }; + spi3cs3_pins: spi3cs3-pins { + groups = "spi3cs3"; + function = "spi3cs3"; + }; + nprd_smi_pins: nprd-smi-pins { + groups = "nprd_smi"; + function = "nprd_smi"; + }; + smb0b_pins: smb0b-pins { + groups = "smb0b"; + function = "smb0b"; + }; + smb0c_pins: smb0c-pins { + groups = "smb0c"; + function = "smb0c"; + }; + smb0den_pins: smb0den-pins { + groups = "smb0den"; + function = "smb0den"; + }; + smb0d_pins: smb0d-pins { + groups = "smb0d"; + function = "smb0d"; + }; + ddc_pins: ddc-pins { + groups = "ddc"; + function = "ddc"; + }; + rg2mdio_pins: rg2mdio-pins { + groups = "rg2mdio"; + function = "rg2mdio"; + }; + wdog1_pins: wdog1-pins { + groups = "wdog1"; + function = "wdog1"; + }; + wdog2_pins: wdog2-pins { + groups = "wdog2"; + function = "wdog2"; + }; + smb12_pins: smb12-pins { + groups = "smb12"; + function = "smb12"; + }; + smb13_pins: smb13-pins { + groups = "smb13"; + function = "smb13"; + }; + spix_pins: spix-pins { + groups = "spix"; + function = "spix"; + }; + spixcs1_pins: spixcs1-pins { + groups = "spixcs1"; + function = "spixcs1"; + }; + clkreq_pins: clkreq-pins { + groups = "clkreq"; + function = "clkreq"; + }; + hgpio0_pins: hgpio0-pins { + groups = "hgpio0"; + function = "hgpio0"; + }; + hgpio1_pins: hgpio1-pins { + groups = "hgpio1"; + function = "hgpio1"; + }; + hgpio2_pins: hgpio2-pins { + groups = "hgpio2"; + function = "hgpio2"; + }; + hgpio3_pins: hgpio3-pins { + groups = "hgpio3"; + function = "hgpio3"; + }; + hgpio4_pins: hgpio4-pins { + groups = "hgpio4"; + function = "hgpio4"; + }; + hgpio5_pins: hgpio5-pins { + groups = "hgpio5"; + function = "hgpio5"; + }; + hgpio6_pins: hgpio6-pins { + groups = "hgpio6"; + function = "hgpio6"; + }; + hgpio7_pins: hgpio7-pins { + groups = "hgpio7"; + function = "hgpio7"; + }; + }; +}; diff --git a/arch/arm/dts/nuvoton-npcm750-evb.dts b/arch/arm/dts/nuvoton-npcm750-evb.dts new file mode 100644 index 00000000000..3e4abe66100 --- /dev/null +++ b/arch/arm/dts/nuvoton-npcm750-evb.dts @@ -0,0 +1,405 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2018 Nuvoton Technology tomer.maimon@nuvoton.com +// Copyright 2018 Google, Inc. + +/dts-v1/; +#include "nuvoton-npcm750.dtsi" +#include "dt-bindings/gpio/gpio.h" +#include "nuvoton-npcm750-pincfg-evb.dtsi" + +/ { + model = "Nuvoton npcm750 Development Board (Device Tree)"; + compatible = "nuvoton,npcm750-evb", "nuvoton,npcm750"; + + aliases { + ethernet2 = &gmac0; + ethernet3 = &gmac1; + serial0 = &serial0; + serial1 = &serial1; + serial2 = &serial2; + serial3 = &serial3; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c4; + i2c5 = &i2c5; + i2c6 = &i2c6; + i2c7 = &i2c7; + i2c8 = &i2c8; + i2c9 = &i2c9; + i2c10 = &i2c10; + i2c11 = &i2c11; + i2c12 = &i2c12; + i2c13 = &i2c13; + i2c14 = &i2c14; + i2c15 = &i2c15; + spi0 = &spi0; + spi1 = &spi1; + fiu0 = &fiu0; + fiu1 = &fiu3; + fiu2 = &fiux; + }; + + chosen { + stdout-path = &serial0; + }; + + memory { + device_type = "memory"; + reg = <0x0 0x20000000>; + }; +}; + +&gmac0 { + phy-mode = "rgmii-id"; + status = "okay"; +}; + +&gmac1 { + phy-mode = "rgmii-id"; + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + +&fiu0 { + status = "okay"; + spi-nor@0 { + compatible = "jedec,spi-nor"; + #address-cells = <1>; + #size-cells = <1>; + spi-rx-bus-width = <2>; + reg = <0>; + spi-max-frequency = <5000000>; + partitions@80000000 { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + bbuboot1@0 { + label = "bb-uboot-1"; + reg = <0x0000000 0x80000>; + read-only; + }; + bbuboot2@80000 { + label = "bb-uboot-2"; + reg = <0x0080000 0x80000>; + read-only; + }; + envparam@100000 { + label = "env-param"; + reg = <0x0100000 0x40000>; + read-only; + }; + spare@140000 { + label = "spare"; + reg = <0x0140000 0xC0000>; + }; + kernel@200000 { + label = "kernel"; + reg = <0x0200000 0x400000>; + }; + rootfs@600000 { + label = "rootfs"; + reg = <0x0600000 0x700000>; + }; + spare1@d00000 { + label = "spare1"; + reg = <0x0D00000 0x200000>; + }; + spare2@f00000 { + label = "spare2"; + reg = <0x0F00000 0x200000>; + }; + spare3@1100000 { + label = "spare3"; + reg = <0x1100000 0x200000>; + }; + spare4@1300000 { + label = "spare4"; + reg = <0x1300000 0x0>; + }; + }; + }; +}; + +&fiu3 { + pinctrl-0 = <&spi3_pins>, <&spi3quad_pins>; + status = "okay"; + spi-nor@0 { + compatible = "jedec,spi-nor"; + #address-cells = <1>; + #size-cells = <1>; + spi-rx-bus-width = <2>; + reg = <0>; + spi-max-frequency = <5000000>; + partitions@A0000000 { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + system1@0 { + label = "spi3-system1"; + reg = <0x0 0x0>; + }; + }; + }; +}; + +&fiux { + spix-mode; +}; + +&watchdog1 { + status = "okay"; +}; + +&rng { + status = "okay"; +}; + +&serial0 { + status = "okay"; + clock-frequency = <24000000>; +}; + +&serial1 { + status = "okay"; +}; + +&serial2 { + status = "okay"; +}; + +&serial3 { + status = "okay"; +}; + +&adc { + status = "okay"; +}; + +&lpc_kcs { + kcs1: kcs1@0 { + status = "okay"; + }; + + kcs2: kcs2@0 { + status = "okay"; + }; + + kcs3: kcs3@0 { + status = "okay"; + }; +}; + +/* lm75 on SVB */ +&i2c0 { + clock-frequency = <100000>; + status = "okay"; + lm75@48 { + compatible = "lm75"; + reg = <0x48>; + status = "okay"; + }; +}; + +/* lm75 on EB */ +&i2c1 { + clock-frequency = <100000>; + status = "okay"; + lm75@48 { + compatible = "lm75"; + reg = <0x48>; + status = "okay"; + }; +}; + +/* tmp100 on EB */ +&i2c2 { + clock-frequency = <100000>; + status = "okay"; + tmp100@48 { + compatible = "tmp100"; + reg = <0x48>; + status = "okay"; + }; +}; + +&i2c3 { + clock-frequency = <100000>; + status = "okay"; +}; + +&i2c5 { + clock-frequency = <100000>; + status = "okay"; +}; + +/* tmp100 on SVB */ +&i2c6 { + clock-frequency = <100000>; + status = "okay"; + tmp100@48 { + compatible = "tmp100"; + reg = <0x48>; + status = "okay"; + }; +}; + +&i2c7 { + clock-frequency = <100000>; + status = "okay"; +}; + +&i2c8 { + clock-frequency = <100000>; + status = "okay"; +}; + +&i2c9 { + clock-frequency = <100000>; + status = "okay"; +}; + +&i2c10 { + clock-frequency = <100000>; + status = "okay"; +}; + +&i2c11 { + clock-frequency = <100000>; + status = "okay"; +}; + +&i2c14 { + clock-frequency = <100000>; + status = "okay"; +}; + +&pwm_fan { + status = "okay"; + fan@0 { + reg = <0x00>; + fan-tach-ch = /bits/ 8 <0x00 0x01>; + cooling-levels = <127 255>; + }; + fan@1 { + reg = <0x01>; + fan-tach-ch = /bits/ 8 <0x02 0x03>; + cooling-levels = /bits/ 8 <127 255>; + }; + fan@2 { + reg = <0x02>; + fan-tach-ch = /bits/ 8 <0x04 0x05>; + cooling-levels = /bits/ 8 <127 255>; + }; + fan@3 { + reg = <0x03>; + fan-tach-ch = /bits/ 8 <0x06 0x07>; + cooling-levels = /bits/ 8 <127 255>; + }; + fan@4 { + reg = <0x04>; + fan-tach-ch = /bits/ 8 <0x08 0x09>; + cooling-levels = /bits/ 8 <127 255>; + }; + fan@5 { + reg = <0x05>; + fan-tach-ch = /bits/ 8 <0x0A 0x0B>; + cooling-levels = /bits/ 8 <127 255>; + }; + fan@6 { + reg = <0x06>; + fan-tach-ch = /bits/ 8 <0x0C 0x0D>; + cooling-levels = /bits/ 8 <127 255>; + }; + fan@7 { + reg = <0x07>; + fan-tach-ch = /bits/ 8 <0x0E 0x0F>; + cooling-levels = /bits/ 8 <127 255>; + }; +}; + +&spi0 { + cs-gpios = <&gpio6 11 GPIO_ACTIVE_LOW>; + status = "okay"; + Flash@0 { + compatible = "winbond,w25q128", + "jedec,spi-nor"; + reg = <0x0>; + #address-cells = <1>; + #size-cells = <1>; + spi-max-frequency = <5000000>; + partition@0 { + label = "spi0_spare1"; + reg = <0x0000000 0x800000>; + }; + partition@1 { + label = "spi0_spare2"; + reg = <0x800000 0x0>; + }; + }; +}; + +&spi1 { + cs-gpios = <&gpio0 20 GPIO_ACTIVE_LOW>; + status = "okay"; + Flash@0 { + compatible = "winbond,w25q128fw", + "jedec,spi-nor"; + reg = <0x0>; + #address-cells = <1>; + #size-cells = <1>; + spi-max-frequency = <5000000>; + partition@0 { + label = "spi1_spare1"; + reg = <0x0000000 0x800000>; + }; + partition@1 { + label = "spi1_spare2"; + reg = <0x800000 0x0>; + }; + }; +}; + +&pinctrl { + pinctrl-names = "default"; + pinctrl-0 = < &iox1_pins + &pin8_input + &pin9_output_high + &pin10_input + &pin11_output_high + &pin16_input + &pin24_output_high + &pin25_output_low + &pin32_output_high + &jtag2_pins + &pin61_output_high + &pin62_output_high + &pin63_output_high + &lpc_pins + &pin160_input + &pin162_input + &pin168_input + &pin169_input + &pin170_input + &pin187_output_high + &pin190_input + &pin191_output_high + &pin192_output_high + &pin197_output_low + &ddc_pins + &pin218_input + &pin219_output_low + &pin220_output_low + &pin221_output_high + &pin222_input + &pin223_output_low + &spix_pins + &pin228_output_low + &pin231_output_high + &pin255_input>; +}; + diff --git a/arch/arm/dts/nuvoton-npcm750-pincfg-evb.dtsi b/arch/arm/dts/nuvoton-npcm750-pincfg-evb.dtsi new file mode 100644 index 00000000000..3b3806274ad --- /dev/null +++ b/arch/arm/dts/nuvoton-npcm750-pincfg-evb.dtsi @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2018 Nuvoton Technology + +/ { + pinctrl: pinctrl@f0800000 { + pin8_input: pin8-input { + pins = "GPIO8/LKGPO1"; + bias-disable; + input-enable; + }; + pin9_output_high: pin9-output-high { + pins = "GPIO9/LKGPO2"; + bias-disable; + output-high; + }; + pin10_input: pin10-input { + pins = "GPIO10/IOXHLD"; + bias-disable; + input-enable; + }; + pin11_output_high: pin11-output-high { + pins = "GPIO11/IOXHCK"; + bias-disable; + output-high; + }; + pin16_input: pin16-input { + pins = "GPIO16/LKGPO0"; + bias-disable; + input-enable; + }; + pin24_output_high: pin24-output-high { + pins = "GPIO24/IOXHDO"; + bias-disable; + output-high; + }; + pin25_output_low: pin25-output-low { + pins = "GPIO25/IOXHDI"; + bias-disable; + output-low; + }; + pin32_output_high: pin32-output-high { + pins = "GPIO32/nSPI0CS1"; + bias-disable; + output-high; + }; + pin61_output_high: pin61-output-high { + pins = "GPO61/nDTR1_BOUT1/STRAP6"; + bias-disable; + output-high; + }; + pin62_output_high: pin62-output-high { + pins = "GPO62/nRTST1/STRAP5"; + bias-disable; + output-high; + }; + pin63_output_high: pin63-output-high { + pins = "GPO63/TXD1/STRAP4"; + bias-disable; + output-high; + }; + pin160_input: pin160-input { + pins = "GPIO160/CLKOUT/RNGOSCOUT"; + bias-disable; + input-enable; + }; + pin162_input: pin162-input { + pins = "GPIO162/SERIRQ"; + bias-disable; + input-enable; + }; + pin168_input: pin168-input { + pins = "GPIO168/nCLKRUN/nESPIALERT"; + bias-disable; + input-enable; + }; + pin169_input: pin169-input { + pins = "GPIO169/nSCIPME"; + bias-disable; + input-enable; + }; + pin170_input: pin170-input { + pins = "GPIO170/nSMI"; + bias-disable; + input-enable; + }; + pin187_output_high: pin187-output-high { + pins = "GPIO187/nSPI3CS1"; + bias-disable; + output-high; + }; + pin190_input: pin190-input { + pins = "GPIO190/nPRD_SMI"; + bias-disable; + input-enable; + }; + pin191_output_high: pin191-output-high { + pins = "GPIO191"; + bias-disable; + output-high; + }; + pin192_output_high: pin192-output-high { + pins = "GPIO192"; + bias-disable; + output-high; + }; + pin197_output_low: pin197-output-low { + pins = "GPIO197/SMB0DEN"; + bias-disable; + output-low; + }; + pin218_input: pin218-input { + pins = "GPIO218/nWDO1"; + bias-disable; + input-enable; + }; + pin219_output_low: pin219-output-low { + pins = "GPIO219/nWDO2"; + bias-disable; + output-low; + }; + pin220_output_low: pin220-output-low { + pins = "GPIO220/SMB12SCL"; + bias-disable; + output-low; + }; + pin221_output_high: pin221-output-high { + pins = "GPIO221/SMB12SDA"; + bias-disable; + output-high; + }; + pin222_input: pin222-input { + pins = "GPIO222/SMB13SCL"; + bias-disable; + input-enable; + }; + pin223_output_low: pin223-output-low { + pins = "GPIO223/SMB13SDA"; + bias-disable; + output-low; + }; + pin228_output_low: pin228-output-low { + pins = "GPIO228/nSPIXCS1"; + bias-disable; + output-low; + }; + pin231_output_high: pin231-output-high { + pins = "GPIO230/SPIXD3"; + bias-disable; + output-high; + }; + pin255_input: pin255-input { + pins = "GPI255/DACOSEL"; + bias-disable; + input-enable; + }; + }; +}; diff --git a/arch/arm/dts/nuvoton-npcm750.dtsi b/arch/arm/dts/nuvoton-npcm750.dtsi new file mode 100644 index 00000000000..13eee0fe564 --- /dev/null +++ b/arch/arm/dts/nuvoton-npcm750.dtsi @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2018 Nuvoton Technology tomer.maimon@nuvoton.com +// Copyright 2018 Google, Inc. + +#include "nuvoton-common-npcm7xx.dtsi" + +/ { + #address-cells = <1>; + #size-cells = <1>; + interrupt-parent = <&gic>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + enable-method = "nuvoton,npcm750-smp"; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a9"; + clocks = <&clk NPCM7XX_CLK_CPU>; + clock-names = "clk_cpu"; + reg = <0>; + next-level-cache = <&l2>; + }; + + cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a9"; + clocks = <&clk NPCM7XX_CLK_CPU>; + clock-names = "clk_cpu"; + reg = <1>; + next-level-cache = <&l2>; + }; + }; + + soc { + timer@3fe600 { + compatible = "arm,cortex-a9-twd-timer"; + reg = <0x3fe600 0x20>; + interrupts = ; + clocks = <&clk NPCM7XX_CLK_AHB>; + }; + }; + + ahb { + gmac1: eth@f0804000 { + device_type = "network"; + compatible = "snps,dwmac"; + reg = <0xf0804000 0x2000>; + interrupts = ; + interrupt-names = "macirq"; + ethernet = <1>; + clocks = <&clk_rg2refck>, <&clk NPCM7XX_CLK_AHB>; + clock-names = "stmmaceth", "clk_gmac"; + pinctrl-names = "default"; + pinctrl-0 = <&rg2_pins + &rg2mdio_pins>; + status = "disabled"; + }; + }; +}; diff --git a/arch/arm/include/asm/arch-npcm7xx/gcr.h b/arch/arm/include/asm/arch-npcm7xx/gcr.h new file mode 100644 index 00000000000..762a0b6d6b4 --- /dev/null +++ b/arch/arm/include/asm/arch-npcm7xx/gcr.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#ifndef __NPCM750_GCR_H_ +#define __NPCM750_GCR_H_ + +/* On-Chip POLEG NPCM750 VERSIONS */ +#define POLEG_Z1 0x00A92750 +#define POLEG_A1 0x04A92750 +#define POLEG_NPCM750 0x00000000 +#define POLEG_NPCM730 0x00300395 +#define POLEG_NPCM710 0x00200380 + +#define PWRON_SECEN 7 /* STRAP8 */ +#define NPCM_GCR_BA 0xF0800000 + +struct npcm_gcr { + unsigned int pdid; + unsigned int pwron; + unsigned char res1[0x4]; + unsigned int mfsel1; + unsigned int mfsel2; + unsigned int miscpe; + unsigned char res2[0x20]; + unsigned int spswc; + unsigned int intcr; + unsigned int intsr; + unsigned char res3[0xc]; + unsigned int hifcr; + unsigned int sd1irv1; + unsigned int sd1irv2; + unsigned char res4[0x4]; + unsigned int intcr2; + unsigned int mfsel3; + unsigned int srcnt; + unsigned int ressr; + unsigned int rlockr1; + unsigned int flockr1; + unsigned int dscnt; + unsigned int mdlr; + unsigned char res5[0x18]; + unsigned int davclvlr; + unsigned int intcr3; + unsigned char res6[0xc]; + unsigned int vsintr; + unsigned int mfsel4; + unsigned int sd2irv1; + unsigned int sd2irv2; + unsigned char res7[0x8]; + unsigned int cpbpntr; + unsigned char res8[0x8]; + unsigned int cpctl; + unsigned int cp2bst; + unsigned int b2cpnt; + unsigned int cppctl; + unsigned int i2csegsel; + unsigned int i2csegctl; + unsigned int vsrcr; + unsigned int mlockr; + unsigned char res9[0x4c]; + unsigned int scrpad; + unsigned int usb1phyctl; + unsigned int usb2phyctl; +}; + +#endif diff --git a/arch/arm/mach-npcm/Kconfig b/arch/arm/mach-npcm/Kconfig new file mode 100644 index 00000000000..cf5043d6b82 --- /dev/null +++ b/arch/arm/mach-npcm/Kconfig @@ -0,0 +1,26 @@ +if ARCH_NPCM + +config SYS_ARCH + default "arm" + +config SYS_TEXT_BASE + default 0x8000 + +choice + prompt "Nuvoton SoC select" + default ARCH_NPCM7xx + +config ARCH_NPCM7xx + bool "Support Nuvoton NPCM7xx SoC" + select CPU_V7A + select OF_CONTROL + select DM + help + General support for NPCM7xx BMC (Poleg). + Nuvoton NPCM7xx BMC is based on the Cortex A9. + +endchoice + +source "arch/arm/mach-npcm/npcm7xx/Kconfig" + +endif diff --git a/arch/arm/mach-npcm/Makefile b/arch/arm/mach-npcm/Makefile new file mode 100644 index 00000000000..8a1572b4f0e --- /dev/null +++ b/arch/arm/mach-npcm/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_ARCH_NPCM7xx) += npcm7xx/ diff --git a/arch/arm/mach-npcm/npcm7xx/Kconfig b/arch/arm/mach-npcm/npcm7xx/Kconfig new file mode 100644 index 00000000000..237e7ba7e50 --- /dev/null +++ b/arch/arm/mach-npcm/npcm7xx/Kconfig @@ -0,0 +1,22 @@ +if ARCH_NPCM7xx + +config SYS_CPU + default "armv7" + +config SYS_SOC + default "npcm7xx" + +config TARGET_POLEG + bool "NPCM POLEG board" + help + poleg EVB is Nuvoton evaluation board for NPCM750 SoC, + supports general functions of Basebase Management + Controller(BMC). + +config SYS_MEM_TOP_HIDE + hex "Reserved TOP memory" + default 0x03000000 + +source "board/nuvoton/poleg_evb/Kconfig" + +endif diff --git a/arch/arm/mach-npcm/npcm7xx/Makefile b/arch/arm/mach-npcm/npcm7xx/Makefile new file mode 100644 index 00000000000..49f9877bd67 --- /dev/null +++ b/arch/arm/mach-npcm/npcm7xx/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_TARGET_POLEG) += cpu.o l2_cache_pl310_init.o l2_cache_pl310.o diff --git a/arch/arm/mach-npcm/npcm7xx/cpu.c b/arch/arm/mach-npcm/npcm7xx/cpu.c new file mode 100644 index 00000000000..dd74bb9e087 --- /dev/null +++ b/arch/arm/mach-npcm/npcm7xx/cpu.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2021 Nuvoton Technology Corp. + */ + +#include +#include +#include +#include +#include + +int print_cpuinfo(void) +{ + struct npcm_gcr *gcr = (struct npcm_gcr *)NPCM_GCR_BA; + unsigned int id, mdlr; + + mdlr = readl(&gcr->mdlr); + + printf("CPU: "); + + switch (mdlr) { + case POLEG_NPCM750: + printf("NPCM750 "); + break; + case POLEG_NPCM730: + printf("NPCM730 "); + break; + case POLEG_NPCM710: + printf("NPCM710 "); + break; + default: + printf("NPCM7XX "); + break; + } + + id = readl(&gcr->pdid); + switch (id) { + case POLEG_Z1: + printf("Z1 is no supported! @ "); + break; + case POLEG_A1: + printf("A1 @ "); + break; + default: + printf("Unknown\n"); + break; + } + + return 0; +} + +void s_init(void) +{ + /* Invalidate L2 cache in lowlevel_init */ + v7_outer_cache_inval_all(); +} + +void enable_caches(void) +{ + dcache_enable(); +} + +void disable_caches(void) +{ + dcache_disable(); +} diff --git a/arch/arm/mach-npcm/npcm7xx/l2_cache_pl310.c b/arch/arm/mach-npcm/npcm7xx/l2_cache_pl310.c new file mode 100644 index 00000000000..cba2e342dc2 --- /dev/null +++ b/arch/arm/mach-npcm/npcm7xx/l2_cache_pl310.c @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2021 Nuvoton Technology Corp. + */ + +#include +#include +#include + +void l2_pl310_init(void); + +void set_pl310_ctrl(u32 enable) +{ + struct pl310_regs *const pl310 = (struct pl310_regs *)CONFIG_SYS_PL310_BASE; + + writel(enable, &pl310->pl310_ctrl); +} + +void v7_outer_cache_enable(void) +{ + l2_pl310_init(); + + set_pl310_ctrl(1); +} + +void v7_outer_cache_disable(void) +{ + set_pl310_ctrl(0); +} diff --git a/arch/arm/mach-npcm/npcm7xx/l2_cache_pl310_init.S b/arch/arm/mach-npcm/npcm7xx/l2_cache_pl310_init.S new file mode 100644 index 00000000000..8ec4e374a50 --- /dev/null +++ b/arch/arm/mach-npcm/npcm7xx/l2_cache_pl310_init.S @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2021 Nuvoton Technology Corp. + */ + +.align 5 + +#include + +#ifndef CONFIG_SYS_L2CACHE_OFF + +ENTRY(l2_pl310_init) + +@------------------------------------------------------------------ +@ L2CC (PL310) Initialization +@------------------------------------------------------------------ + @ In this example PL310 PA = VA. The memory was marked as Device memory + @ in previous stages when defining CORE0 private address space + LDR r0, =0xF03FC000 @ A9_BASE_ADDR + + @ Disable L2 Cache controller just in case it is already on + LDR r1, =0x0 + STR r1, [r0,#0x100] + + @ Set aux cntrl + @ Way size = 32KB + @ Way = 16 + LDR r1, =0x02050000 + ORR r1, r1, #(1 << 29) @ Instruction prefetch enable + ORR r1, r1, #(1 << 28) @ Data prefetch enable + ORR r1, r1, #(1 << 22) @ cache replacement policy + STR r1, [r0,#0x104] @ auxilary control reg at offset 0x104 + + @ Set tag RAM latency + @ 1 cycle RAM write access latency + @ 1 cycle RAM read access latency + @ 1 cycle RAM setup latency + LDR r1, =0x00000000 + STR r1, [r0,#0x108] @ tag ram control reg at offset 0x108 + + @ Set Data RAM latency + @ 1 cycle RAM write access latency + @ 2 cycles RAM read access latency + @ 1 cycle RAM setup latency + LDR r1, =0x00000000 + STR r1, [r0,#0x10C] @ data ram control reg at offset 0x108 + + @Cache maintenance - invalidate 16 ways (0xffff) - base offset 0x77C + LDR r1, =0xFFFF + STR r1, [r0,#0x77C] @ invalidate by way register at offset 0x77C +poll_invalidate: + LDR r1, [r0,#0x77C] @ invalidate by way register at offset 0x77C + TST r1, #1 + BNE poll_invalidate + + @ Ensure L2 remains disabled for the time being + LDR r1, =0x0 + STR r1, [r0,#0x100] + + MRC p15, 4, r0, c15, c0, 0 @ Read periph base address + @ SCU offset from base of private peripheral space = 0x000 + + LDR r1, [r0, #0x0] @ Read the SCU Control Register + ORR r1, r1, #0x1 @ Set bit 0 (The Enable bit) + STR r1, [r0, #0x0] @ Write back modifed value + + BX lr + +ENDPROC(l2_pl310_init) + +#endif diff --git a/board/nuvoton/poleg_evb/Kconfig b/board/nuvoton/poleg_evb/Kconfig new file mode 100644 index 00000000000..d3f4c1dd812 --- /dev/null +++ b/board/nuvoton/poleg_evb/Kconfig @@ -0,0 +1,25 @@ +if TARGET_POLEG + +config SYS_BOARD + default "poleg_evb" + +config SYS_VENDOR + default "nuvoton" + +config SYS_CONFIG_NAME + default "poleg" + +choice + prompt "Target board select" + default TARGET_POLEG_EVB + +config TARGET_POLEG_EVB + bool "Poleg EVB" + help + poleg EVB is Nuvoton evaluation board for NPCM750 SoC, + supports general functions of Basebase Management + Controller(BMC). + +endchoice + +endif diff --git a/board/nuvoton/poleg_evb/MAINTAINERS b/board/nuvoton/poleg_evb/MAINTAINERS new file mode 100644 index 00000000000..8797295c411 --- /dev/null +++ b/board/nuvoton/poleg_evb/MAINTAINERS @@ -0,0 +1,7 @@ +Poleg EVB +M: Stanley Chu +M: Jim Liu +S: Maintained +F: board/nuvoton/poleg_evb/ +F: include/configs/poleg.h +F: configs/poleg_evb_defconfig diff --git a/board/nuvoton/poleg_evb/Makefile b/board/nuvoton/poleg_evb/Makefile new file mode 100644 index 00000000000..377433d60ac --- /dev/null +++ b/board/nuvoton/poleg_evb/Makefile @@ -0,0 +1 @@ +obj-y := poleg_evb.o diff --git a/board/nuvoton/poleg_evb/poleg_evb.c b/board/nuvoton/poleg_evb/poleg_evb.c new file mode 100644 index 00000000000..aef142a881c --- /dev/null +++ b/board/nuvoton/poleg_evb/poleg_evb.c @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * + * Copyright (c) 2021 Nuvoton Technology Corp. + */ + +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +int board_init(void) +{ + return 0; +} + +int dram_init(void) +{ + struct npcm_gcr *gcr = (struct npcm_gcr *)NPCM_GCR_BA; + + int ramsize = (readl(&gcr->intcr3) >> 8) & 0x7; + + switch (ramsize) { + case 0: + gd->ram_size = 0x08000000; /* 128 MB. */ + break; + case 1: + gd->ram_size = 0x10000000; /* 256 MB. */ + break; + case 2: + gd->ram_size = 0x20000000; /* 512 MB. */ + break; + case 3: + gd->ram_size = 0x40000000; /* 1024 MB. */ + break; + case 4: + gd->ram_size = 0x80000000; /* 2048 MB. */ + break; + + default: + break; + } + + return 0; +} diff --git a/configs/poleg_evb_defconfig b/configs/poleg_evb_defconfig new file mode 100644 index 00000000000..f7bdefcf936 --- /dev/null +++ b/configs/poleg_evb_defconfig @@ -0,0 +1,40 @@ +CONFIG_ARM=y +CONFIG_ARCH_CPU_INIT=y +CONFIG_ARCH_NPCM=y +CONFIG_SYS_TEXT_BASE=0x8200 +CONFIG_SYS_MALLOC_LEN=0x240000 +CONFIG_SYS_MALLOC_F_LEN=0x1000 +CONFIG_NR_DRAM_BANKS=2 +CONFIG_ENV_SIZE=0x40000 +CONFIG_ENV_OFFSET=0x100000 +CONFIG_ENV_SECT_SIZE=0x4000 +CONFIG_DM_GPIO=y +CONFIG_DEFAULT_DEVICE_TREE="nuvoton-npcm750-evb" +CONFIG_ARCH_NPCM7xx=y +CONFIG_TARGET_POLEG=y +CONFIG_SYS_LOAD_ADDR=0x10000000 +CONFIG_ENV_ADDR=0x80100000 +CONFIG_USE_BOOTCOMMAND=y +CONFIG_BOOTCOMMAND="run common_bootargs; run romboot" +CONFIG_SYS_PROMPT="U-Boot>" +CONFIG_CMD_GPIO=y +CONFIG_CMD_SPI=y +CONFIG_CMD_CACHE=y +CONFIG_CMD_UUID=y +CONFIG_ENV_OVERWRITE=y +CONFIG_ENV_IS_IN_SPI_FLASH=y +CONFIG_CLK=y +CONFIG_DM_SPI_FLASH=y +CONFIG_SPI_FLASH_MACRONIX=y +CONFIG_SPI_FLASH_WINBOND=y +CONFIG_DM_ETH=y +CONFIG_PINCTRL=y +CONFIG_PINCONF=y +CONFIG_DM_SERIAL=y +CONFIG_NPCM_SERIAL=y +CONFIG_SPI=y +CONFIG_DM_SPI=y +CONFIG_SYSRESET=y +CONFIG_SYSRESET_WATCHDOG=y +CONFIG_TIMER=y +CONFIG_NPCM_TIMER=y diff --git a/include/configs/poleg.h b/include/configs/poleg.h new file mode 100644 index 00000000000..c21b063c059 --- /dev/null +++ b/include/configs/poleg.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2021 Nuvoton Technology Corp. + */ + +#ifndef __CONFIG_POLEG_H +#define __CONFIG_POLEG_H + +#ifndef CONFIG_SYS_L2CACHE_OFF +#define CONFIG_SYS_L2_PL310 1 +#define CONFIG_SYS_PL310_BASE 0xF03FC000 /* L2 - Cache Regs Base (4k Space)*/ +#endif + +#define CONFIG_SYS_MAXARGS 32 +#define CONFIG_SYS_CBSIZE 256 +#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16) +#define CONFIG_SYS_BOOTMAPSZ (0x30 << 20) +#define CONFIG_SYS_SDRAM_BASE 0x0 +#define CONFIG_SYS_INIT_SP_ADDR (0x00008000 - GENERATED_GBL_DATA_SIZE) + +/* Default environemnt variables */ +#define CONFIG_SERVERIP 192.168.0.1 +#define CONFIG_IPADDR 192.168.0.2 +#define CONFIG_NETMASK 255.255.255.0 +#define CONFIG_EXTRA_ENV_SETTINGS "uimage_flash_addr=80200000\0" \ + "stdin=serial\0" \ + "stdout=serial\0" \ + "stderr=serial\0" \ + "ethact=eth${eth_num}\0" \ + "romboot=echo Booting from flash; echo +++ uimage at 0x${uimage_flash_addr}; " \ + "echo Using bootargs: ${bootargs};bootm ${uimage_flash_addr}\0" \ + "autostart=yes\0" \ + "eth_num=0\0" \ + "ethaddr=00:00:F7:A0:00:FC\0" \ + "eth1addr=00:00:F7:A0:00:FD\0" \ + "eth2addr=00:00:F7:A0:00:FE\0" \ + "eth3addr=00:00:F7:A0:00:FF\0" \ + "common_bootargs=setenv bootargs earlycon=${earlycon} root=/dev/ram " \ + "console=${console} mem=${mem} ramdisk_size=48000 basemac=${ethaddr}\0" \ + "sd_prog=fatload mmc 0 10000000 image-bmc; cp.b 10000000 80000000 ${filesize}\0" \ + "sd_run=fatload mmc 0 10000000 image-bmc; bootm 10200000\0" \ + "\0" + +#endif diff --git a/include/dt-bindings/reset/nuvoton,npcm7xx-reset.h b/include/dt-bindings/reset/nuvoton,npcm7xx-reset.h new file mode 100644 index 00000000000..757f5e34c81 --- /dev/null +++ b/include/dt-bindings/reset/nuvoton,npcm7xx-reset.h @@ -0,0 +1,91 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (c) 2020 Nuvoton Technology corporation. + +#ifndef _DT_BINDINGS_NPCM7XX_RESET_H +#define _DT_BINDINGS_NPCM7XX_RESET_H + +#define NPCM7XX_RESET_IPSRST1 0x20 +#define NPCM7XX_RESET_IPSRST2 0x24 +#define NPCM7XX_RESET_IPSRST3 0x34 + +/* Reset lines on IP1 reset module (NPCM7XX_RESET_IPSRST1) */ +#define NPCM7XX_RESET_FIU3 1 +#define NPCM7XX_RESET_UDC1 5 +#define NPCM7XX_RESET_EMC1 6 +#define NPCM7XX_RESET_UART_2_3 7 +#define NPCM7XX_RESET_UDC2 8 +#define NPCM7XX_RESET_PECI 9 +#define NPCM7XX_RESET_AES 10 +#define NPCM7XX_RESET_UART_0_1 11 +#define NPCM7XX_RESET_MC 12 +#define NPCM7XX_RESET_SMB2 13 +#define NPCM7XX_RESET_SMB3 14 +#define NPCM7XX_RESET_SMB4 15 +#define NPCM7XX_RESET_SMB5 16 +#define NPCM7XX_RESET_PWM_M0 18 +#define NPCM7XX_RESET_TIMER_0_4 19 +#define NPCM7XX_RESET_TIMER_5_9 20 +#define NPCM7XX_RESET_EMC2 21 +#define NPCM7XX_RESET_UDC4 22 +#define NPCM7XX_RESET_UDC5 23 +#define NPCM7XX_RESET_UDC6 24 +#define NPCM7XX_RESET_UDC3 25 +#define NPCM7XX_RESET_ADC 27 +#define NPCM7XX_RESET_SMB6 28 +#define NPCM7XX_RESET_SMB7 29 +#define NPCM7XX_RESET_SMB0 30 +#define NPCM7XX_RESET_SMB1 31 + +/* Reset lines on IP2 reset module (NPCM7XX_RESET_IPSRST2) */ +#define NPCM7XX_RESET_MFT0 0 +#define NPCM7XX_RESET_MFT1 1 +#define NPCM7XX_RESET_MFT2 2 +#define NPCM7XX_RESET_MFT3 3 +#define NPCM7XX_RESET_MFT4 4 +#define NPCM7XX_RESET_MFT5 5 +#define NPCM7XX_RESET_MFT6 6 +#define NPCM7XX_RESET_MFT7 7 +#define NPCM7XX_RESET_MMC 8 +#define NPCM7XX_RESET_SDHC 9 +#define NPCM7XX_RESET_GFX_SYS 10 +#define NPCM7XX_RESET_AHB_PCIBRG 11 +#define NPCM7XX_RESET_VDMA 12 +#define NPCM7XX_RESET_ECE 13 +#define NPCM7XX_RESET_VCD 14 +#define NPCM7XX_RESET_OTP 16 +#define NPCM7XX_RESET_SIOX1 18 +#define NPCM7XX_RESET_SIOX2 19 +#define NPCM7XX_RESET_3DES 21 +#define NPCM7XX_RESET_PSPI1 22 +#define NPCM7XX_RESET_PSPI2 23 +#define NPCM7XX_RESET_GMAC2 25 +#define NPCM7XX_RESET_USB_HOST 26 +#define NPCM7XX_RESET_GMAC1 28 +#define NPCM7XX_RESET_CP 31 + +/* Reset lines on IP3 reset module (NPCM7XX_RESET_IPSRST3) */ +#define NPCM7XX_RESET_PWM_M1 0 +#define NPCM7XX_RESET_SMB12 1 +#define NPCM7XX_RESET_SPIX 2 +#define NPCM7XX_RESET_SMB13 3 +#define NPCM7XX_RESET_UDC0 4 +#define NPCM7XX_RESET_UDC7 5 +#define NPCM7XX_RESET_UDC8 6 +#define NPCM7XX_RESET_UDC9 7 +#define NPCM7XX_RESET_PCI_MAILBOX 9 +#define NPCM7XX_RESET_SMB14 12 +#define NPCM7XX_RESET_SHA 13 +#define NPCM7XX_RESET_SEC_ECC 14 +#define NPCM7XX_RESET_PCIE_RC 15 +#define NPCM7XX_RESET_TIMER_10_14 16 +#define NPCM7XX_RESET_RNG 17 +#define NPCM7XX_RESET_SMB15 18 +#define NPCM7XX_RESET_SMB8 19 +#define NPCM7XX_RESET_SMB9 20 +#define NPCM7XX_RESET_SMB10 21 +#define NPCM7XX_RESET_SMB11 22 +#define NPCM7XX_RESET_ESPI 23 +#define NPCM7XX_RESET_USB_PHY_1 24 +#define NPCM7XX_RESET_USB_PHY_2 25 + +#endif From c7554574ff1532983149ab6d7351896d1010b14e Mon Sep 17 00:00:00 2001 From: Jim Liu Date: Tue, 19 Apr 2022 13:32:20 +0800 Subject: [PATCH 02/13] clk: nuvoton: Add support for NPCM750 Add clock controller driver for NPCM750 Signed-off-by: Jim Liu Signed-off-by: Stanley Chu Reviewed-by: Sean Anderson --- drivers/clk/Makefile | 1 + drivers/clk/nuvoton/Makefile | 2 + drivers/clk/nuvoton/clk_npcm.c | 299 ++++++++++++++++++ drivers/clk/nuvoton/clk_npcm.h | 105 ++++++ drivers/clk/nuvoton/clk_npcm7xx.c | 95 ++++++ .../dt-bindings/clock/nuvoton,npcm7xx-clock.h | 46 +++ 6 files changed, 548 insertions(+) create mode 100644 drivers/clk/nuvoton/Makefile create mode 100644 drivers/clk/nuvoton/clk_npcm.c create mode 100644 drivers/clk/nuvoton/clk_npcm.h create mode 100644 drivers/clk/nuvoton/clk_npcm7xx.c create mode 100644 include/dt-bindings/clock/nuvoton,npcm7xx-clock.h diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index bb4eee5d99b..f5b553172c2 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_ARCH_ASPEED) += aspeed/ obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/ obj-$(CONFIG_ARCH_MESON) += meson/ obj-$(CONFIG_ARCH_MTMIPS) += mtmips/ +obj-$(CONFIG_ARCH_NPCM) += nuvoton/ obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ obj-$(CONFIG_ARCH_SOCFPGA) += altera/ obj-$(CONFIG_ARCH_SUNXI) += sunxi/ diff --git a/drivers/clk/nuvoton/Makefile b/drivers/clk/nuvoton/Makefile new file mode 100644 index 00000000000..c63d9c16f1a --- /dev/null +++ b/drivers/clk/nuvoton/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_ARCH_NPCM) += clk_npcm.o +obj-$(CONFIG_ARCH_NPCM7xx) += clk_npcm7xx.o diff --git a/drivers/clk/nuvoton/clk_npcm.c b/drivers/clk/nuvoton/clk_npcm.c new file mode 100644 index 00000000000..8d71f2a24b8 --- /dev/null +++ b/drivers/clk/nuvoton/clk_npcm.c @@ -0,0 +1,299 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2022 Nuvoton Technology Corp. + * + * Formula for calculating clock rate: + * Fout = ((Fin / PRE_DIV) / div) / POST_DIV + */ + +#include +#include +#include +#include +#include +#include "clk_npcm.h" + +static int clkid_to_clksel(struct npcm_clk_select *selector, int id) +{ + int i; + + for (i = 0; i < selector->num_parents; i++) { + if (selector->parents[i].id == id) + return selector->parents[i].clksel; + } + + return -EINVAL; +} + +static int clksel_to_clkid(struct npcm_clk_select *selector, int clksel) +{ + int i; + + for (i = 0; i < selector->num_parents; i++) { + if (selector->parents[i].clksel == clksel) + return selector->parents[i].id; + } + + return -EINVAL; +} + +static struct npcm_clk_pll *npcm_clk_pll_get(struct npcm_clk_data *clk_data, int id) +{ + struct npcm_clk_pll *pll = clk_data->clk_plls; + int i; + + for (i = 0; i < clk_data->num_plls; i++) { + if (pll->id == id) + return pll; + pll++; + } + + return NULL; +} + +static struct npcm_clk_select *npcm_clk_selector_get(struct npcm_clk_data *clk_data, + int id) +{ + struct npcm_clk_select *selector = clk_data->clk_selectors; + int i; + + for (i = 0; i < clk_data->num_selectors; i++) { + if (selector->id == id) + return selector; + selector++; + } + + return NULL; +} + +static struct npcm_clk_div *npcm_clk_divider_get(struct npcm_clk_data *clk_data, + int id) +{ + struct npcm_clk_div *divider = clk_data->clk_dividers; + int i; + + for (i = 0; i < clk_data->num_dividers; i++) { + if (divider->id == id) + return divider; + divider++; + } + + return NULL; +} + +static ulong npcm_clk_get_fin(struct clk *clk) +{ + struct npcm_clk_priv *priv = dev_get_priv(clk->dev); + struct npcm_clk_select *selector; + struct clk parent; + ulong parent_rate; + u32 val, clksel; + int ret; + + selector = npcm_clk_selector_get(priv->clk_data, clk->id); + if (!selector) + return 0; + + if (selector->flags & FIXED_PARENT) { + clksel = 0; + } else { + val = readl(priv->base + selector->reg); + clksel = (val & selector->mask) >> (ffs(selector->mask) - 1); + } + parent.id = clksel_to_clkid(selector, clksel); + + ret = clk_request(clk->dev, &parent); + if (ret) + return 0; + + parent_rate = clk_get_rate(&parent); + + debug("fin of clk%lu = %lu\n", clk->id, parent_rate); + return parent_rate; +} + +static u32 npcm_clk_get_div(struct clk *clk) +{ + struct npcm_clk_priv *priv = dev_get_priv(clk->dev); + struct npcm_clk_div *divider; + u32 val, div; + + divider = npcm_clk_divider_get(priv->clk_data, clk->id); + if (!divider) + return 0; + + val = readl(priv->base + divider->reg); + div = (val & divider->mask) >> (ffs(divider->mask) - 1); + if (divider->flags & DIV_TYPE1) + div = div + 1; + else + div = 1 << div; + + if (divider->flags & PRE_DIV2) + div = div << 1; + + return div; +} + +static u32 npcm_clk_set_div(struct clk *clk, u32 div) +{ + struct npcm_clk_priv *priv = dev_get_priv(clk->dev); + struct npcm_clk_div *divider; + u32 val, clkdiv; + + divider = npcm_clk_divider_get(priv->clk_data, clk->id); + if (!divider) + return -EINVAL; + + if (divider->flags & PRE_DIV2) + div = div >> 1; + + if (divider->flags & DIV_TYPE1) + clkdiv = div - 1; + else + clkdiv = ilog2(div); + + val = readl(priv->base + divider->reg); + val &= ~divider->mask; + val |= (clkdiv << (ffs(divider->mask) - 1)) & divider->mask; + writel(val, priv->base + divider->reg); + + return 0; +} + +static ulong npcm_clk_get_fout(struct clk *clk) +{ + ulong parent_rate; + u32 div; + + parent_rate = npcm_clk_get_fin(clk); + if (!parent_rate) + return -EINVAL; + + div = npcm_clk_get_div(clk); + if (!div) + return -EINVAL; + + debug("fout of clk%lu = (%lu / %u)\n", clk->id, parent_rate, div); + return (parent_rate / div); +} + +static ulong npcm_clk_get_pll_fout(struct clk *clk) +{ + struct npcm_clk_priv *priv = dev_get_priv(clk->dev); + struct npcm_clk_pll *pll; + struct clk parent; + ulong parent_rate; + ulong fbdv, indv, otdv1, otdv2; + u32 val; + u64 ret; + + pll = npcm_clk_pll_get(priv->clk_data, clk->id); + if (!pll) + return -ENODEV; + + parent.id = pll->parent_id; + ret = clk_request(clk->dev, &parent); + if (ret) + return ret; + + parent_rate = clk_get_rate(&parent); + + val = readl(priv->base + pll->reg); + indv = FIELD_GET(PLLCON_INDV, val); + fbdv = FIELD_GET(PLLCON_FBDV, val); + otdv1 = FIELD_GET(PLLCON_OTDV1, val); + otdv2 = FIELD_GET(PLLCON_OTDV2, val); + + ret = (u64)parent_rate * fbdv; + do_div(ret, indv * otdv1 * otdv2); + if (pll->flags & POST_DIV2) + do_div(ret, 2); + + debug("fout of pll(id %lu) = %llu\n", clk->id, ret); + return ret; +} + +static ulong npcm_clk_get_rate(struct clk *clk) +{ + struct npcm_clk_priv *priv = dev_get_priv(clk->dev); + struct npcm_clk_data *clk_data = priv->clk_data; + struct clk refclk; + int ret; + + debug("%s: id %lu\n", __func__, clk->id); + if (clk->id == clk_data->refclk_id) { + ret = clk_get_by_name(clk->dev, "refclk", &refclk); + if (!ret) + return clk_get_rate(&refclk); + else + return ret; + } + + if (clk->id >= clk_data->pll0_id && + clk->id < clk_data->pll0_id + clk_data->num_plls) + return npcm_clk_get_pll_fout(clk); + else + return npcm_clk_get_fout(clk); +} + +static ulong npcm_clk_set_rate(struct clk *clk, ulong rate) +{ + ulong parent_rate; + u32 div; + int ret; + + debug("%s: id %lu, rate %lu\n", __func__, clk->id, rate); + parent_rate = npcm_clk_get_fin(clk); + if (!parent_rate) + return -EINVAL; + + div = DIV_ROUND_UP(parent_rate, rate); + ret = npcm_clk_set_div(clk, div); + if (ret) + return ret; + + debug("%s: rate %lu, new rate (%lu / %u)\n", __func__, rate, parent_rate, div); + return (parent_rate / div); +} + +static int npcm_clk_set_parent(struct clk *clk, struct clk *parent) +{ + struct npcm_clk_priv *priv = dev_get_priv(clk->dev); + struct npcm_clk_select *selector; + int clksel; + u32 val; + + debug("%s: id %lu, parent %lu\n", __func__, clk->id, parent->id); + selector = npcm_clk_selector_get(priv->clk_data, clk->id); + if (!selector) + return -EINVAL; + + clksel = clkid_to_clksel(selector, parent->id); + if (clksel < 0) + return -EINVAL; + + val = readl(priv->base + selector->reg); + val &= ~selector->mask; + val |= clksel << (ffs(selector->mask) - 1); + writel(val, priv->base + selector->reg); + + return 0; +} + +static int npcm_clk_request(struct clk *clk) +{ + struct npcm_clk_priv *priv = dev_get_priv(clk->dev); + + if (clk->id >= priv->num_clks) + return -EINVAL; + + return 0; +} + +const struct clk_ops npcm_clk_ops = { + .get_rate = npcm_clk_get_rate, + .set_rate = npcm_clk_set_rate, + .set_parent = npcm_clk_set_parent, + .request = npcm_clk_request, +}; diff --git a/drivers/clk/nuvoton/clk_npcm.h b/drivers/clk/nuvoton/clk_npcm.h new file mode 100644 index 00000000000..06b60dc8b8d --- /dev/null +++ b/drivers/clk/nuvoton/clk_npcm.h @@ -0,0 +1,105 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#ifndef _CLK_NPCM_H_ +#define _CLK_NPCM_H_ + +#include + +/* Register offsets */ +#define CLKSEL 0x04 /* clock source selection */ +#define CLKDIV1 0x08 /* clock divider 1 */ +#define CLKDIV2 0x2C /* clock divider 2 */ +#define CLKDIV3 0x58 /* clock divider 3 */ +#define PLLCON0 0x0C /* pll0 control */ +#define PLLCON1 0x10 /* pll1 control */ +#define PLLCON2 0x54 /* pll2 control */ + +/* CLKSEL bit filed */ +#define NPCM7XX_CPUCKSEL GENMASK(1, 0) +#define NPCM8XX_CPUCKSEL GENMASK(2, 0) +#define SDCKSEL GENMASK(7, 6) +#define UARTCKSEL GENMASK(9, 8) +#define TIMCKSEL GENMASK(15, 14) + +/* CLKDIV1 bit filed */ +#define SPI3CKDIV GENMASK(10, 6) +#define MMCCKDIV GENMASK(15, 11) +#define UARTDIV1 GENMASK(20, 16) +#define TIMCKDIV GENMASK(25, 21) +#define CLK4DIV GENMASK(27, 26) + +/* CLKDIV2 bit filed */ +#define APB5CKDIV GENMASK(23, 22) +#define APB2CKDIV GENMASK(27, 26) + +/* CLKDIV3 bit filed */ +#define SPIXCKDIV GENMASK(5, 1) +#define SPI0CKDIV GENMASK(10, 6) +#define UARTDIV2 GENMASK(15, 11) +#define SPI1CKDIV GENMASK(23, 16) + +/* PLLCON bit filed */ +#define PLLCON_INDV GENMASK(5, 0) +#define PLLCON_OTDV1 GENMASK(10, 8) +#define PLLCON_OTDV2 GENMASK(15, 13) +#define PLLCON_FBDV GENMASK(27, 16) + +/* Flags */ +#define DIV_TYPE1 BIT(0) /* div = clkdiv + 1 */ +#define DIV_TYPE2 BIT(1) /* div = 1 << clkdiv */ +#define PRE_DIV2 BIT(2) /* Pre divisor = 2 */ +#define POST_DIV2 BIT(3) /* Post divisor = 2 */ +#define FIXED_PARENT BIT(4) /* clock source is fixed */ + +/* Parameters of PLL configuration */ +struct npcm_clk_pll { + const int id; + const int parent_id; + u32 reg; + u32 flags; +}; + +/* Parent clock id to clksel mapping */ +struct parent_data { + int id; + int clksel; +}; + +/* Parameters of parent selection */ +struct npcm_clk_select { + const int id; + const struct parent_data *parents; + u32 reg; + u32 mask; + u8 num_parents; + u32 flags; +}; + +/* Parameters of clock divider */ +struct npcm_clk_div { + const int id; + u32 reg; + u32 mask; + u32 flags; +}; + +struct npcm_clk_data { + struct npcm_clk_pll *clk_plls; + int num_plls; + struct npcm_clk_select *clk_selectors; + int num_selectors; + struct npcm_clk_div *clk_dividers; + int num_dividers; + int refclk_id; + int pll0_id; +}; + +struct npcm_clk_priv { + void __iomem *base; + struct npcm_clk_data *clk_data; + int num_clks; +}; + +extern const struct clk_ops npcm_clk_ops; + +#endif diff --git a/drivers/clk/nuvoton/clk_npcm7xx.c b/drivers/clk/nuvoton/clk_npcm7xx.c new file mode 100644 index 00000000000..a12aaa2f4cd --- /dev/null +++ b/drivers/clk/nuvoton/clk_npcm7xx.c @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2021 Nuvoton Technology Corp. + */ + +#include +#include +#include "clk_npcm.h" + +/* Parent clock map */ +static const struct parent_data pll_parents[] = { + {NPCM7XX_CLK_PLL0, 0}, + {NPCM7XX_CLK_PLL1, 1}, + {NPCM7XX_CLK_REFCLK, 2}, + {NPCM7XX_CLK_PLL2DIV2, 3} +}; + +static const struct parent_data cpuck_parents[] = { + {NPCM7XX_CLK_PLL0, 0}, + {NPCM7XX_CLK_PLL1, 1}, + {NPCM7XX_CLK_REFCLK, 2}, +}; + +static const struct parent_data apb_parent[] = {{NPCM7XX_CLK_AHB, 0}}; + +static struct npcm_clk_pll npcm7xx_clk_plls[] = { + {NPCM7XX_CLK_PLL0, NPCM7XX_CLK_REFCLK, PLLCON0, 0}, + {NPCM7XX_CLK_PLL1, NPCM7XX_CLK_REFCLK, PLLCON1, 0}, + {NPCM7XX_CLK_PLL2, NPCM7XX_CLK_REFCLK, PLLCON2, 0}, + {NPCM7XX_CLK_PLL2DIV2, NPCM7XX_CLK_REFCLK, PLLCON2, POST_DIV2} +}; + +static struct npcm_clk_select npcm7xx_clk_selectors[] = { + {NPCM7XX_CLK_AHB, cpuck_parents, CLKSEL, NPCM7XX_CPUCKSEL, 3, 0}, + {NPCM7XX_CLK_APB2, apb_parent, 0, 0, 1, FIXED_PARENT}, + {NPCM7XX_CLK_APB5, apb_parent, 0, 0, 1, FIXED_PARENT}, + {NPCM7XX_CLK_SPI0, apb_parent, 0, 0, 1, FIXED_PARENT}, + {NPCM7XX_CLK_SPI3, apb_parent, 0, 0, 1, FIXED_PARENT}, + {NPCM7XX_CLK_SPIX, apb_parent, 0, 0, 1, FIXED_PARENT}, + {NPCM7XX_CLK_UART, pll_parents, CLKSEL, UARTCKSEL, 4, 0}, + {NPCM7XX_CLK_TIMER, pll_parents, CLKSEL, TIMCKSEL, 4, 0}, + {NPCM7XX_CLK_SDHC, pll_parents, CLKSEL, SDCKSEL, 4, 0} +}; + +static struct npcm_clk_div npcm7xx_clk_dividers[] = { + {NPCM7XX_CLK_AHB, CLKDIV1, CLK4DIV, DIV_TYPE1 | PRE_DIV2}, + {NPCM7XX_CLK_APB2, CLKDIV2, APB2CKDIV, DIV_TYPE2}, + {NPCM7XX_CLK_APB5, CLKDIV2, APB5CKDIV, DIV_TYPE2}, + {NPCM7XX_CLK_SPI0, CLKDIV3, SPI0CKDIV, DIV_TYPE1}, + {NPCM7XX_CLK_SPI3, CLKDIV1, SPI3CKDIV, DIV_TYPE1}, + {NPCM7XX_CLK_SPIX, CLKDIV3, SPIXCKDIV, DIV_TYPE1}, + {NPCM7XX_CLK_UART, CLKDIV1, UARTDIV1, DIV_TYPE1}, + {NPCM7XX_CLK_TIMER, CLKDIV1, TIMCKDIV, DIV_TYPE2}, + {NPCM7XX_CLK_SDHC, CLKDIV1, MMCCKDIV, DIV_TYPE1} +}; + +static struct npcm_clk_data npcm7xx_clk_data = { + .clk_plls = npcm7xx_clk_plls, + .num_plls = ARRAY_SIZE(npcm7xx_clk_plls), + .clk_selectors = npcm7xx_clk_selectors, + .num_selectors = ARRAY_SIZE(npcm7xx_clk_selectors), + .clk_dividers = npcm7xx_clk_dividers, + .num_dividers = ARRAY_SIZE(npcm7xx_clk_dividers), + .refclk_id = NPCM7XX_CLK_REFCLK, + .pll0_id = NPCM7XX_CLK_PLL0, +}; + +static int npcm7xx_clk_probe(struct udevice *dev) +{ + struct npcm_clk_priv *priv = dev_get_priv(dev); + + priv->base = dev_read_addr_ptr(dev); + if (!priv->base) + return -EINVAL; + + priv->clk_data = &npcm7xx_clk_data; + priv->num_clks = NPCM7XX_NUM_CLOCKS; + + return 0; +} + +static const struct udevice_id npcm7xx_clk_ids[] = { + { .compatible = "nuvoton,npcm750-clk" }, + { } +}; + +U_BOOT_DRIVER(clk_npcm) = { + .name = "clk_npcm", + .id = UCLASS_CLK, + .of_match = npcm7xx_clk_ids, + .ops = &npcm_clk_ops, + .priv_auto = sizeof(struct npcm_clk_priv), + .probe = npcm7xx_clk_probe, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/include/dt-bindings/clock/nuvoton,npcm7xx-clock.h b/include/dt-bindings/clock/nuvoton,npcm7xx-clock.h new file mode 100644 index 00000000000..65e6bc4eeea --- /dev/null +++ b/include/dt-bindings/clock/nuvoton,npcm7xx-clock.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Nuvoton NPCM7xx Clock Generator binding + * clock binding number for all clocks supportted by nuvoton,npcm7xx-clk + * + * Copyright (C) 2018 Nuvoton Technologies tali.perry@nuvoton.com + * + */ + +#ifndef __DT_BINDINGS_CLOCK_NPCM7XX_H +#define __DT_BINDINGS_CLOCK_NPCM7XX_H + +#define NPCM7XX_CLK_CPU 0 +#define NPCM7XX_CLK_GFX_PIXEL 1 +#define NPCM7XX_CLK_MC 2 +#define NPCM7XX_CLK_ADC 3 +#define NPCM7XX_CLK_AHB 4 +#define NPCM7XX_CLK_TIMER 5 +#define NPCM7XX_CLK_UART 6 +#define NPCM7XX_CLK_MMC 7 +#define NPCM7XX_CLK_SPI3 8 +#define NPCM7XX_CLK_PCI 9 +#define NPCM7XX_CLK_AXI 10 +#define NPCM7XX_CLK_APB4 11 +#define NPCM7XX_CLK_APB3 12 +#define NPCM7XX_CLK_APB2 13 +#define NPCM7XX_CLK_APB1 14 +#define NPCM7XX_CLK_APB5 15 +#define NPCM7XX_CLK_CLKOUT 16 +#define NPCM7XX_CLK_GFX 17 +#define NPCM7XX_CLK_SU 18 +#define NPCM7XX_CLK_SU48 19 +#define NPCM7XX_CLK_SDHC 20 +#define NPCM7XX_CLK_SPI0 21 +#define NPCM7XX_CLK_SPIX 22 +#define NPCM7XX_CLK_REFCLK 23 +#define NPCM7XX_CLK_SYSBYPCK 24 +#define NPCM7XX_CLK_MCBYPCK 25 +#define NPCM7XX_CLK_PLL0 26 +#define NPCM7XX_CLK_PLL1 27 +#define NPCM7XX_CLK_PLL2 28 +#define NPCM7XX_CLK_PLL2DIV2 29 +#define NPCM7XX_NUM_CLOCKS (NPCM7XX_CLK_PLL2DIV2 + 1) + +#endif + From 6f6a0b74d65091b302553b16350c32438acddfb7 Mon Sep 17 00:00:00 2001 From: Jim Liu Date: Tue, 19 Apr 2022 13:32:21 +0800 Subject: [PATCH 03/13] serial: npcm: Add support for Nuvoton NPCM SoCs Add Nuvoton BMC NPCM7xx/NPCM8xx uart driver Signed-off-by: Jim Liu Signed-off-by: Stanley Chu --- drivers/serial/Kconfig | 9 ++ drivers/serial/Makefile | 1 + drivers/serial/serial_npcm.c | 157 +++++++++++++++++++++++++++++++++++ 3 files changed, 167 insertions(+) create mode 100644 drivers/serial/serial_npcm.c diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 5dcf5c019da..26fa498bbbb 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -1016,6 +1016,15 @@ config MPC8XX_CONS depends on MPC8xx default y +config NPCM_SERIAL + bool "Nuvoton NPCM UART driver" + depends on DM_SERIAL + help + Select this to enable UART support for Nuvoton BMCs + (NPCM7xx and NPCM8xx). + The driver enables the onboard serial port with 8-N-1 + configuration. + config XEN_SERIAL bool "XEN serial support" depends on XEN diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index d8e26d72ea2..51de06a78c5 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -66,6 +66,7 @@ obj-$(CONFIG_MSM_GENI_SERIAL) += serial_msm_geni.o obj-$(CONFIG_MVEBU_A3700_UART) += serial_mvebu_a3700.o obj-$(CONFIG_MPC8XX_CONS) += serial_mpc8xx.o obj-$(CONFIG_NULLDEV_SERIAL) += serial_nulldev.o +obj-$(CONFIG_NPCM_SERIAL) += serial_npcm.o obj-$(CONFIG_OCTEON_SERIAL_BOOTCMD) += serial_octeon_bootcmd.o obj-$(CONFIG_OCTEON_SERIAL_PCIE_CONSOLE) += serial_octeon_pcie_console.o obj-$(CONFIG_OWL_SERIAL) += serial_owl.o diff --git a/drivers/serial/serial_npcm.c b/drivers/serial/serial_npcm.c new file mode 100644 index 00000000000..76ac7cb80db --- /dev/null +++ b/drivers/serial/serial_npcm.c @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2021 Nuvoton Technology Corp. + */ + +#include +#include +#include +#include + +struct npcm_uart { + union { + u32 rbr; /* Receive Buffer Register */ + u32 thr; /* Transmit Holding Register */ + u32 dll; /* Divisor Latch (Low Byte) Register */ + }; + union { + u32 ier; /* Interrupt Enable Register */ + u32 dlm; /* Divisor Latch (Low Byte) Register */ + }; + union { + u32 iir; /* Interrupt Identification Register */ + u32 fcr; /* FIFO Control Register */ + }; + u32 lcr; /* Line Control Register */ + u32 mcr; /* Modem Control Register */ + u32 lsr; /* Line Status Control Register */ + u32 msr; /* Modem Status Register */ + u32 tor; /* Timeout Register */ +}; + +#define LCR_WLS_8BITS 3 /* 8-bit word length select */ +#define FCR_TFR BIT(2) /* TxFIFO reset */ +#define FCR_RFR BIT(1) /* RxFIFO reset */ +#define FCR_FME BIT(0) /* FIFO mode enable */ +#define LSR_THRE BIT(5) /* Status of TxFIFO empty */ +#define LSR_RFDR BIT(0) /* Status of RxFIFO data ready */ +#define LCR_DLAB BIT(7) /* Divisor latch access bit */ + +struct npcm_serial_plat { + struct npcm_uart *reg; + u32 uart_clk; /* frequency of uart clock source */ +}; + +static int npcm_serial_pending(struct udevice *dev, bool input) +{ + struct npcm_serial_plat *plat = dev_get_plat(dev); + struct npcm_uart *uart = plat->reg; + + if (input) + return readb(&uart->lsr) & LSR_RFDR ? 1 : 0; + else + return readb(&uart->lsr) & LSR_THRE ? 0 : 1; +} + +static int npcm_serial_putc(struct udevice *dev, const char ch) +{ + struct npcm_serial_plat *plat = dev_get_plat(dev); + struct npcm_uart *uart = plat->reg; + + if (!(readb(&uart->lsr) & LSR_THRE)) + return -EAGAIN; + + writeb(ch, &uart->thr); + + return 0; +} + +static int npcm_serial_getc(struct udevice *dev) +{ + struct npcm_serial_plat *plat = dev_get_plat(dev); + struct npcm_uart *uart = plat->reg; + + if (!(readb(&uart->lsr) & LSR_RFDR)) + return -EAGAIN; + + return readb(&uart->rbr); +} + +static int npcm_serial_setbrg(struct udevice *dev, int baudrate) +{ + struct npcm_serial_plat *plat = dev_get_plat(dev); + struct npcm_uart *uart = plat->reg; + u16 divisor; + + /* BaudOut = UART Clock / (16 * [Divisor + 2]) */ + divisor = DIV_ROUND_CLOSEST(plat->uart_clk, 16 * baudrate + 2) - 2; + + setbits_8(&uart->lcr, LCR_DLAB); + writeb(divisor & 0xff, &uart->dll); + writeb(divisor >> 8, &uart->dlm); + clrbits_8(&uart->lcr, LCR_DLAB); + + return 0; +} + +static int npcm_serial_probe(struct udevice *dev) +{ + struct npcm_serial_plat *plat = dev_get_plat(dev); + struct npcm_uart *uart = plat->reg; + struct clk clk, parent; + u32 freq; + int ret; + + plat->reg = dev_read_addr_ptr(dev); + freq = dev_read_u32_default(dev, "clock-frequency", 0); + + ret = clk_get_by_index(dev, 0, &clk); + if (ret < 0) + return ret; + + ret = clk_get_by_index(dev, 1, &parent); + if (!ret) { + ret = clk_set_parent(&clk, &parent); + if (ret) + return ret; + } + + ret = clk_set_rate(&clk, freq); + if (ret < 0) + return ret; + plat->uart_clk = ret; + + /* Disable all interrupt */ + writeb(0, &uart->ier); + + /* Set 8 bit, 1 stop, no parity */ + writeb(LCR_WLS_8BITS, &uart->lcr); + + /* Reset RX/TX FIFO */ + writeb(FCR_FME | FCR_RFR | FCR_TFR, &uart->fcr); + + return 0; +} + +static const struct dm_serial_ops npcm_serial_ops = { + .getc = npcm_serial_getc, + .setbrg = npcm_serial_setbrg, + .putc = npcm_serial_putc, + .pending = npcm_serial_pending, +}; + +static const struct udevice_id npcm_serial_ids[] = { + { .compatible = "nuvoton,npcm750-uart" }, + { .compatible = "nuvoton,npcm845-uart" }, + { } +}; + +U_BOOT_DRIVER(serial_npcm) = { + .name = "serial_npcm", + .id = UCLASS_SERIAL, + .of_match = npcm_serial_ids, + .plat_auto = sizeof(struct npcm_serial_plat), + .probe = npcm_serial_probe, + .ops = &npcm_serial_ops, + .flags = DM_FLAG_PRE_RELOC, +}; From b789e4f215614e3aee2f78925683dc722ca617fc Mon Sep 17 00:00:00 2001 From: Jim Liu Date: Tue, 19 Apr 2022 13:32:22 +0800 Subject: [PATCH 04/13] timer: npcm: Add NPCM timer support Add Nuvoton BMC NPCM7xx/NPCM8xx timer driver. Signed-off-by: Jim Liu Signed-off-by: Stanley Chu --- drivers/timer/Kconfig | 9 +++ drivers/timer/Makefile | 1 + drivers/timer/npcm-timer.c | 115 +++++++++++++++++++++++++++++++++++++ 3 files changed, 125 insertions(+) create mode 100644 drivers/timer/npcm-timer.c diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig index 2eda3bcca5b..7b8ab56ed32 100644 --- a/drivers/timer/Kconfig +++ b/drivers/timer/Kconfig @@ -172,6 +172,15 @@ config NOMADIK_MTU_TIMER The MTU provides 4 decrementing free-running timers. At the moment, only the first timer is used by the driver. +config NPCM_TIMER + bool "Nuvoton NPCM timer support" + depends on TIMER + help + Select this to enable a timer on Nuvoton NPCM SoCs. + NPCM timer module has 5 down-counting timers, only the first timer + is used to implement timer ops. No support for early timer and + boot timer. + config OMAP_TIMER bool "Omap timer support" depends on TIMER diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile index 35cc490db1e..b2f002d5978 100644 --- a/drivers/timer/Makefile +++ b/drivers/timer/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_CADENCE_TTC_TIMER) += cadence-ttc.o obj-$(CONFIG_DESIGNWARE_APB_TIMER) += dw-apb-timer.o obj-$(CONFIG_MPC83XX_TIMER) += mpc83xx_timer.o obj-$(CONFIG_NOMADIK_MTU_TIMER) += nomadik-mtu-timer.o +obj-$(CONFIG_NPCM_TIMER) += npcm-timer.o obj-$(CONFIG_OMAP_TIMER) += omap-timer.o obj-$(CONFIG_RENESAS_OSTM_TIMER) += ostm_timer.o obj-$(CONFIG_RISCV_TIMER) += riscv_timer.o diff --git a/drivers/timer/npcm-timer.c b/drivers/timer/npcm-timer.c new file mode 100644 index 00000000000..4562a6f2311 --- /dev/null +++ b/drivers/timer/npcm-timer.c @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2022 Nuvoton Technology Corp. + */ + +#include +#include +#include +#include +#include + +#define NPCM_TIMER_CLOCK_RATE 1000000UL /* 1MHz timer */ +#define NPCM_TIMER_INPUT_RATE 25000000UL /* Rate of input clock */ +#define NPCM_TIMER_TDR_MASK GENMASK(23, 0) +#define NPCM_TIMER_MAX_VAL NPCM_TIMER_TDR_MASK /* max counter value */ + +/* Register offsets */ +#define TCR0 0x0 /* Timer Control and Status Register */ +#define TICR0 0x8 /* Timer Initial Count Register */ +#define TDR0 0x10 /* Timer Data Register */ + +/* TCR fields */ +#define TCR_MODE_PERIODIC BIT(27) +#define TCR_EN BIT(30) +#define TCR_PRESCALE (NPCM_TIMER_INPUT_RATE / NPCM_TIMER_CLOCK_RATE - 1) + +enum input_clock_type { + INPUT_CLOCK_FIXED, /* input clock rate is fixed */ + INPUT_CLOCK_NON_FIXED +}; + +/** + * struct npcm_timer_priv - private data for npcm timer driver + * npcm timer is a 24-bits down-counting timer. + * + * @last_count: last hw counter value + * @counter: the value to be returned for get_count ops + */ +struct npcm_timer_priv { + void __iomem *base; + u32 last_count; + u64 counter; +}; + +static u64 npcm_timer_get_count(struct udevice *dev) +{ + struct npcm_timer_priv *priv = dev_get_priv(dev); + u32 val; + + /* The timer is counting down */ + val = readl(priv->base + TDR0) & NPCM_TIMER_TDR_MASK; + if (val <= priv->last_count) + priv->counter += priv->last_count - val; + else + priv->counter += priv->last_count + (NPCM_TIMER_MAX_VAL + 1 - val); + priv->last_count = val; + + return priv->counter; +} + +static int npcm_timer_probe(struct udevice *dev) +{ + struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev); + struct npcm_timer_priv *priv = dev_get_priv(dev); + enum input_clock_type type = dev_get_driver_data(dev); + struct clk clk; + int ret; + + priv->base = dev_read_addr_ptr(dev); + if (!priv->base) + return -EINVAL; + uc_priv->clock_rate = NPCM_TIMER_CLOCK_RATE; + + if (type == INPUT_CLOCK_NON_FIXED) { + ret = clk_get_by_index(dev, 0, &clk); + if (ret < 0) + return ret; + + ret = clk_set_rate(&clk, NPCM_TIMER_INPUT_RATE); + if (ret < 0) + return ret; + } + + /* + * Configure timer and start + * periodic mode + * timer clock rate = input clock / prescale + */ + writel(0, priv->base + TCR0); + writel(NPCM_TIMER_MAX_VAL, priv->base + TICR0); + writel(TCR_EN | TCR_MODE_PERIODIC | TCR_PRESCALE, + priv->base + TCR0); + + return 0; +} + +static const struct timer_ops npcm_timer_ops = { + .get_count = npcm_timer_get_count, +}; + +static const struct udevice_id npcm_timer_ids[] = { + { .compatible = "nuvoton,npcm845-timer", .data = INPUT_CLOCK_FIXED}, + { .compatible = "nuvoton,npcm750-timer", .data = INPUT_CLOCK_NON_FIXED}, + {} +}; + +U_BOOT_DRIVER(npcm_timer) = { + .name = "npcm_timer", + .id = UCLASS_TIMER, + .of_match = npcm_timer_ids, + .priv_auto = sizeof(struct npcm_timer_priv), + .probe = npcm_timer_probe, + .ops = &npcm_timer_ops, + .flags = DM_FLAG_PRE_RELOC, +}; From 3166e6fd45ed1aba9029839b482006a839daea2f Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Thu, 28 Apr 2022 12:39:49 -0400 Subject: [PATCH 05/13] ls10xxx: Use a sane SPL_SYS_MALLOC_F_LEN default SPL_SYS_MALLOC_F_LEN defaults to SYS_MALLOC_F_LEN. 0x10000 is 64 KiB, or around half of the total OCRAM size. Revert to the default of 0x2000. This fixes SPL boot. Fixes: 545eceb520 ("imx8/ls10xx: Use a sane SYS_MALLOC_F_LEN default") Signed-off-by: Sean Anderson Reviewed-by: Fabio Estevam --- Kconfig | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Kconfig b/Kconfig index 8bbb988790b..797038b0371 100644 --- a/Kconfig +++ b/Kconfig @@ -257,9 +257,7 @@ config SYS_MALLOC_F_LEN default 0x4000 if SANDBOX || RISCV || ARCH_APPLE || ROCKCHIP_RK3368 || \ ROCKCHIP_RK3399 default 0x8000 if RCAR_GEN3 - default 0x10000 if ARCH_IMX8 || (ARCH_IMX8M && !IMX8MQ) || \ - ARCH_LS1012A || ARCH_LS1021A || ARCH_LS1043A || \ - ARCH_LS1046A + default 0x10000 if ARCH_IMX8 || (ARCH_IMX8M && !IMX8MQ) default 0x2000 help Before relocation, memory is very limited on many platforms. Still, From 55a8bb94f98249f9ac8bbf5850d3db1d564dd197 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Thu, 28 Apr 2022 18:13:04 +0900 Subject: [PATCH 06/13] board: synquacer: developerbox: Remove Masami from MAINTAINERS Remove Masami Hiramatsu from MAINTAINERS since he will leave Linaro and his email will be not available anymore. Signed-off-by: Masami Hiramatsu --- board/socionext/developerbox/MAINTAINERS | 1 - 1 file changed, 1 deletion(-) diff --git a/board/socionext/developerbox/MAINTAINERS b/board/socionext/developerbox/MAINTAINERS index aa672b6e052..c6d4f2749d6 100644 --- a/board/socionext/developerbox/MAINTAINERS +++ b/board/socionext/developerbox/MAINTAINERS @@ -1,5 +1,4 @@ DEVELOPER BOX -M: Masami Hiramatsu M: Jassi Brar S: Maintained F: arch/arm/dts/synquacer-* From ee93f6129d0851b8667efaa5dc91ee201cce24b8 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 27 Apr 2022 13:47:56 -0600 Subject: [PATCH 07/13] test/py: Add a way to start sandbox without a device tree This is useful sometimes when running a specific test. Add support for it in the existing restart_uboot_with_flags() function. Signed-off-by: Simon Glass --- test/py/u_boot_console_sandbox.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/test/py/u_boot_console_sandbox.py b/test/py/u_boot_console_sandbox.py index cef416d738f..27c6db8d719 100644 --- a/test/py/u_boot_console_sandbox.py +++ b/test/py/u_boot_console_sandbox.py @@ -27,6 +27,7 @@ class ConsoleSandbox(ConsoleBase): super(ConsoleSandbox, self).__init__(log, config, max_fifo_fill=1024) self.sandbox_flags = [] + self.use_dtb = True def get_spawn(self): """Connect to a fresh U-Boot instance. @@ -53,16 +54,13 @@ class ConsoleSandbox(ConsoleBase): cmd = [] if self.config.gdbserver: cmd += ['gdbserver', self.config.gdbserver] - cmd += [ - self.config.build_dir + fname, - '-v', - '-d', - self.config.dtb - ] + cmd += [self.config.build_dir + fname, '-v'] + if self.use_dtb: + cmd += ['-d', self.config.dtb] cmd += self.sandbox_flags return Spawn(cmd, cwd=self.config.source_dir) - def restart_uboot_with_flags(self, flags, expect_reset=False): + def restart_uboot_with_flags(self, flags, expect_reset=False, use_dtb=True): """Run U-Boot with the given command-line flags Args: @@ -70,6 +68,7 @@ class ConsoleSandbox(ConsoleBase): expect_reset: Boolean indication whether this boot is expected to be reset while the 1st boot process after main boot before prompt. False by default. + use_dtb: True to use a device tree file, False to run without one Returns: A u_boot_spawn.Spawn object that is attached to U-Boot. @@ -77,9 +76,11 @@ class ConsoleSandbox(ConsoleBase): try: self.sandbox_flags = flags + self.use_dtb = use_dtb return self.restart_uboot(expect_reset) finally: self.sandbox_flags = [] + self.use_dtb = True def kill(self, sig): """Send a specific Unix signal to the sandbox process. From ccf24a9d7739241c08e17b45d7fbe74b9baa3dcc Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 27 Apr 2022 13:47:57 -0600 Subject: [PATCH 08/13] sandbox: Avoid binman error when run without device tree With sandbox, U-Boot can be run without a device tree (i.e. no -d or -T parameter). In this case an empty device tree is created for convenience. With a recent change this causes an error due to the missing '/binman' node. Add this node to avoid the problem, as well as a test that U-Boot can be run without a device tree. Fixes: 059df5624b ("arch: Kconfig: imply BINMAN for SANDBOX") Fixes: https://source.denx.de/u-boot/u-boot/-/issues/11 Signed-off-by: Simon Glass --- arch/sandbox/cpu/cpu.c | 27 ++++++++++++++++++++++++++- test/py/tests/test_help.py | 12 ++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/arch/sandbox/cpu/cpu.c b/arch/sandbox/cpu/cpu.c index ff0fa8a6853..7a82798c36d 100644 --- a/arch/sandbox/cpu/cpu.c +++ b/arch/sandbox/cpu/cpu.c @@ -291,6 +291,31 @@ void invalidate_dcache_range(unsigned long start, unsigned long stop) { } +/** + * setup_auto_tree() - Set up a basic device tree to allow sandbox to work + * + * This is used when no device tree is provided. It creates a simple tree with + * just a /binman node. + * + * @blob: Place to put the created device tree + * Returns: 0 on success, -ve FDT error code on failure + */ +static int setup_auto_tree(void *blob) +{ + int err; + + err = fdt_create_empty_tree(blob, 256); + if (err) + return err; + + /* Create a /binman node in case CONFIG_BINMAN is enabled */ + err = fdt_add_subnode(blob, 0, "binman"); + if (err < 0) + return err; + + return 0; +} + void *board_fdt_blob_setup(int *ret) { struct sandbox_state *state = state_get_current(); @@ -303,7 +328,7 @@ void *board_fdt_blob_setup(int *ret) blob = map_sysmem(CONFIG_SYS_FDT_LOAD_ADDR, 0); *ret = 0; if (!state->fdt_fname) { - err = fdt_create_empty_tree(blob, 256); + err = setup_auto_tree(blob); if (!err) goto done; printf("Unable to create empty FDT: %s\n", fdt_strerror(err)); diff --git a/test/py/tests/test_help.py b/test/py/tests/test_help.py index bac0a29f5a2..153133cf28f 100644 --- a/test/py/tests/test_help.py +++ b/test/py/tests/test_help.py @@ -9,6 +9,18 @@ def test_help(u_boot_console): u_boot_console.run_command('help') +@pytest.mark.boardspec('sandbox') +def test_help_no_devicetree(u_boot_console): + try: + cons = u_boot_console + cons.restart_uboot_with_flags([], use_dtb=False) + cons.run_command('help') + output = cons.get_spawn_output().replace('\r', '') + assert 'print command description/usage' in output + finally: + # Restart afterward to get the normal device tree back + u_boot_console.restart_uboot() + @pytest.mark.boardspec('sandbox_vpl') def test_vpl_help(u_boot_console): try: From dafe0fbfb0f37e2d3be3e25a60975e1eb31ef8b7 Mon Sep 17 00:00:00 2001 From: Sam Shih Date: Thu, 21 Apr 2022 14:23:51 +0800 Subject: [PATCH 09/13] pinctrl: mediatek: rewrite mtk_pinconf_set and related functions There are many pins in a SoCs, and different pin may belong to different "io_type", For example: some pins of MT7622 belongs to "io_type A", the other belongs to "io_type B", and pinctrl "V0" means handle pinconf via "io_type A" or "io_type B", so SoCs that contain "io_type A" and "io_type B" pins, use "V0" in pinctrl driver. This patch separates the implementation of register operations (e.g: "bias-pull-up/down", "driving" and "input-enable") into different functions, and lets the original V0/V1 ops to call the new functions. Signed-off-by: Sam Shih --- drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 128 +++++++++++++----- drivers/pinctrl/mediatek/pinctrl-mtk-common.h | 18 +++ 2 files changed, 115 insertions(+), 31 deletions(-) diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c index a9cedda164c..4ae328699e2 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c @@ -308,13 +308,31 @@ static const struct pinconf_param mtk_conf_params[] = { { "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 0 }, }; - -int mtk_pinconf_bias_set_v0(struct udevice *dev, u32 pin, u32 arg, u32 val) +int mtk_pinconf_bias_set_v0(struct udevice *dev, u32 pin, bool disable, + bool pullup, u32 val) { - int err, disable, pullup; + return mtk_pinconf_bias_set_pu_pd(dev, pin, disable, pullup, val); +} - disable = (arg == PIN_CONFIG_BIAS_DISABLE); - pullup = (arg == PIN_CONFIG_BIAS_PULL_UP); +int mtk_pinconf_bias_set_v1(struct udevice *dev, u32 pin, bool disable, + bool pullup, u32 val) +{ + int err; + + /* try pupd_r1_r0 if pullen_pullsel return error */ + err = mtk_pinconf_bias_set_pullen_pullsel(dev, pin, disable, pullup, + val); + if (err) + return mtk_pinconf_bias_set_pupd_r1_r0(dev, pin, disable, + pullup, val); + + return err; +} + +int mtk_pinconf_bias_set_pu_pd(struct udevice *dev, u32 pin, bool disable, + bool pullup, u32 val) +{ + int err; if (disable) { err = mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_PU, 0); @@ -323,7 +341,6 @@ int mtk_pinconf_bias_set_v0(struct udevice *dev, u32 pin, u32 arg, u32 val) err = mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_PD, 0); if (err) return err; - } else { err = mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_PU, pullup); if (err) @@ -336,14 +353,10 @@ int mtk_pinconf_bias_set_v0(struct udevice *dev, u32 pin, u32 arg, u32 val) return 0; } -int mtk_pinconf_bias_set_v1(struct udevice *dev, u32 pin, u32 arg, u32 val) +int mtk_pinconf_bias_set_pullen_pullsel(struct udevice *dev, u32 pin, + bool disable, bool pullup, u32 val) { - int err, disable, pullup, r0, r1; - - disable = (arg == PIN_CONFIG_BIAS_DISABLE); - pullup = (arg == PIN_CONFIG_BIAS_PULL_UP); - r0 = !!(val & 1); - r1 = !!(val & 2); + int err; if (disable) { err = mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_PULLEN, 0); @@ -359,16 +372,53 @@ int mtk_pinconf_bias_set_v1(struct udevice *dev, u32 pin, u32 arg, u32 val) return err; } - /* Also set PUPD/R0/R1 if the pin has them */ - err = mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_PUPD, !pullup); - if (err != -EINVAL) { - mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_R0, r0); - mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_R1, r1); + return 0; +} + +int mtk_pinconf_bias_set_pupd_r1_r0(struct udevice *dev, u32 pin, bool disable, + bool pullup, u32 val) +{ + int err, r0, r1; + + r0 = !!(val & 1); + r1 = !!(val & 2); + + if (disable) { + pullup = 0; + r0 = 0; + r1 = 0; } + /* MTK HW PUPD bit: 1 for pull-down, 0 for pull-up */ + err = mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_PUPD, !pullup); + if (err) + return err; + + /* Also set PUPD/R0/R1 if the pin has them */ + mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_R0, r0); + mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_R1, r1); + return 0; } +int mtk_pinconf_bias_set(struct udevice *dev, u32 pin, u32 arg, u32 val) +{ + int err; + struct mtk_pinctrl_priv *priv = dev_get_priv(dev); + int rev = priv->soc->rev; + bool disable, pullup; + + disable = (arg == PIN_CONFIG_BIAS_DISABLE); + pullup = (arg == PIN_CONFIG_BIAS_PULL_UP); + + if (rev == MTK_PINCTRL_V0) + err = mtk_pinconf_bias_set_v0(dev, pin, disable, pullup, val); + else + err = mtk_pinconf_bias_set_v1(dev, pin, disable, pullup, val); + + return err; +} + int mtk_pinconf_input_enable_v1(struct udevice *dev, u32 pin, u32 arg) { int err; @@ -379,6 +429,18 @@ int mtk_pinconf_input_enable_v1(struct udevice *dev, u32 pin, u32 arg) err = mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_DIR, 0); if (err) return err; + + return 0; +} + +int mtk_pinconf_input_enable(struct udevice *dev, u32 pin, u32 arg) +{ + struct mtk_pinctrl_priv *priv = dev_get_priv(dev); + int rev = priv->soc->rev; + + if (rev == MTK_PINCTRL_V1) + return mtk_pinconf_input_enable_v1(dev, pin, arg); + return 0; } @@ -410,7 +472,6 @@ int mtk_pinconf_drive_set_v0(struct udevice *dev, u32 pin, u32 arg) return 0; } - int mtk_pinconf_drive_set_v1(struct udevice *dev, u32 pin, u32 arg) { struct mtk_pinctrl_priv *priv = dev_get_priv(dev); @@ -429,21 +490,30 @@ int mtk_pinconf_drive_set_v1(struct udevice *dev, u32 pin, u32 arg) return 0; } +int mtk_pinconf_drive_set(struct udevice *dev, u32 pin, u32 arg) +{ + int err; + struct mtk_pinctrl_priv *priv = dev_get_priv(dev); + int rev = priv->soc->rev; + + if (rev == MTK_PINCTRL_V0) + err = mtk_pinconf_drive_set_v0(dev, pin, arg); + else + err = mtk_pinconf_drive_set_v1(dev, pin, arg); + + return err; +} + static int mtk_pinconf_set(struct udevice *dev, unsigned int pin, unsigned int param, unsigned int arg) { int err = 0; - struct mtk_pinctrl_priv *priv = dev_get_priv(dev); - int rev = priv->soc->rev; switch (param) { case PIN_CONFIG_BIAS_DISABLE: case PIN_CONFIG_BIAS_PULL_UP: case PIN_CONFIG_BIAS_PULL_DOWN: - if (rev == MTK_PINCTRL_V0) - err = mtk_pinconf_bias_set_v0(dev, pin, param, arg); - else - err = mtk_pinconf_bias_set_v1(dev, pin, param, arg); + err = mtk_pinconf_bias_set(dev, pin, param, arg); if (err) goto err; break; @@ -456,8 +526,7 @@ static int mtk_pinconf_set(struct udevice *dev, unsigned int pin, goto err; break; case PIN_CONFIG_INPUT_ENABLE: - if (rev == MTK_PINCTRL_V1) - err = mtk_pinconf_input_enable_v1(dev, pin, param); + err = mtk_pinconf_input_enable(dev, pin, param); if (err) goto err; break; @@ -486,10 +555,7 @@ static int mtk_pinconf_set(struct udevice *dev, unsigned int pin, goto err; break; case PIN_CONFIG_DRIVE_STRENGTH: - if (rev == MTK_PINCTRL_V0) - err = mtk_pinconf_drive_set_v0(dev, pin, arg); - else - err = mtk_pinconf_drive_set_v1(dev, pin, arg); + err = mtk_pinconf_drive_set(dev, pin, arg); if (err) goto err; break; diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.h b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h index 5e51a9a90c1..735fb6fef8b 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.h +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h @@ -192,4 +192,22 @@ void mtk_rmw(struct udevice *dev, u32 reg, u32 mask, u32 set); int mtk_pinctrl_common_probe(struct udevice *dev, struct mtk_pinctrl_soc *soc); +#if CONFIG_IS_ENABLED(PINCONF) + +int mtk_pinconf_bias_set_pu_pd(struct udevice *dev, u32 pin, bool disable, + bool pullup, u32 val); +int mtk_pinconf_bias_set_pullen_pullsel(struct udevice *dev, u32 pin, + bool disable, bool pullup, u32 val); +int mtk_pinconf_bias_set_pupd_r1_r0(struct udevice *dev, u32 pin, bool disable, + bool pullup, u32 val); +int mtk_pinconf_bias_set_v0(struct udevice *dev, u32 pin, bool disable, + bool pullup, u32 val); +int mtk_pinconf_bias_set_v1(struct udevice *dev, u32 pin, bool disable, + bool pullup, u32 val); +int mtk_pinconf_input_enable_v1(struct udevice *dev, u32 pin, u32 arg); +int mtk_pinconf_drive_set_v0(struct udevice *dev, u32 pin, u32 arg); +int mtk_pinconf_drive_set_v1(struct udevice *dev, u32 pin, u32 arg); + +#endif + #endif /* __PINCTRL_MEDIATEK_H__ */ From 10334e0bc8884301466bbca9c474a8a580a3e7ee Mon Sep 17 00:00:00 2001 From: Sam Shih Date: Thu, 21 Apr 2022 14:23:52 +0800 Subject: [PATCH 10/13] pinctrl: mediatek: introduce multiple memory bases support Pinctrl design of some mediatek SoC need to access registers that distribute in multiple memory base address. this patch introduce new mechanism in mediatek pinctrl driver to support the chips which have the new design. This patch add a member 'base_calc' in pinctrl private data, and changed original 'base' private data to an array of *iomem. When 'base_calc' attribute is set, it will requests multiplue regs base from the DT, if 'base_calc' attribute is not set, it only use legacy way to request single reg resource from the DT. Signed-off-by: Sam Shih --- drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 55 +++++++++++++------ drivers/pinctrl/mediatek/pinctrl-mtk-common.h | 22 +++++++- 2 files changed, 57 insertions(+), 20 deletions(-) diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c index 4ae328699e2..ebab43e50ab 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c @@ -45,18 +45,18 @@ static const struct mtk_drive_desc mtk_drive[] = { static const char *mtk_pinctrl_dummy_name = "_dummy"; -static void mtk_w32(struct udevice *dev, u32 reg, u32 val) +static void mtk_w32(struct udevice *dev, u8 i, u32 reg, u32 val) { struct mtk_pinctrl_priv *priv = dev_get_priv(dev); - __raw_writel(val, priv->base + reg); + __raw_writel(val, priv->base[i] + reg); } -static u32 mtk_r32(struct udevice *dev, u32 reg) +static u32 mtk_r32(struct udevice *dev, u8 i, u32 reg) { struct mtk_pinctrl_priv *priv = dev_get_priv(dev); - return __raw_readl(priv->base + reg); + return __raw_readl(priv->base[i] + reg); } static inline int get_count_order(unsigned int count) @@ -70,21 +70,28 @@ static inline int get_count_order(unsigned int count) } void mtk_rmw(struct udevice *dev, u32 reg, u32 mask, u32 set) +{ + return mtk_i_rmw(dev, 0, reg, mask, set); +} + +void mtk_i_rmw(struct udevice *dev, u8 i, u32 reg, u32 mask, u32 set) { u32 val; - val = mtk_r32(dev, reg); + val = mtk_r32(dev, i, reg); val &= ~mask; val |= set; - mtk_w32(dev, reg, val); + mtk_w32(dev, i, reg, val); } static int mtk_hw_pin_field_lookup(struct udevice *dev, int pin, const struct mtk_pin_reg_calc *rc, struct mtk_pin_field *pfd) { + struct mtk_pinctrl_priv *priv = dev_get_priv(dev); const struct mtk_pin_field_calc *c, *e; u32 bits; + u32 base_calc = priv->soc->base_calc; c = rc->range; e = c + rc->nranges; @@ -111,6 +118,11 @@ static int mtk_hw_pin_field_lookup(struct udevice *dev, int pin, pfd->bitpos = bits % c->sz_reg; pfd->mask = (1 << c->x_bits) - 1; + if (base_calc) + pfd->index = c->i_base; + else + pfd->index = 0; + /* pfd->next is used for indicating that bit wrapping-around happens * which requires the manipulation for bit 0 starting in the next * register to form the complete field read/write. @@ -150,10 +162,10 @@ static void mtk_hw_write_cross_field(struct udevice *dev, mtk_hw_bits_part(pf, &nbits_h, &nbits_l); - mtk_rmw(dev, pf->offset, pf->mask << pf->bitpos, + mtk_i_rmw(dev, pf->index, pf->offset, pf->mask << pf->bitpos, (value & pf->mask) << pf->bitpos); - mtk_rmw(dev, pf->offset + pf->next, BIT(nbits_h) - 1, + mtk_i_rmw(dev, pf->index, pf->offset + pf->next, BIT(nbits_h) - 1, (value & pf->mask) >> nbits_l); } @@ -164,8 +176,8 @@ static void mtk_hw_read_cross_field(struct udevice *dev, mtk_hw_bits_part(pf, &nbits_h, &nbits_l); - l = (mtk_r32(dev, pf->offset) >> pf->bitpos) & (BIT(nbits_l) - 1); - h = (mtk_r32(dev, pf->offset + pf->next)) & (BIT(nbits_h) - 1); + l = (mtk_r32(dev, pf->index, pf->offset) >> pf->bitpos) & (BIT(nbits_l) - 1); + h = (mtk_r32(dev, pf->index, pf->offset + pf->next)) & (BIT(nbits_h) - 1); *value = (h << nbits_l) | l; } @@ -181,7 +193,7 @@ static int mtk_hw_set_value(struct udevice *dev, int pin, int field, return err; if (!pf.next) - mtk_rmw(dev, pf.offset, pf.mask << pf.bitpos, + mtk_i_rmw(dev, pf.index, pf.offset, pf.mask << pf.bitpos, (value & pf.mask) << pf.bitpos); else mtk_hw_write_cross_field(dev, &pf, value); @@ -200,7 +212,7 @@ static int mtk_hw_get_value(struct udevice *dev, int pin, int field, return err; if (!pf.next) - *value = (mtk_r32(dev, pf.offset) >> pf.bitpos) & pf.mask; + *value = (mtk_r32(dev, pf.index, pf.offset) >> pf.bitpos) & pf.mask; else mtk_hw_read_cross_field(dev, &pf, value); @@ -236,7 +248,6 @@ static int mtk_get_pin_muxing(struct udevice *dev, unsigned int selector, char *buf, int size) { int val, err; - err = mtk_hw_get_value(dev, selector, PINCTRL_PIN_REG_MODE, &val); if (err) return err; @@ -722,13 +733,23 @@ int mtk_pinctrl_common_probe(struct udevice *dev, { struct mtk_pinctrl_priv *priv = dev_get_priv(dev); int ret = 0; - - priv->base = dev_read_addr_ptr(dev); - if (!priv->base) - return -EINVAL; + u32 i = 0; + fdt_addr_t addr; + u32 base_calc = soc->base_calc; + u32 nbase_names = soc->nbase_names; priv->soc = soc; + if (!base_calc) + nbase_names = 1; + + for (i = 0; i < nbase_names; i++) { + addr = devfdt_get_addr_index(dev, i); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + priv->base[i] = (void __iomem *)addr; + } + #if CONFIG_IS_ENABLED(DM_GPIO) || \ (defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_GPIO)) ret = mtk_gpiochip_register(dev); diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.h b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h index 735fb6fef8b..91a8c0581fa 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.h +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h @@ -8,6 +8,8 @@ #define MTK_PINCTRL_V0 0x0 #define MTK_PINCTRL_V1 0x1 +#define BASE_CALC_NONE 0 +#define MAX_BASE_CALC 10 #define MTK_RANGE(_a) { .range = (_a), .nranges = ARRAY_SIZE(_a), } #define MTK_PIN(_number, _name, _drv_n) { \ @@ -24,10 +26,11 @@ id##_funcs, \ } -#define PIN_FIELD_CALC(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit, \ - _x_bits, _sz_reg, _fixed) { \ +#define PIN_FIELD_BASE_CALC(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, \ + _s_bit, _x_bits, _sz_reg, _fixed) { \ .s_pin = _s_pin, \ .e_pin = _e_pin, \ + .i_base = _i_base, \ .s_addr = _s_addr, \ .x_addrs = _x_addrs, \ .s_bit = _s_bit, \ @@ -36,6 +39,11 @@ .fixed = _fixed, \ } +#define PIN_FIELD_CALC(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit, \ + _x_bits, _sz_reg, _fixed) \ + PIN_FIELD_BASE_CALC(_s_pin, _e_pin, BASE_CALC_NONE, _s_addr, \ + _x_addrs, _s_bit, _x_bits, _sz_reg, _fixed) + /* List these attributes which could be modified for the pin */ enum { PINCTRL_PIN_REG_MODE, @@ -70,6 +78,7 @@ enum { /** * struct mtk_pin_field - the structure that holds the information of the field * used to describe the attribute for the pin + * @index: the index pointing to the entry in base address list * @offset: the register offset relative to the base address * @mask: the mask used to filter out the field from the register * @bitpos: the start bit relative to the register @@ -77,6 +86,7 @@ enum { next register */ struct mtk_pin_field { + u8 index; u32 offset; u32 mask; u8 bitpos; @@ -88,6 +98,7 @@ struct mtk_pin_field { * the guide used to look up the relevant field * @s_pin: the start pin within the range * @e_pin: the end pin within the range + * @i_base: the index pointing to the entry in base address list * @s_addr: the start address for the range * @x_addrs: the address distance between two consecutive registers * within the range @@ -101,6 +112,7 @@ struct mtk_pin_field { struct mtk_pin_field_calc { u16 s_pin; u16 e_pin; + u8 i_base; u32 s_addr; u8 x_addrs; u8 s_bit; @@ -171,7 +183,10 @@ struct mtk_pinctrl_soc { const struct mtk_function_desc *funcs; int nfuncs; int gpio_mode; + const char * const *base_names; + unsigned int nbase_names; int rev; + int base_calc; }; /** @@ -181,7 +196,7 @@ struct mtk_pinctrl_soc { * @soc: SoC specific data */ struct mtk_pinctrl_priv { - void __iomem *base; + void __iomem *base[MAX_BASE_CALC]; struct mtk_pinctrl_soc *soc; }; @@ -189,6 +204,7 @@ extern const struct pinctrl_ops mtk_pinctrl_ops; /* A common read-modify-write helper for MediaTek chips */ void mtk_rmw(struct udevice *dev, u32 reg, u32 mask, u32 set); +void mtk_i_rmw(struct udevice *dev, u8 i, u32 reg, u32 mask, u32 set); int mtk_pinctrl_common_probe(struct udevice *dev, struct mtk_pinctrl_soc *soc); From 1a80ef5520fc0751c5055d422810bf22c6c7e526 Mon Sep 17 00:00:00 2001 From: Sam Shih Date: Thu, 21 Apr 2022 14:23:53 +0800 Subject: [PATCH 11/13] pinctrl: mediatek: add support for different types of IO pins There are many pins in an SoC, and register usage may vary by pins. This patch introduces a concept of "io type" and "io type group" to mediatek pinctrl drivers. This can provide different pinconf handlers implementation (eg: "bias-pull-up/down", "driving" and "input-enable") for IO pins that belong to different types. Signed-off-by: Sam Shih --- drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 48 +++++++++++++++++-- drivers/pinctrl/mediatek/pinctrl-mtk-common.h | 38 ++++++++++++++- 2 files changed, 81 insertions(+), 5 deletions(-) diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c index ebab43e50ab..47e2d67426f 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c @@ -219,6 +219,25 @@ static int mtk_hw_get_value(struct udevice *dev, int pin, int field, return 0; } +#if CONFIG_IS_ENABLED(PINCONF) +static int mtk_get_pin_io_type(struct udevice *dev, int pin, + struct mtk_io_type_desc *io_type) +{ + struct mtk_pinctrl_priv *priv = dev_get_priv(dev); + u8 io_n = priv->soc->pins[pin].io_n; + + if (io_n >= priv->soc->ntype) + return -EINVAL; + + io_type->name = priv->soc->io_type[io_n].name; + io_type->bias_set = priv->soc->io_type[io_n].bias_set; + io_type->drive_set = priv->soc->io_type[io_n].drive_set; + io_type->input_enable = priv->soc->io_type[io_n].input_enable; + + return 0; +} +#endif + static int mtk_get_groups_count(struct udevice *dev) { struct mtk_pinctrl_priv *priv = dev_get_priv(dev); @@ -416,16 +435,25 @@ int mtk_pinconf_bias_set(struct udevice *dev, u32 pin, u32 arg, u32 val) { int err; struct mtk_pinctrl_priv *priv = dev_get_priv(dev); + struct mtk_io_type_desc io_type; int rev = priv->soc->rev; bool disable, pullup; disable = (arg == PIN_CONFIG_BIAS_DISABLE); pullup = (arg == PIN_CONFIG_BIAS_PULL_UP); - if (rev == MTK_PINCTRL_V0) + if (!mtk_get_pin_io_type(dev, pin, &io_type)) { + if (io_type.bias_set) + err = io_type.bias_set(dev, pin, disable, pullup, + val); + else + err = -EINVAL; + + } else if (rev == MTK_PINCTRL_V0) { err = mtk_pinconf_bias_set_v0(dev, pin, disable, pullup, val); - else + } else { err = mtk_pinconf_bias_set_v1(dev, pin, disable, pullup, val); + } return err; } @@ -447,8 +475,13 @@ int mtk_pinconf_input_enable_v1(struct udevice *dev, u32 pin, u32 arg) int mtk_pinconf_input_enable(struct udevice *dev, u32 pin, u32 arg) { struct mtk_pinctrl_priv *priv = dev_get_priv(dev); + struct mtk_io_type_desc io_type; + int rev = priv->soc->rev; + if (!mtk_get_pin_io_type(dev, pin, &io_type)) + if (io_type.input_enable) + return io_type.input_enable(dev, pin, arg); if (rev == MTK_PINCTRL_V1) return mtk_pinconf_input_enable_v1(dev, pin, arg); @@ -505,12 +538,19 @@ int mtk_pinconf_drive_set(struct udevice *dev, u32 pin, u32 arg) { int err; struct mtk_pinctrl_priv *priv = dev_get_priv(dev); + struct mtk_io_type_desc io_type; int rev = priv->soc->rev; - if (rev == MTK_PINCTRL_V0) + if (!mtk_get_pin_io_type(dev, pin, &io_type)) { + if (io_type.drive_set) + err = io_type.drive_set(dev, pin, arg); + else + err = -EINVAL; + } else if (rev == MTK_PINCTRL_V0) { err = mtk_pinconf_drive_set_v0(dev, pin, arg); - else + } else { err = mtk_pinconf_drive_set_v1(dev, pin, arg); + } return err; } diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.h b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h index 91a8c0581fa..0d9596fa72c 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.h +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h @@ -12,10 +12,15 @@ #define MAX_BASE_CALC 10 #define MTK_RANGE(_a) { .range = (_a), .nranges = ARRAY_SIZE(_a), } -#define MTK_PIN(_number, _name, _drv_n) { \ + +#define MTK_PIN(_number, _name, _drv_n) \ + MTK_TYPED_PIN(_number, _name, _drv_n, IO_TYPE_DEFAULT) + +#define MTK_TYPED_PIN(_number, _name, _drv_n, _io_n) { \ .number = _number, \ .name = _name, \ .drv_n = _drv_n, \ + .io_n = _io_n, \ } #define PINCTRL_PIN_GROUP(name, id) \ @@ -75,6 +80,18 @@ enum { DRV_GRP4, }; +/* Group the pins by the io type */ +enum { + IO_TYPE_DEFAULT, + IO_TYPE_GRP0, + IO_TYPE_GRP1, + IO_TYPE_GRP2, + IO_TYPE_GRP3, + IO_TYPE_GRP4, + IO_TYPE_GRP5, + IO_TYPE_GRP6, +}; + /** * struct mtk_pin_field - the structure that holds the information of the field * used to describe the attribute for the pin @@ -139,11 +156,13 @@ struct mtk_pin_reg_calc { * @number: unique pin number from the global pin number space * @name: name for this pin * @drv_n: the index with the driving group + * @io_n: the index with the io type */ struct mtk_pin_desc { unsigned int number; const char *name; u8 drv_n; + u8 io_n; }; /** @@ -172,6 +191,21 @@ struct mtk_function_desc { int num_group_names; }; +/** + * struct mtk_io_type_desc - io class descriptor for specific pins + * @name: name of the io class + */ +struct mtk_io_type_desc { + const char *name; +#if CONFIG_IS_ENABLED(PINCONF) + /* Specific pinconfig operations */ + int (*bias_set)(struct udevice *dev, u32 pin, bool disable, + bool pullup, u32 val); + int (*drive_set)(struct udevice *dev, u32 pin, u32 arg); + int (*input_enable)(struct udevice *dev, u32 pin, u32 arg); +#endif +}; + /* struct mtk_pin_soc - the structure that holds SoC-specific data */ struct mtk_pinctrl_soc { const char *name; @@ -182,6 +216,8 @@ struct mtk_pinctrl_soc { int ngrps; const struct mtk_function_desc *funcs; int nfuncs; + const struct mtk_io_type_desc *io_type; + u8 ntype; int gpio_mode; const char * const *base_names; unsigned int nbase_names; From 56717a1388025b1f6dbc6072b679ee6e8390c32c Mon Sep 17 00:00:00 2001 From: Aswath Govindraju Date: Tue, 19 Apr 2022 20:56:02 +0530 Subject: [PATCH 12/13] include: configs: am**x/j721e/j721s2_evm.h: Move the stack pointer init address in arm64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, in case of arm64 bootloader and U-Boot the stack pointer is initialized at an offset of NON_SECURE_MSRAM_SIZE from arm64 SPL's text base address. After jumping to arm64, execution is done out of DDR. Therefore, having an offset corresponding to the size of MSRAM does not have any significance. Instead, initialize the stack pointer after an offset of 4MB from the SPL text base address. This helps in allocating larger memory for stack. ┌────────────────────┐0x80080000 │ │ │ arm64 SPL │ ├────────────────────┤ │ ▲ │ │ │ │ │ STACK │ ├────────────────────┤0x80480000 │ Memory for Load │ │ Buffer Allocation │ ├────────────────────┤0x80800000 │ │ │ U-Boot Image │ │ │ └────────────────────┘ Signed-off-by: Aswath Govindraju --- include/configs/am64x_evm.h | 3 +-- include/configs/am65x_evm.h | 3 +-- include/configs/j721e_evm.h | 3 +-- include/configs/j721s2_evm.h | 3 +-- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/include/configs/am64x_evm.h b/include/configs/am64x_evm.h index 135cb3c2ee2..d84a8db97ed 100644 --- a/include/configs/am64x_evm.h +++ b/include/configs/am64x_evm.h @@ -24,8 +24,7 @@ #define CONFIG_SPL_MAX_SIZE CONFIG_SYS_K3_MAX_DOWNLODABLE_IMAGE_SIZE #if defined(CONFIG_TARGET_AM642_A53_EVM) -#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SPL_TEXT_BASE + \ - CONFIG_SYS_K3_NON_SECURE_MSRAM_SIZE - 4) +#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SPL_TEXT_BASE + SZ_4M) #else /* * Maximum size in memory allocated to the SPL BSS. Keep it as tight as diff --git a/include/configs/am65x_evm.h b/include/configs/am65x_evm.h index 55fa6419e33..b1f9050f3f5 100644 --- a/include/configs/am65x_evm.h +++ b/include/configs/am65x_evm.h @@ -19,8 +19,7 @@ /* SPL Loader Configuration */ #ifdef CONFIG_TARGET_AM654_A53_EVM -#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SPL_TEXT_BASE + \ - CONFIG_SYS_K3_NON_SECURE_MSRAM_SIZE) +#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SPL_TEXT_BASE + SZ_4M) #else /* * Maximum size in memory allocated to the SPL BSS. Keep it as tight as diff --git a/include/configs/j721e_evm.h b/include/configs/j721e_evm.h index df3c16540ba..2590ee6b014 100644 --- a/include/configs/j721e_evm.h +++ b/include/configs/j721e_evm.h @@ -20,8 +20,7 @@ /* SPL Loader Configuration */ #if defined(CONFIG_TARGET_J721E_A72_EVM) || defined(CONFIG_TARGET_J7200_A72_EVM) -#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SPL_TEXT_BASE + \ - CONFIG_SYS_K3_NON_SECURE_MSRAM_SIZE) +#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SPL_TEXT_BASE + SZ_4M) #define CONFIG_SYS_UBOOT_BASE 0x50280000 /* Image load address in RAM for DFU boot*/ #else diff --git a/include/configs/j721s2_evm.h b/include/configs/j721s2_evm.h index f0d56b8778e..a5505f079b4 100644 --- a/include/configs/j721s2_evm.h +++ b/include/configs/j721s2_evm.h @@ -21,8 +21,7 @@ /* SPL Loader Configuration */ #if defined(CONFIG_TARGET_J721S2_A72_EVM) || defined(CONFIG_TARGET_J7200_A72_EVM) -#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SPL_TEXT_BASE + \ - CONFIG_SYS_K3_NON_SECURE_MSRAM_SIZE) +#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SPL_TEXT_BASE + SZ_4M) #define CONFIG_SYS_UBOOT_BASE 0x50280000 /* Image load address in RAM for DFU boot*/ #else From 344e86c61ec2f88b2740b33ed65ccc34ed708baa Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Fri, 25 Feb 2022 10:14:50 +0800 Subject: [PATCH 13/13] gpio: npcm: Add support for Nuvoton NPCM SoCs Add Nuvoton BMC NPCM7xx/NPCM8xx gpio driver Signed-off-by: Stanley Chu --- drivers/gpio/Kconfig | 7 +++ drivers/gpio/Makefile | 1 + drivers/gpio/npcm_gpio.c | 123 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 131 insertions(+) create mode 100644 drivers/gpio/npcm_gpio.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 886cdbcdbaa..149a62ffe61 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -279,6 +279,13 @@ config MXS_GPIO help Support GPIO controllers on i.MX23 and i.MX28 platforms +config NPCM_GPIO + bool "Nuvoton NPCM GPIO driver" + depends on DM_GPIO + help + Support GPIO controllers on Nuvovon NPCM SoCs. + NPCM7xx/NPCM8xx contain 8 GPIO banks, each bank contains 32 pins. + config OMAP_GPIO bool "TI OMAP GPIO driver" depends on ARCH_OMAP2PLUS diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index b39dde12abf..d7552762d06 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -28,6 +28,7 @@ obj-$(CONFIG_MARVELL_GPIO) += mvgpio.o obj-$(CONFIG_MCP230XX_GPIO) += mcp230xx_gpio.o obj-$(CONFIG_MXC_GPIO) += mxc_gpio.o obj-$(CONFIG_MXS_GPIO) += mxs_gpio.o +obj-$(CONFIG_NPCM_GPIO) += npcm_gpio.o obj-$(CONFIG_PCA953X) += pca953x.o obj-$(CONFIG_PCA9698) += pca9698.o obj-$(CONFIG_ROCKCHIP_GPIO) += rk_gpio.o diff --git a/drivers/gpio/npcm_gpio.c b/drivers/gpio/npcm_gpio.c new file mode 100644 index 00000000000..8afd57fa8e5 --- /dev/null +++ b/drivers/gpio/npcm_gpio.c @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2022 Nuvoton Technology Corp. + */ + +#include +#include +#include +#include + +#define NPCM_GPIOS_PER_BANK 32 + +/* Register offsets */ +#define GPIO_DIN 0x4 /* RO - Data In */ +#define GPIO_DOUT 0xC /* RW - Data Out */ +#define GPIO_OE 0x10 /* RW - Output Enable */ +#define GPIO_IEM 0x58 /* RW - Input Enable Mask */ +#define GPIO_OES 0x70 /* WO - Output Enable Register Set */ +#define GPIO_OEC 0x74 /* WO - Output Enable Register Clear */ + +struct npcm_gpio_priv { + void __iomem *base; +}; + +static int npcm_gpio_direction_input(struct udevice *dev, unsigned int offset) +{ + struct npcm_gpio_priv *priv = dev_get_priv(dev); + + writel(BIT(offset), priv->base + GPIO_OEC); + setbits_le32(priv->base + GPIO_IEM, BIT(offset)); + + return 0; +} + +static int npcm_gpio_direction_output(struct udevice *dev, unsigned int offset, + int value) +{ + struct npcm_gpio_priv *priv = dev_get_priv(dev); + + clrbits_le32(priv->base + GPIO_IEM, BIT(offset)); + writel(BIT(offset), priv->base + GPIO_OES); + + if (value) + setbits_le32(priv->base + GPIO_DOUT, BIT(offset)); + else + clrbits_le32(priv->base + GPIO_DOUT, BIT(offset)); + + return 0; +} + +static int npcm_gpio_get_value(struct udevice *dev, unsigned int offset) +{ + struct npcm_gpio_priv *priv = dev_get_priv(dev); + + if (readl(priv->base + GPIO_IEM) & BIT(offset)) + return !!(readl(priv->base + GPIO_DIN) & BIT(offset)); + + if (readl(priv->base + GPIO_OE) & BIT(offset)) + return !!(readl(priv->base + GPIO_DOUT) & BIT(offset)); + + return -EINVAL; +} + +static int npcm_gpio_set_value(struct udevice *dev, unsigned int offset, + int value) +{ + struct npcm_gpio_priv *priv = dev_get_priv(dev); + + if (value) + setbits_le32(priv->base + GPIO_DOUT, BIT(offset)); + else + clrbits_le32(priv->base + GPIO_DOUT, BIT(offset)); + + return 0; +} + +static int npcm_gpio_get_function(struct udevice *dev, unsigned int offset) +{ + struct npcm_gpio_priv *priv = dev_get_priv(dev); + + if (readl(priv->base + GPIO_IEM) & BIT(offset)) + return GPIOF_INPUT; + + if (readl(priv->base + GPIO_OE) & BIT(offset)) + return GPIOF_OUTPUT; + + return GPIOF_FUNC; +} + +static const struct dm_gpio_ops npcm_gpio_ops = { + .direction_input = npcm_gpio_direction_input, + .direction_output = npcm_gpio_direction_output, + .get_value = npcm_gpio_get_value, + .set_value = npcm_gpio_set_value, + .get_function = npcm_gpio_get_function, +}; + +static int npcm_gpio_probe(struct udevice *dev) +{ + struct npcm_gpio_priv *priv = dev_get_priv(dev); + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); + + priv->base = dev_read_addr_ptr(dev); + uc_priv->gpio_count = NPCM_GPIOS_PER_BANK; + uc_priv->bank_name = dev->name; + + return 0; +} + +static const struct udevice_id npcm_gpio_match[] = { + { .compatible = "nuvoton,npcm845-gpio" }, + { .compatible = "nuvoton,npcm750-gpio" }, + { } +}; + +U_BOOT_DRIVER(npcm_gpio) = { + .name = "npcm_gpio", + .id = UCLASS_GPIO, + .of_match = npcm_gpio_match, + .probe = npcm_gpio_probe, + .priv_auto = sizeof(struct npcm_gpio_priv), + .ops = &npcm_gpio_ops, +};