All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/32] Add support for MediaTek MT7981/MT7986 SoCs - v2
@ 2022-08-31 11:00 Weijie Gao
  2022-08-31 11:00 ` [PATCH v2 01/32] arm: mediatek: add support for MediaTek MT7986 SoC Weijie Gao
                   ` (31 more replies)
  0 siblings, 32 replies; 60+ messages in thread
From: Weijie Gao @ 2022-08-31 11:00 UTC (permalink / raw)
  To: u-boot; +Cc: GSS_MTK_Uboot_upstream, Weijie Gao

This patch series add support for MediaTek MT7981/MT7986 SoCs with their
reference boards and related drivers.

This patch series add basic boot support on eMMC/SD/SPI-NOR/SPI-NAND for these
boards. The clock, pinctrl drivers and the SoC initializaton code are also
included.

Product spec for MT7986:
https://www.mediatek.com/products/home-networking/mediatek-filogic-830

Changes of v2:
- Add cpu driver for print_cpuinfo()
- Fix NULL pointer dereference in mtk_image
- Fix coding style
- Minor changes

Weijie Gao (32):
  arm: mediatek: add support for MediaTek MT7986 SoC
  arm: mediatek: add support for MediaTek MT7981 SoC
  board: mediatek: add MT7986 reference boards
  board: mediatek: add MT7981 reference boards
  mmc: mediatek: add support for MediaTek MT7891/MT7986 SoCs
  net: mediatek: use a struct to cover variations of all SoCs
  net: mediatek: stop using bitfileds for DMA descriptors
  net: mediatek: add support for PDMA v2
  net: mediatek: add support for MediaTek MT7981/MT7986
  serial: mtk: add support for using dynamic baud clock souce
  arm: dts: mt7622: force high-speed mode for uart
  pwm: mtk: add support for MediaTek MT7986 SoC
  pwm: mtk: add support for MediaTek MT7981 SoC
  timer: mtk: add support for MediaTek MT7981/MT7986 SoCs
  watchdog: mediatek: add support for MediaTek MT7986 SoC
  spi: add support for MediaTek spi-mem controller
  i2c: add support for MediaTek I2C interface
  arm: dts: mt7622: add i2c support
  dt-bindings: pinctrl: mediatek: add a header for common pinconf
    parameters
  pinctrl: mediatek: add pinctrl driver for MT7981 SoC
  pinctrl: mediatek: add pinctrl driver for MT7986 SoC
  clk: mediatek: add CLK_BYPASS_XTAL flag to allow bypassing searching
    clock parent of xtal clock
  clk: mediatek: add support to configure clock driver parent
  clk: mediatek: add infrasys clock mux support
  clk: mediatek: add CLK_XTAL support for clock driver
  clk: mediatek: add clock driver support for MediaTek MT7986 SoC
  clk: mediatek: add clock driver support for MediaTek MT7981 SoC
  cpu: add basic cpu driver for MediaTek ARM chips
  tools: mtk_image: split gfh header verification into a new function
  tools: mtk_image: split the code of generating NAND header into a new
    file
  tools: mtk_image: add support for nand headers used by newer chips
  MAINTAINERS: update maintainer for MediaTek ARM platform

 MAINTAINERS                                   |    6 +
 arch/arm/dts/Makefile                         |    9 +
 arch/arm/dts/mt7622-rfb.dts                   |   18 +
 arch/arm/dts/mt7622.dtsi                      |   25 +
 arch/arm/dts/mt7981-emmc-rfb.dts              |  139 +++
 arch/arm/dts/mt7981-rfb.dts                   |  173 +++
 arch/arm/dts/mt7981-sd-rfb.dts                |  139 +++
 arch/arm/dts/mt7981.dtsi                      |  293 +++++
 arch/arm/dts/mt7986-u-boot.dtsi               |   33 +
 arch/arm/dts/mt7986.dtsi                      |  346 ++++++
 arch/arm/dts/mt7986a-emmc-rfb.dts             |   16 +
 arch/arm/dts/mt7986a-rfb.dts                  |  218 ++++
 arch/arm/dts/mt7986a-sd-rfb.dts               |  177 +++
 arch/arm/dts/mt7986b-emmc-rfb.dts             |   16 +
 arch/arm/dts/mt7986b-rfb.dts                  |  204 ++++
 arch/arm/dts/mt7986b-sd-rfb.dts               |  173 +++
 arch/arm/mach-mediatek/Kconfig                |   23 +
 arch/arm/mach-mediatek/Makefile               |    2 +
 arch/arm/mach-mediatek/mt7981/Makefile        |    4 +
 arch/arm/mach-mediatek/mt7981/init.c          |   45 +
 arch/arm/mach-mediatek/mt7981/lowlevel_init.S |   32 +
 arch/arm/mach-mediatek/mt7986/Makefile        |    4 +
 arch/arm/mach-mediatek/mt7986/init.c          |   45 +
 arch/arm/mach-mediatek/mt7986/lowlevel_init.S |   32 +
 board/mediatek/mt7981/MAINTAINERS             |   10 +
 board/mediatek/mt7981/Makefile                |    3 +
 board/mediatek/mt7981/mt7981_rfb.c            |   10 +
 board/mediatek/mt7986/MAINTAINERS             |   10 +
 board/mediatek/mt7986/Makefile                |    3 +
 board/mediatek/mt7986/mt7986_rfb.c            |   10 +
 configs/mt7981_emmc_rfb_defconfig             |   64 +
 configs/mt7981_rfb_defconfig                  |   69 ++
 configs/mt7981_sd_rfb_defconfig               |   64 +
 configs/mt7986_rfb_defconfig                  |   66 ++
 configs/mt7986a_bpir3_emmc_defconfig          |   64 +
 configs/mt7986a_bpir3_sd_defconfig            |   64 +
 drivers/clk/mediatek/Makefile                 |    2 +
 drivers/clk/mediatek/clk-mt7981.c             |  683 +++++++++++
 drivers/clk/mediatek/clk-mt7986.c             |  672 +++++++++++
 drivers/clk/mediatek/clk-mtk.c                |  156 ++-
 drivers/clk/mediatek/clk-mtk.h                |   13 +-
 drivers/cpu/Makefile                          |    1 +
 drivers/cpu/mtk_cpu.c                         |  106 ++
 drivers/i2c/Kconfig                           |    9 +
 drivers/i2c/Makefile                          |    1 +
 drivers/i2c/mtk_i2c.c                         |  822 +++++++++++++
 drivers/mmc/mtk-sd.c                          |   68 +-
 drivers/net/mtk_eth.c                         |  261 ++--
 drivers/net/mtk_eth.h                         |  101 +-
 drivers/pinctrl/mediatek/Kconfig              |    8 +
 drivers/pinctrl/mediatek/Makefile             |    2 +
 drivers/pinctrl/mediatek/pinctrl-mt7981.c     | 1049 +++++++++++++++++
 drivers/pinctrl/mediatek/pinctrl-mt7986.c     |  775 ++++++++++++
 drivers/pwm/pwm-mtk.c                         |   40 +-
 drivers/serial/serial_mtk.c                   |   80 +-
 drivers/spi/Kconfig                           |    8 +
 drivers/spi/Makefile                          |    1 +
 drivers/spi/mtk_spim.c                        |  701 +++++++++++
 drivers/timer/mtk_timer.c                     |   59 +-
 drivers/watchdog/mtk_wdt.c                    |    1 +
 include/configs/mt7981.h                      |   26 +
 include/configs/mt7986.h                      |   26 +
 include/dt-bindings/clock/mt7981-clk.h        |  267 +++++
 include/dt-bindings/clock/mt7986-clk.h        |  249 ++++
 include/dt-bindings/pinctrl/mt65xx.h          |   41 +
 tools/Makefile                                |    1 +
 tools/mtk_image.c                             |  377 ++----
 tools/mtk_image.h                             |   25 -
 tools/mtk_nand_headers.c                      |  668 +++++++++++
 tools/mtk_nand_headers.h                      |  165 +++
 70 files changed, 9525 insertions(+), 548 deletions(-)
 create mode 100644 arch/arm/dts/mt7981-emmc-rfb.dts
 create mode 100644 arch/arm/dts/mt7981-rfb.dts
 create mode 100644 arch/arm/dts/mt7981-sd-rfb.dts
 create mode 100644 arch/arm/dts/mt7981.dtsi
 create mode 100644 arch/arm/dts/mt7986-u-boot.dtsi
 create mode 100644 arch/arm/dts/mt7986.dtsi
 create mode 100644 arch/arm/dts/mt7986a-emmc-rfb.dts
 create mode 100644 arch/arm/dts/mt7986a-rfb.dts
 create mode 100644 arch/arm/dts/mt7986a-sd-rfb.dts
 create mode 100644 arch/arm/dts/mt7986b-emmc-rfb.dts
 create mode 100644 arch/arm/dts/mt7986b-rfb.dts
 create mode 100644 arch/arm/dts/mt7986b-sd-rfb.dts
 create mode 100644 arch/arm/mach-mediatek/mt7981/Makefile
 create mode 100644 arch/arm/mach-mediatek/mt7981/init.c
 create mode 100644 arch/arm/mach-mediatek/mt7981/lowlevel_init.S
 create mode 100644 arch/arm/mach-mediatek/mt7986/Makefile
 create mode 100644 arch/arm/mach-mediatek/mt7986/init.c
 create mode 100644 arch/arm/mach-mediatek/mt7986/lowlevel_init.S
 create mode 100644 board/mediatek/mt7981/MAINTAINERS
 create mode 100644 board/mediatek/mt7981/Makefile
 create mode 100644 board/mediatek/mt7981/mt7981_rfb.c
 create mode 100644 board/mediatek/mt7986/MAINTAINERS
 create mode 100644 board/mediatek/mt7986/Makefile
 create mode 100644 board/mediatek/mt7986/mt7986_rfb.c
 create mode 100644 configs/mt7981_emmc_rfb_defconfig
 create mode 100644 configs/mt7981_rfb_defconfig
 create mode 100644 configs/mt7981_sd_rfb_defconfig
 create mode 100644 configs/mt7986_rfb_defconfig
 create mode 100644 configs/mt7986a_bpir3_emmc_defconfig
 create mode 100644 configs/mt7986a_bpir3_sd_defconfig
 create mode 100644 drivers/clk/mediatek/clk-mt7981.c
 create mode 100644 drivers/clk/mediatek/clk-mt7986.c
 create mode 100644 drivers/cpu/mtk_cpu.c
 create mode 100644 drivers/i2c/mtk_i2c.c
 create mode 100644 drivers/pinctrl/mediatek/pinctrl-mt7981.c
 create mode 100644 drivers/pinctrl/mediatek/pinctrl-mt7986.c
 create mode 100644 drivers/spi/mtk_spim.c
 create mode 100644 include/configs/mt7981.h
 create mode 100644 include/configs/mt7986.h
 create mode 100644 include/dt-bindings/clock/mt7981-clk.h
 create mode 100644 include/dt-bindings/clock/mt7986-clk.h
 create mode 100644 include/dt-bindings/pinctrl/mt65xx.h
 create mode 100644 tools/mtk_nand_headers.c
 create mode 100644 tools/mtk_nand_headers.h

-- 
2.17.1


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

* [PATCH v2 01/32] arm: mediatek: add support for MediaTek MT7986 SoC
  2022-08-31 11:00 [PATCH v2 00/32] Add support for MediaTek MT7981/MT7986 SoCs - v2 Weijie Gao
@ 2022-08-31 11:00 ` Weijie Gao
  2022-08-31 13:46   ` Simon Glass
  2022-09-01  0:09   ` Daniel Golle
  2022-08-31 11:00 ` [PATCH v2 02/32] arm: mediatek: add support for MediaTek MT7981 SoC Weijie Gao
                   ` (30 subsequent siblings)
  31 siblings, 2 replies; 60+ messages in thread
From: Weijie Gao @ 2022-08-31 11:00 UTC (permalink / raw)
  To: u-boot; +Cc: GSS_MTK_Uboot_upstream, Weijie Gao

This patch adds basic support for MediaTek MT7986 SoC.
This include the file that will initialize the SoC after boot and its
device tree.

Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
---
v2 changes:
  Sort include lines
  Add reference link for armv8_el2_to_aarch32 in lowlevel_init.S
  Remove print_cpuinfo and use cpu driver instead
---
 arch/arm/dts/mt7986-u-boot.dtsi               |  33 ++
 arch/arm/dts/mt7986.dtsi                      | 346 ++++++++++++++++++
 arch/arm/mach-mediatek/Kconfig                |  12 +
 arch/arm/mach-mediatek/Makefile               |   1 +
 arch/arm/mach-mediatek/mt7986/Makefile        |   4 +
 arch/arm/mach-mediatek/mt7986/init.c          |  45 +++
 arch/arm/mach-mediatek/mt7986/lowlevel_init.S |  32 ++
 7 files changed, 473 insertions(+)
 create mode 100644 arch/arm/dts/mt7986-u-boot.dtsi
 create mode 100644 arch/arm/dts/mt7986.dtsi
 create mode 100644 arch/arm/mach-mediatek/mt7986/Makefile
 create mode 100644 arch/arm/mach-mediatek/mt7986/init.c
 create mode 100644 arch/arm/mach-mediatek/mt7986/lowlevel_init.S

diff --git a/arch/arm/dts/mt7986-u-boot.dtsi b/arch/arm/dts/mt7986-u-boot.dtsi
new file mode 100644
index 0000000000..95671f8afa
--- /dev/null
+++ b/arch/arm/dts/mt7986-u-boot.dtsi
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ * Author: Sam Shih <sam.shih@mediatek.com>
+ */
+
+&topckgen {
+	u-boot,dm-pre-reloc;
+};
+
+&pericfg {
+	u-boot,dm-pre-reloc;
+};
+
+&apmixedsys {
+	u-boot,dm-pre-reloc;
+};
+
+&timer0 {
+	u-boot,dm-pre-reloc;
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+};
+
+&snand {
+	u-boot,dm-pre-reloc;
+};
+
+&pinctrl {
+	u-boot,dm-pre-reloc;
+};
diff --git a/arch/arm/dts/mt7986.dtsi b/arch/arm/dts/mt7986.dtsi
new file mode 100644
index 0000000000..25b81ab7e1
--- /dev/null
+++ b/arch/arm/dts/mt7986.dtsi
@@ -0,0 +1,346 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ * Author: Sam Shih <sam.shih@mediatek.com>
+ */
+
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/phy/phy.h>
+#include <dt-bindings/clock/mt7986-clk.h>
+#include <dt-bindings/reset/mt7629-reset.h>
+#include <dt-bindings/pinctrl/mt65xx.h>
+
+/ {
+	compatible = "mediatek,mt7986";
+	interrupt-parent = <&gic>;
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	config {
+		u-boot,mmc-env-partition = "u-boot-env";
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		cpu0: cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53";
+			reg = <0x0>;
+		};
+		cpu1: cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53";
+			reg = <0x1>;
+		};
+		cpu2: cpu@2 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53";
+			reg = <0x1>;
+		};
+		cpu3: cpu@3 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53";
+			reg = <0x1>;
+		};
+	};
+
+	dummy_clk: dummy12m {
+		compatible = "fixed-clock";
+		clock-frequency = <12000000>;
+		#clock-cells = <0>;
+		/* must need this line, or uart uanable to get dummy_clk */
+		u-boot,dm-pre-reloc;
+	};
+
+	hwver: hwver {
+		compatible = "mediatek,hwver";
+		reg = <0x8000000 0x1000>;
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupt-parent = <&gic>;
+		clock-frequency = <13000000>;
+		interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+		arm,cpu-registers-not-fw-configured;
+	};
+
+	timer0: timer@10008000 {
+		compatible = "mediatek,mt7986-timer";
+		reg = <0x10008000 0x1000>;
+		interrupts = <GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&infracfg CK_INFRA_CK_F26M>;
+		clock-names = "gpt-clk";
+		u-boot,dm-pre-reloc;
+	};
+
+	watchdog: watchdog@1001c000 {
+		compatible = "mediatek,mt7986-wdt";
+		reg = <0x1001c000 0x1000>;
+		interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+		#reset-cells = <1>;
+		status = "disabled";
+	};
+
+	gic: interrupt-controller@c000000 {
+		compatible = "arm,gic-v3";
+		#interrupt-cells = <3>;
+		interrupt-parent = <&gic>;
+		interrupt-controller;
+		reg = <0x0c000000 0x40000>,  /* GICD */
+		      <0x0c080000 0x200000>; /* GICR */
+
+		interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	fixed_plls: apmixedsys@1001E000 {
+		compatible = "mediatek,mt7986-fixed-plls";
+		reg = <0x1001E000 0x1000>;
+		#clock-cells = <1>;
+	};
+
+	topckgen: topckgen@1001B000 {
+		compatible = "mediatek,mt7986-topckgen";
+		reg = <0x1001B000 0x1000>;
+		clock-parent = <&fixed_plls>;
+		#clock-cells = <1>;
+	};
+
+	infracfg_ao: infracfg_ao@10001000 {
+		compatible = "mediatek,mt7986-infracfg_ao";
+		reg = <0x10001000 0x68>;
+		clock-parent = <&infracfg>;
+		#clock-cells = <1>;
+	};
+
+	infracfg: infracfg@10001040 {
+		compatible = "mediatek,mt7986-infracfg";
+		reg = <0x10001000 0x1000>;
+		clock-parent = <&topckgen>;
+		#clock-cells = <1>;
+	};
+
+	pinctrl: pinctrl@1001f000 {
+		compatible = "mediatek,mt7986-pinctrl";
+		reg = <0x1001f000 0x1000>,
+		      <0x11c30000 0x1000>,
+		      <0x11c40000 0x1000>,
+		      <0x11e20000 0x1000>,
+		      <0x11e30000 0x1000>,
+		      <0x11f00000 0x1000>,
+		      <0x11f10000 0x1000>,
+		      <0x1000b000 0x1000>;
+		reg-names = "gpio_base", "iocfg_rt_base", "iocfg_rb_base",
+			    "iocfg_lt_base", "iocfg_lb_base", "iocfg_tr_base",
+			    "iocfg_tl_base", "eint";
+		gpio: gpio-controller {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+	};
+
+	pwm: pwm@10048000 {
+		compatible = "mediatek,mt7986-pwm";
+		reg = <0x10048000 0x1000>;
+		#clock-cells = <1>;
+		#pwm-cells = <2>;
+		interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&infracfg CK_INFRA_PWM>,
+			 <&infracfg_ao CK_INFRA_PWM_BSEL>,
+			 <&infracfg_ao CK_INFRA_PWM1_CK>,
+			 <&infracfg_ao CK_INFRA_PWM2_CK>;
+		assigned-clocks = <&topckgen CK_TOP_PWM_SEL>,
+				  <&infracfg CK_INFRA_PWM_BSEL>,
+				  <&infracfg CK_INFRA_PWM1_SEL>,
+				  <&infracfg CK_INFRA_PWM2_SEL>;
+		assigned-clock-parents = <&topckgen CK_TOP_CB_M_D4>,
+					 <&infracfg CK_INFRA_PWM>,
+					 <&infracfg CK_INFRA_PWM>,
+					 <&infracfg CK_INFRA_PWM>;
+		clock-names = "top", "main", "pwm1", "pwm2";
+		status = "disabled";
+		u-boot,dm-pre-reloc;
+	};
+
+	uart0: serial@11002000 {
+		compatible = "mediatek,hsuart";
+		reg = <0x11002000 0x400>;
+		interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&infracfg_ao CK_INFRA_UART0_CK>;
+		assigned-clocks = <&topckgen CK_TOP_UART_SEL>,
+				  <&infracfg_ao CK_INFRA_UART0_SEL>;
+		assigned-clock-parents = <&topckgen CK_TOP_CB_CKSQ_40M>,
+					 <&infracfg CK_INFRA_UART>;
+		mediatek,force-highspeed;
+		status = "disabled";
+		u-boot,dm-pre-reloc;
+	};
+
+	uart1: serial@11003000 {
+		compatible = "mediatek,hsuart";
+		reg = <0x11003000 0x400>;
+		interrupts = <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&infracfg_ao CK_INFRA_UART1_CK>;
+		assigned-clocks = <&infracfg CK_INFRA_UART1_SEL>;
+		assigned-clock-parents = <&infracfg CK_INFRA_CK_F26M>;
+		mediatek,force-highspeed;
+		status = "disabled";
+	};
+
+	uart2: serial@11004000 {
+		compatible = "mediatek,hsuart";
+		reg = <0x11004000 0x400>;
+		interrupts = <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&infracfg_ao CK_INFRA_UART2_CK>;
+		assigned-clocks = <&infracfg CK_INFRA_UART2_SEL>;
+		assigned-clock-parents = <&infracfg CK_INFRA_CK_F26M>;
+		mediatek,force-highspeed;
+		status = "disabled";
+	};
+
+	snand: snand@11005000 {
+		compatible = "mediatek,mt7986-snand";
+		reg = <0x11005000 0x1000>,
+		      <0x11006000 0x1000>;
+		reg-names = "nfi", "ecc";
+		clocks = <&infracfg_ao CK_INFRA_SPINFI1_CK>,
+			 <&infracfg_ao CK_INFRA_NFI1_CK>,
+			 <&infracfg_ao CK_INFRA_NFI_HCK_CK>;
+		clock-names = "pad_clk", "nfi_clk", "nfi_hclk";
+		assigned-clocks = <&topckgen CK_TOP_SPINFI_SEL>,
+				  <&topckgen CK_TOP_NFI1X_SEL>;
+		assigned-clock-parents = <&topckgen CK_TOP_CB_M_D8>,
+					 <&topckgen CK_TOP_CB_M_D8>;
+		status = "disabled";
+	};
+
+	ethsys: syscon@15000000 {
+		compatible = "mediatek,mt7986-ethsys", "syscon";
+		reg = <0x15000000 0x1000>;
+		clock-parent = <&topckgen>;
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
+
+	eth: ethernet@15100000 {
+		compatible = "mediatek,mt7986-eth", "syscon";
+		reg = <0x15100000 0x20000>;
+		resets = <&ethsys ETHSYS_FE_RST>;
+		reset-names = "fe";
+		mediatek,ethsys = <&ethsys>;
+		mediatek,sgmiisys = <&sgmiisys0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	sgmiisys0: syscon@10060000 {
+		compatible = "mediatek,mt7986-sgmiisys", "syscon";
+		reg = <0x10060000 0x1000>;
+		#clock-cells = <1>;
+	};
+
+	sgmiisys1: syscon@10070000 {
+		compatible = "mediatek,mt7986-sgmiisys", "syscon";
+		reg = <0x10070000 0x1000>;
+		#clock-cells = <1>;
+	};
+
+	spi0: spi@1100a000 {
+		compatible = "mediatek,ipm-spi";
+		reg = <0x1100a000 0x100>;
+		clocks = <&infracfg_ao CK_INFRA_SPI0_CK>,
+			 <&topckgen CK_TOP_SPI_SEL>;
+		assigned-clocks = <&topckgen CK_TOP_SPI_SEL>,
+				  <&infracfg CK_INFRA_SPI0_SEL>;
+		assigned-clock-parents = <&topckgen CK_TOP_CB_M_D2>,
+					 <&topckgen CK_INFRA_ISPI0>;
+		clock-names = "sel-clk", "spi-clk";
+		interrupts = <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	spi1: spi@1100b000 {
+		compatible = "mediatek,ipm-spi";
+		reg = <0x1100b000 0x100>;
+		interrupts = <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	mmc0: mmc@11230000 {
+		compatible = "mediatek,mt7986-mmc";
+		reg = <0x11230000 0x1000>,
+		      <0x11C20000 0x1000>;
+		interrupts = <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&topckgen CK_TOP_EMMC_416M>,
+			<&topckgen CK_TOP_EMMC_250M>,
+			<&infracfg_ao CK_INFRA_MSDC_CK>;
+		assigned-clocks = <&topckgen CK_TOP_EMMC_416M_SEL>,
+				  <&topckgen CK_TOP_EMMC_250M_SEL>;
+		assigned-clock-parents = <&topckgen CK_TOP_CB_M_416M>,
+					 <&topckgen CK_TOP_NET1_D5_D2>;
+		clock-names = "source", "hclk", "source_cg";
+		status = "disabled";
+	};
+
+	xhci: xhci@11200000 {
+		compatible = "mediatek,mt7986-xhci",
+			     "mediatek,mtk-xhci";
+		reg = <0x11200000 0x2e00>,
+		      <0x11203e00 0x0100>;
+		reg-names = "mac", "ippc";
+		interrupts = <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>;
+		phys = <&u2port0 PHY_TYPE_USB2>,
+		       <&u3port0 PHY_TYPE_USB3>,
+		       <&u2port1 PHY_TYPE_USB2>;
+		clocks = <&dummy_clk>,
+			 <&dummy_clk>,
+			 <&dummy_clk>,
+			 <&dummy_clk>,
+			 <&dummy_clk>;
+		clock-names = "sys_ck",
+			      "xhci_ck",
+			      "ref_ck",
+			      "mcu_ck",
+			      "dma_ck";
+		tpl-support;
+		status = "okay";
+	};
+
+	usbtphy: usb-phy@11e10000 {
+		compatible = "mediatek,mt7986",
+			     "mediatek,generic-tphy-v2";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		status = "okay";
+
+		u2port0: usb-phy@11e10000 {
+			reg = <0x11e10000 0x700>;
+			clocks = <&dummy_clk>;
+			clock-names = "ref";
+			#phy-cells = <1>;
+			status = "okay";
+		};
+
+		u3port0: usb-phy@11e10700 {
+			reg = <0x11e10700 0x900>;
+			clocks = <&dummy_clk>;
+			clock-names = "ref";
+			#phy-cells = <1>;
+			status = "okay";
+		};
+
+		u2port1: usb-phy@11e11000 {
+			reg = <0x11e11000 0x700>;
+			clocks = <&dummy_clk>;
+			clock-names = "ref";
+			#phy-cells = <1>;
+			status = "okay";
+		};
+	};
+};
diff --git a/arch/arm/mach-mediatek/Kconfig b/arch/arm/mach-mediatek/Kconfig
index f79a5c62cd..82fadeba8a 100644
--- a/arch/arm/mach-mediatek/Kconfig
+++ b/arch/arm/mach-mediatek/Kconfig
@@ -40,6 +40,15 @@ config TARGET_MT7629
 	  including DDR3, crypto engine, 3x3 11n/ac Wi-Fi, Gigabit Ethernet,
 	  switch, USB3.0, PCIe, UART, SPI, I2C and PWM.
 
+config TARGET_MT7986
+	bool "MediaTek MT7986 SoC"
+	select ARM64
+	select CPU
+	help
+	  The MediaTek MT7986 is a ARM64-based SoC with a quad-core Cortex-A53.
+	  including UART, SPI, SPI flash, USB3.0, MMC, NAND, SNFI, PWM, PCIe,
+	  Gigabit Ethernet, I2C, built-in 4x4 Wi-Fi, and PCIe.
+
 config TARGET_MT8183
 	bool "MediaTek MT8183 SoC"
 	select ARM64
@@ -84,6 +93,7 @@ config SYS_BOARD
 	default "mt7622" if TARGET_MT7622
 	default "mt7623" if TARGET_MT7623
 	default "mt7629" if TARGET_MT7629
+	default "mt7986" if TARGET_MT7986
 	default "mt8183" if TARGET_MT8183
 	default "mt8512" if TARGET_MT8512
 	default "mt8516" if TARGET_MT8516
@@ -99,6 +109,7 @@ config SYS_CONFIG_NAME
 	default "mt7622" if TARGET_MT7622
 	default "mt7623" if TARGET_MT7623
 	default "mt7629" if TARGET_MT7629
+	default "mt7986" if TARGET_MT7986
 	default "mt8183" if TARGET_MT8183
 	default "mt8512" if TARGET_MT8512
 	default "mt8516" if TARGET_MT8516
@@ -113,6 +124,7 @@ config MTK_BROM_HEADER_INFO
 	string
 	default "media=nor" if TARGET_MT8518 || TARGET_MT8512 || TARGET_MT7629 || TARGET_MT7622
 	default "media=emmc" if TARGET_MT8516 || TARGET_MT8365 || TARGET_MT8183
+	default "media=snand;nandinfo=2k+64" if TARGET_MT7986
 	default "lk=1" if TARGET_MT7623
 
 endif
diff --git a/arch/arm/mach-mediatek/Makefile b/arch/arm/mach-mediatek/Makefile
index 0f5b0c16d2..fe5c3a837c 100644
--- a/arch/arm/mach-mediatek/Makefile
+++ b/arch/arm/mach-mediatek/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_MT8512) += mt8512/
 obj-$(CONFIG_TARGET_MT7622) += mt7622/
 obj-$(CONFIG_TARGET_MT7623) += mt7623/
 obj-$(CONFIG_TARGET_MT7629) += mt7629/
+obj-$(CONFIG_TARGET_MT7986) += mt7986/
 obj-$(CONFIG_TARGET_MT8183) += mt8183/
 obj-$(CONFIG_TARGET_MT8516) += mt8516/
 obj-$(CONFIG_TARGET_MT8518) += mt8518/
diff --git a/arch/arm/mach-mediatek/mt7986/Makefile b/arch/arm/mach-mediatek/mt7986/Makefile
new file mode 100644
index 0000000000..007eb4a367
--- /dev/null
+++ b/arch/arm/mach-mediatek/mt7986/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier:	GPL-2.0
+
+obj-y += init.o
+obj-y += lowlevel_init.o
diff --git a/arch/arm/mach-mediatek/mt7986/init.c b/arch/arm/mach-mediatek/mt7986/init.c
new file mode 100644
index 0000000000..0fd459657d
--- /dev/null
+++ b/arch/arm/mach-mediatek/mt7986/init.c
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2022 MediaTek Inc.
+ * Author: Sam Shih <sam.shih@mediatek.com>
+ */
+
+#include <init.h>
+#include <asm/armv8/mmu.h>
+#include <asm/system.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int dram_init(void)
+{
+	gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE, SZ_2G);
+
+	return 0;
+}
+
+void reset_cpu(ulong addr)
+{
+	psci_system_reset();
+}
+
+static struct mm_region mt7986_mem_map[] = {
+	{
+		/* DDR */
+		.virt = 0x40000000UL,
+		.phys = 0x40000000UL,
+		.size = 0x80000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_OUTER_SHARE,
+	}, {
+		.virt = 0x00000000UL,
+		.phys = 0x00000000UL,
+		.size = 0x40000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			 PTE_BLOCK_NON_SHARE |
+			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	}, {
+		0,
+	}
+};
+
+struct mm_region *mem_map = mt7986_mem_map;
diff --git a/arch/arm/mach-mediatek/mt7986/lowlevel_init.S b/arch/arm/mach-mediatek/mt7986/lowlevel_init.S
new file mode 100644
index 0000000000..85a1cea359
--- /dev/null
+++ b/arch/arm/mach-mediatek/mt7986/lowlevel_init.S
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2022 MediaTek Inc.
+ * Author: Sam Shih <sam.shih@mediatek.com>
+ */
+
+/*
+ * Switch from AArch64 EL2 to AArch32 EL2
+ * @param inputs:
+ * x0: argument, zero
+ * x1: machine nr
+ * x2: fdt address
+ * x3: input argument
+ * x4: kernel entry point
+ * @param outputs for secure firmware:
+ * x0: function id
+ * x1: kernel entry point
+ * x2: machine nr
+ * x3: fdt address
+ *
+ * [1] https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/tree/plat/mediatek/common/mtk_sip_svc.c
+*/
+
+.global armv8_el2_to_aarch32
+armv8_el2_to_aarch32:
+	mov	x3, x2
+	mov	x2, x1
+	mov	x1, x4
+	mov	x4, #0
+	ldr	x0, =0x82000200	/* MTK_SIP_KERNEL_BOOT_AARCH32 */
+	SMC	#0
+	ret
-- 
2.17.1


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

* [PATCH v2 02/32] arm: mediatek: add support for MediaTek MT7981 SoC
  2022-08-31 11:00 [PATCH v2 00/32] Add support for MediaTek MT7981/MT7986 SoCs - v2 Weijie Gao
  2022-08-31 11:00 ` [PATCH v2 01/32] arm: mediatek: add support for MediaTek MT7986 SoC Weijie Gao
@ 2022-08-31 11:00 ` Weijie Gao
  2022-08-31 13:46   ` Simon Glass
  2022-08-31 11:00 ` [PATCH v2 03/32] board: mediatek: add MT7986 reference boards Weijie Gao
                   ` (29 subsequent siblings)
  31 siblings, 1 reply; 60+ messages in thread
From: Weijie Gao @ 2022-08-31 11:00 UTC (permalink / raw)
  To: u-boot; +Cc: GSS_MTK_Uboot_upstream, Weijie Gao

This patch adds basic support for MediaTek MT7981 SoC.
This include the file that will initialize the SoC after boot and its
device tree.

Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
---
v2 changes:
  Sort include lines
  Add reference link for armv8_el2_to_aarch32 in lowlevel_init.S
  Remove print_cpuinfo and use cpu driver instead
---
 arch/arm/dts/mt7981.dtsi                      | 293 ++++++++++++++++++
 arch/arm/mach-mediatek/Kconfig                |  13 +-
 arch/arm/mach-mediatek/Makefile               |   1 +
 arch/arm/mach-mediatek/mt7981/Makefile        |   4 +
 arch/arm/mach-mediatek/mt7981/init.c          |  45 +++
 arch/arm/mach-mediatek/mt7981/lowlevel_init.S |  32 ++
 6 files changed, 387 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/dts/mt7981.dtsi
 create mode 100644 arch/arm/mach-mediatek/mt7981/Makefile
 create mode 100644 arch/arm/mach-mediatek/mt7981/init.c
 create mode 100644 arch/arm/mach-mediatek/mt7981/lowlevel_init.S

diff --git a/arch/arm/dts/mt7981.dtsi b/arch/arm/dts/mt7981.dtsi
new file mode 100644
index 0000000000..5d087ad52e
--- /dev/null
+++ b/arch/arm/dts/mt7981.dtsi
@@ -0,0 +1,293 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ * Author: Sam Shih <sam.shih@mediatek.com>
+ */
+
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/mt7981-clk.h>
+#include <dt-bindings/reset/mt7629-reset.h>
+#include <dt-bindings/pinctrl/mt65xx.h>
+
+/ {
+	compatible = "mediatek,mt7981";
+	interrupt-parent = <&gic>;
+	#address-cells = <1>;
+	#size-cells = <1>;
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		cpu0: cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53";
+			reg = <0x0>;
+		};
+		cpu1: cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53";
+			reg = <0x1>;
+		};
+	};
+
+	gpt_clk: gpt_dummy20m {
+		compatible = "fixed-clock";
+		clock-frequency = <13000000>;
+		#clock-cells = <0>;
+		u-boot,dm-pre-reloc;
+	};
+
+	hwver: hwver {
+		compatible = "mediatek,hwver";
+		reg = <0x8000000 0x1000>;
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupt-parent = <&gic>;
+		clock-frequency = <13000000>;
+		interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+		arm,cpu-registers-not-fw-configured;
+	};
+
+	timer0: timer@10008000 {
+		compatible = "mediatek,mt7986-timer";
+		reg = <0x10008000 0x1000>;
+		interrupts = <GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&gpt_clk>;
+		clock-names = "gpt-clk";
+		u-boot,dm-pre-reloc;
+	};
+
+	watchdog: watchdog@1001c000 {
+		compatible = "mediatek,mt7986-wdt";
+		reg = <0x1001c000 0x1000>;
+		interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+		#reset-cells = <1>;
+		status = "disabled";
+	};
+
+	gic: interrupt-controller@c000000 {
+		compatible = "arm,gic-v3";
+		#interrupt-cells = <3>;
+		interrupt-parent = <&gic>;
+		interrupt-controller;
+		reg = <0x0c000000 0x40000>,  /* GICD */
+		      <0x0c080000 0x200000>; /* GICR */
+
+		interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	fixed_plls: apmixedsys@1001e000 {
+		compatible = "mediatek,mt7981-fixed-plls";
+		reg = <0x1001e000 0x1000>;
+		#clock-cells = <1>;
+		u-boot,dm-pre-reloc;
+	};
+
+	topckgen: topckgen@1001b000 {
+		compatible = "mediatek,mt7981-topckgen";
+		reg = <0x1001b000 0x1000>;
+		clock-parent = <&fixed_plls>;
+		#clock-cells = <1>;
+		u-boot,dm-pre-reloc;
+	};
+
+	infracfg_ao: infracfg_ao@10001000 {
+		compatible = "mediatek,mt7981-infracfg_ao";
+		reg = <0x10001000 0x80>;
+		clock-parent = <&infracfg>;
+		#clock-cells = <1>;
+		u-boot,dm-pre-reloc;
+	};
+
+	infracfg: infracfg@10001000 {
+		compatible = "mediatek,mt7981-infracfg";
+		reg = <0x10001000 0x30>;
+		clock-parent = <&topckgen>;
+		#clock-cells = <1>;
+		u-boot,dm-pre-reloc;
+	};
+
+	pinctrl: pinctrl@11d00000 {
+		compatible = "mediatek,mt7981-pinctrl";
+		reg = <0x11d00000 0x1000>,
+		      <0x11c00000 0x1000>,
+		      <0x11c10000 0x1000>,
+		      <0x11d20000 0x1000>,
+		      <0x11e00000 0x1000>,
+		      <0x11e20000 0x1000>,
+		      <0x11f00000 0x1000>,
+		      <0x11f10000 0x1000>,
+		      <0x1000b000 0x1000>;
+		reg-names = "gpio_base", "iocfg_rt_base", "iocfg_rm_base",
+			    "iocfg_rb_base", "iocfg_lb_base", "iocfg_bl_base",
+			    "iocfg_tm_base", "iocfg_tl_base", "eint";
+		gpio: gpio-controller {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+	};
+
+	pwm: pwm@10048000 {
+		compatible = "mediatek,mt7981-pwm";
+		reg = <0x10048000 0x1000>;
+		#clock-cells = <1>;
+		#pwm-cells = <2>;
+		interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&infracfg CK_INFRA_PWM>,
+			 <&infracfg_ao CK_INFRA_PWM_BSEL>,
+			 <&infracfg_ao CK_INFRA_PWM1_CK>,
+			 <&infracfg_ao CK_INFRA_PWM2_CK>,
+			 /* FIXME */
+			 <&infracfg_ao CK_INFRA_PWM2_CK>;
+		assigned-clocks = <&topckgen CK_TOP_PWM_SEL>;
+		assigned-clock-parents = <&topckgen CK_TOP_CB_CKSQ_40M>;
+		clock-names = "top", "main", "pwm1", "pwm2", "pwm3";
+		status = "disabled";
+	};
+
+	uart0: serial@11002000 {
+		compatible = "mediatek,hsuart";
+		reg = <0x11002000 0x400>;
+		interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&infracfg_ao CK_INFRA_UART0_CK>;
+		assigned-clocks = <&topckgen CK_TOP_UART_SEL>,
+				  <&infracfg_ao CK_INFRA_UART0_SEL>;
+		assigned-clock-parents = <&topckgen CK_TOP_CB_CKSQ_40M>,
+					 <&infracfg CK_INFRA_UART>;
+		mediatek,force-highspeed;
+		status = "disabled";
+		u-boot,dm-pre-reloc;
+	};
+
+	uart1: serial@11003000 {
+		compatible = "mediatek,hsuart";
+		reg = <0x11003000 0x400>;
+		interrupts = <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&infracfg_ao CK_INFRA_UART1_CK>;
+		assigned-clocks = <&topckgen CK_TOP_UART_SEL>,
+				  <&infracfg_ao CK_INFRA_UART1_SEL>;
+		assigned-clock-parents = <&topckgen CK_TOP_CB_CKSQ_40M>,
+					 <&infracfg CK_INFRA_UART>;
+		mediatek,force-highspeed;
+		status = "disabled";
+	};
+
+	uart2: serial@11004000 {
+		compatible = "mediatek,hsuart";
+		reg = <0x11004000 0x400>;
+		interrupts = <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&infracfg_ao CK_INFRA_UART2_CK>;
+		assigned-clocks = <&topckgen CK_TOP_UART_SEL>,
+				  <&infracfg_ao CK_INFRA_UART2_SEL>;
+		assigned-clock-parents = <&topckgen CK_TOP_CB_CKSQ_40M>,
+					 <&infracfg CK_INFRA_UART>;
+		mediatek,force-highspeed;
+		status = "disabled";
+	};
+
+	snand: snand@11005000 {
+		compatible = "mediatek,mt7986-snand";
+		reg = <0x11005000 0x1000>,
+		      <0x11006000 0x1000>;
+		reg-names = "nfi", "ecc";
+		clocks = <&infracfg_ao CK_INFRA_SPINFI1_CK>,
+			 <&infracfg_ao CK_INFRA_NFI1_CK>,
+			 <&infracfg_ao CK_INFRA_NFI_HCK_CK>;
+		clock-names = "pad_clk", "nfi_clk", "nfi_hclk";
+		assigned-clocks = <&topckgen CK_TOP_SPINFI_SEL>,
+				  <&topckgen CK_TOP_NFI1X_SEL>;
+		assigned-clock-parents = <&topckgen CK_TOP_CB_M_D8>,
+					 <&topckgen CK_TOP_CB_M_D8>;
+		status = "disabled";
+	};
+
+	ethsys: syscon@15000000 {
+		compatible = "mediatek,mt7981-ethsys", "syscon";
+		reg = <0x15000000 0x1000>;
+		clock-parent = <&topckgen>;
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
+
+	eth: ethernet@15100000 {
+		compatible = "mediatek,mt7981-eth", "syscon";
+		reg = <0x15100000 0x20000>;
+		resets = <&ethsys ETHSYS_FE_RST>;
+		reset-names = "fe";
+		mediatek,ethsys = <&ethsys>;
+		mediatek,sgmiisys = <&sgmiisys0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	sgmiisys0: syscon@10060000 {
+		compatible = "mediatek,mt7986-sgmiisys", "syscon";
+		reg = <0x10060000 0x1000>;
+		pn_swap;
+		#clock-cells = <1>;
+	};
+
+	sgmiisys1: syscon@10070000 {
+		compatible = "mediatek,mt7986-sgmiisys", "syscon";
+		reg = <0x10070000 0x1000>;
+		#clock-cells = <1>;
+	};
+
+	spi0: spi@1100a000 {
+		compatible = "mediatek,ipm-spi";
+		reg = <0x1100a000 0x100>;
+		clocks = <&infracfg_ao CK_INFRA_SPI0_CK>,
+			 <&topckgen CK_TOP_SPI_SEL>;
+		assigned-clocks = <&topckgen CK_TOP_SPI_SEL>,
+				  <&infracfg CK_INFRA_SPI0_SEL>;
+		assigned-clock-parents = <&topckgen CK_TOP_CB_M_D2>,
+					 <&topckgen CK_INFRA_ISPI0>;
+		clock-names = "sel-clk", "spi-clk";
+		interrupts = <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	spi1: spi@1100b000 {
+		compatible = "mediatek,ipm-spi";
+		reg = <0x1100b000 0x100>;
+		interrupts = <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	spi2: spi@11009000 {
+		compatible = "mediatek,ipm-spi";
+		reg = <0x11009000 0x100>;
+		clocks = <&infracfg_ao CK_INFRA_SPI0_CK>,
+			 <&topckgen CK_TOP_SPI_SEL>;
+		assigned-clocks = <&topckgen CK_TOP_SPI_SEL>,
+				  <&infracfg CK_INFRA_SPI0_SEL>;
+		assigned-clock-parents = <&topckgen CK_TOP_CB_M_D2>,
+					 <&topckgen CK_INFRA_ISPI0>;
+		clock-names = "sel-clk", "spi-clk";
+		interrupts = <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	mmc0: mmc@11230000 {
+		compatible = "mediatek,mt7981-mmc";
+		reg = <0x11230000 0x1000>,
+		      <0x11C20000 0x1000>;
+		interrupts = <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&topckgen CK_TOP_EMMC_400M>,
+			 <&topckgen CK_TOP_EMMC_208M>,
+			 <&infracfg_ao CK_INFRA_MSDC_CK>;
+		assigned-clocks = <&topckgen CK_TOP_EMMC_400M_SEL>,
+				  <&topckgen CK_TOP_EMMC_208M_SEL>;
+		assigned-clock-parents = <&topckgen CK_TOP_CB_NET2_D2>,
+					 <&topckgen CK_TOP_CB_M_D2>;
+		clock-names = "source", "hclk", "source_cg";
+		status = "disabled";
+	};
+
+};
diff --git a/arch/arm/mach-mediatek/Kconfig b/arch/arm/mach-mediatek/Kconfig
index 82fadeba8a..04aa2fd97f 100644
--- a/arch/arm/mach-mediatek/Kconfig
+++ b/arch/arm/mach-mediatek/Kconfig
@@ -40,6 +40,15 @@ config TARGET_MT7629
 	  including DDR3, crypto engine, 3x3 11n/ac Wi-Fi, Gigabit Ethernet,
 	  switch, USB3.0, PCIe, UART, SPI, I2C and PWM.
 
+config TARGET_MT7981
+	bool "MediaTek MT7981 SoC"
+	select ARM64
+	select CPU
+	help
+	  The MediaTek MT7981 is a ARM64-based SoC with a dual-core Cortex-A53.
+	  including UART, SPI, USB, NAND, SNFI, PWM, Gigabit Ethernet, I2C,
+          built-in Wi-Fi, and PCIe.
+
 config TARGET_MT7986
 	bool "MediaTek MT7986 SoC"
 	select ARM64
@@ -93,6 +102,7 @@ config SYS_BOARD
 	default "mt7622" if TARGET_MT7622
 	default "mt7623" if TARGET_MT7623
 	default "mt7629" if TARGET_MT7629
+	default "mt7981" if TARGET_MT7981
 	default "mt7986" if TARGET_MT7986
 	default "mt8183" if TARGET_MT8183
 	default "mt8512" if TARGET_MT8512
@@ -109,6 +119,7 @@ config SYS_CONFIG_NAME
 	default "mt7622" if TARGET_MT7622
 	default "mt7623" if TARGET_MT7623
 	default "mt7629" if TARGET_MT7629
+	default "mt7981" if TARGET_MT7981
 	default "mt7986" if TARGET_MT7986
 	default "mt8183" if TARGET_MT8183
 	default "mt8512" if TARGET_MT8512
@@ -124,7 +135,7 @@ config MTK_BROM_HEADER_INFO
 	string
 	default "media=nor" if TARGET_MT8518 || TARGET_MT8512 || TARGET_MT7629 || TARGET_MT7622
 	default "media=emmc" if TARGET_MT8516 || TARGET_MT8365 || TARGET_MT8183
-	default "media=snand;nandinfo=2k+64" if TARGET_MT7986
+	default "media=snand;nandinfo=2k+64" if TARGET_MT7981 || TARGET_MT7986
 	default "lk=1" if TARGET_MT7623
 
 endif
diff --git a/arch/arm/mach-mediatek/Makefile b/arch/arm/mach-mediatek/Makefile
index fe5c3a837c..fc85293f71 100644
--- a/arch/arm/mach-mediatek/Makefile
+++ b/arch/arm/mach-mediatek/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_MT8512) += mt8512/
 obj-$(CONFIG_TARGET_MT7622) += mt7622/
 obj-$(CONFIG_TARGET_MT7623) += mt7623/
 obj-$(CONFIG_TARGET_MT7629) += mt7629/
+obj-$(CONFIG_TARGET_MT7981) += mt7981/
 obj-$(CONFIG_TARGET_MT7986) += mt7986/
 obj-$(CONFIG_TARGET_MT8183) += mt8183/
 obj-$(CONFIG_TARGET_MT8516) += mt8516/
diff --git a/arch/arm/mach-mediatek/mt7981/Makefile b/arch/arm/mach-mediatek/mt7981/Makefile
new file mode 100644
index 0000000000..007eb4a367
--- /dev/null
+++ b/arch/arm/mach-mediatek/mt7981/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier:	GPL-2.0
+
+obj-y += init.o
+obj-y += lowlevel_init.o
diff --git a/arch/arm/mach-mediatek/mt7981/init.c b/arch/arm/mach-mediatek/mt7981/init.c
new file mode 100644
index 0000000000..4f77a3defb
--- /dev/null
+++ b/arch/arm/mach-mediatek/mt7981/init.c
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2022 MediaTek Inc.
+ * Author: Sam Shih <sam.shih@mediatek.com>
+ */
+
+#include <init.h>
+#include <asm/armv8/mmu.h>
+#include <asm/system.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int dram_init(void)
+{
+	gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE, SZ_2G);
+
+	return 0;
+}
+
+void reset_cpu(ulong addr)
+{
+	psci_system_reset();
+}
+
+static struct mm_region mt7981_mem_map[] = {
+	{
+		/* DDR */
+		.virt = 0x40000000UL,
+		.phys = 0x40000000UL,
+		.size = 0x80000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_OUTER_SHARE,
+	}, {
+		.virt = 0x00000000UL,
+		.phys = 0x00000000UL,
+		.size = 0x40000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			 PTE_BLOCK_NON_SHARE |
+			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	}, {
+		0,
+	}
+};
+
+struct mm_region *mem_map = mt7981_mem_map;
diff --git a/arch/arm/mach-mediatek/mt7981/lowlevel_init.S b/arch/arm/mach-mediatek/mt7981/lowlevel_init.S
new file mode 100644
index 0000000000..85a1cea359
--- /dev/null
+++ b/arch/arm/mach-mediatek/mt7981/lowlevel_init.S
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2022 MediaTek Inc.
+ * Author: Sam Shih <sam.shih@mediatek.com>
+ */
+
+/*
+ * Switch from AArch64 EL2 to AArch32 EL2
+ * @param inputs:
+ * x0: argument, zero
+ * x1: machine nr
+ * x2: fdt address
+ * x3: input argument
+ * x4: kernel entry point
+ * @param outputs for secure firmware:
+ * x0: function id
+ * x1: kernel entry point
+ * x2: machine nr
+ * x3: fdt address
+ *
+ * [1] https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/tree/plat/mediatek/common/mtk_sip_svc.c
+*/
+
+.global armv8_el2_to_aarch32
+armv8_el2_to_aarch32:
+	mov	x3, x2
+	mov	x2, x1
+	mov	x1, x4
+	mov	x4, #0
+	ldr	x0, =0x82000200	/* MTK_SIP_KERNEL_BOOT_AARCH32 */
+	SMC	#0
+	ret
-- 
2.17.1


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

* [PATCH v2 03/32] board: mediatek: add MT7986 reference boards
  2022-08-31 11:00 [PATCH v2 00/32] Add support for MediaTek MT7981/MT7986 SoCs - v2 Weijie Gao
  2022-08-31 11:00 ` [PATCH v2 01/32] arm: mediatek: add support for MediaTek MT7986 SoC Weijie Gao
  2022-08-31 11:00 ` [PATCH v2 02/32] arm: mediatek: add support for MediaTek MT7981 SoC Weijie Gao
@ 2022-08-31 11:00 ` Weijie Gao
  2022-08-31 11:00 ` [PATCH v2 04/32] board: mediatek: add MT7981 " Weijie Gao
                   ` (28 subsequent siblings)
  31 siblings, 0 replies; 60+ messages in thread
From: Weijie Gao @ 2022-08-31 11:00 UTC (permalink / raw)
  To: u-boot
  Cc: GSS_MTK_Uboot_upstream, Simon Glass, Marcel Ziswiler,
	Andre Przywara, Fabio Estevam, Samuel Holland, Marek Vasut,
	Ying-Chun Liu (PaulLiu),
	Christian Hewitt, Weijie Gao

Add general board files based on MT7986 SoCs.

MT7986 uses one mmc controller for booting from both SD and eMMC.
Both MT7986A and MT7986B use the same pins for spi controller.

Configs for various boot types:
1. mt7986_rfb_defconfig - SPI-NOR and SPI-NAND for MT7986A/B
2. mt7986a_bpir3_emmc_defconfig - eMMC for MT7986A only
3. mt7986a_bpir3_sd_defconfig - SD for MT7986A only

Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
---
v2 changes:
  Rename mt7986a_emmc_rfb_defconfig to mt7986a_bpir3_emmc_defconfig
  Rename mt7986a_sd_rfb_defconfig to mt7986a_bpir3_sd_defconfig
  Remove mt7986b defconfig
---
 arch/arm/dts/Makefile                |   6 +
 arch/arm/dts/mt7986a-emmc-rfb.dts    |  16 ++
 arch/arm/dts/mt7986a-rfb.dts         | 218 +++++++++++++++++++++++++++
 arch/arm/dts/mt7986a-sd-rfb.dts      | 177 ++++++++++++++++++++++
 arch/arm/dts/mt7986b-emmc-rfb.dts    |  16 ++
 arch/arm/dts/mt7986b-rfb.dts         | 204 +++++++++++++++++++++++++
 arch/arm/dts/mt7986b-sd-rfb.dts      | 173 +++++++++++++++++++++
 board/mediatek/mt7986/MAINTAINERS    |  10 ++
 board/mediatek/mt7986/Makefile       |   3 +
 board/mediatek/mt7986/mt7986_rfb.c   |  10 ++
 configs/mt7986_rfb_defconfig         |  66 ++++++++
 configs/mt7986a_bpir3_emmc_defconfig |  64 ++++++++
 configs/mt7986a_bpir3_sd_defconfig   |  64 ++++++++
 include/configs/mt7986.h             |  26 ++++
 14 files changed, 1053 insertions(+)
 create mode 100644 arch/arm/dts/mt7986a-emmc-rfb.dts
 create mode 100644 arch/arm/dts/mt7986a-rfb.dts
 create mode 100644 arch/arm/dts/mt7986a-sd-rfb.dts
 create mode 100644 arch/arm/dts/mt7986b-emmc-rfb.dts
 create mode 100644 arch/arm/dts/mt7986b-rfb.dts
 create mode 100644 arch/arm/dts/mt7986b-sd-rfb.dts
 create mode 100644 board/mediatek/mt7986/MAINTAINERS
 create mode 100644 board/mediatek/mt7986/Makefile
 create mode 100644 board/mediatek/mt7986/mt7986_rfb.c
 create mode 100644 configs/mt7986_rfb_defconfig
 create mode 100644 configs/mt7986a_bpir3_emmc_defconfig
 create mode 100644 configs/mt7986a_bpir3_sd_defconfig
 create mode 100644 include/configs/mt7986.h

diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 7330121dba..ee86e467f7 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -1230,6 +1230,12 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += \
 	mt7622-bananapi-bpi-r64.dtb \
 	mt7623n-bananapi-bpi-r2.dtb \
 	mt7629-rfb.dtb \
+	mt7986a-rfb.dtb \
+	mt7986b-rfb.dtb \
+	mt7986a-sd-rfb.dtb \
+	mt7986b-sd-rfb.dtb \
+	mt7986a-emmc-rfb.dtb \
+	mt7986b-emmc-rfb.dtb \
 	mt8183-pumpkin.dtb \
 	mt8512-bm1-emmc.dtb \
 	mt8516-pumpkin.dtb \
diff --git a/arch/arm/dts/mt7986a-emmc-rfb.dts b/arch/arm/dts/mt7986a-emmc-rfb.dts
new file mode 100644
index 0000000000..315bdd0b14
--- /dev/null
+++ b/arch/arm/dts/mt7986a-emmc-rfb.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ * Author: Sam Shih <sam.shih@mediatek.com>
+ */
+
+/dts-v1/;
+#include "mt7986a-rfb.dts"
+
+/ {
+	compatible = "mediatek,mt7986", "mediatek,mt7986-rfb",
+		     "mediatek,mt7986-emmc-rfb";
+	bl2_verify {
+		bl2_compatible = "emmc";
+	};
+};
diff --git a/arch/arm/dts/mt7986a-rfb.dts b/arch/arm/dts/mt7986a-rfb.dts
new file mode 100644
index 0000000000..80def57e1a
--- /dev/null
+++ b/arch/arm/dts/mt7986a-rfb.dts
@@ -0,0 +1,218 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ * Author: Sam Shih <sam.shih@mediatek.com>
+ */
+
+/dts-v1/;
+#include "mt7986.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	model = "mt7986-rfb";
+	compatible = "mediatek,mt7986", "mediatek,mt7986-rfb";
+	chosen {
+		stdout-path = &uart0;
+		tick-timer = &timer0;
+	};
+
+	reg_1p8v: regulator-1p8v {
+		compatible = "regulator-fixed";
+		regulator-name = "fixed-1.8V";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
+	reg_3p3v: regulator-3p3v {
+		compatible = "regulator-fixed";
+		regulator-name = "fixed-3.3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_pins>;
+	status = "disabled";
+};
+
+&eth {
+	status = "okay";
+	mediatek,gmac-id = <0>;
+	phy-mode = "sgmii";
+	mediatek,switch = "mt7531";
+	reset-gpios = <&gpio 5 GPIO_ACTIVE_HIGH>;
+
+	fixed-link {
+		speed = <1000>;
+		full-duplex;
+	};
+};
+
+&pinctrl {
+	spi_flash_pins: spi0-pins-func-1 {
+		mux {
+			function = "flash";
+			groups = "spi0", "spi0_wp_hold";
+		};
+
+		conf-pu {
+			pins = "SPI2_CS", "SPI2_HOLD", "SPI2_WP";
+			drive-strength = <MTK_DRIVE_8mA>;
+			bias-pull-up = <MTK_PUPD_SET_R1R0_11>;
+		};
+
+		conf-pd {
+			pins = "SPI2_CLK", "SPI2_MOSI", "SPI2_MISO";
+			drive-strength = <MTK_DRIVE_8mA>;
+			bias-pull-down = <MTK_PUPD_SET_R1R0_11>;
+		};
+	};
+
+	snfi_pins: snfi-pins-func-1 {
+		mux {
+			function = "flash";
+			groups = "snfi";
+		};
+
+		clk {
+			pins = "SPI0_CLK";
+			drive-strength = <MTK_DRIVE_8mA>;
+			bias-pull-down = <MTK_PUPD_SET_R1R0_00>;
+		};
+
+		conf-pu {
+			pins = "SPI0_CS", "SPI0_HOLD", "SPI0_WP";
+			drive-strength = <MTK_DRIVE_6mA>;
+			bias-pull-up = <MTK_PUPD_SET_R1R0_00>;
+		};
+
+		conf-pd {
+			pins = "SPI0_MOSI", "SPI0_MISO";
+			drive-strength = <MTK_DRIVE_6mA>;
+			bias-pull-down = <MTK_PUPD_SET_R1R0_00>;
+		};
+	};
+
+	spic_pins: spi1-pins-func-1 {
+		mux {
+			function = "spi";
+			groups = "spi1_2";
+		};
+	};
+
+	uart1_pins: spi1-pins-func-3 {
+		mux {
+			function = "uart";
+			groups = "uart1_2";
+		};
+	};
+
+	pwm_pins: pwm0-pins-func-1 {
+		mux {
+			function = "pwm";
+			groups = "pwm0";
+		};
+	};
+
+	mmc0_pins_default: mmc0default {
+		mux {
+			function = "flash";
+			groups =  "emmc_51";
+		};
+
+		conf-cmd-dat {
+			pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2",
+			       "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5",
+			       "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD";
+			input-enable;
+			drive-strength = <MTK_DRIVE_4mA>;
+			bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+		};
+
+		conf-clk {
+			pins = "EMMC_CK";
+			drive-strength = <MTK_DRIVE_6mA>;
+			bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+		};
+
+		conf-dsl {
+			pins = "EMMC_DSL";
+			bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+		};
+
+		conf-rst {
+			pins = "EMMC_RSTB";
+			drive-strength = <MTK_DRIVE_4mA>;
+			bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+		};
+	};
+};
+
+&snand {
+	pinctrl-names = "default";
+	pinctrl-0 = <&snfi_pins>;
+	status = "okay";
+	quad-spi;
+};
+
+&spi0 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi_flash_pins>;
+	status = "okay";
+	must_tx;
+	enhance_timing;
+	dma_ext;
+	ipm_design;
+	support_quad;
+	tick_dly = <2>;
+	sample_sel = <0>;
+
+	spi_nor@0 {
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+		spi-max-frequency = <52000000>;
+	};
+
+	spi_nand@1 {
+		compatible = "spi-nand";
+		reg = <1>;
+		spi-max-frequency = <52000000>;
+	};
+};
+
+&pwm {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pwm_pins>;
+	status = "okay";
+};
+
+&watchdog {
+	status = "disabled";
+};
+
+&mmc0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc0_pins_default>;
+	bus-width = <8>;
+	max-frequency = <52000000>;
+	cap-mmc-highspeed;
+	cap-mmc-hw-reset;
+	vmmc-supply = <&reg_3p3v>;
+	vqmmc-supply = <&reg_1p8v>;
+	non-removable;
+	status = "okay";
+};
diff --git a/arch/arm/dts/mt7986a-sd-rfb.dts b/arch/arm/dts/mt7986a-sd-rfb.dts
new file mode 100644
index 0000000000..5807c5d5cc
--- /dev/null
+++ b/arch/arm/dts/mt7986a-sd-rfb.dts
@@ -0,0 +1,177 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ * Author: Sam Shih <sam.shih@mediatek.com>
+ */
+
+/dts-v1/;
+#include "mt7986.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	model = "mt7986-rfb";
+	compatible = "mediatek,mt7986", "mediatek,mt7986-rfb",
+		     "mediatek,mt7986-sd-rfb";
+	chosen {
+		stdout-path = &uart0;
+		tick-timer = &timer0;
+	};
+
+	reg_3p3v: regulator-3p3v {
+		compatible = "regulator-fixed";
+		regulator-name = "fixed-3.3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_pins>;
+	status = "disabled";
+};
+
+&eth {
+	status = "okay";
+	mediatek,gmac-id = <0>;
+	phy-mode = "sgmii";
+	mediatek,switch = "mt7531";
+	reset-gpios = <&gpio 5 GPIO_ACTIVE_HIGH>;
+
+	fixed-link {
+		speed = <1000>;
+		full-duplex;
+	};
+};
+
+&pinctrl {
+	spi_flash_pins: spi0-pins-func-1 {
+		mux {
+			function = "flash";
+			groups = "spi0", "spi0_wp_hold";
+		};
+
+		conf-pu {
+			pins = "SPI2_CS", "SPI2_HOLD", "SPI2_WP";
+			drive-strength = <MTK_DRIVE_8mA>;
+			bias-pull-up = <MTK_PUPD_SET_R1R0_11>;
+		};
+
+		conf-pd {
+			pins = "SPI2_CLK", "SPI2_MOSI", "SPI2_MISO";
+			drive-strength = <MTK_DRIVE_8mA>;
+			bias-pull-down = <MTK_PUPD_SET_R1R0_11>;
+		};
+	};
+
+	spic_pins: spi1-pins-func-1 {
+		mux {
+			function = "spi";
+			groups = "spi1_2";
+		};
+	};
+
+	uart1_pins: spi1-pins-func-3 {
+		mux {
+			function = "uart";
+			groups = "uart1_2";
+		};
+	};
+
+	pwm_pins: pwm0-pins-func-1 {
+		mux {
+			function = "pwm";
+			groups = "pwm0";
+		};
+	};
+
+	mmc0_pins_default: mmc0default {
+		mux {
+			function = "flash";
+			groups =  "emmc_51";
+		};
+
+		conf-cmd-dat {
+			pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2",
+			       "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5",
+			       "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD";
+			input-enable;
+			drive-strength = <MTK_DRIVE_4mA>;
+			bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+		};
+
+		conf-clk {
+			pins = "EMMC_CK";
+			drive-strength = <MTK_DRIVE_6mA>;
+			bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+		};
+
+		conf-dsl {
+			pins = "EMMC_DSL";
+			bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+		};
+
+		conf-rst {
+			pins = "EMMC_RSTB";
+			drive-strength = <MTK_DRIVE_4mA>;
+			bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+		};
+	};
+};
+
+&spi0 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi_flash_pins>;
+	status = "okay";
+	must_tx;
+	enhance_timing;
+	dma_ext;
+	ipm_design;
+	support_quad;
+	tick_dly = <2>;
+	sample_sel = <0>;
+
+	spi_nor@0 {
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+		spi-max-frequency = <52000000>;
+	};
+
+	spi_nand@1 {
+		compatible = "spi-nand";
+		reg = <1>;
+		spi-max-frequency = <52000000>;
+	};
+};
+
+&pwm {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pwm_pins>;
+	status = "okay";
+};
+
+&watchdog {
+	status = "disabled";
+};
+
+&mmc0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc0_pins_default>;
+	bus-width = <4>;
+	max-frequency = <52000000>;
+	cap-sd-highspeed;
+	r_smpl = <1>;
+	vmmc-supply = <&reg_3p3v>;
+	vqmmc-supply = <&reg_3p3v>;
+	status = "okay";
+};
diff --git a/arch/arm/dts/mt7986b-emmc-rfb.dts b/arch/arm/dts/mt7986b-emmc-rfb.dts
new file mode 100644
index 0000000000..315bdd0b14
--- /dev/null
+++ b/arch/arm/dts/mt7986b-emmc-rfb.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ * Author: Sam Shih <sam.shih@mediatek.com>
+ */
+
+/dts-v1/;
+#include "mt7986a-rfb.dts"
+
+/ {
+	compatible = "mediatek,mt7986", "mediatek,mt7986-rfb",
+		     "mediatek,mt7986-emmc-rfb";
+	bl2_verify {
+		bl2_compatible = "emmc";
+	};
+};
diff --git a/arch/arm/dts/mt7986b-rfb.dts b/arch/arm/dts/mt7986b-rfb.dts
new file mode 100644
index 0000000000..0c4e3e878f
--- /dev/null
+++ b/arch/arm/dts/mt7986b-rfb.dts
@@ -0,0 +1,204 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ * Author: Sam Shih <sam.shih@mediatek.com>
+ */
+
+/dts-v1/;
+#include "mt7986.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	model = "mt7986-rfb";
+	compatible = "mediatek,mt7986", "mediatek,mt7986-rfb";
+	chosen {
+		stdout-path = &uart0;
+		tick-timer = &timer0;
+	};
+
+	reg_3p3v: regulator-3p3v {
+		compatible = "regulator-fixed";
+		regulator-name = "fixed-3.3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_pins>;
+	status = "disabled";
+};
+
+&eth {
+	status = "okay";
+	mediatek,gmac-id = <0>;
+	phy-mode = "sgmii";
+	mediatek,switch = "mt7531";
+	reset-gpios = <&gpio 5 GPIO_ACTIVE_HIGH>;
+
+	fixed-link {
+		speed = <1000>;
+		full-duplex;
+	};
+};
+
+&pinctrl {
+	spi_flash_pins: spi0-pins-func-1 {
+		mux {
+			function = "flash";
+			groups = "spi0", "spi0_wp_hold";
+		};
+
+		conf-pu {
+			pins = "SPI2_CS", "SPI2_HOLD", "SPI2_WP";
+			drive-strength = <MTK_DRIVE_8mA>;
+			bias-pull-up = <MTK_PUPD_SET_R1R0_11>;
+		};
+
+		conf-pd {
+			pins = "SPI2_CLK", "SPI2_MOSI", "SPI2_MISO";
+			drive-strength = <MTK_DRIVE_8mA>;
+			bias-pull-down = <MTK_PUPD_SET_R1R0_11>;
+		};
+	};
+
+	snfi_pins: snfi-pins-func-1 {
+		mux {
+			function = "flash";
+			groups = "snfi";
+		};
+
+		clk {
+			pins = "SPI0_CLK";
+			drive-strength = <MTK_DRIVE_8mA>;
+			bias-pull-down = <MTK_PUPD_SET_R1R0_00>;
+		};
+
+		conf-pu {
+			pins = "SPI0_CS", "SPI0_HOLD", "SPI0_WP";
+			drive-strength = <MTK_DRIVE_6mA>;
+			bias-pull-up = <MTK_PUPD_SET_R1R0_00>;
+		};
+
+		conf-pd {
+			pins = "SPI0_MOSI", "SPI0_MISO";
+			drive-strength = <MTK_DRIVE_6mA>;
+			bias-pull-down = <MTK_PUPD_SET_R1R0_00>;
+		};
+	};
+
+	spic_pins: spi1-pins-func-1 {
+		mux {
+			function = "spi";
+			groups = "spi1_2";
+		};
+	};
+
+	uart1_pins: spi1-pins-func-3 {
+		mux {
+			function = "uart";
+			groups = "uart1_2";
+		};
+	};
+
+	pwm_pins: pwm0-pins-func-1 {
+		mux {
+			function = "pwm";
+			groups = "pwm0";
+		};
+	};
+
+	mmc0_pins_default: mmc0default {
+		mux {
+			function = "flash";
+			groups =  "emmc_45";
+			input-schmitt-enable;
+		};
+
+		conf-cmd-dat {
+			pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO",
+			       "SPI0_CS", "SPI0_HOLD", "SPI0_WP",
+			       "SPI1_CLK", "SPI1_MOSI", "SPI1_MISO";
+			input-enable;
+			drive-strength = <MTK_DRIVE_4mA>;
+			bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+		};
+
+		conf-clk {
+			pins = "SPI1_CS";
+			drive-strength = <MTK_DRIVE_6mA>;
+			bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+		};
+
+		conf-rst {
+			pins = "PWM1";
+			drive-strength = <MTK_DRIVE_4mA>;
+			bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+		};
+	};
+};
+
+&snand {
+	pinctrl-names = "default";
+	pinctrl-0 = <&snfi_pins>;
+	status = "okay";
+	quad-spi;
+};
+
+&spi0 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi_flash_pins>;
+	status = "okay";
+	must_tx;
+	enhance_timing;
+	dma_ext;
+	ipm_design;
+	support_quad;
+	tick_dly = <2>;
+	sample_sel = <0>;
+
+	spi_nor@0 {
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+		spi-max-frequency = <52000000>;
+	};
+
+	spi_nand@1 {
+		compatible = "spi-nand";
+		reg = <1>;
+		spi-max-frequency = <52000000>;
+	};
+};
+
+&pwm {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pwm_pins>;
+	status = "okay";
+};
+
+&watchdog {
+	status = "disabled";
+};
+
+&mmc0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc0_pins_default>;
+	bus-width = <8>;
+	max-frequency = <52000000>;
+	cap-mmc-highspeed;
+	cap-mmc-hw-reset;
+	vmmc-supply = <&reg_3p3v>;
+	non-removable;
+	status = "okay";
+};
diff --git a/arch/arm/dts/mt7986b-sd-rfb.dts b/arch/arm/dts/mt7986b-sd-rfb.dts
new file mode 100644
index 0000000000..48f9320e7a
--- /dev/null
+++ b/arch/arm/dts/mt7986b-sd-rfb.dts
@@ -0,0 +1,173 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ * Author: Sam Shih <sam.shih@mediatek.com>
+ */
+
+/dts-v1/;
+#include "mt7986.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	model = "mt7986-rfb";
+	compatible = "mediatek,mt7986", "mediatek,mt7986-rfb",
+		     "mediatek,mt7986-sd-rfb";
+	chosen {
+		stdout-path = &uart0;
+		tick-timer = &timer0;
+	};
+
+	reg_3p3v: regulator-3p3v {
+		compatible = "regulator-fixed";
+		regulator-name = "fixed-3.3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_pins>;
+	status = "disabled";
+};
+
+&eth {
+	status = "okay";
+	mediatek,gmac-id = <0>;
+	phy-mode = "sgmii";
+	mediatek,switch = "mt7531";
+	reset-gpios = <&gpio 5 GPIO_ACTIVE_HIGH>;
+
+	fixed-link {
+		speed = <1000>;
+		full-duplex;
+	};
+};
+
+&pinctrl {
+	spi_flash_pins: spi0-pins-func-1 {
+		mux {
+			function = "flash";
+			groups = "spi0", "spi0_wp_hold";
+		};
+
+		conf-pu {
+			pins = "SPI2_CS", "SPI2_HOLD", "SPI2_WP";
+			drive-strength = <MTK_DRIVE_8mA>;
+			bias-pull-up = <MTK_PUPD_SET_R1R0_11>;
+		};
+
+		conf-pd {
+			pins = "SPI2_CLK", "SPI2_MOSI", "SPI2_MISO";
+			drive-strength = <MTK_DRIVE_8mA>;
+			bias-pull-down = <MTK_PUPD_SET_R1R0_11>;
+		};
+	};
+
+	spic_pins: spi1-pins-func-1 {
+		mux {
+			function = "spi";
+			groups = "spi1_2";
+		};
+	};
+
+	uart1_pins: spi1-pins-func-3 {
+		mux {
+			function = "uart";
+			groups = "uart1_2";
+		};
+	};
+
+	pwm_pins: pwm0-pins-func-1 {
+		mux {
+			function = "pwm";
+			groups = "pwm0";
+		};
+	};
+
+	mmc0_pins_default: mmc0default {
+		mux {
+			function = "flash";
+			groups =  "emmc_45";
+			input-schmitt-enable;
+		};
+
+		conf-cmd-dat {
+			pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO",
+			       "SPI0_CS", "SPI0_HOLD", "SPI0_WP",
+			       "SPI1_CLK", "SPI1_MOSI", "SPI1_MISO";
+			input-enable;
+			drive-strength = <MTK_DRIVE_4mA>;
+			bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+		};
+
+		conf-clk {
+			pins = "SPI1_CS";
+			drive-strength = <MTK_DRIVE_6mA>;
+			bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+		};
+
+		conf-rst {
+			pins = "PWM1";
+			drive-strength = <MTK_DRIVE_4mA>;
+			bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+		};
+	};
+};
+
+&spi0 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi_flash_pins>;
+	status = "okay";
+	must_tx;
+	enhance_timing;
+	dma_ext;
+	ipm_design;
+	support_quad;
+	tick_dly = <2>;
+	sample_sel = <0>;
+
+	spi_nor@0 {
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+		spi-max-frequency = <52000000>;
+	};
+
+	spi_nand@1 {
+		compatible = "spi-nand";
+		reg = <1>;
+		spi-max-frequency = <52000000>;
+	};
+};
+
+&pwm {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pwm_pins>;
+	status = "okay";
+};
+
+&watchdog {
+	status = "disabled";
+};
+
+&mmc0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc0_pins_default>;
+	bus-width = <4>;
+	max-frequency = <52000000>;
+	cap-sd-highspeed;
+	r_smpl = <1>;
+	vmmc-supply = <&reg_3p3v>;
+	vqmmc-supply = <&reg_3p3v>;
+	status = "okay";
+};
diff --git a/board/mediatek/mt7986/MAINTAINERS b/board/mediatek/mt7986/MAINTAINERS
new file mode 100644
index 0000000000..fddee20001
--- /dev/null
+++ b/board/mediatek/mt7986/MAINTAINERS
@@ -0,0 +1,10 @@
+MT7986
+M:	Sam Shih <sam.shih@mediatek.com>
+S:	Maintained
+F:	board/mediatek/mt7986
+F:	include/configs/mt7986.h
+F:	configs/mt7986_rfb_defconfig
+F:	configs/mt7986a_emmc_rfb_defconfig
+F:	configs/mt7986a_sd_rfb_defconfig
+F:	configs/mt7986b_emmc_rfb_defconfig
+F:	configs/mt7986b_sd_rfb_defconfig
diff --git a/board/mediatek/mt7986/Makefile b/board/mediatek/mt7986/Makefile
new file mode 100644
index 0000000000..7bb84fa2f4
--- /dev/null
+++ b/board/mediatek/mt7986/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier:	GPL-2.0
+
+obj-y	+= mt7986_rfb.o
diff --git a/board/mediatek/mt7986/mt7986_rfb.c b/board/mediatek/mt7986/mt7986_rfb.c
new file mode 100644
index 0000000000..846c715ca0
--- /dev/null
+++ b/board/mediatek/mt7986/mt7986_rfb.c
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2022 MediaTek Inc.
+ * Author: Sam Shih <sam.shih@mediatek.com>
+ */
+
+int board_init(void)
+{
+	return 0;
+}
diff --git a/configs/mt7986_rfb_defconfig b/configs/mt7986_rfb_defconfig
new file mode 100644
index 0000000000..ff1e63b6bd
--- /dev/null
+++ b/configs/mt7986_rfb_defconfig
@@ -0,0 +1,66 @@
+CONFIG_ARM=y
+CONFIG_POSITION_INDEPENDENT=y
+CONFIG_ARCH_MEDIATEK=y
+CONFIG_SYS_TEXT_BASE=0x41e00000
+CONFIG_SYS_MALLOC_F_LEN=0x4000
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_DEFAULT_DEVICE_TREE="mt7986a-rfb"
+CONFIG_TARGET_MT7986=y
+CONFIG_DEBUG_UART_BASE=0x11002000
+CONFIG_DEBUG_UART_CLOCK=40000000
+CONFIG_SYS_LOAD_ADDR=0x46000000
+CONFIG_DEBUG_UART=y
+# CONFIG_AUTOBOOT is not set
+CONFIG_DEFAULT_FDT_FILE="mt7986a-rfb"
+CONFIG_LOGLEVEL=7
+CONFIG_LOG=y
+CONFIG_SYS_PROMPT="MT7986> "
+CONFIG_SYS_CBSIZE=512
+CONFIG_SYS_PBSIZE=1049
+# CONFIG_BOOTM_NETBSD is not set
+# CONFIG_BOOTM_PLAN9 is not set
+# CONFIG_BOOTM_RTEMS is not set
+# CONFIG_BOOTM_VXWORKS is not set
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_UNLZ4 is not set
+# CONFIG_CMD_UNZIP is not set
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_MTD=y
+CONFIG_CMD_SF_TEST=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_SMC=y
+CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_CLK=y
+# CONFIG_MMC is not set
+CONFIG_MTD=y
+CONFIG_DM_MTD=y
+CONFIG_MTD_SPI_NAND=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH_SFDP_SUPPORT=y
+CONFIG_SPI_FLASH_EON=y
+CONFIG_SPI_FLASH_GIGADEVICE=y
+CONFIG_SPI_FLASH_ISSI=y
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_SPI_FLASH_XMC=y
+CONFIG_SPI_FLASH_XTX=y
+CONFIG_SPI_FLASH_MTD=y
+CONFIG_PHY_FIXED=y
+CONFIG_DM_ETH=y
+CONFIG_MEDIATEK_ETH=y
+CONFIG_PINCTRL=y
+CONFIG_PINCONF=y
+CONFIG_PINCTRL_MT7986=y
+CONFIG_POWER_DOMAIN=y
+CONFIG_MTK_POWER_DOMAIN=y
+CONFIG_DM_SERIAL=y
+CONFIG_MTK_SERIAL=y
+CONFIG_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_MTK_SPIM=y
+CONFIG_HEXDUMP=y
diff --git a/configs/mt7986a_bpir3_emmc_defconfig b/configs/mt7986a_bpir3_emmc_defconfig
new file mode 100644
index 0000000000..3e368b68de
--- /dev/null
+++ b/configs/mt7986a_bpir3_emmc_defconfig
@@ -0,0 +1,64 @@
+CONFIG_ARM=y
+CONFIG_POSITION_INDEPENDENT=y
+CONFIG_ARCH_MEDIATEK=y
+CONFIG_SYS_TEXT_BASE=0x41e00000
+CONFIG_SYS_MALLOC_F_LEN=0x4000
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_ENV_SIZE=0x80000
+CONFIG_ENV_OFFSET=0x300000
+CONFIG_DEFAULT_DEVICE_TREE="mt7986a-emmc-rfb"
+CONFIG_TARGET_MT7986=y
+CONFIG_DEBUG_UART_BASE=0x11002000
+CONFIG_DEBUG_UART_CLOCK=40000000
+CONFIG_SYS_LOAD_ADDR=0x46000000
+CONFIG_DEBUG_UART=y
+# CONFIG_AUTOBOOT is not set
+CONFIG_DEFAULT_FDT_FILE="mt7986a-emmc-rfb"
+CONFIG_LOGLEVEL=7
+CONFIG_LOG=y
+CONFIG_SYS_PROMPT="MT7986> "
+CONFIG_SYS_CBSIZE=512
+CONFIG_SYS_PBSIZE=1049
+# CONFIG_BOOTM_NETBSD is not set
+# CONFIG_BOOTM_PLAN9 is not set
+# CONFIG_BOOTM_RTEMS is not set
+# CONFIG_BOOTM_VXWORKS is not set
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_UNLZ4 is not set
+# CONFIG_CMD_UNZIP is not set
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_GPT=y
+CONFIG_CMD_GPT_RENAME=y
+CONFIG_CMD_LSBLK=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_PART=y
+CONFIG_CMD_READ=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_SMC=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_PARTITION_TYPE_GUID=y
+CONFIG_ENV_OVERWRITE=y
+CONFIG_ENV_IS_IN_MMC=y
+CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_CLK=y
+CONFIG_MMC_HS200_SUPPORT=y
+CONFIG_MMC_MTK=y
+CONFIG_PHY_FIXED=y
+CONFIG_DM_ETH=y
+CONFIG_MEDIATEK_ETH=y
+CONFIG_PINCTRL=y
+CONFIG_PINCONF=y
+CONFIG_PINCTRL_MT7986=y
+CONFIG_POWER_DOMAIN=y
+CONFIG_MTK_POWER_DOMAIN=y
+CONFIG_DM_REGULATOR=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_DM_SERIAL=y
+CONFIG_MTK_SERIAL=y
+CONFIG_FAT_WRITE=y
+CONFIG_HEXDUMP=y
+# CONFIG_EFI_LOADER is not set
diff --git a/configs/mt7986a_bpir3_sd_defconfig b/configs/mt7986a_bpir3_sd_defconfig
new file mode 100644
index 0000000000..b9a69a3d3d
--- /dev/null
+++ b/configs/mt7986a_bpir3_sd_defconfig
@@ -0,0 +1,64 @@
+CONFIG_ARM=y
+CONFIG_POSITION_INDEPENDENT=y
+CONFIG_ARCH_MEDIATEK=y
+CONFIG_SYS_TEXT_BASE=0x41e00000
+CONFIG_SYS_MALLOC_F_LEN=0x4000
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_ENV_SIZE=0x80000
+CONFIG_ENV_OFFSET=0x300000
+CONFIG_DEFAULT_DEVICE_TREE="mt7986a-sd-rfb"
+CONFIG_TARGET_MT7986=y
+CONFIG_DEBUG_UART_BASE=0x11002000
+CONFIG_DEBUG_UART_CLOCK=40000000
+CONFIG_SYS_LOAD_ADDR=0x46000000
+CONFIG_DEBUG_UART=y
+# CONFIG_AUTOBOOT is not set
+CONFIG_DEFAULT_FDT_FILE="mt7986a-sd-rfb"
+CONFIG_LOGLEVEL=7
+CONFIG_LOG=y
+CONFIG_SYS_PROMPT="MT7986> "
+CONFIG_SYS_CBSIZE=512
+CONFIG_SYS_PBSIZE=1049
+# CONFIG_BOOTM_NETBSD is not set
+# CONFIG_BOOTM_PLAN9 is not set
+# CONFIG_BOOTM_RTEMS is not set
+# CONFIG_BOOTM_VXWORKS is not set
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_UNLZ4 is not set
+# CONFIG_CMD_UNZIP is not set
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_GPT=y
+CONFIG_CMD_GPT_RENAME=y
+CONFIG_CMD_LSBLK=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_PART=y
+CONFIG_CMD_READ=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_SMC=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_PARTITION_TYPE_GUID=y
+CONFIG_ENV_OVERWRITE=y
+CONFIG_ENV_IS_IN_MMC=y
+CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_CLK=y
+CONFIG_MMC_HS200_SUPPORT=y
+CONFIG_MMC_MTK=y
+CONFIG_PHY_FIXED=y
+CONFIG_DM_ETH=y
+CONFIG_MEDIATEK_ETH=y
+CONFIG_PINCTRL=y
+CONFIG_PINCONF=y
+CONFIG_PINCTRL_MT7986=y
+CONFIG_POWER_DOMAIN=y
+CONFIG_MTK_POWER_DOMAIN=y
+CONFIG_DM_REGULATOR=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_DM_SERIAL=y
+CONFIG_MTK_SERIAL=y
+CONFIG_FAT_WRITE=y
+CONFIG_HEXDUMP=y
+# CONFIG_EFI_LOADER is not set
diff --git a/include/configs/mt7986.h b/include/configs/mt7986.h
new file mode 100644
index 0000000000..b28fc0f613
--- /dev/null
+++ b/include/configs/mt7986.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Configuration for MediaTek MT7986 SoC
+ *
+ * Copyright (C) 2022 MediaTek Inc.
+ * Author: Sam Shih <sam.shih@mediatek.com>
+ */
+
+#ifndef __MT7986_H
+#define __MT7986_H
+
+#include <linux/sizes.h>
+
+#define CONFIG_SYS_NONCACHED_MEMORY	SZ_1M
+#define CONFIG_SYS_MMC_ENV_DEV		0
+
+/* Uboot definition */
+#define CONFIG_SYS_UBOOT_BASE		CONFIG_SYS_TEXT_BASE
+
+/* SPL -> Uboot */
+#define CONFIG_SYS_UBOOT_START		CONFIG_SYS_TEXT_BASE
+
+/* DRAM */
+#define CONFIG_SYS_SDRAM_BASE		0x40000000
+
+#endif
-- 
2.17.1


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

* [PATCH v2 04/32] board: mediatek: add MT7981 reference boards
  2022-08-31 11:00 [PATCH v2 00/32] Add support for MediaTek MT7981/MT7986 SoCs - v2 Weijie Gao
                   ` (2 preceding siblings ...)
  2022-08-31 11:00 ` [PATCH v2 03/32] board: mediatek: add MT7986 reference boards Weijie Gao
@ 2022-08-31 11:00 ` Weijie Gao
  2022-08-31 13:46   ` Simon Glass
  2022-08-31 11:04 ` [PATCH v2 05/32] mmc: mediatek: add support for MediaTek MT7891/MT7986 SoCs Weijie Gao
                   ` (27 subsequent siblings)
  31 siblings, 1 reply; 60+ messages in thread
From: Weijie Gao @ 2022-08-31 11:00 UTC (permalink / raw)
  To: u-boot
  Cc: GSS_MTK_Uboot_upstream, Simon Glass, Marcel Ziswiler,
	Andre Przywara, Fabio Estevam, Samuel Holland, Marek Vasut,
	Ying-Chun Liu (PaulLiu),
	Christian Hewitt, Weijie Gao

This patch adds general board files based on MT7981 SoCs.

MT7981 uses one mmc controller for booting from both SD and eMMC, and the
pins of mmc controller are also shared with spi controller.
So three configs are need for these boot types:

1. mt7981_rfb_defconfig - SPI-NOR and SPI-NAND
2. mt7981_emmc_rfb_defconfig - eMMC only
3. mt7981_sd_rfb_defconfig - SD only

Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
---
v2 changes:
  Remove mt7981_spim_nand_rfb_defconfig and mt7981_spim_nor_rfb_defconfig
---
 arch/arm/dts/Makefile              |   3 +
 arch/arm/dts/mt7981-emmc-rfb.dts   | 139 +++++++++++++++++++++++
 arch/arm/dts/mt7981-rfb.dts        | 173 +++++++++++++++++++++++++++++
 arch/arm/dts/mt7981-sd-rfb.dts     | 139 +++++++++++++++++++++++
 board/mediatek/mt7981/MAINTAINERS  |  10 ++
 board/mediatek/mt7981/Makefile     |   3 +
 board/mediatek/mt7981/mt7981_rfb.c |  10 ++
 configs/mt7981_emmc_rfb_defconfig  |  64 +++++++++++
 configs/mt7981_rfb_defconfig       |  69 ++++++++++++
 configs/mt7981_sd_rfb_defconfig    |  64 +++++++++++
 include/configs/mt7981.h           |  26 +++++
 11 files changed, 700 insertions(+)
 create mode 100644 arch/arm/dts/mt7981-emmc-rfb.dts
 create mode 100644 arch/arm/dts/mt7981-rfb.dts
 create mode 100644 arch/arm/dts/mt7981-sd-rfb.dts
 create mode 100644 board/mediatek/mt7981/MAINTAINERS
 create mode 100644 board/mediatek/mt7981/Makefile
 create mode 100644 board/mediatek/mt7981/mt7981_rfb.c
 create mode 100644 configs/mt7981_emmc_rfb_defconfig
 create mode 100644 configs/mt7981_rfb_defconfig
 create mode 100644 configs/mt7981_sd_rfb_defconfig
 create mode 100644 include/configs/mt7981.h

diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index ee86e467f7..3436b20917 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -1230,6 +1230,9 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += \
 	mt7622-bananapi-bpi-r64.dtb \
 	mt7623n-bananapi-bpi-r2.dtb \
 	mt7629-rfb.dtb \
+	mt7981-rfb.dtb \
+	mt7981-emmc-rfb.dtb \
+	mt7981-sd-rfb.dtb \
 	mt7986a-rfb.dtb \
 	mt7986b-rfb.dtb \
 	mt7986a-sd-rfb.dtb \
diff --git a/arch/arm/dts/mt7981-emmc-rfb.dts b/arch/arm/dts/mt7981-emmc-rfb.dts
new file mode 100644
index 0000000000..2b7eae99ce
--- /dev/null
+++ b/arch/arm/dts/mt7981-emmc-rfb.dts
@@ -0,0 +1,139 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ * Author: Sam Shih <sam.shih@mediatek.com>
+ */
+
+/dts-v1/;
+#include "mt7981.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	model = "mt7981-rfb";
+	compatible = "mediatek,mt7981", "mediatek,mt7981-rfb";
+	chosen {
+		stdout-path = &uart0;
+		tick-timer = &timer0;
+	};
+
+	reg_3p3v: regulator-3p3v {
+		  compatible = "regulator-fixed";
+		  regulator-name = "fixed-3.3V";
+		  regulator-min-microvolt = <3300000>;
+		  regulator-max-microvolt = <3300000>;
+		  regulator-boot-on;
+		  regulator-always-on;
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_pins>;
+	status = "disabled";
+};
+
+&eth {
+	status = "okay";
+	mediatek,gmac-id = <0>;
+	phy-mode = "sgmii";
+	mediatek,switch = "mt7531";
+	reset-gpios = <&gpio 39 GPIO_ACTIVE_HIGH>;
+
+	fixed-link {
+		speed = <1000>;
+		full-duplex;
+	};
+};
+
+&pinctrl {
+	spic_pins: spi1-pins-func-1 {
+		mux {
+			function = "spi";
+			groups = "spi1_1";
+		};
+	};
+
+	uart1_pins: spi1-pins-func-3 {
+		mux {
+			function = "uart";
+			groups = "uart1_2";
+		};
+	};
+
+	/* pin15 as pwm0 */
+	one_pwm_pins: one-pwm-pins {
+		mux {
+			function = "pwm";
+			groups = "pwm0_1";
+		};
+	};
+
+	/* pin15 as pwm0 and pin14 as pwm1 */
+	two_pwm_pins: two-pwm-pins {
+		mux {
+			function = "pwm";
+			groups = "pwm0_1", "pwm1_0";
+		};
+	};
+
+	/* pin15 as pwm0, pin14 as pwm1, pin7 as pwm2 */
+	three_pwm_pins: three-pwm-pins {
+		mux {
+			function = "pwm";
+			groups = "pwm0_1", "pwm1_0", "pwm2";
+		};
+	};
+
+	mmc0_pins_default: mmc0default {
+		mux {
+			function = "flash";
+			groups =  "emmc_45";
+		};
+		conf-cmd-dat {
+			pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO",
+				"SPI0_CS",  "SPI0_HOLD", "SPI0_WP",
+				"SPI1_CLK", "SPI1_MOSI", "SPI1_MISO";
+			input-enable;
+			drive-strength = <MTK_DRIVE_4mA>;
+			bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+		};
+		conf-clk {
+			pins = "SPI1_CS";
+			drive-strength = <MTK_DRIVE_6mA>;
+			bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+		};
+		conf-rst {
+			pins = "PWM0";
+			drive-strength = <MTK_DRIVE_4mA>;
+			bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+		};
+	};
+};
+
+&pwm {
+	pinctrl-names = "default";
+	pinctrl-0 = <&two_pwm_pins>;
+	status = "okay";
+};
+
+&watchdog {
+	status = "disabled";
+};
+
+&mmc0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc0_pins_default>;
+	bus-width = <8>;
+	max-frequency = <52000000>;
+	cap-mmc-highspeed;
+	cap-mmc-hw-reset;
+	vmmc-supply = <&reg_3p3v>;
+	non-removable;
+	status = "okay";
+};
diff --git a/arch/arm/dts/mt7981-rfb.dts b/arch/arm/dts/mt7981-rfb.dts
new file mode 100644
index 0000000000..5559ace953
--- /dev/null
+++ b/arch/arm/dts/mt7981-rfb.dts
@@ -0,0 +1,173 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ * Author: Sam Shih <sam.shih@mediatek.com>
+ */
+
+/dts-v1/;
+#include "mt7981.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	model = "mt7981-rfb";
+	compatible = "mediatek,mt7981", "mediatek,mt7981-rfb";
+	chosen {
+		stdout-path = &uart0;
+		tick-timer = &timer0;
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_pins>;
+	status = "disabled";
+};
+
+&eth {
+	status = "okay";
+	mediatek,gmac-id = <0>;
+	phy-mode = "sgmii";
+	mediatek,switch = "mt7531";
+	reset-gpios = <&gpio 39 GPIO_ACTIVE_HIGH>;
+
+	fixed-link {
+		speed = <1000>;
+		full-duplex;
+	};
+};
+
+&pinctrl {
+	spi_flash_pins: spi0-pins-func-1 {
+		mux {
+			function = "flash";
+			groups = "spi0", "spi0_wp_hold";
+		};
+
+		conf-pu {
+			pins = "SPI0_CS", "SPI0_HOLD", "SPI0_WP";
+			drive-strength = <MTK_DRIVE_8mA>;
+			bias-pull-up = <MTK_PUPD_SET_R1R0_11>;
+		};
+
+		conf-pd {
+			pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO";
+			drive-strength = <MTK_DRIVE_8mA>;
+			bias-pull-down = <MTK_PUPD_SET_R1R0_11>;
+		};
+	};
+
+	spi2_flash_pins: spi2-spi2-pins {
+		mux {
+			function = "spi";
+			groups = "spi2", "spi2_wp_hold";
+		};
+
+		conf-pu {
+			pins = "SPI2_CS", "SPI2_HOLD", "SPI2_WP";
+			drive-strength = <MTK_DRIVE_8mA>;
+			bias-pull-down = <MTK_PUPD_SET_R1R0_00>;
+		};
+
+		conf-pd {
+			pins = "SPI2_CLK", "SPI2_MOSI", "SPI2_MISO";
+			drive-strength = <MTK_DRIVE_8mA>;
+			bias-pull-down = <MTK_PUPD_SET_R1R0_00>;
+		};
+	};
+
+	spic_pins: spi1-pins-func-1 {
+		mux {
+			function = "spi";
+			groups = "spi1_1";
+		};
+	};
+
+	uart1_pins: spi1-pins-func-3 {
+		mux {
+			function = "uart";
+			groups = "uart1_2";
+		};
+	};
+
+	/* pin15 as pwm0 */
+	one_pwm_pins: one-pwm-pins {
+		mux {
+			function = "pwm";
+			groups = "pwm0_1";
+		};
+	};
+
+	/* pin15 as pwm0 and pin14 as pwm1 */
+	two_pwm_pins: two-pwm-pins {
+		mux {
+			function = "pwm";
+			groups = "pwm0_1", "pwm1_0";
+		};
+	};
+
+	/* pin15 as pwm0, pin14 as pwm1, pin7 as pwm2 */
+	three_pwm_pins: three-pwm-pins {
+		mux {
+			function = "pwm";
+			groups = "pwm0_1", "pwm1_0", "pwm2";
+		};
+	};
+};
+
+&spi0 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi_flash_pins>;
+	status = "okay";
+	must_tx;
+	enhance_timing;
+	dma_ext;
+	ipm_design;
+	support_quad;
+	tick_dly = <2>;
+	sample_sel = <0>;
+
+	spi_nand@0 {
+		compatible = "spi-nand";
+		reg = <0>;
+		spi-max-frequency = <52000000>;
+	};
+};
+
+&spi2 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi2_flash_pins>;
+	status = "okay";
+	must_tx;
+	enhance_timing;
+	dma_ext;
+	ipm_design;
+	support_quad;
+	tick_dly = <2>;
+	sample_sel = <0>;
+
+	spi_nor@0 {
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+		spi-max-frequency = <52000000>;
+	};
+};
+
+&pwm {
+	pinctrl-names = "default";
+	pinctrl-0 = <&two_pwm_pins>;
+	status = "okay";
+};
+
+&watchdog {
+	status = "disabled";
+};
diff --git a/arch/arm/dts/mt7981-sd-rfb.dts b/arch/arm/dts/mt7981-sd-rfb.dts
new file mode 100644
index 0000000000..34ac227ecf
--- /dev/null
+++ b/arch/arm/dts/mt7981-sd-rfb.dts
@@ -0,0 +1,139 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ * Author: Sam Shih <sam.shih@mediatek.com>
+ */
+
+/dts-v1/;
+#include "mt7981.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	model = "mt7981-rfb";
+	compatible = "mediatek,mt7981", "mediatek,mt7981-sd-rfb";
+	chosen {
+		stdout-path = &uart0;
+		tick-timer = &timer0;
+	};
+
+	reg_3p3v: regulator-3p3v {
+		  compatible = "regulator-fixed";
+		  regulator-name = "fixed-3.3V";
+		  regulator-min-microvolt = <3300000>;
+		  regulator-max-microvolt = <3300000>;
+		  regulator-boot-on;
+		  regulator-always-on;
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_pins>;
+	status = "disabled";
+};
+
+&eth {
+	status = "okay";
+	mediatek,gmac-id = <0>;
+	phy-mode = "sgmii";
+	mediatek,switch = "mt7531";
+	reset-gpios = <&gpio 39 GPIO_ACTIVE_HIGH>;
+
+	fixed-link {
+		speed = <1000>;
+		full-duplex;
+	};
+};
+
+&pinctrl {
+	spic_pins: spi1-pins-func-1 {
+		mux {
+			function = "spi";
+			groups = "spi1_1";
+		};
+	};
+
+	uart1_pins: spi1-pins-func-3 {
+		mux {
+			function = "uart";
+			groups = "uart1_2";
+		};
+	};
+
+	/* pin15 as pwm0 */
+	one_pwm_pins: one-pwm-pins {
+		mux {
+			function = "pwm";
+			groups = "pwm0_1";
+		};
+	};
+
+	/* pin15 as pwm0 and pin14 as pwm1 */
+	two_pwm_pins: two-pwm-pins {
+		mux {
+			function = "pwm";
+			groups = "pwm0_1", "pwm1_0";
+		};
+	};
+
+	/* pin15 as pwm0, pin14 as pwm1, pin7 as pwm2 */
+	three_pwm_pins: three-pwm-pins {
+		mux {
+			function = "pwm";
+			groups = "pwm0_1", "pwm1_0", "pwm2";
+		};
+	};
+
+	mmc0_pins_default: mmc0default {
+		mux {
+			function = "flash";
+			groups =  "emmc_45";
+		};
+		conf-cmd-dat {
+			pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO",
+				"SPI0_CS",  "SPI0_HOLD", "SPI0_WP",
+				"SPI1_CLK", "SPI1_MOSI", "SPI1_MISO";
+			input-enable;
+			drive-strength = <MTK_DRIVE_4mA>;
+			bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+		};
+		conf-clk {
+			pins = "SPI1_CS";
+			drive-strength = <MTK_DRIVE_6mA>;
+			bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+		};
+		conf-rst {
+			pins = "PWM0";
+			drive-strength = <MTK_DRIVE_4mA>;
+			bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+		};
+	};
+};
+
+&pwm {
+	pinctrl-names = "default";
+	pinctrl-0 = <&two_pwm_pins>;
+	status = "okay";
+};
+
+&watchdog {
+	status = "disabled";
+};
+
+&mmc0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc0_pins_default>;
+	bus-width = <4>;
+	max-frequency = <52000000>;
+	cap-sd-highspeed;
+	r_smpl = <0>;
+	vmmc-supply = <&reg_3p3v>;
+	vqmmc-supply = <&reg_3p3v>;
+	status = "okay";
+};
diff --git a/board/mediatek/mt7981/MAINTAINERS b/board/mediatek/mt7981/MAINTAINERS
new file mode 100644
index 0000000000..e7592a7a54
--- /dev/null
+++ b/board/mediatek/mt7981/MAINTAINERS
@@ -0,0 +1,10 @@
+MT7981
+M:	Sam Shih <sam.shih@mediatek.com>
+S:	Maintained
+F:	board/mediatek/mt7981
+F:	include/configs/mt7981.h
+F:	configs/mt7981_emmc_rfb_defconfig
+F:	configs/mt7981_rfb_defconfig
+F:	configs/mt7981_sd_rfb_defconfig
+F:	configs/mt7981_spim_nand_rfb_defconfig
+F:	configs/mt7981_spim_nor_rfb_defconfig
diff --git a/board/mediatek/mt7981/Makefile b/board/mediatek/mt7981/Makefile
new file mode 100644
index 0000000000..fa5990ffb2
--- /dev/null
+++ b/board/mediatek/mt7981/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier:	GPL-2.0
+
+obj-y	+= mt7981_rfb.o
diff --git a/board/mediatek/mt7981/mt7981_rfb.c b/board/mediatek/mt7981/mt7981_rfb.c
new file mode 100644
index 0000000000..846c715ca0
--- /dev/null
+++ b/board/mediatek/mt7981/mt7981_rfb.c
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2022 MediaTek Inc.
+ * Author: Sam Shih <sam.shih@mediatek.com>
+ */
+
+int board_init(void)
+{
+	return 0;
+}
diff --git a/configs/mt7981_emmc_rfb_defconfig b/configs/mt7981_emmc_rfb_defconfig
new file mode 100644
index 0000000000..5f9f6d8582
--- /dev/null
+++ b/configs/mt7981_emmc_rfb_defconfig
@@ -0,0 +1,64 @@
+CONFIG_ARM=y
+CONFIG_POSITION_INDEPENDENT=y
+CONFIG_ARCH_MEDIATEK=y
+CONFIG_SYS_TEXT_BASE=0x41e00000
+CONFIG_SYS_MALLOC_F_LEN=0x4000
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_ENV_SIZE=0x80000
+CONFIG_ENV_OFFSET=0x300000
+CONFIG_DEFAULT_DEVICE_TREE="mt7981-emmc-rfb"
+CONFIG_TARGET_MT7981=y
+CONFIG_DEBUG_UART_BASE=0x11002000
+CONFIG_DEBUG_UART_CLOCK=40000000
+CONFIG_SYS_LOAD_ADDR=0x46000000
+CONFIG_DEBUG_UART=y
+# CONFIG_AUTOBOOT is not set
+CONFIG_DEFAULT_FDT_FILE="mt7981-emmc-rfb"
+CONFIG_LOGLEVEL=7
+CONFIG_LOG=y
+CONFIG_SYS_PROMPT="MT7981> "
+CONFIG_SYS_CBSIZE=512
+CONFIG_SYS_PBSIZE=1049
+# CONFIG_BOOTM_NETBSD is not set
+# CONFIG_BOOTM_PLAN9 is not set
+# CONFIG_BOOTM_RTEMS is not set
+# CONFIG_BOOTM_VXWORKS is not set
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_UNLZ4 is not set
+# CONFIG_CMD_UNZIP is not set
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_GPT=y
+CONFIG_CMD_GPT_RENAME=y
+CONFIG_CMD_LSBLK=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_PART=y
+CONFIG_CMD_READ=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_SMC=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_PARTITION_TYPE_GUID=y
+CONFIG_ENV_OVERWRITE=y
+CONFIG_ENV_IS_IN_MMC=y
+CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_CLK=y
+CONFIG_MMC_HS200_SUPPORT=y
+CONFIG_MMC_MTK=y
+CONFIG_PHY_FIXED=y
+CONFIG_DM_ETH=y
+CONFIG_MEDIATEK_ETH=y
+CONFIG_PINCTRL=y
+CONFIG_PINCONF=y
+CONFIG_PINCTRL_MT7981=y
+CONFIG_POWER_DOMAIN=y
+CONFIG_MTK_POWER_DOMAIN=y
+CONFIG_DM_REGULATOR=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_DM_SERIAL=y
+CONFIG_MTK_SERIAL=y
+CONFIG_FAT_WRITE=y
+CONFIG_HEXDUMP=y
+# CONFIG_EFI_LOADER is not set
diff --git a/configs/mt7981_rfb_defconfig b/configs/mt7981_rfb_defconfig
new file mode 100644
index 0000000000..88299e3e51
--- /dev/null
+++ b/configs/mt7981_rfb_defconfig
@@ -0,0 +1,69 @@
+CONFIG_ARM=y
+CONFIG_POSITION_INDEPENDENT=y
+CONFIG_ARCH_MEDIATEK=y
+CONFIG_SYS_TEXT_BASE=0x41e00000
+CONFIG_SYS_MALLOC_F_LEN=0x4000
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_DEFAULT_DEVICE_TREE="mt7981-rfb"
+CONFIG_TARGET_MT7981=y
+CONFIG_DEBUG_UART_BASE=0x11002000
+CONFIG_DEBUG_UART_CLOCK=40000000
+CONFIG_SYS_LOAD_ADDR=0x46000000
+CONFIG_DEBUG_UART=y
+# CONFIG_AUTOBOOT is not set
+CONFIG_DEFAULT_FDT_FILE="mt7981-rfb"
+CONFIG_LOGLEVEL=7
+CONFIG_LOG=y
+CONFIG_SYS_PROMPT="MT7981> "
+CONFIG_SYS_CBSIZE=512
+CONFIG_SYS_PBSIZE=1049
+# CONFIG_BOOTM_NETBSD is not set
+# CONFIG_BOOTM_PLAN9 is not set
+# CONFIG_BOOTM_RTEMS is not set
+# CONFIG_BOOTM_VXWORKS is not set
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_UNLZ4 is not set
+# CONFIG_CMD_UNZIP is not set
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_MTD=y
+CONFIG_CMD_SF_TEST=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_SMC=y
+CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_BLK=y
+CONFIG_HAVE_BLOCK_DEVICE=y
+CONFIG_CLK=y
+# CONFIG_MMC is not set
+CONFIG_MTD=y
+CONFIG_DM_MTD=y
+CONFIG_MTD_SPI_NAND=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH_SFDP_SUPPORT=y
+CONFIG_SPI_FLASH_EON=y
+CONFIG_SPI_FLASH_GIGADEVICE=y
+CONFIG_SPI_FLASH_ISSI=y
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_SPI_FLASH_XMC=y
+CONFIG_SPI_FLASH_XTX=y
+CONFIG_SPI_FLASH_MTD=y
+CONFIG_PHY_FIXED=y
+CONFIG_DM_ETH=y
+CONFIG_MEDIATEK_ETH=y
+CONFIG_PINCTRL=y
+CONFIG_PINCONF=y
+CONFIG_PINCTRL_MT7981=y
+CONFIG_POWER_DOMAIN=y
+CONFIG_MTK_POWER_DOMAIN=y
+CONFIG_DM_SERIAL=y
+CONFIG_MTK_SERIAL=y
+CONFIG_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_MTK_SPIM=y
+CONFIG_HEXDUMP=y
+# CONFIG_EFI_LOADER is not set
diff --git a/configs/mt7981_sd_rfb_defconfig b/configs/mt7981_sd_rfb_defconfig
new file mode 100644
index 0000000000..b5c765bd7c
--- /dev/null
+++ b/configs/mt7981_sd_rfb_defconfig
@@ -0,0 +1,64 @@
+CONFIG_ARM=y
+CONFIG_POSITION_INDEPENDENT=y
+CONFIG_ARCH_MEDIATEK=y
+CONFIG_SYS_TEXT_BASE=0x41e00000
+CONFIG_SYS_MALLOC_F_LEN=0x4000
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_ENV_SIZE=0x80000
+CONFIG_ENV_OFFSET=0x300000
+CONFIG_DEFAULT_DEVICE_TREE="mt7981-sd-rfb"
+CONFIG_TARGET_MT7981=y
+CONFIG_DEBUG_UART_BASE=0x11002000
+CONFIG_DEBUG_UART_CLOCK=40000000
+CONFIG_SYS_LOAD_ADDR=0x46000000
+CONFIG_DEBUG_UART=y
+# CONFIG_AUTOBOOT is not set
+CONFIG_DEFAULT_FDT_FILE="mt7981-sd-rfb"
+CONFIG_LOGLEVEL=7
+CONFIG_LOG=y
+CONFIG_SYS_PROMPT="MT7981> "
+CONFIG_SYS_CBSIZE=512
+CONFIG_SYS_PBSIZE=1049
+# CONFIG_BOOTM_NETBSD is not set
+# CONFIG_BOOTM_PLAN9 is not set
+# CONFIG_BOOTM_RTEMS is not set
+# CONFIG_BOOTM_VXWORKS is not set
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_UNLZ4 is not set
+# CONFIG_CMD_UNZIP is not set
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_GPT=y
+CONFIG_CMD_GPT_RENAME=y
+CONFIG_CMD_LSBLK=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_PART=y
+CONFIG_CMD_READ=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_SMC=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_PARTITION_TYPE_GUID=y
+CONFIG_ENV_OVERWRITE=y
+CONFIG_ENV_IS_IN_MMC=y
+CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_CLK=y
+CONFIG_MMC_HS200_SUPPORT=y
+CONFIG_MMC_MTK=y
+CONFIG_PHY_FIXED=y
+CONFIG_DM_ETH=y
+CONFIG_MEDIATEK_ETH=y
+CONFIG_PINCTRL=y
+CONFIG_PINCONF=y
+CONFIG_PINCTRL_MT7981=y
+CONFIG_POWER_DOMAIN=y
+CONFIG_MTK_POWER_DOMAIN=y
+CONFIG_DM_REGULATOR=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_DM_SERIAL=y
+CONFIG_MTK_SERIAL=y
+CONFIG_FAT_WRITE=y
+CONFIG_HEXDUMP=y
+# CONFIG_EFI_LOADER is not set
diff --git a/include/configs/mt7981.h b/include/configs/mt7981.h
new file mode 100644
index 0000000000..a213b8de88
--- /dev/null
+++ b/include/configs/mt7981.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Configuration for MediaTek MT7981 SoC
+ *
+ * Copyright (C) 2022 MediaTek Inc.
+ * Author: Sam Shih <sam.shih@mediatek.com>
+ */
+
+#ifndef __MT7981_H
+#define __MT7981_H
+
+#include <linux/sizes.h>
+
+#define CONFIG_SYS_NONCACHED_MEMORY	SZ_1M
+#define CONFIG_SYS_MMC_ENV_DEV		0
+
+/* Uboot definition */
+#define CONFIG_SYS_UBOOT_BASE		CONFIG_SYS_TEXT_BASE
+
+/* SPL -> Uboot */
+#define CONFIG_SYS_UBOOT_START		CONFIG_SYS_TEXT_BASE
+
+/* DRAM */
+#define CONFIG_SYS_SDRAM_BASE		0x40000000
+
+#endif
-- 
2.17.1


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

* [PATCH v2 05/32] mmc: mediatek: add support for MediaTek MT7891/MT7986 SoCs
  2022-08-31 11:00 [PATCH v2 00/32] Add support for MediaTek MT7981/MT7986 SoCs - v2 Weijie Gao
                   ` (3 preceding siblings ...)
  2022-08-31 11:00 ` [PATCH v2 04/32] board: mediatek: add MT7981 " Weijie Gao
@ 2022-08-31 11:04 ` Weijie Gao
  2022-09-01  0:10   ` Daniel Golle
  2022-08-31 11:04 ` [PATCH v2 06/32] net: mediatek: use a struct to cover variations of all SoCs Weijie Gao
                   ` (26 subsequent siblings)
  31 siblings, 1 reply; 60+ messages in thread
From: Weijie Gao @ 2022-08-31 11:04 UTC (permalink / raw)
  To: u-boot; +Cc: GSS_MTK_Uboot_upstream, Peng Fan, Jaehoon Chung, Weijie Gao

Add eMMC and SDXC support for MediaTek MT7981/MT7986 SoCs
Both chips support SDXC and eMMC 4.5. MT7986A supports eMMC 5.1.

Reviewed-by: Jaehoon Chung <jh80.chung@samsung.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
---
v2 changes: none
---
 drivers/mmc/mtk-sd.c | 68 ++++++++++++++++++++++++++++++++++----------
 1 file changed, 53 insertions(+), 15 deletions(-)

diff --git a/drivers/mmc/mtk-sd.c b/drivers/mmc/mtk-sd.c
index e61e8cf4b9..b206b0a085 100644
--- a/drivers/mmc/mtk-sd.c
+++ b/drivers/mmc/mtk-sd.c
@@ -1496,7 +1496,12 @@ static void msdc_init_hw(struct msdc_host *host)
 	/* Enable data & cmd interrupts */
 	writel(DATA_INTS_MASK | CMD_INTS_MASK, &host->base->msdc_inten);
 
-	writel(0, tune_reg);
+	if (host->top_base) {
+		writel(0, &host->top_base->emmc_top_control);
+		writel(0, &host->top_base->emmc_top_cmd);
+	} else {
+		writel(0, tune_reg);
+	}
 	writel(0, &host->base->msdc_iocon);
 
 	if (host->r_smpl)
@@ -1507,9 +1512,14 @@ static void msdc_init_hw(struct msdc_host *host)
 	writel(0x403c0046, &host->base->patch_bit0);
 	writel(0xffff4089, &host->base->patch_bit1);
 
-	if (host->dev_comp->stop_clk_fix)
+	if (host->dev_comp->stop_clk_fix) {
 		clrsetbits_le32(&host->base->patch_bit1, MSDC_PB1_STOP_DLY_M,
 				3 << MSDC_PB1_STOP_DLY_S);
+		clrbits_le32(&host->base->sdc_fifo_cfg,
+			     SDC_FIFO_CFG_WRVALIDSEL);
+		clrbits_le32(&host->base->sdc_fifo_cfg,
+			     SDC_FIFO_CFG_RDVALIDSEL);
+	}
 
 	if (host->dev_comp->busy_check)
 		clrbits_le32(&host->base->patch_bit1, (1 << 7));
@@ -1544,15 +1554,28 @@ static void msdc_init_hw(struct msdc_host *host)
 	}
 
 	if (host->dev_comp->data_tune) {
-		setbits_le32(tune_reg,
-			     MSDC_PAD_TUNE_RD_SEL | MSDC_PAD_TUNE_CMD_SEL);
-		clrsetbits_le32(&host->base->patch_bit0,
-				MSDC_INT_DAT_LATCH_CK_SEL_M,
-				host->latch_ck <<
-				MSDC_INT_DAT_LATCH_CK_SEL_S);
+		if (host->top_base) {
+			setbits_le32(&host->top_base->emmc_top_control,
+				     PAD_DAT_RD_RXDLY_SEL);
+			clrbits_le32(&host->top_base->emmc_top_control,
+				     DATA_K_VALUE_SEL);
+			setbits_le32(&host->top_base->emmc_top_cmd,
+				     PAD_CMD_RD_RXDLY_SEL);
+		} else {
+			setbits_le32(tune_reg,
+				     MSDC_PAD_TUNE_RD_SEL | MSDC_PAD_TUNE_CMD_SEL);
+			clrsetbits_le32(&host->base->patch_bit0,
+					MSDC_INT_DAT_LATCH_CK_SEL_M,
+					host->latch_ck <<
+					MSDC_INT_DAT_LATCH_CK_SEL_S);
+		}
 	} else {
 		/* choose clock tune */
-		setbits_le32(tune_reg, MSDC_PAD_TUNE_RXDLYSEL);
+		if (host->top_base)
+			setbits_le32(&host->top_base->emmc_top_control,
+				     PAD_RXDLY_SEL);
+		else
+			setbits_le32(tune_reg, MSDC_PAD_TUNE_RXDLYSEL);
 	}
 
 	if (host->dev_comp->builtin_pad_ctrl) {
@@ -1604,12 +1627,6 @@ static void msdc_init_hw(struct msdc_host *host)
 	clrsetbits_le32(&host->base->sdc_cfg, SDC_CFG_DTOC_M,
 			3 << SDC_CFG_DTOC_S);
 
-	if (host->dev_comp->stop_clk_fix) {
-		clrbits_le32(&host->base->sdc_fifo_cfg,
-			     SDC_FIFO_CFG_WRVALIDSEL);
-		clrbits_le32(&host->base->sdc_fifo_cfg,
-			     SDC_FIFO_CFG_RDVALIDSEL);
-	}
 
 	host->def_tune_para.iocon = readl(&host->base->msdc_iocon);
 	host->def_tune_para.pad_tune = readl(&host->base->pad_tune);
@@ -1792,6 +1809,25 @@ static const struct msdc_compatible mt7623_compat = {
 	.enhance_rx = false
 };
 
+static const struct msdc_compatible mt7986_compat = {
+	.clk_div_bits = 12,
+	.pad_tune0 = true,
+	.async_fifo = true,
+	.data_tune = true,
+	.busy_check = true,
+	.stop_clk_fix = true,
+	.enhance_rx = true,
+};
+
+static const struct msdc_compatible mt7981_compat = {
+	.clk_div_bits = 12,
+	.pad_tune0 = true,
+	.async_fifo = true,
+	.data_tune = true,
+	.busy_check = true,
+	.stop_clk_fix = true,
+};
+
 static const struct msdc_compatible mt8512_compat = {
 	.clk_div_bits = 12,
 	.pad_tune0 = true,
@@ -1824,6 +1860,8 @@ static const struct udevice_id msdc_ids[] = {
 	{ .compatible = "mediatek,mt7621-mmc", .data = (ulong)&mt7621_compat },
 	{ .compatible = "mediatek,mt7622-mmc", .data = (ulong)&mt7622_compat },
 	{ .compatible = "mediatek,mt7623-mmc", .data = (ulong)&mt7623_compat },
+	{ .compatible = "mediatek,mt7986-mmc", .data = (ulong)&mt7986_compat },
+	{ .compatible = "mediatek,mt7981-mmc", .data = (ulong)&mt7981_compat },
 	{ .compatible = "mediatek,mt8512-mmc", .data = (ulong)&mt8512_compat },
 	{ .compatible = "mediatek,mt8516-mmc", .data = (ulong)&mt8516_compat },
 	{ .compatible = "mediatek,mt8183-mmc", .data = (ulong)&mt8183_compat },
-- 
2.17.1


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

* [PATCH v2 06/32] net: mediatek: use a struct to cover variations of all SoCs
  2022-08-31 11:00 [PATCH v2 00/32] Add support for MediaTek MT7981/MT7986 SoCs - v2 Weijie Gao
                   ` (4 preceding siblings ...)
  2022-08-31 11:04 ` [PATCH v2 05/32] mmc: mediatek: add support for MediaTek MT7891/MT7986 SoCs Weijie Gao
@ 2022-08-31 11:04 ` Weijie Gao
  2022-09-01  0:20   ` Daniel Golle
  2022-08-31 11:04 ` [PATCH v2 07/32] net: mediatek: stop using bitfileds for DMA descriptors Weijie Gao
                   ` (25 subsequent siblings)
  31 siblings, 1 reply; 60+ messages in thread
From: Weijie Gao @ 2022-08-31 11:04 UTC (permalink / raw)
  To: u-boot; +Cc: GSS_MTK_Uboot_upstream, Joe Hershberger, Ramon Fried, Weijie Gao

Using a single soc id to control different initialization and TX/RX flow
for all SoCs is not extensible if more hardware variations are added in
the future.

This patch introduces a struct to replace the original mtk_soc to allow
the driver be able handle newer hardwares.

Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
---
v2c changes:
  Add description for new struct
---
 drivers/net/mtk_eth.c | 56 ++++++++++++++++++++++++++++++-------------
 drivers/net/mtk_eth.h | 25 ++++++++++++++++++-
 2 files changed, 64 insertions(+), 17 deletions(-)

diff --git a/drivers/net/mtk_eth.c b/drivers/net/mtk_eth.c
index 4fe7ee0d36..ce4aa6e065 100644
--- a/drivers/net/mtk_eth.c
+++ b/drivers/net/mtk_eth.c
@@ -142,11 +142,15 @@ enum mtk_switch {
 	SW_MT7531
 };
 
-enum mtk_soc {
-	SOC_MT7623,
-	SOC_MT7629,
-	SOC_MT7622,
-	SOC_MT7621
+/* struct mtk_soc_data -	This is the structure holding all differences
+ *				among various plaforms
+ * @caps			Flags shown the extra capability for the SoC
+ * @ana_rgc3:			The offset for register ANA_RGC3 related to
+ *				sgmiisys syscon
+ */
+struct mtk_soc_data {
+	u32 caps;
+	u32 ana_rgc3;
 };
 
 struct mtk_eth_priv {
@@ -171,7 +175,7 @@ struct mtk_eth_priv {
 	int (*mmd_write)(struct mtk_eth_priv *priv, u8 addr, u8 devad, u16 reg,
 			 u16 val);
 
-	enum mtk_soc soc;
+	const struct mtk_soc_data *soc;
 	int gmac_id;
 	int force_mode;
 	int speed;
@@ -679,7 +683,7 @@ static int mt7530_setup(struct mtk_eth_priv *priv)
 	u32 val, txdrv;
 	int i;
 
-	if (priv->soc != SOC_MT7621) {
+	if (!MTK_HAS_CAPS(priv->soc->caps, MTK_TRGMII_MT7621_CLK)) {
 		/* Select 250MHz clk for RGMII mode */
 		mtk_ethsys_rmw(priv, ETHSYS_CLKCFG0_REG,
 			       ETHSYS_TRGMII_CLK_SEL362_5, 0);
@@ -1108,9 +1112,8 @@ static int mtk_phy_probe(struct udevice *dev)
 static void mtk_sgmii_init(struct mtk_eth_priv *priv)
 {
 	/* Set SGMII GEN2 speed(2.5G) */
-	clrsetbits_le32(priv->sgmii_base + ((priv->soc == SOC_MT7622) ?
-			SGMSYS_GEN2_SPEED : SGMSYS_GEN2_SPEED_V2),
-			SGMSYS_SPEED_2500, SGMSYS_SPEED_2500);
+	setbits_le32(priv->sgmii_base + priv->soc->ana_rgc3,
+		     SGMSYS_SPEED_2500);
 
 	/* Disable SGMII AN */
 	clrsetbits_le32(priv->sgmii_base + SGMSYS_PCS_CONTROL_1,
@@ -1182,7 +1185,8 @@ static void mtk_mac_init(struct mtk_eth_priv *priv)
 		mtk_gmac_write(priv, GMAC_PORT_MCR(priv->gmac_id), mcr);
 	}
 
-	if (priv->soc == SOC_MT7623) {
+	if (MTK_HAS_CAPS(priv->soc->caps, MTK_GMAC1_TRGMII) &&
+	    !MTK_HAS_CAPS(priv->soc->caps, MTK_TRGMII_MT7621_CLK)) {
 		/* Lower Tx Driving for TRGMII path */
 		for (i = 0 ; i < NUM_TRGMII_CTRL; i++)
 			mtk_gmac_write(priv, GMAC_TRGMII_TD_ODT(i),
@@ -1431,7 +1435,11 @@ static int mtk_eth_of_to_plat(struct udevice *dev)
 	ofnode subnode;
 	int ret;
 
-	priv->soc = dev_get_driver_data(dev);
+	priv->soc = (const struct mtk_soc_data *)dev_get_driver_data(dev);
+	if (!priv->soc) {
+		dev_err(dev, "missing soc compatible data\n");
+		return -EINVAL;
+	}
 
 	pdata->iobase = (phys_addr_t)dev_remap_addr(dev);
 
@@ -1544,11 +1552,27 @@ static int mtk_eth_of_to_plat(struct udevice *dev)
 	return 0;
 }
 
+static const struct mtk_soc_data mt7629_data = {
+	.ana_rgc3 = 0x128,
+};
+
+static const struct mtk_soc_data mt7623_data = {
+	.caps = MT7623_CAPS,
+};
+
+static const struct mtk_soc_data mt7622_data = {
+	.ana_rgc3 = 0x2028,
+};
+
+static const struct mtk_soc_data mt7621_data = {
+	.caps = MT7621_CAPS,
+};
+
 static const struct udevice_id mtk_eth_ids[] = {
-	{ .compatible = "mediatek,mt7629-eth", .data = SOC_MT7629 },
-	{ .compatible = "mediatek,mt7623-eth", .data = SOC_MT7623 },
-	{ .compatible = "mediatek,mt7622-eth", .data = SOC_MT7622 },
-	{ .compatible = "mediatek,mt7621-eth", .data = SOC_MT7621 },
+	{ .compatible = "mediatek,mt7629-eth", .data = (ulong)&mt7629_data },
+	{ .compatible = "mediatek,mt7623-eth", .data = (ulong)&mt7623_data },
+	{ .compatible = "mediatek,mt7622-eth", .data = (ulong)&mt7622_data },
+	{ .compatible = "mediatek,mt7621-eth", .data = (ulong)&mt7621_data },
 	{}
 };
 
diff --git a/drivers/net/mtk_eth.h b/drivers/net/mtk_eth.h
index 057ecfaabf..15c2030617 100644
--- a/drivers/net/mtk_eth.h
+++ b/drivers/net/mtk_eth.h
@@ -9,8 +9,31 @@
 #ifndef _MTK_ETH_H_
 #define _MTK_ETH_H_
 
-/* Frame Engine Register Bases */
 #include <linux/bitops.h>
+
+enum mkt_eth_capabilities {
+	MTK_TRGMII_BIT,
+	MTK_TRGMII_MT7621_CLK_BIT,
+
+	/* PATH BITS */
+	MTK_ETH_PATH_GMAC1_TRGMII_BIT,
+};
+
+#define MTK_TRGMII			BIT(MTK_TRGMII_BIT)
+#define MTK_TRGMII_MT7621_CLK		BIT(MTK_TRGMII_MT7621_CLK_BIT)
+
+/* Supported path present on SoCs */
+#define MTK_ETH_PATH_GMAC1_TRGMII	BIT(MTK_ETH_PATH_GMAC1_TRGMII_BIT)
+
+#define MTK_GMAC1_TRGMII	(MTK_ETH_PATH_GMAC1_TRGMII | MTK_TRGMII)
+
+#define MTK_HAS_CAPS(caps, _x)		(((caps) & (_x)) == (_x))
+
+#define MT7621_CAPS  (MTK_GMAC1_TRGMII | MTK_TRGMII_MT7621_CLK)
+
+#define MT7623_CAPS  (MTK_GMAC1_TRGMII)
+
+/* Frame Engine Register Bases */
 #define PDMA_BASE			0x0800
 #define GDMA1_BASE			0x0500
 #define GDMA2_BASE			0x1500
-- 
2.17.1


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

* [PATCH v2 07/32] net: mediatek: stop using bitfileds for DMA descriptors
  2022-08-31 11:00 [PATCH v2 00/32] Add support for MediaTek MT7981/MT7986 SoCs - v2 Weijie Gao
                   ` (5 preceding siblings ...)
  2022-08-31 11:04 ` [PATCH v2 06/32] net: mediatek: use a struct to cover variations of all SoCs Weijie Gao
@ 2022-08-31 11:04 ` Weijie Gao
  2022-09-01  0:20   ` Daniel Golle
  2022-08-31 11:04 ` [PATCH v2 08/32] net: mediatek: add support for PDMA v2 Weijie Gao
                   ` (24 subsequent siblings)
  31 siblings, 1 reply; 60+ messages in thread
From: Weijie Gao @ 2022-08-31 11:04 UTC (permalink / raw)
  To: u-boot; +Cc: GSS_MTK_Uboot_upstream, Joe Hershberger, Ramon Fried, Weijie Gao

This patch is a preparation for adding a new version of PDMA of which the
DMA descriptor fields has changed. Using bitfields will result in a complex
modification. Convert bitfields to u32 units can solve this problem easily.

Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
---
v2 changes:
  Fix typo in commit message
---
 drivers/net/mtk_eth.c | 144 ++++++++++++++----------------------------
 drivers/net/mtk_eth.h |  32 ++++++++++
 2 files changed, 80 insertions(+), 96 deletions(-)

diff --git a/drivers/net/mtk_eth.c b/drivers/net/mtk_eth.c
index ce4aa6e065..e3738b9277 100644
--- a/drivers/net/mtk_eth.c
+++ b/drivers/net/mtk_eth.c
@@ -65,77 +65,6 @@
 	(DP_DISCARD << MC_DP_S) | \
 	(DP_DISCARD << UN_DP_S))
 
-struct pdma_rxd_info1 {
-	u32 PDP0;
-};
-
-struct pdma_rxd_info2 {
-	u32 PLEN1 : 14;
-	u32 LS1 : 1;
-	u32 UN_USED : 1;
-	u32 PLEN0 : 14;
-	u32 LS0 : 1;
-	u32 DDONE : 1;
-};
-
-struct pdma_rxd_info3 {
-	u32 PDP1;
-};
-
-struct pdma_rxd_info4 {
-	u32 FOE_ENTRY : 14;
-	u32 CRSN : 5;
-	u32 SP : 3;
-	u32 L4F : 1;
-	u32 L4VLD : 1;
-	u32 TACK : 1;
-	u32 IP4F : 1;
-	u32 IP4 : 1;
-	u32 IP6 : 1;
-	u32 UN_USED : 4;
-};
-
-struct pdma_rxdesc {
-	struct pdma_rxd_info1 rxd_info1;
-	struct pdma_rxd_info2 rxd_info2;
-	struct pdma_rxd_info3 rxd_info3;
-	struct pdma_rxd_info4 rxd_info4;
-};
-
-struct pdma_txd_info1 {
-	u32 SDP0;
-};
-
-struct pdma_txd_info2 {
-	u32 SDL1 : 14;
-	u32 LS1 : 1;
-	u32 BURST : 1;
-	u32 SDL0 : 14;
-	u32 LS0 : 1;
-	u32 DDONE : 1;
-};
-
-struct pdma_txd_info3 {
-	u32 SDP1;
-};
-
-struct pdma_txd_info4 {
-	u32 VLAN_TAG : 16;
-	u32 INS : 1;
-	u32 RESV : 2;
-	u32 UDF : 6;
-	u32 FPORT : 3;
-	u32 TSO : 1;
-	u32 TUI_CO : 3;
-};
-
-struct pdma_txdesc {
-	struct pdma_txd_info1 txd_info1;
-	struct pdma_txd_info2 txd_info2;
-	struct pdma_txd_info3 txd_info3;
-	struct pdma_txd_info4 txd_info4;
-};
-
 enum mtk_switch {
 	SW_NONE,
 	SW_MT7530,
@@ -151,13 +80,15 @@ enum mtk_switch {
 struct mtk_soc_data {
 	u32 caps;
 	u32 ana_rgc3;
+	u32 txd_size;
+	u32 rxd_size;
 };
 
 struct mtk_eth_priv {
 	char pkt_pool[TOTAL_PKT_BUF_SIZE] __aligned(ARCH_DMA_MINALIGN);
 
-	struct pdma_txdesc *tx_ring_noc;
-	struct pdma_rxdesc *rx_ring_noc;
+	void *tx_ring_noc;
+	void *rx_ring_noc;
 
 	int rx_dma_owner_idx0;
 	int tx_cpu_owner_idx0;
@@ -1202,14 +1133,16 @@ static void mtk_mac_init(struct mtk_eth_priv *priv)
 static void mtk_eth_fifo_init(struct mtk_eth_priv *priv)
 {
 	char *pkt_base = priv->pkt_pool;
+	struct mtk_tx_dma *txd;
+	struct mtk_rx_dma *rxd;
 	int i;
 
 	mtk_pdma_rmw(priv, PDMA_GLO_CFG_REG, 0xffff0000, 0);
 	udelay(500);
 
-	memset(priv->tx_ring_noc, 0, NUM_TX_DESC * sizeof(struct pdma_txdesc));
-	memset(priv->rx_ring_noc, 0, NUM_RX_DESC * sizeof(struct pdma_rxdesc));
-	memset(priv->pkt_pool, 0, TOTAL_PKT_BUF_SIZE);
+	memset(priv->tx_ring_noc, 0, NUM_TX_DESC * priv->soc->txd_size);
+	memset(priv->rx_ring_noc, 0, NUM_RX_DESC * priv->soc->rxd_size);
+	memset(priv->pkt_pool, 0xff, TOTAL_PKT_BUF_SIZE);
 
 	flush_dcache_range((ulong)pkt_base,
 			   (ulong)(pkt_base + TOTAL_PKT_BUF_SIZE));
@@ -1218,17 +1151,21 @@ static void mtk_eth_fifo_init(struct mtk_eth_priv *priv)
 	priv->tx_cpu_owner_idx0 = 0;
 
 	for (i = 0; i < NUM_TX_DESC; i++) {
-		priv->tx_ring_noc[i].txd_info2.LS0 = 1;
-		priv->tx_ring_noc[i].txd_info2.DDONE = 1;
-		priv->tx_ring_noc[i].txd_info4.FPORT = priv->gmac_id + 1;
+		txd = priv->tx_ring_noc + i * priv->soc->txd_size;
+
+		txd->txd1 = virt_to_phys(pkt_base);
+		txd->txd2 = PDMA_TXD2_DDONE | PDMA_TXD2_LS0;
+		txd->txd4 = PDMA_TXD4_FPORT_SET(priv->gmac_id + 1);
 
-		priv->tx_ring_noc[i].txd_info1.SDP0 = virt_to_phys(pkt_base);
 		pkt_base += PKTSIZE_ALIGN;
 	}
 
 	for (i = 0; i < NUM_RX_DESC; i++) {
-		priv->rx_ring_noc[i].rxd_info2.PLEN0 = PKTSIZE_ALIGN;
-		priv->rx_ring_noc[i].rxd_info1.PDP0 = virt_to_phys(pkt_base);
+		rxd = priv->rx_ring_noc + i * priv->soc->rxd_size;
+
+		rxd->rxd1 = virt_to_phys(pkt_base);
+		rxd->rxd2 = PDMA_RXD2_PLEN0_SET(PKTSIZE_ALIGN);
+
 		pkt_base += PKTSIZE_ALIGN;
 	}
 
@@ -1315,20 +1252,22 @@ static int mtk_eth_send(struct udevice *dev, void *packet, int length)
 {
 	struct mtk_eth_priv *priv = dev_get_priv(dev);
 	u32 idx = priv->tx_cpu_owner_idx0;
+	struct mtk_tx_dma *txd;
 	void *pkt_base;
 
-	if (!priv->tx_ring_noc[idx].txd_info2.DDONE) {
+	txd = priv->tx_ring_noc + idx * priv->soc->txd_size;
+
+	if (!(txd->txd2 & PDMA_TXD2_DDONE)) {
 		debug("mtk-eth: TX DMA descriptor ring is full\n");
 		return -EPERM;
 	}
 
-	pkt_base = (void *)phys_to_virt(priv->tx_ring_noc[idx].txd_info1.SDP0);
+	pkt_base = (void *)phys_to_virt(txd->txd1);
 	memcpy(pkt_base, packet, length);
 	flush_dcache_range((ulong)pkt_base, (ulong)pkt_base +
 			   roundup(length, ARCH_DMA_MINALIGN));
 
-	priv->tx_ring_noc[idx].txd_info2.SDL0 = length;
-	priv->tx_ring_noc[idx].txd_info2.DDONE = 0;
+	txd->txd2 = PDMA_TXD2_LS0 | PDMA_TXD2_SDL0_SET(length);
 
 	priv->tx_cpu_owner_idx0 = (priv->tx_cpu_owner_idx0 + 1) % NUM_TX_DESC;
 	mtk_pdma_write(priv, TX_CTX_IDX_REG(0), priv->tx_cpu_owner_idx0);
@@ -1340,16 +1279,20 @@ static int mtk_eth_recv(struct udevice *dev, int flags, uchar **packetp)
 {
 	struct mtk_eth_priv *priv = dev_get_priv(dev);
 	u32 idx = priv->rx_dma_owner_idx0;
+	struct mtk_rx_dma *rxd;
 	uchar *pkt_base;
 	u32 length;
 
-	if (!priv->rx_ring_noc[idx].rxd_info2.DDONE) {
+	rxd = priv->rx_ring_noc + idx * priv->soc->rxd_size;
+
+	if (!(rxd->rxd2 & PDMA_RXD2_DDONE)) {
 		debug("mtk-eth: RX DMA descriptor ring is empty\n");
 		return -EAGAIN;
 	}
 
-	length = priv->rx_ring_noc[idx].rxd_info2.PLEN0;
-	pkt_base = (void *)phys_to_virt(priv->rx_ring_noc[idx].rxd_info1.PDP0);
+	length = PDMA_RXD2_PLEN0_GET(rxd->rxd2);
+
+	pkt_base = (void *)phys_to_virt(rxd->rxd1);
 	invalidate_dcache_range((ulong)pkt_base, (ulong)pkt_base +
 				roundup(length, ARCH_DMA_MINALIGN));
 
@@ -1363,10 +1306,11 @@ static int mtk_eth_free_pkt(struct udevice *dev, uchar *packet, int length)
 {
 	struct mtk_eth_priv *priv = dev_get_priv(dev);
 	u32 idx = priv->rx_dma_owner_idx0;
+	struct mtk_rx_dma *rxd;
+
+	rxd = priv->rx_ring_noc + idx * priv->soc->rxd_size;
 
-	priv->rx_ring_noc[idx].rxd_info2.DDONE = 0;
-	priv->rx_ring_noc[idx].rxd_info2.LS0 = 0;
-	priv->rx_ring_noc[idx].rxd_info2.PLEN0 = PKTSIZE_ALIGN;
+	rxd->rxd2 = PDMA_RXD2_PLEN0_SET(PKTSIZE_ALIGN);
 
 	mtk_pdma_write(priv, RX_CRX_IDX_REG(0), idx);
 	priv->rx_dma_owner_idx0 = (priv->rx_dma_owner_idx0 + 1) % NUM_RX_DESC;
@@ -1393,11 +1337,11 @@ static int mtk_eth_probe(struct udevice *dev)
 		return ret;
 
 	/* Prepare for tx/rx rings */
-	priv->tx_ring_noc = (struct pdma_txdesc *)
-		noncached_alloc(sizeof(struct pdma_txdesc) * NUM_TX_DESC,
+	priv->tx_ring_noc = (void *)
+		noncached_alloc(priv->soc->txd_size * NUM_TX_DESC,
 				ARCH_DMA_MINALIGN);
-	priv->rx_ring_noc = (struct pdma_rxdesc *)
-		noncached_alloc(sizeof(struct pdma_rxdesc) * NUM_RX_DESC,
+	priv->rx_ring_noc = (void *)
+		noncached_alloc(priv->soc->rxd_size * NUM_RX_DESC,
 				ARCH_DMA_MINALIGN);
 
 	/* Set MAC mode */
@@ -1554,18 +1498,26 @@ static int mtk_eth_of_to_plat(struct udevice *dev)
 
 static const struct mtk_soc_data mt7629_data = {
 	.ana_rgc3 = 0x128,
+	.txd_size = sizeof(struct mtk_tx_dma),
+	.rxd_size = sizeof(struct mtk_rx_dma),
 };
 
 static const struct mtk_soc_data mt7623_data = {
 	.caps = MT7623_CAPS,
+	.txd_size = sizeof(struct mtk_tx_dma),
+	.rxd_size = sizeof(struct mtk_rx_dma),
 };
 
 static const struct mtk_soc_data mt7622_data = {
 	.ana_rgc3 = 0x2028,
+	.txd_size = sizeof(struct mtk_tx_dma),
+	.rxd_size = sizeof(struct mtk_rx_dma),
 };
 
 static const struct mtk_soc_data mt7621_data = {
 	.caps = MT7621_CAPS,
+	.txd_size = sizeof(struct mtk_tx_dma),
+	.rxd_size = sizeof(struct mtk_rx_dma),
 };
 
 static const struct udevice_id mtk_eth_ids[] = {
diff --git a/drivers/net/mtk_eth.h b/drivers/net/mtk_eth.h
index 15c2030617..65bc9fcc04 100644
--- a/drivers/net/mtk_eth.h
+++ b/drivers/net/mtk_eth.h
@@ -10,6 +10,7 @@
 #define _MTK_ETH_H_
 
 #include <linux/bitops.h>
+#include <linux/bitfield.h>
 
 enum mkt_eth_capabilities {
 	MTK_TRGMII_BIT,
@@ -435,4 +436,35 @@ enum mkt_eth_capabilities {
 #define PHY_POWER_SAVING_M		0x300
 #define PHY_POWER_SAVING_TX		0x0
 
+/* PDMA descriptors */
+struct mtk_rx_dma {
+	unsigned int rxd1;
+	unsigned int rxd2;
+	unsigned int rxd3;
+	unsigned int rxd4;
+} __packed __aligned(4);
+
+struct mtk_tx_dma {
+	unsigned int txd1;
+	unsigned int txd2;
+	unsigned int txd3;
+	unsigned int txd4;
+} __packed __aligned(4);
+
+/* PDMA TXD fields */
+#define PDMA_TXD2_DDONE			BIT(31)
+#define PDMA_TXD2_LS0			BIT(30)
+#define PDMA_TXD2_SDL0_M		GENMASK(29, 16)
+#define PDMA_TXD2_SDL0_SET(_v)	FIELD_PREP(PDMA_TXD2_SDL0_M, (_v))
+
+#define PDMA_TXD4_FPORT_M		GENMASK(27, 25)
+#define PDMA_TXD4_FPORT_SET(_v)	FIELD_PREP(PDMA_TXD4_FPORT_M, (_v))
+
+/* PDMA RXD fields */
+#define PDMA_RXD2_DDONE			BIT(31)
+#define PDMA_RXD2_LS0			BIT(30)
+#define PDMA_RXD2_PLEN0_M		GENMASK(29, 16)
+#define PDMA_RXD2_PLEN0_GET(_v)	FIELD_GET(PDMA_RXD2_PLEN0_M, (_v))
+#define PDMA_RXD2_PLEN0_SET(_v)	FIELD_PREP(PDMA_RXD2_PLEN0_M, (_v))
+
 #endif /* _MTK_ETH_H_ */
-- 
2.17.1


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

* [PATCH v2 08/32] net: mediatek: add support for PDMA v2
  2022-08-31 11:00 [PATCH v2 00/32] Add support for MediaTek MT7981/MT7986 SoCs - v2 Weijie Gao
                   ` (6 preceding siblings ...)
  2022-08-31 11:04 ` [PATCH v2 07/32] net: mediatek: stop using bitfileds for DMA descriptors Weijie Gao
@ 2022-08-31 11:04 ` Weijie Gao
  2022-09-01  0:22   ` Daniel Golle
  2022-08-31 11:04 ` [PATCH v2 09/32] net: mediatek: add support for MediaTek MT7981/MT7986 Weijie Gao
                   ` (23 subsequent siblings)
  31 siblings, 1 reply; 60+ messages in thread
From: Weijie Gao @ 2022-08-31 11:04 UTC (permalink / raw)
  To: u-boot; +Cc: GSS_MTK_Uboot_upstream, Joe Hershberger, Ramon Fried, Weijie Gao

This patch adds support for PDMA v2 hardware. The PDMA v2 has extended the
DMA descriptor to 8-words, and some of its fields have changed comparing
to the v1 hardware.

Reviewed-by: Ramon Fried <rfried.dev@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
---
v2 changes:
  Add description for new fields
---
 drivers/net/mtk_eth.c | 54 ++++++++++++++++++++++++++++++++-----------
 drivers/net/mtk_eth.h | 53 +++++++++++++++++++++++++++++++++++-------
 2 files changed, 86 insertions(+), 21 deletions(-)

diff --git a/drivers/net/mtk_eth.c b/drivers/net/mtk_eth.c
index e3738b9277..fb72baae68 100644
--- a/drivers/net/mtk_eth.c
+++ b/drivers/net/mtk_eth.c
@@ -76,10 +76,14 @@ enum mtk_switch {
  * @caps			Flags shown the extra capability for the SoC
  * @ana_rgc3:			The offset for register ANA_RGC3 related to
  *				sgmiisys syscon
+ * @pdma_base:			Register base of PDMA block
+ * @txd_size:			Tx DMA descriptor size.
+ * @rxd_size:			Rx DMA descriptor size.
  */
 struct mtk_soc_data {
 	u32 caps;
 	u32 ana_rgc3;
+	u32 pdma_base;
 	u32 txd_size;
 	u32 rxd_size;
 };
@@ -130,13 +134,13 @@ struct mtk_eth_priv {
 
 static void mtk_pdma_write(struct mtk_eth_priv *priv, u32 reg, u32 val)
 {
-	writel(val, priv->fe_base + PDMA_BASE + reg);
+	writel(val, priv->fe_base + priv->soc->pdma_base + reg);
 }
 
 static void mtk_pdma_rmw(struct mtk_eth_priv *priv, u32 reg, u32 clr,
 			 u32 set)
 {
-	clrsetbits_le32(priv->fe_base + PDMA_BASE + reg, clr, set);
+	clrsetbits_le32(priv->fe_base + priv->soc->pdma_base + reg, clr, set);
 }
 
 static void mtk_gdma_write(struct mtk_eth_priv *priv, int no, u32 reg,
@@ -1133,8 +1137,8 @@ static void mtk_mac_init(struct mtk_eth_priv *priv)
 static void mtk_eth_fifo_init(struct mtk_eth_priv *priv)
 {
 	char *pkt_base = priv->pkt_pool;
-	struct mtk_tx_dma *txd;
-	struct mtk_rx_dma *rxd;
+	struct mtk_tx_dma_v2 *txd;
+	struct mtk_rx_dma_v2 *rxd;
 	int i;
 
 	mtk_pdma_rmw(priv, PDMA_GLO_CFG_REG, 0xffff0000, 0);
@@ -1155,7 +1159,11 @@ static void mtk_eth_fifo_init(struct mtk_eth_priv *priv)
 
 		txd->txd1 = virt_to_phys(pkt_base);
 		txd->txd2 = PDMA_TXD2_DDONE | PDMA_TXD2_LS0;
-		txd->txd4 = PDMA_TXD4_FPORT_SET(priv->gmac_id + 1);
+
+		if (MTK_HAS_CAPS(priv->soc->caps, MTK_NETSYS_V2))
+			txd->txd5 = PDMA_V2_TXD5_FPORT_SET(priv->gmac_id + 1);
+		else
+			txd->txd4 = PDMA_V1_TXD4_FPORT_SET(priv->gmac_id + 1);
 
 		pkt_base += PKTSIZE_ALIGN;
 	}
@@ -1164,7 +1172,11 @@ static void mtk_eth_fifo_init(struct mtk_eth_priv *priv)
 		rxd = priv->rx_ring_noc + i * priv->soc->rxd_size;
 
 		rxd->rxd1 = virt_to_phys(pkt_base);
-		rxd->rxd2 = PDMA_RXD2_PLEN0_SET(PKTSIZE_ALIGN);
+
+		if (MTK_HAS_CAPS(priv->soc->caps, MTK_NETSYS_V2))
+			rxd->rxd2 = PDMA_V2_RXD2_PLEN0_SET(PKTSIZE_ALIGN);
+		else
+			rxd->rxd2 = PDMA_V1_RXD2_PLEN0_SET(PKTSIZE_ALIGN);
 
 		pkt_base += PKTSIZE_ALIGN;
 	}
@@ -1193,6 +1205,9 @@ static int mtk_eth_start(struct udevice *dev)
 	reset_deassert(&priv->rst_fe);
 	mdelay(10);
 
+	if (MTK_HAS_CAPS(priv->soc->caps, MTK_NETSYS_V2))
+		setbits_le32(priv->fe_base + FE_GLO_MISC_REG, PDMA_VER_V2);
+
 	/* Packets forward to PDMA */
 	mtk_gdma_write(priv, priv->gmac_id, GDMA_IG_CTRL_REG, GDMA_FWD_TO_CPU);
 
@@ -1227,7 +1242,7 @@ static void mtk_eth_stop(struct udevice *dev)
 		     TX_WB_DDONE | RX_DMA_EN | TX_DMA_EN, 0);
 	udelay(500);
 
-	wait_for_bit_le32(priv->fe_base + PDMA_BASE + PDMA_GLO_CFG_REG,
+	wait_for_bit_le32(priv->fe_base + priv->soc->pdma_base + PDMA_GLO_CFG_REG,
 			  RX_DMA_BUSY | TX_DMA_BUSY, 0, 5000, 0);
 }
 
@@ -1252,7 +1267,7 @@ static int mtk_eth_send(struct udevice *dev, void *packet, int length)
 {
 	struct mtk_eth_priv *priv = dev_get_priv(dev);
 	u32 idx = priv->tx_cpu_owner_idx0;
-	struct mtk_tx_dma *txd;
+	struct mtk_tx_dma_v2 *txd;
 	void *pkt_base;
 
 	txd = priv->tx_ring_noc + idx * priv->soc->txd_size;
@@ -1267,7 +1282,10 @@ static int mtk_eth_send(struct udevice *dev, void *packet, int length)
 	flush_dcache_range((ulong)pkt_base, (ulong)pkt_base +
 			   roundup(length, ARCH_DMA_MINALIGN));
 
-	txd->txd2 = PDMA_TXD2_LS0 | PDMA_TXD2_SDL0_SET(length);
+	if (MTK_HAS_CAPS(priv->soc->caps, MTK_NETSYS_V2))
+		txd->txd2 = PDMA_TXD2_LS0 | PDMA_V2_TXD2_SDL0_SET(length);
+	else
+		txd->txd2 = PDMA_TXD2_LS0 | PDMA_V1_TXD2_SDL0_SET(length);
 
 	priv->tx_cpu_owner_idx0 = (priv->tx_cpu_owner_idx0 + 1) % NUM_TX_DESC;
 	mtk_pdma_write(priv, TX_CTX_IDX_REG(0), priv->tx_cpu_owner_idx0);
@@ -1279,7 +1297,7 @@ static int mtk_eth_recv(struct udevice *dev, int flags, uchar **packetp)
 {
 	struct mtk_eth_priv *priv = dev_get_priv(dev);
 	u32 idx = priv->rx_dma_owner_idx0;
-	struct mtk_rx_dma *rxd;
+	struct mtk_rx_dma_v2 *rxd;
 	uchar *pkt_base;
 	u32 length;
 
@@ -1290,7 +1308,10 @@ static int mtk_eth_recv(struct udevice *dev, int flags, uchar **packetp)
 		return -EAGAIN;
 	}
 
-	length = PDMA_RXD2_PLEN0_GET(rxd->rxd2);
+	if (MTK_HAS_CAPS(priv->soc->caps, MTK_NETSYS_V2))
+		length = PDMA_V2_RXD2_PLEN0_GET(rxd->rxd2);
+	else
+		length = PDMA_V1_RXD2_PLEN0_GET(rxd->rxd2);
 
 	pkt_base = (void *)phys_to_virt(rxd->rxd1);
 	invalidate_dcache_range((ulong)pkt_base, (ulong)pkt_base +
@@ -1306,11 +1327,14 @@ static int mtk_eth_free_pkt(struct udevice *dev, uchar *packet, int length)
 {
 	struct mtk_eth_priv *priv = dev_get_priv(dev);
 	u32 idx = priv->rx_dma_owner_idx0;
-	struct mtk_rx_dma *rxd;
+	struct mtk_rx_dma_v2 *rxd;
 
 	rxd = priv->rx_ring_noc + idx * priv->soc->rxd_size;
 
-	rxd->rxd2 = PDMA_RXD2_PLEN0_SET(PKTSIZE_ALIGN);
+	if (MTK_HAS_CAPS(priv->soc->caps, MTK_NETSYS_V2))
+		rxd->rxd2 = PDMA_V2_RXD2_PLEN0_SET(PKTSIZE_ALIGN);
+	else
+		rxd->rxd2 = PDMA_V1_RXD2_PLEN0_SET(PKTSIZE_ALIGN);
 
 	mtk_pdma_write(priv, RX_CRX_IDX_REG(0), idx);
 	priv->rx_dma_owner_idx0 = (priv->rx_dma_owner_idx0 + 1) % NUM_RX_DESC;
@@ -1498,24 +1522,28 @@ static int mtk_eth_of_to_plat(struct udevice *dev)
 
 static const struct mtk_soc_data mt7629_data = {
 	.ana_rgc3 = 0x128,
+	.pdma_base = PDMA_V1_BASE,
 	.txd_size = sizeof(struct mtk_tx_dma),
 	.rxd_size = sizeof(struct mtk_rx_dma),
 };
 
 static const struct mtk_soc_data mt7623_data = {
 	.caps = MT7623_CAPS,
+	.pdma_base = PDMA_V1_BASE,
 	.txd_size = sizeof(struct mtk_tx_dma),
 	.rxd_size = sizeof(struct mtk_rx_dma),
 };
 
 static const struct mtk_soc_data mt7622_data = {
 	.ana_rgc3 = 0x2028,
+	.pdma_base = PDMA_V1_BASE,
 	.txd_size = sizeof(struct mtk_tx_dma),
 	.rxd_size = sizeof(struct mtk_rx_dma),
 };
 
 static const struct mtk_soc_data mt7621_data = {
 	.caps = MT7621_CAPS,
+	.pdma_base = PDMA_V1_BASE,
 	.txd_size = sizeof(struct mtk_tx_dma),
 	.rxd_size = sizeof(struct mtk_rx_dma),
 };
diff --git a/drivers/net/mtk_eth.h b/drivers/net/mtk_eth.h
index 65bc9fcc04..236c498a1b 100644
--- a/drivers/net/mtk_eth.h
+++ b/drivers/net/mtk_eth.h
@@ -15,6 +15,7 @@
 enum mkt_eth_capabilities {
 	MTK_TRGMII_BIT,
 	MTK_TRGMII_MT7621_CLK_BIT,
+	MTK_NETSYS_V2_BIT,
 
 	/* PATH BITS */
 	MTK_ETH_PATH_GMAC1_TRGMII_BIT,
@@ -22,6 +23,7 @@ enum mkt_eth_capabilities {
 
 #define MTK_TRGMII			BIT(MTK_TRGMII_BIT)
 #define MTK_TRGMII_MT7621_CLK		BIT(MTK_TRGMII_MT7621_CLK_BIT)
+#define MTK_NETSYS_V2			BIT(MTK_NETSYS_V2_BIT)
 
 /* Supported path present on SoCs */
 #define MTK_ETH_PATH_GMAC1_TRGMII	BIT(MTK_ETH_PATH_GMAC1_TRGMII_BIT)
@@ -35,7 +37,8 @@ enum mkt_eth_capabilities {
 #define MT7623_CAPS  (MTK_GMAC1_TRGMII)
 
 /* Frame Engine Register Bases */
-#define PDMA_BASE			0x0800
+#define PDMA_V1_BASE			0x0800
+#define PDMA_V2_BASE			0x6000
 #define GDMA1_BASE			0x0500
 #define GDMA2_BASE			0x1500
 #define GMAC_BASE			0x10000
@@ -74,6 +77,8 @@ enum mkt_eth_capabilities {
 #define SGMSYS_SPEED_2500		BIT(2)
 
 /* Frame Engine Registers */
+#define FE_GLO_MISC_REG			0x124
+#define PDMA_VER_V2			BIT(4)
 
 /* PDMA */
 #define TX_BASE_PTR_REG(n)		(0x000 + (n) * 0x10)
@@ -444,6 +449,17 @@ struct mtk_rx_dma {
 	unsigned int rxd4;
 } __packed __aligned(4);
 
+struct mtk_rx_dma_v2 {
+	unsigned int rxd1;
+	unsigned int rxd2;
+	unsigned int rxd3;
+	unsigned int rxd4;
+	unsigned int rxd5;
+	unsigned int rxd6;
+	unsigned int rxd7;
+	unsigned int rxd8;
+} __packed __aligned(4);
+
 struct mtk_tx_dma {
 	unsigned int txd1;
 	unsigned int txd2;
@@ -451,20 +467,41 @@ struct mtk_tx_dma {
 	unsigned int txd4;
 } __packed __aligned(4);
 
+struct mtk_tx_dma_v2 {
+	unsigned int txd1;
+	unsigned int txd2;
+	unsigned int txd3;
+	unsigned int txd4;
+	unsigned int txd5;
+	unsigned int txd6;
+	unsigned int txd7;
+	unsigned int txd8;
+} __packed __aligned(4);
+
 /* PDMA TXD fields */
 #define PDMA_TXD2_DDONE			BIT(31)
 #define PDMA_TXD2_LS0			BIT(30)
-#define PDMA_TXD2_SDL0_M		GENMASK(29, 16)
-#define PDMA_TXD2_SDL0_SET(_v)	FIELD_PREP(PDMA_TXD2_SDL0_M, (_v))
+#define PDMA_V1_TXD2_SDL0_M		GENMASK(29, 16)
+#define PDMA_V1_TXD2_SDL0_SET(_v)	FIELD_PREP(PDMA_V1_TXD2_SDL0_M, (_v))
+#define PDMA_V2_TXD2_SDL0_M		GENMASK(23, 8)
+#define PDMA_V2_TXD2_SDL0_SET(_v)	FIELD_PREP(PDMA_V2_TXD2_SDL0_M, (_v))
+
+#define PDMA_V1_TXD4_FPORT_M		GENMASK(27, 25)
+#define PDMA_V1_TXD4_FPORT_SET(_v)	FIELD_PREP(PDMA_V1_TXD4_FPORT_M, (_v))
+#define PDMA_V2_TXD4_FPORT_M		GENMASK(27, 24)
+#define PDMA_V2_TXD4_FPORT_SET(_v)	FIELD_PREP(PDMA_V2_TXD4_FPORT_M, (_v))
 
-#define PDMA_TXD4_FPORT_M		GENMASK(27, 25)
-#define PDMA_TXD4_FPORT_SET(_v)	FIELD_PREP(PDMA_TXD4_FPORT_M, (_v))
+#define PDMA_V2_TXD5_FPORT_M		GENMASK(19, 16)
+#define PDMA_V2_TXD5_FPORT_SET(_v)	FIELD_PREP(PDMA_V2_TXD5_FPORT_M, (_v))
 
 /* PDMA RXD fields */
 #define PDMA_RXD2_DDONE			BIT(31)
 #define PDMA_RXD2_LS0			BIT(30)
-#define PDMA_RXD2_PLEN0_M		GENMASK(29, 16)
-#define PDMA_RXD2_PLEN0_GET(_v)	FIELD_GET(PDMA_RXD2_PLEN0_M, (_v))
-#define PDMA_RXD2_PLEN0_SET(_v)	FIELD_PREP(PDMA_RXD2_PLEN0_M, (_v))
+#define PDMA_V1_RXD2_PLEN0_M		GENMASK(29, 16)
+#define PDMA_V1_RXD2_PLEN0_GET(_v)	FIELD_GET(PDMA_V1_RXD2_PLEN0_M, (_v))
+#define PDMA_V1_RXD2_PLEN0_SET(_v)	FIELD_PREP(PDMA_V1_RXD2_PLEN0_M, (_v))
+#define PDMA_V2_RXD2_PLEN0_M		GENMASK(23, 8)
+#define PDMA_V2_RXD2_PLEN0_GET(_v)	FIELD_GET(PDMA_V2_RXD2_PLEN0_M, (_v))
+#define PDMA_V2_RXD2_PLEN0_SET(_v)	FIELD_PREP(PDMA_V2_RXD2_PLEN0_M, (_v))
 
 #endif /* _MTK_ETH_H_ */
-- 
2.17.1


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

* [PATCH v2 09/32] net: mediatek: add support for MediaTek MT7981/MT7986
  2022-08-31 11:00 [PATCH v2 00/32] Add support for MediaTek MT7981/MT7986 SoCs - v2 Weijie Gao
                   ` (7 preceding siblings ...)
  2022-08-31 11:04 ` [PATCH v2 08/32] net: mediatek: add support for PDMA v2 Weijie Gao
@ 2022-08-31 11:04 ` Weijie Gao
  2022-09-01  0:22   ` Daniel Golle
  2022-08-31 11:04 ` [PATCH v2 10/32] serial: mtk: add support for using dynamic baud clock souce Weijie Gao
                   ` (22 subsequent siblings)
  31 siblings, 1 reply; 60+ messages in thread
From: Weijie Gao @ 2022-08-31 11:04 UTC (permalink / raw)
  To: u-boot; +Cc: GSS_MTK_Uboot_upstream, Joe Hershberger, Ramon Fried, Weijie Gao

This patch adds support for MediaTek MT7981 and MT7986. Both chips uses
PDMA v2.

Reviewed-by: Ramon Fried <rfried.dev@gmail.com>
Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
---
v2 changes: none
---
 drivers/net/mtk_eth.c | 27 +++++++++++++++++++++++++++
 drivers/net/mtk_eth.h |  5 +++++
 2 files changed, 32 insertions(+)

diff --git a/drivers/net/mtk_eth.c b/drivers/net/mtk_eth.c
index fb72baae68..4c9fb266c7 100644
--- a/drivers/net/mtk_eth.c
+++ b/drivers/net/mtk_eth.c
@@ -115,6 +115,7 @@ struct mtk_eth_priv {
 	int force_mode;
 	int speed;
 	int duplex;
+	bool pn_swap;
 
 	struct phy_device *phydev;
 	int phy_interface;
@@ -1057,6 +1058,12 @@ static void mtk_sgmii_init(struct mtk_eth_priv *priv)
 	/* SGMII force mode setting */
 	writel(SGMII_FORCE_MODE, priv->sgmii_base + SGMSYS_SGMII_MODE);
 
+	/* SGMII PN SWAP setting */
+	if (priv->pn_swap) {
+		setbits_le32(priv->sgmii_base + SGMSYS_QPHY_WRAP_CTRL,
+			     SGMII_PN_SWAP_TX_RX);
+	}
+
 	/* Release PHYA power down state */
 	clrsetbits_le32(priv->sgmii_base + SGMSYS_QPHY_PWR_STATE_CTRL,
 			SGMII_PHYA_PWD, 0);
@@ -1470,6 +1477,8 @@ static int mtk_eth_of_to_plat(struct udevice *dev)
 			dev_err(dev, "Unable to find sgmii\n");
 			return -ENODEV;
 		}
+
+		priv->pn_swap = ofnode_read_bool(args.node, "pn_swap");
 	}
 
 	/* check for switch first, otherwise phy will be used */
@@ -1520,6 +1529,22 @@ static int mtk_eth_of_to_plat(struct udevice *dev)
 	return 0;
 }
 
+static const struct mtk_soc_data mt7986_data = {
+	.caps = MT7986_CAPS,
+	.ana_rgc3 = 0x128,
+	.pdma_base = PDMA_V2_BASE,
+	.txd_size = sizeof(struct mtk_tx_dma_v2),
+	.rxd_size = sizeof(struct mtk_rx_dma_v2),
+};
+
+static const struct mtk_soc_data mt7981_data = {
+	.caps = MT7986_CAPS,
+	.ana_rgc3 = 0x128,
+	.pdma_base = PDMA_V2_BASE,
+	.txd_size = sizeof(struct mtk_tx_dma_v2),
+	.rxd_size = sizeof(struct mtk_rx_dma_v2),
+};
+
 static const struct mtk_soc_data mt7629_data = {
 	.ana_rgc3 = 0x128,
 	.pdma_base = PDMA_V1_BASE,
@@ -1549,6 +1574,8 @@ static const struct mtk_soc_data mt7621_data = {
 };
 
 static const struct udevice_id mtk_eth_ids[] = {
+	{ .compatible = "mediatek,mt7986-eth", .data = (ulong)&mt7986_data },
+	{ .compatible = "mediatek,mt7981-eth", .data = (ulong)&mt7981_data },
 	{ .compatible = "mediatek,mt7629-eth", .data = (ulong)&mt7629_data },
 	{ .compatible = "mediatek,mt7623-eth", .data = (ulong)&mt7623_data },
 	{ .compatible = "mediatek,mt7622-eth", .data = (ulong)&mt7622_data },
diff --git a/drivers/net/mtk_eth.h b/drivers/net/mtk_eth.h
index 236c498a1b..1382ccbeb2 100644
--- a/drivers/net/mtk_eth.h
+++ b/drivers/net/mtk_eth.h
@@ -36,6 +36,8 @@ enum mkt_eth_capabilities {
 
 #define MT7623_CAPS  (MTK_GMAC1_TRGMII)
 
+#define MT7986_CAPS  (MTK_NETSYS_V2)
+
 /* Frame Engine Register Bases */
 #define PDMA_V1_BASE			0x0800
 #define PDMA_V2_BASE			0x6000
@@ -72,6 +74,9 @@ enum mkt_eth_capabilities {
 #define SGMSYS_QPHY_PWR_STATE_CTRL	0xe8
 #define SGMII_PHYA_PWD			BIT(4)
 
+#define SGMSYS_QPHY_WRAP_CTRL		0xec
+#define SGMII_PN_SWAP_TX_RX		0x03
+
 #define SGMSYS_GEN2_SPEED		0x2028
 #define SGMSYS_GEN2_SPEED_V2		0x128
 #define SGMSYS_SPEED_2500		BIT(2)
-- 
2.17.1


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

* [PATCH v2 10/32] serial: mtk: add support for using dynamic baud clock souce
  2022-08-31 11:00 [PATCH v2 00/32] Add support for MediaTek MT7981/MT7986 SoCs - v2 Weijie Gao
                   ` (8 preceding siblings ...)
  2022-08-31 11:04 ` [PATCH v2 09/32] net: mediatek: add support for MediaTek MT7981/MT7986 Weijie Gao
@ 2022-08-31 11:04 ` Weijie Gao
  2022-09-01  0:22   ` Daniel Golle
  2022-08-31 11:04 ` [PATCH v2 11/32] arm: dts: mt7622: force high-speed mode for uart Weijie Gao
                   ` (21 subsequent siblings)
  31 siblings, 1 reply; 60+ messages in thread
From: Weijie Gao @ 2022-08-31 11:04 UTC (permalink / raw)
  To: u-boot; +Cc: GSS_MTK_Uboot_upstream, Pali Rohár, Weijie Gao

The baud clock on some platform may change due to assigned-clock-parent
set in DT. In current flow the baud clock is only retrieved during probe
stage. If the parent of the source clock changes after probe stage, the
setbrg will set wrong baudrate.

To get the right clock rate, this patch records the baud clk struct to the
driver's priv, and changes the driver's flow to get the clock rate before
calling _mtk_serial_setbrg().

Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
---
v2 changes:
  Add description for priv struct
  Fix the type of clk_rate
---
 drivers/serial/serial_mtk.c | 80 ++++++++++++++++++++++---------------
 1 file changed, 47 insertions(+), 33 deletions(-)

diff --git a/drivers/serial/serial_mtk.c b/drivers/serial/serial_mtk.c
index a84f39b3fa..1d7cc9f7b6 100644
--- a/drivers/serial/serial_mtk.c
+++ b/drivers/serial/serial_mtk.c
@@ -10,6 +10,7 @@
 #include <common.h>
 #include <div64.h>
 #include <dm.h>
+#include <dm/device_compat.h>
 #include <errno.h>
 #include <log.h>
 #include <serial.h>
@@ -70,27 +71,37 @@ struct mtk_serial_regs {
 #define BAUD_ALLOW_MAX(baud)	((baud) + (baud) * 3 / 100)
 #define BAUD_ALLOW_MIX(baud)	((baud) - (baud) * 3 / 100)
 
+/* struct mtk_serial_priv -	Structure holding all information used by the
+ *				driver
+ * @regs:			Register base of the serial port
+ * @clk:			The baud clock device
+ * @fixed_clk_rate:		Fallback fixed baud clock rate if baud clock
+ *				device is not specified
+ * @force_highspeed:		Force using high-speed mode
+ */
 struct mtk_serial_priv {
 	struct mtk_serial_regs __iomem *regs;
-	u32 clock;
+	struct clk clk;
+	u32 fixed_clk_rate;
 	bool force_highspeed;
 };
 
-static void _mtk_serial_setbrg(struct mtk_serial_priv *priv, int baud)
+static void _mtk_serial_setbrg(struct mtk_serial_priv *priv, int baud,
+			       uint clk_rate)
 {
 	u32 quot, realbaud, samplecount = 1;
 
 	/* Special case for low baud clock */
-	if (baud <= 115200 && priv->clock <= 12000000) {
+	if (baud <= 115200 && clk_rate == 12000000) {
 		writel(3, &priv->regs->highspeed);
 
-		quot = DIV_ROUND_CLOSEST(priv->clock, 256 * baud);
+		quot = DIV_ROUND_CLOSEST(clk_rate, 256 * baud);
 		if (quot == 0)
 			quot = 1;
 
-		samplecount = DIV_ROUND_CLOSEST(priv->clock, quot * baud);
+		samplecount = DIV_ROUND_CLOSEST(clk_rate, quot * baud);
 
-		realbaud = priv->clock / samplecount / quot;
+		realbaud = clk_rate / samplecount / quot;
 		if (realbaud > BAUD_ALLOW_MAX(baud) ||
 		    realbaud < BAUD_ALLOW_MIX(baud)) {
 			pr_info("baud %d can't be handled\n", baud);
@@ -104,7 +115,7 @@ static void _mtk_serial_setbrg(struct mtk_serial_priv *priv, int baud)
 
 	if (baud <= 115200) {
 		writel(0, &priv->regs->highspeed);
-		quot = DIV_ROUND_CLOSEST(priv->clock, 16 * baud);
+		quot = DIV_ROUND_CLOSEST(clk_rate, 16 * baud);
 	} else if (baud <= 576000) {
 		writel(2, &priv->regs->highspeed);
 
@@ -112,13 +123,13 @@ static void _mtk_serial_setbrg(struct mtk_serial_priv *priv, int baud)
 		if ((baud == 500000) || (baud == 576000))
 			baud = 460800;
 
-		quot = DIV_ROUND_UP(priv->clock, 4 * baud);
+		quot = DIV_ROUND_UP(clk_rate, 4 * baud);
 	} else {
 use_hs3:
 		writel(3, &priv->regs->highspeed);
 
-		quot = DIV_ROUND_UP(priv->clock, 256 * baud);
-		samplecount = DIV_ROUND_CLOSEST(priv->clock, quot * baud);
+		quot = DIV_ROUND_UP(clk_rate, 256 * baud);
+		samplecount = DIV_ROUND_CLOSEST(clk_rate, quot * baud);
 	}
 
 set_baud:
@@ -167,8 +178,13 @@ static int _mtk_serial_pending(struct mtk_serial_priv *priv, bool input)
 static int mtk_serial_setbrg(struct udevice *dev, int baudrate)
 {
 	struct mtk_serial_priv *priv = dev_get_priv(dev);
+	u32 clk_rate;
+
+	clk_rate = clk_get_rate(&priv->clk);
+	if (IS_ERR_VALUE(clk_rate) || clk_rate == 0)
+		clk_rate = priv->fixed_clk_rate;
 
-	_mtk_serial_setbrg(priv, baudrate);
+	_mtk_serial_setbrg(priv, baudrate, clk_rate);
 
 	return 0;
 }
@@ -211,7 +227,6 @@ static int mtk_serial_of_to_plat(struct udevice *dev)
 {
 	struct mtk_serial_priv *priv = dev_get_priv(dev);
 	fdt_addr_t addr;
-	struct clk clk;
 	int err;
 
 	addr = dev_read_addr(dev);
@@ -220,22 +235,19 @@ static int mtk_serial_of_to_plat(struct udevice *dev)
 
 	priv->regs = map_physmem(addr, 0, MAP_NOCACHE);
 
-	err = clk_get_by_index(dev, 0, &clk);
-	if (!err) {
-		err = clk_get_rate(&clk);
-		if (!IS_ERR_VALUE(err))
-			priv->clock = err;
-	} else if (err != -ENOENT && err != -ENODEV && err != -ENOSYS) {
-		debug("mtk_serial: failed to get clock\n");
-		return err;
-	}
-
-	if (!priv->clock)
-		priv->clock = dev_read_u32_default(dev, "clock-frequency", 0);
-
-	if (!priv->clock) {
-		debug("mtk_serial: clock not defined\n");
-		return -EINVAL;
+	err = clk_get_by_index(dev, 0, &priv->clk);
+	if (err) {
+		err = dev_read_u32(dev, "clock-frequency", &priv->fixed_clk_rate);
+		if (err) {
+			dev_err(dev, "baud clock not defined\n");
+			return -EINVAL;
+		}
+	} else {
+		err = clk_get_rate(&priv->clk);
+		if (IS_ERR_VALUE(err)) {
+			dev_err(dev, "invalid baud clock\n");
+			return -EINVAL;
+		}
 	}
 
 	priv->force_highspeed = dev_read_bool(dev, "mediatek,force-highspeed");
@@ -273,7 +285,7 @@ DECLARE_GLOBAL_DATA_PTR;
 #define DECLARE_HSUART_PRIV(port) \
 	static struct mtk_serial_priv mtk_hsuart##port = { \
 	.regs = (struct mtk_serial_regs *)CONFIG_SYS_NS16550_COM##port, \
-	.clock = CONFIG_SYS_NS16550_CLK \
+	.fixed_clk_rate = CONFIG_SYS_NS16550_CLK \
 };
 
 #define DECLARE_HSUART_FUNCTIONS(port) \
@@ -282,12 +294,14 @@ DECLARE_GLOBAL_DATA_PTR;
 		writel(0, &mtk_hsuart##port.regs->ier); \
 		writel(UART_MCRVAL, &mtk_hsuart##port.regs->mcr); \
 		writel(UART_FCRVAL, &mtk_hsuart##port.regs->fcr); \
-		_mtk_serial_setbrg(&mtk_hsuart##port, gd->baudrate); \
+		_mtk_serial_setbrg(&mtk_hsuart##port, gd->baudrate, \
+				   mtk_hsuart##port.fixed_clk_rate); \
 		return 0 ; \
 	} \
 	static void mtk_serial##port##_setbrg(void) \
 	{ \
-		_mtk_serial_setbrg(&mtk_hsuart##port, gd->baudrate); \
+		_mtk_serial_setbrg(&mtk_hsuart##port, gd->baudrate, \
+				   mtk_hsuart##port.fixed_clk_rate); \
 	} \
 	static int mtk_serial##port##_getc(void) \
 	{ \
@@ -427,13 +441,13 @@ static inline void _debug_uart_init(void)
 	struct mtk_serial_priv priv;
 
 	priv.regs = (void *) CONFIG_VAL(DEBUG_UART_BASE);
-	priv.clock = CONFIG_DEBUG_UART_CLOCK;
+	priv.fixed_clk_rate = CONFIG_DEBUG_UART_CLOCK;
 
 	writel(0, &priv.regs->ier);
 	writel(UART_MCRVAL, &priv.regs->mcr);
 	writel(UART_FCRVAL, &priv.regs->fcr);
 
-	_mtk_serial_setbrg(&priv, CONFIG_BAUDRATE);
+	_mtk_serial_setbrg(&priv, CONFIG_BAUDRATE, priv.fixed_clk_rate);
 }
 
 static inline void _debug_uart_putc(int ch)
-- 
2.17.1


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

* [PATCH v2 11/32] arm: dts: mt7622: force high-speed mode for uart
  2022-08-31 11:00 [PATCH v2 00/32] Add support for MediaTek MT7981/MT7986 SoCs - v2 Weijie Gao
                   ` (9 preceding siblings ...)
  2022-08-31 11:04 ` [PATCH v2 10/32] serial: mtk: add support for using dynamic baud clock souce Weijie Gao
@ 2022-08-31 11:04 ` Weijie Gao
  2022-09-01  0:23   ` Daniel Golle
  2022-08-31 11:04 ` [PATCH v2 12/32] pwm: mtk: add support for MediaTek MT7986 SoC Weijie Gao
                   ` (20 subsequent siblings)
  31 siblings, 1 reply; 60+ messages in thread
From: Weijie Gao @ 2022-08-31 11:04 UTC (permalink / raw)
  To: u-boot; +Cc: GSS_MTK_Uboot_upstream, Weijie Gao

The input clock for uart is too slow (25MHz) which introduces frequent data
error on both receiving and transmitting even if the baudrate is 115200.

Using high-speed can significantly solve this issue.

Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
---
v2 changes: none
---
 arch/arm/dts/mt7622.dtsi | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/dts/mt7622.dtsi b/arch/arm/dts/mt7622.dtsi
index 0127474c95..fb6c1b7154 100644
--- a/arch/arm/dts/mt7622.dtsi
+++ b/arch/arm/dts/mt7622.dtsi
@@ -175,6 +175,7 @@
 		status = "disabled";
 		assigned-clocks = <&topckgen CLK_TOP_AXI_SEL>;
 		assigned-clock-parents = <&topckgen CLK_TOP_SYSPLL1_D2>;
+		mediatek,force-highspeed;
 	};
 
 	mmc0: mmc@11230000 {
-- 
2.17.1


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

* [PATCH v2 12/32] pwm: mtk: add support for MediaTek MT7986 SoC
  2022-08-31 11:00 [PATCH v2 00/32] Add support for MediaTek MT7981/MT7986 SoCs - v2 Weijie Gao
                   ` (10 preceding siblings ...)
  2022-08-31 11:04 ` [PATCH v2 11/32] arm: dts: mt7622: force high-speed mode for uart Weijie Gao
@ 2022-08-31 11:04 ` Weijie Gao
  2022-08-31 11:04 ` [PATCH v2 13/32] pwm: mtk: add support for MediaTek MT7981 SoC Weijie Gao
                   ` (19 subsequent siblings)
  31 siblings, 0 replies; 60+ messages in thread
From: Weijie Gao @ 2022-08-31 11:04 UTC (permalink / raw)
  To: u-boot; +Cc: GSS_MTK_Uboot_upstream, Weijie Gao

This patch adds PWM support for MediaTek MT7986 SoC.

Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
---
v2 changes: none
---
 drivers/pwm/pwm-mtk.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/pwm/pwm-mtk.c b/drivers/pwm/pwm-mtk.c
index aee1d825a0..3100b5caaf 100644
--- a/drivers/pwm/pwm-mtk.c
+++ b/drivers/pwm/pwm-mtk.c
@@ -171,10 +171,16 @@ static const struct mtk_pwm_soc mt7629_data = {
 	.pwm45_fixup = false,
 };
 
+static const struct mtk_pwm_soc mt7986_data = {
+	.num_pwms = 2,
+	.pwm45_fixup = false,
+};
+
 static const struct udevice_id mtk_pwm_ids[] = {
 	{ .compatible = "mediatek,mt7622-pwm", .data = (ulong)&mt7622_data },
 	{ .compatible = "mediatek,mt7623-pwm", .data = (ulong)&mt7623_data },
 	{ .compatible = "mediatek,mt7629-pwm", .data = (ulong)&mt7629_data },
+	{ .compatible = "mediatek,mt7986-pwm", .data = (ulong)&mt7986_data },
 	{ }
 };
 
-- 
2.17.1


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

* [PATCH v2 13/32] pwm: mtk: add support for MediaTek MT7981 SoC
  2022-08-31 11:00 [PATCH v2 00/32] Add support for MediaTek MT7981/MT7986 SoCs - v2 Weijie Gao
                   ` (11 preceding siblings ...)
  2022-08-31 11:04 ` [PATCH v2 12/32] pwm: mtk: add support for MediaTek MT7986 SoC Weijie Gao
@ 2022-08-31 11:04 ` Weijie Gao
  2022-08-31 11:04 ` [PATCH v2 14/32] timer: mtk: add support for MediaTek MT7981/MT7986 SoCs Weijie Gao
                   ` (18 subsequent siblings)
  31 siblings, 0 replies; 60+ messages in thread
From: Weijie Gao @ 2022-08-31 11:04 UTC (permalink / raw)
  To: u-boot; +Cc: GSS_MTK_Uboot_upstream, Weijie Gao

This patch adds PWM support for MediaTek MT7981 SoC.
MT7981 uses a different register offset so we have to add a version field
to indicate the IP core version.

Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
---
v2 changes: none
---
 drivers/pwm/pwm-mtk.c | 34 ++++++++++++++++++++++++++++++++--
 1 file changed, 32 insertions(+), 2 deletions(-)

diff --git a/drivers/pwm/pwm-mtk.c b/drivers/pwm/pwm-mtk.c
index 3100b5caaf..605142eab0 100644
--- a/drivers/pwm/pwm-mtk.c
+++ b/drivers/pwm/pwm-mtk.c
@@ -29,13 +29,23 @@
 
 #define NSEC_PER_SEC 1000000000L
 
-static const unsigned int mtk_pwm_reg_offset[] = {
+enum mtk_pwm_reg_ver {
+	PWM_REG_V1,
+	PWM_REG_V2,
+};
+
+static const unsigned int mtk_pwm_reg_offset_v1[] = {
 	0x0010, 0x0050, 0x0090, 0x00d0, 0x0110, 0x0150, 0x0190, 0x0220
 };
 
+static const unsigned int mtk_pwm_reg_offset_v2[] = {
+	0x0080, 0x00c0, 0x0100, 0x0140, 0x0180, 0x01c0, 0x0200, 0x0240
+};
+
 struct mtk_pwm_soc {
 	unsigned int num_pwms;
 	bool pwm45_fixup;
+	enum mtk_pwm_reg_ver reg_ver;
 };
 
 struct mtk_pwm_priv {
@@ -49,7 +59,16 @@ struct mtk_pwm_priv {
 static void mtk_pwm_w32(struct udevice *dev, uint channel, uint reg, uint val)
 {
 	struct mtk_pwm_priv *priv = dev_get_priv(dev);
-	u32 offset = mtk_pwm_reg_offset[channel];
+	u32 offset;
+
+	switch (priv->soc->reg_ver) {
+	case PWM_REG_V2:
+		offset = mtk_pwm_reg_offset_v2[channel];
+		break;
+
+	default:
+		offset = mtk_pwm_reg_offset_v1[channel];
+	}
 
 	writel(val, priv->base + offset + reg);
 }
@@ -159,27 +178,38 @@ static const struct pwm_ops mtk_pwm_ops = {
 static const struct mtk_pwm_soc mt7622_data = {
 	.num_pwms = 6,
 	.pwm45_fixup = false,
+	.reg_ver = PWM_REG_V1,
 };
 
 static const struct mtk_pwm_soc mt7623_data = {
 	.num_pwms = 5,
 	.pwm45_fixup = true,
+	.reg_ver = PWM_REG_V1,
 };
 
 static const struct mtk_pwm_soc mt7629_data = {
 	.num_pwms = 1,
 	.pwm45_fixup = false,
+	.reg_ver = PWM_REG_V1,
+};
+
+static const struct mtk_pwm_soc mt7981_data = {
+	.num_pwms = 2,
+	.pwm45_fixup = false,
+	.reg_ver = PWM_REG_V2,
 };
 
 static const struct mtk_pwm_soc mt7986_data = {
 	.num_pwms = 2,
 	.pwm45_fixup = false,
+	.reg_ver = PWM_REG_V1,
 };
 
 static const struct udevice_id mtk_pwm_ids[] = {
 	{ .compatible = "mediatek,mt7622-pwm", .data = (ulong)&mt7622_data },
 	{ .compatible = "mediatek,mt7623-pwm", .data = (ulong)&mt7623_data },
 	{ .compatible = "mediatek,mt7629-pwm", .data = (ulong)&mt7629_data },
+	{ .compatible = "mediatek,mt7981-pwm", .data = (ulong)&mt7981_data },
 	{ .compatible = "mediatek,mt7986-pwm", .data = (ulong)&mt7986_data },
 	{ }
 };
-- 
2.17.1


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

* [PATCH v2 14/32] timer: mtk: add support for MediaTek MT7981/MT7986 SoCs
  2022-08-31 11:00 [PATCH v2 00/32] Add support for MediaTek MT7981/MT7986 SoCs - v2 Weijie Gao
                   ` (12 preceding siblings ...)
  2022-08-31 11:04 ` [PATCH v2 13/32] pwm: mtk: add support for MediaTek MT7981 SoC Weijie Gao
@ 2022-08-31 11:04 ` Weijie Gao
  2022-09-01  0:24   ` Daniel Golle
  2022-08-31 11:04 ` [PATCH v2 15/32] watchdog: mediatek: add support for MediaTek MT7986 SoC Weijie Gao
                   ` (17 subsequent siblings)
  31 siblings, 1 reply; 60+ messages in thread
From: Weijie Gao @ 2022-08-31 11:04 UTC (permalink / raw)
  To: u-boot; +Cc: GSS_MTK_Uboot_upstream, Weijie Gao

This patch add general-purpose timer support for MediaTek MT7981/MT7986.
These two SoCs uses a newer version of timer with its register definition
slightly changed.

Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
---
v2 changes: none
---
 drivers/timer/mtk_timer.c | 59 ++++++++++++++++++++++++---------------
 1 file changed, 37 insertions(+), 22 deletions(-)

diff --git a/drivers/timer/mtk_timer.c b/drivers/timer/mtk_timer.c
index f6b97f868c..223e63f6c1 100644
--- a/drivers/timer/mtk_timer.c
+++ b/drivers/timer/mtk_timer.c
@@ -13,24 +13,32 @@
 #include <asm/io.h>
 #include <linux/bitops.h>
 
-#define MTK_GPT4_CTRL	0x40
-#define MTK_GPT4_CLK	0x44
-#define MTK_GPT4_CNT	0x48
+#define MTK_GPT4_OFFSET_V1	0x40
+#define MTK_GPT4_OFFSET_V2	0x80
 
-#define GPT4_ENABLE	BIT(0)
-#define GPT4_CLEAR	BIT(1)
-#define GPT4_FREERUN	GENMASK(5, 4)
-#define GPT4_CLK_SYS	0x0
-#define GPT4_CLK_DIV1	0x0
+#define MTK_GPT_CON		0x0
+#define MTK_GPT_V1_CLK		0x4
+#define MTK_GPT_CNT		0x8
+
+#define GPT_ENABLE		BIT(0)
+#define GPT_CLEAR		BIT(1)
+#define GPT_V1_FREERUN		GENMASK(5, 4)
+#define GPT_V2_FREERUN		GENMASK(6, 5)
+
+enum mtk_gpt_ver {
+	MTK_GPT_V1,
+	MTK_GPT_V2
+};
 
 struct mtk_timer_priv {
 	void __iomem *base;
+	unsigned int gpt4_offset;
 };
 
 static u64 mtk_timer_get_count(struct udevice *dev)
 {
 	struct mtk_timer_priv *priv = dev_get_priv(dev);
-	u32 val = readl(priv->base + MTK_GPT4_CNT);
+	u32 val = readl(priv->base + priv->gpt4_offset + MTK_GPT_CNT);
 
 	return timer_conv_64(val);
 }
@@ -40,12 +48,27 @@ static int mtk_timer_probe(struct udevice *dev)
 	struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
 	struct mtk_timer_priv *priv = dev_get_priv(dev);
 	struct clk clk, parent;
-	int ret;
+	int ret, gpt_ver;
 
 	priv->base = dev_read_addr_ptr(dev);
+	gpt_ver = dev_get_driver_data(dev);
+
 	if (!priv->base)
 		return -ENOENT;
 
+	if (gpt_ver == MTK_GPT_V2) {
+		priv->gpt4_offset = MTK_GPT4_OFFSET_V2;
+
+		writel(GPT_V2_FREERUN | GPT_CLEAR | GPT_ENABLE,
+		       priv->base + priv->gpt4_offset + MTK_GPT_CON);
+	} else {
+		priv->gpt4_offset = MTK_GPT4_OFFSET_V1;
+
+		writel(GPT_V1_FREERUN | GPT_CLEAR | GPT_ENABLE,
+		       priv->base + priv->gpt4_offset + MTK_GPT_CON);
+		writel(0, priv->base + priv->gpt4_offset + MTK_GPT_V1_CLK);
+	}
+
 	ret = clk_get_by_index(dev, 0, &clk);
 	if (ret)
 		return ret;
@@ -61,16 +84,6 @@ static int mtk_timer_probe(struct udevice *dev)
 	if (!uc_priv->clock_rate)
 		return -EINVAL;
 
-	/*
-	 * Initialize the timer:
-	 * 1. set clock source to system clock with clock divider setting to 1
-	 * 2. set timer mode to free running
-	 * 3. reset timer counter to 0 then enable the timer
-	 */
-	writel(GPT4_CLK_SYS | GPT4_CLK_DIV1, priv->base + MTK_GPT4_CLK);
-	writel(GPT4_FREERUN | GPT4_CLEAR | GPT4_ENABLE,
-	       priv->base + MTK_GPT4_CTRL);
-
 	return 0;
 }
 
@@ -79,8 +92,10 @@ static const struct timer_ops mtk_timer_ops = {
 };
 
 static const struct udevice_id mtk_timer_ids[] = {
-	{ .compatible = "mediatek,timer" },
-	{ .compatible = "mediatek,mt6577-timer" },
+	{ .compatible = "mediatek,timer", .data = MTK_GPT_V1 },
+	{ .compatible = "mediatek,mt6577-timer", .data = MTK_GPT_V1 },
+	{ .compatible = "mediatek,mt7981-timer", .data = MTK_GPT_V2 },
+	{ .compatible = "mediatek,mt7986-timer", .data = MTK_GPT_V2 },
 	{ }
 };
 
-- 
2.17.1


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

* [PATCH v2 15/32] watchdog: mediatek: add support for MediaTek MT7986 SoC
  2022-08-31 11:00 [PATCH v2 00/32] Add support for MediaTek MT7981/MT7986 SoCs - v2 Weijie Gao
                   ` (13 preceding siblings ...)
  2022-08-31 11:04 ` [PATCH v2 14/32] timer: mtk: add support for MediaTek MT7981/MT7986 SoCs Weijie Gao
@ 2022-08-31 11:04 ` Weijie Gao
  2022-09-01  0:25   ` Daniel Golle
  2022-08-31 11:04 ` [PATCH v2 16/32] spi: add support for MediaTek spi-mem controller Weijie Gao
                   ` (16 subsequent siblings)
  31 siblings, 1 reply; 60+ messages in thread
From: Weijie Gao @ 2022-08-31 11:04 UTC (permalink / raw)
  To: u-boot; +Cc: GSS_MTK_Uboot_upstream, Stefan Roese, Weijie Gao

Add watchdog support for MediaTek MT7986 SoC

Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
---
v2 changes: none
---
 drivers/watchdog/mtk_wdt.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/watchdog/mtk_wdt.c b/drivers/watchdog/mtk_wdt.c
index b098b2e3cf..368b36849c 100644
--- a/drivers/watchdog/mtk_wdt.c
+++ b/drivers/watchdog/mtk_wdt.c
@@ -145,6 +145,7 @@ static const struct wdt_ops mtk_wdt_ops = {
 static const struct udevice_id mtk_wdt_ids[] = {
 	{ .compatible = "mediatek,wdt"},
 	{ .compatible = "mediatek,mt6589-wdt"},
+	{ .compatible = "mediatek,mt7986-wdt" },
 	{}
 };
 
-- 
2.17.1


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

* [PATCH v2 16/32] spi: add support for MediaTek spi-mem controller
  2022-08-31 11:00 [PATCH v2 00/32] Add support for MediaTek MT7981/MT7986 SoCs - v2 Weijie Gao
                   ` (14 preceding siblings ...)
  2022-08-31 11:04 ` [PATCH v2 15/32] watchdog: mediatek: add support for MediaTek MT7986 SoC Weijie Gao
@ 2022-08-31 11:04 ` Weijie Gao
  2022-09-01  0:25   ` Daniel Golle
  2022-08-31 11:04 ` [PATCH v2 17/32] i2c: add support for MediaTek I2C interface Weijie Gao
                   ` (15 subsequent siblings)
  31 siblings, 1 reply; 60+ messages in thread
From: Weijie Gao @ 2022-08-31 11:04 UTC (permalink / raw)
  To: u-boot; +Cc: GSS_MTK_Uboot_upstream, Jagan Teki, Weijie Gao, SkyLake . Huang

This patch adds support for spi-mem controller found on newer MediaTek SoCs
This controller supports Single/Dual/Quad SPI mode.

Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
---
v2 changes:
  Remove unused code
  Fix coding style
  Add description for struct fields
---
 drivers/spi/Kconfig    |   8 +
 drivers/spi/Makefile   |   1 +
 drivers/spi/mtk_spim.c | 701 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 710 insertions(+)
 create mode 100644 drivers/spi/mtk_spim.c

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 75b794548b..7e72ab9c24 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -276,6 +276,14 @@ config MTK_SNFI_SPI
 	  used to access SPI memory devices like SPI-NOR or SPI-NAND on
 	  platforms embedding this IP core, like MT7622/M7629.
 
+config MTK_SPIM
+	bool "Mediatek SPI-MEM master controller driver"
+	depends on SPI_MEM
+	help
+	  Enable MediaTek SPI-MEM master controller driver. This driver mainly
+	  supports SPI flashes. You can use single, dual or quad mode
+	  transmission on this controller.
+
 config MVEBU_A3700_SPI
 	bool "Marvell Armada 3700 SPI driver"
 	select CLK_ARMADA_3720
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 4de77c260a..309f6b5328 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -43,6 +43,7 @@ obj-$(CONFIG_MPC8XX_SPI) += mpc8xx_spi.o
 obj-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o
 obj-$(CONFIG_MTK_SNFI_SPI) += mtk_snfi_spi.o
 obj-$(CONFIG_MTK_SNOR) += mtk_snor.o
+obj-$(CONFIG_MTK_SPIM) += mtk_spim.o
 obj-$(CONFIG_MT7620_SPI) += mt7620_spi.o
 obj-$(CONFIG_MT7621_SPI) += mt7621_spi.o
 obj-$(CONFIG_MSCC_BB_SPI) += mscc_bb_spi.o
diff --git a/drivers/spi/mtk_spim.c b/drivers/spi/mtk_spim.c
new file mode 100644
index 0000000000..b45ef529a5
--- /dev/null
+++ b/drivers/spi/mtk_spim.c
@@ -0,0 +1,701 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2022 MediaTek Inc. All Rights Reserved.
+ *
+ * Author: SkyLake.Huang <skylake.huang@mediatek.com>
+ */
+
+#include <clk.h>
+#include <cpu_func.h>
+#include <div64.h>
+#include <dm.h>
+#include <spi.h>
+#include <spi-mem.h>
+#include <stdbool.h>
+#include <watchdog.h>
+#include <dm/device.h>
+#include <dm/device_compat.h>
+#include <dm/devres.h>
+#include <dm/pinctrl.h>
+#include <linux/bitops.h>
+#include <linux/completion.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+
+#define SPI_CFG0_REG				0x0000
+#define SPI_CFG1_REG				0x0004
+#define SPI_TX_SRC_REG				0x0008
+#define SPI_RX_DST_REG				0x000c
+#define SPI_TX_DATA_REG				0x0010
+#define SPI_RX_DATA_REG				0x0014
+#define SPI_CMD_REG				0x0018
+#define SPI_IRQ_REG				0x001c
+#define SPI_STATUS_REG				0x0020
+#define SPI_PAD_SEL_REG				0x0024
+#define SPI_CFG2_REG				0x0028
+#define SPI_TX_SRC_REG_64			0x002c
+#define SPI_RX_DST_REG_64			0x0030
+#define SPI_CFG3_IPM_REG			0x0040
+
+#define SPI_CFG0_SCK_HIGH_OFFSET		0
+#define SPI_CFG0_SCK_LOW_OFFSET			8
+#define SPI_CFG0_CS_HOLD_OFFSET			16
+#define SPI_CFG0_CS_SETUP_OFFSET		24
+#define SPI_ADJUST_CFG0_CS_HOLD_OFFSET		0
+#define SPI_ADJUST_CFG0_CS_SETUP_OFFSET		16
+
+#define SPI_CFG1_CS_IDLE_OFFSET			0
+#define SPI_CFG1_PACKET_LOOP_OFFSET		8
+#define SPI_CFG1_PACKET_LENGTH_OFFSET		16
+#define SPI_CFG1_GET_TICKDLY_OFFSET		29
+
+#define SPI_CFG1_GET_TICKDLY_MASK		GENMASK(31, 29)
+#define SPI_CFG1_CS_IDLE_MASK			0xff
+#define SPI_CFG1_PACKET_LOOP_MASK		0xff00
+#define SPI_CFG1_PACKET_LENGTH_MASK		0x3ff0000
+#define SPI_CFG1_IPM_PACKET_LENGTH_MASK		GENMASK(31, 16)
+#define SPI_CFG2_SCK_HIGH_OFFSET		0
+#define SPI_CFG2_SCK_LOW_OFFSET			16
+#define SPI_CFG2_SCK_HIGH_MASK			GENMASK(15, 0)
+#define SPI_CFG2_SCK_LOW_MASK			GENMASK(31, 16)
+
+#define SPI_CMD_ACT				BIT(0)
+#define SPI_CMD_RESUME				BIT(1)
+#define SPI_CMD_RST				BIT(2)
+#define SPI_CMD_PAUSE_EN			BIT(4)
+#define SPI_CMD_DEASSERT			BIT(5)
+#define SPI_CMD_SAMPLE_SEL			BIT(6)
+#define SPI_CMD_CS_POL				BIT(7)
+#define SPI_CMD_CPHA				BIT(8)
+#define SPI_CMD_CPOL				BIT(9)
+#define SPI_CMD_RX_DMA				BIT(10)
+#define SPI_CMD_TX_DMA				BIT(11)
+#define SPI_CMD_TXMSBF				BIT(12)
+#define SPI_CMD_RXMSBF				BIT(13)
+#define SPI_CMD_RX_ENDIAN			BIT(14)
+#define SPI_CMD_TX_ENDIAN			BIT(15)
+#define SPI_CMD_FINISH_IE			BIT(16)
+#define SPI_CMD_PAUSE_IE			BIT(17)
+#define SPI_CMD_IPM_NONIDLE_MODE		BIT(19)
+#define SPI_CMD_IPM_SPIM_LOOP			BIT(21)
+#define SPI_CMD_IPM_GET_TICKDLY_OFFSET		22
+
+#define SPI_CMD_IPM_GET_TICKDLY_MASK		GENMASK(24, 22)
+
+#define PIN_MODE_CFG(x)				((x) / 2)
+
+#define SPI_CFG3_IPM_PIN_MODE_OFFSET		0
+#define SPI_CFG3_IPM_HALF_DUPLEX_DIR		BIT(2)
+#define SPI_CFG3_IPM_HALF_DUPLEX_EN		BIT(3)
+#define SPI_CFG3_IPM_XMODE_EN			BIT(4)
+#define SPI_CFG3_IPM_NODATA_FLAG		BIT(5)
+#define SPI_CFG3_IPM_CMD_BYTELEN_OFFSET		8
+#define SPI_CFG3_IPM_ADDR_BYTELEN_OFFSET	12
+#define SPI_CFG3_IPM_DUMMY_BYTELEN_OFFSET	16
+
+#define SPI_CFG3_IPM_CMD_PIN_MODE_MASK		GENMASK(1, 0)
+#define SPI_CFG3_IPM_CMD_BYTELEN_MASK		GENMASK(11, 8)
+#define SPI_CFG3_IPM_ADDR_BYTELEN_MASK		GENMASK(15, 12)
+#define SPI_CFG3_IPM_DUMMY_BYTELEN_MASK		GENMASK(19, 16)
+
+#define MT8173_SPI_MAX_PAD_SEL			3
+
+#define MTK_SPI_PAUSE_INT_STATUS		0x2
+
+#define MTK_SPI_IDLE				0
+#define MTK_SPI_PAUSED				1
+
+#define MTK_SPI_MAX_FIFO_SIZE			32U
+#define MTK_SPI_PACKET_SIZE			1024
+#define MTK_SPI_IPM_PACKET_SIZE			SZ_64K
+#define MTK_SPI_IPM_PACKET_LOOP			SZ_256
+
+#define MTK_SPI_32BITS_MASK			0xffffffff
+
+#define DMA_ADDR_EXT_BITS			36
+#define DMA_ADDR_DEF_BITS			32
+
+#define CLK_TO_US(freq, clkcnt) DIV_ROUND_UP((clkcnt), (freq) / 1000000)
+
+/* struct mtk_spim_capability
+ * @enhance_timing:	Some IC design adjust cfg register to enhance time accuracy
+ * @dma_ext:		Some IC support DMA addr extension
+ * @ipm_design:		The IPM IP design improves some features, and supports dual/quad mode
+ * @support_quad:	Whether quad mode is supported
+ */
+struct mtk_spim_capability {
+	bool enhance_timing;
+	bool dma_ext;
+	bool ipm_design;
+	bool support_quad;
+};
+
+/* struct mtk_spim_priv
+ * @base:		Base address of the spi controller
+ * @state:		Controller state
+ * @sel_clk:		Pad clock
+ * @spi_clk:		Core clock
+ * @xfer_len:		Current length of data for transfer
+ * @hw_cap:		Controller capabilities
+ * @tick_dly:		Used to postpone SPI sampling time
+ * @sample_sel:		Sample edge of MISO
+ * @dev:		udevice of this spi controller
+ * @tx_dma:		Tx DMA address
+ * @rx_dma:		Rx DMA address
+ */
+struct mtk_spim_priv {
+	void __iomem *base;
+	u32 state;
+	struct clk sel_clk, spi_clk;
+	u32 xfer_len;
+	struct mtk_spim_capability hw_cap;
+	u32 tick_dly;
+	u32 sample_sel;
+
+	struct device *dev;
+	dma_addr_t tx_dma;
+	dma_addr_t rx_dma;
+};
+
+static void mtk_spim_reset(struct mtk_spim_priv *priv)
+{
+	/* set the software reset bit in SPI_CMD_REG. */
+	setbits_le32(priv->base + SPI_CMD_REG, SPI_CMD_RST);
+	clrbits_le32(priv->base + SPI_CMD_REG, SPI_CMD_RST);
+}
+
+static int mtk_spim_hw_init(struct spi_slave *slave)
+{
+	struct udevice *bus = dev_get_parent(slave->dev);
+	struct mtk_spim_priv *priv = dev_get_priv(bus);
+	u16 cpha, cpol;
+	u32 reg_val;
+
+	cpha = slave->mode & SPI_CPHA ? 1 : 0;
+	cpol = slave->mode & SPI_CPOL ? 1 : 0;
+
+	if (priv->hw_cap.enhance_timing) {
+		if (priv->hw_cap.ipm_design) {
+			/* CFG3 reg only used for spi-mem,
+			 * here write to default value
+			 */
+			writel(0x0, priv->base + SPI_CFG3_IPM_REG);
+			clrsetbits_le32(priv->base + SPI_CMD_REG,
+					SPI_CMD_IPM_GET_TICKDLY_MASK,
+					priv->tick_dly <<
+					SPI_CMD_IPM_GET_TICKDLY_OFFSET);
+		} else {
+			clrsetbits_le32(priv->base + SPI_CFG1_REG,
+					SPI_CFG1_GET_TICKDLY_MASK,
+					priv->tick_dly <<
+					SPI_CFG1_GET_TICKDLY_OFFSET);
+		}
+	}
+
+	reg_val = readl(priv->base + SPI_CMD_REG);
+	if (priv->hw_cap.ipm_design) {
+		/* SPI transfer without idle time until packet length done */
+		reg_val |= SPI_CMD_IPM_NONIDLE_MODE;
+		if (slave->mode & SPI_LOOP)
+			reg_val |= SPI_CMD_IPM_SPIM_LOOP;
+		else
+			reg_val &= ~SPI_CMD_IPM_SPIM_LOOP;
+	}
+
+	if (cpha)
+		reg_val |= SPI_CMD_CPHA;
+	else
+		reg_val &= ~SPI_CMD_CPHA;
+	if (cpol)
+		reg_val |= SPI_CMD_CPOL;
+	else
+		reg_val &= ~SPI_CMD_CPOL;
+
+	/* set the mlsbx and mlsbtx */
+	if (slave->mode & SPI_LSB_FIRST) {
+		reg_val &= ~SPI_CMD_TXMSBF;
+		reg_val &= ~SPI_CMD_RXMSBF;
+	} else {
+		reg_val |= SPI_CMD_TXMSBF;
+		reg_val |= SPI_CMD_RXMSBF;
+	}
+
+	/* do not reverse tx/rx endian */
+	reg_val &= ~SPI_CMD_TX_ENDIAN;
+	reg_val &= ~SPI_CMD_RX_ENDIAN;
+
+	if (priv->hw_cap.enhance_timing) {
+		/* set CS polarity */
+		if (slave->mode & SPI_CS_HIGH)
+			reg_val |= SPI_CMD_CS_POL;
+		else
+			reg_val &= ~SPI_CMD_CS_POL;
+
+		if (priv->sample_sel)
+			reg_val |= SPI_CMD_SAMPLE_SEL;
+		else
+			reg_val &= ~SPI_CMD_SAMPLE_SEL;
+	}
+
+	/* disable dma mode */
+	reg_val &= ~(SPI_CMD_TX_DMA | SPI_CMD_RX_DMA);
+
+	/* disable deassert mode */
+	reg_val &= ~SPI_CMD_DEASSERT;
+
+	writel(reg_val, priv->base + SPI_CMD_REG);
+
+	return 0;
+}
+
+static void mtk_spim_prepare_transfer(struct mtk_spim_priv *priv,
+				      u32 speed_hz)
+{
+	u32 spi_clk_hz, div, sck_time, cs_time, reg_val;
+
+	spi_clk_hz = clk_get_rate(&priv->spi_clk);
+	if (speed_hz <= spi_clk_hz / 4)
+		div = DIV_ROUND_UP(spi_clk_hz, speed_hz);
+	else
+		div = 4;
+
+	sck_time = (div + 1) / 2;
+	cs_time = sck_time * 2;
+
+	if (priv->hw_cap.enhance_timing) {
+		reg_val = ((sck_time - 1) & 0xffff)
+			   << SPI_CFG2_SCK_HIGH_OFFSET;
+		reg_val |= ((sck_time - 1) & 0xffff)
+			   << SPI_CFG2_SCK_LOW_OFFSET;
+		writel(reg_val, priv->base + SPI_CFG2_REG);
+
+		reg_val = ((cs_time - 1) & 0xffff)
+			   << SPI_ADJUST_CFG0_CS_HOLD_OFFSET;
+		reg_val |= ((cs_time - 1) & 0xffff)
+			   << SPI_ADJUST_CFG0_CS_SETUP_OFFSET;
+		writel(reg_val, priv->base + SPI_CFG0_REG);
+	} else {
+		reg_val = ((sck_time - 1) & 0xff)
+			   << SPI_CFG0_SCK_HIGH_OFFSET;
+		reg_val |= ((sck_time - 1) & 0xff) << SPI_CFG0_SCK_LOW_OFFSET;
+		reg_val |= ((cs_time - 1) & 0xff) << SPI_CFG0_CS_HOLD_OFFSET;
+		reg_val |= ((cs_time - 1) & 0xff) << SPI_CFG0_CS_SETUP_OFFSET;
+		writel(reg_val, priv->base + SPI_CFG0_REG);
+	}
+
+	reg_val = readl(priv->base + SPI_CFG1_REG);
+	reg_val &= ~SPI_CFG1_CS_IDLE_MASK;
+	reg_val |= ((cs_time - 1) & 0xff) << SPI_CFG1_CS_IDLE_OFFSET;
+	writel(reg_val, priv->base + SPI_CFG1_REG);
+}
+
+/**
+ * mtk_spim_setup_packet() - setup packet format.
+ * @priv:	controller priv
+ *
+ * This controller sents/receives data in packets. The packet size is
+ * configurable.
+ *
+ * This function calculates the maximum packet size available for current
+ * data, and calculates the number of packets required to sent/receive data
+ * as much as possible.
+ */
+static void mtk_spim_setup_packet(struct mtk_spim_priv *priv)
+{
+	u32 packet_size, packet_loop, reg_val;
+
+	/* Calculate maximum packet size */
+	if (priv->hw_cap.ipm_design)
+		packet_size = min_t(u32,
+				    priv->xfer_len,
+				    MTK_SPI_IPM_PACKET_SIZE);
+	else
+		packet_size = min_t(u32,
+				    priv->xfer_len,
+				    MTK_SPI_PACKET_SIZE);
+
+	/* Calculates number of packets to sent/receive */
+	packet_loop = priv->xfer_len / packet_size;
+
+	reg_val = readl(priv->base + SPI_CFG1_REG);
+	if (priv->hw_cap.ipm_design)
+		reg_val &= ~SPI_CFG1_IPM_PACKET_LENGTH_MASK;
+	else
+		reg_val &= ~SPI_CFG1_PACKET_LENGTH_MASK;
+
+	reg_val |= (packet_size - 1) << SPI_CFG1_PACKET_LENGTH_OFFSET;
+
+	reg_val &= ~SPI_CFG1_PACKET_LOOP_MASK;
+
+	reg_val |= (packet_loop - 1) << SPI_CFG1_PACKET_LOOP_OFFSET;
+
+	writel(reg_val, priv->base + SPI_CFG1_REG);
+}
+
+static void mtk_spim_enable_transfer(struct mtk_spim_priv *priv)
+{
+	u32 cmd;
+
+	cmd = readl(priv->base + SPI_CMD_REG);
+	if (priv->state == MTK_SPI_IDLE)
+		cmd |= SPI_CMD_ACT;
+	else
+		cmd |= SPI_CMD_RESUME;
+	writel(cmd, priv->base + SPI_CMD_REG);
+}
+
+static bool mtk_spim_supports_op(struct spi_slave *slave,
+				 const struct spi_mem_op *op)
+{
+	struct udevice *bus = dev_get_parent(slave->dev);
+	struct mtk_spim_priv *priv = dev_get_priv(bus);
+
+	if (op->cmd.buswidth == 0 || op->cmd.buswidth > 4 ||
+	    op->addr.buswidth > 4 || op->dummy.buswidth > 4 ||
+	    op->data.buswidth > 4)
+		return false;
+
+	if (!priv->hw_cap.support_quad && (op->cmd.buswidth > 2 ||
+	    op->addr.buswidth > 2 || op->dummy.buswidth > 2 ||
+	    op->data.buswidth > 2))
+		return false;
+
+	if (op->addr.nbytes && op->dummy.nbytes &&
+	    op->addr.buswidth != op->dummy.buswidth)
+		return false;
+
+	if (op->addr.nbytes + op->dummy.nbytes > 16)
+		return false;
+
+	if (op->data.nbytes > MTK_SPI_IPM_PACKET_SIZE) {
+		if (op->data.nbytes / MTK_SPI_IPM_PACKET_SIZE >
+		    MTK_SPI_IPM_PACKET_LOOP ||
+		    op->data.nbytes % MTK_SPI_IPM_PACKET_SIZE != 0)
+			return false;
+	}
+
+	return true;
+}
+
+static void mtk_spim_setup_dma_xfer(struct mtk_spim_priv *priv,
+				    const struct spi_mem_op *op)
+{
+	writel((u32)(priv->tx_dma & MTK_SPI_32BITS_MASK),
+	       priv->base + SPI_TX_SRC_REG);
+
+	if (priv->hw_cap.dma_ext)
+		writel((u32)(priv->tx_dma >> 32),
+		       priv->base + SPI_TX_SRC_REG_64);
+
+	if (op->data.dir == SPI_MEM_DATA_IN) {
+		writel((u32)(priv->rx_dma & MTK_SPI_32BITS_MASK),
+		       priv->base + SPI_RX_DST_REG);
+
+		if (priv->hw_cap.dma_ext)
+			writel((u32)(priv->rx_dma >> 32),
+			       priv->base + SPI_RX_DST_REG_64);
+	}
+}
+
+static int mtk_spim_transfer_wait(struct spi_slave *slave,
+				  const struct spi_mem_op *op)
+{
+	struct udevice *bus = dev_get_parent(slave->dev);
+	struct mtk_spim_priv *priv = dev_get_priv(bus);
+	u32 sck_l, sck_h, spi_bus_clk, clk_count, reg;
+	ulong us = 1;
+	int ret = 0;
+
+	if (op->data.dir == SPI_MEM_NO_DATA)
+		clk_count = 32;
+	else
+		clk_count = op->data.nbytes;
+
+	spi_bus_clk = clk_get_rate(&priv->spi_clk);
+	sck_l = readl(priv->base + SPI_CFG2_REG) >> SPI_CFG2_SCK_LOW_OFFSET;
+	sck_h = readl(priv->base + SPI_CFG2_REG) & SPI_CFG2_SCK_HIGH_MASK;
+	do_div(spi_bus_clk, sck_l + sck_h + 2);
+
+	us = CLK_TO_US(spi_bus_clk, clk_count * 8);
+	us += 1000 * 1000; /* 1s tolerance */
+
+	if (us > UINT_MAX)
+		us = UINT_MAX;
+
+	ret = readl_poll_timeout(priv->base + SPI_STATUS_REG, reg,
+				 reg & 0x1, us);
+	if (ret < 0) {
+		dev_err(priv->dev, "transfer timeout, val: 0x%lx\n", us);
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+static int mtk_spim_exec_op(struct spi_slave *slave,
+			    const struct spi_mem_op *op)
+{
+	struct udevice *bus = dev_get_parent(slave->dev);
+	struct mtk_spim_priv *priv = dev_get_priv(bus);
+	u32 reg_val, nio = 1, tx_size;
+	char *tx_tmp_buf;
+	char *rx_tmp_buf;
+	int i, ret = 0;
+
+	mtk_spim_reset(priv);
+	mtk_spim_hw_init(slave);
+	mtk_spim_prepare_transfer(priv, slave->max_hz);
+
+	reg_val = readl(priv->base + SPI_CFG3_IPM_REG);
+	/* opcode byte len */
+	reg_val &= ~SPI_CFG3_IPM_CMD_BYTELEN_MASK;
+	reg_val |= 1 << SPI_CFG3_IPM_CMD_BYTELEN_OFFSET;
+
+	/* addr & dummy byte len */
+	if (op->addr.nbytes || op->dummy.nbytes)
+		reg_val |= (op->addr.nbytes + op->dummy.nbytes) <<
+			    SPI_CFG3_IPM_ADDR_BYTELEN_OFFSET;
+
+	/* data byte len */
+	if (!op->data.nbytes) {
+		reg_val |= SPI_CFG3_IPM_NODATA_FLAG;
+		writel(0, priv->base + SPI_CFG1_REG);
+	} else {
+		reg_val &= ~SPI_CFG3_IPM_NODATA_FLAG;
+		priv->xfer_len = op->data.nbytes;
+		mtk_spim_setup_packet(priv);
+	}
+
+	if (op->addr.nbytes || op->dummy.nbytes) {
+		if (op->addr.buswidth == 1 || op->dummy.buswidth == 1)
+			reg_val |= SPI_CFG3_IPM_XMODE_EN;
+		else
+			reg_val &= ~SPI_CFG3_IPM_XMODE_EN;
+	}
+
+	if (op->addr.buswidth == 2 ||
+	    op->dummy.buswidth == 2 ||
+	    op->data.buswidth == 2)
+		nio = 2;
+	else if (op->addr.buswidth == 4 ||
+		 op->dummy.buswidth == 4 ||
+		 op->data.buswidth == 4)
+		nio = 4;
+
+	reg_val &= ~SPI_CFG3_IPM_CMD_PIN_MODE_MASK;
+	reg_val |= PIN_MODE_CFG(nio) << SPI_CFG3_IPM_PIN_MODE_OFFSET;
+
+	reg_val |= SPI_CFG3_IPM_HALF_DUPLEX_EN;
+	if (op->data.dir == SPI_MEM_DATA_IN)
+		reg_val |= SPI_CFG3_IPM_HALF_DUPLEX_DIR;
+	else
+		reg_val &= ~SPI_CFG3_IPM_HALF_DUPLEX_DIR;
+	writel(reg_val, priv->base + SPI_CFG3_IPM_REG);
+
+	tx_size = 1 + op->addr.nbytes + op->dummy.nbytes;
+	if (op->data.dir == SPI_MEM_DATA_OUT)
+		tx_size += op->data.nbytes;
+
+	tx_size = max(tx_size, (u32)32);
+
+	/* Fill up tx data */
+	tx_tmp_buf = kzalloc(tx_size, GFP_KERNEL);
+	if (!tx_tmp_buf) {
+		ret = -ENOMEM;
+		goto exit;
+	}
+
+	tx_tmp_buf[0] = op->cmd.opcode;
+
+	if (op->addr.nbytes) {
+		for (i = 0; i < op->addr.nbytes; i++)
+			tx_tmp_buf[i + 1] = op->addr.val >>
+					(8 * (op->addr.nbytes - i - 1));
+	}
+
+	if (op->dummy.nbytes)
+		memset(tx_tmp_buf + op->addr.nbytes + 1, 0xff,
+		       op->dummy.nbytes);
+
+	if (op->data.nbytes && op->data.dir == SPI_MEM_DATA_OUT)
+		memcpy(tx_tmp_buf + op->dummy.nbytes + op->addr.nbytes + 1,
+		       op->data.buf.out, op->data.nbytes);
+	/* Finish filling up tx data */
+
+	priv->tx_dma = dma_map_single(tx_tmp_buf, tx_size, DMA_TO_DEVICE);
+	if (dma_mapping_error(priv->dev, priv->tx_dma)) {
+		ret = -ENOMEM;
+		goto tx_free;
+	}
+
+	if (op->data.dir == SPI_MEM_DATA_IN) {
+		if (!IS_ALIGNED((size_t)op->data.buf.in, 4)) {
+			rx_tmp_buf = kzalloc(op->data.nbytes, GFP_KERNEL);
+			if (!rx_tmp_buf) {
+				ret = -ENOMEM;
+				goto tx_unmap;
+			}
+		} else {
+			rx_tmp_buf = op->data.buf.in;
+		}
+
+		priv->rx_dma = dma_map_single(rx_tmp_buf, op->data.nbytes,
+					      DMA_FROM_DEVICE);
+		if (dma_mapping_error(priv->dev, priv->rx_dma)) {
+			ret = -ENOMEM;
+			goto rx_free;
+		}
+	}
+
+	reg_val = readl(priv->base + SPI_CMD_REG);
+	reg_val |= SPI_CMD_TX_DMA;
+	if (op->data.dir == SPI_MEM_DATA_IN)
+		reg_val |= SPI_CMD_RX_DMA;
+
+	writel(reg_val, priv->base + SPI_CMD_REG);
+
+	mtk_spim_setup_dma_xfer(priv, op);
+
+	mtk_spim_enable_transfer(priv);
+
+	/* Wait for the interrupt. */
+	ret = mtk_spim_transfer_wait(slave, op);
+	if (ret)
+		goto rx_unmap;
+
+	if (op->data.dir == SPI_MEM_DATA_IN &&
+	    !IS_ALIGNED((size_t)op->data.buf.in, 4))
+		memcpy(op->data.buf.in, rx_tmp_buf, op->data.nbytes);
+
+rx_unmap:
+	/* spi disable dma */
+	reg_val = readl(priv->base + SPI_CMD_REG);
+	reg_val &= ~SPI_CMD_TX_DMA;
+	if (op->data.dir == SPI_MEM_DATA_IN)
+		reg_val &= ~SPI_CMD_RX_DMA;
+	writel(reg_val, priv->base + SPI_CMD_REG);
+
+	writel(0, priv->base + SPI_TX_SRC_REG);
+	writel(0, priv->base + SPI_RX_DST_REG);
+
+	if (op->data.dir == SPI_MEM_DATA_IN)
+		dma_unmap_single(priv->rx_dma,
+				 op->data.nbytes, DMA_FROM_DEVICE);
+rx_free:
+	if (op->data.dir == SPI_MEM_DATA_IN &&
+	    !IS_ALIGNED((size_t)op->data.buf.in, 4))
+		kfree(rx_tmp_buf);
+tx_unmap:
+	dma_unmap_single(priv->tx_dma,
+			 tx_size, DMA_TO_DEVICE);
+tx_free:
+	kfree(tx_tmp_buf);
+exit:
+	return ret;
+}
+
+static int mtk_spim_adjust_op_size(struct spi_slave *slave,
+				   struct spi_mem_op *op)
+{
+	int opcode_len;
+
+	if (!op->data.nbytes)
+		return 0;
+
+	if (op->data.dir != SPI_MEM_NO_DATA) {
+		opcode_len = 1 + op->addr.nbytes + op->dummy.nbytes;
+		if (opcode_len + op->data.nbytes > MTK_SPI_IPM_PACKET_SIZE) {
+			op->data.nbytes = MTK_SPI_IPM_PACKET_SIZE - opcode_len;
+			/* force data buffer dma-aligned. */
+			op->data.nbytes -= op->data.nbytes % 4;
+		}
+	}
+
+	return 0;
+}
+
+static int mtk_spim_get_attr(struct mtk_spim_priv *priv, struct udevice *dev)
+{
+	int ret;
+
+	priv->hw_cap.enhance_timing = dev_read_bool(dev, "enhance_timing");
+	priv->hw_cap.dma_ext = dev_read_bool(dev, "dma_ext");
+	priv->hw_cap.ipm_design = dev_read_bool(dev, "ipm_design");
+	priv->hw_cap.support_quad = dev_read_bool(dev, "support_quad");
+
+	ret = dev_read_u32(dev, "tick_dly", &priv->tick_dly);
+	if (ret < 0)
+		dev_err(priv->dev, "tick dly not set.\n");
+
+	ret = dev_read_u32(dev, "sample_sel", &priv->sample_sel);
+	if (ret < 0)
+		dev_err(priv->dev, "sample sel not set.\n");
+
+	return ret;
+}
+
+static int mtk_spim_probe(struct udevice *dev)
+{
+	struct mtk_spim_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	priv->base = (void __iomem *)devfdt_get_addr(dev);
+	if (!priv->base)
+		return -EINVAL;
+
+	mtk_spim_get_attr(priv, dev);
+
+	ret = clk_get_by_name(dev, "sel-clk", &priv->sel_clk);
+	if (ret < 0) {
+		dev_err(dev, "failed to get sel-clk\n");
+		return ret;
+	}
+
+	ret = clk_get_by_name(dev, "spi-clk", &priv->spi_clk);
+	if (ret < 0) {
+		dev_err(dev, "failed to get spi-clk\n");
+		return ret;
+	}
+
+	clk_enable(&priv->sel_clk);
+	clk_enable(&priv->spi_clk);
+
+	return 0;
+}
+
+static int mtk_spim_set_speed(struct udevice *dev, uint speed)
+{
+	return 0;
+}
+
+static int mtk_spim_set_mode(struct udevice *dev, uint mode)
+{
+	return 0;
+}
+
+static const struct spi_controller_mem_ops mtk_spim_mem_ops = {
+	.adjust_op_size = mtk_spim_adjust_op_size,
+	.supports_op = mtk_spim_supports_op,
+	.exec_op = mtk_spim_exec_op
+};
+
+static const struct dm_spi_ops mtk_spim_ops = {
+	.mem_ops = &mtk_spim_mem_ops,
+	.set_speed = mtk_spim_set_speed,
+	.set_mode = mtk_spim_set_mode,
+};
+
+static const struct udevice_id mtk_spim_ids[] = {
+	{ .compatible = "mediatek,ipm-spi" },
+	{}
+};
+
+U_BOOT_DRIVER(mtk_spim) = {
+	.name = "mtk_spim",
+	.id = UCLASS_SPI,
+	.of_match = mtk_spim_ids,
+	.ops = &mtk_spim_ops,
+	.priv_auto = sizeof(struct mtk_spim_priv),
+	.probe = mtk_spim_probe,
+};
-- 
2.17.1


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

* [PATCH v2 17/32] i2c: add support for MediaTek I2C interface
  2022-08-31 11:00 [PATCH v2 00/32] Add support for MediaTek MT7981/MT7986 SoCs - v2 Weijie Gao
                   ` (15 preceding siblings ...)
  2022-08-31 11:04 ` [PATCH v2 16/32] spi: add support for MediaTek spi-mem controller Weijie Gao
@ 2022-08-31 11:04 ` Weijie Gao
  2022-08-31 11:04 ` [PATCH v2 18/32] arm: dts: mt7622: add i2c support Weijie Gao
                   ` (14 subsequent siblings)
  31 siblings, 0 replies; 60+ messages in thread
From: Weijie Gao @ 2022-08-31 11:04 UTC (permalink / raw)
  To: u-boot; +Cc: GSS_MTK_Uboot_upstream, Heiko Schocher, Weijie Gao

This patch adds support for MediaTek I2C interface

Reviewed-by: Heiko Schocher <hs@denx.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
---
v2 changes:
  Reorganize code to reduce duplicated code
  Rename mtk_i2c_ofdata_to_platdata to mtk_i2c_of_to_plat
---
 drivers/i2c/Kconfig   |   9 +
 drivers/i2c/Makefile  |   1 +
 drivers/i2c/mtk_i2c.c | 822 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 832 insertions(+)
 create mode 100644 drivers/i2c/mtk_i2c.c

diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index be4724bf8e..08b6c7bdcc 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -261,6 +261,15 @@ config SYS_I2C_MESON
 	  internal buffer holding up to 8 bytes for transfers and supports
 	  both 7-bit and 10-bit addresses.
 
+config SYS_I2C_MTK
+	bool "MediaTek I2C driver"
+	help
+	  This selects the MediaTek Integrated Inter Circuit bus driver.
+	  The I2C bus adapter is the base for some other I2C client,
+	  eg: touch, sensors.
+	  If you want to use MediaTek I2C interface, say Y here.
+	  If unsure, say N.
+
 config SYS_I2C_MICROCHIP
 	bool "Microchip I2C driver"
 	help
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index 7e046f809a..920aafb91c 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_SYS_I2C_MICROCHIP) += i2c-microchip.o
 obj-$(CONFIG_SYS_I2C_MV) += mv_i2c.o
 obj-$(CONFIG_SYS_I2C_MVTWSI) += mvtwsi.o
 obj-$(CONFIG_SYS_I2C_MXC) += mxc_i2c.o
+obj-$(CONFIG_SYS_I2C_MTK) += mtk_i2c.o
 obj-$(CONFIG_SYS_I2C_NEXELL) += nx_i2c.o
 obj-$(CONFIG_SYS_I2C_NPCM) += npcm_i2c.o
 obj-$(CONFIG_SYS_I2C_OCORES) += ocores_i2c.o
diff --git a/drivers/i2c/mtk_i2c.c b/drivers/i2c/mtk_i2c.c
new file mode 100644
index 0000000000..5528bcd7cc
--- /dev/null
+++ b/drivers/i2c/mtk_i2c.c
@@ -0,0 +1,822 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2022 MediaTek Inc. All Rights Reserved.
+ *
+ * Author: Mingming Lee <Mingming.Lee@mediatek.com>
+ *
+ * MediaTek I2C Interface driver
+ */
+
+#include <clk.h>
+#include <cpu_func.h>
+#include <dm.h>
+#include <i2c.h>
+#include <log.h>
+#include <asm/cache.h>
+#include <asm/io.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+
+#define I2C_RS_TRANSFER			BIT(4)
+#define I2C_HS_NACKERR			BIT(2)
+#define I2C_ACKERR			BIT(1)
+#define I2C_TRANSAC_COMP		BIT(0)
+#define I2C_TRANSAC_START		BIT(0)
+#define I2C_RS_MUL_CNFG			BIT(15)
+#define I2C_RS_MUL_TRIG			BIT(14)
+#define I2C_DCM_DISABLE			0x0000
+#define I2C_IO_CONFIG_OPEN_DRAIN	0x0003
+#define I2C_IO_CONFIG_PUSH_PULL		0x0000
+#define I2C_SOFT_RST			0x0001
+#define I2C_FIFO_ADDR_CLR		0x0001
+#define I2C_DELAY_LEN			0x0002
+#define I2C_ST_START_CON		0x8001
+#define I2C_FS_START_CON		0x1800
+#define I2C_TIME_CLR_VALUE		0x0000
+#define I2C_TIME_DEFAULT_VALUE		0x0003
+#define I2C_WRRD_TRANAC_VALUE		0x0002
+#define I2C_RD_TRANAC_VALUE		0x0001
+
+#define I2C_DMA_CON_TX			0x0000
+#define I2C_DMA_CON_RX			0x0001
+#define I2C_DMA_START_EN		0x0001
+#define I2C_DMA_INT_FLAG_NONE		0x0000
+#define I2C_DMA_CLR_FLAG		0x0000
+#define I2C_DMA_TX_RX			0x0000
+#define I2C_DMA_HARD_RST		0x0002
+
+#define MAX_ST_MODE_SPEED		100000
+#define MAX_FS_MODE_SPEED		400000
+#define MAX_HS_MODE_SPEED		3400000
+#define MAX_SAMPLE_CNT_DIV		8
+#define MAX_STEP_CNT_DIV		64
+#define MAX_HS_STEP_CNT_DIV		8
+#define I2C_DEFAULT_CLK_DIV		4
+
+#define MAX_I2C_ADDR			0x7f
+#define MAX_I2C_LEN			0xff
+#define TRANS_ADDR_ONLY			BIT(8)
+#define TRANSFER_TIMEOUT		50000  /* us */
+#define I2C_FIFO_STAT1_MASK		0x001f
+#define TIMING_SAMPLE_OFFSET		8
+#define HS_SAMPLE_OFFSET		12
+#define HS_STEP_OFFSET			8
+
+#define I2C_CONTROL_WRAPPER		BIT(0)
+#define I2C_CONTROL_RS			BIT(1)
+#define I2C_CONTROL_DMA_EN		BIT(2)
+#define I2C_CONTROL_CLK_EXT_EN		BIT(3)
+#define I2C_CONTROL_DIR_CHANGE		BIT(4)
+#define I2C_CONTROL_ACKERR_DET_EN	BIT(5)
+#define I2C_CONTROL_TRANSFER_LEN_CHANGE BIT(6)
+#define I2C_CONTROL_DMAACK		BIT(8)
+#define I2C_CONTROL_ASYNC		BIT(9)
+
+#define I2C_MASTER_WR			BIT(0)
+#define I2C_MASTER_RD			BIT(1)
+#define I2C_MASTER_WRRD			(I2C_MASTER_WR | I2C_MASTER_RD)
+
+enum I2C_REGS_OFFSET {
+	REG_PORT,
+	REG_SLAVE_ADDR,
+	REG_INTR_MASK,
+	REG_INTR_STAT,
+	REG_CONTROL,
+	REG_TRANSFER_LEN,
+	REG_TRANSAC_LEN,
+	REG_DELAY_LEN,
+	REG_TIMING,
+	REG_START,
+	REG_EXT_CONF,
+	REG_FIFO_STAT1,
+	REG_LTIMING,
+	REG_FIFO_STAT,
+	REG_FIFO_THRESH,
+	REG_FIFO_ADDR_CLR,
+	REG_IO_CONFIG,
+	REG_RSV_DEBUG,
+	REG_HS,
+	REG_SOFTRESET,
+	REG_DCM_EN,
+	REG_PATH_DIR,
+	REG_DEBUGSTAT,
+	REG_DEBUGCTRL,
+	REG_TRANSFER_LEN_AUX,
+	REG_CLOCK_DIV,
+	REG_SCL_HL_RATIO,
+	REG_SCL_HS_HL_RATIO,
+	REG_SCL_MIS_COMP_POINT,
+	REG_STA_STOP_AC_TIME,
+	REG_HS_STA_STOP_AC_TIME,
+	REG_DATA_TIME,
+};
+
+enum DMA_REGS_OFFSET {
+	REG_INT_FLAG = 0x0,
+	REG_INT_EN = 0x04,
+	REG_EN = 0x08,
+	REG_RST = 0x0c,
+	REG_CON = 0x18,
+	REG_TX_MEM_ADDR = 0x1c,
+	REG_RX_MEM_ADDR = 0x20,
+	REG_TX_LEN = 0x24,
+	REG_RX_LEN = 0x28,
+};
+
+static const uint mt_i2c_regs_v1[] = {
+	[REG_PORT] = 0x0,
+	[REG_SLAVE_ADDR] = 0x4,
+	[REG_INTR_MASK] = 0x8,
+	[REG_INTR_STAT] = 0xc,
+	[REG_CONTROL] = 0x10,
+	[REG_TRANSFER_LEN] = 0x14,
+	[REG_TRANSAC_LEN] = 0x18,
+	[REG_DELAY_LEN] = 0x1c,
+	[REG_TIMING] = 0x20,
+	[REG_START] = 0x24,
+	[REG_EXT_CONF] = 0x28,
+	[REG_FIFO_STAT1] = 0x2c,
+	[REG_FIFO_STAT] = 0x30,
+	[REG_FIFO_THRESH] = 0x34,
+	[REG_FIFO_ADDR_CLR] = 0x38,
+	[REG_IO_CONFIG] = 0x40,
+	[REG_RSV_DEBUG] = 0x44,
+	[REG_HS] = 0x48,
+	[REG_SOFTRESET] = 0x50,
+	[REG_SOFTRESET] = 0x50,
+	[REG_DCM_EN] = 0x54,
+	[REG_DEBUGSTAT] = 0x64,
+	[REG_DEBUGCTRL] = 0x68,
+	[REG_TRANSFER_LEN_AUX] = 0x6c,
+	[REG_CLOCK_DIV] = 0x70,
+	[REG_SCL_HL_RATIO] = 0x74,
+	[REG_SCL_HS_HL_RATIO] = 0x78,
+	[REG_SCL_MIS_COMP_POINT] = 0x7c,
+	[REG_STA_STOP_AC_TIME] = 0x80,
+	[REG_HS_STA_STOP_AC_TIME] = 0x84,
+	[REG_DATA_TIME] = 0x88,
+};
+
+static const uint mt_i2c_regs_v2[] = {
+	[REG_PORT] = 0x0,
+	[REG_SLAVE_ADDR] = 0x4,
+	[REG_INTR_MASK] = 0x8,
+	[REG_INTR_STAT] = 0xc,
+	[REG_CONTROL] = 0x10,
+	[REG_TRANSFER_LEN] = 0x14,
+	[REG_TRANSAC_LEN] = 0x18,
+	[REG_DELAY_LEN] = 0x1c,
+	[REG_TIMING] = 0x20,
+	[REG_START] = 0x24,
+	[REG_EXT_CONF] = 0x28,
+	[REG_LTIMING] = 0x2c,
+	[REG_HS] = 0x30,
+	[REG_IO_CONFIG] = 0x34,
+	[REG_FIFO_ADDR_CLR] = 0x38,
+	[REG_TRANSFER_LEN_AUX] = 0x44,
+	[REG_CLOCK_DIV] = 0x48,
+	[REG_SOFTRESET] = 0x50,
+	[REG_DEBUGSTAT] = 0xe0,
+	[REG_DEBUGCTRL] = 0xe8,
+	[REG_FIFO_STAT] = 0xf4,
+	[REG_FIFO_THRESH] = 0xf8,
+	[REG_DCM_EN] = 0xf88,
+};
+
+struct mtk_i2c_soc_data {
+	const uint *regs;
+	uint dma_sync: 1;
+};
+
+struct mtk_i2c_priv {
+	/* set in i2c probe */
+	void __iomem *base;		/* i2c base addr */
+	void __iomem *pdmabase;		/* dma base address*/
+	struct clk clk_main;		/* main clock for i2c bus */
+	struct clk clk_dma;		/* DMA clock for i2c via DMA */
+	const struct mtk_i2c_soc_data *soc_data; /* Compatible data for different IC */
+	int op;				/* operation mode */
+	bool zero_len;			/* Only transfer slave address, no data */
+	bool pushpull;			/* push pull mode or open drain mode */
+	bool filter_msg;		/* filter msg error log */
+	bool auto_restart;		/* restart mode */
+	bool ignore_restart_irq;	/* ignore restart IRQ */
+	uint speed;			/* i2c speed, unit: hz */
+};
+
+static inline void i2c_writel(struct mtk_i2c_priv *priv, uint reg, uint value)
+{
+	u32 offset = priv->soc_data->regs[reg];
+
+	writel(value, priv->base + offset);
+}
+
+static inline uint i2c_readl(struct mtk_i2c_priv *priv, uint offset)
+{
+	return readl(priv->base + priv->soc_data->regs[offset]);
+}
+
+static int mtk_i2c_clk_enable(struct mtk_i2c_priv *priv)
+{
+	int ret;
+
+	ret = clk_enable(&priv->clk_main);
+	if (ret)
+		return log_msg_ret("enable clk_main", ret);
+
+	ret = clk_enable(&priv->clk_dma);
+	if (ret)
+		return log_msg_ret("enable clk_dma", ret);
+
+	return 0;
+}
+
+static int mtk_i2c_clk_disable(struct mtk_i2c_priv *priv)
+{
+	int ret;
+
+	ret = clk_disable(&priv->clk_dma);
+	if (ret)
+		return log_msg_ret("disable clk_dma", ret);
+
+	ret = clk_disable(&priv->clk_main);
+	if (ret)
+		return log_msg_ret("disable clk_main", ret);
+
+	return 0;
+}
+
+static void mtk_i2c_init_hw(struct mtk_i2c_priv *priv)
+{
+	uint control_reg;
+
+	writel(I2C_DMA_HARD_RST, priv->pdmabase + REG_RST);
+	writel(I2C_DMA_CLR_FLAG, priv->pdmabase + REG_RST);
+	i2c_writel(priv, REG_SOFTRESET, I2C_SOFT_RST);
+	/* set ioconfig */
+	if (priv->pushpull)
+		i2c_writel(priv, REG_IO_CONFIG, I2C_IO_CONFIG_PUSH_PULL);
+	else
+		i2c_writel(priv, REG_IO_CONFIG, I2C_IO_CONFIG_OPEN_DRAIN);
+
+	i2c_writel(priv, REG_DCM_EN, I2C_DCM_DISABLE);
+	control_reg = I2C_CONTROL_ACKERR_DET_EN | I2C_CONTROL_CLK_EXT_EN;
+	if (priv->soc_data->dma_sync)
+		control_reg |= I2C_CONTROL_DMAACK | I2C_CONTROL_ASYNC;
+	i2c_writel(priv, REG_CONTROL, control_reg);
+	i2c_writel(priv, REG_DELAY_LEN, I2C_DELAY_LEN);
+}
+
+/*
+ * Calculate i2c port speed
+ *
+ * Hardware design:
+ * i2c_bus_freq = parent_clk / (clock_div * 2 * sample_cnt * step_cnt)
+ * clock_div: fixed in hardware, but may be various in different SoCs
+ *
+ * The calculation want to pick the highest bus frequency that is still
+ * less than or equal to target_speed. The calculation try to get
+ * sample_cnt and step_cn
+ * @param[in]
+ *     clk_src: i2c clock source
+ * @param[out]
+ *     timing_step_cnt: step cnt calculate result
+ * @param[out]
+ *     timing_sample_cnt: sample cnt calculate result
+ * @return
+ *     0, set speed successfully.
+ *     -EINVAL, Unsupported speed.
+ */
+static int mtk_i2c_calculate_speed(uint clk_src,
+				   uint target_speed,
+				   uint *timing_step_cnt,
+				   uint *timing_sample_cnt)
+{
+	uint base_sample_cnt = MAX_SAMPLE_CNT_DIV;
+	uint base_step_cnt;
+	uint max_step_cnt;
+	uint sample_cnt;
+	uint step_cnt;
+	uint opt_div;
+	uint best_mul;
+	uint cnt_mul;
+
+	if (target_speed > MAX_HS_MODE_SPEED)
+		target_speed = MAX_HS_MODE_SPEED;
+
+	if (target_speed > MAX_FS_MODE_SPEED)
+		max_step_cnt = MAX_HS_STEP_CNT_DIV;
+	else
+		max_step_cnt = MAX_STEP_CNT_DIV;
+
+	base_step_cnt = max_step_cnt;
+	/* Find the best combination */
+	opt_div = DIV_ROUND_UP(clk_src >> 1, target_speed);
+	best_mul = MAX_SAMPLE_CNT_DIV * max_step_cnt;
+
+	/*
+	 * Search for the best pair (sample_cnt, step_cnt) with
+	 * 0 < sample_cnt < MAX_SAMPLE_CNT_DIV
+	 * 0 < step_cnt < max_step_cnt
+	 * sample_cnt * step_cnt >= opt_div
+	 * optimizing for sample_cnt * step_cnt being minimal
+	 */
+	for (sample_cnt = 1; sample_cnt <= MAX_SAMPLE_CNT_DIV; sample_cnt++) {
+		step_cnt = DIV_ROUND_UP(opt_div, sample_cnt);
+		cnt_mul = step_cnt * sample_cnt;
+		if (step_cnt > max_step_cnt)
+			continue;
+
+		if (cnt_mul < best_mul) {
+			best_mul = cnt_mul;
+			base_sample_cnt = sample_cnt;
+			base_step_cnt = step_cnt;
+			if (best_mul == opt_div)
+				break;
+		}
+	}
+
+	sample_cnt = base_sample_cnt;
+	step_cnt = base_step_cnt;
+
+	if ((clk_src / (2 * sample_cnt * step_cnt)) > target_speed) {
+		/*
+		 * In this case, hardware can't support such
+		 * low i2c_bus_freq
+		 */
+		debug("Unsupported speed(%uhz)\n", target_speed);
+		return log_msg_ret("calculate speed", -EINVAL);
+	}
+
+	*timing_step_cnt = step_cnt - 1;
+	*timing_sample_cnt = sample_cnt - 1;
+
+	return 0;
+}
+
+/*
+ * mtk_i2c_set_speed
+ *
+ * @par Description
+ *     Calculate i2c speed and write sample_cnt, step_cnt to TIMING register.
+ * @param[in]
+ *     dev: udevice pointer, struct udevice contains i2c source clock,
+ *     clock divide and speed.
+ * @return
+ *     0, set speed successfully.\n
+ *     error code from mtk_i2c_calculate_speed().
+ */
+static int mtk_i2c_set_speed(struct udevice *dev, uint speed)
+{
+	struct mtk_i2c_priv *priv = dev_get_priv(dev);
+	uint high_speed_reg;
+	uint sample_cnt;
+	uint timing_reg;
+	uint step_cnt;
+	uint clk_src;
+	int ret = 0;
+
+	priv->speed = speed;
+	if (mtk_i2c_clk_enable(priv))
+		return log_msg_ret("set_speed enable clk", -1);
+
+	clk_src = clk_get_rate(&priv->clk_main) / I2C_DEFAULT_CLK_DIV;
+	i2c_writel(priv, REG_CLOCK_DIV, (I2C_DEFAULT_CLK_DIV - 1));
+	if (priv->speed > MAX_FS_MODE_SPEED) {
+		/* Set master code speed register */
+		ret = mtk_i2c_calculate_speed(clk_src, MAX_FS_MODE_SPEED,
+					      &step_cnt, &sample_cnt);
+		if (ret < 0)
+			goto exit;
+
+		timing_reg = (sample_cnt << TIMING_SAMPLE_OFFSET) | step_cnt;
+		i2c_writel(priv, REG_TIMING, timing_reg);
+		/* Set the high speed mode register */
+		ret = mtk_i2c_calculate_speed(clk_src, priv->speed,
+					      &step_cnt, &sample_cnt);
+		if (ret < 0)
+			goto exit;
+
+		high_speed_reg = I2C_TIME_DEFAULT_VALUE |
+				(sample_cnt << HS_SAMPLE_OFFSET) |
+				(step_cnt << HS_STEP_OFFSET);
+		i2c_writel(priv, REG_HS, high_speed_reg);
+	} else {
+		ret = mtk_i2c_calculate_speed(clk_src, priv->speed,
+					      &step_cnt, &sample_cnt);
+		if (ret < 0)
+			goto exit;
+
+		timing_reg = (sample_cnt << TIMING_SAMPLE_OFFSET) | step_cnt;
+		/* Disable the high speed transaction */
+		high_speed_reg = I2C_TIME_CLR_VALUE;
+		i2c_writel(priv, REG_TIMING, timing_reg);
+		i2c_writel(priv, REG_HS, high_speed_reg);
+	}
+exit:
+	if (mtk_i2c_clk_disable(priv))
+		return log_msg_ret("set_speed disable clk", -1);
+
+	return ret;
+}
+
+/*
+ * mtk_i2c_do_transfer
+ *
+ * @par Description
+ *     Configure i2c register and trigger transfer.
+ * @param[in]
+ *     priv: mtk_i2cmtk_i2c_priv pointer, struct mtk_i2c_priv contains register base\n
+ *     address, operation mode, interrupt status and i2c driver data.
+ * @param[in]
+ *     msgs: i2c_msg pointer, struct i2c_msg contains slave\n
+ *     address, operation mode, msg length and data buffer.
+ * @param[in]
+ *     num: i2c_msg number.
+ * @param[in]
+ *     left_num: left i2c_msg number.
+ * @return
+ *     0, i2c transfer successfully.\n
+ *     -ETIMEDOUT, i2c transfer timeout.\n
+ *     -EREMOTEIO, i2c transfer ack error.
+ */
+static int mtk_i2c_do_transfer(struct mtk_i2c_priv *priv,
+			       struct i2c_msg *msgs,
+			       int num, int left_num)
+{
+	struct i2c_msg *msg_rx = NULL;
+	uint restart_flag = 0;
+	uint trans_error = 0;
+	uint irq_stat = 0;
+	uint tmo_poll = 0;
+	uint control_reg;
+	bool tmo = false;
+	uint start_reg;
+	uint addr_reg;
+	int ret = 0;
+
+	if (priv->auto_restart)
+		restart_flag = I2C_RS_TRANSFER;
+
+	control_reg = i2c_readl(priv, REG_CONTROL) &
+		~(I2C_CONTROL_DIR_CHANGE | I2C_CONTROL_RS);
+
+	if (priv->speed > MAX_FS_MODE_SPEED || num > 1)
+		control_reg |= I2C_CONTROL_RS;
+
+	if (priv->op == I2C_MASTER_WRRD)
+		control_reg |= I2C_CONTROL_DIR_CHANGE | I2C_CONTROL_RS;
+
+	control_reg |= I2C_CONTROL_DMA_EN;
+	i2c_writel(priv, REG_CONTROL, control_reg);
+
+	/* set start condition */
+	if (priv->speed <= MAX_ST_MODE_SPEED)
+		i2c_writel(priv, REG_EXT_CONF, I2C_ST_START_CON);
+	else
+		i2c_writel(priv, REG_EXT_CONF, I2C_FS_START_CON);
+
+	addr_reg = msgs->addr << 1;
+	if (priv->op == I2C_MASTER_RD)
+		addr_reg |= I2C_M_RD;
+	if (priv->zero_len)
+		i2c_writel(priv, REG_SLAVE_ADDR, addr_reg | TRANS_ADDR_ONLY);
+	else
+		i2c_writel(priv, REG_SLAVE_ADDR, addr_reg);
+
+	/* clear interrupt status */
+	i2c_writel(priv, REG_INTR_STAT, restart_flag | I2C_HS_NACKERR |
+		   I2C_ACKERR | I2C_TRANSAC_COMP);
+	i2c_writel(priv, REG_FIFO_ADDR_CLR, I2C_FIFO_ADDR_CLR);
+
+	/* enable interrupt */
+	i2c_writel(priv, REG_INTR_MASK, restart_flag | I2C_HS_NACKERR |
+		   I2C_ACKERR | I2C_TRANSAC_COMP);
+
+	/* set transfer and transaction len */
+	if (priv->op == I2C_MASTER_WRRD) {
+		i2c_writel(priv, REG_TRANSFER_LEN, msgs->len);
+		i2c_writel(priv, REG_TRANSFER_LEN_AUX, (msgs + 1)->len);
+		i2c_writel(priv, REG_TRANSAC_LEN, I2C_WRRD_TRANAC_VALUE);
+	} else {
+		i2c_writel(priv, REG_TRANSFER_LEN, msgs->len);
+		i2c_writel(priv, REG_TRANSAC_LEN, num);
+	}
+
+	/* Clear DMA interrupt flag */
+	writel(I2C_DMA_INT_FLAG_NONE, priv->pdmabase + REG_INT_FLAG);
+
+	/* Flush cache for first msg */
+	flush_cache((ulong)msgs->buf, msgs->len);
+
+	/*
+	 * prepare buffer data to start transfer
+	 * three cases here: read, write, write then read
+	 */
+	if (priv->op & I2C_MASTER_WR) {
+		/* Set DMA direction TX (w/ or w/o RX) */
+		writel(I2C_DMA_CON_TX, priv->pdmabase + REG_CON);
+
+		/* Write the tx buffer address to dma register */
+		writel((ulong)msgs->buf, priv->pdmabase + REG_TX_MEM_ADDR);
+		/* Write the tx length to dma register */
+		writel(msgs->len, priv->pdmabase + REG_TX_LEN);
+
+		if (priv->op & I2C_MASTER_RD) {
+			/* write then read */
+			msg_rx = msgs + 1;
+
+			/* Flush cache for second msg */
+			flush_cache((ulong)msg_rx->buf, msg_rx->len);
+		}
+	}
+
+	if (priv->op & I2C_MASTER_RD) {
+		if (!msg_rx) {
+			/* Set DMA direction RX */
+			writel(I2C_DMA_CON_RX, priv->pdmabase + REG_CON);
+
+			msg_rx = msgs;
+		}
+
+		/* Write the rx buffer address to dma register */
+		writel((ulong)msg_rx->buf, priv->pdmabase + REG_RX_MEM_ADDR);
+		/* Write the rx length to dma register */
+		writel(msg_rx->len, priv->pdmabase + REG_RX_LEN);
+	}
+
+	writel(I2C_DMA_START_EN, priv->pdmabase + REG_EN);
+
+	if (!priv->auto_restart) {
+		start_reg = I2C_TRANSAC_START;
+	} else {
+		start_reg = I2C_TRANSAC_START | I2C_RS_MUL_TRIG;
+		if (left_num >= 1)
+			start_reg |= I2C_RS_MUL_CNFG;
+	}
+	i2c_writel(priv, REG_START, start_reg);
+
+	for (;;) {
+		irq_stat = i2c_readl(priv, REG_INTR_STAT);
+
+		/* ignore the first restart irq after the master code */
+		if (priv->ignore_restart_irq && (irq_stat & restart_flag)) {
+			priv->ignore_restart_irq = false;
+			irq_stat = 0;
+			i2c_writel(priv, REG_START, I2C_RS_MUL_CNFG |
+				   I2C_RS_MUL_TRIG | I2C_TRANSAC_START);
+		}
+
+		if (irq_stat & (I2C_TRANSAC_COMP | restart_flag)) {
+			tmo = false;
+			if (irq_stat & (I2C_HS_NACKERR | I2C_ACKERR))
+				trans_error = 1;
+
+			break;
+		}
+		udelay(1);
+		if (tmo_poll++ >= TRANSFER_TIMEOUT) {
+			tmo = true;
+			break;
+		}
+	}
+
+	/* clear interrupt mask */
+	i2c_writel(priv, REG_INTR_MASK, ~(restart_flag | I2C_HS_NACKERR |
+		  I2C_ACKERR | I2C_TRANSAC_COMP));
+
+	if (!tmo && trans_error != 0) {
+		if (tmo) {
+			ret = -ETIMEDOUT;
+			if (!priv->filter_msg)
+				debug("I2C timeout! addr: 0x%x,\n", msgs->addr);
+		} else {
+			ret = -EREMOTEIO;
+			if (!priv->filter_msg)
+				debug("I2C ACKERR! addr: 0x%x,IRQ:0x%x\n",
+				      msgs->addr, irq_stat);
+		}
+		mtk_i2c_init_hw(priv);
+	}
+
+	return ret;
+}
+
+/*
+ * mtk_i2c_transfer
+ *
+ * @par Description
+ *     Common i2c transfer API. Set i2c transfer mode according to i2c_msg\n
+ *     information, then call mtk_i2c_do_transfer() to configure i2c register\n
+ *     and trigger transfer.
+ * @param[in]
+ *     dev: udevice pointer, struct udevice contains struct mtk_i2c_priv, \n
+ *	   struct mtk_i2c_priv contains register base\n
+ *     address, operation mode, interrupt status and i2c driver data.
+ * @param[in]
+ *     msgs: i2c_msg pointer, struct i2c_msg contains slave\n
+ *     address, operation mode, msg length and data buffer.
+ * @param[in]
+ *     num: i2c_msg number.
+ * @return
+ *     i2c_msg number, i2c transfer successfully.\n
+ *     -EINVAL, msg length is more than 16\n
+ *     use DMA MODE or slave address more than 0x7f.\n
+ *     error code from mtk_i2c_init_base().\n
+ *     error code from mtk_i2c_set_speed().\n
+ *     error code from mtk_i2c_do_transfer().
+ */
+static int mtk_i2c_transfer(struct udevice *dev, struct i2c_msg *msg,
+			    int nmsgs)
+{
+	struct mtk_i2c_priv *priv = dev_get_priv(dev);
+	int left_num;
+	uint num_cnt;
+	int ret;
+
+	priv->auto_restart = true;
+	left_num = nmsgs;
+	if (mtk_i2c_clk_enable(priv))
+		return log_msg_ret("transfer enable clk", -1);
+
+	for (num_cnt = 0; num_cnt < nmsgs; num_cnt++) {
+		if (((msg + num_cnt)->addr) > MAX_I2C_ADDR) {
+			ret = -EINVAL;
+			goto err_exit;
+		}
+		if ((msg + num_cnt)->len > MAX_I2C_LEN) {
+			ret = -EINVAL;
+			goto err_exit;
+		}
+	}
+
+	/* check if we can skip restart and optimize using WRRD mode */
+	if (priv->auto_restart && nmsgs == 2) {
+		if (!(msg[0].flags & I2C_M_RD) && (msg[1].flags & I2C_M_RD) &&
+		    msg[0].addr == msg[1].addr) {
+			priv->auto_restart = false;
+		}
+	}
+
+	if (priv->auto_restart && nmsgs >= 2 && priv->speed > MAX_FS_MODE_SPEED)
+		/* ignore the first restart irq after the master code,
+		 * otherwise the first transfer will be discarded.
+		 */
+		priv->ignore_restart_irq = true;
+	else
+		priv->ignore_restart_irq = false;
+
+	while (left_num--) {
+		/* transfer slave address only to support devices detect */
+		if (!msg->buf)
+			priv->zero_len = true;
+		else
+			priv->zero_len = false;
+
+		if (msg->flags & I2C_M_RD)
+			priv->op = I2C_MASTER_RD;
+		else
+			priv->op = I2C_MASTER_WR;
+
+		if (!priv->auto_restart) {
+			if (nmsgs > 1) {
+				/* combined two messages into one transaction */
+				priv->op = I2C_MASTER_WRRD;
+				left_num--;
+			}
+		}
+		ret = mtk_i2c_do_transfer(priv, msg, nmsgs, left_num);
+		if (ret < 0)
+			goto err_exit;
+		msg++;
+	}
+	ret = 0;
+
+err_exit:
+	if (mtk_i2c_clk_disable(priv))
+		return log_msg_ret("transfer disable clk", -1);
+
+	return ret;
+}
+
+static int mtk_i2c_of_to_plat(struct udevice *dev)
+{
+	struct mtk_i2c_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	priv->base = dev_remap_addr_index(dev, 0);
+	priv->pdmabase = dev_remap_addr_index(dev, 1);
+	ret = clk_get_by_index(dev, 0, &priv->clk_main);
+	if (ret)
+		return log_msg_ret("clk_get_by_index 0", ret);
+
+	ret = clk_get_by_index(dev, 1, &priv->clk_dma);
+
+	return ret;
+}
+
+static int mtk_i2c_probe(struct udevice *dev)
+{
+	struct mtk_i2c_priv *priv = dev_get_priv(dev);
+
+	priv->soc_data = (struct mtk_i2c_soc_data *)dev_get_driver_data(dev);
+
+	if (mtk_i2c_clk_enable(priv))
+		return log_msg_ret("probe enable clk", -1);
+
+	mtk_i2c_init_hw(priv);
+
+	if (mtk_i2c_clk_disable(priv))
+		return log_msg_ret("probe disable clk", -1);
+
+	return 0;
+}
+
+static int mtk_i2c_deblock(struct udevice *dev)
+{
+	struct mtk_i2c_priv *priv = dev_get_priv(dev);
+
+	if (mtk_i2c_clk_enable(priv))
+		return log_msg_ret("deblock enable clk", -1);
+
+	mtk_i2c_init_hw(priv);
+
+	if (mtk_i2c_clk_disable(priv))
+		return log_msg_ret("deblock disable clk", -1);
+
+	return 0;
+}
+
+static const struct mtk_i2c_soc_data mt76xx_soc_data = {
+	.regs = mt_i2c_regs_v1,
+	.dma_sync = 0,
+};
+
+static const struct mtk_i2c_soc_data mt7981_soc_data = {
+	.regs = mt_i2c_regs_v1,
+	.dma_sync = 1,
+};
+
+static const struct mtk_i2c_soc_data mt7986_soc_data = {
+	.regs = mt_i2c_regs_v1,
+	.dma_sync = 1,
+};
+
+static const struct mtk_i2c_soc_data mt8183_soc_data = {
+	.regs = mt_i2c_regs_v2,
+	.dma_sync = 1,
+};
+
+static const struct mtk_i2c_soc_data mt8518_soc_data = {
+	.regs = mt_i2c_regs_v1,
+	.dma_sync = 0,
+};
+
+static const struct mtk_i2c_soc_data mt8512_soc_data = {
+	.regs = mt_i2c_regs_v1,
+	.dma_sync = 1,
+};
+
+static const struct dm_i2c_ops mtk_i2c_ops = {
+	.xfer		= mtk_i2c_transfer,
+	.set_bus_speed	= mtk_i2c_set_speed,
+	.deblock	= mtk_i2c_deblock,
+};
+
+static const struct udevice_id mtk_i2c_ids[] = {
+	{
+		.compatible = "mediatek,mt7622-i2c",
+		.data = (ulong)&mt76xx_soc_data,
+	}, {
+		.compatible = "mediatek,mt7623-i2c",
+		.data = (ulong)&mt76xx_soc_data,
+	}, {
+		.compatible = "mediatek,mt7629-i2c",
+		.data = (ulong)&mt76xx_soc_data,
+	}, {
+		.compatible = "mediatek,mt7981-i2c",
+		.data = (ulong)&mt7981_soc_data,
+	}, {
+		.compatible = "mediatek,mt7986-i2c",
+		.data = (ulong)&mt7986_soc_data,
+	}, {
+		.compatible = "mediatek,mt8183-i2c",
+		.data = (ulong)&mt8183_soc_data,
+	}, {
+		.compatible = "mediatek,mt8512-i2c",
+		.data = (ulong)&mt8512_soc_data,
+	}, {
+		.compatible = "mediatek,mt8518-i2c",
+		.data = (ulong)&mt8518_soc_data,
+	}
+};
+
+U_BOOT_DRIVER(mtk_i2c) = {
+	.name		= "mtk_i2c",
+	.id		= UCLASS_I2C,
+	.of_match	= mtk_i2c_ids,
+	.of_to_plat	= mtk_i2c_of_to_plat,
+	.probe		= mtk_i2c_probe,
+	.priv_auto	= sizeof(struct mtk_i2c_priv),
+	.ops		= &mtk_i2c_ops,
+};
-- 
2.17.1


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

* [PATCH v2 18/32] arm: dts: mt7622: add i2c support
  2022-08-31 11:00 [PATCH v2 00/32] Add support for MediaTek MT7981/MT7986 SoCs - v2 Weijie Gao
                   ` (16 preceding siblings ...)
  2022-08-31 11:04 ` [PATCH v2 17/32] i2c: add support for MediaTek I2C interface Weijie Gao
@ 2022-08-31 11:04 ` Weijie Gao
  2022-08-31 11:04 ` [PATCH v2 19/32] dt-bindings: pinctrl: mediatek: add a header for common pinconf parameters Weijie Gao
                   ` (13 subsequent siblings)
  31 siblings, 0 replies; 60+ messages in thread
From: Weijie Gao @ 2022-08-31 11:04 UTC (permalink / raw)
  To: u-boot; +Cc: GSS_MTK_Uboot_upstream, Weijie Gao

Add both hardware and software i2c support for mt7622.

Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
---
v2 changes: none
---
 arch/arm/dts/mt7622-rfb.dts | 18 ++++++++++++++++++
 arch/arm/dts/mt7622.dtsi    | 24 ++++++++++++++++++++++++
 2 files changed, 42 insertions(+)

diff --git a/arch/arm/dts/mt7622-rfb.dts b/arch/arm/dts/mt7622-rfb.dts
index 30a9137407..b44f19f05a 100644
--- a/arch/arm/dts/mt7622-rfb.dts
+++ b/arch/arm/dts/mt7622-rfb.dts
@@ -159,6 +159,14 @@
 		};
 
 	};
+
+	i2c1_pins_default: i2c1-default {
+		mux {
+			function = "i2c";
+			groups = "i2c1_0";
+		};
+	};
+
 };
 
 &snfi {
@@ -242,3 +250,13 @@
 &u3phy {
        status = "okay";
 };
+
+&soft_i2c {
+	status = "disabled";
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins_default>;
+	status = "okay";
+};
diff --git a/arch/arm/dts/mt7622.dtsi b/arch/arm/dts/mt7622.dtsi
index fb6c1b7154..2d89fa08b4 100644
--- a/arch/arm/dts/mt7622.dtsi
+++ b/arch/arm/dts/mt7622.dtsi
@@ -424,4 +424,28 @@
 		status = "disabled";
 	};
 
+	soft_i2c: soft_i2c@0 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "i2c-gpio";
+		gpios = <&gpio 56 GPIO_ACTIVE_HIGH>, /* SDA */
+			<&gpio 55 GPIO_ACTIVE_HIGH>; /* CLK */
+		i2c-gpio,delay-us = <5>;
+		status = "disabled";
+	};
+
+	i2c1: i2c@11008000 {
+		compatible = "mediatek,mt7622-i2c";
+		reg = <0x11008000 0x90>,
+		      <0x11000180 0x80>;
+		interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_LOW>;
+		clock-div = <16>;
+		clocks = <&pericfg CLK_PERI_I2C1_PD>,
+			 <&pericfg CLK_PERI_AP_DMA_PD>;
+		clock-names = "main", "dma";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
 };
-- 
2.17.1


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

* [PATCH v2 19/32] dt-bindings: pinctrl: mediatek: add a header for common pinconf parameters
  2022-08-31 11:00 [PATCH v2 00/32] Add support for MediaTek MT7981/MT7986 SoCs - v2 Weijie Gao
                   ` (17 preceding siblings ...)
  2022-08-31 11:04 ` [PATCH v2 18/32] arm: dts: mt7622: add i2c support Weijie Gao
@ 2022-08-31 11:04 ` Weijie Gao
  2022-08-31 11:04 ` [PATCH v2 20/32] pinctrl: mediatek: add pinctrl driver for MT7981 SoC Weijie Gao
                   ` (12 subsequent siblings)
  31 siblings, 0 replies; 60+ messages in thread
From: Weijie Gao @ 2022-08-31 11:04 UTC (permalink / raw)
  To: u-boot; +Cc: GSS_MTK_Uboot_upstream, Weijie Gao

This patch adds a pinctrl header for common pinconf parameters such as
pull-up/pull-down resistors and drive strengths.

Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
---
v2 changes: none
---
 include/dt-bindings/pinctrl/mt65xx.h | 41 ++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)
 create mode 100644 include/dt-bindings/pinctrl/mt65xx.h

diff --git a/include/dt-bindings/pinctrl/mt65xx.h b/include/dt-bindings/pinctrl/mt65xx.h
new file mode 100644
index 0000000000..fbea8d35bc
--- /dev/null
+++ b/include/dt-bindings/pinctrl/mt65xx.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ * Author: Hongzhou.Yang <hongzhou.yang@mediatek.com>
+ */
+
+#ifndef _DT_BINDINGS_PINCTRL_MT65XX_H
+#define _DT_BINDINGS_PINCTRL_MT65XX_H
+
+#define MTK_PIN_NO(x)		((x) << 8)
+#define MTK_GET_PIN_NO(x)	((x) >> 8)
+#define MTK_GET_PIN_FUNC(x)	((x) & 0xf)
+
+#define MTK_PUPD_SET_R1R0_00	100
+#define MTK_PUPD_SET_R1R0_01	101
+#define MTK_PUPD_SET_R1R0_10	102
+#define MTK_PUPD_SET_R1R0_11	103
+
+#define MTK_PULL_SET_RSEL_000	200
+#define MTK_PULL_SET_RSEL_001	201
+#define MTK_PULL_SET_RSEL_010	202
+#define MTK_PULL_SET_RSEL_011	203
+#define MTK_PULL_SET_RSEL_100	204
+#define MTK_PULL_SET_RSEL_101	205
+#define MTK_PULL_SET_RSEL_110	206
+#define MTK_PULL_SET_RSEL_111	207
+
+#define MTK_DRIVE_2mA		2
+#define MTK_DRIVE_4mA		4
+#define MTK_DRIVE_6mA		6
+#define MTK_DRIVE_8mA		8
+#define MTK_DRIVE_10mA		10
+#define MTK_DRIVE_12mA		12
+#define MTK_DRIVE_14mA		14
+#define MTK_DRIVE_16mA		16
+#define MTK_DRIVE_20mA		20
+#define MTK_DRIVE_24mA		24
+#define MTK_DRIVE_28mA		28
+#define MTK_DRIVE_32mA		32
+
+#endif /* _DT_BINDINGS_PINCTRL_MT65XX_H */
-- 
2.17.1


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

* [PATCH v2 20/32] pinctrl: mediatek: add pinctrl driver for MT7981 SoC
  2022-08-31 11:00 [PATCH v2 00/32] Add support for MediaTek MT7981/MT7986 SoCs - v2 Weijie Gao
                   ` (18 preceding siblings ...)
  2022-08-31 11:04 ` [PATCH v2 19/32] dt-bindings: pinctrl: mediatek: add a header for common pinconf parameters Weijie Gao
@ 2022-08-31 11:04 ` Weijie Gao
  2022-08-31 11:04 ` [PATCH v2 21/32] pinctrl: mediatek: add pinctrl driver for MT7986 SoC Weijie Gao
                   ` (11 subsequent siblings)
  31 siblings, 0 replies; 60+ messages in thread
From: Weijie Gao @ 2022-08-31 11:04 UTC (permalink / raw)
  To: u-boot; +Cc: GSS_MTK_Uboot_upstream, Weijie Gao

This patch adds pinctrl and gpio support for MT7981 SoC

Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
---
v2 changes: none
---
 drivers/pinctrl/mediatek/Kconfig          |    4 +
 drivers/pinctrl/mediatek/Makefile         |    1 +
 drivers/pinctrl/mediatek/pinctrl-mt7981.c | 1049 +++++++++++++++++++++
 3 files changed, 1054 insertions(+)
 create mode 100644 drivers/pinctrl/mediatek/pinctrl-mt7981.c

diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig
index 58df508d7e..aceec9277d 100644
--- a/drivers/pinctrl/mediatek/Kconfig
+++ b/drivers/pinctrl/mediatek/Kconfig
@@ -16,6 +16,10 @@ config PINCTRL_MT7629
 	bool "MT7629 SoC pinctrl driver"
 	select PINCTRL_MTK
 
+config PINCTRL_MT7981
+	bool "MT7981 SoC pinctrl driver"
+	select PINCTRL_MTK
+
 config PINCTRL_MT8512
 	bool "MT8512 SoC pinctrl driver"
 	select PINCTRL_MTK
diff --git a/drivers/pinctrl/mediatek/Makefile b/drivers/pinctrl/mediatek/Makefile
index d7e8cf1727..1879d7ae2a 100644
--- a/drivers/pinctrl/mediatek/Makefile
+++ b/drivers/pinctrl/mediatek/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_PINCTRL_MTK) += pinctrl-mtk-common.o
 obj-$(CONFIG_PINCTRL_MT7622) += pinctrl-mt7622.o
 obj-$(CONFIG_PINCTRL_MT7623) += pinctrl-mt7623.o
 obj-$(CONFIG_PINCTRL_MT7629) += pinctrl-mt7629.o
+obj-$(CONFIG_PINCTRL_MT7981) += pinctrl-mt7981.o
 obj-$(CONFIG_PINCTRL_MT8512) += pinctrl-mt8512.o
 obj-$(CONFIG_PINCTRL_MT8516) += pinctrl-mt8516.o
 obj-$(CONFIG_PINCTRL_MT8518) += pinctrl-mt8518.o
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt7981.c b/drivers/pinctrl/mediatek/pinctrl-mt7981.c
new file mode 100644
index 0000000000..d8875241cb
--- /dev/null
+++ b/drivers/pinctrl/mediatek/pinctrl-mt7981.c
@@ -0,0 +1,1049 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * The MT7981 driver based on Linux generic pinctrl binding.
+ *
+ * Copyright (C) 2022 MediaTek Inc.
+ * Author: Sam Shih <sam.shih@mediatek.com>
+ */
+
+#include <dm.h>
+#include "pinctrl-mtk-common.h"
+
+#define MT7981_TYPE0_PIN(_number, _name)	\
+	MTK_TYPED_PIN(_number, _name, DRV_GRP4, IO_TYPE_GRP0)
+
+#define MT7981_TYPE1_PIN(_number, _name)	\
+	MTK_TYPED_PIN(_number, _name, DRV_GRP4, IO_TYPE_GRP1)
+
+#define PIN_FIELD_GPIO(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit, _x_bits)	\
+	PIN_FIELD_BASE_CALC(_s_pin, _e_pin, GPIO_BASE, _s_addr, _x_addrs,	\
+			    _s_bit, _x_bits, 32, 0)
+
+#define PIN_FIELD_BASE(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit,	\
+		       _x_bits)							\
+	PIN_FIELD_BASE_CALC(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit,	\
+	_x_bits, 32, 0)
+
+/**
+ * enum - Locking variants of the iocfg bases
+ *
+ * MT7981 have multiple bases to program pin configuration listed as the below:
+ * iocfg_rt:0x11c00000, iocfg_rm:0x11c10000, iocfg_rb:0x11d20000,
+ * iocfg_lb:0x11e00000, iocfg_bl:0x11e20000, iocfg_tm:0x11f00000,
+ * iocfg_tl:0x11f10000,
+ * _i_based could be used to indicate what base the pin should be mapped into.
+ *
+ * Each iocfg register base control different group of pads on the SoC
+ *
+ *
+ *  chip carrier
+ *
+ *      A  B  C  D  E  F  G  H
+ *    +------------------------+
+ *  8 | o  o  o  o  o  o  o  o |
+ *  7 | o  o  o  o  o  o  o  o |
+ *  6 | o  o  o  o  o  o  o  o |
+ *  5 | o  o  o  o  o  o  o  o |
+ *  4 | o  o  o  o  o  o  o  o |
+ *  3 | o  o  o  o  o  o  o  o |
+ *  2 | o  o  o  o  o  o  o  o |
+ *  1 | o  o  o  o  o  o  o  o |
+ *    +------------------------+
+ *
+ *  inside Chip carrier
+ *
+ *      A  B  C  D  E  F  G  H
+ *    +------------------------+
+ *  8 |                        |
+ *  7 |       TL TM            |
+ *  6 |      +---------+       |
+ *  5 |      |         | RT    |
+ *  4 |      |         | RM    |
+ *  3 |   LB |         | RB    |
+ *  2 |      +---------+       |
+ *  1 |        BL              |
+ *    +------------------------+
+ *
+ */
+
+enum {
+	GPIO_BASE,
+	IOCFG_RT_BASE,
+	IOCFG_RM_BASE,
+	IOCFG_RB_BASE,
+	IOCFG_LB_BASE,
+	IOCFG_BL_BASE,
+	IOCFG_TM_BASE,
+	IOCFG_TL_BASE,
+};
+
+static const struct mtk_pin_field_calc mt7981_pin_mode_range[] = {
+	PIN_FIELD_GPIO(0, 56, 0x300, 0x10, 0, 4),
+};
+
+static const struct mtk_pin_field_calc mt7981_pin_dir_range[] = {
+	PIN_FIELD_GPIO(0, 56, 0x0, 0x10, 0, 1),
+};
+
+static const struct mtk_pin_field_calc mt7981_pin_di_range[] = {
+	PIN_FIELD_GPIO(0, 56, 0x200, 0x10, 0, 1),
+};
+
+static const struct mtk_pin_field_calc mt7981_pin_do_range[] = {
+	PIN_FIELD_GPIO(0, 56, 0x100, 0x10, 0, 1),
+};
+
+static const struct mtk_pin_field_calc mt7981_pin_ies_range[] = {
+	PIN_FIELD_BASE(0, 0, 1, 0x10, 0x10, 1, 1),
+	PIN_FIELD_BASE(1, 1, 1, 0x10, 0x10, 0, 1),
+	PIN_FIELD_BASE(2, 2, 5, 0x20, 0x10, 6, 1),
+	PIN_FIELD_BASE(3, 3, 4, 0x20, 0x10, 6, 1),
+	PIN_FIELD_BASE(4, 4, 4, 0x20, 0x10, 2, 1),
+	PIN_FIELD_BASE(5, 5, 4, 0x20, 0x10, 1, 1),
+	PIN_FIELD_BASE(6, 6, 4, 0x20, 0x10, 3, 1),
+	PIN_FIELD_BASE(7, 7, 4, 0x20, 0x10, 0, 1),
+	PIN_FIELD_BASE(8, 8, 4, 0x20, 0x10, 4, 1),
+	PIN_FIELD_BASE(9, 9, 4, 0x20, 0x10, 9, 1),
+
+	PIN_FIELD_BASE(10, 10, 5, 0x20, 0x10, 8, 1),
+	PIN_FIELD_BASE(11, 11, 5, 0x40, 0x10, 10, 1),
+	PIN_FIELD_BASE(12, 12, 5, 0x20, 0x10, 7, 1),
+	PIN_FIELD_BASE(13, 13, 5, 0x20, 0x10, 11, 1),
+
+	PIN_FIELD_BASE(14, 14, 4, 0x20, 0x10, 8, 1),
+
+	PIN_FIELD_BASE(15, 15, 2, 0x20, 0x10, 0, 1),
+	PIN_FIELD_BASE(16, 16, 2, 0x20, 0x10, 1, 1),
+	PIN_FIELD_BASE(17, 17, 2, 0x20, 0x10, 5, 1),
+	PIN_FIELD_BASE(18, 18, 2, 0x20, 0x10, 4, 1),
+	PIN_FIELD_BASE(19, 19, 2, 0x20, 0x10, 2, 1),
+	PIN_FIELD_BASE(20, 20, 2, 0x20, 0x10, 3, 1),
+	PIN_FIELD_BASE(21, 21, 2, 0x20, 0x10, 6, 1),
+	PIN_FIELD_BASE(22, 22, 2, 0x20, 0x10, 7, 1),
+	PIN_FIELD_BASE(23, 23, 2, 0x20, 0x10, 10, 1),
+	PIN_FIELD_BASE(24, 24, 2, 0x20, 0x10, 9, 1),
+	PIN_FIELD_BASE(25, 25, 2, 0x20, 0x10, 8, 1),
+
+	PIN_FIELD_BASE(26, 26, 5, 0x20, 0x10, 0, 1),
+	PIN_FIELD_BASE(27, 27, 5, 0x20, 0x10, 4, 1),
+	PIN_FIELD_BASE(28, 28, 5, 0x20, 0x10, 3, 1),
+	PIN_FIELD_BASE(29, 29, 5, 0x20, 0x10, 1, 1),
+	PIN_FIELD_BASE(30, 30, 5, 0x20, 0x10, 2, 1),
+	PIN_FIELD_BASE(31, 31, 5, 0x20, 0x10, 5, 1),
+
+	PIN_FIELD_BASE(32, 32, 1, 0x10, 0x10, 2, 1),
+	PIN_FIELD_BASE(33, 33, 1, 0x10, 0x10, 3, 1),
+
+	PIN_FIELD_BASE(34, 34, 4, 0x20, 0x10, 5, 1),
+	PIN_FIELD_BASE(35, 35, 4, 0x20, 0x10, 7, 1),
+
+	PIN_FIELD_BASE(36, 36, 3, 0x10, 0x10, 2, 1),
+	PIN_FIELD_BASE(37, 37, 3, 0x10, 0x10, 3, 1),
+	PIN_FIELD_BASE(38, 38, 3, 0x10, 0x10, 0, 1),
+	PIN_FIELD_BASE(39, 39, 3, 0x10, 0x10, 1, 1),
+
+	PIN_FIELD_BASE(40, 40, 7, 0x30, 0x10, 1, 1),
+	PIN_FIELD_BASE(41, 41, 7, 0x30, 0x10, 0, 1),
+	PIN_FIELD_BASE(42, 42, 7, 0x30, 0x10, 9, 1),
+	PIN_FIELD_BASE(43, 43, 7, 0x30, 0x10, 7, 1),
+	PIN_FIELD_BASE(44, 44, 7, 0x30, 0x10, 8, 1),
+	PIN_FIELD_BASE(45, 45, 7, 0x30, 0x10, 3, 1),
+	PIN_FIELD_BASE(46, 46, 7, 0x30, 0x10, 4, 1),
+	PIN_FIELD_BASE(47, 47, 7, 0x30, 0x10, 5, 1),
+	PIN_FIELD_BASE(48, 48, 7, 0x30, 0x10, 6, 1),
+	PIN_FIELD_BASE(49, 49, 7, 0x30, 0x10, 2, 1),
+
+	PIN_FIELD_BASE(50, 50, 6, 0x10, 0x10, 0, 1),
+	PIN_FIELD_BASE(51, 51, 6, 0x10, 0x10, 2, 1),
+	PIN_FIELD_BASE(52, 52, 6, 0x10, 0x10, 3, 1),
+	PIN_FIELD_BASE(53, 53, 6, 0x10, 0x10, 4, 1),
+	PIN_FIELD_BASE(54, 54, 6, 0x10, 0x10, 5, 1),
+	PIN_FIELD_BASE(55, 55, 6, 0x10, 0x10, 6, 1),
+	PIN_FIELD_BASE(56, 56, 6, 0x10, 0x10, 1, 1),
+};
+
+static const struct mtk_pin_field_calc mt7981_pin_smt_range[] = {
+	PIN_FIELD_BASE(0, 0, 1, 0x60, 0x10, 1, 1),
+	PIN_FIELD_BASE(1, 1, 1, 0x60, 0x10, 0, 1),
+	PIN_FIELD_BASE(2, 2, 5, 0x90, 0x10, 6, 1),
+	PIN_FIELD_BASE(3, 3, 4, 0x80, 0x10, 6, 1),
+	PIN_FIELD_BASE(4, 4, 4, 0x80, 0x10, 2, 1),
+	PIN_FIELD_BASE(5, 5, 4, 0x80, 0x10, 1, 1),
+	PIN_FIELD_BASE(6, 6, 4, 0x80, 0x10, 3, 1),
+	PIN_FIELD_BASE(7, 7, 4, 0x80, 0x10, 0, 1),
+	PIN_FIELD_BASE(8, 8, 4, 0x80, 0x10, 4, 1),
+	PIN_FIELD_BASE(9, 9, 4, 0x80, 0x10, 9, 1),
+
+	PIN_FIELD_BASE(10, 10, 5, 0x90, 0x10, 8, 1),
+	PIN_FIELD_BASE(11, 11, 5, 0x90, 0x10, 10, 1),
+	PIN_FIELD_BASE(12, 12, 5, 0x90, 0x10, 7, 1),
+	PIN_FIELD_BASE(13, 13, 5, 0x90, 0x10, 11, 1),
+
+	PIN_FIELD_BASE(14, 14, 4, 0x80, 0x10, 8, 1),
+
+	PIN_FIELD_BASE(15, 15, 2, 0x90, 0x10, 0, 1),
+	PIN_FIELD_BASE(16, 16, 2, 0x90, 0x10, 1, 1),
+	PIN_FIELD_BASE(17, 17, 2, 0x90, 0x10, 5, 1),
+	PIN_FIELD_BASE(18, 18, 2, 0x90, 0x10, 4, 1),
+	PIN_FIELD_BASE(19, 19, 2, 0x90, 0x10, 2, 1),
+	PIN_FIELD_BASE(20, 20, 2, 0x90, 0x10, 3, 1),
+	PIN_FIELD_BASE(21, 21, 2, 0x90, 0x10, 6, 1),
+	PIN_FIELD_BASE(22, 22, 2, 0x90, 0x10, 7, 1),
+	PIN_FIELD_BASE(23, 23, 2, 0x90, 0x10, 10, 1),
+	PIN_FIELD_BASE(24, 24, 2, 0x90, 0x10, 9, 1),
+	PIN_FIELD_BASE(25, 25, 2, 0x90, 0x10, 8, 1),
+
+	PIN_FIELD_BASE(26, 26, 5, 0x90, 0x10, 0, 1),
+	PIN_FIELD_BASE(27, 27, 5, 0x90, 0x10, 4, 1),
+	PIN_FIELD_BASE(28, 28, 5, 0x90, 0x10, 3, 1),
+	PIN_FIELD_BASE(29, 29, 5, 0x90, 0x10, 1, 1),
+	PIN_FIELD_BASE(30, 30, 5, 0x90, 0x10, 2, 1),
+	PIN_FIELD_BASE(31, 31, 5, 0x90, 0x10, 5, 1),
+
+	PIN_FIELD_BASE(32, 32, 1, 0x60, 0x10, 2, 1),
+	PIN_FIELD_BASE(33, 33, 1, 0x60, 0x10, 3, 1),
+
+	PIN_FIELD_BASE(34, 34, 4, 0x80, 0x10, 5, 1),
+	PIN_FIELD_BASE(35, 35, 4, 0x80, 0x10, 7, 1),
+
+	PIN_FIELD_BASE(36, 36, 3, 0x60, 0x10, 2, 1),
+	PIN_FIELD_BASE(37, 37, 3, 0x60, 0x10, 3, 1),
+	PIN_FIELD_BASE(38, 38, 3, 0x60, 0x10, 0, 1),
+	PIN_FIELD_BASE(39, 39, 3, 0x60, 0x10, 1, 1),
+
+	PIN_FIELD_BASE(40, 40, 7, 0x70, 0x10, 1, 1),
+	PIN_FIELD_BASE(41, 41, 7, 0x70, 0x10, 0, 1),
+	PIN_FIELD_BASE(42, 42, 7, 0x70, 0x10, 9, 1),
+	PIN_FIELD_BASE(43, 43, 7, 0x70, 0x10, 7, 1),
+	PIN_FIELD_BASE(44, 44, 7, 0x30, 0x10, 8, 1),
+	PIN_FIELD_BASE(45, 45, 7, 0x70, 0x10, 3, 1),
+	PIN_FIELD_BASE(46, 46, 7, 0x70, 0x10, 4, 1),
+	PIN_FIELD_BASE(47, 47, 7, 0x70, 0x10, 5, 1),
+	PIN_FIELD_BASE(48, 48, 7, 0x70, 0x10, 6, 1),
+	PIN_FIELD_BASE(49, 49, 7, 0x70, 0x10, 2, 1),
+
+	PIN_FIELD_BASE(50, 50, 6, 0x50, 0x10, 0, 1),
+	PIN_FIELD_BASE(51, 51, 6, 0x50, 0x10, 2, 1),
+	PIN_FIELD_BASE(52, 52, 6, 0x50, 0x10, 3, 1),
+	PIN_FIELD_BASE(53, 53, 6, 0x50, 0x10, 4, 1),
+	PIN_FIELD_BASE(54, 54, 6, 0x50, 0x10, 5, 1),
+	PIN_FIELD_BASE(55, 55, 6, 0x50, 0x10, 6, 1),
+	PIN_FIELD_BASE(56, 56, 6, 0x50, 0x10, 1, 1),
+};
+
+static const struct mtk_pin_field_calc mt7981_pin_pu_range[] = {
+	PIN_FIELD_BASE(40, 40, 7, 0x50, 0x10, 1, 1),
+	PIN_FIELD_BASE(41, 41, 7, 0x50, 0x10, 0, 1),
+	PIN_FIELD_BASE(42, 42, 7, 0x50, 0x10, 9, 1),
+	PIN_FIELD_BASE(43, 43, 7, 0x50, 0x10, 7, 1),
+	PIN_FIELD_BASE(44, 44, 7, 0x50, 0x10, 8, 1),
+	PIN_FIELD_BASE(45, 45, 7, 0x50, 0x10, 3, 1),
+	PIN_FIELD_BASE(46, 46, 7, 0x50, 0x10, 4, 1),
+	PIN_FIELD_BASE(47, 47, 7, 0x50, 0x10, 5, 1),
+	PIN_FIELD_BASE(48, 48, 7, 0x50, 0x10, 6, 1),
+	PIN_FIELD_BASE(49, 49, 7, 0x50, 0x10, 2, 1),
+
+	PIN_FIELD_BASE(50, 50, 6, 0x30, 0x10, 0, 1),
+	PIN_FIELD_BASE(51, 51, 6, 0x30, 0x10, 2, 1),
+	PIN_FIELD_BASE(52, 52, 6, 0x30, 0x10, 3, 1),
+	PIN_FIELD_BASE(53, 53, 6, 0x30, 0x10, 4, 1),
+	PIN_FIELD_BASE(54, 54, 6, 0x30, 0x10, 5, 1),
+	PIN_FIELD_BASE(55, 55, 6, 0x30, 0x10, 6, 1),
+	PIN_FIELD_BASE(56, 56, 6, 0x30, 0x10, 1, 1),
+};
+
+static const struct mtk_pin_field_calc mt7981_pin_pd_range[] = {
+	PIN_FIELD_BASE(40, 40, 7, 0x40, 0x10, 1, 1),
+	PIN_FIELD_BASE(41, 41, 7, 0x40, 0x10, 0, 1),
+	PIN_FIELD_BASE(42, 42, 7, 0x40, 0x10, 9, 1),
+	PIN_FIELD_BASE(43, 43, 7, 0x40, 0x10, 7, 1),
+	PIN_FIELD_BASE(44, 44, 7, 0x40, 0x10, 8, 1),
+	PIN_FIELD_BASE(45, 45, 7, 0x40, 0x10, 3, 1),
+	PIN_FIELD_BASE(46, 46, 7, 0x40, 0x10, 4, 1),
+	PIN_FIELD_BASE(47, 47, 7, 0x40, 0x10, 5, 1),
+	PIN_FIELD_BASE(48, 48, 7, 0x40, 0x10, 6, 1),
+	PIN_FIELD_BASE(49, 49, 7, 0x40, 0x10, 2, 1),
+
+	PIN_FIELD_BASE(50, 50, 6, 0x20, 0x10, 0, 1),
+	PIN_FIELD_BASE(51, 51, 6, 0x20, 0x10, 2, 1),
+	PIN_FIELD_BASE(52, 52, 6, 0x20, 0x10, 3, 1),
+	PIN_FIELD_BASE(53, 53, 6, 0x20, 0x10, 4, 1),
+	PIN_FIELD_BASE(54, 54, 6, 0x20, 0x10, 5, 1),
+	PIN_FIELD_BASE(55, 55, 6, 0x20, 0x10, 6, 1),
+	PIN_FIELD_BASE(56, 56, 6, 0x20, 0x10, 1, 1),
+};
+
+static const struct mtk_pin_field_calc mt7981_pin_drv_range[] = {
+	PIN_FIELD_BASE(0, 0, 1, 0x00, 0x10, 3, 3),
+	PIN_FIELD_BASE(1, 1, 1, 0x00, 0x10, 0, 3),
+
+	PIN_FIELD_BASE(2, 2, 5, 0x00, 0x10, 18, 3),
+
+	PIN_FIELD_BASE(3, 3, 4, 0x00, 0x10, 18, 1),
+	PIN_FIELD_BASE(4, 4, 4, 0x00, 0x10, 6, 1),
+	PIN_FIELD_BASE(5, 5, 4, 0x00, 0x10, 3, 3),
+	PIN_FIELD_BASE(6, 6, 4, 0x00, 0x10, 9, 3),
+	PIN_FIELD_BASE(7, 7, 4, 0x00, 0x10, 0, 3),
+	PIN_FIELD_BASE(8, 8, 4, 0x00, 0x10, 12, 3),
+	PIN_FIELD_BASE(9, 9, 4, 0x00, 0x10, 27, 3),
+
+	PIN_FIELD_BASE(10, 10, 5, 0x00, 0x10, 24, 3),
+	PIN_FIELD_BASE(11, 11, 5, 0x00, 0x10, 0, 3),
+	PIN_FIELD_BASE(12, 12, 5, 0x00, 0x10, 21, 3),
+	PIN_FIELD_BASE(13, 13, 5, 0x00, 0x10, 3, 3),
+
+	PIN_FIELD_BASE(14, 14, 4, 0x00, 0x10, 27, 3),
+
+	PIN_FIELD_BASE(15, 15, 2, 0x00, 0x10, 0, 3),
+	PIN_FIELD_BASE(16, 16, 2, 0x00, 0x10, 3, 3),
+	PIN_FIELD_BASE(17, 17, 2, 0x00, 0x10, 15, 3),
+	PIN_FIELD_BASE(18, 18, 2, 0x00, 0x10, 12, 3),
+	PIN_FIELD_BASE(19, 19, 2, 0x00, 0x10, 6, 3),
+	PIN_FIELD_BASE(20, 20, 2, 0x00, 0x10, 9, 3),
+	PIN_FIELD_BASE(21, 21, 2, 0x00, 0x10, 18, 3),
+	PIN_FIELD_BASE(22, 22, 2, 0x00, 0x10, 21, 3),
+	PIN_FIELD_BASE(23, 23, 2, 0x00, 0x10, 0, 3),
+	PIN_FIELD_BASE(24, 24, 2, 0x00, 0x10, 27, 3),
+	PIN_FIELD_BASE(25, 25, 2, 0x00, 0x10, 24, 3),
+
+	PIN_FIELD_BASE(26, 26, 5, 0x00, 0x10, 0, 3),
+	PIN_FIELD_BASE(27, 27, 5, 0x00, 0x10, 12, 3),
+	PIN_FIELD_BASE(28, 28, 5, 0x00, 0x10, 9, 3),
+	PIN_FIELD_BASE(29, 29, 5, 0x00, 0x10, 3, 3),
+	PIN_FIELD_BASE(30, 30, 5, 0x00, 0x10, 6, 3),
+	PIN_FIELD_BASE(31, 31, 5, 0x00, 0x10, 15, 3),
+
+	PIN_FIELD_BASE(32, 32, 1, 0x00, 0x10, 9, 3),
+	PIN_FIELD_BASE(33, 33, 1, 0x00, 0x10, 12, 3),
+
+	PIN_FIELD_BASE(34, 34, 4, 0x00, 0x10, 15, 3),
+	PIN_FIELD_BASE(35, 35, 4, 0x00, 0x10, 21, 3),
+
+	PIN_FIELD_BASE(36, 36, 3, 0x00, 0x10, 6, 3),
+	PIN_FIELD_BASE(37, 37, 3, 0x00, 0x10, 9, 3),
+	PIN_FIELD_BASE(38, 38, 3, 0x00, 0x10, 0, 3),
+	PIN_FIELD_BASE(39, 39, 3, 0x00, 0x10, 3, 3),
+
+	PIN_FIELD_BASE(40, 40, 7, 0x00, 0x10, 3, 3),
+	PIN_FIELD_BASE(41, 41, 7, 0x00, 0x10, 0, 3),
+	PIN_FIELD_BASE(42, 42, 7, 0x00, 0x10, 27, 3),
+	PIN_FIELD_BASE(43, 43, 7, 0x00, 0x10, 21, 3),
+	PIN_FIELD_BASE(44, 44, 7, 0x00, 0x10, 24, 3),
+	PIN_FIELD_BASE(45, 45, 7, 0x00, 0x10, 9, 3),
+	PIN_FIELD_BASE(46, 46, 7, 0x00, 0x10, 12, 3),
+	PIN_FIELD_BASE(47, 47, 7, 0x00, 0x10, 15, 3),
+	PIN_FIELD_BASE(48, 48, 7, 0x00, 0x10, 18, 3),
+	PIN_FIELD_BASE(49, 49, 7, 0x00, 0x10, 6, 3),
+
+	PIN_FIELD_BASE(50, 50, 6, 0x00, 0x10, 0, 3),
+	PIN_FIELD_BASE(51, 51, 6, 0x00, 0x10, 6, 3),
+	PIN_FIELD_BASE(52, 52, 6, 0x00, 0x10, 9, 3),
+	PIN_FIELD_BASE(53, 53, 6, 0x00, 0x10, 12, 3),
+	PIN_FIELD_BASE(54, 54, 6, 0x00, 0x10, 15, 3),
+	PIN_FIELD_BASE(55, 55, 6, 0x00, 0x10, 18, 3),
+	PIN_FIELD_BASE(56, 56, 6, 0x00, 0x10, 3, 3),
+};
+
+static const struct mtk_pin_field_calc mt7981_pin_pupd_range[] = {
+	PIN_FIELD_BASE(0, 0, 1, 0x20, 0x10, 1, 1),
+	PIN_FIELD_BASE(1, 1, 1, 0x20, 0x10, 0, 1),
+	PIN_FIELD_BASE(2, 2, 5, 0x30, 0x10, 6, 1),
+	PIN_FIELD_BASE(3, 3, 4, 0x30, 0x10, 6, 1),
+	PIN_FIELD_BASE(4, 4, 4, 0x30, 0x10, 2, 1),
+	PIN_FIELD_BASE(5, 5, 4, 0x30, 0x10, 1, 1),
+	PIN_FIELD_BASE(6, 6, 4, 0x30, 0x10, 3, 1),
+	PIN_FIELD_BASE(7, 7, 4, 0x30, 0x10, 0, 1),
+	PIN_FIELD_BASE(8, 8, 4, 0x30, 0x10, 4, 1),
+	PIN_FIELD_BASE(9, 9, 4, 0x30, 0x10, 9, 1),
+
+	PIN_FIELD_BASE(10, 10, 5, 0x30, 0x10, 8, 1),
+	PIN_FIELD_BASE(11, 11, 5, 0x30, 0x10, 10, 1),
+	PIN_FIELD_BASE(12, 12, 5, 0x30, 0x10, 7, 1),
+	PIN_FIELD_BASE(13, 13, 5, 0x30, 0x10, 11, 1),
+
+	PIN_FIELD_BASE(14, 14, 4, 0x30, 0x10, 8, 1),
+
+	PIN_FIELD_BASE(15, 15, 2, 0x30, 0x10, 0, 1),
+	PIN_FIELD_BASE(16, 16, 2, 0x30, 0x10, 1, 1),
+	PIN_FIELD_BASE(17, 17, 2, 0x30, 0x10, 5, 1),
+	PIN_FIELD_BASE(18, 18, 2, 0x30, 0x10, 4, 1),
+	PIN_FIELD_BASE(19, 19, 2, 0x30, 0x10, 2, 1),
+	PIN_FIELD_BASE(20, 20, 2, 0x90, 0x10, 3, 1),
+	PIN_FIELD_BASE(21, 21, 2, 0x30, 0x10, 6, 1),
+	PIN_FIELD_BASE(22, 22, 2, 0x30, 0x10, 7, 1),
+	PIN_FIELD_BASE(23, 23, 2, 0x30, 0x10, 10, 1),
+	PIN_FIELD_BASE(24, 24, 2, 0x30, 0x10, 9, 1),
+	PIN_FIELD_BASE(25, 25, 2, 0x30, 0x10, 8, 1),
+
+	PIN_FIELD_BASE(26, 26, 5, 0x30, 0x10, 0, 1),
+	PIN_FIELD_BASE(27, 27, 5, 0x30, 0x10, 4, 1),
+	PIN_FIELD_BASE(28, 28, 5, 0x30, 0x10, 3, 1),
+	PIN_FIELD_BASE(29, 29, 5, 0x30, 0x10, 1, 1),
+	PIN_FIELD_BASE(30, 30, 5, 0x30, 0x10, 2, 1),
+	PIN_FIELD_BASE(31, 31, 5, 0x30, 0x10, 5, 1),
+
+	PIN_FIELD_BASE(32, 32, 1, 0x20, 0x10, 2, 1),
+	PIN_FIELD_BASE(33, 33, 1, 0x20, 0x10, 3, 1),
+
+	PIN_FIELD_BASE(34, 34, 4, 0x30, 0x10, 5, 1),
+	PIN_FIELD_BASE(35, 35, 4, 0x30, 0x10, 7, 1),
+
+	PIN_FIELD_BASE(36, 36, 3, 0x20, 0x10, 2, 1),
+	PIN_FIELD_BASE(37, 37, 3, 0x20, 0x10, 3, 1),
+	PIN_FIELD_BASE(38, 38, 3, 0x20, 0x10, 0, 1),
+	PIN_FIELD_BASE(39, 39, 3, 0x20, 0x10, 1, 1),
+};
+
+static const struct mtk_pin_field_calc mt7981_pin_r0_range[] = {
+	PIN_FIELD_BASE(0, 0, 1, 0x30, 0x10, 1, 1),
+	PIN_FIELD_BASE(1, 1, 1, 0x30, 0x10, 0, 1),
+	PIN_FIELD_BASE(2, 2, 5, 0x40, 0x10, 6, 1),
+	PIN_FIELD_BASE(3, 3, 4, 0x40, 0x10, 6, 1),
+	PIN_FIELD_BASE(4, 4, 4, 0x40, 0x10, 2, 1),
+	PIN_FIELD_BASE(5, 5, 4, 0x40, 0x10, 1, 1),
+	PIN_FIELD_BASE(6, 6, 4, 0x40, 0x10, 3, 1),
+	PIN_FIELD_BASE(7, 7, 4, 0x40, 0x10, 0, 1),
+	PIN_FIELD_BASE(8, 8, 4, 0x40, 0x10, 4, 1),
+	PIN_FIELD_BASE(9, 9, 4, 0x40, 0x10, 9, 1),
+
+	PIN_FIELD_BASE(10, 10, 5, 0x40, 0x10, 8, 1),
+	PIN_FIELD_BASE(11, 11, 5, 0x40, 0x10, 10, 1),
+	PIN_FIELD_BASE(12, 12, 5, 0x40, 0x10, 7, 1),
+	PIN_FIELD_BASE(13, 13, 5, 0x40, 0x10, 11, 1),
+
+	PIN_FIELD_BASE(14, 14, 4, 0x40, 0x10, 8, 1),
+
+	PIN_FIELD_BASE(15, 15, 2, 0x40, 0x10, 0, 1),
+	PIN_FIELD_BASE(16, 16, 2, 0x40, 0x10, 1, 1),
+	PIN_FIELD_BASE(17, 17, 2, 0x40, 0x10, 5, 1),
+	PIN_FIELD_BASE(18, 18, 2, 0x40, 0x10, 4, 1),
+	PIN_FIELD_BASE(19, 19, 2, 0x40, 0x10, 2, 1),
+	PIN_FIELD_BASE(20, 20, 2, 0x40, 0x10, 3, 1),
+	PIN_FIELD_BASE(21, 21, 2, 0x40, 0x10, 6, 1),
+	PIN_FIELD_BASE(22, 22, 2, 0x40, 0x10, 7, 1),
+	PIN_FIELD_BASE(23, 23, 2, 0x40, 0x10, 10, 1),
+	PIN_FIELD_BASE(24, 24, 2, 0x40, 0x10, 9, 1),
+	PIN_FIELD_BASE(25, 25, 2, 0x40, 0x10, 8, 1),
+
+	PIN_FIELD_BASE(26, 26, 5, 0x40, 0x10, 0, 1),
+	PIN_FIELD_BASE(27, 27, 5, 0x40, 0x10, 4, 1),
+	PIN_FIELD_BASE(28, 28, 5, 0x40, 0x10, 3, 1),
+	PIN_FIELD_BASE(29, 29, 5, 0x40, 0x10, 1, 1),
+	PIN_FIELD_BASE(30, 30, 5, 0x40, 0x10, 2, 1),
+	PIN_FIELD_BASE(31, 31, 5, 0x40, 0x10, 5, 1),
+
+	PIN_FIELD_BASE(32, 32, 1, 0x30, 0x10, 2, 1),
+	PIN_FIELD_BASE(33, 33, 1, 0x30, 0x10, 3, 1),
+
+	PIN_FIELD_BASE(34, 34, 4, 0x40, 0x10, 5, 1),
+	PIN_FIELD_BASE(35, 35, 4, 0x40, 0x10, 7, 1),
+
+	PIN_FIELD_BASE(36, 36, 3, 0x30, 0x10, 2, 1),
+	PIN_FIELD_BASE(37, 37, 3, 0x30, 0x10, 3, 1),
+	PIN_FIELD_BASE(38, 38, 3, 0x30, 0x10, 0, 1),
+	PIN_FIELD_BASE(39, 39, 3, 0x30, 0x10, 1, 1),
+};
+
+static const struct mtk_pin_field_calc mt7981_pin_r1_range[] = {
+	PIN_FIELD_BASE(0, 0, 1, 0x40, 0x10, 1, 1),
+	PIN_FIELD_BASE(1, 1, 1, 0x40, 0x10, 0, 1),
+	PIN_FIELD_BASE(2, 2, 5, 0x50, 0x10, 6, 1),
+	PIN_FIELD_BASE(3, 3, 4, 0x50, 0x10, 6, 1),
+	PIN_FIELD_BASE(4, 4, 4, 0x50, 0x10, 2, 1),
+	PIN_FIELD_BASE(5, 5, 4, 0x50, 0x10, 1, 1),
+	PIN_FIELD_BASE(6, 6, 4, 0x50, 0x10, 3, 1),
+	PIN_FIELD_BASE(7, 7, 4, 0x50, 0x10, 0, 1),
+	PIN_FIELD_BASE(8, 8, 4, 0x50, 0x10, 4, 1),
+	PIN_FIELD_BASE(9, 9, 4, 0x50, 0x10, 9, 1),
+
+	PIN_FIELD_BASE(10, 10, 5, 0x50, 0x10, 8, 1),
+	PIN_FIELD_BASE(11, 11, 5, 0x50, 0x10, 10, 1),
+	PIN_FIELD_BASE(12, 12, 5, 0x50, 0x10, 7, 1),
+	PIN_FIELD_BASE(13, 13, 5, 0x50, 0x10, 11, 1),
+
+	PIN_FIELD_BASE(14, 14, 4, 0x50, 0x10, 8, 1),
+
+	PIN_FIELD_BASE(15, 15, 2, 0x50, 0x10, 0, 1),
+	PIN_FIELD_BASE(16, 16, 2, 0x50, 0x10, 1, 1),
+	PIN_FIELD_BASE(17, 17, 2, 0x50, 0x10, 5, 1),
+	PIN_FIELD_BASE(18, 18, 2, 0x50, 0x10, 4, 1),
+	PIN_FIELD_BASE(19, 19, 2, 0x50, 0x10, 2, 1),
+	PIN_FIELD_BASE(20, 20, 2, 0x50, 0x10, 3, 1),
+	PIN_FIELD_BASE(21, 21, 2, 0x50, 0x10, 6, 1),
+	PIN_FIELD_BASE(22, 22, 2, 0x50, 0x10, 7, 1),
+	PIN_FIELD_BASE(23, 23, 2, 0x50, 0x10, 10, 1),
+	PIN_FIELD_BASE(24, 24, 2, 0x50, 0x10, 9, 1),
+	PIN_FIELD_BASE(25, 25, 2, 0x50, 0x10, 8, 1),
+
+	PIN_FIELD_BASE(26, 26, 5, 0x50, 0x10, 0, 1),
+	PIN_FIELD_BASE(27, 27, 5, 0x50, 0x10, 4, 1),
+	PIN_FIELD_BASE(28, 28, 5, 0x50, 0x10, 3, 1),
+	PIN_FIELD_BASE(29, 29, 5, 0x50, 0x10, 1, 1),
+	PIN_FIELD_BASE(30, 30, 5, 0x50, 0x10, 2, 1),
+	PIN_FIELD_BASE(31, 31, 5, 0x50, 0x10, 5, 1),
+
+	PIN_FIELD_BASE(32, 32, 1, 0x40, 0x10, 2, 1),
+	PIN_FIELD_BASE(33, 33, 1, 0x40, 0x10, 3, 1),
+
+	PIN_FIELD_BASE(34, 34, 4, 0x50, 0x10, 5, 1),
+	PIN_FIELD_BASE(35, 35, 4, 0x50, 0x10, 7, 1),
+
+	PIN_FIELD_BASE(36, 36, 3, 0x40, 0x10, 2, 1),
+	PIN_FIELD_BASE(37, 37, 3, 0x40, 0x10, 3, 1),
+	PIN_FIELD_BASE(38, 38, 3, 0x40, 0x10, 0, 1),
+	PIN_FIELD_BASE(39, 39, 3, 0x40, 0x10, 1, 1),
+};
+
+static const struct mtk_pin_reg_calc mt7981_reg_cals[] = {
+	[PINCTRL_PIN_REG_MODE] = MTK_RANGE(mt7981_pin_mode_range),
+	[PINCTRL_PIN_REG_DIR] = MTK_RANGE(mt7981_pin_dir_range),
+	[PINCTRL_PIN_REG_DI] = MTK_RANGE(mt7981_pin_di_range),
+	[PINCTRL_PIN_REG_DO] = MTK_RANGE(mt7981_pin_do_range),
+	[PINCTRL_PIN_REG_SMT] = MTK_RANGE(mt7981_pin_smt_range),
+	[PINCTRL_PIN_REG_IES] = MTK_RANGE(mt7981_pin_ies_range),
+	[PINCTRL_PIN_REG_PU] = MTK_RANGE(mt7981_pin_pu_range),
+	[PINCTRL_PIN_REG_PD] = MTK_RANGE(mt7981_pin_pd_range),
+	[PINCTRL_PIN_REG_DRV] = MTK_RANGE(mt7981_pin_drv_range),
+	[PINCTRL_PIN_REG_PUPD] = MTK_RANGE(mt7981_pin_pupd_range),
+	[PINCTRL_PIN_REG_R0] = MTK_RANGE(mt7981_pin_r0_range),
+	[PINCTRL_PIN_REG_R1] = MTK_RANGE(mt7981_pin_r1_range),
+};
+
+static const struct mtk_pin_desc mt7981_pins[] = {
+	MT7981_TYPE0_PIN(0, "GPIO_WPS"),
+	MT7981_TYPE0_PIN(1, "GPIO_RESET"),
+	MT7981_TYPE0_PIN(2, "SYS_WATCHDOG"),
+	MT7981_TYPE0_PIN(3, "PCIE_PERESET_N"),
+	MT7981_TYPE0_PIN(4, "JTAG_JTDO"),
+	MT7981_TYPE0_PIN(5, "JTAG_JTDI"),
+	MT7981_TYPE0_PIN(6, "JTAG_JTMS"),
+	MT7981_TYPE0_PIN(7, "JTAG_JTCLK"),
+	MT7981_TYPE0_PIN(8, "JTAG_JTRST_N"),
+	MT7981_TYPE0_PIN(9, "WO_JTAG_JTDO"),
+	MT7981_TYPE0_PIN(10, "WO_JTAG_JTDI"),
+	MT7981_TYPE0_PIN(11, "WO_JTAG_JTMS"),
+	MT7981_TYPE0_PIN(12, "WO_JTAG_JTCLK"),
+	MT7981_TYPE0_PIN(13, "WO_JTAG_JTRST_N"),
+	MT7981_TYPE0_PIN(14, "USB_VBUS"),
+	MT7981_TYPE0_PIN(15, "PWM0"),
+	MT7981_TYPE0_PIN(16, "SPI0_CLK"),
+	MT7981_TYPE0_PIN(17, "SPI0_MOSI"),
+	MT7981_TYPE0_PIN(18, "SPI0_MISO"),
+	MT7981_TYPE0_PIN(19, "SPI0_CS"),
+	MT7981_TYPE0_PIN(20, "SPI0_HOLD"),
+	MT7981_TYPE0_PIN(21, "SPI0_WP"),
+	MT7981_TYPE0_PIN(22, "SPI1_CLK"),
+	MT7981_TYPE0_PIN(23, "SPI1_MOSI"),
+	MT7981_TYPE0_PIN(24, "SPI1_MISO"),
+	MT7981_TYPE0_PIN(25, "SPI1_CS"),
+	MT7981_TYPE0_PIN(26, "SPI2_CLK"),
+	MT7981_TYPE0_PIN(27, "SPI2_MOSI"),
+	MT7981_TYPE0_PIN(28, "SPI2_MISO"),
+	MT7981_TYPE0_PIN(29, "SPI2_CS"),
+	MT7981_TYPE0_PIN(30, "SPI2_HOLD"),
+	MT7981_TYPE0_PIN(31, "SPI2_WP"),
+	MT7981_TYPE0_PIN(32, "UART0_RXD"),
+	MT7981_TYPE0_PIN(33, "UART0_TXD"),
+	MT7981_TYPE0_PIN(34, "PCIE_CLK_REQ"),
+	MT7981_TYPE0_PIN(35, "PCIE_WAKE_N"),
+	MT7981_TYPE0_PIN(36, "SMI_MDC"),
+	MT7981_TYPE0_PIN(37, "SMI_MDIO"),
+	MT7981_TYPE0_PIN(38, "GBE_INT"),
+	MT7981_TYPE0_PIN(39, "GBE_RESET"),
+	MT7981_TYPE1_PIN(40, "WF_DIG_RESETB"),
+	MT7981_TYPE1_PIN(41, "WF_CBA_RESETB"),
+	MT7981_TYPE1_PIN(42, "WF_XO_REQ"),
+	MT7981_TYPE1_PIN(43, "WF_TOP_CLK"),
+	MT7981_TYPE1_PIN(44, "WF_TOP_DATA"),
+	MT7981_TYPE1_PIN(45, "WF_HB1"),
+	MT7981_TYPE1_PIN(46, "WF_HB2"),
+	MT7981_TYPE1_PIN(47, "WF_HB3"),
+	MT7981_TYPE1_PIN(48, "WF_HB4"),
+	MT7981_TYPE1_PIN(49, "WF_HB0"),
+	MT7981_TYPE1_PIN(50, "WF_HB0_B"),
+	MT7981_TYPE1_PIN(51, "WF_HB5"),
+	MT7981_TYPE1_PIN(52, "WF_HB6"),
+	MT7981_TYPE1_PIN(53, "WF_HB7"),
+	MT7981_TYPE1_PIN(54, "WF_HB8"),
+	MT7981_TYPE1_PIN(55, "WF_HB9"),
+	MT7981_TYPE1_PIN(56, "WF_HB10"),
+};
+
+/* WA_AICE */
+static int mt7981_wa_aice1_pins[] = { 0, 1, };
+static int mt7981_wa_aice1_funcs[] = { 2, 2, };
+
+static int mt7981_wa_aice2_pins[] = { 0, 1, };
+static int mt7981_wa_aice2_funcs[] = { 3, 3, };
+
+static int mt7981_wa_aice3_pins[] = { 28, 29, };
+static int mt7981_wa_aice3_funcs[] = { 3, 3, };
+
+static int mt7981_wm_aice1_pins[] = { 9, 10, };
+static int mt7981_wm_aice1_funcs[] = { 2, 2, };
+
+static int mt7981_wm_aice2_pins[] = { 30, 31, };
+static int mt7981_wm_aice2_funcs[] = { 5, 5, };
+
+/* WM_UART */
+static int mt7981_wm_uart_0_pins[] = { 0, 1, };
+static int mt7981_wm_uart_0_funcs[] = { 5, 5, };
+
+static int mt7981_wm_uart_1_pins[] = { 20, 21, };
+static int mt7981_wm_uart_1_funcs[] = { 4, 4, };
+
+static int mt7981_wm_uart_2_pins[] = { 30, 31, };
+static int mt7981_wm_uart_2_funcs[] = { 3, 3, };
+
+/* DFD */
+static int mt7981_dfd_pins[] = { 0, 1, 4, 5, };
+static int mt7981_dfd_funcs[] = { 5, 5, 6, 6, };
+
+/* SYS_WATCHDOG */
+static int mt7981_watchdog_pins[] = { 2, };
+static int mt7981_watchdog_funcs[] = { 1, };
+
+static int mt7981_watchdog1_pins[] = { 13, };
+static int mt7981_watchdog1_funcs[] = { 5, };
+
+/* PCIE_PERESET_N */
+static int mt7981_pcie_pereset_pins[] = { 3, };
+static int mt7981_pcie_pereset_funcs[] = { 1, };
+
+/* JTAG */
+static int mt7981_jtag_pins[] = { 4, 5, 6, 7, 8, };
+static int mt7981_jtag_funcs[] = { 1, 1, 1, 1, 1, };
+
+/* WM_JTAG */
+static int mt7981_wm_jtag_0_pins[] = { 4, 5, 6, 7, 8, };
+static int mt7981_wm_jtag_0_funcs[] = { 2, 2, 2, 2, 2, };
+
+static int mt7981_wm_jtag_1_pins[] = { 20, 21, 22, 23, 24, };
+static int mt7981_wm_jtag_1_funcs[] = { 5, 5, 5, 5, 5, };
+
+/* WO0_JTAG */
+static int mt7981_wo0_jtag_0_pins[] = { 9, 10, 11, 12, 13, };
+static int mt7981_wo0_jtag_0_funcs[] = { 1, 1, 1, 1, 1, };
+
+static int mt7981_wo0_jtag_1_pins[] = { 25, 26, 27, 28, 29, };
+static int mt7981_wo0_jtag_1_funcs[] = { 5, 5, 5, 5, 5, };
+
+/* UART2 */
+static int mt7981_uart2_0_pins[] = { 4, 5, 6, 7, };
+static int mt7981_uart2_0_funcs[] = { 3, 3, 3, 3, };
+
+/* GBE_LED0 */
+static int mt7981_gbe_led0_pins[] = { 8, };
+static int mt7981_gbe_led0_funcs[] = { 3, };
+
+/* PTA_EXT */
+static int mt7981_pta_ext_0_pins[] = { 4, 5, 6, };
+static int mt7981_pta_ext_0_funcs[] = { 4, 4, 4, };
+
+static int mt7981_pta_ext_1_pins[] = { 22, 23, 24, };
+static int mt7981_pta_ext_1_funcs[] = { 4, 4, 4, };
+
+/* PWM2 */
+static int mt7981_pwm2_pins[] = { 7, };
+static int mt7981_pwm2_funcs[] = { 4, };
+
+/* NET_WO0_UART_TXD */
+static int mt7981_net_wo0_uart_txd_0_pins[] = { 8, };
+static int mt7981_net_wo0_uart_txd_0_funcs[] = { 4, };
+
+static int mt7981_net_wo0_uart_txd_1_pins[] = { 14, };
+static int mt7981_net_wo0_uart_txd_1_funcs[] = { 3, };
+
+static int mt7981_net_wo0_uart_txd_2_pins[] = { 15, };
+static int mt7981_net_wo0_uart_txd_2_funcs[] = { 4, };
+
+/* SPI1 */
+static int mt7981_spi1_0_pins[] = { 4, 5, 6, 7, };
+static int mt7981_spi1_0_funcs[] = { 5, 5, 5, 5, };
+
+/* I2C */
+static int mt7981_i2c0_0_pins[] = { 6, 7, };
+static int mt7981_i2c0_0_funcs[] = { 6, 6, };
+
+static int mt7981_i2c0_1_pins[] = { 30, 31, };
+static int mt7981_i2c0_1_funcs[] = { 4, 4, };
+
+static int mt7981_i2c0_2_pins[] = { 36, 37, };
+static int mt7981_i2c0_2_funcs[] = { 2, 2, };
+
+static int mt7981_u2_phy_i2c_pins[] = { 30, 31, };
+static int mt7981_u2_phy_i2c_funcs[] = { 6, 6, };
+
+static int mt7981_u3_phy_i2c_pins[] = { 32, 33, };
+static int mt7981_u3_phy_i2c_funcs[] = { 3, 3, };
+
+static int mt7981_sgmii1_phy_i2c_pins[] = { 32, 33, };
+static int mt7981_sgmii1_phy_i2c_funcs[] = { 2, 2, };
+
+static int mt7981_sgmii0_phy_i2c_pins[] = { 32, 33, };
+static int mt7981_sgmii0_phy_i2c_funcs[] = { 5, 5, };
+
+/* DFD_NTRST */
+static int mt7981_dfd_ntrst_pins[] = { 8, };
+static int mt7981_dfd_ntrst_funcs[] = { 6, };
+
+/* PWM0 */
+static int mt7981_pwm0_0_pins[] = { 13, };
+static int mt7981_pwm0_0_funcs[] = { 2, };
+
+static int mt7981_pwm0_1_pins[] = { 15, };
+static int mt7981_pwm0_1_funcs[] = { 1, };
+
+/* PWM1 */
+static int mt7981_pwm1_0_pins[] = { 14, };
+static int mt7981_pwm1_0_funcs[] = { 2, };
+
+static int mt7981_pwm1_1_pins[] = { 15, };
+static int mt7981_pwm1_1_funcs[] = { 3, };
+
+/* GBE_LED1 */
+static int mt7981_gbe_led1_pins[] = { 13, };
+static int mt7981_gbe_led1_funcs[] = { 3, };
+
+/* PCM */
+static int mt7981_pcm_pins[] = { 9, 10, 11, 12, 13, 25 };
+static int mt7981_pcm_funcs[] = { 4, 4, 4, 4, 4, 4, };
+
+/* UDI */
+static int mt7981_udi_pins[] = { 9, 10, 11, 12, 13, };
+static int mt7981_udi_funcs[] = { 6, 6, 6, 6, 6, };
+
+/* DRV_VBUS */
+static int mt7981_drv_vbus_pins[] = { 14, };
+static int mt7981_drv_vbus_funcs[] = { 1, };
+
+/* EMMC */
+static int mt7981_emmc_45_pins[] = { 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, };
+static int mt7981_emmc_45_funcs[] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, };
+
+/* SNFI */
+static int mt7981_snfi_pins[] = { 16, 17, 18, 19, 20, 21, };
+static int mt7981_snfi_funcs[] = { 3, 3, 3, 3, 3, 3, };
+
+/* SPI0 */
+static int mt7981_spi0_pins[] = { 16, 17, 18, 19, };
+static int mt7981_spi0_funcs[] = { 1, 1, 1, 1, };
+
+/* SPI0 */
+static int mt7981_spi0_wp_hold_pins[] = { 20, 21, };
+static int mt7981_spi0_wp_hold_funcs[] = { 1, 1, };
+
+/* SPI1 */
+static int mt7981_spi1_1_pins[] = { 22, 23, 24, 25, };
+static int mt7981_spi1_1_funcs[] = { 1, 1, 1, 1, };
+
+/* SPI2 */
+static int mt7981_spi2_pins[] = { 26, 27, 28, 29, };
+static int mt7981_spi2_funcs[] = { 1, 1, 1, 1, };
+
+/* SPI2 */
+static int mt7981_spi2_wp_hold_pins[] = { 30, 31, };
+static int mt7981_spi2_wp_hold_funcs[] = { 1, 1, };
+
+/* UART1 */
+static int mt7981_uart1_0_pins[] = { 16, 17, 18, 19, };
+static int mt7981_uart1_0_funcs[] = { 4, 4, 4, 4, };
+
+static int mt7981_uart1_1_pins[] = { 26, 27, 28, 29, };
+static int mt7981_uart1_1_funcs[] = { 2, 2, 2, 2, };
+
+/* UART2 */
+static int mt7981_uart2_1_pins[] = { 22, 23, 24, 25, };
+static int mt7981_uart2_1_funcs[] = { 3, 3, 3, 3, };
+
+/* UART0 */
+static int mt7981_uart0_pins[] = { 32, 33, };
+static int mt7981_uart0_funcs[] = { 1, 1, };
+
+/* PCIE_CLK_REQ */
+static int mt7981_pcie_clk_pins[] = { 34, };
+static int mt7981_pcie_clk_funcs[] = { 2, };
+
+/* PCIE_WAKE_N */
+static int mt7981_pcie_wake_pins[] = { 35, };
+static int mt7981_pcie_wake_funcs[] = { 2, };
+
+/* MDC_MDIO */
+static int mt7981_smi_mdc_mdio_pins[] = { 36, 37, };
+static int mt7981_smi_mdc_mdio_funcs[] = { 1, 1, };
+
+static int mt7981_gbe_ext_mdc_mdio_pins[] = { 36, 37, };
+static int mt7981_gbe_ext_mdc_mdio_funcs[] = { 3, 3, };
+
+/* WF0_MODE1 */
+static int mt7981_wf0_mode1_pins[] = { 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+				       50, 51, 52, 53, 54, 55, 56 };
+static int mt7981_wf0_mode1_funcs[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+					1, 1, 1, 1 };
+
+/* WF0_MODE3 */
+static int mt7981_wf0_mode3_pins[] = { 45, 46, 47, 48, 49, 51 };
+static int mt7981_wf0_mode3_funcs[] = { 2, 2, 2, 2, 2, 2 };
+
+/* WF2G_LED */
+static int mt7981_wf2g_led0_pins[] = { 30, };
+static int mt7981_wf2g_led0_funcs[] = { 2, };
+
+static int mt7981_wf2g_led1_pins[] = { 34, };
+static int mt7981_wf2g_led1_funcs[] = { 1, };
+
+/* WF5G_LED */
+static int mt7981_wf5g_led0_pins[] = { 31, };
+static int mt7981_wf5g_led0_funcs[] = { 2, };
+
+static int mt7981_wf5g_led1_pins[] = { 35, };
+static int mt7981_wf5g_led1_funcs[] = { 1, };
+
+/* MT7531_INT */
+static int mt7981_mt7531_int_pins[] = { 38, };
+static int mt7981_mt7531_int_funcs[] = { 1, };
+
+/* ANT_SEL */
+static int mt7981_ant_sel_pins[] = { 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 34, 35 };
+static int mt7981_ant_sel_funcs[] = { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 };
+
+static const struct mtk_group_desc mt7981_groups[] = {
+	/* @GPIO(0,1): WA_AICE(2) */
+	PINCTRL_PIN_GROUP("wa_aice1", mt7981_wa_aice1),
+	/* @GPIO(0,1): WA_AICE(3) */
+	PINCTRL_PIN_GROUP("wa_aice2", mt7981_wa_aice2),
+	/* @GPIO(0,1): WM_UART(5) */
+	PINCTRL_PIN_GROUP("wm_uart_0", mt7981_wm_uart_0),
+	/* @GPIO(0,1,4,5): DFD(6) */
+	PINCTRL_PIN_GROUP("dfd", mt7981_dfd),
+	/* @GPIO(2): SYS_WATCHDOG(1) */
+	PINCTRL_PIN_GROUP("watchdog", mt7981_watchdog),
+	/* @GPIO(3): PCIE_PERESET_N(1) */
+	PINCTRL_PIN_GROUP("pcie_pereset", mt7981_pcie_pereset),
+	/* @GPIO(4,8) JTAG(1) */
+	PINCTRL_PIN_GROUP("jtag", mt7981_jtag),
+	/* @GPIO(4,8) WM_JTAG(2) */
+	PINCTRL_PIN_GROUP("wm_jtag_0", mt7981_wm_jtag_0),
+	/* @GPIO(9,13) WO0_JTAG(1) */
+	PINCTRL_PIN_GROUP("wo0_jtag_0", mt7981_wo0_jtag_0),
+	/* @GPIO(4,7) WM_JTAG(3) */
+	PINCTRL_PIN_GROUP("uart2_0", mt7981_uart2_0),
+	/* @GPIO(8) GBE_LED0(3) */
+	PINCTRL_PIN_GROUP("gbe_led0", mt7981_gbe_led0),
+	/* @GPIO(4,6) PTA_EXT(4) */
+	PINCTRL_PIN_GROUP("pta_ext_0", mt7981_pta_ext_0),
+	/* @GPIO(7) PWM2(4) */
+	PINCTRL_PIN_GROUP("pwm2", mt7981_pwm2),
+	/* @GPIO(8) NET_WO0_UART_TXD(4) */
+	PINCTRL_PIN_GROUP("net_wo0_uart_txd_0", mt7981_net_wo0_uart_txd_0),
+	/* @GPIO(4,7) SPI1(5) */
+	PINCTRL_PIN_GROUP("spi1_0", mt7981_spi1_0),
+	/* @GPIO(6,7) I2C(5) */
+	PINCTRL_PIN_GROUP("i2c0_0", mt7981_i2c0_0),
+	/* @GPIO(8): DFD_NTRST(6) */
+	PINCTRL_PIN_GROUP("dfd_ntrst", mt7981_dfd_ntrst),
+	/* @GPIO(9,10): WM_AICE(2) */
+	PINCTRL_PIN_GROUP("wm_aice1", mt7981_wm_aice1),
+	/* @GPIO(13): PWM0(2) */
+	PINCTRL_PIN_GROUP("pwm0_0", mt7981_pwm0_0),
+	/* @GPIO(15): PWM0(1) */
+	PINCTRL_PIN_GROUP("pwm0_1", mt7981_pwm0_1),
+	/* @GPIO(14): PWM1(2) */
+	PINCTRL_PIN_GROUP("pwm1_0", mt7981_pwm1_0),
+	/* @GPIO(15): PWM1(3) */
+	PINCTRL_PIN_GROUP("pwm1_1", mt7981_pwm1_1),
+	/* @GPIO(14) NET_WO0_UART_TXD(3) */
+	PINCTRL_PIN_GROUP("net_wo0_uart_txd_1", mt7981_net_wo0_uart_txd_1),
+	/* @GPIO(15) NET_WO0_UART_TXD(4) */
+	PINCTRL_PIN_GROUP("net_wo0_uart_txd_2", mt7981_net_wo0_uart_txd_2),
+	/* @GPIO(13) GBE_LED0(3) */
+	PINCTRL_PIN_GROUP("gbe_led1", mt7981_gbe_led1),
+	/* @GPIO(9,13) PCM(4) */
+	PINCTRL_PIN_GROUP("pcm", mt7981_pcm),
+	/* @GPIO(13): SYS_WATCHDOG1(5) */
+	PINCTRL_PIN_GROUP("watchdog1", mt7981_watchdog1),
+	/* @GPIO(9,13) UDI(4) */
+	PINCTRL_PIN_GROUP("udi", mt7981_udi),
+	/* @GPIO(14) DRV_VBUS(1) */
+	PINCTRL_PIN_GROUP("drv_vbus", mt7981_drv_vbus),
+	/* @GPIO(15,25): EMMC(2) */
+	PINCTRL_PIN_GROUP("emmc_45", mt7981_emmc_45),
+	/* @GPIO(16,21): SNFI(3) */
+	PINCTRL_PIN_GROUP("snfi", mt7981_snfi),
+	/* @GPIO(16,19): SPI0(1) */
+	PINCTRL_PIN_GROUP("spi0", mt7981_spi0),
+	/* @GPIO(20,21): SPI0(1) */
+	PINCTRL_PIN_GROUP("spi0_wp_hold", mt7981_spi0_wp_hold),
+	/* @GPIO(22,25) SPI1(1) */
+	PINCTRL_PIN_GROUP("spi1_1", mt7981_spi1_1),
+	/* @GPIO(26,29): SPI2(1) */
+	PINCTRL_PIN_GROUP("spi2", mt7981_spi2),
+	/* @GPIO(30,31): SPI2(1) */
+	PINCTRL_PIN_GROUP("spi2_wp_hold", mt7981_spi2_wp_hold),
+	/* @GPIO(16,19): UART1(4) */
+	PINCTRL_PIN_GROUP("uart1_0", mt7981_uart1_0),
+	/* @GPIO(26,29): UART1(2) */
+	PINCTRL_PIN_GROUP("uart1_1", mt7981_uart1_1),
+	/* @GPIO(22,25): UART2(3) */
+	PINCTRL_PIN_GROUP("uart2_0", mt7981_uart2_1),
+	/* @GPIO(22,24) PTA_EXT(4) */
+	PINCTRL_PIN_GROUP("pta_ext_1", mt7981_pta_ext_1),
+	/* @GPIO(20,21): WM_UART(4) */
+	PINCTRL_PIN_GROUP("wm_aurt_1", mt7981_wm_uart_1),
+	/* @GPIO(30,31): WM_UART(3) */
+	PINCTRL_PIN_GROUP("wm_aurt_2", mt7981_wm_uart_2),
+	/* @GPIO(20,24) WM_JTAG(5) */
+	PINCTRL_PIN_GROUP("wm_jtag_1", mt7981_wm_jtag_1),
+	/* @GPIO(25,29) WO0_JTAG(5) */
+	PINCTRL_PIN_GROUP("wo0_jtag_1", mt7981_wo0_jtag_1),
+	/* @GPIO(28,29): WA_AICE(3) */
+	PINCTRL_PIN_GROUP("wa_aice3", mt7981_wa_aice3),
+	/* @GPIO(30,31): WM_AICE(5) */
+	PINCTRL_PIN_GROUP("wm_aice2", mt7981_wm_aice2),
+	/* @GPIO(30,31): I2C(4) */
+	PINCTRL_PIN_GROUP("i2c0_1", mt7981_i2c0_1),
+	/* @GPIO(30,31): I2C(6) */
+	PINCTRL_PIN_GROUP("u2_phy_i2c", mt7981_u2_phy_i2c),
+	/* @GPIO(32,33): I2C(1) */
+	PINCTRL_PIN_GROUP("uart0", mt7981_uart0),
+	/* @GPIO(32,33): I2C(2) */
+	PINCTRL_PIN_GROUP("sgmii1_phy_i2c", mt7981_sgmii1_phy_i2c),
+	/* @GPIO(32,33): I2C(3) */
+	PINCTRL_PIN_GROUP("u3_phy_i2c", mt7981_u3_phy_i2c),
+	/* @GPIO(32,33): I2C(5) */
+	PINCTRL_PIN_GROUP("sgmii0_phy_i2c", mt7981_sgmii0_phy_i2c),
+	/* @GPIO(34): PCIE_CLK_REQ(2) */
+	PINCTRL_PIN_GROUP("pcie_clk", mt7981_pcie_clk),
+	/* @GPIO(35): PCIE_WAKE_N(2) */
+	PINCTRL_PIN_GROUP("pcie_wake", mt7981_pcie_wake),
+	/* @GPIO(36,37): I2C(2) */
+	PINCTRL_PIN_GROUP("i2c0_2", mt7981_i2c0_2),
+	/* @GPIO(36,37): MDC_MDIO(1) */
+	PINCTRL_PIN_GROUP("smi_mdc_mdio", mt7981_smi_mdc_mdio),
+	/* @GPIO(36,37): MDC_MDIO(3) */
+	PINCTRL_PIN_GROUP("gbe_ext_mdc_mdio", mt7981_gbe_ext_mdc_mdio),
+	/* @GPIO(40,56): WF0_MODE1(1) */
+	PINCTRL_PIN_GROUP("wf0_mode1", mt7981_wf0_mode1),
+	/* @GPIO(45,46,47,48,49,51): WF0_MODE3(3) */
+	PINCTRL_PIN_GROUP("wf0_mode3", mt7981_wf0_mode3),
+	/* @GPIO(30): WF2G_LED(2) */
+	PINCTRL_PIN_GROUP("wf2g_led0", mt7981_wf2g_led0),
+	/* @GPIO(34): WF2G_LED(1) */
+	PINCTRL_PIN_GROUP("wf2g_led1", mt7981_wf2g_led1),
+	/* @GPIO(31): WF5G_LED(2) */
+	PINCTRL_PIN_GROUP("wf5g_led0", mt7981_wf5g_led0),
+	/* @GPIO(35): WF5G_LED(1) */
+	PINCTRL_PIN_GROUP("wf5g_led1", mt7981_wf5g_led1),
+	/* @GPIO(38): MT7531_INT(1) */
+	PINCTRL_PIN_GROUP("mt7531_int", mt7981_mt7531_int),
+	/* @GPIO(14,15,26,17,18,19,20,21,22,23,24,25,34,35): ANT_SEL(1) */
+	PINCTRL_PIN_GROUP("ant_sel", mt7981_ant_sel),
+};
+
+static const struct mtk_io_type_desc mt7981_io_type_desc[] = {
+	[IO_TYPE_GRP0] = {
+		.name = "18OD33",
+		.bias_set = mtk_pinconf_bias_set_pupd_r1_r0,
+		.drive_set = mtk_pinconf_drive_set_v1,
+		.input_enable = mtk_pinconf_input_enable_v1,
+	},
+	[IO_TYPE_GRP1] = {
+		.name = "18A01",
+		.bias_set = mtk_pinconf_bias_set_pu_pd,
+		.drive_set = mtk_pinconf_drive_set_v1,
+		.input_enable = mtk_pinconf_input_enable_v1,
+	},
+};
+
+/* Joint those groups owning the same capability in user point of view which
+ * allows that people tend to use through the device tree.
+ */
+static const char *const mt7981_wa_aice_groups[] = { "wa_aice1", "wa_aice2",
+	"wm_aice1_1", "wa_aice3", "wm_aice1_2", };
+static const char *const mt7981_uart_groups[] = { "wm_uart_0", "uart2_0",
+	"net_wo0_uart_txd_0", "net_wo0_uart_txd_1", "net_wo0_uart_txd_2",
+	"uart1_0", "uart1_1", "uart2_0", "wm_aurt_1", "wm_aurt_2", "uart0", };
+static const char *const mt7981_dfd_groups[] = { "dfd", "dfd_ntrst", };
+static const char *const mt7981_wdt_groups[] = { "watchdog", "watchdog1", };
+static const char *const mt7981_pcie_groups[] = { "pcie_pereset", "pcie_clk",
+	"pcie_wake", };
+static const char *const mt7981_jtag_groups[] = { "jtag", "wm_jtag_0",
+	"wo0_jtag_0", "wo0_jtag_1", "wm_jtag_1", };
+static const char *const mt7981_led_groups[] = { "gbe_led0", "gbe_led1",
+	"wf2g_led0", "wf2g_led1", "wf5g_led0", "wf5g_led1", };
+static const char *const mt7981_pta_groups[] = { "pta_ext_0", "pta_ext_1", };
+static const char *const mt7981_pwm_groups[] = { "pwm2", "pwm0_0", "pwm0_1",
+	"pwm1_0", "pwm1_1", };
+static const char *const mt7981_spi_groups[] = { "spi1_0", "spi0",
+	"spi0_wp_hold", "spi1_1", "spi2", "spi2_wp_hold", };
+static const char *const mt7981_i2c_groups[] = { "i2c0_0", "i2c0_1",
+	"u2_phy_i2c", "sgmii1_phy_i2c", "u3_phy_i2c", "sgmii0_phy_i2c",
+	"i2c0_2", };
+static const char *const mt7981_pcm_groups[] = { "pcm", };
+static const char *const mt7981_udi_groups[] = { "udi", };
+static const char *const mt7981_usb_groups[] = { "drv_vbus", };
+static const char *const mt7981_flash_groups[] = { "emmc_45", "snfi", };
+static const char *const mt7981_ethernet_groups[] = { "smi_mdc_mdio",
+	"gbe_ext_mdc_mdio", "wf0_mode1", "wf0_mode3", "mt7531_int", };
+static const char *const mt7981_ant_groups[] = { "ant_sel", };
+
+static const struct mtk_function_desc mt7981_functions[] = {
+	{"wa_aice", mt7981_wa_aice_groups, ARRAY_SIZE(mt7981_wa_aice_groups)},
+	{"dfd", mt7981_dfd_groups, ARRAY_SIZE(mt7981_dfd_groups)},
+	{"jtag", mt7981_jtag_groups, ARRAY_SIZE(mt7981_jtag_groups)},
+	{"pta", mt7981_pta_groups, ARRAY_SIZE(mt7981_pta_groups)},
+	{"pcm", mt7981_pcm_groups, ARRAY_SIZE(mt7981_pcm_groups)},
+	{"udi", mt7981_udi_groups, ARRAY_SIZE(mt7981_udi_groups)},
+	{"usb", mt7981_usb_groups, ARRAY_SIZE(mt7981_usb_groups)},
+	{"ant", mt7981_ant_groups, ARRAY_SIZE(mt7981_ant_groups)},
+	{"eth", mt7981_ethernet_groups, ARRAY_SIZE(mt7981_ethernet_groups)},
+	{"i2c", mt7981_i2c_groups, ARRAY_SIZE(mt7981_i2c_groups)},
+	{"led", mt7981_led_groups, ARRAY_SIZE(mt7981_led_groups)},
+	{"pwm", mt7981_pwm_groups, ARRAY_SIZE(mt7981_pwm_groups)},
+	{"spi", mt7981_spi_groups, ARRAY_SIZE(mt7981_spi_groups)},
+	{"uart", mt7981_uart_groups, ARRAY_SIZE(mt7981_uart_groups)},
+	{"watchdog", mt7981_wdt_groups, ARRAY_SIZE(mt7981_wdt_groups)},
+	{"flash", mt7981_flash_groups, ARRAY_SIZE(mt7981_flash_groups)},
+	{"pcie", mt7981_pcie_groups, ARRAY_SIZE(mt7981_pcie_groups)},
+};
+
+static const char *const mt7981_pinctrl_register_base_names[] = {
+	"gpio_base", "iocfg_rt_base", "iocfg_rm_base", "iocfg_rb_base",
+	"iocfg_lb_base", "iocfg_bl_base", "iocfg_tm_base", "iocfg_tl_base",
+};
+
+static struct mtk_pinctrl_soc mt7981_data = {
+	.name = "mt7981_pinctrl",
+	.reg_cal = mt7981_reg_cals,
+	.pins = mt7981_pins,
+	.npins = ARRAY_SIZE(mt7981_pins),
+	.grps = mt7981_groups,
+	.ngrps = ARRAY_SIZE(mt7981_groups),
+	.funcs = mt7981_functions,
+	.nfuncs = ARRAY_SIZE(mt7981_functions),
+	.io_type = mt7981_io_type_desc,
+	.ntype = ARRAY_SIZE(mt7981_io_type_desc),
+	.gpio_mode = 0,
+	.base_names = mt7981_pinctrl_register_base_names,
+	.nbase_names = ARRAY_SIZE(mt7981_pinctrl_register_base_names),
+	.base_calc = 1,
+};
+
+static int mtk_pinctrl_mt7981_probe(struct udevice *dev)
+{
+	return mtk_pinctrl_common_probe(dev, &mt7981_data);
+}
+
+static const struct udevice_id mt7981_pctrl_match[] = {
+	{.compatible = "mediatek,mt7981-pinctrl"},
+	{ /* sentinel */ }
+};
+
+U_BOOT_DRIVER(mt7981_pinctrl) = {
+	.name = "mt7981_pinctrl",
+	.id = UCLASS_PINCTRL,
+	.of_match = mt7981_pctrl_match,
+	.ops = &mtk_pinctrl_ops,
+	.probe = mtk_pinctrl_mt7981_probe,
+	.priv_auto = sizeof(struct mtk_pinctrl_priv),
+};
-- 
2.17.1


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

* [PATCH v2 21/32] pinctrl: mediatek: add pinctrl driver for MT7986 SoC
  2022-08-31 11:00 [PATCH v2 00/32] Add support for MediaTek MT7981/MT7986 SoCs - v2 Weijie Gao
                   ` (19 preceding siblings ...)
  2022-08-31 11:04 ` [PATCH v2 20/32] pinctrl: mediatek: add pinctrl driver for MT7981 SoC Weijie Gao
@ 2022-08-31 11:04 ` Weijie Gao
  2022-09-01  0:26   ` Daniel Golle
  2022-08-31 11:04 ` [PATCH v2 22/32] clk: mediatek: add CLK_BYPASS_XTAL flag to allow bypassing searching clock parent of xtal clock Weijie Gao
                   ` (10 subsequent siblings)
  31 siblings, 1 reply; 60+ messages in thread
From: Weijie Gao @ 2022-08-31 11:04 UTC (permalink / raw)
  To: u-boot; +Cc: GSS_MTK_Uboot_upstream, Weijie Gao

This patch adds pinctrl and gpio support for MT7986 SoC

Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
---
v2 changes: none
---
 drivers/pinctrl/mediatek/Kconfig          |   4 +
 drivers/pinctrl/mediatek/Makefile         |   1 +
 drivers/pinctrl/mediatek/pinctrl-mt7986.c | 775 ++++++++++++++++++++++
 3 files changed, 780 insertions(+)
 create mode 100644 drivers/pinctrl/mediatek/pinctrl-mt7986.c

diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig
index aceec9277d..27e8998e59 100644
--- a/drivers/pinctrl/mediatek/Kconfig
+++ b/drivers/pinctrl/mediatek/Kconfig
@@ -20,6 +20,10 @@ config PINCTRL_MT7981
 	bool "MT7981 SoC pinctrl driver"
 	select PINCTRL_MTK
 
+config PINCTRL_MT7986
+	bool "MT7986 SoC pinctrl driver"
+	select PINCTRL_MTK
+
 config PINCTRL_MT8512
 	bool "MT8512 SoC pinctrl driver"
 	select PINCTRL_MTK
diff --git a/drivers/pinctrl/mediatek/Makefile b/drivers/pinctrl/mediatek/Makefile
index 1879d7ae2a..6e733759f5 100644
--- a/drivers/pinctrl/mediatek/Makefile
+++ b/drivers/pinctrl/mediatek/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_PINCTRL_MT7622) += pinctrl-mt7622.o
 obj-$(CONFIG_PINCTRL_MT7623) += pinctrl-mt7623.o
 obj-$(CONFIG_PINCTRL_MT7629) += pinctrl-mt7629.o
 obj-$(CONFIG_PINCTRL_MT7981) += pinctrl-mt7981.o
+obj-$(CONFIG_PINCTRL_MT7986) += pinctrl-mt7986.o
 obj-$(CONFIG_PINCTRL_MT8512) += pinctrl-mt8512.o
 obj-$(CONFIG_PINCTRL_MT8516) += pinctrl-mt8516.o
 obj-$(CONFIG_PINCTRL_MT8518) += pinctrl-mt8518.o
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt7986.c b/drivers/pinctrl/mediatek/pinctrl-mt7986.c
new file mode 100644
index 0000000000..449e5adcd9
--- /dev/null
+++ b/drivers/pinctrl/mediatek/pinctrl-mt7986.c
@@ -0,0 +1,775 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * The MT7986 driver based on Linux generic pinctrl binding.
+ *
+ * Copyright (C) 2022 MediaTek Inc.
+ * Author: Sam Shih <sam.shih@mediatek.com>
+ */
+
+#include <dm.h>
+#include "pinctrl-mtk-common.h"
+
+#define MT7986_TYPE0_PIN(_number, _name)	\
+	MTK_TYPED_PIN(_number, _name, DRV_GRP4, IO_TYPE_GRP0)
+
+#define MT7986_TYPE1_PIN(_number, _name)	\
+	MTK_TYPED_PIN(_number, _name, DRV_GRP4, IO_TYPE_GRP1)
+
+#define PIN_FIELD_GPIO(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit, _x_bits)	\
+	PIN_FIELD_BASE_CALC(_s_pin, _e_pin, GPIO_BASE, _s_addr, _x_addrs,	\
+			    _s_bit, _x_bits, 32, 0)
+
+#define PIN_FIELD_BASE(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit,	\
+		       _x_bits)							\
+	PIN_FIELD_BASE_CALC(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit,	\
+	_x_bits, 32, 0)
+
+/**
+ * enum - Locking variants of the iocfg bases
+ *
+ * MT7986 have multiple bases to program pin configuration listed as the below:
+ * iocfg_rt:0x11c30000, iocfg_rb:0x11c40000, iocfg_lt:0x11e20000,
+ * iocfg_lb:0x11e30000, iocfg_tr:0x11f00000, iocfg_tl:0x11f10000,
+ * _i_based could be used to indicate what base the pin should be mapped into.
+ *
+ * Each iocfg register base control different group of pads on the SoC
+ *
+ *
+ *  chip carrier
+ *
+ *      A  B  C  D  E  F  G  H
+ *    +------------------------+
+ *  8 | o  o  o  o  o  o  o  o |
+ *  7 | o  o  o  o  o  o  o  o |
+ *  6 | o  o  o  o  o  o  o  o |
+ *  5 | o  o  o  o  o  o  o  o |
+ *  4 | o  o  o  o  o  o  o  o |
+ *  3 | o  o  o  o  o  o  o  o |
+ *  2 | o  o  o  o  o  o  o  o |
+ *  1 | o  o  o  o  o  o  o  o |
+ *    +------------------------+
+ *
+ *  inside Chip carrier
+ *
+ *      A  B  C  D  E  F  G  H
+ *    +------------------------+
+ *  8 |                        |
+ *  7 |        TL  TR          |
+ *  6 |      +---------+       |
+ *  5 |   LT |         | RT    |
+ *  4 |      |         |       |
+ *  3 |   LB |         | RB    |
+ *  2 |      +---------+       |
+ *  1 |                        |
+ *    +------------------------+
+ *
+ */
+
+enum {
+	GPIO_BASE,
+	IOCFG_RT_BASE,
+	IOCFG_RB_BASE,
+	IOCFG_LT_BASE,
+	IOCFG_LB_BASE,
+	IOCFG_TR_BASE,
+	IOCFG_TL_BASE,
+};
+
+static const char *const mt7986_pinctrl_register_base_names[] = {
+	"gpio", "iocfg_rt", "iocfg_rb", "iocfg_lt", "iocfg_lb", "iocfg_tr",
+	"iocfg_tl",
+};
+
+static const struct mtk_pin_field_calc mt7986_pin_mode_range[] = {
+	PIN_FIELD_GPIO(0, 100, 0x300, 0x10, 0, 4),
+};
+
+static const struct mtk_pin_field_calc mt7986_pin_dir_range[] = {
+	PIN_FIELD_GPIO(0, 100, 0x0, 0x10, 0, 1),
+};
+
+static const struct mtk_pin_field_calc mt7986_pin_di_range[] = {
+	PIN_FIELD_GPIO(0, 100, 0x200, 0x10, 0, 1),
+};
+
+static const struct mtk_pin_field_calc mt7986_pin_do_range[] = {
+	PIN_FIELD_GPIO(0, 100, 0x100, 0x10, 0, 1),
+};
+
+static const struct mtk_pin_field_calc mt7986_pin_ies_range[] = {
+	PIN_FIELD_BASE(0, 0, IOCFG_RB_BASE, 0x40, 0x10, 17, 1),
+	PIN_FIELD_BASE(1, 2, IOCFG_LT_BASE, 0x20, 0x10, 10, 1),
+	PIN_FIELD_BASE(3, 4, IOCFG_LB_BASE, 0x20, 0x10, 0, 1),
+	PIN_FIELD_BASE(5, 6, IOCFG_RB_BASE, 0x40, 0x10, 0, 1),
+	PIN_FIELD_BASE(7, 10, IOCFG_LT_BASE, 0x20, 0x10, 0, 1),
+	PIN_FIELD_BASE(11, 14, IOCFG_RB_BASE, 0x40, 0x10, 8, 1),
+	PIN_FIELD_BASE(15, 20, IOCFG_RB_BASE, 0x40, 0x10, 2, 1),
+	PIN_FIELD_BASE(21, 23, IOCFG_RT_BASE, 0x30, 0x10, 12, 1),
+	PIN_FIELD_BASE(24, 24, IOCFG_RT_BASE, 0x30, 0x10, 18, 1),
+	PIN_FIELD_BASE(25, 25, IOCFG_RT_BASE, 0x30, 0x10, 17, 1),
+	PIN_FIELD_BASE(26, 27, IOCFG_RT_BASE, 0x30, 0x10, 15, 1),
+	PIN_FIELD_BASE(28, 29, IOCFG_RT_BASE, 0x30, 0x10, 19, 1),
+	PIN_FIELD_BASE(30, 30, IOCFG_RT_BASE, 0x30, 0x10, 23, 1),
+	PIN_FIELD_BASE(31, 31, IOCFG_RT_BASE, 0x30, 0x10, 22, 1),
+	PIN_FIELD_BASE(32, 32, IOCFG_RT_BASE, 0x30, 0x10, 21, 1),
+	PIN_FIELD_BASE(33, 33, IOCFG_LT_BASE, 0x20, 0x10, 4, 1),
+	PIN_FIELD_BASE(34, 34, IOCFG_LT_BASE, 0x20, 0x10, 8, 1),
+	PIN_FIELD_BASE(35, 35, IOCFG_LT_BASE, 0x20, 0x10, 7, 1),
+	PIN_FIELD_BASE(36, 37, IOCFG_LT_BASE, 0x20, 0x10, 5, 1),
+	PIN_FIELD_BASE(38, 38, IOCFG_LT_BASE, 0x20, 0x10, 9, 1),
+	PIN_FIELD_BASE(39, 40, IOCFG_RB_BASE, 0x40, 0x10, 18, 1),
+	PIN_FIELD_BASE(41, 41, IOCFG_RB_BASE, 0x40, 0x10, 12, 1),
+	PIN_FIELD_BASE(42, 43, IOCFG_RB_BASE, 0x40, 0x10, 22, 1),
+	PIN_FIELD_BASE(44, 45, IOCFG_RB_BASE, 0x40, 0x10, 20, 1),
+	PIN_FIELD_BASE(46, 47, IOCFG_RB_BASE, 0x40, 0x10, 26, 1),
+	PIN_FIELD_BASE(48, 49, IOCFG_RB_BASE, 0x40, 0x10, 24, 1),
+	PIN_FIELD_BASE(50, 57, IOCFG_RT_BASE, 0x30, 0x10, 2, 1),
+	PIN_FIELD_BASE(58, 58, IOCFG_RT_BASE, 0x30, 0x10, 1, 1),
+	PIN_FIELD_BASE(59, 59, IOCFG_RT_BASE, 0x30, 0x10, 0, 1),
+	PIN_FIELD_BASE(60, 61, IOCFG_RT_BASE, 0x30, 0x10, 10, 1),
+	PIN_FIELD_BASE(62, 62, IOCFG_RB_BASE, 0x40, 0x10, 15, 1),
+	PIN_FIELD_BASE(63, 63, IOCFG_RB_BASE, 0x40, 0x10, 14, 1),
+	PIN_FIELD_BASE(64, 64, IOCFG_RB_BASE, 0x40, 0x10, 13, 1),
+	PIN_FIELD_BASE(65, 65, IOCFG_RB_BASE, 0x40, 0x10, 16, 1),
+	PIN_FIELD_BASE(66, 68, IOCFG_LB_BASE, 0x20, 0x10, 2, 1),
+	PIN_FIELD_BASE(69, 69, IOCFG_TR_BASE, 0x30, 0x10, 1, 1),
+	PIN_FIELD_BASE(70, 70, IOCFG_TR_BASE, 0x30, 0x10, 0, 1),
+	PIN_FIELD_BASE(71, 71, IOCFG_TR_BASE, 0x30, 0x10, 16, 1),
+	PIN_FIELD_BASE(72, 73, IOCFG_TR_BASE, 0x30, 0x10, 14, 1),
+	PIN_FIELD_BASE(74, 74, IOCFG_TR_BASE, 0x30, 0x10, 4, 1),
+	PIN_FIELD_BASE(75, 77, IOCFG_TR_BASE, 0x30, 0x10, 6, 1),
+	PIN_FIELD_BASE(78, 79, IOCFG_TR_BASE, 0x30, 0x10, 2, 1),
+	PIN_FIELD_BASE(80, 84, IOCFG_TR_BASE, 0x30, 0x10, 9, 1),
+	PIN_FIELD_BASE(85, 85, IOCFG_TR_BASE, 0x30, 0x10, 5, 1),
+	PIN_FIELD_BASE(86, 86, IOCFG_TL_BASE, 0x30, 0x10, 1, 1),
+	PIN_FIELD_BASE(87, 87, IOCFG_TL_BASE, 0x30, 0x10, 0, 1),
+	PIN_FIELD_BASE(88, 88, IOCFG_TL_BASE, 0x30, 0x10, 14, 1),
+	PIN_FIELD_BASE(89, 90, IOCFG_TL_BASE, 0x30, 0x10, 12, 1),
+	PIN_FIELD_BASE(91, 94, IOCFG_TL_BASE, 0x30, 0x10, 4, 1),
+	PIN_FIELD_BASE(95, 96, IOCFG_TL_BASE, 0x30, 0x10, 2, 1),
+	PIN_FIELD_BASE(97, 100, IOCFG_TL_BASE, 0x30, 0x10, 8, 1),
+};
+
+static const struct mtk_pin_field_calc mt7986_pin_smt_range[] = {
+	PIN_FIELD_BASE(0, 0, IOCFG_RB_BASE, 0xf0, 0x10, 17, 1),
+	PIN_FIELD_BASE(1, 2, IOCFG_LT_BASE, 0x90, 0x10, 10, 1),
+	PIN_FIELD_BASE(3, 4, IOCFG_LB_BASE, 0x90, 0x10, 0, 1),
+	PIN_FIELD_BASE(5, 6, IOCFG_RB_BASE, 0xf0, 0x10, 0, 1),
+	PIN_FIELD_BASE(7, 10, IOCFG_LT_BASE, 0x90, 0x10, 0, 1),
+	PIN_FIELD_BASE(11, 14, IOCFG_RB_BASE, 0xf0, 0x10, 8, 1),
+	PIN_FIELD_BASE(15, 20, IOCFG_RB_BASE, 0xf0, 0x10, 2, 1),
+	PIN_FIELD_BASE(21, 23, IOCFG_RT_BASE, 0xc0, 0x10, 12, 1),
+	PIN_FIELD_BASE(24, 24, IOCFG_RT_BASE, 0xc0, 0x10, 18, 1),
+	PIN_FIELD_BASE(25, 25, IOCFG_RT_BASE, 0xc0, 0x10, 17, 1),
+	PIN_FIELD_BASE(26, 27, IOCFG_RT_BASE, 0xc0, 0x10, 15, 1),
+	PIN_FIELD_BASE(28, 29, IOCFG_RT_BASE, 0xc0, 0x10, 19, 1),
+	PIN_FIELD_BASE(30, 30, IOCFG_RT_BASE, 0xc0, 0x10, 23, 1),
+	PIN_FIELD_BASE(31, 31, IOCFG_RT_BASE, 0xc0, 0x10, 22, 1),
+	PIN_FIELD_BASE(32, 32, IOCFG_RT_BASE, 0xc0, 0x10, 21, 1),
+	PIN_FIELD_BASE(33, 33, IOCFG_LT_BASE, 0x90, 0x10, 4, 1),
+	PIN_FIELD_BASE(34, 34, IOCFG_LT_BASE, 0x90, 0x10, 8, 1),
+	PIN_FIELD_BASE(35, 35, IOCFG_LT_BASE, 0x90, 0x10, 7, 1),
+	PIN_FIELD_BASE(36, 37, IOCFG_LT_BASE, 0x90, 0x10, 5, 1),
+	PIN_FIELD_BASE(38, 38, IOCFG_LT_BASE, 0x90, 0x10, 9, 1),
+	PIN_FIELD_BASE(39, 40, IOCFG_RB_BASE, 0xf0, 0x10, 18, 1),
+	PIN_FIELD_BASE(41, 41, IOCFG_RB_BASE, 0xf0, 0x10, 12, 1),
+	PIN_FIELD_BASE(42, 43, IOCFG_RB_BASE, 0xf0, 0x10, 22, 1),
+	PIN_FIELD_BASE(44, 45, IOCFG_RB_BASE, 0xf0, 0x10, 20, 1),
+	PIN_FIELD_BASE(46, 47, IOCFG_RB_BASE, 0xf0, 0x10, 26, 1),
+	PIN_FIELD_BASE(48, 49, IOCFG_RB_BASE, 0xf0, 0x10, 24, 1),
+	PIN_FIELD_BASE(50, 57, IOCFG_RT_BASE, 0xc0, 0x10, 2, 1),
+	PIN_FIELD_BASE(58, 58, IOCFG_RT_BASE, 0xc0, 0x10, 1, 1),
+	PIN_FIELD_BASE(59, 59, IOCFG_RT_BASE, 0xc0, 0x10, 0, 1),
+	PIN_FIELD_BASE(60, 61, IOCFG_RT_BASE, 0xc0, 0x10, 10, 1),
+	PIN_FIELD_BASE(62, 62, IOCFG_RB_BASE, 0xf0, 0x10, 15, 1),
+	PIN_FIELD_BASE(63, 63, IOCFG_RB_BASE, 0xf0, 0x10, 14, 1),
+	PIN_FIELD_BASE(64, 64, IOCFG_RB_BASE, 0xf0, 0x10, 13, 1),
+	PIN_FIELD_BASE(65, 65, IOCFG_RB_BASE, 0xf0, 0x10, 16, 1),
+	PIN_FIELD_BASE(66, 68, IOCFG_LB_BASE, 0x90, 0x10, 2, 1),
+	PIN_FIELD_BASE(69, 69, IOCFG_TR_BASE, 0x80, 0x10, 1, 1),
+	PIN_FIELD_BASE(70, 70, IOCFG_TR_BASE, 0x80, 0x10, 0, 1),
+	PIN_FIELD_BASE(71, 71, IOCFG_TR_BASE, 0x80, 0x10, 16, 1),
+	PIN_FIELD_BASE(72, 73, IOCFG_TR_BASE, 0x80, 0x10, 14, 1),
+	PIN_FIELD_BASE(74, 74, IOCFG_TR_BASE, 0x80, 0x10, 4, 1),
+	PIN_FIELD_BASE(75, 77, IOCFG_TR_BASE, 0x80, 0x10, 6, 1),
+	PIN_FIELD_BASE(78, 79, IOCFG_TR_BASE, 0x80, 0x10, 2, 1),
+	PIN_FIELD_BASE(80, 84, IOCFG_TR_BASE, 0x80, 0x10, 9, 1),
+	PIN_FIELD_BASE(85, 85, IOCFG_TR_BASE, 0x80, 0x10, 5, 1),
+	PIN_FIELD_BASE(86, 86, IOCFG_TL_BASE, 0x70, 0x10, 1, 1),
+	PIN_FIELD_BASE(87, 87, IOCFG_TL_BASE, 0x70, 0x10, 0, 1),
+	PIN_FIELD_BASE(88, 88, IOCFG_TL_BASE, 0x70, 0x10, 14, 1),
+	PIN_FIELD_BASE(89, 90, IOCFG_TL_BASE, 0x70, 0x10, 12, 1),
+	PIN_FIELD_BASE(91, 94, IOCFG_TL_BASE, 0x70, 0x10, 4, 1),
+	PIN_FIELD_BASE(95, 96, IOCFG_TL_BASE, 0x70, 0x10, 2, 1),
+	PIN_FIELD_BASE(97, 100, IOCFG_TL_BASE, 0x70, 0x10, 8, 1),
+};
+
+static const struct mtk_pin_field_calc mt7986_pin_pu_range[] = {
+	PIN_FIELD_BASE(69, 69, IOCFG_TR_BASE, 0x50, 0x10, 1, 1),
+	PIN_FIELD_BASE(70, 70, IOCFG_TR_BASE, 0x50, 0x10, 0, 1),
+	PIN_FIELD_BASE(71, 71, IOCFG_TR_BASE, 0x50, 0x10, 16, 1),
+	PIN_FIELD_BASE(72, 73, IOCFG_TR_BASE, 0x50, 0x10, 14, 1),
+	PIN_FIELD_BASE(74, 74, IOCFG_TR_BASE, 0x50, 0x10, 4, 1),
+	PIN_FIELD_BASE(75, 77, IOCFG_TR_BASE, 0x50, 0x10, 6, 1),
+	PIN_FIELD_BASE(78, 79, IOCFG_TR_BASE, 0x50, 0x10, 2, 1),
+	PIN_FIELD_BASE(80, 84, IOCFG_TR_BASE, 0x50, 0x10, 9, 1),
+	PIN_FIELD_BASE(85, 85, IOCFG_TR_BASE, 0x50, 0x10, 5, 1),
+	PIN_FIELD_BASE(86, 86, IOCFG_TL_BASE, 0x50, 0x10, 1, 1),
+	PIN_FIELD_BASE(87, 87, IOCFG_TL_BASE, 0x50, 0x10, 0, 1),
+	PIN_FIELD_BASE(88, 88, IOCFG_TL_BASE, 0x50, 0x10, 14, 1),
+	PIN_FIELD_BASE(89, 90, IOCFG_TL_BASE, 0x50, 0x10, 12, 1),
+	PIN_FIELD_BASE(91, 94, IOCFG_TL_BASE, 0x50, 0x10, 4, 1),
+	PIN_FIELD_BASE(95, 96, IOCFG_TL_BASE, 0x50, 0x10, 2, 1),
+	PIN_FIELD_BASE(97, 100, IOCFG_TL_BASE, 0x50, 0x10, 8, 1),
+};
+
+static const struct mtk_pin_field_calc mt7986_pin_pd_range[] = {
+	PIN_FIELD_BASE(69, 69, IOCFG_TR_BASE, 0x40, 0x10, 1, 1),
+	PIN_FIELD_BASE(70, 70, IOCFG_TR_BASE, 0x40, 0x10, 0, 1),
+	PIN_FIELD_BASE(71, 71, IOCFG_TR_BASE, 0x40, 0x10, 16, 1),
+	PIN_FIELD_BASE(72, 73, IOCFG_TR_BASE, 0x40, 0x10, 14, 1),
+	PIN_FIELD_BASE(74, 74, IOCFG_TR_BASE, 0x40, 0x10, 4, 1),
+	PIN_FIELD_BASE(75, 77, IOCFG_TR_BASE, 0x40, 0x10, 6, 1),
+	PIN_FIELD_BASE(78, 79, IOCFG_TR_BASE, 0x40, 0x10, 2, 1),
+	PIN_FIELD_BASE(80, 84, IOCFG_TR_BASE, 0x40, 0x10, 9, 1),
+	PIN_FIELD_BASE(85, 85, IOCFG_TR_BASE, 0x40, 0x10, 5, 1),
+	PIN_FIELD_BASE(86, 86, IOCFG_TL_BASE, 0x40, 0x10, 1, 1),
+	PIN_FIELD_BASE(87, 87, IOCFG_TL_BASE, 0x40, 0x10, 0, 1),
+	PIN_FIELD_BASE(88, 88, IOCFG_TL_BASE, 0x40, 0x10, 14, 1),
+	PIN_FIELD_BASE(89, 90, IOCFG_TL_BASE, 0x40, 0x10, 12, 1),
+	PIN_FIELD_BASE(91, 94, IOCFG_TL_BASE, 0x40, 0x10, 4, 1),
+	PIN_FIELD_BASE(95, 96, IOCFG_TL_BASE, 0x40, 0x10, 2, 1),
+	PIN_FIELD_BASE(97, 100, IOCFG_TL_BASE, 0x40, 0x10, 8, 1),
+};
+
+static const struct mtk_pin_field_calc mt7986_pin_drv_range[] = {
+	PIN_FIELD_BASE(0, 0, IOCFG_RB_BASE, 0x10, 0x10, 21, 3),
+	PIN_FIELD_BASE(1, 2, IOCFG_LT_BASE, 0x10, 0x10, 0, 3),
+	PIN_FIELD_BASE(3, 4, IOCFG_LB_BASE, 0x00, 0x10, 0, 1),
+	PIN_FIELD_BASE(5, 5, IOCFG_RB_BASE, 0x00, 0x10, 0, 3),
+	PIN_FIELD_BASE(6, 6, IOCFG_RB_BASE, 0x00, 0x10, 21, 3),
+	PIN_FIELD_BASE(7, 10, IOCFG_LT_BASE, 0x00, 0x10, 0, 3),
+	PIN_FIELD_BASE(11, 12, IOCFG_RB_BASE, 0x00, 0x10, 24, 3),
+	PIN_FIELD_BASE(13, 14, IOCFG_RB_BASE, 0x10, 0x10, 0, 3),
+	PIN_FIELD_BASE(15, 20, IOCFG_RB_BASE, 0x00, 0x10, 3, 3),
+	PIN_FIELD_BASE(21, 23, IOCFG_RT_BASE, 0x10, 0x10, 6, 3),
+	PIN_FIELD_BASE(24, 24, IOCFG_RT_BASE, 0x10, 0x10, 24, 3),
+	PIN_FIELD_BASE(25, 25, IOCFG_RT_BASE, 0x10, 0x10, 21, 3),
+	PIN_FIELD_BASE(26, 27, IOCFG_RT_BASE, 0x10, 0x10, 15, 3),
+	PIN_FIELD_BASE(28, 28, IOCFG_RT_BASE, 0x10, 0x10, 27, 3),
+	PIN_FIELD_BASE(29, 29, IOCFG_RT_BASE, 0x20, 0x10, 0, 3),
+	PIN_FIELD_BASE(30, 30, IOCFG_RT_BASE, 0x20, 0x10, 9, 3),
+	PIN_FIELD_BASE(31, 31, IOCFG_RT_BASE, 0x20, 0x10, 6, 3),
+	PIN_FIELD_BASE(32, 32, IOCFG_RT_BASE, 0x20, 0x10, 3, 3),
+	PIN_FIELD_BASE(33, 33, IOCFG_LT_BASE, 0x00, 0x10, 12, 3),
+	PIN_FIELD_BASE(34, 34, IOCFG_LT_BASE, 0x00, 0x10, 24, 3),
+	PIN_FIELD_BASE(35, 35, IOCFG_LT_BASE, 0x00, 0x10, 21, 3),
+	PIN_FIELD_BASE(36, 37, IOCFG_LT_BASE, 0x00, 0x10, 15, 3),
+	PIN_FIELD_BASE(38, 38, IOCFG_LT_BASE, 0x00, 0x10, 27, 3),
+	PIN_FIELD_BASE(39, 39, IOCFG_RB_BASE, 0x10, 0x10, 27, 3),
+	PIN_FIELD_BASE(40, 40, IOCFG_RB_BASE, 0x20, 0x10, 0, 3),
+	PIN_FIELD_BASE(41, 41, IOCFG_RB_BASE, 0x10, 0x10, 6, 3),
+	PIN_FIELD_BASE(42, 43, IOCFG_RB_BASE, 0x20, 0x10, 9, 3),
+	PIN_FIELD_BASE(44, 45, IOCFG_RB_BASE, 0x20, 0x10, 3, 3),
+	PIN_FIELD_BASE(46, 47, IOCFG_RB_BASE, 0x20, 0x10, 21, 3),
+	PIN_FIELD_BASE(48, 49, IOCFG_RB_BASE, 0x20, 0x10, 15, 3),
+	PIN_FIELD_BASE(50, 57, IOCFG_RT_BASE, 0x00, 0x10, 6, 3),
+	PIN_FIELD_BASE(58, 58, IOCFG_RT_BASE, 0x00, 0x10, 3, 3),
+	PIN_FIELD_BASE(59, 59, IOCFG_RT_BASE, 0x00, 0x10, 0, 3),
+	PIN_FIELD_BASE(60, 61, IOCFG_RT_BASE, 0x10, 0x10, 0, 3),
+	PIN_FIELD_BASE(62, 62, IOCFG_RB_BASE, 0x10, 0x10, 15, 3),
+	PIN_FIELD_BASE(63, 63, IOCFG_RB_BASE, 0x10, 0x10, 12, 3),
+	PIN_FIELD_BASE(64, 64, IOCFG_RB_BASE, 0x10, 0x10, 9, 3),
+	PIN_FIELD_BASE(65, 65, IOCFG_RB_BASE, 0x10, 0x10, 18, 3),
+	PIN_FIELD_BASE(66, 68, IOCFG_LB_BASE, 0x00, 0x10, 2, 3),
+	PIN_FIELD_BASE(69, 69, IOCFG_TR_BASE, 0x00, 0x10, 3, 3),
+	PIN_FIELD_BASE(70, 70, IOCFG_TR_BASE, 0x00, 0x10, 0, 3),
+	PIN_FIELD_BASE(71, 71, IOCFG_TR_BASE, 0x10, 0x10, 18, 3),
+	PIN_FIELD_BASE(72, 73, IOCFG_TR_BASE, 0x10, 0x10, 12, 3),
+	PIN_FIELD_BASE(74, 77, IOCFG_TR_BASE, 0x00, 0x10, 15, 3),
+	PIN_FIELD_BASE(78, 79, IOCFG_TR_BASE, 0x00, 0x10, 6, 3),
+	PIN_FIELD_BASE(80, 80, IOCFG_TR_BASE, 0x00, 0x10, 27, 3),
+	PIN_FIELD_BASE(81, 84, IOCFG_TR_BASE, 0x10, 0x10, 0, 3),
+	PIN_FIELD_BASE(85, 85, IOCFG_TR_BASE, 0x00, 0x10, 12, 3),
+	PIN_FIELD_BASE(86, 86, IOCFG_TL_BASE, 0x00, 0x10, 3, 3),
+	PIN_FIELD_BASE(87, 87, IOCFG_TL_BASE, 0x00, 0x10, 0, 3),
+	PIN_FIELD_BASE(88, 88, IOCFG_TL_BASE, 0x10, 0x10, 12, 3),
+	PIN_FIELD_BASE(89, 90, IOCFG_TL_BASE, 0x10, 0x10, 6, 3),
+	PIN_FIELD_BASE(91, 94, IOCFG_TL_BASE, 0x00, 0x10, 12, 3),
+	PIN_FIELD_BASE(95, 96, IOCFG_TL_BASE, 0x00, 0x10, 6, 3),
+	PIN_FIELD_BASE(97, 98, IOCFG_TL_BASE, 0x00, 0x10, 24, 3),
+	PIN_FIELD_BASE(99, 100, IOCFG_TL_BASE, 0x10, 0x10, 2, 3),
+};
+
+static const struct mtk_pin_field_calc mt7986_pin_pupd_range[] = {
+	PIN_FIELD_BASE(0, 0, IOCFG_RB_BASE, 0x60, 0x10, 17, 1),
+	PIN_FIELD_BASE(1, 2, IOCFG_LT_BASE, 0x30, 0x10, 10, 1),
+	PIN_FIELD_BASE(3, 4, IOCFG_LB_BASE, 0x40, 0x10, 0, 1),
+	PIN_FIELD_BASE(5, 6, IOCFG_RB_BASE, 0x60, 0x10, 0, 1),
+	PIN_FIELD_BASE(7, 10, IOCFG_LT_BASE, 0x30, 0x10, 0, 1),
+	PIN_FIELD_BASE(11, 14, IOCFG_RB_BASE, 0x60, 0x10, 8, 1),
+	PIN_FIELD_BASE(15, 20, IOCFG_RB_BASE, 0x60, 0x10, 2, 1),
+	PIN_FIELD_BASE(21, 23, IOCFG_RT_BASE, 0x40, 0x10, 12, 1),
+	PIN_FIELD_BASE(24, 24, IOCFG_RT_BASE, 0x40, 0x10, 18, 1),
+	PIN_FIELD_BASE(25, 25, IOCFG_RT_BASE, 0x40, 0x10, 17, 1),
+	PIN_FIELD_BASE(26, 27, IOCFG_RT_BASE, 0x40, 0x10, 15, 1),
+	PIN_FIELD_BASE(28, 29, IOCFG_RT_BASE, 0x40, 0x10, 19, 1),
+	PIN_FIELD_BASE(30, 30, IOCFG_RT_BASE, 0x40, 0x10, 23, 1),
+	PIN_FIELD_BASE(31, 31, IOCFG_RT_BASE, 0x40, 0x10, 22, 1),
+	PIN_FIELD_BASE(32, 32, IOCFG_RT_BASE, 0x40, 0x10, 21, 1),
+	PIN_FIELD_BASE(33, 33, IOCFG_LT_BASE, 0x30, 0x10, 4, 1),
+	PIN_FIELD_BASE(34, 34, IOCFG_LT_BASE, 0x30, 0x10, 8, 1),
+	PIN_FIELD_BASE(35, 35, IOCFG_LT_BASE, 0x30, 0x10, 7, 1),
+	PIN_FIELD_BASE(36, 37, IOCFG_LT_BASE, 0x30, 0x10, 5, 1),
+	PIN_FIELD_BASE(38, 38, IOCFG_LT_BASE, 0x30, 0x10, 9, 1),
+	PIN_FIELD_BASE(39, 40, IOCFG_RB_BASE, 0x60, 0x10, 18, 1),
+	PIN_FIELD_BASE(41, 41, IOCFG_RB_BASE, 0x60, 0x10, 12, 1),
+	PIN_FIELD_BASE(42, 43, IOCFG_RB_BASE, 0x60, 0x10, 23, 1),
+	PIN_FIELD_BASE(44, 45, IOCFG_RB_BASE, 0x60, 0x10, 21, 1),
+	PIN_FIELD_BASE(46, 47, IOCFG_RB_BASE, 0x60, 0x10, 27, 1),
+	PIN_FIELD_BASE(48, 49, IOCFG_RB_BASE, 0x60, 0x10, 25, 1),
+	PIN_FIELD_BASE(50, 57, IOCFG_RT_BASE, 0x40, 0x10, 2, 1),
+	PIN_FIELD_BASE(58, 58, IOCFG_RT_BASE, 0x40, 0x10, 1, 1),
+	PIN_FIELD_BASE(59, 59, IOCFG_RT_BASE, 0x40, 0x10, 0, 1),
+	PIN_FIELD_BASE(60, 61, IOCFG_RT_BASE, 0x40, 0x10, 10, 1),
+	PIN_FIELD_BASE(62, 62, IOCFG_RB_BASE, 0x60, 0x10, 15, 1),
+	PIN_FIELD_BASE(63, 63, IOCFG_RB_BASE, 0x60, 0x10, 14, 1),
+	PIN_FIELD_BASE(64, 64, IOCFG_RB_BASE, 0x60, 0x10, 13, 1),
+	PIN_FIELD_BASE(65, 65, IOCFG_RB_BASE, 0x60, 0x10, 16, 1),
+	PIN_FIELD_BASE(66, 68, IOCFG_LB_BASE, 0x40, 0x10, 2, 1),
+};
+
+static const struct mtk_pin_field_calc mt7986_pin_r0_range[] = {
+	PIN_FIELD_BASE(0, 0, IOCFG_RB_BASE, 0x70, 0x10, 17, 1),
+	PIN_FIELD_BASE(1, 2, IOCFG_LT_BASE, 0x40, 0x10, 10, 1),
+	PIN_FIELD_BASE(3, 4, IOCFG_LB_BASE, 0x50, 0x10, 0, 1),
+	PIN_FIELD_BASE(5, 6, IOCFG_RB_BASE, 0x70, 0x10, 0, 1),
+	PIN_FIELD_BASE(7, 10, IOCFG_LT_BASE, 0x40, 0x10, 0, 1),
+	PIN_FIELD_BASE(11, 14, IOCFG_RB_BASE, 0x70, 0x10, 8, 1),
+	PIN_FIELD_BASE(15, 20, IOCFG_RB_BASE, 0x70, 0x10, 2, 1),
+	PIN_FIELD_BASE(21, 23, IOCFG_RT_BASE, 0x50, 0x10, 12, 1),
+	PIN_FIELD_BASE(24, 24, IOCFG_RT_BASE, 0x50, 0x10, 18, 1),
+	PIN_FIELD_BASE(25, 25, IOCFG_RT_BASE, 0x50, 0x10, 17, 1),
+	PIN_FIELD_BASE(26, 27, IOCFG_RT_BASE, 0x50, 0x10, 15, 1),
+	PIN_FIELD_BASE(28, 29, IOCFG_RT_BASE, 0x50, 0x10, 19, 1),
+	PIN_FIELD_BASE(30, 30, IOCFG_RT_BASE, 0x50, 0x10, 23, 1),
+	PIN_FIELD_BASE(31, 31, IOCFG_RT_BASE, 0x50, 0x10, 22, 1),
+	PIN_FIELD_BASE(32, 32, IOCFG_RT_BASE, 0x50, 0x10, 21, 1),
+	PIN_FIELD_BASE(33, 33, IOCFG_LT_BASE, 0x40, 0x10, 4, 1),
+	PIN_FIELD_BASE(34, 34, IOCFG_LT_BASE, 0x40, 0x10, 8, 1),
+	PIN_FIELD_BASE(35, 35, IOCFG_LT_BASE, 0x40, 0x10, 7, 1),
+	PIN_FIELD_BASE(36, 37, IOCFG_LT_BASE, 0x40, 0x10, 5, 1),
+	PIN_FIELD_BASE(38, 38, IOCFG_LT_BASE, 0x40, 0x10, 9, 1),
+	PIN_FIELD_BASE(39, 40, IOCFG_RB_BASE, 0x70, 0x10, 18, 1),
+	PIN_FIELD_BASE(41, 41, IOCFG_RB_BASE, 0x70, 0x10, 12, 1),
+	PIN_FIELD_BASE(42, 43, IOCFG_RB_BASE, 0x70, 0x10, 23, 1),
+	PIN_FIELD_BASE(44, 45, IOCFG_RB_BASE, 0x70, 0x10, 21, 1),
+	PIN_FIELD_BASE(46, 47, IOCFG_RB_BASE, 0x70, 0x10, 27, 1),
+	PIN_FIELD_BASE(48, 49, IOCFG_RB_BASE, 0x70, 0x10, 25, 1),
+	PIN_FIELD_BASE(50, 57, IOCFG_RT_BASE, 0x50, 0x10, 2, 1),
+	PIN_FIELD_BASE(58, 58, IOCFG_RT_BASE, 0x50, 0x10, 1, 1),
+	PIN_FIELD_BASE(59, 59, IOCFG_RT_BASE, 0x50, 0x10, 0, 1),
+	PIN_FIELD_BASE(60, 61, IOCFG_RT_BASE, 0x50, 0x10, 10, 1),
+	PIN_FIELD_BASE(62, 62, IOCFG_RB_BASE, 0x70, 0x10, 15, 1),
+	PIN_FIELD_BASE(63, 63, IOCFG_RB_BASE, 0x70, 0x10, 14, 1),
+	PIN_FIELD_BASE(64, 64, IOCFG_RB_BASE, 0x70, 0x10, 13, 1),
+	PIN_FIELD_BASE(65, 65, IOCFG_RB_BASE, 0x70, 0x10, 16, 1),
+	PIN_FIELD_BASE(66, 68, IOCFG_LB_BASE, 0x50, 0x10, 2, 1),
+};
+
+static const struct mtk_pin_field_calc mt7986_pin_r1_range[] = {
+	PIN_FIELD_BASE(0, 0, IOCFG_RB_BASE, 0x80, 0x10, 17, 1),
+	PIN_FIELD_BASE(1, 2, IOCFG_LT_BASE, 0x50, 0x10, 10, 1),
+	PIN_FIELD_BASE(3, 4, IOCFG_LB_BASE, 0x60, 0x10, 0, 1),
+	PIN_FIELD_BASE(5, 6, IOCFG_RB_BASE, 0x80, 0x10, 0, 1),
+	PIN_FIELD_BASE(7, 10, IOCFG_LT_BASE, 0x50, 0x10, 0, 1),
+	PIN_FIELD_BASE(11, 14, IOCFG_RB_BASE, 0x80, 0x10, 8, 1),
+	PIN_FIELD_BASE(15, 20, IOCFG_RB_BASE, 0x80, 0x10, 2, 1),
+	PIN_FIELD_BASE(21, 23, IOCFG_RT_BASE, 0x60, 0x10, 12, 1),
+	PIN_FIELD_BASE(24, 24, IOCFG_RT_BASE, 0x60, 0x10, 18, 1),
+	PIN_FIELD_BASE(25, 25, IOCFG_RT_BASE, 0x60, 0x10, 17, 1),
+	PIN_FIELD_BASE(26, 27, IOCFG_RT_BASE, 0x60, 0x10, 15, 1),
+	PIN_FIELD_BASE(28, 29, IOCFG_RT_BASE, 0x60, 0x10, 19, 1),
+	PIN_FIELD_BASE(30, 30, IOCFG_RT_BASE, 0x60, 0x10, 23, 1),
+	PIN_FIELD_BASE(31, 31, IOCFG_RT_BASE, 0x60, 0x10, 22, 1),
+	PIN_FIELD_BASE(32, 32, IOCFG_RT_BASE, 0x60, 0x10, 21, 1),
+	PIN_FIELD_BASE(33, 33, IOCFG_LT_BASE, 0x50, 0x10, 4, 1),
+	PIN_FIELD_BASE(34, 34, IOCFG_LT_BASE, 0x50, 0x10, 8, 1),
+	PIN_FIELD_BASE(35, 35, IOCFG_LT_BASE, 0x50, 0x10, 7, 1),
+	PIN_FIELD_BASE(36, 37, IOCFG_LT_BASE, 0x50, 0x10, 5, 1),
+	PIN_FIELD_BASE(38, 38, IOCFG_LT_BASE, 0x50, 0x10, 9, 1),
+	PIN_FIELD_BASE(39, 40, IOCFG_RB_BASE, 0x80, 0x10, 18, 1),
+	PIN_FIELD_BASE(41, 41, IOCFG_RB_BASE, 0x80, 0x10, 12, 1),
+	PIN_FIELD_BASE(42, 43, IOCFG_RB_BASE, 0x80, 0x10, 23, 1),
+	PIN_FIELD_BASE(44, 45, IOCFG_RB_BASE, 0x80, 0x10, 21, 1),
+	PIN_FIELD_BASE(46, 47, IOCFG_RB_BASE, 0x80, 0x10, 27, 1),
+	PIN_FIELD_BASE(48, 49, IOCFG_RB_BASE, 0x80, 0x10, 25, 1),
+	PIN_FIELD_BASE(50, 57, IOCFG_RT_BASE, 0x60, 0x10, 2, 1),
+	PIN_FIELD_BASE(58, 58, IOCFG_RT_BASE, 0x60, 0x10, 1, 1),
+	PIN_FIELD_BASE(59, 59, IOCFG_RT_BASE, 0x60, 0x10, 0, 1),
+	PIN_FIELD_BASE(60, 61, IOCFG_RT_BASE, 0x60, 0x10, 10, 1),
+	PIN_FIELD_BASE(62, 62, IOCFG_RB_BASE, 0x80, 0x10, 15, 1),
+	PIN_FIELD_BASE(63, 63, IOCFG_RB_BASE, 0x80, 0x10, 14, 1),
+	PIN_FIELD_BASE(64, 64, IOCFG_RB_BASE, 0x80, 0x10, 13, 1),
+	PIN_FIELD_BASE(65, 65, IOCFG_RB_BASE, 0x80, 0x10, 16, 1),
+	PIN_FIELD_BASE(66, 68, IOCFG_LB_BASE, 0x60, 0x10, 2, 1),
+};
+
+static const struct mtk_pin_reg_calc mt7986_reg_cals[] = {
+	[PINCTRL_PIN_REG_MODE] = MTK_RANGE(mt7986_pin_mode_range),
+	[PINCTRL_PIN_REG_DIR] = MTK_RANGE(mt7986_pin_dir_range),
+	[PINCTRL_PIN_REG_DI] = MTK_RANGE(mt7986_pin_di_range),
+	[PINCTRL_PIN_REG_DO] = MTK_RANGE(mt7986_pin_do_range),
+	[PINCTRL_PIN_REG_SMT] = MTK_RANGE(mt7986_pin_smt_range),
+	[PINCTRL_PIN_REG_IES] = MTK_RANGE(mt7986_pin_ies_range),
+	[PINCTRL_PIN_REG_DRV] = MTK_RANGE(mt7986_pin_drv_range),
+	[PINCTRL_PIN_REG_PU] = MTK_RANGE(mt7986_pin_pu_range),
+	[PINCTRL_PIN_REG_PD] = MTK_RANGE(mt7986_pin_pd_range),
+	[PINCTRL_PIN_REG_PUPD] = MTK_RANGE(mt7986_pin_pupd_range),
+	[PINCTRL_PIN_REG_R0] = MTK_RANGE(mt7986_pin_r0_range),
+	[PINCTRL_PIN_REG_R1] = MTK_RANGE(mt7986_pin_r1_range),
+};
+
+static const struct mtk_pin_desc mt7986_pins[] = {
+	MT7986_TYPE0_PIN(0, "SYS_WATCHDOG"),
+	MT7986_TYPE0_PIN(1, "WF2G_LED"),
+	MT7986_TYPE0_PIN(2, "WF5G_LED"),
+	MT7986_TYPE0_PIN(3, "I2C_SCL"),
+	MT7986_TYPE0_PIN(4, "I2C_SDA"),
+	MT7986_TYPE0_PIN(5, "GPIO_0"),
+	MT7986_TYPE0_PIN(6, "GPIO_1"),
+	MT7986_TYPE0_PIN(7, "GPIO_2"),
+	MT7986_TYPE0_PIN(8, "GPIO_3"),
+	MT7986_TYPE0_PIN(9, "GPIO_4"),
+	MT7986_TYPE0_PIN(10, "GPIO_5"),
+	MT7986_TYPE0_PIN(11, "GPIO_6"),
+	MT7986_TYPE0_PIN(12, "GPIO_7"),
+	MT7986_TYPE0_PIN(13, "GPIO_8"),
+	MT7986_TYPE0_PIN(14, "GPIO_9"),
+	MT7986_TYPE0_PIN(15, "GPIO_10"),
+	MT7986_TYPE0_PIN(16, "GPIO_11"),
+	MT7986_TYPE0_PIN(17, "GPIO_12"),
+	MT7986_TYPE0_PIN(18, "GPIO_13"),
+	MT7986_TYPE0_PIN(19, "GPIO_14"),
+	MT7986_TYPE0_PIN(20, "GPIO_15"),
+	MT7986_TYPE0_PIN(21, "PWM0"),
+	MT7986_TYPE0_PIN(22, "PWM1"),
+	MT7986_TYPE0_PIN(23, "SPI0_CLK"),
+	MT7986_TYPE0_PIN(24, "SPI0_MOSI"),
+	MT7986_TYPE0_PIN(25, "SPI0_MISO"),
+	MT7986_TYPE0_PIN(26, "SPI0_CS"),
+	MT7986_TYPE0_PIN(27, "SPI0_HOLD"),
+	MT7986_TYPE0_PIN(28, "SPI0_WP"),
+	MT7986_TYPE0_PIN(29, "SPI1_CLK"),
+	MT7986_TYPE0_PIN(30, "SPI1_MOSI"),
+	MT7986_TYPE0_PIN(31, "SPI1_MISO"),
+	MT7986_TYPE0_PIN(32, "SPI1_CS"),
+	MT7986_TYPE0_PIN(33, "SPI2_CLK"),
+	MT7986_TYPE0_PIN(34, "SPI2_MOSI"),
+	MT7986_TYPE0_PIN(35, "SPI2_MISO"),
+	MT7986_TYPE0_PIN(36, "SPI2_CS"),
+	MT7986_TYPE0_PIN(37, "SPI2_HOLD"),
+	MT7986_TYPE0_PIN(38, "SPI2_WP"),
+	MT7986_TYPE0_PIN(39, "UART0_RXD"),
+	MT7986_TYPE0_PIN(40, "UART0_TXD"),
+	MT7986_TYPE0_PIN(41, "PCIE_PERESET_N"),
+	MT7986_TYPE0_PIN(42, "UART1_RXD"),
+	MT7986_TYPE0_PIN(43, "UART1_TXD"),
+	MT7986_TYPE0_PIN(44, "UART1_CTS"),
+	MT7986_TYPE0_PIN(45, "UART1_RTS"),
+	MT7986_TYPE0_PIN(46, "UART2_RXD"),
+	MT7986_TYPE0_PIN(47, "UART2_TXD"),
+	MT7986_TYPE0_PIN(48, "UART2_CTS"),
+	MT7986_TYPE0_PIN(49, "UART2_RTS"),
+	MT7986_TYPE0_PIN(50, "EMMC_DATA_0"),
+	MT7986_TYPE0_PIN(51, "EMMC_DATA_1"),
+	MT7986_TYPE0_PIN(52, "EMMC_DATA_2"),
+	MT7986_TYPE0_PIN(53, "EMMC_DATA_3"),
+	MT7986_TYPE0_PIN(54, "EMMC_DATA_4"),
+	MT7986_TYPE0_PIN(55, "EMMC_DATA_5"),
+	MT7986_TYPE0_PIN(56, "EMMC_DATA_6"),
+	MT7986_TYPE0_PIN(57, "EMMC_DATA_7"),
+	MT7986_TYPE0_PIN(58, "EMMC_CMD"),
+	MT7986_TYPE0_PIN(59, "EMMC_CK"),
+	MT7986_TYPE0_PIN(60, "EMMC_DSL"),
+	MT7986_TYPE0_PIN(61, "EMMC_RSTB"),
+	MT7986_TYPE0_PIN(62, "PCM_DTX"),
+	MT7986_TYPE0_PIN(63, "PCM_DRX"),
+	MT7986_TYPE0_PIN(64, "PCM_CLK"),
+	MT7986_TYPE0_PIN(65, "PCM_FS"),
+	MT7986_TYPE0_PIN(66, "MT7531_INT"),
+	MT7986_TYPE0_PIN(67, "SMI_MDC"),
+	MT7986_TYPE0_PIN(68, "SMI_MDIO"),
+	MT7986_TYPE1_PIN(69, "WF0_DIG_RESETB"),
+	MT7986_TYPE1_PIN(70, "WF0_CBA_RESETB"),
+	MT7986_TYPE1_PIN(71, "WF0_XO_REQ"),
+	MT7986_TYPE1_PIN(72, "WF0_TOP_CLK"),
+	MT7986_TYPE1_PIN(73, "WF0_TOP_DATA"),
+	MT7986_TYPE1_PIN(74, "WF0_HB1"),
+	MT7986_TYPE1_PIN(75, "WF0_HB2"),
+	MT7986_TYPE1_PIN(76, "WF0_HB3"),
+	MT7986_TYPE1_PIN(77, "WF0_HB4"),
+	MT7986_TYPE1_PIN(78, "WF0_HB0"),
+	MT7986_TYPE1_PIN(79, "WF0_HB0_B"),
+	MT7986_TYPE1_PIN(80, "WF0_HB5"),
+	MT7986_TYPE1_PIN(81, "WF0_HB6"),
+	MT7986_TYPE1_PIN(82, "WF0_HB7"),
+	MT7986_TYPE1_PIN(83, "WF0_HB8"),
+	MT7986_TYPE1_PIN(84, "WF0_HB9"),
+	MT7986_TYPE1_PIN(85, "WF0_HB10"),
+	MT7986_TYPE1_PIN(86, "WF1_DIG_RESETB"),
+	MT7986_TYPE1_PIN(87, "WF1_CBA_RESETB"),
+	MT7986_TYPE1_PIN(88, "WF1_XO_REQ"),
+	MT7986_TYPE1_PIN(89, "WF1_TOP_CLK"),
+	MT7986_TYPE1_PIN(90, "WF1_TOP_DATA"),
+	MT7986_TYPE1_PIN(91, "WF1_HB1"),
+	MT7986_TYPE1_PIN(92, "WF1_HB2"),
+	MT7986_TYPE1_PIN(93, "WF1_HB3"),
+	MT7986_TYPE1_PIN(94, "WF1_HB4"),
+	MT7986_TYPE1_PIN(95, "WF1_HB0"),
+	MT7986_TYPE1_PIN(96, "WF1_HB0_B"),
+	MT7986_TYPE1_PIN(97, "WF1_HB5"),
+	MT7986_TYPE1_PIN(98, "WF1_HB6"),
+	MT7986_TYPE1_PIN(99, "WF1_HB7"),
+	MT7986_TYPE1_PIN(100, "WF1_HB8"),
+};
+
+static const struct mtk_io_type_desc mt7986_io_type_desc[] = {
+	[IO_TYPE_GRP0] = {
+		.name = "18OD33",
+		.bias_set = mtk_pinconf_bias_set_pupd_r1_r0,
+		.drive_set = mtk_pinconf_drive_set_v1,
+		.input_enable = mtk_pinconf_input_enable_v1,
+	},
+	[IO_TYPE_GRP1] = {
+		.name = "18A01",
+		.bias_set = mtk_pinconf_bias_set_pu_pd,
+		.drive_set = mtk_pinconf_drive_set_v1,
+		.input_enable = mtk_pinconf_input_enable_v1,
+	},
+};
+
+/* List all groups consisting of these pins dedicated to the enablement of
+ * certain hardware block and the corresponding mode for all of the pins.
+ * The hardware probably has multiple combinations of these pinouts.
+ */
+
+static int mt7986_watchdog_pins[] = { 0, };
+static int mt7986_watchdog_funcs[] = { 1, };
+
+static int mt7986_wifi_led_pins[] = { 1, 2, };
+static int mt7986_wifi_led_funcs[] = { 1, 1, };
+
+static int mt7986_i2c_pins[] = { 3, 4, };
+static int mt7986_i2c_funcs[] = { 1, 1, };
+
+static int mt7986_uart1_0_pins[] = { 7, 8, 9, 10, };
+static int mt7986_uart1_0_funcs[] = { 3, 3, 3, 3, };
+
+static int mt7986_spi1_0_pins[] = { 11, 12, 13, 14, };
+static int mt7986_spi1_0_funcs[] = { 3, 3, 3, 3, };
+
+static int mt7986_pwm1_1_pins[] = { 20, };
+static int mt7986_pwm1_1_funcs[] = { 2, };
+
+static int mt7986_pwm0_pins[] = { 21, };
+static int mt7986_pwm0_funcs[] = { 1, };
+
+static int mt7986_pwm1_0_pins[] = { 22, };
+static int mt7986_pwm1_0_funcs[] = { 1, };
+
+static int mt7986_emmc_45_pins[] = {
+	22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, };
+static int mt7986_emmc_45_funcs[] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, };
+
+static int mt7986_snfi_pins[] = { 23, 24, 25, 26, 27, 28, };
+static int mt7986_snfi_funcs[] = { 1, 1, 1, 1, 1, 1, };
+
+static int mt7986_spi1_1_pins[] = { 23, 24, 25, 26, };
+static int mt7986_spi1_1_funcs[] = { 3, 3, 3, 3, };
+
+static int mt7986_uart1_1_pins[] = { 23, 24, 25, 26, };
+static int mt7986_uart1_1_funcs[] = { 4, 4, 4, 4, };
+
+static int mt7986_spi1_2_pins[] = { 29, 30, 31, 32, };
+static int mt7986_spi1_2_funcs[] = { 1, 1, 1, 1, };
+
+static int mt7986_uart1_2_pins[] = { 29, 30, 31, 32, };
+static int mt7986_uart1_2_funcs[] = { 3, 3, 3, 3, };
+
+static int mt7986_uart2_0_pins[] = { 29, 30, 31, 32, };
+static int mt7986_uart2_0_funcs[] = { 4, 4, 4, 4, };
+
+static int mt7986_spi0_pins[] = { 33, 34, 35, 36, };
+static int mt7986_spi0_funcs[] = { 1, 1, 1, 1, };
+
+static int mt7986_spi0_wp_hold_pins[] = { 37, 38, };
+static int mt7986_spi0_wp_hold_funcs[] = { 1, 1, };
+
+static int mt7986_uart2_1_pins[] = { 33, 34, 35, 36, };
+static int mt7986_uart2_1_funcs[] = { 3, 3, 3, 3, };
+
+static int mt7986_uart1_3_rx_tx_pins[] = { 35, 36, };
+static int mt7986_uart1_3_rx_tx_funcs[] = { 2, 2, };
+
+static int mt7986_uart1_3_cts_rts_pins[] = { 37, 38, };
+static int mt7986_uart1_3_cts_rts_funcs[] = { 2, 2, };
+
+static int mt7986_spi1_3_pins[] = { 33, 34, 35, 36, };
+static int mt7986_spi1_3_funcs[] = { 4, 4, 4, 4, };
+
+static int mt7986_uart0_pins[] = { 39, 40, };
+static int mt7986_uart0_funcs[] = { 1, 1, };
+
+static int mt7986_pcie_reset_pins[] = { 41, };
+static int mt7986_pcie_reset_funcs[] = { 1, };
+
+static int mt7986_uart1_pins[] = { 42, 43, 44, 45, };
+static int mt7986_uart1_funcs[] = { 1, 1, 1, 1, };
+
+static int mt7986_uart2_pins[] = { 46, 47, 48, 49, };
+static int mt7986_uart2_funcs[] = { 1, 1, 1, 1, };
+
+static int mt7986_emmc_51_pins[] = {
+	50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, };
+static int mt7986_emmc_51_funcs[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, };
+
+static int mt7986_pcm_pins[] = { 62, 63, 64, 65, };
+static int mt7986_pcm_funcs[] = { 1, 1, 1, 1, };
+
+static int mt7986_i2s_pins[] = { 62, 63, 64, 65, };
+static int mt7986_i2s_funcs[] = { 1, 1, 1, 1, };
+
+static int mt7986_switch_int_pins[] = { 66, };
+static int mt7986_switch_int_funcs[] = { 1, };
+
+static int mt7986_mdc_mdio_pins[] = { 67, 68, };
+static int mt7986_mdc_mdio_funcs[] = { 1, 1, };
+
+static int mt7986_wf_2g_pins[] = {74, 75, 76, 77, 78, 79, 80, 81, 82, 83, };
+static int mt7986_wf_2g_funcs[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, };
+
+static int mt7986_wf_5g_pins[] = {91, 92, 93, 94, 95, 96, 97, 98, 99, 100, };
+static int mt7986_wf_5g_funcs[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, };
+
+static int mt7986_wf_dbdc_pins[] = {
+	74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, };
+static int mt7986_wf_dbdc_funcs[] = {
+	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, };
+
+static int mt7986_pcie_clk_pins[] = { 9, };
+static int mt7986_pcie_clk_funcs[] = { 1, };
+
+static int mt7986_pcie_wake_pins[] = { 10, };
+static int mt7986_pcie_wake_funcs[] = { 1, };
+
+static const struct mtk_group_desc mt7986_groups[] = {
+	PINCTRL_PIN_GROUP("watchdog", mt7986_watchdog),
+	PINCTRL_PIN_GROUP("wifi_led", mt7986_wifi_led),
+	PINCTRL_PIN_GROUP("i2c", mt7986_i2c),
+	PINCTRL_PIN_GROUP("uart1_0", mt7986_uart1_0),
+	PINCTRL_PIN_GROUP("pcie_clk", mt7986_pcie_clk),
+	PINCTRL_PIN_GROUP("pcie_wake", mt7986_pcie_wake),
+	PINCTRL_PIN_GROUP("spi1_0", mt7986_spi1_0),
+	PINCTRL_PIN_GROUP("pwm1_1", mt7986_pwm1_1),
+	PINCTRL_PIN_GROUP("pwm0", mt7986_pwm0),
+	PINCTRL_PIN_GROUP("pwm1_0", mt7986_pwm1_0),
+	PINCTRL_PIN_GROUP("emmc_45", mt7986_emmc_45),
+	PINCTRL_PIN_GROUP("snfi", mt7986_snfi),
+	PINCTRL_PIN_GROUP("spi1_1", mt7986_spi1_1),
+	PINCTRL_PIN_GROUP("uart1_1", mt7986_uart1_1),
+	PINCTRL_PIN_GROUP("spi1_2", mt7986_spi1_2),
+	PINCTRL_PIN_GROUP("uart1_2", mt7986_uart1_2),
+	PINCTRL_PIN_GROUP("uart2_0", mt7986_uart2_0),
+	PINCTRL_PIN_GROUP("spi0", mt7986_spi0),
+	PINCTRL_PIN_GROUP("spi0_wp_hold", mt7986_spi0_wp_hold),
+	PINCTRL_PIN_GROUP("uart2_1", mt7986_uart2_1),
+	PINCTRL_PIN_GROUP("uart1_3_rx_tx", mt7986_uart1_3_rx_tx),
+	PINCTRL_PIN_GROUP("uart1_3_cts_rts", mt7986_uart1_3_cts_rts),
+	PINCTRL_PIN_GROUP("spi1_3", mt7986_spi1_3),
+	PINCTRL_PIN_GROUP("uart0", mt7986_uart0),
+	PINCTRL_PIN_GROUP("switch_int", mt7986_switch_int),
+	PINCTRL_PIN_GROUP("mdc_mdio", mt7986_mdc_mdio),
+	PINCTRL_PIN_GROUP("pcie_pereset", mt7986_pcie_reset),
+	PINCTRL_PIN_GROUP("uart1", mt7986_uart1),
+	PINCTRL_PIN_GROUP("uart2", mt7986_uart2),
+	PINCTRL_PIN_GROUP("emmc_51", mt7986_emmc_51),
+	PINCTRL_PIN_GROUP("pcm", mt7986_pcm),
+	PINCTRL_PIN_GROUP("i2s", mt7986_i2s),
+	PINCTRL_PIN_GROUP("wf_2g", mt7986_wf_2g),
+	PINCTRL_PIN_GROUP("wf_5g", mt7986_wf_5g),
+	PINCTRL_PIN_GROUP("wf_dbdc", mt7986_wf_dbdc),
+};
+
+/* Joint those groups owning the same capability in user point of view which
+ * allows that people tend to use through the device tree.
+ */
+
+static const char *const mt7986_audio_groups[] = { "pcm", "i2s" };
+static const char *const mt7986_emmc_groups[] = { "emmc_45", "emmc_51", };
+static const char *const mt7986_ethernet_groups[] = { "switch_int",
+	"mdc_mdio", };
+static const char *const mt7986_i2c_groups[] = { "i2c", };
+static const char *const mt7986_led_groups[] = { "wifi_led", };
+static const char *const mt7986_flash_groups[] = { "snfi", };
+static const char *const mt7986_pcie_groups[] = { "pcie_clk", "pcie_wake",
+	"pcie_pereset" };
+static const char *const mt7986_pwm_groups[] = { "pwm0", "pwm1_0", "pwm1_1", };
+static const char *const mt7986_spi_groups[] = { "spi0", "spi0_wp_hold",
+	"spi1_0", "spi1_1", "spi1_2", "spi1_3", };
+static const char *const mt7986_uart_groups[] = { "uart1_0", "uart1_1",
+	"uart1_2", "uart1_3_rx_tx", "uart1_3_cts_rts", "uart2_0", "uart2_1",
+	"uart0", "uart1", "uart2", };
+static const char *const mt7986_wdt_groups[] = { "watchdog", };
+static const char *const mt7986_wf_groups[] = { "wf_2g", "wf_5g", "wf_dbdc", };
+
+static const struct mtk_function_desc mt7986_functions[] = {
+	{"audio", mt7986_audio_groups, ARRAY_SIZE(mt7986_audio_groups)},
+	{"emmc", mt7986_emmc_groups, ARRAY_SIZE(mt7986_emmc_groups)},
+	{"eth", mt7986_ethernet_groups, ARRAY_SIZE(mt7986_ethernet_groups)},
+	{"i2c", mt7986_i2c_groups, ARRAY_SIZE(mt7986_i2c_groups)},
+	{"led", mt7986_led_groups, ARRAY_SIZE(mt7986_led_groups)},
+	{"flash", mt7986_flash_groups, ARRAY_SIZE(mt7986_flash_groups)},
+	{"pcie", mt7986_pcie_groups, ARRAY_SIZE(mt7986_pcie_groups)},
+	{"pwm", mt7986_pwm_groups, ARRAY_SIZE(mt7986_pwm_groups)},
+	{"spi", mt7986_spi_groups, ARRAY_SIZE(mt7986_spi_groups)},
+	{"uart", mt7986_uart_groups, ARRAY_SIZE(mt7986_uart_groups)},
+	{"watchdog", mt7986_wdt_groups, ARRAY_SIZE(mt7986_wdt_groups)},
+	{"wifi", mt7986_wf_groups, ARRAY_SIZE(mt7986_wf_groups)},
+};
+
+static struct mtk_pinctrl_soc mt7986_data = {
+	.name = "mt7986_pinctrl",
+	.reg_cal = mt7986_reg_cals,
+	.pins = mt7986_pins,
+	.npins = ARRAY_SIZE(mt7986_pins),
+	.grps = mt7986_groups,
+	.ngrps = ARRAY_SIZE(mt7986_groups),
+	.funcs = mt7986_functions,
+	.nfuncs = ARRAY_SIZE(mt7986_functions),
+	.io_type = mt7986_io_type_desc,
+	.ntype = ARRAY_SIZE(mt7986_io_type_desc),
+	.gpio_mode = 0,
+	.base_names = mt7986_pinctrl_register_base_names,
+	.nbase_names = ARRAY_SIZE(mt7986_pinctrl_register_base_names),
+	.base_calc = 1,
+};
+
+static int mtk_pinctrl_mt7986_probe(struct udevice *dev)
+{
+	return mtk_pinctrl_common_probe(dev, &mt7986_data);
+}
+
+static const struct udevice_id mt7986_pctrl_match[] = {
+	{.compatible = "mediatek,mt7986-pinctrl"},
+	{ /* sentinel */ }
+};
+
+U_BOOT_DRIVER(mt7986_pinctrl) = {
+	.name = "mt7986_pinctrl",
+	.id = UCLASS_PINCTRL,
+	.of_match = mt7986_pctrl_match,
+	.ops = &mtk_pinctrl_ops,
+	.probe = mtk_pinctrl_mt7986_probe,
+	.priv_auto = sizeof(struct mtk_pinctrl_priv),
+};
-- 
2.17.1


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

* [PATCH v2 22/32] clk: mediatek: add CLK_BYPASS_XTAL flag to allow bypassing searching clock parent of xtal clock
  2022-08-31 11:00 [PATCH v2 00/32] Add support for MediaTek MT7981/MT7986 SoCs - v2 Weijie Gao
                   ` (20 preceding siblings ...)
  2022-08-31 11:04 ` [PATCH v2 21/32] pinctrl: mediatek: add pinctrl driver for MT7986 SoC Weijie Gao
@ 2022-08-31 11:04 ` Weijie Gao
  2022-09-01  0:26   ` Daniel Golle
  2022-08-31 11:05 ` [PATCH v2 23/32] clk: mediatek: add support to configure clock driver parent Weijie Gao
                   ` (9 subsequent siblings)
  31 siblings, 1 reply; 60+ messages in thread
From: Weijie Gao @ 2022-08-31 11:04 UTC (permalink / raw)
  To: u-boot; +Cc: GSS_MTK_Uboot_upstream, Lukasz Majewski, Sean Anderson, Weijie Gao

The mtk clock framework in u-boot uses array index for searching clock
parent (kernel uses strings for search), so we need to specify a special
clock with ID=0 for CLK_XTAL in u-boot.

In the mt7622/mt7629 clock tree, the clocks with ID=0 never call
mtk_topckgen_get_mux_rate, adn return xtal clock directly. This what we
expected.

However for newer chips, they may have some clocks with ID=0 not
representing the xtal clock and still needs mtk_topckgen_get_mux_rate be
called. Current logic will make entire clock driver not working.

This patch adds a flag to indicate that whether a clock driver needs clocks
with ID=0 to call mtk_topckgen_get_mux_rate.

Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
---
v2 changes:
  Add comment for flags
  Fix the if condition of CLK_BYPASS_XTAL
---
 drivers/clk/mediatek/clk-mtk.c | 4 +++-
 drivers/clk/mediatek/clk-mtk.h | 6 ++++++
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c
index d43b8a0648..7d145f4975 100644
--- a/drivers/clk/mediatek/clk-mtk.c
+++ b/drivers/clk/mediatek/clk-mtk.c
@@ -319,7 +319,9 @@ static ulong mtk_topckgen_get_mux_rate(struct clk *clk, u32 off)
 	index &= mux->mux_mask << mux->mux_shift;
 	index = index >> mux->mux_shift;
 
-	if (mux->parent[index])
+	if (mux->parent[index] > 0 ||
+	    (mux->parent[index] == CLK_XTAL &&
+	     priv->tree->flags & CLK_BYPASS_XTAL))
 		return mtk_clk_find_parent_rate(clk, mux->parent[index],
 						NULL);
 
diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
index 95a23d14a8..e0c5550c80 100644
--- a/drivers/clk/mediatek/clk-mtk.h
+++ b/drivers/clk/mediatek/clk-mtk.h
@@ -11,6 +11,11 @@
 #define CLK_XTAL			0
 #define MHZ				(1000 * 1000)
 
+/* flags in struct mtk_clk_tree */
+
+/* clk id == 0 doesn't mean it's xtal clk */
+#define CLK_BYPASS_XTAL			BIT(0)
+
 #define HAVE_RST_BAR			BIT(0)
 #define CLK_DOMAIN_SCPSYS		BIT(0)
 #define CLK_MUX_SETCLR_UPD		BIT(1)
@@ -197,6 +202,7 @@ struct mtk_clk_tree {
 	const struct mtk_fixed_clk *fclks;
 	const struct mtk_fixed_factor *fdivs;
 	const struct mtk_composite *muxes;
+	u32 flags;
 };
 
 struct mtk_clk_priv {
-- 
2.17.1


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

* [PATCH v2 23/32] clk: mediatek: add support to configure clock driver parent
  2022-08-31 11:00 [PATCH v2 00/32] Add support for MediaTek MT7981/MT7986 SoCs - v2 Weijie Gao
                   ` (21 preceding siblings ...)
  2022-08-31 11:04 ` [PATCH v2 22/32] clk: mediatek: add CLK_BYPASS_XTAL flag to allow bypassing searching clock parent of xtal clock Weijie Gao
@ 2022-08-31 11:05 ` Weijie Gao
  2022-09-01  0:27   ` Daniel Golle
  2022-08-31 11:05 ` [PATCH v2 24/32] clk: mediatek: add infrasys clock mux support Weijie Gao
                   ` (8 subsequent siblings)
  31 siblings, 1 reply; 60+ messages in thread
From: Weijie Gao @ 2022-08-31 11:05 UTC (permalink / raw)
  To: u-boot; +Cc: GSS_MTK_Uboot_upstream, Lukasz Majewski, Sean Anderson, Weijie Gao

This patch adds support for a clock node to configure its parent clock
where possible.

Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
---
v2 changes: none
---
 drivers/clk/mediatek/clk-mtk.c | 79 ++++++++++++++++++++--------------
 drivers/clk/mediatek/clk-mtk.h |  2 +
 2 files changed, 48 insertions(+), 33 deletions(-)

diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c
index 7d145f4975..a537ff259f 100644
--- a/drivers/clk/mediatek/clk-mtk.c
+++ b/drivers/clk/mediatek/clk-mtk.c
@@ -42,20 +42,14 @@
  * the accurate frequency.
  */
 static ulong mtk_clk_find_parent_rate(struct clk *clk, int id,
-				      const struct driver *drv)
+				      struct udevice *pdev)
 {
 	struct clk parent = { .id = id, };
 
-	if (drv) {
-		struct udevice *dev;
-
-		if (uclass_get_device_by_driver(UCLASS_CLK, drv, &dev))
-			return -ENODEV;
-
-		parent.dev = dev;
-	} else {
+	if (pdev)
+		parent.dev = pdev;
+	else
 		parent.dev = clk->dev;
-	}
 
 	return clk_get_rate(&parent);
 }
@@ -296,7 +290,7 @@ static ulong mtk_topckgen_get_factor_rate(struct clk *clk, u32 off)
 	switch (fdiv->flags & CLK_PARENT_MASK) {
 	case CLK_PARENT_APMIXED:
 		rate = mtk_clk_find_parent_rate(clk, fdiv->parent,
-				DM_DRIVER_GET(mtk_clk_apmixedsys));
+						priv->parent);
 		break;
 	case CLK_PARENT_TOPCKGEN:
 		rate = mtk_clk_find_parent_rate(clk, fdiv->parent, NULL);
@@ -321,9 +315,18 @@ static ulong mtk_topckgen_get_mux_rate(struct clk *clk, u32 off)
 
 	if (mux->parent[index] > 0 ||
 	    (mux->parent[index] == CLK_XTAL &&
-	     priv->tree->flags & CLK_BYPASS_XTAL))
-		return mtk_clk_find_parent_rate(clk, mux->parent[index],
-						NULL);
+	     priv->tree->flags & CLK_BYPASS_XTAL)) {
+		switch (mux->flags & CLK_PARENT_MASK) {
+		case CLK_PARENT_APMIXED:
+			return mtk_clk_find_parent_rate(clk, mux->parent[index],
+							priv->parent);
+			break;
+		default:
+			return mtk_clk_find_parent_rate(clk, mux->parent[index],
+							NULL);
+			break;
+		}
+	}
 
 	return priv->tree->xtal_rate;
 }
@@ -342,7 +345,7 @@ static ulong mtk_topckgen_get_rate(struct clk *clk)
 						 priv->tree->muxes_offs);
 }
 
-static int mtk_topckgen_enable(struct clk *clk)
+static int mtk_clk_mux_enable(struct clk *clk)
 {
 	struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
 	const struct mtk_composite *mux;
@@ -375,7 +378,7 @@ static int mtk_topckgen_enable(struct clk *clk)
 	return 0;
 }
 
-static int mtk_topckgen_disable(struct clk *clk)
+static int mtk_clk_mux_disable(struct clk *clk)
 {
 	struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
 	const struct mtk_composite *mux;
@@ -401,7 +404,7 @@ static int mtk_topckgen_disable(struct clk *clk)
 	return 0;
 }
 
-static int mtk_topckgen_set_parent(struct clk *clk, struct clk *parent)
+static int mtk_common_clk_set_parent(struct clk *clk, struct clk *parent)
 {
 	struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
 
@@ -473,19 +476,7 @@ static ulong mtk_clk_gate_get_rate(struct clk *clk)
 	struct mtk_cg_priv *priv = dev_get_priv(clk->dev);
 	const struct mtk_gate *gate = &priv->gates[clk->id];
 
-	switch (gate->flags & CLK_PARENT_MASK) {
-	case CLK_PARENT_APMIXED:
-		return mtk_clk_find_parent_rate(clk, gate->parent,
-				DM_DRIVER_GET(mtk_clk_apmixedsys));
-		break;
-	case CLK_PARENT_TOPCKGEN:
-		return mtk_clk_find_parent_rate(clk, gate->parent,
-				DM_DRIVER_GET(mtk_clk_topckgen));
-		break;
-
-	default:
-		return priv->tree->xtal_rate;
-	}
+	return mtk_clk_find_parent_rate(clk, gate->parent, priv->parent);
 }
 
 const struct clk_ops mtk_clk_apmixedsys_ops = {
@@ -496,10 +487,10 @@ const struct clk_ops mtk_clk_apmixedsys_ops = {
 };
 
 const struct clk_ops mtk_clk_topckgen_ops = {
-	.enable = mtk_topckgen_enable,
-	.disable = mtk_topckgen_disable,
+	.enable = mtk_clk_mux_enable,
+	.disable = mtk_clk_mux_disable,
 	.get_rate = mtk_topckgen_get_rate,
-	.set_parent = mtk_topckgen_set_parent,
+	.set_parent = mtk_common_clk_set_parent,
 };
 
 const struct clk_ops mtk_clk_gate_ops = {
@@ -512,11 +503,22 @@ int mtk_common_clk_init(struct udevice *dev,
 			const struct mtk_clk_tree *tree)
 {
 	struct mtk_clk_priv *priv = dev_get_priv(dev);
+	struct udevice *parent;
+	int ret;
 
 	priv->base = dev_read_addr_ptr(dev);
 	if (!priv->base)
 		return -ENOENT;
 
+	ret = uclass_get_device_by_phandle(UCLASS_CLK, dev, "clock-parent", &parent);
+	if (ret || !parent) {
+		ret = uclass_get_device_by_driver(UCLASS_CLK,
+				DM_DRIVER_GET(mtk_clk_apmixedsys), &parent);
+		if (ret || !parent)
+			return -ENOENT;
+	}
+
+	priv->parent = parent;
 	priv->tree = tree;
 
 	return 0;
@@ -527,11 +529,22 @@ int mtk_common_clk_gate_init(struct udevice *dev,
 			     const struct mtk_gate *gates)
 {
 	struct mtk_cg_priv *priv = dev_get_priv(dev);
+	struct udevice *parent;
+	int ret;
 
 	priv->base = dev_read_addr_ptr(dev);
 	if (!priv->base)
 		return -ENOENT;
 
+	ret = uclass_get_device_by_phandle(UCLASS_CLK, dev, "clock-parent", &parent);
+	if (ret || !parent) {
+		ret = uclass_get_device_by_driver(UCLASS_CLK,
+				DM_DRIVER_GET(mtk_clk_topckgen), &parent);
+		if (ret || !parent)
+			return -ENOENT;
+	}
+
+	priv->parent = parent;
 	priv->tree = tree;
 	priv->gates = gates;
 
diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
index e0c5550c80..41854879c6 100644
--- a/drivers/clk/mediatek/clk-mtk.h
+++ b/drivers/clk/mediatek/clk-mtk.h
@@ -206,11 +206,13 @@ struct mtk_clk_tree {
 };
 
 struct mtk_clk_priv {
+	struct udevice *parent;
 	void __iomem *base;
 	const struct mtk_clk_tree *tree;
 };
 
 struct mtk_cg_priv {
+	struct udevice *parent;
 	void __iomem *base;
 	const struct mtk_clk_tree *tree;
 	const struct mtk_gate *gates;
-- 
2.17.1


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

* [PATCH v2 24/32] clk: mediatek: add infrasys clock mux support
  2022-08-31 11:00 [PATCH v2 00/32] Add support for MediaTek MT7981/MT7986 SoCs - v2 Weijie Gao
                   ` (22 preceding siblings ...)
  2022-08-31 11:05 ` [PATCH v2 23/32] clk: mediatek: add support to configure clock driver parent Weijie Gao
@ 2022-08-31 11:05 ` Weijie Gao
  2022-09-01  0:27   ` Daniel Golle
  2022-08-31 11:05 ` [PATCH v2 25/32] clk: mediatek: add CLK_XTAL support for clock driver Weijie Gao
                   ` (7 subsequent siblings)
  31 siblings, 1 reply; 60+ messages in thread
From: Weijie Gao @ 2022-08-31 11:05 UTC (permalink / raw)
  To: u-boot; +Cc: GSS_MTK_Uboot_upstream, Lukasz Majewski, Sean Anderson, Weijie Gao

This patch adds infrasys clock mux support for mediatek clock drivers.

Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
---
v2 changes:
  Fix the if condition of CLK_BYPASS_XTAL
---
 drivers/clk/mediatek/clk-mtk.c | 71 ++++++++++++++++++++++++++++++++++
 drivers/clk/mediatek/clk-mtk.h |  4 +-
 2 files changed, 74 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c
index a537ff259f..207a4c6b11 100644
--- a/drivers/clk/mediatek/clk-mtk.c
+++ b/drivers/clk/mediatek/clk-mtk.c
@@ -303,6 +303,24 @@ static ulong mtk_topckgen_get_factor_rate(struct clk *clk, u32 off)
 	return mtk_factor_recalc_rate(fdiv, rate);
 }
 
+static ulong mtk_infrasys_get_factor_rate(struct clk *clk, u32 off)
+{
+	struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
+	const struct mtk_fixed_factor *fdiv = &priv->tree->fdivs[off];
+	ulong rate;
+
+	switch (fdiv->flags & CLK_PARENT_MASK) {
+	case CLK_PARENT_TOPCKGEN:
+		rate = mtk_clk_find_parent_rate(clk, fdiv->parent,
+						priv->parent);
+		break;
+	default:
+		rate = mtk_clk_find_parent_rate(clk, fdiv->parent, NULL);
+	}
+
+	return mtk_factor_recalc_rate(fdiv, rate);
+}
+
 static ulong mtk_topckgen_get_mux_rate(struct clk *clk, u32 off)
 {
 	struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
@@ -331,6 +349,33 @@ static ulong mtk_topckgen_get_mux_rate(struct clk *clk, u32 off)
 	return priv->tree->xtal_rate;
 }
 
+static ulong mtk_infrasys_get_mux_rate(struct clk *clk, u32 off)
+{
+	struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
+	const struct mtk_composite *mux = &priv->tree->muxes[off];
+	u32 index;
+
+	index = readl(priv->base + mux->mux_reg);
+	index &= mux->mux_mask << mux->mux_shift;
+	index = index >> mux->mux_shift;
+
+	if (mux->parent[index] > 0 ||
+	    (mux->parent[index] == CLK_XTAL &&
+	     priv->tree->flags & CLK_BYPASS_XTAL)) {
+		switch (mux->flags & CLK_PARENT_MASK) {
+		case CLK_PARENT_TOPCKGEN:
+			return mtk_clk_find_parent_rate(clk, mux->parent[index],
+							priv->parent);
+			break;
+		default:
+			return mtk_clk_find_parent_rate(clk, mux->parent[index],
+							NULL);
+			break;
+		}
+	}
+	return 0;
+}
+
 static ulong mtk_topckgen_get_rate(struct clk *clk)
 {
 	struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
@@ -345,6 +390,25 @@ static ulong mtk_topckgen_get_rate(struct clk *clk)
 						 priv->tree->muxes_offs);
 }
 
+static ulong mtk_infrasys_get_rate(struct clk *clk)
+{
+	struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
+
+	ulong rate;
+
+	if (clk->id < priv->tree->fdivs_offs) {
+		rate = priv->tree->fclks[clk->id].rate;
+	} else if (clk->id < priv->tree->muxes_offs) {
+		rate = mtk_infrasys_get_factor_rate(clk, clk->id -
+						    priv->tree->fdivs_offs);
+	} else {
+		rate = mtk_infrasys_get_mux_rate(clk, clk->id -
+						 priv->tree->muxes_offs);
+	}
+
+	return rate;
+}
+
 static int mtk_clk_mux_enable(struct clk *clk)
 {
 	struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
@@ -493,6 +557,13 @@ const struct clk_ops mtk_clk_topckgen_ops = {
 	.set_parent = mtk_common_clk_set_parent,
 };
 
+const struct clk_ops mtk_clk_infrasys_ops = {
+	.enable = mtk_clk_mux_enable,
+	.disable = mtk_clk_mux_disable,
+	.get_rate = mtk_infrasys_get_rate,
+	.set_parent = mtk_common_clk_set_parent,
+};
+
 const struct clk_ops mtk_clk_gate_ops = {
 	.enable = mtk_clk_gate_enable,
 	.disable = mtk_clk_gate_disable,
diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
index 41854879c6..e7c61ae483 100644
--- a/drivers/clk/mediatek/clk-mtk.h
+++ b/drivers/clk/mediatek/clk-mtk.h
@@ -28,7 +28,8 @@
 
 #define CLK_PARENT_APMIXED		BIT(4)
 #define CLK_PARENT_TOPCKGEN		BIT(5)
-#define CLK_PARENT_MASK			GENMASK(5, 4)
+#define CLK_PARENT_INFRASYS		BIT(6)
+#define CLK_PARENT_MASK			GENMASK(6, 4)
 
 #define ETHSYS_HIFSYS_RST_CTRL_OFS	0x34
 
@@ -220,6 +221,7 @@ struct mtk_cg_priv {
 
 extern const struct clk_ops mtk_clk_apmixedsys_ops;
 extern const struct clk_ops mtk_clk_topckgen_ops;
+extern const struct clk_ops mtk_clk_infrasys_ops;
 extern const struct clk_ops mtk_clk_gate_ops;
 
 int mtk_common_clk_init(struct udevice *dev,
-- 
2.17.1


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

* [PATCH v2 25/32] clk: mediatek: add CLK_XTAL support for clock driver
  2022-08-31 11:00 [PATCH v2 00/32] Add support for MediaTek MT7981/MT7986 SoCs - v2 Weijie Gao
                   ` (23 preceding siblings ...)
  2022-08-31 11:05 ` [PATCH v2 24/32] clk: mediatek: add infrasys clock mux support Weijie Gao
@ 2022-08-31 11:05 ` Weijie Gao
  2022-08-31 13:46   ` Simon Glass
  2022-09-01  0:27   ` Daniel Golle
  2022-08-31 11:05 ` [PATCH v2 26/32] clk: mediatek: add clock driver support for MediaTek MT7986 SoC Weijie Gao
                   ` (6 subsequent siblings)
  31 siblings, 2 replies; 60+ messages in thread
From: Weijie Gao @ 2022-08-31 11:05 UTC (permalink / raw)
  To: u-boot; +Cc: GSS_MTK_Uboot_upstream, Lukasz Majewski, Sean Anderson, Weijie Gao

This adds the CLK_XTAL macro/flag to allow modeling clocks which are
directly connected to the xtal clock.

Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
---
v2 changes:
  Fix incorrect fallback in mtk_infrasys_get_factor_rate
  Fix commit description
---
 drivers/clk/mediatek/clk-mtk.c | 4 ++++
 drivers/clk/mediatek/clk-mtk.h | 3 ++-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c
index 207a4c6b11..4303300d3a 100644
--- a/drivers/clk/mediatek/clk-mtk.c
+++ b/drivers/clk/mediatek/clk-mtk.c
@@ -296,6 +296,7 @@ static ulong mtk_topckgen_get_factor_rate(struct clk *clk, u32 off)
 		rate = mtk_clk_find_parent_rate(clk, fdiv->parent, NULL);
 		break;
 
+	case CLK_PARENT_XTAL:
 	default:
 		rate = priv->tree->xtal_rate;
 	}
@@ -314,6 +315,9 @@ static ulong mtk_infrasys_get_factor_rate(struct clk *clk, u32 off)
 		rate = mtk_clk_find_parent_rate(clk, fdiv->parent,
 						priv->parent);
 		break;
+	case CLK_PARENT_XTAL:
+		rate = priv->tree->xtal_rate;
+		break;
 	default:
 		rate = mtk_clk_find_parent_rate(clk, fdiv->parent, NULL);
 	}
diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
index e7c61ae483..48ce16484e 100644
--- a/drivers/clk/mediatek/clk-mtk.h
+++ b/drivers/clk/mediatek/clk-mtk.h
@@ -29,7 +29,8 @@
 #define CLK_PARENT_APMIXED		BIT(4)
 #define CLK_PARENT_TOPCKGEN		BIT(5)
 #define CLK_PARENT_INFRASYS		BIT(6)
-#define CLK_PARENT_MASK			GENMASK(6, 4)
+#define CLK_PARENT_XTAL			BIT(7)
+#define CLK_PARENT_MASK			GENMASK(7, 4)
 
 #define ETHSYS_HIFSYS_RST_CTRL_OFS	0x34
 
-- 
2.17.1


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

* [PATCH v2 26/32] clk: mediatek: add clock driver support for MediaTek MT7986 SoC
  2022-08-31 11:00 [PATCH v2 00/32] Add support for MediaTek MT7981/MT7986 SoCs - v2 Weijie Gao
                   ` (24 preceding siblings ...)
  2022-08-31 11:05 ` [PATCH v2 25/32] clk: mediatek: add CLK_XTAL support for clock driver Weijie Gao
@ 2022-08-31 11:05 ` Weijie Gao
  2022-09-01  0:28   ` Daniel Golle
  2022-08-31 11:05 ` [PATCH v2 27/32] clk: mediatek: add clock driver support for MediaTek MT7981 SoC Weijie Gao
                   ` (5 subsequent siblings)
  31 siblings, 1 reply; 60+ messages in thread
From: Weijie Gao @ 2022-08-31 11:05 UTC (permalink / raw)
  To: u-boot; +Cc: GSS_MTK_Uboot_upstream, Lukasz Majewski, Sean Anderson, Weijie Gao

This patch adds clock driver support for MediaTek MT7986 SoC

Reviewed-by: Sean Anderson <seanga2@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
---
v2 changes:
  Fix coding style
---
 drivers/clk/mediatek/Makefile          |   1 +
 drivers/clk/mediatek/clk-mt7986.c      | 672 +++++++++++++++++++++++++
 include/dt-bindings/clock/mt7986-clk.h | 249 +++++++++
 3 files changed, 922 insertions(+)
 create mode 100644 drivers/clk/mediatek/clk-mt7986.c
 create mode 100644 include/dt-bindings/clock/mt7986-clk.h

diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index 522e724221..1aa38215bf 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_MT8512) += clk-mt8512.o
 obj-$(CONFIG_TARGET_MT7623) += clk-mt7623.o
 obj-$(CONFIG_TARGET_MT7622) += clk-mt7622.o
 obj-$(CONFIG_TARGET_MT7629) += clk-mt7629.o
+obj-$(CONFIG_TARGET_MT7986) += clk-mt7986.o
 obj-$(CONFIG_TARGET_MT8183) += clk-mt8183.o
 obj-$(CONFIG_TARGET_MT8516) += clk-mt8516.o
 obj-$(CONFIG_TARGET_MT8518) += clk-mt8518.o
diff --git a/drivers/clk/mediatek/clk-mt7986.c b/drivers/clk/mediatek/clk-mt7986.c
new file mode 100644
index 0000000000..b3fa63fc0a
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt7986.c
@@ -0,0 +1,672 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MediaTek clock driver for MT7986 SoC
+ *
+ * Copyright (C) 2022 MediaTek Inc.
+ * Author: Sam Shih <sam.shih@mediatek.com>
+ */
+
+#include <dm.h>
+#include <log.h>
+#include <asm/arch-mediatek/reset.h>
+#include <asm/io.h>
+#include <dt-bindings/clock/mt7986-clk.h>
+#include <linux/bitops.h>
+
+#include "clk-mtk.h"
+
+#define MT7986_CLK_PDN 0x250
+#define MT7986_CLK_PDN_EN_WRITE BIT(31)
+
+#define PLL_FACTOR(_id, _name, _parent, _mult, _div)                           \
+	FACTOR(_id, _parent, _mult, _div, CLK_PARENT_APMIXED)
+
+#define TOP_FACTOR(_id, _name, _parent, _mult, _div)                           \
+	FACTOR(_id, _parent, _mult, _div, CLK_PARENT_TOPCKGEN)
+
+#define INFRA_FACTOR(_id, _name, _parent, _mult, _div)                         \
+	FACTOR(_id, _parent, _mult, _div, CLK_PARENT_INFRASYS)
+
+/* FIXED PLLS */
+static const struct mtk_fixed_clk fixed_pll_clks[] = {
+	FIXED_CLK(CK_APMIXED_ARMPLL, CLK_XTAL, 2000000000),
+	FIXED_CLK(CK_APMIXED_NET2PLL, CLK_XTAL, 800000000),
+	FIXED_CLK(CK_APMIXED_MMPLL, CLK_XTAL, 1440000000),
+	FIXED_CLK(CK_APMIXED_SGMPLL, CLK_XTAL, 325000000),
+	FIXED_CLK(CK_APMIXED_WEDMCUPLL, CLK_XTAL, 760000000),
+	FIXED_CLK(CK_APMIXED_NET1PLL, CLK_XTAL, 2500000000),
+	FIXED_CLK(CK_APMIXED_MPLL, CLK_XTAL, 416000000),
+	FIXED_CLK(CK_APMIXED_APLL2, CLK_XTAL, 196608000),
+};
+
+/* TOPCKGEN FIXED CLK */
+static const struct mtk_fixed_clk top_fixed_clks[] = {
+	FIXED_CLK(CK_TOP_CB_CKSQ_40M, CLK_XTAL, 40000000),
+};
+
+/* TOPCKGEN FIXED DIV */
+static const struct mtk_fixed_factor top_fixed_divs[] = {
+	PLL_FACTOR(CK_TOP_CB_M_416M, "cb_m_416m", CK_APMIXED_MPLL, 1, 1),
+	PLL_FACTOR(CK_TOP_CB_M_D2, "cb_m_d2", CK_APMIXED_MPLL, 1, 2),
+	PLL_FACTOR(CK_TOP_CB_M_D4, "cb_m_d4", CK_APMIXED_MPLL, 1, 4),
+	PLL_FACTOR(CK_TOP_CB_M_D8, "cb_m_d8", CK_APMIXED_MPLL, 1, 8),
+	PLL_FACTOR(CK_TOP_M_D8_D2, "m_d8_d2", CK_APMIXED_MPLL, 1, 16),
+	PLL_FACTOR(CK_TOP_M_D3_D2, "m_d3_d2", CK_APMIXED_MPLL, 1, 2),
+	PLL_FACTOR(CK_TOP_CB_MM_D2, "cb_mm_d2", CK_APMIXED_MMPLL, 1, 2),
+	PLL_FACTOR(CK_TOP_CB_MM_D4, "cb_mm_d4", CK_APMIXED_MMPLL, 1, 4),
+	PLL_FACTOR(CK_TOP_CB_MM_D8, "cb_mm_d8", CK_APMIXED_MMPLL, 1, 8),
+	PLL_FACTOR(CK_TOP_MM_D8_D2, "mm_d8_d2", CK_APMIXED_MMPLL, 1, 16),
+	PLL_FACTOR(CK_TOP_MM_D3_D8, "mm_d3_d8", CK_APMIXED_MMPLL, 1, 8),
+	PLL_FACTOR(CK_TOP_CB_U2_PHYD_CK, "cb_u2_phyd", CK_APMIXED_MMPLL, 1, 30),
+	PLL_FACTOR(CK_TOP_CB_APLL2_196M, "cb_apll2_196m", CK_APMIXED_APLL2, 1,
+		   1),
+	PLL_FACTOR(CK_TOP_APLL2_D4, "apll2_d4", CK_APMIXED_APLL2, 1, 4),
+	PLL_FACTOR(CK_TOP_CB_NET1_D4, "cb_net1_d4", CK_APMIXED_NET1PLL, 1, 4),
+	PLL_FACTOR(CK_TOP_CB_NET1_D5, "cb_net1_d5", CK_APMIXED_NET1PLL, 1, 5),
+	PLL_FACTOR(CK_TOP_NET1_D5_D2, "net1_d5_d2", CK_APMIXED_NET1PLL, 1, 10),
+	PLL_FACTOR(CK_TOP_NET1_D5_D4, "net1_d5_d4", CK_APMIXED_NET1PLL, 1, 20),
+	PLL_FACTOR(CK_TOP_NET1_D8_D2, "net1_d8_d2", CK_APMIXED_NET1PLL, 1, 16),
+	PLL_FACTOR(CK_TOP_NET1_D8_D4, "net1_d8_d4", CK_APMIXED_NET1PLL, 1, 32),
+	PLL_FACTOR(CK_TOP_CB_NET2_800M, "cb_net2_800m", CK_APMIXED_NET2PLL, 1,
+		   1),
+	PLL_FACTOR(CK_TOP_CB_NET2_D4, "cb_net2_d4", CK_APMIXED_NET2PLL, 1, 4),
+	PLL_FACTOR(CK_TOP_NET2_D4_D2, "net2_d4_d2", CK_APMIXED_NET2PLL, 1, 8),
+	PLL_FACTOR(CK_TOP_NET2_D3_D2, "net2_d3_d2", CK_APMIXED_NET2PLL, 1, 2),
+	PLL_FACTOR(CK_TOP_CB_WEDMCU_760M, "cb_wedmcu_760m",
+		   CK_APMIXED_WEDMCUPLL, 1, 1),
+	PLL_FACTOR(CK_TOP_WEDMCU_D5_D2, "wedmcu_d5_d2", CK_APMIXED_WEDMCUPLL, 1,
+		   10),
+	PLL_FACTOR(CK_TOP_CB_SGM_325M, "cb_sgm_325m", CK_APMIXED_SGMPLL, 1, 1),
+	TOP_FACTOR(CK_TOP_CB_CKSQ_40M_D2, "cb_cksq_40m_d2", CK_TOP_CB_CKSQ_40M,
+		   1, 2),
+	TOP_FACTOR(CK_TOP_CB_RTC_32K, "cb_rtc_32k", CK_TOP_CB_CKSQ_40M, 1,
+		   1250),
+	TOP_FACTOR(CK_TOP_CB_RTC_32P7K, "cb_rtc_32p7k", CK_TOP_CB_CKSQ_40M, 1,
+		   1220),
+	TOP_FACTOR(CK_TOP_NFI1X, "nfi1x", CK_TOP_NFI1X_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_USB_EQ_RX250M, "usb_eq_rx250m", CK_TOP_CB_CKSQ_40M, 1,
+		   1),
+	TOP_FACTOR(CK_TOP_USB_TX250M, "usb_tx250m", CK_TOP_CB_CKSQ_40M, 1, 1),
+	TOP_FACTOR(CK_TOP_USB_LN0_CK, "usb_ln0", CK_TOP_CB_CKSQ_40M, 1, 1),
+	TOP_FACTOR(CK_TOP_USB_CDR_CK, "usb_cdr", CK_TOP_CB_CKSQ_40M, 1, 1),
+	TOP_FACTOR(CK_TOP_SPINFI_BCK, "spinfi_bck", CK_TOP_SPINFI_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_I2C_BCK, "i2c_bck", CK_TOP_I2C_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_PEXTP_TL, "pextp_tl", CK_TOP_PEXTP_TL_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_EMMC_250M, "emmc_250m", CK_TOP_EMMC_250M_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_EMMC_416M, "emmc_416m", CK_TOP_EMMC_416M_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_F_26M_ADC_CK, "f_26m_adc", CK_TOP_F_26M_ADC_SEL, 1,
+		   1),
+	TOP_FACTOR(CK_TOP_SYSAXI, "sysaxi", CK_TOP_SYSAXI_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_NETSYS_WED_MCU, "netsys_wed_mcu",
+		   CK_TOP_NETSYS_MCU_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_NETSYS_2X, "netsys_2x", CK_TOP_NETSYS_2X_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_SGM_325M, "sgm_325m", CK_TOP_SGM_325M_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_A1SYS, "a1sys", CK_TOP_A1SYS_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_EIP_B, "eip_b", CK_TOP_EIP_B_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_F26M, "csw_f26m", CK_TOP_F26M_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_AUD_L, "aud_l", CK_TOP_AUD_L_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_A_TUNER, "a_tuner", CK_TOP_A_TUNER_SEL, 2, 1),
+	TOP_FACTOR(CK_TOP_U2U3_REF, "u2u3_ref", CK_TOP_U2U3_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_U2U3_SYS, "u2u3_sys", CK_TOP_U2U3_SYS_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_U2U3_XHCI, "u2u3_xhci", CK_TOP_U2U3_XHCI_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_AP2CNN_HOST, "ap2cnn_host", CK_TOP_AP2CNN_HOST_SEL, 1,
+		   1),
+};
+
+/* TOPCKGEN MUX PARENTS */
+static const int nfi1x_parents[] = { CK_TOP_CB_CKSQ_40M,  CK_TOP_CB_MM_D8,
+				     CK_TOP_NET1_D8_D2,   CK_TOP_NET2_D3_D2,
+				     CK_TOP_CB_M_D4,      CK_TOP_MM_D8_D2,
+				     CK_TOP_WEDMCU_D5_D2, CK_TOP_CB_M_D8 };
+
+static const int spinfi_parents[] = {
+	CK_TOP_CB_CKSQ_40M_D2, CK_TOP_CB_CKSQ_40M, CK_TOP_NET1_D5_D4,
+	CK_TOP_CB_M_D4,	CK_TOP_MM_D8_D2,    CK_TOP_WEDMCU_D5_D2,
+	CK_TOP_MM_D3_D8,       CK_TOP_CB_M_D8
+};
+
+static const int spi_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_M_D2,
+				   CK_TOP_CB_MM_D8,    CK_TOP_NET1_D8_D2,
+				   CK_TOP_NET2_D3_D2,  CK_TOP_NET1_D5_D4,
+				   CK_TOP_CB_M_D4,     CK_TOP_WEDMCU_D5_D2 };
+
+static const int uart_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_M_D8,
+				    CK_TOP_M_D8_D2 };
+
+static const int pwm_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_NET1_D8_D2,
+				   CK_TOP_NET1_D5_D4, CK_TOP_CB_M_D4 };
+
+static const int i2c_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_NET1_D5_D4,
+				   CK_TOP_CB_M_D4, CK_TOP_NET1_D8_D4 };
+
+static const int pextp_tl_ck_parents[] = { CK_TOP_CB_CKSQ_40M,
+					   CK_TOP_NET1_D5_D4, CK_TOP_NET2_D4_D2,
+					   CK_TOP_CB_RTC_32K };
+
+static const int emmc_250m_parents[] = { CK_TOP_CB_CKSQ_40M,
+					 CK_TOP_NET1_D5_D2 };
+
+static const int emmc_416m_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_M_416M };
+
+static const int f_26m_adc_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_M_D8_D2 };
+
+static const int dramc_md32_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_M_D2 };
+
+static const int sysaxi_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_NET1_D8_D2,
+				      CK_TOP_CB_NET2_D4 };
+
+static const int sysapb_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_M_D3_D2,
+				      CK_TOP_NET2_D4_D2 };
+
+static const int arm_db_main_parents[] = { CK_TOP_CB_CKSQ_40M,
+					   CK_TOP_NET2_D3_D2 };
+
+static const int arm_db_jtsel_parents[] = { -1, CK_TOP_CB_CKSQ_40M };
+
+static const int netsys_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_MM_D4 };
+
+static const int netsys_500m_parents[] = { CK_TOP_CB_CKSQ_40M,
+					   CK_TOP_CB_NET1_D5 };
+
+static const int netsys_mcu_parents[] = { CK_TOP_CB_CKSQ_40M,
+					  CK_TOP_CB_WEDMCU_760M,
+					  CK_TOP_CB_MM_D2, CK_TOP_CB_NET1_D4,
+					  CK_TOP_CB_NET1_D5 };
+
+static const int netsys_2x_parents[] = { CK_TOP_CB_CKSQ_40M,
+					 CK_TOP_CB_NET2_800M,
+					 CK_TOP_CB_WEDMCU_760M,
+					 CK_TOP_CB_MM_D2 };
+
+static const int sgm_325m_parents[] = { CK_TOP_CB_CKSQ_40M,
+					CK_TOP_CB_SGM_325M };
+
+static const int sgm_reg_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_NET1_D8_D4 };
+
+static const int a1sys_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_APLL2_D4 };
+
+static const int conn_mcusys_parents[] = { CK_TOP_CB_CKSQ_40M,
+					   CK_TOP_CB_MM_D2 };
+
+static const int eip_b_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_NET2_800M };
+
+static const int aud_l_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_APLL2_196M,
+				     CK_TOP_M_D8_D2 };
+
+static const int a_tuner_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_APLL2_D4,
+				       CK_TOP_M_D8_D2 };
+
+static const int u2u3_sys_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_NET1_D5_D4 };
+
+static const int da_u2_refsel_parents[] = { CK_TOP_CB_CKSQ_40M,
+					    CK_TOP_CB_U2_PHYD_CK };
+
+#define TOP_MUX(_id, _name, _parents, _mux_ofs, _mux_set_ofs, _mux_clr_ofs,    \
+		_shift, _width, _gate, _upd_ofs, _upd)                         \
+	{                                                                      \
+		.id = _id, .mux_reg = _mux_ofs, .mux_set_reg = _mux_set_ofs,   \
+		.mux_clr_reg = _mux_clr_ofs, .upd_reg = _upd_ofs,              \
+		.upd_shift = _upd, .mux_shift = _shift,                        \
+		.mux_mask = BIT(_width) - 1, .gate_reg = _mux_ofs,             \
+		.gate_shift = _gate, .parent = _parents,                       \
+		.num_parents = ARRAY_SIZE(_parents),                           \
+		.flags = CLK_MUX_SETCLR_UPD,                                   \
+	}
+
+/* TOPCKGEN MUX_GATE */
+static const struct mtk_composite top_muxes[] = {
+	/* CLK_CFG_0 */
+	TOP_MUX(CK_TOP_NFI1X_SEL, "nfi1x_sel", nfi1x_parents, 0x000, 0x004,
+		0x008, 0, 3, 7, 0x1C0, 0),
+	TOP_MUX(CK_TOP_SPINFI_SEL, "spinfi_sel", spinfi_parents, 0x000, 0x004,
+		0x008, 8, 3, 15, 0x1C0, 1),
+	TOP_MUX(CK_TOP_SPI_SEL, "spi_sel", spi_parents, 0x000, 0x004, 0x008, 16,
+		3, 23, 0x1C0, 2),
+	TOP_MUX(CK_TOP_SPIM_MST_SEL, "spim_mst_sel", spi_parents, 0x000, 0x004,
+		0x008, 24, 3, 31, 0x1C0, 3),
+	/* CLK_CFG_1 */
+	TOP_MUX(CK_TOP_UART_SEL, "uart_sel", uart_parents, 0x010, 0x014, 0x018,
+		0, 2, 7, 0x1C0, 4),
+	TOP_MUX(CK_TOP_PWM_SEL, "pwm_sel", pwm_parents, 0x010, 0x014, 0x018, 8,
+		2, 15, 0x1C0, 5),
+	TOP_MUX(CK_TOP_I2C_SEL, "i2c_sel", i2c_parents, 0x010, 0x014, 0x018, 16,
+		2, 23, 0x1C0, 6),
+	TOP_MUX(CK_TOP_PEXTP_TL_SEL, "pextp_tl_ck_sel", pextp_tl_ck_parents,
+		0x010, 0x014, 0x018, 24, 2, 31, 0x1C0, 7),
+	/* CLK_CFG_2 */
+	TOP_MUX(CK_TOP_EMMC_250M_SEL, "emmc_250m_sel", emmc_250m_parents, 0x020,
+		0x024, 0x028, 0, 1, 7, 0x1C0, 8),
+	TOP_MUX(CK_TOP_EMMC_416M_SEL, "emmc_416m_sel", emmc_416m_parents, 0x020,
+		0x024, 0x028, 8, 1, 15, 0x1C0, 9),
+	TOP_MUX(CK_TOP_F_26M_ADC_SEL, "f_26m_adc_sel", f_26m_adc_parents, 0x020,
+		0x024, 0x028, 16, 1, 23, 0x1C0, 10),
+	TOP_MUX(CK_TOP_DRAMC_SEL, "dramc_sel", f_26m_adc_parents, 0x020, 0x024,
+		0x028, 24, 1, 31, 0x1C0, 11),
+	/* CLK_CFG_3 */
+	TOP_MUX(CK_TOP_DRAMC_MD32_SEL, "dramc_md32_sel", dramc_md32_parents,
+		0x030, 0x034, 0x038, 0, 1, 7, 0x1C0, 12),
+	TOP_MUX(CK_TOP_SYSAXI_SEL, "sysaxi_sel", sysaxi_parents, 0x030, 0x034,
+		0x038, 8, 2, 15, 0x1C0, 13),
+	TOP_MUX(CK_TOP_SYSAPB_SEL, "sysapb_sel", sysapb_parents, 0x030, 0x034,
+		0x038, 16, 2, 23, 0x1C0, 14),
+	TOP_MUX(CK_TOP_ARM_DB_MAIN_SEL, "arm_db_main_sel", arm_db_main_parents,
+		0x030, 0x034, 0x038, 24, 1, 31, 0x1C0, 15),
+	/* CLK_CFG_4 */
+	TOP_MUX(CK_TOP_ARM_DB_JTSEL, "arm_db_jtsel", arm_db_jtsel_parents,
+		0x040, 0x044, 0x048, 0, 1, 7, 0x1C0, 16),
+	TOP_MUX(CK_TOP_NETSYS_SEL, "netsys_sel", netsys_parents, 0x040, 0x044,
+		0x048, 8, 1, 15, 0x1C0, 17),
+	TOP_MUX(CK_TOP_NETSYS_500M_SEL, "netsys_500m_sel", netsys_500m_parents,
+		0x040, 0x044, 0x048, 16, 1, 23, 0x1C0, 18),
+	TOP_MUX(CK_TOP_NETSYS_MCU_SEL, "netsys_mcu_sel", netsys_mcu_parents,
+		0x040, 0x044, 0x048, 24, 3, 31, 0x1C0, 19),
+	/* CLK_CFG_5 */
+	TOP_MUX(CK_TOP_NETSYS_2X_SEL, "netsys_2x_sel", netsys_2x_parents, 0x050,
+		0x054, 0x058, 0, 2, 7, 0x1C0, 20),
+	TOP_MUX(CK_TOP_SGM_325M_SEL, "sgm_325m_sel", sgm_325m_parents, 0x050,
+		0x054, 0x058, 8, 1, 15, 0x1C0, 21),
+	TOP_MUX(CK_TOP_SGM_REG_SEL, "sgm_reg_sel", sgm_reg_parents, 0x050,
+		0x054, 0x058, 16, 1, 23, 0x1C0, 22),
+	TOP_MUX(CK_TOP_A1SYS_SEL, "a1sys_sel", a1sys_parents, 0x050, 0x054,
+		0x058, 24, 1, 31, 0x1C0, 23),
+	/* CLK_CFG_6 */
+	TOP_MUX(CK_TOP_CONN_MCUSYS_SEL, "conn_mcusys_sel", conn_mcusys_parents,
+		0x060, 0x064, 0x068, 0, 1, 7, 0x1C0, 24),
+	TOP_MUX(CK_TOP_EIP_B_SEL, "eip_b_sel", eip_b_parents, 0x060, 0x064,
+		0x068, 8, 1, 15, 0x1C0, 25),
+	TOP_MUX(CK_TOP_PCIE_PHY_SEL, "pcie_phy_sel", f_26m_adc_parents, 0x060,
+		0x064, 0x068, 16, 1, 23, 0x1C0, 26),
+	TOP_MUX(CK_TOP_USB3_PHY_SEL, "usb3_phy_sel", f_26m_adc_parents, 0x060,
+		0x064, 0x068, 24, 1, 31, 0x1C0, 27),
+	/* CLK_CFG_7 */
+	TOP_MUX(CK_TOP_F26M_SEL, "csw_f26m_sel", f_26m_adc_parents, 0x070,
+		0x074, 0x078, 0, 1, 7, 0x1C0, 28),
+	TOP_MUX(CK_TOP_AUD_L_SEL, "aud_l_sel", aud_l_parents, 0x070, 0x074,
+		0x078, 8, 2, 15, 0x1C0, 29),
+	TOP_MUX(CK_TOP_A_TUNER_SEL, "a_tuner_sel", a_tuner_parents, 0x070,
+		0x074, 0x078, 16, 2, 23, 0x1C0, 30),
+	TOP_MUX(CK_TOP_U2U3_SEL, "u2u3_sel", f_26m_adc_parents, 0x070, 0x074,
+		0x078, 24, 1, 31, 0x1C4, 0),
+	/* CLK_CFG_8 */
+	TOP_MUX(CK_TOP_U2U3_SYS_SEL, "u2u3_sys_sel", u2u3_sys_parents, 0x080,
+		0x084, 0x088, 0, 1, 7, 0x1C4, 1),
+	TOP_MUX(CK_TOP_U2U3_XHCI_SEL, "u2u3_xhci_sel", u2u3_sys_parents, 0x080,
+		0x084, 0x088, 8, 1, 15, 0x1C4, 2),
+	TOP_MUX(CK_TOP_DA_U2_REFSEL, "da_u2_refsel", da_u2_refsel_parents,
+		0x080, 0x084, 0x088, 16, 1, 23, 0x1C4, 3),
+	TOP_MUX(CK_TOP_DA_U2_CK_1P_SEL, "da_u2_ck_1p_sel", da_u2_refsel_parents,
+		0x080, 0x084, 0x088, 24, 1, 31, 0x1C4, 4),
+	/* CLK_CFG_9 */
+	TOP_MUX(CK_TOP_AP2CNN_HOST_SEL, "ap2cnn_host_sel", sgm_reg_parents,
+		0x090, 0x094, 0x098, 0, 1, 7, 0x1C4, 5),
+};
+
+/* INFRA FIXED DIV */
+static const struct mtk_fixed_factor infra_fixed_divs[] = {
+	TOP_FACTOR(CK_INFRA_CK_F26M, "infra_ck_f26m", CK_TOP_F26M_SEL, 1, 1),
+	TOP_FACTOR(CK_INFRA_UART, "infra_uart", CK_TOP_UART_SEL, 1, 1),
+	TOP_FACTOR(CK_INFRA_ISPI0, "infra_ispi0", CK_TOP_SPI_SEL, 1, 1),
+	TOP_FACTOR(CK_INFRA_I2C, "infra_i2c", CK_TOP_I2C_SEL, 1, 1),
+	TOP_FACTOR(CK_INFRA_ISPI1, "infra_ispi1", CK_TOP_SPINFI_SEL, 1, 1),
+	TOP_FACTOR(CK_INFRA_PWM, "infra_pwm", CK_TOP_PWM_SEL, 1, 1),
+	TOP_FACTOR(CK_INFRA_66M_MCK, "infra_66m_mck", CK_TOP_SYSAXI_SEL, 1, 2),
+	TOP_FACTOR(CK_INFRA_CK_F32K, "infra_ck_f32k", CK_TOP_CB_RTC_32P7K, 1,
+		   1),
+	TOP_FACTOR(CK_INFRA_PCIE_CK, "infra_pcie", CK_TOP_PEXTP_TL_SEL, 1, 1),
+	INFRA_FACTOR(CK_INFRA_PWM_BCK, "infra_pwm_bck", CK_INFRA_PWM_BSEL, 1,
+		     1),
+	INFRA_FACTOR(CK_INFRA_PWM_CK1, "infra_pwm_ck1", CK_INFRA_PWM1_SEL, 1,
+		     1),
+	INFRA_FACTOR(CK_INFRA_PWM_CK2, "infra_pwm_ck2", CK_INFRA_PWM2_SEL, 1,
+		     1),
+	TOP_FACTOR(CK_INFRA_133M_HCK, "infra_133m_hck", CK_TOP_SYSAXI, 1, 1),
+	TOP_FACTOR(CK_INFRA_EIP_CK, "infra_eip", CK_TOP_EIP_B, 1, 1),
+	INFRA_FACTOR(CK_INFRA_66M_PHCK, "infra_66m_phck", CK_INFRA_133M_HCK, 1,
+		     1),
+	TOP_FACTOR(CK_INFRA_FAUD_L_CK, "infra_faud_l", CK_TOP_AUD_L, 1, 1),
+	TOP_FACTOR(CK_INFRA_FAUD_AUD_CK, "infra_faud_aud", CK_TOP_A1SYS, 1, 1),
+	TOP_FACTOR(CK_INFRA_FAUD_EG2_CK, "infra_faud_eg2", CK_TOP_A_TUNER, 1,
+		   1),
+	TOP_FACTOR(CK_INFRA_I2CS_CK, "infra_i2cs", CK_TOP_I2C_BCK, 1, 1),
+	INFRA_FACTOR(CK_INFRA_MUX_UART0, "infra_mux_uart0", CK_INFRA_UART0_SEL,
+		     1, 1),
+	INFRA_FACTOR(CK_INFRA_MUX_UART1, "infra_mux_uart1", CK_INFRA_UART1_SEL,
+		     1, 1),
+	INFRA_FACTOR(CK_INFRA_MUX_UART2, "infra_mux_uart2", CK_INFRA_UART2_SEL,
+		     1, 1),
+	TOP_FACTOR(CK_INFRA_NFI_CK, "infra_nfi", CK_TOP_NFI1X, 1, 1),
+	TOP_FACTOR(CK_INFRA_SPINFI_CK, "infra_spinfi", CK_TOP_SPINFI_BCK, 1, 1),
+	INFRA_FACTOR(CK_INFRA_MUX_SPI0, "infra_mux_spi0", CK_INFRA_SPI0_SEL, 1,
+		     1),
+	INFRA_FACTOR(CK_INFRA_MUX_SPI1, "infra_mux_spi1", CK_INFRA_SPI1_SEL, 1,
+		     1),
+	TOP_FACTOR(CK_INFRA_RTC_32K, "infra_rtc_32k", CK_TOP_CB_RTC_32K, 1, 1),
+	TOP_FACTOR(CK_INFRA_FMSDC_CK, "infra_fmsdc", CK_TOP_EMMC_416M, 1, 1),
+	TOP_FACTOR(CK_INFRA_FMSDC_HCK_CK, "infra_fmsdc_hck", CK_TOP_EMMC_250M,
+		   1, 1),
+	TOP_FACTOR(CK_INFRA_PERI_133M, "infra_peri_133m", CK_TOP_SYSAXI, 1, 1),
+	TOP_FACTOR(CK_INFRA_133M_PHCK, "infra_133m_phck", CK_TOP_SYSAXI, 1, 1),
+	TOP_FACTOR(CK_INFRA_USB_SYS_CK, "infra_usb_sys", CK_TOP_U2U3_SYS, 1, 1),
+	TOP_FACTOR(CK_INFRA_USB_CK, "infra_usb", CK_TOP_U2U3_REF, 1, 1),
+	TOP_FACTOR(CK_INFRA_USB_XHCI_CK, "infra_usb_xhci", CK_TOP_U2U3_XHCI, 1,
+		   1),
+	TOP_FACTOR(CK_INFRA_PCIE_GFMUX_TL_O_PRE, "infra_pcie_mux",
+		   CK_TOP_PEXTP_TL, 1, 1),
+	TOP_FACTOR(CK_INFRA_F26M_CK0, "infra_f26m_ck0", CK_TOP_F26M, 1, 1),
+	TOP_FACTOR(CK_INFRA_HD_133M, "infra_hd_133m", CK_TOP_SYSAXI, 1, 1),
+};
+
+/* INFRASYS MUX PARENTS */
+static const int infra_uart0_parents[] = { CK_INFRA_CK_F26M, CK_INFRA_UART };
+
+static const int infra_spi0_parents[] = { CK_INFRA_I2C, CK_INFRA_ISPI0 };
+
+static const int infra_spi1_parents[] = { CK_INFRA_I2C, CK_INFRA_ISPI1 };
+
+static const int infra_pwm_bsel_parents[] = { CK_INFRA_CK_F32K,
+					      CK_INFRA_CK_F26M,
+					      CK_INFRA_66M_MCK, CK_INFRA_PWM };
+
+static const int infra_pcie_parents[] = { CK_INFRA_CK_F32K, CK_INFRA_CK_F26M,
+					  -1, CK_INFRA_PCIE_CK };
+
+#define INFRA_MUX(_id, _name, _parents, _reg, _shift, _width)                  \
+	{                                                                      \
+		.id = _id, .mux_reg = (_reg) + 0x8,                            \
+		.mux_set_reg = (_reg) + 0x0, .mux_clr_reg = (_reg) + 0x4,      \
+		.mux_shift = _shift, .mux_mask = BIT(_width) - 1,              \
+		.parent = _parents, .num_parents = ARRAY_SIZE(_parents),       \
+		.flags = CLK_MUX_SETCLR_UPD | CLK_PARENT_INFRASYS,             \
+	}
+
+/* INFRA MUX */
+
+static const struct mtk_composite infra_muxes[] = {
+	/* MODULE_CLK_SEL_0 */
+	INFRA_MUX(CK_INFRA_UART0_SEL, "infra_uart0_sel", infra_uart0_parents,
+		  0x10, 0, 1),
+	INFRA_MUX(CK_INFRA_UART1_SEL, "infra_uart1_sel", infra_uart0_parents,
+		  0x10, 1, 1),
+	INFRA_MUX(CK_INFRA_UART2_SEL, "infra_uart2_sel", infra_uart0_parents,
+		  0x10, 2, 1),
+	INFRA_MUX(CK_INFRA_SPI0_SEL, "infra_spi0_sel", infra_spi0_parents, 0x10,
+		  4, 1),
+	INFRA_MUX(CK_INFRA_SPI1_SEL, "infra_spi1_sel", infra_spi1_parents, 0x10,
+		  5, 1),
+	INFRA_MUX(CK_INFRA_PWM1_SEL, "infra_pwm1_sel", infra_pwm_bsel_parents,
+		  0x10, 9, 2),
+	INFRA_MUX(CK_INFRA_PWM2_SEL, "infra_pwm2_sel", infra_pwm_bsel_parents,
+		  0x10, 11, 2),
+	INFRA_MUX(CK_INFRA_PWM_BSEL, "infra_pwm_bsel", infra_pwm_bsel_parents,
+		  0x10, 13, 2),
+	/* MODULE_CLK_SEL_1 */
+	INFRA_MUX(CK_INFRA_PCIE_SEL, "infra_pcie_sel", infra_pcie_parents, 0x20,
+		  0, 2),
+};
+
+static const struct mtk_gate_regs infra_0_cg_regs = {
+	.set_ofs = 0x40,
+	.clr_ofs = 0x44,
+	.sta_ofs = 0x48,
+};
+
+static const struct mtk_gate_regs infra_1_cg_regs = {
+	.set_ofs = 0x50,
+	.clr_ofs = 0x54,
+	.sta_ofs = 0x58,
+};
+
+static const struct mtk_gate_regs infra_2_cg_regs = {
+	.set_ofs = 0x60,
+	.clr_ofs = 0x64,
+	.sta_ofs = 0x68,
+};
+
+#define GATE_INFRA0(_id, _name, _parent, _shift)                               \
+	{                                                                      \
+		.id = _id, .parent = _parent, .regs = &infra_0_cg_regs,        \
+		.shift = _shift,                                               \
+		.flags = CLK_GATE_SETCLR | CLK_PARENT_INFRASYS,                \
+	}
+
+#define GATE_INFRA1(_id, _name, _parent, _shift)                               \
+	{                                                                      \
+		.id = _id, .parent = _parent, .regs = &infra_1_cg_regs,        \
+		.shift = _shift,                                               \
+		.flags = CLK_GATE_SETCLR | CLK_PARENT_INFRASYS,                \
+	}
+
+#define GATE_INFRA2(_id, _name, _parent, _shift)                               \
+	{                                                                      \
+		.id = _id, .parent = _parent, .regs = &infra_2_cg_regs,        \
+		.shift = _shift,                                               \
+		.flags = CLK_GATE_SETCLR | CLK_PARENT_INFRASYS,                \
+	}
+
+/* INFRA GATE */
+
+static const struct mtk_gate infracfg_ao_gates[] = {
+	/* INFRA0 */
+	GATE_INFRA0(CK_INFRA_GPT_STA, "infra_gpt_sta", CK_INFRA_66M_MCK, 0),
+	GATE_INFRA0(CK_INFRA_PWM_HCK, "infra_pwm_hck", CK_INFRA_66M_MCK, 1),
+	GATE_INFRA0(CK_INFRA_PWM_STA, "infra_pwm_sta", CK_INFRA_PWM_BCK, 2),
+	GATE_INFRA0(CK_INFRA_PWM1_CK, "infra_pwm1", CK_INFRA_PWM_CK1, 3),
+	GATE_INFRA0(CK_INFRA_PWM2_CK, "infra_pwm2", CK_INFRA_PWM_CK2, 4),
+	GATE_INFRA0(CK_INFRA_CQ_DMA_CK, "infra_cq_dma", CK_INFRA_133M_HCK, 6),
+	GATE_INFRA0(CK_INFRA_EIP97_CK, "infra_eip97", CK_INFRA_EIP_CK, 7),
+	GATE_INFRA0(CK_INFRA_AUD_BUS_CK, "infra_aud_bus", CK_INFRA_66M_PHCK, 8),
+	GATE_INFRA0(CK_INFRA_AUD_26M_CK, "infra_aud_26m", CK_INFRA_CK_F26M, 9),
+	GATE_INFRA0(CK_INFRA_AUD_L_CK, "infra_aud_l", CK_INFRA_FAUD_L_CK, 10),
+	GATE_INFRA0(CK_INFRA_AUD_AUD_CK, "infra_aud_aud", CK_INFRA_FAUD_AUD_CK,
+		    11),
+	GATE_INFRA0(CK_INFRA_AUD_EG2_CK, "infra_aud_eg2", CK_INFRA_FAUD_EG2_CK,
+		    13),
+	GATE_INFRA0(CK_INFRA_DRAMC_26M_CK, "infra_dramc_26m", CK_INFRA_CK_F26M,
+		    14),
+	GATE_INFRA0(CK_INFRA_DBG_CK, "infra_dbg", CK_INFRA_66M_MCK, 15),
+	GATE_INFRA0(CK_INFRA_AP_DMA_CK, "infra_ap_dma", CK_INFRA_66M_MCK, 16),
+	GATE_INFRA0(CK_INFRA_SEJ_CK, "infra_sej", CK_INFRA_66M_MCK, 24),
+	GATE_INFRA0(CK_INFRA_SEJ_13M_CK, "infra_sej_13m", CK_INFRA_CK_F26M, 25),
+	GATE_INFRA0(CK_INFRA_TRNG_CK, "infra_trng", CK_INFRA_HD_133M, 26),
+	/* INFRA1 */
+	GATE_INFRA1(CK_INFRA_THERM_CK, "infra_therm", CK_INFRA_CK_F26M, 0),
+	GATE_INFRA1(CK_INFRA_I2CO_CK, "infra_i2co", CK_INFRA_I2CS_CK, 1),
+	GATE_INFRA1(CK_INFRA_UART0_CK, "infra_uart0", CK_INFRA_MUX_UART0, 2),
+	GATE_INFRA1(CK_INFRA_UART1_CK, "infra_uart1", CK_INFRA_MUX_UART1, 3),
+	GATE_INFRA1(CK_INFRA_UART2_CK, "infra_uart2", CK_INFRA_MUX_UART2, 4),
+	GATE_INFRA1(CK_INFRA_NFI1_CK, "infra_nfi1", CK_INFRA_NFI_CK, 8),
+	GATE_INFRA1(CK_INFRA_SPINFI1_CK, "infra_spinfi1", CK_INFRA_SPINFI_CK,
+		    9),
+	GATE_INFRA1(CK_INFRA_NFI_HCK_CK, "infra_nfi_hck", CK_INFRA_66M_MCK, 10),
+	GATE_INFRA1(CK_INFRA_SPI0_CK, "infra_spi0", CK_INFRA_MUX_SPI0, 11),
+	GATE_INFRA1(CK_INFRA_SPI1_CK, "infra_spi1", CK_INFRA_MUX_SPI1, 12),
+	GATE_INFRA1(CK_INFRA_SPI0_HCK_CK, "infra_spi0_hck", CK_INFRA_66M_MCK,
+		    13),
+	GATE_INFRA1(CK_INFRA_SPI1_HCK_CK, "infra_spi1_hck", CK_INFRA_66M_MCK,
+		    14),
+	GATE_INFRA1(CK_INFRA_FRTC_CK, "infra_frtc", CK_INFRA_RTC_32K, 15),
+	GATE_INFRA1(CK_INFRA_MSDC_CK, "infra_msdc", CK_INFRA_FMSDC_CK, 16),
+	GATE_INFRA1(CK_INFRA_MSDC_HCK_CK, "infra_msdc_hck",
+		    CK_INFRA_FMSDC_HCK_CK, 17),
+	GATE_INFRA1(CK_INFRA_MSDC_133M_CK, "infra_msdc_133m",
+		    CK_INFRA_PERI_133M, 18),
+	GATE_INFRA1(CK_INFRA_MSDC_66M_CK, "infra_msdc_66m", CK_INFRA_66M_PHCK,
+		    19),
+	GATE_INFRA1(CK_INFRA_ADC_26M_CK, "infra_adc_26m", CK_INFRA_CK_F26M, 20),
+	GATE_INFRA1(CK_INFRA_ADC_FRC_CK, "infra_adc_frc", CK_INFRA_CK_F26M, 21),
+	GATE_INFRA1(CK_INFRA_FBIST2FPC_CK, "infra_fbist2fpc", CK_INFRA_NFI_CK,
+		    23),
+	/* INFRA2 */
+	GATE_INFRA2(CK_INFRA_IUSB_133_CK, "infra_iusb_133", CK_INFRA_133M_PHCK,
+		    0),
+	GATE_INFRA2(CK_INFRA_IUSB_66M_CK, "infra_iusb_66m", CK_INFRA_66M_PHCK,
+		    1),
+	GATE_INFRA2(CK_INFRA_IUSB_SYS_CK, "infra_iusb_sys", CK_INFRA_USB_SYS_CK,
+		    2),
+	GATE_INFRA2(CK_INFRA_IUSB_CK, "infra_iusb", CK_INFRA_USB_CK, 3),
+	GATE_INFRA2(CK_INFRA_IPCIE_CK, "infra_ipcie", CK_INFRA_PCIE_CK, 13),
+	GATE_INFRA2(CK_INFRA_IPCIER_CK, "infra_ipcier", CK_INFRA_F26M_CK0, 15),
+	GATE_INFRA2(CK_INFRA_IPCIEB_CK, "infra_ipcieb", CK_INFRA_133M_PHCK, 15),
+};
+
+static const struct mtk_clk_tree mt7986_fixed_pll_clk_tree = {
+	.fdivs_offs = CLK_APMIXED_NR_CLK,
+	.xtal_rate = 40 * MHZ,
+	.fclks = fixed_pll_clks,
+};
+
+static const struct mtk_clk_tree mt7986_topckgen_clk_tree = {
+	.fdivs_offs = CK_TOP_CB_M_416M,
+	.muxes_offs = CK_TOP_NFI1X_SEL,
+	.fclks = top_fixed_clks,
+	.fdivs = top_fixed_divs,
+	.muxes = top_muxes,
+	.flags = CLK_BYPASS_XTAL,
+};
+
+static const struct mtk_clk_tree mt7986_infracfg_clk_tree = {
+	.fdivs_offs = CK_INFRA_CK_F26M,
+	.muxes_offs = CK_INFRA_UART0_SEL,
+	.fdivs = infra_fixed_divs,
+	.muxes = infra_muxes,
+};
+
+static const struct udevice_id mt7986_fixed_pll_compat[] = {
+	{ .compatible = "mediatek,mt7986-fixed-plls" },
+	{}
+};
+
+static const struct udevice_id mt7986_topckgen_compat[] = {
+	{ .compatible = "mediatek,mt7986-topckgen" },
+	{}
+};
+
+static int mt7986_fixed_pll_probe(struct udevice *dev)
+{
+	return mtk_common_clk_init(dev, &mt7986_fixed_pll_clk_tree);
+}
+
+static int mt7986_topckgen_probe(struct udevice *dev)
+{
+	struct mtk_clk_priv *priv = dev_get_priv(dev);
+
+	priv->base = dev_read_addr_ptr(dev);
+	writel(MT7986_CLK_PDN_EN_WRITE, priv->base + MT7986_CLK_PDN);
+
+	return mtk_common_clk_init(dev, &mt7986_topckgen_clk_tree);
+}
+
+U_BOOT_DRIVER(mtk_clk_apmixedsys) = {
+	.name = "mt7986-clock-fixed-pll",
+	.id = UCLASS_CLK,
+	.of_match = mt7986_fixed_pll_compat,
+	.probe = mt7986_fixed_pll_probe,
+	.priv_auto = sizeof(struct mtk_clk_priv),
+	.ops = &mtk_clk_topckgen_ops,
+	.flags = DM_FLAG_PRE_RELOC,
+};
+
+U_BOOT_DRIVER(mtk_clk_topckgen) = {
+	.name = "mt7986-clock-topckgen",
+	.id = UCLASS_CLK,
+	.of_match = mt7986_topckgen_compat,
+	.probe = mt7986_topckgen_probe,
+	.priv_auto = sizeof(struct mtk_clk_priv),
+	.ops = &mtk_clk_topckgen_ops,
+	.flags = DM_FLAG_PRE_RELOC,
+};
+
+static const struct udevice_id mt7986_infracfg_compat[] = {
+	{ .compatible = "mediatek,mt7986-infracfg" },
+	{}
+};
+
+static const struct udevice_id mt7986_infracfg_ao_compat[] = {
+	{ .compatible = "mediatek,mt7986-infracfg_ao" },
+	{}
+};
+
+static int mt7986_infracfg_probe(struct udevice *dev)
+{
+	return mtk_common_clk_init(dev, &mt7986_infracfg_clk_tree);
+}
+
+static int mt7986_infracfg_ao_probe(struct udevice *dev)
+{
+	return mtk_common_clk_gate_init(dev, &mt7986_infracfg_clk_tree,
+					infracfg_ao_gates);
+}
+
+U_BOOT_DRIVER(mtk_clk_infracfg) = {
+	.name = "mt7986-clock-infracfg",
+	.id = UCLASS_CLK,
+	.of_match = mt7986_infracfg_compat,
+	.probe = mt7986_infracfg_probe,
+	.priv_auto = sizeof(struct mtk_clk_priv),
+	.ops = &mtk_clk_infrasys_ops,
+	.flags = DM_FLAG_PRE_RELOC,
+};
+
+U_BOOT_DRIVER(mtk_clk_infracfg_ao) = {
+	.name = "mt7986-clock-infracfg-ao",
+	.id = UCLASS_CLK,
+	.of_match = mt7986_infracfg_ao_compat,
+	.probe = mt7986_infracfg_ao_probe,
+	.priv_auto = sizeof(struct mtk_cg_priv),
+	.ops = &mtk_clk_gate_ops,
+	.flags = DM_FLAG_PRE_RELOC,
+};
+
+/* ethsys */
+static const struct mtk_gate_regs eth_cg_regs = {
+	.sta_ofs = 0x30,
+};
+
+#define GATE_ETH(_id, _name, _parent, _shift)                                  \
+	{                                                                      \
+		.id = _id, .parent = _parent, .regs = &eth_cg_regs,            \
+		.shift = _shift,                                               \
+		.flags = CLK_GATE_NO_SETCLR_INV | CLK_PARENT_TOPCKGEN,         \
+	}
+
+static const struct mtk_gate eth_cgs[] = {
+	GATE_ETH(CK_ETH_FE_EN, "eth_fe_en", CK_TOP_NETSYS_2X, 7),
+	GATE_ETH(CK_ETH_GP2_EN, "eth_gp2_en", CK_TOP_SGM_325M, 8),
+	GATE_ETH(CK_ETH_GP1_EN, "eth_gp1_en", CK_TOP_SGM_325M, 8),
+	GATE_ETH(CK_ETH_WOCPU1_EN, "eth_wocpu1_en", CK_TOP_NETSYS_WED_MCU, 14),
+	GATE_ETH(CK_ETH_WOCPU0_EN, "eth_wocpu0_en", CK_TOP_NETSYS_WED_MCU, 15),
+};
+
+static int mt7986_ethsys_probe(struct udevice *dev)
+{
+	return mtk_common_clk_gate_init(dev, &mt7986_topckgen_clk_tree,
+					eth_cgs);
+}
+
+static int mt7986_ethsys_bind(struct udevice *dev)
+{
+	int ret = 0;
+
+	if (CONFIG_IS_ENABLED(RESET_MEDIATEK)) {
+		ret = mediatek_reset_bind(dev, ETHSYS_HIFSYS_RST_CTRL_OFS, 1);
+		if (ret)
+			debug("Warning: failed to bind reset controller\n");
+	}
+
+	return ret;
+}
+
+static const struct udevice_id mt7986_ethsys_compat[] = {
+	{ .compatible = "mediatek,mt7986-ethsys" },
+	{ }
+};
+
+U_BOOT_DRIVER(mtk_clk_ethsys) = {
+	.name = "mt7986-clock-ethsys",
+	.id = UCLASS_CLK,
+	.of_match = mt7986_ethsys_compat,
+	.probe = mt7986_ethsys_probe,
+	.bind = mt7986_ethsys_bind,
+	.priv_auto = sizeof(struct mtk_cg_priv),
+	.ops = &mtk_clk_gate_ops,
+};
diff --git a/include/dt-bindings/clock/mt7986-clk.h b/include/dt-bindings/clock/mt7986-clk.h
new file mode 100644
index 0000000000..820f863183
--- /dev/null
+++ b/include/dt-bindings/clock/mt7986-clk.h
@@ -0,0 +1,249 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2022 MediaTek Inc. All rights reserved.
+ *
+ * Author: Sam Shih <sam.shih@mediatek.com>
+ */
+
+#ifndef _DT_BINDINGS_CLK_MT7986_H
+#define _DT_BINDINGS_CLK_MT7986_H
+
+/* INFRACFG */
+
+#define CK_INFRA_CK_F26M		0
+#define CK_INFRA_UART			1
+#define CK_INFRA_ISPI0			2
+#define CK_INFRA_I2C			3
+#define CK_INFRA_ISPI1			4
+#define CK_INFRA_PWM			5
+#define CK_INFRA_66M_MCK		6
+#define CK_INFRA_CK_F32K		7
+#define CK_INFRA_PCIE_CK		8
+#define CK_INFRA_PWM_BCK		9
+#define CK_INFRA_PWM_CK1		10
+#define CK_INFRA_PWM_CK2		11
+#define CK_INFRA_133M_HCK		12
+#define CK_INFRA_EIP_CK			13
+#define CK_INFRA_66M_PHCK		14
+#define CK_INFRA_FAUD_L_CK		15
+#define CK_INFRA_FAUD_AUD_CK		17
+#define CK_INFRA_FAUD_EG2_CK		17
+#define CK_INFRA_I2CS_CK		18
+#define CK_INFRA_MUX_UART0		19
+#define CK_INFRA_MUX_UART1		20
+#define CK_INFRA_MUX_UART2		21
+#define CK_INFRA_NFI_CK			22
+#define CK_INFRA_SPINFI_CK		23
+#define CK_INFRA_MUX_SPI0		24
+#define CK_INFRA_MUX_SPI1		25
+#define CK_INFRA_RTC_32K		26
+#define CK_INFRA_FMSDC_CK		27
+#define CK_INFRA_FMSDC_HCK_CK		28
+#define CK_INFRA_PERI_133M		29
+#define CK_INFRA_133M_PHCK		30
+#define CK_INFRA_USB_SYS_CK		31
+#define CK_INFRA_USB_CK			32
+#define CK_INFRA_USB_XHCI_CK		33
+#define CK_INFRA_PCIE_GFMUX_TL_O_PRE	34
+#define CK_INFRA_F26M_CK0		35
+#define CK_INFRA_HD_133M		36
+#define CLK_INFRA_NR_CLK		37
+
+/* TOPCKGEN */
+
+#define CK_TOP_CB_CKSQ_40M		0
+#define CK_TOP_CB_M_416M		1
+#define CK_TOP_CB_M_D2			2
+#define CK_TOP_CB_M_D4			3
+#define CK_TOP_CB_M_D8			4
+#define CK_TOP_M_D8_D2			5
+#define CK_TOP_M_D3_D2			6
+#define CK_TOP_CB_MM_D2			7
+#define CK_TOP_CB_MM_D4			8
+#define CK_TOP_CB_MM_D8			9
+#define CK_TOP_MM_D8_D2			10
+#define CK_TOP_MM_D3_D8			11
+#define CK_TOP_CB_U2_PHYD_CK		12
+#define CK_TOP_CB_APLL2_196M		13
+#define CK_TOP_APLL2_D4			14
+#define CK_TOP_CB_NET1_D4		15
+#define CK_TOP_CB_NET1_D5		16
+#define CK_TOP_NET1_D5_D2		17
+#define CK_TOP_NET1_D5_D4		18
+#define CK_TOP_NET1_D8_D2		19
+#define CK_TOP_NET1_D8_D4		20
+#define CK_TOP_CB_NET2_800M		21
+#define CK_TOP_CB_NET2_D4		22
+#define CK_TOP_NET2_D4_D2		23
+#define CK_TOP_NET2_D3_D2		24
+#define CK_TOP_CB_WEDMCU_760M		25
+#define CK_TOP_WEDMCU_D5_D2		26
+#define CK_TOP_CB_SGM_325M		27
+#define CK_TOP_CB_CKSQ_40M_D2		28
+#define CK_TOP_CB_RTC_32K		29
+#define CK_TOP_CB_RTC_32P7K		30
+#define CK_TOP_NFI1X			31
+#define CK_TOP_USB_EQ_RX250M		32
+#define CK_TOP_USB_TX250M		33
+#define CK_TOP_USB_LN0_CK		34
+#define CK_TOP_USB_CDR_CK		35
+#define CK_TOP_SPINFI_BCK		36
+#define CK_TOP_I2C_BCK			37
+#define CK_TOP_PEXTP_TL			38
+#define CK_TOP_EMMC_250M		39
+#define CK_TOP_EMMC_416M		40
+#define CK_TOP_F_26M_ADC_CK		41
+#define CK_TOP_SYSAXI			42
+#define CK_TOP_NETSYS_WED_MCU		43
+#define CK_TOP_NETSYS_2X		44
+#define CK_TOP_SGM_325M			45
+#define CK_TOP_A1SYS			46
+#define CK_TOP_EIP_B			47
+#define CK_TOP_F26M			48
+#define CK_TOP_AUD_L			49
+#define CK_TOP_A_TUNER			50
+#define CK_TOP_U2U3_REF			51
+#define CK_TOP_U2U3_SYS			52
+#define CK_TOP_U2U3_XHCI		53
+#define CK_TOP_AP2CNN_HOST		54
+#define CK_TOP_NFI1X_SEL		55
+#define CK_TOP_SPINFI_SEL		56
+#define CK_TOP_SPI_SEL			57
+#define CK_TOP_SPIM_MST_SEL		58
+#define CK_TOP_UART_SEL			59
+#define CK_TOP_PWM_SEL			60
+#define CK_TOP_I2C_SEL			61
+#define CK_TOP_PEXTP_TL_SEL		62
+#define CK_TOP_EMMC_250M_SEL		63
+#define CK_TOP_EMMC_416M_SEL		64
+#define CK_TOP_F_26M_ADC_SEL		65
+#define CK_TOP_DRAMC_SEL		66
+#define CK_TOP_DRAMC_MD32_SEL		67
+#define CK_TOP_SYSAXI_SEL		68
+#define CK_TOP_SYSAPB_SEL		69
+#define CK_TOP_ARM_DB_MAIN_SEL		70
+#define CK_TOP_ARM_DB_JTSEL		71
+#define CK_TOP_NETSYS_SEL		72
+#define CK_TOP_NETSYS_500M_SEL		73
+#define CK_TOP_NETSYS_MCU_SEL		74
+#define CK_TOP_NETSYS_2X_SEL		75
+#define CK_TOP_SGM_325M_SEL		76
+#define CK_TOP_SGM_REG_SEL		77
+#define CK_TOP_A1SYS_SEL		78
+#define CK_TOP_CONN_MCUSYS_SEL		79
+#define CK_TOP_EIP_B_SEL		80
+#define CK_TOP_PCIE_PHY_SEL		81
+#define CK_TOP_USB3_PHY_SEL		82
+#define CK_TOP_F26M_SEL			83
+#define CK_TOP_AUD_L_SEL		84
+#define CK_TOP_A_TUNER_SEL		85
+#define CK_TOP_U2U3_SEL			86
+#define CK_TOP_U2U3_SYS_SEL		87
+#define CK_TOP_U2U3_XHCI_SEL		88
+#define CK_TOP_DA_U2_REFSEL		89
+#define CK_TOP_DA_U2_CK_1P_SEL		90
+#define CK_TOP_AP2CNN_HOST_SEL		91
+#define CLK_TOP_NR_CLK			92
+
+/*
+ * INFRACFG_AO
+ * clock muxes need to be append to infracfg domain, and clock gates
+ * need to be keep in infracgh_ao domain
+ */
+
+#define CK_INFRA_UART0_SEL		(0 + CLK_INFRA_NR_CLK)
+#define CK_INFRA_UART1_SEL		(1 + CLK_INFRA_NR_CLK)
+#define CK_INFRA_UART2_SEL		(2 + CLK_INFRA_NR_CLK)
+#define CK_INFRA_SPI0_SEL		(3 + CLK_INFRA_NR_CLK)
+#define CK_INFRA_SPI1_SEL		(4 + CLK_INFRA_NR_CLK)
+#define CK_INFRA_PWM1_SEL		(5 + CLK_INFRA_NR_CLK)
+#define CK_INFRA_PWM2_SEL		(6 + CLK_INFRA_NR_CLK)
+#define CK_INFRA_PWM_BSEL		(7 + CLK_INFRA_NR_CLK)
+#define CK_INFRA_PCIE_SEL		(8 + CLK_INFRA_NR_CLK)
+#define CK_INFRA_GPT_STA		0
+#define CK_INFRA_PWM_HCK		1
+#define CK_INFRA_PWM_STA		2
+#define CK_INFRA_PWM1_CK		3
+#define CK_INFRA_PWM2_CK		4
+#define CK_INFRA_CQ_DMA_CK		5
+#define CK_INFRA_EIP97_CK		6
+#define CK_INFRA_AUD_BUS_CK		7
+#define CK_INFRA_AUD_26M_CK		8
+#define CK_INFRA_AUD_L_CK		9
+#define CK_INFRA_AUD_AUD_CK		10
+#define CK_INFRA_AUD_EG2_CK		11
+#define CK_INFRA_DRAMC_26M_CK		12
+#define CK_INFRA_DBG_CK			13
+#define CK_INFRA_AP_DMA_CK		14
+#define CK_INFRA_SEJ_CK			15
+#define CK_INFRA_SEJ_13M_CK		16
+#define CK_INFRA_THERM_CK		17
+#define CK_INFRA_I2CO_CK		18
+#define CK_INFRA_TRNG_CK		19
+#define CK_INFRA_UART0_CK		20
+#define CK_INFRA_UART1_CK		21
+#define CK_INFRA_UART2_CK		22
+#define CK_INFRA_NFI1_CK		23
+#define CK_INFRA_SPINFI1_CK		24
+#define CK_INFRA_NFI_HCK_CK		25
+#define CK_INFRA_SPI0_CK		26
+#define CK_INFRA_SPI1_CK		27
+#define CK_INFRA_SPI0_HCK_CK		28
+#define CK_INFRA_SPI1_HCK_CK		29
+#define CK_INFRA_FRTC_CK		30
+#define CK_INFRA_MSDC_CK		31
+#define CK_INFRA_MSDC_HCK_CK		32
+#define CK_INFRA_MSDC_133M_CK		33
+#define CK_INFRA_MSDC_66M_CK		34
+#define CK_INFRA_ADC_26M_CK		35
+#define CK_INFRA_ADC_FRC_CK		36
+#define CK_INFRA_FBIST2FPC_CK		37
+#define CK_INFRA_IUSB_133_CK		38
+#define CK_INFRA_IUSB_66M_CK		39
+#define CK_INFRA_IUSB_SYS_CK		40
+#define CK_INFRA_IUSB_CK		41
+#define CK_INFRA_IPCIE_CK		42
+#define CK_INFRA_IPCIER_CK		43
+#define CK_INFRA_IPCIEB_CK		44
+#define CLK_INFRA_AO_NR_CLK		45
+
+/* APMIXEDSYS */
+
+#define CK_APMIXED_ARMPLL		0
+#define CK_APMIXED_NET2PLL		1
+#define CK_APMIXED_MMPLL		2
+#define CK_APMIXED_SGMPLL		3
+#define CK_APMIXED_WEDMCUPLL		4
+#define CK_APMIXED_NET1PLL		5
+#define CK_APMIXED_MPLL			6
+#define CK_APMIXED_APLL2		7
+#define CLK_APMIXED_NR_CLK		8
+
+/* SGMIISYS_0 */
+
+#define CK_SGM0_TX_EN			0
+#define CK_SGM0_RX_EN			1
+#define CK_SGM0_CK0_EN			2
+#define CK_SGM0_CDR_CK0_EN		3
+#define CLK_SGMII0_NR_CLK		4
+
+/* SGMIISYS_1 */
+
+#define CK_SGM1_TX_EN			0
+#define CK_SGM1_RX_EN			1
+#define CK_SGM1_CK1_EN			2
+#define CK_SGM1_CDR_CK1_EN		3
+#define CLK_SGMII1_NR_CLK		4
+
+/* ETHSYS */
+
+#define CK_ETH_FE_EN			0
+#define CK_ETH_GP2_EN			1
+#define CK_ETH_GP1_EN			2
+#define CK_ETH_WOCPU1_EN		3
+#define CK_ETH_WOCPU0_EN		4
+#define CLK_ETH_NR_CLK			5
+
+#endif
+
+/* _DT_BINDINGS_CLK_MT7986_H */
-- 
2.17.1


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

* [PATCH v2 27/32] clk: mediatek: add clock driver support for MediaTek MT7981 SoC
  2022-08-31 11:00 [PATCH v2 00/32] Add support for MediaTek MT7981/MT7986 SoCs - v2 Weijie Gao
                   ` (25 preceding siblings ...)
  2022-08-31 11:05 ` [PATCH v2 26/32] clk: mediatek: add clock driver support for MediaTek MT7986 SoC Weijie Gao
@ 2022-08-31 11:05 ` Weijie Gao
  2022-08-31 11:05 ` [PATCH v2 28/32] cpu: add basic cpu driver for MediaTek ARM chips Weijie Gao
                   ` (4 subsequent siblings)
  31 siblings, 0 replies; 60+ messages in thread
From: Weijie Gao @ 2022-08-31 11:05 UTC (permalink / raw)
  To: u-boot; +Cc: GSS_MTK_Uboot_upstream, Lukasz Majewski, Sean Anderson, Weijie Gao

This patch adds clock driver support for MediaTek MT7981 SoC

Reviewed-by: Sean Anderson <seanga2@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
---
v2 changes:
  Fix coding style
---
 drivers/clk/mediatek/Makefile          |   1 +
 drivers/clk/mediatek/clk-mt7981.c      | 683 +++++++++++++++++++++++++
 include/dt-bindings/clock/mt7981-clk.h | 267 ++++++++++
 3 files changed, 951 insertions(+)
 create mode 100644 drivers/clk/mediatek/clk-mt7981.c
 create mode 100644 include/dt-bindings/clock/mt7981-clk.h

diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index 1aa38215bf..1decf31a77 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_TARGET_MT7623) += clk-mt7623.o
 obj-$(CONFIG_TARGET_MT7622) += clk-mt7622.o
 obj-$(CONFIG_TARGET_MT7629) += clk-mt7629.o
 obj-$(CONFIG_TARGET_MT7986) += clk-mt7986.o
+obj-$(CONFIG_TARGET_MT7981) += clk-mt7981.o
 obj-$(CONFIG_TARGET_MT8183) += clk-mt8183.o
 obj-$(CONFIG_TARGET_MT8516) += clk-mt8516.o
 obj-$(CONFIG_TARGET_MT8518) += clk-mt8518.o
diff --git a/drivers/clk/mediatek/clk-mt7981.c b/drivers/clk/mediatek/clk-mt7981.c
new file mode 100644
index 0000000000..7fcb81419c
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt7981.c
@@ -0,0 +1,683 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MediaTek clock driver for MT7981 SoC
+ *
+ * Copyright (C) 2022 MediaTek Inc.
+ * Author: Sam Shih <sam.shih@mediatek.com>
+ */
+
+#include <dm.h>
+#include <log.h>
+#include <asm/arch-mediatek/reset.h>
+#include <asm/io.h>
+#include <dt-bindings/clock/mt7981-clk.h>
+#include <linux/bitops.h>
+
+#include "clk-mtk.h"
+
+#define MT7981_CLK_PDN 0x250
+#define MT7981_CLK_PDN_EN_WRITE BIT(31)
+
+#define PLL_FACTOR(_id, _name, _parent, _mult, _div)                           \
+	FACTOR(_id, _parent, _mult, _div, CLK_PARENT_APMIXED)
+
+#define TOP_FACTOR(_id, _name, _parent, _mult, _div)                           \
+	FACTOR(_id, _parent, _mult, _div, CLK_PARENT_TOPCKGEN)
+
+#define INFRA_FACTOR(_id, _name, _parent, _mult, _div)                         \
+	FACTOR(_id, _parent, _mult, _div, CLK_PARENT_INFRASYS)
+
+/* FIXED PLLS */
+static const struct mtk_fixed_clk fixed_pll_clks[] = {
+	FIXED_CLK(CK_APMIXED_ARMPLL, CLK_XTAL, 1300000000),
+	FIXED_CLK(CK_APMIXED_NET2PLL, CLK_XTAL, 800000000),
+	FIXED_CLK(CK_APMIXED_MMPLL, CLK_XTAL, 720000000),
+	FIXED_CLK(CK_APMIXED_SGMPLL, CLK_XTAL, 325000000),
+	FIXED_CLK(CK_APMIXED_WEDMCUPLL, CLK_XTAL, 208000000),
+	FIXED_CLK(CK_APMIXED_NET1PLL, CLK_XTAL, 2500000000),
+	FIXED_CLK(CK_APMIXED_MPLL, CLK_XTAL, 416000000),
+	FIXED_CLK(CK_APMIXED_APLL2, CLK_XTAL, 196608000),
+};
+
+/* TOPCKGEN FIXED CLK */
+static const struct mtk_fixed_clk top_fixed_clks[] = {
+	FIXED_CLK(CK_TOP_CB_CKSQ_40M, CLK_XTAL, 40000000),
+};
+
+/* TOPCKGEN FIXED DIV */
+static const struct mtk_fixed_factor top_fixed_divs[] = {
+	PLL_FACTOR(CK_TOP_CB_M_416M, "cb_m_416m", CK_APMIXED_MPLL, 1, 1),
+	PLL_FACTOR(CK_TOP_CB_M_D2, "cb_m_d2", CK_APMIXED_MPLL, 1, 2),
+	PLL_FACTOR(CK_TOP_CB_M_D3, "cb_m_d3", CK_APMIXED_MPLL, 1, 3),
+	PLL_FACTOR(CK_TOP_M_D3_D2, "m_d3_d2", CK_APMIXED_MPLL, 1, 2),
+	PLL_FACTOR(CK_TOP_CB_M_D4, "cb_m_d4", CK_APMIXED_MPLL, 1, 4),
+	PLL_FACTOR(CK_TOP_CB_M_D8, "cb_m_d8", CK_APMIXED_MPLL, 1, 8),
+	PLL_FACTOR(CK_TOP_M_D8_D2, "m_d8_d2", CK_APMIXED_MPLL, 1, 16),
+	PLL_FACTOR(CK_TOP_CB_MM_720M, "cb_mm_720m", CK_APMIXED_MMPLL, 1, 1),
+	PLL_FACTOR(CK_TOP_CB_MM_D2, "cb_mm_d2", CK_APMIXED_MMPLL, 1, 2),
+	PLL_FACTOR(CK_TOP_CB_MM_D3, "cb_mm_d3", CK_APMIXED_MMPLL, 1, 3),
+	PLL_FACTOR(CK_TOP_CB_MM_D3_D5, "cb_mm_d3_d5", CK_APMIXED_MMPLL, 1, 15),
+	PLL_FACTOR(CK_TOP_CB_MM_D4, "cb_mm_d4", CK_APMIXED_MMPLL, 1, 4),
+	PLL_FACTOR(CK_TOP_CB_MM_D6, "cb_mm_d6", CK_APMIXED_MMPLL, 1, 6),
+	PLL_FACTOR(CK_TOP_MM_D6_D2, "mm_d6_d2", CK_APMIXED_MMPLL, 1, 12),
+	PLL_FACTOR(CK_TOP_CB_MM_D8, "cb_mm_d8", CK_APMIXED_MMPLL, 1, 8),
+	PLL_FACTOR(CK_TOP_CB_APLL2_196M, "cb_apll2_196m", CK_APMIXED_APLL2, 1,
+		   1),
+	PLL_FACTOR(CK_TOP_APLL2_D2, "apll2_d2", CK_APMIXED_APLL2, 1, 2),
+	PLL_FACTOR(CK_TOP_APLL2_D4, "apll2_d4", CK_APMIXED_APLL2, 1, 4),
+	PLL_FACTOR(CK_TOP_NET1_2500M, "net1_2500m", CK_APMIXED_NET1PLL, 1, 1),
+	PLL_FACTOR(CK_TOP_CB_NET1_D4, "cb_net1_d4", CK_APMIXED_NET1PLL, 1, 4),
+	PLL_FACTOR(CK_TOP_CB_NET1_D5, "cb_net1_d5", CK_APMIXED_NET1PLL, 1, 5),
+	PLL_FACTOR(CK_TOP_NET1_D5_D2, "net1_d5_d2", CK_APMIXED_NET1PLL, 1, 10),
+	PLL_FACTOR(CK_TOP_NET1_D5_D4, "net1_d5_d4", CK_APMIXED_NET1PLL, 1, 20),
+	PLL_FACTOR(CK_TOP_CB_NET1_D8, "cb_net1_d8", CK_APMIXED_NET1PLL, 1, 8),
+	PLL_FACTOR(CK_TOP_NET1_D8_D2, "net1_d8_d2", CK_APMIXED_NET1PLL, 1, 16),
+	PLL_FACTOR(CK_TOP_NET1_D8_D4, "net1_d8_d4", CK_APMIXED_NET1PLL, 1, 32),
+	PLL_FACTOR(CK_TOP_CB_NET2_800M, "cb_net2_800m", CK_APMIXED_NET2PLL, 1,
+		   1),
+	PLL_FACTOR(CK_TOP_CB_NET2_D2, "cb_net2_d2", CK_APMIXED_NET2PLL, 1, 2),
+	PLL_FACTOR(CK_TOP_CB_NET2_D4, "cb_net2_d4", CK_APMIXED_NET2PLL, 1, 4),
+	PLL_FACTOR(CK_TOP_NET2_D4_D2, "net2_d4_d2", CK_APMIXED_NET2PLL, 1, 8),
+	PLL_FACTOR(CK_TOP_NET2_D4_D4, "net2_d4_d4", CK_APMIXED_NET2PLL, 1, 16),
+	PLL_FACTOR(CK_TOP_CB_NET2_D6, "cb_net2_d6", CK_APMIXED_NET2PLL, 1, 6),
+	PLL_FACTOR(CK_TOP_CB_WEDMCU_208M, "cb_wedmcu_208m",
+		   CK_APMIXED_WEDMCUPLL, 1, 1),
+	PLL_FACTOR(CK_TOP_CB_SGM_325M, "cb_sgm_325m", CK_APMIXED_SGMPLL, 1, 1),
+	TOP_FACTOR(CK_TOP_CKSQ_40M_D2, "cksq_40m_d2", CK_TOP_CB_CKSQ_40M, 1, 2),
+	TOP_FACTOR(CK_TOP_CB_RTC_32K, "cb_rtc_32k", CK_TOP_CB_CKSQ_40M, 1,
+		   1250),
+	TOP_FACTOR(CK_TOP_CB_RTC_32P7K, "cb_rtc_32p7k", CK_TOP_CB_CKSQ_40M, 1,
+		   1220),
+	TOP_FACTOR(CK_TOP_USB_TX250M, "usb_tx250m", CK_TOP_CB_CKSQ_40M, 1, 1),
+	TOP_FACTOR(CK_TOP_FAUD, "faud", CK_TOP_CB_CKSQ_40M, 1, 1),
+	TOP_FACTOR(CK_TOP_NFI1X, "nfi1x", CK_TOP_NFI1X_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_USB_EQ_RX250M, "usb_eq_rx250m", CK_TOP_CB_CKSQ_40M, 1,
+		   1),
+	TOP_FACTOR(CK_TOP_USB_CDR_CK, "usb_cdr", CK_TOP_CB_CKSQ_40M, 1, 1),
+	TOP_FACTOR(CK_TOP_USB_LN0_CK, "usb_ln0", CK_TOP_CB_CKSQ_40M, 1, 1),
+	TOP_FACTOR(CK_TOP_SPINFI_BCK, "spinfi_bck", CK_TOP_SPINFI_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_SPI, "spi", CK_TOP_SPI_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_SPIM_MST, "spim_mst", CK_TOP_SPIM_MST_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_UART_BCK, "uart_bck", CK_TOP_UART_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_PWM_BCK, "pwm_bck", CK_TOP_PWM_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_I2C_BCK, "i2c_bck", CK_TOP_I2C_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_PEXTP_TL, "pextp_tl", CK_TOP_PEXTP_TL_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_EMMC_208M, "emmc_208m", CK_TOP_EMMC_208M_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_EMMC_400M, "emmc_400m", CK_TOP_EMMC_400M_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_DRAMC_REF, "dramc_ref", CK_TOP_DRAMC_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_DRAMC_MD32, "dramc_md32", CK_TOP_DRAMC_MD32_SEL, 1,
+		   1),
+	TOP_FACTOR(CK_TOP_SYSAXI, "sysaxi", CK_TOP_SYSAXI_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_SYSAPB, "sysapb", CK_TOP_SYSAPB_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_ARM_DB_MAIN, "arm_db_main", CK_TOP_ARM_DB_MAIN_SEL, 1,
+		   1),
+	TOP_FACTOR(CK_TOP_AP2CNN_HOST, "ap2cnn_host", CK_TOP_AP2CNN_HOST_SEL, 1,
+		   1),
+	TOP_FACTOR(CK_TOP_NETSYS, "netsys", CK_TOP_NETSYS_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_NETSYS_500M, "netsys_500m", CK_TOP_NETSYS_500M_SEL, 1,
+		   1),
+	TOP_FACTOR(CK_TOP_NETSYS_WED_MCU, "netsys_wed_mcu",
+		   CK_TOP_NETSYS_MCU_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_NETSYS_2X, "netsys_2x", CK_TOP_NETSYS_2X_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_SGM_325M, "sgm_325m", CK_TOP_SGM_325M_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_SGM_REG, "sgm_reg", CK_TOP_SGM_REG_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_F26M, "csw_f26m", CK_TOP_F26M_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_EIP97B, "eip97b", CK_TOP_EIP97B_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_USB3_PHY, "usb3_phy", CK_TOP_USB3_PHY_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_AUD, "aud", CK_TOP_FAUD, 1, 1),
+	TOP_FACTOR(CK_TOP_A1SYS, "a1sys", CK_TOP_A1SYS_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_AUD_L, "aud_l", CK_TOP_AUD_L_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_A_TUNER, "a_tuner", CK_TOP_A_TUNER_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_U2U3_REF, "u2u3_ref", CK_TOP_U2U3_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_U2U3_SYS, "u2u3_sys", CK_TOP_U2U3_SYS_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_U2U3_XHCI, "u2u3_xhci", CK_TOP_U2U3_XHCI_SEL, 1, 1),
+	TOP_FACTOR(CK_TOP_USB_FRMCNT, "usb_frmcnt", CK_TOP_USB_FRMCNT_SEL, 1,
+		   1),
+};
+
+/* TOPCKGEN MUX PARENTS */
+static const int nfi1x_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_MM_D4,
+				     CK_TOP_NET1_D8_D2,  CK_TOP_CB_NET2_D6,
+				     CK_TOP_CB_M_D4,     CK_TOP_CB_MM_D8,
+				     CK_TOP_NET1_D8_D4,  CK_TOP_CB_M_D8 };
+
+static const int spinfi_parents[] = { CK_TOP_CKSQ_40M_D2, CK_TOP_CB_CKSQ_40M,
+				      CK_TOP_NET1_D5_D4,  CK_TOP_CB_M_D4,
+				      CK_TOP_CB_MM_D8,    CK_TOP_NET1_D8_D4,
+				      CK_TOP_MM_D6_D2,    CK_TOP_CB_M_D8 };
+
+static const int spi_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_M_D2,
+				   CK_TOP_CB_MM_D4,    CK_TOP_NET1_D8_D2,
+				   CK_TOP_CB_NET2_D6,  CK_TOP_NET1_D5_D4,
+				   CK_TOP_CB_M_D4,     CK_TOP_NET1_D8_D4 };
+
+static const int uart_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_M_D8,
+				    CK_TOP_M_D8_D2 };
+
+static const int pwm_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_NET1_D8_D2,
+				   CK_TOP_NET1_D5_D4,  CK_TOP_CB_M_D4,
+				   CK_TOP_M_D8_D2,     CK_TOP_CB_RTC_32K };
+
+static const int i2c_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_NET1_D5_D4,
+				   CK_TOP_CB_M_D4, CK_TOP_NET1_D8_D4 };
+
+static const int pextp_tl_ck_parents[] = { CK_TOP_CB_CKSQ_40M,
+					   CK_TOP_NET1_D5_D4, CK_TOP_CB_M_D4,
+					   CK_TOP_CB_RTC_32K };
+
+static const int emmc_208m_parents[] = {
+	CK_TOP_CB_CKSQ_40M,   CK_TOP_CB_M_D2,  CK_TOP_CB_NET2_D4,
+	CK_TOP_CB_APLL2_196M, CK_TOP_CB_MM_D4, CK_TOP_NET1_D8_D2,
+	CK_TOP_CB_MM_D6
+};
+
+static const int emmc_400m_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_NET2_D2,
+					 CK_TOP_CB_MM_D2, CK_TOP_CB_NET2_D2 };
+
+static const int csw_f26m_parents[] = { CK_TOP_CKSQ_40M_D2, CK_TOP_M_D8_D2 };
+
+static const int dramc_md32_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_M_D2,
+					  CK_TOP_CB_WEDMCU_208M };
+
+static const int sysaxi_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_NET1_D8_D2 };
+
+static const int sysapb_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_M_D3_D2 };
+
+static const int arm_db_main_parents[] = { CK_TOP_CB_CKSQ_40M,
+					   CK_TOP_CB_NET2_D6 };
+
+static const int ap2cnn_host_parents[] = { CK_TOP_CB_CKSQ_40M,
+					   CK_TOP_NET1_D8_D4 };
+
+static const int netsys_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_MM_D2 };
+
+static const int netsys_500m_parents[] = { CK_TOP_CB_CKSQ_40M,
+					   CK_TOP_CB_NET1_D5 };
+
+static const int netsys_mcu_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_MM_720M,
+					  CK_TOP_CB_NET1_D4, CK_TOP_CB_NET1_D5,
+					  CK_TOP_CB_M_416M };
+
+static const int netsys_2x_parents[] = { CK_TOP_CB_CKSQ_40M,
+					 CK_TOP_CB_NET2_800M,
+					 CK_TOP_CB_MM_720M };
+
+static const int sgm_325m_parents[] = { CK_TOP_CB_CKSQ_40M,
+					CK_TOP_CB_SGM_325M };
+
+static const int sgm_reg_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_NET2_D4 };
+
+static const int eip97b_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_NET1_D5,
+				      CK_TOP_CB_M_416M, CK_TOP_CB_MM_D2,
+				      CK_TOP_NET1_D5_D2 };
+
+static const int aud_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_APLL2_196M };
+
+static const int a1sys_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_APLL2_D4 };
+
+static const int aud_l_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_APLL2_196M,
+				     CK_TOP_M_D8_D2 };
+
+static const int a_tuner_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_APLL2_D4,
+				       CK_TOP_M_D8_D2 };
+
+static const int u2u3_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_M_D8_D2 };
+
+static const int u2u3_sys_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_NET1_D5_D4 };
+
+static const int usb_frmcnt_parents[] = { CK_TOP_CB_CKSQ_40M,
+					  CK_TOP_CB_MM_D3_D5 };
+
+#define TOP_MUX(_id, _name, _parents, _mux_ofs, _mux_set_ofs, _mux_clr_ofs,    \
+		_shift, _width, _gate, _upd_ofs, _upd)                         \
+	{                                                                      \
+		.id = _id, .mux_reg = _mux_ofs, .mux_set_reg = _mux_set_ofs,   \
+		.mux_clr_reg = _mux_clr_ofs, .upd_reg = _upd_ofs,              \
+		.upd_shift = _upd, .mux_shift = _shift,                        \
+		.mux_mask = BIT(_width) - 1, .gate_reg = _mux_ofs,             \
+		.gate_shift = _gate, .parent = _parents,                       \
+		.num_parents = ARRAY_SIZE(_parents),                           \
+		.flags = CLK_MUX_SETCLR_UPD,                                   \
+	}
+
+/* TOPCKGEN MUX_GATE */
+static const struct mtk_composite top_muxes[] = {
+	TOP_MUX(CK_TOP_NFI1X_SEL, "nfi1x_sel", nfi1x_parents, 0x0, 0x4, 0x8, 0,
+		3, 7, 0x1c0, 0),
+	TOP_MUX(CK_TOP_SPINFI_SEL, "spinfi_sel", spinfi_parents, 0x0, 0x4, 0x8,
+		8, 3, 15, 0x1c0, 1),
+	TOP_MUX(CK_TOP_SPI_SEL, "spi_sel", spi_parents, 0x0, 0x4, 0x8, 16, 3,
+		23, 0x1c0, 2),
+	TOP_MUX(CK_TOP_SPIM_MST_SEL, "spim_mst_sel", spi_parents, 0x0, 0x4, 0x8,
+		24, 3, 31, 0x1c0, 3),
+	TOP_MUX(CK_TOP_UART_SEL, "uart_sel", uart_parents, 0x10, 0x14, 0x18, 0,
+		2, 7, 0x1c0, 4),
+	TOP_MUX(CK_TOP_PWM_SEL, "pwm_sel", pwm_parents, 0x10, 0x14, 0x18, 8, 3,
+		15, 0x1c0, 5),
+	TOP_MUX(CK_TOP_I2C_SEL, "i2c_sel", i2c_parents, 0x10, 0x14, 0x18, 16, 2,
+		23, 0x1c0, 6),
+	TOP_MUX(CK_TOP_PEXTP_TL_SEL, "pextp_tl_ck_sel", pextp_tl_ck_parents,
+		0x10, 0x14, 0x18, 24, 2, 31, 0x1c0, 7),
+	TOP_MUX(CK_TOP_EMMC_208M_SEL, "emmc_208m_sel", emmc_208m_parents, 0x20,
+		0x24, 0x28, 0, 3, 7, 0x1c0, 8),
+	TOP_MUX(CK_TOP_EMMC_400M_SEL, "emmc_400m_sel", emmc_400m_parents, 0x20,
+		0x24, 0x28, 8, 2, 15, 0x1c0, 9),
+	TOP_MUX(CK_TOP_F26M_SEL, "csw_f26m_sel", csw_f26m_parents, 0x20, 0x24,
+		0x28, 16, 1, 23, 0x1c0, 10),
+	TOP_MUX(CK_TOP_DRAMC_SEL, "dramc_sel", csw_f26m_parents, 0x20, 0x24,
+		0x28, 24, 1, 31, 0x1c0, 11),
+	TOP_MUX(CK_TOP_DRAMC_MD32_SEL, "dramc_md32_sel", dramc_md32_parents,
+		0x30, 0x34, 0x38, 0, 2, 7, 0x1c0, 12),
+	TOP_MUX(CK_TOP_SYSAXI_SEL, "sysaxi_sel", sysaxi_parents, 0x30, 0x34,
+		0x38, 8, 1, 15, 0x1c0, 13),
+	TOP_MUX(CK_TOP_SYSAPB_SEL, "sysapb_sel", sysapb_parents, 0x30, 0x34,
+		0x38, 16, 1, 23, 0x1c0, 14),
+	TOP_MUX(CK_TOP_ARM_DB_MAIN_SEL, "arm_db_main_sel", arm_db_main_parents,
+		0x30, 0x34, 0x38, 24, 1, 31, 0x1c0, 15),
+	TOP_MUX(CK_TOP_AP2CNN_HOST_SEL, "ap2cnn_host_sel", ap2cnn_host_parents,
+		0x40, 0x44, 0x48, 0, 1, 7, 0x1c0, 16),
+	TOP_MUX(CK_TOP_NETSYS_SEL, "netsys_sel", netsys_parents, 0x40, 0x44,
+		0x48, 8, 1, 15, 0x1c0, 17),
+	TOP_MUX(CK_TOP_NETSYS_500M_SEL, "netsys_500m_sel", netsys_500m_parents,
+		0x40, 0x44, 0x48, 16, 1, 23, 0x1c0, 18),
+	TOP_MUX(CK_TOP_NETSYS_MCU_SEL, "netsys_mcu_sel", netsys_mcu_parents,
+		0x40, 0x44, 0x48, 24, 3, 31, 0x1c0, 19),
+	TOP_MUX(CK_TOP_NETSYS_2X_SEL, "netsys_2x_sel", netsys_2x_parents, 0x50,
+		0x54, 0x58, 0, 2, 7, 0x1c0, 20),
+	TOP_MUX(CK_TOP_SGM_325M_SEL, "sgm_325m_sel", sgm_325m_parents, 0x50,
+		0x54, 0x58, 8, 1, 15, 0x1c0, 21),
+	TOP_MUX(CK_TOP_SGM_REG_SEL, "sgm_reg_sel", sgm_reg_parents, 0x50, 0x54,
+		0x58, 16, 1, 23, 0x1c0, 22),
+	TOP_MUX(CK_TOP_EIP97B_SEL, "eip97b_sel", eip97b_parents, 0x50, 0x54,
+		0x58, 24, 3, 31, 0x1c0, 23),
+	TOP_MUX(CK_TOP_USB3_PHY_SEL, "usb3_phy_sel", csw_f26m_parents, 0x60,
+		0x64, 0x68, 0, 1, 7, 0x1c0, 24),
+	TOP_MUX(CK_TOP_AUD_SEL, "aud_sel", aud_parents, 0x60, 0x64, 0x68, 8, 1,
+		15, 0x1c0, 25),
+	TOP_MUX(CK_TOP_A1SYS_SEL, "a1sys_sel", a1sys_parents, 0x60, 0x64, 0x68,
+		16, 1, 23, 0x1c0, 26),
+	TOP_MUX(CK_TOP_AUD_L_SEL, "aud_l_sel", aud_l_parents, 0x60, 0x64, 0x68,
+		24, 2, 31, 0x1c0, 27),
+	TOP_MUX(CK_TOP_A_TUNER_SEL, "a_tuner_sel", a_tuner_parents, 0x70, 0x74,
+		0x78, 0, 2, 7, 0x1c0, 28),
+	TOP_MUX(CK_TOP_U2U3_SEL, "u2u3_sel", u2u3_parents, 0x70, 0x74, 0x78, 8,
+		1, 15, 0x1c0, 29),
+	TOP_MUX(CK_TOP_U2U3_SYS_SEL, "u2u3_sys_sel", u2u3_sys_parents, 0x70,
+		0x74, 0x78, 16, 1, 23, 0x1c0, 30),
+	TOP_MUX(CK_TOP_U2U3_XHCI_SEL, "u2u3_xhci_sel", u2u3_sys_parents, 0x70,
+		0x74, 0x78, 24, 1, 31, 0x1c4, 0),
+	TOP_MUX(CK_TOP_USB_FRMCNT_SEL, "usb_frmcnt_sel", usb_frmcnt_parents,
+		0x80, 0x84, 0x88, 0, 1, 7, 0x1c4, 1),
+};
+
+/* INFRA FIXED DIV */
+static const struct mtk_fixed_factor infra_fixed_divs[] = {
+	TOP_FACTOR(CK_INFRA_CK_F26M, "infra_ck_f26m", CK_TOP_F26M_SEL, 1, 1),
+	TOP_FACTOR(CK_INFRA_UART, "infra_uart", CK_TOP_UART_SEL, 1, 1),
+	TOP_FACTOR(CK_INFRA_ISPI0, "infra_ispi0", CK_TOP_SPI_SEL, 1, 1),
+	TOP_FACTOR(CK_INFRA_I2C, "infra_i2c", CK_TOP_I2C_SEL, 1, 1),
+	TOP_FACTOR(CK_INFRA_ISPI1, "infra_ispi1", CK_TOP_SPIM_MST_SEL, 1, 1),
+	TOP_FACTOR(CK_INFRA_PWM, "infra_pwm", CK_TOP_PWM_SEL, 1, 1),
+	TOP_FACTOR(CK_INFRA_66M_MCK, "infra_66m_mck", CK_TOP_SYSAXI_SEL, 1, 2),
+	TOP_FACTOR(CK_INFRA_CK_F32K, "infra_ck_f32k", CK_TOP_CB_RTC_32P7K, 1,
+		   1),
+	TOP_FACTOR(CK_INFRA_PCIE_CK, "infra_pcie", CK_TOP_PEXTP_TL_SEL, 1, 1),
+	INFRA_FACTOR(CK_INFRA_PWM_BCK, "infra_pwm_bck", CK_INFRA_PWM_BSEL, 1,
+		     1),
+	INFRA_FACTOR(CK_INFRA_PWM_CK1, "infra_pwm_ck1", CK_INFRA_PWM1_SEL, 1,
+		     1),
+	INFRA_FACTOR(CK_INFRA_PWM_CK2, "infra_pwm_ck2", CK_INFRA_PWM2_SEL, 1,
+		     1),
+	TOP_FACTOR(CK_INFRA_133M_HCK, "infra_133m_hck", CK_TOP_SYSAXI, 1, 1),
+	INFRA_FACTOR(CK_INFRA_66M_PHCK, "infra_66m_phck", CK_INFRA_133M_HCK, 1,
+		     1),
+	TOP_FACTOR(CK_INFRA_FAUD_L_CK, "infra_faud_l", CK_TOP_AUD_L, 1, 1),
+	TOP_FACTOR(CK_INFRA_FAUD_AUD_CK, "infra_faud_aud", CK_TOP_A1SYS, 1, 1),
+	TOP_FACTOR(CK_INFRA_FAUD_EG2_CK, "infra_faud_eg2", CK_TOP_A_TUNER, 1,
+		   1),
+	TOP_FACTOR(CK_INFRA_I2CS_CK, "infra_i2cs", CK_TOP_I2C_BCK, 1, 1),
+	INFRA_FACTOR(CK_INFRA_MUX_UART0, "infra_mux_uart0", CK_INFRA_UART0_SEL,
+		     1, 1),
+	INFRA_FACTOR(CK_INFRA_MUX_UART1, "infra_mux_uart1", CK_INFRA_UART1_SEL,
+		     1, 1),
+	INFRA_FACTOR(CK_INFRA_MUX_UART2, "infra_mux_uart2", CK_INFRA_UART2_SEL,
+		     1, 1),
+	TOP_FACTOR(CK_INFRA_NFI_CK, "infra_nfi", CK_TOP_NFI1X, 1, 1),
+	TOP_FACTOR(CK_INFRA_SPINFI_CK, "infra_spinfi", CK_TOP_SPINFI_BCK, 1, 1),
+	INFRA_FACTOR(CK_INFRA_MUX_SPI0, "infra_mux_spi0", CK_INFRA_SPI0_SEL, 1,
+		     1),
+	INFRA_FACTOR(CK_INFRA_MUX_SPI1, "infra_mux_spi1", CK_INFRA_SPI1_SEL, 1,
+		     1),
+	INFRA_FACTOR(CK_INFRA_MUX_SPI2, "infra_mux_spi2", CK_INFRA_SPI2_SEL, 1,
+		     1),
+	TOP_FACTOR(CK_INFRA_RTC_32K, "infra_rtc_32k", CK_TOP_CB_RTC_32K, 1, 1),
+	TOP_FACTOR(CK_INFRA_FMSDC_CK, "infra_fmsdc", CK_TOP_EMMC_400M, 1, 1),
+	TOP_FACTOR(CK_INFRA_FMSDC_HCK_CK, "infra_fmsdc_hck", CK_TOP_EMMC_208M,
+		   1, 1),
+	TOP_FACTOR(CK_INFRA_PERI_133M, "infra_peri_133m", CK_TOP_SYSAXI, 1, 1),
+	TOP_FACTOR(CK_INFRA_133M_PHCK, "infra_133m_phck", CK_TOP_SYSAXI, 1, 1),
+	TOP_FACTOR(CK_INFRA_USB_SYS_CK, "infra_usb_sys", CK_TOP_U2U3_SYS, 1, 1),
+	TOP_FACTOR(CK_INFRA_USB_CK, "infra_usb", CK_TOP_U2U3_REF, 1, 1),
+	TOP_FACTOR(CK_INFRA_USB_XHCI_CK, "infra_usb_xhci", CK_TOP_U2U3_XHCI, 1,
+		   1),
+	TOP_FACTOR(CK_INFRA_PCIE_GFMUX_TL_O_PRE, "infra_pcie_mux",
+		   CK_TOP_PEXTP_TL, 1, 1),
+	TOP_FACTOR(CK_INFRA_F26M_CK0, "infra_f26m_ck0", CK_TOP_F26M, 1, 1),
+	TOP_FACTOR(CK_INFRA_133M_MCK, "infra_133m_mck", CK_TOP_SYSAXI, 1, 1),
+};
+
+/* INFRASYS MUX PARENTS */
+static const int infra_uart0_parents[] = { CK_INFRA_CK_F26M, CK_INFRA_UART };
+
+static const int infra_spi0_parents[] = { CK_INFRA_I2C, CK_INFRA_ISPI0 };
+
+static const int infra_spi1_parents[] = { CK_INFRA_I2C, CK_INFRA_ISPI1 };
+
+static const int infra_pwm1_parents[] = { -1, -1, -1, CK_INFRA_PWM };
+
+static const int infra_pwm_bsel_parents[] = { -1, -1, -1, CK_INFRA_PWM };
+
+static const int infra_pcie_parents[] = { CK_INFRA_CK_F32K, CK_INFRA_CK_F26M,
+					  CK_TOP_CB_CKSQ_40M, CK_INFRA_PCIE_CK};
+
+#define INFRA_MUX(_id, _name, _parents, _reg, _shift, _width)                  \
+	{                                                                      \
+		.id = _id, .mux_reg = (_reg) + 0x8,                            \
+		.mux_set_reg = (_reg) + 0x0, .mux_clr_reg = (_reg) + 0x4,      \
+		.mux_shift = _shift, .mux_mask = BIT(_width) - 1,              \
+		.parent = _parents, .num_parents = ARRAY_SIZE(_parents),       \
+		.flags = CLK_MUX_SETCLR_UPD | CLK_PARENT_INFRASYS,             \
+	}
+
+/* INFRA MUX */
+static const struct mtk_composite infra_muxes[] = {
+	INFRA_MUX(CK_INFRA_UART0_SEL, "infra_uart0_sel", infra_uart0_parents,
+		  0x10, 0, 1),
+	INFRA_MUX(CK_INFRA_UART1_SEL, "infra_uart1_sel", infra_uart0_parents,
+		  0x10, 1, 1),
+	INFRA_MUX(CK_INFRA_UART2_SEL, "infra_uart2_sel", infra_uart0_parents,
+		  0x10, 2, 1),
+	INFRA_MUX(CK_INFRA_SPI0_SEL, "infra_spi0_sel", infra_spi0_parents, 0x10,
+		  4, 1),
+	INFRA_MUX(CK_INFRA_SPI1_SEL, "infra_spi1_sel", infra_spi1_parents, 0x10,
+		  5, 1),
+	INFRA_MUX(CK_INFRA_SPI2_SEL, "infra_spi2_sel", infra_spi0_parents, 0x10,
+		  6, 1),
+	INFRA_MUX(CK_INFRA_PWM1_SEL, "infra_pwm1_sel", infra_pwm1_parents, 0x10,
+		  9, 2),
+	INFRA_MUX(CK_INFRA_PWM2_SEL, "infra_pwm2_sel", infra_pwm1_parents, 0x10,
+		  11, 2),
+	INFRA_MUX(CK_INFRA_PWM_BSEL, "infra_pwm_bsel", infra_pwm_bsel_parents,
+		  0x10, 13, 2),
+	INFRA_MUX(CK_INFRA_PCIE_SEL, "infra_pcie_sel", infra_pcie_parents, 0x20,
+		  0, 2),
+};
+
+static const struct mtk_gate_regs infra_0_cg_regs = {
+	.set_ofs = 0x40,
+	.clr_ofs = 0x44,
+	.sta_ofs = 0x48,
+};
+
+static const struct mtk_gate_regs infra_1_cg_regs = {
+	.set_ofs = 0x50,
+	.clr_ofs = 0x54,
+	.sta_ofs = 0x58,
+};
+
+static const struct mtk_gate_regs infra_2_cg_regs = {
+	.set_ofs = 0x60,
+	.clr_ofs = 0x64,
+	.sta_ofs = 0x68,
+};
+
+#define GATE_INFRA0(_id, _name, _parent, _shift)                               \
+	{                                                                      \
+		.id = _id, .parent = _parent, .regs = &infra_0_cg_regs,        \
+		.shift = _shift,                                               \
+		.flags = CLK_GATE_SETCLR | CLK_PARENT_INFRASYS,                \
+	}
+
+#define GATE_INFRA1(_id, _name, _parent, _shift)                               \
+	{                                                                      \
+		.id = _id, .parent = _parent, .regs = &infra_1_cg_regs,        \
+		.shift = _shift,                                               \
+		.flags = CLK_GATE_SETCLR | CLK_PARENT_INFRASYS,                \
+	}
+
+#define GATE_INFRA2(_id, _name, _parent, _shift)                               \
+	{                                                                      \
+		.id = _id, .parent = _parent, .regs = &infra_2_cg_regs,        \
+		.shift = _shift,                                               \
+		.flags = CLK_GATE_SETCLR | CLK_PARENT_INFRASYS,                \
+	}
+
+/* INFRA GATE */
+static const struct mtk_gate infracfg_ao_gates[] = {
+	GATE_INFRA0(CK_INFRA_GPT_STA, "infra_gpt_sta", CK_INFRA_66M_MCK, 0),
+	GATE_INFRA0(CK_INFRA_PWM_HCK, "infra_pwm_hck", CK_INFRA_66M_MCK, 1),
+	GATE_INFRA0(CK_INFRA_PWM_STA, "infra_pwm_sta", CK_INFRA_PWM_BCK, 2),
+	GATE_INFRA0(CK_INFRA_PWM1_CK, "infra_pwm1", CK_INFRA_PWM_CK1, 3),
+	GATE_INFRA0(CK_INFRA_PWM2_CK, "infra_pwm2", CK_INFRA_PWM_CK2, 4),
+	GATE_INFRA0(CK_INFRA_CQ_DMA_CK, "infra_cq_dma", CK_INFRA_133M_HCK, 6),
+	GATE_INFRA0(CK_INFRA_AUD_BUS_CK, "infra_aud_bus", CK_INFRA_66M_PHCK, 8),
+	GATE_INFRA0(CK_INFRA_AUD_26M_CK, "infra_aud_26m", CK_INFRA_CK_F26M, 9),
+	GATE_INFRA0(CK_INFRA_AUD_L_CK, "infra_aud_l", CK_INFRA_FAUD_L_CK, 10),
+	GATE_INFRA0(CK_INFRA_AUD_AUD_CK, "infra_aud_aud", CK_INFRA_FAUD_AUD_CK,
+		    11),
+	GATE_INFRA0(CK_INFRA_AUD_EG2_CK, "infra_aud_eg2", CK_INFRA_FAUD_EG2_CK,
+		    13),
+	GATE_INFRA0(CK_INFRA_DRAMC_26M_CK, "infra_dramc_26m", CK_INFRA_CK_F26M,
+		    14),
+	GATE_INFRA0(CK_INFRA_DBG_CK, "infra_dbg", CK_INFRA_66M_MCK, 15),
+	GATE_INFRA0(CK_INFRA_AP_DMA_CK, "infra_ap_dma", CK_INFRA_66M_MCK, 16),
+	GATE_INFRA0(CK_INFRA_SEJ_CK, "infra_sej", CK_INFRA_66M_MCK, 24),
+	GATE_INFRA0(CK_INFRA_SEJ_13M_CK, "infra_sej_13m", CK_INFRA_CK_F26M, 25),
+	GATE_INFRA1(CK_INFRA_THERM_CK, "infra_therm", CK_INFRA_CK_F26M, 0),
+	GATE_INFRA1(CK_INFRA_I2CO_CK, "infra_i2co", CK_INFRA_I2CS_CK, 1),
+	GATE_INFRA1(CK_INFRA_UART0_CK, "infra_uart0", CK_INFRA_MUX_UART0, 2),
+	GATE_INFRA1(CK_INFRA_UART1_CK, "infra_uart1", CK_INFRA_MUX_UART1, 3),
+	GATE_INFRA1(CK_INFRA_UART2_CK, "infra_uart2", CK_INFRA_MUX_UART2, 4),
+	GATE_INFRA1(CK_INFRA_SPI2_CK, "infra_spi2", CK_INFRA_MUX_SPI2, 6),
+	GATE_INFRA1(CK_INFRA_SPI2_HCK_CK, "infra_spi2_hck", CK_INFRA_66M_MCK,
+		    7),
+	GATE_INFRA1(CK_INFRA_NFI1_CK, "infra_nfi1", CK_INFRA_NFI_CK, 8),
+	GATE_INFRA1(CK_INFRA_SPINFI1_CK, "infra_spinfi1", CK_INFRA_SPINFI_CK,
+		    9),
+	GATE_INFRA1(CK_INFRA_NFI_HCK_CK, "infra_nfi_hck", CK_INFRA_66M_MCK, 10),
+	GATE_INFRA1(CK_INFRA_SPI0_CK, "infra_spi0", CK_INFRA_MUX_SPI0, 11),
+	GATE_INFRA1(CK_INFRA_SPI1_CK, "infra_spi1", CK_INFRA_MUX_SPI1, 12),
+	GATE_INFRA1(CK_INFRA_SPI0_HCK_CK, "infra_spi0_hck", CK_INFRA_66M_MCK,
+		    13),
+	GATE_INFRA1(CK_INFRA_SPI1_HCK_CK, "infra_spi1_hck", CK_INFRA_66M_MCK,
+		    14),
+	GATE_INFRA1(CK_INFRA_FRTC_CK, "infra_frtc", CK_INFRA_RTC_32K, 15),
+	GATE_INFRA1(CK_INFRA_MSDC_CK, "infra_msdc", CK_INFRA_FMSDC_CK, 16),
+	GATE_INFRA1(CK_INFRA_MSDC_HCK_CK, "infra_msdc_hck",
+		    CK_INFRA_FMSDC_HCK_CK, 17),
+	GATE_INFRA1(CK_INFRA_MSDC_133M_CK, "infra_msdc_133m",
+		    CK_INFRA_PERI_133M, 18),
+	GATE_INFRA1(CK_INFRA_MSDC_66M_CK, "infra_msdc_66m", CK_INFRA_66M_PHCK,
+		    19),
+	GATE_INFRA1(CK_INFRA_ADC_26M_CK, "infra_adc_26m", CK_TOP_F26M, 20),
+	GATE_INFRA1(CK_INFRA_ADC_FRC_CK, "infra_adc_frc", CK_TOP_F26M, 21),
+	GATE_INFRA1(CK_INFRA_FBIST2FPC_CK, "infra_fbist2fpc", CK_INFRA_NFI_CK,
+		    23),
+	GATE_INFRA1(CK_INFRA_I2C_MCK_CK, "infra_i2c_mck", CK_INFRA_133M_MCK,
+		    25),
+	GATE_INFRA1(CK_INFRA_I2C_PCK_CK, "infra_i2c_pck", CK_INFRA_66M_MCK, 26),
+	GATE_INFRA2(CK_INFRA_IUSB_133_CK, "infra_iusb_133", CK_INFRA_133M_PHCK,
+		    0),
+	GATE_INFRA2(CK_INFRA_IUSB_66M_CK, "infra_iusb_66m", CK_INFRA_66M_PHCK,
+		    1),
+	GATE_INFRA2(CK_INFRA_IUSB_SYS_CK, "infra_iusb_sys", CK_INFRA_USB_SYS_CK,
+		    2),
+	GATE_INFRA2(CK_INFRA_IUSB_CK, "infra_iusb", CK_INFRA_USB_CK, 3),
+	GATE_INFRA2(CK_INFRA_IPCIE_CK, "infra_ipcie",
+		    CK_INFRA_PCIE_GFMUX_TL_O_PRE, 12),
+	GATE_INFRA2(CK_INFRA_IPCIER_CK, "infra_ipcier", CK_INFRA_F26M_CK0, 14),
+	GATE_INFRA2(CK_INFRA_IPCIEB_CK, "infra_ipcieb", CK_INFRA_133M_PHCK, 15),
+};
+
+static const struct mtk_clk_tree mt7981_fixed_pll_clk_tree = {
+	.fdivs_offs = CLK_APMIXED_NR_CLK,
+	.xtal_rate = 40 * MHZ,
+	.fclks = fixed_pll_clks,
+};
+
+static const struct mtk_clk_tree mt7981_topckgen_clk_tree = {
+	.fdivs_offs = CK_TOP_CB_M_416M,
+	.muxes_offs = CK_TOP_NFI1X_SEL,
+	.fclks = top_fixed_clks,
+	.fdivs = top_fixed_divs,
+	.muxes = top_muxes,
+	.flags = CLK_BYPASS_XTAL,
+};
+
+static const struct mtk_clk_tree mt7981_infracfg_clk_tree = {
+	.fdivs_offs = CK_INFRA_CK_F26M,
+	.muxes_offs = CK_INFRA_UART0_SEL,
+	.fdivs = infra_fixed_divs,
+	.muxes = infra_muxes,
+};
+
+static const struct udevice_id mt7981_fixed_pll_compat[] = {
+	{ .compatible = "mediatek,mt7981-fixed-plls" },
+	{}
+};
+
+static const struct udevice_id mt7981_topckgen_compat[] = {
+	{ .compatible = "mediatek,mt7981-topckgen" },
+	{}
+};
+
+static int mt7981_fixed_pll_probe(struct udevice *dev)
+{
+	return mtk_common_clk_init(dev, &mt7981_fixed_pll_clk_tree);
+}
+
+static int mt7981_topckgen_probe(struct udevice *dev)
+{
+	struct mtk_clk_priv *priv = dev_get_priv(dev);
+
+	priv->base = dev_read_addr_ptr(dev);
+	writel(MT7981_CLK_PDN_EN_WRITE, priv->base + MT7981_CLK_PDN);
+
+	return mtk_common_clk_init(dev, &mt7981_topckgen_clk_tree);
+}
+
+U_BOOT_DRIVER(mtk_clk_apmixedsys) = {
+	.name = "mt7981-clock-fixed-pll",
+	.id = UCLASS_CLK,
+	.of_match = mt7981_fixed_pll_compat,
+	.probe = mt7981_fixed_pll_probe,
+	.priv_auto = sizeof(struct mtk_clk_priv),
+	.ops = &mtk_clk_topckgen_ops,
+	.flags = DM_FLAG_PRE_RELOC,
+};
+
+U_BOOT_DRIVER(mtk_clk_topckgen) = {
+	.name = "mt7981-clock-topckgen",
+	.id = UCLASS_CLK,
+	.of_match = mt7981_topckgen_compat,
+	.probe = mt7981_topckgen_probe,
+	.priv_auto = sizeof(struct mtk_clk_priv),
+	.ops = &mtk_clk_topckgen_ops,
+	.flags = DM_FLAG_PRE_RELOC,
+};
+
+static const struct udevice_id mt7981_infracfg_compat[] = {
+	{ .compatible = "mediatek,mt7981-infracfg" },
+	{}
+};
+
+static const struct udevice_id mt7981_infracfg_ao_compat[] = {
+	{ .compatible = "mediatek,mt7981-infracfg_ao" },
+	{}
+};
+
+static int mt7981_infracfg_probe(struct udevice *dev)
+{
+	return mtk_common_clk_init(dev, &mt7981_infracfg_clk_tree);
+}
+
+static int mt7981_infracfg_ao_probe(struct udevice *dev)
+{
+	return mtk_common_clk_gate_init(dev, &mt7981_infracfg_clk_tree,
+					infracfg_ao_gates);
+}
+
+U_BOOT_DRIVER(mtk_clk_infracfg) = {
+	.name = "mt7981-clock-infracfg",
+	.id = UCLASS_CLK,
+	.of_match = mt7981_infracfg_compat,
+	.probe = mt7981_infracfg_probe,
+	.priv_auto = sizeof(struct mtk_clk_priv),
+	.ops = &mtk_clk_infrasys_ops,
+	.flags = DM_FLAG_PRE_RELOC,
+};
+
+U_BOOT_DRIVER(mtk_clk_infracfg_ao) = {
+	.name = "mt7981-clock-infracfg-ao",
+	.id = UCLASS_CLK,
+	.of_match = mt7981_infracfg_ao_compat,
+	.probe = mt7981_infracfg_ao_probe,
+	.priv_auto = sizeof(struct mtk_cg_priv),
+	.ops = &mtk_clk_gate_ops,
+	.flags = DM_FLAG_PRE_RELOC,
+};
+
+/* ethsys */
+static const struct mtk_gate_regs eth_cg_regs = {
+	.set_ofs = 0x30,
+	.clr_ofs = 0x30,
+	.sta_ofs = 0x30,
+};
+
+#define GATE_ETH(_id, _name, _parent, _shift)                                  \
+	{                                                                      \
+		.id = _id, .parent = _parent, .regs = &eth_cg_regs,            \
+		.shift = _shift,                                               \
+		.flags = CLK_GATE_NO_SETCLR_INV | CLK_PARENT_TOPCKGEN,         \
+	}
+
+static const struct mtk_gate eth_cgs[] = {
+	GATE_ETH(CK_ETH_FE_EN, "eth_fe_en", CK_TOP_NETSYS_2X, 6),
+	GATE_ETH(CK_ETH_GP2_EN, "eth_gp2_en", CK_TOP_SGM_325M, 7),
+	GATE_ETH(CK_ETH_GP1_EN, "eth_gp1_en", CK_TOP_SGM_325M, 8),
+	GATE_ETH(CK_ETH_WOCPU0_EN, "eth_wocpu0_en", CK_TOP_NETSYS_WED_MCU, 15),
+};
+
+static int mt7981_ethsys_probe(struct udevice *dev)
+{
+	return mtk_common_clk_gate_init(dev, &mt7981_topckgen_clk_tree,
+					eth_cgs);
+}
+
+static int mt7981_ethsys_bind(struct udevice *dev)
+{
+	int ret = 0;
+
+	if (CONFIG_IS_ENABLED(RESET_MEDIATEK)) {
+		ret = mediatek_reset_bind(dev, ETHSYS_HIFSYS_RST_CTRL_OFS, 1);
+		if (ret)
+			debug("Warning: failed to bind reset controller\n");
+	}
+
+	return ret;
+}
+
+static const struct udevice_id mt7981_ethsys_compat[] = {
+	{ .compatible = "mediatek,mt7981-ethsys", },
+	{}
+};
+
+U_BOOT_DRIVER(mtk_clk_ethsys) = {
+	.name = "mt7981-clock-ethsys",
+	.id = UCLASS_CLK,
+	.of_match = mt7981_ethsys_compat,
+	.probe = mt7981_ethsys_probe,
+	.bind = mt7981_ethsys_bind,
+	.priv_auto = sizeof(struct mtk_cg_priv),
+	.ops = &mtk_clk_gate_ops,
+};
diff --git a/include/dt-bindings/clock/mt7981-clk.h b/include/dt-bindings/clock/mt7981-clk.h
new file mode 100644
index 0000000000..e24c759e49
--- /dev/null
+++ b/include/dt-bindings/clock/mt7981-clk.h
@@ -0,0 +1,267 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2022 MediaTek Inc. All rights reserved.
+ *
+ * Author: Sam Shih <sam.shih@mediatek.com>
+ */
+
+#ifndef _DT_BINDINGS_CLK_MT7981_H
+#define _DT_BINDINGS_CLK_MT7981_H
+
+/* INFRACFG */
+
+#define CK_INFRA_CK_F26M		0
+#define CK_INFRA_UART			1
+#define CK_INFRA_ISPI0			2
+#define CK_INFRA_I2C			3
+#define CK_INFRA_ISPI1			4
+#define CK_INFRA_PWM			5
+#define CK_INFRA_66M_MCK		6
+#define CK_INFRA_CK_F32K		7
+#define CK_INFRA_PCIE_CK		8
+#define CK_INFRA_PWM_BCK		9
+#define CK_INFRA_PWM_CK1		10
+#define CK_INFRA_PWM_CK2		11
+#define CK_INFRA_133M_HCK		12
+#define CK_INFRA_66M_PHCK		13
+#define CK_INFRA_FAUD_L_CK		14
+#define CK_INFRA_FAUD_AUD_CK		15
+#define CK_INFRA_FAUD_EG2_CK		16
+#define CK_INFRA_I2CS_CK		17
+#define CK_INFRA_MUX_UART0		18
+#define CK_INFRA_MUX_UART1		19
+#define CK_INFRA_MUX_UART2		20
+#define CK_INFRA_NFI_CK			21
+#define CK_INFRA_SPINFI_CK		22
+#define CK_INFRA_MUX_SPI0		23
+#define CK_INFRA_MUX_SPI1		24
+#define CK_INFRA_MUX_SPI2		25
+#define CK_INFRA_RTC_32K		26
+#define CK_INFRA_FMSDC_CK		27
+#define CK_INFRA_FMSDC_HCK_CK		28
+#define CK_INFRA_PERI_133M		29
+#define CK_INFRA_133M_PHCK		30
+#define CK_INFRA_USB_SYS_CK		31
+#define CK_INFRA_USB_CK			32
+#define CK_INFRA_USB_XHCI_CK		33
+#define CK_INFRA_PCIE_GFMUX_TL_O_PRE	34
+#define CK_INFRA_F26M_CK0		35
+#define CK_INFRA_133M_MCK		36
+#define CLK_INFRA_NR_CLK		37
+
+/* TOPCKGEN */
+
+#define CK_TOP_CB_CKSQ_40M		0
+#define CK_TOP_CB_M_416M		1
+#define CK_TOP_CB_M_D2			2
+#define CK_TOP_CB_M_D3			3
+#define CK_TOP_M_D3_D2			4
+#define CK_TOP_CB_M_D4			5
+#define CK_TOP_CB_M_D8			6
+#define CK_TOP_M_D8_D2			7
+#define CK_TOP_CB_MM_720M		8
+#define CK_TOP_CB_MM_D2			9
+#define CK_TOP_CB_MM_D3			10
+#define CK_TOP_CB_MM_D3_D5		11
+#define CK_TOP_CB_MM_D4			12
+#define CK_TOP_CB_MM_D6			13
+#define CK_TOP_MM_D6_D2			14
+#define CK_TOP_CB_MM_D8			15
+#define CK_TOP_CB_APLL2_196M		16
+#define CK_TOP_APLL2_D2			17
+#define CK_TOP_APLL2_D4			18
+#define CK_TOP_NET1_2500M		19
+#define CK_TOP_CB_NET1_D4		20
+#define CK_TOP_CB_NET1_D5		21
+#define CK_TOP_NET1_D5_D2		22
+#define CK_TOP_NET1_D5_D4		23
+#define CK_TOP_CB_NET1_D8		24
+#define CK_TOP_NET1_D8_D2		25
+#define CK_TOP_NET1_D8_D4		26
+#define CK_TOP_CB_NET2_800M		27
+#define CK_TOP_CB_NET2_D2		28
+#define CK_TOP_CB_NET2_D4		29
+#define CK_TOP_NET2_D4_D2		30
+#define CK_TOP_NET2_D4_D4		31
+#define CK_TOP_CB_NET2_D6		32
+#define CK_TOP_CB_WEDMCU_208M		33
+#define CK_TOP_CB_SGM_325M		34
+#define CK_TOP_CKSQ_40M_D2		35
+#define CK_TOP_CB_RTC_32K		36
+#define CK_TOP_CB_RTC_32P7K		37
+#define CK_TOP_USB_TX250M		38
+#define CK_TOP_FAUD			39
+#define CK_TOP_NFI1X			40
+#define CK_TOP_USB_EQ_RX250M		41
+#define CK_TOP_USB_CDR_CK		42
+#define CK_TOP_USB_LN0_CK		43
+#define CK_TOP_SPINFI_BCK		44
+#define CK_TOP_SPI			45
+#define CK_TOP_SPIM_MST			46
+#define CK_TOP_UART_BCK			47
+#define CK_TOP_PWM_BCK			48
+#define CK_TOP_I2C_BCK			49
+#define CK_TOP_PEXTP_TL			50
+#define CK_TOP_EMMC_208M		51
+#define CK_TOP_EMMC_400M		52
+#define CK_TOP_DRAMC_REF		53
+#define CK_TOP_DRAMC_MD32		54
+#define CK_TOP_SYSAXI			55
+#define CK_TOP_SYSAPB			56
+#define CK_TOP_ARM_DB_MAIN		57
+#define CK_TOP_AP2CNN_HOST		58
+#define CK_TOP_NETSYS			59
+#define CK_TOP_NETSYS_500M		60
+#define CK_TOP_NETSYS_WED_MCU		61
+#define CK_TOP_NETSYS_2X		62
+#define CK_TOP_SGM_325M			63
+#define CK_TOP_SGM_REG			64
+#define CK_TOP_F26M			65
+#define CK_TOP_EIP97B			66
+#define CK_TOP_USB3_PHY			67
+#define CK_TOP_AUD			68
+#define CK_TOP_A1SYS			69
+#define CK_TOP_AUD_L			70
+#define CK_TOP_A_TUNER			71
+#define CK_TOP_U2U3_REF			72
+#define CK_TOP_U2U3_SYS			73
+#define CK_TOP_U2U3_XHCI		74
+#define CK_TOP_USB_FRMCNT		75
+#define CK_TOP_NFI1X_SEL		76
+#define CK_TOP_SPINFI_SEL		77
+#define CK_TOP_SPI_SEL			78
+#define CK_TOP_SPIM_MST_SEL		79
+#define CK_TOP_UART_SEL			80
+#define CK_TOP_PWM_SEL			81
+#define CK_TOP_I2C_SEL			82
+#define CK_TOP_PEXTP_TL_SEL		83
+#define CK_TOP_EMMC_208M_SEL		84
+#define CK_TOP_EMMC_400M_SEL		85
+#define CK_TOP_F26M_SEL			86
+#define CK_TOP_DRAMC_SEL		87
+#define CK_TOP_DRAMC_MD32_SEL		88
+#define CK_TOP_SYSAXI_SEL		89
+#define CK_TOP_SYSAPB_SEL		90
+#define CK_TOP_ARM_DB_MAIN_SEL		91
+#define CK_TOP_AP2CNN_HOST_SEL		92
+#define CK_TOP_NETSYS_SEL		93
+#define CK_TOP_NETSYS_500M_SEL		94
+#define CK_TOP_NETSYS_MCU_SEL		95
+#define CK_TOP_NETSYS_2X_SEL		96
+#define CK_TOP_SGM_325M_SEL		97
+#define CK_TOP_SGM_REG_SEL		98
+#define CK_TOP_EIP97B_SEL		99
+#define CK_TOP_USB3_PHY_SEL		100
+#define CK_TOP_AUD_SEL			101
+#define CK_TOP_A1SYS_SEL		102
+#define CK_TOP_AUD_L_SEL		103
+#define CK_TOP_A_TUNER_SEL		104
+#define CK_TOP_U2U3_SEL			105
+#define CK_TOP_U2U3_SYS_SEL		106
+#define CK_TOP_U2U3_XHCI_SEL		107
+#define CK_TOP_USB_FRMCNT_SEL		108
+#define CLK_TOP_NR_CLK			109
+
+/*
+ * INFRACFG_AO
+ * clock muxes need to be append to infracfg domain, and clock gates
+ * need to be keep in infracgh_ao domain
+ */
+#define INFRACFG_AO_OFFSET		10
+
+#define CK_INFRA_UART0_SEL		(0 + CLK_INFRA_NR_CLK)
+#define CK_INFRA_UART1_SEL		(1 + CLK_INFRA_NR_CLK)
+#define CK_INFRA_UART2_SEL		(2 + CLK_INFRA_NR_CLK)
+#define CK_INFRA_SPI0_SEL		(3 + CLK_INFRA_NR_CLK)
+#define CK_INFRA_SPI1_SEL		(4 + CLK_INFRA_NR_CLK)
+#define CK_INFRA_SPI2_SEL		(5 + CLK_INFRA_NR_CLK)
+#define CK_INFRA_PWM1_SEL		(6 + CLK_INFRA_NR_CLK)
+#define CK_INFRA_PWM2_SEL		(7 + CLK_INFRA_NR_CLK)
+#define CK_INFRA_PWM_BSEL		(8 + CLK_INFRA_NR_CLK)
+#define CK_INFRA_PCIE_SEL		(9 + CLK_INFRA_NR_CLK)
+#define CK_INFRA_GPT_STA		(10 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_PWM_HCK		(11 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_PWM_STA		(12 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_PWM1_CK		(13 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_PWM2_CK		(14 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_CQ_DMA_CK		(15 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_AUD_BUS_CK		(16 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_AUD_26M_CK		(17 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_AUD_L_CK		(18 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_AUD_AUD_CK		(19 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_AUD_EG2_CK		(20 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_DRAMC_26M_CK		(21 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_DBG_CK			(22 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_AP_DMA_CK		(23 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_SEJ_CK			(24 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_SEJ_13M_CK		(25 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_THERM_CK		(26 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_I2CO_CK		(27 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_UART0_CK		(28 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_UART1_CK		(29 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_UART2_CK		(30 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_SPI2_CK		(31 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_SPI2_HCK_CK		(32 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_NFI1_CK		(33 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_SPINFI1_CK		(34 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_NFI_HCK_CK		(35 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_SPI0_CK		(36 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_SPI1_CK		(37 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_SPI0_HCK_CK		(38 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_SPI1_HCK_CK		(39 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_FRTC_CK		(40 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_MSDC_CK		(41 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_MSDC_HCK_CK		(42 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_MSDC_133M_CK		(43 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_MSDC_66M_CK		(44 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_ADC_26M_CK		(45 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_ADC_FRC_CK		(46 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_FBIST2FPC_CK		(47 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_I2C_MCK_CK		(48 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_I2C_PCK_CK		(49 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_IUSB_133_CK		(50 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_IUSB_66M_CK		(51 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_IUSB_SYS_CK		(52 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_IUSB_CK		(53 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_IPCIE_CK		(54 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_IPCIER_CK		(55 - INFRACFG_AO_OFFSET)
+#define CK_INFRA_IPCIEB_CK		(56 - INFRACFG_AO_OFFSET)
+#define CLK_INFRA_AO_NR_CLK		(57 - INFRACFG_AO_OFFSET)
+
+/* APMIXEDSYS */
+
+#define CK_APMIXED_ARMPLL		0
+#define CK_APMIXED_NET2PLL		1
+#define CK_APMIXED_MMPLL		2
+#define CK_APMIXED_SGMPLL		3
+#define CK_APMIXED_WEDMCUPLL		4
+#define CK_APMIXED_NET1PLL		5
+#define CK_APMIXED_MPLL			6
+#define CK_APMIXED_APLL2		7
+#define CLK_APMIXED_NR_CLK		8
+
+/* SGMIISYS_0 */
+
+#define CK_SGM0_TX_EN			0
+#define CK_SGM0_RX_EN			1
+#define CK_SGM0_CK0_EN			2
+#define CK_SGM0_CDR_CK0_EN		3
+#define CLK_SGMII0_NR_CLK		4
+
+/* SGMIISYS_1 */
+
+#define CK_SGM1_TX_EN			0
+#define CK_SGM1_RX_EN			1
+#define CK_SGM1_CK1_EN			2
+#define CK_SGM1_CDR_CK1_EN		3
+#define CLK_SGMII1_NR_CLK		4
+
+/* ETHSYS */
+
+#define CK_ETH_FE_EN			0
+#define CK_ETH_GP2_EN			1
+#define CK_ETH_GP1_EN			2
+#define CK_ETH_WOCPU0_EN		3
+#define CLK_ETH_NR_CLK			4
+
+#endif /* _DT_BINDINGS_CLK_MT7981_H */
-- 
2.17.1


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

* [PATCH v2 28/32] cpu: add basic cpu driver for MediaTek ARM chips
  2022-08-31 11:00 [PATCH v2 00/32] Add support for MediaTek MT7981/MT7986 SoCs - v2 Weijie Gao
                   ` (26 preceding siblings ...)
  2022-08-31 11:05 ` [PATCH v2 27/32] clk: mediatek: add clock driver support for MediaTek MT7981 SoC Weijie Gao
@ 2022-08-31 11:05 ` Weijie Gao
  2022-08-31 13:46   ` Simon Glass
  2022-09-01  0:28   ` Daniel Golle
  2022-08-31 11:05 ` [PATCH v2 29/32] tools: mtk_image: split gfh header verification into a new function Weijie Gao
                   ` (3 subsequent siblings)
  31 siblings, 2 replies; 60+ messages in thread
From: Weijie Gao @ 2022-08-31 11:05 UTC (permalink / raw)
  To: u-boot; +Cc: GSS_MTK_Uboot_upstream, Michal Simek, Ovidiu Panait, Weijie Gao

Add basic CPU driver used to retrieve CPU model information.

Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
---
  v2 changes: new
---
 drivers/cpu/Makefile  |   1 +
 drivers/cpu/mtk_cpu.c | 106 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 107 insertions(+)
 create mode 100644 drivers/cpu/mtk_cpu.c

diff --git a/drivers/cpu/Makefile b/drivers/cpu/Makefile
index 20884b1795..3b38ba9c58 100644
--- a/drivers/cpu/Makefile
+++ b/drivers/cpu/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_CPU) += cpu-uclass.o
 obj-$(CONFIG_ARCH_BMIPS) += bmips_cpu.o
 obj-$(CONFIG_ARCH_IMX8) += imx8_cpu.o
 obj-$(CONFIG_ARCH_AT91) += at91_cpu.o
+obj-$(CONFIG_ARCH_MEDIATEK) += mtk_cpu.o
 obj-$(CONFIG_CPU_MPC83XX) += mpc83xx_cpu.o
 obj-$(CONFIG_CPU_RISCV) += riscv_cpu.o
 obj-$(CONFIG_CPU_MICROBLAZE) += microblaze_cpu.o
diff --git a/drivers/cpu/mtk_cpu.c b/drivers/cpu/mtk_cpu.c
new file mode 100644
index 0000000000..d00b4c669e
--- /dev/null
+++ b/drivers/cpu/mtk_cpu.c
@@ -0,0 +1,106 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2022 MediaTek Inc. All rights reserved.
+ *
+ * Author: Weijie Gao <weijie.gao@mediatek.com>
+ */
+
+#include <linux/types.h>
+#include <cpu.h>
+#include <dm.h>
+#include <fdt_support.h>
+#include <mapmem.h>
+#include <asm/global_data.h>
+#include <linux/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct mtk_cpu_plat {
+	void __iomem *hwver_base;
+};
+
+static int mtk_cpu_get_desc(const struct udevice *dev, char *buf, int size)
+{
+	struct mtk_cpu_plat *plat = dev_get_plat(dev);
+
+	snprintf(buf, size, "MediaTek MT%04X", readl(plat->hwver_base));
+
+	return 0;
+}
+
+static int mtk_cpu_get_count(const struct udevice *dev)
+{
+	return 1;
+}
+
+static int mtk_cpu_get_vendor(const struct udevice *dev, char *buf, int size)
+{
+	snprintf(buf, size, "MediaTek");
+
+	return 0;
+}
+
+static int mtk_cpu_probe(struct udevice *dev)
+{
+	struct mtk_cpu_plat *plat = dev_get_plat(dev);
+	const void *fdt = gd->fdt_blob, *reg;
+	int offset, parent, len, na, ns;
+	u64 addr;
+
+	if (!fdt)
+		return -ENODEV;
+
+	offset = fdt_path_offset(fdt, "/hwver");
+	if (offset < 0)
+		return -ENODEV;
+
+	parent = fdt_parent_offset(fdt, offset);
+	if (parent < 0)
+		return -ENODEV;
+
+	na = fdt_address_cells(fdt, parent);
+	if (na < 1)
+		return -ENODEV;
+
+	ns = fdt_size_cells(gd->fdt_blob, parent);
+	if (ns < 0)
+		return -ENODEV;
+
+	reg = fdt_getprop(gd->fdt_blob, offset, "reg", &len);
+	if (!reg)
+		return -ENODEV;
+
+	if (ns)
+		addr = fdt_translate_address(fdt, offset, reg);
+	else
+		addr = fdt_read_number(reg, na);
+
+	plat->hwver_base = map_sysmem(addr, 0);
+	if (!plat->hwver_base)
+		return -EINVAL;
+
+	return 0;
+}
+
+static const struct cpu_ops mtk_cpu_ops = {
+	.get_desc	= mtk_cpu_get_desc,
+	.get_count	= mtk_cpu_get_count,
+	.get_vendor	= mtk_cpu_get_vendor,
+};
+
+static const struct udevice_id mtk_cpu_ids[] = {
+	{ .compatible = "arm,cortex-a7" },
+	{ .compatible = "arm,cortex-a53" },
+	{ .compatible = "arm,cortex-a73" },
+	{ /* sentinel */ }
+};
+
+U_BOOT_DRIVER(cpu_mtk) = {
+	.name		= "mtk-cpu",
+	.id		= UCLASS_CPU,
+	.of_match	= mtk_cpu_ids,
+	.ops		= &mtk_cpu_ops,
+	.probe		= mtk_cpu_probe,
+	.plat_auto	= sizeof(struct mtk_cpu_plat),
+	.flags		= DM_FLAG_PRE_RELOC,
+};
-- 
2.17.1


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

* [PATCH v2 29/32] tools: mtk_image: split gfh header verification into a new function
  2022-08-31 11:00 [PATCH v2 00/32] Add support for MediaTek MT7981/MT7986 SoCs - v2 Weijie Gao
                   ` (27 preceding siblings ...)
  2022-08-31 11:05 ` [PATCH v2 28/32] cpu: add basic cpu driver for MediaTek ARM chips Weijie Gao
@ 2022-08-31 11:05 ` Weijie Gao
  2022-09-01  0:31   ` Daniel Golle
  2022-08-31 11:05 ` [PATCH v2 30/32] tools: mtk_image: split the code of generating NAND header into a new file Weijie Gao
                   ` (2 subsequent siblings)
  31 siblings, 1 reply; 60+ messages in thread
From: Weijie Gao @ 2022-08-31 11:05 UTC (permalink / raw)
  To: u-boot; +Cc: GSS_MTK_Uboot_upstream, Weijie Gao

The verification code of gfh header for NAND and non-NAND are identical.
It's better to define a individual function to reduce redundancy.

Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
---
v2 changes: none
---
 tools/mtk_image.c | 51 +++++++++++++++++++----------------------------
 1 file changed, 21 insertions(+), 30 deletions(-)

diff --git a/tools/mtk_image.c b/tools/mtk_image.c
index de5ce4d964..dcd6525f32 100644
--- a/tools/mtk_image.c
+++ b/tools/mtk_image.c
@@ -480,6 +480,25 @@ static int mtk_image_vrec_header(struct image_tool_params *params,
 	return SHA256_SUM_LEN;
 }
 
+static int mtk_image_verify_gfh(struct gfh_header *gfh, uint32_t type, int print)
+{
+	if (strcmp(gfh->file_info.name, GFH_FILE_INFO_NAME))
+		return -1;
+
+	if (le32_to_cpu(gfh->file_info.flash_type) != type)
+		return -1;
+
+	if (print)
+		printf("Load Address: %08x\n",
+		       le32_to_cpu(gfh->file_info.load_addr) +
+		       le32_to_cpu(gfh->file_info.jump_offset));
+
+	if (print)
+		printf("Architecture: %s\n", is_arm64_image ? "ARM64" : "ARM");
+
+	return 0;
+}
+
 static int mtk_image_verify_gen_header(const uint8_t *ptr, int print)
 {
 	union gen_boot_header *gbh = (union gen_boot_header *)ptr;
@@ -542,21 +561,7 @@ static int mtk_image_verify_gen_header(const uint8_t *ptr, int print)
 
 	gfh = (struct gfh_header *)(ptr + gfh_offset);
 
-	if (strcmp(gfh->file_info.name, GFH_FILE_INFO_NAME))
-		return -1;
-
-	if (le32_to_cpu(gfh->file_info.flash_type) != GFH_FLASH_TYPE_GEN)
-		return -1;
-
-	if (print)
-		printf("Load Address: %08x\n",
-		       le32_to_cpu(gfh->file_info.load_addr) +
-		       le32_to_cpu(gfh->file_info.jump_offset));
-
-	if (print)
-		printf("Architecture: %s\n", is_arm64_image ? "ARM64" : "ARM");
-
-	return 0;
+	return mtk_image_verify_gfh(gfh, GFH_FLASH_TYPE_GEN, print);
 }
 
 static int mtk_image_verify_nand_header(const uint8_t *ptr, int print)
@@ -610,21 +615,7 @@ static int mtk_image_verify_nand_header(const uint8_t *ptr, int print)
 
 	gfh = (struct gfh_header *)(ptr + 2 * le16_to_cpu(nh->pagesize));
 
-	if (strcmp(gfh->file_info.name, GFH_FILE_INFO_NAME))
-		return -1;
-
-	if (le32_to_cpu(gfh->file_info.flash_type) != GFH_FLASH_TYPE_NAND)
-		return -1;
-
-	if (print)
-		printf("Load Address: %08x\n",
-		       le32_to_cpu(gfh->file_info.load_addr) +
-		       le32_to_cpu(gfh->file_info.jump_offset));
-
-	if (print)
-		printf("Architecture: %s\n", is_arm64_image ? "ARM64" : "ARM");
-
-	return 0;
+	return mtk_image_verify_gfh(gfh, GFH_FLASH_TYPE_NAND, print);
 }
 
 static uint32_t crc32be_cal(const void *data, size_t length)
-- 
2.17.1


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

* [PATCH v2 30/32] tools: mtk_image: split the code of generating NAND header into a new file
  2022-08-31 11:00 [PATCH v2 00/32] Add support for MediaTek MT7981/MT7986 SoCs - v2 Weijie Gao
                   ` (28 preceding siblings ...)
  2022-08-31 11:05 ` [PATCH v2 29/32] tools: mtk_image: split gfh header verification into a new function Weijie Gao
@ 2022-08-31 11:05 ` Weijie Gao
  2022-09-01  0:32   ` Daniel Golle
  2022-08-31 11:05 ` [PATCH v2 31/32] tools: mtk_image: add support for nand headers used by newer chips Weijie Gao
  2022-08-31 11:05 ` [PATCH v2 32/32] MAINTAINERS: update maintainer for MediaTek ARM platform Weijie Gao
  31 siblings, 1 reply; 60+ messages in thread
From: Weijie Gao @ 2022-08-31 11:05 UTC (permalink / raw)
  To: u-boot
  Cc: GSS_MTK_Uboot_upstream, Simon Glass, AKASHI Takahiro,
	Pali Rohár, Stefan Roese, Andre Przywara, Samuel Holland,
	Weijie Gao

The predefined NAND headers take too much spaces in the mtk_image.c.
Moving them into a new file can significantly improve the readability of
both mtk_image.c and the new mtk_nand_headers.c.

This is a preparation for adding more NAND headers.

Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
---
v2 changes:
  Add comments
  Call mtk_nand_header_size only for NAND/SNAND to avoid NULL pointer access
---
 tools/Makefile           |   1 +
 tools/mtk_image.c        | 305 ++++++---------------------------------
 tools/mtk_image.h        |  25 ----
 tools/mtk_nand_headers.c | 286 ++++++++++++++++++++++++++++++++++++
 tools/mtk_nand_headers.h |  61 ++++++++
 5 files changed, 389 insertions(+), 289 deletions(-)
 create mode 100644 tools/mtk_nand_headers.c
 create mode 100644 tools/mtk_nand_headers.h

diff --git a/tools/Makefile b/tools/Makefile
index 3626919633..34a1aa7a8b 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -147,6 +147,7 @@ dumpimage-mkimage-objs := aisimage.o \
 			gpimage.o \
 			gpimage-common.o \
 			mtk_image.o \
+			mtk_nand_headers.o \
 			$(ECDSA_OBJS-y) \
 			$(RSA_OBJS-y) \
 			$(AES_OBJS-y)
diff --git a/tools/mtk_image.c b/tools/mtk_image.c
index dcd6525f32..1f7396aa69 100644
--- a/tools/mtk_image.c
+++ b/tools/mtk_image.c
@@ -12,216 +12,7 @@
 #include <u-boot/sha256.h>
 #include "imagetool.h"
 #include "mtk_image.h"
-
-/* NAND header for SPI-NAND with 2KB page + 64B spare */
-static const union nand_boot_header snand_hdr_2k_64_data = {
-	.data = {
-		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
-		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
-		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
-		0x00, 0x00, 0x00, 0x08, 0x03, 0x00, 0x40, 0x00,
-		0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x7B, 0xC4, 0x17, 0x9D,
-		0xCA, 0x42, 0x90, 0xD0, 0x98, 0xD0, 0xE0, 0xF7,
-		0xDB, 0xCD, 0x16, 0xF6, 0x03, 0x73, 0xD2, 0xB8,
-		0x93, 0xB2, 0x56, 0x5A, 0x84, 0x6E, 0x00, 0x00
-	}
-};
-
-/* NAND header for SPI-NAND with 2KB page + 120B/128B spare */
-static const union nand_boot_header snand_hdr_2k_128_data = {
-	.data = {
-		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
-		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
-		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
-		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
-		0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x90, 0x28, 0xED, 0x13,
-		0x7F, 0x12, 0x22, 0xCD, 0x3D, 0x06, 0xF1, 0xB3,
-		0x6F, 0x2E, 0xD9, 0xA0, 0x9D, 0x7A, 0xBD, 0xD7,
-		0xB3, 0x28, 0x3C, 0x13, 0xDB, 0x4E, 0x00, 0x00
-	}
-};
-
-/* NAND header for SPI-NAND with 4KB page + 256B spare */
-static const union nand_boot_header snand_hdr_4k_256_data = {
-	.data = {
-		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
-		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
-		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
-		0x00, 0x00, 0x00, 0x10, 0x05, 0x00, 0xE0, 0x00,
-		0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x47, 0xED, 0x0E, 0xC3,
-		0x83, 0xBF, 0x41, 0xD2, 0x85, 0x21, 0x97, 0x57,
-		0xC4, 0x2E, 0x6B, 0x7A, 0x40, 0xE0, 0xCF, 0x8F,
-		0x37, 0xBD, 0x17, 0xB6, 0xC7, 0xFE, 0x00, 0x00
-	}
-};
-
-/* NAND header for Parallel NAND 1Gb with 2KB page + 64B spare */
-static const union nand_boot_header nand_hdr_1gb_2k_64_data = {
-	.data = {
-		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
-		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
-		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
-		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
-		0x40, 0x00, 0x00, 0x04, 0x0B, 0x00, 0x11, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x12, 0x28, 0x1C, 0x12,
-		0x8F, 0xFD, 0xF8, 0x32, 0x6F, 0x6D, 0xCF, 0x6C,
-		0xDA, 0x21, 0x70, 0x8C, 0xDA, 0x0A, 0x22, 0x82,
-		0xAA, 0x59, 0xFA, 0x7C, 0x42, 0x2D, 0x00, 0x00
-	}
-};
-
-/* NAND header for Parallel NAND 2Gb with 2KB page + 64B spare */
-static const union nand_boot_header nand_hdr_2gb_2k_64_data = {
-	.data = {
-		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
-		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
-		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
-		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
-		0x40, 0x00, 0x00, 0x08, 0x0B, 0x00, 0x11, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x20, 0x9C, 0x3D, 0x2D,
-		0x7B, 0x68, 0x63, 0x52, 0x2E, 0x04, 0x63, 0xF1,
-		0x35, 0x4E, 0x44, 0x3E, 0xF8, 0xAC, 0x9B, 0x95,
-		0xAB, 0xFE, 0xE4, 0xE1, 0xD5, 0xF9, 0x00, 0x00
-	}
-};
-
-/* NAND header for Parallel NAND 4Gb with 2KB page + 64B spare */
-static const union nand_boot_header nand_hdr_4gb_2k_64_data = {
-	.data = {
-		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
-		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
-		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
-		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
-		0x40, 0x00, 0x00, 0x10, 0x0B, 0x00, 0x11, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0xE3, 0x0F, 0x86, 0x32,
-		0x68, 0x05, 0xD9, 0xC8, 0x13, 0xDF, 0xC5, 0x0B,
-		0x35, 0x3A, 0x68, 0xA5, 0x3C, 0x0C, 0x73, 0x87,
-		0x63, 0xB0, 0xBE, 0xCC, 0x84, 0x47, 0x00, 0x00
-	}
-};
-
-/* NAND header for Parallel NAND 2Gb with 2KB page + 128B spare */
-static const union nand_boot_header nand_hdr_2gb_2k_128_data = {
-	.data = {
-		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
-		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
-		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
-		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
-		0x40, 0x00, 0x00, 0x08, 0x0B, 0x00, 0x11, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x01, 0xA5, 0xE9, 0x5A,
-		0xDF, 0x58, 0x62, 0x41, 0xD6, 0x26, 0x77, 0xBC,
-		0x76, 0x1F, 0x27, 0x4E, 0x4F, 0x6C, 0xC3, 0xF0,
-		0x36, 0xDE, 0xD9, 0xB3, 0xFF, 0x93, 0x00, 0x00
-	}
-};
-
-/* NAND header for Parallel NAND 4Gb with 2KB page + 128B spare */
-static const union nand_boot_header nand_hdr_4gb_2k_128_data = {
-	.data = {
-		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
-		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
-		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
-		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
-		0x40, 0x00, 0x00, 0x10, 0x0B, 0x00, 0x11, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0xC2, 0x36, 0x52, 0x45,
-		0xCC, 0x35, 0xD8, 0xDB, 0xEB, 0xFD, 0xD1, 0x46,
-		0x76, 0x6B, 0x0B, 0xD5, 0x8B, 0xCC, 0x2B, 0xE2,
-		0xFE, 0x90, 0x83, 0x9E, 0xAE, 0x2D, 0x00, 0x00
-	}
-};
-
-static const struct nand_header_type {
-	const char *name;
-	const union nand_boot_header *data;
-} nand_headers[] = {
-	{
-		.name = "2k+64",
-		.data = &snand_hdr_2k_64_data
-	}, {
-		.name = "2k+120",
-		.data = &snand_hdr_2k_128_data
-	}, {
-		.name = "2k+128",
-		.data = &snand_hdr_2k_128_data
-	}, {
-		.name = "4k+256",
-		.data = &snand_hdr_4k_256_data
-	}, {
-		.name = "1g:2k+64",
-		.data = &nand_hdr_1gb_2k_64_data
-	}, {
-		.name = "2g:2k+64",
-		.data = &nand_hdr_2gb_2k_64_data
-	}, {
-		.name = "4g:2k+64",
-		.data = &nand_hdr_4gb_2k_64_data
-	}, {
-		.name = "2g:2k+128",
-		.data = &nand_hdr_2gb_2k_128_data
-	}, {
-		.name = "4g:2k+128",
-		.data = &nand_hdr_4gb_2k_128_data
-	}
-};
+#include "mtk_nand_headers.h"
 
 static const struct brom_img_type {
 	const char *name;
@@ -264,6 +55,7 @@ static uint32_t crc32tbl[256];
 
 /* NAND header selected by user */
 static const union nand_boot_header *hdr_nand;
+static uint32_t hdr_nand_size;
 
 /* GFH header + 2 * 4KB pages of NAND */
 static char hdr_tmp[sizeof(struct gfh_header) + 0x2000];
@@ -402,12 +194,7 @@ static int mtk_brom_parse_imagename(const char *imagename)
 	}
 
 	/* parse nand header type */
-	for (i = 0; i < ARRAY_SIZE(nand_headers); i++) {
-		if (!strcmp(nand_headers[i].name, nandinfo)) {
-			hdr_nand = nand_headers[i].data;
-			break;
-		}
-	}
+	hdr_nand = mtk_nand_header_find(nandinfo);
 
 	/* parse device header offset */
 	if (hdr_offs && hdr_offs[0])
@@ -432,6 +219,9 @@ static int mtk_brom_parse_imagename(const char *imagename)
 		return -EINVAL;
 	}
 
+	if (hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND)
+		hdr_nand_size = mtk_nand_header_size(hdr_nand);
+
 	return 0;
 }
 
@@ -468,7 +258,7 @@ static int mtk_image_vrec_header(struct image_tool_params *params,
 	}
 
 	if (hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND)
-		tparams->header_size = 2 * le16_to_cpu(hdr_nand->pagesize);
+		tparams->header_size = hdr_nand_size;
 	else
 		tparams->header_size = sizeof(struct gen_device_header);
 
@@ -566,16 +356,17 @@ static int mtk_image_verify_gen_header(const uint8_t *ptr, int print)
 
 static int mtk_image_verify_nand_header(const uint8_t *ptr, int print)
 {
-	union nand_boot_header *nh = (union nand_boot_header *)ptr;
 	struct brom_layout_header *bh;
+	struct nand_header_info info;
 	struct gfh_header *gfh;
 	const char *bootmedia;
+	int ret;
 
-	if (strncmp(nh->version, NAND_BOOT_VERSION, sizeof(nh->version)) ||
-	    strcmp(nh->id, NAND_BOOT_ID))
-		return -1;
+	ret = mtk_nand_header_info(ptr, &info);
+	if (ret < 0)
+		return ret;
 
-	bh = (struct brom_layout_header *)(ptr + le16_to_cpu(nh->pagesize));
+	bh = (struct brom_layout_header *)(ptr + info.page_size);
 
 	if (strcmp(bh->name, BRLYT_NAME))
 		return -1;
@@ -586,34 +377,23 @@ static int mtk_image_verify_nand_header(const uint8_t *ptr, int print)
 		if (le32_to_cpu(bh->type) == BRLYT_TYPE_NAND)
 			bootmedia = "Parallel NAND";
 		else if (le32_to_cpu(bh->type) == BRLYT_TYPE_SNAND)
-			bootmedia = "Serial NAND";
+			bootmedia = "Serial NAND (SNFI/AP)";
 		else
 			return -1;
 	}
 
 	if (print) {
-		printf("Boot Media: %s\n", bootmedia);
-
-		if (le32_to_cpu(bh->type) == BRLYT_TYPE_NAND) {
-			uint64_t capacity =
-				(uint64_t)le16_to_cpu(nh->numblocks) *
-				(uint64_t)le16_to_cpu(nh->pages_of_block) *
-				(uint64_t)le16_to_cpu(nh->pagesize) * 8;
-			printf("Capacity:     %dGb\n",
-			       (uint32_t)(capacity >> 30));
-		}
+		printf("Boot Media:   %s\n", bootmedia);
 
-		if (le16_to_cpu(nh->pagesize) >= 1024)
-			printf("Page Size:    %dKB\n",
-			       le16_to_cpu(nh->pagesize) >> 10);
+		if (info.page_size >= 1024)
+			printf("Page Size:    %dKB\n", info.page_size >> 10);
 		else
-			printf("Page Size:    %dB\n",
-			       le16_to_cpu(nh->pagesize));
+			printf("Page Size:    %dB\n", info.page_size);
 
-		printf("Spare Size:   %dB\n", le16_to_cpu(nh->oobsize));
+		printf("Spare Size:   %dB\n", info.spare_size);
 	}
 
-	gfh = (struct gfh_header *)(ptr + 2 * le16_to_cpu(nh->pagesize));
+	gfh = (struct gfh_header *)(ptr + info.gfh_offset);
 
 	return mtk_image_verify_gfh(gfh, GFH_FLASH_TYPE_NAND, print);
 }
@@ -713,7 +493,7 @@ static int mtk_image_verify_header(unsigned char *ptr, int image_size,
 	if (image_get_magic(hdr) == IH_MAGIC)
 		return mtk_image_verify_mt7621_header(ptr, 0);
 
-	if (!strcmp((char *)ptr, NAND_BOOT_NAME))
+	if (is_mtk_nand_header(ptr))
 		return mtk_image_verify_nand_header(ptr, 0);
 	else
 		return mtk_image_verify_gen_header(ptr, 0);
@@ -739,7 +519,7 @@ static void mtk_image_print_header(const void *ptr)
 		return;
 	}
 
-	if (!strcmp((char *)ptr, NAND_BOOT_NAME))
+	if (is_mtk_nand_header(ptr))
 		mtk_image_verify_nand_header(ptr, 1);
 	else
 		mtk_image_verify_gen_header(ptr, 1);
@@ -870,36 +650,33 @@ static void mtk_image_set_gen_header(void *ptr, off_t filesize,
 static void mtk_image_set_nand_header(void *ptr, off_t filesize,
 				      uint32_t loadaddr)
 {
-	union nand_boot_header *nh = (union nand_boot_header *)ptr;
 	struct brom_layout_header *brlyt;
 	struct gfh_header *gfh;
-	uint32_t payload_pages;
-	int i;
+	uint32_t payload_pages, nand_page_size;
 
-	/* NAND device header, repeat 4 times */
-	for (i = 0; i < 4; i++)
-		memcpy(nh + i, hdr_nand, sizeof(union nand_boot_header));
+	/* NAND header */
+	nand_page_size = mtk_nand_header_put(hdr_nand, ptr);
 
-	/* BRLYT header */
-	payload_pages = (filesize + le16_to_cpu(hdr_nand->pagesize) - 1) /
-			le16_to_cpu(hdr_nand->pagesize);
-	brlyt = (struct brom_layout_header *)
-		(ptr + le16_to_cpu(hdr_nand->pagesize));
-	put_brom_layout_header(brlyt, hdr_media);
-	brlyt->header_size = cpu_to_le32(2);
-	brlyt->total_size = cpu_to_le32(payload_pages);
-	brlyt->header_size_2 = brlyt->header_size;
-	brlyt->total_size_2 = brlyt->total_size;
-	brlyt->unused = cpu_to_le32(1);
+	if (nand_page_size) {
+		/* BRLYT header */
+		payload_pages = (filesize + nand_page_size - 1) /
+				nand_page_size;
+		brlyt = (struct brom_layout_header *)(ptr + nand_page_size);
+		put_brom_layout_header(brlyt, hdr_media);
+		brlyt->header_size = cpu_to_le32(2);
+		brlyt->total_size = cpu_to_le32(payload_pages);
+		brlyt->header_size_2 = brlyt->header_size;
+		brlyt->total_size_2 = brlyt->total_size;
+		brlyt->unused = cpu_to_le32(1);
+	}
 
 	/* GFH header */
-	gfh = (struct gfh_header *)(ptr + 2 * le16_to_cpu(hdr_nand->pagesize));
-	put_ghf_header(gfh, filesize, 2 * le16_to_cpu(hdr_nand->pagesize),
-		       loadaddr, GFH_FLASH_TYPE_NAND);
+	gfh = (struct gfh_header *)(ptr + hdr_nand_size);
+	put_ghf_header(gfh, filesize, hdr_nand_size, loadaddr,
+		       GFH_FLASH_TYPE_NAND);
 
 	/* Generate SHA256 hash */
-	put_hash((uint8_t *)gfh,
-		 filesize - 2 * le16_to_cpu(hdr_nand->pagesize) - SHA256_SUM_LEN);
+	put_hash((uint8_t *)gfh, filesize - hdr_nand_size - SHA256_SUM_LEN);
 }
 
 static void mtk_image_set_mt7621_header(void *ptr, off_t filesize,
diff --git a/tools/mtk_image.h b/tools/mtk_image.h
index d868545a33..fad9372100 100644
--- a/tools/mtk_image.h
+++ b/tools/mtk_image.h
@@ -26,31 +26,6 @@ union gen_boot_header {
 #define SF_BOOT_NAME		"SF_BOOT"
 #define SDMMC_BOOT_NAME		"SDMMC_BOOT"
 
-/* Header for NAND */
-union nand_boot_header {
-	struct {
-		char name[12];
-		char version[4];
-		char id[8];
-		uint16_t ioif;
-		uint16_t pagesize;
-		uint16_t addrcycles;
-		uint16_t oobsize;
-		uint16_t pages_of_block;
-		uint16_t numblocks;
-		uint16_t writesize_shift;
-		uint16_t erasesize_shift;
-		uint8_t dummy[60];
-		uint8_t ecc_parity[28];
-	};
-
-	uint8_t data[0x80];
-};
-
-#define NAND_BOOT_NAME		"BOOTLOADER!"
-#define NAND_BOOT_VERSION	"V006"
-#define NAND_BOOT_ID		"NFIINFO"
-
 /* BootROM layout header */
 struct brom_layout_header {
 	char name[8];
diff --git a/tools/mtk_nand_headers.c b/tools/mtk_nand_headers.c
new file mode 100644
index 0000000000..12f827c39f
--- /dev/null
+++ b/tools/mtk_nand_headers.c
@@ -0,0 +1,286 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * MediaTek BootROM NAND header definitions
+ *
+ * Copyright (C) 2022 MediaTek Inc.
+ * Author: Weijie Gao <weijie.gao@mediatek.com>
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include "imagetool.h"
+#include "mtk_image.h"
+#include "mtk_nand_headers.h"
+
+/* NAND header for SPI-NAND with 2KB page + 64B spare */
+static const union nand_boot_header snand_hdr_2k_64_data = {
+	.data = {
+		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
+		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
+		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
+		0x00, 0x00, 0x00, 0x08, 0x03, 0x00, 0x40, 0x00,
+		0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x7B, 0xC4, 0x17, 0x9D,
+		0xCA, 0x42, 0x90, 0xD0, 0x98, 0xD0, 0xE0, 0xF7,
+		0xDB, 0xCD, 0x16, 0xF6, 0x03, 0x73, 0xD2, 0xB8,
+		0x93, 0xB2, 0x56, 0x5A, 0x84, 0x6E, 0x00, 0x00
+	}
+};
+
+/* NAND header for SPI-NAND with 2KB page + 120B/128B spare */
+static const union nand_boot_header snand_hdr_2k_128_data = {
+	.data = {
+		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
+		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
+		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
+		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
+		0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x90, 0x28, 0xED, 0x13,
+		0x7F, 0x12, 0x22, 0xCD, 0x3D, 0x06, 0xF1, 0xB3,
+		0x6F, 0x2E, 0xD9, 0xA0, 0x9D, 0x7A, 0xBD, 0xD7,
+		0xB3, 0x28, 0x3C, 0x13, 0xDB, 0x4E, 0x00, 0x00
+	}
+};
+
+/* NAND header for SPI-NAND with 4KB page + 256B spare */
+static const union nand_boot_header snand_hdr_4k_256_data = {
+	.data = {
+		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
+		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
+		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
+		0x00, 0x00, 0x00, 0x10, 0x05, 0x00, 0xE0, 0x00,
+		0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x47, 0xED, 0x0E, 0xC3,
+		0x83, 0xBF, 0x41, 0xD2, 0x85, 0x21, 0x97, 0x57,
+		0xC4, 0x2E, 0x6B, 0x7A, 0x40, 0xE0, 0xCF, 0x8F,
+		0x37, 0xBD, 0x17, 0xB6, 0xC7, 0xFE, 0x00, 0x00
+	}
+};
+
+/* NAND header for Parallel NAND 1Gb with 2KB page + 64B spare */
+static const union nand_boot_header nand_hdr_1gb_2k_64_data = {
+	.data = {
+		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
+		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
+		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
+		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
+		0x40, 0x00, 0x00, 0x04, 0x0B, 0x00, 0x11, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x12, 0x28, 0x1C, 0x12,
+		0x8F, 0xFD, 0xF8, 0x32, 0x6F, 0x6D, 0xCF, 0x6C,
+		0xDA, 0x21, 0x70, 0x8C, 0xDA, 0x0A, 0x22, 0x82,
+		0xAA, 0x59, 0xFA, 0x7C, 0x42, 0x2D, 0x00, 0x00
+	}
+};
+
+/* NAND header for Parallel NAND 2Gb with 2KB page + 64B spare */
+static const union nand_boot_header nand_hdr_2gb_2k_64_data = {
+	.data = {
+		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
+		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
+		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
+		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
+		0x40, 0x00, 0x00, 0x08, 0x0B, 0x00, 0x11, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x20, 0x9C, 0x3D, 0x2D,
+		0x7B, 0x68, 0x63, 0x52, 0x2E, 0x04, 0x63, 0xF1,
+		0x35, 0x4E, 0x44, 0x3E, 0xF8, 0xAC, 0x9B, 0x95,
+		0xAB, 0xFE, 0xE4, 0xE1, 0xD5, 0xF9, 0x00, 0x00
+	}
+};
+
+/* NAND header for Parallel NAND 4Gb with 2KB page + 64B spare */
+static const union nand_boot_header nand_hdr_4gb_2k_64_data = {
+	.data = {
+		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
+		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
+		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
+		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
+		0x40, 0x00, 0x00, 0x10, 0x0B, 0x00, 0x11, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0xE3, 0x0F, 0x86, 0x32,
+		0x68, 0x05, 0xD9, 0xC8, 0x13, 0xDF, 0xC5, 0x0B,
+		0x35, 0x3A, 0x68, 0xA5, 0x3C, 0x0C, 0x73, 0x87,
+		0x63, 0xB0, 0xBE, 0xCC, 0x84, 0x47, 0x00, 0x00
+	}
+};
+
+/* NAND header for Parallel NAND 2Gb with 2KB page + 128B spare */
+static const union nand_boot_header nand_hdr_2gb_2k_128_data = {
+	.data = {
+		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
+		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
+		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
+		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
+		0x40, 0x00, 0x00, 0x08, 0x0B, 0x00, 0x11, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x01, 0xA5, 0xE9, 0x5A,
+		0xDF, 0x58, 0x62, 0x41, 0xD6, 0x26, 0x77, 0xBC,
+		0x76, 0x1F, 0x27, 0x4E, 0x4F, 0x6C, 0xC3, 0xF0,
+		0x36, 0xDE, 0xD9, 0xB3, 0xFF, 0x93, 0x00, 0x00
+	}
+};
+
+/* NAND header for Parallel NAND 4Gb with 2KB page + 128B spare */
+static const union nand_boot_header nand_hdr_4gb_2k_128_data = {
+	.data = {
+		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
+		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
+		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
+		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
+		0x40, 0x00, 0x00, 0x10, 0x0B, 0x00, 0x11, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0xC2, 0x36, 0x52, 0x45,
+		0xCC, 0x35, 0xD8, 0xDB, 0xEB, 0xFD, 0xD1, 0x46,
+		0x76, 0x6B, 0x0B, 0xD5, 0x8B, 0xCC, 0x2B, 0xE2,
+		0xFE, 0x90, 0x83, 0x9E, 0xAE, 0x2D, 0x00, 0x00
+	}
+};
+
+static const struct nand_header_type {
+	const char *name;
+	const union nand_boot_header *data;
+} nand_headers[] = {
+	{
+		.name = "2k+64",
+		.data = &snand_hdr_2k_64_data
+	}, {
+		.name = "2k+120",
+		.data = &snand_hdr_2k_128_data
+	}, {
+		.name = "2k+128",
+		.data = &snand_hdr_2k_128_data
+	}, {
+		.name = "4k+256",
+		.data = &snand_hdr_4k_256_data
+	}, {
+		.name = "1g:2k+64",
+		.data = &nand_hdr_1gb_2k_64_data
+	}, {
+		.name = "2g:2k+64",
+		.data = &nand_hdr_2gb_2k_64_data
+	}, {
+		.name = "4g:2k+64",
+		.data = &nand_hdr_4gb_2k_64_data
+	}, {
+		.name = "2g:2k+128",
+		.data = &nand_hdr_2gb_2k_128_data
+	}, {
+		.name = "4g:2k+128",
+		.data = &nand_hdr_4gb_2k_128_data
+	}
+};
+
+const union nand_boot_header *mtk_nand_header_find(const char *name)
+{
+	uint32_t i;
+
+	for (i = 0; i < ARRAY_SIZE(nand_headers); i++) {
+		if (!strcmp(nand_headers[i].name, name))
+			return nand_headers[i].data;
+	}
+
+	return NULL;
+}
+
+uint32_t mtk_nand_header_size(const union nand_boot_header *hdr_nand)
+{
+	return 2 * le16_to_cpu(hdr_nand->pagesize);
+}
+
+static int mtk_nand_header_ap_info(const void *ptr,
+				   struct nand_header_info *info)
+{
+	union nand_boot_header *nh = (union nand_boot_header *)ptr;
+
+	if (strncmp(nh->version, NAND_BOOT_VERSION, sizeof(nh->version)) ||
+	    strcmp(nh->id, NAND_BOOT_ID))
+		return -1;
+
+	info->page_size = le16_to_cpu(nh->pagesize);
+	info->spare_size = le16_to_cpu(nh->oobsize);
+	info->gfh_offset = 2 * info->page_size;
+
+	return 0;
+}
+
+int mtk_nand_header_info(const void *ptr, struct nand_header_info *info)
+{
+	if (!strcmp((char *)ptr, NAND_BOOT_NAME))
+		return mtk_nand_header_ap_info(ptr, info);
+
+	return -1;
+}
+
+bool is_mtk_nand_header(const void *ptr)
+{
+	struct nand_header_info info;
+
+	if (mtk_nand_header_info(ptr, &info) >= 0)
+		return true;
+
+	return false;
+}
+
+uint32_t mtk_nand_header_put(const union nand_boot_header *hdr_nand, void *ptr)
+{
+	union nand_boot_header *nh = (union nand_boot_header *)ptr;
+	int i;
+
+	/* NAND device header, repeat 4 times */
+	for (i = 0; i < 4; i++)
+		memcpy(nh + i, hdr_nand, sizeof(union nand_boot_header));
+
+	return le16_to_cpu(hdr_nand->pagesize);
+}
diff --git a/tools/mtk_nand_headers.h b/tools/mtk_nand_headers.h
new file mode 100644
index 0000000000..20506cab38
--- /dev/null
+++ b/tools/mtk_nand_headers.h
@@ -0,0 +1,61 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * MediaTek BootROM NAND header definitions
+ *
+ * Copyright (C) 2022 MediaTek Inc.
+ * Author: Weijie Gao <weijie.gao@mediatek.com>
+ */
+
+#ifndef _MTK_NAND_HEADERS_H
+#define _MTK_NAND_HEADERS_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+struct nand_header_info {
+	uint32_t page_size;
+	uint32_t spare_size;
+	uint32_t gfh_offset;
+};
+
+/* AP BROM Header for NAND */
+union nand_boot_header {
+	struct {
+		char name[12];
+		char version[4];
+		char id[8];
+		uint16_t ioif;			/* I/O interface */
+		uint16_t pagesize;		/* NAND page size */
+		uint16_t addrcycles;		/* Address cycles */
+		uint16_t oobsize;		/* NAND page spare size */
+		uint16_t pages_of_block;	/* Pages of one block */
+		uint16_t numblocks;		/* Total blocks of NAND chip */
+		uint16_t writesize_shift;
+		uint16_t erasesize_shift;
+		uint8_t dummy[60];
+		uint8_t ecc_parity[28];		/* ECC parity of this header */
+	};
+
+	uint8_t data[0x80];
+};
+
+#define NAND_BOOT_NAME		"BOOTLOADER!"
+#define NAND_BOOT_VERSION	"V006"
+#define NAND_BOOT_ID		"NFIINFO"
+
+/* Find nand header data by name */
+const union nand_boot_header *mtk_nand_header_find(const char *name);
+
+/* Device header size using this nand header */
+uint32_t mtk_nand_header_size(const union nand_boot_header *hdr_nand);
+
+/* Get nand info from nand header (page size, spare size, ...) */
+int mtk_nand_header_info(const void *ptr, struct nand_header_info *info);
+
+/* Whether given header data is valid */
+bool is_mtk_nand_header(const void *ptr);
+
+/* Generate Device header using give nand header */
+uint32_t mtk_nand_header_put(const union nand_boot_header *hdr_nand, void *ptr);
+
+#endif /* _MTK_NAND_HEADERS_H */
-- 
2.17.1


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

* [PATCH v2 31/32] tools: mtk_image: add support for nand headers used by newer chips
  2022-08-31 11:00 [PATCH v2 00/32] Add support for MediaTek MT7981/MT7986 SoCs - v2 Weijie Gao
                   ` (29 preceding siblings ...)
  2022-08-31 11:05 ` [PATCH v2 30/32] tools: mtk_image: split the code of generating NAND header into a new file Weijie Gao
@ 2022-08-31 11:05 ` Weijie Gao
  2022-09-01  0:32   ` Daniel Golle
  2022-08-31 11:05 ` [PATCH v2 32/32] MAINTAINERS: update maintainer for MediaTek ARM platform Weijie Gao
  31 siblings, 1 reply; 60+ messages in thread
From: Weijie Gao @ 2022-08-31 11:05 UTC (permalink / raw)
  To: u-boot; +Cc: GSS_MTK_Uboot_upstream, Weijie Gao

This patch adds more nand headers in two new types:
1. HSM header, used for spi-nand thru SNFI interface
2. SPIM header, used for spi-nand thru spi-mem interface

The original nand header is renamed to AP header.

Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
---
v2 changes: none
---
 tools/mtk_image.c        |  23 ++-
 tools/mtk_nand_headers.c | 422 +++++++++++++++++++++++++++++++++++++--
 tools/mtk_nand_headers.h | 110 +++++++++-
 3 files changed, 525 insertions(+), 30 deletions(-)

diff --git a/tools/mtk_image.c b/tools/mtk_image.c
index 1f7396aa69..9b3136afa3 100644
--- a/tools/mtk_image.c
+++ b/tools/mtk_image.c
@@ -33,6 +33,9 @@ static const struct brom_img_type {
 	}, {
 		.name = "snand",
 		.type = BRLYT_TYPE_SNAND
+	}, {
+		.name = "spim-nand",
+		.type = BRLYT_TYPE_SNAND
 	}
 };
 
@@ -54,7 +57,7 @@ static char lk_name[32] = "U-Boot";
 static uint32_t crc32tbl[256];
 
 /* NAND header selected by user */
-static const union nand_boot_header *hdr_nand;
+static const struct nand_header_type *hdr_nand;
 static uint32_t hdr_nand_size;
 
 /* GFH header + 2 * 4KB pages of NAND */
@@ -366,20 +369,26 @@ static int mtk_image_verify_nand_header(const uint8_t *ptr, int print)
 	if (ret < 0)
 		return ret;
 
-	bh = (struct brom_layout_header *)(ptr + info.page_size);
+	if (!ret) {
+		bh = (struct brom_layout_header *)(ptr + info.page_size);
 
-	if (strcmp(bh->name, BRLYT_NAME))
-		return -1;
+		if (strcmp(bh->name, BRLYT_NAME))
+			return -1;
+
+		if (le32_to_cpu(bh->magic) != BRLYT_MAGIC)
+			return -1;
 
-	if (le32_to_cpu(bh->magic) != BRLYT_MAGIC) {
-		return -1;
-	} else {
 		if (le32_to_cpu(bh->type) == BRLYT_TYPE_NAND)
 			bootmedia = "Parallel NAND";
 		else if (le32_to_cpu(bh->type) == BRLYT_TYPE_SNAND)
 			bootmedia = "Serial NAND (SNFI/AP)";
 		else
 			return -1;
+	} else {
+		if (info.snfi)
+			bootmedia = "Serial NAND (SNFI/HSM)";
+		else
+			bootmedia = "Serial NAND (SPIM)";
 	}
 
 	if (print) {
diff --git a/tools/mtk_nand_headers.c b/tools/mtk_nand_headers.c
index 12f827c39f..2fa91e7af0 100644
--- a/tools/mtk_nand_headers.c
+++ b/tools/mtk_nand_headers.c
@@ -188,55 +188,346 @@ static const union nand_boot_header nand_hdr_4gb_2k_128_data = {
 	}
 };
 
-static const struct nand_header_type {
+/* HSM BROM NAND header for SPI NAND with 2KB page + 64B spare */
+static const union hsm_nand_boot_header hsm_nand_hdr_2k_64_data = {
+	.data = {
+		0x4E, 0x41, 0x4E, 0x44, 0x43, 0x46, 0x47, 0x21,
+		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x08, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+		0x40, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+		0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+		0xFF, 0x00, 0x00, 0x00, 0x21, 0xD2, 0xEE, 0xF6,
+		0xAE, 0xDD, 0x5E, 0xC2, 0x82, 0x8E, 0x9A, 0x62,
+		0x09, 0x8E, 0x80, 0xE2, 0x37, 0x0D, 0xC9, 0xFA,
+		0xA9, 0xDD, 0xFC, 0x92, 0x34, 0x2A, 0xED, 0x51,
+		0xA4, 0x1B, 0xF7, 0x63, 0xCC, 0x5A, 0xC7, 0xFB,
+		0xED, 0x21, 0x02, 0x23, 0x51, 0x31
+	}
+};
+
+/* HSM BROM NAND header for SPI NAND with 2KB page + 128B spare */
+static const union hsm_nand_boot_header hsm_nand_hdr_2k_128_data = {
+	.data = {
+		0x4E, 0x41, 0x4E, 0x44, 0x43, 0x46, 0x47, 0x21,
+		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x08, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+		0x40, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
+		0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+		0xFF, 0x00, 0x00, 0x00, 0x71, 0x7f, 0x71, 0xAC,
+		0x42, 0xD0, 0x5B, 0xD2, 0x12, 0x81, 0x15, 0x0A,
+		0x0C, 0xD4, 0xF6, 0x32, 0x1E, 0x63, 0xE7, 0x81,
+		0x8A, 0x7F, 0xDE, 0xF9, 0x4B, 0x91, 0xEC, 0xC2,
+		0x70, 0x00, 0x7F, 0x57, 0xAF, 0xDC, 0xE4, 0x24,
+		0x57, 0x09, 0xBC, 0xC5, 0x35, 0xDC
+	}
+};
+
+/* HSM BROM NAND header for SPI NAND with 4KB page + 256B spare */
+static const union hsm_nand_boot_header hsm_nand_hdr_4k_256_data = {
+	.data = {
+		0x4E, 0x41, 0x4E, 0x44, 0x43, 0x46, 0x47, 0x21,
+		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+		0x40, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+		0x0C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+		0xFF, 0x00, 0x00, 0x00, 0x62, 0x04, 0xD6, 0x1F,
+		0x2B, 0x57, 0x7A, 0x2D, 0xFE, 0xBB, 0x4A, 0x50,
+		0xEC, 0xF8, 0x70, 0x1A, 0x44, 0x15, 0xF6, 0xA2,
+		0x8E, 0xB0, 0xFD, 0xFA, 0xDC, 0xAA, 0x5A, 0x4E,
+		0xCB, 0x8E, 0xC9, 0x72, 0x08, 0xDC, 0x20, 0xB9,
+		0x98, 0xC8, 0x82, 0xD8, 0xBE, 0x44
+	}
+};
+
+/* HSM2.0 BROM NAND header for SPI NAND with 2KB page + 64B spare */
+static const union hsm20_nand_boot_header hsm20_nand_hdr_2k_64_data = {
+	.data = {
+		0x4E, 0x41, 0x4E, 0x44, 0x43, 0x46, 0x47, 0x21,
+		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+		0x00, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x08, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+		0x40, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+		0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+		0x01, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00,
+		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x5F, 0x4B, 0xB2, 0x5B, 0x8B, 0x1C, 0x35, 0xDA,
+		0x83, 0xE6, 0x6C, 0xC3, 0xFB, 0x8C, 0x78, 0x23,
+		0xD0, 0x89, 0x24, 0xD9, 0x6C, 0x35, 0x2C, 0x5D,
+		0x8F, 0xBB, 0xFC, 0x10, 0xD0, 0xE2, 0x22, 0x7D,
+		0xC8, 0x97, 0x9A, 0xEF, 0xC6, 0xB5, 0xA7, 0x4E,
+		0x4E, 0x0E
+	}
+};
+
+/* HSM2.0 BROM NAND header for SPI NAND with 2KB page + 128B spare */
+static const union hsm20_nand_boot_header hsm20_nand_hdr_2k_128_data = {
+	.data = {
+		0x4E, 0x41, 0x4E, 0x44, 0x43, 0x46, 0x47, 0x21,
+		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+		0x00, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x08, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+		0x40, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+		0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+		0x01, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00,
+		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0xF8, 0x7E, 0xC1, 0x5D, 0x61, 0x54, 0xEA, 0x9F,
+		0x5E, 0x66, 0x39, 0x66, 0x21, 0xFF, 0x8C, 0x3B,
+		0xBE, 0xA7, 0x5A, 0x9E, 0xD7, 0xBD, 0x9E, 0x89,
+		0xEE, 0x7E, 0x10, 0x31, 0x9A, 0x1D, 0x82, 0x49,
+		0xA3, 0x4E, 0xD8, 0x47, 0xD7, 0x19, 0xF4, 0x2D,
+		0x8E, 0x53
+	}
+};
+
+/* HSM2.0 BROM NAND header for SPI NAND with 4KB page + 256B spare */
+static const union hsm20_nand_boot_header hsm20_nand_hdr_4k_256_data = {
+	.data = {
+		0x4E, 0x41, 0x4E, 0x44, 0x43, 0x46, 0x47, 0x21,
+		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+		0x00, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+		0x40, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+		0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+		0x01, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00,
+		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x79, 0x01, 0x1F, 0x86, 0x62, 0x6A, 0x43, 0xAE,
+		0xE6, 0xF8, 0xDD, 0x5B, 0x29, 0xB7, 0xA2, 0x7F,
+		0x29, 0x72, 0x54, 0x37, 0xBE, 0x50, 0xD4, 0x24,
+		0xAB, 0x60, 0xF4, 0x44, 0x97, 0x3B, 0x65, 0x21,
+		0x73, 0x24, 0x1F, 0x93, 0x0E, 0x9E, 0x96, 0x88,
+		0x78, 0x6C
+	}
+};
+
+/* SPIM-NAND header for SPI NAND with 2KB page + 64B spare */
+static const union spim_nand_boot_header spim_nand_hdr_2k_64_data = {
+	.data = {
+		0x53, 0x50, 0x49, 0x4e, 0x41, 0x4e, 0x44, 0x21,
+		0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+		0x00, 0x08, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+		0x40, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x20, 0x30,
+		0x01, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+	}
+};
+
+/* SPIM-NAND header for SPI NAND with 2KB page + 128B spare */
+static const union spim_nand_boot_header spim_nand_hdr_2k_128_data = {
+	.data = {
+		0x53, 0x50, 0x49, 0x4e, 0x41, 0x4e, 0x44, 0x21,
+		0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+		0x00, 0x08, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+		0x40, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x20, 0x30,
+		0x01, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+	}
+};
+
+/* SPIM-NAND header for SPI NAND with 4KB page + 256B spare */
+static const union spim_nand_boot_header spim_nand_hdr_4k_256_data = {
+	.data = {
+		0x53, 0x50, 0x49, 0x4e, 0x41, 0x4e, 0x44, 0x21,
+		0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+		0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+		0x40, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x20, 0x30,
+		0x01, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+	}
+};
+
+struct nand_header_type {
 	const char *name;
-	const union nand_boot_header *data;
+	enum nand_boot_header_type type;
+	union {
+		const union nand_boot_header *ap;
+		const union hsm_nand_boot_header *hsm;
+		const union hsm20_nand_boot_header *hsm20;
+		const union spim_nand_boot_header *spim;
+	};
 } nand_headers[] = {
 	{
 		.name = "2k+64",
-		.data = &snand_hdr_2k_64_data
+		.type = NAND_BOOT_AP_HEADER,
+		.ap = &snand_hdr_2k_64_data,
 	}, {
 		.name = "2k+120",
-		.data = &snand_hdr_2k_128_data
+		.type = NAND_BOOT_AP_HEADER,
+		.ap = &snand_hdr_2k_128_data,
 	}, {
 		.name = "2k+128",
-		.data = &snand_hdr_2k_128_data
+		.type = NAND_BOOT_AP_HEADER,
+		.ap = &snand_hdr_2k_128_data,
 	}, {
 		.name = "4k+256",
-		.data = &snand_hdr_4k_256_data
+		.type = NAND_BOOT_AP_HEADER,
+		.ap = &snand_hdr_4k_256_data,
 	}, {
 		.name = "1g:2k+64",
-		.data = &nand_hdr_1gb_2k_64_data
+		.type = NAND_BOOT_AP_HEADER,
+		.ap = &nand_hdr_1gb_2k_64_data,
 	}, {
 		.name = "2g:2k+64",
-		.data = &nand_hdr_2gb_2k_64_data
+		.type = NAND_BOOT_AP_HEADER,
+		.ap = &nand_hdr_2gb_2k_64_data,
 	}, {
 		.name = "4g:2k+64",
-		.data = &nand_hdr_4gb_2k_64_data
+		.type = NAND_BOOT_AP_HEADER,
+		.ap = &nand_hdr_4gb_2k_64_data,
 	}, {
 		.name = "2g:2k+128",
-		.data = &nand_hdr_2gb_2k_128_data
+		.type = NAND_BOOT_AP_HEADER,
+		.ap = &nand_hdr_2gb_2k_128_data,
 	}, {
 		.name = "4g:2k+128",
-		.data = &nand_hdr_4gb_2k_128_data
+		.type = NAND_BOOT_AP_HEADER,
+		.ap = &nand_hdr_4gb_2k_128_data,
+	}, {
+		.name = "hsm:2k+64",
+		.type = NAND_BOOT_HSM_HEADER,
+		.hsm = &hsm_nand_hdr_2k_64_data,
+	}, {
+		.name = "hsm:2k+128",
+		.type = NAND_BOOT_HSM_HEADER,
+		.hsm = &hsm_nand_hdr_2k_128_data,
+	}, {
+		.name = "hsm:4k+256",
+		.type = NAND_BOOT_HSM_HEADER,
+		.hsm = &hsm_nand_hdr_4k_256_data,
+	},  {
+		.name = "hsm20:2k+64",
+		.type = NAND_BOOT_HSM20_HEADER,
+		.hsm20 = &hsm20_nand_hdr_2k_64_data,
+	}, {
+		.name = "hsm20:2k+128",
+		.type = NAND_BOOT_HSM20_HEADER,
+		.hsm20 = &hsm20_nand_hdr_2k_128_data,
+	}, {
+		.name = "hsm20:4k+256",
+		.type = NAND_BOOT_HSM20_HEADER,
+		.hsm20 = &hsm20_nand_hdr_4k_256_data,
+	}, {
+		.name = "spim:2k+64",
+		.type = NAND_BOOT_SPIM_HEADER,
+		.spim = &spim_nand_hdr_2k_64_data,
+	}, {
+		.name = "spim:2k+128",
+		.type = NAND_BOOT_SPIM_HEADER,
+		.spim = &spim_nand_hdr_2k_128_data,
+	}, {
+		.name = "spim:4k+256",
+		.type = NAND_BOOT_SPIM_HEADER,
+		.spim = &spim_nand_hdr_4k_256_data,
 	}
 };
 
-const union nand_boot_header *mtk_nand_header_find(const char *name)
+const struct nand_header_type *mtk_nand_header_find(const char *name)
 {
 	uint32_t i;
 
 	for (i = 0; i < ARRAY_SIZE(nand_headers); i++) {
 		if (!strcmp(nand_headers[i].name, name))
-			return nand_headers[i].data;
+			return &nand_headers[i];
 	}
 
 	return NULL;
 }
 
-uint32_t mtk_nand_header_size(const union nand_boot_header *hdr_nand)
+uint32_t mtk_nand_header_size(const struct nand_header_type *hdr_nand)
 {
-	return 2 * le16_to_cpu(hdr_nand->pagesize);
+	switch (hdr_nand->type) {
+	case NAND_BOOT_HSM_HEADER:
+		return le32_to_cpu(hdr_nand->hsm->page_size);
+
+	case NAND_BOOT_HSM20_HEADER:
+		return le32_to_cpu(hdr_nand->hsm20->page_size);
+
+	case NAND_BOOT_SPIM_HEADER:
+		return le32_to_cpu(hdr_nand->spim->page_size);
+
+	default:
+		return 2 * le16_to_cpu(hdr_nand->ap->pagesize);
+	}
 }
 
 static int mtk_nand_header_ap_info(const void *ptr,
@@ -251,14 +542,45 @@ static int mtk_nand_header_ap_info(const void *ptr,
 	info->page_size = le16_to_cpu(nh->pagesize);
 	info->spare_size = le16_to_cpu(nh->oobsize);
 	info->gfh_offset = 2 * info->page_size;
+	info->snfi = true;
 
 	return 0;
 }
 
+static int mtk_nand_header_hsm_info(const void *ptr,
+				    struct nand_header_info *info)
+{
+	union hsm_nand_boot_header *nh = (union hsm_nand_boot_header *)ptr;
+
+	info->page_size = le16_to_cpu(nh->page_size);
+	info->spare_size = le16_to_cpu(nh->spare_size);
+	info->gfh_offset = info->page_size;
+	info->snfi = true;
+
+	return 1;
+}
+
+static int mtk_nand_header_spim_info(const void *ptr,
+				     struct nand_header_info *info)
+{
+	union spim_nand_boot_header *nh = (union spim_nand_boot_header *)ptr;
+
+	info->page_size = le16_to_cpu(nh->page_size);
+	info->spare_size = le16_to_cpu(nh->spare_size);
+	info->gfh_offset = info->page_size;
+	info->snfi = false;
+
+	return 1;
+}
+
 int mtk_nand_header_info(const void *ptr, struct nand_header_info *info)
 {
 	if (!strcmp((char *)ptr, NAND_BOOT_NAME))
 		return mtk_nand_header_ap_info(ptr, info);
+	else if (!strncmp((char *)ptr, HSM_NAND_BOOT_NAME, 8))
+		return mtk_nand_header_hsm_info(ptr, info);
+	else if (!strncmp((char *)ptr, SPIM_NAND_BOOT_NAME, 8))
+		return mtk_nand_header_spim_info(ptr, info);
 
 	return -1;
 }
@@ -273,14 +595,74 @@ bool is_mtk_nand_header(const void *ptr)
 	return false;
 }
 
-uint32_t mtk_nand_header_put(const union nand_boot_header *hdr_nand, void *ptr)
+static uint16_t crc16(const uint8_t *p, uint32_t len)
+{
+	uint16_t crc = 0x4f4e;
+	uint32_t i;
+
+	while (len--) {
+		crc ^= *p++ << 8;
+		for (i = 0; i < 8; i++)
+			crc = (crc << 1) ^ ((crc & 0x8000) ? 0x8005 : 0);
+	}
+
+	return crc;
+}
+
+static uint32_t mtk_nand_header_put_ap(const struct nand_header_type *hdr_nand,
+				       void *ptr)
 {
-	union nand_boot_header *nh = (union nand_boot_header *)ptr;
 	int i;
 
 	/* NAND device header, repeat 4 times */
-	for (i = 0; i < 4; i++)
-		memcpy(nh + i, hdr_nand, sizeof(union nand_boot_header));
+	for (i = 0; i < 4; i++) {
+		memcpy(ptr, hdr_nand->ap, sizeof(*hdr_nand->ap));
+		ptr += sizeof(*hdr_nand->ap);
+	}
 
-	return le16_to_cpu(hdr_nand->pagesize);
+	return le16_to_cpu(hdr_nand->ap->pagesize);
+}
+
+static uint32_t mtk_nand_header_put_hsm(const struct nand_header_type *hdr_nand,
+					void *ptr)
+{
+	memcpy(ptr, hdr_nand->hsm, sizeof(*hdr_nand->hsm));
+	return 0;
+}
+
+static uint32_t mtk_nand_header_put_hsm20(const struct nand_header_type *hdr_nand,
+					  void *ptr)
+{
+	memcpy(ptr, hdr_nand->hsm20, sizeof(*hdr_nand->hsm20));
+	return 0;
+}
+
+static uint32_t mtk_nand_header_put_spim(const struct nand_header_type *hdr_nand,
+					 void *ptr)
+{
+	uint16_t crc;
+
+	memcpy(ptr, hdr_nand->spim, sizeof(*hdr_nand->spim));
+
+	crc = crc16(ptr, 0x4e);
+	memcpy(ptr + 0x4e, &crc, sizeof(uint16_t));
+
+	return 0;
+}
+
+uint32_t mtk_nand_header_put(const struct nand_header_type *hdr_nand, void *ptr)
+{
+	switch (hdr_nand->type) {
+	case NAND_BOOT_HSM_HEADER:
+		return mtk_nand_header_put_hsm(hdr_nand, ptr);
+
+	case NAND_BOOT_HSM20_HEADER:
+		return mtk_nand_header_put_hsm20(hdr_nand, ptr);
+
+	case NAND_BOOT_SPIM_HEADER:
+		return mtk_nand_header_put_spim(hdr_nand, ptr);
+
+	default:
+		return mtk_nand_header_put_ap(hdr_nand, ptr);
+	}
 }
diff --git a/tools/mtk_nand_headers.h b/tools/mtk_nand_headers.h
index 20506cab38..9b1c4bab11 100644
--- a/tools/mtk_nand_headers.h
+++ b/tools/mtk_nand_headers.h
@@ -16,6 +16,7 @@ struct nand_header_info {
 	uint32_t page_size;
 	uint32_t spare_size;
 	uint32_t gfh_offset;
+	bool snfi;
 };
 
 /* AP BROM Header for NAND */
@@ -39,15 +40,117 @@ union nand_boot_header {
 	uint8_t data[0x80];
 };
 
+/* HSM BROM Header for NAND */
+union hsm_nand_boot_header {
+	struct {
+		char id[8];
+		uint32_t version;		/* Header version */
+		uint32_t config;		/* Header config */
+		uint32_t sector_size;		/* ECC step size */
+		uint32_t fdm_size;		/* User OOB size of a step */
+		uint32_t fdm_ecc_size;		/* ECC parity size of a step */
+		uint32_t lbs;
+		uint32_t page_size;		/* NAND page size */
+		uint32_t spare_size;		/* NAND page spare size */
+		uint32_t page_per_block;	/* Pages of one block */
+		uint32_t blocks;		/* Total blocks of NAND chip */
+		uint32_t plane_sel_position;	/* Plane bit position */
+		uint32_t pll;			/* Value of pll reg */
+		uint32_t acccon;		/* Value of access timing reg */
+		uint32_t strobe_sel;		/* Value of DQS selection reg*/
+		uint32_t acccon1;		/* Value of access timing reg */
+		uint32_t dqs_mux;		/* Value of DQS mux reg */
+		uint32_t dqs_ctrl;		/* Value of DQS control reg */
+		uint32_t delay_ctrl;		/* Value of delay ctrl reg */
+		uint32_t latch_lat;		/* Value of latch latency reg */
+		uint32_t sample_delay;		/* Value of sample delay reg */
+		uint32_t driving;		/* Value of driving reg */
+		uint32_t bl_start;		/* Bootloader start addr */
+		uint32_t bl_end;		/* Bootloader end addr */
+		uint8_t ecc_parity[42];		/* ECC parity of this header */
+	};
+
+	uint8_t data[0x8E];
+};
+
+/* HSM2.0 BROM Header for NAND */
+union hsm20_nand_boot_header {
+	struct {
+		char id[8];
+		uint32_t version;		/* Header version */
+		uint32_t config;		/* Header config */
+		uint32_t sector_size;		/* ECC step size */
+		uint32_t fdm_size;		/* User OOB size of a step */
+		uint32_t fdm_ecc_size;		/* ECC parity size of a step */
+		uint32_t lbs;
+		uint32_t page_size;		/* NAND page size */
+		uint32_t spare_size;		/* NAND page spare size */
+		uint32_t page_per_block;	/* Pages of one block */
+		uint32_t blocks;		/* Total blocks of NAND chip */
+		uint32_t plane_sel_position;	/* Plane bit position */
+		uint32_t pll;			/* Value of pll reg */
+		uint32_t acccon;		/* Value of access timing reg */
+		uint32_t strobe_sel;		/* Value of DQS selection reg*/
+		uint32_t acccon1;		/* Value of access timing reg */
+		uint32_t dqs_mux;		/* Value of DQS mux reg */
+		uint32_t dqs_ctrl;		/* Value of DQS control reg */
+		uint32_t delay_ctrl;		/* Value of delay ctrl reg */
+		uint32_t latch_lat;		/* Value of latch latency reg */
+		uint32_t sample_delay;		/* Value of sample delay reg */
+		uint32_t driving;		/* Value of driving reg */
+		uint32_t reserved;
+		uint32_t bl0_start;		/* Bootloader start addr */
+		uint32_t bl0_end;		/* Bootloader end addr */
+		uint32_t bl0_type;		/* Bootloader type */
+		uint8_t bl_reserve[84];
+		uint8_t ecc_parity[42];		/* ECC parity of this header */
+	};
+
+	uint8_t data[0xEA];
+};
+
+/* SPIM BROM Header for SPI-NAND */
+union spim_nand_boot_header {
+	struct {
+		char id[8];
+		uint32_t version;		/* Header version */
+		uint32_t config;		/* Header config */
+		uint32_t page_size;		/* NAND page size */
+		uint32_t spare_size;		/* NAND page spare size */
+		uint16_t page_per_block;	/* Pages of one block */
+		uint16_t plane_sel_position;	/* Plane bit position */
+		uint16_t reserve_reg;
+		uint16_t reserve_val;
+		uint16_t ecc_error;		/* ECC error reg addr */
+		uint16_t ecc_mask;		/* ECC error bit mask */
+		uint32_t bl_start;		/* Bootloader start addr */
+		uint32_t bl_end;		/* Bootloader end addr */
+		uint8_t ecc_parity[32];		/* ECC parity of this header */
+		uint32_t integrity_crc;		/* CRC of this header */
+	};
+
+	uint8_t data[0x50];
+};
+
+enum nand_boot_header_type {
+	NAND_BOOT_AP_HEADER,
+	NAND_BOOT_HSM_HEADER,
+	NAND_BOOT_HSM20_HEADER,
+	NAND_BOOT_SPIM_HEADER
+};
+
 #define NAND_BOOT_NAME		"BOOTLOADER!"
 #define NAND_BOOT_VERSION	"V006"
 #define NAND_BOOT_ID		"NFIINFO"
 
+#define HSM_NAND_BOOT_NAME	"NANDCFG!"
+#define SPIM_NAND_BOOT_NAME	"SPINAND!"
+
 /* Find nand header data by name */
-const union nand_boot_header *mtk_nand_header_find(const char *name);
+const struct nand_header_type *mtk_nand_header_find(const char *name);
 
 /* Device header size using this nand header */
-uint32_t mtk_nand_header_size(const union nand_boot_header *hdr_nand);
+uint32_t mtk_nand_header_size(const struct nand_header_type *hdr_nand);
 
 /* Get nand info from nand header (page size, spare size, ...) */
 int mtk_nand_header_info(const void *ptr, struct nand_header_info *info);
@@ -56,6 +159,7 @@ int mtk_nand_header_info(const void *ptr, struct nand_header_info *info);
 bool is_mtk_nand_header(const void *ptr);
 
 /* Generate Device header using give nand header */
-uint32_t mtk_nand_header_put(const union nand_boot_header *hdr_nand, void *ptr);
+uint32_t mtk_nand_header_put(const struct nand_header_type *hdr_nand,
+			     void *ptr);
 
 #endif /* _MTK_NAND_HEADERS_H */
-- 
2.17.1


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

* [PATCH v2 32/32] MAINTAINERS: update maintainer for MediaTek ARM platform
  2022-08-31 11:00 [PATCH v2 00/32] Add support for MediaTek MT7981/MT7986 SoCs - v2 Weijie Gao
                   ` (30 preceding siblings ...)
  2022-08-31 11:05 ` [PATCH v2 31/32] tools: mtk_image: add support for nand headers used by newer chips Weijie Gao
@ 2022-08-31 11:05 ` Weijie Gao
  31 siblings, 0 replies; 60+ messages in thread
From: Weijie Gao @ 2022-08-31 11:05 UTC (permalink / raw)
  To: u-boot; +Cc: GSS_MTK_Uboot_upstream, Weijie Gao

Add new files for MediaTek ARM platform

Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
---
v2 changes:
  Add cpu driver file
---
 MAINTAINERS | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 36a2b69fcb..d47674c476 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -355,20 +355,26 @@ F:	doc/device-tree-bindings/phy/phy-mtk-*
 F:	doc/device-tree-bindings/usb/mediatek,*
 F:	doc/README.mediatek
 F:	drivers/clk/mediatek/
+F:	drivers/cpu/mtk_cpu.c
+F:	drivers/i2c/mtk_i2c.c
 F:	drivers/mmc/mtk-sd.c
 F:	drivers/phy/phy-mtk-*
 F:	drivers/pinctrl/mediatek/
 F:	drivers/power/domain/mtk-power-domain.c
 F:	drivers/ram/mediatek/
 F:	drivers/spi/mtk_snfi_spi.c
+F:	drivers/spi/mtk_spim.c
 F:	drivers/timer/mtk_timer.c
 F:	drivers/usb/host/xhci-mtk.c
 F:	drivers/usb/mtu3/
 F:	drivers/watchdog/mtk_wdt.c
 F:	drivers/net/mtk_eth.c
+F:	drivers/net/mtk_eth.h
 F:	drivers/reset/reset-mediatek.c
 F:	tools/mtk_image.c
 F:	tools/mtk_image.h
+F:	tools/mtk_nand_headers.c
+F:	tools/mtk_nand_headers.h
 N:	mediatek
 
 ARM METHODE SUPPORT
-- 
2.17.1


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

* Re: [PATCH v2 28/32] cpu: add basic cpu driver for MediaTek ARM chips
  2022-08-31 11:05 ` [PATCH v2 28/32] cpu: add basic cpu driver for MediaTek ARM chips Weijie Gao
@ 2022-08-31 13:46   ` Simon Glass
  2022-09-01  3:00     ` Weijie Gao
  2022-09-01  0:28   ` Daniel Golle
  1 sibling, 1 reply; 60+ messages in thread
From: Simon Glass @ 2022-08-31 13:46 UTC (permalink / raw)
  To: Weijie Gao
  Cc: U-Boot Mailing List, GSS_MTK_Uboot_upstream, Michal Simek, Ovidiu Panait

Hi Weijie,

On Wed, 31 Aug 2022 at 05:08, Weijie Gao <weijie.gao@mediatek.com> wrote:
>
> Add basic CPU driver used to retrieve CPU model information.
>
> Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
> ---
>   v2 changes: new
> ---
>  drivers/cpu/Makefile  |   1 +
>  drivers/cpu/mtk_cpu.c | 106 ++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 107 insertions(+)
>  create mode 100644 drivers/cpu/mtk_cpu.c
>
> diff --git a/drivers/cpu/Makefile b/drivers/cpu/Makefile
> index 20884b1795..3b38ba9c58 100644
> --- a/drivers/cpu/Makefile
> +++ b/drivers/cpu/Makefile
> @@ -9,6 +9,7 @@ obj-$(CONFIG_CPU) += cpu-uclass.o
>  obj-$(CONFIG_ARCH_BMIPS) += bmips_cpu.o
>  obj-$(CONFIG_ARCH_IMX8) += imx8_cpu.o
>  obj-$(CONFIG_ARCH_AT91) += at91_cpu.o
> +obj-$(CONFIG_ARCH_MEDIATEK) += mtk_cpu.o
>  obj-$(CONFIG_CPU_MPC83XX) += mpc83xx_cpu.o
>  obj-$(CONFIG_CPU_RISCV) += riscv_cpu.o
>  obj-$(CONFIG_CPU_MICROBLAZE) += microblaze_cpu.o
> diff --git a/drivers/cpu/mtk_cpu.c b/drivers/cpu/mtk_cpu.c
> new file mode 100644
> index 0000000000..d00b4c669e
> --- /dev/null
> +++ b/drivers/cpu/mtk_cpu.c
> @@ -0,0 +1,106 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2022 MediaTek Inc. All rights reserved.
> + *
> + * Author: Weijie Gao <weijie.gao@mediatek.com>
> + */
> +
> +#include <linux/types.h>
> +#include <cpu.h>
> +#include <dm.h>
> +#include <fdt_support.h>
> +#include <mapmem.h>
> +#include <asm/global_data.h>
> +#include <linux/io.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;

dont't need this?

> +
> +struct mtk_cpu_plat {
> +       void __iomem *hwver_base;
> +};
> +
> +static int mtk_cpu_get_desc(const struct udevice *dev, char *buf, int size)
> +{
> +       struct mtk_cpu_plat *plat = dev_get_plat(dev);
> +
> +       snprintf(buf, size, "MediaTek MT%04X", readl(plat->hwver_base));
> +
> +       return 0;
> +}
> +
> +static int mtk_cpu_get_count(const struct udevice *dev)
> +{
> +       return 1;
> +}
> +
> +static int mtk_cpu_get_vendor(const struct udevice *dev, char *buf, int size)
> +{
> +       snprintf(buf, size, "MediaTek");
> +
> +       return 0;
> +}
> +
> +static int mtk_cpu_probe(struct udevice *dev)
> +{
> +       struct mtk_cpu_plat *plat = dev_get_plat(dev);
> +       const void *fdt = gd->fdt_blob, *reg;
> +       int offset, parent, len, na, ns;
> +       u64 addr;
> +
> +       if (!fdt)
> +               return -ENODEV;
> +
> +       offset = fdt_path_offset(fdt, "/hwver");

This is very strange, but you should have a driver for that node, e.g.
a SYSCON driver. Then from this driver you can obtain the address with
syscon_get_first_range() or similar.

> +       if (offset < 0)
> +               return -ENODEV;
> +
> +       parent = fdt_parent_offset(fdt, offset);
> +       if (parent < 0)
> +               return -ENODEV;
> +
> +       na = fdt_address_cells(fdt, parent);
> +       if (na < 1)
> +               return -ENODEV;
> +
> +       ns = fdt_size_cells(gd->fdt_blob, parent);
> +       if (ns < 0)
> +               return -ENODEV;
> +
> +       reg = fdt_getprop(gd->fdt_blob, offset, "reg", &len);
> +       if (!reg)
> +               return -ENODEV;
> +
> +       if (ns)
> +               addr = fdt_translate_address(fdt, offset, reg);
> +       else
> +               addr = fdt_read_number(reg, na);
> +

All of the above should go away. We should use dev_read() / ofnode...
for device tree access.

> +       plat->hwver_base = map_sysmem(addr, 0);
> +       if (!plat->hwver_base)
> +               return -EINVAL;
> +
> +       return 0;
> +}
> +
> +static const struct cpu_ops mtk_cpu_ops = {
> +       .get_desc       = mtk_cpu_get_desc,
> +       .get_count      = mtk_cpu_get_count,
> +       .get_vendor     = mtk_cpu_get_vendor,
> +};
> +
> +static const struct udevice_id mtk_cpu_ids[] = {
> +       { .compatible = "arm,cortex-a7" },
> +       { .compatible = "arm,cortex-a53" },
> +       { .compatible = "arm,cortex-a73" },
> +       { /* sentinel */ }
> +};
> +
> +U_BOOT_DRIVER(cpu_mtk) = {
> +       .name           = "mtk-cpu",
> +       .id             = UCLASS_CPU,
> +       .of_match       = mtk_cpu_ids,
> +       .ops            = &mtk_cpu_ops,
> +       .probe          = mtk_cpu_probe,
> +       .plat_auto      = sizeof(struct mtk_cpu_plat),
> +       .flags          = DM_FLAG_PRE_RELOC,
> +};
> --
> 2.17.1
>

Regards,
Simon

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

* Re: [PATCH v2 04/32] board: mediatek: add MT7981 reference boards
  2022-08-31 11:00 ` [PATCH v2 04/32] board: mediatek: add MT7981 " Weijie Gao
@ 2022-08-31 13:46   ` Simon Glass
  0 siblings, 0 replies; 60+ messages in thread
From: Simon Glass @ 2022-08-31 13:46 UTC (permalink / raw)
  To: Weijie Gao
  Cc: U-Boot Mailing List, GSS_MTK_Uboot_upstream, Marcel Ziswiler,
	Andre Przywara, Fabio Estevam, Samuel Holland, Marek Vasut,
	Ying-Chun Liu (PaulLiu),
	Christian Hewitt

On Wed, 31 Aug 2022 at 05:00, Weijie Gao <weijie.gao@mediatek.com> wrote:
>
> This patch adds general board files based on MT7981 SoCs.
>
> MT7981 uses one mmc controller for booting from both SD and eMMC, and the
> pins of mmc controller are also shared with spi controller.
> So three configs are need for these boot types:
>
> 1. mt7981_rfb_defconfig - SPI-NOR and SPI-NAND
> 2. mt7981_emmc_rfb_defconfig - eMMC only
> 3. mt7981_sd_rfb_defconfig - SD only
>
> Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
> ---
> v2 changes:
>   Remove mt7981_spim_nand_rfb_defconfig and mt7981_spim_nor_rfb_defconfig
> ---
>  arch/arm/dts/Makefile              |   3 +
>  arch/arm/dts/mt7981-emmc-rfb.dts   | 139 +++++++++++++++++++++++
>  arch/arm/dts/mt7981-rfb.dts        | 173 +++++++++++++++++++++++++++++
>  arch/arm/dts/mt7981-sd-rfb.dts     | 139 +++++++++++++++++++++++
>  board/mediatek/mt7981/MAINTAINERS  |  10 ++
>  board/mediatek/mt7981/Makefile     |   3 +
>  board/mediatek/mt7981/mt7981_rfb.c |  10 ++
>  configs/mt7981_emmc_rfb_defconfig  |  64 +++++++++++
>  configs/mt7981_rfb_defconfig       |  69 ++++++++++++
>  configs/mt7981_sd_rfb_defconfig    |  64 +++++++++++
>  include/configs/mt7981.h           |  26 +++++
>  11 files changed, 700 insertions(+)
>  create mode 100644 arch/arm/dts/mt7981-emmc-rfb.dts
>  create mode 100644 arch/arm/dts/mt7981-rfb.dts
>  create mode 100644 arch/arm/dts/mt7981-sd-rfb.dts
>  create mode 100644 board/mediatek/mt7981/MAINTAINERS
>  create mode 100644 board/mediatek/mt7981/Makefile
>  create mode 100644 board/mediatek/mt7981/mt7981_rfb.c
>  create mode 100644 configs/mt7981_emmc_rfb_defconfig
>  create mode 100644 configs/mt7981_rfb_defconfig
>  create mode 100644 configs/mt7981_sd_rfb_defconfig
>  create mode 100644 include/configs/mt7981.h

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* Re: [PATCH v2 02/32] arm: mediatek: add support for MediaTek MT7981 SoC
  2022-08-31 11:00 ` [PATCH v2 02/32] arm: mediatek: add support for MediaTek MT7981 SoC Weijie Gao
@ 2022-08-31 13:46   ` Simon Glass
  0 siblings, 0 replies; 60+ messages in thread
From: Simon Glass @ 2022-08-31 13:46 UTC (permalink / raw)
  To: Weijie Gao; +Cc: U-Boot Mailing List, GSS_MTK_Uboot_upstream

On Wed, 31 Aug 2022 at 05:00, Weijie Gao <weijie.gao@mediatek.com> wrote:
>
> This patch adds basic support for MediaTek MT7981 SoC.
> This include the file that will initialize the SoC after boot and its
> device tree.
>
> Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
> ---
> v2 changes:
>   Sort include lines
>   Add reference link for armv8_el2_to_aarch32 in lowlevel_init.S
>   Remove print_cpuinfo and use cpu driver instead
> ---
>  arch/arm/dts/mt7981.dtsi                      | 293 ++++++++++++++++++
>  arch/arm/mach-mediatek/Kconfig                |  13 +-
>  arch/arm/mach-mediatek/Makefile               |   1 +
>  arch/arm/mach-mediatek/mt7981/Makefile        |   4 +
>  arch/arm/mach-mediatek/mt7981/init.c          |  45 +++
>  arch/arm/mach-mediatek/mt7981/lowlevel_init.S |  32 ++
>  6 files changed, 387 insertions(+), 1 deletion(-)
>  create mode 100644 arch/arm/dts/mt7981.dtsi
>  create mode 100644 arch/arm/mach-mediatek/mt7981/Makefile
>  create mode 100644 arch/arm/mach-mediatek/mt7981/init.c
>  create mode 100644 arch/arm/mach-mediatek/mt7981/lowlevel_init.S
>

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* Re: [PATCH v2 01/32] arm: mediatek: add support for MediaTek MT7986 SoC
  2022-08-31 11:00 ` [PATCH v2 01/32] arm: mediatek: add support for MediaTek MT7986 SoC Weijie Gao
@ 2022-08-31 13:46   ` Simon Glass
  2022-09-01  0:09   ` Daniel Golle
  1 sibling, 0 replies; 60+ messages in thread
From: Simon Glass @ 2022-08-31 13:46 UTC (permalink / raw)
  To: Weijie Gao; +Cc: U-Boot Mailing List, GSS_MTK_Uboot_upstream

On Wed, 31 Aug 2022 at 05:01, Weijie Gao <weijie.gao@mediatek.com> wrote:
>
> This patch adds basic support for MediaTek MT7986 SoC.
> This include the file that will initialize the SoC after boot and its
> device tree.
>
> Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
> ---
> v2 changes:
>   Sort include lines
>   Add reference link for armv8_el2_to_aarch32 in lowlevel_init.S
>   Remove print_cpuinfo and use cpu driver instead
> ---
>  arch/arm/dts/mt7986-u-boot.dtsi               |  33 ++
>  arch/arm/dts/mt7986.dtsi                      | 346 ++++++++++++++++++
>  arch/arm/mach-mediatek/Kconfig                |  12 +
>  arch/arm/mach-mediatek/Makefile               |   1 +
>  arch/arm/mach-mediatek/mt7986/Makefile        |   4 +
>  arch/arm/mach-mediatek/mt7986/init.c          |  45 +++
>  arch/arm/mach-mediatek/mt7986/lowlevel_init.S |  32 ++
>  7 files changed, 473 insertions(+)
>  create mode 100644 arch/arm/dts/mt7986-u-boot.dtsi
>  create mode 100644 arch/arm/dts/mt7986.dtsi
>  create mode 100644 arch/arm/mach-mediatek/mt7986/Makefile
>  create mode 100644 arch/arm/mach-mediatek/mt7986/init.c
>  create mode 100644 arch/arm/mach-mediatek/mt7986/lowlevel_init.S

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* Re: [PATCH v2 25/32] clk: mediatek: add CLK_XTAL support for clock driver
  2022-08-31 11:05 ` [PATCH v2 25/32] clk: mediatek: add CLK_XTAL support for clock driver Weijie Gao
@ 2022-08-31 13:46   ` Simon Glass
  2022-09-01  0:27   ` Daniel Golle
  1 sibling, 0 replies; 60+ messages in thread
From: Simon Glass @ 2022-08-31 13:46 UTC (permalink / raw)
  To: Weijie Gao
  Cc: U-Boot Mailing List, GSS_MTK_Uboot_upstream, Lukasz Majewski,
	Sean Anderson

On Wed, 31 Aug 2022 at 05:08, Weijie Gao <weijie.gao@mediatek.com> wrote:
>
> This adds the CLK_XTAL macro/flag to allow modeling clocks which are
> directly connected to the xtal clock.
>
> Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
> ---
> v2 changes:
>   Fix incorrect fallback in mtk_infrasys_get_factor_rate
>   Fix commit description
> ---
>  drivers/clk/mediatek/clk-mtk.c | 4 ++++
>  drivers/clk/mediatek/clk-mtk.h | 3 ++-
>  2 files changed, 6 insertions(+), 1 deletion(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* Re: [PATCH v2 01/32] arm: mediatek: add support for MediaTek MT7986 SoC
  2022-08-31 11:00 ` [PATCH v2 01/32] arm: mediatek: add support for MediaTek MT7986 SoC Weijie Gao
  2022-08-31 13:46   ` Simon Glass
@ 2022-09-01  0:09   ` Daniel Golle
  1 sibling, 0 replies; 60+ messages in thread
From: Daniel Golle @ 2022-09-01  0:09 UTC (permalink / raw)
  To: Weijie Gao; +Cc: u-boot, GSS_MTK_Uboot_upstream

On Wed, Aug 31, 2022 at 07:00:17PM +0800, Weijie Gao wrote:
> This patch adds basic support for MediaTek MT7986 SoC.
> This include the file that will initialize the SoC after boot and its
> device tree.
> 
> Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>

Tested on Bananapi BPi-R3 (MT7986A).

Tested-by: Daniel Golle <daniel@makrotopia.org>


> ---
> v2 changes:
>   Sort include lines
>   Add reference link for armv8_el2_to_aarch32 in lowlevel_init.S
>   Remove print_cpuinfo and use cpu driver instead
> ---
>  arch/arm/dts/mt7986-u-boot.dtsi               |  33 ++
>  arch/arm/dts/mt7986.dtsi                      | 346 ++++++++++++++++++
>  arch/arm/mach-mediatek/Kconfig                |  12 +
>  arch/arm/mach-mediatek/Makefile               |   1 +
>  arch/arm/mach-mediatek/mt7986/Makefile        |   4 +
>  arch/arm/mach-mediatek/mt7986/init.c          |  45 +++
>  arch/arm/mach-mediatek/mt7986/lowlevel_init.S |  32 ++
>  7 files changed, 473 insertions(+)
>  create mode 100644 arch/arm/dts/mt7986-u-boot.dtsi
>  create mode 100644 arch/arm/dts/mt7986.dtsi
>  create mode 100644 arch/arm/mach-mediatek/mt7986/Makefile
>  create mode 100644 arch/arm/mach-mediatek/mt7986/init.c
>  create mode 100644 arch/arm/mach-mediatek/mt7986/lowlevel_init.S
> 
> diff --git a/arch/arm/dts/mt7986-u-boot.dtsi b/arch/arm/dts/mt7986-u-boot.dtsi
> new file mode 100644
> index 0000000000..95671f8afa
> --- /dev/null
> +++ b/arch/arm/dts/mt7986-u-boot.dtsi
> @@ -0,0 +1,33 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2022 MediaTek Inc.
> + * Author: Sam Shih <sam.shih@mediatek.com>
> + */
> +
> +&topckgen {
> +	u-boot,dm-pre-reloc;
> +};
> +
> +&pericfg {
> +	u-boot,dm-pre-reloc;
> +};
> +
> +&apmixedsys {
> +	u-boot,dm-pre-reloc;
> +};
> +
> +&timer0 {
> +	u-boot,dm-pre-reloc;
> +};
> +
> +&uart0 {
> +	u-boot,dm-pre-reloc;
> +};
> +
> +&snand {
> +	u-boot,dm-pre-reloc;
> +};
> +
> +&pinctrl {
> +	u-boot,dm-pre-reloc;
> +};
> diff --git a/arch/arm/dts/mt7986.dtsi b/arch/arm/dts/mt7986.dtsi
> new file mode 100644
> index 0000000000..25b81ab7e1
> --- /dev/null
> +++ b/arch/arm/dts/mt7986.dtsi
> @@ -0,0 +1,346 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2022 MediaTek Inc.
> + * Author: Sam Shih <sam.shih@mediatek.com>
> + */
> +
> +#include <dt-bindings/interrupt-controller/irq.h>
> +#include <dt-bindings/interrupt-controller/arm-gic.h>
> +#include <dt-bindings/phy/phy.h>
> +#include <dt-bindings/clock/mt7986-clk.h>
> +#include <dt-bindings/reset/mt7629-reset.h>
> +#include <dt-bindings/pinctrl/mt65xx.h>
> +
> +/ {
> +	compatible = "mediatek,mt7986";
> +	interrupt-parent = <&gic>;
> +	#address-cells = <1>;
> +	#size-cells = <1>;
> +
> +	config {
> +		u-boot,mmc-env-partition = "u-boot-env";
> +	};
> +
> +	cpus {
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +		cpu0: cpu@0 {
> +			device_type = "cpu";
> +			compatible = "arm,cortex-a53";
> +			reg = <0x0>;
> +		};
> +		cpu1: cpu@1 {
> +			device_type = "cpu";
> +			compatible = "arm,cortex-a53";
> +			reg = <0x1>;
> +		};
> +		cpu2: cpu@2 {
> +			device_type = "cpu";
> +			compatible = "arm,cortex-a53";
> +			reg = <0x1>;
> +		};
> +		cpu3: cpu@3 {
> +			device_type = "cpu";
> +			compatible = "arm,cortex-a53";
> +			reg = <0x1>;
> +		};
> +	};
> +
> +	dummy_clk: dummy12m {
> +		compatible = "fixed-clock";
> +		clock-frequency = <12000000>;
> +		#clock-cells = <0>;
> +		/* must need this line, or uart uanable to get dummy_clk */
> +		u-boot,dm-pre-reloc;
> +	};
> +
> +	hwver: hwver {
> +		compatible = "mediatek,hwver";
> +		reg = <0x8000000 0x1000>;
> +	};
> +
> +	timer {
> +		compatible = "arm,armv8-timer";
> +		interrupt-parent = <&gic>;
> +		clock-frequency = <13000000>;
> +		interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
> +			     <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
> +			     <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
> +			     <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
> +		arm,cpu-registers-not-fw-configured;
> +	};
> +
> +	timer0: timer@10008000 {
> +		compatible = "mediatek,mt7986-timer";
> +		reg = <0x10008000 0x1000>;
> +		interrupts = <GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&infracfg CK_INFRA_CK_F26M>;
> +		clock-names = "gpt-clk";
> +		u-boot,dm-pre-reloc;
> +	};
> +
> +	watchdog: watchdog@1001c000 {
> +		compatible = "mediatek,mt7986-wdt";
> +		reg = <0x1001c000 0x1000>;
> +		interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
> +		#reset-cells = <1>;
> +		status = "disabled";
> +	};
> +
> +	gic: interrupt-controller@c000000 {
> +		compatible = "arm,gic-v3";
> +		#interrupt-cells = <3>;
> +		interrupt-parent = <&gic>;
> +		interrupt-controller;
> +		reg = <0x0c000000 0x40000>,  /* GICD */
> +		      <0x0c080000 0x200000>; /* GICR */
> +
> +		interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
> +	};
> +
> +	fixed_plls: apmixedsys@1001E000 {
> +		compatible = "mediatek,mt7986-fixed-plls";
> +		reg = <0x1001E000 0x1000>;
> +		#clock-cells = <1>;
> +	};
> +
> +	topckgen: topckgen@1001B000 {
> +		compatible = "mediatek,mt7986-topckgen";
> +		reg = <0x1001B000 0x1000>;
> +		clock-parent = <&fixed_plls>;
> +		#clock-cells = <1>;
> +	};
> +
> +	infracfg_ao: infracfg_ao@10001000 {
> +		compatible = "mediatek,mt7986-infracfg_ao";
> +		reg = <0x10001000 0x68>;
> +		clock-parent = <&infracfg>;
> +		#clock-cells = <1>;
> +	};
> +
> +	infracfg: infracfg@10001040 {
> +		compatible = "mediatek,mt7986-infracfg";
> +		reg = <0x10001000 0x1000>;
> +		clock-parent = <&topckgen>;
> +		#clock-cells = <1>;
> +	};
> +
> +	pinctrl: pinctrl@1001f000 {
> +		compatible = "mediatek,mt7986-pinctrl";
> +		reg = <0x1001f000 0x1000>,
> +		      <0x11c30000 0x1000>,
> +		      <0x11c40000 0x1000>,
> +		      <0x11e20000 0x1000>,
> +		      <0x11e30000 0x1000>,
> +		      <0x11f00000 0x1000>,
> +		      <0x11f10000 0x1000>,
> +		      <0x1000b000 0x1000>;
> +		reg-names = "gpio_base", "iocfg_rt_base", "iocfg_rb_base",
> +			    "iocfg_lt_base", "iocfg_lb_base", "iocfg_tr_base",
> +			    "iocfg_tl_base", "eint";
> +		gpio: gpio-controller {
> +			gpio-controller;
> +			#gpio-cells = <2>;
> +		};
> +	};
> +
> +	pwm: pwm@10048000 {
> +		compatible = "mediatek,mt7986-pwm";
> +		reg = <0x10048000 0x1000>;
> +		#clock-cells = <1>;
> +		#pwm-cells = <2>;
> +		interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&infracfg CK_INFRA_PWM>,
> +			 <&infracfg_ao CK_INFRA_PWM_BSEL>,
> +			 <&infracfg_ao CK_INFRA_PWM1_CK>,
> +			 <&infracfg_ao CK_INFRA_PWM2_CK>;
> +		assigned-clocks = <&topckgen CK_TOP_PWM_SEL>,
> +				  <&infracfg CK_INFRA_PWM_BSEL>,
> +				  <&infracfg CK_INFRA_PWM1_SEL>,
> +				  <&infracfg CK_INFRA_PWM2_SEL>;
> +		assigned-clock-parents = <&topckgen CK_TOP_CB_M_D4>,
> +					 <&infracfg CK_INFRA_PWM>,
> +					 <&infracfg CK_INFRA_PWM>,
> +					 <&infracfg CK_INFRA_PWM>;
> +		clock-names = "top", "main", "pwm1", "pwm2";
> +		status = "disabled";
> +		u-boot,dm-pre-reloc;
> +	};
> +
> +	uart0: serial@11002000 {
> +		compatible = "mediatek,hsuart";
> +		reg = <0x11002000 0x400>;
> +		interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&infracfg_ao CK_INFRA_UART0_CK>;
> +		assigned-clocks = <&topckgen CK_TOP_UART_SEL>,
> +				  <&infracfg_ao CK_INFRA_UART0_SEL>;
> +		assigned-clock-parents = <&topckgen CK_TOP_CB_CKSQ_40M>,
> +					 <&infracfg CK_INFRA_UART>;
> +		mediatek,force-highspeed;
> +		status = "disabled";
> +		u-boot,dm-pre-reloc;
> +	};
> +
> +	uart1: serial@11003000 {
> +		compatible = "mediatek,hsuart";
> +		reg = <0x11003000 0x400>;
> +		interrupts = <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&infracfg_ao CK_INFRA_UART1_CK>;
> +		assigned-clocks = <&infracfg CK_INFRA_UART1_SEL>;
> +		assigned-clock-parents = <&infracfg CK_INFRA_CK_F26M>;
> +		mediatek,force-highspeed;
> +		status = "disabled";
> +	};
> +
> +	uart2: serial@11004000 {
> +		compatible = "mediatek,hsuart";
> +		reg = <0x11004000 0x400>;
> +		interrupts = <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&infracfg_ao CK_INFRA_UART2_CK>;
> +		assigned-clocks = <&infracfg CK_INFRA_UART2_SEL>;
> +		assigned-clock-parents = <&infracfg CK_INFRA_CK_F26M>;
> +		mediatek,force-highspeed;
> +		status = "disabled";
> +	};
> +
> +	snand: snand@11005000 {
> +		compatible = "mediatek,mt7986-snand";
> +		reg = <0x11005000 0x1000>,
> +		      <0x11006000 0x1000>;
> +		reg-names = "nfi", "ecc";
> +		clocks = <&infracfg_ao CK_INFRA_SPINFI1_CK>,
> +			 <&infracfg_ao CK_INFRA_NFI1_CK>,
> +			 <&infracfg_ao CK_INFRA_NFI_HCK_CK>;
> +		clock-names = "pad_clk", "nfi_clk", "nfi_hclk";
> +		assigned-clocks = <&topckgen CK_TOP_SPINFI_SEL>,
> +				  <&topckgen CK_TOP_NFI1X_SEL>;
> +		assigned-clock-parents = <&topckgen CK_TOP_CB_M_D8>,
> +					 <&topckgen CK_TOP_CB_M_D8>;
> +		status = "disabled";
> +	};
> +
> +	ethsys: syscon@15000000 {
> +		compatible = "mediatek,mt7986-ethsys", "syscon";
> +		reg = <0x15000000 0x1000>;
> +		clock-parent = <&topckgen>;
> +		#clock-cells = <1>;
> +		#reset-cells = <1>;
> +	};
> +
> +	eth: ethernet@15100000 {
> +		compatible = "mediatek,mt7986-eth", "syscon";
> +		reg = <0x15100000 0x20000>;
> +		resets = <&ethsys ETHSYS_FE_RST>;
> +		reset-names = "fe";
> +		mediatek,ethsys = <&ethsys>;
> +		mediatek,sgmiisys = <&sgmiisys0>;
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +		status = "disabled";
> +	};
> +
> +	sgmiisys0: syscon@10060000 {
> +		compatible = "mediatek,mt7986-sgmiisys", "syscon";
> +		reg = <0x10060000 0x1000>;
> +		#clock-cells = <1>;
> +	};
> +
> +	sgmiisys1: syscon@10070000 {
> +		compatible = "mediatek,mt7986-sgmiisys", "syscon";
> +		reg = <0x10070000 0x1000>;
> +		#clock-cells = <1>;
> +	};
> +
> +	spi0: spi@1100a000 {
> +		compatible = "mediatek,ipm-spi";
> +		reg = <0x1100a000 0x100>;
> +		clocks = <&infracfg_ao CK_INFRA_SPI0_CK>,
> +			 <&topckgen CK_TOP_SPI_SEL>;
> +		assigned-clocks = <&topckgen CK_TOP_SPI_SEL>,
> +				  <&infracfg CK_INFRA_SPI0_SEL>;
> +		assigned-clock-parents = <&topckgen CK_TOP_CB_M_D2>,
> +					 <&topckgen CK_INFRA_ISPI0>;
> +		clock-names = "sel-clk", "spi-clk";
> +		interrupts = <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
> +		status = "disabled";
> +	};
> +
> +	spi1: spi@1100b000 {
> +		compatible = "mediatek,ipm-spi";
> +		reg = <0x1100b000 0x100>;
> +		interrupts = <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>;
> +		status = "disabled";
> +	};
> +
> +	mmc0: mmc@11230000 {
> +		compatible = "mediatek,mt7986-mmc";
> +		reg = <0x11230000 0x1000>,
> +		      <0x11C20000 0x1000>;
> +		interrupts = <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&topckgen CK_TOP_EMMC_416M>,
> +			<&topckgen CK_TOP_EMMC_250M>,
> +			<&infracfg_ao CK_INFRA_MSDC_CK>;
> +		assigned-clocks = <&topckgen CK_TOP_EMMC_416M_SEL>,
> +				  <&topckgen CK_TOP_EMMC_250M_SEL>;
> +		assigned-clock-parents = <&topckgen CK_TOP_CB_M_416M>,
> +					 <&topckgen CK_TOP_NET1_D5_D2>;
> +		clock-names = "source", "hclk", "source_cg";
> +		status = "disabled";
> +	};
> +
> +	xhci: xhci@11200000 {
> +		compatible = "mediatek,mt7986-xhci",
> +			     "mediatek,mtk-xhci";
> +		reg = <0x11200000 0x2e00>,
> +		      <0x11203e00 0x0100>;
> +		reg-names = "mac", "ippc";
> +		interrupts = <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>;
> +		phys = <&u2port0 PHY_TYPE_USB2>,
> +		       <&u3port0 PHY_TYPE_USB3>,
> +		       <&u2port1 PHY_TYPE_USB2>;
> +		clocks = <&dummy_clk>,
> +			 <&dummy_clk>,
> +			 <&dummy_clk>,
> +			 <&dummy_clk>,
> +			 <&dummy_clk>;
> +		clock-names = "sys_ck",
> +			      "xhci_ck",
> +			      "ref_ck",
> +			      "mcu_ck",
> +			      "dma_ck";
> +		tpl-support;
> +		status = "okay";
> +	};
> +
> +	usbtphy: usb-phy@11e10000 {
> +		compatible = "mediatek,mt7986",
> +			     "mediatek,generic-tphy-v2";
> +		#address-cells = <1>;
> +		#size-cells = <1>;
> +		status = "okay";
> +
> +		u2port0: usb-phy@11e10000 {
> +			reg = <0x11e10000 0x700>;
> +			clocks = <&dummy_clk>;
> +			clock-names = "ref";
> +			#phy-cells = <1>;
> +			status = "okay";
> +		};
> +
> +		u3port0: usb-phy@11e10700 {
> +			reg = <0x11e10700 0x900>;
> +			clocks = <&dummy_clk>;
> +			clock-names = "ref";
> +			#phy-cells = <1>;
> +			status = "okay";
> +		};
> +
> +		u2port1: usb-phy@11e11000 {
> +			reg = <0x11e11000 0x700>;
> +			clocks = <&dummy_clk>;
> +			clock-names = "ref";
> +			#phy-cells = <1>;
> +			status = "okay";
> +		};
> +	};
> +};
> diff --git a/arch/arm/mach-mediatek/Kconfig b/arch/arm/mach-mediatek/Kconfig
> index f79a5c62cd..82fadeba8a 100644
> --- a/arch/arm/mach-mediatek/Kconfig
> +++ b/arch/arm/mach-mediatek/Kconfig
> @@ -40,6 +40,15 @@ config TARGET_MT7629
>  	  including DDR3, crypto engine, 3x3 11n/ac Wi-Fi, Gigabit Ethernet,
>  	  switch, USB3.0, PCIe, UART, SPI, I2C and PWM.
>  
> +config TARGET_MT7986
> +	bool "MediaTek MT7986 SoC"
> +	select ARM64
> +	select CPU
> +	help
> +	  The MediaTek MT7986 is a ARM64-based SoC with a quad-core Cortex-A53.
> +	  including UART, SPI, SPI flash, USB3.0, MMC, NAND, SNFI, PWM, PCIe,
> +	  Gigabit Ethernet, I2C, built-in 4x4 Wi-Fi, and PCIe.
> +
>  config TARGET_MT8183
>  	bool "MediaTek MT8183 SoC"
>  	select ARM64
> @@ -84,6 +93,7 @@ config SYS_BOARD
>  	default "mt7622" if TARGET_MT7622
>  	default "mt7623" if TARGET_MT7623
>  	default "mt7629" if TARGET_MT7629
> +	default "mt7986" if TARGET_MT7986
>  	default "mt8183" if TARGET_MT8183
>  	default "mt8512" if TARGET_MT8512
>  	default "mt8516" if TARGET_MT8516
> @@ -99,6 +109,7 @@ config SYS_CONFIG_NAME
>  	default "mt7622" if TARGET_MT7622
>  	default "mt7623" if TARGET_MT7623
>  	default "mt7629" if TARGET_MT7629
> +	default "mt7986" if TARGET_MT7986
>  	default "mt8183" if TARGET_MT8183
>  	default "mt8512" if TARGET_MT8512
>  	default "mt8516" if TARGET_MT8516
> @@ -113,6 +124,7 @@ config MTK_BROM_HEADER_INFO
>  	string
>  	default "media=nor" if TARGET_MT8518 || TARGET_MT8512 || TARGET_MT7629 || TARGET_MT7622
>  	default "media=emmc" if TARGET_MT8516 || TARGET_MT8365 || TARGET_MT8183
> +	default "media=snand;nandinfo=2k+64" if TARGET_MT7986
>  	default "lk=1" if TARGET_MT7623
>  
>  endif
> diff --git a/arch/arm/mach-mediatek/Makefile b/arch/arm/mach-mediatek/Makefile
> index 0f5b0c16d2..fe5c3a837c 100644
> --- a/arch/arm/mach-mediatek/Makefile
> +++ b/arch/arm/mach-mediatek/Makefile
> @@ -7,6 +7,7 @@ obj-$(CONFIG_MT8512) += mt8512/
>  obj-$(CONFIG_TARGET_MT7622) += mt7622/
>  obj-$(CONFIG_TARGET_MT7623) += mt7623/
>  obj-$(CONFIG_TARGET_MT7629) += mt7629/
> +obj-$(CONFIG_TARGET_MT7986) += mt7986/
>  obj-$(CONFIG_TARGET_MT8183) += mt8183/
>  obj-$(CONFIG_TARGET_MT8516) += mt8516/
>  obj-$(CONFIG_TARGET_MT8518) += mt8518/
> diff --git a/arch/arm/mach-mediatek/mt7986/Makefile b/arch/arm/mach-mediatek/mt7986/Makefile
> new file mode 100644
> index 0000000000..007eb4a367
> --- /dev/null
> +++ b/arch/arm/mach-mediatek/mt7986/Makefile
> @@ -0,0 +1,4 @@
> +# SPDX-License-Identifier:	GPL-2.0
> +
> +obj-y += init.o
> +obj-y += lowlevel_init.o
> diff --git a/arch/arm/mach-mediatek/mt7986/init.c b/arch/arm/mach-mediatek/mt7986/init.c
> new file mode 100644
> index 0000000000..0fd459657d
> --- /dev/null
> +++ b/arch/arm/mach-mediatek/mt7986/init.c
> @@ -0,0 +1,45 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2022 MediaTek Inc.
> + * Author: Sam Shih <sam.shih@mediatek.com>
> + */
> +
> +#include <init.h>
> +#include <asm/armv8/mmu.h>
> +#include <asm/system.h>
> +#include <asm/global_data.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +int dram_init(void)
> +{
> +	gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE, SZ_2G);
> +
> +	return 0;
> +}
> +
> +void reset_cpu(ulong addr)
> +{
> +	psci_system_reset();
> +}
> +
> +static struct mm_region mt7986_mem_map[] = {
> +	{
> +		/* DDR */
> +		.virt = 0x40000000UL,
> +		.phys = 0x40000000UL,
> +		.size = 0x80000000UL,
> +		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_OUTER_SHARE,
> +	}, {
> +		.virt = 0x00000000UL,
> +		.phys = 0x00000000UL,
> +		.size = 0x40000000UL,
> +		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
> +			 PTE_BLOCK_NON_SHARE |
> +			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
> +	}, {
> +		0,
> +	}
> +};
> +
> +struct mm_region *mem_map = mt7986_mem_map;
> diff --git a/arch/arm/mach-mediatek/mt7986/lowlevel_init.S b/arch/arm/mach-mediatek/mt7986/lowlevel_init.S
> new file mode 100644
> index 0000000000..85a1cea359
> --- /dev/null
> +++ b/arch/arm/mach-mediatek/mt7986/lowlevel_init.S
> @@ -0,0 +1,32 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (C) 2022 MediaTek Inc.
> + * Author: Sam Shih <sam.shih@mediatek.com>
> + */
> +
> +/*
> + * Switch from AArch64 EL2 to AArch32 EL2
> + * @param inputs:
> + * x0: argument, zero
> + * x1: machine nr
> + * x2: fdt address
> + * x3: input argument
> + * x4: kernel entry point
> + * @param outputs for secure firmware:
> + * x0: function id
> + * x1: kernel entry point
> + * x2: machine nr
> + * x3: fdt address
> + *
> + * [1] https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/tree/plat/mediatek/common/mtk_sip_svc.c
> +*/
> +
> +.global armv8_el2_to_aarch32
> +armv8_el2_to_aarch32:
> +	mov	x3, x2
> +	mov	x2, x1
> +	mov	x1, x4
> +	mov	x4, #0
> +	ldr	x0, =0x82000200	/* MTK_SIP_KERNEL_BOOT_AARCH32 */
> +	SMC	#0
> +	ret
> -- 
> 2.17.1
> 

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

* Re: [PATCH v2 05/32] mmc: mediatek: add support for MediaTek MT7891/MT7986 SoCs
  2022-08-31 11:04 ` [PATCH v2 05/32] mmc: mediatek: add support for MediaTek MT7891/MT7986 SoCs Weijie Gao
@ 2022-09-01  0:10   ` Daniel Golle
  0 siblings, 0 replies; 60+ messages in thread
From: Daniel Golle @ 2022-09-01  0:10 UTC (permalink / raw)
  To: Weijie Gao; +Cc: u-boot, GSS_MTK_Uboot_upstream, Peng Fan, Jaehoon Chung

On Wed, Aug 31, 2022 at 07:04:12PM +0800, Weijie Gao wrote:
> Add eMMC and SDXC support for MediaTek MT7981/MT7986 SoCs
> Both chips support SDXC and eMMC 4.5. MT7986A supports eMMC 5.1.
> 

Tested on Bananapi BPi-R3 (MT7986A) with both eMMC and SDMMC.

Tested-by: Daniel Golle <daniel@makrotopia.org>


> Reviewed-by: Jaehoon Chung <jh80.chung@samsung.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
> ---
> v2 changes: none
> ---
>  drivers/mmc/mtk-sd.c | 68 ++++++++++++++++++++++++++++++++++----------
>  1 file changed, 53 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/mmc/mtk-sd.c b/drivers/mmc/mtk-sd.c
> index e61e8cf4b9..b206b0a085 100644
> --- a/drivers/mmc/mtk-sd.c
> +++ b/drivers/mmc/mtk-sd.c
> @@ -1496,7 +1496,12 @@ static void msdc_init_hw(struct msdc_host *host)
>  	/* Enable data & cmd interrupts */
>  	writel(DATA_INTS_MASK | CMD_INTS_MASK, &host->base->msdc_inten);
>  
> -	writel(0, tune_reg);
> +	if (host->top_base) {
> +		writel(0, &host->top_base->emmc_top_control);
> +		writel(0, &host->top_base->emmc_top_cmd);
> +	} else {
> +		writel(0, tune_reg);
> +	}
>  	writel(0, &host->base->msdc_iocon);
>  
>  	if (host->r_smpl)
> @@ -1507,9 +1512,14 @@ static void msdc_init_hw(struct msdc_host *host)
>  	writel(0x403c0046, &host->base->patch_bit0);
>  	writel(0xffff4089, &host->base->patch_bit1);
>  
> -	if (host->dev_comp->stop_clk_fix)
> +	if (host->dev_comp->stop_clk_fix) {
>  		clrsetbits_le32(&host->base->patch_bit1, MSDC_PB1_STOP_DLY_M,
>  				3 << MSDC_PB1_STOP_DLY_S);
> +		clrbits_le32(&host->base->sdc_fifo_cfg,
> +			     SDC_FIFO_CFG_WRVALIDSEL);
> +		clrbits_le32(&host->base->sdc_fifo_cfg,
> +			     SDC_FIFO_CFG_RDVALIDSEL);
> +	}
>  
>  	if (host->dev_comp->busy_check)
>  		clrbits_le32(&host->base->patch_bit1, (1 << 7));
> @@ -1544,15 +1554,28 @@ static void msdc_init_hw(struct msdc_host *host)
>  	}
>  
>  	if (host->dev_comp->data_tune) {
> -		setbits_le32(tune_reg,
> -			     MSDC_PAD_TUNE_RD_SEL | MSDC_PAD_TUNE_CMD_SEL);
> -		clrsetbits_le32(&host->base->patch_bit0,
> -				MSDC_INT_DAT_LATCH_CK_SEL_M,
> -				host->latch_ck <<
> -				MSDC_INT_DAT_LATCH_CK_SEL_S);
> +		if (host->top_base) {
> +			setbits_le32(&host->top_base->emmc_top_control,
> +				     PAD_DAT_RD_RXDLY_SEL);
> +			clrbits_le32(&host->top_base->emmc_top_control,
> +				     DATA_K_VALUE_SEL);
> +			setbits_le32(&host->top_base->emmc_top_cmd,
> +				     PAD_CMD_RD_RXDLY_SEL);
> +		} else {
> +			setbits_le32(tune_reg,
> +				     MSDC_PAD_TUNE_RD_SEL | MSDC_PAD_TUNE_CMD_SEL);
> +			clrsetbits_le32(&host->base->patch_bit0,
> +					MSDC_INT_DAT_LATCH_CK_SEL_M,
> +					host->latch_ck <<
> +					MSDC_INT_DAT_LATCH_CK_SEL_S);
> +		}
>  	} else {
>  		/* choose clock tune */
> -		setbits_le32(tune_reg, MSDC_PAD_TUNE_RXDLYSEL);
> +		if (host->top_base)
> +			setbits_le32(&host->top_base->emmc_top_control,
> +				     PAD_RXDLY_SEL);
> +		else
> +			setbits_le32(tune_reg, MSDC_PAD_TUNE_RXDLYSEL);
>  	}
>  
>  	if (host->dev_comp->builtin_pad_ctrl) {
> @@ -1604,12 +1627,6 @@ static void msdc_init_hw(struct msdc_host *host)
>  	clrsetbits_le32(&host->base->sdc_cfg, SDC_CFG_DTOC_M,
>  			3 << SDC_CFG_DTOC_S);
>  
> -	if (host->dev_comp->stop_clk_fix) {
> -		clrbits_le32(&host->base->sdc_fifo_cfg,
> -			     SDC_FIFO_CFG_WRVALIDSEL);
> -		clrbits_le32(&host->base->sdc_fifo_cfg,
> -			     SDC_FIFO_CFG_RDVALIDSEL);
> -	}
>  
>  	host->def_tune_para.iocon = readl(&host->base->msdc_iocon);
>  	host->def_tune_para.pad_tune = readl(&host->base->pad_tune);
> @@ -1792,6 +1809,25 @@ static const struct msdc_compatible mt7623_compat = {
>  	.enhance_rx = false
>  };
>  
> +static const struct msdc_compatible mt7986_compat = {
> +	.clk_div_bits = 12,
> +	.pad_tune0 = true,
> +	.async_fifo = true,
> +	.data_tune = true,
> +	.busy_check = true,
> +	.stop_clk_fix = true,
> +	.enhance_rx = true,
> +};
> +
> +static const struct msdc_compatible mt7981_compat = {
> +	.clk_div_bits = 12,
> +	.pad_tune0 = true,
> +	.async_fifo = true,
> +	.data_tune = true,
> +	.busy_check = true,
> +	.stop_clk_fix = true,
> +};
> +
>  static const struct msdc_compatible mt8512_compat = {
>  	.clk_div_bits = 12,
>  	.pad_tune0 = true,
> @@ -1824,6 +1860,8 @@ static const struct udevice_id msdc_ids[] = {
>  	{ .compatible = "mediatek,mt7621-mmc", .data = (ulong)&mt7621_compat },
>  	{ .compatible = "mediatek,mt7622-mmc", .data = (ulong)&mt7622_compat },
>  	{ .compatible = "mediatek,mt7623-mmc", .data = (ulong)&mt7623_compat },
> +	{ .compatible = "mediatek,mt7986-mmc", .data = (ulong)&mt7986_compat },
> +	{ .compatible = "mediatek,mt7981-mmc", .data = (ulong)&mt7981_compat },
>  	{ .compatible = "mediatek,mt8512-mmc", .data = (ulong)&mt8512_compat },
>  	{ .compatible = "mediatek,mt8516-mmc", .data = (ulong)&mt8516_compat },
>  	{ .compatible = "mediatek,mt8183-mmc", .data = (ulong)&mt8183_compat },
> -- 
> 2.17.1
> 

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

* Re: [PATCH v2 06/32] net: mediatek: use a struct to cover variations of all SoCs
  2022-08-31 11:04 ` [PATCH v2 06/32] net: mediatek: use a struct to cover variations of all SoCs Weijie Gao
@ 2022-09-01  0:20   ` Daniel Golle
  0 siblings, 0 replies; 60+ messages in thread
From: Daniel Golle @ 2022-09-01  0:20 UTC (permalink / raw)
  To: Weijie Gao; +Cc: u-boot, GSS_MTK_Uboot_upstream, Joe Hershberger, Ramon Fried

On Wed, Aug 31, 2022 at 07:04:19PM +0800, Weijie Gao wrote:
> Using a single soc id to control different initialization and TX/RX flow
> for all SoCs is not extensible if more hardware variations are added in
> the future.
> 
> This patch introduces a struct to replace the original mtk_soc to allow
> the driver be able handle newer hardwares.

Tested on Bananapi BPi-R64 (MT7622) and Bananapi BPi-R2 (MT7623).

Tested-by: Daniel Golle <daniel@makrotopia.org>

> 
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
> ---
> v2c changes:
>   Add description for new struct
> ---
>  drivers/net/mtk_eth.c | 56 ++++++++++++++++++++++++++++++-------------
>  drivers/net/mtk_eth.h | 25 ++++++++++++++++++-
>  2 files changed, 64 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/net/mtk_eth.c b/drivers/net/mtk_eth.c
> index 4fe7ee0d36..ce4aa6e065 100644
> --- a/drivers/net/mtk_eth.c
> +++ b/drivers/net/mtk_eth.c
> @@ -142,11 +142,15 @@ enum mtk_switch {
>  	SW_MT7531
>  };
>  
> -enum mtk_soc {
> -	SOC_MT7623,
> -	SOC_MT7629,
> -	SOC_MT7622,
> -	SOC_MT7621
> +/* struct mtk_soc_data -	This is the structure holding all differences
> + *				among various plaforms
> + * @caps			Flags shown the extra capability for the SoC
> + * @ana_rgc3:			The offset for register ANA_RGC3 related to
> + *				sgmiisys syscon
> + */
> +struct mtk_soc_data {
> +	u32 caps;
> +	u32 ana_rgc3;
>  };
>  
>  struct mtk_eth_priv {
> @@ -171,7 +175,7 @@ struct mtk_eth_priv {
>  	int (*mmd_write)(struct mtk_eth_priv *priv, u8 addr, u8 devad, u16 reg,
>  			 u16 val);
>  
> -	enum mtk_soc soc;
> +	const struct mtk_soc_data *soc;
>  	int gmac_id;
>  	int force_mode;
>  	int speed;
> @@ -679,7 +683,7 @@ static int mt7530_setup(struct mtk_eth_priv *priv)
>  	u32 val, txdrv;
>  	int i;
>  
> -	if (priv->soc != SOC_MT7621) {
> +	if (!MTK_HAS_CAPS(priv->soc->caps, MTK_TRGMII_MT7621_CLK)) {
>  		/* Select 250MHz clk for RGMII mode */
>  		mtk_ethsys_rmw(priv, ETHSYS_CLKCFG0_REG,
>  			       ETHSYS_TRGMII_CLK_SEL362_5, 0);
> @@ -1108,9 +1112,8 @@ static int mtk_phy_probe(struct udevice *dev)
>  static void mtk_sgmii_init(struct mtk_eth_priv *priv)
>  {
>  	/* Set SGMII GEN2 speed(2.5G) */
> -	clrsetbits_le32(priv->sgmii_base + ((priv->soc == SOC_MT7622) ?
> -			SGMSYS_GEN2_SPEED : SGMSYS_GEN2_SPEED_V2),
> -			SGMSYS_SPEED_2500, SGMSYS_SPEED_2500);
> +	setbits_le32(priv->sgmii_base + priv->soc->ana_rgc3,
> +		     SGMSYS_SPEED_2500);
>  
>  	/* Disable SGMII AN */
>  	clrsetbits_le32(priv->sgmii_base + SGMSYS_PCS_CONTROL_1,
> @@ -1182,7 +1185,8 @@ static void mtk_mac_init(struct mtk_eth_priv *priv)
>  		mtk_gmac_write(priv, GMAC_PORT_MCR(priv->gmac_id), mcr);
>  	}
>  
> -	if (priv->soc == SOC_MT7623) {
> +	if (MTK_HAS_CAPS(priv->soc->caps, MTK_GMAC1_TRGMII) &&
> +	    !MTK_HAS_CAPS(priv->soc->caps, MTK_TRGMII_MT7621_CLK)) {
>  		/* Lower Tx Driving for TRGMII path */
>  		for (i = 0 ; i < NUM_TRGMII_CTRL; i++)
>  			mtk_gmac_write(priv, GMAC_TRGMII_TD_ODT(i),
> @@ -1431,7 +1435,11 @@ static int mtk_eth_of_to_plat(struct udevice *dev)
>  	ofnode subnode;
>  	int ret;
>  
> -	priv->soc = dev_get_driver_data(dev);
> +	priv->soc = (const struct mtk_soc_data *)dev_get_driver_data(dev);
> +	if (!priv->soc) {
> +		dev_err(dev, "missing soc compatible data\n");
> +		return -EINVAL;
> +	}
>  
>  	pdata->iobase = (phys_addr_t)dev_remap_addr(dev);
>  
> @@ -1544,11 +1552,27 @@ static int mtk_eth_of_to_plat(struct udevice *dev)
>  	return 0;
>  }
>  
> +static const struct mtk_soc_data mt7629_data = {
> +	.ana_rgc3 = 0x128,
> +};
> +
> +static const struct mtk_soc_data mt7623_data = {
> +	.caps = MT7623_CAPS,
> +};
> +
> +static const struct mtk_soc_data mt7622_data = {
> +	.ana_rgc3 = 0x2028,
> +};
> +
> +static const struct mtk_soc_data mt7621_data = {
> +	.caps = MT7621_CAPS,
> +};
> +
>  static const struct udevice_id mtk_eth_ids[] = {
> -	{ .compatible = "mediatek,mt7629-eth", .data = SOC_MT7629 },
> -	{ .compatible = "mediatek,mt7623-eth", .data = SOC_MT7623 },
> -	{ .compatible = "mediatek,mt7622-eth", .data = SOC_MT7622 },
> -	{ .compatible = "mediatek,mt7621-eth", .data = SOC_MT7621 },
> +	{ .compatible = "mediatek,mt7629-eth", .data = (ulong)&mt7629_data },
> +	{ .compatible = "mediatek,mt7623-eth", .data = (ulong)&mt7623_data },
> +	{ .compatible = "mediatek,mt7622-eth", .data = (ulong)&mt7622_data },
> +	{ .compatible = "mediatek,mt7621-eth", .data = (ulong)&mt7621_data },
>  	{}
>  };
>  
> diff --git a/drivers/net/mtk_eth.h b/drivers/net/mtk_eth.h
> index 057ecfaabf..15c2030617 100644
> --- a/drivers/net/mtk_eth.h
> +++ b/drivers/net/mtk_eth.h
> @@ -9,8 +9,31 @@
>  #ifndef _MTK_ETH_H_
>  #define _MTK_ETH_H_
>  
> -/* Frame Engine Register Bases */
>  #include <linux/bitops.h>
> +
> +enum mkt_eth_capabilities {
> +	MTK_TRGMII_BIT,
> +	MTK_TRGMII_MT7621_CLK_BIT,
> +
> +	/* PATH BITS */
> +	MTK_ETH_PATH_GMAC1_TRGMII_BIT,
> +};
> +
> +#define MTK_TRGMII			BIT(MTK_TRGMII_BIT)
> +#define MTK_TRGMII_MT7621_CLK		BIT(MTK_TRGMII_MT7621_CLK_BIT)
> +
> +/* Supported path present on SoCs */
> +#define MTK_ETH_PATH_GMAC1_TRGMII	BIT(MTK_ETH_PATH_GMAC1_TRGMII_BIT)
> +
> +#define MTK_GMAC1_TRGMII	(MTK_ETH_PATH_GMAC1_TRGMII | MTK_TRGMII)
> +
> +#define MTK_HAS_CAPS(caps, _x)		(((caps) & (_x)) == (_x))
> +
> +#define MT7621_CAPS  (MTK_GMAC1_TRGMII | MTK_TRGMII_MT7621_CLK)
> +
> +#define MT7623_CAPS  (MTK_GMAC1_TRGMII)
> +
> +/* Frame Engine Register Bases */
>  #define PDMA_BASE			0x0800
>  #define GDMA1_BASE			0x0500
>  #define GDMA2_BASE			0x1500
> -- 
> 2.17.1
> 

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

* Re: [PATCH v2 07/32] net: mediatek: stop using bitfileds for DMA descriptors
  2022-08-31 11:04 ` [PATCH v2 07/32] net: mediatek: stop using bitfileds for DMA descriptors Weijie Gao
@ 2022-09-01  0:20   ` Daniel Golle
  0 siblings, 0 replies; 60+ messages in thread
From: Daniel Golle @ 2022-09-01  0:20 UTC (permalink / raw)
  To: Weijie Gao; +Cc: u-boot, GSS_MTK_Uboot_upstream, Joe Hershberger, Ramon Fried

On Wed, Aug 31, 2022 at 07:04:23PM +0800, Weijie Gao wrote:
> This patch is a preparation for adding a new version of PDMA of which the
> DMA descriptor fields has changed. Using bitfields will result in a complex
> modification. Convert bitfields to u32 units can solve this problem easily.

Tested on Bananapi BPi-R64 (MT7622) and BPi-R2 (MT7623).

Tested-by: Daniel Golle <daniel@makrotopia.org>

> 
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
> ---
> v2 changes:
>   Fix typo in commit message
> ---
>  drivers/net/mtk_eth.c | 144 ++++++++++++++----------------------------
>  drivers/net/mtk_eth.h |  32 ++++++++++
>  2 files changed, 80 insertions(+), 96 deletions(-)
> 
> diff --git a/drivers/net/mtk_eth.c b/drivers/net/mtk_eth.c
> index ce4aa6e065..e3738b9277 100644
> --- a/drivers/net/mtk_eth.c
> +++ b/drivers/net/mtk_eth.c
> @@ -65,77 +65,6 @@
>  	(DP_DISCARD << MC_DP_S) | \
>  	(DP_DISCARD << UN_DP_S))
>  
> -struct pdma_rxd_info1 {
> -	u32 PDP0;
> -};
> -
> -struct pdma_rxd_info2 {
> -	u32 PLEN1 : 14;
> -	u32 LS1 : 1;
> -	u32 UN_USED : 1;
> -	u32 PLEN0 : 14;
> -	u32 LS0 : 1;
> -	u32 DDONE : 1;
> -};
> -
> -struct pdma_rxd_info3 {
> -	u32 PDP1;
> -};
> -
> -struct pdma_rxd_info4 {
> -	u32 FOE_ENTRY : 14;
> -	u32 CRSN : 5;
> -	u32 SP : 3;
> -	u32 L4F : 1;
> -	u32 L4VLD : 1;
> -	u32 TACK : 1;
> -	u32 IP4F : 1;
> -	u32 IP4 : 1;
> -	u32 IP6 : 1;
> -	u32 UN_USED : 4;
> -};
> -
> -struct pdma_rxdesc {
> -	struct pdma_rxd_info1 rxd_info1;
> -	struct pdma_rxd_info2 rxd_info2;
> -	struct pdma_rxd_info3 rxd_info3;
> -	struct pdma_rxd_info4 rxd_info4;
> -};
> -
> -struct pdma_txd_info1 {
> -	u32 SDP0;
> -};
> -
> -struct pdma_txd_info2 {
> -	u32 SDL1 : 14;
> -	u32 LS1 : 1;
> -	u32 BURST : 1;
> -	u32 SDL0 : 14;
> -	u32 LS0 : 1;
> -	u32 DDONE : 1;
> -};
> -
> -struct pdma_txd_info3 {
> -	u32 SDP1;
> -};
> -
> -struct pdma_txd_info4 {
> -	u32 VLAN_TAG : 16;
> -	u32 INS : 1;
> -	u32 RESV : 2;
> -	u32 UDF : 6;
> -	u32 FPORT : 3;
> -	u32 TSO : 1;
> -	u32 TUI_CO : 3;
> -};
> -
> -struct pdma_txdesc {
> -	struct pdma_txd_info1 txd_info1;
> -	struct pdma_txd_info2 txd_info2;
> -	struct pdma_txd_info3 txd_info3;
> -	struct pdma_txd_info4 txd_info4;
> -};
> -
>  enum mtk_switch {
>  	SW_NONE,
>  	SW_MT7530,
> @@ -151,13 +80,15 @@ enum mtk_switch {
>  struct mtk_soc_data {
>  	u32 caps;
>  	u32 ana_rgc3;
> +	u32 txd_size;
> +	u32 rxd_size;
>  };
>  
>  struct mtk_eth_priv {
>  	char pkt_pool[TOTAL_PKT_BUF_SIZE] __aligned(ARCH_DMA_MINALIGN);
>  
> -	struct pdma_txdesc *tx_ring_noc;
> -	struct pdma_rxdesc *rx_ring_noc;
> +	void *tx_ring_noc;
> +	void *rx_ring_noc;
>  
>  	int rx_dma_owner_idx0;
>  	int tx_cpu_owner_idx0;
> @@ -1202,14 +1133,16 @@ static void mtk_mac_init(struct mtk_eth_priv *priv)
>  static void mtk_eth_fifo_init(struct mtk_eth_priv *priv)
>  {
>  	char *pkt_base = priv->pkt_pool;
> +	struct mtk_tx_dma *txd;
> +	struct mtk_rx_dma *rxd;
>  	int i;
>  
>  	mtk_pdma_rmw(priv, PDMA_GLO_CFG_REG, 0xffff0000, 0);
>  	udelay(500);
>  
> -	memset(priv->tx_ring_noc, 0, NUM_TX_DESC * sizeof(struct pdma_txdesc));
> -	memset(priv->rx_ring_noc, 0, NUM_RX_DESC * sizeof(struct pdma_rxdesc));
> -	memset(priv->pkt_pool, 0, TOTAL_PKT_BUF_SIZE);
> +	memset(priv->tx_ring_noc, 0, NUM_TX_DESC * priv->soc->txd_size);
> +	memset(priv->rx_ring_noc, 0, NUM_RX_DESC * priv->soc->rxd_size);
> +	memset(priv->pkt_pool, 0xff, TOTAL_PKT_BUF_SIZE);
>  
>  	flush_dcache_range((ulong)pkt_base,
>  			   (ulong)(pkt_base + TOTAL_PKT_BUF_SIZE));
> @@ -1218,17 +1151,21 @@ static void mtk_eth_fifo_init(struct mtk_eth_priv *priv)
>  	priv->tx_cpu_owner_idx0 = 0;
>  
>  	for (i = 0; i < NUM_TX_DESC; i++) {
> -		priv->tx_ring_noc[i].txd_info2.LS0 = 1;
> -		priv->tx_ring_noc[i].txd_info2.DDONE = 1;
> -		priv->tx_ring_noc[i].txd_info4.FPORT = priv->gmac_id + 1;
> +		txd = priv->tx_ring_noc + i * priv->soc->txd_size;
> +
> +		txd->txd1 = virt_to_phys(pkt_base);
> +		txd->txd2 = PDMA_TXD2_DDONE | PDMA_TXD2_LS0;
> +		txd->txd4 = PDMA_TXD4_FPORT_SET(priv->gmac_id + 1);
>  
> -		priv->tx_ring_noc[i].txd_info1.SDP0 = virt_to_phys(pkt_base);
>  		pkt_base += PKTSIZE_ALIGN;
>  	}
>  
>  	for (i = 0; i < NUM_RX_DESC; i++) {
> -		priv->rx_ring_noc[i].rxd_info2.PLEN0 = PKTSIZE_ALIGN;
> -		priv->rx_ring_noc[i].rxd_info1.PDP0 = virt_to_phys(pkt_base);
> +		rxd = priv->rx_ring_noc + i * priv->soc->rxd_size;
> +
> +		rxd->rxd1 = virt_to_phys(pkt_base);
> +		rxd->rxd2 = PDMA_RXD2_PLEN0_SET(PKTSIZE_ALIGN);
> +
>  		pkt_base += PKTSIZE_ALIGN;
>  	}
>  
> @@ -1315,20 +1252,22 @@ static int mtk_eth_send(struct udevice *dev, void *packet, int length)
>  {
>  	struct mtk_eth_priv *priv = dev_get_priv(dev);
>  	u32 idx = priv->tx_cpu_owner_idx0;
> +	struct mtk_tx_dma *txd;
>  	void *pkt_base;
>  
> -	if (!priv->tx_ring_noc[idx].txd_info2.DDONE) {
> +	txd = priv->tx_ring_noc + idx * priv->soc->txd_size;
> +
> +	if (!(txd->txd2 & PDMA_TXD2_DDONE)) {
>  		debug("mtk-eth: TX DMA descriptor ring is full\n");
>  		return -EPERM;
>  	}
>  
> -	pkt_base = (void *)phys_to_virt(priv->tx_ring_noc[idx].txd_info1.SDP0);
> +	pkt_base = (void *)phys_to_virt(txd->txd1);
>  	memcpy(pkt_base, packet, length);
>  	flush_dcache_range((ulong)pkt_base, (ulong)pkt_base +
>  			   roundup(length, ARCH_DMA_MINALIGN));
>  
> -	priv->tx_ring_noc[idx].txd_info2.SDL0 = length;
> -	priv->tx_ring_noc[idx].txd_info2.DDONE = 0;
> +	txd->txd2 = PDMA_TXD2_LS0 | PDMA_TXD2_SDL0_SET(length);
>  
>  	priv->tx_cpu_owner_idx0 = (priv->tx_cpu_owner_idx0 + 1) % NUM_TX_DESC;
>  	mtk_pdma_write(priv, TX_CTX_IDX_REG(0), priv->tx_cpu_owner_idx0);
> @@ -1340,16 +1279,20 @@ static int mtk_eth_recv(struct udevice *dev, int flags, uchar **packetp)
>  {
>  	struct mtk_eth_priv *priv = dev_get_priv(dev);
>  	u32 idx = priv->rx_dma_owner_idx0;
> +	struct mtk_rx_dma *rxd;
>  	uchar *pkt_base;
>  	u32 length;
>  
> -	if (!priv->rx_ring_noc[idx].rxd_info2.DDONE) {
> +	rxd = priv->rx_ring_noc + idx * priv->soc->rxd_size;
> +
> +	if (!(rxd->rxd2 & PDMA_RXD2_DDONE)) {
>  		debug("mtk-eth: RX DMA descriptor ring is empty\n");
>  		return -EAGAIN;
>  	}
>  
> -	length = priv->rx_ring_noc[idx].rxd_info2.PLEN0;
> -	pkt_base = (void *)phys_to_virt(priv->rx_ring_noc[idx].rxd_info1.PDP0);
> +	length = PDMA_RXD2_PLEN0_GET(rxd->rxd2);
> +
> +	pkt_base = (void *)phys_to_virt(rxd->rxd1);
>  	invalidate_dcache_range((ulong)pkt_base, (ulong)pkt_base +
>  				roundup(length, ARCH_DMA_MINALIGN));
>  
> @@ -1363,10 +1306,11 @@ static int mtk_eth_free_pkt(struct udevice *dev, uchar *packet, int length)
>  {
>  	struct mtk_eth_priv *priv = dev_get_priv(dev);
>  	u32 idx = priv->rx_dma_owner_idx0;
> +	struct mtk_rx_dma *rxd;
> +
> +	rxd = priv->rx_ring_noc + idx * priv->soc->rxd_size;
>  
> -	priv->rx_ring_noc[idx].rxd_info2.DDONE = 0;
> -	priv->rx_ring_noc[idx].rxd_info2.LS0 = 0;
> -	priv->rx_ring_noc[idx].rxd_info2.PLEN0 = PKTSIZE_ALIGN;
> +	rxd->rxd2 = PDMA_RXD2_PLEN0_SET(PKTSIZE_ALIGN);
>  
>  	mtk_pdma_write(priv, RX_CRX_IDX_REG(0), idx);
>  	priv->rx_dma_owner_idx0 = (priv->rx_dma_owner_idx0 + 1) % NUM_RX_DESC;
> @@ -1393,11 +1337,11 @@ static int mtk_eth_probe(struct udevice *dev)
>  		return ret;
>  
>  	/* Prepare for tx/rx rings */
> -	priv->tx_ring_noc = (struct pdma_txdesc *)
> -		noncached_alloc(sizeof(struct pdma_txdesc) * NUM_TX_DESC,
> +	priv->tx_ring_noc = (void *)
> +		noncached_alloc(priv->soc->txd_size * NUM_TX_DESC,
>  				ARCH_DMA_MINALIGN);
> -	priv->rx_ring_noc = (struct pdma_rxdesc *)
> -		noncached_alloc(sizeof(struct pdma_rxdesc) * NUM_RX_DESC,
> +	priv->rx_ring_noc = (void *)
> +		noncached_alloc(priv->soc->rxd_size * NUM_RX_DESC,
>  				ARCH_DMA_MINALIGN);
>  
>  	/* Set MAC mode */
> @@ -1554,18 +1498,26 @@ static int mtk_eth_of_to_plat(struct udevice *dev)
>  
>  static const struct mtk_soc_data mt7629_data = {
>  	.ana_rgc3 = 0x128,
> +	.txd_size = sizeof(struct mtk_tx_dma),
> +	.rxd_size = sizeof(struct mtk_rx_dma),
>  };
>  
>  static const struct mtk_soc_data mt7623_data = {
>  	.caps = MT7623_CAPS,
> +	.txd_size = sizeof(struct mtk_tx_dma),
> +	.rxd_size = sizeof(struct mtk_rx_dma),
>  };
>  
>  static const struct mtk_soc_data mt7622_data = {
>  	.ana_rgc3 = 0x2028,
> +	.txd_size = sizeof(struct mtk_tx_dma),
> +	.rxd_size = sizeof(struct mtk_rx_dma),
>  };
>  
>  static const struct mtk_soc_data mt7621_data = {
>  	.caps = MT7621_CAPS,
> +	.txd_size = sizeof(struct mtk_tx_dma),
> +	.rxd_size = sizeof(struct mtk_rx_dma),
>  };
>  
>  static const struct udevice_id mtk_eth_ids[] = {
> diff --git a/drivers/net/mtk_eth.h b/drivers/net/mtk_eth.h
> index 15c2030617..65bc9fcc04 100644
> --- a/drivers/net/mtk_eth.h
> +++ b/drivers/net/mtk_eth.h
> @@ -10,6 +10,7 @@
>  #define _MTK_ETH_H_
>  
>  #include <linux/bitops.h>
> +#include <linux/bitfield.h>
>  
>  enum mkt_eth_capabilities {
>  	MTK_TRGMII_BIT,
> @@ -435,4 +436,35 @@ enum mkt_eth_capabilities {
>  #define PHY_POWER_SAVING_M		0x300
>  #define PHY_POWER_SAVING_TX		0x0
>  
> +/* PDMA descriptors */
> +struct mtk_rx_dma {
> +	unsigned int rxd1;
> +	unsigned int rxd2;
> +	unsigned int rxd3;
> +	unsigned int rxd4;
> +} __packed __aligned(4);
> +
> +struct mtk_tx_dma {
> +	unsigned int txd1;
> +	unsigned int txd2;
> +	unsigned int txd3;
> +	unsigned int txd4;
> +} __packed __aligned(4);
> +
> +/* PDMA TXD fields */
> +#define PDMA_TXD2_DDONE			BIT(31)
> +#define PDMA_TXD2_LS0			BIT(30)
> +#define PDMA_TXD2_SDL0_M		GENMASK(29, 16)
> +#define PDMA_TXD2_SDL0_SET(_v)	FIELD_PREP(PDMA_TXD2_SDL0_M, (_v))
> +
> +#define PDMA_TXD4_FPORT_M		GENMASK(27, 25)
> +#define PDMA_TXD4_FPORT_SET(_v)	FIELD_PREP(PDMA_TXD4_FPORT_M, (_v))
> +
> +/* PDMA RXD fields */
> +#define PDMA_RXD2_DDONE			BIT(31)
> +#define PDMA_RXD2_LS0			BIT(30)
> +#define PDMA_RXD2_PLEN0_M		GENMASK(29, 16)
> +#define PDMA_RXD2_PLEN0_GET(_v)	FIELD_GET(PDMA_RXD2_PLEN0_M, (_v))
> +#define PDMA_RXD2_PLEN0_SET(_v)	FIELD_PREP(PDMA_RXD2_PLEN0_M, (_v))
> +
>  #endif /* _MTK_ETH_H_ */
> -- 
> 2.17.1
> 

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

* Re: [PATCH v2 08/32] net: mediatek: add support for PDMA v2
  2022-08-31 11:04 ` [PATCH v2 08/32] net: mediatek: add support for PDMA v2 Weijie Gao
@ 2022-09-01  0:22   ` Daniel Golle
  0 siblings, 0 replies; 60+ messages in thread
From: Daniel Golle @ 2022-09-01  0:22 UTC (permalink / raw)
  To: Weijie Gao; +Cc: u-boot, GSS_MTK_Uboot_upstream, Joe Hershberger, Ramon Fried

On Wed, Aug 31, 2022 at 07:04:27PM +0800, Weijie Gao wrote:
> This patch adds support for PDMA v2 hardware. The PDMA v2 has extended the
> DMA descriptor to 8-words, and some of its fields have changed comparing
> to the v1 hardware.

Tested on Bananapi BPi-R2 (MT7623), Bananapi BPi-R64 (MT7623) and
Bananapi BPi-R3 (MT7986A).

Tested-by: Daniel Golle <daniel@makrotopia.org>

> 
> Reviewed-by: Ramon Fried <rfried.dev@gmail.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
> ---
> v2 changes:
>   Add description for new fields
> ---
>  drivers/net/mtk_eth.c | 54 ++++++++++++++++++++++++++++++++-----------
>  drivers/net/mtk_eth.h | 53 +++++++++++++++++++++++++++++++++++-------
>  2 files changed, 86 insertions(+), 21 deletions(-)
> 
> diff --git a/drivers/net/mtk_eth.c b/drivers/net/mtk_eth.c
> index e3738b9277..fb72baae68 100644
> --- a/drivers/net/mtk_eth.c
> +++ b/drivers/net/mtk_eth.c
> @@ -76,10 +76,14 @@ enum mtk_switch {
>   * @caps			Flags shown the extra capability for the SoC
>   * @ana_rgc3:			The offset for register ANA_RGC3 related to
>   *				sgmiisys syscon
> + * @pdma_base:			Register base of PDMA block
> + * @txd_size:			Tx DMA descriptor size.
> + * @rxd_size:			Rx DMA descriptor size.
>   */
>  struct mtk_soc_data {
>  	u32 caps;
>  	u32 ana_rgc3;
> +	u32 pdma_base;
>  	u32 txd_size;
>  	u32 rxd_size;
>  };
> @@ -130,13 +134,13 @@ struct mtk_eth_priv {
>  
>  static void mtk_pdma_write(struct mtk_eth_priv *priv, u32 reg, u32 val)
>  {
> -	writel(val, priv->fe_base + PDMA_BASE + reg);
> +	writel(val, priv->fe_base + priv->soc->pdma_base + reg);
>  }
>  
>  static void mtk_pdma_rmw(struct mtk_eth_priv *priv, u32 reg, u32 clr,
>  			 u32 set)
>  {
> -	clrsetbits_le32(priv->fe_base + PDMA_BASE + reg, clr, set);
> +	clrsetbits_le32(priv->fe_base + priv->soc->pdma_base + reg, clr, set);
>  }
>  
>  static void mtk_gdma_write(struct mtk_eth_priv *priv, int no, u32 reg,
> @@ -1133,8 +1137,8 @@ static void mtk_mac_init(struct mtk_eth_priv *priv)
>  static void mtk_eth_fifo_init(struct mtk_eth_priv *priv)
>  {
>  	char *pkt_base = priv->pkt_pool;
> -	struct mtk_tx_dma *txd;
> -	struct mtk_rx_dma *rxd;
> +	struct mtk_tx_dma_v2 *txd;
> +	struct mtk_rx_dma_v2 *rxd;
>  	int i;
>  
>  	mtk_pdma_rmw(priv, PDMA_GLO_CFG_REG, 0xffff0000, 0);
> @@ -1155,7 +1159,11 @@ static void mtk_eth_fifo_init(struct mtk_eth_priv *priv)
>  
>  		txd->txd1 = virt_to_phys(pkt_base);
>  		txd->txd2 = PDMA_TXD2_DDONE | PDMA_TXD2_LS0;
> -		txd->txd4 = PDMA_TXD4_FPORT_SET(priv->gmac_id + 1);
> +
> +		if (MTK_HAS_CAPS(priv->soc->caps, MTK_NETSYS_V2))
> +			txd->txd5 = PDMA_V2_TXD5_FPORT_SET(priv->gmac_id + 1);
> +		else
> +			txd->txd4 = PDMA_V1_TXD4_FPORT_SET(priv->gmac_id + 1);
>  
>  		pkt_base += PKTSIZE_ALIGN;
>  	}
> @@ -1164,7 +1172,11 @@ static void mtk_eth_fifo_init(struct mtk_eth_priv *priv)
>  		rxd = priv->rx_ring_noc + i * priv->soc->rxd_size;
>  
>  		rxd->rxd1 = virt_to_phys(pkt_base);
> -		rxd->rxd2 = PDMA_RXD2_PLEN0_SET(PKTSIZE_ALIGN);
> +
> +		if (MTK_HAS_CAPS(priv->soc->caps, MTK_NETSYS_V2))
> +			rxd->rxd2 = PDMA_V2_RXD2_PLEN0_SET(PKTSIZE_ALIGN);
> +		else
> +			rxd->rxd2 = PDMA_V1_RXD2_PLEN0_SET(PKTSIZE_ALIGN);
>  
>  		pkt_base += PKTSIZE_ALIGN;
>  	}
> @@ -1193,6 +1205,9 @@ static int mtk_eth_start(struct udevice *dev)
>  	reset_deassert(&priv->rst_fe);
>  	mdelay(10);
>  
> +	if (MTK_HAS_CAPS(priv->soc->caps, MTK_NETSYS_V2))
> +		setbits_le32(priv->fe_base + FE_GLO_MISC_REG, PDMA_VER_V2);
> +
>  	/* Packets forward to PDMA */
>  	mtk_gdma_write(priv, priv->gmac_id, GDMA_IG_CTRL_REG, GDMA_FWD_TO_CPU);
>  
> @@ -1227,7 +1242,7 @@ static void mtk_eth_stop(struct udevice *dev)
>  		     TX_WB_DDONE | RX_DMA_EN | TX_DMA_EN, 0);
>  	udelay(500);
>  
> -	wait_for_bit_le32(priv->fe_base + PDMA_BASE + PDMA_GLO_CFG_REG,
> +	wait_for_bit_le32(priv->fe_base + priv->soc->pdma_base + PDMA_GLO_CFG_REG,
>  			  RX_DMA_BUSY | TX_DMA_BUSY, 0, 5000, 0);
>  }
>  
> @@ -1252,7 +1267,7 @@ static int mtk_eth_send(struct udevice *dev, void *packet, int length)
>  {
>  	struct mtk_eth_priv *priv = dev_get_priv(dev);
>  	u32 idx = priv->tx_cpu_owner_idx0;
> -	struct mtk_tx_dma *txd;
> +	struct mtk_tx_dma_v2 *txd;
>  	void *pkt_base;
>  
>  	txd = priv->tx_ring_noc + idx * priv->soc->txd_size;
> @@ -1267,7 +1282,10 @@ static int mtk_eth_send(struct udevice *dev, void *packet, int length)
>  	flush_dcache_range((ulong)pkt_base, (ulong)pkt_base +
>  			   roundup(length, ARCH_DMA_MINALIGN));
>  
> -	txd->txd2 = PDMA_TXD2_LS0 | PDMA_TXD2_SDL0_SET(length);
> +	if (MTK_HAS_CAPS(priv->soc->caps, MTK_NETSYS_V2))
> +		txd->txd2 = PDMA_TXD2_LS0 | PDMA_V2_TXD2_SDL0_SET(length);
> +	else
> +		txd->txd2 = PDMA_TXD2_LS0 | PDMA_V1_TXD2_SDL0_SET(length);
>  
>  	priv->tx_cpu_owner_idx0 = (priv->tx_cpu_owner_idx0 + 1) % NUM_TX_DESC;
>  	mtk_pdma_write(priv, TX_CTX_IDX_REG(0), priv->tx_cpu_owner_idx0);
> @@ -1279,7 +1297,7 @@ static int mtk_eth_recv(struct udevice *dev, int flags, uchar **packetp)
>  {
>  	struct mtk_eth_priv *priv = dev_get_priv(dev);
>  	u32 idx = priv->rx_dma_owner_idx0;
> -	struct mtk_rx_dma *rxd;
> +	struct mtk_rx_dma_v2 *rxd;
>  	uchar *pkt_base;
>  	u32 length;
>  
> @@ -1290,7 +1308,10 @@ static int mtk_eth_recv(struct udevice *dev, int flags, uchar **packetp)
>  		return -EAGAIN;
>  	}
>  
> -	length = PDMA_RXD2_PLEN0_GET(rxd->rxd2);
> +	if (MTK_HAS_CAPS(priv->soc->caps, MTK_NETSYS_V2))
> +		length = PDMA_V2_RXD2_PLEN0_GET(rxd->rxd2);
> +	else
> +		length = PDMA_V1_RXD2_PLEN0_GET(rxd->rxd2);
>  
>  	pkt_base = (void *)phys_to_virt(rxd->rxd1);
>  	invalidate_dcache_range((ulong)pkt_base, (ulong)pkt_base +
> @@ -1306,11 +1327,14 @@ static int mtk_eth_free_pkt(struct udevice *dev, uchar *packet, int length)
>  {
>  	struct mtk_eth_priv *priv = dev_get_priv(dev);
>  	u32 idx = priv->rx_dma_owner_idx0;
> -	struct mtk_rx_dma *rxd;
> +	struct mtk_rx_dma_v2 *rxd;
>  
>  	rxd = priv->rx_ring_noc + idx * priv->soc->rxd_size;
>  
> -	rxd->rxd2 = PDMA_RXD2_PLEN0_SET(PKTSIZE_ALIGN);
> +	if (MTK_HAS_CAPS(priv->soc->caps, MTK_NETSYS_V2))
> +		rxd->rxd2 = PDMA_V2_RXD2_PLEN0_SET(PKTSIZE_ALIGN);
> +	else
> +		rxd->rxd2 = PDMA_V1_RXD2_PLEN0_SET(PKTSIZE_ALIGN);
>  
>  	mtk_pdma_write(priv, RX_CRX_IDX_REG(0), idx);
>  	priv->rx_dma_owner_idx0 = (priv->rx_dma_owner_idx0 + 1) % NUM_RX_DESC;
> @@ -1498,24 +1522,28 @@ static int mtk_eth_of_to_plat(struct udevice *dev)
>  
>  static const struct mtk_soc_data mt7629_data = {
>  	.ana_rgc3 = 0x128,
> +	.pdma_base = PDMA_V1_BASE,
>  	.txd_size = sizeof(struct mtk_tx_dma),
>  	.rxd_size = sizeof(struct mtk_rx_dma),
>  };
>  
>  static const struct mtk_soc_data mt7623_data = {
>  	.caps = MT7623_CAPS,
> +	.pdma_base = PDMA_V1_BASE,
>  	.txd_size = sizeof(struct mtk_tx_dma),
>  	.rxd_size = sizeof(struct mtk_rx_dma),
>  };
>  
>  static const struct mtk_soc_data mt7622_data = {
>  	.ana_rgc3 = 0x2028,
> +	.pdma_base = PDMA_V1_BASE,
>  	.txd_size = sizeof(struct mtk_tx_dma),
>  	.rxd_size = sizeof(struct mtk_rx_dma),
>  };
>  
>  static const struct mtk_soc_data mt7621_data = {
>  	.caps = MT7621_CAPS,
> +	.pdma_base = PDMA_V1_BASE,
>  	.txd_size = sizeof(struct mtk_tx_dma),
>  	.rxd_size = sizeof(struct mtk_rx_dma),
>  };
> diff --git a/drivers/net/mtk_eth.h b/drivers/net/mtk_eth.h
> index 65bc9fcc04..236c498a1b 100644
> --- a/drivers/net/mtk_eth.h
> +++ b/drivers/net/mtk_eth.h
> @@ -15,6 +15,7 @@
>  enum mkt_eth_capabilities {
>  	MTK_TRGMII_BIT,
>  	MTK_TRGMII_MT7621_CLK_BIT,
> +	MTK_NETSYS_V2_BIT,
>  
>  	/* PATH BITS */
>  	MTK_ETH_PATH_GMAC1_TRGMII_BIT,
> @@ -22,6 +23,7 @@ enum mkt_eth_capabilities {
>  
>  #define MTK_TRGMII			BIT(MTK_TRGMII_BIT)
>  #define MTK_TRGMII_MT7621_CLK		BIT(MTK_TRGMII_MT7621_CLK_BIT)
> +#define MTK_NETSYS_V2			BIT(MTK_NETSYS_V2_BIT)
>  
>  /* Supported path present on SoCs */
>  #define MTK_ETH_PATH_GMAC1_TRGMII	BIT(MTK_ETH_PATH_GMAC1_TRGMII_BIT)
> @@ -35,7 +37,8 @@ enum mkt_eth_capabilities {
>  #define MT7623_CAPS  (MTK_GMAC1_TRGMII)
>  
>  /* Frame Engine Register Bases */
> -#define PDMA_BASE			0x0800
> +#define PDMA_V1_BASE			0x0800
> +#define PDMA_V2_BASE			0x6000
>  #define GDMA1_BASE			0x0500
>  #define GDMA2_BASE			0x1500
>  #define GMAC_BASE			0x10000
> @@ -74,6 +77,8 @@ enum mkt_eth_capabilities {
>  #define SGMSYS_SPEED_2500		BIT(2)
>  
>  /* Frame Engine Registers */
> +#define FE_GLO_MISC_REG			0x124
> +#define PDMA_VER_V2			BIT(4)
>  
>  /* PDMA */
>  #define TX_BASE_PTR_REG(n)		(0x000 + (n) * 0x10)
> @@ -444,6 +449,17 @@ struct mtk_rx_dma {
>  	unsigned int rxd4;
>  } __packed __aligned(4);
>  
> +struct mtk_rx_dma_v2 {
> +	unsigned int rxd1;
> +	unsigned int rxd2;
> +	unsigned int rxd3;
> +	unsigned int rxd4;
> +	unsigned int rxd5;
> +	unsigned int rxd6;
> +	unsigned int rxd7;
> +	unsigned int rxd8;
> +} __packed __aligned(4);
> +
>  struct mtk_tx_dma {
>  	unsigned int txd1;
>  	unsigned int txd2;
> @@ -451,20 +467,41 @@ struct mtk_tx_dma {
>  	unsigned int txd4;
>  } __packed __aligned(4);
>  
> +struct mtk_tx_dma_v2 {
> +	unsigned int txd1;
> +	unsigned int txd2;
> +	unsigned int txd3;
> +	unsigned int txd4;
> +	unsigned int txd5;
> +	unsigned int txd6;
> +	unsigned int txd7;
> +	unsigned int txd8;
> +} __packed __aligned(4);
> +
>  /* PDMA TXD fields */
>  #define PDMA_TXD2_DDONE			BIT(31)
>  #define PDMA_TXD2_LS0			BIT(30)
> -#define PDMA_TXD2_SDL0_M		GENMASK(29, 16)
> -#define PDMA_TXD2_SDL0_SET(_v)	FIELD_PREP(PDMA_TXD2_SDL0_M, (_v))
> +#define PDMA_V1_TXD2_SDL0_M		GENMASK(29, 16)
> +#define PDMA_V1_TXD2_SDL0_SET(_v)	FIELD_PREP(PDMA_V1_TXD2_SDL0_M, (_v))
> +#define PDMA_V2_TXD2_SDL0_M		GENMASK(23, 8)
> +#define PDMA_V2_TXD2_SDL0_SET(_v)	FIELD_PREP(PDMA_V2_TXD2_SDL0_M, (_v))
> +
> +#define PDMA_V1_TXD4_FPORT_M		GENMASK(27, 25)
> +#define PDMA_V1_TXD4_FPORT_SET(_v)	FIELD_PREP(PDMA_V1_TXD4_FPORT_M, (_v))
> +#define PDMA_V2_TXD4_FPORT_M		GENMASK(27, 24)
> +#define PDMA_V2_TXD4_FPORT_SET(_v)	FIELD_PREP(PDMA_V2_TXD4_FPORT_M, (_v))
>  
> -#define PDMA_TXD4_FPORT_M		GENMASK(27, 25)
> -#define PDMA_TXD4_FPORT_SET(_v)	FIELD_PREP(PDMA_TXD4_FPORT_M, (_v))
> +#define PDMA_V2_TXD5_FPORT_M		GENMASK(19, 16)
> +#define PDMA_V2_TXD5_FPORT_SET(_v)	FIELD_PREP(PDMA_V2_TXD5_FPORT_M, (_v))
>  
>  /* PDMA RXD fields */
>  #define PDMA_RXD2_DDONE			BIT(31)
>  #define PDMA_RXD2_LS0			BIT(30)
> -#define PDMA_RXD2_PLEN0_M		GENMASK(29, 16)
> -#define PDMA_RXD2_PLEN0_GET(_v)	FIELD_GET(PDMA_RXD2_PLEN0_M, (_v))
> -#define PDMA_RXD2_PLEN0_SET(_v)	FIELD_PREP(PDMA_RXD2_PLEN0_M, (_v))
> +#define PDMA_V1_RXD2_PLEN0_M		GENMASK(29, 16)
> +#define PDMA_V1_RXD2_PLEN0_GET(_v)	FIELD_GET(PDMA_V1_RXD2_PLEN0_M, (_v))
> +#define PDMA_V1_RXD2_PLEN0_SET(_v)	FIELD_PREP(PDMA_V1_RXD2_PLEN0_M, (_v))
> +#define PDMA_V2_RXD2_PLEN0_M		GENMASK(23, 8)
> +#define PDMA_V2_RXD2_PLEN0_GET(_v)	FIELD_GET(PDMA_V2_RXD2_PLEN0_M, (_v))
> +#define PDMA_V2_RXD2_PLEN0_SET(_v)	FIELD_PREP(PDMA_V2_RXD2_PLEN0_M, (_v))
>  
>  #endif /* _MTK_ETH_H_ */
> -- 
> 2.17.1
> 

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

* Re: [PATCH v2 09/32] net: mediatek: add support for MediaTek MT7981/MT7986
  2022-08-31 11:04 ` [PATCH v2 09/32] net: mediatek: add support for MediaTek MT7981/MT7986 Weijie Gao
@ 2022-09-01  0:22   ` Daniel Golle
  0 siblings, 0 replies; 60+ messages in thread
From: Daniel Golle @ 2022-09-01  0:22 UTC (permalink / raw)
  To: Weijie Gao; +Cc: u-boot, GSS_MTK_Uboot_upstream, Joe Hershberger, Ramon Fried

On Wed, Aug 31, 2022 at 07:04:29PM +0800, Weijie Gao wrote:
> This patch adds support for MediaTek MT7981 and MT7986. Both chips uses
> PDMA v2.
> 

Tested on Bananapi BPi-R2 (MT7623), Bananapi BPi-R64 (MT7623) and
Bananapi BPi-R3 (MT7986A).

Tested-by: Daniel Golle <daniel@makrotopia.org>


> Reviewed-by: Ramon Fried <rfried.dev@gmail.com>
> Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
> ---
> v2 changes: none
> ---
>  drivers/net/mtk_eth.c | 27 +++++++++++++++++++++++++++
>  drivers/net/mtk_eth.h |  5 +++++
>  2 files changed, 32 insertions(+)
> 
> diff --git a/drivers/net/mtk_eth.c b/drivers/net/mtk_eth.c
> index fb72baae68..4c9fb266c7 100644
> --- a/drivers/net/mtk_eth.c
> +++ b/drivers/net/mtk_eth.c
> @@ -115,6 +115,7 @@ struct mtk_eth_priv {
>  	int force_mode;
>  	int speed;
>  	int duplex;
> +	bool pn_swap;
>  
>  	struct phy_device *phydev;
>  	int phy_interface;
> @@ -1057,6 +1058,12 @@ static void mtk_sgmii_init(struct mtk_eth_priv *priv)
>  	/* SGMII force mode setting */
>  	writel(SGMII_FORCE_MODE, priv->sgmii_base + SGMSYS_SGMII_MODE);
>  
> +	/* SGMII PN SWAP setting */
> +	if (priv->pn_swap) {
> +		setbits_le32(priv->sgmii_base + SGMSYS_QPHY_WRAP_CTRL,
> +			     SGMII_PN_SWAP_TX_RX);
> +	}
> +
>  	/* Release PHYA power down state */
>  	clrsetbits_le32(priv->sgmii_base + SGMSYS_QPHY_PWR_STATE_CTRL,
>  			SGMII_PHYA_PWD, 0);
> @@ -1470,6 +1477,8 @@ static int mtk_eth_of_to_plat(struct udevice *dev)
>  			dev_err(dev, "Unable to find sgmii\n");
>  			return -ENODEV;
>  		}
> +
> +		priv->pn_swap = ofnode_read_bool(args.node, "pn_swap");
>  	}
>  
>  	/* check for switch first, otherwise phy will be used */
> @@ -1520,6 +1529,22 @@ static int mtk_eth_of_to_plat(struct udevice *dev)
>  	return 0;
>  }
>  
> +static const struct mtk_soc_data mt7986_data = {
> +	.caps = MT7986_CAPS,
> +	.ana_rgc3 = 0x128,
> +	.pdma_base = PDMA_V2_BASE,
> +	.txd_size = sizeof(struct mtk_tx_dma_v2),
> +	.rxd_size = sizeof(struct mtk_rx_dma_v2),
> +};
> +
> +static const struct mtk_soc_data mt7981_data = {
> +	.caps = MT7986_CAPS,
> +	.ana_rgc3 = 0x128,
> +	.pdma_base = PDMA_V2_BASE,
> +	.txd_size = sizeof(struct mtk_tx_dma_v2),
> +	.rxd_size = sizeof(struct mtk_rx_dma_v2),
> +};
> +
>  static const struct mtk_soc_data mt7629_data = {
>  	.ana_rgc3 = 0x128,
>  	.pdma_base = PDMA_V1_BASE,
> @@ -1549,6 +1574,8 @@ static const struct mtk_soc_data mt7621_data = {
>  };
>  
>  static const struct udevice_id mtk_eth_ids[] = {
> +	{ .compatible = "mediatek,mt7986-eth", .data = (ulong)&mt7986_data },
> +	{ .compatible = "mediatek,mt7981-eth", .data = (ulong)&mt7981_data },
>  	{ .compatible = "mediatek,mt7629-eth", .data = (ulong)&mt7629_data },
>  	{ .compatible = "mediatek,mt7623-eth", .data = (ulong)&mt7623_data },
>  	{ .compatible = "mediatek,mt7622-eth", .data = (ulong)&mt7622_data },
> diff --git a/drivers/net/mtk_eth.h b/drivers/net/mtk_eth.h
> index 236c498a1b..1382ccbeb2 100644
> --- a/drivers/net/mtk_eth.h
> +++ b/drivers/net/mtk_eth.h
> @@ -36,6 +36,8 @@ enum mkt_eth_capabilities {
>  
>  #define MT7623_CAPS  (MTK_GMAC1_TRGMII)
>  
> +#define MT7986_CAPS  (MTK_NETSYS_V2)
> +
>  /* Frame Engine Register Bases */
>  #define PDMA_V1_BASE			0x0800
>  #define PDMA_V2_BASE			0x6000
> @@ -72,6 +74,9 @@ enum mkt_eth_capabilities {
>  #define SGMSYS_QPHY_PWR_STATE_CTRL	0xe8
>  #define SGMII_PHYA_PWD			BIT(4)
>  
> +#define SGMSYS_QPHY_WRAP_CTRL		0xec
> +#define SGMII_PN_SWAP_TX_RX		0x03
> +
>  #define SGMSYS_GEN2_SPEED		0x2028
>  #define SGMSYS_GEN2_SPEED_V2		0x128
>  #define SGMSYS_SPEED_2500		BIT(2)
> -- 
> 2.17.1
> 

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

* Re: [PATCH v2 10/32] serial: mtk: add support for using dynamic baud clock souce
  2022-08-31 11:04 ` [PATCH v2 10/32] serial: mtk: add support for using dynamic baud clock souce Weijie Gao
@ 2022-09-01  0:22   ` Daniel Golle
  0 siblings, 0 replies; 60+ messages in thread
From: Daniel Golle @ 2022-09-01  0:22 UTC (permalink / raw)
  To: Weijie Gao; +Cc: u-boot, GSS_MTK_Uboot_upstream, Pali Rohár

On Wed, Aug 31, 2022 at 07:04:32PM +0800, Weijie Gao wrote:
> The baud clock on some platform may change due to assigned-clock-parent
> set in DT. In current flow the baud clock is only retrieved during probe
> stage. If the parent of the source clock changes after probe stage, the
> setbrg will set wrong baudrate.
> 
> To get the right clock rate, this patch records the baud clk struct to the
> driver's priv, and changes the driver's flow to get the clock rate before
> calling _mtk_serial_setbrg().

Tested on Bananapi BPi-R2 (MT7623), Bananapi BPi-R64 (MT7623) and
Bananapi BPi-R3 (MT7986A).

Tested-by: Daniel Golle <daniel@makrotopia.org>

> 
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
> ---
> v2 changes:
>   Add description for priv struct
>   Fix the type of clk_rate
> ---
>  drivers/serial/serial_mtk.c | 80 ++++++++++++++++++++++---------------
>  1 file changed, 47 insertions(+), 33 deletions(-)
> 
> diff --git a/drivers/serial/serial_mtk.c b/drivers/serial/serial_mtk.c
> index a84f39b3fa..1d7cc9f7b6 100644
> --- a/drivers/serial/serial_mtk.c
> +++ b/drivers/serial/serial_mtk.c
> @@ -10,6 +10,7 @@
>  #include <common.h>
>  #include <div64.h>
>  #include <dm.h>
> +#include <dm/device_compat.h>
>  #include <errno.h>
>  #include <log.h>
>  #include <serial.h>
> @@ -70,27 +71,37 @@ struct mtk_serial_regs {
>  #define BAUD_ALLOW_MAX(baud)	((baud) + (baud) * 3 / 100)
>  #define BAUD_ALLOW_MIX(baud)	((baud) - (baud) * 3 / 100)
>  
> +/* struct mtk_serial_priv -	Structure holding all information used by the
> + *				driver
> + * @regs:			Register base of the serial port
> + * @clk:			The baud clock device
> + * @fixed_clk_rate:		Fallback fixed baud clock rate if baud clock
> + *				device is not specified
> + * @force_highspeed:		Force using high-speed mode
> + */
>  struct mtk_serial_priv {
>  	struct mtk_serial_regs __iomem *regs;
> -	u32 clock;
> +	struct clk clk;
> +	u32 fixed_clk_rate;
>  	bool force_highspeed;
>  };
>  
> -static void _mtk_serial_setbrg(struct mtk_serial_priv *priv, int baud)
> +static void _mtk_serial_setbrg(struct mtk_serial_priv *priv, int baud,
> +			       uint clk_rate)
>  {
>  	u32 quot, realbaud, samplecount = 1;
>  
>  	/* Special case for low baud clock */
> -	if (baud <= 115200 && priv->clock <= 12000000) {
> +	if (baud <= 115200 && clk_rate == 12000000) {
>  		writel(3, &priv->regs->highspeed);
>  
> -		quot = DIV_ROUND_CLOSEST(priv->clock, 256 * baud);
> +		quot = DIV_ROUND_CLOSEST(clk_rate, 256 * baud);
>  		if (quot == 0)
>  			quot = 1;
>  
> -		samplecount = DIV_ROUND_CLOSEST(priv->clock, quot * baud);
> +		samplecount = DIV_ROUND_CLOSEST(clk_rate, quot * baud);
>  
> -		realbaud = priv->clock / samplecount / quot;
> +		realbaud = clk_rate / samplecount / quot;
>  		if (realbaud > BAUD_ALLOW_MAX(baud) ||
>  		    realbaud < BAUD_ALLOW_MIX(baud)) {
>  			pr_info("baud %d can't be handled\n", baud);
> @@ -104,7 +115,7 @@ static void _mtk_serial_setbrg(struct mtk_serial_priv *priv, int baud)
>  
>  	if (baud <= 115200) {
>  		writel(0, &priv->regs->highspeed);
> -		quot = DIV_ROUND_CLOSEST(priv->clock, 16 * baud);
> +		quot = DIV_ROUND_CLOSEST(clk_rate, 16 * baud);
>  	} else if (baud <= 576000) {
>  		writel(2, &priv->regs->highspeed);
>  
> @@ -112,13 +123,13 @@ static void _mtk_serial_setbrg(struct mtk_serial_priv *priv, int baud)
>  		if ((baud == 500000) || (baud == 576000))
>  			baud = 460800;
>  
> -		quot = DIV_ROUND_UP(priv->clock, 4 * baud);
> +		quot = DIV_ROUND_UP(clk_rate, 4 * baud);
>  	} else {
>  use_hs3:
>  		writel(3, &priv->regs->highspeed);
>  
> -		quot = DIV_ROUND_UP(priv->clock, 256 * baud);
> -		samplecount = DIV_ROUND_CLOSEST(priv->clock, quot * baud);
> +		quot = DIV_ROUND_UP(clk_rate, 256 * baud);
> +		samplecount = DIV_ROUND_CLOSEST(clk_rate, quot * baud);
>  	}
>  
>  set_baud:
> @@ -167,8 +178,13 @@ static int _mtk_serial_pending(struct mtk_serial_priv *priv, bool input)
>  static int mtk_serial_setbrg(struct udevice *dev, int baudrate)
>  {
>  	struct mtk_serial_priv *priv = dev_get_priv(dev);
> +	u32 clk_rate;
> +
> +	clk_rate = clk_get_rate(&priv->clk);
> +	if (IS_ERR_VALUE(clk_rate) || clk_rate == 0)
> +		clk_rate = priv->fixed_clk_rate;
>  
> -	_mtk_serial_setbrg(priv, baudrate);
> +	_mtk_serial_setbrg(priv, baudrate, clk_rate);
>  
>  	return 0;
>  }
> @@ -211,7 +227,6 @@ static int mtk_serial_of_to_plat(struct udevice *dev)
>  {
>  	struct mtk_serial_priv *priv = dev_get_priv(dev);
>  	fdt_addr_t addr;
> -	struct clk clk;
>  	int err;
>  
>  	addr = dev_read_addr(dev);
> @@ -220,22 +235,19 @@ static int mtk_serial_of_to_plat(struct udevice *dev)
>  
>  	priv->regs = map_physmem(addr, 0, MAP_NOCACHE);
>  
> -	err = clk_get_by_index(dev, 0, &clk);
> -	if (!err) {
> -		err = clk_get_rate(&clk);
> -		if (!IS_ERR_VALUE(err))
> -			priv->clock = err;
> -	} else if (err != -ENOENT && err != -ENODEV && err != -ENOSYS) {
> -		debug("mtk_serial: failed to get clock\n");
> -		return err;
> -	}
> -
> -	if (!priv->clock)
> -		priv->clock = dev_read_u32_default(dev, "clock-frequency", 0);
> -
> -	if (!priv->clock) {
> -		debug("mtk_serial: clock not defined\n");
> -		return -EINVAL;
> +	err = clk_get_by_index(dev, 0, &priv->clk);
> +	if (err) {
> +		err = dev_read_u32(dev, "clock-frequency", &priv->fixed_clk_rate);
> +		if (err) {
> +			dev_err(dev, "baud clock not defined\n");
> +			return -EINVAL;
> +		}
> +	} else {
> +		err = clk_get_rate(&priv->clk);
> +		if (IS_ERR_VALUE(err)) {
> +			dev_err(dev, "invalid baud clock\n");
> +			return -EINVAL;
> +		}
>  	}
>  
>  	priv->force_highspeed = dev_read_bool(dev, "mediatek,force-highspeed");
> @@ -273,7 +285,7 @@ DECLARE_GLOBAL_DATA_PTR;
>  #define DECLARE_HSUART_PRIV(port) \
>  	static struct mtk_serial_priv mtk_hsuart##port = { \
>  	.regs = (struct mtk_serial_regs *)CONFIG_SYS_NS16550_COM##port, \
> -	.clock = CONFIG_SYS_NS16550_CLK \
> +	.fixed_clk_rate = CONFIG_SYS_NS16550_CLK \
>  };
>  
>  #define DECLARE_HSUART_FUNCTIONS(port) \
> @@ -282,12 +294,14 @@ DECLARE_GLOBAL_DATA_PTR;
>  		writel(0, &mtk_hsuart##port.regs->ier); \
>  		writel(UART_MCRVAL, &mtk_hsuart##port.regs->mcr); \
>  		writel(UART_FCRVAL, &mtk_hsuart##port.regs->fcr); \
> -		_mtk_serial_setbrg(&mtk_hsuart##port, gd->baudrate); \
> +		_mtk_serial_setbrg(&mtk_hsuart##port, gd->baudrate, \
> +				   mtk_hsuart##port.fixed_clk_rate); \
>  		return 0 ; \
>  	} \
>  	static void mtk_serial##port##_setbrg(void) \
>  	{ \
> -		_mtk_serial_setbrg(&mtk_hsuart##port, gd->baudrate); \
> +		_mtk_serial_setbrg(&mtk_hsuart##port, gd->baudrate, \
> +				   mtk_hsuart##port.fixed_clk_rate); \
>  	} \
>  	static int mtk_serial##port##_getc(void) \
>  	{ \
> @@ -427,13 +441,13 @@ static inline void _debug_uart_init(void)
>  	struct mtk_serial_priv priv;
>  
>  	priv.regs = (void *) CONFIG_VAL(DEBUG_UART_BASE);
> -	priv.clock = CONFIG_DEBUG_UART_CLOCK;
> +	priv.fixed_clk_rate = CONFIG_DEBUG_UART_CLOCK;
>  
>  	writel(0, &priv.regs->ier);
>  	writel(UART_MCRVAL, &priv.regs->mcr);
>  	writel(UART_FCRVAL, &priv.regs->fcr);
>  
> -	_mtk_serial_setbrg(&priv, CONFIG_BAUDRATE);
> +	_mtk_serial_setbrg(&priv, CONFIG_BAUDRATE, priv.fixed_clk_rate);
>  }
>  
>  static inline void _debug_uart_putc(int ch)
> -- 
> 2.17.1
> 

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

* Re: [PATCH v2 11/32] arm: dts: mt7622: force high-speed mode for uart
  2022-08-31 11:04 ` [PATCH v2 11/32] arm: dts: mt7622: force high-speed mode for uart Weijie Gao
@ 2022-09-01  0:23   ` Daniel Golle
  0 siblings, 0 replies; 60+ messages in thread
From: Daniel Golle @ 2022-09-01  0:23 UTC (permalink / raw)
  To: Weijie Gao; +Cc: u-boot, GSS_MTK_Uboot_upstream

On Wed, Aug 31, 2022 at 07:04:34PM +0800, Weijie Gao wrote:
> The input clock for uart is too slow (25MHz) which introduces frequent data
> error on both receiving and transmitting even if the baudrate is 115200.
> 
> Using high-speed can significantly solve this issue.

Tested on Bananapi BPi-R64 (MT7622).
Fixes unstable console issues previously observed on MT7622 systems.

Tested-by: Daniel Golle <daniel@makrotopia.org>

> 
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
> ---
> v2 changes: none
> ---
>  arch/arm/dts/mt7622.dtsi | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/arch/arm/dts/mt7622.dtsi b/arch/arm/dts/mt7622.dtsi
> index 0127474c95..fb6c1b7154 100644
> --- a/arch/arm/dts/mt7622.dtsi
> +++ b/arch/arm/dts/mt7622.dtsi
> @@ -175,6 +175,7 @@
>  		status = "disabled";
>  		assigned-clocks = <&topckgen CLK_TOP_AXI_SEL>;
>  		assigned-clock-parents = <&topckgen CLK_TOP_SYSPLL1_D2>;
> +		mediatek,force-highspeed;
>  	};
>  
>  	mmc0: mmc@11230000 {
> -- 
> 2.17.1
> 

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

* Re: [PATCH v2 14/32] timer: mtk: add support for MediaTek MT7981/MT7986 SoCs
  2022-08-31 11:04 ` [PATCH v2 14/32] timer: mtk: add support for MediaTek MT7981/MT7986 SoCs Weijie Gao
@ 2022-09-01  0:24   ` Daniel Golle
  0 siblings, 0 replies; 60+ messages in thread
From: Daniel Golle @ 2022-09-01  0:24 UTC (permalink / raw)
  To: Weijie Gao; +Cc: u-boot, GSS_MTK_Uboot_upstream

On Wed, Aug 31, 2022 at 07:04:40PM +0800, Weijie Gao wrote:
> This patch add general-purpose timer support for MediaTek MT7981/MT7986.
> These two SoCs uses a newer version of timer with its register definition
> slightly changed.
> 

Tested on Bananapi BPi-R3 (MT7986A).

Tested-by: Daniel Golle <daniel@makrotopia.org>

> Reviewed-by: Simon Glass <sjg@chromium.org>
> Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
> ---
> v2 changes: none
> ---
>  drivers/timer/mtk_timer.c | 59 ++++++++++++++++++++++++---------------
>  1 file changed, 37 insertions(+), 22 deletions(-)
> 
> diff --git a/drivers/timer/mtk_timer.c b/drivers/timer/mtk_timer.c
> index f6b97f868c..223e63f6c1 100644
> --- a/drivers/timer/mtk_timer.c
> +++ b/drivers/timer/mtk_timer.c
> @@ -13,24 +13,32 @@
>  #include <asm/io.h>
>  #include <linux/bitops.h>
>  
> -#define MTK_GPT4_CTRL	0x40
> -#define MTK_GPT4_CLK	0x44
> -#define MTK_GPT4_CNT	0x48
> +#define MTK_GPT4_OFFSET_V1	0x40
> +#define MTK_GPT4_OFFSET_V2	0x80
>  
> -#define GPT4_ENABLE	BIT(0)
> -#define GPT4_CLEAR	BIT(1)
> -#define GPT4_FREERUN	GENMASK(5, 4)
> -#define GPT4_CLK_SYS	0x0
> -#define GPT4_CLK_DIV1	0x0
> +#define MTK_GPT_CON		0x0
> +#define MTK_GPT_V1_CLK		0x4
> +#define MTK_GPT_CNT		0x8
> +
> +#define GPT_ENABLE		BIT(0)
> +#define GPT_CLEAR		BIT(1)
> +#define GPT_V1_FREERUN		GENMASK(5, 4)
> +#define GPT_V2_FREERUN		GENMASK(6, 5)
> +
> +enum mtk_gpt_ver {
> +	MTK_GPT_V1,
> +	MTK_GPT_V2
> +};
>  
>  struct mtk_timer_priv {
>  	void __iomem *base;
> +	unsigned int gpt4_offset;
>  };
>  
>  static u64 mtk_timer_get_count(struct udevice *dev)
>  {
>  	struct mtk_timer_priv *priv = dev_get_priv(dev);
> -	u32 val = readl(priv->base + MTK_GPT4_CNT);
> +	u32 val = readl(priv->base + priv->gpt4_offset + MTK_GPT_CNT);
>  
>  	return timer_conv_64(val);
>  }
> @@ -40,12 +48,27 @@ static int mtk_timer_probe(struct udevice *dev)
>  	struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
>  	struct mtk_timer_priv *priv = dev_get_priv(dev);
>  	struct clk clk, parent;
> -	int ret;
> +	int ret, gpt_ver;
>  
>  	priv->base = dev_read_addr_ptr(dev);
> +	gpt_ver = dev_get_driver_data(dev);
> +
>  	if (!priv->base)
>  		return -ENOENT;
>  
> +	if (gpt_ver == MTK_GPT_V2) {
> +		priv->gpt4_offset = MTK_GPT4_OFFSET_V2;
> +
> +		writel(GPT_V2_FREERUN | GPT_CLEAR | GPT_ENABLE,
> +		       priv->base + priv->gpt4_offset + MTK_GPT_CON);
> +	} else {
> +		priv->gpt4_offset = MTK_GPT4_OFFSET_V1;
> +
> +		writel(GPT_V1_FREERUN | GPT_CLEAR | GPT_ENABLE,
> +		       priv->base + priv->gpt4_offset + MTK_GPT_CON);
> +		writel(0, priv->base + priv->gpt4_offset + MTK_GPT_V1_CLK);
> +	}
> +
>  	ret = clk_get_by_index(dev, 0, &clk);
>  	if (ret)
>  		return ret;
> @@ -61,16 +84,6 @@ static int mtk_timer_probe(struct udevice *dev)
>  	if (!uc_priv->clock_rate)
>  		return -EINVAL;
>  
> -	/*
> -	 * Initialize the timer:
> -	 * 1. set clock source to system clock with clock divider setting to 1
> -	 * 2. set timer mode to free running
> -	 * 3. reset timer counter to 0 then enable the timer
> -	 */
> -	writel(GPT4_CLK_SYS | GPT4_CLK_DIV1, priv->base + MTK_GPT4_CLK);
> -	writel(GPT4_FREERUN | GPT4_CLEAR | GPT4_ENABLE,
> -	       priv->base + MTK_GPT4_CTRL);
> -
>  	return 0;
>  }
>  
> @@ -79,8 +92,10 @@ static const struct timer_ops mtk_timer_ops = {
>  };
>  
>  static const struct udevice_id mtk_timer_ids[] = {
> -	{ .compatible = "mediatek,timer" },
> -	{ .compatible = "mediatek,mt6577-timer" },
> +	{ .compatible = "mediatek,timer", .data = MTK_GPT_V1 },
> +	{ .compatible = "mediatek,mt6577-timer", .data = MTK_GPT_V1 },
> +	{ .compatible = "mediatek,mt7981-timer", .data = MTK_GPT_V2 },
> +	{ .compatible = "mediatek,mt7986-timer", .data = MTK_GPT_V2 },
>  	{ }
>  };
>  
> -- 
> 2.17.1
> 

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

* Re: [PATCH v2 15/32] watchdog: mediatek: add support for MediaTek MT7986 SoC
  2022-08-31 11:04 ` [PATCH v2 15/32] watchdog: mediatek: add support for MediaTek MT7986 SoC Weijie Gao
@ 2022-09-01  0:25   ` Daniel Golle
  0 siblings, 0 replies; 60+ messages in thread
From: Daniel Golle @ 2022-09-01  0:25 UTC (permalink / raw)
  To: Weijie Gao; +Cc: u-boot, GSS_MTK_Uboot_upstream, Stefan Roese

On Wed, Aug 31, 2022 at 07:04:42PM +0800, Weijie Gao wrote:
> Add watchdog support for MediaTek MT7986 SoC

Tested on Bananapi BPi-R3 (MT7986A).

Tested-by: Daniel Golle <daniel@makrotopia.org>

> 
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
> ---
> v2 changes: none
> ---
>  drivers/watchdog/mtk_wdt.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/watchdog/mtk_wdt.c b/drivers/watchdog/mtk_wdt.c
> index b098b2e3cf..368b36849c 100644
> --- a/drivers/watchdog/mtk_wdt.c
> +++ b/drivers/watchdog/mtk_wdt.c
> @@ -145,6 +145,7 @@ static const struct wdt_ops mtk_wdt_ops = {
>  static const struct udevice_id mtk_wdt_ids[] = {
>  	{ .compatible = "mediatek,wdt"},
>  	{ .compatible = "mediatek,mt6589-wdt"},
> +	{ .compatible = "mediatek,mt7986-wdt" },
>  	{}
>  };
>  
> -- 
> 2.17.1
> 

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

* Re: [PATCH v2 16/32] spi: add support for MediaTek spi-mem controller
  2022-08-31 11:04 ` [PATCH v2 16/32] spi: add support for MediaTek spi-mem controller Weijie Gao
@ 2022-09-01  0:25   ` Daniel Golle
  0 siblings, 0 replies; 60+ messages in thread
From: Daniel Golle @ 2022-09-01  0:25 UTC (permalink / raw)
  To: Weijie Gao; +Cc: u-boot, GSS_MTK_Uboot_upstream, Jagan Teki, SkyLake . Huang

On Wed, Aug 31, 2022 at 07:04:45PM +0800, Weijie Gao wrote:
> This patch adds support for spi-mem controller found on newer MediaTek SoCs
> This controller supports Single/Dual/Quad SPI mode.

Tested on Bananapi BPi-R3 (MT7986A).

Tested-by: Daniel Golle <daniel@makrotopia.org>

> 
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
> ---
> v2 changes:
>   Remove unused code
>   Fix coding style
>   Add description for struct fields
> ---
>  drivers/spi/Kconfig    |   8 +
>  drivers/spi/Makefile   |   1 +
>  drivers/spi/mtk_spim.c | 701 +++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 710 insertions(+)
>  create mode 100644 drivers/spi/mtk_spim.c
> 
> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
> index 75b794548b..7e72ab9c24 100644
> --- a/drivers/spi/Kconfig
> +++ b/drivers/spi/Kconfig
> @@ -276,6 +276,14 @@ config MTK_SNFI_SPI
>  	  used to access SPI memory devices like SPI-NOR or SPI-NAND on
>  	  platforms embedding this IP core, like MT7622/M7629.
>  
> +config MTK_SPIM
> +	bool "Mediatek SPI-MEM master controller driver"
> +	depends on SPI_MEM
> +	help
> +	  Enable MediaTek SPI-MEM master controller driver. This driver mainly
> +	  supports SPI flashes. You can use single, dual or quad mode
> +	  transmission on this controller.
> +
>  config MVEBU_A3700_SPI
>  	bool "Marvell Armada 3700 SPI driver"
>  	select CLK_ARMADA_3720
> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
> index 4de77c260a..309f6b5328 100644
> --- a/drivers/spi/Makefile
> +++ b/drivers/spi/Makefile
> @@ -43,6 +43,7 @@ obj-$(CONFIG_MPC8XX_SPI) += mpc8xx_spi.o
>  obj-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o
>  obj-$(CONFIG_MTK_SNFI_SPI) += mtk_snfi_spi.o
>  obj-$(CONFIG_MTK_SNOR) += mtk_snor.o
> +obj-$(CONFIG_MTK_SPIM) += mtk_spim.o
>  obj-$(CONFIG_MT7620_SPI) += mt7620_spi.o
>  obj-$(CONFIG_MT7621_SPI) += mt7621_spi.o
>  obj-$(CONFIG_MSCC_BB_SPI) += mscc_bb_spi.o
> diff --git a/drivers/spi/mtk_spim.c b/drivers/spi/mtk_spim.c
> new file mode 100644
> index 0000000000..b45ef529a5
> --- /dev/null
> +++ b/drivers/spi/mtk_spim.c
> @@ -0,0 +1,701 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2022 MediaTek Inc. All Rights Reserved.
> + *
> + * Author: SkyLake.Huang <skylake.huang@mediatek.com>
> + */
> +
> +#include <clk.h>
> +#include <cpu_func.h>
> +#include <div64.h>
> +#include <dm.h>
> +#include <spi.h>
> +#include <spi-mem.h>
> +#include <stdbool.h>
> +#include <watchdog.h>
> +#include <dm/device.h>
> +#include <dm/device_compat.h>
> +#include <dm/devres.h>
> +#include <dm/pinctrl.h>
> +#include <linux/bitops.h>
> +#include <linux/completion.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/io.h>
> +#include <linux/iopoll.h>
> +
> +#define SPI_CFG0_REG				0x0000
> +#define SPI_CFG1_REG				0x0004
> +#define SPI_TX_SRC_REG				0x0008
> +#define SPI_RX_DST_REG				0x000c
> +#define SPI_TX_DATA_REG				0x0010
> +#define SPI_RX_DATA_REG				0x0014
> +#define SPI_CMD_REG				0x0018
> +#define SPI_IRQ_REG				0x001c
> +#define SPI_STATUS_REG				0x0020
> +#define SPI_PAD_SEL_REG				0x0024
> +#define SPI_CFG2_REG				0x0028
> +#define SPI_TX_SRC_REG_64			0x002c
> +#define SPI_RX_DST_REG_64			0x0030
> +#define SPI_CFG3_IPM_REG			0x0040
> +
> +#define SPI_CFG0_SCK_HIGH_OFFSET		0
> +#define SPI_CFG0_SCK_LOW_OFFSET			8
> +#define SPI_CFG0_CS_HOLD_OFFSET			16
> +#define SPI_CFG0_CS_SETUP_OFFSET		24
> +#define SPI_ADJUST_CFG0_CS_HOLD_OFFSET		0
> +#define SPI_ADJUST_CFG0_CS_SETUP_OFFSET		16
> +
> +#define SPI_CFG1_CS_IDLE_OFFSET			0
> +#define SPI_CFG1_PACKET_LOOP_OFFSET		8
> +#define SPI_CFG1_PACKET_LENGTH_OFFSET		16
> +#define SPI_CFG1_GET_TICKDLY_OFFSET		29
> +
> +#define SPI_CFG1_GET_TICKDLY_MASK		GENMASK(31, 29)
> +#define SPI_CFG1_CS_IDLE_MASK			0xff
> +#define SPI_CFG1_PACKET_LOOP_MASK		0xff00
> +#define SPI_CFG1_PACKET_LENGTH_MASK		0x3ff0000
> +#define SPI_CFG1_IPM_PACKET_LENGTH_MASK		GENMASK(31, 16)
> +#define SPI_CFG2_SCK_HIGH_OFFSET		0
> +#define SPI_CFG2_SCK_LOW_OFFSET			16
> +#define SPI_CFG2_SCK_HIGH_MASK			GENMASK(15, 0)
> +#define SPI_CFG2_SCK_LOW_MASK			GENMASK(31, 16)
> +
> +#define SPI_CMD_ACT				BIT(0)
> +#define SPI_CMD_RESUME				BIT(1)
> +#define SPI_CMD_RST				BIT(2)
> +#define SPI_CMD_PAUSE_EN			BIT(4)
> +#define SPI_CMD_DEASSERT			BIT(5)
> +#define SPI_CMD_SAMPLE_SEL			BIT(6)
> +#define SPI_CMD_CS_POL				BIT(7)
> +#define SPI_CMD_CPHA				BIT(8)
> +#define SPI_CMD_CPOL				BIT(9)
> +#define SPI_CMD_RX_DMA				BIT(10)
> +#define SPI_CMD_TX_DMA				BIT(11)
> +#define SPI_CMD_TXMSBF				BIT(12)
> +#define SPI_CMD_RXMSBF				BIT(13)
> +#define SPI_CMD_RX_ENDIAN			BIT(14)
> +#define SPI_CMD_TX_ENDIAN			BIT(15)
> +#define SPI_CMD_FINISH_IE			BIT(16)
> +#define SPI_CMD_PAUSE_IE			BIT(17)
> +#define SPI_CMD_IPM_NONIDLE_MODE		BIT(19)
> +#define SPI_CMD_IPM_SPIM_LOOP			BIT(21)
> +#define SPI_CMD_IPM_GET_TICKDLY_OFFSET		22
> +
> +#define SPI_CMD_IPM_GET_TICKDLY_MASK		GENMASK(24, 22)
> +
> +#define PIN_MODE_CFG(x)				((x) / 2)
> +
> +#define SPI_CFG3_IPM_PIN_MODE_OFFSET		0
> +#define SPI_CFG3_IPM_HALF_DUPLEX_DIR		BIT(2)
> +#define SPI_CFG3_IPM_HALF_DUPLEX_EN		BIT(3)
> +#define SPI_CFG3_IPM_XMODE_EN			BIT(4)
> +#define SPI_CFG3_IPM_NODATA_FLAG		BIT(5)
> +#define SPI_CFG3_IPM_CMD_BYTELEN_OFFSET		8
> +#define SPI_CFG3_IPM_ADDR_BYTELEN_OFFSET	12
> +#define SPI_CFG3_IPM_DUMMY_BYTELEN_OFFSET	16
> +
> +#define SPI_CFG3_IPM_CMD_PIN_MODE_MASK		GENMASK(1, 0)
> +#define SPI_CFG3_IPM_CMD_BYTELEN_MASK		GENMASK(11, 8)
> +#define SPI_CFG3_IPM_ADDR_BYTELEN_MASK		GENMASK(15, 12)
> +#define SPI_CFG3_IPM_DUMMY_BYTELEN_MASK		GENMASK(19, 16)
> +
> +#define MT8173_SPI_MAX_PAD_SEL			3
> +
> +#define MTK_SPI_PAUSE_INT_STATUS		0x2
> +
> +#define MTK_SPI_IDLE				0
> +#define MTK_SPI_PAUSED				1
> +
> +#define MTK_SPI_MAX_FIFO_SIZE			32U
> +#define MTK_SPI_PACKET_SIZE			1024
> +#define MTK_SPI_IPM_PACKET_SIZE			SZ_64K
> +#define MTK_SPI_IPM_PACKET_LOOP			SZ_256
> +
> +#define MTK_SPI_32BITS_MASK			0xffffffff
> +
> +#define DMA_ADDR_EXT_BITS			36
> +#define DMA_ADDR_DEF_BITS			32
> +
> +#define CLK_TO_US(freq, clkcnt) DIV_ROUND_UP((clkcnt), (freq) / 1000000)
> +
> +/* struct mtk_spim_capability
> + * @enhance_timing:	Some IC design adjust cfg register to enhance time accuracy
> + * @dma_ext:		Some IC support DMA addr extension
> + * @ipm_design:		The IPM IP design improves some features, and supports dual/quad mode
> + * @support_quad:	Whether quad mode is supported
> + */
> +struct mtk_spim_capability {
> +	bool enhance_timing;
> +	bool dma_ext;
> +	bool ipm_design;
> +	bool support_quad;
> +};
> +
> +/* struct mtk_spim_priv
> + * @base:		Base address of the spi controller
> + * @state:		Controller state
> + * @sel_clk:		Pad clock
> + * @spi_clk:		Core clock
> + * @xfer_len:		Current length of data for transfer
> + * @hw_cap:		Controller capabilities
> + * @tick_dly:		Used to postpone SPI sampling time
> + * @sample_sel:		Sample edge of MISO
> + * @dev:		udevice of this spi controller
> + * @tx_dma:		Tx DMA address
> + * @rx_dma:		Rx DMA address
> + */
> +struct mtk_spim_priv {
> +	void __iomem *base;
> +	u32 state;
> +	struct clk sel_clk, spi_clk;
> +	u32 xfer_len;
> +	struct mtk_spim_capability hw_cap;
> +	u32 tick_dly;
> +	u32 sample_sel;
> +
> +	struct device *dev;
> +	dma_addr_t tx_dma;
> +	dma_addr_t rx_dma;
> +};
> +
> +static void mtk_spim_reset(struct mtk_spim_priv *priv)
> +{
> +	/* set the software reset bit in SPI_CMD_REG. */
> +	setbits_le32(priv->base + SPI_CMD_REG, SPI_CMD_RST);
> +	clrbits_le32(priv->base + SPI_CMD_REG, SPI_CMD_RST);
> +}
> +
> +static int mtk_spim_hw_init(struct spi_slave *slave)
> +{
> +	struct udevice *bus = dev_get_parent(slave->dev);
> +	struct mtk_spim_priv *priv = dev_get_priv(bus);
> +	u16 cpha, cpol;
> +	u32 reg_val;
> +
> +	cpha = slave->mode & SPI_CPHA ? 1 : 0;
> +	cpol = slave->mode & SPI_CPOL ? 1 : 0;
> +
> +	if (priv->hw_cap.enhance_timing) {
> +		if (priv->hw_cap.ipm_design) {
> +			/* CFG3 reg only used for spi-mem,
> +			 * here write to default value
> +			 */
> +			writel(0x0, priv->base + SPI_CFG3_IPM_REG);
> +			clrsetbits_le32(priv->base + SPI_CMD_REG,
> +					SPI_CMD_IPM_GET_TICKDLY_MASK,
> +					priv->tick_dly <<
> +					SPI_CMD_IPM_GET_TICKDLY_OFFSET);
> +		} else {
> +			clrsetbits_le32(priv->base + SPI_CFG1_REG,
> +					SPI_CFG1_GET_TICKDLY_MASK,
> +					priv->tick_dly <<
> +					SPI_CFG1_GET_TICKDLY_OFFSET);
> +		}
> +	}
> +
> +	reg_val = readl(priv->base + SPI_CMD_REG);
> +	if (priv->hw_cap.ipm_design) {
> +		/* SPI transfer without idle time until packet length done */
> +		reg_val |= SPI_CMD_IPM_NONIDLE_MODE;
> +		if (slave->mode & SPI_LOOP)
> +			reg_val |= SPI_CMD_IPM_SPIM_LOOP;
> +		else
> +			reg_val &= ~SPI_CMD_IPM_SPIM_LOOP;
> +	}
> +
> +	if (cpha)
> +		reg_val |= SPI_CMD_CPHA;
> +	else
> +		reg_val &= ~SPI_CMD_CPHA;
> +	if (cpol)
> +		reg_val |= SPI_CMD_CPOL;
> +	else
> +		reg_val &= ~SPI_CMD_CPOL;
> +
> +	/* set the mlsbx and mlsbtx */
> +	if (slave->mode & SPI_LSB_FIRST) {
> +		reg_val &= ~SPI_CMD_TXMSBF;
> +		reg_val &= ~SPI_CMD_RXMSBF;
> +	} else {
> +		reg_val |= SPI_CMD_TXMSBF;
> +		reg_val |= SPI_CMD_RXMSBF;
> +	}
> +
> +	/* do not reverse tx/rx endian */
> +	reg_val &= ~SPI_CMD_TX_ENDIAN;
> +	reg_val &= ~SPI_CMD_RX_ENDIAN;
> +
> +	if (priv->hw_cap.enhance_timing) {
> +		/* set CS polarity */
> +		if (slave->mode & SPI_CS_HIGH)
> +			reg_val |= SPI_CMD_CS_POL;
> +		else
> +			reg_val &= ~SPI_CMD_CS_POL;
> +
> +		if (priv->sample_sel)
> +			reg_val |= SPI_CMD_SAMPLE_SEL;
> +		else
> +			reg_val &= ~SPI_CMD_SAMPLE_SEL;
> +	}
> +
> +	/* disable dma mode */
> +	reg_val &= ~(SPI_CMD_TX_DMA | SPI_CMD_RX_DMA);
> +
> +	/* disable deassert mode */
> +	reg_val &= ~SPI_CMD_DEASSERT;
> +
> +	writel(reg_val, priv->base + SPI_CMD_REG);
> +
> +	return 0;
> +}
> +
> +static void mtk_spim_prepare_transfer(struct mtk_spim_priv *priv,
> +				      u32 speed_hz)
> +{
> +	u32 spi_clk_hz, div, sck_time, cs_time, reg_val;
> +
> +	spi_clk_hz = clk_get_rate(&priv->spi_clk);
> +	if (speed_hz <= spi_clk_hz / 4)
> +		div = DIV_ROUND_UP(spi_clk_hz, speed_hz);
> +	else
> +		div = 4;
> +
> +	sck_time = (div + 1) / 2;
> +	cs_time = sck_time * 2;
> +
> +	if (priv->hw_cap.enhance_timing) {
> +		reg_val = ((sck_time - 1) & 0xffff)
> +			   << SPI_CFG2_SCK_HIGH_OFFSET;
> +		reg_val |= ((sck_time - 1) & 0xffff)
> +			   << SPI_CFG2_SCK_LOW_OFFSET;
> +		writel(reg_val, priv->base + SPI_CFG2_REG);
> +
> +		reg_val = ((cs_time - 1) & 0xffff)
> +			   << SPI_ADJUST_CFG0_CS_HOLD_OFFSET;
> +		reg_val |= ((cs_time - 1) & 0xffff)
> +			   << SPI_ADJUST_CFG0_CS_SETUP_OFFSET;
> +		writel(reg_val, priv->base + SPI_CFG0_REG);
> +	} else {
> +		reg_val = ((sck_time - 1) & 0xff)
> +			   << SPI_CFG0_SCK_HIGH_OFFSET;
> +		reg_val |= ((sck_time - 1) & 0xff) << SPI_CFG0_SCK_LOW_OFFSET;
> +		reg_val |= ((cs_time - 1) & 0xff) << SPI_CFG0_CS_HOLD_OFFSET;
> +		reg_val |= ((cs_time - 1) & 0xff) << SPI_CFG0_CS_SETUP_OFFSET;
> +		writel(reg_val, priv->base + SPI_CFG0_REG);
> +	}
> +
> +	reg_val = readl(priv->base + SPI_CFG1_REG);
> +	reg_val &= ~SPI_CFG1_CS_IDLE_MASK;
> +	reg_val |= ((cs_time - 1) & 0xff) << SPI_CFG1_CS_IDLE_OFFSET;
> +	writel(reg_val, priv->base + SPI_CFG1_REG);
> +}
> +
> +/**
> + * mtk_spim_setup_packet() - setup packet format.
> + * @priv:	controller priv
> + *
> + * This controller sents/receives data in packets. The packet size is
> + * configurable.
> + *
> + * This function calculates the maximum packet size available for current
> + * data, and calculates the number of packets required to sent/receive data
> + * as much as possible.
> + */
> +static void mtk_spim_setup_packet(struct mtk_spim_priv *priv)
> +{
> +	u32 packet_size, packet_loop, reg_val;
> +
> +	/* Calculate maximum packet size */
> +	if (priv->hw_cap.ipm_design)
> +		packet_size = min_t(u32,
> +				    priv->xfer_len,
> +				    MTK_SPI_IPM_PACKET_SIZE);
> +	else
> +		packet_size = min_t(u32,
> +				    priv->xfer_len,
> +				    MTK_SPI_PACKET_SIZE);
> +
> +	/* Calculates number of packets to sent/receive */
> +	packet_loop = priv->xfer_len / packet_size;
> +
> +	reg_val = readl(priv->base + SPI_CFG1_REG);
> +	if (priv->hw_cap.ipm_design)
> +		reg_val &= ~SPI_CFG1_IPM_PACKET_LENGTH_MASK;
> +	else
> +		reg_val &= ~SPI_CFG1_PACKET_LENGTH_MASK;
> +
> +	reg_val |= (packet_size - 1) << SPI_CFG1_PACKET_LENGTH_OFFSET;
> +
> +	reg_val &= ~SPI_CFG1_PACKET_LOOP_MASK;
> +
> +	reg_val |= (packet_loop - 1) << SPI_CFG1_PACKET_LOOP_OFFSET;
> +
> +	writel(reg_val, priv->base + SPI_CFG1_REG);
> +}
> +
> +static void mtk_spim_enable_transfer(struct mtk_spim_priv *priv)
> +{
> +	u32 cmd;
> +
> +	cmd = readl(priv->base + SPI_CMD_REG);
> +	if (priv->state == MTK_SPI_IDLE)
> +		cmd |= SPI_CMD_ACT;
> +	else
> +		cmd |= SPI_CMD_RESUME;
> +	writel(cmd, priv->base + SPI_CMD_REG);
> +}
> +
> +static bool mtk_spim_supports_op(struct spi_slave *slave,
> +				 const struct spi_mem_op *op)
> +{
> +	struct udevice *bus = dev_get_parent(slave->dev);
> +	struct mtk_spim_priv *priv = dev_get_priv(bus);
> +
> +	if (op->cmd.buswidth == 0 || op->cmd.buswidth > 4 ||
> +	    op->addr.buswidth > 4 || op->dummy.buswidth > 4 ||
> +	    op->data.buswidth > 4)
> +		return false;
> +
> +	if (!priv->hw_cap.support_quad && (op->cmd.buswidth > 2 ||
> +	    op->addr.buswidth > 2 || op->dummy.buswidth > 2 ||
> +	    op->data.buswidth > 2))
> +		return false;
> +
> +	if (op->addr.nbytes && op->dummy.nbytes &&
> +	    op->addr.buswidth != op->dummy.buswidth)
> +		return false;
> +
> +	if (op->addr.nbytes + op->dummy.nbytes > 16)
> +		return false;
> +
> +	if (op->data.nbytes > MTK_SPI_IPM_PACKET_SIZE) {
> +		if (op->data.nbytes / MTK_SPI_IPM_PACKET_SIZE >
> +		    MTK_SPI_IPM_PACKET_LOOP ||
> +		    op->data.nbytes % MTK_SPI_IPM_PACKET_SIZE != 0)
> +			return false;
> +	}
> +
> +	return true;
> +}
> +
> +static void mtk_spim_setup_dma_xfer(struct mtk_spim_priv *priv,
> +				    const struct spi_mem_op *op)
> +{
> +	writel((u32)(priv->tx_dma & MTK_SPI_32BITS_MASK),
> +	       priv->base + SPI_TX_SRC_REG);
> +
> +	if (priv->hw_cap.dma_ext)
> +		writel((u32)(priv->tx_dma >> 32),
> +		       priv->base + SPI_TX_SRC_REG_64);
> +
> +	if (op->data.dir == SPI_MEM_DATA_IN) {
> +		writel((u32)(priv->rx_dma & MTK_SPI_32BITS_MASK),
> +		       priv->base + SPI_RX_DST_REG);
> +
> +		if (priv->hw_cap.dma_ext)
> +			writel((u32)(priv->rx_dma >> 32),
> +			       priv->base + SPI_RX_DST_REG_64);
> +	}
> +}
> +
> +static int mtk_spim_transfer_wait(struct spi_slave *slave,
> +				  const struct spi_mem_op *op)
> +{
> +	struct udevice *bus = dev_get_parent(slave->dev);
> +	struct mtk_spim_priv *priv = dev_get_priv(bus);
> +	u32 sck_l, sck_h, spi_bus_clk, clk_count, reg;
> +	ulong us = 1;
> +	int ret = 0;
> +
> +	if (op->data.dir == SPI_MEM_NO_DATA)
> +		clk_count = 32;
> +	else
> +		clk_count = op->data.nbytes;
> +
> +	spi_bus_clk = clk_get_rate(&priv->spi_clk);
> +	sck_l = readl(priv->base + SPI_CFG2_REG) >> SPI_CFG2_SCK_LOW_OFFSET;
> +	sck_h = readl(priv->base + SPI_CFG2_REG) & SPI_CFG2_SCK_HIGH_MASK;
> +	do_div(spi_bus_clk, sck_l + sck_h + 2);
> +
> +	us = CLK_TO_US(spi_bus_clk, clk_count * 8);
> +	us += 1000 * 1000; /* 1s tolerance */
> +
> +	if (us > UINT_MAX)
> +		us = UINT_MAX;
> +
> +	ret = readl_poll_timeout(priv->base + SPI_STATUS_REG, reg,
> +				 reg & 0x1, us);
> +	if (ret < 0) {
> +		dev_err(priv->dev, "transfer timeout, val: 0x%lx\n", us);
> +		return -ETIMEDOUT;
> +	}
> +
> +	return 0;
> +}
> +
> +static int mtk_spim_exec_op(struct spi_slave *slave,
> +			    const struct spi_mem_op *op)
> +{
> +	struct udevice *bus = dev_get_parent(slave->dev);
> +	struct mtk_spim_priv *priv = dev_get_priv(bus);
> +	u32 reg_val, nio = 1, tx_size;
> +	char *tx_tmp_buf;
> +	char *rx_tmp_buf;
> +	int i, ret = 0;
> +
> +	mtk_spim_reset(priv);
> +	mtk_spim_hw_init(slave);
> +	mtk_spim_prepare_transfer(priv, slave->max_hz);
> +
> +	reg_val = readl(priv->base + SPI_CFG3_IPM_REG);
> +	/* opcode byte len */
> +	reg_val &= ~SPI_CFG3_IPM_CMD_BYTELEN_MASK;
> +	reg_val |= 1 << SPI_CFG3_IPM_CMD_BYTELEN_OFFSET;
> +
> +	/* addr & dummy byte len */
> +	if (op->addr.nbytes || op->dummy.nbytes)
> +		reg_val |= (op->addr.nbytes + op->dummy.nbytes) <<
> +			    SPI_CFG3_IPM_ADDR_BYTELEN_OFFSET;
> +
> +	/* data byte len */
> +	if (!op->data.nbytes) {
> +		reg_val |= SPI_CFG3_IPM_NODATA_FLAG;
> +		writel(0, priv->base + SPI_CFG1_REG);
> +	} else {
> +		reg_val &= ~SPI_CFG3_IPM_NODATA_FLAG;
> +		priv->xfer_len = op->data.nbytes;
> +		mtk_spim_setup_packet(priv);
> +	}
> +
> +	if (op->addr.nbytes || op->dummy.nbytes) {
> +		if (op->addr.buswidth == 1 || op->dummy.buswidth == 1)
> +			reg_val |= SPI_CFG3_IPM_XMODE_EN;
> +		else
> +			reg_val &= ~SPI_CFG3_IPM_XMODE_EN;
> +	}
> +
> +	if (op->addr.buswidth == 2 ||
> +	    op->dummy.buswidth == 2 ||
> +	    op->data.buswidth == 2)
> +		nio = 2;
> +	else if (op->addr.buswidth == 4 ||
> +		 op->dummy.buswidth == 4 ||
> +		 op->data.buswidth == 4)
> +		nio = 4;
> +
> +	reg_val &= ~SPI_CFG3_IPM_CMD_PIN_MODE_MASK;
> +	reg_val |= PIN_MODE_CFG(nio) << SPI_CFG3_IPM_PIN_MODE_OFFSET;
> +
> +	reg_val |= SPI_CFG3_IPM_HALF_DUPLEX_EN;
> +	if (op->data.dir == SPI_MEM_DATA_IN)
> +		reg_val |= SPI_CFG3_IPM_HALF_DUPLEX_DIR;
> +	else
> +		reg_val &= ~SPI_CFG3_IPM_HALF_DUPLEX_DIR;
> +	writel(reg_val, priv->base + SPI_CFG3_IPM_REG);
> +
> +	tx_size = 1 + op->addr.nbytes + op->dummy.nbytes;
> +	if (op->data.dir == SPI_MEM_DATA_OUT)
> +		tx_size += op->data.nbytes;
> +
> +	tx_size = max(tx_size, (u32)32);
> +
> +	/* Fill up tx data */
> +	tx_tmp_buf = kzalloc(tx_size, GFP_KERNEL);
> +	if (!tx_tmp_buf) {
> +		ret = -ENOMEM;
> +		goto exit;
> +	}
> +
> +	tx_tmp_buf[0] = op->cmd.opcode;
> +
> +	if (op->addr.nbytes) {
> +		for (i = 0; i < op->addr.nbytes; i++)
> +			tx_tmp_buf[i + 1] = op->addr.val >>
> +					(8 * (op->addr.nbytes - i - 1));
> +	}
> +
> +	if (op->dummy.nbytes)
> +		memset(tx_tmp_buf + op->addr.nbytes + 1, 0xff,
> +		       op->dummy.nbytes);
> +
> +	if (op->data.nbytes && op->data.dir == SPI_MEM_DATA_OUT)
> +		memcpy(tx_tmp_buf + op->dummy.nbytes + op->addr.nbytes + 1,
> +		       op->data.buf.out, op->data.nbytes);
> +	/* Finish filling up tx data */
> +
> +	priv->tx_dma = dma_map_single(tx_tmp_buf, tx_size, DMA_TO_DEVICE);
> +	if (dma_mapping_error(priv->dev, priv->tx_dma)) {
> +		ret = -ENOMEM;
> +		goto tx_free;
> +	}
> +
> +	if (op->data.dir == SPI_MEM_DATA_IN) {
> +		if (!IS_ALIGNED((size_t)op->data.buf.in, 4)) {
> +			rx_tmp_buf = kzalloc(op->data.nbytes, GFP_KERNEL);
> +			if (!rx_tmp_buf) {
> +				ret = -ENOMEM;
> +				goto tx_unmap;
> +			}
> +		} else {
> +			rx_tmp_buf = op->data.buf.in;
> +		}
> +
> +		priv->rx_dma = dma_map_single(rx_tmp_buf, op->data.nbytes,
> +					      DMA_FROM_DEVICE);
> +		if (dma_mapping_error(priv->dev, priv->rx_dma)) {
> +			ret = -ENOMEM;
> +			goto rx_free;
> +		}
> +	}
> +
> +	reg_val = readl(priv->base + SPI_CMD_REG);
> +	reg_val |= SPI_CMD_TX_DMA;
> +	if (op->data.dir == SPI_MEM_DATA_IN)
> +		reg_val |= SPI_CMD_RX_DMA;
> +
> +	writel(reg_val, priv->base + SPI_CMD_REG);
> +
> +	mtk_spim_setup_dma_xfer(priv, op);
> +
> +	mtk_spim_enable_transfer(priv);
> +
> +	/* Wait for the interrupt. */
> +	ret = mtk_spim_transfer_wait(slave, op);
> +	if (ret)
> +		goto rx_unmap;
> +
> +	if (op->data.dir == SPI_MEM_DATA_IN &&
> +	    !IS_ALIGNED((size_t)op->data.buf.in, 4))
> +		memcpy(op->data.buf.in, rx_tmp_buf, op->data.nbytes);
> +
> +rx_unmap:
> +	/* spi disable dma */
> +	reg_val = readl(priv->base + SPI_CMD_REG);
> +	reg_val &= ~SPI_CMD_TX_DMA;
> +	if (op->data.dir == SPI_MEM_DATA_IN)
> +		reg_val &= ~SPI_CMD_RX_DMA;
> +	writel(reg_val, priv->base + SPI_CMD_REG);
> +
> +	writel(0, priv->base + SPI_TX_SRC_REG);
> +	writel(0, priv->base + SPI_RX_DST_REG);
> +
> +	if (op->data.dir == SPI_MEM_DATA_IN)
> +		dma_unmap_single(priv->rx_dma,
> +				 op->data.nbytes, DMA_FROM_DEVICE);
> +rx_free:
> +	if (op->data.dir == SPI_MEM_DATA_IN &&
> +	    !IS_ALIGNED((size_t)op->data.buf.in, 4))
> +		kfree(rx_tmp_buf);
> +tx_unmap:
> +	dma_unmap_single(priv->tx_dma,
> +			 tx_size, DMA_TO_DEVICE);
> +tx_free:
> +	kfree(tx_tmp_buf);
> +exit:
> +	return ret;
> +}
> +
> +static int mtk_spim_adjust_op_size(struct spi_slave *slave,
> +				   struct spi_mem_op *op)
> +{
> +	int opcode_len;
> +
> +	if (!op->data.nbytes)
> +		return 0;
> +
> +	if (op->data.dir != SPI_MEM_NO_DATA) {
> +		opcode_len = 1 + op->addr.nbytes + op->dummy.nbytes;
> +		if (opcode_len + op->data.nbytes > MTK_SPI_IPM_PACKET_SIZE) {
> +			op->data.nbytes = MTK_SPI_IPM_PACKET_SIZE - opcode_len;
> +			/* force data buffer dma-aligned. */
> +			op->data.nbytes -= op->data.nbytes % 4;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static int mtk_spim_get_attr(struct mtk_spim_priv *priv, struct udevice *dev)
> +{
> +	int ret;
> +
> +	priv->hw_cap.enhance_timing = dev_read_bool(dev, "enhance_timing");
> +	priv->hw_cap.dma_ext = dev_read_bool(dev, "dma_ext");
> +	priv->hw_cap.ipm_design = dev_read_bool(dev, "ipm_design");
> +	priv->hw_cap.support_quad = dev_read_bool(dev, "support_quad");
> +
> +	ret = dev_read_u32(dev, "tick_dly", &priv->tick_dly);
> +	if (ret < 0)
> +		dev_err(priv->dev, "tick dly not set.\n");
> +
> +	ret = dev_read_u32(dev, "sample_sel", &priv->sample_sel);
> +	if (ret < 0)
> +		dev_err(priv->dev, "sample sel not set.\n");
> +
> +	return ret;
> +}
> +
> +static int mtk_spim_probe(struct udevice *dev)
> +{
> +	struct mtk_spim_priv *priv = dev_get_priv(dev);
> +	int ret;
> +
> +	priv->base = (void __iomem *)devfdt_get_addr(dev);
> +	if (!priv->base)
> +		return -EINVAL;
> +
> +	mtk_spim_get_attr(priv, dev);
> +
> +	ret = clk_get_by_name(dev, "sel-clk", &priv->sel_clk);
> +	if (ret < 0) {
> +		dev_err(dev, "failed to get sel-clk\n");
> +		return ret;
> +	}
> +
> +	ret = clk_get_by_name(dev, "spi-clk", &priv->spi_clk);
> +	if (ret < 0) {
> +		dev_err(dev, "failed to get spi-clk\n");
> +		return ret;
> +	}
> +
> +	clk_enable(&priv->sel_clk);
> +	clk_enable(&priv->spi_clk);
> +
> +	return 0;
> +}
> +
> +static int mtk_spim_set_speed(struct udevice *dev, uint speed)
> +{
> +	return 0;
> +}
> +
> +static int mtk_spim_set_mode(struct udevice *dev, uint mode)
> +{
> +	return 0;
> +}
> +
> +static const struct spi_controller_mem_ops mtk_spim_mem_ops = {
> +	.adjust_op_size = mtk_spim_adjust_op_size,
> +	.supports_op = mtk_spim_supports_op,
> +	.exec_op = mtk_spim_exec_op
> +};
> +
> +static const struct dm_spi_ops mtk_spim_ops = {
> +	.mem_ops = &mtk_spim_mem_ops,
> +	.set_speed = mtk_spim_set_speed,
> +	.set_mode = mtk_spim_set_mode,
> +};
> +
> +static const struct udevice_id mtk_spim_ids[] = {
> +	{ .compatible = "mediatek,ipm-spi" },
> +	{}
> +};
> +
> +U_BOOT_DRIVER(mtk_spim) = {
> +	.name = "mtk_spim",
> +	.id = UCLASS_SPI,
> +	.of_match = mtk_spim_ids,
> +	.ops = &mtk_spim_ops,
> +	.priv_auto = sizeof(struct mtk_spim_priv),
> +	.probe = mtk_spim_probe,
> +};
> -- 
> 2.17.1
> 

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

* Re: [PATCH v2 21/32] pinctrl: mediatek: add pinctrl driver for MT7986 SoC
  2022-08-31 11:04 ` [PATCH v2 21/32] pinctrl: mediatek: add pinctrl driver for MT7986 SoC Weijie Gao
@ 2022-09-01  0:26   ` Daniel Golle
  0 siblings, 0 replies; 60+ messages in thread
From: Daniel Golle @ 2022-09-01  0:26 UTC (permalink / raw)
  To: Weijie Gao; +Cc: u-boot, GSS_MTK_Uboot_upstream

On Wed, Aug 31, 2022 at 07:04:57PM +0800, Weijie Gao wrote:
> This patch adds pinctrl and gpio support for MT7986 SoC
> 

Tested on Bananapi BPi-R3 (MT7986A).

Tested-by: Daniel Golle <daniel@makrotopia.org>

> Reviewed-by: Simon Glass <sjg@chromium.org>
> Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
> ---
> v2 changes: none
> ---
>  drivers/pinctrl/mediatek/Kconfig          |   4 +
>  drivers/pinctrl/mediatek/Makefile         |   1 +
>  drivers/pinctrl/mediatek/pinctrl-mt7986.c | 775 ++++++++++++++++++++++
>  3 files changed, 780 insertions(+)
>  create mode 100644 drivers/pinctrl/mediatek/pinctrl-mt7986.c
> 
> diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig
> index aceec9277d..27e8998e59 100644
> --- a/drivers/pinctrl/mediatek/Kconfig
> +++ b/drivers/pinctrl/mediatek/Kconfig
> @@ -20,6 +20,10 @@ config PINCTRL_MT7981
>  	bool "MT7981 SoC pinctrl driver"
>  	select PINCTRL_MTK
>  
> +config PINCTRL_MT7986
> +	bool "MT7986 SoC pinctrl driver"
> +	select PINCTRL_MTK
> +
>  config PINCTRL_MT8512
>  	bool "MT8512 SoC pinctrl driver"
>  	select PINCTRL_MTK
> diff --git a/drivers/pinctrl/mediatek/Makefile b/drivers/pinctrl/mediatek/Makefile
> index 1879d7ae2a..6e733759f5 100644
> --- a/drivers/pinctrl/mediatek/Makefile
> +++ b/drivers/pinctrl/mediatek/Makefile
> @@ -7,6 +7,7 @@ obj-$(CONFIG_PINCTRL_MT7622) += pinctrl-mt7622.o
>  obj-$(CONFIG_PINCTRL_MT7623) += pinctrl-mt7623.o
>  obj-$(CONFIG_PINCTRL_MT7629) += pinctrl-mt7629.o
>  obj-$(CONFIG_PINCTRL_MT7981) += pinctrl-mt7981.o
> +obj-$(CONFIG_PINCTRL_MT7986) += pinctrl-mt7986.o
>  obj-$(CONFIG_PINCTRL_MT8512) += pinctrl-mt8512.o
>  obj-$(CONFIG_PINCTRL_MT8516) += pinctrl-mt8516.o
>  obj-$(CONFIG_PINCTRL_MT8518) += pinctrl-mt8518.o
> diff --git a/drivers/pinctrl/mediatek/pinctrl-mt7986.c b/drivers/pinctrl/mediatek/pinctrl-mt7986.c
> new file mode 100644
> index 0000000000..449e5adcd9
> --- /dev/null
> +++ b/drivers/pinctrl/mediatek/pinctrl-mt7986.c
> @@ -0,0 +1,775 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * The MT7986 driver based on Linux generic pinctrl binding.
> + *
> + * Copyright (C) 2022 MediaTek Inc.
> + * Author: Sam Shih <sam.shih@mediatek.com>
> + */
> +
> +#include <dm.h>
> +#include "pinctrl-mtk-common.h"
> +
> +#define MT7986_TYPE0_PIN(_number, _name)	\
> +	MTK_TYPED_PIN(_number, _name, DRV_GRP4, IO_TYPE_GRP0)
> +
> +#define MT7986_TYPE1_PIN(_number, _name)	\
> +	MTK_TYPED_PIN(_number, _name, DRV_GRP4, IO_TYPE_GRP1)
> +
> +#define PIN_FIELD_GPIO(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit, _x_bits)	\
> +	PIN_FIELD_BASE_CALC(_s_pin, _e_pin, GPIO_BASE, _s_addr, _x_addrs,	\
> +			    _s_bit, _x_bits, 32, 0)
> +
> +#define PIN_FIELD_BASE(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit,	\
> +		       _x_bits)							\
> +	PIN_FIELD_BASE_CALC(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit,	\
> +	_x_bits, 32, 0)
> +
> +/**
> + * enum - Locking variants of the iocfg bases
> + *
> + * MT7986 have multiple bases to program pin configuration listed as the below:
> + * iocfg_rt:0x11c30000, iocfg_rb:0x11c40000, iocfg_lt:0x11e20000,
> + * iocfg_lb:0x11e30000, iocfg_tr:0x11f00000, iocfg_tl:0x11f10000,
> + * _i_based could be used to indicate what base the pin should be mapped into.
> + *
> + * Each iocfg register base control different group of pads on the SoC
> + *
> + *
> + *  chip carrier
> + *
> + *      A  B  C  D  E  F  G  H
> + *    +------------------------+
> + *  8 | o  o  o  o  o  o  o  o |
> + *  7 | o  o  o  o  o  o  o  o |
> + *  6 | o  o  o  o  o  o  o  o |
> + *  5 | o  o  o  o  o  o  o  o |
> + *  4 | o  o  o  o  o  o  o  o |
> + *  3 | o  o  o  o  o  o  o  o |
> + *  2 | o  o  o  o  o  o  o  o |
> + *  1 | o  o  o  o  o  o  o  o |
> + *    +------------------------+
> + *
> + *  inside Chip carrier
> + *
> + *      A  B  C  D  E  F  G  H
> + *    +------------------------+
> + *  8 |                        |
> + *  7 |        TL  TR          |
> + *  6 |      +---------+       |
> + *  5 |   LT |         | RT    |
> + *  4 |      |         |       |
> + *  3 |   LB |         | RB    |
> + *  2 |      +---------+       |
> + *  1 |                        |
> + *    +------------------------+
> + *
> + */
> +
> +enum {
> +	GPIO_BASE,
> +	IOCFG_RT_BASE,
> +	IOCFG_RB_BASE,
> +	IOCFG_LT_BASE,
> +	IOCFG_LB_BASE,
> +	IOCFG_TR_BASE,
> +	IOCFG_TL_BASE,
> +};
> +
> +static const char *const mt7986_pinctrl_register_base_names[] = {
> +	"gpio", "iocfg_rt", "iocfg_rb", "iocfg_lt", "iocfg_lb", "iocfg_tr",
> +	"iocfg_tl",
> +};
> +
> +static const struct mtk_pin_field_calc mt7986_pin_mode_range[] = {
> +	PIN_FIELD_GPIO(0, 100, 0x300, 0x10, 0, 4),
> +};
> +
> +static const struct mtk_pin_field_calc mt7986_pin_dir_range[] = {
> +	PIN_FIELD_GPIO(0, 100, 0x0, 0x10, 0, 1),
> +};
> +
> +static const struct mtk_pin_field_calc mt7986_pin_di_range[] = {
> +	PIN_FIELD_GPIO(0, 100, 0x200, 0x10, 0, 1),
> +};
> +
> +static const struct mtk_pin_field_calc mt7986_pin_do_range[] = {
> +	PIN_FIELD_GPIO(0, 100, 0x100, 0x10, 0, 1),
> +};
> +
> +static const struct mtk_pin_field_calc mt7986_pin_ies_range[] = {
> +	PIN_FIELD_BASE(0, 0, IOCFG_RB_BASE, 0x40, 0x10, 17, 1),
> +	PIN_FIELD_BASE(1, 2, IOCFG_LT_BASE, 0x20, 0x10, 10, 1),
> +	PIN_FIELD_BASE(3, 4, IOCFG_LB_BASE, 0x20, 0x10, 0, 1),
> +	PIN_FIELD_BASE(5, 6, IOCFG_RB_BASE, 0x40, 0x10, 0, 1),
> +	PIN_FIELD_BASE(7, 10, IOCFG_LT_BASE, 0x20, 0x10, 0, 1),
> +	PIN_FIELD_BASE(11, 14, IOCFG_RB_BASE, 0x40, 0x10, 8, 1),
> +	PIN_FIELD_BASE(15, 20, IOCFG_RB_BASE, 0x40, 0x10, 2, 1),
> +	PIN_FIELD_BASE(21, 23, IOCFG_RT_BASE, 0x30, 0x10, 12, 1),
> +	PIN_FIELD_BASE(24, 24, IOCFG_RT_BASE, 0x30, 0x10, 18, 1),
> +	PIN_FIELD_BASE(25, 25, IOCFG_RT_BASE, 0x30, 0x10, 17, 1),
> +	PIN_FIELD_BASE(26, 27, IOCFG_RT_BASE, 0x30, 0x10, 15, 1),
> +	PIN_FIELD_BASE(28, 29, IOCFG_RT_BASE, 0x30, 0x10, 19, 1),
> +	PIN_FIELD_BASE(30, 30, IOCFG_RT_BASE, 0x30, 0x10, 23, 1),
> +	PIN_FIELD_BASE(31, 31, IOCFG_RT_BASE, 0x30, 0x10, 22, 1),
> +	PIN_FIELD_BASE(32, 32, IOCFG_RT_BASE, 0x30, 0x10, 21, 1),
> +	PIN_FIELD_BASE(33, 33, IOCFG_LT_BASE, 0x20, 0x10, 4, 1),
> +	PIN_FIELD_BASE(34, 34, IOCFG_LT_BASE, 0x20, 0x10, 8, 1),
> +	PIN_FIELD_BASE(35, 35, IOCFG_LT_BASE, 0x20, 0x10, 7, 1),
> +	PIN_FIELD_BASE(36, 37, IOCFG_LT_BASE, 0x20, 0x10, 5, 1),
> +	PIN_FIELD_BASE(38, 38, IOCFG_LT_BASE, 0x20, 0x10, 9, 1),
> +	PIN_FIELD_BASE(39, 40, IOCFG_RB_BASE, 0x40, 0x10, 18, 1),
> +	PIN_FIELD_BASE(41, 41, IOCFG_RB_BASE, 0x40, 0x10, 12, 1),
> +	PIN_FIELD_BASE(42, 43, IOCFG_RB_BASE, 0x40, 0x10, 22, 1),
> +	PIN_FIELD_BASE(44, 45, IOCFG_RB_BASE, 0x40, 0x10, 20, 1),
> +	PIN_FIELD_BASE(46, 47, IOCFG_RB_BASE, 0x40, 0x10, 26, 1),
> +	PIN_FIELD_BASE(48, 49, IOCFG_RB_BASE, 0x40, 0x10, 24, 1),
> +	PIN_FIELD_BASE(50, 57, IOCFG_RT_BASE, 0x30, 0x10, 2, 1),
> +	PIN_FIELD_BASE(58, 58, IOCFG_RT_BASE, 0x30, 0x10, 1, 1),
> +	PIN_FIELD_BASE(59, 59, IOCFG_RT_BASE, 0x30, 0x10, 0, 1),
> +	PIN_FIELD_BASE(60, 61, IOCFG_RT_BASE, 0x30, 0x10, 10, 1),
> +	PIN_FIELD_BASE(62, 62, IOCFG_RB_BASE, 0x40, 0x10, 15, 1),
> +	PIN_FIELD_BASE(63, 63, IOCFG_RB_BASE, 0x40, 0x10, 14, 1),
> +	PIN_FIELD_BASE(64, 64, IOCFG_RB_BASE, 0x40, 0x10, 13, 1),
> +	PIN_FIELD_BASE(65, 65, IOCFG_RB_BASE, 0x40, 0x10, 16, 1),
> +	PIN_FIELD_BASE(66, 68, IOCFG_LB_BASE, 0x20, 0x10, 2, 1),
> +	PIN_FIELD_BASE(69, 69, IOCFG_TR_BASE, 0x30, 0x10, 1, 1),
> +	PIN_FIELD_BASE(70, 70, IOCFG_TR_BASE, 0x30, 0x10, 0, 1),
> +	PIN_FIELD_BASE(71, 71, IOCFG_TR_BASE, 0x30, 0x10, 16, 1),
> +	PIN_FIELD_BASE(72, 73, IOCFG_TR_BASE, 0x30, 0x10, 14, 1),
> +	PIN_FIELD_BASE(74, 74, IOCFG_TR_BASE, 0x30, 0x10, 4, 1),
> +	PIN_FIELD_BASE(75, 77, IOCFG_TR_BASE, 0x30, 0x10, 6, 1),
> +	PIN_FIELD_BASE(78, 79, IOCFG_TR_BASE, 0x30, 0x10, 2, 1),
> +	PIN_FIELD_BASE(80, 84, IOCFG_TR_BASE, 0x30, 0x10, 9, 1),
> +	PIN_FIELD_BASE(85, 85, IOCFG_TR_BASE, 0x30, 0x10, 5, 1),
> +	PIN_FIELD_BASE(86, 86, IOCFG_TL_BASE, 0x30, 0x10, 1, 1),
> +	PIN_FIELD_BASE(87, 87, IOCFG_TL_BASE, 0x30, 0x10, 0, 1),
> +	PIN_FIELD_BASE(88, 88, IOCFG_TL_BASE, 0x30, 0x10, 14, 1),
> +	PIN_FIELD_BASE(89, 90, IOCFG_TL_BASE, 0x30, 0x10, 12, 1),
> +	PIN_FIELD_BASE(91, 94, IOCFG_TL_BASE, 0x30, 0x10, 4, 1),
> +	PIN_FIELD_BASE(95, 96, IOCFG_TL_BASE, 0x30, 0x10, 2, 1),
> +	PIN_FIELD_BASE(97, 100, IOCFG_TL_BASE, 0x30, 0x10, 8, 1),
> +};
> +
> +static const struct mtk_pin_field_calc mt7986_pin_smt_range[] = {
> +	PIN_FIELD_BASE(0, 0, IOCFG_RB_BASE, 0xf0, 0x10, 17, 1),
> +	PIN_FIELD_BASE(1, 2, IOCFG_LT_BASE, 0x90, 0x10, 10, 1),
> +	PIN_FIELD_BASE(3, 4, IOCFG_LB_BASE, 0x90, 0x10, 0, 1),
> +	PIN_FIELD_BASE(5, 6, IOCFG_RB_BASE, 0xf0, 0x10, 0, 1),
> +	PIN_FIELD_BASE(7, 10, IOCFG_LT_BASE, 0x90, 0x10, 0, 1),
> +	PIN_FIELD_BASE(11, 14, IOCFG_RB_BASE, 0xf0, 0x10, 8, 1),
> +	PIN_FIELD_BASE(15, 20, IOCFG_RB_BASE, 0xf0, 0x10, 2, 1),
> +	PIN_FIELD_BASE(21, 23, IOCFG_RT_BASE, 0xc0, 0x10, 12, 1),
> +	PIN_FIELD_BASE(24, 24, IOCFG_RT_BASE, 0xc0, 0x10, 18, 1),
> +	PIN_FIELD_BASE(25, 25, IOCFG_RT_BASE, 0xc0, 0x10, 17, 1),
> +	PIN_FIELD_BASE(26, 27, IOCFG_RT_BASE, 0xc0, 0x10, 15, 1),
> +	PIN_FIELD_BASE(28, 29, IOCFG_RT_BASE, 0xc0, 0x10, 19, 1),
> +	PIN_FIELD_BASE(30, 30, IOCFG_RT_BASE, 0xc0, 0x10, 23, 1),
> +	PIN_FIELD_BASE(31, 31, IOCFG_RT_BASE, 0xc0, 0x10, 22, 1),
> +	PIN_FIELD_BASE(32, 32, IOCFG_RT_BASE, 0xc0, 0x10, 21, 1),
> +	PIN_FIELD_BASE(33, 33, IOCFG_LT_BASE, 0x90, 0x10, 4, 1),
> +	PIN_FIELD_BASE(34, 34, IOCFG_LT_BASE, 0x90, 0x10, 8, 1),
> +	PIN_FIELD_BASE(35, 35, IOCFG_LT_BASE, 0x90, 0x10, 7, 1),
> +	PIN_FIELD_BASE(36, 37, IOCFG_LT_BASE, 0x90, 0x10, 5, 1),
> +	PIN_FIELD_BASE(38, 38, IOCFG_LT_BASE, 0x90, 0x10, 9, 1),
> +	PIN_FIELD_BASE(39, 40, IOCFG_RB_BASE, 0xf0, 0x10, 18, 1),
> +	PIN_FIELD_BASE(41, 41, IOCFG_RB_BASE, 0xf0, 0x10, 12, 1),
> +	PIN_FIELD_BASE(42, 43, IOCFG_RB_BASE, 0xf0, 0x10, 22, 1),
> +	PIN_FIELD_BASE(44, 45, IOCFG_RB_BASE, 0xf0, 0x10, 20, 1),
> +	PIN_FIELD_BASE(46, 47, IOCFG_RB_BASE, 0xf0, 0x10, 26, 1),
> +	PIN_FIELD_BASE(48, 49, IOCFG_RB_BASE, 0xf0, 0x10, 24, 1),
> +	PIN_FIELD_BASE(50, 57, IOCFG_RT_BASE, 0xc0, 0x10, 2, 1),
> +	PIN_FIELD_BASE(58, 58, IOCFG_RT_BASE, 0xc0, 0x10, 1, 1),
> +	PIN_FIELD_BASE(59, 59, IOCFG_RT_BASE, 0xc0, 0x10, 0, 1),
> +	PIN_FIELD_BASE(60, 61, IOCFG_RT_BASE, 0xc0, 0x10, 10, 1),
> +	PIN_FIELD_BASE(62, 62, IOCFG_RB_BASE, 0xf0, 0x10, 15, 1),
> +	PIN_FIELD_BASE(63, 63, IOCFG_RB_BASE, 0xf0, 0x10, 14, 1),
> +	PIN_FIELD_BASE(64, 64, IOCFG_RB_BASE, 0xf0, 0x10, 13, 1),
> +	PIN_FIELD_BASE(65, 65, IOCFG_RB_BASE, 0xf0, 0x10, 16, 1),
> +	PIN_FIELD_BASE(66, 68, IOCFG_LB_BASE, 0x90, 0x10, 2, 1),
> +	PIN_FIELD_BASE(69, 69, IOCFG_TR_BASE, 0x80, 0x10, 1, 1),
> +	PIN_FIELD_BASE(70, 70, IOCFG_TR_BASE, 0x80, 0x10, 0, 1),
> +	PIN_FIELD_BASE(71, 71, IOCFG_TR_BASE, 0x80, 0x10, 16, 1),
> +	PIN_FIELD_BASE(72, 73, IOCFG_TR_BASE, 0x80, 0x10, 14, 1),
> +	PIN_FIELD_BASE(74, 74, IOCFG_TR_BASE, 0x80, 0x10, 4, 1),
> +	PIN_FIELD_BASE(75, 77, IOCFG_TR_BASE, 0x80, 0x10, 6, 1),
> +	PIN_FIELD_BASE(78, 79, IOCFG_TR_BASE, 0x80, 0x10, 2, 1),
> +	PIN_FIELD_BASE(80, 84, IOCFG_TR_BASE, 0x80, 0x10, 9, 1),
> +	PIN_FIELD_BASE(85, 85, IOCFG_TR_BASE, 0x80, 0x10, 5, 1),
> +	PIN_FIELD_BASE(86, 86, IOCFG_TL_BASE, 0x70, 0x10, 1, 1),
> +	PIN_FIELD_BASE(87, 87, IOCFG_TL_BASE, 0x70, 0x10, 0, 1),
> +	PIN_FIELD_BASE(88, 88, IOCFG_TL_BASE, 0x70, 0x10, 14, 1),
> +	PIN_FIELD_BASE(89, 90, IOCFG_TL_BASE, 0x70, 0x10, 12, 1),
> +	PIN_FIELD_BASE(91, 94, IOCFG_TL_BASE, 0x70, 0x10, 4, 1),
> +	PIN_FIELD_BASE(95, 96, IOCFG_TL_BASE, 0x70, 0x10, 2, 1),
> +	PIN_FIELD_BASE(97, 100, IOCFG_TL_BASE, 0x70, 0x10, 8, 1),
> +};
> +
> +static const struct mtk_pin_field_calc mt7986_pin_pu_range[] = {
> +	PIN_FIELD_BASE(69, 69, IOCFG_TR_BASE, 0x50, 0x10, 1, 1),
> +	PIN_FIELD_BASE(70, 70, IOCFG_TR_BASE, 0x50, 0x10, 0, 1),
> +	PIN_FIELD_BASE(71, 71, IOCFG_TR_BASE, 0x50, 0x10, 16, 1),
> +	PIN_FIELD_BASE(72, 73, IOCFG_TR_BASE, 0x50, 0x10, 14, 1),
> +	PIN_FIELD_BASE(74, 74, IOCFG_TR_BASE, 0x50, 0x10, 4, 1),
> +	PIN_FIELD_BASE(75, 77, IOCFG_TR_BASE, 0x50, 0x10, 6, 1),
> +	PIN_FIELD_BASE(78, 79, IOCFG_TR_BASE, 0x50, 0x10, 2, 1),
> +	PIN_FIELD_BASE(80, 84, IOCFG_TR_BASE, 0x50, 0x10, 9, 1),
> +	PIN_FIELD_BASE(85, 85, IOCFG_TR_BASE, 0x50, 0x10, 5, 1),
> +	PIN_FIELD_BASE(86, 86, IOCFG_TL_BASE, 0x50, 0x10, 1, 1),
> +	PIN_FIELD_BASE(87, 87, IOCFG_TL_BASE, 0x50, 0x10, 0, 1),
> +	PIN_FIELD_BASE(88, 88, IOCFG_TL_BASE, 0x50, 0x10, 14, 1),
> +	PIN_FIELD_BASE(89, 90, IOCFG_TL_BASE, 0x50, 0x10, 12, 1),
> +	PIN_FIELD_BASE(91, 94, IOCFG_TL_BASE, 0x50, 0x10, 4, 1),
> +	PIN_FIELD_BASE(95, 96, IOCFG_TL_BASE, 0x50, 0x10, 2, 1),
> +	PIN_FIELD_BASE(97, 100, IOCFG_TL_BASE, 0x50, 0x10, 8, 1),
> +};
> +
> +static const struct mtk_pin_field_calc mt7986_pin_pd_range[] = {
> +	PIN_FIELD_BASE(69, 69, IOCFG_TR_BASE, 0x40, 0x10, 1, 1),
> +	PIN_FIELD_BASE(70, 70, IOCFG_TR_BASE, 0x40, 0x10, 0, 1),
> +	PIN_FIELD_BASE(71, 71, IOCFG_TR_BASE, 0x40, 0x10, 16, 1),
> +	PIN_FIELD_BASE(72, 73, IOCFG_TR_BASE, 0x40, 0x10, 14, 1),
> +	PIN_FIELD_BASE(74, 74, IOCFG_TR_BASE, 0x40, 0x10, 4, 1),
> +	PIN_FIELD_BASE(75, 77, IOCFG_TR_BASE, 0x40, 0x10, 6, 1),
> +	PIN_FIELD_BASE(78, 79, IOCFG_TR_BASE, 0x40, 0x10, 2, 1),
> +	PIN_FIELD_BASE(80, 84, IOCFG_TR_BASE, 0x40, 0x10, 9, 1),
> +	PIN_FIELD_BASE(85, 85, IOCFG_TR_BASE, 0x40, 0x10, 5, 1),
> +	PIN_FIELD_BASE(86, 86, IOCFG_TL_BASE, 0x40, 0x10, 1, 1),
> +	PIN_FIELD_BASE(87, 87, IOCFG_TL_BASE, 0x40, 0x10, 0, 1),
> +	PIN_FIELD_BASE(88, 88, IOCFG_TL_BASE, 0x40, 0x10, 14, 1),
> +	PIN_FIELD_BASE(89, 90, IOCFG_TL_BASE, 0x40, 0x10, 12, 1),
> +	PIN_FIELD_BASE(91, 94, IOCFG_TL_BASE, 0x40, 0x10, 4, 1),
> +	PIN_FIELD_BASE(95, 96, IOCFG_TL_BASE, 0x40, 0x10, 2, 1),
> +	PIN_FIELD_BASE(97, 100, IOCFG_TL_BASE, 0x40, 0x10, 8, 1),
> +};
> +
> +static const struct mtk_pin_field_calc mt7986_pin_drv_range[] = {
> +	PIN_FIELD_BASE(0, 0, IOCFG_RB_BASE, 0x10, 0x10, 21, 3),
> +	PIN_FIELD_BASE(1, 2, IOCFG_LT_BASE, 0x10, 0x10, 0, 3),
> +	PIN_FIELD_BASE(3, 4, IOCFG_LB_BASE, 0x00, 0x10, 0, 1),
> +	PIN_FIELD_BASE(5, 5, IOCFG_RB_BASE, 0x00, 0x10, 0, 3),
> +	PIN_FIELD_BASE(6, 6, IOCFG_RB_BASE, 0x00, 0x10, 21, 3),
> +	PIN_FIELD_BASE(7, 10, IOCFG_LT_BASE, 0x00, 0x10, 0, 3),
> +	PIN_FIELD_BASE(11, 12, IOCFG_RB_BASE, 0x00, 0x10, 24, 3),
> +	PIN_FIELD_BASE(13, 14, IOCFG_RB_BASE, 0x10, 0x10, 0, 3),
> +	PIN_FIELD_BASE(15, 20, IOCFG_RB_BASE, 0x00, 0x10, 3, 3),
> +	PIN_FIELD_BASE(21, 23, IOCFG_RT_BASE, 0x10, 0x10, 6, 3),
> +	PIN_FIELD_BASE(24, 24, IOCFG_RT_BASE, 0x10, 0x10, 24, 3),
> +	PIN_FIELD_BASE(25, 25, IOCFG_RT_BASE, 0x10, 0x10, 21, 3),
> +	PIN_FIELD_BASE(26, 27, IOCFG_RT_BASE, 0x10, 0x10, 15, 3),
> +	PIN_FIELD_BASE(28, 28, IOCFG_RT_BASE, 0x10, 0x10, 27, 3),
> +	PIN_FIELD_BASE(29, 29, IOCFG_RT_BASE, 0x20, 0x10, 0, 3),
> +	PIN_FIELD_BASE(30, 30, IOCFG_RT_BASE, 0x20, 0x10, 9, 3),
> +	PIN_FIELD_BASE(31, 31, IOCFG_RT_BASE, 0x20, 0x10, 6, 3),
> +	PIN_FIELD_BASE(32, 32, IOCFG_RT_BASE, 0x20, 0x10, 3, 3),
> +	PIN_FIELD_BASE(33, 33, IOCFG_LT_BASE, 0x00, 0x10, 12, 3),
> +	PIN_FIELD_BASE(34, 34, IOCFG_LT_BASE, 0x00, 0x10, 24, 3),
> +	PIN_FIELD_BASE(35, 35, IOCFG_LT_BASE, 0x00, 0x10, 21, 3),
> +	PIN_FIELD_BASE(36, 37, IOCFG_LT_BASE, 0x00, 0x10, 15, 3),
> +	PIN_FIELD_BASE(38, 38, IOCFG_LT_BASE, 0x00, 0x10, 27, 3),
> +	PIN_FIELD_BASE(39, 39, IOCFG_RB_BASE, 0x10, 0x10, 27, 3),
> +	PIN_FIELD_BASE(40, 40, IOCFG_RB_BASE, 0x20, 0x10, 0, 3),
> +	PIN_FIELD_BASE(41, 41, IOCFG_RB_BASE, 0x10, 0x10, 6, 3),
> +	PIN_FIELD_BASE(42, 43, IOCFG_RB_BASE, 0x20, 0x10, 9, 3),
> +	PIN_FIELD_BASE(44, 45, IOCFG_RB_BASE, 0x20, 0x10, 3, 3),
> +	PIN_FIELD_BASE(46, 47, IOCFG_RB_BASE, 0x20, 0x10, 21, 3),
> +	PIN_FIELD_BASE(48, 49, IOCFG_RB_BASE, 0x20, 0x10, 15, 3),
> +	PIN_FIELD_BASE(50, 57, IOCFG_RT_BASE, 0x00, 0x10, 6, 3),
> +	PIN_FIELD_BASE(58, 58, IOCFG_RT_BASE, 0x00, 0x10, 3, 3),
> +	PIN_FIELD_BASE(59, 59, IOCFG_RT_BASE, 0x00, 0x10, 0, 3),
> +	PIN_FIELD_BASE(60, 61, IOCFG_RT_BASE, 0x10, 0x10, 0, 3),
> +	PIN_FIELD_BASE(62, 62, IOCFG_RB_BASE, 0x10, 0x10, 15, 3),
> +	PIN_FIELD_BASE(63, 63, IOCFG_RB_BASE, 0x10, 0x10, 12, 3),
> +	PIN_FIELD_BASE(64, 64, IOCFG_RB_BASE, 0x10, 0x10, 9, 3),
> +	PIN_FIELD_BASE(65, 65, IOCFG_RB_BASE, 0x10, 0x10, 18, 3),
> +	PIN_FIELD_BASE(66, 68, IOCFG_LB_BASE, 0x00, 0x10, 2, 3),
> +	PIN_FIELD_BASE(69, 69, IOCFG_TR_BASE, 0x00, 0x10, 3, 3),
> +	PIN_FIELD_BASE(70, 70, IOCFG_TR_BASE, 0x00, 0x10, 0, 3),
> +	PIN_FIELD_BASE(71, 71, IOCFG_TR_BASE, 0x10, 0x10, 18, 3),
> +	PIN_FIELD_BASE(72, 73, IOCFG_TR_BASE, 0x10, 0x10, 12, 3),
> +	PIN_FIELD_BASE(74, 77, IOCFG_TR_BASE, 0x00, 0x10, 15, 3),
> +	PIN_FIELD_BASE(78, 79, IOCFG_TR_BASE, 0x00, 0x10, 6, 3),
> +	PIN_FIELD_BASE(80, 80, IOCFG_TR_BASE, 0x00, 0x10, 27, 3),
> +	PIN_FIELD_BASE(81, 84, IOCFG_TR_BASE, 0x10, 0x10, 0, 3),
> +	PIN_FIELD_BASE(85, 85, IOCFG_TR_BASE, 0x00, 0x10, 12, 3),
> +	PIN_FIELD_BASE(86, 86, IOCFG_TL_BASE, 0x00, 0x10, 3, 3),
> +	PIN_FIELD_BASE(87, 87, IOCFG_TL_BASE, 0x00, 0x10, 0, 3),
> +	PIN_FIELD_BASE(88, 88, IOCFG_TL_BASE, 0x10, 0x10, 12, 3),
> +	PIN_FIELD_BASE(89, 90, IOCFG_TL_BASE, 0x10, 0x10, 6, 3),
> +	PIN_FIELD_BASE(91, 94, IOCFG_TL_BASE, 0x00, 0x10, 12, 3),
> +	PIN_FIELD_BASE(95, 96, IOCFG_TL_BASE, 0x00, 0x10, 6, 3),
> +	PIN_FIELD_BASE(97, 98, IOCFG_TL_BASE, 0x00, 0x10, 24, 3),
> +	PIN_FIELD_BASE(99, 100, IOCFG_TL_BASE, 0x10, 0x10, 2, 3),
> +};
> +
> +static const struct mtk_pin_field_calc mt7986_pin_pupd_range[] = {
> +	PIN_FIELD_BASE(0, 0, IOCFG_RB_BASE, 0x60, 0x10, 17, 1),
> +	PIN_FIELD_BASE(1, 2, IOCFG_LT_BASE, 0x30, 0x10, 10, 1),
> +	PIN_FIELD_BASE(3, 4, IOCFG_LB_BASE, 0x40, 0x10, 0, 1),
> +	PIN_FIELD_BASE(5, 6, IOCFG_RB_BASE, 0x60, 0x10, 0, 1),
> +	PIN_FIELD_BASE(7, 10, IOCFG_LT_BASE, 0x30, 0x10, 0, 1),
> +	PIN_FIELD_BASE(11, 14, IOCFG_RB_BASE, 0x60, 0x10, 8, 1),
> +	PIN_FIELD_BASE(15, 20, IOCFG_RB_BASE, 0x60, 0x10, 2, 1),
> +	PIN_FIELD_BASE(21, 23, IOCFG_RT_BASE, 0x40, 0x10, 12, 1),
> +	PIN_FIELD_BASE(24, 24, IOCFG_RT_BASE, 0x40, 0x10, 18, 1),
> +	PIN_FIELD_BASE(25, 25, IOCFG_RT_BASE, 0x40, 0x10, 17, 1),
> +	PIN_FIELD_BASE(26, 27, IOCFG_RT_BASE, 0x40, 0x10, 15, 1),
> +	PIN_FIELD_BASE(28, 29, IOCFG_RT_BASE, 0x40, 0x10, 19, 1),
> +	PIN_FIELD_BASE(30, 30, IOCFG_RT_BASE, 0x40, 0x10, 23, 1),
> +	PIN_FIELD_BASE(31, 31, IOCFG_RT_BASE, 0x40, 0x10, 22, 1),
> +	PIN_FIELD_BASE(32, 32, IOCFG_RT_BASE, 0x40, 0x10, 21, 1),
> +	PIN_FIELD_BASE(33, 33, IOCFG_LT_BASE, 0x30, 0x10, 4, 1),
> +	PIN_FIELD_BASE(34, 34, IOCFG_LT_BASE, 0x30, 0x10, 8, 1),
> +	PIN_FIELD_BASE(35, 35, IOCFG_LT_BASE, 0x30, 0x10, 7, 1),
> +	PIN_FIELD_BASE(36, 37, IOCFG_LT_BASE, 0x30, 0x10, 5, 1),
> +	PIN_FIELD_BASE(38, 38, IOCFG_LT_BASE, 0x30, 0x10, 9, 1),
> +	PIN_FIELD_BASE(39, 40, IOCFG_RB_BASE, 0x60, 0x10, 18, 1),
> +	PIN_FIELD_BASE(41, 41, IOCFG_RB_BASE, 0x60, 0x10, 12, 1),
> +	PIN_FIELD_BASE(42, 43, IOCFG_RB_BASE, 0x60, 0x10, 23, 1),
> +	PIN_FIELD_BASE(44, 45, IOCFG_RB_BASE, 0x60, 0x10, 21, 1),
> +	PIN_FIELD_BASE(46, 47, IOCFG_RB_BASE, 0x60, 0x10, 27, 1),
> +	PIN_FIELD_BASE(48, 49, IOCFG_RB_BASE, 0x60, 0x10, 25, 1),
> +	PIN_FIELD_BASE(50, 57, IOCFG_RT_BASE, 0x40, 0x10, 2, 1),
> +	PIN_FIELD_BASE(58, 58, IOCFG_RT_BASE, 0x40, 0x10, 1, 1),
> +	PIN_FIELD_BASE(59, 59, IOCFG_RT_BASE, 0x40, 0x10, 0, 1),
> +	PIN_FIELD_BASE(60, 61, IOCFG_RT_BASE, 0x40, 0x10, 10, 1),
> +	PIN_FIELD_BASE(62, 62, IOCFG_RB_BASE, 0x60, 0x10, 15, 1),
> +	PIN_FIELD_BASE(63, 63, IOCFG_RB_BASE, 0x60, 0x10, 14, 1),
> +	PIN_FIELD_BASE(64, 64, IOCFG_RB_BASE, 0x60, 0x10, 13, 1),
> +	PIN_FIELD_BASE(65, 65, IOCFG_RB_BASE, 0x60, 0x10, 16, 1),
> +	PIN_FIELD_BASE(66, 68, IOCFG_LB_BASE, 0x40, 0x10, 2, 1),
> +};
> +
> +static const struct mtk_pin_field_calc mt7986_pin_r0_range[] = {
> +	PIN_FIELD_BASE(0, 0, IOCFG_RB_BASE, 0x70, 0x10, 17, 1),
> +	PIN_FIELD_BASE(1, 2, IOCFG_LT_BASE, 0x40, 0x10, 10, 1),
> +	PIN_FIELD_BASE(3, 4, IOCFG_LB_BASE, 0x50, 0x10, 0, 1),
> +	PIN_FIELD_BASE(5, 6, IOCFG_RB_BASE, 0x70, 0x10, 0, 1),
> +	PIN_FIELD_BASE(7, 10, IOCFG_LT_BASE, 0x40, 0x10, 0, 1),
> +	PIN_FIELD_BASE(11, 14, IOCFG_RB_BASE, 0x70, 0x10, 8, 1),
> +	PIN_FIELD_BASE(15, 20, IOCFG_RB_BASE, 0x70, 0x10, 2, 1),
> +	PIN_FIELD_BASE(21, 23, IOCFG_RT_BASE, 0x50, 0x10, 12, 1),
> +	PIN_FIELD_BASE(24, 24, IOCFG_RT_BASE, 0x50, 0x10, 18, 1),
> +	PIN_FIELD_BASE(25, 25, IOCFG_RT_BASE, 0x50, 0x10, 17, 1),
> +	PIN_FIELD_BASE(26, 27, IOCFG_RT_BASE, 0x50, 0x10, 15, 1),
> +	PIN_FIELD_BASE(28, 29, IOCFG_RT_BASE, 0x50, 0x10, 19, 1),
> +	PIN_FIELD_BASE(30, 30, IOCFG_RT_BASE, 0x50, 0x10, 23, 1),
> +	PIN_FIELD_BASE(31, 31, IOCFG_RT_BASE, 0x50, 0x10, 22, 1),
> +	PIN_FIELD_BASE(32, 32, IOCFG_RT_BASE, 0x50, 0x10, 21, 1),
> +	PIN_FIELD_BASE(33, 33, IOCFG_LT_BASE, 0x40, 0x10, 4, 1),
> +	PIN_FIELD_BASE(34, 34, IOCFG_LT_BASE, 0x40, 0x10, 8, 1),
> +	PIN_FIELD_BASE(35, 35, IOCFG_LT_BASE, 0x40, 0x10, 7, 1),
> +	PIN_FIELD_BASE(36, 37, IOCFG_LT_BASE, 0x40, 0x10, 5, 1),
> +	PIN_FIELD_BASE(38, 38, IOCFG_LT_BASE, 0x40, 0x10, 9, 1),
> +	PIN_FIELD_BASE(39, 40, IOCFG_RB_BASE, 0x70, 0x10, 18, 1),
> +	PIN_FIELD_BASE(41, 41, IOCFG_RB_BASE, 0x70, 0x10, 12, 1),
> +	PIN_FIELD_BASE(42, 43, IOCFG_RB_BASE, 0x70, 0x10, 23, 1),
> +	PIN_FIELD_BASE(44, 45, IOCFG_RB_BASE, 0x70, 0x10, 21, 1),
> +	PIN_FIELD_BASE(46, 47, IOCFG_RB_BASE, 0x70, 0x10, 27, 1),
> +	PIN_FIELD_BASE(48, 49, IOCFG_RB_BASE, 0x70, 0x10, 25, 1),
> +	PIN_FIELD_BASE(50, 57, IOCFG_RT_BASE, 0x50, 0x10, 2, 1),
> +	PIN_FIELD_BASE(58, 58, IOCFG_RT_BASE, 0x50, 0x10, 1, 1),
> +	PIN_FIELD_BASE(59, 59, IOCFG_RT_BASE, 0x50, 0x10, 0, 1),
> +	PIN_FIELD_BASE(60, 61, IOCFG_RT_BASE, 0x50, 0x10, 10, 1),
> +	PIN_FIELD_BASE(62, 62, IOCFG_RB_BASE, 0x70, 0x10, 15, 1),
> +	PIN_FIELD_BASE(63, 63, IOCFG_RB_BASE, 0x70, 0x10, 14, 1),
> +	PIN_FIELD_BASE(64, 64, IOCFG_RB_BASE, 0x70, 0x10, 13, 1),
> +	PIN_FIELD_BASE(65, 65, IOCFG_RB_BASE, 0x70, 0x10, 16, 1),
> +	PIN_FIELD_BASE(66, 68, IOCFG_LB_BASE, 0x50, 0x10, 2, 1),
> +};
> +
> +static const struct mtk_pin_field_calc mt7986_pin_r1_range[] = {
> +	PIN_FIELD_BASE(0, 0, IOCFG_RB_BASE, 0x80, 0x10, 17, 1),
> +	PIN_FIELD_BASE(1, 2, IOCFG_LT_BASE, 0x50, 0x10, 10, 1),
> +	PIN_FIELD_BASE(3, 4, IOCFG_LB_BASE, 0x60, 0x10, 0, 1),
> +	PIN_FIELD_BASE(5, 6, IOCFG_RB_BASE, 0x80, 0x10, 0, 1),
> +	PIN_FIELD_BASE(7, 10, IOCFG_LT_BASE, 0x50, 0x10, 0, 1),
> +	PIN_FIELD_BASE(11, 14, IOCFG_RB_BASE, 0x80, 0x10, 8, 1),
> +	PIN_FIELD_BASE(15, 20, IOCFG_RB_BASE, 0x80, 0x10, 2, 1),
> +	PIN_FIELD_BASE(21, 23, IOCFG_RT_BASE, 0x60, 0x10, 12, 1),
> +	PIN_FIELD_BASE(24, 24, IOCFG_RT_BASE, 0x60, 0x10, 18, 1),
> +	PIN_FIELD_BASE(25, 25, IOCFG_RT_BASE, 0x60, 0x10, 17, 1),
> +	PIN_FIELD_BASE(26, 27, IOCFG_RT_BASE, 0x60, 0x10, 15, 1),
> +	PIN_FIELD_BASE(28, 29, IOCFG_RT_BASE, 0x60, 0x10, 19, 1),
> +	PIN_FIELD_BASE(30, 30, IOCFG_RT_BASE, 0x60, 0x10, 23, 1),
> +	PIN_FIELD_BASE(31, 31, IOCFG_RT_BASE, 0x60, 0x10, 22, 1),
> +	PIN_FIELD_BASE(32, 32, IOCFG_RT_BASE, 0x60, 0x10, 21, 1),
> +	PIN_FIELD_BASE(33, 33, IOCFG_LT_BASE, 0x50, 0x10, 4, 1),
> +	PIN_FIELD_BASE(34, 34, IOCFG_LT_BASE, 0x50, 0x10, 8, 1),
> +	PIN_FIELD_BASE(35, 35, IOCFG_LT_BASE, 0x50, 0x10, 7, 1),
> +	PIN_FIELD_BASE(36, 37, IOCFG_LT_BASE, 0x50, 0x10, 5, 1),
> +	PIN_FIELD_BASE(38, 38, IOCFG_LT_BASE, 0x50, 0x10, 9, 1),
> +	PIN_FIELD_BASE(39, 40, IOCFG_RB_BASE, 0x80, 0x10, 18, 1),
> +	PIN_FIELD_BASE(41, 41, IOCFG_RB_BASE, 0x80, 0x10, 12, 1),
> +	PIN_FIELD_BASE(42, 43, IOCFG_RB_BASE, 0x80, 0x10, 23, 1),
> +	PIN_FIELD_BASE(44, 45, IOCFG_RB_BASE, 0x80, 0x10, 21, 1),
> +	PIN_FIELD_BASE(46, 47, IOCFG_RB_BASE, 0x80, 0x10, 27, 1),
> +	PIN_FIELD_BASE(48, 49, IOCFG_RB_BASE, 0x80, 0x10, 25, 1),
> +	PIN_FIELD_BASE(50, 57, IOCFG_RT_BASE, 0x60, 0x10, 2, 1),
> +	PIN_FIELD_BASE(58, 58, IOCFG_RT_BASE, 0x60, 0x10, 1, 1),
> +	PIN_FIELD_BASE(59, 59, IOCFG_RT_BASE, 0x60, 0x10, 0, 1),
> +	PIN_FIELD_BASE(60, 61, IOCFG_RT_BASE, 0x60, 0x10, 10, 1),
> +	PIN_FIELD_BASE(62, 62, IOCFG_RB_BASE, 0x80, 0x10, 15, 1),
> +	PIN_FIELD_BASE(63, 63, IOCFG_RB_BASE, 0x80, 0x10, 14, 1),
> +	PIN_FIELD_BASE(64, 64, IOCFG_RB_BASE, 0x80, 0x10, 13, 1),
> +	PIN_FIELD_BASE(65, 65, IOCFG_RB_BASE, 0x80, 0x10, 16, 1),
> +	PIN_FIELD_BASE(66, 68, IOCFG_LB_BASE, 0x60, 0x10, 2, 1),
> +};
> +
> +static const struct mtk_pin_reg_calc mt7986_reg_cals[] = {
> +	[PINCTRL_PIN_REG_MODE] = MTK_RANGE(mt7986_pin_mode_range),
> +	[PINCTRL_PIN_REG_DIR] = MTK_RANGE(mt7986_pin_dir_range),
> +	[PINCTRL_PIN_REG_DI] = MTK_RANGE(mt7986_pin_di_range),
> +	[PINCTRL_PIN_REG_DO] = MTK_RANGE(mt7986_pin_do_range),
> +	[PINCTRL_PIN_REG_SMT] = MTK_RANGE(mt7986_pin_smt_range),
> +	[PINCTRL_PIN_REG_IES] = MTK_RANGE(mt7986_pin_ies_range),
> +	[PINCTRL_PIN_REG_DRV] = MTK_RANGE(mt7986_pin_drv_range),
> +	[PINCTRL_PIN_REG_PU] = MTK_RANGE(mt7986_pin_pu_range),
> +	[PINCTRL_PIN_REG_PD] = MTK_RANGE(mt7986_pin_pd_range),
> +	[PINCTRL_PIN_REG_PUPD] = MTK_RANGE(mt7986_pin_pupd_range),
> +	[PINCTRL_PIN_REG_R0] = MTK_RANGE(mt7986_pin_r0_range),
> +	[PINCTRL_PIN_REG_R1] = MTK_RANGE(mt7986_pin_r1_range),
> +};
> +
> +static const struct mtk_pin_desc mt7986_pins[] = {
> +	MT7986_TYPE0_PIN(0, "SYS_WATCHDOG"),
> +	MT7986_TYPE0_PIN(1, "WF2G_LED"),
> +	MT7986_TYPE0_PIN(2, "WF5G_LED"),
> +	MT7986_TYPE0_PIN(3, "I2C_SCL"),
> +	MT7986_TYPE0_PIN(4, "I2C_SDA"),
> +	MT7986_TYPE0_PIN(5, "GPIO_0"),
> +	MT7986_TYPE0_PIN(6, "GPIO_1"),
> +	MT7986_TYPE0_PIN(7, "GPIO_2"),
> +	MT7986_TYPE0_PIN(8, "GPIO_3"),
> +	MT7986_TYPE0_PIN(9, "GPIO_4"),
> +	MT7986_TYPE0_PIN(10, "GPIO_5"),
> +	MT7986_TYPE0_PIN(11, "GPIO_6"),
> +	MT7986_TYPE0_PIN(12, "GPIO_7"),
> +	MT7986_TYPE0_PIN(13, "GPIO_8"),
> +	MT7986_TYPE0_PIN(14, "GPIO_9"),
> +	MT7986_TYPE0_PIN(15, "GPIO_10"),
> +	MT7986_TYPE0_PIN(16, "GPIO_11"),
> +	MT7986_TYPE0_PIN(17, "GPIO_12"),
> +	MT7986_TYPE0_PIN(18, "GPIO_13"),
> +	MT7986_TYPE0_PIN(19, "GPIO_14"),
> +	MT7986_TYPE0_PIN(20, "GPIO_15"),
> +	MT7986_TYPE0_PIN(21, "PWM0"),
> +	MT7986_TYPE0_PIN(22, "PWM1"),
> +	MT7986_TYPE0_PIN(23, "SPI0_CLK"),
> +	MT7986_TYPE0_PIN(24, "SPI0_MOSI"),
> +	MT7986_TYPE0_PIN(25, "SPI0_MISO"),
> +	MT7986_TYPE0_PIN(26, "SPI0_CS"),
> +	MT7986_TYPE0_PIN(27, "SPI0_HOLD"),
> +	MT7986_TYPE0_PIN(28, "SPI0_WP"),
> +	MT7986_TYPE0_PIN(29, "SPI1_CLK"),
> +	MT7986_TYPE0_PIN(30, "SPI1_MOSI"),
> +	MT7986_TYPE0_PIN(31, "SPI1_MISO"),
> +	MT7986_TYPE0_PIN(32, "SPI1_CS"),
> +	MT7986_TYPE0_PIN(33, "SPI2_CLK"),
> +	MT7986_TYPE0_PIN(34, "SPI2_MOSI"),
> +	MT7986_TYPE0_PIN(35, "SPI2_MISO"),
> +	MT7986_TYPE0_PIN(36, "SPI2_CS"),
> +	MT7986_TYPE0_PIN(37, "SPI2_HOLD"),
> +	MT7986_TYPE0_PIN(38, "SPI2_WP"),
> +	MT7986_TYPE0_PIN(39, "UART0_RXD"),
> +	MT7986_TYPE0_PIN(40, "UART0_TXD"),
> +	MT7986_TYPE0_PIN(41, "PCIE_PERESET_N"),
> +	MT7986_TYPE0_PIN(42, "UART1_RXD"),
> +	MT7986_TYPE0_PIN(43, "UART1_TXD"),
> +	MT7986_TYPE0_PIN(44, "UART1_CTS"),
> +	MT7986_TYPE0_PIN(45, "UART1_RTS"),
> +	MT7986_TYPE0_PIN(46, "UART2_RXD"),
> +	MT7986_TYPE0_PIN(47, "UART2_TXD"),
> +	MT7986_TYPE0_PIN(48, "UART2_CTS"),
> +	MT7986_TYPE0_PIN(49, "UART2_RTS"),
> +	MT7986_TYPE0_PIN(50, "EMMC_DATA_0"),
> +	MT7986_TYPE0_PIN(51, "EMMC_DATA_1"),
> +	MT7986_TYPE0_PIN(52, "EMMC_DATA_2"),
> +	MT7986_TYPE0_PIN(53, "EMMC_DATA_3"),
> +	MT7986_TYPE0_PIN(54, "EMMC_DATA_4"),
> +	MT7986_TYPE0_PIN(55, "EMMC_DATA_5"),
> +	MT7986_TYPE0_PIN(56, "EMMC_DATA_6"),
> +	MT7986_TYPE0_PIN(57, "EMMC_DATA_7"),
> +	MT7986_TYPE0_PIN(58, "EMMC_CMD"),
> +	MT7986_TYPE0_PIN(59, "EMMC_CK"),
> +	MT7986_TYPE0_PIN(60, "EMMC_DSL"),
> +	MT7986_TYPE0_PIN(61, "EMMC_RSTB"),
> +	MT7986_TYPE0_PIN(62, "PCM_DTX"),
> +	MT7986_TYPE0_PIN(63, "PCM_DRX"),
> +	MT7986_TYPE0_PIN(64, "PCM_CLK"),
> +	MT7986_TYPE0_PIN(65, "PCM_FS"),
> +	MT7986_TYPE0_PIN(66, "MT7531_INT"),
> +	MT7986_TYPE0_PIN(67, "SMI_MDC"),
> +	MT7986_TYPE0_PIN(68, "SMI_MDIO"),
> +	MT7986_TYPE1_PIN(69, "WF0_DIG_RESETB"),
> +	MT7986_TYPE1_PIN(70, "WF0_CBA_RESETB"),
> +	MT7986_TYPE1_PIN(71, "WF0_XO_REQ"),
> +	MT7986_TYPE1_PIN(72, "WF0_TOP_CLK"),
> +	MT7986_TYPE1_PIN(73, "WF0_TOP_DATA"),
> +	MT7986_TYPE1_PIN(74, "WF0_HB1"),
> +	MT7986_TYPE1_PIN(75, "WF0_HB2"),
> +	MT7986_TYPE1_PIN(76, "WF0_HB3"),
> +	MT7986_TYPE1_PIN(77, "WF0_HB4"),
> +	MT7986_TYPE1_PIN(78, "WF0_HB0"),
> +	MT7986_TYPE1_PIN(79, "WF0_HB0_B"),
> +	MT7986_TYPE1_PIN(80, "WF0_HB5"),
> +	MT7986_TYPE1_PIN(81, "WF0_HB6"),
> +	MT7986_TYPE1_PIN(82, "WF0_HB7"),
> +	MT7986_TYPE1_PIN(83, "WF0_HB8"),
> +	MT7986_TYPE1_PIN(84, "WF0_HB9"),
> +	MT7986_TYPE1_PIN(85, "WF0_HB10"),
> +	MT7986_TYPE1_PIN(86, "WF1_DIG_RESETB"),
> +	MT7986_TYPE1_PIN(87, "WF1_CBA_RESETB"),
> +	MT7986_TYPE1_PIN(88, "WF1_XO_REQ"),
> +	MT7986_TYPE1_PIN(89, "WF1_TOP_CLK"),
> +	MT7986_TYPE1_PIN(90, "WF1_TOP_DATA"),
> +	MT7986_TYPE1_PIN(91, "WF1_HB1"),
> +	MT7986_TYPE1_PIN(92, "WF1_HB2"),
> +	MT7986_TYPE1_PIN(93, "WF1_HB3"),
> +	MT7986_TYPE1_PIN(94, "WF1_HB4"),
> +	MT7986_TYPE1_PIN(95, "WF1_HB0"),
> +	MT7986_TYPE1_PIN(96, "WF1_HB0_B"),
> +	MT7986_TYPE1_PIN(97, "WF1_HB5"),
> +	MT7986_TYPE1_PIN(98, "WF1_HB6"),
> +	MT7986_TYPE1_PIN(99, "WF1_HB7"),
> +	MT7986_TYPE1_PIN(100, "WF1_HB8"),
> +};
> +
> +static const struct mtk_io_type_desc mt7986_io_type_desc[] = {
> +	[IO_TYPE_GRP0] = {
> +		.name = "18OD33",
> +		.bias_set = mtk_pinconf_bias_set_pupd_r1_r0,
> +		.drive_set = mtk_pinconf_drive_set_v1,
> +		.input_enable = mtk_pinconf_input_enable_v1,
> +	},
> +	[IO_TYPE_GRP1] = {
> +		.name = "18A01",
> +		.bias_set = mtk_pinconf_bias_set_pu_pd,
> +		.drive_set = mtk_pinconf_drive_set_v1,
> +		.input_enable = mtk_pinconf_input_enable_v1,
> +	},
> +};
> +
> +/* List all groups consisting of these pins dedicated to the enablement of
> + * certain hardware block and the corresponding mode for all of the pins.
> + * The hardware probably has multiple combinations of these pinouts.
> + */
> +
> +static int mt7986_watchdog_pins[] = { 0, };
> +static int mt7986_watchdog_funcs[] = { 1, };
> +
> +static int mt7986_wifi_led_pins[] = { 1, 2, };
> +static int mt7986_wifi_led_funcs[] = { 1, 1, };
> +
> +static int mt7986_i2c_pins[] = { 3, 4, };
> +static int mt7986_i2c_funcs[] = { 1, 1, };
> +
> +static int mt7986_uart1_0_pins[] = { 7, 8, 9, 10, };
> +static int mt7986_uart1_0_funcs[] = { 3, 3, 3, 3, };
> +
> +static int mt7986_spi1_0_pins[] = { 11, 12, 13, 14, };
> +static int mt7986_spi1_0_funcs[] = { 3, 3, 3, 3, };
> +
> +static int mt7986_pwm1_1_pins[] = { 20, };
> +static int mt7986_pwm1_1_funcs[] = { 2, };
> +
> +static int mt7986_pwm0_pins[] = { 21, };
> +static int mt7986_pwm0_funcs[] = { 1, };
> +
> +static int mt7986_pwm1_0_pins[] = { 22, };
> +static int mt7986_pwm1_0_funcs[] = { 1, };
> +
> +static int mt7986_emmc_45_pins[] = {
> +	22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, };
> +static int mt7986_emmc_45_funcs[] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, };
> +
> +static int mt7986_snfi_pins[] = { 23, 24, 25, 26, 27, 28, };
> +static int mt7986_snfi_funcs[] = { 1, 1, 1, 1, 1, 1, };
> +
> +static int mt7986_spi1_1_pins[] = { 23, 24, 25, 26, };
> +static int mt7986_spi1_1_funcs[] = { 3, 3, 3, 3, };
> +
> +static int mt7986_uart1_1_pins[] = { 23, 24, 25, 26, };
> +static int mt7986_uart1_1_funcs[] = { 4, 4, 4, 4, };
> +
> +static int mt7986_spi1_2_pins[] = { 29, 30, 31, 32, };
> +static int mt7986_spi1_2_funcs[] = { 1, 1, 1, 1, };
> +
> +static int mt7986_uart1_2_pins[] = { 29, 30, 31, 32, };
> +static int mt7986_uart1_2_funcs[] = { 3, 3, 3, 3, };
> +
> +static int mt7986_uart2_0_pins[] = { 29, 30, 31, 32, };
> +static int mt7986_uart2_0_funcs[] = { 4, 4, 4, 4, };
> +
> +static int mt7986_spi0_pins[] = { 33, 34, 35, 36, };
> +static int mt7986_spi0_funcs[] = { 1, 1, 1, 1, };
> +
> +static int mt7986_spi0_wp_hold_pins[] = { 37, 38, };
> +static int mt7986_spi0_wp_hold_funcs[] = { 1, 1, };
> +
> +static int mt7986_uart2_1_pins[] = { 33, 34, 35, 36, };
> +static int mt7986_uart2_1_funcs[] = { 3, 3, 3, 3, };
> +
> +static int mt7986_uart1_3_rx_tx_pins[] = { 35, 36, };
> +static int mt7986_uart1_3_rx_tx_funcs[] = { 2, 2, };
> +
> +static int mt7986_uart1_3_cts_rts_pins[] = { 37, 38, };
> +static int mt7986_uart1_3_cts_rts_funcs[] = { 2, 2, };
> +
> +static int mt7986_spi1_3_pins[] = { 33, 34, 35, 36, };
> +static int mt7986_spi1_3_funcs[] = { 4, 4, 4, 4, };
> +
> +static int mt7986_uart0_pins[] = { 39, 40, };
> +static int mt7986_uart0_funcs[] = { 1, 1, };
> +
> +static int mt7986_pcie_reset_pins[] = { 41, };
> +static int mt7986_pcie_reset_funcs[] = { 1, };
> +
> +static int mt7986_uart1_pins[] = { 42, 43, 44, 45, };
> +static int mt7986_uart1_funcs[] = { 1, 1, 1, 1, };
> +
> +static int mt7986_uart2_pins[] = { 46, 47, 48, 49, };
> +static int mt7986_uart2_funcs[] = { 1, 1, 1, 1, };
> +
> +static int mt7986_emmc_51_pins[] = {
> +	50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, };
> +static int mt7986_emmc_51_funcs[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, };
> +
> +static int mt7986_pcm_pins[] = { 62, 63, 64, 65, };
> +static int mt7986_pcm_funcs[] = { 1, 1, 1, 1, };
> +
> +static int mt7986_i2s_pins[] = { 62, 63, 64, 65, };
> +static int mt7986_i2s_funcs[] = { 1, 1, 1, 1, };
> +
> +static int mt7986_switch_int_pins[] = { 66, };
> +static int mt7986_switch_int_funcs[] = { 1, };
> +
> +static int mt7986_mdc_mdio_pins[] = { 67, 68, };
> +static int mt7986_mdc_mdio_funcs[] = { 1, 1, };
> +
> +static int mt7986_wf_2g_pins[] = {74, 75, 76, 77, 78, 79, 80, 81, 82, 83, };
> +static int mt7986_wf_2g_funcs[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, };
> +
> +static int mt7986_wf_5g_pins[] = {91, 92, 93, 94, 95, 96, 97, 98, 99, 100, };
> +static int mt7986_wf_5g_funcs[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, };
> +
> +static int mt7986_wf_dbdc_pins[] = {
> +	74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, };
> +static int mt7986_wf_dbdc_funcs[] = {
> +	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, };
> +
> +static int mt7986_pcie_clk_pins[] = { 9, };
> +static int mt7986_pcie_clk_funcs[] = { 1, };
> +
> +static int mt7986_pcie_wake_pins[] = { 10, };
> +static int mt7986_pcie_wake_funcs[] = { 1, };
> +
> +static const struct mtk_group_desc mt7986_groups[] = {
> +	PINCTRL_PIN_GROUP("watchdog", mt7986_watchdog),
> +	PINCTRL_PIN_GROUP("wifi_led", mt7986_wifi_led),
> +	PINCTRL_PIN_GROUP("i2c", mt7986_i2c),
> +	PINCTRL_PIN_GROUP("uart1_0", mt7986_uart1_0),
> +	PINCTRL_PIN_GROUP("pcie_clk", mt7986_pcie_clk),
> +	PINCTRL_PIN_GROUP("pcie_wake", mt7986_pcie_wake),
> +	PINCTRL_PIN_GROUP("spi1_0", mt7986_spi1_0),
> +	PINCTRL_PIN_GROUP("pwm1_1", mt7986_pwm1_1),
> +	PINCTRL_PIN_GROUP("pwm0", mt7986_pwm0),
> +	PINCTRL_PIN_GROUP("pwm1_0", mt7986_pwm1_0),
> +	PINCTRL_PIN_GROUP("emmc_45", mt7986_emmc_45),
> +	PINCTRL_PIN_GROUP("snfi", mt7986_snfi),
> +	PINCTRL_PIN_GROUP("spi1_1", mt7986_spi1_1),
> +	PINCTRL_PIN_GROUP("uart1_1", mt7986_uart1_1),
> +	PINCTRL_PIN_GROUP("spi1_2", mt7986_spi1_2),
> +	PINCTRL_PIN_GROUP("uart1_2", mt7986_uart1_2),
> +	PINCTRL_PIN_GROUP("uart2_0", mt7986_uart2_0),
> +	PINCTRL_PIN_GROUP("spi0", mt7986_spi0),
> +	PINCTRL_PIN_GROUP("spi0_wp_hold", mt7986_spi0_wp_hold),
> +	PINCTRL_PIN_GROUP("uart2_1", mt7986_uart2_1),
> +	PINCTRL_PIN_GROUP("uart1_3_rx_tx", mt7986_uart1_3_rx_tx),
> +	PINCTRL_PIN_GROUP("uart1_3_cts_rts", mt7986_uart1_3_cts_rts),
> +	PINCTRL_PIN_GROUP("spi1_3", mt7986_spi1_3),
> +	PINCTRL_PIN_GROUP("uart0", mt7986_uart0),
> +	PINCTRL_PIN_GROUP("switch_int", mt7986_switch_int),
> +	PINCTRL_PIN_GROUP("mdc_mdio", mt7986_mdc_mdio),
> +	PINCTRL_PIN_GROUP("pcie_pereset", mt7986_pcie_reset),
> +	PINCTRL_PIN_GROUP("uart1", mt7986_uart1),
> +	PINCTRL_PIN_GROUP("uart2", mt7986_uart2),
> +	PINCTRL_PIN_GROUP("emmc_51", mt7986_emmc_51),
> +	PINCTRL_PIN_GROUP("pcm", mt7986_pcm),
> +	PINCTRL_PIN_GROUP("i2s", mt7986_i2s),
> +	PINCTRL_PIN_GROUP("wf_2g", mt7986_wf_2g),
> +	PINCTRL_PIN_GROUP("wf_5g", mt7986_wf_5g),
> +	PINCTRL_PIN_GROUP("wf_dbdc", mt7986_wf_dbdc),
> +};
> +
> +/* Joint those groups owning the same capability in user point of view which
> + * allows that people tend to use through the device tree.
> + */
> +
> +static const char *const mt7986_audio_groups[] = { "pcm", "i2s" };
> +static const char *const mt7986_emmc_groups[] = { "emmc_45", "emmc_51", };
> +static const char *const mt7986_ethernet_groups[] = { "switch_int",
> +	"mdc_mdio", };
> +static const char *const mt7986_i2c_groups[] = { "i2c", };
> +static const char *const mt7986_led_groups[] = { "wifi_led", };
> +static const char *const mt7986_flash_groups[] = { "snfi", };
> +static const char *const mt7986_pcie_groups[] = { "pcie_clk", "pcie_wake",
> +	"pcie_pereset" };
> +static const char *const mt7986_pwm_groups[] = { "pwm0", "pwm1_0", "pwm1_1", };
> +static const char *const mt7986_spi_groups[] = { "spi0", "spi0_wp_hold",
> +	"spi1_0", "spi1_1", "spi1_2", "spi1_3", };
> +static const char *const mt7986_uart_groups[] = { "uart1_0", "uart1_1",
> +	"uart1_2", "uart1_3_rx_tx", "uart1_3_cts_rts", "uart2_0", "uart2_1",
> +	"uart0", "uart1", "uart2", };
> +static const char *const mt7986_wdt_groups[] = { "watchdog", };
> +static const char *const mt7986_wf_groups[] = { "wf_2g", "wf_5g", "wf_dbdc", };
> +
> +static const struct mtk_function_desc mt7986_functions[] = {
> +	{"audio", mt7986_audio_groups, ARRAY_SIZE(mt7986_audio_groups)},
> +	{"emmc", mt7986_emmc_groups, ARRAY_SIZE(mt7986_emmc_groups)},
> +	{"eth", mt7986_ethernet_groups, ARRAY_SIZE(mt7986_ethernet_groups)},
> +	{"i2c", mt7986_i2c_groups, ARRAY_SIZE(mt7986_i2c_groups)},
> +	{"led", mt7986_led_groups, ARRAY_SIZE(mt7986_led_groups)},
> +	{"flash", mt7986_flash_groups, ARRAY_SIZE(mt7986_flash_groups)},
> +	{"pcie", mt7986_pcie_groups, ARRAY_SIZE(mt7986_pcie_groups)},
> +	{"pwm", mt7986_pwm_groups, ARRAY_SIZE(mt7986_pwm_groups)},
> +	{"spi", mt7986_spi_groups, ARRAY_SIZE(mt7986_spi_groups)},
> +	{"uart", mt7986_uart_groups, ARRAY_SIZE(mt7986_uart_groups)},
> +	{"watchdog", mt7986_wdt_groups, ARRAY_SIZE(mt7986_wdt_groups)},
> +	{"wifi", mt7986_wf_groups, ARRAY_SIZE(mt7986_wf_groups)},
> +};
> +
> +static struct mtk_pinctrl_soc mt7986_data = {
> +	.name = "mt7986_pinctrl",
> +	.reg_cal = mt7986_reg_cals,
> +	.pins = mt7986_pins,
> +	.npins = ARRAY_SIZE(mt7986_pins),
> +	.grps = mt7986_groups,
> +	.ngrps = ARRAY_SIZE(mt7986_groups),
> +	.funcs = mt7986_functions,
> +	.nfuncs = ARRAY_SIZE(mt7986_functions),
> +	.io_type = mt7986_io_type_desc,
> +	.ntype = ARRAY_SIZE(mt7986_io_type_desc),
> +	.gpio_mode = 0,
> +	.base_names = mt7986_pinctrl_register_base_names,
> +	.nbase_names = ARRAY_SIZE(mt7986_pinctrl_register_base_names),
> +	.base_calc = 1,
> +};
> +
> +static int mtk_pinctrl_mt7986_probe(struct udevice *dev)
> +{
> +	return mtk_pinctrl_common_probe(dev, &mt7986_data);
> +}
> +
> +static const struct udevice_id mt7986_pctrl_match[] = {
> +	{.compatible = "mediatek,mt7986-pinctrl"},
> +	{ /* sentinel */ }
> +};
> +
> +U_BOOT_DRIVER(mt7986_pinctrl) = {
> +	.name = "mt7986_pinctrl",
> +	.id = UCLASS_PINCTRL,
> +	.of_match = mt7986_pctrl_match,
> +	.ops = &mtk_pinctrl_ops,
> +	.probe = mtk_pinctrl_mt7986_probe,
> +	.priv_auto = sizeof(struct mtk_pinctrl_priv),
> +};
> -- 
> 2.17.1
> 

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

* Re: [PATCH v2 22/32] clk: mediatek: add CLK_BYPASS_XTAL flag to allow bypassing searching clock parent of xtal clock
  2022-08-31 11:04 ` [PATCH v2 22/32] clk: mediatek: add CLK_BYPASS_XTAL flag to allow bypassing searching clock parent of xtal clock Weijie Gao
@ 2022-09-01  0:26   ` Daniel Golle
  0 siblings, 0 replies; 60+ messages in thread
From: Daniel Golle @ 2022-09-01  0:26 UTC (permalink / raw)
  To: Weijie Gao; +Cc: u-boot, GSS_MTK_Uboot_upstream, Lukasz Majewski, Sean Anderson

On Wed, Aug 31, 2022 at 07:04:59PM +0800, Weijie Gao wrote:
> The mtk clock framework in u-boot uses array index for searching clock
> parent (kernel uses strings for search), so we need to specify a special
> clock with ID=0 for CLK_XTAL in u-boot.
> 
> In the mt7622/mt7629 clock tree, the clocks with ID=0 never call
> mtk_topckgen_get_mux_rate, adn return xtal clock directly. This what we
> expected.
> 
> However for newer chips, they may have some clocks with ID=0 not
> representing the xtal clock and still needs mtk_topckgen_get_mux_rate be
> called. Current logic will make entire clock driver not working.
> 
> This patch adds a flag to indicate that whether a clock driver needs clocks
> with ID=0 to call mtk_topckgen_get_mux_rate.

Tested on Bananapi BPi-R3 (MT7986A).

Tested-by: Daniel Golle <daniel@makrotopia.org>

> 
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
> ---
> v2 changes:
>   Add comment for flags
>   Fix the if condition of CLK_BYPASS_XTAL
> ---
>  drivers/clk/mediatek/clk-mtk.c | 4 +++-
>  drivers/clk/mediatek/clk-mtk.h | 6 ++++++
>  2 files changed, 9 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c
> index d43b8a0648..7d145f4975 100644
> --- a/drivers/clk/mediatek/clk-mtk.c
> +++ b/drivers/clk/mediatek/clk-mtk.c
> @@ -319,7 +319,9 @@ static ulong mtk_topckgen_get_mux_rate(struct clk *clk, u32 off)
>  	index &= mux->mux_mask << mux->mux_shift;
>  	index = index >> mux->mux_shift;
>  
> -	if (mux->parent[index])
> +	if (mux->parent[index] > 0 ||
> +	    (mux->parent[index] == CLK_XTAL &&
> +	     priv->tree->flags & CLK_BYPASS_XTAL))
>  		return mtk_clk_find_parent_rate(clk, mux->parent[index],
>  						NULL);
>  
> diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
> index 95a23d14a8..e0c5550c80 100644
> --- a/drivers/clk/mediatek/clk-mtk.h
> +++ b/drivers/clk/mediatek/clk-mtk.h
> @@ -11,6 +11,11 @@
>  #define CLK_XTAL			0
>  #define MHZ				(1000 * 1000)
>  
> +/* flags in struct mtk_clk_tree */
> +
> +/* clk id == 0 doesn't mean it's xtal clk */
> +#define CLK_BYPASS_XTAL			BIT(0)
> +
>  #define HAVE_RST_BAR			BIT(0)
>  #define CLK_DOMAIN_SCPSYS		BIT(0)
>  #define CLK_MUX_SETCLR_UPD		BIT(1)
> @@ -197,6 +202,7 @@ struct mtk_clk_tree {
>  	const struct mtk_fixed_clk *fclks;
>  	const struct mtk_fixed_factor *fdivs;
>  	const struct mtk_composite *muxes;
> +	u32 flags;
>  };
>  
>  struct mtk_clk_priv {
> -- 
> 2.17.1
> 

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

* Re: [PATCH v2 23/32] clk: mediatek: add support to configure clock driver parent
  2022-08-31 11:05 ` [PATCH v2 23/32] clk: mediatek: add support to configure clock driver parent Weijie Gao
@ 2022-09-01  0:27   ` Daniel Golle
  0 siblings, 0 replies; 60+ messages in thread
From: Daniel Golle @ 2022-09-01  0:27 UTC (permalink / raw)
  To: Weijie Gao; +Cc: u-boot, GSS_MTK_Uboot_upstream, Lukasz Majewski, Sean Anderson

On Wed, Aug 31, 2022 at 07:05:06PM +0800, Weijie Gao wrote:
> This patch adds support for a clock node to configure its parent clock
> where possible.

Tested on Bananapi BPi-R3 (MT7986A).

Tested-by: Daniel Golle <daniel@makrotopia.org>

> 
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
> ---
> v2 changes: none
> ---
>  drivers/clk/mediatek/clk-mtk.c | 79 ++++++++++++++++++++--------------
>  drivers/clk/mediatek/clk-mtk.h |  2 +
>  2 files changed, 48 insertions(+), 33 deletions(-)
> 
> diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c
> index 7d145f4975..a537ff259f 100644
> --- a/drivers/clk/mediatek/clk-mtk.c
> +++ b/drivers/clk/mediatek/clk-mtk.c
> @@ -42,20 +42,14 @@
>   * the accurate frequency.
>   */
>  static ulong mtk_clk_find_parent_rate(struct clk *clk, int id,
> -				      const struct driver *drv)
> +				      struct udevice *pdev)
>  {
>  	struct clk parent = { .id = id, };
>  
> -	if (drv) {
> -		struct udevice *dev;
> -
> -		if (uclass_get_device_by_driver(UCLASS_CLK, drv, &dev))
> -			return -ENODEV;
> -
> -		parent.dev = dev;
> -	} else {
> +	if (pdev)
> +		parent.dev = pdev;
> +	else
>  		parent.dev = clk->dev;
> -	}
>  
>  	return clk_get_rate(&parent);
>  }
> @@ -296,7 +290,7 @@ static ulong mtk_topckgen_get_factor_rate(struct clk *clk, u32 off)
>  	switch (fdiv->flags & CLK_PARENT_MASK) {
>  	case CLK_PARENT_APMIXED:
>  		rate = mtk_clk_find_parent_rate(clk, fdiv->parent,
> -				DM_DRIVER_GET(mtk_clk_apmixedsys));
> +						priv->parent);
>  		break;
>  	case CLK_PARENT_TOPCKGEN:
>  		rate = mtk_clk_find_parent_rate(clk, fdiv->parent, NULL);
> @@ -321,9 +315,18 @@ static ulong mtk_topckgen_get_mux_rate(struct clk *clk, u32 off)
>  
>  	if (mux->parent[index] > 0 ||
>  	    (mux->parent[index] == CLK_XTAL &&
> -	     priv->tree->flags & CLK_BYPASS_XTAL))
> -		return mtk_clk_find_parent_rate(clk, mux->parent[index],
> -						NULL);
> +	     priv->tree->flags & CLK_BYPASS_XTAL)) {
> +		switch (mux->flags & CLK_PARENT_MASK) {
> +		case CLK_PARENT_APMIXED:
> +			return mtk_clk_find_parent_rate(clk, mux->parent[index],
> +							priv->parent);
> +			break;
> +		default:
> +			return mtk_clk_find_parent_rate(clk, mux->parent[index],
> +							NULL);
> +			break;
> +		}
> +	}
>  
>  	return priv->tree->xtal_rate;
>  }
> @@ -342,7 +345,7 @@ static ulong mtk_topckgen_get_rate(struct clk *clk)
>  						 priv->tree->muxes_offs);
>  }
>  
> -static int mtk_topckgen_enable(struct clk *clk)
> +static int mtk_clk_mux_enable(struct clk *clk)
>  {
>  	struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
>  	const struct mtk_composite *mux;
> @@ -375,7 +378,7 @@ static int mtk_topckgen_enable(struct clk *clk)
>  	return 0;
>  }
>  
> -static int mtk_topckgen_disable(struct clk *clk)
> +static int mtk_clk_mux_disable(struct clk *clk)
>  {
>  	struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
>  	const struct mtk_composite *mux;
> @@ -401,7 +404,7 @@ static int mtk_topckgen_disable(struct clk *clk)
>  	return 0;
>  }
>  
> -static int mtk_topckgen_set_parent(struct clk *clk, struct clk *parent)
> +static int mtk_common_clk_set_parent(struct clk *clk, struct clk *parent)
>  {
>  	struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
>  
> @@ -473,19 +476,7 @@ static ulong mtk_clk_gate_get_rate(struct clk *clk)
>  	struct mtk_cg_priv *priv = dev_get_priv(clk->dev);
>  	const struct mtk_gate *gate = &priv->gates[clk->id];
>  
> -	switch (gate->flags & CLK_PARENT_MASK) {
> -	case CLK_PARENT_APMIXED:
> -		return mtk_clk_find_parent_rate(clk, gate->parent,
> -				DM_DRIVER_GET(mtk_clk_apmixedsys));
> -		break;
> -	case CLK_PARENT_TOPCKGEN:
> -		return mtk_clk_find_parent_rate(clk, gate->parent,
> -				DM_DRIVER_GET(mtk_clk_topckgen));
> -		break;
> -
> -	default:
> -		return priv->tree->xtal_rate;
> -	}
> +	return mtk_clk_find_parent_rate(clk, gate->parent, priv->parent);
>  }
>  
>  const struct clk_ops mtk_clk_apmixedsys_ops = {
> @@ -496,10 +487,10 @@ const struct clk_ops mtk_clk_apmixedsys_ops = {
>  };
>  
>  const struct clk_ops mtk_clk_topckgen_ops = {
> -	.enable = mtk_topckgen_enable,
> -	.disable = mtk_topckgen_disable,
> +	.enable = mtk_clk_mux_enable,
> +	.disable = mtk_clk_mux_disable,
>  	.get_rate = mtk_topckgen_get_rate,
> -	.set_parent = mtk_topckgen_set_parent,
> +	.set_parent = mtk_common_clk_set_parent,
>  };
>  
>  const struct clk_ops mtk_clk_gate_ops = {
> @@ -512,11 +503,22 @@ int mtk_common_clk_init(struct udevice *dev,
>  			const struct mtk_clk_tree *tree)
>  {
>  	struct mtk_clk_priv *priv = dev_get_priv(dev);
> +	struct udevice *parent;
> +	int ret;
>  
>  	priv->base = dev_read_addr_ptr(dev);
>  	if (!priv->base)
>  		return -ENOENT;
>  
> +	ret = uclass_get_device_by_phandle(UCLASS_CLK, dev, "clock-parent", &parent);
> +	if (ret || !parent) {
> +		ret = uclass_get_device_by_driver(UCLASS_CLK,
> +				DM_DRIVER_GET(mtk_clk_apmixedsys), &parent);
> +		if (ret || !parent)
> +			return -ENOENT;
> +	}
> +
> +	priv->parent = parent;
>  	priv->tree = tree;
>  
>  	return 0;
> @@ -527,11 +529,22 @@ int mtk_common_clk_gate_init(struct udevice *dev,
>  			     const struct mtk_gate *gates)
>  {
>  	struct mtk_cg_priv *priv = dev_get_priv(dev);
> +	struct udevice *parent;
> +	int ret;
>  
>  	priv->base = dev_read_addr_ptr(dev);
>  	if (!priv->base)
>  		return -ENOENT;
>  
> +	ret = uclass_get_device_by_phandle(UCLASS_CLK, dev, "clock-parent", &parent);
> +	if (ret || !parent) {
> +		ret = uclass_get_device_by_driver(UCLASS_CLK,
> +				DM_DRIVER_GET(mtk_clk_topckgen), &parent);
> +		if (ret || !parent)
> +			return -ENOENT;
> +	}
> +
> +	priv->parent = parent;
>  	priv->tree = tree;
>  	priv->gates = gates;
>  
> diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
> index e0c5550c80..41854879c6 100644
> --- a/drivers/clk/mediatek/clk-mtk.h
> +++ b/drivers/clk/mediatek/clk-mtk.h
> @@ -206,11 +206,13 @@ struct mtk_clk_tree {
>  };
>  
>  struct mtk_clk_priv {
> +	struct udevice *parent;
>  	void __iomem *base;
>  	const struct mtk_clk_tree *tree;
>  };
>  
>  struct mtk_cg_priv {
> +	struct udevice *parent;
>  	void __iomem *base;
>  	const struct mtk_clk_tree *tree;
>  	const struct mtk_gate *gates;
> -- 
> 2.17.1
> 

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

* Re: [PATCH v2 24/32] clk: mediatek: add infrasys clock mux support
  2022-08-31 11:05 ` [PATCH v2 24/32] clk: mediatek: add infrasys clock mux support Weijie Gao
@ 2022-09-01  0:27   ` Daniel Golle
  0 siblings, 0 replies; 60+ messages in thread
From: Daniel Golle @ 2022-09-01  0:27 UTC (permalink / raw)
  To: Weijie Gao; +Cc: u-boot, GSS_MTK_Uboot_upstream, Lukasz Majewski, Sean Anderson

On Wed, Aug 31, 2022 at 07:05:09PM +0800, Weijie Gao wrote:
> This patch adds infrasys clock mux support for mediatek clock drivers.

Tested on Bananapi BPi-R3 (MT7986A).

Tested-by: Daniel Golle <daniel@makrotopia.org>

> 
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
> ---
> v2 changes:
>   Fix the if condition of CLK_BYPASS_XTAL
> ---
>  drivers/clk/mediatek/clk-mtk.c | 71 ++++++++++++++++++++++++++++++++++
>  drivers/clk/mediatek/clk-mtk.h |  4 +-
>  2 files changed, 74 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c
> index a537ff259f..207a4c6b11 100644
> --- a/drivers/clk/mediatek/clk-mtk.c
> +++ b/drivers/clk/mediatek/clk-mtk.c
> @@ -303,6 +303,24 @@ static ulong mtk_topckgen_get_factor_rate(struct clk *clk, u32 off)
>  	return mtk_factor_recalc_rate(fdiv, rate);
>  }
>  
> +static ulong mtk_infrasys_get_factor_rate(struct clk *clk, u32 off)
> +{
> +	struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
> +	const struct mtk_fixed_factor *fdiv = &priv->tree->fdivs[off];
> +	ulong rate;
> +
> +	switch (fdiv->flags & CLK_PARENT_MASK) {
> +	case CLK_PARENT_TOPCKGEN:
> +		rate = mtk_clk_find_parent_rate(clk, fdiv->parent,
> +						priv->parent);
> +		break;
> +	default:
> +		rate = mtk_clk_find_parent_rate(clk, fdiv->parent, NULL);
> +	}
> +
> +	return mtk_factor_recalc_rate(fdiv, rate);
> +}
> +
>  static ulong mtk_topckgen_get_mux_rate(struct clk *clk, u32 off)
>  {
>  	struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
> @@ -331,6 +349,33 @@ static ulong mtk_topckgen_get_mux_rate(struct clk *clk, u32 off)
>  	return priv->tree->xtal_rate;
>  }
>  
> +static ulong mtk_infrasys_get_mux_rate(struct clk *clk, u32 off)
> +{
> +	struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
> +	const struct mtk_composite *mux = &priv->tree->muxes[off];
> +	u32 index;
> +
> +	index = readl(priv->base + mux->mux_reg);
> +	index &= mux->mux_mask << mux->mux_shift;
> +	index = index >> mux->mux_shift;
> +
> +	if (mux->parent[index] > 0 ||
> +	    (mux->parent[index] == CLK_XTAL &&
> +	     priv->tree->flags & CLK_BYPASS_XTAL)) {
> +		switch (mux->flags & CLK_PARENT_MASK) {
> +		case CLK_PARENT_TOPCKGEN:
> +			return mtk_clk_find_parent_rate(clk, mux->parent[index],
> +							priv->parent);
> +			break;
> +		default:
> +			return mtk_clk_find_parent_rate(clk, mux->parent[index],
> +							NULL);
> +			break;
> +		}
> +	}
> +	return 0;
> +}
> +
>  static ulong mtk_topckgen_get_rate(struct clk *clk)
>  {
>  	struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
> @@ -345,6 +390,25 @@ static ulong mtk_topckgen_get_rate(struct clk *clk)
>  						 priv->tree->muxes_offs);
>  }
>  
> +static ulong mtk_infrasys_get_rate(struct clk *clk)
> +{
> +	struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
> +
> +	ulong rate;
> +
> +	if (clk->id < priv->tree->fdivs_offs) {
> +		rate = priv->tree->fclks[clk->id].rate;
> +	} else if (clk->id < priv->tree->muxes_offs) {
> +		rate = mtk_infrasys_get_factor_rate(clk, clk->id -
> +						    priv->tree->fdivs_offs);
> +	} else {
> +		rate = mtk_infrasys_get_mux_rate(clk, clk->id -
> +						 priv->tree->muxes_offs);
> +	}
> +
> +	return rate;
> +}
> +
>  static int mtk_clk_mux_enable(struct clk *clk)
>  {
>  	struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
> @@ -493,6 +557,13 @@ const struct clk_ops mtk_clk_topckgen_ops = {
>  	.set_parent = mtk_common_clk_set_parent,
>  };
>  
> +const struct clk_ops mtk_clk_infrasys_ops = {
> +	.enable = mtk_clk_mux_enable,
> +	.disable = mtk_clk_mux_disable,
> +	.get_rate = mtk_infrasys_get_rate,
> +	.set_parent = mtk_common_clk_set_parent,
> +};
> +
>  const struct clk_ops mtk_clk_gate_ops = {
>  	.enable = mtk_clk_gate_enable,
>  	.disable = mtk_clk_gate_disable,
> diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
> index 41854879c6..e7c61ae483 100644
> --- a/drivers/clk/mediatek/clk-mtk.h
> +++ b/drivers/clk/mediatek/clk-mtk.h
> @@ -28,7 +28,8 @@
>  
>  #define CLK_PARENT_APMIXED		BIT(4)
>  #define CLK_PARENT_TOPCKGEN		BIT(5)
> -#define CLK_PARENT_MASK			GENMASK(5, 4)
> +#define CLK_PARENT_INFRASYS		BIT(6)
> +#define CLK_PARENT_MASK			GENMASK(6, 4)
>  
>  #define ETHSYS_HIFSYS_RST_CTRL_OFS	0x34
>  
> @@ -220,6 +221,7 @@ struct mtk_cg_priv {
>  
>  extern const struct clk_ops mtk_clk_apmixedsys_ops;
>  extern const struct clk_ops mtk_clk_topckgen_ops;
> +extern const struct clk_ops mtk_clk_infrasys_ops;
>  extern const struct clk_ops mtk_clk_gate_ops;
>  
>  int mtk_common_clk_init(struct udevice *dev,
> -- 
> 2.17.1
> 

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

* Re: [PATCH v2 25/32] clk: mediatek: add CLK_XTAL support for clock driver
  2022-08-31 11:05 ` [PATCH v2 25/32] clk: mediatek: add CLK_XTAL support for clock driver Weijie Gao
  2022-08-31 13:46   ` Simon Glass
@ 2022-09-01  0:27   ` Daniel Golle
  1 sibling, 0 replies; 60+ messages in thread
From: Daniel Golle @ 2022-09-01  0:27 UTC (permalink / raw)
  To: Weijie Gao; +Cc: u-boot, GSS_MTK_Uboot_upstream, Lukasz Majewski, Sean Anderson

On Wed, Aug 31, 2022 at 07:05:11PM +0800, Weijie Gao wrote:
> This adds the CLK_XTAL macro/flag to allow modeling clocks which are
> directly connected to the xtal clock.

Tested on Bananapi BPi-R3 (MT7986A).

Tested-by: Daniel Golle <daniel@makrotopia.org>

> 
> Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
> ---
> v2 changes:
>   Fix incorrect fallback in mtk_infrasys_get_factor_rate
>   Fix commit description
> ---
>  drivers/clk/mediatek/clk-mtk.c | 4 ++++
>  drivers/clk/mediatek/clk-mtk.h | 3 ++-
>  2 files changed, 6 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c
> index 207a4c6b11..4303300d3a 100644
> --- a/drivers/clk/mediatek/clk-mtk.c
> +++ b/drivers/clk/mediatek/clk-mtk.c
> @@ -296,6 +296,7 @@ static ulong mtk_topckgen_get_factor_rate(struct clk *clk, u32 off)
>  		rate = mtk_clk_find_parent_rate(clk, fdiv->parent, NULL);
>  		break;
>  
> +	case CLK_PARENT_XTAL:
>  	default:
>  		rate = priv->tree->xtal_rate;
>  	}
> @@ -314,6 +315,9 @@ static ulong mtk_infrasys_get_factor_rate(struct clk *clk, u32 off)
>  		rate = mtk_clk_find_parent_rate(clk, fdiv->parent,
>  						priv->parent);
>  		break;
> +	case CLK_PARENT_XTAL:
> +		rate = priv->tree->xtal_rate;
> +		break;
>  	default:
>  		rate = mtk_clk_find_parent_rate(clk, fdiv->parent, NULL);
>  	}
> diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
> index e7c61ae483..48ce16484e 100644
> --- a/drivers/clk/mediatek/clk-mtk.h
> +++ b/drivers/clk/mediatek/clk-mtk.h
> @@ -29,7 +29,8 @@
>  #define CLK_PARENT_APMIXED		BIT(4)
>  #define CLK_PARENT_TOPCKGEN		BIT(5)
>  #define CLK_PARENT_INFRASYS		BIT(6)
> -#define CLK_PARENT_MASK			GENMASK(6, 4)
> +#define CLK_PARENT_XTAL			BIT(7)
> +#define CLK_PARENT_MASK			GENMASK(7, 4)
>  
>  #define ETHSYS_HIFSYS_RST_CTRL_OFS	0x34
>  
> -- 
> 2.17.1
> 

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

* Re: [PATCH v2 26/32] clk: mediatek: add clock driver support for MediaTek MT7986 SoC
  2022-08-31 11:05 ` [PATCH v2 26/32] clk: mediatek: add clock driver support for MediaTek MT7986 SoC Weijie Gao
@ 2022-09-01  0:28   ` Daniel Golle
  0 siblings, 0 replies; 60+ messages in thread
From: Daniel Golle @ 2022-09-01  0:28 UTC (permalink / raw)
  To: Weijie Gao; +Cc: u-boot, GSS_MTK_Uboot_upstream, Lukasz Majewski, Sean Anderson

On Wed, Aug 31, 2022 at 07:05:13PM +0800, Weijie Gao wrote:
> This patch adds clock driver support for MediaTek MT7986 SoC

Tested on Bananapi BPi-R3 (MT7986A).

Tested-by: Daniel Golle <daniel@makrotopia.org>

> 
> Reviewed-by: Sean Anderson <seanga2@gmail.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
> ---
> v2 changes:
>   Fix coding style
> ---
>  drivers/clk/mediatek/Makefile          |   1 +
>  drivers/clk/mediatek/clk-mt7986.c      | 672 +++++++++++++++++++++++++
>  include/dt-bindings/clock/mt7986-clk.h | 249 +++++++++
>  3 files changed, 922 insertions(+)
>  create mode 100644 drivers/clk/mediatek/clk-mt7986.c
>  create mode 100644 include/dt-bindings/clock/mt7986-clk.h
> 
> diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
> index 522e724221..1aa38215bf 100644
> --- a/drivers/clk/mediatek/Makefile
> +++ b/drivers/clk/mediatek/Makefile
> @@ -7,6 +7,7 @@ obj-$(CONFIG_MT8512) += clk-mt8512.o
>  obj-$(CONFIG_TARGET_MT7623) += clk-mt7623.o
>  obj-$(CONFIG_TARGET_MT7622) += clk-mt7622.o
>  obj-$(CONFIG_TARGET_MT7629) += clk-mt7629.o
> +obj-$(CONFIG_TARGET_MT7986) += clk-mt7986.o
>  obj-$(CONFIG_TARGET_MT8183) += clk-mt8183.o
>  obj-$(CONFIG_TARGET_MT8516) += clk-mt8516.o
>  obj-$(CONFIG_TARGET_MT8518) += clk-mt8518.o
> diff --git a/drivers/clk/mediatek/clk-mt7986.c b/drivers/clk/mediatek/clk-mt7986.c
> new file mode 100644
> index 0000000000..b3fa63fc0a
> --- /dev/null
> +++ b/drivers/clk/mediatek/clk-mt7986.c
> @@ -0,0 +1,672 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * MediaTek clock driver for MT7986 SoC
> + *
> + * Copyright (C) 2022 MediaTek Inc.
> + * Author: Sam Shih <sam.shih@mediatek.com>
> + */
> +
> +#include <dm.h>
> +#include <log.h>
> +#include <asm/arch-mediatek/reset.h>
> +#include <asm/io.h>
> +#include <dt-bindings/clock/mt7986-clk.h>
> +#include <linux/bitops.h>
> +
> +#include "clk-mtk.h"
> +
> +#define MT7986_CLK_PDN 0x250
> +#define MT7986_CLK_PDN_EN_WRITE BIT(31)
> +
> +#define PLL_FACTOR(_id, _name, _parent, _mult, _div)                           \
> +	FACTOR(_id, _parent, _mult, _div, CLK_PARENT_APMIXED)
> +
> +#define TOP_FACTOR(_id, _name, _parent, _mult, _div)                           \
> +	FACTOR(_id, _parent, _mult, _div, CLK_PARENT_TOPCKGEN)
> +
> +#define INFRA_FACTOR(_id, _name, _parent, _mult, _div)                         \
> +	FACTOR(_id, _parent, _mult, _div, CLK_PARENT_INFRASYS)
> +
> +/* FIXED PLLS */
> +static const struct mtk_fixed_clk fixed_pll_clks[] = {
> +	FIXED_CLK(CK_APMIXED_ARMPLL, CLK_XTAL, 2000000000),
> +	FIXED_CLK(CK_APMIXED_NET2PLL, CLK_XTAL, 800000000),
> +	FIXED_CLK(CK_APMIXED_MMPLL, CLK_XTAL, 1440000000),
> +	FIXED_CLK(CK_APMIXED_SGMPLL, CLK_XTAL, 325000000),
> +	FIXED_CLK(CK_APMIXED_WEDMCUPLL, CLK_XTAL, 760000000),
> +	FIXED_CLK(CK_APMIXED_NET1PLL, CLK_XTAL, 2500000000),
> +	FIXED_CLK(CK_APMIXED_MPLL, CLK_XTAL, 416000000),
> +	FIXED_CLK(CK_APMIXED_APLL2, CLK_XTAL, 196608000),
> +};
> +
> +/* TOPCKGEN FIXED CLK */
> +static const struct mtk_fixed_clk top_fixed_clks[] = {
> +	FIXED_CLK(CK_TOP_CB_CKSQ_40M, CLK_XTAL, 40000000),
> +};
> +
> +/* TOPCKGEN FIXED DIV */
> +static const struct mtk_fixed_factor top_fixed_divs[] = {
> +	PLL_FACTOR(CK_TOP_CB_M_416M, "cb_m_416m", CK_APMIXED_MPLL, 1, 1),
> +	PLL_FACTOR(CK_TOP_CB_M_D2, "cb_m_d2", CK_APMIXED_MPLL, 1, 2),
> +	PLL_FACTOR(CK_TOP_CB_M_D4, "cb_m_d4", CK_APMIXED_MPLL, 1, 4),
> +	PLL_FACTOR(CK_TOP_CB_M_D8, "cb_m_d8", CK_APMIXED_MPLL, 1, 8),
> +	PLL_FACTOR(CK_TOP_M_D8_D2, "m_d8_d2", CK_APMIXED_MPLL, 1, 16),
> +	PLL_FACTOR(CK_TOP_M_D3_D2, "m_d3_d2", CK_APMIXED_MPLL, 1, 2),
> +	PLL_FACTOR(CK_TOP_CB_MM_D2, "cb_mm_d2", CK_APMIXED_MMPLL, 1, 2),
> +	PLL_FACTOR(CK_TOP_CB_MM_D4, "cb_mm_d4", CK_APMIXED_MMPLL, 1, 4),
> +	PLL_FACTOR(CK_TOP_CB_MM_D8, "cb_mm_d8", CK_APMIXED_MMPLL, 1, 8),
> +	PLL_FACTOR(CK_TOP_MM_D8_D2, "mm_d8_d2", CK_APMIXED_MMPLL, 1, 16),
> +	PLL_FACTOR(CK_TOP_MM_D3_D8, "mm_d3_d8", CK_APMIXED_MMPLL, 1, 8),
> +	PLL_FACTOR(CK_TOP_CB_U2_PHYD_CK, "cb_u2_phyd", CK_APMIXED_MMPLL, 1, 30),
> +	PLL_FACTOR(CK_TOP_CB_APLL2_196M, "cb_apll2_196m", CK_APMIXED_APLL2, 1,
> +		   1),
> +	PLL_FACTOR(CK_TOP_APLL2_D4, "apll2_d4", CK_APMIXED_APLL2, 1, 4),
> +	PLL_FACTOR(CK_TOP_CB_NET1_D4, "cb_net1_d4", CK_APMIXED_NET1PLL, 1, 4),
> +	PLL_FACTOR(CK_TOP_CB_NET1_D5, "cb_net1_d5", CK_APMIXED_NET1PLL, 1, 5),
> +	PLL_FACTOR(CK_TOP_NET1_D5_D2, "net1_d5_d2", CK_APMIXED_NET1PLL, 1, 10),
> +	PLL_FACTOR(CK_TOP_NET1_D5_D4, "net1_d5_d4", CK_APMIXED_NET1PLL, 1, 20),
> +	PLL_FACTOR(CK_TOP_NET1_D8_D2, "net1_d8_d2", CK_APMIXED_NET1PLL, 1, 16),
> +	PLL_FACTOR(CK_TOP_NET1_D8_D4, "net1_d8_d4", CK_APMIXED_NET1PLL, 1, 32),
> +	PLL_FACTOR(CK_TOP_CB_NET2_800M, "cb_net2_800m", CK_APMIXED_NET2PLL, 1,
> +		   1),
> +	PLL_FACTOR(CK_TOP_CB_NET2_D4, "cb_net2_d4", CK_APMIXED_NET2PLL, 1, 4),
> +	PLL_FACTOR(CK_TOP_NET2_D4_D2, "net2_d4_d2", CK_APMIXED_NET2PLL, 1, 8),
> +	PLL_FACTOR(CK_TOP_NET2_D3_D2, "net2_d3_d2", CK_APMIXED_NET2PLL, 1, 2),
> +	PLL_FACTOR(CK_TOP_CB_WEDMCU_760M, "cb_wedmcu_760m",
> +		   CK_APMIXED_WEDMCUPLL, 1, 1),
> +	PLL_FACTOR(CK_TOP_WEDMCU_D5_D2, "wedmcu_d5_d2", CK_APMIXED_WEDMCUPLL, 1,
> +		   10),
> +	PLL_FACTOR(CK_TOP_CB_SGM_325M, "cb_sgm_325m", CK_APMIXED_SGMPLL, 1, 1),
> +	TOP_FACTOR(CK_TOP_CB_CKSQ_40M_D2, "cb_cksq_40m_d2", CK_TOP_CB_CKSQ_40M,
> +		   1, 2),
> +	TOP_FACTOR(CK_TOP_CB_RTC_32K, "cb_rtc_32k", CK_TOP_CB_CKSQ_40M, 1,
> +		   1250),
> +	TOP_FACTOR(CK_TOP_CB_RTC_32P7K, "cb_rtc_32p7k", CK_TOP_CB_CKSQ_40M, 1,
> +		   1220),
> +	TOP_FACTOR(CK_TOP_NFI1X, "nfi1x", CK_TOP_NFI1X_SEL, 1, 1),
> +	TOP_FACTOR(CK_TOP_USB_EQ_RX250M, "usb_eq_rx250m", CK_TOP_CB_CKSQ_40M, 1,
> +		   1),
> +	TOP_FACTOR(CK_TOP_USB_TX250M, "usb_tx250m", CK_TOP_CB_CKSQ_40M, 1, 1),
> +	TOP_FACTOR(CK_TOP_USB_LN0_CK, "usb_ln0", CK_TOP_CB_CKSQ_40M, 1, 1),
> +	TOP_FACTOR(CK_TOP_USB_CDR_CK, "usb_cdr", CK_TOP_CB_CKSQ_40M, 1, 1),
> +	TOP_FACTOR(CK_TOP_SPINFI_BCK, "spinfi_bck", CK_TOP_SPINFI_SEL, 1, 1),
> +	TOP_FACTOR(CK_TOP_I2C_BCK, "i2c_bck", CK_TOP_I2C_SEL, 1, 1),
> +	TOP_FACTOR(CK_TOP_PEXTP_TL, "pextp_tl", CK_TOP_PEXTP_TL_SEL, 1, 1),
> +	TOP_FACTOR(CK_TOP_EMMC_250M, "emmc_250m", CK_TOP_EMMC_250M_SEL, 1, 1),
> +	TOP_FACTOR(CK_TOP_EMMC_416M, "emmc_416m", CK_TOP_EMMC_416M_SEL, 1, 1),
> +	TOP_FACTOR(CK_TOP_F_26M_ADC_CK, "f_26m_adc", CK_TOP_F_26M_ADC_SEL, 1,
> +		   1),
> +	TOP_FACTOR(CK_TOP_SYSAXI, "sysaxi", CK_TOP_SYSAXI_SEL, 1, 1),
> +	TOP_FACTOR(CK_TOP_NETSYS_WED_MCU, "netsys_wed_mcu",
> +		   CK_TOP_NETSYS_MCU_SEL, 1, 1),
> +	TOP_FACTOR(CK_TOP_NETSYS_2X, "netsys_2x", CK_TOP_NETSYS_2X_SEL, 1, 1),
> +	TOP_FACTOR(CK_TOP_SGM_325M, "sgm_325m", CK_TOP_SGM_325M_SEL, 1, 1),
> +	TOP_FACTOR(CK_TOP_A1SYS, "a1sys", CK_TOP_A1SYS_SEL, 1, 1),
> +	TOP_FACTOR(CK_TOP_EIP_B, "eip_b", CK_TOP_EIP_B_SEL, 1, 1),
> +	TOP_FACTOR(CK_TOP_F26M, "csw_f26m", CK_TOP_F26M_SEL, 1, 1),
> +	TOP_FACTOR(CK_TOP_AUD_L, "aud_l", CK_TOP_AUD_L_SEL, 1, 1),
> +	TOP_FACTOR(CK_TOP_A_TUNER, "a_tuner", CK_TOP_A_TUNER_SEL, 2, 1),
> +	TOP_FACTOR(CK_TOP_U2U3_REF, "u2u3_ref", CK_TOP_U2U3_SEL, 1, 1),
> +	TOP_FACTOR(CK_TOP_U2U3_SYS, "u2u3_sys", CK_TOP_U2U3_SYS_SEL, 1, 1),
> +	TOP_FACTOR(CK_TOP_U2U3_XHCI, "u2u3_xhci", CK_TOP_U2U3_XHCI_SEL, 1, 1),
> +	TOP_FACTOR(CK_TOP_AP2CNN_HOST, "ap2cnn_host", CK_TOP_AP2CNN_HOST_SEL, 1,
> +		   1),
> +};
> +
> +/* TOPCKGEN MUX PARENTS */
> +static const int nfi1x_parents[] = { CK_TOP_CB_CKSQ_40M,  CK_TOP_CB_MM_D8,
> +				     CK_TOP_NET1_D8_D2,   CK_TOP_NET2_D3_D2,
> +				     CK_TOP_CB_M_D4,      CK_TOP_MM_D8_D2,
> +				     CK_TOP_WEDMCU_D5_D2, CK_TOP_CB_M_D8 };
> +
> +static const int spinfi_parents[] = {
> +	CK_TOP_CB_CKSQ_40M_D2, CK_TOP_CB_CKSQ_40M, CK_TOP_NET1_D5_D4,
> +	CK_TOP_CB_M_D4,	CK_TOP_MM_D8_D2,    CK_TOP_WEDMCU_D5_D2,
> +	CK_TOP_MM_D3_D8,       CK_TOP_CB_M_D8
> +};
> +
> +static const int spi_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_M_D2,
> +				   CK_TOP_CB_MM_D8,    CK_TOP_NET1_D8_D2,
> +				   CK_TOP_NET2_D3_D2,  CK_TOP_NET1_D5_D4,
> +				   CK_TOP_CB_M_D4,     CK_TOP_WEDMCU_D5_D2 };
> +
> +static const int uart_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_M_D8,
> +				    CK_TOP_M_D8_D2 };
> +
> +static const int pwm_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_NET1_D8_D2,
> +				   CK_TOP_NET1_D5_D4, CK_TOP_CB_M_D4 };
> +
> +static const int i2c_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_NET1_D5_D4,
> +				   CK_TOP_CB_M_D4, CK_TOP_NET1_D8_D4 };
> +
> +static const int pextp_tl_ck_parents[] = { CK_TOP_CB_CKSQ_40M,
> +					   CK_TOP_NET1_D5_D4, CK_TOP_NET2_D4_D2,
> +					   CK_TOP_CB_RTC_32K };
> +
> +static const int emmc_250m_parents[] = { CK_TOP_CB_CKSQ_40M,
> +					 CK_TOP_NET1_D5_D2 };
> +
> +static const int emmc_416m_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_M_416M };
> +
> +static const int f_26m_adc_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_M_D8_D2 };
> +
> +static const int dramc_md32_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_M_D2 };
> +
> +static const int sysaxi_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_NET1_D8_D2,
> +				      CK_TOP_CB_NET2_D4 };
> +
> +static const int sysapb_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_M_D3_D2,
> +				      CK_TOP_NET2_D4_D2 };
> +
> +static const int arm_db_main_parents[] = { CK_TOP_CB_CKSQ_40M,
> +					   CK_TOP_NET2_D3_D2 };
> +
> +static const int arm_db_jtsel_parents[] = { -1, CK_TOP_CB_CKSQ_40M };
> +
> +static const int netsys_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_MM_D4 };
> +
> +static const int netsys_500m_parents[] = { CK_TOP_CB_CKSQ_40M,
> +					   CK_TOP_CB_NET1_D5 };
> +
> +static const int netsys_mcu_parents[] = { CK_TOP_CB_CKSQ_40M,
> +					  CK_TOP_CB_WEDMCU_760M,
> +					  CK_TOP_CB_MM_D2, CK_TOP_CB_NET1_D4,
> +					  CK_TOP_CB_NET1_D5 };
> +
> +static const int netsys_2x_parents[] = { CK_TOP_CB_CKSQ_40M,
> +					 CK_TOP_CB_NET2_800M,
> +					 CK_TOP_CB_WEDMCU_760M,
> +					 CK_TOP_CB_MM_D2 };
> +
> +static const int sgm_325m_parents[] = { CK_TOP_CB_CKSQ_40M,
> +					CK_TOP_CB_SGM_325M };
> +
> +static const int sgm_reg_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_NET1_D8_D4 };
> +
> +static const int a1sys_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_APLL2_D4 };
> +
> +static const int conn_mcusys_parents[] = { CK_TOP_CB_CKSQ_40M,
> +					   CK_TOP_CB_MM_D2 };
> +
> +static const int eip_b_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_NET2_800M };
> +
> +static const int aud_l_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_APLL2_196M,
> +				     CK_TOP_M_D8_D2 };
> +
> +static const int a_tuner_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_APLL2_D4,
> +				       CK_TOP_M_D8_D2 };
> +
> +static const int u2u3_sys_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_NET1_D5_D4 };
> +
> +static const int da_u2_refsel_parents[] = { CK_TOP_CB_CKSQ_40M,
> +					    CK_TOP_CB_U2_PHYD_CK };
> +
> +#define TOP_MUX(_id, _name, _parents, _mux_ofs, _mux_set_ofs, _mux_clr_ofs,    \
> +		_shift, _width, _gate, _upd_ofs, _upd)                         \
> +	{                                                                      \
> +		.id = _id, .mux_reg = _mux_ofs, .mux_set_reg = _mux_set_ofs,   \
> +		.mux_clr_reg = _mux_clr_ofs, .upd_reg = _upd_ofs,              \
> +		.upd_shift = _upd, .mux_shift = _shift,                        \
> +		.mux_mask = BIT(_width) - 1, .gate_reg = _mux_ofs,             \
> +		.gate_shift = _gate, .parent = _parents,                       \
> +		.num_parents = ARRAY_SIZE(_parents),                           \
> +		.flags = CLK_MUX_SETCLR_UPD,                                   \
> +	}
> +
> +/* TOPCKGEN MUX_GATE */
> +static const struct mtk_composite top_muxes[] = {
> +	/* CLK_CFG_0 */
> +	TOP_MUX(CK_TOP_NFI1X_SEL, "nfi1x_sel", nfi1x_parents, 0x000, 0x004,
> +		0x008, 0, 3, 7, 0x1C0, 0),
> +	TOP_MUX(CK_TOP_SPINFI_SEL, "spinfi_sel", spinfi_parents, 0x000, 0x004,
> +		0x008, 8, 3, 15, 0x1C0, 1),
> +	TOP_MUX(CK_TOP_SPI_SEL, "spi_sel", spi_parents, 0x000, 0x004, 0x008, 16,
> +		3, 23, 0x1C0, 2),
> +	TOP_MUX(CK_TOP_SPIM_MST_SEL, "spim_mst_sel", spi_parents, 0x000, 0x004,
> +		0x008, 24, 3, 31, 0x1C0, 3),
> +	/* CLK_CFG_1 */
> +	TOP_MUX(CK_TOP_UART_SEL, "uart_sel", uart_parents, 0x010, 0x014, 0x018,
> +		0, 2, 7, 0x1C0, 4),
> +	TOP_MUX(CK_TOP_PWM_SEL, "pwm_sel", pwm_parents, 0x010, 0x014, 0x018, 8,
> +		2, 15, 0x1C0, 5),
> +	TOP_MUX(CK_TOP_I2C_SEL, "i2c_sel", i2c_parents, 0x010, 0x014, 0x018, 16,
> +		2, 23, 0x1C0, 6),
> +	TOP_MUX(CK_TOP_PEXTP_TL_SEL, "pextp_tl_ck_sel", pextp_tl_ck_parents,
> +		0x010, 0x014, 0x018, 24, 2, 31, 0x1C0, 7),
> +	/* CLK_CFG_2 */
> +	TOP_MUX(CK_TOP_EMMC_250M_SEL, "emmc_250m_sel", emmc_250m_parents, 0x020,
> +		0x024, 0x028, 0, 1, 7, 0x1C0, 8),
> +	TOP_MUX(CK_TOP_EMMC_416M_SEL, "emmc_416m_sel", emmc_416m_parents, 0x020,
> +		0x024, 0x028, 8, 1, 15, 0x1C0, 9),
> +	TOP_MUX(CK_TOP_F_26M_ADC_SEL, "f_26m_adc_sel", f_26m_adc_parents, 0x020,
> +		0x024, 0x028, 16, 1, 23, 0x1C0, 10),
> +	TOP_MUX(CK_TOP_DRAMC_SEL, "dramc_sel", f_26m_adc_parents, 0x020, 0x024,
> +		0x028, 24, 1, 31, 0x1C0, 11),
> +	/* CLK_CFG_3 */
> +	TOP_MUX(CK_TOP_DRAMC_MD32_SEL, "dramc_md32_sel", dramc_md32_parents,
> +		0x030, 0x034, 0x038, 0, 1, 7, 0x1C0, 12),
> +	TOP_MUX(CK_TOP_SYSAXI_SEL, "sysaxi_sel", sysaxi_parents, 0x030, 0x034,
> +		0x038, 8, 2, 15, 0x1C0, 13),
> +	TOP_MUX(CK_TOP_SYSAPB_SEL, "sysapb_sel", sysapb_parents, 0x030, 0x034,
> +		0x038, 16, 2, 23, 0x1C0, 14),
> +	TOP_MUX(CK_TOP_ARM_DB_MAIN_SEL, "arm_db_main_sel", arm_db_main_parents,
> +		0x030, 0x034, 0x038, 24, 1, 31, 0x1C0, 15),
> +	/* CLK_CFG_4 */
> +	TOP_MUX(CK_TOP_ARM_DB_JTSEL, "arm_db_jtsel", arm_db_jtsel_parents,
> +		0x040, 0x044, 0x048, 0, 1, 7, 0x1C0, 16),
> +	TOP_MUX(CK_TOP_NETSYS_SEL, "netsys_sel", netsys_parents, 0x040, 0x044,
> +		0x048, 8, 1, 15, 0x1C0, 17),
> +	TOP_MUX(CK_TOP_NETSYS_500M_SEL, "netsys_500m_sel", netsys_500m_parents,
> +		0x040, 0x044, 0x048, 16, 1, 23, 0x1C0, 18),
> +	TOP_MUX(CK_TOP_NETSYS_MCU_SEL, "netsys_mcu_sel", netsys_mcu_parents,
> +		0x040, 0x044, 0x048, 24, 3, 31, 0x1C0, 19),
> +	/* CLK_CFG_5 */
> +	TOP_MUX(CK_TOP_NETSYS_2X_SEL, "netsys_2x_sel", netsys_2x_parents, 0x050,
> +		0x054, 0x058, 0, 2, 7, 0x1C0, 20),
> +	TOP_MUX(CK_TOP_SGM_325M_SEL, "sgm_325m_sel", sgm_325m_parents, 0x050,
> +		0x054, 0x058, 8, 1, 15, 0x1C0, 21),
> +	TOP_MUX(CK_TOP_SGM_REG_SEL, "sgm_reg_sel", sgm_reg_parents, 0x050,
> +		0x054, 0x058, 16, 1, 23, 0x1C0, 22),
> +	TOP_MUX(CK_TOP_A1SYS_SEL, "a1sys_sel", a1sys_parents, 0x050, 0x054,
> +		0x058, 24, 1, 31, 0x1C0, 23),
> +	/* CLK_CFG_6 */
> +	TOP_MUX(CK_TOP_CONN_MCUSYS_SEL, "conn_mcusys_sel", conn_mcusys_parents,
> +		0x060, 0x064, 0x068, 0, 1, 7, 0x1C0, 24),
> +	TOP_MUX(CK_TOP_EIP_B_SEL, "eip_b_sel", eip_b_parents, 0x060, 0x064,
> +		0x068, 8, 1, 15, 0x1C0, 25),
> +	TOP_MUX(CK_TOP_PCIE_PHY_SEL, "pcie_phy_sel", f_26m_adc_parents, 0x060,
> +		0x064, 0x068, 16, 1, 23, 0x1C0, 26),
> +	TOP_MUX(CK_TOP_USB3_PHY_SEL, "usb3_phy_sel", f_26m_adc_parents, 0x060,
> +		0x064, 0x068, 24, 1, 31, 0x1C0, 27),
> +	/* CLK_CFG_7 */
> +	TOP_MUX(CK_TOP_F26M_SEL, "csw_f26m_sel", f_26m_adc_parents, 0x070,
> +		0x074, 0x078, 0, 1, 7, 0x1C0, 28),
> +	TOP_MUX(CK_TOP_AUD_L_SEL, "aud_l_sel", aud_l_parents, 0x070, 0x074,
> +		0x078, 8, 2, 15, 0x1C0, 29),
> +	TOP_MUX(CK_TOP_A_TUNER_SEL, "a_tuner_sel", a_tuner_parents, 0x070,
> +		0x074, 0x078, 16, 2, 23, 0x1C0, 30),
> +	TOP_MUX(CK_TOP_U2U3_SEL, "u2u3_sel", f_26m_adc_parents, 0x070, 0x074,
> +		0x078, 24, 1, 31, 0x1C4, 0),
> +	/* CLK_CFG_8 */
> +	TOP_MUX(CK_TOP_U2U3_SYS_SEL, "u2u3_sys_sel", u2u3_sys_parents, 0x080,
> +		0x084, 0x088, 0, 1, 7, 0x1C4, 1),
> +	TOP_MUX(CK_TOP_U2U3_XHCI_SEL, "u2u3_xhci_sel", u2u3_sys_parents, 0x080,
> +		0x084, 0x088, 8, 1, 15, 0x1C4, 2),
> +	TOP_MUX(CK_TOP_DA_U2_REFSEL, "da_u2_refsel", da_u2_refsel_parents,
> +		0x080, 0x084, 0x088, 16, 1, 23, 0x1C4, 3),
> +	TOP_MUX(CK_TOP_DA_U2_CK_1P_SEL, "da_u2_ck_1p_sel", da_u2_refsel_parents,
> +		0x080, 0x084, 0x088, 24, 1, 31, 0x1C4, 4),
> +	/* CLK_CFG_9 */
> +	TOP_MUX(CK_TOP_AP2CNN_HOST_SEL, "ap2cnn_host_sel", sgm_reg_parents,
> +		0x090, 0x094, 0x098, 0, 1, 7, 0x1C4, 5),
> +};
> +
> +/* INFRA FIXED DIV */
> +static const struct mtk_fixed_factor infra_fixed_divs[] = {
> +	TOP_FACTOR(CK_INFRA_CK_F26M, "infra_ck_f26m", CK_TOP_F26M_SEL, 1, 1),
> +	TOP_FACTOR(CK_INFRA_UART, "infra_uart", CK_TOP_UART_SEL, 1, 1),
> +	TOP_FACTOR(CK_INFRA_ISPI0, "infra_ispi0", CK_TOP_SPI_SEL, 1, 1),
> +	TOP_FACTOR(CK_INFRA_I2C, "infra_i2c", CK_TOP_I2C_SEL, 1, 1),
> +	TOP_FACTOR(CK_INFRA_ISPI1, "infra_ispi1", CK_TOP_SPINFI_SEL, 1, 1),
> +	TOP_FACTOR(CK_INFRA_PWM, "infra_pwm", CK_TOP_PWM_SEL, 1, 1),
> +	TOP_FACTOR(CK_INFRA_66M_MCK, "infra_66m_mck", CK_TOP_SYSAXI_SEL, 1, 2),
> +	TOP_FACTOR(CK_INFRA_CK_F32K, "infra_ck_f32k", CK_TOP_CB_RTC_32P7K, 1,
> +		   1),
> +	TOP_FACTOR(CK_INFRA_PCIE_CK, "infra_pcie", CK_TOP_PEXTP_TL_SEL, 1, 1),
> +	INFRA_FACTOR(CK_INFRA_PWM_BCK, "infra_pwm_bck", CK_INFRA_PWM_BSEL, 1,
> +		     1),
> +	INFRA_FACTOR(CK_INFRA_PWM_CK1, "infra_pwm_ck1", CK_INFRA_PWM1_SEL, 1,
> +		     1),
> +	INFRA_FACTOR(CK_INFRA_PWM_CK2, "infra_pwm_ck2", CK_INFRA_PWM2_SEL, 1,
> +		     1),
> +	TOP_FACTOR(CK_INFRA_133M_HCK, "infra_133m_hck", CK_TOP_SYSAXI, 1, 1),
> +	TOP_FACTOR(CK_INFRA_EIP_CK, "infra_eip", CK_TOP_EIP_B, 1, 1),
> +	INFRA_FACTOR(CK_INFRA_66M_PHCK, "infra_66m_phck", CK_INFRA_133M_HCK, 1,
> +		     1),
> +	TOP_FACTOR(CK_INFRA_FAUD_L_CK, "infra_faud_l", CK_TOP_AUD_L, 1, 1),
> +	TOP_FACTOR(CK_INFRA_FAUD_AUD_CK, "infra_faud_aud", CK_TOP_A1SYS, 1, 1),
> +	TOP_FACTOR(CK_INFRA_FAUD_EG2_CK, "infra_faud_eg2", CK_TOP_A_TUNER, 1,
> +		   1),
> +	TOP_FACTOR(CK_INFRA_I2CS_CK, "infra_i2cs", CK_TOP_I2C_BCK, 1, 1),
> +	INFRA_FACTOR(CK_INFRA_MUX_UART0, "infra_mux_uart0", CK_INFRA_UART0_SEL,
> +		     1, 1),
> +	INFRA_FACTOR(CK_INFRA_MUX_UART1, "infra_mux_uart1", CK_INFRA_UART1_SEL,
> +		     1, 1),
> +	INFRA_FACTOR(CK_INFRA_MUX_UART2, "infra_mux_uart2", CK_INFRA_UART2_SEL,
> +		     1, 1),
> +	TOP_FACTOR(CK_INFRA_NFI_CK, "infra_nfi", CK_TOP_NFI1X, 1, 1),
> +	TOP_FACTOR(CK_INFRA_SPINFI_CK, "infra_spinfi", CK_TOP_SPINFI_BCK, 1, 1),
> +	INFRA_FACTOR(CK_INFRA_MUX_SPI0, "infra_mux_spi0", CK_INFRA_SPI0_SEL, 1,
> +		     1),
> +	INFRA_FACTOR(CK_INFRA_MUX_SPI1, "infra_mux_spi1", CK_INFRA_SPI1_SEL, 1,
> +		     1),
> +	TOP_FACTOR(CK_INFRA_RTC_32K, "infra_rtc_32k", CK_TOP_CB_RTC_32K, 1, 1),
> +	TOP_FACTOR(CK_INFRA_FMSDC_CK, "infra_fmsdc", CK_TOP_EMMC_416M, 1, 1),
> +	TOP_FACTOR(CK_INFRA_FMSDC_HCK_CK, "infra_fmsdc_hck", CK_TOP_EMMC_250M,
> +		   1, 1),
> +	TOP_FACTOR(CK_INFRA_PERI_133M, "infra_peri_133m", CK_TOP_SYSAXI, 1, 1),
> +	TOP_FACTOR(CK_INFRA_133M_PHCK, "infra_133m_phck", CK_TOP_SYSAXI, 1, 1),
> +	TOP_FACTOR(CK_INFRA_USB_SYS_CK, "infra_usb_sys", CK_TOP_U2U3_SYS, 1, 1),
> +	TOP_FACTOR(CK_INFRA_USB_CK, "infra_usb", CK_TOP_U2U3_REF, 1, 1),
> +	TOP_FACTOR(CK_INFRA_USB_XHCI_CK, "infra_usb_xhci", CK_TOP_U2U3_XHCI, 1,
> +		   1),
> +	TOP_FACTOR(CK_INFRA_PCIE_GFMUX_TL_O_PRE, "infra_pcie_mux",
> +		   CK_TOP_PEXTP_TL, 1, 1),
> +	TOP_FACTOR(CK_INFRA_F26M_CK0, "infra_f26m_ck0", CK_TOP_F26M, 1, 1),
> +	TOP_FACTOR(CK_INFRA_HD_133M, "infra_hd_133m", CK_TOP_SYSAXI, 1, 1),
> +};
> +
> +/* INFRASYS MUX PARENTS */
> +static const int infra_uart0_parents[] = { CK_INFRA_CK_F26M, CK_INFRA_UART };
> +
> +static const int infra_spi0_parents[] = { CK_INFRA_I2C, CK_INFRA_ISPI0 };
> +
> +static const int infra_spi1_parents[] = { CK_INFRA_I2C, CK_INFRA_ISPI1 };
> +
> +static const int infra_pwm_bsel_parents[] = { CK_INFRA_CK_F32K,
> +					      CK_INFRA_CK_F26M,
> +					      CK_INFRA_66M_MCK, CK_INFRA_PWM };
> +
> +static const int infra_pcie_parents[] = { CK_INFRA_CK_F32K, CK_INFRA_CK_F26M,
> +					  -1, CK_INFRA_PCIE_CK };
> +
> +#define INFRA_MUX(_id, _name, _parents, _reg, _shift, _width)                  \
> +	{                                                                      \
> +		.id = _id, .mux_reg = (_reg) + 0x8,                            \
> +		.mux_set_reg = (_reg) + 0x0, .mux_clr_reg = (_reg) + 0x4,      \
> +		.mux_shift = _shift, .mux_mask = BIT(_width) - 1,              \
> +		.parent = _parents, .num_parents = ARRAY_SIZE(_parents),       \
> +		.flags = CLK_MUX_SETCLR_UPD | CLK_PARENT_INFRASYS,             \
> +	}
> +
> +/* INFRA MUX */
> +
> +static const struct mtk_composite infra_muxes[] = {
> +	/* MODULE_CLK_SEL_0 */
> +	INFRA_MUX(CK_INFRA_UART0_SEL, "infra_uart0_sel", infra_uart0_parents,
> +		  0x10, 0, 1),
> +	INFRA_MUX(CK_INFRA_UART1_SEL, "infra_uart1_sel", infra_uart0_parents,
> +		  0x10, 1, 1),
> +	INFRA_MUX(CK_INFRA_UART2_SEL, "infra_uart2_sel", infra_uart0_parents,
> +		  0x10, 2, 1),
> +	INFRA_MUX(CK_INFRA_SPI0_SEL, "infra_spi0_sel", infra_spi0_parents, 0x10,
> +		  4, 1),
> +	INFRA_MUX(CK_INFRA_SPI1_SEL, "infra_spi1_sel", infra_spi1_parents, 0x10,
> +		  5, 1),
> +	INFRA_MUX(CK_INFRA_PWM1_SEL, "infra_pwm1_sel", infra_pwm_bsel_parents,
> +		  0x10, 9, 2),
> +	INFRA_MUX(CK_INFRA_PWM2_SEL, "infra_pwm2_sel", infra_pwm_bsel_parents,
> +		  0x10, 11, 2),
> +	INFRA_MUX(CK_INFRA_PWM_BSEL, "infra_pwm_bsel", infra_pwm_bsel_parents,
> +		  0x10, 13, 2),
> +	/* MODULE_CLK_SEL_1 */
> +	INFRA_MUX(CK_INFRA_PCIE_SEL, "infra_pcie_sel", infra_pcie_parents, 0x20,
> +		  0, 2),
> +};
> +
> +static const struct mtk_gate_regs infra_0_cg_regs = {
> +	.set_ofs = 0x40,
> +	.clr_ofs = 0x44,
> +	.sta_ofs = 0x48,
> +};
> +
> +static const struct mtk_gate_regs infra_1_cg_regs = {
> +	.set_ofs = 0x50,
> +	.clr_ofs = 0x54,
> +	.sta_ofs = 0x58,
> +};
> +
> +static const struct mtk_gate_regs infra_2_cg_regs = {
> +	.set_ofs = 0x60,
> +	.clr_ofs = 0x64,
> +	.sta_ofs = 0x68,
> +};
> +
> +#define GATE_INFRA0(_id, _name, _parent, _shift)                               \
> +	{                                                                      \
> +		.id = _id, .parent = _parent, .regs = &infra_0_cg_regs,        \
> +		.shift = _shift,                                               \
> +		.flags = CLK_GATE_SETCLR | CLK_PARENT_INFRASYS,                \
> +	}
> +
> +#define GATE_INFRA1(_id, _name, _parent, _shift)                               \
> +	{                                                                      \
> +		.id = _id, .parent = _parent, .regs = &infra_1_cg_regs,        \
> +		.shift = _shift,                                               \
> +		.flags = CLK_GATE_SETCLR | CLK_PARENT_INFRASYS,                \
> +	}
> +
> +#define GATE_INFRA2(_id, _name, _parent, _shift)                               \
> +	{                                                                      \
> +		.id = _id, .parent = _parent, .regs = &infra_2_cg_regs,        \
> +		.shift = _shift,                                               \
> +		.flags = CLK_GATE_SETCLR | CLK_PARENT_INFRASYS,                \
> +	}
> +
> +/* INFRA GATE */
> +
> +static const struct mtk_gate infracfg_ao_gates[] = {
> +	/* INFRA0 */
> +	GATE_INFRA0(CK_INFRA_GPT_STA, "infra_gpt_sta", CK_INFRA_66M_MCK, 0),
> +	GATE_INFRA0(CK_INFRA_PWM_HCK, "infra_pwm_hck", CK_INFRA_66M_MCK, 1),
> +	GATE_INFRA0(CK_INFRA_PWM_STA, "infra_pwm_sta", CK_INFRA_PWM_BCK, 2),
> +	GATE_INFRA0(CK_INFRA_PWM1_CK, "infra_pwm1", CK_INFRA_PWM_CK1, 3),
> +	GATE_INFRA0(CK_INFRA_PWM2_CK, "infra_pwm2", CK_INFRA_PWM_CK2, 4),
> +	GATE_INFRA0(CK_INFRA_CQ_DMA_CK, "infra_cq_dma", CK_INFRA_133M_HCK, 6),
> +	GATE_INFRA0(CK_INFRA_EIP97_CK, "infra_eip97", CK_INFRA_EIP_CK, 7),
> +	GATE_INFRA0(CK_INFRA_AUD_BUS_CK, "infra_aud_bus", CK_INFRA_66M_PHCK, 8),
> +	GATE_INFRA0(CK_INFRA_AUD_26M_CK, "infra_aud_26m", CK_INFRA_CK_F26M, 9),
> +	GATE_INFRA0(CK_INFRA_AUD_L_CK, "infra_aud_l", CK_INFRA_FAUD_L_CK, 10),
> +	GATE_INFRA0(CK_INFRA_AUD_AUD_CK, "infra_aud_aud", CK_INFRA_FAUD_AUD_CK,
> +		    11),
> +	GATE_INFRA0(CK_INFRA_AUD_EG2_CK, "infra_aud_eg2", CK_INFRA_FAUD_EG2_CK,
> +		    13),
> +	GATE_INFRA0(CK_INFRA_DRAMC_26M_CK, "infra_dramc_26m", CK_INFRA_CK_F26M,
> +		    14),
> +	GATE_INFRA0(CK_INFRA_DBG_CK, "infra_dbg", CK_INFRA_66M_MCK, 15),
> +	GATE_INFRA0(CK_INFRA_AP_DMA_CK, "infra_ap_dma", CK_INFRA_66M_MCK, 16),
> +	GATE_INFRA0(CK_INFRA_SEJ_CK, "infra_sej", CK_INFRA_66M_MCK, 24),
> +	GATE_INFRA0(CK_INFRA_SEJ_13M_CK, "infra_sej_13m", CK_INFRA_CK_F26M, 25),
> +	GATE_INFRA0(CK_INFRA_TRNG_CK, "infra_trng", CK_INFRA_HD_133M, 26),
> +	/* INFRA1 */
> +	GATE_INFRA1(CK_INFRA_THERM_CK, "infra_therm", CK_INFRA_CK_F26M, 0),
> +	GATE_INFRA1(CK_INFRA_I2CO_CK, "infra_i2co", CK_INFRA_I2CS_CK, 1),
> +	GATE_INFRA1(CK_INFRA_UART0_CK, "infra_uart0", CK_INFRA_MUX_UART0, 2),
> +	GATE_INFRA1(CK_INFRA_UART1_CK, "infra_uart1", CK_INFRA_MUX_UART1, 3),
> +	GATE_INFRA1(CK_INFRA_UART2_CK, "infra_uart2", CK_INFRA_MUX_UART2, 4),
> +	GATE_INFRA1(CK_INFRA_NFI1_CK, "infra_nfi1", CK_INFRA_NFI_CK, 8),
> +	GATE_INFRA1(CK_INFRA_SPINFI1_CK, "infra_spinfi1", CK_INFRA_SPINFI_CK,
> +		    9),
> +	GATE_INFRA1(CK_INFRA_NFI_HCK_CK, "infra_nfi_hck", CK_INFRA_66M_MCK, 10),
> +	GATE_INFRA1(CK_INFRA_SPI0_CK, "infra_spi0", CK_INFRA_MUX_SPI0, 11),
> +	GATE_INFRA1(CK_INFRA_SPI1_CK, "infra_spi1", CK_INFRA_MUX_SPI1, 12),
> +	GATE_INFRA1(CK_INFRA_SPI0_HCK_CK, "infra_spi0_hck", CK_INFRA_66M_MCK,
> +		    13),
> +	GATE_INFRA1(CK_INFRA_SPI1_HCK_CK, "infra_spi1_hck", CK_INFRA_66M_MCK,
> +		    14),
> +	GATE_INFRA1(CK_INFRA_FRTC_CK, "infra_frtc", CK_INFRA_RTC_32K, 15),
> +	GATE_INFRA1(CK_INFRA_MSDC_CK, "infra_msdc", CK_INFRA_FMSDC_CK, 16),
> +	GATE_INFRA1(CK_INFRA_MSDC_HCK_CK, "infra_msdc_hck",
> +		    CK_INFRA_FMSDC_HCK_CK, 17),
> +	GATE_INFRA1(CK_INFRA_MSDC_133M_CK, "infra_msdc_133m",
> +		    CK_INFRA_PERI_133M, 18),
> +	GATE_INFRA1(CK_INFRA_MSDC_66M_CK, "infra_msdc_66m", CK_INFRA_66M_PHCK,
> +		    19),
> +	GATE_INFRA1(CK_INFRA_ADC_26M_CK, "infra_adc_26m", CK_INFRA_CK_F26M, 20),
> +	GATE_INFRA1(CK_INFRA_ADC_FRC_CK, "infra_adc_frc", CK_INFRA_CK_F26M, 21),
> +	GATE_INFRA1(CK_INFRA_FBIST2FPC_CK, "infra_fbist2fpc", CK_INFRA_NFI_CK,
> +		    23),
> +	/* INFRA2 */
> +	GATE_INFRA2(CK_INFRA_IUSB_133_CK, "infra_iusb_133", CK_INFRA_133M_PHCK,
> +		    0),
> +	GATE_INFRA2(CK_INFRA_IUSB_66M_CK, "infra_iusb_66m", CK_INFRA_66M_PHCK,
> +		    1),
> +	GATE_INFRA2(CK_INFRA_IUSB_SYS_CK, "infra_iusb_sys", CK_INFRA_USB_SYS_CK,
> +		    2),
> +	GATE_INFRA2(CK_INFRA_IUSB_CK, "infra_iusb", CK_INFRA_USB_CK, 3),
> +	GATE_INFRA2(CK_INFRA_IPCIE_CK, "infra_ipcie", CK_INFRA_PCIE_CK, 13),
> +	GATE_INFRA2(CK_INFRA_IPCIER_CK, "infra_ipcier", CK_INFRA_F26M_CK0, 15),
> +	GATE_INFRA2(CK_INFRA_IPCIEB_CK, "infra_ipcieb", CK_INFRA_133M_PHCK, 15),
> +};
> +
> +static const struct mtk_clk_tree mt7986_fixed_pll_clk_tree = {
> +	.fdivs_offs = CLK_APMIXED_NR_CLK,
> +	.xtal_rate = 40 * MHZ,
> +	.fclks = fixed_pll_clks,
> +};
> +
> +static const struct mtk_clk_tree mt7986_topckgen_clk_tree = {
> +	.fdivs_offs = CK_TOP_CB_M_416M,
> +	.muxes_offs = CK_TOP_NFI1X_SEL,
> +	.fclks = top_fixed_clks,
> +	.fdivs = top_fixed_divs,
> +	.muxes = top_muxes,
> +	.flags = CLK_BYPASS_XTAL,
> +};
> +
> +static const struct mtk_clk_tree mt7986_infracfg_clk_tree = {
> +	.fdivs_offs = CK_INFRA_CK_F26M,
> +	.muxes_offs = CK_INFRA_UART0_SEL,
> +	.fdivs = infra_fixed_divs,
> +	.muxes = infra_muxes,
> +};
> +
> +static const struct udevice_id mt7986_fixed_pll_compat[] = {
> +	{ .compatible = "mediatek,mt7986-fixed-plls" },
> +	{}
> +};
> +
> +static const struct udevice_id mt7986_topckgen_compat[] = {
> +	{ .compatible = "mediatek,mt7986-topckgen" },
> +	{}
> +};
> +
> +static int mt7986_fixed_pll_probe(struct udevice *dev)
> +{
> +	return mtk_common_clk_init(dev, &mt7986_fixed_pll_clk_tree);
> +}
> +
> +static int mt7986_topckgen_probe(struct udevice *dev)
> +{
> +	struct mtk_clk_priv *priv = dev_get_priv(dev);
> +
> +	priv->base = dev_read_addr_ptr(dev);
> +	writel(MT7986_CLK_PDN_EN_WRITE, priv->base + MT7986_CLK_PDN);
> +
> +	return mtk_common_clk_init(dev, &mt7986_topckgen_clk_tree);
> +}
> +
> +U_BOOT_DRIVER(mtk_clk_apmixedsys) = {
> +	.name = "mt7986-clock-fixed-pll",
> +	.id = UCLASS_CLK,
> +	.of_match = mt7986_fixed_pll_compat,
> +	.probe = mt7986_fixed_pll_probe,
> +	.priv_auto = sizeof(struct mtk_clk_priv),
> +	.ops = &mtk_clk_topckgen_ops,
> +	.flags = DM_FLAG_PRE_RELOC,
> +};
> +
> +U_BOOT_DRIVER(mtk_clk_topckgen) = {
> +	.name = "mt7986-clock-topckgen",
> +	.id = UCLASS_CLK,
> +	.of_match = mt7986_topckgen_compat,
> +	.probe = mt7986_topckgen_probe,
> +	.priv_auto = sizeof(struct mtk_clk_priv),
> +	.ops = &mtk_clk_topckgen_ops,
> +	.flags = DM_FLAG_PRE_RELOC,
> +};
> +
> +static const struct udevice_id mt7986_infracfg_compat[] = {
> +	{ .compatible = "mediatek,mt7986-infracfg" },
> +	{}
> +};
> +
> +static const struct udevice_id mt7986_infracfg_ao_compat[] = {
> +	{ .compatible = "mediatek,mt7986-infracfg_ao" },
> +	{}
> +};
> +
> +static int mt7986_infracfg_probe(struct udevice *dev)
> +{
> +	return mtk_common_clk_init(dev, &mt7986_infracfg_clk_tree);
> +}
> +
> +static int mt7986_infracfg_ao_probe(struct udevice *dev)
> +{
> +	return mtk_common_clk_gate_init(dev, &mt7986_infracfg_clk_tree,
> +					infracfg_ao_gates);
> +}
> +
> +U_BOOT_DRIVER(mtk_clk_infracfg) = {
> +	.name = "mt7986-clock-infracfg",
> +	.id = UCLASS_CLK,
> +	.of_match = mt7986_infracfg_compat,
> +	.probe = mt7986_infracfg_probe,
> +	.priv_auto = sizeof(struct mtk_clk_priv),
> +	.ops = &mtk_clk_infrasys_ops,
> +	.flags = DM_FLAG_PRE_RELOC,
> +};
> +
> +U_BOOT_DRIVER(mtk_clk_infracfg_ao) = {
> +	.name = "mt7986-clock-infracfg-ao",
> +	.id = UCLASS_CLK,
> +	.of_match = mt7986_infracfg_ao_compat,
> +	.probe = mt7986_infracfg_ao_probe,
> +	.priv_auto = sizeof(struct mtk_cg_priv),
> +	.ops = &mtk_clk_gate_ops,
> +	.flags = DM_FLAG_PRE_RELOC,
> +};
> +
> +/* ethsys */
> +static const struct mtk_gate_regs eth_cg_regs = {
> +	.sta_ofs = 0x30,
> +};
> +
> +#define GATE_ETH(_id, _name, _parent, _shift)                                  \
> +	{                                                                      \
> +		.id = _id, .parent = _parent, .regs = &eth_cg_regs,            \
> +		.shift = _shift,                                               \
> +		.flags = CLK_GATE_NO_SETCLR_INV | CLK_PARENT_TOPCKGEN,         \
> +	}
> +
> +static const struct mtk_gate eth_cgs[] = {
> +	GATE_ETH(CK_ETH_FE_EN, "eth_fe_en", CK_TOP_NETSYS_2X, 7),
> +	GATE_ETH(CK_ETH_GP2_EN, "eth_gp2_en", CK_TOP_SGM_325M, 8),
> +	GATE_ETH(CK_ETH_GP1_EN, "eth_gp1_en", CK_TOP_SGM_325M, 8),
> +	GATE_ETH(CK_ETH_WOCPU1_EN, "eth_wocpu1_en", CK_TOP_NETSYS_WED_MCU, 14),
> +	GATE_ETH(CK_ETH_WOCPU0_EN, "eth_wocpu0_en", CK_TOP_NETSYS_WED_MCU, 15),
> +};
> +
> +static int mt7986_ethsys_probe(struct udevice *dev)
> +{
> +	return mtk_common_clk_gate_init(dev, &mt7986_topckgen_clk_tree,
> +					eth_cgs);
> +}
> +
> +static int mt7986_ethsys_bind(struct udevice *dev)
> +{
> +	int ret = 0;
> +
> +	if (CONFIG_IS_ENABLED(RESET_MEDIATEK)) {
> +		ret = mediatek_reset_bind(dev, ETHSYS_HIFSYS_RST_CTRL_OFS, 1);
> +		if (ret)
> +			debug("Warning: failed to bind reset controller\n");
> +	}
> +
> +	return ret;
> +}
> +
> +static const struct udevice_id mt7986_ethsys_compat[] = {
> +	{ .compatible = "mediatek,mt7986-ethsys" },
> +	{ }
> +};
> +
> +U_BOOT_DRIVER(mtk_clk_ethsys) = {
> +	.name = "mt7986-clock-ethsys",
> +	.id = UCLASS_CLK,
> +	.of_match = mt7986_ethsys_compat,
> +	.probe = mt7986_ethsys_probe,
> +	.bind = mt7986_ethsys_bind,
> +	.priv_auto = sizeof(struct mtk_cg_priv),
> +	.ops = &mtk_clk_gate_ops,
> +};
> diff --git a/include/dt-bindings/clock/mt7986-clk.h b/include/dt-bindings/clock/mt7986-clk.h
> new file mode 100644
> index 0000000000..820f863183
> --- /dev/null
> +++ b/include/dt-bindings/clock/mt7986-clk.h
> @@ -0,0 +1,249 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (C) 2022 MediaTek Inc. All rights reserved.
> + *
> + * Author: Sam Shih <sam.shih@mediatek.com>
> + */
> +
> +#ifndef _DT_BINDINGS_CLK_MT7986_H
> +#define _DT_BINDINGS_CLK_MT7986_H
> +
> +/* INFRACFG */
> +
> +#define CK_INFRA_CK_F26M		0
> +#define CK_INFRA_UART			1
> +#define CK_INFRA_ISPI0			2
> +#define CK_INFRA_I2C			3
> +#define CK_INFRA_ISPI1			4
> +#define CK_INFRA_PWM			5
> +#define CK_INFRA_66M_MCK		6
> +#define CK_INFRA_CK_F32K		7
> +#define CK_INFRA_PCIE_CK		8
> +#define CK_INFRA_PWM_BCK		9
> +#define CK_INFRA_PWM_CK1		10
> +#define CK_INFRA_PWM_CK2		11
> +#define CK_INFRA_133M_HCK		12
> +#define CK_INFRA_EIP_CK			13
> +#define CK_INFRA_66M_PHCK		14
> +#define CK_INFRA_FAUD_L_CK		15
> +#define CK_INFRA_FAUD_AUD_CK		17
> +#define CK_INFRA_FAUD_EG2_CK		17
> +#define CK_INFRA_I2CS_CK		18
> +#define CK_INFRA_MUX_UART0		19
> +#define CK_INFRA_MUX_UART1		20
> +#define CK_INFRA_MUX_UART2		21
> +#define CK_INFRA_NFI_CK			22
> +#define CK_INFRA_SPINFI_CK		23
> +#define CK_INFRA_MUX_SPI0		24
> +#define CK_INFRA_MUX_SPI1		25
> +#define CK_INFRA_RTC_32K		26
> +#define CK_INFRA_FMSDC_CK		27
> +#define CK_INFRA_FMSDC_HCK_CK		28
> +#define CK_INFRA_PERI_133M		29
> +#define CK_INFRA_133M_PHCK		30
> +#define CK_INFRA_USB_SYS_CK		31
> +#define CK_INFRA_USB_CK			32
> +#define CK_INFRA_USB_XHCI_CK		33
> +#define CK_INFRA_PCIE_GFMUX_TL_O_PRE	34
> +#define CK_INFRA_F26M_CK0		35
> +#define CK_INFRA_HD_133M		36
> +#define CLK_INFRA_NR_CLK		37
> +
> +/* TOPCKGEN */
> +
> +#define CK_TOP_CB_CKSQ_40M		0
> +#define CK_TOP_CB_M_416M		1
> +#define CK_TOP_CB_M_D2			2
> +#define CK_TOP_CB_M_D4			3
> +#define CK_TOP_CB_M_D8			4
> +#define CK_TOP_M_D8_D2			5
> +#define CK_TOP_M_D3_D2			6
> +#define CK_TOP_CB_MM_D2			7
> +#define CK_TOP_CB_MM_D4			8
> +#define CK_TOP_CB_MM_D8			9
> +#define CK_TOP_MM_D8_D2			10
> +#define CK_TOP_MM_D3_D8			11
> +#define CK_TOP_CB_U2_PHYD_CK		12
> +#define CK_TOP_CB_APLL2_196M		13
> +#define CK_TOP_APLL2_D4			14
> +#define CK_TOP_CB_NET1_D4		15
> +#define CK_TOP_CB_NET1_D5		16
> +#define CK_TOP_NET1_D5_D2		17
> +#define CK_TOP_NET1_D5_D4		18
> +#define CK_TOP_NET1_D8_D2		19
> +#define CK_TOP_NET1_D8_D4		20
> +#define CK_TOP_CB_NET2_800M		21
> +#define CK_TOP_CB_NET2_D4		22
> +#define CK_TOP_NET2_D4_D2		23
> +#define CK_TOP_NET2_D3_D2		24
> +#define CK_TOP_CB_WEDMCU_760M		25
> +#define CK_TOP_WEDMCU_D5_D2		26
> +#define CK_TOP_CB_SGM_325M		27
> +#define CK_TOP_CB_CKSQ_40M_D2		28
> +#define CK_TOP_CB_RTC_32K		29
> +#define CK_TOP_CB_RTC_32P7K		30
> +#define CK_TOP_NFI1X			31
> +#define CK_TOP_USB_EQ_RX250M		32
> +#define CK_TOP_USB_TX250M		33
> +#define CK_TOP_USB_LN0_CK		34
> +#define CK_TOP_USB_CDR_CK		35
> +#define CK_TOP_SPINFI_BCK		36
> +#define CK_TOP_I2C_BCK			37
> +#define CK_TOP_PEXTP_TL			38
> +#define CK_TOP_EMMC_250M		39
> +#define CK_TOP_EMMC_416M		40
> +#define CK_TOP_F_26M_ADC_CK		41
> +#define CK_TOP_SYSAXI			42
> +#define CK_TOP_NETSYS_WED_MCU		43
> +#define CK_TOP_NETSYS_2X		44
> +#define CK_TOP_SGM_325M			45
> +#define CK_TOP_A1SYS			46
> +#define CK_TOP_EIP_B			47
> +#define CK_TOP_F26M			48
> +#define CK_TOP_AUD_L			49
> +#define CK_TOP_A_TUNER			50
> +#define CK_TOP_U2U3_REF			51
> +#define CK_TOP_U2U3_SYS			52
> +#define CK_TOP_U2U3_XHCI		53
> +#define CK_TOP_AP2CNN_HOST		54
> +#define CK_TOP_NFI1X_SEL		55
> +#define CK_TOP_SPINFI_SEL		56
> +#define CK_TOP_SPI_SEL			57
> +#define CK_TOP_SPIM_MST_SEL		58
> +#define CK_TOP_UART_SEL			59
> +#define CK_TOP_PWM_SEL			60
> +#define CK_TOP_I2C_SEL			61
> +#define CK_TOP_PEXTP_TL_SEL		62
> +#define CK_TOP_EMMC_250M_SEL		63
> +#define CK_TOP_EMMC_416M_SEL		64
> +#define CK_TOP_F_26M_ADC_SEL		65
> +#define CK_TOP_DRAMC_SEL		66
> +#define CK_TOP_DRAMC_MD32_SEL		67
> +#define CK_TOP_SYSAXI_SEL		68
> +#define CK_TOP_SYSAPB_SEL		69
> +#define CK_TOP_ARM_DB_MAIN_SEL		70
> +#define CK_TOP_ARM_DB_JTSEL		71
> +#define CK_TOP_NETSYS_SEL		72
> +#define CK_TOP_NETSYS_500M_SEL		73
> +#define CK_TOP_NETSYS_MCU_SEL		74
> +#define CK_TOP_NETSYS_2X_SEL		75
> +#define CK_TOP_SGM_325M_SEL		76
> +#define CK_TOP_SGM_REG_SEL		77
> +#define CK_TOP_A1SYS_SEL		78
> +#define CK_TOP_CONN_MCUSYS_SEL		79
> +#define CK_TOP_EIP_B_SEL		80
> +#define CK_TOP_PCIE_PHY_SEL		81
> +#define CK_TOP_USB3_PHY_SEL		82
> +#define CK_TOP_F26M_SEL			83
> +#define CK_TOP_AUD_L_SEL		84
> +#define CK_TOP_A_TUNER_SEL		85
> +#define CK_TOP_U2U3_SEL			86
> +#define CK_TOP_U2U3_SYS_SEL		87
> +#define CK_TOP_U2U3_XHCI_SEL		88
> +#define CK_TOP_DA_U2_REFSEL		89
> +#define CK_TOP_DA_U2_CK_1P_SEL		90
> +#define CK_TOP_AP2CNN_HOST_SEL		91
> +#define CLK_TOP_NR_CLK			92
> +
> +/*
> + * INFRACFG_AO
> + * clock muxes need to be append to infracfg domain, and clock gates
> + * need to be keep in infracgh_ao domain
> + */
> +
> +#define CK_INFRA_UART0_SEL		(0 + CLK_INFRA_NR_CLK)
> +#define CK_INFRA_UART1_SEL		(1 + CLK_INFRA_NR_CLK)
> +#define CK_INFRA_UART2_SEL		(2 + CLK_INFRA_NR_CLK)
> +#define CK_INFRA_SPI0_SEL		(3 + CLK_INFRA_NR_CLK)
> +#define CK_INFRA_SPI1_SEL		(4 + CLK_INFRA_NR_CLK)
> +#define CK_INFRA_PWM1_SEL		(5 + CLK_INFRA_NR_CLK)
> +#define CK_INFRA_PWM2_SEL		(6 + CLK_INFRA_NR_CLK)
> +#define CK_INFRA_PWM_BSEL		(7 + CLK_INFRA_NR_CLK)
> +#define CK_INFRA_PCIE_SEL		(8 + CLK_INFRA_NR_CLK)
> +#define CK_INFRA_GPT_STA		0
> +#define CK_INFRA_PWM_HCK		1
> +#define CK_INFRA_PWM_STA		2
> +#define CK_INFRA_PWM1_CK		3
> +#define CK_INFRA_PWM2_CK		4
> +#define CK_INFRA_CQ_DMA_CK		5
> +#define CK_INFRA_EIP97_CK		6
> +#define CK_INFRA_AUD_BUS_CK		7
> +#define CK_INFRA_AUD_26M_CK		8
> +#define CK_INFRA_AUD_L_CK		9
> +#define CK_INFRA_AUD_AUD_CK		10
> +#define CK_INFRA_AUD_EG2_CK		11
> +#define CK_INFRA_DRAMC_26M_CK		12
> +#define CK_INFRA_DBG_CK			13
> +#define CK_INFRA_AP_DMA_CK		14
> +#define CK_INFRA_SEJ_CK			15
> +#define CK_INFRA_SEJ_13M_CK		16
> +#define CK_INFRA_THERM_CK		17
> +#define CK_INFRA_I2CO_CK		18
> +#define CK_INFRA_TRNG_CK		19
> +#define CK_INFRA_UART0_CK		20
> +#define CK_INFRA_UART1_CK		21
> +#define CK_INFRA_UART2_CK		22
> +#define CK_INFRA_NFI1_CK		23
> +#define CK_INFRA_SPINFI1_CK		24
> +#define CK_INFRA_NFI_HCK_CK		25
> +#define CK_INFRA_SPI0_CK		26
> +#define CK_INFRA_SPI1_CK		27
> +#define CK_INFRA_SPI0_HCK_CK		28
> +#define CK_INFRA_SPI1_HCK_CK		29
> +#define CK_INFRA_FRTC_CK		30
> +#define CK_INFRA_MSDC_CK		31
> +#define CK_INFRA_MSDC_HCK_CK		32
> +#define CK_INFRA_MSDC_133M_CK		33
> +#define CK_INFRA_MSDC_66M_CK		34
> +#define CK_INFRA_ADC_26M_CK		35
> +#define CK_INFRA_ADC_FRC_CK		36
> +#define CK_INFRA_FBIST2FPC_CK		37
> +#define CK_INFRA_IUSB_133_CK		38
> +#define CK_INFRA_IUSB_66M_CK		39
> +#define CK_INFRA_IUSB_SYS_CK		40
> +#define CK_INFRA_IUSB_CK		41
> +#define CK_INFRA_IPCIE_CK		42
> +#define CK_INFRA_IPCIER_CK		43
> +#define CK_INFRA_IPCIEB_CK		44
> +#define CLK_INFRA_AO_NR_CLK		45
> +
> +/* APMIXEDSYS */
> +
> +#define CK_APMIXED_ARMPLL		0
> +#define CK_APMIXED_NET2PLL		1
> +#define CK_APMIXED_MMPLL		2
> +#define CK_APMIXED_SGMPLL		3
> +#define CK_APMIXED_WEDMCUPLL		4
> +#define CK_APMIXED_NET1PLL		5
> +#define CK_APMIXED_MPLL			6
> +#define CK_APMIXED_APLL2		7
> +#define CLK_APMIXED_NR_CLK		8
> +
> +/* SGMIISYS_0 */
> +
> +#define CK_SGM0_TX_EN			0
> +#define CK_SGM0_RX_EN			1
> +#define CK_SGM0_CK0_EN			2
> +#define CK_SGM0_CDR_CK0_EN		3
> +#define CLK_SGMII0_NR_CLK		4
> +
> +/* SGMIISYS_1 */
> +
> +#define CK_SGM1_TX_EN			0
> +#define CK_SGM1_RX_EN			1
> +#define CK_SGM1_CK1_EN			2
> +#define CK_SGM1_CDR_CK1_EN		3
> +#define CLK_SGMII1_NR_CLK		4
> +
> +/* ETHSYS */
> +
> +#define CK_ETH_FE_EN			0
> +#define CK_ETH_GP2_EN			1
> +#define CK_ETH_GP1_EN			2
> +#define CK_ETH_WOCPU1_EN		3
> +#define CK_ETH_WOCPU0_EN		4
> +#define CLK_ETH_NR_CLK			5
> +
> +#endif
> +
> +/* _DT_BINDINGS_CLK_MT7986_H */
> -- 
> 2.17.1
> 

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

* Re: [PATCH v2 28/32] cpu: add basic cpu driver for MediaTek ARM chips
  2022-08-31 11:05 ` [PATCH v2 28/32] cpu: add basic cpu driver for MediaTek ARM chips Weijie Gao
  2022-08-31 13:46   ` Simon Glass
@ 2022-09-01  0:28   ` Daniel Golle
  1 sibling, 0 replies; 60+ messages in thread
From: Daniel Golle @ 2022-09-01  0:28 UTC (permalink / raw)
  To: Weijie Gao; +Cc: u-boot, GSS_MTK_Uboot_upstream, Michal Simek, Ovidiu Panait

On Wed, Aug 31, 2022 at 07:05:20PM +0800, Weijie Gao wrote:
> Add basic CPU driver used to retrieve CPU model information.
> 

Tested on Bananapi BPi-R3 (MT7986A).

Tested-by: Daniel Golle <daniel@makrotopia.org>

> Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
> ---
>   v2 changes: new
> ---
>  drivers/cpu/Makefile  |   1 +
>  drivers/cpu/mtk_cpu.c | 106 ++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 107 insertions(+)
>  create mode 100644 drivers/cpu/mtk_cpu.c
> 
> diff --git a/drivers/cpu/Makefile b/drivers/cpu/Makefile
> index 20884b1795..3b38ba9c58 100644
> --- a/drivers/cpu/Makefile
> +++ b/drivers/cpu/Makefile
> @@ -9,6 +9,7 @@ obj-$(CONFIG_CPU) += cpu-uclass.o
>  obj-$(CONFIG_ARCH_BMIPS) += bmips_cpu.o
>  obj-$(CONFIG_ARCH_IMX8) += imx8_cpu.o
>  obj-$(CONFIG_ARCH_AT91) += at91_cpu.o
> +obj-$(CONFIG_ARCH_MEDIATEK) += mtk_cpu.o
>  obj-$(CONFIG_CPU_MPC83XX) += mpc83xx_cpu.o
>  obj-$(CONFIG_CPU_RISCV) += riscv_cpu.o
>  obj-$(CONFIG_CPU_MICROBLAZE) += microblaze_cpu.o
> diff --git a/drivers/cpu/mtk_cpu.c b/drivers/cpu/mtk_cpu.c
> new file mode 100644
> index 0000000000..d00b4c669e
> --- /dev/null
> +++ b/drivers/cpu/mtk_cpu.c
> @@ -0,0 +1,106 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2022 MediaTek Inc. All rights reserved.
> + *
> + * Author: Weijie Gao <weijie.gao@mediatek.com>
> + */
> +
> +#include <linux/types.h>
> +#include <cpu.h>
> +#include <dm.h>
> +#include <fdt_support.h>
> +#include <mapmem.h>
> +#include <asm/global_data.h>
> +#include <linux/io.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +struct mtk_cpu_plat {
> +	void __iomem *hwver_base;
> +};
> +
> +static int mtk_cpu_get_desc(const struct udevice *dev, char *buf, int size)
> +{
> +	struct mtk_cpu_plat *plat = dev_get_plat(dev);
> +
> +	snprintf(buf, size, "MediaTek MT%04X", readl(plat->hwver_base));
> +
> +	return 0;
> +}
> +
> +static int mtk_cpu_get_count(const struct udevice *dev)
> +{
> +	return 1;
> +}
> +
> +static int mtk_cpu_get_vendor(const struct udevice *dev, char *buf, int size)
> +{
> +	snprintf(buf, size, "MediaTek");
> +
> +	return 0;
> +}
> +
> +static int mtk_cpu_probe(struct udevice *dev)
> +{
> +	struct mtk_cpu_plat *plat = dev_get_plat(dev);
> +	const void *fdt = gd->fdt_blob, *reg;
> +	int offset, parent, len, na, ns;
> +	u64 addr;
> +
> +	if (!fdt)
> +		return -ENODEV;
> +
> +	offset = fdt_path_offset(fdt, "/hwver");
> +	if (offset < 0)
> +		return -ENODEV;
> +
> +	parent = fdt_parent_offset(fdt, offset);
> +	if (parent < 0)
> +		return -ENODEV;
> +
> +	na = fdt_address_cells(fdt, parent);
> +	if (na < 1)
> +		return -ENODEV;
> +
> +	ns = fdt_size_cells(gd->fdt_blob, parent);
> +	if (ns < 0)
> +		return -ENODEV;
> +
> +	reg = fdt_getprop(gd->fdt_blob, offset, "reg", &len);
> +	if (!reg)
> +		return -ENODEV;
> +
> +	if (ns)
> +		addr = fdt_translate_address(fdt, offset, reg);
> +	else
> +		addr = fdt_read_number(reg, na);
> +
> +	plat->hwver_base = map_sysmem(addr, 0);
> +	if (!plat->hwver_base)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +static const struct cpu_ops mtk_cpu_ops = {
> +	.get_desc	= mtk_cpu_get_desc,
> +	.get_count	= mtk_cpu_get_count,
> +	.get_vendor	= mtk_cpu_get_vendor,
> +};
> +
> +static const struct udevice_id mtk_cpu_ids[] = {
> +	{ .compatible = "arm,cortex-a7" },
> +	{ .compatible = "arm,cortex-a53" },
> +	{ .compatible = "arm,cortex-a73" },
> +	{ /* sentinel */ }
> +};
> +
> +U_BOOT_DRIVER(cpu_mtk) = {
> +	.name		= "mtk-cpu",
> +	.id		= UCLASS_CPU,
> +	.of_match	= mtk_cpu_ids,
> +	.ops		= &mtk_cpu_ops,
> +	.probe		= mtk_cpu_probe,
> +	.plat_auto	= sizeof(struct mtk_cpu_plat),
> +	.flags		= DM_FLAG_PRE_RELOC,
> +};
> -- 
> 2.17.1
> 

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

* Re: [PATCH v2 29/32] tools: mtk_image: split gfh header verification into a new function
  2022-08-31 11:05 ` [PATCH v2 29/32] tools: mtk_image: split gfh header verification into a new function Weijie Gao
@ 2022-09-01  0:31   ` Daniel Golle
  0 siblings, 0 replies; 60+ messages in thread
From: Daniel Golle @ 2022-09-01  0:31 UTC (permalink / raw)
  To: Weijie Gao; +Cc: u-boot, GSS_MTK_Uboot_upstream

On Wed, Aug 31, 2022 at 07:05:22PM +0800, Weijie Gao wrote:
> The verification code of gfh header for NAND and non-NAND are identical.
> It's better to define a individual function to reduce redundancy.

Tested ARM Trusted Firmware-A bl2 images generated for
Bananapi R64 (MT7622; eMMC, SDMMC, SPI-NAND),
UniFi 6 LR (MT7622; SPI-NOR) and
Bananapi BPi-R3 (MT7986A; eMMC, SDMMC, SPI-NAND, SPI-NOR).
Also tested MT7621 images still work fine on ZBT-WG3526 (MT7621; SPI-NOR).

Tested-by: Daniel Golle <daniel@makrotopia.org>

> 
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
> ---
> v2 changes: none
> ---
>  tools/mtk_image.c | 51 +++++++++++++++++++----------------------------
>  1 file changed, 21 insertions(+), 30 deletions(-)
> 
> diff --git a/tools/mtk_image.c b/tools/mtk_image.c
> index de5ce4d964..dcd6525f32 100644
> --- a/tools/mtk_image.c
> +++ b/tools/mtk_image.c
> @@ -480,6 +480,25 @@ static int mtk_image_vrec_header(struct image_tool_params *params,
>  	return SHA256_SUM_LEN;
>  }
>  
> +static int mtk_image_verify_gfh(struct gfh_header *gfh, uint32_t type, int print)
> +{
> +	if (strcmp(gfh->file_info.name, GFH_FILE_INFO_NAME))
> +		return -1;
> +
> +	if (le32_to_cpu(gfh->file_info.flash_type) != type)
> +		return -1;
> +
> +	if (print)
> +		printf("Load Address: %08x\n",
> +		       le32_to_cpu(gfh->file_info.load_addr) +
> +		       le32_to_cpu(gfh->file_info.jump_offset));
> +
> +	if (print)
> +		printf("Architecture: %s\n", is_arm64_image ? "ARM64" : "ARM");
> +
> +	return 0;
> +}
> +
>  static int mtk_image_verify_gen_header(const uint8_t *ptr, int print)
>  {
>  	union gen_boot_header *gbh = (union gen_boot_header *)ptr;
> @@ -542,21 +561,7 @@ static int mtk_image_verify_gen_header(const uint8_t *ptr, int print)
>  
>  	gfh = (struct gfh_header *)(ptr + gfh_offset);
>  
> -	if (strcmp(gfh->file_info.name, GFH_FILE_INFO_NAME))
> -		return -1;
> -
> -	if (le32_to_cpu(gfh->file_info.flash_type) != GFH_FLASH_TYPE_GEN)
> -		return -1;
> -
> -	if (print)
> -		printf("Load Address: %08x\n",
> -		       le32_to_cpu(gfh->file_info.load_addr) +
> -		       le32_to_cpu(gfh->file_info.jump_offset));
> -
> -	if (print)
> -		printf("Architecture: %s\n", is_arm64_image ? "ARM64" : "ARM");
> -
> -	return 0;
> +	return mtk_image_verify_gfh(gfh, GFH_FLASH_TYPE_GEN, print);
>  }
>  
>  static int mtk_image_verify_nand_header(const uint8_t *ptr, int print)
> @@ -610,21 +615,7 @@ static int mtk_image_verify_nand_header(const uint8_t *ptr, int print)
>  
>  	gfh = (struct gfh_header *)(ptr + 2 * le16_to_cpu(nh->pagesize));
>  
> -	if (strcmp(gfh->file_info.name, GFH_FILE_INFO_NAME))
> -		return -1;
> -
> -	if (le32_to_cpu(gfh->file_info.flash_type) != GFH_FLASH_TYPE_NAND)
> -		return -1;
> -
> -	if (print)
> -		printf("Load Address: %08x\n",
> -		       le32_to_cpu(gfh->file_info.load_addr) +
> -		       le32_to_cpu(gfh->file_info.jump_offset));
> -
> -	if (print)
> -		printf("Architecture: %s\n", is_arm64_image ? "ARM64" : "ARM");
> -
> -	return 0;
> +	return mtk_image_verify_gfh(gfh, GFH_FLASH_TYPE_NAND, print);
>  }
>  
>  static uint32_t crc32be_cal(const void *data, size_t length)
> -- 
> 2.17.1
> 

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

* Re: [PATCH v2 30/32] tools: mtk_image: split the code of generating NAND header into a new file
  2022-08-31 11:05 ` [PATCH v2 30/32] tools: mtk_image: split the code of generating NAND header into a new file Weijie Gao
@ 2022-09-01  0:32   ` Daniel Golle
  0 siblings, 0 replies; 60+ messages in thread
From: Daniel Golle @ 2022-09-01  0:32 UTC (permalink / raw)
  To: Weijie Gao
  Cc: u-boot, GSS_MTK_Uboot_upstream, Simon Glass, AKASHI Takahiro,
	Pali Rohár, Stefan Roese, Andre Przywara, Samuel Holland

On Wed, Aug 31, 2022 at 07:05:24PM +0800, Weijie Gao wrote:
> The predefined NAND headers take too much spaces in the mtk_image.c.
> Moving them into a new file can significantly improve the readability of
> both mtk_image.c and the new mtk_nand_headers.c.
> 
> This is a preparation for adding more NAND headers.

Tested ARM Trusted Firmware-A bl2 images generated for
Bananapi R64 (MT7622; eMMC, SDMMC, SPI-NAND),
UniFi 6 LR (MT7622; SPI-NOR) and
Bananapi BPi-R3 (MT7986A; eMMC, SDMMC, SPI-NAND, SPI-NOR).
Also tested MT7621 images still work fine on ZBT-WG3526 (MT7621; SPI-NOR).

Tested-by: Daniel Golle <daniel@makrotopia.org>

> 
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
> ---
> v2 changes:
>   Add comments
>   Call mtk_nand_header_size only for NAND/SNAND to avoid NULL pointer access
> ---
>  tools/Makefile           |   1 +
>  tools/mtk_image.c        | 305 ++++++---------------------------------
>  tools/mtk_image.h        |  25 ----
>  tools/mtk_nand_headers.c | 286 ++++++++++++++++++++++++++++++++++++
>  tools/mtk_nand_headers.h |  61 ++++++++
>  5 files changed, 389 insertions(+), 289 deletions(-)
>  create mode 100644 tools/mtk_nand_headers.c
>  create mode 100644 tools/mtk_nand_headers.h
> 
> diff --git a/tools/Makefile b/tools/Makefile
> index 3626919633..34a1aa7a8b 100644
> --- a/tools/Makefile
> +++ b/tools/Makefile
> @@ -147,6 +147,7 @@ dumpimage-mkimage-objs := aisimage.o \
>  			gpimage.o \
>  			gpimage-common.o \
>  			mtk_image.o \
> +			mtk_nand_headers.o \
>  			$(ECDSA_OBJS-y) \
>  			$(RSA_OBJS-y) \
>  			$(AES_OBJS-y)
> diff --git a/tools/mtk_image.c b/tools/mtk_image.c
> index dcd6525f32..1f7396aa69 100644
> --- a/tools/mtk_image.c
> +++ b/tools/mtk_image.c
> @@ -12,216 +12,7 @@
>  #include <u-boot/sha256.h>
>  #include "imagetool.h"
>  #include "mtk_image.h"
> -
> -/* NAND header for SPI-NAND with 2KB page + 64B spare */
> -static const union nand_boot_header snand_hdr_2k_64_data = {
> -	.data = {
> -		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> -		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> -		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> -		0x00, 0x00, 0x00, 0x08, 0x03, 0x00, 0x40, 0x00,
> -		0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x7B, 0xC4, 0x17, 0x9D,
> -		0xCA, 0x42, 0x90, 0xD0, 0x98, 0xD0, 0xE0, 0xF7,
> -		0xDB, 0xCD, 0x16, 0xF6, 0x03, 0x73, 0xD2, 0xB8,
> -		0x93, 0xB2, 0x56, 0x5A, 0x84, 0x6E, 0x00, 0x00
> -	}
> -};
> -
> -/* NAND header for SPI-NAND with 2KB page + 120B/128B spare */
> -static const union nand_boot_header snand_hdr_2k_128_data = {
> -	.data = {
> -		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> -		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> -		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> -		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
> -		0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x90, 0x28, 0xED, 0x13,
> -		0x7F, 0x12, 0x22, 0xCD, 0x3D, 0x06, 0xF1, 0xB3,
> -		0x6F, 0x2E, 0xD9, 0xA0, 0x9D, 0x7A, 0xBD, 0xD7,
> -		0xB3, 0x28, 0x3C, 0x13, 0xDB, 0x4E, 0x00, 0x00
> -	}
> -};
> -
> -/* NAND header for SPI-NAND with 4KB page + 256B spare */
> -static const union nand_boot_header snand_hdr_4k_256_data = {
> -	.data = {
> -		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> -		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> -		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> -		0x00, 0x00, 0x00, 0x10, 0x05, 0x00, 0xE0, 0x00,
> -		0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x47, 0xED, 0x0E, 0xC3,
> -		0x83, 0xBF, 0x41, 0xD2, 0x85, 0x21, 0x97, 0x57,
> -		0xC4, 0x2E, 0x6B, 0x7A, 0x40, 0xE0, 0xCF, 0x8F,
> -		0x37, 0xBD, 0x17, 0xB6, 0xC7, 0xFE, 0x00, 0x00
> -	}
> -};
> -
> -/* NAND header for Parallel NAND 1Gb with 2KB page + 64B spare */
> -static const union nand_boot_header nand_hdr_1gb_2k_64_data = {
> -	.data = {
> -		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> -		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> -		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> -		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
> -		0x40, 0x00, 0x00, 0x04, 0x0B, 0x00, 0x11, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x12, 0x28, 0x1C, 0x12,
> -		0x8F, 0xFD, 0xF8, 0x32, 0x6F, 0x6D, 0xCF, 0x6C,
> -		0xDA, 0x21, 0x70, 0x8C, 0xDA, 0x0A, 0x22, 0x82,
> -		0xAA, 0x59, 0xFA, 0x7C, 0x42, 0x2D, 0x00, 0x00
> -	}
> -};
> -
> -/* NAND header for Parallel NAND 2Gb with 2KB page + 64B spare */
> -static const union nand_boot_header nand_hdr_2gb_2k_64_data = {
> -	.data = {
> -		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> -		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> -		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> -		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
> -		0x40, 0x00, 0x00, 0x08, 0x0B, 0x00, 0x11, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x20, 0x9C, 0x3D, 0x2D,
> -		0x7B, 0x68, 0x63, 0x52, 0x2E, 0x04, 0x63, 0xF1,
> -		0x35, 0x4E, 0x44, 0x3E, 0xF8, 0xAC, 0x9B, 0x95,
> -		0xAB, 0xFE, 0xE4, 0xE1, 0xD5, 0xF9, 0x00, 0x00
> -	}
> -};
> -
> -/* NAND header for Parallel NAND 4Gb with 2KB page + 64B spare */
> -static const union nand_boot_header nand_hdr_4gb_2k_64_data = {
> -	.data = {
> -		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> -		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> -		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> -		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
> -		0x40, 0x00, 0x00, 0x10, 0x0B, 0x00, 0x11, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0xE3, 0x0F, 0x86, 0x32,
> -		0x68, 0x05, 0xD9, 0xC8, 0x13, 0xDF, 0xC5, 0x0B,
> -		0x35, 0x3A, 0x68, 0xA5, 0x3C, 0x0C, 0x73, 0x87,
> -		0x63, 0xB0, 0xBE, 0xCC, 0x84, 0x47, 0x00, 0x00
> -	}
> -};
> -
> -/* NAND header for Parallel NAND 2Gb with 2KB page + 128B spare */
> -static const union nand_boot_header nand_hdr_2gb_2k_128_data = {
> -	.data = {
> -		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> -		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> -		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> -		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
> -		0x40, 0x00, 0x00, 0x08, 0x0B, 0x00, 0x11, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x01, 0xA5, 0xE9, 0x5A,
> -		0xDF, 0x58, 0x62, 0x41, 0xD6, 0x26, 0x77, 0xBC,
> -		0x76, 0x1F, 0x27, 0x4E, 0x4F, 0x6C, 0xC3, 0xF0,
> -		0x36, 0xDE, 0xD9, 0xB3, 0xFF, 0x93, 0x00, 0x00
> -	}
> -};
> -
> -/* NAND header for Parallel NAND 4Gb with 2KB page + 128B spare */
> -static const union nand_boot_header nand_hdr_4gb_2k_128_data = {
> -	.data = {
> -		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> -		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> -		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> -		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
> -		0x40, 0x00, 0x00, 0x10, 0x0B, 0x00, 0x11, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0xC2, 0x36, 0x52, 0x45,
> -		0xCC, 0x35, 0xD8, 0xDB, 0xEB, 0xFD, 0xD1, 0x46,
> -		0x76, 0x6B, 0x0B, 0xD5, 0x8B, 0xCC, 0x2B, 0xE2,
> -		0xFE, 0x90, 0x83, 0x9E, 0xAE, 0x2D, 0x00, 0x00
> -	}
> -};
> -
> -static const struct nand_header_type {
> -	const char *name;
> -	const union nand_boot_header *data;
> -} nand_headers[] = {
> -	{
> -		.name = "2k+64",
> -		.data = &snand_hdr_2k_64_data
> -	}, {
> -		.name = "2k+120",
> -		.data = &snand_hdr_2k_128_data
> -	}, {
> -		.name = "2k+128",
> -		.data = &snand_hdr_2k_128_data
> -	}, {
> -		.name = "4k+256",
> -		.data = &snand_hdr_4k_256_data
> -	}, {
> -		.name = "1g:2k+64",
> -		.data = &nand_hdr_1gb_2k_64_data
> -	}, {
> -		.name = "2g:2k+64",
> -		.data = &nand_hdr_2gb_2k_64_data
> -	}, {
> -		.name = "4g:2k+64",
> -		.data = &nand_hdr_4gb_2k_64_data
> -	}, {
> -		.name = "2g:2k+128",
> -		.data = &nand_hdr_2gb_2k_128_data
> -	}, {
> -		.name = "4g:2k+128",
> -		.data = &nand_hdr_4gb_2k_128_data
> -	}
> -};
> +#include "mtk_nand_headers.h"
>  
>  static const struct brom_img_type {
>  	const char *name;
> @@ -264,6 +55,7 @@ static uint32_t crc32tbl[256];
>  
>  /* NAND header selected by user */
>  static const union nand_boot_header *hdr_nand;
> +static uint32_t hdr_nand_size;
>  
>  /* GFH header + 2 * 4KB pages of NAND */
>  static char hdr_tmp[sizeof(struct gfh_header) + 0x2000];
> @@ -402,12 +194,7 @@ static int mtk_brom_parse_imagename(const char *imagename)
>  	}
>  
>  	/* parse nand header type */
> -	for (i = 0; i < ARRAY_SIZE(nand_headers); i++) {
> -		if (!strcmp(nand_headers[i].name, nandinfo)) {
> -			hdr_nand = nand_headers[i].data;
> -			break;
> -		}
> -	}
> +	hdr_nand = mtk_nand_header_find(nandinfo);
>  
>  	/* parse device header offset */
>  	if (hdr_offs && hdr_offs[0])
> @@ -432,6 +219,9 @@ static int mtk_brom_parse_imagename(const char *imagename)
>  		return -EINVAL;
>  	}
>  
> +	if (hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND)
> +		hdr_nand_size = mtk_nand_header_size(hdr_nand);
> +
>  	return 0;
>  }
>  
> @@ -468,7 +258,7 @@ static int mtk_image_vrec_header(struct image_tool_params *params,
>  	}
>  
>  	if (hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND)
> -		tparams->header_size = 2 * le16_to_cpu(hdr_nand->pagesize);
> +		tparams->header_size = hdr_nand_size;
>  	else
>  		tparams->header_size = sizeof(struct gen_device_header);
>  
> @@ -566,16 +356,17 @@ static int mtk_image_verify_gen_header(const uint8_t *ptr, int print)
>  
>  static int mtk_image_verify_nand_header(const uint8_t *ptr, int print)
>  {
> -	union nand_boot_header *nh = (union nand_boot_header *)ptr;
>  	struct brom_layout_header *bh;
> +	struct nand_header_info info;
>  	struct gfh_header *gfh;
>  	const char *bootmedia;
> +	int ret;
>  
> -	if (strncmp(nh->version, NAND_BOOT_VERSION, sizeof(nh->version)) ||
> -	    strcmp(nh->id, NAND_BOOT_ID))
> -		return -1;
> +	ret = mtk_nand_header_info(ptr, &info);
> +	if (ret < 0)
> +		return ret;
>  
> -	bh = (struct brom_layout_header *)(ptr + le16_to_cpu(nh->pagesize));
> +	bh = (struct brom_layout_header *)(ptr + info.page_size);
>  
>  	if (strcmp(bh->name, BRLYT_NAME))
>  		return -1;
> @@ -586,34 +377,23 @@ static int mtk_image_verify_nand_header(const uint8_t *ptr, int print)
>  		if (le32_to_cpu(bh->type) == BRLYT_TYPE_NAND)
>  			bootmedia = "Parallel NAND";
>  		else if (le32_to_cpu(bh->type) == BRLYT_TYPE_SNAND)
> -			bootmedia = "Serial NAND";
> +			bootmedia = "Serial NAND (SNFI/AP)";
>  		else
>  			return -1;
>  	}
>  
>  	if (print) {
> -		printf("Boot Media: %s\n", bootmedia);
> -
> -		if (le32_to_cpu(bh->type) == BRLYT_TYPE_NAND) {
> -			uint64_t capacity =
> -				(uint64_t)le16_to_cpu(nh->numblocks) *
> -				(uint64_t)le16_to_cpu(nh->pages_of_block) *
> -				(uint64_t)le16_to_cpu(nh->pagesize) * 8;
> -			printf("Capacity:     %dGb\n",
> -			       (uint32_t)(capacity >> 30));
> -		}
> +		printf("Boot Media:   %s\n", bootmedia);
>  
> -		if (le16_to_cpu(nh->pagesize) >= 1024)
> -			printf("Page Size:    %dKB\n",
> -			       le16_to_cpu(nh->pagesize) >> 10);
> +		if (info.page_size >= 1024)
> +			printf("Page Size:    %dKB\n", info.page_size >> 10);
>  		else
> -			printf("Page Size:    %dB\n",
> -			       le16_to_cpu(nh->pagesize));
> +			printf("Page Size:    %dB\n", info.page_size);
>  
> -		printf("Spare Size:   %dB\n", le16_to_cpu(nh->oobsize));
> +		printf("Spare Size:   %dB\n", info.spare_size);
>  	}
>  
> -	gfh = (struct gfh_header *)(ptr + 2 * le16_to_cpu(nh->pagesize));
> +	gfh = (struct gfh_header *)(ptr + info.gfh_offset);
>  
>  	return mtk_image_verify_gfh(gfh, GFH_FLASH_TYPE_NAND, print);
>  }
> @@ -713,7 +493,7 @@ static int mtk_image_verify_header(unsigned char *ptr, int image_size,
>  	if (image_get_magic(hdr) == IH_MAGIC)
>  		return mtk_image_verify_mt7621_header(ptr, 0);
>  
> -	if (!strcmp((char *)ptr, NAND_BOOT_NAME))
> +	if (is_mtk_nand_header(ptr))
>  		return mtk_image_verify_nand_header(ptr, 0);
>  	else
>  		return mtk_image_verify_gen_header(ptr, 0);
> @@ -739,7 +519,7 @@ static void mtk_image_print_header(const void *ptr)
>  		return;
>  	}
>  
> -	if (!strcmp((char *)ptr, NAND_BOOT_NAME))
> +	if (is_mtk_nand_header(ptr))
>  		mtk_image_verify_nand_header(ptr, 1);
>  	else
>  		mtk_image_verify_gen_header(ptr, 1);
> @@ -870,36 +650,33 @@ static void mtk_image_set_gen_header(void *ptr, off_t filesize,
>  static void mtk_image_set_nand_header(void *ptr, off_t filesize,
>  				      uint32_t loadaddr)
>  {
> -	union nand_boot_header *nh = (union nand_boot_header *)ptr;
>  	struct brom_layout_header *brlyt;
>  	struct gfh_header *gfh;
> -	uint32_t payload_pages;
> -	int i;
> +	uint32_t payload_pages, nand_page_size;
>  
> -	/* NAND device header, repeat 4 times */
> -	for (i = 0; i < 4; i++)
> -		memcpy(nh + i, hdr_nand, sizeof(union nand_boot_header));
> +	/* NAND header */
> +	nand_page_size = mtk_nand_header_put(hdr_nand, ptr);
>  
> -	/* BRLYT header */
> -	payload_pages = (filesize + le16_to_cpu(hdr_nand->pagesize) - 1) /
> -			le16_to_cpu(hdr_nand->pagesize);
> -	brlyt = (struct brom_layout_header *)
> -		(ptr + le16_to_cpu(hdr_nand->pagesize));
> -	put_brom_layout_header(brlyt, hdr_media);
> -	brlyt->header_size = cpu_to_le32(2);
> -	brlyt->total_size = cpu_to_le32(payload_pages);
> -	brlyt->header_size_2 = brlyt->header_size;
> -	brlyt->total_size_2 = brlyt->total_size;
> -	brlyt->unused = cpu_to_le32(1);
> +	if (nand_page_size) {
> +		/* BRLYT header */
> +		payload_pages = (filesize + nand_page_size - 1) /
> +				nand_page_size;
> +		brlyt = (struct brom_layout_header *)(ptr + nand_page_size);
> +		put_brom_layout_header(brlyt, hdr_media);
> +		brlyt->header_size = cpu_to_le32(2);
> +		brlyt->total_size = cpu_to_le32(payload_pages);
> +		brlyt->header_size_2 = brlyt->header_size;
> +		brlyt->total_size_2 = brlyt->total_size;
> +		brlyt->unused = cpu_to_le32(1);
> +	}
>  
>  	/* GFH header */
> -	gfh = (struct gfh_header *)(ptr + 2 * le16_to_cpu(hdr_nand->pagesize));
> -	put_ghf_header(gfh, filesize, 2 * le16_to_cpu(hdr_nand->pagesize),
> -		       loadaddr, GFH_FLASH_TYPE_NAND);
> +	gfh = (struct gfh_header *)(ptr + hdr_nand_size);
> +	put_ghf_header(gfh, filesize, hdr_nand_size, loadaddr,
> +		       GFH_FLASH_TYPE_NAND);
>  
>  	/* Generate SHA256 hash */
> -	put_hash((uint8_t *)gfh,
> -		 filesize - 2 * le16_to_cpu(hdr_nand->pagesize) - SHA256_SUM_LEN);
> +	put_hash((uint8_t *)gfh, filesize - hdr_nand_size - SHA256_SUM_LEN);
>  }
>  
>  static void mtk_image_set_mt7621_header(void *ptr, off_t filesize,
> diff --git a/tools/mtk_image.h b/tools/mtk_image.h
> index d868545a33..fad9372100 100644
> --- a/tools/mtk_image.h
> +++ b/tools/mtk_image.h
> @@ -26,31 +26,6 @@ union gen_boot_header {
>  #define SF_BOOT_NAME		"SF_BOOT"
>  #define SDMMC_BOOT_NAME		"SDMMC_BOOT"
>  
> -/* Header for NAND */
> -union nand_boot_header {
> -	struct {
> -		char name[12];
> -		char version[4];
> -		char id[8];
> -		uint16_t ioif;
> -		uint16_t pagesize;
> -		uint16_t addrcycles;
> -		uint16_t oobsize;
> -		uint16_t pages_of_block;
> -		uint16_t numblocks;
> -		uint16_t writesize_shift;
> -		uint16_t erasesize_shift;
> -		uint8_t dummy[60];
> -		uint8_t ecc_parity[28];
> -	};
> -
> -	uint8_t data[0x80];
> -};
> -
> -#define NAND_BOOT_NAME		"BOOTLOADER!"
> -#define NAND_BOOT_VERSION	"V006"
> -#define NAND_BOOT_ID		"NFIINFO"
> -
>  /* BootROM layout header */
>  struct brom_layout_header {
>  	char name[8];
> diff --git a/tools/mtk_nand_headers.c b/tools/mtk_nand_headers.c
> new file mode 100644
> index 0000000000..12f827c39f
> --- /dev/null
> +++ b/tools/mtk_nand_headers.c
> @@ -0,0 +1,286 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * MediaTek BootROM NAND header definitions
> + *
> + * Copyright (C) 2022 MediaTek Inc.
> + * Author: Weijie Gao <weijie.gao@mediatek.com>
> + */
> +
> +#include <stdint.h>
> +#include <string.h>
> +#include "imagetool.h"
> +#include "mtk_image.h"
> +#include "mtk_nand_headers.h"
> +
> +/* NAND header for SPI-NAND with 2KB page + 64B spare */
> +static const union nand_boot_header snand_hdr_2k_64_data = {
> +	.data = {
> +		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> +		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> +		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> +		0x00, 0x00, 0x00, 0x08, 0x03, 0x00, 0x40, 0x00,
> +		0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x7B, 0xC4, 0x17, 0x9D,
> +		0xCA, 0x42, 0x90, 0xD0, 0x98, 0xD0, 0xE0, 0xF7,
> +		0xDB, 0xCD, 0x16, 0xF6, 0x03, 0x73, 0xD2, 0xB8,
> +		0x93, 0xB2, 0x56, 0x5A, 0x84, 0x6E, 0x00, 0x00
> +	}
> +};
> +
> +/* NAND header for SPI-NAND with 2KB page + 120B/128B spare */
> +static const union nand_boot_header snand_hdr_2k_128_data = {
> +	.data = {
> +		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> +		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> +		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> +		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
> +		0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x90, 0x28, 0xED, 0x13,
> +		0x7F, 0x12, 0x22, 0xCD, 0x3D, 0x06, 0xF1, 0xB3,
> +		0x6F, 0x2E, 0xD9, 0xA0, 0x9D, 0x7A, 0xBD, 0xD7,
> +		0xB3, 0x28, 0x3C, 0x13, 0xDB, 0x4E, 0x00, 0x00
> +	}
> +};
> +
> +/* NAND header for SPI-NAND with 4KB page + 256B spare */
> +static const union nand_boot_header snand_hdr_4k_256_data = {
> +	.data = {
> +		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> +		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> +		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> +		0x00, 0x00, 0x00, 0x10, 0x05, 0x00, 0xE0, 0x00,
> +		0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x47, 0xED, 0x0E, 0xC3,
> +		0x83, 0xBF, 0x41, 0xD2, 0x85, 0x21, 0x97, 0x57,
> +		0xC4, 0x2E, 0x6B, 0x7A, 0x40, 0xE0, 0xCF, 0x8F,
> +		0x37, 0xBD, 0x17, 0xB6, 0xC7, 0xFE, 0x00, 0x00
> +	}
> +};
> +
> +/* NAND header for Parallel NAND 1Gb with 2KB page + 64B spare */
> +static const union nand_boot_header nand_hdr_1gb_2k_64_data = {
> +	.data = {
> +		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> +		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> +		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> +		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
> +		0x40, 0x00, 0x00, 0x04, 0x0B, 0x00, 0x11, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x12, 0x28, 0x1C, 0x12,
> +		0x8F, 0xFD, 0xF8, 0x32, 0x6F, 0x6D, 0xCF, 0x6C,
> +		0xDA, 0x21, 0x70, 0x8C, 0xDA, 0x0A, 0x22, 0x82,
> +		0xAA, 0x59, 0xFA, 0x7C, 0x42, 0x2D, 0x00, 0x00
> +	}
> +};
> +
> +/* NAND header for Parallel NAND 2Gb with 2KB page + 64B spare */
> +static const union nand_boot_header nand_hdr_2gb_2k_64_data = {
> +	.data = {
> +		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> +		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> +		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> +		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
> +		0x40, 0x00, 0x00, 0x08, 0x0B, 0x00, 0x11, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x20, 0x9C, 0x3D, 0x2D,
> +		0x7B, 0x68, 0x63, 0x52, 0x2E, 0x04, 0x63, 0xF1,
> +		0x35, 0x4E, 0x44, 0x3E, 0xF8, 0xAC, 0x9B, 0x95,
> +		0xAB, 0xFE, 0xE4, 0xE1, 0xD5, 0xF9, 0x00, 0x00
> +	}
> +};
> +
> +/* NAND header for Parallel NAND 4Gb with 2KB page + 64B spare */
> +static const union nand_boot_header nand_hdr_4gb_2k_64_data = {
> +	.data = {
> +		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> +		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> +		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> +		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
> +		0x40, 0x00, 0x00, 0x10, 0x0B, 0x00, 0x11, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0xE3, 0x0F, 0x86, 0x32,
> +		0x68, 0x05, 0xD9, 0xC8, 0x13, 0xDF, 0xC5, 0x0B,
> +		0x35, 0x3A, 0x68, 0xA5, 0x3C, 0x0C, 0x73, 0x87,
> +		0x63, 0xB0, 0xBE, 0xCC, 0x84, 0x47, 0x00, 0x00
> +	}
> +};
> +
> +/* NAND header for Parallel NAND 2Gb with 2KB page + 128B spare */
> +static const union nand_boot_header nand_hdr_2gb_2k_128_data = {
> +	.data = {
> +		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> +		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> +		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> +		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
> +		0x40, 0x00, 0x00, 0x08, 0x0B, 0x00, 0x11, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x01, 0xA5, 0xE9, 0x5A,
> +		0xDF, 0x58, 0x62, 0x41, 0xD6, 0x26, 0x77, 0xBC,
> +		0x76, 0x1F, 0x27, 0x4E, 0x4F, 0x6C, 0xC3, 0xF0,
> +		0x36, 0xDE, 0xD9, 0xB3, 0xFF, 0x93, 0x00, 0x00
> +	}
> +};
> +
> +/* NAND header for Parallel NAND 4Gb with 2KB page + 128B spare */
> +static const union nand_boot_header nand_hdr_4gb_2k_128_data = {
> +	.data = {
> +		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> +		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> +		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> +		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
> +		0x40, 0x00, 0x00, 0x10, 0x0B, 0x00, 0x11, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0xC2, 0x36, 0x52, 0x45,
> +		0xCC, 0x35, 0xD8, 0xDB, 0xEB, 0xFD, 0xD1, 0x46,
> +		0x76, 0x6B, 0x0B, 0xD5, 0x8B, 0xCC, 0x2B, 0xE2,
> +		0xFE, 0x90, 0x83, 0x9E, 0xAE, 0x2D, 0x00, 0x00
> +	}
> +};
> +
> +static const struct nand_header_type {
> +	const char *name;
> +	const union nand_boot_header *data;
> +} nand_headers[] = {
> +	{
> +		.name = "2k+64",
> +		.data = &snand_hdr_2k_64_data
> +	}, {
> +		.name = "2k+120",
> +		.data = &snand_hdr_2k_128_data
> +	}, {
> +		.name = "2k+128",
> +		.data = &snand_hdr_2k_128_data
> +	}, {
> +		.name = "4k+256",
> +		.data = &snand_hdr_4k_256_data
> +	}, {
> +		.name = "1g:2k+64",
> +		.data = &nand_hdr_1gb_2k_64_data
> +	}, {
> +		.name = "2g:2k+64",
> +		.data = &nand_hdr_2gb_2k_64_data
> +	}, {
> +		.name = "4g:2k+64",
> +		.data = &nand_hdr_4gb_2k_64_data
> +	}, {
> +		.name = "2g:2k+128",
> +		.data = &nand_hdr_2gb_2k_128_data
> +	}, {
> +		.name = "4g:2k+128",
> +		.data = &nand_hdr_4gb_2k_128_data
> +	}
> +};
> +
> +const union nand_boot_header *mtk_nand_header_find(const char *name)
> +{
> +	uint32_t i;
> +
> +	for (i = 0; i < ARRAY_SIZE(nand_headers); i++) {
> +		if (!strcmp(nand_headers[i].name, name))
> +			return nand_headers[i].data;
> +	}
> +
> +	return NULL;
> +}
> +
> +uint32_t mtk_nand_header_size(const union nand_boot_header *hdr_nand)
> +{
> +	return 2 * le16_to_cpu(hdr_nand->pagesize);
> +}
> +
> +static int mtk_nand_header_ap_info(const void *ptr,
> +				   struct nand_header_info *info)
> +{
> +	union nand_boot_header *nh = (union nand_boot_header *)ptr;
> +
> +	if (strncmp(nh->version, NAND_BOOT_VERSION, sizeof(nh->version)) ||
> +	    strcmp(nh->id, NAND_BOOT_ID))
> +		return -1;
> +
> +	info->page_size = le16_to_cpu(nh->pagesize);
> +	info->spare_size = le16_to_cpu(nh->oobsize);
> +	info->gfh_offset = 2 * info->page_size;
> +
> +	return 0;
> +}
> +
> +int mtk_nand_header_info(const void *ptr, struct nand_header_info *info)
> +{
> +	if (!strcmp((char *)ptr, NAND_BOOT_NAME))
> +		return mtk_nand_header_ap_info(ptr, info);
> +
> +	return -1;
> +}
> +
> +bool is_mtk_nand_header(const void *ptr)
> +{
> +	struct nand_header_info info;
> +
> +	if (mtk_nand_header_info(ptr, &info) >= 0)
> +		return true;
> +
> +	return false;
> +}
> +
> +uint32_t mtk_nand_header_put(const union nand_boot_header *hdr_nand, void *ptr)
> +{
> +	union nand_boot_header *nh = (union nand_boot_header *)ptr;
> +	int i;
> +
> +	/* NAND device header, repeat 4 times */
> +	for (i = 0; i < 4; i++)
> +		memcpy(nh + i, hdr_nand, sizeof(union nand_boot_header));
> +
> +	return le16_to_cpu(hdr_nand->pagesize);
> +}
> diff --git a/tools/mtk_nand_headers.h b/tools/mtk_nand_headers.h
> new file mode 100644
> index 0000000000..20506cab38
> --- /dev/null
> +++ b/tools/mtk_nand_headers.h
> @@ -0,0 +1,61 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * MediaTek BootROM NAND header definitions
> + *
> + * Copyright (C) 2022 MediaTek Inc.
> + * Author: Weijie Gao <weijie.gao@mediatek.com>
> + */
> +
> +#ifndef _MTK_NAND_HEADERS_H
> +#define _MTK_NAND_HEADERS_H
> +
> +#include <stdint.h>
> +#include <stdbool.h>
> +
> +struct nand_header_info {
> +	uint32_t page_size;
> +	uint32_t spare_size;
> +	uint32_t gfh_offset;
> +};
> +
> +/* AP BROM Header for NAND */
> +union nand_boot_header {
> +	struct {
> +		char name[12];
> +		char version[4];
> +		char id[8];
> +		uint16_t ioif;			/* I/O interface */
> +		uint16_t pagesize;		/* NAND page size */
> +		uint16_t addrcycles;		/* Address cycles */
> +		uint16_t oobsize;		/* NAND page spare size */
> +		uint16_t pages_of_block;	/* Pages of one block */
> +		uint16_t numblocks;		/* Total blocks of NAND chip */
> +		uint16_t writesize_shift;
> +		uint16_t erasesize_shift;
> +		uint8_t dummy[60];
> +		uint8_t ecc_parity[28];		/* ECC parity of this header */
> +	};
> +
> +	uint8_t data[0x80];
> +};
> +
> +#define NAND_BOOT_NAME		"BOOTLOADER!"
> +#define NAND_BOOT_VERSION	"V006"
> +#define NAND_BOOT_ID		"NFIINFO"
> +
> +/* Find nand header data by name */
> +const union nand_boot_header *mtk_nand_header_find(const char *name);
> +
> +/* Device header size using this nand header */
> +uint32_t mtk_nand_header_size(const union nand_boot_header *hdr_nand);
> +
> +/* Get nand info from nand header (page size, spare size, ...) */
> +int mtk_nand_header_info(const void *ptr, struct nand_header_info *info);
> +
> +/* Whether given header data is valid */
> +bool is_mtk_nand_header(const void *ptr);
> +
> +/* Generate Device header using give nand header */
> +uint32_t mtk_nand_header_put(const union nand_boot_header *hdr_nand, void *ptr);
> +
> +#endif /* _MTK_NAND_HEADERS_H */
> -- 
> 2.17.1
> 

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

* Re: [PATCH v2 31/32] tools: mtk_image: add support for nand headers used by newer chips
  2022-08-31 11:05 ` [PATCH v2 31/32] tools: mtk_image: add support for nand headers used by newer chips Weijie Gao
@ 2022-09-01  0:32   ` Daniel Golle
  0 siblings, 0 replies; 60+ messages in thread
From: Daniel Golle @ 2022-09-01  0:32 UTC (permalink / raw)
  To: Weijie Gao; +Cc: u-boot, GSS_MTK_Uboot_upstream

On Wed, Aug 31, 2022 at 07:05:26PM +0800, Weijie Gao wrote:
> This patch adds more nand headers in two new types:
> 1. HSM header, used for spi-nand thru SNFI interface
> 2. SPIM header, used for spi-nand thru spi-mem interface
> 
> The original nand header is renamed to AP header.

Tested ARM Trusted Firmware-A bl2 images generated for
Bananapi R64 (MT7622; eMMC, SDMMC, SPI-NAND),
UniFi 6 LR (MT7622; SPI-NOR) and
Bananapi BPi-R3 (MT7986A; eMMC, SDMMC, SPI-NAND, SPI-NOR).
Also tested MT7621 images still work fine on ZBT-WG3526 (MT7621; SPI-NOR).

Tested-by: Daniel Golle <daniel@makrotopia.org>

> 
> Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
> ---
> v2 changes: none
> ---
>  tools/mtk_image.c        |  23 ++-
>  tools/mtk_nand_headers.c | 422 +++++++++++++++++++++++++++++++++++++--
>  tools/mtk_nand_headers.h | 110 +++++++++-
>  3 files changed, 525 insertions(+), 30 deletions(-)
> 
> diff --git a/tools/mtk_image.c b/tools/mtk_image.c
> index 1f7396aa69..9b3136afa3 100644
> --- a/tools/mtk_image.c
> +++ b/tools/mtk_image.c
> @@ -33,6 +33,9 @@ static const struct brom_img_type {
>  	}, {
>  		.name = "snand",
>  		.type = BRLYT_TYPE_SNAND
> +	}, {
> +		.name = "spim-nand",
> +		.type = BRLYT_TYPE_SNAND
>  	}
>  };
>  
> @@ -54,7 +57,7 @@ static char lk_name[32] = "U-Boot";
>  static uint32_t crc32tbl[256];
>  
>  /* NAND header selected by user */
> -static const union nand_boot_header *hdr_nand;
> +static const struct nand_header_type *hdr_nand;
>  static uint32_t hdr_nand_size;
>  
>  /* GFH header + 2 * 4KB pages of NAND */
> @@ -366,20 +369,26 @@ static int mtk_image_verify_nand_header(const uint8_t *ptr, int print)
>  	if (ret < 0)
>  		return ret;
>  
> -	bh = (struct brom_layout_header *)(ptr + info.page_size);
> +	if (!ret) {
> +		bh = (struct brom_layout_header *)(ptr + info.page_size);
>  
> -	if (strcmp(bh->name, BRLYT_NAME))
> -		return -1;
> +		if (strcmp(bh->name, BRLYT_NAME))
> +			return -1;
> +
> +		if (le32_to_cpu(bh->magic) != BRLYT_MAGIC)
> +			return -1;
>  
> -	if (le32_to_cpu(bh->magic) != BRLYT_MAGIC) {
> -		return -1;
> -	} else {
>  		if (le32_to_cpu(bh->type) == BRLYT_TYPE_NAND)
>  			bootmedia = "Parallel NAND";
>  		else if (le32_to_cpu(bh->type) == BRLYT_TYPE_SNAND)
>  			bootmedia = "Serial NAND (SNFI/AP)";
>  		else
>  			return -1;
> +	} else {
> +		if (info.snfi)
> +			bootmedia = "Serial NAND (SNFI/HSM)";
> +		else
> +			bootmedia = "Serial NAND (SPIM)";
>  	}
>  
>  	if (print) {
> diff --git a/tools/mtk_nand_headers.c b/tools/mtk_nand_headers.c
> index 12f827c39f..2fa91e7af0 100644
> --- a/tools/mtk_nand_headers.c
> +++ b/tools/mtk_nand_headers.c
> @@ -188,55 +188,346 @@ static const union nand_boot_header nand_hdr_4gb_2k_128_data = {
>  	}
>  };
>  
> -static const struct nand_header_type {
> +/* HSM BROM NAND header for SPI NAND with 2KB page + 64B spare */
> +static const union hsm_nand_boot_header hsm_nand_hdr_2k_64_data = {
> +	.data = {
> +		0x4E, 0x41, 0x4E, 0x44, 0x43, 0x46, 0x47, 0x21,
> +		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
> +		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x08, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
> +		0x40, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
> +		0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
> +		0xFF, 0x00, 0x00, 0x00, 0x21, 0xD2, 0xEE, 0xF6,
> +		0xAE, 0xDD, 0x5E, 0xC2, 0x82, 0x8E, 0x9A, 0x62,
> +		0x09, 0x8E, 0x80, 0xE2, 0x37, 0x0D, 0xC9, 0xFA,
> +		0xA9, 0xDD, 0xFC, 0x92, 0x34, 0x2A, 0xED, 0x51,
> +		0xA4, 0x1B, 0xF7, 0x63, 0xCC, 0x5A, 0xC7, 0xFB,
> +		0xED, 0x21, 0x02, 0x23, 0x51, 0x31
> +	}
> +};
> +
> +/* HSM BROM NAND header for SPI NAND with 2KB page + 128B spare */
> +static const union hsm_nand_boot_header hsm_nand_hdr_2k_128_data = {
> +	.data = {
> +		0x4E, 0x41, 0x4E, 0x44, 0x43, 0x46, 0x47, 0x21,
> +		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
> +		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x08, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
> +		0x40, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
> +		0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
> +		0xFF, 0x00, 0x00, 0x00, 0x71, 0x7f, 0x71, 0xAC,
> +		0x42, 0xD0, 0x5B, 0xD2, 0x12, 0x81, 0x15, 0x0A,
> +		0x0C, 0xD4, 0xF6, 0x32, 0x1E, 0x63, 0xE7, 0x81,
> +		0x8A, 0x7F, 0xDE, 0xF9, 0x4B, 0x91, 0xEC, 0xC2,
> +		0x70, 0x00, 0x7F, 0x57, 0xAF, 0xDC, 0xE4, 0x24,
> +		0x57, 0x09, 0xBC, 0xC5, 0x35, 0xDC
> +	}
> +};
> +
> +/* HSM BROM NAND header for SPI NAND with 4KB page + 256B spare */
> +static const union hsm_nand_boot_header hsm_nand_hdr_4k_256_data = {
> +	.data = {
> +		0x4E, 0x41, 0x4E, 0x44, 0x43, 0x46, 0x47, 0x21,
> +		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
> +		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
> +		0x40, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
> +		0x0C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
> +		0xFF, 0x00, 0x00, 0x00, 0x62, 0x04, 0xD6, 0x1F,
> +		0x2B, 0x57, 0x7A, 0x2D, 0xFE, 0xBB, 0x4A, 0x50,
> +		0xEC, 0xF8, 0x70, 0x1A, 0x44, 0x15, 0xF6, 0xA2,
> +		0x8E, 0xB0, 0xFD, 0xFA, 0xDC, 0xAA, 0x5A, 0x4E,
> +		0xCB, 0x8E, 0xC9, 0x72, 0x08, 0xDC, 0x20, 0xB9,
> +		0x98, 0xC8, 0x82, 0xD8, 0xBE, 0x44
> +	}
> +};
> +
> +/* HSM2.0 BROM NAND header for SPI NAND with 2KB page + 64B spare */
> +static const union hsm20_nand_boot_header hsm20_nand_hdr_2k_64_data = {
> +	.data = {
> +		0x4E, 0x41, 0x4E, 0x44, 0x43, 0x46, 0x47, 0x21,
> +		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
> +		0x00, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
> +		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x08, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
> +		0x40, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
> +		0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
> +		0x01, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00,
> +		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x5F, 0x4B, 0xB2, 0x5B, 0x8B, 0x1C, 0x35, 0xDA,
> +		0x83, 0xE6, 0x6C, 0xC3, 0xFB, 0x8C, 0x78, 0x23,
> +		0xD0, 0x89, 0x24, 0xD9, 0x6C, 0x35, 0x2C, 0x5D,
> +		0x8F, 0xBB, 0xFC, 0x10, 0xD0, 0xE2, 0x22, 0x7D,
> +		0xC8, 0x97, 0x9A, 0xEF, 0xC6, 0xB5, 0xA7, 0x4E,
> +		0x4E, 0x0E
> +	}
> +};
> +
> +/* HSM2.0 BROM NAND header for SPI NAND with 2KB page + 128B spare */
> +static const union hsm20_nand_boot_header hsm20_nand_hdr_2k_128_data = {
> +	.data = {
> +		0x4E, 0x41, 0x4E, 0x44, 0x43, 0x46, 0x47, 0x21,
> +		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
> +		0x00, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
> +		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x08, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
> +		0x40, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
> +		0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
> +		0x01, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00,
> +		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0xF8, 0x7E, 0xC1, 0x5D, 0x61, 0x54, 0xEA, 0x9F,
> +		0x5E, 0x66, 0x39, 0x66, 0x21, 0xFF, 0x8C, 0x3B,
> +		0xBE, 0xA7, 0x5A, 0x9E, 0xD7, 0xBD, 0x9E, 0x89,
> +		0xEE, 0x7E, 0x10, 0x31, 0x9A, 0x1D, 0x82, 0x49,
> +		0xA3, 0x4E, 0xD8, 0x47, 0xD7, 0x19, 0xF4, 0x2D,
> +		0x8E, 0x53
> +	}
> +};
> +
> +/* HSM2.0 BROM NAND header for SPI NAND with 4KB page + 256B spare */
> +static const union hsm20_nand_boot_header hsm20_nand_hdr_4k_256_data = {
> +	.data = {
> +		0x4E, 0x41, 0x4E, 0x44, 0x43, 0x46, 0x47, 0x21,
> +		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
> +		0x00, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
> +		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
> +		0x40, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
> +		0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
> +		0x01, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00,
> +		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x79, 0x01, 0x1F, 0x86, 0x62, 0x6A, 0x43, 0xAE,
> +		0xE6, 0xF8, 0xDD, 0x5B, 0x29, 0xB7, 0xA2, 0x7F,
> +		0x29, 0x72, 0x54, 0x37, 0xBE, 0x50, 0xD4, 0x24,
> +		0xAB, 0x60, 0xF4, 0x44, 0x97, 0x3B, 0x65, 0x21,
> +		0x73, 0x24, 0x1F, 0x93, 0x0E, 0x9E, 0x96, 0x88,
> +		0x78, 0x6C
> +	}
> +};
> +
> +/* SPIM-NAND header for SPI NAND with 2KB page + 64B spare */
> +static const union spim_nand_boot_header spim_nand_hdr_2k_64_data = {
> +	.data = {
> +		0x53, 0x50, 0x49, 0x4e, 0x41, 0x4e, 0x44, 0x21,
> +		0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
> +		0x00, 0x08, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
> +		0x40, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x20, 0x30,
> +		0x01, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
> +	}
> +};
> +
> +/* SPIM-NAND header for SPI NAND with 2KB page + 128B spare */
> +static const union spim_nand_boot_header spim_nand_hdr_2k_128_data = {
> +	.data = {
> +		0x53, 0x50, 0x49, 0x4e, 0x41, 0x4e, 0x44, 0x21,
> +		0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
> +		0x00, 0x08, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
> +		0x40, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x20, 0x30,
> +		0x01, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
> +	}
> +};
> +
> +/* SPIM-NAND header for SPI NAND with 4KB page + 256B spare */
> +static const union spim_nand_boot_header spim_nand_hdr_4k_256_data = {
> +	.data = {
> +		0x53, 0x50, 0x49, 0x4e, 0x41, 0x4e, 0x44, 0x21,
> +		0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
> +		0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
> +		0x40, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x20, 0x30,
> +		0x01, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
> +	}
> +};
> +
> +struct nand_header_type {
>  	const char *name;
> -	const union nand_boot_header *data;
> +	enum nand_boot_header_type type;
> +	union {
> +		const union nand_boot_header *ap;
> +		const union hsm_nand_boot_header *hsm;
> +		const union hsm20_nand_boot_header *hsm20;
> +		const union spim_nand_boot_header *spim;
> +	};
>  } nand_headers[] = {
>  	{
>  		.name = "2k+64",
> -		.data = &snand_hdr_2k_64_data
> +		.type = NAND_BOOT_AP_HEADER,
> +		.ap = &snand_hdr_2k_64_data,
>  	}, {
>  		.name = "2k+120",
> -		.data = &snand_hdr_2k_128_data
> +		.type = NAND_BOOT_AP_HEADER,
> +		.ap = &snand_hdr_2k_128_data,
>  	}, {
>  		.name = "2k+128",
> -		.data = &snand_hdr_2k_128_data
> +		.type = NAND_BOOT_AP_HEADER,
> +		.ap = &snand_hdr_2k_128_data,
>  	}, {
>  		.name = "4k+256",
> -		.data = &snand_hdr_4k_256_data
> +		.type = NAND_BOOT_AP_HEADER,
> +		.ap = &snand_hdr_4k_256_data,
>  	}, {
>  		.name = "1g:2k+64",
> -		.data = &nand_hdr_1gb_2k_64_data
> +		.type = NAND_BOOT_AP_HEADER,
> +		.ap = &nand_hdr_1gb_2k_64_data,
>  	}, {
>  		.name = "2g:2k+64",
> -		.data = &nand_hdr_2gb_2k_64_data
> +		.type = NAND_BOOT_AP_HEADER,
> +		.ap = &nand_hdr_2gb_2k_64_data,
>  	}, {
>  		.name = "4g:2k+64",
> -		.data = &nand_hdr_4gb_2k_64_data
> +		.type = NAND_BOOT_AP_HEADER,
> +		.ap = &nand_hdr_4gb_2k_64_data,
>  	}, {
>  		.name = "2g:2k+128",
> -		.data = &nand_hdr_2gb_2k_128_data
> +		.type = NAND_BOOT_AP_HEADER,
> +		.ap = &nand_hdr_2gb_2k_128_data,
>  	}, {
>  		.name = "4g:2k+128",
> -		.data = &nand_hdr_4gb_2k_128_data
> +		.type = NAND_BOOT_AP_HEADER,
> +		.ap = &nand_hdr_4gb_2k_128_data,
> +	}, {
> +		.name = "hsm:2k+64",
> +		.type = NAND_BOOT_HSM_HEADER,
> +		.hsm = &hsm_nand_hdr_2k_64_data,
> +	}, {
> +		.name = "hsm:2k+128",
> +		.type = NAND_BOOT_HSM_HEADER,
> +		.hsm = &hsm_nand_hdr_2k_128_data,
> +	}, {
> +		.name = "hsm:4k+256",
> +		.type = NAND_BOOT_HSM_HEADER,
> +		.hsm = &hsm_nand_hdr_4k_256_data,
> +	},  {
> +		.name = "hsm20:2k+64",
> +		.type = NAND_BOOT_HSM20_HEADER,
> +		.hsm20 = &hsm20_nand_hdr_2k_64_data,
> +	}, {
> +		.name = "hsm20:2k+128",
> +		.type = NAND_BOOT_HSM20_HEADER,
> +		.hsm20 = &hsm20_nand_hdr_2k_128_data,
> +	}, {
> +		.name = "hsm20:4k+256",
> +		.type = NAND_BOOT_HSM20_HEADER,
> +		.hsm20 = &hsm20_nand_hdr_4k_256_data,
> +	}, {
> +		.name = "spim:2k+64",
> +		.type = NAND_BOOT_SPIM_HEADER,
> +		.spim = &spim_nand_hdr_2k_64_data,
> +	}, {
> +		.name = "spim:2k+128",
> +		.type = NAND_BOOT_SPIM_HEADER,
> +		.spim = &spim_nand_hdr_2k_128_data,
> +	}, {
> +		.name = "spim:4k+256",
> +		.type = NAND_BOOT_SPIM_HEADER,
> +		.spim = &spim_nand_hdr_4k_256_data,
>  	}
>  };
>  
> -const union nand_boot_header *mtk_nand_header_find(const char *name)
> +const struct nand_header_type *mtk_nand_header_find(const char *name)
>  {
>  	uint32_t i;
>  
>  	for (i = 0; i < ARRAY_SIZE(nand_headers); i++) {
>  		if (!strcmp(nand_headers[i].name, name))
> -			return nand_headers[i].data;
> +			return &nand_headers[i];
>  	}
>  
>  	return NULL;
>  }
>  
> -uint32_t mtk_nand_header_size(const union nand_boot_header *hdr_nand)
> +uint32_t mtk_nand_header_size(const struct nand_header_type *hdr_nand)
>  {
> -	return 2 * le16_to_cpu(hdr_nand->pagesize);
> +	switch (hdr_nand->type) {
> +	case NAND_BOOT_HSM_HEADER:
> +		return le32_to_cpu(hdr_nand->hsm->page_size);
> +
> +	case NAND_BOOT_HSM20_HEADER:
> +		return le32_to_cpu(hdr_nand->hsm20->page_size);
> +
> +	case NAND_BOOT_SPIM_HEADER:
> +		return le32_to_cpu(hdr_nand->spim->page_size);
> +
> +	default:
> +		return 2 * le16_to_cpu(hdr_nand->ap->pagesize);
> +	}
>  }
>  
>  static int mtk_nand_header_ap_info(const void *ptr,
> @@ -251,14 +542,45 @@ static int mtk_nand_header_ap_info(const void *ptr,
>  	info->page_size = le16_to_cpu(nh->pagesize);
>  	info->spare_size = le16_to_cpu(nh->oobsize);
>  	info->gfh_offset = 2 * info->page_size;
> +	info->snfi = true;
>  
>  	return 0;
>  }
>  
> +static int mtk_nand_header_hsm_info(const void *ptr,
> +				    struct nand_header_info *info)
> +{
> +	union hsm_nand_boot_header *nh = (union hsm_nand_boot_header *)ptr;
> +
> +	info->page_size = le16_to_cpu(nh->page_size);
> +	info->spare_size = le16_to_cpu(nh->spare_size);
> +	info->gfh_offset = info->page_size;
> +	info->snfi = true;
> +
> +	return 1;
> +}
> +
> +static int mtk_nand_header_spim_info(const void *ptr,
> +				     struct nand_header_info *info)
> +{
> +	union spim_nand_boot_header *nh = (union spim_nand_boot_header *)ptr;
> +
> +	info->page_size = le16_to_cpu(nh->page_size);
> +	info->spare_size = le16_to_cpu(nh->spare_size);
> +	info->gfh_offset = info->page_size;
> +	info->snfi = false;
> +
> +	return 1;
> +}
> +
>  int mtk_nand_header_info(const void *ptr, struct nand_header_info *info)
>  {
>  	if (!strcmp((char *)ptr, NAND_BOOT_NAME))
>  		return mtk_nand_header_ap_info(ptr, info);
> +	else if (!strncmp((char *)ptr, HSM_NAND_BOOT_NAME, 8))
> +		return mtk_nand_header_hsm_info(ptr, info);
> +	else if (!strncmp((char *)ptr, SPIM_NAND_BOOT_NAME, 8))
> +		return mtk_nand_header_spim_info(ptr, info);
>  
>  	return -1;
>  }
> @@ -273,14 +595,74 @@ bool is_mtk_nand_header(const void *ptr)
>  	return false;
>  }
>  
> -uint32_t mtk_nand_header_put(const union nand_boot_header *hdr_nand, void *ptr)
> +static uint16_t crc16(const uint8_t *p, uint32_t len)
> +{
> +	uint16_t crc = 0x4f4e;
> +	uint32_t i;
> +
> +	while (len--) {
> +		crc ^= *p++ << 8;
> +		for (i = 0; i < 8; i++)
> +			crc = (crc << 1) ^ ((crc & 0x8000) ? 0x8005 : 0);
> +	}
> +
> +	return crc;
> +}
> +
> +static uint32_t mtk_nand_header_put_ap(const struct nand_header_type *hdr_nand,
> +				       void *ptr)
>  {
> -	union nand_boot_header *nh = (union nand_boot_header *)ptr;
>  	int i;
>  
>  	/* NAND device header, repeat 4 times */
> -	for (i = 0; i < 4; i++)
> -		memcpy(nh + i, hdr_nand, sizeof(union nand_boot_header));
> +	for (i = 0; i < 4; i++) {
> +		memcpy(ptr, hdr_nand->ap, sizeof(*hdr_nand->ap));
> +		ptr += sizeof(*hdr_nand->ap);
> +	}
>  
> -	return le16_to_cpu(hdr_nand->pagesize);
> +	return le16_to_cpu(hdr_nand->ap->pagesize);
> +}
> +
> +static uint32_t mtk_nand_header_put_hsm(const struct nand_header_type *hdr_nand,
> +					void *ptr)
> +{
> +	memcpy(ptr, hdr_nand->hsm, sizeof(*hdr_nand->hsm));
> +	return 0;
> +}
> +
> +static uint32_t mtk_nand_header_put_hsm20(const struct nand_header_type *hdr_nand,
> +					  void *ptr)
> +{
> +	memcpy(ptr, hdr_nand->hsm20, sizeof(*hdr_nand->hsm20));
> +	return 0;
> +}
> +
> +static uint32_t mtk_nand_header_put_spim(const struct nand_header_type *hdr_nand,
> +					 void *ptr)
> +{
> +	uint16_t crc;
> +
> +	memcpy(ptr, hdr_nand->spim, sizeof(*hdr_nand->spim));
> +
> +	crc = crc16(ptr, 0x4e);
> +	memcpy(ptr + 0x4e, &crc, sizeof(uint16_t));
> +
> +	return 0;
> +}
> +
> +uint32_t mtk_nand_header_put(const struct nand_header_type *hdr_nand, void *ptr)
> +{
> +	switch (hdr_nand->type) {
> +	case NAND_BOOT_HSM_HEADER:
> +		return mtk_nand_header_put_hsm(hdr_nand, ptr);
> +
> +	case NAND_BOOT_HSM20_HEADER:
> +		return mtk_nand_header_put_hsm20(hdr_nand, ptr);
> +
> +	case NAND_BOOT_SPIM_HEADER:
> +		return mtk_nand_header_put_spim(hdr_nand, ptr);
> +
> +	default:
> +		return mtk_nand_header_put_ap(hdr_nand, ptr);
> +	}
>  }
> diff --git a/tools/mtk_nand_headers.h b/tools/mtk_nand_headers.h
> index 20506cab38..9b1c4bab11 100644
> --- a/tools/mtk_nand_headers.h
> +++ b/tools/mtk_nand_headers.h
> @@ -16,6 +16,7 @@ struct nand_header_info {
>  	uint32_t page_size;
>  	uint32_t spare_size;
>  	uint32_t gfh_offset;
> +	bool snfi;
>  };
>  
>  /* AP BROM Header for NAND */
> @@ -39,15 +40,117 @@ union nand_boot_header {
>  	uint8_t data[0x80];
>  };
>  
> +/* HSM BROM Header for NAND */
> +union hsm_nand_boot_header {
> +	struct {
> +		char id[8];
> +		uint32_t version;		/* Header version */
> +		uint32_t config;		/* Header config */
> +		uint32_t sector_size;		/* ECC step size */
> +		uint32_t fdm_size;		/* User OOB size of a step */
> +		uint32_t fdm_ecc_size;		/* ECC parity size of a step */
> +		uint32_t lbs;
> +		uint32_t page_size;		/* NAND page size */
> +		uint32_t spare_size;		/* NAND page spare size */
> +		uint32_t page_per_block;	/* Pages of one block */
> +		uint32_t blocks;		/* Total blocks of NAND chip */
> +		uint32_t plane_sel_position;	/* Plane bit position */
> +		uint32_t pll;			/* Value of pll reg */
> +		uint32_t acccon;		/* Value of access timing reg */
> +		uint32_t strobe_sel;		/* Value of DQS selection reg*/
> +		uint32_t acccon1;		/* Value of access timing reg */
> +		uint32_t dqs_mux;		/* Value of DQS mux reg */
> +		uint32_t dqs_ctrl;		/* Value of DQS control reg */
> +		uint32_t delay_ctrl;		/* Value of delay ctrl reg */
> +		uint32_t latch_lat;		/* Value of latch latency reg */
> +		uint32_t sample_delay;		/* Value of sample delay reg */
> +		uint32_t driving;		/* Value of driving reg */
> +		uint32_t bl_start;		/* Bootloader start addr */
> +		uint32_t bl_end;		/* Bootloader end addr */
> +		uint8_t ecc_parity[42];		/* ECC parity of this header */
> +	};
> +
> +	uint8_t data[0x8E];
> +};
> +
> +/* HSM2.0 BROM Header for NAND */
> +union hsm20_nand_boot_header {
> +	struct {
> +		char id[8];
> +		uint32_t version;		/* Header version */
> +		uint32_t config;		/* Header config */
> +		uint32_t sector_size;		/* ECC step size */
> +		uint32_t fdm_size;		/* User OOB size of a step */
> +		uint32_t fdm_ecc_size;		/* ECC parity size of a step */
> +		uint32_t lbs;
> +		uint32_t page_size;		/* NAND page size */
> +		uint32_t spare_size;		/* NAND page spare size */
> +		uint32_t page_per_block;	/* Pages of one block */
> +		uint32_t blocks;		/* Total blocks of NAND chip */
> +		uint32_t plane_sel_position;	/* Plane bit position */
> +		uint32_t pll;			/* Value of pll reg */
> +		uint32_t acccon;		/* Value of access timing reg */
> +		uint32_t strobe_sel;		/* Value of DQS selection reg*/
> +		uint32_t acccon1;		/* Value of access timing reg */
> +		uint32_t dqs_mux;		/* Value of DQS mux reg */
> +		uint32_t dqs_ctrl;		/* Value of DQS control reg */
> +		uint32_t delay_ctrl;		/* Value of delay ctrl reg */
> +		uint32_t latch_lat;		/* Value of latch latency reg */
> +		uint32_t sample_delay;		/* Value of sample delay reg */
> +		uint32_t driving;		/* Value of driving reg */
> +		uint32_t reserved;
> +		uint32_t bl0_start;		/* Bootloader start addr */
> +		uint32_t bl0_end;		/* Bootloader end addr */
> +		uint32_t bl0_type;		/* Bootloader type */
> +		uint8_t bl_reserve[84];
> +		uint8_t ecc_parity[42];		/* ECC parity of this header */
> +	};
> +
> +	uint8_t data[0xEA];
> +};
> +
> +/* SPIM BROM Header for SPI-NAND */
> +union spim_nand_boot_header {
> +	struct {
> +		char id[8];
> +		uint32_t version;		/* Header version */
> +		uint32_t config;		/* Header config */
> +		uint32_t page_size;		/* NAND page size */
> +		uint32_t spare_size;		/* NAND page spare size */
> +		uint16_t page_per_block;	/* Pages of one block */
> +		uint16_t plane_sel_position;	/* Plane bit position */
> +		uint16_t reserve_reg;
> +		uint16_t reserve_val;
> +		uint16_t ecc_error;		/* ECC error reg addr */
> +		uint16_t ecc_mask;		/* ECC error bit mask */
> +		uint32_t bl_start;		/* Bootloader start addr */
> +		uint32_t bl_end;		/* Bootloader end addr */
> +		uint8_t ecc_parity[32];		/* ECC parity of this header */
> +		uint32_t integrity_crc;		/* CRC of this header */
> +	};
> +
> +	uint8_t data[0x50];
> +};
> +
> +enum nand_boot_header_type {
> +	NAND_BOOT_AP_HEADER,
> +	NAND_BOOT_HSM_HEADER,
> +	NAND_BOOT_HSM20_HEADER,
> +	NAND_BOOT_SPIM_HEADER
> +};
> +
>  #define NAND_BOOT_NAME		"BOOTLOADER!"
>  #define NAND_BOOT_VERSION	"V006"
>  #define NAND_BOOT_ID		"NFIINFO"
>  
> +#define HSM_NAND_BOOT_NAME	"NANDCFG!"
> +#define SPIM_NAND_BOOT_NAME	"SPINAND!"
> +
>  /* Find nand header data by name */
> -const union nand_boot_header *mtk_nand_header_find(const char *name);
> +const struct nand_header_type *mtk_nand_header_find(const char *name);
>  
>  /* Device header size using this nand header */
> -uint32_t mtk_nand_header_size(const union nand_boot_header *hdr_nand);
> +uint32_t mtk_nand_header_size(const struct nand_header_type *hdr_nand);
>  
>  /* Get nand info from nand header (page size, spare size, ...) */
>  int mtk_nand_header_info(const void *ptr, struct nand_header_info *info);
> @@ -56,6 +159,7 @@ int mtk_nand_header_info(const void *ptr, struct nand_header_info *info);
>  bool is_mtk_nand_header(const void *ptr);
>  
>  /* Generate Device header using give nand header */
> -uint32_t mtk_nand_header_put(const union nand_boot_header *hdr_nand, void *ptr);
> +uint32_t mtk_nand_header_put(const struct nand_header_type *hdr_nand,
> +			     void *ptr);
>  
>  #endif /* _MTK_NAND_HEADERS_H */
> -- 
> 2.17.1
> 

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

* Re: [PATCH v2 28/32] cpu: add basic cpu driver for MediaTek ARM chips
  2022-08-31 13:46   ` Simon Glass
@ 2022-09-01  3:00     ` Weijie Gao
  0 siblings, 0 replies; 60+ messages in thread
From: Weijie Gao @ 2022-09-01  3:00 UTC (permalink / raw)
  To: Simon Glass
  Cc: U-Boot Mailing List, GSS_MTK_Uboot_upstream, Michal Simek, Ovidiu Panait

On Wed, 2022-08-31 at 07:46 -0600, Simon Glass wrote:
> Hi Weijie,
> 
> On Wed, 31 Aug 2022 at 05:08, Weijie Gao <weijie.gao@mediatek.com>
> wrote:
> > 
> > Add basic CPU driver used to retrieve CPU model information.
> > 
> > Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
> > ---
> >   v2 changes: new
> > ---
> >  drivers/cpu/Makefile  |   1 +
> >  drivers/cpu/mtk_cpu.c | 106
> > ++++++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 107 insertions(+)
> >  create mode 100644 drivers/cpu/mtk_cpu.c
> > 
> > diff --git a/drivers/cpu/Makefile b/drivers/cpu/Makefile
> > index 20884b1795..3b38ba9c58 100644
> > --- a/drivers/cpu/Makefile
> > +++ b/drivers/cpu/Makefile
> > @@ -9,6 +9,7 @@ obj-$(CONFIG_CPU) += cpu-uclass.o
> >  obj-$(CONFIG_ARCH_BMIPS) += bmips_cpu.o
> >  obj-$(CONFIG_ARCH_IMX8) += imx8_cpu.o
> >  obj-$(CONFIG_ARCH_AT91) += at91_cpu.o
> > +obj-$(CONFIG_ARCH_MEDIATEK) += mtk_cpu.o
> >  obj-$(CONFIG_CPU_MPC83XX) += mpc83xx_cpu.o
> >  obj-$(CONFIG_CPU_RISCV) += riscv_cpu.o
> >  obj-$(CONFIG_CPU_MICROBLAZE) += microblaze_cpu.o
> > diff --git a/drivers/cpu/mtk_cpu.c b/drivers/cpu/mtk_cpu.c
> > new file mode 100644
> > index 0000000000..d00b4c669e
> > --- /dev/null
> > +++ b/drivers/cpu/mtk_cpu.c
> > @@ -0,0 +1,106 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (C) 2022 MediaTek Inc. All rights reserved.
> > + *
> > + * Author: Weijie Gao <weijie.gao@mediatek.com>
> > + */
> > +
> > +#include <linux/types.h>
> > +#include <cpu.h>
> > +#include <dm.h>
> > +#include <fdt_support.h>
> > +#include <mapmem.h>
> > +#include <asm/global_data.h>
> > +#include <linux/io.h>
> > +
> > +DECLARE_GLOBAL_DATA_PTR;
> 
> dont't need this?
> 
> > +
> > +struct mtk_cpu_plat {
> > +       void __iomem *hwver_base;
> > +};
> > +
> > +static int mtk_cpu_get_desc(const struct udevice *dev, char *buf,
> > int size)
> > +{
> > +       struct mtk_cpu_plat *plat = dev_get_plat(dev);
> > +
> > +       snprintf(buf, size, "MediaTek MT%04X", readl(plat-
> > >hwver_base));
> > +
> > +       return 0;
> > +}
> > +
> > +static int mtk_cpu_get_count(const struct udevice *dev)
> > +{
> > +       return 1;
> > +}
> > +
> > +static int mtk_cpu_get_vendor(const struct udevice *dev, char
> > *buf, int size)
> > +{
> > +       snprintf(buf, size, "MediaTek");
> > +
> > +       return 0;
> > +}
> > +
> > +static int mtk_cpu_probe(struct udevice *dev)
> > +{
> > +       struct mtk_cpu_plat *plat = dev_get_plat(dev);
> > +       const void *fdt = gd->fdt_blob, *reg;
> > +       int offset, parent, len, na, ns;
> > +       u64 addr;
> > +
> > +       if (!fdt)
> > +               return -ENODEV;
> > +
> > +       offset = fdt_path_offset(fdt, "/hwver");
> 
> This is very strange, but you should have a driver for that node,
> e.g.
> a SYSCON driver. Then from this driver you can obtain the address
> with
> syscon_get_first_range() or similar.
> 
> > +       if (offset < 0)
> > +               return -ENODEV;
> > +
> > +       parent = fdt_parent_offset(fdt, offset);
> > +       if (parent < 0)
> > +               return -ENODEV;
> > +
> > +       na = fdt_address_cells(fdt, parent);
> > +       if (na < 1)
> > +               return -ENODEV;
> > +
> > +       ns = fdt_size_cells(gd->fdt_blob, parent);
> > +       if (ns < 0)
> > +               return -ENODEV;
> > +
> > +       reg = fdt_getprop(gd->fdt_blob, offset, "reg", &len);
> > +       if (!reg)
> > +               return -ENODEV;
> > +
> > +       if (ns)
> > +               addr = fdt_translate_address(fdt, offset, reg);
> > +       else
> > +               addr = fdt_read_number(reg, na);
> > +
> 
> All of the above should go away. We should use dev_read() / ofnode...
> for device tree access.

OK. This is indeed tricky. I just didn't want to add reference to the
hwver node for every cpu node.
I'll change this using the regular way.

> 
> > +       plat->hwver_base = map_sysmem(addr, 0);
> > +       if (!plat->hwver_base)
> > +               return -EINVAL;
> > +
> > +       return 0;
> > +}
> > +
> > +static const struct cpu_ops mtk_cpu_ops = {
> > +       .get_desc       = mtk_cpu_get_desc,
> > +       .get_count      = mtk_cpu_get_count,
> > +       .get_vendor     = mtk_cpu_get_vendor,
> > +};
> > +
> > +static const struct udevice_id mtk_cpu_ids[] = {
> > +       { .compatible = "arm,cortex-a7" },
> > +       { .compatible = "arm,cortex-a53" },
> > +       { .compatible = "arm,cortex-a73" },
> > +       { /* sentinel */ }
> > +};
> > +
> > +U_BOOT_DRIVER(cpu_mtk) = {
> > +       .name           = "mtk-cpu",
> > +       .id             = UCLASS_CPU,
> > +       .of_match       = mtk_cpu_ids,
> > +       .ops            = &mtk_cpu_ops,
> > +       .probe          = mtk_cpu_probe,
> > +       .plat_auto      = sizeof(struct mtk_cpu_plat),
> > +       .flags          = DM_FLAG_PRE_RELOC,
> > +};
> > --
> > 2.17.1
> > 
> 
> Regards,
> Simon

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

end of thread, other threads:[~2022-09-01  3:00 UTC | newest]

Thread overview: 60+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-31 11:00 [PATCH v2 00/32] Add support for MediaTek MT7981/MT7986 SoCs - v2 Weijie Gao
2022-08-31 11:00 ` [PATCH v2 01/32] arm: mediatek: add support for MediaTek MT7986 SoC Weijie Gao
2022-08-31 13:46   ` Simon Glass
2022-09-01  0:09   ` Daniel Golle
2022-08-31 11:00 ` [PATCH v2 02/32] arm: mediatek: add support for MediaTek MT7981 SoC Weijie Gao
2022-08-31 13:46   ` Simon Glass
2022-08-31 11:00 ` [PATCH v2 03/32] board: mediatek: add MT7986 reference boards Weijie Gao
2022-08-31 11:00 ` [PATCH v2 04/32] board: mediatek: add MT7981 " Weijie Gao
2022-08-31 13:46   ` Simon Glass
2022-08-31 11:04 ` [PATCH v2 05/32] mmc: mediatek: add support for MediaTek MT7891/MT7986 SoCs Weijie Gao
2022-09-01  0:10   ` Daniel Golle
2022-08-31 11:04 ` [PATCH v2 06/32] net: mediatek: use a struct to cover variations of all SoCs Weijie Gao
2022-09-01  0:20   ` Daniel Golle
2022-08-31 11:04 ` [PATCH v2 07/32] net: mediatek: stop using bitfileds for DMA descriptors Weijie Gao
2022-09-01  0:20   ` Daniel Golle
2022-08-31 11:04 ` [PATCH v2 08/32] net: mediatek: add support for PDMA v2 Weijie Gao
2022-09-01  0:22   ` Daniel Golle
2022-08-31 11:04 ` [PATCH v2 09/32] net: mediatek: add support for MediaTek MT7981/MT7986 Weijie Gao
2022-09-01  0:22   ` Daniel Golle
2022-08-31 11:04 ` [PATCH v2 10/32] serial: mtk: add support for using dynamic baud clock souce Weijie Gao
2022-09-01  0:22   ` Daniel Golle
2022-08-31 11:04 ` [PATCH v2 11/32] arm: dts: mt7622: force high-speed mode for uart Weijie Gao
2022-09-01  0:23   ` Daniel Golle
2022-08-31 11:04 ` [PATCH v2 12/32] pwm: mtk: add support for MediaTek MT7986 SoC Weijie Gao
2022-08-31 11:04 ` [PATCH v2 13/32] pwm: mtk: add support for MediaTek MT7981 SoC Weijie Gao
2022-08-31 11:04 ` [PATCH v2 14/32] timer: mtk: add support for MediaTek MT7981/MT7986 SoCs Weijie Gao
2022-09-01  0:24   ` Daniel Golle
2022-08-31 11:04 ` [PATCH v2 15/32] watchdog: mediatek: add support for MediaTek MT7986 SoC Weijie Gao
2022-09-01  0:25   ` Daniel Golle
2022-08-31 11:04 ` [PATCH v2 16/32] spi: add support for MediaTek spi-mem controller Weijie Gao
2022-09-01  0:25   ` Daniel Golle
2022-08-31 11:04 ` [PATCH v2 17/32] i2c: add support for MediaTek I2C interface Weijie Gao
2022-08-31 11:04 ` [PATCH v2 18/32] arm: dts: mt7622: add i2c support Weijie Gao
2022-08-31 11:04 ` [PATCH v2 19/32] dt-bindings: pinctrl: mediatek: add a header for common pinconf parameters Weijie Gao
2022-08-31 11:04 ` [PATCH v2 20/32] pinctrl: mediatek: add pinctrl driver for MT7981 SoC Weijie Gao
2022-08-31 11:04 ` [PATCH v2 21/32] pinctrl: mediatek: add pinctrl driver for MT7986 SoC Weijie Gao
2022-09-01  0:26   ` Daniel Golle
2022-08-31 11:04 ` [PATCH v2 22/32] clk: mediatek: add CLK_BYPASS_XTAL flag to allow bypassing searching clock parent of xtal clock Weijie Gao
2022-09-01  0:26   ` Daniel Golle
2022-08-31 11:05 ` [PATCH v2 23/32] clk: mediatek: add support to configure clock driver parent Weijie Gao
2022-09-01  0:27   ` Daniel Golle
2022-08-31 11:05 ` [PATCH v2 24/32] clk: mediatek: add infrasys clock mux support Weijie Gao
2022-09-01  0:27   ` Daniel Golle
2022-08-31 11:05 ` [PATCH v2 25/32] clk: mediatek: add CLK_XTAL support for clock driver Weijie Gao
2022-08-31 13:46   ` Simon Glass
2022-09-01  0:27   ` Daniel Golle
2022-08-31 11:05 ` [PATCH v2 26/32] clk: mediatek: add clock driver support for MediaTek MT7986 SoC Weijie Gao
2022-09-01  0:28   ` Daniel Golle
2022-08-31 11:05 ` [PATCH v2 27/32] clk: mediatek: add clock driver support for MediaTek MT7981 SoC Weijie Gao
2022-08-31 11:05 ` [PATCH v2 28/32] cpu: add basic cpu driver for MediaTek ARM chips Weijie Gao
2022-08-31 13:46   ` Simon Glass
2022-09-01  3:00     ` Weijie Gao
2022-09-01  0:28   ` Daniel Golle
2022-08-31 11:05 ` [PATCH v2 29/32] tools: mtk_image: split gfh header verification into a new function Weijie Gao
2022-09-01  0:31   ` Daniel Golle
2022-08-31 11:05 ` [PATCH v2 30/32] tools: mtk_image: split the code of generating NAND header into a new file Weijie Gao
2022-09-01  0:32   ` Daniel Golle
2022-08-31 11:05 ` [PATCH v2 31/32] tools: mtk_image: add support for nand headers used by newer chips Weijie Gao
2022-09-01  0:32   ` Daniel Golle
2022-08-31 11:05 ` [PATCH v2 32/32] MAINTAINERS: update maintainer for MediaTek ARM platform Weijie Gao

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.