summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS20
-rw-r--r--Makefile22
-rw-r--r--arch/Kconfig1
-rw-r--r--arch/arm/Kconfig16
-rw-r--r--arch/arm/Makefile1
-rw-r--r--arch/arm/cpu/armv7/start.S9
-rw-r--r--arch/arm/dts/Makefile7
-rw-r--r--arch/arm/dts/am335x-chiliboard-u-boot.dtsi11
-rw-r--r--arch/arm/dts/am335x-chiliboard.dts200
-rw-r--r--arch/arm/dts/am335x-chilisom.dtsi178
-rw-r--r--arch/arm/dts/mt7623.dtsi255
-rw-r--r--arch/arm/dts/mt7623n-bananapi-bpi-r2.dts207
-rw-r--r--arch/arm/dts/mt7629-rfb-u-boot.dtsi24
-rw-r--r--arch/arm/dts/mt7629-rfb.dts70
-rw-r--r--arch/arm/dts/mt7629.dtsi244
-rw-r--r--arch/arm/include/asm/arch-mediatek/gpio.h9
-rw-r--r--arch/arm/include/asm/arch-mediatek/misc.h17
-rw-r--r--arch/arm/mach-k3/Makefile2
-rw-r--r--arch/arm/mach-k3/lowlevel_init.S20
-rw-r--r--arch/arm/mach-mediatek/Kconfig39
-rw-r--r--arch/arm/mach-mediatek/Makefile7
-rw-r--r--arch/arm/mach-mediatek/cpu.c34
-rw-r--r--arch/arm/mach-mediatek/init.h11
-rw-r--r--arch/arm/mach-mediatek/mt7623/Makefile4
-rw-r--r--arch/arm/mach-mediatek/mt7623/init.c54
-rw-r--r--arch/arm/mach-mediatek/mt7623/lowlevel_init.S22
-rw-r--r--arch/arm/mach-mediatek/mt7623/preloader.h99
-rw-r--r--arch/arm/mach-mediatek/mt7629/Makefile4
-rw-r--r--arch/arm/mach-mediatek/mt7629/init.c128
-rw-r--r--arch/arm/mach-mediatek/mt7629/lowlevel_init.S50
-rw-r--r--arch/arm/mach-mediatek/spl.c43
-rw-r--r--arch/arm/mach-sunxi/Kconfig2
-rw-r--r--arch/arm/mach-sunxi/dram_sun8i_a33.c2
-rw-r--r--arch/nds32/cpu/n1213/start.S51
-rw-r--r--arch/powerpc/include/asm/spl.h3
-rw-r--r--arch/riscv/Kconfig34
-rw-r--r--arch/riscv/Makefile20
-rw-r--r--arch/riscv/config.mk7
-rw-r--r--arch/riscv/cpu/ax25/Kconfig7
-rw-r--r--arch/riscv/cpu/ax25/Makefile1
-rw-r--r--arch/riscv/cpu/ax25/cache.c95
-rw-r--r--arch/riscv/cpu/ax25/cpu.c4
-rw-r--r--arch/riscv/cpu/cpu.c6
-rw-r--r--arch/riscv/cpu/qemu/cpu.c2
-rw-r--r--arch/riscv/cpu/start.S346
-rw-r--r--arch/riscv/dts/Makefile1
-rw-r--r--arch/riscv/dts/ae350.dts107
-rw-r--r--arch/riscv/dts/ae350_32.dts229
-rw-r--r--arch/riscv/dts/ae350_64.dts229
-rw-r--r--arch/riscv/include/asm/barrier.h67
-rw-r--r--arch/riscv/include/asm/cache.h3
-rw-r--r--arch/riscv/include/asm/io.h48
-rw-r--r--arch/riscv/include/asm/posix_types.h6
-rw-r--r--arch/riscv/include/asm/types.h4
-rw-r--r--arch/riscv/lib/bootm.c97
-rw-r--r--arch/riscv/lib/cache.c36
-rw-r--r--arch/riscv/lib/interrupts.c31
-rw-r--r--arch/riscv/lib/setjmp.S2
-rw-r--r--arch/sandbox/cpu/eth-raw-os.c9
-rw-r--r--arch/sandbox/cpu/os.c115
-rw-r--r--arch/sandbox/cpu/spl.c31
-rw-r--r--arch/sandbox/cpu/start.c19
-rw-r--r--arch/sandbox/cpu/u-boot-spl.lds2
-rw-r--r--arch/sandbox/include/asm/handoff.h18
-rw-r--r--arch/sandbox/include/asm/state.h8
-rw-r--r--board/AndesTech/ax25-ae350/MAINTAINERS2
-rw-r--r--board/amlogic/odroid-c2/MAINTAINERS1
-rw-r--r--board/amlogic/p212/MAINTAINERS2
-rw-r--r--board/armltd/integrator/README4
-rw-r--r--board/emulation/qemu-riscv/Kconfig2
-rw-r--r--board/emulation/qemu-riscv/qemu-riscv.c73
-rw-r--r--board/grinn/chiliboard/board.c61
-rw-r--r--board/mediatek/mt7623/Kconfig13
-rw-r--r--board/mediatek/mt7623/MAINTAINERS7
-rw-r--r--board/mediatek/mt7623/Makefile3
-rw-r--r--board/mediatek/mt7623/mt7623_rfb.c16
-rw-r--r--board/mediatek/mt7629/Kconfig17
-rw-r--r--board/mediatek/mt7629/MAINTAINERS7
-rw-r--r--board/mediatek/mt7629/Makefile3
-rw-r--r--board/mediatek/mt7629/mt7629_rfb.c16
-rw-r--r--board/sandbox/README.sandbox14
-rw-r--r--cmd/Makefile1
-rw-r--r--cmd/bootmenu.c5
-rw-r--r--cmd/host.c5
-rw-r--r--cmd/sb.c65
-rw-r--r--common/Kconfig84
-rw-r--r--common/Makefile7
-rw-r--r--common/bloblist.c239
-rw-r--r--common/board_f.c49
-rw-r--r--common/console.c7
-rw-r--r--common/image.c1
-rw-r--r--common/init/Makefile1
-rw-r--r--common/init/handoff.c47
-rw-r--r--common/spl/Kconfig95
-rw-r--r--common/spl/spl.c135
-rw-r--r--common/usb.c14
-rw-r--r--common/usb_hub.c16
-rw-r--r--common/usb_kbd.c4
-rw-r--r--common/usb_storage.c34
-rw-r--r--configs/a25-ae350_32_defconfig (renamed from configs/ax25-ae350_defconfig)3
-rw-r--r--configs/am335x_evm_defconfig3
-rw-r--r--configs/ax25-ae350_64_defconfig37
-rw-r--r--configs/chiliboard_defconfig12
-rw-r--r--configs/mt7623n_bpir2_defconfig54
-rw-r--r--configs/mt7629_rfb_defconfig73
-rw-r--r--configs/qemu-riscv32_defconfig5
-rw-r--r--configs/qemu-riscv64_defconfig7
-rw-r--r--configs/sandbox_spl_defconfig1
-rw-r--r--configs/vexpress_aemv8a_dram_defconfig2
-rw-r--r--configs/vexpress_aemv8a_juno_defconfig2
-rw-r--r--configs/vexpress_aemv8a_semi_defconfig2
-rw-r--r--configs/vexpress_ca15_tc2_defconfig2
-rw-r--r--configs/vexpress_ca5x2_defconfig2
-rw-r--r--configs/vexpress_ca9x4_defconfig2
-rw-r--r--doc/README.bloblist82
-rw-r--r--doc/README.distro3
-rw-r--r--doc/README.mediatek221
-rw-r--r--doc/README.trace2
-rw-r--r--drivers/Makefile11
-rw-r--r--drivers/clk/Makefile1
-rw-r--r--drivers/clk/mediatek/Makefile7
-rw-r--r--drivers/clk/mediatek/clk-mt7623.c870
-rw-r--r--drivers/clk/mediatek/clk-mt7629.c709
-rw-r--r--drivers/clk/mediatek/clk-mtk.c493
-rw-r--r--drivers/clk/mediatek/clk-mtk.h194
-rw-r--r--drivers/mmc/Kconfig15
-rw-r--r--drivers/mmc/Makefile1
-rw-r--r--drivers/mmc/mtk-sd.c1394
-rw-r--r--drivers/mmc/sunxi_mmc.c19
-rw-r--r--drivers/net/sun8i_emac.c34
-rw-r--r--drivers/pinctrl/Kconfig1
-rw-r--r--drivers/pinctrl/Makefile1
-rw-r--r--drivers/pinctrl/mediatek/Kconfig15
-rw-r--r--drivers/pinctrl/mediatek/Makefile7
-rw-r--r--drivers/pinctrl/mediatek/pinctrl-mt7623.c1284
-rw-r--r--drivers/pinctrl/mediatek/pinctrl-mt7629.c409
-rw-r--r--drivers/pinctrl/mediatek/pinctrl-mtk-common.c553
-rw-r--r--drivers/pinctrl/mediatek/pinctrl-mtk-common.h184
-rw-r--r--drivers/power/domain/Kconfig7
-rw-r--r--drivers/power/domain/Makefile1
-rw-r--r--drivers/power/domain/mtk-power-domain.c406
-rw-r--r--drivers/ram/Makefile1
-rw-r--r--drivers/ram/mediatek/Makefile7
-rw-r--r--drivers/ram/mediatek/ddr3-mt7629.c766
-rw-r--r--drivers/serial/Kconfig20
-rw-r--r--drivers/serial/Makefile1
-rw-r--r--drivers/serial/serial_mtk.c268
-rw-r--r--drivers/timer/Kconfig7
-rw-r--r--drivers/timer/Makefile1
-rw-r--r--drivers/timer/mtk_timer.c85
-rw-r--r--drivers/usb/Kconfig5
-rw-r--r--drivers/usb/common/Makefile2
-rw-r--r--drivers/usb/dwc3/core.c2
-rw-r--r--drivers/usb/dwc3/core.h2
-rw-r--r--drivers/usb/eth/usb_ether.c2
-rw-r--r--drivers/usb/gadget/ci_udc.c2
-rw-r--r--drivers/usb/gadget/ether.c8
-rw-r--r--drivers/usb/host/Makefile4
-rw-r--r--drivers/usb/host/dwc2.c12
-rw-r--r--drivers/usb/host/ehci-atmel.c2
-rw-r--r--drivers/usb/host/ehci-fsl.c12
-rw-r--r--drivers/usb/host/ehci-hcd.c12
-rw-r--r--drivers/usb/host/ehci-marvell.c4
-rw-r--r--drivers/usb/host/ehci-mx6.c2
-rw-r--r--drivers/usb/host/ehci-pci.c8
-rw-r--r--drivers/usb/host/ehci-vf.c2
-rw-r--r--drivers/usb/host/ohci-hcd.c10
-rw-r--r--drivers/usb/host/ohci.h4
-rw-r--r--drivers/usb/host/xhci-dwc3.c2
-rw-r--r--drivers/usb/host/xhci-fsl.c4
-rw-r--r--drivers/usb/host/xhci-mem.c6
-rw-r--r--drivers/usb/host/xhci.c12
-rw-r--r--drivers/usb/host/xhci.h2
-rw-r--r--drivers/usb/musb-new/musb_uboot.c12
-rw-r--r--drivers/usb/musb-new/omap2430.c4
-rw-r--r--drivers/usb/musb-new/ti-musb.c4
-rw-r--r--drivers/usb/musb-new/usb-compat.h2
-rw-r--r--drivers/video/vidconsole-uclass.c8
-rw-r--r--drivers/watchdog/Kconfig8
-rw-r--r--drivers/watchdog/Makefile1
-rw-r--r--drivers/watchdog/mtk_wdt.c135
-rw-r--r--dts/Makefile2
-rw-r--r--include/asm-generic/global_data.h7
-rw-r--r--include/bloblist.h195
-rw-r--r--include/common.h5
-rw-r--r--include/config_distro_bootcmd.h21
-rw-r--r--include/configs/am65x_evm.h2
-rw-r--r--include/configs/da850evm.h3
-rw-r--r--include/configs/edminiv2.h1
-rw-r--r--include/configs/km/km_arm.h1
-rw-r--r--include/configs/mt7623.h56
-rw-r--r--include/configs/mt7629.h57
-rw-r--r--include/configs/mv-common.h1
-rw-r--r--include/configs/qemu-riscv.h28
-rw-r--r--include/configs/vexpress_common.h2
-rw-r--r--include/dm/ofnode.h10
-rw-r--r--include/dt-bindings/clock/mt7623-clk.h413
-rw-r--r--include/dt-bindings/clock/mt7629-clk.h206
-rw-r--r--include/dt-bindings/power/mt7623-power.h19
-rw-r--r--include/dt-bindings/power/mt7629-power.h13
-rw-r--r--include/environment/ti/boot.h4
-rw-r--r--include/handoff.h36
-rw-r--r--include/image.h1
-rw-r--r--include/log.h20
-rw-r--r--include/spl.h41
-rw-r--r--include/test/suites.h1
-rw-r--r--include/usb.h12
-rw-r--r--scripts/Makefile.spl11
-rw-r--r--scripts/config_whitelist.txt2
-rw-r--r--test/Makefile1
-rw-r--r--test/bloblist.c187
-rw-r--r--test/cmd_ut.c3
-rw-r--r--test/dm/sf.c2
-rw-r--r--test/dm/video.c4
-rwxr-xr-xtest/fs/fs-test.sh14
-rwxr-xr-xtest/py/tests/test_fit.py12
-rw-r--r--test/py/tests/test_handoff.py15
-rw-r--r--test/py/tests/test_ofplatdata.py31
-rw-r--r--test/py/tests/test_vboot.py2
-rw-r--r--test/py/u_boot_console_base.py2
-rw-r--r--test/py/u_boot_console_sandbox.py18
-rwxr-xr-xtest/run2
-rw-r--r--tools/.gitignore1
-rw-r--r--tools/Makefile1
-rw-r--r--tools/file2include.c1
-rw-r--r--tools/mtk_image.c749
-rw-r--r--tools/mtk_image.h199
227 files changed, 14813 insertions, 683 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index abdb6dcdb5..214629e283 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -158,6 +158,26 @@ 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: doc/README.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/mtk_image.c
+F: tools/mtk_image.h
+N: mediatek
+
ARM OWL
M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
S: Maintained
diff --git a/Makefile b/Makefile
index aeb1c1455b..a4b1d1db52 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:"%"=%)
@@ -1361,6 +1363,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)
+spl/u-boot-spl-mtk.bin: spl/u-boot-spl
+
+u-boot-mtk.bin: u-boot.dtb u-boot.img spl/u-boot-spl-mtk.bin FORCE
+ $(call if_changed,binman)
+else
+MKIMAGEFLAGS_u-boot-mtk.bin = -T mtk_image \
+ -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/arch/Kconfig b/arch/Kconfig
index 9fdd2f7e66..947070fdd3 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -91,6 +91,7 @@ config SANDBOX
select SPI
select SUPPORT_OF_CONTROL
imply BITREVERSE
+ select BLOBLIST
imply CMD_DM
imply CMD_GETTIME
imply CMD_HASH
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index f5d4d39683..96eadb6fd6 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -664,6 +664,20 @@ 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 BINMAN
+ 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 developed by MediaTek Inc.
+ Please refer to doc/README.mediatek for more information.
+
config ARCH_LPC32XX
bool "NXP LPC32xx platform"
select CPU_ARM926EJS
@@ -1449,6 +1463,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 4b6c5e1935..c38ef3cb69 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/cpu/armv7/start.S b/arch/arm/cpu/armv7/start.S
index 81edec01bf..0cb6dd39cc 100644
--- a/arch/arm/cpu/armv7/start.S
+++ b/arch/arm/cpu/armv7/start.S
@@ -205,6 +205,15 @@ ENTRY(cpu_init_cp15)
mov r2, r3, lsl #4 @ shift variant field for combined value
orr r2, r4, r2 @ r2 has combined CPU variant + revision
+/* Early stack for ERRATA that needs into call C code */
+#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
+ ldr r0, =(CONFIG_SPL_STACK)
+#else
+ ldr r0, =(CONFIG_SYS_INIT_SP_ADDR)
+#endif
+ bic r0, r0, #7 /* 8-byte alignment for ABI compliance */
+ mov sp, r0
+
#ifdef CONFIG_ARM_ERRATA_798870
cmp r2, #0x30 @ Applies to lower than R3p0
bge skip_errata_798870 @ skip if not affected rev
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 1fa2f2d8dc..d8be3a30dc 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -188,7 +188,8 @@ dtb-$(CONFIG_AM33XX) += am335x-boneblack.dtb am335x-bone.dtb \
am335x-icev2.dtb \
am335x-pxm50.dtb \
am335x-rut.dtb \
- am335x-pdu001.dtb
+ am335x-pdu001.dtb \
+ am335x-chiliboard.dtb
dtb-$(CONFIG_AM43XX) += am437x-gp-evm.dtb am437x-sk-evm.dtb \
am43x-epos-evm.dtb \
am437x-idk-evm.dtb \
@@ -563,6 +564,10 @@ dtb-$(CONFIG_TARGET_STM32MP1) += \
dtb-$(CONFIG_SOC_K3_AM6) += k3-am654-base-board.dtb k3-am654-r5-base-board.dtb
+dtb-$(CONFIG_ARCH_MEDIATEK) += \
+ mt7623n-bananapi-bpi-r2.dtb \
+ mt7629-rfb.dtb
+
targets += $(dtb-y)
# Add any required device tree compiler flags here
diff --git a/arch/arm/dts/am335x-chiliboard-u-boot.dtsi b/arch/arm/dts/am335x-chiliboard-u-boot.dtsi
new file mode 100644
index 0000000000..4f9d308039
--- /dev/null
+++ b/arch/arm/dts/am335x-chiliboard-u-boot.dtsi
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0+ or X11
+/*
+ * Copyright (C) 2018 Grinn Sp. z o.o. -- http://www.grinn-global.com/
+ * Author: Marcin Niestroj <m.niestroj@grinn-global.com>
+ */
+
+/ {
+ chosen {
+ stdout-path = &uart0;
+ };
+};
diff --git a/arch/arm/dts/am335x-chiliboard.dts b/arch/arm/dts/am335x-chiliboard.dts
new file mode 100644
index 0000000000..59431b2359
--- /dev/null
+++ b/arch/arm/dts/am335x-chiliboard.dts
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2015 Jablotron s.r.o. -- http://www.jablotron.com/
+ * Author: Rostislav Lisovy <lisovy@jablotron.cz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+#include "am335x-chilisom.dtsi"
+
+/ {
+ model = "AM335x Chiliboard";
+ compatible = "grinn,am335x-chiliboard", "grinn,am335x-chilisom",
+ "ti,am33xx";
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&led_gpio_pins>;
+
+ led0 {
+ label = "led0";
+ gpios = <&gpio3 7 GPIO_ACTIVE_LOW>;
+ default-state = "keep";
+ linux,default-trigger = "heartbeat";
+ };
+
+ led1 {
+ label = "led1";
+ gpios = <&gpio3 8 GPIO_ACTIVE_LOW>;
+ default-state = "keep";
+ };
+ };
+};
+
+&am33xx_pinmux {
+ uart0_pins: pinmux_uart0_pins {
+ pinctrl-single,pins = <
+ AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0) /* uart0_rxd.uart0_rxd */
+ AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */
+ >;
+ };
+
+ cpsw_default: cpsw_default {
+ pinctrl-single,pins = <
+ /* Slave 1 */
+ AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_crs.rmii1_crs */
+ AM33XX_IOPAD(0x910, PIN_INPUT_PULLUP | MUX_MODE1) /* mii1_rxerr.rmii1_rxerr */
+ AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_txen.rmii1_txen */
+ AM33XX_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_txd1.rmii1_txd1 */
+ AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_txd0.rmii1_txd0 */
+ AM33XX_IOPAD(0x93c, PIN_INPUT_PULLUP | MUX_MODE1) /* mii1_rxd1.rmii1_rxd1 */
+ AM33XX_IOPAD(0x940, PIN_INPUT_PULLUP | MUX_MODE1) /* mii1_rxd0.rmii1_rxd0 */
+ AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE0) /* rmii1_ref_clk.rmii_ref_clk */
+ >;
+ };
+
+ cpsw_sleep: cpsw_sleep {
+ pinctrl-single,pins = <
+ /* Slave 1 reset value */
+ AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+ AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE7)
+ AM33XX_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7)
+ AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE7)
+ AM33XX_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE7)
+ AM33XX_IOPAD(0x928, PIN_INPUT_PULLDOWN | MUX_MODE7)
+ AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+ AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE7)
+ AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE7)
+ >;
+ };
+
+ davinci_mdio_default: davinci_mdio_default {
+ pinctrl-single,pins = <
+ /* mdio_data.mdio_data */
+ AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)
+ /* mdio_clk.mdio_clk */
+ AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0)
+ >;
+ };
+
+ davinci_mdio_sleep: davinci_mdio_sleep {
+ pinctrl-single,pins = <
+ /* MDIO reset value */
+ AM33XX_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7)
+ AM33XX_IOPAD(0x94c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+ >;
+ };
+
+ usb1_drvvbus: usb1_drvvbus {
+ pinctrl-single,pins = <
+ AM33XX_IOPAD(0xa34, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* usb1_drvvbus.usb1_drvvbus */
+ >;
+ };
+
+ sd_pins: pinmux_sd_card {
+ pinctrl-single,pins = <
+ AM33XX_IOPAD(0x8f0, PIN_INPUT | MUX_MODE0) /* mmc0_dat0.mmc0_dat0 */
+ AM33XX_IOPAD(0x8f4, PIN_INPUT | MUX_MODE0) /* mmc0_dat1.mmc0_dat1 */
+ AM33XX_IOPAD(0x8f8, PIN_INPUT | MUX_MODE0) /* mmc0_dat2.mmc0_dat2 */
+ AM33XX_IOPAD(0x8fc, PIN_INPUT | MUX_MODE0) /* mmc0_dat3.mmc0_dat3 */
+ AM33XX_IOPAD(0x900, PIN_INPUT | MUX_MODE0) /* mmc0_clk.mmc0_clk */
+ AM33XX_IOPAD(0x904, PIN_INPUT | MUX_MODE0) /* mmc0_cmd.mmc0_cmd */
+ AM33XX_IOPAD(0x960, PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */
+ >;
+ };
+
+ led_gpio_pins: led_gpio_pins {
+ pinctrl-single,pins = <
+ AM33XX_IOPAD(0x9e4, PIN_OUTPUT | MUX_MODE7) /* emu0.gpio3_7 */
+ AM33XX_IOPAD(0x9e8, PIN_OUTPUT | MUX_MODE7) /* emu1.gpio3_8 */
+ >;
+ };
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pins>;
+
+ status = "okay";
+};
+
+&ldo4_reg {
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+};
+
+/* Ethernet */
+&mac {
+ slaves = <1>;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&cpsw_default>;
+ pinctrl-1 = <&cpsw_sleep>;
+ status = "okay";
+};
+
+&davinci_mdio {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&davinci_mdio_default>;
+ pinctrl-1 = <&davinci_mdio_sleep>;
+ status = "okay";
+};
+
+&cpsw_emac0 {
+ phy_id = <&davinci_mdio>, <0>;
+ phy-mode = "rmii";
+};
+
+&phy_sel {
+ rmii-clock-ext;
+};
+
+/* USB */
+&usb {
+ status = "okay";
+};
+
+&usb_ctrl_mod {
+ status = "okay";
+};
+
+&usb1_phy {
+ status = "okay";
+};
+
+&usb1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb1_drvvbus>;
+
+ status = "okay";
+ dr_mode = "host";
+};
+
+&cppi41dma {
+ status = "okay";
+};
+
+/* microSD */
+&mmc1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&sd_pins>;
+ vmmc-supply = <&ldo4_reg>;
+ bus-width = <0x4>;
+ cd-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+};
+
+&tps {
+ interrupt-parent = <&intc>;
+ interrupts = <7>; /* NNMI */
+
+ charger {
+ status = "okay";
+ };
+
+ pwrbutton {
+ status = "okay";
+ };
+};
diff --git a/arch/arm/dts/am335x-chilisom.dtsi b/arch/arm/dts/am335x-chilisom.dtsi
new file mode 100644
index 0000000000..1b43ebd08b
--- /dev/null
+++ b/arch/arm/dts/am335x-chilisom.dtsi
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2015 Jablotron s.r.o. -- http://www.jablotron.com/
+ * Author: Rostislav Lisovy <lisovy@jablotron.cz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include "am33xx.dtsi"
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+ model = "Grinn AM335x ChiliSOM";
+ compatible = "grinn,am335x-chilisom", "ti,am33xx";
+
+ cpus {
+ cpu@0 {
+ cpu0-supply = <&dcdc2_reg>;
+ };
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0x80000000 0x20000000>; /* 512 MB */
+ };
+};
+
+&am33xx_pinmux {
+ pinctrl-names = "default";
+
+ i2c0_pins: pinmux_i2c0_pins {
+ pinctrl-single,pins = <
+ AM33XX_IOPAD(0x988, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_sda.i2c0_sda */
+ AM33XX_IOPAD(0x98c, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_scl.i2c0_scl */
+ >;
+ };
+
+ nandflash_pins: nandflash_pins {
+ pinctrl-single,pins = <
+ AM33XX_IOPAD(0x800, PIN_INPUT_PULLDOWN | MUX_MODE0) /* gpmc_ad0.gpmc_ad0 */
+ AM33XX_IOPAD(0x804, PIN_INPUT_PULLDOWN | MUX_MODE0) /* gpmc_ad1.gpmc_ad1 */
+ AM33XX_IOPAD(0x808, PIN_INPUT_PULLDOWN | MUX_MODE0) /* gpmc_ad2.gpmc_ad2 */
+ AM33XX_IOPAD(0x80c, PIN_INPUT_PULLDOWN | MUX_MODE0) /* gpmc_ad3.gpmc_ad3 */
+ AM33XX_IOPAD(0x810, PIN_INPUT_PULLDOWN | MUX_MODE0) /* gpmc_ad4.gpmc_ad4 */
+ AM33XX_IOPAD(0x814, PIN_INPUT_PULLDOWN | MUX_MODE0) /* gpmc_ad5.gpmc_ad5 */
+ AM33XX_IOPAD(0x818, PIN_INPUT_PULLDOWN | MUX_MODE0) /* gpmc_ad6.gpmc_ad6 */
+ AM33XX_IOPAD(0x81c, PIN_INPUT_PULLDOWN | MUX_MODE0) /* gpmc_ad7.gpmc_ad7 */
+
+ AM33XX_IOPAD(0x870, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_wait0.gpmc_wait0 */
+ AM33XX_IOPAD(0x87c, PIN_OUTPUT_PULLUP | MUX_MODE0) /* gpmc_csn0.gpmc_csn0 */
+ AM33XX_IOPAD(0x890, PIN_OUTPUT_PULLUP | MUX_MODE0) /* gpmc_advn_ale.gpmc_advn_ale */
+ AM33XX_IOPAD(0x894, PIN_OUTPUT_PULLUP | MUX_MODE0) /* gpmc_oen_ren.gpmc_oen_ren */
+ AM33XX_IOPAD(0x898, PIN_OUTPUT_PULLUP | MUX_MODE0) /* gpmc_wen.gpmc_wen */
+ AM33XX_IOPAD(0x89c, PIN_OUTPUT_PULLUP | MUX_MODE0) /* gpmc_be0n_cle.gpmc_be0n_cle */
+ >;
+ };
+};
+
+&i2c0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins>;
+
+ status = "okay";
+ clock-frequency = <400000>;
+
+ tps: tps@24 {
+ reg = <0x24>;
+ };
+
+};
+
+/include/ "tps65217.dtsi"
+
+&tps {
+ regulators {
+ dcdc1_reg: regulator@0 {
+ regulator-name = "vdds_dpr";
+ regulator-always-on;
+ };
+
+ dcdc2_reg: regulator@1 {
+ /* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
+ regulator-name = "vdd_mpu";
+ regulator-min-microvolt = <925000>;
+ regulator-max-microvolt = <1325000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ dcdc3_reg: regulator@2 {
+ /* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
+ regulator-name = "vdd_core";
+ regulator-min-microvolt = <925000>;
+ regulator-max-microvolt = <1150000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo1_reg: regulator@3 {
+ regulator-name = "vio,vrtc,vdds";
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo2_reg: regulator@4 {
+ regulator-name = "vdd_3v3aux";
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo3_reg: regulator@5 {
+ regulator-name = "vdd_1v8";
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo4_reg: regulator@6 {
+ regulator-name = "vdd_3v3d";
+ regulator-boot-on;
+ regulator-always-on;
+ };
+ };
+};
+
+&rtc {
+ system-power-controller;
+
+ pinctrl-0 = <&ext_wakeup>;
+ pinctrl-names = "default";
+
+ ext_wakeup: ext-wakeup {
+ pins = "ext_wakeup0";
+ input-enable;
+ };
+};
+
+/* NAND Flash */
+&elm {
+ status = "okay";
+};
+
+&gpmc {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&nandflash_pins>;
+ ranges = <0 0 0x08000000 0x01000000>; /* CS0 0 @addr 0x08000000, size 0x01000000 */
+ nand@0,0 {
+ compatible = "ti,omap2-nand";
+ reg = <0 0 4>; /* CS0, offset 0, IO size 4 */
+ interrupt-parent = <&gpmc>;
+ interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
+ <1 IRQ_TYPE_NONE>; /* termcount */
+ rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */
+ ti,nand-ecc-opt = "bch8";
+ ti,elm-id = <&elm>;
+ nand-bus-width = <8>;
+ gpmc,device-width = <1>;
+ gpmc,sync-clk-ps = <0>;
+ gpmc,cs-on-ns = <0>;
+ gpmc,cs-rd-off-ns = <44>;
+ gpmc,cs-wr-off-ns = <44>;
+ gpmc,adv-on-ns = <6>;
+ gpmc,adv-rd-off-ns = <34>;
+ gpmc,adv-wr-off-ns = <44>;
+ gpmc,we-on-ns = <0>;
+ gpmc,we-off-ns = <40>;
+ gpmc,oe-on-ns = <0>;
+ gpmc,oe-off-ns = <54>;
+ gpmc,access-ns = <64>;
+ gpmc,rd-cycle-ns = <82>;
+ gpmc,wr-cycle-ns = <82>;
+ gpmc,bus-turnaround-ns = <0>;
+ gpmc,cycle2cycle-delay-ns = <0>;
+ gpmc,clk-activation-ns = <0>;
+ gpmc,wr-access-ns = <40>;
+ gpmc,wr-data-mux-bus-ns = <0>;
+ };
+};
diff --git a/arch/arm/dts/mt7623.dtsi b/arch/arm/dts/mt7623.dtsi
new file mode 100644
index 0000000000..f50f4ef1b9
--- /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@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@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@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@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@10000000 {
+ compatible = "mediatek,mt7623-topckgen";
+ reg = <0x10000000 0x1000>;
+ #clock-cells = <1>;
+ u-boot,dm-pre-reloc;
+ };
+
+ infracfg: syscon@10001000 {
+ compatible = "mediatek,mt7623-infracfg", "syscon";
+ reg = <0x10001000 0x1000>;
+ #clock-cells = <1>;
+ u-boot,dm-pre-reloc;
+ };
+
+ pericfg: syscon@10003000 {
+ compatible = "mediatek,mt7623-pericfg", "syscon";
+ reg = <0x10003000 0x1000>;
+ #clock-cells = <1>;
+ u-boot,dm-pre-reloc;
+ };
+
+ pinctrl: pinctrl@10005000 {
+ compatible = "mediatek,mt7623-pinctrl";
+ reg = <0x10005000 0x1000>;
+
+ gpio: gpio-controller {
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+ };
+
+ scpsys: scpsys@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@10007000 {
+ compatible = "mediatek,wdt";
+ reg = <0x10007000 0x100>;
+ };
+
+ wdt-reboot {
+ compatible = "wdt-reboot";
+ wdt = <&watchdog>;
+ };
+
+ timer0: timer@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@10200100 {
+ compatible = "mediatek,sysirq";
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ interrupt-parent = <&gic>;
+ reg = <0x10200100 0x1c>;
+ };
+
+ apmixedsys: clock-controller@10209000 {
+ compatible = "mediatek,mt7623-apmixedsys";
+ reg = <0x10209000 0x1000>;
+ #clock-cells = <1>;
+ u-boot,dm-pre-reloc;
+ };
+
+ gic: interrupt-controller@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@11002000 {
+ compatible = "mediatek,hsuart";
+ 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@11003000 {
+ compatible = "mediatek,hsuart";
+ 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@11004000 {
+ compatible = "mediatek,hsuart";
+ 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@11005000 {
+ compatible = "mediatek,hsuart";
+ 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@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@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@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 0000000000..84a77fde44
--- /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/arch/arm/dts/mt7629-rfb-u-boot.dtsi b/arch/arm/dts/mt7629-rfb-u-boot.dtsi
new file mode 100644
index 0000000000..1ef5568518
--- /dev/null
+++ b/arch/arm/dts/mt7629-rfb-u-boot.dtsi
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ *
+ * Author: Weijie Gao <weijie.gao@mediatek.com>
+ */
+
+#include <config.h>
+/ {
+ binman {
+ filename = "u-boot-mtk.bin";
+ pad-byte = <0xff>;
+
+#ifdef CONFIG_SPL
+ blob {
+ filename = "spl/u-boot-spl-mtk.bin";
+ size = <CONFIG_SPL_PAD_TO>;
+ };
+
+ u-boot-img {
+ };
+#endif
+ };
+};
diff --git a/arch/arm/dts/mt7629-rfb.dts b/arch/arm/dts/mt7629-rfb.dts
new file mode 100644
index 0000000000..a6d28a060f
--- /dev/null
+++ b/arch/arm/dts/mt7629-rfb.dts
@@ -0,0 +1,70 @@
+/*
+ * 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 {
+ mux {
+ function = "flash";
+ groups = "spi_nor";
+ };
+ };
+
+ 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@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 0000000000..e6052bbdcf
--- /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@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a7";
+ reg = <0x0>;
+ clock-frequency = <1250000000>;
+ };
+
+ cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a7";
+ reg = <0x1>;
+ clock-frequency = <1250000000>;
+ };
+ };
+
+ clk20m: oscillator@0 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <20000000>;
+ clock-output-names = "clk20m";
+ };
+
+ clk40m: oscillator@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@10000000 {
+ compatible = "mediatek,mt7629-infracfg", "syscon";
+ reg = <0x10000000 0x1000>;
+ #clock-cells = <1>;
+ u-boot,dm-pre-reloc;
+ };
+
+ pericfg: syscon@10002000 {
+ compatible = "mediatek,mt7629-pericfg", "syscon";
+ reg = <0x10002000 0x1000>;
+ #clock-cells = <1>;
+ u-boot,dm-pre-reloc;
+ };
+
+ timer0: timer@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@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@10200000 {
+ compatible = "mediatek,mt7629-mcucfg", "syscon";
+ reg = <0x10200000 0x1000>;
+ #clock-cells = <1>;
+ u-boot,dm-pre-reloc;
+ };
+
+ sysirq: interrupt-controller@10200a80 {
+ compatible = "mediatek,sysirq";
+ reg = <0x10200a80 0x20>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ interrupt-parent = <&gic>;
+ };
+
+ dramc: dramc@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@10209000 {
+ compatible = "mediatek,mt7629-apmixedsys";
+ reg = <0x10209000 0x1000>;
+ #clock-cells = <1>;
+ u-boot,dm-pre-reloc;
+ };
+
+ topckgen: clock-controller@10210000 {
+ compatible = "mediatek,mt7629-topckgen";
+ reg = <0x10210000 0x1000>;
+ #clock-cells = <1>;
+ u-boot,dm-pre-reloc;
+ };
+
+ watchdog: watchdog@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@10217000 {
+ compatible = "mediatek,mt7629-pinctrl";
+ reg = <0x10217000 0x8000>;
+
+ gpio: gpio-controller {
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+ };
+
+ gic: interrupt-controller@10300000 {
+ compatible = "arm,gic-400";
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ interrupt-parent = <&gic>;
+ reg = <0x10310000 0x1000>,
+ <0x10320000 0x1000>,
+ <0x10340000 0x2000>,
+ <0x10360000 0x2000>;
+ };
+
+ uart0: serial@11002000 {
+ compatible = "mediatek,hsuart";
+ 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@11003000 {
+ compatible = "mediatek,hsuart";
+ 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@11004000 {
+ compatible = "mediatek,hsuart";
+ 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@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@1b000000 {
+ compatible = "mediatek,mt7629-ethsys", "syscon";
+ reg = <0x1b000000 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ sgmiisys0: syscon@1b128000 {
+ compatible = "mediatek,mt7629-sgmiisys", "syscon";
+ reg = <0x1b128000 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ sgmiisys1: syscon@1b130000 {
+ compatible = "mediatek,mt7629-sgmiisys", "syscon";
+ reg = <0x1b130000 0x1000>;
+ #clock-cells = <1>;
+ };
+};
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 0000000000..4ea1020634
--- /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/arch/arm/include/asm/arch-mediatek/misc.h b/arch/arm/include/asm/arch-mediatek/misc.h
new file mode 100644
index 0000000000..2530e78a5f
--- /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-k3/Makefile b/arch/arm/mach-k3/Makefile
index 406dda3b02..bd4ab361b2 100644
--- a/arch/arm/mach-k3/Makefile
+++ b/arch/arm/mach-k3/Makefile
@@ -5,5 +5,5 @@
obj-$(CONFIG_SOC_K3_AM6) += am6_init.o
obj-$(CONFIG_ARM64) += arm64-mmu.o
-obj-$(CONFIG_CPU_V7R) += r5_mpu.o
+obj-$(CONFIG_CPU_V7R) += r5_mpu.o lowlevel_init.o
obj-y += common.o
diff --git a/arch/arm/mach-k3/lowlevel_init.S b/arch/arm/mach-k3/lowlevel_init.S
new file mode 100644
index 0000000000..70c5d1cade
--- /dev/null
+++ b/arch/arm/mach-k3/lowlevel_init.S
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+ * Lokesh Vutla <lokeshvutla@ti.com>
+ */
+
+#include <linux/linkage.h>
+
+ENTRY(lowlevel_init)
+
+ mrc p15, 0, r0, c0, c0, 5 @ Read MPIDR
+ and r0, #0xff
+ cmp r0, #0x0
+ bne park_cpu
+ bx lr
+park_cpu:
+ wfi
+ b park_cpu
+
+ENDPROC(lowlevel_init)
diff --git a/arch/arm/mach-mediatek/Kconfig b/arch/arm/mach-mediatek/Kconfig
new file mode 100644
index 0000000000..7a733e95df
--- /dev/null
+++ b/arch/arm/mach-mediatek/Kconfig
@@ -0,0 +1,39 @@
+if ARCH_MEDIATEK
+
+config SYS_SOC
+ default "mediatek"
+
+config SYS_VENDOR
+ default "mediatek"
+
+choice
+ prompt "MediaTek board select"
+
+config TARGET_MT7623
+ bool "MediaTek MT7623 SoC"
+ select CPU_V7A
+ select ARCH_MISC_INIT
+ help
+ The MediaTek MT7623 is a ARM-based SoC with a quad-core Cortex-A7
+ including NEON and GPU, Mali-450 graphics, several DDR3 options,
+ crypto engine, built-in Wi-Fi / Bluetooth combo chip, JPEG decoder,
+ video interfaces supporting HDMI and MIPI, and video codec support.
+ Peripherals include Gigabit Ethernet, switch, USB3.0 and OTG, PCIe,
+ I2S, PCM, S/PDIF, UART, SPI, I2C, IR TX/RX, and PWM.
+
+config TARGET_MT7629
+ bool "MediaTek MT7629 SoC"
+ select CPU_V7A
+ select SPL
+ select ARCH_MISC_INIT
+ help
+ The MediaTek MT7629 is a ARM-based SoC with a dual-core Cortex-A7
+ including DDR3, crypto engine, 3x3 11n/ac Wi-Fi, Gigabit Ethernet,
+ switch, USB3.0, PCIe, UART, SPI, I2C and PWM.
+
+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
new file mode 100644
index 0000000000..b5d3a379bc
--- /dev/null
+++ b/arch/arm/mach-mediatek/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0
+
+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/cpu.c b/arch/arm/mach-mediatek/cpu.c
new file mode 100644
index 0000000000..b37e299b74
--- /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 <wdt.h>
+#include <dm/uclass-internal.h>
+
+int arch_misc_init(void)
+{
+ struct udevice *wdt;
+ int ret;
+
+ ret = uclass_first_device_err(UCLASS_WDT, &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 0000000000..1d896fbbf7
--- /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/mt7623/Makefile b/arch/arm/mach-mediatek/mt7623/Makefile
new file mode 100644
index 0000000000..007eb4a367
--- /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 0000000000..0ee8c6664c
--- /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 0000000000..afb94767ee
--- /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 0000000000..2d2c71ad4c
--- /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/arch/arm/mach-mediatek/mt7629/Makefile b/arch/arm/mach-mediatek/mt7629/Makefile
new file mode 100644
index 0000000000..007eb4a367
--- /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 0000000000..ba91a6eaa6
--- /dev/null
+++ b/arch/arm/mach-mediatek/mt7629/init.c
@@ -0,0 +1,128 @@
+// 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 <fdtdec.h>
+#include <ram.h>
+#include <asm/arch/misc.h>
+#include <asm/sections.h>
+#include <dm/uclass.h>
+#include <linux/io.h>
+
+#include <dt-bindings/clock/mt7629-clk.h>
+
+#define L2_CFG_BASE 0x10200000
+#define L2_CFG_SIZE 0x1000
+#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_first_device_err(UCLASS_RAM, &dev);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+int mach_cpu_init(void)
+{
+ void __iomem *base;
+
+ base = ioremap(L2_CFG_BASE, L2_CFG_SIZE);
+
+ /* 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_first_device_err(UCLASS_RAM, &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 0000000000..90dd4ea48e
--- /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 0000000000..9b3590ff3d
--- /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/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index 560dc9b25d..3c54f5106d 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -230,6 +230,7 @@ config MACH_SUN8I_A83T
select PHY_SUN4I_USB
select SUNXI_GEN_SUN6I
select MMC_SUNXI_HAS_NEW_MODE
+ select MMC_SUNXI_HAS_MODE_SWITCH
select SUPPORT_SPL
config MACH_SUN8I_H3
@@ -281,6 +282,7 @@ config MACH_SUN50I
select SUN6I_PRCM
select SUNXI_DE2
select SUNXI_GEN_SUN6I
+ select MMC_SUNXI_HAS_NEW_MODE
select SUPPORT_SPL
select SUNXI_DRAM_DW
select SUNXI_DRAM_DW_32BIT
diff --git a/arch/arm/mach-sunxi/dram_sun8i_a33.c b/arch/arm/mach-sunxi/dram_sun8i_a33.c
index d9aa0c6d7e..1da2727f98 100644
--- a/arch/arm/mach-sunxi/dram_sun8i_a33.c
+++ b/arch/arm/mach-sunxi/dram_sun8i_a33.c
@@ -334,7 +334,7 @@ unsigned long sunxi_dram_init(void)
struct dram_para para = {
.cs1 = 0,
.bank = 1,
- .rank = 1,
+ .rank = 2,
.rows = 15,
.bus_width = 16,
.page_size = 2048,
diff --git a/arch/nds32/cpu/n1213/start.S b/arch/nds32/cpu/n1213/start.S
index aa9457f5e4..cf966e2132 100644
--- a/arch/nds32/cpu/n1213/start.S
+++ b/arch/nds32/cpu/n1213/start.S
@@ -201,14 +201,6 @@ update_gp:
#endif
/*
- * Do CPU critical regs init only at reboot,
- * not when booting from ram
- */
-#ifdef CONFIG_INIT_CRITICAL
- jal cpu_init_crit ! Do CPU critical regs init
-#endif
-
-/*
* Set stackpointer in internal RAM to call board_init_f
* $sp must be 8-byte alignment for ABI compliance.
*/
@@ -319,49 +311,6 @@ call_board_init_r:
jr $lp /* jump to board_init_r() */
/*
- * Initialize CPU critical registers
- *
- * 1. Setup control registers
- * 1.1 Mask all IRQs
- * 1.2 Flush cache and TLB
- * 1.3 Disable MMU and cache
- * 2. Setup memory timing
- */
-
-cpu_init_crit:
-
- move $r0, $lp /* push ra */
-
- /* Disable Interrupts by clear GIE in $PSW reg */
- setgie.d
-
- /* Flush caches and TLB */
- /* Invalidate caches */
- jal invalidate_icac
- jal invalidate_dcac
-
- /* Flush TLB */
- mfsr $p0, $MMU_CFG
- andi $p0, $p0, 0x3 ! MMPS
- li $p1, 0x2 ! TLB MMU
- bne $p0, $p1, 1f
- tlbop flushall ! Flush TLB
-
-1:
- ! Disable MMU, Dcache
- ! Whitiger is MMU disabled when reset
- ! Disable the D$
- mfsr $p0, MR_CAC_CTL ! Get the $CACHE_CTL reg
- li $p1, DIS_DCAC
- and $p0, $p0, $p1 ! Set DC_EN bit
- mtsr $p0, MR_CAC_CTL ! write back the $CACHE_CTL reg
- isb
-
- move $lp, $r0
-2:
- ret
-
-/*
* Invalidate I$
*/
invalidate_icac:
diff --git a/arch/powerpc/include/asm/spl.h b/arch/powerpc/include/asm/spl.h
index cd6d31c71a..60a7d37d30 100644
--- a/arch/powerpc/include/asm/spl.h
+++ b/arch/powerpc/include/asm/spl.h
@@ -8,7 +8,4 @@
#define BOOT_DEVICE_NOR 1
-/* Linker symbols */
-extern char __bss_start[], __bss_end[];
-
#endif
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 168ca3de7c..3e0af55e71 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -16,27 +16,45 @@ config TARGET_QEMU_VIRT
endchoice
+# board-specific options below
source "board/AndesTech/ax25-ae350/Kconfig"
source "board/emulation/qemu-riscv/Kconfig"
+# platform-specific options below
+source "arch/riscv/cpu/ax25/Kconfig"
+
+# architecture-specific options below
+
choice
- prompt "CPU selection"
- default CPU_RISCV_32
+ prompt "Base ISA"
+ default ARCH_RV32I
-config CPU_RISCV_32
- bool "RISC-V 32-bit"
+config ARCH_RV32I
+ bool "RV32I"
select 32BIT
help
- Choose this option to build an U-Boot for RISCV32 architecture.
+ Choose this option to target the RV32I base integer instruction set.
-config CPU_RISCV_64
- bool "RISC-V 64-bit"
+config ARCH_RV64I
+ bool "RV64I"
select 64BIT
+ select PHYS_64BIT
help
- Choose this option to build an U-Boot for RISCV64 architecture.
+ Choose this option to target the RV64I base integer instruction set.
endchoice
+config RISCV_ISA_C
+ bool "Emit compressed instructions"
+ default y
+ help
+ Adds "C" to the ISA subsets that the toolchain is allowed to emit
+ when building U-Boot, which results in compressed instructions in the
+ U-Boot binary.
+
+config RISCV_ISA_A
+ def_bool y
+
config 32BIT
bool
diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index 8fb6a889d8..55d7c6550e 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -3,6 +3,26 @@
# Copyright (C) 2017 Andes Technology Corporation.
# Rick Chen, Andes Technology Corporation <rick@andestech.com>
+ifeq ($(CONFIG_ARCH_RV64I),y)
+ ARCH_BASE = rv64im
+ ABI = lp64
+endif
+ifeq ($(CONFIG_ARCH_RV32I),y)
+ ARCH_BASE = rv32im
+ ABI = ilp32
+endif
+ifeq ($(CONFIG_RISCV_ISA_A),y)
+ ARCH_A = a
+endif
+ifeq ($(CONFIG_RISCV_ISA_C),y)
+ ARCH_C = c
+endif
+
+ARCH_FLAGS = -march=$(ARCH_BASE)$(ARCH_A)$(ARCH_C) -mabi=$(ABI)
+
+PLATFORM_CPPFLAGS += $(ARCH_FLAGS)
+CFLAGS_EFI += $(ARCH_FLAGS)
+
head-y := arch/riscv/cpu/start.o
libs-y += arch/riscv/cpu/
diff --git a/arch/riscv/config.mk b/arch/riscv/config.mk
index cc5d8d1ad5..ff4fe64001 100644
--- a/arch/riscv/config.mk
+++ b/arch/riscv/config.mk
@@ -14,16 +14,12 @@
64bit-emul := elf64lriscv
ifdef CONFIG_32BIT
-PLATFORM_CPPFLAGS += -march=rv32ima -mabi=ilp32
PLATFORM_LDFLAGS += -m $(32bit-emul)
-CFLAGS_EFI += -march=rv32ima -mabi=ilp32
EFI_LDS := elf_riscv32_efi.lds
endif
ifdef CONFIG_64BIT
-PLATFORM_CPPFLAGS += -march=rv64ima -mabi=lp64
PLATFORM_LDFLAGS += -m $(64bit-emul)
-CFLAGS_EFI += -march=rv64ima -mabi=lp64
EFI_LDS := elf_riscv64_efi.lds
endif
@@ -31,7 +27,8 @@ CONFIG_STANDALONE_LOAD_ADDR = 0x00000000
LDFLAGS_STANDALONE += -T $(srctree)/examples/standalone/riscv.lds
PLATFORM_CPPFLAGS += -ffixed-gp -fpic
-PLATFORM_RELFLAGS += -fno-common -gdwarf-2 -ffunction-sections
+PLATFORM_RELFLAGS += -fno-common -gdwarf-2 -ffunction-sections \
+ -fdata-sections
LDFLAGS_u-boot += --gc-sections -static -pie
EFI_CRT0 := crt0_riscv_efi.o
diff --git a/arch/riscv/cpu/ax25/Kconfig b/arch/riscv/cpu/ax25/Kconfig
new file mode 100644
index 0000000000..6c7022f0f5
--- /dev/null
+++ b/arch/riscv/cpu/ax25/Kconfig
@@ -0,0 +1,7 @@
+config RISCV_NDS
+ bool "AndeStar V5 ISA support"
+ default n
+ help
+ Say Y here if you plan to run U-Boot on AndeStar v5
+ platforms and use some specific features which are
+ provided by Andes Technology AndeStar V5 Families.
diff --git a/arch/riscv/cpu/ax25/Makefile b/arch/riscv/cpu/ax25/Makefile
index 2ab0342fe8..318baccb09 100644
--- a/arch/riscv/cpu/ax25/Makefile
+++ b/arch/riscv/cpu/ax25/Makefile
@@ -4,3 +4,4 @@
# Rick Chen, Andes Technology Corporation <rick@andestech.com>
obj-y := cpu.o
+obj-y += cache.o
diff --git a/arch/riscv/cpu/ax25/cache.c b/arch/riscv/cpu/ax25/cache.c
new file mode 100644
index 0000000000..6600ac2fac
--- /dev/null
+++ b/arch/riscv/cpu/ax25/cache.c
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2017 Andes Technology Corporation
+ * Rick Chen, Andes Technology Corporation <rick@andestech.com>
+ */
+
+#include <common.h>
+
+void icache_enable(void)
+{
+#ifndef CONFIG_SYS_ICACHE_OFF
+#ifdef CONFIG_RISCV_NDS
+ asm volatile (
+ "csrr t1, mcache_ctl\n\t"
+ "ori t0, t1, 0x1\n\t"
+ "csrw mcache_ctl, t0\n\t"
+ );
+#endif
+#endif
+}
+
+void icache_disable(void)
+{
+#ifndef CONFIG_SYS_ICACHE_OFF
+#ifdef CONFIG_RISCV_NDS
+ asm volatile (
+ "fence.i\n\t"
+ "csrr t1, mcache_ctl\n\t"
+ "andi t0, t1, ~0x1\n\t"
+ "csrw mcache_ctl, t0\n\t"
+ );
+#endif
+#endif
+}
+
+void dcache_enable(void)
+{
+#ifndef CONFIG_SYS_DCACHE_OFF
+#ifdef CONFIG_RISCV_NDS
+ asm volatile (
+ "csrr t1, mcache_ctl\n\t"
+ "ori t0, t1, 0x2\n\t"
+ "csrw mcache_ctl, t0\n\t"
+ );
+#endif
+#endif
+}
+
+void dcache_disable(void)
+{
+#ifndef CONFIG_SYS_DCACHE_OFF
+#ifdef CONFIG_RISCV_NDS
+ asm volatile (
+ "fence\n\t"
+ "csrr t1, mcache_ctl\n\t"
+ "andi t0, t1, ~0x2\n\t"
+ "csrw mcache_ctl, t0\n\t"
+ );
+#endif
+#endif
+}
+
+int icache_status(void)
+{
+ int ret = 0;
+
+#ifdef CONFIG_RISCV_NDS
+ asm volatile (
+ "csrr t1, mcache_ctl\n\t"
+ "andi %0, t1, 0x01\n\t"
+ : "=r" (ret)
+ :
+ : "memory"
+ );
+#endif
+
+ return ret;
+}
+
+int dcache_status(void)
+{
+ int ret = 0;
+
+#ifdef CONFIG_RISCV_NDS
+ asm volatile (
+ "csrr t1, mcache_ctl\n\t"
+ "andi %0, t1, 0x02\n\t"
+ : "=r" (ret)
+ :
+ : "memory"
+ );
+#endif
+
+ return ret;
+}
diff --git a/arch/riscv/cpu/ax25/cpu.c b/arch/riscv/cpu/ax25/cpu.c
index fddcc156c3..76689b21d3 100644
--- a/arch/riscv/cpu/ax25/cpu.c
+++ b/arch/riscv/cpu/ax25/cpu.c
@@ -6,6 +6,7 @@
/* CPU specific code */
#include <common.h>
+#include <asm/cache.h>
/*
* cleanup_before_linux() is called just before we call linux
@@ -18,6 +19,9 @@ int cleanup_before_linux(void)
disable_interrupts();
/* turn off I/D-cache */
+ cache_flush();
+ icache_disable();
+ dcache_disable();
return 0;
}
diff --git a/arch/riscv/cpu/cpu.c b/arch/riscv/cpu/cpu.c
index ae57fb8313..d9f820c44c 100644
--- a/arch/riscv/cpu/cpu.c
+++ b/arch/riscv/cpu/cpu.c
@@ -6,6 +6,12 @@
#include <common.h>
#include <asm/csr.h>
+/*
+ * prior_stage_fdt_address must be stored in the data section since it is used
+ * before the bss section is available.
+ */
+phys_addr_t prior_stage_fdt_address __attribute__((section(".data")));
+
enum {
ISA_INVALID = 0,
ISA_32BIT,
diff --git a/arch/riscv/cpu/qemu/cpu.c b/arch/riscv/cpu/qemu/cpu.c
index 6c7a32755a..25d97d0b41 100644
--- a/arch/riscv/cpu/qemu/cpu.c
+++ b/arch/riscv/cpu/qemu/cpu.c
@@ -15,7 +15,7 @@ int cleanup_before_linux(void)
{
disable_interrupts();
- /* turn off I/D-cache */
+ cache_flush();
return 0;
}
diff --git a/arch/riscv/cpu/start.S b/arch/riscv/cpu/start.S
index 7cd7755190..15e1b8199a 100644
--- a/arch/riscv/cpu/start.S
+++ b/arch/riscv/cpu/start.S
@@ -16,56 +16,47 @@
#include <asm/encoding.h>
#ifdef CONFIG_32BIT
-#define LREG lw
-#define SREG sw
-#define REGBYTES 4
+#define LREG lw
+#define SREG sw
+#define REGBYTES 4
#define RELOC_TYPE R_RISCV_32
#define SYM_INDEX 0x8
#define SYM_SIZE 0x10
#else
-#define LREG ld
-#define SREG sd
-#define REGBYTES 8
+#define LREG ld
+#define SREG sd
+#define REGBYTES 8
#define RELOC_TYPE R_RISCV_64
#define SYM_INDEX 0x20
#define SYM_SIZE 0x18
#endif
-.section .text
+.section .text
.globl _start
_start:
- j handle_reset
+ /* save hart id and dtb pointer */
+ mv s0, a0
+ mv s1, a1
-nmi_vector:
- j nmi_vector
+ li t0, CONFIG_SYS_SDRAM_BASE
+ SREG a2, 0(t0)
+ la t0, trap_entry
+ csrw mtvec, t0
-trap_vector:
- j trap_entry
+ /* mask all interrupts */
+ csrw mie, zero
-.global trap_entry
-handle_reset:
- li t0, CONFIG_SYS_SDRAM_BASE
- SREG a2, 0(t0)
- la t0, trap_entry
- csrw mtvec, t0
- csrwi mstatus, 0
- csrwi mie, 0
-
-/*
- * Do CPU critical regs init only at reboot,
- * not when booting from ram
- */
-#ifdef CONFIG_INIT_CRITICAL
- jal cpu_init_crit /* Do CPU critical regs init */
-#endif
+ /* Enable cache */
+ jal icache_enable
+ jal dcache_enable
/*
* Set stackpointer in internal/ex RAM to call board_init_f
*/
call_board_init_f:
- li t0, -16
- li t1, CONFIG_SYS_INIT_SP_ADDR
- and sp, t1, t0 /* force 16 byte alignment */
+ li t0, -16
+ li t1, CONFIG_SYS_INIT_SP_ADDR
+ and sp, t1, t0 /* force 16 byte alignment */
#ifdef CONFIG_DEBUG_UART
jal debug_uart_init
@@ -75,11 +66,15 @@ call_board_init_f_0:
mv a0, sp
jal board_init_f_alloc_reserve
mv sp, a0
+
+ la t0, prior_stage_fdt_address
+ SREG s1, 0(t0)
+
jal board_init_f_init_reserve
- mv a0, zero /* a0 <-- boot_flags = 0 */
- la t5, board_init_f
- jr t5 /* jump to board_init_f() */
+ mv a0, zero /* a0 <-- boot_flags = 0 */
+ la t5, board_init_f
+ jr t5 /* jump to board_init_f() */
/*
* void relocate_code (addr_sp, gd, addr_moni)
@@ -90,203 +85,200 @@ call_board_init_f_0:
*/
.globl relocate_code
relocate_code:
- mv s2, a0 /* save addr_sp */
- mv s3, a1 /* save addr of gd */
- mv s4, a2 /* save addr of destination */
+ mv s2, a0 /* save addr_sp */
+ mv s3, a1 /* save addr of gd */
+ mv s4, a2 /* save addr of destination */
/*
*Set up the stack
*/
stack_setup:
- mv sp, s2
- la t0, _start
- sub t6, s4, t0 /* t6 <- relocation offset */
- beq t0, s4, clear_bss /* skip relocation */
+ mv sp, s2
+ la t0, _start
+ sub t6, s4, t0 /* t6 <- relocation offset */
+ beq t0, s4, clear_bss /* skip relocation */
- mv t1, s4 /* t1 <- scratch for copy_loop */
- la t3, __bss_start
- sub t3, t3, t0 /* t3 <- __bss_start_ofs */
- add t2, t0, t3 /* t2 <- source end address */
+ mv t1, s4 /* t1 <- scratch for copy_loop */
+ la t3, __bss_start
+ sub t3, t3, t0 /* t3 <- __bss_start_ofs */
+ add t2, t0, t3 /* t2 <- source end address */
copy_loop:
- LREG t5, 0(t0)
- addi t0, t0, REGBYTES
- SREG t5, 0(t1)
- addi t1, t1, REGBYTES
- blt t0, t2, copy_loop
+ LREG t5, 0(t0)
+ addi t0, t0, REGBYTES
+ SREG t5, 0(t1)
+ addi t1, t1, REGBYTES
+ blt t0, t2, copy_loop
/*
* Update dynamic relocations after board_init_f
*/
fix_rela_dyn:
- la t1, __rel_dyn_start
- la t2, __rel_dyn_end
- beq t1, t2, clear_bss
- add t1, t1, t6 /* t1 <- rela_dyn_start in RAM */
- add t2, t2, t6 /* t2 <- rela_dyn_end in RAM */
+ la t1, __rel_dyn_start
+ la t2, __rel_dyn_end
+ beq t1, t2, clear_bss
+ add t1, t1, t6 /* t1 <- rela_dyn_start in RAM */
+ add t2, t2, t6 /* t2 <- rela_dyn_end in RAM */
/*
* skip first reserved entry: address, type, addend
*/
- bne t1, t2, 7f
+ bne t1, t2, 7f
6:
- LREG t5, -(REGBYTES*2)(t1) /* t5 <-- relocation info:type */
- li t3, R_RISCV_RELATIVE /* reloc type R_RISCV_RELATIVE */
- bne t5, t3, 8f /* skip non-RISCV_RELOC entries */
- LREG t3, -(REGBYTES*3)(t1)
- LREG t5, -(REGBYTES)(t1) /* t5 <-- addend */
- add t5, t5, t6 /* t5 <-- location to fix up in RAM */
- add t3, t3, t6 /* t3 <-- location to fix up in RAM */
- SREG t5, 0(t3)
+ LREG t5, -(REGBYTES*2)(t1) /* t5 <-- relocation info:type */
+ li t3, R_RISCV_RELATIVE /* reloc type R_RISCV_RELATIVE */
+ bne t5, t3, 8f /* skip non-RISCV_RELOC entries */
+ LREG t3, -(REGBYTES*3)(t1)
+ LREG t5, -(REGBYTES)(t1) /* t5 <-- addend */
+ add t5, t5, t6 /* t5 <-- location to fix up in RAM */
+ add t3, t3, t6 /* t3 <-- location to fix up in RAM */
+ SREG t5, 0(t3)
7:
- addi t1, t1, (REGBYTES*3)
- ble t1, t2, 6b
+ addi t1, t1, (REGBYTES*3)
+ ble t1, t2, 6b
8:
- la t4, __dyn_sym_start
- add t4, t4, t6
+ la t4, __dyn_sym_start
+ add t4, t4, t6
9:
- LREG t5, -(REGBYTES*2)(t1) /* t5 <-- relocation info:type */
- srli t0, t5, SYM_INDEX /* t0 <--- sym table index */
- andi t5, t5, 0xFF /* t5 <--- relocation type */
- li t3, RELOC_TYPE
- bne t5, t3, 10f /* skip non-addned entries */
+ LREG t5, -(REGBYTES*2)(t1) /* t5 <-- relocation info:type */
+ srli t0, t5, SYM_INDEX /* t0 <--- sym table index */
+ andi t5, t5, 0xFF /* t5 <--- relocation type */
+ li t3, RELOC_TYPE
+ bne t5, t3, 10f /* skip non-addned entries */
- LREG t3, -(REGBYTES*3)(t1)
- li t5, SYM_SIZE
- mul t0, t0, t5
- add s1, t4, t0
- LREG t5, REGBYTES(s1)
- add t5, t5, t6 /* t5 <-- location to fix up in RAM */
- add t3, t3, t6 /* t3 <-- location to fix up in RAM */
- SREG t5, 0(t3)
+ LREG t3, -(REGBYTES*3)(t1)
+ li t5, SYM_SIZE
+ mul t0, t0, t5
+ add s5, t4, t0
+ LREG t5, REGBYTES(s5)
+ add t5, t5, t6 /* t5 <-- location to fix up in RAM */
+ add t3, t3, t6 /* t3 <-- location to fix up in RAM */
+ SREG t5, 0(t3)
10:
- addi t1, t1, (REGBYTES*3)
- ble t1, t2, 9b
+ addi t1, t1, (REGBYTES*3)
+ ble t1, t2, 9b
/*
* trap update
*/
- la t0, trap_entry
- add t0, t0, t6
- csrw mtvec, t0
+ la t0, trap_entry
+ add t0, t0, t6
+ csrw mtvec, t0
clear_bss:
- la t0, __bss_start /* t0 <- rel __bss_start in FLASH */
- add t0, t0, t6 /* t0 <- rel __bss_start in RAM */
- la t1, __bss_end /* t1 <- rel __bss_end in FLASH */
- add t1, t1, t6 /* t1 <- rel __bss_end in RAM */
- li t2, 0x00000000 /* clear */
- beq t0, t1, call_board_init_r
+ la t0, __bss_start /* t0 <- rel __bss_start in FLASH */
+ add t0, t0, t6 /* t0 <- rel __bss_start in RAM */
+ la t1, __bss_end /* t1 <- rel __bss_end in FLASH */
+ add t1, t1, t6 /* t1 <- rel __bss_end in RAM */
+ beq t0, t1, call_board_init_r
clbss_l:
- SREG t2, 0(t0) /* clear loop... */
- addi t0, t0, REGBYTES
- bne t0, t1, clbss_l
+ SREG zero, 0(t0) /* clear loop... */
+ addi t0, t0, REGBYTES
+ bne t0, t1, clbss_l
/*
* We are done. Do not return, instead branch to second part of board
* initialization, now running from RAM.
*/
call_board_init_r:
- la t0, board_init_r
- mv t4, t0 /* offset of board_init_r() */
- add t4, t4, t6 /* real address of board_init_r() */
+ jal invalidate_icache_all
+ jal flush_dcache_all
+ la t0, board_init_r
+ mv t4, t0 /* offset of board_init_r() */
+ add t4, t4, t6 /* real address of board_init_r() */
/*
* setup parameters for board_init_r
*/
- mv a0, s3 /* gd_t */
- mv a1, s4 /* dest_addr */
+ mv a0, s3 /* gd_t */
+ mv a1, s4 /* dest_addr */
/*
* jump to it ...
*/
- jr t4 /* jump to board_init_r() */
+ jr t4 /* jump to board_init_r() */
/*
* trap entry
*/
+.align 2
trap_entry:
- addi sp, sp, -32*REGBYTES
- SREG x1, 1*REGBYTES(sp)
- SREG x2, 2*REGBYTES(sp)
- SREG x3, 3*REGBYTES(sp)
- SREG x4, 4*REGBYTES(sp)
- SREG x5, 5*REGBYTES(sp)
- SREG x6, 6*REGBYTES(sp)
- SREG x7, 7*REGBYTES(sp)
- SREG x8, 8*REGBYTES(sp)
- SREG x9, 9*REGBYTES(sp)
- SREG x10, 10*REGBYTES(sp)
- SREG x11, 11*REGBYTES(sp)
- SREG x12, 12*REGBYTES(sp)
- SREG x13, 13*REGBYTES(sp)
- SREG x14, 14*REGBYTES(sp)
- SREG x15, 15*REGBYTES(sp)
- SREG x16, 16*REGBYTES(sp)
- SREG x17, 17*REGBYTES(sp)
- SREG x18, 18*REGBYTES(sp)
- SREG x19, 19*REGBYTES(sp)
- SREG x20, 20*REGBYTES(sp)
- SREG x21, 21*REGBYTES(sp)
- SREG x22, 22*REGBYTES(sp)
- SREG x23, 23*REGBYTES(sp)
- SREG x24, 24*REGBYTES(sp)
- SREG x25, 25*REGBYTES(sp)
- SREG x26, 26*REGBYTES(sp)
- SREG x27, 27*REGBYTES(sp)
- SREG x28, 28*REGBYTES(sp)
- SREG x29, 29*REGBYTES(sp)
- SREG x30, 30*REGBYTES(sp)
- SREG x31, 31*REGBYTES(sp)
- csrr a0, mcause
- csrr a1, mepc
- mv a2, sp
- jal handle_trap
- csrw mepc, a0
+ addi sp, sp, -32*REGBYTES
+ SREG x1, 1*REGBYTES(sp)
+ SREG x2, 2*REGBYTES(sp)
+ SREG x3, 3*REGBYTES(sp)
+ SREG x4, 4*REGBYTES(sp)
+ SREG x5, 5*REGBYTES(sp)
+ SREG x6, 6*REGBYTES(sp)
+ SREG x7, 7*REGBYTES(sp)
+ SREG x8, 8*REGBYTES(sp)
+ SREG x9, 9*REGBYTES(sp)
+ SREG x10, 10*REGBYTES(sp)
+ SREG x11, 11*REGBYTES(sp)
+ SREG x12, 12*REGBYTES(sp)
+ SREG x13, 13*REGBYTES(sp)
+ SREG x14, 14*REGBYTES(sp)
+ SREG x15, 15*REGBYTES(sp)
+ SREG x16, 16*REGBYTES(sp)
+ SREG x17, 17*REGBYTES(sp)
+ SREG x18, 18*REGBYTES(sp)
+ SREG x19, 19*REGBYTES(sp)
+ SREG x20, 20*REGBYTES(sp)
+ SREG x21, 21*REGBYTES(sp)
+ SREG x22, 22*REGBYTES(sp)
+ SREG x23, 23*REGBYTES(sp)
+ SREG x24, 24*REGBYTES(sp)
+ SREG x25, 25*REGBYTES(sp)
+ SREG x26, 26*REGBYTES(sp)
+ SREG x27, 27*REGBYTES(sp)
+ SREG x28, 28*REGBYTES(sp)
+ SREG x29, 29*REGBYTES(sp)
+ SREG x30, 30*REGBYTES(sp)
+ SREG x31, 31*REGBYTES(sp)
+ csrr a0, mcause
+ csrr a1, mepc
+ mv a2, sp
+ jal handle_trap
+ csrw mepc, a0
/*
* Remain in M-mode after mret
*/
- li t0, MSTATUS_MPP
- csrs mstatus, t0
- LREG x1, 1*REGBYTES(sp)
- LREG x2, 2*REGBYTES(sp)
- LREG x3, 3*REGBYTES(sp)
- LREG x4, 4*REGBYTES(sp)
- LREG x5, 5*REGBYTES(sp)
- LREG x6, 6*REGBYTES(sp)
- LREG x7, 7*REGBYTES(sp)
- LREG x8, 8*REGBYTES(sp)
- LREG x9, 9*REGBYTES(sp)
- LREG x10, 10*REGBYTES(sp)
- LREG x11, 11*REGBYTES(sp)
- LREG x12, 12*REGBYTES(sp)
- LREG x13, 13*REGBYTES(sp)
- LREG x14, 14*REGBYTES(sp)
- LREG x15, 15*REGBYTES(sp)
- LREG x16, 16*REGBYTES(sp)
- LREG x17, 17*REGBYTES(sp)
- LREG x18, 18*REGBYTES(sp)
- LREG x19, 19*REGBYTES(sp)
- LREG x20, 20*REGBYTES(sp)
- LREG x21, 21*REGBYTES(sp)
- LREG x22, 22*REGBYTES(sp)
- LREG x23, 23*REGBYTES(sp)
- LREG x24, 24*REGBYTES(sp)
- LREG x25, 25*REGBYTES(sp)
- LREG x26, 26*REGBYTES(sp)
- LREG x27, 27*REGBYTES(sp)
- LREG x28, 28*REGBYTES(sp)
- LREG x29, 29*REGBYTES(sp)
- LREG x30, 30*REGBYTES(sp)
- LREG x31, 31*REGBYTES(sp)
- addi sp, sp, 32*REGBYTES
+ li t0, MSTATUS_MPP
+ csrs mstatus, t0
+ LREG x1, 1*REGBYTES(sp)
+ LREG x2, 2*REGBYTES(sp)
+ LREG x3, 3*REGBYTES(sp)
+ LREG x4, 4*REGBYTES(sp)
+ LREG x5, 5*REGBYTES(sp)
+ LREG x6, 6*REGBYTES(sp)
+ LREG x7, 7*REGBYTES(sp)
+ LREG x8, 8*REGBYTES(sp)
+ LREG x9, 9*REGBYTES(sp)
+ LREG x10, 10*REGBYTES(sp)
+ LREG x11, 11*REGBYTES(sp)
+ LREG x12, 12*REGBYTES(sp)
+ LREG x13, 13*REGBYTES(sp)
+ LREG x14, 14*REGBYTES(sp)
+ LREG x15, 15*REGBYTES(sp)
+ LREG x16, 16*REGBYTES(sp)
+ LREG x17, 17*REGBYTES(sp)
+ LREG x18, 18*REGBYTES(sp)
+ LREG x19, 19*REGBYTES(sp)
+ LREG x20, 20*REGBYTES(sp)
+ LREG x21, 21*REGBYTES(sp)
+ LREG x22, 22*REGBYTES(sp)
+ LREG x23, 23*REGBYTES(sp)
+ LREG x24, 24*REGBYTES(sp)
+ LREG x25, 25*REGBYTES(sp)
+ LREG x26, 26*REGBYTES(sp)
+ LREG x27, 27*REGBYTES(sp)
+ LREG x28, 28*REGBYTES(sp)
+ LREG x29, 29*REGBYTES(sp)
+ LREG x30, 30*REGBYTES(sp)
+ LREG x31, 31*REGBYTES(sp)
+ addi sp, sp, 32*REGBYTES
mret
-
-#ifdef CONFIG_INIT_CRITICAL
-cpu_init_crit:
- ret
-#endif
diff --git a/arch/riscv/dts/Makefile b/arch/riscv/dts/Makefile
index a1b06ffc6f..b400defb38 100644
--- a/arch/riscv/dts/Makefile
+++ b/arch/riscv/dts/Makefile
@@ -1,6 +1,5 @@
# SPDX-License-Identifier: GPL-2.0+
-dtb-$(CONFIG_TARGET_AX25_AE350) += ae350.dtb
targets += $(dtb-y)
DTC_FLAGS += -R 4 -p 0x1000
diff --git a/arch/riscv/dts/ae350.dts b/arch/riscv/dts/ae350.dts
index 4717ae88bc..e48c298645 100644
--- a/arch/riscv/dts/ae350.dts
+++ b/arch/riscv/dts/ae350.dts
@@ -12,15 +12,14 @@
};
chosen {
- bootargs = "console=ttyS0,38400n8 earlyprintk=uart8250-32bit,0xf0300000 debug loglevel=7";
+ bootargs = "console=ttyS0,38400n8 debug loglevel=7";
stdout-path = "uart0:38400n8";
};
cpus {
#address-cells = <1>;
#size-cells = <0>;
- timebase-frequency = <10000000>;
-
+ timebase-frequency = <60000000>;
CPU0: cpu@0 {
device_type = "cpu";
reg = <0>;
@@ -29,7 +28,8 @@
riscv,isa = "rv64imafdc";
mmu-type = "riscv,sv39";
clock-frequency = <60000000>;
-
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <32>;
CPU0_intc: interrupt-controller {
#interrupt-cells = <1>;
interrupt-controller;
@@ -48,13 +48,6 @@
#size-cells = <2>;
compatible = "andestech,riscv-ae350-soc";
ranges;
- };
-
- plmt0@e6000000 {
- compatible = "riscv,plmt0";
- interrupts-extended = <&CPU0_intc 7>;
- reg = <0x0 0xe6000000 0x0 0x100000>;
- };
plic0: interrupt-controller@e4000000 {
compatible = "riscv,plic0";
@@ -62,7 +55,7 @@
#interrupt-cells = <2>;
interrupt-controller;
reg = <0x0 0xe4000000 0x0 0x2000000>;
- riscv,ndev=<31>;
+ riscv,ndev=<71>;
interrupts-extended = <&CPU0_intc 11 &CPU0_intc 9>;
};
@@ -76,6 +69,13 @@
interrupts-extended = <&CPU0_intc 3>;
};
+ plmt0@e6000000 {
+ compatible = "riscv,plmt0";
+ interrupts-extended = <&CPU0_intc 7>;
+ reg = <0x0 0xe6000000 0x0 0x100000>;
+ };
+ };
+
spiclk: virt_100mhz {
#clock-cells = <0>;
compatible = "fixed-clock";
@@ -85,7 +85,7 @@
timer0: timer@f0400000 {
compatible = "andestech,atcpit100";
reg = <0x0 0xf0400000 0x0 0x1000>;
- clock-frequency = <40000000>;
+ clock-frequency = <60000000>;
interrupts = <3 4>;
interrupt-parent = <&plic0>;
};
@@ -119,11 +119,89 @@
interrupt-parent = <&plic0>;
};
+ dma0: dma@f0c00000 {
+ compatible = "andestech,atcdmac300";
+ reg = <0x0 0xf0c00000 0x0 0x1000>;
+ interrupts = <10 4 64 4 65 4 66 4 67 4 68 4 69 4 70 4 71 4>;
+ dma-channels = <8>;
+ interrupt-parent = <&plic0>;
+ };
+
+ lcd0: lcd@e0200000 {
+ compatible = "andestech,atflcdc100";
+ reg = <0x0 0xe0200000 0x0 0x1000>;
+ interrupts = <20 4>;
+ interrupt-parent = <&plic0>;
+ };
+
smc0: smc@e0400000 {
compatible = "andestech,atfsmc020";
reg = <0x0 0xe0400000 0x0 0x1000>;
};
+ snd0: snd@f0d00000 {
+ compatible = "andestech,atfac97";
+ reg = <0x0 0xf0d00000 0x0 0x1000>;
+ interrupts = <17 4>;
+ interrupt-parent = <&plic0>;
+ };
+
+ virtio_mmio@fe007000 {
+ interrupts = <0x17 0x4>;
+ interrupt-parent = <0x2>;
+ reg = <0x0 0xfe007000 0x0 0x1000>;
+ compatible = "virtio,mmio";
+ };
+
+ virtio_mmio@fe006000 {
+ interrupts = <0x16 0x4>;
+ interrupt-parent = <0x2>;
+ reg = <0x0 0xfe006000 0x0 0x1000>;
+ compatible = "virtio,mmio";
+ };
+
+ virtio_mmio@fe005000 {
+ interrupts = <0x15 0x4>;
+ interrupt-parent = <0x2>;
+ reg = <0x0 0xfe005000 0x0 0x1000>;
+ compatible = "virtio,mmio";
+ };
+
+ virtio_mmio@fe004000 {
+ interrupts = <0x14 0x4>;
+ interrupt-parent = <0x2>;
+ reg = <0x0 0xfe004000 0x0 0x1000>;
+ compatible = "virtio,mmio";
+ };
+
+ virtio_mmio@fe003000 {
+ interrupts = <0x13 0x4>;
+ interrupt-parent = <0x2>;
+ reg = <0x0 0xfe003000 0x0 0x1000>;
+ compatible = "virtio,mmio";
+ };
+
+ virtio_mmio@fe002000 {
+ interrupts = <0x12 0x4>;
+ interrupt-parent = <0x2>;
+ reg = <0x0 0xfe002000 0x0 0x1000>;
+ compatible = "virtio,mmio";
+ };
+
+ virtio_mmio@fe001000 {
+ interrupts = <0x11 0x4>;
+ interrupt-parent = <0x2>;
+ reg = <0x0 0xfe001000 0x0 0x1000>;
+ compatible = "virtio,mmio";
+ };
+
+ virtio_mmio@fe000000 {
+ interrupts = <0x10 0x4>;
+ interrupt-parent = <0x2>;
+ reg = <0x0 0xfe000000 0x0 0x1000>;
+ compatible = "virtio,mmio";
+ };
+
nor@0,0 {
compatible = "cfi-flash";
reg = <0x0 0x88000000 0x0 0x1000>;
@@ -138,9 +216,8 @@
#size-cells = <0>;
num-cs = <1>;
clocks = <&spiclk>;
- interrupts = <3 4>;
+ interrupts = <4 4>;
interrupt-parent = <&plic0>;
-
flash@0 {
compatible = "spi-flash";
spi-max-frequency = <50000000>;
diff --git a/arch/riscv/dts/ae350_32.dts b/arch/riscv/dts/ae350_32.dts
new file mode 100644
index 0000000000..0679827313
--- /dev/null
+++ b/arch/riscv/dts/ae350_32.dts
@@ -0,0 +1,229 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "andestech,a25";
+ model = "andestech,a25";
+
+ aliases {
+ uart0 = &serial0;
+ spi0 = &spi;
+ };
+
+ chosen {
+ bootargs = "console=ttyS0,38400n8 debug loglevel=7";
+ stdout-path = "uart0:38400n8";
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ timebase-frequency = <60000000>;
+ CPU0: cpu@0 {
+ device_type = "cpu";
+ reg = <0>;
+ status = "okay";
+ compatible = "riscv";
+ riscv,isa = "rv32imafdc";
+ mmu-type = "riscv,sv32";
+ clock-frequency = <60000000>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <32>;
+ CPU0_intc: interrupt-controller {
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ compatible = "riscv,cpu-intc";
+ };
+ };
+ };
+
+ memory@0 {
+ device_type = "memory";
+ reg = <0x00000000 0x40000000>;
+ };
+
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "andestech,riscv-ae350-soc";
+ ranges;
+
+ plic0: interrupt-controller@e4000000 {
+ compatible = "riscv,plic0";
+ #address-cells = <1>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ reg = <0xe4000000 0x2000000>;
+ riscv,ndev=<71>;
+ interrupts-extended = <&CPU0_intc 11 &CPU0_intc 9>;
+ };
+
+ plic1: interrupt-controller@e6400000 {
+ compatible = "riscv,plic1";
+ #address-cells = <1>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ reg = <0xe6400000 0x400000>;
+ riscv,ndev=<1>;
+ interrupts-extended = <&CPU0_intc 3>;
+ };
+
+ plmt0@e6000000 {
+ compatible = "riscv,plmt0";
+ interrupts-extended = <&CPU0_intc 7>;
+ reg = <0xe6000000 0x100000>;
+ };
+ };
+
+ spiclk: virt_100mhz {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <100000000>;
+ };
+
+ timer0: timer@f0400000 {
+ compatible = "andestech,atcpit100";
+ reg = <0xf0400000 0x1000>;
+ clock-frequency = <60000000>;
+ interrupts = <3 4>;
+ interrupt-parent = <&plic0>;
+ };
+
+ serial0: serial@f0300000 {
+ compatible = "andestech,uart16550", "ns16550a";
+ reg = <0xf0300000 0x1000>;
+ interrupts = <9 4>;
+ clock-frequency = <19660800>;
+ reg-shift = <2>;
+ reg-offset = <32>;
+ no-loopback-test = <1>;
+ interrupt-parent = <&plic0>;
+ };
+
+ mac0: mac@e0100000 {
+ compatible = "andestech,atmac100";
+ reg = <0xe0100000 0x1000>;
+ interrupts = <19 4>;
+ interrupt-parent = <&plic0>;
+ };
+
+ mmc0: mmc@f0e00000 {
+ compatible = "andestech,atfsdc010";
+ max-frequency = <100000000>;
+ clock-freq-min-max = <400000 100000000>;
+ fifo-depth = <0x10>;
+ reg = <0xf0e00000 0x1000>;
+ interrupts = <18 4>;
+ cap-sd-highspeed;
+ interrupt-parent = <&plic0>;
+ };
+
+ dma0: dma@f0c00000 {
+ compatible = "andestech,atcdmac300";
+ reg = <0xf0c00000 0x1000>;
+ interrupts = <10 4 64 4 65 4 66 4 67 4 68 4 69 4 70 4 71 4>;
+ dma-channels = <8>;
+ interrupt-parent = <&plic0>;
+ };
+
+ lcd0: lcd@e0200000 {
+ compatible = "andestech,atflcdc100";
+ reg = <0xe0200000 0x1000>;
+ interrupts = <20 4>;
+ interrupt-parent = <&plic0>;
+ };
+
+ smc0: smc@e0400000 {
+ compatible = "andestech,atfsmc020";
+ reg = <0xe0400000 0x1000>;
+ };
+
+ snd0: snd@f0d00000 {
+ compatible = "andestech,atfac97";
+ reg = <0xf0d00000 0x1000>;
+ interrupts = <17 4>;
+ interrupt-parent = <&plic0>;
+ };
+
+ virtio_mmio@fe007000 {
+ interrupts = <0x17 0x4>;
+ interrupt-parent = <0x2>;
+ reg = <0xfe007000 0x1000>;
+ compatible = "virtio,mmio";
+ };
+
+ virtio_mmio@fe006000 {
+ interrupts = <0x16 0x4>;
+ interrupt-parent = <0x2>;
+ reg = <0xfe006000 0x1000>;
+ compatible = "virtio,mmio";
+ };
+
+ virtio_mmio@fe005000 {
+ interrupts = <0x15 0x4>;
+ interrupt-parent = <0x2>;
+ reg = <0xfe005000 0x1000>;
+ compatible = "virtio,mmio";
+ };
+
+ virtio_mmio@fe004000 {
+ interrupts = <0x14 0x4>;
+ interrupt-parent = <0x2>;
+ reg = <0xfe004000 0x1000>;
+ compatible = "virtio,mmio";
+ };
+
+ virtio_mmio@fe003000 {
+ interrupts = <0x13 0x4>;
+ interrupt-parent = <0x2>;
+ reg = <0xfe003000 0x1000>;
+ compatible = "virtio,mmio";
+ };
+
+ virtio_mmio@fe002000 {
+ interrupts = <0x12 0x4>;
+ interrupt-parent = <0x2>;
+ reg = <0xfe002000 0x1000>;
+ compatible = "virtio,mmio";
+ };
+
+ virtio_mmio@fe001000 {
+ interrupts = <0x11 0x4>;
+ interrupt-parent = <0x2>;
+ reg = <0xfe001000 0x1000>;
+ compatible = "virtio,mmio";
+ };
+
+ virtio_mmio@fe000000 {
+ interrupts = <0x10 0x4>;
+ interrupt-parent = <0x2>;
+ reg = <0xfe000000 0x1000>;
+ compatible = "virtio,mmio";
+ };
+
+ nor@0,0 {
+ compatible = "cfi-flash";
+ reg = <0x88000000 0x1000>;
+ bank-width = <2>;
+ device-width = <1>;
+ };
+
+ spi: spi@f0b00000 {
+ compatible = "andestech,atcspi200";
+ reg = <0xf0b00000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ num-cs = <1>;
+ clocks = <&spiclk>;
+ interrupts = <4 4>;
+ interrupt-parent = <&plic0>;
+ flash@0 {
+ compatible = "spi-flash";
+ spi-max-frequency = <50000000>;
+ reg = <0>;
+ spi-cpol;
+ spi-cpha;
+ };
+ };
+};
diff --git a/arch/riscv/dts/ae350_64.dts b/arch/riscv/dts/ae350_64.dts
new file mode 100644
index 0000000000..e48c298645
--- /dev/null
+++ b/arch/riscv/dts/ae350_64.dts
@@ -0,0 +1,229 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ compatible = "andestech,ax25";
+ model = "andestech,ax25";
+
+ aliases {
+ uart0 = &serial0;
+ spi0 = &spi;
+ };
+
+ chosen {
+ bootargs = "console=ttyS0,38400n8 debug loglevel=7";
+ stdout-path = "uart0:38400n8";
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ timebase-frequency = <60000000>;
+ CPU0: cpu@0 {
+ device_type = "cpu";
+ reg = <0>;
+ status = "okay";
+ compatible = "riscv";
+ riscv,isa = "rv64imafdc";
+ mmu-type = "riscv,sv39";
+ clock-frequency = <60000000>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <32>;
+ CPU0_intc: interrupt-controller {
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ compatible = "riscv,cpu-intc";
+ };
+ };
+ };
+
+ memory@0 {
+ device_type = "memory";
+ reg = <0x0 0x00000000 0x0 0x40000000>;
+ };
+
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ compatible = "andestech,riscv-ae350-soc";
+ ranges;
+
+ plic0: interrupt-controller@e4000000 {
+ compatible = "riscv,plic0";
+ #address-cells = <2>;
+ #interrupt-cells = <2>;
+ interrupt-controller;
+ reg = <0x0 0xe4000000 0x0 0x2000000>;
+ riscv,ndev=<71>;
+ interrupts-extended = <&CPU0_intc 11 &CPU0_intc 9>;
+ };
+
+ plic1: interrupt-controller@e6400000 {
+ compatible = "riscv,plic1";
+ #address-cells = <2>;
+ #interrupt-cells = <2>;
+ interrupt-controller;
+ reg = <0x0 0xe6400000 0x0 0x400000>;
+ riscv,ndev=<1>;
+ interrupts-extended = <&CPU0_intc 3>;
+ };
+
+ plmt0@e6000000 {
+ compatible = "riscv,plmt0";
+ interrupts-extended = <&CPU0_intc 7>;
+ reg = <0x0 0xe6000000 0x0 0x100000>;
+ };
+ };
+
+ spiclk: virt_100mhz {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <100000000>;
+ };
+
+ timer0: timer@f0400000 {
+ compatible = "andestech,atcpit100";
+ reg = <0x0 0xf0400000 0x0 0x1000>;
+ clock-frequency = <60000000>;
+ interrupts = <3 4>;
+ interrupt-parent = <&plic0>;
+ };
+
+ serial0: serial@f0300000 {
+ compatible = "andestech,uart16550", "ns16550a";
+ reg = <0x0 0xf0300000 0x0 0x1000>;
+ interrupts = <9 4>;
+ clock-frequency = <19660800>;
+ reg-shift = <2>;
+ reg-offset = <32>;
+ no-loopback-test = <1>;
+ interrupt-parent = <&plic0>;
+ };
+
+ mac0: mac@e0100000 {
+ compatible = "andestech,atmac100";
+ reg = <0x0 0xe0100000 0x0 0x1000>;
+ interrupts = <19 4>;
+ interrupt-parent = <&plic0>;
+ };
+
+ mmc0: mmc@f0e00000 {
+ compatible = "andestech,atfsdc010";
+ max-frequency = <100000000>;
+ clock-freq-min-max = <400000 100000000>;
+ fifo-depth = <0x10>;
+ reg = <0x0 0xf0e00000 0x0 0x1000>;
+ interrupts = <18 4>;
+ cap-sd-highspeed;
+ interrupt-parent = <&plic0>;
+ };
+
+ dma0: dma@f0c00000 {
+ compatible = "andestech,atcdmac300";
+ reg = <0x0 0xf0c00000 0x0 0x1000>;
+ interrupts = <10 4 64 4 65 4 66 4 67 4 68 4 69 4 70 4 71 4>;
+ dma-channels = <8>;
+ interrupt-parent = <&plic0>;
+ };
+
+ lcd0: lcd@e0200000 {
+ compatible = "andestech,atflcdc100";
+ reg = <0x0 0xe0200000 0x0 0x1000>;
+ interrupts = <20 4>;
+ interrupt-parent = <&plic0>;
+ };
+
+ smc0: smc@e0400000 {
+ compatible = "andestech,atfsmc020";
+ reg = <0x0 0xe0400000 0x0 0x1000>;
+ };
+
+ snd0: snd@f0d00000 {
+ compatible = "andestech,atfac97";
+ reg = <0x0 0xf0d00000 0x0 0x1000>;
+ interrupts = <17 4>;
+ interrupt-parent = <&plic0>;
+ };
+
+ virtio_mmio@fe007000 {
+ interrupts = <0x17 0x4>;
+ interrupt-parent = <0x2>;
+ reg = <0x0 0xfe007000 0x0 0x1000>;
+ compatible = "virtio,mmio";
+ };
+
+ virtio_mmio@fe006000 {
+ interrupts = <0x16 0x4>;
+ interrupt-parent = <0x2>;
+ reg = <0x0 0xfe006000 0x0 0x1000>;
+ compatible = "virtio,mmio";
+ };
+
+ virtio_mmio@fe005000 {
+ interrupts = <0x15 0x4>;
+ interrupt-parent = <0x2>;
+ reg = <0x0 0xfe005000 0x0 0x1000>;
+ compatible = "virtio,mmio";
+ };
+
+ virtio_mmio@fe004000 {
+ interrupts = <0x14 0x4>;
+ interrupt-parent = <0x2>;
+ reg = <0x0 0xfe004000 0x0 0x1000>;
+ compatible = "virtio,mmio";
+ };
+
+ virtio_mmio@fe003000 {
+ interrupts = <0x13 0x4>;
+ interrupt-parent = <0x2>;
+ reg = <0x0 0xfe003000 0x0 0x1000>;
+ compatible = "virtio,mmio";
+ };
+
+ virtio_mmio@fe002000 {
+ interrupts = <0x12 0x4>;
+ interrupt-parent = <0x2>;
+ reg = <0x0 0xfe002000 0x0 0x1000>;
+ compatible = "virtio,mmio";
+ };
+
+ virtio_mmio@fe001000 {
+ interrupts = <0x11 0x4>;
+ interrupt-parent = <0x2>;
+ reg = <0x0 0xfe001000 0x0 0x1000>;
+ compatible = "virtio,mmio";
+ };
+
+ virtio_mmio@fe000000 {
+ interrupts = <0x10 0x4>;
+ interrupt-parent = <0x2>;
+ reg = <0x0 0xfe000000 0x0 0x1000>;
+ compatible = "virtio,mmio";
+ };
+
+ nor@0,0 {
+ compatible = "cfi-flash";
+ reg = <0x0 0x88000000 0x0 0x1000>;
+ bank-width = <2>;
+ device-width = <1>;
+ };
+
+ spi: spi@f0b00000 {
+ compatible = "andestech,atcspi200";
+ reg = <0x0 0xf0b00000 0x0 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ num-cs = <1>;
+ clocks = <&spiclk>;
+ interrupts = <4 4>;
+ interrupt-parent = <&plic0>;
+ flash@0 {
+ compatible = "spi-flash";
+ spi-max-frequency = <50000000>;
+ reg = <0>;
+ spi-cpol;
+ spi-cpha;
+ };
+ };
+};
diff --git a/arch/riscv/include/asm/barrier.h b/arch/riscv/include/asm/barrier.h
new file mode 100644
index 0000000000..a3f60a8458
--- /dev/null
+++ b/arch/riscv/include/asm/barrier.h
@@ -0,0 +1,67 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2012 ARM Ltd.
+ * Copyright (C) 2013 Regents of the University of California
+ * Copyright (C) 2017 SiFive
+ *
+ * Taken from Linux arch/riscv/include/asm/barrier.h, which is based on
+ * arch/arm/include/asm/barrier.h
+ */
+
+#ifndef _ASM_RISCV_BARRIER_H
+#define _ASM_RISCV_BARRIER_H
+
+#ifndef __ASSEMBLY__
+
+#define nop() __asm__ __volatile__ ("nop")
+
+#define RISCV_FENCE(p, s) \
+ __asm__ __volatile__ ("fence " #p "," #s : : : "memory")
+
+/* These barriers need to enforce ordering on both devices or memory. */
+#define mb() RISCV_FENCE(iorw,iorw)
+#define rmb() RISCV_FENCE(ir,ir)
+#define wmb() RISCV_FENCE(ow,ow)
+
+/* These barriers do not need to enforce ordering on devices, just memory. */
+#define __smp_mb() RISCV_FENCE(rw,rw)
+#define __smp_rmb() RISCV_FENCE(r,r)
+#define __smp_wmb() RISCV_FENCE(w,w)
+
+#define __smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ RISCV_FENCE(rw,w); \
+ WRITE_ONCE(*p, v); \
+} while (0)
+
+#define __smp_load_acquire(p) \
+({ \
+ typeof(*p) ___p1 = READ_ONCE(*p); \
+ compiletime_assert_atomic_type(*p); \
+ RISCV_FENCE(r,rw); \
+ ___p1; \
+})
+
+/*
+ * This is a very specific barrier: it's currently only used in two places in
+ * the kernel, both in the scheduler. See include/linux/spinlock.h for the two
+ * orderings it guarantees, but the "critical section is RCsc" guarantee
+ * mandates a barrier on RISC-V. The sequence looks like:
+ *
+ * lr.aq lock
+ * sc lock <= LOCKED
+ * smp_mb__after_spinlock()
+ * // critical section
+ * lr lock
+ * sc.rl lock <= UNLOCKED
+ *
+ * The AQ/RL pair provides a RCpc critical section, but there's not really any
+ * way we can take advantage of that here because the ordering is only enforced
+ * on that one lock. Thus, we're just doing a full fence.
+ */
+#define smp_mb__after_spinlock() RISCV_FENCE(rw,rw)
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_RISCV_BARRIER_H */
diff --git a/arch/riscv/include/asm/cache.h b/arch/riscv/include/asm/cache.h
index ca83dd67c2..ec8fe201d3 100644
--- a/arch/riscv/include/asm/cache.h
+++ b/arch/riscv/include/asm/cache.h
@@ -7,6 +7,9 @@
#ifndef _ASM_RISCV_CACHE_H
#define _ASM_RISCV_CACHE_H
+/* cache */
+void cache_flush(void);
+
/*
* The current upper bound for RISCV L1 data cache line sizes is 32 bytes.
* We use that value for aligning DMA buffers unless the board config has
diff --git a/arch/riscv/include/asm/io.h b/arch/riscv/include/asm/io.h
index f4a76d8720..acf5a96449 100644
--- a/arch/riscv/include/asm/io.h
+++ b/arch/riscv/include/asm/io.h
@@ -10,22 +10,13 @@
#ifdef __KERNEL__
#include <linux/types.h>
+#include <asm/barrier.h>
#include <asm/byteorder.h>
static inline void sync(void)
{
}
-/*
- * Given a physical address and a length, return a virtual address
- * that can be used to access the memory range with the caching
- * properties specified by "flags".
- */
-#define MAP_NOCACHE (0)
-#define MAP_WRCOMBINE (0)
-#define MAP_WRBACK (0)
-#define MAP_WRTHROUGH (0)
-
#ifdef CONFIG_ARCH_MAP_SYSMEM
static inline void *map_sysmem(phys_addr_t paddr, unsigned long len)
{
@@ -48,24 +39,6 @@ static inline phys_addr_t map_to_sysmem(const void *ptr)
}
#endif
-static inline void *
-map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags)
-{
- return (void *)paddr;
-}
-
-/*
- * Take down a mapping set up by map_physmem().
- */
-static inline void unmap_physmem(void *vaddr, unsigned long flags)
-{
-}
-
-static inline phys_addr_t virt_to_phys(void *vaddr)
-{
- return (phys_addr_t)(vaddr);
-}
-
/*
* Generic virtual read/write. Note that we don't support half-word
* read/writes. We define __arch_*[bl] here, and leave __arch_*w
@@ -74,12 +47,12 @@ static inline phys_addr_t virt_to_phys(void *vaddr)
#define __arch_getb(a) (*(unsigned char *)(a))
#define __arch_getw(a) (*(unsigned short *)(a))
#define __arch_getl(a) (*(unsigned int *)(a))
-#define __arch_getq(a) (*(unsigned long *)(a))
+#define __arch_getq(a) (*(unsigned long long *)(a))
#define __arch_putb(v, a) (*(unsigned char *)(a) = (v))
#define __arch_putw(v, a) (*(unsigned short *)(a) = (v))
#define __arch_putl(v, a) (*(unsigned int *)(a) = (v))
-#define __arch_putq(v, a) (*(unsigned long *)(a) = (v))
+#define __arch_putq(v, a) (*(unsigned long long *)(a) = (v))
#define __raw_writeb(v, a) __arch_putb(v, a)
#define __raw_writew(v, a) __arch_putw(v, a)
@@ -91,13 +64,9 @@ static inline phys_addr_t virt_to_phys(void *vaddr)
#define __raw_readl(a) __arch_getl(a)
#define __raw_readq(a) __arch_getq(a)
-/*
- * TODO: The kernel offers some more advanced versions of barriers, it might
- * have some advantages to use them instead of the simple one here.
- */
-#define dmb() __asm__ __volatile__ ("" : : : "memory")
-#define __iormb() dmb()
-#define __iowmb() dmb()
+#define dmb() mb()
+#define __iormb() rmb()
+#define __iowmb() wmb()
static inline void writeb(u8 val, volatile void __iomem *addr)
{
@@ -152,7 +121,7 @@ static inline u32 readl(const volatile void __iomem *addr)
static inline u64 readq(const volatile void __iomem *addr)
{
- u32 val;
+ u64 val;
val = __arch_getq(addr);
__iormb();
@@ -487,4 +456,7 @@ out:
#endif /* __mem_isa */
#endif /* __KERNEL__ */
+
+#include <asm-generic/io.h>
+
#endif /* __ASM_RISCV_IO_H */
diff --git a/arch/riscv/include/asm/posix_types.h b/arch/riscv/include/asm/posix_types.h
index 7438dbeb03..0fc052082a 100644
--- a/arch/riscv/include/asm/posix_types.h
+++ b/arch/riscv/include/asm/posix_types.h
@@ -37,10 +37,10 @@ typedef unsigned short __kernel_gid_t;
#ifdef __GNUC__
typedef __SIZE_TYPE__ __kernel_size_t;
#else
-typedef unsigned int __kernel_size_t;
+typedef unsigned long __kernel_size_t;
#endif
-typedef int __kernel_ssize_t;
-typedef int __kernel_ptrdiff_t;
+typedef long __kernel_ssize_t;
+typedef long __kernel_ptrdiff_t;
typedef long __kernel_time_t;
typedef long __kernel_suseconds_t;
typedef long __kernel_clock_t;
diff --git a/arch/riscv/include/asm/types.h b/arch/riscv/include/asm/types.h
index bd8627196d..403cf9a48f 100644
--- a/arch/riscv/include/asm/types.h
+++ b/arch/riscv/include/asm/types.h
@@ -21,7 +21,11 @@ typedef unsigned short umode_t;
*/
#ifdef __KERNEL__
+#ifdef CONFIG_ARCH_RV64I
+#define BITS_PER_LONG 64
+#else
#define BITS_PER_LONG 32
+#endif
#include <stddef.h>
diff --git a/arch/riscv/lib/bootm.c b/arch/riscv/lib/bootm.c
index 2b5ccce933..124aeefff8 100644
--- a/arch/riscv/lib/bootm.c
+++ b/arch/riscv/lib/bootm.c
@@ -8,6 +8,8 @@
#include <common.h>
#include <command.h>
+#include <dm.h>
+#include <dm/root.h>
#include <image.h>
#include <asm/byteorder.h>
#include <asm/csr.h>
@@ -26,26 +28,41 @@ int arch_fixup_fdt(void *blob)
return 0;
}
-int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
+/**
+ * announce_and_cleanup() - Print message and prepare for kernel boot
+ *
+ * @fake: non-zero to do everything except actually boot
+ */
+static void announce_and_cleanup(int fake)
{
- void (*kernel)(ulong hart, void *dtb);
-
- /*
- * allow the PREP bootm subcommand, it is required for bootm to work
- */
- if (flag & BOOTM_STATE_OS_PREP)
- return 0;
+ printf("\nStarting kernel ...%s\n\n", fake ?
+ "(fake run for tracing)" : "");
+ bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel");
+#ifdef CONFIG_BOOTSTAGE_FDT
+ bootstage_fdt_add_report();
+#endif
+#ifdef CONFIG_BOOTSTAGE_REPORT
+ bootstage_report();
+#endif
- if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
- return 1;
+#ifdef CONFIG_USB_DEVICE
+ udc_disconnect();
+#endif
- kernel = (void (*)(ulong, void *))images->ep;
+ board_quiesce_devices();
- bootstage_mark(BOOTSTAGE_ID_RUN_OS);
+ /*
+ * Call remove function of all devices with a removal flag set.
+ * This may be useful for last-stage operations, like cancelling
+ * of DMA operation or releasing device internal buffers.
+ */
+ dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL);
- debug("## Transferring control to Linux (at address %08lx) ...\n",
- (ulong)kernel);
+ cleanup_before_linux();
+}
+static void boot_prep_linux(bootm_headers_t *images)
+{
if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len) {
#ifdef CONFIG_OF_LIBFDT
debug("using: FDT\n");
@@ -54,24 +71,50 @@ int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
hang();
}
#endif
+ } else {
+ printf("Device tree not found or missing FDT support\n");
+ hang();
}
+}
- /* we assume that the kernel is in place */
- printf("\nStarting kernel ...\n\n");
+static void boot_jump_linux(bootm_headers_t *images, int flag)
+{
+ void (*kernel)(ulong hart, void *dtb);
+ int fake = (flag & BOOTM_STATE_OS_FAKE_GO);
- /*
- * Call remove function of all devices with a removal flag set.
- * This may be useful for last-stage operations, like cancelling
- * of DMA operation or releasing device internal buffers.
- */
- dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL);
+ kernel = (void (*)(ulong, void *))images->ep;
- cleanup_before_linux();
+ bootstage_mark(BOOTSTAGE_ID_RUN_OS);
+
+ debug("## Transferring control to Linux (at address %08lx) ...\n",
+ (ulong)kernel);
- if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len)
- kernel(csr_read(mhartid), images->ft_addr);
+ announce_and_cleanup(fake);
- /* does not return */
+ if (!fake) {
+ if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len)
+ kernel(csr_read(mhartid), images->ft_addr);
+ }
+}
+
+int do_bootm_linux(int flag, int argc, char * const argv[],
+ bootm_headers_t *images)
+{
+ /* No need for those on RISC-V */
+ if (flag & BOOTM_STATE_OS_BD_T || flag & BOOTM_STATE_OS_CMDLINE)
+ return -1;
- return 1;
+ if (flag & BOOTM_STATE_OS_PREP) {
+ boot_prep_linux(images);
+ return 0;
+ }
+
+ if (flag & (BOOTM_STATE_OS_GO | BOOTM_STATE_OS_FAKE_GO)) {
+ boot_jump_linux(images, flag);
+ return 0;
+ }
+
+ boot_prep_linux(images);
+ boot_jump_linux(images, flag);
+ return 0;
}
diff --git a/arch/riscv/lib/cache.c b/arch/riscv/lib/cache.c
index 1d67c49c2c..ae5c60716f 100644
--- a/arch/riscv/lib/cache.c
+++ b/arch/riscv/lib/cache.c
@@ -6,44 +6,68 @@
#include <common.h>
+void invalidate_icache_all(void)
+{
+ asm volatile ("fence.i" ::: "memory");
+}
+
+void flush_dcache_all(void)
+{
+ asm volatile ("fence" :::"memory");
+}
void flush_dcache_range(unsigned long start, unsigned long end)
{
+ flush_dcache_all();
}
void invalidate_icache_range(unsigned long start, unsigned long end)
{
+ /*
+ * RISC-V does not have an instruction for invalidating parts of the
+ * instruction cache. Invalidate all of it instead.
+ */
+ invalidate_icache_all();
}
void invalidate_dcache_range(unsigned long start, unsigned long end)
{
+ flush_dcache_all();
+}
+
+void cache_flush(void)
+{
+ invalidate_icache_all();
+ flush_dcache_all();
}
void flush_cache(unsigned long addr, unsigned long size)
{
+ invalidate_icache_all();
+ flush_dcache_all();
}
-void icache_enable(void)
+__weak void icache_enable(void)
{
}
-void icache_disable(void)
+__weak void icache_disable(void)
{
}
-int icache_status(void)
+__weak int icache_status(void)
{
return 0;
}
-void dcache_enable(void)
+__weak void dcache_enable(void)
{
}
-void dcache_disable(void)
+__weak void dcache_disable(void)
{
}
-int dcache_status(void)
+__weak int dcache_status(void)
{
return 0;
}
diff --git a/arch/riscv/lib/interrupts.c b/arch/riscv/lib/interrupts.c
index 0a0995a7af..903a1c4cd5 100644
--- a/arch/riscv/lib/interrupts.c
+++ b/arch/riscv/lib/interrupts.c
@@ -12,7 +12,7 @@
#include <asm/system.h>
#include <asm/encoding.h>
-static void _exit_trap(int code, uint epc, struct pt_regs *regs);
+static void _exit_trap(ulong code, ulong epc, struct pt_regs *regs);
int interrupt_init(void)
{
@@ -34,9 +34,9 @@ int disable_interrupts(void)
return 0;
}
-uint handle_trap(uint mcause, uint epc, struct pt_regs *regs)
+ulong handle_trap(ulong mcause, ulong epc, struct pt_regs *regs)
{
- uint is_int;
+ ulong is_int;
is_int = (mcause & MCAUSE_INT);
if ((is_int) && ((mcause & MCAUSE_CAUSE) == IRQ_M_EXT))
@@ -60,16 +60,33 @@ __attribute__((weak)) void timer_interrupt(struct pt_regs *regs)
{
}
-static void _exit_trap(int code, uint epc, struct pt_regs *regs)
+static void _exit_trap(ulong code, ulong epc, struct pt_regs *regs)
{
static const char * const exception_code[] = {
"Instruction address misaligned",
"Instruction access fault",
"Illegal instruction",
"Breakpoint",
- "Load address misaligned"
+ "Load address misaligned",
+ "Load access fault",
+ "Store/AMO address misaligned",
+ "Store/AMO access fault",
+ "Environment call from U-mode",
+ "Environment call from S-mode",
+ "Reserved",
+ "Environment call from M-mode",
+ "Instruction page fault",
+ "Load page fault",
+ "Reserved",
+ "Store/AMO page fault",
};
- printf("exception code: %d , %s , epc %08x , ra %08lx\n",
- code, exception_code[code], epc, regs->ra);
+ if (code < ARRAY_SIZE(exception_code)) {
+ printf("exception code: %ld , %s , epc %lx , ra %lx\n",
+ code, exception_code[code], epc, regs->ra);
+ } else {
+ printf("Reserved\n");
+ }
+
+ hang();
}
diff --git a/arch/riscv/lib/setjmp.S b/arch/riscv/lib/setjmp.S
index 8f5a6a23aa..72bc9241f6 100644
--- a/arch/riscv/lib/setjmp.S
+++ b/arch/riscv/lib/setjmp.S
@@ -6,7 +6,7 @@
#include <config.h>
#include <linux/linkage.h>
-#ifdef CONFIG_CPU_RISCV_64
+#ifdef CONFIG_ARCH_RV64I
#define STORE_IDX(reg, idx) sd reg, (idx*8)(a0)
#define LOAD_IDX(reg, idx) ld reg, (idx*8)(a0)
#else
diff --git a/arch/sandbox/cpu/eth-raw-os.c b/arch/sandbox/cpu/eth-raw-os.c
index 75bfaa4c90..8d05bc2eda 100644
--- a/arch/sandbox/cpu/eth-raw-os.c
+++ b/arch/sandbox/cpu/eth-raw-os.c
@@ -11,6 +11,7 @@
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -23,6 +24,8 @@
#include <linux/if_ether.h>
#include <linux/if_packet.h>
+#include <os.h>
+
struct sandbox_eth_raw_if_nameindex *sandbox_eth_raw_if_nameindex(void)
{
return (struct sandbox_eth_raw_if_nameindex *)if_nameindex();
@@ -71,7 +74,7 @@ static int _raw_packet_start(struct eth_sandbox_raw_priv *priv,
/* Prepare device struct */
priv->local_bind_sd = -1;
- priv->device = malloc(sizeof(struct sockaddr_ll));
+ priv->device = os_malloc(sizeof(struct sockaddr_ll));
if (priv->device == NULL)
return -ENOMEM;
device = priv->device;
@@ -144,7 +147,7 @@ static int _local_inet_start(struct eth_sandbox_raw_priv *priv)
/* Prepare device struct */
priv->local_bind_sd = -1;
priv->local_bind_udp_port = 0;
- priv->device = malloc(sizeof(struct sockaddr_in));
+ priv->device = os_malloc(sizeof(struct sockaddr_in));
if (priv->device == NULL)
return -ENOMEM;
device = priv->device;
@@ -279,7 +282,7 @@ int sandbox_eth_raw_os_recv(void *packet, int *length,
void sandbox_eth_raw_os_stop(struct eth_sandbox_raw_priv *priv)
{
- free(priv->device);
+ os_free(priv->device);
priv->device = NULL;
close(priv->sd);
priv->sd = -1;
diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c
index 3e0f4c30af..aa92694342 100644
--- a/arch/sandbox/cpu/os.c
+++ b/arch/sandbox/cpu/os.c
@@ -381,7 +381,7 @@ void os_dirent_free(struct os_dirent_node *node)
while (node) {
next = node->next;
- free(node);
+ os_free(node);
node = next;
}
}
@@ -406,7 +406,7 @@ int os_dirent_ls(const char *dirname, struct os_dirent_node **headp)
/* Create a buffer upfront, with typically sufficient size */
dirlen = strlen(dirname) + 2;
len = dirlen + 256;
- fname = malloc(len);
+ fname = os_malloc(len);
if (!fname) {
ret = -ENOMEM;
goto done;
@@ -419,7 +419,7 @@ int os_dirent_ls(const char *dirname, struct os_dirent_node **headp)
ret = errno;
break;
}
- next = malloc(sizeof(*node) + strlen(entry->d_name) + 1);
+ next = os_malloc(sizeof(*node) + strlen(entry->d_name) + 1);
if (!next) {
os_dirent_free(head);
ret = -ENOMEM;
@@ -428,10 +428,10 @@ int os_dirent_ls(const char *dirname, struct os_dirent_node **headp)
if (dirlen + strlen(entry->d_name) > len) {
len = dirlen + strlen(entry->d_name);
old_fname = fname;
- fname = realloc(fname, len);
+ fname = os_realloc(fname, len);
if (!fname) {
- free(old_fname);
- free(next);
+ os_free(old_fname);
+ os_free(next);
os_dirent_free(head);
ret = -ENOMEM;
goto done;
@@ -465,7 +465,7 @@ int os_dirent_ls(const char *dirname, struct os_dirent_node **headp)
done:
closedir(dir);
- free(fname);
+ os_free(fname);
return ret;
}
@@ -563,20 +563,48 @@ static int make_exec(char *fname, const void *data, int size)
return 0;
}
-static int add_args(char ***argvp, const char *add_args[], int count)
+/**
+ * add_args() - Allocate a new argv with the given args
+ *
+ * This is used to create a new argv array with all the old arguments and some
+ * new ones that are passed in
+ *
+ * @argvp: Returns newly allocated args list
+ * @add_args: Arguments to add, each a string
+ * @count: Number of arguments in @add_args
+ * @return 0 if OK, -ENOMEM if out of memory
+ */
+static int add_args(char ***argvp, char *add_args[], int count)
{
- char **argv;
+ char **argv, **ap;
int argc;
- for (argv = *argvp, argc = 0; (*argvp)[argc]; argc++)
+ for (argc = 0; (*argvp)[argc]; argc++)
;
- argv = malloc((argc + count + 1) * sizeof(char *));
+ argv = os_malloc((argc + count + 1) * sizeof(char *));
if (!argv) {
printf("Out of memory for %d argv\n", count);
return -ENOMEM;
}
- memcpy(argv, *argvp, argc * sizeof(char *));
+ for (ap = *argvp, argc = 0; *ap; ap++) {
+ char *arg = *ap;
+
+ /* Drop args that we don't want to propagate */
+ if (*arg == '-' && strlen(arg) == 2) {
+ switch (arg[1]) {
+ case 'j':
+ case 'm':
+ ap++;
+ continue;
+ }
+ } else if (!strcmp(arg, "--rm_memory")) {
+ ap++;
+ continue;
+ }
+ argv[argc++] = arg;
+ }
+
memcpy(argv + argc, add_args, count * sizeof(char *));
argv[argc + count] = NULL;
@@ -584,21 +612,27 @@ static int add_args(char ***argvp, const char *add_args[], int count)
return 0;
}
-int os_jump_to_image(const void *dest, int size)
+/**
+ * os_jump_to_file() - Jump to a new program
+ *
+ * This saves the memory buffer, sets up arguments to the new process, then
+ * execs it.
+ *
+ * @fname: Filename to exec
+ * @return does not return on success, any return value is an error
+ */
+static int os_jump_to_file(const char *fname)
{
struct sandbox_state *state = state_get_current();
- char fname[30], mem_fname[30];
+ char mem_fname[30];
int fd, err;
- const char *extra_args[5];
+ char *extra_args[5];
char **argv = state->argv;
+ int argc;
#ifdef DEBUG
- int argc, i;
+ int i;
#endif
- err = make_exec(fname, dest, size);
- if (err)
- return err;
-
strcpy(mem_fname, "/tmp/u-boot.mem.XXXXXX");
fd = mkstemp(mem_fname);
if (fd < 0)
@@ -611,14 +645,16 @@ int os_jump_to_image(const void *dest, int size)
os_fd_restore();
extra_args[0] = "-j";
- extra_args[1] = fname;
+ extra_args[1] = (char *)fname;
extra_args[2] = "-m";
extra_args[3] = mem_fname;
- extra_args[4] = "--rm_memory";
- err = add_args(&argv, extra_args,
- sizeof(extra_args) / sizeof(extra_args[0]));
+ argc = 4;
+ if (state->ram_buf_rm)
+ extra_args[argc++] = "--rm_memory";
+ err = add_args(&argv, extra_args, argc);
if (err)
return err;
+ argv[0] = (char *)fname;
#ifdef DEBUG
for (i = 0; argv[i]; i++)
@@ -629,13 +665,28 @@ int os_jump_to_image(const void *dest, int size)
os_exit(2);
err = execv(fname, argv);
- free(argv);
- if (err)
+ os_free(argv);
+ if (err) {
+ perror("Unable to run image");
+ printf("Image filename '%s'\n", mem_fname);
return err;
+ }
return unlink(fname);
}
+int os_jump_to_image(const void *dest, int size)
+{
+ char fname[30];
+ int err;
+
+ err = make_exec(fname, dest, size);
+ if (err)
+ return err;
+
+ return os_jump_to_file(fname);
+}
+
int os_find_u_boot(char *fname, int maxlen)
{
struct sandbox_state *state = state_get_current();
@@ -699,17 +750,7 @@ int os_find_u_boot(char *fname, int maxlen)
int os_spl_to_uboot(const char *fname)
{
- struct sandbox_state *state = state_get_current();
- char *argv[state->argc + 1];
- int ret;
-
- memcpy(argv, state->argv, sizeof(char *) * (state->argc + 1));
- argv[0] = (char *)fname;
- ret = execv(fname, argv);
- if (ret)
- return ret;
-
- return unlink(fname);
+ return os_jump_to_file(fname);
}
void os_localtime(struct rtc_time *rt)
diff --git a/arch/sandbox/cpu/spl.c b/arch/sandbox/cpu/spl.c
index 42c149a498..5005ed2f54 100644
--- a/arch/sandbox/cpu/spl.c
+++ b/arch/sandbox/cpu/spl.c
@@ -37,12 +37,39 @@ static int spl_board_load_image(struct spl_image_info *spl_image,
return ret;
}
- /* Hopefully this will not return */
- return os_spl_to_uboot(fname);
+ /* Set up spl_image to boot from jump_to_image_no_args() */
+ spl_image->arg = strdup(fname);
+ if (!spl_image->arg)
+ return log_msg_ret("Setup exec filename", -ENOMEM);
+
+ return 0;
}
SPL_LOAD_IMAGE_METHOD("sandbox", 0, BOOT_DEVICE_BOARD, spl_board_load_image);
void spl_board_init(void)
{
+ struct sandbox_state *state = state_get_current();
+ struct udevice *dev;
+
preloader_console_init();
+ if (state->show_of_platdata) {
+ /*
+ * Scan all the devices so that we can output their platform
+ * data. See sandbox_spl_probe().
+ */
+ printf("Scanning misc devices\n");
+ for (uclass_first_device(UCLASS_MISC, &dev);
+ dev;
+ uclass_next_device(&dev))
+ ;
+ }
+}
+
+void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
+{
+ const char *fname = spl_image->arg;
+
+ os_fd_restore();
+ os_spl_to_uboot(fname);
+ hang();
}
diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c
index 2ee3b48565..b1566a8143 100644
--- a/arch/sandbox/cpu/start.c
+++ b/arch/sandbox/cpu/start.c
@@ -283,6 +283,15 @@ static int sandbox_cmdline_cb_log_level(struct sandbox_state *state,
SANDBOX_CMDLINE_OPT_SHORT(log_level, 'L', 1,
"Set log level (0=panic, 7=debug)");
+static int sandbox_cmdline_cb_show_of_platdata(struct sandbox_state *state,
+ const char *arg)
+{
+ state->show_of_platdata = true;
+
+ return 0;
+}
+SANDBOX_CMDLINE_OPT(show_of_platdata, 0, "Show of-platdata in SPL");
+
int board_run_command(const char *cmdline)
{
printf("## Commands are disabled. Please enable CONFIG_CMDLINE.\n");
@@ -296,6 +305,16 @@ static void setup_ram_buf(struct sandbox_state *state)
gd->ram_size = state->ram_size;
}
+void state_show(struct sandbox_state *state)
+{
+ char **p;
+
+ printf("Arguments:\n");
+ for (p = state->argv; *p; p++)
+ printf("%s ", *p);
+ printf("\n");
+}
+
int main(int argc, char *argv[])
{
struct sandbox_state *state;
diff --git a/arch/sandbox/cpu/u-boot-spl.lds b/arch/sandbox/cpu/u-boot-spl.lds
index f97abdfa05..de65b01b33 100644
--- a/arch/sandbox/cpu/u-boot-spl.lds
+++ b/arch/sandbox/cpu/u-boot-spl.lds
@@ -14,7 +14,7 @@ SECTIONS
}
__u_boot_sandbox_option_start = .;
- _u_boot_sandbox_getopt : { *(.u_boot_sandbox_getopt) }
+ _u_boot_sandbox_getopt : { KEEP(*(.u_boot_sandbox_getopt)) }
__u_boot_sandbox_option_end = .;
__bss_start = .;
diff --git a/arch/sandbox/include/asm/handoff.h b/arch/sandbox/include/asm/handoff.h
new file mode 100644
index 0000000000..be4e7b0fae
--- /dev/null
+++ b/arch/sandbox/include/asm/handoff.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Architecture-specific SPL handoff information for sandbox
+ *
+ * Copyright 2018 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#ifndef __handoff_h
+#define __handoff_h
+
+#define TEST_HANDOFF_MAGIC 0x14f93c7b
+
+struct arch_spl_handoff {
+ ulong magic; /* Used for testing */
+};
+
+#endif
diff --git a/arch/sandbox/include/asm/state.h b/arch/sandbox/include/asm/state.h
index dcb6d5f568..8fabe70a86 100644
--- a/arch/sandbox/include/asm/state.h
+++ b/arch/sandbox/include/asm/state.h
@@ -89,6 +89,7 @@ struct sandbox_state {
bool skip_delays; /* Ignore any time delays (for test) */
bool show_test_output; /* Don't suppress stdout in tests */
int default_log_level; /* Default log level for sandbox */
+ bool show_of_platdata; /* Show of-platdata in SPL */
/* Pointer to information for each SPI bus/cs */
struct sandbox_spi_info spi[CONFIG_SANDBOX_SPI_MAX_BUS]
@@ -242,6 +243,13 @@ bool state_get_skip_delays(void);
void state_reset_for_test(struct sandbox_state *state);
/**
+ * state_show() - Show information about the sandbox state
+ *
+ * @param state Sandbox state to show
+ */
+void state_show(struct sandbox_state *state);
+
+/**
* Initialize the test system state
*/
int state_init(void);
diff --git a/board/AndesTech/ax25-ae350/MAINTAINERS b/board/AndesTech/ax25-ae350/MAINTAINERS
index 508c6ace72..d87446ee1c 100644
--- a/board/AndesTech/ax25-ae350/MAINTAINERS
+++ b/board/AndesTech/ax25-ae350/MAINTAINERS
@@ -3,4 +3,6 @@ M: Rick Chen <rick@andestech.com>
S: Maintained
F: board/AndesTech/ax25-ae350/
F: include/configs/ax25-ae350.h
+F: configs/a25-ae350_32_defconfig
+F: configs/ax25-ae350_64_defconfig
F: configs/ax25-ae350_defconfig
diff --git a/board/amlogic/odroid-c2/MAINTAINERS b/board/amlogic/odroid-c2/MAINTAINERS
index fd74d53bfe..6a853066d7 100644
--- a/board/amlogic/odroid-c2/MAINTAINERS
+++ b/board/amlogic/odroid-c2/MAINTAINERS
@@ -4,4 +4,5 @@ M: Neil Armstrong <narmstrong@baylibre.com>
S: Maintained
F: board/amlogic/odroid-c2/
F: include/configs/odroid-c2.h
+F: configs/nanopi-k2_defconfig
F: configs/odroid-c2_defconfig
diff --git a/board/amlogic/p212/MAINTAINERS b/board/amlogic/p212/MAINTAINERS
index 6575f17e14..07ca6f204d 100644
--- a/board/amlogic/p212/MAINTAINERS
+++ b/board/amlogic/p212/MAINTAINERS
@@ -3,4 +3,6 @@ M: Neil Armstrong <narmstrong@baylibre.com>
S: Maintained
F: board/amlogic/p212/
F: include/configs/p212.h
+F: configs/khadas-vim_defconfig
+F: configs/libretech-cc_defconfig
F: configs/p212_defconfig
diff --git a/board/armltd/integrator/README b/board/armltd/integrator/README
index 5a0e934924..af9dcc1f4f 100644
--- a/board/armltd/integrator/README
+++ b/board/armltd/integrator/README
@@ -36,9 +36,7 @@ In case c) it may be necessary for U-Boot to perform CM dependent initialization
Configuring U-Boot :
------------------
The makefile contains targets for Integrator platforms of both types
-fitted with all current variants of CM. If these targets are to be used with
-boot process c) above then CONFIG_INIT_CRITICAL may need to be defined to ensure
-that the CM is correctly configured.
+fitted with all current variants of CM.
There are also targets independent of CM. These may not be suitable for
boot process c) above. They have been preserved for backward compatibility with
diff --git a/board/emulation/qemu-riscv/Kconfig b/board/emulation/qemu-riscv/Kconfig
index 37a80db6a9..33ca253432 100644
--- a/board/emulation/qemu-riscv/Kconfig
+++ b/board/emulation/qemu-riscv/Kconfig
@@ -29,5 +29,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy
imply CMD_EXT2
imply CMD_EXT4
imply CMD_FAT
+ imply BOARD_LATE_INIT
+ imply OF_BOARD_SETUP
endif
diff --git a/board/emulation/qemu-riscv/qemu-riscv.c b/board/emulation/qemu-riscv/qemu-riscv.c
index 2730a288fb..d6167aaef1 100644
--- a/board/emulation/qemu-riscv/qemu-riscv.c
+++ b/board/emulation/qemu-riscv/qemu-riscv.c
@@ -9,8 +9,6 @@
#include <virtio_types.h>
#include <virtio.h>
-#define MROM_FDT_ADDR 0x1020
-
int board_init(void)
{
/*
@@ -22,11 +20,70 @@ int board_init(void)
return 0;
}
-void *board_fdt_blob_setup(void)
+int board_late_init(void)
{
- /*
- * QEMU loads a generated DTB for us immediately
- * after the reset vectors in the MROM
- */
- return (void *)MROM_FDT_ADDR;
+ ulong kernel_start;
+ ofnode chosen_node;
+ int ret;
+
+ chosen_node = ofnode_path("/chosen");
+ if (!ofnode_valid(chosen_node)) {
+ debug("No chosen node found, can't get kernel start address\n");
+ return 0;
+ }
+
+#ifdef CONFIG_ARCH_RV64I
+ ret = ofnode_read_u64(chosen_node, "riscv,kernel-start",
+ (u64 *)&kernel_start);
+#else
+ ret = ofnode_read_u32(chosen_node, "riscv,kernel-start",
+ (u32 *)&kernel_start);
+#endif
+ if (ret) {
+ debug("Can't find kernel start address in device tree\n");
+ return 0;
+ }
+
+ env_set_hex("kernel_start", kernel_start);
+
+ return 0;
+}
+
+/*
+ * QEMU specifies the location of Linux (supplied with the -kernel argument)
+ * in the device tree using the riscv,kernel-start and riscv,kernel-end
+ * properties. We currently rely on the SBI implementation of BBL to run
+ * Linux and therefore embed Linux as payload in BBL. This causes an issue,
+ * because BBL detects the kernel properties in the device tree and ignores
+ * the Linux payload as a result. To work around this issue, we clear the
+ * kernel properties before booting Linux.
+ *
+ * This workaround can be removed, once we do not require BBL for its SBI
+ * implementation anymore.
+ */
+int ft_board_setup(void *blob, bd_t *bd)
+{
+ int chosen_offset, ret;
+
+ chosen_offset = fdt_path_offset(blob, "/chosen");
+ if (chosen_offset < 0)
+ return 0;
+
+#ifdef CONFIG_ARCH_RV64I
+ ret = fdt_setprop_u64(blob, chosen_offset, "riscv,kernel-start", 0);
+#else
+ ret = fdt_setprop_u32(blob, chosen_offset, "riscv,kernel-start", 0);
+#endif
+ if (ret)
+ return ret;
+
+#ifdef CONFIG_ARCH_RV64I
+ ret = fdt_setprop_u64(blob, chosen_offset, "riscv,kernel-end", 0);
+#else
+ ret = fdt_setprop_u32(blob, chosen_offset, "riscv,kernel-end", 0);
+#endif
+ if (ret)
+ return ret;
+
+ return 0;
}
diff --git a/board/grinn/chiliboard/board.c b/board/grinn/chiliboard/board.c
index 73a7d8281c..dc0de620fc 100644
--- a/board/grinn/chiliboard/board.c
+++ b/board/grinn/chiliboard/board.c
@@ -19,7 +19,6 @@
#include <environment.h>
#include <errno.h>
#include <miiphy.h>
-#include <serial.h>
#include <spl.h>
#include <watchdog.h>
@@ -69,13 +68,6 @@ static void enable_board_pin_mux(void)
}
#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
-#ifndef CONFIG_DM_SERIAL
-struct serial_device *default_serial_console(void)
-{
- return &eserial1_device;
-}
-#endif
-
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
void set_uart_mux_conf(void)
{
@@ -150,56 +142,3 @@ int board_late_init(void)
return 0;
}
#endif
-
-#if !defined(CONFIG_DM_ETH) && defined(CONFIG_DRIVER_TI_CPSW) && \
- !defined(CONFIG_SPL_BUILD)
-static void cpsw_control(int enabled)
-{
- /* VTP can be added here */
-
- return;
-}
-
-static struct cpsw_slave_data cpsw_slaves[] = {
- {
- .slave_reg_ofs = 0x208,
- .sliver_reg_ofs = 0xd80,
- .phy_addr = 0,
- }
-};
-
-static struct cpsw_platform_data cpsw_data = {
- .mdio_base = CPSW_MDIO_BASE,
- .cpsw_base = CPSW_BASE,
- .mdio_div = 0xff,
- .channels = 8,
- .cpdma_reg_ofs = 0x800,
- .slaves = 1,
- .slave_data = cpsw_slaves,
- .ale_reg_ofs = 0xd00,
- .ale_entries = 1024,
- .host_port_reg_ofs = 0x108,
- .hw_stats_reg_ofs = 0x900,
- .bd_ram_ofs = 0x2000,
- .mac_control = (1 << 5),
- .control = cpsw_control,
- .host_port_num = 0,
- .version = CPSW_CTRL_VERSION_2,
-};
-
-int board_eth_init(bd_t *bis)
-{
- int rv, n = 0;
-
- writel(RMII_MODE_ENABLE | RMII_CHIPCKL_ENABLE, &cdev->miisel);
- cpsw_slaves[0].phy_if = PHY_INTERFACE_MODE_RMII;
-
- rv = cpsw_register(&cpsw_data);
- if (rv < 0)
- printf("Error %d registering CPSW switch\n", rv);
- else
- n += rv;
-
- return n;
-}
-#endif
diff --git a/board/mediatek/mt7623/Kconfig b/board/mediatek/mt7623/Kconfig
new file mode 100644
index 0000000000..a8c670e71f
--- /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 0000000000..eeb0375d70
--- /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 0000000000..2b42071c47
--- /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 0000000000..08468b50ea
--- /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/board/mediatek/mt7629/Kconfig b/board/mediatek/mt7629/Kconfig
new file mode 100644
index 0000000000..6055164b52
--- /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 0000000000..424f115167
--- /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 0000000000..83ccbba8c4
--- /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 0000000000..08468b50ea
--- /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/board/sandbox/README.sandbox b/board/sandbox/README.sandbox
index 0f59da4400..9b09404294 100644
--- a/board/sandbox/README.sandbox
+++ b/board/sandbox/README.sandbox
@@ -422,7 +422,19 @@ coverage in U-Boot is limited, as we need to work to improve it.
Note that many of these tests are implemented as commands which you can
run natively on your board if desired (and enabled).
-It would be useful to have a central script to run all of these.
+To run all tests use "make check".
+
+
+Memory Map
+----------
+
+Sandbox has its own emulated memory starting at 0. Here are some of the things
+that are mapped into that memory:
+
+ 0 CONFIG_SYS_FDT_LOAD_ADDR Device tree
+ e000 CONFIG_BLOBLIST_ADDR Blob list
+ 10000 CONFIG_MALLOC_F_ADDR Early memory allocation
+
--
Simon Glass <sjg@chromium.org>
diff --git a/cmd/Makefile b/cmd/Makefile
index 0534ddc679..5ec2f9e8eb 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -115,6 +115,7 @@ obj-$(CONFIG_CMD_ROCKUSB) += rockusb.o
obj-$(CONFIG_SANDBOX) += host.o
obj-$(CONFIG_CMD_SATA) += sata.o
obj-$(CONFIG_CMD_NVME) += nvme.o
+obj-$(CONFIG_SANDBOX) += sb.o
obj-$(CONFIG_CMD_SF) += sf.o
obj-$(CONFIG_CMD_SCSI) += scsi.o disk.o
obj-$(CONFIG_CMD_SHA1SUM) += sha1sum.o
diff --git a/cmd/bootmenu.c b/cmd/bootmenu.c
index 21f353ffd3..979ac4a638 100644
--- a/cmd/bootmenu.c
+++ b/cmd/bootmenu.c
@@ -253,6 +253,7 @@ static struct bootmenu_data *bootmenu_create(int delay)
int len;
char *sep;
+ char *default_str;
struct bootmenu_entry *entry;
menu = malloc(sizeof(struct bootmenu_data));
@@ -263,6 +264,10 @@ static struct bootmenu_data *bootmenu_create(int delay)
menu->active = 0;
menu->first = NULL;
+ default_str = env_get("bootmenu_default");
+ if (default_str)
+ menu->active = (int)simple_strtol(default_str, NULL, 10);
+
while ((option = bootmenu_getoption(i))) {
sep = strchr(option, '=');
if (!sep) {
diff --git a/cmd/host.c b/cmd/host.c
index 645dba4de8..f7d3eae5b1 100644
--- a/cmd/host.c
+++ b/cmd/host.c
@@ -168,11 +168,6 @@ static int do_host(cmd_tbl_t *cmdtp, int flag, int argc,
}
U_BOOT_CMD(
- sb, 8, 1, do_host,
- "Deprecated: use 'host' command instead.", ""
-);
-
-U_BOOT_CMD(
host, 8, 1, do_host,
"Miscellaneous host commands",
"load hostfs - <addr> <filename> [<bytes> <offset>] - "
diff --git a/cmd/sb.c b/cmd/sb.c
new file mode 100644
index 0000000000..5701e03797
--- /dev/null
+++ b/cmd/sb.c
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018, Google Inc.
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <spl.h>
+#include <asm/state.h>
+
+static int do_sb_handoff(cmd_tbl_t *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+#if CONFIG_IS_ENABLED(HANDOFF)
+ if (gd->spl_handoff)
+ printf("SPL handoff magic %lx\n", gd->spl_handoff->arch.magic);
+ else
+ printf("SPL handoff info not received\n");
+
+ return 0;
+#else
+ printf("Command not supported\n");
+
+ return CMD_RET_USAGE;
+#endif
+}
+
+static int do_sb_state(cmd_tbl_t *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ struct sandbox_state *state;
+
+ state = state_get_current();
+ state_show(state);
+
+ return 0;
+}
+
+static cmd_tbl_t cmd_sb_sub[] = {
+ U_BOOT_CMD_MKENT(handoff, 1, 0, do_sb_handoff, "", ""),
+ U_BOOT_CMD_MKENT(state, 1, 0, do_sb_state, "", ""),
+};
+
+static int do_sb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ cmd_tbl_t *c;
+
+ /* Skip past 'sb' */
+ argc--;
+ argv++;
+
+ c = find_cmd_tbl(argv[0], cmd_sb_sub, ARRAY_SIZE(cmd_sb_sub));
+ if (c)
+ return c->cmd(cmdtp, flag, argc, argv);
+ else
+ return CMD_RET_USAGE;
+}
+
+U_BOOT_CMD(
+ sb, 8, 1, do_sb,
+ "Sandbox status commands",
+ "handoff - Show handoff data received from SPL\n"
+ "sb state - Show sandbox state"
+);
diff --git a/common/Kconfig b/common/Kconfig
index ba460d9150..57bd16d962 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -299,6 +299,10 @@ config SPL_LOGLEVEL
int
default LOGLEVEL
+config TPL_LOGLEVEL
+ int
+ default LOGLEVEL
+
config SILENT_CONSOLE
bool "Support a silent console"
help
@@ -505,6 +509,24 @@ config SPL_LOG_MAX_LEVEL
6 - detail
7 - debug
+config TPL_LOG_MAX_LEVEL
+ int "Maximum log level to record in TPL"
+ depends on TPL_LOG
+ default 3
+ help
+ This selects the maximum log level that will be recorded. Any value
+ higher than this will be ignored. If possible log statements below
+ this level will be discarded at build time. Levels:
+
+ 0 - panic
+ 1 - critical
+ 2 - error
+ 3 - warning
+ 4 - note
+ 5 - info
+ 6 - detail
+ 7 - debug
+
config LOG_CONSOLE
bool "Allow log output to the console"
depends on LOG
@@ -515,9 +537,19 @@ config LOG_CONSOLE
log message is shown - other details like level, category, file and
line number are omitted.
-config LOG_SPL_CONSOLE
+config SPL_LOG_CONSOLE
+ bool "Allow log output to the console in SPL"
+ depends on SPL_LOG
+ default y
+ help
+ Enables a log driver which writes log records to the console.
+ Generally the console is the serial port or LCD display. Only the
+ log message is shown - other details like level, category, file and
+ line number are omitted.
+
+config TPL_LOG_CONSOLE
bool "Allow log output to the console in SPL"
- depends on LOG_SPL
+ depends on TPL_LOG
default y
help
Enables a log driver which writes log records to the console.
@@ -718,4 +750,52 @@ config UPDATE_TFTP_MSEC_MAX
endmenu
+menu "Blob list"
+
+config BLOBLIST
+ bool "Support for a bloblist"
+ help
+ This enables support for a bloblist in U-Boot, which can be passed
+ from TPL to SPL to U-Boot proper (and potentially to Linux). The
+ blob list supports multiple binary blobs of data, each with a tag,
+ so that different U-Boot components can store data which can survive
+ through to the next stage of the boot.
+
+config SPL_BLOBLIST
+ bool "Support for a bloblist in SPL"
+ depends on BLOBLIST
+ default y if SPL
+ help
+ This enables a bloblist in SPL. If this is the first part of U-Boot
+ to run, then the bloblist is set up in SPL and passed to U-Boot
+ proper. If TPL also has a bloblist, then SPL uses the one from there.
+
+config TPL_BLOBLIST
+ bool "Support for a bloblist in TPL"
+ depends on BLOBLIST
+ default y if TPL
+ help
+ This enables a bloblist in TPL. The bloblist is set up in TPL and
+ passed to SPL and U-Boot proper.
+
+config BLOBLIST_SIZE
+ hex "Size of bloblist"
+ depends on BLOBLIST
+ default 0x400
+ help
+ Sets the size of the bloblist in bytes. This must include all
+ overhead (alignment, bloblist header, record header). The bloblist
+ is set up in the first part of U-Boot to run (TPL, SPL or U-Boot
+ proper), and this sane bloblist is used for subsequent stages.
+
+config BLOBLIST_ADDR
+ hex "Address of bloblist"
+ depends on BLOBLIST
+ default 0xe000 if SANDBOX
+ help
+ Sets the address of the bloblist, set up by the first part of U-Boot
+ which runs. Subsequent U-Boot stages typically use the same address.
+
+endmenu
+
source "common/spl/Kconfig"
diff --git a/common/Makefile b/common/Makefile
index bbe2a6e239..65d89dc62d 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -33,7 +33,7 @@ obj-$(CONFIG_MII) += miiphyutil.o
obj-$(CONFIG_CMD_MII) += miiphyutil.o
obj-$(CONFIG_PHYLIB) += miiphyutil.o
-ifdef CONFIG_CMD_USB
+ifdef CONFIG_USB
obj-y += usb.o usb_hub.o
obj-$(CONFIG_USB_STORAGE) += usb_storage.o
endif
@@ -61,6 +61,7 @@ obj-$(CONFIG_CMDLINE) += cli_readline.o cli_simple.o
endif # !CONFIG_SPL_BUILD
obj-$(CONFIG_$(SPL_TPL_)BOOTSTAGE) += bootstage.o
+obj-$(CONFIG_$(SPL_TPL_)BLOBLIST) += bloblist.o
ifdef CONFIG_SPL_BUILD
ifdef CONFIG_SPL_DFU_SUPPORT
@@ -122,8 +123,8 @@ obj-y += cli.o
obj-$(CONFIG_FSL_DDR_INTERACTIVE) += cli_simple.o cli_readline.o
obj-$(CONFIG_DFU_OVER_USB) += dfu.o
obj-y += command.o
-obj-$(CONFIG_$(SPL_)LOG) += log.o
-obj-$(CONFIG_$(SPL_)LOG_CONSOLE) += log_console.o
+obj-$(CONFIG_$(SPL_TPL_)LOG) += log.o
+obj-$(CONFIG_$(SPL_TPL_)LOG_CONSOLE) += log_console.o
obj-y += s_record.o
obj-$(CONFIG_CMD_LOADB) += xyzModem.o
obj-$(CONFIG_$(SPL_TPL_)YMODEM_SUPPORT) += xyzModem.o
diff --git a/common/bloblist.c b/common/bloblist.c
new file mode 100644
index 0000000000..b4cf169b05
--- /dev/null
+++ b/common/bloblist.c
@@ -0,0 +1,239 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <bloblist.h>
+#include <log.h>
+#include <mapmem.h>
+#include <spl.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct bloblist_rec *bloblist_first_blob(struct bloblist_hdr *hdr)
+{
+ if (hdr->alloced <= hdr->hdr_size)
+ return NULL;
+ return (struct bloblist_rec *)((void *)hdr + hdr->hdr_size);
+}
+
+struct bloblist_rec *bloblist_next_blob(struct bloblist_hdr *hdr,
+ struct bloblist_rec *rec)
+{
+ ulong offset;
+
+ offset = (void *)rec - (void *)hdr;
+ offset += rec->hdr_size + ALIGN(rec->size, BLOBLIST_ALIGN);
+ if (offset >= hdr->alloced)
+ return NULL;
+ return (struct bloblist_rec *)((void *)hdr + offset);
+}
+
+#define foreach_rec(_rec, _hdr) \
+ for (_rec = bloblist_first_blob(_hdr); \
+ _rec; \
+ _rec = bloblist_next_blob(_hdr, _rec))
+
+static struct bloblist_rec *bloblist_findrec(uint tag)
+{
+ struct bloblist_hdr *hdr = gd->bloblist;
+ struct bloblist_rec *rec;
+
+ if (!hdr)
+ return NULL;
+
+ foreach_rec(rec, hdr) {
+ if (rec->tag == tag)
+ return rec;
+ }
+
+ return NULL;
+}
+
+static int bloblist_addrec(uint tag, int size, struct bloblist_rec **recp)
+{
+ struct bloblist_hdr *hdr = gd->bloblist;
+ struct bloblist_rec *rec;
+ int new_alloced;
+
+ new_alloced = hdr->alloced + sizeof(*rec) +
+ ALIGN(size, BLOBLIST_ALIGN);
+ if (new_alloced >= hdr->size) {
+ log(LOGC_BLOBLIST, LOGL_ERR,
+ "Failed to allocate %x bytes size=%x, need size>=%x\n",
+ size, hdr->size, new_alloced);
+ return log_msg_ret("bloblist add", -ENOSPC);
+ }
+ rec = (void *)hdr + hdr->alloced;
+ hdr->alloced = new_alloced;
+
+ rec->tag = tag;
+ rec->hdr_size = sizeof(*rec);
+ rec->size = size;
+ rec->spare = 0;
+ *recp = rec;
+
+ return 0;
+}
+
+static int bloblist_ensurerec(uint tag, struct bloblist_rec **recp, int size)
+{
+ struct bloblist_rec *rec;
+
+ rec = bloblist_findrec(tag);
+ if (rec) {
+ if (size && size != rec->size)
+ return -ESPIPE;
+ } else {
+ int ret;
+
+ ret = bloblist_addrec(tag, size, &rec);
+ if (ret)
+ return ret;
+ }
+ *recp = rec;
+
+ return 0;
+}
+
+void *bloblist_find(uint tag, int size)
+{
+ struct bloblist_rec *rec;
+
+ rec = bloblist_findrec(tag);
+ if (!rec)
+ return NULL;
+ if (size && size != rec->size)
+ return NULL;
+
+ return (void *)rec + rec->hdr_size;
+}
+
+void *bloblist_add(uint tag, int size)
+{
+ struct bloblist_rec *rec;
+
+ if (bloblist_addrec(tag, size, &rec))
+ return NULL;
+
+ return rec + 1;
+}
+
+int bloblist_ensure_size(uint tag, int size, void **blobp)
+{
+ struct bloblist_rec *rec;
+ int ret;
+
+ ret = bloblist_ensurerec(tag, &rec, size);
+ if (ret)
+ return ret;
+ *blobp = (void *)rec + rec->hdr_size;
+
+ return 0;
+}
+
+void *bloblist_ensure(uint tag, int size)
+{
+ struct bloblist_rec *rec;
+
+ if (bloblist_ensurerec(tag, &rec, size))
+ return NULL;
+
+ return (void *)rec + rec->hdr_size;
+}
+
+static u32 bloblist_calc_chksum(struct bloblist_hdr *hdr)
+{
+ struct bloblist_rec *rec;
+ u32 chksum;
+
+ chksum = crc32(0, (unsigned char *)hdr,
+ offsetof(struct bloblist_hdr, chksum));
+ foreach_rec(rec, hdr) {
+ chksum = crc32(chksum, (void *)rec, rec->hdr_size);
+ chksum = crc32(chksum, (void *)rec + rec->hdr_size, rec->size);
+ }
+
+ return chksum;
+}
+
+int bloblist_new(ulong addr, uint size, uint flags)
+{
+ struct bloblist_hdr *hdr;
+
+ if (size < sizeof(*hdr))
+ return log_ret(-ENOSPC);
+ if (addr & (BLOBLIST_ALIGN - 1))
+ return log_ret(-EFAULT);
+ hdr = map_sysmem(addr, size);
+ memset(hdr, '\0', sizeof(*hdr));
+ hdr->version = BLOBLIST_VERSION;
+ hdr->hdr_size = sizeof(*hdr);
+ hdr->flags = flags;
+ hdr->magic = BLOBLIST_MAGIC;
+ hdr->size = size;
+ hdr->alloced = hdr->hdr_size;
+ hdr->chksum = 0;
+ gd->bloblist = hdr;
+
+ return 0;
+}
+
+int bloblist_check(ulong addr, uint size)
+{
+ struct bloblist_hdr *hdr;
+ u32 chksum;
+
+ hdr = map_sysmem(addr, sizeof(*hdr));
+ if (hdr->magic != BLOBLIST_MAGIC)
+ return log_msg_ret("Bad magic", -ENOENT);
+ if (hdr->version != BLOBLIST_VERSION)
+ return log_msg_ret("Bad version", -EPROTONOSUPPORT);
+ if (size && hdr->size != size)
+ return log_msg_ret("Bad size", -EFBIG);
+ chksum = bloblist_calc_chksum(hdr);
+ if (hdr->chksum != chksum) {
+ log(LOGC_BLOBLIST, LOGL_ERR, "Checksum %x != %x\n", hdr->chksum,
+ chksum);
+ return log_msg_ret("Bad checksum", -EIO);
+ }
+ gd->bloblist = hdr;
+
+ return 0;
+}
+
+int bloblist_finish(void)
+{
+ struct bloblist_hdr *hdr = gd->bloblist;
+
+ hdr->chksum = bloblist_calc_chksum(hdr);
+
+ return 0;
+}
+
+int bloblist_init(void)
+{
+ bool expected;
+ int ret = -ENOENT;
+
+ /**
+ * Wed expect to find an existing bloblist in the first phase of U-Boot
+ * that runs
+ */
+ expected = !u_boot_first_phase();
+ if (expected)
+ ret = bloblist_check(CONFIG_BLOBLIST_ADDR,
+ CONFIG_BLOBLIST_SIZE);
+ if (ret) {
+ log(LOGC_BLOBLIST, expected ? LOGL_WARNING : LOGL_DEBUG,
+ "Existing bloblist not found: creating new bloblist\n");
+ ret = bloblist_new(CONFIG_BLOBLIST_ADDR, CONFIG_BLOBLIST_SIZE,
+ 0);
+ } else {
+ log(LOGC_BLOBLIST, LOGL_DEBUG, "Found existing bloblist\n");
+ }
+
+ return ret;
+}
diff --git a/common/board_f.c b/common/board_f.c
index f1a1432d86..835b7247c5 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -10,6 +10,7 @@
*/
#include <common.h>
+#include <bloblist.h>
#include <console.h>
#include <cpu.h>
#include <dm.h>
@@ -24,6 +25,9 @@
#include <post.h>
#include <relocate.h>
#include <spi.h>
+#ifdef CONFIG_SPL
+#include <spl.h>
+#endif
#include <status_led.h>
#include <sysreset.h>
#include <timer.h>
@@ -285,6 +289,17 @@ static int setup_mon_len(void)
return 0;
}
+static int setup_spl_handoff(void)
+{
+#if CONFIG_IS_ENABLED(HANDOFF)
+ gd->spl_handoff = bloblist_find(BLOBLISTT_SPL_HANDOFF,
+ sizeof(struct spl_handoff));
+ debug("Found SPL hand-off info %p\n", gd->spl_handoff);
+#endif
+
+ return 0;
+}
+
__weak int arch_cpu_init(void)
{
return 0;
@@ -560,6 +575,16 @@ static int reserve_stacks(void)
return arch_reserve_stacks();
}
+static int reserve_bloblist(void)
+{
+#ifdef CONFIG_BLOBLIST
+ gd->start_addr_sp -= CONFIG_BLOBLIST_SIZE;
+ gd->new_bloblist = map_sysmem(gd->start_addr_sp, CONFIG_BLOBLIST_SIZE);
+#endif
+
+ return 0;
+}
+
static int display_new_sp(void)
{
debug("New Stack Pointer is: %08lx\n", gd->start_addr_sp);
@@ -666,6 +691,24 @@ static int reloc_bootstage(void)
return 0;
}
+static int reloc_bloblist(void)
+{
+#ifdef CONFIG_BLOBLIST
+ if (gd->flags & GD_FLG_SKIP_RELOC)
+ return 0;
+ if (gd->new_bloblist) {
+ int size = CONFIG_BLOBLIST_SIZE;
+
+ debug("Copying bloblist from %p to %p, size %x\n",
+ gd->bloblist, gd->new_bloblist, size);
+ memcpy(gd->new_bloblist, gd->bloblist, size);
+ gd->bloblist = gd->new_bloblist;
+ }
+#endif
+
+ return 0;
+}
+
static int setup_reloc(void)
{
if (gd->flags & GD_FLG_SKIP_RELOC) {
@@ -813,6 +856,10 @@ static const init_fnc_t init_sequence_f[] = {
initf_malloc,
log_init,
initf_bootstage, /* uses its own timer, so does not need DM */
+#ifdef CONFIG_BLOBLIST
+ bloblist_init,
+#endif
+ setup_spl_handoff,
initf_console_record,
#if defined(CONFIG_HAVE_FSP)
arch_fsp_init,
@@ -913,6 +960,7 @@ static const init_fnc_t init_sequence_f[] = {
reserve_global_data,
reserve_fdt,
reserve_bootstage,
+ reserve_bloblist,
reserve_arch,
reserve_stacks,
dram_init_banksize,
@@ -932,6 +980,7 @@ static const init_fnc_t init_sequence_f[] = {
INIT_FUNC_WATCHDOG_RESET
reloc_fdt,
reloc_bootstage,
+ reloc_bloblist,
setup_reloc,
#if defined(CONFIG_X86) || defined(CONFIG_ARC)
copy_uboot_to_ram,
diff --git a/common/console.c b/common/console.c
index 9a94f32192..0b0dd76256 100644
--- a/common/console.c
+++ b/common/console.c
@@ -535,6 +535,13 @@ void putc(const char c)
void puts(const char *s)
{
+#ifdef CONFIG_SANDBOX
+ /* sandbox can send characters to stdout before it has a console */
+ if (!gd || !(gd->flags & GD_FLG_SERIAL_READY)) {
+ os_puts(s);
+ return;
+ }
+#endif
#ifdef CONFIG_DEBUG_UART
if (!gd || !(gd->flags & GD_FLG_SERIAL_READY)) {
while (*s) {
diff --git a/common/image.c b/common/image.c
index 1c3a7720cb..0659133fcc 100644
--- a/common/image.c
+++ b/common/image.c
@@ -166,6 +166,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, "mtk_image", "MediaTek BootROM loadable Image" },
{ -1, "", "", },
};
diff --git a/common/init/Makefile b/common/init/Makefile
index 4902635f53..853b56d1e5 100644
--- a/common/init/Makefile
+++ b/common/init/Makefile
@@ -5,3 +5,4 @@
#
obj-y += board_init.o
+obj-$(CONFIG_$(SPL_TPL_)HANDOFF) += handoff.o
diff --git a/common/init/handoff.c b/common/init/handoff.c
new file mode 100644
index 0000000000..e00b43e6a7
--- /dev/null
+++ b/common/init/handoff.c
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Passing basic information from SPL to U-Boot proper
+ *
+ * Copyright 2018 Google, Inc
+ */
+
+#include <common.h>
+#include <handoff.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void handoff_save_dram(struct spl_handoff *ho)
+{
+ ho->ram_size = gd->ram_size;
+#ifdef CONFIG_NR_DRAM_BANKS
+ {
+ struct bd_info *bd = gd->bd;
+ int i;
+
+ for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+ ho->ram_bank[i].start = bd->bi_dram[i].start;
+ ho->ram_bank[i].size = bd->bi_dram[i].size;
+ }
+ }
+#endif
+}
+
+void handoff_load_dram_size(struct spl_handoff *ho)
+{
+ gd->ram_size = ho->ram_size;
+}
+
+void handoff_load_dram_banks(struct spl_handoff *ho)
+{
+#ifdef CONFIG_NR_DRAM_BANKS
+ {
+ struct bd_info *bd = gd->bd;
+ int i;
+
+ for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+ bd->bi_dram[i].start = ho->ram_bank[i].start;
+ bd->bi_dram[i].size = ho->ram_bank[i].size;
+ }
+ }
+#endif
+}
diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index d0564621d4..0ddbffc7d1 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -25,8 +25,28 @@ config SPL_FRAMEWORK
supports MMC, NAND and YMODEM and other methods loading of U-Boot
and the Linux Kernel. If unsure, say Y.
+config HANDOFF
+ bool "Pass hand-off information from SPL to U-Boot proper"
+ depends on BLOBLIST
+ help
+ It is useful to be able to pass information from SPL to U-Boot
+ proper to preserve state that is known in SPL and is needed in U-Boot.
+ Enable this to locate the handoff information in U-Boot proper, early
+ in boot. It is available in gd->handoff. The state state is set up
+ in SPL (or TPL if that is being used).
+
if SPL
+config SPL_HANDOFF
+ bool "Pass hand-off information from SPL to U-Boot proper"
+ depends on HANDOFF
+ default y
+ help
+ This option enables SPL to write handoff information. This can be
+ used to pass information like the size of SDRAM from SPL to U-Boot
+ proper. Also SPL can receive information from TPL in the same place
+ if that is enabled.
+
config SPL_LDSCRIPT
string "Linker script for the SPL stage"
default "arch/$(ARCH)/cpu/u-boot-spl.lds"
@@ -135,12 +155,21 @@ config SPL_SEPARATE_BSS
location is used. Normally we put the device tree at the end of BSS
but with this option enabled, it goes at _image_binary_end.
-config SPL_DISABLE_BANNER_PRINT
- bool "Disable output of the SPL banner 'U-Boot SPL ...'"
+config SPL_BANNER_PRINT
+ bool "Enable output of the SPL banner 'U-Boot SPL ...'"
+ default y
+ help
+ If this option is enabled, SPL will print the banner with version
+ info. Disabling this option could be useful to reduce TPL boot time
+ (e.g. approx. 6 ms faster, when output on i.MX6 with 115200 baud).
+
+config TPL_BANNER_PRINT
+ bool "Enable output of the TPL banner 'U-Boot TPL ...'"
+ default y
help
If this option is enabled, SPL will not print the banner with version
- info. Selecting this option could be useful to reduce SPL boot time
- (e.g. approx. 6 ms slower, when output on i.MX6 with 115200 baud).
+ info. Disabling this option could be useful to reduce SPL boot time
+ (e.g. approx. 6 ms faster, when output on i.MX6 with 115200 baud).
config SPL_DISPLAY_PRINT
bool "Display a board-specific message in SPL"
@@ -295,6 +324,16 @@ config SPL_HASH_SUPPORT
this option to build system-specific drivers for hash acceleration
as part of an SPL build.
+config TPL_HASH_SUPPORT
+ bool "Support hashing drivers in TPL"
+ select SHA1
+ select SHA256
+ help
+ Enable hashing drivers in SPL. These drivers can be used to
+ accelerate secure boot processing in secure applications. Enable
+ this option to build system-specific drivers for hash acceleration
+ as part of an SPL build.
+
config SPL_DMA_SUPPORT
bool "Support DMA drivers"
help
@@ -376,7 +415,7 @@ config SPL_FPGA_SUPPORT
within SPL.
config SPL_GPIO_SUPPORT
- bool "Support GPIO"
+ bool "Support GPIO in SPL"
help
Enable support for GPIOs (General-purpose Input/Output) in SPL.
GPIOs allow U-Boot to read the state of an input line (high or
@@ -848,6 +887,16 @@ config TPL
if TPL
+config TPL_HANDOFF
+ bool "Pass hand-off information from TPL to SPL and U-Boot proper"
+ depends on HANDOFF
+ default y
+ help
+ This option enables TPL to write handoff information. This can be
+ used to pass information like the size of SDRAM from TPL to U-Boot
+ proper. The information is also available to SPL if it is useful
+ there.
+
config TPL_BOARD_INIT
bool "Call board-specific initialization in TPL"
help
@@ -928,6 +977,17 @@ config TPL_ENV_SUPPORT
help
Enable environment support in TPL. See SPL_ENV_SUPPORT for details.
+config TPL_GPIO_SUPPORT
+ bool "Support GPIO in TPL"
+ help
+ Enable support for GPIOs (General-purpose Input/Output) in TPL.
+ GPIOs allow U-Boot to read the state of an input line (high or
+ low) and set the state of an output line. This can be used to
+ drive LEDs, control power to various system parts and read user
+ input. GPIOs can be useful in TPL to enable a 'sign-of-life' LED,
+ for example. Enable this option to build the drivers in
+ drivers/gpio as part of an TPL build.
+
config TPL_I2C_SUPPORT
bool "Support I2C"
help
@@ -963,6 +1023,22 @@ config TPL_NAND_SUPPORT
help
Enable support for NAND in TPL. See SPL_NAND_SUPPORT for details.
+config TPL_PCI_SUPPORT
+ bool "Support PCI drivers"
+ help
+ Enable support for PCI in TPL. For platforms that need PCI to boot,
+ or must perform some init using PCI in SPL, this provides the
+ necessary driver support. This enables the drivers in drivers/pci
+ as part of a TPL build.
+
+config TPL_PCH_SUPPORT
+ bool "Support PCH drivers"
+ help
+ Enable support for PCH (Platform Controller Hub) devices in TPL.
+ These are used to set up GPIOs and the SPI peripheral early in
+ boot. This enables the drivers in drivers/pch as part of a TPL
+ build.
+
config TPL_RAM_SUPPORT
bool "Support booting from RAM"
help
@@ -977,6 +1053,15 @@ config TPL_RAM_DEVICE
be already in memory when TPL takes over, e.g. loaded by the boot
ROM.
+config TPL_RTC_SUPPORT
+ bool "Support RTC drivers"
+ help
+ Enable RTC (Real-time Clock) support in TPL. This includes support
+ for reading and setting the time. Some RTC devices also have some
+ non-volatile (battery-backed) memory which is accessible if
+ needed. This enables the drivers in drivers/rtc as part of an TPL
+ build.
+
config TPL_SERIAL_SUPPORT
bool "Support serial"
select TPL_PRINTF
diff --git a/common/spl/spl.c b/common/spl/spl.c
index 12f9359c0a..35120b6efd 100644
--- a/common/spl/spl.c
+++ b/common/spl/spl.c
@@ -7,8 +7,10 @@
*/
#include <common.h>
+#include <bloblist.h>
#include <binman_sym.h>
#include <dm.h>
+#include <handoff.h>
#include <spl.h>
#include <asm/u-boot.h>
#include <nand.h>
@@ -44,6 +46,14 @@ static bd_t bdata __attribute__ ((section(".data")));
*/
__weak void show_boot_progress(int val) {}
+#if defined(CONFIG_SPL_OS_BOOT) || CONFIG_IS_ENABLED(HANDOFF)
+/* weak, default platform-specific function to initialize dram banks */
+__weak int dram_init_banksize(void)
+{
+ return 0;
+}
+#endif
+
/*
* Default function to determine if u-boot or the OS should
* be started. This implementation always returns 1.
@@ -57,19 +67,12 @@ __weak void show_boot_progress(int val) {}
#ifdef CONFIG_SPL_OS_BOOT
__weak int spl_start_uboot(void)
{
- puts("SPL: Please implement spl_start_uboot() for your board\n");
- puts("SPL: Direct Linux boot not active!\n");
+ puts(SPL_TPL_PROMPT
+ "Please implement spl_start_uboot() for your board\n");
+ puts(SPL_TPL_PROMPT "Direct Linux boot not active!\n");
return 1;
}
-/* weak default platform specific function to initialize
- * dram banks
- */
-__weak int dram_init_banksize(void)
-{
- return 0;
-}
-
/*
* Weak default function for arch specific zImage check. Return zero
* and fill start and end address if image is recognized.
@@ -100,13 +103,13 @@ void spl_fixup_fdt(void)
/* fixup the memory dt node */
err = fdt_shrink_to_minimum(fdt_blob, 0);
if (err == 0) {
- printf("spl: fdt_shrink_to_minimum err - %d\n", err);
+ printf(SPL_TPL_PROMPT "fdt_shrink_to_minimum err - %d\n", err);
return;
}
err = arch_fixup_fdt(fdt_blob);
if (err) {
- printf("spl: arch_fixup_fdt err - %d\n", err);
+ printf(SPL_TPL_PROMPT "arch_fixup_fdt err - %d\n", err);
return;
}
#endif
@@ -185,7 +188,7 @@ static int spl_load_fit_image(struct spl_image_info *spl_image,
spl_image->os = IH_OS_U_BOOT;
spl_image->name = "U-Boot";
- debug("spl: payload image: %32s load addr: 0x%lx size: %d\n",
+ debug(SPL_TPL_PROMPT "payload image: %32s load addr: 0x%lx size: %d\n",
spl_image->name, spl_image->load_addr, spl_image->size);
#ifdef CONFIG_SPL_FIT_SIGNATURE
@@ -255,7 +258,8 @@ int spl_parse_image_header(struct spl_image_info *spl_image,
}
spl_image->os = image_get_os(header);
spl_image->name = image_get_name(header);
- debug("spl: payload image: %32s load addr: 0x%lx size: %d\n",
+ debug(SPL_TPL_PROMPT
+ "payload image: %32s load addr: 0x%lx size: %d\n",
spl_image->name, spl_image->load_addr, spl_image->size);
#else
/* LEGACY image not supported */
@@ -284,7 +288,8 @@ int spl_parse_image_header(struct spl_image_info *spl_image,
spl_image->load_addr = CONFIG_SYS_LOAD_ADDR;
spl_image->entry_point = CONFIG_SYS_LOAD_ADDR;
spl_image->size = end - start;
- debug("spl: payload zImage, load addr: 0x%lx size: %d\n",
+ debug(SPL_TPL_PROMPT
+ "payload zImage, load addr: 0x%lx size: %d\n",
spl_image->load_addr, spl_image->size);
return 0;
}
@@ -316,6 +321,44 @@ __weak void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
image_entry();
}
+#if CONFIG_IS_ENABLED(HANDOFF)
+/**
+ * Set up the SPL hand-off information
+ *
+ * This is initially empty (zero) but can be written by
+ */
+static int setup_spl_handoff(void)
+{
+ struct spl_handoff *ho;
+
+ ho = bloblist_ensure(BLOBLISTT_SPL_HANDOFF, sizeof(struct spl_handoff));
+ if (!ho)
+ return -ENOENT;
+
+ return 0;
+}
+
+static int write_spl_handoff(void)
+{
+ struct spl_handoff *ho;
+
+ ho = bloblist_find(BLOBLISTT_SPL_HANDOFF, sizeof(struct spl_handoff));
+ if (!ho)
+ return -ENOENT;
+ handoff_save_dram(ho);
+#ifdef CONFIG_SANDBOX
+ ho->arch.magic = TEST_HANDOFF_MAGIC;
+#endif
+ debug(SPL_TPL_PROMPT "Wrote SPL handoff\n");
+
+ return 0;
+}
+#else
+static inline int setup_spl_handoff(void) { return 0; }
+static inline int write_spl_handoff(void) { return 0; }
+
+#endif /* HANDOFF */
+
static int spl_common_init(bool setup_malloc)
{
int ret;
@@ -336,6 +379,30 @@ static int spl_common_init(bool setup_malloc)
return ret;
}
bootstage_mark_name(BOOTSTAGE_ID_START_SPL, "spl");
+#if CONFIG_IS_ENABLED(LOG)
+ ret = log_init();
+ if (ret) {
+ debug("%s: Failed to set up logging\n", __func__);
+ return ret;
+ }
+#endif
+ if (CONFIG_IS_ENABLED(BLOBLIST)) {
+ ret = bloblist_init();
+ if (ret) {
+ debug("%s: Failed to set up bloblist: ret=%d\n",
+ __func__, ret);
+ return ret;
+ }
+ }
+ if (CONFIG_IS_ENABLED(HANDOFF)) {
+ int ret;
+
+ ret = setup_spl_handoff();
+ if (ret) {
+ puts(SPL_TPL_PROMPT "Cannot set up SPL handoff\n");
+ hang();
+ }
+ }
if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) {
ret = fdtdec_setup();
if (ret) {
@@ -359,6 +426,10 @@ static int spl_common_init(bool setup_malloc)
void spl_set_bd(void)
{
+ /*
+ * NOTE: On some platforms (e.g. x86) bdata may be in flash and not
+ * writeable.
+ */
if (!gd->bd)
gd->bd = &bdata;
}
@@ -453,7 +524,7 @@ static int boot_from_devices(struct spl_image_info *spl_image,
if (loader)
printf("Trying to boot from %s\n", loader->name);
else
- puts("SPL: Unsupported Boot Device!\n");
+ puts(SPL_TPL_PROMPT "Unsupported Boot Device!\n");
#endif
if (loader && !spl_load_image(spl_image, loader)) {
spl_image->boot_device = spl_boot_list[i];
@@ -474,15 +545,12 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
BOOT_DEVICE_NONE,
};
struct spl_image_info spl_image;
+ int ret;
- debug(">>spl:board_init_r()\n");
+ debug(">>" SPL_TPL_PROMPT "board_init_r()\n");
spl_set_bd();
-#ifdef CONFIG_SPL_OS_BOOT
- dram_init_banksize();
-#endif
-
#if defined(CONFIG_SYS_SPL_MALLOC_START)
mem_malloc_init(CONFIG_SYS_SPL_MALLOC_START,
CONFIG_SYS_SPL_MALLOC_SIZE);
@@ -504,6 +572,9 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
spl_board_init();
#endif
+ if (IS_ENABLED(CONFIG_SPL_OS_BOOT) || CONFIG_IS_ENABLED(HANDOFF))
+ dram_init_banksize();
+
bootcount_inc();
memset(&spl_image, '\0', sizeof(spl_image));
@@ -515,11 +586,23 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
if (boot_from_devices(&spl_image, spl_boot_list,
ARRAY_SIZE(spl_boot_list))) {
- puts("SPL: failed to boot from all boot devices\n");
+ puts(SPL_TPL_PROMPT "failed to boot from all boot devices\n");
hang();
}
spl_perform_fixups(&spl_image);
+ if (CONFIG_IS_ENABLED(HANDOFF)) {
+ ret = write_spl_handoff();
+ if (ret)
+ printf(SPL_TPL_PROMPT
+ "SPL hand-off write failed (err=%d)\n", ret);
+ }
+ if (CONFIG_IS_ENABLED(BLOBLIST)) {
+ ret = bloblist_finish();
+ if (ret)
+ printf("Warning: Failed to finish bloblist (ret=%d)\n",
+ ret);
+ }
#ifdef CONFIG_CPU_V7M
spl_image.entry_point |= 0x1;
@@ -556,8 +639,6 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
gd->malloc_ptr / 1024);
#endif
#ifdef CONFIG_BOOTSTAGE_STASH
- int ret;
-
bootstage_mark_name(BOOTSTAGE_ID_END_SPL, "end_spl");
ret = bootstage_stash((void *)CONFIG_BOOTSTAGE_STASH_ADDR,
CONFIG_BOOTSTAGE_STASH_SIZE);
@@ -583,9 +664,9 @@ void preloader_console_init(void)
gd->have_console = 1;
-#ifndef CONFIG_SPL_DISABLE_BANNER_PRINT
- puts("\nU-Boot SPL " PLAIN_VERSION " (" U_BOOT_DATE " - " \
- U_BOOT_TIME " " U_BOOT_TZ ")\n");
+#if CONFIG_IS_ENABLED(BANNER_PRINT)
+ puts("\nU-Boot " SPL_TPL_NAME " " PLAIN_VERSION " (" U_BOOT_DATE " - "
+ U_BOOT_TIME " " U_BOOT_TZ ")\n");
#endif
#ifdef CONFIG_SPL_DISPLAY_PRINT
spl_display_print();
diff --git a/common/usb.c b/common/usb.c
index 78178c54c8..b70f614d24 100644
--- a/common/usb.c
+++ b/common/usb.c
@@ -42,7 +42,7 @@
static int asynch_allowed;
char usb_started; /* flag for the started/stopped USB status */
-#ifndef CONFIG_DM_USB
+#if !CONFIG_IS_ENABLED(DM_USB)
static struct usb_device usb_dev[USB_MAX_DEVICE];
static int dev_index;
@@ -183,7 +183,7 @@ int usb_disable_asynch(int disable)
asynch_allowed = !disable;
return old_value;
}
-#endif /* !CONFIG_DM_USB */
+#endif /* !CONFIG_IS_ENABLED(DM_USB) */
/*-------------------------------------------------------------------
@@ -849,7 +849,7 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
* the USB device are static allocated [USB_MAX_DEVICE].
*/
-#ifndef CONFIG_DM_USB
+#if !CONFIG_IS_ENABLED(DM_USB)
/* returns a pointer to the device with the index [index].
* if the device is not assigned (dev->devnum==-1) returns NULL
@@ -906,7 +906,7 @@ __weak int usb_alloc_device(struct usb_device *udev)
{
return 0;
}
-#endif /* !CONFIG_DM_USB */
+#endif /* !CONFIG_IS_ENABLED(DM_USB) */
static int usb_hub_port_reset(struct usb_device *dev, struct usb_device *hub)
{
@@ -1166,7 +1166,7 @@ int usb_setup_device(struct usb_device *dev, bool do_read,
return ret;
}
-#ifndef CONFIG_DM_USB
+#if !CONFIG_IS_ENABLED(DM_USB)
/*
* By the time we get here, the device has gotten a new device ID
* and is in the default state. We need to identify the thing and
@@ -1215,14 +1215,14 @@ int board_usb_cleanup(int index, enum usb_init_type init)
bool usb_device_has_child_on_port(struct usb_device *parent, int port)
{
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
return false;
#else
return parent->children[port] != NULL;
#endif
}
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
void usb_find_usb2_hub_address_port(struct usb_device *udev,
uint8_t *hub_address, uint8_t *hub_port)
{
diff --git a/common/usb_hub.c b/common/usb_hub.c
index e1d93b8333..33aaeb8e44 100644
--- a/common/usb_hub.c
+++ b/common/usb_hub.c
@@ -64,7 +64,7 @@ static inline bool usb_hub_is_superspeed(struct usb_device *hdev)
return hdev->descriptor.bDeviceProtocol == 3;
}
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
bool usb_hub_is_root_hub(struct udevice *hub)
{
if (device_get_uclass_id(hub->parent) != UCLASS_USB_HUB)
@@ -125,7 +125,7 @@ int usb_get_port_status(struct usb_device *dev, int port, void *data)
USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port,
data, sizeof(struct usb_port_status), USB_CNTL_TIMEOUT);
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
if (ret < 0)
return ret;
@@ -209,7 +209,7 @@ static void usb_hub_power_on(struct usb_hub_device *hub)
max(100, (int)pgood_delay) + 1000);
}
-#ifndef CONFIG_DM_USB
+#if !CONFIG_IS_ENABLED(DM_USB)
static struct usb_hub_device hub_dev[USB_MAX_HUB];
static int usb_hub_index;
@@ -273,7 +273,7 @@ static int usb_hub_port_reset(struct usb_device *dev, int port,
unsigned short portstatus, portchange;
int delay = HUB_SHORT_RESET_TIME; /* start with short reset delay */
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
debug("%s: resetting '%s' port %d...\n", __func__, dev->dev->name,
port + 1);
#else
@@ -394,7 +394,7 @@ int usb_hub_port_connect_change(struct usb_device *dev, int port)
break;
}
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
struct udevice *child;
ret = usb_scan_device(dev->dev, port + 1, speed, &child);
@@ -604,7 +604,7 @@ static struct usb_hub_device *usb_get_hub_device(struct usb_device *dev)
{
struct usb_hub_device *hub;
-#ifndef CONFIG_DM_USB
+#if !CONFIG_IS_ENABLED(DM_USB)
/* "allocate" Hub device */
hub = usb_hub_allocate();
#else
@@ -788,7 +788,7 @@ static int usb_hub_configure(struct usb_device *dev)
(le16_to_cpu(hubsts->wHubStatus) & HUB_STATUS_OVERCURRENT) ? \
"" : "no ");
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
/*
* Update USB host controller's internal representation of this hub
* after the hub descriptor is fetched.
@@ -930,7 +930,7 @@ int usb_hub_probe(struct usb_device *dev, int ifnum)
return ret;
}
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
int usb_hub_scan(struct udevice *hub)
{
struct usb_device *udev = dev_get_parent_priv(hub);
diff --git a/common/usb_kbd.c b/common/usb_kbd.c
index fdeb2aed24..020f0d4117 100644
--- a/common/usb_kbd.c
+++ b/common/usb_kbd.c
@@ -539,7 +539,7 @@ static int probe_usb_keyboard(struct usb_device *dev)
return 0;
}
-#ifndef CONFIG_DM_USB
+#if !CONFIG_IS_ENABLED(DM_USB)
/* Search for keyboard and register it if found. */
int drv_usb_kbd_init(void)
{
@@ -602,7 +602,7 @@ int usb_kbd_deregister(int force)
#endif
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
static int usb_kbd_probe(struct udevice *dev)
{
diff --git a/common/usb_storage.c b/common/usb_storage.c
index 560d60538b..8c889bb1a6 100644
--- a/common/usb_storage.c
+++ b/common/usb_storage.c
@@ -66,7 +66,7 @@ static __u32 CBWTag;
static int usb_max_devs; /* number of highest available usb device */
-#ifndef CONFIG_BLK
+#if !CONFIG_IS_ENABLED(BLK)
static struct blk_desc usb_dev_desc[USB_MAX_STOR_DEV];
#endif
@@ -99,7 +99,7 @@ struct us_data {
unsigned short max_xfer_blk; /* maximum transfer blocks */
};
-#ifndef CONFIG_BLK
+#if !CONFIG_IS_ENABLED(BLK)
static struct us_data usb_stor[USB_MAX_STOR_DEV];
#endif
@@ -111,7 +111,7 @@ int usb_stor_get_info(struct usb_device *dev, struct us_data *us,
struct blk_desc *dev_desc);
int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
struct us_data *ss);
-#ifdef CONFIG_BLK
+#if CONFIG_IS_ENABLED(BLK)
static unsigned long usb_stor_read(struct udevice *dev, lbaint_t blknr,
lbaint_t blkcnt, void *buffer);
static unsigned long usb_stor_write(struct udevice *dev, lbaint_t blknr,
@@ -136,7 +136,7 @@ static void usb_show_progress(void)
int usb_stor_info(void)
{
int count = 0;
-#ifdef CONFIG_BLK
+#if CONFIG_IS_ENABLED(BLK)
struct udevice *dev;
for (blk_first_device(IF_TYPE_USB, &dev);
@@ -186,7 +186,7 @@ static int usb_stor_probe_device(struct usb_device *udev)
{
int lun, max_lun;
-#ifdef CONFIG_BLK
+#if CONFIG_IS_ENABLED(BLK)
struct us_data *data;
int ret;
#else
@@ -197,7 +197,7 @@ static int usb_stor_probe_device(struct usb_device *udev)
#endif
debug("\n\nProbing for storage\n");
-#ifdef CONFIG_BLK
+#if CONFIG_IS_ENABLED(BLK)
/*
* We store the us_data in the mass storage device's platdata. It
* is shared by all LUNs (block devices) attached to this mass storage
@@ -299,7 +299,7 @@ int usb_stor_scan(int mode)
if (mode == 1)
printf(" scanning usb for storage devices... ");
-#ifndef CONFIG_DM_USB
+#if !CONFIG_IS_ENABLED(DM_USB)
unsigned char i;
usb_disable_asynch(1); /* asynch transfer not allowed */
@@ -942,7 +942,7 @@ static void usb_stor_set_max_xfer_blk(struct usb_device *udev,
size_t __maybe_unused size;
int __maybe_unused ret;
-#ifndef CONFIG_DM_USB
+#if !CONFIG_IS_ENABLED(DM_USB)
#ifdef CONFIG_USB_EHCI_HCD
/*
* The U-Boot EHCI driver can handle any transfer length as long as
@@ -1119,7 +1119,7 @@ static void usb_bin_fixup(struct usb_device_descriptor descriptor,
}
#endif /* CONFIG_USB_BIN_FIXUP */
-#ifdef CONFIG_BLK
+#if CONFIG_IS_ENABLED(BLK)
static unsigned long usb_stor_read(struct udevice *dev, lbaint_t blknr,
lbaint_t blkcnt, void *buffer)
#else
@@ -1134,14 +1134,14 @@ static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
struct us_data *ss;
int retry;
struct scsi_cmd *srb = &usb_ccb;
-#ifdef CONFIG_BLK
+#if CONFIG_IS_ENABLED(BLK)
struct blk_desc *block_dev;
#endif
if (blkcnt == 0)
return 0;
/* Setup device */
-#ifdef CONFIG_BLK
+#if CONFIG_IS_ENABLED(BLK)
block_dev = dev_get_uclass_platdata(dev);
udev = dev_get_parent_priv(dev_get_parent(dev));
debug("\nusb_read: udev %d\n", block_dev->devnum);
@@ -1200,7 +1200,7 @@ retry_it:
return blkcnt;
}
-#ifdef CONFIG_BLK
+#if CONFIG_IS_ENABLED(BLK)
static unsigned long usb_stor_write(struct udevice *dev, lbaint_t blknr,
lbaint_t blkcnt, const void *buffer)
#else
@@ -1215,7 +1215,7 @@ static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
struct us_data *ss;
int retry;
struct scsi_cmd *srb = &usb_ccb;
-#ifdef CONFIG_BLK
+#if CONFIG_IS_ENABLED(BLK)
struct blk_desc *block_dev;
#endif
@@ -1223,7 +1223,7 @@ static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
return 0;
/* Setup device */
-#ifdef CONFIG_BLK
+#if CONFIG_IS_ENABLED(BLK)
block_dev = dev_get_uclass_platdata(dev);
udev = dev_get_parent_priv(dev_get_parent(dev));
debug("\nusb_read: udev %d\n", block_dev->devnum);
@@ -1495,7 +1495,7 @@ int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
return 1;
}
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
static int usb_mass_storage_probe(struct udevice *dev)
{
@@ -1519,7 +1519,7 @@ U_BOOT_DRIVER(usb_mass_storage) = {
.id = UCLASS_MASS_STORAGE,
.of_match = usb_mass_storage_ids,
.probe = usb_mass_storage_probe,
-#ifdef CONFIG_BLK
+#if CONFIG_IS_ENABLED(BLK)
.platdata_auto_alloc_size = sizeof(struct us_data),
#endif
};
@@ -1540,7 +1540,7 @@ static const struct usb_device_id mass_storage_id_table[] = {
U_BOOT_USB_DEVICE(usb_mass_storage, mass_storage_id_table);
#endif
-#ifdef CONFIG_BLK
+#if CONFIG_IS_ENABLED(BLK)
static const struct blk_ops usb_storage_ops = {
.read = usb_stor_read,
.write = usb_stor_write,
diff --git a/configs/ax25-ae350_defconfig b/configs/a25-ae350_32_defconfig
index d7c4f40e58..5837b48903 100644
--- a/configs/ax25-ae350_defconfig
+++ b/configs/a25-ae350_32_defconfig
@@ -1,7 +1,6 @@
CONFIG_RISCV=y
CONFIG_SYS_TEXT_BASE=0x00000000
CONFIG_TARGET_AX25_AE350=y
-CONFIG_CPU_RISCV_64=y
CONFIG_DISTRO_DEFAULTS=y
CONFIG_NR_DRAM_BANKS=2
CONFIG_FIT=y
@@ -16,7 +15,7 @@ CONFIG_CMD_SF_TEST=y
CONFIG_BOOTP_PREFER_SERVERIP=y
CONFIG_CMD_CACHE=y
CONFIG_OF_BOARD=y
-CONFIG_DEFAULT_DEVICE_TREE="ae350"
+CONFIG_DEFAULT_DEVICE_TREE="ae350_32"
CONFIG_ENV_IS_IN_SPI_FLASH=y
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_MMC=y
diff --git a/configs/am335x_evm_defconfig b/configs/am335x_evm_defconfig
index b6cd49a469..6cc170ad40 100644
--- a/configs/am335x_evm_defconfig
+++ b/configs/am335x_evm_defconfig
@@ -40,15 +40,16 @@ CONFIG_NAND=y
CONFIG_SPI_FLASH=y
CONFIG_SPI_FLASH_WINBOND=y
CONFIG_DM_ETH=y
-CONFIG_DRIVER_TI_CPSW=y
CONFIG_PHY_GIGE=y
CONFIG_MII=y
+CONFIG_DRIVER_TI_CPSW=y
CONFIG_SPI=y
CONFIG_OMAP3_SPI=y
CONFIG_TIMER=y
CONFIG_OMAP_TIMER=y
CONFIG_USB=y
CONFIG_DM_USB=y
+# CONFIG_SPL_DM_USB is not set
CONFIG_USB_MUSB_HOST=y
CONFIG_USB_MUSB_GADGET=y
CONFIG_USB_MUSB_TI=y
diff --git a/configs/ax25-ae350_64_defconfig b/configs/ax25-ae350_64_defconfig
new file mode 100644
index 0000000000..b250d3fc7e
--- /dev/null
+++ b/configs/ax25-ae350_64_defconfig
@@ -0,0 +1,37 @@
+CONFIG_RISCV=y
+CONFIG_SYS_TEXT_BASE=0x00000000
+CONFIG_TARGET_AX25_AE350=y
+CONFIG_ARCH_RV64I=y
+CONFIG_DISTRO_DEFAULTS=y
+CONFIG_NR_DRAM_BANKS=2
+CONFIG_FIT=y
+CONFIG_BOOTDELAY=3
+CONFIG_BOARD_EARLY_INIT_F=y
+CONFIG_SYS_PROMPT="RISC-V # "
+CONFIG_CMD_IMLS=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SF_TEST=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_BOOTP_PREFER_SERVERIP=y
+CONFIG_CMD_CACHE=y
+CONFIG_OF_BOARD=y
+CONFIG_DEFAULT_DEVICE_TREE="ae350_64"
+CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_MMC=y
+CONFIG_FTSDC010=y
+CONFIG_FTSDC010_SDIO=y
+CONFIG_MTD_NOR_FLASH=y
+CONFIG_FLASH_CFI_DRIVER=y
+CONFIG_CFI_FLASH=y
+CONFIG_SYS_FLASH_USE_BUFFER_WRITE=y
+CONFIG_SYS_FLASH_CFI=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_FTMAC100=y
+CONFIG_BAUDRATE=38400
+CONFIG_SYS_NS16550=y
+CONFIG_SPI=y
+CONFIG_ATCSPI200_SPI=y
+CONFIG_ATCPIT100_TIMER=y
diff --git a/configs/chiliboard_defconfig b/configs/chiliboard_defconfig
index b6cde09d6f..3de0223469 100644
--- a/configs/chiliboard_defconfig
+++ b/configs/chiliboard_defconfig
@@ -29,19 +29,27 @@ CONFIG_CMD_EXT4_WRITE=y
CONFIG_CMD_MTDPARTS=y
CONFIG_MTDIDS_DEFAULT="nand0=8000000.nand"
CONFIG_MTDPARTS_DEFAULT="mtdparts=8000000.nand:128k(NAND.SPL),128k(NAND.SPL.backup1),128k(NAND.SPL.backup2),128k(NAND.SPL.backup3),256k(NAND.u-boot-spl-os),1m(NAND.u-boot),128k(NAND.u-boot-env),128k(NAND.u-boot-env.backup1),8m(NAND.kernel),-(NAND.file-system)"
+CONFIG_OF_CONTROL=y
+CONFIG_DEFAULT_DEVICE_TREE="am335x-chiliboard"
CONFIG_ENV_IS_IN_MMC=y
CONFIG_BOOTCOUNT_LIMIT=y
CONFIG_DM_GPIO=y
+CONFIG_MISC=y
+CONFIG_DM_MMC=y
CONFIG_MMC_OMAP_HS=y
CONFIG_NAND=y
-CONFIG_DRIVER_TI_CPSW=y
+CONFIG_DM_ETH=y
CONFIG_MII=y
+CONFIG_DRIVER_TI_CPSW=y
CONFIG_SPI=y
CONFIG_OMAP3_SPI=y
+CONFIG_TIMER=y
+CONFIG_OMAP_TIMER=y
CONFIG_USB=y
+CONFIG_DM_USB=y
CONFIG_USB_MUSB_HOST=y
CONFIG_USB_MUSB_DSPS=y
+CONFIG_USB_MUSB_TI=y
CONFIG_USB_STORAGE=y
CONFIG_FAT_WRITE=y
CONFIG_LZO=y
-CONFIG_OF_LIBFDT=y
diff --git a/configs/mt7623n_bpir2_defconfig b/configs/mt7623n_bpir2_defconfig
new file mode 100644
index 0000000000..3a4de72e23
--- /dev/null
+++ b/configs/mt7623n_bpir2_defconfig
@@ -0,0 +1,54 @@
+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_BLOCK_CACHE is not set
+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_MTK_SERIAL=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/configs/mt7629_rfb_defconfig b/configs/mt7629_rfb_defconfig
new file mode 100644
index 0000000000..1729d13c3d
--- /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_MTK_SERIAL=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/configs/qemu-riscv32_defconfig b/configs/qemu-riscv32_defconfig
index ff1fb1f30e..6334d8c0fc 100644
--- a/configs/qemu-riscv32_defconfig
+++ b/configs/qemu-riscv32_defconfig
@@ -1,6 +1,9 @@
CONFIG_RISCV=y
CONFIG_TARGET_QEMU_VIRT=y
+CONFIG_DISTRO_DEFAULTS=y
CONFIG_NR_DRAM_BANKS=1
+CONFIG_FIT=y
CONFIG_DISPLAY_CPUINFO=y
CONFIG_DISPLAY_BOARDINFO=y
-CONFIG_OF_BOARD=y
+# CONFIG_CMD_MII is not set
+CONFIG_OF_PRIOR_STAGE=y
diff --git a/configs/qemu-riscv64_defconfig b/configs/qemu-riscv64_defconfig
index d6c1a5d646..2d9ead93a2 100644
--- a/configs/qemu-riscv64_defconfig
+++ b/configs/qemu-riscv64_defconfig
@@ -1,7 +1,10 @@
CONFIG_RISCV=y
CONFIG_TARGET_QEMU_VIRT=y
-CONFIG_CPU_RISCV_64=y
+CONFIG_ARCH_RV64I=y
+CONFIG_DISTRO_DEFAULTS=y
CONFIG_NR_DRAM_BANKS=1
+CONFIG_FIT=y
CONFIG_DISPLAY_CPUINFO=y
CONFIG_DISPLAY_BOARDINFO=y
-CONFIG_OF_BOARD=y
+# CONFIG_CMD_MII is not set
+CONFIG_OF_PRIOR_STAGE=y
diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig
index f44e80e8c3..452a2ef4a5 100644
--- a/configs/sandbox_spl_defconfig
+++ b/configs/sandbox_spl_defconfig
@@ -22,6 +22,7 @@ CONFIG_CONSOLE_RECORD=y
CONFIG_CONSOLE_RECORD_OUT_SIZE=0x1000
CONFIG_SILENT_CONSOLE=y
CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_HANDOFF=y
CONFIG_SPL_BOARD_INIT=y
CONFIG_SPL_ENV_SUPPORT=y
CONFIG_CMD_CPU=y
diff --git a/configs/vexpress_aemv8a_dram_defconfig b/configs/vexpress_aemv8a_dram_defconfig
index 9848f96293..0f0f138303 100644
--- a/configs/vexpress_aemv8a_dram_defconfig
+++ b/configs/vexpress_aemv8a_dram_defconfig
@@ -23,12 +23,14 @@ CONFIG_CMD_ARMFLASH=y
# CONFIG_CMD_NFS is not set
CONFIG_CMD_CACHE=y
# CONFIG_CMD_MISC is not set
+CONFIG_CMD_UBI=y
# CONFIG_ISO_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
CONFIG_ENV_IS_IN_FLASH=y
CONFIG_DM=y
# CONFIG_MMC is not set
CONFIG_MTD_NOR_FLASH=y
+CONFIG_MTD_DEVICE=y
CONFIG_FLASH_CFI_DRIVER=y
CONFIG_SYS_FLASH_USE_BUFFER_WRITE=y
CONFIG_SYS_FLASH_PROTECTION=y
diff --git a/configs/vexpress_aemv8a_juno_defconfig b/configs/vexpress_aemv8a_juno_defconfig
index ef38915955..ed611fea7c 100644
--- a/configs/vexpress_aemv8a_juno_defconfig
+++ b/configs/vexpress_aemv8a_juno_defconfig
@@ -23,12 +23,14 @@ CONFIG_CMD_ARMFLASH=y
# CONFIG_CMD_NFS is not set
CONFIG_CMD_CACHE=y
# CONFIG_CMD_MISC is not set
+CONFIG_CMD_UBI=y
# CONFIG_ISO_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
CONFIG_ENV_IS_IN_FLASH=y
CONFIG_DM=y
# CONFIG_MMC is not set
CONFIG_MTD_NOR_FLASH=y
+CONFIG_MTD_DEVICE=y
CONFIG_FLASH_CFI_DRIVER=y
CONFIG_SYS_FLASH_USE_BUFFER_WRITE=y
CONFIG_SYS_FLASH_PROTECTION=y
diff --git a/configs/vexpress_aemv8a_semi_defconfig b/configs/vexpress_aemv8a_semi_defconfig
index a4d1233cd5..0b3bb65ee6 100644
--- a/configs/vexpress_aemv8a_semi_defconfig
+++ b/configs/vexpress_aemv8a_semi_defconfig
@@ -23,12 +23,14 @@ CONFIG_CMD_ARMFLASH=y
# CONFIG_CMD_NFS is not set
CONFIG_CMD_CACHE=y
# CONFIG_CMD_MISC is not set
+CONFIG_CMD_UBI=y
# CONFIG_ISO_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
CONFIG_ENV_IS_IN_FLASH=y
CONFIG_DM=y
# CONFIG_MMC is not set
CONFIG_MTD_NOR_FLASH=y
+CONFIG_MTD_DEVICE=y
CONFIG_FLASH_CFI_DRIVER=y
CONFIG_SYS_FLASH_USE_BUFFER_WRITE=y
CONFIG_SYS_FLASH_PROTECTION=y
diff --git a/configs/vexpress_ca15_tc2_defconfig b/configs/vexpress_ca15_tc2_defconfig
index f4d555be48..cabc0c4577 100644
--- a/configs/vexpress_ca15_tc2_defconfig
+++ b/configs/vexpress_ca15_tc2_defconfig
@@ -18,8 +18,10 @@ CONFIG_CMD_MMC=y
# CONFIG_CMD_SETEXPR is not set
# CONFIG_CMD_NFS is not set
# CONFIG_CMD_MISC is not set
+CONFIG_CMD_UBI=y
CONFIG_ENV_IS_IN_FLASH=y
CONFIG_MTD_NOR_FLASH=y
+CONFIG_MTD_DEVICE=y
CONFIG_FLASH_CFI_DRIVER=y
CONFIG_SYS_FLASH_USE_BUFFER_WRITE=y
CONFIG_SYS_FLASH_PROTECTION=y
diff --git a/configs/vexpress_ca5x2_defconfig b/configs/vexpress_ca5x2_defconfig
index bdacc60c2c..dc4411d6f5 100644
--- a/configs/vexpress_ca5x2_defconfig
+++ b/configs/vexpress_ca5x2_defconfig
@@ -17,8 +17,10 @@ CONFIG_CMD_MMC=y
# CONFIG_CMD_SETEXPR is not set
# CONFIG_CMD_NFS is not set
# CONFIG_CMD_MISC is not set
+CONFIG_CMD_UBI=y
CONFIG_ENV_IS_IN_FLASH=y
CONFIG_MTD_NOR_FLASH=y
+CONFIG_MTD_DEVICE=y
CONFIG_FLASH_CFI_DRIVER=y
CONFIG_SYS_FLASH_USE_BUFFER_WRITE=y
CONFIG_SYS_FLASH_PROTECTION=y
diff --git a/configs/vexpress_ca9x4_defconfig b/configs/vexpress_ca9x4_defconfig
index 7a90831918..9390cf61d1 100644
--- a/configs/vexpress_ca9x4_defconfig
+++ b/configs/vexpress_ca9x4_defconfig
@@ -17,8 +17,10 @@ CONFIG_CMD_MMC=y
# CONFIG_CMD_SETEXPR is not set
# CONFIG_CMD_NFS is not set
# CONFIG_CMD_MISC is not set
+CONFIG_CMD_UBI=y
CONFIG_ENV_IS_IN_FLASH=y
CONFIG_MTD_NOR_FLASH=y
+CONFIG_MTD_DEVICE=y
CONFIG_FLASH_CFI_DRIVER=y
CONFIG_SYS_FLASH_USE_BUFFER_WRITE=y
CONFIG_SYS_FLASH_PROTECTION=y
diff --git a/doc/README.bloblist b/doc/README.bloblist
new file mode 100644
index 0000000000..b0e787b97d
--- /dev/null
+++ b/doc/README.bloblist
@@ -0,0 +1,82 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+Blob Lists - bloblist
+=====================
+
+Introduction
+------------
+
+A bloblist provides a way to store collections of binary information (blobs) in
+a central structure. Each record of information is assigned a tag so that its
+owner can find it and update it. Each record is generally described by a C
+structure defined by the code that owns it.
+
+
+Passing state through the boot process
+--------------------------------------
+
+The bloblist is created when the first U-Boot component runs (often SPL,
+sometimes TPL). It is passed through to each successive part of the boot and
+can be accessed as needed. This provides a way to transfer state from one part
+to the next. For example, TPL may determine that a watchdog reset occurred by
+reading an SoC register. Reading the register may reset the value, so that it
+cannot be read a second time. So TPL can store that in a bloblist record which
+can be passed through to SPL and U-Boot proper, which can print a message
+indicating that something went wrong and the watchdog fired.
+
+
+Blobs
+-----
+
+While each blob in the bloblist can be of any length, bloblists are designed to
+hold small amounts of data, typically a few KB at most. It is not possible to
+change the length of a blob once it has been written. Each blob is normally
+created from a C structure which can beused to access its fields.
+
+
+Blob tags
+---------
+
+Each blob has a tag which is a 32-bit number. This uniquely identifies the
+owner of the blob. Blob tags are listed in enum blob_tag_t and are named
+with a BLOBT_ prefix.
+
+
+Single structure
+----------------
+
+There is normally only one bloblist in U-Boot. Since a bloblist can store
+multiple blobs it does not seem useful to allow multiple bloblists. Of course
+there could be reasons for this, such as needing to spread the blobs around in
+different memory areas due to fragmented memory, but it is simpler to just have
+a single bloblist.
+
+
+API
+---
+
+Bloblist provides a fairly simple API which allows blobs to be created and
+found. All access is via the blob's tag.
+
+
+Finishing the bloblist
+----------------------
+
+When a part of U-Boot is about to jump to the next part, it can 'finish' the
+bloblist in preparation for the next stage. This involves adding a checksum so
+that the next stage can make sure that the data arrived safely. While the
+bloblist is in use, changes can be made which will affect the checksum, so it
+is easier to calculate the checksum at the end after all changes are made.
+
+
+Future work
+-----------
+
+Bootstage has a mechanism to 'stash' its records for passing to the next part.
+This should move to using bloblist, to avoid having its own mechanism for
+passing information between U-Boot parts.
+
+
+Simon Glass
+sjg@chromium.org
+12-Aug-2018
diff --git a/doc/README.distro b/doc/README.distro
index f8e9752a0f..ab6e6f4e74 100644
--- a/doc/README.distro
+++ b/doc/README.distro
@@ -292,7 +292,7 @@ Each entry in the macro defines a single boot device (e.g. a specific eMMC
device or SD card) or type of boot device (e.g. USB disk). The parameters to
the func macro (passed in by the internal implementation of the header) are:
-- Upper-case disk type (MMC, SATA, SCSI, IDE, USB, DHCP, PXE).
+- Upper-case disk type (MMC, SATA, SCSI, IDE, USB, DHCP, PXE, VIRTIO).
- Lower-case disk type (same options as above).
- ID of the specific disk (MMC only) or ignored for other types.
@@ -398,6 +398,7 @@ The list of possible targets consists of:
* scsi
* ide
* usb
+ * virtio
Other *boot* variables than the ones defined above are only for internal use
of the boot environment and are not guaranteed to exist or work in the same
diff --git a/doc/README.mediatek b/doc/README.mediatek
new file mode 100644
index 0000000000..246579d4be
--- /dev/null
+++ b/doc/README.mediatek
@@ -0,0 +1,221 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2018 MediaTek Inc.
+# Ryder Lee <ryder.lee@kernel.org>
+
+
+This document describes how to compile the U-Boot and how to change U-Boot
+configuration about the MediaTek SoCs.
+
+
+Build Procedure
+===============
+ -Set the cross compiler:
+
+ # export CROSS_COMPILE=/path/to/toolchain/arm-linux-gnueabi-
+
+ -Clean-up old residuals:
+
+ # make mrproper
+
+ -Configure the U-Boot:
+
+ # make <defconfig_file>
+ # make
+
+ - For the MT7623n bananapi R2 board use "mt7623n_bpir2_defconfig"
+ - For the MT7629 reference board use "mt7629_rfb_defconfig"
+
+
+Boot sequence
+=============
+ -Bootrom -> MTK preloader -> U-Boot
+
+ - MT7623n
+
+ This version of U-Boot doesn't implement SPL. So, MTK preloader binary
+ is needed to boot up:
+
+ https://github.com/BPI-SINOVOIP/BPI-R2-bsp/tree/master/mt-pack/mtk/bpi-r2/bin
+
+
+ -Bootrom -> SPL -> U-Boot
+
+ - MT7629
+
+
+Configuration update
+====================
+ To update the U-Boot configuration, please refer to doc/README.kconfig
+
+
+MediaTek image header
+=====================
+Currently there are two image headers used for MediaTek chips:
+
+ - BootROM image header. This header is used by the first stage bootloader. It records
+ the desired compatible boot device, integrity information and its load address.
+
+ The on-chip BootROM will firstly verify integrity and compatibility of the bootloader.
+
+ If verification passed, the BootROM will then load the bootloader into on-chip SRAM,
+ and pass control to it.
+
+ Note that this header is actually a combination of three independent headers:
+ Device header, BRLYT header and GFH header.
+
+ Used by U-Boot SPL of MT7629 and preloader of MT7623.
+
+
+ - MediaTek legacy image header. This header was originally used by the legacy image. It
+ basically records the load address, image size and image name.
+
+ After all low level initializations passed, the preloader will locate the LK image and
+ load it into DRAM, and pass control to it.
+
+ Now this header is used by U-Boot of MT7623.
+
+
+To generate these two headers with mkimage:
+
+ # mkimage -T mtk_image -a <load_addr> -n <option_string> -d <input_file> <image_file>
+
+ - mtk_image means using MediaTek's header generation method.
+
+
+ - load_addr is the load address of this image.
+ For first stage bootloader like U-Boot SPL or preloader, it usually points to the
+ on-chip SRAM.
+
+ For second stage bootloader like U-Boot, it usually points to the DRAM.
+
+
+ - option_string contains options to generate the header.
+
+ The option string is using the follow format:
+ key1=value1;key2=value2;...
+
+ The following key names are valid:
+ lk: If lk=1, LK image header is used. Otherwise BootROM image header is used.
+
+ lkname: The name of the LK image header. The maximum length is 32.
+ The default value is "U-Boot".
+
+ media: Desired boot device. The valid values are:
+ nand : Parallel NAND
+ snand: Serial NAND
+ nor : Serial NOR
+ emmc : eMMC
+ sdmmc: SD
+
+ nandinfo: Desired NAND device type, a combination of page size, oob size and
+ optional device capacity. Valid types are:
+ 2k+64 : for Serial NAND, 2KiB page size + 64B oob size
+ 2k+120 : for Serial NAND, 2KiB page size + 120B oob size
+ 2k+128 : for Serial NAND, 2KiB page size + 128B oob size
+ 4k+256 : for Serial NAND, 4KiB page size + 256B oob size
+ 1g:2k+64 : for Parallel NAND, 2KiB page size + 64B oob size, total 1Gbit size
+ 2g:2k+64 : for Parallel NAND, 2KiB page size + 64B oob size, total 2Gbit size
+ 4g:2k+64 : for Parallel NAND, 2KiB page size + 64B oob size, total 4Gbit size
+ 2g:2k+128: for Parallel NAND, 2KiB page size + 128B oob size, total 2Gbit size
+ 4g:2k+128: for Parallel NAND, 2KiB page size + 128B oob size, total 4Gbit size
+
+
+MT7629 partitions on Serial NOR
+===============================
+
+ Start End Size Description
+ 00000000 - 0000ffff: 64KiB U-Boot SPL
+ 00010000 - 0005ffff: 320KiB U-Boot
+ 00060000 - 0006ffff: 64KiB U-Boot env / MediaTek NVRAM
+ 00070000 - 000affff: 256KiB RF calibration data
+ 000b0000 - xxxxxxxx: all left Firmware image
+
+
+BPi-R2 (MT7623N) partitions on SD
+=================================
+ Please note that the last two partitions can vary from different Linux distributions
+ depending on the MBR partition table.
+
+ Start End Size Description
+ 00000000 - 000001ff: 512B Device header (with MBR partition table)
+ 00000200 - 000007ff: 1536B BRLYT header
+ 00000800 - 0004ffff: 318KiB Preloader (with GFH header)
+ 00050000 - 000fffff: 704KiB U-Boot
+ 00100000 - 063fffff: 99MiB Reserved
+ 06400000 - 163fffff: 256MiB Partition 1 (FAT32)
+ 16400000 - xxxxxxxx: all left Partition 2 (ext4)
+
+
+Upgrading notice on Serial NOR
+==============================
+Example: MT7629
+
+ The command sf is used to operate the Serial NOR device:
+
+ - To probe current NOR flash:
+
+ # sf probe
+
+ - To erase a region:
+
+ # sf erase <offset> <len>
+
+ - To write data to an offset:
+
+ # sf write <data_addr> <offset> <len>
+
+ - To boot kernel:
+
+ # bootm 0x300b0000
+
+ The memory address range 0x30000000 - 0x3fffffff is mapped to the NOR flash.
+ The DRAM starts at 0x40000000.
+
+ Please note that the output binary u-boot-mtk.bin is a combination of SPL and U-Boot,
+ and it should be write to beginning of the flash.
+
+ Otherwise you should use standalone files:
+
+ spl/u-boot-spl-mtk.bin for SPL,
+ u-boot.img for U-Boot.
+
+
+Upgrading notice on SD / eMMC
+=============================
+Example: MT7623
+
+ Normally only Preloader and U-Boot can be upgraded within U-Boot, and other partitions
+ should be written in PC.
+
+ - To probe current SD card / eMMC:
+
+ # mmc dev 0 for eMMC
+ # mmc dev 1 for SD
+
+ - To erase a region:
+
+ # mmc erase <blk_offset> <blk_num>
+
+ - To write data to a block offset:
+
+ # mmc write <data_addr> <blk_offset> <blk_num>
+
+ - To load kernel image from partition 1:
+
+ # fatload mmc 0:1 <load_address> <path_to_kernel_uImage> for eMMC
+ # fatload mmc 1:1 <load_address> <path_to_kernel_uImage> for SD
+
+ - To boot kernel:
+
+ # bootm <load_address>
+
+ The DRAM starts at 0x80000000.
+
+ Please note that we use block offset and block count for SD card, not the byte offset.
+ The block size is always 512 bytes for SD card.
+
+
+Documentation
+=============
+ http://wiki.banana-pi.org/Banana_Pi_BPI-R2
diff --git a/doc/README.trace b/doc/README.trace
index 74ba26a5a4..2e7ca3319a 100644
--- a/doc/README.trace
+++ b/doc/README.trace
@@ -88,7 +88,7 @@ stdin=serial
stdout=serial
Environment size: 117/8188 bytes
-=>sb save host 0 trace 0 ${profoffset}
+=>host save host 0 trace 0 ${profoffset}
11405888 bytes written in 10 ms (1.1 GiB/s)
=>reset
diff --git a/drivers/Makefile b/drivers/Makefile
index 4453c62ad3..55de10926e 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -2,14 +2,19 @@
obj-$(CONFIG_$(SPL_TPL_)CLK) += clk/
obj-$(CONFIG_$(SPL_TPL_)DM) += core/
+obj-$(CONFIG_$(SPL_TPL_)GPIO_SUPPORT) += gpio/
obj-$(CONFIG_$(SPL_TPL_)DRIVERS_MISC_SUPPORT) += misc/ sysreset/ firmware/
obj-$(CONFIG_$(SPL_TPL_)I2C_SUPPORT) += i2c/
+obj-$(CONFIG_$(SPL_TPL_)INPUT) += input/
obj-$(CONFIG_$(SPL_TPL_)LED) += led/
obj-$(CONFIG_$(SPL_TPL_)MMC_SUPPORT) += mmc/
obj-$(CONFIG_$(SPL_TPL_)NAND_SUPPORT) += mtd/nand/raw/
+obj-$(CONFIG_$(SPL_TPL_)PCH_SUPPORT) += pch/
+obj-$(CONFIG_$(SPL_TPL_)PCI_SUPPORT) += pci/
obj-$(CONFIG_$(SPL_TPL_)PHY) += phy/
obj-$(CONFIG_$(SPL_TPL_)PINCTRL) += pinctrl/
obj-$(CONFIG_$(SPL_TPL_)RAM) += ram/
+obj-$(CONFIG_$(SPL_TPL_)RTC_SUPPORT) += rtc/
obj-$(CONFIG_$(SPL_TPL_)SERIAL_SUPPORT) += serial/
obj-$(CONFIG_$(SPL_TPL_)SPI_FLASH_SUPPORT) += mtd/spi/
obj-$(CONFIG_$(SPL_TPL_)SPI_SUPPORT) += spi/
@@ -17,6 +22,7 @@ obj-$(CONFIG_$(SPL_TPL_)TIMER) += timer/
obj-$(CONFIG_$(SPL_TPL_)VIRTIO) += virtio/
obj-$(CONFIG_$(SPL_)DM_MAILBOX) += mailbox/
obj-$(CONFIG_$(SPL_)REMOTEPROC) += remoteproc/
+obj-$(CONFIG_$(SPL_TPL_)TPM) += tpm/
ifndef CONFIG_TPL_BUILD
ifdef CONFIG_SPL_BUILD
@@ -24,7 +30,6 @@ ifdef CONFIG_SPL_BUILD
obj-$(CONFIG_SPL_BOOTCOUNT_LIMIT) += bootcount/
obj-$(CONFIG_SPL_CPU_SUPPORT) += cpu/
obj-$(CONFIG_SPL_CRYPTO_SUPPORT) += crypto/
-obj-$(CONFIG_SPL_GPIO_SUPPORT) += gpio/
obj-$(CONFIG_SPL_MPC8XXX_INIT_DDR_SUPPORT) += ddr/fsl/
obj-$(CONFIG_ARMADA_38X) += ddr/marvell/a38x/
obj-$(CONFIG_ARMADA_XP) += ddr/marvell/axp/
@@ -40,9 +45,6 @@ obj-$(CONFIG_SPL_DMA_SUPPORT) += dma/
obj-$(CONFIG_SPL_ETH_SUPPORT) += net/
obj-$(CONFIG_SPL_ETH_SUPPORT) += net/phy/
obj-$(CONFIG_SPL_USB_ETHER) += net/phy/
-obj-$(CONFIG_SPL_PCI_SUPPORT) += pci/
-obj-$(CONFIG_SPL_PCH_SUPPORT) += pch/
-obj-$(CONFIG_SPL_RTC_SUPPORT) += rtc/
obj-$(CONFIG_SPL_MUSB_NEW_SUPPORT) += usb/musb-new/
obj-$(CONFIG_SPL_USB_GADGET_SUPPORT) += usb/gadget/
obj-$(CONFIG_SPL_USB_GADGET_SUPPORT) += usb/gadget/udc/
@@ -92,7 +94,6 @@ obj-y += scsi/
obj-y += sound/
obj-y += spmi/
obj-y += sysreset/
-obj-y += tpm/
obj-y += video/
obj-y += watchdog/
obj-$(CONFIG_QE) += qe/
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index a6962453a1..9acbb1a650 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_$(SPL_TPL_)CLK) += clk-uclass.o clk_fixed_rate.o
obj-y += imx/
obj-y += tegra/
obj-$(CONFIG_ARCH_ASPEED) += aspeed/
+obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/
obj-$(CONFIG_ARCH_MESON) += clk_meson.o clk_meson_axg.o
obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
obj-$(CONFIG_ARCH_SOCFPGA) += altera/
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
new file mode 100644
index 0000000000..0632dc87b6
--- /dev/null
+++ b/drivers/clk/mediatek/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0
+# Core
+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 0000000000..c6b09d8e18
--- /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_common_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_common_clk_init(dev, &mt7623_clk_tree);
+}
+
+static int mt7623_infracfg_probe(struct udevice *dev)
+{
+ return mtk_common_clk_gate_init(dev, &mt7623_clk_tree, infra_cgs);
+}
+
+static int mt7623_pericfg_probe(struct udevice *dev)
+{
+ return mtk_common_clk_gate_init(dev, &mt7623_clk_tree, peri_cgs);
+}
+
+static int mt7623_ethsys_probe(struct udevice *dev)
+{
+ return mtk_common_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,
+};
diff --git a/drivers/clk/mediatek/clk-mt7629.c b/drivers/clk/mediatek/clk-mt7629.c
new file mode 100644
index 0000000000..2601b6cf30
--- /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_common_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_common_clk_init(dev, &mt7629_clk_tree);
+}
+
+static int mt7629_infracfg_probe(struct udevice *dev)
+{
+ return mtk_common_clk_gate_init(dev, &mt7629_clk_tree, infra_cgs);
+}
+
+static int mt7629_pericfg_probe(struct udevice *dev)
+{
+ return mtk_common_clk_gate_init(dev, &mt7629_clk_tree, peri_cgs);
+}
+
+static int mt7629_ethsys_probe(struct udevice *dev)
+{
+ return mtk_common_clk_gate_init(dev, &mt7629_clk_tree, eth_cgs);
+}
+
+static int mt7629_sgmiisys_probe(struct udevice *dev)
+{
+ return mtk_common_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 0000000000..870b14ed8b
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mtk.c
@@ -0,0 +1,493 @@
+// 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_common_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_common_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 0000000000..74152ed9c6
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mtk.h
@@ -0,0 +1,194 @@
+/* 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 - hardware-specific PLLs data */
+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 - fixed clocks
+ *
+ * @id: index of clocks
+ * @parent: index of parnet clocks
+ * @rate: fixed rate
+ */
+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 - fixed multiplier and divider clocks
+ *
+ * @id: index of clocks
+ * @parent: index of parnet clocks
+ * @mult: multiplier
+ * @div: divider
+ * @flag: hardware-specific flags
+ */
+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 - aggregate clock of mux, divider and gate clocks
+ *
+ * @id: index of clocks
+ * @parent: index of parnet clocks
+ * @mux_reg: hardware-specific mux register
+ * @gate_reg: hardware-specific gate register
+ * @mux_mask: mask to the mux bit field
+ * @mux_shift: shift to the mux bit field
+ * @gate_shift: shift to the gate bit field
+ * @num_parents: number of parent clocks
+ * @flags: hardware-specific 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 - gate clocks
+ *
+ * @id: index of gate clocks
+ * @parent: index of parnet clocks
+ * @regs: hardware-specific mux register
+ * @shift: shift to the gate bit field
+ * @flags: hardware-specific flags
+ */
+struct mtk_gate {
+ const int id;
+ const int parent;
+ const struct mtk_gate_regs *regs;
+ int shift;
+ u32 flags;
+};
+
+/* struct mtk_clk_tree - clock tree */
+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_common_clk_init(struct udevice *dev,
+ const struct mtk_clk_tree *tree);
+int mtk_common_clk_gate_init(struct udevice *dev,
+ const struct mtk_clk_tree *tree,
+ const struct mtk_gate *gates);
+
+#endif /* __DRV_CLK_MTK_H */
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 27246ee465..fbd13964a0 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -569,6 +569,10 @@ config MMC_SUNXI_HAS_NEW_MODE
bool
depends on MMC_SUNXI
+config MMC_SUNXI_HAS_MODE_SWITCH
+ bool
+ depends on MMC_SUNXI
+
config GENERIC_ATMEL_MCI
bool "Atmel Multimedia Card Interface support"
depends on DM_MMC && BLK && ARCH_AT91
@@ -598,6 +602,17 @@ config FTSDC010_SDIO
help
This can enable ftsdc010 sdio function.
+config MMC_MTK
+ bool "MediaTek SD/MMC Card Interface support"
+ depends on ARCH_MEDIATEK
+ depends on BLK && DM_MMC
+ depends on OF_CONTROL
+ 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 23c5b0daef..801a26d821 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 0000000000..0741a525c0
--- /dev/null
+++ b/drivers/mmc/mtk-sd.c
@@ -0,0 +1,1394 @@
+// 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 <mmc.h>
+#include <errno.h>
+#include <malloc.h>
+#include <stdbool.h>
+#include <asm/gpio.h>
+#include <dm/pinctrl.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+
+/* MSDC_CFG */
+#define MSDC_CFG_HS400_CK_MODE_EXT BIT(22)
+#define MSDC_CFG_CKMOD_EXT_M 0x300000
+#define MSDC_CFG_CKMOD_EXT_S 20
+#define MSDC_CFG_CKDIV_EXT_M 0xfff00
+#define MSDC_CFG_CKDIV_EXT_S 8
+#define MSDC_CFG_HS400_CK_MODE BIT(18)
+#define MSDC_CFG_CKMOD_M 0x30000
+#define MSDC_CFG_CKMOD_S 16
+#define MSDC_CFG_CKDIV_M 0xff00
+#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)
+
+/* MSDC_IOCON */
+#define MSDC_IOCON_W_DSPL BIT(8)
+#define MSDC_IOCON_DSPL BIT(2)
+#define MSDC_IOCON_RSPL BIT(1)
+
+/* MSDC_PS */
+#define MSDC_PS_DAT0 BIT(16)
+#define MSDC_PS_CDDBCE_M 0xf000
+#define MSDC_PS_CDDBCE_S 12
+#define MSDC_PS_CDSTS BIT(1)
+#define MSDC_PS_CDEN BIT(0)
+
+/* #define MSDC_INT(EN) */
+#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)
+
+/* MSDC_FIFOCS */
+#define MSDC_FIFOCS_CLR BIT(31)
+#define MSDC_FIFOCS_TXCNT_M 0xff0000
+#define MSDC_FIFOCS_TXCNT_S 16
+#define MSDC_FIFOCS_RXCNT_M 0xff
+#define MSDC_FIFOCS_RXCNT_S 0
+
+/* #define SDC_CFG */
+#define SDC_CFG_DTOC_M 0xff000000
+#define SDC_CFG_DTOC_S 24
+#define SDC_CFG_SDIOIDE BIT(20)
+#define SDC_CFG_SDIO BIT(19)
+#define SDC_CFG_BUSWIDTH_M 0x30000
+#define SDC_CFG_BUSWIDTH_S 16
+
+/* SDC_CMD */
+#define SDC_CMD_BLK_LEN_M 0xfff0000
+#define SDC_CMD_BLK_LEN_S 16
+#define SDC_CMD_STOP BIT(14)
+#define SDC_CMD_WR BIT(13)
+#define SDC_CMD_DTYPE_M 0x1800
+#define SDC_CMD_DTYPE_S 11
+#define SDC_CMD_RSPTYP_M 0x380
+#define SDC_CMD_RSPTYP_S 7
+#define SDC_CMD_CMD_M 0x3f
+#define SDC_CMD_CMD_S 0
+
+/* SDC_STS */
+#define SDC_STS_CMDBUSY BIT(1)
+#define SDC_STS_SDCBUSY BIT(0)
+
+/* SDC_ADV_CFG0 */
+#define SDC_RX_ENHANCE_EN BIT(20)
+
+/* PATCH_BIT0 */
+#define MSDC_INT_DAT_LATCH_CK_SEL_M 0x380
+#define MSDC_INT_DAT_LATCH_CK_SEL_S 7
+
+/* PATCH_BIT1 */
+#define MSDC_PB1_STOP_DLY_M 0xf00
+#define MSDC_PB1_STOP_DLY_S 8
+
+/* PATCH_BIT2 */
+#define MSDC_PB2_CRCSTSENSEL_M 0xe0000000
+#define MSDC_PB2_CRCSTSENSEL_S 29
+#define MSDC_PB2_CFGCRCSTS BIT(28)
+#define MSDC_PB2_RESPSTSENSEL_M 0x70000
+#define MSDC_PB2_RESPSTSENSEL_S 16
+#define MSDC_PB2_CFGRESP BIT(15)
+#define MSDC_PB2_RESPWAIT_M 0x0c
+#define MSDC_PB2_RESPWAIT_S 2
+
+/* PAD_TUNE */
+#define MSDC_PAD_TUNE_CMDRRDLY_M 0x7c00000
+#define MSDC_PAD_TUNE_CMDRRDLY_S 22
+#define MSDC_PAD_TUNE_CMD_SEL BIT(21)
+#define MSDC_PAD_TUNE_CMDRDLY_M 0x1f0000
+#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 0x1f00
+#define MSDC_PAD_TUNE_DATRRDLY_S 8
+#define MSDC_PAD_TUNE_DATWRDLY_M 0x1f
+#define MSDC_PAD_TUNE_DATWRDLY_S 0
+
+/* EMMC50_CFG0 */
+#define EMMC50_CFG_CFCSTS_SEL BIT(4)
+
+/* SDC_FIFO_CFG */
+#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 DEFAULT_CD_DEBOUNCE 8
+
+#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)
+
+/* Register offset */
+struct mtk_sd_regs {
+ u32 msdc_cfg;
+ u32 msdc_iocon;
+ u32 msdc_ps;
+ u32 msdc_int;
+ u32 msdc_inten;
+ u32 msdc_fifocs;
+ u32 msdc_txdata;
+ u32 msdc_rxdata;
+ u32 reserved0[4];
+ u32 sdc_cfg;
+ u32 sdc_cmd;
+ u32 sdc_arg;
+ u32 sdc_sts;
+ u32 sdc_resp[4];
+ u32 sdc_blk_num;
+ u32 sdc_vol_chg;
+ u32 sdc_csts;
+ u32 sdc_csts_en;
+ u32 sdc_datcrc_sts;
+ u32 sdc_adv_cfg0;
+ u32 reserved1[2];
+ u32 emmc_cfg0;
+ u32 emmc_cfg1;
+ u32 emmc_sts;
+ u32 emmc_iocon;
+ u32 sd_acmd_resp;
+ u32 sd_acmd19_trg;
+ u32 sd_acmd19_sts;
+ u32 dma_sa_high4bit;
+ u32 dma_sa;
+ u32 dma_ca;
+ u32 dma_ctrl;
+ u32 dma_cfg;
+ u32 sw_dbg_sel;
+ u32 sw_dbg_out;
+ u32 dma_length;
+ u32 reserved2;
+ u32 patch_bit0;
+ u32 patch_bit1;
+ u32 patch_bit2;
+ u32 reserved3;
+ u32 dat0_tune_crc;
+ u32 dat1_tune_crc;
+ u32 dat2_tune_crc;
+ u32 dat3_tune_crc;
+ u32 cmd_tune_crc;
+ u32 sdio_tune_wind;
+ u32 reserved4[5];
+ u32 pad_tune;
+ u32 pad_tune0;
+ u32 pad_tune1;
+ u32 dat_rd_dly[4];
+ u32 reserved5[2];
+ u32 hw_dbg_sel;
+ u32 main_ver;
+ u32 eco_ver;
+ u32 reserved6[27];
+ u32 pad_ds_tune;
+ u32 reserved7[31];
+ u32 emmc50_cfg0;
+ u32 reserved8[7];
+ u32 sdc_fifo_cfg;
+};
+
+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 {
+ struct mtk_sd_regs *base;
+ struct mmc *mmc;
+
+ struct msdc_compatible *dev_comp;
+
+ struct clk src_clk; /* for SD/MMC bus clock */
+ struct clk h_clk; /* MSDC core clock */
+
+ u32 src_clk_freq; /* source clock */
+ u32 mclk; /* mmc framework required bus clock */
+ u32 sclk; /* actual calculated bus clock */
+
+ /* operation timeout clocks */
+ u32 timeout_ns;
+ u32 timeout_clks;
+
+ /* tuning options */
+ u32 hs400_ds_delay;
+ u32 hs200_cmd_int_delay;
+ u32 hs200_write_int_delay;
+ u32 latch_ck;
+ u32 r_smpl; /* sample edge */
+ bool hs400_mode;
+
+ /* whether to use gpio detection or built-in hw detection */
+ bool builtin_cd;
+
+ /* card detection / write protection GPIOs */
+#ifdef CONFIG_DM_GPIO
+ struct gpio_desc gpio_wp;
+ struct gpio_desc gpio_cd;
+#endif
+
+ 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_M) >> MSDC_FIFOCS_RXCNT_S;
+}
+
+static u32 msdc_fifo_tx_bytes(struct msdc_host *host)
+{
+ return (readl(&host->base->msdc_fifocs) &
+ MSDC_FIFOCS_TXCNT_M) >> MSDC_FIFOCS_TXCNT_S;
+}
+
+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_S) & SDC_CMD_CMD_M) |
+ ((resp_type << SDC_CMD_RSPTYP_S) & SDC_CMD_RSPTYP_M) |
+ ((blocksize << SDC_CMD_BLK_LEN_S) & SDC_CMD_BLK_LEN_M) |
+ ((dtype << SDC_CMD_DTYPE_S) & SDC_CMD_DTYPE_M);
+
+ 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_resp[3]);
+ rsp[1] = readl(&host->base->sdc_resp[2]);
+ rsp[2] = readl(&host->base->sdc_resp[1]);
+ rsp[3] = readl(&host->base->sdc_resp[0]);
+ } else {
+ rsp[0] = readl(&host->base->sdc_resp[0]);
+ }
+ }
+
+ 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_M) >> MSDC_CFG_CKMOD_S;
+ else
+ mode = (readl(&host->base->msdc_cfg) &
+ MSDC_CFG_CKMOD_EXT_M) >> MSDC_CFG_CKMOD_EXT_S;
+ /* 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,
+ 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;
+
+ 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 >> MSDC_CFG_CKDIV_S));
+ clrsetbits_le32(&host->base->msdc_cfg,
+ MSDC_CFG_CKMOD_M | MSDC_CFG_CKDIV_M,
+ (mode << MSDC_CFG_CKMOD_S) |
+ (div << MSDC_CFG_CKDIV_S));
+ } else {
+ div = min(div, (u32)(MSDC_CFG_CKDIV_EXT_M >>
+ MSDC_CFG_CKDIV_EXT_S));
+ clrsetbits_le32(&host->base->msdc_cfg,
+ MSDC_CFG_CKMOD_EXT_M | MSDC_CFG_CKDIV_EXT_M,
+ (mode << MSDC_CFG_CKMOD_EXT_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->pad_tune);
+ } else {
+ writel(host->saved_tune_para.iocon, &host->base->msdc_iocon);
+ writel(host->saved_tune_para.pad_tune,
+ &host->base->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;
+}
+
+static int msdc_ops_get_cd(struct udevice *dev)
+{
+ struct msdc_host *host = dev_get_priv(dev);
+ u32 val;
+
+ if (host->builtin_cd) {
+ val = readl(&host->base->msdc_ps);
+ return !(val & MSDC_PS_CDSTS);
+ }
+
+#ifdef CONFIG_DM_GPIO
+ if (!host->gpio_cd.dev)
+ return 1;
+
+ return dm_gpio_get_value(&host->gpio_cd);
+#else
+ return 1;
+#endif
+}
+
+static int msdc_ops_get_wp(struct udevice *dev)
+{
+ struct msdc_host *host = dev_get_priv(dev);
+
+#ifdef CONFIG_DM_GPIO
+ if (!host->gpio_wp.dev)
+ return 0;
+
+ return !dm_gpio_get_value(&host->gpio_wp);
+#else
+ return 0;
+#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;
+ void __iomem *tune_reg = &host->base->pad_tune;
+ int cmd_err;
+ int i, j;
+
+ if (host->dev_comp->pad_tune0)
+ tune_reg = &host->base->pad_tune0;
+
+ if (mmc->selected_mode == MMC_HS_200 ||
+ mmc->selected_mode == UHS_SDR104)
+ clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_CMDRRDLY_M,
+ 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(tune_reg, MSDC_PAD_TUNE_CMDRDLY_M,
+ 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(tune_reg, MSDC_PAD_TUNE_CMDRDLY_M,
+ 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(tune_reg, MSDC_PAD_TUNE_CMDRDLY_M,
+ 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(tune_reg, MSDC_PAD_TUNE_CMDRDLY_M,
+ 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(tune_reg, MSDC_PAD_TUNE_CMDRRDLY_M,
+ 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(tune_reg, MSDC_PAD_TUNE_CMDRRDLY_M,
+ 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;
+ void __iomem *tune_reg = &host->base->pad_tune;
+ int cmd_err;
+ int i, ret;
+
+ if (host->dev_comp->pad_tune0)
+ tune_reg = &host->base->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(tune_reg, MSDC_PAD_TUNE_DATRRDLY_M,
+ 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(tune_reg, MSDC_PAD_TUNE_DATRRDLY_M,
+ 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(tune_reg, MSDC_PAD_TUNE_DATRRDLY_M,
+ 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(tune_reg, MSDC_PAD_TUNE_DATRRDLY_M,
+ 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(tune_reg, MSDC_PAD_TUNE_DATWRDLY_M,
+ 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->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->pad_tune);
+
+ return ret;
+}
+#endif
+
+static void msdc_init_hw(struct msdc_host *host)
+{
+ u32 val;
+ void __iomem *tune_reg = &host->base->pad_tune;
+
+ if (host->dev_comp->pad_tune0)
+ tune_reg = &host->base->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);
+
+ /* Enable/disable hw card detection according to fdt option */
+ if (host->builtin_cd)
+ clrsetbits_le32(&host->base->msdc_ps,
+ MSDC_PS_CDDBCE_M,
+ (DEFAULT_CD_DEBOUNCE << MSDC_PS_CDDBCE_S) |
+ MSDC_PS_CDEN);
+ else
+ 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, 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->patch_bit0);
+ writel(0xffff4089, &host->base->patch_bit1);
+
+ if (host->dev_comp->stop_clk_fix)
+ clrsetbits_le32(&host->base->patch_bit1, MSDC_PB1_STOP_DLY_M,
+ 3 << MSDC_PB1_STOP_DLY_S);
+
+ if (host->dev_comp->busy_check)
+ clrbits_le32(&host->base->patch_bit1, (1 << 7));
+
+ setbits_le32(&host->base->emmc50_cfg0, EMMC50_CFG_CFCSTS_SEL);
+
+ if (host->dev_comp->async_fifo) {
+ clrsetbits_le32(&host->base->patch_bit2, MSDC_PB2_RESPWAIT_M,
+ 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->patch_bit2,
+ MSDC_PB2_RESPSTSENSEL_M,
+ 2 << MSDC_PB2_RESPSTSENSEL_S);
+ clrsetbits_le32(&host->base->patch_bit2,
+ MSDC_PB2_CRCSTSENSEL_M,
+ 2 << MSDC_PB2_CRCSTSENSEL_S);
+ }
+
+ /* use async fifo to avoid tune internal delay */
+ clrbits_le32(&host->base->patch_bit2,
+ MSDC_PB2_CFGRESP);
+ clrbits_le32(&host->base->patch_bit2,
+ MSDC_PB2_CFGCRCSTS);
+ }
+
+ if (host->dev_comp->data_tune) {
+ setbits_le32(tune_reg,
+ MSDC_PAD_TUNE_RD_SEL | MSDC_PAD_TUNE_CMD_SEL);
+ clrsetbits_le32(&host->base->patch_bit0,
+ MSDC_INT_DAT_LATCH_CK_SEL_M,
+ host->latch_ck <<
+ MSDC_INT_DAT_LATCH_CK_SEL_S);
+ } else {
+ /* choose clock tune */
+ setbits_le32(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,
+ 3 << SDC_CFG_DTOC_S);
+
+ if (host->dev_comp->stop_clk_fix) {
+ clrbits_le32(&host->base->sdc_fifo_cfg,
+ SDC_FIFO_CFG_WRVALIDSEL);
+ clrbits_le32(&host->base->sdc_fifo_cfg,
+ SDC_FIFO_CFG_RDVALIDSEL);
+ }
+
+ host->def_tune_para.iocon = readl(&host->base->msdc_iocon);
+ host->def_tune_para.pad_tune = readl(&host->base->pad_tune);
+}
+
+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;
+
+ cfg->name = dev->name;
+
+ 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->f_max = host->src_clk_freq / 2;
+
+ 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;
+
+#ifdef CONFIG_PINCTRL
+ pinctrl_select_state(dev, "default");
+#endif
+
+ msdc_ungate_clock(host);
+ msdc_init_hw(host);
+
+ upriv->mmc = &plat->mmc;
+
+ return 0;
+}
+
+static int msdc_ofdata_to_platdata(struct udevice *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;
+
+ 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;
+
+#ifdef CONFIG_DM_GPIO
+ 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);
+#endif
+
+ 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->builtin_cd = dev_read_u32_default(dev, "builtin-cd", 0);
+
+ 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,
+ .get_cd = msdc_ops_get_cd,
+ .get_wp = msdc_ops_get_wp,
+#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,
+ .ofdata_to_platdata = msdc_ofdata_to_platdata,
+ .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),
+};
diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c
index 147eb9b4d5..9bf040cb40 100644
--- a/drivers/mmc/sunxi_mmc.c
+++ b/drivers/mmc/sunxi_mmc.c
@@ -98,24 +98,21 @@ static int mmc_resource_init(int sdc_no)
static int mmc_set_mod_clk(struct sunxi_mmc_priv *priv, unsigned int hz)
{
unsigned int pll, pll_hz, div, n, oclk_dly, sclk_dly;
- bool new_mode = false;
+ bool new_mode = true;
bool calibrate = false;
u32 val = 0;
- if (IS_ENABLED(CONFIG_MMC_SUNXI_HAS_NEW_MODE) && (priv->mmc_no == 2))
- new_mode = true;
+ if (!IS_ENABLED(CONFIG_MMC_SUNXI_HAS_NEW_MODE))
+ new_mode = false;
+
+ /* A83T support new mode only on eMMC */
+ if (IS_ENABLED(CONFIG_MACH_SUN8I_A83T) && priv->mmc_no != 2)
+ new_mode = false;
#if defined(CONFIG_MACH_SUN50I) || defined(CONFIG_MACH_SUN50I_H6)
calibrate = true;
#endif
- /*
- * The MMC clock has an extra /2 post-divider when operating in the new
- * mode.
- */
- if (new_mode)
- hz = hz * 2;
-
if (hz <= 24000000) {
pll = CCM_MMC_CTRL_OSCM24;
pll_hz = 24000000;
@@ -176,7 +173,9 @@ static int mmc_set_mod_clk(struct sunxi_mmc_priv *priv, unsigned int hz)
if (new_mode) {
#ifdef CONFIG_MMC_SUNXI_HAS_NEW_MODE
+#ifdef CONFIG_MMC_SUNXI_HAS_MODE_SWITCH
val = CCM_MMC_CTRL_MODE_SEL_NEW;
+#endif
setbits_le32(&priv->reg->ntsr, SUNXI_MMC_NTSR_MODE_SEL_NEW);
#endif
} else if (!calibrate) {
diff --git a/drivers/net/sun8i_emac.c b/drivers/net/sun8i_emac.c
index 3ba3a1ff8b..c9798445c7 100644
--- a/drivers/net/sun8i_emac.c
+++ b/drivers/net/sun8i_emac.c
@@ -60,6 +60,10 @@
#define SC_ETCS_MASK GENMASK(1, 0)
#define SC_ETCS_EXT_GMII 0x1
#define SC_ETCS_INT_GMII 0x2
+#define SC_ETXDC_MASK GENMASK(12, 10)
+#define SC_ETXDC_OFFSET 10
+#define SC_ERXDC_MASK GENMASK(9, 5)
+#define SC_ERXDC_OFFSET 5
#define CONFIG_MDIO_TIMEOUT (3 * CONFIG_SYS_HZ)
@@ -140,6 +144,8 @@ struct emac_eth_dev {
struct sun8i_eth_pdata {
struct eth_pdata eth_pdata;
u32 reset_delays[3];
+ int tx_delay_ps;
+ int rx_delay_ps;
};
@@ -273,7 +279,8 @@ static int sun8i_emac_set_syscon_ephy(struct emac_eth_dev *priv, u32 *reg)
return 0;
}
-static int sun8i_emac_set_syscon(struct emac_eth_dev *priv)
+static int sun8i_emac_set_syscon(struct sun8i_eth_pdata *pdata,
+ struct emac_eth_dev *priv)
{
int ret;
u32 reg;
@@ -312,6 +319,14 @@ static int sun8i_emac_set_syscon(struct emac_eth_dev *priv)
return -EINVAL;
}
+ if (pdata->tx_delay_ps)
+ reg |= ((pdata->tx_delay_ps / 100) << SC_ETXDC_OFFSET)
+ & SC_ETXDC_MASK;
+
+ if (pdata->rx_delay_ps)
+ reg |= ((pdata->rx_delay_ps / 100) << SC_ERXDC_OFFSET)
+ & SC_ERXDC_MASK;
+
writel(reg, priv->sysctl_reg + 0x30);
return 0;
@@ -784,13 +799,14 @@ static void sun8i_emac_eth_stop(struct udevice *dev)
static int sun8i_emac_eth_probe(struct udevice *dev)
{
- struct eth_pdata *pdata = dev_get_platdata(dev);
+ struct sun8i_eth_pdata *sun8i_pdata = dev_get_platdata(dev);
+ struct eth_pdata *pdata = &sun8i_pdata->eth_pdata;
struct emac_eth_dev *priv = dev_get_priv(dev);
priv->mac_reg = (void *)pdata->iobase;
sun8i_emac_board_setup(priv);
- sun8i_emac_set_syscon(priv);
+ sun8i_emac_set_syscon(sun8i_pdata, priv);
sun8i_mdio_init(dev->name, dev);
priv->bus = miiphy_get_dev_by_name(dev->name);
@@ -891,6 +907,18 @@ static int sun8i_emac_eth_ofdata_to_platdata(struct udevice *dev)
if (!priv->use_internal_phy)
parse_phy_pins(dev);
+ sun8i_pdata->tx_delay_ps = fdtdec_get_int(gd->fdt_blob, node,
+ "allwinner,tx-delay-ps", 0);
+ if (sun8i_pdata->tx_delay_ps < 0 || sun8i_pdata->tx_delay_ps > 700)
+ printf("%s: Invalid TX delay value %d\n", __func__,
+ sun8i_pdata->tx_delay_ps);
+
+ sun8i_pdata->rx_delay_ps = fdtdec_get_int(gd->fdt_blob, node,
+ "allwinner,rx-delay-ps", 0);
+ if (sun8i_pdata->rx_delay_ps < 0 || sun8i_pdata->rx_delay_ps > 3100)
+ printf("%s: Invalid RX delay value %d\n", __func__,
+ sun8i_pdata->rx_delay_ps);
+
#ifdef CONFIG_DM_GPIO
if (fdtdec_get_bool(gd->fdt_blob, dev_of_offset(dev),
"snps,reset-active-low"))
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index ad0b8daba6..7e6fad305a 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 a3a6c6d163..293bad3a95 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 0000000000..1bd9a925a5
--- /dev/null
+++ b/drivers/pinctrl/mediatek/Kconfig
@@ -0,0 +1,15 @@
+if ARCH_MEDIATEK
+
+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
+
+endif
diff --git a/drivers/pinctrl/mediatek/Makefile b/drivers/pinctrl/mediatek/Makefile
new file mode 100644
index 0000000000..f6ef3627e8
--- /dev/null
+++ b/drivers/pinctrl/mediatek/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0
+# Core
+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 0000000000..fd37dfa442
--- /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_common_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-mt7629.c b/drivers/pinctrl/mediatek/pinctrl-mt7629.c
new file mode 100644
index 0000000000..aa6d1c2d91
--- /dev/null
+++ b/drivers/pinctrl/mediatek/pinctrl-mt7629.c
@@ -0,0 +1,409 @@
+// 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, 66, 67 };
+static int mt7629_snfi_funcs[] = { 2, 2, 2, 2, 2, 2 };
+
+/* SPI NOR */
+static int mt7629_snor_pins[] = { 62, 63, 64, 65, 66, 67 };
+static int mt7629_snor_funcs[] = { 1, 1, 1, 1, 1, 1 };
+
+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("spi_nor", mt7629_snor),
+};
+
+/* 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[] = { "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_wifi_groups[] = { "wf0_5g", "wf0_2g", };
+static const char *const mt7629_flash_groups[] = { "snfi", "spi_nor" };
+
+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)},
+ {"wifi", mt7629_wifi_groups, ARRAY_SIZE(mt7629_wifi_groups)},
+ {"flash", mt7629_flash_groups, ARRAY_SIZE(mt7629_flash_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_common_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 0000000000..938cc75496
--- /dev/null
+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
@@ -0,0 +1,553 @@
+// 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_common_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 0000000000..86559f0f14
--- /dev/null
+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h
@@ -0,0 +1,184 @@
+/* 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;
+
+/* A common read-modify-write helper for MediaTek chips */
+void mtk_rmw(struct udevice *dev, u32 reg, u32 mask, u32 set);
+int mtk_pinctrl_common_probe(struct udevice *dev,
+ struct mtk_pinctrl_soc *soc);
+
+#endif /* __PINCTRL_MEDIATEK_H__ */
diff --git a/drivers/power/domain/Kconfig b/drivers/power/domain/Kconfig
index a08b4288b4..93deaef809 100644
--- a/drivers/power/domain/Kconfig
+++ b/drivers/power/domain/Kconfig
@@ -23,6 +23,13 @@ config IMX8_POWER_DOMAIN
Enable support for manipulating NXP i.MX8 on-SoC power domains via IPC
requests to the SCU.
+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 b08d18f7ac..695aafe17d 100644
--- a/drivers/power/domain/Makefile
+++ b/drivers/power/domain/Makefile
@@ -6,6 +6,7 @@
obj-$(CONFIG_$(SPL_)POWER_DOMAIN) += power-domain-uclass.o
obj-$(CONFIG_BCM6328_POWER_DOMAIN) += bcm6328-power-domain.o
obj-$(CONFIG_IMX8_POWER_DOMAIN) += imx8-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 0000000000..c67e8804b1
--- /dev/null
+++ b/drivers/power/domain/mtk-power-domain.c
@@ -0,0 +1,406 @@
+// 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/mt7623-power.h>
+#include <dt-bindings/power/mt7629-power.h>
+
+#define SPM_EN (0xb16 << 16 | 0x1)
+#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
+#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_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)
+
+/* 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_MT7623,
+ 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_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,
+ .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;
+
+ writel(SPM_EN, scpd->base);
+
+ 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;
+
+ 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_MT7623:
+ scpd->data = scp_domain_mt7623;
+ break;
+ 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,mt7623-scpsys",
+ .data = SCPSYS_MT7623,
+ },
+ {
+ .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),
+};
diff --git a/drivers/ram/Makefile b/drivers/ram/Makefile
index e14c1cf592..976ec66df7 100644
--- a/drivers/ram/Makefile
+++ b/drivers/ram/Makefile
@@ -13,3 +13,4 @@ obj-$(CONFIG_ARCH_BMIPS) += bmips_ram.o
obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
obj-$(CONFIG_K3_AM654_DDRSS) += k3-am654-ddrss.o
+obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/
diff --git a/drivers/ram/mediatek/Makefile b/drivers/ram/mediatek/Makefile
new file mode 100644
index 0000000000..95507b593c
--- /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 0000000000..b413f499d0
--- /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),
+};
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 6625a65b58..3bcc61e731 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -368,6 +368,16 @@ config DEBUG_UART_OMAP
You will need to provide parameters to make this work. The driver
will be available until the real driver model serial is running.
+config DEBUG_UART_MTK
+ bool "MediaTek High-speed UART"
+ depends on MTK_SERIAL
+ help
+ Select this to enable a debug UART using the MediaTek High-speed
+ UART driver.
+ You will need to provide parameters to make this work. The
+ driver will be available until the real driver model serial is
+ running.
+
endchoice
config DEBUG_UART_BASE
@@ -698,6 +708,16 @@ config ZYNQ_SERIAL
This driver supports the Cadence UART. It is found e.g. in Xilinx
Zynq/ZynqMP.
+config MTK_SERIAL
+ bool "MediaTek High-speed UART support"
+ depends on DM_SERIAL
+ help
+ Select this to enable UART support for MediaTek High-speed UART
+ devices. This driver uses driver model and requires a device
+ tree binding to operate.
+ The High-speed UART is compatible with the ns16550a UART and have
+ its own high-speed registers.
+
config MPC8XX_CONS
bool "Console driver for MPC8XX"
depends on MPC8xx
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index a48458f955..b6377b1076 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -67,6 +67,7 @@ obj-$(CONFIG_MPC8XX_CONS) += serial_mpc8xx.o
obj-$(CONFIG_NULLDEV_SERIAL) += serial_nulldev.o
obj-$(CONFIG_OWL_SERIAL) += serial_owl.o
obj-$(CONFIG_OMAP_SERIAL) += serial_omap.o
+obj-$(CONFIG_MTK_SERIAL) += serial_mtk.o
ifndef CONFIG_SPL_BUILD
obj-$(CONFIG_USB_TTY) += usbtty.o
diff --git a/drivers/serial/serial_mtk.c b/drivers/serial/serial_mtk.c
new file mode 100644
index 0000000000..bce1be8227
--- /dev/null
+++ b/drivers/serial/serial_mtk.c
@@ -0,0 +1,268 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MediaTek High-speed UART driver
+ *
+ * Copyright (C) 2018 MediaTek Inc.
+ * Author: Weijie Gao <weijie.gao@mediatek.com>
+ */
+
+#include <clk.h>
+#include <common.h>
+#include <div64.h>
+#include <dm.h>
+#include <errno.h>
+#include <serial.h>
+#include <watchdog.h>
+#include <asm/io.h>
+#include <asm/types.h>
+
+struct mtk_serial_regs {
+ u32 rbr;
+ u32 ier;
+ u32 fcr;
+ u32 lcr;
+ u32 mcr;
+ u32 lsr;
+ u32 msr;
+ u32 spr;
+ u32 mdr1;
+ u32 highspeed;
+ u32 sample_count;
+ u32 sample_point;
+ u32 fracdiv_l;
+ u32 fracdiv_m;
+ u32 escape_en;
+ u32 guard;
+ u32 rx_sel;
+};
+
+#define thr rbr
+#define iir fcr
+#define dll rbr
+#define dlm ier
+
+#define UART_LCR_WLS_8 0x03 /* 8 bit character length */
+#define UART_LCR_DLAB 0x80 /* Divisor latch access bit */
+
+#define UART_LSR_DR 0x01 /* Data ready */
+#define UART_LSR_THRE 0x20 /* Xmit holding register empty */
+
+/* the data is correct if the real baud is within 3%. */
+#define BAUD_ALLOW_MAX(baud) ((baud) + (baud) * 3 / 100)
+#define BAUD_ALLOW_MIX(baud) ((baud) - (baud) * 3 / 100)
+
+struct mtk_serial_priv {
+ struct mtk_serial_regs __iomem *regs;
+ u32 clock;
+};
+
+static void _mtk_serial_setbrg(struct mtk_serial_priv *priv, int baud)
+{
+ bool support_clk12m_baud115200;
+ u32 quot, samplecount, realbaud;
+
+ if ((baud <= 115200) && (priv->clock == 12000000))
+ support_clk12m_baud115200 = true;
+ else
+ support_clk12m_baud115200 = false;
+
+ if (baud <= 115200) {
+ writel(0, &priv->regs->highspeed);
+ quot = DIV_ROUND_CLOSEST(priv->clock, 16 * baud);
+
+ if (support_clk12m_baud115200) {
+ writel(3, &priv->regs->highspeed);
+ quot = DIV_ROUND_CLOSEST(priv->clock, 256 * baud);
+ if (quot == 0)
+ quot = 1;
+
+ samplecount = DIV_ROUND_CLOSEST(priv->clock,
+ quot * baud);
+ if (samplecount != 0) {
+ realbaud = priv->clock / samplecount / quot;
+ if ((realbaud > BAUD_ALLOW_MAX(baud)) ||
+ (realbaud < BAUD_ALLOW_MIX(baud))) {
+ pr_info("baud %d can't be handled\n",
+ baud);
+ }
+ } else {
+ pr_info("samplecount is 0\n");
+ }
+ }
+ } else if (baud <= 576000) {
+ writel(2, &priv->regs->highspeed);
+
+ /* Set to next lower baudrate supported */
+ if ((baud == 500000) || (baud == 576000))
+ baud = 460800;
+ quot = DIV_ROUND_UP(priv->clock, 4 * baud);
+ } else {
+ writel(3, &priv->regs->highspeed);
+ quot = DIV_ROUND_UP(priv->clock, 256 * baud);
+ }
+
+ /* set divisor */
+ writel(UART_LCR_WLS_8 | UART_LCR_DLAB, &priv->regs->lcr);
+ writel(quot & 0xff, &priv->regs->dll);
+ writel((quot >> 8) & 0xff, &priv->regs->dlm);
+ writel(UART_LCR_WLS_8, &priv->regs->lcr);
+
+ if (baud > 460800) {
+ u32 tmp;
+
+ tmp = DIV_ROUND_CLOSEST(priv->clock, quot * baud);
+ writel(tmp - 1, &priv->regs->sample_count);
+ writel((tmp - 2) >> 1, &priv->regs->sample_point);
+ } else {
+ writel(0, &priv->regs->sample_count);
+ writel(0xff, &priv->regs->sample_point);
+ }
+
+ if (support_clk12m_baud115200) {
+ writel(samplecount - 1, &priv->regs->sample_count);
+ writel((samplecount - 2) >> 1, &priv->regs->sample_point);
+ }
+}
+
+static int mtk_serial_setbrg(struct udevice *dev, int baudrate)
+{
+ struct mtk_serial_priv *priv = dev_get_priv(dev);
+
+ _mtk_serial_setbrg(priv, baudrate);
+
+ return 0;
+}
+
+static int mtk_serial_putc(struct udevice *dev, const char ch)
+{
+ struct mtk_serial_priv *priv = dev_get_priv(dev);
+
+ if (!(readl(&priv->regs->lsr) & UART_LSR_THRE))
+ return -EAGAIN;
+
+ writel(ch, &priv->regs->thr);
+
+ if (ch == '\n')
+ WATCHDOG_RESET();
+
+ return 0;
+}
+
+static int mtk_serial_getc(struct udevice *dev)
+{
+ struct mtk_serial_priv *priv = dev_get_priv(dev);
+
+ if (!(readl(&priv->regs->lsr) & UART_LSR_DR))
+ return -EAGAIN;
+
+ return readl(&priv->regs->rbr);
+}
+
+static int mtk_serial_pending(struct udevice *dev, bool input)
+{
+ struct mtk_serial_priv *priv = dev_get_priv(dev);
+
+ if (input)
+ return (readl(&priv->regs->lsr) & UART_LSR_DR) ? 1 : 0;
+ else
+ return (readl(&priv->regs->lsr) & UART_LSR_THRE) ? 0 : 1;
+}
+
+static int mtk_serial_probe(struct udevice *dev)
+{
+ struct mtk_serial_priv *priv = dev_get_priv(dev);
+
+ /* Disable interrupt */
+ writel(0, &priv->regs->ier);
+
+ return 0;
+}
+
+static int mtk_serial_ofdata_to_platdata(struct udevice *dev)
+{
+ struct mtk_serial_priv *priv = dev_get_priv(dev);
+ fdt_addr_t addr;
+ struct clk clk;
+ int err;
+
+ addr = dev_read_addr(dev);
+ if (addr == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ priv->regs = map_physmem(addr, 0, MAP_NOCACHE);
+
+ err = clk_get_by_index(dev, 0, &clk);
+ if (!err) {
+ err = clk_get_rate(&clk);
+ if (!IS_ERR_VALUE(err))
+ priv->clock = err;
+ } else if (err != -ENOENT && err != -ENODEV && err != -ENOSYS) {
+ debug("mtk_serial: failed to get clock\n");
+ return err;
+ }
+
+ if (!priv->clock)
+ priv->clock = dev_read_u32_default(dev, "clock-frequency", 0);
+
+ if (!priv->clock) {
+ debug("mtk_serial: clock not defined\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct dm_serial_ops mtk_serial_ops = {
+ .putc = mtk_serial_putc,
+ .pending = mtk_serial_pending,
+ .getc = mtk_serial_getc,
+ .setbrg = mtk_serial_setbrg,
+};
+
+static const struct udevice_id mtk_serial_ids[] = {
+ { .compatible = "mediatek,hsuart" },
+ { .compatible = "mediatek,mt6577-uart" },
+ { }
+};
+
+U_BOOT_DRIVER(serial_mtk) = {
+ .name = "serial_mtk",
+ .id = UCLASS_SERIAL,
+ .of_match = mtk_serial_ids,
+ .ofdata_to_platdata = mtk_serial_ofdata_to_platdata,
+ .priv_auto_alloc_size = sizeof(struct mtk_serial_priv),
+ .probe = mtk_serial_probe,
+ .ops = &mtk_serial_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
+
+#ifdef CONFIG_DEBUG_UART_MTK
+
+#include <debug_uart.h>
+
+static inline void _debug_uart_init(void)
+{
+ struct mtk_serial_priv priv;
+
+ priv.regs = (void *) CONFIG_DEBUG_UART_BASE;
+ priv.clock = CONFIG_DEBUG_UART_CLOCK;
+
+ writel(0, &priv.regs->ier);
+
+ _mtk_serial_setbrg(&priv, CONFIG_BAUDRATE);
+}
+
+static inline void _debug_uart_putc(int ch)
+{
+ struct mtk_serial_regs __iomem *regs =
+ (void *) CONFIG_DEBUG_UART_BASE;
+
+ while (!(readl(&regs->lsr) & UART_LSR_THRE))
+ ;
+
+ writel(ch, &regs->thr);
+}
+
+DEBUG_UART_FUNCS
+
+#endif \ No newline at end of file
diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig
index d0cfc35306..b0e6f32f0b 100644
--- a/drivers/timer/Kconfig
+++ b/drivers/timer/Kconfig
@@ -160,4 +160,11 @@ config X86_TSC_TIMER
help
Select this to enable Time-Stamp Counter (TSC) timer for x86.
+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 7f19c4970a..c4fbab2aac 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 0000000000..b5e76bd358
--- /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,
+};
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 4fbe172e05..03746dd12f 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -47,6 +47,11 @@ config DM_USB
declared with the U_BOOT_USB_DEVICE() macro and will be
automatically probed when found on the bus.
+config SPL_DM_USB
+ bool "Enable driver model for USB in SPL"
+ depends on DM_USB
+ default y
+
source "drivers/usb/host/Kconfig"
source "drivers/usb/dwc3/Kconfig"
diff --git a/drivers/usb/common/Makefile b/drivers/usb/common/Makefile
index 55e0547b16..3bedbf213f 100644
--- a/drivers/usb/common/Makefile
+++ b/drivers/usb/common/Makefile
@@ -3,6 +3,6 @@
# (C) Copyright 2016 Freescale Semiconductor, Inc.
#
-obj-$(CONFIG_DM_USB) += common.o
+obj-$(CONFIG_$(SPL_)DM_USB) += common.o
obj-$(CONFIG_USB_EHCI_FSL) += fsl-dt-fixup.o fsl-errata.o
obj-$(CONFIG_USB_XHCI_FSL) += fsl-dt-fixup.o fsl-errata.o
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 1ab5cee609..f1ca6191ce 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -789,7 +789,7 @@ MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver");
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
int dwc3_init(struct dwc3 *dwc)
{
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 58fe91dc51..cfe29884e7 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -712,7 +712,7 @@ struct dwc3 {
/* device lock */
spinlock_t lock;
-#if defined(__UBOOT__) && defined(CONFIG_DM_USB)
+#if defined(__UBOOT__) && CONFIG_IS_ENABLED(DM_USB)
struct udevice *dev;
#else
struct device *dev;
diff --git a/drivers/usb/eth/usb_ether.c b/drivers/usb/eth/usb_ether.c
index 1ce3361b45..3aca9ac265 100644
--- a/drivers/usb/eth/usb_ether.c
+++ b/drivers/usb/eth/usb_ether.c
@@ -271,7 +271,7 @@ int usb_host_eth_scan(int mode)
}
usb_max_eth_dev = 0;
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
/*
* TODO: We should add U_BOOT_USB_DEVICE() declarations to each USB
* Ethernet driver and then most of this file can be removed.
diff --git a/drivers/usb/gadget/ci_udc.c b/drivers/usb/gadget/ci_udc.c
index 0a84f6850d..bd596ce977 100644
--- a/drivers/usb/gadget/ci_udc.c
+++ b/drivers/usb/gadget/ci_udc.c
@@ -1015,7 +1015,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
if (driver->speed != USB_SPEED_FULL && driver->speed != USB_SPEED_HIGH)
return -EINVAL;
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
ret = usb_setup_ehci_gadget(&controller.ctrl);
#else
ret = usb_lowlevel_init(0, USB_INIT_DEVICE, (void **)&controller.ctrl);
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 90ef1f055f..193583b437 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -100,7 +100,7 @@ struct eth_dev {
struct usb_gadget *gadget;
struct usb_request *req; /* for control responses */
struct usb_request *stat_req; /* for cdc & rndis status */
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
struct udevice *usb_udev;
#endif
@@ -2337,7 +2337,7 @@ fail:
/*-------------------------------------------------------------------------*/
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
int dm_usb_init(struct eth_dev *e_dev)
{
struct udevice *dev = NULL;
@@ -2362,7 +2362,7 @@ static int _usb_eth_init(struct ether_priv *priv)
unsigned long ts;
unsigned long timeout = USB_CONNECT_TIMEOUT;
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
if (dm_usb_init(dev)) {
pr_err("USB ether not found\n");
return -ENODEV;
@@ -2541,7 +2541,7 @@ void _usb_eth_halt(struct ether_priv *priv)
}
usb_gadget_unregister_driver(&priv->eth_driver);
-#ifndef CONFIG_DM_USB
+#if !CONFIG_IS_ENABLED(DM_USB)
board_usb_cleanup(0, USB_INIT_DEVICE);
#endif
}
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index cb8c315a15..285c20ae86 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -3,8 +3,8 @@
# (C) Copyright 2000-2007
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
-ifdef CONFIG_DM_USB
-obj-$(CONFIG_CMD_USB) += usb-uclass.o
+ifdef CONFIG_$(SPL_)DM_USB
+obj-y += usb-uclass.o
obj-$(CONFIG_SANDBOX) += usb-sandbox.o
endif
diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c
index b6f008a400..a62a2f8a95 100644
--- a/drivers/usb/host/dwc2.c
+++ b/drivers/usb/host/dwc2.c
@@ -29,7 +29,7 @@
#define MAX_ENDPOINT 16
struct dwc2_priv {
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
uint8_t aligned_buffer[DWC2_DATA_BUF_SIZE] __aligned(ARCH_DMA_MINALIGN);
uint8_t status_buffer[DWC2_STATUS_BUF_SIZE] __aligned(ARCH_DMA_MINALIGN);
#ifdef CONFIG_DM_REGULATOR
@@ -54,7 +54,7 @@ struct dwc2_priv {
struct reset_ctl_bulk resets;
};
-#ifndef CONFIG_DM_USB
+#if !CONFIG_IS_ENABLED(DM_USB)
/* We need cacheline-aligned buffers for DMA transfers and dcache support */
DEFINE_ALIGN_BUFFER(uint8_t, aligned_buffer_addr, DWC2_DATA_BUF_SIZE,
ARCH_DMA_MINALIGN);
@@ -168,7 +168,7 @@ static void dwc_otg_core_reset(struct dwc2_core_regs *regs)
mdelay(100);
}
-#if defined(CONFIG_DM_USB) && defined(CONFIG_DM_REGULATOR)
+#if CONFIG_IS_ENABLED(DM_USB) && defined(CONFIG_DM_REGULATOR)
static int dwc_vbus_supply_init(struct udevice *dev)
{
struct dwc2_priv *priv = dev_get_priv(dev);
@@ -211,7 +211,7 @@ static int dwc_vbus_supply_init(struct udevice *dev)
return 0;
}
-#if defined(CONFIG_DM_USB)
+#if CONFIG_IS_ENABLED(DM_USB)
static int dwc_vbus_supply_exit(struct udevice *dev)
{
return 0;
@@ -1222,7 +1222,7 @@ static void dwc2_uninit_common(struct dwc2_core_regs *regs)
DWC2_HPRT0_PRTRST);
}
-#ifndef CONFIG_DM_USB
+#if !CONFIG_IS_ENABLED(DM_USB)
int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
int len, struct devrequest *setup)
{
@@ -1267,7 +1267,7 @@ int usb_lowlevel_stop(int index)
}
#endif
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
static int dwc2_submit_control_msg(struct udevice *dev, struct usb_device *udev,
unsigned long pipe, void *buffer, int length,
struct devrequest *setup)
diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c
index 66dc63da08..6900848df1 100644
--- a/drivers/usb/host/ehci-atmel.c
+++ b/drivers/usb/host/ehci-atmel.c
@@ -14,7 +14,7 @@
#include "ehci.h"
-#ifndef CONFIG_DM_USB
+#if !CONFIG_IS_ENABLED(DM_USB)
int ehci_hcd_init(int index, enum usb_init_type init,
struct ehci_hccr **hccr, struct ehci_hcor **hcor)
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index a8fb2b8ac3..23e7e7125f 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -25,7 +25,7 @@ DECLARE_GLOBAL_DATA_PTR;
#define CONFIG_USB_MAX_CONTROLLER_COUNT 1
#endif
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
struct ehci_fsl_priv {
struct ehci_ctrl ehci;
fdt_addr_t hcd_base;
@@ -34,7 +34,7 @@ struct ehci_fsl_priv {
#endif
static void set_txfifothresh(struct usb_ehci *, u32);
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
static int ehci_fsl_init(struct ehci_fsl_priv *priv, struct usb_ehci *ehci,
struct ehci_hccr *hccr, struct ehci_hcor *hcor);
#else
@@ -54,7 +54,7 @@ static int usb_phy_clk_valid(struct usb_ehci *ehci)
}
}
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
static int ehci_fsl_ofdata_to_platdata(struct udevice *dev)
{
struct ehci_fsl_priv *priv = dev_get_priv(dev);
@@ -183,7 +183,7 @@ int ehci_hcd_stop(int index)
}
#endif
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
static int ehci_fsl_init(struct ehci_fsl_priv *priv, struct usb_ehci *ehci,
struct ehci_hccr *hccr, struct ehci_hcor *hcor)
#else
@@ -192,7 +192,7 @@ static int ehci_fsl_init(int index, struct usb_ehci *ehci,
#endif
{
const char *phy_type = NULL;
-#ifndef CONFIG_DM_USB
+#if !CONFIG_IS_ENABLED(DM_USB)
size_t len;
char current_usb_controller[5];
#endif
@@ -218,7 +218,7 @@ static int ehci_fsl_init(int index, struct usb_ehci *ehci,
out_be32(&ehci->snoop2, 0x80000000 | SNOOP_SIZE_2GB);
/* Init phy */
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
if (priv->phy_type)
phy_type = priv->phy_type;
#else
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index d1d8f08d98..4b28db70a5 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -30,7 +30,7 @@
*/
#define HCHALT_TIMEOUT (8 * 1000)
-#ifndef CONFIG_DM_USB
+#if !CONFIG_IS_ENABLED(DM_USB)
static struct ehci_ctrl ehcic[CONFIG_USB_MAX_CONTROLLER_COUNT];
#endif
@@ -111,7 +111,7 @@ static struct descriptor {
static struct ehci_ctrl *ehci_get_ctrl(struct usb_device *udev)
{
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
return dev_get_priv(usb_get_bus(udev->dev));
#else
return udev->controller;
@@ -973,7 +973,7 @@ static void ehci_setup_ops(struct ehci_ctrl *ctrl, const struct ehci_ops *ops)
}
}
-#ifndef CONFIG_DM_USB
+#if !CONFIG_IS_ENABLED(DM_USB)
void ehci_set_controller_priv(int index, void *priv, const struct ehci_ops *ops)
{
struct ehci_ctrl *ctrl = &ehcic[index];
@@ -1097,7 +1097,7 @@ static int ehci_common_init(struct ehci_ctrl *ctrl, uint tweaks)
return 0;
}
-#ifndef CONFIG_DM_USB
+#if !CONFIG_IS_ENABLED(DM_USB)
int usb_lowlevel_stop(int index)
{
ehci_shutdown(&ehcic[index]);
@@ -1518,7 +1518,7 @@ static int _ehci_submit_int_msg(struct usb_device *dev, unsigned long pipe,
return result;
}
-#ifndef CONFIG_DM_USB
+#if !CONFIG_IS_ENABLED(DM_USB)
int submit_bulk_msg(struct usb_device *dev, unsigned long pipe,
void *buffer, int length)
{
@@ -1556,7 +1556,7 @@ int destroy_int_queue(struct usb_device *dev, struct int_queue *queue)
}
#endif
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
static int ehci_submit_control_msg(struct udevice *dev, struct usb_device *udev,
unsigned long pipe, void *buffer, int length,
struct devrequest *setup)
diff --git a/drivers/usb/host/ehci-marvell.c b/drivers/usb/host/ehci-marvell.c
index 73432f2acd..8efe6b63b9 100644
--- a/drivers/usb/host/ehci-marvell.c
+++ b/drivers/usb/host/ehci-marvell.c
@@ -38,7 +38,7 @@ DECLARE_GLOBAL_DATA_PTR;
/*
* USB 2.0 Bridge Address Decoding registers setup
*/
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
struct ehci_mvebu_priv {
struct ehci_ctrl ehci;
@@ -228,4 +228,4 @@ int ehci_hcd_stop(int index)
return 0;
}
-#endif /* CONFIG_DM_USB */
+#endif /* CONFIG_IS_ENABLED(DM_USB) */
diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c
index be010b1adb..1acf08dfb7 100644
--- a/drivers/usb/host/ehci-mx6.c
+++ b/drivers/usb/host/ehci-mx6.c
@@ -335,7 +335,7 @@ int ehci_mx6_common_init(struct usb_ehci *ehci, int index)
return 0;
}
-#ifndef CONFIG_DM_USB
+#if !CONFIG_IS_ENABLED(DM_USB)
int ehci_hcd_init(int index, enum usb_init_type init,
struct ehci_hccr **hccr, struct ehci_hcor **hcor)
{
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 6150f3d888..04e7c5e37f 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -19,7 +19,7 @@ struct ehci_pci_priv {
struct phy phy;
};
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
static int ehci_pci_init(struct udevice *dev, struct ehci_hccr **ret_hccr,
struct ehci_hcor **ret_hcor)
{
@@ -121,9 +121,9 @@ int ehci_hcd_stop(int index)
{
return 0;
}
-#endif /* nCONFIG_DM_USB */
+#endif /* !CONFIG_IS_ENABLED(DM_USB) */
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
static int ehci_pci_probe(struct udevice *dev)
{
struct ehci_hccr *hccr;
@@ -173,4 +173,4 @@ static struct pci_device_id ehci_pci_supported[] = {
U_BOOT_PCI_DEVICE(ehci_pci, ehci_pci_supported);
-#endif /* CONFIG_DM_USB */
+#endif /* CONFIG_IS_ENABLED(DM_USB) */
diff --git a/drivers/usb/host/ehci-vf.c b/drivers/usb/host/ehci-vf.c
index 22e5afad6e..a16cf135e3 100644
--- a/drivers/usb/host/ehci-vf.c
+++ b/drivers/usb/host/ehci-vf.c
@@ -153,7 +153,7 @@ int ehci_vf_common_init(struct usb_ehci *ehci, int index)
return 0;
}
-#ifndef CONFIG_DM_USB
+#if !CONFIG_IS_ENABLED(DM_USB)
int ehci_hcd_init(int index, enum usb_init_type init,
struct ehci_hccr **hccr, struct ehci_hcor **hcor)
{
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 6ea9f105a6..3b6f889f7b 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -120,7 +120,7 @@ static struct pci_device_id ehci_pci_ids[] = {
#define invalidate_dcache_iso_td(addr) invalidate_dcache_buffer(addr, 32)
#define invalidate_dcache_hcca(addr) invalidate_dcache_buffer(addr, 256)
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
/*
* The various ohci_mdelay(1) calls in the code seem unnecessary. We keep
* them around when building for older boards not yet converted to the dm
@@ -131,7 +131,7 @@ static struct pci_device_id ehci_pci_ids[] = {
#define ohci_mdelay(x) mdelay(x)
#endif
-#ifndef CONFIG_DM_USB
+#if !CONFIG_IS_ENABLED(DM_USB)
/* global ohci_t */
static ohci_t gohci;
/* this must be aligned to a 256 byte boundary */
@@ -1691,7 +1691,7 @@ static int _ohci_destroy_int_queue(ohci_t *ohci, struct usb_device *dev,
return 0;
}
-#ifndef CONFIG_DM_USB
+#if !CONFIG_IS_ENABLED(DM_USB)
/* submit routines called from usb.c */
int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
int transfer_len)
@@ -1980,7 +1980,7 @@ static int hc_interrupt(ohci_t *ohci)
/*-------------------------------------------------------------------------*/
-#ifndef CONFIG_DM_USB
+#if !CONFIG_IS_ENABLED(DM_USB)
/*-------------------------------------------------------------------------*/
@@ -2130,7 +2130,7 @@ int submit_control_msg(struct usb_device *dev, unsigned long pipe,
}
#endif
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
static int ohci_submit_control_msg(struct udevice *dev, struct usb_device *udev,
unsigned long pipe, void *buffer, int length,
struct devrequest *setup)
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
index fba78dcf7a..f9f02cb09c 100644
--- a/drivers/usb/host/ohci.h
+++ b/drivers/usb/host/ohci.h
@@ -27,7 +27,7 @@
#define ED_ALIGNMENT 16
#endif
-#if defined CONFIG_DM_USB && ARCH_DMA_MINALIGN > 32
+#if CONFIG_IS_ENABLED(DM_USB) && ARCH_DMA_MINALIGN > 32
#define TD_ALIGNMENT ARCH_DMA_MINALIGN
#else
#define TD_ALIGNMENT 32
@@ -406,7 +406,7 @@ typedef struct ohci {
const char *slot_name;
} ohci_t;
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
extern struct dm_usb_ops ohci_usb_ops;
int ohci_register(struct udevice *dev, struct ohci_regs *regs);
diff --git a/drivers/usb/host/xhci-dwc3.c b/drivers/usb/host/xhci-dwc3.c
index 80754d76d0..dd0d156027 100644
--- a/drivers/usb/host/xhci-dwc3.c
+++ b/drivers/usb/host/xhci-dwc3.c
@@ -109,7 +109,7 @@ void dwc3_set_fladj(struct dwc3 *dwc3_reg, u32 val)
GFLADJ_30MHZ(val));
}
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
static int xhci_dwc3_setup_phy(struct udevice *dev)
{
struct xhci_dwc3_platdata *plat = dev_get_platdata(dev);
diff --git a/drivers/usb/host/xhci-fsl.c b/drivers/usb/host/xhci-fsl.c
index 047a8dfdef..c0b98a8ec7 100644
--- a/drivers/usb/host/xhci-fsl.c
+++ b/drivers/usb/host/xhci-fsl.c
@@ -19,7 +19,7 @@
#include <dm.h>
/* Declare global data pointer */
-#ifndef CONFIG_DM_USB
+#if !CONFIG_IS_ENABLED(DM_USB)
static struct fsl_xhci fsl_xhci;
unsigned long ctr_addr[] = FSL_USB_XHCI_ADDR;
#else
@@ -107,7 +107,7 @@ static int fsl_xhci_core_exit(struct fsl_xhci *fsl_xhci)
return 0;
}
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
static int xhci_fsl_probe(struct udevice *dev)
{
struct xhci_fsl_priv *priv = dev_get_priv(dev);
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index da5dbd94ed..04ab540695 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -723,7 +723,7 @@ void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl,
int slot_id = udev->slot_id;
int speed = udev->speed;
int route = 0;
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
struct usb_device *dev = udev;
struct usb_hub_device *hub;
#endif
@@ -739,7 +739,7 @@ void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl,
/* Only the control endpoint is valid - one endpoint context */
slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(1));
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
/* Calculate the route string for this device */
port_num = dev->portnr;
while (!usb_hub_is_root_hub(dev->dev)) {
@@ -782,7 +782,7 @@ void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl,
BUG();
}
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
/* Set up TT fields to support FS/LS devices */
if (speed == USB_SPEED_LOW || speed == USB_SPEED_FULL) {
struct udevice *parent = udev->dev;
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 9ded14cc3c..44c5f2d264 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -108,13 +108,13 @@ static struct descriptor {
},
};
-#ifndef CONFIG_DM_USB
+#if !CONFIG_IS_ENABLED(DM_USB)
static struct xhci_ctrl xhcic[CONFIG_USB_MAX_CONTROLLER_COUNT];
#endif
struct xhci_ctrl *xhci_get_ctrl(struct usb_device *udev)
{
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
struct udevice *dev;
/* Find the USB controller */
@@ -741,7 +741,7 @@ static int _xhci_alloc_device(struct usb_device *udev)
return 0;
}
-#ifndef CONFIG_DM_USB
+#if !CONFIG_IS_ENABLED(DM_USB)
int usb_alloc_device(struct usb_device *udev)
{
return _xhci_alloc_device(udev);
@@ -1256,7 +1256,7 @@ static int xhci_lowlevel_stop(struct xhci_ctrl *ctrl)
return 0;
}
-#ifndef CONFIG_DM_USB
+#if !CONFIG_IS_ENABLED(DM_USB)
int submit_control_msg(struct usb_device *udev, unsigned long pipe,
void *buffer, int length, struct devrequest *setup)
{
@@ -1340,9 +1340,9 @@ int usb_lowlevel_stop(int index)
return 0;
}
-#endif /* CONFIG_DM_USB */
+#endif /* CONFIG_IS_ENABLED(DM_USB) */
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
static int xhci_submit_control_msg(struct udevice *dev, struct usb_device *udev,
unsigned long pipe, void *buffer, int length,
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index a7555b2fa8..6017504488 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1211,7 +1211,7 @@ void xhci_hcd_stop(int index);
#define XHCI_STS_CNR (1 << 11)
struct xhci_ctrl {
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
struct udevice *dev;
#endif
struct xhci_hccr *hccr; /* R/O registers, not need for volatile */
diff --git a/drivers/usb/musb-new/musb_uboot.c b/drivers/usb/musb-new/musb_uboot.c
index 2bf918eab4..d40772b1aa 100644
--- a/drivers/usb/musb-new/musb_uboot.c
+++ b/drivers/usb/musb-new/musb_uboot.c
@@ -19,7 +19,7 @@ struct int_queue {
struct urb urb;
};
-#ifndef CONFIG_DM_USB
+#if !CONFIG_IS_ENABLED(DM_USB)
struct musb_host_data musb_host;
#endif
@@ -243,7 +243,7 @@ int musb_lowlevel_init(struct musb_host_data *host)
return 0;
}
-#ifndef CONFIG_DM_USB
+#if !CONFIG_IS_ENABLED(DM_USB)
int usb_lowlevel_stop(int index)
{
if (!musb_host.host) {
@@ -300,9 +300,9 @@ int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)
{
return musb_lowlevel_init(&musb_host);
}
-#endif /* !CONFIG_DM_USB */
+#endif /* !CONFIG_IS_ENABLED(DM_USB) */
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
static int musb_submit_control_msg(struct udevice *dev, struct usb_device *udev,
unsigned long pipe, void *buffer, int length,
struct devrequest *setup)
@@ -364,7 +364,7 @@ struct dm_usb_ops musb_usb_ops = {
.destroy_int_queue = musb_destroy_int_queue,
.reset_root_port = musb_reset_root_port,
};
-#endif /* CONFIG_DM_USB */
+#endif /* CONFIG_IS_ENABLED(DM_USB) */
#endif /* CONFIG_USB_MUSB_HOST */
#ifdef CONFIG_USB_MUSB_GADGET
@@ -425,7 +425,7 @@ struct musb *musb_register(struct musb_hdrc_platform_data *plat, void *bdata,
struct musb **musbp;
switch (plat->mode) {
-#if defined(CONFIG_USB_MUSB_HOST) && !defined(CONFIG_DM_USB)
+#if defined(CONFIG_USB_MUSB_HOST) && !CONFIG_IS_ENABLED(DM_USB)
case MUSB_HOST:
musbp = &musb_host.host;
break;
diff --git a/drivers/usb/musb-new/omap2430.c b/drivers/usb/musb-new/omap2430.c
index 342d76bd6f..58aed72b7d 100644
--- a/drivers/usb/musb-new/omap2430.c
+++ b/drivers/usb/musb-new/omap2430.c
@@ -135,7 +135,7 @@ const struct musb_platform_ops omap2430_ops = {
.disable = omap2430_musb_disable,
};
-#if defined(CONFIG_DM_USB)
+#if CONFIG_IS_ENABLED(DM_USB)
struct omap2430_musb_platdata {
void *base;
@@ -276,4 +276,4 @@ U_BOOT_DRIVER(omap2430_musb) = {
.priv_auto_alloc_size = sizeof(struct musb_host_data),
};
-#endif /* CONFIG_DM_USB */
+#endif /* CONFIG_IS_ENABLED(DM_USB) */
diff --git a/drivers/usb/musb-new/ti-musb.c b/drivers/usb/musb-new/ti-musb.c
index 9fbe2d6861..ee0960704a 100644
--- a/drivers/usb/musb-new/ti-musb.c
+++ b/drivers/usb/musb-new/ti-musb.c
@@ -19,7 +19,7 @@
DECLARE_GLOBAL_DATA_PTR;
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
/* USB 2.0 PHY Control */
#define CM_PHY_PWRDN (1 << 0)
@@ -251,4 +251,4 @@ U_BOOT_DRIVER(ti_musb_wrapper) = {
.bind = ti_musb_wrapper_bind,
};
-#endif /* CONFIG_DM_USB */
+#endif /* CONFIG_IS_ENABLED(DM_USB) */
diff --git a/drivers/usb/musb-new/usb-compat.h b/drivers/usb/musb-new/usb-compat.h
index 760bd787bc..f2c18ad3a2 100644
--- a/drivers/usb/musb-new/usb-compat.h
+++ b/drivers/usb/musb-new/usb-compat.h
@@ -67,7 +67,7 @@ static inline int usb_hcd_unmap_urb_for_dma(struct usb_hcd *hcd,
return 0;
}
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
static inline struct usb_device *usb_dev_get_parent(struct usb_device *udev)
{
struct udevice *parent = udev->dev->parent;
diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c
index d7568bc79a..2ca19d4049 100644
--- a/drivers/video/vidconsole-uclass.c
+++ b/drivers/video/vidconsole-uclass.c
@@ -272,6 +272,14 @@ static void vidconsole_escape_char(struct udevice *dev, char ch)
s++; /* ; */
s = parsenum(s, &col);
+ /*
+ * Video origin is [0, 0], terminal origin is [1, 1].
+ */
+ if (row)
+ --row;
+ if (col)
+ --col;
+
set_cursor_position(priv, row, col);
break;
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 4796da0823..4a9ebb6e26 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 b8f2842f7e..74738eeaf7 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -24,3 +24,4 @@ obj-$(CONFIG_WDT_ORION) += orion_wdt.o
obj-$(CONFIG_WDT_CDNS) += cdns_wdt.o
obj-$(CONFIG_MPC8xx_WATCHDOG) += mpc8xx_wdt.o
obj-$(CONFIG_WDT_MT7621) += mt7621_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 0000000000..0b501733f2
--- /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,
+};
diff --git a/dts/Makefile b/dts/Makefile
index 9a9a3d5c98..cd6e9a968e 100644
--- a/dts/Makefile
+++ b/dts/Makefile
@@ -61,4 +61,4 @@ dtbs: $(obj)/dt.dtb $(obj)/dt-spl.dtb
clean-files := dt.dtb.S dt-spl.dtb.S
# Let clean descend into dts directories
-subdir- += ../arch/arm/dts ../arch/microblaze/dts ../arch/mips/dts ../arch/sandbox/dts ../arch/x86/dts ../arch/powerpc/dts
+subdir- += ../arch/arm/dts ../arch/microblaze/dts ../arch/mips/dts ../arch/sandbox/dts ../arch/x86/dts ../arch/powerpc/dts ../arch/riscv/dts
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
index c83fc01b76..dffd6b2602 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -122,6 +122,13 @@ typedef struct global_data {
struct list_head log_head; /* List of struct log_device */
int log_fmt; /* Mask containing log format info */
#endif
+#if CONFIG_IS_ENABLED(BLOBLIST)
+ struct bloblist_hdr *bloblist; /* Bloblist information */
+ struct bloblist_hdr *new_bloblist; /* Relocated blolist info */
+# ifdef CONFIG_SPL
+ struct spl_handoff *spl_handoff;
+# endif
+#endif
} gd_t;
#endif
diff --git a/include/bloblist.h b/include/bloblist.h
new file mode 100644
index 0000000000..85144010ab
--- /dev/null
+++ b/include/bloblist.h
@@ -0,0 +1,195 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * This provides a standard way of passing information between boot phases
+ * (TPL -> SPL -> U-Boot proper.)
+ *
+ * A list of blobs of data, tagged with their owner. The list resides in memory
+ * and can be updated by SPL, U-Boot, etc.
+ *
+ * Copyright 2018 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#ifndef __BLOBLIST_H
+#define __BLOBLIST_H
+
+enum {
+ BLOBLIST_VERSION = 0,
+ BLOBLIST_MAGIC = 0xb00757a3,
+ BLOBLIST_ALIGN = 16,
+};
+
+enum bloblist_tag_t {
+ BLOBLISTT_NONE = 0,
+
+ /* Vendor-specific tags are permitted here */
+ BLOBLISTT_EC_HOSTEVENT, /* Chromium OS EC host-event mask */
+ BLOBLISTT_SPL_HANDOFF, /* Hand-off info from SPL */
+ BLOBLISTT_VBOOT_CTX, /* Chromium OS verified boot context */
+ BLOBLISTT_VBOOT_HANDOFF, /* Chromium OS internal handoff info */
+};
+
+/**
+ * struct bloblist_hdr - header for the bloblist
+ *
+ * This is stored at the start of the bloblist which is always on a 16-byte
+ * boundary. Records follow this header. The bloblist normally stays in the
+ * same place in memory as SPL and U-Boot execute, but it can be safely moved
+ * around.
+ *
+ * None of the bloblist structures contain pointers but it is possible to put
+ * pointers inside a bloblist record if desired. This is not encouraged,
+ * since it can make part of the bloblist inaccessible if the pointer is
+ * no-longer valid. It is better to just store all the data inside a bloblist
+ * record.
+ *
+ * Each bloblist record is aligned to a 16-byte boundary and follows immediately
+ * from the last.
+ *
+ * @version: BLOBLIST_VERSION
+ * @hdr_size: Size of this header, normally sizeof(struct bloblist_hdr). The
+ * first bloblist_rec starts at this offset from the start of the header
+ * @flags: Space for BLOBLISTF_... flags (none yet)
+ * @magic: BLOBLIST_MAGIC
+ * @size: Total size of all records (non-zero if valid) including this header.
+ * The bloblist extends for this many bytes from the start of this header.
+ * @alloced: Total size allocated for this bloblist. When adding new records,
+ * the bloblist can grow up to this size. This starts out as
+ * sizeof(bloblist_hdr) since we need at least that much space to store a
+ * valid bloblist
+ * @spare: Space space
+ * @chksum: CRC32 for the entire bloblist allocated area. Since any of the
+ * blobs can be altered after being created, this checksum is only valid
+ * when the bloblist is finalised before jumping to the next stage of boot.
+ * Note: @chksum is last to make it easier to exclude it from the checksum
+ * calculation.
+ */
+struct bloblist_hdr {
+ u32 version;
+ u32 hdr_size;
+ u32 flags;
+ u32 magic;
+
+ u32 size;
+ u32 alloced;
+ u32 spare;
+ u32 chksum;
+};
+
+/**
+ * struct bloblist_rec - record for the bloblist
+ *
+ * NOTE: Only exported for testing purposes. Do not use this struct.
+ *
+ * The bloblist contains a number of records each consisting of this record
+ * structure followed by the data contained. Each records is 16-byte aligned.
+ *
+ * @tag: Tag indicating what the record contains
+ * @hdr_size: Size of this header, normally sizeof(struct bloblist_rec). The
+ * record's data starts at this offset from the start of the record
+ * @size: Size of record in bytes, excluding the header size. This does not
+ * need to be aligned (e.g. 3 is OK).
+ * @spare: Spare space for other things
+ */
+struct bloblist_rec {
+ u32 tag;
+ u32 hdr_size;
+ u32 size;
+ u32 spare;
+};
+
+/**
+ * bloblist_find() - Find a blob
+ *
+ * Searches the bloblist and returns the blob with the matching tag
+ *
+ * @tag: Tag to search for (enum bloblist_tag_t)
+ * @size: Expected size of the blob
+ * @return pointer to blob if found, or NULL if not found, or a blob was found
+ * but it is the wrong size
+ */
+void *bloblist_find(uint tag, int size);
+
+/**
+ * bloblist_add() - Add a new blob
+ *
+ * Add a new blob to the bloblist
+ *
+ * This should only be called if you konw there is no existing blob for a
+ * particular tag. It is typically safe to call in the first phase of U-Boot
+ * (e.g. TPL or SPL). After that, bloblist_ensure() should be used instead.
+ *
+ * @tag: Tag to add (enum bloblist_tag_t)
+ * @size: Size of the blob
+ * @return pointer to the newly added block, or NULL if there is not enough
+ * space for the blob
+ */
+void *bloblist_add(uint tag, int size);
+
+/**
+ * bloblist_ensure_size() - Find or add a blob
+ *
+ * Find an existing blob, or add a new one if not found
+ *
+ * @tag: Tag to add (enum bloblist_tag_t)
+ * @size: Size of the blob
+ * @blobp: Returns a pointer to blob on success
+ * @return 0 if OK, -ENOSPC if it is missing and could not be added due to lack
+ * of space, or -ESPIPE it exists but has the wrong size
+ */
+int bloblist_ensure_size(uint tag, int size, void **blobp);
+
+/**
+ * bloblist_ensure() - Find or add a blob
+ *
+ * Find an existing blob, or add a new one if not found
+ *
+ * @tag: Tag to add (enum bloblist_tag_t)
+ * @size: Size of the blob
+ * @return pointer to blob, or NULL if it is missing and could not be added due
+ * to lack of space, or it exists but has the wrong size
+ */
+void *bloblist_ensure(uint tag, int size);
+
+/**
+ * bloblist_new() - Create a new, empty bloblist of a given size
+ *
+ * @addr: Address of bloblist
+ * @size: Initial size for bloblist
+ * @flags: Flags to use for bloblist
+ * @return 0 if OK, -EFAULT if addr is not aligned correctly, -ENOSPC is the
+ * area is not large enough
+ */
+int bloblist_new(ulong addr, uint size, uint flags);
+
+/**
+ * bloblist_check() - Check if a bloblist exists
+ *
+ * @addr: Address of bloblist
+ * @size: Expected size of blobsize, or 0 to detect the size
+ * @return 0 if OK, -ENOENT if the magic number doesn't match (indicating that
+ * there problem is no bloblist at the given address), -EPROTONOSUPPORT
+ * if the version does not match, -EIO if the checksum does not match,
+ * -EFBIG if the expected size does not match the detected size
+ */
+int bloblist_check(ulong addr, uint size);
+
+/**
+ * bloblist_finish() - Set up the bloblist for the next U-Boot part
+ *
+ * This sets the correct checksum for the bloblist. This ensures that the
+ * bloblist will be detected correctly by the next phase of U-Boot.
+ *
+ * @return 0
+ */
+int bloblist_finish(void);
+
+/**
+ * bloblist_init() - Init the bloblist system with a single bloblist
+ *
+ * This uses CONFIG_BLOBLIST_ADDR and CONFIG_BLOBLIST_SIZE to set up a bloblist
+ * for use by U-Boot.
+ */
+int bloblist_init(void);
+
+#endif /* __BLOBLIST_H */
diff --git a/include/common.h b/include/common.h
index 3f69943887..8b56137032 100644
--- a/include/common.h
+++ b/include/common.h
@@ -549,11 +549,6 @@ int cpu_release(u32 nr, int argc, char * const argv[]);
#endif
#endif
-#ifdef CONFIG_INIT_CRITICAL
-#error CONFIG_INIT_CRITICAL is deprecated!
-#error Read section CONFIG_SKIP_LOWLEVEL_INIT in README.
-#endif
-
#define ROUND(a,b) (((a) + (b) - 1) & ~((b) - 1))
/*
diff --git a/include/config_distro_bootcmd.h b/include/config_distro_bootcmd.h
index 5838eb3477..555efb7433 100644
--- a/include/config_distro_bootcmd.h
+++ b/include/config_distro_bootcmd.h
@@ -99,9 +99,9 @@
#define BOOTEFI_NAME "bootia32.efi"
#elif defined(CONFIG_X86_RUN_64BIT)
#define BOOTEFI_NAME "bootx64.efi"
-#elif defined(CONFIG_CPU_RISCV_32)
+#elif defined(CONFIG_ARCH_RV32I)
#define BOOTEFI_NAME "bootriscv32.efi"
-#elif defined(CONFIG_CPU_RISCV_64)
+#elif defined(CONFIG_ARCH_RV64I)
#define BOOTEFI_NAME "bootriscv64.efi"
#endif
#endif
@@ -242,6 +242,18 @@
BOOT_TARGET_DEVICES_references_USB_without_CONFIG_CMD_USB
#endif
+#ifdef CONFIG_CMD_VIRTIO
+#define BOOTENV_SHARED_VIRTIO BOOTENV_SHARED_BLKDEV(virtio)
+#define BOOTENV_DEV_VIRTIO BOOTENV_DEV_BLKDEV
+#define BOOTENV_DEV_NAME_VIRTIO BOOTENV_DEV_NAME_BLKDEV
+#else
+#define BOOTENV_SHARED_VIRTIO
+#define BOOTENV_DEV_VIRTIO \
+ BOOT_TARGET_DEVICES_references_VIRTIO_without_CONFIG_CMD_VIRTIO
+#define BOOTENV_DEV_NAME_VIRTIO \
+ BOOT_TARGET_DEVICES_references_VIRTIO_without_CONFIG_CMD_VIRTIO
+#endif
+
#if defined(CONFIG_CMD_DHCP)
#if defined(CONFIG_EFI_LOADER)
/* http://www.iana.org/assignments/dhcpv6-parameters/dhcpv6-parameters.xml */
@@ -257,10 +269,10 @@
#elif defined(__i386__)
#define BOOTENV_EFI_PXE_ARCH "0x6"
#define BOOTENV_EFI_PXE_VCI "PXEClient:Arch:00006:UNDI:003000"
-#elif defined(CONFIG_CPU_RISCV_32) || ((defined(__riscv) && __riscv_xlen == 32))
+#elif defined(CONFIG_ARCH_RV32I) || ((defined(__riscv) && __riscv_xlen == 32))
#define BOOTENV_EFI_PXE_ARCH "0x19"
#define BOOTENV_EFI_PXE_VCI "PXEClient:Arch:00025:UNDI:003000"
-#elif defined(CONFIG_CPU_RISCV_64) || ((defined(__riscv) && __riscv_xlen == 64))
+#elif defined(CONFIG_ARCH_RV64I) || ((defined(__riscv) && __riscv_xlen == 64))
#define BOOTENV_EFI_PXE_ARCH "0x1b"
#define BOOTENV_EFI_PXE_VCI "PXEClient:Arch:00027:UNDI:003000"
#elif defined(CONFIG_SANDBOX)
@@ -350,6 +362,7 @@
BOOTENV_SHARED_IDE \
BOOTENV_SHARED_UBIFS \
BOOTENV_SHARED_EFI \
+ BOOTENV_SHARED_VIRTIO \
"boot_prefixes=/ /boot/\0" \
"boot_scripts=boot.scr.uimg boot.scr\0" \
"boot_script_dhcp=boot.scr.uimg\0" \
diff --git a/include/configs/am65x_evm.h b/include/configs/am65x_evm.h
index 484c5ef2fe..31749c6d06 100644
--- a/include/configs/am65x_evm.h
+++ b/include/configs/am65x_evm.h
@@ -29,7 +29,9 @@
#define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME "tispl.bin"
#endif
+#ifndef CONFIG_CPU_V7R
#define CONFIG_SKIP_LOWLEVEL_INIT
+#endif
#define CONFIG_SPL_MAX_SIZE CONFIG_SYS_K3_MAX_DOWNLODABLE_IMAGE_SIZE
#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SPL_TEXT_BASE + \
diff --git a/include/configs/da850evm.h b/include/configs/da850evm.h
index ba878eb13b..14a3046f19 100644
--- a/include/configs/da850evm.h
+++ b/include/configs/da850evm.h
@@ -124,8 +124,9 @@
#ifdef CONFIG_SPL_BUILD
#define CONFIG_SYS_SPI_BASE DAVINCI_SPI1_BASE
#define CONFIG_SF_DEFAULT_SPEED 30000000
-#define CONFIG_ENV_SPI_MAX_HZ CONFIG_SF_DEFAULT_SPEED
#endif
+#define CONFIG_ENV_SPI_MAX_HZ 0
+#define CONFIG_ENV_SPI_MODE 0
#ifdef CONFIG_USE_SPIFLASH
#define CONFIG_SYS_SPI_U_BOOT_OFFS 0x8000
diff --git a/include/configs/edminiv2.h b/include/configs/edminiv2.h
index 89aa11c0ed..645fc3ffb8 100644
--- a/include/configs/edminiv2.h
+++ b/include/configs/edminiv2.h
@@ -29,7 +29,6 @@
* High Level Configuration Options (easy to change)
*/
-#define CONFIG_MARVELL 1
#define CONFIG_FEROCEON 1 /* CPU Core subversion */
#define CONFIG_88F5182 1 /* SOC Name */
diff --git a/include/configs/km/km_arm.h b/include/configs/km/km_arm.h
index e2585171af..0de83f6723 100644
--- a/include/configs/km/km_arm.h
+++ b/include/configs/km/km_arm.h
@@ -22,7 +22,6 @@
/*
* High Level Configuration Options (easy to change)
*/
-#define CONFIG_MARVELL
#define CONFIG_FEROCEON_88FR131 /* CPU Core subversion */
#define CONFIG_KW88F6281 /* SOC Name */
diff --git a/include/configs/mt7623.h b/include/configs/mt7623.h
new file mode 100644
index 0000000000..68da920e30
--- /dev/null
+++ b/include/configs/mt7623.h
@@ -0,0 +1,56 @@
+/* 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
+
+/* 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
diff --git a/include/configs/mt7629.h b/include/configs/mt7629.h
new file mode 100644
index 0000000000..a665a5eb7f
--- /dev/null
+++ b/include/configs/mt7629.h
@@ -0,0 +1,57 @@
+/* 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
+
+/* DRAM */
+#define CONFIG_SYS_SDRAM_BASE 0x40000000
+
+#endif
diff --git a/include/configs/mv-common.h b/include/configs/mv-common.h
index 5eeb5a1624..a803093163 100644
--- a/include/configs/mv-common.h
+++ b/include/configs/mv-common.h
@@ -19,7 +19,6 @@
/*
* High Level Configuration Options (easy to change)
*/
-#define CONFIG_MARVELL 1
/*
* Custom CONFIG_SYS_TEXT_BASE can be done in <board>.h
diff --git a/include/configs/qemu-riscv.h b/include/configs/qemu-riscv.h
index d279c233b2..b29d155d09 100644
--- a/include/configs/qemu-riscv.h
+++ b/include/configs/qemu-riscv.h
@@ -15,7 +15,35 @@
#define CONFIG_SYS_MALLOC_LEN SZ_8M
+#define CONFIG_SYS_BOOTM_LEN SZ_16M
+
/* Environment options */
#define CONFIG_ENV_SIZE SZ_4K
+#define BOOT_TARGET_DEVICES(func) \
+ func(QEMU, qemu, na) \
+ func(VIRTIO, virtio, 0) \
+ func(DHCP, dhcp, na)
+
+#include <config_distro_bootcmd.h>
+
+#define BOOTENV_DEV_QEMU(devtypeu, devtypel, instance) \
+ "bootcmd_qemu=" \
+ "if env exists kernel_start; then " \
+ "bootm ${kernel_start} - ${fdtcontroladdr};" \
+ "fi;\0"
+
+#define BOOTENV_DEV_NAME_QEMU(devtypeu, devtypel, instance) \
+ "qemu "
+
+#define CONFIG_EXTRA_ENV_SETTINGS \
+ "fdt_high=0xffffffffffffffff\0" \
+ "initrd_high=0xffffffffffffffff\0" \
+ "kernel_addr_r=0x81000000\0" \
+ "fdt_addr_r=0x82000000\0" \
+ "scriptaddr=0x82100000\0" \
+ "pxefile_addr_r=0x82200000\0" \
+ "ramdisk_addr_r=0x82300000\0" \
+ BOOTENV
+
#endif /* __CONFIG_H */
diff --git a/include/configs/vexpress_common.h b/include/configs/vexpress_common.h
index 267b230fda..47ea89df66 100644
--- a/include/configs/vexpress_common.h
+++ b/include/configs/vexpress_common.h
@@ -120,7 +120,7 @@
#define CONFIG_INITRD_TAG 1
/* Size of malloc() pool */
-#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 128 * 1024)
+#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 512 * 1024) /* >= 512 KiB */
#define SCTL_BASE V2M_SYSCTL
#define VEXPRESS_FLASHPROG_FLVPPEN (1 << 0)
diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h
index 2fc9fa39a3..92539b8b5f 100644
--- a/include/dm/ofnode.h
+++ b/include/dm/ofnode.h
@@ -237,6 +237,16 @@ int ofnode_read_u32_default(ofnode ref, const char *propname, u32 def);
int ofnode_read_s32_default(ofnode node, const char *propname, s32 def);
/**
+ * ofnode_read_u64() - Read a 64-bit integer from a property
+ *
+ * @node: valid node reference to read property from
+ * @propname: name of the property to read from
+ * @outp: place to put value (if found)
+ * @return 0 if OK, -ve on error
+ */
+int ofnode_read_u64(ofnode node, const char *propname, u64 *outp);
+
+/**
* ofnode_read_u64_default() - Read a 64-bit integer from a property
*
* @ref: valid node reference to read property from
diff --git a/include/dt-bindings/clock/mt7623-clk.h b/include/dt-bindings/clock/mt7623-clk.h
new file mode 100644
index 0000000000..71ced1593a
--- /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/clock/mt7629-clk.h b/include/dt-bindings/clock/mt7629-clk.h
new file mode 100644
index 0000000000..0bbfbfa744
--- /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/mt7623-power.h b/include/dt-bindings/power/mt7623-power.h
new file mode 100644
index 0000000000..0e73bb43a5
--- /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 */
diff --git a/include/dt-bindings/power/mt7629-power.h b/include/dt-bindings/power/mt7629-power.h
new file mode 100644
index 0000000000..c7e6130503
--- /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 */
diff --git a/include/environment/ti/boot.h b/include/environment/ti/boot.h
index 3c9c87f21b..5891009a5a 100644
--- a/include/environment/ti/boot.h
+++ b/include/environment/ti/boot.h
@@ -34,9 +34,9 @@
"partitions_android=" \
"uuid_disk=${uuid_gpt_disk};" \
"name=xloader,start=128K,size=256K,uuid=${uuid_gpt_xloader};" \
- "name=bootloader,size=1792K,uuid=${uuid_gpt_bootloader};" \
+ "name=bootloader,size=2048K,uuid=${uuid_gpt_bootloader};" \
+ "name=reserved,start=2432K,size=256K,uuid=${uuid_gpt_reserved};" \
"name=misc,size=128K,uuid=${uuid_gpt_misc};" \
- "name=reserved,size=256K,uuid=${uuid_gpt_reserved};" \
"name=efs,size=16M,uuid=${uuid_gpt_efs};" \
"name=crypto,size=16K,uuid=${uuid_gpt_crypto};" \
"name=recovery,size=40M,uuid=${uuid_gpt_recovery};" \
diff --git a/include/handoff.h b/include/handoff.h
new file mode 100644
index 0000000000..aacb0f5ebf
--- /dev/null
+++ b/include/handoff.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Passing basic information from SPL to U-Boot proper
+ *
+ * Copyright 2018 Google, Inc
+ */
+
+#ifndef __HANDOFF_H
+#define __HANDOFF_H
+
+#if CONFIG_IS_ENABLED(HANDOFF)
+
+#include <asm/handoff.h>
+
+/**
+ * struct spl_handoff - information passed from SPL to U-Boot proper
+ *
+ * @ram_size: Value to use for gd->ram_size
+ */
+struct spl_handoff {
+ struct arch_spl_handoff arch;
+ u64 ram_size;
+#ifdef CONFIG_NR_DRAM_BANKS
+ struct {
+ u64 start;
+ u64 size;
+ } ram_bank[CONFIG_NR_DRAM_BANKS];
+#endif
+};
+
+void handoff_save_dram(struct spl_handoff *ho);
+void handoff_load_dram_size(struct spl_handoff *ho);
+void handoff_load_dram_banks(struct spl_handoff *ho);
+#endif
+
+#endif
diff --git a/include/image.h b/include/image.h
index 031c355b48..f67502e333 100644
--- a/include/image.h
+++ b/include/image.h
@@ -278,6 +278,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, /* MediaTek BootROM loadable Image */
IH_TYPE_COUNT, /* Number of image types */
};
diff --git a/include/log.h b/include/log.h
index deab82966b..c88a1b5eb4 100644
--- a/include/log.h
+++ b/include/log.h
@@ -48,6 +48,7 @@ enum log_category_t {
LOGC_EFI, /* EFI implementation */
LOGC_ALLOC, /* Memory allocation */
LOGC_SANDBOX, /* Related to the sandbox board */
+ LOGC_BLOBLIST, /* Bloblist */
LOGC_COUNT, /* Number of log categories */
LOGC_END, /* Sentinel value for a list of log categories */
@@ -108,6 +109,8 @@ int _log(enum log_category_t cat, enum log_level_t level, const char *file,
#define log_io(_fmt...)
#endif
+#if CONFIG_IS_ENABLED(LOG)
+
/* Emit a log record if the level is less that the maximum */
#define log(_cat, _level, _fmt, _args...) ({ \
int _l = _level; \
@@ -116,6 +119,9 @@ int _log(enum log_category_t cat, enum log_level_t level, const char *file,
__func__, \
pr_fmt(_fmt), ##_args); \
})
+#else
+#define log(_cat, _level, _fmt, _args...)
+#endif
#ifdef DEBUG
#define _DEBUG 1
@@ -175,7 +181,16 @@ void __assert_fail(const char *assertion, const char *file, unsigned int line,
({ if (!(x) && _DEBUG) \
__assert_fail(#x, __FILE__, __LINE__, __func__); })
-#ifdef CONFIG_LOG_ERROR_RETURN
+#if CONFIG_IS_ENABLED(LOG) && defined(CONFIG_LOG_ERROR_RETURN)
+/*
+ * Log an error return value, possibly with a message. Usage:
+ *
+ * return log_ret(fred_call());
+ *
+ * or:
+ *
+ * return log_msg_ret("fred failed", fred_call());
+ */
#define log_ret(_ret) ({ \
int __ret = (_ret); \
if (__ret < 0) \
@@ -190,8 +205,9 @@ void __assert_fail(const char *assertion, const char *file, unsigned int line,
__ret; \
})
#else
+/* Non-logging versions of the above which just return the error code */
#define log_ret(_ret) (_ret)
-#define log_msg_ret(_msg, _ret) (_ret)
+#define log_msg_ret(_msg, _ret) ((void)(_msg), _ret)
#endif
/**
diff --git a/include/spl.h b/include/spl.h
index 9a439f468b..ee92832f0a 100644
--- a/include/spl.h
+++ b/include/spl.h
@@ -11,6 +11,7 @@
/* Platform-specific defines */
#include <linux/compiler.h>
#include <asm/spl.h>
+#include <handoff.h>
/* Value in r0 indicates we booted from U-Boot */
#define UBOOT_NOT_LOADED_FROM_SPL 0x13578642
@@ -21,6 +22,46 @@
#define MMCSD_MODE_FS 2
#define MMCSD_MODE_EMMCBOOT 3
+/*
+ * u_boot_first_phase() - check if this is the first U-Boot phase
+ *
+ * U-Boot has up to three phases: TPL, SPL and U-Boot proper. Depending on the
+ * build flags we can determine whether the current build is for the first
+ * phase of U-Boot or not. If there is no SPL, then this is U-Boot proper. If
+ * there is SPL but no TPL, the the first phase is SPL. If there is TPL, then
+ * it is the first phase.
+ *
+ * @returns true if this is the first phase of U-Boot
+ *
+ */
+static inline bool u_boot_first_phase(void)
+{
+ if (IS_ENABLED(CONFIG_TPL)) {
+ if (IS_ENABLED(CONFIG_TPL_BUILD))
+ return true;
+ } else if (IS_ENABLED(CONFIG_SPL)) {
+ if (IS_ENABLED(CONFIG_SPL_BUILD))
+ return true;
+ } else {
+ return true;
+ }
+
+ return false;
+}
+
+/* A string name for SPL or TPL */
+#ifdef CONFIG_SPL_BUILD
+# ifdef CONFIG_TPL_BUILD
+# define SPL_TPL_NAME "tpl"
+# else
+# define SPL_TPL_NAME "spl"
+# endif
+# define SPL_TPL_PROMPT SPL_TPL_NAME ": "
+#else
+# define SPL_TPL_NAME ""
+# define SPL_TPL_PROMPT ""
+#endif
+
struct spl_image_info {
const char *name;
u8 os;
diff --git a/include/test/suites.h b/include/test/suites.h
index abb3a4b816..77d863b4a6 100644
--- a/include/test/suites.h
+++ b/include/test/suites.h
@@ -23,6 +23,7 @@ struct unit_test;
int cmd_ut_category(const char *name, struct unit_test *tests, int n_ents,
int argc, char * const argv[]);
+int do_ut_bloblist(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]);
int do_ut_compression(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]);
int do_ut_dm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
int do_ut_env(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
diff --git a/include/usb.h b/include/usb.h
index b6b48a8c60..420a30e49f 100644
--- a/include/usb.h
+++ b/include/usb.h
@@ -140,7 +140,7 @@ struct usb_device {
int act_len; /* transferred bytes */
int maxchild; /* Number of ports if hub */
int portnr; /* Port number, 1=first */
-#ifndef CONFIG_DM_USB
+#if !CONFIG_IS_ENABLED(DM_USB)
/* parent hub, or NULL if this is the root hub */
struct usb_device *parent;
struct usb_device *children[USB_MAXCHILDREN];
@@ -148,7 +148,7 @@ struct usb_device {
#endif
/* slot_id - for xHCI enabled devices */
unsigned int slot_id;
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
struct udevice *dev; /* Pointer to associated device */
struct udevice *controller_dev; /* Pointer to associated controller */
#endif
@@ -173,7 +173,7 @@ enum usb_init_type {
int usb_lowlevel_init(int index, enum usb_init_type init, void **controller);
int usb_lowlevel_stop(int index);
-#if defined(CONFIG_USB_MUSB_HOST) || defined(CONFIG_DM_USB)
+#if defined(CONFIG_USB_MUSB_HOST) || CONFIG_IS_ENABLED(DM_USB)
int usb_reset_root_port(struct usb_device *dev);
#else
#define usb_reset_root_port(dev)
@@ -187,7 +187,7 @@ int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
int transfer_len, int interval);
#if defined CONFIG_USB_EHCI_HCD || defined CONFIG_USB_MUSB_HOST \
- || defined(CONFIG_DM_USB)
+ || CONFIG_IS_ENABLED(DM_USB)
struct int_queue *create_int_queue(struct usb_device *dev, unsigned long pipe,
int queuesize, int elementsize, void *buffer, int interval);
int destroy_int_queue(struct usb_device *dev, struct int_queue *queue);
@@ -588,7 +588,7 @@ struct usb_hub_device {
struct usb_tt tt; /* Transaction Translator */
};
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
/**
* struct usb_platdata - Platform data about a USB controller
*
@@ -912,7 +912,7 @@ int usb_setup_ehci_gadget(struct ehci_ctrl **ctlrp);
*/
void usb_stor_reset(void);
-#else /* !CONFIG_DM_USB */
+#else /* !CONFIG_IS_ENABLED(DM_USB) */
struct usb_device *usb_get_dev_index(int index);
diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl
index 7416abec62..22bd8f7c27 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 mtk_image \
+ -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/scripts/config_whitelist.txt b/scripts/config_whitelist.txt
index abfb0ff89f..69bef5e6da 100644
--- a/scripts/config_whitelist.txt
+++ b/scripts/config_whitelist.txt
@@ -961,7 +961,6 @@ CONFIG_IMX_OTP
CONFIG_IMX_VIDEO_SKIP
CONFIG_INETSPACE_V2
CONFIG_INITRD_TAG
-CONFIG_INIT_CRITICAL
CONFIG_INIT_IGNORE_ERROR
CONFIG_INI_ALLOW_MULTILINE
CONFIG_INI_CASE_INSENSITIVE
@@ -1200,7 +1199,6 @@ CONFIG_MALLOC_F_ADDR
CONFIG_MALTA
CONFIG_MARCO_MEMSET
CONFIG_MARUBUN_PCCARD
-CONFIG_MARVELL
CONFIG_MARVELL_GPIO
CONFIG_MARVELL_MFP
CONFIG_MASK_AER_AO
diff --git a/test/Makefile b/test/Makefile
index 1e434730b6..2fe41f489c 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -2,6 +2,7 @@
#
# (C) Copyright 2012 The Chromium Authors
+obj-$(CONFIG_SANDBOX) += bloblist.o
obj-$(CONFIG_UNIT_TEST) += cmd_ut.o
obj-$(CONFIG_UNIT_TEST) += ut.o
obj-$(CONFIG_SANDBOX) += command_ut.o
diff --git a/test/bloblist.c b/test/bloblist.c
new file mode 100644
index 0000000000..89bdb012e3
--- /dev/null
+++ b/test/bloblist.c
@@ -0,0 +1,187 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2018, Google Inc. All rights reserved.
+ */
+
+#include <common.h>
+#include <bloblist.h>
+#include <log.h>
+#include <mapmem.h>
+#include <test/suites.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Declare a new compression test */
+#define BLOBLIST_TEST(_name, _flags) \
+ UNIT_TEST(_name, _flags, bloblist_test)
+
+enum {
+ TEST_TAG = 1,
+ TEST_TAG2 = 2,
+ TEST_TAG_MISSING = 3,
+
+ TEST_SIZE = 10,
+ TEST_SIZE2 = 20,
+
+ TEST_ADDR = CONFIG_BLOBLIST_ADDR,
+ TEST_BLOBLIST_SIZE = 0x100,
+};
+
+static struct bloblist_hdr *clear_bloblist(void)
+{
+ struct bloblist_hdr *hdr;
+
+ /* Clear out any existing bloblist so we have a clean slate */
+ hdr = map_sysmem(CONFIG_BLOBLIST_ADDR, TEST_BLOBLIST_SIZE);
+ memset(hdr, '\0', TEST_BLOBLIST_SIZE);
+
+ return hdr;
+}
+
+static int bloblist_test_init(struct unit_test_state *uts)
+{
+ struct bloblist_hdr *hdr;
+
+ hdr = clear_bloblist();
+ ut_asserteq(-ENOENT, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
+ ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
+ hdr->version++;
+ ut_asserteq(-EPROTONOSUPPORT, bloblist_check(TEST_ADDR,
+ TEST_BLOBLIST_SIZE));
+
+ ut_asserteq(-ENOSPC, bloblist_new(TEST_ADDR, 0x10, 0));
+ ut_asserteq(-EFAULT, bloblist_new(1, TEST_BLOBLIST_SIZE, 0));
+ ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
+
+ ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
+ ut_assertok(bloblist_finish());
+ ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
+ hdr->flags++;
+ ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
+
+ return 1;
+}
+BLOBLIST_TEST(bloblist_test_init, 0);
+
+static int bloblist_test_blob(struct unit_test_state *uts)
+{
+ struct bloblist_hdr *hdr;
+ struct bloblist_rec *rec, *rec2;
+ char *data;
+
+ /* At the start there should be no records */
+ hdr = clear_bloblist();
+ ut_assertnull(bloblist_find(TEST_TAG, TEST_BLOBLIST_SIZE));
+ ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
+
+ /* Add a record and check that we can find it */
+ data = bloblist_add(TEST_TAG, TEST_SIZE);
+ rec = (void *)(hdr + 1);
+ ut_asserteq_ptr(rec + 1, data);
+ data = bloblist_find(TEST_TAG, TEST_SIZE);
+ ut_asserteq_ptr(rec + 1, data);
+
+ /* Check the 'ensure' method */
+ ut_asserteq_ptr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
+ ut_assertnull(bloblist_ensure(TEST_TAG, TEST_SIZE2));
+ rec2 = (struct bloblist_rec *)(data + ALIGN(TEST_SIZE, BLOBLIST_ALIGN));
+
+ /* Check for a non-existent record */
+ ut_asserteq_ptr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
+ ut_asserteq_ptr(rec2 + 1, bloblist_ensure(TEST_TAG2, TEST_SIZE2));
+ ut_assertnull(bloblist_find(TEST_TAG_MISSING, 0));
+
+ return 0;
+}
+BLOBLIST_TEST(bloblist_test_blob, 0);
+
+static int bloblist_test_bad_blob(struct unit_test_state *uts)
+{
+ struct bloblist_hdr *hdr;
+ void *data;
+
+ hdr = clear_bloblist();
+ ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
+ data = hdr + 1;
+ data += sizeof(struct bloblist_rec);
+ ut_asserteq_ptr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
+ ut_asserteq_ptr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
+
+ return 0;
+}
+BLOBLIST_TEST(bloblist_test_bad_blob, 0);
+
+static int bloblist_test_checksum(struct unit_test_state *uts)
+{
+ struct bloblist_hdr *hdr;
+ char *data, *data2;
+
+ hdr = clear_bloblist();
+ ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
+ ut_assertok(bloblist_finish());
+ ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
+
+ /*
+ * Now change things amd make sure that the checksum notices. We cannot
+ * change the size or alloced fields, since that will crash the code.
+ * It has to rely on these being correct.
+ */
+ hdr->flags--;
+ ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
+ hdr->flags++;
+
+ hdr->size--;
+ ut_asserteq(-EFBIG, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
+ hdr->size++;
+
+ hdr->spare++;
+ ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
+ hdr->spare--;
+
+ hdr->chksum++;
+ ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
+ hdr->chksum--;
+
+ /* Make sure the checksum changes when we add blobs */
+ data = bloblist_add(TEST_TAG, TEST_SIZE);
+ ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
+
+ data2 = bloblist_add(TEST_TAG2, TEST_SIZE2);
+ ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
+ ut_assertok(bloblist_finish());
+
+ /* It should also change if we change the data */
+ ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
+ *data += 1;
+ ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
+ *data -= 1;
+
+ ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
+ *data2 += 1;
+ ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
+ *data2 -= 1;
+
+ /*
+ * Changing data outside the range of valid data should not affect
+ * the checksum.
+ */
+ ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
+ data[TEST_SIZE]++;
+ data2[TEST_SIZE2]++;
+ ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
+
+ return 0;
+}
+
+BLOBLIST_TEST(bloblist_test_checksum, 0);
+
+int do_ut_bloblist(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+{
+ struct unit_test *tests = ll_entry_start(struct unit_test,
+ bloblist_test);
+ const int n_ents = ll_entry_count(struct unit_test, bloblist_test);
+
+ return cmd_ut_category("bloblist", tests, n_ents, argc, argv);
+}
diff --git a/test/cmd_ut.c b/test/cmd_ut.c
index b7e01a4847..56924a5272 100644
--- a/test/cmd_ut.c
+++ b/test/cmd_ut.c
@@ -55,6 +55,8 @@ static cmd_tbl_t cmd_ut_sub[] = {
#ifdef CONFIG_SANDBOX
U_BOOT_CMD_MKENT(compression, CONFIG_SYS_MAXARGS, 1, do_ut_compression,
"", ""),
+ U_BOOT_CMD_MKENT(bloblist, CONFIG_SYS_MAXARGS, 1, do_ut_bloblist,
+ "", ""),
#endif
};
@@ -97,6 +99,7 @@ static int do_ut(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
static char ut_help_text[] =
"all - execute all enabled tests\n"
#ifdef CONFIG_SANDBOX
+ "ut bloblist - Test bloblist implementation\n"
"ut compression - Test compressors and bootm decompression\n"
#endif
#ifdef CONFIG_UT_DM
diff --git a/test/dm/sf.c b/test/dm/sf.c
index 35dce4e4c9..3788d59052 100644
--- a/test/dm/sf.c
+++ b/test/dm/sf.c
@@ -79,7 +79,7 @@ static int dm_test_spi_flash_func(struct unit_test_state *uts)
* benefit is worth the extra complexity.
*/
ut_asserteq(0, run_command_list(
- "sb save hostfs - 0 spi.bin 200000;"
+ "host save hostfs - 0 spi.bin 200000;"
"sf probe;"
"sf test 0 10000", -1, 0));
/*
diff --git a/test/dm/video.c b/test/dm/video.c
index 7def338058..5d1faac19c 100644
--- a/test/dm/video.c
+++ b/test/dm/video.c
@@ -178,12 +178,12 @@ static int dm_test_video_ansi(struct unit_test_state *uts)
/* test set-cursor: [%d;%df */
vidconsole_put_string(con, "abc"ANSI_ESC"[2;2fab"ANSI_ESC"[4;4fcd");
- ut_asserteq(142, compress_frame_buffer(dev));
+ ut_asserteq(143, compress_frame_buffer(dev));
/* test colors (30-37 fg color, 40-47 bg color) */
vidconsole_put_string(con, ANSI_ESC"[30;41mfoo"); /* black on red */
vidconsole_put_string(con, ANSI_ESC"[33;44mbar"); /* yellow on blue */
- ut_asserteq(265, compress_frame_buffer(dev));
+ ut_asserteq(272, compress_frame_buffer(dev));
return 0;
}
diff --git a/test/fs/fs-test.sh b/test/fs/fs-test.sh
index 86308cfe2d..721af71d44 100755
--- a/test/fs/fs-test.sh
+++ b/test/fs/fs-test.sh
@@ -194,7 +194,7 @@ function test_image() {
;;
sb)
- PREFIX="sb "
+ PREFIX="host "
WRITE="save"
SUFFIX="fs -"
;;
@@ -217,11 +217,11 @@ function test_image() {
# In u-boot commands, <interface> stands for host or hostfs
# hostfs maps to the host fs.
- # host maps to the "sb bind" that we do
+ # host maps to the "host bind" that we do
$UBOOT << EOF
sb=$5
-setenv bind 'if test "\$sb" != sb; then sb bind 0 "$1"; fi'
+setenv bind 'if test "\$sb" != sb; then host bind 0 "$1"; fi'
run bind
# Test Case 1 - ls
${PREFIX}ls host${SUFFIX} $6
@@ -229,7 +229,7 @@ ${PREFIX}ls host${SUFFIX} $6
${PREFIX}ls host${SUFFIX} invalid_d
#
# We want ${PREFIX}size host 0:0 $3 for host commands and
-# sb size hostfs - $3 for hostfs commands.
+# host size hostfs - $3 for hostfs commands.
# 1MB is 0x0010 0000
# Test Case 2a - size of small file
${PREFIX}size host${SUFFIX} ${FPATH}$FILE_SMALL
@@ -575,7 +575,7 @@ TOTAL_PASS=0
# In each loop, for a given file system image, we test both the
# fs command, like load/size/write, the file system specific command
-# like: ext4load/ext4size/ext4write and the sb load/ls/save commands.
+# like: ext4load/ext4size/ext4write and the host load/ls/save commands.
for fs in ext4 fat16 fat32; do
echo "Creating $fs image if not already present."
@@ -583,11 +583,11 @@ for fs in ext4 fat16 fat32; do
MD5_FILE_FS="${MD5_FILE}.${fs}"
create_image $IMAGE $fs
- # sb commands test
+ # host commands test
echo "Creating files in $fs image if not already present."
create_files $IMAGE $MD5_FILE_FS
- # Lets mount the image and test sb hostfs commands
+ # Lets mount the image and test host hostfs commands
mkdir -p "$MOUNT_DIR"
case "$fs" in
fat*)
diff --git a/test/py/tests/test_fit.py b/test/py/tests/test_fit.py
index 34696e9767..49d6fea571 100755
--- a/test/py/tests/test_fit.py
+++ b/test/py/tests/test_fit.py
@@ -99,15 +99,15 @@ base_fdt = '''
# then run the 'bootm' command, then save out memory from the places where
# we expect 'bootm' to write things. Then quit.
base_script = '''
-sb load hostfs 0 %(fit_addr)x %(fit)s
+host load hostfs 0 %(fit_addr)x %(fit)s
fdt addr %(fit_addr)x
bootm start %(fit_addr)x
bootm loados
-sb save hostfs 0 %(kernel_addr)x %(kernel_out)s %(kernel_size)x
-sb save hostfs 0 %(fdt_addr)x %(fdt_out)s %(fdt_size)x
-sb save hostfs 0 %(ramdisk_addr)x %(ramdisk_out)s %(ramdisk_size)x
-sb save hostfs 0 %(loadables1_addr)x %(loadables1_out)s %(loadables1_size)x
-sb save hostfs 0 %(loadables2_addr)x %(loadables2_out)s %(loadables2_size)x
+host save hostfs 0 %(kernel_addr)x %(kernel_out)s %(kernel_size)x
+host save hostfs 0 %(fdt_addr)x %(fdt_out)s %(fdt_size)x
+host save hostfs 0 %(ramdisk_addr)x %(ramdisk_out)s %(ramdisk_size)x
+host save hostfs 0 %(loadables1_addr)x %(loadables1_out)s %(loadables1_size)x
+host save hostfs 0 %(loadables2_addr)x %(loadables2_out)s %(loadables2_size)x
'''
@pytest.mark.boardspec('sandbox')
diff --git a/test/py/tests/test_handoff.py b/test/py/tests/test_handoff.py
new file mode 100644
index 0000000000..0ee972298c
--- /dev/null
+++ b/test/py/tests/test_handoff.py
@@ -0,0 +1,15 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2016 Google, Inc
+
+import pytest
+
+# Magic number to check that SPL handoff is working
+TEST_HANDOFF_MAGIC = 0x14f93c7b
+
+@pytest.mark.boardspec('sandbox')
+@pytest.mark.buildconfigspec('spl')
+def test_handoff(u_boot_console):
+ """Test that of-platdata can be generated and used in sandbox"""
+ cons = u_boot_console
+ response = cons.run_command('sb handoff')
+ assert ('SPL handoff magic %x' % TEST_HANDOFF_MAGIC) in response
diff --git a/test/py/tests/test_ofplatdata.py b/test/py/tests/test_ofplatdata.py
index dd8a09f032..98103ee71a 100644
--- a/test/py/tests/test_ofplatdata.py
+++ b/test/py/tests/test_ofplatdata.py
@@ -3,11 +3,40 @@
import pytest
-OF_PLATDATA_OUTPUT = ''
+OF_PLATDATA_OUTPUT = '''
+of-platdata probe:
+bool 1
+byte 05
+bytearray 06 00 00
+int 1
+intarray 2 3 4 0
+longbytearray 09 0a 0b 0c 0d 0e 0f 10 11
+string message
+stringarray "multi-word" "message" ""
+of-platdata probe:
+bool 0
+byte 08
+bytearray 01 23 34
+int 3
+intarray 5 0 0 0
+longbytearray 09 00 00 00 00 00 00 00 00
+string message2
+stringarray "another" "multi-word" "message"
+of-platdata probe:
+bool 0
+byte 00
+bytearray 00 00 00
+int 0
+intarray 0 0 0 0
+longbytearray 00 00 00 00 00 00 00 00 00
+string <NULL>
+stringarray "one" "" ""
+'''
@pytest.mark.buildconfigspec('spl_of_platdata')
def test_ofplatdata(u_boot_console):
"""Test that of-platdata can be generated and used in sandbox"""
cons = u_boot_console
+ cons.restart_uboot_with_flags(['--show_of_platdata'])
output = cons.get_spawn_output().replace('\r', '')
assert OF_PLATDATA_OUTPUT in output
diff --git a/test/py/tests/test_vboot.py b/test/py/tests/test_vboot.py
index e9cbd57fba..92144d4c1e 100644
--- a/test/py/tests/test_vboot.py
+++ b/test/py/tests/test_vboot.py
@@ -74,7 +74,7 @@ def test_vboot(u_boot_console):
cons.restart_uboot()
with cons.log.section('Verified boot %s %s' % (sha_algo, test_type)):
output = cons.run_command_list(
- ['sb load hostfs - 100 %stest.fit' % tmpdir,
+ ['host load hostfs - 100 %stest.fit' % tmpdir,
'fdt addr 100',
'bootm 100'])
assert(expect_string in ''.join(output))
diff --git a/test/py/u_boot_console_base.py b/test/py/u_boot_console_base.py
index 326b2ac51f..e044eb3ea1 100644
--- a/test/py/u_boot_console_base.py
+++ b/test/py/u_boot_console_base.py
@@ -16,7 +16,7 @@ import sys
import u_boot_spawn
# Regexes for text we expect U-Boot to send to the console.
-pattern_u_boot_spl_signon = re.compile('(U-Boot SPL \\d{4}\\.\\d{2}[^\r\n]*\\))')
+pattern_u_boot_spl_signon = re.compile('(U-Boot spl \\d{4}\\.\\d{2}[^\r\n]*\\))')
pattern_u_boot_main_signon = re.compile('(U-Boot \\d{4}\\.\\d{2}[^\r\n]*\\))')
pattern_stop_autoboot_prompt = re.compile('Hit any key to stop autoboot: ')
pattern_unknown_command = re.compile('Unknown command \'.*\' - try \'help\'')
diff --git a/test/py/u_boot_console_sandbox.py b/test/py/u_boot_console_sandbox.py
index 778f6d0983..836f5a9e2b 100644
--- a/test/py/u_boot_console_sandbox.py
+++ b/test/py/u_boot_console_sandbox.py
@@ -24,6 +24,7 @@ class ConsoleSandbox(ConsoleBase):
"""
super(ConsoleSandbox, self).__init__(log, config, max_fifo_fill=1024)
+ self.sandbox_flags = []
def get_spawn(self):
"""Connect to a fresh U-Boot instance.
@@ -51,8 +52,25 @@ class ConsoleSandbox(ConsoleBase):
'-d',
self.config.dtb
]
+ cmd += self.sandbox_flags
return Spawn(cmd, cwd=self.config.source_dir)
+ def restart_uboot_with_flags(self, flags):
+ """Run U-Boot with the given command-line flags
+
+ Args:
+ flags: List of flags to pass, each a string
+
+ Returns:
+ A u_boot_spawn.Spawn object that is attached to U-Boot.
+ """
+
+ try:
+ self.sandbox_flags = flags
+ return self.restart_uboot()
+ finally:
+ self.sandbox_flags = []
+
def kill(self, sig):
"""Send a specific Unix signal to the sandbox process.
diff --git a/test/run b/test/run
index fb8ff5da0c..cd323b0a85 100755
--- a/test/run
+++ b/test/run
@@ -19,7 +19,7 @@ run_test "sandbox" ./test/py/test.py --bd sandbox --build
# Run tests which require sandbox_spl
run_test "sandbox_spl" ./test/py/test.py --bd sandbox_spl --build \
- -k test_ofplatdata.py
+ -k 'test_ofplatdata or test_handoff'
# Run tests for the flat-device-tree version of sandbox. This is a special
# build which does not enable CONFIG_OF_LIVE for the live device tree, so we can
diff --git a/tools/.gitignore b/tools/.gitignore
index c8cdaef90c..e5ede22842 100644
--- a/tools/.gitignore
+++ b/tools/.gitignore
@@ -24,6 +24,7 @@
/mksunxiboot
/mxsboot
/ncb
+/prelink-riscv
/proftool
/relocate-rela
/sunxi-spl-image-builder
diff --git a/tools/Makefile b/tools/Makefile
index 3c0521f655..c93d17a42f 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -116,6 +116,7 @@ dumpimage-mkimage-objs := aisimage.o \
$(LIBFDT_OBJS) \
gpimage.o \
gpimage-common.o \
+ mtk_image.o \
$(RSA_OBJS-y)
dumpimage-objs := $(dumpimage-mkimage-objs) dumpimage.o
diff --git a/tools/file2include.c b/tools/file2include.c
index b98af30a72..775440cba9 100644
--- a/tools/file2include.c
+++ b/tools/file2include.c
@@ -18,7 +18,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
-#include <malloc.h>
/* Size of the blocks written to the compressed file */
#define BLOCK_SIZE 8
diff --git a/tools/mtk_image.c b/tools/mtk_image.c
new file mode 100644
index 0000000000..2706d2de32
--- /dev/null
+++ b/tools/mtk_image.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 "mtk_image.h"
+
+/* NAND header for SPI-NAND with 2KB page + 64B spare */
+static const union nand_boot_header snand_hdr_2k_64_data = {
+ .data = {
+ 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
+ 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
+ 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x03, 0x00, 0x40, 0x00,
+ 0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7B, 0xC4, 0x17, 0x9D,
+ 0xCA, 0x42, 0x90, 0xD0, 0x98, 0xD0, 0xE0, 0xF7,
+ 0xDB, 0xCD, 0x16, 0xF6, 0x03, 0x73, 0xD2, 0xB8,
+ 0x93, 0xB2, 0x56, 0x5A, 0x84, 0x6E, 0x00, 0x00
+ }
+};
+
+/* NAND header for SPI-NAND with 2KB page + 120B/128B spare */
+static const union nand_boot_header snand_hdr_2k_128_data = {
+ .data = {
+ 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
+ 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
+ 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
+ 0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x90, 0x28, 0xED, 0x13,
+ 0x7F, 0x12, 0x22, 0xCD, 0x3D, 0x06, 0xF1, 0xB3,
+ 0x6F, 0x2E, 0xD9, 0xA0, 0x9D, 0x7A, 0xBD, 0xD7,
+ 0xB3, 0x28, 0x3C, 0x13, 0xDB, 0x4E, 0x00, 0x00
+ }
+};
+
+/* NAND header for SPI-NAND with 4KB page + 256B spare */
+static const union nand_boot_header snand_hdr_4k_256_data = {
+ .data = {
+ 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
+ 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
+ 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x05, 0x00, 0xE0, 0x00,
+ 0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x47, 0xED, 0x0E, 0xC3,
+ 0x83, 0xBF, 0x41, 0xD2, 0x85, 0x21, 0x97, 0x57,
+ 0xC4, 0x2E, 0x6B, 0x7A, 0x40, 0xE0, 0xCF, 0x8F,
+ 0x37, 0xBD, 0x17, 0xB6, 0xC7, 0xFE, 0x00, 0x00
+ }
+};
+
+/* NAND header for Parallel NAND 1Gb with 2KB page + 64B spare */
+static const union nand_boot_header nand_hdr_1gb_2k_64_data = {
+ .data = {
+ 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
+ 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
+ 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
+ 0x40, 0x00, 0x00, 0x04, 0x0B, 0x00, 0x11, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x12, 0x28, 0x1C, 0x12,
+ 0x8F, 0xFD, 0xF8, 0x32, 0x6F, 0x6D, 0xCF, 0x6C,
+ 0xDA, 0x21, 0x70, 0x8C, 0xDA, 0x0A, 0x22, 0x82,
+ 0xAA, 0x59, 0xFA, 0x7C, 0x42, 0x2D, 0x00, 0x00
+ }
+};
+
+/* NAND header for Parallel NAND 2Gb with 2KB page + 64B spare */
+static const union nand_boot_header nand_hdr_2gb_2k_64_data = {
+ .data = {
+ 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
+ 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
+ 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
+ 0x40, 0x00, 0x00, 0x08, 0x0B, 0x00, 0x11, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x20, 0x9C, 0x3D, 0x2D,
+ 0x7B, 0x68, 0x63, 0x52, 0x2E, 0x04, 0x63, 0xF1,
+ 0x35, 0x4E, 0x44, 0x3E, 0xF8, 0xAC, 0x9B, 0x95,
+ 0xAB, 0xFE, 0xE4, 0xE1, 0xD5, 0xF9, 0x00, 0x00
+ }
+};
+
+/* NAND header for Parallel NAND 4Gb with 2KB page + 64B spare */
+static const union nand_boot_header nand_hdr_4gb_2k_64_data = {
+ .data = {
+ 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
+ 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
+ 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x0B, 0x00, 0x11, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xE3, 0x0F, 0x86, 0x32,
+ 0x68, 0x05, 0xD9, 0xC8, 0x13, 0xDF, 0xC5, 0x0B,
+ 0x35, 0x3A, 0x68, 0xA5, 0x3C, 0x0C, 0x73, 0x87,
+ 0x63, 0xB0, 0xBE, 0xCC, 0x84, 0x47, 0x00, 0x00
+ }
+};
+
+/* NAND header for Parallel NAND 2Gb with 2KB page + 128B spare */
+static const union nand_boot_header nand_hdr_2gb_2k_128_data = {
+ .data = {
+ 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
+ 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
+ 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
+ 0x40, 0x00, 0x00, 0x08, 0x0B, 0x00, 0x11, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0xA5, 0xE9, 0x5A,
+ 0xDF, 0x58, 0x62, 0x41, 0xD6, 0x26, 0x77, 0xBC,
+ 0x76, 0x1F, 0x27, 0x4E, 0x4F, 0x6C, 0xC3, 0xF0,
+ 0x36, 0xDE, 0xD9, 0xB3, 0xFF, 0x93, 0x00, 0x00
+ }
+};
+
+/* NAND header for Parallel NAND 4Gb with 2KB page + 128B spare */
+static const union nand_boot_header nand_hdr_4gb_2k_128_data = {
+ .data = {
+ 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
+ 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
+ 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x0B, 0x00, 0x11, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xC2, 0x36, 0x52, 0x45,
+ 0xCC, 0x35, 0xD8, 0xDB, 0xEB, 0xFD, 0xD1, 0x46,
+ 0x76, 0x6B, 0x0B, 0xD5, 0x8B, 0xCC, 0x2B, 0xE2,
+ 0xFE, 0x90, 0x83, 0x9E, 0xAE, 0x2D, 0x00, 0x00
+ }
+};
+
+static const struct nand_header_type {
+ const char *name;
+ const union nand_boot_header *data;
+} nand_headers[] = {
+ {
+ .name = "2k+64",
+ .data = &snand_hdr_2k_64_data
+ }, {
+ .name = "2k+120",
+ .data = &snand_hdr_2k_128_data
+ }, {
+ .name = "2k+128",
+ .data = &snand_hdr_2k_128_data
+ }, {
+ .name = "4k+256",
+ .data = &snand_hdr_4k_256_data
+ }, {
+ .name = "1g:2k+64",
+ .data = &nand_hdr_1gb_2k_64_data
+ }, {
+ .name = "2g:2k+64",
+ .data = &nand_hdr_2gb_2k_64_data
+ }, {
+ .name = "4g:2k+64",
+ .data = &nand_hdr_4gb_2k_64_data
+ }, {
+ .name = "2g:2k+128",
+ .data = &nand_hdr_2gb_2k_128_data
+ }, {
+ .name = "4g:2k+128",
+ .data = &nand_hdr_4gb_2k_128_data
+ }
+};
+
+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(
+ mtk_image,
+ "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/mtk_image.h b/tools/mtk_image.h
new file mode 100644
index 0000000000..0a9eab372b
--- /dev/null
+++ b/tools/mtk_image.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 */