All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v2 00/18] Add U-Boot support for MediaTek SoCs - MT7623n & MT7629
@ 2018-10-12  7:00 Ryder Lee
  2018-10-12  7:00 ` [U-Boot] [PATCH v2 01/18] tools: MediaTek: add MTK boot header generation to mkimage Ryder Lee
                   ` (17 more replies)
  0 siblings, 18 replies; 57+ messages in thread
From: Ryder Lee @ 2018-10-12  7:00 UTC (permalink / raw)
  To: u-boot

Hello,

This is the new round to add U-Boot support for MediaTek SoCs - MT7623n & MT7629,
and the most of the drivers are based on mainline Linux, such as clock, timer, mmc,
pinctrl, watchdog, power domain and device tree.

The following are the major differences between mainline Linux and U-Boot:
- Modify the drivers to adapt the U-Boot DM framework.
- Remove unneeded DT nodes as they don't have proper drivers in U-Boot yet.
- Just add the basic functions (step-by-step) so that we can monitor the size.
- Reuse UART driver ns16550.c but add a highspeed register for MediaTek chips.
- Add a whole new MT7629 SNOR driver which is based on SPI framework.

Our current progress:

The MT7623n (BananaPi R2) which has already been supported in mainline Linux.
- Boot from eMMC or SD card.
- Boot flow: ROM -> MediaTek's preloder -> U-Boot ...
- An open development board called BananaPi R2 [1]. 

The MT7629 is NOT supported yet in mainline Linux, but I will add it soon.
- Boot from SNOR currently.
- Boot flow: ROM -> (boot header parsing sequence) -> SPL -> U-Boot ...

[1] http://wiki.banana-pi.org/Banana_Pi_BPI-R2

Current implementation was validated via the FIT image.

Thanks,
Ryder

Changes since v2:
- Squash defconfig parts into other patches.
- Drop unneeded definitions in include/configs/*.
- Add a MT7629 qspi driver in the series.

Changes since v1:
- Fix new blank line at EOF and indentation.
- Revise commit message.
- Add missing sgmiisys device nodes.
- Add Tested-by tags from Matthias.
- Drop MT7629 qspi driver in the series, and we will implement another one
  based on the spi-mem framework.

Guochun Mao (1):
  spi: mtk_qspi: add qspi driver for MT7629 SoC

Ryder Lee (15):
  tools: MediaTek: add MTK boot header generation to mkimage
  arm: dts: MediaTek: add device tree for MT7629
  arm: dts: MediaTek: add device tree for MT7623
  arm: MediaTek: add basic support for MT7629 boards
  clk: MediaTek: add clock driver for MT7629 SoC.
  clk: MediaTek: add clock driver for MT7623 SoC.
  timer: MediaTek: add timer driver for MediaTek SoCs
  watchdog: MediaTek: add watchdog driver for MediaTek SoCs
  pinctrl: MediaTek: add pinctrl driver for MT7629 SoC
  pinctrl: MediaTek: add pinctrl driver for MT7623 SoC
  power domain: MediaTek: add power domain driver for MT7629 SoC
  power domain: MediaTek: add power domain driver for MT7623 SoC
  serial: 16550: allow the driver to support MediaTek serial
  ram: MediaTek: add DDR3 driver for MT7629 SoC
  MAINTAINERS: add an entry for MediaTek

Weijie Gao (2):
  arm: MediaTek: add basic support for MT7623 boards
  mmc: mtk-sd: add SD/MMC host controller driver for MT7623 SoC

 MAINTAINERS                                   |   18 +
 Makefile                                      |   22 +
 arch/arm/Kconfig                              |   14 +
 arch/arm/Makefile                             |    1 +
 arch/arm/dts/Makefile                         |    4 +
 arch/arm/dts/mt7623.dtsi                      |  255 +++++
 arch/arm/dts/mt7623n-bananapi-bpi-r2.dts      |  207 ++++
 arch/arm/dts/mt7629-rfb.dts                   |   71 ++
 arch/arm/dts/mt7629.dtsi                      |  244 +++++
 arch/arm/include/asm/arch-mediatek/gpio.h     |    9 +
 arch/arm/include/asm/arch-mediatek/misc.h     |   17 +
 arch/arm/mach-mediatek/Kconfig                |   32 +
 arch/arm/mach-mediatek/Makefile               |    7 +
 arch/arm/mach-mediatek/cpu.c                  |   34 +
 arch/arm/mach-mediatek/init.h                 |   11 +
 arch/arm/mach-mediatek/mt7623/Makefile        |    4 +
 arch/arm/mach-mediatek/mt7623/init.c          |   54 +
 arch/arm/mach-mediatek/mt7623/lowlevel_init.S |   22 +
 arch/arm/mach-mediatek/mt7623/preloader.h     |   99 ++
 arch/arm/mach-mediatek/mt7629/Makefile        |    4 +
 arch/arm/mach-mediatek/mt7629/init.c          |  131 +++
 arch/arm/mach-mediatek/mt7629/lowlevel_init.S |   50 +
 arch/arm/mach-mediatek/spl.c                  |   43 +
 board/mediatek/mt7623/Kconfig                 |   13 +
 board/mediatek/mt7623/MAINTAINERS             |    7 +
 board/mediatek/mt7623/Makefile                |    3 +
 board/mediatek/mt7623/mt7623_rfb.c            |   16 +
 board/mediatek/mt7629/Kconfig                 |   17 +
 board/mediatek/mt7629/MAINTAINERS             |    7 +
 board/mediatek/mt7629/Makefile                |    3 +
 board/mediatek/mt7629/mt7629_rfb.c            |   16 +
 common/image.c                                |    1 +
 configs/mt7623n_bpir2_defconfig               |   53 +
 configs/mt7629_rfb_defconfig                  |   73 ++
 drivers/clk/Makefile                          |    1 +
 drivers/clk/mediatek/Makefile                 |    7 +
 drivers/clk/mediatek/clk-mt7623.c             |  870 ++++++++++++++++
 drivers/clk/mediatek/clk-mt7629.c             |  709 +++++++++++++
 drivers/clk/mediatek/clk-mtk.c                |  492 +++++++++
 drivers/clk/mediatek/clk-mtk.h                |  153 +++
 drivers/mmc/Kconfig                           |    9 +
 drivers/mmc/Makefile                          |    1 +
 drivers/mmc/mtk-sd.c                          | 1331 +++++++++++++++++++++++++
 drivers/pinctrl/Kconfig                       |    1 +
 drivers/pinctrl/Makefile                      |    1 +
 drivers/pinctrl/mediatek/Kconfig              |   15 +
 drivers/pinctrl/mediatek/Makefile             |    7 +
 drivers/pinctrl/mediatek/pinctrl-mt7623.c     | 1284 ++++++++++++++++++++++++
 drivers/pinctrl/mediatek/pinctrl-mt7629.c     |  488 +++++++++
 drivers/pinctrl/mediatek/pinctrl-mtk-common.c |  552 ++++++++++
 drivers/pinctrl/mediatek/pinctrl-mtk-common.h |  183 ++++
 drivers/power/domain/Kconfig                  |    7 +
 drivers/power/domain/Makefile                 |    1 +
 drivers/power/domain/mtk-power-domain.c       |  406 ++++++++
 drivers/ram/Makefile                          |    1 +
 drivers/ram/mediatek/Makefile                 |    7 +
 drivers/ram/mediatek/ddr3-mt7629.c            |  766 ++++++++++++++
 drivers/serial/ns16550.c                      |   10 +
 drivers/spi/Kconfig                           |    7 +
 drivers/spi/Makefile                          |    1 +
 drivers/spi/mtk_qspi.c                        |  359 +++++++
 drivers/timer/Kconfig                         |    7 +
 drivers/timer/Makefile                        |    1 +
 drivers/timer/mtk_timer.c                     |   85 ++
 drivers/watchdog/Kconfig                      |    8 +
 drivers/watchdog/Makefile                     |    1 +
 drivers/watchdog/mtk_wdt.c                    |  135 +++
 include/configs/mt7623.h                      |   61 ++
 include/configs/mt7629.h                      |   62 ++
 include/dt-bindings/clock/mt7623-clk.h        |  413 ++++++++
 include/dt-bindings/clock/mt7629-clk.h        |  206 ++++
 include/dt-bindings/power/mt7623-power.h      |   19 +
 include/dt-bindings/power/mt7629-power.h      |   13 +
 include/image.h                               |    1 +
 scripts/Makefile.spl                          |   11 +
 tools/Makefile                                |    1 +
 tools/mtkimage.c                              |  749 ++++++++++++++
 tools/mtkimage.h                              |  199 ++++
 78 files changed, 11203 insertions(+)
 create mode 100644 arch/arm/dts/mt7623.dtsi
 create mode 100644 arch/arm/dts/mt7623n-bananapi-bpi-r2.dts
 create mode 100644 arch/arm/dts/mt7629-rfb.dts
 create mode 100644 arch/arm/dts/mt7629.dtsi
 create mode 100644 arch/arm/include/asm/arch-mediatek/gpio.h
 create mode 100644 arch/arm/include/asm/arch-mediatek/misc.h
 create mode 100644 arch/arm/mach-mediatek/Kconfig
 create mode 100644 arch/arm/mach-mediatek/Makefile
 create mode 100644 arch/arm/mach-mediatek/cpu.c
 create mode 100644 arch/arm/mach-mediatek/init.h
 create mode 100644 arch/arm/mach-mediatek/mt7623/Makefile
 create mode 100644 arch/arm/mach-mediatek/mt7623/init.c
 create mode 100644 arch/arm/mach-mediatek/mt7623/lowlevel_init.S
 create mode 100644 arch/arm/mach-mediatek/mt7623/preloader.h
 create mode 100644 arch/arm/mach-mediatek/mt7629/Makefile
 create mode 100644 arch/arm/mach-mediatek/mt7629/init.c
 create mode 100644 arch/arm/mach-mediatek/mt7629/lowlevel_init.S
 create mode 100644 arch/arm/mach-mediatek/spl.c
 create mode 100644 board/mediatek/mt7623/Kconfig
 create mode 100644 board/mediatek/mt7623/MAINTAINERS
 create mode 100644 board/mediatek/mt7623/Makefile
 create mode 100644 board/mediatek/mt7623/mt7623_rfb.c
 create mode 100644 board/mediatek/mt7629/Kconfig
 create mode 100644 board/mediatek/mt7629/MAINTAINERS
 create mode 100644 board/mediatek/mt7629/Makefile
 create mode 100644 board/mediatek/mt7629/mt7629_rfb.c
 create mode 100644 configs/mt7623n_bpir2_defconfig
 create mode 100644 configs/mt7629_rfb_defconfig
 create mode 100644 drivers/clk/mediatek/Makefile
 create mode 100644 drivers/clk/mediatek/clk-mt7623.c
 create mode 100644 drivers/clk/mediatek/clk-mt7629.c
 create mode 100644 drivers/clk/mediatek/clk-mtk.c
 create mode 100644 drivers/clk/mediatek/clk-mtk.h
 create mode 100644 drivers/mmc/mtk-sd.c
 create mode 100644 drivers/pinctrl/mediatek/Kconfig
 create mode 100644 drivers/pinctrl/mediatek/Makefile
 create mode 100644 drivers/pinctrl/mediatek/pinctrl-mt7623.c
 create mode 100644 drivers/pinctrl/mediatek/pinctrl-mt7629.c
 create mode 100644 drivers/pinctrl/mediatek/pinctrl-mtk-common.c
 create mode 100644 drivers/pinctrl/mediatek/pinctrl-mtk-common.h
 create mode 100644 drivers/power/domain/mtk-power-domain.c
 create mode 100644 drivers/ram/mediatek/Makefile
 create mode 100644 drivers/ram/mediatek/ddr3-mt7629.c
 create mode 100644 drivers/spi/mtk_qspi.c
 create mode 100644 drivers/timer/mtk_timer.c
 create mode 100644 drivers/watchdog/mtk_wdt.c
 create mode 100644 include/configs/mt7623.h
 create mode 100644 include/configs/mt7629.h
 create mode 100644 include/dt-bindings/clock/mt7623-clk.h
 create mode 100644 include/dt-bindings/clock/mt7629-clk.h
 create mode 100644 include/dt-bindings/power/mt7623-power.h
 create mode 100644 include/dt-bindings/power/mt7629-power.h
 create mode 100644 tools/mtkimage.c
 create mode 100644 tools/mtkimage.h

-- 
1.9.1

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

* [U-Boot] [PATCH v2 01/18] tools: MediaTek: add MTK boot header generation to mkimage
  2018-10-12  7:00 [U-Boot] [PATCH v2 00/18] Add U-Boot support for MediaTek SoCs - MT7623n & MT7629 Ryder Lee
@ 2018-10-12  7:00 ` Ryder Lee
  2018-10-25  3:29   ` Simon Glass
  2018-10-12  7:00 ` [U-Boot] [PATCH v2 02/18] arm: dts: MediaTek: add device tree for MT7629 Ryder Lee
                   ` (16 subsequent siblings)
  17 siblings, 1 reply; 57+ messages in thread
From: Ryder Lee @ 2018-10-12  7:00 UTC (permalink / raw)
  To: u-boot

This patch adds support for MTK boot image generation.

Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
---
 Makefile             |  22 ++
 common/image.c       |   1 +
 include/image.h      |   1 +
 scripts/Makefile.spl |  11 +
 tools/Makefile       |   1 +
 tools/mtkimage.c     | 749 +++++++++++++++++++++++++++++++++++++++++++++++++++
 tools/mtkimage.h     | 199 ++++++++++++++
 7 files changed, 984 insertions(+)
 create mode 100644 tools/mtkimage.c
 create mode 100644 tools/mtkimage.h

diff --git a/Makefile b/Makefile
index aadd1ec..5ca7da6 100644
--- a/Makefile
+++ b/Makefile
@@ -852,6 +852,8 @@ ALL-y += u-boot-tegra.bin u-boot-nodtb-tegra.bin
 ALL-$(CONFIG_OF_SEPARATE) += u-boot-dtb-tegra.bin
 endif
 
+ALL-$(CONFIG_ARCH_MEDIATEK) += u-boot-mtk.bin
+
 # Add optional build target if defined in board/cpu/soc headers
 ifneq ($(CONFIG_BUILD_TARGET),)
 ALL-y += $(CONFIG_BUILD_TARGET:"%"=%)
@@ -1357,6 +1359,26 @@ u-boot.elf: u-boot.bin
 	$(Q)$(OBJCOPY) -I binary $(PLATFORM_ELFFLAGS) $< u-boot-elf.o
 	$(call if_changed,u-boot-elf)
 
+# MediaTek's ARM-based u-boot needs a header to contains its load address
+# which is parsed by the BootROM.
+# If the SPL build is enabled, the header will be added to the spl binary,
+# and the spl binary and the u-boot.img will be combined into one file.
+# Otherwise the header will be added to the u-boot.bin directly.
+
+ifeq ($(CONFIG_SPL),y)
+OBJCOPYFLAGS_u-boot-mtk.bin = -I binary -O binary \
+	--pad-to=$(CONFIG_SPL_PAD_TO)
+u-boot-mtk.bin: spl/u-boot-spl-mtk.bin u-boot.img FORCE
+	$(call if_changed,pad_cat)
+else
+MKIMAGEFLAGS_u-boot-mtk.bin = -T mtkimage \
+	-a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_TEXT_BASE) \
+	-n "$(patsubst "%",%,$(CONFIG_MTK_BROM_HEADER_INFO))"
+
+u-boot-mtk.bin: u-boot.bin FORCE
+	$(call if_changed,mkimage)
+endif
+
 ARCH_POSTLINK := $(wildcard $(srctree)/arch/$(ARCH)/Makefile.postlink)
 
 # Rule to link u-boot
diff --git a/common/image.c b/common/image.c
index 4f20128..3035cc8 100644
--- a/common/image.c
+++ b/common/image.c
@@ -165,6 +165,7 @@ static const table_entry_t uimage_type[] = {
 	{	IH_TYPE_FIRMWARE_IVT, "firmware_ivt", "Firmware with HABv4 IVT" },
 	{       IH_TYPE_PMMC,        "pmmc",        "TI Power Management Micro-Controller Firmware",},
 	{	IH_TYPE_STM32IMAGE, "stm32image", "STMicroelectronics STM32 Image" },
+	{	IH_TYPE_MTKIMAGE,   "mtkimage",   "MeidaTek BootROM loadable Image" },
 	{	-1,		    "",		  "",			},
 };
 
diff --git a/include/image.h b/include/image.h
index 3bb7d29..3128981 100644
--- a/include/image.h
+++ b/include/image.h
@@ -277,6 +277,7 @@ enum {
 	IH_TYPE_PMMC,            /* TI Power Management Micro-Controller Firmware */
 	IH_TYPE_STM32IMAGE,		/* STMicroelectronics STM32 Image */
 	IH_TYPE_SOCFPGAIMAGE_V1,	/* Altera SOCFPGA A10 Preloader	*/
+	IH_TYPE_MTKIMAGE,		/* MeidaTek BootROM loadable Image */
 
 	IH_TYPE_COUNT,			/* Number of image types */
 };
diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl
index 7416abe..989461a 100644
--- a/scripts/Makefile.spl
+++ b/scripts/Makefile.spl
@@ -219,6 +219,8 @@ ALL-$(CONFIG_SPL_X86_16BIT_INIT) += $(obj)/u-boot-x86-16bit-spl.bin
 ALL-$(CONFIG_ARCH_ZYNQ)		+= $(obj)/boot.bin
 ALL-$(CONFIG_ARCH_ZYNQMP)	+= $(obj)/boot.bin
 
+ALL-$(CONFIG_ARCH_MEDIATEK)	+= $(obj)/u-boot-spl-mtk.bin
+
 all:	$(ALL-y)
 
 quiet_cmd_cat = CAT     $@
@@ -349,6 +351,15 @@ cmd_sunxi_spl_image_builder = $(objtree)/tools/sunxi-spl-image-builder \
 $(obj)/sunxi-spl-with-ecc.bin: $(obj)/sunxi-spl.bin
 	$(call if_changed,sunxi_spl_image_builder)
 
+
+# MediaTek's specific SPL build
+MKIMAGEFLAGS_u-boot-spl-mtk.bin = -T mtkimage \
+	-a $(CONFIG_SPL_TEXT_BASE) -e $(CONFIG_SPL_TEXT_BASE) \
+	-n "$(patsubst "%",%,$(CONFIG_MTK_BROM_HEADER_INFO))"
+
+$(obj)/u-boot-spl-mtk.bin: $(obj)/u-boot-spl.bin FORCE
+	$(call if_changed,mkimage)
+
 # Rule to link u-boot-spl
 # May be overridden by arch/$(ARCH)/config.mk
 quiet_cmd_u-boot-spl ?= LD      $@
diff --git a/tools/Makefile b/tools/Makefile
index 0c3341e..11732e3 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -115,6 +115,7 @@ dumpimage-mkimage-objs := aisimage.o \
 			$(LIBFDT_OBJS) \
 			gpimage.o \
 			gpimage-common.o \
+			mtkimage.o \
 			$(RSA_OBJS-y)
 
 dumpimage-objs := $(dumpimage-mkimage-objs) dumpimage.o
diff --git a/tools/mtkimage.c b/tools/mtkimage.c
new file mode 100644
index 0000000..23ca378
--- /dev/null
+++ b/tools/mtkimage.c
@@ -0,0 +1,749 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Generate MediaTek BootROM header for SPL/U-Boot images
+ *
+ * Copyright (C) 2018 MediaTek Inc.
+ * Author: Weijie Gao <weijie.gao@mediatek.com>
+ */
+
+#include <image.h>
+#include <u-boot/sha256.h>
+#include "imagetool.h"
+#include "mtkimage.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+156",
+		.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
+	}
+};
+
+static const struct brom_img_type {
+	const char *name;
+	enum brlyt_img_type type;
+} brom_images[] = {
+	{
+		.name = "nand",
+		.type = BRLYT_TYPE_NAND
+	}, {
+		.name = "emmc",
+		.type = BRLYT_TYPE_EMMC
+	}, {
+		.name = "nor",
+		.type = BRLYT_TYPE_NOR
+	}, {
+		.name = "sdmmc",
+		.type = BRLYT_TYPE_SDMMC
+	}, {
+		.name = "snand",
+		.type = BRLYT_TYPE_SNAND
+	}
+};
+
+/* Image type selected by user */
+static enum brlyt_img_type hdr_media;
+static int use_lk_hdr;
+
+/* LK image name */
+static char lk_name[32] = "U-Boot";
+
+/* NAND header selected by user */
+static const union nand_boot_header *hdr_nand;
+
+/* GFH header + 2 * 4KB pages of NAND */
+static char hdr_tmp[sizeof(struct gfh_header) + 0x2000];
+
+static int mtk_image_check_image_types(uint8_t type)
+{
+	if (type == IH_TYPE_MTKIMAGE)
+		return EXIT_SUCCESS;
+	else
+		return EXIT_FAILURE;
+}
+
+static int mtk_brom_parse_imagename(const char *imagename)
+{
+#define is_blank_char(c) \
+	((c) == '\t' || (c) == '\n' || (c) == '\r' || (c) == ' ')
+
+	char *buf = strdup(imagename), *key, *val, *end, *next;
+	int i;
+
+	/* User passed arguments from image name */
+	static const char *media = "";
+	static const char *nandinfo = "";
+	static const char *lk = "";
+
+	key = buf;
+	while (key) {
+		next = strchr(key, ';');
+		if (next)
+			*next = 0;
+
+		val = strchr(key, '=');
+		if (val) {
+			*val++ = 0;
+
+			/* Trim key */
+			while (is_blank_char(*key))
+				key++;
+
+			end = key + strlen(key) - 1;
+			while ((end >= key) && is_blank_char(*end))
+				end--;
+			end++;
+
+			if (is_blank_char(*end))
+				*end = 0;
+
+			/* Trim value */
+			while (is_blank_char(*val))
+				val++;
+
+			end = val + strlen(val) - 1;
+			while ((end >= val) && is_blank_char(*end))
+				end--;
+			end++;
+
+			if (is_blank_char(*end))
+				*end = 0;
+
+			/* record user passed arguments */
+			if (!strcmp(key, "media"))
+				media = val;
+
+			if (!strcmp(key, "nandinfo"))
+				nandinfo = val;
+
+			if (!strcmp(key, "lk"))
+				lk = val;
+
+			if (!strcmp(key, "lkname"))
+				strncpy(lk_name, val, sizeof(lk_name));
+		}
+
+		if (next)
+			key = next + 1;
+		else
+			break;
+	}
+
+	/* if user specified LK image header, skip following checks */
+	if (lk && lk[0] == '1') {
+		use_lk_hdr = 1;
+		free(buf);
+		return 0;
+	}
+
+	/* parse media type */
+	for (i = 0; i < ARRAY_SIZE(brom_images); i++) {
+		if (!strcmp(brom_images[i].name, media)) {
+			hdr_media = brom_images[i].type;
+			break;
+		}
+	}
+
+	/* 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;
+		}
+	}
+
+	free(buf);
+
+	if (hdr_media == BRLYT_TYPE_INVALID) {
+		fprintf(stderr, "Error: media type is invalid or missing.\n");
+		fprintf(stderr, "       Please specify -n \"media=<type>\"\n");
+		return -EINVAL;
+	}
+
+	if ((hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND) &&
+	    !hdr_nand) {
+		fprintf(stderr, "Error: nand info is invalid or missing.\n");
+		fprintf(stderr, "       Please specify -n \"media=%s;"
+				"nandinfo=<info>\"\n", media);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int mtk_image_check_params(struct image_tool_params *params)
+{
+	if (!params->addr) {
+		fprintf(stderr, "Error: Load Address must be set.\n");
+		return -EINVAL;
+	}
+
+	if (!params->imagename) {
+		fprintf(stderr, "Error: Image Name must be set.\n");
+		return -EINVAL;
+	}
+
+	return mtk_brom_parse_imagename(params->imagename);
+}
+
+static int mtk_image_vrec_header(struct image_tool_params *params,
+				 struct image_type_params *tparams)
+{
+	if (use_lk_hdr) {
+		tparams->header_size = sizeof(union lk_hdr);
+		tparams->hdr = &hdr_tmp;
+		memset(&hdr_tmp, 0xff, tparams->header_size);
+		return 0;
+	}
+
+	if (hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND)
+		tparams->header_size = 2 * le16_to_cpu(hdr_nand->pagesize);
+	else
+		tparams->header_size = sizeof(struct gen_device_header);
+
+	tparams->header_size += sizeof(struct gfh_header);
+	tparams->hdr = &hdr_tmp;
+
+	memset(&hdr_tmp, 0xff, tparams->header_size);
+
+	return SHA256_SUM_LEN;
+}
+
+static int mtk_image_verify_gen_header(const uint8_t *ptr, int print)
+{
+	union gen_boot_header *gbh = (union gen_boot_header *)ptr;
+	struct brom_layout_header *bh;
+	struct gfh_header *gfh;
+	const char *bootmedia;
+
+	if (!strcmp(gbh->name, SF_BOOT_NAME))
+		bootmedia = "Serial NOR";
+	else if (!strcmp(gbh->name, EMMC_BOOT_NAME))
+		bootmedia = "eMMC";
+	else if (!strcmp(gbh->name, SDMMC_BOOT_NAME))
+		bootmedia = "SD/MMC";
+	else
+		return -1;
+
+	if (print)
+		printf("Boot Media:   %s\n", bootmedia);
+
+	if (le32_to_cpu(gbh->version) != 1 ||
+	    le32_to_cpu(gbh->size) != sizeof(union gen_boot_header))
+		return -1;
+
+	bh = (struct brom_layout_header *)(ptr + le32_to_cpu(gbh->size));
+
+	if (strcmp(bh->name, BRLYT_NAME))
+		return -1;
+
+	if (le32_to_cpu(bh->magic) != BRLYT_MAGIC ||
+	    (le32_to_cpu(bh->type) != BRLYT_TYPE_NOR &&
+	    le32_to_cpu(bh->type) != BRLYT_TYPE_EMMC &&
+	    le32_to_cpu(bh->type) != BRLYT_TYPE_SDMMC))
+		return -1;
+
+	gfh = (struct gfh_header *)(ptr + le32_to_cpu(bh->header_size));
+
+	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));
+
+	return 0;
+}
+
+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 gfh_header *gfh;
+	const char *bootmedia;
+
+	if (strncmp(nh->version, NAND_BOOT_VERSION, sizeof(nh->version)) ||
+	    strcmp(nh->id, NAND_BOOT_ID))
+		return -1;
+
+	bh = (struct brom_layout_header *)(ptr + le16_to_cpu(nh->pagesize));
+
+	if (strcmp(bh->name, BRLYT_NAME))
+		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";
+		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));
+		}
+
+		if (le16_to_cpu(nh->pagesize) >= 1024)
+			printf("Page Size:    %dKB\n",
+			       le16_to_cpu(nh->pagesize) >> 10);
+		else
+			printf("Page Size:    %dB\n",
+			       le16_to_cpu(nh->pagesize));
+
+		printf("Spare Size:   %dB\n", le16_to_cpu(nh->oobsize));
+	}
+
+	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));
+
+	return 0;
+}
+
+static int mtk_image_verify_header(unsigned char *ptr, int image_size,
+				   struct image_tool_params *params)
+{
+	union lk_hdr *lk = (union lk_hdr *)ptr;
+
+	/* nothing to verify for LK image header */
+	if (le32_to_cpu(lk->magic) == LK_PART_MAGIC)
+		return 0;
+
+	if (!strcmp((char *)ptr, NAND_BOOT_NAME))
+		return mtk_image_verify_nand_header(ptr, 0);
+	else
+		return mtk_image_verify_gen_header(ptr, 0);
+
+	return -1;
+}
+
+static void mtk_image_print_header(const void *ptr)
+{
+	union lk_hdr *lk = (union lk_hdr *)ptr;
+
+	if (le32_to_cpu(lk->magic) == LK_PART_MAGIC) {
+		printf("Image Type:   MediaTek LK Image\n");
+		printf("Load Address: %08x\n", le32_to_cpu(lk->loadaddr));
+		return;
+	}
+
+	printf("Image Type:   MediaTek BootROM Loadable Image\n");
+
+	if (!strcmp((char *)ptr, NAND_BOOT_NAME))
+		mtk_image_verify_nand_header(ptr, 1);
+	else
+		mtk_image_verify_gen_header(ptr, 1);
+}
+
+static void put_brom_layout_header(struct brom_layout_header *hdr, int type)
+{
+	strncpy(hdr->name, BRLYT_NAME, sizeof(hdr->name));
+	hdr->version = cpu_to_le32(1);
+	hdr->magic = cpu_to_le32(BRLYT_MAGIC);
+	hdr->type = cpu_to_le32(type);
+}
+
+static void put_ghf_common_header(struct gfh_common_header *gfh, int size,
+				  int type, int ver)
+{
+	memcpy(gfh->magic, GFH_HEADER_MAGIC, sizeof(gfh->magic));
+	gfh->version = ver;
+	gfh->size = cpu_to_le16(size);
+	gfh->type = cpu_to_le16(type);
+}
+
+static void put_ghf_header(struct gfh_header *gfh, int file_size,
+			   int dev_hdr_size, int load_addr, int flash_type)
+{
+	memset(gfh, 0, sizeof(struct gfh_header));
+
+	/* GFH_FILE_INFO header */
+	put_ghf_common_header(&gfh->file_info.gfh, sizeof(gfh->file_info),
+			      GFH_TYPE_FILE_INFO, 1);
+	strncpy(gfh->file_info.name, GFH_FILE_INFO_NAME,
+		sizeof(gfh->file_info.name));
+	gfh->file_info.unused = cpu_to_le32(1);
+	gfh->file_info.file_type = cpu_to_le16(1);
+	gfh->file_info.flash_type = flash_type;
+	gfh->file_info.sig_type = GFH_SIG_TYPE_SHA256;
+	gfh->file_info.load_addr = cpu_to_le32(load_addr - sizeof(*gfh));
+	gfh->file_info.total_size = cpu_to_le32(file_size - dev_hdr_size);
+	gfh->file_info.max_size = cpu_to_le32(file_size);
+	gfh->file_info.hdr_size = sizeof(*gfh);
+	gfh->file_info.sig_size = SHA256_SUM_LEN;
+	gfh->file_info.jump_offset = sizeof(*gfh);
+	gfh->file_info.processed = cpu_to_le32(1);
+
+	/* GFH_BL_INFO header */
+	put_ghf_common_header(&gfh->bl_info.gfh, sizeof(gfh->bl_info),
+			      GFH_TYPE_BL_INFO, 1);
+	gfh->bl_info.attr = cpu_to_le32(1);
+
+	/* GFH_BROM_CFG header */
+	put_ghf_common_header(&gfh->brom_cfg.gfh, sizeof(gfh->brom_cfg),
+			      GFH_TYPE_BROM_CFG, 3);
+	gfh->brom_cfg.cfg_bits = cpu_to_le32(
+		GFH_BROM_CFG_USBDL_AUTO_DETECT_DIS |
+		GFH_BROM_CFG_USBDL_BY_KCOL0_TIMEOUT_EN |
+		GFH_BROM_CFG_USBDL_BY_FLAG_TIMEOUT_EN);
+	gfh->brom_cfg.usbdl_by_kcol0_timeout_ms = cpu_to_le32(5000);
+
+	/* GFH_BL_SEC_KEY header */
+	put_ghf_common_header(&gfh->bl_sec_key.gfh, sizeof(gfh->bl_sec_key),
+			      GFH_TYPE_BL_SEC_KEY, 1);
+
+	/* GFH_ANTI_CLONE header */
+	put_ghf_common_header(&gfh->anti_clone.gfh, sizeof(gfh->anti_clone),
+			      GFH_TYPE_ANTI_CLONE, 1);
+	gfh->anti_clone.ac_offset = cpu_to_le32(0x10);
+	gfh->anti_clone.ac_len = cpu_to_le32(0x80);
+
+	/* GFH_BROM_SEC_CFG header */
+	put_ghf_common_header(&gfh->brom_sec_cfg.gfh,
+			      sizeof(gfh->brom_sec_cfg),
+			      GFH_TYPE_BROM_SEC_CFG, 1);
+	gfh->brom_sec_cfg.cfg_bits =
+		cpu_to_le32(BROM_SEC_CFG_JTAG_EN | BROM_SEC_CFG_UART_EN);
+}
+
+static void put_hash(uint8_t *buff, int size)
+{
+	sha256_context ctx;
+
+	sha256_starts(&ctx);
+	sha256_update(&ctx, buff, size);
+	sha256_finish(&ctx, buff + size);
+}
+
+static void mtk_image_set_gen_header(void *ptr, off_t filesize,
+				     uint32_t loadaddr)
+{
+	struct gen_device_header *hdr = (struct gen_device_header *)ptr;
+	struct gfh_header *gfh;
+	const char *bootname = NULL;
+
+	if (hdr_media == BRLYT_TYPE_NOR)
+		bootname = SF_BOOT_NAME;
+	else if (hdr_media == BRLYT_TYPE_EMMC)
+		bootname = EMMC_BOOT_NAME;
+	else if (hdr_media == BRLYT_TYPE_SDMMC)
+		bootname = SDMMC_BOOT_NAME;
+
+	/* Generic device header */
+	strncpy(hdr->boot.name, bootname, sizeof(hdr->boot.name));
+	hdr->boot.version = cpu_to_le32(1);
+	hdr->boot.size = cpu_to_le32(sizeof(hdr->boot));
+
+	/* BRLYT header */
+	put_brom_layout_header(&hdr->brlyt, hdr_media);
+	hdr->brlyt.header_size = cpu_to_le32(sizeof(struct gen_device_header));
+	hdr->brlyt.total_size = cpu_to_le32(filesize);
+	hdr->brlyt.header_size_2 = hdr->brlyt.header_size;
+	hdr->brlyt.total_size_2 = hdr->brlyt.total_size;
+
+	/* GFH header */
+	gfh = (struct gfh_header *)(ptr + sizeof(struct gen_device_header));
+	put_ghf_header(gfh, filesize, sizeof(struct gen_device_header),
+		       loadaddr, GFH_FLASH_TYPE_GEN);
+
+	/* Generate SHA256 hash */
+	put_hash((uint8_t *)gfh,
+		 filesize - sizeof(struct gen_device_header) - SHA256_SUM_LEN);
+}
+
+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;
+
+	/* NAND device header, repeat 4 times */
+	for (i = 0; i < 4; i++)
+		memcpy(nh + i, hdr_nand, sizeof(union nand_boot_header));
+
+	/* 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);
+
+	/* 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);
+
+	/* Generate SHA256 hash */
+	put_hash((uint8_t *)gfh,
+		 filesize - 2 * le16_to_cpu(hdr_nand->pagesize) - SHA256_SUM_LEN);
+}
+
+static void mtk_image_set_header(void *ptr, struct stat *sbuf, int ifd,
+				 struct image_tool_params *params)
+{
+	union lk_hdr *lk = (union lk_hdr *)ptr;
+
+	if (use_lk_hdr) {
+		lk->magic = cpu_to_le32(LK_PART_MAGIC);
+		lk->size = cpu_to_le32(sbuf->st_size - sizeof(union lk_hdr));
+		lk->loadaddr = cpu_to_le32(params->addr);
+		lk->mode = 0xffffffff; /* must be non-zero */
+		memset(lk->name, 0, sizeof(lk->name));
+		strncpy(lk->name, lk_name, sizeof(lk->name));
+		return;
+	}
+
+	if (hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND)
+		mtk_image_set_nand_header(ptr, sbuf->st_size, params->addr);
+	else
+		mtk_image_set_gen_header(ptr, sbuf->st_size, params->addr);
+}
+
+U_BOOT_IMAGE_TYPE(
+	mtkimage,
+	"MediaTek BootROM Loadable Image support",
+	0,
+	NULL,
+	mtk_image_check_params,
+	mtk_image_verify_header,
+	mtk_image_print_header,
+	mtk_image_set_header,
+	NULL,
+	mtk_image_check_image_types,
+	NULL,
+	mtk_image_vrec_header
+);
diff --git a/tools/mtkimage.h b/tools/mtkimage.h
new file mode 100644
index 0000000..0a9eab3
--- /dev/null
+++ b/tools/mtkimage.h
@@ -0,0 +1,199 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * MediaTek BootROM header definitions
+ *
+ * Copyright (C) 2018 MediaTek Inc.
+ * Author: Weijie Gao <weijie.gao@mediatek.com>
+ */
+
+#ifndef _MTK_IMAGE_H
+#define _MTK_IMAGE_H
+
+/* Device header definitions */
+
+/* Header for NOR/SD/eMMC */
+union gen_boot_header {
+	struct {
+		char name[12];
+		__le32 version;
+		__le32 size;
+	};
+
+	uint8_t pad[0x200];
+};
+
+#define EMMC_BOOT_NAME		"EMMC_BOOT"
+#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];
+		__le16 ioif;
+		__le16 pagesize;
+		__le16 addrcycles;
+		__le16 oobsize;
+		__le16 pages_of_block;
+		__le16 numblocks;
+		__le16 writesize_shift;
+		__le16 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];
+	__le32 version;
+	__le32 header_size;
+	__le32 total_size;
+	__le32 magic;
+	__le32 type;
+	__le32 header_size_2;
+	__le32 total_size_2;
+	__le32 unused;
+};
+
+#define BRLYT_NAME		"BRLYT"
+#define BRLYT_MAGIC		0x42424242
+
+enum brlyt_img_type {
+	BRLYT_TYPE_INVALID = 0,
+	BRLYT_TYPE_NAND = 0x10002,
+	BRLYT_TYPE_EMMC = 0x10005,
+	BRLYT_TYPE_NOR = 0x10007,
+	BRLYT_TYPE_SDMMC = 0x10008,
+	BRLYT_TYPE_SNAND = 0x10009
+};
+
+/* Combined device header for NOR/SD/eMMC */
+struct gen_device_header {
+	union gen_boot_header boot;
+
+	union {
+		struct brom_layout_header brlyt;
+		uint8_t brlyt_pad[0x400];
+	};
+};
+
+/* BootROM header definitions */
+struct gfh_common_header {
+	uint8_t magic[3];
+	uint8_t version;
+	__le16 size;
+	__le16 type;
+};
+
+#define GFH_HEADER_MAGIC	"MMM"
+
+#define GFH_TYPE_FILE_INFO	0
+#define GFH_TYPE_BL_INFO	1
+#define GFH_TYPE_BROM_CFG	7
+#define GFH_TYPE_BL_SEC_KEY	3
+#define GFH_TYPE_ANTI_CLONE	2
+#define GFH_TYPE_BROM_SEC_CFG	8
+
+struct gfh_file_info {
+	struct gfh_common_header gfh;
+	char name[12];
+	__le32 unused;
+	__le16 file_type;
+	uint8_t flash_type;
+	uint8_t sig_type;
+	__le32 load_addr;
+	__le32 total_size;
+	__le32 max_size;
+	__le32 hdr_size;
+	__le32 sig_size;
+	__le32 jump_offset;
+	__le32 processed;
+};
+
+#define GFH_FILE_INFO_NAME	"FILE_INFO"
+
+#define GFH_FLASH_TYPE_GEN	5
+#define GFH_FLASH_TYPE_NAND	2
+
+#define GFH_SIG_TYPE_NONE	0
+#define GFH_SIG_TYPE_SHA256	1
+
+struct gfh_bl_info {
+	struct gfh_common_header gfh;
+	__le32 attr;
+};
+
+struct gfh_brom_cfg {
+	struct gfh_common_header gfh;
+	__le32 cfg_bits;
+	__le32 usbdl_by_auto_detect_timeout_ms;
+	uint8_t unused[0x48];
+	__le32 usbdl_by_kcol0_timeout_ms;
+	__le32 usbdl_by_flag_timeout_ms;
+	uint32_t pad;
+};
+
+#define GFH_BROM_CFG_USBDL_BY_AUTO_DETECT_TIMEOUT_EN	0x02
+#define GFH_BROM_CFG_USBDL_AUTO_DETECT_DIS		0x10
+#define GFH_BROM_CFG_USBDL_BY_KCOL0_TIMEOUT_EN		0x80
+#define GFH_BROM_CFG_USBDL_BY_FLAG_TIMEOUT_EN		0x100
+
+struct gfh_bl_sec_key {
+	struct gfh_common_header gfh;
+	uint8_t pad[0x20c];
+};
+
+struct gfh_anti_clone {
+	struct gfh_common_header gfh;
+	uint8_t ac_b2k;
+	uint8_t ac_b2c;
+	uint16_t pad;
+	__le32 ac_offset;
+	__le32 ac_len;
+};
+
+struct gfh_brom_sec_cfg {
+	struct gfh_common_header gfh;
+	__le32 cfg_bits;
+	char customer_name[0x20];
+	__le32 pad;
+};
+
+#define BROM_SEC_CFG_JTAG_EN	1
+#define BROM_SEC_CFG_UART_EN	2
+
+struct gfh_header {
+	struct gfh_file_info file_info;
+	struct gfh_bl_info bl_info;
+	struct gfh_brom_cfg brom_cfg;
+	struct gfh_bl_sec_key bl_sec_key;
+	struct gfh_anti_clone anti_clone;
+	struct gfh_brom_sec_cfg brom_sec_cfg;
+};
+
+/* LK image header */
+
+union lk_hdr {
+	struct {
+		__le32 magic;
+		__le32 size;
+		char name[32];
+		__le32 loadaddr;
+		__le32 mode;
+	};
+
+	uint8_t data[512];
+};
+
+#define LK_PART_MAGIC		0x58881688
+
+#endif /* _MTK_IMAGE_H */
-- 
1.9.1

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

* [U-Boot] [PATCH v2 02/18] arm: dts: MediaTek: add device tree for MT7629
  2018-10-12  7:00 [U-Boot] [PATCH v2 00/18] Add U-Boot support for MediaTek SoCs - MT7623n & MT7629 Ryder Lee
  2018-10-12  7:00 ` [U-Boot] [PATCH v2 01/18] tools: MediaTek: add MTK boot header generation to mkimage Ryder Lee
@ 2018-10-12  7:00 ` Ryder Lee
  2018-10-25  3:29   ` Simon Glass
  2018-10-12  7:00 ` [U-Boot] [PATCH v2 03/18] arm: dts: MediaTek: add device tree for MT7623 Ryder Lee
                   ` (15 subsequent siblings)
  17 siblings, 1 reply; 57+ messages in thread
From: Ryder Lee @ 2018-10-12  7:00 UTC (permalink / raw)
  To: u-boot

This patch adds MT7629 device tree and the includes it needs.

Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
---
 arch/arm/dts/Makefile                    |   3 +
 arch/arm/dts/mt7629-rfb.dts              |  71 +++++++++
 arch/arm/dts/mt7629.dtsi                 | 244 +++++++++++++++++++++++++++++++
 include/dt-bindings/clock/mt7629-clk.h   | 206 ++++++++++++++++++++++++++
 include/dt-bindings/power/mt7629-power.h |  13 ++
 5 files changed, 537 insertions(+)
 create mode 100644 arch/arm/dts/mt7629-rfb.dts
 create mode 100644 arch/arm/dts/mt7629.dtsi
 create mode 100644 include/dt-bindings/clock/mt7629-clk.h
 create mode 100644 include/dt-bindings/power/mt7629-power.h

diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index dfe9335..1ab01e1 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -555,6 +555,9 @@ dtb-$(CONFIG_TARGET_STM32MP1) += \
 
 dtb-$(CONFIG_SOC_K3_AM6) += k3-am654-base-board.dtb
 
+dtb-$(CONFIG_ARCH_MEDIATEK) += \
+	mt7629-rfb.dtb
+
 targets += $(dtb-y)
 
 # Add any required device tree compiler flags here
diff --git a/arch/arm/dts/mt7629-rfb.dts b/arch/arm/dts/mt7629-rfb.dts
new file mode 100644
index 0000000..e3b8fb4
--- /dev/null
+++ b/arch/arm/dts/mt7629-rfb.dts
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ * Author: Ryder Lee <ryder.lee@mediatek.com>
+ *
+ * SPDX-License-Identifier: (GPL-2.0 OR MIT)
+ */
+
+/dts-v1/;
+#include "mt7629.dtsi"
+
+/ {
+	model = "MediaTek MT7629 RFB";
+	compatible = "mediatek,mt7629-rfb", "mediatek,mt7629";
+
+	aliases {
+		spi0 = &qspi;
+	};
+
+	chosen {
+		stdout-path = &uart0;
+		tick-timer = &timer0;
+	};
+};
+
+&pinctrl {
+	qspi_pins: qspi_pins {
+		pins_bus {
+			groups = "nor_flash_io", "nor_flash_wp",
+				 "nor_flash_hold";
+			function = "nor_flash";
+		};
+	};
+
+	uart0_pins: uart0-default {
+		mux {
+			function = "uart";
+			groups = "uart0_txd_rxd";
+		};
+	};
+
+	watchdog_pins: watchdog-default {
+		mux {
+			function = "watchdog";
+			groups = "watchdog";
+		};
+	};
+};
+
+&qspi {
+	pinctrl-names = "default";
+	pinctrl-0 = <&qspi_pins>;
+	status = "okay";
+
+	spi-flash at 0{
+		compatible = "spi-flash";
+		reg = <0>;
+		u-boot,dm-pre-reloc;
+	};
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pins>;
+	status = "okay";
+};
+
+&watchdog {
+	pinctrl-names = "default";
+	pinctrl-0 = <&watchdog_pins>;
+	status = "okay";
+};
diff --git a/arch/arm/dts/mt7629.dtsi b/arch/arm/dts/mt7629.dtsi
new file mode 100644
index 0000000..f7966cb
--- /dev/null
+++ b/arch/arm/dts/mt7629.dtsi
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ * Author: Ryder Lee <ryder.lee@mediatek.com>
+ *
+ * SPDX-License-Identifier: (GPL-2.0 OR MIT)
+ */
+
+#include <dt-bindings/clock/mt7629-clk.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/power/mt7629-power.h>
+#include "skeleton.dtsi"
+
+/ {
+	compatible = "mediatek,mt7629";
+	interrupt-parent = <&sysirq>;
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		enable-method = "mediatek,mt6589-smp";
+
+		cpu at 0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			reg = <0x0>;
+			clock-frequency = <1250000000>;
+		};
+
+		cpu at 1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			reg = <0x1>;
+			clock-frequency = <1250000000>;
+		};
+	};
+
+	clk20m: oscillator at 0 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <20000000>;
+		clock-output-names = "clk20m";
+	};
+
+	clk40m: oscillator at 1 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <40000000>;
+		clock-output-names = "clkxtal";
+	};
+
+	timer {
+		compatible = "arm,armv7-timer";
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+		clock-frequency = <20000000>;
+		arm,cpu-registers-not-fw-configured;
+	};
+
+	infracfg: syscon at 10000000 {
+		compatible = "mediatek,mt7629-infracfg", "syscon";
+		reg = <0x10000000 0x1000>;
+		#clock-cells = <1>;
+		u-boot,dm-pre-reloc;
+	};
+
+	pericfg: syscon at 10002000 {
+		compatible = "mediatek,mt7629-pericfg", "syscon";
+		reg = <0x10002000 0x1000>;
+		#clock-cells = <1>;
+		u-boot,dm-pre-reloc;
+	};
+
+	timer0: timer at 10004000 {
+		compatible = "mediatek,timer";
+		reg = <0x10004000 0x80>;
+		interrupts = <GIC_SPI 152 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&topckgen CLK_TOP_10M_SEL>,
+			 <&topckgen CLK_TOP_CLKXTAL_D4>;
+		clock-names = "mux", "src";
+		u-boot,dm-pre-reloc;
+	};
+
+	scpsys: scpsys at 10006000 {
+		compatible = "mediatek,mt7629-scpsys";
+		reg = <0x10006000 0x1000>;
+		clocks = <&topckgen CLK_TOP_HIF_SEL>;
+		clock-names = "hif_sel";
+		assigned-clocks = <&topckgen CLK_TOP_HIF_SEL>;
+		assigned-clock-parents = <&topckgen CLK_TOP_UNIVPLL1_D2>;
+		#power-domain-cells = <1>;
+		infracfg = <&infracfg>;
+	};
+
+	mcucfg: syscon at 10200000 {
+		compatible = "mediatek,mt7629-mcucfg", "syscon";
+		reg = <0x10200000 0x1000>;
+		#clock-cells = <1>;
+		u-boot,dm-pre-reloc;
+	};
+
+	sysirq: interrupt-controller at 10200a80 {
+		compatible = "mediatek,sysirq";
+		reg = <0x10200a80 0x20>;
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		interrupt-parent = <&gic>;
+	};
+
+	dramc: dramc at 10203000 {
+		compatible = "mediatek,mt7629-dramc";
+		reg = <0x10203000 0x600>,	/* EMI */
+		      <0x10213000 0x1000>,	/* DDRPHY */
+		      <0x10214000 0xd00>;	/* DRAMC_AO */
+		clocks = <&topckgen CLK_TOP_DDRPHYCFG_SEL>,
+			 <&topckgen CLK_TOP_SYSPLL1_D8>,
+			 <&topckgen CLK_TOP_MEM_SEL>,
+			 <&topckgen CLK_TOP_DMPLL>;
+		clock-names = "phy", "phy_mux", "mem", "mem_mux";
+		u-boot,dm-pre-reloc;
+	};
+
+	apmixedsys: clock-controller at 10209000 {
+		compatible = "mediatek,mt7629-apmixedsys";
+		reg = <0x10209000 0x1000>;
+		#clock-cells = <1>;
+		u-boot,dm-pre-reloc;
+	};
+
+	topckgen: clock-controller at 10210000 {
+		compatible = "mediatek,mt7629-topckgen";
+		reg = <0x10210000 0x1000>;
+		#clock-cells = <1>;
+		u-boot,dm-pre-reloc;
+	};
+
+	watchdog: watchdog at 10212000 {
+		compatible = "mediatek,wdt";
+		reg = <0x10212000 0x600>;
+		interrupts = <GIC_SPI 128 IRQ_TYPE_EDGE_FALLING>;
+		#reset-cells = <1>;
+		status = "disabled";
+	};
+
+	wdt-reboot {
+		compatible = "wdt-reboot";
+		wdt = <&watchdog>;
+	};
+
+	pinctrl: pinctrl at 10217000 {
+		compatible = "mediatek,mt7629-pinctrl";
+		reg = <0x10217000 0x8000>;
+
+		gpio: gpio-controller {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+	};
+
+	gic: interrupt-controller at 10300000 {
+		compatible = "arm,gic-400";
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		interrupt-parent = <&gic>;
+		reg = <0x10310000 0x1000>,
+		      <0x10320000 0x1000>,
+		      <0x10340000 0x2000>,
+		      <0x10360000 0x2000>;
+	};
+
+	uart0: serial at 11002000 {
+		compatible = "ns16550a";
+		reg = <0x11002000 0x400>;
+		reg-shift = <2>;
+		interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&topckgen CLK_TOP_UART_SEL>,
+			 <&pericfg CLK_PERI_UART0_PD>;
+		clock-names = "baud", "bus";
+		status = "disabled";
+		assigned-clocks = <&topckgen CLK_TOP_AXI_SEL>;
+		assigned-clock-parents = <&topckgen CLK_TOP_SYSPLL1_D2>;
+		u-boot,dm-pre-reloc;
+	};
+
+	uart1: serial at 11003000 {
+		compatible = "ns16550a";
+		reg = <0x11003000 0x400>;
+		reg-shift = <2>;
+		interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&topckgen CLK_TOP_UART_SEL>,
+			 <&pericfg CLK_PERI_UART1_PD>;
+		clock-names = "baud", "bus";
+		assigned-clocks = <&topckgen CLK_TOP_AXI_SEL>;
+		assigned-clock-parents = <&topckgen CLK_TOP_SYSPLL1_D2>;
+		status = "disabled";
+	};
+
+	uart2: serial at 11004000 {
+		compatible = "ns16550a";
+		reg = <0x11004000 0x400>;
+		reg-shift = <2>;
+		interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&topckgen CLK_TOP_UART_SEL>,
+			 <&pericfg CLK_PERI_UART2_PD>;
+		clock-names = "baud", "bus";
+		assigned-clocks = <&topckgen CLK_TOP_AXI_SEL>;
+		assigned-clock-parents = <&topckgen CLK_TOP_SYSPLL1_D2>;
+		status = "disabled";
+	};
+
+	qspi: qspi at 11014000 {
+		compatible = "mediatek,mt7629-qspi";
+		reg = <0x11014000 0xe0>, <0x30000000 0x10000000>;
+		reg-names = "reg_base", "mem_base";
+		status = "disabled";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		u-boot,dm-pre-reloc;
+	};
+
+	ethsys: syscon at 1b000000 {
+		compatible = "mediatek,mt7629-ethsys", "syscon";
+		reg = <0x1b000000 0x1000>;
+		#clock-cells = <1>;
+	};
+
+	sgmiisys0: syscon at 1b128000 {
+		compatible = "mediatek,mt7629-sgmiisys", "syscon";
+		reg = <0x1b128000 0x1000>;
+		#clock-cells = <1>;
+	};
+
+	sgmiisys1: syscon at 1b130000 {
+		compatible = "mediatek,mt7629-sgmiisys", "syscon";
+		reg = <0x1b130000 0x1000>;
+		#clock-cells = <1>;
+	};
+};
diff --git a/include/dt-bindings/clock/mt7629-clk.h b/include/dt-bindings/clock/mt7629-clk.h
new file mode 100644
index 0000000..0bbfbfa
--- /dev/null
+++ b/include/dt-bindings/clock/mt7629-clk.h
@@ -0,0 +1,206 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ */
+
+#ifndef _DT_BINDINGS_CLK_MT7629_H
+#define _DT_BINDINGS_CLK_MT7629_H
+
+/* TOPCKGEN */
+#define CLK_TOP_FCLKS_OFF		0
+
+#define CLK_TOP_TO_U2_PHY		0
+#define CLK_TOP_TO_U2_PHY_1P		1
+#define CLK_TOP_PCIE0_PIPE_EN		2
+#define CLK_TOP_PCIE1_PIPE_EN		3
+#define CLK_TOP_SSUSB_TX250M		4
+#define CLK_TOP_SSUSB_EQ_RX250M		5
+#define CLK_TOP_SSUSB_CDR_REF		6
+#define CLK_TOP_SSUSB_CDR_FB		7
+#define CLK_TOP_SATA_ASIC		8
+#define CLK_TOP_SATA_RBC		9
+
+#define CLK_TOP_TO_USB3_SYS		10
+#define CLK_TOP_P1_1MHZ			11
+#define CLK_TOP_4MHZ			12
+#define CLK_TOP_P0_1MHZ			13
+#define CLK_TOP_ETH_500M		14
+#define CLK_TOP_TXCLK_SRC_PRE		15
+#define CLK_TOP_RTC			16
+#define CLK_TOP_PWM_QTR_26M		17
+#define CLK_TOP_CPUM_TCK_IN		18
+#define CLK_TOP_TO_USB3_DA_TOP		19
+#define CLK_TOP_MEMPLL			20
+#define CLK_TOP_DMPLL			21
+#define CLK_TOP_DMPLL_D4		22
+#define CLK_TOP_DMPLL_D8		23
+#define CLK_TOP_SYSPLL_D2		24
+#define CLK_TOP_SYSPLL1_D2		25
+#define CLK_TOP_SYSPLL1_D4		26
+#define CLK_TOP_SYSPLL1_D8		27
+#define CLK_TOP_SYSPLL1_D16		28
+#define CLK_TOP_SYSPLL2_D2		29
+#define CLK_TOP_SYSPLL2_D4		30
+#define CLK_TOP_SYSPLL2_D8		31
+#define CLK_TOP_SYSPLL_D5		32
+#define CLK_TOP_SYSPLL3_D2		33
+#define CLK_TOP_SYSPLL3_D4		34
+#define CLK_TOP_SYSPLL_D7		35
+#define CLK_TOP_SYSPLL4_D2		36
+#define CLK_TOP_SYSPLL4_D4		37
+#define CLK_TOP_SYSPLL4_D16		38
+#define CLK_TOP_UNIVPLL			39
+#define CLK_TOP_UNIVPLL1_D2		40
+#define CLK_TOP_UNIVPLL1_D4		41
+#define CLK_TOP_UNIVPLL1_D8		42
+#define CLK_TOP_UNIVPLL_D3		43
+#define CLK_TOP_UNIVPLL2_D2		44
+#define CLK_TOP_UNIVPLL2_D4		45
+#define CLK_TOP_UNIVPLL2_D8		46
+#define CLK_TOP_UNIVPLL2_D16		47
+#define CLK_TOP_UNIVPLL_D5		48
+#define CLK_TOP_UNIVPLL3_D2		49
+#define CLK_TOP_UNIVPLL3_D4		50
+#define CLK_TOP_UNIVPLL3_D16		51
+#define CLK_TOP_UNIVPLL_D7		52
+#define CLK_TOP_UNIVPLL_D80_D4		53
+#define CLK_TOP_UNIV48M			54
+#define CLK_TOP_SGMIIPLL_D2		55
+#define CLK_TOP_CLKXTAL_D4		56
+#define CLK_TOP_HD_FAXI			57
+#define CLK_TOP_FAXI			58
+#define CLK_TOP_F_FAUD_INTBUS		59
+#define CLK_TOP_AP2WBHIF_HCLK		60
+#define CLK_TOP_10M_INFRAO		61
+#define CLK_TOP_MSDC30_1		62
+#define CLK_TOP_SPI			63
+#define CLK_TOP_SF			64
+#define CLK_TOP_FLASH			65
+#define CLK_TOP_TO_USB3_REF		66
+#define CLK_TOP_TO_USB3_MCU		67
+#define CLK_TOP_TO_USB3_DMA		68
+#define CLK_TOP_FROM_TOP_AHB		69
+#define CLK_TOP_FROM_TOP_AXI		70
+#define CLK_TOP_PCIE1_MAC_EN		71
+#define CLK_TOP_PCIE0_MAC_EN		72
+
+#define CLK_TOP_AXI_SEL			73
+#define CLK_TOP_MEM_SEL			74
+#define CLK_TOP_DDRPHYCFG_SEL		75
+#define CLK_TOP_ETH_SEL			76
+#define CLK_TOP_PWM_SEL			77
+#define CLK_TOP_F10M_REF_SEL		78
+#define CLK_TOP_NFI_INFRA_SEL		79
+#define CLK_TOP_FLASH_SEL		80
+#define CLK_TOP_UART_SEL		81
+#define CLK_TOP_SPI0_SEL		82
+#define CLK_TOP_SPI1_SEL		83
+#define CLK_TOP_MSDC50_0_SEL		84
+#define CLK_TOP_MSDC30_0_SEL		85
+#define CLK_TOP_MSDC30_1_SEL		86
+#define CLK_TOP_AP2WBMCU_SEL		87
+#define CLK_TOP_AP2WBHIF_SEL		88
+#define CLK_TOP_AUDIO_SEL		89
+#define CLK_TOP_AUD_INTBUS_SEL		90
+#define CLK_TOP_PMICSPI_SEL		91
+#define CLK_TOP_SCP_SEL			92
+#define CLK_TOP_ATB_SEL			93
+#define CLK_TOP_HIF_SEL			94
+#define CLK_TOP_SATA_SEL		95
+#define CLK_TOP_U2_SEL			96
+#define CLK_TOP_AUD1_SEL		97
+#define CLK_TOP_AUD2_SEL		98
+#define CLK_TOP_IRRX_SEL		99
+#define CLK_TOP_IRTX_SEL		100
+#define CLK_TOP_SATA_MCU_SEL		101
+#define CLK_TOP_PCIE0_MCU_SEL		102
+#define CLK_TOP_PCIE1_MCU_SEL		103
+#define CLK_TOP_SSUSB_MCU_SEL		104
+#define CLK_TOP_CRYPTO_SEL		105
+#define CLK_TOP_SGMII_REF_1_SEL		106
+#define CLK_TOP_10M_SEL			107
+#define CLK_TOP_NR_CLK			108
+
+/* INFRACFG */
+#define CLK_INFRA_MUX1_SEL		0
+#define CLK_INFRA_DBGCLK_PD		1
+#define CLK_INFRA_TRNG_PD		2
+#define CLK_INFRA_DEVAPC_PD		3
+#define CLK_INFRA_APXGPT_PD		4
+#define CLK_INFRA_SEJ_PD		5
+#define CLK_INFRA_NR_CLK		6
+
+/* PERICFG */
+#define CLK_PERIBUS_SEL			0
+#define CLK_PERI_PWM1_PD		1
+#define CLK_PERI_PWM2_PD		2
+#define CLK_PERI_PWM3_PD		3
+#define CLK_PERI_PWM4_PD		4
+#define CLK_PERI_PWM5_PD		5
+#define CLK_PERI_PWM6_PD		6
+#define CLK_PERI_PWM7_PD		7
+#define CLK_PERI_PWM_PD			8
+#define CLK_PERI_AP_DMA_PD		9
+#define CLK_PERI_MSDC30_1_PD		10
+#define CLK_PERI_UART0_PD		11
+#define CLK_PERI_UART1_PD		12
+#define CLK_PERI_UART2_PD		13
+#define CLK_PERI_UART3_PD		14
+#define CLK_PERI_BTIF_PD		15
+#define CLK_PERI_I2C0_PD		16
+#define CLK_PERI_SPI0_PD		17
+#define CLK_PERI_SNFI_PD		18
+#define CLK_PERI_NFI_PD			19
+#define CLK_PERI_NFIECC_PD		20
+#define CLK_PERI_FLASH_PD		21
+#define CLK_PERI_NR_CLK			22
+
+/* APMIXEDSYS */
+#define CLK_APMIXED_ARMPLL		0
+#define CLK_APMIXED_MAINPLL		1
+#define CLK_APMIXED_UNIV2PLL		2
+#define CLK_APMIXED_ETH1PLL		3
+#define CLK_APMIXED_ETH2PLL		4
+#define CLK_APMIXED_SGMIPLL		5
+#define CLK_APMIXED_NR_CLK		6
+
+/* SSUSBSYS */
+#define CLK_SSUSB_U2_PHY_1P_EN		0
+#define CLK_SSUSB_U2_PHY_EN		1
+#define CLK_SSUSB_REF_EN		2
+#define CLK_SSUSB_SYS_EN		3
+#define CLK_SSUSB_MCU_EN		4
+#define CLK_SSUSB_DMA_EN		5
+#define CLK_SSUSB_NR_CLK		6
+
+/* PCIESYS */
+#define CLK_PCIE_P1_AUX_EN		0
+#define CLK_PCIE_P1_OBFF_EN		1
+#define CLK_PCIE_P1_AHB_EN		2
+#define CLK_PCIE_P1_AXI_EN		3
+#define CLK_PCIE_P1_MAC_EN		4
+#define CLK_PCIE_P1_PIPE_EN		5
+#define CLK_PCIE_P0_AUX_EN		6
+#define CLK_PCIE_P0_OBFF_EN		7
+#define CLK_PCIE_P0_AHB_EN		8
+#define CLK_PCIE_P0_AXI_EN		9
+#define CLK_PCIE_P0_MAC_EN		10
+#define CLK_PCIE_P0_PIPE_EN		11
+#define CLK_PCIE_NR_CLK			12
+
+/* ETHSYS */
+#define CLK_ETH_FE_EN			0
+#define CLK_ETH_GP2_EN			1
+#define CLK_ETH_GP1_EN			2
+#define CLK_ETH_GP0_EN			3
+#define CLK_ETH_ESW_EN			4
+#define CLK_ETH_NR_CLK			5
+
+/* SGMIISYS */
+#define CLK_SGMII_TX_EN			0
+#define CLK_SGMII_RX_EN			1
+#define CLK_SGMII_CDR_REF		2
+#define CLK_SGMII_CDR_FB		3
+#define CLK_SGMII_NR_CLK		4
+
+#endif /* _DT_BINDINGS_CLK_MT7629_H */
diff --git a/include/dt-bindings/power/mt7629-power.h b/include/dt-bindings/power/mt7629-power.h
new file mode 100644
index 0000000..c7e6130
--- /dev/null
+++ b/include/dt-bindings/power/mt7629-power.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ */
+
+#ifndef _DT_BINDINGS_MT7629_POWER_H
+#define _DT_BINDINGS_MT7629_POWER_H
+
+#define MT7629_POWER_DOMAIN_ETHSYS	0
+#define MT7629_POWER_DOMAIN_HIF0	1
+#define MT7629_POWER_DOMAIN_HIF1	2
+
+#endif /* _DT_BINDINGS_MT7629_POWER_H */
-- 
1.9.1

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

* [U-Boot] [PATCH v2 03/18] arm: dts: MediaTek: add device tree for MT7623
  2018-10-12  7:00 [U-Boot] [PATCH v2 00/18] Add U-Boot support for MediaTek SoCs - MT7623n & MT7629 Ryder Lee
  2018-10-12  7:00 ` [U-Boot] [PATCH v2 01/18] tools: MediaTek: add MTK boot header generation to mkimage Ryder Lee
  2018-10-12  7:00 ` [U-Boot] [PATCH v2 02/18] arm: dts: MediaTek: add device tree for MT7629 Ryder Lee
@ 2018-10-12  7:00 ` Ryder Lee
  2018-10-25  3:29   ` Simon Glass
  2018-10-12  7:00 ` [U-Boot] [PATCH v2 04/18] arm: MediaTek: add basic support for MT7629 boards Ryder Lee
                   ` (14 subsequent siblings)
  17 siblings, 1 reply; 57+ messages in thread
From: Ryder Lee @ 2018-10-12  7:00 UTC (permalink / raw)
  To: u-boot

This adds device tree for MT7623 development board - Bananapi R2
Detailed hardware information for BPI-R2 which could be found on
http://wiki.banana-pi.org/Banana_Pi_BPI-R2.

Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
Tested-by: Matthias Brugger <matthias.bgg@gmail.com>
---
 arch/arm/dts/Makefile                    |   1 +
 arch/arm/dts/mt7623.dtsi                 | 255 +++++++++++++++++++
 arch/arm/dts/mt7623n-bananapi-bpi-r2.dts | 207 ++++++++++++++++
 include/dt-bindings/clock/mt7623-clk.h   | 413 +++++++++++++++++++++++++++++++
 include/dt-bindings/power/mt7623-power.h |  19 ++
 5 files changed, 895 insertions(+)
 create mode 100644 arch/arm/dts/mt7623.dtsi
 create mode 100644 arch/arm/dts/mt7623n-bananapi-bpi-r2.dts
 create mode 100644 include/dt-bindings/clock/mt7623-clk.h
 create mode 100644 include/dt-bindings/power/mt7623-power.h

diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 1ab01e1..44ed968 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -556,6 +556,7 @@ dtb-$(CONFIG_TARGET_STM32MP1) += \
 dtb-$(CONFIG_SOC_K3_AM6) += k3-am654-base-board.dtb
 
 dtb-$(CONFIG_ARCH_MEDIATEK) += \
+	mt7623n-bananapi-bpi-r2.dtb \
 	mt7629-rfb.dtb
 
 targets += $(dtb-y)
diff --git a/arch/arm/dts/mt7623.dtsi b/arch/arm/dts/mt7623.dtsi
new file mode 100644
index 0000000..3be5b6a
--- /dev/null
+++ b/arch/arm/dts/mt7623.dtsi
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ * Author: Ryder Lee <ryder.lee@mediatek.com>
+ *
+ * SPDX-License-Identifier: (GPL-2.0 OR MIT)
+ */
+
+#include <dt-bindings/clock/mt7623-clk.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/power/mt7623-power.h>
+#include "skeleton.dtsi"
+
+/ {
+	compatible = "mediatek,mt7623";
+	interrupt-parent = <&sysirq>;
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		enable-method = "mediatek,mt6589-smp";
+
+		cpu0: cpu at 0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			reg = <0x0>;
+			clocks = <&infracfg CLK_INFRA_CPUSEL>,
+				 <&apmixedsys CLK_APMIXED_MAINPLL>;
+			clock-names = "cpu", "intermediate";
+			clock-frequency = <1300000000>;
+		};
+
+		cpu1: cpu at 1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			reg = <0x1>;
+			clocks = <&infracfg CLK_INFRA_CPUSEL>,
+				 <&apmixedsys CLK_APMIXED_MAINPLL>;
+			clock-names = "cpu", "intermediate";
+			clock-frequency = <1300000000>;
+		};
+
+		cpu2: cpu at 2 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			reg = <0x2>;
+			clocks = <&infracfg CLK_INFRA_CPUSEL>,
+				 <&apmixedsys CLK_APMIXED_MAINPLL>;
+			clock-names = "cpu", "intermediate";
+			clock-frequency = <1300000000>;
+		};
+
+		cpu3: cpu at 3 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			reg = <0x3>;
+			clocks = <&infracfg CLK_INFRA_CPUSEL>,
+				 <&apmixedsys CLK_APMIXED_MAINPLL>;
+			clock-names = "cpu", "intermediate";
+			clock-frequency = <1300000000>;
+		};
+	};
+
+	system_clk: dummy13m {
+		compatible = "fixed-clock";
+		clock-frequency = <13000000>;
+		#clock-cells = <0>;
+	};
+
+	rtc32k: oscillator-1 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <32000>;
+		clock-output-names = "rtc32k";
+	};
+
+	clk26m: oscillator-0 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <26000000>;
+		clock-output-names = "clk26m";
+	};
+
+	timer {
+		compatible = "arm,armv7-timer";
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+		clock-frequency = <13000000>;
+		arm,cpu-registers-not-fw-configured;
+	};
+
+	topckgen: clock-controller at 10000000 {
+		compatible = "mediatek,mt7623-topckgen";
+		reg = <0x10000000 0x1000>;
+		#clock-cells = <1>;
+		u-boot,dm-pre-reloc;
+	};
+
+	infracfg: syscon at 10001000 {
+		compatible = "mediatek,mt7623-infracfg", "syscon";
+		reg = <0x10001000 0x1000>;
+		#clock-cells = <1>;
+		u-boot,dm-pre-reloc;
+	};
+
+	pericfg: syscon at 10003000 {
+		compatible = "mediatek,mt7623-pericfg", "syscon";
+		reg = <0x10003000 0x1000>;
+		#clock-cells = <1>;
+		u-boot,dm-pre-reloc;
+	};
+
+	pinctrl: pinctrl at 10005000 {
+		compatible = "mediatek,mt7623-pinctrl";
+		reg = <0x10005000 0x1000>;
+
+		gpio: gpio-controller {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+	};
+
+	scpsys: scpsys at 10006000 {
+		compatible = "mediatek,mt7623-scpsys";
+		#power-domain-cells = <1>;
+		reg = <0x10006000 0x1000>;
+		infracfg = <&infracfg>;
+		clocks = <&topckgen CLK_TOP_MM_SEL>,
+			 <&topckgen CLK_TOP_MFG_SEL>,
+			 <&topckgen CLK_TOP_ETHIF_SEL>;
+		clock-names = "mm", "mfg", "ethif";
+	};
+
+	watchdog: watchdog at 10007000 {
+		compatible = "mediatek,wdt";
+		reg = <0x10007000 0x100>;
+	};
+
+	wdt-reboot {
+		compatible = "wdt-reboot";
+		wdt = <&watchdog>;
+	};
+
+	timer0: timer at 10008000 {
+		compatible = "mediatek,timer";
+		reg = <0x10008000 0x80>;
+		interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&system_clk>;
+		clock-names = "system-clk";
+		u-boot,dm-pre-reloc;
+	};
+
+	sysirq: interrupt-controller at 10200100 {
+		compatible = "mediatek,sysirq";
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		interrupt-parent = <&gic>;
+		reg = <0x10200100 0x1c>;
+	};
+
+	apmixedsys: clock-controller at 10209000 {
+		compatible = "mediatek,mt7623-apmixedsys";
+		reg = <0x10209000 0x1000>;
+		#clock-cells = <1>;
+		u-boot,dm-pre-reloc;
+	};
+
+	gic: interrupt-controller at 10211000 {
+		compatible = "arm,cortex-a7-gic";
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		interrupt-parent = <&gic>;
+		reg = <0x10211000 0x1000>,
+		      <0x10212000 0x1000>,
+		      <0x10214000 0x2000>,
+		      <0x10216000 0x2000>;
+	};
+
+	uart0: serial at 11002000 {
+		compatible = "ns16550a";
+		reg = <0x11002000 0x400>;
+		reg-shift = <2>;
+		interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&topckgen CLK_TOP_UART_SEL>,
+			 <&pericfg CLK_PERI_UART0>;
+		clock-names = "baud", "bus";
+		status = "disabled";
+	};
+
+	uart1: serial at 11003000 {
+		compatible = "ns16550a";
+		reg = <0x11003000 0x400>;
+		reg-shift = <2>;
+		interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&topckgen CLK_TOP_UART_SEL>,
+			 <&pericfg CLK_PERI_UART1>;
+		clock-names = "baud", "bus";
+		status = "disabled";
+	};
+
+	uart2: serial at 11004000 {
+		compatible = "ns16550a";
+		reg = <0x11004000 0x400>;
+		reg-shift = <2>;
+		interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&topckgen CLK_TOP_UART_SEL>,
+			 <&pericfg CLK_PERI_UART2>;
+		clock-names = "baud", "bus";
+		status = "disabled";
+		u-boot,dm-pre-reloc;
+	};
+
+	uart3: serial at 11005000 {
+		compatible = "ns16550a";
+		reg = <0x11005000 0x400>;
+		reg-shift = <2>;
+		interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&topckgen CLK_TOP_UART_SEL>,
+			 <&pericfg CLK_PERI_UART3>;
+		clock-names = "baud", "bus";
+		status = "disabled";
+	};
+
+	mmc0: mmc at 11230000 {
+		compatible = "mediatek,mt7623-mmc";
+		reg = <0x11230000 0x1000>;
+		interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&pericfg CLK_PERI_MSDC30_0>,
+			 <&topckgen CLK_TOP_MSDC30_0_SEL>;
+		clock-names = "source", "hclk";
+		status = "disabled";
+	};
+
+	mmc1: mmc at 11240000 {
+		compatible = "mediatek,mt7623-mmc";
+		reg = <0x11240000 0x1000>;
+		interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&pericfg CLK_PERI_MSDC30_1>,
+			 <&topckgen CLK_TOP_MSDC30_1_SEL>;
+		clock-names = "source", "hclk";
+		status = "disabled";
+	};
+
+	ethsys: syscon at 1b000000 {
+		compatible = "mediatek,mt7623-ethsys";
+		reg = <0x1b000000 0x1000>;
+		#clock-cells = <1>;
+	};
+};
diff --git a/arch/arm/dts/mt7623n-bananapi-bpi-r2.dts b/arch/arm/dts/mt7623n-bananapi-bpi-r2.dts
new file mode 100644
index 0000000..84a77fd
--- /dev/null
+++ b/arch/arm/dts/mt7623n-bananapi-bpi-r2.dts
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ * Author: Ryder Lee <ryder.lee@mediatek.com>
+ *
+ * SPDX-License-Identifier: (GPL-2.0 OR MIT)
+ */
+
+/dts-v1/;
+#include "mt7623.dtsi"
+
+/ {
+	model = "Bananapi BPI-R2";
+	compatible = "bananapi,bpi-r2", "mediatek,mt7623";
+
+	chosen {
+		stdout-path = &uart2;
+		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;
+	};
+
+	reg_5v: regulator-5v {
+		compatible = "regulator-fixed";
+		regulator-name = "fixed-5V";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		blue {
+			label = "bpi-r2:pio:blue";
+			gpios = <&gpio 241 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		green {
+			label = "bpi-r2:pio:green";
+			gpios = <&gpio 240 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		red {
+			label = "bpi-r2:pio:red";
+			gpios = <&gpio 239 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+	};
+};
+
+&mmc0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc0_pins_default>;
+	status = "okay";
+	bus-width = <8>;
+	max-frequency = <50000000>;
+	cap-mmc-highspeed;
+	vmmc-supply = <&reg_3p3v>;
+	vqmmc-supply = <&reg_1p8v>;
+	non-removable;
+};
+
+&mmc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc1_pins_default>;
+	status = "okay";
+	bus-width = <4>;
+	max-frequency = <50000000>;
+	cap-sd-highspeed;
+	cd-gpios = <&gpio 261 GPIO_ACTIVE_LOW>;
+	vmmc-supply = <&reg_3p3v>;
+	vqmmc-supply = <&reg_3p3v>;
+};
+
+&pinctrl {
+	ephy_default: ephy_default {
+		mux {
+			function = "eth";
+			groups = "mdc_mdio", "ephy";
+		};
+
+		conf {
+			pins = "G2_TXEN", "G2_TXD0", "G2_TXD1", "G2_TXD2",
+			       "G2_TXD3", "G2_TXC", "G2_RXC", "G2_RXD0",
+			       "G2_RXD1", "G2_RXD2", "G2_RXD3", "G2_RXDV",
+			       "MDC", "MDIO";
+			drive-strength = <12>;
+			mediatek,tdsel = <5>;
+		};
+	};
+
+	mmc0_pins_default: mmc0default {
+		mux {
+			function = "msdc";
+			groups =  "msdc0";
+		};
+
+		conf-cmd-data {
+			pins = "MSDC0_CMD", "MSDC0_DAT0", "MSDC0_DAT1",
+			       "MSDC0_DAT2", "MSDC0_DAT3", "MSDC0_DAT4",
+			       "MSDC0_DAT5", "MSDC0_DAT6", "MSDC0_DAT7";
+			input-enable;
+			bias-pull-up;
+		};
+
+		conf-clk {
+			pins = "MSDC0_CLK";
+			bias-pull-down;
+		};
+
+		conf-rst {
+			pins = "MSDC0_RSTB";
+			bias-pull-up;
+		};
+	};
+
+	mmc1_pins_default: mmc1default {
+		mux {
+			function = "msdc";
+			groups =  "msdc1", "msdc1_wp_0";
+		};
+
+		conf-cmd-data {
+			pins = "MSDC1_DAT0", "MSDC1_DAT1", "MSDC1_DAT2",
+			       "MSDC1_DAT3", "MSDC1_DAT3", "MSDC1_CMD";
+			input-enable;
+			drive-strength = <4>;
+			bias-pull-up;
+		};
+
+		conf-clk {
+			pins = "MSDC1_CLK";
+			drive-strength = <4>;
+		};
+
+		conf-wp {
+			pins = "EINT7";
+			input-enable;
+			bias-pull-up;
+		};
+	};
+
+	uart0_pins_a: uart0-default {
+		mux {
+			function = "uart";
+			groups =  "uart0_0_txd_rxd";
+		};
+	};
+
+	uart1_pins_a: uart1-default {
+		mux {
+			function = "uart";
+			groups =  "uart1_0_txd_rxd";
+		};
+	};
+
+	uart2_pins_a: uart2-default {
+		mux {
+			function = "uart";
+			groups =  "uart2_0_txd_rxd";
+		};
+	};
+
+	uart2_pins_b: uart2-alt {
+		mux {
+			function = "uart";
+			groups =  "uart2_1_txd_rxd";
+		};
+	};
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pins_a>;
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_pins_a>;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart2_pins_a>;
+	status = "okay";
+};
diff --git a/include/dt-bindings/clock/mt7623-clk.h b/include/dt-bindings/clock/mt7623-clk.h
new file mode 100644
index 0000000..71ced15
--- /dev/null
+++ b/include/dt-bindings/clock/mt7623-clk.h
@@ -0,0 +1,413 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ */
+
+#ifndef _DT_BINDINGS_CLK_MT2701_H
+#define _DT_BINDINGS_CLK_MT2701_H
+
+/* TOPCKGEN */
+#define CLK_TOP_FCLKS_OFF			0
+
+#define CLK_TOP_DPI				0
+#define CLK_TOP_DMPLL				1
+#define CLK_TOP_VENCPLL				2
+#define CLK_TOP_HDMI_0_PIX340M			3
+#define CLK_TOP_HDMI_0_DEEP340M			4
+#define CLK_TOP_HDMI_0_PLL340M			5
+#define CLK_TOP_HADDS2_FB			6
+#define CLK_TOP_WBG_DIG_416M			7
+#define CLK_TOP_DSI0_LNTC_DSI			8
+#define CLK_TOP_HDMI_SCL_RX			9
+#define CLK_TOP_32K_EXTERNAL			10
+#define CLK_TOP_HDMITX_CLKDIG_CTS		11
+#define CLK_TOP_AUD_EXT1			12
+#define CLK_TOP_AUD_EXT2			13
+#define CLK_TOP_NFI1X_PAD			14
+
+#define CLK_TOP_SYSPLL				15
+#define CLK_TOP_SYSPLL_D2			16
+#define CLK_TOP_SYSPLL_D3			17
+#define CLK_TOP_SYSPLL_D5			18
+#define CLK_TOP_SYSPLL_D7			19
+#define CLK_TOP_SYSPLL1_D2			20
+#define CLK_TOP_SYSPLL1_D4			21
+#define CLK_TOP_SYSPLL1_D8			22
+#define CLK_TOP_SYSPLL1_D16			23
+#define CLK_TOP_SYSPLL2_D2			24
+#define CLK_TOP_SYSPLL2_D4			25
+#define CLK_TOP_SYSPLL2_D8			26
+#define CLK_TOP_SYSPLL3_D2			27
+#define CLK_TOP_SYSPLL3_D4			28
+#define CLK_TOP_SYSPLL4_D2			29
+#define CLK_TOP_SYSPLL4_D4			30
+#define CLK_TOP_UNIVPLL				31
+#define CLK_TOP_UNIVPLL_D2			32
+#define CLK_TOP_UNIVPLL_D3			33
+#define CLK_TOP_UNIVPLL_D5			34
+#define CLK_TOP_UNIVPLL_D7			35
+#define CLK_TOP_UNIVPLL_D26			36
+#define CLK_TOP_UNIVPLL_D52			37
+#define CLK_TOP_UNIVPLL_D108			38
+#define CLK_TOP_USB_PHY48M			39
+#define CLK_TOP_UNIVPLL1_D2			40
+#define CLK_TOP_UNIVPLL1_D4			41
+#define CLK_TOP_UNIVPLL1_D8			42
+#define CLK_TOP_UNIVPLL2_D2			43
+#define CLK_TOP_UNIVPLL2_D4			44
+#define CLK_TOP_UNIVPLL2_D8			45
+#define CLK_TOP_UNIVPLL2_D16			46
+#define CLK_TOP_UNIVPLL2_D32			47
+#define CLK_TOP_UNIVPLL3_D2			48
+#define CLK_TOP_UNIVPLL3_D4			49
+#define CLK_TOP_UNIVPLL3_D8			50
+#define CLK_TOP_MSDCPLL				51
+#define CLK_TOP_MSDCPLL_D2			52
+#define CLK_TOP_MSDCPLL_D4			53
+#define CLK_TOP_MSDCPLL_D8			54
+#define CLK_TOP_MMPLL				55
+#define CLK_TOP_MMPLL_D2			56
+#define CLK_TOP_DMPLL_D2			57
+#define CLK_TOP_DMPLL_D4			58
+#define CLK_TOP_DMPLL_X2			59
+#define CLK_TOP_TVDPLL				60
+#define CLK_TOP_TVDPLL_D2			61
+#define CLK_TOP_TVDPLL_D4			62
+#define CLK_TOP_VDECPLL				63
+#define CLK_TOP_TVD2PLL				64
+#define CLK_TOP_TVD2PLL_D2			65
+#define CLK_TOP_MIPIPLL				66
+#define CLK_TOP_MIPIPLL_D2			67
+#define CLK_TOP_MIPIPLL_D4			68
+#define CLK_TOP_HDMIPLL				69
+#define CLK_TOP_HDMIPLL_D2			70
+#define CLK_TOP_HDMIPLL_D3			71
+#define CLK_TOP_ARMPLL_1P3G			72
+#define CLK_TOP_AUDPLL				73
+#define CLK_TOP_AUDPLL_D4			74
+#define CLK_TOP_AUDPLL_D8			75
+#define CLK_TOP_AUDPLL_D16			76
+#define CLK_TOP_AUDPLL_D24			77
+#define CLK_TOP_AUD1PLL_98M			78
+#define CLK_TOP_AUD2PLL_90M			79
+#define CLK_TOP_HADDS2PLL_98M			80
+#define CLK_TOP_HADDS2PLL_294M			81
+#define CLK_TOP_ETHPLL_500M			82
+#define CLK_TOP_CLK26M_D8			83
+#define CLK_TOP_32K_INTERNAL			84
+#define CLK_TOP_AXISEL_D4			85
+#define CLK_TOP_8BDAC				86
+
+#define CLK_TOP_AXI_SEL				87
+#define CLK_TOP_MEM_SEL				88
+#define CLK_TOP_DDRPHYCFG_SEL			89
+#define CLK_TOP_MM_SEL				90
+#define CLK_TOP_PWM_SEL				91
+#define CLK_TOP_VDEC_SEL			92
+#define CLK_TOP_MFG_SEL				93
+#define CLK_TOP_CAMTG_SEL			94
+#define CLK_TOP_UART_SEL			95
+#define CLK_TOP_SPI0_SEL			96
+#define CLK_TOP_USB20_SEL			97
+#define CLK_TOP_MSDC30_0_SEL			98
+#define CLK_TOP_MSDC30_1_SEL			99
+#define CLK_TOP_MSDC30_2_SEL			100
+#define CLK_TOP_AUDIO_SEL			101
+#define CLK_TOP_AUDINTBUS_SEL			102
+#define CLK_TOP_PMICSPI_SEL			103
+#define CLK_TOP_SCP_SEL				104
+#define CLK_TOP_DPI0_SEL			105
+#define CLK_TOP_DPI1_SEL			106
+#define CLK_TOP_TVE_SEL				107
+#define CLK_TOP_HDMI_SEL			108
+#define CLK_TOP_APLL_SEL			109
+#define CLK_TOP_RTC_SEL				110
+#define CLK_TOP_NFI2X_SEL			111
+#define CLK_TOP_EMMC_HCLK_SEL			112
+#define CLK_TOP_FLASH_SEL			113
+#define CLK_TOP_DI_SEL				114
+#define CLK_TOP_NR_SEL				115
+#define CLK_TOP_OSD_SEL				116
+#define CLK_TOP_HDMIRX_BIST_SEL			117
+#define CLK_TOP_INTDIR_SEL			118
+#define CLK_TOP_ASM_I_SEL			119
+#define CLK_TOP_ASM_M_SEL			120
+#define CLK_TOP_ASM_H_SEL			121
+#define CLK_TOP_MS_CARD_SEL			122
+#define CLK_TOP_ETHIF_SEL			123
+#define CLK_TOP_HDMIRX26_24_SEL			124
+#define CLK_TOP_MSDC30_3_SEL			125
+#define CLK_TOP_CMSYS_SEL			126
+#define CLK_TOP_SPI1_SEL			127
+#define CLK_TOP_SPI2_SEL			128
+#define CLK_TOP_8BDAC_SEL			129
+#define CLK_TOP_AUD2DVD_SEL			130
+#define CLK_TOP_PADMCLK_SEL			131
+#define CLK_TOP_AUD_MUX1_SEL			132
+#define CLK_TOP_AUD_MUX2_SEL			133
+#define CLK_TOP_AUDPLL_MUX_SEL			134
+#define CLK_TOP_AUD_K1_SRC_SEL			135
+#define CLK_TOP_AUD_K2_SRC_SEL			136
+#define CLK_TOP_AUD_K3_SRC_SEL			137
+#define CLK_TOP_AUD_K4_SRC_SEL			138
+#define CLK_TOP_AUD_K5_SRC_SEL			139
+#define CLK_TOP_AUD_K6_SRC_SEL			140
+
+#define CLK_TOP_AUD_EXTCK1_DIV			141
+#define CLK_TOP_AUD_EXTCK2_DIV			142
+#define CLK_TOP_AUD_MUX1_DIV			143
+#define CLK_TOP_AUD_MUX2_DIV			144
+#define CLK_TOP_AUD_K1_SRC_DIV			145
+#define CLK_TOP_AUD_K2_SRC_DIV			146
+#define CLK_TOP_AUD_K3_SRC_DIV			147
+#define CLK_TOP_AUD_K4_SRC_DIV			148
+#define CLK_TOP_AUD_K5_SRC_DIV			149
+#define CLK_TOP_AUD_K6_SRC_DIV			150
+#define CLK_TOP_AUD_48K_TIMING			151
+#define CLK_TOP_AUD_44K_TIMING			152
+#define CLK_TOP_AUD_I2S1_MCLK			153
+#define CLK_TOP_AUD_I2S2_MCLK			154
+#define CLK_TOP_AUD_I2S3_MCLK			155
+#define CLK_TOP_AUD_I2S4_MCLK			156
+#define CLK_TOP_AUD_I2S5_MCLK			157
+#define CLK_TOP_AUD_I2S6_MCLK			158
+#define CLK_TOP_NR				159
+
+/* APMIXEDSYS */
+#define CLK_APMIXED_ARMPLL			0
+#define CLK_APMIXED_MAINPLL			1
+#define CLK_APMIXED_UNIVPLL			2
+#define CLK_APMIXED_MMPLL			3
+#define CLK_APMIXED_MSDCPLL			4
+#define CLK_APMIXED_TVDPLL			5
+#define CLK_APMIXED_AUD1PLL			6
+#define CLK_APMIXED_TRGPLL			7
+#define CLK_APMIXED_ETHPLL			8
+#define CLK_APMIXED_VDECPLL			9
+#define CLK_APMIXED_HADDS2PLL			10
+#define CLK_APMIXED_AUD2PLL			11
+#define CLK_APMIXED_TVD2PLL			12
+#define CLK_APMIXED_NR				13
+
+/* INFRACFG */
+#define CLK_INFRA_DBG				0
+#define CLK_INFRA_SMI				1
+#define CLK_INFRA_QAXI_CM4			2
+#define CLK_INFRA_AUD_SPLIN_B			3
+#define CLK_INFRA_AUDIO				4
+#define CLK_INFRA_EFUSE				5
+#define CLK_INFRA_L2C_SRAM			6
+#define CLK_INFRA_M4U				7
+#define CLK_INFRA_CONNMCU			8
+#define CLK_INFRA_TRNG				9
+#define CLK_INFRA_RAMBUFIF			10
+#define CLK_INFRA_CPUM				11
+#define CLK_INFRA_KP				12
+#define CLK_INFRA_CEC				13
+#define CLK_INFRA_IRRX				14
+#define CLK_INFRA_PMICSPI			15
+#define CLK_INFRA_PMICWRAP			16
+#define CLK_INFRA_DDCCI				17
+#define CLK_INFRA_CPUSEL			18
+#define CLK_INFRA_NR				19
+
+/* PERICFG */
+#define CLK_PERI_NFI				0
+#define CLK_PERI_THERM				1
+#define CLK_PERI_PWM1				2
+#define CLK_PERI_PWM2				3
+#define CLK_PERI_PWM3				4
+#define CLK_PERI_PWM4				5
+#define CLK_PERI_PWM5				6
+#define CLK_PERI_PWM6				7
+#define CLK_PERI_PWM7				8
+#define CLK_PERI_PWM				9
+#define CLK_PERI_USB0				10
+#define CLK_PERI_USB1				11
+#define CLK_PERI_AP_DMA				12
+#define CLK_PERI_MSDC30_0			13
+#define CLK_PERI_MSDC30_1			14
+#define CLK_PERI_MSDC30_2			15
+#define CLK_PERI_MSDC30_3			16
+#define CLK_PERI_MSDC50_3			17
+#define CLK_PERI_NLI				18
+#define CLK_PERI_UART0				19
+#define CLK_PERI_UART1				20
+#define CLK_PERI_UART2				21
+#define CLK_PERI_UART3				22
+#define CLK_PERI_BTIF				23
+#define CLK_PERI_I2C0				24
+#define CLK_PERI_I2C1				25
+#define CLK_PERI_I2C2				26
+#define CLK_PERI_I2C3				27
+#define CLK_PERI_AUXADC				28
+#define CLK_PERI_SPI0				39
+#define CLK_PERI_ETH				30
+#define CLK_PERI_USB0_MCU			31
+
+#define CLK_PERI_USB1_MCU			32
+#define CLK_PERI_USB_SLV			33
+#define CLK_PERI_GCPU				34
+#define CLK_PERI_NFI_ECC			35
+#define CLK_PERI_NFI_PAD			36
+#define CLK_PERI_FLASH				37
+#define CLK_PERI_HOST89_INT			38
+#define CLK_PERI_HOST89_SPI			39
+#define CLK_PERI_HOST89_DVD			40
+#define CLK_PERI_SPI1				41
+#define CLK_PERI_SPI2				42
+#define CLK_PERI_FCI				43
+#define CLK_PERI_NR				44
+
+/* AUDIO */
+#define CLK_AUD_AFE				0
+#define CLK_AUD_LRCK_DETECT			1
+#define CLK_AUD_I2S				2
+#define CLK_AUD_APLL_TUNER			3
+#define CLK_AUD_HDMI				4
+#define CLK_AUD_SPDF				5
+#define CLK_AUD_SPDF2				6
+#define CLK_AUD_APLL				7
+#define CLK_AUD_TML				8
+#define CLK_AUD_AHB_IDLE_EXT			9
+#define CLK_AUD_AHB_IDLE_INT			10
+
+#define CLK_AUD_I2SIN1				11
+#define CLK_AUD_I2SIN2				12
+#define CLK_AUD_I2SIN3				13
+#define CLK_AUD_I2SIN4				14
+#define CLK_AUD_I2SIN5				15
+#define CLK_AUD_I2SIN6				16
+#define CLK_AUD_I2SO1				17
+#define CLK_AUD_I2SO2				18
+#define CLK_AUD_I2SO3				19
+#define CLK_AUD_I2SO4				20
+#define CLK_AUD_I2SO5				21
+#define CLK_AUD_I2SO6				22
+#define CLK_AUD_ASRCI1				23
+#define CLK_AUD_ASRCI2				24
+#define CLK_AUD_ASRCO1				25
+#define CLK_AUD_ASRCO2				26
+#define CLK_AUD_ASRC11				27
+#define CLK_AUD_ASRC12				28
+#define CLK_AUD_HDMIRX				29
+#define CLK_AUD_INTDIR				30
+#define CLK_AUD_A1SYS				31
+#define CLK_AUD_A2SYS				32
+#define CLK_AUD_AFE_CONN			33
+#define CLK_AUD_AFE_PCMIF			34
+#define CLK_AUD_AFE_MRGIF			35
+
+#define CLK_AUD_MMIF_UL1			36
+#define CLK_AUD_MMIF_UL2			37
+#define CLK_AUD_MMIF_UL3			38
+#define CLK_AUD_MMIF_UL4			39
+#define CLK_AUD_MMIF_UL5			40
+#define CLK_AUD_MMIF_UL6			41
+#define CLK_AUD_MMIF_DL1			42
+#define CLK_AUD_MMIF_DL2			43
+#define CLK_AUD_MMIF_DL3			44
+#define CLK_AUD_MMIF_DL4			45
+#define CLK_AUD_MMIF_DL5			46
+#define CLK_AUD_MMIF_DL6			47
+#define CLK_AUD_MMIF_DLMCH			48
+#define CLK_AUD_MMIF_ARB1			49
+#define CLK_AUD_MMIF_AWB1			50
+#define CLK_AUD_MMIF_AWB2			51
+#define CLK_AUD_MMIF_DAI			52
+
+#define CLK_AUD_DMIC1				53
+#define CLK_AUD_DMIC2				54
+#define CLK_AUD_ASRCI3				55
+#define CLK_AUD_ASRCI4				56
+#define CLK_AUD_ASRCI5				57
+#define CLK_AUD_ASRCI6				58
+#define CLK_AUD_ASRCO3				59
+#define CLK_AUD_ASRCO4				60
+#define CLK_AUD_ASRCO5				61
+#define CLK_AUD_ASRCO6				62
+#define CLK_AUD_MEM_ASRC1			63
+#define CLK_AUD_MEM_ASRC2			64
+#define CLK_AUD_MEM_ASRC3			65
+#define CLK_AUD_MEM_ASRC4			66
+#define CLK_AUD_MEM_ASRC5			67
+#define CLK_AUD_DSD_ENC				68
+#define CLK_AUD_ASRC_BRG			60
+#define CLK_AUD_NR				70
+
+/* MMSYS */
+#define CLK_MM_SMI_COMMON			0
+#define CLK_MM_SMI_LARB0			1
+#define CLK_MM_CMDQ				2
+#define CLK_MM_MUTEX				3
+#define CLK_MM_DISP_COLOR			4
+#define CLK_MM_DISP_BLS				5
+#define CLK_MM_DISP_WDMA			6
+#define CLK_MM_DISP_RDMA			7
+#define CLK_MM_DISP_OVL				8
+#define CLK_MM_MDP_TDSHP			9
+#define CLK_MM_MDP_WROT				10
+#define CLK_MM_MDP_WDMA				11
+#define CLK_MM_MDP_RSZ1				12
+#define CLK_MM_MDP_RSZ0				13
+#define CLK_MM_MDP_RDMA				14
+#define CLK_MM_MDP_BLS_26M			15
+#define CLK_MM_CAM_MDP				16
+#define CLK_MM_FAKE_ENG				17
+#define CLK_MM_MUTEX_32K			18
+#define CLK_MM_DISP_RDMA1			19
+#define CLK_MM_DISP_UFOE			20
+
+#define CLK_MM_DSI_ENGINE			21
+#define CLK_MM_DSI_DIG				22
+#define CLK_MM_DPI_DIGL				23
+#define CLK_MM_DPI_ENGINE			24
+#define CLK_MM_DPI1_DIGL			25
+#define CLK_MM_DPI1_ENGINE			26
+#define CLK_MM_TVE_OUTPUT			27
+#define CLK_MM_TVE_INPUT			28
+#define CLK_MM_HDMI_PIXEL			29
+#define CLK_MM_HDMI_PLL				30
+#define CLK_MM_HDMI_AUDIO			31
+#define CLK_MM_HDMI_SPDIF			32
+#define CLK_MM_TVE_FMM				33
+#define CLK_MM_NR				34
+
+/* IMGSYS */
+#define CLK_IMG_SMI_COMM			0
+#define CLK_IMG_RESZ				1
+#define CLK_IMG_JPGDEC_SMI			2
+#define CLK_IMG_JPGDEC				3
+#define CLK_IMG_VENC_LT				4
+#define CLK_IMG_VENC				5
+#define CLK_IMG_NR				6
+
+/* VDEC */
+#define CLK_VDEC_CKGEN				0
+#define CLK_VDEC_LARB				1
+#define CLK_VDEC_NR				2
+
+/* HIFSYS */
+#define CLK_HIFSYS_USB0PHY			0
+#define CLK_HIFSYS_USB1PHY			1
+#define CLK_HIFSYS_PCIE0			2
+#define CLK_HIFSYS_PCIE1			3
+#define CLK_HIFSYS_PCIE2			4
+#define CLK_HIFSYS_NR				5
+
+/* ETHSYS */
+#define CLK_ETHSYS_HSDMA			0
+#define CLK_ETHSYS_ESW				1
+#define CLK_ETHSYS_GP2				2
+#define CLK_ETHSYS_GP1				3
+#define CLK_ETHSYS_PCM				4
+#define CLK_ETHSYS_GDMA				5
+#define CLK_ETHSYS_I2S				6
+#define CLK_ETHSYS_CRYPTO			7
+#define CLK_ETHSYS_NR				8
+
+/* G3DSYS */
+#define CLK_G3DSYS_CORE				0
+#define CLK_G3DSYS_NR				1
+
+#endif /* _DT_BINDINGS_CLK_MT2701_H */
diff --git a/include/dt-bindings/power/mt7623-power.h b/include/dt-bindings/power/mt7623-power.h
new file mode 100644
index 0000000..0e73bb4
--- /dev/null
+++ b/include/dt-bindings/power/mt7623-power.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ */
+
+#ifndef _DT_BINDINGS_MT7623_POWER_H
+#define _DT_BINDINGS_MT7623_POWER_H
+
+#define MT7623_POWER_DOMAIN_CONN	0
+#define MT7623_POWER_DOMAIN_DISP	1
+#define MT7623_POWER_DOMAIN_MFG		2
+#define MT7623_POWER_DOMAIN_VDEC	3
+#define MT7623_POWER_DOMAIN_ISP		4
+#define MT7623_POWER_DOMAIN_BDP		5
+#define MT7623_POWER_DOMAIN_ETH		6
+#define MT7623_POWER_DOMAIN_HIF		7
+#define MT7623_POWER_DOMAIN_IFR_MSC	8
+
+#endif /* _DT_BINDINGS_MT7623_POWER_H */
-- 
1.9.1

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

* [U-Boot] [PATCH v2 04/18] arm: MediaTek: add basic support for MT7629 boards
  2018-10-12  7:00 [U-Boot] [PATCH v2 00/18] Add U-Boot support for MediaTek SoCs - MT7623n & MT7629 Ryder Lee
                   ` (2 preceding siblings ...)
  2018-10-12  7:00 ` [U-Boot] [PATCH v2 03/18] arm: dts: MediaTek: add device tree for MT7623 Ryder Lee
@ 2018-10-12  7:00 ` Ryder Lee
  2018-10-25  3:29   ` Simon Glass
  2018-10-12  7:00 ` [U-Boot] [PATCH v2 05/18] arm: MediaTek: add basic support for MT7623 boards Ryder Lee
                   ` (13 subsequent siblings)
  17 siblings, 1 reply; 57+ messages in thread
From: Ryder Lee @ 2018-10-12  7:00 UTC (permalink / raw)
  To: u-boot

This adds a general board file based on MT7629 SoCs from MediaTek.

Apart from the generic parts (cpu) we add some low level init codes
and initialize the early clocks.

Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
---
 arch/arm/Kconfig                              |  14 +++
 arch/arm/Makefile                             |   1 +
 arch/arm/include/asm/arch-mediatek/misc.h     |  17 ++++
 arch/arm/mach-mediatek/Kconfig                |  24 +++++
 arch/arm/mach-mediatek/Makefile               |   6 ++
 arch/arm/mach-mediatek/cpu.c                  |  34 +++++++
 arch/arm/mach-mediatek/init.h                 |  11 +++
 arch/arm/mach-mediatek/mt7629/Makefile        |   4 +
 arch/arm/mach-mediatek/mt7629/init.c          | 131 ++++++++++++++++++++++++++
 arch/arm/mach-mediatek/mt7629/lowlevel_init.S |  50 ++++++++++
 arch/arm/mach-mediatek/spl.c                  |  43 +++++++++
 board/mediatek/mt7629/Kconfig                 |  17 ++++
 board/mediatek/mt7629/MAINTAINERS             |   7 ++
 board/mediatek/mt7629/Makefile                |   3 +
 board/mediatek/mt7629/mt7629_rfb.c            |  16 ++++
 configs/mt7629_rfb_defconfig                  |  73 ++++++++++++++
 include/configs/mt7629.h                      |  62 ++++++++++++
 17 files changed, 513 insertions(+)
 create mode 100644 arch/arm/include/asm/arch-mediatek/misc.h
 create mode 100644 arch/arm/mach-mediatek/Kconfig
 create mode 100644 arch/arm/mach-mediatek/Makefile
 create mode 100644 arch/arm/mach-mediatek/cpu.c
 create mode 100644 arch/arm/mach-mediatek/init.h
 create mode 100644 arch/arm/mach-mediatek/mt7629/Makefile
 create mode 100644 arch/arm/mach-mediatek/mt7629/init.c
 create mode 100644 arch/arm/mach-mediatek/mt7629/lowlevel_init.S
 create mode 100644 arch/arm/mach-mediatek/spl.c
 create mode 100644 board/mediatek/mt7629/Kconfig
 create mode 100644 board/mediatek/mt7629/MAINTAINERS
 create mode 100644 board/mediatek/mt7629/Makefile
 create mode 100644 board/mediatek/mt7629/mt7629_rfb.c
 create mode 100644 configs/mt7629_rfb_defconfig
 create mode 100644 include/configs/mt7629.h

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index ccf2a84..eac03f0 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -668,6 +668,18 @@ config ARCH_MESON
 	  targeted at media players and tablet computers. We currently
 	  support the S905 (GXBaby) 64-bit SoC.
 
+config ARCH_MEDIATEK
+	bool "MediaTek SoCs"
+	select DM
+	select OF_CONTROL
+	select SPL_DM if SPL
+	select SPL_LIBCOMMON_SUPPORT if SPL
+	select SPL_LIBGENERIC_SUPPORT if SPL
+	select SPL_OF_CONTROL if SPL
+	select SUPPORT_SPL
+	help
+	  Support for the MediaTek SoCs family.
+
 config ARCH_MX8M
 	bool "NXP i.MX8M platform"
 	select ARM64
@@ -1423,6 +1435,8 @@ source "arch/arm/mach-rmobile/Kconfig"
 
 source "arch/arm/mach-meson/Kconfig"
 
+source "arch/arm/mach-mediatek/Kconfig"
+
 source "arch/arm/mach-qemu/Kconfig"
 
 source "arch/arm/mach-rockchip/Kconfig"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 8f50560..ddb9618 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -62,6 +62,7 @@ machine-$(CONFIG_ARCH_K3)		+= k3
 machine-$(CONFIG_ARCH_KEYSTONE)		+= keystone
 # TODO: rename CONFIG_KIRKWOOD -> CONFIG_ARCH_KIRKWOOD
 machine-$(CONFIG_KIRKWOOD)		+= kirkwood
+machine-$(CONFIG_ARCH_MEDIATEK)		+= mediatek
 machine-$(CONFIG_ARCH_MESON)		+= meson
 machine-$(CONFIG_ARCH_MVEBU)		+= mvebu
 # TODO: rename CONFIG_TEGRA -> CONFIG_ARCH_TEGRA
diff --git a/arch/arm/include/asm/arch-mediatek/misc.h b/arch/arm/include/asm/arch-mediatek/misc.h
new file mode 100644
index 0000000..2530e78
--- /dev/null
+++ b/arch/arm/include/asm/arch-mediatek/misc.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ */
+
+#ifndef __MEDIATEK_MISC_H_
+#define __MEDIATEK_MISC_H_
+
+#define VER_BASE		0x08000000
+#define VER_SIZE		0x10
+
+#define APHW_CODE		0x00
+#define APHW_SUBCODE		0x04
+#define APHW_VER		0x08
+#define APSW_VER		0x0c
+
+#endif /* __MEDIATEK_MISC_H_ */
diff --git a/arch/arm/mach-mediatek/Kconfig b/arch/arm/mach-mediatek/Kconfig
new file mode 100644
index 0000000..a932e70
--- /dev/null
+++ b/arch/arm/mach-mediatek/Kconfig
@@ -0,0 +1,24 @@
+if ARCH_MEDIATEK
+
+config SYS_SOC
+	default "mediatek"
+
+config SYS_VENDOR
+	default "mediatek"
+
+choice
+	prompt "MediaTek board select"
+
+config TARGET_MT7629
+	bool "MediaTek MT7629 SoC"
+	select CPU_V7A
+	select SPL
+	select ARCH_MISC_INIT
+	help
+		Support MediaTek MT7629 SoC.
+
+endchoice
+
+source "board/mediatek/mt7629/Kconfig"
+
+endif
diff --git a/arch/arm/mach-mediatek/Makefile b/arch/arm/mach-mediatek/Makefile
new file mode 100644
index 0000000..852d330
--- /dev/null
+++ b/arch/arm/mach-mediatek/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier:	GPL-2.0
+
+obj-y	+= cpu.o
+obj-$(CONFIG_SPL_BUILD)	+= spl.o
+
+obj-$(CONFIG_TARGET_MT7629) += mt7629/
diff --git a/arch/arm/mach-mediatek/cpu.c b/arch/arm/mach-mediatek/cpu.c
new file mode 100644
index 0000000..2bfeab7
--- /dev/null
+++ b/arch/arm/mach-mediatek/cpu.c
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/uclass-internal.h>
+#include <wdt.h>
+
+int arch_misc_init(void)
+{
+	struct udevice *wdt;
+	int ret;
+
+	ret = uclass_get_device(UCLASS_WDT, 0, &wdt);
+	if (!ret)
+		wdt_stop(wdt);
+
+	return 0;
+}
+
+int arch_cpu_init(void)
+{
+	icache_enable();
+
+	return 0;
+}
+
+void enable_caches(void)
+{
+	/* Enable D-cache. I-cache is already enabled in start.S */
+	dcache_enable();
+}
diff --git a/arch/arm/mach-mediatek/init.h b/arch/arm/mach-mediatek/init.h
new file mode 100644
index 0000000..1d896fb
--- /dev/null
+++ b/arch/arm/mach-mediatek/init.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ */
+
+#ifndef __MEDIATEK_INIT_H_
+#define __MEDIATEK_INIT_H_
+
+extern int mtk_soc_early_init(void);
+
+#endif /* __MEDIATEK_INIT_H_ */
diff --git a/arch/arm/mach-mediatek/mt7629/Makefile b/arch/arm/mach-mediatek/mt7629/Makefile
new file mode 100644
index 0000000..007eb4a
--- /dev/null
+++ b/arch/arm/mach-mediatek/mt7629/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/mt7629/init.c b/arch/arm/mach-mediatek/mt7629/init.c
new file mode 100644
index 0000000..8f195b5
--- /dev/null
+++ b/arch/arm/mach-mediatek/mt7629/init.c
@@ -0,0 +1,131 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ * Author: Ryder Lee <ryder.lee@mediatek.com>
+ */
+
+#include <clk.h>
+#include <common.h>
+#include <dm.h>
+#include <dm/uclass.h>
+#include <fdtdec.h>
+#include <linux/io.h>
+#include <ram.h>
+#include <asm/arch/misc.h>
+#include <asm/sections.h>
+
+#include <dt-bindings/clock/mt7629-clk.h>
+
+#define L2_SHARE_CFG_MP0	0x7f0
+#define L2_SHARE_MODE_OFF	BIT(8)
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int mtk_pll_early_init(void)
+{
+	unsigned long pll_rates[] = {
+		[CLK_APMIXED_ARMPLL] = 1250000000,
+		[CLK_APMIXED_MAINPLL] = 1120000000,
+		[CLK_APMIXED_UNIV2PLL] = 1200000000,
+		[CLK_APMIXED_ETH1PLL] = 500000000,
+		[CLK_APMIXED_ETH2PLL] = 700000000,
+		[CLK_APMIXED_SGMIPLL] = 650000000,
+	};
+	struct udevice *dev;
+	int ret, i;
+
+	ret = uclass_get_device_by_driver(UCLASS_CLK,
+			DM_GET_DRIVER(mtk_clk_apmixedsys), &dev);
+	if (ret)
+		return ret;
+
+	/* configure default rate then enable apmixedsys */
+	for (i = 0; i < ARRAY_SIZE(pll_rates); i++) {
+		struct clk clk = { .id = i, .dev = dev };
+
+		ret = clk_set_rate(&clk, pll_rates[i]);
+		if (ret)
+			return ret;
+
+		ret = clk_enable(&clk);
+		if (ret)
+			return ret;
+	}
+
+	/* setup mcu bus */
+	ret = uclass_get_device_by_driver(UCLASS_SYSCON,
+			DM_GET_DRIVER(mtk_mcucfg), &dev);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+int mtk_soc_early_init(void)
+{
+	struct udevice *dev;
+	int ret;
+
+	/* initialize early clocks */
+	ret = mtk_pll_early_init();
+	if (ret)
+		return ret;
+
+	ret = uclass_get_device(UCLASS_RAM, 0, &dev);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+int mach_cpu_init(void)
+{
+	void __iomem *base;
+	int node;
+
+	node = fdt_node_offset_by_compatible(gd->fdt_blob, -1,
+			"mediatek,mt7629-mcucfg");
+	base = (void __iomem *)fdtdec_get_addr(gd->fdt_blob, node, "reg");
+	if (!base)
+		return -ENOENT;
+
+	/* disable L2C shared mode */
+	writel(L2_SHARE_MODE_OFF, base + L2_SHARE_CFG_MP0);
+
+	return 0;
+}
+
+int dram_init(void)
+{
+	struct ram_info ram;
+	struct udevice *dev;
+	int ret;
+
+	ret = uclass_get_device(UCLASS_RAM, 0, &dev);
+	if (ret)
+		return ret;
+
+	ret = ram_get_info(dev, &ram);
+	if (ret)
+		return ret;
+
+	debug("RAM init base=%lx, size=%x\n", ram.base, ram.size);
+
+	gd->ram_size = ram.size;
+
+	return 0;
+}
+
+int print_cpuinfo(void)
+{
+	void __iomem *chipid;
+	u32 hwcode, swver;
+
+	chipid = ioremap(VER_BASE, VER_SIZE);
+	hwcode = readl(chipid + APHW_CODE);
+	swver = readl(chipid + APSW_VER);
+
+	printf("CPU:   MediaTek MT%04x E%d\n", hwcode, (swver & 0xf) + 1);
+
+	return 0;
+}
diff --git a/arch/arm/mach-mediatek/mt7629/lowlevel_init.S b/arch/arm/mach-mediatek/mt7629/lowlevel_init.S
new file mode 100644
index 0000000..90dd4ea
--- /dev/null
+++ b/arch/arm/mach-mediatek/mt7629/lowlevel_init.S
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ */
+
+#include <linux/linkage.h>
+
+ENTRY(lowlevel_init)
+
+#ifndef CONFIG_SPL_BUILD
+	/* Return to U-Boot via saved link register */
+	mov	pc, lr
+#else
+	/*
+	 * Arch timer :
+	 * set CNTFRQ = 20Mhz, set CNTVOFF = 0
+	 */
+	movw	r0, #0x2d00
+	movt	r0, #0x131
+	mcr	p15, 0, r0, c14, c0, 0
+
+	/* enable SMP bit */
+	mrc	p15, 0, r0, c1, c0, 1
+	orr	r0, r0, #0x40
+	mcr	p15, 0, r0, c1, c0, 1
+
+	/* if MP core, handle secondary cores */
+	mrc	p15, 0, r0, c0, c0, 5
+	ands	r1, r0, #0x40000000
+	bne	go			@ Go if UP
+	ands	r0, r0, #0x0f
+	beq	go			@ Go if core0 on primary core tile
+	b	secondary
+
+go:
+	/* master CPU */
+	mov	pc, lr
+
+secondary:
+	/* read slave CPU number into r0 firstly */
+	mrc	p15, 0, r0, c0, c0, 5
+	and	r0, r0, #0x0f
+
+loop:
+	dsb
+	isb
+	wfi				@Zzz...
+	b	loop
+#endif
+ENDPROC(lowlevel_init)
diff --git a/arch/arm/mach-mediatek/spl.c b/arch/arm/mach-mediatek/spl.c
new file mode 100644
index 0000000..9b3590f
--- /dev/null
+++ b/arch/arm/mach-mediatek/spl.c
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ * Author: Ryder Lee <ryder.lee@mediatek.com>
+ */
+
+#include <clk.h>
+#include <common.h>
+#include <spl.h>
+
+#include "init.h"
+
+void board_init_f(ulong dummy)
+{
+	int ret;
+
+	ret = spl_early_init();
+	if (ret)
+		hang();
+
+	/* enable console uart printing */
+	preloader_console_init();
+
+	/* soc early initialization */
+	ret = mtk_soc_early_init();
+	if (ret)
+		hang();
+}
+
+u32 spl_boot_device(void)
+{
+#if defined(CONFIG_SPL_SPI_SUPPORT)
+	return BOOT_DEVICE_SPI;
+#elif defined(CONFIG_SPL_MMC_SUPPORT)
+	return BOOT_DEVICE_MMC1;
+#elif defined(CONFIG_SPL_NAND_SUPPORT)
+	return BOOT_DEVICE_NAND;
+#elif defined(CONFIG_SPL_NOR_SUPPORT)
+	return BOOT_DEVICE_NOR;
+#else
+	return BOOT_DEVICE_NONE;
+#endif
+}
diff --git a/board/mediatek/mt7629/Kconfig b/board/mediatek/mt7629/Kconfig
new file mode 100644
index 0000000..6055164
--- /dev/null
+++ b/board/mediatek/mt7629/Kconfig
@@ -0,0 +1,17 @@
+if TARGET_MT7629
+
+config SYS_BOARD
+	default "mt7629"
+
+config SYS_CONFIG_NAME
+	default "mt7629"
+
+config MTK_SPL_PAD_SIZE
+	hex
+	default 0x10000
+
+config MTK_BROM_HEADER_INFO
+	string
+	default "media=nor"
+
+endif
diff --git a/board/mediatek/mt7629/MAINTAINERS b/board/mediatek/mt7629/MAINTAINERS
new file mode 100644
index 0000000..424f115
--- /dev/null
+++ b/board/mediatek/mt7629/MAINTAINERS
@@ -0,0 +1,7 @@
+MT7629
+M:	Ryder Lee <ryder.lee@mediatek.com>
+M:	Weijie Gao <weijie.gao@mediatek.com>
+S:	Maintained
+F:	board/mediatek/mt7629
+F:	include/configs/mt7629.h
+F:	configs/mt7629_rfb_defconfig
diff --git a/board/mediatek/mt7629/Makefile b/board/mediatek/mt7629/Makefile
new file mode 100644
index 0000000..83ccbba
--- /dev/null
+++ b/board/mediatek/mt7629/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier:	GPL-2.0
+
+obj-y += mt7629_rfb.o
diff --git a/board/mediatek/mt7629/mt7629_rfb.c b/board/mediatek/mt7629/mt7629_rfb.c
new file mode 100644
index 0000000..08468b5
--- /dev/null
+++ b/board/mediatek/mt7629/mt7629_rfb.c
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ */
+
+#include <common.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int board_init(void)
+{
+	/* address of boot parameters */
+	gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
+
+	return 0;
+}
diff --git a/configs/mt7629_rfb_defconfig b/configs/mt7629_rfb_defconfig
new file mode 100644
index 0000000..2ae9c8f
--- /dev/null
+++ b/configs/mt7629_rfb_defconfig
@@ -0,0 +1,73 @@
+CONFIG_ARM=y
+CONFIG_SYS_THUMB_BUILD=y
+CONFIG_ARCH_MEDIATEK=y
+CONFIG_SYS_TEXT_BASE=0x41e00000
+CONFIG_SYS_MALLOC_F_LEN=0x4000
+CONFIG_TARGET_MT7629=y
+CONFIG_SPL_SERIAL_SUPPORT=y
+CONFIG_SPL_DRIVERS_MISC_SUPPORT=y
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_BOOTDELAY=3
+CONFIG_SYS_CONSOLE_IS_IN_ENV=y
+CONFIG_DEFAULT_FDT_FILE="mt7629-rfb"
+# CONFIG_DISPLAY_BOARDINFO is not set
+CONFIG_SPL_SYS_MALLOC_SIMPLE=y
+CONFIG_SPL_NOR_SUPPORT=y
+CONFIG_SPL_WATCHDOG_SUPPORT=y
+CONFIG_HUSH_PARSER=y
+CONFIG_SYS_PROMPT="U-Boot> "
+CONFIG_CMD_BOOTMENU=y
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_XIMG is not set
+# CONFIG_CMD_FLASH is not set
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SF_TEST=y
+# CONFIG_CMD_SETEXPR is not set
+# CONFIG_CMD_NFS is not set
+CONFIG_CMD_PING=y
+# CONFIG_PARTITIONS is not set
+CONFIG_OF_EMBED=y
+CONFIG_DEFAULT_DEVICE_TREE="mt7629-rfb"
+CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-parents"
+CONFIG_SPL_DM_SEQ_ALIAS=y
+CONFIG_REGMAP=y
+CONFIG_SPL_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_SPL_SYSCON=y
+CONFIG_CLK=y
+CONFIG_SPL_CLK=y
+CONFIG_DM_GPIO=y
+# CONFIG_MMC is not set
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_BAR=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_PINCTRL=y
+CONFIG_PINCONF=y
+CONFIG_PINCTRL_MT7629=y
+CONFIG_POWER_DOMAIN=y
+CONFIG_MTK_POWER_DOMAIN=y
+CONFIG_RAM=y
+CONFIG_SPL_RAM=y
+CONFIG_DM_SERIAL=y
+CONFIG_SYS_NS16550=y
+CONFIG_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_MTK_QSPI=y
+CONFIG_SYSRESET=y
+CONFIG_SYSRESET_WATCHDOG=y
+CONFIG_TIMER=y
+CONFIG_SPL_TIMER=y
+CONFIG_MTK_TIMER=y
+CONFIG_WDT_MTK=y
+CONFIG_LZMA=y
+# CONFIG_EFI_LOADER is not set
diff --git a/include/configs/mt7629.h b/include/configs/mt7629.h
new file mode 100644
index 0000000..9b51e90
--- /dev/null
+++ b/include/configs/mt7629.h
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Configuration for MediaTek MT7629 SoC
+ *
+ * Copyright (C) 2018 MediaTek Inc.
+ * Author: Ryder Lee <ryder.lee@mediatek.com>
+ */
+
+#ifndef __MT7629_H
+#define __MT7629_H
+
+#include <linux/sizes.h>
+
+/* Miscellaneous configurable options */
+#define CONFIG_SETUP_MEMORY_TAGS
+#define CONFIG_INITRD_TAG
+#define CONFIG_CMDLINE_TAG
+
+#define CONFIG_SYS_MAXARGS		8
+#define CONFIG_SYS_BOOTM_LEN		SZ_64M
+#define CONFIG_SYS_CBSIZE		SZ_1K
+#define CONFIG_SYS_PBSIZE		(CONFIG_SYS_CBSIZE +	\
+					sizeof(CONFIG_SYS_PROMPT) + 16)
+
+/* Size of malloc() pool */
+#define CONFIG_SYS_MALLOC_LEN		SZ_4M
+
+/* Environment */
+#define CONFIG_ENV_SIZE			SZ_4K
+/* Allow to overwrite serial and ethaddr */
+#define CONFIG_ENV_OVERWRITE
+
+/* Defines for SPL */
+#define CONFIG_SPL_STACK		0x106000
+#define CONFIG_SPL_TEXT_BASE		0x201000
+#define CONFIG_SPL_MAX_SIZE		SZ_64K
+#define CONFIG_SPL_MAX_FOOTPRINT	SZ_64K
+#define CONFIG_SPL_PAD_TO		0x10000
+
+#define CONFIG_SPI_ADDR			0x30000000
+#define CONFIG_SYS_SPI_U_BOOT_OFFS	CONFIG_SPL_PAD_TO
+#define CONFIG_SYS_UBOOT_BASE		(CONFIG_SPI_ADDR + CONFIG_SPL_PAD_TO)
+
+/* SPL -> Uboot */
+#define CONFIG_SYS_UBOOT_START		CONFIG_SYS_TEXT_BASE
+#define CONFIG_SYS_INIT_SP_ADDR		(CONFIG_SYS_TEXT_BASE + SZ_2M - \
+					 GENERATED_GBL_DATA_SIZE)
+
+/* UBoot -> Kernel */
+#define CONFIG_SYS_SPL_ARGS_ADDR	0x40000000
+#define CONFIG_LOADADDR			0x42007f1c
+#define CONFIG_SYS_LOAD_ADDR		CONFIG_LOADADDR
+
+/* Serial device */
+#define CONFIG_SYS_NS16550_CLK		40000000
+#define CONFIG_SYS_NS16550_MEM32
+#define CONFIG_BAUDRATE			115200
+
+/* DRAM */
+#define CONFIG_SYS_SDRAM_BASE		0x40000000
+
+#endif
-- 
1.9.1

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

* [U-Boot] [PATCH v2 05/18] arm: MediaTek: add basic support for MT7623 boards
  2018-10-12  7:00 [U-Boot] [PATCH v2 00/18] Add U-Boot support for MediaTek SoCs - MT7623n & MT7629 Ryder Lee
                   ` (3 preceding siblings ...)
  2018-10-12  7:00 ` [U-Boot] [PATCH v2 04/18] arm: MediaTek: add basic support for MT7629 boards Ryder Lee
@ 2018-10-12  7:00 ` Ryder Lee
  2018-10-25  3:29   ` Simon Glass
  2018-10-12  7:00 ` [U-Boot] [PATCH v2 06/18] clk: MediaTek: add clock driver for MT7629 SoC Ryder Lee
                   ` (12 subsequent siblings)
  17 siblings, 1 reply; 57+ messages in thread
From: Ryder Lee @ 2018-10-12  7:00 UTC (permalink / raw)
  To: u-boot

From: Weijie Gao <weijie.gao@mediatek.com>

This adds a general board file based on MT7623 SoCs from MediaTek.

As this u-boot is loaded by preloader, there is no low level
initializtion codes.

Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
Tested-by: Matthias Brugger <matthias.bgg@gmail.com>
---
 arch/arm/mach-mediatek/Kconfig                |  8 +++
 arch/arm/mach-mediatek/Makefile               |  1 +
 arch/arm/mach-mediatek/mt7623/Makefile        |  4 ++
 arch/arm/mach-mediatek/mt7623/init.c          | 54 +++++++++++++++
 arch/arm/mach-mediatek/mt7623/lowlevel_init.S | 22 ++++++
 arch/arm/mach-mediatek/mt7623/preloader.h     | 99 +++++++++++++++++++++++++++
 board/mediatek/mt7623/Kconfig                 | 13 ++++
 board/mediatek/mt7623/MAINTAINERS             |  7 ++
 board/mediatek/mt7623/Makefile                |  3 +
 board/mediatek/mt7623/mt7623_rfb.c            | 16 +++++
 configs/mt7623n_bpir2_defconfig               | 53 ++++++++++++++
 include/configs/mt7623.h                      | 61 +++++++++++++++++
 12 files changed, 341 insertions(+)
 create mode 100644 arch/arm/mach-mediatek/mt7623/Makefile
 create mode 100644 arch/arm/mach-mediatek/mt7623/init.c
 create mode 100644 arch/arm/mach-mediatek/mt7623/lowlevel_init.S
 create mode 100644 arch/arm/mach-mediatek/mt7623/preloader.h
 create mode 100644 board/mediatek/mt7623/Kconfig
 create mode 100644 board/mediatek/mt7623/MAINTAINERS
 create mode 100644 board/mediatek/mt7623/Makefile
 create mode 100644 board/mediatek/mt7623/mt7623_rfb.c
 create mode 100644 configs/mt7623n_bpir2_defconfig
 create mode 100644 include/configs/mt7623.h

diff --git a/arch/arm/mach-mediatek/Kconfig b/arch/arm/mach-mediatek/Kconfig
index a932e70..b39bc44 100644
--- a/arch/arm/mach-mediatek/Kconfig
+++ b/arch/arm/mach-mediatek/Kconfig
@@ -9,6 +9,13 @@ config SYS_VENDOR
 choice
 	prompt "MediaTek board select"
 
+config TARGET_MT7623
+	bool "MediaTek MT7623 SoC"
+	select CPU_V7A
+	select ARCH_MISC_INIT
+	help
+		Support MediaTek MT7623 SoC.
+
 config TARGET_MT7629
 	bool "MediaTek MT7629 SoC"
 	select CPU_V7A
@@ -19,6 +26,7 @@ config TARGET_MT7629
 
 endchoice
 
+source "board/mediatek/mt7623/Kconfig"
 source "board/mediatek/mt7629/Kconfig"
 
 endif
diff --git a/arch/arm/mach-mediatek/Makefile b/arch/arm/mach-mediatek/Makefile
index 852d330..b5d3a37 100644
--- a/arch/arm/mach-mediatek/Makefile
+++ b/arch/arm/mach-mediatek/Makefile
@@ -3,4 +3,5 @@
 obj-y	+= cpu.o
 obj-$(CONFIG_SPL_BUILD)	+= spl.o
 
+obj-$(CONFIG_TARGET_MT7623) += mt7623/
 obj-$(CONFIG_TARGET_MT7629) += mt7629/
diff --git a/arch/arm/mach-mediatek/mt7623/Makefile b/arch/arm/mach-mediatek/mt7623/Makefile
new file mode 100644
index 0000000..007eb4a
--- /dev/null
+++ b/arch/arm/mach-mediatek/mt7623/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/mt7623/init.c b/arch/arm/mach-mediatek/mt7623/init.c
new file mode 100644
index 0000000..0ee8c66
--- /dev/null
+++ b/arch/arm/mach-mediatek/mt7623/init.c
@@ -0,0 +1,54 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ */
+
+#include <common.h>
+#include <linux/io.h>
+#include <linux/sizes.h>
+#include <asm/arch/misc.h>
+
+#include "preloader.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct boot_argument *preloader_param;
+
+int mtk_soc_early_init(void)
+{
+	return 0;
+}
+
+int dram_init(void)
+{
+	u32 i;
+
+	if (((size_t)preloader_param >= CONFIG_SYS_SDRAM_BASE) &&
+	    ((size_t)preloader_param % sizeof(size_t) == 0) &&
+	    preloader_param->magic == BOOT_ARGUMENT_MAGIC &&
+	    preloader_param->dram_rank_num <=
+	    ARRAY_SIZE(preloader_param->dram_rank_size)) {
+		gd->ram_size = 0;
+
+		for (i = 0; i < preloader_param->dram_rank_num; i++)
+			gd->ram_size += preloader_param->dram_rank_size[i];
+	} else {
+		gd->ram_size = get_ram_size((long *)CONFIG_SYS_SDRAM_BASE,
+					    SZ_2G);
+	}
+
+	return 0;
+}
+
+int print_cpuinfo(void)
+{
+	void __iomem *chipid;
+	u32 swver;
+
+	chipid = ioremap(VER_BASE, VER_SIZE);
+	swver = readl(chipid + APSW_VER);
+
+	printf("CPU:   MediaTek MT7623 E%d\n", (swver & 0xf) + 1);
+
+	return 0;
+}
diff --git a/arch/arm/mach-mediatek/mt7623/lowlevel_init.S b/arch/arm/mach-mediatek/mt7623/lowlevel_init.S
new file mode 100644
index 0000000..afb9476
--- /dev/null
+++ b/arch/arm/mach-mediatek/mt7623/lowlevel_init.S
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ */
+
+#include <linux/linkage.h>
+
+.extern	preloader_param
+
+ENTRY(save_boot_params)
+	ldr	r6, =preloader_param
+	str	r4, [r6]
+	b	save_boot_params_ret
+ENDPROC(save_boot_params)
+
+ENTRY(lowlevel_init)
+	/* enable SMP bit */
+	mrc	p15, 0, r0, c1, c0, 1
+	orr	r0, r0, #0x40
+	mcr	p15, 0, r0, c1, c0, 1
+	mov	pc, lr
+ENDPROC(lowlevel_init)
diff --git a/arch/arm/mach-mediatek/mt7623/preloader.h b/arch/arm/mach-mediatek/mt7623/preloader.h
new file mode 100644
index 0000000..2d2c71a
--- /dev/null
+++ b/arch/arm/mach-mediatek/mt7623/preloader.h
@@ -0,0 +1,99 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ */
+
+#ifndef __PRELOADER_H_
+#define __PRELOADER_H_
+
+enum forbidden_mode {
+	F_FACTORY_MODE = 0x0001
+};
+
+union lk_hdr {
+	struct {
+		u32 magic;
+		u32 size;
+		char name[32];
+		u32 loadaddr;
+	};
+
+	u8 data[512];
+};
+
+struct sec_limit {
+	unsigned int magic_num;
+	enum forbidden_mode forbid_mode;
+};
+
+enum bootmode {
+	NORMAL_BOOT = 0,
+	META_BOOT = 1,
+	RECOVERY_BOOT = 2,
+	SW_REBOOT = 3,
+	FACTORY_BOOT = 4,
+	ADVMETA_BOOT = 5,
+	ATE_FACTORY_BOOT = 6,
+	ALARM_BOOT = 7,
+
+	KERNEL_POWER_OFF_CHARGING_BOOT = 8,
+	LOW_POWER_OFF_CHARGING_BOOT = 9,
+
+	FAST_BOOT = 99,
+	DOWNLOAD_BOOT = 100,
+	UNKNOWN_BOOT
+};
+
+enum boot_reason {
+	BR_POWER_KEY = 0,
+	BR_USB,
+	BR_RTC,
+	BR_WDT,
+	BR_WDT_BY_PASS_PWK,
+	BR_TOOL_BY_PASS_PWK,
+	BR_2SEC_REBOOT,
+	BR_UNKNOWN
+};
+
+enum meta_com_type {
+	META_UNKNOWN_COM = 0,
+	META_UART_COM,
+	META_USB_COM
+};
+
+struct da_info_t {
+	u32 addr;
+	u32 arg1;
+	u32 arg2;
+	u32 len;
+	u32 sig_len;
+};
+
+struct boot_argument {
+	u32 magic;
+	enum bootmode boot_mode;
+	u32 e_flag;
+	u32 log_port;
+	u32 log_baudrate;
+	u8 log_enable;
+	u8 part_num;
+	u8 reserved[2];
+	u32 dram_rank_num;
+	u32 dram_rank_size[4];
+	u32 boot_reason;
+	enum meta_com_type meta_com_type;
+	u32 meta_com_id;
+	u32 boot_time;
+	struct da_info_t da_info;
+	struct sec_limit sec_limit;
+	union lk_hdr *part_info;
+	u8 md_type[4];
+	u32 ddr_reserve_enable;
+	u32 ddr_reserve_success;
+	u32 chip_ver;
+	char pl_version[8];
+};
+
+#define BOOT_ARGUMENT_MAGIC	0x504c504c
+
+#endif /* __PRELOADER_H_ */
diff --git a/board/mediatek/mt7623/Kconfig b/board/mediatek/mt7623/Kconfig
new file mode 100644
index 0000000..a8c670e
--- /dev/null
+++ b/board/mediatek/mt7623/Kconfig
@@ -0,0 +1,13 @@
+if TARGET_MT7623
+
+config SYS_BOARD
+	default "mt7623"
+
+config SYS_CONFIG_NAME
+	default "mt7623"
+
+config MTK_BROM_HEADER_INFO
+	string
+	default "lk=1"
+
+endif
diff --git a/board/mediatek/mt7623/MAINTAINERS b/board/mediatek/mt7623/MAINTAINERS
new file mode 100644
index 0000000..eeb0375
--- /dev/null
+++ b/board/mediatek/mt7623/MAINTAINERS
@@ -0,0 +1,7 @@
+MT7623
+M:	Ryder Lee <ryder.lee@mediatek.com>
+M:	Weijie Gao <weijie.gao@mediatek.com>
+S:	Maintained
+F:	board/mediatek/mt7623
+F:	include/configs/mt7623.h
+F:	configs/mt7623n_bpir2_defconfig
diff --git a/board/mediatek/mt7623/Makefile b/board/mediatek/mt7623/Makefile
new file mode 100644
index 0000000..2b42071
--- /dev/null
+++ b/board/mediatek/mt7623/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier:	GPL-2.0
+
+obj-y += mt7623_rfb.o
diff --git a/board/mediatek/mt7623/mt7623_rfb.c b/board/mediatek/mt7623/mt7623_rfb.c
new file mode 100644
index 0000000..08468b5
--- /dev/null
+++ b/board/mediatek/mt7623/mt7623_rfb.c
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ */
+
+#include <common.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int board_init(void)
+{
+	/* address of boot parameters */
+	gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
+
+	return 0;
+}
diff --git a/configs/mt7623n_bpir2_defconfig b/configs/mt7623n_bpir2_defconfig
new file mode 100644
index 0000000..a896d6a
--- /dev/null
+++ b/configs/mt7623n_bpir2_defconfig
@@ -0,0 +1,53 @@
+CONFIG_ARM=y
+CONFIG_SYS_THUMB_BUILD=y
+CONFIG_ARCH_MEDIATEK=y
+CONFIG_SYS_TEXT_BASE=0x81e00000
+CONFIG_SYS_MALLOC_F_LEN=0x4000
+CONFIG_TARGET_MT7623=y
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_BOOTDELAY=3
+CONFIG_SYS_CONSOLE_IS_IN_ENV=y
+CONFIG_DEFAULT_FDT_FILE="mt7623n-bananapi-bpi-r2"
+# CONFIG_DISPLAY_BOARDINFO is not set
+CONFIG_HUSH_PARSER=y
+CONFIG_SYS_PROMPT="U-Boot> "
+CONFIG_CMD_BOOTMENU=y
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_XIMG is not set
+# CONFIG_CMD_FLASH is not set
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_GPT=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_PART=y
+CONFIG_CMD_READ=y
+# CONFIG_CMD_SETEXPR is not set
+# CONFIG_CMD_NFS is not set
+CONFIG_CMD_PING=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_OF_EMBED=y
+CONFIG_DEFAULT_DEVICE_TREE="mt7623n-bananapi-bpi-r2"
+CONFIG_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_CLK=y
+CONFIG_DM_GPIO=y
+CONFIG_DM_MMC=y
+# CONFIG_MMC_QUIRKS is not set
+CONFIG_MMC_HS400_SUPPORT=y
+CONFIG_MMC_MTK=y
+CONFIG_PINCTRL=y
+CONFIG_PINCONF=y
+CONFIG_PINCTRL_MT7623=y
+CONFIG_POWER_DOMAIN=y
+CONFIG_MTK_POWER_DOMAIN=y
+CONFIG_DM_SERIAL=y
+CONFIG_SYS_NS16550=y
+CONFIG_SYSRESET=y
+CONFIG_SYSRESET_WATCHDOG=y
+CONFIG_TIMER=y
+CONFIG_MTK_TIMER=y
+CONFIG_WDT_MTK=y
+CONFIG_LZMA=y
+# CONFIG_EFI_LOADER is not set
diff --git a/include/configs/mt7623.h b/include/configs/mt7623.h
new file mode 100644
index 0000000..e6f8d93
--- /dev/null
+++ b/include/configs/mt7623.h
@@ -0,0 +1,61 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Configuration for MediaTek MT7623 SoC
+ *
+ * Copyright (C) 2018 MediaTek Inc.
+ * Author: Weijie Gao <weijie.gao@mediatek.com>
+ */
+
+#ifndef __MT7623_H
+#define __MT7623_H
+
+#include <linux/sizes.h>
+
+/* Miscellaneous configurable options */
+#define CONFIG_SETUP_MEMORY_TAGS
+#define CONFIG_INITRD_TAG
+#define CONFIG_CMDLINE_TAG
+
+#define CONFIG_SYS_MAXARGS		8
+#define CONFIG_SYS_BOOTM_LEN		SZ_64M
+#define CONFIG_SYS_CBSIZE		SZ_1K
+#define CONFIG_SYS_PBSIZE		(CONFIG_SYS_CBSIZE +	\
+					sizeof(CONFIG_SYS_PROMPT) + 16)
+
+/* Size of malloc() pool */
+#define CONFIG_SYS_MALLOC_LEN		SZ_4M
+
+/* Environment */
+#define CONFIG_ENV_SIZE			SZ_4K
+/* Allow to overwrite serial and ethaddr */
+#define CONFIG_ENV_OVERWRITE
+
+/* Preloader -> Uboot */
+#define CONFIG_SYS_UBOOT_START		CONFIG_SYS_TEXT_BASE
+#define CONFIG_SYS_INIT_SP_ADDR		(CONFIG_SYS_TEXT_BASE + SZ_2M - \
+					 GENERATED_GBL_DATA_SIZE)
+
+/* UBoot -> Kernel */
+#define CONFIG_LOADADDR			0x84000000
+#define CONFIG_SYS_LOAD_ADDR		CONFIG_LOADADDR
+
+/* Serial device */
+#define CONFIG_SYS_NS16550_CLK		26000000
+#define CONFIG_SYS_NS16550_MEM32
+#define CONFIG_BAUDRATE			115200
+
+/* MMC */
+#define MMC_SUPPORTS_TUNING
+#define CONFIG_SUPPORT_EMMC_BOOT
+
+/* DRAM */
+#define CONFIG_SYS_SDRAM_BASE		0x80000000
+
+/* This is neede for kernel booting */
+#define FDT_HIGH			"fdt_high=0xac000000\0"
+
+/* Extra environment variables */
+#define CONFIG_EXTRA_ENV_SETTINGS	\
+	FDT_HIGH
+
+#endif
-- 
1.9.1

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

* [U-Boot] [PATCH v2 06/18] clk: MediaTek: add clock driver for MT7629 SoC.
  2018-10-12  7:00 [U-Boot] [PATCH v2 00/18] Add U-Boot support for MediaTek SoCs - MT7623n & MT7629 Ryder Lee
                   ` (4 preceding siblings ...)
  2018-10-12  7:00 ` [U-Boot] [PATCH v2 05/18] arm: MediaTek: add basic support for MT7623 boards Ryder Lee
@ 2018-10-12  7:00 ` Ryder Lee
  2018-10-25  3:29   ` Simon Glass
  2018-10-12  7:00 ` [U-Boot] [PATCH v2 07/18] clk: MediaTek: add clock driver for MT7623 SoC Ryder Lee
                   ` (11 subsequent siblings)
  17 siblings, 1 reply; 57+ messages in thread
From: Ryder Lee @ 2018-10-12  7:00 UTC (permalink / raw)
  To: u-boot

This patch adds clock modules for MediaTek SoCs:
- Shared part: a common driver which contains the general operations
for plls, muxes, dividers and gates so that we can reuse it in future.

- Specific SoC part: the group of structures used to hold the hardware
configuration for each SoC.

We take MT7629 as an example to demonstrate how to implement driver if
any other MediaTek chips would like to use it.

Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
---
 drivers/clk/Makefile              |   1 +
 drivers/clk/mediatek/Makefile     |   6 +
 drivers/clk/mediatek/clk-mt7629.c | 709 ++++++++++++++++++++++++++++++++++++++
 drivers/clk/mediatek/clk-mtk.c    | 492 ++++++++++++++++++++++++++
 drivers/clk/mediatek/clk-mtk.h    | 153 ++++++++
 5 files changed, 1361 insertions(+)
 create mode 100644 drivers/clk/mediatek/Makefile
 create mode 100644 drivers/clk/mediatek/clk-mt7629.c
 create mode 100644 drivers/clk/mediatek/clk-mtk.c
 create mode 100644 drivers/clk/mediatek/clk-mtk.h

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 8bc9f52..3641991 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_$(SPL_TPL_)CLK) += clk-uclass.o clk_fixed_rate.o
 obj-y += tegra/
 obj-$(CONFIG_ARCH_ASPEED) += aspeed/
 obj-$(CONFIG_ARCH_MESON) += clk_meson.o
+obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/
 obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
 obj-$(CONFIG_ARCH_SOCFPGA) += altera/
 obj-$(CONFIG_CLK_AT91) += at91/
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
new file mode 100644
index 0000000..297f99d
--- /dev/null
+++ b/drivers/clk/mediatek/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+# Core
+obj-$(CONFIG_ARCH_MEDIATEK) += clk-mtk.o
+
+# SoC Drivers
+obj-$(CONFIG_TARGET_MT7629) += clk-mt7629.o
diff --git a/drivers/clk/mediatek/clk-mt7629.c b/drivers/clk/mediatek/clk-mt7629.c
new file mode 100644
index 0000000..46e9fad
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt7629.c
@@ -0,0 +1,709 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MediaTek clock driver for MT7629 SoC
+ *
+ * Copyright (C) 2018 MediaTek Inc.
+ * Author: Ryder Lee <ryder.lee@mediatek.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/io.h>
+#include <dt-bindings/clock/mt7629-clk.h>
+
+#include "clk-mtk.h"
+
+#define MT7629_CLKSQ_STB_CON0		0x20
+#define MT7629_PLL_ISO_CON0		0x2c
+#define MT7629_PLL_FMAX			(2500UL * MHZ)
+#define MT7629_CON0_RST_BAR		BIT(24)
+
+#define MCU_AXI_DIV			0x640
+#define AXI_DIV_MSK			GENMASK(4, 0)
+#define AXI_DIV_SEL(x)			(x)
+
+#define MCU_BUS_MUX			0x7c0
+#define MCU_BUS_MSK			GENMASK(10, 9)
+#define MCU_BUS_SEL(x)			((x) << 9)
+
+/* apmixedsys */
+#define PLL(_id, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg,	\
+	    _pd_shift, _pcw_reg, _pcw_shift) {				\
+		.id = _id,						\
+		.reg = _reg,						\
+		.pwr_reg = _pwr_reg,					\
+		.en_mask = _en_mask,					\
+		.rst_bar_mask = MT7629_CON0_RST_BAR,			\
+		.fmax = MT7629_PLL_FMAX,				\
+		.flags = _flags,					\
+		.pcwbits = _pcwbits,					\
+		.pd_reg = _pd_reg,					\
+		.pd_shift = _pd_shift,					\
+		.pcw_reg = _pcw_reg,					\
+		.pcw_shift = _pcw_shift,				\
+	}
+
+static const struct mtk_pll_data apmixed_plls[] = {
+	PLL(CLK_APMIXED_ARMPLL, 0x200, 0x20c, 0x1, 0,
+	    21, 0x204, 24, 0x204, 0),
+	PLL(CLK_APMIXED_MAINPLL, 0x210, 0x21c, 0x1, HAVE_RST_BAR,
+	    21, 0x214, 24, 0x214, 0),
+	PLL(CLK_APMIXED_UNIV2PLL, 0x220, 0x22c, 0x1, HAVE_RST_BAR,
+	    7, 0x224, 24, 0x224, 14),
+	PLL(CLK_APMIXED_ETH1PLL, 0x300, 0x310, 0x1, 0,
+	    21, 0x300, 1, 0x304, 0),
+	PLL(CLK_APMIXED_ETH2PLL, 0x314, 0x320, 0x1, 0,
+	    21, 0x314, 1, 0x318, 0),
+	PLL(CLK_APMIXED_SGMIPLL, 0x358, 0x368, 0x1, 0,
+	    21, 0x358, 1, 0x35c, 0),
+};
+
+/* topckgen */
+#define FACTOR0(_id, _parent, _mult, _div)			\
+	FACTOR(_id, _parent, _mult, _div, CLK_PARENT_APMIXED)
+
+#define FACTOR1(_id, _parent, _mult, _div)			\
+	FACTOR(_id, _parent, _mult, _div, CLK_PARENT_TOPCKGEN)
+
+#define FACTOR2(_id, _parent, _mult, _div)			\
+	FACTOR(_id, _parent, _mult, _div, 0)
+
+static const struct mtk_fixed_clk top_fixed_clks[] = {
+	FIXED_CLK(CLK_TOP_TO_U2_PHY, CLK_XTAL, 31250000),
+	FIXED_CLK(CLK_TOP_TO_U2_PHY_1P, CLK_XTAL, 31250000),
+	FIXED_CLK(CLK_TOP_PCIE0_PIPE_EN, CLK_XTAL, 125000000),
+	FIXED_CLK(CLK_TOP_PCIE1_PIPE_EN, CLK_XTAL, 125000000),
+	FIXED_CLK(CLK_TOP_SSUSB_TX250M, CLK_XTAL, 250000000),
+	FIXED_CLK(CLK_TOP_SSUSB_EQ_RX250M, CLK_XTAL, 250000000),
+	FIXED_CLK(CLK_TOP_SSUSB_CDR_REF, CLK_XTAL, 33333333),
+	FIXED_CLK(CLK_TOP_SSUSB_CDR_FB, CLK_XTAL, 50000000),
+	FIXED_CLK(CLK_TOP_SATA_ASIC, CLK_XTAL, 50000000),
+	FIXED_CLK(CLK_TOP_SATA_RBC, CLK_XTAL, 50000000),
+};
+
+static const struct mtk_fixed_factor top_fixed_divs[] = {
+	FACTOR0(CLK_TOP_TO_USB3_SYS, CLK_APMIXED_ETH1PLL, 1, 4),
+	FACTOR0(CLK_TOP_P1_1MHZ, CLK_APMIXED_ETH1PLL, 1, 500),
+	FACTOR0(CLK_TOP_4MHZ, CLK_APMIXED_ETH1PLL, 1, 125),
+	FACTOR0(CLK_TOP_P0_1MHZ, CLK_APMIXED_ETH1PLL, 1, 500),
+	FACTOR0(CLK_TOP_ETH_500M, CLK_APMIXED_ETH1PLL, 1, 1),
+	FACTOR1(CLK_TOP_TXCLK_SRC_PRE, CLK_TOP_SGMIIPLL_D2, 1, 1),
+	FACTOR2(CLK_TOP_RTC, CLK_XTAL, 1, 1024),
+	FACTOR2(CLK_TOP_PWM_QTR_26M, CLK_XTAL, 1, 1),
+	FACTOR2(CLK_TOP_CPUM_TCK_IN, CLK_XTAL, 1, 1),
+	FACTOR2(CLK_TOP_TO_USB3_DA_TOP, CLK_XTAL, 1, 1),
+	FACTOR2(CLK_TOP_MEMPLL, CLK_XTAL, 32, 1),
+	FACTOR1(CLK_TOP_DMPLL, CLK_TOP_MEMPLL, 1, 1),
+	FACTOR1(CLK_TOP_DMPLL_D4, CLK_TOP_MEMPLL, 1, 4),
+	FACTOR1(CLK_TOP_DMPLL_D8, CLK_TOP_MEMPLL, 1, 8),
+	FACTOR0(CLK_TOP_SYSPLL_D2, CLK_APMIXED_MAINPLL, 1, 2),
+	FACTOR0(CLK_TOP_SYSPLL1_D2, CLK_APMIXED_MAINPLL, 1, 4),
+	FACTOR0(CLK_TOP_SYSPLL1_D4, CLK_APMIXED_MAINPLL, 1, 8),
+	FACTOR0(CLK_TOP_SYSPLL1_D8, CLK_APMIXED_MAINPLL, 1, 16),
+	FACTOR0(CLK_TOP_SYSPLL1_D16, CLK_APMIXED_MAINPLL, 1, 32),
+	FACTOR0(CLK_TOP_SYSPLL2_D2, CLK_APMIXED_MAINPLL, 1, 6),
+	FACTOR0(CLK_TOP_SYSPLL2_D4, CLK_APMIXED_MAINPLL, 1, 12),
+	FACTOR0(CLK_TOP_SYSPLL2_D8, CLK_APMIXED_MAINPLL, 1, 24),
+	FACTOR0(CLK_TOP_SYSPLL_D5, CLK_APMIXED_MAINPLL, 1, 5),
+	FACTOR0(CLK_TOP_SYSPLL3_D2, CLK_APMIXED_MAINPLL, 1, 10),
+	FACTOR0(CLK_TOP_SYSPLL3_D4, CLK_APMIXED_MAINPLL, 1, 20),
+	FACTOR0(CLK_TOP_SYSPLL_D7, CLK_APMIXED_MAINPLL, 1, 7),
+	FACTOR0(CLK_TOP_SYSPLL4_D2, CLK_APMIXED_MAINPLL, 1, 14),
+	FACTOR0(CLK_TOP_SYSPLL4_D4, CLK_APMIXED_MAINPLL, 1, 28),
+	FACTOR0(CLK_TOP_SYSPLL4_D16, CLK_APMIXED_MAINPLL, 1, 112),
+	FACTOR0(CLK_TOP_UNIVPLL, CLK_APMIXED_UNIV2PLL, 1, 2),
+	FACTOR1(CLK_TOP_UNIVPLL1_D2, CLK_TOP_UNIVPLL, 1, 4),
+	FACTOR1(CLK_TOP_UNIVPLL1_D4, CLK_TOP_UNIVPLL, 1, 8),
+	FACTOR1(CLK_TOP_UNIVPLL1_D8, CLK_TOP_UNIVPLL, 1, 16),
+	FACTOR1(CLK_TOP_UNIVPLL_D3, CLK_TOP_UNIVPLL, 1, 3),
+	FACTOR1(CLK_TOP_UNIVPLL2_D2, CLK_TOP_UNIVPLL, 1, 6),
+	FACTOR1(CLK_TOP_UNIVPLL2_D4, CLK_TOP_UNIVPLL, 1, 12),
+	FACTOR1(CLK_TOP_UNIVPLL2_D8, CLK_TOP_UNIVPLL, 1, 24),
+	FACTOR1(CLK_TOP_UNIVPLL2_D16, CLK_TOP_UNIVPLL, 1, 48),
+	FACTOR1(CLK_TOP_UNIVPLL_D5, CLK_TOP_UNIVPLL, 1, 5),
+	FACTOR1(CLK_TOP_UNIVPLL3_D2, CLK_TOP_UNIVPLL, 1, 10),
+	FACTOR1(CLK_TOP_UNIVPLL3_D4, CLK_TOP_UNIVPLL, 1, 20),
+	FACTOR1(CLK_TOP_UNIVPLL3_D16, CLK_TOP_UNIVPLL, 1, 80),
+	FACTOR1(CLK_TOP_UNIVPLL_D7, CLK_TOP_UNIVPLL, 1, 7),
+	FACTOR1(CLK_TOP_UNIVPLL_D80_D4, CLK_TOP_UNIVPLL, 1, 320),
+	FACTOR1(CLK_TOP_UNIV48M, CLK_TOP_UNIVPLL, 1, 25),
+	FACTOR0(CLK_TOP_SGMIIPLL_D2, CLK_APMIXED_SGMIPLL, 1, 2),
+	FACTOR2(CLK_TOP_CLKXTAL_D4, CLK_XTAL, 1, 4),
+	FACTOR1(CLK_TOP_HD_FAXI, CLK_TOP_AXI_SEL, 1, 1),
+	FACTOR1(CLK_TOP_FAXI, CLK_TOP_AXI_SEL, 1, 1),
+	FACTOR1(CLK_TOP_F_FAUD_INTBUS, CLK_TOP_AUD_INTBUS_SEL, 1, 1),
+	FACTOR1(CLK_TOP_AP2WBHIF_HCLK, CLK_TOP_SYSPLL1_D8, 1, 1),
+	FACTOR1(CLK_TOP_10M_INFRAO, CLK_TOP_10M_SEL, 1, 1),
+	FACTOR1(CLK_TOP_MSDC30_1, CLK_TOP_MSDC30_1, 1, 1),
+	FACTOR1(CLK_TOP_SPI, CLK_TOP_SPI0_SEL, 1, 1),
+	FACTOR1(CLK_TOP_SF, CLK_TOP_NFI_INFRA_SEL, 1, 1),
+	FACTOR1(CLK_TOP_FLASH, CLK_TOP_FLASH_SEL, 1, 1),
+	FACTOR1(CLK_TOP_TO_USB3_REF, CLK_TOP_SATA_SEL, 1, 4),
+	FACTOR1(CLK_TOP_TO_USB3_MCU, CLK_TOP_AXI_SEL, 1, 1),
+	FACTOR1(CLK_TOP_TO_USB3_DMA, CLK_TOP_HIF_SEL, 1, 1),
+	FACTOR1(CLK_TOP_FROM_TOP_AHB, CLK_TOP_AXI_SEL, 1, 1),
+	FACTOR1(CLK_TOP_FROM_TOP_AXI, CLK_TOP_HIF_SEL, 1, 1),
+	FACTOR1(CLK_TOP_PCIE1_MAC_EN, CLK_TOP_UNIVPLL1_D4, 1, 1),
+	FACTOR1(CLK_TOP_PCIE0_MAC_EN, CLK_TOP_UNIVPLL1_D4, 1, 1),
+};
+
+static const int axi_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_SYSPLL1_D2,
+	CLK_TOP_SYSPLL_D5,
+	CLK_TOP_SYSPLL1_D4,
+	CLK_TOP_UNIVPLL_D5,
+	CLK_TOP_UNIVPLL2_D2,
+	CLK_TOP_UNIVPLL_D7,
+	CLK_TOP_DMPLL
+};
+
+static const int mem_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_DMPLL
+};
+
+static const int ddrphycfg_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_SYSPLL1_D8
+};
+
+static const int eth_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_SYSPLL1_D2,
+	CLK_TOP_UNIVPLL1_D2,
+	CLK_TOP_SYSPLL1_D4,
+	CLK_TOP_UNIVPLL_D5,
+	CLK_TOP_SGMIIPLL_D2,
+	CLK_TOP_UNIVPLL_D7,
+	CLK_TOP_DMPLL
+};
+
+static const int pwm_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_UNIVPLL2_D4
+};
+
+static const int f10m_ref_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_SGMIIPLL_D2
+};
+
+static const int nfi_infra_parents[] = {
+	CLK_XTAL,
+	CLK_XTAL,
+	CLK_XTAL,
+	CLK_XTAL,
+	CLK_XTAL,
+	CLK_XTAL,
+	CLK_TOP_UNIVPLL2_D8,
+	CLK_TOP_UNIVPLL3_D4,
+	CLK_TOP_SYSPLL1_D8,
+	CLK_TOP_UNIVPLL1_D8,
+	CLK_TOP_SYSPLL4_D2,
+	CLK_TOP_SYSPLL2_D4,
+	CLK_TOP_UNIVPLL2_D4,
+	CLK_TOP_UNIVPLL3_D2,
+	CLK_TOP_SYSPLL1_D4,
+	CLK_TOP_SYSPLL_D7
+};
+
+static const int flash_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_UNIVPLL_D80_D4,
+	CLK_TOP_SYSPLL2_D8,
+	CLK_TOP_SYSPLL3_D4,
+	CLK_TOP_UNIVPLL3_D4,
+	CLK_TOP_UNIVPLL1_D8,
+	CLK_TOP_SYSPLL2_D4,
+	CLK_TOP_UNIVPLL2_D4
+};
+
+static const int uart_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_UNIVPLL2_D8
+};
+
+static const int spi0_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_SYSPLL3_D2,
+	CLK_XTAL,
+	CLK_TOP_SYSPLL2_D4,
+	CLK_TOP_SYSPLL4_D2,
+	CLK_TOP_UNIVPLL2_D4,
+	CLK_TOP_UNIVPLL1_D8,
+	CLK_XTAL
+};
+
+static const int spi1_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_SYSPLL3_D2,
+	CLK_XTAL,
+	CLK_TOP_SYSPLL4_D4,
+	CLK_TOP_SYSPLL4_D2,
+	CLK_TOP_UNIVPLL2_D4,
+	CLK_TOP_UNIVPLL1_D8,
+	CLK_XTAL
+};
+
+static const int msdc30_0_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_UNIVPLL2_D16,
+	CLK_TOP_UNIV48M
+};
+
+static const int msdc30_1_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_UNIVPLL2_D16,
+	CLK_TOP_UNIV48M,
+	CLK_TOP_SYSPLL2_D4,
+	CLK_TOP_UNIVPLL2_D4,
+	CLK_TOP_SYSPLL_D7,
+	CLK_TOP_SYSPLL2_D2,
+	CLK_TOP_UNIVPLL2_D2
+};
+
+static const int ap2wbmcu_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_SYSPLL1_D2,
+	CLK_TOP_UNIV48M,
+	CLK_TOP_SYSPLL1_D8,
+	CLK_TOP_UNIVPLL2_D4,
+	CLK_TOP_SYSPLL_D7,
+	CLK_TOP_SYSPLL2_D2,
+	CLK_TOP_UNIVPLL2_D2
+};
+
+static const int audio_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_SYSPLL3_D4,
+	CLK_TOP_SYSPLL4_D4,
+	CLK_TOP_SYSPLL1_D16
+};
+
+static const int aud_intbus_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_SYSPLL1_D4,
+	CLK_TOP_SYSPLL4_D2,
+	CLK_TOP_DMPLL_D4
+};
+
+static const int pmicspi_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_SYSPLL1_D8,
+	CLK_TOP_SYSPLL3_D4,
+	CLK_TOP_SYSPLL1_D16,
+	CLK_TOP_UNIVPLL3_D4,
+	CLK_XTAL,
+	CLK_TOP_UNIVPLL2_D4,
+	CLK_TOP_DMPLL_D8
+};
+
+static const int scp_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_SYSPLL1_D8,
+	CLK_TOP_UNIVPLL2_D2,
+	CLK_TOP_UNIVPLL2_D4
+};
+
+static const int atb_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_SYSPLL1_D2,
+	CLK_TOP_SYSPLL_D5
+};
+
+static const int hif_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_SYSPLL1_D2,
+	CLK_TOP_UNIVPLL1_D2,
+	CLK_TOP_SYSPLL1_D4,
+	CLK_TOP_UNIVPLL_D5,
+	-1,
+	CLK_TOP_UNIVPLL_D7
+};
+
+static const int sata_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_UNIVPLL2_D4
+};
+
+static const int usb20_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_UNIVPLL3_D4,
+	CLK_TOP_SYSPLL1_D8
+};
+
+static const int aud1_parents[] = {
+	CLK_XTAL
+};
+
+static const int irrx_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_SYSPLL4_D16
+};
+
+static const int crypto_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_UNIVPLL_D3,
+	CLK_TOP_UNIVPLL1_D2,
+	CLK_TOP_SYSPLL1_D2,
+	CLK_TOP_UNIVPLL_D5,
+	CLK_TOP_SYSPLL_D5,
+	CLK_TOP_UNIVPLL2_D2,
+	CLK_TOP_SYSPLL_D2
+};
+
+static const int gpt10m_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_CLKXTAL_D4
+};
+
+static const struct mtk_composite top_muxes[] = {
+	/* CLK_CFG_0 */
+	MUX_GATE(CLK_TOP_AXI_SEL, axi_parents, 0x40, 0, 3, 7),
+	MUX_GATE(CLK_TOP_MEM_SEL, mem_parents, 0x40, 8, 1, 15),
+	MUX_GATE(CLK_TOP_DDRPHYCFG_SEL, ddrphycfg_parents, 0x40, 16, 1, 23),
+	MUX_GATE(CLK_TOP_ETH_SEL, eth_parents, 0x40, 24, 3, 31),
+
+	/* CLK_CFG_1 */
+	MUX_GATE(CLK_TOP_PWM_SEL, pwm_parents, 0x50, 0, 2, 7),
+	MUX_GATE(CLK_TOP_F10M_REF_SEL, f10m_ref_parents, 0x50, 8, 1, 15),
+	MUX_GATE(CLK_TOP_NFI_INFRA_SEL, nfi_infra_parents, 0x50, 16, 4, 23),
+	MUX_GATE(CLK_TOP_FLASH_SEL, flash_parents, 0x50, 24, 3, 31),
+
+	/* CLK_CFG_2 */
+	MUX_GATE(CLK_TOP_UART_SEL, uart_parents, 0x60, 0, 1, 7),
+	MUX_GATE(CLK_TOP_SPI0_SEL, spi0_parents, 0x60, 8, 3, 15),
+	MUX_GATE(CLK_TOP_SPI1_SEL, spi1_parents, 0x60, 16, 3, 23),
+	MUX_GATE(CLK_TOP_MSDC50_0_SEL, uart_parents, 0x60, 24, 3, 31),
+
+	/* CLK_CFG_3 */
+	MUX_GATE(CLK_TOP_MSDC30_0_SEL, msdc30_0_parents, 0x70, 0, 3, 7),
+	MUX_GATE(CLK_TOP_MSDC30_1_SEL, msdc30_1_parents, 0x70, 8, 3, 15),
+	MUX_GATE(CLK_TOP_AP2WBMCU_SEL, ap2wbmcu_parents, 0x70, 16, 3, 23),
+	MUX_GATE(CLK_TOP_AP2WBHIF_SEL, ap2wbmcu_parents, 0x70, 24, 3, 31),
+
+	/* CLK_CFG_4 */
+	MUX_GATE(CLK_TOP_AUDIO_SEL, audio_parents, 0x80, 0, 2, 7),
+	MUX_GATE(CLK_TOP_AUD_INTBUS_SEL, aud_intbus_parents, 0x80, 8, 2, 15),
+	MUX_GATE(CLK_TOP_PMICSPI_SEL, pmicspi_parents, 0x80, 16, 3, 23),
+	MUX_GATE(CLK_TOP_SCP_SEL, scp_parents, 0x80, 24, 2, 31),
+
+	/* CLK_CFG_5 */
+	MUX_GATE(CLK_TOP_ATB_SEL, atb_parents, 0x90, 0, 2, 7),
+	MUX_GATE_FLAGS(CLK_TOP_HIF_SEL, hif_parents, 0x90, 8, 3, 15,
+		       CLK_DOMAIN_SCPSYS),
+	MUX_GATE(CLK_TOP_SATA_SEL, sata_parents, 0x90, 16, 1, 23),
+	MUX_GATE(CLK_TOP_U2_SEL, usb20_parents, 0x90, 24, 2, 31),
+
+	/* CLK_CFG_6 */
+	MUX_GATE(CLK_TOP_AUD1_SEL, aud1_parents, 0xA0, 0, 1, 7),
+	MUX_GATE(CLK_TOP_AUD2_SEL, aud1_parents, 0xA0, 8, 1, 15),
+	MUX_GATE(CLK_TOP_IRRX_SEL, irrx_parents, 0xA0, 16, 1, 23),
+	MUX_GATE(CLK_TOP_IRTX_SEL, irrx_parents, 0xA0, 24, 1, 31),
+
+	/* CLK_CFG_7 */
+	MUX_GATE(CLK_TOP_SATA_MCU_SEL, scp_parents, 0xB0, 0, 2, 7),
+	MUX_GATE(CLK_TOP_PCIE0_MCU_SEL, scp_parents, 0xB0, 8, 2, 15),
+	MUX_GATE(CLK_TOP_PCIE1_MCU_SEL, scp_parents, 0xB0, 16, 2, 23),
+	MUX_GATE(CLK_TOP_SSUSB_MCU_SEL, scp_parents, 0xB0, 24, 2, 31),
+
+	/* CLK_CFG_8 */
+	MUX_GATE(CLK_TOP_CRYPTO_SEL, crypto_parents, 0xC0, 0, 3, 7),
+	MUX_GATE(CLK_TOP_SGMII_REF_1_SEL, f10m_ref_parents, 0xC0, 8, 1, 15),
+	MUX_GATE(CLK_TOP_10M_SEL, gpt10m_parents, 0xC0, 16, 1, 23),
+};
+
+/* infracfg */
+static const struct mtk_gate_regs infra_cg_regs = {
+	.set_ofs = 0x40,
+	.clr_ofs = 0x44,
+	.sta_ofs = 0x48,
+};
+
+#define GATE_INFRA(_id, _parent, _shift) {			\
+		.id = _id,					\
+		.parent = _parent,				\
+		.regs = &infra_cg_regs,				\
+		.shift = _shift,				\
+		.flags = CLK_GATE_SETCLR | CLK_PARENT_TOPCKGEN,	\
+	}
+
+static const struct mtk_gate infra_cgs[] = {
+	GATE_INFRA(CLK_INFRA_DBGCLK_PD, CLK_TOP_HD_FAXI, 0),
+	GATE_INFRA(CLK_INFRA_TRNG_PD, CLK_TOP_HD_FAXI, 2),
+	GATE_INFRA(CLK_INFRA_DEVAPC_PD, CLK_TOP_HD_FAXI, 4),
+	GATE_INFRA(CLK_INFRA_APXGPT_PD, CLK_TOP_10M_INFRAO, 18),
+	GATE_INFRA(CLK_INFRA_SEJ_PD, CLK_TOP_10M_INFRAO, 19),
+};
+
+/* pericfg */
+static const struct mtk_gate_regs peri0_cg_regs = {
+	.set_ofs = 0x8,
+	.clr_ofs = 0x10,
+	.sta_ofs = 0x18,
+};
+
+static const struct mtk_gate_regs peri1_cg_regs = {
+	.set_ofs = 0xC,
+	.clr_ofs = 0x14,
+	.sta_ofs = 0x1C,
+};
+
+#define GATE_PERI0(_id, _parent, _shift) {			\
+		.id = _id,					\
+		.parent = _parent,				\
+		.regs = &peri0_cg_regs,				\
+		.shift = _shift,				\
+		.flags = CLK_GATE_SETCLR | CLK_PARENT_TOPCKGEN,	\
+	}
+
+#define GATE_PERI1(_id, _parent, _shift) {			\
+		.id = _id,					\
+		.parent = _parent,				\
+		.regs = &peri1_cg_regs,				\
+		.shift = _shift,				\
+		.flags = CLK_GATE_SETCLR | CLK_PARENT_TOPCKGEN,	\
+	}
+
+static const struct mtk_gate peri_cgs[] = {
+	GATE_PERI0(CLK_PERI_PWM1_PD, CLK_TOP_PWM_QTR_26M, 2),
+	GATE_PERI0(CLK_PERI_PWM2_PD, CLK_TOP_PWM_QTR_26M, 3),
+	GATE_PERI0(CLK_PERI_PWM3_PD, CLK_TOP_PWM_QTR_26M, 4),
+	GATE_PERI0(CLK_PERI_PWM4_PD, CLK_TOP_PWM_QTR_26M, 5),
+	GATE_PERI0(CLK_PERI_PWM5_PD, CLK_TOP_PWM_QTR_26M, 6),
+	GATE_PERI0(CLK_PERI_PWM6_PD, CLK_TOP_PWM_QTR_26M, 7),
+	GATE_PERI0(CLK_PERI_PWM7_PD, CLK_TOP_PWM_QTR_26M, 8),
+	GATE_PERI0(CLK_PERI_PWM_PD, CLK_TOP_PWM_QTR_26M, 9),
+	GATE_PERI0(CLK_PERI_AP_DMA_PD, CLK_TOP_FAXI, 12),
+	GATE_PERI0(CLK_PERI_MSDC30_1_PD, CLK_TOP_MSDC30_1, 14),
+	GATE_PERI0(CLK_PERI_UART0_PD, CLK_TOP_FAXI, 17),
+	GATE_PERI0(CLK_PERI_UART1_PD, CLK_TOP_FAXI, 18),
+	GATE_PERI0(CLK_PERI_UART2_PD, CLK_TOP_FAXI, 19),
+	GATE_PERI0(CLK_PERI_UART3_PD, CLK_TOP_FAXI, 20),
+	GATE_PERI0(CLK_PERI_BTIF_PD, CLK_TOP_FAXI, 22),
+	GATE_PERI0(CLK_PERI_I2C0_PD, CLK_TOP_FAXI, 23),
+	GATE_PERI0(CLK_PERI_SPI0_PD, CLK_TOP_SPI, 28),
+	GATE_PERI0(CLK_PERI_SNFI_PD, CLK_TOP_SF, 29),
+	GATE_PERI0(CLK_PERI_NFI_PD, CLK_TOP_FAXI, 30),
+	GATE_PERI0(CLK_PERI_NFIECC_PD, CLK_TOP_FAXI, 31),
+	GATE_PERI1(CLK_PERI_FLASH_PD, CLK_TOP_FLASH, 1),
+};
+
+/* ethsys */
+static const struct mtk_gate_regs eth_cg_regs = {
+	.sta_ofs = 0x30,
+};
+
+#define GATE_ETH(_id, _parent, _shift, _flag) {			\
+		.id = _id,					\
+		.parent = _parent,				\
+		.regs = &eth_cg_regs,				\
+		.shift = _shift,				\
+		.flags = CLK_GATE_NO_SETCLR_INV | (_flag),	\
+	}
+
+#define GATE_ETH0(_id, _parent, _shift)				\
+	GATE_ETH(_id, _parent, _shift, CLK_PARENT_APMIXED)
+
+#define GATE_ETH1(_id, _parent, _shift)				\
+	GATE_ETH(_id, _parent, _shift, CLK_PARENT_TOPCKGEN)
+
+static const struct mtk_gate eth_cgs[] = {
+	GATE_ETH0(CLK_ETH_FE_EN, CLK_APMIXED_ETH2PLL, 6),
+	GATE_ETH1(CLK_ETH_GP2_EN, CLK_TOP_TXCLK_SRC_PRE, 7),
+	GATE_ETH1(CLK_ETH_GP1_EN, CLK_TOP_TXCLK_SRC_PRE, 8),
+	GATE_ETH1(CLK_ETH_GP0_EN, CLK_TOP_TXCLK_SRC_PRE, 9),
+	GATE_ETH1(CLK_ETH_ESW_EN, CLK_TOP_ETH_500M, 16),
+};
+
+static const struct mtk_gate_regs sgmii_cg_regs = {
+	.set_ofs = 0xE4,
+	.clr_ofs = 0xE4,
+	.sta_ofs = 0xE4,
+};
+
+#define GATE_SGMII(_id, _parent, _shift) {			\
+	.id = _id,						\
+	.parent = _parent,					\
+	.regs = &sgmii_cg_regs,					\
+	.shift = _shift,					\
+	.flags = CLK_GATE_NO_SETCLR_INV | CLK_PARENT_TOPCKGEN,	\
+}
+
+static const struct mtk_gate sgmii_cgs[] = {
+	GATE_SGMII(CLK_SGMII_TX_EN, CLK_TOP_SSUSB_TX250M, 2),
+	GATE_SGMII(CLK_SGMII_RX_EN, CLK_TOP_SSUSB_EQ_RX250M, 3),
+	GATE_SGMII(CLK_SGMII_CDR_REF, CLK_TOP_SSUSB_CDR_REF, 4),
+	GATE_SGMII(CLK_SGMII_CDR_FB, CLK_TOP_SSUSB_CDR_FB, 5),
+};
+
+static const struct mtk_clk_tree mt7629_clk_tree = {
+	.xtal_rate = 40 * MHZ,
+	.xtal2_rate = 20 * MHZ,
+	.fdivs_offs = CLK_TOP_TO_USB3_SYS,
+	.muxes_offs = CLK_TOP_AXI_SEL,
+	.plls = apmixed_plls,
+	.fclks = top_fixed_clks,
+	.fdivs = top_fixed_divs,
+	.muxes = top_muxes,
+};
+
+static int mt7629_mcucfg_probe(struct udevice *dev)
+{
+	void __iomem *base;
+
+	base = dev_read_addr_ptr(dev);
+	if (!base)
+		return -ENOENT;
+
+	clrsetbits_le32(base + MCU_AXI_DIV, AXI_DIV_MSK,
+			AXI_DIV_SEL(0x12));
+	clrsetbits_le32(base + MCU_BUS_MUX, MCU_BUS_MSK,
+			MCU_BUS_SEL(0x1));
+
+	return 0;
+}
+
+static int mt7629_apmixedsys_probe(struct udevice *dev)
+{
+	struct mtk_clk_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	ret = mtk_clk_init(dev, &mt7629_clk_tree);
+	if (ret)
+		return ret;
+
+	/* reduce clock square disable time */
+	writel(0x501, priv->base + MT7629_CLKSQ_STB_CON0);
+	/* extend pwr/iso control timing to 1us */
+	writel(0x80008, priv->base + MT7629_PLL_ISO_CON0);
+
+	return 0;
+}
+
+static int mt7629_topckgen_probe(struct udevice *dev)
+{
+	return mtk_clk_init(dev, &mt7629_clk_tree);
+}
+
+static int mt7629_infracfg_probe(struct udevice *dev)
+{
+	return mtk_clk_gate_init(dev, &mt7629_clk_tree, infra_cgs);
+}
+
+static int mt7629_pericfg_probe(struct udevice *dev)
+{
+	return mtk_clk_gate_init(dev, &mt7629_clk_tree, peri_cgs);
+}
+
+static int mt7629_ethsys_probe(struct udevice *dev)
+{
+	return mtk_clk_gate_init(dev, &mt7629_clk_tree, eth_cgs);
+}
+
+static int mt7629_sgmiisys_probe(struct udevice *dev)
+{
+	return mtk_clk_gate_init(dev, &mt7629_clk_tree, sgmii_cgs);
+}
+
+static const struct udevice_id mt7629_apmixed_compat[] = {
+	{ .compatible = "mediatek,mt7629-apmixedsys" },
+	{ }
+};
+
+static const struct udevice_id mt7629_topckgen_compat[] = {
+	{ .compatible = "mediatek,mt7629-topckgen" },
+	{ }
+};
+
+static const struct udevice_id mt7629_infracfg_compat[] = {
+	{ .compatible = "mediatek,mt7629-infracfg", },
+	{ }
+};
+
+static const struct udevice_id mt7629_pericfg_compat[] = {
+	{ .compatible = "mediatek,mt7629-pericfg", },
+	{ }
+};
+
+static const struct udevice_id mt7629_ethsys_compat[] = {
+	{ .compatible = "mediatek,mt7629-ethsys", },
+	{ }
+};
+
+static const struct udevice_id mt7629_sgmiisys_compat[] = {
+	{ .compatible = "mediatek,mt7629-sgmiisys", },
+	{ }
+};
+
+static const struct udevice_id mt7629_mcucfg_compat[] = {
+	{ .compatible = "mediatek,mt7629-mcucfg" },
+	{ }
+};
+
+U_BOOT_DRIVER(mtk_mcucfg) = {
+	.name = "mt7629-mcucfg",
+	.id = UCLASS_SYSCON,
+	.of_match = mt7629_mcucfg_compat,
+	.probe = mt7629_mcucfg_probe,
+	.flags = DM_FLAG_PRE_RELOC,
+};
+
+U_BOOT_DRIVER(mtk_clk_apmixedsys) = {
+	.name = "mt7629-clock-apmixedsys",
+	.id = UCLASS_CLK,
+	.of_match = mt7629_apmixed_compat,
+	.probe = mt7629_apmixedsys_probe,
+	.priv_auto_alloc_size = sizeof(struct mtk_clk_priv),
+	.ops = &mtk_clk_apmixedsys_ops,
+	.flags = DM_FLAG_PRE_RELOC,
+};
+
+U_BOOT_DRIVER(mtk_clk_topckgen) = {
+	.name = "mt7629-clock-topckgen",
+	.id = UCLASS_CLK,
+	.of_match = mt7629_topckgen_compat,
+	.probe = mt7629_topckgen_probe,
+	.priv_auto_alloc_size = sizeof(struct mtk_clk_priv),
+	.ops = &mtk_clk_topckgen_ops,
+	.flags = DM_FLAG_PRE_RELOC,
+};
+
+U_BOOT_DRIVER(mtk_clk_infracfg) = {
+	.name = "mt7629-clock-infracfg",
+	.id = UCLASS_CLK,
+	.of_match = mt7629_infracfg_compat,
+	.probe = mt7629_infracfg_probe,
+	.priv_auto_alloc_size = sizeof(struct mtk_cg_priv),
+	.ops = &mtk_clk_gate_ops,
+	.flags = DM_FLAG_PRE_RELOC,
+};
+
+U_BOOT_DRIVER(mtk_clk_pericfg) = {
+	.name = "mt7629-clock-pericfg",
+	.id = UCLASS_CLK,
+	.of_match = mt7629_pericfg_compat,
+	.probe = mt7629_pericfg_probe,
+	.priv_auto_alloc_size = sizeof(struct mtk_cg_priv),
+	.ops = &mtk_clk_gate_ops,
+	.flags = DM_FLAG_PRE_RELOC,
+};
+
+U_BOOT_DRIVER(mtk_clk_ethsys) = {
+	.name = "mt7629-clock-ethsys",
+	.id = UCLASS_CLK,
+	.of_match = mt7629_ethsys_compat,
+	.probe = mt7629_ethsys_probe,
+	.priv_auto_alloc_size = sizeof(struct mtk_cg_priv),
+	.ops = &mtk_clk_gate_ops,
+};
+
+U_BOOT_DRIVER(mtk_clk_sgmiisys) = {
+	.name = "mt7629-clock-sgmiisys",
+	.id = UCLASS_CLK,
+	.of_match = mt7629_sgmiisys_compat,
+	.probe = mt7629_sgmiisys_probe,
+	.priv_auto_alloc_size = sizeof(struct mtk_cg_priv),
+	.ops = &mtk_clk_gate_ops,
+};
diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c
new file mode 100644
index 0000000..73e10fb
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mtk.c
@@ -0,0 +1,492 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MediaTek common clock driver
+ *
+ * Copyright (C) 2018 MediaTek Inc.
+ * Author: Ryder Lee <ryder.lee@mediatek.com>
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <div64.h>
+#include <dm.h>
+#include <asm/io.h>
+
+#include "clk-mtk.h"
+
+#define REG_CON0			0
+#define REG_CON1			4
+
+#define CON0_BASE_EN			BIT(0)
+#define CON0_PWR_ON			BIT(0)
+#define CON0_ISO_EN			BIT(1)
+#define CON1_PCW_CHG			BIT(31)
+
+#define POSTDIV_MASK			0x7
+#define INTEGER_BITS			7
+
+/* scpsys clock off control */
+#define CLK_SCP_CFG0			0x200
+#define CLK_SCP_CFG1			0x204
+#define SCP_ARMCK_OFF_EN		GENMASK(9, 0)
+#define SCP_AXICK_DCM_DIS_EN		BIT(0)
+#define SCP_AXICK_26M_SEL_EN		BIT(4)
+
+/* shared functions */
+
+/*
+ * In case the rate change propagation to parent clocks is undesirable,
+ * this function is recursively called to find the parent to calculate
+ * the accurate frequency.
+ */
+static int mtk_clk_find_parent_rate(struct clk *clk, int id,
+				    const struct driver *drv)
+{
+	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 {
+		parent.dev = clk->dev;
+	}
+
+	return clk_get_rate(&parent);
+}
+
+static int mtk_clk_mux_set_parent(void __iomem *base, u32 parent,
+				  const struct mtk_composite *mux)
+{
+	u32 val, index = 0;
+
+	while (mux->parent[index] != parent)
+		if (++index == mux->num_parents)
+			return -EINVAL;
+
+	/* switch mux to a select parent */
+	val = readl(base + mux->mux_reg);
+	val &= ~(mux->mux_mask << mux->mux_shift);
+
+	val |= index << mux->mux_shift;
+	writel(val, base + mux->mux_reg);
+
+	return 0;
+}
+
+/* apmixedsys functions */
+
+static unsigned long __mtk_pll_recalc_rate(const struct mtk_pll_data *pll,
+					   u32 fin, u32 pcw, int postdiv)
+{
+	int pcwbits = pll->pcwbits;
+	int pcwfbits;
+	u64 vco;
+	u8 c = 0;
+
+	/* The fractional part of the PLL divider. */
+	pcwfbits = pcwbits > INTEGER_BITS ? pcwbits - INTEGER_BITS : 0;
+
+	vco = (u64)fin * pcw;
+
+	if (pcwfbits && (vco & GENMASK(pcwfbits - 1, 0)))
+		c = 1;
+
+	vco >>= pcwfbits;
+
+	if (c)
+		vco++;
+
+	return ((unsigned long)vco + postdiv - 1) / postdiv;
+}
+
+/**
+ * MediaTek PLLs are configured through their pcw value. The pcw value
+ * describes a divider in the PLL feedback loop which consists of 7 bits
+ * for the integer part and the remaining bits (if present) for the
+ * fractional part. Also they have a 3 bit power-of-two post divider.
+ */
+static void mtk_pll_set_rate_regs(struct clk *clk, u32 pcw, int postdiv)
+{
+	struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
+	const struct mtk_pll_data *pll = &priv->tree->plls[clk->id];
+	u32 val;
+
+	/* set postdiv */
+	val = readl(priv->base + pll->pd_reg);
+	val &= ~(POSTDIV_MASK << pll->pd_shift);
+	val |= (ffs(postdiv) - 1) << pll->pd_shift;
+
+	/* postdiv and pcw need to set at the same time if on same register */
+	if (pll->pd_reg != pll->pcw_reg) {
+		writel(val, priv->base + pll->pd_reg);
+		val = readl(priv->base + pll->pcw_reg);
+	}
+
+	/* set pcw */
+	val &= ~GENMASK(pll->pcw_shift + pll->pcwbits - 1, pll->pcw_shift);
+	val |= pcw << pll->pcw_shift;
+	val &= ~CON1_PCW_CHG;
+	writel(val, priv->base + pll->pcw_reg);
+
+	val |= CON1_PCW_CHG;
+	writel(val, priv->base + pll->pcw_reg);
+
+	udelay(20);
+}
+
+/**
+ * mtk_pll_calc_values - calculate good values for a given input frequency.
+ * @clk:	The clk
+ * @pcw:	The pcw value (output)
+ * @postdiv:	The post divider (output)
+ * @freq:	The desired target frequency
+ */
+static void mtk_pll_calc_values(struct clk *clk, u32 *pcw, u32 *postdiv,
+				u32 freq)
+{
+	struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
+	const struct mtk_pll_data *pll = &priv->tree->plls[clk->id];
+	unsigned long fmin = 1000 * MHZ;
+	u64 _pcw;
+	u32 val;
+
+	if (freq > pll->fmax)
+		freq = pll->fmax;
+
+	for (val = 0; val < 5; val++) {
+		*postdiv = 1 << val;
+		if ((u64)freq * *postdiv >= fmin)
+			break;
+	}
+
+	/* _pcw = freq * postdiv / xtal_rate * 2^pcwfbits */
+	_pcw = ((u64)freq << val) << (pll->pcwbits - INTEGER_BITS);
+	do_div(_pcw, priv->tree->xtal2_rate);
+
+	*pcw = (u32)_pcw;
+}
+
+static ulong mtk_apmixedsys_set_rate(struct clk *clk, ulong rate)
+{
+	u32 pcw = 0;
+	u32 postdiv;
+
+	mtk_pll_calc_values(clk, &pcw, &postdiv, rate);
+	mtk_pll_set_rate_regs(clk, pcw, postdiv);
+
+	return 0;
+}
+
+static ulong mtk_apmixedsys_get_rate(struct clk *clk)
+{
+	struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
+	const struct mtk_pll_data *pll = &priv->tree->plls[clk->id];
+	u32 postdiv;
+	u32 pcw;
+
+	postdiv = (readl(priv->base + pll->pd_reg) >> pll->pd_shift) &
+		   POSTDIV_MASK;
+	postdiv = 1 << postdiv;
+
+	pcw = readl(priv->base + pll->pcw_reg) >> pll->pcw_shift;
+	pcw &= GENMASK(pll->pcwbits - 1, 0);
+
+	return __mtk_pll_recalc_rate(pll, priv->tree->xtal2_rate,
+				     pcw, postdiv);
+}
+
+static int mtk_apmixedsys_enable(struct clk *clk)
+{
+	struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
+	const struct mtk_pll_data *pll = &priv->tree->plls[clk->id];
+	u32 r;
+
+	r = readl(priv->base + pll->pwr_reg) | CON0_PWR_ON;
+	writel(r, priv->base + pll->pwr_reg);
+	udelay(1);
+
+	r = readl(priv->base + pll->pwr_reg) & ~CON0_ISO_EN;
+	writel(r, priv->base + pll->pwr_reg);
+	udelay(1);
+
+	r = readl(priv->base + pll->reg + REG_CON0);
+	r |= pll->en_mask;
+	writel(r, priv->base + pll->reg + REG_CON0);
+
+	udelay(20);
+
+	if (pll->flags & HAVE_RST_BAR) {
+		r = readl(priv->base + pll->reg + REG_CON0);
+		r |= pll->rst_bar_mask;
+		writel(r, priv->base + pll->reg + REG_CON0);
+	}
+
+	return 0;
+}
+
+static int mtk_apmixedsys_disable(struct clk *clk)
+{
+	struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
+	const struct mtk_pll_data *pll = &priv->tree->plls[clk->id];
+	u32 r;
+
+	if (pll->flags & HAVE_RST_BAR) {
+		r = readl(priv->base + pll->reg + REG_CON0);
+		r &= ~pll->rst_bar_mask;
+		writel(r, priv->base + pll->reg + REG_CON0);
+	}
+
+	r = readl(priv->base + pll->reg + REG_CON0);
+	r &= ~CON0_BASE_EN;
+	writel(r, priv->base + pll->reg + REG_CON0);
+
+	r = readl(priv->base + pll->pwr_reg) | CON0_ISO_EN;
+	writel(r, priv->base + pll->pwr_reg);
+
+	r = readl(priv->base + pll->pwr_reg) & ~CON0_PWR_ON;
+	writel(r, priv->base + pll->pwr_reg);
+
+	return 0;
+}
+
+/* topckgen functions */
+
+static ulong mtk_factor_recalc_rate(const struct mtk_fixed_factor *fdiv,
+				    ulong parent_rate)
+{
+	u64 rate = parent_rate * fdiv->mult;
+
+	do_div(rate, fdiv->div);
+
+	return rate;
+}
+
+static int mtk_topckgen_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_APMIXED:
+		rate = mtk_clk_find_parent_rate(clk, fdiv->parent,
+				DM_GET_DRIVER(mtk_clk_apmixedsys));
+		break;
+	case CLK_PARENT_TOPCKGEN:
+		rate = mtk_clk_find_parent_rate(clk, fdiv->parent, NULL);
+		break;
+
+	default:
+		rate = priv->tree->xtal_rate;
+	}
+
+	return mtk_factor_recalc_rate(fdiv, rate);
+}
+
+static int mtk_topckgen_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])
+		return mtk_clk_find_parent_rate(clk, mux->parent[index],
+						NULL);
+
+	return priv->tree->xtal_rate;
+}
+
+static ulong mtk_topckgen_get_rate(struct clk *clk)
+{
+	struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
+
+	if (clk->id < priv->tree->fdivs_offs)
+		return priv->tree->fclks[clk->id].rate;
+	else if (clk->id < priv->tree->muxes_offs)
+		return mtk_topckgen_get_factor_rate(clk, clk->id -
+						    priv->tree->fdivs_offs);
+	else
+		return mtk_topckgen_get_mux_rate(clk, clk->id -
+						 priv->tree->muxes_offs);
+}
+
+static int mtk_topckgen_enable(struct clk *clk)
+{
+	struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
+	const struct mtk_composite *mux;
+	u32 val;
+
+	if (clk->id < priv->tree->muxes_offs)
+		return 0;
+
+	mux = &priv->tree->muxes[clk->id - priv->tree->muxes_offs];
+	if (mux->gate_shift < 0)
+		return 0;
+
+	/* enable clock gate */
+	val = readl(priv->base + mux->gate_reg);
+	val &= ~BIT(mux->gate_shift);
+	writel(val, priv->base + mux->gate_reg);
+
+	if (mux->flags & CLK_DOMAIN_SCPSYS) {
+		/* enable scpsys clock off control */
+		writel(SCP_ARMCK_OFF_EN, priv->base + CLK_SCP_CFG0);
+		writel(SCP_AXICK_DCM_DIS_EN | SCP_AXICK_26M_SEL_EN,
+		       priv->base + CLK_SCP_CFG1);
+	}
+
+	return 0;
+}
+
+static int mtk_topckgen_disable(struct clk *clk)
+{
+	struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
+	const struct mtk_composite *mux;
+	u32 val;
+
+	if (clk->id < priv->tree->muxes_offs)
+		return 0;
+
+	mux = &priv->tree->muxes[clk->id - priv->tree->muxes_offs];
+	if (mux->gate_shift < 0)
+		return 0;
+
+	/* disable clock gate */
+	val = readl(priv->base + mux->gate_reg);
+	val |= BIT(mux->gate_shift);
+	writel(val, priv->base + mux->gate_reg);
+
+	return 0;
+}
+
+static int mtk_topckgen_set_parent(struct clk *clk, struct clk *parent)
+{
+	struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
+
+	if (clk->id < priv->tree->muxes_offs)
+		return 0;
+
+	return mtk_clk_mux_set_parent(priv->base, parent->id,
+			&priv->tree->muxes[clk->id - priv->tree->muxes_offs]);
+}
+
+/* CG functions */
+
+static int mtk_clk_gate_enable(struct clk *clk)
+{
+	struct mtk_cg_priv *priv = dev_get_priv(clk->dev);
+	const struct mtk_gate *gate = &priv->gates[clk->id];
+	u32 bit = BIT(gate->shift);
+
+	switch (gate->flags & CLK_GATE_MASK) {
+	case CLK_GATE_SETCLR:
+		writel(bit, priv->base + gate->regs->clr_ofs);
+		break;
+	case CLK_GATE_NO_SETCLR_INV:
+		clrsetbits_le32(priv->base + gate->regs->sta_ofs, bit, bit);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int mtk_clk_gate_disable(struct clk *clk)
+{
+	struct mtk_cg_priv *priv = dev_get_priv(clk->dev);
+	const struct mtk_gate *gate = &priv->gates[clk->id];
+	u32 bit = BIT(gate->shift);
+
+	switch (gate->flags & CLK_GATE_MASK) {
+	case CLK_GATE_SETCLR:
+		writel(bit, priv->base + gate->regs->set_ofs);
+		break;
+	case CLK_GATE_NO_SETCLR_INV:
+		clrsetbits_le32(priv->base + gate->regs->sta_ofs, bit, 0);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+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_GET_DRIVER(mtk_clk_apmixedsys));
+		break;
+	case CLK_PARENT_TOPCKGEN:
+		return mtk_clk_find_parent_rate(clk, gate->parent,
+				DM_GET_DRIVER(mtk_clk_topckgen));
+		break;
+
+	default:
+		return priv->tree->xtal_rate;
+	}
+}
+
+const struct clk_ops mtk_clk_apmixedsys_ops = {
+	.enable = mtk_apmixedsys_enable,
+	.disable = mtk_apmixedsys_disable,
+	.set_rate = mtk_apmixedsys_set_rate,
+	.get_rate = mtk_apmixedsys_get_rate,
+};
+
+const struct clk_ops mtk_clk_topckgen_ops = {
+	.enable = mtk_topckgen_enable,
+	.disable = mtk_topckgen_disable,
+	.get_rate = mtk_topckgen_get_rate,
+	.set_parent = mtk_topckgen_set_parent,
+};
+
+const struct clk_ops mtk_clk_gate_ops = {
+	.enable = mtk_clk_gate_enable,
+	.disable = mtk_clk_gate_disable,
+	.get_rate = mtk_clk_gate_get_rate,
+};
+
+int mtk_clk_init(struct udevice *dev, const struct mtk_clk_tree *tree)
+{
+	struct mtk_clk_priv *priv = dev_get_priv(dev);
+
+	priv->base = dev_read_addr_ptr(dev);
+	if (!priv->base)
+		return -ENOENT;
+
+	priv->tree = tree;
+
+	return 0;
+}
+
+int mtk_clk_gate_init(struct udevice *dev,
+		      const struct mtk_clk_tree *tree,
+		      const struct mtk_gate *gates)
+{
+	struct mtk_cg_priv *priv = dev_get_priv(dev);
+
+	priv->base = dev_read_addr_ptr(dev);
+	if (!priv->base)
+		return -ENOENT;
+
+	priv->tree = tree;
+	priv->gates = gates;
+
+	return 0;
+}
diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
new file mode 100644
index 0000000..7889b01
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mtk.h
@@ -0,0 +1,153 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ * Author: Ryder Lee <ryder.lee@mediatek.com>
+ */
+
+#ifndef __DRV_CLK_MTK_H
+#define __DRV_CLK_MTK_H
+
+#define CLK_XTAL			0
+#define MHZ				(1000 * 1000)
+
+#define HAVE_RST_BAR			BIT(0)
+#define CLK_DOMAIN_SCPSYS		BIT(0)
+
+#define CLK_GATE_SETCLR			BIT(0)
+#define CLK_GATE_SETCLR_INV		BIT(1)
+#define CLK_GATE_NO_SETCLR		BIT(2)
+#define CLK_GATE_NO_SETCLR_INV		BIT(3)
+#define CLK_GATE_MASK			GENMASK(3, 0)
+
+#define CLK_PARENT_APMIXED		BIT(4)
+#define CLK_PARENT_TOPCKGEN		BIT(5)
+#define CLK_PARENT_MASK			GENMASK(5, 4)
+
+struct mtk_pll_data {
+	const int id;
+	u32 reg;
+	u32 pwr_reg;
+	u32 en_mask;
+	u32 pd_reg;
+	int pd_shift;
+	u32 flags;
+	u32 rst_bar_mask;
+	u64 fmax;
+	int pcwbits;
+	u32 pcw_reg;
+	int pcw_shift;
+};
+
+struct mtk_fixed_clk {
+	const int id;
+	const int parent;
+	unsigned long rate;
+};
+
+#define FIXED_CLK(_id, _parent, _rate) {		\
+		.id = _id,				\
+		.parent = _parent,			\
+		.rate = _rate,				\
+	}
+
+struct mtk_fixed_factor {
+	const int id;
+	const int parent;
+	u32 mult;
+	u32 div;
+	u32 flags;
+};
+
+#define FACTOR(_id, _parent, _mult, _div, _flags) {	\
+		.id = _id,				\
+		.parent = _parent,			\
+		.mult = _mult,				\
+		.div = _div,				\
+		.flags = _flags,			\
+	}
+
+struct mtk_composite {
+	const int id;
+	const int *parent;
+	u32 mux_reg;
+	u32 gate_reg;
+	u32 mux_mask;
+	signed char mux_shift;
+	signed char gate_shift;
+	signed char num_parents;
+	u16 flags;
+};
+
+#define MUX_GATE_FLAGS(_id, _parents, _reg, _shift, _width, _gate,	\
+		       _flags) {					\
+		.id = _id,						\
+		.mux_reg = _reg,					\
+		.mux_shift = _shift,					\
+		.mux_mask = BIT(_width) - 1,				\
+		.gate_reg = _reg,					\
+		.gate_shift = _gate,					\
+		.parent = _parents,					\
+		.num_parents = ARRAY_SIZE(_parents),			\
+		.flags = _flags,					\
+	}
+
+#define MUX_GATE(_id, _parents, _reg, _shift, _width, _gate)		\
+	MUX_GATE_FLAGS(_id, _parents, _reg, _shift, _width, _gate, 0)
+
+#define MUX(_id, _parents, _reg, _shift, _width) {			\
+		.id = _id,						\
+		.mux_reg = _reg,					\
+		.mux_shift = _shift,					\
+		.mux_mask = BIT(_width) - 1,				\
+		.gate_shift = -1,					\
+		.parent = _parents,					\
+		.num_parents = ARRAY_SIZE(_parents),			\
+		.flags = 0,						\
+	}
+
+struct mtk_gate_regs {
+	u32 sta_ofs;
+	u32 clr_ofs;
+	u32 set_ofs;
+};
+
+struct mtk_gate {
+	const int id;
+	const int parent;
+	const struct mtk_gate_regs *regs;
+	int shift;
+	u32 flags;
+};
+
+struct mtk_clk_tree {
+	unsigned long xtal_rate;
+	unsigned long xtal2_rate;
+	const int fdivs_offs;
+	const int muxes_offs;
+	const struct mtk_pll_data *plls;
+	const struct mtk_fixed_clk *fclks;
+	const struct mtk_fixed_factor *fdivs;
+	const struct mtk_composite *muxes;
+};
+
+struct mtk_clk_priv {
+	void __iomem *base;
+	const struct mtk_clk_tree *tree;
+};
+
+struct mtk_cg_priv {
+	void __iomem *base;
+	const struct mtk_clk_tree *tree;
+	const struct mtk_gate *gates;
+};
+
+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_gate_ops;
+
+int mtk_clk_init(struct udevice *dev, const struct mtk_clk_tree *tree);
+int mtk_clk_gate_init(struct udevice *dev,
+		      const struct mtk_clk_tree *tree,
+		      const struct mtk_gate *gates);
+
+#endif /* __DRV_CLK_MTK_H */
-- 
1.9.1

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

* [U-Boot] [PATCH v2 07/18] clk: MediaTek: add clock driver for MT7623 SoC.
  2018-10-12  7:00 [U-Boot] [PATCH v2 00/18] Add U-Boot support for MediaTek SoCs - MT7623n & MT7629 Ryder Lee
                   ` (5 preceding siblings ...)
  2018-10-12  7:00 ` [U-Boot] [PATCH v2 06/18] clk: MediaTek: add clock driver for MT7629 SoC Ryder Lee
@ 2018-10-12  7:00 ` Ryder Lee
  2018-10-25  3:29   ` Simon Glass
  2018-10-12  7:00 ` [U-Boot] [PATCH v2 08/18] timer: MediaTek: add timer driver for MediaTek SoCs Ryder Lee
                   ` (10 subsequent siblings)
  17 siblings, 1 reply; 57+ messages in thread
From: Ryder Lee @ 2018-10-12  7:00 UTC (permalink / raw)
  To: u-boot

This patch adds a driver for MT7623 clock blocks.

Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
Tested-by: Matthias Brugger <matthias.bgg@gmail.com>
---
 drivers/clk/mediatek/Makefile     |   1 +
 drivers/clk/mediatek/clk-mt7623.c | 870 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 871 insertions(+)
 create mode 100644 drivers/clk/mediatek/clk-mt7623.c

diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index 297f99d..0632dc8 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -3,4 +3,5 @@
 obj-$(CONFIG_ARCH_MEDIATEK) += clk-mtk.o
 
 # SoC Drivers
+obj-$(CONFIG_TARGET_MT7623) += clk-mt7623.o
 obj-$(CONFIG_TARGET_MT7629) += clk-mt7629.o
diff --git a/drivers/clk/mediatek/clk-mt7623.c b/drivers/clk/mediatek/clk-mt7623.c
new file mode 100644
index 0000000..ac4450e
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt7623.c
@@ -0,0 +1,870 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MediaTek clock driver for MT7623 SoC
+ *
+ * Copyright (C) 2018 MediaTek Inc.
+ * Author: Ryder Lee <ryder.lee@mediatek.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/io.h>
+#include <dt-bindings/clock/mt7623-clk.h>
+
+#include "clk-mtk.h"
+
+#define MT7623_CLKSQ_STB_CON0		0x18
+#define MT7623_PLL_ISO_CON0		0x24
+#define MT7623_PLL_FMAX			(2000UL * MHZ)
+#define MT7623_CON0_RST_BAR		BIT(27)
+
+#define MCU_AXI_DIV			0x60
+#define AXI_DIV_MSK			GENMASK(4, 0)
+#define AXI_DIV_SEL(x)			(x)
+
+/* apmixedsys */
+#define PLL(_id, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg,	\
+	    _pd_shift, _pcw_reg, _pcw_shift) {				\
+		.id = _id,						\
+		.reg = _reg,						\
+		.pwr_reg = _pwr_reg,					\
+		.en_mask = _en_mask,					\
+		.rst_bar_mask = MT7623_CON0_RST_BAR,			\
+		.fmax = MT7623_PLL_FMAX,				\
+		.flags = _flags,					\
+		.pcwbits = _pcwbits,					\
+		.pd_reg = _pd_reg,					\
+		.pd_shift = _pd_shift,					\
+		.pcw_reg = _pcw_reg,					\
+		.pcw_shift = _pcw_shift,				\
+	}
+
+static const struct mtk_pll_data apmixed_plls[] = {
+	PLL(CLK_APMIXED_ARMPLL, 0x200, 0x20c, 0x80000001, 0,
+	    21, 0x204, 24, 0x204, 0),
+	PLL(CLK_APMIXED_MAINPLL, 0x210, 0x21c, 0xf0000001, HAVE_RST_BAR,
+	    21, 0x210, 4, 0x214, 0),
+	PLL(CLK_APMIXED_UNIVPLL, 0x220, 0x22c, 0xf3000001, HAVE_RST_BAR,
+	    7, 0x220, 4, 0x224, 14),
+	PLL(CLK_APMIXED_MMPLL, 0x230, 0x23c, 0x00000001, 0,
+	    21, 0x230, 4, 0x234, 0),
+	PLL(CLK_APMIXED_MSDCPLL, 0x240, 0x24c, 0x00000001, 0,
+	    21, 0x240, 4, 0x244, 0),
+	PLL(CLK_APMIXED_TVDPLL, 0x250, 0x25c, 0x00000001, 0,
+	    21, 0x250, 4, 0x254, 0),
+	PLL(CLK_APMIXED_AUD1PLL, 0x270, 0x27c, 0x00000001, 0,
+	    31, 0x270, 4, 0x274, 0),
+	PLL(CLK_APMIXED_TRGPLL, 0x280, 0x28c, 0x00000001, 0,
+	    31, 0x280, 4, 0x284, 0),
+	PLL(CLK_APMIXED_ETHPLL, 0x290, 0x29c, 0x00000001, 0,
+	    31, 0x290, 4, 0x294, 0),
+	PLL(CLK_APMIXED_VDECPLL, 0x2a0, 0x2ac, 0x00000001, 0,
+	    31, 0x2a0, 4, 0x2a4, 0),
+	PLL(CLK_APMIXED_HADDS2PLL, 0x2b0, 0x2bc, 0x00000001, 0,
+	    31, 0x2b0, 4, 0x2b4, 0),
+	PLL(CLK_APMIXED_AUD2PLL, 0x2c0, 0x2cc, 0x00000001, 0,
+	    31, 0x2c0, 4, 0x2c4, 0),
+	PLL(CLK_APMIXED_TVD2PLL, 0x2d0, 0x2dc, 0x00000001, 0,
+	    21, 0x2d0, 4, 0x2d4, 0),
+};
+
+/* topckgen */
+#define FACTOR0(_id, _parent, _mult, _div)			\
+	FACTOR(_id, _parent, _mult, _div, CLK_PARENT_APMIXED)
+
+#define FACTOR1(_id, _parent, _mult, _div)			\
+	FACTOR(_id, _parent, _mult, _div, CLK_PARENT_TOPCKGEN)
+
+#define FACTOR2(_id, _parent, _mult, _div)			\
+	FACTOR(_id, _parent, _mult, _div, 0)
+
+static const struct mtk_fixed_clk top_fixed_clks[] = {
+	FIXED_CLK(CLK_TOP_DPI, CLK_XTAL, 108 * MHZ),
+	FIXED_CLK(CLK_TOP_DMPLL, CLK_XTAL, 400 * MHZ),
+	FIXED_CLK(CLK_TOP_VENCPLL, CLK_XTAL, 295.75 * MHZ),
+	FIXED_CLK(CLK_TOP_HDMI_0_PIX340M, CLK_XTAL, 340 * MHZ),
+	FIXED_CLK(CLK_TOP_HDMI_0_DEEP340M, CLK_XTAL, 340 * MHZ),
+	FIXED_CLK(CLK_TOP_HDMI_0_PLL340M, CLK_XTAL, 340 * MHZ),
+	FIXED_CLK(CLK_TOP_HADDS2_FB, CLK_XTAL, 27 * MHZ),
+	FIXED_CLK(CLK_TOP_WBG_DIG_416M, CLK_XTAL, 416 * MHZ),
+	FIXED_CLK(CLK_TOP_DSI0_LNTC_DSI, CLK_XTAL, 143 * MHZ),
+	FIXED_CLK(CLK_TOP_HDMI_SCL_RX, CLK_XTAL, 27 * MHZ),
+	FIXED_CLK(CLK_TOP_32K_EXTERNAL, CLK_XTAL, 32000),
+	FIXED_CLK(CLK_TOP_HDMITX_CLKDIG_CTS, CLK_XTAL, 300 * MHZ),
+	FIXED_CLK(CLK_TOP_AUD_EXT1, CLK_XTAL, 0),
+	FIXED_CLK(CLK_TOP_AUD_EXT2, CLK_XTAL, 0),
+	FIXED_CLK(CLK_TOP_NFI1X_PAD, CLK_XTAL, 0),
+};
+
+static const struct mtk_fixed_factor top_fixed_divs[] = {
+	FACTOR0(CLK_TOP_SYSPLL, CLK_APMIXED_MAINPLL, 1, 1),
+	FACTOR0(CLK_TOP_SYSPLL_D2, CLK_APMIXED_MAINPLL, 1, 2),
+	FACTOR0(CLK_TOP_SYSPLL_D3, CLK_APMIXED_MAINPLL, 1, 3),
+	FACTOR0(CLK_TOP_SYSPLL_D5, CLK_APMIXED_MAINPLL, 1, 5),
+	FACTOR0(CLK_TOP_SYSPLL_D7, CLK_APMIXED_MAINPLL, 1, 7),
+	FACTOR1(CLK_TOP_SYSPLL1_D2, CLK_TOP_SYSPLL_D2, 1, 2),
+	FACTOR1(CLK_TOP_SYSPLL1_D4, CLK_TOP_SYSPLL_D2, 1, 4),
+	FACTOR1(CLK_TOP_SYSPLL1_D8, CLK_TOP_SYSPLL_D2, 1, 8),
+	FACTOR1(CLK_TOP_SYSPLL1_D16, CLK_TOP_SYSPLL_D2, 1, 16),
+	FACTOR1(CLK_TOP_SYSPLL2_D2, CLK_TOP_SYSPLL_D3, 1, 2),
+	FACTOR1(CLK_TOP_SYSPLL2_D4, CLK_TOP_SYSPLL_D3, 1, 4),
+	FACTOR1(CLK_TOP_SYSPLL2_D8, CLK_TOP_SYSPLL_D3, 1, 8),
+	FACTOR1(CLK_TOP_SYSPLL3_D2, CLK_TOP_SYSPLL_D5, 1, 2),
+	FACTOR1(CLK_TOP_SYSPLL3_D4, CLK_TOP_SYSPLL_D5, 1, 4),
+	FACTOR1(CLK_TOP_SYSPLL4_D2, CLK_TOP_SYSPLL_D7, 1, 2),
+	FACTOR1(CLK_TOP_SYSPLL4_D4, CLK_TOP_SYSPLL_D7, 1, 4),
+
+	FACTOR0(CLK_TOP_UNIVPLL, CLK_APMIXED_UNIVPLL, 1, 1),
+	FACTOR0(CLK_TOP_UNIVPLL_D2, CLK_APMIXED_UNIVPLL, 1, 2),
+	FACTOR0(CLK_TOP_UNIVPLL_D3, CLK_APMIXED_UNIVPLL, 1, 3),
+	FACTOR0(CLK_TOP_UNIVPLL_D5, CLK_APMIXED_UNIVPLL, 1, 5),
+	FACTOR0(CLK_TOP_UNIVPLL_D7, CLK_APMIXED_UNIVPLL, 1, 7),
+	FACTOR0(CLK_TOP_UNIVPLL_D26, CLK_APMIXED_UNIVPLL, 1, 26),
+	FACTOR0(CLK_TOP_UNIVPLL_D52, CLK_APMIXED_UNIVPLL, 1, 52),
+	FACTOR0(CLK_TOP_UNIVPLL_D108, CLK_APMIXED_UNIVPLL, 1, 108),
+	FACTOR0(CLK_TOP_USB_PHY48M, CLK_APMIXED_UNIVPLL, 1, 26),
+	FACTOR1(CLK_TOP_UNIVPLL1_D2, CLK_TOP_UNIVPLL_D2, 1, 2),
+	FACTOR1(CLK_TOP_UNIVPLL1_D4, CLK_TOP_UNIVPLL_D2, 1, 4),
+	FACTOR1(CLK_TOP_UNIVPLL1_D8, CLK_TOP_UNIVPLL_D2, 1, 8),
+	FACTOR1(CLK_TOP_UNIVPLL2_D2, CLK_TOP_UNIVPLL_D3, 1, 2),
+	FACTOR1(CLK_TOP_UNIVPLL2_D4, CLK_TOP_UNIVPLL_D3, 1, 4),
+	FACTOR1(CLK_TOP_UNIVPLL2_D8, CLK_TOP_UNIVPLL_D3, 1, 8),
+	FACTOR1(CLK_TOP_UNIVPLL2_D16, CLK_TOP_UNIVPLL_D3, 1, 16),
+	FACTOR1(CLK_TOP_UNIVPLL2_D32, CLK_TOP_UNIVPLL_D3, 1, 32),
+	FACTOR1(CLK_TOP_UNIVPLL3_D2, CLK_TOP_UNIVPLL_D5, 1, 2),
+	FACTOR1(CLK_TOP_UNIVPLL3_D4, CLK_TOP_UNIVPLL_D5, 1, 4),
+	FACTOR1(CLK_TOP_UNIVPLL3_D8, CLK_TOP_UNIVPLL_D5, 1, 8),
+
+	FACTOR0(CLK_TOP_MSDCPLL, CLK_APMIXED_MSDCPLL, 1, 1),
+	FACTOR0(CLK_TOP_MSDCPLL_D2, CLK_APMIXED_MSDCPLL, 1, 2),
+	FACTOR0(CLK_TOP_MSDCPLL_D4, CLK_APMIXED_MSDCPLL, 1, 4),
+	FACTOR0(CLK_TOP_MSDCPLL_D8, CLK_APMIXED_MSDCPLL, 1, 8),
+
+	FACTOR0(CLK_TOP_MMPLL, CLK_APMIXED_MMPLL, 1, 1),
+	FACTOR0(CLK_TOP_MMPLL_D2, CLK_APMIXED_MMPLL, 1, 2),
+
+	FACTOR1(CLK_TOP_DMPLL_D2, CLK_TOP_DMPLL, 1, 2),
+	FACTOR1(CLK_TOP_DMPLL_D4, CLK_TOP_DMPLL, 1, 4),
+	FACTOR1(CLK_TOP_DMPLL_X2, CLK_TOP_DMPLL, 1, 1),
+
+	FACTOR0(CLK_TOP_TVDPLL, CLK_APMIXED_TVDPLL, 1, 1),
+	FACTOR0(CLK_TOP_TVDPLL_D2, CLK_APMIXED_TVDPLL, 1, 2),
+	FACTOR0(CLK_TOP_TVDPLL_D4, CLK_APMIXED_TVDPLL, 1, 4),
+
+	FACTOR0(CLK_TOP_VDECPLL, CLK_APMIXED_VDECPLL, 1, 1),
+	FACTOR0(CLK_TOP_TVD2PLL, CLK_APMIXED_TVD2PLL, 1, 1),
+	FACTOR0(CLK_TOP_TVD2PLL_D2, CLK_APMIXED_TVD2PLL, 1, 2),
+
+	FACTOR1(CLK_TOP_MIPIPLL, CLK_TOP_DPI, 1, 1),
+	FACTOR1(CLK_TOP_MIPIPLL_D2, CLK_TOP_DPI, 1, 2),
+	FACTOR1(CLK_TOP_MIPIPLL_D4, CLK_TOP_DPI, 1, 4),
+
+	FACTOR1(CLK_TOP_HDMIPLL, CLK_TOP_HDMITX_CLKDIG_CTS, 1, 1),
+	FACTOR1(CLK_TOP_HDMIPLL_D2, CLK_TOP_HDMITX_CLKDIG_CTS, 1, 2),
+	FACTOR1(CLK_TOP_HDMIPLL_D3, CLK_TOP_HDMITX_CLKDIG_CTS, 1, 3),
+
+	FACTOR0(CLK_TOP_ARMPLL_1P3G, CLK_APMIXED_ARMPLL, 1, 1),
+
+	FACTOR1(CLK_TOP_AUDPLL, CLK_TOP_AUDPLL_MUX_SEL, 1, 1),
+	FACTOR1(CLK_TOP_AUDPLL_D4, CLK_TOP_AUDPLL_MUX_SEL, 1, 4),
+	FACTOR1(CLK_TOP_AUDPLL_D8, CLK_TOP_AUDPLL_MUX_SEL, 1, 8),
+	FACTOR1(CLK_TOP_AUDPLL_D16, CLK_TOP_AUDPLL_MUX_SEL, 1, 16),
+	FACTOR1(CLK_TOP_AUDPLL_D24, CLK_TOP_AUDPLL_MUX_SEL, 1, 24),
+
+	FACTOR0(CLK_TOP_AUD1PLL_98M, CLK_APMIXED_AUD1PLL, 1, 3),
+	FACTOR0(CLK_TOP_AUD2PLL_90M, CLK_APMIXED_AUD2PLL, 1, 3),
+	FACTOR0(CLK_TOP_HADDS2PLL_98M, CLK_APMIXED_HADDS2PLL, 1, 3),
+	FACTOR0(CLK_TOP_HADDS2PLL_294M, CLK_APMIXED_HADDS2PLL, 1, 1),
+	FACTOR0(CLK_TOP_ETHPLL_500M, CLK_APMIXED_ETHPLL, 1, 1),
+	FACTOR2(CLK_TOP_CLK26M_D8, CLK_XTAL, 1, 8),
+	FACTOR2(CLK_TOP_32K_INTERNAL, CLK_XTAL, 1, 793),
+	FACTOR1(CLK_TOP_AXISEL_D4, CLK_TOP_AXI_SEL, 1, 4),
+	FACTOR1(CLK_TOP_8BDAC, CLK_TOP_UNIVPLL_D2, 1, 1),
+};
+
+static const int axi_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_SYSPLL1_D2,
+	CLK_TOP_SYSPLL_D5,
+	CLK_TOP_SYSPLL1_D4,
+	CLK_TOP_UNIVPLL_D5,
+	CLK_TOP_UNIVPLL2_D2,
+	CLK_TOP_MMPLL_D2,
+	CLK_TOP_DMPLL_D2
+};
+
+static const int mem_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_DMPLL
+};
+
+static const int ddrphycfg_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_SYSPLL1_D8
+};
+
+static const int mm_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_VENCPLL,
+	CLK_TOP_SYSPLL1_D2,
+	CLK_TOP_SYSPLL1_D4,
+	CLK_TOP_UNIVPLL_D5,
+	CLK_TOP_UNIVPLL1_D2,
+	CLK_TOP_UNIVPLL2_D2,
+	CLK_TOP_DMPLL
+};
+
+static const int pwm_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_UNIVPLL2_D4,
+	CLK_TOP_UNIVPLL3_D2,
+	CLK_TOP_UNIVPLL1_D4
+};
+
+static const int vdec_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_VDECPLL,
+	CLK_TOP_SYSPLL_D5,
+	CLK_TOP_SYSPLL1_D4,
+	CLK_TOP_UNIVPLL_D5,
+	CLK_TOP_UNIVPLL2_D2,
+	CLK_TOP_VENCPLL,
+	CLK_TOP_MSDCPLL_D2,
+	CLK_TOP_MMPLL_D2
+};
+
+static const int mfg_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_MMPLL,
+	CLK_TOP_DMPLL_X2,
+	CLK_TOP_MSDCPLL,
+	CLK_XTAL,
+	CLK_TOP_SYSPLL_D3,
+	CLK_TOP_UNIVPLL_D3,
+	CLK_TOP_UNIVPLL1_D2
+};
+
+static const int camtg_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_UNIVPLL_D26,
+	CLK_TOP_UNIVPLL2_D2,
+	CLK_TOP_SYSPLL3_D2,
+	CLK_TOP_SYSPLL3_D4,
+	CLK_TOP_MSDCPLL_D2,
+	CLK_TOP_MMPLL_D2
+};
+
+static const int uart_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_UNIVPLL2_D8
+};
+
+static const int spi_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_SYSPLL3_D2,
+	CLK_TOP_SYSPLL4_D2,
+	CLK_TOP_UNIVPLL2_D4,
+	CLK_TOP_UNIVPLL1_D8
+};
+
+static const int usb20_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_UNIVPLL1_D8,
+	CLK_TOP_UNIVPLL3_D4
+};
+
+static const int msdc30_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_MSDCPLL_D2,
+	CLK_TOP_SYSPLL2_D2,
+	CLK_TOP_SYSPLL1_D4,
+	CLK_TOP_UNIVPLL1_D4,
+	CLK_TOP_UNIVPLL2_D4,
+};
+
+static const int aud_intbus_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_SYSPLL1_D4,
+	CLK_TOP_SYSPLL3_D2,
+	CLK_TOP_SYSPLL4_D2,
+	CLK_TOP_UNIVPLL3_D2,
+	CLK_TOP_UNIVPLL2_D4
+};
+
+static const int pmicspi_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_SYSPLL1_D8,
+	CLK_TOP_SYSPLL2_D4,
+	CLK_TOP_SYSPLL4_D2,
+	CLK_TOP_SYSPLL3_D4,
+	CLK_TOP_SYSPLL2_D8,
+	CLK_TOP_SYSPLL1_D16,
+	CLK_TOP_UNIVPLL3_D4,
+	CLK_TOP_UNIVPLL_D26,
+	CLK_TOP_DMPLL_D2,
+	CLK_TOP_DMPLL_D4
+};
+
+static const int scp_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_SYSPLL1_D8,
+	CLK_TOP_DMPLL_D2,
+	CLK_TOP_DMPLL_D4
+};
+
+static const int dpi0_tve_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_MIPIPLL,
+	CLK_TOP_MIPIPLL_D2,
+	CLK_TOP_MIPIPLL_D4,
+	CLK_XTAL,
+	CLK_TOP_TVDPLL,
+	CLK_TOP_TVDPLL_D2,
+	CLK_TOP_TVDPLL_D4
+};
+
+static const int dpi1_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_TVDPLL,
+	CLK_TOP_TVDPLL_D2,
+	CLK_TOP_TVDPLL_D4
+};
+
+static const int hdmi_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_HDMIPLL,
+	CLK_TOP_HDMIPLL_D2,
+	CLK_TOP_HDMIPLL_D3
+};
+
+static const int apll_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_AUDPLL,
+	CLK_TOP_AUDPLL_D4,
+	CLK_TOP_AUDPLL_D8,
+	CLK_TOP_AUDPLL_D16,
+	CLK_TOP_AUDPLL_D24,
+	CLK_XTAL,
+	CLK_XTAL
+};
+
+static const int rtc_parents[] = {
+	CLK_TOP_32K_INTERNAL,
+	CLK_TOP_32K_EXTERNAL,
+	CLK_XTAL,
+	CLK_TOP_UNIVPLL3_D8
+};
+
+static const int nfi2x_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_SYSPLL2_D2,
+	CLK_TOP_SYSPLL_D7,
+	CLK_TOP_UNIVPLL3_D2,
+	CLK_TOP_SYSPLL2_D4,
+	CLK_TOP_UNIVPLL3_D4,
+	CLK_TOP_SYSPLL4_D4,
+	CLK_XTAL
+};
+
+static const int emmc_hclk_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_SYSPLL1_D2,
+	CLK_TOP_SYSPLL1_D4,
+	CLK_TOP_SYSPLL2_D2
+};
+
+static const int flash_parents[] = {
+	CLK_TOP_CLK26M_D8,
+	CLK_XTAL,
+	CLK_TOP_SYSPLL2_D8,
+	CLK_TOP_SYSPLL3_D4,
+	CLK_TOP_UNIVPLL3_D4,
+	CLK_TOP_SYSPLL4_D2,
+	CLK_TOP_SYSPLL2_D4,
+	CLK_TOP_UNIVPLL2_D4
+};
+
+static const int di_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_TVD2PLL,
+	CLK_TOP_TVD2PLL_D2,
+	CLK_XTAL
+};
+
+static const int nr_osd_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_VENCPLL,
+	CLK_TOP_SYSPLL1_D2,
+	CLK_TOP_SYSPLL1_D4,
+	CLK_TOP_UNIVPLL_D5,
+	CLK_TOP_UNIVPLL1_D2,
+	CLK_TOP_UNIVPLL2_D2,
+	CLK_TOP_DMPLL
+};
+
+static const int hdmirx_bist_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_SYSPLL_D3,
+	CLK_XTAL,
+	CLK_TOP_SYSPLL1_D16,
+	CLK_TOP_SYSPLL4_D2,
+	CLK_TOP_SYSPLL1_D4,
+	CLK_TOP_VENCPLL,
+	CLK_XTAL
+};
+
+static const int intdir_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_MMPLL,
+	CLK_TOP_SYSPLL_D2,
+	CLK_TOP_UNIVPLL_D2
+};
+
+static const int asm_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_UNIVPLL2_D4,
+	CLK_TOP_UNIVPLL2_D2,
+	CLK_TOP_SYSPLL_D5
+};
+
+static const int ms_card_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_UNIVPLL3_D8,
+	CLK_TOP_SYSPLL4_D4
+};
+
+static const int ethif_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_SYSPLL1_D2,
+	CLK_TOP_SYSPLL_D5,
+	CLK_TOP_SYSPLL1_D4,
+	CLK_TOP_UNIVPLL_D5,
+	CLK_TOP_UNIVPLL1_D2,
+	CLK_TOP_DMPLL,
+	CLK_TOP_DMPLL_D2
+};
+
+static const int hdmirx_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_UNIVPLL_D52
+};
+
+static const int cmsys_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_SYSPLL1_D2,
+	CLK_TOP_UNIVPLL1_D2,
+	CLK_TOP_UNIVPLL_D5,
+	CLK_TOP_SYSPLL_D5,
+	CLK_TOP_SYSPLL2_D2,
+	CLK_TOP_SYSPLL1_D4,
+	CLK_TOP_SYSPLL3_D2,
+	CLK_TOP_SYSPLL2_D4,
+	CLK_TOP_SYSPLL1_D8,
+	CLK_XTAL,
+	CLK_XTAL,
+	CLK_XTAL,
+	CLK_XTAL,
+	CLK_XTAL
+};
+
+static const int clk_8bdac_parents[] = {
+	CLK_TOP_32K_INTERNAL,
+	CLK_TOP_8BDAC,
+	CLK_XTAL,
+	CLK_XTAL
+};
+
+static const int aud2dvd_parents[] = {
+	CLK_TOP_AUD_48K_TIMING,
+	CLK_TOP_AUD_44K_TIMING
+};
+
+static const int padmclk_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_UNIVPLL_D26,
+	CLK_TOP_UNIVPLL_D52,
+	CLK_TOP_UNIVPLL_D108,
+	CLK_TOP_UNIVPLL2_D8,
+	CLK_TOP_UNIVPLL2_D16,
+	CLK_TOP_UNIVPLL2_D32
+};
+
+static const int aud_mux_parents[] = {
+	CLK_XTAL,
+	CLK_TOP_AUD1PLL_98M,
+	CLK_TOP_AUD2PLL_90M,
+	CLK_TOP_HADDS2PLL_98M,
+	CLK_TOP_AUD_EXTCK1_DIV,
+	CLK_TOP_AUD_EXTCK2_DIV
+};
+
+static const int aud_src_parents[] = {
+	CLK_TOP_AUD_MUX1_SEL,
+	CLK_TOP_AUD_MUX2_SEL
+};
+
+static const struct mtk_composite top_muxes[] = {
+	MUX_GATE(CLK_TOP_AXI_SEL, axi_parents, 0x40, 0, 3, 7),
+	MUX_GATE(CLK_TOP_MEM_SEL, mem_parents, 0x40, 8, 1, 15),
+	MUX_GATE(CLK_TOP_DDRPHYCFG_SEL, ddrphycfg_parents, 0x40, 16, 1, 23),
+	MUX_GATE_FLAGS(CLK_TOP_MM_SEL, mm_parents, 0x40, 24, 3, 31,
+		       CLK_DOMAIN_SCPSYS),
+
+	MUX_GATE(CLK_TOP_PWM_SEL, pwm_parents, 0x50, 0, 2, 7),
+	MUX_GATE(CLK_TOP_VDEC_SEL, vdec_parents, 0x50, 8, 4, 15),
+	MUX_GATE_FLAGS(CLK_TOP_MFG_SEL, mfg_parents, 0x50, 16, 3, 23,
+		       CLK_DOMAIN_SCPSYS),
+	MUX_GATE(CLK_TOP_CAMTG_SEL, camtg_parents, 0x50, 24, 3, 31),
+
+	MUX_GATE(CLK_TOP_UART_SEL, uart_parents, 0x60, 0, 1, 7),
+	MUX_GATE(CLK_TOP_SPI0_SEL, spi_parents, 0x60, 8, 3, 15),
+	MUX_GATE(CLK_TOP_USB20_SEL, usb20_parents, 0x60, 16, 2, 23),
+	MUX_GATE(CLK_TOP_MSDC30_0_SEL, msdc30_parents, 0x60, 24, 3, 31),
+
+	MUX_GATE(CLK_TOP_MSDC30_1_SEL, msdc30_parents, 0x70, 0, 3, 7),
+	MUX_GATE(CLK_TOP_MSDC30_2_SEL, msdc30_parents, 0x70, 8, 3, 15),
+	MUX_GATE(CLK_TOP_AUDIO_SEL, msdc30_parents, 0x70, 16, 1, 23),
+	MUX_GATE(CLK_TOP_AUDINTBUS_SEL, aud_intbus_parents, 0x70, 24, 3, 31),
+
+	MUX_GATE(CLK_TOP_PMICSPI_SEL, pmicspi_parents, 0x80, 0, 4, 7),
+	MUX_GATE(CLK_TOP_SCP_SEL, scp_parents, 0x80, 8, 2, 15),
+	MUX_GATE(CLK_TOP_DPI0_SEL, dpi0_tve_parents, 0x80, 16, 3, 23),
+	MUX_GATE(CLK_TOP_DPI1_SEL, dpi1_parents, 0x80, 24, 2, 31),
+
+	MUX_GATE(CLK_TOP_TVE_SEL, dpi0_tve_parents, 0x90, 0, 3, 7),
+	MUX_GATE(CLK_TOP_HDMI_SEL, hdmi_parents, 0x90, 8, 2, 15),
+	MUX_GATE(CLK_TOP_APLL_SEL, apll_parents, 0x90, 16, 3, 23),
+
+	MUX_GATE(CLK_TOP_RTC_SEL, rtc_parents, 0xA0, 0, 2, 7),
+	MUX_GATE(CLK_TOP_NFI2X_SEL, nfi2x_parents, 0xA0, 8, 3, 15),
+	MUX_GATE(CLK_TOP_EMMC_HCLK_SEL, emmc_hclk_parents, 0xA0, 24, 2, 31),
+
+	MUX_GATE(CLK_TOP_FLASH_SEL, flash_parents, 0xB0, 0, 3, 7),
+	MUX_GATE(CLK_TOP_DI_SEL, di_parents, 0xB0, 8, 2, 15),
+	MUX_GATE(CLK_TOP_NR_SEL, nr_osd_parents, 0xB0, 16, 3, 23),
+	MUX_GATE(CLK_TOP_OSD_SEL, nr_osd_parents, 0xB0, 24, 3, 31),
+
+	MUX_GATE(CLK_TOP_HDMIRX_BIST_SEL, hdmirx_bist_parents, 0xC0, 0, 3, 7),
+	MUX_GATE(CLK_TOP_INTDIR_SEL, intdir_parents, 0xC0, 8, 2, 15),
+	MUX_GATE(CLK_TOP_ASM_I_SEL, asm_parents, 0xC0, 16, 2, 23),
+	MUX_GATE(CLK_TOP_ASM_M_SEL, asm_parents, 0xC0, 24, 3, 31),
+
+	MUX_GATE(CLK_TOP_ASM_H_SEL, asm_parents, 0xD0, 0, 2, 7),
+	MUX_GATE(CLK_TOP_MS_CARD_SEL, ms_card_parents, 0xD0, 16, 2, 23),
+	MUX_GATE_FLAGS(CLK_TOP_ETHIF_SEL, ethif_parents, 0xD0, 24, 3, 31,
+		       CLK_DOMAIN_SCPSYS),
+
+	MUX_GATE(CLK_TOP_HDMIRX26_24_SEL, hdmirx_parents, 0xE0, 0, 1, 7),
+	MUX_GATE(CLK_TOP_MSDC30_3_SEL, msdc30_parents, 0xE0, 8, 3, 15),
+	MUX_GATE(CLK_TOP_CMSYS_SEL, cmsys_parents, 0xE0, 16, 4, 23),
+
+	MUX_GATE(CLK_TOP_SPI1_SEL, spi_parents, 0xE0, 24, 3, 31),
+	MUX_GATE(CLK_TOP_SPI2_SEL, spi_parents, 0xF0, 0, 3, 7),
+	MUX_GATE(CLK_TOP_8BDAC_SEL, clk_8bdac_parents, 0xF0, 8, 2, 15),
+	MUX_GATE(CLK_TOP_AUD2DVD_SEL, aud2dvd_parents, 0xF0, 16, 1, 23),
+
+	MUX(CLK_TOP_PADMCLK_SEL, padmclk_parents, 0x100, 0, 3),
+
+	MUX(CLK_TOP_AUD_MUX1_SEL, aud_mux_parents, 0x12c, 0, 3),
+	MUX(CLK_TOP_AUD_MUX2_SEL, aud_mux_parents, 0x12c, 3, 3),
+	MUX(CLK_TOP_AUDPLL_MUX_SEL, aud_mux_parents, 0x12c, 6, 3),
+
+	MUX_GATE(CLK_TOP_AUD_K1_SRC_SEL, aud_src_parents, 0x12c, 15, 1, 23),
+	MUX_GATE(CLK_TOP_AUD_K2_SRC_SEL, aud_src_parents, 0x12c, 16, 1, 24),
+	MUX_GATE(CLK_TOP_AUD_K3_SRC_SEL, aud_src_parents, 0x12c, 17, 1, 25),
+	MUX_GATE(CLK_TOP_AUD_K4_SRC_SEL, aud_src_parents, 0x12c, 18, 1, 26),
+	MUX_GATE(CLK_TOP_AUD_K5_SRC_SEL, aud_src_parents, 0x12c, 19, 1, 27),
+	MUX_GATE(CLK_TOP_AUD_K6_SRC_SEL, aud_src_parents, 0x12c, 20, 1, 28),
+};
+
+/* infracfg */
+static const struct mtk_gate_regs infra_cg_regs = {
+	.set_ofs = 0x40,
+	.clr_ofs = 0x44,
+	.sta_ofs = 0x48,
+};
+
+#define GATE_INFRA(_id, _parent, _shift) {			\
+		.id = _id,					\
+		.parent = _parent,				\
+		.regs = &infra_cg_regs,				\
+		.shift = _shift,				\
+		.flags = CLK_GATE_SETCLR | CLK_PARENT_TOPCKGEN,	\
+	}
+
+static const struct mtk_gate infra_cgs[] = {
+	GATE_INFRA(CLK_INFRA_DBG, CLK_TOP_AXI_SEL, 0),
+	GATE_INFRA(CLK_INFRA_SMI, CLK_TOP_MM_SEL, 1),
+	GATE_INFRA(CLK_INFRA_QAXI_CM4, CLK_TOP_AXI_SEL, 2),
+	GATE_INFRA(CLK_INFRA_AUD_SPLIN_B, CLK_TOP_HADDS2PLL_294M, 4),
+	GATE_INFRA(CLK_INFRA_AUDIO, CLK_XTAL, 5),
+	GATE_INFRA(CLK_INFRA_EFUSE, CLK_XTAL, 6),
+	GATE_INFRA(CLK_INFRA_L2C_SRAM, CLK_TOP_MM_SEL, 7),
+	GATE_INFRA(CLK_INFRA_M4U, CLK_TOP_MEM_SEL, 8),
+	GATE_INFRA(CLK_INFRA_CONNMCU, CLK_TOP_WBG_DIG_416M, 12),
+	GATE_INFRA(CLK_INFRA_TRNG, CLK_TOP_AXI_SEL, 13),
+	GATE_INFRA(CLK_INFRA_RAMBUFIF, CLK_TOP_MEM_SEL, 14),
+	GATE_INFRA(CLK_INFRA_CPUM, CLK_TOP_MEM_SEL, 15),
+	GATE_INFRA(CLK_INFRA_KP, CLK_TOP_AXI_SEL, 16),
+	GATE_INFRA(CLK_INFRA_CEC, CLK_TOP_RTC_SEL, 18),
+	GATE_INFRA(CLK_INFRA_IRRX, CLK_TOP_AXI_SEL, 19),
+	GATE_INFRA(CLK_INFRA_PMICSPI, CLK_TOP_PMICSPI_SEL, 22),
+	GATE_INFRA(CLK_INFRA_PMICWRAP, CLK_TOP_AXI_SEL, 23),
+	GATE_INFRA(CLK_INFRA_DDCCI, CLK_TOP_AXI_SEL, 24),
+};
+
+/* pericfg */
+static const struct mtk_gate_regs peri0_cg_regs = {
+	.set_ofs = 0x8,
+	.clr_ofs = 0x10,
+	.sta_ofs = 0x18,
+};
+
+static const struct mtk_gate_regs peri1_cg_regs = {
+	.set_ofs = 0xC,
+	.clr_ofs = 0x14,
+	.sta_ofs = 0x1C,
+};
+
+#define GATE_PERI0(_id, _parent, _shift) {			\
+		.id = _id,					\
+		.parent = _parent,				\
+		.regs = &peri0_cg_regs,				\
+		.shift = _shift,				\
+		.flags = CLK_GATE_SETCLR | CLK_PARENT_TOPCKGEN,	\
+	}
+
+#define GATE_PERI1(_id, _parent, _shift) {			\
+		.id = _id,					\
+		.parent = _parent,				\
+		.regs = &peri1_cg_regs,				\
+		.shift = _shift,				\
+		.flags = CLK_GATE_SETCLR | CLK_PARENT_TOPCKGEN,	\
+	}
+
+static const struct mtk_gate peri_cgs[] = {
+	GATE_PERI0(CLK_PERI_NFI, CLK_TOP_NFI2X_SEL, 0),
+	GATE_PERI0(CLK_PERI_THERM, CLK_TOP_AXI_SEL, 1),
+	GATE_PERI0(CLK_PERI_PWM1, CLK_TOP_AXISEL_D4, 2),
+	GATE_PERI0(CLK_PERI_PWM2, CLK_TOP_AXISEL_D4, 3),
+	GATE_PERI0(CLK_PERI_PWM3, CLK_TOP_AXISEL_D4, 4),
+	GATE_PERI0(CLK_PERI_PWM4, CLK_TOP_AXISEL_D4, 5),
+	GATE_PERI0(CLK_PERI_PWM5, CLK_TOP_AXISEL_D4, 6),
+	GATE_PERI0(CLK_PERI_PWM6, CLK_TOP_AXISEL_D4, 7),
+	GATE_PERI0(CLK_PERI_PWM7, CLK_TOP_AXISEL_D4, 8),
+	GATE_PERI0(CLK_PERI_PWM, CLK_TOP_AXI_SEL, 9),
+	GATE_PERI0(CLK_PERI_USB0, CLK_TOP_USB20_SEL, 10),
+	GATE_PERI0(CLK_PERI_USB1, CLK_TOP_USB20_SEL, 11),
+	GATE_PERI0(CLK_PERI_AP_DMA, CLK_TOP_AXI_SEL, 12),
+	GATE_PERI0(CLK_PERI_MSDC30_0, CLK_TOP_MSDC30_0_SEL, 13),
+	GATE_PERI0(CLK_PERI_MSDC30_1, CLK_TOP_MSDC30_1_SEL, 14),
+	GATE_PERI0(CLK_PERI_MSDC30_2, CLK_TOP_MSDC30_2_SEL, 15),
+	GATE_PERI0(CLK_PERI_MSDC30_3, CLK_TOP_MSDC30_3_SEL, 16),
+	GATE_PERI0(CLK_PERI_MSDC50_3, CLK_TOP_EMMC_HCLK_SEL, 17),
+	GATE_PERI0(CLK_PERI_NLI, CLK_TOP_AXI_SEL, 18),
+	GATE_PERI0(CLK_PERI_UART0, CLK_TOP_AXI_SEL, 19),
+	GATE_PERI0(CLK_PERI_UART1, CLK_TOP_AXI_SEL, 20),
+	GATE_PERI0(CLK_PERI_UART2, CLK_TOP_AXI_SEL, 21),
+	GATE_PERI0(CLK_PERI_UART3, CLK_TOP_AXI_SEL, 22),
+	GATE_PERI0(CLK_PERI_BTIF, CLK_TOP_AXI_SEL, 23),
+	GATE_PERI0(CLK_PERI_I2C0, CLK_TOP_AXI_SEL, 24),
+	GATE_PERI0(CLK_PERI_I2C1, CLK_TOP_AXI_SEL, 25),
+	GATE_PERI0(CLK_PERI_I2C2, CLK_TOP_AXI_SEL, 26),
+	GATE_PERI0(CLK_PERI_I2C3, CLK_XTAL, 27),
+	GATE_PERI0(CLK_PERI_AUXADC, CLK_XTAL, 28),
+	GATE_PERI0(CLK_PERI_SPI0, CLK_TOP_SPI0_SEL, 29),
+	GATE_PERI0(CLK_PERI_ETH, CLK_XTAL, 30),
+	GATE_PERI0(CLK_PERI_USB0_MCU, CLK_TOP_AXI_SEL, 31),
+
+	GATE_PERI1(CLK_PERI_USB1_MCU, CLK_TOP_AXI_SEL, 0),
+	GATE_PERI1(CLK_PERI_USB_SLV, CLK_TOP_AXI_SEL, 1),
+	GATE_PERI1(CLK_PERI_GCPU, CLK_TOP_AXI_SEL, 2),
+	GATE_PERI1(CLK_PERI_NFI_ECC, CLK_TOP_NFI1X_PAD, 3),
+	GATE_PERI1(CLK_PERI_NFI_PAD, CLK_TOP_NFI1X_PAD, 4),
+	GATE_PERI1(CLK_PERI_FLASH, CLK_TOP_NFI2X_SEL, 5),
+	GATE_PERI1(CLK_PERI_HOST89_INT, CLK_TOP_AXI_SEL, 6),
+	GATE_PERI1(CLK_PERI_HOST89_SPI, CLK_TOP_SPI0_SEL, 7),
+	GATE_PERI1(CLK_PERI_HOST89_DVD, CLK_TOP_AUD2DVD_SEL, 8),
+	GATE_PERI1(CLK_PERI_SPI1, CLK_TOP_SPI1_SEL, 9),
+	GATE_PERI1(CLK_PERI_SPI2, CLK_TOP_SPI2_SEL, 10),
+	GATE_PERI1(CLK_PERI_FCI, CLK_TOP_MS_CARD_SEL, 11),
+};
+
+/* ethsys */
+static const struct mtk_gate_regs eth_cg_regs = {
+	.sta_ofs = 0x30,
+};
+
+#define GATE_ETH(_id, _parent, _shift, _flag) {			\
+		.id = _id,					\
+		.parent = _parent,				\
+		.regs = &eth_cg_regs,				\
+		.shift = _shift,				\
+		.flags = CLK_GATE_NO_SETCLR_INV | (_flag),	\
+	}
+
+#define GATE_ETH0(_id, _parent, _shift)				\
+	GATE_ETH(_id, _parent, _shift, CLK_PARENT_APMIXED)
+
+#define GATE_ETH1(_id, _parent, _shift)				\
+	GATE_ETH(_id, _parent, _shift, CLK_PARENT_TOPCKGEN)
+
+static const struct mtk_gate eth_cgs[] = {
+	GATE_ETH1(CLK_ETHSYS_HSDMA, CLK_TOP_ETHIF_SEL, 5),
+	GATE_ETH1(CLK_ETHSYS_ESW, CLK_TOP_ETHPLL_500M, 6),
+	GATE_ETH0(CLK_ETHSYS_GP2, CLK_APMIXED_TRGPLL, 7),
+	GATE_ETH1(CLK_ETHSYS_GP1, CLK_TOP_ETHPLL_500M, 8),
+	GATE_ETH1(CLK_ETHSYS_PCM, CLK_TOP_ETHIF_SEL, 11),
+	GATE_ETH1(CLK_ETHSYS_GDMA, CLK_TOP_ETHIF_SEL, 14),
+	GATE_ETH1(CLK_ETHSYS_I2S, CLK_TOP_ETHIF_SEL, 17),
+	GATE_ETH1(CLK_ETHSYS_CRYPTO, CLK_TOP_ETHIF_SEL, 29),
+};
+
+static const struct mtk_clk_tree mt7623_clk_tree = {
+	.xtal_rate = 26 * MHZ,
+	.xtal2_rate = 26 * MHZ,
+	.fdivs_offs = CLK_TOP_SYSPLL,
+	.muxes_offs = CLK_TOP_AXI_SEL,
+	.plls = apmixed_plls,
+	.fclks = top_fixed_clks,
+	.fdivs = top_fixed_divs,
+	.muxes = top_muxes,
+};
+
+static int mt7623_mcucfg_probe(struct udevice *dev)
+{
+	void __iomem *base;
+
+	base = dev_read_addr_ptr(dev);
+	if (!base)
+		return -ENOENT;
+
+	clrsetbits_le32(base + MCU_AXI_DIV, AXI_DIV_MSK,
+			AXI_DIV_SEL(0x12));
+
+	return 0;
+}
+
+static int mt7623_apmixedsys_probe(struct udevice *dev)
+{
+	struct mtk_clk_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	ret = mtk_clk_init(dev, &mt7623_clk_tree);
+	if (ret)
+		return ret;
+
+	/* reduce clock square disable time */
+	writel(0x50001, priv->base + MT7623_CLKSQ_STB_CON0);
+	/* extend control timing to 1us */
+	writel(0x888, priv->base + MT7623_PLL_ISO_CON0);
+
+	return 0;
+}
+
+static int mt7623_topckgen_probe(struct udevice *dev)
+{
+	return mtk_clk_init(dev, &mt7623_clk_tree);
+}
+
+static int mt7623_infracfg_probe(struct udevice *dev)
+{
+	return mtk_clk_gate_init(dev, &mt7623_clk_tree, infra_cgs);
+}
+
+static int mt7623_pericfg_probe(struct udevice *dev)
+{
+	return mtk_clk_gate_init(dev, &mt7623_clk_tree, peri_cgs);
+}
+
+static int mt7623_ethsys_probe(struct udevice *dev)
+{
+	return mtk_clk_gate_init(dev, &mt7623_clk_tree, eth_cgs);
+}
+
+static const struct udevice_id mt7623_apmixed_compat[] = {
+	{ .compatible = "mediatek,mt7623-apmixedsys" },
+	{ }
+};
+
+static const struct udevice_id mt7623_topckgen_compat[] = {
+	{ .compatible = "mediatek,mt7623-topckgen" },
+	{ }
+};
+
+static const struct udevice_id mt7623_infracfg_compat[] = {
+	{ .compatible = "mediatek,mt7623-infracfg", },
+	{ }
+};
+
+static const struct udevice_id mt7623_pericfg_compat[] = {
+	{ .compatible = "mediatek,mt7623-pericfg", },
+	{ }
+};
+
+static const struct udevice_id mt7623_ethsys_compat[] = {
+	{ .compatible = "mediatek,mt7623-ethsys" },
+	{ }
+};
+
+static const struct udevice_id mt7623_mcucfg_compat[] = {
+	{ .compatible = "mediatek,mt7623-mcucfg" },
+	{ }
+};
+
+U_BOOT_DRIVER(mtk_mcucfg) = {
+	.name = "mt7623-mcucfg",
+	.id = UCLASS_SYSCON,
+	.of_match = mt7623_mcucfg_compat,
+	.probe = mt7623_mcucfg_probe,
+	.flags = DM_FLAG_PRE_RELOC,
+};
+
+U_BOOT_DRIVER(mtk_clk_apmixedsys) = {
+	.name = "mt7623-clock-apmixedsys",
+	.id = UCLASS_CLK,
+	.of_match = mt7623_apmixed_compat,
+	.probe = mt7623_apmixedsys_probe,
+	.priv_auto_alloc_size = sizeof(struct mtk_clk_priv),
+	.ops = &mtk_clk_apmixedsys_ops,
+	.flags = DM_FLAG_PRE_RELOC,
+};
+
+U_BOOT_DRIVER(mtk_clk_topckgen) = {
+	.name = "mt7623-clock-topckgen",
+	.id = UCLASS_CLK,
+	.of_match = mt7623_topckgen_compat,
+	.probe = mt7623_topckgen_probe,
+	.priv_auto_alloc_size = sizeof(struct mtk_clk_priv),
+	.ops = &mtk_clk_topckgen_ops,
+	.flags = DM_FLAG_PRE_RELOC,
+};
+
+U_BOOT_DRIVER(mtk_clk_infracfg) = {
+	.name = "mt7623-infracfg",
+	.id = UCLASS_CLK,
+	.of_match = mt7623_infracfg_compat,
+	.probe = mt7623_infracfg_probe,
+	.priv_auto_alloc_size = sizeof(struct mtk_cg_priv),
+	.ops = &mtk_clk_gate_ops,
+	.flags = DM_FLAG_PRE_RELOC,
+};
+
+U_BOOT_DRIVER(mtk_clk_pericfg) = {
+	.name = "mt7623-pericfg",
+	.id = UCLASS_CLK,
+	.of_match = mt7623_pericfg_compat,
+	.probe = mt7623_pericfg_probe,
+	.priv_auto_alloc_size = sizeof(struct mtk_cg_priv),
+	.ops = &mtk_clk_gate_ops,
+	.flags = DM_FLAG_PRE_RELOC,
+};
+
+U_BOOT_DRIVER(mtk_clk_ethsys) = {
+	.name = "mt7623-clock-ethsys",
+	.id = UCLASS_CLK,
+	.of_match = mt7623_ethsys_compat,
+	.probe = mt7623_ethsys_probe,
+	.priv_auto_alloc_size = sizeof(struct mtk_cg_priv),
+	.ops = &mtk_clk_gate_ops,
+};
-- 
1.9.1

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

* [U-Boot] [PATCH v2 08/18] timer: MediaTek: add timer driver for MediaTek SoCs
  2018-10-12  7:00 [U-Boot] [PATCH v2 00/18] Add U-Boot support for MediaTek SoCs - MT7623n & MT7629 Ryder Lee
                   ` (6 preceding siblings ...)
  2018-10-12  7:00 ` [U-Boot] [PATCH v2 07/18] clk: MediaTek: add clock driver for MT7623 SoC Ryder Lee
@ 2018-10-12  7:00 ` Ryder Lee
  2018-10-25  3:29   ` Simon Glass
  2018-10-12  7:00 ` [U-Boot] [PATCH v2 09/18] watchdog: MediaTek: add watchdog " Ryder Lee
                   ` (9 subsequent siblings)
  17 siblings, 1 reply; 57+ messages in thread
From: Ryder Lee @ 2018-10-12  7:00 UTC (permalink / raw)
  To: u-boot

This patch adds clock source and clock event for the timer found
on the Mediatek SoCs.

Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
Tested-by: Matthias Brugger <matthias.bgg@gmail.com>
---
 drivers/timer/Kconfig     |  7 ++++
 drivers/timer/Makefile    |  1 +
 drivers/timer/mtk_timer.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 93 insertions(+)
 create mode 100644 drivers/timer/mtk_timer.c

diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig
index a7d600b..6013945 100644
--- a/drivers/timer/Kconfig
+++ b/drivers/timer/Kconfig
@@ -147,4 +147,11 @@ config MPC83XX_TIMER
 	  Select this to enable support for the timer found on
 	  devices based on the MPC83xx family of SoCs.
 
+config MTK_TIMER
+	bool "MediaTek timer support"
+	depends on TIMER
+	help
+	  Select this to enable support for the timer found on
+	  MediaTek devices.
+
 endmenu
diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile
index 7f19c49..c4fbab2 100644
--- a/drivers/timer/Makefile
+++ b/drivers/timer/Makefile
@@ -18,3 +18,4 @@ obj-$(CONFIG_SANDBOX_TIMER)	+= sandbox_timer.o
 obj-$(CONFIG_STI_TIMER)		+= sti-timer.o
 obj-$(CONFIG_STM32_TIMER)	+= stm32_timer.o
 obj-$(CONFIG_X86_TSC_TIMER)	+= tsc_timer.o
+obj-$(CONFIG_MTK_TIMER)		+= mtk_timer.o
diff --git a/drivers/timer/mtk_timer.c b/drivers/timer/mtk_timer.c
new file mode 100644
index 0000000..b5e76bd
--- /dev/null
+++ b/drivers/timer/mtk_timer.c
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MediaTek timer driver
+ *
+ * Copyright (C) 2018 MediaTek Inc.
+ * Author: Ryder Lee <ryder.lee@mediatek.com>
+ */
+
+#include <clk.h>
+#include <common.h>
+#include <dm.h>
+#include <timer.h>
+#include <asm/io.h>
+
+#define MTK_GPT4_CTRL	0x40
+#define MTK_GPT4_CLK	0x44
+#define MTK_GPT4_CNT	0x48
+
+#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
+
+struct mtk_timer_priv {
+	void __iomem *base;
+};
+
+static int mtk_timer_get_count(struct udevice *dev, u64 *count)
+{
+	struct mtk_timer_priv *priv = dev_get_priv(dev);
+	u32 val = readl(priv->base + MTK_GPT4_CNT);
+
+	*count = timer_conv_64(val);
+
+	return 0;
+}
+
+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;
+
+	priv->base = dev_read_addr_ptr(dev);
+	if (!priv->base)
+		return -ENOENT;
+
+	ret = clk_get_by_index(dev, 0, &clk);
+	if (ret)
+		return ret;
+
+	ret = clk_get_by_index(dev, 1, &parent);
+	if (!ret) {
+		ret = clk_set_parent(&clk, &parent);
+		if (ret)
+			return ret;
+	}
+
+	uc_priv->clock_rate = clk_get_rate(&clk);
+	if (!uc_priv->clock_rate)
+		return -EINVAL;
+
+	return 0;
+}
+
+static const struct timer_ops mtk_timer_ops = {
+	.get_count = mtk_timer_get_count,
+};
+
+static const struct udevice_id mtk_timer_ids[] = {
+	{ .compatible = "mediatek,timer" },
+	{ }
+};
+
+U_BOOT_DRIVER(mtk_timer) = {
+	.name = "mtk_timer",
+	.id = UCLASS_TIMER,
+	.of_match = mtk_timer_ids,
+	.priv_auto_alloc_size = sizeof(struct mtk_timer_priv),
+	.probe = mtk_timer_probe,
+	.ops = &mtk_timer_ops,
+	.flags = DM_FLAG_PRE_RELOC,
+};
-- 
1.9.1

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

* [U-Boot] [PATCH v2 09/18] watchdog: MediaTek: add watchdog driver for MediaTek SoCs
  2018-10-12  7:00 [U-Boot] [PATCH v2 00/18] Add U-Boot support for MediaTek SoCs - MT7623n & MT7629 Ryder Lee
                   ` (7 preceding siblings ...)
  2018-10-12  7:00 ` [U-Boot] [PATCH v2 08/18] timer: MediaTek: add timer driver for MediaTek SoCs Ryder Lee
@ 2018-10-12  7:00 ` Ryder Lee
  2018-10-25  3:29   ` Simon Glass
  2018-10-12  7:00 ` [U-Boot] [PATCH v2 10/18] pinctrl: MediaTek: add pinctrl driver for MT7629 SoC Ryder Lee
                   ` (8 subsequent siblings)
  17 siblings, 1 reply; 57+ messages in thread
From: Ryder Lee @ 2018-10-12  7:00 UTC (permalink / raw)
  To: u-boot

This patch adds a common driver for the Mediatek SoC integrated
watchdog.

Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
Tested-by: Matthias Brugger <matthias.bgg@gmail.com>
---
 drivers/watchdog/Kconfig   |   8 +++
 drivers/watchdog/Makefile  |   1 +
 drivers/watchdog/mtk_wdt.c | 135 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 144 insertions(+)
 create mode 100644 drivers/watchdog/mtk_wdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index d545b3e..57a12f5 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -103,6 +103,14 @@ config WDT_CDNS
 	   Select this to enable Cadence watchdog timer, which can be found on some
 	   Xilinx Microzed Platform.
 
+config WDT_MTK
+	bool "MediaTek watchdog timer support"
+	depends on WDT && ARCH_MEDIATEK
+	help
+	  Select this to enable watchdog timer for MediaTek SoCs.
+	  The watchdog timer is stopped when initialized.
+	  It performs full SoC reset.
+
 config XILINX_TB_WATCHDOG
 	bool "Xilinx Axi watchdog timer support"
 	depends on WDT
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 08406ca..04fa4a6 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -23,3 +23,4 @@ obj-$(CONFIG_BCM2835_WDT)       += bcm2835_wdt.o
 obj-$(CONFIG_WDT_ORION) += orion_wdt.o
 obj-$(CONFIG_WDT_CDNS) += cdns_wdt.o
 obj-$(CONFIG_MPC8xx_WATCHDOG) += mpc8xx_wdt.o
+obj-$(CONFIG_WDT_MTK) += mtk_wdt.o
diff --git a/drivers/watchdog/mtk_wdt.c b/drivers/watchdog/mtk_wdt.c
new file mode 100644
index 0000000..0b50173
--- /dev/null
+++ b/drivers/watchdog/mtk_wdt.c
@@ -0,0 +1,135 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Watchdog driver for MediaTek SoCs
+ *
+ * Copyright (C) 2018 MediaTek Inc.
+ * Author: Ryder Lee <ryder.lee@mediatek.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <wdt.h>
+#include <asm/io.h>
+
+#define MTK_WDT_MODE			0x00
+#define MTK_WDT_LENGTH			0x04
+#define MTK_WDT_RESTART			0x08
+#define MTK_WDT_STATUS			0x0c
+#define MTK_WDT_INTERVAL		0x10
+#define MTK_WDT_SWRST			0x14
+#define MTK_WDT_REQ_MODE		0x30
+#define MTK_WDT_DEBUG_CTL		0x40
+
+#define WDT_MODE_KEY			(0x22 << 24)
+#define WDT_MODE_EN			BIT(0)
+#define WDT_MODE_EXTPOL			BIT(1)
+#define WDT_MODE_EXTEN			BIT(2)
+#define WDT_MODE_IRQ_EN			BIT(3)
+#define WDT_MODE_DUAL_EN		BIT(6)
+
+#define WDT_LENGTH_KEY			0x8
+#define WDT_LENGTH_TIMEOUT(n)		((n) << 5)
+
+#define WDT_RESTART_KEY			0x1971
+#define WDT_SWRST_KEY			0x1209
+
+struct mtk_wdt_priv {
+	void __iomem *base;
+};
+
+static int mtk_wdt_reset(struct udevice *dev)
+{
+	struct mtk_wdt_priv *priv = dev_get_priv(dev);
+
+	/* Reload watchdog duration */
+	writel(WDT_RESTART_KEY, priv->base + MTK_WDT_RESTART);
+
+	return 0;
+}
+
+static int mtk_wdt_stop(struct udevice *dev)
+{
+	struct mtk_wdt_priv *priv = dev_get_priv(dev);
+
+	clrsetbits_le32(priv->base + MTK_WDT_MODE, WDT_MODE_EN, WDT_MODE_KEY);
+
+	return 0;
+}
+
+static int mtk_wdt_expire_now(struct udevice *dev, ulong flags)
+{
+	struct mtk_wdt_priv *priv = dev_get_priv(dev);
+
+	/* Kick watchdog to prevent counter == 0 */
+	writel(WDT_RESTART_KEY, priv->base + MTK_WDT_RESTART);
+
+	/* Reset */
+	writel(WDT_SWRST_KEY, priv->base + MTK_WDT_SWRST);
+	hang();
+
+	return 0;
+}
+
+static void mtk_wdt_set_timeout(struct udevice *dev, unsigned int timeout)
+{
+	struct mtk_wdt_priv *priv = dev_get_priv(dev);
+
+	/*
+	 * One bit is the value of 512 ticks
+	 * The clock has 32 KHz
+	 */
+	timeout = WDT_LENGTH_TIMEOUT(timeout << 6) | WDT_LENGTH_KEY;
+	writel(timeout, priv->base + MTK_WDT_LENGTH);
+
+	mtk_wdt_reset(dev);
+}
+
+static int mtk_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
+{
+	struct mtk_wdt_priv *priv = dev_get_priv(dev);
+
+	mtk_wdt_set_timeout(dev, timeout);
+
+	/* Enable watchdog reset signal */
+	setbits_le32(priv->base + MTK_WDT_MODE,
+		     WDT_MODE_EN | WDT_MODE_KEY | WDT_MODE_EXTEN);
+
+	return 0;
+}
+
+static int mtk_wdt_probe(struct udevice *dev)
+{
+	struct mtk_wdt_priv *priv = dev_get_priv(dev);
+
+	priv->base = dev_read_addr_ptr(dev);
+	if (!priv->base)
+		return -ENOENT;
+
+	/* Clear status */
+	clrsetbits_le32(priv->base + MTK_WDT_MODE,
+			WDT_MODE_IRQ_EN | WDT_MODE_EXTPOL, WDT_MODE_KEY);
+
+	return mtk_wdt_stop(dev);
+}
+
+static const struct wdt_ops mtk_wdt_ops = {
+	.start = mtk_wdt_start,
+	.reset = mtk_wdt_reset,
+	.stop = mtk_wdt_stop,
+	.expire_now = mtk_wdt_expire_now,
+};
+
+static const struct udevice_id mtk_wdt_ids[] = {
+	{ .compatible = "mediatek,wdt"},
+	{}
+};
+
+U_BOOT_DRIVER(mtk_wdt) = {
+	.name = "mtk_wdt",
+	.id = UCLASS_WDT,
+	.of_match = mtk_wdt_ids,
+	.priv_auto_alloc_size = sizeof(struct mtk_wdt_priv),
+	.probe = mtk_wdt_probe,
+	.ops = &mtk_wdt_ops,
+	.flags = DM_FLAG_PRE_RELOC,
+};
-- 
1.9.1

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

* [U-Boot] [PATCH v2 10/18] pinctrl: MediaTek: add pinctrl driver for MT7629 SoC
  2018-10-12  7:00 [U-Boot] [PATCH v2 00/18] Add U-Boot support for MediaTek SoCs - MT7623n & MT7629 Ryder Lee
                   ` (8 preceding siblings ...)
  2018-10-12  7:00 ` [U-Boot] [PATCH v2 09/18] watchdog: MediaTek: add watchdog " Ryder Lee
@ 2018-10-12  7:00 ` Ryder Lee
  2018-10-25  3:29   ` Simon Glass
  2018-10-12  7:01 ` [U-Boot] [PATCH v2 11/18] pinctrl: MediaTek: add pinctrl driver for MT7623 SoC Ryder Lee
                   ` (7 subsequent siblings)
  17 siblings, 1 reply; 57+ messages in thread
From: Ryder Lee @ 2018-10-12  7:00 UTC (permalink / raw)
  To: u-boot

This patch adds pinctrl support for MT7629 SoC. The IO core found on
the SoC has the registers for pinctrl, pinconf and gpio mixed up in
the same register range.  Hence the driver also implements the gpio
functionality through UCLASS_GPIO.

This also creates a common file as there might be other chips that use
the same binding and driver, then being a little more abstract could
help in the long run.

Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
---
 arch/arm/include/asm/arch-mediatek/gpio.h     |   9 +
 drivers/pinctrl/Kconfig                       |   1 +
 drivers/pinctrl/Makefile                      |   1 +
 drivers/pinctrl/mediatek/Kconfig              |  11 +
 drivers/pinctrl/mediatek/Makefile             |   6 +
 drivers/pinctrl/mediatek/pinctrl-mt7629.c     | 488 +++++++++++++++++++++++
 drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 552 ++++++++++++++++++++++++++
 drivers/pinctrl/mediatek/pinctrl-mtk-common.h | 182 +++++++++
 8 files changed, 1250 insertions(+)
 create mode 100644 arch/arm/include/asm/arch-mediatek/gpio.h
 create mode 100644 drivers/pinctrl/mediatek/Kconfig
 create mode 100644 drivers/pinctrl/mediatek/Makefile
 create mode 100644 drivers/pinctrl/mediatek/pinctrl-mt7629.c
 create mode 100644 drivers/pinctrl/mediatek/pinctrl-mtk-common.c
 create mode 100644 drivers/pinctrl/mediatek/pinctrl-mtk-common.h

diff --git a/arch/arm/include/asm/arch-mediatek/gpio.h b/arch/arm/include/asm/arch-mediatek/gpio.h
new file mode 100644
index 0000000..4ea1020
--- /dev/null
+++ b/arch/arm/include/asm/arch-mediatek/gpio.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ */
+
+#ifndef __MEDIATEK_GPIO_H
+#define __MEDIATEK_GPIO_H
+
+#endif	/* __MEDIATEK_GPIO_H */
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index ad0b8da..7e6fad3 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -301,6 +301,7 @@ config ASPEED_AST2500_PINCTRL
 endif
 
 source "drivers/pinctrl/meson/Kconfig"
+source "drivers/pinctrl/mediatek/Kconfig"
 source "drivers/pinctrl/nxp/Kconfig"
 source "drivers/pinctrl/renesas/Kconfig"
 source "drivers/pinctrl/uniphier/Kconfig"
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index a3a6c6d..293bad3 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_PINCTRL_UNIPHIER)	+= uniphier/
 obj-$(CONFIG_PINCTRL_PIC32)	+= pinctrl_pic32.o
 obj-$(CONFIG_PINCTRL_EXYNOS)	+= exynos/
 obj-$(CONFIG_PINCTRL_MESON)	+= meson/
+obj-$(CONFIG_PINCTRL_MTK)	+= mediatek/
 obj-$(CONFIG_ARCH_MVEBU)	+= mvebu/
 obj-$(CONFIG_PINCTRL_SINGLE)	+= pinctrl-single.o
 obj-$(CONFIG_PINCTRL_STI)	+= pinctrl-sti.o
diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig
new file mode 100644
index 0000000..e0145b1
--- /dev/null
+++ b/drivers/pinctrl/mediatek/Kconfig
@@ -0,0 +1,11 @@
+if ARCH_MEDIATEK
+
+config PINCTRL_MTK
+	depends on PINCTRL_GENERIC
+	bool
+
+config PINCTRL_MT7629
+	bool "MT7629 SoC pinctrl driver"
+	select PINCTRL_MTK
+
+endif
diff --git a/drivers/pinctrl/mediatek/Makefile b/drivers/pinctrl/mediatek/Makefile
new file mode 100644
index 0000000..cbf0765
--- /dev/null
+++ b/drivers/pinctrl/mediatek/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+# Core
+obj-$(CONFIG_PINCTRL_MTK) += pinctrl-mtk-common.o
+
+# SoC Drivers
+obj-$(CONFIG_PINCTRL_MT7629) += pinctrl-mt7629.o
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt7629.c b/drivers/pinctrl/mediatek/pinctrl-mt7629.c
new file mode 100644
index 0000000..1787937
--- /dev/null
+++ b/drivers/pinctrl/mediatek/pinctrl-mt7629.c
@@ -0,0 +1,488 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ * Author: Ryder Lee <ryder.lee@mediatek.com>
+ */
+
+#include <dm.h>
+
+#include "pinctrl-mtk-common.h"
+
+#define PIN_FIELD(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit, _x_bits)	\
+	PIN_FIELD_CALC(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit,	\
+		       _x_bits, 32, false)
+
+#define MT7629_PIN(_number, _name)	MTK_PIN(_number, _name, DRV_GRP1)
+
+static const struct mtk_pin_field_calc mt7629_pin_mode_range[] = {
+	PIN_FIELD(0, 78, 0x300, 0x10, 0, 4),
+};
+
+static const struct mtk_pin_field_calc mt7629_pin_dir_range[] = {
+	PIN_FIELD(0, 78, 0x0, 0x10, 0, 1),
+};
+
+static const struct mtk_pin_field_calc mt7629_pin_di_range[] = {
+	PIN_FIELD(0, 78, 0x200, 0x10, 0, 1),
+};
+
+static const struct mtk_pin_field_calc mt7629_pin_do_range[] = {
+	PIN_FIELD(0, 78, 0x100, 0x10, 0, 1),
+};
+
+static const struct mtk_pin_field_calc mt7629_pin_ies_range[] = {
+	PIN_FIELD(0, 10, 0x1000, 0x10, 0, 1),
+	PIN_FIELD(11, 18, 0x2000, 0x10, 0, 1),
+	PIN_FIELD(19, 32, 0x3000, 0x10, 0, 1),
+	PIN_FIELD(33, 48, 0x4000, 0x10, 0, 1),
+	PIN_FIELD(49, 50, 0x5000, 0x10, 0, 1),
+	PIN_FIELD(51, 69, 0x6000, 0x10, 0, 1),
+	PIN_FIELD(70, 78, 0x7000, 0x10, 0, 1),
+};
+
+static const struct mtk_pin_field_calc mt7629_pin_smt_range[] = {
+	PIN_FIELD(0, 10, 0x1100, 0x10, 0, 1),
+	PIN_FIELD(11, 18, 0x2100, 0x10, 0, 1),
+	PIN_FIELD(19, 32, 0x3100, 0x10, 0, 1),
+	PIN_FIELD(33, 48, 0x4100, 0x10, 0, 1),
+	PIN_FIELD(49, 50, 0x5100, 0x10, 0, 1),
+	PIN_FIELD(51, 69, 0x6100, 0x10, 0, 1),
+	PIN_FIELD(70, 78, 0x7100, 0x10, 0, 1),
+};
+
+static const struct mtk_pin_field_calc mt7629_pin_pullen_range[] = {
+	PIN_FIELD(0, 10, 0x1400, 0x10, 0, 1),
+	PIN_FIELD(11, 18, 0x2400, 0x10, 0, 1),
+	PIN_FIELD(19, 32, 0x3400, 0x10, 0, 1),
+	PIN_FIELD(33, 48, 0x4400, 0x10, 0, 1),
+	PIN_FIELD(49, 50, 0x5400, 0x10, 0, 1),
+	PIN_FIELD(51, 69, 0x6400, 0x10, 0, 1),
+	PIN_FIELD(70, 78, 0x7400, 0x10, 0, 1),
+};
+
+static const struct mtk_pin_field_calc mt7629_pin_pullsel_range[] = {
+	PIN_FIELD(0, 10, 0x1500, 0x10, 0, 1),
+	PIN_FIELD(11, 18, 0x2500, 0x10, 0, 1),
+	PIN_FIELD(19, 32, 0x3500, 0x10, 0, 1),
+	PIN_FIELD(33, 48, 0x4500, 0x10, 0, 1),
+	PIN_FIELD(49, 50, 0x5500, 0x10, 0, 1),
+	PIN_FIELD(51, 69, 0x6500, 0x10, 0, 1),
+	PIN_FIELD(70, 78, 0x7500, 0x10, 0, 1),
+};
+
+static const struct mtk_pin_field_calc mt7629_pin_drv_range[] = {
+	PIN_FIELD(0, 10, 0x1600, 0x10, 0, 4),
+	PIN_FIELD(11, 18, 0x2600, 0x10, 0, 4),
+	PIN_FIELD(19, 32, 0x3600, 0x10, 0, 4),
+	PIN_FIELD(33, 48, 0x4600, 0x10, 0, 4),
+	PIN_FIELD(49, 50, 0x5600, 0x10, 0, 4),
+	PIN_FIELD(51, 69, 0x6600, 0x10, 0, 4),
+	PIN_FIELD(70, 78, 0x7600, 0x10, 0, 4),
+};
+
+static const struct mtk_pin_reg_calc mt7629_reg_cals[] = {
+	[PINCTRL_PIN_REG_MODE] = MTK_RANGE(mt7629_pin_mode_range),
+	[PINCTRL_PIN_REG_DIR] = MTK_RANGE(mt7629_pin_dir_range),
+	[PINCTRL_PIN_REG_DI] = MTK_RANGE(mt7629_pin_di_range),
+	[PINCTRL_PIN_REG_DO] = MTK_RANGE(mt7629_pin_do_range),
+	[PINCTRL_PIN_REG_IES] = MTK_RANGE(mt7629_pin_ies_range),
+	[PINCTRL_PIN_REG_SMT] = MTK_RANGE(mt7629_pin_smt_range),
+	[PINCTRL_PIN_REG_PULLSEL] = MTK_RANGE(mt7629_pin_pullsel_range),
+	[PINCTRL_PIN_REG_PULLEN] = MTK_RANGE(mt7629_pin_pullen_range),
+	[PINCTRL_PIN_REG_DRV] = MTK_RANGE(mt7629_pin_drv_range),
+};
+
+static const struct mtk_pin_desc mt7629_pins[] = {
+	MT7629_PIN(0, "TOP_5G_CLK"),
+	MT7629_PIN(1, "TOP_5G_DATA"),
+	MT7629_PIN(2, "WF0_5G_HB0"),
+	MT7629_PIN(3, "WF0_5G_HB1"),
+	MT7629_PIN(4, "WF0_5G_HB2"),
+	MT7629_PIN(5, "WF0_5G_HB3"),
+	MT7629_PIN(6, "WF0_5G_HB4"),
+	MT7629_PIN(7, "WF0_5G_HB5"),
+	MT7629_PIN(8, "WF0_5G_HB6"),
+	MT7629_PIN(9, "XO_REQ"),
+	MT7629_PIN(10, "TOP_RST_N"),
+	MT7629_PIN(11, "SYS_WATCHDOG"),
+	MT7629_PIN(12, "EPHY_LED0_N_JTDO"),
+	MT7629_PIN(13, "EPHY_LED1_N_JTDI"),
+	MT7629_PIN(14, "EPHY_LED2_N_JTMS"),
+	MT7629_PIN(15, "EPHY_LED3_N_JTCLK"),
+	MT7629_PIN(16, "EPHY_LED4_N_JTRST_N"),
+	MT7629_PIN(17, "WF2G_LED_N"),
+	MT7629_PIN(18, "WF5G_LED_N"),
+	MT7629_PIN(19, "I2C_SDA"),
+	MT7629_PIN(20, "I2C_SCL"),
+	MT7629_PIN(21, "GPIO_9"),
+	MT7629_PIN(22, "GPIO_10"),
+	MT7629_PIN(23, "GPIO_11"),
+	MT7629_PIN(24, "GPIO_12"),
+	MT7629_PIN(25, "UART1_TXD"),
+	MT7629_PIN(26, "UART1_RXD"),
+	MT7629_PIN(27, "UART1_CTS"),
+	MT7629_PIN(28, "UART1_RTS"),
+	MT7629_PIN(29, "UART2_TXD"),
+	MT7629_PIN(30, "UART2_RXD"),
+	MT7629_PIN(31, "UART2_CTS"),
+	MT7629_PIN(32, "UART2_RTS"),
+	MT7629_PIN(33, "MDI_TP_P1"),
+	MT7629_PIN(34, "MDI_TN_P1"),
+	MT7629_PIN(35, "MDI_RP_P1"),
+	MT7629_PIN(36, "MDI_RN_P1"),
+	MT7629_PIN(37, "MDI_RP_P2"),
+	MT7629_PIN(38, "MDI_RN_P2"),
+	MT7629_PIN(39, "MDI_TP_P2"),
+	MT7629_PIN(40, "MDI_TN_P2"),
+	MT7629_PIN(41, "MDI_TP_P3"),
+	MT7629_PIN(42, "MDI_TN_P3"),
+	MT7629_PIN(43, "MDI_RP_P3"),
+	MT7629_PIN(44, "MDI_RN_P3"),
+	MT7629_PIN(45, "MDI_RP_P4"),
+	MT7629_PIN(46, "MDI_RN_P4"),
+	MT7629_PIN(47, "MDI_TP_P4"),
+	MT7629_PIN(48, "MDI_TN_P4"),
+	MT7629_PIN(49, "SMI_MDC"),
+	MT7629_PIN(50, "SMI_MDIO"),
+	MT7629_PIN(51, "PCIE_PERESET_N"),
+	MT7629_PIN(52, "PWM_0"),
+	MT7629_PIN(53, "GPIO_0"),
+	MT7629_PIN(54, "GPIO_1"),
+	MT7629_PIN(55, "GPIO_2"),
+	MT7629_PIN(56, "GPIO_3"),
+	MT7629_PIN(57, "GPIO_4"),
+	MT7629_PIN(58, "GPIO_5"),
+	MT7629_PIN(59, "GPIO_6"),
+	MT7629_PIN(60, "GPIO_7"),
+	MT7629_PIN(61, "GPIO_8"),
+	MT7629_PIN(62, "SPI_CLK"),
+	MT7629_PIN(63, "SPI_CS"),
+	MT7629_PIN(64, "SPI_MOSI"),
+	MT7629_PIN(65, "SPI_MISO"),
+	MT7629_PIN(66, "SPI_WP"),
+	MT7629_PIN(67, "SPI_HOLD"),
+	MT7629_PIN(68, "UART0_TXD"),
+	MT7629_PIN(69, "UART0_RXD"),
+	MT7629_PIN(70, "TOP_2G_CLK"),
+	MT7629_PIN(71, "TOP_2G_DATA"),
+	MT7629_PIN(72, "WF0_2G_HB0"),
+	MT7629_PIN(73, "WF0_2G_HB1"),
+	MT7629_PIN(74, "WF0_2G_HB2"),
+	MT7629_PIN(75, "WF0_2G_HB3"),
+	MT7629_PIN(76, "WF0_2G_HB4"),
+	MT7629_PIN(77, "WF0_2G_HB5"),
+	MT7629_PIN(78, "WF0_2G_HB6"),
+};
+
+/* 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.
+ */
+
+/* WF 5G */
+static int mt7629_wf0_5g_pins[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, };
+static int mt7629_wf0_5g_funcs[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, };
+
+/* LED for EPHY */
+static int mt7629_ephy_leds_pins[] = { 12, 13, 14, 15, 16, 17, 18, };
+static int mt7629_ephy_leds_funcs[] = { 1, 1, 1, 1, 1, 1, 1, };
+static int mt7629_ephy_led0_pins[] = { 12, };
+static int mt7629_ephy_led0_funcs[] = { 1, };
+static int mt7629_ephy_led1_pins[] = { 13, };
+static int mt7629_ephy_led1_funcs[] = { 1, };
+static int mt7629_ephy_led2_pins[] = { 14, };
+static int mt7629_ephy_led2_funcs[] = { 1, };
+static int mt7629_ephy_led3_pins[] = { 15, };
+static int mt7629_ephy_led3_funcs[] = { 1, };
+static int mt7629_ephy_led4_pins[] = { 16, };
+static int mt7629_ephy_led4_funcs[] = { 1, };
+static int mt7629_wf2g_led_pins[] = { 17, };
+static int mt7629_wf2g_led_funcs[] = { 1, };
+static int mt7629_wf5g_led_pins[] = { 18, };
+static int mt7629_wf5g_led_funcs[] = { 1, };
+
+/* Watchdog */
+static int mt7629_watchdog_pins[] = { 11, };
+static int mt7629_watchdog_funcs[] = { 1, };
+
+/* LED for GPHY */
+static int mt7629_gphy_leds_0_pins[] = { 21, 22, 23, };
+static int mt7629_gphy_leds_0_funcs[] = { 2, 2, 2, };
+static int mt7629_gphy_led1_0_pins[] = { 21, };
+static int mt7629_gphy_led1_0_funcs[] = { 2, };
+static int mt7629_gphy_led2_0_pins[] = { 22, };
+static int mt7629_gphy_led2_0_funcs[] = { 2, };
+static int mt7629_gphy_led3_0_pins[] = { 23, };
+static int mt7629_gphy_led3_0_funcs[] = { 2, };
+static int mt7629_gphy_leds_1_pins[] = { 57, 58, 59, };
+static int mt7629_gphy_leds_1_funcs[] = { 1, 1, 1, };
+static int mt7629_gphy_led1_1_pins[] = { 57, };
+static int mt7629_gphy_led1_1_funcs[] = { 1, };
+static int mt7629_gphy_led2_1_pins[] = { 58, };
+static int mt7629_gphy_led2_1_funcs[] = { 1, };
+static int mt7629_gphy_led3_1_pins[] = { 59, };
+static int mt7629_gphy_led3_1_funcs[] = { 1, };
+
+/* I2C */
+static int mt7629_i2c_0_pins[] = { 19, 20, };
+static int mt7629_i2c_0_funcs[] = { 1, 1, };
+static int mt7629_i2c_1_pins[] = { 53, 54, };
+static int mt7629_i2c_1_funcs[] = { 1, 1, };
+
+/* SPI */
+static int mt7629_spi_0_pins[] = { 21, 22, 23, 24, };
+static int mt7629_spi_0_funcs[] = { 1, 1, 1, 1, };
+static int mt7629_spi_1_pins[] = { 62, 63, 64, 65, };
+static int mt7629_spi_1_funcs[] = { 1, 1, 1, 1, };
+static int mt7629_spi_wp_pins[] = { 66, };
+static int mt7629_spi_wp_funcs[] = { 1, };
+static int mt7629_spi_hold_pins[] = { 67, };
+static int mt7629_spi_hold_funcs[] = { 1, };
+
+/* UART */
+static int mt7629_uart1_0_txd_rxd_pins[] = { 25, 26, };
+static int mt7629_uart1_0_txd_rxd_funcs[] = { 1, 1, };
+static int mt7629_uart1_1_txd_rxd_pins[] = { 53, 54, };
+static int mt7629_uart1_1_txd_rxd_funcs[] = { 2, 2, };
+static int mt7629_uart2_0_txd_rxd_pins[] = { 29, 30, };
+static int mt7629_uart2_0_txd_rxd_funcs[] = { 1, 1, };
+static int mt7629_uart2_1_txd_rxd_pins[] = { 57, 58, };
+static int mt7629_uart2_1_txd_rxd_funcs[] = { 2, 2, };
+static int mt7629_uart1_0_cts_rts_pins[] = { 27, 28, };
+static int mt7629_uart1_0_cts_rts_funcs[] = { 1, 1, };
+static int mt7629_uart1_1_cts_rts_pins[] = { 55, 56, };
+static int mt7629_uart1_1_cts_rts_funcs[] = { 2, 2, };
+static int mt7629_uart2_0_cts_rts_pins[] = { 31, 32, };
+static int mt7629_uart2_0_cts_rts_funcs[] = { 1, 1, };
+static int mt7629_uart2_1_cts_rts_pins[] = { 59, 60, };
+static int mt7629_uart2_1_cts_rts_funcs[] = { 2, 2, };
+static int mt7629_uart0_txd_rxd_pins[] = { 68, 69, };
+static int mt7629_uart0_txd_rxd_funcs[] = { 1, 1, };
+
+/* MDC/MDIO */
+static int mt7629_mdc_mdio_pins[] = { 49, 50, };
+static int mt7629_mdc_mdio_funcs[] = { 1, 1, };
+
+/* PCIE */
+static int mt7629_pcie_pereset_pins[] = { 51, };
+static int mt7629_pcie_pereset_funcs[] = { 1, };
+static int mt7629_pcie_wake_pins[] = { 55, };
+static int mt7629_pcie_wake_funcs[] = { 1, };
+static int mt7629_pcie_clkreq_pins[] = { 56, };
+static int mt7629_pcie_clkreq_funcs[] = { 1, };
+
+/* PWM */
+static int mt7629_pwm_0_pins[] = { 52, };
+static int mt7629_pwm_0_funcs[] = { 1, };
+static int mt7629_pwm_1_pins[] = { 61, };
+static int mt7629_pwm_1_funcs[] = { 2, };
+
+/* WF 2G */
+static int mt7629_wf0_2g_pins[] = { 70, 71, 72, 73, 74, 75, 76, 77, 78, };
+static int mt7629_wf0_2g_funcs[] = { 1, 1, 1, 1, 1, 1, 1, 1, };
+
+/* SNFI */
+static int mt7629_snfi_pins[] = { 62, 63, 64, 65, };
+static int mt7629_snfi_funcs[] = { 2, 2, 2, 2, };
+static int mt7629_snfi_wp_pins[] = { 66, };
+static int mt7629_snfi_wp_funcs[] = { 2, };
+static int mt7629_snfi_hold_pins[] = { 67, };
+static int mt7629_snfi_hold_funcs[] = { 2, };
+
+/* SPI NOR */
+static int mt7629_snor_io_pins[] = { 62, 63, 64, 65, };
+static int mt7629_snor_io_funcs[] = { 1, 1, 1, 1, };
+static int mt7629_snor_wp_pins[] = { 66, };
+static int mt7629_snor_wp_funcs[] = { 1, };
+static int mt7629_snor_hold_pins[] = { 67, };
+static int mt7629_snor_hold_funcs[] = { 1, };
+
+/* CONN_EXT_PRI */
+static int mt7629_conn_ext_pri_0_pins[] = { 21, };
+static int mt7629_conn_ext_pri_0_funcs[] = { 3, };
+static int mt7629_conn_ext_pri_1_pins[] = { 57, };
+static int mt7629_conn_ext_pri_1_funcs[] = { 3, };
+
+/* CONN_EXT_ACT */
+static int mt7629_conn_ext_act_0_pins[] = { 22, };
+static int mt7629_conn_ext_act_0_funcs[] = { 3, };
+static int mt7629_conn_ext_act_1_pins[] = { 58, };
+static int mt7629_conn_ext_act_1_funcs[] = { 3, };
+
+/* CONN_WLAN_ACT */
+static int mt7629_conn_wlan_act_0_pins[] = { 23, };
+static int mt7629_conn_wlan_act_0_funcs[] = { 3, };
+static int mt7629_conn_wlan_act_1_pins[] = { 59, };
+static int mt7629_conn_wlan_act_1_funcs[] = { 3, };
+
+/* EXT2BT_ACTIVE */
+static int mt7629_ext2bt_active_0_pins[] = { 30, };
+static int mt7629_ext2bt_active_0_funcs[] = { 3, };
+static int mt7629_ext2bt_active_1_pins[] = { 52, };
+static int mt7629_ext2bt_active_1_funcs[] = { 3, };
+
+/* EXT2WF_TX_ACTIVE */
+static int mt7629_ext2wf_tx_active_0_pins[] = { 31, };
+static int mt7629_ext2wf_tx_active_0_funcs[] = { 3, };
+static int mt7629_ext2wf_tx_active_1_pins[] = { 60, };
+static int mt7629_ext2wf_tx_active_1_funcs[] = { 3, };
+
+/* EXT2EXT_TX_ACTIVE */
+static int mt7629_ext2ext_tx_active_pins[] = { 32, };
+static int mt7629_ext2ext_tx_active_funcs[] = { 3, };
+
+/* WF2EXT_TX_ACTIVE */
+static int mt7629_wf2ext_tx_active_pins[] = { 61, };
+static int mt7629_wf2ext_tx_active_funcs[] = { 3, };
+
+static const struct mtk_group_desc mt7629_groups[] = {
+	PINCTRL_PIN_GROUP("wf0_5g", mt7629_wf0_5g),
+	PINCTRL_PIN_GROUP("ephy_leds", mt7629_ephy_leds),
+	PINCTRL_PIN_GROUP("ephy_led0", mt7629_ephy_led0),
+	PINCTRL_PIN_GROUP("ephy_led1", mt7629_ephy_led1),
+	PINCTRL_PIN_GROUP("ephy_led2", mt7629_ephy_led2),
+	PINCTRL_PIN_GROUP("ephy_led3", mt7629_ephy_led3),
+	PINCTRL_PIN_GROUP("ephy_led4", mt7629_ephy_led4),
+	PINCTRL_PIN_GROUP("wf2g_led", mt7629_wf2g_led),
+	PINCTRL_PIN_GROUP("wf5g_led", mt7629_wf5g_led),
+	PINCTRL_PIN_GROUP("watchdog", mt7629_watchdog),
+	PINCTRL_PIN_GROUP("gphy_leds_0", mt7629_gphy_leds_0),
+	PINCTRL_PIN_GROUP("gphy_led1_0", mt7629_gphy_led1_0),
+	PINCTRL_PIN_GROUP("gphy_led2_0", mt7629_gphy_led2_0),
+	PINCTRL_PIN_GROUP("gphy_led3_0", mt7629_gphy_led3_0),
+	PINCTRL_PIN_GROUP("gphy_leds_1", mt7629_gphy_leds_1),
+	PINCTRL_PIN_GROUP("gphy_led1_1", mt7629_gphy_led1_1),
+	PINCTRL_PIN_GROUP("gphy_led2_1", mt7629_gphy_led2_1),
+	PINCTRL_PIN_GROUP("gphy_led3_1", mt7629_gphy_led3_1),
+	PINCTRL_PIN_GROUP("i2c_0", mt7629_i2c_0),
+	PINCTRL_PIN_GROUP("i2c_1", mt7629_i2c_1),
+	PINCTRL_PIN_GROUP("spi_0", mt7629_spi_0),
+	PINCTRL_PIN_GROUP("spi_1", mt7629_spi_1),
+	PINCTRL_PIN_GROUP("spi_wp", mt7629_spi_wp),
+	PINCTRL_PIN_GROUP("spi_hold", mt7629_spi_hold),
+	PINCTRL_PIN_GROUP("uart1_0_txd_rxd", mt7629_uart1_0_txd_rxd),
+	PINCTRL_PIN_GROUP("uart1_1_txd_rxd", mt7629_uart1_1_txd_rxd),
+	PINCTRL_PIN_GROUP("uart2_0_txd_rxd", mt7629_uart2_0_txd_rxd),
+	PINCTRL_PIN_GROUP("uart2_1_txd_rxd", mt7629_uart2_1_txd_rxd),
+	PINCTRL_PIN_GROUP("uart1_0_cts_rts", mt7629_uart1_0_cts_rts),
+	PINCTRL_PIN_GROUP("uart1_1_cts_rts", mt7629_uart1_1_cts_rts),
+	PINCTRL_PIN_GROUP("uart2_0_cts_rts", mt7629_uart2_0_cts_rts),
+	PINCTRL_PIN_GROUP("uart2_1_cts_rts", mt7629_uart2_1_cts_rts),
+	PINCTRL_PIN_GROUP("uart0_txd_rxd", mt7629_uart0_txd_rxd),
+	PINCTRL_PIN_GROUP("mdc_mdio", mt7629_mdc_mdio),
+	PINCTRL_PIN_GROUP("pcie_pereset", mt7629_pcie_pereset),
+	PINCTRL_PIN_GROUP("pcie_wake", mt7629_pcie_wake),
+	PINCTRL_PIN_GROUP("pcie_clkreq", mt7629_pcie_clkreq),
+	PINCTRL_PIN_GROUP("pwm_0", mt7629_pwm_0),
+	PINCTRL_PIN_GROUP("pwm_1", mt7629_pwm_1),
+	PINCTRL_PIN_GROUP("wf0_2g", mt7629_wf0_2g),
+	PINCTRL_PIN_GROUP("snfi", mt7629_snfi),
+	PINCTRL_PIN_GROUP("snfi_wp", mt7629_snfi_wp),
+	PINCTRL_PIN_GROUP("snfi_hold", mt7629_snfi_hold),
+	PINCTRL_PIN_GROUP("snor_io", mt7629_snor_io),
+	PINCTRL_PIN_GROUP("snor_wp", mt7629_snor_wp),
+	PINCTRL_PIN_GROUP("snor_hold", mt7629_snor_hold),
+	PINCTRL_PIN_GROUP("conn_ext_pri_0", mt7629_conn_ext_pri_0),
+	PINCTRL_PIN_GROUP("conn_ext_pri_1", mt7629_conn_ext_pri_1),
+	PINCTRL_PIN_GROUP("conn_ext_act_0", mt7629_conn_ext_act_0),
+	PINCTRL_PIN_GROUP("conn_ext_act_1", mt7629_conn_ext_act_1),
+	PINCTRL_PIN_GROUP("conn_wlan_act_0", mt7629_conn_wlan_act_0),
+	PINCTRL_PIN_GROUP("conn_wlan_act_1", mt7629_conn_wlan_act_1),
+	PINCTRL_PIN_GROUP("ext2bt_active_0", mt7629_ext2bt_active_0),
+	PINCTRL_PIN_GROUP("ext2bt_active_1", mt7629_ext2bt_active_1),
+	PINCTRL_PIN_GROUP("ext2wf_tx_active_0", mt7629_ext2wf_tx_active_0),
+	PINCTRL_PIN_GROUP("ext2wf_tx_active_1", mt7629_ext2wf_tx_active_1),
+	PINCTRL_PIN_GROUP("ext2ext_tx_active", mt7629_ext2ext_tx_active),
+	PINCTRL_PIN_GROUP("wf2ext_tx_active", mt7629_wf2ext_tx_active),
+};
+
+/* 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 mt7629_ethernet_groups[] = { "wf0_5g", "wf0_2g",
+						"mdc_mdio", };
+static const char *const mt7629_i2c_groups[] = { "i2c_0", "i2c_1", };
+static const char *const mt7629_led_groups[] = { "ephy_leds", "ephy_led0",
+						"ephy_led1", "ephy_led2",
+						"ephy_led3", "ephy_led4",
+						"wf2g_led", "wf5g_led",
+						"gphy_leds_0", "gphy_led1_0",
+						"gphy_led2_0", "gphy_led3_0",
+						"gphy_leds_1", "gphy_led1_1",
+						"gphy_led2_1", "gphy_led3_1",};
+static const char *const mt7629_pcie_groups[] = { "pcie_pereset", "pcie_wake",
+						"pcie_clkreq", };
+static const char *const mt7629_pwm_groups[] = { "pwm_0", "pwm_1", };
+static const char *const mt7629_spi_groups[] = { "spi_0", "spi_1", "spi_wp",
+						"spi_hold", };
+static const char *const mt7629_uart_groups[] = { "uart1_0_txd_rxd",
+						"uart1_1_txd_rxd",
+						"uart2_0_txd_rxd",
+						"uart2_1_txd_rxd",
+						"uart1_0_cts_rts",
+						"uart1_1_cts_rts",
+						"uart2_0_cts_rts",
+						"uart2_1_cts_rts",
+						"uart0_txd_rxd", };
+static const char *const mt7629_wdt_groups[] = { "watchdog", };
+static const char *const mt7629_snfi_groups[] = { "snfi", "snfi_wp",
+						"snfi_hold", };
+static const char *const mt7629_snor_groups[] = { "nor_flash_io",
+						"nor_flash_wp",
+						"nor_flash_hold", };
+static const char *const mt7629_ext_groups[] = { "conn_ext_pri_0",
+						"conn_ext_pri_1",
+						"conn_ext_act_0",
+						"conn_ext_act_1",
+						"conn_wlan_act_0",
+						"conn_wlan_act_1",
+						"ext2bt_active_0",
+						"ext2bt_active_1",
+						"ext2wf_tx_active_0",
+						"ext2wf_tx_active_1",
+						"ext2ext_tx_active",
+						"wf2ext_tx_active", };
+
+static const struct mtk_function_desc mt7629_functions[] = {
+	{"eth",	mt7629_ethernet_groups, ARRAY_SIZE(mt7629_ethernet_groups)},
+	{"i2c", mt7629_i2c_groups, ARRAY_SIZE(mt7629_i2c_groups)},
+	{"led",	mt7629_led_groups, ARRAY_SIZE(mt7629_led_groups)},
+	{"pcie", mt7629_pcie_groups, ARRAY_SIZE(mt7629_pcie_groups)},
+	{"pwm",	mt7629_pwm_groups, ARRAY_SIZE(mt7629_pwm_groups)},
+	{"spi",	mt7629_spi_groups, ARRAY_SIZE(mt7629_spi_groups)},
+	{"uart", mt7629_uart_groups, ARRAY_SIZE(mt7629_uart_groups)},
+	{"watchdog", mt7629_wdt_groups, ARRAY_SIZE(mt7629_wdt_groups)},
+	{"snfi", mt7629_snfi_groups, ARRAY_SIZE(mt7629_snfi_groups)},
+	{"nor_flash", mt7629_snor_groups, ARRAY_SIZE(mt7629_snor_groups)},
+	{"ext", mt7629_ext_groups, ARRAY_SIZE(mt7629_ext_groups)},
+};
+
+static struct mtk_pinctrl_soc mt7629_data = {
+	.name = "mt7629_pinctrl",
+	.reg_cal = mt7629_reg_cals,
+	.pins = mt7629_pins,
+	.npins = ARRAY_SIZE(mt7629_pins),
+	.grps = mt7629_groups,
+	.ngrps = ARRAY_SIZE(mt7629_groups),
+	.funcs = mt7629_functions,
+	.nfuncs = ARRAY_SIZE(mt7629_functions),
+};
+
+static int mtk_pinctrl_mt7629_probe(struct udevice *dev)
+{
+	return mtk_pinctrl_probe(dev, &mt7629_data);
+}
+
+static const struct udevice_id mt7629_pctrl_match[] = {
+	{ .compatible = "mediatek,mt7629-pinctrl" },
+	{ /* sentinel */ }
+};
+
+U_BOOT_DRIVER(mt7629_pinctrl) = {
+	.name = "mt7629_pinctrl",
+	.id = UCLASS_PINCTRL,
+	.of_match = mt7629_pctrl_match,
+	.ops = &mtk_pinctrl_ops,
+	.probe = mtk_pinctrl_mt7629_probe,
+	.priv_auto_alloc_size = sizeof(struct mtk_pinctrl_priv),
+};
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
new file mode 100644
index 0000000..3a53307
--- /dev/null
+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
@@ -0,0 +1,552 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ * Author: Ryder Lee <ryder.lee@mediatek.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dm/pinctrl.h>
+#include <asm/io.h>
+#include <asm-generic/gpio.h>
+
+#include "pinctrl-mtk-common.h"
+
+/**
+ * struct mtk_drive_desc - the structure that holds the information
+ *			    of the driving current
+ * @min:	the minimum current of this group
+ * @max:	the maximum current of this group
+ * @step:	the step current of this group
+ * @scal:	the weight factor
+ *
+ * formula: output = ((input) / step - 1) * scal
+ */
+struct mtk_drive_desc {
+	u8 min;
+	u8 max;
+	u8 step;
+	u8 scal;
+};
+
+/* The groups of drive strength */
+static const struct mtk_drive_desc mtk_drive[] = {
+	[DRV_GRP0] = { 4, 16, 4, 1 },
+	[DRV_GRP1] = { 4, 16, 4, 2 },
+	[DRV_GRP2] = { 2, 8, 2, 1 },
+	[DRV_GRP3] = { 2, 8, 2, 2 },
+	[DRV_GRP4] = { 2, 16, 2, 1 },
+};
+
+static const char *mtk_pinctrl_dummy_name = "_dummy";
+
+static void mtk_w32(struct udevice *dev, u32 reg, u32 val)
+{
+	struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
+
+	__raw_writel(val, priv->base + reg);
+}
+
+static u32 mtk_r32(struct udevice *dev, u32 reg)
+{
+	struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
+
+	return __raw_readl(priv->base + reg);
+}
+
+static inline int get_count_order(unsigned int count)
+{
+	int order;
+
+	order = fls(count) - 1;
+	if (count & (count - 1))
+		order++;
+	return order;
+}
+
+void mtk_rmw(struct udevice *dev, u32 reg, u32 mask, u32 set)
+{
+	u32 val;
+
+	val = mtk_r32(dev, reg);
+	val &= ~mask;
+	val |= set;
+	mtk_w32(dev, reg, val);
+}
+
+static int mtk_hw_pin_field_lookup(struct udevice *dev, int pin,
+				   const struct mtk_pin_reg_calc *rc,
+				   struct mtk_pin_field *pfd)
+{
+	const struct mtk_pin_field_calc *c, *e;
+	u32 bits;
+
+	c = rc->range;
+	e = c + rc->nranges;
+
+	while (c < e) {
+		if (pin >= c->s_pin && pin <= c->e_pin)
+			break;
+		c++;
+	}
+
+	if (c >= e)
+		return -EINVAL;
+
+	/* Calculated bits as the overall offset the pin is located at,
+	 * if c->fixed is held, that determines the all the pins in the
+	 * range use the same field with the s_pin.
+	 */
+	bits = c->fixed ? c->s_bit : c->s_bit + (pin - c->s_pin) * (c->x_bits);
+
+	/* Fill pfd from bits. For example 32-bit register applied is assumed
+	 * when c->sz_reg is equal to 32.
+	 */
+	pfd->offset = c->s_addr + c->x_addrs * (bits / c->sz_reg);
+	pfd->bitpos = bits % c->sz_reg;
+	pfd->mask = (1 << c->x_bits) - 1;
+
+	/* pfd->next is used for indicating that bit wrapping-around happens
+	 * which requires the manipulation for bit 0 starting in the next
+	 * register to form the complete field read/write.
+	 */
+	pfd->next = pfd->bitpos + c->x_bits > c->sz_reg ? c->x_addrs : 0;
+
+	return 0;
+}
+
+static int mtk_hw_pin_field_get(struct udevice *dev, int pin,
+				int field, struct mtk_pin_field *pfd)
+{
+	struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
+	const struct mtk_pin_reg_calc *rc;
+
+	if (field < 0 || field >= PINCTRL_PIN_REG_MAX)
+		return -EINVAL;
+
+	if (priv->soc->reg_cal && priv->soc->reg_cal[field].range)
+		rc = &priv->soc->reg_cal[field];
+	else
+		return -EINVAL;
+
+	return mtk_hw_pin_field_lookup(dev, pin, rc, pfd);
+}
+
+static void mtk_hw_bits_part(struct mtk_pin_field *pf, int *h, int *l)
+{
+	*l = 32 - pf->bitpos;
+	*h = get_count_order(pf->mask) - *l;
+}
+
+static void mtk_hw_write_cross_field(struct udevice *dev,
+				     struct mtk_pin_field *pf, int value)
+{
+	int nbits_l, nbits_h;
+
+	mtk_hw_bits_part(pf, &nbits_h, &nbits_l);
+
+	mtk_rmw(dev, pf->offset, pf->mask << pf->bitpos,
+		(value & pf->mask) << pf->bitpos);
+
+	mtk_rmw(dev, pf->offset + pf->next, BIT(nbits_h) - 1,
+		(value & pf->mask) >> nbits_l);
+}
+
+static void mtk_hw_read_cross_field(struct udevice *dev,
+				    struct mtk_pin_field *pf, int *value)
+{
+	int nbits_l, nbits_h, h, l;
+
+	mtk_hw_bits_part(pf, &nbits_h, &nbits_l);
+
+	l  = (mtk_r32(dev, pf->offset) >> pf->bitpos) & (BIT(nbits_l) - 1);
+	h  = (mtk_r32(dev, pf->offset + pf->next)) & (BIT(nbits_h) - 1);
+
+	*value = (h << nbits_l) | l;
+}
+
+static int mtk_hw_set_value(struct udevice *dev, int pin, int field,
+			    int value)
+{
+	struct mtk_pin_field pf;
+	int err;
+
+	err = mtk_hw_pin_field_get(dev, pin, field, &pf);
+	if (err)
+		return err;
+
+	if (!pf.next)
+		mtk_rmw(dev, pf.offset, pf.mask << pf.bitpos,
+			(value & pf.mask) << pf.bitpos);
+	else
+		mtk_hw_write_cross_field(dev, &pf, value);
+
+	return 0;
+}
+
+static int mtk_hw_get_value(struct udevice *dev, int pin, int field,
+			    int *value)
+{
+	struct mtk_pin_field pf;
+	int err;
+
+	err = mtk_hw_pin_field_get(dev, pin, field, &pf);
+	if (err)
+		return err;
+
+	if (!pf.next)
+		*value = (mtk_r32(dev, pf.offset) >> pf.bitpos) & pf.mask;
+	else
+		mtk_hw_read_cross_field(dev, &pf, value);
+
+	return 0;
+}
+
+static int mtk_get_groups_count(struct udevice *dev)
+{
+	struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
+
+	return priv->soc->ngrps;
+}
+
+static const char *mtk_get_pin_name(struct udevice *dev,
+				    unsigned int selector)
+{
+	struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
+
+	if (!priv->soc->grps[selector].name)
+		return mtk_pinctrl_dummy_name;
+
+	return priv->soc->pins[selector].name;
+}
+
+static int mtk_get_pins_count(struct udevice *dev)
+{
+	struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
+
+	return priv->soc->npins;
+}
+
+static const char *mtk_get_group_name(struct udevice *dev,
+				      unsigned int selector)
+{
+	struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
+
+	if (!priv->soc->grps[selector].name)
+		return mtk_pinctrl_dummy_name;
+
+	return priv->soc->grps[selector].name;
+}
+
+static int mtk_get_functions_count(struct udevice *dev)
+{
+	struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
+
+	return priv->soc->nfuncs;
+}
+
+static const char *mtk_get_function_name(struct udevice *dev,
+					 unsigned int selector)
+{
+	struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
+
+	if (!priv->soc->funcs[selector].name)
+		return mtk_pinctrl_dummy_name;
+
+	return priv->soc->funcs[selector].name;
+}
+
+static int mtk_pinmux_group_set(struct udevice *dev,
+				unsigned int group_selector,
+				unsigned int func_selector)
+{
+	struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
+	const struct mtk_group_desc *grp =
+			&priv->soc->grps[group_selector];
+	int i;
+
+	for (i = 0; i < grp->num_pins; i++) {
+		int *pin_modes = grp->data;
+
+		mtk_hw_set_value(dev, grp->pins[i], PINCTRL_PIN_REG_MODE,
+				 pin_modes[i]);
+	}
+
+	return 0;
+}
+
+#if CONFIG_IS_ENABLED(PINCONF)
+static const struct pinconf_param mtk_conf_params[] = {
+	{ "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
+	{ "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
+	{ "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
+	{ "input-schmitt-enable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 1 },
+	{ "input-schmitt-disable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 0 },
+	{ "input-enable", PIN_CONFIG_INPUT_ENABLE, 1 },
+	{ "input-disable", PIN_CONFIG_INPUT_ENABLE, 0 },
+	{ "output-enable", PIN_CONFIG_OUTPUT_ENABLE, 1 },
+	{ "output-high", PIN_CONFIG_OUTPUT, 1, },
+	{ "output-low", PIN_CONFIG_OUTPUT, 0, },
+	{ "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 0 },
+};
+
+int mtk_pinconf_drive_set(struct udevice *dev, u32 pin, u32 arg)
+{
+	struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
+	const struct mtk_pin_desc *desc = &priv->soc->pins[pin];
+	const struct mtk_drive_desc *tb;
+	int err = -ENOTSUPP;
+
+	tb = &mtk_drive[desc->drv_n];
+	/* 4mA when (e8, e4) = (0, 0)
+	 * 8mA when (e8, e4) = (0, 1)
+	 * 12mA when (e8, e4) = (1, 0)
+	 * 16mA when (e8, e4) = (1, 1)
+	 */
+	if ((arg >= tb->min && arg <= tb->max) && !(arg % tb->step)) {
+		arg = (arg / tb->step - 1) * tb->scal;
+
+		err = mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_DRV, arg);
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+
+static int mtk_pinconf_set(struct udevice *dev, unsigned int pin,
+			   unsigned int param, unsigned int arg)
+{
+	int err = 0;
+
+	switch (param) {
+	case PIN_CONFIG_BIAS_DISABLE:
+	case PIN_CONFIG_BIAS_PULL_UP:
+	case PIN_CONFIG_BIAS_PULL_DOWN:
+		arg = (param == PIN_CONFIG_BIAS_DISABLE) ? 0 :
+			(param == PIN_CONFIG_BIAS_PULL_UP) ? 3 : 2;
+
+		err = mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_PULLSEL,
+				       arg & 1);
+		if (err)
+			goto err;
+
+		err = mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_PULLEN,
+				       !!(arg & 2));
+		if (err)
+			goto err;
+		break;
+	case PIN_CONFIG_OUTPUT_ENABLE:
+		err = mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_SMT, 0);
+		if (err)
+			goto err;
+		err = mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_DIR, 1);
+		if (err)
+			goto err;
+		break;
+	case PIN_CONFIG_INPUT_ENABLE:
+		err = mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_IES, 1);
+		if (err)
+			goto err;
+		err = mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_DIR, 0);
+		if (err)
+			goto err;
+		break;
+	case PIN_CONFIG_OUTPUT:
+		err = mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_DIR, 1);
+		if (err)
+			goto err;
+
+		err = mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_DO, arg);
+		if (err)
+			goto err;
+		break;
+	case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+		/* arg = 1: Input mode & SMT enable ;
+		 * arg = 0: Output mode & SMT disable
+		 */
+		arg = arg ? 2 : 1;
+		err = mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_DIR,
+				       arg & 1);
+		if (err)
+			goto err;
+
+		err = mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_SMT,
+				       !!(arg & 2));
+		if (err)
+			goto err;
+		break;
+	case PIN_CONFIG_DRIVE_STRENGTH:
+		err = mtk_pinconf_drive_set(dev, pin, arg);
+		if (err)
+			goto err;
+		break;
+
+	default:
+		err = -ENOTSUPP;
+	}
+
+err:
+
+	return err;
+}
+
+static int mtk_pinconf_group_set(struct udevice *dev,
+				 unsigned int group_selector,
+				 unsigned int param, unsigned int arg)
+{
+	struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
+	const struct mtk_group_desc *grp =
+			&priv->soc->grps[group_selector];
+	int i, ret;
+
+	for (i = 0; i < grp->num_pins; i++) {
+		ret = mtk_pinconf_set(dev, grp->pins[i], param, arg);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+#endif
+
+const struct pinctrl_ops mtk_pinctrl_ops = {
+	.get_pins_count = mtk_get_pins_count,
+	.get_pin_name = mtk_get_pin_name,
+	.get_groups_count = mtk_get_groups_count,
+	.get_group_name = mtk_get_group_name,
+	.get_functions_count = mtk_get_functions_count,
+	.get_function_name = mtk_get_function_name,
+	.pinmux_group_set = mtk_pinmux_group_set,
+#if CONFIG_IS_ENABLED(PINCONF)
+	.pinconf_num_params = ARRAY_SIZE(mtk_conf_params),
+	.pinconf_params = mtk_conf_params,
+	.pinconf_set = mtk_pinconf_set,
+	.pinconf_group_set = mtk_pinconf_group_set,
+#endif
+	.set_state = pinctrl_generic_set_state,
+};
+
+static int mtk_gpio_get(struct udevice *dev, unsigned int off)
+{
+	int val, err;
+
+	err = mtk_hw_get_value(dev->parent, off, PINCTRL_PIN_REG_DI, &val);
+	if (err)
+		return err;
+
+	return !!val;
+}
+
+static int mtk_gpio_set(struct udevice *dev, unsigned int off, int val)
+{
+	return mtk_hw_set_value(dev->parent, off, PINCTRL_PIN_REG_DO, !!val);
+}
+
+static int mtk_gpio_get_direction(struct udevice *dev, unsigned int off)
+{
+	int val, err;
+
+	err = mtk_hw_get_value(dev->parent, off, PINCTRL_PIN_REG_DIR, &val);
+	if (err)
+		return err;
+
+	return val ? GPIOF_OUTPUT : GPIOF_INPUT;
+}
+
+static int mtk_gpio_direction_input(struct udevice *dev, unsigned int off)
+{
+	return mtk_hw_set_value(dev->parent, off, PINCTRL_PIN_REG_DIR, 0);
+}
+
+static int mtk_gpio_direction_output(struct udevice *dev,
+				     unsigned int off, int val)
+{
+	mtk_gpio_set(dev, off, val);
+
+	/* And set the requested value */
+	return mtk_hw_set_value(dev->parent, off, PINCTRL_PIN_REG_DIR, 1);
+}
+
+static int mtk_gpio_request(struct udevice *dev, unsigned int off,
+			    const char *label)
+{
+	return mtk_hw_set_value(dev->parent, off, PINCTRL_PIN_REG_MODE, 0);
+}
+
+static int mtk_gpio_probe(struct udevice *dev)
+{
+	struct mtk_pinctrl_priv *priv = dev_get_priv(dev->parent);
+	struct gpio_dev_priv *uc_priv;
+
+	uc_priv = dev_get_uclass_priv(dev);
+	uc_priv->bank_name = priv->soc->name;
+	uc_priv->gpio_count = priv->soc->npins;
+
+	return 0;
+}
+
+static const struct dm_gpio_ops mtk_gpio_ops = {
+	.request = mtk_gpio_request,
+	.set_value = mtk_gpio_set,
+	.get_value = mtk_gpio_get,
+	.get_function = mtk_gpio_get_direction,
+	.direction_input = mtk_gpio_direction_input,
+	.direction_output = mtk_gpio_direction_output,
+};
+
+static struct driver mtk_gpio_driver = {
+	.name = "mediatek_gpio",
+	.id	= UCLASS_GPIO,
+	.probe = mtk_gpio_probe,
+	.ops = &mtk_gpio_ops,
+};
+
+static int mtk_gpiochip_register(struct udevice *parent)
+{
+	struct uclass_driver *drv;
+	struct udevice *dev;
+	int ret;
+	ofnode node;
+
+	drv = lists_uclass_lookup(UCLASS_GPIO);
+	if (!drv)
+		return -ENOENT;
+
+	dev_for_each_subnode(node, parent)
+		if (ofnode_read_bool(node, "gpio-controller")) {
+			ret = 0;
+			break;
+		}
+
+	if (ret)
+		return ret;
+
+	ret = device_bind_with_driver_data(parent, &mtk_gpio_driver,
+					   "mediatek_gpio", 0, node,
+					   &dev);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+int mtk_pinctrl_probe(struct udevice *dev, struct mtk_pinctrl_soc *soc)
+{
+	struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	priv->base = dev_read_addr_ptr(dev);
+	if (priv->base == (void *)FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	priv->soc = soc;
+
+	ret = mtk_gpiochip_register(dev);
+	if (ret)
+		return ret;
+
+	return 0;
+}
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.h b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h
new file mode 100644
index 0000000..2184fdd
--- /dev/null
+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h
@@ -0,0 +1,182 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ * Author: Ryder Lee <ryder.lee@mediatek.com>
+ */
+
+#ifndef __PINCTRL_MEDIATEK_H__
+#define __PINCTRL_MEDIATEK_H__
+
+#define MTK_RANGE(_a)		{ .range = (_a), .nranges = ARRAY_SIZE(_a), }
+#define MTK_PIN(_number, _name, _drv_n) {				\
+		.number = _number,					\
+		.name = _name,						\
+		.drv_n = _drv_n,					\
+	}
+
+#define PINCTRL_PIN_GROUP(name, id)					\
+	{								\
+		name,							\
+		id##_pins,						\
+		ARRAY_SIZE(id##_pins),					\
+		id##_funcs,						\
+	}
+
+#define PIN_FIELD_CALC(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit,	\
+			_x_bits, _sz_reg, _fixed) {			\
+		.s_pin = _s_pin,					\
+		.e_pin = _e_pin,					\
+		.s_addr = _s_addr,					\
+		.x_addrs = _x_addrs,					\
+		.s_bit = _s_bit,					\
+		.x_bits = _x_bits,					\
+		.sz_reg = _sz_reg,					\
+		.fixed = _fixed,					\
+	}
+
+/* List these attributes which could be modified for the pin */
+enum {
+	PINCTRL_PIN_REG_MODE,
+	PINCTRL_PIN_REG_DIR,
+	PINCTRL_PIN_REG_DI,
+	PINCTRL_PIN_REG_DO,
+	PINCTRL_PIN_REG_IES,
+	PINCTRL_PIN_REG_SMT,
+	PINCTRL_PIN_REG_PULLEN,
+	PINCTRL_PIN_REG_PULLSEL,
+	PINCTRL_PIN_REG_DRV,
+	PINCTRL_PIN_REG_MAX,
+};
+
+/* Group the pins by the driving current */
+enum {
+	DRV_FIXED,
+	DRV_GRP0,
+	DRV_GRP1,
+	DRV_GRP2,
+	DRV_GRP3,
+	DRV_GRP4,
+};
+
+/**
+ * struct mtk_pin_field - the structure that holds the information of the field
+ *			  used to describe the attribute for the pin
+ * @offset:		the register offset relative to the base address
+ * @mask:		the mask used to filter out the field from the register
+ * @bitpos:		the start bit relative to the register
+ * @next:		the indication that the field would be extended to the
+			next register
+ */
+struct mtk_pin_field {
+	u32 offset;
+	u32 mask;
+	u8 bitpos;
+	u8 next;
+};
+
+/**
+ * struct mtk_pin_field_calc - the structure that holds the range providing
+ *			       the guide used to look up the relevant field
+ * @s_pin:		the start pin within the range
+ * @e_pin:		the end pin within the range
+ * @s_addr:		the start address for the range
+ * @x_addrs:		the address distance between two consecutive registers
+ *			within the range
+ * @s_bit:		the start bit for the first register within the range
+ * @x_bits:		the bit distance between two consecutive pins within
+ *			the range
+ * @sz_reg:		the size of bits in a register
+ * @fixed:		the consecutive pins share the same bits with the 1st
+ *			pin
+ */
+struct mtk_pin_field_calc {
+	u16 s_pin;
+	u16 e_pin;
+	u32 s_addr;
+	u8 x_addrs;
+	u8 s_bit;
+	u8 x_bits;
+	u8 sz_reg;
+	u8 fixed;
+};
+
+/**
+ * struct mtk_pin_reg_calc - the structure that holds all ranges used to
+ *			     determine which register the pin would make use of
+ *			     for certain pin attribute.
+ * @range:		     the start address for the range
+ * @nranges:		     the number of items in the range
+ */
+struct mtk_pin_reg_calc {
+	const struct mtk_pin_field_calc *range;
+	unsigned int nranges;
+};
+
+/**
+ * struct mtk_pin_desc - the structure that providing information
+ *			 for each pin of chips
+ * @number:		unique pin number from the global pin number space
+ * @name:		name for this pin
+ * @drv_n:		the index with the driving group
+ */
+struct mtk_pin_desc {
+	unsigned int number;
+	const char *name;
+	u8 drv_n;
+};
+
+/**
+ * struct mtk_group_desc - generic pin group descriptor
+ * @name: name of the pin group
+ * @pins: array of pins that belong to the group
+ * @num_pins: number of pins in the group
+ * @data: pin controller driver specific data
+ */
+struct mtk_group_desc {
+	const char *name;
+	int *pins;
+	int num_pins;
+	void *data;
+};
+
+/**
+ * struct mtk_function_desc - generic function descriptor
+ * @name: name of the function
+ * @group_names: array of pin group names
+ * @num_group_names: number of pin group names
+ */
+struct mtk_function_desc {
+	const char *name;
+	const char * const *group_names;
+	int num_group_names;
+};
+
+/* struct mtk_pin_soc - the structure that holds SoC-specific data */
+struct mtk_pinctrl_soc {
+	const char *name;
+	const struct mtk_pin_reg_calc *reg_cal;
+	const struct mtk_pin_desc *pins;
+	int npins;
+	const struct mtk_group_desc *grps;
+	int ngrps;
+	const struct mtk_function_desc *funcs;
+	int nfuncs;
+};
+
+/**
+ * struct mtk_pinctrl_priv - private data for MTK pinctrl driver
+ *
+ * @base: base address of the pinctrl device
+ * @soc: SoC specific data
+ */
+struct mtk_pinctrl_priv {
+	void __iomem *base;
+	struct mtk_pinctrl_soc *soc;
+};
+
+extern const struct pinctrl_ops mtk_pinctrl_ops;
+
+int mtk_pinctrl_probe(struct udevice *dev,
+		      struct mtk_pinctrl_soc *soc);
+
+#endif /* __PINCTRL_MEDIATEK_H__ */
-- 
1.9.1

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

* [U-Boot] [PATCH v2 11/18] pinctrl: MediaTek: add pinctrl driver for MT7623 SoC
  2018-10-12  7:00 [U-Boot] [PATCH v2 00/18] Add U-Boot support for MediaTek SoCs - MT7623n & MT7629 Ryder Lee
                   ` (9 preceding siblings ...)
  2018-10-12  7:00 ` [U-Boot] [PATCH v2 10/18] pinctrl: MediaTek: add pinctrl driver for MT7629 SoC Ryder Lee
@ 2018-10-12  7:01 ` Ryder Lee
  2018-10-25  3:29   ` Simon Glass
  2018-10-12  7:01 ` [U-Boot] [PATCH v2 12/18] power domain: MediaTek: add power domain driver for MT7629 SoC Ryder Lee
                   ` (6 subsequent siblings)
  17 siblings, 1 reply; 57+ messages in thread
From: Ryder Lee @ 2018-10-12  7:01 UTC (permalink / raw)
  To: u-boot

This patch adds pinctrl support for MT7623 SoC. And most of the
structures are used to hold the hardware configuration for each
pin.

Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
Tested-by: Matthias Brugger <matthias.bgg@gmail.com>
---
 drivers/pinctrl/mediatek/Kconfig              |    4 +
 drivers/pinctrl/mediatek/Makefile             |    1 +
 drivers/pinctrl/mediatek/pinctrl-mt7623.c     | 1284 +++++++++++++++++++++++++
 drivers/pinctrl/mediatek/pinctrl-mtk-common.h |    1 +
 4 files changed, 1290 insertions(+)
 create mode 100644 drivers/pinctrl/mediatek/pinctrl-mt7623.c

diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig
index e0145b1..1bd9a92 100644
--- a/drivers/pinctrl/mediatek/Kconfig
+++ b/drivers/pinctrl/mediatek/Kconfig
@@ -4,6 +4,10 @@ config PINCTRL_MTK
 	depends on PINCTRL_GENERIC
 	bool
 
+config PINCTRL_MT7623
+	bool "MT7623 SoC pinctrl driver"
+	select PINCTRL_MTK
+
 config PINCTRL_MT7629
 	bool "MT7629 SoC pinctrl driver"
 	select PINCTRL_MTK
diff --git a/drivers/pinctrl/mediatek/Makefile b/drivers/pinctrl/mediatek/Makefile
index cbf0765..f6ef362 100644
--- a/drivers/pinctrl/mediatek/Makefile
+++ b/drivers/pinctrl/mediatek/Makefile
@@ -3,4 +3,5 @@
 obj-$(CONFIG_PINCTRL_MTK) += pinctrl-mtk-common.o
 
 # SoC Drivers
+obj-$(CONFIG_PINCTRL_MT7623) += pinctrl-mt7623.o
 obj-$(CONFIG_PINCTRL_MT7629) += pinctrl-mt7629.o
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt7623.c b/drivers/pinctrl/mediatek/pinctrl-mt7623.c
new file mode 100644
index 0000000..6fa3e2b
--- /dev/null
+++ b/drivers/pinctrl/mediatek/pinctrl-mt7623.c
@@ -0,0 +1,1284 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ * Author: Ryder Lee <ryder.lee@mediatek.com>
+ */
+
+#include <dm.h>
+
+#include "pinctrl-mtk-common.h"
+
+#define PIN_BOND_REG0		0xb10
+#define PIN_BOND_REG1		0xf20
+#define PIN_BOND_REG2		0xef0
+#define BOND_PCIE_CLR		(0x77 << 3)
+#define BOND_I2S_CLR		0x3
+#define BOND_MSDC0E_CLR		0x1
+
+#define PIN_FIELD15(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit, _x_bits)	\
+	PIN_FIELD_CALC(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit,	\
+		       _x_bits, 15, false)
+
+#define PIN_FIELD16(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit, _x_bits)	\
+	PIN_FIELD_CALC(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit,	\
+		       _x_bits, 16, false)
+
+#define PINS_FIELD16(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit, _x_bits)\
+	PIN_FIELD_CALC(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit,	\
+		       _x_bits, 16, true)
+
+static const struct mtk_pin_field_calc mt7623_pin_mode_range[] = {
+	PIN_FIELD15(0, 278, 0x760, 0x10, 0, 3),
+};
+
+static const struct mtk_pin_field_calc mt7623_pin_dir_range[] = {
+	PIN_FIELD16(0, 175, 0x0, 0x10, 0, 1),
+	PIN_FIELD16(176, 278, 0xc0, 0x10, 0, 1),
+};
+
+static const struct mtk_pin_field_calc mt7623_pin_di_range[] = {
+	PIN_FIELD16(0, 278, 0x630, 0x10, 0, 1),
+};
+
+static const struct mtk_pin_field_calc mt7623_pin_do_range[] = {
+	PIN_FIELD16(0, 278, 0x500, 0x10, 0, 1),
+};
+
+static const struct mtk_pin_field_calc mt7623_pin_ies_range[] = {
+	PINS_FIELD16(0, 6, 0xb20, 0x10, 0, 1),
+	PINS_FIELD16(7, 9, 0xb20, 0x10, 1, 1),
+	PINS_FIELD16(10, 13, 0xb30, 0x10, 3, 1),
+	PINS_FIELD16(14, 15, 0xb30, 0x10, 13, 1),
+	PINS_FIELD16(16, 17, 0xb40, 0x10, 7, 1),
+	PINS_FIELD16(18, 29, 0xb40, 0x10, 13, 1),
+	PINS_FIELD16(30, 32, 0xb40, 0x10, 7, 1),
+	PINS_FIELD16(33, 37, 0xb40, 0x10, 13, 1),
+	PIN_FIELD16(38, 38, 0xb20, 0x10, 13, 1),
+	PINS_FIELD16(39, 42, 0xb40, 0x10, 13, 1),
+	PINS_FIELD16(43, 45, 0xb20, 0x10, 10, 1),
+	PINS_FIELD16(47, 48, 0xb20, 0x10, 11, 1),
+	PIN_FIELD16(49, 49, 0xb20, 0x10, 12, 1),
+	PINS_FIELD16(50, 52, 0xb20, 0x10, 13, 1),
+	PINS_FIELD16(53, 56, 0xb20, 0x10, 14, 1),
+	PINS_FIELD16(57, 58, 0xb20, 0x10, 15, 1),
+	PIN_FIELD16(59, 59, 0xb30, 0x10, 10, 1),
+	PINS_FIELD16(60, 62, 0xb30, 0x10, 0, 1),
+	PINS_FIELD16(63, 65, 0xb30, 0x10, 1, 1),
+	PINS_FIELD16(66, 71, 0xb30, 0x10, 2, 1),
+	PINS_FIELD16(72, 74, 0xb20, 0x10, 12, 1),
+	PINS_FIELD16(75, 76, 0xb30, 0x10, 3, 1),
+	PINS_FIELD16(77, 78, 0xb30, 0x10, 4, 1),
+	PINS_FIELD16(79, 82, 0xb30, 0x10, 5, 1),
+	PINS_FIELD16(83, 84, 0xb30, 0x10, 2, 1),
+	PIN_FIELD16(85, 85, 0xda0, 0x10, 4, 1),
+	PIN_FIELD16(86, 86, 0xd90, 0x10, 4, 1),
+	PINS_FIELD16(87, 90, 0xdb0, 0x10, 4, 1),
+	PINS_FIELD16(101, 104, 0xb30, 0x10, 6, 1),
+	PIN_FIELD16(105, 105, 0xd40, 0x10, 4, 1),
+	PIN_FIELD16(106, 106, 0xd30, 0x10, 4, 1),
+	PINS_FIELD16(107, 110, 0xd50, 0x10, 4, 1),
+	PINS_FIELD16(111, 115, 0xce0, 0x10, 4, 1),
+	PIN_FIELD16(116, 116, 0xcd0, 0x10, 4, 1),
+	PIN_FIELD16(117, 117, 0xcc0, 0x10, 4, 1),
+	PINS_FIELD16(118, 121, 0xce0, 0x10, 4, 1),
+	PINS_FIELD16(122, 125, 0xb30, 0x10, 7, 1),
+	PIN_FIELD16(126, 126, 0xb20, 0x10, 12, 1),
+	PINS_FIELD16(127, 142, 0xb30, 0x10, 9, 1),
+	PINS_FIELD16(143, 160, 0xb30, 0x10, 10, 1),
+	PINS_FIELD16(161, 168, 0xb30, 0x10, 12, 1),
+	PINS_FIELD16(169, 183, 0xb30, 0x10, 10, 1),
+	PINS_FIELD16(184, 186, 0xb30, 0x10, 9, 1),
+	PIN_FIELD16(187, 187, 0xb30, 0x10, 14, 1),
+	PIN_FIELD16(188, 188, 0xb20, 0x10, 13, 1),
+	PINS_FIELD16(189, 193, 0xb30, 0x10, 15, 1),
+	PINS_FIELD16(194, 198, 0xb40, 0x10, 0, 1),
+	PIN_FIELD16(199, 199, 0xb20, 0x10, 1, 1),
+	PINS_FIELD16(200, 202, 0xb40, 0x10, 1, 1),
+	PINS_FIELD16(203, 207, 0xb40, 0x10, 2, 1),
+	PINS_FIELD16(208, 209, 0xb40, 0x10, 3, 1),
+	PIN_FIELD16(210, 210, 0xb40, 0x10, 4, 1),
+	PINS_FIELD16(211, 235, 0xb40, 0x10, 5, 1),
+	PINS_FIELD16(236, 241, 0xb40, 0x10, 6, 1),
+	PINS_FIELD16(242, 243, 0xb40, 0x10, 7, 1),
+	PINS_FIELD16(244, 247, 0xb40, 0x10, 8, 1),
+	PIN_FIELD16(248, 248, 0xb40, 0x10, 9, 1),
+	PINS_FIELD16(249, 257, 0xfc0, 0x10, 4, 1),
+	PIN_FIELD16(258, 258, 0xcb0, 0x10, 4, 1),
+	PIN_FIELD16(259, 259, 0xc90, 0x10, 4, 1),
+	PIN_FIELD16(260, 260, 0x3a0, 0x10, 4, 1),
+	PIN_FIELD16(261, 261, 0xd50, 0x10, 4, 1),
+	PINS_FIELD16(262, 277, 0xb40, 0x10, 12, 1),
+	PIN_FIELD16(278, 278, 0xb40, 0x10, 13, 1),
+};
+
+static const struct mtk_pin_field_calc mt7623_pin_smt_range[] = {
+	PINS_FIELD16(0, 6, 0xb50, 0x10, 0, 1),
+	PINS_FIELD16(7, 9, 0xb50, 0x10, 1, 1),
+	PINS_FIELD16(10, 13, 0xb60, 0x10, 3, 1),
+	PINS_FIELD16(14, 15, 0xb60, 0x10, 13, 1),
+	PINS_FIELD16(16, 17, 0xb70, 0x10, 7, 1),
+	PINS_FIELD16(18, 29, 0xb70, 0x10, 13, 1),
+	PINS_FIELD16(30, 32, 0xb70, 0x10, 7, 1),
+	PINS_FIELD16(33, 37, 0xb70, 0x10, 13, 1),
+	PIN_FIELD16(38, 38, 0xb50, 0x10, 13, 1),
+	PINS_FIELD16(39, 42, 0xb70, 0x10, 13, 1),
+	PINS_FIELD16(43, 45, 0xb50, 0x10, 10, 1),
+	PINS_FIELD16(47, 48, 0xb50, 0x10, 11, 1),
+	PIN_FIELD16(49, 49, 0xb50, 0x10, 12, 1),
+	PINS_FIELD16(50, 52, 0xb50, 0x10, 13, 1),
+	PINS_FIELD16(53, 56, 0xb50, 0x10, 14, 1),
+	PINS_FIELD16(57, 58, 0xb50, 0x10, 15, 1),
+	PIN_FIELD16(59, 59, 0xb60, 0x10, 10, 1),
+	PINS_FIELD16(60, 62, 0xb60, 0x10, 0, 1),
+	PINS_FIELD16(63, 65, 0xb60, 0x10, 1, 1),
+	PINS_FIELD16(66, 71, 0xb60, 0x10, 2, 1),
+	PINS_FIELD16(72, 74, 0xb50, 0x10, 12, 1),
+	PINS_FIELD16(75, 76, 0xb60, 0x10, 3, 1),
+	PINS_FIELD16(77, 78, 0xb60, 0x10, 4, 1),
+	PINS_FIELD16(79, 82, 0xb60, 0x10, 5, 1),
+	PINS_FIELD16(83, 84, 0xb60, 0x10, 2, 1),
+	PIN_FIELD16(85, 85, 0xda0, 0x10, 11, 1),
+	PIN_FIELD16(86, 86, 0xd90, 0x10, 11, 1),
+	PIN_FIELD16(87, 87, 0xdc0, 0x10, 3, 1),
+	PIN_FIELD16(88, 88, 0xdc0, 0x10, 7, 1),
+	PIN_FIELD16(89, 89, 0xdc0, 0x10, 11, 1),
+	PIN_FIELD16(90, 90, 0xdc0, 0x10, 15, 1),
+	PINS_FIELD16(101, 104, 0xb60, 0x10, 6, 1),
+	PIN_FIELD16(105, 105, 0xd40, 0x10, 11, 1),
+	PIN_FIELD16(106, 106, 0xd30, 0x10, 11, 1),
+	PIN_FIELD16(107, 107, 0xd60, 0x10, 3, 1),
+	PIN_FIELD16(108, 108, 0xd60, 0x10, 7, 1),
+	PIN_FIELD16(109, 109, 0xd60, 0x10, 11, 1),
+	PIN_FIELD16(110, 110, 0xd60, 0x10, 15, 1),
+	PIN_FIELD16(111, 111, 0xd00, 0x10, 15, 1),
+	PIN_FIELD16(112, 112, 0xd00, 0x10, 11, 1),
+	PIN_FIELD16(113, 113, 0xd00, 0x10, 7, 1),
+	PIN_FIELD16(114, 114, 0xd00, 0x10, 3, 1),
+	PIN_FIELD16(115, 115, 0xd10, 0x10, 3, 1),
+	PIN_FIELD16(116, 116, 0xcd0, 0x10, 11, 1),
+	PIN_FIELD16(117, 117, 0xcc0, 0x10, 11, 1),
+	PIN_FIELD16(118, 118, 0xcf0, 0x10, 15, 1),
+	PIN_FIELD16(119, 119, 0xcf0, 0x10, 7, 1),
+	PIN_FIELD16(120, 120, 0xcf0, 0x10, 3, 1),
+	PIN_FIELD16(121, 121, 0xcf0, 0x10, 7, 1),
+	PINS_FIELD16(122, 125, 0xb60, 0x10, 7, 1),
+	PIN_FIELD16(126, 126, 0xb50, 0x10, 12, 1),
+	PINS_FIELD16(127, 142, 0xb60, 0x10, 9, 1),
+	PINS_FIELD16(143, 160, 0xb60, 0x10, 10, 1),
+	PINS_FIELD16(161, 168, 0xb60, 0x10, 12, 1),
+	PINS_FIELD16(169, 183, 0xb60, 0x10, 10, 1),
+	PINS_FIELD16(184, 186, 0xb60, 0x10, 9, 1),
+	PIN_FIELD16(187, 187, 0xb60, 0x10, 14, 1),
+	PIN_FIELD16(188, 188, 0xb50, 0x10, 13, 1),
+	PINS_FIELD16(189, 193, 0xb60, 0x10, 15, 1),
+	PINS_FIELD16(194, 198, 0xb70, 0x10, 0, 1),
+	PIN_FIELD16(199, 199, 0xb50, 0x10, 1, 1),
+	PINS_FIELD16(200, 202, 0xb70, 0x10, 1, 1),
+	PINS_FIELD16(203, 207, 0xb70, 0x10, 2, 1),
+	PINS_FIELD16(208, 209, 0xb70, 0x10, 3, 1),
+	PIN_FIELD16(210, 210, 0xb70, 0x10, 4, 1),
+	PINS_FIELD16(211, 235, 0xb70, 0x10, 5, 1),
+	PINS_FIELD16(236, 241, 0xb70, 0x10, 6, 1),
+	PINS_FIELD16(242, 243, 0xb70, 0x10, 7, 1),
+	PINS_FIELD16(244, 247, 0xb70, 0x10, 8, 1),
+	PIN_FIELD16(248, 248, 0xb70, 0x10, 9, 10),
+	PIN_FIELD16(249, 249, 0x140, 0x10, 3, 1),
+	PIN_FIELD16(250, 250, 0x130, 0x10, 15, 1),
+	PIN_FIELD16(251, 251, 0x130, 0x10, 11, 1),
+	PIN_FIELD16(252, 252, 0x130, 0x10, 7, 1),
+	PIN_FIELD16(253, 253, 0x130, 0x10, 3, 1),
+	PIN_FIELD16(254, 254, 0xf40, 0x10, 15, 1),
+	PIN_FIELD16(255, 255, 0xf40, 0x10, 11, 1),
+	PIN_FIELD16(256, 256, 0xf40, 0x10, 7, 1),
+	PIN_FIELD16(257, 257, 0xf40, 0x10, 3, 1),
+	PIN_FIELD16(258, 258, 0xcb0, 0x10, 11, 1),
+	PIN_FIELD16(259, 259, 0xc90, 0x10, 11, 1),
+	PIN_FIELD16(260, 260, 0x3a0, 0x10, 11, 1),
+	PIN_FIELD16(261, 261, 0x0b0, 0x10, 3, 1),
+	PINS_FIELD16(262, 277, 0xb70, 0x10, 12, 1),
+	PIN_FIELD16(278, 278, 0xb70, 0x10, 13, 1),
+};
+
+static const struct mtk_pin_field_calc mt7623_pin_pullen_range[] = {
+	PIN_FIELD16(0, 278, 0x150, 0x10, 0, 1),
+};
+
+static const struct mtk_pin_field_calc mt7623_pin_pullsel_range[] = {
+	PIN_FIELD16(0, 278, 0x280, 0x10, 0, 1),
+};
+
+static const struct mtk_pin_field_calc mt7623_pin_drv_range[] = {
+	PINS_FIELD16(0, 6, 0xf50, 0x10, 0, 4),
+	PINS_FIELD16(7, 9, 0xf50, 0x10, 4, 4),
+	PINS_FIELD16(10, 13, 0xf50, 0x10, 4, 4),
+	PINS_FIELD16(14, 15, 0xf50, 0x10, 12, 4),
+	PINS_FIELD16(16, 17, 0xf60, 0x10, 0, 4),
+	PINS_FIELD16(18, 21, 0xf60, 0x10, 0, 4),
+	PINS_FIELD16(22, 26, 0xf60, 0x10, 8, 4),
+	PINS_FIELD16(27, 29, 0xf60, 0x10, 12, 4),
+	PINS_FIELD16(30, 32, 0xf60, 0x10, 0, 4),
+	PINS_FIELD16(33, 37, 0xf70, 0x10, 0, 4),
+	PIN_FIELD16(38, 38, 0xf70, 0x10, 4, 4),
+	PINS_FIELD16(39, 42, 0xf70, 0x10, 8, 4),
+	PINS_FIELD16(43, 45, 0xf70, 0x10, 12, 4),
+	PINS_FIELD16(47, 48, 0xf80, 0x10, 0, 4),
+	PIN_FIELD16(49, 49, 0xf80, 0x10, 4, 4),
+	PINS_FIELD16(50, 52, 0xf70, 0x10, 4, 4),
+	PINS_FIELD16(53, 56, 0xf80, 0x10, 12, 4),
+	PINS_FIELD16(60, 62, 0xf90, 0x10, 8, 4),
+	PINS_FIELD16(63, 65, 0xf90, 0x10, 12, 4),
+	PINS_FIELD16(66, 71, 0xfa0, 0x10, 0, 4),
+	PINS_FIELD16(72, 74, 0xf80, 0x10, 4, 4),
+	PIN_FIELD16(85, 85, 0xda0, 0x10, 0, 4),
+	PIN_FIELD16(86, 86, 0xd90, 0x10, 0, 4),
+	PINS_FIELD16(87, 90, 0xdb0, 0x10, 0, 4),
+	PIN_FIELD16(105, 105, 0xd40, 0x10, 0, 4),
+	PIN_FIELD16(106, 106, 0xd30, 0x10, 0, 4),
+	PINS_FIELD16(107, 110, 0xd50, 0x10, 0, 4),
+	PINS_FIELD16(111, 115, 0xce0, 0x10, 0, 4),
+	PIN_FIELD16(116, 116, 0xcd0, 0x10, 0, 4),
+	PIN_FIELD16(117, 117, 0xcc0, 0x10, 0, 4),
+	PINS_FIELD16(118, 121, 0xce0, 0x10, 0, 4),
+	PIN_FIELD16(126, 126, 0xf80, 0x10, 4, 4),
+	PIN_FIELD16(188, 188, 0xf70, 0x10, 4, 4),
+	PINS_FIELD16(189, 193, 0xfe0, 0x10, 8, 4),
+	PINS_FIELD16(194, 198, 0xfe0, 0x10, 12, 4),
+	PIN_FIELD16(199, 199, 0xf50, 0x10, 4, 4),
+	PINS_FIELD16(200, 202, 0xfd0, 0x10, 0, 4),
+	PINS_FIELD16(203, 207, 0xfd0, 0x10, 4, 4),
+	PINS_FIELD16(208, 209, 0xfd0, 0x10, 8, 4),
+	PIN_FIELD16(210, 210, 0xfd0, 0x10, 12, 4),
+	PINS_FIELD16(211, 235, 0xff0, 0x10, 0, 4),
+	PINS_FIELD16(236, 241, 0xff0, 0x10, 4, 4),
+	PINS_FIELD16(242, 243, 0xff0, 0x10, 8, 4),
+	PIN_FIELD16(248, 248, 0xf00, 0x10, 0, 4),
+	PINS_FIELD16(249, 256, 0xfc0, 0x10, 0, 4),
+	PIN_FIELD16(257, 257, 0xce0, 0x10, 0, 4),
+	PIN_FIELD16(258, 258, 0xcb0, 0x10, 0, 4),
+	PIN_FIELD16(259, 259, 0xc90, 0x10, 0, 4),
+	PIN_FIELD16(260, 260, 0x3a0, 0x10, 0, 4),
+	PIN_FIELD16(261, 261, 0xd50, 0x10, 0, 4),
+	PINS_FIELD16(262, 277, 0xf00, 0x10, 8, 4),
+	PIN_FIELD16(278, 278, 0xf70, 0x10, 8, 4),
+};
+
+static const struct mtk_pin_reg_calc mt7623_reg_cals[] = {
+	[PINCTRL_PIN_REG_MODE] = MTK_RANGE(mt7623_pin_mode_range),
+	[PINCTRL_PIN_REG_DIR] = MTK_RANGE(mt7623_pin_dir_range),
+	[PINCTRL_PIN_REG_DI] = MTK_RANGE(mt7623_pin_di_range),
+	[PINCTRL_PIN_REG_DO] = MTK_RANGE(mt7623_pin_do_range),
+	[PINCTRL_PIN_REG_IES] = MTK_RANGE(mt7623_pin_ies_range),
+	[PINCTRL_PIN_REG_SMT] = MTK_RANGE(mt7623_pin_smt_range),
+	[PINCTRL_PIN_REG_PULLSEL] = MTK_RANGE(mt7623_pin_pullsel_range),
+	[PINCTRL_PIN_REG_PULLEN] = MTK_RANGE(mt7623_pin_pullen_range),
+	[PINCTRL_PIN_REG_DRV] = MTK_RANGE(mt7623_pin_drv_range),
+};
+
+static const struct mtk_pin_desc mt7623_pins[] = {
+	MTK_PIN(0, "PWRAP_SPI0_MI", DRV_GRP3),
+	MTK_PIN(1, "PWRAP_SPI0_MO", DRV_GRP3),
+	MTK_PIN(2, "PWRAP_INT", DRV_GRP3),
+	MTK_PIN(3, "PWRAP_SPI0_CK", DRV_GRP3),
+	MTK_PIN(4, "PWRAP_SPI0_CSN", DRV_GRP3),
+	MTK_PIN(5, "PWRAP_SPI0_CK2", DRV_GRP3),
+	MTK_PIN(6, "PWRAP_SPI0_CSN2", DRV_GRP3),
+	MTK_PIN(7, "SPI1_CSN", DRV_GRP3),
+	MTK_PIN(8, "SPI1_MI", DRV_GRP3),
+	MTK_PIN(9, "SPI1_MO", DRV_GRP3),
+	MTK_PIN(10, "RTC32K_CK", DRV_GRP3),
+	MTK_PIN(11, "WATCHDOG", DRV_GRP3),
+	MTK_PIN(12, "SRCLKENA", DRV_GRP3),
+	MTK_PIN(13, "SRCLKENAI", DRV_GRP3),
+	MTK_PIN(14, "URXD2", DRV_GRP1),
+	MTK_PIN(15, "UTXD2", DRV_GRP1),
+	MTK_PIN(16, "I2S5_DATA_IN", DRV_GRP1),
+	MTK_PIN(17, "I2S5_BCK", DRV_GRP1),
+	MTK_PIN(18, "PCM_CLK", DRV_GRP1),
+	MTK_PIN(19, "PCM_SYNC", DRV_GRP1),
+	MTK_PIN(20, "PCM_RX", DRV_GRP1),
+	MTK_PIN(21, "PCM_TX", DRV_GRP1),
+	MTK_PIN(22, "EINT0", DRV_GRP1),
+	MTK_PIN(23, "EINT1", DRV_GRP1),
+	MTK_PIN(24, "EINT2", DRV_GRP1),
+	MTK_PIN(25, "EINT3", DRV_GRP1),
+	MTK_PIN(26, "EINT4", DRV_GRP1),
+	MTK_PIN(27, "EINT5", DRV_GRP1),
+	MTK_PIN(28, "EINT6", DRV_GRP1),
+	MTK_PIN(29, "EINT7", DRV_GRP1),
+	MTK_PIN(30, "I2S5_LRCK", DRV_GRP1),
+	MTK_PIN(31, "I2S5_MCLK", DRV_GRP1),
+	MTK_PIN(32, "I2S5_DATA", DRV_GRP1),
+	MTK_PIN(33, "I2S1_DATA", DRV_GRP1),
+	MTK_PIN(34, "I2S1_DATA_IN", DRV_GRP1),
+	MTK_PIN(35, "I2S1_BCK", DRV_GRP1),
+	MTK_PIN(36, "I2S1_LRCK", DRV_GRP1),
+	MTK_PIN(37, "I2S1_MCLK", DRV_GRP1),
+	MTK_PIN(38, "I2S2_DATA", DRV_GRP1),
+	MTK_PIN(39, "JTMS", DRV_GRP3),
+	MTK_PIN(40, "JTCK", DRV_GRP3),
+	MTK_PIN(41, "JTDI", DRV_GRP3),
+	MTK_PIN(42, "JTDO", DRV_GRP3),
+	MTK_PIN(43, "NCLE", DRV_GRP1),
+	MTK_PIN(44, "NCEB1", DRV_GRP1),
+	MTK_PIN(45, "NCEB0", DRV_GRP1),
+	MTK_PIN(46, "IR", DRV_FIXED),
+	MTK_PIN(47, "NREB", DRV_GRP1),
+	MTK_PIN(48, "NRNB", DRV_GRP1),
+	MTK_PIN(49, "I2S0_DATA", DRV_GRP1),
+	MTK_PIN(50, "I2S2_BCK", DRV_GRP1),
+	MTK_PIN(51, "I2S2_DATA_IN", DRV_GRP1),
+	MTK_PIN(52, "I2S2_LRCK", DRV_GRP1),
+	MTK_PIN(53, "SPI0_CSN", DRV_GRP1),
+	MTK_PIN(54, "SPI0_CK", DRV_GRP1),
+	MTK_PIN(55, "SPI0_MI", DRV_GRP1),
+	MTK_PIN(56, "SPI0_MO", DRV_GRP1),
+	MTK_PIN(57, "SDA1", DRV_FIXED),
+	MTK_PIN(58, "SCL1", DRV_FIXED),
+	MTK_PIN(59, "RAMBUF_I_CLK", DRV_FIXED),
+	MTK_PIN(60, "WB_RSTB", DRV_GRP3),
+	MTK_PIN(61, "F2W_DATA", DRV_GRP3),
+	MTK_PIN(62, "F2W_CLK", DRV_GRP3),
+	MTK_PIN(63, "WB_SCLK", DRV_GRP3),
+	MTK_PIN(64, "WB_SDATA", DRV_GRP3),
+	MTK_PIN(65, "WB_SEN", DRV_GRP3),
+	MTK_PIN(66, "WB_CRTL0", DRV_GRP3),
+	MTK_PIN(67, "WB_CRTL1", DRV_GRP3),
+	MTK_PIN(68, "WB_CRTL2", DRV_GRP3),
+	MTK_PIN(69, "WB_CRTL3", DRV_GRP3),
+	MTK_PIN(70, "WB_CRTL4", DRV_GRP3),
+	MTK_PIN(71, "WB_CRTL5", DRV_GRP3),
+	MTK_PIN(72, "I2S0_DATA_IN", DRV_GRP1),
+	MTK_PIN(73, "I2S0_LRCK", DRV_GRP1),
+	MTK_PIN(74, "I2S0_BCK", DRV_GRP1),
+	MTK_PIN(75, "SDA0", DRV_FIXED),
+	MTK_PIN(76, "SCL0", DRV_FIXED),
+	MTK_PIN(77, "SDA2", DRV_FIXED),
+	MTK_PIN(78, "SCL2", DRV_FIXED),
+	MTK_PIN(79, "URXD0", DRV_FIXED),
+	MTK_PIN(80, "UTXD0", DRV_FIXED),
+	MTK_PIN(81, "URXD1", DRV_FIXED),
+	MTK_PIN(82, "UTXD1", DRV_FIXED),
+	MTK_PIN(83, "LCM_RST", DRV_FIXED),
+	MTK_PIN(84, "DSI_TE", DRV_FIXED),
+	MTK_PIN(85, "MSDC2_CMD", DRV_GRP4),
+	MTK_PIN(86, "MSDC2_CLK", DRV_GRP4),
+	MTK_PIN(87, "MSDC2_DAT0", DRV_GRP4),
+	MTK_PIN(88, "MSDC2_DAT1", DRV_GRP4),
+	MTK_PIN(89, "MSDC2_DAT2", DRV_GRP4),
+	MTK_PIN(90, "MSDC2_DAT3", DRV_GRP4),
+	MTK_PIN(91, "TDN3", DRV_FIXED),
+	MTK_PIN(92, "TDP3", DRV_FIXED),
+	MTK_PIN(93, "TDN2", DRV_FIXED),
+	MTK_PIN(94, "TDP2", DRV_FIXED),
+	MTK_PIN(95, "TCN", DRV_FIXED),
+	MTK_PIN(96, "TCP", DRV_FIXED),
+	MTK_PIN(97, "TDN1", DRV_FIXED),
+	MTK_PIN(98, "TDP1", DRV_FIXED),
+	MTK_PIN(99, "TDN0", DRV_FIXED),
+	MTK_PIN(100, "TDP0", DRV_FIXED),
+	MTK_PIN(101, "SPI2_CSN", DRV_FIXED),
+	MTK_PIN(102, "SPI2_MI", DRV_FIXED),
+	MTK_PIN(103, "SPI2_MO", DRV_FIXED),
+	MTK_PIN(104, "SPI2_CLK", DRV_FIXED),
+	MTK_PIN(105, "MSDC1_CMD", DRV_GRP4),
+	MTK_PIN(106, "MSDC1_CLK", DRV_GRP4),
+	MTK_PIN(107, "MSDC1_DAT0", DRV_GRP4),
+	MTK_PIN(108, "MSDC1_DAT1", DRV_GRP4),
+	MTK_PIN(109, "MSDC1_DAT2", DRV_GRP4),
+	MTK_PIN(110, "MSDC1_DAT3", DRV_GRP4),
+	MTK_PIN(111, "MSDC0_DAT7", DRV_GRP4),
+	MTK_PIN(112, "MSDC0_DAT6", DRV_GRP4),
+	MTK_PIN(113, "MSDC0_DAT5", DRV_GRP4),
+	MTK_PIN(114, "MSDC0_DAT4", DRV_GRP4),
+	MTK_PIN(115, "MSDC0_RSTB", DRV_GRP4),
+	MTK_PIN(116, "MSDC0_CMD", DRV_GRP4),
+	MTK_PIN(117, "MSDC0_CLK", DRV_GRP4),
+	MTK_PIN(118, "MSDC0_DAT3", DRV_GRP4),
+	MTK_PIN(119, "MSDC0_DAT2", DRV_GRP4),
+	MTK_PIN(120, "MSDC0_DAT1", DRV_GRP4),
+	MTK_PIN(121, "MSDC0_DAT0", DRV_GRP4),
+	MTK_PIN(122, "CEC", DRV_FIXED),
+	MTK_PIN(123, "HTPLG", DRV_FIXED),
+	MTK_PIN(124, "HDMISCK", DRV_FIXED),
+	MTK_PIN(125, "HDMISD", DRV_FIXED),
+	MTK_PIN(126, "I2S0_MCLK", DRV_GRP1),
+	MTK_PIN(127, "RAMBUF_IDATA0", DRV_FIXED),
+	MTK_PIN(128, "RAMBUF_IDATA1", DRV_FIXED),
+	MTK_PIN(129, "RAMBUF_IDATA2", DRV_FIXED),
+	MTK_PIN(130, "RAMBUF_IDATA3", DRV_FIXED),
+	MTK_PIN(131, "RAMBUF_IDATA4", DRV_FIXED),
+	MTK_PIN(132, "RAMBUF_IDATA5", DRV_FIXED),
+	MTK_PIN(133, "RAMBUF_IDATA6", DRV_FIXED),
+	MTK_PIN(134, "RAMBUF_IDATA7", DRV_FIXED),
+	MTK_PIN(135, "RAMBUF_IDATA8", DRV_FIXED),
+	MTK_PIN(136, "RAMBUF_IDATA9", DRV_FIXED),
+	MTK_PIN(137, "RAMBUF_IDATA10", DRV_FIXED),
+	MTK_PIN(138, "RAMBUF_IDATA11", DRV_FIXED),
+	MTK_PIN(139, "RAMBUF_IDATA12", DRV_FIXED),
+	MTK_PIN(140, "RAMBUF_IDATA13", DRV_FIXED),
+	MTK_PIN(141, "RAMBUF_IDATA14", DRV_FIXED),
+	MTK_PIN(142, "RAMBUF_IDATA15", DRV_FIXED),
+	MTK_PIN(143, "RAMBUF_ODATA0", DRV_FIXED),
+	MTK_PIN(144, "RAMBUF_ODATA1", DRV_FIXED),
+	MTK_PIN(145, "RAMBUF_ODATA2", DRV_FIXED),
+	MTK_PIN(146, "RAMBUF_ODATA3", DRV_FIXED),
+	MTK_PIN(147, "RAMBUF_ODATA4", DRV_FIXED),
+	MTK_PIN(148, "RAMBUF_ODATA5", DRV_FIXED),
+	MTK_PIN(149, "RAMBUF_ODATA6", DRV_FIXED),
+	MTK_PIN(150, "RAMBUF_ODATA7", DRV_FIXED),
+	MTK_PIN(151, "RAMBUF_ODATA8", DRV_FIXED),
+	MTK_PIN(152, "RAMBUF_ODATA9", DRV_FIXED),
+	MTK_PIN(153, "RAMBUF_ODATA10", DRV_FIXED),
+	MTK_PIN(154, "RAMBUF_ODATA11", DRV_FIXED),
+	MTK_PIN(155, "RAMBUF_ODATA12", DRV_FIXED),
+	MTK_PIN(156, "RAMBUF_ODATA13", DRV_FIXED),
+	MTK_PIN(157, "RAMBUF_ODATA14", DRV_FIXED),
+	MTK_PIN(158, "RAMBUF_ODATA15", DRV_FIXED),
+	MTK_PIN(159, "RAMBUF_BE0", DRV_FIXED),
+	MTK_PIN(160, "RAMBUF_BE1", DRV_FIXED),
+	MTK_PIN(161, "AP2PT_INT", DRV_FIXED),
+	MTK_PIN(162, "AP2PT_INT_CLR", DRV_FIXED),
+	MTK_PIN(163, "PT2AP_INT", DRV_FIXED),
+	MTK_PIN(164, "PT2AP_INT_CLR", DRV_FIXED),
+	MTK_PIN(165, "AP2UP_INT", DRV_FIXED),
+	MTK_PIN(166, "AP2UP_INT_CLR", DRV_FIXED),
+	MTK_PIN(167, "UP2AP_INT", DRV_FIXED),
+	MTK_PIN(168, "UP2AP_INT_CLR", DRV_FIXED),
+	MTK_PIN(169, "RAMBUF_ADDR0", DRV_FIXED),
+	MTK_PIN(170, "RAMBUF_ADDR1", DRV_FIXED),
+	MTK_PIN(171, "RAMBUF_ADDR2", DRV_FIXED),
+	MTK_PIN(172, "RAMBUF_ADDR3", DRV_FIXED),
+	MTK_PIN(173, "RAMBUF_ADDR4", DRV_FIXED),
+	MTK_PIN(174, "RAMBUF_ADDR5", DRV_FIXED),
+	MTK_PIN(175, "RAMBUF_ADDR6", DRV_FIXED),
+	MTK_PIN(176, "RAMBUF_ADDR7", DRV_FIXED),
+	MTK_PIN(177, "RAMBUF_ADDR8", DRV_FIXED),
+	MTK_PIN(178, "RAMBUF_ADDR9", DRV_FIXED),
+	MTK_PIN(179, "RAMBUF_ADDR10", DRV_FIXED),
+	MTK_PIN(180, "RAMBUF_RW", DRV_FIXED),
+	MTK_PIN(181, "RAMBUF_LAST", DRV_FIXED),
+	MTK_PIN(182, "RAMBUF_HP", DRV_FIXED),
+	MTK_PIN(183, "RAMBUF_REQ", DRV_FIXED),
+	MTK_PIN(184, "RAMBUF_ALE", DRV_FIXED),
+	MTK_PIN(185, "RAMBUF_DLE", DRV_FIXED),
+	MTK_PIN(186, "RAMBUF_WDLE", DRV_FIXED),
+	MTK_PIN(187, "RAMBUF_O_CLK", DRV_FIXED),
+	MTK_PIN(188, "I2S2_MCLK", DRV_GRP1),
+	MTK_PIN(189, "I2S3_DATA", DRV_GRP1),
+	MTK_PIN(190, "I2S3_DATA_IN", DRV_GRP1),
+	MTK_PIN(191, "I2S3_BCK", DRV_GRP1),
+	MTK_PIN(192, "I2S3_LRCK", DRV_GRP1),
+	MTK_PIN(193, "I2S3_MCLK", DRV_GRP1),
+	MTK_PIN(194, "I2S4_DATA", DRV_GRP1),
+	MTK_PIN(195, "I2S4_DATA_IN", DRV_GRP1),
+	MTK_PIN(196, "I2S4_BCK", DRV_GRP1),
+	MTK_PIN(197, "I2S4_LRCK", DRV_GRP1),
+	MTK_PIN(198, "I2S4_MCLK", DRV_GRP1),
+	MTK_PIN(199, "SPI1_CLK", DRV_GRP3),
+	MTK_PIN(200, "SPDIF_OUT", DRV_GRP1),
+	MTK_PIN(201, "SPDIF_IN0", DRV_GRP1),
+	MTK_PIN(202, "SPDIF_IN1", DRV_GRP1),
+	MTK_PIN(203, "PWM0", DRV_GRP1),
+	MTK_PIN(204, "PWM1", DRV_GRP1),
+	MTK_PIN(205, "PWM2", DRV_GRP1),
+	MTK_PIN(206, "PWM3", DRV_GRP1),
+	MTK_PIN(207, "PWM4", DRV_GRP1),
+	MTK_PIN(208, "AUD_EXT_CK1", DRV_GRP1),
+	MTK_PIN(209, "AUD_EXT_CK2", DRV_GRP1),
+	MTK_PIN(210, "AUD_CLOCK", DRV_GRP3),
+	MTK_PIN(211, "DVP_RESET", DRV_GRP3),
+	MTK_PIN(212, "DVP_CLOCK", DRV_GRP3),
+	MTK_PIN(213, "DVP_CS", DRV_GRP3),
+	MTK_PIN(214, "DVP_CK", DRV_GRP3),
+	MTK_PIN(215, "DVP_DI", DRV_GRP3),
+	MTK_PIN(216, "DVP_DO", DRV_GRP3),
+	MTK_PIN(217, "AP_CS", DRV_GRP3),
+	MTK_PIN(218, "AP_CK", DRV_GRP3),
+	MTK_PIN(219, "AP_DI", DRV_GRP3),
+	MTK_PIN(220, "AP_DO", DRV_GRP3),
+	MTK_PIN(221, "DVD_BCLK", DRV_GRP3),
+	MTK_PIN(222, "T8032_CLK", DRV_GRP3),
+	MTK_PIN(223, "AP_BCLK", DRV_GRP3),
+	MTK_PIN(224, "HOST_CS", DRV_GRP3),
+	MTK_PIN(225, "HOST_CK", DRV_GRP3),
+	MTK_PIN(226, "HOST_DO0", DRV_GRP3),
+	MTK_PIN(227, "HOST_DO1", DRV_GRP3),
+	MTK_PIN(228, "SLV_CS", DRV_GRP3),
+	MTK_PIN(229, "SLV_CK", DRV_GRP3),
+	MTK_PIN(230, "SLV_DI0", DRV_GRP3),
+	MTK_PIN(231, "SLV_DI1", DRV_GRP3),
+	MTK_PIN(232, "AP2DSP_INT", DRV_GRP3),
+	MTK_PIN(233, "AP2DSP_INT_CLR", DRV_GRP3),
+	MTK_PIN(234, "DSP2AP_INT", DRV_GRP3),
+	MTK_PIN(235, "DSP2AP_INT_CLR", DRV_GRP3),
+	MTK_PIN(236, "EXT_SDIO3", DRV_GRP1),
+	MTK_PIN(237, "EXT_SDIO2", DRV_GRP1),
+	MTK_PIN(238, "EXT_SDIO1", DRV_GRP1),
+	MTK_PIN(239, "EXT_SDIO0", DRV_GRP1),
+	MTK_PIN(240, "EXT_XCS", DRV_GRP1),
+	MTK_PIN(241, "EXT_SCK", DRV_GRP1),
+	MTK_PIN(242, "URTS2", DRV_GRP1),
+	MTK_PIN(243, "UCTS2", DRV_GRP1),
+	MTK_PIN(244, "HDMI_SDA_RX", DRV_FIXED),
+	MTK_PIN(245, "HDMI_SCL_RX", DRV_FIXED),
+	MTK_PIN(246, "MHL_SENCE", DRV_FIXED),
+	MTK_PIN(247, "HDMI_HPD_CBUS_RX", DRV_FIXED),
+	MTK_PIN(248, "HDMI_TESTOUTP_RX", DRV_GRP1),
+	MTK_PIN(249, "MSDC0E_RSTB", DRV_GRP4),
+	MTK_PIN(250, "MSDC0E_DAT7", DRV_GRP4),
+	MTK_PIN(251, "MSDC0E_DAT6", DRV_GRP4),
+	MTK_PIN(252, "MSDC0E_DAT5", DRV_GRP4),
+	MTK_PIN(253, "MSDC0E_DAT4", DRV_GRP4),
+	MTK_PIN(254, "MSDC0E_DAT3", DRV_GRP4),
+	MTK_PIN(255, "MSDC0E_DAT2", DRV_GRP4),
+	MTK_PIN(256, "MSDC0E_DAT1", DRV_GRP4),
+	MTK_PIN(257, "MSDC0E_DAT0", DRV_GRP4),
+	MTK_PIN(258, "MSDC0E_CMD", DRV_GRP4),
+	MTK_PIN(259, "MSDC0E_CLK", DRV_GRP4),
+	MTK_PIN(260, "MSDC0E_DSL", DRV_GRP4),
+	MTK_PIN(261, "MSDC1_INS", DRV_GRP4),
+	MTK_PIN(262, "G2_TXEN", DRV_GRP1),
+	MTK_PIN(263, "G2_TXD3", DRV_GRP1),
+	MTK_PIN(264, "G2_TXD2", DRV_GRP1),
+	MTK_PIN(265, "G2_TXD1", DRV_GRP1),
+	MTK_PIN(266, "G2_TXD0", DRV_GRP1),
+	MTK_PIN(267, "G2_TXC", DRV_GRP1),
+	MTK_PIN(268, "G2_RXC", DRV_GRP1),
+	MTK_PIN(269, "G2_RXD0", DRV_GRP1),
+	MTK_PIN(270, "G2_RXD1", DRV_GRP1),
+	MTK_PIN(271, "G2_RXD2", DRV_GRP1),
+	MTK_PIN(272, "G2_RXD3", DRV_GRP1),
+	MTK_PIN(273, "ESW_INT", DRV_GRP1),
+	MTK_PIN(274, "G2_RXDV", DRV_GRP1),
+	MTK_PIN(275, "MDC", DRV_GRP1),
+	MTK_PIN(276, "MDIO", DRV_GRP1),
+	MTK_PIN(277, "ESW_RST", DRV_GRP1),
+	MTK_PIN(278, "JTAG_RESET", DRV_GRP3),
+	MTK_PIN(279, "USB3_RES_BOND", DRV_GRP1),
+};
+
+/* 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.
+ */
+
+/* AUDIO EXT CLK */
+static int mt7623_aud_ext_clk0_pins[] = { 208, };
+static int mt7623_aud_ext_clk0_funcs[] = { 1, };
+static int mt7623_aud_ext_clk1_pins[] = { 209, };
+static int mt7623_aud_ext_clk1_funcs[] = { 1, };
+
+/* DISP PWM */
+static int mt7623_disp_pwm_0_pins[] = { 72, };
+static int mt7623_disp_pwm_0_funcs[] = { 5, };
+static int mt7623_disp_pwm_1_pins[] = { 203, };
+static int mt7623_disp_pwm_1_funcs[] = { 2, };
+static int mt7623_disp_pwm_2_pins[] = { 208, };
+static int mt7623_disp_pwm_2_funcs[] = { 5, };
+
+/* ESW */
+static int mt7623_esw_int_pins[] = { 273, };
+static int mt7623_esw_int_funcs[] = { 1, };
+static int mt7623_esw_rst_pins[] = { 277, };
+static int mt7623_esw_rst_funcs[] = { 1, };
+
+/* EPHY */
+static int mt7623_ephy_pins[] = { 262, 263, 264, 265, 266, 267, 268,
+				  269, 270, 271, 272, 274, };
+static int mt7623_ephy_funcs[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, };
+
+/* EXT_SDIO */
+static int mt7623_ext_sdio_pins[] = { 236, 237, 238, 239, 240, 241, };
+static int mt7623_ext_sdio_funcs[] = { 1, 1, 1, 1, 1, 1, };
+
+/* HDMI RX */
+static int mt7623_hdmi_rx_pins[] = { 247, 248, };
+static int mt7623_hdmi_rx_funcs[] = { 1, 1 };
+static int mt7623_hdmi_rx_i2c_pins[] = { 244, 245, };
+static int mt7623_hdmi_rx_i2c_funcs[] = { 1, 1 };
+
+/* HDMI TX */
+static int mt7623_hdmi_cec_pins[] = { 122, };
+static int mt7623_hdmi_cec_funcs[] = { 1, };
+static int mt7623_hdmi_htplg_pins[] = { 123, };
+static int mt7623_hdmi_htplg_funcs[] = { 1, };
+static int mt7623_hdmi_i2c_pins[] = { 124, 125, };
+static int mt7623_hdmi_i2c_funcs[] = { 1, 1 };
+
+/* I2C */
+static int mt7623_i2c0_pins[] = { 75, 76, };
+static int mt7623_i2c0_funcs[] = { 1, 1, };
+static int mt7623_i2c1_0_pins[] = { 57, 58, };
+static int mt7623_i2c1_0_funcs[] = { 1, 1, };
+static int mt7623_i2c1_1_pins[] = { 242, 243, };
+static int mt7623_i2c1_1_funcs[] = { 4, 4, };
+static int mt7623_i2c1_2_pins[] = { 85, 86, };
+static int mt7623_i2c1_2_funcs[] = { 3, 3, };
+static int mt7623_i2c1_3_pins[] = { 105, 106, };
+static int mt7623_i2c1_3_funcs[] = { 3, 3, };
+static int mt7623_i2c1_4_pins[] = { 124, 125, };
+static int mt7623_i2c1_4_funcs[] = { 4, 4, };
+static int mt7623_i2c2_0_pins[] = { 77, 78, };
+static int mt7623_i2c2_0_funcs[] = { 1, 1, };
+static int mt7623_i2c2_1_pins[] = { 89, 90, };
+static int mt7623_i2c2_1_funcs[] = { 3, 3, };
+static int mt7623_i2c2_2_pins[] = { 109, 110, };
+static int mt7623_i2c2_2_funcs[] = { 3, 3, };
+static int mt7623_i2c2_3_pins[] = { 122, 123, };
+static int mt7623_i2c2_3_funcs[] = { 4, 4, };
+
+/* I2S */
+static int mt7623_i2s0_pins[] = { 49, 72, 73, 74, 126, };
+static int mt7623_i2s0_funcs[] = { 1, 1, 1, 1, 1, };
+static int mt7623_i2s1_pins[] = { 33, 34, 35, 36, 37, };
+static int mt7623_i2s1_funcs[] = { 1, 1, 1, 1, 1, };
+static int mt7623_i2s2_bclk_lrclk_mclk_pins[] = { 50, 52, 188, };
+static int mt7623_i2s2_bclk_lrclk_mclk_funcs[] = { 1, 1, 1, };
+static int mt7623_i2s2_data_in_pins[] = { 51, };
+static int mt7623_i2s2_data_in_funcs[] = { 1, };
+static int mt7623_i2s2_data_0_pins[] = { 203, };
+static int mt7623_i2s2_data_0_funcs[] = { 9, };
+static int mt7623_i2s2_data_1_pins[] = { 38,  };
+static int mt7623_i2s2_data_1_funcs[] = { 4, };
+static int mt7623_i2s3_bclk_lrclk_mclk_pins[] = { 191, 192, 193, };
+static int mt7623_i2s3_bclk_lrclk_mclk_funcs[] = { 1, 1, 1, };
+static int mt7623_i2s3_data_in_pins[] = { 190, };
+static int mt7623_i2s3_data_in_funcs[] = { 1, };
+static int mt7623_i2s3_data_0_pins[] = { 204, };
+static int mt7623_i2s3_data_0_funcs[] = { 9, };
+static int mt7623_i2s3_data_1_pins[] = { 2, };
+static int mt7623_i2s3_data_1_funcs[] = { 0, };
+static int mt7623_i2s4_pins[] = { 194, 195, 196, 197, 198, };
+static int mt7623_i2s4_funcs[] = { 1, 1, 1, 1, 1, };
+static int mt7623_i2s5_pins[] = { 16, 17, 30, 31, 32, };
+static int mt7623_i2s5_funcs[] = { 1, 1, 1, 1, 1, };
+
+/* IR */
+static int mt7623_ir_pins[] = { 46, };
+static int mt7623_ir_funcs[] = { 1, };
+
+/* LCD */
+static int mt7623_mipi_tx_pins[] = { 91, 92, 93, 94, 95, 96, 97, 98,
+				     99, 100, };
+static int mt7623_mipi_tx_funcs[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, };
+static int mt7623_dsi_te_pins[] = { 84, };
+static int mt7623_dsi_te_funcs[] = { 1, };
+static int mt7623_lcm_rst_pins[] = { 83, };
+static int mt7623_lcm_rst_funcs[] = { 1, };
+
+/* MDC/MDIO */
+static int mt7623_mdc_mdio_pins[] = { 275, 276, };
+static int mt7623_mdc_mdio_funcs[] = { 1, 1, };
+
+/* MSDC */
+static int mt7623_msdc0_pins[] = { 111, 112, 113, 114, 115, 116, 117, 118,
+				   119, 120, 121, };
+static int mt7623_msdc0_funcs[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, };
+static int mt7623_msdc1_pins[] = { 105, 106, 107, 108, 109, 110, };
+static int mt7623_msdc1_funcs[] = { 1, 1, 1, 1, 1, 1, };
+static int mt7623_msdc1_ins_pins[] = { 261, };
+static int mt7623_msdc1_ins_funcs[] = { 1, };
+static int mt7623_msdc1_wp_0_pins[] = { 29, };
+static int mt7623_msdc1_wp_0_funcs[] = { 1, };
+static int mt7623_msdc1_wp_1_pins[] = { 55, };
+static int mt7623_msdc1_wp_1_funcs[] = { 3, };
+static int mt7623_msdc1_wp_2_pins[] = { 209, };
+static int mt7623_msdc1_wp_2_funcs[] = { 2, };
+static int mt7623_msdc2_pins[] = { 85, 86, 87, 88, 89, 90, };
+static int mt7623_msdc2_funcs[] = { 1, 1, 1, 1, 1, 1, };
+static int mt7623_msdc3_pins[] = { 249, 250, 251, 252, 253, 254, 255, 256,
+				   257, 258, 259, 260, };
+static int mt7623_msdc3_funcs[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, };
+
+/* NAND */
+static int mt7623_nandc_pins[] = { 43, 47, 48, 111, 112, 113, 114, 115,
+				   116, 117, 118, 119, 120, 121, };
+static int mt7623_nandc_funcs[] = { 1, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+				   4, 4, };
+static int mt7623_nandc_ceb0_pins[] = { 45, };
+static int mt7623_nandc_ceb0_funcs[] = { 1, };
+static int mt7623_nandc_ceb1_pins[] = { 44, };
+static int mt7623_nandc_ceb1_funcs[] = { 1, };
+
+/* RTC */
+static int mt7623_rtc_pins[] = { 10, };
+static int mt7623_rtc_funcs[] = { 1, };
+
+/* OTG */
+static int mt7623_otg_iddig0_0_pins[] = { 29, };
+static int mt7623_otg_iddig0_0_funcs[] = { 1, };
+static int mt7623_otg_iddig0_1_pins[] = { 44, };
+static int mt7623_otg_iddig0_1_funcs[] = { 2, };
+static int mt7623_otg_iddig0_2_pins[] = { 236, };
+static int mt7623_otg_iddig0_2_funcs[] = { 2, };
+static int mt7623_otg_iddig1_0_pins[] = { 27, };
+static int mt7623_otg_iddig1_0_funcs[] = { 2, };
+static int mt7623_otg_iddig1_1_pins[] = { 47, };
+static int mt7623_otg_iddig1_1_funcs[] = { 2, };
+static int mt7623_otg_iddig1_2_pins[] = { 238, };
+static int mt7623_otg_iddig1_2_funcs[] = { 2, };
+static int mt7623_otg_drv_vbus0_0_pins[] = { 28, };
+static int mt7623_otg_drv_vbus0_0_funcs[] = { 1, };
+static int mt7623_otg_drv_vbus0_1_pins[] = { 45, };
+static int mt7623_otg_drv_vbus0_1_funcs[] = { 2, };
+static int mt7623_otg_drv_vbus0_2_pins[] = { 237, };
+static int mt7623_otg_drv_vbus0_2_funcs[] = { 2, };
+static int mt7623_otg_drv_vbus1_0_pins[] = { 26, };
+static int mt7623_otg_drv_vbus1_0_funcs[] = { 2, };
+static int mt7623_otg_drv_vbus1_1_pins[] = { 48, };
+static int mt7623_otg_drv_vbus1_1_funcs[] = { 2, };
+static int mt7623_otg_drv_vbus1_2_pins[] = { 239, };
+static int mt7623_otg_drv_vbus1_2_funcs[] = { 2, };
+
+/* PCIE */
+static int mt7623_pcie0_0_perst_pins[] = { 208, };
+static int mt7623_pcie0_0_perst_funcs[] = { 3, };
+static int mt7623_pcie0_1_perst_pins[] = { 22, };
+static int mt7623_pcie0_1_perst_funcs[] = { 2, };
+static int mt7623_pcie1_0_perst_pins[] = { 209, };
+static int mt7623_pcie1_0_perst_funcs[] = { 3, };
+static int mt7623_pcie1_1_perst_pins[] = { 23, };
+static int mt7623_pcie1_1_perst_funcs[] = { 2, };
+static int mt7623_pcie2_0_perst_pins[] = { 24, };
+static int mt7623_pcie2_0_perst_funcs[] = { 2, };
+static int mt7623_pcie2_1_perst_pins[] = { 29, };
+static int mt7623_pcie2_1_perst_funcs[] = { 6, };
+static int mt7623_pcie0_0_wake_pins[] = { 28, };
+static int mt7623_pcie0_0_wake_funcs[] = { 6, };
+static int mt7623_pcie0_1_wake_pins[] = { 251, };
+static int mt7623_pcie0_1_wake_funcs[] = { 6, };
+static int mt7623_pcie1_0_wake_pins[] = { 27, };
+static int mt7623_pcie1_0_wake_funcs[] = { 6, };
+static int mt7623_pcie1_1_wake_pins[] = { 253, };
+static int mt7623_pcie1_1_wake_funcs[] = { 6, };
+static int mt7623_pcie2_0_wake_pins[] = { 26, };
+static int mt7623_pcie2_0_wake_funcs[] = { 6, };
+static int mt7623_pcie2_1_wake_pins[] = { 255, };
+static int mt7623_pcie2_1_wake_funcs[] = { 6, };
+static int mt7623_pcie0_clkreq_pins[] = { 250, };
+static int mt7623_pcie0_clkreq_funcs[] = { 6, };
+static int mt7623_pcie1_clkreq_pins[] = { 252, };
+static int mt7623_pcie1_clkreq_funcs[] = { 6, };
+static int mt7623_pcie2_clkreq_pins[] = { 254, };
+static int mt7623_pcie2_clkreq_funcs[] = { 6, };
+/* the pcie_*_rev are only used for MT7623 */
+static int mt7623_pcie0_0_rev_perst_pins[] = { 208, };
+static int mt7623_pcie0_0_rev_perst_funcs[] = { 11, };
+static int mt7623_pcie0_1_rev_perst_pins[] = { 22, };
+static int mt7623_pcie0_1_rev_perst_funcs[] = { 10, };
+static int mt7623_pcie1_0_rev_perst_pins[] = { 209, };
+static int mt7623_pcie1_0_rev_perst_funcs[] = { 11, };
+static int mt7623_pcie1_1_rev_perst_pins[] = { 23, };
+static int mt7623_pcie1_1_rev_perst_funcs[] = { 10, };
+static int mt7623_pcie2_0_rev_perst_pins[] = { 24, };
+static int mt7623_pcie2_0_rev_perst_funcs[] = { 11, };
+static int mt7623_pcie2_1_rev_perst_pins[] = { 29, };
+static int mt7623_pcie2_1_rev_perst_funcs[] = { 14, };
+
+/* PCM */
+static int mt7623_pcm_clk_0_pins[] = { 18, };
+static int mt7623_pcm_clk_0_funcs[] = { 1, };
+static int mt7623_pcm_clk_1_pins[] = { 17, };
+static int mt7623_pcm_clk_1_funcs[] = { 3, };
+static int mt7623_pcm_clk_2_pins[] = { 35, };
+static int mt7623_pcm_clk_2_funcs[] = { 3, };
+static int mt7623_pcm_clk_3_pins[] = { 50, };
+static int mt7623_pcm_clk_3_funcs[] = { 3, };
+static int mt7623_pcm_clk_4_pins[] = { 74, };
+static int mt7623_pcm_clk_4_funcs[] = { 3, };
+static int mt7623_pcm_clk_5_pins[] = { 191, };
+static int mt7623_pcm_clk_5_funcs[] = { 3, };
+static int mt7623_pcm_clk_6_pins[] = { 196, };
+static int mt7623_pcm_clk_6_funcs[] = { 3, };
+static int mt7623_pcm_sync_0_pins[] = { 19, };
+static int mt7623_pcm_sync_0_funcs[] = { 1, };
+static int mt7623_pcm_sync_1_pins[] = { 30, };
+static int mt7623_pcm_sync_1_funcs[] = { 3, };
+static int mt7623_pcm_sync_2_pins[] = { 36, };
+static int mt7623_pcm_sync_2_funcs[] = { 3, };
+static int mt7623_pcm_sync_3_pins[] = { 52, };
+static int mt7623_pcm_sync_3_funcs[] = { 31, };
+static int mt7623_pcm_sync_4_pins[] = { 73, };
+static int mt7623_pcm_sync_4_funcs[] = { 3, };
+static int mt7623_pcm_sync_5_pins[] = { 192, };
+static int mt7623_pcm_sync_5_funcs[] = { 3, };
+static int mt7623_pcm_sync_6_pins[] = { 197, };
+static int mt7623_pcm_sync_6_funcs[] = { 3, };
+static int mt7623_pcm_rx_0_pins[] = { 20, };
+static int mt7623_pcm_rx_0_funcs[] = { 1, };
+static int mt7623_pcm_rx_1_pins[] = { 16, };
+static int mt7623_pcm_rx_1_funcs[] = { 3, };
+static int mt7623_pcm_rx_2_pins[] = { 34, };
+static int mt7623_pcm_rx_2_funcs[] = { 3, };
+static int mt7623_pcm_rx_3_pins[] = { 51, };
+static int mt7623_pcm_rx_3_funcs[] = { 3, };
+static int mt7623_pcm_rx_4_pins[] = { 72, };
+static int mt7623_pcm_rx_4_funcs[] = { 3, };
+static int mt7623_pcm_rx_5_pins[] = { 190, };
+static int mt7623_pcm_rx_5_funcs[] = { 3, };
+static int mt7623_pcm_rx_6_pins[] = { 195, };
+static int mt7623_pcm_rx_6_funcs[] = { 3, };
+static int mt7623_pcm_tx_0_pins[] = { 21, };
+static int mt7623_pcm_tx_0_funcs[] = { 1, };
+static int mt7623_pcm_tx_1_pins[] = { 32, };
+static int mt7623_pcm_tx_1_funcs[] = { 3, };
+static int mt7623_pcm_tx_2_pins[] = { 33, };
+static int mt7623_pcm_tx_2_funcs[] = { 3, };
+static int mt7623_pcm_tx_3_pins[] = { 38, };
+static int mt7623_pcm_tx_3_funcs[] = { 3, };
+static int mt7623_pcm_tx_4_pins[] = { 49, };
+static int mt7623_pcm_tx_4_funcs[] = { 3, };
+static int mt7623_pcm_tx_5_pins[] = { 189, };
+static int mt7623_pcm_tx_5_funcs[] = { 3, };
+static int mt7623_pcm_tx_6_pins[] = { 194, };
+static int mt7623_pcm_tx_6_funcs[] = { 3, };
+
+/* PWM */
+static int mt7623_pwm_ch1_0_pins[] = { 203, };
+static int mt7623_pwm_ch1_0_funcs[] = { 1, };
+static int mt7623_pwm_ch1_1_pins[] = { 208, };
+static int mt7623_pwm_ch1_1_funcs[] = { 2, };
+static int mt7623_pwm_ch1_2_pins[] = { 72, };
+static int mt7623_pwm_ch1_2_funcs[] = { 4, };
+static int mt7623_pwm_ch1_3_pins[] = { 88, };
+static int mt7623_pwm_ch1_3_funcs[] = { 3, };
+static int mt7623_pwm_ch1_4_pins[] = { 108, };
+static int mt7623_pwm_ch1_4_funcs[] = { 3, };
+static int mt7623_pwm_ch2_0_pins[] = { 204, };
+static int mt7623_pwm_ch2_0_funcs[] = { 1, };
+static int mt7623_pwm_ch2_1_pins[] = { 53, };
+static int mt7623_pwm_ch2_1_funcs[] = { 5, };
+static int mt7623_pwm_ch2_2_pins[] = { 88, };
+static int mt7623_pwm_ch2_2_funcs[] = { 6, };
+static int mt7623_pwm_ch2_3_pins[] = { 108, };
+static int mt7623_pwm_ch2_3_funcs[] = { 6, };
+static int mt7623_pwm_ch2_4_pins[] = { 209, };
+static int mt7623_pwm_ch2_4_funcs[] = { 5, };
+static int mt7623_pwm_ch3_0_pins[] = { 205, };
+static int mt7623_pwm_ch3_0_funcs[] = { 1, };
+static int mt7623_pwm_ch3_1_pins[] = { 55, };
+static int mt7623_pwm_ch3_1_funcs[] = { 5, };
+static int mt7623_pwm_ch3_2_pins[] = { 89, };
+static int mt7623_pwm_ch3_2_funcs[] = { 6, };
+static int mt7623_pwm_ch3_3_pins[] = { 109, };
+static int mt7623_pwm_ch3_3_funcs[] = { 6, };
+static int mt7623_pwm_ch4_0_pins[] = { 206, };
+static int mt7623_pwm_ch4_0_funcs[] = { 1, };
+static int mt7623_pwm_ch4_1_pins[] = { 90, };
+static int mt7623_pwm_ch4_1_funcs[] = { 6, };
+static int mt7623_pwm_ch4_2_pins[] = { 110, };
+static int mt7623_pwm_ch4_2_funcs[] = { 6, };
+static int mt7623_pwm_ch4_3_pins[] = { 124, };
+static int mt7623_pwm_ch4_3_funcs[] = { 5, };
+static int mt7623_pwm_ch5_0_pins[] = { 207, };
+static int mt7623_pwm_ch5_0_funcs[] = { 1, };
+static int mt7623_pwm_ch5_1_pins[] = { 125, };
+static int mt7623_pwm_ch5_1_funcs[] = { 5, };
+
+/* PWRAP */
+static int mt7623_pwrap_pins[] = { 0, 1, 2, 3, 4, 5, 6, };
+static int mt7623_pwrap_funcs[] = { 1, 1, 1, 1, 1, 1, 1, };
+
+/* SPDIF */
+static int mt7623_spdif_in0_0_pins[] = { 56, };
+static int mt7623_spdif_in0_0_funcs[] = { 3, };
+static int mt7623_spdif_in0_1_pins[] = { 201, };
+static int mt7623_spdif_in0_1_funcs[] = { 1, };
+static int mt7623_spdif_in1_0_pins[] = { 54, };
+static int mt7623_spdif_in1_0_funcs[] = { 3, };
+static int mt7623_spdif_in1_1_pins[] = { 202, };
+static int mt7623_spdif_in1_1_funcs[] = { 1, };
+static int mt7623_spdif_out_pins[] = { 202, };
+static int mt7623_spdif_out_funcs[] = { 1, };
+
+/* SPI */
+static int mt7623_spi0_pins[] = { 53, 54, 55, 56, };
+static int mt7623_spi0_funcs[] = { 1, 1, 1, 1, };
+static int mt7623_spi1_pins[] = { 7, 199, 8, 9, };
+static int mt7623_spi1_funcs[] = { 1, 1, 1, 1, };
+static int mt7623_spi2_pins[] = { 101, 104, 102, 103, };
+static int mt7623_spi2_funcs[] = { 1, 1, 1, 1, };
+
+/* UART */
+static int mt7623_uart0_0_txd_rxd_pins[] = { 79, 80, };
+static int mt7623_uart0_0_txd_rxd_funcs[] = { 1, 1, };
+static int mt7623_uart0_1_txd_rxd_pins[] = { 87, 88, };
+static int mt7623_uart0_1_txd_rxd_funcs[] = { 5, 5, };
+static int mt7623_uart0_2_txd_rxd_pins[] = { 107, 108, };
+static int mt7623_uart0_2_txd_rxd_funcs[] = { 5, 5, };
+static int mt7623_uart0_3_txd_rxd_pins[] = { 123, 122, };
+static int mt7623_uart0_3_txd_rxd_funcs[] = { 5, 5, };
+static int mt7623_uart0_rts_cts_pins[] = { 22, 23, };
+static int mt7623_uart0_rts_cts_funcs[] = { 1, 1, };
+static int mt7623_uart1_0_txd_rxd_pins[] = { 81, 82, };
+static int mt7623_uart1_0_txd_rxd_funcs[] = { 1, 1, };
+static int mt7623_uart1_1_txd_rxd_pins[] = { 89, 90, };
+static int mt7623_uart1_1_txd_rxd_funcs[] = { 5, 5, };
+static int mt7623_uart1_2_txd_rxd_pins[] = { 109, 110, };
+static int mt7623_uart1_2_txd_rxd_funcs[] = { 5, 5, };
+static int mt7623_uart1_rts_cts_pins[] = { 24, 25, };
+static int mt7623_uart1_rts_cts_funcs[] = { 1, 1, };
+static int mt7623_uart2_0_txd_rxd_pins[] = { 14, 15, };
+static int mt7623_uart2_0_txd_rxd_funcs[] = { 1, 1, };
+static int mt7623_uart2_1_txd_rxd_pins[] = { 200, 201, };
+static int mt7623_uart2_1_txd_rxd_funcs[] = { 6, 6, };
+static int mt7623_uart2_rts_cts_pins[] = { 242, 243, };
+static int mt7623_uart2_rts_cts_funcs[] = { 1, 1, };
+static int mt7623_uart3_txd_rxd_pins[] = { 242, 243, };
+static int mt7623_uart3_txd_rxd_funcs[] = { 2, 2, };
+static int mt7623_uart3_rts_cts_pins[] = { 26, 27, };
+static int mt7623_uart3_rts_cts_funcs[] = { 1, 1, };
+
+/* Watchdog */
+static int mt7623_watchdog_0_pins[] = { 11, };
+static int mt7623_watchdog_0_funcs[] = { 1, };
+static int mt7623_watchdog_1_pins[] = { 121, };
+static int mt7623_watchdog_1_funcs[] = { 5, };
+
+static const struct mtk_group_desc mt7623_groups[] = {
+	PINCTRL_PIN_GROUP("aud_ext_clk0", mt7623_aud_ext_clk0),
+	PINCTRL_PIN_GROUP("aud_ext_clk1", mt7623_aud_ext_clk1),
+	PINCTRL_PIN_GROUP("dsi_te", mt7623_dsi_te),
+	PINCTRL_PIN_GROUP("disp_pwm_0", mt7623_disp_pwm_0),
+	PINCTRL_PIN_GROUP("disp_pwm_1", mt7623_disp_pwm_1),
+	PINCTRL_PIN_GROUP("disp_pwm_2", mt7623_disp_pwm_2),
+	PINCTRL_PIN_GROUP("ephy", mt7623_ephy),
+	PINCTRL_PIN_GROUP("esw_int", mt7623_esw_int),
+	PINCTRL_PIN_GROUP("esw_rst", mt7623_esw_rst),
+	PINCTRL_PIN_GROUP("ext_sdio", mt7623_ext_sdio),
+	PINCTRL_PIN_GROUP("hdmi_cec", mt7623_hdmi_cec),
+	PINCTRL_PIN_GROUP("hdmi_htplg", mt7623_hdmi_htplg),
+	PINCTRL_PIN_GROUP("hdmi_i2c", mt7623_hdmi_i2c),
+	PINCTRL_PIN_GROUP("hdmi_rx", mt7623_hdmi_rx),
+	PINCTRL_PIN_GROUP("hdmi_rx_i2c", mt7623_hdmi_rx_i2c),
+	PINCTRL_PIN_GROUP("i2c0", mt7623_i2c0),
+	PINCTRL_PIN_GROUP("i2c1_0", mt7623_i2c1_0),
+	PINCTRL_PIN_GROUP("i2c1_1", mt7623_i2c1_1),
+	PINCTRL_PIN_GROUP("i2c1_2", mt7623_i2c1_2),
+	PINCTRL_PIN_GROUP("i2c1_3", mt7623_i2c1_3),
+	PINCTRL_PIN_GROUP("i2c1_4", mt7623_i2c1_4),
+	PINCTRL_PIN_GROUP("i2c2_0", mt7623_i2c2_0),
+	PINCTRL_PIN_GROUP("i2c2_1", mt7623_i2c2_1),
+	PINCTRL_PIN_GROUP("i2c2_2", mt7623_i2c2_2),
+	PINCTRL_PIN_GROUP("i2c2_3", mt7623_i2c2_3),
+	PINCTRL_PIN_GROUP("i2s0", mt7623_i2s0),
+	PINCTRL_PIN_GROUP("i2s1", mt7623_i2s1),
+	PINCTRL_PIN_GROUP("i2s4", mt7623_i2s4),
+	PINCTRL_PIN_GROUP("i2s5", mt7623_i2s5),
+	PINCTRL_PIN_GROUP("i2s2_bclk_lrclk_mclk", mt7623_i2s2_bclk_lrclk_mclk),
+	PINCTRL_PIN_GROUP("i2s3_bclk_lrclk_mclk", mt7623_i2s3_bclk_lrclk_mclk),
+	PINCTRL_PIN_GROUP("i2s2_data_in", mt7623_i2s2_data_in),
+	PINCTRL_PIN_GROUP("i2s3_data_in", mt7623_i2s3_data_in),
+	PINCTRL_PIN_GROUP("i2s2_data_0", mt7623_i2s2_data_0),
+	PINCTRL_PIN_GROUP("i2s2_data_1", mt7623_i2s2_data_1),
+	PINCTRL_PIN_GROUP("i2s3_data_0", mt7623_i2s3_data_0),
+	PINCTRL_PIN_GROUP("i2s3_data_1", mt7623_i2s3_data_1),
+	PINCTRL_PIN_GROUP("ir", mt7623_ir),
+	PINCTRL_PIN_GROUP("lcm_rst", mt7623_lcm_rst),
+	PINCTRL_PIN_GROUP("mdc_mdio", mt7623_mdc_mdio),
+	PINCTRL_PIN_GROUP("mipi_tx", mt7623_mipi_tx),
+	PINCTRL_PIN_GROUP("msdc0", mt7623_msdc0),
+	PINCTRL_PIN_GROUP("msdc1", mt7623_msdc1),
+	PINCTRL_PIN_GROUP("msdc1_ins", mt7623_msdc1_ins),
+	PINCTRL_PIN_GROUP("msdc1_wp_0", mt7623_msdc1_wp_0),
+	PINCTRL_PIN_GROUP("msdc1_wp_1", mt7623_msdc1_wp_1),
+	PINCTRL_PIN_GROUP("msdc1_wp_2", mt7623_msdc1_wp_2),
+	PINCTRL_PIN_GROUP("msdc2", mt7623_msdc2),
+	PINCTRL_PIN_GROUP("msdc3", mt7623_msdc3),
+	PINCTRL_PIN_GROUP("nandc", mt7623_nandc),
+	PINCTRL_PIN_GROUP("nandc_ceb0", mt7623_nandc_ceb0),
+	PINCTRL_PIN_GROUP("nandc_ceb1", mt7623_nandc_ceb1),
+	PINCTRL_PIN_GROUP("otg_iddig0_0", mt7623_otg_iddig0_0),
+	PINCTRL_PIN_GROUP("otg_iddig0_1", mt7623_otg_iddig0_1),
+	PINCTRL_PIN_GROUP("otg_iddig0_2", mt7623_otg_iddig0_2),
+	PINCTRL_PIN_GROUP("otg_iddig1_0", mt7623_otg_iddig1_0),
+	PINCTRL_PIN_GROUP("otg_iddig1_1", mt7623_otg_iddig1_1),
+	PINCTRL_PIN_GROUP("otg_iddig1_2", mt7623_otg_iddig1_2),
+	PINCTRL_PIN_GROUP("otg_drv_vbus0_0", mt7623_otg_drv_vbus0_0),
+	PINCTRL_PIN_GROUP("otg_drv_vbus0_1", mt7623_otg_drv_vbus0_1),
+	PINCTRL_PIN_GROUP("otg_drv_vbus0_2", mt7623_otg_drv_vbus0_2),
+	PINCTRL_PIN_GROUP("otg_drv_vbus1_0", mt7623_otg_drv_vbus1_0),
+	PINCTRL_PIN_GROUP("otg_drv_vbus1_1", mt7623_otg_drv_vbus1_1),
+	PINCTRL_PIN_GROUP("otg_drv_vbus1_2", mt7623_otg_drv_vbus1_2),
+	PINCTRL_PIN_GROUP("pcie0_0_perst", mt7623_pcie0_0_perst),
+	PINCTRL_PIN_GROUP("pcie0_1_perst", mt7623_pcie0_1_perst),
+	PINCTRL_PIN_GROUP("pcie1_0_perst", mt7623_pcie1_0_perst),
+	PINCTRL_PIN_GROUP("pcie1_1_perst", mt7623_pcie1_1_perst),
+	PINCTRL_PIN_GROUP("pcie1_1_perst", mt7623_pcie1_1_perst),
+	PINCTRL_PIN_GROUP("pcie0_0_rev_perst", mt7623_pcie0_0_rev_perst),
+	PINCTRL_PIN_GROUP("pcie0_1_rev_perst", mt7623_pcie0_1_rev_perst),
+	PINCTRL_PIN_GROUP("pcie1_0_rev_perst", mt7623_pcie1_0_rev_perst),
+	PINCTRL_PIN_GROUP("pcie1_1_rev_perst", mt7623_pcie1_1_rev_perst),
+	PINCTRL_PIN_GROUP("pcie2_0_rev_perst", mt7623_pcie2_0_rev_perst),
+	PINCTRL_PIN_GROUP("pcie2_1_rev_perst", mt7623_pcie2_1_rev_perst),
+	PINCTRL_PIN_GROUP("pcie2_0_perst", mt7623_pcie2_0_perst),
+	PINCTRL_PIN_GROUP("pcie2_1_perst", mt7623_pcie2_1_perst),
+	PINCTRL_PIN_GROUP("pcie0_0_wake", mt7623_pcie0_0_wake),
+	PINCTRL_PIN_GROUP("pcie0_1_wake", mt7623_pcie0_1_wake),
+	PINCTRL_PIN_GROUP("pcie1_0_wake", mt7623_pcie1_0_wake),
+	PINCTRL_PIN_GROUP("pcie1_1_wake", mt7623_pcie1_1_wake),
+	PINCTRL_PIN_GROUP("pcie2_0_wake", mt7623_pcie2_0_wake),
+	PINCTRL_PIN_GROUP("pcie2_1_wake", mt7623_pcie2_1_wake),
+	PINCTRL_PIN_GROUP("pcie0_clkreq", mt7623_pcie0_clkreq),
+	PINCTRL_PIN_GROUP("pcie1_clkreq", mt7623_pcie1_clkreq),
+	PINCTRL_PIN_GROUP("pcie2_clkreq", mt7623_pcie2_clkreq),
+	PINCTRL_PIN_GROUP("pcm_clk_0", mt7623_pcm_clk_0),
+	PINCTRL_PIN_GROUP("pcm_clk_1", mt7623_pcm_clk_1),
+	PINCTRL_PIN_GROUP("pcm_clk_2", mt7623_pcm_clk_2),
+	PINCTRL_PIN_GROUP("pcm_clk_3", mt7623_pcm_clk_3),
+	PINCTRL_PIN_GROUP("pcm_clk_4", mt7623_pcm_clk_4),
+	PINCTRL_PIN_GROUP("pcm_clk_5", mt7623_pcm_clk_5),
+	PINCTRL_PIN_GROUP("pcm_clk_6", mt7623_pcm_clk_6),
+	PINCTRL_PIN_GROUP("pcm_sync_0", mt7623_pcm_sync_0),
+	PINCTRL_PIN_GROUP("pcm_sync_1", mt7623_pcm_sync_1),
+	PINCTRL_PIN_GROUP("pcm_sync_2", mt7623_pcm_sync_2),
+	PINCTRL_PIN_GROUP("pcm_sync_3", mt7623_pcm_sync_3),
+	PINCTRL_PIN_GROUP("pcm_sync_4", mt7623_pcm_sync_4),
+	PINCTRL_PIN_GROUP("pcm_sync_5", mt7623_pcm_sync_5),
+	PINCTRL_PIN_GROUP("pcm_sync_6", mt7623_pcm_sync_6),
+	PINCTRL_PIN_GROUP("pcm_rx_0", mt7623_pcm_rx_0),
+	PINCTRL_PIN_GROUP("pcm_rx_1", mt7623_pcm_rx_1),
+	PINCTRL_PIN_GROUP("pcm_rx_2", mt7623_pcm_rx_2),
+	PINCTRL_PIN_GROUP("pcm_rx_3", mt7623_pcm_rx_3),
+	PINCTRL_PIN_GROUP("pcm_rx_4", mt7623_pcm_rx_4),
+	PINCTRL_PIN_GROUP("pcm_rx_5", mt7623_pcm_rx_5),
+	PINCTRL_PIN_GROUP("pcm_rx_6", mt7623_pcm_rx_6),
+	PINCTRL_PIN_GROUP("pcm_tx_0", mt7623_pcm_tx_0),
+	PINCTRL_PIN_GROUP("pcm_tx_1", mt7623_pcm_tx_1),
+	PINCTRL_PIN_GROUP("pcm_tx_2", mt7623_pcm_tx_2),
+	PINCTRL_PIN_GROUP("pcm_tx_3", mt7623_pcm_tx_3),
+	PINCTRL_PIN_GROUP("pcm_tx_4", mt7623_pcm_tx_4),
+	PINCTRL_PIN_GROUP("pcm_tx_5", mt7623_pcm_tx_5),
+	PINCTRL_PIN_GROUP("pcm_tx_6", mt7623_pcm_tx_6),
+	PINCTRL_PIN_GROUP("pwm_ch1_0", mt7623_pwm_ch1_0),
+	PINCTRL_PIN_GROUP("pwm_ch1_1", mt7623_pwm_ch1_1),
+	PINCTRL_PIN_GROUP("pwm_ch1_2", mt7623_pwm_ch1_2),
+	PINCTRL_PIN_GROUP("pwm_ch1_3", mt7623_pwm_ch1_3),
+	PINCTRL_PIN_GROUP("pwm_ch1_4", mt7623_pwm_ch1_4),
+	PINCTRL_PIN_GROUP("pwm_ch2_0", mt7623_pwm_ch2_0),
+	PINCTRL_PIN_GROUP("pwm_ch2_1", mt7623_pwm_ch2_1),
+	PINCTRL_PIN_GROUP("pwm_ch2_2", mt7623_pwm_ch2_2),
+	PINCTRL_PIN_GROUP("pwm_ch2_3", mt7623_pwm_ch2_3),
+	PINCTRL_PIN_GROUP("pwm_ch2_4", mt7623_pwm_ch2_4),
+	PINCTRL_PIN_GROUP("pwm_ch3_0", mt7623_pwm_ch3_0),
+	PINCTRL_PIN_GROUP("pwm_ch3_1", mt7623_pwm_ch3_1),
+	PINCTRL_PIN_GROUP("pwm_ch3_2", mt7623_pwm_ch3_2),
+	PINCTRL_PIN_GROUP("pwm_ch3_3", mt7623_pwm_ch3_3),
+	PINCTRL_PIN_GROUP("pwm_ch4_0", mt7623_pwm_ch4_0),
+	PINCTRL_PIN_GROUP("pwm_ch4_1", mt7623_pwm_ch4_1),
+	PINCTRL_PIN_GROUP("pwm_ch4_2", mt7623_pwm_ch4_2),
+	PINCTRL_PIN_GROUP("pwm_ch4_3", mt7623_pwm_ch4_3),
+	PINCTRL_PIN_GROUP("pwm_ch5_0", mt7623_pwm_ch5_0),
+	PINCTRL_PIN_GROUP("pwm_ch5_1", mt7623_pwm_ch5_1),
+	PINCTRL_PIN_GROUP("pwrap", mt7623_pwrap),
+	PINCTRL_PIN_GROUP("rtc", mt7623_rtc),
+	PINCTRL_PIN_GROUP("spdif_in0_0", mt7623_spdif_in0_0),
+	PINCTRL_PIN_GROUP("spdif_in0_1", mt7623_spdif_in0_1),
+	PINCTRL_PIN_GROUP("spdif_in1_0", mt7623_spdif_in1_0),
+	PINCTRL_PIN_GROUP("spdif_in1_1", mt7623_spdif_in1_1),
+	PINCTRL_PIN_GROUP("spdif_out", mt7623_spdif_out),
+	PINCTRL_PIN_GROUP("spi0", mt7623_spi0),
+	PINCTRL_PIN_GROUP("spi1", mt7623_spi1),
+	PINCTRL_PIN_GROUP("spi2", mt7623_spi2),
+	PINCTRL_PIN_GROUP("uart0_0_txd_rxd",  mt7623_uart0_0_txd_rxd),
+	PINCTRL_PIN_GROUP("uart0_1_txd_rxd",  mt7623_uart0_1_txd_rxd),
+	PINCTRL_PIN_GROUP("uart0_2_txd_rxd",  mt7623_uart0_2_txd_rxd),
+	PINCTRL_PIN_GROUP("uart0_3_txd_rxd",  mt7623_uart0_3_txd_rxd),
+	PINCTRL_PIN_GROUP("uart1_0_txd_rxd",  mt7623_uart1_0_txd_rxd),
+	PINCTRL_PIN_GROUP("uart1_1_txd_rxd",  mt7623_uart1_1_txd_rxd),
+	PINCTRL_PIN_GROUP("uart1_2_txd_rxd",  mt7623_uart1_2_txd_rxd),
+	PINCTRL_PIN_GROUP("uart2_0_txd_rxd",  mt7623_uart2_0_txd_rxd),
+	PINCTRL_PIN_GROUP("uart2_1_txd_rxd",  mt7623_uart2_1_txd_rxd),
+	PINCTRL_PIN_GROUP("uart3_txd_rxd",  mt7623_uart3_txd_rxd),
+	PINCTRL_PIN_GROUP("uart0_rts_cts",  mt7623_uart0_rts_cts),
+	PINCTRL_PIN_GROUP("uart1_rts_cts",  mt7623_uart1_rts_cts),
+	PINCTRL_PIN_GROUP("uart2_rts_cts",  mt7623_uart2_rts_cts),
+	PINCTRL_PIN_GROUP("uart3_rts_cts",  mt7623_uart3_rts_cts),
+	PINCTRL_PIN_GROUP("watchdog_0", mt7623_watchdog_0),
+	PINCTRL_PIN_GROUP("watchdog_1", mt7623_watchdog_1),
+};
+
+/* 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 mt7623_aud_clk_groups[] = { "aud_ext_clk0",
+						"aud_ext_clk1", };
+static const char *const mt7623_disp_pwm_groups[] = { "disp_pwm_0",
+						"disp_pwm_1",
+						"disp_pwm_2", };
+static const char *const mt7623_ethernet_groups[] = { "esw_int", "esw_rst",
+						"ephy", "mdc_mdio", };
+static const char *const mt7623_ext_sdio_groups[] = { "ext_sdio", };
+static const char *const mt7623_hdmi_groups[] = { "hdmi_cec", "hdmi_htplg",
+						"hdmi_i2c", "hdmi_rx",
+						"hdmi_rx_i2c", };
+static const char *const mt7623_i2c_groups[] = { "i2c0", "i2c1_0", "i2c1_1",
+						"i2c1_2", "i2c1_3", "i2c1_4",
+						"i2c2_0", "i2c2_1", "i2c2_2",
+						"i2c2_3", };
+static const char *const mt7623_i2s_groups[] = { "i2s0", "i2s1",
+						"i2s2_bclk_lrclk_mclk",
+						"i2s3_bclk_lrclk_mclk",
+						"i2s4", "i2s5",
+						"i2s2_data_in", "i2s3_data_in",
+						"i2s2_data_0", "i2s2_data_1",
+						"i2s3_data_0", "i2s3_data_1",};
+static const char *const mt7623_ir_groups[] = { "ir", };
+static const char *const mt7623_lcd_groups[] = { "dsi_te", "lcm_rst",
+						"mipi_tx", };
+static const char *const mt7623_msdc_groups[] = { "msdc0", "msdc1",
+						"msdc1_ins", "msdc1_wp_0",
+						"msdc1_wp_1", "msdc1_wp_2",
+						"msdc2", "msdc3", };
+static const char *const mt7623_nandc_groups[] = { "nandc", "nandc_ceb0",
+						"nandc_ceb1", };
+static const char *const mt7623_otg_groups[] = { "otg_iddig0_0",
+						"otg_iddig0_1",
+						"otg_iddig0_2",
+						"otg_iddig1_0",
+						"otg_iddig1_1",
+						"otg_iddig1_2",
+						"otg_drv_vbus0_0",
+						"otg_drv_vbus0_1",
+						"otg_drv_vbus0_2",
+						"otg_drv_vbus1_0",
+						"otg_drv_vbus1_1",
+						"otg_drv_vbus1_2", };
+static const char *const mt7623_pcie_groups[] = { "pcie0_0_perst",
+						"pcie0_1_perst",
+						"pcie1_0_perst",
+						"pcie1_1_perst",
+						"pcie2_0_perst",
+						"pcie2_1_perst",
+						"pcie0_0_rev_perst",
+						"pcie0_1_rev_perst",
+						"pcie1_0_rev_perst",
+						"pcie1_1_rev_perst",
+						"pcie2_0_rev_perst",
+						"pcie2_1_rev_perst",
+						"pcie0_0_wake", "pcie0_1_wake",
+						"pcie2_0_wake", "pcie2_1_wake",
+						"pcie0_clkreq", "pcie1_clkreq",
+						"pcie2_clkreq", };
+static const char *const mt7623_pcm_groups[] = { "pcm_clk_0", "pcm_clk_1",
+						"pcm_clk_2", "pcm_clk_3",
+						"pcm_clk_4", "pcm_clk_5",
+						"pcm_clk_6", "pcm_sync_0",
+						"pcm_sync_1", "pcm_sync_2",
+						"pcm_sync_3", "pcm_sync_4",
+						"pcm_sync_5", "pcm_sync_6",
+						"pcm_rx_0", "pcm_rx_1",
+						"pcm_rx_2", "pcm_rx_3",
+						"pcm_rx_4", "pcm_rx_5",
+						"pcm_rx_6", "pcm_tx_0",
+						"pcm_tx_1", "pcm_tx_2",
+						"pcm_tx_3", "pcm_tx_4",
+						"pcm_tx_5", "pcm_tx_6", };
+static const char *const mt7623_pwm_groups[] = { "pwm_ch1_0", "pwm_ch1_1",
+						"pwm_ch1_2", "pwm_ch2_0",
+						"pwm_ch2_1", "pwm_ch2_2",
+						"pwm_ch3_0", "pwm_ch3_1",
+						"pwm_ch3_2", "pwm_ch4_0",
+						"pwm_ch4_1", "pwm_ch4_2",
+						"pwm_ch4_3", "pwm_ch5_0",
+						"pwm_ch5_1", "pwm_ch5_2",
+						"pwm_ch6_0", "pwm_ch6_1",
+						"pwm_ch6_2", "pwm_ch6_3",
+						"pwm_ch7_0", "pwm_ch7_1",
+						"pwm_ch7_2", };
+static const char *const mt7623_pwrap_groups[] = { "pwrap", };
+static const char *const mt7623_rtc_groups[] = { "rtc", };
+static const char *const mt7623_spi_groups[] = { "spi0", "spi2", "spi2", };
+static const char *const mt7623_spdif_groups[] = { "spdif_in0_0",
+						"spdif_in0_1", "spdif_in1_0",
+						"spdif_in1_1", "spdif_out", };
+static const char *const mt7623_uart_groups[] = { "uart0_0_txd_rxd",
+						"uart0_1_txd_rxd",
+						"uart0_2_txd_rxd",
+						"uart0_3_txd_rxd",
+						"uart1_0_txd_rxd",
+						"uart1_1_txd_rxd",
+						"uart1_2_txd_rxd",
+						"uart2_0_txd_rxd",
+						"uart2_1_txd_rxd",
+						"uart3_txd_rxd",
+						"uart0_rts_cts",
+						"uart1_rts_cts",
+						"uart2_rts_cts",
+						"uart3_rts_cts", };
+static const char *const mt7623_wdt_groups[] = { "watchdog_0", "watchdog_1", };
+
+static const struct mtk_function_desc mt7623_functions[] = {
+	{"audck", mt7623_aud_clk_groups, ARRAY_SIZE(mt7623_aud_clk_groups)},
+	{"disp", mt7623_disp_pwm_groups, ARRAY_SIZE(mt7623_disp_pwm_groups)},
+	{"eth",	mt7623_ethernet_groups, ARRAY_SIZE(mt7623_ethernet_groups)},
+	{"sdio", mt7623_ext_sdio_groups, ARRAY_SIZE(mt7623_ext_sdio_groups)},
+	{"hdmi", mt7623_hdmi_groups, ARRAY_SIZE(mt7623_hdmi_groups)},
+	{"i2c", mt7623_i2c_groups, ARRAY_SIZE(mt7623_i2c_groups)},
+	{"i2s",	mt7623_i2s_groups, ARRAY_SIZE(mt7623_i2s_groups)},
+	{"ir",	mt7623_ir_groups, ARRAY_SIZE(mt7623_ir_groups)},
+	{"lcd", mt7623_lcd_groups, ARRAY_SIZE(mt7623_lcd_groups)},
+	{"msdc", mt7623_msdc_groups, ARRAY_SIZE(mt7623_msdc_groups)},
+	{"nand", mt7623_nandc_groups, ARRAY_SIZE(mt7623_nandc_groups)},
+	{"otg", mt7623_otg_groups, ARRAY_SIZE(mt7623_otg_groups)},
+	{"pcie", mt7623_pcie_groups, ARRAY_SIZE(mt7623_pcie_groups)},
+	{"pcm",	mt7623_pcm_groups, ARRAY_SIZE(mt7623_pcm_groups)},
+	{"pwm",	mt7623_pwm_groups, ARRAY_SIZE(mt7623_pwm_groups)},
+	{"pwrap", mt7623_pwrap_groups, ARRAY_SIZE(mt7623_pwrap_groups)},
+	{"rtc", mt7623_rtc_groups, ARRAY_SIZE(mt7623_rtc_groups)},
+	{"spi",	mt7623_spi_groups, ARRAY_SIZE(mt7623_spi_groups)},
+	{"spdif", mt7623_spdif_groups, ARRAY_SIZE(mt7623_spdif_groups)},
+	{"uart", mt7623_uart_groups, ARRAY_SIZE(mt7623_uart_groups)},
+	{"watchdog", mt7623_wdt_groups, ARRAY_SIZE(mt7623_wdt_groups)},
+};
+
+static struct mtk_pinctrl_soc mt7623_data = {
+	.name = "mt7623_pinctrl",
+	.reg_cal = mt7623_reg_cals,
+	.pins = mt7623_pins,
+	.npins = ARRAY_SIZE(mt7623_pins),
+	.grps = mt7623_groups,
+	.ngrps = ARRAY_SIZE(mt7623_groups),
+	.funcs = mt7623_functions,
+	.nfuncs = ARRAY_SIZE(mt7623_functions),
+};
+
+/*
+ * There are some specific pins have mux functions greater than 8,
+ * and if we want to switch thees high modes we need to disable
+ * bonding constraints firstly.
+ */
+static void mt7623_bonding_disable(struct udevice *dev)
+{
+	mtk_rmw(dev, PIN_BOND_REG0, BOND_PCIE_CLR, BOND_PCIE_CLR);
+	mtk_rmw(dev, PIN_BOND_REG1, BOND_I2S_CLR, BOND_I2S_CLR);
+	mtk_rmw(dev, PIN_BOND_REG2, BOND_MSDC0E_CLR, BOND_MSDC0E_CLR);
+}
+
+static int mtk_pinctrl_mt7623_probe(struct udevice *dev)
+{
+	int err;
+
+	err = mtk_pinctrl_probe(dev, &mt7623_data);
+	if (err)
+		return err;
+
+	mt7623_bonding_disable(dev);
+
+	return 0;
+}
+
+static const struct udevice_id mt7623_pctrl_match[] = {
+	{ .compatible = "mediatek,mt7623-pinctrl", },
+	{ /* sentinel */ }
+};
+
+U_BOOT_DRIVER(mt7623_pinctrl) = {
+	.name = "mt7623_pinctrl",
+	.id = UCLASS_PINCTRL,
+	.of_match = mt7623_pctrl_match,
+	.ops = &mtk_pinctrl_ops,
+	.probe = mtk_pinctrl_mt7623_probe,
+	.priv_auto_alloc_size = sizeof(struct mtk_pinctrl_priv),
+};
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.h b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h
index 2184fdd..40f08e2 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.h
+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h
@@ -176,6 +176,7 @@ struct mtk_pinctrl_priv {
 
 extern const struct pinctrl_ops mtk_pinctrl_ops;
 
+void mtk_rmw(struct udevice *dev, u32 reg, u32 mask, u32 set);
 int mtk_pinctrl_probe(struct udevice *dev,
 		      struct mtk_pinctrl_soc *soc);
 
-- 
1.9.1

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

* [U-Boot] [PATCH v2 12/18] power domain: MediaTek: add power domain driver for MT7629 SoC
  2018-10-12  7:00 [U-Boot] [PATCH v2 00/18] Add U-Boot support for MediaTek SoCs - MT7623n & MT7629 Ryder Lee
                   ` (10 preceding siblings ...)
  2018-10-12  7:01 ` [U-Boot] [PATCH v2 11/18] pinctrl: MediaTek: add pinctrl driver for MT7623 SoC Ryder Lee
@ 2018-10-12  7:01 ` Ryder Lee
  2018-10-25  3:29   ` Simon Glass
  2018-10-12  7:01 ` [U-Boot] [PATCH v2 13/18] power domain: MediaTek: add power domain driver for MT7623 SoC Ryder Lee
                   ` (5 subsequent siblings)
  17 siblings, 1 reply; 57+ messages in thread
From: Ryder Lee @ 2018-10-12  7:01 UTC (permalink / raw)
  To: u-boot

This adds a power domain driver for the Mediatek SCPSYS unit.

The System Control Processor System (SCPSYS) has several power
management related tasks in the system. The tasks include thermal
measurement, dynamic voltage frequency scaling (DVFS), interrupt
filter and lowlevel sleep control. The System Power Manager (SPM)
inside the SCPSYS is for the MTCMOS power domain control.

For now this driver only adds power domain support.

Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
---
 drivers/power/domain/Kconfig            |   7 +
 drivers/power/domain/Makefile           |   1 +
 drivers/power/domain/mtk-power-domain.c | 326 ++++++++++++++++++++++++++++++++
 3 files changed, 334 insertions(+)
 create mode 100644 drivers/power/domain/mtk-power-domain.c

diff --git a/drivers/power/domain/Kconfig b/drivers/power/domain/Kconfig
index 2c34488..e479fed 100644
--- a/drivers/power/domain/Kconfig
+++ b/drivers/power/domain/Kconfig
@@ -16,6 +16,13 @@ config BCM6328_POWER_DOMAIN
 	  Enable support for manipulating BCM6345 power domains via MMIO
 	  mapped registers.
 
+config MTK_POWER_DOMAIN
+	bool "Enable the MediaTek power domain driver"
+	depends on POWER_DOMAIN && ARCH_MEDIATEK
+	help
+	  Enable support for manipulating MediaTek power domains via MMIO
+	  mapped registers.
+
 config MESON_GX_VPU_POWER_DOMAIN
 	bool "Enable Amlogic Meson GX VPU power domain driver"
 	depends on ARCH_MESON
diff --git a/drivers/power/domain/Makefile b/drivers/power/domain/Makefile
index 6bdaa17..d6c7aa7 100644
--- a/drivers/power/domain/Makefile
+++ b/drivers/power/domain/Makefile
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_$(SPL_)POWER_DOMAIN) += power-domain-uclass.o
 obj-$(CONFIG_BCM6328_POWER_DOMAIN) += bcm6328-power-domain.o
+obj-$(CONFIG_MTK_POWER_DOMAIN) += mtk-power-domain.o
 obj-$(CONFIG_MESON_GX_VPU_POWER_DOMAIN) += meson-gx-pwrc-vpu.o
 obj-$(CONFIG_SANDBOX_POWER_DOMAIN) += sandbox-power-domain.o
 obj-$(CONFIG_SANDBOX_POWER_DOMAIN) += sandbox-power-domain-test.o
diff --git a/drivers/power/domain/mtk-power-domain.c b/drivers/power/domain/mtk-power-domain.c
new file mode 100644
index 0000000..5ebeabd
--- /dev/null
+++ b/drivers/power/domain/mtk-power-domain.c
@@ -0,0 +1,326 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ * Author: Ryder Lee <ryder.lee@mediatek.com>
+ */
+
+#include <clk.h>
+#include <common.h>
+#include <dm.h>
+#include <power-domain-uclass.h>
+#include <regmap.h>
+#include <syscon.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <linux/iopoll.h>
+
+#include <dt-bindings/power/mt7629-power.h>
+
+#define SPM_ETHSYS_PWR_CON	0x2e0
+#define SPM_HIF0_PWR_CON	0x2e4
+#define SPM_HIF1_PWR_CON	0x2e8
+#define SPM_PWR_STATUS		0x60c
+#define SPM_PWR_STATUS_2ND	0x610
+
+#define PWR_RST_B_BIT		BIT(0)
+#define PWR_ISO_BIT		BIT(1)
+#define PWR_ON_BIT		BIT(2)
+#define PWR_ON_2ND_BIT		BIT(3)
+#define PWR_CLK_DIS_BIT		BIT(4)
+
+#define PWR_STATUS_ETHSYS	BIT(24)
+#define PWR_STATUS_HIF0		BIT(25)
+#define PWR_STATUS_HIF1		BIT(26)
+
+/* Infrasys configuration */
+#define INFRA_TOPDCM_CTRL	0x10
+#define INFRA_TOPAXI_PROT_EN	0x220
+#define INFRA_TOPAXI_PROT_STA1	0x228
+
+#define DCM_TOP_EN		BIT(0)
+
+enum scp_domain_type {
+	SCPSYS_MT7629,
+};
+
+struct scp_domain;
+
+struct scp_domain_data {
+	struct scp_domain *scpd;
+	u32 sta_mask;
+	int ctl_offs;
+	u32 sram_pdn_bits;
+	u32 sram_pdn_ack_bits;
+	u32 bus_prot_mask;
+};
+
+struct scp_domain {
+	void __iomem *base;
+	void __iomem *infracfg;
+	enum scp_domain_type type;
+	struct scp_domain_data *data;
+};
+
+static struct scp_domain_data scp_domain_mt7629[] = {
+	[MT7629_POWER_DOMAIN_ETHSYS] = {
+		.sta_mask = PWR_STATUS_ETHSYS,
+		.ctl_offs = SPM_ETHSYS_PWR_CON,
+		.sram_pdn_bits = GENMASK(11, 8),
+		.sram_pdn_ack_bits = GENMASK(15, 12),
+		.bus_prot_mask = (BIT(3) | BIT(17)),
+	},
+	[MT7629_POWER_DOMAIN_HIF0] = {
+		.sta_mask = PWR_STATUS_HIF0,
+		.ctl_offs = SPM_HIF0_PWR_CON,
+		.sram_pdn_bits = GENMASK(11, 8),
+		.sram_pdn_ack_bits = GENMASK(15, 12),
+		.bus_prot_mask = GENMASK(25, 24),
+	},
+	[MT7629_POWER_DOMAIN_HIF1] = {
+		.sta_mask = PWR_STATUS_HIF1,
+		.ctl_offs = SPM_HIF1_PWR_CON,
+		.sram_pdn_bits = GENMASK(11, 8),
+		.sram_pdn_ack_bits = GENMASK(15, 12),
+		.bus_prot_mask = GENMASK(28, 26),
+	},
+};
+
+/**
+ * This function enables the bus protection bits for disabled power
+ * domains so that the system does not hang when some unit accesses the
+ * bus while in power down.
+ */
+static int mtk_infracfg_set_bus_protection(void __iomem *infracfg,
+					   u32 mask)
+{
+	u32 val;
+
+	clrsetbits_le32(infracfg + INFRA_TOPAXI_PROT_EN, mask, mask);
+
+	return readl_poll_timeout(infracfg + INFRA_TOPAXI_PROT_STA1, val,
+				  (val & mask) == mask, 100);
+}
+
+static int mtk_infracfg_clear_bus_protection(void __iomem *infracfg,
+					     u32 mask)
+{
+	u32 val;
+
+	clrbits_le32(infracfg + INFRA_TOPAXI_PROT_EN, mask);
+
+	return readl_poll_timeout(infracfg + INFRA_TOPAXI_PROT_STA1, val,
+				  !(val & mask), 100);
+}
+
+static int scpsys_domain_is_on(struct scp_domain_data *data)
+{
+	struct scp_domain *scpd = data->scpd;
+	u32 sta = readl(scpd->base + SPM_PWR_STATUS) &
+			data->sta_mask;
+	u32 sta2 = readl(scpd->base + SPM_PWR_STATUS_2ND) &
+			 data->sta_mask;
+
+	/*
+	 * A domain is on when both status bits are set. If only one is set
+	 * return an error. This happens while powering up a domain
+	 */
+	if (sta && sta2)
+		return true;
+	if (!sta && !sta2)
+		return false;
+
+	return -EINVAL;
+}
+
+static int scpsys_power_on(struct power_domain *power_domain)
+{
+	struct scp_domain *scpd = dev_get_priv(power_domain->dev);
+	struct scp_domain_data *data = &scpd->data[power_domain->id];
+	void __iomem *ctl_addr = scpd->base + data->ctl_offs;
+	u32 pdn_ack = data->sram_pdn_ack_bits;
+	u32 val;
+	int ret, tmp;
+
+	val = readl(ctl_addr);
+	val |= PWR_ON_BIT;
+	writel(val, ctl_addr);
+
+	val |= PWR_ON_2ND_BIT;
+	writel(val, ctl_addr);
+
+	ret = readx_poll_timeout(scpsys_domain_is_on, data, tmp, tmp > 0,
+				 100);
+	if (ret < 0)
+		return ret;
+
+	val &= ~PWR_CLK_DIS_BIT;
+	writel(val, ctl_addr);
+
+	val &= ~PWR_ISO_BIT;
+	writel(val, ctl_addr);
+
+	val |= PWR_RST_B_BIT;
+	writel(val, ctl_addr);
+
+	val &= ~data->sram_pdn_bits;
+	writel(val, ctl_addr);
+
+	ret = readl_poll_timeout(ctl_addr, tmp, !(tmp & pdn_ack), 100);
+	if (ret < 0)
+		return ret;
+
+	if (data->bus_prot_mask) {
+		ret = mtk_infracfg_clear_bus_protection(scpd->infracfg,
+							data->bus_prot_mask);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int scpsys_power_off(struct power_domain *power_domain)
+{
+	struct scp_domain *scpd = dev_get_priv(power_domain->dev);
+	struct scp_domain_data *data = &scpd->data[power_domain->id];
+	void __iomem *ctl_addr = scpd->base + data->ctl_offs;
+	u32 pdn_ack = data->sram_pdn_ack_bits;
+	u32 val;
+	int ret, tmp;
+
+	if (data->bus_prot_mask) {
+		ret = mtk_infracfg_set_bus_protection(scpd->infracfg,
+						      data->bus_prot_mask);
+		if (ret)
+			return ret;
+	}
+
+	val = readl(ctl_addr);
+	val |= data->sram_pdn_bits;
+	writel(val, ctl_addr);
+
+	ret = readl_poll_timeout(ctl_addr, tmp, (tmp & pdn_ack) == pdn_ack,
+				 100);
+	if (ret < 0)
+		return ret;
+
+	val |= PWR_ISO_BIT;
+	writel(val, ctl_addr);
+
+	val &= ~PWR_RST_B_BIT;
+	writel(val, ctl_addr);
+
+	val |= PWR_CLK_DIS_BIT;
+	writel(val, ctl_addr);
+
+	val &= ~PWR_ON_BIT;
+	writel(val, ctl_addr);
+
+	val &= ~PWR_ON_2ND_BIT;
+	writel(val, ctl_addr);
+
+	ret = readx_poll_timeout(scpsys_domain_is_on, data, tmp, !tmp, 100);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int scpsys_power_request(struct power_domain *power_domain)
+{
+	struct scp_domain *scpd = dev_get_priv(power_domain->dev);
+	struct scp_domain_data *data;
+
+	if (power_domain->id >= ARRAY_SIZE(scpd->data))
+		return -EINVAL;
+
+	data = &scpd->data[power_domain->id];
+	data->scpd = scpd;
+
+	return 0;
+}
+
+static int scpsys_power_free(struct power_domain *power_domain)
+{
+	return 0;
+}
+
+static int mtk_power_domain_hook(struct udevice *dev)
+{
+	struct scp_domain *scpd = dev_get_priv(dev);
+
+	scpd->type = (enum scp_domain_type)dev_get_driver_data(dev);
+
+	switch (scpd->type) {
+	case SCPSYS_MT7629:
+		scpd->data = scp_domain_mt7629;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int mtk_power_domain_probe(struct udevice *dev)
+{
+	struct ofnode_phandle_args args;
+	struct scp_domain *scpd = dev_get_priv(dev);
+	struct regmap *regmap;
+	struct clk_bulk bulk;
+	int err;
+
+	scpd->base = dev_read_addr_ptr(dev);
+	if (!scpd->base)
+		return -ENOENT;
+
+	err = mtk_power_domain_hook(dev);
+	if (err)
+		return err;
+
+	/* get corresponding syscon phandle */
+	err = dev_read_phandle_with_args(dev, "infracfg", NULL, 0, 0, &args);
+	if (err)
+		return err;
+
+	regmap = syscon_node_to_regmap(args.node);
+	if (IS_ERR(regmap))
+		return PTR_ERR(regmap);
+
+	scpd->infracfg = regmap_get_range(regmap, 0);
+	if (!scpd->infracfg)
+		return -ENOENT;
+
+	/* enable Infra DCM */
+	setbits_le32(scpd->infracfg + INFRA_TOPDCM_CTRL, DCM_TOP_EN);
+
+	err = clk_get_bulk(dev, &bulk);
+	if (err)
+		return err;
+
+	return clk_enable_bulk(&bulk);
+}
+
+static const struct udevice_id mtk_power_domain_ids[] = {
+	{
+		.compatible = "mediatek,mt7629-scpsys",
+		.data = SCPSYS_MT7629,
+	},
+	{ /* sentinel */ }
+};
+
+struct power_domain_ops mtk_power_domain_ops = {
+	.free = scpsys_power_free,
+	.off = scpsys_power_off,
+	.on = scpsys_power_on,
+	.request = scpsys_power_request,
+};
+
+U_BOOT_DRIVER(mtk_power_domain) = {
+	.name = "mtk_power_domain",
+	.id = UCLASS_POWER_DOMAIN,
+	.ops = &mtk_power_domain_ops,
+	.probe = mtk_power_domain_probe,
+	.of_match = mtk_power_domain_ids,
+	.priv_auto_alloc_size = sizeof(struct scp_domain),
+};
-- 
1.9.1

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

* [U-Boot] [PATCH v2 13/18] power domain: MediaTek: add power domain driver for MT7623 SoC
  2018-10-12  7:00 [U-Boot] [PATCH v2 00/18] Add U-Boot support for MediaTek SoCs - MT7623n & MT7629 Ryder Lee
                   ` (11 preceding siblings ...)
  2018-10-12  7:01 ` [U-Boot] [PATCH v2 12/18] power domain: MediaTek: add power domain driver for MT7629 SoC Ryder Lee
@ 2018-10-12  7:01 ` Ryder Lee
  2018-10-25  3:30   ` Simon Glass
  2018-10-12  7:01 ` [U-Boot] [PATCH v2 14/18] serial: 16550: allow the driver to support MediaTek serial Ryder Lee
                   ` (4 subsequent siblings)
  17 siblings, 1 reply; 57+ messages in thread
From: Ryder Lee @ 2018-10-12  7:01 UTC (permalink / raw)
  To: u-boot

This adds power domain (scpsys) support for MT7623 SoC.

Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
---
 drivers/power/domain/mtk-power-domain.c | 80 +++++++++++++++++++++++++++++++++
 1 file changed, 80 insertions(+)

diff --git a/drivers/power/domain/mtk-power-domain.c b/drivers/power/domain/mtk-power-domain.c
index 5ebeabd..8b97a16 100644
--- a/drivers/power/domain/mtk-power-domain.c
+++ b/drivers/power/domain/mtk-power-domain.c
@@ -14,8 +14,18 @@
 #include <asm/processor.h>
 #include <linux/iopoll.h>
 
+#include <dt-bindings/power/mt7623-power.h>
 #include <dt-bindings/power/mt7629-power.h>
 
+#define SPM_VDE_PWR_CON		0x0210
+#define SPM_MFG_PWR_CON		0x0214
+#define SPM_ISP_PWR_CON		0x0238
+#define SPM_DIS_PWR_CON		0x023c
+#define SPM_CONN_PWR_CON	0x0280
+#define SPM_BDP_PWR_CON		0x029c
+#define SPM_ETH_PWR_CON		0x02a0
+#define SPM_HIF_PWR_CON		0x02a4
+#define SPM_IFR_MSC_PWR_CON	0x02a8
 #define SPM_ETHSYS_PWR_CON	0x2e0
 #define SPM_HIF0_PWR_CON	0x2e4
 #define SPM_HIF1_PWR_CON	0x2e8
@@ -28,6 +38,15 @@
 #define PWR_ON_2ND_BIT		BIT(3)
 #define PWR_CLK_DIS_BIT		BIT(4)
 
+#define PWR_STATUS_CONN		BIT(1)
+#define PWR_STATUS_DISP		BIT(3)
+#define PWR_STATUS_MFG		BIT(4)
+#define PWR_STATUS_ISP		BIT(5)
+#define PWR_STATUS_VDEC		BIT(7)
+#define PWR_STATUS_BDP		BIT(14)
+#define PWR_STATUS_ETH		BIT(15)
+#define PWR_STATUS_HIF		BIT(16)
+#define PWR_STATUS_IFR_MSC	BIT(17)
 #define PWR_STATUS_ETHSYS	BIT(24)
 #define PWR_STATUS_HIF0		BIT(25)
 #define PWR_STATUS_HIF1		BIT(26)
@@ -40,6 +59,7 @@
 #define DCM_TOP_EN		BIT(0)
 
 enum scp_domain_type {
+	SCPSYS_MT7623,
 	SCPSYS_MT7629,
 };
 
@@ -61,6 +81,59 @@ struct scp_domain {
 	struct scp_domain_data *data;
 };
 
+static struct scp_domain_data scp_domain_mt7623[] = {
+	[MT7623_POWER_DOMAIN_CONN] = {
+		.sta_mask = PWR_STATUS_CONN,
+		.ctl_offs = SPM_CONN_PWR_CON,
+		.bus_prot_mask = BIT(8) | BIT(2),
+	},
+	[MT7623_POWER_DOMAIN_DISP] = {
+		.sta_mask = PWR_STATUS_DISP,
+		.ctl_offs = SPM_DIS_PWR_CON,
+		.sram_pdn_bits = GENMASK(11, 8),
+		.bus_prot_mask = BIT(2),
+	},
+	[MT7623_POWER_DOMAIN_MFG] = {
+		.sta_mask = PWR_STATUS_MFG,
+		.ctl_offs = SPM_MFG_PWR_CON,
+		.sram_pdn_bits = GENMASK(11, 8),
+		.sram_pdn_ack_bits = GENMASK(12, 12),
+	},
+	[MT7623_POWER_DOMAIN_VDEC] = {
+		.sta_mask = PWR_STATUS_VDEC,
+		.ctl_offs = SPM_VDE_PWR_CON,
+		.sram_pdn_bits = GENMASK(11, 8),
+		.sram_pdn_ack_bits = GENMASK(12, 12),
+	},
+	[MT7623_POWER_DOMAIN_ISP] = {
+		.sta_mask = PWR_STATUS_ISP,
+		.ctl_offs = SPM_ISP_PWR_CON,
+		.sram_pdn_bits = GENMASK(11, 8),
+		.sram_pdn_ack_bits = GENMASK(13, 12),
+	},
+	[MT7623_POWER_DOMAIN_BDP] = {
+		.sta_mask = PWR_STATUS_BDP,
+		.ctl_offs = SPM_BDP_PWR_CON,
+		.sram_pdn_bits = GENMASK(11, 8),
+	},
+	[MT7623_POWER_DOMAIN_ETH] = {
+		.sta_mask = PWR_STATUS_ETH,
+		.ctl_offs = SPM_ETH_PWR_CON,
+		.sram_pdn_bits = GENMASK(11, 8),
+		.sram_pdn_ack_bits = GENMASK(15, 12),
+	},
+	[MT7623_POWER_DOMAIN_HIF] = {
+		.sta_mask = PWR_STATUS_HIF,
+		.ctl_offs = SPM_HIF_PWR_CON,
+		.sram_pdn_bits = GENMASK(11, 8),
+		.sram_pdn_ack_bits = GENMASK(15, 12),
+	},
+	[MT7623_POWER_DOMAIN_IFR_MSC] = {
+		.sta_mask = PWR_STATUS_IFR_MSC,
+		.ctl_offs = SPM_IFR_MSC_PWR_CON,
+	},
+};
+
 static struct scp_domain_data scp_domain_mt7629[] = {
 	[MT7629_POWER_DOMAIN_ETHSYS] = {
 		.sta_mask = PWR_STATUS_ETHSYS,
@@ -252,6 +325,9 @@ static int mtk_power_domain_hook(struct udevice *dev)
 	scpd->type = (enum scp_domain_type)dev_get_driver_data(dev);
 
 	switch (scpd->type) {
+	case SCPSYS_MT7623:
+		scpd->data = scp_domain_mt7623;
+		break;
 	case SCPSYS_MT7629:
 		scpd->data = scp_domain_mt7629;
 		break;
@@ -303,6 +379,10 @@ static int mtk_power_domain_probe(struct udevice *dev)
 
 static const struct udevice_id mtk_power_domain_ids[] = {
 	{
+		.compatible = "mediatek,mt7623-scpsys",
+		.data = SCPSYS_MT7623,
+	},
+	{
 		.compatible = "mediatek,mt7629-scpsys",
 		.data = SCPSYS_MT7629,
 	},
-- 
1.9.1

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

* [U-Boot] [PATCH v2 14/18] serial: 16550: allow the driver to support MediaTek serial
  2018-10-12  7:00 [U-Boot] [PATCH v2 00/18] Add U-Boot support for MediaTek SoCs - MT7623n & MT7629 Ryder Lee
                   ` (12 preceding siblings ...)
  2018-10-12  7:01 ` [U-Boot] [PATCH v2 13/18] power domain: MediaTek: add power domain driver for MT7623 SoC Ryder Lee
@ 2018-10-12  7:01 ` Ryder Lee
  2018-10-25  3:30   ` Simon Glass
  2018-10-12  7:01 ` [U-Boot] [PATCH v2 15/18] ram: MediaTek: add DDR3 driver for MT7629 SoC Ryder Lee
                   ` (3 subsequent siblings)
  17 siblings, 1 reply; 57+ messages in thread
From: Ryder Lee @ 2018-10-12  7:01 UTC (permalink / raw)
  To: u-boot

This patch adds an extra operation in ns16550.c to suuport MediaTek
SoCs as we have a highspeed register which influences the calcualtion
of the divisor.

Note that we don't support the baudrate greater than 115200 currently.

Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
Tested-by: Matthias Brugger <matthias.bgg@gmail.com>
---
 drivers/serial/ns16550.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c
index f9041aa..f5410af 100644
--- a/drivers/serial/ns16550.c
+++ b/drivers/serial/ns16550.c
@@ -148,6 +148,13 @@ int ns16550_calc_divisor(NS16550_t port, int clock, int baudrate)
 
 static void NS16550_setbrg(NS16550_t com_port, int baud_divisor)
 {
+#ifdef CONFIG_ARCH_MEDIATEK
+	/*
+	 * MediaTek UARTs has an extra highspeed register.
+	 * We need to clear it if baudrate <= 115200.
+	 */
+	serial_out(0, &com_port->reg9);
+#endif
 	serial_out(UART_LCR_BKSE | UART_LCRVAL, &com_port->lcr);
 	serial_out(baud_divisor & 0xff, &com_port->dll);
 	serial_out((baud_divisor >> 8) & 0xff, &com_port->dlm);
@@ -261,6 +268,9 @@ static inline void _debug_uart_init(void)
 	serial_dout(&com_port->mcr, UART_MCRVAL);
 	serial_dout(&com_port->fcr, UART_FCR_DEFVAL);
 
+#ifdef CONFIG_ARCH_MEDIATEK
+	serial_dout(&com_port->reg9, 0);
+#endif
 	serial_dout(&com_port->lcr, UART_LCR_BKSE | UART_LCRVAL);
 	serial_dout(&com_port->dll, baud_divisor & 0xff);
 	serial_dout(&com_port->dlm, (baud_divisor >> 8) & 0xff);
-- 
1.9.1

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

* [U-Boot] [PATCH v2 15/18] ram: MediaTek: add DDR3 driver for MT7629 SoC
  2018-10-12  7:00 [U-Boot] [PATCH v2 00/18] Add U-Boot support for MediaTek SoCs - MT7623n & MT7629 Ryder Lee
                   ` (13 preceding siblings ...)
  2018-10-12  7:01 ` [U-Boot] [PATCH v2 14/18] serial: 16550: allow the driver to support MediaTek serial Ryder Lee
@ 2018-10-12  7:01 ` Ryder Lee
  2018-10-25  3:30   ` Simon Glass
  2018-10-12  7:01 ` [U-Boot] [PATCH v2 16/18] mmc: mtk-sd: add SD/MMC host controller driver for MT7623 SoC Ryder Lee
                   ` (2 subsequent siblings)
  17 siblings, 1 reply; 57+ messages in thread
From: Ryder Lee @ 2018-10-12  7:01 UTC (permalink / raw)
  To: u-boot

This patch adds a DDR3 driver for MT7629 SoC.

Signed-off-by: Wu Zou <wu.zou@mediatek.com>
Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
---
 drivers/ram/Makefile               |   1 +
 drivers/ram/mediatek/Makefile      |   7 +
 drivers/ram/mediatek/ddr3-mt7629.c | 766 +++++++++++++++++++++++++++++++++++++
 3 files changed, 774 insertions(+)
 create mode 100644 drivers/ram/mediatek/Makefile
 create mode 100644 drivers/ram/mediatek/ddr3-mt7629.c

diff --git a/drivers/ram/Makefile b/drivers/ram/Makefile
index 4ad3604..65cba80 100644
--- a/drivers/ram/Makefile
+++ b/drivers/ram/Makefile
@@ -12,3 +12,4 @@ obj-$(CONFIG_STM32_SDRAM) += stm32_sdram.o
 obj-$(CONFIG_ARCH_BMIPS) += bmips_ram.o
 
 obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
+obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/
diff --git a/drivers/ram/mediatek/Makefile b/drivers/ram/mediatek/Makefile
new file mode 100644
index 0000000..95507b5
--- /dev/null
+++ b/drivers/ram/mediatek/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright (c) 2018 MediaTek Inc.
+#
+# SPDX-License-Identifier:      GPL-2.0
+#
+
+obj-$(CONFIG_TARGET_MT7629) = ddr3-mt7629.o
diff --git a/drivers/ram/mediatek/ddr3-mt7629.c b/drivers/ram/mediatek/ddr3-mt7629.c
new file mode 100644
index 0000000..b413f49
--- /dev/null
+++ b/drivers/ram/mediatek/ddr3-mt7629.c
@@ -0,0 +1,766 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MediaTek DDR3 driver for MT7629 SoC
+ *
+ * Copyright (C) 2018 MediaTek Inc.
+ * Author: Wu Zou <wu.zou@mediatek.com>
+ *	   Ryder Lee <ryder.lee@mediatek.com>
+ */
+
+#include <clk.h>
+#include <common.h>
+#include <dm.h>
+#include <ram.h>
+#include <asm/io.h>
+
+/* EMI */
+#define EMI_CONA			0x000
+#define EMI_CONF			0x028
+#define EMI_CONM			0x060
+
+/* DDR PHY */
+#define DDRPHY_PLL1			0x0000
+#define DDRPHY_PLL2			0x0004
+#define DDRPHY_PLL3			0x0008
+#define DDRPHY_PLL4			0x000c
+#define DDRPHY_PLL5			0x0010
+#define DDRPHY_PLL7			0x0018
+#define DDRPHY_B0_DLL_ARPI0		0x0080
+#define DDRPHY_B0_DLL_ARPI1		0x0084
+#define DDRPHY_B0_DLL_ARPI2		0x0088
+#define DDRPHY_B0_DLL_ARPI3		0x008c
+#define DDRPHY_B0_DLL_ARPI4		0x0090
+#define DDRPHY_B0_DLL_ARPI5		0x0094
+#define DDRPHY_B0_DQ2			0x00a0
+#define DDRPHY_B0_DQ3			0x00a4
+#define DDRPHY_B0_DQ4			0x00a8
+#define DDRPHY_B0_DQ5			0x00ac
+#define DDRPHY_B0_DQ6			0x00b0
+#define DDRPHY_B0_DQ7			0x00b4
+#define DDRPHY_B0_DQ8			0x00b8
+#define DDRPHY_B1_DLL_ARPI0		0x0100
+#define DDRPHY_B1_DLL_ARPI1		0x0104
+#define DDRPHY_B1_DLL_ARPI2		0x0108
+#define DDRPHY_B1_DLL_ARPI3		0x010c
+#define DDRPHY_B1_DLL_ARPI4		0x0110
+#define DDRPHY_B1_DLL_ARPI5		0x0114
+#define DDRPHY_B1_DQ2			0x0120
+#define DDRPHY_B1_DQ3			0x0124
+#define DDRPHY_B1_DQ4			0x0128
+#define DDRPHY_B1_DQ5			0x012c
+#define DDRPHY_B1_DQ6			0x0130
+#define DDRPHY_B1_DQ7			0x0134
+#define DDRPHY_B1_DQ8			0x0138
+#define DDRPHY_CA_DLL_ARPI0		0x0180
+#define DDRPHY_CA_DLL_ARPI1		0x0184
+#define DDRPHY_CA_DLL_ARPI2		0x0188
+#define DDRPHY_CA_DLL_ARPI3		0x018c
+#define DDRPHY_CA_DLL_ARPI4		0x0190
+#define DDRPHY_CA_DLL_ARPI5		0x0194
+#define DDRPHY_CA_CMD2			0x01a0
+#define DDRPHY_CA_CMD3			0x01a4
+#define DDRPHY_CA_CMD5			0x01ac
+#define DDRPHY_CA_CMD6			0x01b0
+#define DDRPHY_CA_CMD7			0x01b4
+#define DDRPHY_CA_CMD8			0x01b8
+#define DDRPHY_MISC_VREF_CTRL		0x0264
+#define DDRPHY_MISC_IMP_CTRL0		0x0268
+#define DDRPHY_MISC_IMP_CTRL1		0x026c
+#define DDRPHY_MISC_SHU_OPT		0x0270
+#define DDRPHY_MISC_SPM_CTRL0		0x0274
+#define DDRPHY_MISC_SPM_CTRL1		0x0278
+#define DDRPHY_MISC_SPM_CTRL2		0x027c
+#define DDRPHY_MISC_CG_CTRL0		0x0284
+#define DDRPHY_MISC_CG_CTRL1		0x0288
+#define DDRPHY_MISC_CG_CTRL2		0x028c
+#define DDRPHY_MISC_CG_CTRL4		0x0294
+#define DDRPHY_MISC_CTRL0		0x029c
+#define DDRPHY_MISC_CTRL1		0x02a0
+#define DDRPHY_MISC_CTRL3		0x02a8
+#define DDRPHY_MISC_RXDVS1		0x05e4
+#define DDRPHY_SHU1_B0_DQ4		0x0c10
+#define DDRPHY_SHU1_B0_DQ5		0x0c14
+#define DDRPHY_SHU1_B0_DQ6		0x0c18
+#define DDRPHY_SHU1_B0_DQ7		0x0c1c
+#define DDRPHY_SHU1_B1_DQ4		0x0c90
+#define DDRPHY_SHU1_B1_DQ5		0x0c94
+#define DDRPHY_SHU1_B1_DQ6		0x0c98
+#define DDRPHY_SHU1_B1_DQ7		0x0c9c
+#define DDRPHY_SHU1_CA_CMD2		0x0d08
+#define DDRPHY_SHU1_CA_CMD4		0x0d10
+#define DDRPHY_SHU1_CA_CMD5		0x0d14
+#define DDRPHY_SHU1_CA_CMD6		0x0d18
+#define DDRPHY_SHU1_CA_CMD7		0x0d1c
+#define DDRPHY_SHU1_PLL0		0x0d80
+#define DDRPHY_SHU1_PLL1		0x0d84
+#define DDRPHY_SHU1_PLL4		0x0d90
+#define DDRPHY_SHU1_PLL5		0x0d94
+#define DDRPHY_SHU1_PLL6		0x0d98
+#define DDRPHY_SHU1_PLL7		0x0d9C
+#define DDRPHY_SHU1_PLL8		0x0da0
+#define DDRPHY_SHU1_PLL9		0x0da4
+#define DDRPHY_SHU1_PLL10		0x0da8
+#define DDRPHY_SHU1_PLL11		0x0dac
+#define DDRPHY_SHU1_R0_B0_DQ2		0x0e08
+#define DDRPHY_SHU1_R0_B0_DQ3		0x0e0c
+#define DDRPHY_SHU1_R0_B0_DQ4		0x0e10
+#define DDRPHY_SHU1_R0_B0_DQ5		0x0e14
+#define DDRPHY_SHU1_R0_B0_DQ6		0x0e18
+#define DDRPHY_SHU1_R0_B0_DQ7		0x0e1c
+#define DDRPHY_SHU1_R0_B1_DQ2		0x0e58
+#define DDRPHY_SHU1_R0_B1_DQ3		0x0e5c
+#define DDRPHY_SHU1_R0_B1_DQ4		0x0e60
+#define DDRPHY_SHU1_R0_B1_DQ5		0x0e64
+#define DDRPHY_SHU1_R0_B1_DQ6		0x0e68
+#define DDRPHY_SHU1_R0_B1_DQ7		0x0e6c
+#define DDRPHY_SHU1_R0_CA_CMD9		0x0ec4
+#define DDRPHY_SHU1_R1_B0_DQ2		0x0f08
+#define DDRPHY_SHU1_R1_B0_DQ3		0x0f0c
+#define DDRPHY_SHU1_R1_B0_DQ4		0x0f10
+#define DDRPHY_SHU1_R1_B0_DQ5		0x0f14
+#define DDRPHY_SHU1_R1_B0_DQ6		0x0f18
+#define DDRPHY_SHU1_R1_B0_DQ7		0x0f1c
+#define DDRPHY_SHU1_R1_B1_DQ2		0x0f58
+#define DDRPHY_SHU1_R1_B1_DQ3		0x0f5c
+#define DDRPHY_SHU1_R1_B1_DQ4		0x0f60
+#define DDRPHY_SHU1_R1_B1_DQ5		0x0f64
+#define DDRPHY_SHU1_R1_B1_DQ6		0x0f68
+#define DDRPHY_SHU1_R1_B1_DQ7		0x0f6c
+#define DDRPHY_SHU1_R1_CA_CMD9		0x0fc4
+
+/* DRAMC */
+#define DRAMC_DDRCONF0			0x0000
+#define DRAMC_DRAMCTRL			0x0004
+#define DRAMC_MISCTL0			0x0008
+#define DRAMC_PERFCTL0			0x000c
+#define DRAMC_ARBCTL			0x0010
+#define DRAMC_RSTMASK			0x001c
+#define DRAMC_PADCTRL			0x0020
+#define DRAMC_CKECTRL			0x0024
+#define DRAMC_RKCFG			0x0034
+#define DRAMC_DRAMC_PD_CTRL		0x0038
+#define DRAMC_CLKAR			0x003c
+#define DRAMC_CLKCTRL			0x0040
+#define DRAMC_SREFCTRL			0x0048
+#define DRAMC_REFCTRL0			0x004c
+#define DRAMC_REFCTRL1			0x0050
+#define DRAMC_REFRATRE_FILTER		0x0054
+#define DRAMC_ZQCS			0x0058
+#define DRAMC_MRS			0x005c
+#define DRAMC_SPCMD			0x0060
+#define DRAMC_SPCMDCTRL			0x0064
+#define DRAMC_HW_MRR_FUN		0x0074
+#define DRAMC_TEST2_1			0x0094
+#define DRAMC_TEST2_2			0x0098
+#define DRAMC_TEST2_3			0x009c
+#define DRAMC_TEST2_4			0x00a0
+#define DRAMC_CATRAINING1		0x00b0
+#define DRAMC_DUMMY_RD			0x00d0
+#define DRAMC_SHUCTRL			0x00d4
+#define DRAMC_SHUCTRL2			0x00dc
+#define DRAMC_STBCAL			0x0200
+#define DRAMC_STBCAL1			0x0204
+#define DRAMC_EYESCAN			0x020c
+#define DRAMC_DVFSDLL			0x0210
+#define DRAMC_SHU_ACTIM0		0x0800
+#define DRAMC_SHU_ACTIM1		0x0804
+#define DRAMC_SHU_ACTIM2		0x0808
+#define DRAMC_SHU_ACTIM3		0x080c
+#define DRAMC_SHU_ACTIM4		0x0810
+#define DRAMC_SHU_ACTIM5		0x0814
+#define DRAMC_SHU_ACTIM_XRT		0x081c
+#define DRAMC_SHU_AC_TIME_05T		0x0820
+#define DRAMC_SHU_CONF0			0x0840
+#define DRAMC_SHU_CONF1			0x0844
+#define DRAMC_SHU_CONF2			0x0848
+#define DRAMC_SHU_CONF3			0x084c
+#define DRAMC_SHU_RANKCTL		0x0858
+#define DRAMC_SHU_CKECTRL		0x085c
+#define DRAMC_SHU_ODTCTRL		0x0860
+#define DRAMC_SHU_PIPE			0x0878
+#define DRAMC_SHU_SELPH_CA1		0x0880
+#define DRAMC_SHU_SELPH_CA2		0x0884
+#define DRAMC_SHU_SELPH_CA3		0x0888
+#define DRAMC_SHU_SELPH_CA4		0x088c
+#define DRAMC_SHU_SELPH_CA5		0x0890
+#define DRAMC_SHU_SELPH_CA6		0x0894
+#define DRAMC_SHU_SELPH_CA7		0x0898
+#define DRAMC_SHU_SELPH_CA8		0x089c
+#define DRAMC_SHU_SELPH_DQS0		0x08a0
+#define DRAMC_SHU_SELPH_DQS1		0x08a4
+#define DRAMC_SHU1_DRVING1		0x08a8
+#define DRAMC_SHU1_DRVING2		0x08ac
+#define DRAMC_SHU1_WODT			0x08c0
+#define DRAMC_SHU_SCINTV		0x08c8
+#define DRAMC_SHURK0_DQSCTL		0x0a00
+#define DRAMC_SHURK0_DQSIEN		0x0a04
+#define DRAMC_SHURK0_SELPH_ODTEN0	0x0a1c
+#define DRAMC_SHURK0_SELPH_ODTEN1	0x0a20
+#define DRAMC_SHURK0_SELPH_DQSG0	0x0a24
+#define DRAMC_SHURK0_SELPH_DQSG1	0x0a28
+#define DRAMC_SHURK0_SELPH_DQ0		0x0a2c
+#define DRAMC_SHURK0_SELPH_DQ1		0x0a30
+#define DRAMC_SHURK0_SELPH_DQ2		0x0a34
+#define DRAMC_SHURK0_SELPH_DQ3		0x0a38
+#define DRAMC_SHURK1_DQSCTL		0x0b00
+#define DRAMC_SHURK1_SELPH_ODTEN0	0x0b1c
+#define DRAMC_SHURK1_SELPH_ODTEN1	0x0b20
+#define DRAMC_SHURK1_SELPH_DQSG0	0x0b24
+#define DRAMC_SHURK1_SELPH_DQSG1	0x0b28
+#define DRAMC_SHURK1_SELPH_DQ0		0x0b2c
+#define DRAMC_SHURK1_SELPH_DQ1		0x0b30
+#define DRAMC_SHURK1_SELPH_DQ2		0x0b34
+#define DRAMC_SHURK1_SELPH_DQ3		0x0b38
+#define DRAMC_SHURK2_SELPH_ODTEN0	0x0c1c
+#define DRAMC_SHURK2_SELPH_ODTEN1	0x0c20
+#define DRAMC_SHU_DQSG_RETRY		0x0c54
+
+#define EMI_COL_ADDR_MASK		GENMASK(13, 12)
+#define EMI_COL_ADDR_SHIFT		12
+#define WALKING_PATTERN			0x12345678
+#define WALKING_STEP			0x4000000
+
+struct mtk_ddr3_priv {
+	fdt_addr_t emi;
+	fdt_addr_t ddrphy;
+	fdt_addr_t dramc_ao;
+	struct clk phy;
+	struct clk phy_mux;
+	struct clk mem;
+	struct clk mem_mux;
+};
+
+#ifdef CONFIG_SPL_BUILD
+static int mtk_ddr3_rank_size_detect(struct udevice *dev)
+{
+	struct mtk_ddr3_priv *priv = dev_get_priv(dev);
+	int step;
+	u32 start, test;
+
+	/* To detect size, we have to make sure it's single rank
+	 * and it has maximum addressing region
+	 */
+
+	writel(WALKING_PATTERN, CONFIG_SYS_SDRAM_BASE);
+
+	if (readl(CONFIG_SYS_SDRAM_BASE) != WALKING_PATTERN)
+		return -EINVAL;
+
+	for (step = 0; step < 5; step++) {
+		writel(~WALKING_PATTERN, CONFIG_SYS_SDRAM_BASE +
+		       (WALKING_STEP << step));
+
+		start = readl(CONFIG_SYS_SDRAM_BASE);
+		test = readl(CONFIG_SYS_SDRAM_BASE + (WALKING_STEP << step));
+		if ((test != ~WALKING_PATTERN) || test == start)
+			break;
+	}
+
+	step = step ? step - 1 : 3;
+	clrsetbits_le32(priv->emi + EMI_CONA, EMI_COL_ADDR_MASK,
+			step << EMI_COL_ADDR_SHIFT);
+
+	return 0;
+}
+
+static int mtk_ddr3_init(struct udevice *dev)
+{
+	struct mtk_ddr3_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	ret = clk_set_parent(&priv->phy, &priv->phy_mux);
+	if (ret)
+		return ret;
+
+	/* EMI Setting */
+	writel(0x00003010, priv->emi + EMI_CONA);
+	writel(0x00000000, priv->emi + EMI_CONF);
+	writel(0x000006b8, priv->emi + EMI_CONM);
+	/* DQS */
+	writel(0x20c00, priv->dramc_ao + DRAMC_SHU1_DRVING1);
+	/* Clock */
+	writel(0x8320c83, priv->dramc_ao + DRAMC_SHU1_DRVING2);
+
+	/* DDRPHY setting */
+	writel(0x2201, priv->dramc_ao + DRAMC_DRAMCTRL);
+	writel(0x3000000c, priv->dramc_ao + DRAMC_CLKCTRL);
+	writel(0xe08, priv->ddrphy + DDRPHY_CA_CMD5);
+	writel(0x60e, priv->ddrphy + DDRPHY_SHU1_CA_CMD5);
+	writel(0x0, priv->ddrphy + DDRPHY_MISC_SPM_CTRL1);
+	writel(0xffffffff, priv->ddrphy + DDRPHY_MISC_SPM_CTRL0);
+	writel(0xffffffff, priv->ddrphy + DDRPHY_MISC_SPM_CTRL2);
+	writel(0x6003bf, priv->ddrphy + DDRPHY_MISC_CG_CTRL2);
+	writel(0x13300000, priv->ddrphy + DDRPHY_MISC_CG_CTRL4);
+
+	writel(0x1, priv->ddrphy + DDRPHY_SHU1_CA_CMD7);
+	writel(0x21, priv->ddrphy + DDRPHY_SHU1_B0_DQ7);
+	writel(0x1, priv->ddrphy + DDRPHY_SHU1_B1_DQ7);
+	writel(0xfff0, priv->ddrphy + DDRPHY_CA_CMD2);
+	writel(0x0, priv->ddrphy + DDRPHY_B0_DQ2);
+	writel(0x0, priv->ddrphy + DDRPHY_B1_DQ2);
+	writel(0x7, priv->ddrphy + DDRPHY_MISC_RXDVS1);
+	writel(0x10, priv->ddrphy + DDRPHY_PLL3);
+	writel(0x8e8e0000, priv->ddrphy + DDRPHY_MISC_VREF_CTRL);
+	writel(0x2e0040, priv->ddrphy + DDRPHY_MISC_IMP_CTRL0);
+	writel(0x50060e, priv->ddrphy + DDRPHY_SHU1_B0_DQ5);
+	writel(0x50060e, priv->ddrphy + DDRPHY_SHU1_B1_DQ5);
+	udelay(1);
+
+	writel(0x10, priv->ddrphy + DDRPHY_B0_DQ3);
+	writel(0x10, priv->ddrphy + DDRPHY_B1_DQ3);
+	writel(0x3f600, priv->ddrphy + DDRPHY_MISC_CG_CTRL1);
+	writel(0x1010, priv->ddrphy + DDRPHY_B0_DQ4);
+	writel(0x1110e0e, priv->ddrphy + DDRPHY_B0_DQ5);
+	writel(0x10c10d0, priv->ddrphy + DDRPHY_B0_DQ6);
+	writel(0x3110e0e, priv->ddrphy + DDRPHY_B0_DQ5);
+	writel(0x1010, priv->ddrphy + DDRPHY_B1_DQ4);
+	writel(0x1110e0e, priv->ddrphy + DDRPHY_B1_DQ5);
+	writel(0x10c10d0, priv->ddrphy + DDRPHY_B1_DQ6);
+	writel(0x3110e0e, priv->ddrphy + DDRPHY_B1_DQ5);
+	writel(0x7fffffc, priv->ddrphy + DDRPHY_CA_CMD3);
+	writel(0xc0010, priv->ddrphy + DDRPHY_CA_CMD6);
+	writel(0x101, priv->ddrphy + DDRPHY_SHU1_CA_CMD2);
+	writel(0x41e, priv->ddrphy + DDRPHY_B0_DQ3);
+	writel(0x41e, priv->ddrphy + DDRPHY_B1_DQ3);
+	writel(0x180101, priv->ddrphy + DDRPHY_CA_CMD8);
+	writel(0x0, priv->ddrphy + DDRPHY_MISC_IMP_CTRL1);
+	writel(0x11400000, priv->ddrphy + DDRPHY_MISC_CG_CTRL4);
+	writel(0xfff0f0f0, priv->ddrphy + DDRPHY_MISC_SHU_OPT);
+	writel(0x1f, priv->ddrphy + DDRPHY_MISC_CG_CTRL0);
+
+	writel(0x0, priv->ddrphy + DDRPHY_SHU1_CA_CMD6);
+	writel(0x0, priv->ddrphy + DDRPHY_SHU1_B0_DQ6);
+	writel(0x0, priv->ddrphy + DDRPHY_SHU1_B1_DQ6);
+	writel(0x40000, priv->ddrphy + DDRPHY_PLL4);
+	writel(0x0, priv->ddrphy + DDRPHY_PLL1);
+	writel(0x0, priv->ddrphy + DDRPHY_PLL2);
+	writel(0x666008, priv->ddrphy + DDRPHY_CA_DLL_ARPI5);
+	writel(0x80666008, priv->ddrphy + DDRPHY_B0_DLL_ARPI5);
+	writel(0x80666008, priv->ddrphy + DDRPHY_B1_DLL_ARPI5);
+	writel(0x0, priv->ddrphy + DDRPHY_CA_DLL_ARPI0);
+	writel(0x0, priv->ddrphy + DDRPHY_B0_DLL_ARPI0);
+	writel(0x0, priv->ddrphy + DDRPHY_B1_DLL_ARPI0);
+	writel(0x400, priv->ddrphy + DDRPHY_CA_DLL_ARPI2);
+	writel(0x20400, priv->ddrphy + DDRPHY_B0_DLL_ARPI2);
+	writel(0x20400, priv->ddrphy + DDRPHY_B1_DLL_ARPI2);
+	writel(0x0, priv->ddrphy + DDRPHY_SHU1_PLL9);
+	writel(0x0, priv->ddrphy + DDRPHY_SHU1_PLL11);
+	writel(0xf7f, priv->ddrphy + DDRPHY_SHU1_PLL0);
+	writel(0x40000, priv->ddrphy + DDRPHY_SHU1_PLL8);
+	writel(0x40000, priv->ddrphy + DDRPHY_SHU1_PLL10);
+	writel(0xe57800fe, priv->ddrphy + DDRPHY_SHU1_PLL4);
+	writel(0xe57800fe, priv->ddrphy + DDRPHY_SHU1_PLL6);
+
+	writel(0xB5000000, priv->ddrphy + DDRPHY_SHU1_PLL5);
+	writel(0xB5000000, priv->ddrphy + DDRPHY_SHU1_PLL7);
+
+	writel(0x14d0002, priv->ddrphy + DDRPHY_PLL5);
+	writel(0x14d0002, priv->ddrphy + DDRPHY_PLL7);
+	writel(0x80040000, priv->ddrphy + DDRPHY_SHU1_PLL8);
+	writel(0x80040000, priv->ddrphy + DDRPHY_SHU1_PLL10);
+	writel(0xf, priv->ddrphy + DDRPHY_SHU1_PLL1);
+	writel(0x4, priv->ddrphy + DDRPHY_CA_DLL_ARPI0);
+	writel(0x1, priv->ddrphy + DDRPHY_B0_DLL_ARPI0);
+	writel(0x1, priv->ddrphy + DDRPHY_B1_DLL_ARPI0);
+	writel(0x698600, priv->ddrphy + DDRPHY_CA_DLL_ARPI5);
+	writel(0xc0778600, priv->ddrphy + DDRPHY_B0_DLL_ARPI5);
+	writel(0xc0778600, priv->ddrphy + DDRPHY_B1_DLL_ARPI5);
+	writel(0x0, priv->ddrphy + DDRPHY_CA_DLL_ARPI4);
+	writel(0x0, priv->ddrphy + DDRPHY_B0_DLL_ARPI4);
+	writel(0x0, priv->ddrphy + DDRPHY_B1_DLL_ARPI4);
+	writel(0x2ba800, priv->ddrphy + DDRPHY_CA_DLL_ARPI1);
+	writel(0x2ae806, priv->ddrphy + DDRPHY_B0_DLL_ARPI1);
+	writel(0xae806, priv->ddrphy + DDRPHY_B1_DLL_ARPI1);
+	writel(0xba000, priv->ddrphy + DDRPHY_CA_DLL_ARPI3);
+	writel(0x2e800, priv->ddrphy + DDRPHY_B0_DLL_ARPI3);
+	writel(0x2e800, priv->ddrphy + DDRPHY_B1_DLL_ARPI3);
+	writel(0x0, priv->ddrphy + DDRPHY_SHU1_CA_CMD4);
+	writel(0x0, priv->ddrphy + DDRPHY_SHU1_B0_DQ4);
+	writel(0x0, priv->ddrphy + DDRPHY_SHU1_B1_DQ4);
+	writel(0x4, priv->ddrphy + DDRPHY_CA_DLL_ARPI0);
+	writel(0x1, priv->ddrphy + DDRPHY_B0_DLL_ARPI0);
+	writel(0x1, priv->ddrphy + DDRPHY_B1_DLL_ARPI0);
+	writel(0x32cf0000, priv->ddrphy + DDRPHY_SHU1_CA_CMD6);
+	writel(0x32cd0000, priv->ddrphy + DDRPHY_SHU1_B0_DQ6);
+	writel(0x32cd0000, priv->ddrphy + DDRPHY_SHU1_B1_DQ6);
+	writel(0x80010000, priv->ddrphy + DDRPHY_PLL1);
+	writel(0x80000000, priv->ddrphy + DDRPHY_PLL2);
+	udelay(100);
+
+	writel(0xc, priv->ddrphy + DDRPHY_CA_DLL_ARPI0);
+	writel(0x9, priv->ddrphy + DDRPHY_B0_DLL_ARPI0);
+	writel(0x9, priv->ddrphy + DDRPHY_B1_DLL_ARPI0);
+	writel(0xd0000, priv->ddrphy + DDRPHY_PLL4);
+	udelay(1);
+
+	writel(0x82, priv->ddrphy + DDRPHY_MISC_CTRL1);
+	writel(0x2, priv->dramc_ao + DRAMC_DDRCONF0);
+	writel(0x3acf0000, priv->ddrphy + DDRPHY_SHU1_CA_CMD6);
+	writel(0x3acd0000, priv->ddrphy + DDRPHY_SHU1_B0_DQ6);
+	writel(0x3acd0000, priv->ddrphy + DDRPHY_SHU1_B1_DQ6);
+	udelay(1);
+
+	writel(0x0, priv->ddrphy + DDRPHY_CA_DLL_ARPI2);
+	writel(0x0, priv->ddrphy + DDRPHY_B0_DLL_ARPI2);
+	writel(0x0, priv->ddrphy + DDRPHY_B1_DLL_ARPI2);
+	writel(0x80, priv->ddrphy + DDRPHY_MISC_CTRL1);
+	writel(0x0, priv->dramc_ao + DRAMC_DDRCONF0);
+	writel(0x80000000, priv->ddrphy + DDRPHY_PLL1);
+	udelay(1);
+
+	writel(0x698e00, priv->ddrphy + DDRPHY_CA_DLL_ARPI5);
+	udelay(1);
+
+	writel(0xc0778e00, priv->ddrphy + DDRPHY_B0_DLL_ARPI5);
+	udelay(1);
+
+	writel(0xc0778e00, priv->ddrphy + DDRPHY_B1_DLL_ARPI5);
+	udelay(1);
+
+	ret = clk_set_parent(&priv->mem, &priv->mem_mux);
+	if (ret)
+		return ret;
+
+	/* DDR PHY PLL setting */
+	writel(0x51e, priv->ddrphy + DDRPHY_B0_DQ3);
+	writel(0x51e, priv->ddrphy + DDRPHY_B1_DQ3);
+	writel(0x8100008c, priv->ddrphy + DDRPHY_MISC_CTRL1);
+	writel(0x80101, priv->ddrphy + DDRPHY_CA_CMD8);
+	writel(0x100, priv->ddrphy + DDRPHY_CA_CMD7);
+	writel(0x0, priv->ddrphy + DDRPHY_CA_CMD7);
+	writel(0x0, priv->ddrphy + DDRPHY_B0_DQ7);
+	writel(0x0, priv->ddrphy + DDRPHY_B1_DQ7);
+	writel(0x51e, priv->ddrphy + DDRPHY_B0_DQ3);
+	writel(0xff051e, priv->ddrphy + DDRPHY_B1_DQ3);
+	writel(0x0, priv->ddrphy + DDRPHY_B0_DQ2);
+	writel(0x1ff, priv->ddrphy + DDRPHY_B1_DQ2);
+
+	/* Update initial setting */
+	writel(0x5fc, priv->ddrphy + DDRPHY_B0_DQ3);
+	writel(0xff05fc, priv->ddrphy + DDRPHY_B1_DQ3);
+	writel(0x10c12d9, priv->ddrphy + DDRPHY_B0_DQ6);
+	writel(0x10c12d9, priv->ddrphy + DDRPHY_B1_DQ6);
+	writel(0xc0259, priv->ddrphy + DDRPHY_CA_CMD6);
+	writel(0x4000, priv->ddrphy + DDRPHY_B0_DQ2);
+	writel(0x41ff, priv->ddrphy + DDRPHY_B1_DQ2);
+	writel(0x0, priv->ddrphy + DDRPHY_B0_DQ8);
+	writel(0x100, priv->ddrphy + DDRPHY_B1_DQ8);
+	writel(0x3110e0e, priv->ddrphy + DDRPHY_B0_DQ5);
+	writel(0x3110e0e, priv->ddrphy + DDRPHY_B1_DQ5);
+	writel(0x51060e, priv->ddrphy + DDRPHY_SHU1_B0_DQ5);
+	writel(0x51060e, priv->ddrphy + DDRPHY_SHU1_B1_DQ5);
+	writel(0x39eff6, priv->dramc_ao + DRAMC_SHU_SCINTV);
+	writel(0x204ffff, priv->dramc_ao + DRAMC_CLKAR);
+	writel(0x31b1f1cf, priv->dramc_ao + DRAMC_SPCMDCTRL);
+	writel(0x0, priv->dramc_ao + DRAMC_PERFCTL0);
+	writel(0x80000, priv->dramc_ao + DRAMC_PERFCTL0);
+
+	/* Dramc setting PC3 */
+	writel(0x65714001, priv->dramc_ao + DRAMC_REFCTRL0);
+
+	writel(0x11351131, priv->ddrphy + DDRPHY_MISC_CTRL3);
+	writel(0x200600, priv->dramc_ao + DRAMC_SHU_DQSG_RETRY);
+	writel(0x101d007, priv->dramc_ao + DRAMC_SHUCTRL2);
+	writel(0xe090601, priv->dramc_ao + DRAMC_DVFSDLL);
+	writel(0x20003000, priv->dramc_ao + DRAMC_DDRCONF0);
+	writel(0x3900020f, priv->ddrphy + DDRPHY_MISC_CTRL0);
+	writel(0xa20810bf, priv->dramc_ao + DRAMC_SHU_CONF0);
+	writel(0x30050, priv->dramc_ao + DRAMC_SHU_ODTCTRL);
+	writel(0x25712000, priv->dramc_ao + DRAMC_REFCTRL0);
+	writel(0xb0100000, priv->dramc_ao + DRAMC_STBCAL);
+	writel(0x8000000, priv->dramc_ao + DRAMC_SREFCTRL);
+	writel(0xc0000000, priv->dramc_ao + DRAMC_SHU_PIPE);
+	writel(0x731004, priv->dramc_ao + DRAMC_RKCFG);
+	writel(0x8007320f, priv->dramc_ao + DRAMC_SHU_CONF2);
+	writel(0x2a7c0, priv->dramc_ao + DRAMC_SHU_SCINTV);
+	writel(0xc110, priv->dramc_ao + DRAMC_SHUCTRL);
+	writel(0x30000700, priv->dramc_ao + DRAMC_REFCTRL1);
+	writel(0x6543b321, priv->dramc_ao + DRAMC_REFRATRE_FILTER);
+
+	/* Update PCDDR3 default setting */
+	writel(0x0, priv->dramc_ao + DRAMC_SHU_SELPH_CA1);
+	writel(0x0, priv->dramc_ao + DRAMC_SHU_SELPH_CA2);
+	writel(0x0, priv->dramc_ao + DRAMC_SHU_SELPH_CA3);
+	writel(0x0, priv->dramc_ao + DRAMC_SHU_SELPH_CA4);
+	writel(0x10000111, priv->dramc_ao + DRAMC_SHU_SELPH_CA5);
+	writel(0x1000000, priv->dramc_ao + DRAMC_SHU_SELPH_CA6);
+	writel(0x0, priv->dramc_ao + DRAMC_SHU_SELPH_CA7);
+	writel(0x0, priv->dramc_ao + DRAMC_SHU_SELPH_CA8);
+	writel(0x0, priv->ddrphy + DDRPHY_SHU1_R0_CA_CMD9);
+	writel(0x0, priv->ddrphy + DDRPHY_SHU1_R1_CA_CMD9);
+	writel(0x11112222, priv->dramc_ao + DRAMC_SHU_SELPH_DQS0);
+	writel(0x33331111, priv->dramc_ao + DRAMC_SHU_SELPH_DQS1);
+	writel(0x11112222, priv->dramc_ao + DRAMC_SHURK0_SELPH_DQ0);
+	writel(0x11112222, priv->dramc_ao + DRAMC_SHURK0_SELPH_DQ1);
+	writel(0x33331111, priv->dramc_ao + DRAMC_SHURK0_SELPH_DQ2);
+	writel(0x33331111, priv->dramc_ao + DRAMC_SHURK0_SELPH_DQ3);
+	writel(0x11112222, priv->dramc_ao + DRAMC_SHURK1_SELPH_DQ0);
+	writel(0x11112222, priv->dramc_ao + DRAMC_SHURK1_SELPH_DQ1);
+	writel(0x33331111, priv->dramc_ao + DRAMC_SHURK1_SELPH_DQ2);
+	writel(0x33331111, priv->dramc_ao + DRAMC_SHURK1_SELPH_DQ3);
+	writel(0xf0f00, priv->ddrphy + DDRPHY_SHU1_R0_B0_DQ7);
+	writel(0xf0f00, priv->ddrphy + DDRPHY_SHU1_R1_B0_DQ7);
+	writel(0xf0f00, priv->ddrphy + DDRPHY_SHU1_R0_B1_DQ7);
+	writel(0xf0f00, priv->ddrphy + DDRPHY_SHU1_R1_B1_DQ7);
+	writel(0x0, priv->dramc_ao + DRAMC_SHURK0_SELPH_ODTEN0);
+	writel(0x0, priv->dramc_ao + DRAMC_SHURK0_SELPH_ODTEN1);
+	writel(0x0, priv->dramc_ao + DRAMC_SHURK1_SELPH_ODTEN0);
+	writel(0x0, priv->dramc_ao + DRAMC_SHURK1_SELPH_ODTEN1);
+	writel(0x0, priv->dramc_ao + DRAMC_SHURK2_SELPH_ODTEN0);
+	writel(0x66666666, priv->dramc_ao + DRAMC_SHURK2_SELPH_ODTEN1);
+	writel(0x2c000b0f, priv->dramc_ao + DRAMC_SHU_CONF1);
+	writel(0x11111111, priv->dramc_ao + DRAMC_SHURK0_SELPH_DQSG0);
+	writel(0x64646464, priv->dramc_ao + DRAMC_SHURK0_SELPH_DQSG1);
+	writel(0x11111111, priv->dramc_ao + DRAMC_SHURK1_SELPH_DQSG0);
+	writel(0x64646464, priv->dramc_ao + DRAMC_SHURK1_SELPH_DQSG1);
+	writel(0xc0c0c0c, priv->ddrphy + DDRPHY_SHU1_R0_B0_DQ2);
+	writel(0xc0c0c0c, priv->ddrphy + DDRPHY_SHU1_R0_B0_DQ3);
+	writel(0xc0c0c0c, priv->ddrphy + DDRPHY_SHU1_R0_B0_DQ4);
+	writel(0xc0c0c0c, priv->ddrphy + DDRPHY_SHU1_R0_B0_DQ5);
+	writel(0x0, priv->ddrphy + DDRPHY_SHU1_R0_B0_DQ6);
+	writel(0xc0c0c0c, priv->ddrphy + DDRPHY_SHU1_R1_B0_DQ2);
+	writel(0xc0c0c0c, priv->ddrphy + DDRPHY_SHU1_R1_B0_DQ3);
+	writel(0xc0c0c0c, priv->ddrphy + DDRPHY_SHU1_R1_B0_DQ4);
+	writel(0xc0c0c0c, priv->ddrphy + DDRPHY_SHU1_R1_B0_DQ5);
+	writel(0x0, priv->ddrphy + DDRPHY_SHU1_R1_B0_DQ6);
+	writel(0xc0c0c0c, priv->ddrphy + DDRPHY_SHU1_R0_B1_DQ2);
+	writel(0xc0c0c0c, priv->ddrphy + DDRPHY_SHU1_R0_B1_DQ3);
+	writel(0xc0c0c0c, priv->ddrphy + DDRPHY_SHU1_R0_B1_DQ4);
+	writel(0xc0c0c0c, priv->ddrphy + DDRPHY_SHU1_R0_B1_DQ5);
+	writel(0x0, priv->ddrphy + DDRPHY_SHU1_R0_B1_DQ6);
+	writel(0xc0c0c0c, priv->ddrphy + DDRPHY_SHU1_R1_B1_DQ2);
+	writel(0xc0c0c0c, priv->ddrphy + DDRPHY_SHU1_R1_B1_DQ3);
+	writel(0xc0c0c0c, priv->ddrphy + DDRPHY_SHU1_R1_B1_DQ4);
+	writel(0xc0c0c0c, priv->ddrphy + DDRPHY_SHU1_R1_B1_DQ5);
+	writel(0x0, priv->ddrphy + DDRPHY_SHU1_R1_B1_DQ6);
+	writel(0x20000001, priv->dramc_ao + DRAMC_SHU_RANKCTL);
+	writel(0x2, priv->dramc_ao + DRAMC_SHURK0_DQSCTL);
+	writel(0x2, priv->dramc_ao + DRAMC_SHURK1_DQSCTL);
+	writel(0x4020b07, priv->dramc_ao + DRAMC_SHU_ACTIM0);
+	writel(0xb060400, priv->dramc_ao + DRAMC_SHU_ACTIM1);
+	writel(0x8090200, priv->dramc_ao + DRAMC_SHU_ACTIM2);
+	writel(0x810018, priv->dramc_ao + DRAMC_SHU_ACTIM3);
+	writel(0x1e9700ff, priv->dramc_ao + DRAMC_SHU_ACTIM4);
+	writel(0x1000908, priv->dramc_ao + DRAMC_SHU_ACTIM5);
+	writel(0x801040b, priv->dramc_ao + DRAMC_SHU_ACTIM_XRT);
+	writel(0x20000D1, priv->dramc_ao + DRAMC_SHU_AC_TIME_05T);
+	writel(0x80010000, priv->ddrphy + DDRPHY_PLL2);
+	udelay(500);
+
+	writel(0x81080000, priv->dramc_ao + DRAMC_MISCTL0);
+	writel(0xacf13, priv->dramc_ao + DRAMC_PERFCTL0);
+	writel(0xacf12, priv->dramc_ao + DRAMC_PERFCTL0);
+	writel(0x80, priv->dramc_ao + DRAMC_ARBCTL);
+	writel(0x9, priv->dramc_ao + DRAMC_PADCTRL);
+	writel(0x80000107, priv->dramc_ao + DRAMC_DRAMC_PD_CTRL);
+	writel(0x3000000c, priv->dramc_ao + DRAMC_CLKCTRL);
+	writel(0x25714001, priv->dramc_ao + DRAMC_REFCTRL0);
+	writel(0x35b1f1cf, priv->dramc_ao + DRAMC_SPCMDCTRL);
+	writel(0x4300000, priv->dramc_ao + DRAMC_CATRAINING1);
+	writel(0xb0300000, priv->dramc_ao + DRAMC_STBCAL);
+	writel(0x731414, priv->dramc_ao + DRAMC_RKCFG);
+	writel(0x733414, priv->dramc_ao + DRAMC_RKCFG);
+	udelay(20);
+
+	writel(0x80002050, priv->dramc_ao + DRAMC_CKECTRL);
+	udelay(100);
+
+	writel(0x400000, priv->dramc_ao + DRAMC_MRS);
+	writel(0x401800, priv->dramc_ao + DRAMC_MRS);
+	writel(0x1, priv->dramc_ao + DRAMC_SPCMD);
+	writel(0x0, priv->dramc_ao + DRAMC_SPCMD);
+	udelay(100);
+
+	writel(0x601800, priv->dramc_ao + DRAMC_MRS);
+	writel(0x600000, priv->dramc_ao + DRAMC_MRS);
+	writel(0x1, priv->dramc_ao + DRAMC_SPCMD);
+	writel(0x0, priv->dramc_ao + DRAMC_SPCMD);
+	udelay(100);
+
+	writel(0x200000, priv->dramc_ao + DRAMC_MRS);
+	writel(0x200400, priv->dramc_ao + DRAMC_MRS);
+	writel(0x1, priv->dramc_ao + DRAMC_SPCMD);
+	writel(0x0, priv->dramc_ao + DRAMC_SPCMD);
+	udelay(100);
+
+	writel(0x400, priv->dramc_ao + DRAMC_MRS);
+	writel(0x1d7000, priv->dramc_ao + DRAMC_MRS);
+	writel(0x1, priv->dramc_ao + DRAMC_SPCMD);
+	writel(0x0, priv->dramc_ao + DRAMC_SPCMD);
+	udelay(100);
+
+	writel(0x702201, priv->dramc_ao + DRAMC_DRAMCTRL);
+	writel(0x10, priv->dramc_ao + DRAMC_SPCMD);
+	writel(0x0, priv->dramc_ao + DRAMC_SPCMD);
+	writel(0x20, priv->dramc_ao + DRAMC_SPCMD);
+	writel(0x0, priv->dramc_ao + DRAMC_SPCMD);
+	writel(0x1, priv->dramc_ao + DRAMC_HW_MRR_FUN);
+	writel(0x702301, priv->dramc_ao + DRAMC_DRAMCTRL);
+	writel(0x702301, priv->dramc_ao + DRAMC_DRAMCTRL);
+	writel(0xa56, priv->dramc_ao + DRAMC_ZQCS);
+	writel(0xff0000, priv->dramc_ao + DRAMC_SHU_CONF3);
+	writel(0x15b1f1cf, priv->dramc_ao + DRAMC_SPCMDCTRL);
+	writel(0x2cb00b0f, priv->dramc_ao + DRAMC_SHU_CONF1);
+	writel(0x65714001, priv->dramc_ao + DRAMC_REFCTRL0);
+	writel(0x48000000, priv->dramc_ao + DRAMC_SREFCTRL);
+	writel(0xc0000107, priv->dramc_ao + DRAMC_DRAMC_PD_CTRL);
+	writel(0x10002, priv->dramc_ao + DRAMC_EYESCAN);
+	writel(0x15e00, priv->dramc_ao + DRAMC_STBCAL1);
+	writel(0x100000, priv->dramc_ao + DRAMC_TEST2_1);
+	writel(0x4000, priv->dramc_ao + DRAMC_TEST2_2);
+	writel(0x12000480, priv->dramc_ao + DRAMC_TEST2_3);
+	writel(0x301d007, priv->dramc_ao + DRAMC_SHUCTRL2);
+	writel(0x4782321, priv->dramc_ao + DRAMC_DRAMCTRL);
+	writel(0x30210000, priv->dramc_ao + DRAMC_SHU_CKECTRL);
+	writel(0x20000, priv->dramc_ao + DRAMC_DUMMY_RD);
+	writel(0x4080110d, priv->dramc_ao + DRAMC_TEST2_4);
+	writel(0x30000721, priv->dramc_ao + DRAMC_REFCTRL1);
+	writel(0x0, priv->dramc_ao + DRAMC_RSTMASK);
+	writel(0x4782320, priv->dramc_ao + DRAMC_DRAMCTRL);
+	writel(0x80002000, priv->dramc_ao + DRAMC_CKECTRL);
+	writel(0x45714001, priv->dramc_ao + DRAMC_REFCTRL0);
+
+	/* Apply config before calibration */
+	writel(0x120, priv->dramc_ao + DRAMC_DRAMC_PD_CTRL);
+	writel(0x11351131, priv->ddrphy + DDRPHY_MISC_CTRL3);
+	writel(0xffffffff, priv->ddrphy + DDRPHY_MISC_CG_CTRL0);
+	writel(0x2a7fe, priv->dramc_ao + DRAMC_SHU_SCINTV);
+	writel(0xff01ff, priv->dramc_ao + DRAMC_SHU_CONF3);
+	writel(0x4782320, priv->dramc_ao + DRAMC_DRAMCTRL);
+	writel(0xa56, priv->dramc_ao + DRAMC_ZQCS);
+	writel(0x80000000, priv->dramc_ao + DRAMC_SHU1_WODT);
+	writel(0x21, priv->ddrphy + DDRPHY_SHU1_B0_DQ7);
+	writel(0x1, priv->ddrphy + DDRPHY_SHU1_B1_DQ7);
+	writel(0x35b1f1cf, priv->dramc_ao + DRAMC_SPCMDCTRL);
+	writel(0x35b1f1cf, priv->dramc_ao + DRAMC_SPCMDCTRL);
+	writel(0x35b1f1cf, priv->dramc_ao + DRAMC_SPCMDCTRL);
+	writel(0xb0300000, priv->dramc_ao + DRAMC_STBCAL);
+	writel(0xb0300000, priv->dramc_ao + DRAMC_STBCAL);
+	writel(0x10002, priv->dramc_ao + DRAMC_EYESCAN);
+	writel(0x8100008c, priv->ddrphy + DDRPHY_MISC_CTRL1);
+	writel(0x45714001, priv->dramc_ao + DRAMC_REFCTRL0);
+	writel(0xb0300000, priv->dramc_ao + DRAMC_STBCAL);
+	writel(0xb0300000, priv->dramc_ao + DRAMC_STBCAL);
+
+	/* Write leveling */
+	writel(0x1f2e2e00, priv->ddrphy + DDRPHY_SHU1_R0_B0_DQ7);
+	writel(0x202f2f00, priv->ddrphy + DDRPHY_SHU1_R0_B1_DQ7);
+	writel(0x33221100, priv->dramc_ao + DRAMC_SHU_SELPH_DQS1);
+	writel(0x11112222, priv->dramc_ao + DRAMC_SHU_SELPH_DQS0);
+
+	/* RX dqs gating cal */
+	writel(0x11111010, priv->dramc_ao + DRAMC_SHURK0_SELPH_DQSG0);
+	writel(0x20201717, priv->dramc_ao + DRAMC_SHURK0_SELPH_DQSG1);
+	writel(0x1d1f, priv->dramc_ao + DRAMC_SHURK0_DQSIEN);
+
+	/* RX window per-bit cal */
+	writel(0x03030404, priv->ddrphy + DDRPHY_SHU1_R0_B0_DQ2);
+	writel(0x01010303, priv->ddrphy + DDRPHY_SHU1_R0_B0_DQ3);
+	writel(0x01010303, priv->ddrphy + DDRPHY_SHU1_R0_B0_DQ4);
+	writel(0x01010000, priv->ddrphy + DDRPHY_SHU1_R0_B0_DQ5);
+	writel(0x03030606, priv->ddrphy + DDRPHY_SHU1_R0_B1_DQ2);
+	writel(0x02020202, priv->ddrphy + DDRPHY_SHU1_R0_B1_DQ3);
+	writel(0x04040303, priv->ddrphy + DDRPHY_SHU1_R0_B1_DQ4);
+	writel(0x06060101, priv->ddrphy + DDRPHY_SHU1_R0_B1_DQ5);
+
+	/* RX datlat cal */
+	writel(0x28b00a0e, priv->dramc_ao + DRAMC_SHU_CONF1);
+
+	/* TX window per-byte with 2UI cal */
+	writel(0x11112222, priv->dramc_ao + DRAMC_SHURK0_SELPH_DQ0);
+	writel(0x22220000, priv->dramc_ao + DRAMC_SHURK0_SELPH_DQ2);
+	writel(0x11112222, priv->dramc_ao + DRAMC_SHURK0_SELPH_DQ1);
+	writel(0x22220000, priv->dramc_ao + DRAMC_SHURK0_SELPH_DQ3);
+	writel(0x1f2e2e00, priv->ddrphy + DDRPHY_SHU1_R0_B0_DQ7);
+	writel(0x202f2f00, priv->ddrphy + DDRPHY_SHU1_R0_B1_DQ7);
+
+	return mtk_ddr3_rank_size_detect(dev);
+}
+#endif
+
+static int mtk_ddr3_probe(struct udevice *dev)
+{
+	struct mtk_ddr3_priv *priv = dev_get_priv(dev);
+
+	priv->emi = dev_read_addr_index(dev, 0);
+	if (priv->emi == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	priv->ddrphy = dev_read_addr_index(dev, 1);
+	if (priv->ddrphy == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	priv->dramc_ao = dev_read_addr_index(dev, 2);
+	if (priv->dramc_ao == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+#ifdef CONFIG_SPL_BUILD
+	int ret;
+
+	ret = clk_get_by_index(dev, 0, &priv->phy);
+	if (ret)
+		return ret;
+
+	ret = clk_get_by_index(dev, 1, &priv->phy_mux);
+	if (ret)
+		return ret;
+
+	ret = clk_get_by_index(dev, 2, &priv->mem);
+	if (ret)
+		return ret;
+
+	ret = clk_get_by_index(dev, 3, &priv->mem_mux);
+	if (ret)
+		return ret;
+
+	ret = mtk_ddr3_init(dev);
+	if (ret)
+		return ret;
+#endif
+	return 0;
+}
+
+static int mtk_ddr3_get_info(struct udevice *dev, struct ram_info *info)
+{
+	struct mtk_ddr3_priv *priv = dev_get_priv(dev);
+	u32 val = readl(priv->emi + EMI_CONA);
+
+	info->base = CONFIG_SYS_SDRAM_BASE;
+
+	switch ((val & EMI_COL_ADDR_MASK) >> EMI_COL_ADDR_SHIFT) {
+	case 0:
+		info->size = SZ_128M;
+		break;
+	case 1:
+		info->size = SZ_256M;
+		break;
+	case 2:
+		info->size = SZ_512M;
+		break;
+	case 3:
+		info->size = SZ_1G;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static struct ram_ops mtk_ddr3_ops = {
+	.get_info = mtk_ddr3_get_info,
+};
+
+static const struct udevice_id mtk_ddr3_ids[] = {
+	{ .compatible = "mediatek,mt7629-dramc" },
+	{ }
+};
+
+U_BOOT_DRIVER(mediatek_ddr3) = {
+	.name     = "mediatek_ddr3",
+	.id       = UCLASS_RAM,
+	.of_match = mtk_ddr3_ids,
+	.ops      = &mtk_ddr3_ops,
+	.probe    = mtk_ddr3_probe,
+	.priv_auto_alloc_size = sizeof(struct mtk_ddr3_priv),
+};
-- 
1.9.1

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

* [U-Boot] [PATCH v2 16/18] mmc: mtk-sd: add SD/MMC host controller driver for MT7623 SoC
  2018-10-12  7:00 [U-Boot] [PATCH v2 00/18] Add U-Boot support for MediaTek SoCs - MT7623n & MT7629 Ryder Lee
                   ` (14 preceding siblings ...)
  2018-10-12  7:01 ` [U-Boot] [PATCH v2 15/18] ram: MediaTek: add DDR3 driver for MT7629 SoC Ryder Lee
@ 2018-10-12  7:01 ` Ryder Lee
  2018-10-25  3:30   ` Simon Glass
  2018-10-12  7:01 ` [U-Boot] [PATCH v2 17/18] spi: mtk_qspi: add qspi driver for MT7629 SoC Ryder Lee
  2018-10-12  7:01 ` [U-Boot] [PATCH v2 18/18] MAINTAINERS: add an entry for MediaTek Ryder Lee
  17 siblings, 1 reply; 57+ messages in thread
From: Ryder Lee @ 2018-10-12  7:01 UTC (permalink / raw)
  To: u-boot

From: Weijie Gao <weijie.gao@mediatek.com>

This patch adds MT7623 host controller driver for accessing SD/MMC.

Cc: Jaehoon Chung <jh80.chung@samsung.com>
Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
Tested-by: Matthias Brugger <matthias.bgg@gmail.com>
---
 drivers/mmc/Kconfig  |    9 +
 drivers/mmc/Makefile |    1 +
 drivers/mmc/mtk-sd.c | 1331 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 1341 insertions(+)
 create mode 100644 drivers/mmc/mtk-sd.c

diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 0a0d4aa..ca13341 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -598,6 +598,15 @@ config FTSDC010_SDIO
 	help
 		This can enable ftsdc010 sdio function.
 
+config MMC_MTK
+	bool "MediaTek SD/MMC Card Interface support"
+	default n
+	help
+	  This selects the MediaTek(R) Secure digital and Multimedia card Interface.
+	  If you have a machine with a integrated SD/MMC card reader, say Y or M here.
+	  This is needed if support for any SD/SDIO/MMC devices is required.
+	  If unsure, say N.
+
 endif
 
 config TEGRA124_MMC_DISABLE_EXT_LOOPBACK
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 23c5b0d..801a26d 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -65,3 +65,4 @@ obj-$(CONFIG_MMC_SUNXI)			+= sunxi_mmc.o
 obj-$(CONFIG_MMC_UNIPHIER)		+= tmio-common.o uniphier-sd.o
 obj-$(CONFIG_RENESAS_SDHI)		+= tmio-common.o renesas-sdhi.o
 obj-$(CONFIG_MMC_BCM2835)		+= bcm2835_sdhost.o
+obj-$(CONFIG_MMC_MTK)			+= mtk-sd.o
diff --git a/drivers/mmc/mtk-sd.c b/drivers/mmc/mtk-sd.c
new file mode 100644
index 0000000..5027764
--- /dev/null
+++ b/drivers/mmc/mtk-sd.c
@@ -0,0 +1,1331 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MediaTek SD/MMC Card Interface driver
+ *
+ * Copyright (C) 2018 MediaTek Inc.
+ * Author: Weijie Gao <weijie.gao@mediatek.com>
+ */
+
+#include <clk.h>
+#include <common.h>
+#include <dm.h>
+#include <dm/pinctrl.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <malloc.h>
+#include <mmc.h>
+#include <asm/gpio.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+
+#define MSDC_CFG			0x0
+#define   MSDC_CFG_HS400_CK_MODE_EXT	BIT(22)
+#define   MSDC_CFG_CKMOD_EXT_M		0x03
+#define   MSDC_CFG_CKMOD_EXT_S		20
+#define   MSDC_CFG_CKDIV_EXT_M		0xfff
+#define   MSDC_CFG_CKDIV_EXT_S		8
+#define   MSDC_CFG_HS400_CK_MODE	BIT(18)
+#define   MSDC_CFG_CKMOD_M		0x03
+#define   MSDC_CFG_CKMOD_S		16
+#define   MSDC_CFG_CKDIV_M		0xff
+#define   MSDC_CFG_CKDIV_S		8
+#define   MSDC_CFG_CKSTB		BIT(7)
+#define   MSDC_CFG_PIO			BIT(3)
+#define   MSDC_CFG_RST			BIT(2)
+#define   MSDC_CFG_CKPDN		BIT(1)
+#define   MSDC_CFG_MODE			BIT(0)
+
+#define MSDC_IOCON			0x04
+#define   MSDC_IOCON_W_DSPL		BIT(8)
+#define   MSDC_IOCON_DSPL		BIT(2)
+#define   MSDC_IOCON_RSPL		BIT(1)
+
+#define MSDC_PS				0x08
+#define   MSDC_PS_DAT0			BIT(16)
+#define   MSDC_PS_CDEN			BIT(0)
+
+#define MSDC_INT			0x0c
+#define MSDC_INTEN			0x10
+#define   MSDC_INT_ACMDRDY		BIT(3)
+#define   MSDC_INT_ACMDTMO		BIT(4)
+#define   MSDC_INT_ACMDCRCERR		BIT(5)
+#define   MSDC_INT_CMDRDY		BIT(8)
+#define   MSDC_INT_CMDTMO		BIT(9)
+#define   MSDC_INT_RSPCRCERR		BIT(10)
+#define   MSDC_INT_XFER_COMPL		BIT(12)
+#define   MSDC_INT_DATTMO		BIT(14)
+#define   MSDC_INT_DATCRCERR		BIT(15)
+
+#define MSDC_FIFOCS			0x14
+#define   MSDC_FIFOCS_CLR		BIT(31)
+#define   MSDC_FIFOCS_TXCNT_M		0xff
+#define   MSDC_FIFOCS_TXCNT_S		16
+#define   MSDC_FIFOCS_RXCNT_M		0xff
+#define   MSDC_FIFOCS_RXCNT_S		0
+
+#define MSDC_TXDATA			0x18
+#define MSDC_RXDATA			0x1c
+
+#define SDC_CFG				0x30
+#define   SDC_CFG_DTOC_M		0xff
+#define   SDC_CFG_DTOC_S		24
+#define   SDC_CFG_SDIOIDE		BIT(20)
+#define   SDC_CFG_SDIO			BIT(19)
+#define   SDC_CFG_BUSWIDTH_M		0x03
+#define   SDC_CFG_BUSWIDTH_S		16
+
+#define SDC_CMD				0x34
+#define   SDC_CMD_BLK_LEN_M		0xfff
+#define   SDC_CMD_BLK_LEN_S		16
+#define   SDC_CMD_STOP			BIT(14)
+#define   SDC_CMD_WR			BIT(13)
+#define   SDC_CMD_DTYPE_M		0x03
+#define   SDC_CMD_DTYPE_S		11
+#define   SDC_CMD_RSPTYP_M		0x07
+#define   SDC_CMD_RSPTYP_S		7
+#define   SDC_CMD_CMD_M			0x3f
+#define   SDC_CMD_CMD_S			0
+
+#define SDC_ARG				0x38
+
+#define SDC_STS				0x3c
+#define   SDC_STS_CMDBUSY		BIT(1)
+#define   SDC_STS_SDCBUSY		BIT(0)
+
+#define SDC_RESP0			0x40
+#define SDC_RESP1			0x44
+#define SDC_RESP2			0x48
+#define SDC_RESP3			0x4c
+
+#define SDC_BLK_NUM			0x50
+
+#define SDC_ADV_CFG0			0x64
+#define   SDC_RX_ENHANCE_EN		BIT(20)
+
+#define MSDC_PATCH_BIT			0xb0
+#define   MSDC_INT_DAT_LATCH_CK_SEL_M	0x07
+#define   MSDC_INT_DAT_LATCH_CK_SEL_S	7
+
+#define MSDC_PATCH_BIT1			0xb4
+#define   MSDC_PB1_STOP_DLY_M		0x0f
+#define   MSDC_PB1_STOP_DLY_S		8
+
+#define MSDC_PATCH_BIT2			0xb8
+#define   MSDC_PB2_CRCSTSENSEL_M	0x07
+#define   MSDC_PB2_CRCSTSENSEL_S	29
+#define   MSDC_PB2_CFGCRCSTS		BIT(28)
+#define   MSDC_PB2_RESPSTSENSEL_M	0x07
+#define   MSDC_PB2_RESPSTSENSEL_S	16
+#define   MSDC_PB2_CFGRESP		BIT(15)
+#define   MSDC_PB2_RESPWAIT_M		0x03
+#define   MSDC_PB2_RESPWAIT_S		2
+
+#define MSDC_PAD_TUNE			0xec
+#define   MSDC_PAD_TUNE_CMDRRDLY_M	0x1f
+#define   MSDC_PAD_TUNE_CMDRRDLY_S	22
+#define   MSDC_PAD_TUNE_CMD_SEL		BIT(21)
+#define   MSDC_PAD_TUNE_CMDRDLY_M	0x1f
+#define   MSDC_PAD_TUNE_CMDRDLY_S	16
+#define   MSDC_PAD_TUNE_RXDLYSEL	BIT(15)
+#define   MSDC_PAD_TUNE_RD_SEL		BIT(13)
+#define   MSDC_PAD_TUNE_DATRRDLY_M	0x1f
+#define   MSDC_PAD_TUNE_DATRRDLY_S	8
+#define   MSDC_PAD_TUNE_DATWRDLY_M	0x1f
+#define   MSDC_PAD_TUNE_DATWRDLY_S	0
+
+#define MSDC_PAD_TUNE0			0xf0
+
+#define PAD_DS_TUNE			0x188
+
+#define EMMC50_CFG0			0x208
+#define   EMMC50_CFG_CFCSTS_SEL		BIT(4)
+
+#define SDC_FIFO_CFG			0x228
+#define   SDC_FIFO_CFG_WRVALIDSEL	BIT(24)
+#define   SDC_FIFO_CFG_RDVALIDSEL	BIT(25)
+
+/* SDC_CFG_BUSWIDTH */
+#define MSDC_BUS_1BITS			0x0
+#define MSDC_BUS_4BITS			0x1
+#define MSDC_BUS_8BITS			0x2
+
+#define MSDC_FIFO_SIZE			128
+
+#define PAD_DELAY_MAX			32
+
+#define CMD_INTS_MASK	\
+	(MSDC_INT_CMDRDY | MSDC_INT_RSPCRCERR | MSDC_INT_CMDTMO)
+
+#define DATA_INTS_MASK	\
+	(MSDC_INT_XFER_COMPL | MSDC_INT_DATTMO | MSDC_INT_DATCRCERR)
+
+struct msdc_compatible {
+	u8 clk_div_bits;
+	bool pad_tune0;
+	bool async_fifo;
+	bool data_tune;
+	bool busy_check;
+	bool stop_clk_fix;
+	bool enhance_rx;
+};
+
+struct msdc_delay_phase {
+	u8 maxlen;
+	u8 start;
+	u8 final_phase;
+};
+
+struct msdc_plat {
+	struct mmc_config cfg;
+	struct mmc mmc;
+};
+
+struct msdc_tune_para {
+	u32 iocon;
+	u32 pad_tune;
+};
+
+struct msdc_host {
+	void __iomem *base;
+	struct mmc *mmc;
+
+	struct msdc_compatible *dev_comp;
+
+	struct clk src_clk;
+	struct clk h_clk;
+
+	u32 mclk;
+	u32 src_clk_freq;
+	u32 sclk;
+
+	u32 timeout_ns;
+	u32 timeout_clks;
+
+	u32 hs400_ds_delay;
+	u32 hs200_cmd_int_delay;
+	u32 hs200_write_int_delay;
+	u32 latch_ck;
+	u32 r_smpl;
+	bool hs400_mode;
+
+	struct gpio_desc gpio_wp;
+	struct gpio_desc gpio_cd;
+
+	uint last_resp_type;
+	uint last_data_write;
+
+	enum bus_mode timing;
+
+	struct msdc_tune_para def_tune_para;
+	struct msdc_tune_para saved_tune_para;
+};
+
+static void msdc_reset_hw(struct msdc_host *host)
+{
+	u32 reg;
+
+	setbits_le32(host->base + MSDC_CFG, MSDC_CFG_RST);
+
+	readl_poll_timeout(host->base + MSDC_CFG, reg,
+			   !(reg & MSDC_CFG_RST), 1000000);
+}
+
+static void msdc_fifo_clr(struct msdc_host *host)
+{
+	u32 reg;
+
+	setbits_le32(host->base + MSDC_FIFOCS, MSDC_FIFOCS_CLR);
+
+	readl_poll_timeout(host->base + MSDC_FIFOCS, reg,
+			   !(reg & MSDC_FIFOCS_CLR), 1000000);
+}
+
+static u32 msdc_fifo_rx_bytes(struct msdc_host *host)
+{
+	return (readl(host->base + MSDC_FIFOCS) >> MSDC_FIFOCS_RXCNT_S) &
+		MSDC_FIFOCS_RXCNT_M;
+}
+
+static u32 msdc_fifo_tx_bytes(struct msdc_host *host)
+{
+	return (readl(host->base + MSDC_FIFOCS) >> MSDC_FIFOCS_TXCNT_S) &
+		MSDC_FIFOCS_TXCNT_M;
+}
+
+static u32 msdc_cmd_find_resp(struct msdc_host *host, struct mmc_cmd *cmd)
+{
+	u32 resp;
+
+	switch (cmd->resp_type) {
+		/* Actually, R1, R5, R6, R7 are the same */
+	case MMC_RSP_R1:
+		resp = 0x1;
+		break;
+	case MMC_RSP_R1b:
+		resp = 0x7;
+		break;
+	case MMC_RSP_R2:
+		resp = 0x2;
+		break;
+	case MMC_RSP_R3:
+		resp = 0x3;
+		break;
+	case MMC_RSP_NONE:
+	default:
+		resp = 0x0;
+		break;
+	}
+
+	return resp;
+}
+
+static u32 msdc_cmd_prepare_raw_cmd(struct msdc_host *host,
+				    struct mmc_cmd *cmd,
+				    struct mmc_data *data)
+{
+	u32 opcode = cmd->cmdidx;
+	u32 resp_type = msdc_cmd_find_resp(host, cmd);
+	uint blocksize = 0;
+	u32 dtype = 0;
+	u32 rawcmd = 0;
+
+	switch (opcode) {
+	case MMC_CMD_WRITE_MULTIPLE_BLOCK:
+	case MMC_CMD_READ_MULTIPLE_BLOCK:
+		dtype = 2;
+		break;
+	case MMC_CMD_WRITE_SINGLE_BLOCK:
+	case MMC_CMD_READ_SINGLE_BLOCK:
+	case SD_CMD_APP_SEND_SCR:
+		dtype = 1;
+		break;
+	case SD_CMD_SWITCH_FUNC: /* same as MMC_CMD_SWITCH */
+	case SD_CMD_SEND_IF_COND: /* same as MMC_CMD_SEND_EXT_CSD */
+	case SD_CMD_APP_SD_STATUS: /* same as MMC_CMD_SEND_STATUS */
+		if (data)
+			dtype = 1;
+	}
+
+	if (data) {
+		if (data->flags == MMC_DATA_WRITE)
+			rawcmd |= SDC_CMD_WR;
+
+		if (data->blocks > 1)
+			dtype = 2;
+
+		blocksize = data->blocksize;
+	}
+
+	rawcmd |= ((opcode & SDC_CMD_CMD_M) << SDC_CMD_CMD_S) |
+		((resp_type & SDC_CMD_RSPTYP_M) << SDC_CMD_RSPTYP_S) |
+		((blocksize & SDC_CMD_BLK_LEN_M) << SDC_CMD_BLK_LEN_S) |
+		((dtype & SDC_CMD_DTYPE_M) << SDC_CMD_DTYPE_S);
+
+	if (opcode == MMC_CMD_STOP_TRANSMISSION)
+		rawcmd |= SDC_CMD_STOP;
+
+	return rawcmd;
+}
+
+static int msdc_cmd_done(struct msdc_host *host, int events,
+			 struct mmc_cmd *cmd)
+{
+	u32 *rsp = cmd->response;
+	int ret = 0;
+
+	if (cmd->resp_type & MMC_RSP_PRESENT) {
+		if (cmd->resp_type & MMC_RSP_136) {
+			rsp[0] = readl(host->base + SDC_RESP3);
+			rsp[1] = readl(host->base + SDC_RESP2);
+			rsp[2] = readl(host->base + SDC_RESP1);
+			rsp[3] = readl(host->base + SDC_RESP0);
+		} else {
+			rsp[0] = readl(host->base + SDC_RESP0);
+		}
+	}
+
+	if (!(events & MSDC_INT_CMDRDY)) {
+		if (cmd->cmdidx != MMC_CMD_SEND_TUNING_BLOCK &&
+		    cmd->cmdidx != MMC_CMD_SEND_TUNING_BLOCK_HS200)
+			/*
+			 * should not clear fifo/interrupt as the tune data
+			 * may have alreay come.
+			 */
+			msdc_reset_hw(host);
+
+		if (events & MSDC_INT_CMDTMO)
+			ret = -ETIMEDOUT;
+		else
+			ret = -EIO;
+	}
+
+	return ret;
+}
+
+static bool msdc_cmd_is_ready(struct msdc_host *host)
+{
+	int ret;
+	u32 reg;
+
+	/* The max busy time we can endure is 20ms */
+	ret = readl_poll_timeout(host->base + SDC_STS, reg,
+				 !(reg & SDC_STS_CMDBUSY), 20000);
+
+	if (ret) {
+		pr_err("CMD bus busy detected\n");
+		msdc_reset_hw(host);
+		return false;
+	}
+
+	if (host->last_resp_type == MMC_RSP_R1b && host->last_data_write) {
+		ret = readl_poll_timeout(host->base + MSDC_PS, reg,
+					 reg & MSDC_PS_DAT0, 1000000);
+
+		if (ret) {
+			pr_err("Card stuck in programming state!\n");
+			msdc_reset_hw(host);
+			return false;
+		}
+	}
+
+	return true;
+}
+
+static int msdc_start_command(struct msdc_host *host, struct mmc_cmd *cmd,
+			      struct mmc_data *data)
+{
+	u32 rawcmd;
+	u32 status;
+	u32 blocks = 0;
+	int ret;
+
+	if (!msdc_cmd_is_ready(host))
+		return -EIO;
+
+	msdc_fifo_clr(host);
+
+	host->last_resp_type = cmd->resp_type;
+	host->last_data_write = 0;
+
+	rawcmd = msdc_cmd_prepare_raw_cmd(host, cmd, data);
+
+	if (data)
+		blocks = data->blocks;
+
+	writel(CMD_INTS_MASK, host->base + MSDC_INT);
+	writel(blocks, host->base + SDC_BLK_NUM);
+	writel(cmd->cmdarg, host->base + SDC_ARG);
+	writel(rawcmd, host->base + SDC_CMD);
+
+	ret = readl_poll_timeout(host->base + MSDC_INT, status,
+				 status & CMD_INTS_MASK, 1000000);
+
+	if (ret)
+		status = MSDC_INT_CMDTMO;
+
+	return msdc_cmd_done(host, status, cmd);
+}
+
+static void msdc_fifo_read(struct msdc_host *host, u8 *buf, u32 size)
+{
+	u32 *wbuf;
+
+	while ((size_t)buf % 4) {
+		*buf++ = readb(host->base + MSDC_RXDATA);
+		size--;
+	}
+
+	wbuf = (u32 *)buf;
+	while (size >= 4) {
+		*wbuf++ = readl(host->base + MSDC_RXDATA);
+		size -= 4;
+	}
+
+	buf = (u8 *)wbuf;
+	while (size) {
+		*buf++ = readb(host->base + MSDC_RXDATA);
+		size--;
+	}
+}
+
+static void msdc_fifo_write(struct msdc_host *host, const u8 *buf, u32 size)
+{
+	const u32 *wbuf;
+
+	while ((size_t)buf % 4) {
+		writeb(*buf++, host->base + MSDC_TXDATA);
+		size--;
+	}
+
+	wbuf = (const u32 *)buf;
+	while (size >= 4) {
+		writel(*wbuf++, host->base + MSDC_TXDATA);
+		size -= 4;
+	}
+
+	buf = (const u8 *)wbuf;
+	while (size) {
+		writeb(*buf++, host->base + MSDC_TXDATA);
+		size--;
+	}
+}
+
+static int msdc_pio_read(struct msdc_host *host, u8 *ptr, u32 size)
+{
+	u32 status;
+	u32 chksz;
+	int ret = 0;
+
+	while (1) {
+		status = readl(host->base + MSDC_INT);
+		writel(status, host->base + MSDC_INT);
+		status &= DATA_INTS_MASK;
+
+		if (status & MSDC_INT_DATCRCERR) {
+			ret = -EIO;
+			break;
+		}
+
+		if (status & MSDC_INT_DATTMO) {
+			ret = -ETIMEDOUT;
+			break;
+		}
+
+		if (status & MSDC_INT_XFER_COMPL) {
+			if (size) {
+				pr_err("data not fully read\n");
+				ret = -EIO;
+			}
+
+			break;
+		}
+
+		chksz = min(size, (u32)MSDC_FIFO_SIZE);
+
+		if (msdc_fifo_rx_bytes(host) >= chksz) {
+			msdc_fifo_read(host, ptr, chksz);
+			ptr += chksz;
+			size -= chksz;
+		}
+	}
+
+	return ret;
+}
+
+static int msdc_pio_write(struct msdc_host *host, const u8 *ptr, u32 size)
+{
+	u32 status;
+	u32 chksz;
+	int ret = 0;
+
+	while (1) {
+		status = readl(host->base + MSDC_INT);
+		writel(status, host->base + MSDC_INT);
+		status &= DATA_INTS_MASK;
+
+		if (status & MSDC_INT_DATCRCERR) {
+			ret = -EIO;
+			break;
+		}
+
+		if (status & MSDC_INT_DATTMO) {
+			ret = -ETIMEDOUT;
+			break;
+		}
+
+		if (status & MSDC_INT_XFER_COMPL) {
+			if (size) {
+				pr_err("data not fully written\n");
+				ret = -EIO;
+			}
+
+			break;
+		}
+
+		chksz = min(size, (u32)MSDC_FIFO_SIZE);
+
+		if (MSDC_FIFO_SIZE - msdc_fifo_tx_bytes(host) >= chksz) {
+			msdc_fifo_write(host, ptr, chksz);
+			ptr += chksz;
+			size -= chksz;
+		}
+	}
+
+	return ret;
+}
+
+static int msdc_start_data(struct msdc_host *host, struct mmc_data *data)
+{
+	u32 size;
+	int ret;
+
+	if (data->flags == MMC_DATA_WRITE)
+		host->last_data_write = 1;
+
+	writel(DATA_INTS_MASK, host->base + MSDC_INT);
+
+	size = data->blocks * data->blocksize;
+
+	if (data->flags == MMC_DATA_WRITE)
+		ret = msdc_pio_write(host, (const u8 *)data->src, size);
+	else
+		ret = msdc_pio_read(host, (u8 *)data->dest, size);
+
+	if (ret) {
+		msdc_reset_hw(host);
+		msdc_fifo_clr(host);
+	}
+
+	return ret;
+}
+
+static int msdc_ops_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
+			     struct mmc_data *data)
+{
+	struct msdc_host *host = dev_get_priv(dev);
+	int ret;
+
+	ret = msdc_start_command(host, cmd, data);
+	if (ret)
+		return ret;
+
+	if (data)
+		return msdc_start_data(host, data);
+
+	return 0;
+}
+
+static void msdc_set_timeout(struct msdc_host *host, u32 ns, u32 clks)
+{
+	u32 timeout, clk_ns;
+	u32 mode = 0;
+
+	host->timeout_ns = ns;
+	host->timeout_clks = clks;
+
+	if (host->sclk == 0) {
+		timeout = 0;
+	} else {
+		clk_ns = 1000000000UL / host->sclk;
+		timeout = (ns + clk_ns - 1) / clk_ns + clks;
+		/* unit is 1048576 sclk cycles */
+		timeout = (timeout + (0x1 << 20) - 1) >> 20;
+		if (host->dev_comp->clk_div_bits == 8)
+			mode = (readl(host->base + MSDC_CFG) >>
+				MSDC_CFG_CKMOD_S) & MSDC_CFG_CKMOD_M;
+		else
+			mode = (readl(host->base + MSDC_CFG) >>
+				MSDC_CFG_CKMOD_EXT_S) & MSDC_CFG_CKMOD_EXT_M;
+		/* DDR mode will double the clk cycles for data timeout */
+		timeout = mode >= 2 ? timeout * 2 : timeout;
+		timeout = timeout > 1 ? timeout - 1 : 0;
+		timeout = timeout > 255 ? 255 : timeout;
+	}
+
+	clrsetbits_le32(host->base + SDC_CFG, SDC_CFG_DTOC_M << SDC_CFG_DTOC_S,
+			timeout << SDC_CFG_DTOC_S);
+}
+
+static void msdc_set_buswidth(struct msdc_host *host, u32 width)
+{
+	u32 val = readl(host->base + SDC_CFG);
+
+	val &= ~(SDC_CFG_BUSWIDTH_M << SDC_CFG_BUSWIDTH_S);
+
+	switch (width) {
+	default:
+	case 1:
+		val |= (MSDC_BUS_1BITS << SDC_CFG_BUSWIDTH_S);
+		break;
+	case 4:
+		val |= (MSDC_BUS_4BITS << SDC_CFG_BUSWIDTH_S);
+		break;
+	case 8:
+		val |= (MSDC_BUS_8BITS << SDC_CFG_BUSWIDTH_S);
+		break;
+	}
+
+	writel(val, host->base + SDC_CFG);
+}
+
+static void msdc_set_mclk(struct msdc_host *host, enum bus_mode timing, u32 hz)
+{
+	u32 mode;
+	u32 div;
+	u32 sclk;
+	u32 reg;
+
+	if (!hz) {
+		host->mclk = 0;
+		clrbits_le32(host->base + MSDC_CFG, MSDC_CFG_CKPDN);
+		return;
+	}
+
+	if (host->dev_comp->clk_div_bits == 8)
+		clrbits_le32(host->base + MSDC_CFG, MSDC_CFG_HS400_CK_MODE);
+	else
+		clrbits_le32(host->base + MSDC_CFG,
+			     MSDC_CFG_HS400_CK_MODE_EXT);
+
+	if (timing == UHS_DDR50 || timing == MMC_DDR_52 ||
+	    timing == MMC_HS_400) {
+		if (timing == MMC_HS_400)
+			mode = 0x3;
+		else
+			mode = 0x2; /* ddr mode and use divisor */
+
+		if (hz >= (host->src_clk_freq >> 2)) {
+			div = 0; /* mean div = 1/4 */
+			sclk = host->src_clk_freq >> 2; /* sclk = clk / 4 */
+		} else {
+			div = (host->src_clk_freq + ((hz << 2) - 1)) /
+			       (hz << 2);
+			sclk = (host->src_clk_freq >> 2) / div;
+			div = (div >> 1);
+		}
+
+		if (timing == MMC_HS_400 && hz >= (host->src_clk_freq >> 1)) {
+			if (host->dev_comp->clk_div_bits == 8)
+				setbits_le32(host->base + MSDC_CFG,
+					     MSDC_CFG_HS400_CK_MODE);
+			else
+				setbits_le32(host->base + MSDC_CFG,
+					     MSDC_CFG_HS400_CK_MODE_EXT);
+
+			sclk = host->src_clk_freq >> 1;
+			div = 0; /* div is ignore when bit18 is set */
+		}
+	} else if (hz >= host->src_clk_freq) {
+		mode = 0x1; /* no divisor */
+		div = 0;
+		sclk = host->src_clk_freq;
+	} else {
+		mode = 0x0; /* use divisor */
+		if (hz >= (host->src_clk_freq >> 1)) {
+			div = 0; /* mean div = 1/2 */
+			sclk = host->src_clk_freq >> 1; /* sclk = clk / 2 */
+		} else {
+			div = (host->src_clk_freq + ((hz << 2) - 1)) /
+			       (hz << 2);
+			sclk = (host->src_clk_freq >> 2) / div;
+		}
+	}
+
+	clrbits_le32(host->base + MSDC_CFG, MSDC_CFG_CKPDN);
+
+	if (host->dev_comp->clk_div_bits == 8) {
+		div = min(div, (u32)MSDC_CFG_CKDIV_M);
+		clrsetbits_le32(host->base + MSDC_CFG,
+				(MSDC_CFG_CKMOD_M << MSDC_CFG_CKMOD_S) |
+				(MSDC_CFG_CKDIV_M << MSDC_CFG_CKDIV_S),
+				(mode << MSDC_CFG_CKMOD_S) |
+				(div << MSDC_CFG_CKDIV_S));
+	} else {
+		div = min(div, (u32)MSDC_CFG_CKDIV_EXT_M);
+		clrsetbits_le32(host->base + MSDC_CFG,
+				(MSDC_CFG_CKMOD_EXT_M << MSDC_CFG_CKMOD_EXT_S) |
+				(MSDC_CFG_CKDIV_EXT_M << MSDC_CFG_CKDIV_EXT_S),
+				(mode << MSDC_CFG_CKMOD_S) |
+				(div << MSDC_CFG_CKDIV_EXT_S));
+	}
+
+	readl_poll_timeout(host->base + MSDC_CFG, reg,
+			   reg & MSDC_CFG_CKSTB, 1000000);
+
+	setbits_le32(host->base + MSDC_CFG, MSDC_CFG_CKPDN);
+	host->sclk = sclk;
+	host->mclk = hz;
+	host->timing = timing;
+
+	/* needed because clk changed. */
+	msdc_set_timeout(host, host->timeout_ns, host->timeout_clks);
+
+	/*
+	 * mmc_select_hs400() will drop to 50Mhz and High speed mode,
+	 * tune result of hs200/200Mhz is not suitable for 50Mhz
+	 */
+	if (host->sclk <= 52000000) {
+		writel(host->def_tune_para.iocon, host->base + MSDC_IOCON);
+		writel(host->def_tune_para.pad_tune,
+		       host->base + MSDC_PAD_TUNE);
+	} else {
+		writel(host->saved_tune_para.iocon, host->base + MSDC_IOCON);
+		writel(host->saved_tune_para.pad_tune,
+		       host->base + MSDC_PAD_TUNE);
+	}
+
+	dev_dbg(dev, "sclk: %d, timing: %d\n", host->sclk, timing);
+}
+
+static int msdc_ops_set_ios(struct udevice *dev)
+{
+	struct msdc_plat *plat = dev_get_platdata(dev);
+	struct msdc_host *host = dev_get_priv(dev);
+	struct mmc *mmc = &plat->mmc;
+	uint clock = mmc->clock;
+
+	msdc_set_buswidth(host, mmc->bus_width);
+
+	if (mmc->clk_disable)
+		clock = 0;
+	else if (clock < mmc->cfg->f_min)
+		clock = mmc->cfg->f_min;
+
+	if (host->mclk != clock || host->timing != mmc->selected_mode)
+		msdc_set_mclk(host, mmc->selected_mode, clock);
+
+	return 0;
+}
+
+#ifdef CONFIG_DM_GPIO
+static int msdc_ops_get_cd(struct udevice *dev)
+{
+	struct msdc_host *host = dev_get_priv(dev);
+
+	if (!host->gpio_cd.dev)
+		return 1;
+
+	return dm_gpio_get_value(&host->gpio_cd);
+}
+
+static int msdc_ops_get_wp(struct udevice *dev)
+{
+	struct msdc_host *host = dev_get_priv(dev);
+
+	if (!host->gpio_wp.dev)
+		return 0;
+
+	return !dm_gpio_get_value(&host->gpio_wp);
+}
+#endif
+
+#ifdef MMC_SUPPORTS_TUNING
+static u32 test_delay_bit(u32 delay, u32 bit)
+{
+	bit %= PAD_DELAY_MAX;
+	return delay & (1 << bit);
+}
+
+static int get_delay_len(u32 delay, u32 start_bit)
+{
+	int i;
+
+	for (i = 0; i < (PAD_DELAY_MAX - start_bit); i++) {
+		if (test_delay_bit(delay, start_bit + i) == 0)
+			return i;
+	}
+
+	return PAD_DELAY_MAX - start_bit;
+}
+
+static struct msdc_delay_phase get_best_delay(struct msdc_host *host, u32 delay)
+{
+	int start = 0, len = 0;
+	int start_final = 0, len_final = 0;
+	u8 final_phase = 0xff;
+	struct msdc_delay_phase delay_phase = { 0, };
+
+	if (delay == 0) {
+		dev_err(dev, "phase error: [map:%x]\n", delay);
+		delay_phase.final_phase = final_phase;
+		return delay_phase;
+	}
+
+	while (start < PAD_DELAY_MAX) {
+		len = get_delay_len(delay, start);
+		if (len_final < len) {
+			start_final = start;
+			len_final = len;
+		}
+
+		start += len ? len : 1;
+		if (len >= 12 && start_final < 4)
+			break;
+	}
+
+	/* The rule is to find the smallest delay cell */
+	if (start_final == 0)
+		final_phase = (start_final + len_final / 3) % PAD_DELAY_MAX;
+	else
+		final_phase = (start_final + len_final / 2) % PAD_DELAY_MAX;
+
+	dev_info(dev, "phase: [map:%x] [maxlen:%d] [final:%d]\n",
+		 delay, len_final, final_phase);
+
+	delay_phase.maxlen = len_final;
+	delay_phase.start = start_final;
+	delay_phase.final_phase = final_phase;
+	return delay_phase;
+}
+
+static int msdc_tune_response(struct udevice *dev, u32 opcode)
+{
+	struct msdc_plat *plat = dev_get_platdata(dev);
+	struct msdc_host *host = dev_get_priv(dev);
+	struct mmc *mmc = &plat->mmc;
+	u32 rise_delay = 0, fall_delay = 0;
+	struct msdc_delay_phase final_rise_delay, final_fall_delay = { 0, };
+	struct msdc_delay_phase internal_delay_phase;
+	u8 final_delay, final_maxlen;
+	u32 internal_delay = 0;
+	u32 tune_reg = MSDC_PAD_TUNE;
+	int cmd_err;
+	int i, j;
+
+	if (host->dev_comp->pad_tune0)
+		tune_reg = MSDC_PAD_TUNE0;
+
+	if (mmc->selected_mode == MMC_HS_200 ||
+	    mmc->selected_mode == UHS_SDR104)
+		clrsetbits_le32(host->base + tune_reg,
+				MSDC_PAD_TUNE_CMDRRDLY_M <<
+				MSDC_PAD_TUNE_CMDRRDLY_S,
+				host->hs200_cmd_int_delay <<
+				MSDC_PAD_TUNE_CMDRRDLY_S);
+
+	clrbits_le32(host->base + MSDC_IOCON, MSDC_IOCON_RSPL);
+
+	for (i = 0; i < PAD_DELAY_MAX; i++) {
+		clrsetbits_le32(host->base + tune_reg,
+				MSDC_PAD_TUNE_CMDRDLY_M <<
+				MSDC_PAD_TUNE_CMDRDLY_S,
+				i << MSDC_PAD_TUNE_CMDRDLY_S);
+
+		for (j = 0; j < 3; j++) {
+			mmc_send_tuning(mmc, opcode, &cmd_err);
+			if (!cmd_err) {
+				rise_delay |= (1 << i);
+			} else {
+				rise_delay &= ~(1 << i);
+				break;
+			}
+		}
+	}
+
+	final_rise_delay = get_best_delay(host, rise_delay);
+	/* if rising edge has enough margin, do not scan falling edge */
+	if (final_rise_delay.maxlen >= 12 ||
+	    (final_rise_delay.start == 0 && final_rise_delay.maxlen >= 4))
+		goto skip_fall;
+
+	setbits_le32(host->base + MSDC_IOCON, MSDC_IOCON_RSPL);
+	for (i = 0; i < PAD_DELAY_MAX; i++) {
+		clrsetbits_le32(host->base + tune_reg,
+				MSDC_PAD_TUNE_CMDRDLY_M <<
+				MSDC_PAD_TUNE_CMDRDLY_S,
+				i << MSDC_PAD_TUNE_CMDRDLY_S);
+
+		for (j = 0; j < 3; j++) {
+			mmc_send_tuning(mmc, opcode, &cmd_err);
+			if (!cmd_err) {
+				fall_delay |= (1 << i);
+			} else {
+				fall_delay &= ~(1 << i);
+				break;
+			}
+		}
+	}
+
+	final_fall_delay = get_best_delay(host, fall_delay);
+
+skip_fall:
+	final_maxlen = max(final_rise_delay.maxlen, final_fall_delay.maxlen);
+	if (final_maxlen == final_rise_delay.maxlen) {
+		clrbits_le32(host->base + MSDC_IOCON, MSDC_IOCON_RSPL);
+		clrsetbits_le32(host->base + tune_reg,
+				MSDC_PAD_TUNE_CMDRDLY_M <<
+				MSDC_PAD_TUNE_CMDRDLY_S,
+				final_rise_delay.final_phase <<
+				MSDC_PAD_TUNE_CMDRDLY_S);
+		final_delay = final_rise_delay.final_phase;
+	} else {
+		setbits_le32(host->base + MSDC_IOCON, MSDC_IOCON_RSPL);
+		clrsetbits_le32(host->base + tune_reg,
+				MSDC_PAD_TUNE_CMDRDLY_M <<
+				MSDC_PAD_TUNE_CMDRDLY_S,
+				final_fall_delay.final_phase <<
+				MSDC_PAD_TUNE_CMDRDLY_S);
+		final_delay = final_fall_delay.final_phase;
+	}
+
+	if (host->dev_comp->async_fifo || host->hs200_cmd_int_delay)
+		goto skip_internal;
+
+	for (i = 0; i < PAD_DELAY_MAX; i++) {
+		clrsetbits_le32(host->base + tune_reg,
+				MSDC_PAD_TUNE_CMDRRDLY_M <<
+				MSDC_PAD_TUNE_CMDRRDLY_S,
+				i << MSDC_PAD_TUNE_CMDRRDLY_S);
+
+		mmc_send_tuning(mmc, opcode, &cmd_err);
+		if (!cmd_err)
+			internal_delay |= (1 << i);
+	}
+
+	dev_err(dev, "Final internal delay: 0x%x\n", internal_delay);
+
+	internal_delay_phase = get_best_delay(host, internal_delay);
+	clrsetbits_le32(host->base + tune_reg,
+			MSDC_PAD_TUNE_CMDRRDLY_M <<
+			MSDC_PAD_TUNE_CMDRRDLY_S,
+			internal_delay_phase.final_phase <<
+			MSDC_PAD_TUNE_CMDRRDLY_S);
+
+skip_internal:
+	dev_err(dev, "Final cmd pad delay: %x\n", final_delay);
+	return final_delay == 0xff ? -EIO : 0;
+}
+
+static int msdc_tune_data(struct udevice *dev, u32 opcode)
+{
+	struct msdc_plat *plat = dev_get_platdata(dev);
+	struct msdc_host *host = dev_get_priv(dev);
+	struct mmc *mmc = &plat->mmc;
+	u32 rise_delay = 0, fall_delay = 0;
+	struct msdc_delay_phase final_rise_delay, final_fall_delay = { 0, };
+	u8 final_delay, final_maxlen;
+	u32 tune_reg = MSDC_PAD_TUNE;
+	int cmd_err;
+	int i, ret;
+
+	if (host->dev_comp->pad_tune0)
+		tune_reg = MSDC_PAD_TUNE0;
+
+	clrbits_le32(host->base + MSDC_IOCON, MSDC_IOCON_DSPL);
+	clrbits_le32(host->base + MSDC_IOCON, MSDC_IOCON_W_DSPL);
+
+	for (i = 0; i < PAD_DELAY_MAX; i++) {
+		clrsetbits_le32(host->base + tune_reg,
+				MSDC_PAD_TUNE_DATRRDLY_M <<
+				MSDC_PAD_TUNE_DATRRDLY_S,
+				i << MSDC_PAD_TUNE_DATRRDLY_S);
+
+		ret = mmc_send_tuning(mmc, opcode, &cmd_err);
+		if (!ret) {
+			rise_delay |= (1 << i);
+		} else if (cmd_err) {
+			/* in this case, retune response is needed */
+			ret = msdc_tune_response(dev, opcode);
+			if (ret)
+				break;
+		}
+	}
+
+	final_rise_delay = get_best_delay(host, rise_delay);
+	if (final_rise_delay.maxlen >= 12 ||
+	    (final_rise_delay.start == 0 && final_rise_delay.maxlen >= 4))
+		goto skip_fall;
+
+	setbits_le32(host->base + MSDC_IOCON, MSDC_IOCON_DSPL);
+	setbits_le32(host->base + MSDC_IOCON, MSDC_IOCON_W_DSPL);
+
+	for (i = 0; i < PAD_DELAY_MAX; i++) {
+		clrsetbits_le32(host->base + tune_reg,
+				MSDC_PAD_TUNE_DATRRDLY_M <<
+				MSDC_PAD_TUNE_DATRRDLY_S,
+				i << MSDC_PAD_TUNE_DATRRDLY_S);
+
+		ret = mmc_send_tuning(mmc, opcode, &cmd_err);
+		if (!ret) {
+			fall_delay |= (1 << i);
+		} else if (cmd_err) {
+			/* in this case, retune response is needed */
+			ret = msdc_tune_response(dev, opcode);
+			if (ret)
+				break;
+		}
+	}
+
+	final_fall_delay = get_best_delay(host, fall_delay);
+
+skip_fall:
+	final_maxlen = max(final_rise_delay.maxlen, final_fall_delay.maxlen);
+	if (final_maxlen == final_rise_delay.maxlen) {
+		clrbits_le32(host->base + MSDC_IOCON, MSDC_IOCON_DSPL);
+		clrbits_le32(host->base + MSDC_IOCON, MSDC_IOCON_W_DSPL);
+		clrsetbits_le32(host->base + tune_reg,
+				MSDC_PAD_TUNE_DATRRDLY_M <<
+				MSDC_PAD_TUNE_DATRRDLY_S,
+				final_rise_delay.final_phase <<
+				MSDC_PAD_TUNE_DATRRDLY_S);
+		final_delay = final_rise_delay.final_phase;
+	} else {
+		setbits_le32(host->base + MSDC_IOCON, MSDC_IOCON_DSPL);
+		setbits_le32(host->base + MSDC_IOCON, MSDC_IOCON_W_DSPL);
+		clrsetbits_le32(host->base + tune_reg,
+				MSDC_PAD_TUNE_DATRRDLY_M <<
+				MSDC_PAD_TUNE_DATRRDLY_S,
+				final_fall_delay.final_phase <<
+				MSDC_PAD_TUNE_DATRRDLY_S);
+		final_delay = final_fall_delay.final_phase;
+	}
+
+	if (mmc->selected_mode == MMC_HS_200 ||
+	    mmc->selected_mode == UHS_SDR104)
+		clrsetbits_le32(host->base + tune_reg,
+				MSDC_PAD_TUNE_DATWRDLY_M <<
+				MSDC_PAD_TUNE_DATWRDLY_S,
+				host->hs200_write_int_delay <<
+				MSDC_PAD_TUNE_DATWRDLY_S);
+
+	dev_err(dev, "Final data pad delay: %x\n", final_delay);
+
+	return final_delay == 0xff ? -EIO : 0;
+}
+
+static int msdc_execute_tuning(struct udevice *dev, uint opcode)
+{
+	struct msdc_plat *plat = dev_get_platdata(dev);
+	struct msdc_host *host = dev_get_priv(dev);
+	struct mmc *mmc = &plat->mmc;
+	int ret;
+
+	if (mmc->selected_mode == MMC_HS_400) {
+		writel(host->hs400_ds_delay, host->base + PAD_DS_TUNE);
+		/* for hs400 mode it must be set to 0 */
+		clrbits_le32(host->base + MSDC_PATCH_BIT2, MSDC_PB2_CFGCRCSTS);
+		host->hs400_mode = true;
+	}
+
+	ret = msdc_tune_response(dev, opcode);
+	if (ret == -EIO) {
+		dev_err(dev, "Tune response fail!\n");
+		return ret;
+	}
+
+	if (!host->hs400_mode) {
+		ret = msdc_tune_data(dev, opcode);
+		if (ret == -EIO)
+			dev_err(dev, "Tune data fail!\n");
+	}
+
+	host->saved_tune_para.iocon = readl(host->base + MSDC_IOCON);
+	host->saved_tune_para.pad_tune = readl(host->base + MSDC_PAD_TUNE);
+
+	return ret;
+}
+#endif
+
+static void msdc_init_hw(struct msdc_host *host)
+{
+	u32 val;
+	u32 tune_reg = MSDC_PAD_TUNE;
+
+	if (host->dev_comp->pad_tune0)
+		tune_reg = MSDC_PAD_TUNE0;
+
+	/* Configure to MMC/SD mode, clock free running */
+	setbits_le32(host->base + MSDC_CFG, MSDC_CFG_MODE);
+
+	/* Use PIO mode */
+	setbits_le32(host->base + MSDC_CFG, MSDC_CFG_PIO);
+
+	/* Reset */
+	msdc_reset_hw(host);
+
+	/* Disable card detection */
+	clrbits_le32(host->base + MSDC_PS, MSDC_PS_CDEN);
+
+	/* Clear all interrupts */
+	val = readl(host->base + MSDC_INT);
+	writel(val, host->base + MSDC_INT);
+
+	/* Enable data & cmd interrupts */
+	writel(DATA_INTS_MASK | CMD_INTS_MASK, host->base + MSDC_INTEN);
+
+	writel(0, host->base + tune_reg);
+	writel(0, host->base + MSDC_IOCON);
+
+	if (host->r_smpl)
+		setbits_le32(host->base + MSDC_IOCON, MSDC_IOCON_RSPL);
+	else
+		clrbits_le32(host->base + MSDC_IOCON, MSDC_IOCON_RSPL);
+
+	writel(0x403c0046, host->base + MSDC_PATCH_BIT);
+	writel(0xffff4089, host->base + MSDC_PATCH_BIT1);
+
+	if (host->dev_comp->stop_clk_fix)
+		clrsetbits_le32(host->base + MSDC_PATCH_BIT1,
+				MSDC_PB1_STOP_DLY_M << MSDC_PB1_STOP_DLY_S,
+				3 << MSDC_PB1_STOP_DLY_S);
+
+	if (host->dev_comp->busy_check)
+		clrbits_le32(host->base + MSDC_PATCH_BIT1, (1 << 7));
+
+	setbits_le32(host->base + EMMC50_CFG0, EMMC50_CFG_CFCSTS_SEL);
+
+	if (host->dev_comp->async_fifo) {
+		clrsetbits_le32(host->base + MSDC_PATCH_BIT2,
+				MSDC_PB2_RESPWAIT_M << MSDC_PB2_RESPWAIT_S,
+				3 << MSDC_PB2_RESPWAIT_S);
+
+		if (host->dev_comp->enhance_rx) {
+			setbits_le32(host->base + SDC_ADV_CFG0,
+				     SDC_RX_ENHANCE_EN);
+		} else {
+			clrsetbits_le32(host->base + MSDC_PATCH_BIT2,
+					MSDC_PB2_RESPSTSENSEL_M <<
+					MSDC_PB2_RESPSTSENSEL_S,
+					2 << MSDC_PB2_RESPSTSENSEL_S);
+			clrsetbits_le32(host->base + MSDC_PATCH_BIT2,
+					MSDC_PB2_CRCSTSENSEL_M <<
+					MSDC_PB2_CRCSTSENSEL_S,
+					2 << MSDC_PB2_CRCSTSENSEL_S);
+		}
+
+		/* use async fifo to avoid tune internal delay */
+		clrbits_le32(host->base + MSDC_PATCH_BIT2,
+			     MSDC_PB2_CFGRESP);
+		clrbits_le32(host->base + MSDC_PATCH_BIT2,
+			     MSDC_PB2_CFGCRCSTS);
+	}
+
+	if (host->dev_comp->data_tune) {
+		setbits_le32(host->base + tune_reg,
+			     MSDC_PAD_TUNE_RD_SEL | MSDC_PAD_TUNE_CMD_SEL);
+		clrsetbits_le32(host->base + MSDC_PATCH_BIT,
+				MSDC_INT_DAT_LATCH_CK_SEL_S <<
+				MSDC_INT_DAT_LATCH_CK_SEL_M,
+				host->latch_ck <<
+				MSDC_INT_DAT_LATCH_CK_SEL_S);
+	} else {
+		/* choose clock tune */
+		setbits_le32(host->base + tune_reg, MSDC_PAD_TUNE_RXDLYSEL);
+	}
+
+	/* Configure to enable SDIO mode otherwise sdio cmd5 won't work */
+	setbits_le32(host->base + SDC_CFG, SDC_CFG_SDIO);
+
+	/* disable detecting SDIO device interrupt function */
+	clrbits_le32(host->base + SDC_CFG, SDC_CFG_SDIOIDE);
+
+	/* Configure to default data timeout */
+	clrsetbits_le32(host->base + SDC_CFG,
+			SDC_CFG_DTOC_M << SDC_CFG_DTOC_S,
+			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 + MSDC_PAD_TUNE);
+}
+
+static void msdc_ungate_clock(struct msdc_host *host)
+{
+	clk_enable(&host->src_clk);
+	clk_enable(&host->h_clk);
+}
+
+static int msdc_drv_probe(struct udevice *dev)
+{
+	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+	struct msdc_plat *plat = dev_get_platdata(dev);
+	struct msdc_host *host = dev_get_priv(dev);
+	struct mmc_config *cfg = &plat->cfg;
+	int ret;
+
+	cfg->name = dev->name;
+
+	host->base = (void *)dev_read_addr(dev);
+	if (!host->base)
+		return -EINVAL;
+
+	ret = mmc_of_parse(dev, cfg);
+	if (ret)
+		return ret;
+
+	ret = clk_get_by_name(dev, "source", &host->src_clk);
+	if (ret < 0)
+		return ret;
+
+	ret = clk_get_by_name(dev, "hclk", &host->h_clk);
+	if (ret < 0)
+		return ret;
+
+	gpio_request_by_name(dev, "wp-gpios", 0, &host->gpio_wp, GPIOD_IS_IN);
+	gpio_request_by_name(dev, "cd-gpios", 0, &host->gpio_cd, GPIOD_IS_IN);
+
+	host->hs400_ds_delay = dev_read_u32_default(dev, "hs400-ds-delay", 0);
+	host->hs200_cmd_int_delay =
+			dev_read_u32_default(dev, "cmd_int_delay", 0);
+	host->hs200_write_int_delay =
+			dev_read_u32_default(dev, "write_int_delay", 0);
+	host->latch_ck = dev_read_u32_default(dev, "latch-ck", 0);
+	host->r_smpl = dev_read_u32_default(dev, "r_smpl", 0);
+
+	host->dev_comp = (struct msdc_compatible *)dev_get_driver_data(dev);
+
+	host->src_clk_freq = clk_get_rate(&host->src_clk);
+
+	if (host->dev_comp->clk_div_bits == 8)
+		cfg->f_min = host->src_clk_freq / (4 * 255);
+	else
+		cfg->f_min = host->src_clk_freq / (4 * 4095);
+
+	cfg->b_max = 1024;
+	cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
+
+	host->mmc = &plat->mmc;
+	host->timeout_ns = 100000000;
+	host->timeout_clks = 3 * 1048576;
+
+	pinctrl_select_state(dev, "default");
+
+	msdc_ungate_clock(host);
+	msdc_init_hw(host);
+
+	upriv->mmc = &plat->mmc;
+
+	return 0;
+}
+
+static int msdc_drv_bind(struct udevice *dev)
+{
+	struct msdc_plat *plat = dev_get_platdata(dev);
+
+	return mmc_bind(dev, &plat->mmc, &plat->cfg);
+}
+
+static const struct dm_mmc_ops msdc_ops = {
+	.send_cmd = msdc_ops_send_cmd,
+	.set_ios = msdc_ops_set_ios,
+#ifdef CONFIG_DM_GPIO
+	.get_cd = msdc_ops_get_cd,
+	.get_wp = msdc_ops_get_wp,
+#endif
+#ifdef MMC_SUPPORTS_TUNING
+	.execute_tuning = msdc_execute_tuning,
+#endif
+};
+
+static const struct msdc_compatible mt7623_compat = {
+	.clk_div_bits = 12,
+	.pad_tune0 = true,
+	.async_fifo = true,
+	.data_tune = true,
+	.busy_check = false,
+	.stop_clk_fix = false,
+	.enhance_rx = false
+};
+
+static const struct udevice_id msdc_ids[] = {
+	{ .compatible = "mediatek,mt7623-mmc", .data = (ulong)&mt7623_compat },
+	{}
+};
+
+U_BOOT_DRIVER(mtk_sd_drv) = {
+	.name = "mtk_sd",
+	.id = UCLASS_MMC,
+	.of_match = msdc_ids,
+	.bind = msdc_drv_bind,
+	.probe = msdc_drv_probe,
+	.ops = &msdc_ops,
+	.platdata_auto_alloc_size = sizeof(struct msdc_plat),
+	.priv_auto_alloc_size = sizeof(struct msdc_host),
+};
-- 
1.9.1

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

* [U-Boot] [PATCH v2 17/18] spi: mtk_qspi: add qspi driver for MT7629 SoC
  2018-10-12  7:00 [U-Boot] [PATCH v2 00/18] Add U-Boot support for MediaTek SoCs - MT7623n & MT7629 Ryder Lee
                   ` (15 preceding siblings ...)
  2018-10-12  7:01 ` [U-Boot] [PATCH v2 16/18] mmc: mtk-sd: add SD/MMC host controller driver for MT7623 SoC Ryder Lee
@ 2018-10-12  7:01 ` Ryder Lee
  2018-10-25  3:30   ` Simon Glass
                     ` (2 more replies)
  2018-10-12  7:01 ` [U-Boot] [PATCH v2 18/18] MAINTAINERS: add an entry for MediaTek Ryder Lee
  17 siblings, 3 replies; 57+ messages in thread
From: Ryder Lee @ 2018-10-12  7:01 UTC (permalink / raw)
  To: u-boot

From: Guochun Mao <guochun.mao@mediatek.com>

This patch adds MT7629 qspi driver for accessing SPI NOR flash.

Cc: Jagan Teki <jagan@openedev.com>
Signed-off-by: Guochun Mao <guochun.mao@mediatek.com>
---
change since v2:
- Drop flash commands in the driver.
---
 drivers/spi/Kconfig    |   7 +
 drivers/spi/Makefile   |   1 +
 drivers/spi/mtk_qspi.c | 359 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 367 insertions(+)
 create mode 100644 drivers/spi/mtk_qspi.c

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 1df6876..f9cf4ba 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -124,6 +124,13 @@ config MT7621_SPI
 	  the SPI NOR flash on platforms embedding this Ralink / MediaTek
 	  SPI core, like MT7621/7628/7688.
 
+config MTK_QSPI
+	bool "Mediatek QSPI driver"
+	help
+	  Enable the Mediatek QSPI driver. This driver can be
+	  used to access the SPI NOR flash on platforms embedding this
+	  Mediatek QSPI IP core.
+
 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 7242ea7..e5a78f5 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -33,6 +33,7 @@ obj-$(CONFIG_KIRKWOOD_SPI) += kirkwood_spi.o
 obj-$(CONFIG_LPC32XX_SSP) += lpc32xx_ssp.o
 obj-$(CONFIG_MPC8XX_SPI) += mpc8xx_spi.o
 obj-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o
+obj-$(CONFIG_MTK_QSPI) += mtk_qspi.o
 obj-$(CONFIG_MT7621_SPI) += mt7621_spi.o
 obj-$(CONFIG_MVEBU_A3700_SPI) += mvebu_a3700_spi.o
 obj-$(CONFIG_MXC_SPI) += mxc_spi.o
diff --git a/drivers/spi/mtk_qspi.c b/drivers/spi/mtk_qspi.c
new file mode 100644
index 0000000..b510733
--- /dev/null
+++ b/drivers/spi/mtk_qspi.c
@@ -0,0 +1,359 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018  MediaTek, Inc.
+ * Author : Guochun.Mao at mediatek.com
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <malloc.h>
+#include <spi.h>
+#include <asm/io.h>
+#include <linux/iopoll.h>
+#include <linux/ioport.h>
+
+/* Register Offset */
+struct mtk_qspi_regs {
+	u32 cmd;
+	u32 cnt;
+	u32 rdsr;
+	u32 rdata;
+	u32 radr[3];
+	u32 wdata;
+	u32 prgdata[6];
+	u32 shreg[10];
+	u32 cfg[2];
+	u32 shreg10;
+	u32 mode_mon;
+	u32 status[4];
+	u32 flash_time;
+	u32 flash_cfg;
+	u32 reserved_0[3];
+	u32 sf_time;
+	u32 pp_dw_data;
+	u32 reserved_1;
+	u32 delsel_0[2];
+	u32 intrstus;
+	u32 intren;
+	u32 reserved_2;
+	u32 cfg3;
+	u32 reserved_3;
+	u32 chksum;
+	u32 aaicmd;
+	u32 wrprot;
+	u32 radr3;
+	u32 dual;
+	u32 delsel_1[3];
+};
+
+struct mtk_qspi_platdata {
+	fdt_addr_t reg_base;
+	fdt_addr_t mem_base;
+};
+
+struct mtk_qspi_priv {
+	struct mtk_qspi_regs *regs;
+	unsigned long *mem_base;
+	u8 op;
+	u8 tx[3]; /* only record max 3 bytes paras, when it's address. */
+	u32 txlen; /* dout buffer length  - op code length */
+	u8 *rx;
+	u32 rxlen;
+};
+
+#define MTK_QSPI_CMD_POLLINGREG_US 500000
+#define MTK_QSPI_WRBUF_SIZE        256
+#define MTK_QSPI_COMMAND_ENABLE    0x30
+
+/* NOR flash controller commands */
+#define MTK_QSPI_RD_TRIGGER        BIT(0)
+#define MTK_QSPI_READSTATUS        BIT(1)
+#define MTK_QSPI_PRG_CMD           BIT(2)
+#define MTK_QSPI_WR_TRIGGER        BIT(4)
+#define MTK_QSPI_WRITESTATUS       BIT(5)
+#define MTK_QSPI_AUTOINC           BIT(7)
+
+#define MTK_QSPI_MAX_RX_TX_SHIFT   0x6
+#define MTK_QSPI_MAX_SHIFT         0x8
+
+#define MTK_QSPI_WR_BUF_ENABLE     0x1
+#define MTK_QSPI_WR_BUF_DISABLE    0x0
+
+static int mtk_qspi_execute_cmd(struct mtk_qspi_priv *priv, u8 cmd)
+{
+	u8 tmp;
+	u8 val = cmd & ~MTK_QSPI_AUTOINC;
+
+	writeb(cmd, &priv->regs->cmd);
+
+	return readb_poll_timeout(&priv->regs->cmd, tmp, !(val & tmp),
+				  MTK_QSPI_CMD_POLLINGREG_US);
+}
+
+static int mtk_qspi_tx_rx(struct mtk_qspi_priv *priv)
+{
+	int len = 1 + priv->txlen + priv->rxlen;
+	int i, ret, idx;
+
+	if (len > MTK_QSPI_MAX_SHIFT)
+		return -ERR_INVAL;
+
+	writeb(len * 8, &priv->regs->cnt);
+
+	/* start at PRGDATA5, go down to PRGDATA0 */
+	idx = MTK_QSPI_MAX_RX_TX_SHIFT - 1;
+
+	/* opcode */
+	writeb(priv->op, &priv->regs->prgdata[idx]);
+	idx--;
+
+	/* program TX data */
+	for (i = 0; i < priv->txlen; i++, idx--)
+		writeb(priv->tx[i], &priv->regs->prgdata[idx]);
+
+	/* clear out rest of TX registers */
+	while (idx >= 0) {
+		writeb(0, &priv->regs->prgdata[idx]);
+		idx--;
+	}
+
+	ret = mtk_qspi_execute_cmd(priv, MTK_QSPI_PRG_CMD);
+	if (ret)
+		return ret;
+
+	/* restart at first RX byte */
+	idx = priv->rxlen - 1;
+
+	/* read out RX data */
+	for (i = 0; i < priv->rxlen; i++, idx--)
+		priv->rx[i] = readb(&priv->regs->shreg[idx]);
+
+	return 0;
+}
+
+static int mtk_qspi_read(struct mtk_qspi_priv *priv,
+			 u32 addr, u8 *buf, u32 len)
+{
+	memcpy(buf, (u8 *)priv->mem_base + addr, len);
+	return 0;
+}
+
+static void mtk_qspi_set_addr(struct mtk_qspi_priv *priv, u32 addr)
+{
+	int i;
+
+	for (i = 0; i < 3; i++) {
+		writeb(addr & 0xff, &priv->regs->radr[i]);
+		addr >>= 8;
+	}
+}
+
+static int mtk_qspi_write_single_byte(struct mtk_qspi_priv *priv,
+				      u32 addr, u32 length, const u8 *data)
+{
+	int i, ret;
+
+	mtk_qspi_set_addr(priv, addr);
+
+	for (i = 0; i < length; i++) {
+		writeb(*data++, &priv->regs->wdata);
+		ret = mtk_qspi_execute_cmd(priv, MTK_QSPI_WR_TRIGGER);
+		if (ret < 0)
+			return ret;
+	}
+	return 0;
+}
+
+static int mtk_qspi_write_buffer(struct mtk_qspi_priv *priv, u32 addr,
+				 const u8 *buf)
+{
+	int i, data;
+
+	mtk_qspi_set_addr(priv, addr);
+
+	for (i = 0; i < MTK_QSPI_WRBUF_SIZE; i += 4) {
+		data = buf[i + 3] << 24 | buf[i + 2] << 16 |
+		       buf[i + 1] << 8 | buf[i];
+		writel(data, &priv->regs->pp_dw_data);
+	}
+
+	return mtk_qspi_execute_cmd(priv, MTK_QSPI_WR_TRIGGER);
+}
+
+static int mtk_qspi_write(struct mtk_qspi_priv *priv,
+			  u32 addr, const u8 *buf, u32 len)
+{
+	int ret;
+
+	/* setting pre-fetch buffer for page program */
+	writel(MTK_QSPI_WR_BUF_ENABLE, &priv->regs->cfg[1]);
+	while (len >= MTK_QSPI_WRBUF_SIZE) {
+		ret = mtk_qspi_write_buffer(priv, addr, buf);
+		if (ret < 0)
+			return ret;
+
+		len -= MTK_QSPI_WRBUF_SIZE;
+		addr += MTK_QSPI_WRBUF_SIZE;
+		buf += MTK_QSPI_WRBUF_SIZE;
+	}
+	/* disable pre-fetch buffer for page program */
+	writel(MTK_QSPI_WR_BUF_DISABLE, &priv->regs->cfg[1]);
+
+	if (len)
+		return mtk_qspi_write_single_byte(priv, addr, len, buf);
+
+	return 0;
+}
+
+static int mtk_qspi_claim_bus(struct udevice *dev)
+{
+	/* nothing to do */
+	return 0;
+}
+
+static int mtk_qspi_release_bus(struct udevice *dev)
+{
+	/* nothing to do */
+	return 0;
+}
+
+static int mtk_qspi_transfer(struct mtk_qspi_priv *priv, unsigned int bitlen,
+			     const void *dout, void *din, unsigned long flags)
+{
+	u32 bytes = DIV_ROUND_UP(bitlen, 8);
+	u32 addr;
+
+	if (!bytes)
+		return -ERR_INVAL;
+
+	if (dout) {
+		if (flags & SPI_XFER_BEGIN) {
+			/* parse op code and potential paras first */
+			priv->op = *(u8 *)dout;
+			if (bytes > 1)
+				memcpy(priv->tx, (u8 *)dout + 1,
+				       bytes <= 4 ? bytes - 1 : 3);
+			priv->txlen = bytes - 1;
+		}
+
+		if (flags == SPI_XFER_ONCE) {
+			/* operations without receiving or sending data.
+			 * for example: erase, write flash register or write
+			 * enable...
+			 */
+			priv->rx = NULL;
+			priv->rxlen = 0;
+			return mtk_qspi_tx_rx(priv);
+		}
+
+		if (flags & SPI_XFER_END) {
+			/* here, dout should be data to be written.
+			 * and priv->tx should be filled 3Bytes address.
+			 */
+			addr = priv->tx[0] << 16 | priv->tx[1] << 8 |
+			       priv->tx[2];
+			return mtk_qspi_write(priv, addr, (u8 *)dout, bytes);
+		}
+	}
+
+	if (din) {
+		if (priv->txlen >= 3) {
+			/* if run to here, priv->tx[] should be the address
+			 * where read data from,
+			 * and, din is the buf to receive data.
+			 */
+			addr = priv->tx[0] << 16 | priv->tx[1] << 8 |
+			       priv->tx[2];
+			return mtk_qspi_read(priv, addr, (u8 *)din, bytes);
+		}
+
+		/* should be reading flash's register */
+		priv->rx = (u8 *)din;
+		priv->rxlen = bytes;
+		return mtk_qspi_tx_rx(priv);
+	}
+
+	return 0;
+}
+
+static int mtk_qspi_xfer(struct udevice *dev, unsigned int bitlen,
+			 const void *dout, void *din, unsigned long flags)
+{
+	struct udevice *bus = dev->parent;
+	struct mtk_qspi_priv *priv = dev_get_priv(bus);
+
+	return  mtk_qspi_transfer(priv, bitlen, dout, din, flags);
+}
+
+static int mtk_qspi_set_speed(struct udevice *bus, uint speed)
+{
+	/* nothing to do */
+	return 0;
+}
+
+static int mtk_qspi_set_mode(struct udevice *bus, uint mode)
+{
+	/* nothing to do */
+	return 0;
+}
+
+static int mtk_qspi_ofdata_to_platdata(struct udevice *bus)
+{
+	struct resource res_reg, res_mem;
+	struct mtk_qspi_platdata *plat = bus->platdata;
+	int ret;
+
+	ret = dev_read_resource_byname(bus, "reg_base", &res_reg);
+	if (ret) {
+		debug("can't get reg_base resource(ret = %d)\n", ret);
+		return -ENOMEM;
+	}
+
+	ret = dev_read_resource_byname(bus, "mem_base", &res_mem);
+	if (ret) {
+		debug("can't get map_base resource(ret = %d)\n", ret);
+		return -ENOMEM;
+	}
+
+	plat->mem_base = res_mem.start;
+	plat->reg_base = res_reg.start;
+
+	return 0;
+}
+
+static int mtk_qspi_probe(struct udevice *bus)
+{
+	struct mtk_qspi_platdata *plat = dev_get_platdata(bus);
+	struct mtk_qspi_priv *priv = dev_get_priv(bus);
+
+	priv->regs = (struct mtk_qspi_regs *)plat->reg_base;
+	priv->mem_base = (unsigned long *)plat->mem_base;
+
+	writel(MTK_QSPI_COMMAND_ENABLE, &priv->regs->wrprot);
+
+	return 0;
+}
+
+static const struct dm_spi_ops mtk_qspi_ops = {
+	.claim_bus      = mtk_qspi_claim_bus,
+	.release_bus    = mtk_qspi_release_bus,
+	.xfer           = mtk_qspi_xfer,
+	.set_speed      = mtk_qspi_set_speed,
+	.set_mode       = mtk_qspi_set_mode,
+};
+
+static const struct udevice_id mtk_qspi_ids[] = {
+	{ .compatible = "mediatek,mt7629-qspi" },
+	{ }
+};
+
+U_BOOT_DRIVER(mtk_qspi) = {
+	.name     = "mtk_qspi",
+	.id       = UCLASS_SPI,
+	.of_match = mtk_qspi_ids,
+	.ops      = &mtk_qspi_ops,
+	.ofdata_to_platdata       = mtk_qspi_ofdata_to_platdata,
+	.platdata_auto_alloc_size = sizeof(struct mtk_qspi_platdata),
+	.priv_auto_alloc_size     = sizeof(struct mtk_qspi_priv),
+	.probe    = mtk_qspi_probe,
+};
-- 
1.9.1

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

* [U-Boot] [PATCH v2 18/18] MAINTAINERS: add an entry for MediaTek
  2018-10-12  7:00 [U-Boot] [PATCH v2 00/18] Add U-Boot support for MediaTek SoCs - MT7623n & MT7629 Ryder Lee
                   ` (16 preceding siblings ...)
  2018-10-12  7:01 ` [U-Boot] [PATCH v2 17/18] spi: mtk_qspi: add qspi driver for MT7629 SoC Ryder Lee
@ 2018-10-12  7:01 ` Ryder Lee
  2018-10-25  3:30   ` Simon Glass
  17 siblings, 1 reply; 57+ messages in thread
From: Ryder Lee @ 2018-10-12  7:01 UTC (permalink / raw)
  To: u-boot

This patch adds an entry for MediaTek.

Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
---
 MAINTAINERS | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index ace7d9a..c8b7ecb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -157,6 +157,24 @@ T:	git git://git.denx.de/u-boot-pxa.git
 F:	arch/arm/cpu/pxa/
 F:	arch/arm/include/asm/arch-pxa/
 
+ARM MEDIATEK
+M:	Ryder Lee <ryder.lee@mediatek.com>
+M:	Weijie Gao <weijie.gao@mediatek.com>
+S:	Maintained
+F:	arch/arm/mach-mediatek/
+F:	arch/arm/include/asm/arch-mediatek/
+F:	board/mediatek/
+F:	drivers/clk/mediatek/
+F:	drivers/mmc/mtk-sd.c
+F:	drivers/pinctrl/mediatek/
+F:	drivers/power/domain/mtk-power-domain.c
+F:	drivers/ram/mediatek/
+F:	drivers/spi/mtk_qspi.c
+F:	drivers/timer/mtk_timer.c
+F:	drivers/watchdog/mtk_wdt.c
+F:	tools/mtkimage.c
+N:	mediatek
+
 ARM OWL
 M:	Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
 S:	Maintained
-- 
1.9.1

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

* [U-Boot] [PATCH v2 09/18] watchdog: MediaTek: add watchdog driver for MediaTek SoCs
  2018-10-12  7:00 ` [U-Boot] [PATCH v2 09/18] watchdog: MediaTek: add watchdog " Ryder Lee
@ 2018-10-25  3:29   ` Simon Glass
  0 siblings, 0 replies; 57+ messages in thread
From: Simon Glass @ 2018-10-25  3:29 UTC (permalink / raw)
  To: u-boot

On 12 October 2018 at 01:00, Ryder Lee <ryder.lee@mediatek.com> wrote:
> This patch adds a common driver for the Mediatek SoC integrated
> watchdog.
>
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> Tested-by: Matthias Brugger <matthias.bgg@gmail.com>
> ---
>  drivers/watchdog/Kconfig   |   8 +++
>  drivers/watchdog/Makefile  |   1 +
>  drivers/watchdog/mtk_wdt.c | 135 +++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 144 insertions(+)
>  create mode 100644 drivers/watchdog/mtk_wdt.c

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

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

* [U-Boot] [PATCH v2 02/18] arm: dts: MediaTek: add device tree for MT7629
  2018-10-12  7:00 ` [U-Boot] [PATCH v2 02/18] arm: dts: MediaTek: add device tree for MT7629 Ryder Lee
@ 2018-10-25  3:29   ` Simon Glass
  0 siblings, 0 replies; 57+ messages in thread
From: Simon Glass @ 2018-10-25  3:29 UTC (permalink / raw)
  To: u-boot

On 12 October 2018 at 01:00, Ryder Lee <ryder.lee@mediatek.com> wrote:
> This patch adds MT7629 device tree and the includes it needs.
>
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> ---
>  arch/arm/dts/Makefile                    |   3 +
>  arch/arm/dts/mt7629-rfb.dts              |  71 +++++++++
>  arch/arm/dts/mt7629.dtsi                 | 244 +++++++++++++++++++++++++++++++
>  include/dt-bindings/clock/mt7629-clk.h   | 206 ++++++++++++++++++++++++++
>  include/dt-bindings/power/mt7629-power.h |  13 ++
>  5 files changed, 537 insertions(+)
>  create mode 100644 arch/arm/dts/mt7629-rfb.dts
>  create mode 100644 arch/arm/dts/mt7629.dtsi
>  create mode 100644 include/dt-bindings/clock/mt7629-clk.h
>  create mode 100644 include/dt-bindings/power/mt7629-power.h

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

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

* [U-Boot] [PATCH v2 03/18] arm: dts: MediaTek: add device tree for MT7623
  2018-10-12  7:00 ` [U-Boot] [PATCH v2 03/18] arm: dts: MediaTek: add device tree for MT7623 Ryder Lee
@ 2018-10-25  3:29   ` Simon Glass
  0 siblings, 0 replies; 57+ messages in thread
From: Simon Glass @ 2018-10-25  3:29 UTC (permalink / raw)
  To: u-boot

On 12 October 2018 at 01:00, Ryder Lee <ryder.lee@mediatek.com> wrote:
> This adds device tree for MT7623 development board - Bananapi R2
> Detailed hardware information for BPI-R2 which could be found on
> http://wiki.banana-pi.org/Banana_Pi_BPI-R2.
>
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> Tested-by: Matthias Brugger <matthias.bgg@gmail.com>
> ---
>  arch/arm/dts/Makefile                    |   1 +
>  arch/arm/dts/mt7623.dtsi                 | 255 +++++++++++++++++++
>  arch/arm/dts/mt7623n-bananapi-bpi-r2.dts | 207 ++++++++++++++++
>  include/dt-bindings/clock/mt7623-clk.h   | 413 +++++++++++++++++++++++++++++++
>  include/dt-bindings/power/mt7623-power.h |  19 ++
>  5 files changed, 895 insertions(+)
>  create mode 100644 arch/arm/dts/mt7623.dtsi
>  create mode 100644 arch/arm/dts/mt7623n-bananapi-bpi-r2.dts
>  create mode 100644 include/dt-bindings/clock/mt7623-clk.h
>  create mode 100644 include/dt-bindings/power/mt7623-power.h

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

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

* [U-Boot] [PATCH v2 04/18] arm: MediaTek: add basic support for MT7629 boards
  2018-10-12  7:00 ` [U-Boot] [PATCH v2 04/18] arm: MediaTek: add basic support for MT7629 boards Ryder Lee
@ 2018-10-25  3:29   ` Simon Glass
  2018-10-25  6:44     ` Ryder Lee
  0 siblings, 1 reply; 57+ messages in thread
From: Simon Glass @ 2018-10-25  3:29 UTC (permalink / raw)
  To: u-boot

Hi Ryder,

On 12 October 2018 at 01:00, Ryder Lee <ryder.lee@mediatek.com> wrote:
> This adds a general board file based on MT7629 SoCs from MediaTek.
>
> Apart from the generic parts (cpu) we add some low level init codes
> and initialize the early clocks.
>
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
> ---
>  arch/arm/Kconfig                              |  14 +++
>  arch/arm/Makefile                             |   1 +
>  arch/arm/include/asm/arch-mediatek/misc.h     |  17 ++++
>  arch/arm/mach-mediatek/Kconfig                |  24 +++++
>  arch/arm/mach-mediatek/Makefile               |   6 ++
>  arch/arm/mach-mediatek/cpu.c                  |  34 +++++++
>  arch/arm/mach-mediatek/init.h                 |  11 +++
>  arch/arm/mach-mediatek/mt7629/Makefile        |   4 +
>  arch/arm/mach-mediatek/mt7629/init.c          | 131 ++++++++++++++++++++++++++
>  arch/arm/mach-mediatek/mt7629/lowlevel_init.S |  50 ++++++++++
>  arch/arm/mach-mediatek/spl.c                  |  43 +++++++++
>  board/mediatek/mt7629/Kconfig                 |  17 ++++
>  board/mediatek/mt7629/MAINTAINERS             |   7 ++
>  board/mediatek/mt7629/Makefile                |   3 +
>  board/mediatek/mt7629/mt7629_rfb.c            |  16 ++++
>  configs/mt7629_rfb_defconfig                  |  73 ++++++++++++++
>  include/configs/mt7629.h                      |  62 ++++++++++++
>  17 files changed, 513 insertions(+)
>  create mode 100644 arch/arm/include/asm/arch-mediatek/misc.h
>  create mode 100644 arch/arm/mach-mediatek/Kconfig
>  create mode 100644 arch/arm/mach-mediatek/Makefile
>  create mode 100644 arch/arm/mach-mediatek/cpu.c
>  create mode 100644 arch/arm/mach-mediatek/init.h
>  create mode 100644 arch/arm/mach-mediatek/mt7629/Makefile
>  create mode 100644 arch/arm/mach-mediatek/mt7629/init.c
>  create mode 100644 arch/arm/mach-mediatek/mt7629/lowlevel_init.S
>  create mode 100644 arch/arm/mach-mediatek/spl.c
>  create mode 100644 board/mediatek/mt7629/Kconfig
>  create mode 100644 board/mediatek/mt7629/MAINTAINERS
>  create mode 100644 board/mediatek/mt7629/Makefile
>  create mode 100644 board/mediatek/mt7629/mt7629_rfb.c
>  create mode 100644 configs/mt7629_rfb_defconfig
>  create mode 100644 include/configs/mt7629.h

Looks good. A few nits below

>
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index ccf2a84..eac03f0 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -668,6 +668,18 @@ config ARCH_MESON
>           targeted at media players and tablet computers. We currently
>           support the S905 (GXBaby) 64-bit SoC.
>
> +config ARCH_MEDIATEK
> +       bool "MediaTek SoCs"
> +       select DM
> +       select OF_CONTROL
> +       select SPL_DM if SPL
> +       select SPL_LIBCOMMON_SUPPORT if SPL
> +       select SPL_LIBGENERIC_SUPPORT if SPL
> +       select SPL_OF_CONTROL if SPL
> +       select SUPPORT_SPL
> +       help
> +         Support for the MediaTek SoCs family.

Please add more info. What type of SoCs are these? What are the
capabilities? Link to web site? datasheets? wiki? Or maybe point to a
doc/README.mediatek?

> +
>  config ARCH_MX8M
>         bool "NXP i.MX8M platform"
>         select ARM64
> @@ -1423,6 +1435,8 @@ source "arch/arm/mach-rmobile/Kconfig"
>
>  source "arch/arm/mach-meson/Kconfig"
>
> +source "arch/arm/mach-mediatek/Kconfig"
> +
>  source "arch/arm/mach-qemu/Kconfig"
>
>  source "arch/arm/mach-rockchip/Kconfig"
> diff --git a/arch/arm/Makefile b/arch/arm/Makefile
> index 8f50560..ddb9618 100644
> --- a/arch/arm/Makefile
> +++ b/arch/arm/Makefile
> @@ -62,6 +62,7 @@ machine-$(CONFIG_ARCH_K3)             += k3
>  machine-$(CONFIG_ARCH_KEYSTONE)                += keystone
>  # TODO: rename CONFIG_KIRKWOOD -> CONFIG_ARCH_KIRKWOOD
>  machine-$(CONFIG_KIRKWOOD)             += kirkwood
> +machine-$(CONFIG_ARCH_MEDIATEK)                += mediatek
>  machine-$(CONFIG_ARCH_MESON)           += meson
>  machine-$(CONFIG_ARCH_MVEBU)           += mvebu
>  # TODO: rename CONFIG_TEGRA -> CONFIG_ARCH_TEGRA
> diff --git a/arch/arm/include/asm/arch-mediatek/misc.h b/arch/arm/include/asm/arch-mediatek/misc.h
> new file mode 100644
> index 0000000..2530e78
> --- /dev/null
> +++ b/arch/arm/include/asm/arch-mediatek/misc.h
> @@ -0,0 +1,17 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (C) 2018 MediaTek Inc.
> + */
> +
> +#ifndef __MEDIATEK_MISC_H_
> +#define __MEDIATEK_MISC_H_
> +
> +#define VER_BASE               0x08000000
> +#define VER_SIZE               0x10
> +
> +#define APHW_CODE              0x00
> +#define APHW_SUBCODE           0x04
> +#define APHW_VER               0x08
> +#define APSW_VER               0x0c
> +
> +#endif /* __MEDIATEK_MISC_H_ */
> diff --git a/arch/arm/mach-mediatek/Kconfig b/arch/arm/mach-mediatek/Kconfig
> new file mode 100644
> index 0000000..a932e70
> --- /dev/null
> +++ b/arch/arm/mach-mediatek/Kconfig
> @@ -0,0 +1,24 @@
> +if ARCH_MEDIATEK
> +
> +config SYS_SOC
> +       default "mediatek"
> +
> +config SYS_VENDOR
> +       default "mediatek"
> +
> +choice
> +       prompt "MediaTek board select"
> +
> +config TARGET_MT7629
> +       bool "MediaTek MT7629 SoC"
> +       select CPU_V7A
> +       select SPL
> +       select ARCH_MISC_INIT
> +       help
> +               Support MediaTek MT7629 SoC.

Please describe the features of this SoC.

> +
> +endchoice
> +
> +source "board/mediatek/mt7629/Kconfig"
> +
> +endif
> diff --git a/arch/arm/mach-mediatek/Makefile b/arch/arm/mach-mediatek/Makefile
> new file mode 100644
> index 0000000..852d330
> --- /dev/null
> +++ b/arch/arm/mach-mediatek/Makefile
> @@ -0,0 +1,6 @@
> +# SPDX-License-Identifier:     GPL-2.0
> +
> +obj-y  += cpu.o
> +obj-$(CONFIG_SPL_BUILD)        += spl.o
> +
> +obj-$(CONFIG_TARGET_MT7629) += mt7629/
> diff --git a/arch/arm/mach-mediatek/cpu.c b/arch/arm/mach-mediatek/cpu.c
> new file mode 100644
> index 0000000..2bfeab7
> --- /dev/null
> +++ b/arch/arm/mach-mediatek/cpu.c
> @@ -0,0 +1,34 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2018 MediaTek Inc.
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <dm/uclass-internal.h>
> +#include <wdt.h>

dm/ goes after wdt.h

https://www.denx.de/wiki/U-Boot/CodingStyle

> +
> +int arch_misc_init(void)
> +{
> +       struct udevice *wdt;
> +       int ret;
> +
> +       ret = uclass_get_device(UCLASS_WDT, 0, &wdt);
> +       if (!ret)
> +               wdt_stop(wdt);
> +
> +       return 0;
> +}
> +
> +int arch_cpu_init(void)
> +{
> +       icache_enable();
> +
> +       return 0;
> +}
> +
> +void enable_caches(void)
> +{
> +       /* Enable D-cache. I-cache is already enabled in start.S */
> +       dcache_enable();
> +}
> diff --git a/arch/arm/mach-mediatek/init.h b/arch/arm/mach-mediatek/init.h
> new file mode 100644
> index 0000000..1d896fb
> --- /dev/null
> +++ b/arch/arm/mach-mediatek/init.h
> @@ -0,0 +1,11 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (C) 2018 MediaTek Inc.
> + */
> +
> +#ifndef __MEDIATEK_INIT_H_
> +#define __MEDIATEK_INIT_H_
> +
> +extern int mtk_soc_early_init(void);
> +
> +#endif /* __MEDIATEK_INIT_H_ */
> diff --git a/arch/arm/mach-mediatek/mt7629/Makefile b/arch/arm/mach-mediatek/mt7629/Makefile
> new file mode 100644
> index 0000000..007eb4a
> --- /dev/null
> +++ b/arch/arm/mach-mediatek/mt7629/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/mt7629/init.c b/arch/arm/mach-mediatek/mt7629/init.c
> new file mode 100644
> index 0000000..8f195b5
> --- /dev/null
> +++ b/arch/arm/mach-mediatek/mt7629/init.c
> @@ -0,0 +1,131 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2018 MediaTek Inc.
> + * Author: Ryder Lee <ryder.lee@mediatek.com>
> + */
> +
> +#include <clk.h>
> +#include <common.h>
> +#include <dm.h>
> +#include <dm/uclass.h>
> +#include <fdtdec.h>
> +#include <linux/io.h>
> +#include <ram.h>
> +#include <asm/arch/misc.h>
> +#include <asm/sections.h>

fix ordering

> +
> +#include <dt-bindings/clock/mt7629-clk.h>
> +
> +#define L2_SHARE_CFG_MP0       0x7f0
> +#define L2_SHARE_MODE_OFF      BIT(8)
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +int mtk_pll_early_init(void)
> +{
> +       unsigned long pll_rates[] = {
> +               [CLK_APMIXED_ARMPLL] = 1250000000,
> +               [CLK_APMIXED_MAINPLL] = 1120000000,
> +               [CLK_APMIXED_UNIV2PLL] = 1200000000,
> +               [CLK_APMIXED_ETH1PLL] = 500000000,
> +               [CLK_APMIXED_ETH2PLL] = 700000000,
> +               [CLK_APMIXED_SGMIPLL] = 650000000,
> +       };
> +       struct udevice *dev;
> +       int ret, i;
> +
> +       ret = uclass_get_device_by_driver(UCLASS_CLK,
> +                       DM_GET_DRIVER(mtk_clk_apmixedsys), &dev);
> +       if (ret)
> +               return ret;
> +
> +       /* configure default rate then enable apmixedsys */
> +       for (i = 0; i < ARRAY_SIZE(pll_rates); i++) {
> +               struct clk clk = { .id = i, .dev = dev };
> +
> +               ret = clk_set_rate(&clk, pll_rates[i]);
> +               if (ret)
> +                       return ret;
> +
> +               ret = clk_enable(&clk);
> +               if (ret)
> +                       return ret;
> +       }
> +
> +       /* setup mcu bus */
> +       ret = uclass_get_device_by_driver(UCLASS_SYSCON,
> +                       DM_GET_DRIVER(mtk_mcucfg), &dev);
> +       if (ret)
> +               return ret;
> +
> +       return 0;
> +}
> +
> +int mtk_soc_early_init(void)
> +{
> +       struct udevice *dev;
> +       int ret;
> +
> +       /* initialize early clocks */
> +       ret = mtk_pll_early_init();
> +       if (ret)
> +               return ret;
> +
> +       ret = uclass_get_device(UCLASS_RAM, 0, &dev);

Consider uclass_first_device_err(). Same elsewhere.

> +       if (ret)
> +               return ret;
> +
> +       return 0;
> +}
> +
> +int mach_cpu_init(void)
> +{
> +       void __iomem *base;
> +       int node;
> +
> +       node = fdt_node_offset_by_compatible(gd->fdt_blob, -1,
> +                       "mediatek,mt7629-mcucfg");

Add a driver fopr this - don't access it directly. This could be a
syscon device perhaps?

> +       base = (void __iomem *)fdtdec_get_addr(gd->fdt_blob, node, "reg");

dev_read_addr(). Please use the live tree functions.

> +       if (!base)
> +               return -ENOENT;
> +
> +       /* disable L2C shared mode */
> +       writel(L2_SHARE_MODE_OFF, base + L2_SHARE_CFG_MP0);
> +
> +       return 0;
> +}
> +
> +int dram_init(void)
> +{
> +       struct ram_info ram;
> +       struct udevice *dev;
> +       int ret;
> +
> +       ret = uclass_get_device(UCLASS_RAM, 0, &dev);
> +       if (ret)
> +               return ret;
> +
> +       ret = ram_get_info(dev, &ram);
> +       if (ret)
> +               return ret;
> +
> +       debug("RAM init base=%lx, size=%x\n", ram.base, ram.size);
> +
> +       gd->ram_size = ram.size;
> +
> +       return 0;
> +}
> +
> +int print_cpuinfo(void)
> +{
> +       void __iomem *chipid;
> +       u32 hwcode, swver;
> +
> +       chipid = ioremap(VER_BASE, VER_SIZE);
> +       hwcode = readl(chipid + APHW_CODE);
> +       swver = readl(chipid + APSW_VER);
> +
> +       printf("CPU:   MediaTek MT%04x E%d\n", hwcode, (swver & 0xf) + 1);
> +
> +       return 0;
> +}

[..]

> new file mode 100644
> index 0000000..83ccbba
> --- /dev/null
> +++ b/board/mediatek/mt7629/Makefile
> @@ -0,0 +1,3 @@
> +# SPDX-License-Identifier:     GPL-2.0
> +
> +obj-y += mt7629_rfb.o
> diff --git a/board/mediatek/mt7629/mt7629_rfb.c b/board/mediatek/mt7629/mt7629_rfb.c
> new file mode 100644
> index 0000000..08468b5
> --- /dev/null
> +++ b/board/mediatek/mt7629/mt7629_rfb.c
> @@ -0,0 +1,16 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2018 MediaTek Inc.
> + */
> +
> +#include <common.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +int board_init(void)
> +{
> +       /* address of boot parameters */
> +       gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;

Do we need these?

> +
> +       return 0;
> +}

[..]

> diff --git a/include/configs/mt7629.h b/include/configs/mt7629.h
> new file mode 100644
> index 0000000..9b51e90
> --- /dev/null
> +++ b/include/configs/mt7629.h
> @@ -0,0 +1,62 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Configuration for MediaTek MT7629 SoC
> + *
> + * Copyright (C) 2018 MediaTek Inc.
> + * Author: Ryder Lee <ryder.lee@mediatek.com>
> + */
> +
> +#ifndef __MT7629_H
> +#define __MT7629_H
> +
> +#include <linux/sizes.h>
> +
> +/* Miscellaneous configurable options */
> +#define CONFIG_SETUP_MEMORY_TAGS
> +#define CONFIG_INITRD_TAG
> +#define CONFIG_CMDLINE_TAG
> +
> +#define CONFIG_SYS_MAXARGS             8
> +#define CONFIG_SYS_BOOTM_LEN           SZ_64M
> +#define CONFIG_SYS_CBSIZE              SZ_1K
> +#define CONFIG_SYS_PBSIZE              (CONFIG_SYS_CBSIZE +    \
> +                                       sizeof(CONFIG_SYS_PROMPT) + 16)
> +
> +/* Size of malloc() pool */
> +#define CONFIG_SYS_MALLOC_LEN          SZ_4M
> +
> +/* Environment */
> +#define CONFIG_ENV_SIZE                        SZ_4K
> +/* Allow to overwrite serial and ethaddr */
> +#define CONFIG_ENV_OVERWRITE
> +
> +/* Defines for SPL */
> +#define CONFIG_SPL_STACK               0x106000
> +#define CONFIG_SPL_TEXT_BASE           0x201000
> +#define CONFIG_SPL_MAX_SIZE            SZ_64K
> +#define CONFIG_SPL_MAX_FOOTPRINT       SZ_64K
> +#define CONFIG_SPL_PAD_TO              0x10000
> +
> +#define CONFIG_SPI_ADDR                        0x30000000
> +#define CONFIG_SYS_SPI_U_BOOT_OFFS     CONFIG_SPL_PAD_TO
> +#define CONFIG_SYS_UBOOT_BASE          (CONFIG_SPI_ADDR + CONFIG_SPL_PAD_TO)
> +
> +/* SPL -> Uboot */
> +#define CONFIG_SYS_UBOOT_START         CONFIG_SYS_TEXT_BASE
> +#define CONFIG_SYS_INIT_SP_ADDR                (CONFIG_SYS_TEXT_BASE + SZ_2M - \
> +                                        GENERATED_GBL_DATA_SIZE)
> +
> +/* UBoot -> Kernel */
> +#define CONFIG_SYS_SPL_ARGS_ADDR       0x40000000
> +#define CONFIG_LOADADDR                        0x42007f1c
> +#define CONFIG_SYS_LOAD_ADDR           CONFIG_LOADADDR
> +
> +/* Serial device */
> +#define CONFIG_SYS_NS16550_CLK         40000000
> +#define CONFIG_SYS_NS16550_MEM32

Can you use the device tree for this?

> +#define CONFIG_BAUDRATE                        115200
> +
> +/* DRAM */
> +#define CONFIG_SYS_SDRAM_BASE          0x40000000
> +
> +#endif
> --
> 1.9.1
>

Regards,
Simon

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

* [U-Boot] [PATCH v2 05/18] arm: MediaTek: add basic support for MT7623 boards
  2018-10-12  7:00 ` [U-Boot] [PATCH v2 05/18] arm: MediaTek: add basic support for MT7623 boards Ryder Lee
@ 2018-10-25  3:29   ` Simon Glass
  2018-10-25  6:40     ` Ryder Lee
  0 siblings, 1 reply; 57+ messages in thread
From: Simon Glass @ 2018-10-25  3:29 UTC (permalink / raw)
  To: u-boot

Hi,

On 12 October 2018 at 01:00, Ryder Lee <ryder.lee@mediatek.com> wrote:
> From: Weijie Gao <weijie.gao@mediatek.com>
>
> This adds a general board file based on MT7623 SoCs from MediaTek.
>
> As this u-boot is loaded by preloader, there is no low level
> initializtion codes.
>
> Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> Tested-by: Matthias Brugger <matthias.bgg@gmail.com>
> ---
>  arch/arm/mach-mediatek/Kconfig                |  8 +++
>  arch/arm/mach-mediatek/Makefile               |  1 +
>  arch/arm/mach-mediatek/mt7623/Makefile        |  4 ++
>  arch/arm/mach-mediatek/mt7623/init.c          | 54 +++++++++++++++
>  arch/arm/mach-mediatek/mt7623/lowlevel_init.S | 22 ++++++
>  arch/arm/mach-mediatek/mt7623/preloader.h     | 99 +++++++++++++++++++++++++++
>  board/mediatek/mt7623/Kconfig                 | 13 ++++
>  board/mediatek/mt7623/MAINTAINERS             |  7 ++
>  board/mediatek/mt7623/Makefile                |  3 +
>  board/mediatek/mt7623/mt7623_rfb.c            | 16 +++++
>  configs/mt7623n_bpir2_defconfig               | 53 ++++++++++++++
>  include/configs/mt7623.h                      | 61 +++++++++++++++++
>  12 files changed, 341 insertions(+)
>  create mode 100644 arch/arm/mach-mediatek/mt7623/Makefile
>  create mode 100644 arch/arm/mach-mediatek/mt7623/init.c
>  create mode 100644 arch/arm/mach-mediatek/mt7623/lowlevel_init.S
>  create mode 100644 arch/arm/mach-mediatek/mt7623/preloader.h
>  create mode 100644 board/mediatek/mt7623/Kconfig
>  create mode 100644 board/mediatek/mt7623/MAINTAINERS
>  create mode 100644 board/mediatek/mt7623/Makefile
>  create mode 100644 board/mediatek/mt7623/mt7623_rfb.c
>  create mode 100644 configs/mt7623n_bpir2_defconfig
>  create mode 100644 include/configs/mt7623.h
>

There is a new SPL handoff and bloblist feature that I hope will land
in the next release. Can you please look at using this instead of an
SoC-specififc mechanism?

See u-boot-dm/spl-working

Regards,
Simon

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

* [U-Boot] [PATCH v2 06/18] clk: MediaTek: add clock driver for MT7629 SoC.
  2018-10-12  7:00 ` [U-Boot] [PATCH v2 06/18] clk: MediaTek: add clock driver for MT7629 SoC Ryder Lee
@ 2018-10-25  3:29   ` Simon Glass
  2018-10-25  6:37     ` Ryder Lee
  0 siblings, 1 reply; 57+ messages in thread
From: Simon Glass @ 2018-10-25  3:29 UTC (permalink / raw)
  To: u-boot

Hi Ryder,

On 12 October 2018 at 01:00, Ryder Lee <ryder.lee@mediatek.com> wrote:
> This patch adds clock modules for MediaTek SoCs:
> - Shared part: a common driver which contains the general operations
> for plls, muxes, dividers and gates so that we can reuse it in future.
>
> - Specific SoC part: the group of structures used to hold the hardware
> configuration for each SoC.
>
> We take MT7629 as an example to demonstrate how to implement driver if
> any other MediaTek chips would like to use it.
>
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> ---
>  drivers/clk/Makefile              |   1 +
>  drivers/clk/mediatek/Makefile     |   6 +
>  drivers/clk/mediatek/clk-mt7629.c | 709 ++++++++++++++++++++++++++++++++++++++
>  drivers/clk/mediatek/clk-mtk.c    | 492 ++++++++++++++++++++++++++
>  drivers/clk/mediatek/clk-mtk.h    | 153 ++++++++
>  5 files changed, 1361 insertions(+)
>  create mode 100644 drivers/clk/mediatek/Makefile
>  create mode 100644 drivers/clk/mediatek/clk-mt7629.c
>  create mode 100644 drivers/clk/mediatek/clk-mtk.c
>  create mode 100644 drivers/clk/mediatek/clk-mtk.h

Looks good except for a few things below.

[..]

> +const struct clk_ops mtk_clk_gate_ops = {
> +       .enable = mtk_clk_gate_enable,
> +       .disable = mtk_clk_gate_disable,
> +       .get_rate = mtk_clk_gate_get_rate,
> +};
> +
> +int mtk_clk_init(struct udevice *dev, const struct mtk_clk_tree *tree)
> +{
> +       struct mtk_clk_priv *priv = dev_get_priv(dev);
> +
> +       priv->base = dev_read_addr_ptr(dev);
> +       if (!priv->base)
> +               return -ENOENT;

Why do you export these two functions? Devices should be probed in the
normal DM way.

> +
> +       priv->tree = tree;
> +
> +       return 0;
> +}
> +
> +int mtk_clk_gate_init(struct udevice *dev,
> +                     const struct mtk_clk_tree *tree,
> +                     const struct mtk_gate *gates)
> +{
> +       struct mtk_cg_priv *priv = dev_get_priv(dev);
> +
> +       priv->base = dev_read_addr_ptr(dev);
> +       if (!priv->base)
> +               return -ENOENT;
> +
> +       priv->tree = tree;
> +       priv->gates = gates;
> +
> +       return 0;
> +}

[...]

Regards,
Simon

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

* [U-Boot] [PATCH v2 07/18] clk: MediaTek: add clock driver for MT7623 SoC.
  2018-10-12  7:00 ` [U-Boot] [PATCH v2 07/18] clk: MediaTek: add clock driver for MT7623 SoC Ryder Lee
@ 2018-10-25  3:29   ` Simon Glass
  0 siblings, 0 replies; 57+ messages in thread
From: Simon Glass @ 2018-10-25  3:29 UTC (permalink / raw)
  To: u-boot

On 12 October 2018 at 01:00, Ryder Lee <ryder.lee@mediatek.com> wrote:
> This patch adds a driver for MT7623 clock blocks.
>
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> Tested-by: Matthias Brugger <matthias.bgg@gmail.com>
> ---
>  drivers/clk/mediatek/Makefile     |   1 +
>  drivers/clk/mediatek/clk-mt7623.c | 870 ++++++++++++++++++++++++++++++++++++++
>  2 files changed, 871 insertions(+)
>  create mode 100644 drivers/clk/mediatek/clk-mt7623.c

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

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

* [U-Boot] [PATCH v2 08/18] timer: MediaTek: add timer driver for MediaTek SoCs
  2018-10-12  7:00 ` [U-Boot] [PATCH v2 08/18] timer: MediaTek: add timer driver for MediaTek SoCs Ryder Lee
@ 2018-10-25  3:29   ` Simon Glass
  0 siblings, 0 replies; 57+ messages in thread
From: Simon Glass @ 2018-10-25  3:29 UTC (permalink / raw)
  To: u-boot

On 12 October 2018 at 01:00, Ryder Lee <ryder.lee@mediatek.com> wrote:
> This patch adds clock source and clock event for the timer found
> on the Mediatek SoCs.
>
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> Tested-by: Matthias Brugger <matthias.bgg@gmail.com>
> ---
>  drivers/timer/Kconfig     |  7 ++++
>  drivers/timer/Makefile    |  1 +
>  drivers/timer/mtk_timer.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 93 insertions(+)
>  create mode 100644 drivers/timer/mtk_timer.c

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

Consider supporting the early timer too so you can use bootstage.

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

* [U-Boot] [PATCH v2 01/18] tools: MediaTek: add MTK boot header generation to mkimage
  2018-10-12  7:00 ` [U-Boot] [PATCH v2 01/18] tools: MediaTek: add MTK boot header generation to mkimage Ryder Lee
@ 2018-10-25  3:29   ` Simon Glass
  2018-10-25 13:11     ` Ryder Lee
  0 siblings, 1 reply; 57+ messages in thread
From: Simon Glass @ 2018-10-25  3:29 UTC (permalink / raw)
  To: u-boot

Hi Ryder,

On 12 October 2018 at 01:00, Ryder Lee <ryder.lee@mediatek.com> wrote:
> This patch adds support for MTK boot image generation.
>
> Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> ---
>  Makefile             |  22 ++
>  common/image.c       |   1 +
>  include/image.h      |   1 +
>  scripts/Makefile.spl |  11 +
>  tools/Makefile       |   1 +
>  tools/mtkimage.c     | 749 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  tools/mtkimage.h     | 199 ++++++++++++++
>  7 files changed, 984 insertions(+)
>  create mode 100644 tools/mtkimage.c
>  create mode 100644 tools/mtkimage.h

The mkimage stuff looks fine.

But can you use binman for the pad/cat part of this? See for example
sunxi. - sunxi-u-boot.dtsi

Also mtkimage.c is too close to mkimage.c - how about mtk_image.c ?

Regards,
Simon

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

* [U-Boot] [PATCH v2 10/18] pinctrl: MediaTek: add pinctrl driver for MT7629 SoC
  2018-10-12  7:00 ` [U-Boot] [PATCH v2 10/18] pinctrl: MediaTek: add pinctrl driver for MT7629 SoC Ryder Lee
@ 2018-10-25  3:29   ` Simon Glass
  2018-10-25  6:08     ` Ryder Lee
  0 siblings, 1 reply; 57+ messages in thread
From: Simon Glass @ 2018-10-25  3:29 UTC (permalink / raw)
  To: u-boot

Hi Ryder,

On 12 October 2018 at 01:00, Ryder Lee <ryder.lee@mediatek.com> wrote:
> This patch adds pinctrl support for MT7629 SoC. The IO core found on
> the SoC has the registers for pinctrl, pinconf and gpio mixed up in
> the same register range.  Hence the driver also implements the gpio
> functionality through UCLASS_GPIO.
>
> This also creates a common file as there might be other chips that use
> the same binding and driver, then being a little more abstract could
> help in the long run.
>
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> ---
>  arch/arm/include/asm/arch-mediatek/gpio.h     |   9 +
>  drivers/pinctrl/Kconfig                       |   1 +
>  drivers/pinctrl/Makefile                      |   1 +
>  drivers/pinctrl/mediatek/Kconfig              |  11 +
>  drivers/pinctrl/mediatek/Makefile             |   6 +
>  drivers/pinctrl/mediatek/pinctrl-mt7629.c     | 488 +++++++++++++++++++++++
>  drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 552 ++++++++++++++++++++++++++
>  drivers/pinctrl/mediatek/pinctrl-mtk-common.h | 182 +++++++++
>  8 files changed, 1250 insertions(+)
>  create mode 100644 arch/arm/include/asm/arch-mediatek/gpio.h
>  create mode 100644 drivers/pinctrl/mediatek/Kconfig
>  create mode 100644 drivers/pinctrl/mediatek/Makefile
>  create mode 100644 drivers/pinctrl/mediatek/pinctrl-mt7629.c
>  create mode 100644 drivers/pinctrl/mediatek/pinctrl-mtk-common.c
>  create mode 100644 drivers/pinctrl/mediatek/pinctrl-mtk-common.h
>

[..]

> +int mtk_pinctrl_probe(struct udevice *dev, struct mtk_pinctrl_soc *soc)
> +{
> +       struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
> +       int ret;
> +
> +       priv->base = dev_read_addr_ptr(dev);
> +       if (priv->base == (void *)FDT_ADDR_T_NONE)
> +               return -EINVAL;
> +
> +       priv->soc = soc;
> +
> +       ret = mtk_gpiochip_register(dev);
> +       if (ret)
> +               return ret;
> +
> +       return 0;
> +}

How come this function is exported? It should be probed like any other driver.

Regards,
Simon

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

* [U-Boot] [PATCH v2 11/18] pinctrl: MediaTek: add pinctrl driver for MT7623 SoC
  2018-10-12  7:01 ` [U-Boot] [PATCH v2 11/18] pinctrl: MediaTek: add pinctrl driver for MT7623 SoC Ryder Lee
@ 2018-10-25  3:29   ` Simon Glass
  2018-10-25  6:13     ` Ryder Lee
  0 siblings, 1 reply; 57+ messages in thread
From: Simon Glass @ 2018-10-25  3:29 UTC (permalink / raw)
  To: u-boot

Hi Ryder,

On 12 October 2018 at 01:01, Ryder Lee <ryder.lee@mediatek.com> wrote:
> This patch adds pinctrl support for MT7623 SoC. And most of the
> structures are used to hold the hardware configuration for each
> pin.
>
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> Tested-by: Matthias Brugger <matthias.bgg@gmail.com>
> ---
>  drivers/pinctrl/mediatek/Kconfig              |    4 +
>  drivers/pinctrl/mediatek/Makefile             |    1 +
>  drivers/pinctrl/mediatek/pinctrl-mt7623.c     | 1284 +++++++++++++++++++++++++
>  drivers/pinctrl/mediatek/pinctrl-mtk-common.h |    1 +
>  4 files changed, 1290 insertions(+)
>  create mode 100644 drivers/pinctrl/mediatek/pinctrl-mt7623.c

[..]

> +void mtk_rmw(struct udevice *dev, u32 reg, u32 mask, u32 set);

What is this for? It has no comment and is an exported function. We
should not export things from drivers unless there is a good reason.

Regards,
Simon

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

* [U-Boot] [PATCH v2 12/18] power domain: MediaTek: add power domain driver for MT7629 SoC
  2018-10-12  7:01 ` [U-Boot] [PATCH v2 12/18] power domain: MediaTek: add power domain driver for MT7629 SoC Ryder Lee
@ 2018-10-25  3:29   ` Simon Glass
  0 siblings, 0 replies; 57+ messages in thread
From: Simon Glass @ 2018-10-25  3:29 UTC (permalink / raw)
  To: u-boot

On 12 October 2018 at 01:01, Ryder Lee <ryder.lee@mediatek.com> wrote:
> This adds a power domain driver for the Mediatek SCPSYS unit.
>
> The System Control Processor System (SCPSYS) has several power
> management related tasks in the system. The tasks include thermal
> measurement, dynamic voltage frequency scaling (DVFS), interrupt
> filter and lowlevel sleep control. The System Power Manager (SPM)
> inside the SCPSYS is for the MTCMOS power domain control.
>
> For now this driver only adds power domain support.
>
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> ---
>  drivers/power/domain/Kconfig            |   7 +
>  drivers/power/domain/Makefile           |   1 +
>  drivers/power/domain/mtk-power-domain.c | 326 ++++++++++++++++++++++++++++++++
>  3 files changed, 334 insertions(+)
>  create mode 100644 drivers/power/domain/mtk-power-domain.c

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

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

* [U-Boot] [PATCH v2 13/18] power domain: MediaTek: add power domain driver for MT7623 SoC
  2018-10-12  7:01 ` [U-Boot] [PATCH v2 13/18] power domain: MediaTek: add power domain driver for MT7623 SoC Ryder Lee
@ 2018-10-25  3:30   ` Simon Glass
  0 siblings, 0 replies; 57+ messages in thread
From: Simon Glass @ 2018-10-25  3:30 UTC (permalink / raw)
  To: u-boot

On 12 October 2018 at 01:01, Ryder Lee <ryder.lee@mediatek.com> wrote:
> This adds power domain (scpsys) support for MT7623 SoC.
>
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> ---
>  drivers/power/domain/mtk-power-domain.c | 80 +++++++++++++++++++++++++++++++++
>  1 file changed, 80 insertions(+)

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

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

* [U-Boot] [PATCH v2 14/18] serial: 16550: allow the driver to support MediaTek serial
  2018-10-12  7:01 ` [U-Boot] [PATCH v2 14/18] serial: 16550: allow the driver to support MediaTek serial Ryder Lee
@ 2018-10-25  3:30   ` Simon Glass
  0 siblings, 0 replies; 57+ messages in thread
From: Simon Glass @ 2018-10-25  3:30 UTC (permalink / raw)
  To: u-boot

On 12 October 2018 at 01:01, Ryder Lee <ryder.lee@mediatek.com> wrote:
> This patch adds an extra operation in ns16550.c to suuport MediaTek
> SoCs as we have a highspeed register which influences the calcualtion
> of the divisor.
>
> Note that we don't support the baudrate greater than 115200 currently.
>
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> Tested-by: Matthias Brugger <matthias.bgg@gmail.com>
> ---
>  drivers/serial/ns16550.c | 10 ++++++++++
>  1 file changed, 10 insertions(+)
>

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

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

* [U-Boot] [PATCH v2 15/18] ram: MediaTek: add DDR3 driver for MT7629 SoC
  2018-10-12  7:01 ` [U-Boot] [PATCH v2 15/18] ram: MediaTek: add DDR3 driver for MT7629 SoC Ryder Lee
@ 2018-10-25  3:30   ` Simon Glass
  2018-10-25  9:38     ` Ryder Lee
  0 siblings, 1 reply; 57+ messages in thread
From: Simon Glass @ 2018-10-25  3:30 UTC (permalink / raw)
  To: u-boot

On 12 October 2018 at 01:01, Ryder Lee <ryder.lee@mediatek.com> wrote:
> This patch adds a DDR3 driver for MT7629 SoC.
>
> Signed-off-by: Wu Zou <wu.zou@mediatek.com>
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> ---
>  drivers/ram/Makefile               |   1 +
>  drivers/ram/mediatek/Makefile      |   7 +
>  drivers/ram/mediatek/ddr3-mt7629.c | 766 +++++++++++++++++++++++++++++++++++++
>  3 files changed, 774 insertions(+)
>  create mode 100644 drivers/ram/mediatek/Makefile
>  create mode 100644 drivers/ram/mediatek/ddr3-mt7629.c

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

Thoughts below.

[..]

> +#define DDRPHY_PLL1                    0x0000
> +#define DDRPHY_PLL2                    0x0004

Why not use a C struct for these registers?

[..]

> +       writel(0x400, priv->dramc_ao + DRAMC_MRS);
> +       writel(0x1d7000, priv->dramc_ao + DRAMC_MRS);
> +       writel(0x1, priv->dramc_ao + DRAMC_SPCMD);
> +       writel(0x0, priv->dramc_ao + DRAMC_SPCMD);
> +       udelay(100);

Are these delays specified in a datasheet? Why did you chose 100?
Perhaps add an enum for this value? Is there a way to check for when
the hardware is ready, e.g. by reading a registers in a loop?

[..]

> +static int mtk_ddr3_probe(struct udevice *dev)
> +{
> +       struct mtk_ddr3_priv *priv = dev_get_priv(dev);
> +
> +       priv->emi = dev_read_addr_index(dev, 0);
> +       if (priv->emi == FDT_ADDR_T_NONE)
> +               return -EINVAL;
> +
> +       priv->ddrphy = dev_read_addr_index(dev, 1);
> +       if (priv->ddrphy == FDT_ADDR_T_NONE)
> +               return -EINVAL;
> +
> +       priv->dramc_ao = dev_read_addr_index(dev, 2);
> +       if (priv->dramc_ao == FDT_ADDR_T_NONE)
> +               return -EINVAL;
> +
> +#ifdef CONFIG_SPL_BUILD
> +       int ret;
> +
> +       ret = clk_get_by_index(dev, 0, &priv->phy);
> +       if (ret)
> +               return ret;
> +
> +       ret = clk_get_by_index(dev, 1, &priv->phy_mux);
> +       if (ret)
> +               return ret;
> +
> +       ret = clk_get_by_index(dev, 2, &priv->mem);
> +       if (ret)
> +               return ret;
> +
> +       ret = clk_get_by_index(dev, 3, &priv->mem_mux);
> +       if (ret)
> +               return ret;

Do you have phandles for these clocks? I only worry that it is a bit
brittle to have them numbered.

> +
> +       ret = mtk_ddr3_init(dev);
> +       if (ret)
> +               return ret;
> +#endif
> +       return 0;
> +}
> +

Regards,
Simon

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

* [U-Boot] [PATCH v2 16/18] mmc: mtk-sd: add SD/MMC host controller driver for MT7623 SoC
  2018-10-12  7:01 ` [U-Boot] [PATCH v2 16/18] mmc: mtk-sd: add SD/MMC host controller driver for MT7623 SoC Ryder Lee
@ 2018-10-25  3:30   ` Simon Glass
  0 siblings, 0 replies; 57+ messages in thread
From: Simon Glass @ 2018-10-25  3:30 UTC (permalink / raw)
  To: u-boot

Hi Ryder.

On 12 October 2018 at 01:01, Ryder Lee <ryder.lee@mediatek.com> wrote:
> From: Weijie Gao <weijie.gao@mediatek.com>
>
> This patch adds MT7623 host controller driver for accessing SD/MMC.
>
> Cc: Jaehoon Chung <jh80.chung@samsung.com>
> Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> Tested-by: Matthias Brugger <matthias.bgg@gmail.com>
> ---
>  drivers/mmc/Kconfig  |    9 +
>  drivers/mmc/Makefile |    1 +
>  drivers/mmc/mtk-sd.c | 1331 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 1341 insertions(+)
>  create mode 100644 drivers/mmc/mtk-sd.c

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

nits below

>
> diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
> index 0a0d4aa..ca13341 100644
> --- a/drivers/mmc/Kconfig
> +++ b/drivers/mmc/Kconfig
> @@ -598,6 +598,15 @@ config FTSDC010_SDIO
>         help
>                 This can enable ftsdc010 sdio function.
>
> +config MMC_MTK
> +       bool "MediaTek SD/MMC Card Interface support"
> +       default n

You should be able to omit this since it is the default.

> +       help
> +         This selects the MediaTek(R) Secure digital and Multimedia card Interface.
> +         If you have a machine with a integrated SD/MMC card reader, say Y or M here.
> +         This is needed if support for any SD/SDIO/MMC devices is required.
> +         If unsure, say N.
> +
>  endif
>
>  config TEGRA124_MMC_DISABLE_EXT_LOOPBACK
> diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
> index 23c5b0d..801a26d 100644
> --- a/drivers/mmc/Makefile
> +++ b/drivers/mmc/Makefile
> @@ -65,3 +65,4 @@ obj-$(CONFIG_MMC_SUNXI)                       += sunxi_mmc.o
>  obj-$(CONFIG_MMC_UNIPHIER)             += tmio-common.o uniphier-sd.o
>  obj-$(CONFIG_RENESAS_SDHI)             += tmio-common.o renesas-sdhi.o
>  obj-$(CONFIG_MMC_BCM2835)              += bcm2835_sdhost.o
> +obj-$(CONFIG_MMC_MTK)                  += mtk-sd.o
> diff --git a/drivers/mmc/mtk-sd.c b/drivers/mmc/mtk-sd.c
> new file mode 100644
> index 0000000..5027764
> --- /dev/null
> +++ b/drivers/mmc/mtk-sd.c
> @@ -0,0 +1,1331 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * MediaTek SD/MMC Card Interface driver
> + *
> + * Copyright (C) 2018 MediaTek Inc.
> + * Author: Weijie Gao <weijie.gao@mediatek.com>
> + */
> +
> +#include <clk.h>
> +#include <common.h>
> +#include <dm.h>
> +#include <dm/pinctrl.h>
> +#include <errno.h>
> +#include <stdbool.h>
> +#include <malloc.h>
> +#include <mmc.h>
> +#include <asm/gpio.h>
> +#include <linux/bitops.h>
> +#include <linux/io.h>
> +#include <linux/iopoll.h>

Please check include-file order on all these patches.

> +
> +#define MSDC_CFG                       0x0
> +#define   MSDC_CFG_HS400_CK_MODE_EXT   BIT(22)
> +#define   MSDC_CFG_CKMOD_EXT_M         0x03
> +#define   MSDC_CFG_CKMOD_EXT_S         20
> +#define   MSDC_CFG_CKDIV_EXT_M         0xfff
> +#define   MSDC_CFG_CKDIV_EXT_S         8
> +#define   MSDC_CFG_HS400_CK_MODE       BIT(18)
> +#define   MSDC_CFG_CKMOD_M             0x03
> +#define   MSDC_CFG_CKMOD_S             16
> +#define   MSDC_CFG_CKDIV_M             0xff
> +#define   MSDC_CFG_CKDIV_S             8

We mostly use shifted masks in U-Boot since they are easier to use:

+#define   MSDC_CFG_CKDIV_S             8
+#define   MSDC_CFG_CKDIV_M             (0xff << MSDC_CFG_CKDIV_S)

> +#define   MSDC_CFG_CKSTB               BIT(7)
> +#define   MSDC_CFG_PIO                 BIT(3)
> +#define   MSDC_CFG_RST                 BIT(2)
> +#define   MSDC_CFG_CKPDN               BIT(1)
> +#define   MSDC_CFG_MODE                        BIT(0)
> +
> +#define MSDC_IOCON                     0x04
> +#define   MSDC_IOCON_W_DSPL            BIT(8)
> +#define   MSDC_IOCON_DSPL              BIT(2)
> +#define   MSDC_IOCON_RSPL              BIT(1)
> +
> +#define MSDC_PS                                0x08
> +#define   MSDC_PS_DAT0                 BIT(16)
> +#define   MSDC_PS_CDEN                 BIT(0)
> +
> +#define MSDC_INT                       0x0c
> +#define MSDC_INTEN                     0x10
> +#define   MSDC_INT_ACMDRDY             BIT(3)
> +#define   MSDC_INT_ACMDTMO             BIT(4)
> +#define   MSDC_INT_ACMDCRCERR          BIT(5)
> +#define   MSDC_INT_CMDRDY              BIT(8)
> +#define   MSDC_INT_CMDTMO              BIT(9)
> +#define   MSDC_INT_RSPCRCERR           BIT(10)
> +#define   MSDC_INT_XFER_COMPL          BIT(12)
> +#define   MSDC_INT_DATTMO              BIT(14)
> +#define   MSDC_INT_DATCRCERR           BIT(15)
> +
> +#define MSDC_FIFOCS                    0x14
> +#define   MSDC_FIFOCS_CLR              BIT(31)
> +#define   MSDC_FIFOCS_TXCNT_M          0xff
> +#define   MSDC_FIFOCS_TXCNT_S          16
> +#define   MSDC_FIFOCS_RXCNT_M          0xff
> +#define   MSDC_FIFOCS_RXCNT_S          0
> +
> +#define MSDC_TXDATA                    0x18
> +#define MSDC_RXDATA                    0x1c
> +
> +#define SDC_CFG                                0x30
> +#define   SDC_CFG_DTOC_M               0xff
> +#define   SDC_CFG_DTOC_S               24
> +#define   SDC_CFG_SDIOIDE              BIT(20)
> +#define   SDC_CFG_SDIO                 BIT(19)
> +#define   SDC_CFG_BUSWIDTH_M           0x03
> +#define   SDC_CFG_BUSWIDTH_S           16
> +
> +#define SDC_CMD                                0x34
> +#define   SDC_CMD_BLK_LEN_M            0xfff
> +#define   SDC_CMD_BLK_LEN_S            16
> +#define   SDC_CMD_STOP                 BIT(14)
> +#define   SDC_CMD_WR                   BIT(13)
> +#define   SDC_CMD_DTYPE_M              0x03
> +#define   SDC_CMD_DTYPE_S              11
> +#define   SDC_CMD_RSPTYP_M             0x07
> +#define   SDC_CMD_RSPTYP_S             7
> +#define   SDC_CMD_CMD_M                        0x3f
> +#define   SDC_CMD_CMD_S                        0
> +
> +#define SDC_ARG                                0x38
> +
> +#define SDC_STS                                0x3c
> +#define   SDC_STS_CMDBUSY              BIT(1)
> +#define   SDC_STS_SDCBUSY              BIT(0)
> +
> +#define SDC_RESP0                      0x40
> +#define SDC_RESP1                      0x44
> +#define SDC_RESP2                      0x48
> +#define SDC_RESP3                      0x4c
> +
> +#define SDC_BLK_NUM                    0x50
> +
> +#define SDC_ADV_CFG0                   0x64
> +#define   SDC_RX_ENHANCE_EN            BIT(20)
> +
> +#define MSDC_PATCH_BIT                 0xb0
> +#define   MSDC_INT_DAT_LATCH_CK_SEL_M  0x07
> +#define   MSDC_INT_DAT_LATCH_CK_SEL_S  7
> +
> +#define MSDC_PATCH_BIT1                        0xb4
> +#define   MSDC_PB1_STOP_DLY_M          0x0f
> +#define   MSDC_PB1_STOP_DLY_S          8
> +
> +#define MSDC_PATCH_BIT2                        0xb8
> +#define   MSDC_PB2_CRCSTSENSEL_M       0x07
> +#define   MSDC_PB2_CRCSTSENSEL_S       29
> +#define   MSDC_PB2_CFGCRCSTS           BIT(28)
> +#define   MSDC_PB2_RESPSTSENSEL_M      0x07
> +#define   MSDC_PB2_RESPSTSENSEL_S      16
> +#define   MSDC_PB2_CFGRESP             BIT(15)
> +#define   MSDC_PB2_RESPWAIT_M          0x03
> +#define   MSDC_PB2_RESPWAIT_S          2
> +
> +#define MSDC_PAD_TUNE                  0xec
> +#define   MSDC_PAD_TUNE_CMDRRDLY_M     0x1f
> +#define   MSDC_PAD_TUNE_CMDRRDLY_S     22
> +#define   MSDC_PAD_TUNE_CMD_SEL                BIT(21)
> +#define   MSDC_PAD_TUNE_CMDRDLY_M      0x1f
> +#define   MSDC_PAD_TUNE_CMDRDLY_S      16
> +#define   MSDC_PAD_TUNE_RXDLYSEL       BIT(15)
> +#define   MSDC_PAD_TUNE_RD_SEL         BIT(13)
> +#define   MSDC_PAD_TUNE_DATRRDLY_M     0x1f
> +#define   MSDC_PAD_TUNE_DATRRDLY_S     8
> +#define   MSDC_PAD_TUNE_DATWRDLY_M     0x1f
> +#define   MSDC_PAD_TUNE_DATWRDLY_S     0
> +
> +#define MSDC_PAD_TUNE0                 0xf0
> +
> +#define PAD_DS_TUNE                    0x188
> +
> +#define EMMC50_CFG0                    0x208
> +#define   EMMC50_CFG_CFCSTS_SEL                BIT(4)
> +
> +#define SDC_FIFO_CFG                   0x228
> +#define   SDC_FIFO_CFG_WRVALIDSEL      BIT(24)
> +#define   SDC_FIFO_CFG_RDVALIDSEL      BIT(25)
> +
> +/* SDC_CFG_BUSWIDTH */
> +#define MSDC_BUS_1BITS                 0x0
> +#define MSDC_BUS_4BITS                 0x1
> +#define MSDC_BUS_8BITS                 0x2
> +
> +#define MSDC_FIFO_SIZE                 128
> +
> +#define PAD_DELAY_MAX                  32
> +
> +#define CMD_INTS_MASK  \
> +       (MSDC_INT_CMDRDY | MSDC_INT_RSPCRCERR | MSDC_INT_CMDTMO)
> +
> +#define DATA_INTS_MASK \
> +       (MSDC_INT_XFER_COMPL | MSDC_INT_DATTMO | MSDC_INT_DATCRCERR)
> +
> +struct msdc_compatible {
> +       u8 clk_div_bits;
> +       bool pad_tune0;
> +       bool async_fifo;
> +       bool data_tune;
> +       bool busy_check;
> +       bool stop_clk_fix;
> +       bool enhance_rx;
> +};
> +
> +struct msdc_delay_phase {
> +       u8 maxlen;
> +       u8 start;
> +       u8 final_phase;
> +};
> +
> +struct msdc_plat {
> +       struct mmc_config cfg;
> +       struct mmc mmc;
> +};
> +
> +struct msdc_tune_para {
> +       u32 iocon;
> +       u32 pad_tune;
> +};
> +
> +struct msdc_host {
> +       void __iomem *base;
> +       struct mmc *mmc;
> +
> +       struct msdc_compatible *dev_comp;
> +
> +       struct clk src_clk;
> +       struct clk h_clk;
> +
> +       u32 mclk;
> +       u32 src_clk_freq;
> +       u32 sclk;
> +
> +       u32 timeout_ns;
> +       u32 timeout_clks;
> +
> +       u32 hs400_ds_delay;
> +       u32 hs200_cmd_int_delay;
> +       u32 hs200_write_int_delay;
> +       u32 latch_ck;
> +       u32 r_smpl;
> +       bool hs400_mode;
> +
> +       struct gpio_desc gpio_wp;
> +       struct gpio_desc gpio_cd;
> +
> +       uint last_resp_type;
> +       uint last_data_write;
> +
> +       enum bus_mode timing;
> +
> +       struct msdc_tune_para def_tune_para;
> +       struct msdc_tune_para saved_tune_para;

This struct needs comments.

> +};
> +
> +static void msdc_reset_hw(struct msdc_host *host)
> +{
> +       u32 reg;
> +
> +       setbits_le32(host->base + MSDC_CFG, MSDC_CFG_RST);
> +
> +       readl_poll_timeout(host->base + MSDC_CFG, reg,
> +                          !(reg & MSDC_CFG_RST), 1000000);
> +}
> +
> +static void msdc_fifo_clr(struct msdc_host *host)
> +{
> +       u32 reg;
> +
> +       setbits_le32(host->base + MSDC_FIFOCS, MSDC_FIFOCS_CLR);
> +
> +       readl_poll_timeout(host->base + MSDC_FIFOCS, reg,
> +                          !(reg & MSDC_FIFOCS_CLR), 1000000);
> +}
> +
> +static u32 msdc_fifo_rx_bytes(struct msdc_host *host)
> +{
> +       return (readl(host->base + MSDC_FIFOCS) >> MSDC_FIFOCS_RXCNT_S) &
> +               MSDC_FIFOCS_RXCNT_M;
> +}
> +
> +static u32 msdc_fifo_tx_bytes(struct msdc_host *host)
> +{
> +       return (readl(host->base + MSDC_FIFOCS) >> MSDC_FIFOCS_TXCNT_S) &
> +               MSDC_FIFOCS_TXCNT_M;
> +}
> +
> +static u32 msdc_cmd_find_resp(struct msdc_host *host, struct mmc_cmd *cmd)
> +{
> +       u32 resp;
> +
> +       switch (cmd->resp_type) {
> +               /* Actually, R1, R5, R6, R7 are the same */
> +       case MMC_RSP_R1:
> +               resp = 0x1;
> +               break;
> +       case MMC_RSP_R1b:
> +               resp = 0x7;
> +               break;
> +       case MMC_RSP_R2:
> +               resp = 0x2;
> +               break;
> +       case MMC_RSP_R3:
> +               resp = 0x3;
> +               break;
> +       case MMC_RSP_NONE:
> +       default:
> +               resp = 0x0;
> +               break;
> +       }
> +
> +       return resp;
> +}
> +
> +static u32 msdc_cmd_prepare_raw_cmd(struct msdc_host *host,
> +                                   struct mmc_cmd *cmd,
> +                                   struct mmc_data *data)
> +{
> +       u32 opcode = cmd->cmdidx;
> +       u32 resp_type = msdc_cmd_find_resp(host, cmd);
> +       uint blocksize = 0;
> +       u32 dtype = 0;
> +       u32 rawcmd = 0;
> +
> +       switch (opcode) {
> +       case MMC_CMD_WRITE_MULTIPLE_BLOCK:
> +       case MMC_CMD_READ_MULTIPLE_BLOCK:
> +               dtype = 2;
> +               break;
> +       case MMC_CMD_WRITE_SINGLE_BLOCK:
> +       case MMC_CMD_READ_SINGLE_BLOCK:
> +       case SD_CMD_APP_SEND_SCR:
> +               dtype = 1;
> +               break;
> +       case SD_CMD_SWITCH_FUNC: /* same as MMC_CMD_SWITCH */
> +       case SD_CMD_SEND_IF_COND: /* same as MMC_CMD_SEND_EXT_CSD */
> +       case SD_CMD_APP_SD_STATUS: /* same as MMC_CMD_SEND_STATUS */
> +               if (data)
> +                       dtype = 1;
> +       }
> +
> +       if (data) {
> +               if (data->flags == MMC_DATA_WRITE)
> +                       rawcmd |= SDC_CMD_WR;
> +
> +               if (data->blocks > 1)
> +                       dtype = 2;
> +
> +               blocksize = data->blocksize;
> +       }
> +
> +       rawcmd |= ((opcode & SDC_CMD_CMD_M) << SDC_CMD_CMD_S) |
> +               ((resp_type & SDC_CMD_RSPTYP_M) << SDC_CMD_RSPTYP_S) |
> +               ((blocksize & SDC_CMD_BLK_LEN_M) << SDC_CMD_BLK_LEN_S) |
> +               ((dtype & SDC_CMD_DTYPE_M) << SDC_CMD_DTYPE_S);
> +
> +       if (opcode == MMC_CMD_STOP_TRANSMISSION)
> +               rawcmd |= SDC_CMD_STOP;
> +
> +       return rawcmd;
> +}
> +
> +static int msdc_cmd_done(struct msdc_host *host, int events,
> +                        struct mmc_cmd *cmd)
> +{
> +       u32 *rsp = cmd->response;
> +       int ret = 0;
> +
> +       if (cmd->resp_type & MMC_RSP_PRESENT) {
> +               if (cmd->resp_type & MMC_RSP_136) {
> +                       rsp[0] = readl(host->base + SDC_RESP3);
> +                       rsp[1] = readl(host->base + SDC_RESP2);
> +                       rsp[2] = readl(host->base + SDC_RESP1);
> +                       rsp[3] = readl(host->base + SDC_RESP0);
> +               } else {
> +                       rsp[0] = readl(host->base + SDC_RESP0);

Use a C struct instead of all this base +_ xxx stuff?

[..]

> +static int msdc_drv_probe(struct udevice *dev)
> +{
> +       struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
> +       struct msdc_plat *plat = dev_get_platdata(dev);
> +       struct msdc_host *host = dev_get_priv(dev);
> +       struct mmc_config *cfg = &plat->cfg;
> +       int ret;
> +
> +       cfg->name = dev->name;
> +
> +       host->base = (void *)dev_read_addr(dev);
> +       if (!host->base)
> +               return -EINVAL;
> +
> +       ret = mmc_of_parse(dev, cfg);
> +       if (ret)
> +               return ret;

Normally we read the DT in the ofdata_to_platdata() method.

[..]

Regards,
Simon

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

* [U-Boot] [PATCH v2 17/18] spi: mtk_qspi: add qspi driver for MT7629 SoC
  2018-10-12  7:01 ` [U-Boot] [PATCH v2 17/18] spi: mtk_qspi: add qspi driver for MT7629 SoC Ryder Lee
@ 2018-10-25  3:30   ` Simon Glass
  2018-10-26  6:33   ` Jagan Teki
  2018-11-14  9:04   ` Jagan Teki
  2 siblings, 0 replies; 57+ messages in thread
From: Simon Glass @ 2018-10-25  3:30 UTC (permalink / raw)
  To: u-boot

On 12 October 2018 at 01:01, Ryder Lee <ryder.lee@mediatek.com> wrote:
> From: Guochun Mao <guochun.mao@mediatek.com>
>
> This patch adds MT7629 qspi driver for accessing SPI NOR flash.
>
> Cc: Jagan Teki <jagan@openedev.com>
> Signed-off-by: Guochun Mao <guochun.mao@mediatek.com>
> ---
> change since v2:
> - Drop flash commands in the driver.
> ---
>  drivers/spi/Kconfig    |   7 +
>  drivers/spi/Makefile   |   1 +
>  drivers/spi/mtk_qspi.c | 359 +++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 367 insertions(+)
>  create mode 100644 drivers/spi/mtk_qspi.c
>

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

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

* [U-Boot] [PATCH v2 18/18] MAINTAINERS: add an entry for MediaTek
  2018-10-12  7:01 ` [U-Boot] [PATCH v2 18/18] MAINTAINERS: add an entry for MediaTek Ryder Lee
@ 2018-10-25  3:30   ` Simon Glass
  0 siblings, 0 replies; 57+ messages in thread
From: Simon Glass @ 2018-10-25  3:30 UTC (permalink / raw)
  To: u-boot

On 12 October 2018 at 01:01, Ryder Lee <ryder.lee@mediatek.com> wrote:
> This patch adds an entry for MediaTek.
>
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> ---
>  MAINTAINERS | 18 ++++++++++++++++++
>  1 file changed, 18 insertions(+)

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

Please also add something like README.mediatek explaining what boards
are supported and how to build and put on a board (or two).

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

* [U-Boot] [PATCH v2 10/18] pinctrl: MediaTek: add pinctrl driver for MT7629 SoC
  2018-10-25  3:29   ` Simon Glass
@ 2018-10-25  6:08     ` Ryder Lee
  2018-11-03  6:08       ` Simon Glass
  0 siblings, 1 reply; 57+ messages in thread
From: Ryder Lee @ 2018-10-25  6:08 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Wed, 2018-10-24 at 21:29 -0600, Simon Glass wrote:
> Hi Ryder,
> 
> On 12 October 2018 at 01:00, Ryder Lee <ryder.lee@mediatek.com> wrote:
> > This patch adds pinctrl support for MT7629 SoC. The IO core found on
> > the SoC has the registers for pinctrl, pinconf and gpio mixed up in
> > the same register range.  Hence the driver also implements the gpio
> > functionality through UCLASS_GPIO.
> >
> > This also creates a common file as there might be other chips that use
> > the same binding and driver, then being a little more abstract could
> > help in the long run.
> >
> > Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> > ---
> >  arch/arm/include/asm/arch-mediatek/gpio.h     |   9 +
> >  drivers/pinctrl/Kconfig                       |   1 +
> >  drivers/pinctrl/Makefile                      |   1 +
> >  drivers/pinctrl/mediatek/Kconfig              |  11 +
> >  drivers/pinctrl/mediatek/Makefile             |   6 +
> >  drivers/pinctrl/mediatek/pinctrl-mt7629.c     | 488 +++++++++++++++++++++++
> >  drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 552 ++++++++++++++++++++++++++
> >  drivers/pinctrl/mediatek/pinctrl-mtk-common.h | 182 +++++++++
> >  8 files changed, 1250 insertions(+)
> >  create mode 100644 arch/arm/include/asm/arch-mediatek/gpio.h
> >  create mode 100644 drivers/pinctrl/mediatek/Kconfig
> >  create mode 100644 drivers/pinctrl/mediatek/Makefile
> >  create mode 100644 drivers/pinctrl/mediatek/pinctrl-mt7629.c
> >  create mode 100644 drivers/pinctrl/mediatek/pinctrl-mtk-common.c
> >  create mode 100644 drivers/pinctrl/mediatek/pinctrl-mtk-common.h
> >
> 
> [..]
> 
> > +int mtk_pinctrl_probe(struct udevice *dev, struct mtk_pinctrl_soc *soc)
> > +{
> > +       struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
> > +       int ret;
> > +
> > +       priv->base = dev_read_addr_ptr(dev);
> > +       if (priv->base == (void *)FDT_ADDR_T_NONE)
> > +               return -EINVAL;
> > +
> > +       priv->soc = soc;
> > +
> > +       ret = mtk_gpiochip_register(dev);
> > +       if (ret)
> > +               return ret;
> > +
> > +       return 0;
> > +}
> 
> How come this function is exported? It should be probed like any other driver.

It makes no difference. We could reuse it for other MTK chips in this
way.

In pinctrl-mt7623.c (patch 11/18):

static int mtk_pinctrl_mt7623_probe(struct udevice *dev)
{

//common probed function
	mtk_pinctrl_probe(dev, &mt7623_data);

//proprietary operations for the chip....
	mt7623_bonding_disable(dev);
        ....
}

The similar usage is meson_pinctrl_probe() in pinctrl-meson.c

Ryder

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

* [U-Boot] [PATCH v2 11/18] pinctrl: MediaTek: add pinctrl driver for MT7623 SoC
  2018-10-25  3:29   ` Simon Glass
@ 2018-10-25  6:13     ` Ryder Lee
  2018-11-03  6:08       ` Simon Glass
  0 siblings, 1 reply; 57+ messages in thread
From: Ryder Lee @ 2018-10-25  6:13 UTC (permalink / raw)
  To: u-boot

On Wed, 2018-10-24 at 21:29 -0600, Simon Glass wrote:
> Hi Ryder,
> 
> On 12 October 2018 at 01:01, Ryder Lee <ryder.lee@mediatek.com> wrote:
> > This patch adds pinctrl support for MT7623 SoC. And most of the
> > structures are used to hold the hardware configuration for each
> > pin.
> >
> > Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> > Tested-by: Matthias Brugger <matthias.bgg@gmail.com>
> > ---
> >  drivers/pinctrl/mediatek/Kconfig              |    4 +
> >  drivers/pinctrl/mediatek/Makefile             |    1 +
> >  drivers/pinctrl/mediatek/pinctrl-mt7623.c     | 1284 +++++++++++++++++++++++++
> >  drivers/pinctrl/mediatek/pinctrl-mtk-common.h |    1 +
> >  4 files changed, 1290 insertions(+)
> >  create mode 100644 drivers/pinctrl/mediatek/pinctrl-mt7623.c
> 
> [..]
> 
> > +void mtk_rmw(struct udevice *dev, u32 reg, u32 mask, u32 set);
> 
> What is this for? It has no comment and is an exported function. We
> should not export things from drivers unless there is a good reason.

This is a common 'read-modify-write' helper. I think we could export it
in this shared header?

> Regards,
> Simon

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

* [U-Boot] [PATCH v2 06/18] clk: MediaTek: add clock driver for MT7629 SoC.
  2018-10-25  3:29   ` Simon Glass
@ 2018-10-25  6:37     ` Ryder Lee
  2018-11-03  6:08       ` Simon Glass
  0 siblings, 1 reply; 57+ messages in thread
From: Ryder Lee @ 2018-10-25  6:37 UTC (permalink / raw)
  To: u-boot

On Wed, 2018-10-24 at 21:29 -0600, Simon Glass wrote:
> Hi Ryder,
> 
> On 12 October 2018 at 01:00, Ryder Lee <ryder.lee@mediatek.com> wrote:
> > This patch adds clock modules for MediaTek SoCs:
> > - Shared part: a common driver which contains the general operations
> > for plls, muxes, dividers and gates so that we can reuse it in future.
> >
> > - Specific SoC part: the group of structures used to hold the hardware
> > configuration for each SoC.
> >
> > We take MT7629 as an example to demonstrate how to implement driver if
> > any other MediaTek chips would like to use it.
> >
> > Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> > ---
> >  drivers/clk/Makefile              |   1 +
> >  drivers/clk/mediatek/Makefile     |   6 +
> >  drivers/clk/mediatek/clk-mt7629.c | 709 ++++++++++++++++++++++++++++++++++++++
> >  drivers/clk/mediatek/clk-mtk.c    | 492 ++++++++++++++++++++++++++
> >  drivers/clk/mediatek/clk-mtk.h    | 153 ++++++++
> >  5 files changed, 1361 insertions(+)
> >  create mode 100644 drivers/clk/mediatek/Makefile
> >  create mode 100644 drivers/clk/mediatek/clk-mt7629.c
> >  create mode 100644 drivers/clk/mediatek/clk-mtk.c
> >  create mode 100644 drivers/clk/mediatek/clk-mtk.h
> 
> Looks good except for a few things below.
> 
> [..]
> 
> > +const struct clk_ops mtk_clk_gate_ops = {
> > +       .enable = mtk_clk_gate_enable,
> > +       .disable = mtk_clk_gate_disable,
> > +       .get_rate = mtk_clk_gate_get_rate,
> > +};
> > +
> > +int mtk_clk_init(struct udevice *dev, const struct mtk_clk_tree *tree)
> > +{
> > +       struct mtk_clk_priv *priv = dev_get_priv(dev);
> > +
> > +       priv->base = dev_read_addr_ptr(dev);
> > +       if (!priv->base)
> > +               return -ENOENT;
> 
> Why do you export these two functions? Devices should be probed in the
> normal DM way.

Yes, they are probed in the normal way. These functions are used by
several clock blocks and MTK SoCs. so I put the common parts here to
keep the code as clean as possible.

ex:
static int mt7629_apmixedsys_probe(struct udevice *dev)
{
	...
	ret = mtk_clk_init(...);

	/* reduce clock square disable time */
	writel(...);
	...

}

static int mt7629_topckgen_probe(struct udevice *dev)
{
	return mtk_clk_init(...);
}

> > +
> > +       priv->tree = tree;
> > +
> > +       return 0;
> > +}
> > +
> > +int mtk_clk_gate_init(struct udevice *dev,
> > +                     const struct mtk_clk_tree *tree,
> > +                     const struct mtk_gate *gates)
> > +{
> > +       struct mtk_cg_priv *priv = dev_get_priv(dev);
> > +
> > +       priv->base = dev_read_addr_ptr(dev);
> > +       if (!priv->base)
> > +               return -ENOENT;
> > +
> > +       priv->tree = tree;
> > +       priv->gates = gates;
> > +
> > +       return 0;
> > +}
> 
> [...]
> 
> Regards,
> Simon

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

* [U-Boot] [PATCH v2 05/18] arm: MediaTek: add basic support for MT7623 boards
  2018-10-25  3:29   ` Simon Glass
@ 2018-10-25  6:40     ` Ryder Lee
  0 siblings, 0 replies; 57+ messages in thread
From: Ryder Lee @ 2018-10-25  6:40 UTC (permalink / raw)
  To: u-boot

On Wed, 2018-10-24 at 21:29 -0600, Simon Glass wrote:
> Hi,
> 
> On 12 October 2018 at 01:00, Ryder Lee <ryder.lee@mediatek.com> wrote:
> > From: Weijie Gao <weijie.gao@mediatek.com>
> >
> > This adds a general board file based on MT7623 SoCs from MediaTek.
> >
> > As this u-boot is loaded by preloader, there is no low level
> > initializtion codes.
> >
> > Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
> > Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> > Tested-by: Matthias Brugger <matthias.bgg@gmail.com>
> > ---
> >  arch/arm/mach-mediatek/Kconfig                |  8 +++
> >  arch/arm/mach-mediatek/Makefile               |  1 +
> >  arch/arm/mach-mediatek/mt7623/Makefile        |  4 ++
> >  arch/arm/mach-mediatek/mt7623/init.c          | 54 +++++++++++++++
> >  arch/arm/mach-mediatek/mt7623/lowlevel_init.S | 22 ++++++
> >  arch/arm/mach-mediatek/mt7623/preloader.h     | 99 +++++++++++++++++++++++++++
> >  board/mediatek/mt7623/Kconfig                 | 13 ++++
> >  board/mediatek/mt7623/MAINTAINERS             |  7 ++
> >  board/mediatek/mt7623/Makefile                |  3 +
> >  board/mediatek/mt7623/mt7623_rfb.c            | 16 +++++
> >  configs/mt7623n_bpir2_defconfig               | 53 ++++++++++++++
> >  include/configs/mt7623.h                      | 61 +++++++++++++++++
> >  12 files changed, 341 insertions(+)
> >  create mode 100644 arch/arm/mach-mediatek/mt7623/Makefile
> >  create mode 100644 arch/arm/mach-mediatek/mt7623/init.c
> >  create mode 100644 arch/arm/mach-mediatek/mt7623/lowlevel_init.S
> >  create mode 100644 arch/arm/mach-mediatek/mt7623/preloader.h
> >  create mode 100644 board/mediatek/mt7623/Kconfig
> >  create mode 100644 board/mediatek/mt7623/MAINTAINERS
> >  create mode 100644 board/mediatek/mt7623/Makefile
> >  create mode 100644 board/mediatek/mt7623/mt7623_rfb.c
> >  create mode 100644 configs/mt7623n_bpir2_defconfig
> >  create mode 100644 include/configs/mt7623.h
> >
> 
> There is a new SPL handoff and bloblist feature that I hope will land
> in the next release. Can you please look at using this instead of an
> SoC-specififc mechanism?
> 
> See u-boot-dm/spl-working

Okay, I will take a look at this.

Ryder

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

* [U-Boot] [PATCH v2 04/18] arm: MediaTek: add basic support for MT7629 boards
  2018-10-25  3:29   ` Simon Glass
@ 2018-10-25  6:44     ` Ryder Lee
  0 siblings, 0 replies; 57+ messages in thread
From: Ryder Lee @ 2018-10-25  6:44 UTC (permalink / raw)
  To: u-boot

On Wed, 2018-10-24 at 21:29 -0600, Simon Glass wrote:
> Hi Ryder,
> 
> On 12 October 2018 at 01:00, Ryder Lee <ryder.lee@mediatek.com> wrote:
> > This adds a general board file based on MT7629 SoCs from MediaTek.
> >
> > Apart from the generic parts (cpu) we add some low level init codes
> > and initialize the early clocks.
> >
> > Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> > Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
> > ---
> >  arch/arm/Kconfig                              |  14 +++
> >  arch/arm/Makefile                             |   1 +
> >  arch/arm/include/asm/arch-mediatek/misc.h     |  17 ++++
> >  arch/arm/mach-mediatek/Kconfig                |  24 +++++
> >  arch/arm/mach-mediatek/Makefile               |   6 ++
> >  arch/arm/mach-mediatek/cpu.c                  |  34 +++++++
> >  arch/arm/mach-mediatek/init.h                 |  11 +++
> >  arch/arm/mach-mediatek/mt7629/Makefile        |   4 +
> >  arch/arm/mach-mediatek/mt7629/init.c          | 131 ++++++++++++++++++++++++++
> >  arch/arm/mach-mediatek/mt7629/lowlevel_init.S |  50 ++++++++++
> >  arch/arm/mach-mediatek/spl.c                  |  43 +++++++++
> >  board/mediatek/mt7629/Kconfig                 |  17 ++++
> >  board/mediatek/mt7629/MAINTAINERS             |   7 ++
> >  board/mediatek/mt7629/Makefile                |   3 +
> >  board/mediatek/mt7629/mt7629_rfb.c            |  16 ++++
> >  configs/mt7629_rfb_defconfig                  |  73 ++++++++++++++
> >  include/configs/mt7629.h                      |  62 ++++++++++++
> >  17 files changed, 513 insertions(+)
> >  create mode 100644 arch/arm/include/asm/arch-mediatek/misc.h
> >  create mode 100644 arch/arm/mach-mediatek/Kconfig
> >  create mode 100644 arch/arm/mach-mediatek/Makefile
> >  create mode 100644 arch/arm/mach-mediatek/cpu.c
> >  create mode 100644 arch/arm/mach-mediatek/init.h
> >  create mode 100644 arch/arm/mach-mediatek/mt7629/Makefile
> >  create mode 100644 arch/arm/mach-mediatek/mt7629/init.c
> >  create mode 100644 arch/arm/mach-mediatek/mt7629/lowlevel_init.S
> >  create mode 100644 arch/arm/mach-mediatek/spl.c
> >  create mode 100644 board/mediatek/mt7629/Kconfig
> >  create mode 100644 board/mediatek/mt7629/MAINTAINERS
> >  create mode 100644 board/mediatek/mt7629/Makefile
> >  create mode 100644 board/mediatek/mt7629/mt7629_rfb.c
> >  create mode 100644 configs/mt7629_rfb_defconfig
> >  create mode 100644 include/configs/mt7629.h
> 
> Looks good. A few nits below
> 
> >
> > diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> > index ccf2a84..eac03f0 100644
> > --- a/arch/arm/Kconfig
> > +++ b/arch/arm/Kconfig
> > @@ -668,6 +668,18 @@ config ARCH_MESON
> >           targeted at media players and tablet computers. We currently
> >           support the S905 (GXBaby) 64-bit SoC.
> >
> > +config ARCH_MEDIATEK
> > +       bool "MediaTek SoCs"
> > +       select DM
> > +       select OF_CONTROL
> > +       select SPL_DM if SPL
> > +       select SPL_LIBCOMMON_SUPPORT if SPL
> > +       select SPL_LIBGENERIC_SUPPORT if SPL
> > +       select SPL_OF_CONTROL if SPL
> > +       select SUPPORT_SPL
> > +       help
> > +         Support for the MediaTek SoCs family.
> 
> Please add more info. What type of SoCs are these? What are the
> capabilities? Link to web site? datasheets? wiki? Or maybe point to a
> doc/README.mediatek?
> 
> > +
> >  config ARCH_MX8M
> >         bool "NXP i.MX8M platform"
> >         select ARM64
> > @@ -1423,6 +1435,8 @@ source "arch/arm/mach-rmobile/Kconfig"
> >
> >  source "arch/arm/mach-meson/Kconfig"
> >
> > +source "arch/arm/mach-mediatek/Kconfig"
> > +
> >  source "arch/arm/mach-qemu/Kconfig"
> >
> >  source "arch/arm/mach-rockchip/Kconfig"
> > diff --git a/arch/arm/Makefile b/arch/arm/Makefile
> > index 8f50560..ddb9618 100644
> > --- a/arch/arm/Makefile
> > +++ b/arch/arm/Makefile
> > @@ -62,6 +62,7 @@ machine-$(CONFIG_ARCH_K3)             += k3
> >  machine-$(CONFIG_ARCH_KEYSTONE)                += keystone
> >  # TODO: rename CONFIG_KIRKWOOD -> CONFIG_ARCH_KIRKWOOD
> >  machine-$(CONFIG_KIRKWOOD)             += kirkwood
> > +machine-$(CONFIG_ARCH_MEDIATEK)                += mediatek
> >  machine-$(CONFIG_ARCH_MESON)           += meson
> >  machine-$(CONFIG_ARCH_MVEBU)           += mvebu
> >  # TODO: rename CONFIG_TEGRA -> CONFIG_ARCH_TEGRA
> > diff --git a/arch/arm/include/asm/arch-mediatek/misc.h b/arch/arm/include/asm/arch-mediatek/misc.h
> > new file mode 100644
> > index 0000000..2530e78
> > --- /dev/null
> > +++ b/arch/arm/include/asm/arch-mediatek/misc.h
> > @@ -0,0 +1,17 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * Copyright (C) 2018 MediaTek Inc.
> > + */
> > +
> > +#ifndef __MEDIATEK_MISC_H_
> > +#define __MEDIATEK_MISC_H_
> > +
> > +#define VER_BASE               0x08000000
> > +#define VER_SIZE               0x10
> > +
> > +#define APHW_CODE              0x00
> > +#define APHW_SUBCODE           0x04
> > +#define APHW_VER               0x08
> > +#define APSW_VER               0x0c
> > +
> > +#endif /* __MEDIATEK_MISC_H_ */
> > diff --git a/arch/arm/mach-mediatek/Kconfig b/arch/arm/mach-mediatek/Kconfig
> > new file mode 100644
> > index 0000000..a932e70
> > --- /dev/null
> > +++ b/arch/arm/mach-mediatek/Kconfig
> > @@ -0,0 +1,24 @@
> > +if ARCH_MEDIATEK
> > +
> > +config SYS_SOC
> > +       default "mediatek"
> > +
> > +config SYS_VENDOR
> > +       default "mediatek"
> > +
> > +choice
> > +       prompt "MediaTek board select"
> > +
> > +config TARGET_MT7629
> > +       bool "MediaTek MT7629 SoC"
> > +       select CPU_V7A
> > +       select SPL
> > +       select ARCH_MISC_INIT
> > +       help
> > +               Support MediaTek MT7629 SoC.
> 
> Please describe the features of this SoC.
> 
> > +
> > +endchoice
> > +
> > +source "board/mediatek/mt7629/Kconfig"
> > +
> > +endif
> > diff --git a/arch/arm/mach-mediatek/Makefile b/arch/arm/mach-mediatek/Makefile
> > new file mode 100644
> > index 0000000..852d330
> > --- /dev/null
> > +++ b/arch/arm/mach-mediatek/Makefile
> > @@ -0,0 +1,6 @@
> > +# SPDX-License-Identifier:     GPL-2.0
> > +
> > +obj-y  += cpu.o
> > +obj-$(CONFIG_SPL_BUILD)        += spl.o
> > +
> > +obj-$(CONFIG_TARGET_MT7629) += mt7629/
> > diff --git a/arch/arm/mach-mediatek/cpu.c b/arch/arm/mach-mediatek/cpu.c
> > new file mode 100644
> > index 0000000..2bfeab7
> > --- /dev/null
> > +++ b/arch/arm/mach-mediatek/cpu.c
> > @@ -0,0 +1,34 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (C) 2018 MediaTek Inc.
> > + */
> > +
> > +#include <common.h>
> > +#include <dm.h>
> > +#include <dm/uclass-internal.h>
> > +#include <wdt.h>
> 
> dm/ goes after wdt.h
> 
> https://www.denx.de/wiki/U-Boot/CodingStyle
> 
> > +
> > +int arch_misc_init(void)
> > +{
> > +       struct udevice *wdt;
> > +       int ret;
> > +
> > +       ret = uclass_get_device(UCLASS_WDT, 0, &wdt);
> > +       if (!ret)
> > +               wdt_stop(wdt);
> > +
> > +       return 0;
> > +}
> > +
> > +int arch_cpu_init(void)
> > +{
> > +       icache_enable();
> > +
> > +       return 0;
> > +}
> > +
> > +void enable_caches(void)
> > +{
> > +       /* Enable D-cache. I-cache is already enabled in start.S */
> > +       dcache_enable();
> > +}
> > diff --git a/arch/arm/mach-mediatek/init.h b/arch/arm/mach-mediatek/init.h
> > new file mode 100644
> > index 0000000..1d896fb
> > --- /dev/null
> > +++ b/arch/arm/mach-mediatek/init.h
> > @@ -0,0 +1,11 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * Copyright (C) 2018 MediaTek Inc.
> > + */
> > +
> > +#ifndef __MEDIATEK_INIT_H_
> > +#define __MEDIATEK_INIT_H_
> > +
> > +extern int mtk_soc_early_init(void);
> > +
> > +#endif /* __MEDIATEK_INIT_H_ */
> > diff --git a/arch/arm/mach-mediatek/mt7629/Makefile b/arch/arm/mach-mediatek/mt7629/Makefile
> > new file mode 100644
> > index 0000000..007eb4a
> > --- /dev/null
> > +++ b/arch/arm/mach-mediatek/mt7629/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/mt7629/init.c b/arch/arm/mach-mediatek/mt7629/init.c
> > new file mode 100644
> > index 0000000..8f195b5
> > --- /dev/null
> > +++ b/arch/arm/mach-mediatek/mt7629/init.c
> > @@ -0,0 +1,131 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (C) 2018 MediaTek Inc.
> > + * Author: Ryder Lee <ryder.lee@mediatek.com>
> > + */
> > +
> > +#include <clk.h>
> > +#include <common.h>
> > +#include <dm.h>
> > +#include <dm/uclass.h>
> > +#include <fdtdec.h>
> > +#include <linux/io.h>
> > +#include <ram.h>
> > +#include <asm/arch/misc.h>
> > +#include <asm/sections.h>
> 
> fix ordering
> 
> > +
> > +#include <dt-bindings/clock/mt7629-clk.h>
> > +
> > +#define L2_SHARE_CFG_MP0       0x7f0
> > +#define L2_SHARE_MODE_OFF      BIT(8)
> > +
> > +DECLARE_GLOBAL_DATA_PTR;
> > +
> > +int mtk_pll_early_init(void)
> > +{
> > +       unsigned long pll_rates[] = {
> > +               [CLK_APMIXED_ARMPLL] = 1250000000,
> > +               [CLK_APMIXED_MAINPLL] = 1120000000,
> > +               [CLK_APMIXED_UNIV2PLL] = 1200000000,
> > +               [CLK_APMIXED_ETH1PLL] = 500000000,
> > +               [CLK_APMIXED_ETH2PLL] = 700000000,
> > +               [CLK_APMIXED_SGMIPLL] = 650000000,
> > +       };
> > +       struct udevice *dev;
> > +       int ret, i;
> > +
> > +       ret = uclass_get_device_by_driver(UCLASS_CLK,
> > +                       DM_GET_DRIVER(mtk_clk_apmixedsys), &dev);
> > +       if (ret)
> > +               return ret;
> > +
> > +       /* configure default rate then enable apmixedsys */
> > +       for (i = 0; i < ARRAY_SIZE(pll_rates); i++) {
> > +               struct clk clk = { .id = i, .dev = dev };
> > +
> > +               ret = clk_set_rate(&clk, pll_rates[i]);
> > +               if (ret)
> > +                       return ret;
> > +
> > +               ret = clk_enable(&clk);
> > +               if (ret)
> > +                       return ret;
> > +       }
> > +
> > +       /* setup mcu bus */
> > +       ret = uclass_get_device_by_driver(UCLASS_SYSCON,
> > +                       DM_GET_DRIVER(mtk_mcucfg), &dev);
> > +       if (ret)
> > +               return ret;
> > +
> > +       return 0;
> > +}
> > +
> > +int mtk_soc_early_init(void)
> > +{
> > +       struct udevice *dev;
> > +       int ret;
> > +
> > +       /* initialize early clocks */
> > +       ret = mtk_pll_early_init();
> > +       if (ret)
> > +               return ret;
> > +
> > +       ret = uclass_get_device(UCLASS_RAM, 0, &dev);
> 
> Consider uclass_first_device_err(). Same elsewhere.
> 
> > +       if (ret)
> > +               return ret;
> > +
> > +       return 0;
> > +}
> > +
> > +int mach_cpu_init(void)
> > +{
> > +       void __iomem *base;
> > +       int node;
> > +
> > +       node = fdt_node_offset_by_compatible(gd->fdt_blob, -1,
> > +                       "mediatek,mt7629-mcucfg");
> 
> Add a driver fopr this - don't access it directly. This could be a
> syscon device perhaps?
> 
> > +       base = (void __iomem *)fdtdec_get_addr(gd->fdt_blob, node, "reg");
> 
> dev_read_addr(). Please use the live tree functions.
> 
> > +       if (!base)
> > +               return -ENOENT;
> > +
> > +       /* disable L2C shared mode */
> > +       writel(L2_SHARE_MODE_OFF, base + L2_SHARE_CFG_MP0);
> > +
> > +       return 0;
> > +}
> > +
> > +int dram_init(void)
> > +{
> > +       struct ram_info ram;
> > +       struct udevice *dev;
> > +       int ret;
> > +
> > +       ret = uclass_get_device(UCLASS_RAM, 0, &dev);
> > +       if (ret)
> > +               return ret;
> > +
> > +       ret = ram_get_info(dev, &ram);
> > +       if (ret)
> > +               return ret;
> > +
> > +       debug("RAM init base=%lx, size=%x\n", ram.base, ram.size);
> > +
> > +       gd->ram_size = ram.size;
> > +
> > +       return 0;
> > +}
> > +
> > +int print_cpuinfo(void)
> > +{
> > +       void __iomem *chipid;
> > +       u32 hwcode, swver;
> > +
> > +       chipid = ioremap(VER_BASE, VER_SIZE);
> > +       hwcode = readl(chipid + APHW_CODE);
> > +       swver = readl(chipid + APSW_VER);
> > +
> > +       printf("CPU:   MediaTek MT%04x E%d\n", hwcode, (swver & 0xf) + 1);
> > +
> > +       return 0;
> > +}
> 
> [..]
> 
> > new file mode 100644
> > index 0000000..83ccbba
> > --- /dev/null
> > +++ b/board/mediatek/mt7629/Makefile
> > @@ -0,0 +1,3 @@
> > +# SPDX-License-Identifier:     GPL-2.0
> > +
> > +obj-y += mt7629_rfb.o
> > diff --git a/board/mediatek/mt7629/mt7629_rfb.c b/board/mediatek/mt7629/mt7629_rfb.c
> > new file mode 100644
> > index 0000000..08468b5
> > --- /dev/null
> > +++ b/board/mediatek/mt7629/mt7629_rfb.c
> > @@ -0,0 +1,16 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (C) 2018 MediaTek Inc.
> > + */
> > +
> > +#include <common.h>
> > +
> > +DECLARE_GLOBAL_DATA_PTR;
> > +
> > +int board_init(void)
> > +{
> > +       /* address of boot parameters */
> > +       gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
> 
> Do we need these?
> 
> > +
> > +       return 0;
> > +}
> 
> [..]
> 
> > diff --git a/include/configs/mt7629.h b/include/configs/mt7629.h
> > new file mode 100644
> > index 0000000..9b51e90
> > --- /dev/null
> > +++ b/include/configs/mt7629.h
> > @@ -0,0 +1,62 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * Configuration for MediaTek MT7629 SoC
> > + *
> > + * Copyright (C) 2018 MediaTek Inc.
> > + * Author: Ryder Lee <ryder.lee@mediatek.com>
> > + */
> > +
> > +#ifndef __MT7629_H
> > +#define __MT7629_H
> > +
> > +#include <linux/sizes.h>
> > +
> > +/* Miscellaneous configurable options */
> > +#define CONFIG_SETUP_MEMORY_TAGS
> > +#define CONFIG_INITRD_TAG
> > +#define CONFIG_CMDLINE_TAG
> > +
> > +#define CONFIG_SYS_MAXARGS             8
> > +#define CONFIG_SYS_BOOTM_LEN           SZ_64M
> > +#define CONFIG_SYS_CBSIZE              SZ_1K
> > +#define CONFIG_SYS_PBSIZE              (CONFIG_SYS_CBSIZE +    \
> > +                                       sizeof(CONFIG_SYS_PROMPT) + 16)
> > +
> > +/* Size of malloc() pool */
> > +#define CONFIG_SYS_MALLOC_LEN          SZ_4M
> > +
> > +/* Environment */
> > +#define CONFIG_ENV_SIZE                        SZ_4K
> > +/* Allow to overwrite serial and ethaddr */
> > +#define CONFIG_ENV_OVERWRITE
> > +
> > +/* Defines for SPL */
> > +#define CONFIG_SPL_STACK               0x106000
> > +#define CONFIG_SPL_TEXT_BASE           0x201000
> > +#define CONFIG_SPL_MAX_SIZE            SZ_64K
> > +#define CONFIG_SPL_MAX_FOOTPRINT       SZ_64K
> > +#define CONFIG_SPL_PAD_TO              0x10000
> > +
> > +#define CONFIG_SPI_ADDR                        0x30000000
> > +#define CONFIG_SYS_SPI_U_BOOT_OFFS     CONFIG_SPL_PAD_TO
> > +#define CONFIG_SYS_UBOOT_BASE          (CONFIG_SPI_ADDR + CONFIG_SPL_PAD_TO)
> > +
> > +/* SPL -> Uboot */
> > +#define CONFIG_SYS_UBOOT_START         CONFIG_SYS_TEXT_BASE
> > +#define CONFIG_SYS_INIT_SP_ADDR                (CONFIG_SYS_TEXT_BASE + SZ_2M - \
> > +                                        GENERATED_GBL_DATA_SIZE)
> > +
> > +/* UBoot -> Kernel */
> > +#define CONFIG_SYS_SPL_ARGS_ADDR       0x40000000
> > +#define CONFIG_LOADADDR                        0x42007f1c
> > +#define CONFIG_SYS_LOAD_ADDR           CONFIG_LOADADDR
> > +
> > +/* Serial device */
> > +#define CONFIG_SYS_NS16550_CLK         40000000
> > +#define CONFIG_SYS_NS16550_MEM32
> 
> Can you use the device tree for this?
> 
> > +#define CONFIG_BAUDRATE                        115200
> > +
> > +/* DRAM */
> > +#define CONFIG_SYS_SDRAM_BASE          0x40000000
> > +
> > +#endif
> > --
> > 1.9.1
> >


I will fix these in v3.

Ryder

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

* [U-Boot] [PATCH v2 15/18] ram: MediaTek: add DDR3 driver for MT7629 SoC
  2018-10-25  3:30   ` Simon Glass
@ 2018-10-25  9:38     ` Ryder Lee
  2018-10-26 16:53       ` Simon Glass
  0 siblings, 1 reply; 57+ messages in thread
From: Ryder Lee @ 2018-10-25  9:38 UTC (permalink / raw)
  To: u-boot

On Wed, 2018-10-24 at 21:30 -0600, Simon Glass wrote:
> On 12 October 2018 at 01:01, Ryder Lee <ryder.lee@mediatek.com> wrote:
> > This patch adds a DDR3 driver for MT7629 SoC.
> >
> > Signed-off-by: Wu Zou <wu.zou@mediatek.com>
> > Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> > ---
> >  drivers/ram/Makefile               |   1 +
> >  drivers/ram/mediatek/Makefile      |   7 +
> >  drivers/ram/mediatek/ddr3-mt7629.c | 766 +++++++++++++++++++++++++++++++++++++
> >  3 files changed, 774 insertions(+)
> >  create mode 100644 drivers/ram/mediatek/Makefile
> >  create mode 100644 drivers/ram/mediatek/ddr3-mt7629.c
> 
> Reviewed-by: Simon Glass <sjg@chromium.org>
> 
> Thoughts below.
> 
> [..]
> 
> > +#define DDRPHY_PLL1                    0x0000
> > +#define DDRPHY_PLL2                    0x0004
> 
> Why not use a C struct for these registers?

These are copy-n-paste from our SDK. I've considered converting these
into C struct but it will take me a while. Just let it be.

But, I could do that if you insist.

> [..]
> 
> > +       writel(0x400, priv->dramc_ao + DRAMC_MRS);
> > +       writel(0x1d7000, priv->dramc_ao + DRAMC_MRS);
> > +       writel(0x1, priv->dramc_ao + DRAMC_SPCMD);
> > +       writel(0x0, priv->dramc_ao + DRAMC_SPCMD);
> > +       udelay(100);
> 
> Are these delays specified in a datasheet? Why did you chose 100?
> Perhaps add an enum for this value? Is there a way to check for when
> the hardware is ready, e.g. by reading a registers in a loop?

Rule of thumb. There is no registers to read here, but I can try to
reduce the delay time.

> [..]
> 
> > +static int mtk_ddr3_probe(struct udevice *dev)
> > +{
> > +       struct mtk_ddr3_priv *priv = dev_get_priv(dev);
> > +
> > +       priv->emi = dev_read_addr_index(dev, 0);
> > +       if (priv->emi == FDT_ADDR_T_NONE)
> > +               return -EINVAL;
> > +
> > +       priv->ddrphy = dev_read_addr_index(dev, 1);
> > +       if (priv->ddrphy == FDT_ADDR_T_NONE)
> > +               return -EINVAL;
> > +
> > +       priv->dramc_ao = dev_read_addr_index(dev, 2);
> > +       if (priv->dramc_ao == FDT_ADDR_T_NONE)
> > +               return -EINVAL;
> > +
> > +#ifdef CONFIG_SPL_BUILD
> > +       int ret;
> > +
> > +       ret = clk_get_by_index(dev, 0, &priv->phy);
> > +       if (ret)
> > +               return ret;
> > +
> > +       ret = clk_get_by_index(dev, 1, &priv->phy_mux);
> > +       if (ret)
> > +               return ret;
> > +
> > +       ret = clk_get_by_index(dev, 2, &priv->mem);
> > +       if (ret)
> > +               return ret;
> > +
> > +       ret = clk_get_by_index(dev, 3, &priv->mem_mux);
> > +       if (ret)
> > +               return ret;
> 
> Do you have phandles for these clocks? I only worry that it is a bit
> brittle to have them numbered.

Yes. I choose clk_get_by_index() here as I stripped the 'clock-names'
via CONFIG_OF_SPL_REMOVE_PROPS to reduce the size .

Also I don't understand why we cannot use clk_set_defaults() in
pre-relocate state?


Ryder

> > +
> > +       ret = mtk_ddr3_init(dev);
> > +       if (ret)
> > +               return ret;
> > +#endif
> > +       return 0;
> > +}
> > +
> 
> Regards,
> Simon

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

* [U-Boot] [PATCH v2 01/18] tools: MediaTek: add MTK boot header generation to mkimage
  2018-10-25  3:29   ` Simon Glass
@ 2018-10-25 13:11     ` Ryder Lee
  0 siblings, 0 replies; 57+ messages in thread
From: Ryder Lee @ 2018-10-25 13:11 UTC (permalink / raw)
  To: u-boot

On Wed, 2018-10-24 at 21:29 -0600, Simon Glass wrote:
> Hi Ryder,
> 
> On 12 October 2018 at 01:00, Ryder Lee <ryder.lee@mediatek.com> wrote:
> > This patch adds support for MTK boot image generation.
> >
> > Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
> > Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> > ---
> >  Makefile             |  22 ++
> >  common/image.c       |   1 +
> >  include/image.h      |   1 +
> >  scripts/Makefile.spl |  11 +
> >  tools/Makefile       |   1 +
> >  tools/mtkimage.c     | 749 +++++++++++++++++++++++++++++++++++++++++++++++++++
> >  tools/mtkimage.h     | 199 ++++++++++++++
> >  7 files changed, 984 insertions(+)
> >  create mode 100644 tools/mtkimage.c
> >  create mode 100644 tools/mtkimage.h
> 
> The mkimage stuff looks fine.
> 
> But can you use binman for the pad/cat part of this? See for example
> sunxi. - sunxi-u-boot.dtsi
> 
> Also mtkimage.c is too close to mkimage.c - how about mtk_image.c ?
> 

This looks great. I will switch to use binman in v3.

Thanks
Ryder

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

* [U-Boot] [PATCH v2 17/18] spi: mtk_qspi: add qspi driver for MT7629 SoC
  2018-10-12  7:01 ` [U-Boot] [PATCH v2 17/18] spi: mtk_qspi: add qspi driver for MT7629 SoC Ryder Lee
  2018-10-25  3:30   ` Simon Glass
@ 2018-10-26  6:33   ` Jagan Teki
  2018-11-14  9:04   ` Jagan Teki
  2 siblings, 0 replies; 57+ messages in thread
From: Jagan Teki @ 2018-10-26  6:33 UTC (permalink / raw)
  To: u-boot

On Fri, Oct 12, 2018 at 12:46 PM Ryder Lee <ryder.lee@mediatek.com> wrote:
>
> From: Guochun Mao <guochun.mao@mediatek.com>
>
> This patch adds MT7629 qspi driver for accessing SPI NOR flash.
>
> Cc: Jagan Teki <jagan@openedev.com>
> Signed-off-by: Guochun Mao <guochun.mao@mediatek.com>
> ---

Few spaces need to add, will fix while applying.

Reviewed-by: Jagan Teki <jagan@openedev.com>

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

* [U-Boot] [PATCH v2 15/18] ram: MediaTek: add DDR3 driver for MT7629 SoC
  2018-10-25  9:38     ` Ryder Lee
@ 2018-10-26 16:53       ` Simon Glass
  0 siblings, 0 replies; 57+ messages in thread
From: Simon Glass @ 2018-10-26 16:53 UTC (permalink / raw)
  To: u-boot

Hi Ryder,

On 25 October 2018 at 03:38, Ryder Lee <ryder.lee@mediatek.com> wrote:
> On Wed, 2018-10-24 at 21:30 -0600, Simon Glass wrote:
>> On 12 October 2018 at 01:01, Ryder Lee <ryder.lee@mediatek.com> wrote:
>> > This patch adds a DDR3 driver for MT7629 SoC.
>> >
>> > Signed-off-by: Wu Zou <wu.zou@mediatek.com>
>> > Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
>> > ---
>> >  drivers/ram/Makefile               |   1 +
>> >  drivers/ram/mediatek/Makefile      |   7 +
>> >  drivers/ram/mediatek/ddr3-mt7629.c | 766 +++++++++++++++++++++++++++++++++++++
>> >  3 files changed, 774 insertions(+)
>> >  create mode 100644 drivers/ram/mediatek/Makefile
>> >  create mode 100644 drivers/ram/mediatek/ddr3-mt7629.c
>>
>> Reviewed-by: Simon Glass <sjg@chromium.org>
>>
>> Thoughts below.
>>
>> [..]
>>
>> > +#define DDRPHY_PLL1                    0x0000
>> > +#define DDRPHY_PLL2                    0x0004
>>
>> Why not use a C struct for these registers?
>
> These are copy-n-paste from our SDK. I've considered converting these
> into C struct but it will take me a while. Just let it be.
>
> But, I could do that if you insist.

OK we can leave it.

>
>> [..]
>>
>> > +       writel(0x400, priv->dramc_ao + DRAMC_MRS);
>> > +       writel(0x1d7000, priv->dramc_ao + DRAMC_MRS);
>> > +       writel(0x1, priv->dramc_ao + DRAMC_SPCMD);
>> > +       writel(0x0, priv->dramc_ao + DRAMC_SPCMD);
>> > +       udelay(100);
>>
>> Are these delays specified in a datasheet? Why did you chose 100?
>> Perhaps add an enum for this value? Is there a way to check for when
>> the hardware is ready, e.g. by reading a registers in a loop?
>
> Rule of thumb. There is no registers to read here, but I can try to
> reduce the delay time.

We often end up worrying about delays later so any comments about how
you came to those values are useful.

>
>> [..]
>>
>> > +static int mtk_ddr3_probe(struct udevice *dev)
>> > +{
>> > +       struct mtk_ddr3_priv *priv = dev_get_priv(dev);
>> > +
>> > +       priv->emi = dev_read_addr_index(dev, 0);
>> > +       if (priv->emi == FDT_ADDR_T_NONE)
>> > +               return -EINVAL;
>> > +
>> > +       priv->ddrphy = dev_read_addr_index(dev, 1);
>> > +       if (priv->ddrphy == FDT_ADDR_T_NONE)
>> > +               return -EINVAL;
>> > +
>> > +       priv->dramc_ao = dev_read_addr_index(dev, 2);
>> > +       if (priv->dramc_ao == FDT_ADDR_T_NONE)
>> > +               return -EINVAL;
>> > +
>> > +#ifdef CONFIG_SPL_BUILD
>> > +       int ret;
>> > +
>> > +       ret = clk_get_by_index(dev, 0, &priv->phy);
>> > +       if (ret)
>> > +               return ret;
>> > +
>> > +       ret = clk_get_by_index(dev, 1, &priv->phy_mux);
>> > +       if (ret)
>> > +               return ret;
>> > +
>> > +       ret = clk_get_by_index(dev, 2, &priv->mem);
>> > +       if (ret)
>> > +               return ret;
>> > +
>> > +       ret = clk_get_by_index(dev, 3, &priv->mem_mux);
>> > +       if (ret)
>> > +               return ret;
>>
>> Do you have phandles for these clocks? I only worry that it is a bit
>> brittle to have them numbered.
>
> Yes. I choose clk_get_by_index() here as I stripped the 'clock-names'
> via CONFIG_OF_SPL_REMOVE_PROPS to reduce the size .

OK

>
> Also I don't understand why we cannot use clk_set_defaults() in
> pre-relocate state?

I don't know either. It should be possible.

Regards,
Simon

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

* [U-Boot] [PATCH v2 10/18] pinctrl: MediaTek: add pinctrl driver for MT7629 SoC
  2018-10-25  6:08     ` Ryder Lee
@ 2018-11-03  6:08       ` Simon Glass
  0 siblings, 0 replies; 57+ messages in thread
From: Simon Glass @ 2018-11-03  6:08 UTC (permalink / raw)
  To: u-boot

Hi Ryder,

On 25 October 2018 at 00:08, Ryder Lee <ryder.lee@mediatek.com> wrote:
> Hi Simon,
>
> On Wed, 2018-10-24 at 21:29 -0600, Simon Glass wrote:
>> Hi Ryder,
>>
>> On 12 October 2018 at 01:00, Ryder Lee <ryder.lee@mediatek.com> wrote:
>> > This patch adds pinctrl support for MT7629 SoC. The IO core found on
>> > the SoC has the registers for pinctrl, pinconf and gpio mixed up in
>> > the same register range.  Hence the driver also implements the gpio
>> > functionality through UCLASS_GPIO.
>> >
>> > This also creates a common file as there might be other chips that use
>> > the same binding and driver, then being a little more abstract could
>> > help in the long run.
>> >
>> > Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
>> > ---
>> >  arch/arm/include/asm/arch-mediatek/gpio.h     |   9 +
>> >  drivers/pinctrl/Kconfig                       |   1 +
>> >  drivers/pinctrl/Makefile                      |   1 +
>> >  drivers/pinctrl/mediatek/Kconfig              |  11 +
>> >  drivers/pinctrl/mediatek/Makefile             |   6 +
>> >  drivers/pinctrl/mediatek/pinctrl-mt7629.c     | 488 +++++++++++++++++++++++
>> >  drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 552 ++++++++++++++++++++++++++
>> >  drivers/pinctrl/mediatek/pinctrl-mtk-common.h | 182 +++++++++
>> >  8 files changed, 1250 insertions(+)
>> >  create mode 100644 arch/arm/include/asm/arch-mediatek/gpio.h
>> >  create mode 100644 drivers/pinctrl/mediatek/Kconfig
>> >  create mode 100644 drivers/pinctrl/mediatek/Makefile
>> >  create mode 100644 drivers/pinctrl/mediatek/pinctrl-mt7629.c
>> >  create mode 100644 drivers/pinctrl/mediatek/pinctrl-mtk-common.c
>> >  create mode 100644 drivers/pinctrl/mediatek/pinctrl-mtk-common.h
>> >
>>
>> [..]
>>
>> > +int mtk_pinctrl_probe(struct udevice *dev, struct mtk_pinctrl_soc *soc)
>> > +{
>> > +       struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
>> > +       int ret;
>> > +
>> > +       priv->base = dev_read_addr_ptr(dev);
>> > +       if (priv->base == (void *)FDT_ADDR_T_NONE)
>> > +               return -EINVAL;
>> > +
>> > +       priv->soc = soc;
>> > +
>> > +       ret = mtk_gpiochip_register(dev);
>> > +       if (ret)
>> > +               return ret;
>> > +
>> > +       return 0;
>> > +}
>>
>> How come this function is exported? It should be probed like any other driver.
>
> It makes no difference. We could reuse it for other MTK chips in this
> way.
>
> In pinctrl-mt7623.c (patch 11/18):
>
> static int mtk_pinctrl_mt7623_probe(struct udevice *dev)
> {
>
> //common probed function
>         mtk_pinctrl_probe(dev, &mt7623_data);
>
> //proprietary operations for the chip....
>         mt7623_bonding_disable(dev);
>         ....
> }
>
> The similar usage is meson_pinctrl_probe() in pinctrl-meson.c

OK I see, so it is a common function called by all probe functions?

In that case, can it have a _common suffix?

Regards,
Simon

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

* [U-Boot] [PATCH v2 11/18] pinctrl: MediaTek: add pinctrl driver for MT7623 SoC
  2018-10-25  6:13     ` Ryder Lee
@ 2018-11-03  6:08       ` Simon Glass
  0 siblings, 0 replies; 57+ messages in thread
From: Simon Glass @ 2018-11-03  6:08 UTC (permalink / raw)
  To: u-boot

Hi Ryder,

On 25 October 2018 at 00:13, Ryder Lee <ryder.lee@mediatek.com> wrote:
> On Wed, 2018-10-24 at 21:29 -0600, Simon Glass wrote:
>> Hi Ryder,
>>
>> On 12 October 2018 at 01:01, Ryder Lee <ryder.lee@mediatek.com> wrote:
>> > This patch adds pinctrl support for MT7623 SoC. And most of the
>> > structures are used to hold the hardware configuration for each
>> > pin.
>> >
>> > Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
>> > Tested-by: Matthias Brugger <matthias.bgg@gmail.com>
>> > ---
>> >  drivers/pinctrl/mediatek/Kconfig              |    4 +
>> >  drivers/pinctrl/mediatek/Makefile             |    1 +
>> >  drivers/pinctrl/mediatek/pinctrl-mt7623.c     | 1284 +++++++++++++++++++++++++
>> >  drivers/pinctrl/mediatek/pinctrl-mtk-common.h |    1 +
>> >  4 files changed, 1290 insertions(+)
>> >  create mode 100644 drivers/pinctrl/mediatek/pinctrl-mt7623.c
>>
>> [..]
>>
>> > +void mtk_rmw(struct udevice *dev, u32 reg, u32 mask, u32 set);
>>
>> What is this for? It has no comment and is an exported function. We
>> should not export things from drivers unless there is a good reason.
>
> This is a common 'read-modify-write' helper. I think we could export it
> in this shared header?

OK I see, fair enough. Please add a comment to the function.

Regards,
Simon

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

* [U-Boot] [PATCH v2 06/18] clk: MediaTek: add clock driver for MT7629 SoC.
  2018-10-25  6:37     ` Ryder Lee
@ 2018-11-03  6:08       ` Simon Glass
  0 siblings, 0 replies; 57+ messages in thread
From: Simon Glass @ 2018-11-03  6:08 UTC (permalink / raw)
  To: u-boot

Hi Ryder,

On 25 October 2018 at 00:37, Ryder Lee <ryder.lee@mediatek.com> wrote:
> On Wed, 2018-10-24 at 21:29 -0600, Simon Glass wrote:
>> Hi Ryder,
>>
>> On 12 October 2018 at 01:00, Ryder Lee <ryder.lee@mediatek.com> wrote:
>> > This patch adds clock modules for MediaTek SoCs:
>> > - Shared part: a common driver which contains the general operations
>> > for plls, muxes, dividers and gates so that we can reuse it in future.
>> >
>> > - Specific SoC part: the group of structures used to hold the hardware
>> > configuration for each SoC.
>> >
>> > We take MT7629 as an example to demonstrate how to implement driver if
>> > any other MediaTek chips would like to use it.
>> >
>> > Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
>> > ---
>> >  drivers/clk/Makefile              |   1 +
>> >  drivers/clk/mediatek/Makefile     |   6 +
>> >  drivers/clk/mediatek/clk-mt7629.c | 709 ++++++++++++++++++++++++++++++++++++++
>> >  drivers/clk/mediatek/clk-mtk.c    | 492 ++++++++++++++++++++++++++
>> >  drivers/clk/mediatek/clk-mtk.h    | 153 ++++++++
>> >  5 files changed, 1361 insertions(+)
>> >  create mode 100644 drivers/clk/mediatek/Makefile
>> >  create mode 100644 drivers/clk/mediatek/clk-mt7629.c
>> >  create mode 100644 drivers/clk/mediatek/clk-mtk.c
>> >  create mode 100644 drivers/clk/mediatek/clk-mtk.h
>>
>> Looks good except for a few things below.
>>
>> [..]
>>
>> > +const struct clk_ops mtk_clk_gate_ops = {
>> > +       .enable = mtk_clk_gate_enable,
>> > +       .disable = mtk_clk_gate_disable,
>> > +       .get_rate = mtk_clk_gate_get_rate,
>> > +};
>> > +
>> > +int mtk_clk_init(struct udevice *dev, const struct mtk_clk_tree *tree)
>> > +{
>> > +       struct mtk_clk_priv *priv = dev_get_priv(dev);
>> > +
>> > +       priv->base = dev_read_addr_ptr(dev);
>> > +       if (!priv->base)
>> > +               return -ENOENT;
>>
>> Why do you export these two functions? Devices should be probed in the
>> normal DM way.
>
> Yes, they are probed in the normal way. These functions are used by
> several clock blocks and MTK SoCs. so I put the common parts here to
> keep the code as clean as possible.

OK I see, thank you. How about a _common suffix on the function to
make this clear?

Regards,
Simon

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

* [U-Boot] [PATCH v2 17/18] spi: mtk_qspi: add qspi driver for MT7629 SoC
  2018-10-12  7:01 ` [U-Boot] [PATCH v2 17/18] spi: mtk_qspi: add qspi driver for MT7629 SoC Ryder Lee
  2018-10-25  3:30   ` Simon Glass
  2018-10-26  6:33   ` Jagan Teki
@ 2018-11-14  9:04   ` Jagan Teki
  2018-11-14 12:53     ` Guochun Mao
  2 siblings, 1 reply; 57+ messages in thread
From: Jagan Teki @ 2018-11-14  9:04 UTC (permalink / raw)
  To: u-boot

On Fri, Oct 12, 2018 at 12:46 PM Ryder Lee <ryder.lee@mediatek.com> wrote:
>
> From: Guochun Mao <guochun.mao@mediatek.com>
>
> This patch adds MT7629 qspi driver for accessing SPI NOR flash.
>
> Cc: Jagan Teki <jagan@openedev.com>
> Signed-off-by: Guochun Mao <guochun.mao@mediatek.com>
> ---
> change since v2:
> - Drop flash commands in the driver.
> ---
>  drivers/spi/Kconfig    |   7 +
>  drivers/spi/Makefile   |   1 +
>  drivers/spi/mtk_qspi.c | 359 +++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 367 insertions(+)
>  create mode 100644 drivers/spi/mtk_qspi.c
>
> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
> index 1df6876..f9cf4ba 100644
> --- a/drivers/spi/Kconfig
> +++ b/drivers/spi/Kconfig
> @@ -124,6 +124,13 @@ config MT7621_SPI
>           the SPI NOR flash on platforms embedding this Ralink / MediaTek
>           SPI core, like MT7621/7628/7688.
>
> +config MTK_QSPI
> +       bool "Mediatek QSPI driver"
> +       help
> +         Enable the Mediatek QSPI driver. This driver can be
> +         used to access the SPI NOR flash on platforms embedding this
> +         Mediatek QSPI IP core.
> +
>  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 7242ea7..e5a78f5 100644
> --- a/drivers/spi/Makefile
> +++ b/drivers/spi/Makefile
> @@ -33,6 +33,7 @@ obj-$(CONFIG_KIRKWOOD_SPI) += kirkwood_spi.o
>  obj-$(CONFIG_LPC32XX_SSP) += lpc32xx_ssp.o
>  obj-$(CONFIG_MPC8XX_SPI) += mpc8xx_spi.o
>  obj-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o
> +obj-$(CONFIG_MTK_QSPI) += mtk_qspi.o
>  obj-$(CONFIG_MT7621_SPI) += mt7621_spi.o
>  obj-$(CONFIG_MVEBU_A3700_SPI) += mvebu_a3700_spi.o
>  obj-$(CONFIG_MXC_SPI) += mxc_spi.o
> diff --git a/drivers/spi/mtk_qspi.c b/drivers/spi/mtk_qspi.c
> new file mode 100644
> index 0000000..b510733
> --- /dev/null
> +++ b/drivers/spi/mtk_qspi.c
> @@ -0,0 +1,359 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2018  MediaTek, Inc.
> + * Author : Guochun.Mao at mediatek.com
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <malloc.h>
> +#include <spi.h>
> +#include <asm/io.h>
> +#include <linux/iopoll.h>
> +#include <linux/ioport.h>
> +
> +/* Register Offset */
> +struct mtk_qspi_regs {
> +       u32 cmd;
> +       u32 cnt;
> +       u32 rdsr;
> +       u32 rdata;
> +       u32 radr[3];
> +       u32 wdata;
> +       u32 prgdata[6];
> +       u32 shreg[10];
> +       u32 cfg[2];
> +       u32 shreg10;
> +       u32 mode_mon;
> +       u32 status[4];
> +       u32 flash_time;
> +       u32 flash_cfg;
> +       u32 reserved_0[3];
> +       u32 sf_time;
> +       u32 pp_dw_data;
> +       u32 reserved_1;
> +       u32 delsel_0[2];
> +       u32 intrstus;
> +       u32 intren;
> +       u32 reserved_2;
> +       u32 cfg3;
> +       u32 reserved_3;
> +       u32 chksum;
> +       u32 aaicmd;
> +       u32 wrprot;
> +       u32 radr3;
> +       u32 dual;
> +       u32 delsel_1[3];
> +};
> +
> +struct mtk_qspi_platdata {
> +       fdt_addr_t reg_base;
> +       fdt_addr_t mem_base;
> +};
> +
> +struct mtk_qspi_priv {
> +       struct mtk_qspi_regs *regs;
> +       unsigned long *mem_base;
> +       u8 op;
> +       u8 tx[3]; /* only record max 3 bytes paras, when it's address. */
> +       u32 txlen; /* dout buffer length  - op code length */
> +       u8 *rx;
> +       u32 rxlen;
> +};
> +
> +#define MTK_QSPI_CMD_POLLINGREG_US 500000
> +#define MTK_QSPI_WRBUF_SIZE        256
> +#define MTK_QSPI_COMMAND_ENABLE    0x30
> +
> +/* NOR flash controller commands */
> +#define MTK_QSPI_RD_TRIGGER        BIT(0)
> +#define MTK_QSPI_READSTATUS        BIT(1)
> +#define MTK_QSPI_PRG_CMD           BIT(2)
> +#define MTK_QSPI_WR_TRIGGER        BIT(4)
> +#define MTK_QSPI_WRITESTATUS       BIT(5)
> +#define MTK_QSPI_AUTOINC           BIT(7)
> +
> +#define MTK_QSPI_MAX_RX_TX_SHIFT   0x6
> +#define MTK_QSPI_MAX_SHIFT         0x8
> +
> +#define MTK_QSPI_WR_BUF_ENABLE     0x1
> +#define MTK_QSPI_WR_BUF_DISABLE    0x0

All these bits look flash handling bit's , aren't ?

> +
> +static int mtk_qspi_execute_cmd(struct mtk_qspi_priv *priv, u8 cmd)
> +{
> +       u8 tmp;
> +       u8 val = cmd & ~MTK_QSPI_AUTOINC;
> +
> +       writeb(cmd, &priv->regs->cmd);
> +
> +       return readb_poll_timeout(&priv->regs->cmd, tmp, !(val & tmp),
> +                                 MTK_QSPI_CMD_POLLINGREG_US);
> +}
> +
> +static int mtk_qspi_tx_rx(struct mtk_qspi_priv *priv)
> +{
> +       int len = 1 + priv->txlen + priv->rxlen;
> +       int i, ret, idx;
> +
> +       if (len > MTK_QSPI_MAX_SHIFT)
> +               return -ERR_INVAL;
> +
> +       writeb(len * 8, &priv->regs->cnt);
> +
> +       /* start at PRGDATA5, go down to PRGDATA0 */
> +       idx = MTK_QSPI_MAX_RX_TX_SHIFT - 1;
> +
> +       /* opcode */
> +       writeb(priv->op, &priv->regs->prgdata[idx]);
> +       idx--;
> +
> +       /* program TX data */
> +       for (i = 0; i < priv->txlen; i++, idx--)
> +               writeb(priv->tx[i], &priv->regs->prgdata[idx]);
> +
> +       /* clear out rest of TX registers */
> +       while (idx >= 0) {
> +               writeb(0, &priv->regs->prgdata[idx]);
> +               idx--;
> +       }
> +
> +       ret = mtk_qspi_execute_cmd(priv, MTK_QSPI_PRG_CMD);

What does this execute do? does it intiate the controller register
based flash command or so?

Do you have Linux driver on the controller?

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

* [U-Boot] [PATCH v2 17/18] spi: mtk_qspi: add qspi driver for MT7629 SoC
  2018-11-14  9:04   ` Jagan Teki
@ 2018-11-14 12:53     ` Guochun Mao
  2018-11-21  9:38       ` Jagan Teki
  0 siblings, 1 reply; 57+ messages in thread
From: Guochun Mao @ 2018-11-14 12:53 UTC (permalink / raw)
  To: u-boot

On Wed, 2018-11-14 at 14:34 +0530, Jagan Teki wrote:
> On Fri, Oct 12, 2018 at 12:46 PM Ryder Lee <ryder.lee@mediatek.com> wrote:
> >
> > From: Guochun Mao <guochun.mao@mediatek.com>
> >
> > This patch adds MT7629 qspi driver for accessing SPI NOR flash.
> >
> > Cc: Jagan Teki <jagan@openedev.com>
> > Signed-off-by: Guochun Mao <guochun.mao@mediatek.com>
> > ---
> > change since v2:
> > - Drop flash commands in the driver.
> > ---
> >  drivers/spi/Kconfig    |   7 +
> >  drivers/spi/Makefile   |   1 +
> >  drivers/spi/mtk_qspi.c | 359 +++++++++++++++++++++++++++++++++++++++++++++++++
> >  3 files changed, 367 insertions(+)
> >  create mode 100644 drivers/spi/mtk_qspi.c
> >
> > diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
> > index 1df6876..f9cf4ba 100644
> > --- a/drivers/spi/Kconfig
> > +++ b/drivers/spi/Kconfig
> > @@ -124,6 +124,13 @@ config MT7621_SPI
> >           the SPI NOR flash on platforms embedding this Ralink / MediaTek
> >           SPI core, like MT7621/7628/7688.
> >
> > +config MTK_QSPI
> > +       bool "Mediatek QSPI driver"
> > +       help
> > +         Enable the Mediatek QSPI driver. This driver can be
> > +         used to access the SPI NOR flash on platforms embedding this
> > +         Mediatek QSPI IP core.
> > +
> >  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 7242ea7..e5a78f5 100644
> > --- a/drivers/spi/Makefile
> > +++ b/drivers/spi/Makefile
> > @@ -33,6 +33,7 @@ obj-$(CONFIG_KIRKWOOD_SPI) += kirkwood_spi.o
> >  obj-$(CONFIG_LPC32XX_SSP) += lpc32xx_ssp.o
> >  obj-$(CONFIG_MPC8XX_SPI) += mpc8xx_spi.o
> >  obj-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o
> > +obj-$(CONFIG_MTK_QSPI) += mtk_qspi.o
> >  obj-$(CONFIG_MT7621_SPI) += mt7621_spi.o
> >  obj-$(CONFIG_MVEBU_A3700_SPI) += mvebu_a3700_spi.o
> >  obj-$(CONFIG_MXC_SPI) += mxc_spi.o
> > diff --git a/drivers/spi/mtk_qspi.c b/drivers/spi/mtk_qspi.c
> > new file mode 100644
> > index 0000000..b510733
> > --- /dev/null
> > +++ b/drivers/spi/mtk_qspi.c
> > @@ -0,0 +1,359 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (c) 2018  MediaTek, Inc.
> > + * Author : Guochun.Mao at mediatek.com
> > + */
> > +
> > +#include <common.h>
> > +#include <dm.h>
> > +#include <malloc.h>
> > +#include <spi.h>
> > +#include <asm/io.h>
> > +#include <linux/iopoll.h>
> > +#include <linux/ioport.h>
> > +
> > +/* Register Offset */
> > +struct mtk_qspi_regs {
> > +       u32 cmd;
> > +       u32 cnt;
> > +       u32 rdsr;
> > +       u32 rdata;
> > +       u32 radr[3];
> > +       u32 wdata;
> > +       u32 prgdata[6];
> > +       u32 shreg[10];
> > +       u32 cfg[2];
> > +       u32 shreg10;
> > +       u32 mode_mon;
> > +       u32 status[4];
> > +       u32 flash_time;
> > +       u32 flash_cfg;
> > +       u32 reserved_0[3];
> > +       u32 sf_time;
> > +       u32 pp_dw_data;
> > +       u32 reserved_1;
> > +       u32 delsel_0[2];
> > +       u32 intrstus;
> > +       u32 intren;
> > +       u32 reserved_2;
> > +       u32 cfg3;
> > +       u32 reserved_3;
> > +       u32 chksum;
> > +       u32 aaicmd;
> > +       u32 wrprot;
> > +       u32 radr3;
> > +       u32 dual;
> > +       u32 delsel_1[3];
> > +};
> > +
> > +struct mtk_qspi_platdata {
> > +       fdt_addr_t reg_base;
> > +       fdt_addr_t mem_base;
> > +};
> > +
> > +struct mtk_qspi_priv {
> > +       struct mtk_qspi_regs *regs;
> > +       unsigned long *mem_base;
> > +       u8 op;
> > +       u8 tx[3]; /* only record max 3 bytes paras, when it's address. */
> > +       u32 txlen; /* dout buffer length  - op code length */
> > +       u8 *rx;
> > +       u32 rxlen;
> > +};
> > +
> > +#define MTK_QSPI_CMD_POLLINGREG_US 500000
> > +#define MTK_QSPI_WRBUF_SIZE        256
> > +#define MTK_QSPI_COMMAND_ENABLE    0x30
> > +
> > +/* NOR flash controller commands */
> > +#define MTK_QSPI_RD_TRIGGER        BIT(0)
> > +#define MTK_QSPI_READSTATUS        BIT(1)
> > +#define MTK_QSPI_PRG_CMD           BIT(2)
> > +#define MTK_QSPI_WR_TRIGGER        BIT(4)
> > +#define MTK_QSPI_WRITESTATUS       BIT(5)
> > +#define MTK_QSPI_AUTOINC           BIT(7)
> > +
> > +#define MTK_QSPI_MAX_RX_TX_SHIFT   0x6
> > +#define MTK_QSPI_MAX_SHIFT         0x8
> > +
> > +#define MTK_QSPI_WR_BUF_ENABLE     0x1
> > +#define MTK_QSPI_WR_BUF_DISABLE    0x0
> 
> All these bits look flash handling bit's , aren't ?
> 
> > +
> > +static int mtk_qspi_execute_cmd(struct mtk_qspi_priv *priv, u8 cmd)
> > +{
> > +       u8 tmp;
> > +       u8 val = cmd & ~MTK_QSPI_AUTOINC;
> > +
> > +       writeb(cmd, &priv->regs->cmd);
> > +
> > +       return readb_poll_timeout(&priv->regs->cmd, tmp, !(val & tmp),
> > +                                 MTK_QSPI_CMD_POLLINGREG_US);
> > +}
> > +
> > +static int mtk_qspi_tx_rx(struct mtk_qspi_priv *priv)
> > +{
> > +       int len = 1 + priv->txlen + priv->rxlen;
> > +       int i, ret, idx;
> > +
> > +       if (len > MTK_QSPI_MAX_SHIFT)
> > +               return -ERR_INVAL;
> > +
> > +       writeb(len * 8, &priv->regs->cnt);
> > +
> > +       /* start at PRGDATA5, go down to PRGDATA0 */
> > +       idx = MTK_QSPI_MAX_RX_TX_SHIFT - 1;
> > +
> > +       /* opcode */
> > +       writeb(priv->op, &priv->regs->prgdata[idx]);
> > +       idx--;
> > +
> > +       /* program TX data */
> > +       for (i = 0; i < priv->txlen; i++, idx--)
> > +               writeb(priv->tx[i], &priv->regs->prgdata[idx]);
> > +
> > +       /* clear out rest of TX registers */
> > +       while (idx >= 0) {
> > +               writeb(0, &priv->regs->prgdata[idx]);
> > +               idx--;
> > +       }
> > +
> > +       ret = mtk_qspi_execute_cmd(priv, MTK_QSPI_PRG_CMD);
> 
> What does this execute do? 
It send command to flash, and latch data if need.

> does it intiate the controller register
> based flash command or so?
No, it doesn't.

> 
> Do you have Linux driver on the controller?
Yes, it's drivers/mtd/spi-nor/mtk-quadspi.c

BR,
Guochun

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

* [U-Boot] [PATCH v2 17/18] spi: mtk_qspi: add qspi driver for MT7629 SoC
  2018-11-14 12:53     ` Guochun Mao
@ 2018-11-21  9:38       ` Jagan Teki
  2018-11-21 11:46         ` Guochun Mao
  0 siblings, 1 reply; 57+ messages in thread
From: Jagan Teki @ 2018-11-21  9:38 UTC (permalink / raw)
  To: u-boot

On Wed, Nov 14, 2018 at 6:23 PM Guochun Mao <guochun.mao@mediatek.com> wrote:
>
> On Wed, 2018-11-14 at 14:34 +0530, Jagan Teki wrote:
> > On Fri, Oct 12, 2018 at 12:46 PM Ryder Lee <ryder.lee@mediatek.com> wrote:
> > >
> > > From: Guochun Mao <guochun.mao@mediatek.com>
> > >
> > > This patch adds MT7629 qspi driver for accessing SPI NOR flash.
> > >
> > > Cc: Jagan Teki <jagan@openedev.com>
> > > Signed-off-by: Guochun Mao <guochun.mao@mediatek.com>
> > > ---
> > > change since v2:
> > > - Drop flash commands in the driver.
> > > ---
> > >  drivers/spi/Kconfig    |   7 +
> > >  drivers/spi/Makefile   |   1 +
> > >  drivers/spi/mtk_qspi.c | 359 +++++++++++++++++++++++++++++++++++++++++++++++++
> > >  3 files changed, 367 insertions(+)
> > >  create mode 100644 drivers/spi/mtk_qspi.c
> > >
> > > diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
> > > index 1df6876..f9cf4ba 100644
> > > --- a/drivers/spi/Kconfig
> > > +++ b/drivers/spi/Kconfig
> > > @@ -124,6 +124,13 @@ config MT7621_SPI
> > >           the SPI NOR flash on platforms embedding this Ralink / MediaTek
> > >           SPI core, like MT7621/7628/7688.
> > >
> > > +config MTK_QSPI
> > > +       bool "Mediatek QSPI driver"
> > > +       help
> > > +         Enable the Mediatek QSPI driver. This driver can be
> > > +         used to access the SPI NOR flash on platforms embedding this
> > > +         Mediatek QSPI IP core.
> > > +
> > >  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 7242ea7..e5a78f5 100644
> > > --- a/drivers/spi/Makefile
> > > +++ b/drivers/spi/Makefile
> > > @@ -33,6 +33,7 @@ obj-$(CONFIG_KIRKWOOD_SPI) += kirkwood_spi.o
> > >  obj-$(CONFIG_LPC32XX_SSP) += lpc32xx_ssp.o
> > >  obj-$(CONFIG_MPC8XX_SPI) += mpc8xx_spi.o
> > >  obj-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o
> > > +obj-$(CONFIG_MTK_QSPI) += mtk_qspi.o
> > >  obj-$(CONFIG_MT7621_SPI) += mt7621_spi.o
> > >  obj-$(CONFIG_MVEBU_A3700_SPI) += mvebu_a3700_spi.o
> > >  obj-$(CONFIG_MXC_SPI) += mxc_spi.o
> > > diff --git a/drivers/spi/mtk_qspi.c b/drivers/spi/mtk_qspi.c
> > > new file mode 100644
> > > index 0000000..b510733
> > > --- /dev/null
> > > +++ b/drivers/spi/mtk_qspi.c
> > > @@ -0,0 +1,359 @@
> > > +// SPDX-License-Identifier: GPL-2.0
> > > +/*
> > > + * Copyright (c) 2018  MediaTek, Inc.
> > > + * Author : Guochun.Mao at mediatek.com
> > > + */
> > > +
> > > +#include <common.h>
> > > +#include <dm.h>
> > > +#include <malloc.h>
> > > +#include <spi.h>
> > > +#include <asm/io.h>
> > > +#include <linux/iopoll.h>
> > > +#include <linux/ioport.h>
> > > +
> > > +/* Register Offset */
> > > +struct mtk_qspi_regs {
> > > +       u32 cmd;
> > > +       u32 cnt;
> > > +       u32 rdsr;
> > > +       u32 rdata;
> > > +       u32 radr[3];
> > > +       u32 wdata;
> > > +       u32 prgdata[6];
> > > +       u32 shreg[10];
> > > +       u32 cfg[2];
> > > +       u32 shreg10;
> > > +       u32 mode_mon;
> > > +       u32 status[4];
> > > +       u32 flash_time;
> > > +       u32 flash_cfg;
> > > +       u32 reserved_0[3];
> > > +       u32 sf_time;
> > > +       u32 pp_dw_data;
> > > +       u32 reserved_1;
> > > +       u32 delsel_0[2];
> > > +       u32 intrstus;
> > > +       u32 intren;
> > > +       u32 reserved_2;
> > > +       u32 cfg3;
> > > +       u32 reserved_3;
> > > +       u32 chksum;
> > > +       u32 aaicmd;
> > > +       u32 wrprot;
> > > +       u32 radr3;
> > > +       u32 dual;
> > > +       u32 delsel_1[3];
> > > +};
> > > +
> > > +struct mtk_qspi_platdata {
> > > +       fdt_addr_t reg_base;
> > > +       fdt_addr_t mem_base;
> > > +};
> > > +
> > > +struct mtk_qspi_priv {
> > > +       struct mtk_qspi_regs *regs;
> > > +       unsigned long *mem_base;
> > > +       u8 op;
> > > +       u8 tx[3]; /* only record max 3 bytes paras, when it's address. */
> > > +       u32 txlen; /* dout buffer length  - op code length */
> > > +       u8 *rx;
> > > +       u32 rxlen;
> > > +};
> > > +
> > > +#define MTK_QSPI_CMD_POLLINGREG_US 500000
> > > +#define MTK_QSPI_WRBUF_SIZE        256
> > > +#define MTK_QSPI_COMMAND_ENABLE    0x30
> > > +
> > > +/* NOR flash controller commands */
> > > +#define MTK_QSPI_RD_TRIGGER        BIT(0)
> > > +#define MTK_QSPI_READSTATUS        BIT(1)
> > > +#define MTK_QSPI_PRG_CMD           BIT(2)
> > > +#define MTK_QSPI_WR_TRIGGER        BIT(4)
> > > +#define MTK_QSPI_WRITESTATUS       BIT(5)
> > > +#define MTK_QSPI_AUTOINC           BIT(7)
> > > +
> > > +#define MTK_QSPI_MAX_RX_TX_SHIFT   0x6
> > > +#define MTK_QSPI_MAX_SHIFT         0x8
> > > +
> > > +#define MTK_QSPI_WR_BUF_ENABLE     0x1
> > > +#define MTK_QSPI_WR_BUF_DISABLE    0x0
> >
> > All these bits look flash handling bit's , aren't ?
> >
> > > +
> > > +static int mtk_qspi_execute_cmd(struct mtk_qspi_priv *priv, u8 cmd)
> > > +{
> > > +       u8 tmp;
> > > +       u8 val = cmd & ~MTK_QSPI_AUTOINC;
> > > +
> > > +       writeb(cmd, &priv->regs->cmd);
> > > +
> > > +       return readb_poll_timeout(&priv->regs->cmd, tmp, !(val & tmp),
> > > +                                 MTK_QSPI_CMD_POLLINGREG_US);
> > > +}
> > > +
> > > +static int mtk_qspi_tx_rx(struct mtk_qspi_priv *priv)
> > > +{
> > > +       int len = 1 + priv->txlen + priv->rxlen;
> > > +       int i, ret, idx;
> > > +
> > > +       if (len > MTK_QSPI_MAX_SHIFT)
> > > +               return -ERR_INVAL;
> > > +
> > > +       writeb(len * 8, &priv->regs->cnt);
> > > +
> > > +       /* start at PRGDATA5, go down to PRGDATA0 */
> > > +       idx = MTK_QSPI_MAX_RX_TX_SHIFT - 1;
> > > +
> > > +       /* opcode */
> > > +       writeb(priv->op, &priv->regs->prgdata[idx]);
> > > +       idx--;
> > > +
> > > +       /* program TX data */
> > > +       for (i = 0; i < priv->txlen; i++, idx--)
> > > +               writeb(priv->tx[i], &priv->regs->prgdata[idx]);
> > > +
> > > +       /* clear out rest of TX registers */
> > > +       while (idx >= 0) {
> > > +               writeb(0, &priv->regs->prgdata[idx]);
> > > +               idx--;
> > > +       }
> > > +
> > > +       ret = mtk_qspi_execute_cmd(priv, MTK_QSPI_PRG_CMD);
> >
> > What does this execute do?
> It send command to flash, and latch data if need.
>
> > does it intiate the controller register
> > based flash command or so?
> No, it doesn't.
>
> >
> > Do you have Linux driver on the controller?
> Yes, it's drivers/mtd/spi-nor/mtk-quadspi.c

This sounds more specific to flash controller rather than spi driver.
Can you try to write driver in mtd side itself, like Linux spi-nor.
use UCLASS_SPI_FLASH

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

* [U-Boot] [PATCH v2 17/18] spi: mtk_qspi: add qspi driver for MT7629 SoC
  2018-11-21  9:38       ` Jagan Teki
@ 2018-11-21 11:46         ` Guochun Mao
  2018-11-22  6:21           ` Jagan Teki
  0 siblings, 1 reply; 57+ messages in thread
From: Guochun Mao @ 2018-11-21 11:46 UTC (permalink / raw)
  To: u-boot

Hi Jagan,

On Wed, 2018-11-21 at 15:08 +0530, Jagan Teki wrote:

> > > > +static int mtk_qspi_tx_rx(struct mtk_qspi_priv *priv)
> > > > +{
> > > > +       int len = 1 + priv->txlen + priv->rxlen;
> > > > +       int i, ret, idx;
> > > > +
> > > > +       if (len > MTK_QSPI_MAX_SHIFT)
> > > > +               return -ERR_INVAL;
> > > > +
> > > > +       writeb(len * 8, &priv->regs->cnt);
> > > > +
> > > > +       /* start at PRGDATA5, go down to PRGDATA0 */
> > > > +       idx = MTK_QSPI_MAX_RX_TX_SHIFT - 1;
> > > > +
> > > > +       /* opcode */
> > > > +       writeb(priv->op, &priv->regs->prgdata[idx]);
> > > > +       idx--;
> > > > +
> > > > +       /* program TX data */
> > > > +       for (i = 0; i < priv->txlen; i++, idx--)
> > > > +               writeb(priv->tx[i], &priv->regs->prgdata[idx]);
> > > > +
> > > > +       /* clear out rest of TX registers */
> > > > +       while (idx >= 0) {
> > > > +               writeb(0, &priv->regs->prgdata[idx]);
> > > > +               idx--;
> > > > +       }
> > > > +
> > > > +       ret = mtk_qspi_execute_cmd(priv, MTK_QSPI_PRG_CMD);
> > >
> > > What does this execute do?
> > It send command to flash, and latch data if need.
> >
> > > does it intiate the controller register
> > > based flash command or so?
> > No, it doesn't.
> >
> > >
> > > Do you have Linux driver on the controller?
> > Yes, it's drivers/mtd/spi-nor/mtk-quadspi.c
> 
> This sounds more specific to flash controller rather than spi driver.
> Can you try to write driver in mtd side itself, like Linux spi-nor.
> use UCLASS_SPI_FLASH

Sorry, I'm a little confused.
There are many files(***qspi.c) those that used for accessing spi flash
under folder drivers/spi/.
However, there's no specific flash controller driver implemented under
drives/mtd, only common spi_flash framework. It's different with kernel.
It seems that we only need implement the spi control logic of
spi-flash-controller(this part not based on flash, it only do
data-xfer), and spi_flash framework will work well base on it.
Isn't that the purpose of this architecture?

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

* [U-Boot] [PATCH v2 17/18] spi: mtk_qspi: add qspi driver for MT7629 SoC
  2018-11-21 11:46         ` Guochun Mao
@ 2018-11-22  6:21           ` Jagan Teki
  2018-11-22  8:58             ` Guochun Mao
  0 siblings, 1 reply; 57+ messages in thread
From: Jagan Teki @ 2018-11-22  6:21 UTC (permalink / raw)
  To: u-boot

On Wed, Nov 21, 2018 at 5:16 PM Guochun Mao <guochun.mao@mediatek.com> wrote:
>
> Hi Jagan,
>
> On Wed, 2018-11-21 at 15:08 +0530, Jagan Teki wrote:
>
> > > > > +static int mtk_qspi_tx_rx(struct mtk_qspi_priv *priv)
> > > > > +{
> > > > > +       int len = 1 + priv->txlen + priv->rxlen;
> > > > > +       int i, ret, idx;
> > > > > +
> > > > > +       if (len > MTK_QSPI_MAX_SHIFT)
> > > > > +               return -ERR_INVAL;
> > > > > +
> > > > > +       writeb(len * 8, &priv->regs->cnt);
> > > > > +
> > > > > +       /* start at PRGDATA5, go down to PRGDATA0 */
> > > > > +       idx = MTK_QSPI_MAX_RX_TX_SHIFT - 1;
> > > > > +
> > > > > +       /* opcode */
> > > > > +       writeb(priv->op, &priv->regs->prgdata[idx]);
> > > > > +       idx--;
> > > > > +
> > > > > +       /* program TX data */
> > > > > +       for (i = 0; i < priv->txlen; i++, idx--)
> > > > > +               writeb(priv->tx[i], &priv->regs->prgdata[idx]);
> > > > > +
> > > > > +       /* clear out rest of TX registers */
> > > > > +       while (idx >= 0) {
> > > > > +               writeb(0, &priv->regs->prgdata[idx]);
> > > > > +               idx--;
> > > > > +       }
> > > > > +
> > > > > +       ret = mtk_qspi_execute_cmd(priv, MTK_QSPI_PRG_CMD);
> > > >
> > > > What does this execute do?
> > > It send command to flash, and latch data if need.
> > >
> > > > does it intiate the controller register
> > > > based flash command or so?
> > > No, it doesn't.
> > >
> > > >
> > > > Do you have Linux driver on the controller?
> > > Yes, it's drivers/mtd/spi-nor/mtk-quadspi.c
> >
> > This sounds more specific to flash controller rather than spi driver.
> > Can you try to write driver in mtd side itself, like Linux spi-nor.
> > use UCLASS_SPI_FLASH
>
> Sorry, I'm a little confused.
> There are many files(***qspi.c) those that used for accessing spi flash
> under folder drivers/spi/.
> However, there's no specific flash controller driver implemented under
> drives/mtd, only common spi_flash framework. It's different with kernel.
> It seems that we only need implement the spi control logic of
> spi-flash-controller(this part not based on flash, it only do
> data-xfer), and spi_flash framework will work well base on it.
> Isn't that the purpose of this architecture?

Understand your point, to be precise the driver may a fall in trouble
after sometime, if there is an additional flash specific features will
attach in future. ie reason few of flash controllers in drivers/spi
were unable to move further to add their features. and ie also reason
for your driver in Linux which resides in spi-nor.

You can directly write UCLASS_SPI_FLASH like sf_dataflash, I can help
if any issues with probing setup etc.

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

* [U-Boot] [PATCH v2 17/18] spi: mtk_qspi: add qspi driver for MT7629 SoC
  2018-11-22  6:21           ` Jagan Teki
@ 2018-11-22  8:58             ` Guochun Mao
  2018-11-23  5:43               ` Jagan Teki
  0 siblings, 1 reply; 57+ messages in thread
From: Guochun Mao @ 2018-11-22  8:58 UTC (permalink / raw)
  To: u-boot

On Thu, 2018-11-22 at 11:51 +0530, Jagan Teki wrote:
> On Wed, Nov 21, 2018 at 5:16 PM Guochun Mao <guochun.mao@mediatek.com> wrote:
> >
> > Hi Jagan,
> >
> > On Wed, 2018-11-21 at 15:08 +0530, Jagan Teki wrote:
> >
> > > > > > +static int mtk_qspi_tx_rx(struct mtk_qspi_priv *priv)
> > > > > > +{
> > > > > > +       int len = 1 + priv->txlen + priv->rxlen;
> > > > > > +       int i, ret, idx;
> > > > > > +
> > > > > > +       if (len > MTK_QSPI_MAX_SHIFT)
> > > > > > +               return -ERR_INVAL;
> > > > > > +
> > > > > > +       writeb(len * 8, &priv->regs->cnt);
> > > > > > +
> > > > > > +       /* start at PRGDATA5, go down to PRGDATA0 */
> > > > > > +       idx = MTK_QSPI_MAX_RX_TX_SHIFT - 1;
> > > > > > +
> > > > > > +       /* opcode */
> > > > > > +       writeb(priv->op, &priv->regs->prgdata[idx]);
> > > > > > +       idx--;
> > > > > > +
> > > > > > +       /* program TX data */
> > > > > > +       for (i = 0; i < priv->txlen; i++, idx--)
> > > > > > +               writeb(priv->tx[i], &priv->regs->prgdata[idx]);
> > > > > > +
> > > > > > +       /* clear out rest of TX registers */
> > > > > > +       while (idx >= 0) {
> > > > > > +               writeb(0, &priv->regs->prgdata[idx]);
> > > > > > +               idx--;
> > > > > > +       }
> > > > > > +
> > > > > > +       ret = mtk_qspi_execute_cmd(priv, MTK_QSPI_PRG_CMD);
> > > > >
> > > > > What does this execute do?
> > > > It send command to flash, and latch data if need.
> > > >
> > > > > does it intiate the controller register
> > > > > based flash command or so?
> > > > No, it doesn't.
> > > >
> > > > >
> > > > > Do you have Linux driver on the controller?
> > > > Yes, it's drivers/mtd/spi-nor/mtk-quadspi.c
> > >
> > > This sounds more specific to flash controller rather than spi driver.
> > > Can you try to write driver in mtd side itself, like Linux spi-nor.
> > > use UCLASS_SPI_FLASH
> >
> > Sorry, I'm a little confused.
> > There are many files(***qspi.c) those that used for accessing spi flash
> > under folder drivers/spi/.
> > However, there's no specific flash controller driver implemented under
> > drives/mtd, only common spi_flash framework. It's different with kernel.
> > It seems that we only need implement the spi control logic of
> > spi-flash-controller(this part not based on flash, it only do
> > data-xfer), and spi_flash framework will work well base on it.
> > Isn't that the purpose of this architecture?
> 
> Understand your point, to be precise the driver may a fall in trouble
> after sometime, if there is an additional flash specific features will
> attach in future. ie reason few of flash controllers in drivers/spi
> were unable to move further to add their features. and ie also reason
> for your driver in Linux which resides in spi-nor.
> 
> You can directly write UCLASS_SPI_FLASH like sf_dataflash, I can help
> if any issues with probing setup etc.

Hi Jagan,

Could you reconsider this driver?

The code can match our needs for a considerable time, it's simple and
doesn't disrupt current architecture.

If we switched to MTD_SPI_FLASH, there will inevitably be some
duplicated codes. The current version of code adopts the sf/spi
framework, it can guarantee compatibility and code reusability ratio.

If spi-mem or spi-nor was introduced to uboot in future, we can quickly
implement new version code.

Thanks.

BR,
Guochun

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

* [U-Boot] [PATCH v2 17/18] spi: mtk_qspi: add qspi driver for MT7629 SoC
  2018-11-22  8:58             ` Guochun Mao
@ 2018-11-23  5:43               ` Jagan Teki
  2018-11-23  8:24                 ` Guochun Mao
  0 siblings, 1 reply; 57+ messages in thread
From: Jagan Teki @ 2018-11-23  5:43 UTC (permalink / raw)
  To: u-boot

On Thu, Nov 22, 2018 at 2:29 PM Guochun Mao <guochun.mao@mediatek.com> wrote:
>
> On Thu, 2018-11-22 at 11:51 +0530, Jagan Teki wrote:
> > On Wed, Nov 21, 2018 at 5:16 PM Guochun Mao <guochun.mao@mediatek.com> wrote:
> > >
> > > Hi Jagan,
> > >
> > > On Wed, 2018-11-21 at 15:08 +0530, Jagan Teki wrote:
> > >
> > > > > > > +static int mtk_qspi_tx_rx(struct mtk_qspi_priv *priv)
> > > > > > > +{
> > > > > > > +       int len = 1 + priv->txlen + priv->rxlen;
> > > > > > > +       int i, ret, idx;
> > > > > > > +
> > > > > > > +       if (len > MTK_QSPI_MAX_SHIFT)
> > > > > > > +               return -ERR_INVAL;
> > > > > > > +
> > > > > > > +       writeb(len * 8, &priv->regs->cnt);
> > > > > > > +
> > > > > > > +       /* start at PRGDATA5, go down to PRGDATA0 */
> > > > > > > +       idx = MTK_QSPI_MAX_RX_TX_SHIFT - 1;
> > > > > > > +
> > > > > > > +       /* opcode */
> > > > > > > +       writeb(priv->op, &priv->regs->prgdata[idx]);
> > > > > > > +       idx--;
> > > > > > > +
> > > > > > > +       /* program TX data */
> > > > > > > +       for (i = 0; i < priv->txlen; i++, idx--)
> > > > > > > +               writeb(priv->tx[i], &priv->regs->prgdata[idx]);
> > > > > > > +
> > > > > > > +       /* clear out rest of TX registers */
> > > > > > > +       while (idx >= 0) {
> > > > > > > +               writeb(0, &priv->regs->prgdata[idx]);
> > > > > > > +               idx--;
> > > > > > > +       }
> > > > > > > +
> > > > > > > +       ret = mtk_qspi_execute_cmd(priv, MTK_QSPI_PRG_CMD);
> > > > > >
> > > > > > What does this execute do?
> > > > > It send command to flash, and latch data if need.
> > > > >
> > > > > > does it intiate the controller register
> > > > > > based flash command or so?
> > > > > No, it doesn't.
> > > > >
> > > > > >
> > > > > > Do you have Linux driver on the controller?
> > > > > Yes, it's drivers/mtd/spi-nor/mtk-quadspi.c
> > > >
> > > > This sounds more specific to flash controller rather than spi driver.
> > > > Can you try to write driver in mtd side itself, like Linux spi-nor.
> > > > use UCLASS_SPI_FLASH
> > >
> > > Sorry, I'm a little confused.
> > > There are many files(***qspi.c) those that used for accessing spi flash
> > > under folder drivers/spi/.
> > > However, there's no specific flash controller driver implemented under
> > > drives/mtd, only common spi_flash framework. It's different with kernel.
> > > It seems that we only need implement the spi control logic of
> > > spi-flash-controller(this part not based on flash, it only do
> > > data-xfer), and spi_flash framework will work well base on it.
> > > Isn't that the purpose of this architecture?
> >
> > Understand your point, to be precise the driver may a fall in trouble
> > after sometime, if there is an additional flash specific features will
> > attach in future. ie reason few of flash controllers in drivers/spi
> > were unable to move further to add their features. and ie also reason
> > for your driver in Linux which resides in spi-nor.
> >
> > You can directly write UCLASS_SPI_FLASH like sf_dataflash, I can help
> > if any issues with probing setup etc.
>
> Hi Jagan,
>
> Could you reconsider this driver?
>
> The code can match our needs for a considerable time, it's simple and
> doesn't disrupt current architecture.
>
> If we switched to MTD_SPI_FLASH, there will inevitably be some
> duplicated codes. The current version of code adopts the sf/spi
> framework, it can guarantee compatibility and code reusability ratio.
>
> If spi-mem or spi-nor was introduced to uboot in future, we can quickly
> implement new version code.

Thanks.

Applied to u-boot-spi/master

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

* [U-Boot] [PATCH v2 17/18] spi: mtk_qspi: add qspi driver for MT7629 SoC
  2018-11-23  5:43               ` Jagan Teki
@ 2018-11-23  8:24                 ` Guochun Mao
  0 siblings, 0 replies; 57+ messages in thread
From: Guochun Mao @ 2018-11-23  8:24 UTC (permalink / raw)
  To: u-boot

On Fri, 2018-11-23 at 11:13 +0530, Jagan Teki wrote:
> On Thu, Nov 22, 2018 at 2:29 PM Guochun Mao <guochun.mao@mediatek.com> wrote:
> >
> > On Thu, 2018-11-22 at 11:51 +0530, Jagan Teki wrote:
> > > On Wed, Nov 21, 2018 at 5:16 PM Guochun Mao <guochun.mao@mediatek.com> wrote:
> > > >
> > > > Hi Jagan,
> > > >
> > > > On Wed, 2018-11-21 at 15:08 +0530, Jagan Teki wrote:
> > > >
> > > > > > > > +static int mtk_qspi_tx_rx(struct mtk_qspi_priv *priv)
> > > > > > > > +{
> > > > > > > > +       int len = 1 + priv->txlen + priv->rxlen;
> > > > > > > > +       int i, ret, idx;
> > > > > > > > +
> > > > > > > > +       if (len > MTK_QSPI_MAX_SHIFT)
> > > > > > > > +               return -ERR_INVAL;
> > > > > > > > +
> > > > > > > > +       writeb(len * 8, &priv->regs->cnt);
> > > > > > > > +
> > > > > > > > +       /* start at PRGDATA5, go down to PRGDATA0 */
> > > > > > > > +       idx = MTK_QSPI_MAX_RX_TX_SHIFT - 1;
> > > > > > > > +
> > > > > > > > +       /* opcode */
> > > > > > > > +       writeb(priv->op, &priv->regs->prgdata[idx]);
> > > > > > > > +       idx--;
> > > > > > > > +
> > > > > > > > +       /* program TX data */
> > > > > > > > +       for (i = 0; i < priv->txlen; i++, idx--)
> > > > > > > > +               writeb(priv->tx[i], &priv->regs->prgdata[idx]);
> > > > > > > > +
> > > > > > > > +       /* clear out rest of TX registers */
> > > > > > > > +       while (idx >= 0) {
> > > > > > > > +               writeb(0, &priv->regs->prgdata[idx]);
> > > > > > > > +               idx--;
> > > > > > > > +       }
> > > > > > > > +
> > > > > > > > +       ret = mtk_qspi_execute_cmd(priv, MTK_QSPI_PRG_CMD);
> > > > > > >
> > > > > > > What does this execute do?
> > > > > > It send command to flash, and latch data if need.
> > > > > >
> > > > > > > does it intiate the controller register
> > > > > > > based flash command or so?
> > > > > > No, it doesn't.
> > > > > >
> > > > > > >
> > > > > > > Do you have Linux driver on the controller?
> > > > > > Yes, it's drivers/mtd/spi-nor/mtk-quadspi.c
> > > > >
> > > > > This sounds more specific to flash controller rather than spi driver.
> > > > > Can you try to write driver in mtd side itself, like Linux spi-nor.
> > > > > use UCLASS_SPI_FLASH
> > > >
> > > > Sorry, I'm a little confused.
> > > > There are many files(***qspi.c) those that used for accessing spi flash
> > > > under folder drivers/spi/.
> > > > However, there's no specific flash controller driver implemented under
> > > > drives/mtd, only common spi_flash framework. It's different with kernel.
> > > > It seems that we only need implement the spi control logic of
> > > > spi-flash-controller(this part not based on flash, it only do
> > > > data-xfer), and spi_flash framework will work well base on it.
> > > > Isn't that the purpose of this architecture?
> > >
> > > Understand your point, to be precise the driver may a fall in trouble
> > > after sometime, if there is an additional flash specific features will
> > > attach in future. ie reason few of flash controllers in drivers/spi
> > > were unable to move further to add their features. and ie also reason
> > > for your driver in Linux which resides in spi-nor.
> > >
> > > You can directly write UCLASS_SPI_FLASH like sf_dataflash, I can help
> > > if any issues with probing setup etc.
> >
> > Hi Jagan,
> >
> > Could you reconsider this driver?
> >
> > The code can match our needs for a considerable time, it's simple and
> > doesn't disrupt current architecture.
> >
> > If we switched to MTD_SPI_FLASH, there will inevitably be some
> > duplicated codes. The current version of code adopts the sf/spi
> > framework, it can guarantee compatibility and code reusability ratio.
> >
> > If spi-mem or spi-nor was introduced to uboot in future, we can quickly
> > implement new version code.
> 
> Thanks.
> 
> Applied to u-boot-spi/master

Thanks for your great effort for the review.

Guochun

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

end of thread, other threads:[~2018-11-23  8:24 UTC | newest]

Thread overview: 57+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-10-12  7:00 [U-Boot] [PATCH v2 00/18] Add U-Boot support for MediaTek SoCs - MT7623n & MT7629 Ryder Lee
2018-10-12  7:00 ` [U-Boot] [PATCH v2 01/18] tools: MediaTek: add MTK boot header generation to mkimage Ryder Lee
2018-10-25  3:29   ` Simon Glass
2018-10-25 13:11     ` Ryder Lee
2018-10-12  7:00 ` [U-Boot] [PATCH v2 02/18] arm: dts: MediaTek: add device tree for MT7629 Ryder Lee
2018-10-25  3:29   ` Simon Glass
2018-10-12  7:00 ` [U-Boot] [PATCH v2 03/18] arm: dts: MediaTek: add device tree for MT7623 Ryder Lee
2018-10-25  3:29   ` Simon Glass
2018-10-12  7:00 ` [U-Boot] [PATCH v2 04/18] arm: MediaTek: add basic support for MT7629 boards Ryder Lee
2018-10-25  3:29   ` Simon Glass
2018-10-25  6:44     ` Ryder Lee
2018-10-12  7:00 ` [U-Boot] [PATCH v2 05/18] arm: MediaTek: add basic support for MT7623 boards Ryder Lee
2018-10-25  3:29   ` Simon Glass
2018-10-25  6:40     ` Ryder Lee
2018-10-12  7:00 ` [U-Boot] [PATCH v2 06/18] clk: MediaTek: add clock driver for MT7629 SoC Ryder Lee
2018-10-25  3:29   ` Simon Glass
2018-10-25  6:37     ` Ryder Lee
2018-11-03  6:08       ` Simon Glass
2018-10-12  7:00 ` [U-Boot] [PATCH v2 07/18] clk: MediaTek: add clock driver for MT7623 SoC Ryder Lee
2018-10-25  3:29   ` Simon Glass
2018-10-12  7:00 ` [U-Boot] [PATCH v2 08/18] timer: MediaTek: add timer driver for MediaTek SoCs Ryder Lee
2018-10-25  3:29   ` Simon Glass
2018-10-12  7:00 ` [U-Boot] [PATCH v2 09/18] watchdog: MediaTek: add watchdog " Ryder Lee
2018-10-25  3:29   ` Simon Glass
2018-10-12  7:00 ` [U-Boot] [PATCH v2 10/18] pinctrl: MediaTek: add pinctrl driver for MT7629 SoC Ryder Lee
2018-10-25  3:29   ` Simon Glass
2018-10-25  6:08     ` Ryder Lee
2018-11-03  6:08       ` Simon Glass
2018-10-12  7:01 ` [U-Boot] [PATCH v2 11/18] pinctrl: MediaTek: add pinctrl driver for MT7623 SoC Ryder Lee
2018-10-25  3:29   ` Simon Glass
2018-10-25  6:13     ` Ryder Lee
2018-11-03  6:08       ` Simon Glass
2018-10-12  7:01 ` [U-Boot] [PATCH v2 12/18] power domain: MediaTek: add power domain driver for MT7629 SoC Ryder Lee
2018-10-25  3:29   ` Simon Glass
2018-10-12  7:01 ` [U-Boot] [PATCH v2 13/18] power domain: MediaTek: add power domain driver for MT7623 SoC Ryder Lee
2018-10-25  3:30   ` Simon Glass
2018-10-12  7:01 ` [U-Boot] [PATCH v2 14/18] serial: 16550: allow the driver to support MediaTek serial Ryder Lee
2018-10-25  3:30   ` Simon Glass
2018-10-12  7:01 ` [U-Boot] [PATCH v2 15/18] ram: MediaTek: add DDR3 driver for MT7629 SoC Ryder Lee
2018-10-25  3:30   ` Simon Glass
2018-10-25  9:38     ` Ryder Lee
2018-10-26 16:53       ` Simon Glass
2018-10-12  7:01 ` [U-Boot] [PATCH v2 16/18] mmc: mtk-sd: add SD/MMC host controller driver for MT7623 SoC Ryder Lee
2018-10-25  3:30   ` Simon Glass
2018-10-12  7:01 ` [U-Boot] [PATCH v2 17/18] spi: mtk_qspi: add qspi driver for MT7629 SoC Ryder Lee
2018-10-25  3:30   ` Simon Glass
2018-10-26  6:33   ` Jagan Teki
2018-11-14  9:04   ` Jagan Teki
2018-11-14 12:53     ` Guochun Mao
2018-11-21  9:38       ` Jagan Teki
2018-11-21 11:46         ` Guochun Mao
2018-11-22  6:21           ` Jagan Teki
2018-11-22  8:58             ` Guochun Mao
2018-11-23  5:43               ` Jagan Teki
2018-11-23  8:24                 ` Guochun Mao
2018-10-12  7:01 ` [U-Boot] [PATCH v2 18/18] MAINTAINERS: add an entry for MediaTek Ryder Lee
2018-10-25  3:30   ` Simon Glass

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.