All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/4] Add Nuvoton NPCM750 support
@ 2022-04-19  5:32 Jim Liu
  2022-04-19  5:32 ` [PATCH v3 1/4] arm: nuvoton: Add support for Nuvoton NPCM750 BMC Jim Liu
                   ` (3 more replies)
  0 siblings, 4 replies; 10+ messages in thread
From: Jim Liu @ 2022-04-19  5:32 UTC (permalink / raw)
  To: JJLIU0, KWLIU, YSCHU, lukma, seanga2, sjg, sr, trini; +Cc: u-boot

The patch series add basic supoorts for NPCM750, which
is Nuvoton's 3th-generation BMC (Baseboard Management Controller).
Add drivers to support Clock,Timer,Uart for NPCM7xx SoC.

the NPCM750 computing subsystem comprises a dual-core ARM a9
at 800MHz speed with L1/L2 caches

dts,dtsi and npcm7xx-reset.h have been submitted to kernel upstream.

the patch is base on top of current master and pass the CI test.
https://github.com/u-boot/u-boot/pull/169

Jim Liu (4):
  arm: nuvoton: Add support for Nuvoton NPCM750 BMC
  clk: nuvoton: Add support for NPCM750
  serial: npcm: Add support for Nuvoton NPCM SoCs
  timer: npcm: Add NPCM timer support

 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 +
 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 ++
 drivers/serial/Kconfig                        |    9 +
 drivers/serial/Makefile                       |    1 +
 drivers/serial/serial_npcm.c                  |  157 +++
 drivers/timer/Kconfig                         |    9 +
 drivers/timer/Makefile                        |    1 +
 drivers/timer/npcm-timer.c                    |  115 ++
 include/configs/poleg.h                       |   44 +
 .../dt-bindings/clock/nuvoton,npcm7xx-clock.h |   46 +
 .../dt-bindings/reset/nuvoton,npcm7xx-reset.h |   91 ++
 34 files changed, 3131 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 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 drivers/serial/serial_npcm.c
 create mode 100644 drivers/timer/npcm-timer.c
 create mode 100644 include/configs/poleg.h
 create mode 100644 include/dt-bindings/clock/nuvoton,npcm7xx-clock.h
 create mode 100644 include/dt-bindings/reset/nuvoton,npcm7xx-reset.h

-- 
2.17.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v3 1/4] arm: nuvoton: Add support for Nuvoton NPCM750 BMC
  2022-04-19  5:32 [PATCH v3 0/4] Add Nuvoton NPCM750 support Jim Liu
