diff options
72 files changed, 4406 insertions, 308 deletions
@@ -552,7 +552,7 @@ config BOARD_SIZE_LIMIT Maximum size of the U-Boot image. When defined, the build system checks that the actual size does not exceed it. This does not include SPL nor TPL, on platforms that use that functionality, they - have a separate option to restict size. + have separate options to restrict size. config SYS_CUSTOM_LDSCRIPT bool "Use a custom location for the U-Boot linker script" @@ -1574,7 +1574,6 @@ u-boot-nodtb.bin: u-boot FORCE $(BOARD_SIZE_CHECK) u-boot.ldr: u-boot - $(CREATE_LDR_ENV) $(LDR) -T $(CONFIG_LDR_CPU) -c $@ $< $(LDR_FLAGS) $(BOARD_SIZE_CHECK) diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index 0dc7e190eb9..e212ed40b78 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -92,6 +92,8 @@ dtb-$(CONFIG_ARCH_TEGRA) += \ tegra20-motorola-olympus.dtb \ tegra20-paz00.dtb \ tegra20-plutux.dtb \ + tegra20-samsung-bose.dtb \ + tegra20-samsung-n1.dtb \ tegra20-seaboard.dtb \ tegra20-tec.dtb \ tegra20-trimslice.dtb \ @@ -117,6 +119,7 @@ dtb-$(CONFIG_ARCH_TEGRA) += \ tegra30-lg-p895.dtb \ tegra30-microsoft-surface-rt.dtb \ tegra30-ouya.dtb \ + tegra30-pegatron-chagall.dtb \ tegra30-tec-ng.dtb \ tegra30-wexler-qc750.dtb \ tegra114-asus-tf701t.dtb \ diff --git a/arch/arm/dts/tegra20-acer-a500-picasso.dts b/arch/arm/dts/tegra20-acer-a500-picasso.dts index 0c301483180..4afde766330 100644 --- a/arch/arm/dts/tegra20-acer-a500-picasso.dts +++ b/arch/arm/dts/tegra20-acer-a500-picasso.dts @@ -40,6 +40,10 @@ }; }; + bsev@6001b000 { + status = "okay"; + }; + pinmux@70000014 { pinctrl-names = "default"; pinctrl-0 = <&state_default>; diff --git a/arch/arm/dts/tegra20-asus-transformer.dtsi b/arch/arm/dts/tegra20-asus-transformer.dtsi index 49efabbfd92..61b1cea6e90 100644 --- a/arch/arm/dts/tegra20-asus-transformer.dtsi +++ b/arch/arm/dts/tegra20-asus-transformer.dtsi @@ -36,6 +36,10 @@ }; }; + bsev@6001b000 { + status = "okay"; + }; + pinmux@70000014 { pinctrl-names = "default"; pinctrl-0 = <&state_default>; diff --git a/arch/arm/dts/tegra20-lg-star.dts b/arch/arm/dts/tegra20-lg-star.dts index 3045bc3135f..083598b1b92 100644 --- a/arch/arm/dts/tegra20-lg-star.dts +++ b/arch/arm/dts/tegra20-lg-star.dts @@ -46,6 +46,10 @@ }; }; + bsev@6001b000 { + status = "okay"; + }; + pinmux@70000014 { pinctrl-names = "default"; pinctrl-0 = <&state_default>; diff --git a/arch/arm/dts/tegra20-motorola-mot.dtsi b/arch/arm/dts/tegra20-motorola-mot.dtsi index f00707c2859..db2cce1cc0d 100644 --- a/arch/arm/dts/tegra20-motorola-mot.dtsi +++ b/arch/arm/dts/tegra20-motorola-mot.dtsi @@ -62,6 +62,10 @@ }; }; + bsev@6001b000 { + status = "okay"; + }; + pinmux@70000014 { pinctrl-names = "default"; pinctrl-0 = <&state_default>; diff --git a/arch/arm/dts/tegra20-samsung-bose.dts b/arch/arm/dts/tegra20-samsung-bose.dts new file mode 100644 index 00000000000..5bb9a33adf2 --- /dev/null +++ b/arch/arm/dts/tegra20-samsung-bose.dts @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: GPL-2.0 +/dts-v1/; + +#include "tegra20-samsung-n1-common.dtsi" + +/ { + model = "Samsung Captivate Glide (SGH-i927)"; + compatible = "samsung,bose", "nvidia,tegra20"; + + aliases { + spi0 = &panel_spi; + }; + + host1x@50000000 { + dc@54200000 { + rgb { + status = "okay"; + + port { + dpi_output: endpoint { + remote-endpoint = <&panel_input>; + bus-width = <24>; + }; + }; + }; + }; + }; + + pinmux@70000014 { + pinctrl-names = "default"; + pinctrl-0 = <&state_default>; + + state_default: pinmux { + conf-dtf { + nvidia,pins = "dtf", "spdi", "spib", "spih"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + conf-gpv { + nvidia,pins = "gpv"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + conf-kbcd { + nvidia,pins = "kbcd"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + drive-dap { + nvidia,pins = "drive_dap2", "drive_dap3"; + nvidia,high-speed-mode = <TEGRA_PIN_ENABLE>; + nvidia,schmitt = <TEGRA_PIN_ENABLE>; + nvidia,low-power-mode = <TEGRA_PIN_LP_DRIVE_DIV_1>; + nvidia,pull-down-strength = <31>; + nvidia,pull-up-strength = <31>; + nvidia,slew-rate-rising = <TEGRA_PIN_SLEW_RATE_SLOWEST>; + nvidia,slew-rate-falling = <TEGRA_PIN_SLEW_RATE_SLOWEST>; + }; + }; + }; + + panel_spi: spi@7000d800 { + status = "okay"; + spi-max-frequency = <1000000>; + + panel: panel@2 { + /* 480x800 AMOLED panel */ + compatible = "samsung,bose-panel", "samsung,s6e63m0"; + reg = <2>; + + spi-max-frequency = <1000000>; + + spi-cpol; + spi-cpha; + + reset-gpios = <&gpio TEGRA_GPIO(C, 1) GPIO_ACTIVE_LOW>; + + vdd3-supply = <&vlcd_1v8_reg>; + vci-supply = <&vlcd_3v0_reg>; + + panel-width-mm = <52>; + panel-height-mm = <87>; + + port { + panel_input: endpoint { + remote-endpoint = <&dpi_output>; + }; + }; + }; + }; + + sdhci@c8000400 { + broken-cd; + }; + + gpio-keys { + compatible = "gpio-keys"; + + switch-hall { + label = "Keyboard Slide"; + gpios = <&gpio TEGRA_GPIO(W, 3) GPIO_ACTIVE_HIGH>; + linux,input-type = <EV_SW>; + linux,code = <SW_KEYPAD_SLIDE>; + }; + }; + + leds { + compatible = "gpio-leds"; + + led-kbd { + label = "Keyboard backlight"; + gpios = <&gpio TEGRA_GPIO(L, 5) GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + }; +}; diff --git a/arch/arm/dts/tegra20-samsung-n1-common.dtsi b/arch/arm/dts/tegra20-samsung-n1-common.dtsi new file mode 100644 index 00000000000..8223c5ece54 --- /dev/null +++ b/arch/arm/dts/tegra20-samsung-n1-common.dtsi @@ -0,0 +1,428 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <dt-bindings/input/input.h> +#include "tegra20.dtsi" + +/ { + chosen { + stdout-path = &uartb; + }; + + aliases { + i2c0 = &pwr_i2c; + + mmc0 = &sdmmc4; /* eMMC */ + mmc1 = &sdmmc3; /* uSD slot */ + + rtc0 = &pmic; + rtc1 = "/rtc@7000e000"; + + usb0 = µ_usb; + }; + + memory { + device_type = "memory"; + reg = <0x00000000 0x40000000>; /* 1 GB */ + }; + + pinmux@70000014 { + pinctrl-names = "default"; + pinctrl-0 = <&state_default>; + + state_default: pinmux { + ata { + nvidia,pins = "ata", "atc", "atd", "ate", + "gmb", "gmd", "irrx", "irtx", + "spid", "spie"; + nvidia,function = "gmi"; + }; + + atb { + nvidia,pins = "atb", "gma", "gme"; + nvidia,function = "sdio4"; + }; + + cdev1 { + nvidia,pins = "cdev1"; + nvidia,function = "plla_out"; + }; + + cdev2 { + nvidia,pins = "cdev2"; + nvidia,function = "pllp_out4"; + }; + + crtp { + nvidia,pins = "crtp"; + nvidia,function = "crt"; + }; + + csus { + nvidia,pins = "csus"; + nvidia,function = "vi_sensor_clk"; + }; + + dap1 { + nvidia,pins = "dap1"; + nvidia,function = "dap1"; + }; + + dap2 { + nvidia,pins = "dap2"; + nvidia,function = "dap2"; + }; + + dap3 { + nvidia,pins = "dap3"; + nvidia,function = "dap3"; + }; + + dap4 { + nvidia,pins = "dap4"; + nvidia,function = "dap4"; + }; + + ddc { + nvidia,pins = "ddc"; + nvidia,function = "rsvd4"; + }; + + pta { + nvidia,pins = "pta"; + nvidia,function = "i2c2"; + }; + + spif { + nvidia,pins = "spif", "uac"; + nvidia,function = "rsvd4"; + }; + + dta { + nvidia,pins = "dta", "dtb", "dtc", "dtd", "dte"; + nvidia,function = "vi"; + }; + + dtf { + nvidia,pins = "dtf"; + nvidia,function = "i2c3"; + }; + + gmc { + nvidia,pins = "gmc"; + nvidia,function = "uartd"; + }; + + gpu { + nvidia,pins = "gpu", "uaa", "uab"; + nvidia,function = "uarta"; + }; + + gpu7 { + nvidia,pins = "gpu7"; + nvidia,function = "rtck"; + }; + + gpv { + nvidia,pins = "gpv", "slxa", "slxk"; + nvidia,function = "pcie"; + }; + + hdint { + nvidia,pins = "hdint", "spdi", "spdo"; + nvidia,function = "rsvd2"; + }; + + i2cp { + nvidia,pins = "i2cp"; + nvidia,function = "i2cp"; + }; + + kbca { + nvidia,pins = "kbca", "kbcb", "kbcc", "kbcd", + "kbce", "kbcf"; + nvidia,function = "kbc"; + }; + + lcsn { + nvidia,pins = "lcsn", "lsck", "lsda", "lsdi"; + nvidia,function = "spi3"; + }; + + ld0 { + nvidia,pins = "ld0", "ld1", "ld2", "ld3", "ld4", + "ld5", "ld6", "ld7", "ld8", "ld9", + "ld10", "ld11", "ld12", "ld13", "ld14", + "ld15", "ld16", "ld17", "ldc", "ldi", + "lhp0", "lhp1", "lhp2", "lhs", "lm0", + "lm1", "lpp", "lpw0", "lpw1", "lpw2", + "lsc0", "lsc1", "lspi", "lvp0", "lvp1", + "lvs"; + nvidia,function = "displaya"; + }; + + owc { + nvidia,pins = "owc"; + nvidia,function = "owr"; + }; + + pmc { + nvidia,pins = "pmc"; + nvidia,function = "pwr_on"; + }; + + rm { + nvidia,pins = "rm"; + nvidia,function = "i2c1"; + }; + + sdb { + nvidia,pins = "sdb", "sdc", "sdd"; + nvidia,function = "sdio3"; + }; + + sdio1 { + nvidia,pins = "sdio1"; + nvidia,function = "sdio1"; + }; + + slxc { + nvidia,pins = "slxc", "slxd"; + nvidia,function = "spi4"; + }; + + spig { + nvidia,pins = "spig", "spih"; + nvidia,function = "spi2_alt"; + }; + + uad { + nvidia,pins = "uad"; + nvidia,function = "irda"; + }; + + uca { + nvidia,pins = "uca", "ucb"; + nvidia,function = "uartc"; + }; + + uda { + nvidia,pins = "uda"; + nvidia,function = "spi1"; + }; + + spia { + nvidia,pins = "spia", "spib", "spic"; + nvidia,function = "spi2"; + }; + + conf-cdev1 { + nvidia,pins = "cdev1", "cdev2", "dap1", "dap2", + "dap3", "dap4", "ddc", "dte", "gma", + "gmc", "gmd", "gme", "gpu7", "hdint", + "i2cp", "lcsn", "lhs", "lm0", "lm1", + "lpw1", "lsc0", "lsck", "lsda", "lsdi", + "lspi", "lvs", "pmc", "pta", "rm", + "sdb", "sdio1", "uac", "uda", "ck32", + "ddrc", "pmca", "pmcb", "pmcc", "pmcd", + "xm2c", "xm2d"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + conf-crtp { + nvidia,pins = "crtp", "lvp0"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + }; + + conf-csus { + nvidia,pins = "csus", "spid"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + }; + + conf-ata { + nvidia,pins = "ata", "atb", "atc", "ate", + "gmb", "gpu", "irrx", "irtx", + "kbca", "kbcc", "kbce", "kbcf", + "ldc", "lpw0", "lpw2", "lsc1", "sdc", + "sdd", "spig", "uaa", "uab", + "uad", "uca", "ucb", "pmce"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + conf-owc { + nvidia,pins = "owc"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + }; + + conf-atd { + nvidia,pins = "atd", "dta", "dtb", "dtc", "dtd", + "kbcb", "ld0", "ld1", "ld10", "ld11", + "ld12", "ld13", "ld14", "ld15", "ld16", + "ld17", "ld2", "ld3", "ld4", "ld5", + "ld6", "ld7", "ld8", "ld9", "ldi", + "lhp0", "lhp1", "lhp2", "lpp", "lvp1", + "slxa", "slxc", "slxd", "slxk", "spdo", + "spia", "spic", "spie", "spif"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + drive-ao1 { + nvidia,pins = "drive_ao1", "drive_at1", "drive_dbg", + "drive_vi1", "drive_vi2"; + nvidia,high-speed-mode = <TEGRA_PIN_DISABLE>; + nvidia,schmitt = <TEGRA_PIN_ENABLE>; + nvidia,low-power-mode = <TEGRA_PIN_LP_DRIVE_DIV_1>; + nvidia,pull-down-strength = <31>; + nvidia,pull-up-strength = <31>; + nvidia,slew-rate-rising = <TEGRA_PIN_SLEW_RATE_SLOWEST>; + nvidia,slew-rate-falling = <TEGRA_PIN_SLEW_RATE_SLOWEST>; + }; + + drive-sdio1 { + nvidia,pins = "drive_sdio1"; + nvidia,high-speed-mode = <TEGRA_PIN_DISABLE>; + nvidia,schmitt = <TEGRA_PIN_ENABLE>; + nvidia,low-power-mode = <TEGRA_PIN_LP_DRIVE_DIV_1>; + nvidia,pull-down-strength = <31>; + nvidia,pull-up-strength = <31>; + nvidia,slew-rate-rising = <TEGRA_PIN_SLEW_RATE_SLOWEST>; + nvidia,slew-rate-falling = <TEGRA_PIN_SLEW_RATE_SLOWEST>; + }; + + drive-ddc { + nvidia,pins = "drive_ddc"; + nvidia,high-speed-mode = <TEGRA_PIN_DISABLE>; + nvidia,schmitt = <TEGRA_PIN_ENABLE>; + nvidia,low-power-mode = <TEGRA_PIN_LP_DRIVE_DIV_1>; + nvidia,pull-down-strength = <31>; + nvidia,pull-up-strength = <31>; + nvidia,slew-rate-rising = <TEGRA_PIN_SLEW_RATE_FASTEST>; + nvidia,slew-rate-falling = <TEGRA_PIN_SLEW_RATE_FASTEST>; + }; + }; + }; + + uartb: serial@70006040 { + clocks = <&tegra_car 7>; + status = "okay"; + }; + + pwr_i2c: i2c@7000d000 { + status = "okay"; + clock-frequency = <400000>; + + pmic: max8907@3c { + compatible = "maxim,max8907"; + reg = <0x3c>; + + interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>; + #interrupt-cells = <2>; + interrupt-controller; + + #gpio-cells = <2>; + gpio-controller; + + maxim,system-power-controller; + + regulators { + vlcd_1v8_reg: ldo3 { + regulator-name = "vlcd_1v8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + }; + + usb_phy_reg: ldo4 { + regulator-name = "vap_usb_3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + }; + + vlcd_3v0_reg: ldo12 { + regulator-name = "vlcd_3v0"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + }; + + vmmc_usd_reg: ldo16 { + regulator-name = "vmmc_usd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + }; + }; + }; + + micro_usb: usb@c5000000 { + status = "okay"; + dr_mode = "otg"; + }; + + usb-phy@c5000000 { + status = "okay"; + vbus-supply = <&usb_phy_reg>; + }; + + sdmmc3: sdhci@c8000400 { + status = "okay"; + bus-width = <4>; + + vmmc-supply = <&vmmc_usd_reg>; + vqmmc-supply = <&vdd_3v3_sys>; + }; + + sdmmc4: sdhci@c8000600 { + status = "okay"; + bus-width = <8>; + non-removable; + + vmmc-supply = <&vdd_3v3_sys>; + vqmmc-supply = <&vdd_3v3_sys>; + }; + + /* 32KHz oscillator which is used by PMC */ + clk32k_in: clock-32k-in { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + clock-output-names = "ref-oscillator"; + }; + + gpio-keys { + compatible = "gpio-keys"; + + key-power { + label = "Power"; + gpios = <&gpio TEGRA_GPIO(U, 5) GPIO_ACTIVE_HIGH>; + linux,code = <KEY_ENTER>; + }; + + key-volume-up { + label = "Volume Up"; + gpios = <&gpio TEGRA_GPIO(Q, 1) GPIO_ACTIVE_LOW>; + linux,code = <KEY_UP>; + }; + + key-volume-down { + label = "Volume Down"; + gpios = <&gpio TEGRA_GPIO(Q, 2) GPIO_ACTIVE_LOW>; + linux,code = <KEY_DOWN>; + }; + }; + + vdd_3v3_sys: regulator-3v3 { + compatible = "regulator-fixed"; + regulator-name = "vdd_3v3_vs"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; +}; diff --git a/arch/arm/dts/tegra20-samsung-n1.dts b/arch/arm/dts/tegra20-samsung-n1.dts new file mode 100644 index 00000000000..930a3195aa0 --- /dev/null +++ b/arch/arm/dts/tegra20-samsung-n1.dts @@ -0,0 +1,184 @@ +// SPDX-License-Identifier: GPL-2.0 +/dts-v1/; + +#include "tegra20-samsung-n1-common.dtsi" + +/ { + model = "Samsung Galaxy R (GT-I9103)"; + compatible = "samsung,n1", "nvidia,tegra20"; + + aliases { + i2c10 = &cmc_i2c; + spi0 = &panel_spi; + }; + + host1x@50000000 { + dc@54200000 { + rgb { + status = "okay"; + + port { + dpi_output: endpoint { + remote-endpoint = <&bridge_input>; + bus-width = <24>; + }; + }; + }; + }; + }; + + pinmux@70000014 { + pinctrl-names = "default"; + pinctrl-0 = <&state_default>; + + state_default: pinmux { + conf-dtf { + nvidia,pins = "dtf", "spdi", "spih"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + conf-gpv { + nvidia,pins = "gpv", "spib"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + conf-kbcd { + nvidia,pins = "kbcd"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + }; + }; + + i2c@7000d000 { + max8907@3c { + regulators { + vcmc623_io_1v8: ldo15 { + regulator-name = "vcmc623_io_1v8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + }; + }; + }; + + cmc_i2c: i2c-10 { + compatible = "i2c-gpio"; + + sda-gpios = <&gpio TEGRA_GPIO(Z, 3) GPIO_ACTIVE_HIGH>; + scl-gpios = <&gpio TEGRA_GPIO(C, 6) GPIO_ACTIVE_HIGH>; + + i2c-gpio,scl-output-only; + i2c-gpio,delay-us = <1>; + + #address-cells = <1>; + #size-cells = <0>; + + cmc623: bridge@38 { + compatible = "samsung,cmc623"; + reg = <0x38>; + + enable-gpios = <&gpio TEGRA_GPIO(Q, 4) GPIO_ACTIVE_HIGH>; + reset-gpios = <&gpio TEGRA_GPIO(J, 6) GPIO_ACTIVE_HIGH>; + + bypass-gpios = <&gpio TEGRA_GPIO(BB, 5) GPIO_ACTIVE_LOW>; + sleep-gpios = <&gpio TEGRA_GPIO(W, 0) GPIO_ACTIVE_HIGH>; + + vdd3v0-supply = <&vcmc623_3v0>; + vdd1v2-supply = <&vcmc623_1v2>; + vddio1v8-supply = <&vcmc623_io_1v8>; + + cmc623_backlight: backlight { + compatible = "samsung,cmc623-backlight"; + + enable-gpios = <&gpio TEGRA_GPIO(R, 3) GPIO_ACTIVE_HIGH>; + }; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + bridge_input: endpoint { + remote-endpoint = <&dpi_output>; + }; + }; + + port@1 { + reg = <1>; + + bridge_output: endpoint { + remote-endpoint = <&panel_input>; + }; + }; + }; + }; + }; + + panel_spi: spi@7000d800 { + status = "okay"; + spi-max-frequency = <1000000>; + + panel: panel@2 { + /* 480x800 TFT LCD panel */ + compatible = "sony,l4f00430t01"; + reg = <2>; + + spi-max-frequency = <1000000>; + + spi-cpol; + spi-cpha; + + reset-gpios = <&gpio TEGRA_GPIO(C, 1) GPIO_ACTIVE_LOW>; + + vdd1v8-supply = <&vlcd_1v8_reg>; + vdd3v0-supply = <&vlcd_3v0_reg>; + + panel-width-mm = <55>; + panel-height-mm = <91>; + + backlight = <&cmc623_backlight>; + + port { + panel_input: endpoint { + remote-endpoint = <&bridge_output>; + }; + }; + }; + }; + + sdhci@c8000400 { + /* battery blocks the sdcard slot and the device lacks CD pin */ + non-removable; + }; + + gpio-keys { + compatible = "gpio-keys"; + + key-home { + label = "Home"; + gpios = <&gpio TEGRA_GPIO(O, 5) GPIO_ACTIVE_LOW>; + linux,code = <KEY_ENTER>; + }; + }; + + vcmc623_3v0: regulator-cmc623-3v0 { + compatible = "regulator-fixed"; + regulator-name = "vcmc623_3v0"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + vcmc623_1v2: regulator-cmc623-1v2 { + compatible = "regulator-fixed"; + regulator-name = "vcmc623_1v2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + gpio = <&gpio TEGRA_GPIO(L, 5) GPIO_ACTIVE_HIGH>; + enable-active-high; + }; +}; diff --git a/arch/arm/dts/tegra20.dtsi b/arch/arm/dts/tegra20.dtsi index 275b3432bd8..4a40edfdfbe 100644 --- a/arch/arm/dts/tegra20.dtsi +++ b/arch/arm/dts/tegra20.dtsi @@ -249,6 +249,35 @@ */ }; + /* Audio Bitstream Engine */ + bsea@60011000 { + compatible = "nvidia,tegra20-bsea"; + reg = <0x60011000 0x1000>, <0x4000c000 0x4000>; + reg-names = "bsea", "iram-buffer"; + interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "bsea"; + clocks = <&tegra_car TEGRA20_CLK_BSEA>; + resets = <&tegra_car 62>; + reset-names = "bsea"; + status = "disabled"; + }; + + /* Video Bitstream Engine */ + bsev@6001b000 { + compatible = "nvidia,tegra20-bsev"; + reg = <0x6001b000 0x1000>, <0x40008000 0x4000>; + reg-names = "bsev", "iram-buffer"; + interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "bsev"; + clocks = <&tegra_car TEGRA20_CLK_BSEV>, + <&tegra_car TEGRA20_CLK_VDE>; + clock-names = "bsev", "vde"; + resets = <&tegra_car 63>, + <&tegra_car 61>; + reset-names = "bsev", "vde"; + status = "disabled"; + }; + apbmisc@70000800 { compatible = "nvidia,tegra20-apbmisc"; reg = <0x70000800 0x64 /* Chip revision */ diff --git a/arch/arm/dts/tegra30-asus-grouper-common.dtsi b/arch/arm/dts/tegra30-asus-grouper-common.dtsi index d437ddc4dce..ddacdbb85c8 100644 --- a/arch/arm/dts/tegra30-asus-grouper-common.dtsi +++ b/arch/arm/dts/tegra30-asus-grouper-common.dtsi @@ -44,6 +44,10 @@ }; }; + bsev@6001b000 { + status = "okay"; + }; + pinmux@70000868 { pinctrl-names = "default"; pinctrl-0 = <&state_default>; diff --git a/arch/arm/dts/tegra30-asus-p1801-t.dts b/arch/arm/dts/tegra30-asus-p1801-t.dts index 58f1499cb92..31cbef1b93c 100644 --- a/arch/arm/dts/tegra30-asus-p1801-t.dts +++ b/arch/arm/dts/tegra30-asus-p1801-t.dts @@ -50,6 +50,10 @@ }; }; + bsev@6001b000 { + status = "okay"; + }; + pinmux@70000868 { pinctrl-names = "default"; pinctrl-0 = <&state_default>; diff --git a/arch/arm/dts/tegra30-asus-tf600t.dts b/arch/arm/dts/tegra30-asus-tf600t.dts index 1b5729c65f4..5135b8c666c 100644 --- a/arch/arm/dts/tegra30-asus-tf600t.dts +++ b/arch/arm/dts/tegra30-asus-tf600t.dts @@ -53,6 +53,10 @@ }; }; + bsev@6001b000 { + status = "okay"; + }; + pinmux@70000868 { pinctrl-names = "default"; pinctrl-0 = <&state_default>; diff --git a/arch/arm/dts/tegra30-asus-transformer.dtsi b/arch/arm/dts/tegra30-asus-transformer.dtsi index 032fb3d00ac..47a44fbc9dd 100644 --- a/arch/arm/dts/tegra30-asus-transformer.dtsi +++ b/arch/arm/dts/tegra30-asus-transformer.dtsi @@ -37,6 +37,10 @@ }; }; + bsev@6001b000 { + status = "okay"; + }; + pinmux@70000868 { pinctrl-names = "default"; pinctrl-0 = <&state_default>; diff --git a/arch/arm/dts/tegra30-htc-endeavoru.dts b/arch/arm/dts/tegra30-htc-endeavoru.dts index db8ac457880..79f423bd22a 100644 --- a/arch/arm/dts/tegra30-htc-endeavoru.dts +++ b/arch/arm/dts/tegra30-htc-endeavoru.dts @@ -60,6 +60,10 @@ }; }; + bsev@6001b000 { + status = "okay"; + }; + pinmux@70000868 { pinctrl-names = "default"; pinctrl-0 = <&state_default>; diff --git a/arch/arm/dts/tegra30-lenovo-ideapad-yoga-11.dts b/arch/arm/dts/tegra30-lenovo-ideapad-yoga-11.dts index 876fac7b661..53f42089d30 100644 --- a/arch/arm/dts/tegra30-lenovo-ideapad-yoga-11.dts +++ b/arch/arm/dts/tegra30-lenovo-ideapad-yoga-11.dts @@ -43,6 +43,10 @@ }; }; + bsev@6001b000 { + status = "okay"; + }; + pinmux@70000868 { pinctrl-names = "default"; pinctrl-0 = <&state_default>; diff --git a/arch/arm/dts/tegra30-lg-x3.dtsi b/arch/arm/dts/tegra30-lg-x3.dtsi index 40b0ee07787..09c5d04a225 100644 --- a/arch/arm/dts/tegra30-lg-x3.dtsi +++ b/arch/arm/dts/tegra30-lg-x3.dtsi @@ -42,6 +42,10 @@ }; }; + bsev@6001b000 { + status = "okay"; + }; + pinmux@70000868 { pinctrl-names = "default"; pinctrl-0 = <&state_default>; diff --git a/arch/arm/dts/tegra30-ouya.dts b/arch/arm/dts/tegra30-ouya.dts index 04453eb2432..e6b2824d783 100644 --- a/arch/arm/dts/tegra30-ouya.dts +++ b/arch/arm/dts/tegra30-ouya.dts @@ -56,6 +56,10 @@ }; }; + bsev@6001b000 { + status = "okay"; + }; + pinmux@70000868 { pinctrl-names = "default"; pinctrl-0 = <&state_default>; diff --git a/arch/arm/dts/tegra30-pegatron-chagall.dts b/arch/arm/dts/tegra30-pegatron-chagall.dts new file mode 100644 index 00000000000..98eb369f7a8 --- /dev/null +++ b/arch/arm/dts/tegra30-pegatron-chagall.dts @@ -0,0 +1,1291 @@ +// SPDX-License-Identifier: GPL-2.0 +/dts-v1/; + +#include <dt-bindings/input/input.h> +#include "tegra30.dtsi" + +/ { + model = "Pegatron Chagall"; + compatible = "pegatron,chagall", "nvidia,tegra30"; + + chosen { + stdout-path = &uarta; + }; + + aliases { + i2c0 = &pwr_i2c; + + mmc0 = &sdmmc4; /* eMMC */ + mmc1 = &sdmmc1; /* uSD slot */ + + rtc0 = &pmic; + rtc1 = "/rtc@7000e000"; + + usb0 = &usb1; + usb1 = &usb3; /* Dock USB */ + }; + + memory { + device_type = "memory"; + reg = <0x80000000 0x40000000>; + }; + + host1x@50000000 { + dc@54200000 { + rgb { + status = "okay"; + + port { + dpi_output: endpoint { + remote-endpoint = <&bridge_input>; + bus-width = <24>; + }; + }; + }; + }; + }; + + pinmux@70000868 { + pinctrl-names = "default"; + pinctrl-0 = <&state_default>; + + state_default: pinmux { + /* SDMMC1 pinmux */ + sdmmc1_clk_pz0 { + nvidia,pins = "sdmmc1_clk_pz0"; + nvidia,function = "sdmmc1"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + sdmmc1_dat3_py4 { + nvidia,pins = "sdmmc1_dat3_py4", + "sdmmc1_dat2_py5", + "sdmmc1_dat1_py6", + "sdmmc1_dat0_py7", + "sdmmc1_cmd_pz1"; + nvidia,function = "sdmmc1"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* SDMMC2 pinmux */ + vi_d1_pd5 { + nvidia,pins = "vi_d1_pd5", + "vi_d2_pl0", + "vi_d3_pl1", + "vi_d5_pl3", + "vi_d7_pl5"; + nvidia,function = "sdmmc2"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + vi_d8_pl6 { + nvidia,pins = "vi_d8_pl6", + "vi_d9_pl7"; + nvidia,function = "sdmmc2"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + nvidia,lock = <0>; + nvidia,io-reset = <0>; + }; + + /* SDMMC3 pinmux */ + sdmmc3_clk_pa6 { + nvidia,pins = "sdmmc3_clk_pa6"; + nvidia,function = "sdmmc3"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + sdmmc3_cmd_pa7 { + nvidia,pins = "sdmmc3_cmd_pa7", + "sdmmc3_dat3_pb4", + "sdmmc3_dat2_pb5", + "sdmmc3_dat1_pb6", + "sdmmc3_dat0_pb7", + "sdmmc3_dat5_pd0", + "sdmmc3_dat4_pd1", + "sdmmc3_dat6_pd3", + "sdmmc3_dat7_pd4"; + nvidia,function = "sdmmc3"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* SDMMC4 pinmux */ + sdmmc4_clk_pcc4 { + nvidia,pins = "sdmmc4_clk_pcc4"; + nvidia,function = "sdmmc4"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + sdmmc4_cmd_pt7 { + nvidia,pins = "sdmmc4_cmd_pt7", + "sdmmc4_dat0_paa0", + "sdmmc4_dat1_paa1", + "sdmmc4_dat2_paa2", + "sdmmc4_dat3_paa3", + "sdmmc4_dat4_paa4", + "sdmmc4_dat5_paa5", + "sdmmc4_dat6_paa6", + "sdmmc4_dat7_paa7"; + nvidia,function = "sdmmc4"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* I2C pinmux */ + gen1_i2c_scl_pc4 { + nvidia,pins = "gen1_i2c_scl_pc4", + "gen1_i2c_sda_pc5"; + nvidia,function = "i2c1"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + nvidia,open-drain = <TEGRA_PIN_ENABLE>; + nvidia,lock = <0>; + }; + + gen2_i2c_scl_pt5 { + nvidia,pins = "gen2_i2c_scl_pt5", + "gen2_i2c_sda_pt6"; + nvidia,function = "i2c2"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + nvidia,open-drain = <TEGRA_PIN_ENABLE>; + nvidia,lock = <0>; + }; + + cam_i2c_scl_pbb1 { + nvidia,pins = "cam_i2c_scl_pbb1", + "cam_i2c_sda_pbb2"; + nvidia,function = "i2c3"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + nvidia,open-drain = <TEGRA_PIN_ENABLE>; + nvidia,lock = <0>; + }; + + ddc_scl_pv4 { + nvidia,pins = "ddc_scl_pv4", + "ddc_sda_pv5"; + nvidia,function = "i2c4"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + nvidia,lock = <0>; + }; + + pwr_i2c_scl_pz6 { + nvidia,pins = "pwr_i2c_scl_pz6", + "pwr_i2c_sda_pz7"; + nvidia,function = "i2cpwr"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + nvidia,open-drain = <TEGRA_PIN_ENABLE>; + nvidia,lock = <0>; + }; + + /* HDMI-CEC pinmux */ + hdmi_cec_pee3 { + nvidia,pins = "hdmi_cec_pee3"; + nvidia,function = "cec"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + nvidia,open-drain = <TEGRA_PIN_ENABLE>; + nvidia,lock = <0>; + }; + + /* UART-A */ + ulpi_data0_po1 { + nvidia,pins = "ulpi_data0_po1"; + nvidia,function = "uarta"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + ulpi_data1_po2 { + nvidia,pins = "ulpi_data1_po2", + "ulpi_data2_po3", + "ulpi_data3_po4", + "ulpi_data4_po5", + "ulpi_data5_po6", + "ulpi_data6_po7"; + nvidia,function = "uarta"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + ulpi_data7_po0 { + nvidia,pins = "ulpi_data7_po0"; + nvidia,function = "uarta"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + /* UART-B */ + uart2_txd_pc2 { + nvidia,pins = "uart2_txd_pc2", + "uart2_rts_n_pj6"; + nvidia,function = "uartb"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + uart2_rxd_pc3 { + nvidia,pins = "uart2_rxd_pc3", + "uart2_cts_n_pj5"; + nvidia,function = "uartb"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* UART-C */ + uart3_cts_n_pa1 { + nvidia,pins = "uart3_cts_n_pa1", + "uart3_rxd_pw7"; + nvidia,function = "uartc"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + uart3_rts_n_pc0 { + nvidia,pins = "uart3_rts_n_pc0", + "uart3_txd_pw6"; + nvidia,function = "uartc"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + /* UART-D */ + ulpi_clk_py0 { + nvidia,pins = "ulpi_clk_py0", + "ulpi_stp_py3"; + nvidia,function = "uartd"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + ulpi_dir_py1 { + nvidia,pins = "ulpi_dir_py1", + "ulpi_nxt_py2"; + nvidia,function = "uartd"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* I2S pinmux */ + dap1_fs_pn0 { + nvidia,pins = "dap1_fs_pn0", + "dap1_din_pn1", + "dap1_dout_pn2", + "dap1_sclk_pn3"; + nvidia,function = "i2s0"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + dap2_fs_pa2 { + nvidia,pins = "dap2_fs_pa2", + "dap2_sclk_pa3", + "dap2_din_pa4", + "dap2_dout_pa5"; + nvidia,function = "i2s1"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + dap3_fs_pp0 { + nvidia,pins = "dap3_fs_pp0", + "dap3_din_pp1", + "dap3_dout_pp2", + "dap3_sclk_pp3"; + nvidia,function = "i2s2"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + dap4_fs_pp4 { + nvidia,pins = "dap4_fs_pp4", + "dap4_din_pp5", + "dap4_dout_pp6", + "dap4_sclk_pp7"; + nvidia,function = "i2s3"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + pcc2 { + nvidia,pins = "pcc2"; + nvidia,function = "i2s4"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* PCI-e pinmux */ + pex_l2_rst_n_pcc6 { + nvidia,pins = "pex_l2_rst_n_pcc6", + "pex_l0_rst_n_pdd1", + "pex_l1_rst_n_pdd5"; + nvidia,function = "pcie"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + pex_l2_clkreq_n_pcc7 { + nvidia,pins = "pex_l2_clkreq_n_pcc7", + "pex_l0_prsnt_n_pdd0", + "pex_l0_clkreq_n_pdd2", + "pex_l2_prsnt_n_pdd7"; + nvidia,function = "pcie"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + pex_wake_n_pdd3 { + nvidia,pins = "pex_wake_n_pdd3"; + nvidia,function = "pcie"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + /* SPI pinmux */ + spi1_mosi_px4 { + nvidia,pins = "spi1_mosi_px4", + "spi1_sck_px5", + "spi1_cs0_n_px6", + "spi1_miso_px7"; + nvidia,function = "spi1"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + spi2_cs1_n_pw2 { + nvidia,pins = "spi2_cs1_n_pw2", + "spi2_cs2_n_pw3"; + nvidia,function = "spi2"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + spi2_sck_px2 { + nvidia,pins = "spi2_sck_px2"; + nvidia,function = "gmi"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + gmi_a16_pj7 { + nvidia,pins = "gmi_a16_pj7", + "gmi_a19_pk7"; + nvidia,function = "spi4"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + gmi_a17_pb0 { + nvidia,pins = "gmi_a17_pb0", + "gmi_a18_pb1"; + nvidia,function = "spi4"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + spi2_mosi_px0 { + nvidia,pins = "spi2_mosi_px0"; + nvidia,function = "spi6"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + spdif_out_pk5 { + nvidia,pins = "spdif_out_pk5"; + nvidia,function = "spdif"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + spdif_in_pk6 { + nvidia,pins = "spdif_in_pk6"; + nvidia,function = "spdif"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* Display A pinmux */ + lcd_pwr0_pb2 { + nvidia,pins = "lcd_pwr0_pb2", + "lcd_pclk_pb3", + "lcd_pwr1_pc1", + "lcd_pwr2_pc6", + "lcd_d0_pe0", + "lcd_d1_pe1", + "lcd_d2_pe2", + "lcd_d3_pe3", + "lcd_d4_pe4", + "lcd_d5_pe5", + "lcd_d6_pe6", + "lcd_d7_pe7", + "lcd_d8_pf0", + "lcd_d9_pf1", + "lcd_d10_pf2", + "lcd_d11_pf3", + "lcd_d12_pf4", + "lcd_d13_pf5", + "lcd_d14_pf6", + "lcd_d15_pf7", + "lcd_de_pj1", + "lcd_hsync_pj3", + "lcd_vsync_pj4", + "lcd_d16_pm0", + "lcd_d17_pm1", + "lcd_d18_pm2", + "lcd_d19_pm3", + "lcd_d20_pm4", + "lcd_d21_pm5", + "lcd_d22_pm6", + "lcd_d23_pm7", + "lcd_cs0_n_pn4", + "lcd_sdout_pn5", + "lcd_dc0_pn6", + "lcd_sdin_pz2", + "lcd_wr_n_pz3", + "lcd_sck_pz4", + "lcd_cs1_n_pw0", + "lcd_m1_pw1"; + nvidia,function = "displaya"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + lcd_dc1_pd2 { + nvidia,pins = "lcd_dc1_pd2"; + nvidia,function = "displaya"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + clk_32k_out_pa0 { + nvidia,pins = "clk_32k_out_pa0"; + nvidia,function = "blink"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + /* KBC keys */ + kb_row0_pr0 { + nvidia,pins = "kb_row0_pr0", + "kb_row1_pr1", + "kb_row2_pr2", + "kb_row3_pr3", + "kb_row8_ps0", + "kb_col0_pq0", + "kb_col1_pq1", + "kb_col2_pq2", + "kb_col3_pq3", + "kb_col4_pq4", + "kb_col5_pq5", + "kb_col7_pq7"; + nvidia,function = "kbc"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + kb_row4_pr4 { + nvidia,pins = "kb_row4_pr4", + "kb_row7_pr7", + "kb_row10_ps2", + "kb_row13_ps5"; + nvidia,function = "kbc"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + kb_row11_ps3 { + nvidia,pins = "kb_row11_ps3", + "kb_row12_ps4", + "kb_row15_ps7"; + nvidia,function = "kbc"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + kb_row14_ps6 { + nvidia,pins = "kb_row14_ps6"; + nvidia,function = "kbc"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + gmi_iordy_pi5 { + nvidia,pins = "gmi_iordy_pi5"; + nvidia,function = "rsvd1"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + vi_pclk_pt0 { + nvidia,pins = "vi_pclk_pt0"; + nvidia,function = "rsvd1"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + nvidia,lock = <0>; + nvidia,io-reset = <0>; + }; + + pu1 { + nvidia,pins = "pu1"; + nvidia,function = "rsvd1"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + pu2 { + nvidia,pins = "pu2"; + nvidia,function = "rsvd1"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + pv0 { + nvidia,pins = "pv0"; + nvidia,function = "rsvd1"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + pv1 { + nvidia,pins = "pv1"; + nvidia,function = "rsvd1"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + pcc1 { + nvidia,pins = "pcc1"; + nvidia,function = "rsvd2"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + sdmmc4_rst_n_pcc3 { + nvidia,pins = "sdmmc4_rst_n_pcc3"; + nvidia,function = "rsvd2"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + pv3 { + nvidia,pins = "pv3"; + nvidia,function = "rsvd2"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + vi_vsync_pd6 { + nvidia,pins = "vi_vsync_pd6", + "vi_hsync_pd7"; + nvidia,function = "rsvd2"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + nvidia,lock = <0>; + nvidia,io-reset = <0>; + }; + + vi_d10_pt2 { + nvidia,pins = "vi_d10_pt2", + "vi_d0_pt4", "pbb0"; + nvidia,function = "rsvd2"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + vi_d11_pt3 { + nvidia,pins = "vi_d11_pt3"; + nvidia,function = "rsvd2"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + pu0 { + nvidia,pins = "pu0"; + nvidia,function = "rsvd4"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + pu3 { + nvidia,pins = "pu3"; + nvidia,function = "rsvd4"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + pu6 { + nvidia,pins = "pu6"; + nvidia,function = "rsvd4"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + pex_l1_prsnt_n_pdd4 { + nvidia,pins = "pex_l1_prsnt_n_pdd4", + "pex_l1_clkreq_n_pdd6"; + nvidia,function = "rsvd4"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + gmi_wait_pi7 { + nvidia,pins = "gmi_wait_pi7", + "gmi_cs0_n_pj0", + "gmi_cs1_n_pj2", + "gmi_cs4_n_pk2"; + nvidia,function = "nand"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + gmi_ad0_pg0 { + nvidia,pins = "gmi_ad0_pg0", + "gmi_ad1_pg1", + "gmi_ad2_pg2", + "gmi_ad3_pg3", + "gmi_ad4_pg4", + "gmi_ad5_pg5", + "gmi_ad6_pg6", + "gmi_ad7_pg7", + "gmi_wr_n_pi0", + "gmi_oe_n_pi1", + "gmi_dqs_pi2", + "gmi_adv_n_pk0", + "gmi_clk_pk1"; + nvidia,function = "nand"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + gmi_cs2_n_pk3 { + nvidia,pins = "gmi_cs2_n_pk3"; + nvidia,function = "rsvd1"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + gmi_cs3_n_pk4 { + nvidia,pins = "gmi_cs3_n_pk4"; + nvidia,function = "nand"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + gmi_ad10_ph2 { + nvidia,pins = "gmi_ad10_ph2", + "gmi_ad11_ph3", + "gmi_ad14_ph6"; + nvidia,function = "nand"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + gmi_ad13_ph5 { + nvidia,pins = "gmi_ad13_ph5", + "gmi_ad12_ph4", + "gmi_cs7_n_pi6"; + nvidia,function = "nand"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + gmi_rst_n_pi4 { + nvidia,pins = "gmi_rst_n_pi4"; + nvidia,function = "gmi"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + gmi_ad8_ph0 { + nvidia,pins = "gmi_ad8_ph0"; + nvidia,function = "pwm0"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + gmi_ad9_ph1 { + nvidia,pins = "gmi_ad9_ph1"; + nvidia,function = "pwm1"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + gmi_wp_n_pc7 { + nvidia,pins = "gmi_wp_n_pc7"; + nvidia,function = "gmi"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + gmi_cs6_n_pi3 { + nvidia,pins = "gmi_cs6_n_pi3"; + nvidia,function = "sata"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + vi_d4_pl2 { + nvidia,pins = "vi_d4_pl2"; + nvidia,function = "vi"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + vi_d6_pl4 { + nvidia,pins = "vi_d6_pl4"; + nvidia,function = "vi"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + nvidia,lock = <0>; + nvidia,io-reset = <0>; + }; + + vi_mclk_pt1 { + nvidia,pins = "vi_mclk_pt1"; + nvidia,function = "vi"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* HDMI hot-plug-detect */ + hdmi_int_pn7 { + nvidia,pins = "hdmi_int_pn7"; + nvidia,function = "hdmi"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + pu4 { + nvidia,pins = "pu4"; + nvidia,function = "pwm1"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + pu5 { + nvidia,pins = "pu5"; + nvidia,function = "pwm2"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + jtag_rtck_pu7 { + nvidia,pins = "jtag_rtck_pu7"; + nvidia,function = "rtck"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + crt_hsync_pv6 { + nvidia,pins = "crt_hsync_pv6", + "crt_vsync_pv7"; + nvidia,function = "crt"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + clk1_out_pw4 { + nvidia,pins = "clk1_out_pw4"; + nvidia,function = "extperiph1"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + clk2_out_pw5 { + nvidia,pins = "clk2_out_pw5"; + nvidia,function = "extperiph2"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + clk3_out_pee0 { + nvidia,pins = "clk3_out_pee0"; + nvidia,function = "extperiph3"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + sys_clk_req_pz5 { + nvidia,pins = "sys_clk_req_pz5"; + nvidia,function = "sysclk"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + pbb4 { + nvidia,pins = "pbb4"; + nvidia,function = "vgp4"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + pbb5 { + nvidia,pins = "pbb5"; + nvidia,function = "vgp5"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + pbb6 { + nvidia,pins = "pbb6"; + nvidia,function = "vgp6"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + clk1_req_pee2 { + nvidia,pins = "clk1_req_pee2"; + nvidia,function = "dap"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + clk2_req_pcc5 { + nvidia,pins = "clk2_req_pcc5"; + nvidia,function = "dap"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + clk3_req_pee1 { + nvidia,pins = "clk3_req_pee1"; + nvidia,function = "dev3"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + owr { + nvidia,pins = "owr"; + nvidia,function = "owr"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + pv2 { + nvidia,pins = "pv2", + "kb_row5_pr5"; + nvidia,function = "owr"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + pbb3 { + nvidia,pins = "pbb3"; + nvidia,function = "vgp3"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + pbb7 { + nvidia,pins = "pbb7"; + nvidia,function = "i2s4"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + cam_mclk_pcc0 { + nvidia,pins = "cam_mclk_pcc0"; + nvidia,function = "vi_alt3"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* GPIO power/drive control */ + drive_dap1 { + nvidia,pins = "drive_dap1", + "drive_dap2", + "drive_dbg", + "drive_at5", + "drive_gme", + "drive_ddc", + "drive_ao1", + "drive_uart3"; + nvidia,high-speed-mode = <0>; + nvidia,schmitt = <TEGRA_PIN_ENABLE>; + nvidia,low-power-mode = <TEGRA_PIN_LP_DRIVE_DIV_1>; + nvidia,pull-down-strength = <31>; + nvidia,pull-up-strength = <31>; + nvidia,slew-rate-rising = <TEGRA_PIN_SLEW_RATE_FASTEST>; + nvidia,slew-rate-falling = <TEGRA_PIN_SLEW_RATE_FASTEST>; + }; + + drive_sdio1 { + nvidia,pins = "drive_sdio1"; + nvidia,high-speed-mode = <0>; + nvidia,schmitt = <TEGRA_PIN_DISABLE>; + nvidia,pull-down-strength = <5>; + nvidia,pull-up-strength = <5>; + nvidia,slew-rate-rising = <TEGRA_PIN_SLEW_RATE_FAST>; + nvidia,slew-rate-falling = <TEGRA_PIN_SLEW_RATE_FAST>; + }; + + drive_sdio3 { + nvidia,pins = "drive_sdio3"; + nvidia,high-speed-mode = <0>; + nvidia,schmitt = <TEGRA_PIN_DISABLE>; + nvidia,pull-down-strength = <46>; + nvidia,pull-up-strength = <42>; + nvidia,slew-rate-rising = <TEGRA_PIN_SLEW_RATE_FAST>; + nvidia,slew-rate-falling = <TEGRA_PIN_SLEW_RATE_FAST>; + }; + + drive_gma { + nvidia,pins = "drive_gma", + "drive_gmb", + "drive_gmc", + "drive_gmd"; + nvidia,pull-down-strength = <9>; + nvidia,pull-up-strength = <9>; + nvidia,slew-rate-rising = <TEGRA_PIN_SLEW_RATE_SLOWEST>; + nvidia,slew-rate-falling = <TEGRA_PIN_SLEW_RATE_SLOWEST>; + }; + + drive_lcd2 { + nvidia,pins = "drive_lcd2"; + nvidia,high-speed-mode = <0>; + nvidia,schmitt = <TEGRA_PIN_ENABLE>; + nvidia,low-power-mode = <TEGRA_PIN_LP_DRIVE_DIV_4>; + nvidia,pull-down-strength = <20>; + nvidia,pull-up-strength = <20>; + nvidia,slew-rate-rising = <TEGRA_PIN_SLEW_RATE_FASTEST>; + nvidia,slew-rate-falling = <TEGRA_PIN_SLEW_RATE_FASTEST>; + }; + }; + }; + + uarta: serial@70006000 { + status = "okay"; + }; + + pwm: pwm@7000a000 { + status = "okay"; + }; + + pwr_i2c: i2c@7000d000 { + status = "okay"; + clock-frequency = <400000>; + + /* Texas Instruments TPS659110 PMIC */ + pmic: tps65911@2d { + compatible = "ti,tps65911"; + reg = <0x2d>; + + interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>; + #interrupt-cells = <2>; + interrupt-controller; + + ti,system-power-controller; + + #gpio-cells = <2>; + gpio-controller; + + regulators { + vdd_1v8_vio: vddio { + regulator-name = "vdd_1v8_gen"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + }; + + /* eMMC VDD */ + vcore_emmc: ldo1 { + regulator-name = "vdd_emmc_core"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + }; + + /* uSD slot VDD */ + vdd_usd: ldo2 { + regulator-name = "vdd_usd"; + regulator-min-microvolt = <3100000>; + regulator-max-microvolt = <3100000>; + regulator-boot-on; + }; + + /* uSD slot VDDIO */ + vddio_usd: ldo3 { + regulator-name = "vddio_usd"; + regulator-min-microvolt = <3100000>; + regulator-max-microvolt = <3100000>; + regulator-always-on; + regulator-boot-on; + }; + }; + }; + }; + + sdmmc1: sdhci@78000000 { + status = "okay"; + bus-width = <4>; + + cd-gpios = <&gpio TEGRA_GPIO(I, 5) GPIO_ACTIVE_LOW>; + + vmmc-supply = <&vdd_usd>; + vqmmc-supply = <&vddio_usd>; + }; + + sdmmc4: sdhci@78000600 { + status = "okay"; + bus-width = <8>; + non-removable; + + vmmc-supply = <&vcore_emmc>; + vqmmc-supply = <&vdd_1v8_vio>; + }; + + usb1: usb@7d000000 { + status = "okay"; + dr_mode = "otg"; + nvidia,vbus-gpio = <&gpio TEGRA_GPIO(DD, 3) GPIO_ACTIVE_HIGH>; + }; + + usb-phy@7d000000 { + status = "okay"; + nvidia,hssync-start-delay = <0>; + nvidia,xcvr-lsfslew = <2>; + nvidia,xcvr-lsrslew = <2>; + }; + + usb3: usb@7d008000 { + status = "okay"; + nvidia,vbus-gpio = <&gpio TEGRA_GPIO(CC, 6) GPIO_ACTIVE_HIGH>; + }; + + usb-phy@7d008000 { + status = "okay"; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + + enable-gpios = <&gpio TEGRA_GPIO(H, 2) GPIO_ACTIVE_HIGH>; + power-supply = <&vdd_5v0_bl>; + pwms = <&pwm 0 5000000>; + + brightness-levels = <1 35 70 105 140 175 210 255>; + default-brightness-level = <5>; + }; + + /* PMIC has a built-in 32KHz oscillator which is used by PMC */ + clk32k_in: clock-32k { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + clock-output-names = "pmic-oscillator"; + }; + + gpio-keys { + compatible = "gpio-keys"; + + key-power { + label = "Power"; + gpios = <&gpio TEGRA_GPIO(V, 0) GPIO_ACTIVE_LOW>; + linux,code = <KEY_ENTER>; + }; + + key-volume-up { + label = "Volume Up"; + gpios = <&gpio TEGRA_GPIO(Q, 0) GPIO_ACTIVE_LOW>; + linux,code = <KEY_UP>; + }; + + key-volume-down { + label = "Volume Down"; + gpios = <&gpio TEGRA_GPIO(Q, 1) GPIO_ACTIVE_LOW>; + linux,code = <KEY_DOWN>; + }; + }; + + display-panel { + compatible = "hannstar,hsd101pww2", "simple-panel"; + + power-supply = <&vdd_pnl_reg>; + backlight = <&backlight>; + + display-timings { + timing@0 { + /* 1280x800@60Hz */ + clock-frequency = <68000000>; + + hactive = <1280>; + hfront-porch = <48>; + hback-porch = <18>; + hsync-len = <30>; + + vactive = <800>; + vfront-porch = <3>; + vback-porch = <12>; + vsync-len = <5>; + }; + }; + + port { + panel_input: endpoint { + remote-endpoint = <&bridge_output>; + }; + }; + }; + + /* Texas Instruments SN75LVDS83B LVDS Transmitter */ + lvds-encoder { + compatible = "ti,sn75lvds83", "lvds-encoder"; + + powerdown-gpios = <&gpio TEGRA_GPIO(N, 6) GPIO_ACTIVE_LOW>; + power-supply = <&vdd_3v3_sys>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + bridge_input: endpoint { + remote-endpoint = <&dpi_output>; + }; + }; + + port@1 { + reg = <1>; + + bridge_output: endpoint { + remote-endpoint = <&panel_input>; + }; + }; + }; + }; + + vdd_3v3_sys: regulator-3v { + compatible = "regulator-fixed"; + regulator-name = "vdd_3v3_sys"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + }; + + vdd_pnl_reg: regulator-pnl { + compatible = "regulator-fixed"; + regulator-name = "vdd_panel"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio TEGRA_GPIO(W, 1) GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + vdd_5v0_bl: regulator-bl { + compatible = "regulator-fixed"; + regulator-name = "vdd_5v0_bl"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpio TEGRA_GPIO(H, 3) GPIO_ACTIVE_HIGH>; + enable-active-high; + }; +}; diff --git a/arch/arm/dts/tegra30-wexler-qc750.dts b/arch/arm/dts/tegra30-wexler-qc750.dts index b376b91a7fa..ededbf579fd 100644 --- a/arch/arm/dts/tegra30-wexler-qc750.dts +++ b/arch/arm/dts/tegra30-wexler-qc750.dts @@ -44,6 +44,10 @@ }; }; + bsev@6001b000 { + status = "okay"; + }; + pinmux@70000868 { pinctrl-names = "default"; pinctrl-0 = <&state_default>; diff --git a/arch/arm/dts/tegra30.dtsi b/arch/arm/dts/tegra30.dtsi index d5de1ecaf05..82e843d05be 100644 --- a/arch/arm/dts/tegra30.dtsi +++ b/arch/arm/dts/tegra30.dtsi @@ -373,6 +373,35 @@ */ }; + /* Audio Bitstream Engine */ + bsea@60011000 { + compatible = "nvidia,tegra30-bsea"; + reg = <0x60011000 0x1000>, <0x4000c000 0x4000>; + reg-names = "bsea", "iram-buffer"; + interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "bsea"; + clocks = <&tegra_car TEGRA30_CLK_BSEA>; + resets = <&tegra_car 62>; + reset-names = "bsea"; + status = "disabled"; + }; + + /* Video Bitstream Engine */ + bsev@6001b000 { + compatible = "nvidia,tegra30-bsev"; + reg = <0x6001b000 0x1000>, <0x40008000 0x4000>; + reg-names = "bsev", "iram-buffer"; + interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "bsev"; + clocks = <&tegra_car TEGRA30_CLK_BSEV>, + <&tegra_car TEGRA30_CLK_VDE>; + clock-names = "bsev", "vde"; + resets = <&tegra_car 63>, + <&tegra_car 61>; + reset-names = "bsev", "vde"; + status = "disabled"; + }; + apbmisc@70000800 { compatible = "nvidia,tegra30-apbmisc", "nvidia,tegra20-apbmisc"; reg = <0x70000800 0x64 /* Chip revision */ diff --git a/arch/arm/include/asm/arch-tegra/ap.h b/arch/arm/include/asm/arch-tegra/ap.h index b922b2d30ea..295c3287737 100644 --- a/arch/arm/include/asm/arch-tegra/ap.h +++ b/arch/arm/include/asm/arch-tegra/ap.h @@ -55,6 +55,13 @@ int tegra_get_chip_sku(void); int tegra_get_chip(void); /** + * Returns the pure SOC major version from the HIDREV register + * + * Return: SOC major version + */ +u32 tegra_get_major_version(void); + +/** * Returns the SKU ID from the sku_info register * * Return: SKU ID - see SKU_ID_Txx... diff --git a/arch/arm/include/asm/arch-tegra/crypto.h b/arch/arm/include/asm/arch-tegra/crypto.h index 7646163b97b..930bc842039 100644 --- a/arch/arm/include/asm/arch-tegra/crypto.h +++ b/arch/arm/include/asm/arch-tegra/crypto.h @@ -7,41 +7,36 @@ #ifndef _CRYPTO_H_ #define _CRYPTO_H_ -/** - * Sign a block of data - * - * \param source Source data - * \param length Size of source data - * \param signature Destination address for signature, AES_KEY_LENGTH bytes - */ -int sign_data_block(u8 *source, unsigned int length, u8 *signature); +#define TEGRA_AES_SLOT_SBK 0 /** - * Sign an encrypted block of data + * sign_data_block - Sign a block of data * - * \param source Source data - * \param length Size of source data - * \param signature Destination address for signature, AES_KEY_LENGTH bytes - * \param key AES128 encryption key + * @source Source data + * @length Size of source data in bytes + * @signature Destination address for signature, AES_KEY_LENGTH bytes + * Return: 0 on success, negative value on failure */ -int sign_enc_data_block(u8 *source, unsigned int length, u8 *signature, u8 *key); +int sign_data_block(u8 *source, unsigned int length, u8 *signature); /** - * Encrypt a block of data + * encrypt_data_block - Encrypt a block of data * - * \param source Source data - * \param length Size of source data - * \param key AES128 encryption key + * @source Source data + * @dest Destination data + * @length Size of source data in bytes + * Return: 0 on success, negative value on failure */ -int encrypt_data_block(u8 *source, unsigned int length, u8 *key); +int encrypt_data_block(u8 *source, u8 *dest, unsigned int length); /** - * Decrypt a block of data + * decrypt_data_block - Decrypt a block of data * - * \param source Source data - * \param length Size of source data - * \param key AES128 encryption key + * @source Source data + * @dest Destination data + * @length Size of source data in bytes + * Return: 0 on success, negative value on failure */ -int decrypt_data_block(u8 *source, unsigned int length, u8 *key); +int decrypt_data_block(u8 *source, u8 *dest, unsigned int length); #endif /* #ifndef _CRYPTO_H_ */ diff --git a/arch/arm/include/asm/arch-tegra/dc.h b/arch/arm/include/asm/arch-tegra/dc.h index ab12cc9c7d0..22f8f977cc6 100644 --- a/arch/arm/include/asm/arch-tegra/dc.h +++ b/arch/arm/include/asm/arch-tegra/dc.h @@ -448,6 +448,9 @@ enum win_color_depth_id { #define LVS_OUTPUT_POLARITY_LOW BIT(28) #define LSC0_OUTPUT_POLARITY_LOW BIT(24) +/* DC_COM_PIN_OUTPUT_POLARITY3 0x309 */ +#define LSPI_OUTPUT_POLARITY_LOW BIT(8) + /* DC_COM_PIN_OUTPUT_SELECT6 0x31a */ #define LDC_OUTPUT_SELECT_V_PULSE1 BIT(14) /* 100b */ diff --git a/arch/arm/include/asm/arch-tegra/fuse.h b/arch/arm/include/asm/arch-tegra/fuse.h index f3f2ad8e3f2..631ebbb283c 100644 --- a/arch/arm/include/asm/arch-tegra/fuse.h +++ b/arch/arm/include/asm/arch-tegra/fuse.h @@ -17,8 +17,22 @@ struct fuse_regs { u32 fa; /* 0x148: FUSE_FA */ u32 reserved3[21]; /* 0x14C - 0x19C: */ u32 security_mode; /* 0x1A0: FUSE_SECURITY_MODE */ + u32 sbk[4]; /* 0x1A4 - 0x1B4 */ }; +/* Defines the supported operating modes */ +enum fuse_operating_mode { + MODE_UNDEFINED = 0, + MODE_PRODUCTION = 3, + MODE_ODM_PRODUCTION_SECURE = 4, + MODE_ODM_PRODUCTION_OPEN = 5, +}; + +/** + * Initializes fuse hardware + */ +void tegra_fuse_init(void); + /** * Calculate SoC UID * @@ -26,4 +40,11 @@ struct fuse_regs { */ unsigned long long tegra_chip_uid(void); +/** + * Gives the current operating mode from fuses + * + * @return current operating mode + */ +enum fuse_operating_mode tegra_fuse_get_operation_mode(void); + #endif /* ifndef _FUSE_H_ */ diff --git a/arch/arm/include/asm/arch-tegra/warmboot.h b/arch/arm/include/asm/arch-tegra/warmboot.h index 9a53456370f..4352f1dc5e8 100644 --- a/arch/arm/include/asm/arch-tegra/warmboot.h +++ b/arch/arm/include/asm/arch-tegra/warmboot.h @@ -10,12 +10,6 @@ #define STRAP_OPT_A_RAM_CODE_SHIFT 4 #define STRAP_OPT_A_RAM_CODE_MASK (0xf << STRAP_OPT_A_RAM_CODE_SHIFT) -/* Defines the supported operating modes */ -enum fuse_operating_mode { - MODE_PRODUCTION = 3, - MODE_UNDEFINED, -}; - /* Defines the CMAC-AES-128 hash length in 32 bit words. (128 bits = 4 words) */ enum { HASH_LENGTH = 4 @@ -125,7 +119,6 @@ union scratch3_reg { int warmboot_save_sdram_params(void); int warmboot_prepare_code(u32 seg_address, u32 seg_length); -int sign_data_block(u8 *source, u32 length, u8 *signature); void wb_start(void); /* Start of WB assembly code */ void wb_end(void); /* End of WB assembly code */ diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index c3c352eceb1..32cdfebfc01 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -17,7 +17,9 @@ config TEGRA_CLKRST config TEGRA_CRYPTO bool "Tegra AES128 crypto module" + select DM_AES select AES + select TEGRA_AES config TEGRA_GP_PADCTRL bool diff --git a/arch/arm/mach-tegra/ap.c b/arch/arm/mach-tegra/ap.c index f35bdba4d48..a7938ed7910 100644 --- a/arch/arm/mach-tegra/ap.c +++ b/arch/arm/mach-tegra/ap.c @@ -37,6 +37,14 @@ int tegra_get_chip(void) return rev; } +u32 tegra_get_major_version(void) +{ + struct apb_misc_gp_ctlr *gp = + (struct apb_misc_gp_ctlr *)NV_PA_APB_MISC_GP_BASE; + + return (readl(&gp->hidrev) & HIDREV_MAJORPREV_MASK) >> HIDREV_MAJORPREV_SHIFT; +} + int tegra_get_sku_info(void) { int sku_id; diff --git a/arch/arm/mach-tegra/cpu.h b/arch/arm/mach-tegra/cpu.h index 006aae3d070..5477423f4d0 100644 --- a/arch/arm/mach-tegra/cpu.h +++ b/arch/arm/mach-tegra/cpu.h @@ -71,6 +71,7 @@ void powerup_cpu(void); void reset_A9_cpu(int reset); void start_cpu(u32 reset_vector); int tegra_get_chip(void); +u32 tegra_get_major_version(void); int tegra_get_sku_info(void); int tegra_get_chip_sku(void); void adjust_pllp_out_freqs(void); diff --git a/arch/arm/mach-tegra/crypto.c b/arch/arm/mach-tegra/crypto.c index 49e6a45243a..1005c815b36 100644 --- a/arch/arm/mach-tegra/crypto.c +++ b/arch/arm/mach-tegra/crypto.c @@ -4,164 +4,68 @@ * (C) Copyright 2010 - 2011 NVIDIA Corporation <www.nvidia.com> */ +#include <dm.h> #include <log.h> #include <linux/errno.h> #include <asm/arch-tegra/crypto.h> #include "uboot_aes.h" -static u8 zero_key[16]; - -#define AES_CMAC_CONST_RB 0x87 /* from RFC 4493, Figure 2.2 */ - -enum security_op { - SECURITY_SIGN = 1 << 0, /* Sign the data */ - SECURITY_ENCRYPT = 1 << 1, /* Encrypt the data */ - SECURITY_DECRYPT = 1 << 2, /* Dectypt the data */ -}; - -/** - * Shift a vector left by one bit - * - * \param in Input vector - * \param out Output vector - * \param size Length of vector in bytes - */ -static void left_shift_vector(u8 *in, u8 *out, int size) +int sign_data_block(u8 *source, unsigned int length, u8 *signature) { - int carry = 0; - int i; - - for (i = size - 1; i >= 0; i--) { - out[i] = (in[i] << 1) | carry; - carry = in[i] >> 7; /* get most significant bit */ + struct udevice *dev; + int ret; + + /* Only one AES engine should be present */ + ret = uclass_get_device(UCLASS_AES, 0, &dev); + if (ret) { + log_err("%s: failed to get tegra_aes: %d\n", __func__, ret); + return ret; } -} - -/** - * Sign a block of data, putting the result into dst. - * - * \param key Input AES key, length AES128_KEY_LENGTH - * \param key_schedule Expanded key to use - * \param src Source data of length 'num_aes_blocks' blocks - * \param dst Destination buffer, length AES128_KEY_LENGTH - * \param num_aes_blocks Number of AES blocks to encrypt - */ -static void sign_object(u8 *key, u8 *key_schedule, u8 *src, u8 *dst, - u32 num_aes_blocks) -{ - u8 tmp_data[AES128_KEY_LENGTH]; - u8 iv[AES128_KEY_LENGTH] = {0}; - u8 left[AES128_KEY_LENGTH]; - u8 k1[AES128_KEY_LENGTH]; - u8 *cbc_chain_data; - unsigned int i; - cbc_chain_data = zero_key; /* Convenient array of 0's for IV */ + ret = dm_aes_select_key_slot(dev, 128, TEGRA_AES_SLOT_SBK); + if (ret) + return ret; - /* compute K1 constant needed by AES-CMAC calculation */ - for (i = 0; i < AES128_KEY_LENGTH; i++) - tmp_data[i] = 0; - - aes_cbc_encrypt_blocks(AES128_KEY_LENGTH, key_schedule, iv, - tmp_data, left, 1); - - left_shift_vector(left, k1, sizeof(left)); - - if ((left[0] >> 7) != 0) /* get MSB of L */ - k1[AES128_KEY_LENGTH - 1] ^= AES_CMAC_CONST_RB; - - /* compute the AES-CMAC value */ - for (i = 0; i < num_aes_blocks; i++) { - /* Apply the chain data */ - aes_apply_cbc_chain_data(cbc_chain_data, src, tmp_data); - - /* for the final block, XOR K1 into the IV */ - if (i == num_aes_blocks - 1) - aes_apply_cbc_chain_data(tmp_data, k1, tmp_data); - - /* encrypt the AES block */ - aes_encrypt(AES128_KEY_LENGTH, tmp_data, - key_schedule, dst); - - debug("sign_obj: block %d of %d\n", i, num_aes_blocks); - - /* Update pointers for next loop. */ - cbc_chain_data = dst; - src += AES128_KEY_LENGTH; - } + return dm_aes_cmac(dev, source, signature, + DIV_ROUND_UP(length, AES_BLOCK_LENGTH)); } -/** - * Decrypt, encrypt or sign a block of data (depending on security mode). - * - * \param key Input AES key, length AES128_KEY_LENGTH - * \param oper Security operations mask to perform (enum security_op) - * \param src Source data - * \param length Size of source data - * \param sig_dst Destination address for signature, AES128_KEY_LENGTH bytes - */ -static int tegra_crypto_core(u8 *key, enum security_op oper, u8 *src, - u32 length, u8 *sig_dst) +int encrypt_data_block(u8 *source, u8 *dest, unsigned int length) { - u32 num_aes_blocks; - u8 key_schedule[AES128_EXPAND_KEY_LENGTH]; - u8 iv[AES128_KEY_LENGTH] = {0}; - - debug("%s: length = %d\n", __func__, length); - - aes_expand_key(key, AES128_KEY_LENGTH, key_schedule); - - num_aes_blocks = (length + AES128_KEY_LENGTH - 1) / AES128_KEY_LENGTH; - - if (oper & SECURITY_DECRYPT) { - /* Perform this in place, resulting in src being decrypted. */ - debug("%s: begin decryption\n", __func__); - aes_cbc_decrypt_blocks(AES128_KEY_LENGTH, key_schedule, iv, src, - src, num_aes_blocks); - debug("%s: end decryption\n", __func__); - } - - if (oper & SECURITY_ENCRYPT) { - /* Perform this in place, resulting in src being encrypted. */ - debug("%s: begin encryption\n", __func__); - aes_cbc_encrypt_blocks(AES128_KEY_LENGTH, key_schedule, iv, src, - src, num_aes_blocks); - debug("%s: end encryption\n", __func__); - } - - if (oper & SECURITY_SIGN) { - /* encrypt the data, overwriting the result in signature. */ - debug("%s: begin signing\n", __func__); - sign_object(key, key_schedule, src, sig_dst, num_aes_blocks); - debug("%s: end signing\n", __func__); + struct udevice *dev; + int ret; + + /* Only one AES engine should be present */ + ret = uclass_get_device(UCLASS_AES, 0, &dev); + if (ret) { + log_err("%s: failed to get tegra_aes: %d\n", __func__, ret); + return ret; } - return 0; -} + ret = dm_aes_select_key_slot(dev, 128, TEGRA_AES_SLOT_SBK); + if (ret) + return ret; -/** - * Tegra crypto group - */ -int sign_data_block(u8 *source, unsigned int length, u8 *signature) -{ - return tegra_crypto_core(zero_key, SECURITY_SIGN, source, - length, signature); + return dm_aes_cbc_encrypt(dev, (u8 *)AES_ZERO_BLOCK, source, dest, + DIV_ROUND_UP(length, AES_BLOCK_LENGTH)); } -int sign_enc_data_block(u8 *source, unsigned int length, u8 *signature, u8 *key) +int decrypt_data_block(u8 *source, u8 *dest, unsigned int length) { - return tegra_crypto_core(key, SECURITY_SIGN, source, - length, signature); -} + struct udevice *dev; + int ret; + + /* Only one AES engine should be present */ + ret = uclass_get_device(UCLASS_AES, 0, &dev); + if (ret) { + log_err("%s: failed to get tegra_aes: %d\n", __func__, ret); + return ret; + } -int encrypt_data_block(u8 *source, unsigned int length, u8 *key) -{ - return tegra_crypto_core(key, SECURITY_ENCRYPT, source, - length, NULL); -} + ret = dm_aes_select_key_slot(dev, 128, TEGRA_AES_SLOT_SBK); + if (ret) + return ret; -int decrypt_data_block(u8 *source, unsigned int length, u8 *key) -{ - return tegra_crypto_core(key, SECURITY_DECRYPT, source, - length, NULL); + return dm_aes_cbc_decrypt(dev, (u8 *)AES_ZERO_BLOCK, source, dest, + DIV_ROUND_UP(length, AES_BLOCK_LENGTH)); } diff --git a/arch/arm/mach-tegra/fuse.c b/arch/arm/mach-tegra/fuse.c index e9b5259ac70..abdf6504161 100644 --- a/arch/arm/mach-tegra/fuse.c +++ b/arch/arm/mach-tegra/fuse.c @@ -39,7 +39,7 @@ static u32 tegra_fuse_readl(unsigned long offset) return readl(NV_PA_FUSE_BASE + offset); } -static void tegra_fuse_init(void) +void tegra_fuse_init(void) { u32 reg; @@ -49,8 +49,11 @@ static void tegra_fuse_init(void) * this bit fuse region will not work. */ reg = readl_relaxed(NV_PA_CLK_RST_BASE + 0x48); - reg |= BIT(28); - writel(reg, NV_PA_CLK_RST_BASE + 0x48); + + if (reg & BIT(28)) + return; + + writel(reg | BIT(28), NV_PA_CLK_RST_BASE + 0x48); clock_enable(PERIPH_ID_FUSE); udelay(2); @@ -148,3 +151,57 @@ unsigned long long tegra_chip_uid(void) return uid; } + +static int tegra_is_production_mode_fuse_set(struct fuse_regs *fuse) +{ + return readl(&fuse->production_mode); +} + +static int tegra_is_odm_production_mode_fuse_set(struct fuse_regs *fuse) +{ + return readl(&fuse->security_mode); +} + +static int tegra_is_failure_analysis_mode(struct fuse_regs *fuse) +{ + return readl(&fuse->fa); +} + +static int tegra_is_sbk_zeroes(struct fuse_regs *fuse) +{ + int i; + + for (i = 0; i < 4; i++) + if (readl(&fuse->sbk[i])) + return 0; + + return 1; +} + +static int tegra_is_production_mode(struct fuse_regs *fuse) +{ + if (!tegra_get_major_version()) + return 1; + + return !tegra_is_failure_analysis_mode(fuse) && + tegra_is_production_mode_fuse_set(fuse); +} + +enum fuse_operating_mode tegra_fuse_get_operation_mode(void) +{ + struct fuse_regs *fuse = (struct fuse_regs *)NV_PA_FUSE_BASE; + + tegra_fuse_init(); + + if (tegra_is_production_mode(fuse)) { + if (!tegra_is_odm_production_mode_fuse_set(fuse)) + return MODE_PRODUCTION; + else + if (tegra_is_sbk_zeroes(fuse)) + return MODE_ODM_PRODUCTION_OPEN; + else + return MODE_ODM_PRODUCTION_SECURE; + } + + return MODE_UNDEFINED; +} diff --git a/arch/arm/mach-tegra/tegra124/bct.c b/arch/arm/mach-tegra/tegra124/bct.c index 4dc4b7138ab..676b68dc5de 100644 --- a/arch/arm/mach-tegra/tegra124/bct.c +++ b/arch/arm/mach-tegra/tegra124/bct.c @@ -9,12 +9,10 @@ #include <vsprintf.h> #include <linux/string.h> #include <asm/arch-tegra/crypto.h> +#include <asm/arch-tegra/fuse.h> #include "bct.h" #include "uboot_aes.h" -/* Device with "sbk burned: false" will expose zero key */ -const u8 nosbk[AES128_KEY_LENGTH] = { 0 }; - /* * @param bct boot config table start in RAM * @param ect bootloader start in RAM @@ -26,29 +24,25 @@ static int bct_patch(u8 *bct, u8 *ebt, u32 ebt_size) struct nvboot_config_table *bct_tbl = NULL; u8 ebt_hash[AES128_KEY_LENGTH] = { 0 }; u8 bct_hash[AES128_KEY_LENGTH] = { 0 }; - u8 sbk[AES128_KEY_LENGTH] = { 0 }; u8 *sbct = bct + UBCT_LENGTH; bool encrypted; int ret; ebt_size = roundup(ebt_size, EBT_ALIGNMENT); - memcpy(sbk, (u8 *)(bct + UBCT_LENGTH + SBCT_LENGTH), - NVBOOT_CMAC_AES_HASH_LENGTH * 4); - - encrypted = memcmp(&sbk, &nosbk, AES128_KEY_LENGTH); + encrypted = tegra_fuse_get_operation_mode() == MODE_ODM_PRODUCTION_SECURE; if (encrypted) { - ret = decrypt_data_block(sbct, SBCT_LENGTH, sbk); + ret = decrypt_data_block(sbct, sbct, SBCT_LENGTH); if (ret) return 1; - ret = encrypt_data_block(ebt, ebt_size, sbk); + ret = encrypt_data_block(ebt, ebt, ebt_size); if (ret) return 1; } - ret = sign_enc_data_block(ebt, ebt_size, ebt_hash, sbk); + ret = sign_data_block(ebt, ebt_size, ebt_hash); if (ret) return 1; @@ -61,12 +55,12 @@ static int bct_patch(u8 *bct, u8 *ebt, u32 ebt_size) bct_tbl->bootloader[0].length = ebt_size; if (encrypted) { - ret = encrypt_data_block(sbct, SBCT_LENGTH, sbk); + ret = encrypt_data_block(sbct, sbct, SBCT_LENGTH); if (ret) return 1; } - ret = sign_enc_data_block(sbct, SBCT_LENGTH, bct_hash, sbk); + ret = sign_data_block(sbct, SBCT_LENGTH, bct_hash); if (ret) return 1; diff --git a/arch/arm/mach-tegra/tegra20/Kconfig b/arch/arm/mach-tegra/tegra20/Kconfig index bedbedade7b..b07b5a15585 100644 --- a/arch/arm/mach-tegra/tegra20/Kconfig +++ b/arch/arm/mach-tegra/tegra20/Kconfig @@ -54,6 +54,10 @@ config TARGET_SEABOARD select TEGRA_LP0 select TEGRA_PMU +config TARGET_SAMSUNG_N1 + bool "Samsung Tegra20 N1 board" + select BOARD_LATE_INIT + config TARGET_STAR bool "LG Tegra20 Star board" select BOARD_LATE_INIT @@ -92,6 +96,7 @@ source "board/compal/paz00/Kconfig" source "board/acer/picasso/Kconfig" source "board/avionic-design/plutux/Kconfig" source "board/nvidia/seaboard/Kconfig" +source "board/samsung/n1/Kconfig" source "board/lg/star/Kconfig" source "board/avionic-design/tec/Kconfig" source "board/asus/transformer-t20/Kconfig" diff --git a/arch/arm/mach-tegra/tegra20/bct.c b/arch/arm/mach-tegra/tegra20/bct.c index 253cb243676..0270cf592c1 100644 --- a/arch/arm/mach-tegra/tegra20/bct.c +++ b/arch/arm/mach-tegra/tegra20/bct.c @@ -9,12 +9,10 @@ #include <vsprintf.h> #include <linux/string.h> #include <asm/arch-tegra/crypto.h> +#include <asm/arch-tegra/fuse.h> #include "bct.h" #include "uboot_aes.h" -/* Device with "sbk burned: false" will expose zero key */ -const u8 nosbk[AES128_KEY_LENGTH] = { 0 }; - /* * @param bct boot config table start in RAM * @param ect bootloader start in RAM @@ -25,7 +23,6 @@ static int bct_patch(u8 *bct, u8 *ebt, u32 ebt_size) { struct nvboot_config_table *bct_tbl = NULL; u8 ebt_hash[AES128_KEY_LENGTH] = { 0 }; - u8 sbk[AES128_KEY_LENGTH] = { 0 }; u8 *bct_hash = bct; bool encrypted; int ret; @@ -34,22 +31,19 @@ static int bct_patch(u8 *bct, u8 *ebt, u32 ebt_size) ebt_size = roundup(ebt_size, EBT_ALIGNMENT); - memcpy(sbk, (u8 *)(bct + BCT_LENGTH), - NVBOOT_CMAC_AES_HASH_LENGTH * 4); - - encrypted = memcmp(&sbk, &nosbk, AES128_KEY_LENGTH); + encrypted = tegra_fuse_get_operation_mode() == MODE_ODM_PRODUCTION_SECURE; if (encrypted) { - ret = decrypt_data_block(bct, BCT_LENGTH, sbk); + ret = decrypt_data_block(bct, bct, BCT_LENGTH); if (ret) return 1; - ret = encrypt_data_block(ebt, ebt_size, sbk); + ret = encrypt_data_block(ebt, ebt, ebt_size); if (ret) return 1; } - ret = sign_enc_data_block(ebt, ebt_size, ebt_hash, sbk); + ret = sign_data_block(ebt, ebt_size, ebt_hash); if (ret) return 1; @@ -62,12 +56,12 @@ static int bct_patch(u8 *bct, u8 *ebt, u32 ebt_size) bct_tbl->bootloader[0].length = ebt_size; if (encrypted) { - ret = encrypt_data_block(bct, BCT_LENGTH, sbk); + ret = encrypt_data_block(bct, bct, BCT_LENGTH); if (ret) return 1; } - ret = sign_enc_data_block(bct, BCT_LENGTH, bct_hash, sbk); + ret = sign_data_block(bct, BCT_LENGTH, bct_hash); if (ret) return 1; diff --git a/arch/arm/mach-tegra/tegra20/warmboot.c b/arch/arm/mach-tegra/tegra20/warmboot.c index 18034c83a1c..3fd39fe3c1a 100644 --- a/arch/arm/mach-tegra/tegra20/warmboot.c +++ b/arch/arm/mach-tegra/tegra20/warmboot.c @@ -19,6 +19,7 @@ #include <asm/arch-tegra/pmc.h> #include <asm/arch-tegra/fuse.h> #include <asm/arch-tegra/warmboot.h> +#include <asm/arch-tegra/crypto.h> DECLARE_GLOBAL_DATA_PTR; @@ -182,98 +183,36 @@ int warmboot_save_sdram_params(void) return 0; } -static u32 get_major_version(void) +static void determine_crypto_options(int *is_encrypted, int *is_signed) { - u32 major_id; - struct apb_misc_gp_ctlr *gp = - (struct apb_misc_gp_ctlr *)NV_PA_APB_MISC_GP_BASE; - - major_id = (readl(&gp->hidrev) & HIDREV_MAJORPREV_MASK) >> - HIDREV_MAJORPREV_SHIFT; - return major_id; -} - -static int is_production_mode_fuse_set(struct fuse_regs *fuse) -{ - return readl(&fuse->production_mode); -} - -static int is_odm_production_mode_fuse_set(struct fuse_regs *fuse) -{ - return readl(&fuse->security_mode); -} - -static int is_failure_analysis_mode(struct fuse_regs *fuse) -{ - return readl(&fuse->fa); -} - -static int ap20_is_odm_production_mode(void) -{ - struct fuse_regs *fuse = (struct fuse_regs *)NV_PA_FUSE_BASE; - - if (!is_failure_analysis_mode(fuse) && - is_odm_production_mode_fuse_set(fuse)) - return 1; - else - return 0; -} - -static int ap20_is_production_mode(void) -{ - struct fuse_regs *fuse = (struct fuse_regs *)NV_PA_FUSE_BASE; - - if (get_major_version() == 0) - return 1; - - if (!is_failure_analysis_mode(fuse) && - is_production_mode_fuse_set(fuse) && - !is_odm_production_mode_fuse_set(fuse)) - return 1; - else - return 0; -} - -static enum fuse_operating_mode fuse_get_operation_mode(void) -{ - u32 chip_id; - struct apb_misc_gp_ctlr *gp = - (struct apb_misc_gp_ctlr *)NV_PA_APB_MISC_GP_BASE; - - chip_id = (readl(&gp->hidrev) & HIDREV_CHIPID_MASK) >> - HIDREV_CHIPID_SHIFT; - if (chip_id == CHIPID_TEGRA20) { - if (ap20_is_odm_production_mode()) { - printf("!! odm_production_mode is not supported !!\n"); - return MODE_UNDEFINED; - } else - if (ap20_is_production_mode()) - return MODE_PRODUCTION; - else - return MODE_UNDEFINED; - } - return MODE_UNDEFINED; -} - -static void determine_crypto_options(int *is_encrypted, int *is_signed, - int *use_zero_key) -{ - switch (fuse_get_operation_mode()) { + switch (tegra_fuse_get_operation_mode()) { + case MODE_ODM_PRODUCTION_SECURE: + *is_encrypted = 1; + *is_signed = 1; + break; + case MODE_ODM_PRODUCTION_OPEN: case MODE_PRODUCTION: *is_encrypted = 0; *is_signed = 1; - *use_zero_key = 1; break; case MODE_UNDEFINED: default: *is_encrypted = 0; *is_signed = 0; - *use_zero_key = 0; break; } } -static int sign_wb_code(u32 start, u32 length, int use_zero_key) +static int encrypt_wb_code(u8 *source, u8 *destination, u32 length) +{ + source += offsetof(struct wb_header, random_aes_block); + destination += offsetof(struct wb_header, random_aes_block); + length -= offsetof(struct wb_header, random_aes_block); + + return encrypt_data_block(source, destination, length); +} + +static int sign_wb_code(u32 start, u32 length) { int err; u8 *source; /* Pointer to source */ @@ -295,10 +234,9 @@ int warmboot_prepare_code(u32 seg_address, u32 seg_length) struct wb_header *dst_header; /* Pointer to dest WB header */ int is_encrypted; /* Segment is encrypted */ int is_signed; /* Segment is signed */ - int use_zero_key; /* Use key of all zeros */ /* Determine crypto options. */ - determine_crypto_options(&is_encrypted, &is_signed, &use_zero_key); + determine_crypto_options(&is_encrypted, &is_signed); /* Get the actual code limits. */ length = roundup(((u32)wb_end - (u32)wb_start), 16); @@ -346,18 +284,15 @@ int warmboot_prepare_code(u32 seg_address, u32 seg_length) dst_header->entry_point = NV_WB_RUN_ADDRESS; dst_header->code_length = length; - if (is_encrypted) { - printf("!!!! Encryption is not supported !!!!\n"); - dst_header->length_insecure = 0; - err = -EACCES; - goto fail; - } else - /* copy the wb code directly following dst_header. */ - memcpy((char *)(dst_header+1), (char *)wb_start, length); + if (is_encrypted) + encrypt_wb_code((u8 *)wb_start, (u8 *)dst_header, + length + sizeof(struct wb_header)); + else + /* copy the wb code directly following dst_header */ + memcpy((char *)(dst_header + 1), (char *)wb_start, length); if (is_signed) - err = sign_wb_code(seg_address, dst_header->length_insecure, - use_zero_key); + err = sign_wb_code(seg_address, dst_header->length_insecure); fail: if (err) diff --git a/arch/arm/mach-tegra/tegra30/Kconfig b/arch/arm/mach-tegra/tegra30/Kconfig index b5099ce67fc..4da67b19990 100644 --- a/arch/arm/mach-tegra/tegra30/Kconfig +++ b/arch/arm/mach-tegra/tegra30/Kconfig @@ -16,6 +16,10 @@ config TARGET_CARDHU bool "NVIDIA Tegra30 Cardhu evaluation board" select BOARD_LATE_INIT +config TARGET_CHAGALL + bool "Pegatron Tegra30 Chagall board" + select BOARD_LATE_INIT + config TARGET_COLIBRI_T30 bool "Toradex Colibri T30 board" select BOARD_LATE_INIT @@ -64,6 +68,7 @@ config SYS_SOC source "board/toradex/apalis_t30/Kconfig" source "board/nvidia/beaver/Kconfig" source "board/nvidia/cardhu/Kconfig" +source "board/pegatron/chagall/Kconfig" source "board/toradex/colibri_t30/Kconfig" source "board/htc/endeavoru/Kconfig" source "board/asus/grouper/Kconfig" diff --git a/arch/arm/mach-tegra/tegra30/bct.c b/arch/arm/mach-tegra/tegra30/bct.c index 398ba1de386..de668214517 100644 --- a/arch/arm/mach-tegra/tegra30/bct.c +++ b/arch/arm/mach-tegra/tegra30/bct.c @@ -9,12 +9,10 @@ #include <vsprintf.h> #include <linux/string.h> #include <asm/arch-tegra/crypto.h> +#include <asm/arch-tegra/fuse.h> #include "bct.h" #include "uboot_aes.h" -/* Device with "sbk burned: false" will expose zero key */ -const u8 nosbk[AES128_KEY_LENGTH] = { 0 }; - /* * @param bct boot config table start in RAM * @param ect bootloader start in RAM @@ -25,7 +23,6 @@ static int bct_patch(u8 *bct, u8 *ebt, u32 ebt_size) { struct nvboot_config_table *bct_tbl = NULL; u8 ebt_hash[AES128_KEY_LENGTH] = { 0 }; - u8 sbk[AES128_KEY_LENGTH] = { 0 }; u8 *bct_hash = bct; bool encrypted; int ret; @@ -34,22 +31,19 @@ static int bct_patch(u8 *bct, u8 *ebt, u32 ebt_size) ebt_size = roundup(ebt_size, EBT_ALIGNMENT); - memcpy(sbk, (u8 *)(bct + BCT_LENGTH), - NVBOOT_CMAC_AES_HASH_LENGTH * 4); - - encrypted = memcmp(&sbk, &nosbk, AES128_KEY_LENGTH); + encrypted = tegra_fuse_get_operation_mode() == MODE_ODM_PRODUCTION_SECURE; if (encrypted) { - ret = decrypt_data_block(bct, BCT_LENGTH, sbk); + ret = decrypt_data_block(bct, bct, BCT_LENGTH); if (ret) return 1; - ret = encrypt_data_block(ebt, ebt_size, sbk); + ret = encrypt_data_block(ebt, ebt, ebt_size); if (ret) return 1; } - ret = sign_enc_data_block(ebt, ebt_size, ebt_hash, sbk); + ret = sign_data_block(ebt, ebt_size, ebt_hash); if (ret) return 1; @@ -62,12 +56,12 @@ static int bct_patch(u8 *bct, u8 *ebt, u32 ebt_size) bct_tbl->bootloader[0].length = ebt_size; if (encrypted) { - ret = encrypt_data_block(bct, BCT_LENGTH, sbk); + ret = encrypt_data_block(bct, bct, BCT_LENGTH); if (ret) return 1; } - ret = sign_enc_data_block(bct, BCT_LENGTH, bct_hash, sbk); + ret = sign_data_block(bct, BCT_LENGTH, bct_hash); if (ret) return 1; diff --git a/board/pegatron/chagall/Kconfig b/board/pegatron/chagall/Kconfig new file mode 100644 index 00000000000..8c229d0e333 --- /dev/null +++ b/board/pegatron/chagall/Kconfig @@ -0,0 +1,13 @@ +if TARGET_CHAGALL + +config SYS_BOARD + default "chagall" + +config SYS_VENDOR + default "pegatron" + +config TEGRA_BOARD_STRING + string "Default Tegra board name" + default "Pegatron Chagall" + +endif diff --git a/board/pegatron/chagall/MAINTAINERS b/board/pegatron/chagall/MAINTAINERS new file mode 100644 index 00000000000..5ebd5940f42 --- /dev/null +++ b/board/pegatron/chagall/MAINTAINERS @@ -0,0 +1,7 @@ +CHAGALL BOARD +M: Svyatoslav Ryhel <clamor95@gmail.com> +S: Maintained +F: arch/arm/dts/tegra30-pegatron-chagall.dts +F: board/pegatron/chagall/ +F: configs/chagall_defconfig +F: doc/board/pegatron/chagall.rst diff --git a/board/pegatron/chagall/Makefile b/board/pegatron/chagall/Makefile new file mode 100644 index 00000000000..17cfef50987 --- /dev/null +++ b/board/pegatron/chagall/Makefile @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2010-2012 +# NVIDIA Corporation <www.nvidia.com> +# +# (C) Copyright 2021 +# Svyatoslav Ryhel <clamor95@gmail.com> + +obj-$(CONFIG_XPL_BUILD) += chagall-spl.o + +obj-y += chagall.o diff --git a/board/pegatron/chagall/chagall-spl.c b/board/pegatron/chagall/chagall-spl.c new file mode 100644 index 00000000000..6c271973ada --- /dev/null +++ b/board/pegatron/chagall/chagall-spl.c @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Chagall SPL stage configuration + * + * (C) Copyright 2010-2013 + * NVIDIA Corporation <www.nvidia.com> + * + * (C) Copyright 2021 + * Svyatoslav Ryhel <clamor95@gmail.com> + */ + +#include <asm/arch/tegra.h> +#include <asm/arch-tegra/tegra_i2c.h> +#include <linux/delay.h> + +#define TPS65911_I2C_ADDR (0x2D << 1) +#define TPS65911_VDDCTRL_OP_REG 0x28 +#define TPS65911_VDDCTRL_SR_REG 0x27 +#define TPS65911_VDDCTRL_OP_DATA (0x2400 | TPS65911_VDDCTRL_OP_REG) +#define TPS65911_VDDCTRL_SR_DATA (0x0100 | TPS65911_VDDCTRL_SR_REG) + +#define TPS62361B_I2C_ADDR (0x60 << 1) +#define TPS62361B_SET3_REG 0x03 +#define TPS62361B_SET3_DATA (0x4600 | TPS62361B_SET3_REG) + +void pmic_enable_cpu_vdd(void) +{ + /* Set VDD_CORE to 1.200V. */ + tegra_i2c_ll_write(TPS62361B_I2C_ADDR, TPS62361B_SET3_DATA); + + udelay(1000); + + /* + * Bring up CPU VDD via the TPS65911x PMIC on the DVC I2C bus. + * First set VDD to 1.0125V, then enable the VDD regulator. + */ + tegra_i2c_ll_write(TPS65911_I2C_ADDR, TPS65911_VDDCTRL_OP_DATA); + udelay(1000); + tegra_i2c_ll_write(TPS65911_I2C_ADDR, TPS65911_VDDCTRL_SR_DATA); + udelay(10 * 1000); +} diff --git a/board/pegatron/chagall/chagall.c b/board/pegatron/chagall/chagall.c new file mode 100644 index 00000000000..1412c4f9b60 --- /dev/null +++ b/board/pegatron/chagall/chagall.c @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2010-2013 + * NVIDIA Corporation <www.nvidia.com> + * + * (C) Copyright 2021 + * Svyatoslav Ryhel <clamor95@gmail.com> + */ + +/* Chagall derives from Cardhu board */ + +#include <fdt_support.h> + +#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP) +int ft_board_setup(void *blob, struct bd_info *bd) +{ + /* Remove TrustZone nodes */ + fdt_del_node_and_alias(blob, "/firmware"); + fdt_del_node_and_alias(blob, "/reserved-memory/trustzone@bfe00000"); + + return 0; +} +#endif diff --git a/board/pegatron/chagall/chagall.env b/board/pegatron/chagall/chagall.env new file mode 100644 index 00000000000..68bf51bdc3c --- /dev/null +++ b/board/pegatron/chagall/chagall.env @@ -0,0 +1,9 @@ +button_cmd_0_name=Volume Down +button_cmd_0=bootmenu + +bootmenu_0=mount external storage=usb start && ums 0 mmc 1; bootmenu +bootmenu_1=fastboot=echo Starting Fastboot protocol ...; fastboot usb 0; bootmenu +bootmenu_2=reboot RCM=enterrcm +bootmenu_3=reboot=reset +bootmenu_4=power off=poweroff +bootmenu_delay=-1 diff --git a/board/samsung/n1/Kconfig b/board/samsung/n1/Kconfig new file mode 100644 index 00000000000..a5e5edda9e2 --- /dev/null +++ b/board/samsung/n1/Kconfig @@ -0,0 +1,13 @@ +if TARGET_SAMSUNG_N1 + +config SYS_BOARD + default "n1" + +config SYS_VENDOR + default "samsung" + +config TEGRA_BOARD_STRING + string "Default Tegra board name" + default "Samsung N1" + +endif diff --git a/board/samsung/n1/MAINTAINERS b/board/samsung/n1/MAINTAINERS new file mode 100644 index 00000000000..798cb56cd37 --- /dev/null +++ b/board/samsung/n1/MAINTAINERS @@ -0,0 +1,9 @@ +N1 BOARD +M: Ion Agorria <ion@agorria.com> +M: Svyatoslav Ryhel <clamor95@gmail.com> +S: Maintained +F: arch/arm/dts/tegra20-samsung-bose.dts +F: arch/arm/dts/tegra20-samsung-n1.dts +F: board/samsung/n1/ +F: configs/n1_defconfig +F: doc/board/samsung/n1.rst diff --git a/board/samsung/n1/bose.config b/board/samsung/n1/bose.config new file mode 100644 index 00000000000..6d6d9d3f2ce --- /dev/null +++ b/board/samsung/n1/bose.config @@ -0,0 +1,6 @@ +CONFIG_DEFAULT_DEVICE_TREE="tegra20-samsung-bose" +CONFIG_SYS_PROMPT="Tegra20 (Bose) # " +# CONFIG_VIDEO_BRIDGE_SAMSUNG_CMC623 is not set +# CONFIG_BACKLIGHT_SAMSUNG_CMC623 is not set +# CONFIG_VIDEO_LCD_SONY_L4F00430T01 is not set +CONFIG_VIDEO_LCD_SAMSUNG_S6E63M0=y diff --git a/board/samsung/n1/n1.env b/board/samsung/n1/n1.env new file mode 100644 index 00000000000..e2b883dbc10 --- /dev/null +++ b/board/samsung/n1/n1.env @@ -0,0 +1,16 @@ +#include <env/nvidia/prod_upd.env> + +button_cmd_0_name=Volume Down +button_cmd_0=bootmenu + +boot_block_size_r=0x80000 +boot_block_size=0x400 +boot_dev=1 + +bootmenu_0=mount internal storage=usb start && ums 0 mmc 0; bootmenu +bootmenu_1=mount external storage=usb start && ums 0 mmc 1; bootmenu +bootmenu_2=fastboot=echo Starting Fastboot protocol ...; fastboot usb 0; bootmenu +bootmenu_3=reboot RCM=enterrcm +bootmenu_4=reboot=reset +bootmenu_5=power off=poweroff +bootmenu_delay=-1 diff --git a/cmd/bdinfo.c b/cmd/bdinfo.c index ae9e1923eac..20c8c97f0cd 100644 --- a/cmd/bdinfo.c +++ b/cmd/bdinfo.c @@ -46,6 +46,7 @@ void bdinfo_print_num_ll(const char *name, unsigned long long value) static void print_eth(void) { const int idx = eth_get_dev_index(); + char ipstr[] = "ipaddr\0\0"; uchar enetaddr[6]; char name[10]; int ret; @@ -62,7 +63,11 @@ static void print_eth(void) printf("%-12s= (not set)\n", name); else printf("%-12s= %pM\n", name, enetaddr); - printf("IP addr = %s\n", env_get("ipaddr")); + + if (idx > 0) + sprintf(ipstr, "ipaddr%d", idx); + + printf("IP addr = %s\n", env_get(ipstr)); } void bdinfo_print_mhz(const char *name, unsigned long hz) diff --git a/configs/chagall_defconfig b/configs/chagall_defconfig new file mode 100644 index 00000000000..9ad5fb98a8a --- /dev/null +++ b/configs/chagall_defconfig @@ -0,0 +1,80 @@ +CONFIG_ARM=y +CONFIG_ARCH_TEGRA=y +CONFIG_SUPPORT_PASSING_ATAGS=y +CONFIG_CMDLINE_TAG=y +CONFIG_INITRD_TAG=y +CONFIG_TEXT_BASE=0x80110000 +CONFIG_NR_DRAM_BANKS=2 +CONFIG_ENV_SOURCE_FILE="chagall" +CONFIG_ENV_SIZE=0x3000 +CONFIG_ENV_OFFSET=0xFFFFD000 +CONFIG_DEFAULT_DEVICE_TREE="tegra30-pegatron-chagall" +CONFIG_SPL_STACK=0x800ffffc +CONFIG_SPL_TEXT_BASE=0x80108000 +CONFIG_SYS_LOAD_ADDR=0x82000000 +CONFIG_TEGRA30=y +CONFIG_TARGET_CHAGALL=y +CONFIG_BUTTON_CMD=y +CONFIG_BOOTDELAY=0 +CONFIG_AUTOBOOT_KEYED=y +CONFIG_AUTOBOOT_KEYED_CTRLC=y +CONFIG_OF_BOARD_SETUP=y +CONFIG_OF_SYSTEM_SETUP=y +CONFIG_BOOTCOMMAND="bootflow scan; echo 'Boot configuration not found... Power off in 3 sec'; sleep 3; poweroff" +CONFIG_SYS_PBSIZE=2084 +CONFIG_SPL_FOOTPRINT_LIMIT=y +CONFIG_SPL_MAX_FOOTPRINT=0x8000 +# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set +CONFIG_SPL_HAVE_INIT_STACK=y +CONFIG_SPL_SYS_MALLOC=y +CONFIG_SPL_HAS_CUSTOM_MALLOC_START=y +CONFIG_SPL_CUSTOM_SYS_MALLOC_ADDR=0x80090000 +CONFIG_SPL_SYS_MALLOC_SIZE=0x10000 +CONFIG_SYS_PROMPT="Tegra30 (Chagall) # " +# CONFIG_CMD_BOOTEFI_BOOTMGR is not set +CONFIG_CMD_BOOTMENU=y +# CONFIG_CMD_IMI is not set +CONFIG_CMD_GPIO=y +CONFIG_CMD_I2C=y +CONFIG_CMD_MMC=y +CONFIG_CMD_POWEROFF=y +CONFIG_CMD_USB=y +CONFIG_CMD_USB_MASS_STORAGE=y +CONFIG_CMD_UMS_ABORT_KEYED=y +# CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_PAUSE=y +CONFIG_CMD_REGULATOR=y +CONFIG_CMD_EXT4_WRITE=y +# CONFIG_SPL_DOS_PARTITION is not set +# CONFIG_SPL_EFI_PARTITION is not set +CONFIG_ENV_OVERWRITE=y +CONFIG_SYS_RELOC_GD_ENV_ADDR=y +CONFIG_SYS_MMC_ENV_PART=2 +CONFIG_BUTTON=y +CONFIG_USB_FUNCTION_FASTBOOT=y +CONFIG_FASTBOOT_BUF_ADDR=0x91000000 +CONFIG_FASTBOOT_BUF_SIZE=0x10000000 +CONFIG_FASTBOOT_FLASH=y +CONFIG_FASTBOOT_FLASH_MMC_DEV=0 +CONFIG_FASTBOOT_CMD_OEM_FORMAT=y +CONFIG_SYS_I2C_TEGRA=y +CONFIG_BUTTON_KEYBOARD=y +CONFIG_DM_PMIC=y +CONFIG_DM_PMIC_TPS65910=y +CONFIG_DM_REGULATOR=y +CONFIG_DM_REGULATOR_FIXED=y +CONFIG_DM_REGULATOR_TPS65911=y +CONFIG_PWM_TEGRA=y +CONFIG_SYS_NS16550=y +CONFIG_SYSRESET_TPS65910=y +CONFIG_USB=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_TEGRA=y +CONFIG_USB_KEYBOARD=y +CONFIG_USB_GADGET=y +CONFIG_CI_UDC=y +CONFIG_VIDEO=y +# CONFIG_VIDEO_LOGO is not set +CONFIG_VIDEO_BRIDGE=y +CONFIG_VIDEO_BRIDGE_LVDS_CODEC=y +CONFIG_VIDEO_TEGRA=y diff --git a/configs/n1_defconfig b/configs/n1_defconfig new file mode 100644 index 00000000000..da76c59412d --- /dev/null +++ b/configs/n1_defconfig @@ -0,0 +1,92 @@ +CONFIG_ARM=y +CONFIG_ARCH_TEGRA=y +CONFIG_SUPPORT_PASSING_ATAGS=y +CONFIG_CMDLINE_TAG=y +CONFIG_INITRD_TAG=y +CONFIG_TEXT_BASE=0x00110000 +CONFIG_NR_DRAM_BANKS=2 +CONFIG_ENV_SOURCE_FILE="n1" +CONFIG_ENV_SIZE=0x3000 +CONFIG_ENV_OFFSET=0xFFFFD000 +CONFIG_DEFAULT_DEVICE_TREE="tegra20-samsung-n1" +CONFIG_SPL_STACK=0xffffc +CONFIG_SPL_TEXT_BASE=0x00108000 +CONFIG_SYS_LOAD_ADDR=0x2000000 +CONFIG_TEGRA20=y +CONFIG_TARGET_SAMSUNG_N1=y +CONFIG_TEGRA_ENABLE_UARTB=y +CONFIG_CMD_EBTUPDATE=y +CONFIG_BUTTON_CMD=y +CONFIG_BOOTDELAY=0 +CONFIG_AUTOBOOT_KEYED=y +CONFIG_AUTOBOOT_KEYED_CTRLC=y +CONFIG_OF_SYSTEM_SETUP=y +CONFIG_BOOTCOMMAND="bootflow scan; echo 'Boot configuration not found... Power off in 3 sec'; sleep 3; poweroff" +CONFIG_SYS_PBSIZE=2085 +CONFIG_SPL_FOOTPRINT_LIMIT=y +CONFIG_SPL_MAX_FOOTPRINT=0x8000 +# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set +CONFIG_SPL_HAVE_INIT_STACK=y +CONFIG_SPL_SYS_MALLOC=y +CONFIG_SPL_HAS_CUSTOM_MALLOC_START=y +CONFIG_SPL_CUSTOM_SYS_MALLOC_ADDR=0x90000 +CONFIG_SPL_SYS_MALLOC_SIZE=0x10000 +CONFIG_SYS_PROMPT="Tegra20 (N1) # " +# CONFIG_CMD_BOOTEFI_BOOTMGR is not set +CONFIG_CMD_BOOTMENU=y +# CONFIG_CMD_IMI is not set +CONFIG_CMD_GPIO=y +CONFIG_CMD_GPT=y +CONFIG_CMD_GPT_RENAME=y +CONFIG_CMD_I2C=y +CONFIG_CMD_MMC=y +CONFIG_CMD_POWEROFF=y +CONFIG_CMD_USB=y +CONFIG_CMD_USB_MASS_STORAGE=y +CONFIG_CMD_UMS_ABORT_KEYED=y +# CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_PAUSE=y +CONFIG_CMD_EXT4_WRITE=y +# CONFIG_SPL_DOS_PARTITION is not set +# CONFIG_SPL_EFI_PARTITION is not set +CONFIG_ENV_OVERWRITE=y +CONFIG_ENV_IS_IN_MMC=y +CONFIG_SYS_RELOC_GD_ENV_ADDR=y +CONFIG_SYS_MMC_ENV_PART=2 +CONFIG_BUTTON=y +CONFIG_USB_FUNCTION_FASTBOOT=y +CONFIG_FASTBOOT_BUF_ADDR=0x11000000 +CONFIG_FASTBOOT_BUF_SIZE=0x5000000 +CONFIG_FASTBOOT_FLASH=y +CONFIG_FASTBOOT_FLASH_MMC_DEV=0 +CONFIG_FASTBOOT_CMD_OEM_FORMAT=y +CONFIG_DM_I2C_GPIO=y +CONFIG_SYS_I2C_TEGRA=y +CONFIG_BUTTON_KEYBOARD=y +CONFIG_DM_PMIC=y +CONFIG_DM_PMIC_MAX8907=y +CONFIG_DM_REGULATOR=y +CONFIG_DM_REGULATOR_MAX8907=y +CONFIG_DM_REGULATOR_FIXED=y +CONFIG_SYS_NS16550=y +CONFIG_TEGRA20_SLINK=y +CONFIG_SYSRESET_MAX8907=y +CONFIG_USB=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_TEGRA=y +CONFIG_USB_ULPI_VIEWPORT=y +CONFIG_USB_ULPI=y +CONFIG_USB_KEYBOARD=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_MANUFACTURER="Samsung" +CONFIG_USB_GADGET_VENDOR_NUM=0x04e8 +CONFIG_USB_GADGET_PRODUCT_NUM=0x685F +CONFIG_CI_UDC=y +CONFIG_VIDEO=y +# CONFIG_VIDEO_LOGO is not set +# CONFIG_VIDEO_BPP8 is not set +CONFIG_VIDEO_BRIDGE=y +CONFIG_VIDEO_TEGRA=y +CONFIG_VIDEO_BRIDGE_SAMSUNG_CMC623=y +CONFIG_BACKLIGHT_SAMSUNG_CMC623=y +CONFIG_VIDEO_LCD_SONY_L4F00430T01=y diff --git a/doc/board/index.rst b/doc/board/index.rst index e084c7fb1df..7870f1bc246 100644 --- a/doc/board/index.rst +++ b/doc/board/index.rst @@ -47,6 +47,7 @@ Board-specific doc nxp/index openpiton/index ouya/index + pegatron/index phytec/index purism/index qualcomm/index diff --git a/doc/board/pegatron/chagall.rst b/doc/board/pegatron/chagall.rst new file mode 100644 index 00000000000..18ed425ec73 --- /dev/null +++ b/doc/board/pegatron/chagall.rst @@ -0,0 +1,41 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +U-Boot for the Pegatron Chagall tablet +====================================== + +Quick Start +----------- + +- Build U-Boot +- Boot + +Build U-Boot +------------ + +.. code-block:: bash + + $ export CROSS_COMPILE=arm-none-eabi- + $ make chagall_defconfig + $ make + +After the build succeeds, you will obtain the final ``u-boot-dtb-tegra.bin`` +image, ready for loading. + +Boot +---- + +Currently, U-Boot can be preloaded into RAM via the Fusée Gelée. To enter +RCM protocol use ``power`` and ``volume up`` key combination from powered +off device. The host PC should recognize an APX device. + +Built U-Boot ``u-boot-dtb-tegra.bin`` can be loaded from fusee-tools +directory with + +.. code-block:: bash + + $ ./run_bootloader.sh -s T30 -t ./bct/chagall.bct + +To boot Linux, U-Boot will look for an ``extlinux.conf`` on MicroSD and then on +eMMC. Additionally, if the Volume Down button is pressed while loading, the +device will enter bootmenu. Bootmenu contains entries to mount MicroSD and eMMC +as mass storage, fastboot, reboot, reboot RCM and poweroff. diff --git a/doc/board/pegatron/index.rst b/doc/board/pegatron/index.rst new file mode 100644 index 00000000000..8fd8d5fa547 --- /dev/null +++ b/doc/board/pegatron/index.rst @@ -0,0 +1,9 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Pegatron +======== + +.. toctree:: + :maxdepth: 2 + + chagall diff --git a/doc/board/samsung/index.rst b/doc/board/samsung/index.rst index a1c9636b050..1b92c9518a5 100644 --- a/doc/board/samsung/index.rst +++ b/doc/board/samsung/index.rst @@ -8,3 +8,4 @@ Samsung axy17lte e850-96 + n1 diff --git a/doc/board/samsung/n1.rst b/doc/board/samsung/n1.rst new file mode 100644 index 00000000000..4dbb3141774 --- /dev/null +++ b/doc/board/samsung/n1.rst @@ -0,0 +1,51 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +U-Boot for the Samsung N1 device family +======================================= + +``DISCLAMER!`` Moving your Samsung Galaxy R (GT-I9103) or Samsung Captivate Glide +(SGH-i927) to use U-Boot assumes replacement of the sboot. Vendor android firmwares +will no longer be able to run on the device. This replacement IS reversible. + +Quick Start +----------- + +- Build U-Boot +- Boot + +Build U-Boot +------------ + +Device support is implemented by applying config fragment to a generic board +defconfig. Generic board defconfig is suitable for Samsung Galaxy R (GT-I9103) +while Samsung Captivate Glide (SGH-i927) support is provided by applying +``bose.config`` fragment. + +.. code-block:: bash + + $ export CROSS_COMPILE=arm-none-eabi- + $ make n1_defconfig bose.config # For Captivate Glide + $ make + +After the build succeeds, you will obtain the final ``u-boot-dtb-tegra.bin`` +image, ready for further processing. + +Boot +---- + +Currently, U-Boot can be preloaded into RAM via the NvFlash. To enter +RCM protocol use ``home`` and ``volume up`` for Galaxy R and ``volume down`` +and ``volume up`` Captivate Glide key combination plus plugging usb in. +The host PC should recognize an APX device. + +Built U-Boot ``u-boot-dtb-tegra.bin`` can be loaded from fusee-tools +directory with + +.. code-block:: bash + + $ ./utils/nvflash_t20 --setbct --bct ./bct/i927.bct --configfile ./utils/flash.cfg --bl u-boot-dtb-tegra.bin --sbk (in form of 0xABCDABCD 4 times) --sync # For Captivate Glide + +To boot Linux, U-Boot will look for an ``extlinux.conf`` on MicroSD and then on +eMMC. Additionally, if the Volume Down button is pressed while loading, the +device will enter bootmenu. Bootmenu contains entries to mount MicroSD and eMMC +as mass storage, fastboot, reboot, reboot RCM and poweroff. diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index d26f87364f9..0d58e3910fe 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -10,4 +10,6 @@ source "drivers/crypto/aspeed/Kconfig" source "drivers/crypto/nuvoton/Kconfig" +source "drivers/crypto/tegra/Kconfig" + endmenu diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile index 2bd99fc2763..e4a4482b7f3 100644 --- a/drivers/crypto/Makefile +++ b/drivers/crypto/Makefile @@ -10,3 +10,4 @@ obj-y += fsl/ obj-y += hash/ obj-y += aspeed/ obj-y += nuvoton/ +obj-y += tegra/ diff --git a/drivers/crypto/tegra/Kconfig b/drivers/crypto/tegra/Kconfig new file mode 100644 index 00000000000..b027609307b --- /dev/null +++ b/drivers/crypto/tegra/Kconfig @@ -0,0 +1,7 @@ +config TEGRA_AES + bool "Support the Tegra AES" + depends on DM_AES + help + This provides a means to encrypt and decrypt data using the Tegra + Bit Stream Engine for Video/Audio. Also may provide a mean to + encrypt/decrypt/sign using already loaded device SBK. diff --git a/drivers/crypto/tegra/Makefile b/drivers/crypto/tegra/Makefile new file mode 100644 index 00000000000..a118350fd11 --- /dev/null +++ b/drivers/crypto/tegra/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0+ + +obj-$(CONFIG_$(PHASE_)TEGRA_AES) += tegra_aes.o diff --git a/drivers/crypto/tegra/tegra_aes.c b/drivers/crypto/tegra/tegra_aes.c new file mode 100644 index 00000000000..7b374c757ba --- /dev/null +++ b/drivers/crypto/tegra/tegra_aes.c @@ -0,0 +1,591 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Driver for NVIDIA Tegra AES hardware engine residing inside the Bit Stream Engine + * for Video (BSEV) hardware block and Bit Stream Engine for Audio (BSEA). + * + * The programming sequence for this engine is with the help of commands which travel + * via a command queue residing between the CPU and the BSEV/BSEA block. + * + * The hardware key table length is 64 bytes and each key slot divided as follows: + * 1. Key - 32 bytes + * 2. Original IV - 16 bytes + * 3. Updated IV - 16 bytes + * + * The engine has 4 slots in T20/T30 in which 0th contains SBK loaded by bootrom, + * vendor bootloaders tend to clear this slot so that anything booted after can't + * use the SBK. This is relevant for U-Boot's chainloaded from these vendor bootloaders. + * + * Copyright (c) 2010-2011, NVIDIA Corporation + * Copyright (c) 2025, Ion Agorria. + */ + +#include <dm.h> +#include <asm/io.h> +#include <malloc.h> +#include <time.h> +#include <linux/delay.h> +#include <clk.h> +#include <reset.h> +#include <uboot_aes.h> + +#include <asm/arch-tegra/crypto.h> +#include <asm/arch-tegra/fuse.h> + +/* Make sure pointers will fit register size for AES engine */ +static_assert(sizeof(void *) == sizeof(u32)); + +#define IRAM_BASE 0x40000000 + +#define TEGRA_AES_DMA_BUFFER_SIZE (0x4000 / AES_BLOCK_LENGTH) +#define TEGRA_AES_HW_MAX_KEY_LENGTH AES256_KEY_LENGTH +#define TEGRA_AES_HW_TABLE_LENGTH (TEGRA_AES_HW_MAX_KEY_LENGTH + AES_BLOCK_LENGTH * 2) +#define TEGRA_AES_IRAM_MAX_ADDR (IRAM_BASE | TEGRA_AES_KEYTABLEADDR_FIELD) + +#define TEGRA_AES_BUSY_TIMEOUT_MS 1000 + +/* Registers */ +#define TEGRA_AES_ICMDQUE_WR 0x000 +#define TEGRA_AES_CMDQUE_CONTROL 0x008 +#define TEGRA_AES_INTR_STATUS 0x018 +#define TEGRA_AES_INT_ENB 0x040 +#define TEGRA_AES_BSE_CFG 0x044 +#define TEGRA_AES_IRAM_ACCESS_CFG 0x0a0 +#define TEGRA_AES_SECURE_DEST_ADDR 0x100 +#define TEGRA_AES_SECURE_INPUT_SELECT 0x104 +#define TEGRA_AES_SECURE_CONFIG 0x108 +#define TEGRA_AES_SECURE_CONFIG_EXT 0x10c + +/* Register field macros */ +#define TEGRA_AES_ENGINE_BUSY_FIELD BIT(0) +#define TEGRA_AES_ICQ_EMPTY_FIELD BIT(3) +#define TEGRA_AES_DMA_BUSY_FIELD BIT(23) +#define TEGRA_AES_SECURE_KEY_SCH_DIS_FIELD BIT(15) +#define TEGRA_AES_KEYTABLEADDR_FIELD (BIT(17) - 1) +#define TEGRA_AES_SECURE_KEY_INDEX_SHIFT 20 +#define TEGRA_AES_SECURE_KEY_INDEX_FIELD (0x1f << TEGRA_AES_SECURE_KEY_INDEX_SHIFT) +#define TEGRA_AES_SECURE_CTR_CNT_SHIFT 16 +#define TEGRA_AES_SECURE_CTR_CNT_FIELD (0xffff << TEGRA_AES_SECURE_CTR_CNT_SHIFT) +#define TEGRA_AES_BSE_MODE_FIELD 0x1f +#define TEGRA_AES_BSE_LITTLE_ENDIAN_FIELD BIT(10) +#define TEGRA_AES_CMDQ_OPCODE_SHIFT 26 +#define TEGRA_AES_CMDQ_CTRL_ICMDQEN_FIELD BIT(1) +#define TEGRA_AES_CMDQ_CTRL_SRC_STM_SEL_FIELD BIT(4) +#define TEGRA_AES_CMDQ_CTRL_DST_STM_SEL_FIELD BIT(5) +#define TEGRA_AES_SECURE_INPUT_ALG_SEL_SHIFT 28 +#define TEGRA_AES_SECURE_INPUT_KEY_LEN_SHIFT 16 +#define TEGRA_AES_SECURE_INPUT_IV_FIELD BIT(10) +#define TEGRA_AES_SECURE_INPUT_HASH_ENB_FIELD BIT(2) +#define TEGRA_AES_SECURE_CORE_SEL_SHIFT 9 +#define TEGRA_AES_SECURE_VCTRAM_SEL_SHIFT 7 +#define TEGRA_AES_SECURE_XOR_POS_SHIFT 3 +#define TEGRA_AES_INT_ERROR_MASK 0x6ff000 + +/* Commands for BSEV/BSEA */ +#define TEGRA_AES_CMD_BLKSTARTENGINE 0x0e +#define TEGRA_AES_CMD_DMASETUP 0x10 +#define TEGRA_AES_CMD_DMACOMPLETE 0x11 +#define TEGRA_AES_CMD_SETTABLE 0x15 + +/* Flags for mode */ +#define TEGRA_AES_MODE_ENCRYPT BIT(0) +#define TEGRA_AES_MODE_CBC BIT(1) +#define TEGRA_AES_MODE_UPDATE_IV BIT(2) +#define TEGRA_AES_MODE_HASH BIT(3) + +struct tegra_aes_priv { + void *regs; + void *iram_addr; + + struct reset_ctl reset_ctl; + struct reset_ctl reset_ctl_vde; + + struct clk *clk; + struct clk *clk_parent; + + u8 current_key_size; + bool sbk_available; +}; + +static bool tegra_aes_is_busy(struct tegra_aes_priv *priv, bool dma_wait) +{ + u32 value = readl(priv->regs + TEGRA_AES_INTR_STATUS); + bool engine_busy = value & TEGRA_AES_ENGINE_BUSY_FIELD; + bool non_empty_queue = !(value & TEGRA_AES_ICQ_EMPTY_FIELD); + bool dma_busy = dma_wait && (value & TEGRA_AES_DMA_BUSY_FIELD); + + log_debug("%s - e:%d q:%d dma:%d\n", __func__, engine_busy, non_empty_queue, dma_busy); + + return engine_busy || non_empty_queue || dma_busy; +} + +static u32 tegra_aes_check_error(struct tegra_aes_priv *priv) +{ + u32 value = readl(priv->regs + TEGRA_AES_INTR_STATUS) & TEGRA_AES_INT_ERROR_MASK; + + if (value) { + writel(TEGRA_AES_INT_ERROR_MASK, priv->regs + TEGRA_AES_INTR_STATUS); + log_debug("%s 0x%x\n", __func__, value); + } + + return value; +} + +static int tegra_aes_wait_for_idle_dma(struct tegra_aes_priv *priv, bool dma_wait) +{ + ulong start = get_timer(0); + + while (tegra_aes_is_busy(priv, dma_wait)) { + if (get_timer(start) > TEGRA_AES_BUSY_TIMEOUT_MS) { + log_err("%s: TIMEOUT!!!\n", __func__); + break; + } + mdelay(5); + } + + if (tegra_aes_check_error(priv)) + return -1; + + return 0; +} + +static int tegra_aes_wait_for_idle(struct tegra_aes_priv *priv) +{ + return tegra_aes_wait_for_idle_dma(priv, 1); +} + +static int tegra_aes_configure(struct tegra_aes_priv *priv) +{ + u32 value; + + if (tegra_aes_wait_for_idle(priv)) + return -1; + + /* IRAM config */ + writel(0, priv->regs + TEGRA_AES_IRAM_ACCESS_CFG); + + /* Reset interrupts bits, or engine will hang on next operation */ + writel(0xFFFFFFFF, priv->regs + TEGRA_AES_INTR_STATUS); + + /* Set interrupts */ + writel(0, priv->regs + TEGRA_AES_INT_ENB); + + /* Configure CMDQUE */ + value = readl(priv->regs + TEGRA_AES_CMDQUE_CONTROL); + value |= TEGRA_AES_CMDQ_CTRL_SRC_STM_SEL_FIELD | + TEGRA_AES_CMDQ_CTRL_DST_STM_SEL_FIELD | + TEGRA_AES_CMDQ_CTRL_ICMDQEN_FIELD; + writel(value, priv->regs + TEGRA_AES_CMDQUE_CONTROL); + + value = readl(priv->regs + TEGRA_AES_SECURE_CONFIG_EXT); + value &= ~TEGRA_AES_SECURE_CTR_CNT_FIELD; + writel(value, priv->regs + TEGRA_AES_SECURE_CONFIG_EXT); + + /* Configure BSE */ + value = readl(priv->regs + TEGRA_AES_BSE_CFG); + value &= ~TEGRA_AES_BSE_MODE_FIELD; + value |= TEGRA_AES_BSE_LITTLE_ENDIAN_FIELD; + writel(value, priv->regs + TEGRA_AES_BSE_CFG); + + return 0; +} + +static int tegra_aes_select_key_slot(struct tegra_aes_priv *priv, u32 key_size, u8 slot) +{ + if (tegra_aes_wait_for_idle(priv)) + return -1; + + if (key_size < (AES128_KEY_LENGTH * 8) || + key_size > (TEGRA_AES_HW_MAX_KEY_LENGTH * 8)) + return -EINVAL; + + priv->current_key_size = key_size; + + /* Select the key slot */ + u32 value = readl(priv->regs + TEGRA_AES_SECURE_CONFIG); + + value &= ~TEGRA_AES_SECURE_KEY_INDEX_FIELD; + value |= (slot << TEGRA_AES_SECURE_KEY_INDEX_SHIFT); + writel(value, priv->regs + TEGRA_AES_SECURE_CONFIG); + + return 0; +} + +static int tegra_aes_call_engine(struct tegra_aes_priv *priv, u8 *src, u8 *dst, + u32 nblocks, u32 mode) +{ + u32 value; + const u32 ICMDQ_LENGTH = 4; + u32 cmdq[ICMDQ_LENGTH]; + + log_debug("%s: 0x%p -> 0x%p blocks %d mode 0x%x\n", __func__, + src, dst, nblocks, mode); + + if (!nblocks) { + log_warning("%s: called with 0 blocks!\n", __func__); + return -1; + } + + if (tegra_aes_configure(priv)) + return -1; + + /* Configure Secure Input */ + value = 1 << TEGRA_AES_SECURE_INPUT_ALG_SEL_SHIFT | + priv->current_key_size << TEGRA_AES_SECURE_INPUT_KEY_LEN_SHIFT; + + if (mode & TEGRA_AES_MODE_UPDATE_IV) + value |= TEGRA_AES_SECURE_INPUT_IV_FIELD; + if (mode & TEGRA_AES_MODE_HASH) + value |= TEGRA_AES_SECURE_INPUT_HASH_ENB_FIELD; + if (mode & TEGRA_AES_MODE_CBC) { + value |= ((mode & TEGRA_AES_MODE_ENCRYPT) ? 2 : 3) << + TEGRA_AES_SECURE_XOR_POS_SHIFT; + value |= ((mode & TEGRA_AES_MODE_ENCRYPT) ? 2 : 3) << + TEGRA_AES_SECURE_VCTRAM_SEL_SHIFT; + value |= ((mode & TEGRA_AES_MODE_ENCRYPT) ? 1 : 0) << + TEGRA_AES_SECURE_CORE_SEL_SHIFT; + } else { + /* ECB */ + value |= ((mode & TEGRA_AES_MODE_ENCRYPT) ? 1 : 0) << + TEGRA_AES_SECURE_CORE_SEL_SHIFT; + } + + writel(value, priv->regs + TEGRA_AES_SECURE_INPUT_SELECT); + + /* Set destination address (doing in-place at IRAM) */ + writel((u32)priv->iram_addr, priv->regs + TEGRA_AES_SECURE_DEST_ADDR); + + /* Copy src data to IRAM */ + if (src != priv->iram_addr) + memcpy(priv->iram_addr, src, nblocks * AES_BLOCK_LENGTH); + + /* Run ICMD commands */ + cmdq[0] = TEGRA_AES_CMD_DMASETUP << TEGRA_AES_CMDQ_OPCODE_SHIFT; + cmdq[1] = (u32)priv->iram_addr; + cmdq[2] = TEGRA_AES_CMD_BLKSTARTENGINE << TEGRA_AES_CMDQ_OPCODE_SHIFT | (nblocks - 1); + cmdq[3] = TEGRA_AES_CMD_DMACOMPLETE << TEGRA_AES_CMDQ_OPCODE_SHIFT; + + for (int i = 0; i < ICMDQ_LENGTH; i++) { + tegra_aes_wait_for_idle_dma(priv, (ICMDQ_LENGTH - 1) == i); + writel(cmdq[i], priv->regs + TEGRA_AES_ICMDQUE_WR); + } + + if (tegra_aes_wait_for_idle(priv)) + return -1; + + /* Put the result from IRAM to destination if not hashing */ + if (dst != priv->iram_addr && !(mode & TEGRA_AES_MODE_HASH)) + memcpy(dst, priv->iram_addr, nblocks * AES_BLOCK_LENGTH); + + return 0; +} + +static int tegra_aes_process_blocks(struct udevice *dev, u8 *iv, u8 *src, + u8 *dst, u32 num_aes_blocks, u32 mode) +{ + struct tegra_aes_priv *priv = dev_get_priv(dev); + + log_debug("%s: 0x%p -> 0x%p blocks %d mode 0x%x\n", + __func__, src, dst, num_aes_blocks, mode); + + if (!num_aes_blocks) { + log_warning("%s: called with 0 blocks!\n", __func__); + return -1; + } + + /* Load initial IV if CBC mode */ + if (mode & TEGRA_AES_MODE_CBC) { + if (tegra_aes_call_engine(priv, iv, priv->iram_addr, 1, TEGRA_AES_MODE_CBC)) + return -1; + + /* Add update IV flag */ + mode |= TEGRA_AES_MODE_UPDATE_IV; + } + + /* Process blocks by calling engine several times per dma buffer size */ + while (num_aes_blocks > 0) { + u32 blocks = min(num_aes_blocks, (u32)TEGRA_AES_DMA_BUFFER_SIZE); + + if (tegra_aes_call_engine(priv, src, dst, blocks, mode)) + return -1; + + num_aes_blocks -= blocks; + src += blocks * AES_BLOCK_LENGTH; + dst += blocks * AES_BLOCK_LENGTH; + } + + return 0; +} + +static int tegra_aes_ops_available_key_slots(struct udevice *dev) +{ + return 4; /* 4 slots in Tegra20 and Tegra30 */ +} + +static int tegra_aes_ops_select_key_slot(struct udevice *dev, u32 key_size, u8 slot) +{ + struct tegra_aes_priv *priv = dev_get_priv(dev); + + if (slot == TEGRA_AES_SLOT_SBK && !priv->sbk_available) { + log_warning("%s: SBK not available!\n", __func__); + return -1; + } + + return tegra_aes_select_key_slot(priv, key_size, slot); +} + +static int tegra_aes_ops_set_key_for_key_slot(struct udevice *dev, u32 key_size, + u8 *key, u8 slot) +{ + struct tegra_aes_priv *priv = dev_get_priv(dev); + const u8 SUBCMD_CRYPTO_TABLE_SEL = 0x3; + const u8 SUBCMD_KEY_TABLE_SEL = 0x8; + const u8 CMDQ_KEYTABLEADDR_SHIFT = 0; + const u8 CMDQ_KEYTABLEID_SHIFT = 17; + const u8 CMDQ_TABLESEL_SHIFT = 24; + u32 value, addr; + + log_debug("%s: slot %d\n", __func__, slot); + + if (tegra_aes_configure(priv)) + return -1; + + if (key_size < (AES128_KEY_LENGTH * 8) || + key_size > (TEGRA_AES_HW_MAX_KEY_LENGTH * 8)) + return -EINVAL; + + if (slot == TEGRA_AES_SLOT_SBK) + log_debug("%s: SBK slot being set!\n", __func__); + + /* Clear and copy data to IRAM */ + memset(priv->iram_addr, 0, TEGRA_AES_HW_TABLE_LENGTH); + memcpy(priv->iram_addr, key, key_size / 8); + + /* Mask the addr */ + addr = ((u32)priv->iram_addr) & TEGRA_AES_KEYTABLEADDR_FIELD; + + /* Command for engine to load AES key from IRAM */ + value = TEGRA_AES_CMD_SETTABLE << TEGRA_AES_CMDQ_OPCODE_SHIFT | + SUBCMD_CRYPTO_TABLE_SEL << CMDQ_TABLESEL_SHIFT | + (SUBCMD_KEY_TABLE_SEL | slot) << CMDQ_KEYTABLEID_SHIFT | + addr << CMDQ_KEYTABLEADDR_SHIFT; + writel(value, priv->regs + TEGRA_AES_ICMDQUE_WR); + + return tegra_aes_wait_for_idle(priv); +} + +static int tegra_aes_ops_aes_ecb_encrypt(struct udevice *dev, u8 *src, u8 *dst, + u32 num_aes_blocks) +{ + return tegra_aes_process_blocks(dev, NULL, src, dst, num_aes_blocks, + TEGRA_AES_MODE_ENCRYPT); +} + +static int tegra_aes_ops_aes_ecb_decrypt(struct udevice *dev, u8 *src, u8 *dst, + u32 num_aes_blocks) +{ + return tegra_aes_process_blocks(dev, NULL, src, dst, num_aes_blocks, 0); +} + +static int tegra_aes_ops_aes_cbc_encrypt(struct udevice *dev, u8 *iv, u8 *src, + u8 *dst, u32 num_aes_blocks) +{ + return tegra_aes_process_blocks(dev, iv, src, dst, num_aes_blocks, + TEGRA_AES_MODE_CBC | TEGRA_AES_MODE_ENCRYPT); +} + +static int tegra_aes_ops_aes_cbc_decrypt(struct udevice *dev, u8 *iv, u8 *src, + u8 *dst, u32 num_aes_blocks) +{ + return tegra_aes_process_blocks(dev, iv, src, dst, num_aes_blocks, + TEGRA_AES_MODE_CBC); +} + +static void tegra_aes_test_loaded_sbk(struct udevice *dev) +{ + struct tegra_aes_priv *priv = dev_get_priv(dev); + enum fuse_operating_mode opmode = tegra_fuse_get_operation_mode(); + const u8 ZERO_KEY_CIPHERTEXT[AES_BLOCK_LENGTH] = { + 0x66, 0xe9, 0x4b, 0xd4, 0xef, 0x8a, 0x2c, 0x3b, + 0x88, 0x4c, 0xfa, 0x59, 0xca, 0x34, 0x2b, 0x2e + }; + + /* Encrypt a zero block, we use ECB so that we only care about SBK and not the IV */ + memset(priv->iram_addr, 0, AES_BLOCK_LENGTH); + tegra_aes_select_key_slot(priv, 128, TEGRA_AES_SLOT_SBK); + tegra_aes_call_engine(priv, priv->iram_addr, priv->iram_addr, 1, TEGRA_AES_MODE_ENCRYPT); + + /* Evaluate the result of engine operation */ + if (!memcmp(priv->iram_addr, AES_ZERO_BLOCK, AES_BLOCK_LENGTH)) { + log_err("%s: engine is not operational! (opmode 0x%x)\n", __func__, opmode); + } else if (!memcmp(priv->iram_addr, ZERO_KEY_CIPHERTEXT, AES_BLOCK_LENGTH)) { + if (opmode == MODE_ODM_PRODUCTION_SECURE) { + log_warning("%s: SBK is zero or is cleared from engine! (opmode 0x%x)\n", + __func__, opmode); + } else { + log_debug("%s - SBK is zero and available! (opmode 0x%x)\n", + __func__, opmode); + priv->sbk_available = true; + } + } else { + if (opmode == MODE_ODM_PRODUCTION_SECURE) { + log_debug("%s: SBK is available! (opmode 0x%x)\n", __func__, opmode); + priv->sbk_available = true; + } else { + log_warning("%s: SBK is not zero and should be! (opmode 0x%x)\n", + __func__, opmode); + } + } +} + +static int tegra_aes_hw_init(struct udevice *dev) +{ + struct tegra_aes_priv *priv = dev_get_priv(dev); + u32 value; + int ret; + + if (priv->clk_parent) { + ret = reset_assert(&priv->reset_ctl_vde); + if (ret) { + log_debug("%s: VDE reset assert failed: %d\n", __func__, ret); + return ret; + } + } + + ret = reset_assert(&priv->reset_ctl); + if (ret) { + log_debug("%s: BSE reset assert failed: %d\n", __func__, ret); + return ret; + } + + if (priv->clk_parent) { + ret = clk_enable(priv->clk_parent); + if (ret) { + log_err("%s: VDE clock enable failed: %d\n", __func__, ret); + return ret; + } + + ret = clk_set_rate(priv->clk_parent, 50 * 1000000); + if (IS_ERR_VALUE(ret)) { + log_err("%s: VDE clock set rate failed: %d\n", __func__, ret); + return ret; + } + } + + ret = clk_enable(priv->clk); + if (ret) { + log_err("%s: BSE clock enable failed: %d\n", __func__, ret); + return ret; + } + + if (priv->clk_parent) { + ret = reset_deassert(&priv->reset_ctl_vde); + if (ret) { + log_err("%s: VDE reset deassert failed: %d\n", __func__, ret); + return ret; + } + } + + ret = reset_deassert(&priv->reset_ctl); + if (ret) { + log_err("%s: BSE reset deassert failed: %d\n", __func__, ret); + return ret; + } + + /* Enable key schedule generation in hardware */ + value = readl(priv->regs + TEGRA_AES_SECURE_CONFIG_EXT); + value &= ~TEGRA_AES_SECURE_KEY_SCH_DIS_FIELD; + writel(value, priv->regs + TEGRA_AES_SECURE_CONFIG_EXT); + + /* Check if SBK is loaded in SBK slot or was erased */ + priv->sbk_available = false; + tegra_aes_test_loaded_sbk(dev); + + return 0; +} + +static int tegra_aes_probe(struct udevice *dev) +{ + struct tegra_aes_priv *priv = dev_get_priv(dev); + fdt_size_t iram_size = 0; + u32 value; + int ret; + + priv->current_key_size = AES128_KEY_LENGTH; + + priv->regs = dev_read_addr_ptr(dev); + if (!priv->regs) { + log_err("%s: Cannot find aes reg address, binding failed\n", __func__); + return -EINVAL; + } + + priv->iram_addr = devfdt_get_addr_size_name_ptr(dev, "iram-buffer", &iram_size); + if (!priv->iram_addr) { + log_debug("%s: Cannot find iram buffer address, binding failed\n", __func__); + return -EINVAL; + } + + if (iram_size < TEGRA_AES_DMA_BUFFER_SIZE * AES_BLOCK_LENGTH) { + log_debug("%s: Unsupported iram buffer size: 0x%x required: 0x%x\n", + __func__, iram_size, TEGRA_AES_DMA_BUFFER_SIZE); + return -EINVAL; + } + + /* Make sure the IRAM address is kept block aligned and accessible for slot loading */ + value = (uint32_t)priv->iram_addr; + if ((value & 0xFFF0000F) != IRAM_BASE || value > TEGRA_AES_IRAM_MAX_ADDR) { + log_debug("%s: iram buffer must be located inside iram,", __func__); + log_debug("AES block aligned and not above 0x%08x, current addr %p\n", + (u32)TEGRA_AES_IRAM_MAX_ADDR, priv->iram_addr); + return -EINVAL; + } + + ret = reset_get_by_name(dev, NULL, &priv->reset_ctl); + if (ret) { + log_debug("%s: failed to get BSE reset: %d\n", __func__, ret); + return ret; + } + + priv->clk = devm_clk_get(dev, NULL); + if (IS_ERR(priv->clk)) { + log_err("%s: failed to get BSE clock: %d\n", __func__, ret); + return ret; + } + + /* VDE clock and reset required by BSEV */ + ret = reset_get_by_name(dev, "vde", &priv->reset_ctl_vde); + if (ret) + log_debug("%s: failed to get VDE reset: %d\n", __func__, ret); + + priv->clk_parent = devm_clk_get(dev, "vde"); + if (IS_ERR(priv->clk_parent)) + log_debug("%s: failed to get BSE clock: %d\n", __func__, ret); + + return tegra_aes_hw_init(dev); +} + +static const struct aes_ops tegra_aes_ops = { + .available_key_slots = tegra_aes_ops_available_key_slots, + .select_key_slot = tegra_aes_ops_select_key_slot, + .set_key_for_key_slot = tegra_aes_ops_set_key_for_key_slot, + .aes_ecb_encrypt = tegra_aes_ops_aes_ecb_encrypt, + .aes_ecb_decrypt = tegra_aes_ops_aes_ecb_decrypt, + .aes_cbc_encrypt = tegra_aes_ops_aes_cbc_encrypt, + .aes_cbc_decrypt = tegra_aes_ops_aes_cbc_decrypt, +}; + +static const struct udevice_id tegra_aes_ids[] = { + { .compatible = "nvidia,tegra20-bsea" }, + { .compatible = "nvidia,tegra20-bsev" }, + { .compatible = "nvidia,tegra30-bsea" }, + { .compatible = "nvidia,tegra30-bsev" }, + { } +}; + +U_BOOT_DRIVER(tegra_aes) = { + .name = "tegra_aes", + .id = UCLASS_AES, + .of_match = tegra_aes_ids, + .probe = tegra_aes_probe, + .ops = &tegra_aes_ops, + .priv_auto = sizeof(struct tegra_aes_priv), +}; diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index dfe4b3b8a02..b5777da5218 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -691,6 +691,23 @@ config VIDEO_LCD_HITACHI_TX18D42VM lcd controller which needs to be initialized over SPI, once that is done they work like a regular LVDS panel. +config VIDEO_LCD_SONY_L4F00430T01 + tristate "Sony L4F00430T01 480x800 LCD panel support" + depends on PANEL + help + Say Y here if you want to enable support for Sony L4F00430T01 + LCD module found in Samsung Galaxy R. The panel has a + WVGA resolution (480x800) and is setup over SPI, video + data comes from RGB. + +config VIDEO_LCD_SAMSUNG_S6E63M0 + tristate "Samsung S6E63M0 controller based panel support" + depends on PANEL && BACKLIGHT + help + Say Y here if you want to enable support for Samsung S6E63M0 + controller found in some panels like on Samsung Captivate Glide. + Currently only DBI C panel is implemented. + config VIDEO_LCD_SPI_CS string "SPI CS pin for LCD related config job" depends on VIDEO_LCD_SSD2828 || VIDEO_LCD_HITACHI_TX18D42VM @@ -821,6 +838,13 @@ config BACKLIGHT_LP855x supported for now, PWM mode can be added if there will be any need in it. Supported backlight level range is from 0 to 255 with step of 1. +config BACKLIGHT_SAMSUNG_CMC623 + bool "Backlight Driver for Samsung CMC623" + depends on VIDEO_BRIDGE_SAMSUNG_CMC623 + help + Say Y to enable the backlight driver for Samsung CMC623 image converter + chip's PWM output to control backlight brightness. + source "drivers/video/ti/Kconfig" source "drivers/video/exynos/Kconfig" diff --git a/drivers/video/Makefile b/drivers/video/Makefile index ebe4a3961fc..96c7ce7bb09 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -33,6 +33,7 @@ obj-$(CONFIG_BACKLIGHT_AAT2870) += aat2870_backlight.o obj-$(CONFIG_BACKLIGHT_LM3532) += lm3532_backlight.o obj-$(CONFIG_BACKLIGHT_LM3533) += lm3533_backlight.o obj-$(CONFIG_BACKLIGHT_LP855x) += lp855x_backlight.o +obj-$(CONFIG_BACKLIGHT_SAMSUNG_CMC623) += cmc623_backlight.o obj-${CONFIG_EXYNOS_FB} += exynos/ obj-${CONFIG_VIDEO_ROCKCHIP} += rockchip/ obj-${CONFIG_VIDEO_STM32} += stm32/ @@ -74,6 +75,8 @@ obj-$(CONFIG_VIDEO_LCD_SHARP_LQ079L1SX01) += sharp-lq079l1sx01.o obj-$(CONFIG_VIDEO_LCD_SHARP_LQ101R1SX01) += sharp-lq101r1sx01.o obj-$(CONFIG_VIDEO_LCD_SSD2828) += ssd2828.o obj-$(CONFIG_VIDEO_LCD_TDO_TL070WSH30) += tdo-tl070wsh30.o +obj-$(CONFIG_VIDEO_LCD_SONY_L4F00430T01) += sony-l4f00430t01.o +obj-$(CONFIG_VIDEO_LCD_SAMSUNG_S6E63M0) += samsung-s6e63m0.o obj-$(CONFIG_VIDEO_MCDE_SIMPLE) += mcde_simple.o obj-${CONFIG_VIDEO_MESON} += meson/ obj-${CONFIG_VIDEO_MIPI_DSI} += mipi_dsi.o diff --git a/drivers/video/bridge/Kconfig b/drivers/video/bridge/Kconfig index be53034bd3d..a48cec7a138 100644 --- a/drivers/video/bridge/Kconfig +++ b/drivers/video/bridge/Kconfig @@ -66,3 +66,11 @@ config VIDEO_BRIDGE_LVDS_CODEC help Support for transparent LVDS encoders and decoders that don't require any configuration. + +config VIDEO_BRIDGE_SAMSUNG_CMC623 + bool "Samsung CMC623 Image Converter driver" + depends on VIDEO_BRIDGE && DM_GPIO + select DM_I2C + help + Samsung CMC623 image converter chip driver. + Found in several Samsung devices such as N1 diff --git a/drivers/video/bridge/Makefile b/drivers/video/bridge/Makefile index 63dc6e62c49..520f36a7a6f 100644 --- a/drivers/video/bridge/Makefile +++ b/drivers/video/bridge/Makefile @@ -11,3 +11,4 @@ obj-$(CONFIG_VIDEO_BRIDGE_ANALOGIX_ANX6345) += anx6345.o obj-$(CONFIG_VIDEO_BRIDGE_SOLOMON_SSD2825) += ssd2825.o obj-$(CONFIG_VIDEO_BRIDGE_TOSHIBA_TC358768) += tc358768.o obj-$(CONFIG_VIDEO_BRIDGE_LVDS_CODEC) += lvds-codec.o +obj-$(CONFIG_VIDEO_BRIDGE_SAMSUNG_CMC623) += cmc623.o diff --git a/drivers/video/bridge/cmc623.c b/drivers/video/bridge/cmc623.c new file mode 100644 index 00000000000..78dafef8145 --- /dev/null +++ b/drivers/video/bridge/cmc623.c @@ -0,0 +1,234 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2025 Ion Agorria <ion@agorria.com> + */ + +#include <clk.h> +#include <dm.h> +#include <dm/ofnode_graph.h> +#include <i2c.h> +#include <log.h> +#include <backlight.h> +#include <panel.h> +#include <video_bridge.h> +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/kernel.h> +#include <linux/math64.h> +#include <power/regulator.h> +#include <asm/gpio.h> + +static const char * const cmc623_supplies[] = { + "vdd3v0-supply", "vdd1v2-supply", "vddio1v8-supply" +}; + +struct cmc623_priv { + struct udevice *panel; + struct display_timing timing; + + struct udevice *supplies[ARRAY_SIZE(cmc623_supplies)]; + + struct gpio_desc enable_gpio; /* also known as FAILSAFE */ + struct gpio_desc bypass_gpio; +}; + +static int cmc623_attach(struct udevice *dev) +{ + struct cmc623_priv *priv = dev_get_priv(dev); + int ret; + + /* Perform panel setup */ + ret = panel_enable_backlight(priv->panel); + if (ret) + return ret; + + return 0; +} + +static int cmc623_set_backlight(struct udevice *dev, int percent) +{ + struct cmc623_priv *priv = dev_get_priv(dev); + + return panel_set_backlight(priv->panel, percent); +} + +static int cmc623_panel_timings(struct udevice *dev, struct display_timing *timing) +{ + struct cmc623_priv *priv = dev_get_priv(dev); + + memcpy(timing, &priv->timing, sizeof(*timing)); + + return 0; +} + +static int cmc623_hw_init(struct udevice *dev) +{ + struct cmc623_priv *priv = dev_get_priv(dev); + struct video_bridge_priv *uc_priv = dev_get_uclass_priv(dev); + int i, ret; + + /* enable supplies */ + for (i = 0; i < ARRAY_SIZE(cmc623_supplies); i++) { + ret = regulator_set_enable_if_allowed(priv->supplies[i], 1); + if (ret) { + log_debug("%s: cannot enable %s %d\n", __func__, + cmc623_supplies[i], ret); + return ret; + } + } + + mdelay(10); + + ret = dm_gpio_set_value(&uc_priv->reset, 1); + if (ret) { + log_debug("%s: error at reset = 1 (%d)\n", __func__, ret); + return ret; + } + + ret = dm_gpio_set_value(&priv->enable_gpio, 0); + if (ret) { + log_debug("%s: error at enable = 0 (%d)\n", __func__, ret); + return ret; + } + + ret = dm_gpio_set_value(&priv->bypass_gpio, 0); + if (ret) { + log_debug("%s: error at bypass = 0 (%d)\n", __func__, ret); + return ret; + } + + ret = dm_gpio_set_value(&uc_priv->sleep, 0); + if (ret) { + log_debug("%s: error at sleep = 0 (%d)\n", __func__, ret); + return ret; + } + + udelay(2000); + + ret = dm_gpio_set_value(&priv->enable_gpio, 1); + if (ret) { + log_debug("%s: error at enable = 1 (%d)\n", __func__, ret); + return ret; + } + + udelay(2000); + + ret = dm_gpio_set_value(&priv->bypass_gpio, 1); + if (ret) { + log_debug("%s: error at bypass = 1 (%d)\n", __func__, ret); + return ret; + } + + udelay(2000); + + ret = dm_gpio_set_value(&uc_priv->sleep, 1); + if (ret) { + log_debug("%s: error at sleep = 1 (%d)\n", __func__, ret); + return ret; + } + + udelay(2000); + + ret = dm_gpio_set_value(&uc_priv->reset, 0); + if (ret) { + log_debug("%s: error at sleep = 0 (%d)\n", __func__, ret); + return ret; + } + + mdelay(10); + + ret = dm_gpio_set_value(&uc_priv->reset, 1); + if (ret) { + log_debug("%s: error at sleep = 1 (%d)\n", __func__, ret); + return ret; + } + + mdelay(10); + + return 0; +} + +static int cmc623_get_panel(struct udevice *dev) +{ + struct cmc623_priv *priv = dev_get_priv(dev); + int i, ret; + + u32 num = ofnode_graph_get_port_count(dev_ofnode(dev)); + + for (i = 0; i < num; i++) { + ofnode remote = ofnode_graph_get_remote_node(dev_ofnode(dev), i, -1); + + ret = uclass_get_device_by_ofnode(UCLASS_PANEL, remote, &priv->panel); + if (!ret) + return 0; + } + + /* If this point is reached, no panels were found */ + return -ENODEV; +} + +static int cmc623_probe(struct udevice *dev) +{ + struct cmc623_priv *priv = dev_get_priv(dev); + int i, ret; + + /* get supplies */ + for (i = 0; i < ARRAY_SIZE(cmc623_supplies); i++) { + ret = device_get_supply_regulator(dev, cmc623_supplies[i], &priv->supplies[i]); + if (ret) { + log_debug("%s: cannot get %s %d\n", __func__, cmc623_supplies[i], ret); + if (ret != -ENOENT) + return log_ret(ret); + } + } + + /* get control gpios */ + ret = gpio_request_by_name(dev, "enable-gpios", 0, &priv->enable_gpio, GPIOD_IS_OUT); + if (ret) { + log_debug("%s: could not get enable-gpios (%d)\n", __func__, ret); + return ret; + } + + ret = gpio_request_by_name(dev, "bypass-gpios", 0, &priv->bypass_gpio, GPIOD_IS_OUT); + if (ret) { + log_debug("%s: could not get bypass-gpios (%d)\n", __func__, ret); + return ret; + } + + ret = cmc623_hw_init(dev); + if (ret) { + log_debug("%s: error doing hw init, ret %d\n", __func__, ret); + return ret; + } + + ret = cmc623_get_panel(dev); + if (ret) { + log_debug("%s: panel not found, ret %d\n", __func__, ret); + return ret; + } + + panel_get_display_timing(priv->panel, &priv->timing); + + return 0; +} + +static const struct video_bridge_ops cmc623_ops = { + .attach = cmc623_attach, + .set_backlight = cmc623_set_backlight, + .get_display_timing = cmc623_panel_timings, +}; + +static const struct udevice_id cmc623_ids[] = { + { .compatible = "samsung,cmc623" }, + { } +}; + +U_BOOT_DRIVER(samsung_cmc623) = { + .name = "samsung_cmc623", + .id = UCLASS_VIDEO_BRIDGE, + .of_match = cmc623_ids, + .ops = &cmc623_ops, + .bind = dm_scan_fdt_dev, + .probe = cmc623_probe, + .priv_auto = sizeof(struct cmc623_priv), +}; diff --git a/drivers/video/cmc623_backlight.c b/drivers/video/cmc623_backlight.c new file mode 100644 index 00000000000..84b01724a07 --- /dev/null +++ b/drivers/video/cmc623_backlight.c @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2025 Ion Agorria <ion@agorria.com> + */ + +#define LOG_CATEGORY UCLASS_PANEL_BACKLIGHT + +#include <backlight.h> +#include <dm.h> +#include <i2c.h> +#include <log.h> +#include <linux/err.h> +#include <asm/gpio.h> +#include <power/regulator.h> + +#define CMC623_I2C_REG_SELBANK 0x00 +#define CMC623_I2C_REG_PWMCTRL 0xb4 +#define CMC623_I2C_REG_REGMASK 0x28 + +#define CMC623_BL_MIN_BRIGHTNESS 0 +#define CMC623_BL_DEF_BRIGHTNESS 50 +#define CMC623_BL_MAX_BRIGHTNESS 100 + +struct cmc623_backlight_priv { + struct gpio_desc enable_gpio; +}; + +static int cmc623_backlight_enable(struct udevice *dev) +{ + struct cmc623_backlight_priv *priv = dev_get_priv(dev); + + if (dm_gpio_is_valid(&priv->enable_gpio)) + dm_gpio_set_value(&priv->enable_gpio, 1); + + return 0; +} + +static int cmc623_i2c_write(struct udevice *dev, u8 reg, u16 value) +{ + u8 data[2]; + + data[0] = (value >> 8) & 0xff; + data[1] = value & 0xff; + + return dm_i2c_write(dev->parent, reg, data, 2); +} + +static int cmc623_backlight_set_brightness(struct udevice *dev, int percent) +{ + int ret; + u16 brightness; + + if (percent == BACKLIGHT_DEFAULT) + percent = CMC623_BL_DEF_BRIGHTNESS; + + if (percent < CMC623_BL_MIN_BRIGHTNESS) + percent = CMC623_BL_MIN_BRIGHTNESS; + + if (percent > CMC623_BL_MAX_BRIGHTNESS) + percent = CMC623_BL_MAX_BRIGHTNESS; + + brightness = 0x4000 | (percent << 4); + + ret = cmc623_i2c_write(dev, CMC623_I2C_REG_SELBANK, 0x0000); + if (ret) { + log_debug("%s: error at CMC623_I2C_REG_SELBANK (%d)\n", + __func__, ret); + return ret; + } + + ret = cmc623_i2c_write(dev, CMC623_I2C_REG_PWMCTRL, brightness); + if (ret) { + log_debug("%s: error at CMC623_I2C_REG_PWMCTRL (%d)\n", + __func__, ret); + return ret; + } + + ret = cmc623_i2c_write(dev, CMC623_I2C_REG_REGMASK, 0x0000); + if (ret) { + log_debug("%s: error at CMC623_I2C_REG_REGMASK (%d)\n", + __func__, ret); + return ret; + } + + return 0; +} + +static int cmc623_backlight_of_to_plat(struct udevice *dev) +{ + struct cmc623_backlight_priv *priv = dev_get_priv(dev); + + gpio_request_by_name(dev, "enable-gpios", 0, + &priv->enable_gpio, GPIOD_IS_OUT); + + return 0; +} + +static int cmc623_backlight_probe(struct udevice *dev) +{ + if (device_get_uclass_id(dev->parent) != UCLASS_VIDEO_BRIDGE) + return -EPROTONOSUPPORT; + + return 0; +} + +static const struct backlight_ops cmc623_backlight_ops = { + .enable = cmc623_backlight_enable, + .set_brightness = cmc623_backlight_set_brightness, +}; + +static const struct udevice_id cmc623_backlight_ids[] = { + { .compatible = "samsung,cmc623-backlight" }, + { } +}; + +U_BOOT_DRIVER(cmc623_backlight) = { + .name = "cmc623_backlight", + .id = UCLASS_PANEL_BACKLIGHT, + .of_match = cmc623_backlight_ids, + .of_to_plat = cmc623_backlight_of_to_plat, + .probe = cmc623_backlight_probe, + .ops = &cmc623_backlight_ops, + .priv_auto = sizeof(struct cmc623_backlight_priv), +}; diff --git a/drivers/video/samsung-s6e63m0.c b/drivers/video/samsung-s6e63m0.c new file mode 100644 index 00000000000..7497fc0f53a --- /dev/null +++ b/drivers/video/samsung-s6e63m0.c @@ -0,0 +1,393 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2025 Ion Agorria <ion@agorria.com> + */ + +#include <backlight.h> +#include <dm.h> +#include <panel.h> +#include <log.h> +#include <malloc.h> +#include <spi.h> +#include <mipi_display.h> +#include <linux/delay.h> +#include <power/regulator.h> +#include <asm/gpio.h> + +#define S6E63M0_DCS_CMD 0 +#define S6E63M0_DCS_DATA 1 + +#define S6E63M0_INFO_FLAG_PGAMMACTL BIT(0) +#define S6E63M0_INFO_FLAG_GAMMA_DELTA BIT(1) + +#define S6E63M0_GTCON_FLAG_FLIP_H BIT(0) +#define S6E63M0_GTCON_FLAG_FLIP_V BIT(1) + +/* Manufacturer Command Set */ +#define MCS_PENTILE_1 0xb3 +#define MCS_GAMMA_DELTA_Y_RED 0xb5 +#define MCS_GAMMA_DELTA_X_RED 0xb6 +#define MCS_GAMMA_DELTA_Y_GREEN 0xb7 +#define MCS_GAMMA_DELTA_X_GREEN 0xb8 +#define MCS_GAMMA_DELTA_Y_BLUE 0xb9 +#define MCS_GAMMA_DELTA_X_BLUE 0xba +#define MCS_DISCTL 0xf2 +#define MCS_SRCCTL 0xf6 +#define MCS_IFCTL 0xf7 +#define MCS_PANELCTL 0xf8 +#define MCS_PGAMMACTL 0xfa + +#define MCS_PANELCTL_LEN 14 +#define MCS_IFCTL_LEN 3 +#define MCS_PGAMMACTL_LEN 22 +#define MCS_GAMMA_DELTA_Y_LEN 32 +#define MCS_GAMMA_DELTA_X_LEN 16 + +struct s6e63m0_priv { + struct udevice *vdd3; + struct udevice *vci; + + struct s6e63m0_info *info; + + struct gpio_desc reset_gpio; + + u8 gtcon; +}; + +struct s6e63m0_info { + const u32 flags; + struct display_timing timing; + const u8 cmd_mcs_panelctl[MCS_PANELCTL_LEN]; + const u8 cmd_mcs_pgammactl_1[MCS_PGAMMACTL_LEN]; + const u8 cmd_mcs_pgammactl_2; + const u8 cmd_mcs_gamma_delta_y[MCS_GAMMA_DELTA_Y_LEN]; + const u8 cmd_mcs_gamma_delta_x[MCS_GAMMA_DELTA_X_LEN]; +}; + +static const struct s6e63m0_info s6e63m0_generic_info = { + .flags = S6E63M0_INFO_FLAG_GAMMA_DELTA, + .timing = { + .pixelclock.typ = 25628, + .hactive.typ = 480, + .hfront_porch.typ = 16, + .hback_porch.typ = 16, + .hsync_len.typ = 2, + .vactive.typ = 800, + .vfront_porch.typ = 28, + .vback_porch.typ = 1, + .vsync_len.typ = 2, + .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW, + }, + .cmd_mcs_panelctl = { + 0x01, /* DOCT */ 0x27, /* CLWEA */ + 0x27, /* CLWEB*/ 0x07, /* CLTE */ + 0x07, /* SHE */ 0x54, /* FLTE */ + 0x9F, /* FLWE */ 0x63, /* SCTE */ + 0x8F, /* SCWE */ 0x1A, /* INTE */ + 0x33, /* INWE */ 0x0D, /* EMPS */ + 0x00, /* E_INTE */ 0x00 /* E_INWE */ + }, + .cmd_mcs_pgammactl_1 = { + 0x00, 0x18, 0x08, 0x24, 0x64, 0x56, 0x33, 0xb6, + 0xba, 0xa8, 0xac, 0xb1, 0x9d, 0xc1, 0xc1, 0xb7, + 0x00, 0x9c, 0x00, 0x9f, 0x00, 0xd6 + }, + .cmd_mcs_pgammactl_2 = 0x01, + .cmd_mcs_gamma_delta_y = { + 0x2c, 0x12, 0x0c, 0x0a, 0x10, 0x0e, 0x17, 0x13, + 0x1f, 0x1a, 0x2a, 0x24, 0x1f, 0x1b, 0x1a, 0x17, + 0x2b, 0x26, 0x22, 0x20, 0x3a, 0x34, 0x30, 0x2c, + 0x29, 0x26, 0x25, 0x23, 0x21, 0x20, 0x1e, 0x1e + }, + .cmd_mcs_gamma_delta_x = { + 0x00, 0x00, 0x11, 0x22, 0x33, 0x44, 0x44, 0x44, + 0x55, 0x55, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66 + }, +}; + +static const struct s6e63m0_info samsung_bose_panel_info = { + .flags = S6E63M0_INFO_FLAG_PGAMMACTL | S6E63M0_INFO_FLAG_GAMMA_DELTA, + .timing = { + .pixelclock.typ = 24000000, + .hactive.typ = 480, + .hfront_porch.typ = 16, + .hback_porch.typ = 14, + .hsync_len.typ = 2, + .vactive.typ = 800, + .vfront_porch.typ = 28, + .vback_porch.typ = 1, + .vsync_len.typ = 2, + .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW | + DISPLAY_FLAGS_DE_LOW | DISPLAY_FLAGS_PIXDATA_NEGEDGE, + }, + .cmd_mcs_panelctl = { + 0x01, /* DOCT */ 0x27, /* CLWEA */ + 0x27, /* CLWEB*/ 0x07, /* CLTE */ + 0x07, /* SHE */ 0x54, /* FLTE */ + 0x9F, /* FLWE */ 0x63, /* SCTE */ + 0x86, /* SCWE */ 0x1A, /* INTE */ + 0x33, /* INWE */ 0x0D, /* EMPS */ + 0x00, /* E_INTE */ 0x00 /* E_INWE */ + }, + .cmd_mcs_pgammactl_1 = { + 0x02, 0x18, 0x08, 0x24, 0x70, 0x6e, 0x4e, 0xbc, + 0xc0, 0xaf, 0xb3, 0xb8, 0xa5, 0xc5, 0xc7, 0xbb, + 0x00, 0xb9, 0x00, 0xb8, 0x00, 0xfc + }, + .cmd_mcs_pgammactl_2 = 0x03, + .cmd_mcs_gamma_delta_y = { + 0x2c, 0x12, 0x0c, 0x0a, 0x10, 0x0e, 0x17, 0x13, + 0x1f, 0x1a, 0x2a, 0x24, 0x1f, 0x1b, 0x1a, 0x17, + 0x2b, 0x26, 0x22, 0x20, 0x3a, 0x34, 0x30, 0x2c, + 0x29, 0x26, 0x25, 0x23, 0x21, 0x20, 0x1e, 0x1e + }, + .cmd_mcs_gamma_delta_x = { + 0x00, 0x00, 0x11, 0x22, 0x33, 0x44, 0x44, 0x44, + 0x55, 0x55, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66 + }, +}; + +static int s6e63m0_dcs_write(struct udevice *dev, u8 cmd, const u8 *seq, size_t len) +{ + int ret; + u8 data[2]; + int i; + + data[0] = S6E63M0_DCS_CMD; + data[1] = cmd; + + ret = dm_spi_xfer(dev, 9, &data, NULL, SPI_XFER_ONCE); + if (ret) + return ret; + + for (i = 0; i < len; i++) { + data[0] = S6E63M0_DCS_DATA; + data[1] = seq[i]; + + ret = dm_spi_xfer(dev, 9, &data, NULL, SPI_XFER_ONCE); + if (ret) + return ret; + } + + return 0; +} + +#define s6e63m0_dcs_write_seq_static(dev, cmd, seq ...) ({ \ + static const u8 d[] = { seq }; \ + ret = s6e63m0_dcs_write(dev, cmd, d, ARRAY_SIZE(d)); \ + if (ret) \ + return ret; \ +}) + +static int s6e63m0_enable_backlight(struct udevice *dev) +{ + struct s6e63m0_priv *priv = dev_get_priv(dev); + struct s6e63m0_info *info = priv->info; + u8 cmd_mcs_ifctl[MCS_IFCTL_LEN]; + int ret; + + ret = s6e63m0_dcs_write(dev, MCS_PANELCTL, info->cmd_mcs_panelctl, MCS_PANELCTL_LEN); + if (ret) + return ret; + + s6e63m0_dcs_write_seq_static(dev, MCS_DISCTL, + 0x02, /* Number of Line */ + 0x03, /* VBP */ + 0x1c, /* VFP */ + 0x10, /* HBP */ + 0x10); /* HFP */ + + cmd_mcs_ifctl[0] = priv->gtcon; /* GTCON */ + cmd_mcs_ifctl[1] = 0x00; /* Display Mode */ + cmd_mcs_ifctl[2] = 0x00; /* Vsync/Hsync, DOCCLK, RGB mode */ + ret = s6e63m0_dcs_write(dev, MCS_IFCTL, cmd_mcs_ifctl, MCS_IFCTL_LEN); + if (ret) + return ret; + + if (info->flags & S6E63M0_INFO_FLAG_PGAMMACTL) { + ret = s6e63m0_dcs_write(dev, MCS_PGAMMACTL, info->cmd_mcs_pgammactl_1, + MCS_PGAMMACTL_LEN); + if (ret) + return ret; + + s6e63m0_dcs_write(dev, MCS_PGAMMACTL, &info->cmd_mcs_pgammactl_2, 1); + } + + s6e63m0_dcs_write_seq_static(dev, MCS_SRCCTL, 0x00, 0x8e, 0x07); + s6e63m0_dcs_write_seq_static(dev, MCS_PENTILE_1, 0x6c); + + if (info->flags & S6E63M0_INFO_FLAG_GAMMA_DELTA) { + ret = s6e63m0_dcs_write(dev, MCS_GAMMA_DELTA_Y_RED, info->cmd_mcs_gamma_delta_y, + MCS_GAMMA_DELTA_Y_LEN); + if (ret) + return ret; + + ret = s6e63m0_dcs_write(dev, MCS_GAMMA_DELTA_X_RED, info->cmd_mcs_gamma_delta_x, + MCS_GAMMA_DELTA_X_LEN); + if (ret) + return ret; + + ret = s6e63m0_dcs_write(dev, MCS_GAMMA_DELTA_Y_GREEN, info->cmd_mcs_gamma_delta_y, + MCS_GAMMA_DELTA_Y_LEN); + if (ret) + return ret; + + ret = s6e63m0_dcs_write(dev, MCS_GAMMA_DELTA_X_GREEN, info->cmd_mcs_gamma_delta_x, + MCS_GAMMA_DELTA_X_LEN); + if (ret) + return ret; + + ret = s6e63m0_dcs_write(dev, MCS_GAMMA_DELTA_Y_BLUE, info->cmd_mcs_gamma_delta_y, + MCS_GAMMA_DELTA_Y_LEN); + if (ret) + return ret; + + ret = s6e63m0_dcs_write(dev, MCS_GAMMA_DELTA_X_BLUE, info->cmd_mcs_gamma_delta_x, + MCS_GAMMA_DELTA_X_LEN); + if (ret) + return ret; + } + + s6e63m0_dcs_write_seq_static(dev, MIPI_DCS_EXIT_SLEEP_MODE); + s6e63m0_dcs_write_seq_static(dev, MIPI_DCS_SET_DISPLAY_ON); + + return 0; +} + +static int s6e63m0_set_backlight(struct udevice *dev, int percent) +{ + return 0; +} + +static int s6e63m0_get_display_timing(struct udevice *dev, struct display_timing *timing) +{ + struct s6e63m0_priv *priv = dev_get_priv(dev); + + memcpy(timing, &priv->info->timing, sizeof(*timing)); + + return 0; +} + +static int s6e63m0_of_to_plat(struct udevice *dev) +{ + struct s6e63m0_priv *priv = dev_get_priv(dev); + int ret; + + ret = device_get_supply_regulator(dev, "vdd3-supply", &priv->vdd3); + if (ret) { + log_debug("%s: cannot get vdd3-supply: ret = %d\n", + __func__, ret); + return ret; + } + + ret = device_get_supply_regulator(dev, "vci-supply", &priv->vci); + if (ret) { + log_debug("%s: cannot get vci-supply: ret = %d\n", + __func__, ret); + return ret; + } + + ret = gpio_request_by_name(dev, "reset-gpios", 0, + &priv->reset_gpio, GPIOD_IS_OUT); + if (ret) { + log_debug("%s: cannot decode reset-gpios (%d)\n", + __func__, ret); + return ret; + } + + if (dev_read_bool(dev, "flip-horizontal")) + priv->gtcon |= S6E63M0_GTCON_FLAG_FLIP_H; + + if (dev_read_bool(dev, "flip-vertical")) + priv->gtcon |= S6E63M0_GTCON_FLAG_FLIP_V; + + return 0; +} + +static int s6e63m0_hw_init(struct udevice *dev) +{ + struct s6e63m0_priv *priv = dev_get_priv(dev); + int ret; + + ret = dm_gpio_set_value(&priv->reset_gpio, 1); + if (ret) { + log_debug("%s: error entering reset (%d)\n", __func__, ret); + return ret; + } + + ret = regulator_set_enable_if_allowed(priv->vdd3, 1); + if (ret) { + log_debug("%s: enabling vdd3-supply failed (%d)\n", + __func__, ret); + return ret; + } + + mdelay(1); + + ret = regulator_set_enable_if_allowed(priv->vci, 1); + if (ret) { + log_debug("%s: enabling vci-supply failed (%d)\n", + __func__, ret); + return ret; + } + + mdelay(26); + + ret = dm_gpio_set_value(&priv->reset_gpio, 0); + if (ret) { + log_debug("%s: error exiting reset (%d)\n", __func__, ret); + return ret; + } + + mdelay(10); + + return 0; +} + +static int s6e63m0_probe(struct udevice *dev) +{ + struct s6e63m0_priv *priv = dev_get_priv(dev); + struct spi_slave *slave = dev_get_parent_priv(dev); + int ret; + + if (device_get_uclass_id(dev->parent) != UCLASS_SPI) + return -EPROTONOSUPPORT; + + ret = spi_claim_bus(slave); + if (ret) { + log_err("SPI bus allocation failed (%d)\n", ret); + return ret; + } + + priv->info = (struct s6e63m0_info *)dev_get_driver_data(dev); + + return s6e63m0_hw_init(dev); +} + +static const struct panel_ops s6e63m0_ops = { + .enable_backlight = s6e63m0_enable_backlight, + .set_backlight = s6e63m0_set_backlight, + .get_display_timing = s6e63m0_get_display_timing, +}; + +static const struct udevice_id s6e63m0_ids[] = { + { + .compatible = "samsung,s6e63m0", + .data = (ulong)&s6e63m0_generic_info + }, + { + .compatible = "samsung,bose-panel", + .data = (ulong)&samsung_bose_panel_info + }, + { } +}; + +U_BOOT_DRIVER(samsung_s6e63m0) = { + .name = "samsung_s6e63m0", + .id = UCLASS_PANEL, + .of_match = s6e63m0_ids, + .ops = &s6e63m0_ops, + .of_to_plat = s6e63m0_of_to_plat, + .probe = s6e63m0_probe, + .priv_auto = sizeof(struct s6e63m0_priv), +}; diff --git a/drivers/video/sony-l4f00430t01.c b/drivers/video/sony-l4f00430t01.c new file mode 100644 index 00000000000..2303eb86143 --- /dev/null +++ b/drivers/video/sony-l4f00430t01.c @@ -0,0 +1,210 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2025 Ion Agorria <ion@agorria.com> + */ + +#include <backlight.h> +#include <dm.h> +#include <panel.h> +#include <log.h> +#include <spi.h> +#include <mipi_display.h> +#include <linux/delay.h> +#include <power/regulator.h> +#include <asm/gpio.h> + +#define SONY_L4F00430T01_DCS_CMD 0 +#define SONY_L4F00430T01_DCS_DATA 1 + +struct sony_l4f00430t01_priv { + struct udevice *vdd1v8; + struct udevice *vdd3v0; + + struct udevice *backlight; + + struct gpio_desc reset_gpio; +}; + +static struct display_timing default_timing = { + .pixelclock.typ = 24000000, + .hactive.typ = 480, + .hfront_porch.typ = 10, + .hback_porch.typ = 20, + .hsync_len.typ = 10, + .vactive.typ = 800, + .vfront_porch.typ = 3, + .vback_porch.typ = 4, + .vsync_len.typ = 2, + .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW | + DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_NEGEDGE, +}; + +static int sony_l4f00430t01_write(struct udevice *dev, u8 cmd, const u8 *seq, int len) +{ + u8 data[2]; + int i, ret; + + data[0] = SONY_L4F00430T01_DCS_CMD; + data[1] = cmd; + + ret = dm_spi_xfer(dev, 9, &data, NULL, SPI_XFER_ONCE); + if (ret) + return ret; + + for (i = 0; i < len; i++) { + data[0] = SONY_L4F00430T01_DCS_DATA; + data[1] = seq[i]; + + ret = dm_spi_xfer(dev, 9, &data, NULL, SPI_XFER_ONCE); + if (ret) + return ret; + } + + return 0; +} + +#define sony_l4f00430t01_write_seq(dev, cmd, seq...) do { \ + static const u8 b[] = { seq }; \ + sony_l4f00430t01_write(dev, cmd, b, ARRAY_SIZE(b)); \ + } while (0) + +static int sony_l4f00430t01_enable_backlight(struct udevice *dev) +{ + sony_l4f00430t01_write_seq(dev, MIPI_DCS_SET_ADDRESS_MODE, 0xd4); + mdelay(25); + + sony_l4f00430t01_write_seq(dev, MIPI_DCS_EXIT_SLEEP_MODE); + mdelay(150); + + sony_l4f00430t01_write_seq(dev, MIPI_DCS_SET_DISPLAY_ON); + + return 0; +} + +static int sony_l4f00430t01_set_backlight(struct udevice *dev, int percent) +{ + struct sony_l4f00430t01_priv *priv = dev_get_priv(dev); + int ret; + + ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev, + "backlight", &priv->backlight); + if (ret) { + log_debug("%s: cannot get backlight: ret = %d\n", + __func__, ret); + return ret; + } + + ret = backlight_enable(priv->backlight); + if (ret) + return ret; + + return backlight_set_brightness(priv->backlight, percent); +} + +static int sony_l4f00430t01_get_display_timing(struct udevice *dev, + struct display_timing *timing) +{ + memcpy(timing, &default_timing, sizeof(*timing)); + return 0; +} + +static int sony_l4f00430t01_of_to_plat(struct udevice *dev) +{ + struct sony_l4f00430t01_priv *priv = dev_get_priv(dev); + int ret; + + ret = device_get_supply_regulator(dev, "vdd1v8-supply", &priv->vdd1v8); + if (ret) { + log_debug("%s: cannot get vdd1v8-supply: ret = %d\n", + __func__, ret); + return ret; + } + + ret = device_get_supply_regulator(dev, "vdd3v0-supply", &priv->vdd3v0); + if (ret) { + log_debug("%s: cannot get vdd3v0-supply: ret = %d\n", + __func__, ret); + return ret; + } + + ret = gpio_request_by_name(dev, "reset-gpios", 0, + &priv->reset_gpio, GPIOD_IS_OUT); + if (ret) { + log_debug("%s: cannot decode reset-gpios (%d)\n", + __func__, ret); + return ret; + } + + return 0; +} + +static int sony_l4f00430t01_hw_init(struct udevice *dev) +{ + struct sony_l4f00430t01_priv *priv = dev_get_priv(dev); + int ret; + + ret = dm_gpio_set_value(&priv->reset_gpio, 1); + if (ret) { + log_debug("%s: error entering reset (%d)\n", __func__, ret); + return ret; + } + + ret = regulator_set_enable_if_allowed(priv->vdd1v8, 1); + if (ret) { + log_debug("%s: enabling vdd1v8-supply failed (%d)\n", + __func__, ret); + return ret; + } + + ret = regulator_set_enable_if_allowed(priv->vdd3v0, 1); + if (ret) { + log_debug("%s: enabling vdd3v0-supply failed (%d)\n", + __func__, ret); + return ret; + } + mdelay(15); + + ret = dm_gpio_set_value(&priv->reset_gpio, 0); + if (ret) { + log_debug("%s: error exiting reset (%d)\n", __func__, ret); + return ret; + } + mdelay(100); + + return 0; +} + +static int sony_l4f00430t01_probe(struct udevice *dev) +{ + struct spi_slave *slave = dev_get_parent_priv(dev); + int ret; + + ret = spi_claim_bus(slave); + if (ret) { + log_err("SPI bus allocation failed (%d)\n", ret); + return ret; + } + + return sony_l4f00430t01_hw_init(dev); +} + +static const struct panel_ops sony_l4f00430t01_ops = { + .enable_backlight = sony_l4f00430t01_enable_backlight, + .set_backlight = sony_l4f00430t01_set_backlight, + .get_display_timing = sony_l4f00430t01_get_display_timing, +}; + +static const struct udevice_id sony_l4f00430t01_ids[] = { + { .compatible = "sony,l4f00430t01" }, + { } +}; + +U_BOOT_DRIVER(sony_l4f00430t01) = { + .name = "sony_l4f00430t01", + .id = UCLASS_PANEL, + .of_match = sony_l4f00430t01_ids, + .ops = &sony_l4f00430t01_ops, + .of_to_plat = sony_l4f00430t01_of_to_plat, + .probe = sony_l4f00430t01_probe, + .priv_auto = sizeof(struct sony_l4f00430t01_priv), +}; diff --git a/drivers/video/tegra/dc.c b/drivers/video/tegra/dc.c index f0e3d2c993f..ced49718834 100644 --- a/drivers/video/tegra/dc.c +++ b/drivers/video/tegra/dc.c @@ -238,8 +238,24 @@ static void rgb_enable(struct tegra_lcd_priv *priv) else value &= ~LVS_OUTPUT_POLARITY_LOW; + /* configure pixel data signal polarity */ + if (dt->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE) + value &= ~LSC0_OUTPUT_POLARITY_LOW; + else + value |= LSC0_OUTPUT_POLARITY_LOW; + writel(value, &com->pin_output_polarity[1]); + /* configure data enable signal polarity */ + value = readl(&com->pin_output_polarity[3]); + + if (dt->flags & DISPLAY_FLAGS_DE_LOW) + value |= LSPI_OUTPUT_POLARITY_LOW; + else + value &= ~LSPI_OUTPUT_POLARITY_LOW; + + writel(value, &com->pin_output_polarity[3]); + for (i = 0; i < PIN_OUTPUT_SEL_COUNT; i++) writel(rgb_sel_tab[i], &com->pin_output_sel[i]); } diff --git a/scripts/Makefile.xpl b/scripts/Makefile.xpl index 03a2f151d91..3e940bf562d 100644 --- a/scripts/Makefile.xpl +++ b/scripts/Makefile.xpl @@ -390,7 +390,6 @@ $(obj)/$(BOARD)-spl.bin: $(obj)/u-boot-spl.bin endif $(obj)/u-boot-spl.ldr: $(obj)/u-boot-spl - $(CREATE_LDR_ENV) $(LDR) -T $(CONFIG_LDR_CPU) -c $@ $< $(LDR_FLAGS) $(BOARD_SIZE_CHECK) diff --git a/test/py/tests/test_fit_mkimage_validate.py b/test/py/tests/test_fit_mkimage_validate.py index ef974c8c762..170b2a8cbbb 100644 --- a/test/py/tests/test_fit_mkimage_validate.py +++ b/test/py/tests/test_fit_mkimage_validate.py @@ -57,6 +57,8 @@ def test_fit_invalid_image_reference(ubman): assert result.returncode != 0, "mkimage should fail due to missing image reference" assert "references undefined image 'notexist'" in result.stderr +@pytest.mark.boardspec('sandbox') +@pytest.mark.requiredtool('dtc') def test_fit_invalid_default_config(ubman): """Test that mkimage fails when default config is missing""" |