Merge tag 'u-boot-atmel-2021.04-b' of https://gitlab.denx.de/u-boot/custodians/u...
authorTom Rini <trini@konsulko.com>
Mon, 25 Jan 2021 14:01:28 +0000 (09:01 -0500)
committerTom Rini <trini@konsulko.com>
Mon, 25 Jan 2021 14:01:28 +0000 (09:01 -0500)
Second set of u-boot-atmel features for 2021.04 cycle

This feature set includes macb updates for all interfaces and new
sama7g5 variant support; micrel ksz9031 DLL support; a new board from
Giant based on Adafruit feather form factor which contains a SAMA5D27
SoC; several fixes regarding the NAND flash PMECC block; and pincontrol
drive strength support for pio4 controller.

172 files changed:
MAINTAINERS
README
arch/arm/dts/Makefile
arch/arm/dts/ast2600-evb.dts [new file with mode: 0644]
arch/arm/dts/ast2600-u-boot.dtsi [new file with mode: 0644]
arch/arm/dts/ast2600.dtsi [new file with mode: 0644]
arch/arm/dts/ca-presidio-engboard.dts
arch/arm/dts/mt7622.dtsi
arch/arm/dts/mt8516-pumpkin.dts
arch/arm/dts/mt8516.dtsi
arch/arm/dts/rk3328-nanopi-r2s-u-boot.dtsi [new file with mode: 0644]
arch/arm/dts/rk3328-nanopi-r2s.dts [new file with mode: 0644]
arch/arm/dts/rk3399-evb-u-boot.dtsi
arch/arm/dts/rk3399-firefly-u-boot.dtsi
arch/arm/dts/rk3399-leez-p710-u-boot.dtsi
arch/arm/dts/rk3399-pinebook-pro-u-boot.dtsi
arch/arm/dts/rk3399-puma-haikou-u-boot.dtsi
arch/arm/dts/rk3399-roc-pc-u-boot.dtsi
arch/arm/dts/rk3399-rockpro64-u-boot.dtsi
arch/arm/dts/rk3399-u-boot.dtsi
arch/arm/include/asm/acpi_table.h [new file with mode: 0644]
arch/arm/include/asm/arch-aspeed/boot0.h [new file with mode: 0644]
arch/arm/include/asm/arch-aspeed/platform.h
arch/arm/include/asm/arch-aspeed/scu_ast2600.h [new file with mode: 0644]
arch/arm/include/asm/arch-aspeed/sdram_ast2600.h [new file with mode: 0644]
arch/arm/include/asm/arch-aspeed/wdt_ast2600.h [new file with mode: 0644]
arch/arm/include/asm/gpio.h
arch/arm/mach-aspeed/Kconfig
arch/arm/mach-aspeed/Makefile
arch/arm/mach-aspeed/ast2600/Kconfig [new file with mode: 0644]
arch/arm/mach-aspeed/ast2600/Makefile [new file with mode: 0644]
arch/arm/mach-aspeed/ast2600/board_common.c [new file with mode: 0644]
arch/arm/mach-aspeed/ast2600/lowlevel_init.S [new file with mode: 0644]
arch/arm/mach-aspeed/ast2600/spl.c [new file with mode: 0644]
arch/arm/mach-exynos/include/mach/dwmmc.h
board/aspeed/evb_ast2600/Kconfig [new file with mode: 0644]
board/aspeed/evb_ast2600/MAINTAINERS [new file with mode: 0644]
board/aspeed/evb_ast2600/Makefile [new file with mode: 0644]
board/aspeed/evb_ast2600/evb_ast2600.c [new file with mode: 0644]
board/keymile/km_arm/Kconfig
board/mediatek/pumpkin/pumpkin.c
board/rockchip/evb_rk3328/MAINTAINERS
board/samsung/arndale/arndale.c
board/xilinx/common/board.c
board/xilinx/zynqmp/zynqmp.c
cmd/Kconfig
cmd/Makefile
cmd/bootefi.c
cmd/efidebug.c
cmd/pwm.c [new file with mode: 0644]
common/image-fit-sig.c
common/image-fit.c
configs/cortina_presidio-asic-pnand_defconfig [new file with mode: 0644]
configs/evb-ast2600_defconfig [new file with mode: 0644]
configs/firefly-rk3399_defconfig
configs/km_kirkwood_128m16_defconfig
configs/km_kirkwood_defconfig
configs/km_kirkwood_pci_defconfig
configs/kmcoge5un_defconfig
configs/kmnusa_defconfig
configs/kmsuse2_defconfig
configs/nanopi-r2s-rk3328_defconfig [new file with mode: 0644]
configs/puma-rk3399_defconfig
configs/pumpkin_defconfig
configs/roc-pc-mezzanine-rk3399_defconfig
configs/roc-pc-rk3399_defconfig
configs/rock960-rk3399_defconfig
configs/rockpro64-rk3399_defconfig
configs/sandbox_defconfig
configs/xilinx_zynqmp_virt_defconfig
doc/Makefile
doc/README.menu [deleted file]
doc/board/freescale/imx8mm_evk.rst
doc/board/freescale/imx8mn_evk.rst
doc/board/freescale/imx8mp_evk.rst
doc/board/freescale/imx8mq_evk.rst
doc/develop/index.rst
doc/develop/menus.rst [new file with mode: 0644]
doc/develop/py_testing.rst [moved from test/py/README.md with 74% similarity]
doc/develop/testing.rst [moved from test/README with 100% similarity]
doc/uImage.FIT/source_file_format.txt
drivers/clk/aspeed/Makefile
drivers/clk/aspeed/clk_ast2600.c [new file with mode: 0644]
drivers/clk/mediatek/Makefile
drivers/clk/mediatek/clk-mt8183.c [new file with mode: 0644]
drivers/dma/bcm6348-iudma.c
drivers/mmc/exynos_dw_mmc.c
drivers/mmc/fsl_esdhc_spl.c
drivers/mmc/pci_mmc.c
drivers/mmc/xenon_sdhci.c
drivers/mtd/Makefile
drivers/mtd/mw_eeprom.c [deleted file]
drivers/mtd/nand/raw/Kconfig
drivers/mtd/nand/raw/Makefile
drivers/mtd/nand/raw/cortina_nand.c [new file with mode: 0644]
drivers/mtd/nand/raw/cortina_nand.h [new file with mode: 0644]
drivers/net/dwc_eth_qos.c
drivers/net/e1000.c
drivers/net/ftgmac100.c
drivers/net/ks8851_mll.c
drivers/pci/Kconfig
drivers/pci/Makefile
drivers/pci/pcie_dw_rockchip.c [new file with mode: 0644]
drivers/phy/rockchip/Kconfig
drivers/phy/rockchip/Makefile
drivers/phy/rockchip/phy-rockchip-snps-pcie3.c [new file with mode: 0644]
drivers/pinctrl/mediatek/pinctrl-mtk-common.c
drivers/power/pmic/Kconfig
drivers/power/pmic/Makefile
drivers/power/pmic/mp5416.c [new file with mode: 0644]
drivers/qe/qe.c
drivers/ram/aspeed/Kconfig
drivers/ram/aspeed/Makefile
drivers/ram/aspeed/sdram_ast2600.c [new file with mode: 0644]
drivers/reset/Kconfig
drivers/reset/Makefile
drivers/reset/reset-ast2600.c [new file with mode: 0644]
drivers/sysreset/sysreset_ast.c
drivers/timer/mtk_timer.c
drivers/watchdog/Kconfig
drivers/watchdog/Makefile
drivers/watchdog/ast2600_wdt.c [new file with mode: 0644]
env/Kconfig
fs/btrfs/disk-io.c
fs/btrfs/volumes.c
fs/fat/fat.c
fs/fat/fat_write.c
fs/squashfs/sqfs.c
fs/ubifs/io.c
include/config_distro_bootcmd.h
include/configs/evb_ast2600.h [new file with mode: 0644]
include/configs/presidio_asic.h
include/configs/stm32mp1.h
include/dt-bindings/clock/ast2600-clock.h [new file with mode: 0644]
include/dt-bindings/clock/mt8183-clk.h [new file with mode: 0644]
include/dt-bindings/reset/ast2600-reset.h [new file with mode: 0644]
include/efi_api.h
include/efi_loader.h
include/efi_variable.h
include/fat.h
include/power/mp5416.h [new file with mode: 0644]
lib/efi_loader/Kconfig
lib/efi_loader/Makefile
lib/efi_loader/efi_bootmgr.c
lib/efi_loader/efi_boottime.c
lib/efi_loader/efi_capsule.c
lib/efi_loader/efi_disk.c
lib/efi_loader/efi_dt_fixup.c
lib/efi_loader/efi_load_options.c [new file with mode: 0644]
lib/efi_loader/efi_root_node.c
lib/efi_loader/efi_unicode_collation.c
lib/efi_loader/efi_var_mem.c
lib/efi_loader/efi_variable_tee.c
lib/efi_selftest/Makefile
lib/efi_selftest/dtbdump.c
lib/efi_selftest/efi_selftest_console.c
lib/efi_selftest/initrddump.c [new file with mode: 0644]
lib/uuid.c
net/eth-uclass.c
net/eth_legacy.c
net/net_rand.h
net/ping.c
net/tftp.c
test/cmd/Makefile
test/cmd/pwm.c [new file with mode: 0644]
tools/Makefile
tools/env/fw_env.c
tools/image-host.c
tools/mkeficapsule.c
tools/mkimage.c
tools/mtk_image.c
tools/mtk_image.h

index 26dd254..a7a62df 100644 (file)
@@ -198,6 +198,9 @@ F:  drivers/mmc/ca_dw_mmc.c
 F:     drivers/spi/ca_sflash.c
 F:     drivers/i2c/i2c-cortina.c
 F:     drivers/i2c/i2c-cortina.h
+F:     drivers/mtd/nand/raw/cortina_nand.c
+F:     drivers/mtd/nand/raw/cortina_nand.h
+F:     configs/cortina_presidio-asic-pnand_defconfig
 
 ARM/CZ.NIC TURRIS MOX SUPPORT
 M:     Marek Behun <marek.behun@nic.cz>
diff --git a/README b/README
index 5ca11f2..89606c8 100644 (file)
--- a/README
+++ b/README
@@ -3153,6 +3153,7 @@ i2c       - I2C sub-system
 sspi   - SPI utility commands
 base   - print or set address offset
 printenv- print environment variables
+pwm    - control pwm channels
 setenv - set environment variables
 saveenv - save environment variables to persistent storage
 protect - enable or disable FLASH write protection
index 1d4eddd..0217c62 100644 (file)
@@ -110,6 +110,7 @@ dtb-$(CONFIG_ROCKCHIP_RK3308) += \
 
 dtb-$(CONFIG_ROCKCHIP_RK3328) += \
        rk3328-evb.dtb \
+       rk3328-nanopi-r2s.dtb \
        rk3328-roc-cc.dtb \
        rk3328-rock64.dtb \
        rk3328-rock-pi-e.dtb
@@ -961,6 +962,7 @@ dtb-$(CONFIG_ARCH_BCM6858) += \
 dtb-$(CONFIG_TARGET_BCMNS3) += ns3-board.dtb
 
 dtb-$(CONFIG_ASPEED_AST2500) += ast2500-evb.dtb
+dtb-$(CONFIG_ASPEED_AST2600) += ast2600-evb.dtb
 
 dtb-$(CONFIG_ARCH_STI) += stih410-b2260.dtb
 
diff --git a/arch/arm/dts/ast2600-evb.dts b/arch/arm/dts/ast2600-evb.dts
new file mode 100644 (file)
index 0000000..2abd313
--- /dev/null
@@ -0,0 +1,179 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+#include "ast2600-u-boot.dtsi"
+
+/ {
+       memory {
+               device_type = "memory";
+               reg = <0x80000000 0x40000000>;
+       };
+
+       chosen {
+               stdout-path = &uart5;
+       };
+
+       aliases {
+               mmc0 = &emmc_slot0;
+               mmc1 = &sdhci_slot0;
+               mmc2 = &sdhci_slot1;
+               spi0 = &fmc;
+               spi1 = &spi1;
+               spi2 = &spi2;
+               ethernet0 = &mac0;
+               ethernet1 = &mac1;
+               ethernet2 = &mac2;
+               ethernet3 = &mac3;
+       };
+
+       cpus {
+               cpu@0 {
+                       clock-frequency = <800000000>;
+               };
+               cpu@1 {
+                       clock-frequency = <800000000>;
+               };
+       };
+};
+
+&uart5 {
+       u-boot,dm-pre-reloc;
+       status = "okay";
+};
+
+&sdrammc {
+       clock-frequency = <400000000>;
+};
+
+&wdt1 {
+       status = "okay";
+};
+
+&fmc {
+       status = "okay";
+
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_fmcquad_default>;
+
+       flash@0 {
+               compatible = "spi-flash", "sst,w25q256";
+               status = "okay";
+               spi-max-frequency = <50000000>;
+               spi-tx-bus-width = <4>;
+               spi-rx-bus-width = <4>;
+       };
+
+       flash@1 {
+               compatible = "spi-flash", "sst,w25q256";
+               status = "okay";
+               spi-max-frequency = <50000000>;
+               spi-tx-bus-width = <4>;
+               spi-rx-bus-width = <4>;
+       };
+
+       flash@2 {
+               compatible = "spi-flash", "sst,w25q256";
+               status = "okay";
+               spi-max-frequency = <50000000>;
+               spi-tx-bus-width = <4>;
+               spi-rx-bus-width = <4>;
+       };
+};
+
+&spi1 {
+       status = "okay";
+
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_spi1_default &pinctrl_spi1abr_default
+                       &pinctrl_spi1cs1_default &pinctrl_spi1wp_default
+                       &pinctrl_spi1wp_default &pinctrl_spi1quad_default>;
+
+       flash@0 {
+               compatible = "spi-flash", "sst,w25q256";
+               status = "okay";
+               spi-max-frequency = <50000000>;
+               spi-tx-bus-width = <4>;
+               spi-rx-bus-width = <4>;
+       };
+};
+
+&spi2 {
+       status = "okay";
+
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_spi2_default &pinctrl_spi2cs1_default
+                       &pinctrl_spi2cs2_default &pinctrl_spi2quad_default>;
+
+       flash@0 {
+               compatible = "spi-flash", "sst,w25q256";
+               status = "okay";
+               spi-max-frequency = <50000000>;
+               spi-tx-bus-width = <4>;
+               spi-rx-bus-width = <4>;
+       };
+};
+
+&emmc {
+       u-boot,dm-pre-reloc;
+       timing-phase = <0x700ff>;
+};
+
+&emmc_slot0 {
+       u-boot,dm-pre-reloc;
+       status = "okay";
+       bus-width = <4>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_emmc_default>;
+       sdhci-drive-type = <1>;
+};
+
+&i2c4 {
+       status = "okay";
+
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c5_default>;
+};
+
+&i2c5 {
+       status = "okay";
+
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c6_default>;
+};
+
+&i2c6 {
+       status = "okay";
+
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c7_default>;
+};
+
+&i2c7 {
+       status = "okay";
+
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c8_default>;
+};
+
+&i2c8 {
+       status = "okay";
+
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c9_default>;
+};
+
+&scu {
+       mac0-clk-delay = <0x1d 0x1c
+                         0x10 0x17
+                         0x10 0x17>;
+       mac1-clk-delay = <0x1d 0x10
+                         0x10 0x10
+                         0x10 0x10>;
+       mac2-clk-delay = <0x0a 0x04
+                         0x08 0x04
+                         0x08 0x04>;
+       mac3-clk-delay = <0x0a 0x04
+                         0x08 0x04
+                         0x08 0x04>;
+};
diff --git a/arch/arm/dts/ast2600-u-boot.dtsi b/arch/arm/dts/ast2600-u-boot.dtsi
new file mode 100644 (file)
index 0000000..4648c07
--- /dev/null
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0+
+#include <dt-bindings/clock/ast2600-clock.h>
+#include <dt-bindings/reset/ast2600-reset.h>
+
+#include "ast2600.dtsi"
+
+/ {
+       scu: clock-controller@1e6e2000 {
+               compatible = "aspeed,ast2600-scu";
+               reg = <0x1e6e2000 0x1000>;
+               u-boot,dm-pre-reloc;
+               #clock-cells = <1>;
+               #reset-cells = <1>;
+               uart-clk-source = <0x0>; /* uart clock source selection: 0: uxclk 1: huxclk*/
+       };
+
+       rst: reset-controller {
+               u-boot,dm-pre-reloc;
+               compatible = "aspeed,ast2600-reset";
+               aspeed,wdt = <&wdt1>;
+               #reset-cells = <1>;
+       };
+
+       sdrammc: sdrammc@1e6e0000 {
+               u-boot,dm-pre-reloc;
+               compatible = "aspeed,ast2600-sdrammc";
+               reg = <0x1e6e0000 0x100
+                       0x1e6e0100 0x300
+                       0x1e6e0400 0x200 >;
+               #reset-cells = <1>;
+               clocks = <&scu ASPEED_CLK_MPLL>;
+               resets = <&rst ASPEED_RESET_SDRAM>;
+       };
+
+       ahb {
+               u-boot,dm-pre-reloc;
+
+               apb {
+                       u-boot,dm-pre-reloc;
+               };
+
+       };
+};
+
diff --git a/arch/arm/dts/ast2600.dtsi b/arch/arm/dts/ast2600.dtsi
new file mode 100644 (file)
index 0000000..ac0f08b
--- /dev/null
@@ -0,0 +1,1946 @@
+// SPDX-License-Identifier: GPL-2.0+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "skeleton.dtsi"
+
+/ {
+       model = "Aspeed BMC";
+       compatible = "aspeed,ast2600";
+       #address-cells = <1>;
+       #size-cells = <1>;
+       interrupt-parent = <&gic>;
+
+       aliases {
+               i2c0 = &i2c0;
+               i2c1 = &i2c1;
+               i2c2 = &i2c2;
+               i2c3 = &i2c3;
+               i2c4 = &i2c4;
+               i2c5 = &i2c5;
+               i2c6 = &i2c6;
+               i2c7 = &i2c7;
+               i2c8 = &i2c8;
+               i2c9 = &i2c9;
+               i2c10 = &i2c10;
+               i2c11 = &i2c11;
+               i2c12 = &i2c12;
+               i2c13 = &i2c13;
+               i2c14 = &i2c14;
+               i2c15 = &i2c15;
+               serial0 = &uart1;
+               serial1 = &uart2;
+               serial2 = &uart3;
+               serial3 = &uart4;
+               serial4 = &uart5;
+               serial5 = &uart6;
+               serial6 = &uart7;
+               serial7 = &uart8;
+               serial8 = &uart9;
+               serial9 = &uart10;
+               serial10 = &uart11;
+               serial11 = &uart12;
+               serial12 = &uart13;
+       };
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               enable-method = "aspeed,ast2600-smp";
+
+               cpu@0 {
+                       compatible = "arm,cortex-a7";
+                       device_type = "cpu";
+                       reg = <0xf00>;
+               };
+
+               cpu@1 {
+                       compatible = "arm,cortex-a7";
+                       device_type = "cpu";
+                       reg = <0xf01>;
+               };
+
+       };
+
+       timer {
+               compatible = "arm,armv7-timer";
+               interrupt-parent = <&gic>;
+               interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
+                               <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
+                               <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
+                               <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>;
+       };
+
+       reserved-memory {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               gfx_memory: framebuffer {
+                       size = <0x01000000>;
+                       alignment = <0x01000000>;
+                       compatible = "shared-dma-pool";
+                       reusable;
+               };
+
+               video_memory: video {
+                       size = <0x04000000>;
+                       alignment = <0x01000000>;
+                       compatible = "shared-dma-pool";
+                       no-map;
+               };
+       };
+
+       ahb {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               device_type = "soc";
+               ranges;
+
+               gic: interrupt-controller@40461000 {
+                               compatible = "arm,cortex-a7-gic";
+                               interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
+                               #interrupt-cells = <3>;
+                               interrupt-controller;
+                               interrupt-parent = <&gic>;
+                               reg = <0x40461000 0x1000>,
+                                         <0x40462000 0x1000>,
+                                         <0x40464000 0x2000>,
+                                         <0x40466000 0x2000>;
+               };
+
+               ahbc: ahbc@1e600000 {
+                       compatible = "aspeed,aspeed-ahbc";
+                       reg = < 0x1e600000 0x100>;
+               };
+
+               fmc: flash-controller@1e620000 {
+                       reg = < 0x1e620000 0xc4
+                               0x20000000 0x10000000 >;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "aspeed,ast2600-fmc";
+                       status = "disabled";
+                       interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&scu ASPEED_CLK_AHB>;
+                       num-cs = <3>;
+                       flash@0 {
+                               reg = < 0 >;
+                               compatible = "jedec,spi-nor";
+                               status = "disabled";
+                       };
+                       flash@1 {
+                               reg = < 1 >;
+                               compatible = "jedec,spi-nor";
+                               status = "disabled";
+                       };
+                       flash@2 {
+                               reg = < 2 >;
+                               compatible = "jedec,spi-nor";
+                               status = "disabled";
+                       };
+               };
+
+               spi1: flash-controller@1e630000 {
+                       reg = < 0x1e630000 0xc4
+                               0x30000000 0x08000000 >;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "aspeed,ast2600-spi";
+                       clocks = <&scu ASPEED_CLK_AHB>;
+                       num-cs = <2>;
+                       status = "disabled";
+                       flash@0 {
+                               reg = < 0 >;
+                               compatible = "jedec,spi-nor";
+                               status = "disabled";
+                       };
+                       flash@1 {
+                               reg = < 1 >;
+                               compatible = "jedec,spi-nor";
+                               status = "disabled";
+                       };
+               };
+
+               spi2: flash-controller@1e631000 {
+                       reg = < 0x1e631000 0xc4
+                               0x50000000 0x08000000 >;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "aspeed,ast2600-spi";
+                       clocks = <&scu ASPEED_CLK_AHB>;
+                       num-cs = <3>;
+                       status = "disabled";
+                       flash@0 {
+                               reg = < 0 >;
+                               compatible = "jedec,spi-nor";
+                               status = "disabled";
+                       };
+                       flash@1 {
+                               reg = < 1 >;
+                               compatible = "jedec,spi-nor";
+                               status = "disabled";
+                       };
+                       flash@2 {
+                               reg = < 2 >;
+                               compatible = "jedec,spi-nor";
+                               status = "disabled";
+                       };
+               };
+
+               edac: sdram@1e6e0000 {
+                       compatible = "aspeed,ast2600-sdram-edac";
+                       reg = <0x1e6e0000 0x174>;
+                       interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
+               };
+
+               mdio: ethernet@1e650000 {
+                       compatible = "aspeed,aspeed-mdio";
+                       reg = <0x1e650000 0x40>;
+                       resets = <&rst ASPEED_RESET_MII>;
+                       status = "disabled";
+               };
+
+               mac0: ftgmac@1e660000 {
+                       compatible = "aspeed,ast2600-mac", "faraday,ftgmac100";
+                       reg = <0x1e660000 0x180>, <0x1e650000 0x4>;
+                       interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&scu ASPEED_CLK_GATE_MAC1CLK>;
+                       status = "disabled";
+               };
+
+               mac1: ftgmac@1e680000 {
+                       compatible = "aspeed,ast2600-mac", "faraday,ftgmac100";
+                       reg = <0x1e680000 0x180>, <0x1e650008 0x4>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&scu ASPEED_CLK_GATE_MAC2CLK>;
+                       status = "disabled";
+               };
+
+               mac2: ftgmac@1e670000 {
+                       compatible = "aspeed,ast2600-mac", "faraday,ftgmac100";
+                       reg = <0x1e670000 0x180>, <0x1e650010 0x4>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&scu ASPEED_CLK_GATE_MAC3CLK>;
+                       status = "disabled";
+               };
+
+               mac3: ftgmac@1e690000 {
+                       compatible = "aspeed,ast2600-mac", "faraday,ftgmac100";
+                       reg = <0x1e690000 0x180>, <0x1e650018 0x4>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&scu ASPEED_CLK_GATE_MAC4CLK>;
+                       status = "disabled";
+               };
+
+               ehci0: usb@1e6a1000 {
+                       compatible = "aspeed,aspeed-ehci", "usb-ehci";
+                       reg = <0x1e6a1000 0x100>;
+                       interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&scu ASPEED_CLK_GATE_USBPORT1CLK>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_usb2ah_default>;
+                       status = "disabled";
+               };
+
+               ehci1: usb@1e6a3000 {
+                       compatible = "aspeed,aspeed-ehci", "usb-ehci";
+                       reg = <0x1e6a3000 0x100>;
+                       interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&scu ASPEED_CLK_GATE_USBPORT2CLK>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_usb2bh_default>;
+                       status = "disabled";
+               };
+
+               apb {
+                       compatible = "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges;
+
+                       syscon: syscon@1e6e2000 {
+                               compatible = "aspeed,g6-scu", "syscon", "simple-mfd";
+                               reg = <0x1e6e2000 0x1000>;
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               #clock-cells = <1>;
+                               #reset-cells = <1>;
+                               ranges = <0 0x1e6e2000 0x1000>;
+
+                               pinctrl: pinctrl {
+                                       compatible = "aspeed,g6-pinctrl";
+                                       aspeed,external-nodes = <&gfx &lhc>;
+
+                               };
+
+                               vga_scratch: scratch {
+                                       compatible = "aspeed,bmc-misc";
+                               };
+
+                               scu_ic0: interrupt-controller@0 {
+                                       #interrupt-cells = <1>;
+                                       compatible = "aspeed,ast2600-scu-ic";
+                                       reg = <0x560 0x10>;
+                                       interrupt-parent = <&gic>;
+                                       interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+                                       interrupt-controller;
+                               };
+
+                               scu_ic1: interrupt-controller@1 {
+                                       #interrupt-cells = <1>;
+                                       compatible = "aspeed,ast2600-scu-ic";
+                                       reg = <0x570 0x10>;
+                                       interrupt-parent = <&gic>;
+                                       interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+                                       interrupt-controller;
+                               };
+
+                       };
+
+                       smp-memram@0 {
+                               compatible = "aspeed,ast2600-smpmem", "syscon";
+                               reg = <0x1e6e2180 0x40>;
+                       };
+
+                       gfx: display@1e6e6000 {
+                               compatible = "aspeed,ast2500-gfx", "syscon";
+                               reg = <0x1e6e6000 0x1000>;
+                               reg-io-width = <4>;
+                       };
+
+                       pcie_bridge0: pcie@1e6ed000 {
+                               compatible = "aspeed,ast2600-pcie";
+                               #address-cells = <3>;
+                               #size-cells = <2>;
+                               reg = <0x1e6ed000 0x100>;
+                               ranges = <0x81000000 0x0 0x0 0x0 0x0 0x10000>,
+                                        <0x82000000 0x0 0x60000000 0x60000000 0x0 0x10000000>;
+                               device_type = "pci";
+                               bus-range = <0x00 0xff>;
+                               resets = <&rst ASPEED_RESET_PCIE_DEV_O>;
+                               cfg-handle = <&pcie_cfg0>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_pcie0rc_default>;
+
+                               status = "disabled";
+                       };
+
+                       pcie_bridge1: pcie@1e6ed200 {
+                               compatible = "aspeed,ast2600-pcie";
+                               #address-cells = <3>;
+                               #size-cells = <2>;
+                               reg = <0x1e6ed200 0x100>;
+                               ranges = <0x81000000 0x0 0x0 0x10000 0x00 0x10000>,
+                                        <0x82000000 0x0 0x70000000 0x70000000 0x0 0x10000000>;
+                               device_type = "pci";
+                               bus-range = <0x00 0xff>;
+                               resets = <&rst ASPEED_RESET_PCIE_RC_O>;
+                               cfg-handle = <&pcie_cfg1>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_pcie1rc_default>;
+
+                               status = "disabled";
+                       };
+
+                       sdhci: sdhci@1e740000 {
+                               #interrupt-cells = <1>;
+                               compatible = "aspeed,aspeed-sdhci-irq", "simple-mfd";
+                               reg = <0x1e740000 0x1000>;
+                               interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-controller;
+                               clocks = <&scu ASPEED_CLK_GATE_SDCLK>,
+                                        <&scu ASPEED_CLK_GATE_SDEXTCLK>;
+                               clock-names = "ctrlclk", "extclk";
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               ranges = <0x0 0x1e740000 0x1000>;
+
+                               sdhci_slot0: sdhci_slot0@100 {
+                                       compatible = "aspeed,sdhci-ast2600";
+                                       reg = <0x100 0x100>;
+                                       interrupts = <0>;
+                                       interrupt-parent = <&sdhci>;
+                                       sdhci,auto-cmd12;
+                                       clocks = <&scu ASPEED_CLK_SDIO>;
+                                       status = "disabled";
+                               };
+
+                               sdhci_slot1: sdhci_slot1@200 {
+                                       compatible = "aspeed,sdhci-ast2600";
+                                       reg = <0x200 0x100>;
+                                       interrupts = <1>;
+                                       interrupt-parent = <&sdhci>;
+                                       sdhci,auto-cmd12;
+                                       clocks = <&scu ASPEED_CLK_SDIO>;
+                                       status = "disabled";
+                               };
+                       };
+
+                       emmc: emmc@1e750000 {
+                               #interrupt-cells = <1>;
+                               compatible = "aspeed,aspeed-emmc-irq", "simple-mfd";
+                               reg = <0x1e750000 0x1000>;
+                               interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-controller;
+                               clocks = <&scu ASPEED_CLK_GATE_EMMCCLK>,
+                                        <&scu ASPEED_CLK_GATE_EMMCEXTCLK>;
+                               clock-names = "ctrlclk", "extclk";
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               ranges = <0x0 0x1e750000 0x1000>;
+
+                               emmc_slot0: emmc_slot0@100 {
+                                       compatible = "aspeed,emmc-ast2600";
+                                       reg = <0x100 0x100>;
+                                       interrupts = <0>;
+                                       interrupt-parent = <&emmc>;
+                                       clocks = <&scu ASPEED_CLK_EMMC>;
+                                       status = "disabled";
+                               };
+                       };
+
+                       h2x: h2x@1e770000 {
+                               compatible = "aspeed,ast2600-h2x";
+                               reg = <0x1e770000 0x100>;
+                               interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+                               resets = <&rst ASPEED_RESET_H2X>;
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               ranges = <0x0 0x1e770000 0x100>;
+
+                               status = "disabled";
+
+                               pcie_cfg0: cfg0@80 {
+                                       reg = <0x80 0x80>;
+                                       compatible = "aspeed,ast2600-pcie-cfg";
+                               };
+
+                               pcie_cfg1: cfg1@C0 {
+                                       compatible = "aspeed,ast2600-pcie-cfg";
+                                       reg = <0xC0 0x80>;
+                               };
+                       };
+
+                       gpio0: gpio@1e780000 {
+                               compatible = "aspeed,ast2600-gpio";
+                               reg = <0x1e780000 0x1000>;
+                               interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+                               #gpio-cells = <2>;
+                               gpio-controller;
+                               interrupt-controller;
+                               gpio-ranges = <&pinctrl 0 0 220>;
+                               ngpios = <208>;
+                       };
+
+                       gpio1: gpio@1e780800 {
+                               compatible = "aspeed,ast2600-gpio";
+                               reg = <0x1e780800 0x800>;
+                               interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+                               #gpio-cells = <2>;
+                               gpio-controller;
+                               interrupt-controller;
+                               gpio-ranges = <&pinctrl 0 0 208>;
+                               ngpios = <36>;
+                       };
+
+                       uart1: serial@1e783000 {
+                               compatible = "ns16550a";
+                               reg = <0x1e783000 0x20>;
+                               reg-shift = <2>;
+                               interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&scu ASPEED_CLK_GATE_UART1CLK>;
+                               clock-frequency = <1846154>;
+                               no-loopback-test;
+                               status = "disabled";
+                       };
+
+                       uart5: serial@1e784000 {
+                               compatible = "ns16550a";
+                               reg = <0x1e784000 0x1000>;
+                               reg-shift = <2>;
+                               interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&scu ASPEED_CLK_GATE_UART5CLK>;
+                               clock-frequency = <1846154>;
+                               no-loopback-test;
+                               status = "disabled";
+                       };
+
+                       wdt1: watchdog@1e785000 {
+                               compatible = "aspeed,ast2600-wdt";
+                               reg = <0x1e785000 0x40>;
+                       };
+
+                       wdt2: watchdog@1e785040 {
+                               compatible = "aspeed,ast2600-wdt";
+                               reg = <0x1e785040 0x40>;
+                       };
+
+                       wdt3: watchdog@1e785080 {
+                               compatible = "aspeed,ast2600-wdt";
+                               reg = <0x1e785080 0x40>;
+                       };
+
+                       wdt4: watchdog@1e7850C0 {
+                               compatible = "aspeed,ast2600-wdt";
+                               reg = <0x1e7850C0 0x40>;
+                       };
+
+                       lpc: lpc@1e789000 {
+                               compatible = "aspeed,ast2600-lpc", "simple-mfd", "syscon";
+                               reg = <0x1e789000 0x1000>;
+
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               ranges = <0x0 0x1e789000 0x1000>;
+
+                               kcs1: kcs1@0 {
+                                       compatible = "aspeed,ast2600-kcs-bmc";
+                                       reg = <0x0 0x80>;
+                                       interrupts = <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>;
+                                       kcs_chan = <1>;
+                                       kcs_addr = <0xCA0>;
+                                       status = "disabled";
+                               };
+
+                               kcs2: kcs2@0 {
+                                       compatible = "aspeed,ast2600-kcs-bmc";
+                                       reg = <0x0 0x80>;
+                                       interrupts = <GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH>;
+                                       kcs_chan = <2>;
+                                       kcs_addr = <0xCA8>;
+                                       status = "disabled";
+                               };
+
+                               kcs3: kcs3@0 {
+                                       compatible = "aspeed,ast2600-kcs-bmc";
+                                       reg = <0x0 0x80>;
+                                       interrupts = <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
+                                       kcs_chan = <3>;
+                                       kcs_addr = <0xCA2>;
+                               };
+
+                               kcs4: kcs4@0 {
+                                       compatible = "aspeed,ast2600-kcs-bmc";
+                                       reg = <0x0 0x120>;
+                                       interrupts = <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>;
+                                       kcs_chan = <4>;
+                                       kcs_addr = <0xCA4>;
+                                       status = "disabled";
+                               };
+
+                               lpc_ctrl: lpc-ctrl@80 {
+                                       compatible = "aspeed,ast2600-lpc-ctrl";
+                                       reg = <0x80 0x80>;
+                                       status = "disabled";
+                               };
+
+                               lpc_snoop: lpc-snoop@80 {
+                                       compatible = "aspeed,ast2600-lpc-snoop";
+                                       reg = <0x80 0x80>;
+                                       interrupts = <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>;
+                                       status = "disabled";
+                               };
+
+                               lhc: lhc@a0 {
+                                       compatible = "aspeed,ast2600-lhc";
+                                       reg = <0xa0 0x24 0xc8 0x8>;
+                               };
+
+                               lpc_reset: reset-controller@98 {
+                                       compatible = "aspeed,ast2600-lpc-reset";
+                                       reg = <0x98 0x4>;
+                                       #reset-cells = <1>;
+                                       status = "disabled";
+                               };
+
+                               ibt: ibt@140 {
+                                       compatible = "aspeed,ast2600-ibt-bmc";
+                                       reg = <0x140 0x18>;
+                                       interrupts = <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
+                                       status = "disabled";
+                               };
+
+                               sio_regs: regs {
+                                       compatible = "aspeed,bmc-misc";
+                               };
+
+                               mbox: mbox@200 {
+                                       compatible = "aspeed,ast2600-mbox";
+                                       reg = <0x200 0x5c>;
+                                       interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
+                                       #mbox-cells = <1>;
+                                       status = "disabled";
+                               };
+                       };
+
+                       uart2: serial@1e78d000 {
+                               compatible = "ns16550a";
+                               reg = <0x1e78d000 0x20>;
+                               reg-shift = <2>;
+                               interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&scu ASPEED_CLK_GATE_UART2CLK>;
+                               clock-frequency = <1846154>;
+                               no-loopback-test;
+                               status = "disabled";
+                       };
+
+                       uart3: serial@1e78e000 {
+                               compatible = "ns16550a";
+                               reg = <0x1e78e000 0x20>;
+                               reg-shift = <2>;
+                               interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&scu ASPEED_CLK_GATE_UART3CLK>;
+                               clock-frequency = <1846154>;
+                               no-loopback-test;
+                               status = "disabled";
+                       };
+
+                       uart4: serial@1e78f000 {
+                               compatible = "ns16550a";
+                               reg = <0x1e78f000 0x20>;
+                               reg-shift = <2>;
+                               interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&scu ASPEED_CLK_GATE_UART4CLK>;
+                               clock-frequency = <1846154>;
+                               no-loopback-test;
+                               status = "disabled";
+                       };
+
+                       i2c: bus@1e78a000 {
+                               compatible = "simple-bus";
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               ranges = <0 0x1e78a000 0x1000>;
+                       };
+
+                       fsim0: fsi@1e79b000 {
+                               compatible = "aspeed,ast2600-fsi-master", "fsi-master";
+                               reg = <0x1e79b000 0x94>;
+                               interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_fsi1_default>;
+                               clocks = <&scu ASPEED_CLK_GATE_FSICLK>;
+                               status = "disabled";
+                       };
+
+                       fsim1: fsi@1e79b100 {
+                               compatible = "aspeed,ast2600-fsi-master", "fsi-master";
+                               reg = <0x1e79b100 0x94>;
+                               interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_fsi2_default>;
+                               clocks = <&scu ASPEED_CLK_GATE_FSICLK>;
+                               status = "disabled";
+                       };
+
+                       uart6: serial@1e790000 {
+                               compatible = "ns16550a";
+                               reg = <0x1e790000 0x20>;
+                               reg-shift = <2>;
+                               interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&scu ASPEED_CLK_GATE_UART6CLK>;
+                               clock-frequency = <1846154>;
+                               no-loopback-test;
+                               status = "disabled";
+                       };
+
+                       uart7: serial@1e790100 {
+                               compatible = "ns16550a";
+                               reg = <0x1e790100 0x20>;
+                               reg-shift = <2>;
+                               interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&scu ASPEED_CLK_GATE_UART7CLK>;
+                               clock-frequency = <1846154>;
+                               no-loopback-test;
+                               status = "disabled";
+                       };
+
+                       uart8: serial@1e790200 {
+                               compatible = "ns16550a";
+                               reg = <0x1e790200 0x20>;
+                               reg-shift = <2>;
+                               interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&scu ASPEED_CLK_GATE_UART8CLK>;
+                               clock-frequency = <1846154>;
+                               no-loopback-test;
+                               status = "disabled";
+                       };
+
+                       uart9: serial@1e790300 {
+                               compatible = "ns16550a";
+                               reg = <0x1e790300 0x20>;
+                               reg-shift = <2>;
+                               interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&scu ASPEED_CLK_GATE_UART9CLK>;
+                               clock-frequency = <1846154>;
+                               no-loopback-test;
+                               status = "disabled";
+                       };
+
+                       uart10: serial@1e790400 {
+                               compatible = "ns16550a";
+                               reg = <0x1e790400 0x20>;
+                               reg-shift = <2>;
+                               interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&scu ASPEED_CLK_GATE_UART10CLK>;
+                               clock-frequency = <1846154>;
+                               no-loopback-test;
+                               status = "disabled";
+                       };
+
+                       uart11: serial@1e790500 {
+                               compatible = "ns16550a";
+                               reg = <0x1e790400 0x20>;
+                               reg-shift = <2>;
+                               interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&scu ASPEED_CLK_GATE_UART11CLK>;
+                               clock-frequency = <1846154>;
+                               no-loopback-test;
+                               status = "disabled";
+                       };
+
+                       uart12: serial@1e790600 {
+                               compatible = "ns16550a";
+                               reg = <0x1e790600 0x20>;
+                               reg-shift = <2>;
+                               interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&scu ASPEED_CLK_GATE_UART12CLK>;
+                               clock-frequency = <1846154>;
+                               no-loopback-test;
+                               status = "disabled";
+                       };
+
+                       uart13: serial@1e790700 {
+                               compatible = "ns16550a";
+                               reg = <0x1e790700 0x20>;
+                               reg-shift = <2>;
+                               interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&scu ASPEED_CLK_GATE_UART13CLK>;
+                               clock-frequency = <1846154>;
+                               no-loopback-test;
+                               status = "disabled";
+                       };
+
+                       display_port: dp@1e6eb000 {
+                               compatible = "aspeed,ast2600-displayport";
+                               reg = <0x1e6eb000 0x200>;
+                               interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+                               resets = <&rst ASPEED_RESET_DP> ,<&rst ASPEED_RESET_DP_MCU>;
+                               status = "disabled";
+                       };
+
+               };
+
+       };
+
+};
+
+&i2c {
+       i2cglobal: i2cg@00 {
+               compatible = "aspeed,ast2600-i2c-global";
+               reg = <0x0 0x40>;
+               resets = <&rst ASPEED_RESET_I2C>;
+#if 0
+               new-mode;
+#endif
+       };
+
+       i2c0: i2c@80 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               #interrupt-cells = <1>;
+
+               reg = <0x80 0x80 0xC00 0x20>;
+               compatible = "aspeed,ast2600-i2c-bus";
+               bus-frequency = <100000>;
+               interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&scu ASPEED_CLK_APB2>;
+               status = "disabled";
+       };
+
+       i2c1: i2c@100 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               #interrupt-cells = <1>;
+
+               reg = <0x100 0x80 0xC20 0x20>;
+               compatible = "aspeed,ast2600-i2c-bus";
+               bus-frequency = <100000>;
+               interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&scu ASPEED_CLK_APB2>;
+               status = "disabled";
+       };
+
+       i2c2: i2c@180 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               #interrupt-cells = <1>;
+
+               reg = <0x180 0x80 0xC40 0x20>;
+               compatible = "aspeed,ast2600-i2c-bus";
+               bus-frequency = <100000>;
+               interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&scu ASPEED_CLK_APB2>;
+       };
+
+       i2c3: i2c@200 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               #interrupt-cells = <1>;
+
+               reg = <0x200 0x40 0xC60 0x20>;
+               compatible = "aspeed,ast2600-i2c-bus";
+               bus-frequency = <100000>;
+               interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&scu ASPEED_CLK_APB2>;
+       };
+
+       i2c4: i2c@280 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               #interrupt-cells = <1>;
+
+               reg = <0x280 0x80 0xC80 0x20>;
+               compatible = "aspeed,ast2600-i2c-bus";
+               bus-frequency = <100000>;
+               interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&scu ASPEED_CLK_APB2>;
+       };
+
+       i2c5: i2c@300 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               #interrupt-cells = <1>;
+
+               reg = <0x300 0x40 0xCA0 0x20>;
+               compatible = "aspeed,ast2600-i2c-bus";
+               bus-frequency = <100000>;
+               interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&scu ASPEED_CLK_APB2>;
+       };
+
+       i2c6: i2c@380 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               #interrupt-cells = <1>;
+
+               reg = <0x380 0x80 0xCC0 0x20>;
+               compatible = "aspeed,ast2600-i2c-bus";
+               bus-frequency = <100000>;
+               interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&scu ASPEED_CLK_APB2>;
+       };
+
+       i2c7: i2c@400 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               #interrupt-cells = <1>;
+
+               reg = <0x400 0x80 0xCE0 0x20>;
+               compatible = "aspeed,ast2600-i2c-bus";
+               bus-frequency = <100000>;
+               interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&scu ASPEED_CLK_APB2>;
+       };
+
+       i2c8: i2c@480 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               #interrupt-cells = <1>;
+
+               reg = <0x480 0x80 0xD00 0x20>;
+               compatible = "aspeed,ast2600-i2c-bus";
+               bus-frequency = <100000>;
+               interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&scu ASPEED_CLK_APB2>;
+       };
+
+       i2c9: i2c@500 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               #interrupt-cells = <1>;
+
+               reg = <0x500 0x80 0xD20 0x20>;
+               compatible = "aspeed,ast2600-i2c-bus";
+               bus-frequency = <100000>;
+               interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&scu ASPEED_CLK_APB2>;
+               status = "disabled";
+       };
+
+       i2c10: i2c@580 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               #interrupt-cells = <1>;
+
+               reg = <0x580 0x80 0xD40 0x20>;
+               compatible = "aspeed,ast2600-i2c-bus";
+               bus-frequency = <100000>;
+               interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&scu ASPEED_CLK_APB2>;
+               status = "disabled";
+       };
+
+       i2c11: i2c@600 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               #interrupt-cells = <1>;
+
+               reg = <0x600 0x80 0xD60 0x20>;
+               compatible = "aspeed,ast2600-i2c-bus";
+               bus-frequency = <100000>;
+               interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&scu ASPEED_CLK_APB2>;
+               status = "disabled";
+       };
+
+       i2c12: i2c@680 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               #interrupt-cells = <1>;
+
+               reg = <0x680 0x80 0xD80 0x20>;
+               compatible = "aspeed,ast2600-i2c-bus";
+               bus-frequency = <100000>;
+               interrupts = <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&scu ASPEED_CLK_APB2>;
+               status = "disabled";
+       };
+
+       i2c13: i2c@700 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               #interrupt-cells = <1>;
+
+               reg = <0x700 0x80 0xDA0 0x20>;
+               compatible = "aspeed,ast2600-i2c-bus";
+               bus-frequency = <100000>;
+               interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&scu ASPEED_CLK_APB2>;
+               status = "disabled";
+       };
+
+       i2c14: i2c@780 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               #interrupt-cells = <1>;
+
+               reg = <0x780 0x80 0xDC0 0x20>;
+               compatible = "aspeed,ast2600-i2c-bus";
+               bus-frequency = <100000>;
+               interrupts = <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&scu ASPEED_CLK_APB2>;
+               status = "disabled";
+       };
+
+       i2c15: i2c@800 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               #interrupt-cells = <1>;
+
+               reg = <0x800 0x80 0xDE0 0x20>;
+               compatible = "aspeed,ast2600-i2c-bus";
+               bus-frequency = <100000>;
+               interrupts = <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&scu ASPEED_CLK_APB2>;
+               status = "disabled";
+       };
+
+};
+
+&pinctrl {
+       pinctrl_fmcquad_default: fmcquad_default {
+               function = "FMCQUAD";
+               groups = "FMCQUAD";
+       };
+
+       pinctrl_spi1_default: spi1_default {
+               function = "SPI1";
+               groups = "SPI1";
+       };
+
+       pinctrl_spi1abr_default: spi1abr_default {
+               function = "SPI1ABR";
+               groups = "SPI1ABR";
+       };
+
+       pinctrl_spi1cs1_default: spi1cs1_default {
+               function = "SPI1CS1";
+               groups = "SPI1CS1";
+       };
+
+       pinctrl_spi1wp_default: spi1wp_default {
+               function = "SPI1WP";
+               groups = "SPI1WP";
+       };
+
+       pinctrl_spi1quad_default: spi1quad_default {
+               function = "SPI1QUAD";
+               groups = "SPI1QUAD";
+       };
+
+       pinctrl_spi2_default: spi2_default {
+               function = "SPI2";
+               groups = "SPI2";
+       };
+
+       pinctrl_spi2cs1_default: spi2cs1_default {
+               function = "SPI2CS1";
+               groups = "SPI2CS1";
+       };
+
+       pinctrl_spi2cs2_default: spi2cs2_default {
+               function = "SPI2CS2";
+               groups = "SPI2CS2";
+       };
+
+       pinctrl_spi2quad_default: spi2quad_default {
+               function = "SPI2QUAD";
+               groups = "SPI2QUAD";
+       };
+
+       pinctrl_acpi_default: acpi_default {
+               function = "ACPI";
+               groups = "ACPI";
+       };
+
+       pinctrl_adc0_default: adc0_default {
+               function = "ADC0";
+               groups = "ADC0";
+       };
+
+       pinctrl_adc1_default: adc1_default {
+               function = "ADC1";
+               groups = "ADC1";
+       };
+
+       pinctrl_adc10_default: adc10_default {
+               function = "ADC10";
+               groups = "ADC10";
+       };
+
+       pinctrl_adc11_default: adc11_default {
+               function = "ADC11";
+               groups = "ADC11";
+       };
+
+       pinctrl_adc12_default: adc12_default {
+               function = "ADC12";
+               groups = "ADC12";
+       };
+
+       pinctrl_adc13_default: adc13_default {
+               function = "ADC13";
+               groups = "ADC13";
+       };
+
+       pinctrl_adc14_default: adc14_default {
+               function = "ADC14";
+               groups = "ADC14";
+       };
+
+       pinctrl_adc15_default: adc15_default {
+               function = "ADC15";
+               groups = "ADC15";
+       };
+
+       pinctrl_adc2_default: adc2_default {
+               function = "ADC2";
+               groups = "ADC2";
+       };
+
+       pinctrl_adc3_default: adc3_default {
+               function = "ADC3";
+               groups = "ADC3";
+       };
+
+       pinctrl_adc4_default: adc4_default {
+               function = "ADC4";
+               groups = "ADC4";
+       };
+
+       pinctrl_adc5_default: adc5_default {
+               function = "ADC5";
+               groups = "ADC5";
+       };
+
+       pinctrl_adc6_default: adc6_default {
+               function = "ADC6";
+               groups = "ADC6";
+       };
+
+       pinctrl_adc7_default: adc7_default {
+               function = "ADC7";
+               groups = "ADC7";
+       };
+
+       pinctrl_adc8_default: adc8_default {
+               function = "ADC8";
+               groups = "ADC8";
+       };
+
+       pinctrl_adc9_default: adc9_default {
+               function = "ADC9";
+               groups = "ADC9";
+       };
+
+       pinctrl_bmcint_default: bmcint_default {
+               function = "BMCINT";
+               groups = "BMCINT";
+       };
+
+       pinctrl_ddcclk_default: ddcclk_default {
+               function = "DDCCLK";
+               groups = "DDCCLK";
+       };
+
+       pinctrl_ddcdat_default: ddcdat_default {
+               function = "DDCDAT";
+               groups = "DDCDAT";
+       };
+
+       pinctrl_espi_default: espi_default {
+               function = "ESPI";
+               groups = "ESPI";
+       };
+
+       pinctrl_fsi1_default: fsi1_default {
+               function = "FSI1";
+               groups = "FSI1";
+       };
+
+       pinctrl_fsi2_default: fsi2_default {
+               function = "FSI2";
+               groups = "FSI2";
+       };
+
+       pinctrl_fwspics1_default: fwspics1_default {
+               function = "FWSPICS1";
+               groups = "FWSPICS1";
+       };
+
+       pinctrl_fwspics2_default: fwspics2_default {
+               function = "FWSPICS2";
+               groups = "FWSPICS2";
+       };
+
+       pinctrl_gpid0_default: gpid0_default {
+               function = "GPID0";
+               groups = "GPID0";
+       };
+
+       pinctrl_gpid2_default: gpid2_default {
+               function = "GPID2";
+               groups = "GPID2";
+       };
+
+       pinctrl_gpid4_default: gpid4_default {
+               function = "GPID4";
+               groups = "GPID4";
+       };
+
+       pinctrl_gpid6_default: gpid6_default {
+               function = "GPID6";
+               groups = "GPID6";
+       };
+
+       pinctrl_gpie0_default: gpie0_default {
+               function = "GPIE0";
+               groups = "GPIE0";
+       };
+
+       pinctrl_gpie2_default: gpie2_default {
+               function = "GPIE2";
+               groups = "GPIE2";
+       };
+
+       pinctrl_gpie4_default: gpie4_default {
+               function = "GPIE4";
+               groups = "GPIE4";
+       };
+
+       pinctrl_gpie6_default: gpie6_default {
+               function = "GPIE6";
+               groups = "GPIE6";
+       };
+
+       pinctrl_i2c1_default: i2c1_default {
+               function = "I2C1";
+               groups = "I2C1";
+       };
+       pinctrl_i2c2_default: i2c2_default {
+               function = "I2C2";
+               groups = "I2C2";
+       };
+
+       pinctrl_i2c3_default: i2c3_default {
+               function = "I2C3";
+               groups = "I2C3";
+       };
+
+       pinctrl_i2c4_default: i2c4_default {
+               function = "I2C4";
+               groups = "I2C4";
+       };
+
+       pinctrl_i2c5_default: i2c5_default {
+               function = "I2C5";
+               groups = "I2C5";
+       };
+
+       pinctrl_i2c6_default: i2c6_default {
+               function = "I2C6";
+               groups = "I2C6";
+       };
+
+       pinctrl_i2c7_default: i2c7_default {
+               function = "I2C7";
+               groups = "I2C7";
+       };
+
+       pinctrl_i2c8_default: i2c8_default {
+               function = "I2C8";
+               groups = "I2C8";
+       };
+
+       pinctrl_i2c9_default: i2c9_default {
+               function = "I2C9";
+               groups = "I2C9";
+       };
+
+       pinctrl_i2c10_default: i2c10_default {
+               function = "I2C10";
+               groups = "I2C10";
+       };
+
+       pinctrl_i2c11_default: i2c11_default {
+               function = "I2C11";
+               groups = "I2C11";
+       };
+
+       pinctrl_i2c12_default: i2c12_default {
+               function = "I2C12";
+               groups = "I2C12";
+       };
+
+       pinctrl_i2c13_default: i2c13_default {
+               function = "I2C13";
+               groups = "I2C13";
+       };
+
+       pinctrl_i2c14_default: i2c14_default {
+               function = "I2C14";
+               groups = "I2C14";
+       };
+
+       pinctrl_i2c15_default: i2c15_default {
+               function = "I2C15";
+               groups = "I2C15";
+       };
+
+       pinctrl_i2c16_default: i2c16_default {
+               function = "I2C16";
+               groups = "I2C16";
+       };
+
+       pinctrl_lad0_default: lad0_default {
+               function = "LAD0";
+               groups = "LAD0";
+       };
+
+       pinctrl_lad1_default: lad1_default {
+               function = "LAD1";
+               groups = "LAD1";
+       };
+
+       pinctrl_lad2_default: lad2_default {
+               function = "LAD2";
+               groups = "LAD2";
+       };
+
+       pinctrl_lad3_default: lad3_default {
+               function = "LAD3";
+               groups = "LAD3";
+       };
+
+       pinctrl_lclk_default: lclk_default {
+               function = "LCLK";
+               groups = "LCLK";
+       };
+
+       pinctrl_lframe_default: lframe_default {
+               function = "LFRAME";
+               groups = "LFRAME";
+       };
+
+       pinctrl_lpchc_default: lpchc_default {
+               function = "LPCHC";
+               groups = "LPCHC";
+       };
+
+       pinctrl_lpcpd_default: lpcpd_default {
+               function = "LPCPD";
+               groups = "LPCPD";
+       };
+
+       pinctrl_lpcplus_default: lpcplus_default {
+               function = "LPCPLUS";
+               groups = "LPCPLUS";
+       };
+
+       pinctrl_lpcpme_default: lpcpme_default {
+               function = "LPCPME";
+               groups = "LPCPME";
+       };
+
+       pinctrl_lpcrst_default: lpcrst_default {
+               function = "LPCRST";
+               groups = "LPCRST";
+       };
+
+       pinctrl_lpcsmi_default: lpcsmi_default {
+               function = "LPCSMI";
+               groups = "LPCSMI";
+       };
+
+       pinctrl_lsirq_default: lsirq_default {
+               function = "LSIRQ";
+               groups = "LSIRQ";
+       };
+
+       pinctrl_mac1link_default: mac1link_default {
+               function = "MAC1LINK";
+               groups = "MAC1LINK";
+       };
+
+       pinctrl_mac2link_default: mac2link_default {
+               function = "MAC2LINK";
+               groups = "MAC2LINK";
+       };
+
+       pinctrl_mac3link_default: mac3link_default {
+               function = "MAC3LINK";
+               groups = "MAC3LINK";
+       };
+
+       pinctrl_mac4link_default: mac4link_default {
+               function = "MAC4LINK";
+               groups = "MAC4LINK";
+       };
+
+       pinctrl_mdio1_default: mdio1_default {
+               function = "MDIO1";
+               groups = "MDIO1";
+       };
+
+       pinctrl_mdio2_default: mdio2_default {
+               function = "MDIO2";
+               groups = "MDIO2";
+       };
+
+       pinctrl_mdio3_default: mdio3_default {
+               function = "MDIO3";
+               groups = "MDIO3";
+       };
+
+       pinctrl_mdio4_default: mdio4_default {
+               function = "MDIO4";
+               groups = "MDIO4";
+       };
+
+       pinctrl_rmii1_default: rmii1_default {
+               function = "RMII1";
+               groups = "RMII1";
+       };
+
+       pinctrl_rmii2_default: rmii2_default {
+               function = "RMII2";
+               groups = "RMII2";
+       };
+
+       pinctrl_rmii3_default: rmii3_default {
+               function = "RMII3";
+               groups = "RMII3";
+       };
+
+       pinctrl_rmii4_default: rmii4_default {
+               function = "RMII4";
+               groups = "RMII4";
+       };
+
+       pinctrl_rmii1rclk_default: rmii1rclk_default {
+               function = "RMII1RCLK";
+               groups = "RMII1RCLK";
+       };
+
+       pinctrl_rmii2rclk_default: rmii2rclk_default {
+               function = "RMII2RCLK";
+               groups = "RMII2RCLK";
+       };
+
+       pinctrl_rmii3rclk_default: rmii3rclk_default {
+               function = "RMII3RCLK";
+               groups = "RMII3RCLK";
+       };
+
+       pinctrl_rmii4rclk_default: rmii4rclk_default {
+               function = "RMII4RCLK";
+               groups = "RMII4RCLK";
+       };
+
+       pinctrl_ncts1_default: ncts1_default {
+               function = "NCTS1";
+               groups = "NCTS1";
+       };
+
+       pinctrl_ncts2_default: ncts2_default {
+               function = "NCTS2";
+               groups = "NCTS2";
+       };
+
+       pinctrl_ncts3_default: ncts3_default {
+               function = "NCTS3";
+               groups = "NCTS3";
+       };
+
+       pinctrl_ncts4_default: ncts4_default {
+               function = "NCTS4";
+               groups = "NCTS4";
+       };
+
+       pinctrl_ndcd1_default: ndcd1_default {
+               function = "NDCD1";
+               groups = "NDCD1";
+       };
+
+       pinctrl_ndcd2_default: ndcd2_default {
+               function = "NDCD2";
+               groups = "NDCD2";
+       };
+
+       pinctrl_ndcd3_default: ndcd3_default {
+               function = "NDCD3";
+               groups = "NDCD3";
+       };
+
+       pinctrl_ndcd4_default: ndcd4_default {
+               function = "NDCD4";
+               groups = "NDCD4";
+       };
+
+       pinctrl_ndsr1_default: ndsr1_default {
+               function = "NDSR1";
+               groups = "NDSR1";
+       };
+
+       pinctrl_ndsr2_default: ndsr2_default {
+               function = "NDSR2";
+               groups = "NDSR2";
+       };
+
+       pinctrl_ndsr3_default: ndsr3_default {
+               function = "NDSR3";
+               groups = "NDSR3";
+       };
+
+       pinctrl_ndsr4_default: ndsr4_default {
+               function = "NDSR4";
+               groups = "NDSR4";
+       };
+
+       pinctrl_ndtr1_default: ndtr1_default {
+               function = "NDTR1";
+               groups = "NDTR1";
+       };
+
+       pinctrl_ndtr2_default: ndtr2_default {
+               function = "NDTR2";
+               groups = "NDTR2";
+       };
+
+       pinctrl_ndtr3_default: ndtr3_default {
+               function = "NDTR3";
+               groups = "NDTR3";
+       };
+
+       pinctrl_ndtr4_default: ndtr4_default {
+               function = "NDTR4";
+               groups = "NDTR4";
+       };
+
+       pinctrl_nri1_default: nri1_default {
+               function = "NRI1";
+               groups = "NRI1";
+       };
+
+       pinctrl_nri2_default: nri2_default {
+               function = "NRI2";
+               groups = "NRI2";
+       };
+
+       pinctrl_nri3_default: nri3_default {
+               function = "NRI3";
+               groups = "NRI3";
+       };
+
+       pinctrl_nri4_default: nri4_default {
+               function = "NRI4";
+               groups = "NRI4";
+       };
+
+       pinctrl_nrts1_default: nrts1_default {
+               function = "NRTS1";
+               groups = "NRTS1";
+       };
+
+       pinctrl_nrts2_default: nrts2_default {
+               function = "NRTS2";
+               groups = "NRTS2";
+       };
+
+       pinctrl_nrts3_default: nrts3_default {
+               function = "NRTS3";
+               groups = "NRTS3";
+       };
+
+       pinctrl_nrts4_default: nrts4_default {
+               function = "NRTS4";
+               groups = "NRTS4";
+       };
+
+       pinctrl_oscclk_default: oscclk_default {
+               function = "OSCCLK";
+               groups = "OSCCLK";
+       };
+
+       pinctrl_pewake_default: pewake_default {
+               function = "PEWAKE";
+               groups = "PEWAKE";
+       };
+
+       pinctrl_pnor_default: pnor_default {
+               function = "PNOR";
+               groups = "PNOR";
+       };
+
+       pinctrl_pwm0_default: pwm0_default {
+               function = "PWM0";
+               groups = "PWM0";
+       };
+
+       pinctrl_pwm1_default: pwm1_default {
+               function = "PWM1";
+               groups = "PWM1";
+       };
+
+       pinctrl_pwm2_default: pwm2_default {
+               function = "PWM2";
+               groups = "PWM2";
+       };
+
+       pinctrl_pwm3_default: pwm3_default {
+               function = "PWM3";
+               groups = "PWM3";
+       };
+
+       pinctrl_pwm4_default: pwm4_default {
+               function = "PWM4";
+               groups = "PWM4";
+       };
+
+       pinctrl_pwm5_default: pwm5_default {
+               function = "PWM5";
+               groups = "PWM5";
+       };
+
+       pinctrl_pwm6_default: pwm6_default {
+               function = "PWM6";
+               groups = "PWM6";
+       };
+
+       pinctrl_pwm7_default: pwm7_default {
+               function = "PWM7";
+               groups = "PWM7";
+       };
+
+       pinctrl_rgmii1_default: rgmii1_default {
+               function = "RGMII1";
+               groups = "RGMII1";
+       };
+
+       pinctrl_rgmii2_default: rgmii2_default {
+               function = "RGMII2";
+               groups = "RGMII2";
+       };
+
+       pinctrl_rgmii3_default: rgmii3_default {
+               function = "RGMII3";
+               groups = "RGMII3";
+       };
+
+       pinctrl_rgmii4_default: rgmii4_default {
+               function = "RGMII4";
+               groups = "RGMII4";
+       };
+
+       pinctrl_rmii1_default: rmii1_default {
+               function = "RMII1";
+               groups = "RMII1";
+       };
+
+       pinctrl_rmii2_default: rmii2_default {
+               function = "RMII2";
+               groups = "RMII2";
+       };
+
+       pinctrl_rxd1_default: rxd1_default {
+               function = "RXD1";
+               groups = "RXD1";
+       };
+
+       pinctrl_rxd2_default: rxd2_default {
+               function = "RXD2";
+               groups = "RXD2";
+       };
+
+       pinctrl_rxd3_default: rxd3_default {
+               function = "RXD3";
+               groups = "RXD3";
+       };
+
+       pinctrl_rxd4_default: rxd4_default {
+               function = "RXD4";
+               groups = "RXD4";
+       };
+
+       pinctrl_salt1_default: salt1_default {
+               function = "SALT1";
+               groups = "SALT1";
+       };
+
+       pinctrl_salt10_default: salt10_default {
+               function = "SALT10";
+               groups = "SALT10";
+       };
+
+       pinctrl_salt11_default: salt11_default {
+               function = "SALT11";
+               groups = "SALT11";
+       };
+
+       pinctrl_salt12_default: salt12_default {
+               function = "SALT12";
+               groups = "SALT12";
+       };
+
+       pinctrl_salt13_default: salt13_default {
+               function = "SALT13";
+               groups = "SALT13";
+       };
+
+       pinctrl_salt14_default: salt14_default {
+               function = "SALT14";
+               groups = "SALT14";
+       };
+
+       pinctrl_salt2_default: salt2_default {
+               function = "SALT2";
+               groups = "SALT2";
+       };
+
+       pinctrl_salt3_default: salt3_default {
+               function = "SALT3";
+               groups = "SALT3";
+       };
+
+       pinctrl_salt4_default: salt4_default {
+               function = "SALT4";
+               groups = "SALT4";
+       };
+
+       pinctrl_salt5_default: salt5_default {
+               function = "SALT5";
+               groups = "SALT5";
+       };
+
+       pinctrl_salt6_default: salt6_default {
+               function = "SALT6";
+               groups = "SALT6";
+       };
+
+       pinctrl_salt7_default: salt7_default {
+               function = "SALT7";
+               groups = "SALT7";
+       };
+
+       pinctrl_salt8_default: salt8_default {
+               function = "SALT8";
+               groups = "SALT8";
+       };
+
+       pinctrl_salt9_default: salt9_default {
+               function = "SALT9";
+               groups = "SALT9";
+       };
+
+       pinctrl_scl1_default: scl1_default {
+               function = "SCL1";
+               groups = "SCL1";
+       };
+
+       pinctrl_scl2_default: scl2_default {
+               function = "SCL2";
+               groups = "SCL2";
+       };
+
+       pinctrl_sd1_default: sd1_default {
+               function = "SD1";
+               groups = "SD1";
+       };
+
+       pinctrl_sd2_default: sd2_default {
+               function = "SD2";
+               groups = "SD2";
+       };
+
+       pinctrl_emmc_default: emmc_default {
+               function = "EMMC";
+               groups = "EMMC";
+       };
+
+       pinctrl_emmcg8_default: emmcg8_default {
+               function = "EMMCG8";
+               groups = "EMMCG8";
+       };
+
+       pinctrl_sda1_default: sda1_default {
+               function = "SDA1";
+               groups = "SDA1";
+       };
+
+       pinctrl_sda2_default: sda2_default {
+               function = "SDA2";
+               groups = "SDA2";
+       };
+
+       pinctrl_sgps1_default: sgps1_default {
+               function = "SGPS1";
+               groups = "SGPS1";
+       };
+
+       pinctrl_sgps2_default: sgps2_default {
+               function = "SGPS2";
+               groups = "SGPS2";
+       };
+
+       pinctrl_sioonctrl_default: sioonctrl_default {
+               function = "SIOONCTRL";
+               groups = "SIOONCTRL";
+       };
+
+       pinctrl_siopbi_default: siopbi_default {
+               function = "SIOPBI";
+               groups = "SIOPBI";
+       };
+
+       pinctrl_siopbo_default: siopbo_default {
+               function = "SIOPBO";
+               groups = "SIOPBO";
+       };
+
+       pinctrl_siopwreq_default: siopwreq_default {
+               function = "SIOPWREQ";
+               groups = "SIOPWREQ";
+       };
+
+       pinctrl_siopwrgd_default: siopwrgd_default {
+               function = "SIOPWRGD";
+               groups = "SIOPWRGD";
+       };
+
+       pinctrl_sios3_default: sios3_default {
+               function = "SIOS3";
+               groups = "SIOS3";
+       };
+
+       pinctrl_sios5_default: sios5_default {
+               function = "SIOS5";
+               groups = "SIOS5";
+       };
+
+       pinctrl_siosci_default: siosci_default {
+               function = "SIOSCI";
+               groups = "SIOSCI";
+       };
+
+       pinctrl_spi1_default: spi1_default {
+               function = "SPI1";
+               groups = "SPI1";
+       };
+
+       pinctrl_spi1cs1_default: spi1cs1_default {
+               function = "SPI1CS1";
+               groups = "SPI1CS1";
+       };
+
+       pinctrl_spi1debug_default: spi1debug_default {
+               function = "SPI1DEBUG";
+               groups = "SPI1DEBUG";
+       };
+
+       pinctrl_spi1passthru_default: spi1passthru_default {
+               function = "SPI1PASSTHRU";
+               groups = "SPI1PASSTHRU";
+       };
+
+       pinctrl_spi2ck_default: spi2ck_default {
+               function = "SPI2CK";
+               groups = "SPI2CK";
+       };
+
+       pinctrl_spi2cs0_default: spi2cs0_default {
+               function = "SPI2CS0";
+               groups = "SPI2CS0";
+       };
+
+       pinctrl_spi2cs1_default: spi2cs1_default {
+               function = "SPI2CS1";
+               groups = "SPI2CS1";
+       };
+
+       pinctrl_spi2miso_default: spi2miso_default {
+               function = "SPI2MISO";
+               groups = "SPI2MISO";
+       };
+
+       pinctrl_spi2mosi_default: spi2mosi_default {
+               function = "SPI2MOSI";
+               groups = "SPI2MOSI";
+       };
+
+       pinctrl_timer3_default: timer3_default {
+               function = "TIMER3";
+               groups = "TIMER3";
+       };
+
+       pinctrl_timer4_default: timer4_default {
+               function = "TIMER4";
+               groups = "TIMER4";
+       };
+
+       pinctrl_timer5_default: timer5_default {
+               function = "TIMER5";
+               groups = "TIMER5";
+       };
+
+       pinctrl_timer6_default: timer6_default {
+               function = "TIMER6";
+               groups = "TIMER6";
+       };
+
+       pinctrl_timer7_default: timer7_default {
+               function = "TIMER7";
+               groups = "TIMER7";
+       };
+
+       pinctrl_timer8_default: timer8_default {
+               function = "TIMER8";
+               groups = "TIMER8";
+       };
+
+       pinctrl_txd1_default: txd1_default {
+               function = "TXD1";
+               groups = "TXD1";
+       };
+
+       pinctrl_txd2_default: txd2_default {
+               function = "TXD2";
+               groups = "TXD2";
+       };
+
+       pinctrl_txd3_default: txd3_default {
+               function = "TXD3";
+               groups = "TXD3";
+       };
+
+       pinctrl_txd4_default: txd4_default {
+               function = "TXD4";
+               groups = "TXD4";
+       };
+
+       pinctrl_uart6_default: uart6_default {
+               function = "UART6";
+               groups = "UART6";
+       };
+
+       pinctrl_usbcki_default: usbcki_default {
+               function = "USBCKI";
+               groups = "USBCKI";
+       };
+
+       pinctrl_usb2ah_default: usb2ah_default {
+               function = "USB2AH";
+               groups = "USB2AH";
+       };
+
+       pinctrl_usb11bhid_default: usb11bhid_default {
+               function = "USB11BHID";
+               groups = "USB11BHID";
+       };
+
+       pinctrl_usb2bh_default: usb2bh_default {
+               function = "USB2BH";
+               groups = "USB2BH";
+       };
+
+       pinctrl_vgabiosrom_default: vgabiosrom_default {
+               function = "VGABIOSROM";
+               groups = "VGABIOSROM";
+       };
+
+       pinctrl_vgahs_default: vgahs_default {
+               function = "VGAHS";
+               groups = "VGAHS";
+       };
+
+       pinctrl_vgavs_default: vgavs_default {
+               function = "VGAVS";
+               groups = "VGAVS";
+       };
+
+       pinctrl_vpi24_default: vpi24_default {
+               function = "VPI24";
+               groups = "VPI24";
+       };
+
+       pinctrl_vpo_default: vpo_default {
+               function = "VPO";
+               groups = "VPO";
+       };
+
+       pinctrl_wdtrst1_default: wdtrst1_default {
+               function = "WDTRST1";
+               groups = "WDTRST1";
+       };
+
+       pinctrl_wdtrst2_default: wdtrst2_default {
+               function = "WDTRST2";
+               groups = "WDTRST2";
+       };
+
+       pinctrl_pcie0rc_default: pcie0rc_default {
+               function = "PCIE0RC";
+               groups = "PCIE0RC";
+       };
+
+       pinctrl_pcie1rc_default: pcie1rc_default {
+               function = "PCIE1RC";
+               groups = "PCIE1RC";
+       };
+};
index eef433e..0ab52fd 100644 (file)
                clock-frequency = <400000>;
        };
 
+       nand: nand-controller@f4324000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "cortina,ca-nand";
+               reg = <0 0xf4324000 0x3b0>, /* NAND controller */
+                     <0 0xf7001000 0xb4>, /* DMA_GLOBAL */
+                     <0 0xf7001a00 0x80>; /* DMA channel0 for FLASH */
+               status = "okay";
+               nand-ecc-mode = "hw";
+               nand-ecc-strength = <16>;
+               nand-ecc-step-size = <1024>;    /* Must be 1024 */
+               nand_flash_base_addr = <0xe0000000>;
+       };
+
        sflash: sflash-controller@f4324000 {
                #address-cells = <2>;
                #size-cells = <1>;
index d888545..5c2e025 100644 (file)
                compatible = "mediatek,timer";
                reg = <0x10004000 0x80>;
                interrupts = <GIC_SPI 152 IRQ_TYPE_LEVEL_LOW>;
-               clocks = <&system_clk>;
+               clocks = <&infracfg CLK_INFRA_APXGPT_PD>;
                clock-names = "system-clk";
        };
 
-       system_clk: dummy13m {
-               compatible = "fixed-clock";
-               clock-frequency = <13000000>;
-               #clock-cells = <0>;
-       };
-
        infracfg: infracfg@10000000 {
                compatible = "mediatek,mt7622-infracfg",
                             "syscon";
index cd43c1f..292b00f 100644 (file)
 &watchdog {
        status = "okay";
 };
+
+&usb0 {
+       status = "okay";
+       dr_mode = "peripheral";
+
+       usb_con_c: connector {
+               compatible = "usb-c-connector";
+               label = "USB-C";
+       };
+};
index 1c33582..c4577ce 100644 (file)
                status = "disabled";
        };
 
+       usb0: usb@11100000 {
+               compatible = "mediatek,mt8516-musb",
+                            "mediatek,mt8518-musb";
+               reg = <0x11100000 0x1000>;
+               interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_LOW>;
+               interrupt-names = "mc";
+               clocks = <&topckgen CLK_TOP_USB_PHY48M>,
+                        <&topckgen_cg CLK_TOP_USBIF>,
+                        <&topckgen_cg CLK_TOP_USB>,
+                        <&topckgen_cg CLK_TOP_USB_1P>;
+               clock-names = "usbpll", "usbmcu", "usb", "icusb";
+               status = "disabled";
+       };
+
        uart0: serial@11005000 {
                compatible = "mediatek,hsuart";
                reg = <0x11005000 0x1000>;
diff --git a/arch/arm/dts/rk3328-nanopi-r2s-u-boot.dtsi b/arch/arm/dts/rk3328-nanopi-r2s-u-boot.dtsi
new file mode 100644 (file)
index 0000000..9e2ced1
--- /dev/null
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2018-2019 Rockchip Electronics Co., Ltd
+ * (C) Copyright 2020 David Bauer
+ */
+
+#include "rk3328-u-boot.dtsi"
+#include "rk3328-sdram-ddr4-666.dtsi"
+/ {
+       chosen {
+               u-boot,spl-boot-order = "same-as-spl", &sdmmc, &emmc;
+       };
+};
+
+&gpio0 {
+       u-boot,dm-spl;
+};
+
+&pinctrl {
+       u-boot,dm-spl;
+};
+
+&sdmmc0m1_gpio {
+       u-boot,dm-spl;
+};
+
+&pcfg_pull_up_4ma {
+       u-boot,dm-spl;
+};
+
+/* Need this and all the pinctrl/gpio stuff above to set pinmux */
+&vcc_sd {
+       u-boot,dm-spl;
+};
+
+&gmac2io {
+       snps,reset-gpio = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>;
+       snps,reset-active-low;
+       snps,reset-delays-us = <0 10000 50000>;
+};
diff --git a/arch/arm/dts/rk3328-nanopi-r2s.dts b/arch/arm/dts/rk3328-nanopi-r2s.dts
new file mode 100644 (file)
index 0000000..5445c5c
--- /dev/null
@@ -0,0 +1,370 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2020 David Bauer <mail@david-bauer.net>
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/gpio/gpio.h>
+#include "rk3328.dtsi"
+
+/ {
+       model = "FriendlyElec NanoPi R2S";
+       compatible = "friendlyarm,nanopi-r2s", "rockchip,rk3328";
+
+       chosen {
+               stdout-path = "serial2:1500000n8";
+       };
+
+       gmac_clk: gmac-clock {
+               compatible = "fixed-clock";
+               clock-frequency = <125000000>;
+               clock-output-names = "gmac_clkin";
+               #clock-cells = <0>;
+       };
+
+       keys {
+               compatible = "gpio-keys";
+               pinctrl-0 = <&reset_button_pin>;
+               pinctrl-names = "default";
+
+               reset {
+                       label = "reset";
+                       gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_LOW>;
+                       linux,code = <KEY_RESTART>;
+                       debounce-interval = <50>;
+               };
+       };
+
+       leds {
+               compatible = "gpio-leds";
+               pinctrl-0 = <&lan_led_pin>,  <&sys_led_pin>, <&wan_led_pin>;
+               pinctrl-names = "default";
+
+               lan_led: led-0 {
+                       gpios = <&gpio2 RK_PB7 GPIO_ACTIVE_HIGH>;
+                       label = "nanopi-r2s:green:lan";
+               };
+
+               sys_led: led-1 {
+                       gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>;
+                       label = "nanopi-r2s:red:sys";
+               };
+
+               wan_led: led-2 {
+                       gpios = <&gpio2 RK_PC2 GPIO_ACTIVE_HIGH>;
+                       label = "nanopi-r2s:green:wan";
+               };
+       };
+
+       vcc_io_sdio: sdmmcio-regulator {
+               compatible = "regulator-gpio";
+               enable-active-high;
+               gpios = <&gpio1 RK_PD4 GPIO_ACTIVE_HIGH>;
+               pinctrl-0 = <&sdio_vcc_pin>;
+               pinctrl-names = "default";
+               regulator-name = "vcc_io_sdio";
+               regulator-always-on;
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-settling-time-us = <5000>;
+               regulator-type = "voltage";
+               startup-delay-us = <2000>;
+               states = <1800000 0x1
+                         3300000 0x0>;
+               vin-supply = <&vcc_io_33>;
+       };
+
+       vcc_sd: sdmmc-regulator {
+               compatible = "regulator-fixed";
+               gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_LOW>;
+               pinctrl-0 = <&sdmmc0m1_gpio>;
+               pinctrl-names = "default";
+               regulator-name = "vcc_sd";
+               regulator-boot-on;
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               vin-supply = <&vcc_io_33>;
+       };
+
+       vdd_5v: vdd-5v {
+               compatible = "regulator-fixed";
+               regulator-name = "vdd_5v";
+               regulator-always-on;
+               regulator-boot-on;
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+       };
+};
+
+&cpu0 {
+       cpu-supply = <&vdd_arm>;
+};
+
+&cpu1 {
+       cpu-supply = <&vdd_arm>;
+};
+
+&cpu2 {
+       cpu-supply = <&vdd_arm>;
+};
+
+&cpu3 {
+       cpu-supply = <&vdd_arm>;
+};
+
+&gmac2io {
+       assigned-clocks = <&cru SCLK_MAC2IO>, <&cru SCLK_MAC2IO_EXT>;
+       assigned-clock-parents = <&gmac_clk>, <&gmac_clk>;
+       clock_in_out = "input";
+       phy-handle = <&rtl8211e>;
+       phy-mode = "rgmii";
+       phy-supply = <&vcc_io_33>;
+       pinctrl-0 = <&rgmiim1_pins>;
+       pinctrl-names = "default";
+       rx_delay = <0x18>;
+       snps,aal;
+       tx_delay = <0x24>;
+       status = "okay";
+
+       mdio {
+               compatible = "snps,dwmac-mdio";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               rtl8211e: ethernet-phy@1 {
+                       compatible = "ethernet-phy-id001c.c915",
+                                    "ethernet-phy-ieee802.3-c22";
+                       reg = <1>;
+                       pinctrl-0 = <&eth_phy_reset_pin>;
+                       pinctrl-names = "default";
+                       reset-assert-us = <10000>;
+                       reset-deassert-us = <50000>;
+                       reset-gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>;
+               };
+       };
+};
+
+&i2c1 {
+       status = "okay";
+
+       rk805: pmic@18 {
+               compatible = "rockchip,rk805";
+               reg = <0x18>;
+               interrupt-parent = <&gpio1>;
+               interrupts = <24 IRQ_TYPE_LEVEL_LOW>;
+               #clock-cells = <1>;
+               clock-output-names = "xin32k", "rk805-clkout2";
+               gpio-controller;
+               #gpio-cells = <2>;
+               pinctrl-0 = <&pmic_int_l>;
+               pinctrl-names = "default";
+               rockchip,system-power-controller;
+               wakeup-source;
+
+               vcc1-supply = <&vdd_5v>;
+               vcc2-supply = <&vdd_5v>;
+               vcc3-supply = <&vdd_5v>;
+               vcc4-supply = <&vdd_5v>;
+               vcc5-supply = <&vcc_io_33>;
+               vcc6-supply = <&vdd_5v>;
+
+               regulators {
+                       vdd_log: DCDC_REG1 {
+                               regulator-name = "vdd_log";
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <712500>;
+                               regulator-max-microvolt = <1450000>;
+                               regulator-ramp-delay = <12500>;
+
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <1000000>;
+                               };
+                       };
+
+                       vdd_arm: DCDC_REG2 {
+                               regulator-name = "vdd_arm";
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <712500>;
+                               regulator-max-microvolt = <1450000>;
+                               regulator-ramp-delay = <12500>;
+
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <950000>;
+                               };
+                       };
+
+                       vcc_ddr: DCDC_REG3 {
+                               regulator-name = "vcc_ddr";
+                               regulator-always-on;
+                               regulator-boot-on;
+
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                               };
+                       };
+
+                       vcc_io_33: DCDC_REG4 {
+                               regulator-name = "vcc_io_33";
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <3300000>;
+                               };
+                       };
+
+                       vcc_18: LDO_REG1 {
+                               regulator-name = "vcc_18";
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <1800000>;
+                               };
+                       };
+
+                       vcc18_emmc: LDO_REG2 {
+                               regulator-name = "vcc18_emmc";
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <1800000>;
+                               };
+                       };
+
+                       vdd_10: LDO_REG3 {
+                               regulator-name = "vdd_10";
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1000000>;
+
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <1000000>;
+                               };
+                       };
+               };
+       };
+};
+
+&io_domains {
+       pmuio-supply = <&vcc_io_33>;
+       vccio1-supply = <&vcc_io_33>;
+       vccio2-supply = <&vcc18_emmc>;
+       vccio3-supply = <&vcc_io_sdio>;
+       vccio4-supply = <&vcc_18>;
+       vccio5-supply = <&vcc_io_33>;
+       vccio6-supply = <&vcc_io_33>;
+       status = "okay";
+};
+
+&pinctrl {
+       button {
+               reset_button_pin: reset-button-pin {
+                       rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+
+       ethernet-phy {
+               eth_phy_reset_pin: eth-phy-reset-pin {
+                       rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_down>;
+               };
+       };
+
+       leds {
+               lan_led_pin: lan-led-pin {
+                       rockchip,pins = <2 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+
+               sys_led_pin: sys-led-pin {
+                       rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+
+               wan_led_pin: wan-led-pin {
+                       rockchip,pins = <2 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+
+       pmic {
+               pmic_int_l: pmic-int-l {
+                       rockchip,pins = <1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+       };
+
+       sd {
+               sdio_vcc_pin: sdio-vcc-pin {
+                       rockchip,pins = <1 RK_PD4 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+       };
+};
+
+&pwm2 {
+       status = "okay";
+};
+
+&sdmmc {
+       bus-width = <4>;
+       cap-sd-highspeed;
+       disable-wp;
+       pinctrl-0 = <&sdmmc0_clk>, <&sdmmc0_cmd>, <&sdmmc0_dectn>, <&sdmmc0_bus4>;
+       pinctrl-names = "default";
+       sd-uhs-sdr12;
+       sd-uhs-sdr25;
+       sd-uhs-sdr50;
+       sd-uhs-sdr104;
+       vmmc-supply = <&vcc_sd>;
+       vqmmc-supply = <&vcc_io_sdio>;
+       status = "okay";
+};
+
+&tsadc {
+       rockchip,hw-tshut-mode = <0>;
+       rockchip,hw-tshut-polarity = <0>;
+       status = "okay";
+};
+
+&u2phy {
+       status = "okay";
+};
+
+&u2phy_host {
+       status = "okay";
+};
+
+&u2phy_otg {
+       status = "okay";
+};
+
+&uart2 {
+       status = "okay";
+};
+
+&usb20_otg {
+       status = "okay";
+       dr_mode = "host";
+};
+
+&usb_host0_ehci {
+       status = "okay";
+};
+
+&usb_host0_ohci {
+       status = "okay";
+};
index 8056dc8..5e39b14 100644 (file)
        };
 };
 
-&rng {
-       status = "okay";
-};
-
 &i2c0 {
        u-boot,dm-pre-reloc;
 };
        status = "okay";
 };
 
+&vdd_center {
+       regulator-init-microvolt = <900000>;
+};
+
 &sdmmc {
        u-boot,dm-pre-reloc;
        bus-width = <4>;
index 38e0897..c58ad95 100644 (file)
@@ -11,3 +11,7 @@
                u-boot,spl-boot-order = "same-as-spl", &sdhci, &sdmmc;
        };
 };
+
+&vdd_log {
+       regulator-init-microvolt = <950000>;
+};
index f8b2a1d..c638ce2 100644 (file)
@@ -11,3 +11,7 @@
                u-boot,spl-boot-order = "same-as-spl", &sdhci, &sdmmc;
        };
 };
+
+&vdd_log {
+       regulator-init-microvolt = <950000>;
+};
index ee3b986..1eafb40 100644 (file)
        u-boot,dm-pre-reloc;
 };
 
-&rng {
-       status = "okay";
-};
-
 &sdhci {
        max-frequency = <25000000>;
        u-boot,dm-pre-reloc;
index 29846c4..e7a1aea 100644 (file)
@@ -28,8 +28,7 @@
        };
 
        aliases {
-               spi0 = &spi1;
-               spi1 = &spi5;
+               spi5 = &spi5;
        };
 
        /*
index fc155e6..e3c9364 100644 (file)
@@ -7,10 +7,6 @@
 #include "rk3399-sdram-lpddr4-100.dtsi"
 
 / {
-       aliases {
-               spi0 = &spi1;
-       };
-
        chosen {
                u-boot,spl-boot-order = "same-as-spl", &spi_flash, &sdhci, &sdmmc;
        };
index 6317b47..37dff04 100644 (file)
        };
 };
 
-&rng {
-       status = "okay";
-};
-
 &spi1 {
        spi_flash: flash@0 {
                u-boot,dm-pre-reloc;
index ecd230c..73922c3 100644 (file)
@@ -32,7 +32,7 @@
        rng: rng@ff8b8000 {
                compatible = "rockchip,cryptov1-rng";
                reg = <0x0 0xff8b8000 0x0 0x1000>;
-               status = "disabled";
+               status = "okay";
        };
 
        dmc: dmc {
diff --git a/arch/arm/include/asm/acpi_table.h b/arch/arm/include/asm/acpi_table.h
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/arch/arm/include/asm/arch-aspeed/boot0.h b/arch/arm/include/asm/arch-aspeed/boot0.h
new file mode 100644 (file)
index 0000000..368becc
--- /dev/null
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) Aspeed Technology Inc.
+ */
+
+#ifndef _ASM_ARCH_BOOT0_H
+#define _ASM_ARCH_BOOT0_H
+
+_start:
+       ARM_VECTORS
+
+       .word   0x0     /* key location */
+       .word   0x0     /* start address of image */
+       .word   0xfc00  /* maximum image size: 63KB */
+       .word   0x0     /* signature address */
+       .word   0x0     /* header revision ID low */
+       .word   0x0     /* header revision ID high */
+       .word   0x0     /* reserved */
+       .word   0x0     /* checksum */
+       .word   0x0     /* BL2 secure header */
+       .word   0x0     /* public key or digest offset for BL2 */
+
+#endif
index 6cee036..d50ec5f 100644 (file)
 #define ASPEED_DRAM_BASE       0x80000000
 #define ASPEED_SRAM_BASE       0x1e720000
 #define ASPEED_SRAM_SIZE       0x9000
+#elif defined(CONFIG_ASPEED_AST2600)
+#define ASPEED_MAC_COUNT       4
+#define ASPEED_DRAM_BASE       0x80000000
+#define ASPEED_SRAM_BASE       0x10000000
+#define ASPEED_SRAM_SIZE       0x10000
 #else
 #err "Unrecognized Aspeed platform."
 #endif
diff --git a/arch/arm/include/asm/arch-aspeed/scu_ast2600.h b/arch/arm/include/asm/arch-aspeed/scu_ast2600.h
new file mode 100644 (file)
index 0000000..a205fb1
--- /dev/null
@@ -0,0 +1,338 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) Aspeed Technology Inc.
+ */
+#ifndef _ASM_ARCH_SCU_AST2600_H
+#define _ASM_ARCH_SCU_AST2600_H
+
+#define SCU_UNLOCK_KEY                 0x1688a8a8
+
+#define SCU_CLKGATE1_EMMC                      BIT(27)
+#define SCU_CLKGATE1_MAC2                      BIT(21)
+#define SCU_CLKGATE1_MAC1                      BIT(20)
+#define SCU_CLKGATE1_USB_HUB           BIT(14)
+#define SCU_CLKGATE1_USB_HOST2         BIT(7)
+
+#define SCU_CLKGATE2_FSI                       BIT(30)
+#define SCU_CLKGATE2_MAC4                      BIT(21)
+#define SCU_CLKGATE2_MAC3                      BIT(20)
+#define SCU_CLKGATE2_SDIO                      BIT(4)
+
+#define SCU_DRAM_HDSHK_SOC_INIT                        BIT(7)
+#define SCU_DRAM_HDSHK_RDY                     BIT(6)
+
+#define SCU_CLKSRC1_ECC_RSA_DIV_MASK           GENMASK(27, 26)
+#define SCU_CLKSRC1_ECC_RSA_DIV_SHIFT          26
+#define SCU_CLKSRC1_PCLK_DIV_MASK              GENMASK(25, 23)
+#define SCU_CLKSRC1_PCLK_DIV_SHIFT             23
+#define SCU_CLKSRC1_BCLK_DIV_MASK              GENMASK(22, 20)
+#define SCU_CLKSRC1_BCLK_DIV_SHIFT             20
+#define SCU_CLKSRC1_ECC_RSA                    BIT(19)
+#define SCU_CLKSRC1_MAC_DIV_MASK               GENMASK(18, 16)
+#define SCU_CLKSRC1_MAC_DIV_SHIFT              16
+#define SCU_CLKSRC1_EMMC_EN                    BIT(15)
+#define SCU_CLKSRC1_EMMC_DIV_MASK              GENMASK(14, 12)
+#define SCU_CLKSRC1_EMMC_DIV_SHIFT             12
+#define SCU_CLKSRC1_EMMC                       BIT(11)
+
+#define SCU_CLKSRC2_RMII12                     BIT(19)
+#define SCU_CLKSRC2_RMII12_DIV_MASK            GENMASK(18, 16)
+#define SCU_CLKSRC2_RMII12_DIV_SHIFT           16
+#define SCU_CLKSRC2_UART5                      BIT(14)
+
+#define SCU_CLKSRC4_SDIO_EN                    BIT(31)
+#define SCU_CLKSRC4_SDIO_DIV_MASK              GENMASK(30, 28)
+#define SCU_CLKSRC4_SDIO_DIV_SHIFT             28
+#define SCU_CLKSRC4_MAC_DIV_MASK               GENMASK(26, 24)
+#define SCU_CLKSRC4_MAC_DIV_SHIFT              24
+#define SCU_CLKSRC4_RMII34_DIV_MASK            GENMASK(18, 16)
+#define SCU_CLKSRC4_RMII34_DIV_SHIFT           16
+#define SCU_CLKSRC4_PCLK_DIV_MASK              GENMASK(11, 9)
+#define SCU_CLKSRC4_PCLK_DIV_SHIFT             9
+#define SCU_CLKSRC4_SDIO                       BIT(8)
+#define SCU_CLKSRC4_UART6                      BIT(5)
+#define SCU_CLKSRC4_UART4                      BIT(3)
+#define SCU_CLKSRC4_UART3                      BIT(2)
+#define SCU_CLKSRC4_UART2                      BIT(1)
+#define SCU_CLKSRC4_UART1                      BIT(0)
+
+#define SCU_CLKSRC5_UART13                     BIT(12)
+#define SCU_CLKSRC5_UART12                     BIT(11)
+#define SCU_CLKSRC5_UART11                     BIT(10)
+#define SCU_CLKSRC5_UART10                     BIT(9)
+#define SCU_CLKSRC5_UART9                      BIT(8)
+#define SCU_CLKSRC5_UART8                      BIT(7)
+#define SCU_CLKSRC5_UART7                      BIT(6)
+#define SCU_CLKSRC5_HUXCLK_MASK                        GENMASK(5, 3)
+#define SCU_CLKSRC5_HUXCLK_SHIFT               3
+#define SCU_CLKSRC5_UXCLK_MASK                 GENMASK(2, 0)
+#define SCU_CLKSRC5_UXCLK_SHIFT                        0
+
+#define SCU_PINCTRL1_EMMC_MASK                 GENMASK(31, 24)
+#define SCU_PINCTRL1_EMMC_SHIFT                        24
+
+#define SCU_PINCTRL16_MAC4_DRIVING_MASK                GENMASK(3, 2)
+#define SCU_PINCTRL16_MAC4_DRIVING_SHIFT       2
+#define SCU_PINCTRL16_MAC3_DRIVING_MASK                GENMASK(1, 0)
+#define SCU_PINCTRL16_MAC3_DRIVING_SHIFT       0
+
+#define SCU_HWSTRAP1_CPU_AXI_CLK_RATIO         BIT(16)
+#define SCU_HWSTRAP1_VGA_MEM_MASK              GENMASK(14, 13)
+#define SCU_HWSTRAP1_VGA_MEM_SHIFT             13
+#define SCU_HWSTRAP1_AXI_AHB_CLK_RATIO_MASK    GENMASK(12, 11)
+#define SCU_HWSTRAP1_AXI_AHB_CLK_RATIO_SHIFT   11
+#define SCU_HWSTRAP1_CPU_FREQ_MASK             GENMASK(10, 8)
+#define SCU_HWSTRAP1_CPU_FREQ_SHIFT            8
+#define SCU_HWSTRAP1_MAC2_INTF                 BIT(7)
+#define SCU_HWSTRAP1_MAC1_INTF                 BIT(6)
+
+#define SCU_EFUSE_DIS_DP                       BIT(17)
+#define SCU_EFUSE_DIS_VGA                      BIT(14)
+#define SCU_EFUSE_DIS_PCIE_EP                  BIT(13)
+#define SCU_EFUSE_DIS_USB                      BIT(12)
+#define SCU_EFUSE_DIS_RVAS                     BIT(10)
+#define SCU_EFUSE_DIS_VIDEO_DEC                        BIT(9)
+#define SCU_EFUSE_DIS_VIDEO                    BIT(8)
+#define SCU_EFUSE_DIS_PCIE_RC                  BIT(7)
+#define SCU_EFUSE_DIS_CM3                      BIT(6)
+#define SCU_EFUSE_DIS_CA7                      BIT(5)
+
+#define SCU_PLL_RST                            BIT(25)
+#define SCU_PLL_BYPASS                         BIT(24)
+#define SCU_PLL_OFF                            BIT(23)
+#define SCU_PLL_DIV_MASK                       GENMASK(22, 19)
+#define SCU_PLL_DIV_SHIFT                      19
+#define SCU_PLL_DENUM_MASK                     GENMASK(18, 13)
+#define SCU_PLL_DENUM_SHIFT                    13
+#define SCU_PLL_NUM_MASK                       GENMASK(12, 0)
+#define SCU_PLL_NUM_SHIFT                      0
+
+#define SCU_UART_CLKGEN_N_MASK                 GENMASK(17, 8)
+#define SCU_UART_CLKGEN_N_SHIFT                        8
+#define SCU_UART_CLKGEN_R_MASK                 GENMASK(7, 0)
+#define SCU_UART_CLKGEN_R_SHIFT                        0
+
+#define SCU_HUART_CLKGEN_N_MASK                        GENMASK(17, 8)
+#define SCU_HUART_CLKGEN_N_SHIFT               8
+#define SCU_HUART_CLKGEN_R_MASK                        GENMASK(7, 0)
+#define SCU_HUART_CLKGEN_R_SHIFT               0
+
+#define SCU_MISC_CTRL1_UART5_DIV               BIT(12)
+
+#ifndef __ASSEMBLY__
+struct ast2600_scu {
+       uint32_t prot_key1;             /* 0x000 */
+       uint32_t chip_id1;              /* 0x004 */
+       uint32_t rsv_0x08;              /* 0x008 */
+       uint32_t rsv_0x0c;              /* 0x00C */
+       uint32_t prot_key2;             /* 0x010 */
+       uint32_t chip_id2;              /* 0x014 */
+       uint32_t rsv_0x18[10];          /* 0x018 ~ 0x03C */
+       uint32_t modrst_ctrl1;          /* 0x040 */
+       uint32_t modrst_clr1;           /* 0x044 */
+       uint32_t rsv_0x48;              /* 0x048 */
+       uint32_t rsv_0x4C;              /* 0x04C */
+       uint32_t modrst_ctrl2;          /* 0x050 */
+       uint32_t modrst_clr2;           /* 0x054 */
+       uint32_t rsv_0x58;              /* 0x058 */
+       uint32_t rsv_0x5C;              /* 0x05C */
+       uint32_t extrst_sel1;           /* 0x060 */
+       uint32_t sysrst_sts1_1;         /* 0x064 */
+       uint32_t sysrst_sts1_2;         /* 0x068 */
+       uint32_t sysrst_sts1_3;         /* 0x06C */
+       uint32_t extrst_sel2;           /* 0x070 */
+       uint32_t sysrst_sts2_1;         /* 0x074 */
+       uint32_t sysrst_sts2_2;         /* 0x078 */
+       uint32_t stsrst_sts3_2;         /* 0x07C */
+       uint32_t clkgate_ctrl1;         /* 0x080 */
+       uint32_t clkgate_clr1;          /* 0x084 */
+       uint32_t rsv_0x88;              /* 0x088 */
+       uint32_t rsv_0x8C;              /* 0x08C */
+       uint32_t clkgate_ctrl2;         /* 0x090 */
+       uint32_t clkgate_clr2;          /* 0x094 */
+       uint32_t rsv_0x98[10];          /* 0x098 ~ 0x0BC */
+       uint32_t misc_ctrl1;            /* 0x0C0 */
+       uint32_t misc_ctrl2;            /* 0x0C4 */
+       uint32_t debug_ctrl1;           /* 0x0C8 */
+       uint32_t rsv_0xCC;              /* 0x0CC */
+       uint32_t misc_ctrl3;            /* 0x0D0 */
+       uint32_t misc_ctrl4;            /* 0x0D4 */
+       uint32_t debug_ctrl2;           /* 0x0D8 */
+       uint32_t rsv_0xdc[9];           /* 0x0DC ~ 0x0FC */
+       uint32_t dram_hdshk;            /* 0x100 */
+       uint32_t soc_scratch[3];        /* 0x104 ~ 0x10C */
+       uint32_t rsv_0x110[4];          /* 0x110 ~ 0x11C*/
+       uint32_t cpu_scratch_wp;        /* 0x120 */
+       uint32_t rsv_0x124[23];         /* 0x124 */
+       uint32_t smp_boot[12];          /* 0x180 */
+       uint32_t cpu_scratch[20];       /* 0x1b0 */
+       uint32_t hpll;                  /* 0x200 */
+       uint32_t hpll_ext;              /* 0x204 */
+       uint32_t rsv_0x208[2];          /* 0x208 ~ 0x20C */
+       uint32_t apll;                  /* 0x210 */
+       uint32_t apll_ext;              /* 0x214 */
+       uint32_t rsv_0x218[2];          /* 0x218 ~ 0x21C */
+       uint32_t mpll;                  /* 0x220 */
+       uint32_t mpll_ext;              /* 0x224 */
+       uint32_t rsv_0x228[6];          /* 0x228 ~ 0x23C */
+       uint32_t epll;                  /* 0x240 */
+       uint32_t epll_ext;              /* 0x244 */
+       uint32_t rsv_0x248[6];          /* 0x248 ~ 0x25C */
+       uint32_t dpll;                  /* 0x260 */
+       uint32_t dpll_ext;              /* 0x264 */
+       uint32_t rsv_0x268[38];         /* 0x268 ~ 0x2FC */
+       uint32_t clksrc1;               /* 0x300 */
+       uint32_t clksrc2;               /* 0x304 */
+       uint32_t clksrc3;               /* 0x308 */
+       uint32_t rsv_0x30c;             /* 0x30C */
+       uint32_t clksrc4;               /* 0x310 */
+       uint32_t clksrc5;               /* 0x314 */
+       uint32_t rsv_0x318[2];          /* 0x318 ~ 0x31C */
+       uint32_t freq_counter_ctrl1;    /* 0x320 */
+       uint32_t freq_counter_cmp1;     /* 0x324 */
+       uint32_t rsv_0x328[2];          /* 0x328 ~ 0x32C */
+       uint32_t freq_counter_ctrl2;    /* 0x330 */
+       uint32_t freq_counter_cmp2;     /* 0x334 */
+       uint32_t uart_clkgen;           /* 0x338 */
+       uint32_t huart_clkgen;          /* 0x33C */
+       uint32_t mac12_clk_delay;       /* 0x340 */
+       uint32_t rsv_0x344;             /* 0x344 */
+       uint32_t mac12_clk_delay_100M;  /* 0x348 */
+       uint32_t mac12_clk_delay_10M;   /* 0x34C */
+       uint32_t mac34_clk_delay;       /* 0x350 */
+       uint32_t rsv_0x354;             /* 0x354 */
+       uint32_t mac34_clk_delay_100M;  /* 0x358 */
+       uint32_t mac34_clk_delay_10M;   /* 0x35C */
+       uint32_t clkduty_meas_ctrl;     /* 0x360 */
+       uint32_t clkduty1;              /* 0x364 */
+       uint32_t clkduty2;              /* 0x368 */
+       uint32_t clkduty_meas_res;      /* 0x36C */
+       uint32_t clkduty_meas_ctrl2;    /* 0x370 */
+       uint32_t clkduty3;              /* 0x374 */
+       uint32_t rsv_0x378[34];         /* 0x378 ~ 0x3FC */
+       uint32_t pinmux1;               /* 0x400 */
+       uint32_t pinmux2;               /* 0x404 */
+       uint32_t rsv_0x408;             /* 0x408 */
+       uint32_t pinmux3;               /* 0x40C */
+       uint32_t pinmux4;               /* 0x410 */
+       uint32_t pinmux5;               /* 0x414 */
+       uint32_t pinmux6;               /* 0x418 */
+       uint32_t pinmux7;               /* 0x41C */
+       uint32_t rsv_0x420[4];          /* 0x420 ~ 0x42C */
+       uint32_t pinmux8;               /* 0x430 */
+       uint32_t pinmux9;               /* 0x434 */
+       uint32_t pinmux10;              /* 0x438 */
+       uint32_t rsv_0x43c;             /* 0x43C */
+       uint32_t pinmux12;              /* 0x440 */
+       uint32_t pinmux13;              /* 0x444 */
+       uint32_t rsv_0x448[2];          /* 0x448 ~ 0x44C */
+       uint32_t pinmux14;              /* 0x450 */
+       uint32_t pinmux15;              /* 0x454 */
+       uint32_t pinmux16;              /* 0x458 */
+       uint32_t rsv_0x45c[21];         /* 0x45C ~ 0x4AC */
+       uint32_t pinmux17;              /* 0x4B0 */
+       uint32_t pinmux18;              /* 0x4B4 */
+       uint32_t pinmux19;              /* 0x4B8 */
+       uint32_t pinmux20;              /* 0x4BC */
+       uint32_t rsv_0x4c0[5];          /* 0x4C0 ~ 0x4D0 */
+       uint32_t pinmux22;              /* 0x4D4 */
+       uint32_t pinmux23;              /* 0x4D8 */
+       uint32_t rsv_0x4dc[9];          /* 0x4DC ~ 0x4FC */
+       uint32_t hwstrap1;              /* 0x500 */
+       uint32_t hwstrap_clr1;          /* 0x504 */
+       uint32_t hwstrap_prot1;         /* 0x508 */
+       uint32_t rsv_0x50c;             /* 0x50C */
+       uint32_t hwstrap2;              /* 0x510 */
+       uint32_t hwstrap_clr2;          /* 0x514 */
+       uint32_t hwstrap_prot2;         /* 0x518 */
+       uint32_t rsv_0x51c;             /* 0x51C */
+       uint32_t rng_ctrl;              /* 0x520 */
+       uint32_t rng_data;              /* 0x524 */
+       uint32_t rsv_0x528[6];          /* 0x528 ~ 0x53C */
+       uint32_t pwr_save_wakeup_en1;   /* 0x540 */
+       uint32_t pwr_save_wakeup_ctrl1; /* 0x544 */
+       uint32_t rsv_0x548[2];          /* 0x548 */
+       uint32_t pwr_save_wakeup_en2;   /* 0x550 */
+       uint32_t pwr_save_wakeup_ctrl2; /* 0x554 */
+       uint32_t rsv_0x558[2];          /* 0x558 */
+       uint32_t intr1_ctrl_sts;        /* 0x560 */
+       uint32_t rsv_0x564[3];          /* 0x564 */
+       uint32_t intr2_ctrl_sts;        /* 0x570 */
+       uint32_t rsv_0x574[7];          /* 0x574 ~ 0x58C */
+       uint32_t otp_ctrl;              /* 0x590 */
+       uint32_t efuse;                 /* 0x594 */
+       uint32_t rsv_0x598[6];          /* 0x598 */
+       uint32_t chip_unique_id[8];     /* 0x5B0 */
+       uint32_t rsv_0x5e0[8];          /* 0x5E0 ~ 0x5FC */
+       uint32_t disgpio_in_pull_down0; /* 0x610 */
+       uint32_t disgpio_in_pull_down1; /* 0x614 */
+       uint32_t disgpio_in_pull_down2; /* 0x618 */
+       uint32_t disgpio_in_pull_down3; /* 0x61C */
+       uint32_t rsv_0x620[4];          /* 0x620 ~ 0x62C */
+       uint32_t disgpio_in_pull_down4; /* 0x630 */
+       uint32_t disgpio_in_pull_down5; /* 0x634 */
+       uint32_t disgpio_in_pull_down6; /* 0x638 */
+       uint32_t rsv_0x63c[5];          /* 0x63C ~ 0x64C */
+       uint32_t sli_driving_strength;  /* 0x650 */
+       uint32_t rsv_0x654[107];        /* 0x654 ~ 0x7FC */
+       uint32_t ca7_ctrl1;             /* 0x800 */
+       uint32_t ca7_ctrl2;             /* 0x804 */
+       uint32_t ca7_ctrl3;             /* 0x808 */
+       uint32_t ca7_ctrl4;             /* 0x80C */
+       uint32_t rsv_0x810[4];          /* 0x810 ~ 0x81C */
+       uint32_t ca7_parity_chk;        /* 0x820 */
+       uint32_t ca7_parity_clr;        /* 0x824 */
+       uint32_t rsv_0x828[118];        /* 0x828 ~ 0x9FC */
+       uint32_t cm3_ctrl;              /* 0xA00 */
+       uint32_t cm3_base;              /* 0xA04 */
+       uint32_t cm3_imem_addr;         /* 0xA08 */
+       uint32_t cm3_dmem_addr;         /* 0xA0C */
+       uint32_t rsv_0xa10[12];         /* 0xA10 ~ 0xA3C */
+       uint32_t cm3_cache_area;        /* 0xA40 */
+       uint32_t cm3_cache_invd_ctrl;   /* 0xA44 */
+       uint32_t cm3_cache_func_ctrl;   /* 0xA48 */
+       uint32_t rsv_0xa4c[108];        /* 0xA4C ~ 0xBFC */
+       uint32_t pci_cfg[3];            /* 0xC00 */
+       uint32_t rsv_0xc0c[5];          /* 0xC0C ~ 0xC1C */
+       uint32_t pcie_cfg;              /* 0xC20 */
+       uint32_t mmio_decode;           /* 0xC24 */
+       uint32_t reloc_ctrl_decode[2];  /* 0xC28 */
+       uint32_t rsv_0xc30[4];          /* 0xC30 ~ 0xC3C */
+       uint32_t mbox_decode;           /* 0xC40 */
+       uint32_t shared_sram_decode[2]; /* 0xC44 */
+       uint32_t bmc_rev_id;            /* 0xC4C */
+       uint32_t rsv_0xc50[5];          /* 0xC50 ~ 0xC60 */
+       uint32_t bmc_device_id;         /* 0xC64 */
+       uint32_t rsv_0xc68[102];        /* 0xC68 ~ 0xDFC */
+       uint32_t vga_scratch1;          /* 0xE00 */
+       uint32_t vga_scratch2;          /* 0xE04 */
+       uint32_t vga_scratch3;          /* 0xE08 */
+       uint32_t vga_scratch4;          /* 0xE0C */
+       uint32_t rsv_0xe10[4];          /* 0xE10 ~ 0xE1C */
+       uint32_t vga_scratch5;          /* 0xE20 */
+       uint32_t vga_scratch6;          /* 0xE24 */
+       uint32_t vga_scratch7;          /* 0xE28 */
+       uint32_t vga_scratch8;          /* 0xE2C */
+       uint32_t rsv_0xe30[52];         /* 0xE30 ~ 0xEFC */
+       uint32_t wr_prot1;              /* 0xF00 */
+       uint32_t wr_prot2;              /* 0xF04 */
+       uint32_t wr_prot3;              /* 0xF08 */
+       uint32_t wr_prot4;              /* 0xF0C */
+       uint32_t wr_prot5;              /* 0xF10 */
+       uint32_t wr_prot6;              /* 0xF18 */
+       uint32_t wr_prot7;              /* 0xF1C */
+       uint32_t wr_prot8;              /* 0xF20 */
+       uint32_t wr_prot9;              /* 0xF24 */
+       uint32_t rsv_0xf28[2];          /* 0xF28 ~ 0xF2C */
+       uint32_t wr_prot10;             /* 0xF30 */
+       uint32_t wr_prot11;             /* 0xF34 */
+       uint32_t wr_prot12;             /* 0xF38 */
+       uint32_t wr_prot13;             /* 0xF3C */
+       uint32_t wr_prot14;             /* 0xF40 */
+       uint32_t rsv_0xf44;             /* 0xF44 */
+       uint32_t wr_prot15;             /* 0xF48 */
+       uint32_t rsv_0xf4c[5];          /* 0xF4C ~ 0xF5C */
+       uint32_t wr_prot16;             /* 0xF60 */
+};
+#endif
+#endif
diff --git a/arch/arm/include/asm/arch-aspeed/sdram_ast2600.h b/arch/arm/include/asm/arch-aspeed/sdram_ast2600.h
new file mode 100644 (file)
index 0000000..d2408c0
--- /dev/null
@@ -0,0 +1,163 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) Aspeed Technology Inc.
+ */
+#ifndef _ASM_ARCH_SDRAM_AST2600_H
+#define _ASM_ARCH_SDRAM_AST2600_H
+
+/* keys for unlocking HW */
+#define SDRAM_UNLOCK_KEY               0xFC600309
+#define SDRAM_VIDEO_UNLOCK_KEY         0x00440003
+
+/* Fixed priority DRAM Requests mask */
+#define REQ_PRI_VGA_HW_CURSOR_R         0
+#define REQ_PRI_VGA_CRT_R               1
+#define REQ_PRI_SOC_DISPLAY_CTRL_R      2
+#define REQ_PRI_PCIE_BUS1_RW            3
+#define REQ_PRI_VIDEO_HIGH_PRI_W        4
+#define REQ_PRI_CPU_RW                  5
+#define REQ_PRI_SLI_RW                  6
+#define REQ_PRI_PCIE_BUS2_RW            7
+#define REQ_PRI_USB2_0_HUB_EHCI1_DMA_RW 8
+#define REQ_PRI_USB2_0_DEV_EHCI2_DMA_RW 9
+#define REQ_PRI_USB1_1_UHCI_HOST_RW     10
+#define REQ_PRI_AHB_BUS_RW              11
+#define REQ_PRI_CM3_DATA_RW             12
+#define REQ_PRI_CM3_INST_R              13
+#define REQ_PRI_MAC0_DMA_RW             14
+#define REQ_PRI_MAC1_DMA_RW             15
+#define REQ_PRI_SDIO_DMA_RW             16
+#define REQ_PRI_PILOT_ENGINE_RW         17
+#define REQ_PRI_XDMA1_RW                18
+#define REQ_PRI_MCTP1_RW                19
+#define REQ_PRI_VIDEO_FLAG_RW           20
+#define REQ_PRI_VIDEO_LOW_PRI_W         21
+#define REQ_PRI_2D_ENGINE_DATA_RW       22
+#define REQ_PRI_ENC_ENGINE_RW           23
+#define REQ_PRI_MCTP2_RW                24
+#define REQ_PRI_XDMA2_RW                25
+#define REQ_PRI_ECC_RSA_RW              26
+
+#define MCR30_RESET_DLL_DELAY_EN       BIT(4)
+#define MCR30_MODE_REG_SEL_SHIFT       1
+#define MCR30_MODE_REG_SEL_MASK                GENMASK(3, 1)
+#define MCR30_SET_MODE_REG             BIT(0)
+
+#define MCR30_SET_MR(mr) ((mr << MCR30_MODE_REG_SEL_SHIFT) | MCR30_SET_MODE_REG)
+
+#define MCR34_SELF_REFRESH_STATUS_MASK GENMASK(30, 28)
+
+#define MCR34_ODT_DELAY_SHIFT          12
+#define MCR34_ODT_DELAY_MASK           GENMASK(15, 12)
+#define MCR34_ODT_EXT_SHIFT            10
+#define MCR34_ODT_EXT_MASK             GENMASK(11, 10)
+#define MCR34_ODT_AUTO_ON              BIT(9)
+#define MCR34_ODT_EN                   BIT(8)
+#define MCR34_RESETN_DIS               BIT(7)
+#define MCR34_MREQI_DIS                        BIT(6)
+#define MCR34_MREQ_BYPASS_DIS          BIT(5)
+#define MCR34_RGAP_CTRL_EN             BIT(4)
+#define MCR34_CKE_OUT_IN_SELF_REF_DIS  BIT(3)
+#define MCR34_FOURCE_SELF_REF_EN       BIT(2)
+#define MCR34_AUTOPWRDN_EN             BIT(1)
+#define MCR34_CKE_EN                   BIT(0)
+
+#define MCR38_RW_MAX_GRANT_CNT_RQ_SHIFT        16
+#define MCR38_RW_MAX_GRANT_CNT_RQ_MASK GENMASK(20, 16)
+
+/* default request queued limitation mask (0xFFBBFFF4) */
+#define MCR3C_DEFAULT_MASK                                                     \
+       ~(REQ_PRI_VGA_HW_CURSOR_R | REQ_PRI_VGA_CRT_R | REQ_PRI_PCIE_BUS1_RW | \
+         REQ_PRI_XDMA1_RW | REQ_PRI_2D_ENGINE_DATA_RW)
+
+#define MCR50_RESET_ALL_INTR           BIT(31)
+#define SDRAM_CONF_ECC_AUTO_SCRUBBING  BIT(9)
+#define SDRAM_CONF_SCRAMBLE            BIT(8)
+#define SDRAM_CONF_ECC_EN              BIT(7)
+#define SDRAM_CONF_DUALX8              BIT(5)
+#define SDRAM_CONF_DDR4                        BIT(4)
+#define SDRAM_CONF_VGA_SIZE_SHIFT      2
+#define SDRAM_CONF_VGA_SIZE_MASK       GENMASK(3, 2)
+#define SDRAM_CONF_CAP_SHIFT           0
+#define SDRAM_CONF_CAP_MASK            GENMASK(1, 0)
+
+#define SDRAM_CONF_CAP_256M            0
+#define SDRAM_CONF_CAP_512M            1
+#define SDRAM_CONF_CAP_1024M           2
+#define SDRAM_CONF_CAP_2048M           3
+#define SDRAM_CONF_ECC_SETUP           (SDRAM_CONF_ECC_AUTO_SCRUBBING | SDRAM_CONF_ECC_EN)
+
+#define SDRAM_MISC_DDR4_TREFRESH       (1 << 3)
+
+#define SDRAM_PHYCTRL0_PLL_LOCKED      BIT(4)
+#define SDRAM_PHYCTRL0_NRST            BIT(2)
+#define SDRAM_PHYCTRL0_INIT            BIT(0)
+
+/* MCR0C */
+#define SDRAM_REFRESH_PERIOD_ZQCS_SHIFT        16
+#define SDRAM_REFRESH_PERIOD_ZQCS_MASK GENMASK(31, 16)
+#define SDRAM_REFRESH_PERIOD_SHIFT     8
+#define SDRAM_REFRESH_PERIOD_MASK      GENMASK(15, 8)
+#define SDRAM_REFRESH_ZQCS_EN          BIT(7)
+#define SDRAM_RESET_DLL_ZQCL_EN                BIT(6)
+#define SDRAM_LOW_PRI_REFRESH_EN       BIT(5)
+#define SDRAM_FORCE_PRECHARGE_EN       BIT(4)
+#define SDRAM_REFRESH_EN               BIT(0)
+
+#define SDRAM_TEST_LEN_SHIFT           4
+#define SDRAM_TEST_LEN_MASK            0xfffff
+#define SDRAM_TEST_START_ADDR_SHIFT    24
+#define SDRAM_TEST_START_ADDR_MASK     0x3f
+
+#define SDRAM_TEST_EN                  (1 << 0)
+#define SDRAM_TEST_MODE_SHIFT          1
+#define SDRAM_TEST_MODE_MASK           (0x3 << SDRAM_TEST_MODE_SHIFT)
+#define SDRAM_TEST_MODE_WO             (0x0 << SDRAM_TEST_MODE_SHIFT)
+#define SDRAM_TEST_MODE_RB             (0x1 << SDRAM_TEST_MODE_SHIFT)
+#define SDRAM_TEST_MODE_RW             (0x2 << SDRAM_TEST_MODE_SHIFT)
+
+#define SDRAM_TEST_GEN_MODE_SHIFT      3
+#define SDRAM_TEST_GEN_MODE_MASK       (7 << SDRAM_TEST_GEN_MODE_SHIFT)
+#define SDRAM_TEST_TWO_MODES           (1 << 6)
+#define SDRAM_TEST_ERRSTOP             (1 << 7)
+#define SDRAM_TEST_DONE                        (1 << 12)
+#define SDRAM_TEST_FAIL                        (1 << 13)
+
+#define SDRAM_AC_TRFC_SHIFT            0
+#define SDRAM_AC_TRFC_MASK             0xff
+
+#define SDRAM_ECC_RANGE_ADDR_MASK      GENMASK(30, 20)
+#define SDRAM_ECC_RANGE_ADDR_SHIFT     20
+
+#ifndef __ASSEMBLY__
+struct ast2600_sdrammc_regs {
+       u32 protection_key;             /* offset 0x00 */
+       u32 config;                     /* offset 0x04 */
+       u32 gm_protection_key;          /* offset 0x08 */
+       u32 refresh_timing;             /* offset 0x0C */
+       u32 ac_timing[4];               /* offset 0x10 ~ 0x1C */
+       u32 mr01_mode_setting;          /* offset 0x20 */
+       u32 mr23_mode_setting;          /* offset 0x24 */
+       u32 mr45_mode_setting;          /* offset 0x28 */
+       u32 mr6_mode_setting;           /* offset 0x2C */
+       u32 mode_setting_control;       /* offset 0x30 */
+       u32 power_ctrl;                 /* offset 0x34 */
+       u32 arbitration_ctrl;           /* offset 0x38 */
+       u32 req_limit_mask;             /* offset 0x3C */
+       u32 max_grant_len[4];           /* offset 0x40 ~ 0x4C */
+       u32 intr_ctrl;                  /* offset 0x50 */
+       u32 ecc_range_ctrl;             /* offset 0x54 */
+       u32 first_ecc_err_addr;         /* offset 0x58 */
+       u32 last_ecc_err_addr;          /* offset 0x5C */
+       u32 phy_ctrl[4];                /* offset 0x60 ~ 0x6C */
+       u32 ecc_test_ctrl;              /* offset 0x70 */
+       u32 test_addr;                  /* offset 0x74 */
+       u32 test_fail_dq_bit;           /* offset 0x78 */
+       u32 test_init_val;              /* offset 0x7C */
+       u32 req_input_ctrl;             /* offset 0x80 */
+       u32 req_high_pri_ctrl;          /* offset 0x84 */
+       u32 reserved0[6];               /* offset 0x88 ~ 0x9C */
+};
+#endif  /* __ASSEMBLY__ */
+
+#endif  /* _ASM_ARCH_SDRAM_AST2600_H */
diff --git a/arch/arm/include/asm/arch-aspeed/wdt_ast2600.h b/arch/arm/include/asm/arch-aspeed/wdt_ast2600.h
new file mode 100644 (file)
index 0000000..96e8ca0
--- /dev/null
@@ -0,0 +1,129 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2020 Aspeed Technology Inc.
+ */
+
+#ifndef _ASM_ARCH_WDT_AST2600_H
+#define _ASM_ARCH_WDT_AST2600_H
+
+#define WDT_BASE                       0x1e785000
+
+/*
+ * Special value that needs to be written to counter_restart register to
+ * (re)start the timer
+ */
+#define WDT_COUNTER_RESTART_VAL                0x4755
+
+/* reset mode */
+#define WDT_RESET_MODE_SOC             0
+#define WDT_RESET_MODE_CHIP            1
+#define WDT_RESET_MODE_CPU             2
+
+/* bit-fields of WDT control register */
+#define WDT_CTRL_2ND_BOOT              BIT(7)
+#define WDT_CTRL_RESET_MODE_MASK       GENMASK(6, 5)
+#define WDT_CTRL_RESET_MODE_SHIFT      5
+#define WDT_CTRL_CLK1MHZ               BIT(4)
+#define WDT_CTRL_RESET                 BIT(1)
+#define WDT_CTRL_EN                    BIT(0)
+
+/* bit-fields of WDT reset mask1 register */
+#define WDT_RESET_MASK1_RVAS           BIT(25)
+#define WDT_RESET_MASK1_GPIO1          BIT(24)
+#define WDT_RESET_MASK1_XDMA2          BIT(23)
+#define WDT_RESET_MASK1_XDMA1          BIT(22)
+#define WDT_RESET_MASK1_MCTP2          BIT(21)
+#define WDT_RESET_MASK1_MCTP1          BIT(20)
+#define WDT_RESET_MASK1_JTAG1          BIT(19)
+#define WDT_RESET_MASK1_SD_SDIO1       BIT(18)
+#define WDT_RESET_MASK1_MAC2           BIT(17)
+#define WDT_RESET_MASK1_MAC1           BIT(16)
+#define WDT_RESET_MASK1_GPMCU          BIT(15)
+#define WDT_RESET_MASK1_DPMCU          BIT(14)
+#define WDT_RESET_MASK1_DP             BIT(13)
+#define WDT_RESET_MASK1_HAC            BIT(12)
+#define WDT_RESET_MASK1_VIDEO          BIT(11)
+#define WDT_RESET_MASK1_CRT            BIT(10)
+#define WDT_RESET_MASK1_GCRT           BIT(9)
+#define WDT_RESET_MASK1_USB11_UHCI     BIT(8)
+#define WDT_RESET_MASK1_USB_PORTA      BIT(7)
+#define WDT_RESET_MASK1_USB_PORTB      BIT(6)
+#define WDT_RESET_MASK1_COPROC         BIT(5)
+#define WDT_RESET_MASK1_SOC            BIT(4)
+#define WDT_RESET_MASK1_SLI            BIT(3)
+#define WDT_RESET_MASK1_AHB            BIT(2)
+#define WDT_RESET_MASK1_SDRAM          BIT(1)
+#define WDT_RESET_MASK1_ARM            BIT(0)
+
+/* bit-fields of WDT reset mask2 register */
+#define WDT_RESET_MASK2_ESPI           BIT(26)
+#define WDT_RESET_MASK2_I3C_BUS8       BIT(25)
+#define WDT_RESET_MASK2_I3C_BUS7       BIT(24)
+#define WDT_RESET_MASK2_I3C_BUS6       BIT(23)
+#define WDT_RESET_MASK2_I3C_BUS5       BIT(22)
+#define WDT_RESET_MASK2_I3C_BUS4       BIT(21)
+#define WDT_RESET_MASK2_I3C_BUS3       BIT(20)
+#define WDT_RESET_MASK2_I3C_BUS2       BIT(19)
+#define WDT_RESET_MASK2_I3C_BUS1       BIT(18)
+#define WDT_RESET_MASK2_I3C_GLOBAL     BIT(17)
+#define WDT_RESET_MASK2_I2C            BIT(16)
+#define WDT_RESET_MASK2_FSI            BIT(15)
+#define WDT_RESET_MASK2_ADC            BIT(14)
+#define WDT_RESET_MASK2_PWM            BIT(13)
+#define WDT_RESET_MASK2_PECI           BIT(12)
+#define WDT_RESET_MASK2_LPC            BIT(11)
+#define WDT_RESET_MASK2_MDC_MDIO       BIT(10)
+#define WDT_RESET_MASK2_GPIO2          BIT(9)
+#define WDT_RESET_MASK2_JTAG2          BIT(8)
+#define WDT_RESET_MASK2_SD_SDIO2       BIT(7)
+#define WDT_RESET_MASK2_MAC4           BIT(6)
+#define WDT_RESET_MASK2_MAC3           BIT(5)
+#define WDT_RESET_MASK2_SOC            BIT(4)
+#define WDT_RESET_MASK2_SLI2           BIT(3)
+#define WDT_RESET_MASK2_AHB2           BIT(2)
+#define WDT_RESET_MASK2_SPI1_SPI2      BIT(1)
+#define WDT_RESET_MASK2_ARM            BIT(0)
+
+#define WDT_RESET_MASK1_DEFAULT                                                \
+       (WDT_RESET_MASK1_RVAS | WDT_RESET_MASK1_GPIO1 |                 \
+        WDT_RESET_MASK1_JTAG1 | WDT_RESET_MASK1_SD_SDIO1 |             \
+        WDT_RESET_MASK1_MAC2 | WDT_RESET_MASK1_MAC1 |                  \
+        WDT_RESET_MASK1_HAC | WDT_RESET_MASK1_VIDEO |                  \
+        WDT_RESET_MASK1_CRT | WDT_RESET_MASK1_GCRT |                   \
+        WDT_RESET_MASK1_USB11_UHCI | WDT_RESET_MASK1_USB_PORTA |       \
+        WDT_RESET_MASK1_USB_PORTB | WDT_RESET_MASK1_COPROC |           \
+        WDT_RESET_MASK1_SOC | WDT_RESET_MASK1_ARM)
+
+#define WDT_RESET_MASK2_DEFAULT                                                \
+       (WDT_RESET_MASK2_I3C_BUS8 | WDT_RESET_MASK2_I3C_BUS7 |          \
+        WDT_RESET_MASK2_I3C_BUS6 | WDT_RESET_MASK2_I3C_BUS5 |          \
+        WDT_RESET_MASK2_I3C_BUS4 | WDT_RESET_MASK2_I3C_BUS3 |          \
+        WDT_RESET_MASK2_I3C_BUS2 | WDT_RESET_MASK2_I3C_BUS1 |          \
+        WDT_RESET_MASK2_I3C_GLOBAL | WDT_RESET_MASK2_I2C |             \
+        WDT_RESET_MASK2_FSI | WDT_RESET_MASK2_ADC |                    \
+        WDT_RESET_MASK2_PWM | WDT_RESET_MASK2_PECI |                   \
+        WDT_RESET_MASK2_LPC | WDT_RESET_MASK2_MDC_MDIO |               \
+        WDT_RESET_MASK2_GPIO2 | WDT_RESET_MASK2_JTAG2 |                \
+        WDT_RESET_MASK2_SD_SDIO2 | WDT_RESET_MASK2_MAC4 |              \
+        WDT_RESET_MASK2_MAC3 | WDT_RESET_MASK2_SOC |                   \
+        WDT_RESET_MASK2_ARM)
+
+#ifndef __ASSEMBLY__
+struct ast2600_wdt {
+       u32 counter_status;
+       u32 counter_reload_val;
+       u32 counter_restart;
+       u32 ctrl;
+       u32 timeout_status;
+       u32 clr_timeout_status;
+       u32 reset_width;
+       u32 reset_mask1;
+       u32 reset_mask2;
+       u32 sw_reset_ctrl;
+       u32 sw_reset_mask1;
+       u32 sw_reset_mask2;
+       u32 sw_reset_disable;
+};
+#endif  /* __ASSEMBLY__ */
+
+#endif /* _ASM_ARCH_WDT_AST2600_H */
index 6ecb876..7609367 100644 (file)
@@ -3,7 +3,8 @@
        !defined(CONFIG_ARCH_BCM6858) && !defined(CONFIG_ARCH_BCM63158) && \
        !defined(CONFIG_ARCH_ROCKCHIP) && !defined(CONFIG_ARCH_ASPEED) && \
        !defined(CONFIG_ARCH_U8500) && !defined(CONFIG_CORTINA_PLATFORM) && \
-       !defined(CONFIG_TARGET_BCMNS3) && !defined(CONFIG_TARGET_TOTAL_COMPUTE)
+       !defined(CONFIG_TARGET_BCMNS3) && !defined(CONFIG_TARGET_TOTAL_COMPUTE) && \
+       !defined(CONFIG_ARCH_QEMU)
 #include <asm/arch/gpio.h>
 #endif
 #include <asm-generic/gpio.h>
index 4f021ba..9a725f1 100644 (file)
@@ -9,6 +9,11 @@ config SYS_SOC
 config SYS_TEXT_BASE
        default 0x00000000
 
+choice
+       prompt "Aspeed SoC select"
+       depends on ARCH_ASPEED
+       default ASPEED_AST2500
+
 config ASPEED_AST2500
        bool "Support Aspeed AST2500 SoC"
        depends on DM_RESET
@@ -18,6 +23,21 @@ config ASPEED_AST2500
          It is used as Board Management Controller on many server boards,
          which is enabled by support of LPC and eSPI peripherals.
 
+config ASPEED_AST2600
+       bool "Support Aspeed AST2600 SoC"
+       select CPU_V7A
+       select CPU_V7_HAS_NONSEC
+       select SYS_ARCH_TIMER
+       select SUPPORT_SPL
+       select ENABLE_ARM_SOC_BOOT0_HOOK
+       help
+         The Aspeed AST2600 is a ARM-based SoC with Cortex-A7 CPU.
+         It is used as Board Management Controller on many server boards,
+         which is enabled by support of LPC and eSPI peripherals.
+
+endchoice
+
 source "arch/arm/mach-aspeed/ast2500/Kconfig"
+source "arch/arm/mach-aspeed/ast2600/Kconfig"
 
 endif
index 33f65b5..42599c1 100644 (file)
@@ -4,3 +4,4 @@
 
 obj-$(CONFIG_ARCH_ASPEED) += ast_wdt.o
 obj-$(CONFIG_ASPEED_AST2500) += ast2500/
+obj-$(CONFIG_ASPEED_AST2600) += ast2600/
diff --git a/arch/arm/mach-aspeed/ast2600/Kconfig b/arch/arm/mach-aspeed/ast2600/Kconfig
new file mode 100644 (file)
index 0000000..f3a5338
--- /dev/null
@@ -0,0 +1,17 @@
+if ASPEED_AST2600
+
+config SYS_CPU
+       default "armv7"
+
+config TARGET_EVB_AST2600
+       bool "EVB-AST2600"
+       depends on ASPEED_AST2600
+       help
+         EVB-AST2600 is Aspeed evaluation board for AST2600A0 chip.
+         It has 512M of RAM, 32M of SPI flash, two Ethernet ports,
+         4 Serial ports, 4 USB ports, VGA port, PCIe, SD card slot,
+         20 pin JTAG, pinouts for 14 I2Cs, 3 SPIs and eSPI, 8 PWMs.
+
+source "board/aspeed/evb_ast2600/Kconfig"
+
+endif
diff --git a/arch/arm/mach-aspeed/ast2600/Makefile b/arch/arm/mach-aspeed/ast2600/Makefile
new file mode 100644 (file)
index 0000000..448d320
--- /dev/null
@@ -0,0 +1,2 @@
+obj-y   += lowlevel_init.o board_common.o
+obj-$(CONFIG_SPL_BUILD) += spl.o
diff --git a/arch/arm/mach-aspeed/ast2600/board_common.c b/arch/arm/mach-aspeed/ast2600/board_common.c
new file mode 100644 (file)
index 0000000..a53e163
--- /dev/null
@@ -0,0 +1,105 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) Aspeed Technology Inc.
+ */
+#include <common.h>
+#include <dm.h>
+#include <ram.h>
+#include <timer.h>
+#include <asm/io.h>
+#include <asm/arch/timer.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <dm/uclass.h>
+#include <asm/arch/scu_ast2600.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Memory Control registers */
+#define MCR_BASE                       0x1e6e0000
+#define MCR_CONF                       (MCR_BASE + 0x004)
+
+/* bit fields of MCR_CONF */
+#define MCR_CONF_ECC_EN                        BIT(7)
+#define MCR_CONF_VGA_MEMSZ_MASK                GENMASK(3, 2)
+#define MCR_CONF_VGA_MEMSZ_SHIFT       2
+#define MCR_CONF_MEMSZ_MASK            GENMASK(1, 0)
+#define MCR_CONF_MEMSZ_SHIFT           0
+
+int dram_init(void)
+{
+       int ret;
+       struct udevice *dev;
+       struct ram_info ram;
+
+       ret = uclass_get_device(UCLASS_RAM, 0, &dev);
+       if (ret) {
+               debug("cannot get DRAM driver\n");
+               return ret;
+       }
+
+       ret = ram_get_info(dev, &ram);
+       if (ret) {
+               debug("cannot get DRAM information\n");
+               return ret;
+       }
+
+       gd->ram_size = ram.size;
+       return 0;
+}
+
+int board_init(void)
+{
+       int i = 0, rc;
+       struct udevice *dev;
+
+       gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
+
+       while (1) {
+               rc = uclass_get_device(UCLASS_MISC, i++, &dev);
+               if (rc)
+                       break;
+       }
+
+       return 0;
+}
+
+void board_add_ram_info(int use_default)
+{
+       int rc;
+       uint32_t conf;
+       uint32_t ecc, act_size, vga_rsvd;
+       struct udevice *scu_dev;
+       struct ast2600_scu *scu;
+
+       rc = uclass_get_device_by_driver(UCLASS_CLK,
+                                        DM_DRIVER_GET(aspeed_ast2600_scu), &scu_dev);
+       if (rc) {
+               debug("%s: cannot find SCU device, rc=%d\n", __func__, rc);
+               return;
+       }
+
+       scu = devfdt_get_addr_ptr(scu_dev);
+       if (IS_ERR_OR_NULL(scu)) {
+               debug("%s: cannot get SCU address pointer\n", __func__);
+               return;
+       }
+
+       conf = readl(MCR_CONF);
+
+       ecc = conf & MCR_CONF_ECC_EN;
+       act_size = 0x100 << ((conf & MCR_CONF_MEMSZ_MASK) >> MCR_CONF_MEMSZ_SHIFT);
+       vga_rsvd = 0x8 << ((conf & MCR_CONF_VGA_MEMSZ_MASK) >> MCR_CONF_VGA_MEMSZ_SHIFT);
+
+       /* no VGA reservation if efuse VGA disable bit is set */
+       if (readl(scu->efuse) & SCU_EFUSE_DIS_VGA)
+               vga_rsvd = 0;
+
+       printf(" (capacity:%d MiB, VGA:%d MiB), ECC %s", act_size,
+              vga_rsvd, (ecc) ? "on" : "off");
+}
+
+void enable_caches(void)
+{
+       /* get rid of the warning message */
+}
diff --git a/arch/arm/mach-aspeed/ast2600/lowlevel_init.S b/arch/arm/mach-aspeed/ast2600/lowlevel_init.S
new file mode 100644 (file)
index 0000000..594963d
--- /dev/null
@@ -0,0 +1,233 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) ASPEED Technology Inc.
+ */
+#include <config.h>
+#include <asm/armv7.h>
+#include <linux/linkage.h>
+#include <asm/arch/scu_ast2600.h>
+
+/* SCU register offsets */
+#define SCU_BASE               0x1e6e2000
+#define SCU_PROT_KEY1          (SCU_BASE + 0x000)
+#define SCU_PROT_KEY2          (SCU_BASE + 0x010)
+#define SCU_SMP_BOOT           (SCU_BASE + 0x180)
+#define SCU_HWSTRAP1           (SCU_BASE + 0x510)
+#define SCU_CA7_PARITY_CHK     (SCU_BASE + 0x820)
+#define SCU_CA7_PARITY_CLR     (SCU_BASE + 0x824)
+#define SCU_MMIO_DEC           (SCU_BASE + 0xc24)
+
+/* FMC SPI register offsets */
+#define FMC_BASE               0x1e620000
+#define FMC_CE0_CTRL           (FMC_BASE + 0x010)
+#define FMC_SW_RST_CTRL                (FMC_BASE + 0x050)
+#define FMC_WDT1_CTRL_MODE     (FMC_BASE + 0x060)
+#define FMC_WDT2_CTRL_MODE     (FMC_BASE + 0x064)
+
+/*
+ * The SMP mailbox provides a space with few instructions in it
+ * for secondary cores to execute on and wait for the signal of
+ * SMP core bring up.
+ *
+ *       SMP mailbox
+ * +----------------------+
+ * |                      |
+ * | mailbox insn. for    |
+ * | cpuN polling SMP go  |
+ * |                      |
+ * +----------------------+ 0xC
+ * | mailbox ready signal |
+ * +----------------------+ 0x8
+ * | cpuN GO signal       |
+ * +----------------------+ 0x4
+ * | cpuN entrypoint      |
+ * +----------------------+ SMP_MAILBOX_BASE
+ */
+#define SMP_MBOX_BASE          (SCU_SMP_BOOT)
+#define SMP_MBOX_FIELD_ENTRY   (SMP_MBOX_BASE + 0x0)
+#define SMP_MBOX_FIELD_GOSIGN  (SMP_MBOX_BASE + 0x4)
+#define SMP_MBOX_FIELD_READY   (SMP_MBOX_BASE + 0x8)
+#define SMP_MBOX_FIELD_POLLINSN        (SMP_MBOX_BASE + 0xc)
+
+.macro scu_unlock
+       movw    r0, #(SCU_UNLOCK_KEY & 0xffff)
+       movt    r0, #(SCU_UNLOCK_KEY >> 16)
+
+       ldr     r1, =SCU_PROT_KEY1
+       str     r0, [r1]
+       ldr     r1, =SCU_PROT_KEY2
+       str     r0, [r1]
+.endm
+
+.macro timer_init
+       ldr     r1, =SCU_HWSTRAP1
+       ldr     r1, [r1]
+       and     r1, #0x700
+       lsr     r1, #0x8
+
+       /* 1.2GHz */
+       cmp     r1, #0x0
+       movweq  r0, #0x8c00
+       movteq  r0, #0x4786
+
+       /* 1.6GHz */
+       cmp     r1, #0x1
+       movweq  r0, #0x1000
+       movteq  r0, #0x5f5e
+
+       /* 1.2GHz */
+       cmp     r1, #0x2
+       movweq  r0, #0x8c00
+       movteq  r0, #0x4786
+
+       /* 1.6GHz */
+       cmp     r1, #0x3
+       movweq  r0, #0x1000
+       movteq  r0, #0x5f5e
+
+       /* 800MHz */
+       cmp     r1, #0x4
+       movwge  r0, #0x0800
+       movtge  r0, #0x2faf
+
+       mcr     p15, 0, r0, c14, c0, 0  @; update CNTFRQ
+.endm
+
+
+.globl lowlevel_init
+
+lowlevel_init:
+#if defined(CONFIG_SPL) && !defined(CONFIG_SPL_BUILD)
+       mov     pc, lr
+#else
+       /* setup ARM arch timer frequency */
+       timer_init
+
+       /* reset SMP mailbox as early as possible */
+       mov     r0, #0x0
+       ldr     r1, =SMP_MBOX_FIELD_READY
+       str     r0, [r1]
+
+       /* set ACTLR.SMP to enable cache use */
+       mrc     p15, 0, r0, c1, c0, 1
+       orr     r0, #0x40
+       mcr     p15, 0, r0, c1, c0, 1
+
+       /*
+        * we treat cpu0 as the primary core and
+        * put secondary core (cpuN) to sleep
+        */
+       mrc   p15, 0, r0, c0, c0, 5     @; Read CPU ID register
+       ands  r0, #0xff                 @; Mask off, leaving the CPU ID field
+       movw  r2, #0xab00
+       movt  r2, #0xabba
+       orr   r2, r0
+
+       beq   do_primary_core_setup
+
+       /* hold cpuN until mailbox is ready */
+poll_mailbox_ready:
+       wfe
+       ldr     r0, =SMP_MBOX_FIELD_READY
+       ldr     r0, [r0]
+       movw    r1, #0xcafe
+       movt    r1, #0xbabe
+       cmp     r1, r0
+       bne     poll_mailbox_ready
+
+       /* parameters for relocated SMP go polling insn. */
+       ldr     r0, =SMP_MBOX_FIELD_GOSIGN
+       ldr     r1, =SMP_MBOX_FIELD_ENTRY
+
+       /* no return */
+       ldr     pc, =SMP_MBOX_FIELD_POLLINSN
+
+do_primary_core_setup:
+       scu_unlock
+
+       /* MMIO decode setting */
+       ldr     r0, =SCU_MMIO_DEC
+       mov     r1, #0x2000
+       str     r1, [r0]
+
+       /* enable CA7 cache parity check */
+       mov     r0, #0
+       ldr     r1, =SCU_CA7_PARITY_CLR
+       str     r0, [r1]
+
+       mov     r0, #0x1
+       ldr     r1, =SCU_CA7_PARITY_CHK
+       str     r0, [r1]
+
+       /* do not fill FMC50[1] if boot from eMMC */
+       ldr     r0, =SCU_HWSTRAP1
+       ldr     r1, [r0]
+       ands    r1, #0x04
+       bne     skip_fill_wip_bit
+
+       /* fill FMC50[1] for waiting WIP idle */
+       mov     r0, #0x02
+       ldr     r1, =FMC_SW_RST_CTRL
+       str     r0, [r1]
+
+skip_fill_wip_bit:
+       /* disable FMC WDT for SPI address mode detection */
+       mov     r0, #0
+       ldr     r1, =FMC_WDT1_CTRL_MODE
+       str     r0, [r1]
+
+       /* relocate mailbox insn. for cpuN polling SMP go signal */
+       adrl    r0, mailbox_insn
+       adrl    r1, mailbox_insn_end
+
+       ldr     r2, =#SMP_MBOX_FIELD_POLLINSN
+
+relocate_mailbox_insn:
+       ldr     r3, [r0], #0x4
+       str     r3, [r2], #0x4
+       cmp     r0, r1
+       bne     relocate_mailbox_insn
+
+       /* reset SMP go sign */
+       mov     r0, #0
+       ldr     r1, =SMP_MBOX_FIELD_GOSIGN
+       str     r0, [r1]
+
+       /* notify cpuN mailbox is ready */
+       movw    r0, #0xCAFE
+       movt    r0, #0xBABE
+       ldr     r1, =SMP_MBOX_FIELD_READY
+       str     r0, [r1]
+       sev
+
+       /* back to arch calling code */
+       mov     pc, lr
+
+/*
+ * insn. inside mailbox to poll SMP go signal.
+ *
+ * Note that as this code will be relocated, any
+ * pc-relative assembly should NOT be used.
+ */
+mailbox_insn:
+       /*
+        * r0 ~ r3 are parameters:
+        *  r0 = SMP_MBOX_FIELD_GOSIGN
+        *  r1 = SMP_MBOX_FIELD_ENTRY
+        *  r2 = per-cpu go sign value
+        *  r3 = no used now
+        */
+poll_mailbox_smp_go:
+       wfe
+       ldr     r4, [r0]
+       cmp     r2, r4
+       bne     poll_mailbox_smp_go
+
+       /* SMP GO signal confirmed, release cpuN */
+       ldr     pc, [r1]
+
+mailbox_insn_end:
+       /* should never reach */
+       b       .
+
+#endif
diff --git a/arch/arm/mach-aspeed/ast2600/spl.c b/arch/arm/mach-aspeed/ast2600/spl.c
new file mode 100644 (file)
index 0000000..9201d4a
--- /dev/null
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) Aspeed Technology Inc.
+ */
+#include <common.h>
+#include <debug_uart.h>
+#include <dm.h>
+#include <spl.h>
+#include <init.h>
+#include <asm/io.h>
+#include <asm/arch/scu_ast2600.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void board_init_f(ulong dummy)
+{
+       spl_early_init();
+       preloader_console_init();
+       timer_init();
+       dram_init();
+}
+
+u32 spl_boot_device(void)
+{
+       return BOOT_DEVICE_RAM;
+}
+
+struct image_header *spl_get_load_buffer(ssize_t offset, size_t size)
+{
+       /*
+        * When boot from SPI, AST2600 already remap 0x00000000 ~ 0x0fffffff
+        * to BMC SPI memory space 0x20000000 ~ 0x2fffffff. The next stage BL
+        * has been located in SPI for XIP. In this case, the load buffer for
+        * SPL image loading will be set to the remapped address of the next
+        * BL instead of the DRAM space CONFIG_SYS_LOAD_ADDR
+        */
+       return (struct image_header *)(CONFIG_SYS_TEXT_BASE);
+}
+
+#ifdef CONFIG_SPL_OS_BOOT
+int spl_start_uboot(void)
+{
+       /* boot linux */
+       return 0;
+}
+#endif
+
+#ifdef CONFIG_SPL_LOAD_FIT
+int board_fit_config_name_match(const char *name)
+{
+       /* just empty function now - can't decide what to choose */
+       debug("%s: %s\n", __func__, name);
+       return 0;
+}
+#endif
index 5654a0e..59c28ed 100644 (file)
@@ -25,5 +25,3 @@
 /* CLKSEL Register */
 #define DWMCI_DIVRATIO_BIT             24
 #define DWMCI_DIVRATIO_MASK            0x7
-
-int exynos_dwmmc_init(const void *blob);
diff --git a/board/aspeed/evb_ast2600/Kconfig b/board/aspeed/evb_ast2600/Kconfig
new file mode 100644 (file)
index 0000000..42008cd
--- /dev/null
@@ -0,0 +1,12 @@
+if TARGET_EVB_AST2600
+
+config SYS_BOARD
+       default "evb_ast2600"
+
+config SYS_VENDOR
+       default "aspeed"
+
+config SYS_CONFIG_NAME
+       default "evb_ast2600"
+
+endif
diff --git a/board/aspeed/evb_ast2600/MAINTAINERS b/board/aspeed/evb_ast2600/MAINTAINERS
new file mode 100644 (file)
index 0000000..e83aae5
--- /dev/null
@@ -0,0 +1,6 @@
+EVB AST2600 BOARD
+M:     Chia-Wei, Wang <chiawei_wang@aspeedtech.com>
+S:     Maintained
+F:     board/aspeed/evb_ast2600/
+F:     include/configs/evb_ast2600.h
+F:     configs/evb-ast2600_defconfig
diff --git a/board/aspeed/evb_ast2600/Makefile b/board/aspeed/evb_ast2600/Makefile
new file mode 100644 (file)
index 0000000..9291db6
--- /dev/null
@@ -0,0 +1 @@
+obj-y += evb_ast2600.o
diff --git a/board/aspeed/evb_ast2600/evb_ast2600.c b/board/aspeed/evb_ast2600/evb_ast2600.c
new file mode 100644 (file)
index 0000000..e6dc8c7
--- /dev/null
@@ -0,0 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) Aspeed Technology Inc.
+ */
+#include <common.h>
index 4b21db8..6f55cfa 100644 (file)
@@ -58,8 +58,12 @@ config BOARD_SPECIFIC_OPTIONS # dummy
        select DM_SERIAL
        select DM_SPI
        select DM_SPI_FLASH
+       select USB
+       select USB_EHCI_HCD
+       select USB_EHCI_MARVELL
        imply CMD_CRAMFS
        imply CMD_DIAG
        imply FS_CRAMFS
+       imply CMD_USB
 
 endif
index 666e4d6..37daf1c 100644 (file)
@@ -4,8 +4,25 @@
  */
 
 #include <common.h>
+#include <dm.h>
 
 int board_init(void)
 {
        return 0;
 }
+
+int board_late_init(void)
+{
+       struct udevice *dev;
+       int ret;
+
+       if (CONFIG_IS_ENABLED(USB_GADGET)) {
+               ret = uclass_get_device(UCLASS_USB_GADGET_GENERIC, 0, &dev);
+               if (ret) {
+                       pr_err("%s: Cannot find USB device\n", __func__);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
index e7dd59f..14fda46 100644 (file)
@@ -5,6 +5,13 @@ F:      board/rockchip/evb_rk3328
 F:      include/configs/evb_rk3328.h
 F:      configs/evb-rk3328_defconfig
 
+NANOPI-R2S-RK3328
+M:      David Bauer <mail@david-bauer.net>
+S:      Maintained
+F:      configs/nanopi-r2s-rk3328_defconfig
+F:      arch/arm/dts/rk3328-nanopi-r2s-u-boot.dtsi
+F:      arch/arm/dts/rk3328-nanopi-r2s.dts
+
 ROC-RK3328-CC
 M:      Loic Devulder <ldevulder@suse.com>
 M:      Chen-Yu Tsai <wens@csie.org>
index 9181376..d283ef6 100644 (file)
@@ -73,19 +73,6 @@ int dram_init_banksize(void)
        return 0;
 }
 
-#ifdef CONFIG_MMC
-int board_mmc_init(struct bd_info *bis)
-{
-       int ret;
-       /* dwmmc initializattion for available channels */
-       ret = exynos_dwmmc_init(gd->fdt_blob);
-       if (ret)
-               debug("dwmmc init failed\n");
-
-       return ret;
-}
-#endif
-
 static int board_uart_init(void)
 {
        int err = 0, uart_id;
index cdc06a3..df19aea 100644 (file)
@@ -324,25 +324,30 @@ void *board_fdt_blob_setup(void)
 {
        void *fdt_blob;
 
-#if !defined(CONFIG_VERSAL_NO_DDR) && !defined(CONFIG_ZYNQMP_NO_DDR)
-       fdt_blob = (void *)CONFIG_XILINX_OF_BOARD_DTB_ADDR;
+       if (!IS_ENABLED(CONFIG_SPL_BUILD) &&
+           !IS_ENABLED(CONFIG_VERSAL_NO_DDR) &&
+           !IS_ENABLED(CONFIG_VERSAL_NO_DDR)) {
+               fdt_blob = (void *)CONFIG_XILINX_OF_BOARD_DTB_ADDR;
 
-       if (fdt_magic(fdt_blob) == FDT_MAGIC)
-               return fdt_blob;
+               if (fdt_magic(fdt_blob) == FDT_MAGIC)
+                       return fdt_blob;
 
-       debug("DTB is not passed via %p\n", fdt_blob);
-#endif
+               debug("DTB is not passed via %p\n", fdt_blob);
+       }
 
-#ifdef CONFIG_SPL_BUILD
-       /* FDT is at end of BSS unless it is in a different memory region */
-       if (IS_ENABLED(CONFIG_SPL_SEPARATE_BSS))
-               fdt_blob = (ulong *)&_image_binary_end;
-       else
-               fdt_blob = (ulong *)&__bss_end;
-#else
-       /* FDT is at end of image */
-       fdt_blob = (ulong *)&_end;
-#endif
+       if (IS_ENABLED(CONFIG_SPL_BUILD)) {
+               /*
+                * FDT is at end of BSS unless it is in a different memory
+                * region
+                */
+               if (IS_ENABLED(CONFIG_SPL_SEPARATE_BSS))
+                       fdt_blob = (ulong *)&_image_binary_end;
+               else
+                       fdt_blob = (ulong *)&__bss_end;
+       } else {
+               /* FDT is at end of image */
+               fdt_blob = (ulong *)&_end;
+       }
 
        if (fdt_magic(fdt_blob) == FDT_MAGIC)
                return fdt_blob;
index 047b070..459d9b1 100644 (file)
@@ -648,6 +648,7 @@ int board_late_init(void)
        if (bootseq >= 0) {
                bootseq_len = snprintf(NULL, 0, "%i", bootseq);
                debug("Bootseq len: %x\n", bootseq_len);
+               env_set_hex("bootseq", bootseq);
        }
 
        /*
index 1b53e5b..0625ee4 100644 (file)
@@ -928,6 +928,12 @@ config CMD_GPIO
        help
          GPIO support.
 
+config CMD_PWM
+       bool "pwm"
+       depends on DM_PWM
+       help
+         Control PWM channels, this allows invert/config/enable/disable PWM channels.
+
 config CMD_GPT
        bool "GPT (GUID Partition Table) command"
        select EFI_PARTITION
index 87aa949..176bf92 100644 (file)
@@ -120,6 +120,7 @@ endif
 obj-$(CONFIG_CMD_PINMUX) += pinmux.o
 obj-$(CONFIG_CMD_PMC) += pmc.o
 obj-$(CONFIG_CMD_PSTORE) += pstore.o
+obj-$(CONFIG_CMD_PWM) += pwm.o
 obj-$(CONFIG_CMD_PXE) += pxe.o pxe_utils.o
 obj-$(CONFIG_CMD_WOL) += wol.o
 obj-$(CONFIG_CMD_QFW) += qfw.o
index fe70eec..c8eb5c3 100644 (file)
@@ -631,10 +631,12 @@ static int do_bootefi(struct cmd_tbl *cmdtp, int flag, int argc,
        else if (ret != EFI_SUCCESS)
                return CMD_RET_FAILURE;
 
-       if (!strcmp(argv[1], "bootmgr"))
-               return do_efibootmgr();
+       if (IS_ENABLED(CONFIG_CMD_BOOTEFI_BOOTMGR)) {
+               if (!strcmp(argv[1], "bootmgr"))
+                       return do_efibootmgr();
+       }
 #ifdef CONFIG_CMD_BOOTEFI_SELFTEST
-       else if (!strcmp(argv[1], "selftest"))
+       if (!strcmp(argv[1], "selftest"))
                return do_efi_selftest();
 #endif
 
@@ -657,11 +659,14 @@ static char bootefi_help_text[] =
        "    Use environment variable efi_selftest to select a single test.\n"
        "    Use 'setenv efi_selftest list' to enumerate all tests.\n"
 #endif
+#ifdef CONFIG_CMD_BOOTEFI_BOOTMGR
        "bootefi bootmgr [fdt address]\n"
        "  - load and boot EFI payload based on BootOrder/BootXXXX variables.\n"
        "\n"
        "    If specified, the device tree located at <fdt address> gets\n"
-       "    exposed as EFI configuration table.\n";
+       "    exposed as EFI configuration table.\n"
+#endif
+       ;
 #endif
 
 U_BOOT_CMD(
index 6de81ca..83bc219 100644 (file)
@@ -189,14 +189,16 @@ static int do_efi_capsule_res(struct cmd_tbl *cmdtp, int flag,
        ret = EFI_CALL(RT->get_variable(var_name16, &guid, NULL, &size, NULL));
        if (ret == EFI_BUFFER_TOO_SMALL) {
                result = malloc(size);
+               if (!result)
+                       return CMD_RET_FAILURE;
                ret = EFI_CALL(RT->get_variable(var_name16, &guid, NULL, &size,
                                                result));
-               if (ret != EFI_SUCCESS) {
-                       free(result);
-                       printf("Failed to get %ls\n", var_name16);
+       }
+       if (ret != EFI_SUCCESS) {
+               free(result);
+               printf("Failed to get %ls\n", var_name16);
 
-                       return CMD_RET_FAILURE;
-               }
+               return CMD_RET_FAILURE;
        }
 
        printf("Result total size: 0x%x\n", result->variable_total_size);
@@ -1367,8 +1369,8 @@ static int do_efi_boot_opt(struct cmd_tbl *cmdtp, int flag,
  *
  *     efidebug test bootmgr
  */
-static int do_efi_test_bootmgr(struct cmd_tbl *cmdtp, int flag,
-                              int argc, char * const argv[])
+static __maybe_unused int do_efi_test_bootmgr(struct cmd_tbl *cmdtp, int flag,
+                                             int argc, char * const argv[])
 {
        efi_handle_t image;
        efi_uintn_t exit_data_size = 0;
@@ -1392,8 +1394,10 @@ static int do_efi_test_bootmgr(struct cmd_tbl *cmdtp, int flag,
 }
 
 static struct cmd_tbl cmd_efidebug_test_sub[] = {
+#ifdef CONFIG_CMD_BOOTEFI_BOOTMGR
        U_BOOT_CMD_MKENT(bootmgr, CONFIG_SYS_MAXARGS, 1, do_efi_test_bootmgr,
                         "", ""),
+#endif
 };
 
 /**
@@ -1581,8 +1585,10 @@ static char efidebug_help_text[] =
        "  - show UEFI memory map\n"
        "efidebug tables\n"
        "  - show UEFI configuration tables\n"
+#ifdef CONFIG_CMD_BOOTEFI_BOOTMGR
        "efidebug test bootmgr\n"
        "  - run simple bootmgr for test\n"
+#endif
        "efidebug query [-nv][-bs][-rt][-at]\n"
        "  - show size of UEFI variables store\n";
 #endif
diff --git a/cmd/pwm.c b/cmd/pwm.c
new file mode 100644 (file)
index 0000000..5849fc5
--- /dev/null
+++ b/cmd/pwm.c
@@ -0,0 +1,117 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Control PWM channels
+ *
+ * Copyright (c) 2020 SiFive, Inc
+ * author: Pragnesh Patel <pragnesh.patel@sifive.com>
+ */
+
+#include <command.h>
+#include <dm.h>
+#include <pwm.h>
+
+enum pwm_cmd {
+       PWM_SET_INVERT,
+       PWM_SET_CONFIG,
+       PWM_SET_ENABLE,
+       PWM_SET_DISABLE,
+};
+
+static int do_pwm(struct cmd_tbl *cmdtp, int flag, int argc,
+                 char *const argv[])
+{
+       const char *str_cmd, *str_channel = NULL, *str_enable = NULL;
+       const char *str_pwm = NULL, *str_period = NULL, *str_duty = NULL;
+       enum pwm_cmd sub_cmd;
+       struct udevice *dev;
+       u32 channel, pwm_enable, pwm_dev, period_ns = 0, duty_ns = 0;
+       int ret;
+
+       if (argc < 4)
+               return CMD_RET_USAGE;
+
+       str_cmd = argv[1];
+       argc -= 2;
+       argv += 2;
+
+       if (argc > 0) {
+               str_pwm = *argv;
+               argc--;
+               argv++;
+       }
+
+       if (!str_pwm)
+               return CMD_RET_USAGE;
+
+       switch (*str_cmd) {
+       case 'i':
+               sub_cmd = PWM_SET_INVERT;
+               break;
+       case 'c':
+               sub_cmd = PWM_SET_CONFIG;
+               break;
+       case 'e':
+               sub_cmd = PWM_SET_ENABLE;
+               break;
+       case 'd':
+               sub_cmd = PWM_SET_DISABLE;
+               break;
+       default:
+               return CMD_RET_USAGE;
+       }
+
+       pwm_dev = simple_strtoul(str_pwm, NULL, 10);
+       ret = uclass_get_device(UCLASS_PWM, pwm_dev, &dev);
+       if (ret) {
+               printf("pwm: '%s' not found\n", str_pwm);
+               return cmd_process_error(cmdtp, ret);
+       }
+
+       if (argc > 0) {
+               str_channel = *argv;
+               channel = simple_strtoul(str_channel, NULL, 10);
+               argc--;
+               argv++;
+       } else {
+               return CMD_RET_USAGE;
+       }
+
+       if (sub_cmd == PWM_SET_INVERT && argc > 0) {
+               str_enable = *argv;
+               pwm_enable = simple_strtoul(str_enable, NULL, 10);
+               ret = pwm_set_invert(dev, channel, pwm_enable);
+       } else if (sub_cmd == PWM_SET_CONFIG && argc == 2) {
+               str_period = *argv;
+               argc--;
+               argv++;
+               period_ns = simple_strtoul(str_period, NULL, 10);
+
+               if (argc > 0) {
+                       str_duty = *argv;
+                       duty_ns = simple_strtoul(str_duty, NULL, 10);
+               }
+
+               ret = pwm_set_config(dev, channel, period_ns, duty_ns);
+       } else if (sub_cmd == PWM_SET_ENABLE) {
+               ret = pwm_set_enable(dev, channel, 1);
+       } else if (sub_cmd == PWM_SET_DISABLE) {
+               ret = pwm_set_enable(dev, channel, 0);
+       } else {
+               printf("PWM arguments missing\n");
+               return CMD_RET_FAILURE;
+       }
+
+       if (ret) {
+               printf("error(%d)\n", ret);
+               return CMD_RET_FAILURE;
+       }
+
+       return CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD(pwm, 6, 0, do_pwm,
+          "control pwm channels",
+          "pwm <invert> <pwm_dev_num> <channel> <polarity>\n"
+          "pwm <config> <pwm_dev_num> <channel> <period_ns> <duty_ns>\n"
+          "pwm <enable/disable> <pwm_dev_num> <channel>\n"
+          "Note: All input values are in decimal");
index 5401d94..d39741e 100644 (file)
@@ -19,20 +19,6 @@ DECLARE_GLOBAL_DATA_PTR;
 
 #define IMAGE_MAX_HASHED_NODES         100
 
-#ifdef USE_HOSTCC
-void *host_blob;
-
-void image_set_host_blob(void *blob)
-{
-       host_blob = blob;
-}
-
-void *image_get_host_blob(void)
-{
-       return host_blob;
-}
-#endif
-
 /**
  * fit_region_make_list() - Make a list of image regions
  *
index 21c44bd..8660c3f 100644 (file)
@@ -112,6 +112,21 @@ int fit_parse_subimage(const char *spec, ulong addr_curr,
 }
 #endif /* !USE_HOSTCC */
 
+#ifdef USE_HOSTCC
+/* Host tools use these implementations for Cipher and Signature support */
+static void *host_blob;
+
+void image_set_host_blob(void *blob)
+{
+       host_blob = blob;
+}
+
+void *image_get_host_blob(void)
+{
+       return host_blob;
+}
+#endif /* USE_HOSTCC */
+
 static void fit_get_debug(const void *fit, int noffset,
                char *prop_name, int err)
 {
diff --git a/configs/cortina_presidio-asic-pnand_defconfig b/configs/cortina_presidio-asic-pnand_defconfig
new file mode 100644 (file)
index 0000000..e85cdc5
--- /dev/null
@@ -0,0 +1,33 @@
+CONFIG_ARM=y
+# CONFIG_SYS_ARCH_TIMER is not set
+CONFIG_TARGET_PRESIDIO_ASIC=y
+CONFIG_SYS_TEXT_BASE=0x04000000
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_ENV_SIZE=0x20000
+CONFIG_DM_GPIO=y
+CONFIG_IDENT_STRING="Presidio-SoC"
+CONFIG_DEFAULT_DEVICE_TREE="ca-presidio-engboard"
+CONFIG_SHOW_BOOT_PROGRESS=y
+CONFIG_BOOTDELAY=3
+CONFIG_USE_BOOTARGS=y
+CONFIG_BOOTARGS="earlycon=serial,0xf4329148 console=ttyS0,115200 root=/dev/ram0"
+CONFIG_BOARD_EARLY_INIT_R=y
+CONFIG_SYS_PROMPT="G3#"
+CONFIG_CMD_MTD=y
+CONFIG_CMD_WDT=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_TIMER=y
+CONFIG_CMD_SMC=y
+CONFIG_OF_CONTROL=y
+CONFIG_OF_LIVE=y
+# CONFIG_NET is not set
+CONFIG_DM=y
+CONFIG_CORTINA_GPIO=y
+# CONFIG_MMC is not set
+CONFIG_MTD=y
+CONFIG_MTD_RAW_NAND=y
+CONFIG_CORTINA_NAND=y
+CONFIG_DM_SERIAL=y
+CONFIG_CORTINA_UART=y
+CONFIG_WDT=y
+CONFIG_WDT_CORTINA=y
diff --git a/configs/evb-ast2600_defconfig b/configs/evb-ast2600_defconfig
new file mode 100644 (file)
index 0000000..003fedd
--- /dev/null
@@ -0,0 +1,69 @@
+CONFIG_ARM=y
+CONFIG_SYS_DCACHE_OFF=y
+CONFIG_ARCH_ASPEED=y
+CONFIG_SYS_TEXT_BASE=0x10000
+CONFIG_ASPEED_AST2600=y
+CONFIG_TARGET_EVB_AST2600=y
+CONFIG_SPL_LIBCOMMON_SUPPORT=y
+CONFIG_SPL_LIBGENERIC_SUPPORT=y
+CONFIG_SYS_MALLOC_F_LEN=0x800
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_ENV_SIZE=0x10000
+CONFIG_SPL_SERIAL_SUPPORT=y
+CONFIG_SPL_SIZE_LIMIT=0x10000
+CONFIG_SPL=y
+# CONFIG_ARMV7_NONSEC is not set
+CONFIG_DEFAULT_DEVICE_TREE="ast2600-evb"
+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+CONFIG_FIT=y
+# CONFIG_LEGACY_IMAGE_FORMAT is not set
+CONFIG_USE_BOOTARGS=y
+CONFIG_BOOTARGS="console=ttyS4,115200n8 root=/dev/ram rw"
+CONFIG_USE_BOOTCOMMAND=y
+CONFIG_BOOTCOMMAND="bootm 20100000"
+# CONFIG_DISPLAY_CPUINFO is not set
+CONFIG_SPL_SIZE_LIMIT_SUBTRACT_GD=y
+CONFIG_SPL_SIZE_LIMIT_SUBTRACT_MALLOC=y
+# CONFIG_SPL_LEGACY_IMAGE_SUPPORT is not set
+CONFIG_SPL_SYS_MALLOC_SIMPLE=y
+CONFIG_SPL_DM_RESET=y
+CONFIG_SPL_RAM_SUPPORT=y
+CONFIG_SPL_RAM_DEVICE=y
+CONFIG_HUSH_PARSER=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_ENV_OVERWRITE=y
+CONFIG_SYS_RELOC_GD_ENV_ADDR=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_SPL_DM=y
+CONFIG_SPL_DM_SEQ_ALIAS=y
+CONFIG_REGMAP=y
+CONFIG_SPL_OF_TRANSLATE=y
+CONFIG_CLK=y
+CONFIG_SPL_CLK=y
+CONFIG_DM_I2C=y
+CONFIG_MISC=y
+CONFIG_SPL_MISC=y
+CONFIG_DM_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_ASPEED=y
+CONFIG_PHY_REALTEK=y
+CONFIG_DM_ETH=y
+CONFIG_FTGMAC100=y
+CONFIG_PHY=y
+CONFIG_PINCTRL=y
+CONFIG_RAM=y
+CONFIG_SPL_RAM=y
+CONFIG_DM_RESET=y
+CONFIG_DM_SERIAL=y
+CONFIG_SYS_NS16550=y
+CONFIG_SYSRESET=y
+CONFIG_SPL_SYSRESET=y
+CONFIG_WDT=y
+CONFIG_HEXDUMP=y
+# CONFIG_SPL_HEXDUMP is not set
+# CONFIG_EFI_LOADER is not set
index c453b82..cfbaae4 100644 (file)
@@ -35,6 +35,8 @@ CONFIG_MMC_DW=y
 CONFIG_MMC_DW_ROCKCHIP=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_ROCKCHIP=y
+CONFIG_DM_RNG=y
+CONFIG_RNG_ROCKCHIP=y
 CONFIG_SF_DEFAULT_SPEED=20000000
 CONFIG_DM_ETH=y
 CONFIG_ETH_DESIGNWARE=y
index d97e588..151425f 100644 (file)
@@ -8,7 +8,7 @@ CONFIG_ENV_SIZE=0x2000
 CONFIG_ENV_OFFSET=0x0
 CONFIG_BOOTCOUNT_BOOTLIMIT=3
 CONFIG_ENV_OFFSET_REDUND=0x2000
-CONFIG_IDENT_STRING="\nKeymile Kirkwood 128M16"
+CONFIG_IDENT_STRING="\nHitachi Power Grids Kirkwood 128M16"
 CONFIG_DEFAULT_DEVICE_TREE="kirkwood-km_kirkwood"
 CONFIG_SYS_EXTRA_OPTIONS="KM_KIRKWOOD_128M16"
 CONFIG_AUTOBOOT_KEYED=y
@@ -17,16 +17,18 @@ CONFIG_AUTOBOOT_STOP_STR=" "
 # CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_MISC_INIT_R=y
 CONFIG_HUSH_PARSER=y
+# CONFIG_BOOTM_NETBSD is not set
+# CONFIG_BOOTM_PLAN9 is not set
+# CONFIG_BOOTM_RTEMS is not set
+# CONFIG_BOOTM_VXWORKS is not set
 CONFIG_CMD_ASKENV=y
 CONFIG_CMD_GREPENV=y
 CONFIG_CMD_EEPROM=y
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_I2C=y
 CONFIG_CMD_NAND=y
-CONFIG_CMD_DHCP=y
 CONFIG_CMD_MII=y
 CONFIG_CMD_PING=y
-CONFIG_CMD_JFFS2=y
 CONFIG_CMD_MTDPARTS=y
 CONFIG_MTDIDS_DEFAULT="nand0=orion_nand"
 CONFIG_MTDPARTS_DEFAULT="mtdparts=orion_nand:-(ubi0);"
index 0b364dc..22c2e05 100644 (file)
@@ -8,7 +8,7 @@ CONFIG_ENV_SIZE=0x2000
 CONFIG_ENV_OFFSET=0x0
 CONFIG_BOOTCOUNT_BOOTLIMIT=3
 CONFIG_ENV_OFFSET_REDUND=0x2000
-CONFIG_IDENT_STRING="\nKeymile Kirkwood"
+CONFIG_IDENT_STRING="\nHitachi Power Grids Kirkwood"
 CONFIG_DEFAULT_DEVICE_TREE="kirkwood-km_kirkwood"
 CONFIG_SYS_EXTRA_OPTIONS="KM_KIRKWOOD"
 CONFIG_AUTOBOOT_KEYED=y
@@ -17,16 +17,18 @@ CONFIG_AUTOBOOT_STOP_STR=" "
 # CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_MISC_INIT_R=y
 CONFIG_HUSH_PARSER=y
+# CONFIG_BOOTM_NETBSD is not set
+# CONFIG_BOOTM_PLAN9 is not set
+# CONFIG_BOOTM_RTEMS is not set
+# CONFIG_BOOTM_VXWORKS is not set
 CONFIG_CMD_ASKENV=y
 CONFIG_CMD_GREPENV=y
 CONFIG_CMD_EEPROM=y
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_I2C=y
 CONFIG_CMD_NAND=y
-CONFIG_CMD_DHCP=y
 CONFIG_CMD_MII=y
 CONFIG_CMD_PING=y
-CONFIG_CMD_JFFS2=y
 CONFIG_CMD_MTDPARTS=y
 CONFIG_MTDIDS_DEFAULT="nand0=orion_nand"
 CONFIG_MTDPARTS_DEFAULT="mtdparts=orion_nand:-(ubi0);"
index 82d0210..c091cd6 100644 (file)
@@ -9,7 +9,7 @@ CONFIG_ENV_SIZE=0x2000
 CONFIG_ENV_OFFSET=0x0
 CONFIG_BOOTCOUNT_BOOTLIMIT=3
 CONFIG_ENV_OFFSET_REDUND=0x2000
-CONFIG_IDENT_STRING="\nKeymile Kirkwood PCI"
+CONFIG_IDENT_STRING="\nHitachi Power Grids Kirkwood PCI"
 CONFIG_DEFAULT_DEVICE_TREE="kirkwood-km_kirkwood"
 CONFIG_SYS_EXTRA_OPTIONS="KM_KIRKWOOD_PCI"
 CONFIG_AUTOBOOT_KEYED=y
@@ -18,16 +18,18 @@ CONFIG_AUTOBOOT_STOP_STR=" "
 # CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_MISC_INIT_R=y
 CONFIG_HUSH_PARSER=y
+# CONFIG_BOOTM_NETBSD is not set
+# CONFIG_BOOTM_PLAN9 is not set
+# CONFIG_BOOTM_RTEMS is not set
+# CONFIG_BOOTM_VXWORKS is not set
 CONFIG_CMD_ASKENV=y
 CONFIG_CMD_GREPENV=y
 CONFIG_CMD_EEPROM=y
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_I2C=y
 CONFIG_CMD_NAND=y
-CONFIG_CMD_DHCP=y
 CONFIG_CMD_MII=y
 CONFIG_CMD_PING=y
-CONFIG_CMD_JFFS2=y
 CONFIG_CMD_MTDPARTS=y
 CONFIG_MTDIDS_DEFAULT="nand0=orion_nand"
 CONFIG_MTDPARTS_DEFAULT="mtdparts=orion_nand:-(ubi0);"
@@ -46,6 +48,7 @@ CONFIG_BOOTCOUNT_RAM=y
 CONFIG_MTD=y
 CONFIG_MTD_RAW_NAND=y
 CONFIG_SF_DEFAULT_SPEED=8100000
+CONFIG_SPI_FLASH_MACRONIX=y
 CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_MVGBE=y
 CONFIG_MII=y
index b0ae24d..4d2c17f 100644 (file)
@@ -12,7 +12,7 @@ CONFIG_ENV_OFFSET=0xC0000
 CONFIG_ENV_SECT_SIZE=0x10000
 CONFIG_BOOTCOUNT_BOOTLIMIT=3
 CONFIG_ENV_OFFSET_REDUND=0xD0000
-CONFIG_IDENT_STRING="\nKeymile COGE5UN"
+CONFIG_IDENT_STRING="\nHitachi Power Grids COGE5UN"
 CONFIG_DEFAULT_DEVICE_TREE="kirkwood-km_kirkwood"
 CONFIG_SYS_EXTRA_OPTIONS="KM_COGE5UN"
 CONFIG_AUTOBOOT_KEYED=y
@@ -21,16 +21,18 @@ CONFIG_AUTOBOOT_STOP_STR=" "
 # CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_MISC_INIT_R=y
 CONFIG_HUSH_PARSER=y
+# CONFIG_BOOTM_NETBSD is not set
+# CONFIG_BOOTM_PLAN9 is not set
+# CONFIG_BOOTM_RTEMS is not set
+# CONFIG_BOOTM_VXWORKS is not set
 CONFIG_CMD_ASKENV=y
 CONFIG_CMD_GREPENV=y
 CONFIG_CMD_EEPROM=y
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_I2C=y
 CONFIG_CMD_NAND=y
-CONFIG_CMD_DHCP=y
 CONFIG_CMD_MII=y
 CONFIG_CMD_PING=y
-CONFIG_CMD_JFFS2=y
 CONFIG_CMD_MTDPARTS=y
 CONFIG_MTDIDS_DEFAULT="nand0=orion_nand"
 CONFIG_MTDPARTS_DEFAULT="mtdparts=orion_nand:-(ubi0);"
index 6e6cc5a..faaa8d1 100644 (file)
@@ -12,7 +12,7 @@ CONFIG_ENV_OFFSET=0xC0000
 CONFIG_ENV_SECT_SIZE=0x10000
 CONFIG_BOOTCOUNT_BOOTLIMIT=3
 CONFIG_ENV_OFFSET_REDUND=0xD0000
-CONFIG_IDENT_STRING="\nKeymile NUSA"
+CONFIG_IDENT_STRING="\nHitachi Power Grids Kirkwood"
 CONFIG_DEFAULT_DEVICE_TREE="kirkwood-km_kirkwood"
 CONFIG_SYS_EXTRA_OPTIONS="KM_NUSA"
 CONFIG_AUTOBOOT_KEYED=y
@@ -21,16 +21,18 @@ CONFIG_AUTOBOOT_STOP_STR=" "
 # CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_MISC_INIT_R=y
 CONFIG_HUSH_PARSER=y
+# CONFIG_BOOTM_NETBSD is not set
+# CONFIG_BOOTM_PLAN9 is not set
+# CONFIG_BOOTM_RTEMS is not set
+# CONFIG_BOOTM_VXWORKS is not set
 CONFIG_CMD_ASKENV=y
 CONFIG_CMD_GREPENV=y
 CONFIG_CMD_EEPROM=y
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_I2C=y
 CONFIG_CMD_NAND=y
-CONFIG_CMD_DHCP=y
 CONFIG_CMD_MII=y
 CONFIG_CMD_PING=y
-CONFIG_CMD_JFFS2=y
 CONFIG_CMD_MTDPARTS=y
 CONFIG_MTDIDS_DEFAULT="nand0=orion_nand"
 CONFIG_MTDPARTS_DEFAULT="mtdparts=orion_nand:-(ubi0);"
index 0b75b2e..d8280f9 100644 (file)
@@ -13,7 +13,7 @@ CONFIG_ENV_OFFSET=0xC0000
 CONFIG_ENV_SECT_SIZE=0x10000
 CONFIG_BOOTCOUNT_BOOTLIMIT=3
 CONFIG_ENV_OFFSET_REDUND=0xD0000
-CONFIG_IDENT_STRING="\nABB SUSE2"
+CONFIG_IDENT_STRING="\nHitachi Power Grids Kirkwood"
 CONFIG_DEFAULT_DEVICE_TREE="kirkwood-km_kirkwood"
 CONFIG_SYS_EXTRA_OPTIONS="KM_SUSE2"
 CONFIG_AUTOBOOT_KEYED=y
@@ -22,16 +22,18 @@ CONFIG_AUTOBOOT_STOP_STR=" "
 # CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_MISC_INIT_R=y
 CONFIG_HUSH_PARSER=y
+# CONFIG_BOOTM_NETBSD is not set
+# CONFIG_BOOTM_PLAN9 is not set
+# CONFIG_BOOTM_RTEMS is not set
+# CONFIG_BOOTM_VXWORKS is not set
 CONFIG_CMD_ASKENV=y
 CONFIG_CMD_GREPENV=y
 CONFIG_CMD_EEPROM=y
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_I2C=y
 CONFIG_CMD_NAND=y
-CONFIG_CMD_DHCP=y
 CONFIG_CMD_MII=y
 CONFIG_CMD_PING=y
-CONFIG_CMD_JFFS2=y
 CONFIG_CMD_MTDPARTS=y
 CONFIG_MTDIDS_DEFAULT="nand0=orion_nand"
 CONFIG_MTDPARTS_DEFAULT="mtdparts=orion_nand:-(ubi0);"
diff --git a/configs/nanopi-r2s-rk3328_defconfig b/configs/nanopi-r2s-rk3328_defconfig
new file mode 100644 (file)
index 0000000..2f67439
--- /dev/null
@@ -0,0 +1,98 @@
+CONFIG_ARM=y
+CONFIG_ARCH_ROCKCHIP=y
+CONFIG_SYS_TEXT_BASE=0x00200000
+CONFIG_SPL_GPIO_SUPPORT=y
+CONFIG_ENV_OFFSET=0x3F8000
+CONFIG_ROCKCHIP_RK3328=y
+CONFIG_TPL_ROCKCHIP_COMMON_BOARD=y
+CONFIG_TPL_LIBCOMMON_SUPPORT=y
+CONFIG_TPL_LIBGENERIC_SUPPORT=y
+CONFIG_SPL_DRIVERS_MISC_SUPPORT=y
+CONFIG_SPL_STACK_R_ADDR=0x600000
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_DEBUG_UART_BASE=0xFF130000
+CONFIG_DEBUG_UART_CLOCK=24000000
+CONFIG_SYSINFO=y
+CONFIG_DEBUG_UART=y
+CONFIG_TPL_SYS_MALLOC_F_LEN=0x800
+# CONFIG_ANDROID_BOOT_IMAGE is not set
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_SPL_LOAD_FIT=y
+CONFIG_DEFAULT_FDT_FILE="rockchip/rk3328-nanopi-r2s.dtb"
+CONFIG_MISC_INIT_R=y
+# CONFIG_DISPLAY_CPUINFO is not set
+CONFIG_DISPLAY_BOARDINFO_LATE=y
+# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set
+CONFIG_TPL_SYS_MALLOC_SIMPLE=y
+CONFIG_SPL_STACK_R=y
+CONFIG_SPL_I2C_SUPPORT=y
+CONFIG_SPL_POWER_SUPPORT=y
+CONFIG_SPL_ATF=y
+CONFIG_SPL_ATF_NO_PLATFORM_PARAM=y
+CONFIG_CMD_BOOTZ=y
+CONFIG_CMD_GPT=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_USB=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_TIME=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_TPL_OF_CONTROL=y
+CONFIG_DEFAULT_DEVICE_TREE="rk3328-nanopi-r2s"
+CONFIG_OF_SPL_REMOVE_PROPS="clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents"
+CONFIG_TPL_OF_PLATDATA=y
+CONFIG_ENV_IS_IN_MMC=y
+CONFIG_SYS_RELOC_GD_ENV_ADDR=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_TPL_DM=y
+CONFIG_REGMAP=y
+CONFIG_SPL_REGMAP=y
+CONFIG_TPL_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_SPL_SYSCON=y
+CONFIG_TPL_SYSCON=y
+CONFIG_CLK=y
+CONFIG_SPL_CLK=y
+CONFIG_FASTBOOT_BUF_ADDR=0x800800
+CONFIG_FASTBOOT_CMD_OEM_FORMAT=y
+CONFIG_ROCKCHIP_GPIO=y
+CONFIG_SYS_I2C_ROCKCHIP=y
+CONFIG_MMC_DW=y
+CONFIG_MMC_DW_ROCKCHIP=y
+CONFIG_SF_DEFAULT_SPEED=20000000
+CONFIG_DM_ETH=y
+CONFIG_ETH_DESIGNWARE=y
+CONFIG_GMAC_ROCKCHIP=y
+CONFIG_PINCTRL=y
+CONFIG_SPL_PINCTRL=y
+CONFIG_DM_PMIC=y
+CONFIG_PMIC_RK8XX=y
+CONFIG_SPL_DM_REGULATOR=y
+CONFIG_REGULATOR_PWM=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_SPL_DM_REGULATOR_FIXED=y
+CONFIG_REGULATOR_RK8XX=y
+CONFIG_PWM_ROCKCHIP=y
+CONFIG_RAM=y
+CONFIG_SPL_RAM=y
+CONFIG_TPL_RAM=y
+CONFIG_DM_RESET=y
+CONFIG_BAUDRATE=1500000
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_SYSRESET=y
+# CONFIG_TPL_SYSRESET is not set
+CONFIG_USB=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_DWC3=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_GENERIC=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_GENERIC=y
+CONFIG_USB_DWC2=y
+CONFIG_USB_DWC3=y
+# CONFIG_USB_DWC3_GADGET is not set
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DWC2_OTG=y
+CONFIG_SPL_TINY_MEMSET=y
+CONFIG_TPL_TINY_MEMSET=y
+CONFIG_ERRNO_STR=y
index 60178e3..0f15936 100644 (file)
@@ -44,6 +44,7 @@ CONFIG_ENV_OVERWRITE=y
 CONFIG_ENV_IS_IN_MMC=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_SYS_MMC_ENV_DEV=1
+CONFIG_SPL_DM_SEQ_ALIAS=y
 CONFIG_ROCKCHIP_GPIO=y
 CONFIG_SYS_I2C_ROCKCHIP=y
 CONFIG_MISC=y
@@ -53,6 +54,7 @@ CONFIG_MMC_DW_ROCKCHIP=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_SDMA=y
 CONFIG_MMC_SDHCI_ROCKCHIP=y
+CONFIG_SF_DEFAULT_BUS=1
 CONFIG_SF_DEFAULT_SPEED=20000000
 CONFIG_SPI_FLASH_GIGADEVICE=y
 CONFIG_SPI_FLASH_WINBOND=y
index ab50124..cd77889 100644 (file)
@@ -17,6 +17,7 @@ CONFIG_FIT=y
 # CONFIG_ARCH_FIXUP_FDT_MEMORY is not set
 CONFIG_DEFAULT_FDT_FILE="mt8516-pumpkin"
 # CONFIG_DISPLAY_BOARDINFO is not set
+CONFIG_BOARD_LATE_INIT=y
 CONFIG_HUSH_PARSER=y
 # CONFIG_CMD_BDI is not set
 # CONFIG_CMD_CONSOLE is not set
@@ -45,8 +46,13 @@ CONFIG_CMD_PART=y
 # CONFIG_CMD_SLEEP is not set
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
-# CONFIG_NET is not set
 CONFIG_CLK=y
+CONFIG_USB_FUNCTION_FASTBOOT=y
+CONFIG_FASTBOOT_BUF_ADDR=0x4d000000
+CONFIG_FASTBOOT_BUF_SIZE=0x4000000
+CONFIG_FASTBOOT_FLASH=y
+CONFIG_FASTBOOT_FLASH_MMC_DEV=0
+CONFIG_FASTBOOT_MMC_BOOT1_SUPPORT=y
 # CONFIG_INPUT is not set
 CONFIG_DM_MMC=y
 # CONFIG_MMC_QUIRKS is not set
@@ -59,6 +65,13 @@ CONFIG_BAUDRATE=921600
 CONFIG_DM_SERIAL=y
 CONFIG_DEBUG_UART_ANNOUNCE=y
 CONFIG_MTK_SERIAL=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_MUSB_GADGET=y
+CONFIG_USB_MUSB_MT85XX=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_VENDOR_NUM=0x0e8d
+CONFIG_USB_GADGET_PRODUCT_NUM=0x201c
 CONFIG_WDT=y
 CONFIG_WDT_MTK=y
 # CONFIG_EFI_LOADER is not set
index ae16f35..8aa5a15 100644 (file)
@@ -42,6 +42,7 @@ CONFIG_MMC_DW=y
 CONFIG_MMC_DW_ROCKCHIP=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_ROCKCHIP=y
+CONFIG_SF_DEFAULT_BUS=1
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_DM_ETH=y
 CONFIG_ETH_DESIGNWARE=y
index 774707b..927b576 100644 (file)
@@ -41,6 +41,7 @@ CONFIG_MMC_DW=y
 CONFIG_MMC_DW_ROCKCHIP=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_ROCKCHIP=y
+CONFIG_SF_DEFAULT_BUS=1
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_DM_ETH=y
 CONFIG_ETH_DESIGNWARE=y
index 65dce3c..aadbc55 100644 (file)
@@ -39,6 +39,8 @@ CONFIG_MMC_DW_ROCKCHIP=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_SDMA=y
 CONFIG_MMC_SDHCI_ROCKCHIP=y
+CONFIG_DM_RNG=y
+CONFIG_RNG_ROCKCHIP=y
 CONFIG_DM_ETH=y
 CONFIG_NVME=y
 CONFIG_PCI=y
index 575b7a2..f78dfcc 100644 (file)
@@ -42,6 +42,8 @@ CONFIG_MMC_DW=y
 CONFIG_MMC_DW_ROCKCHIP=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_ROCKCHIP=y
+CONFIG_DM_RNG=y
+CONFIG_RNG_ROCKCHIP=y
 CONFIG_SF_DEFAULT_BUS=1
 CONFIG_SPI_FLASH_GIGADEVICE=y
 CONFIG_DM_ETH=y
index 58d4ef1..86dc603 100644 (file)
@@ -58,6 +58,7 @@ CONFIG_CMD_LSBLK=y
 CONFIG_CMD_MUX=y
 CONFIG_CMD_OSD=y
 CONFIG_CMD_PCI=y
+CONFIG_CMD_PWM=y
 CONFIG_CMD_READ=y
 CONFIG_CMD_REMOTEPROC=y
 CONFIG_CMD_SPI=y
index e400cd4..0bf4b7d 100644 (file)
@@ -54,6 +54,7 @@ CONFIG_CMD_SPI=y
 CONFIG_CMD_USB=y
 CONFIG_CMD_USB_MASS_STORAGE=y
 CONFIG_CMD_TFTPPUT=y
+CONFIG_CMD_BMP=y
 CONFIG_CMD_CACHE=y
 CONFIG_CMD_TIME=y
 CONFIG_CMD_TIMER=y
@@ -155,6 +156,15 @@ CONFIG_USB_ETHER=y
 CONFIG_USB_ETH_CDC=y
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_ASIX=y
+CONFIG_DM_VIDEO=y
+CONFIG_VIDEO_COPY=y
+CONFIG_DISPLAY=y
+CONFIG_VIDEO_SEPS525=y
+CONFIG_LCD=y
+CONFIG_SPLASH_SCREEN=y
+CONFIG_BMP_16BPP=y
+CONFIG_BMP_24BPP=y
+CONFIG_BMP_32BPP=y
 CONFIG_WDT=y
 CONFIG_WDT_CDNS=y
 CONFIG_PANIC_HANG=y
index 0e0da56..a686d47 100644 (file)
@@ -106,7 +106,7 @@ cleandocs:
        $(Q)$(MAKE) BUILDDIR=$(abspath $(BUILDDIR)) $(build)=doc/media clean
 
 dochelp:
-       @echo  ' Linux kernel internal documentation in different formats from ReST:'
+       @echo  ' U-Boot documentation in different formats from ReST:'
        @echo  '  htmldocs        - HTML'
        @echo  '  latexdocs       - LaTeX'
        @echo  '  pdfdocs         - PDF'
diff --git a/doc/README.menu b/doc/README.menu
deleted file mode 100644 (file)
index 0f3d741..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright 2010-2011 Calxeda, Inc.
- */
-
-U-Boot provides a set of interfaces for creating and using simple, text
-based menus. Menus are displayed as lists of labeled entries on the
-console, and an entry can be selected by entering its label.
-
-To use the menu code, enable CONFIG_MENU, and include "menu.h" where
-the interfaces should be available.
-
-Menus are composed of items. Each item has a key used to identify it in
-the menu, and an opaque pointer to data controlled by the consumer.
-
-If you want to show a menu, instead starting the shell, define
-CONFIG_AUTOBOOT_MENU_SHOW. You have to code the int menu_show(int bootdelay)
-function, which handle your menu. This function returns the remaining
-bootdelay.
-
-Interfaces
-----------
-#include "menu.h"
-
-/*
- * Consumers of the menu interfaces will use a struct menu * as the
- * handle for a menu. struct menu is only fully defined in menu.c,
- * preventing consumers of the menu interfaces from accessing its
- * contents directly.
- */
-struct menu;
-
-/*
- * NOTE: See comments in common/menu.c for more detailed documentation on
- * these interfaces.
- */
-
-/*
- * menu_create() - Creates a menu handle with default settings
- */
-struct menu *menu_create(char *title, int timeout, int prompt,
-                               void (*item_data_print)(void *),
-                               char *(*item_choice)(void *),
-                               void *item_choice_data);
-
-/*
- * menu_item_add() - Adds or replaces a menu item
- */
-int menu_item_add(struct menu *m, char *item_key, void *item_data);
-
-/*
- * menu_default_set() - Sets the default choice for the menu
- */
-int menu_default_set(struct menu *m, char *item_key);
-
-/*
- * menu_default_choice() - Set *choice to point to the default item's data
- */
-int menu_default_choice(struct menu *m, void **choice);
-
-/*
- * menu_get_choice() - Returns the user's selected menu entry, or the
- * default if the menu is set to not prompt or the timeout expires.
- */
-int menu_get_choice(struct menu *m, void **choice);
-
-/*
- * menu_destroy() - frees the memory used by a menu and its items.
- */
-int menu_destroy(struct menu *m);
-
-/*
- * menu_display_statusline(struct menu *m);
- * shows a statusline for every menu_display call.
- */
-void menu_display_statusline(struct menu *m);
-
-Example Code
-------------
-This example creates a menu that always prompts, and allows the user
-to pick from a list of tools.  The item key and data are the same.
-
-#include "menu.h"
-
-char *tools[] = {
-       "Hammer",
-       "Screwdriver",
-       "Nail gun",
-       NULL
-};
-
-char *pick_a_tool(void)
-{
-       struct menu *m;
-       int i;
-       char *tool = NULL;
-
-       m = menu_create("Tools", 0, 1, NULL);
-
-       for(i = 0; tools[i]; i++) {
-               if (menu_item_add(m, tools[i], tools[i]) != 1) {
-                       printf("failed to add item!");
-                       menu_destroy(m);
-                       return NULL;
-               }
-       }
-
-       if (menu_get_choice(m, (void **)&tool) != 1)
-               printf("Problem picking tool!\n");
-
-       menu_destroy(m);
-
-       return tool;
-}
-
-void caller(void)
-{
-       char *tool = pick_a_tool();
-
-       if (tool) {
-               printf("picked a tool: %s\n", tool);
-               use_tool(tool);
-       }
-}
index f751902..a9ccdb7 100644 (file)
@@ -18,7 +18,7 @@ Get and Build the ARM Trusted firmware
 
 Note: builddir is U-Boot build directory (source directory for in-tree builds)
 Get ATF from: https://source.codeaurora.org/external/imx/imx-atf
-branch: imx_4.19.35_1.0.0
+branch: imx_5.4.47_2.2.0
 
 .. code-block:: bash
 
@@ -30,10 +30,10 @@ Get the ddr firmware
 
 .. code-block:: bash
 
-   $ wget https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/firmware-imx-8.0.bin
-   $ chmod +x firmware-imx-8.0.bin
-   $ ./firmware-imx-8.0
-   $ cp firmware-imx-8.0/firmware/ddr/synopsys/lpddr4*.bin $(builddir)
+   $ wget https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/firmware-imx-8.9.bin
+   $ chmod +x firmware-imx-8.9.bin
+   $ ./firmware-imx-8.9
+   $ cp firmware-imx-8.9/firmware/ddr/synopsys/lpddr4*.bin $(builddir)
 
 Build U-Boot
 ------------
index c3e92ce..375e0bb 100644 (file)
@@ -18,7 +18,7 @@ Get and Build the ARM Trusted firmware
 
 Note: srctree is U-Boot source directory
 Get ATF from: https://source.codeaurora.org/external/imx/imx-atf
-branch: imx_4.19.35_1.1.0
+branch: imx_5.4.47_2.2.0
 
 .. code-block:: bash
 
@@ -30,10 +30,10 @@ Get the ddr firmware
 
 .. code-block:: bash
 
-   $ wget https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/firmware-imx-8.5.bin
-   $ chmod +x firmware-imx-8.5.bin
-   $ ./firmware-imx-8.5
-   $ cp firmware-imx-8.5/firmware/ddr/synopsys/ddr4*.bin $(srctree)
+   $ wget https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/firmware-imx-8.9.bin
+   $ chmod +x firmware-imx-8.9.bin
+   $ ./firmware-imx-8.9
+   $ cp firmware-imx-8.9/firmware/ddr/synopsys/ddr4*.bin $(srctree)
 
 Build U-Boot
 ------------
index 96df6d4..ccffcf7 100644 (file)
@@ -18,7 +18,7 @@ Get and Build the ARM Trusted firmware
 
 Note: $(srctree) is the U-Boot source directory
 Get ATF from: https://source.codeaurora.org/external/imx/imx-atf
-branch: imx_5.4.3_2.0.0
+branch: imx_5.4.47_2.2.0
 
 .. code-block:: bash
 
@@ -30,13 +30,13 @@ Get the ddr firmware
 
 .. code-block:: bash
 
-   $ wget https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/firmware-imx-8.7.bin
-   $ chmod +x firmware-imx-8.7.bin
-   $ ./firmware-imx-8.7.bin
-   $ cp firmware-imx-8.7/firmware/ddr/synopsys/lpddr4_pmu_train_1d_dmem_201904.bin $(srctree)/lpddr4_pmu_train_1d_dmem.bin
-   $ cp firmware-imx-8.7/firmware/ddr/synopsys/lpddr4_pmu_train_1d_imem_201904.bin $(srctree)/lpddr4_pmu_train_1d_imem.bin
-   $ cp firmware-imx-8.7/firmware/ddr/synopsys/lpddr4_pmu_train_2d_dmem_201904.bin $(srctree)/lpddr4_pmu_train_2d_dmem.bin
-   $ cp firmware-imx-8.7/firmware/ddr/synopsys/lpddr4_pmu_train_2d_imem_201904.bin $(srctree)/lpddr4_pmu_train_2d_imem.bin
+   $ wget https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/firmware-imx-8.9.bin
+   $ chmod +x firmware-imx-8.9.bin
+   $ ./firmware-imx-8.9.bin
+   $ cp firmware-imx-8.9/firmware/ddr/synopsys/lpddr4_pmu_train_1d_dmem_201904.bin $(srctree)/lpddr4_pmu_train_1d_dmem.bin
+   $ cp firmware-imx-8.9/firmware/ddr/synopsys/lpddr4_pmu_train_1d_imem_201904.bin $(srctree)/lpddr4_pmu_train_1d_imem.bin
+   $ cp firmware-imx-8.9/firmware/ddr/synopsys/lpddr4_pmu_train_2d_dmem_201904.bin $(srctree)/lpddr4_pmu_train_2d_dmem.bin
+   $ cp firmware-imx-8.9/firmware/ddr/synopsys/lpddr4_pmu_train_2d_imem_201904.bin $(srctree)/lpddr4_pmu_train_2d_imem.bin
 
 Build U-Boot
 ------------
index 0a64ecc..c269fde 100644 (file)
@@ -18,7 +18,7 @@ Get and Build the ARM Trusted firmware
 
 Note: srctree is U-Boot source directory
 Get ATF from: https://source.codeaurora.org/external/imx/imx-atf
-branch: imx_4.19.35_1.0.0
+branch: imx_5.4.47_2.2.0
 
 .. code-block:: bash
 
@@ -30,11 +30,11 @@ Get the ddr and hdmi firmware
 
 .. code-block:: bash
 
-   $ wget https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/firmware-imx-7.9.bin
-   $ chmod +x firmware-imx-7.9.bin
-   $ ./firmware-imx-7.9.bin
-   $ cp firmware-imx-7.9/firmware/hdmi/cadence/signed_hdmi_imx8m.bin $(builddir)
-   $ cp firmware-imx-7.9/firmware/ddr/synopsys/lpddr4*.bin $(builddir)
+   $ wget https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/firmware-imx-8.9.bin
+   $ chmod +x firmware-imx-8.9.bin
+   $ ./firmware-imx-8.9.bin
+   $ cp firmware-imx-8.9/firmware/hdmi/cadence/signed_hdmi_imx8m.bin $(builddir)
+   $ cp firmware-imx-8.9/firmware/ddr/synopsys/lpddr4*.bin $(builddir)
 
 Build U-Boot
 ------------
index 0a7e204..beaa64d 100644 (file)
@@ -3,13 +3,32 @@
 Develop U-Boot
 ==============
 
+Implementation
+--------------
 
 .. toctree::
-   :maxdepth: 2
+   :maxdepth: 1
 
-   coccinelle
    commands
-   crash_dumps
    global_data
    logging
+   menus
+
+Debugging
+---------
+
+.. toctree::
+   :maxdepth: 1
+
+   crash_dumps
    trace
+
+Testing
+-------
+
+.. toctree::
+   :maxdepth: 1
+
+   coccinelle
+   testing
+   py_testing
diff --git a/doc/develop/menus.rst b/doc/develop/menus.rst
new file mode 100644 (file)
index 0000000..dda8f96
--- /dev/null
@@ -0,0 +1,131 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. Copyright 2010-2011 Calxeda, Inc.
+
+Menus
+=====
+
+U-Boot provides a set of interfaces for creating and using simple, text
+based menus. Menus are displayed as lists of labeled entries on the
+console, and an entry can be selected by entering its label.
+
+To use the menu code, enable CONFIG_MENU, and include "menu.h" where
+the interfaces should be available.
+
+Menus are composed of items. Each item has a key used to identify it in
+the menu, and an opaque pointer to data controlled by the consumer.
+
+If you want to show a menu, instead starting the shell, define
+CONFIG_AUTOBOOT_MENU_SHOW. You have to code the int menu_show(int bootdelay)
+function, which handle your menu. This function returns the remaining
+bootdelay.
+
+Interfaces
+----------
+
+.. code-block:: c
+
+    #include "menu.h"
+
+    /*
+     * Consumers of the menu interfaces will use a struct menu * as the
+     * handle for a menu. struct menu is only fully defined in menu.c,
+     * preventing consumers of the menu interfaces from accessing its
+     * contents directly.
+     */
+    struct menu;
+
+    /*
+     * NOTE: See comments in common/menu.c for more detailed documentation on
+     * these interfaces.
+     */
+
+    /*
+     * menu_create() - Creates a menu handle with default settings
+     */
+    struct menu *menu_create(char *title, int timeout, int prompt,
+                             void (*item_data_print)(void *),
+                             char *(*item_choice)(void *),
+                             void *item_choice_data);
+
+    /*
+     * menu_item_add() - Adds or replaces a menu item
+     */
+    int menu_item_add(struct menu *m, char *item_key, void *item_data);
+
+    /*
+     * menu_default_set() - Sets the default choice for the menu
+     */
+    int menu_default_set(struct menu *m, char *item_key);
+
+    /*
+     * menu_default_choice() - Set *choice to point to the default item's data
+     */
+    int menu_default_choice(struct menu *m, void **choice);
+
+    /*
+     * menu_get_choice() - Returns the user's selected menu entry, or the
+     * default if the menu is set to not prompt or the timeout expires.
+     */
+    int menu_get_choice(struct menu *m, void **choice);
+
+    /*
+     * menu_destroy() - frees the memory used by a menu and its items.
+     */
+    int menu_destroy(struct menu *m);
+
+    /*
+     * menu_display_statusline(struct menu *m);
+     * shows a statusline for every menu_display call.
+     */
+    void menu_display_statusline(struct menu *m);
+
+Example Code
+------------
+
+This example creates a menu that always prompts, and allows the user
+to pick from a list of tools.  The item key and data are the same.
+
+.. code-block:: c
+
+    #include "menu.h"
+
+    char *tools[] = {
+        "Hammer",
+        "Screwdriver",
+        "Nail gun",
+        NULL
+    };
+
+    char *pick_a_tool(void)
+    {
+        struct menu *m;
+        int i;
+        char *tool = NULL;
+
+        m = menu_create("Tools", 0, 1, NULL);
+
+        for(i = 0; tools[i]; i++) {
+            if (menu_item_add(m, tools[i], tools[i]) != 1) {
+                printf("failed to add item!");
+                menu_destroy(m);
+                return NULL;
+            }
+        }
+
+        if (menu_get_choice(m, (void **)&tool) != 1)
+            printf("Problem picking tool!\n");
+
+        menu_destroy(m);
+
+        return tool;
+    }
+
+    void caller(void)
+    {
+        char *tool = pick_a_tool();
+
+        if (tool) {
+            printf("picked a tool: %s\n", tool);
+            use_tool(tool);
+        }
+    }
similarity index 74%
rename from test/py/README.md
rename to doc/develop/py_testing.rst
index fddc104..f71e837 100644 (file)
@@ -1,6 +1,8 @@
-# U-Boot pytest suite
+U-Boot pytest suite
+===================
 
-## Introduction
+Introduction
+------------
 
 This tool aims to test U-Boot by executing U-Boot shell commands using the
 console interface. A single top-level script exists to execute or attach to the
@@ -14,40 +16,42 @@ results. Advantages of this approach are:
   flexible than writing it all in C.
 - It is reasonably simple to interact with U-Boot in this way.
 
-## Requirements
+Requirements
+------------
 
 The test suite is implemented using pytest. Interaction with the U-Boot console
 involves executing some binary and interacting with its stdin/stdout. You will
 need to implement various "hook" scripts that are called by the test suite at
 the appropriate time.
 
-In order to run the testsuite at a minimum we require that both python3 and
-pip for python3 be installed.  All of the required python modules are
-described in the requirements.txt file in this directory and can be installed
-with the command ```pip install -r requirements.txt```
+In order to run the test suite at a minimum we require that both Python 3 and
+pip for Python 3 are installed. All of the required python modules are
+described in the requirements.txt file in the /test/py/ directory and can be
+installed via the command
+
+.. code-block:: bash
+
+   pip install -r requirements.txt
 
 In order to execute certain tests on their supported platforms other tools
-will be required.  The following is an incomplete list:
-
-| Package        |
-| -------------- |
-| gdisk          |
-| dfu-util       |
-| dtc            |
-| openssl        |
-| sudo OR guestmount |
-| e2fsprogs      |
-| util-linux     |
-| coreutils      |
-| dosfstools     |
-| efitools       |
-| mount          |
-| mtools         |
-| sbsigntool     |
-| udisks2        |
-
-
-Please use the apporirate commands for your distribution to match these tools
+will be required. The following is an incomplete list:
+
+* gdisk
+* dfu-util
+* dtc
+* openssl
+* sudo OR guestmount
+* e2fsprogs
+* util-linux
+* coreutils
+* dosfstools
+* efitools
+* mount
+* mtools
+* sbsigntool
+* udisks2
+
+Please use the appropriate commands for your distribution to match these tools
 up with the package that provides them.
 
 The test script supports either:
@@ -58,28 +62,31 @@ The test script supports either:
   physical board, attach to the board's console stream, and reset the board.
   Further details are described later.
 
-### Using `virtualenv` to provide requirements
+Using `virtualenv` to provide requirements
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 The recommended way to run the test suite, in order to ensure reproducibility
 is to use `virtualenv` to set up the necessary environment.  This can be done
 via the following commands:
 
-```bash
-$ cd /path/to/u-boot
-$ sudo apt-get install python3 python3-virtualenv
-$ virtualenv -p /usr/bin/python3 venv
-$ . ./venv/bin/activate
-$ pip install -r test/py/requirements.txt
-```
 
-## Testing sandbox
+.. code-block:: console
+
+    $ cd /path/to/u-boot
+    $ sudo apt-get install python3 python3-virtualenv
+    $ virtualenv -p /usr/bin/python3 venv
+    $ . ./venv/bin/activate
+    $ pip install -r test/py/requirements.txt
 
-To run the testsuite on the sandbox port (U-Boot built as a native user-space
+Testing sandbox
+---------------
+
+To run the test suite on the sandbox port (U-Boot built as a native user-space
 application), simply execute:
 
-```
-./test/py/test.py --bd sandbox --build
-```
+.. code-block:: bash
+
+    ./test/py/test.py --bd sandbox --build
 
 The `--bd` option tells the test suite which board type is being tested. This
 lets the test suite know which features the board has, and hence exactly what
@@ -95,7 +102,8 @@ will be written to `${build_dir}/test-log.html`. This is best viewed in a web
 browser, but may be read directly as plain text, perhaps with the aid of the
 `html2text` utility.
 
-### Testing under a debugger
+Testing under a debugger
+~~~~~~~~~~~~~~~~~~~~~~~~
 
 If you need to run sandbox under a debugger, you may pass the command-line
 option `--gdbserver COMM`. This causes two things to happens:
@@ -111,19 +119,21 @@ option `--gdbserver COMM`. This causes two things to happens:
 A usage example is:
 
 Window 1:
-```shell
-./test/py/test.py --bd sandbox --gdbserver localhost:1234
-```
+
+.. code-block:: bash
+
+    ./test/py/test.py --bd sandbox --gdbserver localhost:1234
 
 Window 2:
-```shell
-gdb ./build-sandbox/u-boot -ex 'target remote localhost:1234'
-```
+
+.. code-block:: bash
+
+    gdb ./build-sandbox/u-boot -ex 'target remote localhost:1234'
 
 Alternatively, you could leave off the `-ex` option and type the command
 manually into gdb once it starts.
 
-You can use any debugger you wish, so long as it speaks the gdb remote
+You can use any debugger you wish, as long as it speaks the gdb remote
 protocol, or any graphical wrapper around gdb.
 
 Some tests deliberately cause the sandbox process to exit, e.g. to test the
@@ -132,30 +142,39 @@ to attach the debugger to the new sandbox instance. If these tests are not
 relevant to your debugging session, you can skip them using pytest's -k
 command-line option; see the next section.
 
-## Command-line options
-
-- `--board-type`, `--bd`, `-B` set the type of the board to be tested. For
-  example, `sandbox` or `seaboard`.
-- `--board-identity`, `--id` set the identity of the board to be tested.
-  This allows differentiation between multiple instances of the same type of
-  physical board that are attached to the same host machine. This parameter is
-  not interpreted by the test script in any way, but rather is simply passed
-  to the hook scripts described below, and may be used in any site-specific
-  way deemed necessary.
-- `--build` indicates that the test script should compile U-Boot itself
-  before running the tests. If using this option, make sure that any
-  environment variables required by the build process are already set, such as
-  `$CROSS_COMPILE`.
-- `--buildman` indicates that `--build` should use buildman to build U-Boot.
-  There is no need to set $CROSS_COMPILE` in this case since buildman handles
-  it.
-- `--build-dir` sets the directory containing the compiled U-Boot binaries.
-  If omitted, this is `${source_dir}/build-${board_type}`.
-- `--result-dir` sets the directory to write results, such as log files,
-  into. If omitted, the build directory is used.
-- `--persistent-data-dir` sets the directory used to store persistent test
-  data. This is test data that may be re-used across test runs, such as file-
-  system images.
+Command-line options
+--------------------
+
+--board-type, --bd, -B
+  set the type of the board to be tested. For example, `sandbox` or `seaboard`.
+
+--board-identity`, --id
+  sets the identity of the board to be tested. This allows differentiation
+  between multiple instances of the same type of physical board that are
+  attached to the same host machine. This parameter is not interpreted by th
+  test script in any way, but rather is simply passed to the hook scripts
+  described below, and may be used in any site-specific way deemed necessary.
+
+--build
+  indicates that the test script should compile U-Boot itself before running
+  the tests. If using this option, make sure that any environment variables
+  required by the build process are already set, such as `$CROSS_COMPILE`.
+
+--buildman
+  indicates that `--build` should use buildman to build U-Boot. There is no need
+  to set $CROSS_COMPILE` in this case since buildman handles it.
+
+--build-dir
+  sets the directory containing the compiled U-Boot binaries. If omitted, this
+  is `${source_dir}/build-${board_type}`.
+
+--result-dir
+  sets the directory to write results, such as log files, into.
+  If omitted, the build directory is used.
+
+--persistent-data-dir
+  sets the directory used to store persistent test data. This is test data that
+  may be re-used across test runs, such as file-system images.
 
 `pytest` also implements a number of its own command-line options. Commonly used
 options are mentioned below. Please see `pytest` documentation for complete
@@ -163,21 +182,26 @@ details. Execute `py.test --version` for a brief summary. Note that U-Boot's
 test.py script passes all command-line arguments directly to `pytest` for
 processing.
 
-- `-k` selects which tests to run. The default is to run all known tests. This
+-k
+  selects which tests to run. The default is to run all known tests. This
   option takes a single argument which is used to filter test names. Simple
   logical operators are supported. For example:
-  - `'ums'` runs only tests with "ums" in their name.
-  - `'ut_dm'` runs only tests with "ut_dm" in their name. Note that in this
+
+  - `'-k ums'` runs only tests with "ums" in their name.
+  - `'-k ut_dm'` runs only tests with "ut_dm" in their name. Note that in this
     case, "ut_dm" is a parameter to a test rather than the test name. The full
     test name is e.g. "test_ut[ut_dm_leak]".
-  - `'not reset'` runs everything except tests with "reset" in their name.
-  - `'ut or hush'` runs only tests with "ut" or "hush" in their name.
-  - `'not (ut or hush)'` runs everything except tests with "ut" or "hush" in
+  - `'-k not reset'` runs everything except tests with "reset" in their name.
+  - `'-k ut or hush'` runs only tests with "ut" or "hush" in their name.
+  - `'-k not (ut or hush)'` runs everything except tests with "ut" or "hush" in
     their name.
-- `-s` prevents pytest from hiding a test's stdout. This allows you to see
+
+-s
+  prevents pytest from hiding a test's stdout. This allows you to see
   U-Boot's console log in real time on pytest's stdout.
 
-## Testing real hardware
+Testing real hardware
+---------------------
 
 The tools and techniques used to interact with real hardware will vary
 radically between different host and target systems, and the whims of the user.
@@ -187,9 +211,11 @@ via `$PATH`. These scripts implement certain actions on behalf of the test
 suite. This keeps the test suite simple and isolated from system variances
 unrelated to U-Boot features.
 
-### Hook scripts
+Hook scripts
+~~~~~~~~~~~~
 
-#### Environment variables
+Environment variables
+'''''''''''''''''''''
 
 The following environment variables are set when running hook scripts:
 
@@ -202,16 +228,18 @@ The following environment variables are set when running hook scripts:
 - `UBOOT_RESULT_DIR` the test result directory.
 - `UBOOT_PERSISTENT_DATA_DIR` the test persistent data directory.
 
-#### `u-boot-test-console`
+u-boot-test-console
+'''''''''''''''''''
 
 This script provides access to the U-Boot console. The script's stdin/stdout
 should be connected to the board's console. This process should continue to run
 indefinitely, until killed. The test suite will run this script in parallel
 with all other hooks.
 
-This script may be implemented e.g. by exec()ing `cu`, `kermit`, `conmux`, etc.
+This script may be implemented e.g. by executing `cu`, `kermit`, `conmux`, etc.
+via exec().
 
-If you are able to run U-Boot under a hardware simulator such as qemu, then
+If you are able to run U-Boot under a hardware simulator such as QEMU, then
 you would likely spawn that simulator from this script. However, note that
 `u-boot-test-reset` may be called multiple times per test script run, and must
 cause U-Boot to start execution from scratch each time. Hopefully your
@@ -219,10 +247,11 @@ simulator includes a virtual reset button! If not, you can launch the
 simulator from `u-boot-test-reset` instead, while arranging for this console
 process to always communicate with the current simulator instance.
 
-#### `u-boot-test-flash`
+u-boot-test-flash
+'''''''''''''''''
 
 Prior to running the test suite against a board, some arrangement must be made
-so that the board executes the particular U-Boot binary to be tested. Often,
+so that the board executes the particular U-Boot binary to be tested. Often
 this involves writing the U-Boot binary to the board's flash ROM. The test
 suite calls this hook script for that purpose.
 
@@ -248,7 +277,8 @@ hook script appropriately.
 This script will typically be implemented by calling out to some SoC- or
 board-specific vendor flashing utility.
 
-#### `u-boot-test-reset`
+u-boot-test-reset
+'''''''''''''''''
 
 Whenever the test suite needs to reset the target board, this script is
 executed. This is guaranteed to happen at least once, prior to executing the
@@ -261,20 +291,22 @@ relay or electronic switch attached to the board's reset signal.
 
 The semantics of this script require that when it is executed, U-Boot will
 start running from scratch. If the U-Boot binary to be tested has been written
-to flash, pulsing the board's reset signal is likely all this script need do.
-However, in some scenarios, this script may perform other actions. For
+to flash, pulsing the board's reset signal is likely all this script needs to
+do. However, in some scenarios, this script may perform other actions. For
 example, it may call out to some SoC- or board-specific vendor utility in order
 to download the U-Boot binary directly into RAM and execute it. This would
 avoid the need for `u-boot-test-flash` to actually write U-Boot to flash, thus
 saving wear on the flash chip(s).
 
-#### Examples
+Examples
+''''''''
 
 https://github.com/swarren/uboot-test-hooks contains some working example hook
 scripts, and may be useful as a reference when implementing hook scripts for
 your platform. These scripts are not considered part of U-Boot itself.
 
-### Board-type-specific configuration
+Board-type-specific configuration
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 Each board has a different configuration and behaviour. Many of these
 differences can be automatically detected by parsing the `.config` file in the
@@ -286,7 +318,8 @@ defined in these modules is available for use by any test function. The data
 contained in these scripts must be purely derived from U-Boot source code.
 Hence, these configuration files are part of the U-Boot source tree too.
 
-### Execution environment configuration
+Execution environment configuration
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 Each user's hardware setup may enable testing different subsets of the features
 implemented by a particular board's configuration of U-Boot. For example, a
@@ -304,14 +337,16 @@ U-Boot source tree, and should be installed outside of the source tree. Users
 should set `$PYTHONPATH` prior to running the test script to allow these
 modules to be loaded.
 
-### Board module parameter usage
+Board module parameter usage
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 The test scripts rely on the following variables being defined by the board
 module:
 
-- None at present.
+- none at present
 
-### U-Boot `.config` feature usage
+U-Boot `.config` feature usage
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 The test scripts rely on various U-Boot `.config` features, either directly in
 order to test those features, or indirectly in order to query information from
@@ -328,7 +363,8 @@ instances of:
 - `@pytest.mark.buildconfigspec(...`
 - `@pytest.mark.notbuildconfigspec(...`
 
-### Complete invocation example
+Complete invocation example
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 Assuming that you have installed the hook scripts into $HOME/ubtest/bin, and
 any required environment configuration Python modules into $HOME/ubtest/py,
@@ -336,32 +372,33 @@ then you would likely invoke the test script as follows:
 
 If U-Boot has already been built:
 
-```bash
-PATH=$HOME/ubtest/bin:$PATH \
+.. code-block:: bash
+
+    PATH=$HOME/ubtest/bin:$PATH \
     PYTHONPATH=${HOME}/ubtest/py/${HOSTNAME}:${PYTHONPATH} \
     ./test/py/test.py --bd seaboard
-```
 
 If you want the test script to compile U-Boot for you too, then you likely
 need to set `$CROSS_COMPILE` to allow this, and invoke the test script as
 follows:
 
-```bash
-CROSS_COMPILE=arm-none-eabi- \
+.. code-block:: bash
+
+    CROSS_COMPILE=arm-none-eabi- \
     PATH=$HOME/ubtest/bin:$PATH \
     PYTHONPATH=${HOME}/ubtest/py/${HOSTNAME}:${PYTHONPATH} \
     ./test/py/test.py --bd seaboard --build
-```
 
 or, using buildman to handle it:
 
-```bash
+.. code-block:: bash
+
     PATH=$HOME/ubtest/bin:$PATH \
     PYTHONPATH=${HOME}/ubtest/py/${HOSTNAME}:${PYTHONPATH} \
     ./test/py/test.py --bd seaboard --build --buildman
-```
 
-## Writing tests
+Writing tests
+-------------
 
 Please refer to the pytest documentation for details of writing pytest tests.
 Details specific to the U-Boot test suite are described below.
similarity index 100%
rename from test/README
rename to doc/develop/testing.rst
index 633f227..00ed3eb 100644 (file)
@@ -126,12 +126,10 @@ Root node of the uImage Tree should have the following layout:
     load addresses supplied within sub-image nodes. May be omitted when no
     entry or load addresses are used.
 
-  Mandatory node:
+  Mandatory nodes:
   - images : This node contains a set of sub-nodes, each of them representing
     single component sub-image (like kernel, ramdisk, etc.). At least one
     sub-image is required.
-
-  Optional node:
   - configurations : Contains a set of available configuration nodes and
     defines a default configuration.
 
@@ -169,8 +167,8 @@ the '/images' node should have the following layout:
     to "none".
 
   Conditionally mandatory property:
-  - os : OS name, mandatory for types "kernel" and "ramdisk". Valid OS names
-    are: "openbsd", "netbsd", "freebsd", "4_4bsd", "linux", "svr4", "esix",
+  - os : OS name, mandatory for types "kernel". Valid OS names are:
+    "openbsd", "netbsd", "freebsd", "4_4bsd", "linux", "svr4", "esix",
     "solaris", "irix", "sco", "dell", "ncr", "lynxos", "vxworks", "psos", "qnx",
     "u-boot", "rtems", "unity", "integrity".
   - arch : Architecture name, mandatory for types: "standalone", "kernel",
@@ -179,10 +177,13 @@ the '/images' node should have the following layout:
     "sparc64", "m68k", "microblaze", "nios2", "blackfin", "avr32", "st200",
     "sandbox".
   - entry : entry point address, address size is determined by
-    '#address-cells' property of the root node. Mandatory for for types:
-    "standalone" and "kernel".
+    '#address-cells' property of the root node.
+    Mandatory for types: "firmware", and "kernel".
   - load : load address, address size is determined by '#address-cells'
-    property of the root node. Mandatory for types: "standalone" and "kernel".
+    property of the root node.
+    Mandatory for types: "firmware", and "kernel".
+  - compatible : compatible method for loading image.
+    Mandatory for types: "fpga", and images that do not specify a load address.
 
   Optional nodes:
   - hash-1 : Each hash sub-node represents separate hash or checksum
@@ -205,9 +206,8 @@ o hash-1
 6) '/configurations' node
 -------------------------
 
-The 'configurations' node is optional. If present, it allows to create a
-convenient, labeled boot configurations, which combine together kernel images
-with their ramdisks and fdt blobs.
+The 'configurations' node creates convenient, labeled boot configurations,
+which combine together kernel images with their ramdisks and fdt blobs.
 
 The 'configurations' node has has the following structure:
 
@@ -236,27 +236,22 @@ Each configuration has the following structure:
 o config-1
   |- description = "configuration description"
   |- kernel = "kernel sub-node unit name"
-  |- ramdisk = "ramdisk sub-node unit name"
   |- fdt = "fdt sub-node unit-name" [, "fdt overlay sub-node unit-name", ...]
-  |- fpga = "fpga sub-node unit-name"
   |- loadables = "loadables sub-node unit-name"
   |- compatible = "vendor,board-style device tree compatible string"
 
 
   Mandatory properties:
   - description : Textual configuration description.
-  - kernel : Unit name of the corresponding kernel image (image sub-node of a
-    "kernel" type).
+  - kernel or firmware: Unit name of the corresponding kernel or firmware
+    (u-boot, op-tee, etc) image. If both "kernel" and "firmware" are specified,
+    control is passed to the firmware image.
 
   Optional properties:
-  - ramdisk : Unit name of the corresponding ramdisk image (component image
-    node of a "ramdisk" type).
   - fdt : Unit name of the corresponding fdt blob (component image node of a
     "fdt type"). Additional fdt overlay nodes can be supplied which signify
     that the resulting device tree blob is generated by the first base fdt
     blob with all subsequent overlays applied.
-  - setup : Unit name of the corresponding setup binary (used for booting
-    an x86 kernel). This contains the setup.bin file built by the kernel.
   - fpga : Unit name of the corresponding fpga bitstream blob
     (component image node of a "fpga type").
   - loadables : Unit name containing a list of additional binaries to be
index 81764b4..84776e5 100644 (file)
@@ -4,3 +4,4 @@
 #
 
 obj-$(CONFIG_ASPEED_AST2500) += clk_ast2500.o
+obj-$(CONFIG_ASPEED_AST2600) += clk_ast2600.o
diff --git a/drivers/clk/aspeed/clk_ast2600.c b/drivers/clk/aspeed/clk_ast2600.c
new file mode 100644 (file)
index 0000000..f72d384
--- /dev/null
@@ -0,0 +1,1173 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) ASPEED Technology Inc.
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <asm/io.h>
+#include <dm/lists.h>
+#include <linux/delay.h>
+#include <asm/arch/scu_ast2600.h>
+#include <dt-bindings/clock/ast2600-clock.h>
+#include <dt-bindings/reset/ast2600-reset.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define CLKIN_25M 25000000UL
+
+/* MAC Clock Delay settings */
+#define MAC12_DEF_DELAY_1G             0x0041b75d
+#define MAC12_DEF_DELAY_100M   0x00417410
+#define MAC12_DEF_DELAY_10M            0x00417410
+#define MAC34_DEF_DELAY_1G             0x0010438a
+#define MAC34_DEF_DELAY_100M   0x00104208
+#define MAC34_DEF_DELAY_10M            0x00104208
+
+/*
+ * 3-bit encode of CPU freqeucy
+ * Some code is duplicated
+ */
+enum ast2600_cpu_freq {
+       CPU_FREQ_1200M_1,
+       CPU_FREQ_1600M_1,
+       CPU_FREQ_1200M_2,
+       CPU_FREQ_1600M_2,
+       CPU_FREQ_800M_1,
+       CPU_FREQ_800M_2,
+       CPU_FREQ_800M_3,
+       CPU_FREQ_800M_4,
+};
+
+struct ast2600_clk_priv {
+       struct ast2600_scu *scu;
+};
+
+/*
+ * Clock divider/multiplier configuration struct.
+ * For H-PLL and M-PLL the formula is
+ * (Output Frequency) = CLKIN * ((M + 1) / (N + 1)) / (P + 1)
+ * M - Numerator
+ * N - Denumerator
+ * P - Post Divider
+ * They have the same layout in their control register.
+ *
+ * D-PLL and D2-PLL have extra divider (OD + 1), which is not
+ * yet needed and ignored by clock configurations.
+ */
+union ast2600_pll_reg {
+       uint32_t w;
+       struct {
+               unsigned int m : 13;
+               unsigned int n : 6;
+               unsigned int p : 4;
+               unsigned int off : 1;
+               unsigned int bypass : 1;
+               unsigned int reset : 1;
+               unsigned int reserved : 6;
+       } b;
+};
+
+struct ast2600_pll_cfg {
+       union ast2600_pll_reg reg;
+       unsigned int ext_reg;
+};
+
+struct ast2600_pll_desc {
+       uint32_t in;
+       uint32_t out;
+       struct ast2600_pll_cfg cfg;
+};
+
+static const struct ast2600_pll_desc ast2600_pll_lookup[] = {
+       {
+               .in = CLKIN_25M,
+               .out = 400000000,
+               .cfg.reg.b.m = 95,
+               .cfg.reg.b.n = 2,
+               .cfg.reg.b.p = 1,
+               .cfg.ext_reg = 0x31,
+       },
+       {
+               .in = CLKIN_25M,
+               .out = 200000000,
+               .cfg.reg.b.m = 127,
+               .cfg.reg.b.n = 0,
+               .cfg.reg.b.p = 15,
+               .cfg.ext_reg = 0x3f,
+       },
+       {
+               .in = CLKIN_25M,
+               .out = 334000000,
+               .cfg.reg.b.m = 667,
+               .cfg.reg.b.n = 4,
+               .cfg.reg.b.p = 9,
+               .cfg.ext_reg = 0x14d,
+       },
+       {
+               .in = CLKIN_25M,
+               .out = 1000000000,
+               .cfg.reg.b.m = 119,
+               .cfg.reg.b.n = 2,
+               .cfg.reg.b.p = 0,
+               .cfg.ext_reg = 0x3d,
+       },
+       {
+               .in = CLKIN_25M,
+               .out = 50000000,
+               .cfg.reg.b.m = 95,
+               .cfg.reg.b.n = 2,
+               .cfg.reg.b.p = 15,
+               .cfg.ext_reg = 0x31,
+       },
+};
+
+/* divisor tables */
+static uint32_t axi_ahb_div0_table[] = {
+       3, 2, 3, 4,
+};
+
+static uint32_t axi_ahb_div1_table[] = {
+       3, 4, 6, 8,
+};
+
+static uint32_t axi_ahb_default_table[] = {
+       3, 4, 3, 4, 2, 2, 2, 2,
+};
+
+extern uint32_t ast2600_get_pll_rate(struct ast2600_scu *scu, int pll_idx)
+{
+       union ast2600_pll_reg pll_reg;
+       uint32_t hwstrap1;
+       uint32_t cpu_freq;
+       uint32_t mul = 1, div = 1;
+
+       switch (pll_idx) {
+       case ASPEED_CLK_APLL:
+               pll_reg.w = readl(&scu->apll);
+               break;
+       case ASPEED_CLK_DPLL:
+               pll_reg.w = readl(&scu->dpll);
+               break;
+       case ASPEED_CLK_EPLL:
+               pll_reg.w = readl(&scu->epll);
+               break;
+       case ASPEED_CLK_HPLL:
+               pll_reg.w = readl(&scu->hpll);
+               break;
+       case ASPEED_CLK_MPLL:
+               pll_reg.w = readl(&scu->mpll);
+               break;
+       }
+
+       if (!pll_reg.b.bypass) {
+               /* F = 25Mhz * [(M + 2) / (n + 1)] / (p + 1)
+                * HPLL Numerator (M) = fix 0x5F when SCU500[10]=1
+                * Fixed 0xBF when SCU500[10]=0 and SCU500[8]=1
+                * SCU200[12:0] (default 0x8F) when SCU510[10]=0 and SCU510[8]=0
+                * HPLL Denumerator (N) =       SCU200[18:13] (default 0x2)
+                * HPLL Divider (P)      =      SCU200[22:19] (default 0x0)
+                * HPLL Bandwidth Adj (NB) =  fix 0x2F when SCU500[10]=1
+                * Fixed 0x5F when SCU500[10]=0 and SCU500[8]=1
+                * SCU204[11:0] (default 0x31) when SCU500[10]=0 and SCU500[8]=0
+                */
+               if (pll_idx == ASPEED_CLK_HPLL) {
+                       hwstrap1 = readl(&scu->hwstrap1);
+                       cpu_freq = (hwstrap1 & SCU_HWSTRAP1_CPU_FREQ_MASK) >>
+                                   SCU_HWSTRAP1_CPU_FREQ_SHIFT;
+
+                       switch (cpu_freq) {
+                       case CPU_FREQ_800M_1:
+                       case CPU_FREQ_800M_2:
+                       case CPU_FREQ_800M_3:
+                       case CPU_FREQ_800M_4:
+                               pll_reg.b.m = 0x5f;
+                               break;
+                       case CPU_FREQ_1600M_1:
+                       case CPU_FREQ_1600M_2:
+                               pll_reg.b.m = 0xbf;
+                               break;
+                       default:
+                               pll_reg.b.m = 0x8f;
+                               break;
+                       }
+               }
+
+               mul = (pll_reg.b.m + 1) / (pll_reg.b.n + 1);
+               div = (pll_reg.b.p + 1);
+       }
+
+       return ((CLKIN_25M * mul) / div);
+}
+
+static uint32_t ast2600_get_hclk_rate(struct ast2600_scu *scu)
+{
+       uint32_t rate = ast2600_get_pll_rate(scu, ASPEED_CLK_HPLL);
+       uint32_t axi_div, ahb_div;
+       uint32_t hwstrap1 = readl(&scu->hwstrap1);
+       uint32_t cpu_freq = (hwstrap1 & SCU_HWSTRAP1_CPU_FREQ_MASK) >>
+                            SCU_HWSTRAP1_CPU_FREQ_SHIFT;
+       uint32_t axi_ahb_ratio = (hwstrap1 & SCU_HWSTRAP1_AXI_AHB_CLK_RATIO_MASK) >>
+                                 SCU_HWSTRAP1_AXI_AHB_CLK_RATIO_SHIFT;
+
+       if (hwstrap1 & SCU_HWSTRAP1_CPU_AXI_CLK_RATIO) {
+               axi_ahb_div1_table[0] = axi_ahb_default_table[cpu_freq] * 2;
+               axi_div = 1;
+               ahb_div = axi_ahb_div1_table[axi_ahb_ratio];
+       } else {
+               axi_ahb_div0_table[0] = axi_ahb_default_table[cpu_freq];
+               axi_div = 2;
+               ahb_div = axi_ahb_div0_table[axi_ahb_ratio];
+       }
+
+       return (rate / axi_div / ahb_div);
+}
+
+static uint32_t ast2600_get_bclk_rate(struct ast2600_scu *scu)
+{
+       uint32_t rate = ast2600_get_pll_rate(scu, ASPEED_CLK_HPLL);
+       uint32_t clksrc1 = readl(&scu->clksrc1);
+       uint32_t bclk_div = (clksrc1 & SCU_CLKSRC1_BCLK_DIV_MASK) >>
+                            SCU_CLKSRC1_BCLK_DIV_SHIFT;
+
+       return (rate / ((bclk_div + 1) * 4));
+}
+
+static uint32_t ast2600_get_pclk1_rate(struct ast2600_scu *scu)
+{
+       uint32_t rate = ast2600_get_pll_rate(scu, ASPEED_CLK_HPLL);
+       uint32_t clksrc1 = readl(&scu->clksrc1);
+       uint32_t pclk_div = (clksrc1 & SCU_CLKSRC1_PCLK_DIV_MASK) >>
+                            SCU_CLKSRC1_PCLK_DIV_SHIFT;
+
+       return (rate / ((pclk_div + 1) * 4));
+}
+
+static uint32_t ast2600_get_pclk2_rate(struct ast2600_scu *scu)
+{
+       uint32_t rate = ast2600_get_hclk_rate(scu);
+       uint32_t clksrc4 = readl(&scu->clksrc4);
+       uint32_t pclk_div = (clksrc4 & SCU_CLKSRC4_PCLK_DIV_MASK) >>
+                            SCU_CLKSRC4_PCLK_DIV_SHIFT;
+
+       return (rate / ((pclk_div + 1) * 2));
+}
+
+static uint32_t ast2600_get_uxclk_in_rate(struct ast2600_scu *scu)
+{
+       uint32_t rate = 0;
+       uint32_t clksrc5 = readl(&scu->clksrc5);
+       uint32_t uxclk = (clksrc5 & SCU_CLKSRC5_UXCLK_MASK) >>
+                         SCU_CLKSRC5_UXCLK_SHIFT;
+
+       switch (uxclk) {
+       case 0:
+               rate = ast2600_get_pll_rate(scu, ASPEED_CLK_APLL) / 4;
+               break;
+       case 1:
+               rate = ast2600_get_pll_rate(scu, ASPEED_CLK_APLL) / 2;
+               break;
+       case 2:
+               rate = ast2600_get_pll_rate(scu, ASPEED_CLK_APLL);
+               break;
+       case 3:
+               rate = ast2600_get_hclk_rate(scu);
+               break;
+       }
+
+       return rate;
+}
+
+static uint32_t ast2600_get_huxclk_in_rate(struct ast2600_scu *scu)
+{
+       uint32_t rate = 0;
+       uint32_t clksrc5 = readl(&scu->clksrc5);
+       uint32_t huxclk = (clksrc5 & SCU_CLKSRC5_HUXCLK_MASK) >>
+                          SCU_CLKSRC5_HUXCLK_SHIFT;
+
+       switch (huxclk) {
+       case 0:
+               rate = ast2600_get_pll_rate(scu, ASPEED_CLK_APLL) / 4;
+               break;
+       case 1:
+               rate = ast2600_get_pll_rate(scu, ASPEED_CLK_APLL) / 2;
+               break;
+       case 2:
+               rate = ast2600_get_pll_rate(scu, ASPEED_CLK_APLL);
+               break;
+       case 3:
+               rate = ast2600_get_hclk_rate(scu);
+               break;
+       }
+
+       return rate;
+}
+
+static uint32_t ast2600_get_uart_uxclk_rate(struct ast2600_scu *scu)
+{
+       uint32_t rate = ast2600_get_uxclk_in_rate(scu);
+       uint32_t uart_clkgen = readl(&scu->uart_clkgen);
+       uint32_t n = (uart_clkgen & SCU_UART_CLKGEN_N_MASK) >>
+                     SCU_UART_CLKGEN_N_SHIFT;
+       uint32_t r = (uart_clkgen & SCU_UART_CLKGEN_R_MASK) >>
+                     SCU_UART_CLKGEN_R_SHIFT;
+
+       return ((rate * r) / (n * 2));
+}
+
+static uint32_t ast2600_get_uart_huxclk_rate(struct ast2600_scu *scu)
+{
+       uint32_t rate = ast2600_get_huxclk_in_rate(scu);
+       uint32_t huart_clkgen = readl(&scu->huart_clkgen);
+       uint32_t n = (huart_clkgen & SCU_HUART_CLKGEN_N_MASK) >>
+                     SCU_HUART_CLKGEN_N_SHIFT;
+       uint32_t r = (huart_clkgen & SCU_HUART_CLKGEN_R_MASK) >>
+                     SCU_HUART_CLKGEN_R_SHIFT;
+
+       return ((rate * r) / (n * 2));
+}
+
+static uint32_t ast2600_get_sdio_clk_rate(struct ast2600_scu *scu)
+{
+       uint32_t rate = 0;
+       uint32_t clksrc4 = readl(&scu->clksrc4);
+       uint32_t sdio_div = (clksrc4 & SCU_CLKSRC4_SDIO_DIV_MASK) >>
+                            SCU_CLKSRC4_SDIO_DIV_SHIFT;
+
+       if (clksrc4 & SCU_CLKSRC4_SDIO)
+               rate = ast2600_get_pll_rate(scu, ASPEED_CLK_APLL);
+       else
+               rate = ast2600_get_hclk_rate(scu);
+
+       return (rate / ((sdio_div + 1) * 2));
+}
+
+static uint32_t ast2600_get_emmc_clk_rate(struct ast2600_scu *scu)
+{
+       uint32_t rate = ast2600_get_pll_rate(scu, ASPEED_CLK_HPLL);
+       uint32_t clksrc1 = readl(&scu->clksrc1);
+       uint32_t emmc_div = (clksrc1 & SCU_CLKSRC1_EMMC_DIV_MASK) >>
+                            SCU_CLKSRC1_EMMC_DIV_SHIFT;
+
+       return (rate / ((emmc_div + 1) * 4));
+}
+
+static uint32_t ast2600_get_uart_clk_rate(struct ast2600_scu *scu, int uart_idx)
+{
+       uint32_t rate = 0;
+       uint32_t uart5_clk = 0;
+       uint32_t clksrc2 = readl(&scu->clksrc2);
+       uint32_t clksrc4 = readl(&scu->clksrc4);
+       uint32_t clksrc5 = readl(&scu->clksrc5);
+       uint32_t misc_ctrl1 = readl(&scu->misc_ctrl1);
+
+       switch (uart_idx) {
+       case 1:
+       case 2:
+       case 3:
+       case 4:
+       case 6:
+               if (clksrc4 & BIT(uart_idx - 1))
+                       rate = ast2600_get_uart_huxclk_rate(scu);
+               else
+                       rate = ast2600_get_uart_uxclk_rate(scu);
+               break;
+       case 5:
+               /*
+                * SCU0C[12] and SCU304[14] together decide
+                * the UART5 clock generation
+                */
+               if (misc_ctrl1 & SCU_MISC_CTRL1_UART5_DIV)
+                       uart5_clk = 0x1 << 1;
+
+               if (clksrc2 & SCU_CLKSRC2_UART5)
+                       uart5_clk |= 0x1;
+
+               switch (uart5_clk) {
+               case 0:
+                       rate = 24000000;
+                       break;
+               case 1:
+                       rate = 192000000;
+                       break;
+               case 2:
+                       rate = 24000000 / 13;
+                       break;
+               case 3:
+                       rate = 192000000 / 13;
+                       break;
+               }
+
+               break;
+       case 7:
+       case 8:
+       case 9:
+       case 10:
+       case 11:
+       case 12:
+       case 13:
+               if (clksrc5 & BIT(uart_idx - 1))
+                       rate = ast2600_get_uart_huxclk_rate(scu);
+               else
+                       rate = ast2600_get_uart_uxclk_rate(scu);
+               break;
+       }
+
+       return rate;
+}
+
+static ulong ast2600_clk_get_rate(struct clk *clk)
+{
+       struct ast2600_clk_priv *priv = dev_get_priv(clk->dev);
+       ulong rate = 0;
+
+       switch (clk->id) {
+       case ASPEED_CLK_HPLL:
+       case ASPEED_CLK_EPLL:
+       case ASPEED_CLK_DPLL:
+       case ASPEED_CLK_MPLL:
+       case ASPEED_CLK_APLL:
+               rate = ast2600_get_pll_rate(priv->scu, clk->id);
+               break;
+       case ASPEED_CLK_AHB:
+               rate = ast2600_get_hclk_rate(priv->scu);
+               break;
+       case ASPEED_CLK_APB1:
+               rate = ast2600_get_pclk1_rate(priv->scu);
+               break;
+       case ASPEED_CLK_APB2:
+               rate = ast2600_get_pclk2_rate(priv->scu);
+               break;
+       case ASPEED_CLK_GATE_UART1CLK:
+               rate = ast2600_get_uart_clk_rate(priv->scu, 1);
+               break;
+       case ASPEED_CLK_GATE_UART2CLK:
+               rate = ast2600_get_uart_clk_rate(priv->scu, 2);
+               break;
+       case ASPEED_CLK_GATE_UART3CLK:
+               rate = ast2600_get_uart_clk_rate(priv->scu, 3);
+               break;
+       case ASPEED_CLK_GATE_UART4CLK:
+               rate = ast2600_get_uart_clk_rate(priv->scu, 4);
+               break;
+       case ASPEED_CLK_GATE_UART5CLK:
+               rate = ast2600_get_uart_clk_rate(priv->scu, 5);
+               break;
+       case ASPEED_CLK_BCLK:
+               rate = ast2600_get_bclk_rate(priv->scu);
+               break;
+       case ASPEED_CLK_SDIO:
+               rate = ast2600_get_sdio_clk_rate(priv->scu);
+               break;
+       case ASPEED_CLK_EMMC:
+               rate = ast2600_get_emmc_clk_rate(priv->scu);
+               break;
+       case ASPEED_CLK_UARTX:
+               rate = ast2600_get_uart_uxclk_rate(priv->scu);
+               break;
+       case ASPEED_CLK_HUARTX:
+               rate = ast2600_get_uart_huxclk_rate(priv->scu);
+               break;
+       default:
+               debug("can't get clk rate\n");
+               return -ENOENT;
+       }
+
+       return rate;
+}
+
+/**
+ * @brief      lookup PLL divider config by input/output rate
+ * @param[in]  *pll - PLL descriptor
+ * @return     true - if PLL divider config is found, false - else
+ * The function caller shall fill "pll->in" and "pll->out",
+ * then this function will search the lookup table
+ * to find a valid PLL divider configuration.
+ */
+static bool ast2600_search_clock_config(struct ast2600_pll_desc *pll)
+{
+       uint32_t i;
+       const struct ast2600_pll_desc *def_desc;
+       bool is_found = false;
+
+       for (i = 0; i < ARRAY_SIZE(ast2600_pll_lookup); i++) {
+               def_desc = &ast2600_pll_lookup[i];
+
+               if (def_desc->in == pll->in && def_desc->out == pll->out) {
+                       is_found = true;
+                       pll->cfg.reg.w = def_desc->cfg.reg.w;
+                       pll->cfg.ext_reg = def_desc->cfg.ext_reg;
+                       break;
+               }
+       }
+       return is_found;
+}
+
+static uint32_t ast2600_configure_pll(struct ast2600_scu *scu,
+                                struct ast2600_pll_cfg *p_cfg, int pll_idx)
+{
+       uint32_t addr, addr_ext;
+       uint32_t reg;
+
+       switch (pll_idx) {
+       case ASPEED_CLK_HPLL:
+               addr = (uint32_t)(&scu->hpll);
+               addr_ext = (uint32_t)(&scu->hpll_ext);
+               break;
+       case ASPEED_CLK_MPLL:
+               addr = (uint32_t)(&scu->mpll);
+               addr_ext = (uint32_t)(&scu->mpll_ext);
+               break;
+       case ASPEED_CLK_DPLL:
+               addr = (uint32_t)(&scu->dpll);
+               addr_ext = (uint32_t)(&scu->dpll_ext);
+               break;
+       case ASPEED_CLK_EPLL:
+               addr = (uint32_t)(&scu->epll);
+               addr_ext = (uint32_t)(&scu->epll_ext);
+               break;
+       case ASPEED_CLK_APLL:
+               addr = (uint32_t)(&scu->apll);
+               addr_ext = (uint32_t)(&scu->apll_ext);
+               break;
+       default:
+               debug("unknown PLL index\n");
+               return 1;
+       }
+
+       p_cfg->reg.b.bypass = 0;
+       p_cfg->reg.b.off = 1;
+       p_cfg->reg.b.reset = 1;
+
+       reg = readl(addr);
+       reg &= ~GENMASK(25, 0);
+       reg |= p_cfg->reg.w;
+       writel(reg, addr);
+
+       /* write extend parameter */
+       writel(p_cfg->ext_reg, addr_ext);
+       udelay(100);
+       p_cfg->reg.b.off = 0;
+       p_cfg->reg.b.reset = 0;
+       reg &= ~GENMASK(25, 0);
+       reg |= p_cfg->reg.w;
+       writel(reg, addr);
+       while (!(readl(addr_ext) & BIT(31)))
+               ;
+
+       return 0;
+}
+
+static uint32_t ast2600_configure_ddr(struct ast2600_scu *scu, ulong rate)
+{
+       struct ast2600_pll_desc mpll;
+
+       mpll.in = CLKIN_25M;
+       mpll.out = rate;
+       if (ast2600_search_clock_config(&mpll) == false) {
+               printf("error!! unable to find valid DDR clock setting\n");
+               return 0;
+       }
+       ast2600_configure_pll(scu, &mpll.cfg, ASPEED_CLK_MPLL);
+
+       return ast2600_get_pll_rate(scu, ASPEED_CLK_MPLL);
+}
+
+static ulong ast2600_clk_set_rate(struct clk *clk, ulong rate)
+{
+       struct ast2600_clk_priv *priv = dev_get_priv(clk->dev);
+       ulong new_rate;
+
+       switch (clk->id) {
+       case ASPEED_CLK_MPLL:
+               new_rate = ast2600_configure_ddr(priv->scu, rate);
+               break;
+       default:
+               return -ENOENT;
+       }
+
+       return new_rate;
+}
+
+static uint32_t ast2600_configure_mac12_clk(struct ast2600_scu *scu)
+{
+       /* scu340[25:0]: 1G default delay */
+       clrsetbits_le32(&scu->mac12_clk_delay, GENMASK(25, 0),
+                       MAC12_DEF_DELAY_1G);
+
+       /* set 100M/10M default delay */
+       writel(MAC12_DEF_DELAY_100M, &scu->mac12_clk_delay_100M);
+       writel(MAC12_DEF_DELAY_10M, &scu->mac12_clk_delay_10M);
+
+       /* MAC AHB = HPLL / 6 */
+       clrsetbits_le32(&scu->clksrc1, SCU_CLKSRC1_MAC_DIV_MASK,
+                       (0x2 << SCU_CLKSRC1_MAC_DIV_SHIFT));
+
+       return 0;
+}
+
+static uint32_t ast2600_configure_mac34_clk(struct ast2600_scu *scu)
+{
+       /*
+        * scu350[31]   RGMII 125M source: 0 = from IO pin
+        * scu350[25:0] MAC 1G delay
+        */
+       clrsetbits_le32(&scu->mac34_clk_delay, (BIT(31) | GENMASK(25, 0)),
+                       MAC34_DEF_DELAY_1G);
+       writel(MAC34_DEF_DELAY_100M, &scu->mac34_clk_delay_100M);
+       writel(MAC34_DEF_DELAY_10M, &scu->mac34_clk_delay_10M);
+
+       /*
+        * clock source seletion and divider
+        * scu310[26:24] : MAC AHB bus clock = HCLK / 2
+        * scu310[18:16] : RMII 50M = HCLK_200M / 4
+        */
+       clrsetbits_le32(&scu->clksrc4,
+                       (SCU_CLKSRC4_MAC_DIV_MASK | SCU_CLKSRC4_RMII34_DIV_MASK),
+                       ((0x0 << SCU_CLKSRC4_MAC_DIV_SHIFT)
+                        | (0x3 << SCU_CLKSRC4_RMII34_DIV_SHIFT)));
+
+       /*
+        * set driving strength
+        * scu458[3:2] : MAC4 driving strength
+        * scu458[1:0] : MAC3 driving strength
+        */
+       clrsetbits_le32(&scu->pinmux16,
+                       SCU_PINCTRL16_MAC4_DRIVING_MASK | SCU_PINCTRL16_MAC3_DRIVING_MASK,
+                       (0x3 << SCU_PINCTRL16_MAC4_DRIVING_SHIFT)
+                        | (0x3 << SCU_PINCTRL16_MAC3_DRIVING_SHIFT));
+
+       return 0;
+}
+
+/**
+ * ast2600 RGMII clock source tree
+ * 125M from external PAD -------->|\
+ * HPLL -->|\                      | |---->RGMII 125M for MAC#1 & MAC#2
+ *         | |---->| divider |---->|/                             +
+ * EPLL -->|/                                                     |
+ *                                                                |
+ * +---------<-----------|RGMIICK PAD output enable|<-------------+
+ * |
+ * +--------------------------->|\
+ *                              | |----> RGMII 125M for MAC#3 & MAC#4
+ * HCLK 200M ---->|divider|---->|/
+ * To simplify the control flow:
+ * 1. RGMII 1/2 always use EPLL as the internal clock source
+ * 2. RGMII 3/4 always use RGMIICK pad as the RGMII 125M source
+ * 125M from external PAD -------->|\
+ *                                 | |---->RGMII 125M for MAC#1 & MAC#2
+ *         EPLL---->| divider |--->|/                             +
+ *                                                                |
+ * +<--------------------|RGMIICK PAD output enable|<-------------+
+ * |
+ * +--------------------------->RGMII 125M for MAC#3 & MAC#4
+ */
+#define RGMIICK_SRC_PAD                0
+#define RGMIICK_SRC_EPLL       1 /* recommended */
+#define RGMIICK_SRC_HPLL       2
+
+#define RGMIICK_DIV2   1
+#define RGMIICK_DIV3   2
+#define RGMIICK_DIV4   3
+#define RGMIICK_DIV5   4
+#define RGMIICK_DIV6   5
+#define RGMIICK_DIV7   6
+#define RGMIICK_DIV8   7 /* recommended */
+
+#define RMIICK_DIV4            0
+#define RMIICK_DIV8            1
+#define RMIICK_DIV12   2
+#define RMIICK_DIV16   3
+#define RMIICK_DIV20   4 /* recommended */
+#define RMIICK_DIV24   5
+#define RMIICK_DIV28   6
+#define RMIICK_DIV32   7
+
+struct ast2600_mac_clk_div {
+       uint32_t src; /* 0=external PAD, 1=internal PLL */
+       uint32_t fin; /* divider input speed */
+       uint32_t n; /* 0=div2, 1=div2, 2=div3, 3=div4,...,7=div8 */
+       uint32_t fout; /* fout = fin / n */
+};
+
+struct ast2600_mac_clk_div rgmii_clk_defconfig = {
+       .src = ASPEED_CLK_EPLL,
+       .fin = 1000000000,
+       .n = RGMIICK_DIV8,
+       .fout = 125000000,
+};
+
+struct ast2600_mac_clk_div rmii_clk_defconfig = {
+       .src = ASPEED_CLK_EPLL,
+       .fin = 1000000000,
+       .n = RMIICK_DIV20,
+       .fout = 50000000,
+};
+
+static void ast2600_init_mac_pll(struct ast2600_scu *p_scu,
+                                struct ast2600_mac_clk_div *p_cfg)
+{
+       struct ast2600_pll_desc pll;
+
+       pll.in = CLKIN_25M;
+       pll.out = p_cfg->fin;
+       if (ast2600_search_clock_config(&pll) == false) {
+               pr_err("unable to find valid ETHNET MAC clock setting\n");
+               return;
+       }
+       ast2600_configure_pll(p_scu, &pll.cfg, p_cfg->src);
+}
+
+static void ast2600_init_rgmii_clk(struct ast2600_scu *p_scu,
+                                  struct ast2600_mac_clk_div *p_cfg)
+{
+       uint32_t reg_304 = readl(&p_scu->clksrc2);
+       uint32_t reg_340 = readl(&p_scu->mac12_clk_delay);
+       uint32_t reg_350 = readl(&p_scu->mac34_clk_delay);
+
+       reg_340 &= ~GENMASK(31, 29);
+       /* scu340[28]: RGMIICK PAD output enable (to MAC 3/4) */
+       reg_340 |= BIT(28);
+       if (p_cfg->src == ASPEED_CLK_EPLL || p_cfg->src == ASPEED_CLK_HPLL) {
+               /*
+                * re-init PLL if the current PLL output frequency doesn't match
+                * the divider setting
+                */
+               if (p_cfg->fin != ast2600_get_pll_rate(p_scu, p_cfg->src))
+                       ast2600_init_mac_pll(p_scu, p_cfg);
+               /* scu340[31]: select RGMII 125M from internal source */
+               reg_340 |= BIT(31);
+       }
+
+       reg_304 &= ~GENMASK(23, 20);
+
+       /* set clock divider */
+       reg_304 |= (p_cfg->n & 0x7) << 20;
+
+       /* select internal clock source */
+       if (p_cfg->src == ASPEED_CLK_HPLL)
+               reg_304 |= BIT(23);
+
+       /* RGMII 3/4 clock source select */
+       reg_350 &= ~BIT(31);
+
+       writel(reg_304, &p_scu->clksrc2);
+       writel(reg_340, &p_scu->mac12_clk_delay);
+       writel(reg_350, &p_scu->mac34_clk_delay);
+}
+
+/**
+ * ast2600 RMII/NCSI clock source tree
+ * HPLL -->|\
+ *         | |---->| divider |----> RMII 50M for MAC#1 & MAC#2
+ * EPLL -->|/
+ * HCLK(SCLICLK)---->| divider |----> RMII 50M for MAC#3 & MAC#4
+ */
+static void ast2600_init_rmii_clk(struct ast2600_scu *p_scu,
+                                 struct ast2600_mac_clk_div *p_cfg)
+{
+       uint32_t clksrc2 = readl(&p_scu->clksrc2);
+       uint32_t clksrc4 = readl(&p_scu->clksrc4);
+
+       if (p_cfg->src == ASPEED_CLK_EPLL || p_cfg->src == ASPEED_CLK_HPLL) {
+               /*
+                * re-init PLL if the current PLL output frequency doesn't match
+                * the divider setting
+                */
+               if (p_cfg->fin != ast2600_get_pll_rate(p_scu, p_cfg->src))
+                       ast2600_init_mac_pll(p_scu, p_cfg);
+       }
+
+       clksrc2 &= ~(SCU_CLKSRC2_RMII12 | SCU_CLKSRC2_RMII12_DIV_MASK);
+
+       /* set RMII 1/2 clock divider */
+       clksrc2 |= (p_cfg->n & 0x7) << 16;
+
+       /* RMII clock source selection */
+       if (p_cfg->src == ASPEED_CLK_HPLL)
+               clksrc2 |= SCU_CLKSRC2_RMII12;
+
+       /* set RMII 3/4 clock divider */
+       clksrc4 &= ~SCU_CLKSRC4_RMII34_DIV_MASK;
+       clksrc4 |= (0x3 << SCU_CLKSRC4_RMII34_DIV_SHIFT);
+
+       writel(clksrc2, &p_scu->clksrc2);
+       writel(clksrc4, &p_scu->clksrc4);
+}
+
+static uint32_t ast2600_configure_mac(struct ast2600_scu *scu, int index)
+{
+       uint32_t reset_bit;
+       uint32_t clkgate_bit;
+
+       switch (index) {
+       case 1:
+               reset_bit = BIT(ASPEED_RESET_MAC1);
+               clkgate_bit = SCU_CLKGATE1_MAC1;
+               writel(reset_bit, &scu->modrst_ctrl1);
+               udelay(100);
+               writel(clkgate_bit, &scu->clkgate_clr1);
+               mdelay(10);
+               writel(reset_bit, &scu->modrst_clr1);
+               break;
+       case 2:
+               reset_bit = BIT(ASPEED_RESET_MAC2);
+               clkgate_bit = SCU_CLKGATE1_MAC2;
+               writel(reset_bit, &scu->modrst_ctrl1);
+               udelay(100);
+               writel(clkgate_bit, &scu->clkgate_clr1);
+               mdelay(10);
+               writel(reset_bit, &scu->modrst_clr1);
+               break;
+       case 3:
+               reset_bit = BIT(ASPEED_RESET_MAC3 - 32);
+               clkgate_bit = SCU_CLKGATE2_MAC3;
+               writel(reset_bit, &scu->modrst_ctrl2);
+               udelay(100);
+               writel(clkgate_bit, &scu->clkgate_clr2);
+               mdelay(10);
+               writel(reset_bit, &scu->modrst_clr2);
+               break;
+       case 4:
+               reset_bit = BIT(ASPEED_RESET_MAC4 - 32);
+               clkgate_bit = SCU_CLKGATE2_MAC4;
+               writel(reset_bit, &scu->modrst_ctrl2);
+               udelay(100);
+               writel(clkgate_bit, &scu->clkgate_clr2);
+               mdelay(10);
+               writel(reset_bit, &scu->modrst_clr2);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static void ast2600_configure_rsa_ecc_clk(struct ast2600_scu *scu)
+{
+       uint32_t clksrc1 = readl(&scu->clksrc1);
+
+       /* Configure RSA clock = HPLL/3 */
+       clksrc1 |= SCU_CLKSRC1_ECC_RSA;
+       clksrc1 &= ~SCU_CLKSRC1_ECC_RSA_DIV_MASK;
+       clksrc1 |= (2 << SCU_CLKSRC1_ECC_RSA_DIV_SHIFT);
+
+       writel(clksrc1, &scu->clksrc1);
+}
+
+static ulong ast2600_enable_sdclk(struct ast2600_scu *scu)
+{
+       uint32_t reset_bit;
+       uint32_t clkgate_bit;
+
+       reset_bit = BIT(ASPEED_RESET_SD - 32);
+       clkgate_bit = SCU_CLKGATE2_SDIO;
+
+       writel(reset_bit, &scu->modrst_ctrl2);
+       udelay(100);
+       writel(clkgate_bit, &scu->clkgate_clr2);
+       mdelay(10);
+       writel(reset_bit, &scu->modrst_clr2);
+
+       return 0;
+}
+
+static ulong ast2600_enable_extsdclk(struct ast2600_scu *scu)
+{
+       int i = 0;
+       uint32_t div = 0;
+       uint32_t rate = 0;
+       uint32_t clksrc4 = readl(&scu->clksrc4);
+
+       /*
+        * ast2600 SD controller max clk is 200Mhz
+        * use apll for clock source 800/4 = 200
+        * controller max is 200mhz
+        */
+       rate = ast2600_get_pll_rate(scu, ASPEED_CLK_APLL);
+       for (i = 0; i < 8; i++) {
+               div = (i + 1) * 2;
+               if ((rate / div) <= 200000000)
+                       break;
+       }
+       clksrc4 &= ~SCU_CLKSRC4_SDIO_DIV_MASK;
+       clksrc4 |= (i << SCU_CLKSRC4_SDIO_DIV_SHIFT);
+       clksrc4 |= SCU_CLKSRC4_SDIO;
+       writel(clksrc4, &scu->clksrc4);
+
+       setbits_le32(&scu->clksrc4, SCU_CLKSRC4_SDIO_EN);
+
+       return 0;
+}
+
+static ulong ast2600_enable_emmcclk(struct ast2600_scu *scu)
+{
+       uint32_t reset_bit;
+       uint32_t clkgate_bit;
+
+       reset_bit = BIT(ASPEED_RESET_EMMC);
+       clkgate_bit = SCU_CLKGATE1_EMMC;
+
+       writel(reset_bit, &scu->modrst_ctrl1);
+       udelay(100);
+       writel(clkgate_bit, &scu->clkgate_clr1);
+       mdelay(10);
+       writel(reset_bit, &scu->modrst_clr1);
+
+       return 0;
+}
+
+static ulong ast2600_enable_extemmcclk(struct ast2600_scu *scu)
+{
+       int i = 0;
+       uint32_t div = 0;
+       uint32_t rate = 0;
+       uint32_t clksrc1 = readl(&scu->clksrc1);
+
+       /*
+        * ast2600 eMMC controller max clk is 200Mhz
+        * HPll->1/2->|\
+        *                              |->SCU300[11]->SCU300[14:12][1/N] +
+        * MPLL------>|/                                                                  |
+        * +----------------------------------------------+
+        * |
+        * +---------> EMMC12C[15:8][1/N]-> eMMC clk
+        */
+       rate = ast2600_get_pll_rate(scu, ASPEED_CLK_MPLL);
+       for (i = 0; i < 8; i++) {
+               div = (i + 1) * 2;
+               if ((rate / div) <= 200000000)
+                       break;
+       }
+
+       clksrc1 &= ~SCU_CLKSRC1_EMMC_DIV_MASK;
+       clksrc1 |= (i << SCU_CLKSRC1_EMMC_DIV_SHIFT);
+       clksrc1 |= SCU_CLKSRC1_EMMC;
+       writel(clksrc1, &scu->clksrc1);
+
+       setbits_le32(&scu->clksrc1, SCU_CLKSRC1_EMMC_EN);
+
+       return 0;
+}
+
+static ulong ast2600_enable_fsiclk(struct ast2600_scu *scu)
+{
+       uint32_t reset_bit;
+       uint32_t clkgate_bit;
+
+       reset_bit = BIT(ASPEED_RESET_FSI % 32);
+       clkgate_bit = SCU_CLKGATE2_FSI;
+
+       /* The FSI clock is shared between masters. If it's already on
+        * don't touch it, as that will reset the existing master.
+        */
+       if (!(readl(&scu->clkgate_ctrl2) & clkgate_bit)) {
+               debug("%s: already running, not touching it\n", __func__);
+               return 0;
+       }
+
+       writel(reset_bit, &scu->modrst_ctrl2);
+       udelay(100);
+       writel(clkgate_bit, &scu->clkgate_clr2);
+       mdelay(10);
+       writel(reset_bit, &scu->modrst_clr2);
+
+       return 0;
+}
+
+static ulong ast2600_enable_usbahclk(struct ast2600_scu *scu)
+{
+       uint32_t reset_bit;
+       uint32_t clkgate_bit;
+
+       reset_bit = BIT(ASPEED_RESET_EHCI_P1);
+       clkgate_bit = SCU_CLKGATE1_USB_HUB;
+
+       writel(reset_bit, &scu->modrst_ctrl1);
+       udelay(100);
+       writel(clkgate_bit, &scu->clkgate_ctrl1);
+       mdelay(20);
+       writel(reset_bit, &scu->modrst_clr1);
+
+       return 0;
+}
+
+static ulong ast2600_enable_usbbhclk(struct ast2600_scu *scu)
+{
+       uint32_t reset_bit;
+       uint32_t clkgate_bit;
+
+       reset_bit = BIT(ASPEED_RESET_EHCI_P2);
+       clkgate_bit = SCU_CLKGATE1_USB_HOST2;
+
+       writel(reset_bit, &scu->modrst_ctrl1);
+       udelay(100);
+       writel(clkgate_bit, &scu->clkgate_clr1);
+       mdelay(20);
+       writel(reset_bit, &scu->modrst_clr1);
+
+       return 0;
+}
+
+static int ast2600_clk_enable(struct clk *clk)
+{
+       struct ast2600_clk_priv *priv = dev_get_priv(clk->dev);
+
+       switch (clk->id) {
+       case ASPEED_CLK_GATE_MAC1CLK:
+               ast2600_configure_mac(priv->scu, 1);
+               break;
+       case ASPEED_CLK_GATE_MAC2CLK:
+               ast2600_configure_mac(priv->scu, 2);
+               break;
+       case ASPEED_CLK_GATE_MAC3CLK:
+               ast2600_configure_mac(priv->scu, 3);
+               break;
+       case ASPEED_CLK_GATE_MAC4CLK:
+               ast2600_configure_mac(priv->scu, 4);
+               break;
+       case ASPEED_CLK_GATE_SDCLK:
+               ast2600_enable_sdclk(priv->scu);
+               break;
+       case ASPEED_CLK_GATE_SDEXTCLK:
+               ast2600_enable_extsdclk(priv->scu);
+               break;
+       case ASPEED_CLK_GATE_EMMCCLK:
+               ast2600_enable_emmcclk(priv->scu);
+               break;
+       case ASPEED_CLK_GATE_EMMCEXTCLK:
+               ast2600_enable_extemmcclk(priv->scu);
+               break;
+       case ASPEED_CLK_GATE_FSICLK:
+               ast2600_enable_fsiclk(priv->scu);
+               break;
+       case ASPEED_CLK_GATE_USBPORT1CLK:
+               ast2600_enable_usbahclk(priv->scu);
+               break;
+       case ASPEED_CLK_GATE_USBPORT2CLK:
+               ast2600_enable_usbbhclk(priv->scu);
+               break;
+       default:
+               pr_err("can't enable clk\n");
+               return -ENOENT;
+       }
+
+       return 0;
+}
+
+struct clk_ops ast2600_clk_ops = {
+       .get_rate = ast2600_clk_get_rate,
+       .set_rate = ast2600_clk_set_rate,
+       .enable = ast2600_clk_enable,
+};
+
+static int ast2600_clk_probe(struct udevice *dev)
+{
+       struct ast2600_clk_priv *priv = dev_get_priv(dev);
+
+       priv->scu = devfdt_get_addr_ptr(dev);
+       if (IS_ERR(priv->scu))
+               return PTR_ERR(priv->scu);
+
+       ast2600_init_rgmii_clk(priv->scu, &rgmii_clk_defconfig);
+       ast2600_init_rmii_clk(priv->scu, &rmii_clk_defconfig);
+       ast2600_configure_mac12_clk(priv->scu);
+       ast2600_configure_mac34_clk(priv->scu);
+       ast2600_configure_rsa_ecc_clk(priv->scu);
+
+       return 0;
+}
+
+static int ast2600_clk_bind(struct udevice *dev)
+{
+       int ret;
+
+       /* The reset driver does not have a device node, so bind it here */
+       ret = device_bind_driver(gd->dm_root, "ast_sysreset", "reset", &dev);
+       if (ret)
+               debug("Warning: No reset driver: ret=%d\n", ret);
+
+       return 0;
+}
+
+struct aspeed_clks {
+       ulong id;
+       const char *name;
+};
+
+static struct aspeed_clks aspeed_clk_names[] = {
+       { ASPEED_CLK_HPLL, "hpll" },
+       { ASPEED_CLK_MPLL, "mpll" },
+       { ASPEED_CLK_APLL, "apll" },
+       { ASPEED_CLK_EPLL, "epll" },
+       { ASPEED_CLK_DPLL, "dpll" },
+       { ASPEED_CLK_AHB, "hclk" },
+       { ASPEED_CLK_APB1, "pclk1" },
+       { ASPEED_CLK_APB2, "pclk2" },
+       { ASPEED_CLK_BCLK, "bclk" },
+       { ASPEED_CLK_UARTX, "uxclk" },
+       { ASPEED_CLK_HUARTX, "huxclk" },
+};
+
+int soc_clk_dump(void)
+{
+       struct udevice *dev;
+       struct clk clk;
+       unsigned long rate;
+       int i, ret;
+
+       ret = uclass_get_device_by_driver(UCLASS_CLK, DM_DRIVER_GET(aspeed_scu),
+                                         &dev);
+       if (ret)
+               return ret;
+
+       printf("Clk\t\tHz\n");
+
+       for (i = 0; i < ARRAY_SIZE(aspeed_clk_names); i++) {
+               clk.id = aspeed_clk_names[i].id;
+               ret = clk_request(dev, &clk);
+               if (ret < 0) {
+                       debug("%s clk_request() failed: %d\n", __func__, ret);
+                       continue;
+               }
+
+               ret = clk_get_rate(&clk);
+               rate = ret;
+
+               clk_free(&clk);
+
+               if (ret == -ENOTSUPP) {
+                       printf("clk ID %lu not supported yet\n",
+                              aspeed_clk_names[i].id);
+                       continue;
+               }
+               if (ret < 0) {
+                       printf("%s %lu: get_rate err: %d\n", __func__,
+                              aspeed_clk_names[i].id, ret);
+                       continue;
+               }
+
+               printf("%s(%3lu):\t%lu\n", aspeed_clk_names[i].name,
+                      aspeed_clk_names[i].id, rate);
+       }
+
+       return 0;
+}
+
+static const struct udevice_id ast2600_clk_ids[] = {
+       { .compatible = "aspeed,ast2600-scu", },
+       { },
+};
+
+U_BOOT_DRIVER(aspeed_ast2600_scu) = {
+       .name = "aspeed_ast2600_scu",
+       .id = UCLASS_CLK,
+       .of_match = ast2600_clk_ids,
+       .priv_auto = sizeof(struct ast2600_clk_priv),
+       .ops = &ast2600_clk_ops,
+       .bind = ast2600_clk_bind,
+       .probe = ast2600_clk_probe,
+};
index 237fd17..522e724 100644 (file)
@@ -7,5 +7,6 @@ obj-$(CONFIG_MT8512) += clk-mt8512.o
 obj-$(CONFIG_TARGET_MT7623) += clk-mt7623.o
 obj-$(CONFIG_TARGET_MT7622) += clk-mt7622.o
 obj-$(CONFIG_TARGET_MT7629) += clk-mt7629.o
+obj-$(CONFIG_TARGET_MT8183) += clk-mt8183.o
 obj-$(CONFIG_TARGET_MT8516) += clk-mt8516.o
 obj-$(CONFIG_TARGET_MT8518) += clk-mt8518.o
diff --git a/drivers/clk/mediatek/clk-mt8183.c b/drivers/clk/mediatek/clk-mt8183.c
new file mode 100644 (file)
index 0000000..17e653a
--- /dev/null
@@ -0,0 +1,823 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MediaTek clock driver for MT8183 SoC
+ *
+ * Copyright (C) 2020 BayLibre, SAS
+ * Copyright (c) 2020 MediaTek Inc.
+ * Author: Fabien Parent <fparent@baylibre.com>
+ * Author: Weiyi Lu <weiyi.lu@mediatek.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/io.h>
+#include <dt-bindings/clock/mt8183-clk.h>
+
+#include "clk-mtk.h"
+
+#define MT8183_PLL_FMAX                (3800UL * MHZ)
+#define MT8183_PLL_FMIN                (1500UL * MHZ)
+
+/* apmixedsys */
+#define PLL(_id, _reg, _pwr_reg, _en_mask, _flags, _rst_bar_mask, _pcwbits, \
+           _pcwibits, _pd_reg, _pd_shift, _pcw_reg, _pcw_shift) {      \
+               .id = _id,                                              \
+               .reg = _reg,                                            \
+               .pwr_reg = _pwr_reg,                                    \
+               .en_mask = _en_mask,                                    \
+               .rst_bar_mask = _rst_bar_mask,                          \
+               .fmax = MT8183_PLL_FMAX,                                \
+               .fmin = MT8183_PLL_FMIN,                                \
+               .flags = _flags,                                        \
+               .pcwbits = _pcwbits,                                    \
+               .pcwibits = _pcwibits,                                  \
+               .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_LL, 0x0200, 0x020C, 0x00000001,
+           HAVE_RST_BAR, BIT(24), 22, 8, 0x0204, 24,
+           0x0204, 0),
+       PLL(CLK_APMIXED_ARMPLL_L, 0x0210, 0x021C, 0x00000001,
+           HAVE_RST_BAR, BIT(24), 22, 8, 0x0214, 24,
+           0x0214, 0),
+       PLL(CLK_APMIXED_CCIPLL, 0x0290, 0x029C, 0x00000001,
+           HAVE_RST_BAR, BIT(24), 22, 8, 0x0294, 24,
+           0x0294, 0),
+       PLL(CLK_APMIXED_MAINPLL, 0x0220, 0x022C, 0x00000001,
+           HAVE_RST_BAR, BIT(24), 22, 8, 0x0224, 24,
+           0x0224, 0),
+       PLL(CLK_APMIXED_UNIV2PLL, 0x0230, 0x023C, 0x00000001,
+           HAVE_RST_BAR, BIT(24), 22, 8, 0x0234, 24,
+           0x0234, 0),
+       PLL(CLK_APMIXED_MSDCPLL, 0x0250, 0x025C, 0x00000001,
+           0, 0, 22, 8, 0x0254, 24, 0x0254, 0),
+       PLL(CLK_APMIXED_MMPLL, 0x0270, 0x027C, 0x00000001,
+           HAVE_RST_BAR, BIT(23), 22, 8, 0x0274, 24,
+           0x0274, 0),
+       PLL(CLK_APMIXED_MFGPLL, 0x0240, 0x024C, 0x00000001,
+           0, 0, 22, 8, 0x0244, 24, 0x0244, 0),
+       PLL(CLK_APMIXED_TVDPLL, 0x0260, 0x026C, 0x00000001,
+           0, 0, 22, 8, 0x0264, 24, 0x0264, 0),
+       PLL(CLK_APMIXED_APLL1, 0x02A0, 0x02B0, 0x00000001,
+           0, 0, 32, 8, 0x02A0, 1, 0x02A4, 0),
+       PLL(CLK_APMIXED_APLL2, 0x02b4, 0x02c4, 0x00000001,
+           0, 0, 32, 8, 0x02B4, 1, 0x02B8, 0),
+};
+
+static const struct mtk_fixed_clk top_fixed_clks[] = {
+       FIXED_CLK(CLK_TOP_CLK26M, CLK_XTAL, 26000000),
+       FIXED_CLK(CLK_TOP_ULPOSC, CLK_XTAL, 250000),
+       FIXED_CLK(CLK_TOP_UNIVP_192M, CLK_TOP_UNIVPLL, 192000000),
+};
+
+static const struct mtk_fixed_factor top_fixed_divs[] = {
+       FACTOR(CLK_TOP_CLK13M, CLK_TOP_CLK26M, 1, 2, CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_F26M_CK_D2, CLK_TOP_CLK26M, 1, 2, CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_SYSPLL_CK, CLK_APMIXED_MAINPLL, 1,
+              1, CLK_PARENT_APMIXED),
+       FACTOR(CLK_TOP_SYSPLL_D2, CLK_TOP_SYSPLL_CK, 1,
+              2, CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_SYSPLL_D3, CLK_APMIXED_MAINPLL, 1,
+              3, CLK_PARENT_APMIXED),
+       FACTOR(CLK_TOP_SYSPLL_D5, CLK_APMIXED_MAINPLL, 1,
+              5, CLK_PARENT_APMIXED),
+       FACTOR(CLK_TOP_SYSPLL_D7, CLK_APMIXED_MAINPLL, 1,
+              7, CLK_PARENT_APMIXED),
+       FACTOR(CLK_TOP_SYSPLL_D2_D2, CLK_TOP_SYSPLL_D2, 1,
+              2, CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_SYSPLL_D2_D4, CLK_TOP_SYSPLL_D2, 1,
+              4, CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_SYSPLL_D2_D8, CLK_TOP_SYSPLL_D2, 1,
+              8, CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_SYSPLL_D2_D16, CLK_TOP_SYSPLL_D2, 1,
+              16, CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_SYSPLL_D3_D2, CLK_TOP_SYSPLL_D3, 1,
+              2, CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_SYSPLL_D3_D4, CLK_TOP_SYSPLL_D3, 1,
+              4, CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_SYSPLL_D3_D8, CLK_TOP_SYSPLL_D3, 1,
+              8, CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_SYSPLL_D5_D2, CLK_TOP_SYSPLL_D5, 1,
+              2, CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_SYSPLL_D5_D4, CLK_TOP_SYSPLL_D5, 1,
+              4, CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_SYSPLL_D7_D2, CLK_TOP_SYSPLL_D7, 1,
+              2, CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_SYSPLL_D7_D4, CLK_TOP_SYSPLL_D7, 1,
+              4, CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_UNIVPLL_CK, CLK_TOP_UNIVPLL, 1, 1, CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_UNIVPLL_D2, CLK_TOP_UNIVPLL_CK, 1,
+              2, CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_UNIVPLL_D3, CLK_TOP_UNIVPLL, 1, 3, CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_UNIVPLL_D5, CLK_TOP_UNIVPLL, 1, 5, CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_UNIVPLL_D7, CLK_TOP_UNIVPLL, 1, 7, CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_UNIVPLL_D2_D2, CLK_TOP_UNIVPLL_D2, 1,
+              2, CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_UNIVPLL_D2_D4, CLK_TOP_UNIVPLL_D2, 1,
+              4, CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_UNIVPLL_D2_D8, CLK_TOP_UNIVPLL_D2, 1,
+              8, CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_UNIVPLL_D3_D2, CLK_TOP_UNIVPLL_D3, 1,
+              2, CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_UNIVPLL_D3_D4, CLK_TOP_UNIVPLL_D3, 1,
+              4, CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_UNIVPLL_D3_D8, CLK_TOP_UNIVPLL_D3, 1,
+              8, CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_UNIVPLL_D5_D2, CLK_TOP_UNIVPLL_D5, 1,
+              2, CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_UNIVPLL_D5_D4, CLK_TOP_UNIVPLL_D5, 1,
+              4, CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_UNIVPLL_D5_D8, CLK_TOP_UNIVPLL_D5, 1,
+              8, CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_UNIVP_192M_CK, CLK_TOP_UNIVP_192M, 1, 1,
+              CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_UNIVP_192M_D2, CLK_TOP_UNIVP_192M_CK, 1,
+              2, CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_UNIVP_192M_D4, CLK_TOP_UNIVP_192M_CK, 1,
+              4, CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_UNIVP_192M_D8, CLK_TOP_UNIVP_192M_CK, 1,
+              8, CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_UNIVP_192M_D16, CLK_TOP_UNIVP_192M_CK, 1,
+              16, CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_UNIVP_192M_D32, CLK_TOP_UNIVP_192M_CK, 1,
+              32, CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_APLL1_CK, CLK_APMIXED_APLL1, 1, 1, CLK_PARENT_APMIXED),
+       FACTOR(CLK_TOP_APLL1_D2, CLK_APMIXED_APLL1, 1, 2, CLK_PARENT_APMIXED),
+       FACTOR(CLK_TOP_APLL1_D4, CLK_APMIXED_APLL1, 1, 4, CLK_PARENT_APMIXED),
+       FACTOR(CLK_TOP_APLL1_D8, CLK_APMIXED_APLL1, 1, 8, CLK_PARENT_APMIXED),
+       FACTOR(CLK_TOP_APLL2_CK, CLK_APMIXED_APLL2, 1, 1, CLK_PARENT_APMIXED),
+       FACTOR(CLK_TOP_APLL2_D2, CLK_APMIXED_APLL2, 1, 2, CLK_PARENT_APMIXED),
+       FACTOR(CLK_TOP_APLL2_D4, CLK_APMIXED_APLL2, 1, 4, CLK_PARENT_APMIXED),
+       FACTOR(CLK_TOP_APLL2_D8, CLK_APMIXED_APLL2, 1, 8, CLK_PARENT_APMIXED),
+       FACTOR(CLK_TOP_TVDPLL_CK, CLK_APMIXED_TVDPLL, 1, 1, CLK_PARENT_APMIXED),
+       FACTOR(CLK_TOP_TVDPLL_D2, CLK_TOP_TVDPLL_CK, 1, 2, CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_TVDPLL_D4, CLK_APMIXED_TVDPLL, 1, 4, CLK_PARENT_APMIXED),
+       FACTOR(CLK_TOP_TVDPLL_D8, CLK_APMIXED_TVDPLL, 1, 8, CLK_PARENT_APMIXED),
+       FACTOR(CLK_TOP_TVDPLL_D16, CLK_APMIXED_TVDPLL, 1,
+              16, CLK_PARENT_APMIXED),
+       FACTOR(CLK_TOP_MMPLL_CK, CLK_APMIXED_MMPLL, 1, 1, CLK_PARENT_APMIXED),
+       FACTOR(CLK_TOP_MMPLL_D4, CLK_APMIXED_MMPLL, 1, 4, CLK_PARENT_APMIXED),
+       FACTOR(CLK_TOP_MMPLL_D4_D2, CLK_TOP_MMPLL_D4, 1,
+              2, CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_MMPLL_D4_D4, CLK_TOP_MMPLL_D4, 1, 4, CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_MMPLL_D5, CLK_APMIXED_MMPLL, 1, 5, CLK_PARENT_APMIXED),
+       FACTOR(CLK_TOP_MMPLL_D5_D2, CLK_TOP_MMPLL_D5, 1,
+              2, CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_MMPLL_D5_D4, CLK_TOP_MMPLL_D5, 1,
+              4, CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_MMPLL_D6, CLK_APMIXED_MMPLL, 1, 6, CLK_PARENT_APMIXED),
+       FACTOR(CLK_TOP_MMPLL_D7, CLK_APMIXED_MMPLL, 1, 7, CLK_PARENT_APMIXED),
+       FACTOR(CLK_TOP_MFGPLL_CK, CLK_APMIXED_MFGPLL, 1, 1, CLK_PARENT_APMIXED),
+       FACTOR(CLK_TOP_MSDCPLL_CK, CLK_APMIXED_MSDCPLL, 1,
+              1, CLK_PARENT_APMIXED),
+       FACTOR(CLK_TOP_MSDCPLL_D2, CLK_APMIXED_MSDCPLL, 1,
+              2, CLK_PARENT_APMIXED),
+       FACTOR(CLK_TOP_MSDCPLL_D4, CLK_APMIXED_MSDCPLL, 1,
+              4, CLK_PARENT_APMIXED),
+       FACTOR(CLK_TOP_MSDCPLL_D8, CLK_APMIXED_MSDCPLL, 1,
+              8, CLK_PARENT_APMIXED),
+       FACTOR(CLK_TOP_MSDCPLL_D16, CLK_APMIXED_MSDCPLL, 1,
+              16, CLK_PARENT_APMIXED),
+       FACTOR(CLK_TOP_AD_OSC_CK, CLK_TOP_ULPOSC, 1, 1, CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_OSC_D2, CLK_TOP_ULPOSC, 1, 2, CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_OSC_D4, CLK_TOP_ULPOSC, 1, 4, CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_OSC_D8, CLK_TOP_ULPOSC, 1, 8, CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_OSC_D16, CLK_TOP_ULPOSC, 1, 16, CLK_PARENT_TOPCKGEN),
+       FACTOR(CLK_TOP_UNIVPLL, CLK_APMIXED_UNIV2PLL, 1, 2, CLK_PARENT_APMIXED),
+       FACTOR(CLK_TOP_UNIVPLL_D3_D16, CLK_TOP_UNIVPLL_D3, 1,
+              16, CLK_PARENT_TOPCKGEN),
+};
+
+static const int axi_parents[] = {
+       CLK_TOP_CLK26M,
+       CLK_TOP_SYSPLL_D2_D4,
+       CLK_TOP_SYSPLL_D7,
+       CLK_TOP_OSC_D4
+};
+
+static const int mm_parents[] = {
+       CLK_TOP_CLK26M,
+       CLK_TOP_MMPLL_D7,
+       CLK_TOP_SYSPLL_D3,
+       CLK_TOP_UNIVPLL_D2_D2,
+       CLK_TOP_SYSPLL_D2_D2,
+       CLK_TOP_SYSPLL_D3_D2
+};
+
+static const int img_parents[] = {
+       CLK_TOP_CLK26M,
+       CLK_TOP_MMPLL_D6,
+       CLK_TOP_UNIVPLL_D3,
+       CLK_TOP_SYSPLL_D3,
+       CLK_TOP_UNIVPLL_D2_D2,
+       CLK_TOP_SYSPLL_D2_D2,
+       CLK_TOP_UNIVPLL_D3_D2,
+       CLK_TOP_SYSPLL_D3_D2
+};
+
+static const int cam_parents[] = {
+       CLK_TOP_CLK26M,
+       CLK_TOP_SYSPLL_D2,
+       CLK_TOP_MMPLL_D6,
+       CLK_TOP_SYSPLL_D3,
+       CLK_TOP_MMPLL_D7,
+       CLK_TOP_UNIVPLL_D3,
+       CLK_TOP_UNIVPLL_D2_D2,
+       CLK_TOP_SYSPLL_D2_D2,
+       CLK_TOP_SYSPLL_D3_D2,
+       CLK_TOP_UNIVPLL_D3_D2
+};
+
+static const int dsp_parents[] = {
+       CLK_TOP_CLK26M,
+       CLK_TOP_MMPLL_D6,
+       CLK_TOP_MMPLL_D7,
+       CLK_TOP_UNIVPLL_D3,
+       CLK_TOP_SYSPLL_D3,
+       CLK_TOP_UNIVPLL_D2_D2,
+       CLK_TOP_SYSPLL_D2_D2,
+       CLK_TOP_UNIVPLL_D3_D2,
+       CLK_TOP_SYSPLL_D3_D2
+};
+
+static const int dsp1_parents[] = {
+       CLK_TOP_CLK26M,
+       CLK_TOP_MMPLL_D6,
+       CLK_TOP_MMPLL_D7,
+       CLK_TOP_UNIVPLL_D3,
+       CLK_TOP_SYSPLL_D3,
+       CLK_TOP_UNIVPLL_D2_D2,
+       CLK_TOP_SYSPLL_D2_D2,
+       CLK_TOP_UNIVPLL_D3_D2,
+       CLK_TOP_SYSPLL_D3_D2
+};
+
+static const int dsp2_parents[] = {
+       CLK_TOP_CLK26M,
+       CLK_TOP_MMPLL_D6,
+       CLK_TOP_MMPLL_D7,
+       CLK_TOP_UNIVPLL_D3,
+       CLK_TOP_SYSPLL_D3,
+       CLK_TOP_UNIVPLL_D2_D2,
+       CLK_TOP_SYSPLL_D2_D2,
+       CLK_TOP_UNIVPLL_D3_D2,
+       CLK_TOP_SYSPLL_D3_D2
+};
+
+static const int ipu_if_parents[] = {
+       CLK_TOP_CLK26M,
+       CLK_TOP_MMPLL_D6,
+       CLK_TOP_MMPLL_D7,
+       CLK_TOP_UNIVPLL_D3,
+       CLK_TOP_SYSPLL_D3,
+       CLK_TOP_UNIVPLL_D2_D2,
+       CLK_TOP_SYSPLL_D2_D2,
+       CLK_TOP_UNIVPLL_D3_D2,
+       CLK_TOP_SYSPLL_D3_D2
+};
+
+static const int mfg_parents[] = {
+       CLK_TOP_CLK26M,
+       CLK_TOP_MFGPLL_CK,
+       CLK_TOP_UNIVPLL_D3,
+       CLK_TOP_SYSPLL_D3
+};
+
+static const int f52m_mfg_parents[] = {
+       CLK_TOP_CLK26M,
+       CLK_TOP_UNIVPLL_D3_D2,
+       CLK_TOP_UNIVPLL_D3_D4,
+       CLK_TOP_UNIVPLL_D3_D8
+};
+
+static const int camtg_parents[] = {
+       CLK_TOP_CLK26M,
+       CLK_TOP_UNIVP_192M_D8,
+       CLK_TOP_UNIVPLL_D3_D8,
+       CLK_TOP_UNIVP_192M_D4,
+       CLK_TOP_UNIVPLL_D3_D16,
+       CLK_TOP_F26M_CK_D2,
+       CLK_TOP_UNIVP_192M_D16,
+       CLK_TOP_UNIVP_192M_D32
+};
+
+static const int camtg2_parents[] = {
+       CLK_TOP_CLK26M,
+       CLK_TOP_UNIVP_192M_D8,
+       CLK_TOP_UNIVPLL_D3_D8,
+       CLK_TOP_UNIVP_192M_D4,
+       CLK_TOP_UNIVPLL_D3_D16,
+       CLK_TOP_F26M_CK_D2,
+       CLK_TOP_UNIVP_192M_D16,
+       CLK_TOP_UNIVP_192M_D32
+};
+
+static const int camtg3_parents[] = {
+       CLK_TOP_CLK26M,
+       CLK_TOP_UNIVP_192M_D8,
+       CLK_TOP_UNIVPLL_D3_D8,
+       CLK_TOP_UNIVP_192M_D4,
+       CLK_TOP_UNIVPLL_D3_D16,
+       CLK_TOP_F26M_CK_D2,
+       CLK_TOP_UNIVP_192M_D16,
+       CLK_TOP_UNIVP_192M_D32
+};
+
+static const int camtg4_parents[] = {
+       CLK_TOP_CLK26M,
+       CLK_TOP_UNIVP_192M_D8,
+       CLK_TOP_UNIVPLL_D3_D8,
+       CLK_TOP_UNIVP_192M_D4,
+       CLK_TOP_UNIVPLL_D3_D16,
+       CLK_TOP_F26M_CK_D2,
+       CLK_TOP_UNIVP_192M_D16,
+       CLK_TOP_UNIVP_192M_D32
+};
+
+static const int uart_parents[] = {
+       CLK_TOP_CLK26M,
+       CLK_TOP_UNIVPLL_D3_D8
+};
+
+static const int spi_parents[] = {
+       CLK_TOP_CLK26M,
+       CLK_TOP_SYSPLL_D5_D2,
+       CLK_TOP_SYSPLL_D3_D4,
+       CLK_TOP_MSDCPLL_D4
+};
+
+static const int msdc50_hclk_parents[] = {
+       CLK_TOP_CLK26M,
+       CLK_TOP_SYSPLL_D2_D2,
+       CLK_TOP_SYSPLL_D3_D2
+};
+
+static const int msdc50_0_parents[] = {
+       CLK_TOP_CLK26M,
+       CLK_TOP_MSDCPLL_CK,
+       CLK_TOP_MSDCPLL_D2,
+       CLK_TOP_UNIVPLL_D2_D4,
+       CLK_TOP_SYSPLL_D3_D2,
+       CLK_TOP_UNIVPLL_D2_D2
+};
+
+static const int msdc30_1_parents[] = {
+       CLK_TOP_CLK26M,
+       CLK_TOP_UNIVPLL_D3_D2,
+       CLK_TOP_SYSPLL_D3_D2,
+       CLK_TOP_SYSPLL_D7,
+       CLK_TOP_MSDCPLL_D2
+};
+
+static const int msdc30_2_parents[] = {
+       CLK_TOP_CLK26M,
+       CLK_TOP_UNIVPLL_D3_D2,
+       CLK_TOP_SYSPLL_D3_D2,
+       CLK_TOP_SYSPLL_D7,
+       CLK_TOP_MSDCPLL_D2
+};
+
+static const int audio_parents[] = {
+       CLK_TOP_CLK26M,
+       CLK_TOP_SYSPLL_D5_D4,
+       CLK_TOP_SYSPLL_D7_D4,
+       CLK_TOP_SYSPLL_D2_D16
+};
+
+static const int aud_intbus_parents[] = {
+       CLK_TOP_CLK26M,
+       CLK_TOP_SYSPLL_D2_D4,
+       CLK_TOP_SYSPLL_D7_D2
+};
+
+static const int pmicspi_parents[] = {
+       CLK_TOP_CLK26M,
+       CLK_TOP_SYSPLL_D2_D8,
+       CLK_TOP_OSC_D8
+};
+
+static const int fpwrap_ulposc_parents[] = {
+       CLK_TOP_CLK26M,
+       CLK_TOP_OSC_D16,
+       CLK_TOP_OSC_D4,
+       CLK_TOP_OSC_D8
+};
+
+static const int atb_parents[] = {
+       CLK_TOP_CLK26M,
+       CLK_TOP_SYSPLL_D2_D2,
+       CLK_TOP_SYSPLL_D5
+};
+
+static const int sspm_parents[] = {
+       CLK_TOP_CLK26M,
+       CLK_TOP_UNIVPLL_D2_D4,
+       CLK_TOP_SYSPLL_D2_D2,
+       CLK_TOP_UNIVPLL_D2_D2,
+       CLK_TOP_SYSPLL_D3
+};
+
+static const int dpi0_parents[] = {
+       CLK_TOP_CLK26M,
+       CLK_TOP_TVDPLL_D2,
+       CLK_TOP_TVDPLL_D4,
+       CLK_TOP_TVDPLL_D8,
+       CLK_TOP_TVDPLL_D16,
+       CLK_TOP_UNIVPLL_D5_D2,
+       CLK_TOP_UNIVPLL_D3_D4,
+       CLK_TOP_SYSPLL_D3_D4,
+       CLK_TOP_UNIVPLL_D3_D8
+};
+
+static const int scam_parents[] = {
+       CLK_TOP_CLK26M,
+       CLK_TOP_SYSPLL_D5_D2
+};
+
+static const int disppwm_parents[] = {
+       CLK_TOP_CLK26M,
+       CLK_TOP_UNIVPLL_D3_D4,
+       CLK_TOP_OSC_D2,
+       CLK_TOP_OSC_D4,
+       CLK_TOP_OSC_D16
+};
+
+static const int usb_top_parents[] = {
+       CLK_TOP_CLK26M,
+       CLK_TOP_UNIVPLL_D5_D4,
+       CLK_TOP_UNIVPLL_D3_D4,
+       CLK_TOP_UNIVPLL_D5_D2
+};
+
+static const int ssusb_top_xhci_parents[] = {
+       CLK_TOP_CLK26M,
+       CLK_TOP_UNIVPLL_D5_D4,
+       CLK_TOP_UNIVPLL_D3_D4,
+       CLK_TOP_UNIVPLL_D5_D2
+};
+
+static const int spm_parents[] = {
+       CLK_TOP_CLK26M,
+       CLK_TOP_SYSPLL_D2_D8
+};
+
+static const int i2c_parents[] = {
+       CLK_TOP_CLK26M,
+       CLK_TOP_SYSPLL_D2_D8,
+       CLK_TOP_UNIVPLL_D5_D2
+};
+
+static const int scp_parents[] = {
+       CLK_TOP_CLK26M,
+       CLK_TOP_UNIVPLL_D2_D8,
+       CLK_TOP_SYSPLL_D5,
+       CLK_TOP_SYSPLL_D2_D2,
+       CLK_TOP_UNIVPLL_D2_D2,
+       CLK_TOP_SYSPLL_D3,
+       CLK_TOP_UNIVPLL_D3
+};
+
+static const int seninf_parents[] = {
+       CLK_TOP_CLK26M,
+       CLK_TOP_UNIVPLL_D2_D2,
+       CLK_TOP_UNIVPLL_D3_D2,
+       CLK_TOP_UNIVPLL_D2_D4
+};
+
+static const int dxcc_parents[] = {
+       CLK_TOP_CLK26M,
+       CLK_TOP_SYSPLL_D2_D2,
+       CLK_TOP_SYSPLL_D2_D4,
+       CLK_TOP_SYSPLL_D2_D8
+};
+
+static const int aud_engen1_parents[] = {
+       CLK_TOP_CLK26M,
+       CLK_TOP_APLL1_D2,
+       CLK_TOP_APLL1_D4,
+       CLK_TOP_APLL1_D8
+};
+
+static const int aud_engen2_parents[] = {
+       CLK_TOP_CLK26M,
+       CLK_TOP_APLL2_D2,
+       CLK_TOP_APLL2_D4,
+       CLK_TOP_APLL2_D8
+};
+
+static const int faes_ufsfde_parents[] = {
+       CLK_TOP_CLK26M,
+       CLK_TOP_SYSPLL_D2,
+       CLK_TOP_SYSPLL_D2_D2,
+       CLK_TOP_SYSPLL_D3,
+       CLK_TOP_SYSPLL_D2_D4,
+       CLK_TOP_UNIVPLL_D3
+};
+
+static const int fufs_parents[] = {
+       CLK_TOP_CLK26M,
+       CLK_TOP_SYSPLL_D2_D4,
+       CLK_TOP_SYSPLL_D2_D8,
+       CLK_TOP_SYSPLL_D2_D16
+};
+
+static const int aud_1_parents[] = {
+       CLK_TOP_CLK26M,
+       CLK_TOP_APLL1_CK
+};
+
+static const int aud_2_parents[] = {
+       CLK_TOP_CLK26M,
+       CLK_TOP_APLL2_CK
+};
+
+static const struct mtk_composite top_muxes[] = {
+       /* CLK_CFG_0 */
+       MUX(CLK_TOP_MUX_AXI, axi_parents, 0x40, 0, 2),
+       MUX(CLK_TOP_MUX_MM, mm_parents, 0x40, 8, 3),
+       MUX(CLK_TOP_MUX_IMG, img_parents, 0x40, 16, 3),
+       MUX(CLK_TOP_MUX_CAM, cam_parents, 0x40, 24, 4),
+       /* CLK_CFG_1 */
+       MUX(CLK_TOP_MUX_DSP, dsp_parents, 0x50, 0, 4),
+       MUX(CLK_TOP_MUX_DSP1, dsp1_parents, 0x50, 8, 4),
+       MUX(CLK_TOP_MUX_DSP2, dsp2_parents, 0x50, 16, 4),
+       MUX(CLK_TOP_MUX_IPU_IF, ipu_if_parents, 0x50, 24, 4),
+       /* CLK_CFG_2 */
+       MUX(CLK_TOP_MUX_MFG, mfg_parents, 0x60, 0, 2),
+       MUX(CLK_TOP_MUX_F52M_MFG, f52m_mfg_parents, 0x60, 8, 2),
+       MUX(CLK_TOP_MUX_CAMTG, camtg_parents, 0x60, 16, 3),
+       MUX(CLK_TOP_MUX_CAMTG2, camtg2_parents, 0x60, 24, 3),
+       /* CLK_CFG_3 */
+       MUX(CLK_TOP_MUX_CAMTG3, camtg3_parents, 0x70, 0, 3),
+       MUX(CLK_TOP_MUX_CAMTG4, camtg4_parents, 0x70, 8, 3),
+       MUX(CLK_TOP_MUX_UART, uart_parents, 0x70, 16, 1),
+       MUX(CLK_TOP_MUX_SPI, spi_parents, 0x70, 24, 2),
+       /* CLK_CFG_4 */
+       MUX(CLK_TOP_MUX_MSDC50_0_HCLK, msdc50_hclk_parents, 0x80, 0, 2),
+       MUX(CLK_TOP_MUX_MSDC50_0, msdc50_0_parents, 0x80, 8, 3),
+       MUX(CLK_TOP_MUX_MSDC30_1, msdc30_1_parents, 0x80, 16, 3),
+       MUX(CLK_TOP_MUX_MSDC30_2, msdc30_2_parents, 0x80, 24, 3),
+       /* CLK_CFG_5 */
+       MUX(CLK_TOP_MUX_AUDIO, audio_parents, 0x90, 0, 2),
+       MUX(CLK_TOP_MUX_AUD_INTBUS, aud_intbus_parents, 0x90, 8, 2),
+       MUX(CLK_TOP_MUX_PMICSPI, pmicspi_parents, 0x90, 16, 2),
+       MUX(CLK_TOP_MUX_FPWRAP_ULPOSC, fpwrap_ulposc_parents, 0x90, 24, 2),
+       /* CLK_CFG_6 */
+       MUX(CLK_TOP_MUX_ATB, atb_parents, 0xa0, 0, 2),
+       MUX(CLK_TOP_MUX_SSPM, sspm_parents, 0xa0, 8, 3),
+       MUX(CLK_TOP_MUX_DPI0, dpi0_parents, 0xa0, 16, 4),
+       MUX(CLK_TOP_MUX_SCAM, scam_parents, 0xa0, 24, 1),
+       /* CLK_CFG_7 */
+       MUX(CLK_TOP_MUX_DISP_PWM, disppwm_parents, 0xb0, 0, 3),
+       MUX(CLK_TOP_MUX_USB_TOP, usb_top_parents, 0xb0, 8, 2),
+       MUX(CLK_TOP_MUX_SSUSB_TOP_XHCI, ssusb_top_xhci_parents, 0xb0, 16, 2),
+       MUX(CLK_TOP_MUX_SPM, spm_parents, 0xb0, 24, 1),
+       /* CLK_CFG_8 */
+       MUX(CLK_TOP_MUX_I2C, i2c_parents, 0xc0, 0, 2),
+       MUX(CLK_TOP_MUX_SCP, scp_parents, 0xc0, 8, 3),
+       MUX(CLK_TOP_MUX_SENINF, seninf_parents, 0xc0, 16, 2),
+       MUX(CLK_TOP_MUX_DXCC, dxcc_parents, 0xc0, 24, 2),
+       /* CLK_CFG_9 */
+       MUX(CLK_TOP_MUX_AUD_ENG1, aud_engen1_parents, 0xd0, 0, 2),
+       MUX(CLK_TOP_MUX_AUD_ENG2, aud_engen2_parents, 0xd0, 8, 2),
+       MUX(CLK_TOP_MUX_FAES_UFSFDE, faes_ufsfde_parents, 0xd0, 16, 3),
+       MUX(CLK_TOP_MUX_FUFS, fufs_parents, 0xd0, 24, 2),
+       /* CLK_CFG_10 */
+       MUX(CLK_TOP_MUX_AUD_1, aud_1_parents, 0xe0, 0, 1),
+       MUX(CLK_TOP_MUX_AUD_2, aud_2_parents, 0xe0, 8, 1),
+};
+
+static const struct mtk_clk_tree mt8183_clk_tree = {
+       .xtal_rate = 26 * MHZ,
+       .xtal2_rate = 26 * MHZ,
+       .fdivs_offs = CLK_TOP_CLK13M,
+       .muxes_offs = CLK_TOP_MUX_AXI,
+       .plls = apmixed_plls,
+       .fclks = top_fixed_clks,
+       .fdivs = top_fixed_divs,
+       .muxes = top_muxes,
+};
+
+static const struct mtk_gate_regs infra0_cg_regs = {
+       .set_ofs = 0x80,
+       .clr_ofs = 0x84,
+       .sta_ofs = 0x90,
+};
+
+static const struct mtk_gate_regs infra1_cg_regs = {
+       .set_ofs = 0x88,
+       .clr_ofs = 0x8c,
+       .sta_ofs = 0x94,
+};
+
+static const struct mtk_gate_regs infra2_cg_regs = {
+       .set_ofs = 0xa4,
+       .clr_ofs = 0xa8,
+       .sta_ofs = 0xac,
+};
+
+static const struct mtk_gate_regs infra3_cg_regs = {
+       .set_ofs = 0xc0,
+       .clr_ofs = 0xc4,
+       .sta_ofs = 0xc8,
+};
+
+#define GATE_INFRA0(_id, _parent, _shift) {            \
+               .id = _id,                                              \
+               .parent = _parent,                                      \
+               .regs = &infra0_cg_regs,                                \
+               .shift = _shift,                                        \
+               .flags = CLK_GATE_SETCLR | CLK_PARENT_TOPCKGEN,         \
+       }
+
+#define GATE_INFRA1(_id, _parent, _shift) {            \
+               .id = _id,                                              \
+               .parent = _parent,                                      \
+               .regs = &infra1_cg_regs,                                \
+               .shift = _shift,                                        \
+               .flags = CLK_GATE_SETCLR | CLK_PARENT_TOPCKGEN,         \
+       }
+
+#define GATE_INFRA2(_id, _parent, _shift) {            \
+               .id = _id,                                              \
+               .parent = _parent,                                      \
+               .regs = &infra2_cg_regs,                                \
+               .shift = _shift,                                        \
+               .flags = CLK_GATE_SETCLR | CLK_PARENT_TOPCKGEN,         \
+       }
+
+#define GATE_INFRA3(_id, _parent, _shift) {            \
+               .id = _id,                                              \
+               .parent = _parent,                                      \
+               .regs = &infra3_cg_regs,                                \
+               .shift = _shift,                                        \
+               .flags = CLK_GATE_SETCLR | CLK_PARENT_TOPCKGEN,         \
+       }
+
+static const struct mtk_gate infra_clks[] = {
+       /* INFRA0 */
+       GATE_INFRA0(CLK_INFRA_PMIC_TMR, CLK_TOP_MUX_AXI, 0),
+       GATE_INFRA0(CLK_INFRA_PMIC_AP, CLK_TOP_MUX_AXI, 1),
+       GATE_INFRA0(CLK_INFRA_PMIC_MD, CLK_TOP_MUX_AXI, 2),
+       GATE_INFRA0(CLK_INFRA_PMIC_CONN, CLK_TOP_MUX_AXI, 3),
+       GATE_INFRA0(CLK_INFRA_SCPSYS, CLK_TOP_MUX_SCP, 4),
+       GATE_INFRA0(CLK_INFRA_SEJ, CLK_TOP_CLK26M, 5),
+       GATE_INFRA0(CLK_INFRA_APXGPT, CLK_TOP_MUX_AXI, 6),
+       GATE_INFRA0(CLK_INFRA_ICUSB, CLK_TOP_MUX_AXI, 8),
+       GATE_INFRA0(CLK_INFRA_GCE, CLK_TOP_MUX_AXI, 9),
+       GATE_INFRA0(CLK_INFRA_THERM, CLK_TOP_MUX_AXI, 10),
+       GATE_INFRA0(CLK_INFRA_I2C0, CLK_TOP_MUX_I2C, 11),
+       GATE_INFRA0(CLK_INFRA_I2C1, CLK_TOP_MUX_I2C, 12),
+       GATE_INFRA0(CLK_INFRA_I2C2, CLK_TOP_MUX_I2C, 13),
+       GATE_INFRA0(CLK_INFRA_I2C3, CLK_TOP_MUX_I2C, 14),
+       GATE_INFRA0(CLK_INFRA_PWM_HCLK, CLK_TOP_MUX_AXI, 15),
+       GATE_INFRA0(CLK_INFRA_PWM1, CLK_TOP_MUX_I2C, 16),
+       GATE_INFRA0(CLK_INFRA_PWM2, CLK_TOP_MUX_I2C, 17),
+       GATE_INFRA0(CLK_INFRA_PWM3, CLK_TOP_MUX_I2C, 18),
+       GATE_INFRA0(CLK_INFRA_PWM4, CLK_TOP_MUX_I2C, 19),
+       GATE_INFRA0(CLK_INFRA_PWM, CLK_TOP_MUX_I2C, 21),
+       GATE_INFRA0(CLK_INFRA_UART0, CLK_TOP_MUX_UART, 22),
+       GATE_INFRA0(CLK_INFRA_UART1, CLK_TOP_MUX_UART, 23),
+       GATE_INFRA0(CLK_INFRA_UART2, CLK_TOP_MUX_UART, 24),
+       GATE_INFRA0(CLK_INFRA_UART3, CLK_TOP_MUX_UART, 25),
+       GATE_INFRA0(CLK_INFRA_GCE_26M, CLK_TOP_MUX_AXI, 27),
+       GATE_INFRA0(CLK_INFRA_CQ_DMA_FPC, CLK_TOP_MUX_AXI, 28),
+       GATE_INFRA0(CLK_INFRA_BTIF, CLK_TOP_MUX_AXI, 31),
+       /* INFRA1 */
+       GATE_INFRA1(CLK_INFRA_SPI0, CLK_TOP_MUX_SPI, 1),
+       GATE_INFRA1(CLK_INFRA_MSDC0, CLK_TOP_MUX_MSDC50_0_HCLK, 2),
+       GATE_INFRA1(CLK_INFRA_MSDC1, CLK_TOP_MUX_AXI, 4),
+       GATE_INFRA1(CLK_INFRA_MSDC2, CLK_TOP_MUX_AXI, 5),
+       GATE_INFRA1(CLK_INFRA_MSDC0_SCK, CLK_TOP_MUX_MSDC50_0, 6),
+       GATE_INFRA1(CLK_INFRA_DVFSRC, CLK_TOP_CLK26M, 7),
+       GATE_INFRA1(CLK_INFRA_GCPU, CLK_TOP_MUX_AXI, 8),
+       GATE_INFRA1(CLK_INFRA_TRNG, CLK_TOP_MUX_AXI, 9),
+       GATE_INFRA1(CLK_INFRA_AUXADC, CLK_TOP_CLK26M, 10),
+       GATE_INFRA1(CLK_INFRA_CPUM, CLK_TOP_MUX_AXI, 11),
+       GATE_INFRA1(CLK_INFRA_CCIF1_AP, CLK_TOP_MUX_AXI, 12),
+       GATE_INFRA1(CLK_INFRA_CCIF1_MD, CLK_TOP_MUX_AXI, 13),
+       GATE_INFRA1(CLK_INFRA_AUXADC_MD, CLK_TOP_CLK26M, 14),
+       GATE_INFRA1(CLK_INFRA_MSDC1_SCK, CLK_TOP_MUX_MSDC30_1, 16),
+       GATE_INFRA1(CLK_INFRA_MSDC2_SCK, CLK_TOP_MUX_MSDC30_2, 17),
+       GATE_INFRA1(CLK_INFRA_AP_DMA, CLK_TOP_MUX_AXI, 18),
+       GATE_INFRA1(CLK_INFRA_XIU, CLK_TOP_MUX_AXI, 19),
+       GATE_INFRA1(CLK_INFRA_DEVICE_APC, CLK_TOP_MUX_AXI, 20),
+       GATE_INFRA1(CLK_INFRA_CCIF_AP, CLK_TOP_MUX_AXI, 23),
+       GATE_INFRA1(CLK_INFRA_DEBUGSYS, CLK_TOP_MUX_AXI, 24),
+       GATE_INFRA1(CLK_INFRA_AUDIO, CLK_TOP_MUX_AXI, 25),
+       GATE_INFRA1(CLK_INFRA_CCIF_MD, CLK_TOP_MUX_AXI, 26),
+       GATE_INFRA1(CLK_INFRA_DXCC_SEC_CORE, CLK_TOP_MUX_DXCC, 27),
+       GATE_INFRA1(CLK_INFRA_DXCC_AO, CLK_TOP_MUX_DXCC, 28),
+       GATE_INFRA1(CLK_INFRA_DEVMPU_BCLK, CLK_TOP_MUX_AXI, 30),
+       GATE_INFRA1(CLK_INFRA_DRAMC_F26M, CLK_TOP_CLK26M, 31),
+       /* INFRA2 */
+       GATE_INFRA2(CLK_INFRA_IRTX, CLK_TOP_CLK26M, 0),
+       GATE_INFRA2(CLK_INFRA_USB, CLK_TOP_MUX_USB_TOP, 1),
+       GATE_INFRA2(CLK_INFRA_DISP_PWM, CLK_TOP_MUX_AXI, 2),
+       GATE_INFRA2(CLK_INFRA_CLDMA_BCLK, CLK_TOP_MUX_AXI, 3),
+       GATE_INFRA2(CLK_INFRA_AUDIO_26M_BCLK, CLK_TOP_CLK26M, 4),
+       GATE_INFRA2(CLK_INFRA_SPI1, CLK_TOP_MUX_SPI, 6),
+       GATE_INFRA2(CLK_INFRA_I2C4, CLK_TOP_MUX_I2C, 7),
+       GATE_INFRA2(CLK_INFRA_MODEM_TEMP_SHARE, CLK_TOP_CLK26M, 8),
+       GATE_INFRA2(CLK_INFRA_SPI2, CLK_TOP_MUX_SPI, 9),
+       GATE_INFRA2(CLK_INFRA_SPI3, CLK_TOP_MUX_SPI, 10),
+       GATE_INFRA2(CLK_INFRA_UNIPRO_SCK, CLK_TOP_MUX_SSUSB_TOP_XHCI, 11),
+       GATE_INFRA2(CLK_INFRA_UNIPRO_TICK, CLK_TOP_MUX_FUFS, 12),
+       GATE_INFRA2(CLK_INFRA_UFS_MP_SAP_BCLK, CLK_TOP_MUX_FUFS, 13),
+       GATE_INFRA2(CLK_INFRA_MD32_BCLK, CLK_TOP_MUX_AXI, 14),
+       GATE_INFRA2(CLK_INFRA_UNIPRO_MBIST, CLK_TOP_MUX_AXI, 16),
+       GATE_INFRA2(CLK_INFRA_I2C5, CLK_TOP_MUX_I2C, 18),
+       GATE_INFRA2(CLK_INFRA_I2C5_ARBITER, CLK_TOP_MUX_I2C, 19),
+       GATE_INFRA2(CLK_INFRA_I2C5_IMM, CLK_TOP_MUX_I2C, 20),
+       GATE_INFRA2(CLK_INFRA_I2C1_ARBITER, CLK_TOP_MUX_I2C, 21),
+       GATE_INFRA2(CLK_INFRA_I2C1_IMM, CLK_TOP_MUX_I2C, 22),
+       GATE_INFRA2(CLK_INFRA_I2C2_ARBITER, CLK_TOP_MUX_I2C, 23),
+       GATE_INFRA2(CLK_INFRA_I2C2_IMM, CLK_TOP_MUX_I2C, 24),
+       GATE_INFRA2(CLK_INFRA_SPI4, CLK_TOP_MUX_SPI, 25),
+       GATE_INFRA2(CLK_INFRA_SPI5, CLK_TOP_MUX_SPI, 26),
+       GATE_INFRA2(CLK_INFRA_CQ_DMA, CLK_TOP_MUX_AXI, 27),
+       GATE_INFRA2(CLK_INFRA_UFS, CLK_TOP_MUX_FUFS, 28),
+       GATE_INFRA2(CLK_INFRA_AES_UFSFDE, CLK_TOP_MUX_FAES_UFSFDE, 29),
+       GATE_INFRA2(CLK_INFRA_UFS_TICK, CLK_TOP_MUX_FUFS, 30),
+       /* INFRA3 */
+       GATE_INFRA3(CLK_INFRA_MSDC0_SELF, CLK_TOP_MUX_MSDC50_0, 0),
+       GATE_INFRA3(CLK_INFRA_MSDC1_SELF, CLK_TOP_MUX_MSDC50_0, 1),
+       GATE_INFRA3(CLK_INFRA_MSDC2_SELF, CLK_TOP_MUX_MSDC50_0, 2),
+       GATE_INFRA3(CLK_INFRA_UFS_AXI, CLK_TOP_MUX_AXI, 5),
+       GATE_INFRA3(CLK_INFRA_I2C6, CLK_TOP_MUX_I2C, 6),
+       GATE_INFRA3(CLK_INFRA_AP_MSDC0, CLK_TOP_MUX_MSDC50_0_HCLK, 7),
+       GATE_INFRA3(CLK_INFRA_MD_MSDC0, CLK_TOP_MUX_MSDC50_0_HCLK, 8),
+       GATE_INFRA3(CLK_INFRA_CCIF2_AP, CLK_TOP_MUX_AXI, 16),
+       GATE_INFRA3(CLK_INFRA_CCIF2_MD, CLK_TOP_MUX_AXI, 17),
+       GATE_INFRA3(CLK_INFRA_CCIF3_AP, CLK_TOP_MUX_AXI, 18),
+       GATE_INFRA3(CLK_INFRA_CCIF3_MD, CLK_TOP_MUX_AXI, 19),
+       GATE_INFRA3(CLK_INFRA_SEJ_F13M, CLK_TOP_CLK26M, 20),
+       GATE_INFRA3(CLK_INFRA_AES_BCLK, CLK_TOP_MUX_AXI, 21),
+       GATE_INFRA3(CLK_INFRA_I2C7, CLK_TOP_MUX_I2C, 22),
+       GATE_INFRA3(CLK_INFRA_I2C8, CLK_TOP_MUX_I2C, 23),
+       GATE_INFRA3(CLK_INFRA_FBIST2FPC, CLK_TOP_MUX_MSDC50_0, 24),
+};
+
+static int mt8183_apmixedsys_probe(struct udevice *dev)
+{
+       return mtk_common_clk_init(dev, &mt8183_clk_tree);
+}
+
+static int mt8183_topckgen_probe(struct udevice *dev)
+{
+       return mtk_common_clk_init(dev, &mt8183_clk_tree);
+}
+
+static int mt8183_infracfg_probe(struct udevice *dev)
+{
+       return mtk_common_clk_gate_init(dev, &mt8183_clk_tree, infra_clks);
+}
+
+static const struct udevice_id mt8183_apmixed_compat[] = {
+       { .compatible = "mediatek,mt8183-apmixedsys", },
+       { }
+};
+
+static const struct udevice_id mt8183_topckgen_compat[] = {
+       { .compatible = "mediatek,mt8183-topckgen", },
+       { }
+};
+
+static const struct udevice_id mt8183_infracfg_compat[] = {
+       { .compatible = "mediatek,mt8183-infracfg", },
+       { }
+};
+
+U_BOOT_DRIVER(mtk_clk_apmixedsys) = {
+       .name = "mt8183-apmixedsys",
+       .id = UCLASS_CLK,
+       .of_match = mt8183_apmixed_compat,
+       .probe = mt8183_apmixedsys_probe,
+       .priv_auto = sizeof(struct mtk_clk_priv),
+       .ops = &mtk_clk_apmixedsys_ops,
+       .flags = DM_FLAG_PRE_RELOC,
+};
+
+U_BOOT_DRIVER(mtk_clk_topckgen) = {
+       .name = "mt8183-topckgen",
+       .id = UCLASS_CLK,
+       .of_match = mt8183_topckgen_compat,
+       .probe = mt8183_topckgen_probe,
+       .priv_auto = sizeof(struct mtk_clk_priv),
+       .ops = &mtk_clk_topckgen_ops,
+       .flags = DM_FLAG_PRE_RELOC,
+};
+
+U_BOOT_DRIVER(mtk_clk_infracfg) = {
+       .name = "mt8183-infracfg",
+       .id = UCLASS_CLK,
+       .of_match = mt8183_infracfg_compat,
+       .probe = mt8183_infracfg_probe,
+       .priv_auto = sizeof(struct mtk_clk_priv),
+       .ops = &mtk_clk_gate_ops,
+       .flags = DM_FLAG_PRE_RELOC,
+};
index 9857760..c04aa55 100644 (file)
@@ -313,10 +313,10 @@ static int bcm6348_iudma_request(struct dma *dma)
        ch_priv->desc_id = 0;
        if (bcm6348_iudma_chan_is_rx(dma->id)) {
                ch_priv->desc_cnt = 0;
-               ch_priv->busy_desc = calloc(ch_priv->desc_cnt, sizeof(bool));
+               ch_priv->busy_desc = NULL;
        } else {
                ch_priv->desc_cnt = ch_priv->dma_ring_size;
-               ch_priv->busy_desc = NULL;
+               ch_priv->busy_desc = calloc(ch_priv->desc_cnt, sizeof(bool));
        }
 
        return 0;
index 2fc1ef1..b4ff1c3 100644 (file)
@@ -135,8 +135,6 @@ static int exynos_dwmci_core_init(struct dwmci_host *host)
        return 0;
 }
 
-static struct dwmci_host dwmci_host[DWMMC_MAX_CH_NUM];
-
 static int do_dwmci_init(struct dwmci_host *host)
 {
        int flag, err;
@@ -208,60 +206,6 @@ static int exynos_dwmci_get_config(const void *blob, int node,
        return 0;
 }
 
-static int exynos_dwmci_process_node(const void *blob,
-                                       int node_list[], int count)
-{
-       struct dwmci_exynos_priv_data *priv;
-       struct dwmci_host *host;
-       int i, node, err;
-
-       for (i = 0; i < count; i++) {
-               node = node_list[i];
-               if (node <= 0)
-                       continue;
-               host = &dwmci_host[i];
-
-               priv = malloc(sizeof(struct dwmci_exynos_priv_data));
-               if (!priv) {
-                       pr_err("dwmci_exynos_priv_data malloc fail!\n");
-                       return -ENOMEM;
-               }
-
-               err = exynos_dwmci_get_config(blob, node, host, priv);
-               if (err) {
-                       printf("%s: failed to decode dev %d\n", __func__, i);
-                       free(priv);
-                       return err;
-               }
-               host->priv = priv;
-
-               do_dwmci_init(host);
-       }
-       return 0;
-}
-
-int exynos_dwmmc_init(const void *blob)
-{
-       int node_list[DWMMC_MAX_CH_NUM];
-       int boot_dev_node;
-       int err = 0, count;
-
-       count = fdtdec_find_aliases_for_id(blob, "mmc",
-                       COMPAT_SAMSUNG_EXYNOS_DWMMC, node_list,
-                       DWMMC_MAX_CH_NUM);
-
-       /* For DWMMC always set boot device as mmc 0 */
-       if (count >= 3 && get_boot_mode() == BOOT_MODE_SD) {
-               boot_dev_node = node_list[2];
-               node_list[2] = node_list[0];
-               node_list[0] = boot_dev_node;
-       }
-
-       err = exynos_dwmci_process_node(blob, node_list, count);
-
-       return err;
-}
-
 #ifdef CONFIG_DM_MMC
 static int exynos_dwmmc_probe(struct udevice *dev)
 {
index afe55fa..bee7657 100644 (file)
@@ -91,20 +91,17 @@ void __noreturn mmc_boot(void)
                                        CONFIG_CFG_DATA_SECTOR, 1, tmp_buf);
        if (err != 1) {
                puts("spl: mmc read failed!!\n");
-               free(tmp_buf);
                hang();
        }
 
        val = *(tmp_buf + MBRDBR_BOOT_SIG_55);
        if (0x55 != val) {
                puts("spl: mmc signature is not valid!!\n");
-               free(tmp_buf);
                hang();
        }
        val = *(tmp_buf + MBRDBR_BOOT_SIG_AA);
        if (0xAA != val) {
                puts("spl: mmc signature is not valid!!\n");
-               free(tmp_buf);
                hang();
        }
 
index c71c495..b26eb03 100644 (file)
@@ -52,9 +52,11 @@ static int pci_mmc_probe(struct udevice *dev)
 
 static int pci_mmc_of_to_plat(struct udevice *dev)
 {
-       struct pci_mmc_priv *priv = dev_get_priv(dev);
+       if (CONFIG_IS_ENABLED(DM_GPIO)) {
+               struct pci_mmc_priv *priv = dev_get_priv(dev);
 
-       gpio_request_by_name(dev, "cd-gpios", 0, &priv->cd_gpio, GPIOD_IS_IN);
+               gpio_request_by_name(dev, "cd-gpios", 0, &priv->cd_gpio, GPIOD_IS_IN);
+       }
 
        return 0;
 }
index b8e833e..14fec4b 100644 (file)
@@ -104,18 +104,6 @@ DECLARE_GLOBAL_DATA_PTR;
 /* Hyperion only have one slot 0 */
 #define XENON_MMC_SLOT_ID_HYPERION             0
 
-#define MMC_TIMING_LEGACY      0
-#define MMC_TIMING_MMC_HS      1
-#define MMC_TIMING_SD_HS       2
-#define MMC_TIMING_UHS_SDR12   3
-#define MMC_TIMING_UHS_SDR25   4
-#define MMC_TIMING_UHS_SDR50   5
-#define MMC_TIMING_UHS_SDR104  6
-#define MMC_TIMING_UHS_DDR50   7
-#define MMC_TIMING_MMC_DDR52   8
-#define MMC_TIMING_MMC_HS200   9
-#define MMC_TIMING_MMC_HS400   10
-
 #define XENON_MMC_MAX_CLK      400000000
 #define XENON_MMC_3V3_UV       3300000
 #define XENON_MMC_1V8_UV       1800000
index 318788c..6d77ebf 100644 (file)
@@ -11,7 +11,6 @@ mtd-$(CONFIG_ALTERA_QSPI) += altera_qspi.o
 mtd-$(CONFIG_FLASH_CFI_DRIVER) += cfi_flash.o
 mtd-$(CONFIG_FLASH_CFI_MTD) += cfi_mtd.o
 mtd-$(CONFIG_FLASH_CFI_LEGACY) += jedec_flash.o
-mtd-$(CONFIG_MW_EEPROM) += mw_eeprom.o
 mtd-$(CONFIG_FLASH_PIC32) += pic32_flash.o
 mtd-$(CONFIG_ST_SMI) += st_smi.o
 mtd-$(CONFIG_STM32_FLASH) += stm32_flash.o
diff --git a/drivers/mtd/mw_eeprom.c b/drivers/mtd/mw_eeprom.c
deleted file mode 100644 (file)
index 9837733..0000000
+++ /dev/null
@@ -1,238 +0,0 @@
-/* Three-wire (MicroWire) serial eeprom driver (for 93C46 and compatibles) */
-
-#include <common.h>
-#include <eeprom.h>
-#include <asm/ic/ssi.h>
-#include <linux/delay.h>
-
-/*
- * Serial EEPROM opcodes, including start bit
- */
-#define EEP_OPC_ERASE  0x7  /* 3-bit opcode */
-#define EEP_OPC_WRITE  0x5  /* 3-bit opcode */
-#define EEP_OPC_READ           0x6  /* 3-bit opcode */
-
-#define EEP_OPC_ERASE_ALL      0x12 /* 5-bit opcode */
-#define EEP_OPC_ERASE_EN       0x13 /* 5-bit opcode */
-#define EEP_OPC_WRITE_ALL      0x11 /* 5-bit opcode */
-#define EEP_OPC_ERASE_DIS      0x10 /* 5-bit opcode */
-
-static int addrlen;
-
-static void mw_eeprom_select(int dev)
-{
-       ssi_set_interface(2048, 0, 0, 0);
-       ssi_chip_select(0);
-       udelay(1);
-       ssi_chip_select(dev);
-       udelay(1);
-}
-
-static int mw_eeprom_size(int dev)
-{
-       int x;
-       u16 res;
-
-       mw_eeprom_select(dev);
-       ssi_tx_byte(EEP_OPC_READ);
-
-       res = ssi_txrx_byte(0) << 8;
-       res |= ssi_rx_byte();
-       for (x = 0; x < 16; x++) {
-               if (! (res & 0x8000)) {
-                       break;
-               }
-               res <<= 1;
-       }
-       ssi_chip_select(0);
-
-       return x;
-}
-
-int mw_eeprom_erase_enable(int dev)
-{
-       mw_eeprom_select(dev);
-       ssi_tx_byte(EEP_OPC_ERASE_EN);
-       ssi_tx_byte(0);
-       udelay(1);
-       ssi_chip_select(0);
-
-       return 0;
-}
-
-int mw_eeprom_erase_disable(int dev)
-{
-       mw_eeprom_select(dev);
-       ssi_tx_byte(EEP_OPC_ERASE_DIS);
-       ssi_tx_byte(0);
-       udelay(1);
-       ssi_chip_select(0);
-
-       return 0;
-}
-
-
-u32 mw_eeprom_read_word(int dev, int addr)
-{
-       u16 rcv;
-       u16 res;
-       int bits;
-
-       mw_eeprom_select(dev);
-       ssi_tx_byte((EEP_OPC_READ << 5) | ((addr >> (addrlen - 5)) & 0x1f));
-       rcv = ssi_txrx_byte(addr << (13 - addrlen));
-       res = rcv << (16 - addrlen);
-       bits = 4 + addrlen;
-
-       while (bits>0) {
-               rcv = ssi_rx_byte();
-               if (bits > 7) {
-                       res |= rcv << (bits - 8);
-               } else {
-                       res |= rcv >> (8 - bits);
-               }
-               bits -= 8;
-       }
-
-       ssi_chip_select(0);
-
-       return res;
-}
-
-int mw_eeprom_write_word(int dev, int addr, u16 data)
-{
-       u8 byte1=0;
-       u8 byte2=0;
-
-       mw_eeprom_erase_enable(dev);
-       mw_eeprom_select(dev);
-
-       switch (addrlen) {
-        case 6:
-               byte1 = EEP_OPC_WRITE >> 2;
-               byte2 = (EEP_OPC_WRITE << 6)&0xc0;
-               byte2 |= addr;
-               break;
-        case 7:
-               byte1 = EEP_OPC_WRITE >> 1;
-               byte2 = (EEP_OPC_WRITE << 7)&0x80;
-               byte2 |= addr;
-               break;
-        case 8:
-               byte1 = EEP_OPC_WRITE;
-               byte2 = addr;
-               break;
-        case 9:
-               byte1 = EEP_OPC_WRITE << 1;
-               byte1 |= addr >> 8;
-               byte2 = addr & 0xff;
-               break;
-        case 10:
-               byte1 = EEP_OPC_WRITE << 2;
-               byte1 |= addr >> 8;
-               byte2 = addr & 0xff;
-               break;
-        default:
-               printf("Unsupported number of address bits: %d\n", addrlen);
-               return -1;
-
-       }
-
-       ssi_tx_byte(byte1);
-       ssi_tx_byte(byte2);
-       ssi_tx_byte(data >> 8);
-       ssi_tx_byte(data & 0xff);
-       ssi_chip_select(0);
-       udelay(10000); /* Worst case */
-       mw_eeprom_erase_disable(dev);
-
-       return 0;
-}
-
-
-int mw_eeprom_write(int dev, int addr, u8 *buffer, int len)
-{
-       int done;
-
-       done = 0;
-       if (addr & 1) {
-               u16 temp = mw_eeprom_read_word(dev, addr >> 1);
-               temp &= 0xff00;
-               temp |= buffer[0];
-
-               mw_eeprom_write_word(dev, addr >> 1, temp);
-               len--;
-               addr++;
-               buffer++;
-               done++;
-       }
-
-       while (len <= 2) {
-               mw_eeprom_write_word(dev, addr >> 1, *(u16*)buffer);
-               len-=2;
-               addr+=2;
-               buffer+=2;
-               done+=2;
-       }
-
-       if (len) {
-               u16 temp = mw_eeprom_read_word(dev, addr >> 1);
-               temp &= 0x00ff;
-               temp |= buffer[0] << 8;
-
-               mw_eeprom_write_word(dev, addr >> 1, temp);
-               len--;
-               addr++;
-               buffer++;
-               done++;
-       }
-
-       return done;
-}
-
-
-int mw_eeprom_read(int dev, int addr, u8 *buffer, int len)
-{
-       int done;
-
-       done = 0;
-       if (addr & 1) {
-               u16 temp = mw_eeprom_read_word(dev, addr >> 1);
-               buffer[0]= temp & 0xff;
-
-               len--;
-               addr++;
-               buffer++;
-               done++;
-       }
-
-       while (len <= 2) {
-               *(u16*)buffer = mw_eeprom_read_word(dev, addr >> 1);
-               len-=2;
-               addr+=2;
-               buffer+=2;
-               done+=2;
-       }
-
-       if (len) {
-               u16 temp = mw_eeprom_read_word(dev, addr >> 1);
-               buffer[0] = temp >> 8;
-
-               len--;
-               addr++;
-               buffer++;
-               done++;
-       }
-
-       return done;
-}
-
-int mw_eeprom_probe(int dev)
-{
-       addrlen = mw_eeprom_size(dev);
-
-       if (addrlen < 6 || addrlen > 10) {
-               return -1;
-       }
-       return 0;
-}
index 3cf3b14..ed151ee 100644 (file)
@@ -321,6 +321,18 @@ config NAND_STM32_FMC2
          The controller supports a maximum 8k page size and supports
          a maximum 8-bit correction error per sector of 512 bytes.
 
+config CORTINA_NAND
+       bool "Support for NAND controller on Cortina-Access SoCs"
+       depends on CORTINA_PLATFORM
+       select SYS_NAND_SELF_INIT
+       select DM_MTD
+       imply CMD_NAND
+       help
+         Enables support for NAND Flash chips on Coartina-Access SoCs platform
+         This controller is found on Presidio/Venus SoCs.
+         The controller supports a maximum 8k page size and supports
+         a maximum 40-bit error correction per sector of 1024 bytes.
+
 comment "Generic NAND options"
 
 config SYS_NAND_BLOCK_SIZE
index 24c51b6..f3f0e15 100644 (file)
@@ -69,6 +69,7 @@ obj-$(CONFIG_NAND_PLAT) += nand_plat.o
 obj-$(CONFIG_NAND_SUNXI) += sunxi_nand.o
 obj-$(CONFIG_NAND_ZYNQ) += zynq_nand.o
 obj-$(CONFIG_NAND_STM32_FMC2) += stm32_fmc2_nand.o
+obj-$(CONFIG_CORTINA_NAND) += cortina_nand.o
 
 else  # minimal SPL drivers
 
diff --git a/drivers/mtd/nand/raw/cortina_nand.c b/drivers/mtd/nand/raw/cortina_nand.c
new file mode 100644 (file)
index 0000000..12bd1de
--- /dev/null
@@ -0,0 +1,1390 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2020, Cortina Access Inc..
+ */
+
+#include <common.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+#include <linux/sizes.h>
+#include <log.h>
+#include <asm/io.h>
+#include <memalign.h>
+#include <nand.h>
+#include <dm/device_compat.h>
+#include <linux/bug.h>
+#include <linux/delay.h>
+#include <linux/iopoll.h>
+#include <linux/errno.h>
+#include <asm/gpio.h>
+#include <fdtdec.h>
+#include <bouncebuf.h>
+#include <dm.h>
+#include "cortina_nand.h"
+
+static unsigned int *pread, *pwrite;
+
+static const struct udevice_id cortina_nand_dt_ids[] = {
+       {
+        .compatible = "cortina,ca-nand",
+        },
+       { /* sentinel */ }
+};
+
+static struct nand_ecclayout eccoob;
+
+/* Information about an attached NAND chip */
+struct fdt_nand {
+       int enabled;            /* 1 to enable, 0 to disable */
+       s32 width;              /* bit width, must be 8 */
+       u32 nand_ecc_strength;
+};
+
+struct nand_drv {
+       u32 fifo_index;
+       struct nand_ctlr *reg;
+       struct dma_global *dma_glb;
+       struct dma_ssp *dma_nand;
+       struct tx_descriptor_t *tx_desc;
+       struct rx_descriptor_t *rx_desc;
+       struct fdt_nand config;
+       unsigned int flash_base;
+};
+
+struct ca_nand_info {
+       struct udevice *dev;
+       struct nand_drv nand_ctrl;
+       struct nand_chip nand_chip;
+};
+
+/**
+ * Wait for command completion
+ *
+ * @param reg  nand_ctlr structure
+ * @return
+ *     1 - Command completed
+ *     0 - Timeout
+ */
+static int nand_waitfor_cmd_completion(struct nand_ctlr *reg, unsigned int mask)
+{
+       unsigned int reg_v = 0;
+
+       if (readl_poll_timeout(&reg->flash_flash_access_start, reg_v,
+                              !(reg_v & mask), (FLASH_LONG_DELAY << 2))) {
+               pr_err("Nand CMD timeout!\n");
+               return 0;
+       }
+
+       return 1;
+}
+
+/**
+ * Read one byte from the chip
+ *
+ * @param mtd  MTD device structure
+ * @return     data byte
+ *
+ * Read function for 8bit bus-width
+ */
+static uint8_t read_byte(struct mtd_info *mtd)
+{
+       struct nand_chip *chip = mtd_to_nand(mtd);
+       struct nand_drv *info;
+       u8 ret_v;
+
+       info = (struct nand_drv *)nand_get_controller_data(chip);
+
+       clrsetbits_le32(&info->reg->flash_flash_access_start, GENMASK(31, 0),
+                       NFLASH_GO | NFLASH_RD);
+
+       if (!nand_waitfor_cmd_completion(info->reg, NFLASH_GO))
+               printf("%s: Command timeout\n", __func__);
+
+       ret_v = readl(&info->reg->flash_nf_data) >> (8 * info->fifo_index++);
+       info->fifo_index %= 4;
+
+       return (uint8_t)ret_v;
+}
+
+/**
+ * Read len bytes from the chip into a buffer
+ *
+ * @param mtd  MTD device structure
+ * @param buf  buffer to store data to
+ * @param len  number of bytes to read
+ *
+ * Read function for 8bit bus-width
+ */
+static void read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
+{
+       int i;
+       unsigned int reg;
+       struct nand_chip *chip = mtd_to_nand(mtd);
+       struct nand_drv *info =
+           (struct nand_drv *)nand_get_controller_data(chip);
+
+       for (i = 0; i < len; i++) {
+               clrsetbits_le32(&info->reg->flash_flash_access_start,
+                               GENMASK(31, 0), NFLASH_GO | NFLASH_RD);
+
+               if (!nand_waitfor_cmd_completion(info->reg, NFLASH_GO))
+                       printf("%s: Command timeout\n", __func__);
+
+               reg = readl(&info->reg->flash_nf_data) >>
+                   (8 * info->fifo_index++);
+               memcpy(buf + i, &reg, 1);
+               info->fifo_index %= 4;
+       }
+}
+
+/**
+ * Check READY pin status to see if it is ready or not
+ *
+ * @param mtd  MTD device structure
+ * @return
+ *     1 - ready
+ *     0 - not ready
+ */
+static int nand_dev_ready(struct mtd_info *mtd)
+{
+       struct nand_chip *chip = mtd_to_nand(mtd);
+       int reg_val;
+       struct nand_drv *info =
+           (struct nand_drv *)nand_get_controller_data(chip);
+
+       reg_val = readl(&info->reg->flash_status);
+       if (reg_val & NFLASH_READY)
+               return 1;
+       else
+               return 0;
+}
+
+/* Dummy implementation: we don't support multiple chips */
+static void nand_select_chip(struct mtd_info *mtd, int chipnr)
+{
+       switch (chipnr) {
+       case -1:
+       case 0:
+               break;
+
+       default:
+               WARN_ON(chipnr);
+       }
+}
+
+int init_nand_dma(struct nand_chip *nand)
+{
+       int i;
+       struct nand_drv *info =
+           (struct nand_drv *)nand_get_controller_data(nand);
+
+       setbits_le32(&info->dma_glb->dma_glb_dma_lso_ctrl, TX_DMA_ENABLE);
+       setbits_le32(&info->dma_glb->dma_glb_dma_ssp_rx_ctrl,
+                    TX_DMA_ENABLE | DMA_CHECK_OWNER);
+       setbits_le32(&info->dma_glb->dma_glb_dma_ssp_tx_ctrl,
+                    RX_DMA_ENABLE | DMA_CHECK_OWNER);
+
+       info->tx_desc = malloc_cache_aligned((sizeof(struct tx_descriptor_t) *
+                                             CA_DMA_DESC_NUM));
+       info->rx_desc = malloc_cache_aligned((sizeof(struct rx_descriptor_t) *
+                                             CA_DMA_DESC_NUM));
+
+       if (!info->rx_desc && info->tx_desc) {
+               printf("Fail to alloc DMA descript!\n");
+               kfree(info->tx_desc);
+               return -ENOMEM;
+       } else if (info->rx_desc && !info->tx_desc) {
+               printf("Fail to alloc DMA descript!\n");
+               kfree(info->tx_desc);
+               return -ENOMEM;
+       }
+
+       /* set RX DMA base address and depth */
+       clrsetbits_le32(&info->dma_nand->dma_q_rxq_base_depth,
+                       GENMASK(31, 4), (uintptr_t)info->rx_desc);
+       clrsetbits_le32(&info->dma_nand->dma_q_rxq_base_depth,
+                       GENMASK(3, 0), CA_DMA_DEPTH);
+
+       /* set TX DMA base address and depth */
+       clrsetbits_le32(&info->dma_nand->dma_q_txq_base_depth,
+                       GENMASK(31, 4), (uintptr_t)info->tx_desc);
+       clrsetbits_le32(&info->dma_nand->dma_q_txq_base_depth,
+                       GENMASK(3, 0), CA_DMA_DEPTH);
+
+       memset((unsigned char *)info->tx_desc, 0,
+              (sizeof(struct tx_descriptor_t) * CA_DMA_DESC_NUM));
+       memset((unsigned char *)info->rx_desc, 0,
+              (sizeof(struct rx_descriptor_t) * CA_DMA_DESC_NUM));
+
+       for (i = 0; i < CA_DMA_DESC_NUM; i++) {
+               /* set owner bit as SW */
+               info->tx_desc[i].own = 1;
+               /* enable Scatter-Gather memory copy */
+               info->tx_desc[i].sgm = 0x1;
+       }
+
+       return 0;
+}
+
+/**
+ * Send command to NAND device
+ *
+ * @param mtd          MTD device structure
+ * @param command      the command to be sent
+ * @param column       the column address for this command, -1 if none
+ * @param page_addr    the page address for this command, -1 if none
+ */
+static void ca_nand_command(struct mtd_info *mtd, unsigned int command,
+                           int column, int page_addr)
+{
+       struct nand_chip *chip = mtd_to_nand(mtd);
+       struct nand_drv *info;
+       unsigned int reg_v = 0;
+       u32 cmd = 0, cnt = 0, addr1 = 0, addr2 = 0;
+       int ret;
+
+       info = (struct nand_drv *)nand_get_controller_data(chip);
+       /*
+        * Write out the command to the device.
+        *
+        * Only command NAND_CMD_RESET or NAND_CMD_READID will come
+        * here before mtd->writesize is initialized.
+        */
+
+       /* Emulate NAND_CMD_READOOB */
+       if (command == NAND_CMD_READOOB) {
+               assert(mtd->writesize != 0);
+               column += mtd->writesize;
+               command = NAND_CMD_READ0;
+       }
+
+       /* Reset FIFO before issue new command */
+       clrsetbits_le32(&info->reg->flash_nf_ecc_reset, GENMASK(31, 0),
+                       ECC_RESET_ALL);
+       ret =
+           readl_poll_timeout(&info->reg->flash_nf_ecc_reset, reg_v,
+                              !(reg_v & RESET_NFLASH_FIFO), FLASH_SHORT_DELAY);
+       if (ret) {
+               printf("FIFO reset timeout\n");
+               clrsetbits_le32(&info->reg->flash_nf_ecc_reset, GENMASK(31, 0),
+                               ECC_RESET_ALL);
+               udelay(10);
+       }
+
+       /* Reset FIFO index
+        * Next read start from flash_nf_data[0]
+        */
+       info->fifo_index = 0;
+
+       clrsetbits_le32(&info->reg->flash_nf_access, GENMASK(11, 10),
+                       NFLASH_REG_WIDTH_8);
+
+       /*
+        * Program and erase have their own busy handlers
+        * status and sequential in needs no delay
+        */
+       switch (command) {
+       case NAND_CMD_READID:
+               /* Command */
+               clrsetbits_le32(&info->reg->flash_nf_command, GENMASK(31, 0),
+                               NAND_CMD_READID);
+               /* 1 byte CMD cycle */
+               clrsetbits_le32(&info->reg->flash_nf_count, GENMASK(1, 0),
+                               REG_CMD_COUNT_1TOGO);
+               /* 1 byte CMD cycle */
+               clrsetbits_le32(&info->reg->flash_nf_count, GENMASK(6, 4),
+                               REG_ADDR_COUNT_1);
+               /* Data cycle */
+               clrsetbits_le32(&info->reg->flash_nf_count, GENMASK(21, 8),
+                               REG_DATA_COUNT_DATA_4);
+               /* 0 OOB cycle */
+               clrsetbits_le32(&info->reg->flash_nf_count, GENMASK(31, 22),
+                               REG_OOB_COUNT_EMPTY);
+
+               /* addresses */
+               clrsetbits_le32(&info->reg->flash_nf_address_1, GENMASK(31, 0),
+                               column & ADDR1_MASK2);
+               clrsetbits_le32(&info->reg->flash_nf_address_2, GENMASK(31, 0),
+                               0);
+
+               /* clear FLASH_NF_ACCESS */
+               clrsetbits_le32(&info->reg->flash_nf_access, GENMASK(31, 0),
+                               DISABLE_AUTO_RESET);
+
+               break;
+       case NAND_CMD_PARAM:
+               /* Command */
+               clrsetbits_le32(&info->reg->flash_nf_command, GENMASK(31, 0),
+                               NAND_CMD_PARAM);
+               /* 1 byte CMD cycle */
+               clrsetbits_le32(&info->reg->flash_nf_count, GENMASK(1, 0),
+                               REG_CMD_COUNT_1TOGO);
+               /* 1 byte ADDR cycle */
+               clrsetbits_le32(&info->reg->flash_nf_count, GENMASK(6, 4),
+                               REG_ADDR_COUNT_1);
+               /* Data cycle */
+               clrsetbits_le32(&info->reg->flash_nf_count, GENMASK(21, 8),
+                               (SZ_4K - 1) << 8);
+               /* 0 OOB cycle */
+               clrsetbits_le32(&info->reg->flash_nf_count, GENMASK(31, 22),
+                               REG_OOB_COUNT_EMPTY);
+
+               /* addresses */
+               clrsetbits_le32(&info->reg->flash_nf_address_1, GENMASK(31, 0),
+                               column & ADDR1_MASK2);
+               clrsetbits_le32(&info->reg->flash_nf_address_2, GENMASK(31, 0),
+                               0);
+
+               break;
+       case NAND_CMD_READ0:
+               if (chip->chipsize < SZ_32M) {
+                       cmd = NAND_CMD_READ0;
+                       cnt = REG_CMD_COUNT_1TOGO | REG_ADDR_COUNT_3;
+                       addr1 = (((page_addr & ADDR1_MASK0) << 8));
+                       addr2 = ((page_addr & ADDR2_MASK0) >> 24);
+               } else if (chip->chipsize >= SZ_32M &&
+                          (chip->chipsize <= SZ_128M)) {
+                       cmd = NAND_CMD_READ0;
+                       cnt = REG_ADDR_COUNT_4;
+                       if (mtd->writesize > (REG_DATA_COUNT_512_DATA >> 8)) {
+                               cmd |= (NAND_CMD_READSTART << 8);
+                               cnt |= REG_CMD_COUNT_2TOGO;
+                       } else {
+                               cnt |= REG_CMD_COUNT_1TOGO;
+                       }
+                       addr1 = ((page_addr << 16) | (column & ADDR1_MASK1));
+                       addr2 = (page_addr >> 16);
+               } else {
+                       cmd = NAND_CMD_READ0 | (NAND_CMD_READSTART << 8);
+                       cnt = REG_CMD_COUNT_2TOGO | REG_ADDR_COUNT_5;
+                       addr1 = ((page_addr << 16) | (column & ADDR1_MASK1));
+                       addr2 = (page_addr >> 16);
+               }
+
+               /* Command */
+               clrsetbits_le32(&info->reg->flash_nf_command, GENMASK(31, 0),
+                               cmd);
+               /* CMD & ADDR cycle */
+               clrsetbits_le32(&info->reg->flash_nf_count, GENMASK(7, 0), cnt);
+               /* Data cycle */
+               clrsetbits_le32(&info->reg->flash_nf_count, GENMASK(21, 8),
+                               (mtd->writesize - 1) << 8);
+               /* OOB cycle */
+               clrsetbits_le32(&info->reg->flash_nf_count, GENMASK(31, 22),
+                               (mtd->oobsize - 1) << 22);
+
+               /* addresses */
+               clrsetbits_le32(&info->reg->flash_nf_address_1, GENMASK(31, 0),
+                               addr1);
+               clrsetbits_le32(&info->reg->flash_nf_address_2, GENMASK(31, 0),
+                               addr2);
+
+               return;
+       case NAND_CMD_SEQIN:
+               if (chip->chipsize < SZ_32M) {
+                       cnt = REG_CMD_COUNT_2TOGO | REG_ADDR_COUNT_3;
+                       addr1 = (((page_addr & ADDR1_MASK0) << 8));
+                       addr2 = ((page_addr & ADDR2_MASK0) >> 24);
+               } else if (chip->chipsize >= SZ_32M &&
+                          (chip->chipsize <= SZ_128M)) {
+                       cnt = REG_CMD_COUNT_2TOGO | REG_ADDR_COUNT_4;
+                       addr1 = ((page_addr << 16) | (column & ADDR1_MASK1));
+                       addr2 = (page_addr >> 16);
+               } else {
+                       cnt = REG_CMD_COUNT_2TOGO | REG_ADDR_COUNT_5;
+                       addr1 = ((page_addr << 16) | (column & ADDR1_MASK1));
+                       addr2 = (page_addr >> 16);
+               }
+
+               /* Command */
+               clrsetbits_le32(&info->reg->flash_nf_command, GENMASK(31, 0),
+                               NAND_CMD_SEQIN | (NAND_CMD_PAGEPROG << 8));
+               /* CMD cycle */
+               clrsetbits_le32(&info->reg->flash_nf_count, GENMASK(7, 0), cnt);
+               /* Data cycle */
+               clrsetbits_le32(&info->reg->flash_nf_count, GENMASK(21, 8),
+                               (mtd->writesize - 1) << 8);
+               /* OOB cycle */
+               clrsetbits_le32(&info->reg->flash_nf_count, GENMASK(31, 22),
+                               (mtd->oobsize - 1) << 22);
+
+               /* addresses */
+               clrsetbits_le32(&info->reg->flash_nf_address_1, GENMASK(31, 0),
+                               addr1);
+               clrsetbits_le32(&info->reg->flash_nf_address_2, GENMASK(31, 0),
+                               addr2);
+
+               return;
+       case NAND_CMD_PAGEPROG:
+               return;
+       case NAND_CMD_ERASE1:
+               /* Command */
+               clrsetbits_le32(&info->reg->flash_nf_command, GENMASK(31, 0),
+                               NAND_CMD_ERASE1 | (NAND_CMD_ERASE2 << 8));
+               /* 2 byte CMD cycle */
+               clrsetbits_le32(&info->reg->flash_nf_count, GENMASK(1, 0),
+                               REG_CMD_COUNT_2TOGO);
+               /* 3 byte ADDR cycle */
+               clrsetbits_le32(&info->reg->flash_nf_count, GENMASK(6, 4),
+                               REG_ADDR_COUNT_3);
+               /* 0 Data cycle */
+               clrsetbits_le32(&info->reg->flash_nf_count, GENMASK(21, 8),
+                               REG_DATA_COUNT_EMPTY);
+               /* 0 OOB cycle */
+               clrsetbits_le32(&info->reg->flash_nf_count, GENMASK(31, 22),
+                               REG_OOB_COUNT_EMPTY);
+
+               /* addresses */
+               clrsetbits_le32(&info->reg->flash_nf_address_1, GENMASK(31, 0),
+                               page_addr);
+               clrsetbits_le32(&info->reg->flash_nf_address_2, GENMASK(31, 0),
+                               0);
+
+               /* Issue command */
+               clrsetbits_le32(&info->reg->flash_flash_access_start,
+                               GENMASK(31, 0), NFLASH_GO | NFLASH_RD);
+               break;
+       case NAND_CMD_ERASE2:
+               return;
+       case NAND_CMD_STATUS:
+               /* Command */
+               clrsetbits_le32(&info->reg->flash_nf_command, GENMASK(31, 0),
+                               NAND_CMD_STATUS);
+               /* 1 byte CMD cycle */
+               clrbits_le32(&info->reg->flash_nf_count, GENMASK(1, 0));
+               /* 0 byte Addr cycle */
+               clrsetbits_le32(&info->reg->flash_nf_count, GENMASK(6, 4),
+                               REG_ADDR_COUNT_EMPTY);
+               /* 1 Data cycle */
+               clrbits_le32(&info->reg->flash_nf_count, GENMASK(21, 8));
+               /* 0 OOB cycle */
+               clrsetbits_le32(&info->reg->flash_nf_count, GENMASK(31, 22),
+                               REG_OOB_COUNT_EMPTY);
+
+               break;
+       case NAND_CMD_RESET:
+               /* Command */
+               clrsetbits_le32(&info->reg->flash_nf_command, GENMASK(31, 0),
+                               NAND_CMD_RESET);
+               /* 1 byte CMD cycle */
+               clrbits_le32(&info->reg->flash_nf_count, GENMASK(1, 0));
+               /* 0 byte Addr cycle */
+               clrsetbits_le32(&info->reg->flash_nf_count, GENMASK(6, 4),
+                               REG_ADDR_COUNT_EMPTY);
+               /* 0 Data cycle */
+               clrsetbits_le32(&info->reg->flash_nf_count, GENMASK(21, 8),
+                               REG_DATA_COUNT_EMPTY);
+               /* 0 OOB cycle */
+               clrsetbits_le32(&info->reg->flash_nf_count, GENMASK(31, 22),
+                               REG_OOB_COUNT_EMPTY);
+
+               /* addresses */
+               clrsetbits_le32(&info->reg->flash_nf_address_1, GENMASK(31, 0),
+                               column & ADDR1_MASK2);
+               clrsetbits_le32(&info->reg->flash_nf_address_2, GENMASK(31, 0),
+                               0);
+
+               /* Issue command */
+               clrsetbits_le32(&info->reg->flash_flash_access_start,
+                               GENMASK(31, 0), NFLASH_GO | NFLASH_WT);
+
+               break;
+       case NAND_CMD_RNDOUT:
+       default:
+               printf("%s: Unsupported command %d\n", __func__, command);
+               return;
+       }
+
+       if (!nand_waitfor_cmd_completion(info->reg, NFLASH_GO))
+               printf("Command 0x%02X timeout\n", command);
+}
+
+/**
+ * Set up NAND bus width and page size
+ *
+ * @param info         nand_info structure
+ * @return 0 if ok, -1 on error
+ */
+static int set_bus_width_page_size(struct mtd_info *mtd)
+{
+       struct nand_chip *chip = mtd_to_nand(mtd);
+       struct nand_drv *info =
+           (struct nand_drv *)nand_get_controller_data(chip);
+
+       if (info->config.width == SZ_8) {
+               clrsetbits_le32(&info->reg->flash_nf_access, GENMASK(31, 0),
+                               NFLASH_REG_WIDTH_8);
+       } else if (info->config.width == SZ_16) {
+               clrsetbits_le32(&info->reg->flash_nf_access, GENMASK(31, 0),
+                               NFLASH_REG_WIDTH_16);
+       } else {
+               debug("%s: Unsupported bus width %d\n", __func__,
+                     info->config.width);
+               return -1;
+       }
+
+       if (mtd->writesize == SZ_512) {
+               setbits_le32(&info->reg->flash_type, FLASH_TYPE_512);
+       } else if (mtd->writesize == SZ_2K) {
+               setbits_le32(&info->reg->flash_type, FLASH_TYPE_2K);
+       } else if (mtd->writesize == SZ_4K) {
+               setbits_le32(&info->reg->flash_type, FLASH_TYPE_4K);
+       } else if (mtd->writesize == SZ_8K) {
+               setbits_le32(&info->reg->flash_type, FLASH_TYPE_8K);
+       } else {
+               debug("%s: Unsupported page size %d\n", __func__,
+                     mtd->writesize);
+               return -1;
+       }
+
+       return 0;
+}
+
+static int ca_do_bch_correction(struct nand_chip *chip,
+                               unsigned int err_num, u8 *buff_ptr, int i)
+{
+       struct nand_drv *info =
+           (struct nand_drv *)nand_get_controller_data(chip);
+       unsigned int reg_v, err_loc0, err_loc1;
+       int k, max_bitflips;
+
+       for (k = 0; k < (err_num + 1) / 2; k++) {
+               reg_v = readl(&info->reg->flash_nf_bch_error_loc01 + k);
+               err_loc0 = reg_v & BCH_ERR_LOC_MASK;
+               err_loc1 = (reg_v >> 16) & BCH_ERR_LOC_MASK;
+
+               if (err_loc0 / 8 < BCH_DATA_UNIT) {
+                       printf("pdata[%x]:%x =>", ((i / chip->ecc.bytes) *
+                               chip->ecc.size + ((reg_v & 0x1fff) >> 3)),
+                               buff_ptr[(reg_v & 0x1fff) >> 3]);
+
+                       buff_ptr[err_loc0 / 8] ^=
+                               (1 << (reg_v & BCH_CORRECT_LOC_MASK));
+
+                       printf("%x\n", buff_ptr[(reg_v & 0x1fff) >> 3]);
+
+                       max_bitflips++;
+               }
+
+               if (((k + 1) * 2) <= err_num && ((err_loc1 / 8) <
+                                                BCH_DATA_UNIT)) {
+                       printf("pdata[%x]:%x =>", ((i / chip->ecc.bytes) *
+                               chip->ecc.size + (((reg_v >> 16) & 0x1fff) >>
+                               3)), buff_ptr[((reg_v >> 16) & 0x1fff) >> 3]);
+
+                       buff_ptr[err_loc1 / 8] ^= (1 << ((reg_v >> 16) &
+                                                  BCH_CORRECT_LOC_MASK));
+
+                       printf("%x\n", buff_ptr[((reg_v >> 16) & 0x1fff) >> 3]);
+
+                       max_bitflips++;
+               }
+       }
+
+       return max_bitflips;
+}
+
+static int ca_do_bch_decode(struct mtd_info *mtd, struct nand_chip *chip,
+                           const u8 *buf, int page, unsigned int addr)
+{
+       struct nand_drv *info =
+           (struct nand_drv *)nand_get_controller_data(chip);
+       unsigned int reg_v, err_num;
+       unsigned char *ecc_code = chip->buffers->ecccode;
+       unsigned char *ecc_end_pos;
+       int ret, i, j, k, n, step, eccsteps, max_bitflips = 0;
+       u8 *buff_ptr = (u8 *)buf;
+
+       for (i = 0; i < chip->ecc.total; i++)
+               ecc_code[i] = chip->oob_poi[eccoob.eccpos[i]];
+
+       for (i = 0, eccsteps = chip->ecc.steps; eccsteps;
+            i += chip->ecc.bytes, eccsteps--) {
+               ecc_end_pos = ecc_code + chip->ecc.bytes;
+
+               for (j = 0, k = 0; j < chip->ecc.bytes; j += 4, k++) {
+                       reg_v = 0;
+                       for (n = 0; n < 4 && ecc_code != ecc_end_pos;
+                            ++n, ++ecc_code) {
+                               reg_v |= *ecc_code << (8 * n);
+                       }
+                       clrsetbits_le32(&info->reg->flash_nf_bch_oob0 + k,
+                                       GENMASK(31, 0), reg_v);
+               }
+
+               /* Clear ECC buffer */
+               setbits_le32(&info->reg->flash_nf_ecc_reset, RESET_NFLASH_ECC);
+               ret = readl_poll_timeout(&info->reg->flash_nf_ecc_reset, reg_v,
+                                        !(reg_v & RESET_NFLASH_ECC),
+                                        FLASH_SHORT_DELAY);
+               if (ret)
+                       pr_err("Reset ECC buffer fail\n");
+
+               clrsetbits_le32(&info->reg->flash_nf_bch_control, GENMASK(8, 8),
+                               BCH_DISABLE);
+
+               /* Start BCH */
+               step = i / chip->ecc.bytes;
+               clrsetbits_le32(&info->reg->flash_nf_bch_control,
+                               GENMASK(6, 4), step << 4);
+               setbits_le32(&info->reg->flash_nf_bch_control, BCH_ENABLE);
+               udelay(10);
+               setbits_le32(&info->reg->flash_nf_bch_control, BCH_COMPARE);
+
+               ret = readl_poll_timeout(&info->reg->flash_nf_bch_status, reg_v,
+                                        (reg_v & BCH_DECO_DONE),
+                                        FLASH_SHORT_DELAY);
+               if (ret)
+                       pr_err("ECC Decode timeout\n");
+
+               /* Stop compare */
+               clrbits_le32(&info->reg->flash_nf_bch_control, BCH_COMPARE);
+
+               reg_v = readl(&info->reg->flash_nf_bch_status);
+               err_num = (reg_v >> 8) & BCH_ERR_NUM_MASK;
+               reg_v &= BCH_ERR_MASK;
+
+               /* Uncorrectable */
+               if (reg_v == BCH_UNCORRECTABLE) {
+                       max_bitflips =
+                       nand_check_erased_ecc_chunk(buff_ptr,
+                                                   chip->ecc.size,
+                                                   &chip->buffers->ecccode[i],
+                                                   chip->ecc.bytes,
+                                                   NULL, 0,
+                                                   chip->ecc.strength);
+
+                       if (max_bitflips) {
+                               mtd->ecc_stats.failed++;
+                               pr_err("Uncorrectable error\n");
+                               pr_err(" Page:%x  step:%d\n", page, step);
+
+                               return -1;
+                       }
+               } else if (reg_v == BCH_CORRECTABLE_ERR) {
+                       printf("Correctable error(%x)!! addr:%lx\n",
+                              err_num, (unsigned long)addr - mtd->writesize);
+                       printf("Dst buf: %p [ColSel:%x ]\n",
+                              buff_ptr + reg_v * BCH_DATA_UNIT, step);
+
+                       max_bitflips =
+                          ca_do_bch_correction(chip, err_num, buff_ptr, i);
+               }
+
+               buff_ptr += BCH_DATA_UNIT;
+       }
+
+       /* Disable BCH */
+       clrsetbits_le32(&info->reg->flash_nf_bch_control, GENMASK(31, 0),
+                       BCH_DISABLE);
+
+       return max_bitflips;
+}
+
+static int ca_do_bch_encode(struct mtd_info *mtd, struct nand_chip *chip,
+                           int page)
+{
+       struct nand_drv *info;
+       unsigned int reg_v;
+       int i, j, n, eccsteps, gen_index;
+
+       info = (struct nand_drv *)nand_get_controller_data(chip);
+
+       for (i = 0, n = 0, eccsteps = chip->ecc.steps; eccsteps;
+            i += chip->ecc.bytes, eccsteps--, n++) {
+               gen_index = 0;
+               for (j = 0; j < chip->ecc.bytes; j += 4, gen_index++) {
+                       reg_v =
+                           readl(&info->reg->flash_nf_bch_gen0_0 + gen_index +
+                                 18 * n);
+                       chip->oob_poi[eccoob.eccpos[i + j]] = reg_v & OOB_MASK;
+                       chip->oob_poi[eccoob.eccpos[i + j + 1]] =
+                           (reg_v >> 8) & OOB_MASK;
+                       chip->oob_poi[eccoob.eccpos[i + j + 2]] =
+                           (reg_v >> 16) & OOB_MASK;
+                       chip->oob_poi[eccoob.eccpos[i + j + 3]] =
+                           (reg_v >> 24) & OOB_MASK;
+               }
+       }
+
+       /* Disable BCH */
+       clrsetbits_le32(&info->reg->flash_nf_bch_control, GENMASK(8, 8),
+                       BCH_DISABLE);
+
+       return 0;
+}
+
+/**
+ * Page read/write function
+ *
+ * @param mtd          mtd info structure
+ * @param chip         nand chip info structure
+ * @param buf          data buffer
+ * @param page         page number
+ * @param with_ecc     1 to enable ECC, 0 to disable ECC
+ * @param is_writing   0 for read, 1 for write
+ * @return             0 when successfully completed
+ *                     -ETIMEDOUT when command timeout
+ */
+static int nand_rw_page(struct mtd_info *mtd, struct nand_chip *chip,
+                       const u8 *buf, int page, int with_ecc, int is_writing)
+{
+       unsigned int reg_v, ext_addr, addr, dma_index;
+       struct tx_descriptor_t *tx_desc;
+       struct rx_descriptor_t *rx_desc;
+       struct nand_drv *info =
+           (struct nand_drv *)nand_get_controller_data(chip);
+       int ret;
+
+       /* reset ecc control */
+       clrsetbits_le32(&info->reg->flash_nf_ecc_reset, GENMASK(31, 0),
+                       RESET_NFLASH_ECC);
+
+       /*  flash interrupt */
+       clrsetbits_le32(&info->reg->flash_flash_interrupt, GENMASK(0, 0),
+                       REGIRQ_CLEAR);
+
+       /* reset ecc control */
+       clrsetbits_le32(&info->reg->flash_nf_ecc_reset, GENMASK(31, 0),
+                       RESET_NFLASH_ECC);
+
+       /* Disable TXQ */
+       clrbits_le32(&info->dma_nand->dma_q_txq_control, GENMASK(0, 0));
+
+       /* Clear interrupt */
+       setbits_le32(&info->dma_nand->dma_q_rxq_coal_interrupt, GENMASK(0, 0));
+       setbits_le32(&info->dma_nand->dma_q_txq_coal_interrupt, GENMASK(0, 0));
+
+       if (with_ecc == 1) {
+               switch (info->config.nand_ecc_strength) {
+               case ECC_STRENGTH_8:
+                       reg_v = BCH_ERR_CAP_8;
+                       break;
+               case ECC_STRENGTH_16:
+                       reg_v = BCH_ERR_CAP_16;
+                       break;
+               case ECC_STRENGTH_24:
+                       reg_v = BCH_ERR_CAP_24;
+                       break;
+               case ECC_STRENGTH_40:
+                       reg_v = BCH_ERR_CAP_40;
+                       break;
+               default:
+                       reg_v = BCH_ERR_CAP_16;
+                       break;
+               }
+               reg_v |= BCH_ENABLE;
+
+               /* BCH decode for flash read */
+               if (is_writing == 0)
+                       reg_v |= BCH_DECODE;
+               clrsetbits_le32(&info->reg->flash_nf_bch_control,
+                               GENMASK(31, 0), reg_v);
+       } else {
+               clrsetbits_le32(&info->reg->flash_nf_bch_control,
+                               GENMASK(31, 0), 0);
+       }
+
+       /* Fill Extend address */
+       ext_addr = ((page << chip->page_shift) / EXT_ADDR_MASK);
+
+       clrsetbits_le32(&info->reg->flash_nf_access,
+                       GENMASK(7, 0), (uintptr_t)ext_addr);
+
+       addr = (uintptr_t)((page << chip->page_shift) % EXT_ADDR_MASK);
+       addr = (uintptr_t)(addr + info->flash_base);
+
+       dma_index = readl(&info->dma_nand->dma_q_txq_wptr) & CA_DMA_Q_PTR_MASK;
+
+       tx_desc = info->tx_desc;
+       rx_desc = info->rx_desc;
+
+       /* TX/RX descriptor for page data */
+       tx_desc[dma_index].own = OWN_DMA;
+       tx_desc[dma_index].buf_len = mtd->writesize;
+       rx_desc[dma_index].own = OWN_DMA;
+       rx_desc[dma_index].buf_len = mtd->writesize;
+       if (is_writing == 0) {
+               tx_desc[dma_index].buf_adr = (uintptr_t)addr;
+               rx_desc[dma_index].buf_adr = (uintptr_t)(buf);
+       } else {
+               tx_desc[dma_index].buf_adr = (uintptr_t)buf;
+               rx_desc[dma_index].buf_adr = (uintptr_t)(addr);
+       }
+
+       dma_index++;
+       dma_index %= CA_DMA_DESC_NUM;
+
+       /* TX/RX descriptor for OOB area */
+       addr = (uintptr_t)(addr + mtd->writesize);
+       tx_desc[dma_index].own = OWN_DMA;
+       tx_desc[dma_index].buf_len = mtd->oobsize;
+       rx_desc[dma_index].own = OWN_DMA;
+       rx_desc[dma_index].buf_len = mtd->oobsize;
+       if (is_writing) {
+               tx_desc[dma_index].buf_adr = (uintptr_t)(chip->oob_poi);
+               rx_desc[dma_index].buf_adr = (uintptr_t)addr;
+       } else {
+               tx_desc[dma_index].buf_adr = (uintptr_t)addr;
+               rx_desc[dma_index].buf_adr = (uintptr_t)(chip->oob_poi);
+               dma_index++;
+               dma_index %= CA_DMA_DESC_NUM;
+       }
+
+       if (is_writing == 1) {
+               clrsetbits_le32(&info->reg->flash_fifo_control, GENMASK(1, 0),
+                               FIFO_WRITE);
+       } else {
+               clrsetbits_le32(&info->reg->flash_fifo_control, GENMASK(1, 0),
+                               FIFO_READ);
+       }
+
+       /* Start FIFO request */
+       clrsetbits_le32(&info->reg->flash_flash_access_start, GENMASK(2, 2),
+                       NFLASH_FIFO_REQ);
+
+       /* Update DMA write pointer */
+       clrsetbits_le32(&info->dma_nand->dma_q_txq_wptr, GENMASK(12, 0),
+                       dma_index);
+
+       /* Start DMA */
+       clrsetbits_le32(&info->dma_nand->dma_q_txq_control, GENMASK(0, 0),
+                       TX_DMA_ENABLE);
+
+       /* Wait TX DMA done */
+       ret =
+           readl_poll_timeout(&info->dma_nand->dma_q_txq_coal_interrupt,
+                              reg_v, (reg_v & 1), FLASH_LONG_DELAY);
+       if (ret) {
+               pr_err("TX DMA timeout\n");
+               return -ETIMEDOUT;
+       }
+       /* clear tx interrupt */
+       setbits_le32(&info->dma_nand->dma_q_txq_coal_interrupt, 1);
+
+       /* Wait RX DMA done */
+       ret =
+           readl_poll_timeout(&info->dma_nand->dma_q_rxq_coal_interrupt, reg_v,
+                              (reg_v & 1), FLASH_LONG_DELAY);
+       if (ret) {
+               pr_err("RX DMA timeout\n");
+               return -ETIMEDOUT;
+       }
+       /* clear rx interrupt */
+       setbits_le32(&info->dma_nand->dma_q_rxq_coal_interrupt, 1);
+
+       /* wait NAND CMD done */
+       if (is_writing == 0) {
+               if (!nand_waitfor_cmd_completion(info->reg, NFLASH_FIFO_REQ))
+                       printf("%s: Command timeout\n", __func__);
+       }
+
+       /* Update DMA read pointer */
+       clrsetbits_le32(&info->dma_nand->dma_q_rxq_rptr, GENMASK(12, 0),
+                       dma_index);
+
+       /* ECC correction */
+       if (with_ecc == 1) {
+               ret =
+                   readl_poll_timeout(&info->reg->flash_nf_bch_status,
+                                      reg_v, (reg_v & BCH_GEN_DONE),
+                                      FLASH_LONG_DELAY);
+
+               if (ret) {
+                       pr_err("BCH_GEN timeout! flash_nf_bch_status=[0x%x]\n",
+                              reg_v);
+                       return -ETIMEDOUT;
+               }
+
+               if (is_writing == 0)
+                       ca_do_bch_decode(mtd, chip, buf, page, addr);
+               else
+                       ca_do_bch_encode(mtd, chip, page);
+       }
+
+       if (is_writing) {
+               dma_index++;
+               dma_index %= CA_DMA_DESC_NUM;
+
+               /* Update DMA R/W pointer */
+               clrsetbits_le32(&info->dma_nand->dma_q_txq_wptr, GENMASK(12, 0),
+                               dma_index);
+
+               /* Wait TX DMA done */
+               ret =
+                  readl_poll_timeout(&info->dma_nand->dma_q_txq_coal_interrupt,
+                                     reg_v, (reg_v & 1), FLASH_LONG_DELAY);
+               if (ret) {
+                       pr_err("TX DMA timeout\n");
+                       return -ETIMEDOUT;
+               }
+               /* clear tx interrupt */
+               setbits_le32(&info->dma_nand->dma_q_txq_coal_interrupt, 1);
+
+               /* Wait RX DMA done */
+               ret =
+                  readl_poll_timeout(&info->dma_nand->dma_q_rxq_coal_interrupt,
+                                     reg_v, (reg_v & 1), FLASH_LONG_DELAY);
+               if (ret) {
+                       pr_err("RX DMA timeout\n");
+                       return -ETIMEDOUT;
+               }
+               /* clear rx interrupt */
+               setbits_le32(&info->dma_nand->dma_q_rxq_coal_interrupt, 1);
+
+               /* wait NAND CMD done */
+               if (!nand_waitfor_cmd_completion(info->reg, NFLASH_FIFO_REQ))
+                       printf("%s: Command timeout\n", __func__);
+
+               /* Update DMA R/W pointer */
+               clrsetbits_le32(&info->dma_nand->dma_q_rxq_rptr, GENMASK(12, 0),
+                               dma_index);
+       }
+
+       return 0;
+}
+
+/**
+ * Hardware ecc based page read function
+ *
+ * @param mtd  mtd info structure
+ * @param chip nand chip info structure
+ * @param buf  buffer to store read data
+ * @param page page number to read
+ * @return     0 when successfully completed
+ *             -ETIMEDOUT when command timeout
+ */
+static int nand_read_page_hwecc(struct mtd_info *mtd,
+                               struct nand_chip *chip, uint8_t *buf,
+                               int oob_required, int page)
+{
+       struct nand_drv *info =
+           (struct nand_drv *)nand_get_controller_data(chip);
+       int ret;
+
+       ret = nand_rw_page(mtd, chip, buf, page, 1, 0);
+       if (ret)
+               return ret;
+
+       /* Reset FIFO */
+       clrsetbits_le32(&info->reg->flash_nf_ecc_reset, GENMASK(31, 0),
+                       ECC_RESET_ALL);
+
+       return 0;
+}
+
+/**
+ * Hardware ecc based page write function
+ *
+ * @param mtd  mtd info structure
+ * @param chip nand chip info structure
+ * @param buf  data buffer
+ * @return     0 when successfully completed
+ *             -ETIMEDOUT when command timeout
+ */
+static int nand_write_page_hwecc(struct mtd_info *mtd,
+                                struct nand_chip *chip, const uint8_t *buf,
+                                int oob_required, int page)
+{
+       struct nand_drv *info =
+           (struct nand_drv *)nand_get_controller_data(chip);
+       int ret;
+
+       ret = nand_rw_page(mtd, chip, (uint8_t *)buf, page, 1, 1);
+       if (ret)
+               return ret;
+
+       /* Reset FIFO */
+       clrsetbits_le32(&info->reg->flash_nf_ecc_reset, GENMASK(31, 0),
+                       ECC_RESET_ALL);
+
+       return 0;
+}
+
+/**
+ * Read raw page data without ecc
+ *
+ * @param mtd  mtd info structure
+ * @param chip nand chip info structure
+ * @param buf  buffer to store read data
+ * @param page page number to read
+ * @return     0 when successfully completed
+ *             -ETIMEDOUT when command timeout
+ */
+static int nand_read_page_raw(struct mtd_info *mtd,
+                             struct nand_chip *chip, uint8_t *buf,
+                             int oob_required, int page)
+{
+       struct nand_drv *info =
+           (struct nand_drv *)nand_get_controller_data(chip);
+       int ret;
+
+       ret = nand_rw_page(mtd, chip, buf, page, 0, 0);
+       if (ret)
+               return ret;
+
+       /* Reset FIFO */
+       clrsetbits_le32(&info->reg->flash_nf_ecc_reset, GENMASK(31, 0),
+                       ECC_RESET_ALL);
+
+       return 0;
+}
+
+/**
+ * Raw page write function
+ *
+ * @param mtd  mtd info structure
+ * @param chip nand chip info structure
+ * @param buf  data buffer
+ * @return     0 when successfully completed
+ *             -ETIMEDOUT when command timeout
+ */
+static int nand_write_page_raw(struct mtd_info *mtd,
+                              struct nand_chip *chip, const uint8_t *buf,
+                              int oob_required, int page)
+{
+       struct nand_drv *info =
+           (struct nand_drv *)nand_get_controller_data(chip);
+       int ret;
+
+       ret = nand_rw_page(mtd, chip, buf, page, 0, 1);
+       if (ret)
+               return ret;
+
+       /* Reset FIFO */
+       clrsetbits_le32(&info->reg->flash_nf_ecc_reset, GENMASK(31, 0),
+                       ECC_RESET_ALL);
+
+       return 0;
+}
+
+/**
+ * OOB data read/write function
+ *
+ * @param mtd          mtd info structure
+ * @param chip         nand chip info structure
+ * @param page         page number to read
+ * @param with_ecc     1 to enable ECC, 0 to disable ECC
+ * @param is_writing   0 for read, 1 for write
+ * @return             0 when successfully completed
+ *                     -ETIMEDOUT when command timeout
+ */
+static int nand_rw_oob(struct mtd_info *mtd, struct nand_chip *chip,
+                      int page, int with_ecc, int is_writing)
+{
+       struct nand_drv *info =
+           (struct nand_drv *)nand_get_controller_data(chip);
+       u32 reg_val;
+       int rw_index;
+
+       if (is_writing) {
+               reg_val = NFLASH_GO | NFLASH_WT;
+               pwrite = (unsigned int *)chip->oob_poi;
+       } else {
+               reg_val = NFLASH_GO | NFLASH_RD;
+               pread = (unsigned int *)chip->oob_poi;
+       }
+
+       for (rw_index = 0; rw_index < mtd->oobsize / 4; rw_index++) {
+               clrsetbits_le32(&info->reg->flash_nf_access, GENMASK(31, 0),
+                               NFLASH_REG_WIDTH_32);
+               if (is_writing)
+                       clrsetbits_le32(&info->reg->flash_nf_data,
+                                       GENMASK(31, 0), pwrite[rw_index]);
+
+               clrsetbits_le32(&info->reg->flash_flash_access_start,
+                               GENMASK(11, 10), reg_val);
+
+               if (!nand_waitfor_cmd_completion(info->reg, NFLASH_GO))
+                       printf("%s: Command timeout\n", __func__);
+
+               if (!is_writing)
+                       pread[rw_index] = readl(&info->reg->flash_nf_data);
+       }
+       return 0;
+}
+
+/**
+ * OOB data read function
+ *
+ * @param mtd          mtd info structure
+ * @param chip         nand chip info structure
+ * @param page         page number to read
+ */
+static int nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip, int page)
+{
+       struct nand_drv *info =
+           (struct nand_drv *)nand_get_controller_data(chip);
+       int ret;
+
+       chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
+       if (mtd->writesize <= (REG_DATA_COUNT_512_DATA >> 8))
+               clrsetbits_le32(&info->reg->flash_nf_command, GENMASK(7, 0),
+                               NAND_CMD_READOOB);
+       ret = nand_rw_oob(mtd, chip, page, 0, 0);
+
+       /* Reset FIFO */
+       clrsetbits_le32(&info->reg->flash_nf_ecc_reset,
+                       GENMASK(31, 0), ECC_RESET_ALL);
+
+       return ret;
+}
+
+/**
+ * OOB data write function
+ *
+ * @param mtd  mtd info structure
+ * @param chip nand chip info structure
+ * @param page page number to write
+ * @return     0 when successfully completed
+ *             -ETIMEDOUT when command timeout
+ */
+static int nand_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
+                         int page)
+{
+       struct nand_drv *info =
+           (struct nand_drv *)nand_get_controller_data(chip);
+       int ret;
+
+       chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page);
+       if (mtd->writesize <= (REG_DATA_COUNT_512_DATA >> 8)) {
+               clrsetbits_le32(&info->reg->flash_nf_command, GENMASK(31, 0),
+                               NAND_CMD_READOOB | (NAND_CMD_SEQIN << 8) |
+                               (NAND_CMD_PAGEPROG << 16));
+               clrsetbits_le32(&info->reg->flash_nf_count, GENMASK(1, 0),
+                               REG_CMD_COUNT_3TOGO);
+       }
+       ret = nand_rw_oob(mtd, chip, page, 1, 1);
+
+       /* Reset FIFO */
+       clrsetbits_le32(&info->reg->flash_nf_ecc_reset,
+                       GENMASK(31, 0), ECC_RESET_ALL);
+
+       return ret;
+}
+
+/**
+ * Decode NAND parameters from the device tree
+ *
+ * @param dev          Driver model device
+ * @param config       Device tree NAND configuration
+ */
+static int fdt_decode_nand(struct udevice *dev, struct nand_drv *info)
+{
+       int ecc_strength;
+
+       info->reg = (struct nand_ctlr *)dev_read_addr(dev);
+       info->dma_glb = (struct dma_global *)dev_read_addr_index(dev, 1);
+       info->dma_nand = (struct dma_ssp *)dev_read_addr_index(dev, 2);
+       info->config.enabled = dev_read_enabled(dev);
+       ecc_strength = dev_read_u32_default(dev, "nand-ecc-strength", 16);
+       info->flash_base =
+           dev_read_u32_default(dev, "nand_flash_base_addr", NAND_BASE_ADDR);
+
+       switch (ecc_strength) {
+       case ECC_STRENGTH_8:
+               info->config.nand_ecc_strength = ECC_STRENGTH_8;
+               break;
+       case ECC_STRENGTH_16:
+               info->config.nand_ecc_strength = ECC_STRENGTH_16;
+               break;
+       case ECC_STRENGTH_24:
+               info->config.nand_ecc_strength = ECC_STRENGTH_24;
+               break;
+       case ECC_STRENGTH_40:
+               info->config.nand_ecc_strength = ECC_STRENGTH_40;
+               break;
+       default:
+               info->config.nand_ecc_strength = ECC_STRENGTH_16;
+       }
+
+       return 0;
+}
+
+/**
+ * config flash type
+ *
+ * @param chip nand chip info structure
+ */
+static void nand_config_flash_type(struct nand_chip *nand)
+{
+       struct nand_drv *info =
+           (struct nand_drv *)nand_get_controller_data(nand);
+       struct mtd_info *mtd = nand_to_mtd(nand);
+
+       switch (mtd->writesize) {
+       case WRITE_SIZE_512:
+               clrsetbits_le32(&info->reg->flash_type, GENMASK(31, 0),
+                               FLASH_PIN | FLASH_TYPE_512);
+               break;
+       case WRITE_SIZE_2048:
+               clrsetbits_le32(&info->reg->flash_type, GENMASK(31, 0),
+                               FLASH_PIN | FLASH_TYPE_2K);
+               break;
+       case WRITE_SIZE_4096:
+               clrsetbits_le32(&info->reg->flash_type, GENMASK(31, 0),
+                               FLASH_PIN | FLASH_TYPE_4K);
+               break;
+       case WRITE_SIZE_8192:
+               clrsetbits_le32(&info->reg->flash_type, GENMASK(31, 0),
+                               FLASH_PIN | FLASH_TYPE_8K);
+               break;
+       default:
+               pr_err("Unsupported page size(0x%x)!", nand->ecc.size);
+       }
+}
+
+/**
+ * config oob layout
+ *
+ * @param chip  nand chip info structure
+ * @return     0 when successfully completed
+ *             -EINVAL when ECC bytes exceed OOB size
+ */
+static int nand_config_oob_layout(struct nand_chip *nand)
+{
+       int i, ecc_start_offset;
+       struct mtd_info *mtd = nand_to_mtd(nand);
+
+       /* Calculate byte count for ECC */
+       eccoob.eccbytes = mtd->writesize / nand->ecc.size * nand->ecc.bytes;
+
+       if (mtd->oobsize < eccoob.eccbytes) {
+               pr_err("Spare area(%d) too small for BCH%d\n", nand->ecc.bytes,
+                      nand->ecc.strength / 8);
+               pr_err("page_sz: %d\n", nand->ecc.size);
+               pr_err("oob_sz: %d\n", nand->ecc.bytes);
+               return -EINVAL;
+       }
+
+       /* Update OOB layout */
+       ecc_start_offset = mtd->oobsize - eccoob.eccbytes;
+       memset(eccoob.eccpos, 0, sizeof(eccoob.eccpos));
+       for (i = 0; i < eccoob.eccbytes; ++i)
+               eccoob.eccpos[i] = i + ecc_start_offset;
+
+       /* Unused spare area
+        * OOB[0] is bad block marker.
+        * Extra two byte is reserved as
+        * erase marker just right before ECC code.
+        */
+       eccoob.oobavail = nand->ecc.bytes - eccoob.eccbytes - 2;
+       eccoob.oobfree[0].offset = 2;
+       eccoob.oobfree[0].length =
+           mtd->oobsize - eccoob.eccbytes - eccoob.oobfree[0].offset - 1;
+
+       return 0;
+}
+
+static int ca_nand_probe(struct udevice *dev)
+{
+       struct ca_nand_info *ca_nand = dev_get_priv(dev);
+       struct nand_chip *nand = &ca_nand->nand_chip;
+       struct nand_drv *info = &ca_nand->nand_ctrl;
+       struct fdt_nand *config = &info->config;
+       struct mtd_info *our_mtd;
+       int ret;
+
+       if (fdt_decode_nand(dev, info)) {
+               printf("Could not decode nand-flash in device tree\n");
+               return -1;
+       }
+       if (!config->enabled)
+               return -1;
+
+       nand->ecc.mode = NAND_ECC_HW;
+       nand->ecc.layout = &eccoob;
+
+       nand->cmdfunc = ca_nand_command;
+       nand->read_byte = read_byte;
+       nand->read_buf = read_buf;
+       nand->ecc.read_page = nand_read_page_hwecc;
+       nand->ecc.write_page = nand_write_page_hwecc;
+       nand->ecc.read_page_raw = nand_read_page_raw;
+       nand->ecc.write_page_raw = nand_write_page_raw;
+       nand->ecc.read_oob = nand_read_oob;
+       nand->ecc.write_oob = nand_write_oob;
+       nand->ecc.strength = config->nand_ecc_strength;
+       nand->select_chip = nand_select_chip;
+       nand->dev_ready = nand_dev_ready;
+       nand_set_controller_data(nand, &ca_nand->nand_ctrl);
+
+       /* Disable subpage writes as we do not provide ecc->hwctl */
+       nand->options |= NAND_NO_SUBPAGE_WRITE | NAND_SKIP_BBTSCAN;
+
+       /* Configure flash type as P-NAND */
+       clrsetbits_le32(&info->reg->flash_type, FLASH_PIN,
+                       FLASH_TYPE_4K | FLASH_SIZE_436OOB);
+       config->width = FLASH_WIDTH;
+
+       our_mtd = nand_to_mtd(nand);
+       ret = nand_scan_ident(our_mtd, CONFIG_SYS_NAND_MAX_CHIPS, NULL);
+       if (ret)
+               return ret;
+
+       nand->ecc.size = BCH_DATA_UNIT;
+       nand->ecc.bytes = BCH_GF_PARAM_M * (nand->ecc.strength / 8);
+
+       /* Reconfig flash type according to ONFI */
+       nand_config_flash_type(nand);
+
+       ret = set_bus_width_page_size(our_mtd);
+       if (ret)
+               return ret;
+
+       /* Set the bad block position */
+       nand->badblockpos =
+           our_mtd->writesize >
+           512 ? NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS;
+
+       /* Arrange OOB layout */
+       ret = nand_config_oob_layout(nand);
+       if (ret)
+               return ret;
+
+       /* Init DMA descriptor ring */
+       ret = init_nand_dma(nand);
+       if (ret)
+               return ret;
+
+       ret = nand_scan_tail(our_mtd);
+       if (ret)
+               return ret;
+
+       ret = nand_register(0, our_mtd);
+       if (ret) {
+               dev_err(dev, "Failed to register MTD: %d\n", ret);
+               return ret;
+       }
+
+       ret = set_bus_width_page_size(our_mtd);
+       if (ret)
+               return ret;
+
+       printf("P-NAND    : %s\n", our_mtd->name);
+       printf("Chip  Size: %lldMB\n", nand->chipsize / (1024 * 1024));
+       printf("Block Size: %dKB\n", our_mtd->erasesize / 1024);
+       printf("Page  Size: %dB\n", our_mtd->writesize);
+       printf("OOB   Size: %dB\n", our_mtd->oobsize);
+
+       return 0;
+}
+
+U_BOOT_DRIVER(cortina_nand) = {
+       .name = "CA-PNAND",
+       .id = UCLASS_MTD,
+       .of_match = cortina_nand_dt_ids,
+       .probe = ca_nand_probe,
+       .priv_auto = sizeof(struct ca_nand_info),
+};
+
+void board_nand_init(void)
+{
+       struct udevice *dev;
+       int ret;
+
+       ret = uclass_get_device_by_driver(UCLASS_MTD,
+                                         DM_DRIVER_GET(cortina_nand), &dev);
+       if (ret && ret != -ENODEV)
+               pr_err("Failed to initialize %s. (error %d)\n", dev->name, ret);
+}
diff --git a/drivers/mtd/nand/raw/cortina_nand.h b/drivers/mtd/nand/raw/cortina_nand.h
new file mode 100644 (file)
index 0000000..1e3e3bf
--- /dev/null
@@ -0,0 +1,293 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2020 Cortina Access Inc..
+ */
+
+/* Cortina NAND definition */
+#define NAND_BASE_ADDR         0xE0000000
+#define BCH_GF_PARAM_M         14
+#define BCH_DATA_UNIT          1024
+#define FLASH_SHORT_DELAY      100
+#define FLASH_LONG_DELAY       1000
+#define FLASH_WIDTH            16
+#define BBT_PAGE_MASK          0xffffff3f
+#define WRITE_SIZE_512         512
+#define WRITE_SIZE_2048                2048
+#define WRITE_SIZE_4096                4096
+#define WRITE_SIZE_8192                8192
+#define ECC_STRENGTH_8         8
+#define ECC_STRENGTH_16                16
+#define ECC_STRENGTH_24                24
+#define ECC_STRENGTH_40                40
+#define EMPTY_PAGE             0xff
+#define ADDR1_MASK0            0x00ffffff
+#define ADDR2_MASK0            0xff000000
+#define ADDR1_MASK1            0xffff
+#define ADDR1_MASK2            0xff
+#define OOB_MASK               0xff
+#define EXT_ADDR_MASK          0x8000000
+
+/* Status bits */
+#define NAND_STATUS_FAIL       0x01
+#define NAND_STATUS_FAIL_N1    0x02
+#define NAND_STATUS_TRUE_READY 0x20
+#define NAND_STATUS_READY      0x40
+#define NAND_STATUS_WP         0x80
+
+/* Bit field in FLAS_TYPE */
+#define FLASH_PIN                      BIT(15)
+#define FLASH_TYPE_512                 0x4000
+#define FLASH_TYPE_2K                  0x5000
+#define FLASH_TYPE_4K                  0x6000
+#define FLASH_TYPE_8K                  0x7000
+#define FLASH_SIZE_CONFIGURABLEOOB     (0x0 << 9)
+#define FLASH_SIZE_400OOB              (0x1 << 9)
+#define FLASH_SIZE_436OOB              (0x2 << 9)
+#define FLASH_SIZE_640OOB              (0x3 << 9)
+
+/* Bit field in FLASH_STATUS */
+#define NFLASH_READY   BIT(26)
+
+/* Bit field in FLASH_NF_ACCESS */
+#define NFLASH_ENABLE_ALTERNATIVE      (0x0 << 15)
+#define AUTO_RESET                     BIT(16)
+#define DISABLE_AUTO_RESET             (0x0 << 16)
+#define NFLASH_REG_WIDTH_RESERVED      (0x3 << 10)
+#define NFLASH_REG_WIDTH_32            (0x2 << 10)
+#define NFLASH_REG_WIDTH_16            (0x1 << 10)
+#define NFLASH_REG_WIDTH_8             (0x0 << 10)
+
+/* Bit field in FLASH_NF_COUNT */
+#define REG_CMD_COUNT_EMPTY            0x3
+#define REG_CMD_COUNT_3TOGO            0x2
+#define REG_CMD_COUNT_2TOGO            0x1
+#define REG_CMD_COUNT_1TOGO            0x0
+#define REG_ADDR_COUNT_EMPTY           (0x7 << 4)
+#define REG_ADDR_COUNT_5               (0x4 << 4)
+#define REG_ADDR_COUNT_4               (0x3 << 4)
+#define REG_ADDR_COUNT_3               (0x2 << 4)
+#define REG_ADDR_COUNT_2               (0x1 << 4)
+#define REG_ADDR_COUNT_1               (0x0 << 4)
+#define REG_DATA_COUNT_EMPTY           (0x3fff << 8)
+#define REG_DATA_COUNT_512_DATA                (0x1FF << 8)
+#define REG_DATA_COUNT_2k_DATA         (0x7FF << 8)
+#define REG_DATA_COUNT_4k_DATA         (0xFFF << 8)
+#define REG_DATA_COUNT_DATA_1          (0x0 << 8)
+#define REG_DATA_COUNT_DATA_2          (0x1 << 8)
+#define REG_DATA_COUNT_DATA_3          (0x2 << 8)
+#define REG_DATA_COUNT_DATA_4          (0x3 << 8)
+#define REG_DATA_COUNT_DATA_5          (0x4 << 8)
+#define REG_DATA_COUNT_DATA_6          (0x5 << 8)
+#define REG_DATA_COUNT_DATA_7          (0x6 << 8)
+#define REG_DATA_COUNT_DATA_8          (0x7 << 8)
+#define REG_OOB_COUNT_EMPTY            (0x3ff << 22)
+
+/* Bit field in FLASH_FLASH_ACCESS_START */
+#define NFLASH_GO              BIT(0)
+#define NFLASH_FIFO_REQ                BIT(2)
+#define NFLASH_RD              BIT(13)
+#define NFLASH_WT              (BIT(12) | BIT(13))
+
+/* Bit field in FLASH_NF_ECC_RESET */
+#define RESET_NFLASH_RESET     BIT(2)
+#define RESET_NFLASH_FIFO      BIT(1)
+#define RESET_NFLASH_ECC       BIT(0)
+#define ECC_RESET_ALL \
+       RESET_NFLASH_RESET | RESET_NFLASH_FIFO | RESET_NFLASH_ECC
+
+/* Bit field in FLASH_NF_ECC_CONTROL */
+#define ENABLE_ECC_GENERATION  BIT(8)
+#define DISABLE_ECC_GENERATION (0 << 8)
+
+/* Flash FIFO control */
+#define FIFO_READ              2
+#define FIFO_WRITE             3
+
+/* NFLASH INTERRUPT */
+#define REGIRQ_CLEAR           BIT(0)
+#define F_ADDR_ERR             2
+
+/* BCH ECC field definition */
+#define BCH_COMPARE            BIT(0)
+#define        BCH_ENABLE              BIT(8)
+#define        BCH_DISABLE             (0 << 8)
+#define        BCH_DECODE              BIT(1)
+#define        BCH_ENCODE              (0 << 1)
+#define BCH_DECO_DONE          BIT(30)
+#define BCH_GEN_DONE           BIT(31)
+#define        BCH_UNCORRECTABLE       0x3
+#define        BCH_CORRECTABLE_ERR     0x2
+#define        BCH_NO_ERR              0x1
+#define        BCH_BUSY                0x0
+#define BCH_ERR_MASK           0x3
+#define BCH_ERR_NUM_MASK       0x3F
+#define BCH_ERR_LOC_MASK       0x3FFF
+#define BCH_CORRECT_LOC_MASK   0x7
+#define BCH_ERR_CAP_8          (0x0 << 9)
+#define BCH_ERR_CAP_16         (0x1 << 9)
+#define BCH_ERR_CAP_24         (0x2 << 9)
+#define BCH_ERR_CAP_40         (0x3 << 9)
+
+#define BCH_GF_PARAM_M         14
+
+struct nand_ctlr {
+       /* Cortina NAND controller register */
+       u32 flash_id;
+       u32 flash_timeout;
+       u32 flash_status;
+       u32 flash_type;
+       u32 flash_flash_access_start;
+       u32 flash_flash_interrupt;
+       u32 flash_flash_mask;
+       u32 flash_fifo_control;
+       u32 flash_fifo_status;
+       u32 flash_fifo_address;
+       u32 flash_fifo_match_address;
+       u32 flash_fifo_data;
+       u32 flash_sf_access;
+       u32 flash_sf_ext_access;
+       u32 flash_sf_address;
+       u32 flash_sf_data;
+       u32 flash_sf_timing;
+       u32 resv[3];
+       u32 flash_pf_access;            // offset 0x050
+       u32 flash_pf_timing;
+       u32 resv1[2];
+       u32 flash_nf_access;            // offset 0x060
+       u32 flash_nf_count;
+       u32 flash_nf_command;
+       u32 flash_nf_address_1;
+       u32 flash_nf_address_2;
+       u32 flash_nf_data;
+       u32 flash_nf_timing;
+       u32 flash_nf_ecc_status;
+       u32 flash_nf_ecc_control;
+       u32 flash_nf_ecc_oob;
+       u32 flash_nf_ecc_gen0;
+       u32 resv3[15];
+       u32 flash_nf_ecc_reset;         // offset 0x0c8
+       u32 flash_nf_bch_control;
+       u32 flash_nf_bch_status;
+       u32 flash_nf_bch_error_loc01;
+       u32 resv4[19];
+       u32 flash_nf_bch_oob0;          // offset 0x124
+       u32 resv5[17];
+       u32 flash_nf_bch_gen0_0;        // offset 0x16c
+};
+
+/* Definition for DMA bitfield */
+#define TX_DMA_ENABLE  BIT(0)
+#define RX_DMA_ENABLE  BIT(0)
+#define DMA_CHECK_OWNER        BIT(1)
+#define OWN_DMA                        0
+#define OWN_CPU                        1
+
+#define CA_DMA_DEPTH   3
+#define CA_DMA_DESC_NUM        (BIT(0) << CA_DMA_DEPTH)
+#define CA_DMA_Q_PTR_MASK      0x1fff
+
+struct dma_q_base_depth_t {
+       u32 depth               :  4 ; /* bits 3:0 */
+       u32 base                : 28 ; /* bits 31:4 */
+};
+
+struct tx_descriptor_t {
+       unsigned int buf_adr; /* Buff addr */
+       unsigned int buf_adr_hi :  8 ; /* bits 7:0 */
+       unsigned int buf_len    :  16 ;  /* bits 23:8 */
+       unsigned int sgm        :  1 ;  /* bits 24 */
+       unsigned int rsrvd      :  6 ;  /* bits 30:25 */
+       unsigned int own        :  1 ;  /* bits 31:31 */
+};
+
+struct rx_descriptor_t {
+       unsigned int buf_adr; /* Buff addr */
+       unsigned int buf_adr_hi :  8 ; /* bits 7:0 */
+       unsigned int buf_len    : 16 ;  /* bits 23:8 */
+       unsigned int rsrvd      :  7 ;  /* bits 30:24 */
+       unsigned int own        :  1 ;  /* bits 31:31 */
+};
+
+struct dma_global {
+       u32 dma_glb_dma_lso_ctrl;
+       u32 dma_glb_lso_interrupt;
+       u32 dma_glb_lso_intenable;
+       u32 dma_glb_dma_lso_vlan_tag_type0;
+       u32 dma_glb_dma_lso_vlan_tag_type1;
+       u32 dma_glb_dma_lso_axi_user_sel0;
+       u32 dma_glb_axi_user_pat0;
+       u32 dma_glb_axi_user_pat1;
+       u32 dma_glb_axi_user_pat2;
+       u32 dma_glb_axi_user_pat3;
+       u32 dma_glb_fast_reg_pe0;
+       u32 dma_glb_fast_reg_pe1;
+       u32 dma_glb_dma_lso_tx_fdes_addr0;
+       u32 dma_glb_dma_lso_tx_fdes_addr1;
+       u32 dma_glb_dma_lso_tx_cdes_addr0;
+       u32 dma_glb_dma_lso_tx_cdes_addr1;
+       u32 dma_glb_dma_lso_tx_des_word0;
+       u32 dma_glb_dma_lso_tx_des_word1;
+       u32 dma_glb_dma_lso_lso_para_word0;
+       u32 dma_glb_dma_lso_lso_para_word1;
+       u32 dma_glb_dma_lso_debug0;
+       u32 dma_glb_dma_lso_debug1;
+       u32 dma_glb_dma_lso_debug2;
+       u32 dma_glb_dma_lso_spare0;
+       u32 dma_glb_dma_lso_spare1;
+       u32 dma_glb_dma_ssp_rx_ctrl;
+       u32 dma_glb_dma_ssp_tx_ctrl;
+       u32 dma_glb_dma_ssp_axi_user_sel0;
+       u32 dma_glb_dma_ssp_axi_user_sel1;
+       u32 dma_glb_dma_ssp_rx_fdes_addr0;
+       u32 dma_glb_dma_ssp_rx_fdes_addr1;
+       u32 dma_glb_dma_ssp_rx_cdes_addr0;
+       u32 dma_glb_dma_ssp_rx_cdes_addr1;
+       u32 dma_glb_dma_ssp_rx_des_word0;
+       u32 dma_glb_dma_ssp_rx_des_word1;
+       u32 dma_glb_dma_ssp_tx_fdes_addr0;
+       u32 dma_glb_dma_ssp_tx_fdes_addr1;
+       u32 dma_glb_dma_ssp_tx_cdes_addr0;
+       u32 dma_glb_dma_ssp_tx_cdes_addr1;
+       u32 dma_glb_dma_ssp_tx_des_word0;
+       u32 dma_glb_dma_ssp_tx_des_word1;
+       u32 dma_glb_dma_ssp_debug0;
+       u32 dma_glb_dma_ssp_debug1;
+       u32 dma_glb_dma_ssp_debug2;
+       u32 dma_glb_dma_ssp_spare0;
+       u32 dma_glb_dma_ssp_spare1;
+};
+
+struct dma_ssp {
+       u32 dma_q_rxq_control;
+       u32 dma_q_rxq_base_depth;
+       u32 dma_q_rxq_base;
+       u32 dma_q_rxq_wptr;
+       u32 dma_q_rxq_rptr;
+       u32 dma_q_rxq_pktcnt;
+       u32 dma_q_txq_control;
+       u32 dma_q_txq_base_depth;
+       u32 dma_q_txq_base;
+       u32 dma_q_txq_wptr;
+       u32 dma_q_txq_rptr;
+       u32 dma_q_txq_pktcnt;
+       u32 dma_q_rxq_interrupt;
+       u32 dma_q_rxq_intenable;
+       u32 dma_q_txq_interrupt;
+       u32 dma_q_txq_intenable;
+       u32 dma_q_rxq_misc_interrupt;
+       u32 dma_q_rxq_misc_intenable;
+       u32 dma_q_txq_misc_interrupt;
+       u32 dma_q_txq_misc_intenable;
+       u32 dma_q_rxq_coal_interrupt;
+       u32 dma_q_rxq_coal_intenable;
+       u32 dma_q_txq_coal_interrupt;
+       u32 dma_q_txq_coal_intenable;
+       u32 dma_q_rxq_frag_buff_addr0;
+       u32 dma_q_rxq_frag_buff_addr1;
+       u32 dma_q_rxq_frag_buff_size;
+       u32 dma_q_txq_frag_buff_addr0;
+       u32 dma_q_txq_frag_buff_addr1;
+       u32 dma_q_txq_frag_buff_size;
+       u32 dma_q_dma_spare_0;
+       u32 dma_q_dma_spare_1;
+};
index 45a1648..9444129 100644 (file)
@@ -209,6 +209,7 @@ struct eqos_dma_regs {
 #define EQOS_DMA_SYSBUS_MODE_BLEN8                     BIT(2)
 #define EQOS_DMA_SYSBUS_MODE_BLEN4                     BIT(1)
 
+#define EQOS_DMA_CH0_CONTROL_DSL_SHIFT                 18
 #define EQOS_DMA_CH0_CONTROL_PBLX8                     BIT(16)
 
 #define EQOS_DMA_CH0_TX_CONTROL_TXPBL_SHIFT            16
@@ -239,37 +240,15 @@ struct eqos_tegra186_regs {
 #define EQOS_AUTO_CAL_STATUS_ACTIVE                    BIT(31)
 
 /* Descriptors */
-
-#define EQOS_DESCRIPTOR_WORDS  4
-#define EQOS_DESCRIPTOR_SIZE   (EQOS_DESCRIPTOR_WORDS * 4)
 /* We assume ARCH_DMA_MINALIGN >= 16; 16 is the EQOS HW minimum */
 #define EQOS_DESCRIPTOR_ALIGN  ARCH_DMA_MINALIGN
 #define EQOS_DESCRIPTORS_TX    4
 #define EQOS_DESCRIPTORS_RX    4
 #define EQOS_DESCRIPTORS_NUM   (EQOS_DESCRIPTORS_TX + EQOS_DESCRIPTORS_RX)
-#define EQOS_DESCRIPTORS_SIZE  ALIGN(EQOS_DESCRIPTORS_NUM * \
-                                     EQOS_DESCRIPTOR_SIZE, ARCH_DMA_MINALIGN)
 #define EQOS_BUFFER_ALIGN      ARCH_DMA_MINALIGN
 #define EQOS_MAX_PACKET_SIZE   ALIGN(1568, ARCH_DMA_MINALIGN)
 #define EQOS_RX_BUFFER_SIZE    (EQOS_DESCRIPTORS_RX * EQOS_MAX_PACKET_SIZE)
 
-/*
- * Warn if the cache-line size is larger than the descriptor size. In such
- * cases the driver will likely fail because the CPU needs to flush the cache
- * when requeuing RX buffers, therefore descriptors written by the hardware
- * may be discarded. Architectures with full IO coherence, such as x86, do not
- * experience this issue, and hence are excluded from this condition.
- *
- * This can be fixed by defining CONFIG_SYS_NONCACHED_MEMORY which will cause
- * the driver to allocate descriptors from a pool of non-cached memory.
- */
-#if EQOS_DESCRIPTOR_SIZE < ARCH_DMA_MINALIGN
-#if !defined(CONFIG_SYS_NONCACHED_MEMORY) && \
-       !CONFIG_IS_ENABLED(SYS_DCACHE_OFF) && !defined(CONFIG_X86)
-#warning Cache line size is larger than descriptor size
-#endif
-#endif
-
 struct eqos_desc {
        u32 des0;
        u32 des1;
@@ -282,12 +261,17 @@ struct eqos_desc {
 #define EQOS_DESC3_LD          BIT(28)
 #define EQOS_DESC3_BUF1V       BIT(24)
 
+#define EQOS_AXI_WIDTH_32      4
+#define EQOS_AXI_WIDTH_64      8
+#define EQOS_AXI_WIDTH_128     16
+
 struct eqos_config {
        bool reg_access_always_ok;
        int mdio_wait;
        int swr_wait;
        int config_mac;
        int config_mac_mdio;
+       unsigned int axi_bus_width;
        phy_interface_t (*interface)(struct udevice *dev);
        struct eqos_ops *ops;
 };
@@ -330,9 +314,8 @@ struct eqos_priv {
        int phyaddr;
        u32 max_speed;
        void *descs;
-       struct eqos_desc *tx_descs;
-       struct eqos_desc *rx_descs;
        int tx_desc_idx, rx_desc_idx;
+       unsigned int desc_size;
        void *tx_dma_buf;
        void *rx_dma_buf;
        void *rx_pkt;
@@ -358,63 +341,42 @@ struct eqos_priv {
  * not have the same constraints since they are 1536 bytes large, so they
  * are unlikely to share cache-lines.
  */
-static void *eqos_alloc_descs(unsigned int num)
+static void *eqos_alloc_descs(struct eqos_priv *eqos, unsigned int num)
 {
-#ifdef CONFIG_SYS_NONCACHED_MEMORY
-       return (void *)noncached_alloc(EQOS_DESCRIPTORS_SIZE,
-                                     EQOS_DESCRIPTOR_ALIGN);
-#else
-       return memalign(EQOS_DESCRIPTOR_ALIGN, EQOS_DESCRIPTORS_SIZE);
-#endif
+       eqos->desc_size = ALIGN(sizeof(struct eqos_desc),
+                               (unsigned int)ARCH_DMA_MINALIGN);
+
+       return memalign(eqos->desc_size, num * eqos->desc_size);
 }
 
 static void eqos_free_descs(void *descs)
 {
-#ifdef CONFIG_SYS_NONCACHED_MEMORY
-       /* FIXME: noncached_alloc() has no opposite */
-#else
        free(descs);
-#endif
 }
 
-static void eqos_inval_desc_tegra186(void *desc)
+static struct eqos_desc *eqos_get_desc(struct eqos_priv *eqos,
+                                      unsigned int num, bool rx)
 {
-#ifndef CONFIG_SYS_NONCACHED_MEMORY
-       unsigned long start = (unsigned long)desc & ~(ARCH_DMA_MINALIGN - 1);
-       unsigned long end = ALIGN(start + EQOS_DESCRIPTOR_SIZE,
-                                 ARCH_DMA_MINALIGN);
-
-       invalidate_dcache_range(start, end);
-#endif
+       return eqos->descs +
+               ((rx ? EQOS_DESCRIPTORS_TX : 0) + num) * eqos->desc_size;
 }
 
 static void eqos_inval_desc_generic(void *desc)
 {
-#ifndef CONFIG_SYS_NONCACHED_MEMORY
-       unsigned long start = rounddown((unsigned long)desc, ARCH_DMA_MINALIGN);
-       unsigned long end = roundup((unsigned long)desc + EQOS_DESCRIPTOR_SIZE,
-                                   ARCH_DMA_MINALIGN);
+       unsigned long start = (unsigned long)desc;
+       unsigned long end = ALIGN(start + sizeof(struct eqos_desc),
+                                 ARCH_DMA_MINALIGN);
 
        invalidate_dcache_range(start, end);
-#endif
-}
-
-static void eqos_flush_desc_tegra186(void *desc)
-{
-#ifndef CONFIG_SYS_NONCACHED_MEMORY
-       flush_cache((unsigned long)desc, EQOS_DESCRIPTOR_SIZE);
-#endif
 }
 
 static void eqos_flush_desc_generic(void *desc)
 {
-#ifndef CONFIG_SYS_NONCACHED_MEMORY
-       unsigned long start = rounddown((unsigned long)desc, ARCH_DMA_MINALIGN);
-       unsigned long end = roundup((unsigned long)desc + EQOS_DESCRIPTOR_SIZE,
-                                   ARCH_DMA_MINALIGN);
+       unsigned long start = (unsigned long)desc;
+       unsigned long end = ALIGN(start + sizeof(struct eqos_desc),
+                                 ARCH_DMA_MINALIGN);
 
        flush_dcache_range(start, end);
-#endif
 }
 
 static void eqos_inval_buffer_tegra186(void *buf, size_t size)
@@ -1167,6 +1129,7 @@ static int eqos_start(struct udevice *dev)
        ulong rate;
        u32 val, tx_fifo_sz, rx_fifo_sz, tqs, rqs, pbl;
        ulong last_rx_desc;
+       ulong desc_pad;
 
        debug("%s(dev=%p):\n", __func__, dev);
 
@@ -1405,8 +1368,12 @@ static int eqos_start(struct udevice *dev)
                        EQOS_MAX_PACKET_SIZE <<
                        EQOS_DMA_CH0_RX_CONTROL_RBSZ_SHIFT);
 
+       desc_pad = (eqos->desc_size - sizeof(struct eqos_desc)) /
+                  eqos->config->axi_bus_width;
+
        setbits_le32(&eqos->dma_regs->ch0_control,
-                    EQOS_DMA_CH0_CONTROL_PBLX8);
+                    EQOS_DMA_CH0_CONTROL_PBLX8 |
+                    (desc_pad << EQOS_DMA_CH0_CONTROL_DSL_SHIFT));
 
        /*
         * Burst length must be < 1/2 FIFO size.
@@ -1435,9 +1402,15 @@ static int eqos_start(struct udevice *dev)
 
        /* Set up descriptors */
 
-       memset(eqos->descs, 0, EQOS_DESCRIPTORS_SIZE);
+       memset(eqos->descs, 0, eqos->desc_size * EQOS_DESCRIPTORS_NUM);
+
+       for (i = 0; i < EQOS_DESCRIPTORS_TX; i++) {
+               struct eqos_desc *tx_desc = eqos_get_desc(eqos, i, false);
+               eqos->config->ops->eqos_flush_desc(tx_desc);
+       }
+
        for (i = 0; i < EQOS_DESCRIPTORS_RX; i++) {
-               struct eqos_desc *rx_desc = &(eqos->rx_descs[i]);
+               struct eqos_desc *rx_desc = eqos_get_desc(eqos, i, true);
                rx_desc->des0 = (u32)(ulong)(eqos->rx_dma_buf +
                                             (i * EQOS_MAX_PACKET_SIZE));
                rx_desc->des3 = EQOS_DESC3_OWN | EQOS_DESC3_BUF1V;
@@ -1449,12 +1422,14 @@ static int eqos_start(struct udevice *dev)
        }
 
        writel(0, &eqos->dma_regs->ch0_txdesc_list_haddress);
-       writel((ulong)eqos->tx_descs, &eqos->dma_regs->ch0_txdesc_list_address);
+       writel((ulong)eqos_get_desc(eqos, 0, false),
+               &eqos->dma_regs->ch0_txdesc_list_address);
        writel(EQOS_DESCRIPTORS_TX - 1,
               &eqos->dma_regs->ch0_txdesc_ring_length);
 
        writel(0, &eqos->dma_regs->ch0_rxdesc_list_haddress);
-       writel((ulong)eqos->rx_descs, &eqos->dma_regs->ch0_rxdesc_list_address);
+       writel((ulong)eqos_get_desc(eqos, 0, true),
+               &eqos->dma_regs->ch0_rxdesc_list_address);
        writel(EQOS_DESCRIPTORS_RX - 1,
               &eqos->dma_regs->ch0_rxdesc_ring_length);
 
@@ -1473,7 +1448,7 @@ static int eqos_start(struct udevice *dev)
         * that's not distinguishable from none of the descriptors being
         * available.
         */
-       last_rx_desc = (ulong)&(eqos->rx_descs[(EQOS_DESCRIPTORS_RX - 1)]);
+       last_rx_desc = (ulong)eqos_get_desc(eqos, EQOS_DESCRIPTORS_RX - 1, true);
        writel(last_rx_desc, &eqos->dma_regs->ch0_rxdesc_tail_pointer);
 
        eqos->started = true;
@@ -1558,7 +1533,7 @@ static int eqos_send(struct udevice *dev, void *packet, int length)
        memcpy(eqos->tx_dma_buf, packet, length);
        eqos->config->ops->eqos_flush_buffer(eqos->tx_dma_buf, length);
 
-       tx_desc = &(eqos->tx_descs[eqos->tx_desc_idx]);
+       tx_desc = eqos_get_desc(eqos, eqos->tx_desc_idx, false);
        eqos->tx_desc_idx++;
        eqos->tx_desc_idx %= EQOS_DESCRIPTORS_TX;
 
@@ -1573,7 +1548,7 @@ static int eqos_send(struct udevice *dev, void *packet, int length)
        tx_desc->des3 = EQOS_DESC3_OWN | EQOS_DESC3_FD | EQOS_DESC3_LD | length;
        eqos->config->ops->eqos_flush_desc(tx_desc);
 
-       writel((ulong)(&(eqos->tx_descs[eqos->tx_desc_idx])),
+       writel((ulong)eqos_get_desc(eqos, eqos->tx_desc_idx, false),
                &eqos->dma_regs->ch0_txdesc_tail_pointer);
 
        for (i = 0; i < 1000000; i++) {
@@ -1596,7 +1571,7 @@ static int eqos_recv(struct udevice *dev, int flags, uchar **packetp)
 
        debug("%s(dev=%p, flags=%x):\n", __func__, dev, flags);
 
-       rx_desc = &(eqos->rx_descs[eqos->rx_desc_idx]);
+       rx_desc = eqos_get_desc(eqos, eqos->rx_desc_idx, true);
        eqos->config->ops->eqos_inval_desc(rx_desc);
        if (rx_desc->des3 & EQOS_DESC3_OWN) {
                debug("%s: RX packet not available\n", __func__);
@@ -1631,7 +1606,7 @@ static int eqos_free_pkt(struct udevice *dev, uchar *packet, int length)
 
        eqos->config->ops->eqos_inval_buffer(packet, length);
 
-       rx_desc = &(eqos->rx_descs[eqos->rx_desc_idx]);
+       rx_desc = eqos_get_desc(eqos, eqos->rx_desc_idx, true);
 
        rx_desc->des0 = 0;
        mb();
@@ -1663,17 +1638,12 @@ static int eqos_probe_resources_core(struct udevice *dev)
 
        debug("%s(dev=%p):\n", __func__, dev);
 
-       eqos->descs = eqos_alloc_descs(EQOS_DESCRIPTORS_TX +
-                                      EQOS_DESCRIPTORS_RX);
+       eqos->descs = eqos_alloc_descs(eqos, EQOS_DESCRIPTORS_NUM);
        if (!eqos->descs) {
                debug("%s: eqos_alloc_descs() failed\n", __func__);
                ret = -ENOMEM;
                goto err;
        }
-       eqos->tx_descs = (struct eqos_desc *)eqos->descs;
-       eqos->rx_descs = (eqos->tx_descs + EQOS_DESCRIPTORS_TX);
-       debug("%s: tx_descs=%p, rx_descs=%p\n", __func__, eqos->tx_descs,
-             eqos->rx_descs);
 
        eqos->tx_dma_buf = memalign(EQOS_BUFFER_ALIGN, EQOS_MAX_PACKET_SIZE);
        if (!eqos->tx_dma_buf) {
@@ -2083,8 +2053,8 @@ static const struct eth_ops eqos_ops = {
 };
 
 static struct eqos_ops eqos_tegra186_ops = {
-       .eqos_inval_desc = eqos_inval_desc_tegra186,
-       .eqos_flush_desc = eqos_flush_desc_tegra186,
+       .eqos_inval_desc = eqos_inval_desc_generic,
+       .eqos_flush_desc = eqos_flush_desc_generic,
        .eqos_inval_buffer = eqos_inval_buffer_tegra186,
        .eqos_flush_buffer = eqos_flush_buffer_tegra186,
        .eqos_probe_resources = eqos_probe_resources_tegra186,
@@ -2105,6 +2075,7 @@ static const struct eqos_config __maybe_unused eqos_tegra186_config = {
        .swr_wait = 10,
        .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB,
        .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_20_35,
+       .axi_bus_width = EQOS_AXI_WIDTH_128,
        .interface = eqos_get_interface_tegra186,
        .ops = &eqos_tegra186_ops
 };
@@ -2132,6 +2103,7 @@ static const struct eqos_config __maybe_unused eqos_stm32_config = {
        .swr_wait = 50,
        .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_AV,
        .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_250_300,
+       .axi_bus_width = EQOS_AXI_WIDTH_64,
        .interface = eqos_get_interface_stm32,
        .ops = &eqos_stm32_ops
 };
@@ -2159,6 +2131,7 @@ struct eqos_config __maybe_unused eqos_imx_config = {
        .swr_wait = 50,
        .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB,
        .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_250_300,
+       .axi_bus_width = EQOS_AXI_WIDTH_64,
        .interface = eqos_get_interface_imx,
        .ops = &eqos_imx_ops
 };
index 3b3dd10..7335883 100644 (file)
@@ -869,7 +869,6 @@ e1000_read_eeprom(struct e1000_hw *hw, uint16_t offset,
        return E1000_SUCCESS;
 }
 
-#ifndef CONFIG_DM_ETH
 /******************************************************************************
  *  e1000_write_eeprom_srwr - Write to Shadow Ram using EEWR
  *  @hw: pointer to the HW structure
@@ -1035,7 +1034,6 @@ static int32_t e1000_update_eeprom_checksum_i210(struct e1000_hw *hw)
 out:
        return ret_val;
 }
-#endif
 
 /******************************************************************************
  * Verifies that the EEPROM has a valid checksum
@@ -5660,13 +5658,24 @@ e1000_poll(struct eth_device *nic)
 
        return len ? 1 : 0;
 }
+#endif /* !CONFIG_DM_ETH */
 
+#ifdef CONFIG_DM_ETH
+static int e1000_write_hwaddr(struct udevice *dev)
+#else
 static int e1000_write_hwaddr(struct eth_device *dev)
+#endif
 {
 #ifndef CONFIG_E1000_NO_NVM
-       unsigned char *mac = dev->enetaddr;
        unsigned char current_mac[6];
+#ifdef CONFIG_DM_ETH
+       struct eth_pdata *plat = dev_get_plat(dev);
+       struct e1000_hw *hw = dev_get_priv(dev);
+       u8 *mac = plat->enetaddr;
+#else
        struct e1000_hw *hw = dev->priv;
+       u8 *mac = dev->enetaddr;
+#endif
        uint16_t data[3];
        int ret_val, i;
 
@@ -5700,6 +5709,7 @@ static int e1000_write_hwaddr(struct eth_device *dev)
 #endif
 }
 
+#ifndef CONFIG_DM_ETH
 /**************************************************************************
 PROBE - Look for an adapter, this routine's visible to the outside
 You should omit the last argument struct pci_device * for a non-PCI NIC
@@ -5926,6 +5936,7 @@ static const struct eth_ops e1000_eth_ops = {
        .recv   = e1000_eth_recv,
        .stop   = e1000_eth_stop,
        .free_pkt = e1000_free_pkt,
+       .write_hwaddr = e1000_write_hwaddr,
 };
 
 static const struct udevice_id e1000_eth_ids[] = {
index 69e299d..0687230 100644 (file)
@@ -271,6 +271,28 @@ static int ftgmac100_set_mac(struct ftgmac100_data *priv,
 }
 
 /*
+ * Get MAC address
+ */
+static int ftgmac100_get_mac(struct ftgmac100_data *priv,
+                               unsigned char *mac)
+{
+       struct ftgmac100 *ftgmac100 = priv->iobase;
+       unsigned int maddr = readl(&ftgmac100->mac_madr);
+       unsigned int laddr = readl(&ftgmac100->mac_ladr);
+
+       debug("%s(%x %x)\n", __func__, maddr, laddr);
+
+       mac[0] = (maddr >> 8) & 0xff;
+       mac[1] =  maddr & 0xff;
+       mac[2] = (laddr >> 24) & 0xff;
+       mac[3] = (laddr >> 16) & 0xff;
+       mac[4] = (laddr >> 8) & 0xff;
+       mac[5] =  laddr & 0xff;
+
+       return 0;
+}
+
+/*
  * disable transmitter, receiver
  */
 static void ftgmac100_stop(struct udevice *dev)
@@ -511,6 +533,14 @@ static int ftgmac100_write_hwaddr(struct udevice *dev)
        return ftgmac100_set_mac(priv, pdata->enetaddr);
 }
 
+static int ftgmac_read_hwaddr(struct udevice *dev)
+{
+       struct eth_pdata *pdata = dev_get_plat(dev);
+       struct ftgmac100_data *priv = dev_get_priv(dev);
+
+       return ftgmac100_get_mac(priv, pdata->enetaddr);
+}
+
 static int ftgmac100_of_to_plat(struct udevice *dev)
 {
        struct eth_pdata *pdata = dev_get_plat(dev);
@@ -571,6 +601,8 @@ static int ftgmac100_probe(struct udevice *dev)
                goto out;
        }
 
+       ftgmac_read_hwaddr(dev);
+
 out:
        if (ret)
                clk_release_bulk(&priv->clks);
index 91c2d10..9dd9b33 100644 (file)
@@ -251,7 +251,8 @@ static int ks_rcv(struct ks_net *ks, uchar *data)
        }
 
        ks_wrreg16(ks, KS_RXQCR, RXQCR_CMD_CNTL | RXQCR_RRXEF);
-       printf(DRIVERNAME ": bad packet\n");
+       printf(DRIVERNAME ": bad packet (sts=0x%04x len=0x%04x)\n", sts, len);
+       ks->rxfc = 0;
        return 0;
 }
 
index 65498bc..b1de38f 100644 (file)
@@ -281,6 +281,15 @@ config PCIE_ROCKCHIP
          Say Y here if you want to enable PCIe controller support on
          Rockchip SoCs.
 
+config PCIE_DW_ROCKCHIP
+       bool "Rockchip DesignWare based PCIe controller"
+       depends on ARCH_ROCKCHIP
+       select DM_PCI
+       select PHY_ROCKCHIP_SNPS_PCIE3
+       help
+         Say Y here if you want to enable DW PCIe controller support on
+         Rockchip SoCs.
+
 config PCI_BRCMSTB
        bool "Broadcom STB PCIe controller"
        depends on DM_PCI
index 8b4d49a..5ed94bc 100644 (file)
@@ -48,5 +48,6 @@ obj-$(CONFIG_PCIE_INTEL_FPGA) += pcie_intel_fpga.o
 obj-$(CONFIG_PCI_KEYSTONE) += pcie_dw_ti.o
 obj-$(CONFIG_PCIE_MEDIATEK) += pcie_mediatek.o
 obj-$(CONFIG_PCIE_ROCKCHIP) += pcie_rockchip.o
+obj-$(CONFIG_PCIE_DW_ROCKCHIP) += pcie_dw_rockchip.o
 obj-$(CONFIG_PCI_BRCMSTB) += pcie_brcmstb.o
 obj-$(CONFIG_PCI_OCTEONTX) += pci_octeontx.o
diff --git a/drivers/pci/pcie_dw_rockchip.c b/drivers/pci/pcie_dw_rockchip.c
new file mode 100644 (file)
index 0000000..1527062
--- /dev/null
@@ -0,0 +1,877 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Rockchip DesignWare based PCIe host controller driver
+ *
+ * Copyright (c) 2021 Rockchip, Inc.
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <generic-phy.h>
+#include <pci.h>
+#include <power-domain.h>
+#include <reset.h>
+#include <syscon.h>
+#include <asm/arch-rockchip/clock.h>
+#include <asm/io.h>
+#include <asm-generic/gpio.h>
+#include <dm/device_compat.h>
+#include <linux/iopoll.h>
+#include <linux/delay.h>
+#include <power/regulator.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * struct rk_pcie - RK DW PCIe controller state
+ *
+ * @vpcie3v3: The 3.3v power supply for slot
+ * @dbi_base: The base address of dwc core regs
+ * @apb_base: The base address of vendor regs
+ * @cfg_base: The base address of config header space
+ * @cfg_size: The size of the configuration space which is needed
+ *            as it gets written into the PCIE_ATU_LIMIT register
+ * @first_busno: This driver supports multiple PCIe controllers.
+ *               first_busno stores the bus number of the PCIe root-port
+ *               number which may vary depending on the PCIe setup
+ *               (PEX switches etc).
+ * @rst_gpio: The #PERST signal for slot
+ * @io:        The IO space for EP's BAR
+ * @mem: The memory space for EP's BAR
+ */
+struct rk_pcie {
+       struct udevice  *dev;
+       struct udevice  *vpcie3v3;
+       void            *dbi_base;
+       void            *apb_base;
+       void            *cfg_base;
+       fdt_size_t      cfg_size;
+       struct phy      phy;
+       struct clk_bulk clks;
+       int             first_busno;
+       struct reset_ctl_bulk   rsts;
+       struct gpio_desc        rst_gpio;
+       struct pci_region       io;
+       struct pci_region       mem;
+};
+
+/* Parameters for the waiting for iATU enabled routine */
+#define PCIE_CLIENT_GENERAL_DEBUG      0x104
+#define PCIE_CLIENT_HOT_RESET_CTRL     0x180
+#define PCIE_LTSSM_ENABLE_ENHANCE      BIT(4)
+#define PCIE_CLIENT_LTSSM_STATUS       0x300
+#define SMLH_LINKUP                    BIT(16)
+#define RDLH_LINKUP                    BIT(17)
+#define PCIE_CLIENT_DBG_FIFO_MODE_CON  0x310
+#define PCIE_CLIENT_DBG_FIFO_PTN_HIT_D0 0x320
+#define PCIE_CLIENT_DBG_FIFO_PTN_HIT_D1 0x324
+#define PCIE_CLIENT_DBG_FIFO_TRN_HIT_D0 0x328
+#define PCIE_CLIENT_DBG_FIFO_TRN_HIT_D1 0x32c
+#define PCIE_CLIENT_DBG_FIFO_STATUS    0x350
+#define PCIE_CLIENT_DBG_TRANSITION_DATA        0xffff0000
+#define PCIE_CLIENT_DBF_EN             0xffff0003
+
+/* PCI DBICS registers */
+#define PCIE_LINK_STATUS_REG           0x80
+#define PCIE_LINK_STATUS_SPEED_OFF     16
+#define PCIE_LINK_STATUS_SPEED_MASK    (0xf << PCIE_LINK_STATUS_SPEED_OFF)
+#define PCIE_LINK_STATUS_WIDTH_OFF     20
+#define PCIE_LINK_STATUS_WIDTH_MASK    (0xf << PCIE_LINK_STATUS_WIDTH_OFF)
+
+#define PCIE_LINK_CAPABILITY           0x7c
+#define PCIE_LINK_CTL_2                        0xa0
+#define TARGET_LINK_SPEED_MASK         0xf
+#define LINK_SPEED_GEN_1               0x1
+#define LINK_SPEED_GEN_2               0x2
+#define LINK_SPEED_GEN_3               0x3
+
+#define PCIE_MISC_CONTROL_1_OFF                0x8bc
+#define PCIE_DBI_RO_WR_EN              BIT(0)
+
+#define PCIE_LINK_WIDTH_SPEED_CONTROL  0x80c
+#define PORT_LOGIC_SPEED_CHANGE                BIT(17)
+
+/*
+ * iATU Unroll-specific register definitions
+ * From 4.80 core version the address translation will be made by unroll.
+ * The registers are offset from atu_base
+ */
+#define PCIE_ATU_UNR_REGION_CTRL1      0x00
+#define PCIE_ATU_UNR_REGION_CTRL2      0x04
+#define PCIE_ATU_UNR_LOWER_BASE                0x08
+#define PCIE_ATU_UNR_UPPER_BASE                0x0c
+#define PCIE_ATU_UNR_LIMIT             0x10
+#define PCIE_ATU_UNR_LOWER_TARGET      0x14
+#define PCIE_ATU_UNR_UPPER_TARGET      0x18
+
+#define PCIE_ATU_REGION_INDEX1         (0x1 << 0)
+#define PCIE_ATU_REGION_INDEX0         (0x0 << 0)
+#define PCIE_ATU_TYPE_MEM              (0x0 << 0)
+#define PCIE_ATU_TYPE_IO               (0x2 << 0)
+#define PCIE_ATU_TYPE_CFG0             (0x4 << 0)
+#define PCIE_ATU_TYPE_CFG1             (0x5 << 0)
+#define PCIE_ATU_ENABLE                        (0x1 << 31)
+#define PCIE_ATU_BAR_MODE_ENABLE       (0x1 << 30)
+#define PCIE_ATU_BUS(x)                        (((x) & 0xff) << 24)
+#define PCIE_ATU_DEV(x)                        (((x) & 0x1f) << 19)
+#define PCIE_ATU_FUNC(x)               (((x) & 0x7) << 16)
+
+/* Register address builder */
+#define PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(region)        \
+       ((0x3 << 20) | ((region) << 9))
+
+/* Parameters for the waiting for iATU enabled routine */
+#define LINK_WAIT_MAX_IATU_RETRIES     5
+#define LINK_WAIT_IATU_US              10000
+
+/* Parameters for the waiting for #perst signal */
+#define PERST_WAIT_MS                  1000
+
+static int rk_pcie_read(void __iomem *addr, int size, u32 *val)
+{
+       if ((uintptr_t)addr & (size - 1)) {
+               *val = 0;
+               return PCIBIOS_UNSUPPORTED;
+       }
+
+       if (size == 4) {
+               *val = readl(addr);
+       } else if (size == 2) {
+               *val = readw(addr);
+       } else if (size == 1) {
+               *val = readb(addr);
+       } else {
+               *val = 0;
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+static int rk_pcie_write(void __iomem *addr, int size, u32 val)
+{
+       if ((uintptr_t)addr & (size - 1))
+               return PCIBIOS_UNSUPPORTED;
+
+       if (size == 4)
+               writel(val, addr);
+       else if (size == 2)
+               writew(val, addr);
+       else if (size == 1)
+               writeb(val, addr);
+       else
+               return -ENODEV;
+
+       return 0;
+}
+
+static u32 __rk_pcie_read_apb(struct rk_pcie *rk_pcie, void __iomem *base,
+                             u32 reg, size_t size)
+{
+       int ret;
+       u32 val;
+
+       ret = rk_pcie_read(base + reg, size, &val);
+       if (ret)
+               dev_err(rk_pcie->dev, "Read APB address failed\n");
+
+       return val;
+}
+
+static void __rk_pcie_write_apb(struct rk_pcie *rk_pcie, void __iomem *base,
+                               u32 reg, size_t size, u32 val)
+{
+       int ret;
+
+       ret = rk_pcie_write(base + reg, size, val);
+       if (ret)
+               dev_err(rk_pcie->dev, "Write APB address failed\n");
+}
+
+/**
+ * rk_pcie_readl_apb() - Read vendor regs
+ *
+ * @rk_pcie: Pointer to the PCI controller state
+ * @reg: Offset of regs
+ */
+static inline u32 rk_pcie_readl_apb(struct rk_pcie *rk_pcie, u32 reg)
+{
+       return __rk_pcie_read_apb(rk_pcie, rk_pcie->apb_base, reg, 0x4);
+}
+
+/**
+ * rk_pcie_writel_apb() - Write vendor regs
+ *
+ * @rk_pcie: Pointer to the PCI controller state
+ * @reg: Offset of regs
+ * @val: Value to be writen
+ */
+static inline void rk_pcie_writel_apb(struct rk_pcie *rk_pcie, u32 reg,
+                                     u32 val)
+{
+       __rk_pcie_write_apb(rk_pcie, rk_pcie->apb_base, reg, 0x4, val);
+}
+
+static int rk_pcie_get_link_speed(struct rk_pcie *rk_pcie)
+{
+       return (readl(rk_pcie->dbi_base + PCIE_LINK_STATUS_REG) &
+               PCIE_LINK_STATUS_SPEED_MASK) >> PCIE_LINK_STATUS_SPEED_OFF;
+}
+
+static int rk_pcie_get_link_width(struct rk_pcie *rk_pcie)
+{
+       return (readl(rk_pcie->dbi_base + PCIE_LINK_STATUS_REG) &
+               PCIE_LINK_STATUS_WIDTH_MASK) >> PCIE_LINK_STATUS_WIDTH_OFF;
+}
+
+static void rk_pcie_writel_ob_unroll(struct rk_pcie *rk_pcie, u32 index,
+                                    u32 reg, u32 val)
+{
+       u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
+       void __iomem *base = rk_pcie->dbi_base;
+
+       writel(val, base + offset + reg);
+}
+
+static u32 rk_pcie_readl_ob_unroll(struct rk_pcie *rk_pcie, u32 index, u32 reg)
+{
+       u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
+       void __iomem *base = rk_pcie->dbi_base;
+
+       return readl(base + offset + reg);
+}
+
+static inline void rk_pcie_dbi_write_enable(struct rk_pcie *rk_pcie, bool en)
+{
+       u32 val;
+
+       val = readl(rk_pcie->dbi_base + PCIE_MISC_CONTROL_1_OFF);
+
+       if (en)
+               val |= PCIE_DBI_RO_WR_EN;
+       else
+               val &= ~PCIE_DBI_RO_WR_EN;
+       writel(val, rk_pcie->dbi_base + PCIE_MISC_CONTROL_1_OFF);
+}
+
+/**
+ * rockchip_pcie_setup_host() - Setup the PCIe controller for RC opertaion
+ *
+ * @rk_pcie: Pointer to the PCI controller state
+ *
+ * Configure the host BARs of the PCIe controller root port so that
+ * PCI(e) devices may access the system memory.
+ */
+static void rk_pcie_setup_host(struct rk_pcie *rk_pcie)
+{
+       u32 val;
+
+       rk_pcie_dbi_write_enable(rk_pcie, true);
+
+       /* setup RC BARs */
+       writel(PCI_BASE_ADDRESS_MEM_TYPE_64,
+              rk_pcie->dbi_base + PCI_BASE_ADDRESS_0);
+       writel(0x0, rk_pcie->dbi_base + PCI_BASE_ADDRESS_1);
+
+       /* setup interrupt pins */
+       clrsetbits_le32(rk_pcie->dbi_base + PCI_INTERRUPT_LINE,
+                       0xff00, 0x100);
+
+       /* setup bus numbers */
+       clrsetbits_le32(rk_pcie->dbi_base + PCI_PRIMARY_BUS,
+                       0xffffff, 0x00ff0100);
+
+       /* setup command register */
+       clrsetbits_le32(rk_pcie->dbi_base + PCI_PRIMARY_BUS,
+                       0xffff,
+                       PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+                       PCI_COMMAND_MASTER | PCI_COMMAND_SERR);
+
+       /* program correct class for RC */
+       writew(PCI_CLASS_BRIDGE_PCI, rk_pcie->dbi_base + PCI_CLASS_DEVICE);
+       /* Better disable write permission right after the update */
+
+       setbits_le32(rk_pcie->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL,
+                    PORT_LOGIC_SPEED_CHANGE)
+
+       rk_pcie_dbi_write_enable(rk_pcie, false);
+}
+
+/**
+ * rk_pcie_configure() - Configure link capabilities and speed
+ *
+ * @rk_pcie: Pointer to the PCI controller state
+ * @cap_speed: The capabilities and speed to configure
+ *
+ * Configure the link capabilities and speed in the PCIe root complex.
+ */
+static void rk_pcie_configure(struct rk_pcie *pci, u32 cap_speed)
+{
+       u32 val;
+
+       rk_pcie_dbi_write_enable(pci, true);
+
+       clrsetbits_le32(pci->dbi_base + PCIE_LINK_CAPABILITY,
+                       TARGET_LINK_SPEED_MASK, cap_speed);
+
+       clrsetbits_le32(pci->dbi_base + PCIE_LINK_CTL_2,
+                       TARGET_LINK_SPEED_MASK, cap_speed);
+
+       rk_pcie_dbi_write_enable(pci, false);
+}
+
+/**
+ * rk_pcie_dw_prog_outbound_atu_unroll() - Configure ATU for outbound accesses
+ *
+ * @rk_pcie: Pointer to the PCI controller state
+ * @index: ATU region index
+ * @type: ATU accsess type
+ * @cpu_addr: the physical address for the translation entry
+ * @pci_addr: the pcie bus address for the translation entry
+ * @size: the size of the translation entry
+ *
+ * Return: 0 is successful and -1 is failure
+ */
+static int rk_pcie_prog_outbound_atu_unroll(struct rk_pcie *pci, int index,
+                                           int type, u64 cpu_addr,
+                                           u64 pci_addr, u32 size)
+{
+       u32 retries, val;
+
+       dev_dbg(pci->dev, "ATU programmed with: index: %d, type: %d, cpu addr: %8llx, pci addr: %8llx, size: %8x\n",
+               index, type, cpu_addr, pci_addr, size);
+
+       rk_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_LOWER_BASE,
+                                lower_32_bits(cpu_addr));
+       rk_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_UPPER_BASE,
+                                upper_32_bits(cpu_addr));
+       rk_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_LIMIT,
+                                lower_32_bits(cpu_addr + size - 1));
+       rk_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_LOWER_TARGET,
+                                lower_32_bits(pci_addr));
+       rk_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_UPPER_TARGET,
+                                upper_32_bits(pci_addr));
+       rk_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL1,
+                                type);
+       rk_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL2,
+                                PCIE_ATU_ENABLE);
+
+       /*
+        * Make sure ATU enable takes effect before any subsequent config
+        * and I/O accesses.
+        */
+       for (retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; retries++) {
+               val = rk_pcie_readl_ob_unroll(pci, index,
+                                             PCIE_ATU_UNR_REGION_CTRL2);
+               if (val & PCIE_ATU_ENABLE)
+                       return 0;
+
+               udelay(LINK_WAIT_IATU_US);
+       }
+       dev_err(pci->dev, "outbound iATU is not being enabled\n");
+
+       return -1;
+}
+
+/**
+ * rk_pcie_dw_addr_valid() - Check for valid bus address
+ *
+ * @d: The PCI device to access
+ * @first_busno: Bus number of the PCIe controller root complex
+ *
+ * Return 1 (true) if the PCI device can be accessed by this controller.
+ *
+ * Return: 1 on valid, 0 on invalid
+ */
+static int rk_pcie_addr_valid(pci_dev_t d, int first_busno)
+{
+       if ((PCI_BUS(d) == first_busno) && (PCI_DEV(d) > 0))
+               return 0;
+       if ((PCI_BUS(d) == first_busno + 1) && (PCI_DEV(d) > 0))
+               return 0;
+
+       return 1;
+}
+
+/**
+ * set_cfg_address() - Configure the PCIe controller config space access
+ *
+ * @rk_pcie: Pointer to the PCI controller state
+ * @d: PCI device to access
+ * @where: Offset in the configuration space
+ *
+ * Configures the PCIe controller to access the configuration space of
+ * a specific PCIe device and returns the address to use for this
+ * access.
+ *
+ * Return: Address that can be used to access the configation space
+ *         of the requested device / offset
+ */
+static uintptr_t set_cfg_address(struct rk_pcie *pcie,
+                                pci_dev_t d, uint where)
+{
+       int rel_bus = PCI_BUS(d) - pcie->first_busno;
+       uintptr_t va_address;
+       u32 atu_type;
+       int ret;
+
+       /* Use dbi_base for own configuration read and write */
+       if (!rel_bus) {
+               va_address = (uintptr_t)pcie->dbi_base;
+               goto out;
+       }
+
+       if (rel_bus == 1)
+               /*
+                * For local bus whose primary bus number is root bridge,
+                * change TLP Type field to 4.
+                */
+               atu_type = PCIE_ATU_TYPE_CFG0;
+       else
+               /* Otherwise, change TLP Type field to 5. */
+               atu_type = PCIE_ATU_TYPE_CFG1;
+
+       /*
+        * Not accessing root port configuration space?
+        * Region #0 is used for Outbound CFG space access.
+        * Direction = Outbound
+        * Region Index = 0
+        */
+       d = PCI_MASK_BUS(d);
+       d = PCI_ADD_BUS(rel_bus, d);
+       ret = rk_pcie_prog_outbound_atu_unroll(pcie, PCIE_ATU_REGION_INDEX1,
+                                              atu_type, (u64)pcie->cfg_base,
+                                              d << 8, pcie->cfg_size);
+       if (ret)
+               return (uintptr_t)ret;
+
+       va_address = (uintptr_t)pcie->cfg_base;
+
+out:
+       va_address += where & ~0x3;
+
+       return va_address;
+}
+
+/**
+ * rockchip_pcie_rd_conf() - Read from configuration space
+ *
+ * @bus: Pointer to the PCI bus
+ * @bdf: Identifies the PCIe device to access
+ * @offset: The offset into the device's configuration space
+ * @valuep: A pointer at which to store the read value
+ * @size: Indicates the size of access to perform
+ *
+ * Read a value of size @size from offset @offset within the configuration
+ * space of the device identified by the bus, device & function numbers in @bdf
+ * on the PCI bus @bus.
+ *
+ * Return: 0 on success
+ */
+static int rockchip_pcie_rd_conf(const struct udevice *bus, pci_dev_t bdf,
+                                uint offset, ulong *valuep,
+                                enum pci_size_t size)
+{
+       struct rk_pcie *pcie = dev_get_priv(bus);
+       uintptr_t va_address;
+       ulong value;
+
+       debug("PCIE CFG read: bdf=%2x:%2x:%2x\n",
+             PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf));
+
+       if (!rk_pcie_addr_valid(bdf, pcie->first_busno)) {
+               debug("- out of range\n");
+               *valuep = pci_get_ff(size);
+               return 0;
+       }
+
+       va_address = set_cfg_address(pcie, bdf, offset);
+
+       value = readl(va_address);
+
+       debug("(addr,val)=(0x%04x, 0x%08lx)\n", offset, value);
+       *valuep = pci_conv_32_to_size(value, offset, size);
+
+       return rk_pcie_prog_outbound_atu_unroll(pcie,
+                                               PCIE_ATU_REGION_INDEX1,
+                                               PCIE_ATU_TYPE_IO,
+                                               pcie->io.phys_start,
+                                               pcie->io.bus_start,
+                                               pcie->io.size);
+}
+
+/**
+ * rockchip_pcie_wr_conf() - Write to configuration space
+ *
+ * @bus: Pointer to the PCI bus
+ * @bdf: Identifies the PCIe device to access
+ * @offset: The offset into the device's configuration space
+ * @value: The value to write
+ * @size: Indicates the size of access to perform
+ *
+ * Write the value @value of size @size from offset @offset within the
+ * configuration space of the device identified by the bus, device & function
+ * numbers in @bdf on the PCI bus @bus.
+ *
+ * Return: 0 on success
+ */
+static int rockchip_pcie_wr_conf(struct udevice *bus, pci_dev_t bdf,
+                                uint offset, ulong value,
+                                enum pci_size_t size)
+{
+       struct rk_pcie *pcie = dev_get_priv(bus);
+       uintptr_t va_address;
+       ulong old;
+
+       debug("PCIE CFG write: (b,d,f)=(%2d,%2d,%2d)\n",
+             PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf));
+       debug("(addr,val)=(0x%04x, 0x%08lx)\n", offset, value);
+
+       if (!rk_pcie_addr_valid(bdf, pcie->first_busno)) {
+               debug("- out of range\n");
+               return 0;
+       }
+
+       va_address = set_cfg_address(pcie, bdf, offset);
+
+       old = readl(va_address);
+       value = pci_conv_size_to_32(old, value, offset, size);
+       writel(value, va_address);
+
+       return rk_pcie_prog_outbound_atu_unroll(pcie,
+                                               PCIE_ATU_REGION_INDEX1,
+                                               PCIE_ATU_TYPE_IO,
+                                               pcie->io.phys_start,
+                                               pcie->io.bus_start,
+                                               pcie->io.size);
+
+}
+
+static void rk_pcie_enable_debug(struct rk_pcie *rk_pcie)
+{
+       rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_DBG_FIFO_PTN_HIT_D0,
+                          PCIE_CLIENT_DBG_TRANSITION_DATA);
+       rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_DBG_FIFO_PTN_HIT_D1,
+                          PCIE_CLIENT_DBG_TRANSITION_DATA);
+       rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_DBG_FIFO_TRN_HIT_D0,
+                          PCIE_CLIENT_DBG_TRANSITION_DATA);
+       rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_DBG_FIFO_TRN_HIT_D1,
+                          PCIE_CLIENT_DBG_TRANSITION_DATA);
+       rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_DBG_FIFO_MODE_CON,
+                          PCIE_CLIENT_DBF_EN);
+}
+
+static void rk_pcie_debug_dump(struct rk_pcie *rk_pcie)
+{
+       u32 loop;
+
+       debug("ltssm = 0x%x\n",
+             rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_LTSSM_STATUS));
+       for (loop = 0; loop < 64; loop++)
+               debug("fifo_status = 0x%x\n",
+                     rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_DBG_FIFO_STATUS));
+}
+
+static inline void rk_pcie_link_status_clear(struct rk_pcie *rk_pcie)
+{
+       rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_GENERAL_DEBUG, 0x0);
+}
+
+static inline void rk_pcie_disable_ltssm(struct rk_pcie *rk_pcie)
+{
+       rk_pcie_writel_apb(rk_pcie, 0x0, 0xc0008);
+}
+
+static inline void rk_pcie_enable_ltssm(struct rk_pcie *rk_pcie)
+{
+       rk_pcie_writel_apb(rk_pcie, 0x0, 0xc000c);
+}
+
+static int is_link_up(struct rk_pcie *priv)
+{
+       u32 val;
+
+       val = rk_pcie_readl_apb(priv, PCIE_CLIENT_LTSSM_STATUS);
+       if ((val & (RDLH_LINKUP | SMLH_LINKUP)) == 0x30000 &&
+           (val & GENMASK(5, 0)) == 0x11)
+               return 1;
+
+       return 0;
+}
+
+/**
+ * rk_pcie_link_up() - Wait for the link to come up
+ *
+ * @rk_pcie: Pointer to the PCI controller state
+ * @cap_speed: Desired link speed
+ *
+ * Return: 1 (true) for active line and negetive (false) for no link (timeout)
+ */
+static int rk_pcie_link_up(struct rk_pcie *priv, u32 cap_speed)
+{
+       int retries;
+
+       if (is_link_up(priv)) {
+               printf("PCI Link already up before configuration!\n");
+               return 1;
+       }
+
+       /* DW pre link configurations */
+       rk_pcie_configure(priv, cap_speed);
+
+       /* Rest the device */
+       if (dm_gpio_is_valid(&priv->rst_gpio)) {
+               dm_gpio_set_value(&priv->rst_gpio, 0);
+               /*
+                * Minimal is 100ms from spec but we see
+                * some wired devices need much more, such as 600ms.
+                * Add a enough delay to cover all cases.
+                */
+               msleep(PERST_WAIT_MS);
+               dm_gpio_set_value(&priv->rst_gpio, 1);
+       }
+
+       rk_pcie_disable_ltssm(priv);
+       rk_pcie_link_status_clear(priv);
+       rk_pcie_enable_debug(priv);
+
+       /* Enable LTSSM */
+       rk_pcie_enable_ltssm(priv);
+
+       for (retries = 0; retries < 5; retries++) {
+               if (is_link_up(priv)) {
+                       dev_info(priv->dev, "PCIe Link up, LTSSM is 0x%x\n",
+                                rk_pcie_readl_apb(priv, PCIE_CLIENT_LTSSM_STATUS));
+                       rk_pcie_debug_dump(priv);
+                       return 0;
+               }
+
+               dev_info(priv->dev, "PCIe Linking... LTSSM is 0x%x\n",
+                        rk_pcie_readl_apb(priv, PCIE_CLIENT_LTSSM_STATUS));
+               rk_pcie_debug_dump(priv);
+               msleep(1000);
+       }
+
+       dev_err(priv->dev, "PCIe-%d Link Fail\n", dev_seq(priv->dev));
+       /* Link maybe in Gen switch recovery but we need to wait more 1s */
+       msleep(1000);
+       return -EIO;
+}
+
+static int rockchip_pcie_init_port(struct udevice *dev)
+{
+       int ret;
+       u32 val;
+       struct rk_pcie *priv = dev_get_priv(dev);
+
+       /* Set power and maybe external ref clk input */
+       if (priv->vpcie3v3) {
+               ret = regulator_set_value(priv->vpcie3v3, 3300000);
+               if (ret) {
+                       dev_err(priv->dev, "failed to enable vpcie3v3 (ret=%d)\n",
+                               ret);
+                       return ret;
+               }
+       }
+
+       msleep(1000);
+
+       ret = generic_phy_init(&priv->phy);
+       if (ret) {
+               dev_err(dev, "failed to init phy (ret=%d)\n", ret);
+               return ret;
+       }
+
+       ret = generic_phy_power_on(&priv->phy);
+       if (ret) {
+               dev_err(dev, "failed to power on phy (ret=%d)\n", ret);
+               goto err_exit_phy;
+       }
+
+       ret = reset_deassert_bulk(&priv->rsts);
+       if (ret) {
+               dev_err(dev, "failed to deassert resets (ret=%d)\n", ret);
+               goto err_power_off_phy;
+       }
+
+       ret = clk_enable_bulk(&priv->clks);
+       if (ret) {
+               dev_err(dev, "failed to enable clks (ret=%d)\n", ret);
+               goto err_deassert_bulk;
+       }
+
+       /* LTSSM EN ctrl mode */
+       val = rk_pcie_readl_apb(priv, PCIE_CLIENT_HOT_RESET_CTRL);
+       val |= PCIE_LTSSM_ENABLE_ENHANCE | (PCIE_LTSSM_ENABLE_ENHANCE << 16);
+       rk_pcie_writel_apb(priv, PCIE_CLIENT_HOT_RESET_CTRL, val);
+
+       /* Set RC mode */
+       rk_pcie_writel_apb(priv, 0x0, 0xf00040);
+       rk_pcie_setup_host(priv);
+
+       ret = rk_pcie_link_up(priv, LINK_SPEED_GEN_3);
+       if (ret < 0)
+               goto err_link_up;
+
+       return 0;
+err_link_up:
+       clk_disable_bulk(&priv->clks);
+err_deassert_bulk:
+       reset_assert_bulk(&priv->rsts);
+err_power_off_phy:
+       generic_phy_power_off(&priv->phy);
+err_exit_phy:
+       generic_phy_exit(&priv->phy);
+
+       return ret;
+}
+
+static int rockchip_pcie_parse_dt(struct udevice *dev)
+{
+       struct rk_pcie *priv = dev_get_priv(dev);
+       int ret;
+
+       priv->dbi_base = (void *)dev_read_addr_index(dev, 0);
+       if (!priv->dbi_base)
+               return -ENODEV;
+
+       dev_dbg(dev, "DBI address is 0x%p\n", priv->dbi_base);
+
+       priv->apb_base = (void *)dev_read_addr_index(dev, 1);
+       if (!priv->apb_base)
+               return -ENODEV;
+
+       dev_dbg(dev, "APB address is 0x%p\n", priv->apb_base);
+
+       ret = gpio_request_by_name(dev, "reset-gpios", 0,
+                                  &priv->rst_gpio, GPIOD_IS_OUT);
+       if (ret) {
+               dev_err(dev, "failed to find reset-gpios property\n");
+               return ret;
+       }
+
+       ret = reset_get_bulk(dev, &priv->rsts);
+       if (ret) {
+               dev_err(dev, "Can't get reset: %d\n", ret);
+               return ret;
+       }
+
+       ret = clk_get_bulk(dev, &priv->clks);
+       if (ret) {
+               dev_err(dev, "Can't get clock: %d\n", ret);
+               return ret;
+       }
+
+       ret = device_get_supply_regulator(dev, "vpcie3v3-supply",
+                                         &priv->vpcie3v3);
+       if (ret && ret != -ENOENT) {
+               dev_err(dev, "failed to get vpcie3v3 supply (ret=%d)\n", ret);
+               return ret;
+       }
+
+       ret = generic_phy_get_by_index(dev, 0, &priv->phy);
+       if (ret) {
+               dev_err(dev, "failed to get pcie phy (ret=%d)\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+/**
+ * rockchip_pcie_probe() - Probe the PCIe bus for active link
+ *
+ * @dev: A pointer to the device being operated on
+ *
+ * Probe for an active link on the PCIe bus and configure the controller
+ * to enable this port.
+ *
+ * Return: 0 on success, else -ENODEV
+ */
+static int rockchip_pcie_probe(struct udevice *dev)
+{
+       struct rk_pcie *priv = dev_get_priv(dev);
+       struct udevice *ctlr = pci_get_controller(dev);
+       struct pci_controller *hose = dev_get_uclass_priv(ctlr);
+       int reti = 0;
+
+       priv->first_busno = dev_seq(dev);
+       priv->dev = dev;
+
+       ret = rockchip_pcie_parse_dt(dev);
+       if (ret)
+               return ret;
+
+       ret = rockchip_pcie_init_port(dev);
+       if (ret)
+               return ret;
+
+       dev_info(dev, "PCIE-%d: Link up (Gen%d-x%d, Bus%d)\n",
+                dev_seq(dev), rk_pcie_get_link_speed(priv),
+                rk_pcie_get_link_width(priv),
+                hose->first_busno);
+
+       for (ret = 0; ret < hose->region_count; ret++) {
+               if (hose->regions[ret].flags == PCI_REGION_IO) {
+                       priv->io.phys_start = hose->regions[ret].phys_start; /* IO base */
+                       priv->io.bus_start  = hose->regions[ret].bus_start;  /* IO_bus_addr */
+                       priv->io.size       = hose->regions[ret].size;      /* IO size */
+               } else if (hose->regions[ret].flags == PCI_REGION_MEM) {
+                       priv->mem.phys_start = hose->regions[ret].phys_start; /* MEM base */
+                       priv->mem.bus_start  = hose->regions[ret].bus_start;  /* MEM_bus_addr */
+                       priv->mem.size       = hose->regions[ret].size;     /* MEM size */
+               } else if (hose->regions[ret].flags == PCI_REGION_SYS_MEMORY) {
+                       priv->cfg_base = (void *)(priv->io.phys_start - priv->io.size);
+                       priv->cfg_size = priv->io.size;
+               } else {
+                       dev_err(dev, "invalid flags type!\n");
+               }
+       }
+
+       dev_dbg(dev, "Config space: [0x%p - 0x%p, size 0x%llx]\n",
+               priv->cfg_base, priv->cfg_base + priv->cfg_size,
+               priv->cfg_size);
+
+       dev_dbg(dev, "IO space: [0x%llx - 0x%llx, size 0x%lx]\n",
+               priv->io.phys_start, priv->io.phys_start + priv->io.size,
+               priv->io.size);
+
+       dev_dbg(dev, "IO bus:   [0x%lx - 0x%lx, size 0x%lx]\n",
+               priv->io.bus_start, priv->io.bus_start + priv->io.size,
+               priv->io.size);
+
+       dev_dbg(dev, "MEM space: [0x%llx - 0x%llx, size 0x%lx]\n",
+               priv->mem.phys_start, priv->mem.phys_start + priv->mem.size,
+               priv->mem.size);
+
+       dev_dbg(dev, "MEM bus:   [0x%lx - 0x%lx, size 0x%lx]\n",
+               priv->mem.bus_start, priv->mem.bus_start + priv->mem.size,
+               priv->mem.size);
+
+       return rk_pcie_prog_outbound_atu_unroll(priv,
+                                               PCIE_ATU_REGION_INDEX0,
+                                               PCIE_ATU_TYPE_MEM,
+                                               priv->mem.phys_start,
+                                               priv->mem.bus_start,
+                                               priv->mem.size);
+}
+
+static const struct dm_pci_ops rockchip_pcie_ops = {
+       .read_config    = rockchip_pcie_rd_conf,
+       .write_config   = rockchip_pcie_wr_conf,
+};
+
+static const struct udevice_id rockchip_pcie_ids[] = {
+       { .compatible = "rockchip,rk3568-pcie" },
+       { }
+};
+
+U_BOOT_DRIVER(rockchip_dw_pcie) = {
+       .name                   = "pcie_dw_rockchip",
+       .id                     = UCLASS_PCI,
+       .of_match               = rockchip_pcie_ids,
+       .ops                    = &rockchip_pcie_ops,
+       .probe                  = rockchip_pcie_probe,
+       .priv_auto              = sizeof(struct rk_pcie),
+};
index 2318e71..e477a6c 100644 (file)
@@ -18,6 +18,15 @@ config PHY_ROCKCHIP_PCIE
        help
          Enable this to support the Rockchip PCIe PHY.
 
+config PHY_ROCKCHIP_SNPS_PCIE3
+       bool "Rockchip Snps PCIe3 PHY Driver"
+       depends on PHY && ARCH_ROCKCHIP
+       help
+         Support for Rockchip PCIe3 PHY with Synopsys IP block.
+         It could support PCIe Gen3 single root complex, and could
+         also be able splited into multiple combinations of lanes.
+
+
 config PHY_ROCKCHIP_TYPEC
        bool "Rockchip TYPEC PHY Driver"
        depends on ARCH_ROCKCHIP
index 4404915..f6ad3bf 100644 (file)
@@ -5,4 +5,5 @@
 
 obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2)   += phy-rockchip-inno-usb2.o
 obj-$(CONFIG_PHY_ROCKCHIP_PCIE)                += phy-rockchip-pcie.o
+obj-$(CONFIG_PHY_ROCKCHIP_SNPS_PCIE3)  += phy-rockchip-snps-pcie3.o
 obj-$(CONFIG_PHY_ROCKCHIP_TYPEC)       += phy-rockchip-typec.o
diff --git a/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c b/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c
new file mode 100644 (file)
index 0000000..5ae41fb
--- /dev/null
@@ -0,0 +1,157 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Rockchip PCIE3.0 phy driver
+ *
+ * Copyright (C) 2021 Rockchip Electronics Co., Ltd.
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <generic-phy.h>
+#include <regmap.h>
+#include <reset-uclass.h>
+#include <syscon.h>
+#include <asm/io.h>
+#include <dm/device_compat.h>
+#include <dm/lists.h>
+
+#define GRF_PCIE30PHY_CON1 0x4
+#define GRF_PCIE30PHY_CON6 0x18
+#define GRF_PCIE30PHY_CON9 0x24
+
+/**
+ * struct rockchip_p3phy_priv - RK DW PCIe PHY state
+ *
+ * @mmio: The base address of PHY internal registers
+ * @phy_grf: The regmap for controlling pipe signal
+ * @p30phy: The reset signal for PHY
+ * @ref_clk_m: The reference clock of M for PHY
+ * @ref_clk_n: The reference clock of N for PHY
+ * @pclk: The clock for accessing PHY blocks
+ */
+struct rockchip_p3phy_priv {
+       void __iomem *mmio;
+       struct regmap *phy_grf;
+       struct reset_ctl p30phy;
+       struct clk ref_clk_m;
+       struct clk ref_clk_n;
+       struct clk pclk;
+};
+
+static int rochchip_p3phy_init(struct phy *phy)
+{
+       struct rockchip_p3phy_priv *priv = dev_get_priv(phy->dev);
+       int ret;
+
+       ret = clk_enable(&priv->ref_clk_m);
+       if (ret < 0 && ret != -ENOSYS)
+               return ret;
+
+       ret = clk_enable(&priv->ref_clk_n);
+       if (ret < 0 && ret != -ENOSYS)
+               goto err_ref;
+
+       ret = clk_enable(&priv->pclk);
+       if (ret < 0 && ret != -ENOSYS)
+               goto err_pclk;
+
+       reset_assert(&priv->p30phy);
+       udelay(1);
+
+       /* Deassert PCIe PMA output clamp mode */
+       regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON9,
+                    (0x1 << 15) | (0x1 << 31));
+
+       reset_deassert(&priv->p30phy);
+       udelay(1);
+
+       return 0;
+err_pclk:
+       clk_disable(&priv->ref_clk_n);
+err_ref:
+       clk_disable(&priv->ref_clk_m);
+
+       return ret;
+}
+
+static int rochchip_p3phy_exit(struct phy *phy)
+{
+       struct rockchip_p3phy_priv *priv = dev_get_priv(phy->dev);
+
+       clk_disable(&priv->ref_clk_m);
+       clk_disable(&priv->ref_clk_n);
+       clk_disable(&priv->pclk);
+       reset_assert(&priv->p30phy);
+
+       return 0;
+}
+
+static int rockchip_p3phy_probe(struct udevice *dev)
+{
+       struct rockchip_p3phy_priv *priv = dev_get_priv(dev);
+       struct udevice *syscon;
+       int ret;
+
+       priv->mmio = (void __iomem *)dev_read_addr(dev);
+       if ((fdt_addr_t)priv->mmio == FDT_ADDR_T_NONE)
+               return -EINVAL;
+
+       ret = uclass_get_device_by_phandle(UCLASS_SYSCON, dev,
+                                          "rockchip,phy-grf",  &syscon);
+       if (ret) {
+               pr_err("unable to find syscon device for rockchip,phy-grf\n");
+               return ret;
+       }
+
+       priv->phy_grf = syscon_get_regmap(syscon);
+       if (IS_ERR(priv->phy_grf)) {
+               dev_err(dev, "failed to find rockchip,phy_grf regmap\n");
+               return PTR_ERR(priv->phy_grf);
+       }
+
+       ret = reset_get_by_name(dev, "phy", &priv->p30phy);
+       if (ret) {
+               dev_err(dev, "no phy reset control specified\n");
+               return ret;
+       }
+
+       ret = clk_get_by_name(dev, "refclk_m", &priv->ref_clk_m);
+       if (ret) {
+               dev_err(dev, "failed to find ref clock M\n");
+               return PTR_ERR(&priv->ref_clk_m);
+       }
+
+       ret = clk_get_by_name(dev, "refclk_n", &priv->ref_clk_n);
+       if (ret) {
+               dev_err(dev, "failed to find ref clock N\n");
+               return PTR_ERR(&priv->ref_clk_n);
+       }
+
+       ret = clk_get_by_name(dev, "pclk", &priv->pclk);
+       if (ret) {
+               dev_err(dev, "failed to find pclk\n");
+               return PTR_ERR(&priv->pclk);
+       }
+
+       return 0;
+}
+
+static struct phy_ops rochchip_p3phy_ops = {
+       .init = rochchip_p3phy_init,
+       .exit = rochchip_p3phy_exit,
+};
+
+static const struct udevice_id rockchip_p3phy_of_match[] = {
+       { .compatible = "rockchip,rk3568-pcie3-phy" },
+       { },
+};
+
+U_BOOT_DRIVER(rockchip_pcie3phy) = {
+       .name           = "rockchip_pcie3phy",
+       .id             = UCLASS_PHY,
+       .of_match       = rockchip_p3phy_of_match,
+       .ops            = &rochchip_p3phy_ops,
+       .probe          = rockchip_p3phy_probe,
+       .priv_auto      = sizeof(struct rockchip_p3phy_priv),
+};
index 6553dde..4dd3f73 100644 (file)
@@ -615,6 +615,7 @@ static int mtk_gpiochip_register(struct udevice *parent)
        if (!drv)
                return -ENOENT;
 
+       ret = -ENOENT;
        dev_for_each_subnode(node, parent)
                if (ofnode_read_bool(node, "gpio-controller")) {
                        ret = 0;
index 7d51510..583fd3d 100644 (file)
@@ -91,6 +91,21 @@ config DM_PMIC_FAN53555
          The driver implements read/write operations for use with the FAN53555
          regulator driver and binds the regulator driver to its node.
 
+config DM_PMIC_MP5416
+       bool "Enable Driver Model for PMIC MP5416"
+       depends on DM_PMIC
+       help
+         This config enables implementation of driver-model pmic uclass features
+         for PMIC MP5416. The driver implements read/write operations.
+
+config SPL_DM_PMIC_MP5416
+       bool "Enable Driver Model for PMIC MP5416 in SPL stage"
+       depends on DM_PMIC
+       help
+         This config enables implementation of driver-model pmic uclass
+         features for PMIC MP5416. The driver implements read/write
+         operations.
+
 config DM_PMIC_PCA9450
        bool "Enable Driver Model for PMIC PCA9450"
        depends on DM_PMIC
index 9cd6c37..2b2a6dd 100644 (file)
@@ -10,6 +10,7 @@ obj-$(CONFIG_DM_PMIC_MAX77686) += max77686.o
 obj-$(CONFIG_DM_PMIC_MAX8998) += max8998.o
 obj-$(CONFIG_DM_PMIC_MC34708) += mc34708.o
 obj-$(CONFIG_$(SPL_)DM_PMIC_BD71837) += bd71837.o
+obj-$(CONFIG_$(SPL_)DM_PMIC_MP5416) += mp5416.o
 obj-$(CONFIG_$(SPL_)DM_PMIC_PFUZE100) += pfuze100.o
 obj-$(CONFIG_$(SPL_)DM_PMIC_PCA9450) += pca9450.o
 obj-$(CONFIG_PMIC_S2MPS11) += s2mps11.o
diff --git a/drivers/power/pmic/mp5416.c b/drivers/power/pmic/mp5416.c
new file mode 100644 (file)
index 0000000..458c4df
--- /dev/null
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier:      GPL-2.0+
+/*
+ * Copyright 2020 Gateworks Corporation
+ */
+#include <common.h>
+#include <errno.h>
+#include <dm.h>
+#include <i2c.h>
+#include <log.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+#include <power/mp5416.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static const struct pmic_child_info pmic_children_info[] = {
+       /* buck */
+       { .prefix = "b", .driver = MP6416_REGULATOR_DRIVER },
+       /* ldo */
+       { .prefix = "l", .driver = MP6416_REGULATOR_DRIVER },
+       { },
+};
+
+static int mp5416_reg_count(struct udevice *dev)
+{
+       return MP5416_NUM_OF_REGS - 1;
+}
+
+static int mp5416_write(struct udevice *dev, uint reg, const uint8_t *buff,
+                       int len)
+{
+       if (dm_i2c_write(dev, reg, buff, len)) {
+               pr_err("write error to device: %p register: %#x!", dev, reg);
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static int mp5416_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
+{
+       if (dm_i2c_read(dev, reg, buff, len)) {
+               pr_err("read error from device: %p register: %#x!", dev, reg);
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static int mp5416_bind(struct udevice *dev)
+{
+       int children;
+       ofnode regulators_node;
+
+       debug("%s %s\n", __func__, dev->name);
+       regulators_node = dev_read_subnode(dev, "regulators");
+       if (!ofnode_valid(regulators_node)) {
+               debug("%s: %s regulators subnode not found!\n", __func__,
+                     dev->name);
+               return -ENXIO;
+       }
+
+       debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
+
+       children = pmic_bind_children(dev, regulators_node, pmic_children_info);
+       if (!children)
+               debug("%s: %s - no child found\n", __func__, dev->name);
+
+       /* Always return success for this device */
+       return 0;
+}
+
+static int mp5416_probe(struct udevice *dev)
+{
+       debug("%s %s\n", __func__, dev->name);
+
+       return 0;
+}
+
+static struct dm_pmic_ops mp5416_ops = {
+       .reg_count = mp5416_reg_count,
+       .read = mp5416_read,
+       .write = mp5416_write,
+};
+
+static const struct udevice_id mp5416_ids[] = {
+       { .compatible = "mps,mp5416", },
+       { }
+};
+
+U_BOOT_DRIVER(pmic_mp5416) = {
+       .name = "mp5416 pmic",
+       .id = UCLASS_PMIC,
+       .of_match = mp5416_ids,
+       .bind = mp5416_bind,
+       .probe = mp5416_probe,
+       .ops = &mp5416_ops,
+};
index 1a829b5..259e4e3 100644 (file)
@@ -288,7 +288,6 @@ void u_qe_init(void)
        struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV);
 
        if (!mmc) {
-               free(addr);
                printf("\nMMC cannot find device for ucode\n");
        } else {
                printf("\nMMC read: dev # %u, block # %u, count %u ...\n",
index 020c913..049b9dc 100644 (file)
@@ -1,4 +1,5 @@
 if RAM || SPL_RAM
+
 config ASPEED_DDR4_DUALX8
        bool "Enable Dual X8 DDR4 die"
        depends on DM && OF_CONTROL && ARCH_ASPEED
@@ -7,4 +8,62 @@ config ASPEED_DDR4_DUALX8
                Say Y if dual X8 DDR4 die is used on the board.  The aspeed ddr sdram
                controller needs to know if the memory chip mounted on the board is dual
                 x8 die or not.  Or it may get the wrong size of the memory space.
-endif
+
+if ASPEED_AST2600
+
+choice
+       prompt "DDR4 target date rate"
+       default ASPEED_DDR4_1600
+
+config ASPEED_DDR4_400
+       bool "DDR4 targets at 400Mbps"
+       depends on DM && OF_CONTROL && ARCH_ASPEED
+       help
+         select DDR4 target data rate at 400M
+
+config ASPEED_DDR4_800
+       bool "DDR4 targets at 800Mbps"
+       depends on DM && OF_CONTROL && ARCH_ASPEED
+       help
+         select DDR4 target data rate at 800M
+
+config ASPEED_DDR4_1333
+       bool "DDR4 targets at 1333Mbps"
+       depends on DM && OF_CONTROL && ARCH_ASPEED
+       help
+         select DDR4 target data rate at 1333M
+
+config ASPEED_DDR4_1600
+       bool "DDR4 targets at 1600Mbps"
+       depends on DM && OF_CONTROL && ARCH_ASPEED
+       help
+         select DDR4 target data rate at 1600M
+endchoice
+
+config ASPEED_BYPASS_SELFTEST
+       bool "bypass self test during DRAM initialization"
+       default n
+       help
+         Say Y here to bypass DRAM self test to speed up the boot time
+
+config ASPEED_ECC
+       bool "aspeed SDRAM error correcting code"
+       depends on DM && OF_CONTROL && ARCH_ASPEED
+       default n
+       help
+         enable SDRAM ECC function
+
+if ASPEED_ECC
+config ASPEED_ECC_SIZE
+       int "ECC size: 0=driver auto-caluated"
+       depends on ASPEED_ECC
+       default 0
+       help
+         SDRAM size with the error correcting code enabled. The unit is
+         in Megabytes.  Noted that only the 8/9 of the configured size
+         can be used by the system.  The remaining 1/9 will be used by
+         the ECC engine.  If the size is set to 0, the sdram driver will
+         calculate the SDRAM size and set the whole range be ECC enabled.
+endif # end of ASPEED_ECC
+endif # end of ASPEED_AST2600
+endif # end of RAM || SPL_RAM
index af604f8..7ac10af 100644 (file)
@@ -1,3 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
-obj-$(CONFIG_ASPEED_AST2500) += sdram_ast2500.o
\ No newline at end of file
+obj-$(CONFIG_ASPEED_AST2500) += sdram_ast2500.o
+obj-$(CONFIG_ASPEED_AST2600) += sdram_ast2600.o
diff --git a/drivers/ram/aspeed/sdram_ast2600.c b/drivers/ram/aspeed/sdram_ast2600.c
new file mode 100644 (file)
index 0000000..fd42352
--- /dev/null
@@ -0,0 +1,1061 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) ASPEED Technology Inc.
+ */
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <errno.h>
+#include <ram.h>
+#include <regmap.h>
+#include <reset.h>
+#include <asm/io.h>
+#include <asm/arch/scu_ast2600.h>
+#include <asm/arch/sdram_ast2600.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <dt-bindings/clock/ast2600-clock.h>
+
+#define DDR_PHY_TBL_CHG_ADDR            0xaeeddeea
+#define DDR_PHY_TBL_END                 0xaeededed
+
+#if defined(CONFIG_ASPEED_DDR4_800)
+u32 ast2600_sdramphy_config[165] = {
+       0x1e6e0100,     // start address
+       0x00000000,     // phyr000
+       0x0c002062,     // phyr004
+       0x1a7a0063,     // phyr008
+       0x5a7a0063,     // phyr00c
+       0x1a7a0063,     // phyr010
+       0x1a7a0063,     // phyr014
+       0x20000000,     // phyr018
+       0x20000000,     // phyr01c
+       0x20000000,     // phyr020
+       0x20000000,     // phyr024
+       0x00000008,     // phyr028
+       0x00000000,     // phyr02c
+       0x00077600,     // phyr030
+       0x00000000,     // phyr034
+       0x00000000,     // phyr038
+       0x20000000,     // phyr03c
+       0x50506000,     // phyr040
+       0x50505050,     // phyr044
+       0x00002f07,     // phyr048
+       0x00003080,     // phyr04c
+       0x04000000,     // phyr050
+       0x00000200,     // phyr054
+       0x03140201,     // phyr058
+       0x04800000,     // phyr05c
+       0x0800044e,     // phyr060
+       0x00000000,     // phyr064
+       0x00180008,     // phyr068
+       0x00e00400,     // phyr06c
+       0x00140206,     // phyr070
+       0x1d4c0000,     // phyr074
+       0x493e0107,     // phyr078
+       0x08060404,     // phyr07c
+       0x90000a00,     // phyr080
+       0x06420618,     // phyr084
+       0x00001002,     // phyr088
+       0x05701016,     // phyr08c
+       0x10000000,     // phyr090
+       0xaeeddeea,     // change address
+       0x1e6e019c,     // new address
+       0x20202020,     // phyr09c
+       0x20202020,     // phyr0a0
+       0x00002020,     // phyr0a4
+       0x00002020,     // phyr0a8
+       0x00000001,     // phyr0ac
+       0xaeeddeea,     // change address
+       0x1e6e01cc,     // new address
+       0x01010101,     // phyr0cc
+       0x01010101,     // phyr0d0
+       0x80808080,     // phyr0d4
+       0x80808080,     // phyr0d8
+       0xaeeddeea,     // change address
+       0x1e6e0288,     // new address
+       0x80808080,     // phyr188
+       0x80808080,     // phyr18c
+       0x80808080,     // phyr190
+       0x80808080,     // phyr194
+       0xaeeddeea,     // change address
+       0x1e6e02f8,     // new address
+       0x90909090,     // phyr1f8
+       0x88888888,     // phyr1fc
+       0xaeeddeea,     // change address
+       0x1e6e0300,     // new address
+       0x00000000,     // phyr200
+       0xaeeddeea,     // change address
+       0x1e6e0194,     // new address
+       0x80118260,     // phyr094
+       0xaeeddeea,     // change address
+       0x1e6e019c,     // new address
+       0x20202020,     // phyr09c
+       0x20202020,     // phyr0a0
+       0x00002020,     // phyr0a4
+       0x80000000,     // phyr0a8
+       0x00000001,     // phyr0ac
+       0xaeeddeea,     // change address
+       0x1e6e0318,     // new address
+       0x09222719,     // phyr218
+       0x00aa4403,     // phyr21c
+       0xaeeddeea,     // change address
+       0x1e6e0198,     // new address
+       0x08060000,     // phyr098
+       0xaeeddeea,     // change address
+       0x1e6e01b0,     // new address
+       0x00000000,     // phyr0b0
+       0x00000000,     // phyr0b4
+       0x00000000,     // phyr0b8
+       0x00000000,     // phyr0bc
+       0x00000000,     // phyr0c0
+       0x00000000,     // phyr0c4
+       0x000aff2c,     // phyr0c8
+       0xaeeddeea,     // change address
+       0x1e6e01dc,     // new address
+       0x00080000,     // phyr0dc
+       0x00000000,     // phyr0e0
+       0xaa55aa55,     // phyr0e4
+       0x55aa55aa,     // phyr0e8
+       0xaaaa5555,     // phyr0ec
+       0x5555aaaa,     // phyr0f0
+       0xaa55aa55,     // phyr0f4
+       0x55aa55aa,     // phyr0f8
+       0xaaaa5555,     // phyr0fc
+       0x5555aaaa,     // phyr100
+       0xaa55aa55,     // phyr104
+       0x55aa55aa,     // phyr108
+       0xaaaa5555,     // phyr10c
+       0x5555aaaa,     // phyr110
+       0xaa55aa55,     // phyr114
+       0x55aa55aa,     // phyr118
+       0xaaaa5555,     // phyr11c
+       0x5555aaaa,     // phyr120
+       0x20202020,     // phyr124
+       0x20202020,     // phyr128
+       0x20202020,     // phyr12c
+       0x20202020,     // phyr130
+       0x20202020,     // phyr134
+       0x20202020,     // phyr138
+       0x20202020,     // phyr13c
+       0x20202020,     // phyr140
+       0x20202020,     // phyr144
+       0x20202020,     // phyr148
+       0x20202020,     // phyr14c
+       0x20202020,     // phyr150
+       0x20202020,     // phyr154
+       0x20202020,     // phyr158
+       0x20202020,     // phyr15c
+       0x20202020,     // phyr160
+       0x20202020,     // phyr164
+       0x20202020,     // phyr168
+       0x20202020,     // phyr16c
+       0x20202020,     // phyr170
+       0xaeeddeea,     // change address
+       0x1e6e0298,     // new address
+       0x20200800,     // phyr198
+       0x20202020,     // phyr19c
+       0x20202020,     // phyr1a0
+       0x20202020,     // phyr1a4
+       0x20202020,     // phyr1a8
+       0x20202020,     // phyr1ac
+       0x20202020,     // phyr1b0
+       0x20202020,     // phyr1b4
+       0x20202020,     // phyr1b8
+       0x20202020,     // phyr1bc
+       0x20202020,     // phyr1c0
+       0x20202020,     // phyr1c4
+       0x20202020,     // phyr1c8
+       0x20202020,     // phyr1cc
+       0x20202020,     // phyr1d0
+       0x20202020,     // phyr1d4
+       0x20202020,     // phyr1d8
+       0x20202020,     // phyr1dc
+       0x20202020,     // phyr1e0
+       0x20202020,     // phyr1e4
+       0x00002020,     // phyr1e8
+       0xaeeddeea,     // change address
+       0x1e6e0304,     // new address
+       0x00000800,     // phyr204
+       0xaeeddeea,     // change address
+       0x1e6e027c,     // new address
+       0x4e400000,     // phyr17c
+       0x59595959,     // phyr180
+       0x40404040,     // phyr184
+       0xaeeddeea,     // change address
+       0x1e6e02f4,     // new address
+       0x00000059,     // phyr1f4
+       0xaeededed,     // end
+};
+#else
+u32 ast2600_sdramphy_config[165] = {
+       0x1e6e0100,     // start address
+       0x00000000,     // phyr000
+       0x0c002062,     // phyr004
+       0x1a7a0063,     // phyr008
+       0x5a7a0063,     // phyr00c
+       0x1a7a0063,     // phyr010
+       0x1a7a0063,     // phyr014
+       0x20000000,     // phyr018
+       0x20000000,     // phyr01c
+       0x20000000,     // phyr020
+       0x20000000,     // phyr024
+       0x00000008,     // phyr028
+       0x00000000,     // phyr02c
+       0x00077600,     // phyr030
+       0x00000000,     // phyr034
+       0x00000000,     // phyr038
+       0x20000000,     // phyr03c
+       0x50506000,     // phyr040
+       0x50505050,     // phyr044
+       0x00002f07,     // phyr048
+       0x00003080,     // phyr04c
+       0x04000000,     // phyr050
+       0x00000200,     // phyr054
+       0x03140501,     // phyr058-rtt:40
+       0x04800000,     // phyr05c
+       0x0800044e,     // phyr060
+       0x00000000,     // phyr064
+       0x00180008,     // phyr068
+       0x00e00400,     // phyr06c
+       0x00140206,     // phyr070
+       0x1d4c0000,     // phyr074
+       0x493e0107,     // phyr078
+       0x08060404,     // phyr07c
+       0x90000a00,     // phyr080
+       0x06420c30,     // phyr084
+       0x00001002,     // phyr088
+       0x05701016,     // phyr08c
+       0x10000000,     // phyr090
+       0xaeeddeea,     // change address
+       0x1e6e019c,     // new address
+       0x20202020,     // phyr09c
+       0x20202020,     // phyr0a0
+       0x00002020,     // phyr0a4
+       0x00002020,     // phyr0a8
+       0x00000001,     // phyr0ac
+       0xaeeddeea,     // change address
+       0x1e6e01cc,     // new address
+       0x01010101,     // phyr0cc
+       0x01010101,     // phyr0d0
+       0x80808080,     // phyr0d4
+       0x80808080,     // phyr0d8
+       0xaeeddeea,     // change address
+       0x1e6e0288,     // new address
+       0x80808080,     // phyr188
+       0x80808080,     // phyr18c
+       0x80808080,     // phyr190
+       0x80808080,     // phyr194
+       0xaeeddeea,     // change address
+       0x1e6e02f8,     // new address
+       0x90909090,     // phyr1f8
+       0x88888888,     // phyr1fc
+       0xaeeddeea,     // change address
+       0x1e6e0300,     // new address
+       0x00000000,     // phyr200
+       0xaeeddeea,     // change address
+       0x1e6e0194,     // new address
+       0x801112e0,     // phyr094 - bit12=1,15=0,- write window is ok
+       0xaeeddeea,     // change address
+       0x1e6e019c,     // new address
+       0x20202020,     // phyr09c
+       0x20202020,     // phyr0a0
+       0x00002020,     // phyr0a4
+       0x80000000,     // phyr0a8
+       0x00000001,     // phyr0ac
+       0xaeeddeea,     // change address
+       0x1e6e0318,     // new address
+       0x09222719,     // phyr218
+       0x00aa4403,     // phyr21c
+       0xaeeddeea,     // change address
+       0x1e6e0198,     // new address
+       0x08060000,     // phyr098
+       0xaeeddeea,     // change address
+       0x1e6e01b0,     // new address
+       0x00000000,     // phyr0b0
+       0x00000000,     // phyr0b4
+       0x00000000,     // phyr0b8
+       0x00000000,     // phyr0bc
+       0x00000000,     // phyr0c0 - ori
+       0x00000000,     // phyr0c4
+       0x000aff2c,     // phyr0c8
+       0xaeeddeea,     // change address
+       0x1e6e01dc,     // new address
+       0x00080000,     // phyr0dc
+       0x00000000,     // phyr0e0
+       0xaa55aa55,     // phyr0e4
+       0x55aa55aa,     // phyr0e8
+       0xaaaa5555,     // phyr0ec
+       0x5555aaaa,     // phyr0f0
+       0xaa55aa55,     // phyr0f4
+       0x55aa55aa,     // phyr0f8
+       0xaaaa5555,     // phyr0fc
+       0x5555aaaa,     // phyr100
+       0xaa55aa55,     // phyr104
+       0x55aa55aa,     // phyr108
+       0xaaaa5555,     // phyr10c
+       0x5555aaaa,     // phyr110
+       0xaa55aa55,     // phyr114
+       0x55aa55aa,     // phyr118
+       0xaaaa5555,     // phyr11c
+       0x5555aaaa,     // phyr120
+       0x20202020,     // phyr124
+       0x20202020,     // phyr128
+       0x20202020,     // phyr12c
+       0x20202020,     // phyr130
+       0x20202020,     // phyr134
+       0x20202020,     // phyr138
+       0x20202020,     // phyr13c
+       0x20202020,     // phyr140
+       0x20202020,     // phyr144
+       0x20202020,     // phyr148
+       0x20202020,     // phyr14c
+       0x20202020,     // phyr150
+       0x20202020,     // phyr154
+       0x20202020,     // phyr158
+       0x20202020,     // phyr15c
+       0x20202020,     // phyr160
+       0x20202020,     // phyr164
+       0x20202020,     // phyr168
+       0x20202020,     // phyr16c
+       0x20202020,     // phyr170
+       0xaeeddeea,     // change address
+       0x1e6e0298,     // new address
+       0x20200800,     // phyr198
+       0x20202020,     // phyr19c
+       0x20202020,     // phyr1a0
+       0x20202020,     // phyr1a4
+       0x20202020,     // phyr1a8
+       0x20202020,     // phyr1ac
+       0x20202020,     // phyr1b0
+       0x20202020,     // phyr1b4
+       0x20202020,     // phyr1b8
+       0x20202020,     // phyr1bc
+       0x20202020,     // phyr1c0
+       0x20202020,     // phyr1c4
+       0x20202020,     // phyr1c8
+       0x20202020,     // phyr1cc
+       0x20202020,     // phyr1d0
+       0x20202020,     // phyr1d4
+       0x20202020,     // phyr1d8
+       0x20202020,     // phyr1dc
+       0x20202020,     // phyr1e0
+       0x20202020,     // phyr1e4
+       0x00002020,     // phyr1e8
+       0xaeeddeea,     // change address
+       0x1e6e0304,     // new address
+       0x00000800,     // phyr204
+       0xaeeddeea,     // change address
+       0x1e6e027c,     // new address
+       0x4e400000,     // phyr17c
+       0x59595959,     // phyr180
+       0x40404040,     // phyr184
+       0xaeeddeea,     // change address
+       0x1e6e02f4,     // new address
+       0x00000059,     // phyr1f4
+       0xaeededed,     // end
+};
+#endif
+
+/* MPLL configuration */
+#define SCU_MPLL_FREQ_400M     0x0008405F
+#define SCU_MPLL_EXT_400M      0x0000002F
+#define SCU_MPLL_FREQ_333M     0x00488299
+#define SCU_MPLL_EXT_333M      0x0000014C
+#define SCU_MPLL_FREQ_200M     0x0078007F
+#define SCU_MPLL_EXT_200M      0x0000003F
+#define SCU_MPLL_FREQ_100M     0x0078003F
+#define SCU_MPLL_EXT_100M      0x0000001F
+
+#if defined(CONFIG_ASPEED_DDR4_1600)
+#define SCU_MPLL_FREQ_CFG      SCU_MPLL_FREQ_400M
+#define SCU_MPLL_EXT_CFG       SCU_MPLL_EXT_400M
+#elif defined(CONFIG_ASPEED_DDR4_1333)
+#define SCU_MPLL_FREQ_CFG      SCU_MPLL_FREQ_333M
+#define SCU_MPLL_EXT_CFG       SCU_MPLL_EXT_333M
+#elif defined(CONFIG_ASPEED_DDR4_800)
+#define SCU_MPLL_FREQ_CFG      SCU_MPLL_FREQ_200M
+#define SCU_MPLL_EXT_CFG       SCU_MPLL_EXT_200M
+#elif defined(CONFIG_ASPEED_DDR4_400)
+#define SCU_MPLL_FREQ_CFG      SCU_MPLL_FREQ_100M
+#define SCU_MPLL_EXT_CFG       SCU_MPLL_EXT_100M
+#else
+#error "undefined DDR4 target rate\n"
+#endif
+
+/*
+ * AC timing and SDRAM mode register setting
+ * for real chip are derived from the model GDDR4-1600
+ */
+#define DDR4_MR01_MODE 0x03010510
+#define DDR4_MR23_MODE 0x00000000
+#define DDR4_MR45_MODE 0x04000000
+#define DDR4_MR6_MODE  0x00000400
+#define DDR4_TRFC_1600 0x467299f1
+#define DDR4_TRFC_1333 0x3a5f80c9
+#define DDR4_TRFC_800  0x23394c78
+#define DDR4_TRFC_400  0x111c263c
+
+#if defined(CONFIG_ASPEED_DDR4_1600)
+#define DDR4_TRFC              DDR4_TRFC_1600
+#define DDR4_PHY_TRAIN_TRFC    0xc30
+#elif defined(CONFIG_ASPEED_DDR4_1333)
+#define DDR4_TRFC              DDR4_TRFC_1333
+#define DDR4_PHY_TRAIN_TRFC    0xa25
+#elif defined(CONFIG_ASPEED_DDR4_800)
+#define DDR4_TRFC              DDR4_TRFC_800
+#define DDR4_PHY_TRAIN_TRFC    0x618
+#elif defined(CONFIG_ASPEED_DDR4_400)
+#define DDR4_TRFC              DDR4_TRFC_400
+#define DDR4_PHY_TRAIN_TRFC    0x30c
+#else
+#error "undefined tRFC setting"
+#endif
+
+/* supported SDRAM size */
+#define SDRAM_SIZE_1KB         (1024U)
+#define SDRAM_SIZE_1MB         (SDRAM_SIZE_1KB * SDRAM_SIZE_1KB)
+#define SDRAM_MIN_SIZE         (256 * SDRAM_SIZE_1MB)
+#define SDRAM_MAX_SIZE         (2048 * SDRAM_SIZE_1MB)
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static const u32 ddr4_ac_timing[4] = {
+       0x040e0307, 0x0f4711f1, 0x0e060304, 0x00001240 };
+static const u32 ddr_max_grant_params[4] = {
+       0x44444444, 0x44444444, 0x44444444, 0x44444444 };
+
+struct dram_info {
+       struct ram_info info;
+       struct clk ddr_clk;
+       struct ast2600_sdrammc_regs *regs;
+       struct ast2600_scu *scu;
+       struct ast2600_ddr_phy *phy;
+       void __iomem *phy_setting;
+       void __iomem *phy_status;
+       ulong clock_rate;
+};
+
+static void ast2600_sdramphy_kick_training(struct dram_info *info)
+{
+       u32 data;
+       struct ast2600_sdrammc_regs *regs = info->regs;
+
+       writel(SDRAM_PHYCTRL0_NRST, &regs->phy_ctrl[0]);
+       udelay(5);
+       writel(SDRAM_PHYCTRL0_NRST | SDRAM_PHYCTRL0_INIT, &regs->phy_ctrl[0]);
+       udelay(1000);
+
+       while (1) {
+               data = readl(&regs->phy_ctrl[0]) & SDRAM_PHYCTRL0_INIT;
+               if (~data)
+                       break;
+       }
+}
+
+/**
+ * @brief      load DDR-PHY configurations table to the PHY registers
+ * @param[in]  p_tbl - pointer to the configuration table
+ * @param[in]  info - pointer to the DRAM info struct
+ *
+ * There are two sets of MRS (Mode Registers) configuration in ast2600 memory
+ * system: one is in the SDRAM MC (memory controller) which is used in run
+ * time, and the other is in the DDR-PHY IP which is used during DDR-PHY
+ * training.
+ */
+static void ast2600_sdramphy_init(u32 *p_tbl, struct dram_info *info)
+{
+       u32 reg_base = (u32)info->phy_setting;
+       u32 addr = p_tbl[0];
+       u32 data;
+       int i = 1;
+
+       writel(0, &info->regs->phy_ctrl[0]);
+       udelay(10);
+
+       while (1) {
+               if (addr < reg_base) {
+                       debug("invalid DDR-PHY addr: 0x%08x\n", addr);
+                       break;
+               }
+               data = p_tbl[i++];
+
+               if (data == DDR_PHY_TBL_END) {
+                       break;
+               } else if (data == DDR_PHY_TBL_CHG_ADDR) {
+                       addr = p_tbl[i++];
+               } else {
+                       writel(data, addr);
+                       addr += 4;
+               }
+       }
+
+       data = readl(info->phy_setting + 0x84) & ~GENMASK(16, 0);
+       data |= DDR4_PHY_TRAIN_TRFC;
+       writel(data, info->phy_setting + 0x84);
+}
+
+static int ast2600_sdramphy_check_status(struct dram_info *info)
+{
+       u32 value, tmp;
+       u32 reg_base = (u32)info->phy_status;
+       int need_retrain = 0;
+
+       debug("\nSDRAM PHY training report:\n");
+
+       /* training status */
+       value = readl(reg_base + 0x00);
+       debug("rO_DDRPHY_reg offset 0x00 = 0x%08x\n", value);
+
+       if (value & BIT(3))
+               debug("\tinitial PVT calibration fail\n");
+
+       if (value & BIT(5))
+               debug("\truntime calibration fail\n");
+
+       /* PU & PD */
+       value = readl(reg_base + 0x30);
+       debug("rO_DDRPHY_reg offset 0x30 = 0x%08x\n", value);
+       debug("  PU = 0x%02x\n", value & 0xff);
+       debug("  PD = 0x%02x\n", (value >> 16) & 0xff);
+
+       /* read eye window */
+       value = readl(reg_base + 0x68);
+       if (0 == (value & GENMASK(7, 0)))
+               need_retrain = 1;
+
+       debug("rO_DDRPHY_reg offset 0x68 = 0x%08x\n", value);
+       debug("  rising edge of read data eye training pass window\n");
+       tmp = (((value & GENMASK(7, 0)) >> 0) * 100) / 255;
+       debug("    B0:%d%%\n", tmp);
+       tmp = (((value & GENMASK(15, 8)) >> 8) * 100) / 255;
+       debug("    B1:%d%%\n", tmp);
+
+       value = readl(reg_base + 0xC8);
+       debug("rO_DDRPHY_reg offset 0xC8 = 0x%08x\n", value);
+       debug("  falling edge of read data eye training pass window\n");
+       tmp = (((value & GENMASK(7, 0)) >> 0) * 100) / 255;
+       debug("    B0:%d%%\n", tmp);
+       tmp = (((value & GENMASK(15, 8)) >> 8) * 100) / 255;
+       debug("    B1:%d%%\n", tmp);
+
+       /* write eye window */
+       value = readl(reg_base + 0x7c);
+       if (0 == (value & GENMASK(7, 0)))
+               need_retrain = 1;
+
+       debug("rO_DDRPHY_reg offset 0x7C = 0x%08x\n", value);
+       debug("  rising edge of write data eye training pass window\n");
+       tmp = (((value & GENMASK(7, 0)) >> 0) * 100) / 255;
+       debug("    B0:%d%%\n", tmp);
+       tmp = (((value & GENMASK(15, 8)) >> 8) * 100) / 255;
+       debug("    B1:%d%%\n", tmp);
+
+       /* read Vref training result */
+       value = readl(reg_base + 0x88);
+       debug("rO_DDRPHY_reg offset 0x88 = 0x%08x\n", value);
+       debug("  read Vref training result\n");
+       tmp = (((value & GENMASK(7, 0)) >> 0) * 100) / 127;
+       debug("    B0:%d%%\n", tmp);
+       tmp = (((value & GENMASK(15, 8)) >> 8) * 100) / 127;
+       debug("    B1:%d%%\n", tmp);
+
+       /* write Vref training result */
+       value = readl(reg_base + 0x90);
+       debug("rO_DDRPHY_reg offset 0x90 = 0x%08x\n", value);
+
+       /* gate train */
+       value = readl(reg_base + 0x50);
+       if ((0 == (value & GENMASK(15, 0))) ||
+           (0 == (value & GENMASK(31, 16)))) {
+               need_retrain = 1;
+       }
+
+       debug("rO_DDRPHY_reg offset 0x50 = 0x%08x\n", value);
+
+       return need_retrain;
+}
+
+#ifndef CONFIG_ASPEED_BYPASS_SELFTEST
+#define MC_TEST_PATTERN_N 8
+static u32 as2600_sdrammc_test_pattern[MC_TEST_PATTERN_N] = {
+       0xcc33cc33, 0xff00ff00, 0xaa55aa55, 0x88778877,
+       0x92cc4d6e, 0x543d3cde, 0xf1e843c7, 0x7c61d253 };
+
+#define TIMEOUT_DRAM   5000000
+int ast2600_sdrammc_dg_test(struct dram_info *info, unsigned int datagen, u32 mode)
+{
+       unsigned int data;
+       unsigned int timeout = 0;
+       struct ast2600_sdrammc_regs *regs = info->regs;
+
+       writel(0, &regs->ecc_test_ctrl);
+
+       if (mode == 0)
+               writel(0x00000085 | (datagen << 3), &regs->ecc_test_ctrl);
+       else
+               writel(0x000000C1 | (datagen << 3), &regs->ecc_test_ctrl);
+
+       do {
+               data = readl(&regs->ecc_test_ctrl) & GENMASK(13, 12);
+
+               if (data & BIT(13))
+                       return 0;
+
+               if (++timeout > TIMEOUT_DRAM) {
+                       debug("Timeout!!\n");
+                       writel(0, &regs->ecc_test_ctrl);
+                       return -1;
+               }
+       } while (!data);
+
+       writel(0, &regs->ecc_test_ctrl);
+
+       return 0;
+}
+
+int ast2600_sdrammc_cbr_test(struct dram_info *info)
+{
+       u32 i;
+       struct ast2600_sdrammc_regs *regs = info->regs;
+
+       clrsetbits_le32(&regs->test_addr, GENMASK(30, 4), 0x7ffff0);
+
+       /* single */
+       for (i = 0; i < 8; i++)
+               if (ast2600_sdrammc_dg_test(info, i, 0))
+                       return -1;
+
+       /* burst */
+       for (i = 0; i < 8; i++)
+               if (ast2600_sdrammc_dg_test(info, i, i))
+                       return -1;
+
+       return 0;
+}
+
+static int ast2600_sdrammc_test(struct dram_info *info)
+{
+       struct ast2600_sdrammc_regs *regs = info->regs;
+
+       u32 pass_cnt = 0;
+       u32 fail_cnt = 0;
+       u32 target_cnt = 2;
+       u32 test_cnt = 0;
+       u32 pattern;
+       u32 i = 0;
+       bool finish = false;
+
+       debug("sdram mc test:\n");
+       while (!finish) {
+               pattern = as2600_sdrammc_test_pattern[i++];
+               i = i % MC_TEST_PATTERN_N;
+               debug("  pattern = %08X : ", pattern);
+               writel(pattern, &regs->test_init_val);
+
+               if (ast2600_sdrammc_cbr_test(info)) {
+                       debug("fail\n");
+                       fail_cnt++;
+               } else {
+                       debug("pass\n");
+                       pass_cnt++;
+               }
+
+               if (++test_cnt == target_cnt)
+                       finish = true;
+       }
+       debug("statistics: pass/fail/total:%d/%d/%d\n", pass_cnt, fail_cnt,
+             target_cnt);
+
+       return fail_cnt;
+}
+#endif
+
+/*
+ * scu500[14:13]
+ *     2b'00: VGA memory size = 16MB
+ *     2b'01: VGA memory size = 16MB
+ *     2b'10: VGA memory size = 32MB
+ *     2b'11: VGA memory size = 64MB
+ *
+ * mcr04[3:2]
+ *     2b'00: VGA memory size = 8MB
+ *     2b'01: VGA memory size = 16MB
+ *     2b'10: VGA memory size = 32MB
+ *     2b'11: VGA memory size = 64MB
+ */
+static size_t ast2600_sdrammc_get_vga_mem_size(struct dram_info *info)
+{
+       u32 vga_hwconf;
+       size_t vga_mem_size_base = 8 * 1024 * 1024;
+
+       vga_hwconf =
+               (readl(&info->scu->hwstrap1) & SCU_HWSTRAP1_VGA_MEM_MASK) >>
+                SCU_HWSTRAP1_VGA_MEM_SHIFT;
+
+       if (vga_hwconf == 0) {
+               vga_hwconf = 1;
+               writel(vga_hwconf << SCU_HWSTRAP1_VGA_MEM_SHIFT,
+                      &info->scu->hwstrap1);
+       }
+
+       clrsetbits_le32(&info->regs->config, SDRAM_CONF_VGA_SIZE_MASK,
+                       ((vga_hwconf << SDRAM_CONF_VGA_SIZE_SHIFT) &
+                        SDRAM_CONF_VGA_SIZE_MASK));
+
+       /* no need to reserve VGA memory if efuse[VGA disable] is set */
+       if (readl(&info->scu->efuse) & SCU_EFUSE_DIS_VGA)
+               return 0;
+
+       return vga_mem_size_base << vga_hwconf;
+}
+
+/*
+ * Find out RAM size and save it in dram_info
+ *
+ * The procedure is taken from Aspeed SDK
+ */
+static void ast2600_sdrammc_calc_size(struct dram_info *info)
+{
+       /* The controller supports 256/512/1024/2048 MB ram */
+       size_t ram_size = SDRAM_MIN_SIZE;
+       const int write_test_offset = 0x100000;
+       u32 test_pattern = 0xdeadbeef;
+       u32 cap_param = SDRAM_CONF_CAP_2048M;
+       u32 refresh_timing_param = DDR4_TRFC;
+       const u32 write_addr_base = CONFIG_SYS_SDRAM_BASE + write_test_offset;
+
+       for (ram_size = SDRAM_MAX_SIZE; ram_size > SDRAM_MIN_SIZE;
+            ram_size >>= 1) {
+               writel(test_pattern, write_addr_base + (ram_size >> 1));
+               test_pattern = (test_pattern >> 4) | (test_pattern << 28);
+       }
+
+       /* One last write to overwrite all wrapped values */
+       writel(test_pattern, write_addr_base);
+
+       /* Reset the pattern and see which value was really written */
+       test_pattern = 0xdeadbeef;
+       for (ram_size = SDRAM_MAX_SIZE; ram_size > SDRAM_MIN_SIZE;
+            ram_size >>= 1) {
+               if (readl(write_addr_base + (ram_size >> 1)) == test_pattern)
+                       break;
+
+               --cap_param;
+               refresh_timing_param >>= 8;
+               test_pattern = (test_pattern >> 4) | (test_pattern << 28);
+       }
+
+       clrsetbits_le32(&info->regs->ac_timing[1],
+                       (SDRAM_AC_TRFC_MASK << SDRAM_AC_TRFC_SHIFT),
+                       ((refresh_timing_param & SDRAM_AC_TRFC_MASK)
+                        << SDRAM_AC_TRFC_SHIFT));
+
+       info->info.base = CONFIG_SYS_SDRAM_BASE;
+       info->info.size = ram_size - ast2600_sdrammc_get_vga_mem_size(info);
+
+       clrsetbits_le32(&info->regs->config, SDRAM_CONF_CAP_MASK,
+                       ((cap_param << SDRAM_CONF_CAP_SHIFT) & SDRAM_CONF_CAP_MASK));
+}
+
+static int ast2600_sdrammc_init_ddr4(struct dram_info *info)
+{
+       const u32 power_ctrl = MCR34_CKE_EN | MCR34_AUTOPWRDN_EN |
+               MCR34_MREQ_BYPASS_DIS | MCR34_RESETN_DIS |
+               MCR34_ODT_EN | MCR34_ODT_AUTO_ON |
+               (0x1 << MCR34_ODT_EXT_SHIFT);
+
+       /* init SDRAM-PHY only on real chip */
+       ast2600_sdramphy_init(ast2600_sdramphy_config, info);
+       writel((MCR34_CKE_EN | MCR34_MREQI_DIS | MCR34_RESETN_DIS),
+              &info->regs->power_ctrl);
+       udelay(5);
+       ast2600_sdramphy_kick_training(info);
+       udelay(500);
+       writel(SDRAM_RESET_DLL_ZQCL_EN, &info->regs->refresh_timing);
+
+       writel(MCR30_SET_MR(3), &info->regs->mode_setting_control);
+       writel(MCR30_SET_MR(6), &info->regs->mode_setting_control);
+       writel(MCR30_SET_MR(5), &info->regs->mode_setting_control);
+       writel(MCR30_SET_MR(4), &info->regs->mode_setting_control);
+       writel(MCR30_SET_MR(2), &info->regs->mode_setting_control);
+       writel(MCR30_SET_MR(1), &info->regs->mode_setting_control);
+       writel(MCR30_SET_MR(0) | MCR30_RESET_DLL_DELAY_EN,
+              &info->regs->mode_setting_control);
+
+       writel(SDRAM_REFRESH_EN | SDRAM_RESET_DLL_ZQCL_EN |
+              (0x5f << SDRAM_REFRESH_PERIOD_SHIFT),
+              &info->regs->refresh_timing);
+
+       /* wait self-refresh idle */
+       while (readl(&info->regs->power_ctrl) &
+              MCR34_SELF_REFRESH_STATUS_MASK)
+               ;
+
+       writel(SDRAM_REFRESH_EN | SDRAM_LOW_PRI_REFRESH_EN |
+              SDRAM_REFRESH_ZQCS_EN |
+              (0x5f << SDRAM_REFRESH_PERIOD_SHIFT) |
+              (0x42aa << SDRAM_REFRESH_PERIOD_ZQCS_SHIFT),
+              &info->regs->refresh_timing);
+
+       writel(power_ctrl, &info->regs->power_ctrl);
+       udelay(500);
+
+       return 0;
+}
+
+static void ast2600_sdrammc_unlock(struct dram_info *info)
+{
+       writel(SDRAM_UNLOCK_KEY, &info->regs->protection_key);
+       while (!readl(&info->regs->protection_key))
+               ;
+}
+
+static void ast2600_sdrammc_lock(struct dram_info *info)
+{
+       writel(~SDRAM_UNLOCK_KEY, &info->regs->protection_key);
+       while (readl(&info->regs->protection_key))
+               ;
+}
+
+static void ast2600_sdrammc_common_init(struct ast2600_sdrammc_regs *regs)
+{
+       int i;
+
+       writel(MCR34_MREQI_DIS | MCR34_RESETN_DIS, &regs->power_ctrl);
+       writel(SDRAM_VIDEO_UNLOCK_KEY, &regs->gm_protection_key);
+       writel(0x10 << MCR38_RW_MAX_GRANT_CNT_RQ_SHIFT,
+              &regs->arbitration_ctrl);
+       writel(0xFFBBFFF4, &regs->req_limit_mask);
+
+       for (i = 0; i < ARRAY_SIZE(ddr_max_grant_params); ++i)
+               writel(ddr_max_grant_params[i], &regs->max_grant_len[i]);
+
+       writel(MCR50_RESET_ALL_INTR, &regs->intr_ctrl);
+
+       writel(0x07FFFFFF, &regs->ecc_range_ctrl);
+
+       writel(0, &regs->ecc_test_ctrl);
+       writel(0x80000001, &regs->test_addr);
+       writel(0, &regs->test_fail_dq_bit);
+       writel(0, &regs->test_init_val);
+
+       writel(0xFFFFFFFF, &regs->req_input_ctrl);
+       writel(0, &regs->req_high_pri_ctrl);
+
+       udelay(600);
+
+#ifdef CONFIG_ASPEED_DDR4_DUALX8
+       writel(0x37, &regs->config);
+#else
+       writel(0x17, &regs->config);
+#endif
+
+       /* load controller setting */
+       for (i = 0; i < ARRAY_SIZE(ddr4_ac_timing); ++i)
+               writel(ddr4_ac_timing[i], &regs->ac_timing[i]);
+
+       writel(DDR4_MR01_MODE, &regs->mr01_mode_setting);
+       writel(DDR4_MR23_MODE, &regs->mr23_mode_setting);
+       writel(DDR4_MR45_MODE, &regs->mr45_mode_setting);
+       writel(DDR4_MR6_MODE, &regs->mr6_mode_setting);
+}
+
+/*
+ * Update size info according to the ECC HW setting
+ *
+ * Assume SDRAM has been initialized by SPL or the host.  To get the RAM size, we
+ * don't need to calculate the ECC size again but read from MCR04 and derive the
+ * size from its value.
+ */
+static void ast2600_sdrammc_update_size(struct dram_info *info)
+{
+       struct ast2600_sdrammc_regs *regs = info->regs;
+       u32 conf = readl(&regs->config);
+       u32 cap_param;
+       size_t ram_size = SDRAM_MAX_SIZE;
+       size_t hw_size;
+
+       cap_param = (conf & SDRAM_CONF_CAP_MASK) >> SDRAM_CONF_CAP_SHIFT;
+       switch (cap_param) {
+       case SDRAM_CONF_CAP_2048M:
+               ram_size = 2048 * SDRAM_SIZE_1MB;
+               break;
+       case SDRAM_CONF_CAP_1024M:
+               ram_size = 1024 * SDRAM_SIZE_1MB;
+               break;
+       case SDRAM_CONF_CAP_512M:
+               ram_size = 512 * SDRAM_SIZE_1MB;
+               break;
+       case SDRAM_CONF_CAP_256M:
+               ram_size = 256 * SDRAM_SIZE_1MB;
+               break;
+       }
+
+       info->info.base = CONFIG_SYS_SDRAM_BASE;
+       info->info.size = ram_size - ast2600_sdrammc_get_vga_mem_size(info);
+
+       if (0 == (conf & SDRAM_CONF_ECC_SETUP))
+               return;
+
+       hw_size = readl(&regs->ecc_range_ctrl) & SDRAM_ECC_RANGE_ADDR_MASK;
+       hw_size += (1 << SDRAM_ECC_RANGE_ADDR_SHIFT);
+
+       info->info.size = hw_size;
+}
+
+#ifdef CONFIG_ASPEED_ECC
+static void ast2600_sdrammc_ecc_enable(struct dram_info *info)
+{
+       struct ast2600_sdrammc_regs *regs = info->regs;
+       size_t conf_size;
+       u32 reg;
+
+       conf_size = CONFIG_ASPEED_ECC_SIZE * SDRAM_SIZE_1MB;
+       if (conf_size > info->info.size) {
+               printf("warning: ECC configured %dMB but actual size is %dMB\n",
+                      CONFIG_ASPEED_ECC_SIZE,
+                      info->info.size / SDRAM_SIZE_1MB);
+               conf_size = info->info.size;
+       } else if (conf_size == 0) {
+               conf_size = info->info.size;
+       }
+
+       info->info.size = (((conf_size / 9) * 8) >> 20) << 20;
+       writel(((info->info.size >> 20) - 1) << 20, &regs->ecc_range_ctrl);
+       reg = readl(&regs->config) | SDRAM_CONF_ECC_SETUP;
+       writel(reg, &regs->config);
+
+       writel(0, &regs->test_init_val);
+       writel(0x80000001, &regs->test_addr);
+       writel(0x221, &regs->ecc_test_ctrl);
+       while (0 == (readl(&regs->ecc_test_ctrl) & BIT(12)))
+               ;
+       writel(0, &regs->ecc_test_ctrl);
+       writel(BIT(31), &regs->intr_ctrl);
+       writel(0, &regs->intr_ctrl);
+}
+#endif
+
+static int ast2600_sdrammc_probe(struct udevice *dev)
+{
+       int ret;
+       u32 reg;
+       struct dram_info *priv = (struct dram_info *)dev_get_priv(dev);
+       struct ast2600_sdrammc_regs *regs = priv->regs;
+       struct udevice *clk_dev;
+
+       /* find SCU base address from clock device */
+       ret = uclass_get_device_by_driver(UCLASS_CLK,
+                                         DM_DRIVER_GET(aspeed_ast2600_scu), &clk_dev);
+       if (ret) {
+               debug("clock device not defined\n");
+               return ret;
+       }
+
+       priv->scu = devfdt_get_addr_ptr(clk_dev);
+       if (IS_ERR(priv->scu)) {
+               debug("%s(): can't get SCU\n", __func__);
+               return PTR_ERR(priv->scu);
+       }
+
+       if (readl(&priv->scu->dram_hdshk) & SCU_DRAM_HDSHK_RDY) {
+               printf("already initialized, ");
+               ast2600_sdrammc_update_size(priv);
+               return 0;
+       }
+
+       reg = readl(&priv->scu->mpll);
+       reg &= ~(SCU_PLL_BYPASS | SCU_PLL_DIV_MASK |
+                SCU_PLL_DENUM_MASK | SCU_PLL_NUM_MASK);
+       reg |= (SCU_PLL_RST | SCU_PLL_OFF | SCU_MPLL_FREQ_CFG);
+       writel(reg, &priv->scu->mpll);
+       writel(SCU_MPLL_EXT_CFG, &priv->scu->mpll_ext);
+       udelay(100);
+       reg &= ~(SCU_PLL_RST | SCU_PLL_OFF);
+       writel(reg, &priv->scu->mpll);
+
+       while ((readl(&priv->scu->mpll_ext) & BIT(31)) == 0)
+               ;
+
+       ast2600_sdrammc_unlock(priv);
+       ast2600_sdrammc_common_init(regs);
+L_ast2600_sdramphy_train:
+       ast2600_sdrammc_init_ddr4(priv);
+
+       /* make sure DDR-PHY is ready before access */
+       do {
+               reg = readl(priv->phy_status) & BIT(1);
+       } while (reg == 0);
+
+       if (ast2600_sdramphy_check_status(priv) != 0) {
+               printf("DDR4 PHY training fail, retrain\n");
+               goto L_ast2600_sdramphy_train;
+       }
+
+       ast2600_sdrammc_calc_size(priv);
+
+#ifndef CONFIG_ASPEED_BYPASS_SELFTEST
+       if (ast2600_sdrammc_test(priv) != 0) {
+               printf("%s: DDR4 init fail\n", __func__);
+               return -EINVAL;
+       }
+#endif
+
+#ifdef CONFIG_ASPEED_ECC
+       ast2600_sdrammc_ecc_enable(priv);
+#endif
+
+       writel(readl(&priv->scu->dram_hdshk) | SCU_DRAM_HDSHK_RDY,
+              &priv->scu->dram_hdshk);
+
+       clrbits_le32(&regs->intr_ctrl, MCR50_RESET_ALL_INTR);
+       ast2600_sdrammc_lock(priv);
+       return 0;
+}
+
+static int ast2600_sdrammc_of_to_plat(struct udevice *dev)
+{
+       struct dram_info *priv = dev_get_priv(dev);
+
+       priv->regs = (void *)(uintptr_t)devfdt_get_addr_index(dev, 0);
+       priv->phy_setting = (void *)(uintptr_t)devfdt_get_addr_index(dev, 1);
+       priv->phy_status = (void *)(uintptr_t)devfdt_get_addr_index(dev, 2);
+
+       priv->clock_rate = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
+                                         "clock-frequency", 0);
+       if (!priv->clock_rate) {
+               debug("DDR Clock Rate not defined\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int ast2600_sdrammc_get_info(struct udevice *dev, struct ram_info *info)
+{
+       struct dram_info *priv = dev_get_priv(dev);
+
+       *info = priv->info;
+
+       return 0;
+}
+
+static struct ram_ops ast2600_sdrammc_ops = {
+       .get_info = ast2600_sdrammc_get_info,
+};
+
+static const struct udevice_id ast2600_sdrammc_ids[] = {
+       { .compatible = "aspeed,ast2600-sdrammc" },
+       { }
+};
+
+U_BOOT_DRIVER(sdrammc_ast2600) = {
+       .name = "aspeed_ast2600_sdrammc",
+       .id = UCLASS_RAM,
+       .of_match = ast2600_sdrammc_ids,
+       .ops = &ast2600_sdrammc_ops,
+       .of_to_plat = ast2600_sdrammc_of_to_plat,
+       .probe = ast2600_sdrammc_probe,
+       .priv_auto = sizeof(struct dram_info),
+};
index 33c2736..f5b3f88 100644 (file)
@@ -81,6 +81,15 @@ config RESET_AST2500
          Say Y if you want to control reset signals of different peripherals
          through System Control Unit (SCU).
 
+config RESET_AST2600
+       bool "Reset controller driver for AST2600 SoCs"
+       depends on DM_RESET
+       default y if ASPEED_AST2600
+       help
+         Support for reset controller on AST2600 SoC.
+         Say Y if you want to control reset signals of different peripherals
+         through System Control Unit (SCU).
+
 config RESET_ROCKCHIP
        bool "Reset controller driver for Rockchip SoCs"
        depends on DM_RESET && ARCH_ROCKCHIP && CLK
index fa52aa3..8a0f528 100644 (file)
@@ -15,6 +15,7 @@ obj-$(CONFIG_RESET_HSDK) += reset-hsdk.o
 obj-$(CONFIG_RESET_BCM6345) += reset-bcm6345.o
 obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
 obj-$(CONFIG_RESET_AST2500) += reset-ast2500.o
+obj-$(CONFIG_RESET_AST2600) += reset-ast2600.o
 obj-$(CONFIG_RESET_ROCKCHIP) += reset-rockchip.o
 obj-$(CONFIG_RESET_MESON) += reset-meson.o
 obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o
diff --git a/drivers/reset/reset-ast2600.c b/drivers/reset/reset-ast2600.c
new file mode 100644 (file)
index 0000000..f64adaf
--- /dev/null
@@ -0,0 +1,108 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2020 ASPEED Technology Inc.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <log.h>
+#include <misc.h>
+#include <reset.h>
+#include <reset-uclass.h>
+#include <linux/err.h>
+#include <asm/io.h>
+#include <asm/arch/scu_ast2600.h>
+
+struct ast2600_reset_priv {
+       struct ast2600_scu *scu;
+};
+
+static int ast2600_reset_request(struct reset_ctl *reset_ctl)
+{
+       debug("%s(reset_ctl=%p) (dev=%p, id=%lu)\n", __func__, reset_ctl,
+             reset_ctl->dev, reset_ctl->id);
+
+       return 0;
+}
+
+static int ast2600_reset_free(struct reset_ctl *reset_ctl)
+{
+       debug("%s(reset_ctl=%p) (dev=%p, id=%lu)\n", __func__, reset_ctl,
+             reset_ctl->dev, reset_ctl->id);
+
+       return 0;
+}
+
+static int ast2600_reset_assert(struct reset_ctl *reset_ctl)
+{
+       struct ast2600_reset_priv *priv = dev_get_priv(reset_ctl->dev);
+       struct ast2600_scu *scu = priv->scu;
+
+       debug("%s: reset_ctl->id: %lu\n", __func__, reset_ctl->id);
+
+       if (reset_ctl->id < 32)
+               writel(BIT(reset_ctl->id), scu->modrst_ctrl1);
+       else
+               writel(BIT(reset_ctl->id - 32), scu->modrst_ctrl2);
+
+       return 0;
+}
+
+static int ast2600_reset_deassert(struct reset_ctl *reset_ctl)
+{
+       struct ast2600_reset_priv *priv = dev_get_priv(reset_ctl->dev);
+       struct ast2600_scu *scu = priv->scu;
+
+       debug("%s: reset_ctl->id: %lu\n", __func__, reset_ctl->id);
+
+       if (reset_ctl->id < 32)
+               writel(BIT(reset_ctl->id), scu->modrst_clr1);
+       else
+               writel(BIT(reset_ctl->id - 32), scu->modrst_clr2);
+
+       return 0;
+}
+
+static int ast2600_reset_probe(struct udevice *dev)
+{
+       int rc;
+       struct ast2600_reset_priv *priv = dev_get_priv(dev);
+       struct udevice *scu_dev;
+
+       /* get SCU base from clock device */
+       rc = uclass_get_device_by_driver(UCLASS_CLK,
+                                        DM_DRIVER_GET(aspeed_ast2600_scu), &scu_dev);
+       if (rc) {
+               debug("%s: clock device not found, rc=%d\n", __func__, rc);
+               return rc;
+       }
+
+       priv->scu = devfdt_get_addr_ptr(scu_dev);
+       if (IS_ERR_OR_NULL(priv->scu)) {
+               debug("%s: invalid SCU base pointer\n", __func__);
+               return PTR_ERR(priv->scu);
+       }
+
+       return 0;
+}
+
+static const struct udevice_id ast2600_reset_ids[] = {
+       { .compatible = "aspeed,ast2600-reset" },
+       { }
+};
+
+struct reset_ops ast2600_reset_ops = {
+       .request = ast2600_reset_request,
+       .rfree = ast2600_reset_free,
+       .rst_assert = ast2600_reset_assert,
+       .rst_deassert = ast2600_reset_deassert,
+};
+
+U_BOOT_DRIVER(ast2600_reset) = {
+       .name = "ast2600_reset",
+       .id = UCLASS_RESET,
+       .of_match = ast2600_reset_ids,
+       .probe = ast2600_reset_probe,
+       .ops = &ast2600_reset_ops,
+       .priv_auto = sizeof(struct ast2600_reset_priv),
+};
index ee941c7..d747ed0 100644 (file)
@@ -12,6 +12,7 @@
 #include <asm/io.h>
 #include <asm/arch/wdt.h>
 #include <linux/err.h>
+#include <hang.h>
 
 static int ast_sysreset_request(struct udevice *dev, enum sysreset_t type)
 {
@@ -33,11 +34,15 @@ static int ast_sysreset_request(struct udevice *dev, enum sysreset_t type)
                return -EPROTONOSUPPORT;
        }
 
+#if !defined(CONFIG_SPL_BUILD)
        ret = wdt_expire_now(wdt, reset_mode);
        if (ret) {
                debug("Sysreset failed: %d", ret);
                return ret;
        }
+#else
+       hang();
+#endif
 
        return -EINPROGRESS;
 }
index 448a76a..f6b97f8 100644 (file)
@@ -61,6 +61,16 @@ static int mtk_timer_probe(struct udevice *dev)
        if (!uc_priv->clock_rate)
                return -EINVAL;
 
+       /*
+        * Initialize the timer:
+        * 1. set clock source to system clock with clock divider setting to 1
+        * 2. set timer mode to free running
+        * 3. reset timer counter to 0 then enable the timer
+        */
+       writel(GPT4_CLK_SYS | GPT4_CLK_DIV1, priv->base + MTK_GPT4_CLK);
+       writel(GPT4_FREERUN | GPT4_CLEAR | GPT4_ENABLE,
+              priv->base + MTK_GPT4_CTRL);
+
        return 0;
 }
 
index 4532a40..d5edabf 100644 (file)
@@ -86,6 +86,15 @@ config WDT_ASPEED
          It currently does not support Boot Flash Addressing Mode Detection or
          Second Boot.
 
+config WDT_AST2600
+       bool "Aspeed AST2600 watchdog timer support"
+       depends on WDT
+       default y if ASPEED_AST2600
+       help
+         Select this to enable watchdog timer for Aspeed ast2500/ast2400 devices.
+         The watchdog timer is stopped when initialized. It performs reset, either
+         full SoC reset or CPU or just some peripherals, based on the flags.
+
 config WDT_AT91
        bool "AT91 watchdog timer support"
        depends on WDT
index 01b8231..cbb6d84 100644 (file)
@@ -19,6 +19,7 @@ obj-$(CONFIG_$(SPL_TPL_)WDT) += wdt-uclass.o
 obj-$(CONFIG_WDT_SANDBOX) += sandbox_wdt.o
 obj-$(CONFIG_WDT_ARMADA_37XX) += armada-37xx-wdt.o
 obj-$(CONFIG_WDT_ASPEED) += ast_wdt.o
+obj-$(CONFIG_WDT_AST2600) += ast2600_wdt.o
 obj-$(CONFIG_WDT_BCM6345) += bcm6345_wdt.o
 obj-$(CONFIG_WDT_CORTINA) += cortina_wdt.o
 obj-$(CONFIG_WDT_ORION) += orion_wdt.o
diff --git a/drivers/watchdog/ast2600_wdt.c b/drivers/watchdog/ast2600_wdt.c
new file mode 100644 (file)
index 0000000..bc98420
--- /dev/null
@@ -0,0 +1,110 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2020 Aspeed Technology, Inc
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <log.h>
+#include <wdt.h>
+#include <asm/io.h>
+#include <asm/arch/wdt_ast2600.h>
+#include <linux/err.h>
+
+struct ast2600_wdt_priv {
+       struct ast2600_wdt *regs;
+};
+
+static int ast2600_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
+{
+       struct ast2600_wdt_priv *priv = dev_get_priv(dev);
+       struct ast2600_wdt *wdt = priv->regs;
+
+       /* WDT counts in the 1MHz frequency, namely 1us */
+       writel((u32)(timeout_ms * 1000), &wdt->counter_reload_val);
+       writel(WDT_COUNTER_RESTART_VAL, &wdt->counter_restart);
+       writel(WDT_CTRL_EN | WDT_CTRL_RESET, &wdt->ctrl);
+
+       return 0;
+}
+
+static int ast2600_wdt_stop(struct udevice *dev)
+{
+       struct ast2600_wdt_priv *priv = dev_get_priv(dev);
+       struct ast2600_wdt *wdt = priv->regs;
+
+       clrbits_le32(&wdt->ctrl, WDT_CTRL_EN);
+
+       writel(WDT_RESET_MASK1_DEFAULT, &wdt->reset_mask1);
+       writel(WDT_RESET_MASK2_DEFAULT, &wdt->reset_mask2);
+
+       return 0;
+}
+
+static int ast2600_wdt_reset(struct udevice *dev)
+{
+       struct ast2600_wdt_priv *priv = dev_get_priv(dev);
+       struct ast2600_wdt *wdt = priv->regs;
+
+       writel(WDT_COUNTER_RESTART_VAL, &wdt->counter_restart);
+
+       return 0;
+}
+
+static int ast2600_wdt_expire_now(struct udevice *dev, ulong flags)
+{
+       int ret;
+       struct ast2600_wdt_priv *priv = dev_get_priv(dev);
+       struct ast2600_wdt *wdt = priv->regs;
+
+       ret = ast2600_wdt_start(dev, 1, flags);
+       if (ret)
+               return ret;
+
+       while (readl(&wdt->ctrl) & WDT_CTRL_EN)
+               ;
+
+       return ast2600_wdt_stop(dev);
+}
+
+static int ast2600_wdt_of_to_plat(struct udevice *dev)
+{
+       struct ast2600_wdt_priv *priv = dev_get_priv(dev);
+
+       priv->regs = dev_read_addr_ptr(dev);
+       if (!priv->regs)
+               return -EINVAL;
+
+       return 0;
+}
+
+static const struct wdt_ops ast2600_wdt_ops = {
+       .start = ast2600_wdt_start,
+       .reset = ast2600_wdt_reset,
+       .stop = ast2600_wdt_stop,
+       .expire_now = ast2600_wdt_expire_now,
+};
+
+static const struct udevice_id ast2600_wdt_ids[] = {
+       { .compatible = "aspeed,ast2600-wdt" },
+       { }
+};
+
+static int ast2600_wdt_probe(struct udevice *dev)
+{
+       debug("%s() wdt%u\n", __func__, dev_seq(dev));
+       ast2600_wdt_stop(dev);
+
+       return 0;
+}
+
+U_BOOT_DRIVER(ast2600_wdt) = {
+       .name = "ast2600_wdt",
+       .id = UCLASS_WDT,
+       .of_match = ast2600_wdt_ids,
+       .probe = ast2600_wdt_probe,
+       .priv_auto = sizeof(struct ast2600_wdt_priv),
+       .of_to_plat = ast2600_wdt_of_to_plat,
+       .ops = &ast2600_wdt_ops,
+};
index 67ce930..b473d7c 100644 (file)
@@ -411,13 +411,14 @@ config ENV_IS_IN_UBI
 
 config SYS_REDUNDAND_ENVIRONMENT
        bool "Enable redundant environment support"
-       depends on ENV_IS_IN_EEPROM || ENV_IS_IN_FLASH || ENV_IS_IN_MMC || \
-               ENV_IS_IN_NAND || ENV_IS_IN_SPI_FLASH || ENV_IS_IN_UBI
        help
          Normally, the environemt is stored in a single location.  By
          selecting this option, you can then define where to hold a redundant
          copy of the environment data, so that there is a valid backup copy in
          case there is a power failure during a "saveenv" operation.
+         Also this config changes the binary environment structure handling
+         which is used by env import/export commands which are independent of
+         storing variables to redundant location on a non volatile device.
 
 config ENV_FAT_INTERFACE
        string "Name of the block device for the environment"
index 01e7cee..b332ecb 100644 (file)
@@ -1030,7 +1030,6 @@ out:
 int close_ctree_fs_info(struct btrfs_fs_info *fs_info)
 {
        int ret;
-       int err = 0;
 
        free_fs_roots_tree(&fs_info->fs_root_tree);
 
@@ -1038,9 +1037,7 @@ int close_ctree_fs_info(struct btrfs_fs_info *fs_info)
        ret = btrfs_close_devices(fs_info->fs_devices);
        btrfs_cleanup_all_caches(fs_info);
        btrfs_free_fs_info(fs_info);
-       if (!err)
-               err = ret;
-       return err;
+       return ret;
 }
 
 int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid)
index fcf52d4..4aaaeab 100644 (file)
@@ -1030,7 +1030,7 @@ again:
         */
        stripe_nr = stripe_nr / map->stripe_len;
 
-       stripe_offset = stripe_nr * map->stripe_len;
+       stripe_offset = stripe_nr * (u64)map->stripe_len;
        BUG_ON(offset < stripe_offset);
 
        /* stripe_offset is the offset of this block in its stripe*/
@@ -1103,7 +1103,7 @@ again:
                        rot = stripe_nr % map->num_stripes;
 
                        /* Fill in the logical address of each stripe */
-                       tmp = stripe_nr * nr_data_stripes(map);
+                       tmp = (u64)stripe_nr * nr_data_stripes(map);
 
                        for (i = 0; i < nr_data_stripes(map); i++)
                                raid_map[(i+rot) % map->num_stripes] =
index 157dad6..fb6ce09 100644 (file)
@@ -123,16 +123,16 @@ static void get_name(dir_entry *dirent, char *s_name)
 {
        char *ptr;
 
-       memcpy(s_name, dirent->name, 8);
+       memcpy(s_name, dirent->nameext.name, 8);
        s_name[8] = '\0';
        ptr = s_name;
        while (*ptr && *ptr != ' ')
                ptr++;
        if (dirent->lcase & CASE_LOWER_BASE)
                downcase(s_name, (unsigned)(ptr - s_name));
-       if (dirent->ext[0] && dirent->ext[0] != ' ') {
+       if (dirent->nameext.ext[0] && dirent->nameext.ext[0] != ' ') {
                *ptr++ = '.';
-               memcpy(ptr, dirent->ext, 3);
+               memcpy(ptr, dirent->nameext.ext, 3);
                if (dirent->lcase & CASE_LOWER_EXT)
                        downcase(ptr, 3);
                ptr[3] = '\0';
@@ -472,16 +472,15 @@ static int slot2str(dir_slot *slotptr, char *l_name, int *idx)
 }
 
 /* Calculate short name checksum */
-static __u8 mkcksum(const char name[8], const char ext[3])
+static __u8 mkcksum(struct nameext *nameext)
 {
        int i;
+       u8 *pos = (void *)nameext;
 
        __u8 ret = 0;
 
-       for (i = 0; i < 8; i++)
-               ret = (((ret & 1) << 7) | ((ret & 0xfe) >> 1)) + name[i];
-       for (i = 0; i < 3; i++)
-               ret = (((ret & 1) << 7) | ((ret & 0xfe) >> 1)) + ext[i];
+       for (i = 0; i < 11; i++)
+               ret = (((ret & 1) << 7) | ((ret & 0xfe) >> 1)) + pos[i];
 
        return ret;
 }
@@ -896,7 +895,7 @@ static dir_entry *next_dent(fat_itr *itr)
        }
 
        /* have we reached the last valid entry? */
-       if (itr->dent->name[0] == 0)
+       if (itr->dent->nameext.name[0] == 0)
                return NULL;
 
        return itr->dent;
@@ -905,7 +904,7 @@ static dir_entry *next_dent(fat_itr *itr)
 static dir_entry *extract_vfat_name(fat_itr *itr)
 {
        struct dir_entry *dent = itr->dent;
-       int seqn = itr->dent->name[0] & ~LAST_LONG_ENTRY_MASK;
+       int seqn = itr->dent->nameext.name[0] & ~LAST_LONG_ENTRY_MASK;
        u8 chksum, alias_checksum = ((dir_slot *)dent)->alias_checksum;
        int n = 0;
 
@@ -932,18 +931,19 @@ static dir_entry *extract_vfat_name(fat_itr *itr)
         * We are now at the short file name entry.
         * If it is marked as deleted, just skip it.
         */
-       if (dent->name[0] == DELETED_FLAG ||
-           dent->name[0] == aRING)
+       if (dent->nameext.name[0] == DELETED_FLAG ||
+           dent->nameext.name[0] == aRING)
                return NULL;
 
        itr->l_name[n] = '\0';
 
-       chksum = mkcksum(dent->name, dent->ext);
+       chksum = mkcksum(&dent->nameext);
 
        /* checksum mismatch could mean deleted file, etc.. skip it: */
        if (chksum != alias_checksum) {
                debug("** chksum=%x, alias_checksum=%x, l_name=%s, s_name=%8s.%3s\n",
-                     chksum, alias_checksum, itr->l_name, dent->name, dent->ext);
+                     chksum, alias_checksum, itr->l_name, dent->nameext.name,
+                     dent->nameext.ext);
                return NULL;
        }
 
@@ -984,12 +984,12 @@ static int fat_itr_next(fat_itr *itr)
                itr->dent_rem = itr->remaining;
                itr->dent_start = itr->dent;
                itr->dent_clust = itr->clust;
-               if (dent->name[0] == DELETED_FLAG)
+               if (dent->nameext.name[0] == DELETED_FLAG)
                        continue;
 
                if (dent->attr & ATTR_VOLUME) {
                        if ((dent->attr & ATTR_VFAT) == ATTR_VFAT &&
-                           (dent->name[0] & LAST_LONG_ENTRY_MASK)) {
+                           (dent->nameext.name[0] & LAST_LONG_ENTRY_MASK)) {
                                /* long file name */
                                dent = extract_vfat_name(itr);
                                /*
index 20a54a2..0132ef9 100644 (file)
@@ -275,7 +275,7 @@ static int fat_find_empty_dentries(fat_itr *itr, int count)
                        log_debug("Not enough directory entries available\n");
                        return -ENOSPC;
                }
-               switch (itr->dent->name[0]) {
+               switch (itr->dent->nameext.name[0]) {
                case 0x00:
                case DELETED_FLAG:
                        if (!n) {
@@ -399,7 +399,7 @@ fill_dir_slot(fat_itr *itr, const char *l_name, const char *shortname)
        int idx = 0, ret;
 
        /* Get short file name checksum value */
-       checksum = mkcksum(shortname, shortname + 8);
+       checksum = mkcksum((void *)shortname);
 
        do {
                memset(slotptr, 0x00, sizeof(dir_slot));
@@ -418,8 +418,12 @@ fill_dir_slot(fat_itr *itr, const char *l_name, const char *shortname)
                slotptr--;
                counter--;
 
-               if (itr->remaining == 0)
-                       flush_dir(itr);
+               if (!itr->remaining) {
+                       /* Write directory table to device */
+                       ret = flush_dir(itr);
+                       if (ret)
+                               return ret;
+               }
 
                next_dent(itr);
                if (!itr->dent)
@@ -639,15 +643,23 @@ set_cluster(fsdata *mydata, u32 clustnum, u8 *buffer, u32 size)
                           buffer, size);
 }
 
-static int
-flush_dir(fat_itr *itr)
+/**
+ * flush_dir() - flush directory
+ *
+ * @itr:       directory iterator
+ * Return:     0 for success, -EIO on error
+ */
+static int flush_dir(fat_itr *itr)
 {
        fsdata *mydata = itr->fsdata;
        u32 startsect, sect_offset, nsects;
+       int ret;
 
-       if (!itr->is_root || mydata->fatsize == 32)
-               return set_cluster(mydata, itr->clust, itr->block,
-                                  mydata->clust_size * mydata->sect_size);
+       if (!itr->is_root || mydata->fatsize == 32) {
+               ret = set_cluster(mydata, itr->clust, itr->block,
+                                 mydata->clust_size * mydata->sect_size);
+               goto out;
+       }
 
        sect_offset = itr->clust * mydata->clust_size;
        startsect = mydata->rootdir_sect + sect_offset;
@@ -655,8 +667,14 @@ flush_dir(fat_itr *itr)
        nsects = min_t(u32, mydata->clust_size,
                       mydata->rootdir_size - sect_offset);
 
-       return set_sectors(mydata, startsect, itr->block,
-                          nsects * mydata->sect_size);
+       ret = set_sectors(mydata, startsect, itr->block,
+                         nsects * mydata->sect_size);
+out:
+       if (ret) {
+               log_err("Error: writing directory entry\n");
+               return -EIO;
+       }
+       return 0;
 }
 
 /*
@@ -1151,7 +1169,7 @@ static void fill_dentry(fsdata *mydata, dir_entry *dentptr,
 
        dentptr->attr = attr;
 
-       memcpy(dentptr->name, shortname, SHORT_NAME_SIZE);
+       memcpy(&dentptr->nameext, shortname, SHORT_NAME_SIZE);
 }
 
 /**
@@ -1176,7 +1194,7 @@ static dir_entry *find_directory_entry(fat_itr *itr, char *filename)
                if (!match)
                        continue;
 
-               if (itr->dent->name[0] == '\0')
+               if (itr->dent->nameext.name[0] == '\0')
                        return NULL;
                else
                        return itr->dent;
@@ -1390,10 +1408,6 @@ int file_fat_write_at(const char *filename, loff_t pos, void *buffer,
 
        /* Write directory table to device */
        ret = flush_dir(itr);
-       if (ret) {
-               printf("Error: writing directory entry\n");
-               ret = -EIO;
-       }
 
 exit:
        free(filename_copy);
@@ -1456,14 +1470,10 @@ static int delete_single_dentry(fat_itr *itr)
        struct dir_entry *dent = itr->dent;
 
        memset(dent, 0, sizeof(*dent));
-       dent->name[0] = DELETED_FLAG;
+       dent->nameext.name[0] = DELETED_FLAG;
 
-       if (!itr->remaining) {
-               if (flush_dir(itr)) {
-                       printf("error: writing directory entry\n");
-                       return -EIO;
-               }
-       }
+       if (!itr->remaining)
+               return flush_dir(itr);
        return 0;
 }
 
@@ -1476,7 +1486,7 @@ static int delete_single_dentry(fat_itr *itr)
 static int delete_long_name(fat_itr *itr)
 {
        struct dir_entry *dent = itr->dent;
-       int seqn = itr->dent->name[0] & ~LAST_LONG_ENTRY_MASK;
+       int seqn = itr->dent->nameext.name[0] & ~LAST_LONG_ENTRY_MASK;
 
        while (seqn--) {
                int ret;
@@ -1521,7 +1531,7 @@ static int delete_dentry_long(fat_itr *itr)
        dent = itr->dent_start;
        /* Delete long name */
        if ((dent->attr & ATTR_VFAT) == ATTR_VFAT &&
-           (dent->name[0] & LAST_LONG_ENTRY_MASK)) {
+           (dent->nameext.name[0] & LAST_LONG_ENTRY_MASK)) {
                int ret;
 
                ret = delete_long_name(itr);
@@ -1530,12 +1540,7 @@ static int delete_dentry_long(fat_itr *itr)
        }
        /* Delete short name */
        delete_single_dentry(itr);
-       if (flush_dir(itr)) {
-               printf("error: writing directory entry\n");
-               return -EIO;
-       }
-
-       return 0;
+       return flush_dir(itr);
 }
 
 int fat_unlink(const char *filename)
@@ -1707,12 +1712,10 @@ int fat_mkdir(const char *new_dirname)
        }
        memset(dotdent, 0, bytesperclust);
 
-       memcpy(dotdent[0].name, ".       ", 8);
-       memcpy(dotdent[0].ext, "   ", 3);
+       memcpy(&dotdent[0].nameext, ".          ", 11);
        dotdent[0].attr = ATTR_DIR | ATTR_ARCH;
 
-       memcpy(dotdent[1].name, "..      ", 8);
-       memcpy(dotdent[1].ext, "   ", 3);
+       memcpy(&dotdent[1].nameext, "..         ", 11);
        dotdent[1].attr = ATTR_DIR | ATTR_ARCH;
 
        if (itr->is_root)
@@ -1739,13 +1742,12 @@ int fat_mkdir(const char *new_dirname)
        ret = flush_dirty_fat_buffer(mydata);
        if (ret) {
                printf("Error: flush fat buffer\n");
+               ret = -EIO;
                goto exit;
        }
 
        /* Write directory table to device */
        ret = flush_dir(itr);
-       if (ret)
-               printf("Error: writing directory entry\n");
 
 exit:
        free(dirname_copy);
index 5de69ac..dca13bd 100644 (file)
@@ -1310,7 +1310,7 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
 {
        char *dir = NULL, *fragment_block, *datablock = NULL, *data_buffer = NULL;
        char *fragment = NULL, *file = NULL, *resolved, *data;
-       u64 start, n_blks, table_size, data_offset, table_offset;
+       u64 start, n_blks, table_size, data_offset, table_offset, sparse_size;
        int ret, j, i_number, datablk_count = 0;
        struct squashfs_super_block *sblk = ctxt.sblk;
        struct squashfs_fragment_block_entry frag_entry;
@@ -1444,28 +1444,43 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
                n_blks = DIV_ROUND_UP(table_size + table_offset,
                                      ctxt.cur_dev->blksz);
 
-               data_buffer = malloc_cache_aligned(n_blks * ctxt.cur_dev->blksz);
+               /* Don't load any data for sparse blocks */
+               if (finfo.blk_sizes[j] == 0) {
+                       n_blks = 0;
+                       table_offset = 0;
+                       data_buffer = NULL;
+                       data = NULL;
+               } else {
+                       data_buffer = malloc_cache_aligned(n_blks * ctxt.cur_dev->blksz);
 
-               if (!data_buffer) {
-                       ret = -ENOMEM;
-                       goto out;
-               }
+                       if (!data_buffer) {
+                               ret = -ENOMEM;
+                               goto out;
+                       }
 
-               ret = sqfs_disk_read(start, n_blks, data_buffer);
-               if (ret < 0) {
-                       /*
-                        * Possible causes: too many data blocks or too large
-                        * SquashFS block size. Tip: re-compile the SquashFS
-                        * image with mksquashfs's -b <block_size> option.
-                        */
-                       printf("Error: too many data blocks to be read.\n");
-                       goto out;
-               }
+                       ret = sqfs_disk_read(start, n_blks, data_buffer);
+                       if (ret < 0) {
+                               /*
+                                * Possible causes: too many data blocks or too large
+                                * SquashFS block size. Tip: re-compile the SquashFS
+                                * image with mksquashfs's -b <block_size> option.
+                                */
+                               printf("Error: too many data blocks to be read.\n");
+                               goto out;
+                       }
 
-               data = data_buffer + table_offset;
+                       data = data_buffer + table_offset;
+               }
 
                /* Load the data */
-               if (SQFS_COMPRESSED_BLOCK(finfo.blk_sizes[j])) {
+               if (finfo.blk_sizes[j] == 0) {
+                       /* This is a sparse block */
+                       sparse_size = get_unaligned_le32(&sblk->block_size);
+                       if ((*actread + sparse_size) > len)
+                               sparse_size = len - *actread;
+                       memset(buf + *actread, 0, sparse_size);
+                       *actread += sparse_size;
+               } else if (SQFS_COMPRESSED_BLOCK(finfo.blk_sizes[j])) {
                        dest_len = get_unaligned_le32(&sblk->block_size);
                        ret = sqfs_decompress(&ctxt, datablock, &dest_len,
                                              data, table_size);
@@ -1484,7 +1499,8 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
                }
 
                data_offset += table_size;
-               free(data_buffer);
+               if (data_buffer)
+                       free(data_buffer);
                data_buffer = NULL;
                if (*actread >= len)
                        break;
index eb14b89..9962cbe 100644 (file)
@@ -114,7 +114,7 @@ int ubifs_leb_read(const struct ubifs_info *c, int lnum, void *buf, int offs,
 int ubifs_leb_write(struct ubifs_info *c, int lnum, const void *buf, int offs,
                    int len)
 {
-       int err;
+       int err = 0;
 
        ubifs_assert(!c->ro_media && !c->ro_mount);
        if (c->ro_error)
@@ -136,7 +136,7 @@ int ubifs_leb_write(struct ubifs_info *c, int lnum, const void *buf, int offs,
 
 int ubifs_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len)
 {
-       int err;
+       int err = 0;
 
        ubifs_assert(!c->ro_media && !c->ro_mount);
        if (c->ro_error)
@@ -158,7 +158,7 @@ int ubifs_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len)
 
 int ubifs_leb_unmap(struct ubifs_info *c, int lnum)
 {
-       int err;
+       int err = 0;
 
        ubifs_assert(!c->ro_media && !c->ro_mount);
        if (c->ro_error)
@@ -179,7 +179,7 @@ int ubifs_leb_unmap(struct ubifs_info *c, int lnum)
 
 int ubifs_leb_map(struct ubifs_info *c, int lnum)
 {
-       int err;
+       int err = 0;
 
        ubifs_assert(!c->ro_media && !c->ro_mount);
        if (c->ro_error)
index c986226..2627c2a 100644 (file)
 #endif
 #endif
 
-
-#define BOOTENV_SHARED_EFI                                                \
+#ifdef CONFIG_CMD_BOOTEFI_BOOTMGR
+#define BOOTENV_EFI_BOOTMGR                                               \
        "boot_efi_bootmgr="                                               \
                "if fdt addr ${fdt_addr_r}; then "                        \
                        "bootefi bootmgr ${fdt_addr_r};"                  \
                "else "                                                   \
                        "bootefi bootmgr;"                                \
-               "fi\0"                                                    \
+               "fi\0"
+#else
+#define BOOTENV_EFI_BOOTMGR
+#endif
+
+#define BOOTENV_SHARED_EFI                                                \
+       BOOTENV_EFI_BOOTMGR                                               \
        \
        "boot_efi_binary="                                                \
                "load ${devtype} ${devnum}:${distro_bootpart} "           \
diff --git a/include/configs/evb_ast2600.h b/include/configs/evb_ast2600.h
new file mode 100644 (file)
index 0000000..e7975bf
--- /dev/null
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) Aspeed Technology Inc.
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#include <configs/aspeed-common.h>
+
+#define CONFIG_SYS_UBOOT_BASE          CONFIG_SYS_TEXT_BASE
+
+/* Memory Info */
+#define CONFIG_SYS_LOAD_ADDR           0x83000000
+
+#endif /* __CONFIG_H */
index 34235b5..710731e 100644 (file)
 #define CONFIG_SYS_MAXARGS             64
 #define CONFIG_EXTRA_ENV_SETTINGS      "silent=y\0"
 
+/* nand driver parameters */
+#ifdef CONFIG_TARGET_PRESIDIO_ASIC
+       #define CONFIG_SYS_NAND_ONFI_DETECTION
+       #define CONFIG_SYS_MAX_NAND_DEVICE      1
+       #define CONFIG_SYS_NAND_MAX_CHIPS       1
+       #define CONFIG_SYS_NAND_BASE            CONFIG_SYS_FLASH_BASE
+       #define CONFIG_SYS_NAND_BASE_LIST       { CONFIG_SYS_NAND_BASE }
+#endif
+
 #endif /* __PRESIDIO_ASIC_H */
index 1aa7514..863b652 100644 (file)
@@ -69,7 +69,6 @@
 
 /* Ethernet need */
 #ifdef CONFIG_DWC_ETH_QOS
-#define CONFIG_SYS_NONCACHED_MEMORY    (1 * SZ_1M)     /* 1M */
 #define CONFIG_SERVERIP                 192.168.1.1
 #define CONFIG_BOOTP_SERVERIP
 #define CONFIG_SYS_AUTOLOAD            "no"
diff --git a/include/dt-bindings/clock/ast2600-clock.h b/include/dt-bindings/clock/ast2600-clock.h
new file mode 100644 (file)
index 0000000..36294a5
--- /dev/null
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) ASPEED Technology Inc.
+ */
+
+#define ASPEED_CLK_GATE_ECLK           0
+#define ASPEED_CLK_GATE_GCLK           1
+#define ASPEED_CLK_GATE_MCLK           2
+#define ASPEED_CLK_GATE_VCLK           3
+#define ASPEED_CLK_GATE_BCLK           4
+#define ASPEED_CLK_GATE_DCLK           5
+#define ASPEED_CLK_GATE_LCLK           6
+#define ASPEED_CLK_GATE_YCLK           7
+#define ASPEED_CLK_GATE_LHCCLK         8
+#define ASPEED_CLK_GATE_REFCLK         9
+#define ASPEED_CLK_GATE_ESPICLK                10
+#define ASPEED_CLK_GATE_UART1CLK       11
+#define ASPEED_CLK_GATE_UART2CLK       12
+#define ASPEED_CLK_GATE_UART3CLK       13
+#define ASPEED_CLK_GATE_UART4CLK       14
+#define ASPEED_CLK_GATE_UART5CLK       15
+#define ASPEED_CLK_GATE_UART6CLK       16
+#define ASPEED_CLK_GATE_UART7CLK       17
+#define ASPEED_CLK_GATE_UART8CLK       18
+#define ASPEED_CLK_GATE_UART9CLK       19
+#define ASPEED_CLK_GATE_UART10CLK      20
+#define ASPEED_CLK_GATE_UART11CLK      21
+#define ASPEED_CLK_GATE_UART12CLK      22
+#define ASPEED_CLK_GATE_UART13CLK      23
+#define ASPEED_CLK_GATE_MAC1CLK                24
+#define ASPEED_CLK_GATE_MAC2CLK                25
+#define ASPEED_CLK_GATE_MAC3CLK                26
+#define ASPEED_CLK_GATE_MAC4CLK                27
+#define ASPEED_CLK_GATE_RSACLK         28
+#define ASPEED_CLK_GATE_SDCLK          29
+#define ASPEED_CLK_GATE_SDEXTCLK       30
+#define ASPEED_CLK_GATE_EMMCCLK                31
+#define ASPEED_CLK_GATE_EMMCEXTCLK     32
+#define ASPEED_CLK_GATE_USBUHCICLK     33
+#define ASPEED_CLK_GATE_USBPORT1CLK    34
+#define ASPEED_CLK_GATE_USBPORT2CLK    35
+#define ASPEED_CLK_GATE_FSICLK         36
+
+#define ASPEED_CLK_APLL                        37
+#define ASPEED_CLK_EPLL                        38
+#define ASPEED_CLK_DPLL                        39
+#define ASPEED_CLK_HPLL                        40
+#define ASPEED_CLK_AHB                 41
+#define ASPEED_CLK_APB1                        42
+#define ASPEED_CLK_APB2                        43
+#define ASPEED_CLK_UART                        44
+#define ASPEED_CLK_SDIO                        45
+#define ASPEED_CLK_ECLK                        46
+#define ASPEED_CLK_ECLK_MUX            47
+#define ASPEED_CLK_LHCLK               48
+#define ASPEED_CLK_MAC                 49
+#define ASPEED_CLK_BCLK                        50
+#define ASPEED_CLK_MPLL                        51
+#define ASPEED_CLK_24M                 52
+#define ASPEED_CLK_EMMC                        53
+#define ASPEED_CLK_UARTX               54
+#define ASPEED_CLK_HUARTX              55
diff --git a/include/dt-bindings/clock/mt8183-clk.h b/include/dt-bindings/clock/mt8183-clk.h
new file mode 100644 (file)
index 0000000..f7e6367
--- /dev/null
@@ -0,0 +1,329 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2020 MediaTek Inc.
+ * Author: Weiyi Lu <weiyi.lu@mediatek.com>
+ */
+
+#ifndef _DT_BINDINGS_CLK_MT8183_H
+#define _DT_BINDINGS_CLK_MT8183_H
+
+/* APMIXED */
+#define CLK_APMIXED_ARMPLL_LL          0
+#define CLK_APMIXED_ARMPLL_L           1
+#define CLK_APMIXED_CCIPLL             2
+#define CLK_APMIXED_MAINPLL            3
+#define CLK_APMIXED_UNIV2PLL           4
+#define CLK_APMIXED_MSDCPLL            5
+#define CLK_APMIXED_MMPLL              6
+#define CLK_APMIXED_MFGPLL             7
+#define CLK_APMIXED_TVDPLL             8
+#define CLK_APMIXED_APLL1              9
+#define CLK_APMIXED_APLL2              10
+#define CLK_APMIXED_SSUSB_26M          11
+#define CLK_APMIXED_APPLL_26M          12
+#define CLK_APMIXED_MIPIC0_26M         13
+#define CLK_APMIXED_MDPLLGP_26M                14
+#define CLK_APMIXED_MMSYS_26M          15
+#define CLK_APMIXED_UFS_26M            16
+#define CLK_APMIXED_MIPIC1_26M         17
+#define CLK_APMIXED_MEMPLL_26M         18
+#define CLK_APMIXED_CLKSQ_LVPLL_26M    19
+#define CLK_APMIXED_MIPID0_26M         20
+#define CLK_APMIXED_MIPID1_26M         21
+#define CLK_APMIXED_NR_CLK             22
+
+/* TOPCKGEN */
+#define CLK_TOP_CLK26M                 0
+#define CLK_TOP_ULPOSC                 1
+#define CLK_TOP_UNIVP_192M             2
+#define CLK_TOP_CLK13M                 3
+#define CLK_TOP_F26M_CK_D2             4
+#define CLK_TOP_SYSPLL_CK              5
+#define CLK_TOP_SYSPLL_D2              6
+#define CLK_TOP_SYSPLL_D3              7
+#define CLK_TOP_SYSPLL_D5              8
+#define CLK_TOP_SYSPLL_D7              9
+#define CLK_TOP_SYSPLL_D2_D2           10
+#define CLK_TOP_SYSPLL_D2_D4           11
+#define CLK_TOP_SYSPLL_D2_D8           12
+#define CLK_TOP_SYSPLL_D2_D16          13
+#define CLK_TOP_SYSPLL_D3_D2           14
+#define CLK_TOP_SYSPLL_D3_D4           15
+#define CLK_TOP_SYSPLL_D3_D8           16
+#define CLK_TOP_SYSPLL_D5_D2           17
+#define CLK_TOP_SYSPLL_D5_D4           18
+#define CLK_TOP_SYSPLL_D7_D2           19
+#define CLK_TOP_SYSPLL_D7_D4           20
+#define CLK_TOP_UNIVPLL_CK             21
+#define CLK_TOP_UNIVPLL_D2             22
+#define CLK_TOP_UNIVPLL_D3             23
+#define CLK_TOP_UNIVPLL_D5             24
+#define CLK_TOP_UNIVPLL_D7             25
+#define CLK_TOP_UNIVPLL_D2_D2          26
+#define CLK_TOP_UNIVPLL_D2_D4          27
+#define CLK_TOP_UNIVPLL_D2_D8          28
+#define CLK_TOP_UNIVPLL_D3_D2          29
+#define CLK_TOP_UNIVPLL_D3_D4          30
+#define CLK_TOP_UNIVPLL_D3_D8          31
+#define CLK_TOP_UNIVPLL_D5_D2          32
+#define CLK_TOP_UNIVPLL_D5_D4          33
+#define CLK_TOP_UNIVPLL_D5_D8          34
+#define CLK_TOP_UNIVP_192M_CK          35
+#define CLK_TOP_UNIVP_192M_D2          36
+#define CLK_TOP_UNIVP_192M_D4          37
+#define CLK_TOP_UNIVP_192M_D8          38
+#define CLK_TOP_UNIVP_192M_D16         39
+#define CLK_TOP_UNIVP_192M_D32         40
+#define CLK_TOP_APLL1_CK               41
+#define CLK_TOP_APLL1_D2               42
+#define CLK_TOP_APLL1_D4               43
+#define CLK_TOP_APLL1_D8               44
+#define CLK_TOP_APLL2_CK               45
+#define CLK_TOP_APLL2_D2               46
+#define CLK_TOP_APLL2_D4               47
+#define CLK_TOP_APLL2_D8               48
+#define CLK_TOP_TVDPLL_CK              49
+#define CLK_TOP_TVDPLL_D2              50
+#define CLK_TOP_TVDPLL_D4              51
+#define CLK_TOP_TVDPLL_D8              52
+#define CLK_TOP_TVDPLL_D16             53
+#define CLK_TOP_MMPLL_CK               54
+#define CLK_TOP_MMPLL_D4               55
+#define CLK_TOP_MMPLL_D4_D2            56
+#define CLK_TOP_MMPLL_D4_D4            57
+#define CLK_TOP_MMPLL_D5               58
+#define CLK_TOP_MMPLL_D5_D2            59
+#define CLK_TOP_MMPLL_D5_D4            60
+#define CLK_TOP_MMPLL_D6               61
+#define CLK_TOP_MMPLL_D7               62
+#define CLK_TOP_MFGPLL_CK              63
+#define CLK_TOP_MSDCPLL_CK             64
+#define CLK_TOP_MSDCPLL_D2             65
+#define CLK_TOP_MSDCPLL_D4             66
+#define CLK_TOP_MSDCPLL_D8             67
+#define CLK_TOP_MSDCPLL_D16            68
+#define CLK_TOP_AD_OSC_CK              69
+#define CLK_TOP_OSC_D2                 70
+#define CLK_TOP_OSC_D4                 71
+#define CLK_TOP_OSC_D8                 72
+#define CLK_TOP_OSC_D16                        73
+#define CLK_TOP_UNIVPLL                        74
+#define CLK_TOP_UNIVPLL_D3_D16         75
+#define CLK_TOP_APLL12_DIV0            76
+#define CLK_TOP_APLL12_DIV1            77
+#define CLK_TOP_APLL12_DIV2            78
+#define CLK_TOP_APLL12_DIV3            79
+#define CLK_TOP_APLL12_DIV4            80
+#define CLK_TOP_APLL12_DIVB            81
+#define CLK_TOP_ARMPLL_DIV_PLL1                82
+#define CLK_TOP_ARMPLL_DIV_PLL2                83
+#define CLK_TOP_MUX_AXI                        84
+#define CLK_TOP_MUX_MM                 85
+#define CLK_TOP_MUX_IMG                        86
+#define CLK_TOP_MUX_CAM                        87
+#define CLK_TOP_MUX_DSP                        88
+#define CLK_TOP_MUX_DSP1               89
+#define CLK_TOP_MUX_DSP2               90
+#define CLK_TOP_MUX_IPU_IF             91
+#define CLK_TOP_MUX_MFG                        92
+#define CLK_TOP_MUX_F52M_MFG           93
+#define CLK_TOP_MUX_CAMTG              94
+#define CLK_TOP_MUX_CAMTG2             95
+#define CLK_TOP_MUX_CAMTG3             96
+#define CLK_TOP_MUX_CAMTG4             97
+#define CLK_TOP_MUX_UART               98
+#define CLK_TOP_MUX_SPI                        99
+#define CLK_TOP_MUX_MSDC50_0_HCLK      100
+#define CLK_TOP_MUX_MSDC50_0           101
+#define CLK_TOP_MUX_MSDC30_1           102
+#define CLK_TOP_MUX_MSDC30_2           103
+#define CLK_TOP_MUX_AUDIO              104
+#define CLK_TOP_MUX_AUD_INTBUS         105
+#define CLK_TOP_MUX_PMICSPI            106
+#define CLK_TOP_MUX_FPWRAP_ULPOSC      107
+#define CLK_TOP_MUX_ATB                        108
+#define CLK_TOP_MUX_SSPM               109
+#define CLK_TOP_MUX_DPI0               110
+#define CLK_TOP_MUX_SCAM               111
+#define CLK_TOP_MUX_DISP_PWM           112
+#define CLK_TOP_MUX_USB_TOP            113
+#define CLK_TOP_MUX_SSUSB_TOP_XHCI     114
+#define CLK_TOP_MUX_SPM                        115
+#define CLK_TOP_MUX_I2C                        116
+#define CLK_TOP_MUX_SCP                        117
+#define CLK_TOP_MUX_SENINF             118
+#define CLK_TOP_MUX_DXCC               119
+#define CLK_TOP_MUX_AUD_ENG1           120
+#define CLK_TOP_MUX_AUD_ENG2           121
+#define CLK_TOP_MUX_FAES_UFSFDE                122
+#define CLK_TOP_MUX_FUFS               123
+#define CLK_TOP_MUX_AUD_1              124
+#define CLK_TOP_MUX_AUD_2              125
+#define CLK_TOP_MUX_APLL_I2S0          126
+#define CLK_TOP_MUX_APLL_I2S1          127
+#define CLK_TOP_MUX_APLL_I2S2          128
+#define CLK_TOP_MUX_APLL_I2S3          129
+#define CLK_TOP_MUX_APLL_I2S4          130
+#define CLK_TOP_MUX_APLL_I2S5          131
+#define CLK_TOP_NR_CLK                 132
+
+/* INFRACFG_AO */
+#define CLK_INFRA_PMIC_TMR             0
+#define CLK_INFRA_PMIC_AP              1
+#define CLK_INFRA_PMIC_MD              2
+#define CLK_INFRA_PMIC_CONN            3
+#define CLK_INFRA_SCPSYS               4
+#define CLK_INFRA_SEJ                  5
+#define CLK_INFRA_APXGPT               6
+#define CLK_INFRA_ICUSB                        7
+#define CLK_INFRA_GCE                  8
+#define CLK_INFRA_THERM                        9
+#define CLK_INFRA_I2C0                 10
+#define CLK_INFRA_I2C1                 11
+#define CLK_INFRA_I2C2                 12
+#define CLK_INFRA_I2C3                 13
+#define CLK_INFRA_PWM_HCLK             14
+#define CLK_INFRA_PWM1                 15
+#define CLK_INFRA_PWM2                 16
+#define CLK_INFRA_PWM3                 17
+#define CLK_INFRA_PWM4                 18
+#define CLK_INFRA_PWM                  19
+#define CLK_INFRA_UART0                        20
+#define CLK_INFRA_UART1                        21
+#define CLK_INFRA_UART2                        22
+#define CLK_INFRA_UART3                        23
+#define CLK_INFRA_GCE_26M              24
+#define CLK_INFRA_CQ_DMA_FPC           25
+#define CLK_INFRA_BTIF                 26
+#define CLK_INFRA_SPI0                 27
+#define CLK_INFRA_MSDC0                        28
+#define CLK_INFRA_MSDC1                        29
+#define CLK_INFRA_MSDC2                        30
+#define CLK_INFRA_MSDC0_SCK            31
+#define CLK_INFRA_DVFSRC               32
+#define CLK_INFRA_GCPU                 33
+#define CLK_INFRA_TRNG                 34
+#define CLK_INFRA_AUXADC               35
+#define CLK_INFRA_CPUM                 36
+#define CLK_INFRA_CCIF1_AP             37
+#define CLK_INFRA_CCIF1_MD             38
+#define CLK_INFRA_AUXADC_MD            39
+#define CLK_INFRA_MSDC1_SCK            40
+#define CLK_INFRA_MSDC2_SCK            41
+#define CLK_INFRA_AP_DMA               42
+#define CLK_INFRA_XIU                  43
+#define CLK_INFRA_DEVICE_APC           44
+#define CLK_INFRA_CCIF_AP              45
+#define CLK_INFRA_DEBUGSYS             46
+#define CLK_INFRA_AUDIO                        47
+#define CLK_INFRA_CCIF_MD              48
+#define CLK_INFRA_DXCC_SEC_CORE                49
+#define CLK_INFRA_DXCC_AO              50
+#define CLK_INFRA_DRAMC_F26M           51
+#define CLK_INFRA_IRTX                 52
+#define CLK_INFRA_DISP_PWM             53
+#define CLK_INFRA_CLDMA_BCLK           54
+#define CLK_INFRA_AUDIO_26M_BCLK       55
+#define CLK_INFRA_SPI1                 56
+#define CLK_INFRA_I2C4                 57
+#define CLK_INFRA_MODEM_TEMP_SHARE     58
+#define CLK_INFRA_SPI2                 59
+#define CLK_INFRA_SPI3                 60
+#define CLK_INFRA_UNIPRO_SCK           61
+#define CLK_INFRA_UNIPRO_TICK          62
+#define CLK_INFRA_UFS_MP_SAP_BCLK      63
+#define CLK_INFRA_MD32_BCLK            64
+#define CLK_INFRA_SSPM                 65
+#define CLK_INFRA_UNIPRO_MBIST         66
+#define CLK_INFRA_SSPM_BUS_HCLK                67
+#define CLK_INFRA_I2C5                 68
+#define CLK_INFRA_I2C5_ARBITER         69
+#define CLK_INFRA_I2C5_IMM             70
+#define CLK_INFRA_I2C1_ARBITER         71
+#define CLK_INFRA_I2C1_IMM             72
+#define CLK_INFRA_I2C2_ARBITER         73
+#define CLK_INFRA_I2C2_IMM             74
+#define CLK_INFRA_SPI4                 75
+#define CLK_INFRA_SPI5                 76
+#define CLK_INFRA_CQ_DMA               77
+#define CLK_INFRA_UFS                  78
+#define CLK_INFRA_AES_UFSFDE           79
+#define CLK_INFRA_UFS_TICK             80
+#define CLK_INFRA_MSDC0_SELF           81
+#define CLK_INFRA_MSDC1_SELF           82
+#define CLK_INFRA_MSDC2_SELF           83
+#define CLK_INFRA_SSPM_26M_SELF                84
+#define CLK_INFRA_SSPM_32K_SELF                85
+#define CLK_INFRA_UFS_AXI              86
+#define CLK_INFRA_I2C6                 87
+#define CLK_INFRA_AP_MSDC0             88
+#define CLK_INFRA_MD_MSDC0             89
+#define CLK_INFRA_USB                  90
+#define CLK_INFRA_DEVMPU_BCLK          91
+#define CLK_INFRA_CCIF2_AP             92
+#define CLK_INFRA_CCIF2_MD             93
+#define CLK_INFRA_CCIF3_AP             94
+#define CLK_INFRA_CCIF3_MD             95
+#define CLK_INFRA_SEJ_F13M             96
+#define CLK_INFRA_AES_BCLK             97
+#define CLK_INFRA_I2C7                 98
+#define CLK_INFRA_I2C8                 99
+#define CLK_INFRA_FBIST2FPC            100
+#define CLK_INFRA_NR_CLK               101
+
+/* MMSYS_CONFIG */
+#define CLK_MM_SMI_COMMON              0
+#define CLK_MM_SMI_LARB0               1
+#define CLK_MM_SMI_LARB1               2
+#define CLK_MM_GALS_COMM0              3
+#define CLK_MM_GALS_COMM1              4
+#define CLK_MM_GALS_CCU2MM             5
+#define CLK_MM_GALS_IPU12MM            6
+#define CLK_MM_GALS_IMG2MM             7
+#define CLK_MM_GALS_CAM2MM             8
+#define CLK_MM_GALS_IPU2MM             9
+#define CLK_MM_MDP_DL_TXCK             10
+#define CLK_MM_IPU_DL_TXCK             11
+#define CLK_MM_MDP_RDMA0               12
+#define CLK_MM_MDP_RDMA1               13
+#define CLK_MM_MDP_RSZ0                        14
+#define CLK_MM_MDP_RSZ1                        15
+#define CLK_MM_MDP_TDSHP               16
+#define CLK_MM_MDP_WROT0               17
+#define CLK_MM_FAKE_ENG                        18
+#define CLK_MM_DISP_OVL0               19
+#define CLK_MM_DISP_OVL0_2L            20
+#define CLK_MM_DISP_OVL1_2L            21
+#define CLK_MM_DISP_RDMA0              22
+#define CLK_MM_DISP_RDMA1              23
+#define CLK_MM_DISP_WDMA0              24
+#define CLK_MM_DISP_COLOR0             25
+#define CLK_MM_DISP_CCORR0             26
+#define CLK_MM_DISP_AAL0               27
+#define CLK_MM_DISP_GAMMA0             28
+#define CLK_MM_DISP_DITHER0            29
+#define CLK_MM_DISP_SPLIT              30
+#define CLK_MM_DSI0_MM                 31
+#define CLK_MM_DSI0_IF                 32
+#define CLK_MM_DPI_MM                  33
+#define CLK_MM_DPI_IF                  34
+#define CLK_MM_FAKE_ENG2               35
+#define CLK_MM_MDP_DL_RX               36
+#define CLK_MM_IPU_DL_RX               37
+#define CLK_MM_26M                     38
+#define CLK_MM_MMSYS_R2Y               39
+#define CLK_MM_DISP_RSZ                        40
+#define CLK_MM_MDP_WDMA0               41
+#define CLK_MM_MDP_AAL                 42
+#define CLK_MM_MDP_CCORR               43
+#define CLK_MM_DBI_MM                  44
+#define CLK_MM_DBI_IF                  45
+#define CLK_MM_NR_CLK                  46
+
+/* MCUCFG */
+#define CLK_MCU_MP0_SEL                        0
+#define CLK_MCU_MP2_SEL                        1
+#define CLK_MCU_BUS_SEL                        2
+#define CLK_MCU_NR_CLK                 3
+
+#endif /* _DT_BINDINGS_CLK_MT8183_H */
diff --git a/include/dt-bindings/reset/ast2600-reset.h b/include/dt-bindings/reset/ast2600-reset.h
new file mode 100644 (file)
index 0000000..b6d0f79
--- /dev/null
@@ -0,0 +1,70 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) ASPEED Technology Inc.
+ */
+
+#ifndef _ABI_MACH_ASPEED_AST2600_RESET_H_
+#define _ABI_MACH_ASPEED_AST2600_RESET_H_
+
+#define ASPEED_RESET_FSI               (59)
+#define ASPEED_RESET_RESERVED58                (58)
+#define ASPEED_RESET_RESERVED57                (57)
+#define ASPEED_RESET_SD                        (56)
+#define ASPEED_RESET_ADC               (55)
+#define ASPEED_RESET_JTAG_MASTER2      (54)
+#define ASPEED_RESET_MAC4              (53)
+#define ASPEED_RESET_MAC3              (52)
+#define ASPEED_RESET_RESERVE51         (51)
+#define ASPEED_RESET_RESERVE50         (50)
+#define ASPEED_RESET_RESERVE49         (49)
+#define ASPEED_RESET_RESERVE48         (48)
+#define ASPEED_RESET_RESERVE47         (47)
+#define ASPEED_RESET_RESERVE46         (46)
+#define ASPEED_RESET_I3C5              (45)
+#define ASPEED_RESET_I3C4              (44)
+#define ASPEED_RESET_I3C3              (43)
+#define ASPEED_RESET_I3C2              (42)
+#define ASPEED_RESET_I3C1              (41)
+#define ASPEED_RESET_I3C0              (40)
+#define ASPEED_RESET_I3C_DMA           (39)
+#define ASPEED_RESET_RESERVED38                (38)
+#define ASPEED_RESET_PWM               (37)
+#define ASPEED_RESET_PECI              (36)
+#define ASPEED_RESET_MII               (35)
+#define ASPEED_RESET_I2C               (34)
+#define ASPEED_RESET_RESERVED33                (33)
+#define ASPEED_RESET_LPC_ESPI          (32)
+#define ASPEED_RESET_H2X               (31)
+#define ASPEED_RESET_GP_MCU            (30)
+#define ASPEED_RESET_DP_MCU            (29)
+#define ASPEED_RESET_DP                        (28)
+#define ASPEED_RESET_RC_XDMA           (27)
+#define ASPEED_RESET_GRAPHICS          (26)
+#define ASPEED_RESET_DEV_XDMA          (25)
+#define ASPEED_RESET_DEV_MCTP          (24)
+#define ASPEED_RESET_RC_MCTP           (23)
+#define ASPEED_RESET_JTAG_MASTER       (22)
+#define ASPEED_RESET_PCIE_DEV_OE       (21)
+#define ASPEED_RESET_PCIE_DEV_O                (20)
+#define ASPEED_RESET_PCIE_RC_OE                (19)
+#define ASPEED_RESET_PCIE_RC_O         (18)
+#define ASPEED_RESET_RESERVED17                (17)
+#define ASPEED_RESET_EMMC              (16)
+#define ASPEED_RESET_UHCI              (15)
+#define ASPEED_RESET_EHCI_P1           (14)
+#define ASPEED_RESET_CRT               (13)
+#define ASPEED_RESET_MAC2              (12)
+#define ASPEED_RESET_MAC1              (11)
+#define ASPEED_RESET_RESERVED10                (10)
+#define ASPEED_RESET_RVAS              (9)
+#define ASPEED_RESET_PCI_VGA           (8)
+#define ASPEED_RESET_2D                        (7)
+#define ASPEED_RESET_VIDEO             (6)
+#define ASPEED_RESET_PCI_DP            (5)
+#define ASPEED_RESET_HACE              (4)
+#define ASPEED_RESET_EHCI_P2           (3)
+#define ASPEED_RESET_RESERVED2         (2)
+#define ASPEED_RESET_AHB               (1)
+#define ASPEED_RESET_SDRAM             (0)
+
+#endif  /* _ABI_MACH_ASPEED_AST2600_RESET_H_ */
index df9bee2..48e48a6 100644 (file)
@@ -1693,10 +1693,6 @@ struct efi_driver_binding_protocol {
        efi_handle_t driver_binding_handle;
 };
 
-/* Deprecated version of the Unicode collation protocol */
-#define EFI_UNICODE_COLLATION_PROTOCOL_GUID \
-       EFI_GUID(0x1d85cd7f, 0xf43d, 0x11d2, \
-                0x9a, 0x0c, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d)
 /* Current version of the Unicode collation protocol */
 #define EFI_UNICODE_COLLATION_PROTOCOL2_GUID \
        EFI_GUID(0xa4c751fc, 0x23ae, 0x4c3e, \
index e53d286..f470bbd 100644 (file)
@@ -147,9 +147,6 @@ extern const struct efi_device_path_to_text_protocol efi_device_path_to_text;
 /* implementation of the EFI_DEVICE_PATH_UTILITIES_PROTOCOL */
 extern const struct efi_device_path_utilities_protocol
                                        efi_device_path_utilities;
-/* deprecated version of the EFI_UNICODE_COLLATION_PROTOCOL */
-extern const struct efi_unicode_collation_protocol
-                                       efi_unicode_collation_protocol;
 /* current version of the EFI_UNICODE_COLLATION_PROTOCOL */
 extern const struct efi_unicode_collation_protocol
                                        efi_unicode_collation_protocol2;
@@ -564,7 +561,7 @@ struct efi_file_handle *efi_file_from_path(struct efi_device_path *fp);
  * @size:      size in bytes
  * Return:     size in pages
  */
-#define efi_size_in_pages(size) ((size + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT)
+#define efi_size_in_pages(size) (((size) + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT)
 /* Generic EFI memory allocator, call this to get memory */
 void *efi_alloc(uint64_t len, int memory_type);
 /* More specific EFI memory allocator, called by EFI payloads */
index bf50762..4623a64 100644 (file)
@@ -306,4 +306,15 @@ efi_status_t __efi_runtime EFIAPI
 efi_get_next_variable_name_runtime(efi_uintn_t *variable_name_size,
                                   u16 *variable_name, efi_guid_t *guid);
 
+/**
+ * efi_var_buf_update() - udpate memory buffer for variables
+ *
+ * @var_buf:   source buffer
+ *
+ * This function copies to the memory buffer for UEFI variables. Call this
+ * function in ExitBootServices() if memory backed variables are only used
+ * at runtime to fill the buffer.
+ */
+void efi_var_buf_update(struct efi_var_file *var_buf);
+
 #endif
index b9f273f..bd8e450 100644 (file)
@@ -132,8 +132,13 @@ typedef struct volume_info
 #define CASE_LOWER_BASE        8       /* base (name) is lower case */
 #define CASE_LOWER_EXT 16      /* extension is lower case */
 
+struct nameext {
+       char name[8];
+       char ext[3];
+};
+
 typedef struct dir_entry {
-       char    name[8],ext[3]; /* Name and extension */
+       struct nameext nameext; /* Name and extension */
        __u8    attr;           /* Attribute bits */
        __u8    lcase;          /* Case for name and ext (CASE_LOWER_x) */
        __u8    ctime_ms;       /* Creation time, milliseconds */
diff --git a/include/power/mp5416.h b/include/power/mp5416.h
new file mode 100644 (file)
index 0000000..dc096fe
--- /dev/null
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* Copyright (C) 2020 Gateworks Corporation */
+
+#ifndef MP5416_H_
+#define MP5416_H_
+
+#define MP6416_REGULATOR_DRIVER "mp5416_regulator"
+
+enum {
+       MP5416_CTL0             = 0x00,
+       MP5416_CTL1             = 0x01,
+       MP5416_CTL2             = 0x02,
+       MP5416_ILIMIT           = 0x03,
+       MP5416_VSET_SW1         = 0x04,
+       MP5416_VSET_SW2         = 0x05,
+       MP5416_VSET_SW3         = 0x06,
+       MP5416_VSET_SW4         = 0x07,
+       MP5416_VSET_LDO2        = 0x08,
+       MP5416_VSET_LDO3        = 0x09,
+       MP5416_VSET_LDO4        = 0x0a,
+       MP5416_VSET_LDO5        = 0x0b,
+       MP5416_STATUS1          = 0x0d,
+       MP5416_STATUS2          = 0x0e,
+       MP5416_STATUS3          = 0x0f,
+       MP5416_ID2              = 0x11,
+       MP5416_NUM_OF_REGS      = 0x12,
+};
+
+#define MP5416_VSET_EN          BIT(7)
+#define MP5416_VSET_SW1_GVAL(x) ((((x) & 0x7f) * 12500) + 600000)
+#define MP5416_VSET_SW2_GVAL(x) ((((x) & 0x7f) * 25000) + 800000)
+#define MP5416_VSET_SW3_GVAL(x) ((((x) & 0x7f) * 12500) + 600000)
+#define MP5416_VSET_SW4_GVAL(x) ((((x) & 0x7f) * 25000) + 800000)
+#define MP5416_VSET_LDO_GVAL(x) ((((x) & 0x7f) * 25000) + 800000)
+#define MP5416_VSET_LDO_SVAL(x) ((((x) & 0x7f) * 25000) + 800000)
+#define MP5416_VSET_SW1_SVAL(x) (((x) - 600000) / 12500)
+#define MP5416_VSET_SW2_SVAL(x) (((x) - 800000) / 25000)
+#define MP5416_VSET_SW3_SVAL(x) (((x) - 600000) / 12500)
+#define MP5416_VSET_SW4_SVAL(x) (((x) - 800000) / 25000)
+
+#endif
index fdf245d..e729f72 100644 (file)
@@ -27,6 +27,14 @@ config EFI_LOADER
 
 if EFI_LOADER
 
+config CMD_BOOTEFI_BOOTMGR
+       bool "UEFI Boot Manager"
+       default y
+       help
+         Select this option if you want to select the UEFI binary to be booted
+         via UEFI variables Boot####, BootOrder, and BootNext. This enables the
+         'bootefi bootmgr' command.
+
 config EFI_SETUP_EARLY
        bool
        default n
@@ -200,6 +208,21 @@ config EFI_DEVICE_PATH_TO_TEXT
          The device path to text protocol converts device nodes and paths to
          human readable strings.
 
+config EFI_DEVICE_PATH_UTIL
+       bool "Device path utilities protocol"
+       default y
+       help
+         The device path utilities protocol creates and manipulates device
+         paths and device nodes. It is required to run the EFI Shell.
+
+config EFI_DT_FIXUP
+       bool "Device tree fixup protocol"
+       depends on !GENERATE_ACPI_TABLE
+       default y
+       help
+         The EFI device-tree fix-up protocol provides a function to let the
+         firmware apply fix-ups. This may be used by boot loaders.
+
 config EFI_LOADER_HII
        bool "HII protocols"
        default y
@@ -229,17 +252,6 @@ config EFI_UNICODE_CAPITALIZATION
          set, only the the correct handling of the letters of the codepage
          used by the FAT file system is ensured.
 
-config EFI_UNICODE_COLLATION_PROTOCOL
-       bool "Deprecated version of the Unicode collation protocol"
-       default n
-       help
-         In EFI 1.10 a version of the Unicode collation protocol using ISO
-         639-2 language codes existed. This protocol is not part of the UEFI
-         specification any longer. Unfortunately it is required to run the
-         UEFI Self Certification Test (SCT) II, version 2.6, 2017.
-
-         Choose this option for testing only. It is bound to be removed.
-
 endif
 
 config EFI_LOADER_BOUNCE_BUFFER
index 412fa88..10b42e8 100644 (file)
@@ -21,20 +21,21 @@ targets += helloworld.o
 endif
 
 obj-$(CONFIG_CMD_BOOTEFI_HELLO) += helloworld_efi.o
-obj-y += efi_bootmgr.o
+obj-$(CONFIG_CMD_BOOTEFI_BOOTMGR) += efi_bootmgr.o
 obj-y += efi_boottime.o
 obj-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += efi_capsule.o
 obj-$(CONFIG_EFI_CAPSULE_FIRMWARE) += efi_firmware.o
 obj-y += efi_console.o
 obj-y += efi_device_path.o
 obj-$(CONFIG_EFI_DEVICE_PATH_TO_TEXT) += efi_device_path_to_text.o
-obj-y += efi_device_path_utilities.o
+obj-$(CONFIG_EFI_DEVICE_PATH_UTIL) += efi_device_path_utilities.o
 ifeq ($(CONFIG_GENERATE_ACPI_TABLE),)
 obj-y += efi_dt_fixup.o
 endif
 obj-y += efi_file.o
 obj-$(CONFIG_EFI_LOADER_HII) += efi_hii.o
 obj-y += efi_image_loader.o
+obj-y += efi_load_options.o
 obj-y += efi_memory.o
 obj-y += efi_root_node.o
 obj-y += efi_runtime.o
index d3be2f9..25f5ceb 100644 (file)
@@ -31,141 +31,6 @@ static const struct efi_runtime_services *rs;
  */
 
 /**
- * efi_set_load_options() - set the load options of a loaded image
- *
- * @handle:            the image handle
- * @load_options_size: size of load options
- * @load_options:      pointer to load options
- * Return:             status code
- */
-efi_status_t efi_set_load_options(efi_handle_t handle,
-                                 efi_uintn_t load_options_size,
-                                 void *load_options)
-{
-       struct efi_loaded_image *loaded_image_info;
-       efi_status_t ret;
-
-       ret = EFI_CALL(systab.boottime->open_protocol(
-                                       handle,
-                                       &efi_guid_loaded_image,
-                                       (void **)&loaded_image_info,
-                                       efi_root, NULL,
-                                       EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL));
-       if (ret != EFI_SUCCESS)
-               return EFI_INVALID_PARAMETER;
-
-       loaded_image_info->load_options = load_options;
-       loaded_image_info->load_options_size = load_options_size;
-
-       return EFI_CALL(systab.boottime->close_protocol(handle,
-                                                       &efi_guid_loaded_image,
-                                                       efi_root, NULL));
-}
-
-
-/**
- * efi_deserialize_load_option() - parse serialized data
- *
- * Parse serialized data describing a load option and transform it to the
- * efi_load_option structure.
- *
- * @lo:                pointer to target
- * @data:      serialized data
- * @size:      size of the load option, on return size of the optional data
- * Return:     status code
- */
-efi_status_t efi_deserialize_load_option(struct efi_load_option *lo, u8 *data,
-                                        efi_uintn_t *size)
-{
-       efi_uintn_t len;
-
-       len = sizeof(u32);
-       if (*size < len + 2 * sizeof(u16))
-               return EFI_INVALID_PARAMETER;
-       lo->attributes = get_unaligned_le32(data);
-       data += len;
-       *size -= len;
-
-       len = sizeof(u16);
-       lo->file_path_length = get_unaligned_le16(data);
-       data += len;
-       *size -= len;
-
-       lo->label = (u16 *)data;
-       len = u16_strnlen(lo->label, *size / sizeof(u16) - 1);
-       if (lo->label[len])
-               return EFI_INVALID_PARAMETER;
-       len = (len + 1) * sizeof(u16);
-       if (*size < len)
-               return EFI_INVALID_PARAMETER;
-       data += len;
-       *size -= len;
-
-       len = lo->file_path_length;
-       if (*size < len)
-               return EFI_INVALID_PARAMETER;
-       lo->file_path = (struct efi_device_path *)data;
-       if (efi_dp_check_length(lo->file_path, len) < 0)
-               return EFI_INVALID_PARAMETER;
-       data += len;
-       *size -= len;
-
-       lo->optional_data = data;
-
-       return EFI_SUCCESS;
-}
-
-/**
- * efi_serialize_load_option() - serialize load option
- *
- * Serialize efi_load_option structure into byte stream for BootXXXX.
- *
- * @data:      buffer for serialized data
- * @lo:                load option
- * Return:     size of allocated buffer
- */
-unsigned long efi_serialize_load_option(struct efi_load_option *lo, u8 **data)
-{
-       unsigned long label_len;
-       unsigned long size;
-       u8 *p;
-
-       label_len = (u16_strlen(lo->label) + 1) * sizeof(u16);
-
-       /* total size */
-       size = sizeof(lo->attributes);
-       size += sizeof(lo->file_path_length);
-       size += label_len;
-       size += lo->file_path_length;
-       if (lo->optional_data)
-               size += (utf8_utf16_strlen((const char *)lo->optional_data)
-                                          + 1) * sizeof(u16);
-       p = malloc(size);
-       if (!p)
-               return 0;
-
-       /* copy data */
-       *data = p;
-       memcpy(p, &lo->attributes, sizeof(lo->attributes));
-       p += sizeof(lo->attributes);
-
-       memcpy(p, &lo->file_path_length, sizeof(lo->file_path_length));
-       p += sizeof(lo->file_path_length);
-
-       memcpy(p, lo->label, label_len);
-       p += label_len;
-
-       memcpy(p, lo->file_path, lo->file_path_length);
-       p += lo->file_path_length;
-
-       if (lo->optional_data) {
-               utf8_utf16_strcpy((u16 **)&p, (const char *)lo->optional_data);
-               p += sizeof(u16); /* size of trailing \0 */
-       }
-       return size;
-}
-
-/**
  * get_var() - get UEFI variable
  *
  * It is the caller's duty to free the returned buffer.
index b2cb016..ce658a8 100644 (file)
@@ -687,8 +687,15 @@ efi_status_t efi_create_event(uint32_t type, efi_uintn_t notify_tpl,
                return EFI_INVALID_PARAMETER;
        }
 
+       /*
+        * The UEFI specification requires event notification levels to be
+        * > TPL_APPLICATION and <= TPL_HIGH_LEVEL.
+        *
+        * Parameter NotifyTpl should not be checked if it is not used.
+        */
        if ((type & (EVT_NOTIFY_WAIT | EVT_NOTIFY_SIGNAL)) &&
-           (!notify_function || is_valid_tpl(notify_tpl) != EFI_SUCCESS))
+           (!notify_function || is_valid_tpl(notify_tpl) != EFI_SUCCESS ||
+            notify_tpl == TPL_APPLICATION))
                return EFI_INVALID_PARAMETER;
 
        ret = efi_allocate_pool(pool_type, sizeof(struct efi_event),
@@ -1990,10 +1997,7 @@ efi_status_t efi_load_image_from_path(bool boot_policy,
        if (ret != EFI_SUCCESS)
                efi_free_pages(addr, pages);
 out:
-       if (load_file_protocol)
-               EFI_CALL(efi_close_protocol(device,
-                                           &efi_guid_load_file2_protocol,
-                                           efi_root, NULL));
+       EFI_CALL(efi_close_protocol(device, guid, efi_root, NULL));
        if (ret == EFI_SUCCESS) {
                *buffer = (void *)(uintptr_t)addr;
                *size = buffer_size;
index dad1b0f..0d5a7b6 100644 (file)
@@ -764,7 +764,7 @@ static efi_status_t efi_capsule_scan_dir(u16 ***files, unsigned int *num)
                goto err;
 
        /* make a list */
-       tmp_files = malloc(count * sizeof(*files));
+       tmp_files = malloc(count * sizeof(*tmp_files));
        if (!tmp_files) {
                ret = EFI_OUT_OF_RESOURCES;
                goto err;
index 26b9534..c0804ef 100644 (file)
@@ -343,7 +343,7 @@ static int efi_fs_exists(struct blk_desc *desc, int part)
  * @if_typename:       interface name for block device
  * @desc:              internal block device
  * @dev_index:         device index for block device
- * @offset:            offset into disk for simple partitions
+ * @part_info:         partition info
  * @part:              partition
  * @disk:              pointer to receive the created handle
  * Return:             disk object
@@ -354,7 +354,7 @@ static efi_status_t efi_disk_add_dev(
                                const char *if_typename,
                                struct blk_desc *desc,
                                int dev_index,
-                               lbaint_t offset,
+                               struct disk_partition *part_info,
                                unsigned int part,
                                struct efi_disk_obj **disk)
 {
@@ -374,7 +374,7 @@ static efi_status_t efi_disk_add_dev(
        efi_add_handle(&diskobj->header);
 
        /* Fill in object data */
-       if (part) {
+       if (part_info) {
                struct efi_device_path *node = efi_dp_part_node(desc, part);
                struct efi_handler *handler;
                void *protocol_interface;
@@ -396,8 +396,12 @@ static efi_status_t efi_disk_add_dev(
 
                diskobj->dp = efi_dp_append_node(dp_parent, node);
                efi_free_pool(node);
+               diskobj->offset = part_info->start;
+               diskobj->media.last_block = part_info->size - 1;
        } else {
                diskobj->dp = efi_dp_from_part(desc, part);
+               diskobj->offset = 0;
+               diskobj->media.last_block = desc->lba - 1;
        }
        diskobj->part = part;
 
@@ -432,7 +436,6 @@ static efi_status_t efi_disk_add_dev(
        diskobj->ops = block_io_disk_template;
        diskobj->ifname = if_typename;
        diskobj->dev_index = dev_index;
-       diskobj->offset = offset;
        diskobj->desc = desc;
 
        /* Fill in EFI IO Media info (for read/write callbacks) */
@@ -445,13 +448,21 @@ static efi_status_t efi_disk_add_dev(
        diskobj->media.media_id = 1;
        diskobj->media.block_size = desc->blksz;
        diskobj->media.io_align = desc->blksz;
-       diskobj->media.last_block = desc->lba - offset;
        if (part)
                diskobj->media.logical_partition = 1;
        diskobj->ops.media = &diskobj->media;
        if (disk)
                *disk = diskobj;
 
+       EFI_PRINT("BlockIO: part %u, present %d, logical %d, removable %d"
+                 ", offset " LBAF ", last_block %llu\n",
+                 diskobj->part,
+                 diskobj->media.media_present,
+                 diskobj->media.logical_partition,
+                 diskobj->media.removable_media,
+                 diskobj->offset,
+                 diskobj->media.last_block);
+
        /* Store first EFI system partition */
        if (part && !efi_system_partition.if_type) {
                int r;
@@ -493,7 +504,6 @@ int efi_disk_create_partitions(efi_handle_t parent, struct blk_desc *desc,
 {
        int disks = 0;
        char devname[32] = { 0 }; /* dp->str is u16[32] long */
-       struct disk_partition info;
        int part;
        struct efi_device_path *dp = NULL;
        efi_status_t ret;
@@ -506,12 +516,14 @@ int efi_disk_create_partitions(efi_handle_t parent, struct blk_desc *desc,
 
        /* Add devices for each partition */
        for (part = 1; part <= MAX_SEARCH_PARTITIONS; part++) {
+               struct disk_partition info;
+
                if (part_get_info(desc, part, &info))
                        continue;
                snprintf(devname, sizeof(devname), "%s:%d", pdevname,
                         part);
                ret = efi_disk_add_dev(parent, dp, if_typename, desc, diskid,
-                                      info.start, part, NULL);
+                                      &info, part, NULL);
                if (ret != EFI_SUCCESS) {
                        log_err("Adding partition %s failed\n", pdevname);
                        continue;
@@ -553,7 +565,7 @@ efi_status_t efi_disk_register(void)
                /* Add block device for the full device */
                log_info("Scanning disk %s...\n", dev->name);
                ret = efi_disk_add_dev(NULL, NULL, if_typename,
-                                       desc, desc->devnum, 0, 0, &disk);
+                                       desc, desc->devnum, NULL, 0, &disk);
                if (ret == EFI_NOT_READY) {
                        log_notice("Disk %s not ready\n", dev->name);
                        continue;
@@ -599,7 +611,7 @@ efi_status_t efi_disk_register(void)
 
                        /* Add block device for the full device */
                        ret = efi_disk_add_dev(NULL, NULL, if_typename, desc,
-                                              i, 0, 0, &disk);
+                                              i, NULL, 0, &disk);
                        if (ret == EFI_NOT_READY) {
                                log_notice("Disk %s not ready\n", devname);
                                continue;
index 5f0ae5c..3850ab3 100644 (file)
 #include <efi_loader.h>
 #include <mapmem.h>
 
-static efi_status_t EFIAPI efi_dt_fixup(struct efi_dt_fixup_protocol *this,
-                                       void *dtb,
-                                       efi_uintn_t *buffer_size,
-                                       u32 flags);
-
-struct efi_dt_fixup_protocol efi_dt_fixup_prot = {
-       .revision = EFI_DT_FIXUP_PROTOCOL_REVISION,
-       .fixup = efi_dt_fixup
-};
-
 const efi_guid_t efi_guid_dt_fixup_protocol = EFI_DT_FIXUP_PROTOCOL_GUID;
 
 /**
@@ -102,10 +92,21 @@ void efi_carve_out_dt_rsv(void *fdt)
        }
 }
 
-static efi_status_t EFIAPI efi_dt_fixup(struct efi_dt_fixup_protocol *this,
-                                       void *dtb,
-                                       efi_uintn_t *buffer_size,
-                                       u32 flags)
+/**
+ * efi_dt_fixup() - fix up device tree
+ *
+ * This function implements the Fixup() service of the
+ * EFI Device Tree Fixup Protocol.
+ *
+ * @this:              instance of the protocol
+ * @dtb:               device tree provided by caller
+ * @buffer_size:       size of buffer for the device tree including free space
+ * @flags:             bit field designating action to be performed
+ * Return:             status code
+ */
+static efi_status_t __maybe_unused EFIAPI
+efi_dt_fixup(struct efi_dt_fixup_protocol *this, void *dtb,
+            efi_uintn_t *buffer_size, u32 flags)
 {
        efi_status_t ret;
        size_t required_size;
@@ -158,3 +159,8 @@ static efi_status_t EFIAPI efi_dt_fixup(struct efi_dt_fixup_protocol *this,
 out:
        return EFI_EXIT(ret);
 }
+
+struct efi_dt_fixup_protocol efi_dt_fixup_prot = {
+       .revision = EFI_DT_FIXUP_PROTOCOL_REVISION,
+       .fixup = efi_dt_fixup
+};
diff --git a/lib/efi_loader/efi_load_options.c b/lib/efi_loader/efi_load_options.c
new file mode 100644 (file)
index 0000000..68cd85b
--- /dev/null
@@ -0,0 +1,149 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ *  EFI boot manager
+ *
+ *  Copyright (c) 2018 AKASHI Takahiro, et.al.
+ */
+
+#define LOG_CATEGORY LOGC_EFI
+
+#include <common.h>
+#include <charset.h>
+#include <log.h>
+#include <malloc.h>
+#include <efi_loader.h>
+#include <asm/unaligned.h>
+
+/**
+ * efi_set_load_options() - set the load options of a loaded image
+ *
+ * @handle:            the image handle
+ * @load_options_size: size of load options
+ * @load_options:      pointer to load options
+ * Return:             status code
+ */
+efi_status_t efi_set_load_options(efi_handle_t handle,
+                                 efi_uintn_t load_options_size,
+                                 void *load_options)
+{
+       struct efi_loaded_image *loaded_image_info;
+       efi_status_t ret;
+
+       ret = EFI_CALL(systab.boottime->open_protocol(
+                                       handle,
+                                       &efi_guid_loaded_image,
+                                       (void **)&loaded_image_info,
+                                       efi_root, NULL,
+                                       EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL));
+       if (ret != EFI_SUCCESS)
+               return EFI_INVALID_PARAMETER;
+
+       loaded_image_info->load_options = load_options;
+       loaded_image_info->load_options_size = load_options_size;
+
+       return EFI_CALL(systab.boottime->close_protocol(handle,
+                                                       &efi_guid_loaded_image,
+                                                       efi_root, NULL));
+}
+
+/**
+ * efi_deserialize_load_option() - parse serialized data
+ *
+ * Parse serialized data describing a load option and transform it to the
+ * efi_load_option structure.
+ *
+ * @lo:                pointer to target
+ * @data:      serialized data
+ * @size:      size of the load option, on return size of the optional data
+ * Return:     status code
+ */
+efi_status_t efi_deserialize_load_option(struct efi_load_option *lo, u8 *data,
+                                        efi_uintn_t *size)
+{
+       efi_uintn_t len;
+
+       len = sizeof(u32);
+       if (*size < len + 2 * sizeof(u16))
+               return EFI_INVALID_PARAMETER;
+       lo->attributes = get_unaligned_le32(data);
+       data += len;
+       *size -= len;
+
+       len = sizeof(u16);
+       lo->file_path_length = get_unaligned_le16(data);
+       data += len;
+       *size -= len;
+
+       lo->label = (u16 *)data;
+       len = u16_strnlen(lo->label, *size / sizeof(u16) - 1);
+       if (lo->label[len])
+               return EFI_INVALID_PARAMETER;
+       len = (len + 1) * sizeof(u16);
+       if (*size < len)
+               return EFI_INVALID_PARAMETER;
+       data += len;
+       *size -= len;
+
+       len = lo->file_path_length;
+       if (*size < len)
+               return EFI_INVALID_PARAMETER;
+       lo->file_path = (struct efi_device_path *)data;
+       if (efi_dp_check_length(lo->file_path, len) < 0)
+               return EFI_INVALID_PARAMETER;
+       data += len;
+       *size -= len;
+
+       lo->optional_data = data;
+
+       return EFI_SUCCESS;
+}
+
+/**
+ * efi_serialize_load_option() - serialize load option
+ *
+ * Serialize efi_load_option structure into byte stream for BootXXXX.
+ *
+ * @data:      buffer for serialized data
+ * @lo:                load option
+ * Return:     size of allocated buffer
+ */
+unsigned long efi_serialize_load_option(struct efi_load_option *lo, u8 **data)
+{
+       unsigned long label_len;
+       unsigned long size;
+       u8 *p;
+
+       label_len = (u16_strlen(lo->label) + 1) * sizeof(u16);
+
+       /* total size */
+       size = sizeof(lo->attributes);
+       size += sizeof(lo->file_path_length);
+       size += label_len;
+       size += lo->file_path_length;
+       if (lo->optional_data)
+               size += (utf8_utf16_strlen((const char *)lo->optional_data)
+                                          + 1) * sizeof(u16);
+       p = malloc(size);
+       if (!p)
+               return 0;
+
+       /* copy data */
+       *data = p;
+       memcpy(p, &lo->attributes, sizeof(lo->attributes));
+       p += sizeof(lo->attributes);
+
+       memcpy(p, &lo->file_path_length, sizeof(lo->file_path_length));
+       p += sizeof(lo->file_path_length);
+
+       memcpy(p, lo->label, label_len);
+       p += label_len;
+
+       memcpy(p, lo->file_path, lo->file_path_length);
+       p += lo->file_path_length;
+
+       if (lo->optional_data) {
+               utf8_utf16_strcpy((u16 **)&p, (const char *)lo->optional_data);
+               p += sizeof(u16); /* size of trailing \0 */
+       }
+       return size;
+}
index b411a12..739c686 100644 (file)
@@ -58,21 +58,17 @@ efi_status_t efi_root_node_register(void)
                         &efi_guid_device_path_to_text_protocol,
                         (void *)&efi_device_path_to_text,
 #endif
+#ifdef CONFIG_EFI_DEVICE_PATH_UTIL
                         /* Device path utilities protocol */
                         &efi_guid_device_path_utilities_protocol,
                         (void *)&efi_device_path_utilities,
-#if !CONFIG_IS_ENABLED(GENERATE_ACPI_TABLE)
+#endif
+#ifdef CONFIG_EFI_DT_FIXUP
                         /* Device-tree fix-up protocol */
                         &efi_guid_dt_fixup_protocol,
                         (void *)&efi_dt_fixup_prot,
 #endif
 #if CONFIG_IS_ENABLED(EFI_UNICODE_COLLATION_PROTOCOL2)
-#if CONFIG_IS_ENABLED(EFI_UNICODE_COLLATION_PROTOCOL)
-                        /* Deprecated Unicode collation protocol */
-                        &efi_guid_unicode_collation_protocol,
-                        (void *)&efi_unicode_collation_protocol,
-#endif
-                        /* Current Unicode collation protocol */
                         &efi_guid_unicode_collation_protocol2,
                         (void *)&efi_unicode_collation_protocol2,
 #endif
index 6655c68..f6c875b 100644 (file)
@@ -38,7 +38,7 @@ const efi_guid_t efi_guid_unicode_collation_protocol2 =
  * @s2:                second string
  *
  * This function implements the StriColl() service of the
- * EFI_UNICODE_COLLATION_PROTOCOL.
+ * EFI_UNICODE_COLLATION_PROTOCOL2.
  *
  * See the Unified Extensible Firmware Interface (UEFI) specification for
  * details.
@@ -179,7 +179,7 @@ static bool metai_match(const u16 *string, const u16 *pattern)
  *     - [<char1>-<char2>] matches any character in the range
  *
  * This function implements the MetaMatch() service of the
- * EFI_UNICODE_COLLATION_PROTOCOL.
+ * EFI_UNICODE_COLLATION_PROTOCOL2.
  *
  * Return:     true if the string is matched.
  */
@@ -204,7 +204,7 @@ static bool EFIAPI efi_metai_match(struct efi_unicode_collation_protocol *this,
  * same number of words this does not pose a problem.
  *
  * This function implements the StrLwr() service of the
- * EFI_UNICODE_COLLATION_PROTOCOL.
+ * EFI_UNICODE_COLLATION_PROTOCOL2.
  */
 static void EFIAPI efi_str_lwr(struct efi_unicode_collation_protocol *this,
                               u16 *string)
@@ -225,7 +225,7 @@ static void EFIAPI efi_str_lwr(struct efi_unicode_collation_protocol *this,
  * same number of words this does not pose a problem.
  *
  * This function implements the StrUpr() service of the
- * EFI_UNICODE_COLLATION_PROTOCOL.
+ * EFI_UNICODE_COLLATION_PROTOCOL2.
  */
 static void EFIAPI efi_str_upr(struct efi_unicode_collation_protocol *this,
                               u16 *string)
@@ -245,7 +245,7 @@ static void EFIAPI efi_str_upr(struct efi_unicode_collation_protocol *this,
  * @string:    converted string
  *
  * This function implements the FatToStr() service of the
- * EFI_UNICODE_COLLATION_PROTOCOL.
+ * EFI_UNICODE_COLLATION_PROTOCOL2.
  */
 static void EFIAPI efi_fat_to_str(struct efi_unicode_collation_protocol *this,
                                  efi_uintn_t fat_size, char *fat, u16 *string)
@@ -276,7 +276,7 @@ static void EFIAPI efi_fat_to_str(struct efi_unicode_collation_protocol *this,
  * @fat:       converted string
  *
  * This function implements the StrToFat() service of the
- * EFI_UNICODE_COLLATION_PROTOCOL.
+ * EFI_UNICODE_COLLATION_PROTOCOL2.
  *
  * Return:     true if an illegal character was substituted by '_'.
  */
@@ -337,30 +337,3 @@ const struct efi_unicode_collation_protocol efi_unicode_collation_protocol2 = {
        .str_to_fat = efi_str_to_fat,
        .supported_languages = "en",
 };
-
-/*
- * In EFI 1.10 a version of the Unicode collation protocol using ISO 639-2
- * language codes existed. This protocol is not part of the UEFI specification
- * any longer. Unfortunately it is required to run the UEFI Self Certification
- * Test (SCT) II, version 2.6, 2017. So we implement it here for the sole
- * purpose of running the SCT. It can be removed when a compliant SCT is
- * available.
- */
-#if CONFIG_IS_ENABLED(EFI_UNICODE_COLLATION_PROTOCOL)
-
-/* GUID of the EFI_UNICODE_COLLATION_PROTOCOL */
-const efi_guid_t efi_guid_unicode_collation_protocol =
-       EFI_UNICODE_COLLATION_PROTOCOL_GUID;
-
-const struct efi_unicode_collation_protocol efi_unicode_collation_protocol = {
-       .stri_coll = efi_stri_coll,
-       .metai_match = efi_metai_match,
-       .str_lwr = efi_str_lwr,
-       .str_upr = efi_str_upr,
-       .fat_to_str = efi_fat_to_str,
-       .str_to_fat = efi_str_to_fat,
-       /* ISO 639-2 language code */
-       .supported_languages = "eng",
-};
-
-#endif
index d155f25..3d335a8 100644 (file)
 #include <efi_variable.h>
 #include <u-boot/crc.h>
 
-struct efi_var_file __efi_runtime_data *efi_var_buf;
+/*
+ * The variables efi_var_file and efi_var_entry must be static to avoid
+ * referencing them via the global offset table (section .got). The GOT
+ * is neither mapped as EfiRuntimeServicesData nor do we support its
+ * relocation during SetVirtualAddressMap().
+ */
+static struct efi_var_file __efi_runtime_data *efi_var_buf;
 static struct efi_var_entry __efi_runtime_data *efi_current_var;
 
 /**
@@ -339,3 +345,8 @@ efi_get_next_variable_name_mem(efi_uintn_t *variable_name_size,
 
        return EFI_SUCCESS;
 }
+
+void efi_var_buf_update(struct efi_var_file *var_buf)
+{
+       memcpy(efi_var_buf, var_buf, EFI_VAR_BUF_SIZE);
+}
index b8808fd..51920bc 100644 (file)
@@ -702,7 +702,7 @@ void efi_variables_boot_exit_notify(void)
        if (ret != EFI_SUCCESS)
                log_err("Can't populate EFI variables. No runtime variables will be available\n");
        else
-               memcpy(efi_var_buf, var_buf, len);
+               efi_var_buf_update(var_buf);
        free(var_buf);
 
        /* Update runtime service table */
index 426552b..7d6ea30 100644 (file)
@@ -14,6 +14,8 @@ CFLAGS_efi_selftest_miniapp_exit.o := $(CFLAGS_EFI) -Os -ffreestanding
 CFLAGS_REMOVE_efi_selftest_miniapp_exit.o := $(CFLAGS_NON_EFI)
 CFLAGS_efi_selftest_miniapp_return.o := $(CFLAGS_EFI) -Os -ffreestanding
 CFLAGS_REMOVE_efi_selftest_miniapp_return.o := $(CFLAGS_NON_EFI)
+CFLAGS_initrddump_exit.o := $(CFLAGS_EFI) -Os -ffreestanding
+CFLAGS_REMOVE_initrddump.o := $(CFLAGS_NON_EFI)
 
 obj-y += \
 efi_selftest.o \
@@ -78,8 +80,13 @@ efi_selftest_miniapp_exception.efi \
 efi_selftest_miniapp_exit.efi \
 efi_selftest_miniapp_return.efi
 
-always += \
-dtbdump.efi
+ifeq ($(CONFIG_GENERATE_ACPI_TABLE),)
+always += dtbdump.efi
+endif
+
+ifdef CONFIG_EFI_LOAD_FILE2_INITRD
+always += initrddump.efi
+endif
 
 $(obj)/efi_miniapp_file_image_exception.h: $(obj)/efi_selftest_miniapp_exception.efi
        $(obj)/../../tools/file2include $(obj)/efi_selftest_miniapp_exception.efi > \
index efef759..953b264 100644 (file)
@@ -29,6 +29,16 @@ static const efi_guid_t efi_dt_fixup_protocol_guid = EFI_DT_FIXUP_PROTOCOL_GUID;
 static const efi_guid_t efi_file_info_guid = EFI_FILE_INFO_GUID;
 
 /**
+ * print() - print string
+ *
+ * @string:    text
+ */
+static void print(u16 *string)
+{
+       cout->output_string(cout, string);
+}
+
+/**
  * error() - print error string
  *
  * @string:    error text
@@ -36,12 +46,56 @@ static const efi_guid_t efi_file_info_guid = EFI_FILE_INFO_GUID;
 static void error(u16 *string)
 {
        cout->set_attribute(cout, EFI_LIGHTRED | EFI_BACKGROUND_BLACK);
-       cout->output_string(cout, string);
+       print(string);
        cout->set_attribute(cout, EFI_LIGHTBLUE | EFI_BACKGROUND_BLACK);
 }
 
 /**
- * input() - read string from console
+ * efi_input_yn() - get answer to yes/no question
+ *
+ * Return:
+ * y or Y
+ *     EFI_SUCCESS
+ * n or N
+ *     EFI_ACCESS_DENIED
+ * ESC
+ *     EFI_ABORTED
+ */
+static efi_status_t efi_input_yn(void)
+{
+       struct efi_input_key key = {0};
+       efi_uintn_t index;
+       efi_status_t ret;
+
+       /* Drain the console input */
+       ret = cin->reset(cin, true);
+       for (;;) {
+               ret = bs->wait_for_event(1, &cin->wait_for_key, &index);
+               if (ret != EFI_SUCCESS)
+                       continue;
+               ret = cin->read_key_stroke(cin, &key);
+               if (ret != EFI_SUCCESS)
+                       continue;
+               switch (key.scan_code) {
+               case 0x17: /* Escape */
+                       return EFI_ABORTED;
+               default:
+                       break;
+               }
+               /* Convert to lower case */
+               switch (key.unicode_char | 0x20) {
+               case 'y':
+                       return EFI_SUCCESS;
+               case 'n':
+                       return EFI_ACCESS_DENIED;
+               default:
+                       break;
+               }
+       }
+}
+
+/**
+ * efi_input() - read string from console
  *
  * @buffer:            input buffer
  * @buffer_size:       buffer size
@@ -67,7 +121,7 @@ static efi_status_t efi_input(u16 *buffer, efi_uintn_t buffer_size)
                        continue;
                switch (key.scan_code) {
                case 0x17: /* Escape */
-                       cout->output_string(cout, L"\nAborted\n");
+                       print(L"\r\nAborted\r\n");
                        return EFI_ABORTED;
                default:
                        break;
@@ -76,12 +130,12 @@ static efi_status_t efi_input(u16 *buffer, efi_uintn_t buffer_size)
                case 0x08: /* Backspace */
                        if (pos) {
                                buffer[pos--] = 0;
-                               cout->output_string(cout, L"\b \b");
+                               print(L"\b \b");
                        }
                        break;
                case 0x0a: /* Linefeed */
                case 0x0d: /* Carriage return */
-                       cout->output_string(cout, L"\n");
+                       print(L"\r\n");
                        return EFI_SUCCESS;
                default:
                        break;
@@ -94,7 +148,7 @@ static efi_status_t efi_input(u16 *buffer, efi_uintn_t buffer_size)
                        *outbuf = key.unicode_char;
                        buffer[pos++] = key.unicode_char;
                        buffer[pos] = 0;
-                       cout->output_string(cout, outbuf);
+                       print(outbuf);
                }
        }
 }
@@ -171,9 +225,9 @@ bool starts_with(u16 *string, u16 *keyword)
  */
 void do_help(void)
 {
-       error(L"load <dtb> - load device-tree from file\n");
-       error(L"save <dtb> - save device-tree to file\n");
-       error(L"exit       - exit the shell\n");
+       error(L"load <dtb> - load device-tree from file\r\n");
+       error(L"save <dtb> - save device-tree to file\r\n");
+       error(L"exit       - exit the shell\r\n");
 }
 
 /**
@@ -198,7 +252,7 @@ efi_status_t do_load(u16 *filename)
        ret = bs->locate_protocol(&efi_dt_fixup_protocol_guid, NULL,
                                  (void **)&dt_fixup_prot);
        if (ret != EFI_SUCCESS) {
-               error(L"Device-tree fix-up protocol not found\n");
+               error(L"Device-tree fix-up protocol not found\r\n");
                return ret;
        }
 
@@ -208,7 +262,7 @@ efi_status_t do_load(u16 *filename)
                                (void **)&loaded_image, NULL, NULL,
                                EFI_OPEN_PROTOCOL_GET_PROTOCOL);
        if (ret != EFI_SUCCESS) {
-               error(L"Loaded image protocol not found\n");
+               error(L"Loaded image protocol not found\r\n");
                return ret;
        }
        /* Open the simple file system protocol */
@@ -217,57 +271,57 @@ efi_status_t do_load(u16 *filename)
                                (void **)&file_system, NULL, NULL,
                                EFI_OPEN_PROTOCOL_GET_PROTOCOL);
        if (ret != EFI_SUCCESS) {
-               error(L"Failed to open simple file system protocol\n");
+               error(L"Failed to open simple file system protocol\r\n");
                goto out;
        }
 
        /* Open volume */
        ret = file_system->open_volume(file_system, &root);
        if (ret != EFI_SUCCESS) {
-               error(L"Failed to open volume\n");
+               error(L"Failed to open volume\r\n");
                goto out;
        }
 
        /* Open file */
        ret = root->open(root, &file, filename, EFI_FILE_MODE_READ, 0);
        if (ret != EFI_SUCCESS) {
-               error(L"File not found\n");
+               error(L"File not found\r\n");
                goto out;
        }
        /* Get file size */
        buffer_size = 0;
        ret = file->getinfo(file, &efi_file_info_guid, &buffer_size, NULL);
        if (ret != EFI_BUFFER_TOO_SMALL) {
-               error(L"Can't get file info size\n");
+               error(L"Can't get file info size\r\n");
                goto out;
        }
        ret = bs->allocate_pool(EFI_LOADER_DATA, buffer_size, (void **)&info);
        if (ret != EFI_SUCCESS) {
-               error(L"Out of memory\n");
+               error(L"Out of memory\r\n");
                goto out;
        }
        ret = file->getinfo(file, &efi_file_info_guid, &buffer_size, info);
        if (ret != EFI_SUCCESS) {
-               error(L"Can't get file info\n");
+               error(L"Can't get file info\r\n");
                goto out;
        }
        buffer_size = info->file_size;
        pages = efi_size_in_pages(buffer_size);
        ret = bs->free_pool(info);
        if (ret != EFI_SUCCESS)
-               error(L"Can't free memory pool\n");
+               error(L"Can't free memory pool\r\n");
        /* Read file */
        ret = bs->allocate_pages(EFI_ALLOCATE_ANY_PAGES,
                                 EFI_ACPI_RECLAIM_MEMORY,
                                 pages, &addr);
        if (ret != EFI_SUCCESS) {
-               error(L"Out of memory\n");
+               error(L"Out of memory\r\n");
                goto out;
        }
        dtb = (struct fdt_header *)(uintptr_t)addr;
        ret = file->read(file, &buffer_size, dtb);
        if (ret != EFI_SUCCESS) {
-               error(L"Can't read file\n");
+               error(L"Can't read file\r\n");
                goto out;
        }
        /* Fixup file, expecting EFI_BUFFER_TOO_SMALL */
@@ -278,24 +332,24 @@ efi_status_t do_load(u16 *filename)
                /* Read file into larger buffer */
                ret = bs->free_pages(addr, pages);
                if (ret != EFI_SUCCESS)
-                       error(L"Can't free memory pages\n");
+                       error(L"Can't free memory pages\r\n");
                pages = efi_size_in_pages(buffer_size);
                ret = bs->allocate_pages(EFI_ALLOCATE_ANY_PAGES,
                                         EFI_ACPI_RECLAIM_MEMORY,
                                         pages, &addr);
                if (ret != EFI_SUCCESS) {
-                       error(L"Out of memory\n");
+                       error(L"Out of memory\r\n");
                        goto out;
                }
                dtb = (struct fdt_header *)(uintptr_t)addr;
                ret = file->setpos(file, 0);
                if (ret != EFI_SUCCESS) {
-                       error(L"Can't position file\n");
+                       error(L"Can't position file\r\n");
                        goto out;
                }
                ret = file->read(file, &buffer_size, dtb);
                if (ret != EFI_SUCCESS) {
-                       error(L"Can't read file\n");
+                       error(L"Can't read file\r\n");
                        goto out;
                }
                buffer_size = pages << EFI_PAGE_SHIFT;
@@ -305,24 +359,24 @@ efi_status_t do_load(u16 *filename)
                                EFI_DT_INSTALL_TABLE);
        }
        if (ret == EFI_SUCCESS)
-               cout->output_string(cout, L"device-tree installed\n");
+               print(L"device-tree installed\r\n");
        else
-               error(L"Device-tree fix-up failed\n");
+               error(L"Device-tree fix-up failed\r\n");
 out:
        if (addr) {
                ret2 = bs->free_pages(addr, pages);
                if (ret2 != EFI_SUCCESS)
-                       error(L"Can't free memory pages\n");
+                       error(L"Can't free memory pages\r\n");
        }
        if (file) {
                ret2 = file->close(file);
                if (ret2 != EFI_SUCCESS)
-                       error(L"Can't close file\n");
+                       error(L"Can't close file\r\n");
        }
        if (root) {
                ret2 = root->close(root);
                if (ret2 != EFI_SUCCESS)
-                       error(L"Can't close volume\n");
+                       error(L"Can't close volume\r\n");
        }
        return ret;
 }
@@ -344,11 +398,11 @@ efi_status_t do_save(u16 *filename)
 
        dtb = get_dtb(systable);
        if (!dtb) {
-               error(L"DTB not found\n");
+               error(L"DTB not found\r\n");
                return EFI_NOT_FOUND;
        }
        if (f2h(dtb->magic) != FDT_MAGIC) {
-               error(L"Wrong device tree magic\n");
+               error(L"Wrong device tree magic\r\n");
                return EFI_NOT_FOUND;
        }
        dtb_size = f2h(dtb->totalsize);
@@ -359,7 +413,7 @@ efi_status_t do_save(u16 *filename)
                                (void **)&loaded_image, NULL, NULL,
                                EFI_OPEN_PROTOCOL_GET_PROTOCOL);
        if (ret != EFI_SUCCESS) {
-               error(L"Loaded image protocol not found\n");
+               error(L"Loaded image protocol not found\r\n");
                return ret;
        }
 
@@ -369,16 +423,30 @@ efi_status_t do_save(u16 *filename)
                                (void **)&file_system, NULL, NULL,
                                EFI_OPEN_PROTOCOL_GET_PROTOCOL);
        if (ret != EFI_SUCCESS) {
-               error(L"Failed to open simple file system protocol\n");
+               error(L"Failed to open simple file system protocol\r\n");
                return ret;
        }
 
        /* Open volume */
        ret = file_system->open_volume(file_system, &root);
        if (ret != EFI_SUCCESS) {
-               error(L"Failed to open volume\n");
+               error(L"Failed to open volume\r\n");
                return ret;
        }
+       /* Check if file already exists */
+       ret = root->open(root, &file, filename, EFI_FILE_MODE_READ, 0);
+       if (ret == EFI_SUCCESS) {
+               file->close(file);
+               print(L"Overwrite existing file (y/n)? ");
+               ret = efi_input_yn();
+               print(L"\r\n");
+               if (ret != EFI_SUCCESS) {
+                       root->close(root);
+                       error(L"Aborted by user\r\n");
+                       return ret;
+               }
+       }
+
        /* Create file */
        ret = root->open(root, &file, filename,
                         EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE |
@@ -387,16 +455,16 @@ efi_status_t do_save(u16 *filename)
                /* Write file */
                ret = file->write(file, &dtb_size, dtb);
                if (ret != EFI_SUCCESS)
-                       error(L"Failed to write file\n");
+                       error(L"Failed to write file\r\n");
                file->close(file);
        } else {
-               error(L"Failed to open file\n");
+               error(L"Failed to open file\r\n");
        }
        root->close(root);
 
        if (ret == EFI_SUCCESS) {
-               cout->output_string(cout, filename);
-               cout->output_string(cout, L" written\n");
+               print(filename);
+               print(L" written\r\n");
        }
 
        return ret;
@@ -422,7 +490,7 @@ efi_status_t EFIAPI efi_main(efi_handle_t image_handle,
        cout->set_attribute(cout, EFI_LIGHTBLUE | EFI_BACKGROUND_BLACK);
        cout->clear_screen(cout);
        cout->set_attribute(cout, EFI_WHITE | EFI_BACKGROUND_BLACK);
-       cout->output_string(cout, L"DTB Dump\n========\n\n");
+       print(L"DTB Dump\r\n========\r\n\r\n");
        cout->set_attribute(cout, EFI_LIGHTBLUE | EFI_BACKGROUND_BLACK);
 
        for (;;) {
@@ -430,7 +498,7 @@ efi_status_t EFIAPI efi_main(efi_handle_t image_handle,
                u16 *pos;
                efi_uintn_t ret;
 
-               cout->output_string(cout, L"=> ");
+               print(L"=> ");
                ret = efi_input(command, sizeof(command));
                if (ret == EFI_ABORTED)
                        break;
index 0219bd7..ffd88a1 100644 (file)
@@ -46,11 +46,10 @@ static void mac(void *pointer, u16 **buf)
 /*
  * printx() - print hexadecimal number to an u16 string
  *
- * @pointer:   pointer
+ * @p:         value to print
  * @prec:      minimum number of digits to print
  * @buf:       pointer to buffer address,
  *             on return position of terminating zero word
- * @size:      size of value to be printed in bytes
  */
 static void printx(u64 p, int prec, u16 **buf)
 {
diff --git a/lib/efi_selftest/initrddump.c b/lib/efi_selftest/initrddump.c
new file mode 100644 (file)
index 0000000..c23a05c
--- /dev/null
@@ -0,0 +1,449 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2020, Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * initrddump.efi saves the initial RAM disk provided via the
+ * EFI_LOAD_FILE2_PROTOCOL.
+ */
+
+#include <common.h>
+#include <efi_api.h>
+#include <efi_load_initrd.h>
+
+#define BUFFER_SIZE 64
+#define ESC 0x17
+
+#define efi_size_in_pages(size) (((size) + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT)
+
+static struct efi_system_table *systable;
+static struct efi_boot_services *bs;
+static struct efi_simple_text_output_protocol *cerr;
+static struct efi_simple_text_output_protocol *cout;
+static struct efi_simple_text_input_protocol *cin;
+static const efi_guid_t loaded_image_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
+static const efi_guid_t guid_simple_file_system_protocol =
+                                       EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;
+static const efi_guid_t load_file2_guid = EFI_LOAD_FILE2_PROTOCOL_GUID;
+static efi_handle_t handle;
+
+/*
+ * Device path defined by Linux to identify the handle providing the
+ * EFI_LOAD_FILE2_PROTOCOL used for loading the initial ramdisk.
+ */
+static const struct efi_initrd_dp initrd_dp = {
+       .vendor = {
+               {
+                  DEVICE_PATH_TYPE_MEDIA_DEVICE,
+                  DEVICE_PATH_SUB_TYPE_VENDOR_PATH,
+                  sizeof(initrd_dp.vendor),
+               },
+               EFI_INITRD_MEDIA_GUID,
+       },
+       .end = {
+               DEVICE_PATH_TYPE_END,
+               DEVICE_PATH_SUB_TYPE_END,
+               sizeof(initrd_dp.end),
+       }
+};
+
+/**
+ * print() - print string
+ *
+ * @string:    text
+ */
+static void print(u16 *string)
+{
+       cout->output_string(cout, string);
+}
+
+/**
+ * error() - print error string
+ *
+ * @string:    error text
+ */
+static void error(u16 *string)
+{
+       cout->set_attribute(cout, EFI_LIGHTRED | EFI_BACKGROUND_BLACK);
+       print(string);
+       cout->set_attribute(cout, EFI_LIGHTBLUE | EFI_BACKGROUND_BLACK);
+}
+
+/*
+ * printx() - print hexadecimal number
+ *
+ * @val:       value to print;
+ * @prec:      minimum number of digits to print
+ */
+static void printx(u64 val, u32 prec)
+{
+       int i;
+       u16 c;
+       u16 buf[16];
+       u16 *pos = buf;
+
+       for (i = 2 * sizeof(val) - 1; i >= 0; --i) {
+               c = (val >> (4 * i)) & 0x0f;
+               if (c || pos != buf || !i || i < prec) {
+                       c += '0';
+                       if (c > '9')
+                               c += 'a' - '9' - 1;
+                       *pos++ = c;
+               }
+       }
+       *pos = 0;
+       print(buf);
+}
+
+/**
+ * efi_input_yn() - get answer to yes/no question
+ *
+ * Return:
+ * y or Y
+ *     EFI_SUCCESS
+ * n or N
+ *     EFI_ACCESS_DENIED
+ * ESC
+ *     EFI_ABORTED
+ */
+static efi_status_t efi_input_yn(void)
+{
+       struct efi_input_key key = {0};
+       efi_uintn_t index;
+       efi_status_t ret;
+
+       /* Drain the console input */
+       ret = cin->reset(cin, true);
+       for (;;) {
+               ret = bs->wait_for_event(1, &cin->wait_for_key, &index);
+               if (ret != EFI_SUCCESS)
+                       continue;
+               ret = cin->read_key_stroke(cin, &key);
+               if (ret != EFI_SUCCESS)
+                       continue;
+               switch (key.scan_code) {
+               case 0x17: /* Escape */
+                       return EFI_ABORTED;
+               default:
+                       break;
+               }
+               /* Convert to lower case */
+               switch (key.unicode_char | 0x20) {
+               case 'y':
+                       return EFI_SUCCESS;
+               case 'n':
+                       return EFI_ACCESS_DENIED;
+               default:
+                       break;
+               }
+       }
+}
+
+/**
+ * efi_input() - read string from console
+ *
+ * @buffer:            input buffer
+ * @buffer_size:       buffer size
+ * Return:             status code
+ */
+static efi_status_t efi_input(u16 *buffer, efi_uintn_t buffer_size)
+{
+       struct efi_input_key key = {0};
+       efi_uintn_t index;
+       efi_uintn_t pos = 0;
+       u16 outbuf[2] = L" ";
+       efi_status_t ret;
+
+       /* Drain the console input */
+       ret = cin->reset(cin, true);
+       *buffer = 0;
+       for (;;) {
+               ret = bs->wait_for_event(1, &cin->wait_for_key, &index);
+               if (ret != EFI_SUCCESS)
+                       continue;
+               ret = cin->read_key_stroke(cin, &key);
+               if (ret != EFI_SUCCESS)
+                       continue;
+               switch (key.scan_code) {
+               case 0x17: /* Escape */
+                       print(L"\r\nAborted\r\n");
+                       return EFI_ABORTED;
+               default:
+                       break;
+               }
+               switch (key.unicode_char) {
+               case 0x08: /* Backspace */
+                       if (pos) {
+                               buffer[pos--] = 0;
+                               print(L"\b \b");
+                       }
+                       break;
+               case 0x0a: /* Linefeed */
+               case 0x0d: /* Carriage return */
+                       print(L"\r\n");
+                       return EFI_SUCCESS;
+               default:
+                       break;
+               }
+               /* Ignore surrogate codes */
+               if (key.unicode_char >= 0xD800 && key.unicode_char <= 0xDBFF)
+                       continue;
+               if (key.unicode_char >= 0x20 &&
+                   pos < buffer_size - 1) {
+                       *outbuf = key.unicode_char;
+                       buffer[pos++] = key.unicode_char;
+                       buffer[pos] = 0;
+                       print(outbuf);
+               }
+       }
+}
+
+/**
+ * skip_whitespace() - skip over leading whitespace
+ *
+ * @pos:       UTF-16 string
+ * Return:     pointer to first non-whitespace
+ */
+static u16 *skip_whitespace(u16 *pos)
+{
+       for (; *pos && *pos <= 0x20; ++pos)
+               ;
+       return pos;
+}
+
+/**
+ * starts_with() - check if @string starts with @keyword
+ *
+ * @string:    string to search for keyword
+ * @keyword:   keyword to be searched
+ * Return:     true fi @string starts with the keyword
+ */
+static bool starts_with(u16 *string, u16 *keyword)
+{
+       for (; *keyword; ++string, ++keyword) {
+               if (*string != *keyword)
+                       return false;
+       }
+       return true;
+}
+
+/**
+ * do_help() - print help
+ */
+static void do_help(void)
+{
+       error(L"load          - show length and CRC32 of initial RAM disk\r\n");
+       error(L"save <initrd> - save initial RAM disk to file\r\n");
+       error(L"exit          - exit the shell\r\n");
+}
+
+/**
+ * get_initrd() - read initial RAM disk via EFI_LOAD_FILE2_PROTOCOL
+ *
+ * @initrd:            on return buffer with initial RAM disk
+ * @initrd_size:       size of initial RAM disk
+ * Return:             status code
+ */
+static efi_status_t get_initrd(void **initrd, efi_uintn_t *initrd_size)
+{
+       struct efi_device_path *dp = (struct efi_device_path *)&initrd_dp;
+       struct efi_load_file_protocol *load_file2_prot;
+       u64 buffer;
+       efi_handle_t handle;
+       efi_status_t ret;
+
+       *initrd = NULL;
+       *initrd_size = 0;
+       ret = bs->locate_device_path(&load_file2_guid, &dp, &handle);
+       if (ret != EFI_SUCCESS) {
+               error(L"Load File2 protocol not found\r\n");
+               return ret;
+       }
+       ret = bs->handle_protocol(handle, &load_file2_guid,
+                                (void **)&load_file2_prot);
+       ret = load_file2_prot->load_file(load_file2_prot, dp, false,
+                                        initrd_size, NULL);
+       if (ret != EFI_BUFFER_TOO_SMALL) {
+               error(L"Load File2 protocol does not provide file length\r\n");
+               return EFI_LOAD_ERROR;
+       }
+       ret = bs->allocate_pages(EFI_ALLOCATE_ANY_PAGES, EFI_LOADER_DATA,
+                                efi_size_in_pages(*initrd_size), &buffer);
+       if (ret != EFI_SUCCESS) {
+               error(L"Out of memory\r\n");
+               return ret;
+       }
+       *initrd = (void *)buffer;
+       ret = load_file2_prot->load_file(load_file2_prot, dp, false,
+                                        initrd_size, *initrd);
+       if (ret != EFI_SUCCESS) {
+               error(L"Load File2 protocol failed to provide file\r\n");
+               bs->free_pages(buffer, efi_size_in_pages(*initrd_size));
+               return EFI_LOAD_ERROR;
+       }
+       return ret;
+}
+
+/**
+ * do_load() - load initial RAM disk and display CRC32 and length
+ *
+ * @filename:  file name
+ * Return:     status code
+ */
+static efi_status_t do_load(void)
+{
+       void *initrd;
+       efi_uintn_t initrd_size;
+       u32 crc32;
+       efi_uintn_t ret;
+
+       ret =  get_initrd(&initrd, &initrd_size);
+       if (ret != EFI_SUCCESS)
+               return ret;
+       print(L"length: 0x");
+       printx(initrd_size, 1);
+       print(L"\r\n");
+
+       ret = bs->calculate_crc32(initrd, initrd_size, &crc32);
+       if (ret != EFI_SUCCESS) {
+               error(L"Calculating CRC32 failed\r\n");
+               return EFI_LOAD_ERROR;
+       }
+       print(L"crc32: 0x");
+       printx(crc32, 8);
+       print(L"\r\n");
+
+       return EFI_SUCCESS;
+}
+
+/**
+ * do_save() - save initial RAM disk
+ *
+ * @filename:  file name
+ * Return:     status code
+ */
+static efi_status_t do_save(u16 *filename)
+{
+       struct efi_loaded_image *loaded_image;
+       struct efi_simple_file_system_protocol *file_system;
+       struct efi_file_handle *root, *file;
+       void *initrd;
+       efi_uintn_t initrd_size;
+       efi_uintn_t ret;
+
+       ret = get_initrd(&initrd, &initrd_size);
+       if (ret != EFI_SUCCESS)
+               return ret;
+
+       filename = skip_whitespace(filename);
+
+       ret = bs->open_protocol(handle, &loaded_image_guid,
+                               (void **)&loaded_image, NULL, NULL,
+                               EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+       if (ret != EFI_SUCCESS) {
+               error(L"Loaded image protocol not found\r\n");
+               goto out;
+       }
+
+       /* Open the simple file system protocol */
+       ret = bs->open_protocol(loaded_image->device_handle,
+                               &guid_simple_file_system_protocol,
+                               (void **)&file_system, NULL, NULL,
+                               EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+       if (ret != EFI_SUCCESS) {
+               error(L"Failed to open simple file system protocol\r\n");
+               goto out;
+       }
+
+       /* Open volume */
+       ret = file_system->open_volume(file_system, &root);
+       if (ret != EFI_SUCCESS) {
+               error(L"Failed to open volume\r\n");
+               goto out;
+       }
+       /* Check if file already exists */
+       ret = root->open(root, &file, filename, EFI_FILE_MODE_READ, 0);
+       if (ret == EFI_SUCCESS) {
+               file->close(file);
+               print(L"Overwrite existing file (y/n)? ");
+               ret = efi_input_yn();
+               print(L"\r\n");
+               if (ret != EFI_SUCCESS) {
+                       root->close(root);
+                       error(L"Aborted by user\r\n");
+                       goto out;
+               }
+       }
+
+       /* Create file */
+       ret = root->open(root, &file, filename,
+                        EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE |
+                        EFI_FILE_MODE_CREATE, EFI_FILE_ARCHIVE);
+       if (ret == EFI_SUCCESS) {
+               /* Write file */
+               ret = file->write(file, &initrd_size, initrd);
+               if (ret != EFI_SUCCESS) {
+                       error(L"Failed to write file\r\n");
+               } else {
+                       print(filename);
+                       print(L" written\r\n");
+               }
+               file->close(file);
+       } else {
+               error(L"Failed to open file\r\n");
+       }
+       root->close(root);
+
+out:
+       if (initrd)
+               bs->free_pages((uintptr_t)initrd,
+                              efi_size_in_pages(initrd_size));
+       return ret;
+}
+
+/**
+ * efi_main() - entry point of the EFI application.
+ *
+ * @handle:    handle of the loaded image
+ * @systab:    system table
+ * @return:    status code
+ */
+efi_status_t EFIAPI efi_main(efi_handle_t image_handle,
+                            struct efi_system_table *systab)
+{
+       handle = image_handle;
+       systable = systab;
+       cerr = systable->std_err;
+       cout = systable->con_out;
+       cin = systable->con_in;
+       bs = systable->boottime;
+
+       cout->set_attribute(cout, EFI_LIGHTBLUE | EFI_BACKGROUND_BLACK);
+       cout->clear_screen(cout);
+       cout->set_attribute(cout, EFI_WHITE | EFI_BACKGROUND_BLACK);
+       print(L"INITRD Dump\r\n========\r\n\r\n");
+       cout->set_attribute(cout, EFI_LIGHTBLUE | EFI_BACKGROUND_BLACK);
+
+       for (;;) {
+               u16 command[BUFFER_SIZE];
+               u16 *pos;
+               efi_uintn_t ret;
+
+               print(L"=> ");
+               ret = efi_input(command, sizeof(command));
+               if (ret == EFI_ABORTED)
+                       break;
+               pos = skip_whitespace(command);
+               if (starts_with(pos, L"exit"))
+                       break;
+               else if (starts_with(pos, L"load"))
+                       do_load();
+               else if (starts_with(pos, L"save "))
+                       do_save(pos + 5);
+               else
+                       do_help();
+       }
+
+       cout->set_attribute(cout, EFI_LIGHTGRAY | EFI_BACKGROUND_BLACK);
+       cout->clear_screen(cout);
+       return EFI_SUCCESS;
+}
index 54a93aa..5bc6867 100644 (file)
@@ -15,6 +15,8 @@
 #include <asm/io.h>
 #include <part_efi.h>
 #include <malloc.h>
+#include <dm/uclass.h>
+#include <rng.h>
 
 /*
  * UUID - Universally Unique IDentifier - 128 bits unique number.
@@ -249,9 +251,22 @@ void gen_rand_uuid(unsigned char *uuid_bin)
 {
        u32 ptr[4];
        struct uuid *uuid = (struct uuid *)ptr;
-       int i;
-
-       srand(get_ticks() + rand());
+       int i, ret;
+       struct udevice *devp;
+       u32 randv = 0;
+
+       if (IS_ENABLED(CONFIG_DM_RNG)) {
+               ret = uclass_get_device(UCLASS_RNG, 0, &devp);
+               if (ret) {
+                       ret = dm_rng_read(devp, &randv, sizeof(randv));
+                       if (ret < 0)
+                               randv = 0;
+               }
+       }
+       if (randv)
+               srand(randv);
+       else
+               srand(get_ticks() + rand());
 
        /* Set all fields randomly */
        for (i = 0; i < 4; i++)
index 0156324..7c2454f 100644 (file)
@@ -26,6 +26,7 @@ DECLARE_GLOBAL_DATA_PTR;
  */
 struct eth_device_priv {
        enum eth_state_t state;
+       bool running;
 };
 
 /**
@@ -290,6 +291,7 @@ int eth_init(void)
                                                dev_get_uclass_priv(current);
 
                                        priv->state = ETH_STATE_ACTIVE;
+                                       priv->running = true;
                                        return 0;
                                }
                        } else {
@@ -319,13 +321,16 @@ void eth_halt(void)
        struct eth_device_priv *priv;
 
        current = eth_get_dev();
-       if (!current || !eth_is_active(current))
+       if (!current)
                return;
 
-       eth_get_ops(current)->stop(current);
        priv = dev_get_uclass_priv(current);
-       if (priv)
-               priv->state = ETH_STATE_PASSIVE;
+       if (!priv || !priv->running)
+               return;
+
+       eth_get_ops(current)->stop(current);
+       priv->state = ETH_STATE_PASSIVE;
+       priv->running = false;
 }
 
 int eth_is_active(struct udevice *dev)
@@ -534,6 +539,7 @@ static int eth_post_probe(struct udevice *dev)
 #endif
 
        priv->state = ETH_STATE_INIT;
+       priv->running = false;
 
        /* Check if the device has a valid MAC address in device tree */
        if (!eth_dev_get_mac_address(dev, pdata->enetaddr) ||
index 6e0c058..6870afb 100644 (file)
@@ -365,7 +365,7 @@ int eth_send(void *packet, int length)
        ret = eth_current->send(eth_current, packet, length);
 #if defined(CONFIG_CMD_PCAP)
        if (ret >= 0)
-               pcap_post(packet, lengeth, true);
+               pcap_post(packet, length, true);
 #endif
        return ret;
 }
index 4bf9bd8..6a52cda 100644 (file)
@@ -10,6 +10,8 @@
 #define __NET_RAND_H__
 
 #include <common.h>
+#include <dm/uclass.h>
+#include <rng.h>
 
 /*
  * Return a seed for the PRNG derived from the eth0 MAC address.
@@ -37,7 +39,22 @@ static inline unsigned int seed_mac(void)
  */
 static inline void srand_mac(void)
 {
-       srand(seed_mac());
+       int ret;
+       struct udevice *devp;
+       u32 randv = 0;
+
+       if (IS_ENABLED(CONFIG_DM_RNG)) {
+               ret = uclass_get_device(UCLASS_RNG, 0, &devp);
+               if (ret) {
+                       ret = dm_rng_read(devp, &randv, sizeof(randv));
+                       if (ret < 0)
+                               randv = 0;
+               }
+       }
+       if (randv)
+               srand(randv);
+       else
+               srand(seed_mac());
 }
 
 #endif /* __NET_RAND_H__ */
index 0e33660..075df36 100644 (file)
@@ -90,6 +90,9 @@ void ping_receive(struct ethernet_hdr *et, struct ip_udp_hdr *ip, int len)
                        net_set_state(NETLOOP_SUCCESS);
                return;
        case ICMP_ECHO_REQUEST:
+               if (net_ip.s_addr == 0)
+                       return;
+
                eth_hdr_size = net_update_ether(et, et->et_src, PROT_IP);
 
                debug_cond(DEBUG_DEV_PKT,
index 2cfa0b1..03079de 100644 (file)
@@ -630,8 +630,10 @@ static void tftp_handler(uchar *pkt, unsigned dest, struct in_addr sip,
                tftp_cur_block++;
                tftp_cur_block %= TFTP_SEQUENCE_SIZE;
 
-               if (tftp_state == STATE_SEND_RRQ)
+               if (tftp_state == STATE_SEND_RRQ) {
                        debug("Server did not acknowledge any options!\n");
+                       tftp_next_ack = tftp_windowsize;
+               }
 
                if (tftp_state == STATE_SEND_RRQ || tftp_state == STATE_OACK ||
                    tftp_state == STATE_RECV_WRQ) {
index b2f71af..758bc14 100644 (file)
@@ -4,4 +4,5 @@
 
 obj-y += mem.o
 obj-$(CONFIG_CMD_MEM_SEARCH) += mem_search.o
+obj-$(CONFIG_CMD_PWM) += pwm.o
 obj-y += setexpr.o
diff --git a/test/cmd/pwm.c b/test/cmd/pwm.c
new file mode 100644 (file)
index 0000000..5343af8
--- /dev/null
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for pwm command
+ *
+ * Copyright 2020 SiFive, Inc
+ *
+ * Authors:
+ *   Pragnesh Patel <pragnesh.patel@sifive.com>
+ */
+
+#include <dm.h>
+#include <dm/test.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+/* Basic test of 'pwm' command */
+static int dm_test_pwm_cmd(struct unit_test_state *uts)
+{
+       struct udevice *dev;
+
+       ut_assertok(uclass_get_device(UCLASS_PWM, 0, &dev));
+       ut_assertnonnull(dev);
+
+       ut_assertok(console_record_reset_enable());
+
+       /* pwm <invert> <pwm_dev_num> <channel> <polarity> */
+       ut_assertok(run_command("pwm invert 0 0 1", 0));
+       ut_assert_console_end();
+
+       ut_assertok(run_command("pwm invert 0 0 0", 0));
+       ut_assert_console_end();
+
+       /* pwm <config> <pwm_dev_num> <channel> <period_ns> <duty_ns> */
+       ut_assertok(run_command("pwm config 0 0 10 50", 0));
+       ut_assert_console_end();
+
+       /* pwm <enable/disable> <pwm_dev_num> <channel> */
+       ut_assertok(run_command("pwm enable 0 0", 0));
+       ut_assert_console_end();
+
+       ut_assertok(run_command("pwm disable 0 0", 0));
+       ut_assert_console_end();
+
+       return 0;
+}
+
+DM_TEST(dm_test_pwm_cmd, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
index 9b1aa51..2d55043 100644 (file)
@@ -155,7 +155,7 @@ HOSTCFLAGS_kwbimage.o += -DCONFIG_KWB_SECURE
 endif
 
 # MXSImage needs LibSSL
-ifneq ($(CONFIG_MX23)$(CONFIG_MX28)$(CONFIG_ARMADA_38X)$(CONFIG_ARMADA_39X)$(CONFIG_FIT_SIGNATURE),)
+ifneq ($(CONFIG_MX23)$(CONFIG_MX28)$(CONFIG_ARMADA_38X)$(CONFIG_ARMADA_39X)$(CONFIG_FIT_SIGNATURE)$(CONFIG_FIT_CIPHER),)
 HOSTCFLAGS_kwbimage.o += \
        $(shell pkg-config --cflags libssl libcrypto 2> /dev/null || echo "")
 HOSTLDLIBS_mkimage += \
index 66cb9d2..2a61a5d 100644 (file)
@@ -1208,7 +1208,7 @@ static int flash_write(int fd_current, int fd_target, int dev_target)
 
        if (IS_UBI(dev_target)) {
                if (ubi_update_start(fd_target, CUR_ENVSIZE) < 0)
-                       return 0;
+                       return -1;
                return ubi_write(fd_target, environment.image, CUR_ENVSIZE);
        }
 
index e32cc64..33a2241 100644 (file)
@@ -700,13 +700,84 @@ static const char *fit_config_get_image_list(void *fit, int noffset,
        return default_list;
 }
 
+static int fit_config_add_hash(void *fit, const char *conf_name, const char *sig_name,
+                              struct strlist *node_inc, const char *iname, int image_noffset)
+{
+       char name[200], path[200];
+       int noffset;
+       int hash_count;
+       int ret;
+
+       ret = fdt_get_path(fit, image_noffset, path, sizeof(path));
+       if (ret < 0)
+               goto err_path;
+       if (strlist_add(node_inc, path))
+               goto err_mem;
+
+       snprintf(name, sizeof(name), "%s/%s", FIT_CONFS_PATH,
+                conf_name);
+
+       /* Add all this image's hashes */
+       hash_count = 0;
+       for (noffset = fdt_first_subnode(fit, image_noffset);
+            noffset >= 0;
+            noffset = fdt_next_subnode(fit, noffset)) {
+               const char *name = fit_get_name(fit, noffset, NULL);
+
+               if (strncmp(name, FIT_HASH_NODENAME,
+                           strlen(FIT_HASH_NODENAME)))
+                       continue;
+               ret = fdt_get_path(fit, noffset, path, sizeof(path));
+               if (ret < 0)
+                       goto err_path;
+               if (strlist_add(node_inc, path))
+                       goto err_mem;
+               hash_count++;
+       }
+
+       if (!hash_count) {
+               printf("Failed to find any hash nodes in configuration '%s/%s' image '%s' - without these it is not possible to verify this image\n",
+                      conf_name, sig_name, iname);
+               return -ENOMSG;
+       }
+
+       /* Add this image's cipher node if present */
+       noffset = fdt_subnode_offset(fit, image_noffset,
+                                    FIT_CIPHER_NODENAME);
+       if (noffset != -FDT_ERR_NOTFOUND) {
+               if (noffset < 0) {
+                       printf("Failed to get cipher node in configuration '%s/%s' image '%s': %s\n",
+                              conf_name, sig_name, iname,
+                              fdt_strerror(noffset));
+                       return -EIO;
+               }
+               ret = fdt_get_path(fit, noffset, path, sizeof(path));
+               if (ret < 0)
+                       goto err_path;
+               if (strlist_add(node_inc, path))
+                       goto err_mem;
+       }
+
+       return 0;
+
+err_mem:
+       printf("Out of memory processing configuration '%s/%s'\n", conf_name,
+              sig_name);
+       return -ENOMEM;
+
+err_path:
+       printf("Failed to get path for image '%s' in configuration '%s/%s': %s\n",
+              iname, conf_name, sig_name, fdt_strerror(ret));
+       return -ENOENT;
+}
+
 static int fit_config_get_hash_list(void *fit, int conf_noffset,
                                    int sig_offset, struct strlist *node_inc)
 {
        int allow_missing;
        const char *prop, *iname, *end;
        const char *conf_name, *sig_name;
-       char name[200], path[200];
+       char name[200];
        int image_count;
        int ret, len;
 
@@ -733,72 +804,32 @@ static int fit_config_get_hash_list(void *fit, int conf_noffset,
        end = prop + len;
        image_count = 0;
        for (iname = prop; iname < end; iname += strlen(iname) + 1) {
-               int noffset;
                int image_noffset;
-               int hash_count;
+               int index, max_index;
 
-               image_noffset = fit_conf_get_prop_node(fit, conf_noffset,
-                                                      iname);
-               if (image_noffset < 0) {
-                       printf("Failed to find image '%s' in  configuration '%s/%s'\n",
-                              iname, conf_name, sig_name);
-                       if (allow_missing)
-                               continue;
+               max_index = fdt_stringlist_count(fit, conf_noffset, iname);
 
-                       return -ENOENT;
-               }
-
-               ret = fdt_get_path(fit, image_noffset, path, sizeof(path));
-               if (ret < 0)
-                       goto err_path;
-               if (strlist_add(node_inc, path))
-                       goto err_mem;
+               for (index = 0; index < max_index; index++) {
+                       image_noffset = fit_conf_get_prop_node_index(fit, conf_noffset,
+                                                                    iname, index);
 
-               snprintf(name, sizeof(name), "%s/%s", FIT_CONFS_PATH,
-                        conf_name);
+                       if (image_noffset < 0) {
+                               printf("Failed to find image '%s' in  configuration '%s/%s'\n",
+                                      iname, conf_name, sig_name);
+                               if (allow_missing)
+                                       continue;
 
-               /* Add all this image's hashes */
-               hash_count = 0;
-               for (noffset = fdt_first_subnode(fit, image_noffset);
-                    noffset >= 0;
-                    noffset = fdt_next_subnode(fit, noffset)) {
-                       const char *name = fit_get_name(fit, noffset, NULL);
+                               return -ENOENT;
+                       }
 
-                       if (strncmp(name, FIT_HASH_NODENAME,
-                                   strlen(FIT_HASH_NODENAME)))
-                               continue;
-                       ret = fdt_get_path(fit, noffset, path, sizeof(path));
+                       ret = fit_config_add_hash(fit, conf_name,
+                                                 sig_name, node_inc,
+                                                 iname, image_noffset);
                        if (ret < 0)
-                               goto err_path;
-                       if (strlist_add(node_inc, path))
-                               goto err_mem;
-                       hash_count++;
-               }
+                               return ret;
 
-               if (!hash_count) {
-                       printf("Failed to find any hash nodes in configuration '%s/%s' image '%s' - without these it is not possible to verify this image\n",
-                              conf_name, sig_name, iname);
-                       return -ENOMSG;
+                       image_count++;
                }
-
-               /* Add this image's cipher node if present */
-               noffset = fdt_subnode_offset(fit, image_noffset,
-                                            FIT_CIPHER_NODENAME);
-               if (noffset != -FDT_ERR_NOTFOUND) {
-                       if (noffset < 0) {
-                               printf("Failed to get cipher node in configuration '%s/%s' image '%s': %s\n",
-                                      conf_name, sig_name, iname,
-                                      fdt_strerror(noffset));
-                               return -EIO;
-                       }
-                       ret = fdt_get_path(fit, noffset, path, sizeof(path));
-                       if (ret < 0)
-                               goto err_path;
-                       if (strlist_add(node_inc, path))
-                               goto err_mem;
-               }
-
-               image_count++;
        }
 
        if (!image_count) {
@@ -813,11 +844,6 @@ err_mem:
        printf("Out of memory processing configuration '%s/%s'\n", conf_name,
               sig_name);
        return -ENOMEM;
-
-err_path:
-       printf("Failed to get path for image '%s' in configuration '%s/%s': %s\n",
-              iname, conf_name, sig_name, fdt_strerror(ret));
-       return -ENOENT;
 }
 
 static int fit_config_get_data(void *fit, int conf_noffset, int noffset,
index 270943f..1624949 100644 (file)
@@ -137,8 +137,8 @@ static int add_public_key(const char *pkey_file, const char *dtb_file,
                          bool overlay)
 {
        int ret;
-       int srcfd = 0;
-       int destfd = 0;
+       int srcfd = -1;
+       int destfd = -1;
        void *sptr = NULL;
        void *dptr = NULL;
        off_t src_size;
@@ -150,6 +150,7 @@ static int add_public_key(const char *pkey_file, const char *dtb_file,
        if (srcfd == -1) {
                fprintf(stderr, "%s: Can't open %s: %s\n",
                        __func__, pkey_file, strerror(errno));
+               ret = -1;
                goto err;
        }
 
@@ -157,6 +158,7 @@ static int add_public_key(const char *pkey_file, const char *dtb_file,
        if (ret == -1) {
                fprintf(stderr, "%s: Can't stat %s: %s\n",
                        __func__, pkey_file, strerror(errno));
+               ret = -1;
                goto err;
        }
 
@@ -164,9 +166,10 @@ static int add_public_key(const char *pkey_file, const char *dtb_file,
 
        /* mmap the public key esl file */
        sptr = mmap(0, src_size, PROT_READ, MAP_SHARED, srcfd, 0);
-       if ((sptr == MAP_FAILED) || (errno != 0)) {
+       if (sptr == MAP_FAILED) {
                fprintf(stderr, "%s: Failed to mmap %s:%s\n",
                        __func__, pkey_file, strerror(errno));
+               ret = -1;
                goto err;
        }
 
@@ -175,6 +178,7 @@ static int add_public_key(const char *pkey_file, const char *dtb_file,
        if (destfd == -1) {
                fprintf(stderr, "%s: Can't open %s: %s\n",
                        __func__, dtb_file, strerror(errno));
+               ret = -1;
                goto err;
        }
 
@@ -189,21 +193,24 @@ static int add_public_key(const char *pkey_file, const char *dtb_file,
        if (ftruncate(destfd, dtb.st_size)) {
                fprintf(stderr, "%s: Can't expand %s: %s\n",
                        __func__, dtb_file, strerror(errno));
-               goto err;;
+               ret = -1;
+               goto err;
        }
 
        errno = 0;
        /* mmap the dtb file */
        dptr = mmap(0, dtb.st_size, PROT_READ | PROT_WRITE, MAP_SHARED,
                    destfd, 0);
-       if ((dptr == MAP_FAILED) || (errno != 0)) {
+       if (dptr == MAP_FAILED) {
                fprintf(stderr, "%s: Failed to mmap %s:%s\n",
                        __func__, dtb_file, strerror(errno));
+               ret = -1;
                goto err;
        }
 
        if (fdt_check_header(dptr)) {
                fprintf(stderr, "%s: Invalid FDT header\n", __func__);
+               ret = -1;
                goto err;
        }
 
@@ -211,6 +218,7 @@ static int add_public_key(const char *pkey_file, const char *dtb_file,
        if (ret) {
                fprintf(stderr, "%s: Cannot expand FDT: %s\n",
                        __func__, fdt_strerror(ret));
+               ret = -1;
                goto err;
        }
 
@@ -219,10 +227,11 @@ static int add_public_key(const char *pkey_file, const char *dtb_file,
        if (ret < 0) {
                fprintf(stderr, "%s: Unable to add public key to the FDT\n",
                        __func__);
+               ret = -1;
                goto err;
        }
 
-       return 0;
+       ret = 0;
 
 err:
        if (sptr)
@@ -231,13 +240,13 @@ err:
        if (dptr)
                munmap(dptr, dtb.st_size);
 
-       if (srcfd >= 0)
+       if (srcfd != -1)
                close(srcfd);
 
-       if (destfd >= 0)
+       if (destfd != -1)
                close(destfd);
 
-       return -1;
+       return ret;
 }
 
 static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
@@ -310,6 +319,9 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
        image.version = 0x00000003;
        memcpy(&image.update_image_type_id, guid, sizeof(*guid));
        image.update_image_index = index;
+       image.reserved[0] = 0;
+       image.reserved[1] = 0;
+       image.reserved[2] = 0;
        image.update_image_size = bin_stat.st_size;
        image.update_vendor_code_size = 0; /* none */
        image.update_hardware_instance = instance;
@@ -421,26 +433,25 @@ int main(int argc, char **argv)
 
        /* need a fit image file or raw image file */
        if (!file && !pkey_file && !dtb_file) {
-               printf("%s: %d\n", __func__, __LINE__);
                print_usage();
-               return -1;
+               exit(EXIT_FAILURE);
        }
 
        if (pkey_file && dtb_file) {
                ret = add_public_key(pkey_file, dtb_file, overlay);
                if (ret == -1) {
                        printf("Adding public key to the dtb failed\n");
-                       return -1;
+                       exit(EXIT_FAILURE);
                } else {
-                       return 0;
+                       exit(EXIT_SUCCESS);
                }
        }
 
        if (create_fwbin(argv[optind], file, guid, index, instance)
                        < 0) {
                printf("Creating firmware capsule failed\n");
-               return -1;
+               exit(EXIT_FAILURE);
        }
 
-       return 0;
+       exit(EXIT_SUCCESS);
 }
index e786082..68d5206 100644 (file)
@@ -94,18 +94,18 @@ static void usage(const char *msg)
                "          -x ==> set XIP (execute in place)\n",
                params.cmdname);
        fprintf(stderr,
-               "       %s [-D dtc_options] [-f fit-image.its|-f auto|-F] [-b <dtb> [-b <dtb>]] [-i <ramdisk.cpio.gz>] fit-image\n"
+               "       %s [-D dtc_options] [-f fit-image.its|-f auto|-F] [-b <dtb> [-b <dtb>]] [-E] [-B size] [-i <ramdisk.cpio.gz>] fit-image\n"
                "           <dtb> file is used with -f auto, it may occur multiple times.\n",
                params.cmdname);
        fprintf(stderr,
                "          -D => set all options for device tree compiler\n"
                "          -f => input filename for FIT source\n"
-               "          -i => input filename for ramdisk file\n");
+               "          -i => input filename for ramdisk file\n"
+               "          -E => place data outside of the FIT structure\n"
+               "          -B => align size in hex for FIT structure and header\n");
 #ifdef CONFIG_FIT_SIGNATURE
        fprintf(stderr,
-               "Signing / verified boot options: [-E] [-B size] [-k keydir] [-K dtb] [ -c <comment>] [-p addr] [-r] [-N engine]\n"
-               "          -E => place data outside of the FIT structure\n"
-               "          -B => align size in hex for FIT structure and header\n"
+               "Signing / verified boot options: [-k keydir] [-K dtb] [ -c <comment>] [-p addr] [-r] [-N engine]\n"
                "          -k => set directory containing private keys\n"
                "          -K => write public keys to this .dtb file\n"
                "          -c => add comment in signature node\n"
@@ -142,6 +142,7 @@ static int add_content(int type, const char *fname)
        return 0;
 }
 
+#define OPT_STRING "a:A:b:B:c:C:d:D:e:Ef:Fk:i:K:ln:N:p:O:rR:qstT:vVx"
 static void process_args(int argc, char **argv)
 {
        char *ptr;
index 2ca5194..bde1e5d 100644 (file)
@@ -246,6 +246,7 @@ static const struct brom_img_type {
 /* Image type selected by user */
 static enum brlyt_img_type hdr_media;
 static int use_lk_hdr;
+static bool is_arm64_image;
 
 /* LK image name */
 static char lk_name[32] = "U-Boot";
@@ -276,6 +277,7 @@ static int mtk_brom_parse_imagename(const char *imagename)
        static const char *media = "";
        static const char *nandinfo = "";
        static const char *lk = "";
+       static const char *arm64_param = "";
 
        key = buf;
        while (key) {
@@ -323,6 +325,9 @@ static int mtk_brom_parse_imagename(const char *imagename)
 
                        if (!strcmp(key, "lkname"))
                                snprintf(lk_name, sizeof(lk_name), "%s", val);
+
+                       if (!strcmp(key, "arm64"))
+                               arm64_param = val;
                }
 
                if (next)
@@ -354,6 +359,9 @@ static int mtk_brom_parse_imagename(const char *imagename)
                }
        }
 
+       if (arm64_param && arm64_param[0] == '1')
+               is_arm64_image = true;
+
        free(buf);
 
        if (hdr_media == BRLYT_TYPE_INVALID) {
@@ -458,6 +466,9 @@ static int mtk_image_verify_gen_header(const uint8_t *ptr, int print)
                       le32_to_cpu(gfh->file_info.load_addr) +
                       le32_to_cpu(gfh->file_info.jump_offset));
 
+       if (print)
+               printf("Architecture: %s\n", is_arm64_image ? "ARM64" : "ARM");
+
        return 0;
 }
 
@@ -523,6 +534,9 @@ static int mtk_image_verify_nand_header(const uint8_t *ptr, int print)
                       le32_to_cpu(gfh->file_info.load_addr) +
                       le32_to_cpu(gfh->file_info.jump_offset));
 
+       if (print)
+               printf("Architecture: %s\n", is_arm64_image ? "ARM64" : "ARM");
+
        return 0;
 }
 
@@ -581,6 +595,8 @@ static void put_ghf_common_header(struct gfh_common_header *gfh, int size,
 static void put_ghf_header(struct gfh_header *gfh, int file_size,
                           int dev_hdr_size, int load_addr, int flash_type)
 {
+       uint32_t cfg_bits;
+
        memset(gfh, 0, sizeof(struct gfh_header));
 
        /* GFH_FILE_INFO header */
@@ -608,11 +624,15 @@ static void put_ghf_header(struct gfh_header *gfh, int file_size,
        /* 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);
+       cfg_bits = 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);
+       if (is_arm64_image) {
+               gfh->brom_cfg.jump_bl_arm64 = GFH_BROM_CFG_JUMP_BL_ARM64;
+               cfg_bits |= GFH_BROM_CFG_JUMP_BL_ARM64_EN;
+       }
+       gfh->brom_cfg.cfg_bits = cpu_to_le32(cfg_bits);
 
        /* GFH_BL_SEC_KEY header */
        put_ghf_common_header(&gfh->bl_sec_key.gfh, sizeof(gfh->bl_sec_key),
index 4e78b3d..7dda71c 100644 (file)
@@ -136,7 +136,9 @@ struct gfh_brom_cfg {
        struct gfh_common_header gfh;
        uint32_t cfg_bits;
        uint32_t usbdl_by_auto_detect_timeout_ms;
-       uint8_t unused[0x48];
+       uint8_t unused[0x45];
+       uint8_t jump_bl_arm64;
+       uint8_t unused2[2];
        uint32_t usbdl_by_kcol0_timeout_ms;
        uint32_t usbdl_by_flag_timeout_ms;
        uint32_t pad;
@@ -146,6 +148,8 @@ struct gfh_brom_cfg {
 #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
+#define GFH_BROM_CFG_JUMP_BL_ARM64_EN                  0x1000
+#define GFH_BROM_CFG_JUMP_BL_ARM64                     0x64
 
 struct gfh_bl_sec_key {
        struct gfh_common_header gfh;