@ 2022-04-19  5:32 ` Jim Liu
  2022-05-05 18:51   ` Tom Rini
  2022-04-19  5:32 ` [PATCH v3 2/4] clk: nuvoton: Add support for NPCM750 Jim Liu
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 10+ messages in thread
From: Jim Liu @ 2022-04-19  5:32 UTC (permalink / raw)
  To: JJLIU0, KWLIU, YSCHU, lukma, seanga2, sjg, sr, trini; +Cc: u-boot

Add basic support for the Nuvoton NPCM750 EVB (Poleg).

Signed-off-by: Jim Liu <JJLIU0@nuvoton.com>
---
Changes for V3:
   - remove unused define in poleg.h
   - add define to defconfig
Changes for v2:
   - coding style cleanup
   - remove reset.c and use sysreset function
   - re-generate the defconfig
   - remove v1 dts/dtsi and use linux upstream dts/dtsi
---
 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 efe33a58e1..f4cc5df93b 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -977,6 +977,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
@@ -2256,6 +2262,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 ad757e982e..85c23bcf77 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 df7b4addf9..70869c6136 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -1173,6 +1173,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 0000000000..02ee4d78e2
--- /dev/null
+++ b/arch/arm/dts/nuvoton-common-npcm7xx.dtsi
@@ -0,0 +1,1120 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/nuvoton,npcm7xx-clock.h>
+#include <dt-bindings/reset/nuvoton,npcm7xx-reset.h>
+
+/ {
+	#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 = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+			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 = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+			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 = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
+			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 = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
+					kcs_chan = <1>;
+					status = "disabled";
+				};
+
+				kcs2: kcs2@0 {
+					compatible = "nuvoton,npcm750-kcs-bmc";
+					reg = <0x0 0x40>;
+					interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
+					kcs_chan = <2>;
+					status = "disabled";
+				};
+
+				kcs3: kcs3@0 {
+					compatible = "nuvoton,npcm750-kcs-bmc";
+					reg = <0x0 0x40>;
+					interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
+					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 = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+				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 = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
+				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 = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+				reg = <0x8000 0x1C>;
+				clocks = <&clk NPCM7XX_CLK_TIMER>;
+			};
+
+			watchdog0: watchdog@801C {
+				compatible = "nuvoton,npcm750-wdt";
+				interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>;
+				reg = <0x801C 0x4>;
+				status = "disabled";
+				clocks = <&clk NPCM7XX_CLK_TIMER>;
+			};
+
+			watchdog1: watchdog@901C {
+				compatible = "nuvoton,npcm750-wdt";
+				interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+				reg = <0x901C 0x4>;
+				status = "disabled";
+				clocks = <&clk NPCM7XX_CLK_TIMER>;
+			};
+
+			watchdog2: watchdog@a01C {
+				compatible = "nuvoton,npcm750-wdt";
+				interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
+				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 = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+				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 = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
+				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 = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+				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 = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
+				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 = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
+				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 = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>,
+						<GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>,
+						<GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>,
+						<GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>,
+						<GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>,
+						<GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>,
+						<GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>,
+						<GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
+				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 = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
+				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 = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
+				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 = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
+				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 = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
+				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 = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
+				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 = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
+				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 = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
+				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 = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+				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 = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
+				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 = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+				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 = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
+				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 = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
+				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 = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
+				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 = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
+				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 = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
+				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 = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
+				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 = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
+			gpio-ranges = <&pinctrl 0 0 32>;
+		};
+		gpio1: gpio@f0011000 {
+			gpio-controller;
+			#gpio-cells = <2>;
+			reg = <0x1000 0x80>;
+			interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
+			gpio-ranges = <&pinctrl 0 32 32>;
+		};
+		gpio2: gpio@f0012000 {
+			gpio-controller;
+			#gpio-cells = <2>;
+			reg = <0x2000 0x80>;
+			interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
+			gpio-ranges = <&pinctrl 0 64 32>;
+		};
+		gpio3: gpio@f0013000 {
+			gpio-controller;
+			#gpio-cells = <2>;
+			reg = <0x3000 0x80>;
+			interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;
+			gpio-ranges = <&pinctrl 0 96 32>;
+		};
+		gpio4: gpio@f0014000 {
+			gpio-controller;
+			#gpio-cells = <2>;
+			reg = <0x4000 0x80>;
+			interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
+			gpio-ranges = <&pinctrl 0 128 32>;
+		};
+		gpio5: gpio@f0015000 {
+			gpio-controller;
+			#gpio-cells = <2>;
+			reg = <0x5000 0x80>;
+			interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
+			gpio-ranges = <&pinctrl 0 160 32>;
+		};
+		gpio6: gpio@f0016000 {
+			gpio-controller;
+			#gpio-cells = <2>;
+			reg = <0x6000 0x80>;
+			interrupts = <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>;
+			gpio-ranges = <&pinctrl 0 192 32>;
+		};
+		gpio7: gpio@f0017000 {
+			gpio-controller;
+			#gpio-cells = <2>;
+			reg = <0x7000 0x80>;
+			interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
+			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 0000000000..3e4abe6610
--- /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 0000000000..3b3806274a
--- /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 0000000000..13eee0fe56
--- /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 = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) |
+						  IRQ_TYPE_LEVEL_HIGH)>;
+			clocks = <&clk NPCM7XX_CLK_AHB>;
+		};
+	};
+
+	ahb {
+		gmac1: eth@f0804000 {
+			device_type = "network";
+			compatible = "snps,dwmac";
+			reg = <0xf0804000 0x2000>;
+			interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+			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 0000000000..762a0b6d6b
--- /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 0000000000..cf5043d6b8
--- /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 0000000000..8a1572b4f0
--- /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 0000000000..237e7ba7e5
--- /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 0000000000..49f9877bd6
--- /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 0000000000..dd74bb9e08
--- /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 <common.h>
+#include <cpu_func.h>
+#include <asm/armv7.h>
+#include <asm/io.h>
+#include <asm/arch/gcr.h>
+
+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 0000000000..cba2e342dc
--- /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 <common.h>
+#include <asm/io.h>
+#include <asm/pl310.h>
+
+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 0000000000..8ec4e374a5
--- /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 <linux/linkage.h>
+
+#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 0000000000..d3f4c1dd81
--- /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 0000000000..8797295c41
--- /dev/null
+++ b/board/nuvoton/poleg_evb/MAINTAINERS
@@ -0,0 +1,7 @@
+Poleg EVB
+M:	Stanley Chu <yschu@nuvoton.com>
+M:	Jim Liu <JJLIU0@nuvoton.com>
+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 0000000000..377433d60a
--- /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 0000000000..aef142a881
--- /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 <common.h>
+#include <dm.h>
+#include <asm/io.h>
+#include <asm/arch/gcr.h>
+#include <asm/mach-types.h>
+
+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 0000000000..f7bdefcf93
--- /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 0000000000..c21b063c05
--- /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 0000000000..757f5e34c8
--- /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
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v3 2/4] clk: nuvoton: Add support for NPCM750
  2022-04-19  5:32 [PATCH v3 0/4] Add Nuvoton NPCM750 support Jim Liu
  2022-04-19  5:32 ` [PATCH v3 1/4] arm: nuvoton: Add support for Nuvoton NPCM750 BMC Jim Liu
