diff --git a/.gitignore b/.gitignore index 29757aa51e3..eb86558201b 100644 --- a/.gitignore +++ b/.gitignore @@ -50,6 +50,7 @@ fit-dtb.blob /spl/ /tpl/ /defconfig +/tmp/ # # Generated include files diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 00000000000..50ea0c70166 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,49 @@ +image: ayufan/rock64-dockerfiles:x86_64 + +variables: + GITHUB_USER: ayufan-rock64 + GITHUB_REPO: linux-u-boot + + USE_CCACHE: "true" + CCACHE_DIR: "/data/shared/ccache" + +stages: [build] + +before_script: + - ccache -M 0 -F 0 + +build: + stage: build + only: [branches] + script: + - rm -f ../*.deb + - export RELEASE=$((1000+$CI_PIPELINE_IID)) + - ./dev-make BOARD_TARGET=rock64 -j5 + - ./dev-make BOARD_TARGET=rockpro64 -j5 + - ./dev-make BOARD_TARGET=pinebookpro -j5 + - ./dev-make BOARD_TARGET=rockpi4b -j5 + - | + set -x + + export RELEASE_NAME="$(./dev-make version BOARD_TARGET=rock64)" + export RELEASE_TITLE="$(./dev-make version BOARD_TARGET=rock64)" + export DESCRIPTION="$CI_PROJECT_URL/pipelines/$CI_PIPELINE_ID" + + github-release release \ + --tag "${RELEASE_NAME}" \ + --name "${RELEASE_TITLE}" \ + --description "${DESCRIPTION}" \ + --target "${CI_COMMIT_SHA}" \ + --draft + + for i in *.deb *.img.xz; do + github-release upload \ + --tag "${RELEASE_NAME}" \ + --name "${i}" \ + --file "${i}" + done + + github-release edit \ + --tag "${RELEASE_NAME}" \ + --name "${RELEASE_TITLE}" \ + --description "${DESCRIPTION}" diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index 0032a213771..2fdb32a8cec 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -46,15 +46,19 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \ rk3288-veyron-mickey.dtb \ rk3288-veyron-minnie.dtb \ rk3328-evb.dtb \ + rk3328-rock64.dtb \ rk3368-lion.dtb \ rk3368-sheep.dtb \ rk3368-geekbox.dtb \ rk3368-px5-evb.dtb \ rk3399-evb.dtb \ rk3399-firefly.dtb \ + rk3399-pinebook-pro.dtb \ rk3399-puma-ddr1333.dtb \ rk3399-puma-ddr1600.dtb \ rk3399-puma-ddr1866.dtb \ + rk3399-rockpi4b.dtb \ + rk3399-rockpro64.dtb \ rv1108-evb.dtb dtb-$(CONFIG_ARCH_MESON) += \ meson-gxbb-odroidc2.dtb diff --git a/arch/arm/dts/rk3328-evb.dts b/arch/arm/dts/rk3328-evb.dts index 4b13a8da641..930478782bb 100644 --- a/arch/arm/dts/rk3328-evb.dts +++ b/arch/arm/dts/rk3328-evb.dts @@ -16,6 +16,20 @@ stdout-path = &uart2; }; + gmac_clkin: external-gmac-clock { + compatible = "fixed-clock"; + clock-frequency = <125000000>; + clock-output-names = "gmac_clkin"; + #clock-cells = <0>; + }; + + vcc_phy: vcc-phy-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_phy"; + regulator-always-on; + regulator-boot-on; + }; + vcc3v3_sdmmc: sdmmc-pwren { compatible = "regulator-fixed"; regulator-name = "vcc3v3"; @@ -214,6 +228,79 @@ regulator-on-in-suspend; regulator-suspend-microvolt = <1000000>; }; + }; + }; + }; +}; + +&gmac2io { + phy-supply = <&vcc_phy>; + phy-mode = "rgmii"; + clock_in_out = "input"; + snps,reset-gpio = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; + snps,reset-active-low; + snps,reset-delays-us = <0 10000 50000>; + assigned-clocks = <&cru SCLK_MAC2IO>, <&cru SCLK_MAC2IO_EXT>; + assigned-clock-parents = <&gmac_clkin>, <&gmac_clkin>; + pinctrl-names = "default"; + pinctrl-0 = <&rgmiim1_pins>; + tx_delay = <0x26>; + rx_delay = <0x11>; + status = "okay"; +}; + +&spi0 { + status = "okay"; + + /* SPI DMA does not work currently */ + /delete-property/ dmas; + /delete-property/ #dma-cells; + /delete-property/ dma-names; + + spi-flash@0 { + #address-cells = <0x1>; + #size-cells = <1>; + compatible = "st,m25p128", "spi-flash"; + reg = <0x0>; + spi-max-frequency = <25000000>; + status = "okay"; + m25p,fast-read; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + system@0 { + label = "system"; + reg = <0x0 0x8000>; + read-only; + }; + + loader@8000 { + label = "loader"; + reg = <0x8000 0x3F8000>; + }; + + reserved@400000 { + label = "reserved"; + reg = <0x400000 0x3C0000>; + read-only; + }; + + vendor@7c0000 { + label = "vendor"; + reg = <0x7C0000 0x40000>; + }; + + uboot@800000 { + label = "uboot"; + reg = <0x800000 0x400000>; + }; + + atf@c00000 { + label = "atf"; + reg = <0xC00000 0x400000>; }; }; }; diff --git a/arch/arm/dts/rk3328-rock64.dts b/arch/arm/dts/rk3328-rock64.dts new file mode 100644 index 00000000000..31677da0740 --- /dev/null +++ b/arch/arm/dts/rk3328-rock64.dts @@ -0,0 +1,317 @@ +/* + * (C) Copyright 2017 PINE64 + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/dts-v1/; +#include "rk3328.dtsi" +#include "rk3328-sdram-lpddr3-1600.dtsi" + +/ { + model = "Pine64 Rock64"; + compatible = "pine64,rock64", "rockchip,rk3328"; + + chosen { + stdout-path = &uart2; + }; + + aliases { + spi0 = &spi0; + }; + + gmac_clkin: external-gmac-clock { + compatible = "fixed-clock"; + clock-frequency = <125000000>; + clock-output-names = "gmac_clkin"; + #clock-cells = <0>; + }; + + vcc_phy: vcc-phy-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_phy"; + regulator-always-on; + regulator-boot-on; + }; + + vcc3v3_sdmmc: sdmmc-pwren { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3_sdmmc"; + enable-active-high; + gpio = <&gpio0 30 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc0m1_pwren>; + regulator-always-on; + regulator-boot-on; + }; + + vcc5v0_otg: vcc5v0-otg-drv { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_otg"; + gpio = <&gpio0 2 GPIO_ACTIVE_LOW>; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; + + vcc5v0_host_xhci: vcc5v0-host-xhci-drv { + compatible = "regulator-fixed"; + enable-active-high; + regulator-name = "vcc5v0_host_xhci"; + gpio = <&gpio0 0 GPIO_ACTIVE_HIGH>; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; + + adc-keys { + compatible = "adc-keys"; + io-channels = <&saradc 0>; + }; +}; + +&saradc { + status = "okay"; +}; + +&uart2 { + u-boot,dm-pre-reloc; + status = "okay"; +}; + +&sdmmc { + u-boot,dm-spl; + bus-width = <4>; + cap-mmc-highspeed; + cap-sd-highspeed; + card-detect-delay = <200>; + disable-wp; + num-slots = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc0_clk>, <&sdmmc0_cmd>, <&sdmmc0_dectn>, <&sdmmc0_bus4>; + status = "okay"; +}; + +&emmc { + u-boot,dm-spl; + bus-width = <8>; + cap-mmc-highspeed; + supports-emmc; + disable-wp; + non-removable; + num-slots = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>; + status = "okay"; +}; + +&u2phy { + status = "okay"; +}; + +&u2phy_otg { + status = "okay"; +}; + +&u2phy_host { + status = "okay"; +}; + +&usb_host0_ehci { + status = "okay"; +}; + +&usb_host0_ohci { + status = "okay"; +}; + +&usb20_otg { + vbus-supply = <&vcc5v0_otg>; + status = "okay"; +}; + +&usb_host0_xhci { + vbus-supply = <&vcc5v0_host_xhci>; + status = "okay"; + maximum-speed = "high-speed"; +}; + +&i2c1 { + clock-frequency = <400000>; + i2c-scl-rising-time-ns = <168>; + i2c-scl-falling-time-ns = <4>; + status = "okay"; + + rk805: pmic@18 { + compatible = "rockchip,rk805"; + status = "okay"; + reg = <0x18>; + interrupt-parent = <&gpio2>; + interrupts = <6 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int_l>; + rockchip,system-power-controller; + wakeup-source; + gpio-controller; + #gpio-cells = <2>; + #clock-cells = <1>; + clock-output-names = "xin32k", "rk805-clkout2"; + + pwrkey { + status = "okay"; + }; + + led1 { + label = "standby"; + }; + + led2 { + label = "power"; + }; + + regulators { + vdd_logic: DCDC_REG1 { + regulator-name = "vdd_logic"; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1450000>; + regulator-ramp-delay = <6001>; + regulator-boot-on; + regulator-always-on; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vdd_arm: DCDC_REG2 { + regulator-name = "vdd_arm"; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1450000>; + regulator-ramp-delay = <6001>; + regulator-boot-on; + regulator-always-on; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-name = "vcc_ddr"; + regulator-boot-on; + regulator-always-on; + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_io: DCDC_REG4 { + regulator-name = "vcc_io"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vdd_18: LDO_REG1 { + regulator-name = "vdd_18"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcc_18emmc: LDO_REG2 { + regulator-name = "vcc_18emmc"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd_10: LDO_REG3 { + regulator-name = "vdd_10"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-boot-on; + regulator-always-on; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + }; + }; +}; + +&gmac2io { + phy-supply = <&vcc_phy>; + phy-mode = "rgmii"; + clock_in_out = "input"; + snps,reset-gpio = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; + snps,reset-active-low; + snps,reset-delays-us = <0 10000 50000>; + assigned-clocks = <&cru SCLK_MAC2IO>, <&cru SCLK_MAC2IO_EXT>; + assigned-clock-parents = <&gmac_clkin>, <&gmac_clkin>; + pinctrl-names = "default"; + pinctrl-0 = <&rgmiim1_pins>; + tx_delay = <0x18>; + rx_delay = <0x18>; + status = "okay"; +}; + +&spi0 { + u-boot,dm-spl; + status = "okay"; + + spiflash: spi-flash@0 { + u-boot,dm-spl; + #address-cells = <0x1>; + #size-cells = <1>; + compatible = "spi-flash"; + reg = <0x0>; + spi-max-frequency = <25000000>; + status = "okay"; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + loader@8000 { + label = "loader"; + reg = <0x8000 0x3F0000>; + }; + + env@3f8000 { + label = "env"; + reg = <0x3F8000 0x8000>; + }; + + vendor@7c0000 { + label = "vendor"; + reg = <0x7C0000 0x40000>; + }; + }; + }; +}; + +&pinctrl { + pmic { + pmic_int_l: pmic-int-l { + rockchip,pins = + <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>; /* gpio2_a6 */ + }; + }; +}; + diff --git a/arch/arm/dts/rk3328-sdram-lpddr3-1600.dtsi b/arch/arm/dts/rk3328-sdram-lpddr3-1600.dtsi new file mode 100644 index 00000000000..cc0011cf7b1 --- /dev/null +++ b/arch/arm/dts/rk3328-sdram-lpddr3-1600.dtsi @@ -0,0 +1,215 @@ +/* + * (C) 2017 Theobroma Systems Design und Consulting GmbH + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +&dmc { + rockchip,sdram-params = < + 0x1 + 0xC + 0x3 + 0x1 + 0x0 + 0x0 + 0x10 + 0x10 + 0 + + 0x98899459 + 0x00000000 + 0x0000002e + 0x00000544 + 0x00000015 + 0x00000432 + 0x000000ff + + 800 + 6 + 1 + + 0x00000000 + 0x43041008 + 0x00000064 + 0x00300054 + 0x000000d0 + 0x00500002 + 0x000000d4 + 0x00010000 + 0x000000d8 + 0x00000e03 + 0x000000dc + 0x0043001a + 0x000000e0 + 0x00010000 + 0x000000e4 + 0x000e0005 + 0x000000f4 + 0x000f011f + 0x00000100 + 0x0b141b11 + 0x00000104 + 0x0003031a + 0x00000108 + 0x03060809 + 0x0000010c + 0x00606000 + 0x00000110 + 0x08020409 + 0x00000114 + 0x01010606 + 0x00000118 + 0x02020004 + 0x00000120 + 0x00000404 + 0x00000138 + 0x00000058 + 0x00000180 + 0x00900024 + 0x00000184 + 0x01400000 + 0x00000190 + 0x07050002 + 0x00000198 + 0x05001100 + 0x000001a0 + 0xc0400003 + 0x00000240 + 0x0a020b28 + 0x00000244 + 0x00000101 + 0x00000250 + 0x00000f00 + 0x00000490 + 0x00000001 + 0xffffffff + 0xffffffff + 0xffffffff + 0xffffffff + 0xffffffff + 0xffffffff + + 0x00000004 + 0x0000000b + 0x00000028 + 0x0000000c + 0x0000002c + 0x00000000 + 0x00000030 + 0x00000006 + 0xffffffff + 0xffffffff + + 0x77 + 0x88 + 0x79 + 0x79 + 0x87 + 0x97 + 0x87 + 0x78 + 0x77 + 0x78 + 0x87 + 0x88 + 0x87 + 0x87 + 0x77 + + 0x78 + 0x78 + 0x78 + 0x78 + 0x78 + 0x78 + 0x78 + 0x78 + 0x78 + 0x69 + 0x9 + + 0x77 + 0x78 + 0x77 + 0x78 + 0x77 + 0x78 + 0x77 + 0x78 + 0x77 + 0x79 + 0x9 + + 0x78 + 0x78 + 0x78 + 0x78 + 0x78 + 0x78 + 0x78 + 0x78 + 0x78 + 0x69 + 0x9 + + 0x77 + 0x78 + 0x77 + 0x77 + 0x77 + 0x77 + 0x77 + 0x77 + 0x77 + 0x79 + 0x9 + + 0x78 + 0x78 + 0x78 + 0x78 + 0x78 + 0x78 + 0x78 + 0x78 + 0x78 + 0x69 + 0x9 + + 0x77 + 0x78 + 0x77 + 0x78 + 0x77 + 0x78 + 0x77 + 0x78 + 0x77 + 0x79 + 0x9 + + 0x78 + 0x78 + 0x78 + 0x78 + 0x78 + 0x78 + 0x78 + 0x78 + 0x78 + 0x69 + 0x9 + + 0x77 + 0x78 + 0x77 + 0x77 + 0x77 + 0x77 + 0x77 + 0x77 + 0x77 + 0x79 + 0x9 + >; +}; diff --git a/arch/arm/dts/rk3328-sdram-lpddr3-1866.dtsi b/arch/arm/dts/rk3328-sdram-lpddr3-1866.dtsi new file mode 100644 index 00000000000..6766a9ae907 --- /dev/null +++ b/arch/arm/dts/rk3328-sdram-lpddr3-1866.dtsi @@ -0,0 +1,215 @@ +/* + * (C) 2017 Theobroma Systems Design und Consulting GmbH + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +&dmc { + rockchip,sdram-params = < + 0x1 + 0xC + 0x3 + 0x1 + 0x0 + 0x0 + 0x10 + 0x10 + 0 + + 0x9c89d51e + 0x00000000 + 0x00000031 + 0x00000575 + 0x00000015 + 0x0000053a + 0x000000ff + + 933 + 6 + 1 + + 0x00000000 + 0x43041008 + 0x00000064 + 0x00380062 + 0x000000d0 + 0x005d0002 + 0x000000d4 + 0x00010000 + 0x000000d8 + 0x00001003 + 0x000000dc + 0x0083001c + 0x000000e0 + 0x00010000 + 0x000000e4 + 0x00100006 + 0x000000f4 + 0x000f011f + 0x00000100 + 0x0d181f14 + 0x00000104 + 0x0004031e + 0x00000108 + 0x0407090a + 0x0000010c + 0x00707000 + 0x00000110 + 0x0902050b + 0x00000114 + 0x01010707 + 0x00000118 + 0x02020005 + 0x00000120 + 0x00000505 + 0x00000138 + 0x00000067 + 0x00000180 + 0x00a8002a + 0x00000184 + 0x01800000 + 0x00000190 + 0x07060003 + 0x00000198 + 0x05001100 + 0x000001a0 + 0xc0400003 + 0x00000240 + 0x0b030d2c + 0x00000244 + 0x00000101 + 0x00000250 + 0x00000f00 + 0x00000490 + 0x00000001 + 0xffffffff + 0xffffffff + 0xffffffff + 0xffffffff + 0xffffffff + 0xffffffff + + 0x00000004 + 0x0000000b + 0x00000028 + 0x0000000e + 0x0000002c + 0x00000000 + 0x00000030 + 0x00000008 + 0xffffffff + 0xffffffff + + 0x77 + 0x88 + 0x79 + 0x79 + 0x87 + 0x97 + 0x87 + 0x78 + 0x77 + 0x78 + 0x87 + 0x88 + 0x87 + 0x87 + 0x77 + + 0x78 + 0x78 + 0x78 + 0x78 + 0x78 + 0x78 + 0x78 + 0x78 + 0x78 + 0x69 + 0x9 + + 0x77 + 0x78 + 0x77 + 0x78 + 0x77 + 0x78 + 0x77 + 0x78 + 0x77 + 0x79 + 0x9 + + 0x78 + 0x78 + 0x78 + 0x78 + 0x78 + 0x78 + 0x78 + 0x78 + 0x78 + 0x69 + 0x9 + + 0x77 + 0x78 + 0x77 + 0x77 + 0x77 + 0x77 + 0x77 + 0x77 + 0x77 + 0x79 + 0x9 + + 0x78 + 0x78 + 0x78 + 0x78 + 0x78 + 0x78 + 0x78 + 0x78 + 0x78 + 0x69 + 0x9 + + 0x77 + 0x78 + 0x77 + 0x78 + 0x77 + 0x78 + 0x77 + 0x78 + 0x77 + 0x79 + 0x9 + + 0x78 + 0x78 + 0x78 + 0x78 + 0x78 + 0x78 + 0x78 + 0x78 + 0x78 + 0x69 + 0x9 + + 0x77 + 0x78 + 0x77 + 0x77 + 0x77 + 0x77 + 0x77 + 0x77 + 0x77 + 0x79 + 0x9 + >; +}; diff --git a/arch/arm/dts/rk3328.dtsi b/arch/arm/dts/rk3328.dtsi index 2a4c4929d70..dc4e9600100 100644 --- a/arch/arm/dts/rk3328.dtsi +++ b/arch/arm/dts/rk3328.dtsi @@ -342,6 +342,31 @@ }; }; + efuse: efuse@ff260000 { + compatible = "rockchip,rk3328-efuse"; + reg = <0x0 0xff260000 0x0 0x50>; + #address-cells = <1>; + #size-cells = <1>; + clocks = <&cru SCLK_EFUSE>; + clock-names = "pclk_efuse"; + rockchip,efuse-size = <0x20>; + + /* Data cells */ + efuse_id: id@7 { + reg = <0x07 0x10>; + }; + cpu_leakage: cpu-leakage@17 { + reg = <0x17 0x1>; + }; + logic_leakage: logic-leakage@19 { + reg = <0x19 0x1>; + }; + efuse_cpu_version: cpu-version@1a { + reg = <0x1a 0x1>; + bits = <3 3>; + }; + }; + saradc: saradc@ff280000 { compatible = "rockchip,rk3328-saradc", "rockchip,saradc"; reg = <0x0 0xff280000 0x0 0x100>; @@ -466,6 +491,17 @@ }; }; + emmc: rksdmmc@ff520000 { + compatible = "rockchip,rk3328-dw-mshc", "rockchip,rk3288-dw-mshc"; + reg = <0x0 0xff520000 0x0 0x4000>; + max-frequency = <150000000>; + clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>; + clock-names = "biu", "ciu"; + fifo-depth = <0x100>; + interrupts = ; + status = "disabled"; + }; + sdmmc: rksdmmc@ff500000 { compatible = "rockchip,rk3328-dw-mshc", "rockchip,rk3288-dw-mshc"; reg = <0x0 0xff500000 0x0 0x4000>; @@ -489,14 +525,22 @@ status = "disabled"; }; - emmc: rksdmmc@ff520000 { - compatible = "rockchip,rk3328-dw-mshc", "rockchip,rk3288-dw-mshc"; - reg = <0x0 0xff520000 0x0 0x4000>; - max-frequency = <150000000>; - clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>; - clock-names = "biu", "ciu"; - fifo-depth = <0x100>; - interrupts = ; + gmac2io: ethernet@ff540000 { + compatible = "rockchip,rk3328-gmac"; + reg = <0x0 0xff540000 0x0 0x10000>; + rockchip,grf = <&grf>; + interrupts = ; + interrupt-names = "macirq"; + clocks = <&cru SCLK_MAC2IO>, <&cru SCLK_MAC2IO_RX>, + <&cru SCLK_MAC2IO_TX>, <&cru SCLK_MAC2IO_REF>, + <&cru SCLK_MAC2IO_REFOUT>, <&cru ACLK_MAC2IO>, + <&cru PCLK_MAC2IO>; + clock-names = "stmmaceth", "mac_clk_rx", + "mac_clk_tx", "clk_mac_ref", + "clk_mac_refout", "aclk_mac", + "pclk_mac"; + resets = <&cru SRST_GMAC2IO_A>; + reset-names = "stmmaceth"; status = "disabled"; }; diff --git a/arch/arm/dts/rk3399-pinebook-pro-v1.dts b/arch/arm/dts/rk3399-pinebook-pro-v1.dts new file mode 100644 index 00000000000..750f2f296fb --- /dev/null +++ b/arch/arm/dts/rk3399-pinebook-pro-v1.dts @@ -0,0 +1,562 @@ +/* + * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/dts-v1/; +#include +#include +#include "rk3399.dtsi" + +/ { + model = "Pine64 Pinebook Pro"; + compatible = "pine64,pinebook-pro", "rockchip,rk3399"; + + chosen { + stdout-path = &uart2; + }; + + aliases { + spi0 = &spi1; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + enable-gpios = <&gpio4 RK_PD2 GPIO_ACTIVE_HIGH>; + pwms = <&pwm0 0 740740 0>; + brightness-levels = < + 0 1 2 3 4 5 6 7 + 8 9 10 11 12 13 14 15 + 16 17 18 19 20 21 22 23 + 24 25 26 27 28 29 30 31 + 32 33 34 35 36 37 38 39 + 40 41 42 43 44 45 46 47 + 48 49 50 51 52 53 54 55 + 56 57 58 59 60 61 62 63 + 64 65 66 67 68 69 70 71 + 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 + 88 89 90 91 92 93 94 95 + 96 97 98 99 100 101 102 103 + 104 105 106 107 108 109 110 111 + 112 113 114 115 116 117 118 119 + 120 121 122 123 124 125 126 127 + 128 129 130 131 132 133 134 135 + 136 137 138 139 140 141 142 143 + 144 145 146 147 148 149 150 151 + 152 153 154 155 156 157 158 159 + 160 161 162 163 164 165 166 167 + 168 169 170 171 172 173 174 175 + 176 177 178 179 180 181 182 183 + 184 185 186 187 188 189 190 191 + 192 193 194 195 196 197 198 199 + 200 201 202 203 204 205 206 207 + 208 209 210 211 212 213 214 215 + 216 217 218 219 220 221 222 223 + 224 225 226 227 228 229 230 231 + 232 233 234 235 236 237 238 239 + 240 241 242 243 244 245 246 247 + 248 249 250 251 252 253 254 255>; + default-brightness-level = <200>; + }; + + sdio_pwrseq: sdio-pwrseq { + compatible = "mmc-pwrseq-simple"; + clocks = <&rk808 1>; + clock-names = "ext_clock"; + pinctrl-names = "default"; + pinctrl-0 = <&wifi_enable_h>; + + /* + * On the module itself this is one of these (depending + * on the actual card populated): + * - SDIO_RESET_L_WL_REG_ON + * - PDN (power down when low) + */ + reset-gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_LOW>; + }; + + vcc1v8_s0: vcc1v8-s0 { + compatible = "regulator-fixed"; + regulator-name = "vcc1v8_s0"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + dc_12v: dc-12v { + compatible = "regulator-fixed"; + regulator-name = "dc_12v"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + }; + + vcc_sys: vcc-sys { + compatible = "regulator-fixed"; + regulator-name = "vcc_sys"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + vin-supply = <&dc_12v>; + }; + + vcc3v3_sys: vcc3v3-sys { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc_sys>; + }; + + vcc5v0_host: vcc5v0-host-regulator { + compatible = "regulator-fixed"; + gpio = <&gpio4 RK_PC5 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&host_vbus_drv>; + regulator-name = "vcc5v0_host"; + }; + + vcc5v0_usb3_host: vcc5v0-usb3-host-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&host_usb3_drv>; + regulator-name = "vcc5v0_usb3_host"; + regulator-always-on; + }; + + vdd_log: vdd-log { + compatible = "pwm-regulator"; + pwms = <&pwm2 0 25000 1>; + regulator-name = "vdd_log"; + regulator-always-on; + regulator-boot-on; + regulator-init-microvolt = <900000>; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1400000>; + }; +}; + +&cpu_l0 { + cpu-supply = <&vdd_cpu_l>; +}; + +&cpu_l1 { + cpu-supply = <&vdd_cpu_l>; +}; + +&cpu_l2 { + cpu-supply = <&vdd_cpu_l>; +}; + +&cpu_l3 { + cpu-supply = <&vdd_cpu_l>; +}; + +&emmc_phy { + status = "okay"; +}; + +&i2c0 { + clock-frequency = <400000>; + i2c-scl-rising-time-ns = <168>; + i2c-scl-falling-time-ns = <4>; + status = "okay"; + + rk808: pmic@1b { + compatible = "rockchip,rk808"; + reg = <0x1b>; + interrupt-parent = <&gpio1>; + interrupts = <21 IRQ_TYPE_LEVEL_LOW>; + #clock-cells = <1>; + clock-output-names = "xin32k", "rk808-clkout2"; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int_l>; + rockchip,system-power-controller; + wakeup-source; + + vcc1-supply = <&vcc_sys>; + vcc2-supply = <&vcc_sys>; + vcc3-supply = <&vcc_sys>; + vcc4-supply = <&vcc_sys>; + vcc6-supply = <&vcc_sys>; + vcc7-supply = <&vcc_sys>; + vcc8-supply = <&vcc3v3_sys>; + vcc9-supply = <&vcc_sys>; + vcc10-supply = <&vcc_sys>; + vcc11-supply = <&vcc_sys>; + vcc12-supply = <&vcc3v3_sys>; + vddio-supply = <&vcc_1v8>; + + regulators { + vdd_center: DCDC_REG1 { + regulator-name = "vdd_center"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_l: DCDC_REG2 { + regulator-name = "vdd_cpu_l"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-name = "vcc_ddr"; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_1v8: DCDC_REG4 { + regulator-name = "vcc_1v8"; + 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>; + }; + }; + + vcc1v8_dvp: LDO_REG1 { + regulator-name = "vcc1v8_dvp"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc3v0_touch: LDO_REG2 { + regulator-name = "vcc3v0_touch"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vcc1v8_pmu: LDO_REG3 { + regulator-name = "vcc1v8_pmu"; + 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>; + }; + }; + + vcc_sd: LDO_REG4 { + regulator-name = "vcc_sd"; + 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>; + }; + }; + + vcca3v0_codec: LDO_REG5 { + regulator-name = "vcca3v0_codec"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v5: LDO_REG6 { + regulator-name = "vcc_1v5"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1500000>; + }; + }; + + vcca1v8_codec: LDO_REG7 { + regulator-name = "vcca1v8_codec"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_3v0: LDO_REG8 { + regulator-name = "vcc_3v0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vcc3v3_s3: SWITCH_REG1 { + regulator-name = "vcc3v3_s3"; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc3v3_s0: SWITCH_REG2 { + regulator-name = "vcc3v3_s0"; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + }; + }; +}; + +&i2c4 { + i2c-scl-rising-time-ns = <600>; + i2c-scl-falling-time-ns = <20>; + status = "okay"; +}; + +&io_domains { + status = "okay"; + + bt656-supply = <&vcc1v8_dvp>; + audio-supply = <&vcca1v8_codec>; + sdmmc-supply = <&vcc_sd>; + gpio1830-supply = <&vcc_3v0>; +}; + +&pmu_io_domains { + pmu1830-supply = <&vcc_3v0>; + status = "okay"; +}; + +&pinctrl { + pmic { + vsel1_gpio: vsel1-gpio { + rockchip,pins = <1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + vsel2_gpio: vsel2-gpio { + rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; + + sdio-pwrseq { + wifi_enable_h: wifi-enable-h { + rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pmic { + pmic_int_l: pmic-int-l { + rockchip,pins = <1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + usb2 { + host_vbus_drv: host-vbus-drv { + rockchip,pins = <4 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + host_usb3_drv: host-usb3-drv { + rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&pwm0 { + status = "okay"; +}; + +&pwm2 { + status = "okay"; +}; + +&saradc { + status = "okay"; +}; + +&sdmmc { + u-boot,dm-spl; + bus-width = <4>; + status = "okay"; + max-frequency = <20000000>; +}; + +&sdhci { + u-boot,dm-spl; + bus-width = <8>; + max-frequency = <25000000>; + mmc-hs400-1_8v; + mmc-hs400-enhanced-strobe; + non-removable; + status = "okay"; +}; + +&tsadc { + /* tshut mode 0:CRU 1:GPIO */ + rockchip,hw-tshut-mode = <1>; + /* tshut polarity 0:LOW 1:HIGH */ + rockchip,hw-tshut-polarity = <1>; + status = "okay"; +}; + +&u2phy0 { + /delete-property/ clocks; + /delete-property/ clock-names; + + status = "okay"; + + u2phy0_otg: otg-port { + status = "okay"; + }; + + u2phy0_host: host-port { + phy-supply = <&vcc5v0_host>; + status = "okay"; + }; +}; + +&u2phy1 { + /delete-property/ clocks; + /delete-property/ clock-names; + + status = "okay"; + + u2phy1_otg: otg-port { + status = "okay"; + }; + + u2phy1_host: host-port { + phy-supply = <&vcc5v0_host>; + status = "okay"; + }; +}; + +&uart2 { + u-boot,dm-pre-reloc; + status = "okay"; +}; + +&dwc3_typec0 { + status = "okay"; + maximum-speed = "high-speed"; +}; + +&usb_host0_ehci { + /delete-property/ clocks; + /delete-property/ clock-names; + + vbus-supply = <&vcc5v0_host>; + status = "okay"; +}; + +&usb_host0_ohci { + /delete-property/ clocks; + /delete-property/ clock-names; + + vbus-supply = <&vcc5v0_host>; + status = "okay"; +}; + +&usb_host1_ehci { + /delete-property/ clocks; + /delete-property/ clock-names; + + vbus-supply = <&vcc5v0_host>; + status = "okay"; +}; + +&usb_host1_ohci { + /delete-property/ clocks; + /delete-property/ clock-names; + + vbus-supply = <&vcc5v0_host>; + status = "okay"; +}; + +&dwc3_typec1 { + vbus-supply = <&vcc5v0_host>; + status = "okay"; + maximum-speed = "high-speed"; +}; + +&spi1 { + u-boot,dm-spl; + status = "okay"; + + spiflash: spi-flash@0 { + u-boot,dm-spl; + #address-cells = <0x1>; + #size-cells = <1>; + compatible = "spi-flash"; + reg = <0x0>; + spi-max-frequency = <25000000>; + status = "okay"; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + loader@8000 { + label = "loader"; + reg = <0x0 0x3F8000>; + }; + + env@3f8000 { + label = "env"; + reg = <0x3F8000 0x8000>; + }; + + vendor@7c0000 { + label = "vendor"; + reg = <0x7C0000 0x40000>; + }; + }; + }; +}; diff --git a/arch/arm/dts/rk3399-pinebook-pro.dts b/arch/arm/dts/rk3399-pinebook-pro.dts new file mode 100644 index 00000000000..f76d19d51f9 --- /dev/null +++ b/arch/arm/dts/rk3399-pinebook-pro.dts @@ -0,0 +1,577 @@ +/* + * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/dts-v1/; +#include +#include +#include "rk3399.dtsi" + +/ { + model = "Pine64 Pinebook Pro"; + compatible = "pine64,pinebook-pro", "rockchip,rk3399"; + + chosen { + stdout-path = &uart2; + }; + + aliases { + spi0 = &spi1; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + enable-gpios = <&gpio1 RK_PA0 GPIO_ACTIVE_HIGH>; + pwms = <&pwm0 0 740740 0>; + brightness-levels = < + 0 1 2 3 4 5 6 7 + 8 9 10 11 12 13 14 15 + 16 17 18 19 20 21 22 23 + 24 25 26 27 28 29 30 31 + 32 33 34 35 36 37 38 39 + 40 41 42 43 44 45 46 47 + 48 49 50 51 52 53 54 55 + 56 57 58 59 60 61 62 63 + 64 65 66 67 68 69 70 71 + 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 + 88 89 90 91 92 93 94 95 + 96 97 98 99 100 101 102 103 + 104 105 106 107 108 109 110 111 + 112 113 114 115 116 117 118 119 + 120 121 122 123 124 125 126 127 + 128 129 130 131 132 133 134 135 + 136 137 138 139 140 141 142 143 + 144 145 146 147 148 149 150 151 + 152 153 154 155 156 157 158 159 + 160 161 162 163 164 165 166 167 + 168 169 170 171 172 173 174 175 + 176 177 178 179 180 181 182 183 + 184 185 186 187 188 189 190 191 + 192 193 194 195 196 197 198 199 + 200 201 202 203 204 205 206 207 + 208 209 210 211 212 213 214 215 + 216 217 218 219 220 221 222 223 + 224 225 226 227 228 229 230 231 + 232 233 234 235 236 237 238 239 + 240 241 242 243 244 245 246 247 + 248 249 250 251 252 253 254 255>; + default-brightness-level = <200>; + }; + + leds { + status = "okay"; + compatible = "gpio-leds"; + + work-led { + label = "work"; + gpios = <&gpio0 RK_PB3 GPIO_ACTIVE_HIGH>; + }; + + standby-led { + label = "standby"; + gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>; + }; + }; + + sdio_pwrseq: sdio-pwrseq { + compatible = "mmc-pwrseq-simple"; + clocks = <&rk808 1>; + clock-names = "ext_clock"; + pinctrl-names = "default"; + pinctrl-0 = <&wifi_enable_h>; + + /* + * On the module itself this is one of these (depending + * on the actual card populated): + * - SDIO_RESET_L_WL_REG_ON + * - PDN (power down when low) + */ + reset-gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_LOW>; // TODO? + }; + + vcc1v8_s0: vcc1v8-s0 { + compatible = "regulator-fixed"; + regulator-name = "vcc1v8_s0"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + dc_12v: dc-12v { + compatible = "regulator-fixed"; + regulator-name = "dc_12v"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + }; + + vcc_sys: vcc-sys { + compatible = "regulator-fixed"; + regulator-name = "vcc_sys"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + vin-supply = <&dc_12v>; + }; + + vcc3v3_sys: vcc3v3-sys { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc_sys>; + }; + + vcc5v0_host: vcc5v0-host-regulator { + compatible = "regulator-fixed"; + gpio = <&gpio4 RK_PD2 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&host_vbus_drv>; + regulator-name = "vcc5v0_host"; + }; + + vcc5v0_usb3_host: vcc5v0-usb3-host-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio1 RK_PB5 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&host_usb3_drv>; + regulator-name = "vcc5v0_usb3_host"; + regulator-always-on; + }; + + vdd_log: vdd-log { + compatible = "pwm-regulator"; + pwms = <&pwm2 0 25000 1>; + regulator-name = "vdd_log"; + regulator-always-on; + regulator-boot-on; + regulator-init-microvolt = <900000>; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1400000>; + }; +}; + +&cpu_l0 { + cpu-supply = <&vdd_cpu_l>; +}; + +&cpu_l1 { + cpu-supply = <&vdd_cpu_l>; +}; + +&cpu_l2 { + cpu-supply = <&vdd_cpu_l>; +}; + +&cpu_l3 { + cpu-supply = <&vdd_cpu_l>; +}; + +&emmc_phy { + status = "okay"; +}; + +&i2c0 { + clock-frequency = <400000>; + i2c-scl-rising-time-ns = <168>; + i2c-scl-falling-time-ns = <4>; + status = "okay"; + + rk808: pmic@1b { + compatible = "rockchip,rk808"; + reg = <0x1b>; + interrupt-parent = <&gpio1>; + interrupts = <21 IRQ_TYPE_LEVEL_LOW>; + #clock-cells = <1>; + clock-output-names = "xin32k", "rk808-clkout2"; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int_l>; + rockchip,system-power-controller; + wakeup-source; + + vcc1-supply = <&vcc_sys>; + vcc2-supply = <&vcc_sys>; + vcc3-supply = <&vcc_sys>; + vcc4-supply = <&vcc_sys>; + vcc6-supply = <&vcc_sys>; + vcc7-supply = <&vcc_sys>; + vcc8-supply = <&vcc3v3_sys>; + vcc9-supply = <&vcc_sys>; + vcc10-supply = <&vcc_sys>; + vcc11-supply = <&vcc_sys>; + vcc12-supply = <&vcc3v3_sys>; + vddio-supply = <&vcc_1v8>; + + regulators { + vdd_center: DCDC_REG1 { + regulator-name = "vdd_center"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_l: DCDC_REG2 { + regulator-name = "vdd_cpu_l"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-name = "vcc_ddr"; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_1v8: DCDC_REG4 { + regulator-name = "vcc_1v8"; + 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>; + }; + }; + + vcc1v8_dvp: LDO_REG1 { + regulator-name = "vcc1v8_dvp"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc3v0_touch: LDO_REG2 { + regulator-name = "vcc3v0_touch"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vcc1v8_pmu: LDO_REG3 { + regulator-name = "vcc1v8_pmu"; + 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>; + }; + }; + + vcc_sd: LDO_REG4 { + regulator-name = "vcc_sd"; + 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>; + }; + }; + + vcca3v0_codec: LDO_REG5 { + regulator-name = "vcca3v0_codec"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v5: LDO_REG6 { + regulator-name = "vcc_1v5"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1500000>; + }; + }; + + vcca1v8_codec: LDO_REG7 { + regulator-name = "vcca1v8_codec"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_3v0: LDO_REG8 { + regulator-name = "vcc_3v0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vcc3v3_s3: SWITCH_REG1 { + regulator-name = "vcc3v3_s3"; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc3v3_s0: SWITCH_REG2 { + regulator-name = "vcc3v3_s0"; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + }; + }; +}; + +&i2c4 { + i2c-scl-rising-time-ns = <600>; + i2c-scl-falling-time-ns = <20>; + status = "okay"; +}; + +&io_domains { + status = "okay"; + + bt656-supply = <&vcc1v8_dvp>; + audio-supply = <&vcca1v8_codec>; + sdmmc-supply = <&vcc_sd>; + gpio1830-supply = <&vcc_3v0>; +}; + +&pmu_io_domains { + pmu1830-supply = <&vcc_3v0>; + status = "okay"; +}; + +&pinctrl { + pmic { + vsel1_gpio: vsel1-gpio { + rockchip,pins = <1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + vsel2_gpio: vsel2-gpio { + rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; + + sdio-pwrseq { + wifi_enable_h: wifi-enable-h { + rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pmic { + pmic_int_l: pmic-int-l { + rockchip,pins = <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + usb2 { + host_vbus_drv: host-vbus-drv { + rockchip,pins = <4 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + host_usb3_drv: host-usb3-drv { + rockchip,pins = <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&pwm0 { + status = "okay"; +}; + +&pwm2 { + status = "okay"; +}; + +&saradc { + status = "okay"; +}; + +&sdmmc { + u-boot,dm-spl; + bus-width = <4>; + status = "okay"; + max-frequency = <20000000>; +}; + +&sdhci { + u-boot,dm-spl; + bus-width = <8>; + max-frequency = <25000000>; + mmc-hs400-1_8v; + mmc-hs400-enhanced-strobe; + non-removable; + status = "okay"; +}; + +&tsadc { + /* tshut mode 0:CRU 1:GPIO */ + rockchip,hw-tshut-mode = <1>; + /* tshut polarity 0:LOW 1:HIGH */ + rockchip,hw-tshut-polarity = <1>; + status = "okay"; +}; + +&u2phy0 { + /delete-property/ clocks; + /delete-property/ clock-names; + + status = "okay"; + + u2phy0_otg: otg-port { + status = "okay"; + }; + + u2phy0_host: host-port { + phy-supply = <&vcc5v0_host>; + status = "okay"; + }; +}; + +&u2phy1 { + /delete-property/ clocks; + /delete-property/ clock-names; + + status = "okay"; + + u2phy1_otg: otg-port { + status = "okay"; + }; + + u2phy1_host: host-port { + phy-supply = <&vcc5v0_host>; + status = "okay"; + }; +}; + +&uart2 { + u-boot,dm-pre-reloc; + status = "okay"; +}; + +&dwc3_typec0 { + status = "okay"; + maximum-speed = "high-speed"; +}; + +&usb_host0_ehci { + /delete-property/ clocks; + /delete-property/ clock-names; + + vbus-supply = <&vcc5v0_host>; + status = "okay"; +}; + +&usb_host0_ohci { + /delete-property/ clocks; + /delete-property/ clock-names; + + vbus-supply = <&vcc5v0_host>; + status = "okay"; +}; + +&usb_host1_ehci { + /delete-property/ clocks; + /delete-property/ clock-names; + + vbus-supply = <&vcc5v0_host>; + status = "okay"; +}; + +&usb_host1_ohci { + /delete-property/ clocks; + /delete-property/ clock-names; + + vbus-supply = <&vcc5v0_host>; + status = "okay"; +}; + +&dwc3_typec1 { + vbus-supply = <&vcc5v0_host>; + status = "okay"; + maximum-speed = "high-speed"; +}; + +&spi1 { + u-boot,dm-spl; + status = "okay"; + + spiflash: spi-flash@0 { + u-boot,dm-spl; + #address-cells = <0x1>; + #size-cells = <1>; + compatible = "spi-flash"; + reg = <0x0>; + spi-max-frequency = <25000000>; + status = "okay"; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + loader@8000 { + label = "loader"; + reg = <0x0 0x3F8000>; + }; + + env@3f8000 { + label = "env"; + reg = <0x3F8000 0x8000>; + }; + + vendor@7c0000 { + label = "vendor"; + reg = <0x7C0000 0x40000>; + }; + }; + }; +}; diff --git a/arch/arm/dts/rk3399-rockpi4b.dts b/arch/arm/dts/rk3399-rockpi4b.dts new file mode 100644 index 00000000000..5574e9bcec1 --- /dev/null +++ b/arch/arm/dts/rk3399-rockpi4b.dts @@ -0,0 +1,633 @@ +/* + * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/dts-v1/; +#include +#include +#include "rk3399.dtsi" + +/ { + model = "RockPi-4B"; + compatible = "radxa,rockpi-4b", "rockchip,rk3399"; + + chosen { + stdout-path = &uart2; + }; + + aliases { + spi0 = &spi1; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + enable-gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_HIGH>; + pwms = <&pwm0 0 25000 0>; + brightness-levels = < + 0 1 2 3 4 5 6 7 + 8 9 10 11 12 13 14 15 + 16 17 18 19 20 21 22 23 + 24 25 26 27 28 29 30 31 + 32 33 34 35 36 37 38 39 + 40 41 42 43 44 45 46 47 + 48 49 50 51 52 53 54 55 + 56 57 58 59 60 61 62 63 + 64 65 66 67 68 69 70 71 + 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 + 88 89 90 91 92 93 94 95 + 96 97 98 99 100 101 102 103 + 104 105 106 107 108 109 110 111 + 112 113 114 115 116 117 118 119 + 120 121 122 123 124 125 126 127 + 128 129 130 131 132 133 134 135 + 136 137 138 139 140 141 142 143 + 144 145 146 147 148 149 150 151 + 152 153 154 155 156 157 158 159 + 160 161 162 163 164 165 166 167 + 168 169 170 171 172 173 174 175 + 176 177 178 179 180 181 182 183 + 184 185 186 187 188 189 190 191 + 192 193 194 195 196 197 198 199 + 200 201 202 203 204 205 206 207 + 208 209 210 211 212 213 214 215 + 216 217 218 219 220 221 222 223 + 224 225 226 227 228 229 230 231 + 232 233 234 235 236 237 238 239 + 240 241 242 243 244 245 246 247 + 248 249 250 251 252 253 254 255>; + default-brightness-level = <200>; + }; + + leds { + status = "okay"; + compatible = "gpio-leds"; + + system-status { + label = "status"; + gpios = <&gpio3 28 GPIO_ACTIVE_HIGH>; + }; + }; + + clkin_gmac: external-gmac-clock { + compatible = "fixed-clock"; + clock-frequency = <125000000>; + clock-output-names = "clkin_gmac"; + #clock-cells = <0>; + }; + + sdio_pwrseq: sdio-pwrseq { + compatible = "mmc-pwrseq-simple"; + clocks = <&rk808 1>; + clock-names = "ext_clock"; + pinctrl-names = "default"; + pinctrl-0 = <&wifi_enable_h>; + + /* + * On the module itself this is one of these (depending + * on the actual card populated): + * - SDIO_RESET_L_WL_REG_ON + * - PDN (power down when low) + */ + reset-gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_LOW>; + }; + + vcc1v8_s0: vcc1v8-s0 { + compatible = "regulator-fixed"; + regulator-name = "vcc1v8_s0"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + dc_12v: dc-12v { + compatible = "regulator-fixed"; + regulator-name = "dc_12v"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + }; + + vcc_sys: vcc-sys { + compatible = "regulator-fixed"; + regulator-name = "vcc_sys"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + vin-supply = <&dc_12v>; + }; + + vcc3v3_sys: vcc3v3-sys { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc_sys>; + }; + + vcc5v0_host: vcc5v0-host-regulator { + compatible = "regulator-fixed"; + gpio = <&gpio4 RK_PD1 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&host_vbus_drv>; + regulator-name = "vcc5v0_host"; + }; + + vcc5v0_typec0: vcc5v0-typec0-en { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_typec0"; + gpio = <&gpio1 3 GPIO_ACTIVE_HIGH>; + }; + + vcc_phy: vcc-phy-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_phy"; + regulator-always-on; + regulator-boot-on; + }; + + vdd_log: vdd-log { + compatible = "pwm-regulator"; + pwms = <&pwm2 0 25000 1>; + regulator-name = "vdd_log"; + regulator-always-on; + regulator-boot-on; + regulator-init-microvolt = <900000>; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1400000>; + }; +}; + +&cpu_l0 { + cpu-supply = <&vdd_cpu_l>; +}; + +&cpu_l1 { + cpu-supply = <&vdd_cpu_l>; +}; + +&cpu_l2 { + cpu-supply = <&vdd_cpu_l>; +}; + +&cpu_l3 { + cpu-supply = <&vdd_cpu_l>; +}; + +&emmc_phy { + status = "okay"; +}; + +&gmac { + assigned-clocks = <&cru SCLK_RMII_SRC>; + assigned-clock-parents = <&clkin_gmac>; + clock_in_out = "input"; + phy-supply = <&vcc_phy>; + phy-mode = "rgmii"; + pinctrl-names = "default"; + pinctrl-0 = <&rgmii_pins>; + snps,reset-gpio = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; + snps,reset-active-low; + snps,reset-delays-us = <0 10000 50000>; + tx_delay = <0x28>; + rx_delay = <0x20>; + status = "okay"; +}; + +&i2c0 { + clock-frequency = <400000>; + i2c-scl-rising-time-ns = <168>; + i2c-scl-falling-time-ns = <4>; + status = "okay"; + + rk808: pmic@1b { + compatible = "rockchip,rk808"; + reg = <0x1b>; + interrupt-parent = <&gpio1>; + interrupts = <21 IRQ_TYPE_LEVEL_LOW>; + #clock-cells = <1>; + clock-output-names = "xin32k", "rk808-clkout2"; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int_l>; + rockchip,system-power-controller; + wakeup-source; + + vcc1-supply = <&vcc_sys>; + vcc2-supply = <&vcc_sys>; + vcc3-supply = <&vcc_sys>; + vcc4-supply = <&vcc_sys>; + vcc6-supply = <&vcc_sys>; + vcc7-supply = <&vcc_sys>; + vcc8-supply = <&vcc3v3_sys>; + vcc9-supply = <&vcc_sys>; + vcc10-supply = <&vcc_sys>; + vcc11-supply = <&vcc_sys>; + vcc12-supply = <&vcc3v3_sys>; + vddio-supply = <&vcc_1v8>; + + regulators { + vdd_center: DCDC_REG1 { + regulator-name = "vdd_center"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_l: DCDC_REG2 { + regulator-name = "vdd_cpu_l"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-name = "vcc_ddr"; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_1v8: DCDC_REG4 { + regulator-name = "vcc_1v8"; + 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>; + }; + }; + + vcc1v8_dvp: LDO_REG1 { + regulator-name = "vcc1v8_dvp"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc3v0_touch: LDO_REG2 { + regulator-name = "vcc3v0_touch"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vcc1v8_pmu: LDO_REG3 { + regulator-name = "vcc1v8_pmu"; + 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>; + }; + }; + + vcc_sd: LDO_REG4 { + regulator-name = "vcc_sd"; + 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>; + }; + }; + + vcca3v0_codec: LDO_REG5 { + regulator-name = "vcca3v0_codec"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v5: LDO_REG6 { + regulator-name = "vcc_1v5"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1500000>; + }; + }; + + vcca1v8_codec: LDO_REG7 { + regulator-name = "vcca1v8_codec"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_3v0: LDO_REG8 { + regulator-name = "vcc_3v0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vcc3v0_sd: vcc3v0-sd { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio0 RK_PA1 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc0_pwr_h>; + regulator-always-on; + regulator-max-microvolt = <3000000>; + regulator-min-microvolt = <3000000>; + regulator-name = "vcc3v0_sd"; + vin-supply = <&vcc3v3_sys>; + }; + + vcc3v3_s3: SWITCH_REG1 { + regulator-name = "vcc3v3_s3"; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc3v3_s0: SWITCH_REG2 { + regulator-name = "vcc3v3_s0"; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + }; + }; +}; + +&i2c1 { + i2c-scl-rising-time-ns = <300>; + i2c-scl-falling-time-ns = <15>; + status = "okay"; +}; + +&i2c3 { + i2c-scl-rising-time-ns = <450>; + i2c-scl-falling-time-ns = <15>; + status = "okay"; +}; + +&i2c4 { + i2c-scl-rising-time-ns = <600>; + i2c-scl-falling-time-ns = <20>; + status = "okay"; +}; + +&io_domains { + status = "okay"; + + bt656-supply = <&vcc1v8_s0>; + audio-supply = <&vcc1v8_s0>; + sdmmc-supply = <&vcc_sd>; + gpio1830-supply = <&vcc_3v0>; +}; + +&pmu_io_domains { + pmu1830-supply = <&vcc_3v0>; + status = "okay"; +}; + +&pinctrl { + pmic { + vsel1_gpio: vsel1-gpio { + rockchip,pins = <1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + vsel2_gpio: vsel2-gpio { + rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; + + sd { + sdmmc0_pwr_h: sdmmc0-pwr-h { + rockchip,pins = + ; + }; + }; + + sdio-pwrseq { + wifi_enable_h: wifi-enable-h { + rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pmic { + pmic_int_l: pmic-int-l { + rockchip,pins = <1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + usb2 { + host_vbus_drv: host-vbus-drv { + rockchip,pins = <4 RK_PD1 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&pwm0 { + status = "okay"; +}; + +&pwm2 { + status = "okay"; +}; + +&saradc { + status = "okay"; +}; + +&sdmmc { + vmmc-supply = <&vcc3v0_sd>; + u-boot,dm-spl; + bus-width = <4>; + status = "okay"; + max-frequency = <20000000>; +}; + +&sdhci { + u-boot,dm-spl; + bus-width = <8>; + max-frequency = <25000000>; + //mmc-hs400-1_8v; + //mmc-hs400-enhanced-strobe; + non-removable; + status = "okay"; +}; + +&tsadc { + /* tshut mode 0:CRU 1:GPIO */ + rockchip,hw-tshut-mode = <1>; + /* tshut polarity 0:LOW 1:HIGH */ + rockchip,hw-tshut-polarity = <1>; + status = "okay"; +}; + +&u2phy0 { + /delete-property/ clocks; + /delete-property/ clock-names; + + status = "okay"; + + u2phy0_otg: otg-port { + status = "okay"; + }; + + u2phy0_host: host-port { + phy-supply = <&vcc5v0_host>; + status = "okay"; + }; +}; + +&u2phy1 { + /delete-property/ clocks; + /delete-property/ clock-names; + + status = "okay"; + + u2phy1_otg: otg-port { + status = "okay"; + }; + + u2phy1_host: host-port { + phy-supply = <&vcc5v0_host>; + status = "okay"; + }; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_xfer &uart0_cts>; + status = "okay"; +}; + +&uart2 { + u-boot,dm-pre-reloc; + status = "okay"; +}; + +&dwc3_typec0 { + status = "okay"; + maximum-speed = "high-speed"; +}; + +&usb_host0_ehci { + /delete-property/ clocks; + /delete-property/ clock-names; + + vbus-supply = <&vcc5v0_host>; + status = "okay"; +}; + +&usb_host0_ohci { + /delete-property/ clocks; + /delete-property/ clock-names; + + vbus-supply = <&vcc5v0_host>; + status = "okay"; +}; + +&usb_host1_ehci { + /delete-property/ clocks; + /delete-property/ clock-names; + + vbus-supply = <&vcc5v0_host>; + status = "okay"; +}; + +&usb_host1_ohci { + /delete-property/ clocks; + /delete-property/ clock-names; + + vbus-supply = <&vcc5v0_host>; + status = "okay"; +}; + +&dwc3_typec1 { + vbus-supply = <&vcc5v0_host>; + status = "okay"; + maximum-speed = "high-speed"; +}; + +&spi1 { + u-boot,dm-spl; + status = "okay"; + + spiflash: spi-flash@0 { + u-boot,dm-spl; + #address-cells = <0x1>; + #size-cells = <1>; + compatible = "spi-flash"; + reg = <0x0>; + spi-max-frequency = <3000000>; + status = "okay"; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + loader@8000 { + label = "loader"; + reg = <0x0 0x3F8000>; + }; + + env@3f8000 { + label = "env"; + reg = <0x3F8000 0x8000>; + }; + + vendor@7c0000 { + label = "vendor"; + reg = <0x7C0000 0x40000>; + }; + }; + }; +}; diff --git a/arch/arm/dts/rk3399-rockpro64.dts b/arch/arm/dts/rk3399-rockpro64.dts new file mode 100644 index 00000000000..12c790093a9 --- /dev/null +++ b/arch/arm/dts/rk3399-rockpro64.dts @@ -0,0 +1,617 @@ +/* + * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/dts-v1/; +#include +#include +#include "rk3399.dtsi" + +/ { + model = "Pine64 RockPro64"; + compatible = "pine64,rockpro64", "rockchip,rk3399"; + + chosen { + stdout-path = &uart2; + }; + + aliases { + spi0 = &spi1; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + enable-gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_HIGH>; + pwms = <&pwm0 0 25000 0>; + brightness-levels = < + 0 1 2 3 4 5 6 7 + 8 9 10 11 12 13 14 15 + 16 17 18 19 20 21 22 23 + 24 25 26 27 28 29 30 31 + 32 33 34 35 36 37 38 39 + 40 41 42 43 44 45 46 47 + 48 49 50 51 52 53 54 55 + 56 57 58 59 60 61 62 63 + 64 65 66 67 68 69 70 71 + 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 + 88 89 90 91 92 93 94 95 + 96 97 98 99 100 101 102 103 + 104 105 106 107 108 109 110 111 + 112 113 114 115 116 117 118 119 + 120 121 122 123 124 125 126 127 + 128 129 130 131 132 133 134 135 + 136 137 138 139 140 141 142 143 + 144 145 146 147 148 149 150 151 + 152 153 154 155 156 157 158 159 + 160 161 162 163 164 165 166 167 + 168 169 170 171 172 173 174 175 + 176 177 178 179 180 181 182 183 + 184 185 186 187 188 189 190 191 + 192 193 194 195 196 197 198 199 + 200 201 202 203 204 205 206 207 + 208 209 210 211 212 213 214 215 + 216 217 218 219 220 221 222 223 + 224 225 226 227 228 229 230 231 + 232 233 234 235 236 237 238 239 + 240 241 242 243 244 245 246 247 + 248 249 250 251 252 253 254 255>; + default-brightness-level = <200>; + }; + + leds { + status = "okay"; + compatible = "gpio-leds"; + + power-led { + label = "power"; + gpios = <&gpio0 11 GPIO_ACTIVE_HIGH>; + }; + + standby-led { + label = "standby"; + gpios = <&gpio0 2 GPIO_ACTIVE_HIGH>; + }; + }; + + clkin_gmac: external-gmac-clock { + compatible = "fixed-clock"; + clock-frequency = <125000000>; + clock-output-names = "clkin_gmac"; + #clock-cells = <0>; + }; + + sdio_pwrseq: sdio-pwrseq { + compatible = "mmc-pwrseq-simple"; + clocks = <&rk808 1>; + clock-names = "ext_clock"; + pinctrl-names = "default"; + pinctrl-0 = <&wifi_enable_h>; + + /* + * On the module itself this is one of these (depending + * on the actual card populated): + * - SDIO_RESET_L_WL_REG_ON + * - PDN (power down when low) + */ + reset-gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_LOW>; + }; + + vcc1v8_s0: vcc1v8-s0 { + compatible = "regulator-fixed"; + regulator-name = "vcc1v8_s0"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + dc_12v: dc-12v { + compatible = "regulator-fixed"; + regulator-name = "dc_12v"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + }; + + vcc_sys: vcc-sys { + compatible = "regulator-fixed"; + regulator-name = "vcc_sys"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + vin-supply = <&dc_12v>; + }; + + vcc3v3_sys: vcc3v3-sys { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc_sys>; + }; + + vcc5v0_host: vcc5v0-host-regulator { + compatible = "regulator-fixed"; + gpio = <&gpio4 RK_PD2 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&host_vbus_drv>; + regulator-name = "vcc5v0_host"; + }; + + vcc5v0_typec0: vcc5v0-typec0-en { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_typec0"; + gpio = <&gpio1 3 GPIO_ACTIVE_HIGH>; + }; + + vcc_phy: vcc-phy-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_phy"; + regulator-always-on; + regulator-boot-on; + }; + + vdd_log: vdd-log { + compatible = "pwm-regulator"; + pwms = <&pwm2 0 25000 1>; + regulator-name = "vdd_log"; + regulator-always-on; + regulator-boot-on; + regulator-init-microvolt = <900000>; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1400000>; + }; +}; + +&cpu_l0 { + cpu-supply = <&vdd_cpu_l>; +}; + +&cpu_l1 { + cpu-supply = <&vdd_cpu_l>; +}; + +&cpu_l2 { + cpu-supply = <&vdd_cpu_l>; +}; + +&cpu_l3 { + cpu-supply = <&vdd_cpu_l>; +}; + +&emmc_phy { + status = "okay"; +}; + +&gmac { + assigned-clocks = <&cru SCLK_RMII_SRC>; + assigned-clock-parents = <&clkin_gmac>; + clock_in_out = "input"; + phy-supply = <&vcc_phy>; + phy-mode = "rgmii"; + pinctrl-names = "default"; + pinctrl-0 = <&rgmii_pins>; + snps,reset-gpio = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; + snps,reset-active-low; + snps,reset-delays-us = <0 10000 50000>; + tx_delay = <0x28>; + rx_delay = <0x20>; + status = "okay"; +}; + +&i2c0 { + clock-frequency = <400000>; + i2c-scl-rising-time-ns = <168>; + i2c-scl-falling-time-ns = <4>; + status = "okay"; + + rk808: pmic@1b { + compatible = "rockchip,rk808"; + reg = <0x1b>; + interrupt-parent = <&gpio1>; + interrupts = <21 IRQ_TYPE_LEVEL_LOW>; + #clock-cells = <1>; + clock-output-names = "xin32k", "rk808-clkout2"; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int_l>; + rockchip,system-power-controller; + wakeup-source; + + vcc1-supply = <&vcc_sys>; + vcc2-supply = <&vcc_sys>; + vcc3-supply = <&vcc_sys>; + vcc4-supply = <&vcc_sys>; + vcc6-supply = <&vcc_sys>; + vcc7-supply = <&vcc_sys>; + vcc8-supply = <&vcc3v3_sys>; + vcc9-supply = <&vcc_sys>; + vcc10-supply = <&vcc_sys>; + vcc11-supply = <&vcc_sys>; + vcc12-supply = <&vcc3v3_sys>; + vddio-supply = <&vcc_1v8>; + + regulators { + vdd_center: DCDC_REG1 { + regulator-name = "vdd_center"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_l: DCDC_REG2 { + regulator-name = "vdd_cpu_l"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-name = "vcc_ddr"; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_1v8: DCDC_REG4 { + regulator-name = "vcc_1v8"; + 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>; + }; + }; + + vcc1v8_dvp: LDO_REG1 { + regulator-name = "vcc1v8_dvp"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc3v0_touch: LDO_REG2 { + regulator-name = "vcc3v0_touch"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vcc1v8_pmu: LDO_REG3 { + regulator-name = "vcc1v8_pmu"; + 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>; + }; + }; + + vcc_sd: LDO_REG4 { + regulator-name = "vcc_sd"; + 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>; + }; + }; + + vcca3v0_codec: LDO_REG5 { + regulator-name = "vcca3v0_codec"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v5: LDO_REG6 { + regulator-name = "vcc_1v5"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1500000>; + }; + }; + + vcca1v8_codec: LDO_REG7 { + regulator-name = "vcca1v8_codec"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_3v0: LDO_REG8 { + regulator-name = "vcc_3v0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vcc3v3_s3: SWITCH_REG1 { + regulator-name = "vcc3v3_s3"; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc3v3_s0: SWITCH_REG2 { + regulator-name = "vcc3v3_s0"; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + }; + }; +}; + +&i2c1 { + i2c-scl-rising-time-ns = <300>; + i2c-scl-falling-time-ns = <15>; + status = "okay"; +}; + +&i2c3 { + i2c-scl-rising-time-ns = <450>; + i2c-scl-falling-time-ns = <15>; + status = "okay"; +}; + +&i2c4 { + i2c-scl-rising-time-ns = <600>; + i2c-scl-falling-time-ns = <20>; + status = "okay"; +}; + +&io_domains { + status = "okay"; + + bt656-supply = <&vcc1v8_s0>; + audio-supply = <&vcc1v8_s0>; + sdmmc-supply = <&vcc_sd>; + gpio1830-supply = <&vcc_3v0>; +}; + +&pmu_io_domains { + pmu1830-supply = <&vcc_3v0>; + status = "okay"; +}; + +&pinctrl { + pmic { + vsel1_gpio: vsel1-gpio { + rockchip,pins = <1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + vsel2_gpio: vsel2-gpio { + rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; + + sdio-pwrseq { + wifi_enable_h: wifi-enable-h { + rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pmic { + pmic_int_l: pmic-int-l { + rockchip,pins = <1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + usb2 { + host_vbus_drv: host-vbus-drv { + rockchip,pins = <4 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&pwm0 { + status = "okay"; +}; + +&pwm2 { + status = "okay"; +}; + +&saradc { + status = "okay"; +}; + +&sdmmc { + u-boot,dm-spl; + bus-width = <4>; + status = "okay"; + max-frequency = <20000000>; +}; + +&sdhci { + u-boot,dm-spl; + bus-width = <8>; + max-frequency = <25000000>; + mmc-hs400-1_8v; + mmc-hs400-enhanced-strobe; + non-removable; + status = "okay"; +}; + +&tsadc { + /* tshut mode 0:CRU 1:GPIO */ + rockchip,hw-tshut-mode = <1>; + /* tshut polarity 0:LOW 1:HIGH */ + rockchip,hw-tshut-polarity = <1>; + status = "okay"; +}; + +&u2phy0 { + /delete-property/ clocks; + /delete-property/ clock-names; + + status = "okay"; + + u2phy0_otg: otg-port { + status = "okay"; + }; + + u2phy0_host: host-port { + phy-supply = <&vcc5v0_host>; + status = "okay"; + }; +}; + +&u2phy1 { + /delete-property/ clocks; + /delete-property/ clock-names; + + status = "okay"; + + u2phy1_otg: otg-port { + status = "okay"; + }; + + u2phy1_host: host-port { + phy-supply = <&vcc5v0_host>; + status = "okay"; + }; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_xfer &uart0_cts>; + status = "okay"; +}; + +&uart2 { + u-boot,dm-pre-reloc; + status = "okay"; +}; + +&dwc3_typec0 { + status = "okay"; + maximum-speed = "high-speed"; +}; + +&usb_host0_ehci { + /delete-property/ clocks; + /delete-property/ clock-names; + + vbus-supply = <&vcc5v0_host>; + status = "okay"; +}; + +&usb_host0_ohci { + /delete-property/ clocks; + /delete-property/ clock-names; + + vbus-supply = <&vcc5v0_host>; + status = "okay"; +}; + +&usb_host1_ehci { + /delete-property/ clocks; + /delete-property/ clock-names; + + vbus-supply = <&vcc5v0_host>; + status = "okay"; +}; + +&usb_host1_ohci { + /delete-property/ clocks; + /delete-property/ clock-names; + + vbus-supply = <&vcc5v0_host>; + status = "okay"; +}; + +&dwc3_typec1 { + vbus-supply = <&vcc5v0_host>; + status = "okay"; + maximum-speed = "high-speed"; +}; + +&spi1 { + u-boot,dm-spl; + status = "okay"; + + spiflash: spi-flash@0 { + u-boot,dm-spl; + #address-cells = <0x1>; + #size-cells = <1>; + compatible = "spi-flash"; + reg = <0x0>; + spi-max-frequency = <25000000>; + status = "okay"; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + loader@8000 { + label = "loader"; + reg = <0x0 0x3F8000>; + }; + + env@3f8000 { + label = "env"; + reg = <0x3F8000 0x8000>; + }; + + vendor@7c0000 { + label = "vendor"; + reg = <0x7C0000 0x40000>; + }; + }; + }; +}; diff --git a/arch/arm/dts/rk3399.dtsi b/arch/arm/dts/rk3399.dtsi index 68221b47f74..ac4c1c71703 100644 --- a/arch/arm/dts/rk3399.dtsi +++ b/arch/arm/dts/rk3399.dtsi @@ -259,22 +259,6 @@ status = "disabled"; }; - sdmmc: dwmmc@fe320000 { - compatible = "rockchip,rk3399-dw-mshc", - "rockchip,rk3288-dw-mshc"; - reg = <0x0 0xfe320000 0x0 0x4000>; - interrupts = ; - max-frequency = <150000000>; - clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>, - <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>; - clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; - fifo-depth = <0x100>; - power-domains = <&power RK3399_PD_SD>; - resets = <&cru SRST_SDMMC>; - reset-names = "reset"; - status = "disabled"; - }; - sdhci: sdhci@fe330000 { u-boot,dm-pre-reloc; compatible = "rockchip,rk3399-sdhci-5.1", "arasan,sdhci-5.1"; @@ -294,6 +278,22 @@ status = "disabled"; }; + sdmmc: dwmmc@fe320000 { + compatible = "rockchip,rk3399-dw-mshc", + "rockchip,rk3288-dw-mshc"; + reg = <0x0 0xfe320000 0x0 0x4000>; + interrupts = ; + max-frequency = <150000000>; + clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>, + <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>; + clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; + fifo-depth = <0x100>; + power-domains = <&power RK3399_PD_SD>; + resets = <&cru SRST_SDMMC>; + reset-names = "reset"; + status = "disabled"; + }; + usb_host0_ehci: usb@fe380000 { compatible = "generic-ehci"; reg = <0x0 0xfe380000 0x0 0x20000>; diff --git a/arch/arm/include/asm/arch-rockchip/boot_mode.h b/arch/arm/include/asm/arch-rockchip/boot_mode.h index 6b2a610cf4c..ad50b2e2f35 100644 --- a/arch/arm/include/asm/arch-rockchip/boot_mode.h +++ b/arch/arm/include/asm/arch-rockchip/boot_mode.h @@ -22,4 +22,6 @@ int setup_boot_mode(void); #endif +int setup_boot_mode(void); + #endif diff --git a/arch/arm/include/asm/arch-rockchip/bootrom.h b/arch/arm/include/asm/arch-rockchip/bootrom.h index 21994a65ee1..a62f71c4537 100644 --- a/arch/arm/include/asm/arch-rockchip/bootrom.h +++ b/arch/arm/include/asm/arch-rockchip/bootrom.h @@ -39,4 +39,24 @@ enum rockchip_bootrom_cmd { }; void back_to_bootrom(enum rockchip_bootrom_cmd brom_cmd); + +/** + * Boot-device identifiers as used by the BROM + */ +enum { + BROM_BOOTSOURCE_NAND = 1, + BROM_BOOTSOURCE_EMMC = 2, + BROM_BOOTSOURCE_SPINOR = 3, + BROM_BOOTSOURCE_SPINAND = 4, + BROM_BOOTSOURCE_SD = 5, + BROM_BOOTSOURCE_USB = 10, + BROM_LAST_BOOTSOURCE = BROM_BOOTSOURCE_USB +}; + +/** + * Locations of the boot-device identifier in SRAM + */ +#define RK3328_BROM_BOOTSOURCE_ID_ADDR 0xff090010 +#define RK3399_BROM_BOOTSOURCE_ID_ADDR 0xff8c0010 + #endif diff --git a/arch/arm/include/asm/arch-rockchip/grf_rk3328.h b/arch/arm/include/asm/arch-rockchip/grf_rk3328.h index f0a0781d8db..a396510d558 100644 --- a/arch/arm/include/asm/arch-rockchip/grf_rk3328.h +++ b/arch/arm/include/asm/arch-rockchip/grf_rk3328.h @@ -145,6 +145,74 @@ enum { GPIO0A7_SEL_MASK = 3 << GPIO0A7_SEL_SHIFT, GPIO0A7_EMMC_DATA0 = 2, + GPIO0B0_SEL_SHIFT = 0, + GPIO0B0_SEL_MASK = 3 << GPIO0B0_SEL_SHIFT, + GPIO0B0_MAC_TXCLK = 1, + + GPIO0B1_SEL_SHIFT = 2, + GPIO0B1_SEL_MASK = 3 << GPIO0B1_SEL_SHIFT, + GPIO0B1_MAC_CRS = 1, + + GPIO0B2_SEL_SHIFT = 4, + GPIO0B2_SEL_MASK = 3 << GPIO0B2_SEL_SHIFT, + GPIO0B2_MAC_RXCLK = 1, + + GPIO0B3_SEL_SHIFT = 6, + GPIO0B3_SEL_MASK = 3 << GPIO0B3_SEL_SHIFT, + GPIO0B3_MAC_MDIO = 1, + + GPIO0B4_SEL_SHIFT = 8, + GPIO0B4_SEL_MASK = 3 << GPIO0B4_SEL_SHIFT, + GPIO0B4_MAC_TXEN = 1, + + GPIO0B6_SEL_SHIFT = 12, + GPIO0B6_SEL_MASK = 3 << GPIO0B6_SEL_SHIFT, + GPIO0B6_MAC_RXD1 = 1, + + GPIO0B7_SEL_SHIFT = 14, + GPIO0B7_SEL_MASK = 3 << GPIO0B7_SEL_SHIFT, + GPIO0B7_MAC_RXD0 = 1, + + GPIO0C0_SEL_SHIFT = 0, + GPIO0C0_SEL_MASK = 3 << GPIO0C0_SEL_SHIFT, + GPIO0C0_MAC_TXD1 = 1, + + GPIO0C1_SEL_SHIFT = 2, + GPIO0C1_SEL_MASK = 3 << GPIO0C1_SEL_SHIFT, + GPIO0C1_MAC_TXD0 = 1, + + GPIO0C2_SEL_SHIFT = 4, + GPIO0C2_SEL_MASK = 3 << GPIO0C2_SEL_SHIFT, + GPIO0C2_MAC_COL = 1, + + GPIO0C3_SEL_SHIFT = 6, + GPIO0C3_SEL_MASK = 3 << GPIO0C3_SEL_SHIFT, + GPIO0C3_MAC_MDC = 1, + + GPIO0C4_SEL_SHIFT = 8, + GPIO0C4_SEL_MASK = 3 << GPIO0C4_SEL_SHIFT, + GPIO0C4_MAC_RXD3 = 1, + + GPIO0C5_SEL_SHIFT = 10, + GPIO0C5_SEL_MASK = 3 << GPIO0C5_SEL_SHIFT, + GPIO0C5_MAC_RXD2 = 1, + + GPIO0C6_SEL_SHIFT = 12, + GPIO0C6_SEL_MASK = 3 << GPIO0C6_SEL_SHIFT, + GPIO0C6_MAC_TXD2 = 1, + + GPIO0C7_SEL_SHIFT = 14, + GPIO0C7_SEL_MASK = 3 << GPIO0C7_SEL_SHIFT, + GPIO0C7_MAC_TXD3 = 1, + + GPIO0D0_SEL_SHIFT = 0, + GPIO0D0_SEL_MASK = 3 << GPIO0D0_SEL_SHIFT, + GPIO0D0_MAC_CLK = 1, + + GPIO0D1_SEL_SHIFT = 2, + GPIO0D1_SEL_MASK = 3 << GPIO0D1_SEL_SHIFT, + GPIO0D1_MAC_RXDV = 1, + /* GPIO0D_IOMUX*/ GPIO0D6_SEL_SHIFT = 12, GPIO0D6_SEL_MASK = 3 << GPIO0D6_SEL_SHIFT, @@ -156,6 +224,77 @@ enum { GPIO1A0_SEL_MASK = 0x3fff << GPIO1A0_SEL_SHIFT, GPIO1A0_CARD_DATA_CLK_CMD_DETN = 0x1555, + /* GPIO1B_IOMUX */ + GPIO1B0_SEL_SHIFT = 0, + GPIO1B0_SEL_MASK = 3 << GPIO1B0_SEL_SHIFT, + GPIO1B0_MAC_TXD1 = 2, + + GPIO1B1_SEL_SHIFT = 2, + GPIO1B1_SEL_MASK = 3 << GPIO1B1_SEL_SHIFT, + GPIO1B1_MAC_TXD0 = 2, + + GPIO1B2_SEL_SHIFT = 4, + GPIO1B2_SEL_MASK = 3 << GPIO1B2_SEL_SHIFT, + GPIO1B2_MAC_RXD1 = 2, + + GPIO1B3_SEL_SHIFT = 6, + GPIO1B3_SEL_MASK = 3 << GPIO1B3_SEL_SHIFT, + GPIO1B3_MAC_RXD0 = 2, + + GPIO1B4_SEL_SHIFT = 8, + GPIO1B4_SEL_MASK = 3 << GPIO1B4_SEL_SHIFT, + GPIO1B4_MAC_TXCLK = 2, + + GPIO1B5_SEL_SHIFT = 10, + GPIO1B5_SEL_MASK = 3 << GPIO1B5_SEL_SHIFT, + GPIO1B5_MAC_RXCLK = 2, + + GPIO1B6_SEL_SHIFT = 12, + GPIO1B6_SEL_MASK = 3 << GPIO1B6_SEL_SHIFT, + GPIO1B6_MAC_RXD3 = 2, + + GPIO1B7_SEL_SHIFT = 14, + GPIO1B7_SEL_MASK = 3 << GPIO1B7_SEL_SHIFT, + GPIO1B7_MAC_RXD2 = 2, + + /* GPIO1C_IOMUX */ + GPIO1C0_SEL_SHIFT = 0, + GPIO1C0_SEL_MASK = 3 << GPIO1C0_SEL_SHIFT, + GPIO1C0_MAC_TXD3 = 2, + + GPIO1C1_SEL_SHIFT = 2, + GPIO1C1_SEL_MASK = 3 << GPIO1C1_SEL_SHIFT, + GPIO1C1_MAC_TXD2 = 2, + + GPIO1C2_SEL_SHIFT = 4, + GPIO1C2_SEL_MASK = 3 << GPIO1C2_SEL_SHIFT, + GPIO1C2_MAC_CRS = 2, + + GPIO1C3_SEL_SHIFT = 6, + GPIO1C3_SEL_MASK = 3 << GPIO1C3_SEL_SHIFT, + GPIO1C3_MAC_MDIO = 2, + + GPIO1C4_SEL_SHIFT = 8, + GPIO1C4_SEL_MASK = 3 << GPIO1C4_SEL_SHIFT, + GPIO1C4_MAC_COL = 2, + + GPIO1C5_SEL_SHIFT = 10, + GPIO1C5_SEL_MASK = 3 << GPIO1C5_SEL_SHIFT, + GPIO1C5_MAC_CLK = 2, + + GPIO1C6_SEL_SHIFT = 12, + GPIO1C6_SEL_MASK = 3 << GPIO1C6_SEL_SHIFT, + GPIO1C6_MAC_RXDV = 2, + + GPIO1C7_SEL_SHIFT = 14, + GPIO1C7_SEL_MASK = 3 << GPIO1C7_SEL_SHIFT, + GPIO1C7_MAC_MDC = 2, + + /* GPIO1D_IOMUX */ + GPIO1D1_SEL_SHIFT = 2, + GPIO1D1_SEL_MASK = 3 << GPIO1D1_SEL_SHIFT, + GPIO1D1_MAC_TXEN = 2, + /* GPIO2A_IOMUX */ GPIO2A0_SEL_SHIFT = 0, GPIO2A0_SEL_MASK = 3 << GPIO2A0_SEL_SHIFT, @@ -245,4 +384,29 @@ enum { IOMUX_SEL_SDMMC_M1, }; +#ifndef GPIO_BIAS_MASK +/* GPIO Bias settings */ +enum GPIO_BIAS { + GPIO_BIAS_2MA = 0, + GPIO_BIAS_4MA, + GPIO_BIAS_8MA, + GPIO_BIAS_12MA, +}; + +#define GPIO_BIAS_MASK 0x3 +#define GPIO_BIAS_SHIFT(x) ((x) * 2) +#endif + +#ifndef GPIO_PULL_MASK +enum GPIO_PU_PD { + GPIO_PULL_NORMAL = 0, + GPIO_PULL_UP, + GPIO_PULL_DOWN, + GPIO_PULL_REPEAT, +}; + +#define GPIO_PULL_MASK 0x3 +#define GPIO_PULL_SHIFT(x) ((x) * 2) +#endif + #endif /* __SOC_ROCKCHIP_RK3328_GRF_H__ */ diff --git a/arch/arm/include/asm/arch-rockchip/grf_rk3399.h b/arch/arm/include/asm/arch-rockchip/grf_rk3399.h index 8d21eb7bee7..3b256ea28fc 100644 --- a/arch/arm/include/asm/arch-rockchip/grf_rk3399.h +++ b/arch/arm/include/asm/arch-rockchip/grf_rk3399.h @@ -575,6 +575,12 @@ enum { PMUGRF_GPIO1B2_SEL_SHIFT = 4, PMUGRF_GPIO1B2_SEL_MASK = 3 << PMUGRF_GPIO1B2_SEL_SHIFT, PMUGRF_SPI1EC_CSN0 = 2, + PMUGRF_GPIO1B3_SEL_SHIFT = 6, + PMUGRF_GPIO1B3_SEL_MASK = 3 << PMUGRF_GPIO1B3_SEL_SHIFT, + PMUGRF_I2C4PMU_SDA = 1, + PMUGRF_GPIO1B4_SEL_SHIFT = 8, + PMUGRF_GPIO1B4_SEL_MASK = 3 << PMUGRF_GPIO1B4_SEL_SHIFT, + PMUGRF_I2C4PMU_SCL = 1, PMUGRF_GPIO1B6_SEL_SHIFT = 12, PMUGRF_GPIO1B6_SEL_MASK = 3 << PMUGRF_GPIO1B6_SEL_SHIFT, PMUGRF_PWM_3B = 1, diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig index cb80f26ac32..aa498a893d4 100644 --- a/arch/arm/mach-rockchip/Kconfig +++ b/arch/arm/mach-rockchip/Kconfig @@ -119,6 +119,7 @@ config ROCKCHIP_RK3328 imply SPL_SERIAL_SUPPORT imply TPL_SERIAL_SUPPORT imply SPL_SEPARATE_BSS + select ENABLE_ARM_SOC_BOOT0_HOOK select DEBUG_UART_BOARD_INIT select SYS_NS16550 help @@ -192,6 +193,7 @@ config ROCKCHIP_RK3399 select SPL_SEPARATE_BSS select SPL_SERIAL_SUPPORT select SPL_DRIVERS_MISC_SUPPORT + select ENABLE_ARM_SOC_BOOT0_HOOK select DEBUG_UART_BOARD_INIT select GICV3 select BOARD_LATE_INIT @@ -241,6 +243,7 @@ config ROCKCHIP_BOOT_MODE_REG default 0xff738200 if ROCKCHIP_RK3368 default 0xff320300 if ROCKCHIP_RK3399 default 0x10300580 if ROCKCHIP_RV1108 + default 0xff1005c8 if ROCKCHIP_RK3328 default 0 help The Soc will enter to different boot mode(defined in asm/arch/boot_mode.h) diff --git a/arch/arm/mach-rockchip/boot_mode.c b/arch/arm/mach-rockchip/boot_mode.c index d0dbff3bb85..639b7e0cb6a 100644 --- a/arch/arm/mach-rockchip/boot_mode.c +++ b/arch/arm/mach-rockchip/boot_mode.c @@ -54,15 +54,81 @@ __weak int rockchip_dnl_key_pressed(void) return false; } +void rockchip_blink_power(int times) +{ + for (int i = 0; i < times; ++i) { + cli_simple_run_command("led power off", 0); + mdelay(100); + cli_simple_run_command("led power on", 0); + mdelay(100); + } +} + +int rockchip_dnl_mode(int num_modes) +{ + int mode = 0; + + while(mode < num_modes) { + ++mode; + + printf("rockchip_dnl_mode = %d mode\n", mode); + rockchip_blink_power(mode); + + // return early + if (mode == num_modes) { + goto end; + } + + // wait 2 seconds + for (int i = 0; i < 100; ++i) { + if (!rockchip_dnl_key_pressed()) { + goto end; + } + mdelay(20); + } + } + +end: + cli_simple_run_command("led power off", 0); + cli_simple_run_command("led standby on", 0); + return mode; +} + void rockchip_dnl_mode_check(void) { - if (rockchip_dnl_key_pressed()) { - printf("download key pressed, entering download mode...\n"); - /* If failed, we fall back to bootrom download mode */ + if (!rockchip_dnl_key_pressed()) { + return 0; + } + + switch(rockchip_dnl_mode(4)) { + case 0: + return; + + case 1: + printf("entering ums mode...\n"); + cli_simple_run_command("ums 0 mmc 0", 0); + cli_simple_run_command("ums 0 mmc 1", 0); + break; + + case 2: + printf("entering fastboot mode...\n"); + cli_simple_run_command("mmc dev 0; fastboot usb 0", 0); + cli_simple_run_command("mmc dev 1; fastboot usb 0", 0); + break; + + case 3: + printf("entering download mode...\n"); cli_simple_run_command("rockusb 0 mmc 0", 0); - set_back_to_bootrom_dnl_flag(); - do_reset(NULL, 0, 0, NULL); + cli_simple_run_command("rockusb 0 mmc 1", 0); + break; + + case 4: + printf("entering maskrom mode...\n"); + break; } + + set_back_to_bootrom_dnl_flag(); + do_reset(NULL, 0, 0, NULL); } int setup_boot_mode(void) @@ -83,8 +149,23 @@ int setup_boot_mode(void) writel(BOOT_NORMAL, reg); switch (boot_mode) { + case BOOT_NORMAL: + printf("normal boot\n"); + env_set("boot_mode", "normal"); + break; + case BOOT_LOADER: + printf("enter Rockusb!\n"); + env_set("boot_mode", "loader"); + env_set("preboot", "setenv preboot; rockusb 0 mmc 0"); + break; + case BOOT_RECOVERY: + printf("enter recovery!\n"); + env_set("boot_mode", "recovery"); + env_set("reboot_mode", "recovery"); + break; case BOOT_FASTBOOT: printf("enter fastboot!\n"); + env_set("boot_mode", "fastboot"); #if defined(CONFIG_FASTBOOT_FLASH_MMC_DEV) snprintf(env_preboot, 256, "setenv preboot; mmc dev %x; fastboot usb 0; ", @@ -95,21 +176,15 @@ int setup_boot_mode(void) #endif env_set("preboot", env_preboot); break; - case BOOT_UMS: - printf("enter UMS!\n"); - env_set("preboot", "setenv preboot; ums mmc 0"); - break; - case BOOT_LOADER: - printf("enter Rockusb!\n"); - env_set("preboot", "setenv preboot; rockusb 0 mmc 0"); - break; case BOOT_CHARGING: printf("enter charging!\n"); + env_set("boot_mode", "charging"); env_set("preboot", "setenv preboot; charge"); break; - case BOOT_RECOVERY: - printf("enter Recovery mode!\n"); - env_set("reboot_mode", "recovery"); + case BOOT_UMS: + printf("enter UMS!\n"); + env_set("boot_mode", "ums"); + env_set("preboot", "setenv preboot; ums mmc 0"); break; } diff --git a/arch/arm/mach-rockchip/rk3328-board-spl.c b/arch/arm/mach-rockchip/rk3328-board-spl.c index 1f7274a8d0d..ecb749fbfb0 100644 --- a/arch/arm/mach-rockchip/rk3328-board-spl.c +++ b/arch/arm/mach-rockchip/rk3328-board-spl.c @@ -11,11 +11,18 @@ #include #include #include +#include +#include #include #include #include #include #include +#include +#include + +#define GRF_BASE 0xFF100000 +#define GPIO0_BASE 0xFF210000 DECLARE_GLOBAL_DATA_PTR; @@ -23,6 +30,32 @@ void board_debug_uart_init(void) { } +void board_init_sdmmc_pwr_en(void) +{ + struct rk3328_grf_regs * const grf = (void *)GRF_BASE; + struct rockchip_gpio_regs * const gpio0 = (void *)GPIO0_BASE; + + printf("board_init_sdmmc_pwr_en\n"); + + rk_clrsetreg(&grf->com_iomux, + IOMUX_SEL_SDMMC_MASK, + IOMUX_SEL_SDMMC_M1 << IOMUX_SEL_SDMMC_SHIFT); + + rk_clrsetreg(&grf->gpio0d_iomux, + GPIO0D6_SEL_MASK, + GPIO0D6_GPIO << GPIO0D6_SEL_SHIFT); + + rk_clrsetreg(&grf->gpio1a_iomux, + GPIO1A0_SEL_MASK, + GPIO1A0_CARD_DATA_CLK_CMD_DETN + << GPIO1A0_SEL_SHIFT); + + // set GPIO0_D6 to GPIO_ACTIVE_LOW + // set GPIO0_D6 to OUTPUT + clrbits_le32(&gpio0->swport_dr, 1 << RK_PD6); + setbits_le32(&gpio0->swport_ddr, 1 << RK_PD6); +} + void board_init_f(ulong dummy) { struct udevice *dev; @@ -35,6 +68,7 @@ void board_init_f(ulong dummy) } preloader_console_init(); + board_init_sdmmc_pwr_en(); ret = uclass_get_device(UCLASS_RAM, 0, &dev); if (ret) { @@ -50,7 +84,26 @@ u32 spl_boot_mode(const u32 boot_device) u32 spl_boot_device(void) { - return BOOT_DEVICE_MMC1; + u32 bootdevice_brom_id = readl(RK3328_BROM_BOOTSOURCE_ID_ADDR); + switch (bootdevice_brom_id) { + case BROM_BOOTSOURCE_EMMC: + printf("booted from eMMC\n"); + return BOOT_DEVICE_MMC1; + + case BROM_BOOTSOURCE_SD: + printf("booted from SD\n"); + return BOOT_DEVICE_MMC2; + + case BROM_BOOTSOURCE_SPINOR: + printf("booted from SPI flash\n"); + return BOOT_DEVICE_SPI; + + case BROM_BOOTSOURCE_USB: + printf("booted from USB\n"); + return BOOT_DEVICE_MMC1; + } + + return BOOT_DEVICE_BOOTROM; } #ifdef CONFIG_SPL_LOAD_FIT diff --git a/arch/arm/mach-rockchip/rk3328-board-tpl.c b/arch/arm/mach-rockchip/rk3328-board-tpl.c index 0b8a0e16e42..942223f505a 100644 --- a/arch/arm/mach-rockchip/rk3328-board-tpl.c +++ b/arch/arm/mach-rockchip/rk3328-board-tpl.c @@ -86,6 +86,7 @@ u32 spl_boot_device(void) return BOOT_DEVICE_BOOTROM; } +#define FW_DDR_CON_REG 0xff7c0040 void board_init_f(ulong dummy) { @@ -111,4 +112,7 @@ void board_init_f(ulong dummy) printf("DRAM init failed: %d\n", ret); return; } + /* Disable the ddr secure region setting to make it non-secure */ + rk_setreg(FW_DDR_CON_REG, 0x200); + } diff --git a/arch/arm/mach-rockchip/rk3328/Kconfig b/arch/arm/mach-rockchip/rk3328/Kconfig index 43afba24304..cefd6f5dba0 100644 --- a/arch/arm/mach-rockchip/rk3328/Kconfig +++ b/arch/arm/mach-rockchip/rk3328/Kconfig @@ -5,11 +5,23 @@ choice config TARGET_EVB_RK3328 bool "RK3328 evaluation board" + select BOARD_LATE_INIT help RK3328evb is a evaluation board for Rockchip rk3328, with full function and phisical connectors support like usb2.0 host ports, LVDS, JTAG, MAC, SDcard, HDMI, USB-2-serial... +config TARGET_ROCK64_RK3328 + bool "ROCK64 RK3328" + select BOARD_LATE_INIT + help + ROCK64 is a credit card size 4K60P HDR Media Board Computer + powered by Rockchip RK3328 Quad-Core ARM Cortex A53 64-Bit Processor + and support up to 4GB 1600MHz LPDDR3 memory. + It provides eMMC module socket, MicroSD Card slot, Pi-2 Bus, Pi-P5+ Bus, + USB 3.0 and many others peripheral devices interface for makers + to integrate with sensors and devices + endchoice config SYS_SOC @@ -19,5 +31,6 @@ config SYS_MALLOC_F_LEN default 0x0800 source "board/rockchip/evb_rk3328/Kconfig" +source "board/rockchip/rock64_rk3328/Kconfig" endif diff --git a/arch/arm/mach-rockchip/rk3328/rk3328.c b/arch/arm/mach-rockchip/rk3328/rk3328.c index df5b190a1ec..f1db5bfc78e 100644 --- a/arch/arm/mach-rockchip/rk3328/rk3328.c +++ b/arch/arm/mach-rockchip/rk3328/rk3328.c @@ -1,18 +1,28 @@ /* - * Copyright (c) 2016 Rockchip Electronics Co., Ltd + * (C) Copyright 2016 Rockchip Electronics Co., Ltd * * SPDX-License-Identifier: GPL-2.0+ */ #include #include +#include +#include +#include +#include #include #include +#include +#include +#include +#include +#include +#include DECLARE_GLOBAL_DATA_PTR; -#define GRF_SOC_CON4 0xff100410 -#define CRU_MISC_CON 0xff440084 +#define RK3328_CPUID_OFF 0x7 +#define RK3328_CPUID_LEN 0x10 static struct mm_region rk3328_mem_map[] = { { @@ -51,13 +61,218 @@ int arch_cpu_init(void) { /* We do some SoC one time setting here. */ - /* Enable force to jtag, jtag_tclk/tms iomuxed with sdmmc0_d2/d3 */ - rk_setreg(GRF_SOC_CON4, 1 << 12); + return 0; +} + +static void boot_mode_set(int boot_mode) +{ + struct rk3328_grf_regs *grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); + writel(boot_mode, &grf->os_reg[0]); +} + +#if defined(CONFIG_USB_FUNCTION_FASTBOOT) +int fb_set_reboot_flag(void) +{ + printf("Setting reboot to fastboot flag ...\n"); + boot_mode_set(BOOT_FASTBOOT); + return 0; +} +#endif + +__weak int rk_board_late_init(void) +{ + return 0; +} + +int board_late_init(void) +{ + setup_boot_mode(); + return rk_board_late_init(); +} + +int board_init(void) +{ + int ret; +#define GRF_BASE 0xff100000 + struct rk3328_grf_regs * const grf = (void *)GRF_BASE; - /* HDMI phy clock source select HDMIPHY clock out */ - rk_clrreg(CRU_MISC_CON, 1 << 13); + /* uart2 select m1, sdcard select m1*/ + rk_clrsetreg(&grf->com_iomux, + IOMUX_SEL_UART2_MASK | IOMUX_SEL_SDMMC_MASK, + IOMUX_SEL_UART2_M1 << IOMUX_SEL_UART2_SHIFT | + IOMUX_SEL_SDMMC_M1 << IOMUX_SEL_SDMMC_SHIFT); - /* TODO: ECO version */ + ret = regulators_enable_boot_on(false); + if (ret) + debug("%s: Cannot enable boot on regulator\n", __func__); + return ret; +} + +#if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG) +#include +#include + +static struct dwc2_plat_otg_data rk3328_otg_data = { + .rx_fifo_sz = 512, + .np_tx_fifo_sz = 16, + .tx_fifo_sz = 128, +}; + +int board_usb_init(int index, enum usb_init_type init) +{ + int node; + const char *mode; + bool matched = false; + const void *blob = gd->fdt_blob; + + /* find the usb_otg node */ + node = fdt_node_offset_by_compatible(blob, -1, + "rockchip,rk3328-usb"); + + while (node > 0) { + mode = fdt_getprop(blob, node, "dr_mode", NULL); + if (mode && strcmp(mode, "otg") == 0) { + matched = true; + break; + } + + node = fdt_node_offset_by_compatible(blob, node, + "rockchip,rk3328-usb"); + } + if (!matched) { + debug("Not found usb_otg device\n"); + return -ENODEV; + } + + rk3328_otg_data.regs_otg = fdtdec_get_addr(blob, node, "reg"); + + return dwc2_udc_probe(&rk3328_otg_data); +} + +int board_usb_cleanup(int index, enum usb_init_type init) +{ return 0; } +#endif + +static void setup_macaddr(void) +{ +#if CONFIG_IS_ENABLED(CMD_NET) + int ret; + const char *cpuid = env_get("cpuid#"); + u8 hash[SHA256_SUM_LEN]; + int size = sizeof(hash); + u8 mac_addr[6]; + + /* Only generate a MAC address, if none is set in the environment */ + if (env_get("ethaddr")) + return; + + if (!cpuid) { + debug("%s: could not retrieve 'cpuid#'\n", __func__); + return; + } + + ret = hash_block("sha256", (void *)cpuid, strlen(cpuid), hash, &size); + if (ret) { + debug("%s: failed to calculate SHA256\n", __func__); + return; + } + + /* Copy 6 bytes of the hash to base the MAC address on */ + memcpy(mac_addr, hash, 6); + + /* Make this a valid MAC address and set it */ + mac_addr[0] &= 0xfe; /* clear multicast bit */ + mac_addr[0] |= 0x02; /* set local assignment bit (IEEE802) */ + eth_env_set_enetaddr("ethaddr", mac_addr); + + /* Make a valid MAC address for eth1 */ + mac_addr[5] += 0x20; + mac_addr[5] &= 0xff; + eth_env_set_enetaddr("eth1addr", mac_addr); +#endif + + return; +} + +static void setup_serial(void) +{ +#if CONFIG_IS_ENABLED(ROCKCHIP_EFUSE) + struct udevice *dev; + int ret, i; + u8 cpuid[RK3328_CPUID_LEN]; + u8 low[RK3328_CPUID_LEN/2], high[RK3328_CPUID_LEN/2]; + char cpuid_str[RK3328_CPUID_LEN * 2 + 1]; + u64 serialno; + char serialno_str[16]; + + /* retrieve the device */ + ret = uclass_get_device_by_driver(UCLASS_MISC, + DM_GET_DRIVER(rockchip_efuse), &dev); + if (ret) { + printf("%s: could not find efuse device\n", __func__); + return; + } + + /* read the cpu_id range from the efuses */ + ret = misc_read(dev, RK3328_CPUID_OFF, &cpuid, sizeof(cpuid)); + if (ret) { + printf("%s: reading cpuid from the efuses failed: %d\n", + __func__, ret); + return; + } + + memset(cpuid_str, 0, sizeof(cpuid_str)); + for (i = 0; i < 16; i++) + sprintf(&cpuid_str[i * 2], "%02x", cpuid[i]); + + debug("cpuid: %s\n", cpuid_str); + + /* + * Mix the cpuid bytes using the same rules as in + * ${linux}/drivers/soc/rockchip/rockchip-cpuinfo.c + */ + for (i = 0; i < 8; i++) { + low[i] = cpuid[1 + (i << 1)]; + high[i] = cpuid[i << 1]; + } + + serialno = crc32_no_comp(0, low, 8); + serialno |= (u64)crc32_no_comp(serialno, high, 8) << 32; + snprintf(serialno_str, sizeof(serialno_str), "%llx", serialno); + + printf("cpuid=%s\n", cpuid_str); + printf("serial=%s\n", serialno_str); + env_set("cpuid#", cpuid_str); + env_set("serial#", serialno_str); +#endif + + return; +} + +int misc_init_r(void) +{ + printf("misc_init_r\n"); + setup_serial(); + setup_macaddr(); + + return 0; +} + +#ifdef CONFIG_SERIAL_TAG +void get_board_serial(struct tag_serialnr *serialnr) +{ + char *serial_string; + u64 serial = 0; + + serial_string = env_get("serial#"); + + if (serial_string) + serial = simple_strtoull(serial_string, NULL, 16); + + serialnr->high = (u32)(serial >> 32); + serialnr->low = (u32)(serial & 0xffffffff); +} +#endif diff --git a/arch/arm/mach-rockchip/rk3328/u-boot-tpl.lds b/arch/arm/mach-rockchip/rk3328/u-boot-tpl.lds new file mode 100644 index 00000000000..3fd50fd86cf --- /dev/null +++ b/arch/arm/mach-rockchip/rk3328/u-boot-tpl.lds @@ -0,0 +1,91 @@ +/* + * (C) Copyright 2013 + * David Feng + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, + * + * (C) Copyright 2010 + * Texas Instruments, + * Aneesh V + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64") +OUTPUT_ARCH(aarch64) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + + .text : { + . = ALIGN(8); + *(.__image_copy_start) + CPUDIR/start.o (.text*) + *(.text*) + } + + .rodata : { + . = ALIGN(8); + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) + } + + .data : { + . = ALIGN(8); + *(.data*) + } + + .u_boot_list : { + . = ALIGN(8); + KEEP(*(SORT(.u_boot_list*))); + } + + .image_copy_end : { + . = ALIGN(8); + *(.__image_copy_end) + } + + .end : { + . = ALIGN(8); + *(.__end) + } + + _image_binary_end = .; + + .bss_start (NOLOAD) : { + . = ALIGN(8); + KEEP(*(.__bss_start)); + } + + .bss (NOLOAD) : { + *(.bss*) + . = ALIGN(8); + } + + .bss_end (NOLOAD) : { + KEEP(*(.__bss_end)); + } + + /DISCARD/ : { *(.dynsym) } + /DISCARD/ : { *(.dynstr*) } + /DISCARD/ : { *(.dynamic*) } + /DISCARD/ : { *(.plt*) } + /DISCARD/ : { *(.interp*) } + /DISCARD/ : { *(.gnu*) } +} + +#if defined(CONFIG_TPL_MAX_SIZE) +ASSERT(__image_copy_end - __image_copy_start < (CONFIG_TPL_MAX_SIZE), \ + "TPL image too big"); +#endif + +#if defined(CONFIG_TPL_BSS_MAX_SIZE) +ASSERT(__bss_end - __bss_start < (CONFIG_TPL_BSS_MAX_SIZE), \ + "TPL image BSS too big"); +#endif + +#if defined(CONFIG_TPL_MAX_FOOTPRINT) +ASSERT(__bss_end - _start < (CONFIG_TPL_MAX_FOOTPRINT), \ + "TPL image plus BSS too big"); +#endif diff --git a/arch/arm/mach-rockchip/rk3399-board-spl.c b/arch/arm/mach-rockchip/rk3399-board-spl.c index cae09da0c6a..b00bbdc9154 100644 --- a/arch/arm/mach-rockchip/rk3399-board-spl.c +++ b/arch/arm/mach-rockchip/rk3399-board-spl.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -18,12 +19,33 @@ #include #include #include +#include +#include DECLARE_GLOBAL_DATA_PTR; u32 spl_boot_device(void) { - return BOOT_DEVICE_MMC1; + u32 bootdevice_brom_id = readl(RK3399_BROM_BOOTSOURCE_ID_ADDR); + switch (bootdevice_brom_id) { + case BROM_BOOTSOURCE_EMMC: + printf("booted from eMMC\n"); + return BOOT_DEVICE_MMC1; + + case BROM_BOOTSOURCE_SD: + printf("booted from SD\n"); + return BOOT_DEVICE_MMC2; + + case BROM_BOOTSOURCE_SPINOR: + printf("booted from SPI flash\n"); + return BOOT_DEVICE_SPI; + + case BROM_BOOTSOURCE_USB: + printf("booted from USB\n"); + return BOOT_DEVICE_MMC1; + } + + return BOOT_DEVICE_BOOTROM; } u32 spl_boot_mode(const u32 boot_device) @@ -51,6 +73,19 @@ void secure_timer_init(void) writel(TIMER_EN | TIMER_FMODE, TIMER_CHN10_BASE + TIMER_CONTROL_REG); } +void board_init_power_standby_leds(void) +{ +#define GPIO0_BASE 0xff720000 + + struct rockchip_gpio_regs * const gpio0 = (void *)GPIO0_BASE; + + // set GPIO0_A2/B3 to GPIO_ACTIVE_HIGH + // set GPIO0_A2/B3 to OUTPUT + int mask = (1UL << RK_PA2) | (1UL << RK_PB3); + setbits_le32(&gpio0->swport_dr, mask); + setbits_le32(&gpio0->swport_ddr, mask); +} + void board_debug_uart_init(void) { #include @@ -100,7 +135,7 @@ void board_init_f(ulong dummy) * printascii("string"); */ debug_uart_init(); - printascii("U-Boot SPL board init"); + printascii("U-Boot SPL board init\n"); #endif rk_clrsetreg(SGRF_DDR_RGN_CON16, 0x1FF, 0x200); @@ -116,6 +151,9 @@ void board_init_f(ulong dummy) hang(); } + preloader_console_init(); + board_init_power_standby_leds(); + /* * Disable DDR and SRAM security regions. * diff --git a/arch/arm/mach-rockchip/rk3399/Kconfig b/arch/arm/mach-rockchip/rk3399/Kconfig index c4a6d46649f..a3b13b3eff7 100644 --- a/arch/arm/mach-rockchip/rk3399/Kconfig +++ b/arch/arm/mach-rockchip/rk3399/Kconfig @@ -29,6 +29,14 @@ config TARGET_PUMA_RK3399 * HDMI, eDP, MIPI-DSI, MIPI-DSI/CSI and MIPI-CSI * SPI, I2C, I2S, UART, GPIO, ... +config TARGET_PINEBOOK_PRO_RK3399 + bool "Pinebook Pro" + select BOARD_LATE_INIT + +config TARGET_ROCKPRO64_RK3399 + bool "RockPro64" + select BOARD_LATE_INIT + endchoice config SYS_SOC @@ -38,6 +46,8 @@ config SYS_MALLOC_F_LEN default 0x0800 source "board/rockchip/evb_rk3399/Kconfig" +source "board/rockchip/rockpro64_rk3399/Kconfig" +source "board/rockchip/pinebook_pro_rk3399/Kconfig" source "board/theobroma-systems/puma_rk3399/Kconfig" endif diff --git a/board/rockchip/evb_rk3328/evb-rk3328.c b/board/rockchip/evb_rk3328/evb-rk3328.c index d6fc57cd8ec..38463a91690 100644 --- a/board/rockchip/evb_rk3328/evb-rk3328.c +++ b/board/rockchip/evb_rk3328/evb-rk3328.c @@ -5,78 +5,8 @@ */ #include -#include -#include -#include -#include #include #include #include DECLARE_GLOBAL_DATA_PTR; - -int board_init(void) -{ - int ret; -#define GRF_BASE 0xff100000 - struct rk3328_grf_regs * const grf = (void *)GRF_BASE; - - /* uart2 select m1, sdcard select m1*/ - rk_clrsetreg(&grf->com_iomux, - IOMUX_SEL_UART2_MASK | IOMUX_SEL_SDMMC_MASK, - IOMUX_SEL_UART2_M1 << IOMUX_SEL_UART2_SHIFT | - IOMUX_SEL_SDMMC_M1 << IOMUX_SEL_SDMMC_SHIFT); - - ret = regulators_enable_boot_on(false); - if (ret) - debug("%s: Cannot enable boot on regulator\n", __func__); - - return ret; -} - -#if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG) -#include -#include - -static struct dwc2_plat_otg_data rk3328_otg_data = { - .rx_fifo_sz = 512, - .np_tx_fifo_sz = 16, - .tx_fifo_sz = 128, -}; - -int board_usb_init(int index, enum usb_init_type init) -{ - int node; - const char *mode; - bool matched = false; - const void *blob = gd->fdt_blob; - - /* find the usb_otg node */ - node = fdt_node_offset_by_compatible(blob, -1, - "rockchip,rk3328-usb"); - - while (node > 0) { - mode = fdt_getprop(blob, node, "dr_mode", NULL); - if (mode && strcmp(mode, "otg") == 0) { - matched = true; - break; - } - - node = fdt_node_offset_by_compatible(blob, node, - "rockchip,rk3328-usb"); - } - if (!matched) { - debug("Not found usb_otg device\n"); - return -ENODEV; - } - - rk3328_otg_data.regs_otg = fdtdec_get_addr(blob, node, "reg"); - - return dwc2_udc_probe(&rk3328_otg_data); -} - -int board_usb_cleanup(int index, enum usb_init_type init) -{ - return 0; -} -#endif diff --git a/board/rockchip/evb_rk3328/mk_fit_atf.sh b/board/rockchip/evb_rk3328/mk_fit_atf.sh index 192c303af0c..e5de13f1776 100755 --- a/board/rockchip/evb_rk3328/mk_fit_atf.sh +++ b/board/rockchip/evb_rk3328/mk_fit_atf.sh @@ -5,11 +5,9 @@ # # usage: $0 [ [&2 - BL31=/dev/null +if [ -z "$BL31" ] || [ ! -e "$BL31" ]; then + echo "ERROR: BL31 file $BL31 NOT found, resulting binary is non-functional" >&2 + exit 1 fi cat << __HEADER_EOF diff --git a/board/rockchip/evb_rk3399/mk_fit_atf.sh b/board/rockchip/evb_rk3399/mk_fit_atf.sh index 146550aab33..bb43ba73a54 100755 --- a/board/rockchip/evb_rk3399/mk_fit_atf.sh +++ b/board/rockchip/evb_rk3399/mk_fit_atf.sh @@ -5,11 +5,9 @@ # # usage: $0 [ [&2 - BL31=/dev/null +if [ -z "$BL31" ] || [ ! -e "$BL31" ]; then + echo "ERROR: BL31 file $BL31 NOT found, resulting binary is non-functional" >&2 + exit 1 fi #tools/mkimage -n rk3399 -T rksd -d spl/u-boot-spl.bin idbspl.img diff --git a/board/rockchip/pinebook_pro_rk3399/Kconfig b/board/rockchip/pinebook_pro_rk3399/Kconfig new file mode 100644 index 00000000000..b179186596f --- /dev/null +++ b/board/rockchip/pinebook_pro_rk3399/Kconfig @@ -0,0 +1,15 @@ +if TARGET_PINEBOOK_PRO_RK3399 + +config SYS_BOARD + default "pinebook_pro_rk3399" + +config SYS_VENDOR + default "rockchip" + +config SYS_CONFIG_NAME + default "pinebook_pro_rk3399" + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + +endif diff --git a/board/rockchip/pinebook_pro_rk3399/Makefile b/board/rockchip/pinebook_pro_rk3399/Makefile new file mode 100644 index 00000000000..2f692a12a67 --- /dev/null +++ b/board/rockchip/pinebook_pro_rk3399/Makefile @@ -0,0 +1 @@ +obj-y += pinebook-pro-rk3399.o diff --git a/board/rockchip/pinebook_pro_rk3399/mk_fit_atf.sh b/board/rockchip/pinebook_pro_rk3399/mk_fit_atf.sh new file mode 100755 index 00000000000..bb43ba73a54 --- /dev/null +++ b/board/rockchip/pinebook_pro_rk3399/mk_fit_atf.sh @@ -0,0 +1,108 @@ +#!/bin/sh +# +# script to generate FIT image source for rk3399 boards with +# ARM Trusted Firmware and multiple device trees (given on the command line) +# +# usage: $0 [ [&2 + exit 1 +fi + +#tools/mkimage -n rk3399 -T rksd -d spl/u-boot-spl.bin idbspl.img + +cat << __HEADER_EOF +/dts-v1/; + +/ { + description = "Configuration to load ATF before U-Boot"; + #address-cells = <1>; + + images { + uboot@1 { + description = "U-Boot (64-bit)"; + data = /incbin/("u-boot-nodtb.bin"); + type = "standalone"; + arch = "arm64"; + compression = "none"; + load = <0x00200000>; + }; +__HEADER_EOF + +atf_cnt=1 + +for l in `readelf -l $BL31 | grep -A1 LOAD | gawk --non-decimal-data \ + '{if (NR % 2) {printf "%d:0x%x:", $2,$4} else {printf "%d\n", $1}}'` +do + offset=${l%%:*} + ll=${l#*:} + phy_offset=${ll%:*} + filesz=${ll##*:} + + #echo "$offset/$phy_offset/$filesz" + + of=rk3399bl31_${phy_offset}.bin + dd if=$BL31 of=$of bs=1 skip=$offset count=$filesz + + out_string="${out_string}:${phy_offset}" + + cat << __ATF1_EOF + atf@$atf_cnt { + description = "ARM Trusted Firmware"; + data = /incbin/("$of"); + type = "firmware"; + arch = "arm64"; + compression = "none"; + load = <$phy_offset>; +__ATF1_EOF + if [ "$atf_cnt" -eq 1 ]; then + cat << __ATF2_EOF + entry = <$phy_offset>; +__ATF2_EOF + fi + cat << __ATF3_EOF + }; +__ATF3_EOF + atf_cnt=$((atf_cnt + 1)) +done + +cnt=1 +for dtname in $* +do + cat << __FDT_IMAGE_EOF + fdt@$cnt { + description = "$(basename $dtname .dtb)"; + data = /incbin/("$dtname"); + type = "flat_dt"; + compression = "none"; + }; +__FDT_IMAGE_EOF + cnt=$((cnt+1)) +done + +cat << __CONF_HEADER_EOF + }; + configurations { + default = "config@1"; + +__CONF_HEADER_EOF + +cnt=1 +for dtname in $* +do + cat << __CONF_SECTION_EOF + config@$cnt { + description = "$(basename $dtname .dtb)"; + firmware = "uboot@1"; + loadables = "atf@1","atf@2","atf@3"; + fdt = "fdt@1"; + }; +__CONF_SECTION_EOF + cnt=$((cnt+1)) +done + +cat << __ITS_EOF + }; +}; +__ITS_EOF diff --git a/board/rockchip/pinebook_pro_rk3399/pinebook-pro-rk3399.c b/board/rockchip/pinebook_pro_rk3399/pinebook-pro-rk3399.c new file mode 100644 index 00000000000..246959d6eac --- /dev/null +++ b/board/rockchip/pinebook_pro_rk3399/pinebook-pro-rk3399.c @@ -0,0 +1,203 @@ +/* + * (C) Copyright 2016 Rockchip Electronics Co., Ltd + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +#define RK3399_CPUID_OFF 0x7 +#define RK3399_CPUID_LEN 0x10 + +static int fix_lcd_backling_pull_mode(void) +{ +#include + +#define PMU_GRF_BASE 0xff320000 + + // set pull of GPIO1_A0 + struct rk3399_pmugrf_regs * const pmugrf = (void *)PMU_GRF_BASE; + rk_clrsetreg(&pmugrf->gpio1_p[0], 3 << (2 * 0), 0 << (2 * 0)); + return 0; +} + +int board_init(void) +{ + struct udevice *pinctrl, *regulator; + int ret; + + /* + * The PWM does not have decicated interrupt number in dts and can + * not get periph_id by pinctrl framework, so let's init them here. + * The PWM2 and PWM3 are for pwm regulators. + */ + ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl); + if (ret) { + debug("%s: Cannot find pinctrl device\n", __func__); + goto out; + } + + ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_PWM2); + if (ret) { + debug("%s PWM2 pinctrl init fail!\n", __func__); + goto out; + } + + ret = regulators_enable_boot_on(true); + if (ret) { + debug("%s: Cannot enable boot on regulator\n", __func__); + } + + fix_lcd_backling_pull_mode(); + +out: + return 0; +} + +static void setup_macaddr(void) +{ +#if CONFIG_IS_ENABLED(CMD_NET) + int ret; + const char *cpuid = env_get("cpuid#"); + u8 hash[SHA256_SUM_LEN]; + int size = sizeof(hash); + u8 mac_addr[6]; + + /* Only generate a MAC address, if none is set in the environment */ + if (env_get("ethaddr")) + return; + + if (!cpuid) { + debug("%s: could not retrieve 'cpuid#'\n", __func__); + return; + } + + ret = hash_block("sha256", (void *)cpuid, strlen(cpuid), hash, &size); + if (ret) { + debug("%s: failed to calculate SHA256\n", __func__); + return; + } + + /* Copy 6 bytes of the hash to base the MAC address on */ + memcpy(mac_addr, hash, 6); + + /* Make this a valid MAC address and set it */ + mac_addr[0] &= 0xfe; /* clear multicast bit */ + mac_addr[0] |= 0x02; /* set local assignment bit (IEEE802) */ + eth_env_set_enetaddr("ethaddr", mac_addr); +#endif + + return; +} + +static void setup_serial(void) +{ +#if CONFIG_IS_ENABLED(ROCKCHIP_EFUSE) + struct udevice *dev; + int ret, i; + u8 cpuid[RK3399_CPUID_LEN]; + u8 low[RK3399_CPUID_LEN/2], high[RK3399_CPUID_LEN/2]; + char cpuid_str[RK3399_CPUID_LEN * 2 + 1]; + u64 serialno; + char serialno_str[16]; + + /* retrieve the device */ + ret = uclass_get_device_by_driver(UCLASS_MISC, + DM_GET_DRIVER(rockchip_efuse), &dev); + if (ret) { + debug("%s: could not find efuse device\n", __func__); + return; + } + + /* read the cpu_id range from the efuses */ + ret = misc_read(dev, RK3399_CPUID_OFF, &cpuid, sizeof(cpuid)); + if (ret) { + debug("%s: reading cpuid from the efuses failed\n", + __func__); + return; + } + + memset(cpuid_str, 0, sizeof(cpuid_str)); + for (i = 0; i < 16; i++) + sprintf(&cpuid_str[i * 2], "%02x", cpuid[i]); + + debug("cpuid: %s\n", cpuid_str); + + /* + * Mix the cpuid bytes using the same rules as in + * ${linux}/drivers/soc/rockchip/rockchip-cpuinfo.c + */ + for (i = 0; i < 8; i++) { + low[i] = cpuid[1 + (i << 1)]; + high[i] = cpuid[i << 1]; + } + + serialno = crc32_no_comp(0, low, 8); + serialno |= (u64)crc32_no_comp(serialno, high, 8) << 32; + snprintf(serialno_str, sizeof(serialno_str), "%llx", serialno); + + env_set("cpuid#", cpuid_str); + env_set("serial#", serialno_str); +#endif + + return; +} + +int misc_init_r(void) +{ + setup_serial(); + setup_macaddr(); + + return 0; +} + +#ifdef CONFIG_SERIAL_TAG +void get_board_serial(struct tag_serialnr *serialnr) +{ + char *serial_string; + u64 serial = 0; + + serial_string = env_get("serial#"); + + if (serial_string) + serial = simple_strtoull(serial_string, NULL, 16); + + serialnr->high = (u32)(serial >> 32); + serialnr->low = (u32)(serial & 0xffffffff); +} +#endif + +#ifdef CONFIG_USB_DWC3 +static struct dwc3_device dwc3_device_data = { + .maximum_speed = USB_SPEED_HIGH, + .base = 0xfe800000, + .dr_mode = USB_DR_MODE_PERIPHERAL, + .index = 0, + .dis_u2_susphy_quirk = 1, +}; + +int usb_gadget_handle_interrupts(void) +{ + dwc3_uboot_handle_interrupt(0); + return 0; +} + +int board_usb_init(int index, enum usb_init_type init) +{ + return dwc3_uboot_init(&dwc3_device_data); +} +#endif diff --git a/board/rockchip/rock64_rk3328/Kconfig b/board/rockchip/rock64_rk3328/Kconfig new file mode 100644 index 00000000000..f8a8f12d681 --- /dev/null +++ b/board/rockchip/rock64_rk3328/Kconfig @@ -0,0 +1,15 @@ +if TARGET_ROCK64_RK3328 + +config SYS_BOARD + default "rock64_rk3328" + +config SYS_VENDOR + default "rockchip" + +config SYS_CONFIG_NAME + default "rock64_rk3328" + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + +endif diff --git a/board/rockchip/rock64_rk3328/Makefile b/board/rockchip/rock64_rk3328/Makefile new file mode 100644 index 00000000000..3d3aa95ede6 --- /dev/null +++ b/board/rockchip/rock64_rk3328/Makefile @@ -0,0 +1,7 @@ +# +# (C) Copyright 2016 Rockchip Electronics Co., Ltd +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += rock64-rk3328.o diff --git a/board/rockchip/rock64_rk3328/rock64-rk3328.c b/board/rockchip/rock64_rk3328/rock64-rk3328.c new file mode 100644 index 00000000000..b0c97f7f4a4 --- /dev/null +++ b/board/rockchip/rock64_rk3328/rock64-rk3328.c @@ -0,0 +1,15 @@ +/* + * (C) Copyright 2017 PINE64 + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +int rk_board_late_init(void) +{ + return 0; +} diff --git a/board/rockchip/rockpro64_rk3399/Kconfig b/board/rockchip/rockpro64_rk3399/Kconfig new file mode 100644 index 00000000000..08d7e8dadb3 --- /dev/null +++ b/board/rockchip/rockpro64_rk3399/Kconfig @@ -0,0 +1,15 @@ +if TARGET_ROCKPRO64_RK3399 + +config SYS_BOARD + default "rockpro64_rk3399" + +config SYS_VENDOR + default "rockchip" + +config SYS_CONFIG_NAME + default "rockpro64_rk3399" + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + +endif diff --git a/board/rockchip/rockpro64_rk3399/Makefile b/board/rockchip/rockpro64_rk3399/Makefile new file mode 100644 index 00000000000..58b3ce124bc --- /dev/null +++ b/board/rockchip/rockpro64_rk3399/Makefile @@ -0,0 +1 @@ +obj-y += rockpro64-rk3399.o diff --git a/board/rockchip/rockpro64_rk3399/mk_fit_atf.sh b/board/rockchip/rockpro64_rk3399/mk_fit_atf.sh new file mode 100755 index 00000000000..bb43ba73a54 --- /dev/null +++ b/board/rockchip/rockpro64_rk3399/mk_fit_atf.sh @@ -0,0 +1,108 @@ +#!/bin/sh +# +# script to generate FIT image source for rk3399 boards with +# ARM Trusted Firmware and multiple device trees (given on the command line) +# +# usage: $0 [ [&2 + exit 1 +fi + +#tools/mkimage -n rk3399 -T rksd -d spl/u-boot-spl.bin idbspl.img + +cat << __HEADER_EOF +/dts-v1/; + +/ { + description = "Configuration to load ATF before U-Boot"; + #address-cells = <1>; + + images { + uboot@1 { + description = "U-Boot (64-bit)"; + data = /incbin/("u-boot-nodtb.bin"); + type = "standalone"; + arch = "arm64"; + compression = "none"; + load = <0x00200000>; + }; +__HEADER_EOF + +atf_cnt=1 + +for l in `readelf -l $BL31 | grep -A1 LOAD | gawk --non-decimal-data \ + '{if (NR % 2) {printf "%d:0x%x:", $2,$4} else {printf "%d\n", $1}}'` +do + offset=${l%%:*} + ll=${l#*:} + phy_offset=${ll%:*} + filesz=${ll##*:} + + #echo "$offset/$phy_offset/$filesz" + + of=rk3399bl31_${phy_offset}.bin + dd if=$BL31 of=$of bs=1 skip=$offset count=$filesz + + out_string="${out_string}:${phy_offset}" + + cat << __ATF1_EOF + atf@$atf_cnt { + description = "ARM Trusted Firmware"; + data = /incbin/("$of"); + type = "firmware"; + arch = "arm64"; + compression = "none"; + load = <$phy_offset>; +__ATF1_EOF + if [ "$atf_cnt" -eq 1 ]; then + cat << __ATF2_EOF + entry = <$phy_offset>; +__ATF2_EOF + fi + cat << __ATF3_EOF + }; +__ATF3_EOF + atf_cnt=$((atf_cnt + 1)) +done + +cnt=1 +for dtname in $* +do + cat << __FDT_IMAGE_EOF + fdt@$cnt { + description = "$(basename $dtname .dtb)"; + data = /incbin/("$dtname"); + type = "flat_dt"; + compression = "none"; + }; +__FDT_IMAGE_EOF + cnt=$((cnt+1)) +done + +cat << __CONF_HEADER_EOF + }; + configurations { + default = "config@1"; + +__CONF_HEADER_EOF + +cnt=1 +for dtname in $* +do + cat << __CONF_SECTION_EOF + config@$cnt { + description = "$(basename $dtname .dtb)"; + firmware = "uboot@1"; + loadables = "atf@1","atf@2","atf@3"; + fdt = "fdt@1"; + }; +__CONF_SECTION_EOF + cnt=$((cnt+1)) +done + +cat << __ITS_EOF + }; +}; +__ITS_EOF diff --git a/board/rockchip/rockpro64_rk3399/rockpro64-rk3399.c b/board/rockchip/rockpro64_rk3399/rockpro64-rk3399.c new file mode 100644 index 00000000000..fa9d70da4fd --- /dev/null +++ b/board/rockchip/rockpro64_rk3399/rockpro64-rk3399.c @@ -0,0 +1,203 @@ +/* + * (C) Copyright 2016 Rockchip Electronics Co., Ltd + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +#define RK3399_CPUID_OFF 0x7 +#define RK3399_CPUID_LEN 0x10 + +static int fix_usb2_vbus_pull_mode(void) +{ +#include + +#define GRF_BASE 0xff770000 + + // set pull of GPIO4_D2 + struct rk3399_grf_regs * const grf = (void *)GRF_BASE; + rk_clrsetreg(&grf->gpio4_p[3], 3 << 4, 0 << 4); + return 0; +} + +int board_init(void) +{ + struct udevice *pinctrl, *regulator; + int ret; + + /* + * The PWM does not have decicated interrupt number in dts and can + * not get periph_id by pinctrl framework, so let's init them here. + * The PWM2 and PWM3 are for pwm regulators. + */ + ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl); + if (ret) { + debug("%s: Cannot find pinctrl device\n", __func__); + goto out; + } + + ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_PWM2); + if (ret) { + debug("%s PWM2 pinctrl init fail!\n", __func__); + goto out; + } + + ret = regulators_enable_boot_on(true); + if (ret) { + debug("%s: Cannot enable boot on regulator\n", __func__); + } + + fix_usb2_vbus_pull_mode(); + +out: + return 0; +} + +static void setup_macaddr(void) +{ +#if CONFIG_IS_ENABLED(CMD_NET) + int ret; + const char *cpuid = env_get("cpuid#"); + u8 hash[SHA256_SUM_LEN]; + int size = sizeof(hash); + u8 mac_addr[6]; + + /* Only generate a MAC address, if none is set in the environment */ + if (env_get("ethaddr")) + return; + + if (!cpuid) { + debug("%s: could not retrieve 'cpuid#'\n", __func__); + return; + } + + ret = hash_block("sha256", (void *)cpuid, strlen(cpuid), hash, &size); + if (ret) { + debug("%s: failed to calculate SHA256\n", __func__); + return; + } + + /* Copy 6 bytes of the hash to base the MAC address on */ + memcpy(mac_addr, hash, 6); + + /* Make this a valid MAC address and set it */ + mac_addr[0] &= 0xfe; /* clear multicast bit */ + mac_addr[0] |= 0x02; /* set local assignment bit (IEEE802) */ + eth_env_set_enetaddr("ethaddr", mac_addr); +#endif + + return; +} + +static void setup_serial(void) +{ +#if CONFIG_IS_ENABLED(ROCKCHIP_EFUSE) + struct udevice *dev; + int ret, i; + u8 cpuid[RK3399_CPUID_LEN]; + u8 low[RK3399_CPUID_LEN/2], high[RK3399_CPUID_LEN/2]; + char cpuid_str[RK3399_CPUID_LEN * 2 + 1]; + u64 serialno; + char serialno_str[16]; + + /* retrieve the device */ + ret = uclass_get_device_by_driver(UCLASS_MISC, + DM_GET_DRIVER(rockchip_efuse), &dev); + if (ret) { + debug("%s: could not find efuse device\n", __func__); + return; + } + + /* read the cpu_id range from the efuses */ + ret = misc_read(dev, RK3399_CPUID_OFF, &cpuid, sizeof(cpuid)); + if (ret) { + debug("%s: reading cpuid from the efuses failed\n", + __func__); + return; + } + + memset(cpuid_str, 0, sizeof(cpuid_str)); + for (i = 0; i < 16; i++) + sprintf(&cpuid_str[i * 2], "%02x", cpuid[i]); + + debug("cpuid: %s\n", cpuid_str); + + /* + * Mix the cpuid bytes using the same rules as in + * ${linux}/drivers/soc/rockchip/rockchip-cpuinfo.c + */ + for (i = 0; i < 8; i++) { + low[i] = cpuid[1 + (i << 1)]; + high[i] = cpuid[i << 1]; + } + + serialno = crc32_no_comp(0, low, 8); + serialno |= (u64)crc32_no_comp(serialno, high, 8) << 32; + snprintf(serialno_str, sizeof(serialno_str), "%llx", serialno); + + env_set("cpuid#", cpuid_str); + env_set("serial#", serialno_str); +#endif + + return; +} + +int misc_init_r(void) +{ + setup_serial(); + setup_macaddr(); + + return 0; +} + +#ifdef CONFIG_SERIAL_TAG +void get_board_serial(struct tag_serialnr *serialnr) +{ + char *serial_string; + u64 serial = 0; + + serial_string = env_get("serial#"); + + if (serial_string) + serial = simple_strtoull(serial_string, NULL, 16); + + serialnr->high = (u32)(serial >> 32); + serialnr->low = (u32)(serial & 0xffffffff); +} +#endif + +#ifdef CONFIG_USB_DWC3 +static struct dwc3_device dwc3_device_data = { + .maximum_speed = USB_SPEED_HIGH, + .base = 0xfe800000, + .dr_mode = USB_DR_MODE_PERIPHERAL, + .index = 0, + .dis_u2_susphy_quirk = 1, +}; + +int usb_gadget_handle_interrupts(void) +{ + dwc3_uboot_handle_interrupt(0); + return 0; +} + +int board_usb_init(int index, enum usb_init_type init) +{ + return dwc3_uboot_init(&dwc3_device_data); +} +#endif diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 3196d860407..09800886684 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -22,97 +22,14 @@ DECLARE_GLOBAL_DATA_PTR; static uint8_t efi_obj_list_initalized; -/* - * When booting using the "bootefi" command, we don't know which - * physical device the file came from. So we create a pseudo-device - * called "bootefi" with the device path /bootefi. - * - * In addition to the originating device we also declare the file path - * of "bootefi" based loads to be /bootefi. - */ -static struct efi_device_path_file_path bootefi_image_path[] = { - { - .dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE, - .dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH, - .dp.length = sizeof(bootefi_image_path[0]), - .str = { 'b','o','o','t','e','f','i' }, - }, { - .dp.type = DEVICE_PATH_TYPE_END, - .dp.sub_type = DEVICE_PATH_SUB_TYPE_END, - .dp.length = sizeof(bootefi_image_path[0]), - } -}; - -static struct efi_device_path_file_path bootefi_device_path[] = { - { - .dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE, - .dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH, - .dp.length = sizeof(bootefi_image_path[0]), - .str = { 'b','o','o','t','e','f','i' }, - }, { - .dp.type = DEVICE_PATH_TYPE_END, - .dp.sub_type = DEVICE_PATH_SUB_TYPE_END, - .dp.length = sizeof(bootefi_image_path[0]), - } -}; - -/* The EFI loaded_image interface for the image executed via "bootefi" */ -static struct efi_loaded_image loaded_image_info = { - .device_handle = bootefi_device_path, - .file_path = bootefi_image_path, -}; - -/* The EFI object struct for the image executed via "bootefi" */ -static struct efi_object loaded_image_info_obj = { - .handle = &loaded_image_info, - .protocols = { - { - /* - * When asking for the loaded_image interface, just - * return handle which points to loaded_image_info - */ - .guid = &efi_guid_loaded_image, - .protocol_interface = &loaded_image_info, - }, - { - /* - * When asking for the device path interface, return - * bootefi_device_path - */ - .guid = &efi_guid_device_path, - .protocol_interface = bootefi_device_path, - }, - { - .guid = &efi_guid_console_control, - .protocol_interface = (void *) &efi_console_control - }, - { - .guid = &efi_guid_device_path_to_text_protocol, - .protocol_interface = (void *) &efi_device_path_to_text - }, - }, -}; - -/* The EFI object struct for the device the "bootefi" image was loaded from */ -static struct efi_object bootefi_device_obj = { - .handle = bootefi_device_path, - .protocols = { - { - /* When asking for the device path interface, return - * bootefi_device_path */ - .guid = &efi_guid_device_path, - .protocol_interface = bootefi_device_path - } - }, -}; +static struct efi_device_path *bootefi_image_path; +static struct efi_device_path *bootefi_device_path; /* Initialize and populate EFI object list */ static void efi_init_obj_list(void) { efi_obj_list_initalized = 1; - list_add_tail(&loaded_image_info_obj.link, &efi_obj_list); - list_add_tail(&bootefi_device_obj.link, &efi_obj_list); efi_console_register(); #ifdef CONFIG_PARTITIONS efi_disk_register(); @@ -121,13 +38,7 @@ static void efi_init_obj_list(void) efi_gop_register(); #endif #ifdef CONFIG_NET - void *nethandle = loaded_image_info.device_handle; - efi_net_register(&nethandle); - - if (!memcmp(bootefi_device_path[0].str, "N\0e\0t", 6)) - loaded_image_info.device_handle = nethandle; - else - loaded_image_info.device_handle = bootefi_device_path; + efi_net_register(); #endif #ifdef CONFIG_GENERATE_SMBIOS_TABLE efi_smbios_register(); @@ -210,14 +121,27 @@ static unsigned long efi_run_in_el2(asmlinkage ulong (*entry)( * Load an EFI payload into a newly allocated piece of memory, register all * EFI objects it would want to access and jump to it. */ -static unsigned long do_bootefi_exec(void *efi, void *fdt) +static unsigned long do_bootefi_exec(void *efi, void *fdt, + struct efi_device_path *device_path, + struct efi_device_path *image_path) { + struct efi_loaded_image loaded_image_info = {}; + struct efi_object loaded_image_info_obj = {}; + ulong ret; + ulong (*entry)(void *image_handle, struct efi_system_table *st) asmlinkage; ulong fdt_pages, fdt_size, fdt_start, fdt_end; const efi_guid_t fdt_guid = EFI_FDT_GUID; bootm_headers_t img = { 0 }; + /* Initialize and populate EFI object list */ + if (!efi_obj_list_initalized) + efi_init_obj_list(); + + efi_setup_loaded_image(&loaded_image_info, &loaded_image_info_obj, + device_path, image_path); + /* * gd lives in a fixed register which may get clobbered while we execute * the payload. So save it here and restore it on every callback entry @@ -252,18 +176,18 @@ static unsigned long do_bootefi_exec(void *efi, void *fdt) /* Load the EFI payload */ entry = efi_load_pe(efi, &loaded_image_info); - if (!entry) - return -ENOENT; - - /* Initialize and populate EFI object list */ - if (!efi_obj_list_initalized) - efi_init_obj_list(); + if (!entry) { + ret = -ENOENT; + goto exit; + } /* Call our payload! */ debug("%s:%d Jumping to 0x%lx\n", __func__, __LINE__, (long)entry); if (setjmp(&loaded_image_info.exit_jmp)) { - return loaded_image_info.exit_status; + ret = loaded_image_info.exit_status; + EFI_EXIT(ret); + goto exit; } #ifdef CONFIG_ARM64 @@ -282,7 +206,13 @@ static unsigned long do_bootefi_exec(void *efi, void *fdt) } #endif - return efi_do_enter(&loaded_image_info, &systab, entry); + ret = efi_do_enter(&loaded_image_info, &systab, entry); + +exit: + /* image has returned, loaded-image obj goes *poof*: */ + list_del(&loaded_image_info_obj.link); + + return ret; } @@ -315,7 +245,8 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } printf("## Starting EFI application at %08lx ...\n", addr); - r = do_bootefi_exec((void *)addr, (void*)fdt_addr); + r = do_bootefi_exec((void *)addr, (void *)fdt_addr, + bootefi_device_path, bootefi_image_path); printf("## Application terminated, r = %lu\n", r & ~EFI_ERROR_MASK); @@ -344,58 +275,44 @@ U_BOOT_CMD( bootefi_help_text ); -void efi_set_bootdev(const char *dev, const char *devnr, const char *path) +static int parse_partnum(const char *devnr) { - __maybe_unused struct blk_desc *desc; - char devname[32] = { 0 }; /* dp->str is u16[32] long */ - char *colon, *s; - -#if defined(CONFIG_BLK) || CONFIG_IS_ENABLED(ISO_PARTITION) - desc = blk_get_dev(dev, simple_strtol(devnr, NULL, 10)); -#endif - -#ifdef CONFIG_BLK - if (desc) { - snprintf(devname, sizeof(devname), "%s", desc->bdev->name); - } else -#endif - - { - /* Assemble the condensed device name we use in efi_disk.c */ - snprintf(devname, sizeof(devname), "%s%s", dev, devnr); + const char *str = strchr(devnr, ':'); + if (str) { + str++; + return simple_strtoul(str, NULL, 16); } + return 0; +} - colon = strchr(devname, ':'); - -#if CONFIG_IS_ENABLED(ISO_PARTITION) - /* For ISOs we create partition block devices */ - if (desc && (desc->type != DEV_TYPE_UNKNOWN) && - (desc->part_type == PART_TYPE_ISO)) { - if (!colon) - snprintf(devname, sizeof(devname), "%s:1", devname); +void efi_set_bootdev(const char *dev, const char *devnr, const char *path) +{ + char filename[32] = { 0 }; /* dp->str is u16[32] long */ + char *s; - colon = NULL; - } -#endif + if (strcmp(dev, "Net")) { + struct blk_desc *desc; + int part; - if (colon) - *colon = '\0'; + desc = blk_get_dev(dev, simple_strtol(devnr, NULL, 10)); + part = parse_partnum(devnr); - /* Patch bootefi_device_path to the target device */ - memset(bootefi_device_path[0].str, 0, sizeof(bootefi_device_path[0].str)); - ascii2unicode(bootefi_device_path[0].str, devname); + bootefi_device_path = efi_dp_from_part(desc, part); + } else { +#ifdef CONFIG_NET + bootefi_device_path = efi_dp_from_eth(); +#endif + } - /* Patch bootefi_image_path to the target file path */ - memset(bootefi_image_path[0].str, 0, sizeof(bootefi_image_path[0].str)); if (strcmp(dev, "Net")) { /* Add leading / to fs paths, because they're absolute */ - snprintf(devname, sizeof(devname), "/%s", path); + snprintf(filename, sizeof(filename), "/%s", path); } else { - snprintf(devname, sizeof(devname), "%s", path); + snprintf(filename, sizeof(filename), "%s", path); } /* DOS style file path: */ - s = devname; + s = filename; while ((s = strchr(s, '/'))) *s++ = '\\'; - ascii2unicode(bootefi_image_path[0].str, devname); + bootefi_image_path = efi_dp_from_file(NULL, 0, filename); } diff --git a/cmd/mmc.c b/cmd/mmc.c index ae42200bfa2..5def4ea1a29 100644 --- a/cmd/mmc.c +++ b/cmd/mmc.c @@ -4,22 +4,17 @@ * * SPDX-License-Identifier: GPL-2.0+ */ + #include #include #include #include -#include -#include static int curr_device = -1; static void print_mmcinfo(struct mmc *mmc) { int i; - const char *timing[] = { - "Legacy", "High Speed", "High Speed", "SDR12", - "SDR25", "SDR50", "SDR104", "DDR50", - "DDR52", "HS200", "HS400", "HS400 Enhanced Strobe"}; printf("Device: %s\n", mmc->cfg->name); printf("Manufacturer ID: %x\n", mmc->cid[0] >> 24); @@ -28,8 +23,7 @@ static void print_mmcinfo(struct mmc *mmc) (mmc->cid[1] >> 24), (mmc->cid[1] >> 16) & 0xff, (mmc->cid[1] >> 8) & 0xff, mmc->cid[1] & 0xff); - printf("Timing Interface: %s\n", timing[mmc->timing]); - printf("Tran Speed: %d\n", mmc->clock); + printf("Tran Speed: %d\n", mmc->tran_speed); printf("Rd Block Len: %d\n", mmc->read_bl_len); printf("%s version %d.%d", IS_SD(mmc) ? "SD" : "MMC", @@ -44,7 +38,7 @@ static void print_mmcinfo(struct mmc *mmc) print_size(mmc->capacity, "\n"); printf("Bus Width: %d-bit%s\n", mmc->bus_width, - mmc_card_ddr(mmc) ? " DDR" : ""); + mmc->ddr_mode ? " DDR" : ""); puts("Erase Group Size: "); print_size(((u64)mmc->erase_grp_size) << 9, "\n"); @@ -124,171 +118,7 @@ static int do_mmcinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return CMD_RET_SUCCESS; } -#ifdef CONFIG_OPTEE_CLIENT -static int do_mmc_testrpmb(cmd_tbl_t *cmdtp, - int flag, int argc, char * const argv[]) -{ - struct mmc *mmc; - - if (curr_device < 0) { - if (get_mmc_num() > 0) { - puts("MMC device available\n"); - curr_device = 0; - } else { - puts("No MMC device available\n"); - return 1; - } - } - - mmc = init_mmc_device(curr_device, false); - if (!mmc) - return CMD_RET_FAILURE; - - uint64_t value; - trusty_write_rollback_index(0x87654321, 0x1122334455667788); - trusty_read_rollback_index(0x87654321, &value); - debug("sizeof(value) %x\n ", sizeof(value)); - if (value == 0x1122334455667788) - printf("good ! value==0x1122334455667788\n "); - else - printf("error ! value!=0x1122334455667788\n "); - - uint8_t data[] = "just a data"; - uint8_t data_read[11]; - trusty_write_permanent_attributes(data, sizeof(data)); - trusty_read_permanent_attributes(data_read, sizeof(data)); - printf("attribute: %s\n ", data_read); - - trusty_notify_optee_uboot_end(); - printf(" tell_optee_uboot_end \n "); - value = 0; - trusty_read_rollback_index(0x87654321, &value); - if (value == 0x1122334455667788) - printf(" value==0x1122334455667788 read still enable\n "); - else - printf(" good! value!=0x1122334455667788 read denied\n "); - return CMD_RET_SUCCESS; -} - -static int do_mmc_testefuse(cmd_tbl_t *cmdtp, - int flag, int argc, char * const argv[]) -{ - uint32_t buf32[8]; - uint32_t outbuf32[8]; - - buf32[0] = 0x01020304; - buf32[1] = 0x05060708; - buf32[2] = 0x090a0b0c; - buf32[3] = 0x0d0e0f10; - buf32[4] = 0x11121314; - buf32[5] = 0x15161718; - buf32[6] = 0x191a1b1c; - buf32[7] = 0x1d1e1f20; - - trusty_write_attribute_hash(buf32, 8); - - trusty_read_attribute_hash(outbuf32, 8); - - printf(" 0x%x 0x%x 0x%x 0x%x \n", - outbuf32[0], outbuf32[1], outbuf32[2], outbuf32[3]); - printf(" 0x%x 0x%x 0x%x 0x%x \n", - outbuf32[4], outbuf32[5], outbuf32[6], outbuf32[7]); - - trusty_write_vbootkey_hash(buf32, 8); - - trusty_read_vbootkey_hash(outbuf32, 8); - - printf(" 0x%x 0x%x 0x%x 0x%x \n", - outbuf32[0], outbuf32[1], outbuf32[2], outbuf32[3]); - printf(" 0x%x 0x%x 0x%x 0x%x \n", - outbuf32[4], outbuf32[5], outbuf32[6], outbuf32[7]); - - return CMD_RET_SUCCESS; -} - -#endif - #ifdef CONFIG_SUPPORT_EMMC_RPMB -char temp_original_part; -int init_rpmb(void) -{ - struct mmc *mmc; - - mmc = init_mmc_device(curr_device, false); - if (!mmc) - return CMD_RET_FAILURE; - - if (!(mmc->version & MMC_VERSION_MMC)) { - printf("It is not a EMMC device\n"); - return CMD_RET_FAILURE; - } - if (mmc->version < MMC_VERSION_4_41) { - printf("RPMB not supported before version 4.41\n"); - return CMD_RET_FAILURE; - } - - /* Switch to the RPMB partition */ -#ifndef CONFIG_BLK - temp_original_part = mmc->block_dev.hwpart; - debug("mmc->block_dev.hwpart\n"); -#else - temp_original_part = mmc_get_blk_desc(mmc)->hwpart; - debug("mmc_get_blk_desc(mmc)->hwpart\n"); -#endif - debug("init_rpmb temp_original_part = 0x%X\n", temp_original_part); - if (blk_select_hwpart_devnum - (IF_TYPE_MMC, curr_device, MMC_PART_RPMB) != 0) - return CMD_RET_FAILURE; - - return CMD_RET_SUCCESS; -} - -int finish_rpmb(void) -{ - /* Return to original partition */ - debug("finish_rpmb temp_original_part = 0x%X\n", temp_original_part); - if (blk_select_hwpart_devnum - (IF_TYPE_MMC, curr_device, temp_original_part) != 0) - return CMD_RET_FAILURE; - - return CMD_RET_SUCCESS; -} - -int do_readcounter(struct s_rpmb *requestpackets) -{ - struct mmc *mmc = find_mmc_device(curr_device); - - return read_counter(mmc, requestpackets); -} - -int do_programkey(struct s_rpmb *requestpackets) -{ - struct mmc *mmc = find_mmc_device(curr_device); - - return program_key(mmc, requestpackets); -} - -int do_authenticatedread(struct s_rpmb *requestpackets, uint16_t block_count) -{ - struct mmc *mmc = find_mmc_device(curr_device); - - return authenticated_read(mmc, requestpackets, block_count); -} - -int do_authenticatedwrite(struct s_rpmb *requestpackets) -{ - struct mmc *mmc = find_mmc_device(curr_device); - - return authenticated_write(mmc, requestpackets); -} - -struct mmc *do_returnmmc(void) -{ - struct mmc *mmc = find_mmc_device(curr_device); - - return mmc; -} - static int confirm_key_prog(void) { puts("Warning: Programming authentication key can be done only once !\n" @@ -463,8 +293,6 @@ static int do_mmc_read(cmd_tbl_t *cmdtp, int flag, curr_device, blk, cnt); n = blk_dread(mmc_get_blk_desc(mmc), blk, cnt, addr); - /* flush cache after read */ - flush_cache((ulong)addr, cnt * 512); /* FIXME */ printf("%d blocks read: %s\n", n, (n == cnt) ? "OK" : "ERROR"); return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE; @@ -970,10 +798,6 @@ static cmd_tbl_t cmd_mmc[] = { U_BOOT_CMD_MKENT(partconf, 5, 0, do_mmc_partconf, "", ""), U_BOOT_CMD_MKENT(rst-function, 3, 0, do_mmc_rst_func, "", ""), #endif -#ifdef CONFIG_OPTEE_CLIENT - U_BOOT_CMD_MKENT(testrpmb, 1, 0, do_mmc_testrpmb, "", ""), - U_BOOT_CMD_MKENT(testefuse, 1, 0, do_mmc_testefuse, "", ""), -#endif #ifdef CONFIG_SUPPORT_EMMC_RPMB U_BOOT_CMD_MKENT(rpmb, CONFIG_SYS_MAXARGS, 1, do_mmcrpmb, "", ""), #endif @@ -1038,10 +862,6 @@ U_BOOT_CMD( " - Change the RST_n_FUNCTION field of the specified device\n" " WARNING: This is a write-once field and 0 / 1 / 2 are the only valid values.\n" #endif -#ifdef CONFIG_OPTEE_CLIENT - "mmc testrpmb - test CA call static TA,and TA call rpmb in uboot\n" - "mmc testefuse - test CA call static TA,and TA read or write efuse\n" -#endif #ifdef CONFIG_SUPPORT_EMMC_RPMB "mmc rpmb read addr blk# cnt [address of auth-key] - block size is 256 bytes\n" "mmc rpmb write addr blk# cnt
- block size is 256 bytes\n" @@ -1061,4 +881,3 @@ U_BOOT_CMD( "display MMC info", "- display info of the current MMC device" ); - diff --git a/common/spl/spl.c b/common/spl/spl.c index d156e745337..1757b575bc3 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -424,6 +424,18 @@ void board_init_r(gd_t *dummy1, ulong dummy2) debug("SPL malloc() used %#lx bytes (%ld KB)\n", gd->malloc_ptr, gd->malloc_ptr / 1024); #endif + + if (CONFIG_IS_ENABLED(ATF_SUPPORT)) { + debug("loaded - jumping to U-Boot via ATF BL31.\n"); + spl_bl31_entry((void *)spl_image.entry_point); + } + + if (CONFIG_IS_ENABLED(OPTEE_SUPPORT)) { + debug("loaded - jumping to U-Boot via OP-TEE.\n"); + spl_optee_entry(0, 0, 0, (void *)spl_image.entry_point); + } + + debug("loaded - jumping to U-Boot...\n"); #ifdef CONFIG_BOOTSTAGE_STASH int ret; diff --git a/common/spl/spl_atf.c b/common/spl/spl_atf.c index 2f6fff971ab..06c4a039203 100644 --- a/common/spl/spl_atf.c +++ b/common/spl/spl_atf.c @@ -49,13 +49,14 @@ struct bl31_params *bl2_plat_get_bl31_params(void) ATF_PARAM_IMAGE_BINARY, ATF_VERSION_1, 0); /* Fill BL32 related information if it exists */ -#ifdef BL32_BASE bl2_to_bl31_params->bl32_ep_info = &bl31_params_mem.bl32_ep_info; SET_PARAM_HEAD(bl2_to_bl31_params->bl32_ep_info, ATF_PARAM_EP, ATF_VERSION_1, 0); bl2_to_bl31_params->bl32_image_info = &bl31_params_mem.bl32_image_info; SET_PARAM_HEAD(bl2_to_bl31_params->bl32_image_info, ATF_PARAM_IMAGE_BINARY, ATF_VERSION_1, 0); +#ifndef BL32_BASE + bl2_to_bl31_params->bl32_ep_info->pc = 0; #endif /* BL32_BASE */ /* Fill BL33 related information */ diff --git a/common/usb_storage.c b/common/usb_storage.c index df0b0573087..ca2e38a3f4d 100644 --- a/common/usb_storage.c +++ b/common/usb_storage.c @@ -106,7 +106,7 @@ struct us_data { * enough free heap space left, but the SCSI READ(10) and WRITE(10) commands are * limited to 65535 blocks. */ -#define USB_MAX_XFER_BLK 65535 +#define USB_MAX_XFER_BLK 512 #else #define USB_MAX_XFER_BLK 20 #endif diff --git a/configs/chromebit_mickey_defconfig b/configs/chromebit_mickey_defconfig index f40c0b9afa7..e84706ddaae 100644 --- a/configs/chromebit_mickey_defconfig +++ b/configs/chromebit_mickey_defconfig @@ -40,6 +40,8 @@ CONFIG_SPL_REGMAP=y CONFIG_SYSCON=y CONFIG_SPL_SYSCON=y # CONFIG_SPL_SIMPLE_BUS is not set +CONFIG_ADC=y +CONFIG_SARADC_ROCKCHIP=y CONFIG_CLK=y CONFIG_SPL_CLK=y CONFIG_ROCKCHIP_GPIO=y diff --git a/configs/chromebook_jerry_defconfig b/configs/chromebook_jerry_defconfig index cdeabaa12aa..f612d31c721 100644 --- a/configs/chromebook_jerry_defconfig +++ b/configs/chromebook_jerry_defconfig @@ -42,6 +42,8 @@ CONFIG_SPL_REGMAP=y CONFIG_SYSCON=y CONFIG_SPL_SYSCON=y # CONFIG_SPL_SIMPLE_BUS is not set +CONFIG_ADC=y +CONFIG_SARADC_ROCKCHIP=y CONFIG_CLK=y CONFIG_SPL_CLK=y CONFIG_ROCKCHIP_GPIO=y diff --git a/configs/chromebook_minnie_defconfig b/configs/chromebook_minnie_defconfig index c1e36fa8601..38a4b42db9b 100644 --- a/configs/chromebook_minnie_defconfig +++ b/configs/chromebook_minnie_defconfig @@ -41,6 +41,8 @@ CONFIG_SPL_REGMAP=y CONFIG_SYSCON=y CONFIG_SPL_SYSCON=y # CONFIG_SPL_SIMPLE_BUS is not set +CONFIG_ADC=y +CONFIG_SARADC_ROCKCHIP=y CONFIG_CLK=y CONFIG_SPL_CLK=y CONFIG_ROCKCHIP_GPIO=y diff --git a/configs/evb-px5_defconfig b/configs/evb-px5_defconfig index a93dae0928e..b2d291a1a0c 100644 --- a/configs/evb-px5_defconfig +++ b/configs/evb-px5_defconfig @@ -13,6 +13,8 @@ CONFIG_CMD_MMC=y CONFIG_CMD_CACHE=y CONFIG_REGMAP=y CONFIG_SYSCON=y +CONFIG_ADC=y +CONFIG_SARADC_ROCKCHIP=y CONFIG_CLK=y CONFIG_MMC_DW=y CONFIG_MMC_DW_ROCKCHIP=y diff --git a/configs/evb-rk3288_defconfig b/configs/evb-rk3288_defconfig index 04f6a064e3a..059343287a0 100644 --- a/configs/evb-rk3288_defconfig +++ b/configs/evb-rk3288_defconfig @@ -37,6 +37,8 @@ CONFIG_REGMAP=y CONFIG_SPL_REGMAP=y CONFIG_SYSCON=y CONFIG_SPL_SYSCON=y +CONFIG_ADC=y +CONFIG_SARADC_ROCKCHIP=y CONFIG_CLK=y CONFIG_SPL_CLK=y CONFIG_ROCKCHIP_GPIO=y diff --git a/configs/evb-rk3328_defconfig b/configs/evb-rk3328_defconfig index d4a00718c5b..1e906efd231 100644 --- a/configs/evb-rk3328_defconfig +++ b/configs/evb-rk3328_defconfig @@ -5,6 +5,10 @@ CONFIG_SPL_LIBGENERIC_SUPPORT=y CONFIG_SYS_MALLOC_F_LEN=0x2000 CONFIG_TPL_SYS_MALLOC_F_LEN=0x600 CONFIG_ROCKCHIP_RK3328=y +CONFIG_TPL_LDSCRIPT="arch/arm/mach-rockchip/rk3328/u-boot-tpl.lds" +CONFIG_TPL_TEXT_BASE=0xff091000 +CONFIG_TPL_STACK=0xff098000 +CONFIG_TPL_MAX_SIZE=28672 CONFIG_TPL_SERIAL_PRESENT=y CONFIG_TPL_LIBCOMMON_SUPPORT=y CONFIG_TPL_LIBGENERIC_SUPPORT=y @@ -21,6 +25,7 @@ CONFIG_SPL_FIT_GENERATOR="board/rockchip/evb_rk3328/mk_fit_atf.sh" # CONFIG_DISPLAY_CPUINFO is not set CONFIG_TPL_SYS_MALLOC_SIMPLE=y CONFIG_SPL_STACK_R=y +CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x200 CONFIG_SPL_ATF_SUPPORT=y CONFIG_TPL=y CONFIG_TPL_BOOTROM_SUPPORT=y @@ -36,6 +41,7 @@ CONFIG_CMD_BOOTZ=y CONFIG_CMD_GPT=y CONFIG_CMD_MMC=y CONFIG_CMD_USB=y +CONFIG_CMD_USB_MASS_STORAGE=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_TIME=y CONFIG_SPL_OF_CONTROL=y @@ -44,12 +50,18 @@ CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent CONFIG_TPL_OF_PLATDATA=y CONFIG_ENV_IS_IN_MMC=y CONFIG_TPL_DM=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_ADC=y +CONFIG_SARADC_ROCKCHIP=y +CONFIG_SPL_SYSCON=y +CONFIG_TPL_SYSCON=y CONFIG_CLK=y CONFIG_SPL_CLK=y CONFIG_ROCKCHIP_GPIO=y @@ -59,11 +71,20 @@ CONFIG_MMC_DW=y CONFIG_MMC_DW_ROCKCHIP=y CONFIG_PHY=y CONFIG_PHY_ROCKCHIP_INNO_USB2=y +CONFIG_MTD=y +CONFIG_CMD_SF=y +CONFIG_SPI_FLASH=y +CONFIG_SPI_FLASH_STMICRO=y +CONFIG_SPI_FLASH_MTD=y +CONFIG_DM_ETH=y +CONFIG_ETH_DESIGNWARE=y +CONFIG_GMAC_ROCKCHIP=y CONFIG_PINCTRL=y CONFIG_SPL_PINCTRL=y CONFIG_PINCTRL_ROCKCHIP_RK3328=y CONFIG_DM_PMIC=y CONFIG_PMIC_RK8XX=y +CONFIG_DM_REGULATOR=y CONFIG_REGULATOR_PWM=y CONFIG_DM_REGULATOR_FIXED=y CONFIG_REGULATOR_RK8XX=y @@ -79,6 +100,9 @@ CONFIG_DEBUG_UART_SHIFT=2 CONFIG_DEBUG_UART_ANNOUNCE=y CONFIG_DEBUG_UART_SKIP_INIT=y CONFIG_SYS_NS16550=y +CONFIG_ROCKCHIP_SPI=y +CONFIG_DEBUG_UART_ANNOUNCE=y +CONFIG_DEBUG_UART_SKIP_INIT=y CONFIG_SYSRESET=y CONFIG_SPL_SYSRESET=y CONFIG_USB=y @@ -99,3 +123,7 @@ CONFIG_G_DNL_PRODUCT_NUM=0x330a CONFIG_USE_TINY_PRINTF=y CONFIG_SPL_TINY_MEMSET=y CONFIG_ERRNO_STR=y +CONFIG_CMD_ETHSW=y +CONFIG_ROCKCHIP_EFUSE=y +CONFIG_MISC=y +CONFIG_MISC_INIT_R=y diff --git a/configs/evb-rk3399_defconfig b/configs/evb-rk3399_defconfig index 4557c2b0326..1a74eb2ea24 100644 --- a/configs/evb-rk3399_defconfig +++ b/configs/evb-rk3399_defconfig @@ -38,6 +38,8 @@ CONFIG_REGMAP=y CONFIG_SPL_REGMAP=y CONFIG_SYSCON=y CONFIG_SPL_SYSCON=y +CONFIG_ADC=y +CONFIG_SARADC_ROCKCHIP=y CONFIG_CLK=y CONFIG_SPL_CLK=y CONFIG_ROCKCHIP_GPIO=y @@ -94,3 +96,7 @@ CONFIG_VIDEO_ROCKCHIP_MAX_YRES=1200 CONFIG_DISPLAY_ROCKCHIP_MIPI=y CONFIG_USE_TINY_PRINTF=y CONFIG_ERRNO_STR=y +CONFIG_MTD=y +CONFIG_ST_SMI=y +CONFIG_MTD_PARTITIONS=y +CONFIG_FLASH_CFI_LEGACY=y diff --git a/configs/evb-rv1108_defconfig b/configs/evb-rv1108_defconfig index c7ef5940716..1e7c2f42059 100644 --- a/configs/evb-rv1108_defconfig +++ b/configs/evb-rv1108_defconfig @@ -21,6 +21,8 @@ CONFIG_CMD_TIME=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_REGMAP=y CONFIG_SYSCON=y +CONFIG_ADC=y +CONFIG_SARADC_ROCKCHIP=y CONFIG_CLK=y CONFIG_ROCKCHIP_GPIO=y CONFIG_PHY=y diff --git a/configs/fennec-rk3288_defconfig b/configs/fennec-rk3288_defconfig index d9c4d30e05f..e4324717fb9 100644 --- a/configs/fennec-rk3288_defconfig +++ b/configs/fennec-rk3288_defconfig @@ -40,6 +40,8 @@ CONFIG_SPL_REGMAP=y CONFIG_SYSCON=y CONFIG_SPL_SYSCON=y # CONFIG_SPL_SIMPLE_BUS is not set +CONFIG_ADC=y +CONFIG_SARADC_ROCKCHIP=y CONFIG_CLK=y CONFIG_SPL_CLK=y CONFIG_ROCKCHIP_GPIO=y diff --git a/configs/firefly-rk3288_defconfig b/configs/firefly-rk3288_defconfig index 40d7393859f..fc0ad2a0505 100644 --- a/configs/firefly-rk3288_defconfig +++ b/configs/firefly-rk3288_defconfig @@ -40,6 +40,8 @@ CONFIG_SPL_REGMAP=y CONFIG_SYSCON=y CONFIG_SPL_SYSCON=y # CONFIG_SPL_SIMPLE_BUS is not set +CONFIG_ADC=y +CONFIG_SARADC_ROCKCHIP=y CONFIG_CLK=y CONFIG_SPL_CLK=y CONFIG_ROCKCHIP_GPIO=y diff --git a/configs/firefly-rk3399_defconfig b/configs/firefly-rk3399_defconfig index 5d228af96c8..da2aec0421a 100644 --- a/configs/firefly-rk3399_defconfig +++ b/configs/firefly-rk3399_defconfig @@ -45,6 +45,8 @@ CONFIG_REGMAP=y CONFIG_SPL_REGMAP=y CONFIG_SYSCON=y CONFIG_SPL_SYSCON=y +CONFIG_ADC=y +CONFIG_SARADC_ROCKCHIP=y CONFIG_CLK=y CONFIG_SPL_CLK=y CONFIG_ROCKCHIP_GPIO=y diff --git a/configs/geekbox_defconfig b/configs/geekbox_defconfig index 19255fb209f..a2705156b45 100644 --- a/configs/geekbox_defconfig +++ b/configs/geekbox_defconfig @@ -9,6 +9,8 @@ CONFIG_DEBUG_UART=y # CONFIG_CMD_IMLS is not set CONFIG_REGMAP=y CONFIG_SYSCON=y +CONFIG_ADC=y +CONFIG_SARADC_ROCKCHIP=y CONFIG_CLK=y CONFIG_PINCTRL=y CONFIG_PINCTRL_ROCKCHIP_RK3368=y diff --git a/configs/lion-rk3368_defconfig b/configs/lion-rk3368_defconfig index ca8eee57f17..a485444147e 100644 --- a/configs/lion-rk3368_defconfig +++ b/configs/lion-rk3368_defconfig @@ -51,6 +51,8 @@ CONFIG_TPL_REGMAP=y CONFIG_SYSCON=y CONFIG_SPL_SYSCON=y CONFIG_TPL_SYSCON=y +CONFIG_ADC=y +CONFIG_SARADC_ROCKCHIP=y CONFIG_CLK=y CONFIG_SPL_CLK=y CONFIG_TPL_CLK=y diff --git a/configs/miqi-rk3288_defconfig b/configs/miqi-rk3288_defconfig index b0437e13a7a..7825467df69 100644 --- a/configs/miqi-rk3288_defconfig +++ b/configs/miqi-rk3288_defconfig @@ -40,6 +40,8 @@ CONFIG_SPL_REGMAP=y CONFIG_SYSCON=y CONFIG_SPL_SYSCON=y # CONFIG_SPL_SIMPLE_BUS is not set +CONFIG_ADC=y +CONFIG_SARADC_ROCKCHIP=y CONFIG_CLK=y CONFIG_SPL_CLK=y CONFIG_ROCKCHIP_GPIO=y diff --git a/configs/phycore-rk3288_defconfig b/configs/phycore-rk3288_defconfig index 93ee353d0dc..911600d3efe 100644 --- a/configs/phycore-rk3288_defconfig +++ b/configs/phycore-rk3288_defconfig @@ -42,6 +42,8 @@ CONFIG_SPL_REGMAP=y CONFIG_SYSCON=y CONFIG_SPL_SYSCON=y # CONFIG_SPL_SIMPLE_BUS is not set +CONFIG_ADC=y +CONFIG_SARADC_ROCKCHIP=y CONFIG_CLK=y CONFIG_SPL_CLK=y CONFIG_ROCKCHIP_GPIO=y diff --git a/configs/pinebook_pro-rk3399_defconfig b/configs/pinebook_pro-rk3399_defconfig new file mode 100644 index 00000000000..ee7bd126297 --- /dev/null +++ b/configs/pinebook_pro-rk3399_defconfig @@ -0,0 +1,113 @@ +CONFIG_ARM=y +CONFIG_ARCH_ROCKCHIP=y +CONFIG_SPL_LIBCOMMON_SUPPORT=y +CONFIG_SPL_LIBGENERIC_SUPPORT=y +CONFIG_SYS_MALLOC_F_LEN=0x4000 +CONFIG_ROCKCHIP_RK3399=y +CONFIG_ROCKCHIP_SPL_RESERVE_IRAM=0x0 +CONFIG_TARGET_PINEBOOK_PRO_RK3399=y +CONFIG_SPL_SPI_FLASH_SUPPORT=y +CONFIG_SPL_SPI_SUPPORT=y +CONFIG_SPL_STACK_R_ADDR=0x600000 +CONFIG_DEFAULT_DEVICE_TREE="rk3399-pinebook-pro" +CONFIG_DEBUG_UART=y +CONFIG_FIT=y +CONFIG_SPL_LOAD_FIT=y +CONFIG_SPL_FIT_GENERATOR="board/rockchip/pinebook_pro_rk3399/mk_fit_atf.sh" +CONFIG_BOOTDELAY=0 +# CONFIG_DISPLAY_CPUINFO is not set +CONFIG_ANDROID_BOOTLOADER=y +CONFIG_SPL_BOOTROM_SUPPORT=y +CONFIG_SPL_STACK_R=y +CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x4000 +CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x200 +CONFIG_SPL_MTD_SUPPORT=y +CONFIG_SPL_ATF_SUPPORT=y +CONFIG_FASTBOOT_BUF_ADDR=0x00800800 +CONFIG_FASTBOOT_BUF_SIZE=0x08000000 +CONFIG_FASTBOOT_FLASH=y +CONFIG_FASTBOOT_FLASH_MMC_DEV=0 +CONFIG_CMD_BOOTZ=y +# CONFIG_CMD_IMLS is not set +CONFIG_CMD_MEMINFO=y +CONFIG_CMD_SHA1SUM=y +CONFIG_SHA1SUM_VERIFY=y +CONFIG_CMD_GPIO=y +CONFIG_CMD_GPT=y +CONFIG_CMD_I2C=y +CONFIG_CMD_LOAD_ANDROID=y +CONFIG_CMD_BOOT_ANDROID=y +CONFIG_CMD_MMC=y +CONFIG_CMD_SF=y +CONFIG_CMD_USB=y +CONFIG_CMD_USB_MASS_STORAGE=y +# CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_TIME=y +CONFIG_CMD_REGULATOR=y +CONFIG_CMD_MTDPARTS=y +CONFIG_SPL_OF_CONTROL=y +CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" +CONFIG_ENV_IS_IN_SPI_FLASH=y +CONFIG_SPL_DM_SEQ_ALIAS=y +CONFIG_REGMAP=y +CONFIG_SPL_REGMAP=y +CONFIG_SYSCON=y +CONFIG_SPL_SYSCON=y +CONFIG_CLK=y +CONFIG_SPL_CLK=y +CONFIG_ROCKCHIP_GPIO=y +CONFIG_SYS_I2C_ROCKCHIP=y +CONFIG_LED=y +CONFIG_LED_GPIO=y +CONFIG_MISC=y +CONFIG_ROCKCHIP_EFUSE=y +CONFIG_MMC_DW=y +CONFIG_MMC_DW_ROCKCHIP=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_ROCKCHIP=y +CONFIG_SPI_FLASH=y +CONFIG_SPI_FLASH_GIGADEVICE=y +CONFIG_SPI_FLASH_WINBOND=y +CONFIG_DM_ETH=y +CONFIG_ETH_DESIGNWARE=y +CONFIG_GMAC_ROCKCHIP=y +CONFIG_PINCTRL=y +CONFIG_SPL_PINCTRL=y +CONFIG_PINCTRL_ROCKCHIP_RK3399=y +CONFIG_DM_PMIC=y +CONFIG_PMIC_RK8XX=y +CONFIG_REGULATOR_PWM=y +CONFIG_DM_REGULATOR_FIXED=y +CONFIG_REGULATOR_RK8XX=y +CONFIG_PWM_ROCKCHIP=y +CONFIG_RAM=y +CONFIG_SPL_RAM=y +CONFIG_DM_RESET=y +CONFIG_BAUDRATE=1500000 +CONFIG_DEBUG_UART_BASE=0xFF1A0000 +CONFIG_DEBUG_UART_CLOCK=24000000 +CONFIG_DEBUG_UART_SHIFT=2 +CONFIG_SYS_NS16550=y +CONFIG_ROCKCHIP_SPI=y +CONFIG_SYSRESET=y +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_DWC3=y +CONFIG_USB_DWC3_GADGET=y +CONFIG_USB_STORAGE=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_DOWNLOAD=y +CONFIG_G_DNL_MANUFACTURER="Rockchip" +CONFIG_G_DNL_VENDOR_NUM=0x18d1 +CONFIG_G_DNL_PRODUCT_NUM=0xd00d +CONFIG_USB_HOST_ETHER=y +CONFIG_USB_ETHER_ASIX=y +CONFIG_USB_ETHER_ASIX88179=y +CONFIG_USB_ETHER_MCS7830=y +CONFIG_USB_ETHER_RTL8152=y +CONFIG_USB_ETHER_SMSC95XX=y +CONFIG_USE_TINY_PRINTF=y +CONFIG_ERRNO_STR=y diff --git a/configs/popmetal-rk3288_defconfig b/configs/popmetal-rk3288_defconfig index 5e99f9c0892..9f5d78d2040 100644 --- a/configs/popmetal-rk3288_defconfig +++ b/configs/popmetal-rk3288_defconfig @@ -40,6 +40,8 @@ CONFIG_SPL_REGMAP=y CONFIG_SYSCON=y CONFIG_SPL_SYSCON=y # CONFIG_SPL_SIMPLE_BUS is not set +CONFIG_ADC=y +CONFIG_SARADC_ROCKCHIP=y CONFIG_CLK=y CONFIG_SPL_CLK=y CONFIG_ROCKCHIP_GPIO=y diff --git a/configs/puma-rk3399_defconfig b/configs/puma-rk3399_defconfig index 1badf80beb4..7929a697f07 100644 --- a/configs/puma-rk3399_defconfig +++ b/configs/puma-rk3399_defconfig @@ -41,6 +41,8 @@ CONFIG_REGMAP=y CONFIG_SPL_REGMAP=y CONFIG_SYSCON=y CONFIG_SPL_SYSCON=y +CONFIG_ADC=y +CONFIG_SARADC_ROCKCHIP=y CONFIG_CLK=y CONFIG_SPL_CLK=y CONFIG_ROCKCHIP_GPIO=y diff --git a/configs/rock2_defconfig b/configs/rock2_defconfig index b41644ef5fb..7d91b68301e 100644 --- a/configs/rock2_defconfig +++ b/configs/rock2_defconfig @@ -39,6 +39,8 @@ CONFIG_SPL_REGMAP=y CONFIG_SYSCON=y CONFIG_SPL_SYSCON=y # CONFIG_SPL_SIMPLE_BUS is not set +CONFIG_ADC=y +CONFIG_SARADC_ROCKCHIP=y CONFIG_CLK=y CONFIG_SPL_CLK=y CONFIG_ROCKCHIP_GPIO=y diff --git a/configs/rock64-rk3328_defconfig b/configs/rock64-rk3328_defconfig new file mode 100644 index 00000000000..13e4baed9d2 --- /dev/null +++ b/configs/rock64-rk3328_defconfig @@ -0,0 +1,131 @@ +CONFIG_ARM=y +CONFIG_ARCH_ROCKCHIP=y +CONFIG_SPL_LIBCOMMON_SUPPORT=y +CONFIG_SPL_LIBGENERIC_SUPPORT=y +CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_ROCKCHIP_RK3328=y +CONFIG_TPL_LDSCRIPT="arch/arm/mach-rockchip/rk3328/u-boot-tpl.lds" +CONFIG_ROCKCHIP_SPL_RESERVE_IRAM=0x0 +CONFIG_TPL_LIBCOMMON_SUPPORT=y +CONFIG_TPL_LIBGENERIC_SUPPORT=y +CONFIG_SPL_DRIVERS_MISC_SUPPORT=y +CONFIG_TARGET_ROCK64_RK3328=y +CONFIG_SPL_SPI_FLASH_SUPPORT=y +CONFIG_SPL_SPI_SUPPORT=y +CONFIG_SPL_STACK_R_ADDR=0x600000 +CONFIG_DEFAULT_DEVICE_TREE="rk3328-rock64" +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_SPL_FIT_GENERATOR="board/rockchip/evb_rk3328/mk_fit_atf.sh" +CONFIG_BOOTDELAY=0 +# CONFIG_DISPLAY_CPUINFO is not set +CONFIG_SPL_BOOTROM_SUPPORT=y +CONFIG_TPL_SYS_MALLOC_SIMPLE=y +CONFIG_SPL_STACK_R=y +CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x200 +CONFIG_SPL_MTD_SUPPORT=y +CONFIG_SPL_ATF_SUPPORT=y +CONFIG_TPL_BOOTROM_SUPPORT=y +CONFIG_TPL_DRIVERS_MISC_SUPPORT=y +CONFIG_FASTBOOT_BUF_ADDR=0x00800800 +CONFIG_FASTBOOT_BUF_SIZE=0x08000000 +CONFIG_FASTBOOT_FLASH=y +CONFIG_FASTBOOT_FLASH_MMC_DEV=1 +CONFIG_CMD_BOOTZ=y +# CONFIG_CMD_IMLS is not set +CONFIG_CMD_MEMINFO=y +CONFIG_CMD_SHA1SUM=y +CONFIG_CMD_GPIO=y +CONFIG_CMD_GPT=y +CONFIG_CMD_I2C=y +CONFIG_CMD_MMC=y +CONFIG_CMD_SF=y +CONFIG_CMD_SPI=y +CONFIG_CMD_USB=y +CONFIG_CMD_USB_MASS_STORAGE=y +# CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_ETHSW=y +CONFIG_CMD_TIME=y +CONFIG_CMD_REGULATOR=y +CONFIG_CMD_MTDPARTS=y +# CONFIG_SPL_DOS_PARTITION is not set +# CONFIG_SPL_ISO_PARTITION is not set +# CONFIG_SPL_EFI_PARTITION is not set +CONFIG_SPL_OF_CONTROL=y +CONFIG_TPL_OF_CONTROL=y +CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" +CONFIG_TPL_OF_PLATDATA=y +CONFIG_ENV_IS_IN_SPI_FLASH=y +CONFIG_NET_RANDOM_ETHADDR=y +CONFIG_TPL_DM=y +CONFIG_SPL_DM_SEQ_ALIAS=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_TPL_CLK=y +CONFIG_ROCKCHIP_GPIO=y +CONFIG_SYS_I2C_ROCKCHIP=y +CONFIG_DM_KEY=y +CONFIG_LED=y +CONFIG_MISC=y +CONFIG_ROCKCHIP_EFUSE=y +CONFIG_MMC_DW=y +CONFIG_MMC_DW_ROCKCHIP=y +CONFIG_MTD=y +CONFIG_SPI_FLASH=y +CONFIG_SPI_FLASH_GIGADEVICE=y +CONFIG_SPI_FLASH_WINBOND=y +CONFIG_PHY_REALTEK=y +CONFIG_DM_ETH=y +CONFIG_ETH_DESIGNWARE=y +CONFIG_GMAC_ROCKCHIP=y +CONFIG_PHY=y +CONFIG_PHY_ROCKCHIP_INNO_USB2=y +CONFIG_PINCTRL=y +CONFIG_SPL_PINCTRL=y +CONFIG_PINCTRL_ROCKCHIP_RK3328=y +CONFIG_DM_PMIC=y +# CONFIG_SPL_PMIC_CHILDREN is not set +CONFIG_PMIC_RK8XX=y +CONFIG_REGULATOR_PWM=y +CONFIG_DM_REGULATOR_FIXED=y +CONFIG_REGULATOR_RK8XX=y +CONFIG_RAM=y +CONFIG_SPL_RAM=y +CONFIG_TPL_RAM=y +CONFIG_DM_RESET=y +CONFIG_BAUDRATE=1500000 +CONFIG_DEBUG_UART_BASE=0xFF130000 +CONFIG_DEBUG_UART_CLOCK=24000000 +CONFIG_DEBUG_UART_SHIFT=2 +CONFIG_DEBUG_UART_ANNOUNCE=y +CONFIG_DEBUG_UART_SKIP_INIT=y +CONFIG_ROCKCHIP_SPI=y +CONFIG_SYSRESET=y +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_STORAGE=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_DWC2_OTG=y +CONFIG_USB_GADGET_DOWNLOAD=y +CONFIG_G_DNL_MANUFACTURER="Rockchip" +CONFIG_G_DNL_VENDOR_NUM=0x2207 +CONFIG_G_DNL_PRODUCT_NUM=0x330a +CONFIG_USE_TINY_PRINTF=y +CONFIG_SPL_TINY_MEMSET=y +CONFIG_ERRNO_STR=y diff --git a/configs/rock_defconfig b/configs/rock_defconfig index cd7b36b5a73..0bc81afb0c7 100644 --- a/configs/rock_defconfig +++ b/configs/rock_defconfig @@ -30,6 +30,8 @@ CONFIG_ENV_IS_IN_MMC=y CONFIG_REGMAP=y CONFIG_SYSCON=y # CONFIG_SPL_SIMPLE_BUS is not set +CONFIG_ADC=y +CONFIG_SARADC_ROCKCHIP=y CONFIG_CLK=y CONFIG_ROCKCHIP_GPIO=y CONFIG_SYS_I2C_ROCKCHIP=y diff --git a/configs/rockpi4b-rk3399_defconfig b/configs/rockpi4b-rk3399_defconfig new file mode 100644 index 00000000000..61435d304fa --- /dev/null +++ b/configs/rockpi4b-rk3399_defconfig @@ -0,0 +1,112 @@ +CONFIG_ARM=y +CONFIG_ARCH_ROCKCHIP=y +CONFIG_SPL_LIBCOMMON_SUPPORT=y +CONFIG_SPL_LIBGENERIC_SUPPORT=y +CONFIG_SYS_MALLOC_F_LEN=0x4000 +CONFIG_ROCKCHIP_RK3399=y +CONFIG_ROCKCHIP_SPL_RESERVE_IRAM=0x0 +CONFIG_TARGET_ROCKPRO64_RK3399=y +CONFIG_SPL_SPI_FLASH_SUPPORT=y +CONFIG_SPL_SPI_SUPPORT=y +CONFIG_SPL_STACK_R_ADDR=0x600000 +CONFIG_DEFAULT_DEVICE_TREE="rk3399-rockpi4b" +CONFIG_DEBUG_UART=y +CONFIG_FIT=y +CONFIG_SPL_LOAD_FIT=y +CONFIG_SPL_FIT_GENERATOR="board/rockchip/rockpro64_rk3399/mk_fit_atf.sh" +CONFIG_BOOTDELAY=2 +# CONFIG_DISPLAY_CPUINFO is not set +CONFIG_ANDROID_BOOTLOADER=y +CONFIG_SPL_BOOTROM_SUPPORT=y +CONFIG_SPL_STACK_R=y +CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x4000 +CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x200 +CONFIG_SPL_MTD_SUPPORT=y +CONFIG_SPL_ATF_SUPPORT=y +CONFIG_FASTBOOT_BUF_ADDR=0x00800800 +CONFIG_FASTBOOT_BUF_SIZE=0x08000000 +CONFIG_FASTBOOT_FLASH=y +CONFIG_FASTBOOT_FLASH_MMC_DEV=0 +CONFIG_CMD_BOOTZ=y +# CONFIG_CMD_IMLS is not set +CONFIG_CMD_MEMINFO=y +CONFIG_CMD_SHA1SUM=y +CONFIG_SHA1SUM_VERIFY=y +CONFIG_CMD_GPIO=y +CONFIG_CMD_GPT=y +CONFIG_CMD_LOAD_ANDROID=y +CONFIG_CMD_BOOT_ANDROID=y +CONFIG_CMD_MMC=y +CONFIG_CMD_SF=y +CONFIG_CMD_USB=y +CONFIG_CMD_USB_MASS_STORAGE=y +# CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_TIME=y +CONFIG_CMD_REGULATOR=y +CONFIG_CMD_MTDPARTS=y +CONFIG_SPL_OF_CONTROL=y +CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" +CONFIG_ENV_IS_IN_SPI_FLASH=y +CONFIG_SPL_DM_SEQ_ALIAS=y +CONFIG_REGMAP=y +CONFIG_SPL_REGMAP=y +CONFIG_SYSCON=y +CONFIG_SPL_SYSCON=y +CONFIG_CLK=y +CONFIG_SPL_CLK=y +CONFIG_ROCKCHIP_GPIO=y +CONFIG_SYS_I2C_ROCKCHIP=y +CONFIG_LED=y +CONFIG_LED_GPIO=y +CONFIG_MISC=y +CONFIG_ROCKCHIP_EFUSE=y +CONFIG_MMC_DW=y +CONFIG_MMC_DW_ROCKCHIP=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_ROCKCHIP=y +CONFIG_SPI_FLASH=y +CONFIG_SPI_FLASH_GIGADEVICE=y +CONFIG_SPI_FLASH_WINBOND=y +CONFIG_DM_ETH=y +CONFIG_ETH_DESIGNWARE=y +CONFIG_GMAC_ROCKCHIP=y +CONFIG_PINCTRL=y +CONFIG_SPL_PINCTRL=y +CONFIG_PINCTRL_ROCKCHIP_RK3399=y +CONFIG_DM_PMIC=y +CONFIG_PMIC_RK8XX=y +CONFIG_REGULATOR_PWM=y +CONFIG_DM_REGULATOR_FIXED=y +CONFIG_REGULATOR_RK8XX=y +CONFIG_PWM_ROCKCHIP=y +CONFIG_RAM=y +CONFIG_SPL_RAM=y +CONFIG_DM_RESET=y +CONFIG_BAUDRATE=1500000 +CONFIG_DEBUG_UART_BASE=0xFF1A0000 +CONFIG_DEBUG_UART_CLOCK=24000000 +CONFIG_DEBUG_UART_SHIFT=2 +CONFIG_SYS_NS16550=y +CONFIG_ROCKCHIP_SPI=y +CONFIG_SYSRESET=y +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_DWC3=y +CONFIG_USB_DWC3_GADGET=y +CONFIG_USB_STORAGE=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_DOWNLOAD=y +CONFIG_G_DNL_MANUFACTURER="Rockchip" +CONFIG_G_DNL_VENDOR_NUM=0x18d1 +CONFIG_G_DNL_PRODUCT_NUM=0xd00d +CONFIG_USB_HOST_ETHER=y +CONFIG_USB_ETHER_ASIX=y +CONFIG_USB_ETHER_ASIX88179=y +CONFIG_USB_ETHER_MCS7830=y +CONFIG_USB_ETHER_RTL8152=y +CONFIG_USB_ETHER_SMSC95XX=y +CONFIG_USE_TINY_PRINTF=y +CONFIG_ERRNO_STR=y diff --git a/configs/rockpro64-rk3399_defconfig b/configs/rockpro64-rk3399_defconfig new file mode 100644 index 00000000000..ac0cca784cb --- /dev/null +++ b/configs/rockpro64-rk3399_defconfig @@ -0,0 +1,113 @@ +CONFIG_ARM=y +CONFIG_ARCH_ROCKCHIP=y +CONFIG_SPL_LIBCOMMON_SUPPORT=y +CONFIG_SPL_LIBGENERIC_SUPPORT=y +CONFIG_SYS_MALLOC_F_LEN=0x4000 +CONFIG_ROCKCHIP_RK3399=y +CONFIG_ROCKCHIP_SPL_RESERVE_IRAM=0x0 +CONFIG_TARGET_ROCKPRO64_RK3399=y +CONFIG_SPL_SPI_FLASH_SUPPORT=y +CONFIG_SPL_SPI_SUPPORT=y +CONFIG_SPL_STACK_R_ADDR=0x600000 +CONFIG_DEFAULT_DEVICE_TREE="rk3399-rockpro64" +CONFIG_DEBUG_UART=y +CONFIG_FIT=y +CONFIG_SPL_LOAD_FIT=y +CONFIG_SPL_FIT_GENERATOR="board/rockchip/rockpro64_rk3399/mk_fit_atf.sh" +CONFIG_BOOTDELAY=0 +# CONFIG_DISPLAY_CPUINFO is not set +CONFIG_ANDROID_BOOTLOADER=y +CONFIG_SPL_BOOTROM_SUPPORT=y +CONFIG_SPL_STACK_R=y +CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x4000 +CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x200 +CONFIG_SPL_MTD_SUPPORT=y +CONFIG_SPL_ATF_SUPPORT=y +CONFIG_FASTBOOT_BUF_ADDR=0x00800800 +CONFIG_FASTBOOT_BUF_SIZE=0x08000000 +CONFIG_FASTBOOT_FLASH=y +CONFIG_FASTBOOT_FLASH_MMC_DEV=0 +CONFIG_CMD_BOOTZ=y +# CONFIG_CMD_IMLS is not set +CONFIG_CMD_MEMINFO=y +CONFIG_CMD_SHA1SUM=y +CONFIG_SHA1SUM_VERIFY=y +CONFIG_CMD_GPIO=y +CONFIG_CMD_GPT=y +CONFIG_CMD_I2C=y +CONFIG_CMD_LOAD_ANDROID=y +CONFIG_CMD_BOOT_ANDROID=y +CONFIG_CMD_MMC=y +CONFIG_CMD_SF=y +CONFIG_CMD_USB=y +CONFIG_CMD_USB_MASS_STORAGE=y +# CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_TIME=y +CONFIG_CMD_REGULATOR=y +CONFIG_CMD_MTDPARTS=y +CONFIG_SPL_OF_CONTROL=y +CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" +CONFIG_ENV_IS_IN_SPI_FLASH=y +CONFIG_SPL_DM_SEQ_ALIAS=y +CONFIG_REGMAP=y +CONFIG_SPL_REGMAP=y +CONFIG_SYSCON=y +CONFIG_SPL_SYSCON=y +CONFIG_CLK=y +CONFIG_SPL_CLK=y +CONFIG_ROCKCHIP_GPIO=y +CONFIG_SYS_I2C_ROCKCHIP=y +CONFIG_LED=y +CONFIG_LED_GPIO=y +CONFIG_MISC=y +CONFIG_ROCKCHIP_EFUSE=y +CONFIG_MMC_DW=y +CONFIG_MMC_DW_ROCKCHIP=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_ROCKCHIP=y +CONFIG_SPI_FLASH=y +CONFIG_SPI_FLASH_GIGADEVICE=y +CONFIG_SPI_FLASH_WINBOND=y +CONFIG_DM_ETH=y +CONFIG_ETH_DESIGNWARE=y +CONFIG_GMAC_ROCKCHIP=y +CONFIG_PINCTRL=y +CONFIG_SPL_PINCTRL=y +CONFIG_PINCTRL_ROCKCHIP_RK3399=y +CONFIG_DM_PMIC=y +CONFIG_PMIC_RK8XX=y +CONFIG_REGULATOR_PWM=y +CONFIG_DM_REGULATOR_FIXED=y +CONFIG_REGULATOR_RK8XX=y +CONFIG_PWM_ROCKCHIP=y +CONFIG_RAM=y +CONFIG_SPL_RAM=y +CONFIG_DM_RESET=y +CONFIG_BAUDRATE=1500000 +CONFIG_DEBUG_UART_BASE=0xFF1A0000 +CONFIG_DEBUG_UART_CLOCK=24000000 +CONFIG_DEBUG_UART_SHIFT=2 +CONFIG_SYS_NS16550=y +CONFIG_ROCKCHIP_SPI=y +CONFIG_SYSRESET=y +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_DWC3=y +CONFIG_USB_DWC3_GADGET=y +CONFIG_USB_STORAGE=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_DOWNLOAD=y +CONFIG_G_DNL_MANUFACTURER="Rockchip" +CONFIG_G_DNL_VENDOR_NUM=0x18d1 +CONFIG_G_DNL_PRODUCT_NUM=0xd00d +CONFIG_USB_HOST_ETHER=y +CONFIG_USB_ETHER_ASIX=y +CONFIG_USB_ETHER_ASIX88179=y +CONFIG_USB_ETHER_MCS7830=y +CONFIG_USB_ETHER_RTL8152=y +CONFIG_USB_ETHER_SMSC95XX=y +CONFIG_USE_TINY_PRINTF=y +CONFIG_ERRNO_STR=y diff --git a/configs/sheep-rk3368_defconfig b/configs/sheep-rk3368_defconfig index b862a147514..d4877d30c1c 100644 --- a/configs/sheep-rk3368_defconfig +++ b/configs/sheep-rk3368_defconfig @@ -10,6 +10,8 @@ CONFIG_ANDROID_BOOT_IMAGE=y CONFIG_CMD_MMC=y CONFIG_REGMAP=y CONFIG_SYSCON=y +CONFIG_ADC=y +CONFIG_SARADC_ROCKCHIP=y CONFIG_CLK=y CONFIG_MMC_DW=y CONFIG_MMC_DW_ROCKCHIP=y diff --git a/configs/tinker-rk3288_defconfig b/configs/tinker-rk3288_defconfig index 00e2d819543..e7eba10bc47 100644 --- a/configs/tinker-rk3288_defconfig +++ b/configs/tinker-rk3288_defconfig @@ -41,6 +41,8 @@ CONFIG_SPL_REGMAP=y CONFIG_SYSCON=y CONFIG_SPL_SYSCON=y # CONFIG_SPL_SIMPLE_BUS is not set +CONFIG_ADC=y +CONFIG_SARADC_ROCKCHIP=y CONFIG_CLK=y CONFIG_SPL_CLK=y CONFIG_ROCKCHIP_GPIO=y diff --git a/dev-ayufan/blobs/pinebookpro/erase-spi.cmd b/dev-ayufan/blobs/pinebookpro/erase-spi.cmd new file mode 100644 index 00000000000..4921013f078 --- /dev/null +++ b/dev-ayufan/blobs/pinebookpro/erase-spi.cmd @@ -0,0 +1,9 @@ +setenv blink_power 'led power off; sleep 0.1; led power on' + +# erase flash +run blink_power blink_power +sf probe +sf erase 0 400000 + +# blink forever +while true; do run blink_power; sleep 1; done diff --git a/dev-ayufan/blobs/pinebookpro/flash-spi.cmd b/dev-ayufan/blobs/pinebookpro/flash-spi.cmd new file mode 100644 index 00000000000..4f1728ace84 --- /dev/null +++ b/dev-ayufan/blobs/pinebookpro/flash-spi.cmd @@ -0,0 +1,28 @@ +setenv blink_power 'led power off; sleep 0.1; led power on' +setenv blink_standby 'led standby off; sleep 0.1; led standby on' + +# first read existing loader +run blink_power +sf probe + +# or load rkspi_loader.img and write it to 0 offset of spi +# or fail badly + +if size ${devtype} ${devnum}:${distro_bootpart} rkspi_loader.img; then + load ${devtype} ${devnum}:${distro_bootpart} ${kernel_addr_r} rkspi_loader.img + + # erase flash + run blink_power blink_power + sf erase 0 400000 + + # write flash + run blink_power blink_power blink_power + sf write ${kernel_addr_r} 0 ${filesize} + + # blink forever + while true; do run blink_power; sleep 1; done +else + # blink forever + echo "missing rkspi_loader.img" + while true; do run blink_standby; sleep 1; done +fi diff --git a/dev-ayufan/blobs/rock64/erase-spi.cmd b/dev-ayufan/blobs/rock64/erase-spi.cmd new file mode 100644 index 00000000000..4921013f078 --- /dev/null +++ b/dev-ayufan/blobs/rock64/erase-spi.cmd @@ -0,0 +1,9 @@ +setenv blink_power 'led power off; sleep 0.1; led power on' + +# erase flash +run blink_power blink_power +sf probe +sf erase 0 400000 + +# blink forever +while true; do run blink_power; sleep 1; done diff --git a/dev-ayufan/blobs/rock64/flash-spi.cmd b/dev-ayufan/blobs/rock64/flash-spi.cmd new file mode 100644 index 00000000000..856be70f222 --- /dev/null +++ b/dev-ayufan/blobs/rock64/flash-spi.cmd @@ -0,0 +1,28 @@ +setenv blink_power 'led power off; sleep 0.1; led power on' +setenv blink_standby 'led standby off; sleep 0.1; led standby on' + +# first read existing loader +run blink_power +sf probe + +# or load rksd_loader.img and write it to 8000 offset of spi +# or fail badly + +if size ${devtype} ${devnum}:${distro_bootpart} rksd_loader.img; then + load ${devtype} ${devnum}:${distro_bootpart} ${kernel_addr_r} rksd_loader.img + + # erase flash + run blink_power blink_power + sf erase 8000 3f8000 + + # write flash + run blink_power blink_power blink_power + sf write ${kernel_addr_r} 8000 ${filesize} + + # blink forever + while true; do run blink_power; sleep 1; done +else + # blink forever + echo "missing rksd_loader.img" + while true; do run blink_standby; sleep 1; done +fi diff --git a/dev-ayufan/blobs/rockpi4b/erase-spi.cmd b/dev-ayufan/blobs/rockpi4b/erase-spi.cmd new file mode 100644 index 00000000000..9ad0dd25e4d --- /dev/null +++ b/dev-ayufan/blobs/rockpi4b/erase-spi.cmd @@ -0,0 +1,9 @@ +setenv blink_power 'led status off; sleep 0.1; led status on' + +# erase flash +run blink_power blink_power +sf probe +sf erase 0 400000 + +# blink forever +while true; do run blink_power; sleep 1; done diff --git a/dev-ayufan/blobs/rockpi4b/flash-spi.cmd b/dev-ayufan/blobs/rockpi4b/flash-spi.cmd new file mode 100644 index 00000000000..b0c51693bdb --- /dev/null +++ b/dev-ayufan/blobs/rockpi4b/flash-spi.cmd @@ -0,0 +1,28 @@ +setenv blink_power 'led status off; sleep 0.1; led status on' +setenv blink_standby 'led status off; sleep 0.1; led status on' + +# first read existing loader +run blink_power +sf probe + +# or load rkspi_loader.img and write it to 0 offset of spi +# or fail badly + +if size ${devtype} ${devnum}:${distro_bootpart} rkspi_loader.img; then + load ${devtype} ${devnum}:${distro_bootpart} ${kernel_addr_r} rkspi_loader.img + + # erase flash + run blink_power blink_power + sf erase 0 400000 + + # write flash + run blink_power blink_power blink_power + sf write ${kernel_addr_r} 0 ${filesize} + + # blink forever + while true; do run blink_power; sleep 1; done +else + # blink forever + echo "missing rkspi_loader.img" + while true; do run blink_standby; sleep 1; done +fi diff --git a/dev-ayufan/blobs/rockpro64/erase-spi.cmd b/dev-ayufan/blobs/rockpro64/erase-spi.cmd new file mode 100644 index 00000000000..4921013f078 --- /dev/null +++ b/dev-ayufan/blobs/rockpro64/erase-spi.cmd @@ -0,0 +1,9 @@ +setenv blink_power 'led power off; sleep 0.1; led power on' + +# erase flash +run blink_power blink_power +sf probe +sf erase 0 400000 + +# blink forever +while true; do run blink_power; sleep 1; done diff --git a/dev-ayufan/blobs/rockpro64/flash-spi.cmd b/dev-ayufan/blobs/rockpro64/flash-spi.cmd new file mode 100644 index 00000000000..4f1728ace84 --- /dev/null +++ b/dev-ayufan/blobs/rockpro64/flash-spi.cmd @@ -0,0 +1,28 @@ +setenv blink_power 'led power off; sleep 0.1; led power on' +setenv blink_standby 'led standby off; sleep 0.1; led standby on' + +# first read existing loader +run blink_power +sf probe + +# or load rkspi_loader.img and write it to 0 offset of spi +# or fail badly + +if size ${devtype} ${devnum}:${distro_bootpart} rkspi_loader.img; then + load ${devtype} ${devnum}:${distro_bootpart} ${kernel_addr_r} rkspi_loader.img + + # erase flash + run blink_power blink_power + sf erase 0 400000 + + # write flash + run blink_power blink_power blink_power + sf write ${kernel_addr_r} 0 ${filesize} + + # blink forever + while true; do run blink_power; sleep 1; done +else + # blink forever + echo "missing rkspi_loader.img" + while true; do run blink_standby; sleep 1; done +fi diff --git a/dev-ayufan/boards.mk b/dev-ayufan/boards.mk new file mode 100644 index 00000000000..c1c18497000 --- /dev/null +++ b/dev-ayufan/boards.mk @@ -0,0 +1,50 @@ +ifeq (rock64,$(BOARD_TARGET)) + +UBOOT_DEFCONFIG ?= rock64-rk3328_defconfig +UBOOT_TPL ?= tmp/rkbin/rk33/rk3328_ddr_786MHz_v1.13.bin +BL31 ?= tmp/rkbin/rk33/rk3328_bl31_v1.39.bin +BOARD_CHIP ?= rk3328 +ifneq (,$(FLASH_SPI)) +LOADER_BIN ?= tmp/rkbin/rk33/rk3328_loader_v1.08.244_for_spi_nor_build_Aug_7_2017.bin +else +LOADER_BIN ?= tmp/rkbin/rk33/rk3328_loader_ddr333_v1.08.244.bin +endif +IMAGES ?= flash-spi erase-spi +LOADERS ?= rksd_loader + +else ifeq (rockpro64,$(BOARD_TARGET)) + +UBOOT_DEFCONFIG ?= rockpro64-rk3399_defconfig +UBOOT_TPL ?= tmp/rkbin/rk33/rk3399_ddr_933MHz_v1.19.bin +BL31 ?= tmp/rkbin/rk33/rk3399_bl31_v1.25.elf +BOARD_CHIP ?= rk3399 +LOADER_BIN ?= tmp/rkbin/rk33/rk3399_loader_v1.10.112_support_1CS.bin +USE_SEPARATE_SPIFLASH ?= true +IMAGES ?= flash-spi erase-spi +LOADERS ?= rksd_loader rkspi_loader + +else ifeq (rockpi4b,$(BOARD_TARGET)) + +UBOOT_DEFCONFIG ?= rockpi4b-rk3399_defconfig +UBOOT_TPL ?= tmp/rkbin/rk33/rk3399_ddr_933MHz_v1.19.bin +BL31 ?= tmp/rkbin/rk33/rk3399_bl31_v1.25.elf +BOARD_CHIP ?= rk3399 +LOADER_BIN ?= tmp/rkbin/rk33/rk3399_loader_v1.10.112_support_1CS.bin +USE_SEPARATE_SPIFLASH ?= true +IMAGES ?= flash-spi erase-spi +LOADERS ?= rksd_loader rkspi_loader + +else ifeq (pinebookpro,$(BOARD_TARGET)) + +UBOOT_DEFCONFIG ?= pinebook_pro-rk3399_defconfig +UBOOT_TPL ?= tmp/rkbin/rk33/rk3399_ddr_933MHz_v1.19.bin +BL31 ?= tmp/rkbin/rk33/rk3399_bl31_v1.25.elf +BOARD_CHIP ?= rk3399 +LOADER_BIN ?= tmp/rkbin/rk33/rk3399_loader_v1.10.112_support_1CS.bin +USE_SEPARATE_SPIFLASH ?= true +IMAGES ?= flash-spi erase-spi +LOADERS ?= rksd_loader rkspi_loader + +else +$(error Unsupported BOARD_TARGET) +endif diff --git a/dev-ayufan/build.mk b/dev-ayufan/build.mk new file mode 100644 index 00000000000..df7b8563fcb --- /dev/null +++ b/dev-ayufan/build.mk @@ -0,0 +1,56 @@ +UBOOT_TMP_DIR ?= $(CURDIR)/tmp/u-boot-$(BOARD_TARGET)-build +UBOOT_OUTPUT_DIR ?= $(CURDIR)/tmp/u-boot-$(BOARD_TARGET) +UBOOT_MAKE ?= make KBUILD_OUTPUT=$(UBOOT_OUTPUT_DIR) BL31=$(realpath $(BL31)) \ + CROSS_COMPILE="ccache aarch64-linux-gnu-" + +UBOOT_LOADERS ?= $(addprefix $(UBOOT_OUTPUT_DIR)/, $(addsuffix .img, $(LOADERS))) +UBOOT_TPL ?= $(UBOOT_OUTPUT_DIR)/tpl/u-boot-tpl.bin +UBOOT_SPL ?= $(UBOOT_OUTPUT_DIR)/spl/u-boot-spl.bin + +tmp/u-boot-$(BOARD_TARGET)/.config: configs/$(UBOOT_DEFCONFIG) + $(UBOOT_MAKE) $(UBOOT_DEFCONFIG) + +$(UBOOT_OUTPUT_DIR): + mkdir -p $@ + +$(UBOOT_OUTPUT_DIR)/u-boot.itb: .scmversion $(UBOOT_OUTPUT_DIR) tmp/u-boot-$(BOARD_TARGET)/.config $(BL31) + $(UBOOT_MAKE) -j $$(nproc) + $(UBOOT_MAKE) -j $$(nproc) u-boot.itb + +$(UBOOT_TPL) $(UBOOT_SPL): $(UBOOT_OUTPUT_DIR)/u-boot.itb + +$(UBOOT_OUTPUT_DIR)/rksd_loader.img: $(UBOOT_OUTPUT_DIR)/u-boot.itb $(UBOOT_TPL) $(UBOOT_SPL) + $(UBOOT_OUTPUT_DIR)/tools/mkimage -n $(BOARD_CHIP) -T rksd -d $(word 1,$(UBOOT_TPL) $(UBOOT_SPL)) $@.tmp +ifneq (,$(UBOOT_TPL)) + cat $(UBOOT_SPL) >> $@.tmp +endif + dd if=$(UBOOT_OUTPUT_DIR)/u-boot.itb of=$@.tmp seek=$$((0x200-64)) conv=notrunc + mv $@.tmp $@ + +$(UBOOT_OUTPUT_DIR)/rkspi_loader.img: $(UBOOT_OUTPUT_DIR)/u-boot.itb $(UBOOT_TPL) $(UBOOT_SPL) + $(UBOOT_OUTPUT_DIR)/tools/mkimage -n $(BOARD_CHIP) -T rksd -d $(word 1,$(UBOOT_TPL) $(UBOOT_SPL)) $@.tmp +ifneq (,$(UBOOT_TPL)) + cat $(UBOOT_SPL) >> $@.tmp +endif + # pad every 2k with 2k of zeros + for i in $$(seq 1 128); do dd count=4 status=none; dd if=/dev/zero count=4 status=none; done < $@.tmp > $@.tmp2 + mv $@.tmp2 $@.tmp + dd if=$(UBOOT_OUTPUT_DIR)/u-boot.itb of=$@.tmp seek=$$((0x400)) conv=notrunc + mv $@.tmp $@ + +.PHONY: u-boot-menuconfig # edit u-boot config and save as defconfig +u-boot-menuconfig: + $(UBOOT_MAKE) ARCH=arm64 $(UBOOT_DEFCONFIG) + $(UBOOT_MAKE) ARCH=arm64 menuconfig + $(UBOOT_MAKE) ARCH=arm64 savedefconfig + mv $(UBOOT_OUTPUT_DIR)/defconfig configs/$(UBOOT_DEFCONFIG) + +.PHONY: u-boot-build # compile u-boot +u-boot-build: $(UBOOT_LOADERS) + +.PHONY: u-boot-clear +u-boot-clear: + rm -rf $(UBOOT_OUTPUT_DIR) + rm -rf $(UBOOT_TMP_DIR) + +all: u-boot-build diff --git a/dev-ayufan/images.mk b/dev-ayufan/images.mk new file mode 100644 index 00000000000..4137b9cbbf1 --- /dev/null +++ b/dev-ayufan/images.mk @@ -0,0 +1,27 @@ +$(UBOOT_OUTPUT_DIR)/%/boot.scr: dev-ayufan/blobs/$(BOARD_TARGET)/%.cmd + mkdir -p $$(dirname $@) + mkimage -C none -A arm -T script -d $< $@ + +$(UBOOT_OUTPUT_DIR)/%/boot.img: $(UBOOT_OUTPUT_DIR)/%/boot.scr $(UBOOT_LOADERS) + dd if=/dev/zero of=$@.tmp bs=1M count=32 + mkfs.vfat -n "u-boot-script" $@.tmp + mcopy -sm -i $@.tmp $^ :: + mv $@.tmp $@ + +u-boot-%-$(BOARD_TARGET).img: $(UBOOT_OUTPUT_DIR)/%/boot.img $(UBOOT_LOADERS) + dd if=/dev/zero of=$@.tmp bs=1M count=16 + parted -s $@.tmp mklabel gpt + parted -s $@.tmp unit s mkpart bootloader 64 8127 + parted -s $@.tmp unit s mkpart boot fat16 8192 100% + parted -s $@.tmp set 2 legacy_boot on + dd if=$(word 2,$^) of=$@.tmp conv=notrunc seek=64 + dd if=$(word 1,$^) of=$@.tmp conv=notrunc seek=8192 + mv "$@.tmp" $@ + +u-boot-%-$(BOARD_TARGET).img.xz: u-boot-%-$(BOARD_TARGET).img + xz -f $< + +.PHONY: u-boot-images +u-boot-images: $(addprefix u-boot-, $(addsuffix -$(BOARD_TARGET).img.xz, $(IMAGES))) + +all: u-boot-images diff --git a/dev-ayufan/package.mk b/dev-ayufan/package.mk new file mode 100644 index 00000000000..58e3ae088b8 --- /dev/null +++ b/dev-ayufan/package.mk @@ -0,0 +1,24 @@ +.PHONY: u-boot-package +u-boot-package: $(UBOOT_LOADERS) + fpm -s dir -t deb -n u-boot-rockchip-$(BOARD_TARGET)-$(RELEASE_NAME) -v $(RELEASE_NAME) \ + -p u-boot-rockchip-$(BOARD_TARGET)-$(RELEASE_NAME).deb \ + --deb-priority optional --category admin \ + --force \ + --depends debsums \ + --depends mtd-utils \ + --deb-field "Multi-Arch: foreign" \ + --deb-field "Replaces: u-boot-virtual, u-boot-rockchip, u-boot-$(BOARD_TARGET), u-boot-rockchip-$(BOARD_TARGET)" \ + --deb-field "Conflicts: u-boot-virtual, u-boot-rockchip, u-boot-$(BOARD_TARGET), u-boot-rockchip-$(BOARD_TARGET)" \ + --deb-field "Provides: u-boot-virtual, u-boot-rockchip, u-boot-$(BOARD_TARGET), u-boot-rockchip-$(BOARD_TARGET)" \ + --after-install dev-ayufan/scripts/postinst.deb \ + --before-remove dev-ayufan/scripts/prerm.deb \ + --url https://gitlab.com/ayufan-rock64/linux-build \ + --description "Rock64 U-boot package" \ + -m "Kamil TrzciÅ„ski " \ + --license "MIT" \ + --vendor "Kamil TrzciÅ„ski" \ + -a all \ + dev-ayufan/root/=/ \ + $(addsuffix =/usr/lib/u-boot-$(BOARD_TARGET)/,$(UBOOT_LOADERS)) + +all: u-boot-package diff --git a/dev-ayufan/rockchip.mk b/dev-ayufan/rockchip.mk new file mode 100644 index 00000000000..43ece80b65f --- /dev/null +++ b/dev-ayufan/rockchip.mk @@ -0,0 +1,45 @@ +.PHONY: loader-download-mode +loader-download-mode: $(LOADER_BIN) + rkdeveloptool db $(LOADER_BIN) + sleep 1s + +.PHONY: loader-boot # boot loader over USB +loader-boot: $(UBOOT_LOADERS) $(UBOOT_TPL) $(UBOOT_SPL) + ./dev-make loader-download-mode + rkdeveloptool rid + dd if=/dev/zero of=$(UBOOT_OUTPUT_DIR)/clear.img count=1 + rkdeveloptool wl 64 $(UBOOT_OUTPUT_DIR)/clear.img + rkdeveloptool wl 512 $(UBOOT_OUTPUT_DIR)/u-boot.itb + +ifeq (rk3399,$(BOARD_CHIP)) + @echo Restart device and press ENTER + @read XX + sleep 3s +else + rkdeveloptool rd + sleep 1s +endif + +ifneq (,$(UBOOT_TPL)) + cat $(UBOOT_TPL) | openssl rc4 -K 7c4e0304550509072d2c7b38170d1711 | rkflashtool l +endif +ifneq (,$(UBOOT_SPL)) + cat $(UBOOT_SPL) | openssl rc4 -K 7c4e0304550509072d2c7b38170d1711 | rkflashtool L +endif + +.PHONY: loader-flash # flash loader to the device +loader-flash: $(UBOOT_LOADERS) + ./dev-make loader-download-mode + sleep 1s + rkdeveloptool rid + rkdeveloptool wl 64 $< + rkdeveloptool rd + +.PHONY: loader-wipe # clear loader +loader-wipe: + dd if=/dev/zero of=$(UBOOT_OUTPUT_DIR)/clear.img count=1 + ./dev-make loader-download-mode + sleep 1s + rkdeveloptool rid + rkdeveloptool wl 64 $(UBOOT_OUTPUT_DIR)/clear.img + rkdeveloptool rd diff --git a/dev-ayufan/root/usr/local/lib/u-boot-rockchip/loader-common b/dev-ayufan/root/usr/local/lib/u-boot-rockchip/loader-common new file mode 100644 index 00000000000..1f2a772da68 --- /dev/null +++ b/dev-ayufan/root/usr/local/lib/u-boot-rockchip/loader-common @@ -0,0 +1,94 @@ +#!/bin/bash + +if [[ "$(id -u)" -ne "0" ]]; then + echo "This script requires root." + exit 1 +fi + +if ! which nandwrite &>/dev/null; then + echo "Install mtd-utils with 'apt-get install mtd-utils'" + exit 1 +fi + +if ! which flash_erase &>/dev/null; then + echo "Install mtd-utils with 'apt-get install mtd-utils'" + exit 1 +fi + +if ! PACKAGE_NAME=$(dpkg -S "$0" | cut -d: -f1); then + exit "Unknown package installed." + exit 1 +fi + +if ! debsums -s "${PACKAGE_NAME}"; then + echo "Verification of '${PACKAGE_NAME}' failed." + echo "Your disk might have got corrupted." + if [[ -z "IGNORE_VERIFICATION" ]]; then + echo "Use 'export IGNORE_VERIFICATION=1'" + exit 1 + fi +fi + +case "$PACKAGE_NAME" in + *-rockchip-rock64-*) + SD_LOADER=/usr/lib/u-boot-rock64/rksd_loader.img + SPI_LOADER=/usr/lib/u-boot-rock64/rksd_loader.img + BOARD=rock64 + ;; + + *-rockchip-rockpro64-*) + SD_LOADER=/usr/lib/u-boot-rockpro64/rksd_loader.img + SPI_LOADER=/usr/lib/u-boot-rockpro64/rkspi_loader.img + BOARD=rockpro64 + ;; + + *-rockchip-pinebookpro-*) + SD_LOADER=/usr/lib/u-boot-pinebookpro/rksd_loader.img + SPI_LOADER=/usr/lib/u-boot-pinebookpro/rkspi_loader.img + BOARD=pinebookpro + ;; + + *-rockchip-rockpi4b-*) + SD_LOADER=/usr/lib/u-boot-rockpi4b/rksd_loader.img + SPI_LOADER=/usr/lib/u-boot-rockpi4b/rkspi_loader.img + BOARD=rockpi4b + ;; + + *) + echo "Cannot detect board from $PACKAGE_NAME." + exit 1 + ;; +esac + +if ! grep -qi "$BOARD" /proc/device-tree/compatible; then + echo "You are currently running on different board:" + echo "$(cat /proc/device-tree/model || true)" + echo "It may brick your device or the system unless" + echo "you know what are you doing." + echo "" +fi + +confirm() { + while true; do + echo "Type YES to continue or Ctrl-C to abort." + read CONFIRM + if [[ "$CONFIRM" == "YES" ]]; then + break + fi + done +} + +version() { + local DEVICE="${1/p6/p1}" + + echo -n "Current version: " + if strings "$DEVICE" | grep "^U-Boot [a-z0-9.-]*$"; then + echo -n "Board: " + strings "$DEVICE" | grep -E "^board=" + echo -n "FDT: " + strings "$DEVICE" | grep -E "^fdtfile=" + else + echo "not installed on $DEVICE." + fi + echo +} diff --git a/dev-ayufan/root/usr/local/sbin/rock64_erase_bootloader.sh b/dev-ayufan/root/usr/local/sbin/rock64_erase_bootloader.sh new file mode 100755 index 00000000000..af3537680ca --- /dev/null +++ b/dev-ayufan/root/usr/local/sbin/rock64_erase_bootloader.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +set -eo pipefail + +source /usr/local/lib/u-boot-rockchip/loader-common + +echo "Doing this will erase bootloader stored on your boot device" +echo " and it might break your system." +echo "Use this only if you prefer to boot from SPI ('rock64_write_spi_flash.sh')." +echo "To bring back bootloader run 'rock64_upgrade_bootloader.sh'." +echo "" + +MNT_DEV=$(findmnt /boot/efi -n -o SOURCE) + +version "$MNT_DEV" +confirm + +write_sd() { + case "$1" in + /dev/mmcblk*p6|/dev/sd*p6|/dev/mapper/loop*p6|/dev/mapper/nvme*p6) + dd if="$2" of="${1/p6/p1}" + ;; + + *) + echo "Cannot detect boot device ($MNT_DEV)." + exit 1 + ;; + esac +} + +write_sd "$MNT_DEV" "/dev/zero" + +sync + +echo Done. diff --git a/dev-ayufan/root/usr/local/sbin/rock64_erase_spi_flash.sh b/dev-ayufan/root/usr/local/sbin/rock64_erase_spi_flash.sh new file mode 100755 index 00000000000..8b66410d047 --- /dev/null +++ b/dev-ayufan/root/usr/local/sbin/rock64_erase_spi_flash.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +set -eo pipefail + +source /usr/local/lib/u-boot-rockchip/loader-common + +echo "Doing this will overwrite data stored on SPI Flash" +echo " and it will require that you use eMMC or SD" +echo " as your boot device." +echo "" + +if ! MTD=$(grep \"loader\" /proc/mtd | cut -d: -f1); then + echo "loader partition on MTD is not found" + return 1 +fi + +version "/dev/${MTD/mtd/mtdblock}" +confirm + +flash_erase "/dev/$MTD" 0 0 + +echo Done. diff --git a/dev-ayufan/root/usr/local/sbin/rock64_upgrade_bootloader.sh b/dev-ayufan/root/usr/local/sbin/rock64_upgrade_bootloader.sh new file mode 100755 index 00000000000..19b7041ffc9 --- /dev/null +++ b/dev-ayufan/root/usr/local/sbin/rock64_upgrade_bootloader.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +set -eo pipefail + +source /usr/local/lib/u-boot-rockchip/loader-common + +echo "Doing this will overwrite bootloader stored on your boot device it might break your system." +echo "If this happens you will have to manually fix that outside of your Rock64." +echo "If you are booting from SPI. You have to use 'rock64_write_spi_flash.sh'." +echo "" + +MNT_DEV=$(findmnt /boot/efi -n -o SOURCE) + +version "$MNT_DEV" +confirm + +write_sd() { + case "$1" in + /dev/mmcblk*p6|/dev/sd*p6|/dev/mapper/loop*p6|/dev/mapper/nvme*p6) + dd if="$2" of="${1/p6/p1}" + ;; + + *) + echo "Cannot detect boot device ($MNT_DEV)." + exit 1 + ;; + esac +} + +write_sd "$MNT_DEV" "$SD_LOADER" + +sync + +echo Done. diff --git a/dev-ayufan/root/usr/local/sbin/rock64_write_spi_flash.sh b/dev-ayufan/root/usr/local/sbin/rock64_write_spi_flash.sh new file mode 100755 index 00000000000..e56d6863d9b --- /dev/null +++ b/dev-ayufan/root/usr/local/sbin/rock64_write_spi_flash.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +set -eo pipefail + +source /usr/local/lib/u-boot-rockchip/loader-common + +echo "Doing this will overwrite data stored on SPI Flash" +echo " and it will require that you use eMMC or SD" +echo " as your boot device." +echo "" + +if ! MTD=$(grep \"loader\" /proc/mtd | cut -d: -f1); then + echo "loader partition on MTD is not found" + exit 1 +fi + +version "/dev/${MTD/mtd/mtdblock}" +confirm + +write_nand() { + echo "Writing /dev/$MTD with content of $2" + flash_erase "/dev/$MTD" 0 0 + nandwrite "/dev/$MTD" < "$2" +} + +write_nand loader "$SPI_LOADER" + +echo Done. diff --git a/dev-ayufan/scripts/postinst.deb b/dev-ayufan/scripts/postinst.deb new file mode 100755 index 00000000000..1da0a85286d --- /dev/null +++ b/dev-ayufan/scripts/postinst.deb @@ -0,0 +1,19 @@ +#!/bin/bash + +set -e + +case "$1" in + abort-upgrade|abort-remove|abort-deconfigure) + ;; + + configure) + echo "Consider upgrading device bootloader with 'rock64_upgrade_bootloader.sh'." + ;; + + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/dev-ayufan/scripts/prerm.deb b/dev-ayufan/scripts/prerm.deb new file mode 100755 index 00000000000..1a2485251c3 --- /dev/null +++ b/dev-ayufan/scripts/prerm.deb @@ -0,0 +1 @@ +#!/bin/sh diff --git a/dev-make b/dev-make new file mode 100755 index 00000000000..efd829a9c81 --- /dev/null +++ b/dev-make @@ -0,0 +1,3 @@ +#!/bin/bash + +exec make -f dev.mk "$@" diff --git a/dev-shell b/dev-shell new file mode 100755 index 00000000000..188e73931fb --- /dev/null +++ b/dev-shell @@ -0,0 +1,21 @@ +#!/bin/bash + +CURDIR="$PWD" + +exec docker run \ + --rm \ + -it \ + -e HOME -v "${HOME}:${HOME}" \ + -e USER \ + -u "$(id -u):$(id -g)" \ + $(id -Gz | xargs -0 -n1 -I{} echo "--group-add={}") \ + -v /etc/passwd:/etc/passwd:ro \ + -v /dev/bus/usb:/dev/bus/usb \ + -v "${SSH_AUTH_SOCK}:${SSH_AUTH_SOCK}" \ + -e SSH_AUTH_SOCK \ + --privileged \ + -h rock64-build-env \ + -v "${CURDIR}:${CURDIR}" \ + -w "${CURDIR}" \ + ayufan/rock64-dockerfiles:x86_64 \ + "$@" diff --git a/dev.mk b/dev.mk new file mode 100644 index 00000000000..aa4fcceaa4e --- /dev/null +++ b/dev.mk @@ -0,0 +1,28 @@ +export RELEASE ?= 1 + +all: + +include dev-ayufan/boards.mk +include dev-ayufan/build.mk +include dev-ayufan/images.mk +include dev-ayufan/package.mk +include dev-ayufan/rockchip.mk + +RELEASE_NAME ?= $(shell $(UBOOT_MAKE) -s ubootrelease) + +.PHONY: .scmversion +.scmversion: + @echo "-rockchip-ayufan-$(RELEASE)-g$$(git rev-parse --short HEAD)" > .scmversion + +version: .scmversion + @echo $(RELEASE_NAME) + +$(filter tmp/rkbin/%, $(BL31) $(UBOOT_TPL) $(UBOOT_SPL) $(LOADER_BIN)): + mkdir -p $$(dirname "$@") + curl --fail -L https://github.com/ayufan-rock64/rkbin/raw/master/$(subst tmp/rkbin/,,$@) > $@.tmp + mv $@.tmp $@ + +deploy: u-boot-package + scp u-boot-rockchip-$(BOARD_TARGET)-$(RELEASE_NAME).deb root@$(TARGET_HOST): + ssh root@$(TARGET_HOST) apt install ./u-boot-rockchip-$(BOARD_TARGET)-$(RELEASE_NAME).deb + ssh root@$(TARGET_HOST) rock64_upgrade_bootloader.sh diff --git a/disk/part_dos.c b/disk/part_dos.c index 7ede15ec261..850a538e836 100644 --- a/disk/part_dos.c +++ b/disk/part_dos.c @@ -89,14 +89,20 @@ static int test_block_type(unsigned char *buffer) static int part_test_dos(struct blk_desc *dev_desc) { - ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, dev_desc->blksz); + ALLOC_CACHE_ALIGN_BUFFER(legacy_mbr, mbr, dev_desc->blksz); - if (blk_dread(dev_desc, 0, 1, (ulong *)buffer) != 1) + if (blk_dread(dev_desc, 0, 1, (ulong *)mbr) != 1) return -1; - if (test_block_type(buffer) != DOS_MBR) + if (test_block_type((unsigned char *)mbr) != DOS_MBR) return -1; + if (dev_desc->sig_type == SIG_TYPE_NONE && + mbr->unique_mbr_signature != 0) { + dev_desc->sig_type = SIG_TYPE_MBR; + dev_desc->mbr_sig = mbr->unique_mbr_signature; + } + return 0; } diff --git a/disk/part_efi.c b/disk/part_efi.c index b43b8b3d19c..58bb3d56278 100644 --- a/disk/part_efi.c +++ b/disk/part_efi.c @@ -931,11 +931,19 @@ static int is_pmbr_valid(legacy_mbr * mbr) static int is_gpt_valid(struct blk_desc *dev_desc, u64 lba, gpt_header *pgpt_head, gpt_entry **pgpt_pte) { + ALLOC_CACHE_ALIGN_BUFFER(legacy_mbr, mbr, dev_desc->blksz); + if (!dev_desc || !pgpt_head) { printf("%s: Invalid Argument(s)\n", __func__); return 0; } + /* Read MBR Header from device */ + if (blk_dread(dev_desc, 0, 1, (ulong *)mbr) != 1) { + printf("*** ERROR: Can't read MBR header ***\n"); + return 0; + } + /* Read GPT Header from device */ if (blk_dread(dev_desc, (lbaint_t)lba, 1, pgpt_head) != 1) { printf("*** ERROR: Can't read GPT header ***\n"); @@ -945,6 +953,18 @@ static int is_gpt_valid(struct blk_desc *dev_desc, u64 lba, if (validate_gpt_header(pgpt_head, (lbaint_t)lba, dev_desc->lba)) return 0; + if (dev_desc->sig_type == SIG_TYPE_NONE) { + efi_guid_t empty = {}; + if (memcmp(&pgpt_head->disk_guid, &empty, sizeof(empty))) { + dev_desc->sig_type = SIG_TYPE_GUID; + memcpy(&dev_desc->guid_sig, &pgpt_head->disk_guid, + sizeof(empty)); + } else if (mbr->unique_mbr_signature != 0) { + dev_desc->sig_type = SIG_TYPE_MBR; + dev_desc->mbr_sig = mbr->unique_mbr_signature; + } + } + /* Read and allocate Partition Table Entries */ *pgpt_pte = alloc_read_gpt_entries(dev_desc, pgpt_head); if (*pgpt_pte == NULL) { diff --git a/drivers/clk/rockchip/clk_rk3328.c b/drivers/clk/rockchip/clk_rk3328.c index db79ffe3bd8..8438047b219 100644 --- a/drivers/clk/rockchip/clk_rk3328.c +++ b/drivers/clk/rockchip/clk_rk3328.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -475,7 +476,30 @@ static ulong rk3328_pwm_set_clk(struct rk3328_cru *cru, uint hz) rk_clrsetreg(&cru->clksel_con[24], CLK_PWM_PLL_SEL_MASK | CLK_PWM_DIV_CON_MASK, CLK_PWM_PLL_SEL_GPLL << CLK_PWM_PLL_SEL_SHIFT | - (div - 1) << CLK_PWM_DIV_CON_SHIFT); + (div - 1) << CLK_PWM_DIV_CON_SHIFT); + + return DIV_TO_RATE(GPLL_HZ, div); +} + +static ulong rk3328_spi_get_clk(struct rk3328_cru *cru) +{ + u32 div, con; + + con = readl(&cru->clksel_con[24]); + div = (con & CLK_SPI_DIV_CON_MASK) >> CLK_SPI_DIV_CON_SHIFT; + + return DIV_TO_RATE(GPLL_HZ, div); +} + +static ulong rk3328_spi_set_clk(struct rk3328_cru *cru, + ulong clk_id, ulong hz) +{ + u32 div = GPLL_HZ / hz; + + rk_clrsetreg(&cru->clksel_con[24], + CLK_PWM_PLL_SEL_MASK | CLK_PWM_DIV_CON_MASK, + CLK_PWM_PLL_SEL_GPLL << CLK_PWM_PLL_SEL_SHIFT | + (div - 1) << CLK_PWM_DIV_CON_SHIFT); return DIV_TO_RATE(GPLL_HZ, div); } @@ -505,6 +529,30 @@ static ulong rk3328_saradc_set_clk(struct rk3328_cru *cru, uint hz) return rk3328_saradc_get_clk(cru); } +#if CONFIG_IS_ENABLED(GMAC_ROCKCHIP) +static ulong rk3328_gmac_set_clk(struct rk3328_cru *cru, + ulong clk_id, ulong set_rate) +{ + struct rk3328_grf_regs *grf; + grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); + + switch (clk_id) { + case SCLK_MAC2IO: + rk_clrsetreg(&grf->mac_con[1], BIT(10), BIT(10)); + break; + + case SCLK_MAC2IO_EXT: + rk_clrsetreg(&grf->soc_con[4], BIT(14), BIT(14)); + break; + + default: + return -EINVAL; + } + + return set_rate; +} +#endif + static ulong rk3328_clk_get_rate(struct clk *clk) { struct rk3328_clk_priv *priv = dev_get_priv(clk->dev); @@ -531,6 +579,9 @@ static ulong rk3328_clk_get_rate(struct clk *clk) case SCLK_SARADC: rate = rk3328_saradc_get_clk(priv->cru); break; + case SCLK_SPI: + rate = rk3328_spi_get_clk(priv->cru); + break; default: return -ENOENT; } @@ -558,12 +609,21 @@ static ulong rk3328_clk_set_rate(struct clk *clk, ulong rate) case SCLK_I2C3: ret = rk3328_i2c_set_clk(priv->cru, clk->id, rate); break; + case SCLK_SPI: + ret = rk3328_spi_set_clk(priv->cru, clk->id, rate); + break; case SCLK_PWM: ret = rk3328_pwm_set_clk(priv->cru, rate); break; case SCLK_SARADC: ret = rk3328_saradc_set_clk(priv->cru, rate); break; +#if CONFIG_IS_ENABLED(GMAC_ROCKCHIP) + case SCLK_MAC2IO: + case SCLK_MAC2IO_EXT: + ret = rk3328_gmac_set_clk(priv->cru, clk->id, rate); + break; +#endif default: return -ENOENT; } diff --git a/drivers/misc/rockchip-efuse.c b/drivers/misc/rockchip-efuse.c index b4ad19cfe8c..81b78f9b2c5 100644 --- a/drivers/misc/rockchip-efuse.c +++ b/drivers/misc/rockchip-efuse.c @@ -16,6 +16,14 @@ #include #include +#define RK3328_INT_CON 0x0014 +#define RK3328_INT_STATUS 0x0018 +#define RK3328_DOUT 0x0020 +#define RK3328_AUTO_CTRL 0x0024 +#define RK3328_INT_FINISH BIT(0) +#define RK3328_AUTO_ENB BIT(0) +#define RK3328_AUTO_RD BIT(1) + #define RK3399_A_SHIFT 16 #define RK3399_A_MASK 0x3ff #define RK3399_NFUSES 32 @@ -95,6 +103,49 @@ U_BOOT_CMD( ); #endif +static int rockchip_rk3328_efuse_read(struct udevice *dev, int offset, + void *buf, int size) +{ + struct rockchip_efuse_platdata *plat = dev_get_platdata(dev); + + unsigned int addr_start, addr_end, addr_offset; + u32 out_value, status; + u8 bytes[RK3399_NFUSES * RK3399_BYTES_PER_FUSE]; + int i = 0; + u32 addr; + + /* 128 Byte efuse, 96 Byte for secure, 32 Byte for non-secure */ + offset += 96; + + addr_start = offset / RK3399_BYTES_PER_FUSE; + addr_offset = offset % RK3399_BYTES_PER_FUSE; + addr_end = DIV_ROUND_UP(offset + size, RK3399_BYTES_PER_FUSE); + + /* cap to the size of the efuse block */ + if (addr_end > RK3399_NFUSES) + addr_end = RK3399_NFUSES; + + for (addr = addr_start; addr < addr_end; addr++) { + writel(RK3328_AUTO_RD | RK3328_AUTO_ENB | + ((addr & RK3399_A_MASK) << RK3399_A_SHIFT), + plat->base + RK3328_AUTO_CTRL); + udelay(10); + status = readl(plat->base + RK3328_INT_STATUS); + if (!(status & RK3328_INT_FINISH)) { + return -EIO; + } + out_value = readl(plat->base + RK3328_DOUT); + writel(RK3328_INT_FINISH, plat->base + RK3328_INT_STATUS); + + memcpy(&bytes[i], &out_value, RK3399_BYTES_PER_FUSE); + i += RK3399_BYTES_PER_FUSE; + } + + memcpy(buf, bytes + addr_offset, size); + + return 0; +} + static int rockchip_rk3399_efuse_read(struct udevice *dev, int offset, void *buf, int size) { @@ -223,6 +274,10 @@ static const struct udevice_id rockchip_efuse_ids[] = { .compatible = "rockchip,rk322x-efuse", .data = (ulong)&rockchip_rk3288_efuse_read, }, + { + .compatible = "rockchip,rk3328-efuse", + .data = (ulong)rockchip_rk3328_efuse_read, + }, { .compatible = "rockchip,rk3399-efuse", .data = (ulong)&rockchip_rk3399_efuse_read, diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index 6de927b8c6c..8fbeaa740d6 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -33,6 +33,15 @@ config SPL_DM_MMC if MMC +config ARM_PL180_MMCI + bool "ARM AMBA Multimedia Card Interface and compatible support" + depends on DM_MMC && OF_CONTROL + help + This selects the ARM(R) AMBA(R) PrimeCell Multimedia Card + Interface (PL180, PL181 and compatible) support. + If you have an ARM(R) platform with a Multimedia Card slot, + say Y or M here. + config SPL_MMC_TINY bool "Tiny MMC framework in SPL" help @@ -136,6 +145,7 @@ config MMC_PCI config MMC_OMAP_HS bool "TI OMAP High Speed Multimedia Card Interface support" select DM_REGULATOR_PBIAS if DM_MMC && DM_REGULATOR + select DM_REGULATOR_PBIAS if DM_MMC && DM_REGULATOR help This selects the TI OMAP High Speed Multimedia card Interface. If you have an omap2plus board with a Multimedia Card slot, @@ -162,12 +172,13 @@ config SH_SDHI Support for the on-chip SDHI host controller on SuperH/Renesas ARM SoCs platform config MMC_UNIPHIER - bool "UniPhier SD/MMC Host Controller support" - depends on ARCH_UNIPHIER + bool "UniPhier/RCar SD/MMC Host Controller support" + depends on ARCH_UNIPHIER || ARCH_RMOBILE depends on BLK && DM_MMC depends on OF_CONTROL help - This selects support for the SD/MMC Host Controller on UniPhier SoCs. + This selects support for the Matsushita SD/MMC Host Controller on + SocioNext UniPhier and Renesas RCar SoCs. config MMC_SANDBOX bool "Sandbox MMC support" @@ -382,6 +393,26 @@ config GENERIC_ATMEL_MCI the SD Memory Card Specification V2.0, the SDIO V2.0 specification and CE-ATA V1.1. +config STM32_SDMMC2 + bool "STMicroelectronics STM32H7 SD/MMC Host Controller support" + depends on DM_MMC && BLK && OF_CONTROL + help + This selects support for the SD/MMC controller on STM32H7 SoCs. + If you have a board based on such a SoC and with a SD/MMC slot, + say Y or M here. + +config MMC_NDS32 + bool "Andestech SD/MMC controller support" + depends on DM_MMC && OF_CONTROL && BLK && FTSDC010 + help + This enables support for the Andestech SD/MMM controller, which is + based on Faraday IP. + +config FTSDC010 + bool "Ftsdc010 SD/MMC controller Support" + help + This SD/MMC controller is present in Andestech SoCs which is based on Faraday IP. + endif config TEGRA124_MMC_DISABLE_EXT_LOOPBACK diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index a6becb23090..9af375b044a 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -43,6 +43,8 @@ obj-$(CONFIG_SUPPORT_EMMC_RPMB) += rpmb.o obj-$(CONFIG_MMC_SANDBOX) += sandbox_mmc.o obj-$(CONFIG_SH_MMCIF) += sh_mmcif.o obj-$(CONFIG_SH_SDHI) += sh_sdhi.o +obj-$(CONFIG_STM32_SDMMC2) += stm32_sdmmc2.o +obj-$(CONFIG_MMC_NDS32) += nds32_mmc.o # SDHCI obj-$(CONFIG_MMC_SDHCI) += sdhci.o diff --git a/drivers/mmc/arm_pl180_mmci.c b/drivers/mmc/arm_pl180_mmci.c index ddf8383f1c6..89a7c192424 100644 --- a/drivers/mmc/arm_pl180_mmci.c +++ b/drivers/mmc/arm_pl180_mmci.c @@ -12,12 +12,29 @@ /* #define DEBUG */ -#include #include "common.h" +#include #include +#include #include + +#include +#include + #include "arm_pl180_mmci.h" -#include + +#ifdef CONFIG_DM_MMC +#include +DECLARE_GLOBAL_DATA_PTR; + +#define MMC_CLOCK_MAX 48000000 +#define MMC_CLOCK_MIN 400000 + +struct arm_pl180_mmc_plat { + struct mmc_config cfg; + struct mmc mmc; +}; +#endif static int wait_for_command_end(struct mmc *dev, struct mmc_cmd *cmd) { @@ -265,16 +282,6 @@ static int host_request(struct mmc *dev, return result; } -/* MMC uses open drain drivers in the enumeration phase */ -static int mmc_host_reset(struct mmc *dev) -{ - struct pl180_mmc_host *host = dev->priv; - - writel(host->pwr_init, &host->base->power); - - return 0; -} - static int host_set_ios(struct mmc *dev) { struct pl180_mmc_host *host = dev->priv; @@ -337,20 +344,31 @@ static int host_set_ios(struct mmc *dev) return 0; } +#ifndef CONFIG_DM_MMC +/* MMC uses open drain drivers in the enumeration phase */ +static int mmc_host_reset(struct mmc *dev) +{ + struct pl180_mmc_host *host = dev->priv; + + writel(host->pwr_init, &host->base->power); + + return 0; +} + static const struct mmc_ops arm_pl180_mmci_ops = { .send_cmd = host_request, .set_ios = host_set_ios, .init = mmc_host_reset, }; +#endif /* * mmc_host_init - initialize the mmc controller. * Set initial clock and power for mmc slot. * Initialize mmc struct and register with mmc framework. */ -int arm_pl180_mmci_init(struct pl180_mmc_host *host) +int arm_pl180_mmci_init(struct pl180_mmc_host *host, struct mmc **mmc) { - struct mmc *mmc; u32 sdi_u32; writel(host->pwr_init, &host->base->power); @@ -362,7 +380,9 @@ int arm_pl180_mmci_init(struct pl180_mmc_host *host) writel(sdi_u32, &host->base->mask0); host->cfg.name = host->name; +#ifndef CONFIG_DM_MMC host->cfg.ops = &arm_pl180_mmci_ops; +#endif /* TODO remove the duplicates */ host->cfg.host_caps = host->caps; host->cfg.voltages = host->voltages; @@ -373,11 +393,144 @@ int arm_pl180_mmci_init(struct pl180_mmc_host *host) else host->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; - mmc = mmc_create(&host->cfg, host); - if (mmc == NULL) + *mmc = mmc_create(&host->cfg, host); + if (!*mmc) return -1; - debug("registered mmc interface number is:%d\n", mmc->block_dev.devnum); + debug("registered mmc interface number is:%d\n", + (*mmc)->block_dev.devnum); return 0; } + +#ifdef CONFIG_DM_MMC +static int arm_pl180_mmc_probe(struct udevice *dev) +{ + struct arm_pl180_mmc_plat *pdata = dev_get_platdata(dev); + struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); + struct mmc *mmc = &pdata->mmc; + struct pl180_mmc_host *host = mmc->priv; + struct clk clk; + u32 bus_width; + int ret; + + ret = clk_get_by_index(dev, 0, &clk); + if (ret < 0) + return ret; + + ret = clk_enable(&clk); + if (ret) { + dev_err(dev, "failed to enable clock\n"); + return ret; + } + + strcpy(host->name, "MMC"); + host->pwr_init = INIT_PWR; + host->clkdiv_init = SDI_CLKCR_CLKDIV_INIT_V1 | SDI_CLKCR_CLKEN | + SDI_CLKCR_HWFC_EN; + host->voltages = VOLTAGE_WINDOW_SD; + host->caps = 0; + host->clock_in = clk_get_rate(&clk); + host->clock_min = host->clock_in / (2 * (SDI_CLKCR_CLKDIV_INIT_V1 + 1)); + host->clock_max = dev_read_u32_default(dev, "max-frequency", + MMC_CLOCK_MAX); + host->version2 = dev_get_driver_data(dev); + + gpio_request_by_name(dev, "cd-gpios", 0, &host->cd_gpio, GPIOD_IS_IN); + + bus_width = dev_read_u32_default(dev, "bus-width", 1); + switch (bus_width) { + case 8: + host->caps |= MMC_MODE_8BIT; + /* Hosts capable of 8-bit transfers can also do 4 bits */ + case 4: + host->caps |= MMC_MODE_4BIT; + break; + case 1: + break; + default: + dev_err(dev, "Invalid bus-width value %u\n", bus_width); + } + + ret = arm_pl180_mmci_init(host, &mmc); + if (ret) { + dev_err(dev, "arm_pl180_mmci init failed\n"); + return ret; + } + + mmc->dev = dev; + dev->priv = host; + upriv->mmc = mmc; + + return 0; +} + +static int dm_host_request(struct udevice *dev, struct mmc_cmd *cmd, + struct mmc_data *data) +{ + struct mmc *mmc = mmc_get_mmc_dev(dev); + + return host_request(mmc, cmd, data); +} + +static int dm_host_set_ios(struct udevice *dev) +{ + struct mmc *mmc = mmc_get_mmc_dev(dev); + + return host_set_ios(mmc); +} + +static int dm_mmc_getcd(struct udevice *dev) +{ + struct arm_pl180_mmc_plat *pdata = dev_get_platdata(dev); + struct mmc *mmc = &pdata->mmc; + struct pl180_mmc_host *host = mmc->priv; + int value = 1; + + if (dm_gpio_is_valid(&host->cd_gpio)) { + value = dm_gpio_get_value(&host->cd_gpio); + if (host->cd_inverted) + return !value; + } + + return value; +} + +static const struct dm_mmc_ops arm_pl180_dm_mmc_ops = { + .send_cmd = dm_host_request, + .set_ios = dm_host_set_ios, + .get_cd = dm_mmc_getcd, +}; + +static int arm_pl180_mmc_ofdata_to_platdata(struct udevice *dev) +{ + struct arm_pl180_mmc_plat *pdata = dev_get_platdata(dev); + struct mmc *mmc = &pdata->mmc; + struct pl180_mmc_host *host = mmc->priv; + fdt_addr_t addr; + + addr = devfdt_get_addr(dev); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + host->base = (void *)addr; + + return 0; +} + +static const struct udevice_id arm_pl180_mmc_match[] = { + { .compatible = "st,stm32f4xx-sdio", .data = VERSION1 }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(arm_pl180_mmc) = { + .name = "arm_pl180_mmc", + .id = UCLASS_MMC, + .of_match = arm_pl180_mmc_match, + .ops = &arm_pl180_dm_mmc_ops, + .probe = arm_pl180_mmc_probe, + .ofdata_to_platdata = arm_pl180_mmc_ofdata_to_platdata, + .priv_auto_alloc_size = sizeof(struct pl180_mmc_host), + .platdata_auto_alloc_size = sizeof(struct arm_pl180_mmc_plat), +}; +#endif diff --git a/drivers/mmc/arm_pl180_mmci.h b/drivers/mmc/arm_pl180_mmci.h index f23bd391eed..9df4b75470f 100644 --- a/drivers/mmc/arm_pl180_mmci.h +++ b/drivers/mmc/arm_pl180_mmci.h @@ -142,6 +142,9 @@ #define SDI_FIFO_BURST_SIZE 8 +#define VERSION1 false +#define VERSION2 true + struct sdi_registers { u32 power; /* 0x00*/ u32 clock; /* 0x04*/ @@ -188,8 +191,12 @@ struct pl180_mmc_host { unsigned int pwr_init; int version2; struct mmc_config cfg; +#ifdef CONFIG_DM_MMC + struct gpio_desc cd_gpio; + bool cd_inverted; +#endif }; -int arm_pl180_mmci_init(struct pl180_mmc_host *); +int arm_pl180_mmci_init(struct pl180_mmc_host *host, struct mmc **mmc); #endif diff --git a/drivers/mmc/atmel_sdhci.c b/drivers/mmc/atmel_sdhci.c index c19a1f36b69..9b37e32c8db 100644 --- a/drivers/mmc/atmel_sdhci.c +++ b/drivers/mmc/atmel_sdhci.c @@ -13,6 +13,7 @@ #include #define ATMEL_SDHC_MIN_FREQ 400000 +#define ATMEL_SDHC_GCK_RATE 240000000 #ifndef CONFIG_DM_MMC int atmel_sdhci_init(void *regbase, u32 id) @@ -57,9 +58,6 @@ static int atmel_sdhci_probe(struct udevice *dev) struct atmel_sdhci_plat *plat = dev_get_platdata(dev); struct sdhci_host *host = dev_get_priv(dev); u32 max_clk; - u32 caps, caps_1; - u32 clk_base, clk_mul; - ulong gck_rate; struct clk clk; int ret; @@ -78,17 +76,11 @@ static int atmel_sdhci_probe(struct udevice *dev) host->bus_width = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "bus-width", 4); - caps = sdhci_readl(host, SDHCI_CAPABILITIES); - clk_base = (caps & SDHCI_CLOCK_V3_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT; - caps_1 = sdhci_readl(host, SDHCI_CAPABILITIES_1); - clk_mul = (caps_1 & SDHCI_CLOCK_MUL_MASK) >> SDHCI_CLOCK_MUL_SHIFT; - gck_rate = clk_base * 1000000 * (clk_mul + 1); - ret = clk_get_by_index(dev, 1, &clk); if (ret) return ret; - ret = clk_set_rate(&clk, gck_rate); + ret = clk_set_rate(&clk, ATMEL_SDHC_GCK_RATE); if (ret) return ret; diff --git a/drivers/mmc/bcm2835_sdhci.c b/drivers/mmc/bcm2835_sdhci.c index 819bd88960c..3157354d2ae 100644 --- a/drivers/mmc/bcm2835_sdhci.c +++ b/drivers/mmc/bcm2835_sdhci.c @@ -50,6 +50,11 @@ #define MIN_FREQ 400000 #define SDHCI_BUFFER 0x20 +struct bcm2835_sdhci_plat { + struct mmc_config cfg; + struct mmc mmc; +}; + struct bcm2835_sdhci_host { struct sdhci_host host; uint twoticks_delay; @@ -75,7 +80,8 @@ static inline void bcm2835_sdhci_raw_writel(struct sdhci_host *host, u32 val, * too) */ if (reg != SDHCI_BUFFER) { - while (timer_get_us() - bcm_host->last_write < bcm_host->twoticks_delay) + while (timer_get_us() - bcm_host->last_write < + bcm_host->twoticks_delay) ; } diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c index 1603f15f079..23f642980bf 100644 --- a/drivers/mmc/dw_mmc.c +++ b/drivers/mmc/dw_mmc.c @@ -16,67 +16,6 @@ #define PAGE_SIZE 4096 -/* - * Currently it supports read/write up to 8*8*4 Bytes per - * stride as a burst mode. Please note that if you change - * MAX_STRIDE, you should also update dwmci_memcpy_fromio - * to augment the groups of {ldm, stm}. - */ -#define MAX_STRIDE 64 -#if CONFIG_ARM && CONFIG_CPU_V7 -void noinline dwmci_memcpy_fromio(void *buffer, void *fifo_addr) -{ - __asm__ __volatile__ ( - "push {r2, r3, r4, r5, r6, r7, r8, r9}\n" - "ldm r1, {r2,r3,r4,r5,r6,r7,r8,r9}\n" - "stm r0!, {r2,r3,r4,r5,r6,r7,r8,r9}\n" - "ldm r1, {r2,r3,r4,r5,r6,r7,r8,r9}\n" - "stm r0!, {r2,r3,r4,r5,r6,r7,r8,r9}\n" - "ldm r1, {r2,r3,r4,r5,r6,r7,r8,r9}\n" - "stm r0!, {r2,r3,r4,r5,r6,r7,r8,r9}\n" - "ldm r1, {r2,r3,r4,r5,r6,r7,r8,r9}\n" - "stm r0!, {r2,r3,r4,r5,r6,r7,r8,r9}\n" - "ldm r1, {r2,r3,r4,r5,r6,r7,r8,r9}\n" - "stm r0!, {r2,r3,r4,r5,r6,r7,r8,r9}\n" - "ldm r1, {r2,r3,r4,r5,r6,r7,r8,r9}\n" - "stm r0!, {r2,r3,r4,r5,r6,r7,r8,r9}\n" - "ldm r1, {r2,r3,r4,r5,r6,r7,r8,r9}\n" - "stm r0!, {r2,r3,r4,r5,r6,r7,r8,r9}\n" - "ldm r1, {r2,r3,r4,r5,r6,r7,r8,r9}\n" - "stm r0!, {r2,r3,r4,r5,r6,r7,r8,r9}\n" - "pop {r2, r3, r4, r5, r6,r7,r8,r9}\n" - :::"memory" - ); -} - -void noinline dwmci_memcpy_toio(void *buffer, void *fifo_addr) -{ - __asm__ __volatile__ ( - "push {r2, r3, r4, r5, r6, r7, r8, r9}\n" - "ldm r0!, {r2,r3,r4,r5,r6,r7,r8,r9}\n" - "stm r1, {r2,r3,r4,r5,r6,r7,r8,r9}\n" - "ldm r0!, {r2,r3,r4,r5,r6,r7,r8,r9}\n" - "stm r1, {r2,r3,r4,r5,r6,r7,r8,r9}\n" - "ldm r0!, {r2,r3,r4,r5,r6,r7,r8,r9}\n" - "stm r1, {r2,r3,r4,r5,r6,r7,r8,r9}\n" - "ldm r0!, {r2,r3,r4,r5,r6,r7,r8,r9}\n" - "stm r1, {r2,r3,r4,r5,r6,r7,r8,r9}\n" - "ldm r0!, {r2,r3,r4,r5,r6,r7,r8,r9}\n" - "stm r1, {r2,r3,r4,r5,r6,r7,r8,r9}\n" - "ldm r0!, {r2,r3,r4,r5,r6,r7,r8,r9}\n" - "stm r1, {r2,r3,r4,r5,r6,r7,r8,r9}\n" - "ldm r0!, {r2,r3,r4,r5,r6,r7,r8,r9}\n" - "stm r1, {r2,r3,r4,r5,r6,r7,r8,r9}\n" - "ldm r0!, {r2,r3,r4,r5,r6,r7,r8,r9}\n" - "stm r1, {r2,r3,r4,r5,r6,r7,r8,r9}\n" - "pop {r2, r3, r4, r5, r6,r7,r8,r9}\n" - :::"memory" - ); -} -#else -void dwmci_memcpy_fromio(void *buffer, void *fifo_addr) {}; -void dwmci_memcpy_toio(void *buffer, void *fifo_addr) {}; -#endif static int dwmci_wait_reset(struct dwmci_host *host, u32 value) { unsigned long timeout = 1000; @@ -158,16 +97,13 @@ static int dwmci_data_transfer(struct dwmci_host *host, struct mmc_data *data) { int ret = 0; u32 timeout = 240000; - u32 status, ctrl, mask, size, i, len = 0; + u32 mask, size, i, len = 0; u32 *buf = NULL; ulong start = get_timer(0); u32 fifo_depth = (((host->fifoth_val & RX_WMARK_MASK) >> RX_WMARK_SHIFT) + 1) * 2; - bool stride; size = data->blocksize * data->blocks / 4; - /* Still use legacy PIO mode if size < 512(128 * 4) Bytes */ - stride = host->stride_pio && size > 128; if (data->flags == MMC_DATA_READ) buf = (unsigned int *)data->dest; else @@ -178,23 +114,6 @@ static int dwmci_data_transfer(struct dwmci_host *host, struct mmc_data *data) /* Error during data transfer. */ if (mask & (DWMCI_DATA_ERR | DWMCI_DATA_TOUT)) { debug("%s: DATA ERROR!\n", __func__); - - dwmci_wait_reset(host, DWMCI_RESET_ALL); - dwmci_writel(host, DWMCI_CMD, DWMCI_CMD_PRV_DAT_WAIT | - DWMCI_CMD_UPD_CLK | DWMCI_CMD_START); - - do { - status = dwmci_readl(host, DWMCI_CMD); - if (timeout-- < 0) - ret = -ETIMEDOUT; - } while (status & DWMCI_CMD_START); - - if (!host->fifo_mode) { - ctrl = dwmci_readl(host, DWMCI_BMOD); - ctrl |= DWMCI_BMOD_IDMAC_RESET; - dwmci_writel(host, DWMCI_BMOD, ctrl); - } - ret = -EINVAL; break; } @@ -208,24 +127,9 @@ static int dwmci_data_transfer(struct dwmci_host *host, struct mmc_data *data) len = (len >> DWMCI_FIFO_SHIFT) & DWMCI_FIFO_MASK; len = min(size, len); - if (!stride) { - /* Legacy pio mode */ - for (i = 0; i < len; i++) - *buf++ = dwmci_readl(host, DWMCI_DATA); - goto read_again; - } - - /* dwmci_memcpy_fromio now bursts 256 Bytes once */ - if (len < MAX_STRIDE) - continue; - - for (i = 0; i < len / MAX_STRIDE; i++) { - dwmci_memcpy_fromio(buf, host->ioaddr + DWMCI_DATA); - buf += MAX_STRIDE; - } - - len = i * MAX_STRIDE; -read_again: + for (i = 0; i < len; i++) + *buf++ = + dwmci_readl(host, DWMCI_DATA); size = size > len ? (size - len) : 0; } dwmci_writel(host, DWMCI_RINTSTS, @@ -238,23 +142,9 @@ static int dwmci_data_transfer(struct dwmci_host *host, struct mmc_data *data) DWMCI_FIFO_SHIFT) & DWMCI_FIFO_MASK); len = min(size, len); - if (!stride) { - for (i = 0; i < len; i++) - dwmci_writel(host, DWMCI_DATA, - *buf++); - goto write_again; - } - /* dwmci_memcpy_toio now bursts 256 Bytes once */ - if (len < MAX_STRIDE) - continue; - - for (i = 0; i < len / MAX_STRIDE; i++) { - dwmci_memcpy_toio(buf, host->ioaddr + DWMCI_DATA); - buf += MAX_STRIDE; - } - - len = i * MAX_STRIDE; -write_again: + for (i = 0; i < len; i++) + dwmci_writel(host, DWMCI_DATA, + *buf++); size = size > len ? (size - len) : 0; } dwmci_writel(host, DWMCI_RINTSTS, @@ -437,7 +327,7 @@ static int dwmci_setup_bus(struct dwmci_host *host, u32 freq) int timeout = 10000; unsigned long sclk; - if (freq == 0) + if ((freq == host->clock) || (freq == 0)) return 0; /* * If host->get_mmc_clk isn't defined, @@ -493,42 +383,6 @@ static int dwmci_setup_bus(struct dwmci_host *host, u32 freq) return 0; } -#ifdef CONFIG_DM_MMC -static bool dwmci_card_busy(struct udevice *dev) -{ - struct mmc *mmc = mmc_get_mmc_dev(dev); -#else -static bool dwmci_card_busy(struct mmc *mmc) -{ -#endif - u32 status; - struct dwmci_host *host = (struct dwmci_host *)mmc->priv; - - /* - * Check the busy bit which is low when DAT[3:0] - * (the data lines) are 0000 - */ - status = dwmci_readl(host, DWMCI_STATUS); - - return !!(status & DWMCI_BUSY); -} - -#ifdef CONFIG_DM_MMC -static int dwmci_execute_tuning(struct udevice *dev, u32 opcode) -{ - struct mmc *mmc = mmc_get_mmc_dev(dev); -#else -static int dwmci_execute_tuning(struct mmc *mmc, u32 opcode) -{ -#endif - struct dwmci_host *host = (struct dwmci_host *)mmc->priv; - - if (!host->execute_tuning) - return -EIO; - - return host->execute_tuning(host, opcode); -} - #ifdef CONFIG_DM_MMC static int dwmci_set_ios(struct udevice *dev) { @@ -558,7 +412,7 @@ static int dwmci_set_ios(struct mmc *mmc) dwmci_writel(host, DWMCI_CTYPE, ctype); regs = dwmci_readl(host, DWMCI_UHS_REG); - if (mmc_card_ddr(mmc)) + if (mmc->ddr_mode) regs |= DWMCI_DDR_MODE; else regs &= ~DWMCI_DDR_MODE; @@ -574,7 +428,6 @@ static int dwmci_set_ios(struct mmc *mmc) static int dwmci_init(struct mmc *mmc) { struct dwmci_host *host = mmc->priv; - uint32_t use_dma; if (host->board_init) host->board_init(host); @@ -586,13 +439,6 @@ static int dwmci_init(struct mmc *mmc) return -EIO; } - use_dma = SDMMC_GET_TRANS_MODE(dwmci_readl(host, DWMCI_HCON)); - if (use_dma == DMA_INTERFACE_IDMA) { - host->fifo_mode = 0; - } else { - host->fifo_mode = 1; - } - /* Enumerate at 400KHz */ dwmci_setup_bus(host, mmc->cfg->f_min); @@ -629,19 +475,15 @@ int dwmci_probe(struct udevice *dev) } const struct dm_mmc_ops dm_dwmci_ops = { - .card_busy = dwmci_card_busy, .send_cmd = dwmci_send_cmd, .set_ios = dwmci_set_ios, - .execute_tuning = dwmci_execute_tuning, }; #else static const struct mmc_ops dwmci_ops = { - .card_busy = dwmci_card_busy, .send_cmd = dwmci_send_cmd, .set_ios = dwmci_set_ios, .init = dwmci_init, - .execute_tuning = dwmci_execute_tuning, }; #endif @@ -660,7 +502,8 @@ void dwmci_setup_cfg(struct mmc_config *cfg, struct dwmci_host *host, cfg->host_caps = host->caps; if (host->buswidth == 8) { - cfg->host_caps |= MMC_MODE_8BIT | MMC_MODE_4BIT; + cfg->host_caps |= MMC_MODE_8BIT; + cfg->host_caps &= ~MMC_MODE_4BIT; } else { cfg->host_caps |= MMC_MODE_4BIT; cfg->host_caps &= ~MMC_MODE_8BIT; diff --git a/drivers/mmc/exynos_dw_mmc.c b/drivers/mmc/exynos_dw_mmc.c index 40f7892ac80..5edd383c684 100644 --- a/drivers/mmc/exynos_dw_mmc.c +++ b/drivers/mmc/exynos_dw_mmc.c @@ -155,7 +155,7 @@ static int exynos_dwmci_get_config(const void *blob, int node, priv = malloc(sizeof(struct dwmci_exynos_priv_data)); if (!priv) { - error("dwmci_exynos_priv_data malloc fail!\n"); + pr_err("dwmci_exynos_priv_data malloc fail!\n"); return -ENOMEM; } diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index e3d1f91c94d..499d622c6d9 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -171,20 +171,20 @@ static void esdhc_pio_read_write(struct fsl_esdhc_priv *priv, uint databuf; uint size; uint irqstat; - uint timeout; + ulong start; if (data->flags & MMC_DATA_READ) { blocks = data->blocks; buffer = data->dest; while (blocks) { - timeout = PIO_TIMEOUT; + start = get_timer(0); size = data->blocksize; irqstat = esdhc_read32(®s->irqstat); - while (!(esdhc_read32(®s->prsstat) & PRSSTAT_BREN) - && --timeout); - if (timeout <= 0) { - printf("\nData Read Failed in PIO Mode."); - return; + while (!(esdhc_read32(®s->prsstat) & PRSSTAT_BREN)) { + if (get_timer(start) > PIO_TIMEOUT) { + printf("\nData Read Failed in PIO Mode."); + return; + } } while (size && (!(irqstat & IRQSTAT_TC))) { udelay(100); /* Wait before last byte transfer complete */ @@ -200,14 +200,14 @@ static void esdhc_pio_read_write(struct fsl_esdhc_priv *priv, blocks = data->blocks; buffer = (char *)data->src; while (blocks) { - timeout = PIO_TIMEOUT; + start = get_timer(0); size = data->blocksize; irqstat = esdhc_read32(®s->irqstat); - while (!(esdhc_read32(®s->prsstat) & PRSSTAT_BWEN) - && --timeout); - if (timeout <= 0) { - printf("\nData Write Failed in PIO Mode."); - return; + while (!(esdhc_read32(®s->prsstat) & PRSSTAT_BWEN)) { + if (get_timer(start) > PIO_TIMEOUT) { + printf("\nData Write Failed in PIO Mode."); + return; + } } while (size && (!(irqstat & IRQSTAT_TC))) { udelay(100); /* Wait before last byte transfer complete */ @@ -407,7 +407,7 @@ static int esdhc_send_cmd_common(struct fsl_esdhc_priv *priv, struct mmc *mmc, #if defined(CONFIG_FSL_USDHC) esdhc_write32(®s->mixctrl, (esdhc_read32(®s->mixctrl) & 0xFFFFFF80) | (xfertyp & 0x7F) - | (mmc_card_ddr(mmc) ? XFERTYP_DDREN : 0)); + | (mmc->ddr_mode ? XFERTYP_DDREN : 0)); esdhc_write32(®s->xfertyp, xfertyp & 0xFFFF0000); #else esdhc_write32(®s->xfertyp, xfertyp); @@ -548,7 +548,7 @@ static void set_sysctl(struct fsl_esdhc_priv *priv, struct mmc *mmc, uint clock) while (sdhc_clk / (div * pre_div * ddr_pre_div) > clock && div < 16) div++; - pre_div >>= mmc_card_ddr(mmc) ? 2 : 1; + pre_div >>= 1; div -= 1; clk = (pre_div << 8) | (div << 4); diff --git a/drivers/mmc/ftsdc010_mci.c b/drivers/mmc/ftsdc010_mci.c index 652a718467a..6ac4f83bd1c 100644 --- a/drivers/mmc/ftsdc010_mci.c +++ b/drivers/mmc/ftsdc010_mci.c @@ -12,24 +12,15 @@ #include #include -#include +#include #include #include #include +#include "ftsdc010_mci.h" #define CFG_CMD_TIMEOUT (CONFIG_SYS_HZ >> 4) /* 250 ms */ #define CFG_RST_TIMEOUT CONFIG_SYS_HZ /* 1 sec reset timeout */ -struct ftsdc010_chip { - void __iomem *regs; - uint32_t wprot; /* write protected (locked) */ - uint32_t rate; /* actual SD clock in Hz */ - uint32_t sclk; /* FTSDC010 source clock in Hz */ - uint32_t fifo; /* fifo depth in bytes */ - uint32_t acmd; - struct mmc_config cfg; /* mmc configuration */ -}; - static inline int ftsdc010_send_cmd(struct mmc *mmc, struct mmc_cmd *mmc_cmd) { struct ftsdc010_chip *chip = mmc->priv; @@ -127,9 +118,8 @@ static void ftsdc010_clkset(struct mmc *mmc, uint32_t rate) static int ftsdc010_wait(struct ftsdc010_mmc __iomem *regs, uint32_t mask) { int ret = -ETIMEDOUT; - uint32_t st, ts; - - for (ts = get_timer(0); get_timer(ts) < CFG_CMD_TIMEOUT; ) { + uint32_t st, timeout = 10000000; + while (timeout--) { st = readl(®s->status); if (!(st & mask)) continue; @@ -138,8 +128,9 @@ static int ftsdc010_wait(struct ftsdc010_mmc __iomem *regs, uint32_t mask) break; } - if (ret) + if (ret){ debug("ftsdc010: wait st(0x%x) timeout\n", mask); + } return ret; } @@ -147,10 +138,16 @@ static int ftsdc010_wait(struct ftsdc010_mmc __iomem *regs, uint32_t mask) /* * u-boot mmc api */ - +#ifdef CONFIG_DM_MMC +static int ftsdc010_request(struct udevice *dev, struct mmc_cmd *cmd, + struct mmc_data *data) +{ + struct mmc *mmc = mmc_get_mmc_dev(dev); +#else static int ftsdc010_request(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) { +#endif int ret = -EOPNOTSUPP; uint32_t len = 0; struct ftsdc010_chip *chip = mmc->priv; @@ -245,14 +242,20 @@ static int ftsdc010_request(struct mmc *mmc, struct mmc_cmd *cmd, if (!ret) { ret = ftsdc010_wait(regs, - FTSDC010_STATUS_DATA_END | FTSDC010_STATUS_DATA_ERROR); + FTSDC010_STATUS_DATA_END | FTSDC010_STATUS_DATA_CRC_OK); } return ret; } +#ifdef CONFIG_DM_MMC +static int ftsdc010_set_ios(struct udevice *dev) +{ + struct mmc *mmc = mmc_get_mmc_dev(dev); +#else static int ftsdc010_set_ios(struct mmc *mmc) { +#endif struct ftsdc010_chip *chip = mmc->priv; struct ftsdc010_mmc __iomem *regs = chip->regs; @@ -274,20 +277,43 @@ static int ftsdc010_set_ios(struct mmc *mmc) return 0; } -static int ftsdc010_init(struct mmc *mmc) +#ifdef CONFIG_DM_MMC +static int ftsdc010_get_cd(struct udevice *dev) +{ + struct mmc *mmc = mmc_get_mmc_dev(dev); +#else +static int ftsdc010_get_cd(struct mmc *mmc) { +#endif struct ftsdc010_chip *chip = mmc->priv; struct ftsdc010_mmc __iomem *regs = chip->regs; - uint32_t ts; - - if (readl(®s->status) & FTSDC010_STATUS_CARD_DETECT) - return -ENOMEDIUM; + return !(readl(®s->status) & FTSDC010_STATUS_CARD_DETECT); +} +#ifdef CONFIG_DM_MMC +static int ftsdc010_get_wp(struct udevice *dev) +{ + struct mmc *mmc = mmc_get_mmc_dev(dev); +#else +static int ftsdc010_get_wp(struct mmc *mmc) +{ +#endif + struct ftsdc010_chip *chip = mmc->priv; + struct ftsdc010_mmc __iomem *regs = chip->regs; if (readl(®s->status) & FTSDC010_STATUS_WRITE_PROT) { printf("ftsdc010: write protected\n"); chip->wprot = 1; } + return 0; +} + +static int ftsdc010_init(struct mmc *mmc) +{ + struct ftsdc010_chip *chip = mmc->priv; + struct ftsdc010_mmc __iomem *regs = chip->regs; + uint32_t ts; + chip->fifo = (readl(®s->feature) & 0xff) << 2; /* 1. chip reset */ @@ -311,11 +337,69 @@ static int ftsdc010_init(struct mmc *mmc) return 0; } +#ifdef CONFIG_DM_MMC +int ftsdc010_probe(struct udevice *dev) +{ + struct mmc *mmc = mmc_get_mmc_dev(dev); + return ftsdc010_init(mmc); +} + +const struct dm_mmc_ops dm_ftsdc010_ops = { + .send_cmd = ftsdc010_request, + .set_ios = ftsdc010_set_ios, + .get_cd = ftsdc010_get_cd, + .get_wp = ftsdc010_get_wp, +}; + +#else static const struct mmc_ops ftsdc010_ops = { .send_cmd = ftsdc010_request, .set_ios = ftsdc010_set_ios, + .getcd = ftsdc010_get_cd, + .getwp = ftsdc010_get_wp, .init = ftsdc010_init, }; +#endif + +void ftsdc_setup_cfg(struct mmc_config *cfg, const char *name, int buswidth, + uint caps, u32 max_clk, u32 min_clk) +{ + cfg->name = name; + cfg->f_min = min_clk; + cfg->f_max = max_clk; + cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; + cfg->host_caps = caps; + if (buswidth == 8) { + cfg->host_caps |= MMC_MODE_8BIT; + cfg->host_caps &= ~MMC_MODE_4BIT; + } else { + cfg->host_caps |= MMC_MODE_4BIT; + cfg->host_caps &= ~MMC_MODE_8BIT; + } + cfg->part_type = PART_TYPE_DOS; + cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; +} + +void set_bus_width(struct ftsdc010_mmc __iomem *regs, struct mmc_config *cfg) +{ + switch (readl(®s->bwr) & FTSDC010_BWR_CAPS_MASK) { + case FTSDC010_BWR_CAPS_4BIT: + cfg->host_caps |= MMC_MODE_4BIT; + break; + case FTSDC010_BWR_CAPS_8BIT: + cfg->host_caps |= MMC_MODE_4BIT | MMC_MODE_8BIT; + break; + default: + break; + } +} + +#ifdef CONFIG_BLK +int ftsdc010_bind(struct udevice *dev, struct mmc *mmc, struct mmc_config *cfg) +{ + return mmc_bind(dev, mmc, cfg); +} +#else int ftsdc010_mmc_init(int devid) { @@ -345,19 +429,11 @@ int ftsdc010_mmc_init(int devid) #endif chip->cfg.name = "ftsdc010"; +#ifndef CONFIG_DM_MMC chip->cfg.ops = &ftsdc010_ops; +#endif chip->cfg.host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz; - switch (readl(®s->bwr) & FTSDC010_BWR_CAPS_MASK) { - case FTSDC010_BWR_CAPS_4BIT: - chip->cfg.host_caps |= MMC_MODE_4BIT; - break; - case FTSDC010_BWR_CAPS_8BIT: - chip->cfg.host_caps |= MMC_MODE_4BIT | MMC_MODE_8BIT; - break; - default: - break; - } - + set_bus_width(regs , &chip->cfg); chip->cfg.voltages = MMC_VDD_32_33 | MMC_VDD_33_34; chip->cfg.f_max = chip->sclk / 2; chip->cfg.f_min = chip->sclk / 0x100; @@ -373,3 +449,4 @@ int ftsdc010_mmc_init(int devid) return 0; } +#endif diff --git a/drivers/mmc/ftsdc010_mci.h b/drivers/mmc/ftsdc010_mci.h new file mode 100644 index 00000000000..31a27fd7728 --- /dev/null +++ b/drivers/mmc/ftsdc010_mci.h @@ -0,0 +1,53 @@ +/* + * Faraday FTSDC010 Secure Digital Memory Card Host Controller + * + * Copyright (C) 2011 Andes Technology Corporation + * Macpaul Lin, Andes Technology Corporation + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include + +#ifndef __FTSDC010_MCI_H +#define __FTSDC010_MCI_H + +struct ftsdc010_chip { + void __iomem *regs; + uint32_t wprot; /* write protected (locked) */ + uint32_t rate; /* actual SD clock in Hz */ + uint32_t sclk; /* FTSDC010 source clock in Hz */ + uint32_t fifo; /* fifo depth in bytes */ + uint32_t acmd; + struct mmc_config cfg; /* mmc configuration */ + const char *name; + void *ioaddr; + unsigned int caps; + unsigned int version; + unsigned int clock; + unsigned int bus_hz; + unsigned int div; + int dev_index; + int dev_id; + int buswidth; + u32 fifoth_val; + struct mmc *mmc; + void *priv; + bool fifo_mode; +}; + + +#ifdef CONFIG_DM_MMC +/* Export the operations to drivers */ +int ftsdc010_probe(struct udevice *dev); +extern const struct dm_mmc_ops dm_ftsdc010_ops; +#endif +void ftsdc_setup_cfg(struct mmc_config *cfg, const char *name, int buswidth, + uint caps, u32 max_clk, u32 min_clk); +void set_bus_width(struct ftsdc010_mmc __iomem *regs, struct mmc_config *cfg); + +#ifdef CONFIG_BLK +int ftsdc010_bind(struct udevice *dev, struct mmc *mmc, struct mmc_config *cfg); +#endif + + +#endif /* __FTSDC010_MCI_H */ diff --git a/drivers/mmc/hi6220_dw_mmc.c b/drivers/mmc/hi6220_dw_mmc.c index d795198534b..44a8ef825f3 100644 --- a/drivers/mmc/hi6220_dw_mmc.c +++ b/drivers/mmc/hi6220_dw_mmc.c @@ -44,7 +44,7 @@ int hi6220_dwmci_add_port(int index, u32 regbase, int bus_width) host = calloc(1, sizeof(struct dwmci_host)); if (!host) { - error("dwmci_host calloc failed!\n"); + pr_err("dwmci_host calloc failed!\n"); return -ENOMEM; } diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c index 1a11844caee..5dda20cda5e 100644 --- a/drivers/mmc/mmc-uclass.c +++ b/drivers/mmc/mmc-uclass.c @@ -37,22 +37,6 @@ int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) return dm_mmc_send_cmd(mmc->dev, cmd, data); } -bool mmc_card_busy(struct mmc *mmc) -{ - struct dm_mmc_ops *ops = mmc_get_ops(mmc->dev); - - if (!ops->card_busy) - return -ENOSYS; - return ops->card_busy(mmc->dev); -} - -bool mmc_can_card_busy(struct mmc *mmc) -{ - struct dm_mmc_ops *ops = mmc_get_ops(mmc->dev); - - return !!ops->card_busy; -} - int dm_mmc_set_ios(struct udevice *dev) { struct dm_mmc_ops *ops = mmc_get_ops(dev); diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 2749c24d13a..38d2e07dd51 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -210,7 +210,7 @@ int mmc_set_blocklen(struct mmc *mmc, int len) { struct mmc_cmd cmd; - if (mmc_card_ddr(mmc)) + if (mmc->ddr_mode) return 0; cmd.cmdidx = MMC_CMD_SET_BLOCKLEN; @@ -318,32 +318,6 @@ ulong mmc_bread(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt, return blkcnt; } -void mmc_set_clock(struct mmc *mmc, uint clock) -{ - if (clock > mmc->cfg->f_max) - clock = mmc->cfg->f_max; - - if (clock < mmc->cfg->f_min) - clock = mmc->cfg->f_min; - - mmc->clock = clock; - - mmc_set_ios(mmc); -} - -static void mmc_set_bus_width(struct mmc *mmc, uint width) -{ - mmc->bus_width = width; - - mmc_set_ios(mmc); -} - -static void mmc_set_timing(struct mmc *mmc, uint timing) -{ - mmc->timing = timing; - mmc_set_ios(mmc); -} - static int mmc_go_idle(struct mmc *mmc) { struct mmc_cmd cmd; @@ -543,46 +517,10 @@ static int mmc_send_ext_csd(struct mmc *mmc, u8 *ext_csd) return err; } -static int mmc_poll_for_busy(struct mmc *mmc) +int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value) { struct mmc_cmd cmd; - u8 busy = true; - uint start; - int ret; int timeout = 1000; - - cmd.cmdidx = MMC_CMD_SEND_STATUS; - cmd.resp_type = MMC_RSP_R1; - cmd.cmdarg = mmc->rca << 16; - - start = get_timer(0); - - do { - if (mmc_can_card_busy(mmc)) { - busy = mmc_card_busy(mmc); - } else { - ret = mmc_send_cmd(mmc, &cmd, NULL); - - if (ret) - return ret; - - if (cmd.response[0] & MMC_STATUS_SWITCH_ERROR) - return -EBADMSG; - busy = (cmd.response[0] & MMC_STATUS_CURR_STATE) == - MMC_STATE_PRG; - } - - if (get_timer(start) > timeout && busy) - return -ETIMEDOUT; - } while (busy); - - return 0; -} - -static int __mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value, - u8 send_status) -{ - struct mmc_cmd cmd; int retries = 3; int ret; @@ -592,378 +530,26 @@ static int __mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value, (index << 16) | (value << 8); - do { - ret = mmc_send_cmd(mmc, &cmd, NULL); - - if (!ret && send_status) - return mmc_poll_for_busy(mmc); - } while (--retries > 0 && ret); - - return ret; -} - -int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value) -{ - return __mmc_switch(mmc, set, index, value, true); -} - -static int mmc_select_bus_width(struct mmc *mmc) -{ - u32 ext_csd_bits[] = { - EXT_CSD_BUS_WIDTH_8, - EXT_CSD_BUS_WIDTH_4, - }; - u32 bus_widths[] = { - MMC_BUS_WIDTH_8BIT, - MMC_BUS_WIDTH_4BIT, - }; - ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN); - ALLOC_CACHE_ALIGN_BUFFER(u8, test_csd, MMC_MAX_BLOCK_LEN); - u32 idx, bus_width = 0; - int err = 0; - - if (mmc->version < MMC_VERSION_4 || - !(mmc->cfg->host_caps & (MMC_MODE_4BIT | MMC_MODE_8BIT))) - return 0; - - err = mmc_send_ext_csd(mmc, ext_csd); - - if (err) - return err; - - idx = (mmc->cfg->host_caps & MMC_MODE_8BIT) ? 0 : 1; - - /* - * Unlike SD, MMC cards dont have a configuration register to notify - * supported bus width. So bus test command should be run to identify - * the supported bus width or compare the ext csd values of current - * bus width and ext csd values of 1 bit mode read earlier. - */ - for (; idx < ARRAY_SIZE(bus_widths); idx++) { - /* - * Host is capable of 8bit transfer, then switch - * the device to work in 8bit transfer mode. If the - * mmc switch command returns error then switch to - * 4bit transfer mode. On success set the corresponding - * bus width on the host. - */ - err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, - EXT_CSD_BUS_WIDTH, ext_csd_bits[idx]); - if (err) - continue; - - bus_width = bus_widths[idx]; - mmc_set_bus_width(mmc, bus_width); - - err = mmc_send_ext_csd(mmc, test_csd); - - if (err) - continue; - - /* Only compare read only fields */ - if ((ext_csd[EXT_CSD_PARTITIONING_SUPPORT] == - test_csd[EXT_CSD_PARTITIONING_SUPPORT]) && - (ext_csd[EXT_CSD_HC_WP_GRP_SIZE] == - test_csd[EXT_CSD_HC_WP_GRP_SIZE]) && - (ext_csd[EXT_CSD_REV] == test_csd[EXT_CSD_REV]) && - (ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] == - test_csd[EXT_CSD_HC_ERASE_GRP_SIZE]) && - !memcmp(&ext_csd[EXT_CSD_SEC_CNT], - &test_csd[EXT_CSD_SEC_CNT], 4)) { - err = bus_width; - break; - } else { - err = -EBADMSG; - } - } - - return err; -} - -static const u8 tuning_blk_pattern_4bit[] = { - 0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc, - 0xc3, 0x3c, 0xcc, 0xff, 0xfe, 0xff, 0xfe, 0xef, - 0xff, 0xdf, 0xff, 0xdd, 0xff, 0xfb, 0xff, 0xfb, - 0xbf, 0xff, 0x7f, 0xff, 0x77, 0xf7, 0xbd, 0xef, - 0xff, 0xf0, 0xff, 0xf0, 0x0f, 0xfc, 0xcc, 0x3c, - 0xcc, 0x33, 0xcc, 0xcf, 0xff, 0xef, 0xff, 0xee, - 0xff, 0xfd, 0xff, 0xfd, 0xdf, 0xff, 0xbf, 0xff, - 0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde, -}; - -static const u8 tuning_blk_pattern_8bit[] = { - 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, 0xcc, - 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, 0xff, - 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, 0xff, - 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, 0xdd, - 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb, - 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 0xff, - 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, 0xff, - 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, - 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, - 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, - 0xff, 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, - 0xff, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, - 0xdd, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, - 0xbb, 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, - 0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, -}; - -int mmc_send_tuning(struct mmc *mmc, u32 opcode) -{ - struct mmc_cmd cmd; - struct mmc_data data; - const u8 *tuning_block_pattern; - int size, err = 0; - u8 *data_buf; - - if (mmc->bus_width == MMC_BUS_WIDTH_8BIT) { - tuning_block_pattern = tuning_blk_pattern_8bit; - size = sizeof(tuning_blk_pattern_8bit); - } else if (mmc->bus_width == MMC_BUS_WIDTH_4BIT) { - tuning_block_pattern = tuning_blk_pattern_4bit; - size = sizeof(tuning_blk_pattern_4bit); - } else { - return -EINVAL; - } - - data_buf = calloc(1, size); - if (!data_buf) - return -ENOMEM; - - cmd.cmdidx = opcode; - cmd.resp_type = MMC_RSP_R1; - cmd.cmdarg = 0; - - data.dest = (char *)data_buf; - data.blocksize = size; - data.blocks = 1; - data.flags = MMC_DATA_READ; - - err = mmc_send_cmd(mmc, &cmd, &data); - if (err) - goto out; - - if (memcmp(data_buf, tuning_block_pattern, size)) - err = -EIO; -out: - free(data_buf); - return err; -} - -static int mmc_execute_tuning(struct mmc *mmc) -{ -#ifdef CONFIG_DM_MMC - struct dm_mmc_ops *ops = mmc_get_ops(mmc->dev); -#endif - u32 opcode; - - if (IS_SD(mmc)) - opcode = MMC_SEND_TUNING_BLOCK; - else - opcode = MMC_SEND_TUNING_BLOCK_HS200; - -#ifndef CONFIG_DM_MMC - if (mmc->cfg->ops->execute_tuning) { - return mmc->cfg->ops->execute_tuning(mmc, opcode); -#else - if (ops->execute_tuning) { - return ops->execute_tuning(mmc->dev, opcode); -#endif - } else { - debug("Tuning feature required for HS200 mode.\n"); - return -EIO; - } -} - -static int mmc_hs200_tuning(struct mmc *mmc) -{ - return mmc_execute_tuning(mmc); -} - -static int mmc_select_hs(struct mmc *mmc) -{ - int ret; - - ret = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, - EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS); - - if (!ret) - mmc_set_timing(mmc, MMC_TIMING_MMC_HS); - - return ret; -} - -static int mmc_select_hs_ddr(struct mmc *mmc) -{ - u32 ext_csd_bits; - int err = 0; - - if (mmc->bus_width == MMC_BUS_WIDTH_1BIT) - return 0; - - ext_csd_bits = (mmc->bus_width == MMC_BUS_WIDTH_8BIT) ? - EXT_CSD_DDR_BUS_WIDTH_8 : EXT_CSD_DDR_BUS_WIDTH_4; - - err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, - EXT_CSD_BUS_WIDTH, ext_csd_bits); - if (err) - return err; - - mmc_set_timing(mmc, MMC_TIMING_MMC_DDR52); - - return 0; -} - -#ifndef CONFIG_SPL_BUILD -static int mmc_select_hs200(struct mmc *mmc) -{ - int ret; - struct mmc_cmd cmd; - - /* - * Set the bus width(4 or 8) with host's support and - * switch to HS200 mode if bus width is set successfully. - */ - ret = mmc_select_bus_width(mmc); - - if (ret > 0) { - ret = __mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, - EXT_CSD_HS_TIMING, - EXT_CSD_TIMING_HS200, false); - - if (ret) - return ret; - - mmc_set_timing(mmc, MMC_TIMING_MMC_HS200); - - cmd.cmdidx = MMC_CMD_SEND_STATUS; - cmd.resp_type = MMC_RSP_R1; - cmd.cmdarg = mmc->rca << 16; - + while (retries > 0) { ret = mmc_send_cmd(mmc, &cmd, NULL); - if (ret) + /* Waiting for the ready status */ + if (!ret) { + ret = mmc_send_status(mmc, timeout); return ret; + } - if (cmd.response[0] & MMC_STATUS_SWITCH_ERROR) - return -EBADMSG; + retries--; } return ret; -} -#endif - -static int mmc_select_hs400(struct mmc *mmc) -{ - int ret; - - /* Switch card to HS mode */ - ret = __mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, - EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS, false); - if (ret) - return ret; - - /* Set host controller to HS timing */ - mmc_set_timing(mmc, MMC_TIMING_MMC_HS); - /* Reduce frequency to HS frequency */ - mmc_set_clock(mmc, MMC_HIGH_52_MAX_DTR); - - ret = mmc_send_status(mmc, 1000); - if (ret) - return ret; - - /* Switch card to DDR */ - ret = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, - EXT_CSD_BUS_WIDTH, - EXT_CSD_DDR_BUS_WIDTH_8); - if (ret) - return ret; - - /* Switch card to HS400 */ - ret = __mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, - EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS400, false); - if (ret) - return ret; - - /* Set host controller to HS400 timing and frequency */ - mmc_set_timing(mmc, MMC_TIMING_MMC_HS400); - - return ret; -} - -static u32 mmc_select_card_type(struct mmc *mmc, u8 *ext_csd) -{ - u8 card_type; - u32 host_caps, avail_type = 0; - - card_type = ext_csd[EXT_CSD_CARD_TYPE]; - host_caps = mmc->cfg->host_caps; - - if ((host_caps & MMC_MODE_HS) && - (card_type & EXT_CSD_CARD_TYPE_26)) - avail_type |= EXT_CSD_CARD_TYPE_26; - - if ((host_caps & MMC_MODE_HS) && - (card_type & EXT_CSD_CARD_TYPE_52)) - avail_type |= EXT_CSD_CARD_TYPE_52; - - /* - * For the moment, u-boot doesn't support signal voltage - * switch, therefor we assume that host support ddr52 - * at 1.8v or 3.3v I/O(1.2v I/O not supported, hs200 and - * hs400 are the same). - */ - if ((host_caps & MMC_MODE_DDR_52MHz) && - (card_type & EXT_CSD_CARD_TYPE_DDR_1_8V)) - avail_type |= EXT_CSD_CARD_TYPE_DDR_1_8V; - - if ((host_caps & MMC_MODE_HS200) && - (card_type & EXT_CSD_CARD_TYPE_HS200_1_8V)) - avail_type |= EXT_CSD_CARD_TYPE_HS200_1_8V; - - /* - * If host can support HS400, it means that host can also - * support HS200. - */ - if ((host_caps & MMC_MODE_HS400) && - (host_caps & MMC_MODE_8BIT) && - (card_type & EXT_CSD_CARD_TYPE_HS400_1_8V)) - avail_type |= EXT_CSD_CARD_TYPE_HS200_1_8V | - EXT_CSD_CARD_TYPE_HS400_1_8V; - - if ((host_caps & MMC_MODE_HS400ES) && - (host_caps & MMC_MODE_8BIT) && - ext_csd[EXT_CSD_STROBE_SUPPORT] && - (avail_type & EXT_CSD_CARD_TYPE_HS400_1_8V)) - avail_type |= EXT_CSD_CARD_TYPE_HS200_1_8V | - EXT_CSD_CARD_TYPE_HS400_1_8V | - EXT_CSD_CARD_TYPE_HS400ES; - - return avail_type; -} - -static void mmc_set_bus_speed(struct mmc *mmc, u8 avail_type) -{ - int clock = 0; - - if (mmc_card_hs(mmc)) - clock = (avail_type & EXT_CSD_CARD_TYPE_52) ? - MMC_HIGH_52_MAX_DTR : MMC_HIGH_26_MAX_DTR; - else if (mmc_card_hs200(mmc) || - mmc_card_hs400(mmc) || - mmc_card_hs400es(mmc)) - clock = MMC_HS200_MAX_DTR; - - mmc_set_clock(mmc, clock); } static int mmc_change_freq(struct mmc *mmc) { ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN); - u32 avail_type; + char cardtype; int err; mmc->card_caps = 0; @@ -982,37 +568,33 @@ static int mmc_change_freq(struct mmc *mmc) if (err) return err; - avail_type = mmc_select_card_type(mmc, ext_csd); + cardtype = ext_csd[EXT_CSD_CARD_TYPE] & 0xf; -#ifndef CONFIG_SPL_BUILD - if (avail_type & EXT_CSD_CARD_TYPE_HS200) - err = mmc_select_hs200(mmc); - else -#endif - if (avail_type & EXT_CSD_CARD_TYPE_HS) - err = mmc_select_hs(mmc); - else - err = -EINVAL; + err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, 1); if (err) return err; - mmc_set_bus_speed(mmc, avail_type); + /* Now check to see that it worked */ + err = mmc_send_ext_csd(mmc, ext_csd); - if (mmc_card_hs200(mmc)) { - err = mmc_hs200_tuning(mmc); - if (avail_type & EXT_CSD_CARD_TYPE_HS400 && - mmc->bus_width == MMC_BUS_WIDTH_8BIT) { - err = mmc_select_hs400(mmc); - mmc_set_bus_speed(mmc, avail_type); - } - } else if (!mmc_card_hs400es(mmc)) { - err = mmc_select_bus_width(mmc) > 0 ? 0 : err; - if (!err && avail_type & EXT_CSD_CARD_TYPE_DDR_52) - err = mmc_select_hs_ddr(mmc); + if (err) + return err; + + /* No high-speed support */ + if (!ext_csd[EXT_CSD_HS_TIMING]) + return 0; + + /* High Speed is set, there are two types: 52MHz and 26MHz */ + if (cardtype & EXT_CSD_CARD_TYPE_52) { + if (cardtype & EXT_CSD_CARD_TYPE_DDR_1_8V) + mmc->card_caps |= MMC_MODE_DDR_52MHz; + mmc->card_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS; + } else { + mmc->card_caps |= MMC_MODE_HS; } - return err; + return 0; } static int mmc_set_capacity(struct mmc *mmc, int part_num) @@ -1499,28 +1081,36 @@ static void mmc_set_ios(struct mmc *mmc) if (mmc->cfg->ops->set_ios) mmc->cfg->ops->set_ios(mmc); } +#endif -static bool mmc_card_busy(struct mmc *mmc) +void mmc_set_clock(struct mmc *mmc, uint clock) { - if (!mmc->cfg->ops->card_busy) - return -ENOSYS; + if (clock > mmc->cfg->f_max) + clock = mmc->cfg->f_max; - return mmc->cfg->ops->card_busy(mmc); + if (clock < mmc->cfg->f_min) + clock = mmc->cfg->f_min; + + mmc->clock = clock; + + mmc_set_ios(mmc); } -static bool mmc_can_card_busy(struct mmc *) +static void mmc_set_bus_width(struct mmc *mmc, uint width) { - return !!mmc->cfg->ops->card_busy; + mmc->bus_width = width; + + mmc_set_ios(mmc); } -#endif static int mmc_startup(struct mmc *mmc) { int err, i; - uint mult, freq, tran_speed; + uint mult, freq; u64 cmult, csize, capacity; struct mmc_cmd cmd; ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN); + ALLOC_CACHE_ALIGN_BUFFER(u8, test_csd, MMC_MAX_BLOCK_LEN); bool has_parts = false; bool part_completed; struct blk_desc *bdesc; @@ -1613,7 +1203,7 @@ static int mmc_startup(struct mmc *mmc) freq = fbase[(cmd.response[0] & 0x7)]; mult = multipliers[((cmd.response[0] >> 3) & 0xf)]; - tran_speed = freq * mult; + mmc->tran_speed = freq * mult; mmc->dsr_imp = ((cmd.response[1] >> 12) & 0x1); mmc->read_bl_len = 1 << ((cmd.response[1] >> 16) & 0xf); @@ -1860,15 +1450,105 @@ static int mmc_startup(struct mmc *mmc) return err; if (mmc->card_caps & MMC_MODE_HS) - tran_speed = 50000000; + mmc->tran_speed = 50000000; else - tran_speed = 25000000; + mmc->tran_speed = 25000000; + } else if (mmc->version >= MMC_VERSION_4) { + /* Only version 4 of MMC supports wider bus widths */ + int idx; + + /* An array of possible bus widths in order of preference */ + static unsigned ext_csd_bits[] = { + EXT_CSD_DDR_BUS_WIDTH_8, + EXT_CSD_DDR_BUS_WIDTH_4, + EXT_CSD_BUS_WIDTH_8, + EXT_CSD_BUS_WIDTH_4, + EXT_CSD_BUS_WIDTH_1, + }; + + /* An array to map CSD bus widths to host cap bits */ + static unsigned ext_to_hostcaps[] = { + [EXT_CSD_DDR_BUS_WIDTH_4] = + MMC_MODE_DDR_52MHz | MMC_MODE_4BIT, + [EXT_CSD_DDR_BUS_WIDTH_8] = + MMC_MODE_DDR_52MHz | MMC_MODE_8BIT, + [EXT_CSD_BUS_WIDTH_4] = MMC_MODE_4BIT, + [EXT_CSD_BUS_WIDTH_8] = MMC_MODE_8BIT, + }; + + /* An array to map chosen bus width to an integer */ + static unsigned widths[] = { + 8, 4, 8, 4, 1, + }; + + for (idx=0; idx < ARRAY_SIZE(ext_csd_bits); idx++) { + unsigned int extw = ext_csd_bits[idx]; + unsigned int caps = ext_to_hostcaps[extw]; + + /* + * If the bus width is still not changed, + * don't try to set the default again. + * Otherwise, recover from switch attempts + * by switching to 1-bit bus width. + */ + if (extw == EXT_CSD_BUS_WIDTH_1 && + mmc->bus_width == 1) { + err = 0; + break; + } - mmc_set_clock(mmc, tran_speed); + /* + * Check to make sure the card and controller support + * these capabilities + */ + if ((mmc->card_caps & caps) != caps) + continue; + + err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_BUS_WIDTH, extw); + + if (err) + continue; + + mmc->ddr_mode = (caps & MMC_MODE_DDR_52MHz) ? 1 : 0; + mmc_set_bus_width(mmc, widths[idx]); + + err = mmc_send_ext_csd(mmc, test_csd); + + if (err) + continue; + + /* Only compare read only fields */ + if (ext_csd[EXT_CSD_PARTITIONING_SUPPORT] + == test_csd[EXT_CSD_PARTITIONING_SUPPORT] && + ext_csd[EXT_CSD_HC_WP_GRP_SIZE] + == test_csd[EXT_CSD_HC_WP_GRP_SIZE] && + ext_csd[EXT_CSD_REV] + == test_csd[EXT_CSD_REV] && + ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] + == test_csd[EXT_CSD_HC_ERASE_GRP_SIZE] && + memcmp(&ext_csd[EXT_CSD_SEC_CNT], + &test_csd[EXT_CSD_SEC_CNT], 4) == 0) + break; + else + err = -EBADMSG; + } + + if (err) + return err; + + if (mmc->card_caps & MMC_MODE_HS) { + if (mmc->card_caps & MMC_MODE_HS_52MHz) + mmc->tran_speed = 52000000; + else + mmc->tran_speed = 26000000; + } } + mmc_set_clock(mmc, mmc->tran_speed); + /* Fix the block length for DDR mode */ - if (mmc_card_ddr(mmc)) { + if (mmc->ddr_mode) { mmc->read_bl_len = MMC_MAX_BLOCK_LEN; mmc->write_bl_len = MMC_MAX_BLOCK_LEN; } @@ -2001,9 +1681,9 @@ int mmc_start_init(struct mmc *mmc) if (err) return err; #endif + mmc->ddr_mode = 0; mmc_set_bus_width(mmc, 1); mmc_set_clock(mmc, 1); - mmc_set_timing(mmc, MMC_TIMING_LEGACY); /* Reset the Card */ err = mmc_go_idle(mmc); diff --git a/drivers/mmc/nds32_mmc.c b/drivers/mmc/nds32_mmc.c new file mode 100644 index 00000000000..6d3c8572e50 --- /dev/null +++ b/drivers/mmc/nds32_mmc.c @@ -0,0 +1,136 @@ +/* + * Andestech ATFSDC010 SD/MMC driver + * + * (C) Copyright 2017 + * Rick Chen, NDS32 Software Engineering, rick@andestech.com + + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ftsdc010_mci.h" + +DECLARE_GLOBAL_DATA_PTR; + +#if CONFIG_IS_ENABLED(OF_PLATDATA) +struct nds_mmc { + fdt32_t bus_width; + bool cap_mmc_highspeed; + bool cap_sd_highspeed; + fdt32_t clock_freq_min_max[2]; + struct phandle_2_cell clocks[4]; + fdt32_t fifo_depth; + fdt32_t reg[2]; +}; +#endif + +struct nds_mmc_plat { +#if CONFIG_IS_ENABLED(OF_PLATDATA) + struct nds_mmc dtplat; +#endif + struct mmc_config cfg; + struct mmc mmc; +}; + +struct ftsdc_priv { + struct clk clk; + struct ftsdc010_chip chip; + int fifo_depth; + bool fifo_mode; + u32 minmax[2]; +}; + +static int nds32_mmc_ofdata_to_platdata(struct udevice *dev) +{ +#if !CONFIG_IS_ENABLED(OF_PLATDATA) + struct ftsdc_priv *priv = dev_get_priv(dev); + struct ftsdc010_chip *chip = &priv->chip; + chip->name = dev->name; + chip->ioaddr = (void *)devfdt_get_addr(dev); + chip->buswidth = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), + "bus-width", 4); + chip->priv = dev; + priv->fifo_depth = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), + "fifo-depth", 0); + priv->fifo_mode = fdtdec_get_bool(gd->fdt_blob, dev_of_offset(dev), + "fifo-mode"); + if (fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(dev), + "clock-freq-min-max", priv->minmax, 2)) { + int val = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), + "max-frequency", -EINVAL); + if (val < 0) + return val; + + priv->minmax[0] = 400000; /* 400 kHz */ + priv->minmax[1] = val; + } else { + debug("%s: 'clock-freq-min-max' property was deprecated.\n", + __func__); + } +#endif + chip->sclk = priv->minmax[1]; + chip->regs = chip->ioaddr; + return 0; +} + +static int nds32_mmc_probe(struct udevice *dev) +{ + struct nds_mmc_plat *plat = dev_get_platdata(dev); + struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); + struct ftsdc_priv *priv = dev_get_priv(dev); + struct ftsdc010_chip *chip = &priv->chip; + struct udevice *pwr_dev __maybe_unused; +#if CONFIG_IS_ENABLED(OF_PLATDATA) + int ret; + struct nds_mmc *dtplat = &plat->dtplat; + chip->name = dev->name; + chip->ioaddr = map_sysmem(dtplat->reg[0], dtplat->reg[1]); + chip->buswidth = dtplat->bus_width; + chip->priv = dev; + chip->dev_index = 1; + memcpy(priv->minmax, dtplat->clock_freq_min_max, sizeof(priv->minmax)); + ret = clk_get_by_index_platdata(dev, 0, dtplat->clocks, &priv->clk); + if (ret < 0) + return ret; +#endif + ftsdc_setup_cfg(&plat->cfg, dev->name, chip->buswidth, chip->caps, + priv->minmax[1] , priv->minmax[0]); + chip->mmc = &plat->mmc; + chip->mmc->priv = &priv->chip; + chip->mmc->dev = dev; + upriv->mmc = chip->mmc; + return ftsdc010_probe(dev); +} + +static int nds32_mmc_bind(struct udevice *dev) +{ + struct nds_mmc_plat *plat = dev_get_platdata(dev); + return ftsdc010_bind(dev, &plat->mmc, &plat->cfg); +} + +static const struct udevice_id nds32_mmc_ids[] = { + { .compatible = "andestech,atsdc010" }, + { } +}; + +U_BOOT_DRIVER(nds32_mmc_drv) = { + .name = "nds32_mmc", + .id = UCLASS_MMC, + .of_match = nds32_mmc_ids, + .ofdata_to_platdata = nds32_mmc_ofdata_to_platdata, + .ops = &dm_ftsdc010_ops, + .bind = nds32_mmc_bind, + .probe = nds32_mmc_probe, + .priv_auto_alloc_size = sizeof(struct ftsdc_priv), + .platdata_auto_alloc_size = sizeof(struct nds_mmc_plat), +}; diff --git a/drivers/mmc/rockchip_dw_mmc.c b/drivers/mmc/rockchip_dw_mmc.c index 20c083db632..c11988914a7 100644 --- a/drivers/mmc/rockchip_dw_mmc.c +++ b/drivers/mmc/rockchip_dw_mmc.c @@ -30,7 +30,6 @@ struct rockchip_mmc_plat { struct rockchip_dwmmc_priv { struct clk clk; - struct clk sample_clk; struct dwmci_host host; int fifo_depth; bool fifo_mode; @@ -43,13 +42,6 @@ static uint rockchip_dwmmc_get_mmc_clk(struct dwmci_host *host, uint freq) struct rockchip_dwmmc_priv *priv = dev_get_priv(dev); int ret; - /* - * If DDR52 8bit mode(only emmc work in 8bit mode), - * divider must be set 1 - */ - if (mmc_card_ddr52(host->mmc) && host->mmc->bus_width == 8) - freq *= 2; - ret = clk_set_rate(&priv->clk, freq); if (ret < 0) { debug("%s: err=%d\n", __func__, ret); @@ -81,7 +73,11 @@ static int rockchip_dwmmc_ofdata_to_platdata(struct udevice *dev) if (priv->fifo_depth < 0) return -EINVAL; +#ifdef CONFIG_SPL_BUILD + priv->fifo_mode = true; // always force fifo mode +#else priv->fifo_mode = dev_read_bool(dev, "fifo-mode"); +#endif /* * 'clock-freq-min-max' is deprecated @@ -103,123 +99,6 @@ static int rockchip_dwmmc_ofdata_to_platdata(struct udevice *dev) return 0; } -#define NUM_PHASES 270 -#define TUNING_ITERATION_TO_PHASE(i) (DIV_ROUND_UP((i) * 270, NUM_PHASES)) - -static int rockchip_dwmmc_execute_tuning(struct dwmci_host *host, u32 opcode) -{ - int ret = 0; - int i; - bool v, prev_v = 0, first_v; - struct range_t { - int start; - int end; /* inclusive */ - }; - struct range_t *ranges; - unsigned int range_count = 0; - int longest_range_len = -1; - int longest_range = -1; - int middle_phase; - struct udevice *dev = host->priv; - struct rockchip_dwmmc_priv *priv = dev_get_priv(dev); - struct mmc *mmc = host->mmc; - - if (IS_ERR(&priv->sample_clk)) - return -EIO; - - ranges = calloc(sizeof(*ranges), NUM_PHASES / 2 + 1); - if (!ranges) - return -ENOMEM; - - /* Try each phase and extract good ranges */ - for (i = 0; i < NUM_PHASES; ) { - clk_set_phase(&priv->sample_clk, TUNING_ITERATION_TO_PHASE(i)); - - v = !mmc_send_tuning(mmc, opcode); - - if (i == 0) - first_v = v; - - if ((!prev_v) && v) { - range_count++; - ranges[range_count - 1].start = i; - } - if (v) { - ranges[range_count - 1].end = i; - i++; - } else if (i == NUM_PHASES - 1) { - /* No extra skipping rules if we're at the end */ - i++; - } else { - /* - * No need to check too close to an invalid - * one since testing bad phases is slow. Skip - * 20 degrees. - */ - i += DIV_ROUND_UP(20 * NUM_PHASES, NUM_PHASES); - - /* Always test the last one */ - if (i >= NUM_PHASES) - i = NUM_PHASES - 1; - } - - prev_v = v; - } - - if (range_count == 0) { - debug("All phases bad!"); - ret = -EIO; - goto free; - } - - /* wrap around case, merge the end points */ - if ((range_count > 1) && first_v && v) { - ranges[0].start = ranges[range_count - 1].start; - range_count--; - } - - if (ranges[0].start == 0 && ranges[0].end == NUM_PHASES - 1) { - clk_set_phase(&priv->sample_clk, - TUNING_ITERATION_TO_PHASE(NUM_PHASES / 2)); - debug("All phases work, using middle phase.\n"); - goto free; - } - - /* Find the longest range */ - for (i = 0; i < range_count; i++) { - int len = (ranges[i].end - ranges[i].start + 1); - - if (len < 0) - len += NUM_PHASES; - - if (longest_range_len < len) { - longest_range_len = len; - longest_range = i; - } - - debug("Good phase range %d-%d (%d len)\n", - TUNING_ITERATION_TO_PHASE(ranges[i].start), - TUNING_ITERATION_TO_PHASE(ranges[i].end), len); - } - - printf("Best phase range %d-%d (%d len)\n", - TUNING_ITERATION_TO_PHASE(ranges[longest_range].start), - TUNING_ITERATION_TO_PHASE(ranges[longest_range].end), - longest_range_len); - - middle_phase = ranges[longest_range].start + longest_range_len / 2; - middle_phase %= NUM_PHASES; - debug("Successfully tuned phase to %d\n", - TUNING_ITERATION_TO_PHASE(middle_phase)); - - clk_set_phase(&priv->sample_clk, - TUNING_ITERATION_TO_PHASE(middle_phase)); - -free: - free(ranges); - return ret; -} - static int rockchip_dwmmc_probe(struct udevice *dev) { struct rockchip_mmc_plat *plat = dev_get_platdata(dev); @@ -236,7 +115,6 @@ static int rockchip_dwmmc_probe(struct udevice *dev) host->ioaddr = map_sysmem(dtplat->reg[0], dtplat->reg[1]); host->buswidth = dtplat->bus_width; host->get_mmc_clk = rockchip_dwmmc_get_mmc_clk; - host->execute_tuning = rockchip_dwmmc_execute_tuning; host->priv = dev; host->dev_index = 0; priv->fifo_depth = dtplat->fifo_depth; @@ -251,8 +129,6 @@ static int rockchip_dwmmc_probe(struct udevice *dev) ret = clk_get_by_index(dev, 0, &priv->clk); if (ret < 0) return ret; - clk_get_by_name(dev, "ciu_sample", &priv->sample_clk); - host->execute_tuning = rockchip_dwmmc_execute_tuning; #endif host->fifoth_val = MSIZE(0x2) | RX_WMARK(priv->fifo_depth / 2 - 1) | @@ -260,12 +136,6 @@ static int rockchip_dwmmc_probe(struct udevice *dev) host->fifo_mode = priv->fifo_mode; -#ifdef CONFIG_ROCKCHIP_RK3128 - host->stride_pio = true; -#else - host->stride_pio = false; -#endif - #ifdef CONFIG_PWRSEQ /* Enable power if needed */ ret = uclass_get_device_by_phandle(UCLASS_PWRSEQ, dev, "mmc-pwrseq", @@ -277,7 +147,6 @@ static int rockchip_dwmmc_probe(struct udevice *dev) } #endif dwmci_setup_cfg(&plat->cfg, host, priv->minmax[1], priv->minmax[0]); - plat->cfg.host_caps |= MMC_MODE_DDR_52MHz; host->mmc = &plat->mmc; host->mmc->priv = &priv->host; host->mmc->dev = dev; @@ -295,7 +164,6 @@ static int rockchip_dwmmc_bind(struct udevice *dev) static const struct udevice_id rockchip_dwmmc_ids[] = { { .compatible = "rockchip,rk3288-dw-mshc" }, - { .compatible = "rockchip,rk2928-dw-mshc" }, { } }; diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c index a05a4227285..c05b511b38a 100644 --- a/drivers/mmc/rockchip_sdhci.c +++ b/drivers/mmc/rockchip_sdhci.c @@ -6,11 +6,9 @@ * SPDX-License-Identifier: GPL-2.0+ */ -#include #include #include #include -#include #include #include #include @@ -29,151 +27,11 @@ struct rockchip_sdhc_plat { struct mmc mmc; }; -struct rockchip_emmc_phy { - u32 emmcphy_con[7]; - u32 reserved; - u32 emmcphy_status; -}; - struct rockchip_sdhc { struct sdhci_host host; void *base; - struct rockchip_emmc_phy *phy; -}; - -#define PHYCTRL_CALDONE_MASK 0x1 -#define PHYCTRL_CALDONE_SHIFT 0x6 -#define PHYCTRL_CALDONE_DONE 0x1 - -#define PHYCTRL_DLLRDY_MASK 0x1 -#define PHYCTRL_DLLRDY_SHIFT 0x5 -#define PHYCTRL_DLLRDY_DONE 0x1 - -#define PHYCTRL_FREQSEL_200M 0x0 -#define PHYCTRL_FREQSEL_50M 0x1 -#define PHYCTRL_FREQSEL_100M 0x2 -#define PHYCTRL_FREQSEL_150M 0x3 - -#define KHz (1000) -#define MHz (1000 * KHz) - -static void rk3399_emmc_phy_power_on(struct rockchip_emmc_phy *phy, u32 clock) -{ - u32 caldone, dllrdy, freqsel; - uint start; - - writel(RK_CLRSETBITS(7 << 4, 0), &phy->emmcphy_con[6]); - writel(RK_CLRSETBITS(1 << 11, 1 << 11), &phy->emmcphy_con[0]); - writel(RK_CLRSETBITS(0xf << 7, 4 << 7), &phy->emmcphy_con[0]); - - /* - * According to the user manual, calpad calibration - * cycle takes more than 2us without the minimal recommended - * value, so we may need a little margin here - */ - udelay(3); - writel(RK_CLRSETBITS(1, 1), &phy->emmcphy_con[6]); - - /* - * According to the user manual, it asks driver to - * wait 5us for calpad busy trimming - */ - udelay(5); - caldone = readl(&phy->emmcphy_status); - caldone = (caldone >> PHYCTRL_CALDONE_SHIFT) & PHYCTRL_CALDONE_MASK; - if (caldone != PHYCTRL_CALDONE_DONE) { - debug("%s: caldone timeout.\n", __func__); - return; - } - - /* Set the frequency of the DLL operation */ - if (clock < 75 * MHz) - freqsel = PHYCTRL_FREQSEL_50M; - else if (clock < 125 * MHz) - freqsel = PHYCTRL_FREQSEL_100M; - else if (clock < 175 * MHz) - freqsel = PHYCTRL_FREQSEL_150M; - else - freqsel = PHYCTRL_FREQSEL_200M; - - /* Set the frequency of the DLL operation */ - writel(RK_CLRSETBITS(3 << 12, freqsel << 12), &phy->emmcphy_con[0]); - writel(RK_CLRSETBITS(1 << 1, 1 << 1), &phy->emmcphy_con[6]); - - start = get_timer(0); - - do { - udelay(1); - dllrdy = readl(&phy->emmcphy_status); - dllrdy = (dllrdy >> PHYCTRL_DLLRDY_SHIFT) & PHYCTRL_DLLRDY_MASK; - if (dllrdy == PHYCTRL_DLLRDY_DONE) - break; - } while (get_timer(start) < 50000); - - if (dllrdy != PHYCTRL_DLLRDY_DONE) - debug("%s: dllrdy timeout.\n", __func__); -} - -static void rk3399_emmc_phy_power_off(struct rockchip_emmc_phy *phy) -{ - writel(RK_CLRSETBITS(1, 0), &phy->emmcphy_con[6]); - writel(RK_CLRSETBITS(1 << 1, 0), &phy->emmcphy_con[6]); -} - -static int arasan_sdhci_set_clock(struct sdhci_host *host, unsigned int clock) -{ - struct rockchip_sdhc *priv = - container_of(host, struct rockchip_sdhc, host); - int cycle_phy = host->clock != clock && - clock > EMMC_MIN_FREQ; - - if (cycle_phy) - rk3399_emmc_phy_power_off(priv->phy); - - sdhci_set_clock(host, clock); - - if (cycle_phy) - rk3399_emmc_phy_power_on(priv->phy, clock); - - return 0; -} - -static struct sdhci_ops arasan_sdhci_ops = { - .set_clock = arasan_sdhci_set_clock, }; -static int arasan_get_phy(struct udevice *dev) -{ - struct rockchip_sdhc *priv = dev_get_priv(dev); - -#if CONFIG_IS_ENABLED(OF_PLATDATA) - priv->phy = (struct rockchip_emmc_phy *)0xff77f780; -#else - int phy_node, grf_node; - fdt_addr_t grf_base, grf_phy_offset; - - phy_node = fdtdec_lookup_phandle(gd->fdt_blob, - dev_of_offset(dev), "phys"); - if (phy_node <= 0) { - debug("Not found emmc phy device\n"); - return -ENODEV; - } - - grf_node = fdt_parent_offset(gd->fdt_blob, phy_node); - if (grf_node <= 0) { - debug("Not found usb phy device\n"); - return -ENODEV; - } - - grf_base = fdtdec_get_addr(gd->fdt_blob, grf_node, "reg"); - grf_phy_offset = fdtdec_get_addr_size_auto_parent(gd->fdt_blob, - grf_node, phy_node, "reg", 0, NULL, false); - - priv->phy = (struct rockchip_emmc_phy *)(grf_base + grf_phy_offset); -#endif - return 0; -} - static int arasan_sdhci_probe(struct udevice *dev) { struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); @@ -188,24 +46,10 @@ static int arasan_sdhci_probe(struct udevice *dev) host->name = dev->name; host->ioaddr = map_sysmem(dtplat->reg[0], dtplat->reg[1]); - host->host_caps |= MMC_MODE_8BIT; max_frequency = dtplat->max_frequency; ret = clk_get_by_index_platdata(dev, 0, dtplat->clocks, &clk); #else max_frequency = dev_read_u32_default(dev, "max-frequency", 0); - switch (dev_read_u32_default(dev, "bus-width", 4)) { - case 8: - host->host_caps |= MMC_MODE_8BIT; - break; - case 4: - host->host_caps |= MMC_MODE_4BIT; - break; - case 1: - break; - default: - printf("Invalid \"bus-width\" value\n"); - return -EINVAL; - } ret = clk_get_by_index(dev, 0, &clk); #endif if (!ret) { @@ -216,14 +60,15 @@ static int arasan_sdhci_probe(struct udevice *dev) printf("%s fail to get clk\n", __func__); } - ret = arasan_get_phy(dev); - if (ret) - return ret; - - host->ops = &arasan_sdhci_ops; - host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD; host->max_clk = max_frequency; + /* + * The sdhci-driver only supports 4bit and 8bit, as sdhci_setup_cfg + * doesn't allow us to clear MMC_MODE_4BIT. Consequently, we don't + * check for other bus-width values. + */ + if (host->bus_width == 8) + host->host_caps |= MMC_MODE_8BIT; ret = sdhci_setup_cfg(&plat->cfg, host, 0, EMMC_MIN_FREQ); @@ -243,7 +88,8 @@ static int arasan_sdhci_ofdata_to_platdata(struct udevice *dev) struct sdhci_host *host = dev_get_priv(dev); host->name = dev->name; - host->ioaddr = devfdt_get_addr_ptr(dev); + host->ioaddr = (void *)devfdt_get_addr(dev); + host->bus_width = dev_read_u32_default(dev, "bus-width", 4); #endif return 0; diff --git a/drivers/mmc/rpmb.c b/drivers/mmc/rpmb.c index dda84de781e..0b6b6222bdc 100644 --- a/drivers/mmc/rpmb.c +++ b/drivers/mmc/rpmb.c @@ -40,6 +40,12 @@ #define RPMB_ERR_CNT_EXPIRED 0x80 #define RPMB_ERR_MSK 0x7 +/* Sizes of RPMB data frame */ +#define RPMB_SZ_STUFF 196 +#define RPMB_SZ_MAC 32 +#define RPMB_SZ_DATA 256 +#define RPMB_SZ_NONCE 16 + #define SHA256_BLOCK_SIZE 64 /* Error messages */ @@ -54,6 +60,20 @@ static const char * const rpmb_err_msg[] = { "Authentication key not yet programmed", }; + +/* Structure of RPMB data frame. */ +struct s_rpmb { + unsigned char stuff[RPMB_SZ_STUFF]; + unsigned char mac[RPMB_SZ_MAC]; + unsigned char data[RPMB_SZ_DATA]; + unsigned char nonce[RPMB_SZ_NONCE]; + unsigned int write_counter; + unsigned short address; + unsigned short block_count; + unsigned short result; + unsigned short request; +}; + static int mmc_set_blockcount(struct mmc *mmc, unsigned int blockcount, bool is_rel_write) { @@ -67,7 +87,7 @@ static int mmc_set_blockcount(struct mmc *mmc, unsigned int blockcount, return mmc_send_cmd(mmc, &cmd, NULL); } -static int mmc_rpmb_request(struct mmc *mmc, const void *s, +static int mmc_rpmb_request(struct mmc *mmc, const struct s_rpmb *s, unsigned int count, bool is_rel_write) { struct mmc_cmd cmd = {0}; @@ -87,7 +107,7 @@ static int mmc_rpmb_request(struct mmc *mmc, const void *s, cmd.resp_type = MMC_RSP_R1b; data.src = (const char *)s; - data.blocks = count; + data.blocks = 1; data.blocksize = MMC_MAX_BLOCK_LEN; data.flags = MMC_DATA_WRITE; @@ -101,13 +121,13 @@ static int mmc_rpmb_request(struct mmc *mmc, const void *s, return 0; } static int mmc_rpmb_response(struct mmc *mmc, struct s_rpmb *s, - unsigned short expected, unsigned short cnt) + unsigned short expected) { struct mmc_cmd cmd = {0}; struct mmc_data data; int ret; - ret = mmc_set_blockcount(mmc, cnt, false); + ret = mmc_set_blockcount(mmc, 1, false); if (ret) { #ifdef CONFIG_MMC_RPMB_TRACE printf("%s:mmc_set_blockcount-> %d\n", __func__, ret); @@ -119,7 +139,7 @@ static int mmc_rpmb_response(struct mmc *mmc, struct s_rpmb *s, cmd.resp_type = MMC_RSP_R1; data.dest = (char *)s; - data.blocks = cnt; + data.blocks = 1; data.blocksize = MMC_MAX_BLOCK_LEN; data.flags = MMC_DATA_READ; @@ -158,7 +178,7 @@ static int mmc_rpmb_status(struct mmc *mmc, unsigned short expected) return -1; /* Read the result */ - return mmc_rpmb_response(mmc, rpmb_frame, expected, 1); + return mmc_rpmb_response(mmc, rpmb_frame, expected); } static void rpmb_hmac(unsigned char *key, unsigned char *buff, int len, unsigned char *output) @@ -216,7 +236,7 @@ int mmc_rpmb_get_counter(struct mmc *mmc, unsigned long *pcounter) return -1; /* Read the result */ - ret = mmc_rpmb_response(mmc, rpmb_frame, RPMB_RESP_WCOUNTER, 1); + ret = mmc_rpmb_response(mmc, rpmb_frame, RPMB_RESP_WCOUNTER); if (ret) return ret; @@ -240,168 +260,65 @@ int mmc_rpmb_set_key(struct mmc *mmc, void *key) int mmc_rpmb_read(struct mmc *mmc, void *addr, unsigned short blk, unsigned short cnt, unsigned char *key) { - ALLOC_CACHE_ALIGN_BUFFER - (char, rpmb_frame_data, - sizeof(struct s_rpmb) * cnt); - ALLOC_CACHE_ALIGN_BUFFER - (char, rpmb_frame_data_verify, - sizeof(struct s_rpmb_verify) * cnt); - struct s_rpmb *rpmb_frame; - struct s_rpmb_verify *rpmb_frame_vrify; + ALLOC_CACHE_ALIGN_BUFFER(struct s_rpmb, rpmb_frame, 1); int i; - memset(rpmb_frame_data, 0, sizeof(struct s_rpmb) * cnt); - memset(rpmb_frame_data_verify, 0, sizeof(struct s_rpmb_verify) * cnt); - rpmb_frame = (struct s_rpmb *)rpmb_frame_data; - rpmb_frame->address = cpu_to_be16(blk); - rpmb_frame->request = cpu_to_be16(RPMB_REQ_READ_DATA); - if (mmc_rpmb_request(mmc, rpmb_frame, 1, false)) { - printf("mmc_rpmb_read request error\n"); - return -1; - } - - if (mmc_rpmb_response - (mmc, - (struct s_rpmb *)rpmb_frame_data, - RPMB_RESP_READ_DATA, cnt)) { - printf("mmc_rpmb_read response error\n"); - return -1; - } - for (i = 0; i < cnt; i++) { - rpmb_frame = (struct s_rpmb *) - (rpmb_frame_data + - i * sizeof(struct s_rpmb)); - - rpmb_frame_vrify = (struct s_rpmb_verify *) - (rpmb_frame_data_verify + - i * sizeof(struct s_rpmb_verify)); - memcpy(addr + i * RPMB_SZ_DATA, rpmb_frame->data, RPMB_SZ_DATA); - memcpy(rpmb_frame_vrify->data, rpmb_frame->data, 284); - } - - if (key) { - unsigned char ret_hmac[RPMB_SZ_MAC]; - rpmb_hmac - (key, (unsigned char *)rpmb_frame_data_verify, - 284 * cnt, ret_hmac); - if (memcmp(ret_hmac, rpmb_frame->mac, RPMB_SZ_MAC)) { - printf("MAC error on block #%d\n", i); - return -1; + /* Fill the request */ + memset(rpmb_frame, 0, sizeof(struct s_rpmb)); + rpmb_frame->address = cpu_to_be16(blk + i); + rpmb_frame->request = cpu_to_be16(RPMB_REQ_READ_DATA); + if (mmc_rpmb_request(mmc, rpmb_frame, 1, false)) + break; + + /* Read the result */ + if (mmc_rpmb_response(mmc, rpmb_frame, RPMB_RESP_READ_DATA)) + break; + + /* Check the HMAC if key is provided */ + if (key) { + unsigned char ret_hmac[RPMB_SZ_MAC]; + + rpmb_hmac(key, rpmb_frame->data, 284, ret_hmac); + if (memcmp(ret_hmac, rpmb_frame->mac, RPMB_SZ_MAC)) { + printf("MAC error on block #%d\n", i); + break; + } } + /* Copy data */ + memcpy(addr + i * RPMB_SZ_DATA, rpmb_frame->data, RPMB_SZ_DATA); } - - return cnt; + return i; } int mmc_rpmb_write(struct mmc *mmc, void *addr, unsigned short blk, unsigned short cnt, unsigned char *key) { - struct s_rpmb *rpmb_frame; - struct s_rpmb_verify *rpmb_frame_vrify; - ALLOC_CACHE_ALIGN_BUFFER - (char, rpmb_frame_data, - sizeof(struct s_rpmb) * cnt); - ALLOC_CACHE_ALIGN_BUFFER - (char, rpmb_frame_data_verify, - sizeof(struct s_rpmb_verify) * cnt); - + ALLOC_CACHE_ALIGN_BUFFER(struct s_rpmb, rpmb_frame, 1); unsigned long wcount; - unsigned short i; - unsigned short temp; + int i; - temp = cnt - 1; - memset(rpmb_frame_data, 0, sizeof(struct s_rpmb) * cnt); - memset(rpmb_frame_data_verify, 0, sizeof(struct s_rpmb_verify) * cnt); for (i = 0; i < cnt; i++) { - if (i == 0) { - if (mmc_rpmb_get_counter(mmc, &wcount)) { - printf("Cannot read RPMB write counter\n"); - break; - } + if (mmc_rpmb_get_counter(mmc, &wcount)) { + printf("Cannot read RPMB write counter\n"); + break; } - rpmb_frame = (struct s_rpmb *) - (rpmb_frame_data + - i * sizeof(struct s_rpmb)); - rpmb_frame_vrify = (struct s_rpmb_verify *) - (rpmb_frame_data_verify + - i * sizeof(struct s_rpmb_verify)); + /* Fill the request */ + memset(rpmb_frame, 0, sizeof(struct s_rpmb)); memcpy(rpmb_frame->data, addr + i * RPMB_SZ_DATA, RPMB_SZ_DATA); - memcpy(rpmb_frame_vrify->data, addr + - i * RPMB_SZ_DATA, RPMB_SZ_DATA); - rpmb_frame->address = cpu_to_be16(blk); - rpmb_frame_vrify->address = cpu_to_be16(blk); - rpmb_frame->block_count = cpu_to_be16(cnt); - rpmb_frame_vrify->block_count = cpu_to_be16(cnt); + rpmb_frame->address = cpu_to_be16(blk + i); + rpmb_frame->block_count = cpu_to_be16(1); rpmb_frame->write_counter = cpu_to_be32(wcount); - rpmb_frame_vrify->write_counter = cpu_to_be32(wcount); rpmb_frame->request = cpu_to_be16(RPMB_REQ_WRITE_DATA); - rpmb_frame_vrify->request = cpu_to_be16(RPMB_REQ_WRITE_DATA); - if (i == temp) { - rpmb_hmac - (key, (unsigned char *)rpmb_frame_data_verify, - 284 * cnt, rpmb_frame->mac); - } - } - if (mmc_rpmb_request(mmc, rpmb_frame_data, cnt, true)) - return -1; - - if (mmc_rpmb_status(mmc, RPMB_RESP_WRITE_DATA)) - return -1; - return cnt; -} + /* Computes HMAC */ + rpmb_hmac(key, rpmb_frame->data, 284, rpmb_frame->mac); -int read_counter(struct mmc *mmc, struct s_rpmb *requestpackets) -{ - if (mmc_rpmb_request(mmc, requestpackets, 1, false)) - return -1; + if (mmc_rpmb_request(mmc, rpmb_frame, 1, true)) + break; - if (mmc_rpmb_response(mmc, requestpackets, RPMB_RESP_WCOUNTER, 1)) - return -1; - - return 0; -} - -int program_key(struct mmc *mmc, struct s_rpmb *requestpackets) -{ - if (mmc_rpmb_request(mmc, requestpackets, 1, true)) - return -1; - - memset(requestpackets, 0, sizeof(struct s_rpmb)); - - requestpackets->request = cpu_to_be16(RPMB_REQ_STATUS); - - if (mmc_rpmb_request(mmc, requestpackets, 1, false)) - return -1; - - return mmc_rpmb_response(mmc, requestpackets, RPMB_RESP_KEY, 1); -} - -int authenticated_read(struct mmc *mmc, - struct s_rpmb *requestpackets, uint16_t block_count) -{ - if (mmc_rpmb_request(mmc, requestpackets, 1, false)) - return -1; - - if (mmc_rpmb_response - (mmc, requestpackets, RPMB_RESP_READ_DATA, block_count)) - return -1; - - return 0; -} - -int authenticated_write(struct mmc *mmc, struct s_rpmb *requestpackets) -{ - if (mmc_rpmb_request(mmc, requestpackets, 1, true)) - return -1; - - memset(requestpackets, 0, sizeof(struct s_rpmb)); - - requestpackets->request = cpu_to_be16(RPMB_REQ_STATUS); - - if (mmc_rpmb_request(mmc, requestpackets, 1, false)) - return -1; - - return mmc_rpmb_response(mmc, requestpackets, RPMB_RESP_WRITE_DATA, 1); + /* Get status */ + if (mmc_rpmb_status(mmc, RPMB_RESP_WRITE_DATA)) + break; + } + return i; } - diff --git a/drivers/mmc/s5p_sdhci.c b/drivers/mmc/s5p_sdhci.c index 95447310ab6..62817a0d074 100644 --- a/drivers/mmc/s5p_sdhci.c +++ b/drivers/mmc/s5p_sdhci.c @@ -73,14 +73,14 @@ static void s5p_sdhci_set_control_reg(struct sdhci_host *host) sdhci_writel(host, ctrl, SDHCI_CONTROL2); } -static void s5p_set_clock_ext(struct sdhci_host *host, u32 div) +static void s5p_set_clock(struct sdhci_host *host, u32 div) { /* ToDo : Use the Clock Framework */ set_mmc_clk(host->index, div); } static const struct sdhci_ops s5p_sdhci_ops = { - .set_clock_ext = &s5p_set_clock_ext, + .set_clock = &s5p_set_clock, .set_control_reg = &s5p_sdhci_set_control_reg, }; diff --git a/drivers/mmc/sdhci-cadence.c b/drivers/mmc/sdhci-cadence.c index f83c1d72410..72d1c646a2b 100644 --- a/drivers/mmc/sdhci-cadence.c +++ b/drivers/mmc/sdhci-cadence.c @@ -23,6 +23,18 @@ #define SDHCI_CDNS_HRS04_WDATA_SHIFT 8 #define SDHCI_CDNS_HRS04_ADDR_SHIFT 0 +#define SDHCI_CDNS_HRS06 0x18 /* eMMC control */ +#define SDHCI_CDNS_HRS06_TUNE_UP BIT(15) +#define SDHCI_CDNS_HRS06_TUNE_SHIFT 8 +#define SDHCI_CDNS_HRS06_TUNE_MASK 0x3f +#define SDHCI_CDNS_HRS06_MODE_MASK 0x7 +#define SDHCI_CDNS_HRS06_MODE_SD 0x0 +#define SDHCI_CDNS_HRS06_MODE_MMC_SDR 0x2 +#define SDHCI_CDNS_HRS06_MODE_MMC_DDR 0x3 +#define SDHCI_CDNS_HRS06_MODE_MMC_HS200 0x4 +#define SDHCI_CDNS_HRS06_MODE_MMC_HS400 0x5 +#define SDHCI_CDNS_HRS06_MODE_MMC_HS400ES 0x6 + /* SRS - Slot Register Set (SDHCI-compatible) */ #define SDHCI_CDNS_SRS_BASE 0x200 @@ -111,6 +123,44 @@ static int sdhci_cdns_phy_init(struct sdhci_cdns_plat *plat, return 0; } +static void sdhci_cdns_set_control_reg(struct sdhci_host *host) +{ + struct mmc *mmc = host->mmc; + struct sdhci_cdns_plat *plat = dev_get_platdata(mmc->dev); + unsigned int clock = mmc->clock; + u32 mode, tmp; + + /* + * REVISIT: + * The mode should be decided by MMC_TIMING_* like Linux, but + * U-Boot does not support timing. Use the clock frequency instead. + */ + if (clock <= 26000000) + mode = SDHCI_CDNS_HRS06_MODE_SD; /* use this for Legacy */ + else if (clock <= 52000000) { + if (mmc->ddr_mode) + mode = SDHCI_CDNS_HRS06_MODE_MMC_DDR; + else + mode = SDHCI_CDNS_HRS06_MODE_MMC_SDR; + } else { + /* + * REVISIT: + * The IP supports HS200/HS400, revisit once U-Boot support it + */ + printf("unsupported frequency %d\n", clock); + return; + } + + tmp = readl(plat->hrs_addr + SDHCI_CDNS_HRS06); + tmp &= ~SDHCI_CDNS_HRS06_MODE_MASK; + tmp |= mode; + writel(tmp, plat->hrs_addr + SDHCI_CDNS_HRS06); +} + +static const struct sdhci_ops sdhci_cdns_ops = { + .set_control_reg = sdhci_cdns_set_control_reg, +}; + static int sdhci_cdns_bind(struct udevice *dev) { struct sdhci_cdns_plat *plat = dev_get_platdata(dev); @@ -137,6 +187,7 @@ static int sdhci_cdns_probe(struct udevice *dev) host->name = dev->name; host->ioaddr = plat->hrs_addr + SDHCI_CDNS_SRS_BASE; + host->ops = &sdhci_cdns_ops; host->quirks |= SDHCI_QUIRK_WAIT_SEND_CMD; ret = sdhci_cdns_phy_init(plat, gd->fdt_blob, dev_of_offset(dev)); diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index f5ae3a6bdc8..11d1f0c24cd 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -158,10 +158,7 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd, static unsigned int cmd_timeout = SDHCI_CMD_DEFAULT_TIMEOUT; sdhci_writel(host, SDHCI_INT_ALL_MASK, SDHCI_INT_STATUS); - mask = SDHCI_CMD_INHIBIT; - - if (data) - mask |= SDHCI_DATA_INHIBIT; + mask = SDHCI_CMD_INHIBIT | SDHCI_DATA_INHIBIT; /* We shouldn't wait for data inihibit for stop commands, even though they might use busy signaling */ @@ -203,13 +200,6 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd, if (data) flags |= SDHCI_CMD_DATA; - if (cmd->cmdidx == MMC_SEND_TUNING_BLOCK || - cmd->cmdidx == MMC_SEND_TUNING_BLOCK_HS200) { - mask &= ~SDHCI_INT_RESPONSE; - mask |= SDHCI_INT_DATA_AVAIL; - flags |= SDHCI_CMD_DATA; - } - /* Set Transfer mode regarding to data flag */ if (data != 0) { sdhci_writeb(host, 0xe, SDHCI_TIMEOUT_CONTROL); @@ -311,8 +301,9 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd, return -ECOMM; } -int sdhci_set_clock(struct sdhci_host *host, unsigned int clock) +static int sdhci_set_clock(struct mmc *mmc, unsigned int clock) { + struct sdhci_host *host = mmc->priv; unsigned int div, clk = 0, timeout; /* Wait max 20 ms */ @@ -328,10 +319,12 @@ int sdhci_set_clock(struct sdhci_host *host, unsigned int clock) timeout--; udelay(100); } + sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); if (clock == 0) return 0; + if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) { /* * Check if the Host Controller supports Programmable Clock @@ -371,8 +364,9 @@ int sdhci_set_clock(struct sdhci_host *host, unsigned int clock) } div >>= 1; } - if (host->ops && host->ops->set_clock_ext) - host->ops->set_clock_ext(host, div); + + if (host->ops && host->ops->set_clock) + host->ops->set_clock(host, div); clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT; clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN) @@ -392,10 +386,9 @@ int sdhci_set_clock(struct sdhci_host *host, unsigned int clock) timeout--; udelay(1000); } + clk |= SDHCI_CLOCK_CARD_EN; sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); - - host->clock = clock; return 0; } @@ -429,56 +422,6 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power) sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); } -static void sdhci_set_uhs_signaling(struct sdhci_host *host) -{ - u16 ctrl_2; - u32 timing = host->mmc->timing; - - ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); - /* Select Bus Speed Mode for host */ - ctrl_2 &= ~SDHCI_CTRL_UHS_MASK; - - if ((timing != MMC_TIMING_LEGACY) && - (timing != MMC_TIMING_MMC_HS) && - (timing != MMC_TIMING_SD_HS)) - ctrl_2 |= SDHCI_CTRL_VDD_180; - - if ((timing == MMC_TIMING_MMC_HS200) || - (timing == MMC_TIMING_UHS_SDR104)) - ctrl_2 |= SDHCI_CTRL_UHS_SDR104 | SDHCI_CTRL_DRV_TYPE_A; - else if (timing == MMC_TIMING_UHS_SDR12) - ctrl_2 |= SDHCI_CTRL_UHS_SDR12; - else if (timing == MMC_TIMING_UHS_SDR25) - ctrl_2 |= SDHCI_CTRL_UHS_SDR25; - else if (timing == MMC_TIMING_UHS_SDR50) - ctrl_2 |= SDHCI_CTRL_UHS_SDR50; - else if ((timing == MMC_TIMING_UHS_DDR50) || - (timing == MMC_TIMING_MMC_DDR52)) - ctrl_2 |= SDHCI_CTRL_UHS_DDR50; - else if (timing == MMC_TIMING_MMC_HS400 || - timing == MMC_TIMING_MMC_HS400ES) - ctrl_2 |= SDHCI_CTRL_HS400 | SDHCI_CTRL_DRV_TYPE_A; - - sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); -} - -#ifdef CONFIG_DM_MMC -static bool sdhci_card_busy(struct udevice *dev) -{ - struct mmc *mmc = mmc_get_mmc_dev(dev); -#else -static bool sdhci_card_busy(struct mmc *mmc) -{ -#endif - struct sdhci_host *host = mmc->priv; - u32 present_state; - - /* Check whether DAT[0] is 0 */ - present_state = sdhci_readl(host, SDHCI_PRESENT_STATE); - - return !(present_state & SDHCI_DATA_0_LVL); -} - #ifdef CONFIG_DM_MMC static int sdhci_set_ios(struct udevice *dev) { @@ -493,12 +436,8 @@ static int sdhci_set_ios(struct mmc *mmc) if (host->ops && host->ops->set_control_reg) host->ops->set_control_reg(host); - if (mmc->clock != host->clock) { - if (host->ops && host->ops->set_clock) - host->ops->set_clock(host, mmc->clock); - else - sdhci_set_clock(host, mmc->clock); - } + if (mmc->clock != host->clock) + sdhci_set_clock(mmc, mmc->clock); /* Set bus width */ ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); @@ -517,20 +456,15 @@ static int sdhci_set_ios(struct mmc *mmc) ctrl &= ~SDHCI_CTRL_4BITBUS; } - if (!(mmc->timing == MMC_TIMING_LEGACY) && - !(host->quirks & SDHCI_QUIRK_NO_HISPD_BIT)) + if (mmc->clock > 26000000) ctrl |= SDHCI_CTRL_HISPD; else ctrl &= ~SDHCI_CTRL_HISPD; - sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); - - if ((mmc->timing != MMC_TIMING_LEGACY) && - (mmc->timing != MMC_TIMING_MMC_HS) && - (mmc->timing != MMC_TIMING_SD_HS)) - sdhci_set_power(host, MMC_VDD_165_195_SHIFT); + if (host->quirks & SDHCI_QUIRK_NO_HISPD_BIT) + ctrl &= ~SDHCI_CTRL_HISPD; - sdhci_set_uhs_signaling(host); + sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); /* If available, call the driver specific "post" set_ios() function */ if (host->ops && host->ops->set_ios_post) @@ -568,108 +502,6 @@ static int sdhci_init(struct mmc *mmc) return 0; } -static int sdhci_send_tuning(struct sdhci_host *host, u32 opcode) -{ - struct mmc_cmd cmd; - - cmd.cmdidx = opcode; - cmd.resp_type = MMC_RSP_R1; - cmd.cmdarg = 0; - /* - * In response to CMD19, the card sends 64 bytes of tuning - * block to the Host Controller. So we set the block size - * to 64 here. - */ - if (opcode == MMC_SEND_TUNING_BLOCK_HS200 && - host->mmc->bus_width == MMC_BUS_WIDTH_8BIT) - sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 128), SDHCI_BLOCK_SIZE); - else - sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 64), SDHCI_BLOCK_SIZE); - - /* - * The tuning block is sent by the card to the host controller. - * So we set the TRNS_READ bit in the Transfer Mode register. - * This also takes care of setting DMA Enable and Multi Block - * Select in the same register to 0. - */ - sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE); - -#ifdef CONFIG_DM_MMC - return sdhci_send_command(host->mmc->dev, &cmd, NULL); -#else - return sdhci_send_command(host->mmc, &cmd, NULL); -#endif -} - -#define MAX_TUNING_LOOP 40 -static int __sdhci_execute_tuning(struct sdhci_host *host, u32 opcode) -{ - int i; - int ret; - - /* - * Issue opcode repeatedly till Execute Tuning is set to 0 or the number - * of loops reaches 40 times. - */ - for (i = 0; i < MAX_TUNING_LOOP; i++) { - u16 ctrl; - - ret = sdhci_send_tuning(host, opcode); - - if (ret) - return ret; - - ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); - if (!(ctrl & SDHCI_CTRL_EXEC_TUNING)) { - if (ctrl & SDHCI_CTRL_TUNED_CLK) - /* Tuning successfully */ - return 0; - break; - } - } - - return -ETIMEDOUT; -} - -#ifdef CONFIG_DM_MMC -static int sdhci_execute_tuning(struct udevice *dev, u32 opcode) -{ - struct mmc *mmc = mmc_get_mmc_dev(dev); -#else -static int sdhci_execute_tuning(struct mmc *mmc, u32 opcode) -{ -#endif - struct sdhci_host *host = mmc->priv; - u16 ctrl; - - /* - * The Host Controller needs tuning in case of SDR104 and DDR50 - * mode, and for SDR50 mode when Use Tuning for SDR50 is set in - * the Capabilities register. - * If the Host Controller supports the HS200 mode then the - * tuning function has to be executed. - */ - switch (mmc->timing) { - /* HS400 tuning is done in HS200 mode */ - case MMC_TIMING_MMC_HS400: - return -EINVAL; - case MMC_TIMING_MMC_HS200: - /* - * Periodic re-tuning for HS400 is not expected to be needed, so - * disable it here. - */ - break; - default: - return -EINVAL; - } - - ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); - ctrl |= SDHCI_CTRL_EXEC_TUNING; - sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); - - return __sdhci_execute_tuning(host, opcode); -} - #ifdef CONFIG_DM_MMC int sdhci_probe(struct udevice *dev) { @@ -679,18 +511,14 @@ int sdhci_probe(struct udevice *dev) } const struct dm_mmc_ops sdhci_ops = { - .card_busy = sdhci_card_busy, .send_cmd = sdhci_send_command, .set_ios = sdhci_set_ios, - .execute_tuning = sdhci_execute_tuning, }; #else static const struct mmc_ops sdhci_ops = { - .card_busy = sdhci_card_busy, .send_cmd = sdhci_send_command, .set_ios = sdhci_set_ios, .init = sdhci_init, - .execute_tuning = sdhci_execute_tuning, }; #endif diff --git a/drivers/mmc/sti_sdhci.c b/drivers/mmc/sti_sdhci.c index f85f6b4db61..1c92bb2b377 100644 --- a/drivers/mmc/sti_sdhci.c +++ b/drivers/mmc/sti_sdhci.c @@ -1,13 +1,14 @@ /* - * Copyright (c) 2017 - * Patrice Chotard + * Copyright (C) 2017, STMicroelectronics - All Rights Reserved + * Author(s): Patrice Chotard, for STMicroelectronics. * - * SPDX-License-Identifier: GPL-2.0 + * SPDX-License-Identifier: GPL-2.0+ */ #include #include #include +#include #include #include @@ -16,18 +17,14 @@ DECLARE_GLOBAL_DATA_PTR; struct sti_sdhci_plat { struct mmc_config cfg; struct mmc mmc; + struct reset_ctl reset; + int instance; }; -/* - * used to get access to MMC1 reset, - * will be removed when STi reset driver will be available - */ -#define STIH410_SYSCONF5_BASE 0x092b0000 - /** * sti_mmc_core_config: configure the Arasan HC - * @regbase: base address - * @mmc_instance: mmc instance id + * @dev : udevice + * * Description: this function is to configure the Arasan MMC HC. * This should be called when the system starts in case of, on the SoC, * it is needed to configure the host controller. @@ -36,33 +33,39 @@ struct sti_sdhci_plat { * W/o these settings the SDHCI could configure and use the embedded controller * with limited features. */ -static void sti_mmc_core_config(const u32 regbase, int mmc_instance) +static int sti_mmc_core_config(struct udevice *dev) { - unsigned long *sysconf; + struct sti_sdhci_plat *plat = dev_get_platdata(dev); + struct sdhci_host *host = dev_get_priv(dev); + int ret; /* only MMC1 has a reset line */ - if (mmc_instance) { - sysconf = (unsigned long *)(STIH410_SYSCONF5_BASE + - ST_MMC_CCONFIG_REG_5); - generic_set_bit(SYSCONF_MMC1_ENABLE_BIT, sysconf); + if (plat->instance) { + ret = reset_deassert(&plat->reset); + if (ret < 0) { + pr_err("MMC1 deassert failed: %d", ret); + return ret; + } } writel(STI_FLASHSS_MMC_CORE_CONFIG_1, - regbase + FLASHSS_MMC_CORE_CONFIG_1); + host->ioaddr + FLASHSS_MMC_CORE_CONFIG_1); - if (mmc_instance) { + if (plat->instance) { writel(STI_FLASHSS_MMC_CORE_CONFIG2, - regbase + FLASHSS_MMC_CORE_CONFIG_2); + host->ioaddr + FLASHSS_MMC_CORE_CONFIG_2); writel(STI_FLASHSS_MMC_CORE_CONFIG3, - regbase + FLASHSS_MMC_CORE_CONFIG_3); + host->ioaddr + FLASHSS_MMC_CORE_CONFIG_3); } else { writel(STI_FLASHSS_SDCARD_CORE_CONFIG2, - regbase + FLASHSS_MMC_CORE_CONFIG_2); + host->ioaddr + FLASHSS_MMC_CORE_CONFIG_2); writel(STI_FLASHSS_SDCARD_CORE_CONFIG3, - regbase + FLASHSS_MMC_CORE_CONFIG_3); + host->ioaddr + FLASHSS_MMC_CORE_CONFIG_3); } writel(STI_FLASHSS_MMC_CORE_CONFIG4, - regbase + FLASHSS_MMC_CORE_CONFIG_4); + host->ioaddr + FLASHSS_MMC_CORE_CONFIG_4); + + return 0; } static int sti_sdhci_probe(struct udevice *dev) @@ -70,20 +73,25 @@ static int sti_sdhci_probe(struct udevice *dev) struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); struct sti_sdhci_plat *plat = dev_get_platdata(dev); struct sdhci_host *host = dev_get_priv(dev); - int ret, mmc_instance; + int ret; /* * identify current mmc instance, mmc1 has a reset, not mmc0 * MMC0 is wired to the SD slot, * MMC1 is wired on the high speed connector */ - - if (fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "resets", NULL)) - mmc_instance = 1; + ret = reset_get_by_index(dev, 0, &plat->reset); + if (!ret) + plat->instance = 1; else - mmc_instance = 0; + if (ret == -ENOENT) + plat->instance = 0; + else + return ret; - sti_mmc_core_config((const u32) host->ioaddr, mmc_instance); + ret = sti_mmc_core_config(dev); + if (ret) + return ret; host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_32BIT_DMA_ADDR | diff --git a/drivers/mmc/stm32_sdmmc2.c b/drivers/mmc/stm32_sdmmc2.c new file mode 100644 index 00000000000..f3b77f512e8 --- /dev/null +++ b/drivers/mmc/stm32_sdmmc2.c @@ -0,0 +1,608 @@ +/* + * Copyright (C) 2017, STMicroelectronics - All Rights Reserved + * Author(s): Patrice Chotard, for STMicroelectronics. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct stm32_sdmmc2_plat { + struct mmc_config cfg; + struct mmc mmc; +}; + +struct stm32_sdmmc2_priv { + fdt_addr_t base; + struct clk clk; + struct reset_ctl reset_ctl; + struct gpio_desc cd_gpio; + u32 clk_reg_msk; + u32 pwr_reg_msk; +}; + +struct stm32_sdmmc2_ctx { + u32 cache_start; + u32 cache_end; + u32 data_length; + bool dpsm_abort; +}; + +/* SDMMC REGISTERS OFFSET */ +#define SDMMC_POWER 0x00 /* SDMMC power control */ +#define SDMMC_CLKCR 0x04 /* SDMMC clock control */ +#define SDMMC_ARG 0x08 /* SDMMC argument */ +#define SDMMC_CMD 0x0C /* SDMMC command */ +#define SDMMC_RESP1 0x14 /* SDMMC response 1 */ +#define SDMMC_RESP2 0x18 /* SDMMC response 2 */ +#define SDMMC_RESP3 0x1C /* SDMMC response 3 */ +#define SDMMC_RESP4 0x20 /* SDMMC response 4 */ +#define SDMMC_DTIMER 0x24 /* SDMMC data timer */ +#define SDMMC_DLEN 0x28 /* SDMMC data length */ +#define SDMMC_DCTRL 0x2C /* SDMMC data control */ +#define SDMMC_DCOUNT 0x30 /* SDMMC data counter */ +#define SDMMC_STA 0x34 /* SDMMC status */ +#define SDMMC_ICR 0x38 /* SDMMC interrupt clear */ +#define SDMMC_MASK 0x3C /* SDMMC mask */ +#define SDMMC_IDMACTRL 0x50 /* SDMMC DMA control */ +#define SDMMC_IDMABASE0 0x58 /* SDMMC DMA buffer 0 base address */ + +/* SDMMC_POWER register */ +#define SDMMC_POWER_PWRCTRL GENMASK(1, 0) +#define SDMMC_POWER_VSWITCH BIT(2) +#define SDMMC_POWER_VSWITCHEN BIT(3) +#define SDMMC_POWER_DIRPOL BIT(4) + +/* SDMMC_CLKCR register */ +#define SDMMC_CLKCR_CLKDIV GENMASK(9, 0) +#define SDMMC_CLKCR_CLKDIV_MAX SDMMC_CLKCR_CLKDIV +#define SDMMC_CLKCR_PWRSAV BIT(12) +#define SDMMC_CLKCR_WIDBUS_4 BIT(14) +#define SDMMC_CLKCR_WIDBUS_8 BIT(15) +#define SDMMC_CLKCR_NEGEDGE BIT(16) +#define SDMMC_CLKCR_HWFC_EN BIT(17) +#define SDMMC_CLKCR_DDR BIT(18) +#define SDMMC_CLKCR_BUSSPEED BIT(19) +#define SDMMC_CLKCR_SELCLKRX GENMASK(21, 20) + +/* SDMMC_CMD register */ +#define SDMMC_CMD_CMDINDEX GENMASK(5, 0) +#define SDMMC_CMD_CMDTRANS BIT(6) +#define SDMMC_CMD_CMDSTOP BIT(7) +#define SDMMC_CMD_WAITRESP GENMASK(9, 8) +#define SDMMC_CMD_WAITRESP_0 BIT(8) +#define SDMMC_CMD_WAITRESP_1 BIT(9) +#define SDMMC_CMD_WAITINT BIT(10) +#define SDMMC_CMD_WAITPEND BIT(11) +#define SDMMC_CMD_CPSMEN BIT(12) +#define SDMMC_CMD_DTHOLD BIT(13) +#define SDMMC_CMD_BOOTMODE BIT(14) +#define SDMMC_CMD_BOOTEN BIT(15) +#define SDMMC_CMD_CMDSUSPEND BIT(16) + +/* SDMMC_DCTRL register */ +#define SDMMC_DCTRL_DTEN BIT(0) +#define SDMMC_DCTRL_DTDIR BIT(1) +#define SDMMC_DCTRL_DTMODE GENMASK(3, 2) +#define SDMMC_DCTRL_DBLOCKSIZE GENMASK(7, 4) +#define SDMMC_DCTRL_DBLOCKSIZE_SHIFT 4 +#define SDMMC_DCTRL_RWSTART BIT(8) +#define SDMMC_DCTRL_RWSTOP BIT(9) +#define SDMMC_DCTRL_RWMOD BIT(10) +#define SDMMC_DCTRL_SDMMCEN BIT(11) +#define SDMMC_DCTRL_BOOTACKEN BIT(12) +#define SDMMC_DCTRL_FIFORST BIT(13) + +/* SDMMC_STA register */ +#define SDMMC_STA_CCRCFAIL BIT(0) +#define SDMMC_STA_DCRCFAIL BIT(1) +#define SDMMC_STA_CTIMEOUT BIT(2) +#define SDMMC_STA_DTIMEOUT BIT(3) +#define SDMMC_STA_TXUNDERR BIT(4) +#define SDMMC_STA_RXOVERR BIT(5) +#define SDMMC_STA_CMDREND BIT(6) +#define SDMMC_STA_CMDSENT BIT(7) +#define SDMMC_STA_DATAEND BIT(8) +#define SDMMC_STA_DHOLD BIT(9) +#define SDMMC_STA_DBCKEND BIT(10) +#define SDMMC_STA_DABORT BIT(11) +#define SDMMC_STA_DPSMACT BIT(12) +#define SDMMC_STA_CPSMACT BIT(13) +#define SDMMC_STA_TXFIFOHE BIT(14) +#define SDMMC_STA_RXFIFOHF BIT(15) +#define SDMMC_STA_TXFIFOF BIT(16) +#define SDMMC_STA_RXFIFOF BIT(17) +#define SDMMC_STA_TXFIFOE BIT(18) +#define SDMMC_STA_RXFIFOE BIT(19) +#define SDMMC_STA_BUSYD0 BIT(20) +#define SDMMC_STA_BUSYD0END BIT(21) +#define SDMMC_STA_SDMMCIT BIT(22) +#define SDMMC_STA_ACKFAIL BIT(23) +#define SDMMC_STA_ACKTIMEOUT BIT(24) +#define SDMMC_STA_VSWEND BIT(25) +#define SDMMC_STA_CKSTOP BIT(26) +#define SDMMC_STA_IDMATE BIT(27) +#define SDMMC_STA_IDMABTC BIT(28) + +/* SDMMC_ICR register */ +#define SDMMC_ICR_CCRCFAILC BIT(0) +#define SDMMC_ICR_DCRCFAILC BIT(1) +#define SDMMC_ICR_CTIMEOUTC BIT(2) +#define SDMMC_ICR_DTIMEOUTC BIT(3) +#define SDMMC_ICR_TXUNDERRC BIT(4) +#define SDMMC_ICR_RXOVERRC BIT(5) +#define SDMMC_ICR_CMDRENDC BIT(6) +#define SDMMC_ICR_CMDSENTC BIT(7) +#define SDMMC_ICR_DATAENDC BIT(8) +#define SDMMC_ICR_DHOLDC BIT(9) +#define SDMMC_ICR_DBCKENDC BIT(10) +#define SDMMC_ICR_DABORTC BIT(11) +#define SDMMC_ICR_BUSYD0ENDC BIT(21) +#define SDMMC_ICR_SDMMCITC BIT(22) +#define SDMMC_ICR_ACKFAILC BIT(23) +#define SDMMC_ICR_ACKTIMEOUTC BIT(24) +#define SDMMC_ICR_VSWENDC BIT(25) +#define SDMMC_ICR_CKSTOPC BIT(26) +#define SDMMC_ICR_IDMATEC BIT(27) +#define SDMMC_ICR_IDMABTCC BIT(28) +#define SDMMC_ICR_STATIC_FLAGS ((GENMASK(28, 21)) | (GENMASK(11, 0))) + +/* SDMMC_MASK register */ +#define SDMMC_MASK_CCRCFAILIE BIT(0) +#define SDMMC_MASK_DCRCFAILIE BIT(1) +#define SDMMC_MASK_CTIMEOUTIE BIT(2) +#define SDMMC_MASK_DTIMEOUTIE BIT(3) +#define SDMMC_MASK_TXUNDERRIE BIT(4) +#define SDMMC_MASK_RXOVERRIE BIT(5) +#define SDMMC_MASK_CMDRENDIE BIT(6) +#define SDMMC_MASK_CMDSENTIE BIT(7) +#define SDMMC_MASK_DATAENDIE BIT(8) +#define SDMMC_MASK_DHOLDIE BIT(9) +#define SDMMC_MASK_DBCKENDIE BIT(10) +#define SDMMC_MASK_DABORTIE BIT(11) +#define SDMMC_MASK_TXFIFOHEIE BIT(14) +#define SDMMC_MASK_RXFIFOHFIE BIT(15) +#define SDMMC_MASK_RXFIFOFIE BIT(17) +#define SDMMC_MASK_TXFIFOEIE BIT(18) +#define SDMMC_MASK_BUSYD0ENDIE BIT(21) +#define SDMMC_MASK_SDMMCITIE BIT(22) +#define SDMMC_MASK_ACKFAILIE BIT(23) +#define SDMMC_MASK_ACKTIMEOUTIE BIT(24) +#define SDMMC_MASK_VSWENDIE BIT(25) +#define SDMMC_MASK_CKSTOPIE BIT(26) +#define SDMMC_MASK_IDMABTCIE BIT(28) + +/* SDMMC_IDMACTRL register */ +#define SDMMC_IDMACTRL_IDMAEN BIT(0) + +#define SDMMC_CMD_TIMEOUT 0xFFFFFFFF + +DECLARE_GLOBAL_DATA_PTR; + +static void stm32_sdmmc2_start_data(struct stm32_sdmmc2_priv *priv, + struct mmc_data *data, + struct stm32_sdmmc2_ctx *ctx) +{ + u32 data_ctrl, idmabase0; + + /* Configure the SDMMC DPSM (Data Path State Machine) */ + data_ctrl = (__ilog2(data->blocksize) << + SDMMC_DCTRL_DBLOCKSIZE_SHIFT) & + SDMMC_DCTRL_DBLOCKSIZE; + + if (data->flags & MMC_DATA_READ) { + data_ctrl |= SDMMC_DCTRL_DTDIR; + idmabase0 = (u32)data->dest; + } else { + idmabase0 = (u32)data->src; + } + + /* Set the SDMMC Data TimeOut value */ + writel(SDMMC_CMD_TIMEOUT, priv->base + SDMMC_DTIMER); + + /* Set the SDMMC DataLength value */ + writel(ctx->data_length, priv->base + SDMMC_DLEN); + + /* Write to SDMMC DCTRL */ + writel(data_ctrl, priv->base + SDMMC_DCTRL); + + /* Cache align */ + ctx->cache_start = rounddown(idmabase0, ARCH_DMA_MINALIGN); + ctx->cache_end = roundup(idmabase0 + ctx->data_length, + ARCH_DMA_MINALIGN); + + /* + * Flush data cache before DMA start (clean and invalidate) + * Clean also needed for read + * Avoid issue on buffer not cached-aligned + */ + flush_dcache_range(ctx->cache_start, ctx->cache_end); + + /* Enable internal DMA */ + writel(idmabase0, priv->base + SDMMC_IDMABASE0); + writel(SDMMC_IDMACTRL_IDMAEN, priv->base + SDMMC_IDMACTRL); +} + +static void stm32_sdmmc2_start_cmd(struct stm32_sdmmc2_priv *priv, + struct mmc_cmd *cmd, u32 cmd_param) +{ + if (readl(priv->base + SDMMC_ARG) & SDMMC_CMD_CPSMEN) + writel(0, priv->base + SDMMC_ARG); + + cmd_param |= cmd->cmdidx | SDMMC_CMD_CPSMEN; + if (cmd->resp_type & MMC_RSP_PRESENT) { + if (cmd->resp_type & MMC_RSP_136) + cmd_param |= SDMMC_CMD_WAITRESP; + else if (cmd->resp_type & MMC_RSP_CRC) + cmd_param |= SDMMC_CMD_WAITRESP_0; + else + cmd_param |= SDMMC_CMD_WAITRESP_1; + } + + /* Clear flags */ + writel(SDMMC_ICR_STATIC_FLAGS, priv->base + SDMMC_ICR); + + /* Set SDMMC argument value */ + writel(cmd->cmdarg, priv->base + SDMMC_ARG); + + /* Set SDMMC command parameters */ + writel(cmd_param, priv->base + SDMMC_CMD); +} + +static int stm32_sdmmc2_end_cmd(struct stm32_sdmmc2_priv *priv, + struct mmc_cmd *cmd, + struct stm32_sdmmc2_ctx *ctx) +{ + u32 mask = SDMMC_STA_CTIMEOUT; + u32 status; + int ret; + + if (cmd->resp_type & MMC_RSP_PRESENT) { + mask |= SDMMC_STA_CMDREND; + if (cmd->resp_type & MMC_RSP_CRC) + mask |= SDMMC_STA_CCRCFAIL; + } else { + mask |= SDMMC_STA_CMDSENT; + } + + /* Polling status register */ + ret = readl_poll_timeout(priv->base + SDMMC_STA, status, status & mask, + 10000); + + if (ret < 0) { + debug("%s: timeout reading SDMMC_STA register\n", __func__); + ctx->dpsm_abort = true; + return ret; + } + + /* Check status */ + if (status & SDMMC_STA_CTIMEOUT) { + debug("%s: error SDMMC_STA_CTIMEOUT (0x%x) for cmd %d\n", + __func__, status, cmd->cmdidx); + ctx->dpsm_abort = true; + return -ETIMEDOUT; + } + + if (status & SDMMC_STA_CCRCFAIL && cmd->resp_type & MMC_RSP_CRC) { + debug("%s: error SDMMC_STA_CCRCFAIL (0x%x) for cmd %d\n", + __func__, status, cmd->cmdidx); + ctx->dpsm_abort = true; + return -EILSEQ; + } + + if (status & SDMMC_STA_CMDREND && cmd->resp_type & MMC_RSP_PRESENT) { + cmd->response[0] = readl(priv->base + SDMMC_RESP1); + if (cmd->resp_type & MMC_RSP_136) { + cmd->response[1] = readl(priv->base + SDMMC_RESP2); + cmd->response[2] = readl(priv->base + SDMMC_RESP3); + cmd->response[3] = readl(priv->base + SDMMC_RESP4); + } + } + + return 0; +} + +static int stm32_sdmmc2_end_data(struct stm32_sdmmc2_priv *priv, + struct mmc_cmd *cmd, + struct mmc_data *data, + struct stm32_sdmmc2_ctx *ctx) +{ + u32 mask = SDMMC_STA_DCRCFAIL | SDMMC_STA_DTIMEOUT | + SDMMC_STA_IDMATE | SDMMC_STA_DATAEND; + u32 status; + + if (data->flags & MMC_DATA_READ) + mask |= SDMMC_STA_RXOVERR; + else + mask |= SDMMC_STA_TXUNDERR; + + status = readl(priv->base + SDMMC_STA); + while (!(status & mask)) + status = readl(priv->base + SDMMC_STA); + + /* + * Need invalidate the dcache again to avoid any + * cache-refill during the DMA operations (pre-fetching) + */ + if (data->flags & MMC_DATA_READ) + invalidate_dcache_range(ctx->cache_start, ctx->cache_end); + + if (status & SDMMC_STA_DCRCFAIL) { + debug("%s: error SDMMC_STA_DCRCFAIL (0x%x) for cmd %d\n", + __func__, status, cmd->cmdidx); + if (readl(priv->base + SDMMC_DCOUNT)) + ctx->dpsm_abort = true; + return -EILSEQ; + } + + if (status & SDMMC_STA_DTIMEOUT) { + debug("%s: error SDMMC_STA_DTIMEOUT (0x%x) for cmd %d\n", + __func__, status, cmd->cmdidx); + ctx->dpsm_abort = true; + return -ETIMEDOUT; + } + + if (status & SDMMC_STA_TXUNDERR) { + debug("%s: error SDMMC_STA_TXUNDERR (0x%x) for cmd %d\n", + __func__, status, cmd->cmdidx); + ctx->dpsm_abort = true; + return -EIO; + } + + if (status & SDMMC_STA_RXOVERR) { + debug("%s: error SDMMC_STA_RXOVERR (0x%x) for cmd %d\n", + __func__, status, cmd->cmdidx); + ctx->dpsm_abort = true; + return -EIO; + } + + if (status & SDMMC_STA_IDMATE) { + debug("%s: error SDMMC_STA_IDMATE (0x%x) for cmd %d\n", + __func__, status, cmd->cmdidx); + ctx->dpsm_abort = true; + return -EIO; + } + + return 0; +} + +static int stm32_sdmmc2_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, + struct mmc_data *data) +{ + struct stm32_sdmmc2_priv *priv = dev_get_priv(dev); + struct stm32_sdmmc2_ctx ctx; + u32 cmdat = data ? SDMMC_CMD_CMDTRANS : 0; + int ret, retry = 3; + +retry_cmd: + ctx.data_length = 0; + ctx.dpsm_abort = false; + + if (data) { + ctx.data_length = data->blocks * data->blocksize; + stm32_sdmmc2_start_data(priv, data, &ctx); + } + + stm32_sdmmc2_start_cmd(priv, cmd, cmdat); + + debug("%s: send cmd %d data: 0x%x @ 0x%x\n", + __func__, cmd->cmdidx, + data ? ctx.data_length : 0, (unsigned int)data); + + ret = stm32_sdmmc2_end_cmd(priv, cmd, &ctx); + + if (data && !ret) + ret = stm32_sdmmc2_end_data(priv, cmd, data, &ctx); + + /* Clear flags */ + writel(SDMMC_ICR_STATIC_FLAGS, priv->base + SDMMC_ICR); + if (data) + writel(0x0, priv->base + SDMMC_IDMACTRL); + + /* + * To stop Data Path State Machine, a stop_transmission command + * shall be send on cmd or data errors. + */ + if (ctx.dpsm_abort && (cmd->cmdidx != MMC_CMD_STOP_TRANSMISSION)) { + struct mmc_cmd stop_cmd; + + stop_cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION; + stop_cmd.cmdarg = 0; + stop_cmd.resp_type = MMC_RSP_R1b; + + debug("%s: send STOP command to abort dpsm treatments\n", + __func__); + + stm32_sdmmc2_start_cmd(priv, &stop_cmd, SDMMC_CMD_CMDSTOP); + stm32_sdmmc2_end_cmd(priv, &stop_cmd, &ctx); + + writel(SDMMC_ICR_STATIC_FLAGS, priv->base + SDMMC_ICR); + } + + if ((ret != -ETIMEDOUT) && (ret != 0) && retry) { + printf("%s: cmd %d failed, retrying ...\n", + __func__, cmd->cmdidx); + retry--; + goto retry_cmd; + } + + debug("%s: end for CMD %d, ret = %d\n", __func__, cmd->cmdidx, ret); + + return ret; +} + +static void stm32_sdmmc2_pwron(struct stm32_sdmmc2_priv *priv) +{ + /* Reset */ + reset_assert(&priv->reset_ctl); + udelay(2); + reset_deassert(&priv->reset_ctl); + + udelay(1000); + + /* Set Power State to ON */ + writel(SDMMC_POWER_PWRCTRL | priv->pwr_reg_msk, priv->base + SDMMC_POWER); + + /* + * 1ms: required power up waiting time before starting the + * SD initialization sequence + */ + udelay(1000); +} + +#define IS_RISING_EDGE(reg) (reg & SDMMC_CLKCR_NEGEDGE ? 0 : 1) +static int stm32_sdmmc2_set_ios(struct udevice *dev) +{ + struct mmc *mmc = mmc_get_mmc_dev(dev); + struct stm32_sdmmc2_priv *priv = dev_get_priv(dev); + struct stm32_sdmmc2_plat *plat = dev_get_platdata(dev); + struct mmc_config *cfg = &plat->cfg; + u32 desired = mmc->clock; + u32 sys_clock = clk_get_rate(&priv->clk); + u32 clk = 0; + + debug("%s: bus_with = %d, clock = %d\n", __func__, + mmc->bus_width, mmc->clock); + + if ((mmc->bus_width == 1) && (desired == cfg->f_min)) + stm32_sdmmc2_pwron(priv); + + /* + * clk_div = 0 => command and data generated on SDMMCCLK falling edge + * clk_div > 0 and NEGEDGE = 0 => command and data generated on + * SDMMCCLK rising edge + * clk_div > 0 and NEGEDGE = 1 => command and data generated on + * SDMMCCLK falling edge + */ + if (desired && ((sys_clock > desired) || + IS_RISING_EDGE(priv->clk_reg_msk))) { + clk = DIV_ROUND_UP(sys_clock, 2 * desired); + if (clk > SDMMC_CLKCR_CLKDIV_MAX) + clk = SDMMC_CLKCR_CLKDIV_MAX; + } + + if (mmc->bus_width == 4) + clk |= SDMMC_CLKCR_WIDBUS_4; + if (mmc->bus_width == 8) + clk |= SDMMC_CLKCR_WIDBUS_8; + + writel(clk | priv->clk_reg_msk, priv->base + SDMMC_CLKCR); + + return 0; +} + +static int stm32_sdmmc2_getcd(struct udevice *dev) +{ + struct stm32_sdmmc2_priv *priv = dev_get_priv(dev); + + debug("stm32_sdmmc2_getcd called\n"); + + if (dm_gpio_is_valid(&priv->cd_gpio)) + return dm_gpio_get_value(&priv->cd_gpio); + + return 1; +} + +static const struct dm_mmc_ops stm32_sdmmc2_ops = { + .send_cmd = stm32_sdmmc2_send_cmd, + .set_ios = stm32_sdmmc2_set_ios, + .get_cd = stm32_sdmmc2_getcd, +}; + +static int stm32_sdmmc2_probe(struct udevice *dev) +{ + struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); + struct stm32_sdmmc2_plat *plat = dev_get_platdata(dev); + struct stm32_sdmmc2_priv *priv = dev_get_priv(dev); + struct mmc_config *cfg = &plat->cfg; + int ret; + + priv->base = dev_read_addr(dev); + if (priv->base == FDT_ADDR_T_NONE) + return -EINVAL; + + if (dev_read_bool(dev, "st,negedge")) + priv->clk_reg_msk |= SDMMC_CLKCR_NEGEDGE; + if (dev_read_bool(dev, "st,dirpol")) + priv->pwr_reg_msk |= SDMMC_POWER_DIRPOL; + + ret = clk_get_by_index(dev, 0, &priv->clk); + if (ret) + return ret; + + ret = clk_enable(&priv->clk); + if (ret) + goto clk_free; + + ret = reset_get_by_index(dev, 0, &priv->reset_ctl); + if (ret) + goto clk_disable; + + gpio_request_by_name(dev, "cd-gpios", 0, &priv->cd_gpio, + GPIOD_IS_IN); + + cfg->f_min = 400000; + cfg->f_max = dev_read_u32_default(dev, "max-frequency", 52000000); + cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; + cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; + cfg->name = "STM32 SDMMC2"; + + cfg->host_caps = 0; + if (cfg->f_max > 25000000) + cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS; + + switch (dev_read_u32_default(dev, "bus-width", 1)) { + case 8: + cfg->host_caps |= MMC_MODE_8BIT; + case 4: + cfg->host_caps |= MMC_MODE_4BIT; + break; + case 1: + break; + default: + pr_err("invalid \"bus-width\" property, force to 1\n"); + } + + upriv->mmc = &plat->mmc; + + return 0; + +clk_disable: + clk_disable(&priv->clk); +clk_free: + clk_free(&priv->clk); + + return ret; +} + +int stm32_sdmmc_bind(struct udevice *dev) +{ + struct stm32_sdmmc2_plat *plat = dev_get_platdata(dev); + + return mmc_bind(dev, &plat->mmc, &plat->cfg); +} + +static const struct udevice_id stm32_sdmmc2_ids[] = { + { .compatible = "st,stm32-sdmmc2" }, + { } +}; + +U_BOOT_DRIVER(stm32_sdmmc2) = { + .name = "stm32_sdmmc2", + .id = UCLASS_MMC, + .of_match = stm32_sdmmc2_ids, + .ops = &stm32_sdmmc2_ops, + .probe = stm32_sdmmc2_probe, + .bind = stm32_sdmmc_bind, + .priv_auto_alloc_size = sizeof(struct stm32_sdmmc2_priv), + .platdata_auto_alloc_size = sizeof(struct stm32_sdmmc2_plat), +}; diff --git a/drivers/mmc/uniphier-sd.c b/drivers/mmc/uniphier-sd.c index 398bd5648a6..741f9dfd9cd 100644 --- a/drivers/mmc/uniphier-sd.c +++ b/drivers/mmc/uniphier-sd.c @@ -11,10 +11,11 @@ #include #include #include +#include #include #include +#include #include -#include DECLARE_GLOBAL_DATA_PTR; @@ -132,8 +133,43 @@ struct uniphier_sd_priv { #define UNIPHIER_SD_CAP_NONREMOVABLE BIT(0) /* Nonremovable e.g. eMMC */ #define UNIPHIER_SD_CAP_DMA_INTERNAL BIT(1) /* have internal DMA engine */ #define UNIPHIER_SD_CAP_DIV1024 BIT(2) /* divisor 1024 is available */ +#define UNIPHIER_SD_CAP_64BIT BIT(3) /* Controller is 64bit */ }; +static u64 uniphier_sd_readq(struct uniphier_sd_priv *priv, unsigned int reg) +{ + if (priv->caps & UNIPHIER_SD_CAP_64BIT) + return readq(priv->regbase + (reg << 1)); + else + return readq(priv->regbase + reg); +} + +static void uniphier_sd_writeq(struct uniphier_sd_priv *priv, + u64 val, unsigned int reg) +{ + if (priv->caps & UNIPHIER_SD_CAP_64BIT) + writeq(val, priv->regbase + (reg << 1)); + else + writeq(val, priv->regbase + reg); +} + +static u32 uniphier_sd_readl(struct uniphier_sd_priv *priv, unsigned int reg) +{ + if (priv->caps & UNIPHIER_SD_CAP_64BIT) + return readl(priv->regbase + (reg << 1)); + else + return readl(priv->regbase + reg); +} + +static void uniphier_sd_writel(struct uniphier_sd_priv *priv, + u32 val, unsigned int reg) +{ + if (priv->caps & UNIPHIER_SD_CAP_64BIT) + writel(val, priv->regbase + (reg << 1)); + else + writel(val, priv->regbase + reg); +} + static dma_addr_t __dma_map_single(void *ptr, size_t size, enum dma_data_direction dir) { @@ -157,7 +193,7 @@ static void __dma_unmap_single(dma_addr_t addr, size_t size, static int uniphier_sd_check_error(struct udevice *dev) { struct uniphier_sd_priv *priv = dev_get_priv(dev); - u32 info2 = readl(priv->regbase + UNIPHIER_SD_INFO2); + u32 info2 = uniphier_sd_readl(priv, UNIPHIER_SD_INFO2); if (info2 & UNIPHIER_SD_INFO2_ERR_RTO) { /* @@ -195,7 +231,7 @@ static int uniphier_sd_wait_for_irq(struct udevice *dev, unsigned int reg, long wait = 1000000; int ret; - while (!(readl(priv->regbase + reg) & flag)) { + while (!(uniphier_sd_readl(priv, reg) & flag)) { if (wait-- < 0) { dev_err(dev, "timeout\n"); return -ETIMEDOUT; @@ -211,7 +247,7 @@ static int uniphier_sd_wait_for_irq(struct udevice *dev, unsigned int reg, return 0; } -static int uniphier_sd_pio_read_one_block(struct udevice *dev, u32 **pbuf, +static int uniphier_sd_pio_read_one_block(struct udevice *dev, char *pbuf, uint blocksize) { struct uniphier_sd_priv *priv = dev_get_priv(dev); @@ -227,22 +263,44 @@ static int uniphier_sd_pio_read_one_block(struct udevice *dev, u32 **pbuf, * Clear the status flag _before_ read the buffer out because * UNIPHIER_SD_INFO2_BRE is edge-triggered, not level-triggered. */ - writel(0, priv->regbase + UNIPHIER_SD_INFO2); - - if (likely(IS_ALIGNED((unsigned long)*pbuf, 4))) { - for (i = 0; i < blocksize / 4; i++) - *(*pbuf)++ = readl(priv->regbase + UNIPHIER_SD_BUF); + uniphier_sd_writel(priv, 0, UNIPHIER_SD_INFO2); + + if (priv->caps & UNIPHIER_SD_CAP_64BIT) { + u64 *buf = (u64 *)pbuf; + if (likely(IS_ALIGNED((uintptr_t)buf, 8))) { + for (i = 0; i < blocksize / 8; i++) { + *buf++ = uniphier_sd_readq(priv, + UNIPHIER_SD_BUF); + } + } else { + for (i = 0; i < blocksize / 8; i++) { + u64 data; + data = uniphier_sd_readq(priv, + UNIPHIER_SD_BUF); + put_unaligned(data, buf++); + } + } } else { - for (i = 0; i < blocksize / 4; i++) - put_unaligned(readl(priv->regbase + UNIPHIER_SD_BUF), - (*pbuf)++); + u32 *buf = (u32 *)pbuf; + if (likely(IS_ALIGNED((uintptr_t)buf, 4))) { + for (i = 0; i < blocksize / 4; i++) { + *buf++ = uniphier_sd_readl(priv, + UNIPHIER_SD_BUF); + } + } else { + for (i = 0; i < blocksize / 4; i++) { + u32 data; + data = uniphier_sd_readl(priv, UNIPHIER_SD_BUF); + put_unaligned(data, buf++); + } + } } return 0; } static int uniphier_sd_pio_write_one_block(struct udevice *dev, - const u32 **pbuf, uint blocksize) + const char *pbuf, uint blocksize) { struct uniphier_sd_priv *priv = dev_get_priv(dev); int i, ret; @@ -253,15 +311,36 @@ static int uniphier_sd_pio_write_one_block(struct udevice *dev, if (ret) return ret; - writel(0, priv->regbase + UNIPHIER_SD_INFO2); - - if (likely(IS_ALIGNED((unsigned long)*pbuf, 4))) { - for (i = 0; i < blocksize / 4; i++) - writel(*(*pbuf)++, priv->regbase + UNIPHIER_SD_BUF); + uniphier_sd_writel(priv, 0, UNIPHIER_SD_INFO2); + + if (priv->caps & UNIPHIER_SD_CAP_64BIT) { + const u64 *buf = (const u64 *)pbuf; + if (likely(IS_ALIGNED((uintptr_t)buf, 8))) { + for (i = 0; i < blocksize / 8; i++) { + uniphier_sd_writeq(priv, *buf++, + UNIPHIER_SD_BUF); + } + } else { + for (i = 0; i < blocksize / 8; i++) { + u64 data = get_unaligned(buf++); + uniphier_sd_writeq(priv, data, + UNIPHIER_SD_BUF); + } + } } else { - for (i = 0; i < blocksize / 4; i++) - writel(get_unaligned((*pbuf)++), - priv->regbase + UNIPHIER_SD_BUF); + const u32 *buf = (const u32 *)pbuf; + if (likely(IS_ALIGNED((uintptr_t)buf, 4))) { + for (i = 0; i < blocksize / 4; i++) { + uniphier_sd_writel(priv, *buf++, + UNIPHIER_SD_BUF); + } + } else { + for (i = 0; i < blocksize / 4; i++) { + u32 data = get_unaligned(buf++); + uniphier_sd_writel(priv, data, + UNIPHIER_SD_BUF); + } + } } return 0; @@ -269,19 +348,24 @@ static int uniphier_sd_pio_write_one_block(struct udevice *dev, static int uniphier_sd_pio_xfer(struct udevice *dev, struct mmc_data *data) { - u32 *dest = (u32 *)data->dest; - const u32 *src = (const u32 *)data->src; + const char *src = data->src; + char *dest = data->dest; int i, ret; for (i = 0; i < data->blocks; i++) { if (data->flags & MMC_DATA_READ) - ret = uniphier_sd_pio_read_one_block(dev, &dest, + ret = uniphier_sd_pio_read_one_block(dev, dest, data->blocksize); else - ret = uniphier_sd_pio_write_one_block(dev, &src, + ret = uniphier_sd_pio_write_one_block(dev, src, data->blocksize); if (ret) return ret; + + if (data->flags & MMC_DATA_READ) + dest += data->blocksize; + else + src += data->blocksize; } return 0; @@ -292,22 +376,22 @@ static void uniphier_sd_dma_start(struct uniphier_sd_priv *priv, { u32 tmp; - writel(0, priv->regbase + UNIPHIER_SD_DMA_INFO1); - writel(0, priv->regbase + UNIPHIER_SD_DMA_INFO2); + uniphier_sd_writel(priv, 0, UNIPHIER_SD_DMA_INFO1); + uniphier_sd_writel(priv, 0, UNIPHIER_SD_DMA_INFO2); /* enable DMA */ - tmp = readl(priv->regbase + UNIPHIER_SD_EXTMODE); + tmp = uniphier_sd_readl(priv, UNIPHIER_SD_EXTMODE); tmp |= UNIPHIER_SD_EXTMODE_DMA_EN; - writel(tmp, priv->regbase + UNIPHIER_SD_EXTMODE); + uniphier_sd_writel(priv, tmp, UNIPHIER_SD_EXTMODE); - writel(dma_addr & U32_MAX, priv->regbase + UNIPHIER_SD_DMA_ADDR_L); + uniphier_sd_writel(priv, dma_addr & U32_MAX, UNIPHIER_SD_DMA_ADDR_L); /* suppress the warning "right shift count >= width of type" */ dma_addr >>= min_t(int, 32, 8 * sizeof(dma_addr)); - writel(dma_addr & U32_MAX, priv->regbase + UNIPHIER_SD_DMA_ADDR_H); + uniphier_sd_writel(priv, dma_addr & U32_MAX, UNIPHIER_SD_DMA_ADDR_H); - writel(UNIPHIER_SD_DMA_CTL_START, priv->regbase + UNIPHIER_SD_DMA_CTL); + uniphier_sd_writel(priv, UNIPHIER_SD_DMA_CTL_START, UNIPHIER_SD_DMA_CTL); } static int uniphier_sd_dma_wait_for_irq(struct udevice *dev, u32 flag, @@ -316,7 +400,7 @@ static int uniphier_sd_dma_wait_for_irq(struct udevice *dev, u32 flag, struct uniphier_sd_priv *priv = dev_get_priv(dev); long wait = 1000000 + 10 * blocks; - while (!(readl(priv->regbase + UNIPHIER_SD_DMA_INFO1) & flag)) { + while (!(uniphier_sd_readl(priv, UNIPHIER_SD_DMA_INFO1) & flag)) { if (wait-- < 0) { dev_err(dev, "timeout during DMA\n"); return -ETIMEDOUT; @@ -325,7 +409,7 @@ static int uniphier_sd_dma_wait_for_irq(struct udevice *dev, u32 flag, udelay(10); } - if (readl(priv->regbase + UNIPHIER_SD_DMA_INFO2)) { + if (uniphier_sd_readl(priv, UNIPHIER_SD_DMA_INFO2)) { dev_err(dev, "error during DMA\n"); return -EIO; } @@ -343,7 +427,7 @@ static int uniphier_sd_dma_xfer(struct udevice *dev, struct mmc_data *data) u32 poll_flag, tmp; int ret; - tmp = readl(priv->regbase + UNIPHIER_SD_DMA_MODE); + tmp = uniphier_sd_readl(priv, UNIPHIER_SD_DMA_MODE); if (data->flags & MMC_DATA_READ) { buf = data->dest; @@ -357,7 +441,7 @@ static int uniphier_sd_dma_xfer(struct udevice *dev, struct mmc_data *data) tmp &= ~UNIPHIER_SD_DMA_MODE_DIR_RD; } - writel(tmp, priv->regbase + UNIPHIER_SD_DMA_MODE); + uniphier_sd_writel(priv, tmp, UNIPHIER_SD_DMA_MODE); dma_addr = __dma_map_single(buf, len, dir); @@ -396,27 +480,27 @@ static int uniphier_sd_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, int ret; u32 tmp; - if (readl(priv->regbase + UNIPHIER_SD_INFO2) & UNIPHIER_SD_INFO2_CBSY) { + if (uniphier_sd_readl(priv, UNIPHIER_SD_INFO2) & UNIPHIER_SD_INFO2_CBSY) { dev_err(dev, "command busy\n"); return -EBUSY; } /* clear all status flags */ - writel(0, priv->regbase + UNIPHIER_SD_INFO1); - writel(0, priv->regbase + UNIPHIER_SD_INFO2); + uniphier_sd_writel(priv, 0, UNIPHIER_SD_INFO1); + uniphier_sd_writel(priv, 0, UNIPHIER_SD_INFO2); /* disable DMA once */ - tmp = readl(priv->regbase + UNIPHIER_SD_EXTMODE); + tmp = uniphier_sd_readl(priv, UNIPHIER_SD_EXTMODE); tmp &= ~UNIPHIER_SD_EXTMODE_DMA_EN; - writel(tmp, priv->regbase + UNIPHIER_SD_EXTMODE); + uniphier_sd_writel(priv, tmp, UNIPHIER_SD_EXTMODE); - writel(cmd->cmdarg, priv->regbase + UNIPHIER_SD_ARG); + uniphier_sd_writel(priv, cmd->cmdarg, UNIPHIER_SD_ARG); tmp = cmd->cmdidx; if (data) { - writel(data->blocksize, priv->regbase + UNIPHIER_SD_SIZE); - writel(data->blocks, priv->regbase + UNIPHIER_SD_SECCNT); + uniphier_sd_writel(priv, data->blocksize, UNIPHIER_SD_SIZE); + uniphier_sd_writel(priv, data->blocks, UNIPHIER_SD_SECCNT); /* Do not send CMD12 automatically */ tmp |= UNIPHIER_SD_CMD_NOSTOP | UNIPHIER_SD_CMD_DATA; @@ -457,7 +541,7 @@ static int uniphier_sd_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, dev_dbg(dev, "sending CMD%d (SD_CMD=%08x, SD_ARG=%08x)\n", cmd->cmdidx, tmp, cmd->cmdarg); - writel(tmp, priv->regbase + UNIPHIER_SD_CMD); + uniphier_sd_writel(priv, tmp, UNIPHIER_SD_CMD); ret = uniphier_sd_wait_for_irq(dev, UNIPHIER_SD_INFO1, UNIPHIER_SD_INFO1_RSP); @@ -465,10 +549,10 @@ static int uniphier_sd_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, return ret; if (cmd->resp_type & MMC_RSP_136) { - u32 rsp_127_104 = readl(priv->regbase + UNIPHIER_SD_RSP76); - u32 rsp_103_72 = readl(priv->regbase + UNIPHIER_SD_RSP54); - u32 rsp_71_40 = readl(priv->regbase + UNIPHIER_SD_RSP32); - u32 rsp_39_8 = readl(priv->regbase + UNIPHIER_SD_RSP10); + u32 rsp_127_104 = uniphier_sd_readl(priv, UNIPHIER_SD_RSP76); + u32 rsp_103_72 = uniphier_sd_readl(priv, UNIPHIER_SD_RSP54); + u32 rsp_71_40 = uniphier_sd_readl(priv, UNIPHIER_SD_RSP32); + u32 rsp_39_8 = uniphier_sd_readl(priv, UNIPHIER_SD_RSP10); cmd->response[0] = ((rsp_127_104 & 0x00ffffff) << 8) | ((rsp_103_72 & 0xff000000) >> 24); @@ -479,7 +563,7 @@ static int uniphier_sd_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, cmd->response[3] = (rsp_39_8 & 0xffffff) << 8; } else { /* bit 39-8 */ - cmd->response[0] = readl(priv->regbase + UNIPHIER_SD_RSP10); + cmd->response[0] = uniphier_sd_readl(priv, UNIPHIER_SD_RSP10); } if (data) { @@ -518,10 +602,10 @@ static int uniphier_sd_set_bus_width(struct uniphier_sd_priv *priv, return -EINVAL; } - tmp = readl(priv->regbase + UNIPHIER_SD_OPTION); + tmp = uniphier_sd_readl(priv, UNIPHIER_SD_OPTION); tmp &= ~UNIPHIER_SD_OPTION_WIDTH_MASK; tmp |= val; - writel(tmp, priv->regbase + UNIPHIER_SD_OPTION); + uniphier_sd_writel(priv, tmp, UNIPHIER_SD_OPTION); return 0; } @@ -531,12 +615,12 @@ static void uniphier_sd_set_ddr_mode(struct uniphier_sd_priv *priv, { u32 tmp; - tmp = readl(priv->regbase + UNIPHIER_SD_IF_MODE); - if (mmc_card_ddr(mmc)) + tmp = uniphier_sd_readl(priv, UNIPHIER_SD_IF_MODE); + if (mmc->ddr_mode) tmp |= UNIPHIER_SD_IF_MODE_DDR; else tmp &= ~UNIPHIER_SD_IF_MODE_DDR; - writel(tmp, priv->regbase + UNIPHIER_SD_IF_MODE); + uniphier_sd_writel(priv, tmp, UNIPHIER_SD_IF_MODE); } static void uniphier_sd_set_clk_rate(struct uniphier_sd_priv *priv, @@ -573,21 +657,21 @@ static void uniphier_sd_set_clk_rate(struct uniphier_sd_priv *priv, else val = UNIPHIER_SD_CLKCTL_DIV1024; - tmp = readl(priv->regbase + UNIPHIER_SD_CLKCTL); + tmp = uniphier_sd_readl(priv, UNIPHIER_SD_CLKCTL); if (tmp & UNIPHIER_SD_CLKCTL_SCLKEN && (tmp & UNIPHIER_SD_CLKCTL_DIV_MASK) == val) return; /* stop the clock before changing its rate to avoid a glitch signal */ tmp &= ~UNIPHIER_SD_CLKCTL_SCLKEN; - writel(tmp, priv->regbase + UNIPHIER_SD_CLKCTL); + uniphier_sd_writel(priv, tmp, UNIPHIER_SD_CLKCTL); tmp &= ~UNIPHIER_SD_CLKCTL_DIV_MASK; tmp |= val | UNIPHIER_SD_CLKCTL_OFFEN; - writel(tmp, priv->regbase + UNIPHIER_SD_CLKCTL); + uniphier_sd_writel(priv, tmp, UNIPHIER_SD_CLKCTL); tmp |= UNIPHIER_SD_CLKCTL_SCLKEN; - writel(tmp, priv->regbase + UNIPHIER_SD_CLKCTL); + uniphier_sd_writel(priv, tmp, UNIPHIER_SD_CLKCTL); udelay(1000); } @@ -599,7 +683,7 @@ static int uniphier_sd_set_ios(struct udevice *dev) int ret; dev_dbg(dev, "clock %uHz, DDRmode %d, width %u\n", - mmc->clock, mmc_card_ddr(mmc), mmc->bus_width); + mmc->clock, mmc->ddr_mode, mmc->bus_width); ret = uniphier_sd_set_bus_width(priv, mmc); if (ret) @@ -617,7 +701,7 @@ static int uniphier_sd_get_cd(struct udevice *dev) if (priv->caps & UNIPHIER_SD_CAP_NONREMOVABLE) return 1; - return !!(readl(priv->regbase + UNIPHIER_SD_INFO1) & + return !!(uniphier_sd_readl(priv, UNIPHIER_SD_INFO1) & UNIPHIER_SD_INFO1_CD); } @@ -632,28 +716,28 @@ static void uniphier_sd_host_init(struct uniphier_sd_priv *priv) u32 tmp; /* soft reset of the host */ - tmp = readl(priv->regbase + UNIPHIER_SD_SOFT_RST); + tmp = uniphier_sd_readl(priv, UNIPHIER_SD_SOFT_RST); tmp &= ~UNIPHIER_SD_SOFT_RST_RSTX; - writel(tmp, priv->regbase + UNIPHIER_SD_SOFT_RST); + uniphier_sd_writel(priv, tmp, UNIPHIER_SD_SOFT_RST); tmp |= UNIPHIER_SD_SOFT_RST_RSTX; - writel(tmp, priv->regbase + UNIPHIER_SD_SOFT_RST); + uniphier_sd_writel(priv, tmp, UNIPHIER_SD_SOFT_RST); /* FIXME: implement eMMC hw_reset */ - writel(UNIPHIER_SD_STOP_SEC, priv->regbase + UNIPHIER_SD_STOP); + uniphier_sd_writel(priv, UNIPHIER_SD_STOP_SEC, UNIPHIER_SD_STOP); /* * Connected to 32bit AXI. * This register dropped backward compatibility at version 0x10. * Write an appropriate value depending on the IP version. */ - writel(priv->version >= 0x10 ? 0x00000101 : 0x00000000, - priv->regbase + UNIPHIER_SD_HOST_MODE); + uniphier_sd_writel(priv, priv->version >= 0x10 ? 0x00000101 : 0x00000000, + UNIPHIER_SD_HOST_MODE); if (priv->caps & UNIPHIER_SD_CAP_DMA_INTERNAL) { - tmp = readl(priv->regbase + UNIPHIER_SD_DMA_MODE); + tmp = uniphier_sd_readl(priv, UNIPHIER_SD_DMA_MODE); tmp |= UNIPHIER_SD_DMA_MODE_ADDR_INC; - writel(tmp, priv->regbase + UNIPHIER_SD_DMA_MODE); + uniphier_sd_writel(priv, tmp, UNIPHIER_SD_DMA_MODE); } } @@ -669,9 +753,13 @@ static int uniphier_sd_probe(struct udevice *dev) struct uniphier_sd_plat *plat = dev_get_platdata(dev); struct uniphier_sd_priv *priv = dev_get_priv(dev); struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); + const u32 quirks = dev_get_driver_data(dev); fdt_addr_t base; struct clk clk; int ret; +#ifdef CONFIG_DM_REGULATOR + struct udevice *vqmmc_dev; +#endif base = devfdt_get_addr(dev); if (base == FDT_ADDR_T_NONE) @@ -681,6 +769,15 @@ static int uniphier_sd_probe(struct udevice *dev) if (!priv->regbase) return -ENOMEM; +#ifdef CONFIG_DM_REGULATOR + ret = device_get_supply_regulator(dev, "vqmmc-supply", &vqmmc_dev); + if (!ret) { + /* Set the regulator to 3.3V until we support 1.8V modes */ + regulator_set_value(vqmmc_dev, 3300000); + regulator_set_enable(vqmmc_dev, true); + } +#endif + ret = clk_get_by_index(dev, 0, &clk); if (ret < 0) { dev_err(dev, "failed to get host clock\n"); @@ -720,18 +817,22 @@ static int uniphier_sd_probe(struct udevice *dev) return -EINVAL; } + if (quirks) { + priv->caps = quirks; + } else { + priv->version = uniphier_sd_readl(priv, UNIPHIER_SD_VERSION) & + UNIPHIER_SD_VERSION_IP; + dev_dbg(dev, "version %x\n", priv->version); + if (priv->version >= 0x10) { + priv->caps |= UNIPHIER_SD_CAP_DMA_INTERNAL; + priv->caps |= UNIPHIER_SD_CAP_DIV1024; + } + } + if (fdt_get_property(gd->fdt_blob, dev_of_offset(dev), "non-removable", NULL)) priv->caps |= UNIPHIER_SD_CAP_NONREMOVABLE; - priv->version = readl(priv->regbase + UNIPHIER_SD_VERSION) & - UNIPHIER_SD_VERSION_IP; - dev_dbg(dev, "version %x\n", priv->version); - if (priv->version >= 0x10) { - priv->caps |= UNIPHIER_SD_CAP_DMA_INTERNAL; - priv->caps |= UNIPHIER_SD_CAP_DIV1024; - } - uniphier_sd_host_init(priv); plat->cfg.voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34; @@ -746,7 +847,11 @@ static int uniphier_sd_probe(struct udevice *dev) } static const struct udevice_id uniphier_sd_match[] = { - { .compatible = "socionext,uniphier-sdhc" }, + { .compatible = "renesas,sdhi-r8a7795", .data = UNIPHIER_SD_CAP_64BIT }, + { .compatible = "renesas,sdhi-r8a7796", .data = UNIPHIER_SD_CAP_64BIT }, + { .compatible = "renesas,sdhi-r8a77970", .data = UNIPHIER_SD_CAP_64BIT }, + { .compatible = "renesas,sdhi-r8a77995", .data = UNIPHIER_SD_CAP_64BIT }, + { .compatible = "socionext,uniphier-sdhc", .data = 0 }, { /* sentinel */ } }; diff --git a/drivers/mmc/xenon_sdhci.c b/drivers/mmc/xenon_sdhci.c index b9a3338666c..490a01f9bdb 100644 --- a/drivers/mmc/xenon_sdhci.c +++ b/drivers/mmc/xenon_sdhci.c @@ -94,6 +94,18 @@ 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 enum soc_pad_ctrl_type { @@ -147,7 +159,7 @@ static int xenon_mmc_phy_init(struct sdhci_host *host) } if (time <= 0) { - error("Failed to enable MMC internal clock in time\n"); + pr_err("Failed to enable MMC internal clock in time\n"); return -ETIMEDOUT; } @@ -175,7 +187,7 @@ static int xenon_mmc_phy_init(struct sdhci_host *host) } if (time <= 0) { - error("Failed to init MMC PHY in time\n"); + pr_err("Failed to init MMC PHY in time\n"); return -ETIMEDOUT; } @@ -237,7 +249,7 @@ static void xenon_mmc_phy_set(struct sdhci_host *host) sdhci_writew(host, var, SDHCI_CLOCK_CONTROL); var = sdhci_readl(host, EMMC_PHY_FUNC_CONTROL); - if (mmc_card_ddr(host->mmc)) { + if (host->mmc->ddr_mode) { var |= (DQ_DDR_MODE_MASK << DQ_DDR_MODE_SHIFT) | CMD_DDR_MODE; } else { var &= ~((DQ_DDR_MODE_MASK << DQ_DDR_MODE_SHIFT) | @@ -318,7 +330,7 @@ static void xenon_mask_cmd_conflict_err(struct sdhci_host *host) static void xenon_sdhci_set_ios_post(struct sdhci_host *host) { struct xenon_sdhci_priv *priv = host->mmc->priv; - uint speed = host->mmc->clock; + uint speed = host->mmc->tran_speed; int pwr_18v = 0; if ((sdhci_readb(host, SDHCI_POWER_CONTROL) & ~SDHCI_POWER_ON) == @@ -329,7 +341,7 @@ static void xenon_sdhci_set_ios_post(struct sdhci_host *host) if (IS_SD(host->mmc)) { /* SD/SDIO */ if (pwr_18v) { - if (mmc_card_ddr(host->mmc)) + if (host->mmc->ddr_mode) priv->timing = MMC_TIMING_UHS_DDR50; else if (speed <= 25000000) priv->timing = MMC_TIMING_UHS_SDR25; @@ -343,7 +355,7 @@ static void xenon_sdhci_set_ios_post(struct sdhci_host *host) } } else { /* eMMC */ - if (mmc_card_ddr(host->mmc)) + if (host->mmc->ddr_mode) priv->timing = MMC_TIMING_MMC_DDR52; else if (speed <= 26000000) priv->timing = MMC_TIMING_LEGACY; diff --git a/drivers/mtd/spi/spi_flash_ids.c b/drivers/mtd/spi/spi_flash_ids.c index bb43231b16c..f167d0dd699 100644 --- a/drivers/mtd/spi/spi_flash_ids.c +++ b/drivers/mtd/spi/spi_flash_ids.c @@ -63,6 +63,7 @@ const struct spi_flash_info spi_flash_ids[] = { {"en25s64", INFO(0x1c3817, 0x0, 64 * 1024, 128, 0) }, #endif #ifdef CONFIG_SPI_FLASH_GIGADEVICE /* GIGADEVICE */ + {"gd25q128", INFO(0xc84018, 0x0, 64 * 1024, 256, SECT_4K) }, {"gd25q64b", INFO(0xc84017, 0x0, 64 * 1024, 128, SECT_4K) }, {"gd25lq32", INFO(0xc86016, 0x0, 64 * 1024, 64, SECT_4K) }, {"GD25Q256", INFO(0xc84019, 0x0, 64 * 1024, 512, RD_FULL | WR_QPP | SECT_4K)}, diff --git a/drivers/net/designware.c b/drivers/net/designware.c index 521e4dde41f..4da3b6d0abd 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -252,6 +252,8 @@ static int dw_adjust_link(struct dw_eth_dev *priv, struct eth_mac_regs *mac_p, if (phydev->duplex) conf |= FULLDPLXMODE; + conf |= ENABLEIPC; + writel(conf, &mac_p->conf); printf("Speed: %d, %s duplex%s\n", phydev->speed, diff --git a/drivers/net/designware.h b/drivers/net/designware.h index 7992d0ebeeb..c4921052d4c 100644 --- a/drivers/net/designware.h +++ b/drivers/net/designware.h @@ -44,6 +44,7 @@ struct eth_mac_regs { #define FES_100 (1 << 14) #define DISABLERXOWN (1 << 13) #define FULLDPLXMODE (1 << 11) +#define ENABLEIPC (1 << 10) #define RXENABLE (1 << 2) #define TXENABLE (1 << 3) diff --git a/drivers/net/gmac_rockchip.c b/drivers/net/gmac_rockchip.c index 49cba41f524..98094e4bd28 100644 --- a/drivers/net/gmac_rockchip.c +++ b/drivers/net/gmac_rockchip.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -95,6 +96,37 @@ static int rk3288_gmac_fix_mac_speed(struct dw_eth_dev *priv) return 0; } +static int rk3328_gmac_fix_mac_speed(struct dw_eth_dev *priv) +{ + struct rk3328_grf_regs *grf; + int clk; + enum { + RK3328_GMAC_CLK_SEL_2_5M = 2 << 11, + RK3328_GMAC_CLK_SEL_25M = 3 << 11, + RK3328_GMAC_CLK_SEL_125M = 0 << 11, + RK3328_GMAC_CLK_SEL_MASK = GENMASK(12, 11), + }; + + switch (priv->phydev->speed) { + case 10: + clk = RK3328_GMAC_CLK_SEL_2_5M; + break; + case 100: + clk = RK3328_GMAC_CLK_SEL_25M; + break; + case 1000: + clk = RK3328_GMAC_CLK_SEL_125M; + break; + default: + debug("Unknown phy speed: %d\n", priv->phydev->speed); + return -EINVAL; + } + + grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); + rk_clrsetreg(&grf->mac_con[1], RK3328_GMAC_CLK_SEL_MASK, clk); + return 0; +} + static int rk3368_gmac_fix_mac_speed(struct dw_eth_dev *priv) { struct rk3368_grf *grf; @@ -173,6 +205,61 @@ static void rk3288_gmac_set_to_rgmii(struct gmac_rockchip_platdata *pdata) pdata->tx_delay << RK3288_CLK_TX_DL_CFG_GMAC_SHIFT); } +static void rk3328_gmac_set_to_rgmii(struct gmac_rockchip_platdata *pdata) +{ + struct rk3328_grf_regs *grf; + enum { + RK3328_GMAC_PHY_INTF_SEL_RGMII = BIT(4), + RK3328_GMAC_PHY_INTF_SEL_MASK = GENMASK(6, 4), + + RK3328_GMAC_RMII_MODE_MASK = BIT(9), + RK3328_GMAC_RMII_MODE_DISABLE = 0, + RK3328_GMAC_RMII_MODE_ENABLE = BIT(9), + }; + enum { + RK3328_RXCLK_DLY_ENA_GMAC_MASK = BIT(1), + RK3328_RXCLK_DLY_ENA_GMAC_DISABLE = 0, + RK3328_RXCLK_DLY_ENA_GMAC_ENABLE = BIT(1), + RK3328_TXCLK_DLY_ENA_GMAC_MASK = BIT(0), + RK3328_TXCLK_DLY_ENA_GMAC_DISABLE = 0, + RK3328_TXCLK_DLY_ENA_GMAC_ENABLE = BIT(0), + RK3328_CLK_RX_DL_CFG_GMAC_SHIFT = 7, + RK3328_CLK_RX_DL_CFG_GMAC_MASK = GENMASK(13, 7), + RK3328_CLK_TX_DL_CFG_GMAC_SHIFT = 0, + RK3328_CLK_TX_DL_CFG_GMAC_MASK = GENMASK(6, 0), + }; + enum { + RK3328_GMAC_IO_SEL_MASK = BIT(2), + RK3328_GMAC_IO_SEL_M1 = BIT(2), + + RK3328_GMAC_M1_CH_SELECT_MASK = BIT(10), + RK3328_GMAC_M1_CH_SELECT_M1 = 0, + }; + + grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); + rk_clrsetreg(&grf->mac_con[1], + RK3328_GMAC_PHY_INTF_SEL_MASK | + RK3328_RXCLK_DLY_ENA_GMAC_MASK | + RK3328_TXCLK_DLY_ENA_GMAC_MASK | + RK3328_GMAC_RMII_MODE_MASK, + RK3328_GMAC_PHY_INTF_SEL_RGMII | + RK3328_RXCLK_DLY_ENA_GMAC_ENABLE | + RK3328_TXCLK_DLY_ENA_GMAC_ENABLE | + RK3328_GMAC_RMII_MODE_DISABLE); + + rk_clrsetreg(&grf->mac_con[0], + RK3328_CLK_RX_DL_CFG_GMAC_MASK | + RK3328_CLK_TX_DL_CFG_GMAC_MASK, + pdata->rx_delay << RK3328_CLK_RX_DL_CFG_GMAC_SHIFT | + pdata->tx_delay << RK3328_CLK_TX_DL_CFG_GMAC_SHIFT); + + rk_clrsetreg(&grf->com_iomux, + RK3328_GMAC_IO_SEL_MASK | + RK3328_GMAC_M1_CH_SELECT_MASK, + RK3328_GMAC_IO_SEL_M1 | + RK3328_GMAC_M1_CH_SELECT_M1); +} + static void rk3368_gmac_set_to_rgmii(struct gmac_rockchip_platdata *pdata) { struct rk3368_grf *grf; @@ -290,6 +377,11 @@ const struct rk_gmac_ops rk3288_gmac_ops = { .set_to_rgmii = rk3288_gmac_set_to_rgmii, }; +const struct rk_gmac_ops rk3328_gmac_ops = { + .fix_mac_speed = rk3328_gmac_fix_mac_speed, + .set_to_rgmii = rk3328_gmac_set_to_rgmii, +}; + const struct rk_gmac_ops rk3368_gmac_ops = { .fix_mac_speed = rk3368_gmac_fix_mac_speed, .set_to_rgmii = rk3368_gmac_set_to_rgmii, @@ -303,6 +395,8 @@ const struct rk_gmac_ops rk3399_gmac_ops = { static const struct udevice_id rockchip_gmac_ids[] = { { .compatible = "rockchip,rk3288-gmac", .data = (ulong)&rk3288_gmac_ops }, + { .compatible = "rockchip,rk3328-gmac", + .data = (ulong)&rk3328_gmac_ops }, { .compatible = "rockchip,rk3368-gmac", .data = (ulong)&rk3368_gmac_ops }, { .compatible = "rockchip,rk3399-gmac", diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c index 6d917f86f44..370bd83962d 100644 --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c @@ -48,7 +48,10 @@ #define MIIM_RTL8211F_PHYSTAT_LINK 0x0004 #define MIIM_RTL8211F_PAGE_SELECT 0x1f -#define MIIM_RTL8211F_TX_DELAY 0x100 +#define MIIM_RTL8211F_RX_DELAY_REG 0x15 +#define MIIM_RTL8211F_RX_DELAY_EN BIT(3) +#define MIIM_RTL8211F_TX_DELAY_REG 0x11 +#define MIIM_RTL8211F_TX_DELAY_EN BIT(8) #define MIIM_RTL8211F_LCR 0x10 static int rtl8211b_probe(struct phy_device *phydev) @@ -97,16 +100,29 @@ static int rtl8211f_config(struct phy_device *phydev) phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211F_PAGE_SELECT, 0xd08); - reg = phy_read(phydev, MDIO_DEVAD_NONE, 0x11); + + reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211F_TX_DELAY_REG); /* enable TX-delay for rgmii-id and rgmii-txid, otherwise disable it */ if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) - reg |= MIIM_RTL8211F_TX_DELAY; + reg |= MIIM_RTL8211F_TX_DELAY_EN; + else + reg &= ~MIIM_RTL8211F_TX_DELAY_EN; + + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211F_TX_DELAY_REG, reg); + + reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211F_RX_DELAY_REG); + + /* enable TX-delay for rgmii-id and rgmii-txid, otherwise disable it */ + if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || + phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) + reg |= MIIM_RTL8211F_RX_DELAY_EN; else - reg &= ~MIIM_RTL8211F_TX_DELAY; + reg &= ~MIIM_RTL8211F_RX_DELAY_EN; + + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211F_RX_DELAY_REG, reg); - phy_write(phydev, MDIO_DEVAD_NONE, 0x11, reg); /* restore to default page 0 */ phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211F_PAGE_SELECT, 0x0); diff --git a/drivers/pinctrl/rockchip/pinctrl_rk3328.c b/drivers/pinctrl/rockchip/pinctrl_rk3328.c index f3e7eec9e44..c928134deca 100644 --- a/drivers/pinctrl/rockchip/pinctrl_rk3328.c +++ b/drivers/pinctrl/rockchip/pinctrl_rk3328.c @@ -200,6 +200,159 @@ static void pinctrl_rk3328_sdmmc_config(struct rk3328_grf_regs *grf, } } +#if CONFIG_IS_ENABLED(GMAC_ROCKCHIP) +static void pinctrl_rk3328_gmac_config(struct rk3328_grf_regs *grf, int gmac_id) +{ + rk_clrsetreg(&grf->gpio1b_iomux, + GPIO1B0_SEL_MASK | + GPIO1B1_SEL_MASK | + GPIO1B2_SEL_MASK | + GPIO1B4_SEL_MASK | + GPIO1B5_SEL_MASK | + GPIO1B6_SEL_MASK | + GPIO1B7_SEL_MASK, + GPIO1B0_MAC_TXD1 << GPIO1B0_SEL_SHIFT | + GPIO1B1_MAC_TXD0 << GPIO1B1_SEL_SHIFT | + GPIO1B2_MAC_RXD1 << GPIO1B2_SEL_SHIFT | + GPIO1B3_MAC_RXD0 << GPIO1B3_SEL_SHIFT | + GPIO1B4_MAC_TXCLK << GPIO1B4_SEL_SHIFT | + GPIO1B5_MAC_RXCLK << GPIO1B5_SEL_SHIFT | + GPIO1B6_MAC_RXD3 << GPIO1B6_SEL_SHIFT | + GPIO1B7_MAC_RXD2 << GPIO1B7_SEL_SHIFT); + + rk_clrsetreg(&grf->gpio1b_p, + GPIO1B0_SEL_MASK | + GPIO1B1_SEL_MASK | + GPIO1B2_SEL_MASK | + GPIO1B4_SEL_MASK | + GPIO1B5_SEL_MASK | + GPIO1B6_SEL_MASK | + GPIO1B7_SEL_MASK, + GPIO_PULL_NORMAL << GPIO1B0_SEL_SHIFT | + GPIO_PULL_NORMAL << GPIO1B1_SEL_SHIFT | + GPIO_PULL_NORMAL << GPIO1B2_SEL_SHIFT | + GPIO_PULL_NORMAL << GPIO1B3_SEL_SHIFT | + GPIO_PULL_NORMAL << GPIO1B4_SEL_SHIFT | + GPIO_PULL_NORMAL << GPIO1B5_SEL_SHIFT | + GPIO_PULL_NORMAL << GPIO1B6_SEL_SHIFT | + GPIO_PULL_NORMAL << GPIO1B7_SEL_SHIFT); + + rk_clrsetreg(&grf->gpio1b_e, + GPIO1B0_SEL_MASK | + GPIO1B1_SEL_MASK | + GPIO1B2_SEL_MASK | + GPIO1B4_SEL_MASK | + GPIO1B5_SEL_MASK | + GPIO1B6_SEL_MASK | + GPIO1B7_SEL_MASK, + GPIO_BIAS_12MA << GPIO1B0_SEL_SHIFT | + GPIO_BIAS_12MA << GPIO1B1_SEL_SHIFT | + GPIO_BIAS_2MA << GPIO1B2_SEL_SHIFT | + GPIO_BIAS_2MA << GPIO1B3_SEL_SHIFT | + GPIO_BIAS_12MA << GPIO1B4_SEL_SHIFT | + GPIO_BIAS_2MA << GPIO1B5_SEL_SHIFT | + GPIO_BIAS_2MA << GPIO1B6_SEL_SHIFT | + GPIO_BIAS_2MA << GPIO1B7_SEL_SHIFT); + + rk_clrsetreg(&grf->gpio1c_iomux, + GPIO1C0_SEL_MASK | + GPIO1C1_SEL_MASK | + GPIO1C3_SEL_MASK | + GPIO1C5_SEL_MASK | + GPIO1C6_SEL_MASK | + GPIO1C7_SEL_MASK, + GPIO1C0_MAC_TXD3 << GPIO1C0_SEL_SHIFT | + GPIO1C1_MAC_TXD2 << GPIO1C1_SEL_SHIFT | + GPIO1C3_MAC_MDIO << GPIO1C3_SEL_SHIFT | + GPIO1C5_MAC_CLK << GPIO1C5_SEL_SHIFT | + GPIO1C6_MAC_RXDV << GPIO1C6_SEL_SHIFT | + GPIO1C7_MAC_MDC << GPIO1C7_SEL_SHIFT); + + rk_clrsetreg(&grf->gpio1c_p, + GPIO1C0_SEL_MASK | + GPIO1C1_SEL_MASK | + GPIO1C3_SEL_MASK | + GPIO1C5_SEL_MASK | + GPIO1C6_SEL_MASK | + GPIO1C7_SEL_MASK, + GPIO_PULL_NORMAL << GPIO1C0_SEL_SHIFT | + GPIO_PULL_NORMAL << GPIO1C1_SEL_SHIFT | + GPIO_PULL_NORMAL << GPIO1C3_SEL_SHIFT | + GPIO_PULL_NORMAL << GPIO1C5_SEL_SHIFT | + GPIO_PULL_NORMAL << GPIO1C6_SEL_SHIFT | + GPIO_PULL_NORMAL << GPIO1C7_SEL_SHIFT); + + rk_clrsetreg(&grf->gpio1c_e, + GPIO1C0_SEL_MASK | + GPIO1C1_SEL_MASK | + GPIO1C2_SEL_MASK | + GPIO1C3_SEL_MASK | + GPIO1C4_SEL_MASK | + GPIO1C5_SEL_MASK | + GPIO1C6_SEL_MASK | + GPIO1C7_SEL_MASK, + GPIO_BIAS_12MA << GPIO1C0_SEL_SHIFT | + GPIO_BIAS_12MA << GPIO1C1_SEL_SHIFT | + GPIO_BIAS_2MA << GPIO1C2_SEL_SHIFT | + GPIO_BIAS_2MA << GPIO1C3_SEL_SHIFT | + GPIO_BIAS_2MA << GPIO1C4_SEL_SHIFT | + GPIO_BIAS_2MA << GPIO1C5_SEL_SHIFT | + GPIO_BIAS_2MA << GPIO1C6_SEL_SHIFT | + GPIO_BIAS_2MA << GPIO1C7_SEL_SHIFT); + + rk_clrsetreg(&grf->gpio1d_iomux, + GPIO1D1_SEL_MASK, + GPIO1D1_MAC_TXEN << GPIO1D1_SEL_SHIFT); + + rk_clrsetreg(&grf->gpio1d_p, + GPIO1D1_SEL_MASK, 0); + + rk_clrsetreg(&grf->gpio1d_e, + GPIO1D1_SEL_MASK, + GPIO_BIAS_12MA << GPIO1D1_SEL_SHIFT); + + rk_clrsetreg(&grf->gpio0b_iomux, + GPIO0B0_SEL_MASK | + GPIO0B4_SEL_MASK, + GPIO0B0_MAC_TXCLK << GPIO0B0_SEL_SHIFT | + GPIO0B4_MAC_TXEN << GPIO0B4_SEL_SHIFT); + + rk_clrsetreg(&grf->gpio0b_p, + GPIO0B0_SEL_MASK | + GPIO0B4_SEL_MASK, + GPIO_PULL_NORMAL << GPIO0B0_SEL_SHIFT | + GPIO_PULL_NORMAL << GPIO0B4_SEL_SHIFT); + + rk_clrsetreg(&grf->gpio0c_iomux, + GPIO0C0_SEL_MASK | + GPIO0C1_SEL_MASK | + GPIO0C6_SEL_MASK | + GPIO0C7_SEL_MASK, + GPIO0C0_MAC_TXD1 << GPIO0C0_SEL_SHIFT | + GPIO0C1_MAC_TXD0 << GPIO0C1_SEL_SHIFT | + GPIO0C6_MAC_TXD2 << GPIO0C6_SEL_SHIFT | + GPIO0C7_MAC_TXD3 << GPIO0C7_SEL_SHIFT); + + rk_clrsetreg(&grf->gpio0c_p, + GPIO0C0_SEL_MASK | + GPIO0C1_SEL_MASK | + GPIO0C6_SEL_MASK | + GPIO0C7_SEL_MASK, + GPIO_PULL_NORMAL << GPIO0C0_SEL_SHIFT | + GPIO_PULL_NORMAL << GPIO0C1_SEL_SHIFT | + GPIO_PULL_NORMAL << GPIO0C6_SEL_SHIFT | + GPIO_PULL_NORMAL << GPIO0C7_SEL_SHIFT); + + rk_clrsetreg(&grf->gpio0d_iomux, + GPIO0D0_SEL_MASK, + GPIO0D0_MAC_CLK << GPIO0D0_SEL_SHIFT); + + rk_clrsetreg(&grf->gpio0d_p, + GPIO0D0_SEL_MASK, + GPIO_PULL_NORMAL << GPIO0D0_SEL_SHIFT); +} +#endif + static int rk3328_pinctrl_request(struct udevice *dev, int func, int flags) { struct rk3328_pinctrl_priv *priv = dev_get_priv(dev); @@ -236,6 +389,11 @@ static int rk3328_pinctrl_request(struct udevice *dev, int func, int flags) case PERIPH_ID_SDMMC1: pinctrl_rk3328_sdmmc_config(priv->grf, func); break; +#if CONFIG_IS_ENABLED(GMAC_ROCKCHIP) + case PERIPH_ID_GMAC: + pinctrl_rk3328_gmac_config(priv->grf, func); + break; +#endif default: return -EINVAL; } @@ -271,6 +429,10 @@ static int rk3328_pinctrl_get_periph_id(struct udevice *dev, return PERIPH_ID_SDCARD; case 14: return PERIPH_ID_EMMC; +#if CONFIG_IS_ENABLED(GMAC_ROCKCHIP) + case 24: + return PERIPH_ID_GMAC; +#endif } return -ENOENT; diff --git a/drivers/pinctrl/rockchip/pinctrl_rk3399.c b/drivers/pinctrl/rockchip/pinctrl_rk3399.c index d93b90310b0..b8a7b9ae875 100644 --- a/drivers/pinctrl/rockchip/pinctrl_rk3399.c +++ b/drivers/pinctrl/rockchip/pinctrl_rk3399.c @@ -70,10 +70,17 @@ static void pinctrl_rk3399_i2c_config(struct rk3399_grf_regs *grf, PMUGRF_GPIO1C0_SEL_MASK, PMUGRF_I2C0PMU_SCL << PMUGRF_GPIO1C0_SEL_SHIFT); break; + case PERIPH_ID_I2C4: + rk_clrsetreg(&pmugrf->gpio1b_iomux, + PMUGRF_GPIO1B3_SEL_MASK, + PMUGRF_I2C4PMU_SDA << PMUGRF_GPIO1B3_SEL_SHIFT); + rk_clrsetreg(&pmugrf->gpio1b_iomux, + PMUGRF_GPIO1B4_SEL_MASK, + PMUGRF_I2C4PMU_SCL << PMUGRF_GPIO1B4_SEL_SHIFT); + break; case PERIPH_ID_I2C1: case PERIPH_ID_I2C2: case PERIPH_ID_I2C3: - case PERIPH_ID_I2C4: case PERIPH_ID_I2C5: default: debug("i2c id = %d iomux error!\n", i2c_id); diff --git a/drivers/power/pmic/rk8xx.c b/drivers/power/pmic/rk8xx.c index 0f7771f7b34..8acefa403af 100644 --- a/drivers/power/pmic/rk8xx.c +++ b/drivers/power/pmic/rk8xx.c @@ -33,6 +33,11 @@ static const struct pmic_child_info fuel_gauge_info[] = { { }, }; +static const struct pmic_child_info led_info[] = { + { .prefix = "led", .driver = "rk8xx_led"}, + { }, +}; + static int rk8xx_reg_count(struct udevice *dev) { return RK808_NUM_OF_REGS; @@ -130,6 +135,10 @@ static int rk8xx_bind(struct udevice *dev) if (!children) debug("%s: %s - no child found\n", __func__, dev->name); + children = pmic_bind_children(dev, dev->node, led_info); + if (!children) + debug("%s: %s - no child found\n", __func__, dev->name); + /* Always return success for this device */ return 0; } diff --git a/drivers/power/regulator/rk8xx.c b/drivers/power/regulator/rk8xx.c index 355c945a3bb..9af501f6b86 100644 --- a/drivers/power/regulator/rk8xx.c +++ b/drivers/power/regulator/rk8xx.c @@ -15,6 +15,7 @@ #include #include #include +#include #ifndef CONFIG_SPL_BUILD #define ENABLE_DRIVER @@ -518,6 +519,39 @@ static int switch_get_enable(struct udevice *dev) return ret & mask ? true : false; } +static enum led_state_t rk8xx_led_get_state(struct udevice *dev) +{ + int sw = dev->driver_data - 1; + int ret; + uint mask; + + mask = 1 << sw; + + ret = pmic_reg_read(dev->parent, REG_OUT_CTRL); + if (ret < 0) + return ret; + + return ret & mask ? LEDST_OFF : LEDST_ON; +} + +static int rk8xx_led_set_state(struct udevice *dev, enum led_state_t state) +{ + int sw = dev->driver_data - 1; + uint mask; + + mask = 1 << sw; + + if (state == LEDST_TOGGLE) { + if (rk8xx_led_get_state(dev) == LEDST_ON) + state = LEDST_OFF; + else + state = LEDST_ON; + } + + return pmic_clrsetbits(dev->parent, REG_OUT_CTRL, mask, + state ? 0 : mask); +} + static int rk8xx_buck_probe(struct udevice *dev) { struct dm_regulator_uclass_platdata *uc_pdata; @@ -554,6 +588,21 @@ static int rk8xx_switch_probe(struct udevice *dev) return 0; } +static int rk8xx_led_bind(struct udevice *dev) +{ + struct led_uc_plat *uc_pdata; + + uc_pdata = dev_get_uclass_platdata(dev); + uc_pdata->label = dev_read_string(dev, "label"); + + return 0; +} + +static int rk8xx_led_probe(struct udevice *dev) +{ + return 0; +} + static const struct dm_regulator_ops rk8xx_buck_ops = { .get_value = buck_get_value, .set_value = buck_set_value, @@ -577,6 +626,11 @@ static const struct dm_regulator_ops rk8xx_switch_ops = { .set_enable = switch_set_enable, }; +static const struct led_ops rk8xx_led_ops = { + .get_state = rk8xx_led_get_state, + .set_state = rk8xx_led_set_state, +}; + U_BOOT_DRIVER(rk8xx_buck) = { .name = "rk8xx_buck", .id = UCLASS_REGULATOR, @@ -597,6 +651,14 @@ U_BOOT_DRIVER(rk8xx_switch) = { .ops = &rk8xx_switch_ops, .probe = rk8xx_switch_probe, }; + +U_BOOT_DRIVER(rk8xx_led) = { + .name = "rk8xx_led", + .id = UCLASS_LED, + .ops = &rk8xx_led_ops, + .bind = rk8xx_led_bind, + .probe = rk8xx_led_probe, +}; #endif int rk8xx_spl_configure_buck(struct udevice *pmic, int buck, int uvolt) diff --git a/drivers/ram/rockchip/sdram_rk3328.c b/drivers/ram/rockchip/sdram_rk3328.c index 863b1202b70..d32e2c5cee7 100644 --- a/drivers/ram/rockchip/sdram_rk3328.c +++ b/drivers/ram/rockchip/sdram_rk3328.c @@ -598,6 +598,16 @@ static void enable_low_power(struct dram_info *dram, setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, (1 << 3)); } +static inline void mmio_write_32(uintptr_t addr, uint32_t value) +{ + *(volatile uint32_t*)addr = value; +} + +static inline void mmio_write_64(uintptr_t addr, uint64_t value) +{ + *(volatile uint64_t*)addr = value; +} + static int sdram_init(struct dram_info *dram, struct rk3328_sdram_params *sdram_params, u32 pre_init) { @@ -625,6 +635,8 @@ static int sdram_init(struct dram_info *dram, printf("LPDDR3\n"); break; } + + printf("DRAM frequency: %dMHz\n", sdram_params->ddr_freq); } /* release phy srst to provide clk to ctrl */ rkclk_ddr_reset(dram, 1, 1, 0, 0); @@ -661,6 +673,18 @@ static int sdram_init(struct dram_info *dram, dram_all_config(dram, sdram_params); enable_low_power(dram, sdram_params); + // TODO: ayufan configure memory regions for ATF +#define DDR_PARAM_BASE 0x02000000 +#define DDR_REGION_NR_MAX 10 +#define REGION_NR_OFFSET 0 +#define REGION_ADDR_OFFSET 8 +#define REGION_DATA_PER_BYTES 8 + + printf("configuring DDR parameters\n"); + mmio_write_32(DDR_PARAM_BASE + REGION_NR_OFFSET, 1); + mmio_write_64(DDR_PARAM_BASE + REGION_ADDR_OFFSET, 0); + mmio_write_64(DDR_PARAM_BASE + REGION_ADDR_OFFSET + REGION_DATA_PER_BYTES, 0x100000000); + return 0; } @@ -979,6 +1003,24 @@ static int rk3328_dmc_ofdata_to_platdata(struct udevice *dev) #endif +struct ddr_param{ + u32 count; + u32 reserved; + u64 bank_addr; + u64 bank_size; +}; +#define PARAM_DRAM_INFO_OFFSET 0x2000000 +int setup_ddr_param(struct ram_info *info) +{ + struct ddr_param *dinfo = (struct ddr_param *)PARAM_DRAM_INFO_OFFSET; + + dinfo->count = 1; + dinfo->bank_addr = info->base; + dinfo->bank_size = info->size; + printf("%s %p %d\n", __func__, &dinfo->count, dinfo->count); + return 0; +} + static int rk3328_dmc_probe(struct udevice *dev) { #ifdef CONFIG_TPL_BUILD @@ -992,6 +1034,9 @@ static int rk3328_dmc_probe(struct udevice *dev) priv->info.base = CONFIG_SYS_SDRAM_BASE; priv->info.size = rockchip_sdram_size( (phys_addr_t)&priv->grf->os_reg[2]); +#ifdef CONFIG_SPL_BUILD + setup_ddr_param(&priv->info); +#endif #endif return 0; } diff --git a/drivers/ram/rockchip/sdram_rk3399.c b/drivers/ram/rockchip/sdram_rk3399.c index 5ed4b03837d..7b66967a4af 100644 --- a/drivers/ram/rockchip/sdram_rk3399.c +++ b/drivers/ram/rockchip/sdram_rk3399.c @@ -32,7 +32,7 @@ struct chan_info { }; struct dram_info { -#ifdef CONFIG_SPL_BUILD +#ifdef CONFIG_TPL_BUILD struct chan_info chan[2]; struct clk ddr_clk; struct rk3399_cru *cru; @@ -57,7 +57,7 @@ struct dram_info { #define PHY_DRV_ODT_40 0xe #define PHY_DRV_ODT_34_3 0xf -#ifdef CONFIG_SPL_BUILD +#ifdef CONFIG_TPL_BUILD struct rockchip_dmc_plat { #if CONFIG_IS_ENABLED(OF_PLATDATA) @@ -1188,7 +1188,7 @@ static int rk3399_dmc_init(struct udevice *dev) static int rk3399_dmc_probe(struct udevice *dev) { -#ifdef CONFIG_SPL_BUILD +#ifdef CONFIG_TPL_BUILD if (rk3399_dmc_init(dev)) return 0; #else @@ -1227,12 +1227,12 @@ U_BOOT_DRIVER(dmc_rk3399) = { .id = UCLASS_RAM, .of_match = rk3399_dmc_ids, .ops = &rk3399_dmc_ops, -#ifdef CONFIG_SPL_BUILD +#ifdef CONFIG_TPL_BUILD .ofdata_to_platdata = rk3399_dmc_ofdata_to_platdata, #endif .probe = rk3399_dmc_probe, .priv_auto_alloc_size = sizeof(struct dram_info), -#ifdef CONFIG_SPL_BUILD +#ifdef CONFIG_TPL_BUILD .platdata_auto_alloc_size = sizeof(struct rockchip_dmc_plat), #endif }; diff --git a/drivers/spi/rk_spi.c b/drivers/spi/rk_spi.c index c70d6362770..cadf881eb14 100644 --- a/drivers/spi/rk_spi.c +++ b/drivers/spi/rk_spi.c @@ -29,7 +29,7 @@ DECLARE_GLOBAL_DATA_PTR; struct rockchip_spi_platdata { #if CONFIG_IS_ENABLED(OF_PLATDATA) - struct dtd_rockchip_rk3288_spi of_plat; + struct dtd_rockchip_rk3066_spi of_plat; #endif s32 frequency; /* Default clock frequency, -1 for none */ fdt_addr_t base; @@ -162,7 +162,7 @@ static void spi_cs_deactivate(struct udevice *dev, uint cs) static int conv_of_platdata(struct udevice *dev) { struct rockchip_spi_platdata *plat = dev->platdata; - struct dtd_rockchip_rk3288_spi *dtplat = &plat->of_plat; + struct dtd_rockchip_rk3066_spi *dtplat = &plat->of_plat; struct rockchip_spi_priv *priv = dev_get_priv(dev); int ret; @@ -451,6 +451,7 @@ static const struct dm_spi_ops rockchip_spi_ops = { static const struct udevice_id rockchip_spi_ids[] = { { .compatible = "rockchip,rk3288-spi" }, + { .compatible = "rockchip,rk3328-spi" }, { .compatible = "rockchip,rk3368-spi" }, { .compatible = "rockchip,rk3399-spi" }, { } diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c index 64c42ac4715..5426f4c9da6 100644 --- a/drivers/usb/host/dwc2.c +++ b/drivers/usb/host/dwc2.c @@ -1122,7 +1122,11 @@ static int dwc2_init_common(struct udevice *dev, struct dwc2_priv *priv) #endif dwc_otg_core_init(priv); - dwc_otg_core_host_init(dev, regs); + + // HACK: needed by RK3328 to have OTG properly working + for(i = 0; i < 2; ++i) { + dwc_otg_core_host_init(dev, regs); + } clrsetbits_le32(®s->hprt0, DWC2_HPRT0_PRTENA | DWC2_HPRT0_PRTCONNDET | DWC2_HPRT0_PRTENCHNG | diff --git a/drivers/usb/host/xhci-rockchip.c b/drivers/usb/host/xhci-rockchip.c index ec55f4e59f7..920ffb73f9a 100644 --- a/drivers/usb/host/xhci-rockchip.c +++ b/drivers/usb/host/xhci-rockchip.c @@ -37,6 +37,30 @@ struct rockchip_xhci { struct dwc3 *dwc3_reg; }; +static const char *const speed_names[] = { + [DWC3_DCFG_SUPERSPEED] = "UNKNOWN", + [DWC3_DCFG_LOWSPEED] = "low-speed", + [DWC3_DCFG_FULLSPEED2] = "full-speed", + [DWC3_DCFG_HIGHSPEED] = "high-speed", + [DWC3_DCFG_SUPERSPEED] = "super-speed" +}; + +u32 xhci_usb_get_maximum_speed(struct udevice *dev) +{ + const char *maximum_speed; + int i; + + maximum_speed = dev_read_string(dev, "maximum-speed"); + if (maximum_speed == NULL) + return DWC3_DCFG_SUPERSPEED; + + for (i = 0; i < ARRAY_SIZE(speed_names); i++) + if (strcmp(maximum_speed, speed_names[i]) == 0) + return i; + + return DWC3_DCFG_SUPERSPEED; +} + static int xhci_usb_ofdata_to_platdata(struct udevice *dev) { struct rockchip_xhci_platdata *plat = dev_get_platdata(dev); @@ -110,6 +134,12 @@ static void rockchip_dwc3_phy_setup(struct dwc3 *dwc3_reg, reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; writel(reg, &dwc3_reg->g_usb2phycfg[0]); + + /* Set dwc3 device config register */ + reg = readl(&dwc3_reg->d_cfg); + reg &= ~DWC3_DCFG_SPEED_MASK; + reg |= xhci_usb_get_maximum_speed(dev); + writel(reg, &dwc3_reg->d_cfg); } static int rockchip_xhci_core_init(struct rockchip_xhci *rkxhci, @@ -117,17 +147,17 @@ static int rockchip_xhci_core_init(struct rockchip_xhci *rkxhci, { int ret; + rockchip_dwc3_phy_setup(rkxhci->dwc3_reg, dev); + + /* We are hard-coding DWC3 core to Host Mode */ + dwc3_set_mode(rkxhci->dwc3_reg, DWC3_GCTL_PRTCAP_HOST); + ret = dwc3_core_init(rkxhci->dwc3_reg); if (ret) { error("failed to initialize core\n"); return ret; } - rockchip_dwc3_phy_setup(rkxhci->dwc3_reg, dev); - - /* We are hard-coding DWC3 core to Host Mode */ - dwc3_set_mode(rkxhci->dwc3_reg, DWC3_GCTL_PRTCAP_HOST); - return 0; } diff --git a/include/blk.h b/include/blk.h index 9cf5466662a..d8e3825454a 100644 --- a/include/blk.h +++ b/include/blk.h @@ -8,6 +8,8 @@ #ifndef BLK_H #define BLK_H +#include + #ifdef CONFIG_SYS_64BIT_LBA typedef uint64_t lbaint_t; #define LBAFlength "ll" @@ -43,6 +45,17 @@ enum if_type { #define BLK_PRD_SIZE 20 #define BLK_REV_SIZE 8 +/* + * Identifies the partition table type (ie. MBR vs GPT GUID) signature + */ +enum sig_type { + SIG_TYPE_NONE, + SIG_TYPE_MBR, + SIG_TYPE_GUID, + + SIG_TYPE_COUNT /* Number of signature types */ +}; + /* * With driver model (CONFIG_BLK) this is uclass platform data, accessible * with dev_get_uclass_platdata(dev) @@ -70,6 +83,11 @@ struct blk_desc { char vendor[BLK_VEN_SIZE + 1]; /* device vendor string */ char product[BLK_PRD_SIZE + 1]; /* device product number */ char revision[BLK_REV_SIZE + 1]; /* firmware revision */ + enum sig_type sig_type; /* Partition table signature type */ + union { + uint32_t mbr_sig; /* MBR integer signature */ + efi_guid_t guid_sig; /* GPT GUID Signature */ + }; #if CONFIG_IS_ENABLED(BLK) /* * For now we have a few functions which take struct blk_desc as a diff --git a/include/configs/evb_rk3399.h b/include/configs/evb_rk3399.h index 9e2c2e5c136..868491380a5 100644 --- a/include/configs/evb_rk3399.h +++ b/include/configs/evb_rk3399.h @@ -9,7 +9,10 @@ #include +#ifndef CONFIG_SPL_BUILD #define CONFIG_MMC_SDHCI_SDMA +#endif + #define CONFIG_SYS_MMC_ENV_DEV 0 #define SDRAM_BANK_SIZE (2UL << 30) diff --git a/include/configs/pinebook_pro_rk3399.h b/include/configs/pinebook_pro_rk3399.h new file mode 100644 index 00000000000..0d6a159f0f4 --- /dev/null +++ b/include/configs/pinebook_pro_rk3399.h @@ -0,0 +1,34 @@ +/* + * (C) Copyright 2016 Rockchip Electronics Co., Ltd + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __EVB_RK3399_H +#define __EVB_RK3399_H + +#include + +#ifndef CONFIG_SPL_BUILD +#define CONFIG_MMC_SDHCI_SDMA +#endif + +#define CONFIG_SYS_MMC_ENV_DEV 0 + +#define SDRAM_BANK_SIZE (2UL << 30) +#define CONFIG_MISC_INIT_R +#define CONFIG_SERIAL_TAG +#define CONFIG_ENV_OVERWRITE + +#define CONFIG_BMP_16BPP +#define CONFIG_BMP_24BPP +#define CONFIG_BMP_32BPP + +#define ROCKCHIP_DEVICE_SETTINGS \ + "stdout=serial,vidconsole\0" \ + "stderr=serial,vidconsole\0" + +#undef CONFIG_SYS_SPI_U_BOOT_OFFS +#define CONFIG_SYS_SPI_U_BOOT_OFFS 1024 * 512 + +#endif diff --git a/include/configs/rk3036_common.h b/include/configs/rk3036_common.h index d883efcf9b3..2322c45c023 100644 --- a/include/configs/rk3036_common.h +++ b/include/configs/rk3036_common.h @@ -65,6 +65,7 @@ * so limit the fdt reallocation to that */ #define CONFIG_EXTRA_ENV_SETTINGS \ "fdt_high=0x7fffffff\0" \ + "fdtfile=" FDTFILE \ "partitions=" PARTS_DEFAULT \ ENV_MEM_LAYOUT_SETTINGS \ BOOTENV diff --git a/include/configs/rk3188_common.h b/include/configs/rk3188_common.h index 0fde4cc9856..db1ee28224f 100644 --- a/include/configs/rk3188_common.h +++ b/include/configs/rk3188_common.h @@ -80,6 +80,7 @@ #define CONFIG_EXTRA_ENV_SETTINGS \ "fdt_high=0x6fffffff\0" \ "initrd_high=0x6fffffff\0" \ + "fdtfile=" FDTFILE \ "partitions=" PARTS_DEFAULT \ ENV_MEM_LAYOUT_SETTINGS \ ROCKCHIP_DEVICE_SETTINGS \ diff --git a/include/configs/rk322x_common.h b/include/configs/rk322x_common.h index d0e7fda38a5..2775bfe4e60 100644 --- a/include/configs/rk322x_common.h +++ b/include/configs/rk322x_common.h @@ -62,6 +62,7 @@ * so limit the fdt reallocation to that */ #define CONFIG_EXTRA_ENV_SETTINGS \ "fdt_high=0x7fffffff\0" \ + "fdtfile=" FDTFILE \ "partitions=" PARTS_DEFAULT \ ENV_MEM_LAYOUT_SETTINGS \ BOOTENV diff --git a/include/configs/rk3288_common.h b/include/configs/rk3288_common.h index 2d1a41a0405..d6255653d37 100644 --- a/include/configs/rk3288_common.h +++ b/include/configs/rk3288_common.h @@ -80,6 +80,7 @@ #define CONFIG_EXTRA_ENV_SETTINGS \ "fdt_high=0x0fffffff\0" \ "initrd_high=0x0fffffff\0" \ + "fdtfile=" FDTFILE \ "partitions=" PARTS_DEFAULT \ ENV_MEM_LAYOUT_SETTINGS \ ROCKCHIP_DEVICE_SETTINGS \ diff --git a/include/configs/rk3328_common.h b/include/configs/rk3328_common.h index b7971782b5c..4018ea2c7dc 100644 --- a/include/configs/rk3328_common.h +++ b/include/configs/rk3328_common.h @@ -9,11 +9,18 @@ #include "rockchip-common.h" +#define CONFIG_MISC_INIT_R + #define CONFIG_SYS_MALLOC_LEN (32 << 20) #define CONFIG_SYS_CBSIZE 1024 #define CONFIG_SKIP_LOWLEVEL_INIT +/* #define CONFIG_MTD_DEVICE */ + #define CONFIG_SPL_FRAMEWORK +#if defined(CONFIG_SPL_SPI_SUPPORT) +#define CONFIG_SPL_SPI_LOAD +#endif #define CONFIG_SYS_NS16550_MEM32 @@ -23,8 +30,10 @@ #define CONFIG_SPL_STACK 0x00400000 #define CONFIG_SPL_TEXT_BASE 0x00000000 #define CONFIG_SPL_MAX_SIZE 0x10000 -#define CONFIG_SPL_BSS_START_ADDR 0x2000000 -#define CONFIG_SPL_BSS_MAX_SIZE 0x2000 +#define CONFIG_SPL_BSS_START_ADDR 0x00400000 +#define CONFIG_SPL_BSS_MAX_SIZE 0x20000 +#define CONFIG_TPL_STACK 0xff098000 +#define CONFIG_TPL_TEXT_BASE 0xff091000 #define CONFIG_SYS_BOOTM_LEN (64 << 20) /* 64M */ #define GICD_BASE 0xFF811000 @@ -32,6 +41,8 @@ #define CONFIG_ROCKUSB_G_DNL_PID 0x320C +#define CONFIG_UDP_CHECKSUM + /* MMC/SD IP block */ #define CONFIG_BOUNCE_BUFFER @@ -39,7 +50,7 @@ #define CONFIG_FS_EXT4 /* RAW SD card / eMMC locations. */ -#define CONFIG_SYS_SPI_U_BOOT_OFFS (128 << 10) +#define CONFIG_SYS_SPI_U_BOOT_OFFS (CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR * 512) /* FAT sd card locations. */ #define CONFIG_SYS_MMCSD_FS_BOOT_PARTITION 1 @@ -47,7 +58,7 @@ #define CONFIG_NR_DRAM_BANKS 1 #define SDRAM_MAX_SIZE 0xff000000 -#define CONFIG_SPI_FLASH +#define CONFIG_SPI_FLASH 1 #define CONFIG_SPI #define CONFIG_SF_DEFAULT_SPEED 20000000 @@ -66,6 +77,7 @@ #include #define CONFIG_EXTRA_ENV_SETTINGS \ ENV_MEM_LAYOUT_SETTINGS \ + "fdtfile=" FDTFILE \ "partitions=" PARTS_DEFAULT \ BOOTENV @@ -75,4 +87,17 @@ #define CONFIG_USB_OHCI_NEW #define CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS 1 +#define CONFIG_USB_FUNCTION_MASS_STORAGE + +#define CONFIG_PREBOOT + +/* enable usb config for usb ether */ +#define CONFIG_USB_HOST_ETHER + +#define CONFIG_USB_ETHER_ASIX +#define CONFIG_USB_ETHER_ASIX88179 +#define CONFIG_USB_ETHER_MCS7830 +#define CONFIG_USB_ETHER_SMSC95XX +#define CONFIG_USB_ETHER_RTL8152 + #endif diff --git a/include/configs/rk3368_common.h b/include/configs/rk3368_common.h index 734dd636368..9cd8967f88c 100644 --- a/include/configs/rk3368_common.h +++ b/include/configs/rk3368_common.h @@ -60,6 +60,8 @@ #include #define CONFIG_EXTRA_ENV_SETTINGS \ + ENV_MEM_LAYOUT_SETTINGS \ + "fdtfile=" FDTFILE \ BOOTENV #endif diff --git a/include/configs/rk3399_common.h b/include/configs/rk3399_common.h index a9a7905723f..014a29acb0d 100644 --- a/include/configs/rk3399_common.h +++ b/include/configs/rk3399_common.h @@ -25,12 +25,12 @@ #define CONFIG_SYS_TEXT_BASE 0x00200000 #define CONFIG_SYS_INIT_SP_ADDR 0x00300000 #define CONFIG_SYS_LOAD_ADDR 0x00800800 -#define CONFIG_SPL_STACK 0xff8effff -#define CONFIG_SPL_TEXT_BASE 0xff8c2000 -#define CONFIG_SPL_MAX_SIZE 0x30000 - 0x2000 -/* BSS setup */ -#define CONFIG_SPL_BSS_START_ADDR 0xff8e0000 -#define CONFIG_SPL_BSS_MAX_SIZE 0x10000 + +#define CONFIG_SPL_STACK 0x00400000 +#define CONFIG_SPL_TEXT_BASE 0x00000000 +#define CONFIG_SPL_MAX_SIZE 0x10000 +#define CONFIG_SPL_BSS_START_ADDR 0x00400000 +#define CONFIG_SPL_BSS_MAX_SIZE 0x20000 #define CONFIG_SYS_BOOTM_LEN (64 << 20) /* 64M */ @@ -72,6 +72,7 @@ #include #define CONFIG_EXTRA_ENV_SETTINGS \ ENV_MEM_LAYOUT_SETTINGS \ + "fdtfile=" FDTFILE \ "partitions=" PARTS_DEFAULT \ ROCKCHIP_DEVICE_SETTINGS \ BOOTENV diff --git a/include/configs/rock64_rk3328.h b/include/configs/rock64_rk3328.h new file mode 100644 index 00000000000..06963b46d26 --- /dev/null +++ b/include/configs/rock64_rk3328.h @@ -0,0 +1,18 @@ +/* + * (C) Copyright 2017 PINE64 + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __EVB_RK3328_H +#define __EVB_RK3328_H + +#include + +#define CONFIG_SYS_MMC_ENV_DEV 1 + +#define SDRAM_BANK_SIZE (2UL << 30) + +#define CONFIG_CONSOLE_SCROLL_LINES 10 + +#endif diff --git a/include/configs/rockchip-common.h b/include/configs/rockchip-common.h index 5b3fdb5ddb9..1b00ef4d9d8 100644 --- a/include/configs/rockchip-common.h +++ b/include/configs/rockchip-common.h @@ -29,6 +29,12 @@ #define CONFIG_RANDOM_UUID +#ifdef CONFIG_ARM64 +#define FDTFILE "rockchip/" CONFIG_DEFAULT_DEVICE_TREE ".dtb" "\0" +#else +#define FDTFILE CONFIG_DEFAULT_DEVICE_TREE ".dtb" "\0" +#endif + #ifdef CONFIG_ARM64 #define ROOT_UUID "B921B045-1DF0-41C3-AF44-4C6F280D3FAE;\0" #else @@ -74,6 +80,7 @@ */ #define CONFIG_ENV_OFFSET (SZ_4M - SZ_32K) #define CONFIG_ENV_SIZE SZ_32K +#define CONFIG_ENV_SECT_SIZE SZ_4K #define CONFIG_DISPLAY_BOARDINFO_LATE diff --git a/include/configs/rockpro64_rk3399.h b/include/configs/rockpro64_rk3399.h new file mode 100644 index 00000000000..0d6a159f0f4 --- /dev/null +++ b/include/configs/rockpro64_rk3399.h @@ -0,0 +1,34 @@ +/* + * (C) Copyright 2016 Rockchip Electronics Co., Ltd + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __EVB_RK3399_H +#define __EVB_RK3399_H + +#include + +#ifndef CONFIG_SPL_BUILD +#define CONFIG_MMC_SDHCI_SDMA +#endif + +#define CONFIG_SYS_MMC_ENV_DEV 0 + +#define SDRAM_BANK_SIZE (2UL << 30) +#define CONFIG_MISC_INIT_R +#define CONFIG_SERIAL_TAG +#define CONFIG_ENV_OVERWRITE + +#define CONFIG_BMP_16BPP +#define CONFIG_BMP_24BPP +#define CONFIG_BMP_32BPP + +#define ROCKCHIP_DEVICE_SETTINGS \ + "stdout=serial,vidconsole\0" \ + "stderr=serial,vidconsole\0" + +#undef CONFIG_SYS_SPI_U_BOOT_OFFS +#define CONFIG_SYS_SPI_U_BOOT_OFFS 1024 * 512 + +#endif diff --git a/include/dt-bindings/clock/rk3328-cru.h b/include/dt-bindings/clock/rk3328-cru.h index 6d8bf1330ba..068f179498c 100644 --- a/include/dt-bindings/clock/rk3328-cru.h +++ b/include/dt-bindings/clock/rk3328-cru.h @@ -86,6 +86,9 @@ #define SCLK_USB3OTG_SUSPEND 97 #define SCLK_REF_USB3OTG_SRC 98 #define SCLK_MAC2IO_SRC 99 +#define SCLK_MAC2IO 100 +#define SCLK_MAC2PHY 101 +#define SCLK_MAC2IO_EXT 102 /* dclk gates */ #define DCLK_LCDC 180 @@ -199,10 +202,7 @@ #define CLK_NR_CLKS (HCLK_HDCP + 1) -#define SCLK_MAC2IO 0 -#define SCLK_MAC2PHY 1 - -#define CLKGRF_NR_CLKS (SCLK_MAC2PHY + 1) +#define CLKGRF_NR_CLKS (0) /* soft-reset indices */ #define SRST_CORE0_PO 0 diff --git a/include/dwmmc.h b/include/dwmmc.h index 2003f40b600..a9058824e0d 100644 --- a/include/dwmmc.h +++ b/include/dwmmc.h @@ -115,10 +115,6 @@ #define RX_WMARK_SHIFT 16 #define RX_WMARK_MASK (0xfff << RX_WMARK_SHIFT) -/* HCON Register */ -#define DMA_INTERFACE_IDMA (0x0) -#define SDMMC_GET_TRANS_MODE(x) (((x)>>16) & 0x3) - #define DWMCI_IDMAC_OWN (1 << 31) #define DWMCI_IDMAC_CH (1 << 4) #define DWMCI_IDMAC_FS (1 << 3) @@ -150,7 +146,6 @@ * @fifoth_val: Value for FIFOTH register (or 0 to leave unset) * @mmc: Pointer to generic MMC structure for this device * @priv: Private pointer for use by controller - * @stride_pio: Provide the ability of accessing fifo with burst mode */ struct dwmci_host { const char *name; @@ -167,7 +162,6 @@ struct dwmci_host { u32 fifoth_val; struct mmc *mmc; void *priv; - bool stride_pio; void (*clksel)(struct dwmci_host *host); void (*board_init)(struct dwmci_host *host); @@ -186,7 +180,6 @@ struct dwmci_host { * @freq: Frequency the host is trying to achieve */ unsigned int (*get_mmc_clk)(struct dwmci_host *host, uint freq); - int (*execute_tuning)(struct dwmci_host *host, u32 opcode); #ifndef CONFIG_BLK struct mmc_config cfg; #endif diff --git a/include/efi.h b/include/efi.h index 02b78b31b12..87b0b43f20f 100644 --- a/include/efi.h +++ b/include/efi.h @@ -28,6 +28,10 @@ struct efi_device_path; +typedef struct { + u8 b[16]; +} efi_guid_t; + #define EFI_BITS_PER_LONG BITS_PER_LONG /* diff --git a/include/efi_api.h b/include/efi_api.h index ec1b321e8e7..4e27c82129b 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -284,28 +284,92 @@ struct efi_device_path { u8 type; u8 sub_type; u16 length; -}; +} __packed; struct efi_mac_addr { u8 addr[32]; -}; +} __packed; + +#define DEVICE_PATH_TYPE_HARDWARE_DEVICE 0x01 +# define DEVICE_PATH_SUB_TYPE_VENDOR 0x04 + +struct efi_device_path_vendor { + struct efi_device_path dp; + efi_guid_t guid; + u8 vendor_data[]; +} __packed; + +#define DEVICE_PATH_TYPE_ACPI_DEVICE 0x02 +# define DEVICE_PATH_SUB_TYPE_ACPI_DEVICE 0x01 + +#define EFI_PNP_ID(ID) (u32)(((ID) << 16) | 0x41D0) +#define EISA_PNP_ID(ID) EFI_PNP_ID(ID) + +struct efi_device_path_acpi_path { + struct efi_device_path dp; + u32 hid; + u32 uid; +} __packed; #define DEVICE_PATH_TYPE_MESSAGING_DEVICE 0x03 +# define DEVICE_PATH_SUB_TYPE_MSG_USB 0x05 # define DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR 0x0b +# define DEVICE_PATH_SUB_TYPE_MSG_USB_CLASS 0x0f +# define DEVICE_PATH_SUB_TYPE_MSG_SD 0x1a +# define DEVICE_PATH_SUB_TYPE_MSG_MMC 0x1d + +struct efi_device_path_usb { + struct efi_device_path dp; + u8 parent_port_number; + u8 usb_interface; +} __packed; struct efi_device_path_mac_addr { struct efi_device_path dp; struct efi_mac_addr mac; u8 if_type; -}; +} __packed; + +struct efi_device_path_usb_class { + struct efi_device_path dp; + u16 vendor_id; + u16 product_id; + u8 device_class; + u8 device_subclass; + u8 device_protocol; +} __packed; + +struct efi_device_path_sd_mmc_path { + struct efi_device_path dp; + u8 slot_number; +} __packed; #define DEVICE_PATH_TYPE_MEDIA_DEVICE 0x04 +# define DEVICE_PATH_SUB_TYPE_HARD_DRIVE_PATH 0x01 +# define DEVICE_PATH_SUB_TYPE_CDROM_PATH 0x02 # define DEVICE_PATH_SUB_TYPE_FILE_PATH 0x04 +struct efi_device_path_hard_drive_path { + struct efi_device_path dp; + u32 partition_number; + u64 partition_start; + u64 partition_end; + u8 partition_signature[16]; + u8 partmap_type; + u8 signature_type; +} __packed; + +struct efi_device_path_cdrom_path { + struct efi_device_path dp; + u32 boot_entry; + u64 partition_start; + u64 partition_end; +} __packed; + struct efi_device_path_file_path { struct efi_device_path dp; u16 str[32]; -}; +} __packed; #define BLOCK_IO_GUID \ EFI_GUID(0x964e5b21, 0x6459, 0x11d2, \ diff --git a/include/efi_loader.h b/include/efi_loader.h index 1179234f683..27cce2d10a6 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -134,7 +134,7 @@ int efi_disk_register(void); /* Called by bootefi to make GOP (graphical) interface available */ int efi_gop_register(void); /* Called by bootefi to make the network interface available */ -int efi_net_register(void **handle); +int efi_net_register(void); /* Called by bootefi to make SMBIOS tables available */ void efi_smbios_register(void); @@ -191,12 +191,41 @@ uint64_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type, int efi_memory_init(void); /* Adds new or overrides configuration table entry to the system table */ efi_status_t efi_install_configuration_table(const efi_guid_t *guid, void *table); +void efi_setup_loaded_image(struct efi_loaded_image *info, struct efi_object *obj, + struct efi_device_path *device_path, + struct efi_device_path *file_path); #ifdef CONFIG_EFI_LOADER_BOUNCE_BUFFER extern void *efi_bounce_buffer; #define EFI_LOADER_BOUNCE_BUFFER_SIZE (64 * 1024 * 1024) #endif + +struct efi_device_path *efi_dp_next(const struct efi_device_path *dp); +int efi_dp_match(struct efi_device_path *a, struct efi_device_path *b); +struct efi_object *efi_dp_find_obj(struct efi_device_path *dp, + struct efi_device_path **rem); +unsigned efi_dp_size(const struct efi_device_path *dp); +struct efi_device_path *efi_dp_dup(const struct efi_device_path *dp); +struct efi_device_path *efi_dp_append(const struct efi_device_path *dp1, + const struct efi_device_path *dp2); +struct efi_device_path *efi_dp_append_node(const struct efi_device_path *dp, + const struct efi_device_path *node); + + +struct efi_device_path *efi_dp_from_dev(struct udevice *dev); +struct efi_device_path *efi_dp_from_part(struct blk_desc *desc, int part); +struct efi_device_path *efi_dp_from_file(struct blk_desc *desc, int part, + const char *path); +struct efi_device_path *efi_dp_from_eth(void); +void efi_dp_split_file_path(struct efi_device_path *full_path, + struct efi_device_path **device_path, + struct efi_device_path **file_path); + +#define EFI_DP_TYPE(_dp, _type, _subtype) \ + (((_dp)->type == DEVICE_PATH_TYPE_##_type) && \ + ((_dp)->sub_type == DEVICE_PATH_SUB_TYPE_##_subtype)) + /* Convert strings from normal C strings to uEFI strings */ static inline void ascii2unicode(u16 *unicode, const char *ascii) { diff --git a/include/linux/usb/dwc3.h b/include/linux/usb/dwc3.h index c1b23b2f1bd..6261a069fc9 100644 --- a/include/linux/usb/dwc3.h +++ b/include/linux/usb/dwc3.h @@ -205,6 +205,14 @@ struct dwc3 { /* offset: 0xC100 */ #define DWC3_GTXFIFOSIZ_TXFDEF(n) ((n) & 0xffff) #define DWC3_GTXFIFOSIZ_TXFSTADDR(n) ((n) & 0xffff0000) +/* Device Config Register */ +#define DWC3_DCFG_SPEED_MASK (7 << 0) +#define DWC3_DCFG_SUPERSPEED (4 << 0) +#define DWC3_DCFG_HIGHSPEED (0 << 0) +#define DWC3_DCFG_FULLSPEED2 (1 << 0) +#define DWC3_DCFG_LOWSPEED (2 << 0) +#define DWC3_DCFG_FULLSPEED1 (3 << 0) + /* Device Control Register */ #define DWC3_DCTL_RUN_STOP (1 << 31) #define DWC3_DCTL_CSFTRST (1 << 30) diff --git a/include/mmc.h b/include/mmc.h index 492b0434e75..010ebe048c4 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -58,9 +58,6 @@ #define MMC_MODE_8BIT (1 << 3) #define MMC_MODE_SPI (1 << 4) #define MMC_MODE_DDR_52MHz (1 << 5) -#define MMC_MODE_HS200 (1 << 6) -#define MMC_MODE_HS400 (1 << 7) -#define MMC_MODE_HS400ES (1 << 8) #define SD_DATA_4BIT 0x00040000 @@ -85,8 +82,6 @@ #define MMC_CMD_SET_BLOCKLEN 16 #define MMC_CMD_READ_SINGLE_BLOCK 17 #define MMC_CMD_READ_MULTIPLE_BLOCK 18 -#define MMC_SEND_TUNING_BLOCK 19 -#define MMC_SEND_TUNING_BLOCK_HS200 21 #define MMC_CMD_SET_BLOCK_COUNT 23 #define MMC_CMD_WRITE_SINGLE_BLOCK 24 #define MMC_CMD_WRITE_MULTIPLE_BLOCK 25 @@ -138,7 +133,6 @@ #define MMC_STATE_PRG (7 << 9) -#define MMC_VDD_165_195_SHIFT 7 #define MMC_VDD_165_195 0x00000080 /* VDD voltage 1.65 - 1.95 */ #define MMC_VDD_20_21 0x00000100 /* VDD voltage 2.0 ~ 2.1 */ #define MMC_VDD_21_22 0x00000200 /* VDD voltage 2.1 ~ 2.2 */ @@ -188,7 +182,6 @@ #define EXT_CSD_BOOT_BUS_WIDTH 177 #define EXT_CSD_PART_CONF 179 /* R/W */ #define EXT_CSD_BUS_WIDTH 183 /* R/W */ -#define EXT_CSD_STROBE_SUPPORT 184 /* RO */ #define EXT_CSD_HS_TIMING 185 /* R/W */ #define EXT_CSD_REV 192 /* RO */ #define EXT_CSD_CARD_TYPE 196 /* RO */ @@ -208,18 +201,6 @@ #define EXT_CSD_CARD_TYPE_26 (1 << 0) /* Card can run at 26MHz */ #define EXT_CSD_CARD_TYPE_52 (1 << 1) /* Card can run at 52MHz */ -#define EXT_CSD_CARD_TYPE_HS (EXT_CSD_CARD_TYPE_26 | \ - EXT_CSD_CARD_TYPE_52) -#define EXT_CSD_CARD_TYPE_HS200_1_8V BIT(4) /* Card can run at 200MHz */ -#define EXT_CSD_CARD_TYPE_HS200_1_2V BIT(5) /* Card can run at 200MHz */ -#define EXT_CSD_CARD_TYPE_HS200 (EXT_CSD_CARD_TYPE_HS200_1_8V | \ - EXT_CSD_CARD_TYPE_HS200_1_2V) -#define EXT_CSD_CARD_TYPE_HS400_1_8V BIT(6) /* Card can run at 200MHz DDR, 1.8V */ -#define EXT_CSD_CARD_TYPE_HS400_1_2V BIT(7) /* Card can run at 200MHz DDR, 1.2V */ -#define EXT_CSD_CARD_TYPE_HS400 (EXT_CSD_CARD_TYPE_HS400_1_8V | \ - EXT_CSD_CARD_TYPE_HS400_1_2V) -#define EXT_CSD_CARD_TYPE_HS400ES BIT(8) /* Card can run at HS400ES */ - #define EXT_CSD_CARD_TYPE_DDR_1_8V (1 << 2) #define EXT_CSD_CARD_TYPE_DDR_1_2V (1 << 3) #define EXT_CSD_CARD_TYPE_DDR_52 (EXT_CSD_CARD_TYPE_DDR_1_8V \ @@ -231,12 +212,6 @@ #define EXT_CSD_DDR_BUS_WIDTH_4 5 /* Card is in 4 bit DDR mode */ #define EXT_CSD_DDR_BUS_WIDTH_8 6 /* Card is in 8 bit DDR mode */ -#define EXT_CSD_TIMING_BC 0 /* Backwards compatility */ -#define EXT_CSD_TIMING_HS 1 /* High speed */ -#define EXT_CSD_TIMING_HS200 2 /* HS200 */ -#define EXT_CSD_TIMING_HS400 3 /* HS400 */ -#define EXT_CSD_DRV_STR_SHIFT 4 /* Driver Strength shift */ - #define EXT_CSD_BOOT_ACK_ENABLE (1 << 6) #define EXT_CSD_BOOT_PARTITION_ENABLE (1 << 3) #define EXT_CSD_PARTITION_ACCESS_ENABLE (1 << 0) @@ -299,49 +274,6 @@ #define MMC_NUM_BOOT_PARTITION 2 #define MMC_PART_RPMB 3 /* RPMB partition number */ -/* Sizes of RPMB data frame */ -#define RPMB_SZ_STUFF 196 -#define RPMB_SZ_MAC 32 -#define RPMB_SZ_DATA 256 -#define RPMB_SZ_NONCE 16 - -/* Structure of RPMB data frame. */ -struct s_rpmb { - unsigned char stuff[RPMB_SZ_STUFF]; - unsigned char mac[RPMB_SZ_MAC]; - unsigned char data[RPMB_SZ_DATA]; - unsigned char nonce[RPMB_SZ_NONCE]; - unsigned int write_counter; - unsigned short address; - unsigned short block_count; - unsigned short result; - unsigned short request; -} __packed; - -struct s_rpmb_verify { - unsigned char data[RPMB_SZ_DATA]; - unsigned char nonce[RPMB_SZ_NONCE]; - unsigned int write_counter; - unsigned short address; - unsigned short block_count; - unsigned short result; - unsigned short request; -} __packed; - -int init_rpmb(void); -int finish_rpmb(void); -int do_readcounter(struct s_rpmb *requestpackets); -int do_programkey(struct s_rpmb *requestpackets); -int do_authenticatedread(struct s_rpmb *requestpackets, uint16_t block_count); -int do_authenticatedwrite(struct s_rpmb *requestpackets); -struct mmc *do_returnmmc(void); - -int read_counter(struct mmc *mmc, struct s_rpmb *requestpackets); -int program_key(struct mmc *mmc, struct s_rpmb *requestpackets); -int authenticated_read - (struct mmc *mmc, struct s_rpmb *requestpackets, uint16_t block_count); -int authenticated_write(struct mmc *mmc, struct s_rpmb *requestpackets); - /* Driver model support */ /** @@ -406,14 +338,6 @@ struct dm_mmc_ops { int (*send_cmd)(struct udevice *dev, struct mmc_cmd *cmd, struct mmc_data *data); - /** - * card_busy() - Query the card device status - * - * @dev: Device to update - * @return true if card device is busy - */ - bool (*card_busy)(struct udevice *dev); - /** * set_ios() - Set the I/O speed/width for an MMC device * @@ -437,17 +361,6 @@ struct dm_mmc_ops { * @return 0 if write-enabled, 1 if write-protected, -ve on error */ int (*get_wp)(struct udevice *dev); - - /** - * execute_tuning() - Find the optimal sampling point of a data - * input signals. - * - * @dev: Device to check - * @opcode: The tuning command opcode value is different - * for SD and eMMC cards - * @return 0 if write-enabled, 1 if write-protected, -ve on error - */ - int (*execute_tuning)(struct udevice *dev, u32 opcode); }; #define mmc_get_ops(dev) ((struct dm_mmc_ops *)(dev)->driver->ops) @@ -459,22 +372,18 @@ int dm_mmc_get_cd(struct udevice *dev); int dm_mmc_get_wp(struct udevice *dev); /* Transition functions for compatibility */ -bool mmc_card_busy(struct mmc *mmc); -bool mmc_can_card_busy(struct mmc *mmc); int mmc_set_ios(struct mmc *mmc); int mmc_getcd(struct mmc *mmc); int mmc_getwp(struct mmc *mmc); #else struct mmc_ops { - bool (*card_busy)(struct mmc *mmc); int (*send_cmd)(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data); int (*set_ios)(struct mmc *mmc); int (*init)(struct mmc *mmc); int (*getcd)(struct mmc *mmc); int (*getwp)(struct mmc *mmc); - int (*execute_tuning)(struct udevice *dev, u32 opcode); }; #endif @@ -513,33 +422,7 @@ struct mmc { uint has_init; int high_capacity; uint bus_width; - -#define MMC_BUS_WIDTH_1BIT 1 -#define MMC_BUS_WIDTH_4BIT 4 -#define MMC_BUS_WIDTH_8BIT 8 - - uint timing; - -#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 MMC_TIMING_MMC_HS400ES 11 - uint clock; - -#define MMC_HIGH_26_MAX_DTR 26000000 -#define MMC_HIGH_52_MAX_DTR 52000000 -#define MMC_HIGH_DDR_MAX_DTR 52000000 -#define MMC_HS200_MAX_DTR 200000000 - uint card_caps; uint ocr; uint dsr; @@ -552,6 +435,7 @@ struct mmc { u8 part_attr; u8 wr_rel_set; u8 part_config; + uint tran_speed; uint read_bl_len; uint write_bl_len; uint erase_grp_size; /* in 512-byte sectors */ @@ -570,6 +454,7 @@ struct mmc { char op_cond_pending; /* 1 if we are waiting on an op_cond command */ char init_in_progress; /* 1 if we have done mmc_start_init() */ char preinit; /* start init as early as possible */ + int ddr_mode; #if CONFIG_IS_ENABLED(DM_MMC) struct udevice *dev; /* Device for this MMC controller */ #endif @@ -596,42 +481,6 @@ enum mmc_hwpart_conf_mode { MMC_HWPART_CONF_COMPLETE, }; -static inline bool mmc_card_hs(struct mmc *mmc) -{ - return (mmc->timing == MMC_TIMING_MMC_HS) || - (mmc->timing == MMC_TIMING_SD_HS); -} - -static inline bool mmc_card_ddr(struct mmc *mmc) -{ - return (mmc->timing == MMC_TIMING_UHS_DDR50) || - (mmc->timing == MMC_TIMING_MMC_DDR52) || - (mmc->timing == MMC_TIMING_MMC_HS400) || - (mmc->timing == MMC_TIMING_MMC_HS400ES); -} - -static inline bool mmc_card_hs200(struct mmc *mmc) -{ - return mmc->timing == MMC_TIMING_MMC_HS200; -} - -static inline bool mmc_card_ddr52(struct mmc *mmc) -{ - return mmc->timing == MMC_TIMING_MMC_DDR52; -} - -static inline bool mmc_card_hs400(struct mmc *mmc) -{ - return mmc->timing == MMC_TIMING_MMC_HS400; -} - -static inline bool mmc_card_hs400es(struct mmc *mmc) -{ - return mmc->timing == MMC_TIMING_MMC_HS400ES; -} - -int mmc_send_tuning(struct mmc *mmc, u32 opcode); - struct mmc *mmc_create(const struct mmc_config *cfg, void *priv); /** @@ -754,4 +603,3 @@ int mmc_get_env_dev(void); struct blk_desc *mmc_get_blk_desc(struct mmc *mmc); #endif /* _MMC_H_ */ - diff --git a/include/part.h b/include/part.h index 5739a2d37b5..7bf89f911d8 100644 --- a/include/part.h +++ b/include/part.h @@ -272,8 +272,9 @@ struct part_driver { #define U_BOOT_PART_TYPE(__name) \ ll_entry_declare(struct part_driver, __name, part_driver) -#if CONFIG_IS_ENABLED(EFI_PARTITION) #include + +#if CONFIG_IS_ENABLED(EFI_PARTITION) /* disk/part_efi.c */ /** * write_gpt_table() - Write the GUID Partition Table to disk diff --git a/include/part_efi.h b/include/part_efi.h index 317c044795c..31e6bc6e140 100644 --- a/include/part_efi.h +++ b/include/part_efi.h @@ -58,10 +58,6 @@ /* linux/include/efi.h */ typedef u16 efi_char16_t; -typedef struct { - u8 b[16]; -} efi_guid_t; - /* based on linux/include/genhd.h */ struct partition { u8 boot_ind; /* 0x80 - active */ diff --git a/include/power/rk8xx_pmic.h b/include/power/rk8xx_pmic.h index 699fd87dba2..88abcb05a5f 100644 --- a/include/power/rk8xx_pmic.h +++ b/include/power/rk8xx_pmic.h @@ -88,6 +88,8 @@ enum { REG_BOOST_LDO9_SLP_VSEL, REG_BOOST_CTRL, + REG_OUT_CTRL = 0x52, + /* Not sure what this does */ REG_DCDC_ILMAX = 0x90, REG_CHRG_COMP = 0x9a, diff --git a/include/sdhci.h b/include/sdhci.h index 354f1e70997..fcc5856c5b1 100644 --- a/include/sdhci.h +++ b/include/sdhci.h @@ -280,8 +280,6 @@ struct sdhci_host { struct mmc_config cfg; }; -int sdhci_set_clock(struct sdhci_host *host, unsigned int clock); - #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS static inline void sdhci_writel(struct sdhci_host *host, u32 val, int reg) diff --git a/include/spl.h b/include/spl.h index d21a3d21cb9..ce1ae3ae8a6 100644 --- a/include/spl.h +++ b/include/spl.h @@ -282,6 +282,15 @@ void spl_bl31_entry(void *entry_addr); */ void spl_optee_entry(void *arg0, void *arg1, void *arg2, void *arg3); +/** + * spl_optee_entry - entry function for optee + * entry arg0, pagestore + * entry arg1, (ARMv7 standard bootarg #1) + * entry arg2, device tree address, (ARMv7 standard bootarg #2) + * entry arg3, non-secure entry address (ARMv7 bootarg #0) + */ +void spl_optee_entry(void *arg0, void *arg1, void *arg2, void *arg3); + /** * board_return_to_bootrom - allow for boards to continue with the boot ROM * diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index 30bf343a365..f35e5ce8a8f 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -15,7 +15,7 @@ always := $(efiprogs-y) obj-$(CONFIG_CMD_BOOTEFI_HELLO) += helloworld_efi.o obj-y += efi_image_loader.o efi_boottime.o efi_runtime.o efi_console.o -obj-y += efi_memory.o efi_device_path_to_text.o +obj-y += efi_memory.o efi_device_path_to_text.o efi_device_path.o obj-$(CONFIG_LCD) += efi_gop.o obj-$(CONFIG_DM_VIDEO) += efi_gop.o obj-$(CONFIG_PARTITIONS) += efi_disk.o diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 43f32385fae..837e61d8fe6 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -665,8 +665,17 @@ static efi_status_t EFIAPI efi_locate_device_path(efi_guid_t *protocol, struct efi_device_path **device_path, efi_handle_t *device) { - EFI_ENTRY("%p, %p, %p", protocol, device_path, device); - return EFI_EXIT(EFI_NOT_FOUND); + struct efi_object *efiobj; + + EFI_ENTRY("%pUl, %p, %p", protocol, device_path, device); + + efiobj = efi_dp_find_obj(*device_path, device_path); + if (!efiobj) + return EFI_EXIT(EFI_NOT_FOUND); + + *device = efiobj->handle; + + return EFI_EXIT(EFI_SUCCESS); } /* Collapses configuration table entries, removing index i */ @@ -717,6 +726,42 @@ static efi_status_t EFIAPI efi_install_configuration_table_ext(efi_guid_t *guid, return EFI_EXIT(efi_install_configuration_table(guid, table)); } +/* Initialize a loaded_image_info + loaded_image_info object with correct + * protocols, boot-device, etc. + */ +void efi_setup_loaded_image(struct efi_loaded_image *info, struct efi_object *obj, + struct efi_device_path *device_path, + struct efi_device_path *file_path) +{ + obj->handle = info; + + /* + * When asking for the device path interface, return + * bootefi_device_path + */ + obj->protocols[0].guid = &efi_guid_device_path; + obj->protocols[0].protocol_interface = device_path; + + /* + * When asking for the loaded_image interface, just + * return handle which points to loaded_image_info + */ + obj->protocols[1].guid = &efi_guid_loaded_image; + obj->protocols[1].protocol_interface = info; + + obj->protocols[2].guid = &efi_guid_console_control; + obj->protocols[2].protocol_interface = (void *)&efi_console_control; + + obj->protocols[3].guid = &efi_guid_device_path_to_text_protocol; + obj->protocols[3].protocol_interface = + (void *)&efi_device_path_to_text; + + info->file_path = file_path; + info->device_handle = efi_dp_find_obj(device_path, NULL); + + list_add_tail(&obj->link, &efi_obj_list); +} + static efi_status_t EFIAPI efi_load_image(bool boot_policy, efi_handle_t parent_image, struct efi_device_path *file_path, diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c new file mode 100644 index 00000000000..5d5c3b34646 --- /dev/null +++ b/lib/efi_loader/efi_device_path.c @@ -0,0 +1,563 @@ +/* + * EFI device path from u-boot device-model mapping + * + * (C) Copyright 2017 Rob Clark + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* template END node: */ +static const struct efi_device_path END = { + .type = DEVICE_PATH_TYPE_END, + .sub_type = DEVICE_PATH_SUB_TYPE_END, + .length = sizeof(END), +}; + +#define U_BOOT_GUID \ + EFI_GUID(0xe61d73b9, 0xa384, 0x4acc, \ + 0xae, 0xab, 0x82, 0xe8, 0x28, 0xf3, 0x62, 0x8b) + +/* template ROOT node: */ +static const struct efi_device_path_vendor ROOT = { + .dp = { + .type = DEVICE_PATH_TYPE_HARDWARE_DEVICE, + .sub_type = DEVICE_PATH_SUB_TYPE_VENDOR, + .length = sizeof(ROOT), + }, + .guid = U_BOOT_GUID, +}; + +static void *dp_alloc(size_t sz) +{ + void *buf; + + if (efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES, sz, &buf) != EFI_SUCCESS) + return NULL; + + return buf; +} + +/* + * Iterate to next block in device-path, terminating (returning NULL) + * at /End* node. + */ +struct efi_device_path *efi_dp_next(const struct efi_device_path *dp) +{ + if (dp == NULL) + return NULL; + if (dp->type == DEVICE_PATH_TYPE_END) + return NULL; + dp = ((void *)dp) + dp->length; + if (dp->type == DEVICE_PATH_TYPE_END) + return NULL; + return (struct efi_device_path *)dp; +} + +/* + * Compare two device-paths, stopping when the shorter of the two hits + * an End* node. This is useful to, for example, compare a device-path + * representing a device with one representing a file on the device, or + * a device with a parent device. + */ +int efi_dp_match(struct efi_device_path *a, struct efi_device_path *b) +{ + while (1) { + int ret; + + ret = memcmp(&a->length, &b->length, sizeof(a->length)); + if (ret) + return ret; + + ret = memcmp(a, b, a->length); + if (ret) + return ret; + + a = efi_dp_next(a); + b = efi_dp_next(b); + + if (!a || !b) + return 0; + } +} + + +/* + * See UEFI spec (section 3.1.2, about short-form device-paths.. + * tl;dr: we can have a device-path that starts with a USB WWID + * or USB Class node, and a few other cases which don't encode + * the full device path with bus hierarchy: + * + * - MESSAGING:USB_WWID + * - MESSAGING:USB_CLASS + * - MEDIA:FILE_PATH + * - MEDIA:HARD_DRIVE + * - MESSAGING:URI + */ +static struct efi_device_path *shorten_path(struct efi_device_path *dp) +{ + while (dp) { + /* + * TODO: Add MESSAGING:USB_WWID and MESSAGING:URI.. + * in practice fallback.efi just uses MEDIA:HARD_DRIVE + * so not sure when we would see these other cases. + */ + if (EFI_DP_TYPE(dp, MESSAGING_DEVICE, MSG_USB_CLASS) || + EFI_DP_TYPE(dp, MEDIA_DEVICE, HARD_DRIVE_PATH) || + EFI_DP_TYPE(dp, MEDIA_DEVICE, FILE_PATH)) + return dp; + + dp = efi_dp_next(dp); + } + + return dp; +} + +static struct efi_object *find_obj(struct efi_device_path *dp, bool short_path, + struct efi_device_path **rem) +{ + struct efi_object *efiobj; + + list_for_each_entry(efiobj, &efi_obj_list, link) { + int i; + + for (i = 0; i < ARRAY_SIZE(efiobj->protocols); i++) { + struct efi_handler *handler = &efiobj->protocols[i]; + struct efi_device_path *obj_dp; + + if (!handler->guid) + break; + + if (guidcmp(handler->guid, &efi_guid_device_path)) + continue; + + obj_dp = handler->protocol_interface; + + do { + if (efi_dp_match(dp, obj_dp) == 0) { + if (rem) { + *rem = ((void *)dp) + + efi_dp_size(obj_dp); + } + return efiobj; + } + + obj_dp = shorten_path(efi_dp_next(obj_dp)); + } while (short_path && obj_dp); + } + } + + return NULL; +} + + +/* + * Find an efiobj from device-path, if 'rem' is not NULL, returns the + * remaining part of the device path after the matched object. + */ +struct efi_object *efi_dp_find_obj(struct efi_device_path *dp, + struct efi_device_path **rem) +{ + struct efi_object *efiobj; + + efiobj = find_obj(dp, false, rem); + + if (!efiobj) + efiobj = find_obj(dp, true, rem); + + return efiobj; +} + +/* return size not including End node: */ +unsigned efi_dp_size(const struct efi_device_path *dp) +{ + unsigned sz = 0; + + while (dp) { + sz += dp->length; + dp = efi_dp_next(dp); + } + + return sz; +} + +struct efi_device_path *efi_dp_dup(const struct efi_device_path *dp) +{ + struct efi_device_path *ndp; + unsigned sz = efi_dp_size(dp) + sizeof(END); + + if (!dp) + return NULL; + + ndp = dp_alloc(sz); + memcpy(ndp, dp, sz); + + return ndp; +} + +struct efi_device_path *efi_dp_append(const struct efi_device_path *dp1, + const struct efi_device_path *dp2) +{ + struct efi_device_path *ret; + + if (!dp1) { + ret = efi_dp_dup(dp2); + } else if (!dp2) { + ret = efi_dp_dup(dp1); + } else { + /* both dp1 and dp2 are non-null */ + unsigned sz1 = efi_dp_size(dp1); + unsigned sz2 = efi_dp_size(dp2); + void *p = dp_alloc(sz1 + sz2 + sizeof(END)); + memcpy(p, dp1, sz1); + memcpy(p + sz1, dp2, sz2); + memcpy(p + sz1 + sz2, &END, sizeof(END)); + ret = p; + } + + return ret; +} + +struct efi_device_path *efi_dp_append_node(const struct efi_device_path *dp, + const struct efi_device_path *node) +{ + struct efi_device_path *ret; + + if (!node && !dp) { + ret = efi_dp_dup(&END); + } else if (!node) { + ret = efi_dp_dup(dp); + } else if (!dp) { + unsigned sz = node->length; + void *p = dp_alloc(sz + sizeof(END)); + memcpy(p, node, sz); + memcpy(p + sz, &END, sizeof(END)); + ret = p; + } else { + /* both dp and node are non-null */ + unsigned sz = efi_dp_size(dp); + void *p = dp_alloc(sz + node->length + sizeof(END)); + memcpy(p, dp, sz); + memcpy(p + sz, node, node->length); + memcpy(p + sz + node->length, &END, sizeof(END)); + ret = p; + } + + return ret; +} + +#ifdef CONFIG_DM +/* size of device-path not including END node for device and all parents + * up to the root device. + */ +static unsigned dp_size(struct udevice *dev) +{ + if (!dev || !dev->driver) + return sizeof(ROOT); + + switch (dev->driver->id) { + case UCLASS_ROOT: + case UCLASS_SIMPLE_BUS: + /* stop traversing parents at this point: */ + return sizeof(ROOT); + case UCLASS_MMC: + return dp_size(dev->parent) + + sizeof(struct efi_device_path_sd_mmc_path); + case UCLASS_MASS_STORAGE: + case UCLASS_USB_HUB: + return dp_size(dev->parent) + + sizeof(struct efi_device_path_usb_class); + default: + /* just skip over unknown classes: */ + return dp_size(dev->parent); + } +} + +static void *dp_fill(void *buf, struct udevice *dev) +{ + if (!dev || !dev->driver) + return buf; + + switch (dev->driver->id) { + case UCLASS_ROOT: + case UCLASS_SIMPLE_BUS: { + /* stop traversing parents at this point: */ + struct efi_device_path_vendor *vdp = buf; + *vdp = ROOT; + return &vdp[1]; + } +#if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC) + case UCLASS_MMC: { + struct efi_device_path_sd_mmc_path *sddp = + dp_fill(buf, dev->parent); + struct mmc *mmc = mmc_get_mmc_dev(dev); + struct blk_desc *desc = mmc_get_blk_desc(mmc); + + sddp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE; + sddp->dp.sub_type = (desc->if_type == IF_TYPE_MMC) ? + DEVICE_PATH_SUB_TYPE_MSG_MMC : + DEVICE_PATH_SUB_TYPE_MSG_SD; + sddp->dp.length = sizeof(*sddp); + sddp->slot_number = dev->seq; + + return &sddp[1]; + } +#endif + case UCLASS_MASS_STORAGE: + case UCLASS_USB_HUB: { + struct efi_device_path_usb_class *udp = + dp_fill(buf, dev->parent); + struct usb_device *udev = dev_get_parent_priv(dev); + struct usb_device_descriptor *desc = &udev->descriptor; + + udp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE; + udp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_USB_CLASS; + udp->dp.length = sizeof(*udp); + udp->vendor_id = desc->idVendor; + udp->product_id = desc->idProduct; + udp->device_class = desc->bDeviceClass; + udp->device_subclass = desc->bDeviceSubClass; + udp->device_protocol = desc->bDeviceProtocol; + + return &udp[1]; + } + default: + debug("unhandled device class: %s (%u)\n", + dev->name, dev->driver->id); + return dp_fill(buf, dev->parent); + } +} + +/* Construct a device-path from a device: */ +struct efi_device_path *efi_dp_from_dev(struct udevice *dev) +{ + void *buf, *start; + + start = buf = dp_alloc(dp_size(dev) + sizeof(END)); + buf = dp_fill(buf, dev); + *((struct efi_device_path *)buf) = END; + + return start; +} +#endif + +static unsigned dp_part_size(struct blk_desc *desc, int part) +{ + unsigned dpsize; + +#ifdef CONFIG_BLK + dpsize = dp_size(desc->bdev->parent); +#else + dpsize = sizeof(ROOT) + sizeof(struct efi_device_path_usb); +#endif + + if (part == 0) /* the actual disk, not a partition */ + return dpsize; + + if (desc->part_type == PART_TYPE_ISO) + dpsize += sizeof(struct efi_device_path_cdrom_path); + else + dpsize += sizeof(struct efi_device_path_hard_drive_path); + + return dpsize; +} + +static void *dp_part_fill(void *buf, struct blk_desc *desc, int part) +{ + disk_partition_t info; + +#ifdef CONFIG_BLK + buf = dp_fill(buf, desc->bdev->parent); +#else + /* + * We *could* make a more accurate path, by looking at if_type + * and handling all the different cases like we do for non- + * legacy (ie CONFIG_BLK=y) case. But most important thing + * is just to have a unique device-path for if_type+devnum. + * So map things to a fictional USB device: + */ + struct efi_device_path_usb *udp; + + memcpy(buf, &ROOT, sizeof(ROOT)); + buf += sizeof(ROOT); + + udp = buf; + udp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE; + udp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_USB; + udp->dp.length = sizeof(*udp); + udp->parent_port_number = desc->if_type; + udp->usb_interface = desc->devnum; + buf = &udp[1]; +#endif + + if (part == 0) /* the actual disk, not a partition */ + return buf; + + part_get_info(desc, part, &info); + + if (desc->part_type == PART_TYPE_ISO) { + struct efi_device_path_cdrom_path *cddp = buf; + + cddp->boot_entry = part - 1; + cddp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE; + cddp->dp.sub_type = DEVICE_PATH_SUB_TYPE_CDROM_PATH; + cddp->dp.length = sizeof(*cddp); + cddp->partition_start = info.start; + cddp->partition_end = info.size; + + buf = &cddp[1]; + } else { + struct efi_device_path_hard_drive_path *hddp = buf; + + hddp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE; + hddp->dp.sub_type = DEVICE_PATH_SUB_TYPE_HARD_DRIVE_PATH; + hddp->dp.length = sizeof(*hddp); + hddp->partition_number = part - 1; + hddp->partition_start = info.start; + hddp->partition_end = info.size; + if (desc->part_type == PART_TYPE_EFI) + hddp->partmap_type = 2; + else + hddp->partmap_type = 1; + hddp->signature_type = desc->sig_type; + if (hddp->signature_type != 0) + memcpy(hddp->partition_signature, &desc->guid_sig, + sizeof(hddp->partition_signature)); + + buf = &hddp[1]; + } + + return buf; +} + + +/* Construct a device-path from a partition on a blk device: */ +struct efi_device_path *efi_dp_from_part(struct blk_desc *desc, int part) +{ + void *buf, *start; + + start = buf = dp_alloc(dp_part_size(desc, part) + sizeof(END)); + + buf = dp_part_fill(buf, desc, part); + + *((struct efi_device_path *)buf) = END; + + return start; +} + +/* convert path to an UEFI style path (ie. DOS style backslashes and utf16) */ +static void path_to_uefi(u16 *uefi, const char *path) +{ + while (*path) { + char c = *(path++); + if (c == '/') + c = '\\'; + *(uefi++) = c; + } + *uefi = '\0'; +} + +/* + * If desc is NULL, this creates a path with only the file component, + * otherwise it creates a full path with both device and file components + */ +struct efi_device_path *efi_dp_from_file(struct blk_desc *desc, int part, + const char *path) +{ + struct efi_device_path_file_path *fp; + void *buf, *start; + unsigned dpsize = 0, fpsize; + + if (desc) + dpsize = dp_part_size(desc, part); + + fpsize = sizeof(struct efi_device_path) + 2 * (strlen(path) + 1); + dpsize += fpsize; + + start = buf = dp_alloc(dpsize + sizeof(END)); + + if (desc) + buf = dp_part_fill(buf, desc, part); + + /* add file-path: */ + fp = buf; + fp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE; + fp->dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH; + fp->dp.length = fpsize; + path_to_uefi(fp->str, path); + buf += fpsize; + + *((struct efi_device_path *)buf) = END; + + return start; +} + +#ifdef CONFIG_NET +struct efi_device_path *efi_dp_from_eth(void) +{ + struct efi_device_path_mac_addr *ndp; + void *buf, *start; + unsigned dpsize = 0; + + assert(eth_get_dev()); + +#ifdef CONFIG_DM_ETH + dpsize += dp_size(eth_get_dev()); +#else + dpsize += sizeof(ROOT); +#endif + dpsize += sizeof(*ndp); + + start = buf = dp_alloc(dpsize + sizeof(END)); + +#ifdef CONFIG_DM_ETH + buf = dp_fill(buf, eth_get_dev()); +#else + memcpy(buf, &ROOT, sizeof(ROOT)); + buf += sizeof(ROOT); +#endif + + ndp = buf; + ndp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE; + ndp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR; + ndp->dp.length = sizeof(*ndp); + memcpy(ndp->mac.addr, eth_get_ethaddr(), ARP_HLEN); + buf = &ndp[1]; + + *((struct efi_device_path *)buf) = END; + + return start; +} +#endif + +/* + * Helper to split a full device path (containing both device and file + * parts) into it's constituent parts. + */ +void efi_dp_split_file_path(struct efi_device_path *full_path, + struct efi_device_path **device_path, + struct efi_device_path **file_path) +{ + struct efi_device_path *p, *dp, *fp; + + dp = efi_dp_dup(full_path); + p = dp; + while (!EFI_DP_TYPE(p, MEDIA_DEVICE, FILE_PATH)) + p = efi_dp_next(p); + fp = efi_dp_dup(p); + + p->type = DEVICE_PATH_TYPE_END; + p->sub_type = DEVICE_PATH_SUB_TYPE_END; + p->length = sizeof(*p); + + *device_path = dp; + *file_path = fp; +} diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index ed06485e334..4e3de020a05 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -28,11 +28,13 @@ struct efi_disk_obj { /* EFI Interface Media descriptor struct, referenced by ops */ struct efi_block_io_media media; /* EFI device path to this block device */ - struct efi_device_path_file_path *dp; + struct efi_device_path *dp; + /* partition # */ + unsigned int part; /* Offset into disk for simple partitions */ lbaint_t offset; /* Internal block device */ - const struct blk_desc *desc; + struct blk_desc *desc; }; static efi_status_t EFIAPI efi_disk_reset(struct efi_block_io *this, @@ -172,26 +174,26 @@ static const struct efi_block_io block_io_disk_template = { static void efi_disk_add_dev(const char *name, const char *if_typename, - const struct blk_desc *desc, + struct blk_desc *desc, int dev_index, - lbaint_t offset) + lbaint_t offset, + unsigned int part) { struct efi_disk_obj *diskobj; - struct efi_device_path_file_path *dp; - int objlen = sizeof(*diskobj) + (sizeof(*dp) * 2); /* Don't add empty devices */ if (!desc->lba) return; - diskobj = calloc(1, objlen); + diskobj = calloc(1, sizeof(*diskobj)); /* Fill in object data */ - dp = (void *)&diskobj[1]; + diskobj->dp = efi_dp_from_part(desc, part); + diskobj->part = part; diskobj->parent.protocols[0].guid = &efi_block_io_guid; diskobj->parent.protocols[0].protocol_interface = &diskobj->ops; diskobj->parent.protocols[1].guid = &efi_guid_device_path; - diskobj->parent.protocols[1].protocol_interface = dp; + diskobj->parent.protocols[1].protocol_interface = diskobj->dp; diskobj->parent.handle = diskobj; diskobj->ops = block_io_disk_template; diskobj->ifname = if_typename; @@ -207,17 +209,6 @@ static void efi_disk_add_dev(const char *name, diskobj->media.last_block = desc->lba - offset; diskobj->ops.media = &diskobj->media; - /* Fill in device path */ - diskobj->dp = dp; - dp[0].dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE; - dp[0].dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH; - dp[0].dp.length = sizeof(*dp); - ascii2unicode(dp[0].str, name); - - dp[1].dp.type = DEVICE_PATH_TYPE_END; - dp[1].dp.sub_type = DEVICE_PATH_SUB_TYPE_END; - dp[1].dp.length = sizeof(*dp); - /* Hook up to the device list */ list_add_tail(&diskobj->parent.link, &efi_obj_list); } @@ -236,14 +227,18 @@ static int efi_disk_create_eltorito(struct blk_desc *desc, if (desc->part_type != PART_TYPE_ISO) return 0; + /* and devices for each partition: */ while (!part_get_info(desc, part, &info)) { snprintf(devname, sizeof(devname), "%s:%d", pdevname, part); efi_disk_add_dev(devname, if_typename, desc, diskid, - info.start); + info.start, part); part++; disks++; } + + /* ... and add block device: */ + efi_disk_add_dev(devname, if_typename, desc, diskid, 0, 0); #endif return disks; @@ -271,9 +266,22 @@ int efi_disk_register(void) uclass_next_device_check(&dev)) { struct blk_desc *desc = dev_get_uclass_platdata(dev); const char *if_typename = dev->driver->name; + disk_partition_t info; + int part = 1; printf("Scanning disk %s...\n", dev->name); - efi_disk_add_dev(dev->name, if_typename, desc, desc->devnum, 0); + + /* add devices for each partition: */ + while (!part_get_info(desc, part, &info)) { + efi_disk_add_dev(dev->name, if_typename, desc, + desc->devnum, 0, part); + part++; + } + + /* ... and add block device: */ + efi_disk_add_dev(dev->name, if_typename, desc, + desc->devnum, 0, 0); + disks++; /* @@ -309,7 +317,7 @@ int efi_disk_register(void) snprintf(devname, sizeof(devname), "%s%d", if_typename, i); - efi_disk_add_dev(devname, if_typename, desc, i, 0); + efi_disk_add_dev(devname, if_typename, desc, i, 0, 0); disks++; /* diff --git a/lib/efi_loader/efi_net.c b/lib/efi_loader/efi_net.c index 0b949d86e8d..91f1e4a69e1 100644 --- a/lib/efi_loader/efi_net.c +++ b/lib/efi_loader/efi_net.c @@ -26,9 +26,6 @@ struct efi_net_obj { /* EFI Interface callback struct for network */ struct efi_simple_network net; struct efi_simple_network_mode net_mode; - /* Device path to the network adapter */ - struct efi_device_path_mac_addr dp_mac; - struct efi_device_path_file_path dp_end; /* PXE struct to transmit dhcp data */ struct efi_pxe pxe; struct efi_pxe_mode pxe_mode; @@ -210,19 +207,9 @@ void efi_net_set_dhcp_ack(void *pkt, int len) } /* This gets called from do_bootefi_exec(). */ -int efi_net_register(void **handle) +int efi_net_register(void) { struct efi_net_obj *netobj; - struct efi_device_path_mac_addr dp_net = { - .dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE, - .dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR, - .dp.length = sizeof(dp_net), - }; - struct efi_device_path_file_path dp_end = { - .dp.type = DEVICE_PATH_TYPE_END, - .dp.sub_type = DEVICE_PATH_SUB_TYPE_END, - .dp.length = sizeof(dp_end), - }; if (!eth_get_dev()) { /* No eth device active, don't expose any */ @@ -236,7 +223,8 @@ int efi_net_register(void **handle) netobj->parent.protocols[0].guid = &efi_net_guid; netobj->parent.protocols[0].protocol_interface = &netobj->net; netobj->parent.protocols[1].guid = &efi_guid_device_path; - netobj->parent.protocols[1].protocol_interface = &netobj->dp_mac; + netobj->parent.protocols[1].protocol_interface = + efi_dp_from_eth(); netobj->parent.protocols[2].guid = &efi_pxe_guid; netobj->parent.protocols[2].protocol_interface = &netobj->pxe; netobj->parent.handle = &netobj->net; @@ -255,9 +243,6 @@ int efi_net_register(void **handle) netobj->net.receive = efi_net_receive; netobj->net.mode = &netobj->net_mode; netobj->net_mode.state = EFI_NETWORK_STARTED; - netobj->dp_mac = dp_net; - netobj->dp_end = dp_end; - memcpy(netobj->dp_mac.mac.addr, eth_get_ethaddr(), 6); memcpy(netobj->net_mode.current_address.mac_addr, eth_get_ethaddr(), 6); netobj->net_mode.max_packet_size = PKTSIZE; @@ -268,8 +253,5 @@ int efi_net_register(void **handle) /* Hook net up to the device list */ list_add_tail(&netobj->parent.link, &efi_obj_list); - if (handle) - *handle = &netobj->net; - return 0; }