@ 2022-04-19  5:32 ` Jim Liu
  2022-04-22  0:36   ` Sean Anderson
  2022-05-05 18:52   ` Tom Rini
  2022-04-19  5:32 ` [PATCH v3 3/4] serial: npcm: Add support for Nuvoton NPCM SoCs Jim Liu
  2022-04-19  5:32 ` [PATCH v3 4/4] timer: npcm: Add NPCM timer support Jim Liu
  3 siblings, 2 replies; 10+ messages in thread
From: Jim Liu @ 2022-04-19  5:32 UTC (permalink / raw)
  To: JJLIU0, KWLIU, YSCHU, lukma, seanga2, sjg, sr, trini; +Cc: u-boot, Stanley Chu

Add clock controller driver for NPCM750

Signed-off-by: Jim Liu <JJLIU0@nuvoton.com>
Signed-off-by: Stanley Chu <yschu@nuvoton.com>
---
Changes for v3:
   - no changes since v2
Changes for v2:
   - combine NPCM750 and NPCM845 clk driver.
---
 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 bb4eee5d99..f5b553172c 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 0000000000..c63d9c16f1
--- /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 0000000000..8d71f2a24b
--- /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 <div64.h>
+#include <dm.h>
+#include <asm/io.h>
+#include <linux/bitfield.h>
+#include <linux/log2.h>
+#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 0000000000..06b60dc8b8
--- /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 <clk-uclass.h>
+
+/* 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 0000000000..a12aaa2f4c
--- /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 <dm.h>
+#include <dt-bindings/clock/nuvoton,npcm7xx-clock.h>
+#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 0000000000..65e6bc4eee
--- /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
+
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v3 3/4] serial: npcm: Add support for Nuvoton NPCM SoCs
  2022-04-19  5:32 [PATCH v3 0/4] Add Nuvoton NPCM750 support Jim Liu
  2022-04-19  5:32 ` [PATCH v3 1/4] arm: nuvoton: Add support for Nuvoton NPCM750 BMC Jim Liu
  2022-04-19  5:32 ` [PATCH v3 2/4] clk: nuvoton: Add support for NPCM750 Jim Liu
@ 2022-04-19  5:32 ` Jim Liu
  2022-05-05 18:52   ` Tom Rini
  2022-04-19  5:32 ` [PATCH v3 4/4] timer: npcm: Add NPCM timer support Jim Liu
  3 siblings, 1 reply; 10+ messages in thread
From: Jim Liu @ 2022-04-19  5:32 UTC (permalink / raw)
  To: JJLIU0, KWLIU, YSCHU, lukma, seanga2, sjg, sr, trini; +Cc: u-boot, Stanley Chu

Add Nuvoton BMC NPCM7xx/NPCM8xx uart driver

Signed-off-by: Jim Liu <JJLIU0@nuvoton.com>
Signed-off-by: Stanley Chu <yschu@nuvoton.com>
---
Changes for v3:
   - no changes since v2
Changes for v2:
   - coding style cleanup
   - Add support for setting parent clock
---
 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 dc514c95d3..5434389835 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -995,6 +995,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 b68b5e7b2b..033e060a44 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -68,6 +68,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 0000000000..76ac7cb80d
--- /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 <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <serial.h>
+
+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,
+};
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v3 4/4] timer: npcm: Add NPCM timer support
  2022-04-19  5:32 [PATCH v3 0/4] Add Nuvoton NPCM750 support Jim Liu
                   ` (2 preceding siblings ...)
  2022-04-19  5:32 ` [PATCH v3 3/4] serial: npcm: Add support for Nuvoton NPCM SoCs Jim Liu
@ 2022-04-19  5:32 ` Jim Liu
  2022-05-05 18:52   ` Tom Rini
  3 siblings, 1 reply; 10+ messages in thread
From: Jim Liu @ 2022-04-19  5:32 UTC (permalink / raw)
  To: JJLIU0, KWLIU, YSCHU, lukma, seanga2, sjg, sr, trini; +Cc: u-boot, Stanley Chu

Add Nuvoton BMC NPCM7xx/NPCM8xx timer driver.

Signed-off-by: Jim Liu <JJLIU0@nuvoton.com>
Signed-off-by: Stanley Chu <yschu@nuvoton.com>
---
Changes for v3:
   - no changes since v2
Changes for v2:
   - coding style cleanup
---
 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 8fad59b81a..4d538a6892 100644
--- a/drivers/timer/Kconfig
+++ b/drivers/timer/Kconfig
@@ -151,6 +151,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 58da6c1e84..6d7558cc56 100644
--- a/drivers/timer/Makefile
+++ b/drivers/timer/Makefile
@@ -15,6 +15,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 0000000000..4562a6f231
--- /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 <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <timer.h>
+#include <asm/io.h>
+
+#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,
+};
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH v3 2/4] clk: nuvoton: Add support for NPCM750
  2022-04-19  5:32 ` [PATCH v3 2/4] clk: nuvoton: Add support for NPCM750 Jim Liu
@ 2022-04-22  0:36   ` Sean Anderson
  2022-05-05 18:52   ` Tom Rini
  1 sibling, 0 replies; 10+ messages in thread
From: Sean Anderson @ 2022-04-22  0:36 UTC (permalink / raw)
  To: Jim Liu, JJLIU0, KWLIU, YSCHU, lukma, sjg, sr, trini; +Cc: u-boot

On 4/19/22 1:32 AM, Jim Liu wrote:
> Add clock controller driver for NPCM750
> 
> Signed-off-by: Jim Liu <JJLIU0@nuvoton.com>
> Signed-off-by: Stanley Chu <yschu@nuvoton.com>
> ---
> Changes for v3:
>     - no changes since v2
> Changes for v2:
>     - combine NPCM750 and NPCM845 clk driver.
> ---
>   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 bb4eee5d99..f5b553172c 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 0000000000..c63d9c16f1
> --- /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 0000000000..8d71f2a24b
> --- /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 <div64.h>
> +#include <dm.h>
> +#include <asm/io.h>
> +#include <linux/bitfield.h>
> +#include <linux/log2.h>
> +#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 0000000000..06b60dc8b8
> --- /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 <clk-uclass.h>
> +
> +/* 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 0000000000..a12aaa2f4c
> --- /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 <dm.h>
> +#include <dt-bindings/clock/nuvoton,npcm7xx-clock.h>
> +#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 0000000000..65e6bc4eee
> --- /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
> +
> 

Reviewed-by: Sean Anderson <seanga2@gmail.com>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v3 1/4] arm: nuvoton: Add support for Nuvoton NPCM750 BMC
  2022-04-19  5:32 ` [PATCH v3 1/4] arm: nuvoton: Add support for Nuvoton NPCM750 BMC Jim Liu
@ 2022-05-05 18:51   ` Tom Rini
  0 siblings, 0 replies; 10+ messages in thread
From: Tom Rini @ 2022-05-05 18:51 UTC (permalink / raw)
  To: Jim Liu; +Cc: JJLIU0, KWLIU, YSCHU, lukma, seanga2, sjg, sr, u-boot

[-- Attachment #1: Type: text/plain, Size: 218 bytes --]

On Tue, Apr 19, 2022 at 01:32:19PM +0800, Jim Liu wrote:

> Add basic support for the Nuvoton NPCM750 EVB (Poleg).
> 
> Signed-off-by: Jim Liu <JJLIU0@nuvoton.com>

Applied to u-boot/master, thanks!

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v3 2/4] clk: nuvoton: Add support for NPCM750
  2022-04-19  5:32 ` [PATCH v3 2/4] clk: nuvoton: Add support for NPCM750 Jim Liu
  2022-04-22  0:36   ` Sean Anderson
@ 2022-05-05 18:52   ` Tom Rini
  1 sibling, 0 replies; 10+ messages in thread
From: Tom Rini @ 2022-05-05 18:52 UTC (permalink / raw)
  To: Jim Liu; +Cc: JJLIU0, KWLIU, YSCHU, lukma, seanga2, sjg, sr, u-boot

[-- Attachment #1: Type: text/plain, Size: 303 bytes --]

On Tue, Apr 19, 2022 at 01:32:20PM +0800, Jim Liu wrote:

> Add clock controller driver for NPCM750
> 
> Signed-off-by: Jim Liu <JJLIU0@nuvoton.com>
> Signed-off-by: Stanley Chu <yschu@nuvoton.com>
> Reviewed-by: Sean Anderson <seanga2@gmail.com>

Applied to u-boot/master, thanks!

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v3 3/4] serial: npcm: Add support for Nuvoton NPCM SoCs
  2022-04-19  5:32 ` [PATCH v3 3/4] serial: npcm: Add support for Nuvoton NPCM SoCs Jim Liu
@ 2022-05-05 18:52   ` Tom Rini
  0 siblings, 0 replies; 10+ messages in thread
From: Tom Rini @ 2022-05-05 18:52 UTC (permalink / raw)
  To: Jim Liu; +Cc: JJLIU0, KWLIU, YSCHU, lukma, seanga2, sjg, sr, u-boot

[-- Attachment #1: Type: text/plain, Size: 257 bytes --]

On Tue, Apr 19, 2022 at 01:32:21PM +0800, Jim Liu wrote:

> Add Nuvoton BMC NPCM7xx/NPCM8xx uart driver
> 
> Signed-off-by: Jim Liu <JJLIU0@nuvoton.com>
> Signed-off-by: Stanley Chu <yschu@nuvoton.com>

Applied to u-boot/master, thanks!

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v3 4/4] timer: npcm: Add NPCM timer support
  2022-04-19  5:32 ` [PATCH v3 4/4] timer: npcm: Add NPCM timer support Jim Liu
@ 2022-05-05 18:52   ` Tom Rini
  0 siblings, 0 replies; 10+ messages in thread
From: Tom Rini @ 2022-05-05 18:52 UTC (permalink / raw)
  To: Jim Liu; +Cc: JJLIU0, KWLIU, YSCHU, lukma, seanga2, sjg, sr, u-boot

[-- Attachment #1: Type: text/plain, Size: 259 bytes --]

On Tue, Apr 19, 2022 at 01:32:22PM +0800, Jim Liu wrote:

> Add Nuvoton BMC NPCM7xx/NPCM8xx timer driver.
> 
> Signed-off-by: Jim Liu <JJLIU0@nuvoton.com>
> Signed-off-by: Stanley Chu <yschu@nuvoton.com>

Applied to u-boot/master, thanks!

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2022-05-05 18:52 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-19  5:32 [PATCH v3 0/4] Add Nuvoton NPCM750 support Jim Liu
2022-04-19  5:32 ` [PATCH v3 1/4] arm: nuvoton: Add support for Nuvoton NPCM750 BMC Jim Liu
2022-05-05 18:51   ` Tom Rini
2022-04-19  5:32 ` [PATCH v3 2/4] clk: nuvoton: Add support for NPCM750 Jim Liu
2022-04-22  0:36   ` Sean Anderson
2022-05-05 18:52   ` Tom Rini
2022-04-19  5:32 ` [PATCH v3 3/4] serial: npcm: Add support for Nuvoton NPCM SoCs Jim Liu
2022-05-05 18:52   ` Tom Rini
2022-04-19  5:32 ` [PATCH v3 4/4] timer: npcm: Add NPCM timer support Jim Liu
2022-05-05 18:52   ` Tom Rini

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.