diff options
415 files changed, 15863 insertions, 3715 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 2477923a520..87991cccddb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1330,7 +1330,7 @@ F: doc/arch/riscv.rst F: doc/usage/sbi.rst F: drivers/sysreset/sysreset_sbi.c F: drivers/timer/andes_plmt_timer.c -F: drivers/timer/sifive_clint_timer.c +F: drivers/timer/riscv_aclint_timer.c F: tools/prelink-riscv.c RISC-V CANAAN KENDRYTE K210 @@ -2430,27 +2430,6 @@ Hit 'q': [q, b, e, ?] ## Application terminated, rc = 0x0 -Minicom warning: -================ - -Over time, many people have reported problems when trying to use the -"minicom" terminal emulation program for serial download. I (wd) -consider minicom to be broken, and recommend not to use it. Under -Unix, I recommend to use C-Kermit for general purpose use (and -especially for kermit binary protocol download ("loadb" command), and -use "cu" for S-Record download ("loads" command). See -https://www.denx.de/wiki/view/DULG/SystemSetup#Section_4.3. -for help with kermit. - - -Nevertheless, if you absolutely want to use it try adding this -configuration to your "File transfer protocols" section: - - Name Program Name U/D FullScr IO-Red. Multi - X kermit /usr/bin/kermit -i -l %l -s Y U Y N N - Y kermit /usr/bin/kermit -i -l %l -r N D Y N N - - Implementation Internals: ========================= diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 99264a64780..b3115b054c8 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -882,7 +882,7 @@ config ARCH_IMX8ULP select SUPPORT_SPL select GPIO_EXTRA_HEADER select MISC - select IMX_SENTINEL + select IMX_ELE imply CMD_DM config ARCH_IMX9 @@ -894,7 +894,7 @@ config ARCH_IMX9 select SUPPORT_SPL select GPIO_EXTRA_HEADER select MISC - select IMX_SENTINEL + select IMX_ELE imply CMD_DM config ARCH_IMXRT @@ -912,14 +912,12 @@ config ARCH_MX23 select CPU_ARM926EJS select GPIO_EXTRA_HEADER select MACH_IMX - select PL011_SERIAL select SUPPORT_SPL config ARCH_MX28 bool "NXP i.MX28 family" select CPU_ARM926EJS select GPIO_EXTRA_HEADER - select PL011_SERIAL select MACH_IMX select SUPPORT_SPL diff --git a/arch/arm/cpu/arm926ejs/mxs/spl_boot.c b/arch/arm/cpu/arm926ejs/mxs/spl_boot.c index 763d79e8036..5598c552ab9 100644 --- a/arch/arm/cpu/arm926ejs/mxs/spl_boot.c +++ b/arch/arm/cpu/arm926ejs/mxs/spl_boot.c @@ -128,8 +128,10 @@ void mxs_common_spl_init(const uint32_t arg, const uint32_t *resptr, mxs_iomux_setup_multiple_pads(iomux_setup, iomux_size); - mxs_spl_console_init(); - debug("SPL: Serial Console Initialised\n"); + if (!CONFIG_IS_ENABLED(DM_SERIAL)) { + mxs_spl_console_init(); + debug("SPL: Serial Console Initialised\n"); + } mxs_power_init(); diff --git a/arch/arm/cpu/arm926ejs/mxs/spl_power_init.c b/arch/arm/cpu/arm926ejs/mxs/spl_power_init.c index c33170f06d3..7ea029e3712 100644 --- a/arch/arm/cpu/arm926ejs/mxs/spl_power_init.c +++ b/arch/arm/cpu/arm926ejs/mxs/spl_power_init.c @@ -41,6 +41,29 @@ static void mxs_power_clock2xtal(void) &clkctrl_regs->hw_clkctrl_clkseq_set); } +static void mxs_power_regs_dump(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + + debug("ctrl:\t\t 0x%x\n", readl(&power_regs->hw_power_ctrl)); + debug("5vctrl:\t\t 0x%x\n", readl(&power_regs->hw_power_5vctrl)); + debug("minpwr:\t\t 0x%x\n", readl(&power_regs->hw_power_minpwr)); + debug("charge:\t\t 0x%x\n", readl(&power_regs->hw_power_charge)); + debug("vddctrl:\t 0x%x\n", readl(&power_regs->hw_power_vdddctrl)); + debug("vddactrl:\t 0x%x\n", readl(&power_regs->hw_power_vddactrl)); + debug("vddioctrl:\t 0x%x\n", readl(&power_regs->hw_power_vddioctrl)); + debug("vddmemctrl:\t 0x%x\n", readl(&power_regs->hw_power_vddmemctrl)); + debug("dcdc4p2:\t 0x%x\n", readl(&power_regs->hw_power_dcdc4p2)); + debug("misc:\t\t 0x%x\n", readl(&power_regs->hw_power_misc)); + debug("dclimits:\t 0x%x\n", readl(&power_regs->hw_power_dclimits)); + debug("loopctrl:\t 0x%x\n", readl(&power_regs->hw_power_loopctrl)); + debug("sts:\t\t 0x%x\n", readl(&power_regs->hw_power_sts)); + debug("speed:\t\t 0x%x\n", readl(&power_regs->hw_power_speed)); + debug("battmonitor:\t 0x%x\n", + readl(&power_regs->hw_power_battmonitor)); +} + /** * mxs_power_clock2pll() - Switch CPU core clock source to PLL * @@ -752,7 +775,19 @@ static void mxs_batt_boot(void) POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK, 0x8 << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET); - mxs_power_enable_4p2(); + if (CONFIG_IS_ENABLED(MXS_PMU_MINIMAL_VDD5V_CURRENT)) + setbits_le32(&power_regs->hw_power_5vctrl, + POWER_5VCTRL_ILIMIT_EQ_ZERO); + + if (CONFIG_IS_ENABLED(MXS_PMU_DISABLE_BATT_CHARGE)) { + writel(POWER_CHARGE_PWD_BATTCHRG, + &power_regs->hw_power_charge_set); + writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK, + &power_regs->hw_power_5vctrl_set); + } + + if (CONFIG_IS_ENABLED(MXS_PMU_ENABLE_4P2_LINEAR_REGULATOR)) + mxs_power_enable_4p2(); } /** @@ -1268,6 +1303,7 @@ void mxs_power_init(void) POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr); writel(POWER_5VCTRL_PWDN_5VBRNOUT, &power_regs->hw_power_5vctrl_set); + mxs_power_regs_dump(); early_delay(1000); } diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index 17f506a8fa0..07b26df2750 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -305,7 +305,8 @@ dtb-$(CONFIG_ARCH_MVEBU) += \ cn9132-db-B.dtb \ cn9130-crb-A.dtb \ cn9130-crb-B.dtb \ - ac5-98dx35xx-rd.dtb + ac5-98dx35xx-rd.dtb \ + ac5-98dx35xx-atl-x240.dtb endif dtb-$(CONFIG_ARCH_SYNQUACER) += synquacer-sc2a11-developerbox.dtb @@ -1017,6 +1018,7 @@ dtb-$(CONFIG_ARCH_IMX8M) += \ imx8mp-phyboard-pollux-rdk.dtb \ imx8mp-venice.dtb \ imx8mp-venice-gw74xx.dtb \ + imx8mp-venice-gw7905-2x.dtb \ imx8mp-verdin-wifi-dev.dtb \ imx8mq-pico-pi.dtb \ imx8mq-kontron-pitx-imx8m.dtb \ diff --git a/arch/arm/dts/ac5-98dx25xx.dtsi b/arch/arm/dts/ac5-98dx25xx.dtsi index 3c68355f323..f53b4781d7f 100644 --- a/arch/arm/dts/ac5-98dx25xx.dtsi +++ b/arch/arm/dts/ac5-98dx25xx.dtsi @@ -251,6 +251,15 @@ status = "disabled"; }; + nand: nand-controller@805b0000 { + compatible = "marvell,mvebu-ac5-pxa3xx-nand"; + reg = <0x0 0x805b0000 0x0 0x54>; + #address-cells = <0x00000001>; + marvell,nand-enable-arbiter; + num-cs = <0x00000001>; + status = "disabled"; + }; + gic: interrupt-controller@80600000 { compatible = "arm,gic-v3"; #interrupt-cells = <3>; diff --git a/arch/arm/dts/ac5-98dx35xx-atl-x240.dts b/arch/arm/dts/ac5-98dx35xx-atl-x240.dts new file mode 100644 index 00000000000..820ec18b435 --- /dev/null +++ b/arch/arm/dts/ac5-98dx35xx-atl-x240.dts @@ -0,0 +1,212 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) + +/dts-v1/; + +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/interrupt-controller/irq.h> +#include "ac5-98dx35xx.dtsi" + +/ { + model = "Allied Telesis x240"; + compatible = "alliedtelesis,x240", "marvell,ac5x", "marvell,ac5"; + + aliases { + serial0 = &uart0; + spiflash0 = &spiflash0; + gpio0 = &gpio0; + gpio1 = &gpio1; + spi0 = &spi0; + i2c0 = &i2c0; + usb0 = &usb0; + pinctrl0 = &pinctrl0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + boot-board { + compatible = "atl,boot-board"; + present-gpio = <&gpio1 6 GPIO_ACTIVE_HIGH>; + override-gpio = <&gpio1 2 GPIO_ACTIVE_HIGH>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + fault { + label = "fault:red"; + gpios = <&system_gpio 11 GPIO_ACTIVE_LOW>; + default-state = "on"; + }; + }; +}; + +&nand { + pinctrl-names = "default"; + pinctrl-0 = <&nand_pins>; + + nand-ecc-strength = <4>; + nand-ecc-step-size = <512>; + status = "okay"; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@user { + reg = <0x00000000 0x10000000>; + label = "user"; + }; + }; +}; + +&uart0 { + status = "okay"; +}; + +&usb0 { + status = "okay"; +}; + +&i2c0 { + status = "okay"; + + mux@71 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "nxp,pca9546"; + reg = <0x71>; + i2c-mux-idle-disconnect; + reset-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>; /* MPP36 */ + status = "okay"; + + i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + + hwmon@2e { + compatible = "adi,adt7476"; + reg = <0x2e>; + }; + + rtc@68 { + compatible = "adi,max31331"; + reg = <0x68>; + }; + + system_gpio: gpio@27 { + compatible = "nxp,pca9555"; + gpio-controller; + #gpio-cells= <2>; + reg = <0x27>; + interrupt-parent = <&gpio0>; + interrupts = <25 IRQ_TYPE_LEVEL_LOW>; /* MPP25 */ + }; + }; + }; +}; + +&spi0 { + status = "okay"; + spiflash0: flash@0 { + compatible = "jedec,spi-nor"; + spi-max-frequency = <50000000>; + spi-tx-bus-width = <1>; /* 1-single, 2-dual, 4-quad */ + spi-rx-bus-width = <1>; /* 1-single, 2-dual, 4-quad */ + reg = <0>; + + #address-cells = <1>; + #size-cells = <1>; + }; +}; + +&gpio0 { + phy-reset { + gpio-hog; + gpios = <19 GPIO_ACTIVE_LOW>; + output-high; + line-name = "phy-reset"; + }; + + usb-en { + gpio-hog; + gpios = <28 GPIO_ACTIVE_HIGH>; + output-high; + line-name = "usb-en"; + }; + + led-oe-n { + gpio-hog; + gpios = <23 GPIO_ACTIVE_LOW>; + output-low; + line-name = "led-oe-n"; + }; +}; + +&gpio1 { + nand-protect { + gpio-hog; + gpios = <8 GPIO_ACTIVE_LOW>; + output-low; + line-name = "nand-protect"; + }; +}; + +&pinctrl0 { + /* + * MPP Bus: MPP# + * NF_IO [0-7] + * NF_Wen [8] + * NF_ALE [9] + * NF_CLE [10] + * NF_Cen [11] + * QSPI_SCK/SPI0_SCK [12] + * QSPI_CSn/SPI0_CSn [13] + * QSPI_DIO[0]/SPI0_MOSI [14] + * QSPI_DIO[1]/SPI0_MISO [15] + * NF_Ren [16] + * NF_RBn [17] + * WD_INTn [18] + * B_B_OVRIDE_N [19] + * GREEN_SW_N [20] + * PHY_INT_N[0] [21] + * SPI_WPn [22] + * LED_OE_N [23] + * USB_PWR_FLT_N [24] + * SFP_INT_N [25] + * I2C0_SCL [26] + * I2C0_SDA [27] + * USB_EN [28] + * MONITOR_INT_N [29] + * XM1_MDC [30] + * XM1_MDIO [31] + * UA0_RXD [32] + * UA0_TXD [33] + * PHY_RST0n [34] + * TPM_INT_N [35] + * I2CMUX_RESET_N [36] + * SPI_SRAM_SEL_N [37] + * B_B_PRESENT [38] + * SPI_FLASH_SEL_N [39] + * NF_WP_N [40] + * POE_INT_N [41] + * PoE_RST_N [42] + * LED0_CLK [43] + * LED0_STB [44] + * LED0_DATA [45] + */ + /* 0 1 2 3 4 5 6 7 8 9 */ + pin-func = < 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff + 0xff 0xff 1 1 1 1 0xff 0xff 0 0 + 0 0 0 0 0 0 1 1 0 0 + 1 1 1 1 0 0 0 0 0 0 + 0 0 0 1 1 1 >; + + nand_pins: nand-pins { + marvell,pins = <0 1 2 3 4 5 6 7 8 9 10 11 16 17>; + marvell,function = <2>; + }; +}; diff --git a/arch/arm/dts/ac5-98dx35xx-rd.dts b/arch/arm/dts/ac5-98dx35xx-rd.dts index d9f217cd4a5..1dc85bb7ef2 100644 --- a/arch/arm/dts/ac5-98dx35xx-rd.dts +++ b/arch/arm/dts/ac5-98dx35xx-rd.dts @@ -31,7 +31,6 @@ usb0 = &usb0; usb1 = &usb1; pinctrl0 = &pinctrl0; - sar-reg0 = "/config-space/sar-reg"; }; usb1phy: usb-phy { diff --git a/arch/arm/dts/armada-385-thecus-n2350.dts b/arch/arm/dts/armada-385-thecus-n2350.dts index fc29c4d25a8..253cf011308 100644 --- a/arch/arm/dts/armada-385-thecus-n2350.dts +++ b/arch/arm/dts/armada-385-thecus-n2350.dts @@ -23,7 +23,7 @@ stdout-path = "serial0:115200n8"; }; - memory { + memory@0 { device_type = "memory"; reg = <0x00000000 0x40000000>; /* 1GB */ }; @@ -37,43 +37,43 @@ }; - usb3_0_phy: usb3_0_phy { + usb3_0_phy: usb-phy { compatible = "usb-nop-xceiv"; vcc-supply = <&usb3_0_power>; + #phy-cells = <0>; }; - usb3_1_phy: usb3_1_phy { + usb3_1_phy: usb-phy { compatible = "usb-nop-xceiv"; vcc-supply = <&usb3_1_power>; + #phy-cells = <0>; }; - gpio-keys { + keys { compatible = "gpio-keys"; - #address-cells = <1>; - #size-cells = <0>; pinctrl-0 = <&pmx_power_button &pmx_copy_button &pmx_reset_button>; pinctrl-names = "default"; - button@1 { + button-1 { label = "Power Button"; linux,code = <KEY_POWER>; gpios = <&gpio1 17 GPIO_ACTIVE_HIGH>; }; - button@2 { + button-2 { label = "Copy Button"; linux,code = <KEY_COPY>; gpios = <&gpio1 20 GPIO_ACTIVE_HIGH>; }; - button@3 { + button-3 { label = "Reset Button"; linux,code = <KEY_RESTART>; gpios = <&gpio1 18 GPIO_ACTIVE_HIGH>; }; }; - gpio-leds { + leds { compatible = "gpio-leds"; pinctrl-0 = <&pmx_sata1_white_led &pmx_sata1_red_led @@ -88,142 +88,142 @@ pinctrl-names = "default"; - white_sata1 { + led-1 { label = "n2350:white:sata1"; gpios = <&gpio0 20 GPIO_ACTIVE_HIGH>; - linux,default-trigger = "ide-disk1"; }; - red_sata1 { + led-2 { label = "n2350:red:sata1"; gpios = <&gpio1 14 GPIO_ACTIVE_HIGH>; }; - white-sata2 { + led-3 { label = "n2350:white:sata2"; gpios = <&gpio0 19 GPIO_ACTIVE_HIGH>; }; - red-sata2 { + led-4 { label = "n2350:red:sata2"; gpios = <&gpio1 15 GPIO_ACTIVE_HIGH>; }; - white-sys { + led-5 { label = "n2350:white:sys"; gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>; linux,default-trigger = "default-on"; }; - red-sys { + led-6 { label = "n2350:red:sys"; gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>; }; - blue-pwr { + led-7 { label = "n2350:blue:pwr"; gpios = <&gpio1 11 GPIO_ACTIVE_HIGH>; }; - red-pwr { + led-8 { label = "n2350:red:pwr"; gpios = <&gpio0 18 GPIO_ACTIVE_HIGH>; }; - white-usb { + led-9 { label = "n2350:white:usb"; gpios = <&gpio0 16 GPIO_ACTIVE_HIGH>; }; - red-usb { + led-10 { label = "n2350:red:usb"; gpios = <&gpio0 17 GPIO_ACTIVE_HIGH>; }; }; - regulators { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <0>; - - usb3_0_power: regulator@1 { - compatible = "regulator-fixed"; - reg = <1>; - regulator-name = "USB3_0_Power"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - enable-active-high; - regulator-always-on; - regulator-boot-on; - gpio = <&gpio0 21 GPIO_ACTIVE_HIGH>; - }; + fan { + compatible = "gpio-fan"; + gpios = <&gpio1 16 GPIO_ACTIVE_HIGH>; + gpio-fan,speed-map = < 0 0 + 600 1 + 3000 2 >; + pinctrl-0 = <&pmx_fan>; + pinctrl-names = "default"; + }; - usb3_1_power: regulator@2 { - compatible = "regulator-fixed"; - reg = <1>; - regulator-name = "USB3_1_Power"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - enable-active-high; - regulator-always-on; - regulator-boot-on; - gpio = <&gpio0 24 GPIO_ACTIVE_HIGH>; - }; + usb3_0_power: v5-vbus0 { + compatible = "regulator-fixed"; + regulator-name = "USB3_0_Power"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + regulator-always-on; + regulator-boot-on; + gpio = <&gpio0 21 GPIO_ACTIVE_HIGH>; + }; - reg_sata0: regulator@3 { - compatible = "regulator-fixed"; - regulator-name = "pwr_en_sata0"; - regulator-min-microvolt = <12000000>; - regulator-max-microvolt = <12000000>; - enable-active-high; - regulator-always-on; - regulator-boot-on; - gpio = <&gpio1 12 GPIO_ACTIVE_HIGH>; - }; + usb3_1_power: v5-vbus1 { + compatible = "regulator-fixed"; + regulator-name = "USB3_1_Power"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + regulator-always-on; + regulator-boot-on; + gpio = <&gpio0 24 GPIO_ACTIVE_HIGH>; + }; - reg_5v_sata0: v5-sata0 { - compatible = "regulator-fixed"; - regulator-name = "v5.0-sata0"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - vin-supply = <®_sata0>; - }; + reg_sata0: pwr-sata0 { + compatible = "regulator-fixed"; + regulator-name = "pwr_en_sata0"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + enable-active-high; + regulator-always-on; + regulator-boot-on; + gpio = <&gpio1 12 GPIO_ACTIVE_HIGH>; + }; - reg_12v_sata0: v12-sata0 { - compatible = "regulator-fixed"; - regulator-name = "v12.0-sata0"; - regulator-min-microvolt = <12000000>; - regulator-max-microvolt = <12000000>; - vin-supply = <®_sata0>; - }; + reg_5v_sata0: v5-sata0 { + compatible = "regulator-fixed"; + regulator-name = "v5.0-sata0"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <®_sata0>; + }; - reg_sata1: regulator@4 { - regulator-name = "pwr_en_sata1"; - compatible = "regulator-fixed"; - regulator-min-microvolt = <12000000>; - regulator-max-microvolt = <12000000>; - enable-active-high; - regulator-always-on; - regulator-boot-on; - gpio = <&gpio1 13 GPIO_ACTIVE_HIGH>; - }; + reg_12v_sata0: v12-sata0 { + compatible = "regulator-fixed"; + regulator-name = "v12.0-sata0"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + vin-supply = <®_sata0>; + }; - reg_5v_sata1: v5-sata1 { - compatible = "regulator-fixed"; - regulator-name = "v5.0-sata1"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - vin-supply = <®_sata1>; - }; + reg_sata1: pwr-sata0 { + regulator-name = "pwr_en_sata1"; + compatible = "regulator-fixed"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + enable-active-high; + regulator-always-on; + regulator-boot-on; + gpio = <&gpio1 13 GPIO_ACTIVE_HIGH>; + }; - reg_12v_sata1: v12-sata1 { - compatible = "regulator-fixed"; - regulator-name = "v12.0-sata1"; - regulator-min-microvolt = <12000000>; - regulator-max-microvolt = <12000000>; - vin-supply = <®_sata1>; - }; + reg_5v_sata1: v5-sata1 { + compatible = "regulator-fixed"; + regulator-name = "v5.0-sata1"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <®_sata1>; + }; + reg_12v_sata1: v12-sata1 { + compatible = "regulator-fixed"; + regulator-name = "v12.0-sata1"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + vin-supply = <®_sata1>; }; gpio-poweroff { @@ -267,7 +267,7 @@ }; &mdio { - phy0: ethernet-phy@0 { + phy0: ethernet-phy@1 { reg = <1>; }; }; @@ -301,18 +301,14 @@ &pciec { status = "okay"; - /* - * The two PCIe units are accessible through - * standard PCIe slots on the board. - */ - pcie@1,0 { - /* Port 0, Lane 0 */ - status = "okay"; - }; - pcie@2,0 { - /* Port 1, Lane 0 */ - status = "okay"; - }; +}; + +&pcie1 { + status = "okay"; +}; + +&pcie2 { + status = "okay"; }; &pinctrl { @@ -392,6 +388,11 @@ marvell,pins = "mpp17"; marvell,function = "gpio"; }; + + pmx_fan: pmx-fan { + marvell,pins = "mpp48"; + marvell,function = "gpio"; + }; }; &sdhci { @@ -408,10 +409,10 @@ status = "okay"; /* spi: 4M Flash Macronix MX25L3205D */ - spi-flash@0 { + flash@0 { #address-cells = <1>; #size-cells = <0>; - compatible = "macronix,mx25l3205d", "jedec,spi-nor"; + compatible = "jedec,spi-nor"; reg = <0>; spi-max-frequency = <108000000>; diff --git a/arch/arm/dts/imx28-xea-u-boot.dtsi b/arch/arm/dts/imx28-xea-u-boot.dtsi index f6488154d8d..bdbeca528c6 100644 --- a/arch/arm/dts/imx28-xea-u-boot.dtsi +++ b/arch/arm/dts/imx28-xea-u-boot.dtsi @@ -12,6 +12,11 @@ */ #include "imx28-u-boot.dtsi" / { + aliases { + /delete-property/ spi1; + /delete-property/ usbphy0; + /delete-property/ usbphy1; + }; apb@80000000 { bootph-pre-ram; @@ -27,16 +32,47 @@ &clks { bootph-pre-ram; + status = "disable"; +}; + +&duart { + /delete-property/ clocks; + bootph-pre-ram; + type = <1>; /* TYPE_PL011 */ }; &gpio0 { bootph-pre-ram; }; +&mac0 { + phy-mode = "rmii"; + pinctrl-names = "default"; + pinctrl-0 = <&mac0_pins_a>; + phy-supply = <®_fec_3v3>; + phy-reset-gpios = <&gpio2 13 GPIO_ACTIVE_LOW>; + phy-reset-duration = <1>; + phy-reset-post-delay = <1>; + status = "okay"; + + fixed-link { + speed = <100>; + full-duplex; + }; +}; + &pinctrl { + /delete-property/ pinctrl-names; + /delete-property/ pinctrl-0; bootph-pre-ram; }; +®_fec_3v3 { + gpio = <&gpio0 0 GPIO_ACTIVE_HIGH>; + enable-active-high; + regulator-boot-on; +}; + &ssp0 { bootph-pre-ram; }; @@ -46,3 +82,12 @@ spi-max-frequency = <40000000>; bootph-pre-ram; }; + +/delete-node/ &ssp2; +/delete-node/ &usb0; +/delete-node/ &usbphy0; +/delete-node/ &usb1; +/delete-node/ &usbphy1; +/delete-node/ &hog_pins_a; +/delete-node/ &hog_pins_tiva; +/delete-node/ &hog_pins_coding; diff --git a/arch/arm/dts/imx8mm-beacon-kit-u-boot.dtsi b/arch/arm/dts/imx8mm-beacon-kit-u-boot.dtsi index fd0061f00fd..00abbeb22fe 100644 --- a/arch/arm/dts/imx8mm-beacon-kit-u-boot.dtsi +++ b/arch/arm/dts/imx8mm-beacon-kit-u-boot.dtsi @@ -6,6 +6,10 @@ #include "imx8mm-u-boot.dtsi" / { + aliases { + spi0 = &flexspi; + }; + wdt-reboot { compatible = "wdt-reboot"; wdt = <&wdog1>; diff --git a/arch/arm/dts/imx8mm-mx8menlo.dts b/arch/arm/dts/imx8mm-mx8menlo.dts index 32f6f2f50c1..0b123a84018 100644 --- a/arch/arm/dts/imx8mm-mx8menlo.dts +++ b/arch/arm/dts/imx8mm-mx8menlo.dts @@ -10,6 +10,7 @@ / { model = "MENLO MX8MM EMBEDDED DEVICE"; compatible = "menlo,mx8menlo", + "toradex,verdin-imx8mm-nonwifi", "toradex,verdin-imx8mm", "fsl,imx8mm"; @@ -250,21 +251,21 @@ /* SODIMM 96 */ MX8MM_IOMUXC_SAI1_RXD2_GPIO4_IO4 0x1c4 /* CPLD_D[7] */ - MX8MM_IOMUXC_SAI1_RXD3_GPIO4_IO5 0x1c4 + MX8MM_IOMUXC_SAI1_RXD3_GPIO4_IO5 0x184 /* CPLD_D[6] */ - MX8MM_IOMUXC_SAI1_RXFS_GPIO4_IO0 0x1c4 + MX8MM_IOMUXC_SAI1_RXFS_GPIO4_IO0 0x184 /* CPLD_D[5] */ - MX8MM_IOMUXC_SAI1_TXC_GPIO4_IO11 0x1c4 + MX8MM_IOMUXC_SAI1_TXC_GPIO4_IO11 0x184 /* CPLD_D[4] */ - MX8MM_IOMUXC_SAI1_TXD0_GPIO4_IO12 0x1c4 + MX8MM_IOMUXC_SAI1_TXD0_GPIO4_IO12 0x184 /* CPLD_D[3] */ - MX8MM_IOMUXC_SAI1_TXD1_GPIO4_IO13 0x1c4 + MX8MM_IOMUXC_SAI1_TXD1_GPIO4_IO13 0x184 /* CPLD_D[2] */ - MX8MM_IOMUXC_SAI1_TXD2_GPIO4_IO14 0x1c4 + MX8MM_IOMUXC_SAI1_TXD2_GPIO4_IO14 0x184 /* CPLD_D[1] */ - MX8MM_IOMUXC_SAI1_TXD3_GPIO4_IO15 0x1c4 + MX8MM_IOMUXC_SAI1_TXD3_GPIO4_IO15 0x184 /* CPLD_D[0] */ - MX8MM_IOMUXC_SAI1_TXD4_GPIO4_IO16 0x1c4 + MX8MM_IOMUXC_SAI1_TXD4_GPIO4_IO16 0x184 /* KBD_intK */ MX8MM_IOMUXC_SAI2_MCLK_GPIO4_IO27 0x1c4 /* DISP_reset */ diff --git a/arch/arm/dts/imx8mm-verdin-dahlia.dtsi b/arch/arm/dts/imx8mm-verdin-dahlia.dtsi deleted file mode 100644 index c2a5c2f7b20..00000000000 --- a/arch/arm/dts/imx8mm-verdin-dahlia.dtsi +++ /dev/null @@ -1,150 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -/* - * Copyright 2022 Toradex - */ - -/ { - sound_card: sound-card { - compatible = "simple-audio-card"; - simple-audio-card,bitclock-master = <&dailink_master>; - simple-audio-card,format = "i2s"; - simple-audio-card,frame-master = <&dailink_master>; - simple-audio-card,name = "imx8mm-wm8904"; - simple-audio-card,routing = - "Headphone Jack", "HPOUTL", - "Headphone Jack", "HPOUTR", - "IN2L", "Line In Jack", - "IN2R", "Line In Jack", - "Headphone Jack", "MICBIAS", - "IN1L", "Headphone Jack"; - simple-audio-card,widgets = - "Microphone", "Headphone Jack", - "Headphone", "Headphone Jack", - "Line", "Line In Jack"; - - dailink_master: simple-audio-card,codec { - clocks = <&clk IMX8MM_CLK_SAI2_ROOT>; - sound-dai = <&wm8904_1a>; - }; - - simple-audio-card,cpu { - sound-dai = <&sai2>; - }; - }; -}; - -/* Verdin SPI_1 */ -&ecspi2 { - status = "okay"; -}; - -/* EEPROM on display adapter boards */ -&eeprom_display_adapter { - status = "okay"; -}; - -/* EEPROM on Verdin Development board */ -&eeprom_carrier_board { - status = "okay"; -}; - -&fec1 { - status = "okay"; -}; - -/* Verdin QSPI_1 */ -&flexspi { - status = "okay"; -}; - -/* Current measurement into module VCC */ -&hwmon { - status = "okay"; -}; - -&hwmon_temp { - vs-supply = <®_1p8v>; - status = "okay"; -}; - -&i2c3 { - status = "okay"; -}; - -/* Verdin I2C_1 */ -&i2c4 { - status = "okay"; - - /* Audio Codec */ - wm8904_1a: audio-codec@1a { - compatible = "wlf,wm8904"; - AVDD-supply = <®_3p3v>; - clocks = <&clk IMX8MM_CLK_SAI2_ROOT>; - clock-names = "mclk"; - CPVDD-supply = <®_3p3v>; - DBVDD-supply = <®_3p3v>; - DCVDD-supply = <®_3p3v>; - MICVDD-supply = <®_3p3v>; - reg = <0x1a>; - #sound-dai-cells = <0>; - }; -}; - -/* Verdin PCIE_1 */ -&pcie0 { - status = "okay"; -}; - -&pcie_phy { - status = "okay"; -}; - -/* Verdin PWM_3_DSI */ -&pwm1 { - status = "okay"; -}; - -/* Verdin PWM_1 */ -&pwm2 { - status = "okay"; -}; - -/* Verdin PWM_2 */ -&pwm3 { - status = "okay"; -}; - -/* Verdin I2S_1 */ -&sai2 { - status = "okay"; -}; - -/* Verdin UART_3 */ -&uart1 { - status = "okay"; -}; - -/* Verdin UART_1 */ -&uart2 { - status = "okay"; -}; - -/* Verdin UART_2 */ -&uart3 { - status = "okay"; -}; - -/* Verdin USB_1 */ -&usbotg1 { - status = "okay"; -}; - -/* Verdin USB_2 */ -&usbotg2 { - status = "okay"; -}; - -/* Verdin SD_1 */ -&usdhc2 { - status = "okay"; -}; diff --git a/arch/arm/dts/imx8mm-verdin-dev.dtsi b/arch/arm/dts/imx8mm-verdin-dev.dtsi index 73cc3fafa01..3c4b8ca125e 100644 --- a/arch/arm/dts/imx8mm-verdin-dev.dtsi +++ b/arch/arm/dts/imx8mm-verdin-dev.dtsi @@ -3,14 +3,13 @@ * Copyright 2022 Toradex */ -#include "imx8mm-verdin-dahlia.dtsi" - / { sound_card: sound-card { compatible = "simple-audio-card"; simple-audio-card,bitclock-master = <&dailink_master>; simple-audio-card,format = "i2s"; simple-audio-card,frame-master = <&dailink_master>; + simple-audio-card,mclk-fs = <256>; simple-audio-card,name = "imx8mm-nau8822"; simple-audio-card,routing = "Headphones", "LHP", @@ -41,27 +40,121 @@ }; }; +/* Verdin SPI_1 */ +&ecspi2 { + status = "okay"; +}; + +/* EEPROM on display adapter boards */ +&eeprom_display_adapter { + status = "okay"; +}; + +/* EEPROM on Verdin Development board */ +&eeprom_carrier_board { + status = "okay"; +}; + +&fec1 { + status = "okay"; +}; + +/* Verdin QSPI_1 */ +&flexspi { + status = "okay"; +}; + +/* Current measurement into module VCC */ +&hwmon { + status = "okay"; +}; + +&hwmon_temp { + vs-supply = <®_1p8v>; + status = "okay"; +}; + +&i2c3 { + status = "okay"; +}; + &gpio_expander_21 { status = "okay"; }; /* Verdin I2C_1 */ &i2c4 { + status = "okay"; + /* Audio Codec */ nau8822_1a: audio-codec@1a { compatible = "nuvoton,nau8822"; reg = <0x1a>; + #sound-dai-cells = <0>; }; }; +/* Verdin PCIE_1 */ +&pcie0 { + status = "okay"; +}; + +&pcie_phy { + status = "okay"; +}; + +/* Verdin PWM_3_DSI */ +&pwm1 { + status = "okay"; +}; + +/* Verdin PWM_1 */ +&pwm2 { + status = "okay"; +}; + +/* Verdin PWM_2 */ +&pwm3 { + status = "okay"; +}; + +/* Verdin I2S_1 */ +&sai2 { + status = "okay"; +}; + +/* Verdin UART_3 */ +&uart1 { + status = "okay"; +}; + /* Verdin UART_1, connector X50 through RS485 transceiver */ &uart2 { linux,rs485-enabled-at-boot-time; rs485-rts-active-low; rs485-rx-during-tx; + status = "okay"; +}; + +/* Verdin UART_2 */ +&uart3 { + status = "okay"; +}; + +/* Verdin USB_1 */ +&usbotg1 { + disable-over-current; + status = "okay"; +}; + +/* Verdin USB_2 */ +&usbotg2 { + disable-over-current; + status = "okay"; }; /* Limit frequency on dev board due to long traces and bad signal integrity */ &usdhc2 { max-frequency = <100000000>; + status = "okay"; }; diff --git a/arch/arm/dts/imx8mm-verdin-wifi-dev-u-boot.dtsi b/arch/arm/dts/imx8mm-verdin-wifi-dev-u-boot.dtsi index 494229e4e62..2b268f55cb9 100644 --- a/arch/arm/dts/imx8mm-verdin-wifi-dev-u-boot.dtsi +++ b/arch/arm/dts/imx8mm-verdin-wifi-dev-u-boot.dtsi @@ -56,6 +56,10 @@ &gpio5 { bootph-pre-ram; + + ctrl-sleep-moci-hog { + bootph-pre-ram; + }; }; &i2c1 { @@ -88,6 +92,10 @@ }; }; +&pinctrl_ctrl_sleep_moci { + bootph-pre-ram; +}; + &pinctrl_i2c1 { bootph-pre-ram; }; diff --git a/arch/arm/dts/imx8mm-verdin.dtsi b/arch/arm/dts/imx8mm-verdin.dtsi index bcab830c6e9..6f081158714 100644 --- a/arch/arm/dts/imx8mm-verdin.dtsi +++ b/arch/arm/dts/imx8mm-verdin.dtsi @@ -3,8 +3,8 @@ * Copyright 2022 Toradex */ -#include "dt-bindings/phy/phy-imx8-pcie.h" -#include "dt-bindings/pwm/pwm.h" +#include <dt-bindings/phy/phy-imx8-pcie.h> +#include <dt-bindings/pwm/pwm.h> #include "imx8mm.dtsi" / { @@ -56,7 +56,11 @@ hdmi_connector: hdmi-connector { compatible = "hdmi-connector"; ddc-i2c-bus = <&i2c2>; + /* Verdin PWM_3_DSI (SODIMM 19) */ + hpd-gpios = <&gpio1 1 GPIO_ACTIVE_HIGH>; label = "hdmi"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm_3_dsi_hpd_gpio>; type = "a"; status = "disabled"; }; @@ -95,9 +99,10 @@ compatible = "regulator-fixed"; enable-active-high; gpio = <&gpio2 20 GPIO_ACTIVE_HIGH>; /* PMIC_EN_ETH */ - off-on-delay = <500000>; + off-on-delay-us = <500000>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_reg_eth>; + regulator-always-on; regulator-boot-on; regulator-max-microvolt = <3300000>; regulator-min-microvolt = <3300000>; @@ -134,7 +139,7 @@ enable-active-high; /* Verdin SD_1_PWR_EN (SODIMM 76) */ gpio = <&gpio3 5 GPIO_ACTIVE_HIGH>; - off-on-delay = <100000>; + off-on-delay-us = <100000>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc2_pwr_en>; regulator-max-microvolt = <3300000>; @@ -183,15 +188,15 @@ ddrc_opp_table: opp-table { compatible = "operating-points-v2"; - opp-25M { + opp-25000000 { opp-hz = /bits/ 64 <25000000>; }; - opp-100M { + opp-100000000 { opp-hz = /bits/ 64 <100000000>; }; - opp-750M { + opp-750000000 { opp-hz = /bits/ 64 <750000000>; }; }; @@ -358,7 +363,6 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_pmic>; reg = <0x25>; - sd-vsel-gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>; /* * The bootloader is expected to switch on the I2C level shifter for the TLA2024 ADC @@ -598,7 +602,7 @@ hdmi_lontium_lt8912: hdmi@48 { compatible = "lontium,lt8912b"; pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_gpio_10_dsi>, <&pinctrl_pwm_3_dsi_hpd_gpio>; + pinctrl-0 = <&pinctrl_gpio_10_dsi>; reg = <0x48>; /* Verdin GPIO_9_DSI (LT8912 INT, SODIMM 17, unused) */ /* Verdin GPIO_10_DSI (SODIMM 21) */ @@ -610,7 +614,7 @@ compatible = "atmel,maxtouch"; /* * Verdin GPIO_9_DSI - * (TOUCH_INT#, SODIMM 17, also routed to SN65DSI83 IRQ albeit currently unused) + * (TOUCH_INT#, SODIMM 17, also routed to SN65DSI84 IRQ albeit currently unused) */ interrupt-parent = <&gpio3>; interrupts = <15 IRQ_TYPE_EDGE_FALLING>; @@ -653,9 +657,6 @@ assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_50M>, <&clk IMX8MM_SYS_PLL2_250M>; assigned-clock-rates = <10000000>, <250000000>; - clocks = <&clk IMX8MM_CLK_PCIE1_ROOT>, <&clk IMX8MM_CLK_PCIE1_AUX>, - <&clk IMX8MM_CLK_PCIE1_PHY>; - clock-names = "pcie", "pcie_aux", "pcie_bus"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_pcie0>; /* PCIE_1_RESET# (SODIMM 244) */ @@ -664,6 +665,7 @@ &pcie_phy { clocks = <&clk IMX8MM_CLK_PCIE1_PHY>; + clock-names = "ref"; fsl,clkreq-unsupported; fsl,refclk-pad-mode = <IMX8_PCIE_REFCLK_PAD_OUTPUT>; fsl,tx-deemph-gen1 = <0x2d>; @@ -739,7 +741,6 @@ adp-disable; dr_mode = "otg"; hnp-disable; - over-current-active-low; samsung,picophy-dc-vol-level-adjust = <7>; samsung,picophy-pre-emp-curr-control = <3>; srp-disable; @@ -749,7 +750,6 @@ /* Verdin USB_2 */ &usbotg2 { dr_mode = "host"; - over-current-active-low; samsung,picophy-dc-vol-level-adjust = <7>; samsung,picophy-pre-emp-curr-control = <3>; vbus-supply = <®_usb_otg2_vbus>; diff --git a/arch/arm/dts/imx8mn-var-som-symphony-u-boot.dtsi b/arch/arm/dts/imx8mn-var-som-symphony-u-boot.dtsi index af80aaea0b8..e0caf3179ea 100644 --- a/arch/arm/dts/imx8mn-var-som-symphony-u-boot.dtsi +++ b/arch/arm/dts/imx8mn-var-som-symphony-u-boot.dtsi @@ -13,6 +13,19 @@ bootph-pre-ram; }; +&eeprom_som { + #address-cells = <1>; + #size-cells = <1>; + eth_mac_address: eth-mac-address@19 { + reg = <0x19 0x06>; + }; +}; + +&fec1 { + nvmem-cells = <ð_mac_address>; + nvmem-cell-names = "mac-address"; +}; + &gpio1 { bootph-pre-ram; }; @@ -68,3 +81,7 @@ &usdhc3 { bootph-pre-ram; }; + +&eeprom_som { + bootph-pre-ram; +}; diff --git a/arch/arm/dts/imx8mn-var-som-symphony.dts b/arch/arm/dts/imx8mn-var-som-symphony.dts index 3ed7021a487..5c8e4e81752 100644 --- a/arch/arm/dts/imx8mn-var-som-symphony.dts +++ b/arch/arm/dts/imx8mn-var-som-symphony.dts @@ -56,10 +56,6 @@ }; }; -ðphy { - reset-gpios = <&pca9534 5 GPIO_ACTIVE_HIGH>; -}; - &i2c2 { clock-frequency = <400000>; pinctrl-names = "default"; diff --git a/arch/arm/dts/imx8mn-var-som.dtsi b/arch/arm/dts/imx8mn-var-som.dtsi index 87b5e23c766..4eb578a03fc 100644 --- a/arch/arm/dts/imx8mn-var-som.dtsi +++ b/arch/arm/dts/imx8mn-var-som.dtsi @@ -11,6 +11,10 @@ model = "Variscite VAR-SOM-MX8MN module"; compatible = "variscite,var-som-mx8mn", "fsl,imx8mn"; + aliases { + eeprom-som = &eeprom_som; + }; + chosen { stdout-path = &uart4; }; @@ -98,11 +102,17 @@ #address-cells = <1>; #size-cells = <0>; - ethphy: ethernet-phy@4 { + ethphy: ethernet-phy@4 { /* AR8033 or ADIN1300 */ compatible = "ethernet-phy-ieee802.3-c22"; reg = <4>; reset-gpios = <&gpio1 9 GPIO_ACTIVE_LOW>; reset-assert-us = <10000>; + /* + * Deassert delay: + * ADIN1300 requires 5ms. + * AR8033 requires 1ms. + */ + reset-deassert-us = <20000>; }; }; }; @@ -222,6 +232,12 @@ }; }; }; + + eeprom_som: eeprom@52 { + compatible = "atmel,24c04"; + reg = <0x52>; + pagesize = <16>; + }; }; &i2c3 { diff --git a/arch/arm/dts/imx8mp-beacon-kit-u-boot.dtsi b/arch/arm/dts/imx8mp-beacon-kit-u-boot.dtsi index 5ca631e9d8c..b56f3a2bd2e 100644 --- a/arch/arm/dts/imx8mp-beacon-kit-u-boot.dtsi +++ b/arch/arm/dts/imx8mp-beacon-kit-u-boot.dtsi @@ -185,12 +185,10 @@ &usb3_0 { dma-ranges = <0x40000000 0x40000000 0xc0000000>; - /delete-property/ power-domains; }; &usb3_1 { dma-ranges = <0x40000000 0x40000000 0xc0000000>; - /delete-property/ power-domains; }; &usb_dwc3_0 { diff --git a/arch/arm/dts/imx8mp-u-boot.dtsi b/arch/arm/dts/imx8mp-u-boot.dtsi index 68cd0e10f02..36e7444a627 100644 --- a/arch/arm/dts/imx8mp-u-boot.dtsi +++ b/arch/arm/dts/imx8mp-u-boot.dtsi @@ -44,6 +44,9 @@ &aips3 { bootph-pre-ram; + spba-bus@30800000 { + bootph-pre-ram; + }; }; &iomuxc { diff --git a/arch/arm/dts/imx8mp-venice-gw702x-u-boot.dtsi b/arch/arm/dts/imx8mp-venice-gw702x-u-boot.dtsi new file mode 100644 index 00000000000..b9e3db7de93 --- /dev/null +++ b/arch/arm/dts/imx8mp-venice-gw702x-u-boot.dtsi @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2023 Gateworks Corporation + */ + +#include "imx8mp-venice-u-boot.dtsi" + +&eqos { + /delete-property/ assigned-clocks; + /delete-property/ assigned-clock-parents; + /delete-property/ assigned-clock-rates; +}; diff --git a/arch/arm/dts/imx8mp-venice-gw702x.dtsi b/arch/arm/dts/imx8mp-venice-gw702x.dtsi new file mode 100644 index 00000000000..560c68e4da6 --- /dev/null +++ b/arch/arm/dts/imx8mp-venice-gw702x.dtsi @@ -0,0 +1,587 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2023 Gateworks Corporation + */ + +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/input/linux-event-codes.h> +#include <dt-bindings/net/ti-dp83867.h> + +/ { + aliases { + ethernet0 = &eqos; + }; + + memory@40000000 { + device_type = "memory"; + reg = <0x0 0x40000000 0 0x80000000>; + }; + + gpio-keys { + compatible = "gpio-keys"; + + key-user-pb { + label = "user_pb"; + gpios = <&gpio 2 GPIO_ACTIVE_LOW>; + linux,code = <BTN_0>; + }; + + key-user-pb1x { + label = "user_pb1x"; + linux,code = <BTN_1>; + interrupt-parent = <&gsc>; + interrupts = <0>; + }; + + key-erased { + label = "key_erased"; + linux,code = <BTN_2>; + interrupt-parent = <&gsc>; + interrupts = <1>; + }; + + key-eeprom-wp { + label = "eeprom_wp"; + linux,code = <BTN_3>; + interrupt-parent = <&gsc>; + interrupts = <2>; + }; + + key-tamper { + label = "tamper"; + linux,code = <BTN_4>; + interrupt-parent = <&gsc>; + interrupts = <5>; + }; + + switch-hold { + label = "switch_hold"; + linux,code = <BTN_5>; + interrupt-parent = <&gsc>; + interrupts = <7>; + }; + }; +}; + +&A53_0 { + cpu-supply = <&buck3_reg>; +}; + +&A53_1 { + cpu-supply = <&buck3_reg>; +}; + +&A53_2 { + cpu-supply = <&buck3_reg>; +}; + +&A53_3 { + cpu-supply = <&buck3_reg>; +}; + +&eqos { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_eqos>; + phy-mode = "rgmii-id"; + phy-handle = <ðphy0>; + status = "okay"; + + mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + ethphy0: ethernet-phy@0 { + compatible = "ethernet-phy-ieee802.3-c22"; + pinctrl-0 = <&pinctrl_ethphy0>; + pinctrl-names = "default"; + reg = <0x0>; + interrupt-parent = <&gpio3>; + interrupts = <16 IRQ_TYPE_EDGE_FALLING>; + ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>; + ti,tx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>; + tx-fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>; + rx-fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>; + }; + }; +}; + +&i2c1 { + clock-frequency = <100000>; + pinctrl-names = "default", "gpio"; + pinctrl-0 = <&pinctrl_i2c1>; + pinctrl-1 = <&pinctrl_i2c1_gpio>; + scl-gpios = <&gpio5 14 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio5 15 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + status = "okay"; + + gsc: gsc@20 { + compatible = "gw,gsc"; + reg = <0x20>; + pinctrl-0 = <&pinctrl_gsc>; + interrupt-parent = <&gpio2>; + interrupts = <6 IRQ_TYPE_EDGE_FALLING>; + interrupt-controller; + #interrupt-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; + + adc { + compatible = "gw,gsc-adc"; + #address-cells = <1>; + #size-cells = <0>; + + channel@6 { + gw,mode = <0>; + reg = <0x06>; + label = "temp"; + }; + + channel@8 { + gw,mode = <3>; + reg = <0x08>; + label = "vdd_bat"; + }; + + channel@16 { + gw,mode = <4>; + reg = <0x16>; + label = "fan_tach"; + }; + + channel@82 { + gw,mode = <2>; + reg = <0x82>; + label = "vdd_vin"; + gw,voltage-divider-ohms = <22100 1000>; + }; + + channel@84 { + gw,mode = <2>; + reg = <0x84>; + label = "vdd_adc1"; + gw,voltage-divider-ohms = <10000 10000>; + }; + + channel@86 { + gw,mode = <2>; + reg = <0x86>; + label = "vdd_adc2"; + gw,voltage-divider-ohms = <10000 10000>; + }; + + channel@88 { + gw,mode = <2>; + reg = <0x88>; + label = "vdd_1p0"; + }; + + channel@8c { + gw,mode = <2>; + reg = <0x8c>; + label = "vdd_1p8"; + }; + + channel@8e { + gw,mode = <2>; + reg = <0x8e>; + label = "vdd_2p5"; + }; + + channel@90 { + gw,mode = <2>; + reg = <0x90>; + label = "vdd_3p3"; + gw,voltage-divider-ohms = <10000 10000>; + }; + + channel@92 { + gw,mode = <2>; + reg = <0x92>; + label = "vdd_dram"; + }; + + channel@98 { + gw,mode = <2>; + reg = <0x98>; + label = "vdd_soc"; + }; + + channel@9a { + gw,mode = <2>; + reg = <0x9a>; + label = "vdd_arm"; + }; + + channel@a2 { + gw,mode = <2>; + reg = <0xa2>; + label = "vdd_gsc"; + gw,voltage-divider-ohms = <10000 10000>; + }; + }; + + fan-controller@0 { + compatible = "gw,gsc-fan"; + reg = <0x0a>; + }; + }; + + gpio: gpio@23 { + compatible = "nxp,pca9555"; + reg = <0x23>; + gpio-controller; + #gpio-cells = <2>; + interrupt-parent = <&gsc>; + interrupts = <4>; + }; + + eeprom@50 { + compatible = "atmel,24c02"; + reg = <0x50>; + pagesize = <16>; + }; + + eeprom@51 { + compatible = "atmel,24c02"; + reg = <0x51>; + pagesize = <16>; + }; + + eeprom@52 { + compatible = "atmel,24c02"; + reg = <0x52>; + pagesize = <16>; + }; + + eeprom@53 { + compatible = "atmel,24c02"; + reg = <0x53>; + pagesize = <16>; + }; + + rtc@68 { + compatible = "dallas,ds1672"; + reg = <0x68>; + }; + + pmic@69 { + compatible = "mps,mp5416"; + reg = <0x69>; + + regulators { + /* vdd_soc */ + buck1 { + regulator-name = "buck1"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <1000000>; + regulator-always-on; + regulator-boot-on; + }; + + /* vdd_dram */ + buck2 { + regulator-name = "buck2"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + regulator-always-on; + regulator-boot-on; + }; + + /* vdd_arm */ + buck3_reg: buck3 { + regulator-name = "buck3"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <1000000>; + regulator-always-on; + regulator-boot-on; + }; + + /* vdd_1p8 */ + buck4 { + regulator-name = "buck4"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + }; + + /* OUT2: nvcc_snvs_1p8 */ + ldo1 { + regulator-name = "ldo1"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + }; + + /* OUT3: vdd_1p0 */ + ldo2 { + regulator-name = "ldo2"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-always-on; + regulator-boot-on; + }; + + /* OUT4: vdd_2p5 */ + ldo3 { + regulator-name = "ldo3"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + regulator-always-on; + regulator-boot-on; + }; + + /* OUT5: vdd_3p3 */ + ldo4 { + regulator-name = "ldo4"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + }; + }; + }; +}; + +/* off-board header */ +&i2c2 { + clock-frequency = <400000>; + pinctrl-names = "default", "gpio"; + pinctrl-0 = <&pinctrl_i2c2>; + pinctrl-1 = <&pinctrl_i2c2_gpio>; + scl-gpios = <&gpio5 16 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio5 17 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + status = "okay"; + + eeprom@52 { + compatible = "atmel,24c32"; + reg = <0x52>; + pagesize = <32>; + }; +}; + +/* off-board header */ +&i2c3 { + clock-frequency = <400000>; + pinctrl-names = "default", "gpio"; + pinctrl-0 = <&pinctrl_i2c3>; + pinctrl-1 = <&pinctrl_i2c3_gpio>; + scl-gpios = <&gpio5 18 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio5 19 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + status = "okay"; +}; + +/* off-board header */ +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1>; + status = "okay"; +}; + +/* console */ +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart2>; + status = "okay"; +}; + +/* off-board header */ +&uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart3>; + status = "okay"; +}; + +/* off-board */ +&usdhc1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc1>; + bus-width = <4>; + non-removable; + status = "okay"; + bus-width = <4>; + non-removable; + status = "okay"; +}; + +/* eMMC */ +&usdhc3 { + pinctrl-names = "default", "state_100mhz", "state_200mhz"; + pinctrl-0 = <&pinctrl_usdhc3>; + pinctrl-1 = <&pinctrl_usdhc3_100mhz>; + pinctrl-2 = <&pinctrl_usdhc3_200mhz>; + bus-width = <8>; + non-removable; + status = "okay"; +}; + +&wdog1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_wdog>; + fsl,ext-reset-output; + status = "okay"; +}; + +&iomuxc { + pinctrl_eqos: eqosgrp { + fsl,pins = < + MX8MP_IOMUXC_ENET_MDC__ENET_QOS_MDC 0x2 + MX8MP_IOMUXC_ENET_MDIO__ENET_QOS_MDIO 0x2 + MX8MP_IOMUXC_ENET_RD0__ENET_QOS_RGMII_RD0 0x90 + MX8MP_IOMUXC_ENET_RD1__ENET_QOS_RGMII_RD1 0x90 + MX8MP_IOMUXC_ENET_RD2__ENET_QOS_RGMII_RD2 0x90 + MX8MP_IOMUXC_ENET_RD3__ENET_QOS_RGMII_RD3 0x90 + MX8MP_IOMUXC_ENET_RXC__CCM_ENET_QOS_CLOCK_GENERATE_RX_CLK 0x90 + MX8MP_IOMUXC_ENET_RX_CTL__ENET_QOS_RGMII_RX_CTL 0x90 + MX8MP_IOMUXC_ENET_TD0__ENET_QOS_RGMII_TD0 0x16 + MX8MP_IOMUXC_ENET_TD1__ENET_QOS_RGMII_TD1 0x16 + MX8MP_IOMUXC_ENET_TD2__ENET_QOS_RGMII_TD2 0x16 + MX8MP_IOMUXC_ENET_TD3__ENET_QOS_RGMII_TD3 0x16 + MX8MP_IOMUXC_ENET_TX_CTL__ENET_QOS_RGMII_TX_CTL 0x16 + MX8MP_IOMUXC_ENET_TXC__CCM_ENET_QOS_CLOCK_GENERATE_TX_CLK 0x16 + >; + }; + + pinctrl_ethphy0: ethphy0grp { + fsl,pins = < + MX8MP_IOMUXC_NAND_DQS__GPIO3_IO14 0x140 /* RST# */ + MX8MP_IOMUXC_NAND_READY_B__GPIO3_IO16 0x150 /* IRQ# */ + >; + }; + + pinctrl_gsc: gscgrp { + fsl,pins = < + MX8MP_IOMUXC_SD1_DATA4__GPIO2_IO06 0x150 /* IRQ# */ + >; + }; + + pinctrl_i2c1: i2c1grp { + fsl,pins = < + MX8MP_IOMUXC_I2C1_SCL__I2C1_SCL 0x400001c2 + MX8MP_IOMUXC_I2C1_SDA__I2C1_SDA 0x400001c2 + >; + }; + + pinctrl_i2c1_gpio: i2c1gpiogrp { + fsl,pins = < + MX8MP_IOMUXC_I2C1_SCL__GPIO5_IO14 0x400001c2 + MX8MP_IOMUXC_I2C1_SDA__GPIO5_IO15 0x400001c2 + >; + }; + + pinctrl_i2c2: i2c2grp { + fsl,pins = < + MX8MP_IOMUXC_I2C2_SCL__I2C2_SCL 0x400001c2 + MX8MP_IOMUXC_I2C2_SDA__I2C2_SDA 0x400001c2 + >; + }; + + pinctrl_i2c2_gpio: i2c2gpiogrp { + fsl,pins = < + MX8MP_IOMUXC_I2C2_SCL__GPIO5_IO16 0x400001c2 + MX8MP_IOMUXC_I2C2_SDA__GPIO5_IO17 0x400001c2 + >; + }; + + pinctrl_i2c3: i2c3grp { + fsl,pins = < + MX8MP_IOMUXC_I2C3_SCL__I2C3_SCL 0x400001c2 + MX8MP_IOMUXC_I2C3_SDA__I2C3_SDA 0x400001c2 + >; + }; + + pinctrl_i2c3_gpio: i2c3gpiogrp { + fsl,pins = < + MX8MP_IOMUXC_I2C3_SCL__GPIO5_IO18 0x400001c2 + MX8MP_IOMUXC_I2C3_SDA__GPIO5_IO19 0x400001c2 + >; + }; + + pinctrl_uart1: uart1grp { + fsl,pins = < + MX8MP_IOMUXC_UART1_RXD__UART1_DCE_RX 0x140 + MX8MP_IOMUXC_UART1_TXD__UART1_DCE_TX 0x140 + >; + }; + + pinctrl_uart2: uart2grp { + fsl,pins = < + MX8MP_IOMUXC_UART2_RXD__UART2_DCE_RX 0x140 + MX8MP_IOMUXC_UART2_TXD__UART2_DCE_TX 0x140 + >; + }; + + pinctrl_uart3: uart3grp { + fsl,pins = < + MX8MP_IOMUXC_UART3_RXD__UART3_DCE_RX 0x140 + MX8MP_IOMUXC_UART3_TXD__UART3_DCE_TX 0x140 + >; + }; + + pinctrl_usdhc1: usdhc1grp { + fsl,pins = < + MX8MP_IOMUXC_SD1_CLK__USDHC1_CLK 0x190 + MX8MP_IOMUXC_SD1_CMD__USDHC1_CMD 0x1d0 + MX8MP_IOMUXC_SD1_DATA0__USDHC1_DATA0 0x1d0 + MX8MP_IOMUXC_SD1_DATA1__USDHC1_DATA1 0x1d0 + MX8MP_IOMUXC_SD1_DATA2__USDHC1_DATA2 0x1d0 + MX8MP_IOMUXC_SD1_DATA3__USDHC1_DATA3 0x1d0 + >; + }; + + pinctrl_usdhc3: usdhc3grp { + fsl,pins = < + MX8MP_IOMUXC_NAND_WE_B__USDHC3_CLK 0x190 + MX8MP_IOMUXC_NAND_WP_B__USDHC3_CMD 0x1d0 + MX8MP_IOMUXC_NAND_DATA04__USDHC3_DATA0 0x1d0 + MX8MP_IOMUXC_NAND_DATA05__USDHC3_DATA1 0x1d0 + MX8MP_IOMUXC_NAND_DATA06__USDHC3_DATA2 0x1d0 + MX8MP_IOMUXC_NAND_DATA07__USDHC3_DATA3 0x1d0 + MX8MP_IOMUXC_NAND_RE_B__USDHC3_DATA4 0x1d0 + MX8MP_IOMUXC_NAND_CE2_B__USDHC3_DATA5 0x1d0 + MX8MP_IOMUXC_NAND_CE3_B__USDHC3_DATA6 0x1d0 + MX8MP_IOMUXC_NAND_CLE__USDHC3_DATA7 0x1d0 + MX8MP_IOMUXC_NAND_CE1_B__USDHC3_STROBE 0x190 + >; + }; + + pinctrl_usdhc3_100mhz: usdhc3-100mhzgrp { + fsl,pins = < + MX8MP_IOMUXC_NAND_WE_B__USDHC3_CLK 0x194 + MX8MP_IOMUXC_NAND_WP_B__USDHC3_CMD 0x1d4 + MX8MP_IOMUXC_NAND_DATA04__USDHC3_DATA0 0x1d4 + MX8MP_IOMUXC_NAND_DATA05__USDHC3_DATA1 0x1d4 + MX8MP_IOMUXC_NAND_DATA06__USDHC3_DATA2 0x1d4 + MX8MP_IOMUXC_NAND_DATA07__USDHC3_DATA3 0x1d4 + MX8MP_IOMUXC_NAND_RE_B__USDHC3_DATA4 0x1d4 + MX8MP_IOMUXC_NAND_CE2_B__USDHC3_DATA5 0x1d4 + MX8MP_IOMUXC_NAND_CE3_B__USDHC3_DATA6 0x1d4 + MX8MP_IOMUXC_NAND_CLE__USDHC3_DATA7 0x1d4 + MX8MP_IOMUXC_NAND_CE1_B__USDHC3_STROBE 0x194 + >; + }; + + pinctrl_usdhc3_200mhz: usdhc3-200mhzgrp { + fsl,pins = < + MX8MP_IOMUXC_NAND_WE_B__USDHC3_CLK 0x196 + MX8MP_IOMUXC_NAND_WP_B__USDHC3_CMD 0x1d6 + MX8MP_IOMUXC_NAND_DATA04__USDHC3_DATA0 0x1d6 + MX8MP_IOMUXC_NAND_DATA05__USDHC3_DATA1 0x1d6 + MX8MP_IOMUXC_NAND_DATA06__USDHC3_DATA2 0x1d6 + MX8MP_IOMUXC_NAND_DATA07__USDHC3_DATA3 0x1d6 + MX8MP_IOMUXC_NAND_RE_B__USDHC3_DATA4 0x1d6 + MX8MP_IOMUXC_NAND_CE2_B__USDHC3_DATA5 0x1d6 + MX8MP_IOMUXC_NAND_CE3_B__USDHC3_DATA6 0x1d6 + MX8MP_IOMUXC_NAND_CLE__USDHC3_DATA7 0x1d6 + MX8MP_IOMUXC_NAND_CE1_B__USDHC3_STROBE 0x196 + >; + }; + + pinctrl_wdog: wdoggrp { + fsl,pins = < + MX8MP_IOMUXC_GPIO1_IO02__WDOG1_WDOG_B 0x166 + >; + }; +}; diff --git a/arch/arm/dts/imx8mp-venice-gw7905-2x-u-boot.dtsi b/arch/arm/dts/imx8mp-venice-gw7905-2x-u-boot.dtsi new file mode 100644 index 00000000000..981841cee0a --- /dev/null +++ b/arch/arm/dts/imx8mp-venice-gw7905-2x-u-boot.dtsi @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2023 Gateworks Corporation + */ +#include "imx8mp-venice-gw702x-u-boot.dtsi" + +&gpio1 { + app_gpioa { + gpio-hog; + input; + gpios = <13 GPIO_ACTIVE_HIGH>; + line-name = "gpioa"; + }; +}; + +&gpio4 { + app_gpiod { + gpio-hog; + input; + gpios = <1 GPIO_ACTIVE_HIGH>; + line-name = "gpiod"; + }; + + app_gpiob { + gpio-hog; + input; + gpios = <4 GPIO_ACTIVE_HIGH>; + line-name = "gpiob"; + }; + + app_gpioc { + gpio-hog; + input; + gpios = <5 GPIO_ACTIVE_HIGH>; + line-name = "gpioc"; + }; + + pci_usb_sel { + gpio-hog; + output-low; + gpios = <26 GPIO_ACTIVE_HIGH>; + line-name = "pci_usb_sel"; + }; + + pci_wdis { + gpio-hog; + output-high; + gpios = <28 GPIO_ACTIVE_HIGH>; + line-name = "pci_wdis#"; + }; +}; diff --git a/arch/arm/dts/imx8mp-venice-gw7905-2x.dts b/arch/arm/dts/imx8mp-venice-gw7905-2x.dts new file mode 100644 index 00000000000..4a1bbbbe19e --- /dev/null +++ b/arch/arm/dts/imx8mp-venice-gw7905-2x.dts @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2023 Gateworks Corporation + */ + +/dts-v1/; + +#include "imx8mp.dtsi" +#include "imx8mp-venice-gw702x.dtsi" +#include "imx8mp-venice-gw7905.dtsi" + +/ { + model = "Gateworks Venice GW7905-2x i.MX8MP Development Kit"; + compatible = "gateworks,imx8mp-gw7905-2x", "fsl,imx8mp"; + + chosen { + stdout-path = &uart2; + }; +}; + +/* Disable SOM interfaces not used on baseboard */ +&eqos { + status = "disabled"; +}; + +&usdhc1 { + status = "disabled"; +}; diff --git a/arch/arm/dts/imx8mp-venice-gw7905.dtsi b/arch/arm/dts/imx8mp-venice-gw7905.dtsi new file mode 100644 index 00000000000..0d40cb0f05f --- /dev/null +++ b/arch/arm/dts/imx8mp-venice-gw7905.dtsi @@ -0,0 +1,309 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2023 Gateworks Corporation + */ + +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/leds/common.h> +#include <dt-bindings/phy/phy-imx8-pcie.h> + +/ { + led-controller { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio_leds>; + + led-0 { + function = LED_FUNCTION_STATUS; + color = <LED_COLOR_ID_GREEN>; + gpios = <&gpio4 22 GPIO_ACTIVE_HIGH>; + default-state = "on"; + linux,default-trigger = "heartbeat"; + }; + + led-1 { + function = LED_FUNCTION_STATUS; + color = <LED_COLOR_ID_RED>; + gpios = <&gpio4 27 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + }; + + pcie0_refclk: pcie0-refclk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <100000000>; + }; + + pps { + compatible = "pps-gpio"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pps>; + gpios = <&gpio4 21 GPIO_ACTIVE_HIGH>; + status = "okay"; + }; + + reg_usb2_vbus: regulator-usb2-vbus { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_reg_usb2_en>; + compatible = "regulator-fixed"; + regulator-name = "usb2_vbus"; + gpio = <&gpio4 12 GPIO_ACTIVE_HIGH>; + enable-active-high; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; + + reg_usdhc2_vmmc: regulator-usdhc2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_reg_usdhc2_vmmc>; + compatible = "regulator-fixed"; + regulator-name = "SD2_3P3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio2 19 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; +}; + +/* off-board header */ +&ecspi2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_spi2>; + cs-gpios = <&gpio5 13 GPIO_ACTIVE_LOW>; + status = "okay"; +}; + +&gpio4 { + gpio-line-names = + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "gpioa", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", ""; +}; + +&gpio4 { + gpio-line-names = + "", "gpiod", "", "", + "gpiob", "gpioc", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "pci_usb_sel", "", + "pci_wdis#", "", "", ""; +}; + +&i2c2 { + clock-frequency = <400000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c2>; + status = "okay"; + + eeprom@52 { + compatible = "atmel,24c32"; + reg = <0x52>; + pagesize = <32>; + }; +}; + +/* off-board header */ +&i2c3 { + clock-frequency = <400000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c3>; + status = "okay"; +}; + +&pcie_phy { + fsl,refclk-pad-mode = <IMX8_PCIE_REFCLK_PAD_INPUT>; + fsl,clkreq-unsupported; + clocks = <&pcie0_refclk>; + clock-names = "ref"; + status = "okay"; +}; + +&pcie { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pcie0>; + reset-gpio = <&gpio4 29 GPIO_ACTIVE_LOW>; + status = "okay"; +}; + +/* GPS */ +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1>; + status = "okay"; +}; + +/* USB1 - Type C front panel SINK port J14 */ +&usb3_0 { + status = "okay"; +}; + +&usb3_phy0 { + status = "okay"; +}; + +&usb_dwc3_0 { + dr_mode = "peripheral"; + status = "okay"; +}; + +/* USB2 4-port USB3.0 HUB: + * P1 - USBC connector (host only) + * P2 - USB2 test connector + * P3 - miniPCIe full card + * P4 - miniPCIe half card + */ +&usb3_phy1 { + vbus-supply = <®_usb2_vbus>; + status = "okay"; +}; + +&usb3_1 { + fsl,permanently-attached; + fsl,disable-port-power-control; + status = "okay"; +}; + +&usb_dwc3_1 { + dr_mode = "host"; + status = "okay"; +}; + +/* microSD */ +&usdhc2 { + pinctrl-names = "default", "state_100mhz", "state_200mhz"; + pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>; + pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_gpio>; + pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>; + cd-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>; + vmmc-supply = <®_usdhc2_vmmc>; + bus-width = <4>; + status = "okay"; +}; + +&iomuxc { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_hog>; + + pinctrl_hog: hoggrp { + fsl,pins = < + MX8MP_IOMUXC_GPIO1_IO13__GPIO1_IO13 0x40000040 /* GPIOA */ + MX8MP_IOMUXC_SAI1_RXC__GPIO4_IO01 0x40000040 /* GPIOD */ + MX8MP_IOMUXC_SAI1_RXD2__GPIO4_IO04 0x40000040 /* GPIOB */ + MX8MP_IOMUXC_SAI1_RXD3__GPIO4_IO05 0x40000040 /* GPIOC */ + MX8MP_IOMUXC_SAI2_TXD0__GPIO4_IO26 0x40000106 /* PCI_USBSEL */ + MX8MP_IOMUXC_SAI3_RXFS__GPIO4_IO28 0x40000106 /* PCI_WDIS# */ + >; + }; + + pinctrl_gpio_leds: gpioledgrp { + fsl,pins = < + MX8MP_IOMUXC_SAI2_RXC__GPIO4_IO22 0x6 /* LEDG */ + MX8MP_IOMUXC_SAI2_MCLK__GPIO4_IO27 0x6 /* LEDR */ + >; + }; + + pinctrl_i2c2: i2c2grp { + fsl,pins = < + MX8MP_IOMUXC_I2C2_SCL__I2C2_SCL 0x400001c2 + MX8MP_IOMUXC_I2C2_SDA__I2C2_SDA 0x400001c2 + >; + }; + + pinctrl_i2c3: i2c3grp { + fsl,pins = < + MX8MP_IOMUXC_I2C3_SCL__I2C3_SCL 0x400001c2 + MX8MP_IOMUXC_I2C3_SDA__I2C3_SDA 0x400001c2 + >; + }; + + pinctrl_pcie0: pciegrp { + fsl,pins = < + MX8MP_IOMUXC_SAI3_RXC__GPIO4_IO29 0x106 + >; + }; + + pinctrl_pps: ppsgrp { + fsl,pins = < + MX8MP_IOMUXC_SAI2_RXFS__GPIO4_IO21 0x106 + >; + }; + + pinctrl_reg_usb2_en: regusb2grp { + fsl,pins = < + MX8MP_IOMUXC_SAI1_TXD0__GPIO4_IO12 0x6 /* USBHUB_RST# (ext p/u) */ + >; + }; + + pinctrl_reg_usdhc2_vmmc: regusdhc2vmmcgrp { + fsl,pins = < + MX8MP_IOMUXC_SD2_RESET_B__GPIO2_IO19 0x40 + >; + }; + + pinctrl_spi2: spi2grp { + fsl,pins = < + MX8MP_IOMUXC_ECSPI2_SCLK__ECSPI2_SCLK 0x140 + MX8MP_IOMUXC_ECSPI2_MOSI__ECSPI2_MOSI 0x140 + MX8MP_IOMUXC_ECSPI2_MISO__ECSPI2_MISO 0x140 + MX8MP_IOMUXC_ECSPI2_SS0__GPIO5_IO13 0x140 + >; + }; + + pinctrl_uart1: uart1grp { + fsl,pins = < + MX8MP_IOMUXC_UART1_RXD__UART1_DCE_RX 0x140 + MX8MP_IOMUXC_UART1_TXD__UART1_DCE_TX 0x140 + >; + }; + + pinctrl_usdhc2: usdhc2grp { + fsl,pins = < + MX8MP_IOMUXC_SD2_CLK__USDHC2_CLK 0x190 + MX8MP_IOMUXC_SD2_CMD__USDHC2_CMD 0x1d0 + MX8MP_IOMUXC_SD2_DATA0__USDHC2_DATA0 0x1d0 + MX8MP_IOMUXC_SD2_DATA1__USDHC2_DATA1 0x1d0 + MX8MP_IOMUXC_SD2_DATA2__USDHC2_DATA2 0x1d0 + MX8MP_IOMUXC_SD2_DATA3__USDHC2_DATA3 0x1d0 + MX8MP_IOMUXC_GPIO1_IO04__USDHC2_VSELECT 0xc0 + >; + }; + + pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp { + fsl,pins = < + MX8MP_IOMUXC_SD2_CLK__USDHC2_CLK 0x194 + MX8MP_IOMUXC_SD2_CMD__USDHC2_CMD 0x1d4 + MX8MP_IOMUXC_SD2_DATA0__USDHC2_DATA0 0x1d4 + MX8MP_IOMUXC_SD2_DATA1__USDHC2_DATA1 0x1d4 + MX8MP_IOMUXC_SD2_DATA2__USDHC2_DATA2 0x1d4 + MX8MP_IOMUXC_SD2_DATA3__USDHC2_DATA3 0x1d4 + MX8MP_IOMUXC_GPIO1_IO04__USDHC2_VSELECT 0xc0 + >; + }; + + pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp { + fsl,pins = < + MX8MP_IOMUXC_SD2_CLK__USDHC2_CLK 0x196 + MX8MP_IOMUXC_SD2_CMD__USDHC2_CMD 0x1d6 + MX8MP_IOMUXC_SD2_DATA0__USDHC2_DATA0 0x1d6 + MX8MP_IOMUXC_SD2_DATA1__USDHC2_DATA1 0x1d6 + MX8MP_IOMUXC_SD2_DATA2__USDHC2_DATA2 0x1d6 + MX8MP_IOMUXC_SD2_DATA3__USDHC2_DATA3 0x1d6 + MX8MP_IOMUXC_GPIO1_IO04__USDHC2_VSELECT 0xc0 + >; + }; + + pinctrl_usdhc2_gpio: usdhc2gpiogrp { + fsl,pins = < + MX8MP_IOMUXC_SD2_CD_B__GPIO2_IO12 0x1c4 + >; + }; +}; diff --git a/arch/arm/dts/imx8mp-verdin-dahlia.dtsi b/arch/arm/dts/imx8mp-verdin-dahlia.dtsi deleted file mode 100644 index 4b8f86f6308..00000000000 --- a/arch/arm/dts/imx8mp-verdin-dahlia.dtsi +++ /dev/null @@ -1,129 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -/* - * Copyright 2022 Toradex - */ - -/* TODO: Audio Codec */ - -&backlight { - power-supply = <®_3p3v>; -}; - -/* Verdin SPI_1 */ -&ecspi1 { - status = "okay"; -}; - -/* EEPROM on display adapter boards */ -&eeprom_display_adapter { - status = "okay"; -}; - -/* EEPROM on Verdin Development board */ -&eeprom_carrier_board { - status = "okay"; -}; - -&eqos { - status = "okay"; -}; - -&flexcan1 { - status = "okay"; -}; - -&flexcan2 { - status = "okay"; -}; - -/* Verdin QSPI_1 */ -&flexspi { - status = "okay"; -}; - -/* Current measurement into module VCC */ -&hwmon { - status = "okay"; -}; - -&hwmon_temp { - vs-supply = <®_1p8v>; - status = "okay"; -}; - -/* Verdin I2C_2_DSI */ -&i2c2 { - status = "okay"; -}; - -&i2c3 { - status = "okay"; -}; - -/* Verdin I2C_1 */ -&i2c4 { - status = "okay"; - - /* TODO: Audio Codec */ -}; - -/* TODO: Verdin PCIE_1 */ - -/* Verdin PWM_1 */ -&pwm1 { - status = "okay"; -}; - -/* Verdin PWM_2 */ -&pwm2 { - status = "okay"; -}; - -/* Verdin PWM_3_DSI */ -&pwm3 { - status = "okay"; -}; - -®_usdhc2_vmmc { - vin-supply = <®_3p3v>; -}; - -/* TODO: Verdin I2S_1 */ - -/* Verdin UART_1 */ -&uart1 { - status = "okay"; -}; - -/* Verdin UART_2 */ -&uart2 { - status = "okay"; -}; - -/* Verdin UART_3, used as the Linux Console */ -&uart3 { - status = "okay"; -}; - -/* Verdin USB_1 */ -&usb3_0 { - status = "okay"; -}; - -&usb3_phy0 { - status = "okay"; -}; - -/* Verdin USB_2 */ -&usb3_1 { - status = "okay"; -}; - -&usb3_phy1 { - status = "okay"; -}; - -/* Verdin SD_1 */ -&usdhc2 { - status = "okay"; -}; diff --git a/arch/arm/dts/imx8mp-verdin-dev.dtsi b/arch/arm/dts/imx8mp-verdin-dev.dtsi index cefabe65b25..bdfdd4c782f 100644 --- a/arch/arm/dts/imx8mp-verdin-dev.dtsi +++ b/arch/arm/dts/imx8mp-verdin-dev.dtsi @@ -3,8 +3,6 @@ * Copyright 2022 Toradex */ -#include "imx8mp-verdin-dahlia.dtsi" - / { /* TODO: Audio Codec */ @@ -12,7 +10,7 @@ compatible = "regulator-fixed"; enable-active-high; gpio = <&gpio_expander_21 4 GPIO_ACTIVE_HIGH>; /* ETH_PWR_EN */ - off-on-delay = <500000>; + off-on-delay-us = <500000>; regulator-max-microvolt = <3300000>; regulator-min-microvolt = <3300000>; regulator-name = "+V3.3_ETH"; @@ -21,16 +19,106 @@ }; }; +&backlight { + power-supply = <®_3p3v>; +}; + +/* Verdin SPI_1 */ +&ecspi1 { + status = "okay"; +}; + +/* EEPROM on display adapter boards */ +&eeprom_display_adapter { + status = "okay"; +}; + +/* EEPROM on Verdin Development board */ +&eeprom_carrier_board { + status = "okay"; +}; + +&eqos { + status = "okay"; +}; + &fec { phy-supply = <®_eth2phy>; status = "okay"; }; +&flexcan1 { + status = "okay"; +}; + +&flexcan2 { + status = "okay"; +}; + +/* Verdin QSPI_1 */ +&flexspi { + status = "okay"; +}; + &gpio_expander_21 { status = "okay"; vcc-supply = <®_1p8v>; }; +/* Current measurement into module VCC */ +&hwmon { + status = "okay"; +}; + +&hwmon_temp { + vs-supply = <®_1p8v>; + status = "okay"; +}; + +/* Verdin I2C_2_DSI */ +&i2c2 { + status = "okay"; +}; + +&i2c3 { + status = "okay"; +}; + +/* Verdin I2C_1 */ +&i2c4 { + status = "okay"; + + /* TODO: Audio Codec */ +}; + +/* Verdin PCIE_1 */ +&pcie { + status = "okay"; +}; + +&pcie_phy { + status = "okay"; +}; + +/* Verdin PWM_1 */ +&pwm1 { + status = "okay"; +}; + +/* Verdin PWM_2 */ +&pwm2 { + status = "okay"; +}; + +/* Verdin PWM_3_DSI */ +&pwm3 { + status = "okay"; +}; + +®_usdhc2_vmmc { + vin-supply = <®_3p3v>; +}; + /* TODO: Verdin I2C_1 with Audio Codec */ /* Verdin UART_1, connector X50 through RS485 transceiver */ @@ -38,9 +126,40 @@ linux,rs485-enabled-at-boot-time; rs485-rts-active-low; rs485-rx-during-tx; + status = "okay"; +}; + +/* Verdin UART_2 */ +&uart2 { + status = "okay"; +}; + +/* Verdin UART_3, used as the Linux Console */ +&uart3 { + status = "okay"; +}; + +/* Verdin USB_1 */ +&usb3_0 { + status = "okay"; +}; + +&usb3_phy0 { + status = "okay"; +}; + +/* Verdin USB_2 */ +&usb3_1 { + fsl,permanently-attached; + status = "okay"; +}; + +&usb3_phy1 { + status = "okay"; }; /* Limit frequency on dev board due to long traces and bad signal integrity */ &usdhc2 { max-frequency = <100000000>; + status = "okay"; }; diff --git a/arch/arm/dts/imx8mp-verdin-wifi-dev-u-boot.dtsi b/arch/arm/dts/imx8mp-verdin-wifi-dev-u-boot.dtsi index 9c6c417f7ee..0162f9b2da3 100644 --- a/arch/arm/dts/imx8mp-verdin-wifi-dev-u-boot.dtsi +++ b/arch/arm/dts/imx8mp-verdin-wifi-dev-u-boot.dtsi @@ -62,6 +62,10 @@ &gpio4 { bootph-pre-ram; + + ctrl-sleep-moci-hog { + bootph-pre-ram; + }; }; &gpio5 { @@ -106,6 +110,10 @@ bootph-pre-ram; }; +&pinctrl_ctrl_sleep_moci { + bootph-pre-ram; +}; + &pinctrl_i2c1 { bootph-pre-ram; }; diff --git a/arch/arm/dts/imx8mp-verdin-wifi.dtsi b/arch/arm/dts/imx8mp-verdin-wifi.dtsi index 36289c175e6..ef94f9a57e2 100644 --- a/arch/arm/dts/imx8mp-verdin-wifi.dtsi +++ b/arch/arm/dts/imx8mp-verdin-wifi.dtsi @@ -65,6 +65,11 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_bt_uart>; status = "okay"; + + bluetooth { + compatible = "mrvl,88w8997"; + max-speed = <921600>; + }; }; /* On-module Wi-Fi */ diff --git a/arch/arm/dts/imx8mp-verdin.dtsi b/arch/arm/dts/imx8mp-verdin.dtsi index 7b712d1888e..e9e4fcb562f 100644 --- a/arch/arm/dts/imx8mp-verdin.dtsi +++ b/arch/arm/dts/imx8mp-verdin.dtsi @@ -3,7 +3,8 @@ * Copyright 2022 Toradex */ -#include "dt-bindings/pwm/pwm.h" +#include <dt-bindings/phy/phy-imx8-pcie.h> +#include <dt-bindings/pwm/pwm.h> #include "imx8mp.dtsi" / { @@ -49,7 +50,7 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_gpio_keys>; - button-wakeup { + key-wakeup { debounce-interval = <10>; /* Verdin CTRL_WAKE1_MICO# (SODIMM 252) */ gpios = <&gpio4 0 GPIO_ACTIVE_LOW>; @@ -86,7 +87,7 @@ compatible = "regulator-fixed"; enable-active-high; gpio = <&gpio2 20 GPIO_ACTIVE_HIGH>; /* PMIC_EN_ETH */ - off-on-delay = <500000>; + off-on-delay-us = <500000>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_reg_eth>; regulator-always-on; @@ -127,7 +128,7 @@ enable-active-high; /* Verdin SD_1_PWR_EN (SODIMM 76) */ gpio = <&gpio4 22 GPIO_ACTIVE_HIGH>; - off-on-delay = <100000>; + off-on-delay-us = <100000>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc2_pwr_en>; regulator-max-microvolt = <3300000>; @@ -354,16 +355,6 @@ "SODIMM_82", "SODIMM_70", "SODIMM_72"; - - ctrl-sleep-moci-hog { - gpio-hog; - /* Verdin CTRL_SLEEP_MOCI# (SODIMM 256) */ - gpios = <29 GPIO_ACTIVE_HIGH>; - line-name = "CTRL_SLEEP_MOCI#"; - output-high; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_ctrl_sleep_moci>; - }; }; &gpio3 { @@ -432,6 +423,16 @@ "SODIMM_256", "SODIMM_48", "SODIMM_44"; + + ctrl-sleep-moci-hog { + gpio-hog; + /* Verdin CTRL_SLEEP_MOCI# (SODIMM 256) */ + gpios = <29 GPIO_ACTIVE_HIGH>; + line-name = "CTRL_SLEEP_MOCI#"; + output-high; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ctrl_sleep_moci>; + }; }; /* On-module I2C */ @@ -452,7 +453,6 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_pmic>; reg = <0x25>; - sd-vsel-gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>; /* * The bootloader is expected to switch on LDO4 for the on-module +V3.3_ADC and the @@ -678,8 +678,8 @@ status = "disabled"; }; - lvds_ti_sn65dsi83: bridge@2c { - compatible = "ti,sn65dsi83"; + lvds_ti_sn65dsi84: bridge@2c { + compatible = "ti,sn65dsi84"; /* Verdin GPIO_9_DSI (SN65DSI84 IRQ, SODIMM 17, unused) */ /* Verdin GPIO_10_DSI (SODIMM 21) */ enable-gpios = <&gpio4 28 GPIO_ACTIVE_HIGH>; @@ -712,7 +712,7 @@ compatible = "atmel,maxtouch"; /* * Verdin GPIO_9_DSI - * (TOUCH_INT#, SODIMM 17, also routed to SN65DSI83 IRQ albeit currently unused) + * (TOUCH_INT#, SODIMM 17, also routed to SN65DSI84 IRQ albeit currently unused) */ interrupt-parent = <&gpio4>; interrupts = <25 IRQ_TYPE_EDGE_FALLING>; @@ -748,7 +748,20 @@ }; }; -/* TODO: Verdin PCIE_1 */ +/* Verdin PCIE_1 */ +&pcie { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pcie>; + /* PCIE_1_RESET# (SODIMM 244) */ + reset-gpio = <&gpio4 19 GPIO_ACTIVE_LOW>; +}; + +&pcie_phy { + clocks = <&hsio_blk_ctrl>; + clock-names = "ref"; + fsl,clkreq-unsupported; + fsl,refclk-pad-mode = <IMX8_PCIE_REFCLK_PAD_OUTPUT>; +}; /* Verdin PWM_1 */ &pwm1 { @@ -806,28 +819,45 @@ }; /* Verdin USB_1 */ -&usb3_phy0 { - vbus-supply = <®_usb1_vbus>; +&usb3_0 { + fsl,disable-port-power-control; + fsl,over-current-active-low; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usb_1_oc_n>; }; &usb_dwc3_0 { + /* dual role only, not full featured OTG */ adp-disable; dr_mode = "otg"; hnp-disable; maximum-speed = "high-speed"; - over-current-active-low; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_usb_1_id>; + role-switch-default-mode = "peripheral"; srp-disable; + usb-role-switch; + + connector { + compatible = "gpio-usb-b-connector", "usb-b-connector"; + id-gpios = <&gpio2 10 GPIO_ACTIVE_HIGH>; + label = "Type-C"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usb_1_id>; + self-powered; + type = "micro"; + vbus-supply = <®_usb1_vbus>; + }; }; /* Verdin USB_2 */ +&usb3_1 { + fsl,disable-port-power-control; +}; + &usb3_phy1 { vbus-supply = <®_usb2_vbus>; }; &usb_dwc3_1 { - disable-over-current; dr_mode = "host"; }; @@ -1045,7 +1075,6 @@ pinctrl_gpio_hog3: gpiohog3grp { fsl,pins = - <MX8MP_IOMUXC_GPIO1_IO13__GPIO1_IO13 0x1c4>, /* SODIMM 157 */ /* CSI_1_MCLK */ <MX8MP_IOMUXC_GPIO1_IO15__GPIO1_IO15 0x1c4>; /* SODIMM 91 */ }; @@ -1220,7 +1249,7 @@ pinctrl_usb1_vbus: usb1vbusgrp { fsl,pins = - <MX8MP_IOMUXC_GPIO1_IO12__USB1_OTG_PWR 0x19>; /* SODIMM 155 */ + <MX8MP_IOMUXC_GPIO1_IO12__GPIO1_IO12 0x106>; /* SODIMM 155 */ }; /* USB_1_ID */ @@ -1229,9 +1258,15 @@ <MX8MP_IOMUXC_SD1_RESET_B__GPIO2_IO10 0x1c4>; /* SODIMM 161 */ }; + /* USB_1_OC# */ + pinctrl_usb_1_oc_n: usb1ocngrp { + fsl,pins = + <MX8MP_IOMUXC_GPIO1_IO13__USB1_OTG_OC 0x1c4>; /* SODIMM 157 */ + }; + pinctrl_usb2_vbus: usb2vbusgrp { fsl,pins = - <MX8MP_IOMUXC_GPIO1_IO14__USB2_OTG_PWR 0x19>; /* SODIMM 185 */ + <MX8MP_IOMUXC_GPIO1_IO14__GPIO1_IO14 0x106>; /* SODIMM 185 */ }; /* On-module Wi-Fi */ diff --git a/arch/arm/dts/imx8mp.dtsi b/arch/arm/dts/imx8mp.dtsi index bb916a0948a..428c60462e3 100644 --- a/arch/arm/dts/imx8mp.dtsi +++ b/arch/arm/dts/imx8mp.dtsi @@ -123,6 +123,7 @@ A53_L2: l2-cache0 { compatible = "cache"; + cache-unified; cache-level = <2>; cache-size = <0x80000>; cache-line-size = <64>; @@ -379,6 +380,8 @@ compatible = "fsl,imx8mp-tmu"; reg = <0x30260000 0x10000>; clocks = <&clk IMX8MP_CLK_TSENSOR_ROOT>; + nvmem-cells = <&tmu_calib>; + nvmem-cell-names = "calib"; #thermal-sensor-cells = <1>; }; @@ -406,12 +409,36 @@ status = "disabled"; }; + gpt1: timer@302d0000 { + compatible = "fsl,imx8mp-gpt", "fsl,imx6dl-gpt"; + reg = <0x302d0000 0x10000>; + interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk IMX8MP_CLK_GPT1_ROOT>, <&clk IMX8MP_CLK_GPT1>; + clock-names = "ipg", "per"; + }; + + gpt2: timer@302e0000 { + compatible = "fsl,imx8mp-gpt", "fsl,imx6dl-gpt"; + reg = <0x302e0000 0x10000>; + interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk IMX8MP_CLK_GPT2_ROOT>, <&clk IMX8MP_CLK_GPT2>; + clock-names = "ipg", "per"; + }; + + gpt3: timer@302f0000 { + compatible = "fsl,imx8mp-gpt", "fsl,imx6dl-gpt"; + reg = <0x302f0000 0x10000>; + interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk IMX8MP_CLK_GPT3_ROOT>, <&clk IMX8MP_CLK_GPT3>; + clock-names = "ipg", "per"; + }; + iomuxc: pinctrl@30330000 { compatible = "fsl,imx8mp-iomuxc"; reg = <0x30330000 0x10000>; }; - gpr: iomuxc-gpr@30340000 { + gpr: syscon@30340000 { compatible = "fsl,imx8mp-iomuxc-gpr", "syscon"; reg = <0x30340000 0x10000>; }; @@ -424,27 +451,44 @@ #address-cells = <1>; #size-cells = <1>; - imx8mp_uid: unique-id@420 { + /* + * The register address below maps to the MX8M + * Fusemap Description Table entries this way. + * Assuming + * reg = <ADDR SIZE>; + * then + * Fuse Address = (ADDR * 4) + 0x400 + * Note that if SIZE is greater than 4, then + * each subsequent fuse is located at offset + * +0x10 in Fusemap Description Table (e.g. + * reg = <0x8 0x8> describes fuses 0x420 and + * 0x430). + */ + imx8mp_uid: unique-id@8 { /* 0x420-0x430 */ reg = <0x8 0x8>; }; - cpu_speed_grade: speed-grade@10 { + cpu_speed_grade: speed-grade@10 { /* 0x440 */ reg = <0x10 4>; }; - eth_mac1: mac-address@90 { + eth_mac1: mac-address@90 { /* 0x640 */ reg = <0x90 6>; }; - eth_mac2: mac-address@96 { + eth_mac2: mac-address@96 { /* 0x658 */ reg = <0x96 6>; }; + + tmu_calib: calib@264 { /* 0xd90-0xdc0 */ + reg = <0x264 0x10>; + }; }; - anatop: anatop@30360000 { - compatible = "fsl,imx8mp-anatop", "fsl,imx8mm-anatop", - "syscon"; + anatop: clock-controller@30360000 { + compatible = "fsl,imx8mp-anatop", "fsl,imx8mm-anatop"; reg = <0x30360000 0x10000>; + #clock-cells = <1>; }; snvs: snvs@30370000 { @@ -523,6 +567,7 @@ compatible = "fsl,imx8mp-gpc"; reg = <0x303a0000 0x1000>; interrupt-parent = <&gic>; + interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>; interrupt-controller; #interrupt-cells = <3>; @@ -589,7 +634,7 @@ reg = <IMX8MP_POWER_DOMAIN_MIPI_PHY2>; }; - pgc_hsiomix: power-domains@17 { + pgc_hsiomix: power-domain@17 { #power-domain-cells = <0>; reg = <IMX8MP_POWER_DOMAIN_HSIOMIX>; clocks = <&clk IMX8MP_CLK_HSIO_AXI>, @@ -631,6 +676,14 @@ reg = <IMX8MP_POWER_DOMAIN_VPU_VC8000E>; clocks = <&clk IMX8MP_CLK_VPU_VC8KE_ROOT>; }; + + pgc_mlmix: power-domain@24 { + #power-domain-cells = <0>; + reg = <IMX8MP_POWER_DOMAIN_MLMIX>; + clocks = <&clk IMX8MP_CLK_ML_AXI>, + <&clk IMX8MP_CLK_ML_AHB>, + <&clk IMX8MP_CLK_NPU_ROOT>; + }; }; }; }; @@ -693,6 +746,30 @@ clocks = <&osc_24m>; clock-names = "per"; }; + + gpt6: timer@306e0000 { + compatible = "fsl,imx8mp-gpt", "fsl,imx6dl-gpt"; + reg = <0x306e0000 0x10000>; + interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk IMX8MP_CLK_GPT6_ROOT>, <&clk IMX8MP_CLK_GPT6>; + clock-names = "ipg", "per"; + }; + + gpt5: timer@306f0000 { + compatible = "fsl,imx8mp-gpt", "fsl,imx6dl-gpt"; + reg = <0x306f0000 0x10000>; + interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk IMX8MP_CLK_GPT5_ROOT>, <&clk IMX8MP_CLK_GPT5>; + clock-names = "ipg", "per"; + }; + + gpt4: timer@30700000 { + compatible = "fsl,imx8mp-gpt", "fsl,imx6dl-gpt"; + reg = <0x30700000 0x10000>; + interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk IMX8MP_CLK_GPT4_ROOT>, <&clk IMX8MP_CLK_GPT4>; + clock-names = "ipg", "per"; + }; }; aips3: bus@30800000 { @@ -702,112 +779,129 @@ #size-cells = <1>; ranges; - ecspi1: spi@30820000 { + spba-bus@30800000 { + compatible = "fsl,spba-bus", "simple-bus"; + reg = <0x30800000 0x100000>; #address-cells = <1>; - #size-cells = <0>; - compatible = "fsl,imx8mp-ecspi", "fsl,imx51-ecspi"; - reg = <0x30820000 0x10000>; - interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clk IMX8MP_CLK_ECSPI1_ROOT>, - <&clk IMX8MP_CLK_ECSPI1_ROOT>; - clock-names = "ipg", "per"; - dmas = <&sdma1 0 7 1>, <&sdma1 1 7 2>; - dma-names = "rx", "tx"; - status = "disabled"; - }; + #size-cells = <1>; + ranges; - ecspi2: spi@30830000 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "fsl,imx8mp-ecspi", "fsl,imx51-ecspi"; - reg = <0x30830000 0x10000>; - interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clk IMX8MP_CLK_ECSPI2_ROOT>, - <&clk IMX8MP_CLK_ECSPI2_ROOT>; - clock-names = "ipg", "per"; - dmas = <&sdma1 2 7 1>, <&sdma1 3 7 2>; - dma-names = "rx", "tx"; - status = "disabled"; - }; + ecspi1: spi@30820000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx8mp-ecspi", "fsl,imx6ul-ecspi"; + reg = <0x30820000 0x10000>; + interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk IMX8MP_CLK_ECSPI1_ROOT>, + <&clk IMX8MP_CLK_ECSPI1_ROOT>; + clock-names = "ipg", "per"; + assigned-clock-rates = <80000000>; + assigned-clocks = <&clk IMX8MP_CLK_ECSPI1>; + assigned-clock-parents = <&clk IMX8MP_SYS_PLL1_800M>; + dmas = <&sdma1 0 7 1>, <&sdma1 1 7 2>; + dma-names = "rx", "tx"; + status = "disabled"; + }; - ecspi3: spi@30840000 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "fsl,imx8mp-ecspi", "fsl,imx51-ecspi"; - reg = <0x30840000 0x10000>; - interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clk IMX8MP_CLK_ECSPI3_ROOT>, - <&clk IMX8MP_CLK_ECSPI3_ROOT>; - clock-names = "ipg", "per"; - dmas = <&sdma1 4 7 1>, <&sdma1 5 7 2>; - dma-names = "rx", "tx"; - status = "disabled"; - }; + ecspi2: spi@30830000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx8mp-ecspi", "fsl,imx6ul-ecspi"; + reg = <0x30830000 0x10000>; + interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk IMX8MP_CLK_ECSPI2_ROOT>, + <&clk IMX8MP_CLK_ECSPI2_ROOT>; + clock-names = "ipg", "per"; + assigned-clock-rates = <80000000>; + assigned-clocks = <&clk IMX8MP_CLK_ECSPI2>; + assigned-clock-parents = <&clk IMX8MP_SYS_PLL1_800M>; + dmas = <&sdma1 2 7 1>, <&sdma1 3 7 2>; + dma-names = "rx", "tx"; + status = "disabled"; + }; - uart1: serial@30860000 { - compatible = "fsl,imx8mp-uart", "fsl,imx6q-uart"; - reg = <0x30860000 0x10000>; - interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clk IMX8MP_CLK_UART1_ROOT>, - <&clk IMX8MP_CLK_UART1_ROOT>; - clock-names = "ipg", "per"; - dmas = <&sdma1 22 4 0>, <&sdma1 23 4 0>; - dma-names = "rx", "tx"; - status = "disabled"; - }; + ecspi3: spi@30840000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx8mp-ecspi", "fsl,imx6ul-ecspi"; + reg = <0x30840000 0x10000>; + interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk IMX8MP_CLK_ECSPI3_ROOT>, + <&clk IMX8MP_CLK_ECSPI3_ROOT>; + clock-names = "ipg", "per"; + assigned-clock-rates = <80000000>; + assigned-clocks = <&clk IMX8MP_CLK_ECSPI3>; + assigned-clock-parents = <&clk IMX8MP_SYS_PLL1_800M>; + dmas = <&sdma1 4 7 1>, <&sdma1 5 7 2>; + dma-names = "rx", "tx"; + status = "disabled"; + }; - uart3: serial@30880000 { - compatible = "fsl,imx8mp-uart", "fsl,imx6q-uart"; - reg = <0x30880000 0x10000>; - interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clk IMX8MP_CLK_UART3_ROOT>, - <&clk IMX8MP_CLK_UART3_ROOT>; - clock-names = "ipg", "per"; - dmas = <&sdma1 26 4 0>, <&sdma1 27 4 0>; - dma-names = "rx", "tx"; - status = "disabled"; - }; + uart1: serial@30860000 { + compatible = "fsl,imx8mp-uart", "fsl,imx6q-uart"; + reg = <0x30860000 0x10000>; + interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk IMX8MP_CLK_UART1_ROOT>, + <&clk IMX8MP_CLK_UART1_ROOT>; + clock-names = "ipg", "per"; + dmas = <&sdma1 22 4 0>, <&sdma1 23 4 0>; + dma-names = "rx", "tx"; + status = "disabled"; + }; - uart2: serial@30890000 { - compatible = "fsl,imx8mp-uart", "fsl,imx6q-uart"; - reg = <0x30890000 0x10000>; - interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clk IMX8MP_CLK_UART2_ROOT>, - <&clk IMX8MP_CLK_UART2_ROOT>; - clock-names = "ipg", "per"; - dmas = <&sdma1 24 4 0>, <&sdma1 25 4 0>; - dma-names = "rx", "tx"; - status = "disabled"; - }; + uart3: serial@30880000 { + compatible = "fsl,imx8mp-uart", "fsl,imx6q-uart"; + reg = <0x30880000 0x10000>; + interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk IMX8MP_CLK_UART3_ROOT>, + <&clk IMX8MP_CLK_UART3_ROOT>; + clock-names = "ipg", "per"; + dmas = <&sdma1 26 4 0>, <&sdma1 27 4 0>; + dma-names = "rx", "tx"; + status = "disabled"; + }; - flexcan1: can@308c0000 { - compatible = "fsl,imx8mp-flexcan"; - reg = <0x308c0000 0x10000>; - interrupts = <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clk IMX8MP_CLK_IPG_ROOT>, - <&clk IMX8MP_CLK_CAN1_ROOT>; - clock-names = "ipg", "per"; - assigned-clocks = <&clk IMX8MP_CLK_CAN1>; - assigned-clock-parents = <&clk IMX8MP_SYS_PLL1_40M>; - assigned-clock-rates = <40000000>; - fsl,clk-source = /bits/ 8 <0>; - fsl,stop-mode = <&gpr 0x10 4>; - status = "disabled"; - }; + uart2: serial@30890000 { + compatible = "fsl,imx8mp-uart", "fsl,imx6q-uart"; + reg = <0x30890000 0x10000>; + interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk IMX8MP_CLK_UART2_ROOT>, + <&clk IMX8MP_CLK_UART2_ROOT>; + clock-names = "ipg", "per"; + dmas = <&sdma1 24 4 0>, <&sdma1 25 4 0>; + dma-names = "rx", "tx"; + status = "disabled"; + }; - flexcan2: can@308d0000 { - compatible = "fsl,imx8mp-flexcan"; - reg = <0x308d0000 0x10000>; - interrupts = <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clk IMX8MP_CLK_IPG_ROOT>, - <&clk IMX8MP_CLK_CAN2_ROOT>; - clock-names = "ipg", "per"; - assigned-clocks = <&clk IMX8MP_CLK_CAN2>; - assigned-clock-parents = <&clk IMX8MP_SYS_PLL1_40M>; - assigned-clock-rates = <40000000>; - fsl,clk-source = /bits/ 8 <0>; - fsl,stop-mode = <&gpr 0x10 5>; - status = "disabled"; + flexcan1: can@308c0000 { + compatible = "fsl,imx8mp-flexcan"; + reg = <0x308c0000 0x10000>; + interrupts = <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk IMX8MP_CLK_IPG_ROOT>, + <&clk IMX8MP_CLK_CAN1_ROOT>; + clock-names = "ipg", "per"; + assigned-clocks = <&clk IMX8MP_CLK_CAN1>; + assigned-clock-parents = <&clk IMX8MP_SYS_PLL1_40M>; + assigned-clock-rates = <40000000>; + fsl,clk-source = /bits/ 8 <0>; + fsl,stop-mode = <&gpr 0x10 4>; + status = "disabled"; + }; + + flexcan2: can@308d0000 { + compatible = "fsl,imx8mp-flexcan"; + reg = <0x308d0000 0x10000>; + interrupts = <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk IMX8MP_CLK_IPG_ROOT>, + <&clk IMX8MP_CLK_CAN2_ROOT>; + clock-names = "ipg", "per"; + assigned-clocks = <&clk IMX8MP_CLK_CAN2>; + assigned-clock-parents = <&clk IMX8MP_SYS_PLL1_40M>; + assigned-clock-rates = <40000000>; + fsl,clk-source = /bits/ 8 <0>; + fsl,stop-mode = <&gpr 0x10 5>; + status = "disabled"; + }; }; crypto: crypto@30900000 { @@ -1063,11 +1157,11 @@ noc_opp_table: opp-table { compatible = "operating-points-v2"; - opp-200M { + opp-200000000 { opp-hz = /bits/ 64 <200000000>; }; - opp-1000M { + opp-1000000000 { opp-hz = /bits/ 64 <1000000000>; }; }; @@ -1080,10 +1174,78 @@ #size-cells = <1>; ranges; + mipi_dsi: dsi@32e60000 { + compatible = "fsl,imx8mp-mipi-dsim"; + reg = <0x32e60000 0x400>; + clocks = <&clk IMX8MP_CLK_MEDIA_APB_ROOT>, + <&clk IMX8MP_CLK_MEDIA_MIPI_PHY1_REF>; + clock-names = "bus_clk", "sclk_mipi"; + assigned-clocks = <&clk IMX8MP_CLK_MEDIA_APB>, + <&clk IMX8MP_CLK_MEDIA_MIPI_PHY1_REF>; + assigned-clock-parents = <&clk IMX8MP_SYS_PLL1_800M>, + <&clk IMX8MP_CLK_24M>; + assigned-clock-rates = <200000000>, <24000000>; + samsung,pll-clock-frequency = <24000000>; + interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>; + power-domains = <&media_blk_ctrl IMX8MP_MEDIABLK_PD_MIPI_DSI_1>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + dsim_from_lcdif1: endpoint { + remote-endpoint = <&lcdif1_to_dsim>; + }; + }; + }; + }; + + lcdif1: display-controller@32e80000 { + compatible = "fsl,imx8mp-lcdif"; + reg = <0x32e80000 0x10000>; + clocks = <&clk IMX8MP_CLK_MEDIA_DISP1_PIX_ROOT>, + <&clk IMX8MP_CLK_MEDIA_APB_ROOT>, + <&clk IMX8MP_CLK_MEDIA_AXI_ROOT>; + clock-names = "pix", "axi", "disp_axi"; + interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>; + power-domains = <&media_blk_ctrl IMX8MP_MEDIABLK_PD_LCDIF_1>; + status = "disabled"; + + port { + lcdif1_to_dsim: endpoint { + remote-endpoint = <&dsim_from_lcdif1>; + }; + }; + }; + + lcdif2: display-controller@32e90000 { + compatible = "fsl,imx8mp-lcdif"; + reg = <0x32e90000 0x10000>; + interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk IMX8MP_CLK_MEDIA_DISP2_PIX_ROOT>, + <&clk IMX8MP_CLK_MEDIA_APB_ROOT>, + <&clk IMX8MP_CLK_MEDIA_AXI_ROOT>; + clock-names = "pix", "axi", "disp_axi"; + power-domains = <&media_blk_ctrl IMX8MP_MEDIABLK_PD_LCDIF_2>; + status = "disabled"; + + port { + lcdif2_to_ldb: endpoint { + remote-endpoint = <&ldb_from_lcdif2>; + }; + }; + }; + media_blk_ctrl: blk-ctrl@32ec0000 { compatible = "fsl,imx8mp-media-blk-ctrl", "syscon"; reg = <0x32ec0000 0x10000>; + #address-cells = <1>; + #size-cells = <1>; power-domains = <&pgc_mediamix>, <&pgc_mipi_phy1>, <&pgc_mipi_phy1>, @@ -1122,12 +1284,55 @@ "disp1", "disp2", "isp", "phy"; assigned-clocks = <&clk IMX8MP_CLK_MEDIA_AXI>, - <&clk IMX8MP_CLK_MEDIA_APB>; + <&clk IMX8MP_CLK_MEDIA_APB>, + <&clk IMX8MP_CLK_MEDIA_DISP1_PIX>, + <&clk IMX8MP_CLK_MEDIA_DISP2_PIX>, + <&clk IMX8MP_VIDEO_PLL1>; assigned-clock-parents = <&clk IMX8MP_SYS_PLL2_1000M>, - <&clk IMX8MP_SYS_PLL1_800M>; - assigned-clock-rates = <500000000>, <200000000>; - + <&clk IMX8MP_SYS_PLL1_800M>, + <&clk IMX8MP_VIDEO_PLL1_OUT>, + <&clk IMX8MP_VIDEO_PLL1_OUT>; + assigned-clock-rates = <500000000>, <200000000>, + <0>, <0>, <1039500000>; #power-domain-cells = <1>; + + lvds_bridge: bridge@5c { + compatible = "fsl,imx8mp-ldb"; + reg = <0x5c 0x4>, <0x128 0x4>; + reg-names = "ldb", "lvds"; + clocks = <&clk IMX8MP_CLK_MEDIA_LDB>; + clock-names = "ldb"; + assigned-clocks = <&clk IMX8MP_CLK_MEDIA_LDB>; + assigned-clock-parents = <&clk IMX8MP_VIDEO_PLL1_OUT>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ldb_from_lcdif2: endpoint { + remote-endpoint = <&lcdif2_to_ldb>; + }; + }; + + port@1 { + reg = <1>; + + ldb_lvds_ch0: endpoint { + }; + }; + + port@2 { + reg = <2>; + + ldb_lvds_ch1: endpoint { + }; + }; + }; + }; }; pcie_phy: pcie-phy@32f00000 { @@ -1158,6 +1363,7 @@ <&noc IMX8MP_ICM_PCIE &noc IMX8MP_ICN_HSIO>; interconnect-names = "noc-pcie", "usb1", "usb2", "pcie"; #power-domain-cells = <1>; + #clock-cells = <0>; }; }; @@ -1165,6 +1371,13 @@ compatible = "fsl,imx8mp-pcie"; reg = <0x33800000 0x400000>, <0x1ff00000 0x80000>; reg-names = "dbi", "config"; + clocks = <&clk IMX8MP_CLK_HSIO_ROOT>, + <&clk IMX8MP_CLK_HSIO_AXI>, + <&clk IMX8MP_CLK_PCIE_ROOT>; + clock-names = "pcie", "pcie_bus", "pcie_aux"; + assigned-clocks = <&clk IMX8MP_CLK_PCIE_AUX>; + assigned-clock-rates = <10000000>; + assigned-clock-parents = <&clk IMX8MP_SYS_PLL2_50M>; #address-cells = <3>; #size-cells = <2>; device_type = "pci"; @@ -1192,6 +1405,32 @@ status = "disabled"; }; + pcie_ep: pcie-ep@33800000 { + compatible = "fsl,imx8mp-pcie-ep"; + reg = <0x33800000 0x000400000>, <0x18000000 0x08000000>; + reg-names = "dbi", "addr_space"; + clocks = <&clk IMX8MP_CLK_HSIO_ROOT>, + <&clk IMX8MP_CLK_HSIO_AXI>, + <&clk IMX8MP_CLK_PCIE_ROOT>; + clock-names = "pcie", "pcie_bus", "pcie_aux"; + assigned-clocks = <&clk IMX8MP_CLK_PCIE_AUX>; + assigned-clock-rates = <10000000>; + assigned-clock-parents = <&clk IMX8MP_SYS_PLL2_50M>; + num-lanes = <1>; + interrupts = <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>; /* eDMA */ + interrupt-names = "dma"; + fsl,max-link-speed = <3>; + power-domains = <&hsio_blk_ctrl IMX8MP_HSIOBLK_PD_PCIE>; + resets = <&src IMX8MP_RESET_PCIE_CTRL_APPS_EN>, + <&src IMX8MP_RESET_PCIE_CTRL_APPS_TURNOFF>; + reset-names = "apps", "turnoff"; + phys = <&pcie_phy>; + phy-names = "pcie-phy"; + num-ib-windows = <4>; + num-ob-windows = <4>; + status = "disabled"; + }; + gpu3d: gpu@38000000 { compatible = "vivante,gc"; reg = <0x38000000 0x8000>; @@ -1223,6 +1462,28 @@ power-domains = <&pgc_gpu2d>; }; + vpu_g1: video-codec@38300000 { + compatible = "nxp,imx8mm-vpu-g1"; + reg = <0x38300000 0x10000>; + interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk IMX8MP_CLK_VPU_G1_ROOT>; + assigned-clocks = <&clk IMX8MP_CLK_VPU_G1>; + assigned-clock-parents = <&clk IMX8MP_VPU_PLL_OUT>; + assigned-clock-rates = <600000000>; + power-domains = <&vpumix_blk_ctrl IMX8MP_VPUBLK_PD_G1>; + }; + + vpu_g2: video-codec@38310000 { + compatible = "nxp,imx8mq-vpu-g2"; + reg = <0x38310000 0x10000>; + interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk IMX8MP_CLK_VPU_G2_ROOT>; + assigned-clocks = <&clk IMX8MP_CLK_VPU_G2>; + assigned-clock-parents = <&clk IMX8MP_SYS_PLL2_1000M>; + assigned-clock-rates = <500000000>; + power-domains = <&vpumix_blk_ctrl IMX8MP_VPUBLK_PD_G2>; + }; + vpumix_blk_ctrl: blk-ctrl@38330000 { compatible = "fsl,imx8mp-vpu-blk-ctrl", "syscon"; reg = <0x38330000 0x100>; @@ -1234,6 +1495,9 @@ <&clk IMX8MP_CLK_VPU_G2_ROOT>, <&clk IMX8MP_CLK_VPU_VC8KE_ROOT>; clock-names = "g1", "g2", "vc8000e"; + assigned-clocks = <&clk IMX8MP_CLK_VPU_BUS>, <&clk IMX8MP_VPU_PLL>; + assigned-clock-parents = <&clk IMX8MP_VPU_PLL_OUT>; + assigned-clock-rates = <600000000>, <600000000>; interconnects = <&noc IMX8MP_ICM_VPU_G1 &noc IMX8MP_ICN_VIDEO>, <&noc IMX8MP_ICM_VPU_G2 &noc IMX8MP_ICN_VIDEO>, <&noc IMX8MP_ICM_VPU_H1 &noc IMX8MP_ICN_VIDEO>; @@ -1279,7 +1543,7 @@ reg = <0x32f10100 0x8>, <0x381f0000 0x20>; clocks = <&clk IMX8MP_CLK_HSIO_ROOT>, - <&clk IMX8MP_CLK_USB_ROOT>; + <&clk IMX8MP_CLK_USB_SUSP>; clock-names = "hsio", "suspend"; interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>; power-domains = <&hsio_blk_ctrl IMX8MP_HSIOBLK_PD_USB>; @@ -1292,9 +1556,9 @@ usb_dwc3_0: usb@38100000 { compatible = "snps,dwc3"; reg = <0x38100000 0x10000>; - clocks = <&clk IMX8MP_CLK_HSIO_AXI>, + clocks = <&clk IMX8MP_CLK_USB_ROOT>, <&clk IMX8MP_CLK_USB_CORE_REF>, - <&clk IMX8MP_CLK_USB_ROOT>; + <&clk IMX8MP_CLK_USB_SUSP>; clock-names = "bus_early", "ref", "suspend"; interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>; phys = <&usb3_phy0>, <&usb3_phy0>; @@ -1321,7 +1585,7 @@ reg = <0x32f10108 0x8>, <0x382f0000 0x20>; clocks = <&clk IMX8MP_CLK_HSIO_ROOT>, - <&clk IMX8MP_CLK_USB_ROOT>; + <&clk IMX8MP_CLK_USB_SUSP>; clock-names = "hsio", "suspend"; interrupts = <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>; power-domains = <&hsio_blk_ctrl IMX8MP_HSIOBLK_PD_USB>; @@ -1334,9 +1598,9 @@ usb_dwc3_1: usb@38200000 { compatible = "snps,dwc3"; reg = <0x38200000 0x10000>; - clocks = <&clk IMX8MP_CLK_HSIO_AXI>, + clocks = <&clk IMX8MP_CLK_USB_ROOT>, <&clk IMX8MP_CLK_USB_CORE_REF>, - <&clk IMX8MP_CLK_USB_ROOT>; + <&clk IMX8MP_CLK_USB_SUSP>; clock-names = "bus_early", "ref", "suspend"; interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>; phys = <&usb3_phy1>, <&usb3_phy1>; diff --git a/arch/arm/dts/nuvoton-npcm8xx-u-boot.dtsi b/arch/arm/dts/nuvoton-npcm8xx-u-boot.dtsi index be2ad0cf6cd..e49e564b790 100644 --- a/arch/arm/dts/nuvoton-npcm8xx-u-boot.dtsi +++ b/arch/arm/dts/nuvoton-npcm8xx-u-boot.dtsi @@ -289,6 +289,23 @@ status = "disable"; }; + aes: aes@f0858000 { + compatible = "nuvoton,npcm845-aes"; + reg = <0x0 0xf0858000 0x0 0x1000>, + <0x0 0xf0851000 0x0 0x1000>; + status = "disabled"; + clocks = <&clk NPCM8XX_CLK_AHB>; + clock-names = "clk_ahb"; + }; + + sha:sha@f085a000 { + compatible = "nuvoton,npcm845-sha"; + reg = <0x0 0xf085a000 0x0 0x1000>; + status = "disabled"; + clocks = <&clk NPCM8XX_CLK_AHB>; + clock-names = "clk_ahb"; + }; + apb { serial0: serial@0 { compatible = "nuvoton,npcm845-uart"; @@ -417,22 +434,6 @@ status = "disabled"; }; - aes: aes@f0858000 { - compatible = "nuvoton,npcm845-aes"; - reg = <0x0 0xf0858000 0x0 0x1000>, - <0x0 0xf0851000 0x0 0x1000>; - status = "disabled"; - clocks = <&clk NPCM8XX_CLK_AHB>; - clock-names = "clk_ahb"; - }; - - sha:sha@f085a000 { - compatible = "nuvoton,npcm845-sha"; - reg = <0x0 0xf085a000 0x0 0x1000>; - status = "disabled"; - clocks = <&clk NPCM8XX_CLK_AHB>; - clock-names = "clk_ahb"; - }; }; }; pinctrl: pinctrl@f0800000 { diff --git a/arch/arm/include/asm/arch-imx8m/imx-regs.h b/arch/arm/include/asm/arch-imx8m/imx-regs.h index 6e2fc82a0e4..f1b7526ac77 100644 --- a/arch/arm/include/asm/arch-imx8m/imx-regs.h +++ b/arch/arm/include/asm/arch-imx8m/imx-regs.h @@ -13,7 +13,7 @@ #define ROM_VERSION_A0 IS_ENABLED(CONFIG_IMX8MQ) ? 0x800 : 0x800 #define ROM_VERSION_B0 IS_ENABLED(CONFIG_IMX8MQ) ? 0x83C : 0x800 -#define M4_BOOTROM_BASE_ADDR 0x007E0000 +#define MCU_BOOTROM_BASE_ADDR 0x007E0000 #define GPIO1_BASE_ADDR 0X30200000 #define GPIO2_BASE_ADDR 0x30210000 @@ -40,6 +40,7 @@ #define UART1_BASE_ADDR 0x30860000 #define UART3_BASE_ADDR 0x30880000 #define UART2_BASE_ADDR 0x30890000 +#define CAAM_BASE_ADDR 0x30900000 #define I2C1_BASE_ADDR 0x30A20000 #define I2C2_BASE_ADDR 0x30A30000 #define I2C3_BASE_ADDR 0x30A40000 diff --git a/arch/arm/include/asm/arch-imx9/ccm_regs.h b/arch/arm/include/asm/arch-imx9/ccm_regs.h index d326a6ea516..f6ec8fda3e6 100644 --- a/arch/arm/include/asm/arch-imx9/ccm_regs.h +++ b/arch/arm/include/asm/arch-imx9/ccm_regs.h @@ -12,7 +12,7 @@ #define ARM_A55_MTR_BUS_CLK_ROOT 1 #define ARM_A55_CLK_ROOT 2 #define M33_CLK_ROOT 3 -#define SENTINEL_CLK_ROOT 4 +#define ELE_CLK_ROOT 4 #define BUS_WAKEUP_CLK_ROOT 5 #define BUS_AON_CLK_ROOT 6 #define WAKEUP_AXI_CLK_ROOT 7 diff --git a/arch/arm/include/asm/arch-mx6/imx-regs.h b/arch/arm/include/asm/arch-mx6/imx-regs.h index 72944af18a4..8fd3dd2df3a 100644 --- a/arch/arm/include/asm/arch-mx6/imx-regs.h +++ b/arch/arm/include/asm/arch-mx6/imx-regs.h @@ -23,7 +23,7 @@ #define GPU_ARB_END_ADDR 0x01803FFF #define APBH_DMA_ARB_BASE_ADDR 0x01804000 #define APBH_DMA_ARB_END_ADDR 0x0180BFFF -#define M4_BOOTROM_BASE_ADDR 0x007F8000 +#define MCU_BOOTROM_BASE_ADDR 0x007F8000 #elif !defined(CONFIG_MX6SLL) #define CAAM_ARB_BASE_ADDR 0x00100000 diff --git a/arch/arm/include/asm/arch-mx7/imx-regs.h b/arch/arm/include/asm/arch-mx7/imx-regs.h index c863cd9da36..6f5ae5173c0 100644 --- a/arch/arm/include/asm/arch-mx7/imx-regs.h +++ b/arch/arm/include/asm/arch-mx7/imx-regs.h @@ -18,7 +18,7 @@ #define GIC400_ARB_END_ADDR 0x31007FFF #define APBH_DMA_ARB_BASE_ADDR 0x33000000 #define APBH_DMA_ARB_END_ADDR 0x33007FFF -#define M4_BOOTROM_BASE_ADDR 0x00180000 +#define MCU_BOOTROM_BASE_ADDR 0x00180000 #define MXS_APBH_BASE APBH_DMA_ARB_BASE_ADDR #define MXS_GPMI_BASE (APBH_DMA_ARB_BASE_ADDR + 0x02000) diff --git a/arch/arm/include/asm/arch-npcm8xx/gcr.h b/arch/arm/include/asm/arch-npcm8xx/gcr.h index ee6677a0e54..20230d64e6b 100644 --- a/arch/arm/include/asm/arch-npcm8xx/gcr.h +++ b/arch/arm/include/asm/arch-npcm8xx/gcr.h @@ -12,6 +12,7 @@ /* On-Chip ARBEL NPCM8XX VERSIONS */ #define ARBEL_Z1 0x00A35850 #define ARBEL_A1 0x04a35850 +#define ARBEL_A2 0x08a35850 #define ARBEL_NPCM845 0x00000000 #define ARBEL_NPCM830 0x00300395 #define ARBEL_NPCM810 0x00000220 diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h index 0c130757110..2a222c53882 100644 --- a/arch/arm/include/asm/global_data.h +++ b/arch/arm/include/asm/global_data.h @@ -92,8 +92,8 @@ struct arch_global_data { struct udevice *scu_dev; #endif -#ifdef CONFIG_IMX_SENTINEL - struct udevice *s400_dev; +#ifdef CONFIG_IMX_ELE + struct udevice *ele_dev; u32 soc_rev; u32 lifecycle; u32 uid[4]; diff --git a/arch/arm/include/asm/mach-imx/ahab.h b/arch/arm/include/asm/mach-imx/ahab.h new file mode 100644 index 00000000000..4222e3db278 --- /dev/null +++ b/arch/arm/include/asm/mach-imx/ahab.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2020 NXP + */ + +#ifndef __IMX_AHAB_H__ +#define __IMX_AHAB_H__ + +#include <asm/mach-imx/image.h> + +int ahab_auth_cntr_hdr(struct container_hdr *container, u16 length); +int ahab_auth_release(void); +int ahab_verify_cntr_image(struct boot_img_t *img, int image_index); + +#endif diff --git a/arch/arm/include/asm/mach-imx/s400_api.h b/arch/arm/include/asm/mach-imx/ele_api.h index 5582ff1a254..cfd4ecebb62 100644 --- a/arch/arm/include/asm/mach-imx/s400_api.h +++ b/arch/arm/include/asm/mach-imx/ele_api.h @@ -3,12 +3,12 @@ * Copyright 2021 NXP */ -#ifndef __S400_API_H__ -#define __S400_API_H__ +#ifndef __ELE_API_H__ +#define __ELE_API_H__ -#define AHAB_VERSION 0x6 -#define AHAB_CMD_TAG 0x17 -#define AHAB_RESP_TAG 0xe1 +#define ELE_VERSION 0x6 +#define ELE_CMD_TAG 0x17 +#define ELE_RESP_TAG 0xe1 /* ELE commands */ #define ELE_PING_REQ (0x01) @@ -24,6 +24,8 @@ #define ELE_GET_FW_VERSION_REQ (0x9D) #define ELE_RET_LIFECYCLE_UP_REQ (0xA0) #define ELE_GET_EVENTS_REQ (0xA2) +#define ELE_START_RNG (0xA3) +#define ELE_GENERATE_DEK_BLOB (0xAF) #define ELE_ENABLE_PATCH_REQ (0xC3) #define ELE_RELEASE_RDC_REQ (0xC4) #define ELE_GET_FW_STATUS_REQ (0xC5) @@ -109,17 +111,17 @@ #define ELE_SUCCESS_IND (0xD6) #define ELE_FAILURE_IND (0x29) -#define S400_MAX_MSG 255U +#define ELE_MAX_MSG 255U -struct sentinel_msg { +struct ele_msg { u8 version; u8 size; u8 command; u8 tag; - u32 data[(S400_MAX_MSG - 1U)]; + u32 data[(ELE_MAX_MSG - 1U)]; }; -struct sentinel_get_info_data { +struct ele_get_info_data { u32 hdr; u32 soc; u32 lc; @@ -130,19 +132,22 @@ struct sentinel_get_info_data { u32 state; }; -int ahab_release_rdc(u8 core_id, u8 xrdc, u32 *response); -int ahab_auth_oem_ctnr(ulong ctnr_addr, u32 *response); -int ahab_release_container(u32 *response); -int ahab_verify_image(u32 img_id, u32 *response); -int ahab_forward_lifecycle(u16 life_cycle, u32 *response); -int ahab_write_fuse(u16 fuse_id, u32 fuse_val, bool lock, u32 *response); -int ahab_read_common_fuse(u16 fuse_id, u32 *fuse_words, u32 fuse_num, u32 *response); -int ahab_release_caam(u32 core_did, u32 *response); -int ahab_get_fw_version(u32 *fw_version, u32 *sha1, u32 *response); -int ahab_dump_buffer(u32 *buffer, u32 buffer_length); -int ahab_get_info(struct sentinel_get_info_data *info, u32 *response); -int ahab_get_fw_status(u32 *status, u32 *response); -int ahab_release_m33_trout(void); -int ahab_get_events(u32 *events, u32 *events_cnt, u32 *response); - +int ele_release_rdc(u8 core_id, u8 xrdc, u32 *response); +int ele_auth_oem_ctnr(ulong ctnr_addr, u32 *response); +int ele_release_container(u32 *response); +int ele_verify_image(u32 img_id, u32 *response); +int ele_forward_lifecycle(u16 life_cycle, u32 *response); +int ele_write_fuse(u16 fuse_id, u32 fuse_val, bool lock, u32 *response); +int ele_read_common_fuse(u16 fuse_id, u32 *fuse_words, u32 fuse_num, u32 *response); +int ele_release_caam(u32 core_did, u32 *response); +int ele_get_fw_version(u32 *fw_version, u32 *sha1, u32 *response); +int ele_get_events(u32 *events, u32 *events_cnt, u32 *response); +int ele_generate_dek_blob(u32 key_id, u32 src_paddr, u32 dst_paddr, u32 max_output_size); +int ele_dump_buffer(u32 *buffer, u32 buffer_length); +int ele_get_info(struct ele_get_info_data *info, u32 *response); +int ele_get_fw_status(u32 *status, u32 *response); +int ele_release_m33_trout(void); +int ele_write_secure_fuse(ulong signed_msg_blk, u32 *response); +int ele_return_lifecycle_update(ulong signed_msg_blk, u32 *response); +int ele_start_rng(void); #endif diff --git a/arch/arm/include/asm/mach-imx/sys_proto.h b/arch/arm/include/asm/mach-imx/sys_proto.h index 85d9ca60b14..31ae179b211 100644 --- a/arch/arm/include/asm/mach-imx/sys_proto.h +++ b/arch/arm/include/asm/mach-imx/sys_proto.h @@ -236,6 +236,7 @@ void board_mem_get_layout(u64 *phys_sdram_1_start, u64 *phys_sdram_2_start, u64 *phys_sdram_2_size); +int arch_auxiliary_core_up(u32 core_id, ulong boot_private_data); int arch_auxiliary_core_check_up(u32 core_id); int board_mmc_get_env_dev(int devno); diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 3266545c266..d94b5828d0d 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -31,7 +31,7 @@ config IMX_RDC config IMX_BOOTAUX bool "Support boot auxiliary core" - depends on ARCH_MX7 || ARCH_MX6 || ARCH_VF610 || ARCH_IMX8M + depends on ARCH_MX7 || ARCH_MX6 || ARCH_VF610 || ARCH_IMX8 || ARCH_IMX8M help bootaux [addr] to boot auxiliary core. @@ -86,6 +86,7 @@ config CMD_DEKBLOB select IMX_CAAM_DEK_ENCAP if ARCH_MX6 || ARCH_MX7 || ARCH_MX7ULP select IMX_OPTEE_DEK_ENCAP if ARCH_IMX8M select IMX_SECO_DEK_ENCAP if ARCH_IMX8 + select IMX_ELE_DEK_ENCAP if ARCH_IMX8ULP || ARCH_IMX9 help This enables the 'dek_blob' command which is used with the Freescale secure boot mechanism. This command encapsulates and @@ -113,6 +114,12 @@ config IMX_SECO_DEK_ENCAP This enabled the DEK blob encapsulation with the SECO API. This option is only available on imx8. +config IMX_ELE_DEK_ENCAP + bool "Support the DEK blob encapsulation with ELE" + help + This enabled the DEK blob encapsulation with the ELE API. This option + is only available on imx8ulp and imx9. + config CMD_PRIBLOB bool "Support the set_priblob_bitfield command" depends on HAS_CAAM && IMX_HAB diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index 00d6ad85c56..aebfa6517bd 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -66,6 +66,11 @@ ifeq ($(SOC),$(filter $(SOC),vf610)) obj-y += ddrmc-vf610.o obj-$(CONFIG_DDRMC_VF610_CALIBRATION) += ddrmc-vf610-calibration.o endif +ifeq ($(SOC),$(filter $(SOC),imx8)) +ifneq ($(CONFIG_SPL_BUILD),y) +obj-$(CONFIG_IMX_BOOTAUX) += imx_bootaux.o +endif +endif ifneq ($(CONFIG_SPL_BUILD),y) obj-$(CONFIG_CMD_BMODE) += cmd_bmode.o obj-$(CONFIG_CMD_HDMIDETECT) += cmd_hdmidet.o diff --git a/arch/arm/mach-imx/cmd_dek.c b/arch/arm/mach-imx/cmd_dek.c index 69ed57537b3..6fa5b41fcd3 100644 --- a/arch/arm/mach-imx/cmd_dek.c +++ b/arch/arm/mach-imx/cmd_dek.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0+ /* * Copyright 2008-2015 Freescale Semiconductor, Inc. + * Copyright 2022 NXP * * Command for encapsulating DEK blob */ @@ -20,6 +21,11 @@ #include <firmware/imx/sci/sci.h> #include <asm/mach-imx/image.h> #endif +#ifdef CONFIG_IMX_ELE_DEK_ENCAP +#include <asm/mach-imx/ele_api.h> +#include <asm/mach-imx/image.h> +#endif + #include <cpu_func.h> /** @@ -101,6 +107,7 @@ static int blob_encap_dek(u32 src_addr, u32 dst_addr, u32 len) 0x0, &shm_output); if (ret < 0) { printf("Cannot register output shared memory 0x%X\n", ret); + tee_shm_free(shm_input); goto error; } @@ -122,11 +129,11 @@ static int blob_encap_dek(u32 src_addr, u32 dst_addr, u32 len) if (ret < 0) printf("Cannot generate Blob with PTA DEK Blob 0x%X\n", ret); -error: /* Free shared memory */ tee_shm_free(shm_input); tee_shm_free(shm_output); +error: /* Close session */ ret = tee_close_session(dev, arg.session); if (ret < 0) @@ -154,7 +161,7 @@ error: static int blob_encap_dek(u32 src_addr, u32 dst_addr, u32 len) { - sc_err_t err; + int err; sc_rm_mr_t mr_input, mr_output; struct generate_key_blob_hdr hdr; u8 in_size, out_size; @@ -283,6 +290,84 @@ error: } #endif /* CONFIG_IMX_SECO_DEK_ENCAP */ +#ifdef CONFIG_IMX_ELE_DEK_ENCAP + +#define DEK_BLOB_HDR_SIZE 8 +#define AHAB_PRIVATE_KEY 0x81 +#define AHAB_DEK_BLOB 0x01 +#define AHAB_ALG_AES 0x03 +#define AHAB_128_AES_KEY 0x10 +#define AHAB_192_AES_KEY 0x18 +#define AHAB_256_AES_KEY 0x20 + +static int blob_encap_dek(u32 src_addr, u32 dst_addr, u32 len) +{ + u8 in_size, out_size; + u8 *src_ptr, *dst_ptr; + struct generate_key_blob_hdr hdr; + + /* Set sizes */ + in_size = sizeof(struct generate_key_blob_hdr) + len / 8; + out_size = BLOB_SIZE(len / 8) + DEK_BLOB_HDR_SIZE; + + /* Get src and dst virtual addresses */ + src_ptr = map_sysmem(src_addr, in_size); + dst_ptr = map_sysmem(dst_addr, out_size); + + /* Check addr input */ + if (!(src_ptr && dst_ptr)) { + debug("src_addr or dst_addr invalid\n"); + return -1; + } + + /* Build key header */ + hdr.version = 0x0; + hdr.length_lsb = in_size; + hdr.length_msb = 0x00; + hdr.tag = AHAB_PRIVATE_KEY; + hdr.flags = AHAB_DEK_BLOB; + hdr.algorithm = AHAB_ALG_AES; + hdr.mode = 0x0; /* Not used by the ELE */ + + switch (len) { + case 128: + hdr.size = AHAB_128_AES_KEY; + break; + case 192: + hdr.size = AHAB_192_AES_KEY; + break; + case 256: + hdr.size = AHAB_256_AES_KEY; + break; + default: + /* Not supported */ + debug("Invalid DEK size. Valid sizes are 128, 192 and 256b\n"); + return -1; + } + + /* Move input key and append blob header */ + memmove((void *)(src_ptr + sizeof(struct generate_key_blob_hdr)), + (void *)src_ptr, len / 8); + memcpy((void *)src_ptr, (void *)&hdr, + sizeof(struct generate_key_blob_hdr)); + + /* Flush the cache */ + flush_dcache_range(src_addr, src_addr + in_size); + flush_dcache_range((ulong)dst_ptr, (ulong)(dst_ptr + + roundup(out_size, ARCH_DMA_MINALIGN))); + + /* Call ELE */ + if (ele_generate_dek_blob(0x00, src_addr, dst_addr, out_size)) + return -1; + + /* Invalidate output buffer */ + invalidate_dcache_range((ulong)dst_ptr, (ulong)(dst_ptr + + roundup(out_size, ARCH_DMA_MINALIGN))); + + return 0; +} +#endif /* CONFIG_IMX_ELE_DEK_ENCAP */ + /** * do_dek_blob() - Handle the "dek_blob" command-line command * @cmdtp: Command data struct pointer diff --git a/arch/arm/mach-imx/ele_ahab.c b/arch/arm/mach-imx/ele_ahab.c index 99fc5402719..785b0d6ec3c 100644 --- a/arch/arm/mach-imx/ele_ahab.c +++ b/arch/arm/mach-imx/ele_ahab.c @@ -7,14 +7,13 @@ #include <command.h> #include <errno.h> #include <asm/io.h> -#include <asm/mach-imx/s400_api.h> +#include <asm/mach-imx/ele_api.h> #include <asm/mach-imx/sys_proto.h> #include <asm/arch-imx/cpu.h> #include <asm/arch/sys_proto.h> #include <asm/mach-imx/image.h> #include <console.h> #include <cpu_func.h> -#include <asm/mach-imx/ahab.h> #include <asm/global_data.h> DECLARE_GLOBAL_DATA_PTR; @@ -267,7 +266,7 @@ int ahab_auth_cntr_hdr(struct container_hdr *container, u16 length) flush_dcache_range(IMG_CONTAINER_BASE, IMG_CONTAINER_BASE + ALIGN(length, CONFIG_SYS_CACHELINE_SIZE) - 1); - err = ahab_auth_oem_ctnr(IMG_CONTAINER_BASE, &resp); + err = ele_auth_oem_ctnr(IMG_CONTAINER_BASE, &resp); if (err) { printf("Authenticate container hdr failed, return %d, resp 0x%x\n", err, resp); @@ -282,7 +281,7 @@ int ahab_auth_release(void) int err; u32 resp; - err = ahab_release_container(&resp); + err = ele_release_container(&resp); if (err) { printf("Error: release container failed, resp 0x%x!\n", resp); display_ahab_auth_ind(resp); @@ -296,7 +295,7 @@ int ahab_verify_cntr_image(struct boot_img_t *img, int image_index) int err; u32 resp; - err = ahab_verify_image(image_index, &resp); + err = ele_verify_image(image_index, &resp); if (err) { printf("Authenticate img %d failed, return %d, resp 0x%x\n", image_index, err, resp); @@ -403,7 +402,7 @@ static int do_authenticate(struct cmd_tbl *cmdtp, int flag, int argc, if (argc < 2) return CMD_RET_USAGE; - addr = simple_strtoul(argv[1], NULL, 16); + addr = hextoul(argv[1], NULL); printf("Authenticate OS container at 0x%lx\n", addr); @@ -485,7 +484,7 @@ static int do_ahab_close(struct cmd_tbl *cmdtp, int flag, int argc, return -EPERM; } - err = ahab_forward_lifecycle(8, &resp); + err = ele_forward_lifecycle(8, &resp); if (err != 0) { printf("Error in forward lifecycle to OEM closed\n"); return -EIO; @@ -502,7 +501,7 @@ int ahab_dump(void) int ret, i = 0; do { - ret = ahab_dump_buffer(buffer, 32); + ret = ele_dump_buffer(buffer, 32); if (ret < 0) { printf("Error in dump AHAB log\n"); return -EIO; @@ -547,7 +546,7 @@ static int do_ahab_status(struct cmd_tbl *cmdtp, int flag, int argc, char *const display_life_cycle(lc); - ret = ahab_get_events(events, &cnt, NULL); + ret = ele_get_events(events, &cnt, NULL); if (ret) { printf("Get ELE EVENTS error %d\n", ret); return CMD_RET_FAILURE; @@ -564,6 +563,68 @@ static int do_ahab_status(struct cmd_tbl *cmdtp, int flag, int argc, char *const return 0; } +static int do_sec_fuse_prog(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) +{ + ulong addr; + u32 header, response; + + if (argc < 2) + return CMD_RET_USAGE; + + addr = hextoul(argv[1], NULL); + header = *(u32 *)addr; + + if ((header & 0xff0000ff) != 0x89000000) { + printf("Wrong Signed message block format, header 0x%x\n", header); + return CMD_RET_FAILURE; + } + + header = (header & 0xffff00) >> 8; + + printf("Signed Message block at 0x%lx, size 0x%x\n", addr, header); + flush_dcache_range(addr, addr + header - 1); + + if (ele_write_secure_fuse(addr, &response)) { + printf("Program secure fuse failed, response 0x%x\n", response); + return CMD_RET_FAILURE; + } + + printf("Program secure fuse completed, response 0x%x\n", response); + + return CMD_RET_SUCCESS; +} + +static int do_ahab_return_lifecycle(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) +{ + ulong addr; + u32 header, response; + + if (argc < 2) + return CMD_RET_USAGE; + + addr = hextoul(argv[1], NULL); + header = *(u32 *)addr; + + if ((header & 0xff0000ff) != 0x89000000) { + printf("Wrong Signed message block format, header 0x%x\n", header); + return CMD_RET_FAILURE; + } + + header = (header & 0xffff00) >> 8; + + printf("Signed Message block at 0x%lx, size 0x%x\n", addr, header); + flush_dcache_range(addr, addr + header - 1); + + if (ele_return_lifecycle_update(addr, &response)) { + printf("Return lifecycle failed, response 0x%x\n", response); + return CMD_RET_FAILURE; + } + + printf("Return lifecycle completed, response 0x%x\n", response); + + return CMD_RET_SUCCESS; +} + U_BOOT_CMD(auth_cntr, CONFIG_SYS_MAXARGS, 1, do_authenticate, "autenticate OS container via AHAB", "addr\n" @@ -584,3 +645,15 @@ U_BOOT_CMD(ahab_status, CONFIG_SYS_MAXARGS, 1, do_ahab_status, "display AHAB lifecycle only", "" ); + +U_BOOT_CMD(ahab_sec_fuse_prog, CONFIG_SYS_MAXARGS, 1, do_sec_fuse_prog, + "Program secure fuse via signed message block", + "addr\n" + "addr - Signed message block for secure fuse\n" +); + +U_BOOT_CMD(ahab_return_lifecycle, CONFIG_SYS_MAXARGS, 1, do_ahab_return_lifecycle, + "Return lifecycle to OEM field return via signed message block", + "addr\n" + "addr - Return lifecycle message block signed by OEM SRK\n" +); diff --git a/arch/arm/mach-imx/hab.c b/arch/arm/mach-imx/hab.c index 439cdaf07a7..b3ef36c7973 100644 --- a/arch/arm/mach-imx/hab.c +++ b/arch/arm/mach-imx/hab.c @@ -289,9 +289,10 @@ static char *rsn_str[] = { }; static char *sts_str[] = { - "STS = HAB_SUCCESS (0xF0)\n", + "STS = HAB_STS_ANY (0x00)\n", "STS = HAB_FAILURE (0x33)\n", "STS = HAB_WARNING (0x69)\n", + "STS = HAB_SUCCESS (0xF0)\n", "STS = INVALID\n", NULL }; @@ -336,8 +337,7 @@ static uint8_t hab_statuses[5] = { HAB_STS_ANY, HAB_FAILURE, HAB_WARNING, - HAB_SUCCESS, - -1 + HAB_SUCCESS }; static uint8_t hab_reasons[26] = { @@ -365,8 +365,7 @@ static uint8_t hab_reasons[26] = { HAB_UNS_ITEM, HAB_UNS_KEY, HAB_UNS_PROTOCOL, - HAB_UNS_STATE, - -1 + HAB_UNS_STATE }; static uint8_t hab_contexts[12] = { @@ -380,8 +379,7 @@ static uint8_t hab_contexts[12] = { HAB_CTX_COMMAND, HAB_CTX_AUT_DAT, HAB_CTX_ASSERT, - HAB_CTX_EXIT, - -1 + HAB_CTX_EXIT }; static uint8_t hab_engines[16] = { @@ -399,30 +397,35 @@ static uint8_t hab_engines[16] = { HAB_ENG_ROM, HAB_ENG_HDCP, HAB_ENG_RTL, - HAB_ENG_SW, - -1 + HAB_ENG_SW }; -static inline uint8_t get_idx(uint8_t *list, uint8_t tgt) +static inline u32 get_idx(u8 *list, u8 tgt, u32 size) { - uint8_t idx = 0; - uint8_t element = list[idx]; - while (element != -1) { + u32 idx = 0; + u8 element; + + while (idx < size) { + element = list[idx]; if (element == tgt) return idx; - element = list[++idx]; + ++idx; } - return -1; + return idx; } static void process_event_record(uint8_t *event_data, size_t bytes) { struct record *rec = (struct record *)event_data; - printf("\n\n%s", sts_str[get_idx(hab_statuses, rec->contents[0])]); - printf("%s", rsn_str[get_idx(hab_reasons, rec->contents[1])]); - printf("%s", ctx_str[get_idx(hab_contexts, rec->contents[2])]); - printf("%s", eng_str[get_idx(hab_engines, rec->contents[3])]); + printf("\n\n%s", sts_str[get_idx(hab_statuses, rec->contents[0], + ARRAY_SIZE(hab_statuses))]); + printf("%s", rsn_str[get_idx(hab_reasons, rec->contents[1], + ARRAY_SIZE(hab_reasons))]); + printf("%s", ctx_str[get_idx(hab_contexts, rec->contents[2], + ARRAY_SIZE(hab_contexts))]); + printf("%s", eng_str[get_idx(hab_engines, rec->contents[3], + ARRAY_SIZE(hab_engines))]); } static void display_event(uint8_t *event_data, size_t bytes) diff --git a/arch/arm/mach-imx/image-container.c b/arch/arm/mach-imx/image-container.c index 5b059a64292..5f188ab32d1 100644 --- a/arch/arm/mach-imx/image-container.c +++ b/arch/arm/mach-imx/image-container.c @@ -22,6 +22,25 @@ #define QSPI_NOR_DEV 3 #define ROM_API_DEV 4 +/* The unit of second image offset number which provision by the fuse bits */ +#define SND_IMG_OFF_UNIT (0x100000UL) + +/* + * If num = 0, off = (2 ^ 2) * 1MB + * else If num = 2, off = (2 ^ 0) * 1MB + * else off = (2 ^ num) * 1MB + */ +#define SND_IMG_NUM_TO_OFF(num) \ + ((1UL << ((0 == (num)) ? 2 : (2 == (num)) ? 0 : (num))) * SND_IMG_OFF_UNIT) + +#define GET_SND_IMG_NUM(fuse) (((fuse) >> 24) & 0x1F) + +#if defined(CONFIG_IMX8QM) +#define FUSE_IMG_SET_OFF_WORD 464 +#elif defined(CONFIG_IMX8QXP) +#define FUSE_IMG_SET_OFF_WORD 720 +#endif + int get_container_size(ulong addr, u16 *header_length) { struct container_hdr *phdr; @@ -31,7 +50,7 @@ int get_container_size(ulong addr, u16 *header_length) u32 max_offset = 0, img_end; phdr = (struct container_hdr *)addr; - if (phdr->tag != 0x87 && phdr->version != 0x0) { + if (phdr->tag != 0x87 || phdr->version != 0x0) { debug("Wrong container header\n"); return -EFAULT; } @@ -136,15 +155,53 @@ static int get_dev_container_size(void *dev, int dev_type, unsigned long offset, return ret; } +static bool check_secondary_cnt_set(unsigned long *set_off) +{ +#if IS_ENABLED(CONFIG_ARCH_IMX8) + int ret; + u8 set_id = 1; + u32 fuse_val = 0; + + if (!(is_imx8qxp() && is_soc_rev(CHIP_REV_B))) { + ret = sc_misc_get_boot_container(-1, &set_id); + if (ret) + return false; + /* Secondary boot */ + if (set_id == 2) { + ret = sc_misc_otp_fuse_read(-1, FUSE_IMG_SET_OFF_WORD, &fuse_val); + if (!ret) { + if (set_off) + *set_off = SND_IMG_NUM_TO_OFF(GET_SND_IMG_NUM(fuse_val)); + return true; + } + } + } +#endif + + return false; +} + static unsigned long get_boot_device_offset(void *dev, int dev_type) { - unsigned long offset = 0; + unsigned long offset = 0, sec_set_off = 0; + bool sec_boot = false; + + if (dev_type == ROM_API_DEV) { + offset = (unsigned long)dev; + return offset; + } + + sec_boot = check_secondary_cnt_set(&sec_set_off); + if (sec_boot) + printf("Secondary set selected\n"); + else + printf("Primary set selected\n"); if (dev_type == MMC_DEV) { struct mmc *mmc = (struct mmc *)dev; if (IS_SD(mmc) || mmc->part_config == MMCPART_NOAVAILABLE) { - offset = CONTAINER_HDR_MMCSD_OFFSET; + offset = sec_boot ? sec_set_off : CONTAINER_HDR_MMCSD_OFFSET; } else { u8 part = EXT_CSD_EXTRACT_BOOT_PART(mmc->part_config); @@ -154,19 +211,23 @@ static unsigned long get_boot_device_offset(void *dev, int dev_type) else offset = CONTAINER_HDR_EMMC_OFFSET; } else { - offset = CONTAINER_HDR_MMCSD_OFFSET; + offset = sec_boot ? sec_set_off : CONTAINER_HDR_MMCSD_OFFSET; } } } else if (dev_type == QSPI_DEV) { - offset = CONTAINER_HDR_QSPI_OFFSET; + offset = sec_boot ? (sec_set_off + CONTAINER_HDR_QSPI_OFFSET) : + CONTAINER_HDR_QSPI_OFFSET; } else if (dev_type == NAND_DEV) { - offset = CONTAINER_HDR_NAND_OFFSET; + offset = sec_boot ? (sec_set_off + CONTAINER_HDR_NAND_OFFSET) : + CONTAINER_HDR_NAND_OFFSET; } else if (dev_type == QSPI_NOR_DEV) { offset = CONTAINER_HDR_QSPI_OFFSET + 0x08000000; - } else if (dev_type == ROM_API_DEV) { - offset = (unsigned long)dev; + } else { + printf("Not supported dev_type: %d\n", dev_type); } + debug("container set offset 0x%lx\n", offset); + return offset; } @@ -227,6 +288,25 @@ unsigned long spl_mmc_get_uboot_raw_sector(struct mmc *mmc, return end / mmc->read_bl_len; } + +int spl_mmc_emmc_boot_partition(struct mmc *mmc) +{ + int part; + + part = EXT_CSD_EXTRACT_BOOT_PART(mmc->part_config); + if (part == 1 || part == 2) { + unsigned long sec_set_off = 0; + bool sec_boot = false; + + sec_boot = check_secondary_cnt_set(&sec_set_off); + if (sec_boot) + part = (part == 1) ? 2 : 1; + } else if (part == 7) { + part = 0; + } + + return part; +} #endif #ifdef CONFIG_SPL_NAND_SUPPORT diff --git a/arch/arm/mach-imx/imx8/ahab.c b/arch/arm/mach-imx/imx8/ahab.c index 9addb824b6d..b58b14ca9b4 100644 --- a/arch/arm/mach-imx/imx8/ahab.c +++ b/arch/arm/mach-imx/imx8/ahab.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Copyright 2018-2019 NXP + * Copyright 2018-2019, 2022 NXP */ #include <common.h> @@ -16,6 +16,8 @@ #include <asm/mach-imx/image.h> #include <console.h> #include <cpu_func.h> +#include "u-boot/sha256.h" +#include <asm/mach-imx/ahab.h> DECLARE_GLOBAL_DATA_PTR; @@ -24,6 +26,86 @@ DECLARE_GLOBAL_DATA_PTR; #define SECO_LOCAL_SEC_SEC_SECURE_RAM_BASE (0x60000000UL) #define SECO_PT 2U +#define AHAB_HASH_TYPE_MASK 0x00000700 +#define AHAB_HASH_TYPE_SHA256 0 + +int ahab_auth_cntr_hdr(struct container_hdr *container, u16 length) +{ + int err; + + memcpy((void *)SEC_SECURE_RAM_BASE, (const void *)container, + ALIGN(length, CONFIG_SYS_CACHELINE_SIZE)); + + err = sc_seco_authenticate(-1, SC_SECO_AUTH_CONTAINER, + SECO_LOCAL_SEC_SEC_SECURE_RAM_BASE); + if (err) + printf("Authenticate container hdr failed, return %d\n", err); + + return err; +} + +int ahab_auth_release(void) +{ + int err; + + err = sc_seco_authenticate(-1, SC_SECO_REL_CONTAINER, 0); + if (err) + printf("Error: release container failed!\n"); + + return err; +} + +int ahab_verify_cntr_image(struct boot_img_t *img, int image_index) +{ + sc_faddr_t start, end; + sc_rm_mr_t mr; + int err; + int ret = 0; + + debug("img %d, dst 0x%llx, src 0x%x, size 0x%x\n", + image_index, img->dst, img->offset, img->size); + + /* Find the memreg and set permission for seco pt */ + err = sc_rm_find_memreg(-1, &mr, + img->dst & ~(CONFIG_SYS_CACHELINE_SIZE - 1), + ALIGN(img->dst + img->size, CONFIG_SYS_CACHELINE_SIZE) - 1); + + if (err) { + printf("Error: can't find memreg for image load address 0x%llx, error %d\n", + img->dst, err); + return -ENOMEM; + } + + err = sc_rm_get_memreg_info(-1, mr, &start, &end); + if (!err) + debug("memreg %u 0x%llx -- 0x%llx\n", mr, start, end); + + err = sc_rm_set_memreg_permissions(-1, mr, + SECO_PT, SC_RM_PERM_FULL); + if (err) { + printf("Set permission failed for img %d, error %d\n", + image_index, err); + return -EPERM; + } + + err = sc_seco_authenticate(-1, SC_SECO_VERIFY_IMAGE, + 1 << image_index); + if (err) { + printf("Authenticate img %d failed, return %d\n", + image_index, err); + ret = -EIO; + } + + err = sc_rm_set_memreg_permissions(-1, mr, + SECO_PT, SC_RM_PERM_NONE); + if (err) { + printf("Remove permission failed for img %d, error %d\n", + image_index, err); + ret = -EPERM; + } + + return ret; +} static inline bool check_in_dram(ulong addr) { @@ -46,11 +128,12 @@ int authenticate_os_container(ulong addr) struct container_hdr *phdr; int i, ret = 0; int err; - sc_rm_mr_t mr; - sc_faddr_t start, end; u16 length; struct boot_img_t *img; unsigned long s, e; +#ifdef CONFIG_ARMV8_CE_SHA256 + u8 hash_value[SHA256_SUM_LEN]; +#endif if (addr % 4) { puts("Error: Image's address is not 4 byte aligned\n"); @@ -76,14 +159,9 @@ int authenticate_os_container(ulong addr) length = phdr->length_lsb + (phdr->length_msb << 8); debug("container length %u\n", length); - memcpy((void *)SEC_SECURE_RAM_BASE, (const void *)addr, - ALIGN(length, CONFIG_SYS_CACHELINE_SIZE)); - err = sc_seco_authenticate(-1, SC_SECO_AUTH_CONTAINER, - SECO_LOCAL_SEC_SEC_SECURE_RAM_BASE); + err = ahab_auth_cntr_hdr(phdr, length); if (err) { - printf("Authenticate container hdr failed, return %d\n", - err); ret = -EIO; goto exit; } @@ -105,50 +183,27 @@ int authenticate_os_container(ulong addr) flush_dcache_range(s, e); - /* Find the memreg and set permission for seco pt */ - err = sc_rm_find_memreg(-1, &mr, s, e); - if (err) { - printf("Error: can't find memreg for image load address 0x%llx, error %d\n", img->dst, err); - ret = -ENOMEM; - goto exit; - } - - err = sc_rm_get_memreg_info(-1, mr, &start, &end); - if (!err) - debug("memreg %u 0x%llx -- 0x%llx\n", mr, start, end); - - err = sc_rm_set_memreg_permissions(-1, mr, SECO_PT, - SC_RM_PERM_FULL); - if (err) { - printf("Set permission failed for img %d, error %d\n", - i, err); - ret = -EPERM; - goto exit; - } - - err = sc_seco_authenticate(-1, SC_SECO_VERIFY_IMAGE, - (1 << i)); - if (err) { - printf("Authenticate img %d failed, return %d\n", - i, err); - ret = -EIO; +#ifdef CONFIG_ARMV8_CE_SHA256 + if (((img->hab_flags & AHAB_HASH_TYPE_MASK) >> 8) == AHAB_HASH_TYPE_SHA256) { + sha256_csum_wd((void *)img->dst, img->size, hash_value, CHUNKSZ_SHA256); + err = memcmp(&img->hash, &hash_value, SHA256_SUM_LEN); + if (err) { + printf("img %d hash comparison failed, error %d\n", i, err); + ret = -EIO; + goto exit; + } + } else { +#endif + ret = ahab_verify_cntr_image(img, i); + if (ret) + goto exit; +#ifdef CONFIG_ARMV8_CE_SHA256 } - - err = sc_rm_set_memreg_permissions(-1, mr, SECO_PT, - SC_RM_PERM_NONE); - if (err) { - printf("Remove permission failed for img %d, err %d\n", - i, err); - ret = -EPERM; - } - - if (ret) - goto exit; +#endif } exit: - if (sc_seco_authenticate(-1, SC_SECO_REL_CONTAINER, 0) != SC_ERR_NONE) - printf("Error: release container failed!\n"); + ahab_auth_release(); return ret; } @@ -263,7 +318,7 @@ static int do_ahab_status(struct cmd_tbl *cmdtp, int flag, int argc, u16 lc; err = sc_seco_chip_info(-1, &lc, NULL, NULL, NULL); - if (err != SC_ERR_NONE) { + if (err) { printf("Error in get lifecycle\n"); return -EIO; } @@ -271,7 +326,7 @@ static int do_ahab_status(struct cmd_tbl *cmdtp, int flag, int argc, display_life_cycle(lc); err = sc_seco_get_event(-1, idx, &event); - while (err == SC_ERR_NONE) { + while (!err) { printf("SECO Event[%u] = 0x%08X\n", idx, event); display_ahab_auth_event(event); @@ -312,7 +367,7 @@ static int do_ahab_close(struct cmd_tbl *cmdtp, int flag, int argc, return -EACCES; err = sc_seco_chip_info(-1, &lc, NULL, NULL, NULL); - if (err != SC_ERR_NONE) { + if (err) { printf("Error in get lifecycle\n"); return -EIO; } @@ -324,7 +379,7 @@ static int do_ahab_close(struct cmd_tbl *cmdtp, int flag, int argc, } err = sc_seco_forward_lifecycle(-1, 16); - if (err != SC_ERR_NONE) { + if (err) { printf("Error in forward lifecycle to OEM closed\n"); return -EIO; } diff --git a/arch/arm/mach-imx/imx8/cpu.c b/arch/arm/mach-imx/imx8/cpu.c index 7b292c07ef9..c62357044e0 100644 --- a/arch/arm/mach-imx/imx8/cpu.c +++ b/arch/arm/mach-imx/imx8/cpu.c @@ -26,6 +26,8 @@ #include <asm/armv8/mmu.h> #include <asm/setup.h> #include <asm/mach-imx/boot_mode.h> +#include <power-domain.h> +#include <elf.h> #include <spl.h> DECLARE_GLOBAL_DATA_PTR; @@ -107,6 +109,178 @@ int arch_misc_init(void) } #endif +#ifdef CONFIG_IMX_BOOTAUX + +#ifdef CONFIG_IMX8QM +int arch_auxiliary_core_up(u32 core_id, ulong boot_private_data) +{ + sc_rsrc_t core_rsrc, mu_rsrc; + sc_faddr_t tcml_addr; + u32 tcml_size = SZ_128K; + ulong addr; + + switch (core_id) { + case 0: + core_rsrc = SC_R_M4_0_PID0; + tcml_addr = 0x34FE0000; + mu_rsrc = SC_R_M4_0_MU_1A; + break; + case 1: + core_rsrc = SC_R_M4_1_PID0; + tcml_addr = 0x38FE0000; + mu_rsrc = SC_R_M4_1_MU_1A; + break; + default: + printf("Not support this core boot up, ID:%u\n", core_id); + return -EINVAL; + } + + addr = (sc_faddr_t)boot_private_data; + + if (addr >= tcml_addr && addr <= tcml_addr + tcml_size) { + printf("Wrong image address 0x%lx, should not in TCML\n", + addr); + return -EINVAL; + } + + printf("Power on M4 and MU\n"); + + if (sc_pm_set_resource_power_mode(-1, core_rsrc, SC_PM_PW_MODE_ON) != SC_ERR_NONE) + return -EIO; + + if (sc_pm_set_resource_power_mode(-1, mu_rsrc, SC_PM_PW_MODE_ON) != SC_ERR_NONE) + return -EIO; + + printf("Copy M4 image from 0x%lx to TCML 0x%lx\n", addr, (ulong)tcml_addr); + + if (addr != tcml_addr) + memcpy((void *)tcml_addr, (void *)addr, tcml_size); + + printf("Start M4 %u\n", core_id); + if (sc_pm_cpu_start(-1, core_rsrc, true, tcml_addr) != SC_ERR_NONE) + return -EIO; + + printf("bootaux complete\n"); + return 0; +} +#endif + +#ifdef CONFIG_IMX8QXP +int arch_auxiliary_core_up(u32 core_id, ulong boot_private_data) +{ + sc_rsrc_t core_rsrc, mu_rsrc = SC_R_NONE; + sc_faddr_t aux_core_ram; + u32 size; + ulong addr; + + switch (core_id) { + case 0: + core_rsrc = SC_R_M4_0_PID0; + aux_core_ram = 0x34FE0000; + mu_rsrc = SC_R_M4_0_MU_1A; + size = SZ_128K; + break; + case 1: + core_rsrc = SC_R_DSP; + aux_core_ram = 0x596f8000; + size = SZ_2K; + break; + default: + printf("Not support this core boot up, ID:%u\n", core_id); + return -EINVAL; + } + + addr = (sc_faddr_t)boot_private_data; + + if (addr >= aux_core_ram && addr <= aux_core_ram + size) { + printf("Wrong image address 0x%lx, should not in aux core ram\n", + addr); + return -EINVAL; + } + + printf("Power on aux core %d\n", core_id); + + if (sc_pm_set_resource_power_mode(-1, core_rsrc, SC_PM_PW_MODE_ON) != SC_ERR_NONE) + return -EIO; + + if (mu_rsrc != SC_R_NONE) { + if (sc_pm_set_resource_power_mode(-1, mu_rsrc, SC_PM_PW_MODE_ON) != SC_ERR_NONE) + return -EIO; + } + + if (core_id == 1) { + struct power_domain pd; + + if (sc_pm_clock_enable(-1, core_rsrc, SC_PM_CLK_PER, true, false) != SC_ERR_NONE) { + printf("Error enable clock\n"); + return -EIO; + } + + if (!power_domain_lookup_name("audio_sai0", &pd)) { + if (power_domain_on(&pd)) { + printf("Error power on SAI0\n"); + return -EIO; + } + } + + if (!power_domain_lookup_name("audio_ocram", &pd)) { + if (power_domain_on(&pd)) { + printf("Error power on HIFI RAM\n"); + return -EIO; + } + } + } + + printf("Copy image from 0x%lx to 0x%lx\n", addr, (ulong)aux_core_ram); + if (core_id == 0) { + /* M4 use bin file */ + memcpy((void *)aux_core_ram, (void *)addr, size); + } else { + /* HIFI use elf file */ + if (!valid_elf_image(addr)) + return -1; + addr = load_elf_image_shdr(addr); + } + + printf("Start %s\n", core_id == 0 ? "M4" : "HIFI"); + + if (sc_pm_cpu_start(-1, core_rsrc, true, aux_core_ram) != SC_ERR_NONE) + return -EIO; + + printf("bootaux complete\n"); + return 0; +} +#endif + +int arch_auxiliary_core_check_up(u32 core_id) +{ + sc_rsrc_t core_rsrc; + sc_pm_power_mode_t power_mode; + + switch (core_id) { + case 0: + core_rsrc = SC_R_M4_0_PID0; + break; +#ifdef CONFIG_IMX8QM + case 1: + core_rsrc = SC_R_M4_1_PID0; + break; +#endif + default: + printf("Not support this core, ID:%u\n", core_id); + return 0; + } + + if (sc_pm_get_resource_power_mode(-1, core_rsrc, &power_mode) != SC_ERR_NONE) + return 0; + + if (power_mode != SC_PM_PW_MODE_OFF) + return 1; + + return 0; +} +#endif + int print_bootinfo(void) { enum boot_device bt_dev = get_boot_device(); @@ -195,7 +369,7 @@ enum boot_device get_boot_device(void) #define FUSE_UNIQUE_ID_WORD1 17 void get_board_serial(struct tag_serialnr *serialnr) { - sc_err_t err; + int err; u32 val1 = 0, val2 = 0; u32 word1, word2; @@ -206,13 +380,13 @@ void get_board_serial(struct tag_serialnr *serialnr) word2 = FUSE_UNIQUE_ID_WORD1; err = sc_misc_otp_fuse_read(-1, word1, &val1); - if (err != SC_ERR_NONE) { + if (err) { printf("%s fuse %d read error: %d\n", __func__, word1, err); return; } err = sc_misc_otp_fuse_read(-1, word2, &val2); - if (err != SC_ERR_NONE) { + if (err) { printf("%s fuse %d read error: %d\n", __func__, word2, err); return; } diff --git a/arch/arm/mach-imx/imx8/fdt.c b/arch/arm/mach-imx/imx8/fdt.c index 02b3ee5c111..491c8bb8c75 100644 --- a/arch/arm/mach-imx/imx8/fdt.c +++ b/arch/arm/mach-imx/imx8/fdt.c @@ -110,7 +110,7 @@ static int config_smmu_resource_sid(int rsrc, int sid) err = sc_rm_set_master_sid(-1, rsrc, sid); debug("set_master_sid rsrc=%d sid=0x%x err=%d\n", rsrc, sid, err); - if (err != SC_ERR_NONE) { + if (err) { if (!check_owned_resource(rsrc)) { printf("%s rsrc[%d] not owned\n", __func__, rsrc); return -1; diff --git a/arch/arm/mach-imx/imx8/snvs_security_sc.c b/arch/arm/mach-imx/imx8/snvs_security_sc.c index d7b20a1fcbf..1eaa68f8d5f 100644 --- a/arch/arm/mach-imx/imx8/snvs_security_sc.c +++ b/arch/arm/mach-imx/imx8/snvs_security_sc.c @@ -286,16 +286,15 @@ static int check_write_secvio_config(u32 id, u32 *_p1, u32 *_p2, u32 *_p3, u32 *_p4, u32 *_p5, u32 _cnt) { - int scierr = 0; + int err; u32 d1 = ptr_value(_p1); u32 d2 = ptr_value(_p2); u32 d3 = ptr_value(_p3); u32 d4 = ptr_value(_p4); u32 d5 = ptr_value(_p5); - scierr = sc_seco_secvio_config(-1, id, SC_WRITE_CONF, &d1, &d2, &d3, - &d4, &d4, _cnt); - if (scierr != SC_ERR_NONE) { + err = sc_seco_secvio_config(-1, id, SC_WRITE_CONF, &d1, &d2, &d3, &d4, &d4, _cnt); + if (err) { printf("Failed to set secvio configuration\n"); debug("Failed to set conf id 0x%x with values ", id); debug("0x%.8x 0x%.8x 0x%.8x 0x%.8x 0x%.8x (cnt: %d)\n", @@ -315,7 +314,7 @@ static int check_write_secvio_config(u32 id, u32 *_p1, u32 *_p2, *(u32 *)_p5 = d5; exit: - return scierr; + return err; } #define SC_CHECK_WRITE1(id, _p1) \ @@ -323,7 +322,7 @@ exit: static int apply_snvs_config(struct snvs_security_sc_conf *cnf) { - int scierr = 0; + int err = 0; debug("%s\n", __func__); @@ -365,92 +364,88 @@ static int apply_snvs_config(struct snvs_security_sc_conf *cnf) cnf->lp.act_tamper_routing_ctl1, cnf->lp.act_tamper_routing_ctl2); - scierr = check_write_secvio_config(SC_CONF_OFFSET_OF(lp.tamper_filt_cfg), - &cnf->lp.tamper_filt_cfg, - &cnf->lp.tamper_filt1_cfg, - &cnf->lp.tamper_filt2_cfg, NULL, - NULL, 3); - if (scierr != SC_ERR_NONE) + err = check_write_secvio_config(SC_CONF_OFFSET_OF(lp.tamper_filt_cfg), + &cnf->lp.tamper_filt_cfg, + &cnf->lp.tamper_filt1_cfg, + &cnf->lp.tamper_filt2_cfg, + NULL, NULL, 3); + if (err) goto exit; /* Configure AT */ - scierr = check_write_secvio_config(SC_CONF_OFFSET_OF(lp.act_tamper1_cfg), - &cnf->lp.act_tamper1_cfg, - &cnf->lp.act_tamper2_cfg, - &cnf->lp.act_tamper2_cfg, - &cnf->lp.act_tamper2_cfg, - &cnf->lp.act_tamper2_cfg, 5); - if (scierr != SC_ERR_NONE) + err = check_write_secvio_config(SC_CONF_OFFSET_OF(lp.act_tamper1_cfg), + &cnf->lp.act_tamper1_cfg, + &cnf->lp.act_tamper2_cfg, + &cnf->lp.act_tamper2_cfg, + &cnf->lp.act_tamper2_cfg, + &cnf->lp.act_tamper2_cfg, 5); + if (err) goto exit; /* Configure AT routing */ - scierr = check_write_secvio_config(SC_CONF_OFFSET_OF(lp.act_tamper_routing_ctl1), - &cnf->lp.act_tamper_routing_ctl1, - &cnf->lp.act_tamper_routing_ctl2, - NULL, NULL, NULL, 2); - if (scierr != SC_ERR_NONE) + err = check_write_secvio_config(SC_CONF_OFFSET_OF(lp.act_tamper_routing_ctl1), + &cnf->lp.act_tamper_routing_ctl1, + &cnf->lp.act_tamper_routing_ctl2, + NULL, NULL, NULL, 2); + if (err) goto exit; /* Configure AT frequency */ - scierr = SC_CHECK_WRITE1(SC_CONF_OFFSET_OF(lp.act_tamper_clk_ctl), - &cnf->lp.act_tamper_clk_ctl); - if (scierr != SC_ERR_NONE) + err = SC_CHECK_WRITE1(SC_CONF_OFFSET_OF(lp.act_tamper_clk_ctl), + &cnf->lp.act_tamper_clk_ctl); + if (err) goto exit; /* Activate the ATs */ - scierr = SC_CHECK_WRITE1(SC_CONF_OFFSET_OF(lp.act_tamper_ctl), - &cnf->lp.act_tamper_ctl); - if (scierr != SC_ERR_NONE) + err = SC_CHECK_WRITE1(SC_CONF_OFFSET_OF(lp.act_tamper_ctl), &cnf->lp.act_tamper_ctl); + if (err) goto exit; /* Activate the detectors */ - scierr = check_write_secvio_config(SC_CONF_OFFSET_OF(lp.tamper_det_cfg), - &cnf->lp.tamper_det_cfg, - &cnf->lp.tamper_det_cfg2, NULL, NULL, - NULL, 2); - if (scierr != SC_ERR_NONE) + err = check_write_secvio_config(SC_CONF_OFFSET_OF(lp.tamper_det_cfg), + &cnf->lp.tamper_det_cfg, + &cnf->lp.tamper_det_cfg2, NULL, NULL, NULL, 2); + if (err) goto exit; /* Configure LP secvio */ - scierr = SC_CHECK_WRITE1(SC_CONF_OFFSET_OF(lp.secvio_ctl), - &cnf->lp.secvio_ctl); - if (scierr != SC_ERR_NONE) + err = SC_CHECK_WRITE1(SC_CONF_OFFSET_OF(lp.secvio_ctl), &cnf->lp.secvio_ctl); + if (err) goto exit; /* Configure HP secvio */ - scierr = SC_CHECK_WRITE1(SC_CONF_OFFSET_OF(hp.secvio_ctl), - &cnf->hp.secvio_ctl); - if (scierr != SC_ERR_NONE) + err = SC_CHECK_WRITE1(SC_CONF_OFFSET_OF(hp.secvio_ctl), &cnf->hp.secvio_ctl); + if (err) goto exit; /* Lock access */ - scierr = SC_CHECK_WRITE1(SC_CONF_OFFSET_OF(hp.lock), &cnf->hp.lock); - if (scierr != SC_ERR_NONE) + err = SC_CHECK_WRITE1(SC_CONF_OFFSET_OF(hp.lock), &cnf->hp.lock); + if (err) goto exit; - scierr = SC_CHECK_WRITE1(SC_CONF_OFFSET_OF(lp.lock), &cnf->lp.lock); - if (scierr != SC_ERR_NONE) + err = SC_CHECK_WRITE1(SC_CONF_OFFSET_OF(lp.lock), &cnf->lp.lock); + if (err) goto exit; exit: - return (scierr == SC_ERR_NONE) ? 0 : -EIO; + return err; } static int dgo_write(u32 _id, u8 _access, u32 *_pdata) { - int scierr = sc_seco_secvio_dgo_config(-1, _id, _access, _pdata); + int err = sc_seco_secvio_dgo_config(-1, _id, _access, _pdata); - if (scierr != SC_ERR_NONE) { + if (err) { printf("Failed to set dgo configuration\n"); debug("Failed to set conf id 0x%x : 0x%.8x", _id, *_pdata); } - return scierr; + return err; } static int apply_snvs_dgo_config(struct snvs_dgo_conf *cnf) { - int scierr = 0; + int err; debug("%s\n", __func__); @@ -468,50 +463,50 @@ static int apply_snvs_dgo_config(struct snvs_dgo_conf *cnf) cnf->tamper_misc_ctl, cnf->tamper_core_volt_mon_ctl); - dgo_write(0x04, 1, &cnf->tamper_offset_ctl); - if (scierr != SC_ERR_NONE) + err = dgo_write(0x04, 1, &cnf->tamper_offset_ctl); + if (err) goto exit; - dgo_write(0x14, 1, &cnf->tamper_pull_ctl); - if (scierr != SC_ERR_NONE) + err = dgo_write(0x14, 1, &cnf->tamper_pull_ctl); + if (err) goto exit; - dgo_write(0x24, 1, &cnf->tamper_ana_test_ctl); - if (scierr != SC_ERR_NONE) + err = dgo_write(0x24, 1, &cnf->tamper_ana_test_ctl); + if (err) goto exit; - dgo_write(0x34, 1, &cnf->tamper_sensor_trim_ctl); - if (scierr != SC_ERR_NONE) + err = dgo_write(0x34, 1, &cnf->tamper_sensor_trim_ctl); + if (err) goto exit; - dgo_write(0x54, 1, &cnf->tamper_core_volt_mon_ctl); - if (scierr != SC_ERR_NONE) + err = dgo_write(0x54, 1, &cnf->tamper_core_volt_mon_ctl); + if (err) goto exit; /* Last as it could lock the writes */ - dgo_write(0x44, 1, &cnf->tamper_misc_ctl); - if (scierr != SC_ERR_NONE) + err = dgo_write(0x44, 1, &cnf->tamper_misc_ctl); + if (err) goto exit; exit: - return (scierr == SC_ERR_NONE) ? 0 : -EIO; + return err; } static int pad_write(u32 _pad, u32 _value) { - int scierr = sc_pad_set(-1, _pad, _value); + int err = sc_pad_set(-1, _pad, _value); - if (scierr != SC_ERR_NONE) { + if (err) { printf("Failed to set pad configuration\n"); debug("Failed to set conf pad 0x%x : 0x%.8x", _pad, _value); } - return scierr; + return err; } static int apply_tamper_pin_list_config(struct tamper_pin_cfg *confs, u32 size) { - int scierr = 0; + int err = 0; u32 idx; debug("%s\n", __func__); @@ -519,13 +514,13 @@ static int apply_tamper_pin_list_config(struct tamper_pin_cfg *confs, u32 size) for (idx = 0; idx < size; idx++) { debug("\t idx %d: pad %d: 0x%.8x\n", idx, confs[idx].pad, confs[idx].mux_conf); - pad_write(confs[idx].pad, 3 << 30 | confs[idx].mux_conf); - if (scierr != SC_ERR_NONE) + err = pad_write(confs[idx].pad, 3 << 30 | confs[idx].mux_conf); + if (err) goto exit; } exit: - return (scierr == SC_ERR_NONE) ? 0 : -EIO; + return err; } int examples(void) @@ -753,7 +748,7 @@ static char snvs_clear_status_help_text[] = static int do_snvs_clear_status(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { - int scierr = 0; + int err; u32 idx = 0; struct snvs_security_sc_conf conf = {0}; @@ -764,20 +759,18 @@ static int do_snvs_clear_status(struct cmd_tbl *cmdtp, int flag, int argc, conf.lp.status = hextoul(argv[++idx], NULL); conf.lp.tamper_det_status = hextoul(argv[++idx], NULL); - scierr = check_write_secvio_config(SC_CONF_OFFSET_OF(lp.status), - &conf.lp.status, NULL, NULL, NULL, - NULL, 1); - if (scierr != SC_ERR_NONE) + err = check_write_secvio_config(SC_CONF_OFFSET_OF(lp.status), + &conf.lp.status, NULL, NULL, NULL, NULL, 1); + if (err) goto exit; - scierr = check_write_secvio_config(SC_CONF_OFFSET_OF(lp.tamper_det_status), - &conf.lp.tamper_det_status, NULL, - NULL, NULL, NULL, 1); - if (scierr != SC_ERR_NONE) + err = check_write_secvio_config(SC_CONF_OFFSET_OF(lp.tamper_det_status), + &conf.lp.tamper_det_status, NULL, NULL, NULL, NULL, 1); + if (err) goto exit; exit: - return (scierr == SC_ERR_NONE) ? 0 : 1; + return err; } U_BOOT_CMD(snvs_clear_status, @@ -793,7 +786,7 @@ static char snvs_sec_status_help_text[] = static int do_snvs_sec_status(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { - int scierr; + int err; u32 idx; u32 data[5]; @@ -864,8 +857,8 @@ static int do_snvs_sec_status(struct cmd_tbl *cmdtp, int flag, int argc, for (idx = 0; idx < ARRAY_SIZE(pads); idx++) { u8 pad_id = pads[idx]; - scierr = sc_pad_get(-1, pad_id, &data[0]); - if (scierr == 0) + err = sc_pad_get(-1, pad_id, &data[0]); + if (!err) printf("\t- Pin %d: %.8x\n", pad_id, data[0]); else printf("Failed to read Pin %d\n", pad_id); @@ -876,8 +869,8 @@ static int do_snvs_sec_status(struct cmd_tbl *cmdtp, int flag, int argc, for (idx = 0; idx < ARRAY_SIZE(fuses); idx++) { u32 fuse_id = fuses[idx]; - scierr = sc_misc_otp_fuse_read(-1, fuse_id, &data[0]); - if (scierr == 0) + err = sc_misc_otp_fuse_read(-1, fuse_id, &data[0]); + if (!err) printf("\t- Fuse %d: %.8x\n", fuse_id, data[0]); else printf("Failed to read Fuse %d\n", fuse_id); @@ -888,10 +881,10 @@ static int do_snvs_sec_status(struct cmd_tbl *cmdtp, int flag, int argc, for (idx = 0; idx < ARRAY_SIZE(snvs); idx++) { struct snvs_reg *reg = &snvs[idx]; - scierr = sc_seco_secvio_config(-1, reg->id, 0, &data[0], - &data[1], &data[2], &data[3], - &data[4], reg->nb); - if (scierr == 0) { + err = sc_seco_secvio_config(-1, reg->id, 0, &data[0], + &data[1], &data[2], &data[3], + &data[4], reg->nb); + if (!err) { int subidx; printf("\t- SNVS %.2x(%d):", reg->id, reg->nb); @@ -908,8 +901,8 @@ static int do_snvs_sec_status(struct cmd_tbl *cmdtp, int flag, int argc, for (idx = 0; idx < ARRAY_SIZE(dgo); idx++) { u8 dgo_id = dgo[idx]; - scierr = sc_seco_secvio_dgo_config(-1, dgo_id, 0, &data[0]); - if (scierr == 0) + err = sc_seco_secvio_dgo_config(-1, dgo_id, 0, &data[0]); + if (!err) printf("\t- DGO %.2x: %.8x\n", dgo_id, data[0]); else printf("Failed to read DGO %d\n", dgo_id); diff --git a/arch/arm/mach-imx/imx8m/Kconfig b/arch/arm/mach-imx/imx8m/Kconfig index 7639439bdc9..3d62d7052e7 100644 --- a/arch/arm/mach-imx/imx8m/Kconfig +++ b/arch/arm/mach-imx/imx8m/Kconfig @@ -124,6 +124,9 @@ config TARGET_IMX8MM_VENICE select IMX8M_LPDDR4 select GATEWORKS_SC select MISC + select FSL_CAAM + select ARCH_MISC_INIT + select SPL_CRYPTO if SPL config TARGET_KONTRON_MX8MM bool "Kontron Electronics N80xx" @@ -175,6 +178,9 @@ config TARGET_IMX8MN_VENICE select IMX8M_LPDDR4 select GATEWORKS_SC select MISC + select FSL_CAAM + select ARCH_MISC_INIT + select SPL_CRYPTO if SPL config TARGET_IMX8MP_DATA_MODUL_EDM_SBC bool "Data Modul eDM SBC i.MX8M Plus" @@ -232,6 +238,9 @@ config TARGET_IMX8MP_VENICE select IMX8M_LPDDR4 select GATEWORKS_SC select MISC + select FSL_CAAM + select ARCH_MISC_INIT + select SPL_CRYPTO if SPL config TARGET_PICO_IMX8MQ bool "Support Technexion Pico iMX8MQ" @@ -245,6 +254,10 @@ config TARGET_IMX8MN_VAR_SOM select IMX8MN select SUPPORT_SPL select IMX8M_DDR4 + select MISC + select I2C_EEPROM + select DM_ETH_PHY + select NVMEM config TARGET_KONTRON_PITX_IMX8M bool "Support Kontron pITX-imx8m" diff --git a/arch/arm/mach-imx/imx8m/clock_imx8mm.c b/arch/arm/mach-imx/imx8m/clock_imx8mm.c index 31c34b6031f..986870799d3 100644 --- a/arch/arm/mach-imx/imx8m/clock_imx8mm.c +++ b/arch/arm/mach-imx/imx8m/clock_imx8mm.c @@ -90,7 +90,6 @@ static int fracpll_configure(enum pll_clocks pll, u32 freq) case ANATOP_DRAM_PLL: setbits_le32(GPC_BASE_ADDR + 0xEC, 1 << 7); setbits_le32(GPC_BASE_ADDR + 0xF8, 1 << 5); - writel(SRC_DDR1_ENABLE_MASK, SRC_BASE_ADDR + 0x1004); pll_base = &ana_pll->dram_pll_gnrl_ctl; break; diff --git a/arch/arm/mach-imx/imx8m/soc.c b/arch/arm/mach-imx/imx8m/soc.c index 5ffdcabbb51..d5254886bed 100644 --- a/arch/arm/mach-imx/imx8m/soc.c +++ b/arch/arm/mach-imx/imx8m/soc.c @@ -737,7 +737,7 @@ static int disable_fdt_nodes(void *blob, const char *const nodes_path[], int siz if (nodeoff < 0) continue; /* Not found, skip it */ - printf("Found %s node\n", nodes_path[i]); + debug("Found %s node\n", nodes_path[i]); add_status: rc = fdt_setprop(blob, nodeoff, "status", status, strlen(status) + 1); @@ -1266,7 +1266,7 @@ int ft_system_setup(void *blob, struct bd_info *bd) if (nodeoff >= 0) { const char *speed = "high-speed"; - printf("Found %s node\n", usb_dwc3_path[v]); + debug("Found %s node\n", usb_dwc3_path[v]); usb_modify_speed: diff --git a/arch/arm/mach-imx/imx8ulp/Makefile b/arch/arm/mach-imx/imx8ulp/Makefile index f7692cf3a78..2c9938fcdf0 100644 --- a/arch/arm/mach-imx/imx8ulp/Makefile +++ b/arch/arm/mach-imx/imx8ulp/Makefile @@ -5,7 +5,6 @@ obj-y += lowlevel_init.o obj-y += soc.o clock.o iomux.o pcc.o cgc.o rdc.o -obj-$(CONFIG_AHAB_BOOT) += ahab.o ifeq ($(CONFIG_SPL_BUILD),y) obj-y += upower/ diff --git a/arch/arm/mach-imx/imx8ulp/rdc.c b/arch/arm/mach-imx/imx8ulp/rdc.c index 50b097b035a..cfc09e79cbd 100644 --- a/arch/arm/mach-imx/imx8ulp/rdc.c +++ b/arch/arm/mach-imx/imx8ulp/rdc.c @@ -9,7 +9,7 @@ #include <asm/arch/imx-regs.h> #include <asm/arch/sys_proto.h> #include <asm/mach-imx/mu_hal.h> -#include <asm/mach-imx/s400_api.h> +#include <asm/mach-imx/ele_api.h> #include <asm/arch/rdc.h> #include <div64.h> @@ -203,12 +203,12 @@ int xrdc_config_msc(u32 msc, u32 index, u32 dom, u32 perm) int release_rdc(enum rdc_type type) { ulong s_mu_base = 0x27020000UL; - struct sentinel_msg msg; + struct ele_msg msg; int ret; u32 rdc_id = (type == RDC_XRDC) ? 0x78 : 0x74; - msg.version = AHAB_VERSION; - msg.tag = AHAB_CMD_TAG; + msg.version = ELE_VERSION; + msg.tag = ELE_CMD_TAG; msg.size = 2; msg.command = ELE_RELEASE_RDC_REQ; msg.data[0] = (rdc_id << 8) | 0x2; /* A35 XRDC */ @@ -266,7 +266,7 @@ void xrdc_mrc_region_set_access(int mrc_index, u32 addr, u32 access) mrgd[4] |= ((access & 0xFFF) << 16); } - /* not handle other cases, since S400 only set ACCESS1 and 2 */ + /* not handle other cases, since ELE only set ACCESS1 and 2 */ writel(mrgd[4], xrdc_base + off + 0x10); return; } @@ -295,7 +295,7 @@ void xrdc_init_mda(void) void xrdc_init_mrc(void) { - /* Re-config MRC3 for SRAM0 in case protected by S400 */ + /* Re-config MRC3 for SRAM0 in case protected by ELE */ xrdc_config_mrc_w0_w1(3, 0, 0x22010000, 0x10000); xrdc_config_mrc_dx_perm(3, 0, 0, 1); xrdc_config_mrc_dx_perm(3, 0, 1, 1); @@ -320,7 +320,7 @@ void xrdc_init_mrc(void) xrdc_config_mrc_dx_perm(5, 0, 1, 1); xrdc_config_mrc_w3_w4(5, 0, 0x0, 0x80000FFF); - /* Set MRC6 for DDR access from Sentinel */ + /* Set MRC6 for DDR access from ELE */ xrdc_config_mrc_w0_w1(6, 0, CFG_SYS_SDRAM_BASE, PHYS_SDRAM_SIZE); xrdc_config_mrc_dx_perm(6, 0, 4, 1); xrdc_config_mrc_w3_w4(6, 0, 0x0, 0x80000FFF); @@ -404,7 +404,7 @@ int trdc_mbc_set_access(u32 mbc_x, u32 dom_x, u32 mem_x, u32 blk_x, bool sec_acc val &= ~(0xFU << offset); /* MBC0-3 - * Global 0, 0x7777 secure pri/user read/write/execute, S400 has already set it. + * Global 0, 0x7777 secure pri/user read/write/execute, ELE has already set it. * So select MBC0_MEMN_GLBAC0 */ if (sec_access) { @@ -445,7 +445,7 @@ int trdc_mrc_region_set_access(u32 mrc_x, u32 dom_x, u32 addr_start, u32 addr_en continue; /* MRC0,1 - * Global 0, 0x7777 secure pri/user read/write/execute, S400 has already set it. + * Global 0, 0x7777 secure pri/user read/write/execute, ELE has already set it. * So select MRCx_MEMN_GLBAC0 */ if (sec_access) { diff --git a/arch/arm/mach-imx/imx8ulp/soc.c b/arch/arm/mach-imx/imx8ulp/soc.c index 81eae02b6a8..e23cf60d126 100644 --- a/arch/arm/mach-imx/imx8ulp/soc.c +++ b/arch/arm/mach-imx/imx8ulp/soc.c @@ -14,7 +14,7 @@ #include <event.h> #include <spl.h> #include <asm/arch/rdc.h> -#include <asm/mach-imx/s400_api.h> +#include <asm/mach-imx/ele_api.h> #include <asm/mach-imx/mu_hal.h> #include <cpu_func.h> #include <asm/setup.h> @@ -70,7 +70,7 @@ int mmc_get_env_dev(void) } #endif -static void set_cpu_info(struct sentinel_get_info_data *info) +static void set_cpu_info(struct ele_get_info_data *info) { gd->arch.soc_rev = info->soc; gd->arch.lifecycle = info->lc; @@ -582,9 +582,9 @@ void get_board_serial(struct tag_serialnr *serialnr) u32 res; int ret; - ret = ahab_read_common_fuse(1, uid, 4, &res); + ret = ele_read_common_fuse(1, uid, 4, &res); if (ret) - printf("ahab read fuse failed %d, 0x%x\n", ret, res); + printf("ele read fuse failed %d, 0x%x\n", ret, res); else printf("UID 0x%x,0x%x,0x%x,0x%x\n", uid[0], uid[1], uid[2], uid[3]); @@ -783,7 +783,7 @@ int imx8ulp_dm_post_init(void) struct udevice *devp; int ret; u32 res; - struct sentinel_get_info_data *info = (struct sentinel_get_info_data *)SRAM0_BASE; + struct ele_get_info_data *info = (struct ele_get_info_data *)SRAM0_BASE; ret = uclass_get_device_by_driver(UCLASS_MISC, DM_DRIVER_GET(imx8ulp_mu), &devp); if (ret) { @@ -791,11 +791,11 @@ int imx8ulp_dm_post_init(void) return ret; } - ret = ahab_get_info(info, &res); + ret = ele_get_info(info, &res); if (ret) { - printf("ahab_get_info failed %d\n", ret); + printf("ele_get_info failed %d\n", ret); /* fallback to A0.1 revision */ - memset((void *)info, 0, sizeof(struct sentinel_get_info_data)); + memset((void *)info, 0, sizeof(struct ele_get_info_data)); info->soc = 0xa000084d; } diff --git a/arch/arm/mach-imx/imx8ulp/upower/upower_hal.c b/arch/arm/mach-imx/imx8ulp/upower/upower_hal.c index fcb02ed3af6..b471a75caa1 100644 --- a/arch/arm/mach-imx/imx8ulp/upower/upower_hal.c +++ b/arch/arm/mach-imx/imx8ulp/upower/upower_hal.c @@ -217,8 +217,8 @@ int upower_init(void) * CM33 Cache * PowerQuad RAM * ETF RAM - * Sentinel PKC, Data RAM1, Inst RAM0/1 - * Sentinel ROM + * ELE PKC, Data RAM1, Inst RAM0/1 + * ELE ROM * uPower IRAM/DRAM * uPower ROM * CM33 ROM @@ -230,7 +230,7 @@ int upower_init(void) * SSRAM Partition 7_a(128KB) * SSRAM Partition 7_b(64KB) * SSRAM Partition 7_c(64KB) - * Sentinel Data RAM0, Inst RAM2 + * ELE Data RAM0, Inst RAM2 */ /* MIPI-CSI FIFO BIT28 not set */ memon = 0x3FFFFFEFFFFFFCUL; diff --git a/arch/arm/mach-imx/imx9/clock.c b/arch/arm/mach-imx/imx9/clock.c index a7ecccaf879..766a8811c1f 100644 --- a/arch/arm/mach-imx/imx9/clock.c +++ b/arch/arm/mach-imx/imx9/clock.c @@ -709,8 +709,8 @@ struct imx_clk_setting imx_clk_settings[] = { /* Set A55 mtr bus to 133M */ {ARM_A55_MTR_BUS_CLK_ROOT, SYS_PLL_PFD1_DIV2, 3}, - /* Sentinel to 133M */ - {SENTINEL_CLK_ROOT, SYS_PLL_PFD1_DIV2, 3}, + /* ELE to 133M */ + {ELE_CLK_ROOT, SYS_PLL_PFD1_DIV2, 3}, /* Bus_wakeup to 133M */ {BUS_WAKEUP_CLK_ROOT, SYS_PLL_PFD1_DIV2, 3}, /* Bus_AON to 133M */ @@ -740,8 +740,8 @@ struct imx_clk_setting imx_clk_settings[] = { {ARM_A55_PERIPH_CLK_ROOT, SYS_PLL_PFD0, 3}, /* Set A55 mtr bus to 133M */ {ARM_A55_MTR_BUS_CLK_ROOT, SYS_PLL_PFD1_DIV2, 3}, - /* Sentinel to 200M */ - {SENTINEL_CLK_ROOT, SYS_PLL_PFD1_DIV2, 2}, + /* ELE to 200M */ + {ELE_CLK_ROOT, SYS_PLL_PFD1_DIV2, 2}, /* Bus_wakeup to 133M */ {BUS_WAKEUP_CLK_ROOT, SYS_PLL_PFD1_DIV2, 3}, /* Bus_AON to 133M */ diff --git a/arch/arm/mach-imx/imx9/clock_root.c b/arch/arm/mach-imx/imx9/clock_root.c index 06b93f60996..7d7ae865946 100644 --- a/arch/arm/mach-imx/imx9/clock_root.c +++ b/arch/arm/mach-imx/imx9/clock_root.c @@ -34,7 +34,7 @@ static struct clk_root_map clk_root_array[] = { { ARM_A55_MTR_BUS_CLK_ROOT, 2 }, { ARM_A55_CLK_ROOT, 0 }, { M33_CLK_ROOT, 2 }, - { SENTINEL_CLK_ROOT, 2 }, + { ELE_CLK_ROOT, 2 }, { BUS_WAKEUP_CLK_ROOT, 2 }, { BUS_AON_CLK_ROOT, 2 }, { WAKEUP_AXI_CLK_ROOT, 0 }, diff --git a/arch/arm/mach-imx/imx9/imx_bootaux.c b/arch/arm/mach-imx/imx9/imx_bootaux.c index 256e6fa1c54..6afb59e0515 100644 --- a/arch/arm/mach-imx/imx9/imx_bootaux.c +++ b/arch/arm/mach-imx/imx9/imx_bootaux.c @@ -13,7 +13,7 @@ int arch_auxiliary_core_check_up(u32 core_id) { struct arm_smccc_res res; - arm_smccc_smc(IMX_SIP_SRC, IMX_SIP_SRC_M4_STARTED, 0, 0, + arm_smccc_smc(IMX_SIP_SRC, IMX_SIP_SRC_MCU_STARTED, 0, 0, 0, 0, 0, 0, &res); return res.a0; @@ -25,7 +25,7 @@ int arch_auxiliary_core_down(u32 core_id) printf("## Stopping auxiliary core\n"); - arm_smccc_smc(IMX_SIP_SRC, IMX_SIP_SRC_M4_STOP, 0, 0, + arm_smccc_smc(IMX_SIP_SRC, IMX_SIP_SRC_MCU_STOP, 0, 0, 0, 0, 0, 0, &res); return 0; @@ -40,7 +40,7 @@ int arch_auxiliary_core_up(u32 core_id, ulong addr) printf("## Starting auxiliary core addr = 0x%08lX...\n", addr); - arm_smccc_smc(IMX_SIP_SRC, IMX_SIP_SRC_M4_START, addr, 0, + arm_smccc_smc(IMX_SIP_SRC, IMX_SIP_SRC_MCU_START, addr, 0, 0, 0, 0, 0, &res); return 0; diff --git a/arch/arm/mach-imx/imx9/soc.c b/arch/arm/mach-imx/imx9/soc.c index 64e8ac610e5..f43b73a6c21 100644 --- a/arch/arm/mach-imx/imx9/soc.c +++ b/arch/arm/mach-imx/imx9/soc.c @@ -34,7 +34,7 @@ #include <asm/setup.h> #include <asm/bootm.h> #include <asm/arch-imx/cpu.h> -#include <asm/mach-imx/s400_api.h> +#include <asm/mach-imx/ele_api.h> #include <fuse.h> #include <asm/arch/ddr.h> @@ -151,7 +151,7 @@ u32 get_cpu_temp_grade(int *minc, int *maxc) return val; } -static void set_cpu_info(struct sentinel_get_info_data *info) +static void set_cpu_info(struct ele_get_info_data *info) { gd->arch.soc_rev = info->soc; gd->arch.lifecycle = info->lc; @@ -557,7 +557,7 @@ int imx9_probe_mu(void *ctx, struct event *event) struct udevice *devp; int node, ret; u32 res; - struct sentinel_get_info_data info; + struct ele_get_info_data info; node = fdt_node_offset_by_compatible(gd->fdt_blob, -1, "fsl,imx93-mu-s4"); @@ -568,7 +568,7 @@ int imx9_probe_mu(void *ctx, struct event *event) if (gd->flags & GD_FLG_RELOC) return 0; - ret = ahab_get_info(&info, &res); + ret = ele_get_info(&info, &res); if (ret) return ret; @@ -600,35 +600,31 @@ int timer_init(void) enum env_location env_get_location(enum env_operation op, int prio) { enum boot_device dev = get_boot_device(); - enum env_location env_loc = ENVL_UNKNOWN; if (prio) - return env_loc; + return ENVL_UNKNOWN; switch (dev) { -#if defined(CONFIG_ENV_IS_IN_SPI_FLASH) case QSPI_BOOT: - env_loc = ENVL_SPI_FLASH; - break; -#endif -#if defined(CONFIG_ENV_IS_IN_MMC) + if (CONFIG_IS_ENABLED(ENV_IS_IN_SPI_FLASH)) + return ENVL_SPI_FLASH; + return ENVL_NOWHERE; case SD1_BOOT: case SD2_BOOT: case SD3_BOOT: case MMC1_BOOT: case MMC2_BOOT: case MMC3_BOOT: - env_loc = ENVL_MMC; - break; -#endif + if (CONFIG_IS_ENABLED(ENV_IS_IN_MMC)) + return ENVL_MMC; + else if (CONFIG_IS_ENABLED(ENV_IS_IN_EXT4)) + return ENVL_EXT4; + else if (CONFIG_IS_ENABLED(ENV_IS_IN_FAT)) + return ENVL_FAT; + return ENVL_NOWHERE; default: -#if defined(CONFIG_ENV_IS_NOWHERE) - env_loc = ENVL_NOWHERE; -#endif - break; + return ENVL_NOWHERE; } - - return env_loc; } static int mix_power_init(enum mix_power_domain pd) @@ -646,7 +642,7 @@ static int mix_power_init(enum mix_power_domain pd) mem_id = SRC_MEM_MEDIA; scr = BIT(5); - /* Enable S400 handshake */ + /* Enable ELE handshake */ struct blk_ctrl_s_aonmix_regs *s_regs = (struct blk_ctrl_s_aonmix_regs *)BLK_CTRL_S_ANOMIX_BASE_ADDR; @@ -763,8 +759,8 @@ int m33_prepare(void) while (!(val & SRC_MIX_SLICE_FUNC_STAT_RST_STAT)) val = readl(&mix_regs->func_stat); - /* Release Sentinel TROUT */ - ahab_release_m33_trout(); + /* Release ELE TROUT */ + ele_release_m33_trout(); /* Mask WDOG1 IRQ from A55, we use it for M33 reset */ setbits_le32(&s_regs->ca55_irq_mask[1], BIT(6)); @@ -772,7 +768,7 @@ int m33_prepare(void) /* Turn on WDOG1 clock */ ccm_lpcg_on(CCGR_WDG1, 1); - /* Set sentinel LP handshake for M33 reset */ + /* Set ELE LP handshake for M33 reset */ setbits_le32(&s_regs->lp_handshake[0], BIT(6)); /* Clear M33 TCM for ECC */ diff --git a/arch/arm/mach-imx/imx9/trdc.c b/arch/arm/mach-imx/imx9/trdc.c index e05c7048106..d0f855bb1bc 100644 --- a/arch/arm/mach-imx/imx9/trdc.c +++ b/arch/arm/mach-imx/imx9/trdc.c @@ -10,7 +10,7 @@ #include <asm/arch/imx-regs.h> #include <asm/arch/sys_proto.h> #include <div64.h> -#include <asm/mach-imx/s400_api.h> +#include <asm/mach-imx/ele_api.h> #include <asm/mach-imx/mu_hal.h> #define DID_NUM 16 @@ -196,7 +196,7 @@ int trdc_mbc_blk_config(ulong trdc_reg, u32 mbc_x, u32 dom_x, u32 mem_x, val &= ~(0xFU << offset); /* MBC0-3 - * Global 0, 0x7777 secure pri/user read/write/execute, S400 has already set it. + * Global 0, 0x7777 secure pri/user read/write/execute, ELE has already set it. * So select MBC0_MEMN_GLBAC0 */ if (sec_access) { @@ -266,7 +266,7 @@ int trdc_mrc_region_config(ulong trdc_reg, u32 mrc_x, u32 dom_x, u32 addr_start, continue; /* MRC0,1 - * Global 0, 0x7777 secure pri/user read/write/execute, S400 has already set it. + * Global 0, 0x7777 secure pri/user read/write/execute, ELE has already set it. * So select MRCx_MEMN_GLBAC0 */ if (sec_access) { @@ -315,7 +315,7 @@ bool trdc_mbc_enabled(ulong trdc_base) int release_rdc(u8 xrdc) { ulong s_mu_base = 0x47520000UL; - struct sentinel_msg msg; + struct ele_msg msg; int ret; u32 rdc_id; @@ -336,8 +336,8 @@ int release_rdc(u8 xrdc) return -EINVAL; } - msg.version = AHAB_VERSION; - msg.tag = AHAB_CMD_TAG; + msg.version = ELE_VERSION; + msg.tag = ELE_CMD_TAG; msg.size = 2; msg.command = ELE_RELEASE_RDC_REQ; msg.data[0] = (rdc_id << 8) | 0x2; /* A55 */ @@ -394,7 +394,7 @@ void trdc_init(void) /* DDR */ trdc_mrc_set_control(0x49010000, 0, 0, 0x7777); - /* S400*/ + /* ELE */ trdc_mrc_region_config(0x49010000, 0, 0, 0x80000000, 0xFFFFFFFF, false, 0); /* MTR */ diff --git a/arch/arm/mach-imx/imx_bootaux.c b/arch/arm/mach-imx/imx_bootaux.c index 888c53d6901..f7b14ca38d9 100644 --- a/arch/arm/mach-imx/imx_bootaux.c +++ b/arch/arm/mach-imx/imx_bootaux.c @@ -14,6 +14,7 @@ #include <linux/compiler.h> #include <cpu_func.h> +#ifndef CONFIG_IMX8 /* Just to avoid build error */ #if IS_ENABLED(CONFIG_IMX8M) #define SRC_M4C_NON_SCLR_RST_MASK BIT(0) @@ -45,7 +46,7 @@ static const struct rproc_att *get_host_mapping(unsigned long auxcore) * is valid, returns the entry point address. * Translates load addresses in the elf file to the U-Boot address space. */ -static unsigned long load_elf_image_m_core_phdr(unsigned long addr, ulong *stack) +static u32 load_elf_image_m_core_phdr(unsigned long addr, u32 *stack) { Elf32_Ehdr *ehdr; /* ELF header structure pointer */ Elf32_Phdr *phdr; /* Program header structure pointer */ @@ -95,7 +96,7 @@ static unsigned long load_elf_image_m_core_phdr(unsigned long addr, ulong *stack int arch_auxiliary_core_up(u32 core_id, ulong addr) { - ulong stack, pc; + u32 stack, pc; if (!addr) return -EINVAL; @@ -121,18 +122,18 @@ int arch_auxiliary_core_up(u32 core_id, ulong addr) pc = *(u32 *)(addr + 4); } - printf("## Starting auxiliary core stack = 0x%08lX, pc = 0x%08lX...\n", + printf("## Starting auxiliary core stack = 0x%08X, pc = 0x%08X...\n", stack, pc); - /* Set the stack and pc to M4 bootROM */ - writel(stack, M4_BOOTROM_BASE_ADDR); - writel(pc, M4_BOOTROM_BASE_ADDR + 4); + /* Set the stack and pc to MCU bootROM */ + writel(stack, MCU_BOOTROM_BASE_ADDR); + writel(pc, MCU_BOOTROM_BASE_ADDR + 4); flush_dcache_all(); - /* Enable M4 */ + /* Enable MCU */ if (IS_ENABLED(CONFIG_IMX8M)) { - arm_smccc_smc(IMX_SIP_SRC, IMX_SIP_SRC_M4_START, 0, 0, 0, 0, 0, 0, NULL); + arm_smccc_smc(IMX_SIP_SRC, IMX_SIP_SRC_MCU_START, 0, 0, 0, 0, 0, 0, NULL); } else { clrsetbits_le32(SRC_BASE_ADDR + SRC_M4_REG_OFFSET, SRC_M4C_NON_SCLR_RST_MASK, SRC_M4_ENABLE_MASK); @@ -147,7 +148,7 @@ int arch_auxiliary_core_check_up(u32 core_id) unsigned int val; if (IS_ENABLED(CONFIG_IMX8M)) { - arm_smccc_smc(IMX_SIP_SRC, IMX_SIP_SRC_M4_STARTED, 0, 0, 0, 0, 0, 0, &res); + arm_smccc_smc(IMX_SIP_SRC, IMX_SIP_SRC_MCU_STARTED, 0, 0, 0, 0, 0, 0, &res); return res.a0; } @@ -158,30 +159,34 @@ int arch_auxiliary_core_check_up(u32 core_id) return 1; } - +#endif /* * To i.MX6SX and i.MX7D, the image supported by bootaux needs * the reset vector at the head for the image, with SP and PC * as the first two words. * - * Per the cortex-M reference manual, the reset vector of M4 needs - * to exist at 0x0 (TCMUL). The PC and SP are the first two addresses - * of that vector. So to boot M4, the A core must build the M4's reset + * Per the cortex-M reference manual, the reset vector of M4/M7 needs + * to exist at 0x0 (TCMUL/IDTCM). The PC and SP are the first two addresses + * of that vector. So to boot M4/M7, the A core must build the M4/M7's reset * vector with getting the PC and SP from image and filling them to - * TCMUL. When M4 is kicked, it will load the PC and SP by itself. - * The TCMUL is mapped to (M4_BOOTROM_BASE_ADDR) at A core side for - * accessing the M4 TCMUL. + * TCMUL/IDTCM. When M4/M7 is kicked, it will load the PC and SP by itself. + * The TCMUL/IDTCM is mapped to (MCU_BOOTROM_BASE_ADDR) at A core side for + * accessing the M4/M7 TCMUL/IDTCM. */ static int do_bootaux(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { ulong addr; int ret, up; + u32 core = 0; if (argc < 2) return CMD_RET_USAGE; - up = arch_auxiliary_core_check_up(0); + if (argc > 2) + core = simple_strtoul(argv[2], NULL, 10); + + up = arch_auxiliary_core_check_up(core); if (up) { printf("## Auxiliary core is already up\n"); return CMD_RET_SUCCESS; @@ -192,7 +197,7 @@ static int do_bootaux(struct cmd_tbl *cmdtp, int flag, int argc, if (!addr) return CMD_RET_FAILURE; - ret = arch_auxiliary_core_up(0, addr); + ret = arch_auxiliary_core_up(core, addr); if (ret) return CMD_RET_FAILURE; @@ -202,5 +207,7 @@ static int do_bootaux(struct cmd_tbl *cmdtp, int flag, int argc, U_BOOT_CMD( bootaux, CONFIG_SYS_MAXARGS, 1, do_bootaux, "Start auxiliary core", - "" + "<address> [<core>]\n" + " - start auxiliary core [<core>] (default 0),\n" + " at address <address>\n" ); diff --git a/arch/arm/mach-imx/mx6/module_fuse.c b/arch/arm/mach-imx/mx6/module_fuse.c index 0f4565e3117..b58f11c1e56 100644 --- a/arch/arm/mach-imx/mx6/module_fuse.c +++ b/arch/arm/mach-imx/mx6/module_fuse.c @@ -206,7 +206,7 @@ int ft_system_setup(void *blob, struct bd_info *bd) if (off < 0) continue; /* Not found, skip it */ add_status: - rc = fdt_setprop(blob, nodeoff, "status", status, + rc = fdt_setprop(blob, off, "status", status, strlen(status) + 1); if (rc) { if (rc == -FDT_ERR_NOSPACE) { diff --git a/arch/arm/mach-imx/mxs/Kconfig b/arch/arm/mach-imx/mxs/Kconfig index b2026a3758a..d3233d8d14f 100644 --- a/arch/arm/mach-imx/mxs/Kconfig +++ b/arch/arm/mach-imx/mxs/Kconfig @@ -10,10 +10,12 @@ choice config TARGET_MX23_OLINUXINO bool "Support mx23_olinuxino" + select PL01X_SERIAL select BOARD_EARLY_INIT_F config TARGET_MX23EVK bool "Support mx23evk" + select PL01X_SERIAL select BOARD_EARLY_INIT_F config TARGET_XFI3 @@ -41,16 +43,37 @@ choice config TARGET_MX28EVK bool "Support mx28evk" + select PL01X_SERIAL select BOARD_EARLY_INIT_F config TARGET_XEA bool "Support XEA" + select PL01X_SERIAL endchoice config SYS_SOC default "mxs" +config SPL_MXS_PMU_MINIMAL_VDD5V_CURRENT + bool "Force minimal current draw from VDD5V by MX28 PMU" + default n + help + After setting this option, the current drawn from VDD5V + by the PMU is reduced to zero - the DCDC_BATT is used as + the main power source for PMU. + +config SPL_MXS_PMU_DISABLE_BATT_CHARGE + bool "Disable Battery Charging in MX28 PMU" + default n + +config SPL_MXS_PMU_ENABLE_4P2_LINEAR_REGULATOR + bool "Enable the 4P2 linear regulator in MX28 PMU" + default y + help + This option enables the 4P2 linear regulator (derived + from VDD5V) - so the VDD4P2 power source is operational. + source "board/freescale/mx28evk/Kconfig" source "board/liebherr/xea/Kconfig" diff --git a/arch/arm/mach-imx/parse-container.c b/arch/arm/mach-imx/parse-container.c index f7582825d6d..e2a9e2b2732 100644 --- a/arch/arm/mach-imx/parse-container.c +++ b/arch/arm/mach-imx/parse-container.c @@ -1,75 +1,16 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Copyright 2018-2019 NXP + * Copyright 2018-2021 NXP */ #include <common.h> +#include <stdlib.h> #include <errno.h> #include <log.h> #include <spl.h> #include <asm/mach-imx/image.h> #ifdef CONFIG_AHAB_BOOT -#include <firmware/imx/sci/sci.h> -#endif - -#define SEC_SECURE_RAM_BASE 0x31800000UL -#define SEC_SECURE_RAM_END_BASE (SEC_SECURE_RAM_BASE + 0xFFFFUL) -#define SECO_LOCAL_SEC_SEC_SECURE_RAM_BASE 0x60000000UL - -#define SECO_PT 2U - -#ifdef CONFIG_AHAB_BOOT -static int authenticate_image(struct boot_img_t *img, int image_index) -{ - sc_faddr_t start, end; - sc_rm_mr_t mr; - int err; - int ret = 0; - - debug("img %d, dst 0x%x, src 0x%x, size 0x%x\n", - image_index, (uint32_t)img->dst, img->offset, img->size); - - /* Find the memreg and set permission for seco pt */ - err = sc_rm_find_memreg(-1, &mr, - img->dst & ~(CONFIG_SYS_CACHELINE_SIZE - 1), - ALIGN(img->dst + img->size, CONFIG_SYS_CACHELINE_SIZE) - 1); - - if (err) { - printf("can't find memreg for image %d load address 0x%x, error %d\n", - image_index, img->dst & ~(CONFIG_SYS_CACHELINE_SIZE - 1), err); - return -ENOMEM; - } - - err = sc_rm_get_memreg_info(-1, mr, &start, &end); - if (!err) - debug("memreg %u 0x%x -- 0x%x\n", mr, start, end); - - err = sc_rm_set_memreg_permissions(-1, mr, - SECO_PT, SC_RM_PERM_FULL); - if (err) { - printf("set permission failed for img %d, error %d\n", - image_index, err); - return -EPERM; - } - - err = sc_seco_authenticate(-1, SC_SECO_VERIFY_IMAGE, - 1 << image_index); - if (err) { - printf("authenticate img %d failed, return %d\n", - image_index, err); - ret = -EIO; - } - - err = sc_rm_set_memreg_permissions(-1, mr, - SECO_PT, SC_RM_PERM_NONE); - if (err) { - printf("remove permission failed for img %d, error %d\n", - image_index, err); - ret = -EPERM; - } - - return ret; -} +#include <asm/mach-imx/ahab.h> #endif static struct boot_img_t *read_auth_image(struct spl_image_info *spl_image, @@ -110,10 +51,8 @@ static struct boot_img_t *read_auth_image(struct spl_image_info *spl_image, } #ifdef CONFIG_AHAB_BOOT - if (authenticate_image(&images[image_index], image_index)) { - printf("Failed to authenticate image %d\n", image_index); + if (ahab_verify_cntr_image(&images[image_index], image_index)) return NULL; - } #endif return &images[image_index]; @@ -134,21 +73,27 @@ static int read_auth_container(struct spl_image_info *spl_image, * It will not override the ATF code, so safe to use it here, * no need malloc */ - container = (struct container_hdr *)spl_get_load_buffer(-size, size); + container = malloc(size); + if (!container) + return -ENOMEM; debug("%s: container: %p sector: %lu sectors: %u\n", __func__, container, sector, sectors); - if (info->read(info, sector, sectors, container) != sectors) - return -EIO; + if (info->read(info, sector, sectors, container) != sectors) { + ret = -EIO; + goto end; + } if (container->tag != 0x87 && container->version != 0x0) { - printf("Wrong container header\n"); - return -ENOENT; + printf("Wrong container header"); + ret = -ENOENT; + goto end; } if (!container->num_images) { - printf("Wrong container, no image found\n"); - return -ENOENT; + printf("Wrong container, no image found"); + ret = -ENOENT; + goto end; } length = container->length_lsb + (container->length_msb << 8); @@ -158,25 +103,24 @@ static int read_auth_container(struct spl_image_info *spl_image, size = roundup(length, info->bl_len); sectors = size / info->bl_len; - container = (struct container_hdr *)spl_get_load_buffer(-size, size); + free(container); + container = malloc(size); + if (!container) + return -ENOMEM; debug("%s: container: %p sector: %lu sectors: %u\n", __func__, container, sector, sectors); if (info->read(info, sector, sectors, container) != - sectors) - return -EIO; + sectors) { + ret = -EIO; + goto end; + } } #ifdef CONFIG_AHAB_BOOT - memcpy((void *)SEC_SECURE_RAM_BASE, (const void *)container, - ALIGN(length, CONFIG_SYS_CACHELINE_SIZE)); - - ret = sc_seco_authenticate(-1, SC_SECO_AUTH_CONTAINER, - SECO_LOCAL_SEC_SEC_SECURE_RAM_BASE); - if (ret) { - printf("authenticate container hdr failed, return %d\n", ret); - return ret; - } + ret = ahab_auth_cntr_hdr(container, length); + if (ret) + goto end_auth; #endif for (i = 0; i < container->num_images; i++) { @@ -197,9 +141,12 @@ static int read_auth_container(struct spl_image_info *spl_image, end_auth: #ifdef CONFIG_AHAB_BOOT - if (sc_seco_authenticate(-1, SC_SECO_REL_CONTAINER, 0)) - printf("Error: release container failed!\n"); + ahab_auth_release(); #endif + +end: + free(container); + return ret; } diff --git a/arch/arm/mach-imx/priblob.c b/arch/arm/mach-imx/priblob.c index 9b92eae7818..5b022d5c820 100644 --- a/arch/arm/mach-imx/priblob.c +++ b/arch/arm/mach-imx/priblob.c @@ -13,12 +13,16 @@ #include <asm/io.h> #include <common.h> #include <command.h> -#include "../drivers/crypto/fsl_caam_internal.h" +#include <fsl_sec.h> int do_priblob_write(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]) { - writel((readl(CAAM_SCFGR) & 0xFFFFFFFC) | 3, CAAM_SCFGR); - printf("New priblob setting = 0x%x\n", readl(CAAM_SCFGR) & 0x3); + ccsr_sec_t *sec_regs = (ccsr_sec_t *)CAAM_BASE_ADDR; + u32 scfgr = sec_in32(&sec_regs->scfgr); + + scfgr |= 0x3; + sec_out32(&sec_regs->scfgr, scfgr); + printf("New priblob setting = 0x%x\n", sec_in32(&sec_regs->scfgr) & 0x3); return 0; } diff --git a/arch/arm/mach-imx/spl_imx_romapi.c b/arch/arm/mach-imx/spl_imx_romapi.c index 9164045115f..4af41699678 100644 --- a/arch/arm/mach-imx/spl_imx_romapi.c +++ b/arch/arm/mach-imx/spl_imx_romapi.c @@ -76,13 +76,16 @@ static int spl_romapi_load_image_seekable(struct spl_image_info *spl_image, u32 image_offset; ret = rom_api_query_boot_infor(QUERY_IVT_OFF, &offset); - ret |= rom_api_query_boot_infor(QUERY_PAGE_SZ, &pagesize); - ret |= rom_api_query_boot_infor(QUERY_IMG_OFF, &image_offset); + if (ret != ROM_API_OKAY) + goto err; - if (ret != ROM_API_OKAY) { - puts("ROMAPI: Failure query boot infor pagesize/offset\n"); - return -1; - } + ret = rom_api_query_boot_infor(QUERY_PAGE_SZ, &pagesize); + if (ret != ROM_API_OKAY) + goto err; + + ret = rom_api_query_boot_infor(QUERY_IMG_OFF, &image_offset); + if (ret != ROM_API_OKAY) + goto err; header = (struct legacy_img_hdr *)(CONFIG_SPL_IMX_ROMAPI_LOADADDR); @@ -124,6 +127,10 @@ static int spl_romapi_load_image_seekable(struct spl_image_info *spl_image, } return 0; + +err: + puts("ROMAPI: Failure query boot infor pagesize/offset\n"); + return -1; } static ulong spl_ram_load_read(struct spl_load_info *load, ulong sector, @@ -344,12 +351,12 @@ int board_return_to_bootrom(struct spl_image_info *spl_image, u32 boot, bstage; ret = rom_api_query_boot_infor(QUERY_BT_DEV, &boot); - ret |= rom_api_query_boot_infor(QUERY_BT_STAGE, &bstage); + if (ret != ROM_API_OKAY) + goto err; - if (ret != ROM_API_OKAY) { - puts("ROMAPI: failure at query_boot_info\n"); - return -1; - } + ret = rom_api_query_boot_infor(QUERY_BT_STAGE, &bstage); + if (ret != ROM_API_OKAY) + goto err; printf("Boot Stage: "); @@ -374,4 +381,7 @@ int board_return_to_bootrom(struct spl_image_info *spl_image, return spl_romapi_load_image_stream(spl_image, bootdev); return spl_romapi_load_image_seekable(spl_image, bootdev, boot); +err: + puts("ROMAPI: failure at query_boot_info\n"); + return -1; } diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig index ac484c73f62..5c7f4bf964a 100644 --- a/arch/arm/mach-mvebu/Kconfig +++ b/arch/arm/mach-mvebu/Kconfig @@ -202,6 +202,10 @@ config TARGET_X530 bool "Support Allied Telesis x530" select 88F6820 +config TARGET_X240 + bool "Support Allied Telesis x240" + select ALLEYCAT_5 + config TARGET_DB_XC3_24G4XG bool "Support DB-XC3-24G4XG" select 98DX3336 @@ -274,6 +278,7 @@ config SYS_BOARD default "theadorable" if TARGET_THEADORABLE default "a38x" if TARGET_CONTROLCENTERDC default "x530" if TARGET_X530 + default "x240" if TARGET_X240 default "db-xc3-24g4xg" if TARGET_DB_XC3_24G4XG default "crs3xx-98dx3236" if TARGET_CRS3XX_98DX3236 default "mvebu_alleycat-5" if TARGET_MVEBU_ALLEYCAT5 @@ -297,6 +302,7 @@ config SYS_CONFIG_NAME default "turris_mox" if TARGET_TURRIS_MOX default "controlcenterdc" if TARGET_CONTROLCENTERDC default "x530" if TARGET_X530 + default "x240" if TARGET_X240 default "db-xc3-24g4xg" if TARGET_DB_XC3_24G4XG default "crs3xx-98dx3236" if TARGET_CRS3XX_98DX3236 default "mvebu_alleycat-5" if TARGET_MVEBU_ALLEYCAT5 @@ -320,6 +326,7 @@ config SYS_VENDOR default "CZ.NIC" if TARGET_TURRIS_MOX default "gdsys" if TARGET_CONTROLCENTERDC default "alliedtelesis" if TARGET_X530 + default "alliedtelesis" if TARGET_X240 default "mikrotik" if TARGET_CRS3XX_98DX3236 default "Marvell" if TARGET_MVEBU_ALLEYCAT5 diff --git a/arch/arm/mach-mvebu/alleycat5/soc.c b/arch/arm/mach-mvebu/alleycat5/soc.c index dc69f46eedb..734b0a87dd4 100644 --- a/arch/arm/mach-mvebu/alleycat5/soc.c +++ b/arch/arm/mach-mvebu/alleycat5/soc.c @@ -255,6 +255,12 @@ void soc_print_clock_info(void) printf("\tMSS %4d MHz\n", 200); } +/* Return NAND clock in Hz */ +u32 mvebu_get_nand_clock(void) +{ + return 400 * 1000000; +} + /* * Override of __weak int mach_cpu_init(void) : * SoC/machine dependent CPU setup diff --git a/arch/arm/mach-npcm/npcm8xx/cpu.c b/arch/arm/mach-npcm/npcm8xx/cpu.c index 2d839cfae95..af594526094 100644 --- a/arch/arm/mach-npcm/npcm8xx/cpu.c +++ b/arch/arm/mach-npcm/npcm8xx/cpu.c @@ -68,6 +68,9 @@ int print_cpuinfo(void) case ARBEL_A1: printf("A1 @ "); break; + case ARBEL_A2: + printf("A2 @ "); + break; default: printf("Unknown\n"); break; @@ -92,7 +95,7 @@ int arch_cpu_init(void) return 0; } -static struct mm_region npcm_mem_map[1 + CONFIG_NR_DRAM_BANKS + 1] = { +static struct mm_region npcm_mem_map[] = { { /* DRAM */ .phys = 0x0UL, @@ -110,6 +113,13 @@ static struct mm_region npcm_mem_map[1 + CONFIG_NR_DRAM_BANKS + 1] = { PTE_BLOCK_PXN | PTE_BLOCK_UXN }, { + .phys = 0x100000000UL, + .virt = 0x100000000UL, + .size = 0x80000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE + }, + { /* List terminator */ 0, } diff --git a/arch/powerpc/lib/Kconfig b/arch/powerpc/lib/Kconfig index b30b5edf7cf..d38ba45a990 100644 --- a/arch/powerpc/lib/Kconfig +++ b/arch/powerpc/lib/Kconfig @@ -1,9 +1,9 @@ config CACHE_FLUSH_WATCHDOG_THRESHOLD - int "Bytes to flush between WATCHDOG_RESET calls" - default 0 + int "Bytes to flush between schedule() calls" + default 4096 help The flush_cache() function periodically, and by default for - every cache line, calls WATCHDOG_RESET(). When flushing a - large area, that may add a significant amount of + every 4k block, calls schedule() to reset watchdog. When + flushing a large area, that may add a significant amount of overhead. This option allows you to set a threshold for how - many bytes to flush between each WATCHDOG_RESET call. + many bytes to flush between each schedule() call. diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index f6ed05906a2..867cbcbe74e 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -27,6 +27,10 @@ config TARGET_SIFIVE_UNMATCHED config TARGET_STARFIVE_VISIONFIVE2 bool "Support StarFive VisionFive2 Board" +config TARGET_TH1520_LPI4A + bool "Support Sipeed's TH1520 Lichee PI 4A Board" + select SYS_CACHE_SHIFT_6 + config TARGET_SIPEED_MAIX bool "Support Sipeed Maix Board" select SYS_CACHE_SHIFT_6 @@ -66,6 +70,7 @@ source "board/emulation/qemu-riscv/Kconfig" source "board/microchip/mpfs_icicle/Kconfig" source "board/sifive/unleashed/Kconfig" source "board/sifive/unmatched/Kconfig" +source "board/thead/th1520_lpi4a/Kconfig" source "board/openpiton/riscv64/Kconfig" source "board/sipeed/maix/Kconfig" source "board/starfive/visionfive2/Kconfig" @@ -185,18 +190,22 @@ config DMA_ADDR_T_64BIT bool default y if 64BIT -config SIFIVE_CLINT +config RISCV_ACLINT bool depends on RISCV_MMODE + select REGMAP + select SYSCON help - The SiFive CLINT block holds memory-mapped control and status registers + The RISC-V ACLINT block holds memory-mapped control and status registers associated with software and timer interrupts. -config SPL_SIFIVE_CLINT +config SPL_RISCV_ACLINT bool depends on SPL_RISCV_MMODE + select SPL_REGMAP + select SPL_SYSCON help - The SiFive CLINT block holds memory-mapped control and status registers + The RISC-V ACLINT block holds memory-mapped control and status registers associated with software and timer interrupts. config SIFIVE_CACHE diff --git a/arch/riscv/cpu/fu540/Kconfig b/arch/riscv/cpu/fu540/Kconfig index 1604b412b48..c68209d8fb2 100644 --- a/arch/riscv/cpu/fu540/Kconfig +++ b/arch/riscv/cpu/fu540/Kconfig @@ -11,7 +11,7 @@ config SIFIVE_FU540 imply CPU imply CPU_RISCV imply RISCV_TIMER if (RISCV_SMODE || SPL_RISCV_SMODE) - imply SPL_SIFIVE_CLINT + imply SPL_RISCV_ACLINT imply CMD_CPU imply SPL_CPU imply SPL_OPENSBI diff --git a/arch/riscv/cpu/fu740/Kconfig b/arch/riscv/cpu/fu740/Kconfig index 3e0c1fddc88..d7ca9687171 100644 --- a/arch/riscv/cpu/fu740/Kconfig +++ b/arch/riscv/cpu/fu740/Kconfig @@ -11,7 +11,7 @@ config SIFIVE_FU740 imply CPU imply CPU_RISCV imply RISCV_TIMER if (RISCV_SMODE || SPL_RISCV_SMODE) - imply SPL_SIFIVE_CLINT + imply SPL_RISCV_ACLINT imply CMD_CPU imply SPL_CPU imply SPL_OPENSBI diff --git a/arch/riscv/cpu/generic/Kconfig b/arch/riscv/cpu/generic/Kconfig index e025134b23c..897765c3c68 100644 --- a/arch/riscv/cpu/generic/Kconfig +++ b/arch/riscv/cpu/generic/Kconfig @@ -9,8 +9,8 @@ config GENERIC_RISCV imply CPU imply CPU_RISCV imply RISCV_TIMER if (RISCV_SMODE || SPL_RISCV_SMODE) - imply SIFIVE_CLINT if RISCV_MMODE - imply SPL_SIFIVE_CLINT if SPL_RISCV_MMODE + imply RISCV_ACLINT if RISCV_MMODE + imply SPL_RISCV_ACLINT if SPL_RISCV_MMODE imply CMD_CPU imply SPL_CPU imply SPL_OPENSBI diff --git a/arch/riscv/cpu/jh7110/Kconfig b/arch/riscv/cpu/jh7110/Kconfig index 3f145415eb9..4d9581165bf 100644 --- a/arch/riscv/cpu/jh7110/Kconfig +++ b/arch/riscv/cpu/jh7110/Kconfig @@ -25,4 +25,4 @@ config STARFIVE_JH7110 imply SPL_CPU imply SPL_LOAD_FIT imply SPL_OPENSBI - imply SPL_SIFIVE_CLINT + imply SPL_RISCV_ACLINT diff --git a/arch/riscv/cpu/jh7110/spl.c b/arch/riscv/cpu/jh7110/spl.c index 104f0fe9497..72adcefa0e9 100644 --- a/arch/riscv/cpu/jh7110/spl.c +++ b/arch/riscv/cpu/jh7110/spl.c @@ -3,19 +3,49 @@ * Copyright (C) 2022 StarFive Technology Co., Ltd. * Author: Yanhong Wang<yanhong.wang@starfivetech.com> */ - +#include <common.h> +#include <asm/arch/eeprom.h> #include <asm/csr.h> #include <asm/sections.h> #include <dm.h> +#include <linux/sizes.h> #include <log.h> +#include <init.h> #define CSR_U74_FEATURE_DISABLE 0x7c1 #define L2_LIM_MEM_END 0x81FFFFFUL +DECLARE_GLOBAL_DATA_PTR; + +static bool check_ddr_size(phys_size_t size) +{ + switch (size) { + case SZ_2: + case SZ_4: + case SZ_8: + case SZ_16: + return true; + default: + return false; + } +} + int spl_soc_init(void) { int ret; struct udevice *dev; + phys_size_t size; + + ret = fdtdec_setup_mem_size_base(); + if (ret) + return ret; + + /* Read the definition of the DDR size from eeprom, and if not, + * use the definition in DT + */ + size = (get_ddr_size_from_eeprom() >> 16) & 0xFF; + if (check_ddr_size(size)) + gd->ram_size = size << 30; /* DDR init */ ret = uclass_get_device(UCLASS_RAM, 0, &dev); diff --git a/arch/riscv/dts/Makefile b/arch/riscv/dts/Makefile index 1d61eb80205..f1525cb6680 100644 --- a/arch/riscv/dts/Makefile +++ b/arch/riscv/dts/Makefile @@ -7,8 +7,8 @@ dtb-$(CONFIG_TARGET_OPENPITON_RISCV64) += openpiton-riscv64.dtb dtb-$(CONFIG_TARGET_SIFIVE_UNLEASHED) += hifive-unleashed-a00.dtb dtb-$(CONFIG_TARGET_SIFIVE_UNMATCHED) += hifive-unmatched-a00.dtb dtb-$(CONFIG_TARGET_SIPEED_MAIX) += k210-maix-bit.dtb -dtb-$(CONFIG_TARGET_STARFIVE_VISIONFIVE2) += jh7110-starfive-visionfive-2-v1.3b.dtb -dtb-$(CONFIG_TARGET_STARFIVE_VISIONFIVE2) += jh7110-starfive-visionfive-2-v1.2a.dtb +dtb-$(CONFIG_TARGET_STARFIVE_VISIONFIVE2) += jh7110-starfive-visionfive-2.dtb +dtb-$(CONFIG_TARGET_TH1520_LPI4A) += th1520-lichee-pi-4a.dtb include $(srctree)/scripts/Makefile.dts targets += $(dtb-y) diff --git a/arch/riscv/dts/jh7110-starfive-visionfive-2-v1.3b-u-boot.dtsi b/arch/riscv/dts/jh7110-starfive-visionfive-2-u-boot.dtsi index 3c322c5c972..13f69da31ec 100644 --- a/arch/riscv/dts/jh7110-starfive-visionfive-2-v1.3b-u-boot.dtsi +++ b/arch/riscv/dts/jh7110-starfive-visionfive-2-u-boot.dtsi @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR MIT /* - * Copyright (C) 2022 StarFive Technology Co., Ltd. + * Copyright (C) 2023 StarFive Technology Co., Ltd. */ #include "binman.dtsi" @@ -67,3 +67,40 @@ }; }; +&i2c5_pins { + bootph-pre-ram; + i2c-pins { + bootph-pre-ram; + }; +}; + +&i2c5 { + bootph-pre-ram; + eeprom@50 { + bootph-pre-ram; + }; +}; + +&binman { + itb { + fit { + images { + fdt-1 { + description = "NAME"; + load = <0x40400000>; + compression = "none"; + + uboot_fdt_blob: blob-ext { + filename = "u-boot.dtb"; + }; + }; + }; + + configurations { + conf-1 { + fdt = "fdt-1"; + }; + }; + }; + }; +}; diff --git a/arch/riscv/dts/jh7110-starfive-visionfive-2-v1.2a-u-boot.dtsi b/arch/riscv/dts/jh7110-starfive-visionfive-2-v1.2a-u-boot.dtsi deleted file mode 100644 index 3c322c5c972..00000000000 --- a/arch/riscv/dts/jh7110-starfive-visionfive-2-v1.2a-u-boot.dtsi +++ /dev/null @@ -1,69 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 OR MIT -/* - * Copyright (C) 2022 StarFive Technology Co., Ltd. - */ - -#include "binman.dtsi" -#include "jh7110-u-boot.dtsi" -/ { - chosen { - bootph-pre-ram; - }; - - firmware { - spi0 = &qspi; - bootph-pre-ram; - }; - - config { - bootph-pre-ram; - u-boot,spl-payload-offset = <0x100000>; - }; - - memory@40000000 { - bootph-pre-ram; - }; -}; - -&uart0 { - bootph-pre-ram; -}; - -&mmc0 { - bootph-pre-ram; -}; - -&mmc1 { - bootph-pre-ram; -}; - -&qspi { - bootph-pre-ram; - - nor-flash@0 { - bootph-pre-ram; - }; -}; - -&sysgpio { - bootph-pre-ram; -}; - -&mmc0_pins { - bootph-pre-ram; - mmc0-pins-rest { - bootph-pre-ram; - }; -}; - -&mmc1_pins { - bootph-pre-ram; - mmc1-pins0 { - bootph-pre-ram; - }; - - mmc1-pins1 { - bootph-pre-ram; - }; -}; - diff --git a/arch/riscv/dts/jh7110-starfive-visionfive-2-v1.2a.dts b/arch/riscv/dts/jh7110-starfive-visionfive-2-v1.2a.dts deleted file mode 100644 index b9d26d7af7c..00000000000 --- a/arch/riscv/dts/jh7110-starfive-visionfive-2-v1.2a.dts +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 OR MIT -/* - * Copyright (C) 2022 StarFive Technology Co., Ltd. - */ - -/dts-v1/; -#include "jh7110-starfive-visionfive-2.dtsi" - -/ { - model = "StarFive VisionFive 2 v1.2A"; - compatible = "starfive,visionfive-2-v1.2a", "starfive,jh7110"; -}; diff --git a/arch/riscv/dts/jh7110-starfive-visionfive-2-v1.3b.dts b/arch/riscv/dts/jh7110-starfive-visionfive-2.dts index 3b3b3453a17..288ea394939 100644 --- a/arch/riscv/dts/jh7110-starfive-visionfive-2-v1.3b.dts +++ b/arch/riscv/dts/jh7110-starfive-visionfive-2.dts @@ -1,12 +1,11 @@ // SPDX-License-Identifier: GPL-2.0 OR MIT /* - * Copyright (C) 2022 StarFive Technology Co., Ltd. + * Copyright (C) 2023 StarFive Technology Co., Ltd. */ /dts-v1/; #include "jh7110-starfive-visionfive-2.dtsi" / { - model = "StarFive VisionFive 2 v1.3B"; compatible = "starfive,visionfive-2-v1.3b", "starfive,jh7110"; }; diff --git a/arch/riscv/dts/jh7110-starfive-visionfive-2.dtsi b/arch/riscv/dts/jh7110-starfive-visionfive-2.dtsi index c6b6dfa9407..710b082766d 100644 --- a/arch/riscv/dts/jh7110-starfive-visionfive-2.dtsi +++ b/arch/riscv/dts/jh7110-starfive-visionfive-2.dtsi @@ -17,6 +17,8 @@ i2c2 = &i2c2; i2c5 = &i2c5; i2c6 = &i2c6; + ethernet0 = &gmac0; + ethernet1 = &gmac1; }; chosen { @@ -118,6 +120,12 @@ pinctrl-names = "default"; pinctrl-0 = <&i2c5_pins>; status = "okay"; + + eeprom@50 { + compatible = "atmel,24c04"; + reg = <0x50>; + pagesize = <16>; + }; }; &i2c6 { @@ -317,3 +325,35 @@ assigned-clock-parents = <&osc>; assigned-clock-rates = <0>; }; + +&gmac0 { + phy-handle = <&phy0>; + phy-mode = "rgmii-id"; + status = "okay"; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + compatible = "snps,dwmac-mdio"; + + phy0: ethernet-phy@0 { + reg = <0>; + }; + }; +}; + +&gmac1 { + phy-handle = <&phy1>; + phy-mode = "rgmii-id"; + status = "okay"; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + compatible = "snps,dwmac-mdio"; + + phy1: ethernet-phy@1 { + reg = <0>; + }; + }; +}; diff --git a/arch/riscv/dts/jh7110.dtsi b/arch/riscv/dts/jh7110.dtsi index bd60879615a..58e332e9d71 100644 --- a/arch/riscv/dts/jh7110.dtsi +++ b/arch/riscv/dts/jh7110.dtsi @@ -235,6 +235,13 @@ #clock-cells = <0>; }; + stmmac_axi_setup: stmmac-axi-config { + snps,lpi_en; + snps,wr_osr_lmt = <4>; + snps,rd_osr_lmt = <4>; + snps,blen = <256 128 64 32 0 0 0>; + }; + soc { compatible = "simple-bus"; interrupt-parent = <&plic>; @@ -539,6 +546,68 @@ status = "disabled"; }; + gmac0: ethernet@16030000 { + compatible = "starfive,jh7110-dwmac", "snps,dwmac-5.20"; + reg = <0x0 0x16030000 0x0 0x10000>; + clocks = <&aoncrg JH7110_AONCLK_GMAC0_AXI>, + <&aoncrg JH7110_AONCLK_GMAC0_AHB>, + <&syscrg JH7110_SYSCLK_GMAC0_PTP>, + <&aoncrg JH7110_AONCLK_GMAC0_TX_INV>, + <&syscrg JH7110_SYSCLK_GMAC0_GTXC>; + clock-names = "stmmaceth", "pclk", "ptp_ref", + "tx", "gtx"; + resets = <&aoncrg JH7110_AONRST_GMAC0_AXI>, + <&aoncrg JH7110_AONRST_GMAC0_AHB>; + reset-names = "stmmaceth", "ahb"; + interrupts = <7>, <6>, <5>; + interrupt-names = "macirq", "eth_wake_irq", "eth_lpi"; + snps,multicast-filter-bins = <64>; + snps,perfect-filter-entries = <8>; + rx-fifo-depth = <2048>; + tx-fifo-depth = <2048>; + snps,fixed-burst; + snps,no-pbl-x8; + snps,force_thresh_dma_mode; + snps,axi-config = <&stmmac_axi_setup>; + snps,tso; + snps,en-tx-lpi-clockgating; + snps,txpbl = <16>; + snps,rxpbl = <16>; + starfive,syscon = <&aon_syscon 0xc 0x12>; + status = "disabled"; + }; + + gmac1: ethernet@16040000 { + compatible = "starfive,jh7110-dwmac", "snps,dwmac-5.20"; + reg = <0x0 0x16040000 0x0 0x10000>; + clocks = <&syscrg JH7110_SYSCLK_GMAC1_AXI>, + <&syscrg JH7110_SYSCLK_GMAC1_AHB>, + <&syscrg JH7110_SYSCLK_GMAC1_PTP>, + <&syscrg JH7110_SYSCLK_GMAC1_TX_INV>, + <&syscrg JH7110_SYSCLK_GMAC1_GTXC>; + clock-names = "stmmaceth", "pclk", "ptp_ref", + "tx", "gtx"; + resets = <&syscrg JH7110_SYSRST_GMAC1_AXI>, + <&syscrg JH7110_SYSRST_GMAC1_AHB>; + reset-names = "stmmaceth", "ahb"; + interrupts = <78>, <77>, <76>; + interrupt-names = "macirq", "eth_wake_irq", "eth_lpi"; + snps,multicast-filter-bins = <64>; + snps,perfect-filter-entries = <8>; + rx-fifo-depth = <2048>; + tx-fifo-depth = <2048>; + snps,fixed-burst; + snps,no-pbl-x8; + snps,force_thresh_dma_mode; + snps,axi-config = <&stmmac_axi_setup>; + snps,tso; + snps,en-tx-lpi-clockgating; + snps,txpbl = <16>; + snps,rxpbl = <16>; + starfive,syscon = <&sys_syscon 0x90 0x2>; + status = "disabled"; + }; + aoncrg: clock-controller@17000000 { compatible = "starfive,jh7110-aoncrg"; reg = <0x0 0x17000000 0x0 0x10000>; diff --git a/arch/riscv/dts/th1520-lichee-module-4a.dtsi b/arch/riscv/dts/th1520-lichee-module-4a.dtsi new file mode 100644 index 00000000000..dc00e3dfa02 --- /dev/null +++ b/arch/riscv/dts/th1520-lichee-module-4a.dtsi @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2023 Jisheng Zhang <jszhang@kernel.org> + */ + +/dts-v1/; + +#include "th1520.dtsi" + +/ { + model = "Sipeed Lichee Module 4A"; + compatible = "sipeed,lichee-module-4a", "thead,th1520"; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x00000000 0x2 0x00000000>; + }; +}; + +&osc { + clock-frequency = <24000000>; +}; + +&osc_32k { + clock-frequency = <32768>; +}; + +&apb_clk { + clock-frequency = <62500000>; +}; + +&uart_sclk { + clock-frequency = <100000000>; +}; diff --git a/arch/riscv/dts/th1520-lichee-pi-4a.dts b/arch/riscv/dts/th1520-lichee-pi-4a.dts new file mode 100644 index 00000000000..a1248b2ee3a --- /dev/null +++ b/arch/riscv/dts/th1520-lichee-pi-4a.dts @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2023 Jisheng Zhang <jszhang@kernel.org> + */ + +#include "th1520-lichee-module-4a.dtsi" + +/ { + model = "Sipeed Lichee Pi 4A"; + compatible = "sipeed,lichee-pi-4a", "sipeed,lichee-module-4a", "thead,th1520"; + + aliases { + gpio0 = &gpio0; + gpio1 = &gpio1; + gpio2 = &gpio2; + gpio3 = &gpio3; + serial0 = &uart0; + serial1 = &uart1; + serial2 = &uart2; + serial3 = &uart3; + serial4 = &uart4; + serial5 = &uart5; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; + +&uart0 { + status = "okay"; +}; diff --git a/arch/riscv/dts/th1520.dtsi b/arch/riscv/dts/th1520.dtsi new file mode 100644 index 00000000000..f7bfa422439 --- /dev/null +++ b/arch/riscv/dts/th1520.dtsi @@ -0,0 +1,406 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2021 Alibaba Group Holding Limited. + * Copyright (C) 2023 Jisheng Zhang <jszhang@kernel.org> + */ + +#include <dt-bindings/interrupt-controller/irq.h> + +/ { + compatible = "thead,th1520"; + #address-cells = <2>; + #size-cells = <2>; + + cpus: cpus { + #address-cells = <1>; + #size-cells = <0>; + timebase-frequency = <3000000>; + + c910_0: cpu@0 { + compatible = "thead,c910", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + reg = <0>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache>; + mmu-type = "riscv,sv39"; + + cpu0_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + c910_1: cpu@1 { + compatible = "thead,c910", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + reg = <1>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache>; + mmu-type = "riscv,sv39"; + + cpu1_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + c910_2: cpu@2 { + compatible = "thead,c910", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + reg = <2>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache>; + mmu-type = "riscv,sv39"; + + cpu2_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + c910_3: cpu@3 { + compatible = "thead,c910", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + reg = <3>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache>; + mmu-type = "riscv,sv39"; + + cpu3_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + l2_cache: l2-cache { + compatible = "cache"; + cache-block-size = <64>; + cache-level = <2>; + cache-size = <1048576>; + cache-sets = <1024>; + cache-unified; + }; + }; + + osc: oscillator { + compatible = "fixed-clock"; + clock-output-names = "osc_24m"; + #clock-cells = <0>; + }; + + osc_32k: 32k-oscillator { + compatible = "fixed-clock"; + clock-output-names = "osc_32k"; + #clock-cells = <0>; + }; + + apb_clk: apb-clk-clock { + compatible = "fixed-clock"; + clock-output-names = "apb_clk"; + #clock-cells = <0>; + }; + + uart_sclk: uart-sclk-clock { + compatible = "fixed-clock"; + clock-output-names = "uart_sclk"; + #clock-cells = <0>; + }; + + soc { + compatible = "simple-bus"; + interrupt-parent = <&plic>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + plic: interrupt-controller@ffd8000000 { + compatible = "thead,th1520-plic", "thead,c900-plic"; + reg = <0xff 0xd8000000 0x0 0x01000000>; + interrupts-extended = <&cpu0_intc 11>, <&cpu0_intc 9>, + <&cpu1_intc 11>, <&cpu1_intc 9>, + <&cpu2_intc 11>, <&cpu2_intc 9>, + <&cpu3_intc 11>, <&cpu3_intc 9>; + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <2>; + riscv,ndev = <240>; + }; + + clint: timer@ffdc000000 { + compatible = "thead,th1520-clint", "thead,c900-clint"; + reg = <0xff 0xdc000000 0x0 0x00010000>; + interrupts-extended = <&cpu0_intc 3>, <&cpu0_intc 7>, + <&cpu1_intc 3>, <&cpu1_intc 7>, + <&cpu2_intc 3>, <&cpu2_intc 7>, + <&cpu3_intc 3>, <&cpu3_intc 7>; + }; + + uart0: serial@ffe7014000 { + compatible = "snps,dw-apb-uart"; + reg = <0xff 0xe7014000 0x0 0x100>; + interrupts = <36 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&uart_sclk>; + reg-shift = <2>; + reg-io-width = <4>; + status = "disabled"; + }; + + uart1: serial@ffe7f00000 { + compatible = "snps,dw-apb-uart"; + reg = <0xff 0xe7f00000 0x0 0x100>; + interrupts = <37 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&uart_sclk>; + reg-shift = <2>; + reg-io-width = <4>; + status = "disabled"; + }; + + uart3: serial@ffe7f04000 { + compatible = "snps,dw-apb-uart"; + reg = <0xff 0xe7f04000 0x0 0x100>; + interrupts = <39 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&uart_sclk>; + reg-shift = <2>; + reg-io-width = <4>; + status = "disabled"; + }; + + gpio2: gpio@ffe7f34000 { + compatible = "snps,dw-apb-gpio"; + reg = <0xff 0xe7f34000 0x0 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + + portc: gpio-controller@0 { + compatible = "snps,dw-apb-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <32>; + reg = <0>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = <58 IRQ_TYPE_LEVEL_HIGH>; + }; + }; + + gpio3: gpio@ffe7f38000 { + compatible = "snps,dw-apb-gpio"; + reg = <0xff 0xe7f38000 0x0 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + + portd: gpio-controller@0 { + compatible = "snps,dw-apb-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <32>; + reg = <0>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = <59 IRQ_TYPE_LEVEL_HIGH>; + }; + }; + + gpio0: gpio@ffec005000 { + compatible = "snps,dw-apb-gpio"; + reg = <0xff 0xec005000 0x0 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + + porta: gpio-controller@0 { + compatible = "snps,dw-apb-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <32>; + reg = <0>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = <56 IRQ_TYPE_LEVEL_HIGH>; + }; + }; + + gpio1: gpio@ffec006000 { + compatible = "snps,dw-apb-gpio"; + reg = <0xff 0xec006000 0x0 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + + portb: gpio-controller@0 { + compatible = "snps,dw-apb-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <32>; + reg = <0>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = <57 IRQ_TYPE_LEVEL_HIGH>; + }; + }; + + uart2: serial@ffec010000 { + compatible = "snps,dw-apb-uart"; + reg = <0xff 0xec010000 0x0 0x4000>; + interrupts = <38 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&uart_sclk>; + reg-shift = <2>; + reg-io-width = <4>; + status = "disabled"; + }; + + timer0: timer@ffefc32000 { + compatible = "snps,dw-apb-timer"; + reg = <0xff 0xefc32000 0x0 0x14>; + clocks = <&apb_clk>; + clock-names = "timer"; + interrupts = <16 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + timer1: timer@ffefc32014 { + compatible = "snps,dw-apb-timer"; + reg = <0xff 0xefc32014 0x0 0x14>; + clocks = <&apb_clk>; + clock-names = "timer"; + interrupts = <17 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + timer2: timer@ffefc32028 { + compatible = "snps,dw-apb-timer"; + reg = <0xff 0xefc32028 0x0 0x14>; + clocks = <&apb_clk>; + clock-names = "timer"; + interrupts = <18 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + timer3: timer@ffefc3203c { + compatible = "snps,dw-apb-timer"; + reg = <0xff 0xefc3203c 0x0 0x14>; + clocks = <&apb_clk>; + clock-names = "timer"; + interrupts = <19 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + uart4: serial@fff7f08000 { + compatible = "snps,dw-apb-uart"; + reg = <0xff 0xf7f08000 0x0 0x4000>; + interrupts = <40 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&uart_sclk>; + reg-shift = <2>; + reg-io-width = <4>; + status = "disabled"; + }; + + uart5: serial@fff7f0c000 { + compatible = "snps,dw-apb-uart"; + reg = <0xff 0xf7f0c000 0x0 0x4000>; + interrupts = <41 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&uart_sclk>; + reg-shift = <2>; + reg-io-width = <4>; + status = "disabled"; + }; + + timer4: timer@ffffc33000 { + compatible = "snps,dw-apb-timer"; + reg = <0xff 0xffc33000 0x0 0x14>; + clocks = <&apb_clk>; + clock-names = "timer"; + interrupts = <20 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + timer5: timer@ffffc33014 { + compatible = "snps,dw-apb-timer"; + reg = <0xff 0xffc33014 0x0 0x14>; + clocks = <&apb_clk>; + clock-names = "timer"; + interrupts = <21 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + timer6: timer@ffffc33028 { + compatible = "snps,dw-apb-timer"; + reg = <0xff 0xffc33028 0x0 0x14>; + clocks = <&apb_clk>; + clock-names = "timer"; + interrupts = <22 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + timer7: timer@ffffc3303c { + compatible = "snps,dw-apb-timer"; + reg = <0xff 0xffc3303c 0x0 0x14>; + clocks = <&apb_clk>; + clock-names = "timer"; + interrupts = <23 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + ao_gpio0: gpio@fffff41000 { + compatible = "snps,dw-apb-gpio"; + reg = <0xff 0xfff41000 0x0 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + + porte: gpio-controller@0 { + compatible = "snps,dw-apb-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <32>; + reg = <0>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = <76 IRQ_TYPE_LEVEL_HIGH>; + }; + }; + + ao_gpio1: gpio@fffff52000 { + compatible = "snps,dw-apb-gpio"; + reg = <0xff 0xfff52000 0x0 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + + portf: gpio-controller@0 { + compatible = "snps,dw-apb-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <32>; + reg = <0>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = <55 IRQ_TYPE_LEVEL_HIGH>; + }; + }; + }; +}; diff --git a/arch/riscv/include/asm/arch-jh7110/eeprom.h b/arch/riscv/include/asm/arch-jh7110/eeprom.h new file mode 100644 index 00000000000..f354d5c60cd --- /dev/null +++ b/arch/riscv/include/asm/arch-jh7110/eeprom.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2023 StarFive Technology Co., Ltd. + * Author: Yanhong Wang<yanhong.wang@starfivetech.com> + */ + +#ifndef _ASM_RISCV_EEPROM_H +#define _ASM_RISCV_EEPROM_H + +u8 get_pcb_revision_from_eeprom(void); +u32 get_ddr_size_from_eeprom(void); + +#endif /* _ASM_RISCV_EEPROM_H */ diff --git a/arch/riscv/include/asm/global_data.h b/arch/riscv/include/asm/global_data.h index 31ba72693d7..9d97517e124 100644 --- a/arch/riscv/include/asm/global_data.h +++ b/arch/riscv/include/asm/global_data.h @@ -18,8 +18,8 @@ struct arch_global_data { long boot_hart; /* boot hart id */ phys_addr_t firmware_fdt_addr; -#if CONFIG_IS_ENABLED(SIFIVE_CLINT) - void __iomem *clint; /* clint base address */ +#if CONFIG_IS_ENABLED(RISCV_ACLINT) + void __iomem *aclint; /* aclint base address */ #endif #ifdef CONFIG_ANDES_PLICSW void __iomem *plicsw; /* andes plicsw base address */ diff --git a/arch/riscv/include/asm/syscon.h b/arch/riscv/include/asm/syscon.h index f2b37975f37..5787702e746 100644 --- a/arch/riscv/include/asm/syscon.h +++ b/arch/riscv/include/asm/syscon.h @@ -12,7 +12,7 @@ */ enum { RISCV_NONE, - RISCV_SYSCON_CLINT, /* Core Local Interruptor (CLINT) */ + RISCV_SYSCON_ACLINT, /* Advanced Core Local Interruptor (ACLINT) */ RISCV_SYSCON_PLICSW, /* Andes PLICSW */ }; diff --git a/arch/riscv/lib/Makefile b/arch/riscv/lib/Makefile index e5a81ba7223..02c4d8fcc6c 100644 --- a/arch/riscv/lib/Makefile +++ b/arch/riscv/lib/Makefile @@ -12,7 +12,7 @@ obj-$(CONFIG_CMD_GO) += boot.o obj-y += cache.o obj-$(CONFIG_SIFIVE_CACHE) += sifive_cache.o ifeq ($(CONFIG_$(SPL_)RISCV_MMODE),y) -obj-$(CONFIG_$(SPL_)SIFIVE_CLINT) += sifive_clint.o +obj-$(CONFIG_$(SPL_)RISCV_ACLINT) += aclint_ipi.o obj-$(CONFIG_ANDES_PLICSW) += andes_plicsw.o else obj-$(CONFIG_SBI) += sbi.o diff --git a/arch/riscv/lib/sifive_clint.c b/arch/riscv/lib/aclint_ipi.c index ab22395c552..90b8e128cb1 100644 --- a/arch/riscv/lib/sifive_clint.c +++ b/arch/riscv/lib/aclint_ipi.c @@ -10,9 +10,12 @@ #include <common.h> #include <dm.h> +#include <regmap.h> +#include <syscon.h> #include <asm/global_data.h> #include <asm/io.h> #include <asm/smp.h> +#include <asm/syscon.h> #include <linux/err.h> /* MSIP registers */ @@ -26,12 +29,16 @@ int riscv_init_ipi(void) struct udevice *dev; ret = uclass_get_device_by_driver(UCLASS_TIMER, - DM_DRIVER_GET(sifive_clint), &dev); + DM_DRIVER_GET(riscv_aclint_timer), &dev); if (ret) return ret; - gd->arch.clint = dev_read_addr_ptr(dev); - if (!gd->arch.clint) + if (dev_get_driver_data(dev) != 0) + gd->arch.aclint = dev_read_addr_ptr(dev); + else + gd->arch.aclint = syscon_get_first_range(RISCV_SYSCON_ACLINT); + + if (!gd->arch.aclint) return -EINVAL; return 0; @@ -39,21 +46,33 @@ int riscv_init_ipi(void) int riscv_send_ipi(int hart) { - writel(1, (void __iomem *)MSIP_REG(gd->arch.clint, hart)); + writel(1, (void __iomem *)MSIP_REG(gd->arch.aclint, hart)); return 0; } int riscv_clear_ipi(int hart) { - writel(0, (void __iomem *)MSIP_REG(gd->arch.clint, hart)); + writel(0, (void __iomem *)MSIP_REG(gd->arch.aclint, hart)); return 0; } int riscv_get_ipi(int hart, int *pending) { - *pending = readl((void __iomem *)MSIP_REG(gd->arch.clint, hart)); + *pending = readl((void __iomem *)MSIP_REG(gd->arch.aclint, hart)); return 0; } + +static const struct udevice_id riscv_aclint_swi_ids[] = { + { .compatible = "riscv,aclint-mswi", .data = RISCV_SYSCON_ACLINT }, + { } +}; + +U_BOOT_DRIVER(riscv_aclint_swi) = { + .name = "riscv_aclint_swi", + .id = UCLASS_SYSCON, + .of_match = riscv_aclint_swi_ids, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/arch/sandbox/cpu/sdl.c b/arch/sandbox/cpu/sdl.c index 2c570ed8d16..590e406517b 100644 --- a/arch/sandbox/cpu/sdl.c +++ b/arch/sandbox/cpu/sdl.c @@ -6,6 +6,7 @@ #include <errno.h> #include <unistd.h> #include <stdbool.h> +#include <sysreset.h> #include <linux/input.h> #include <SDL2/SDL.h> #include <asm/state.h> @@ -81,7 +82,7 @@ static void sandbox_sdl_poll_events(void) switch (event.type) { case SDL_QUIT: puts("LCD window closed - quitting\n"); - reset_cpu(); + sysreset_walk(SYSRESET_POWER_OFF); break; } } diff --git a/arch/sandbox/dts/cedit.dtsi b/arch/sandbox/dts/cedit.dtsi new file mode 100644 index 00000000000..a9eb4c2d594 --- /dev/null +++ b/arch/sandbox/dts/cedit.dtsi @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Expo definition for the configuration editor + * + * This used for testing building an expo from a data file. This devicetree + * provides a description of the objects to be created. + */ + +#include <test/cedit-test.h> + +&cedit { + dynamic-start = <ID_DYNAMIC_START>; + + scenes { + main { + id = <ID_SCENE1>; + + /* value refers to the matching id in /strings */ + title-id = <ID_SCENE1_TITLE>; + + /* simple string is used as it is */ + prompt = "UP and DOWN to choose, ENTER to select"; + + /* defines a menu within the scene */ + cpu-speed { + type = "menu"; + id = <ID_CPU_SPEED>; + + /* + * has both string and ID. The string is ignored + * if the ID is present and points to a string + */ + title = "CPU speed"; + title-id = <ID_CPU_SPEED_TITLE>; + + /* menu items as simple strings */ + item-label = "2 GHz", "2.5 GHz", "3 GHz"; + + /* IDs for the menu items */ + item-id = <ID_CPU_SPEED_1 ID_CPU_SPEED_2 + ID_CPU_SPEED_3>; + }; + + power-loss { + type = "menu"; + id = <ID_POWER_LOSS>; + + title = "AC Power"; + item-label = "Always Off", "Always On", + "Memory"; + + item-id = <ID_AC_OFF ID_AC_ON ID_AC_MEMORY>; + }; + }; + }; + + strings { + title { + id = <ID_SCENE1_TITLE>; + value = "Test Configuration"; + value-es = "configuración de prueba"; + }; + }; +}; diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi index 30a305c4d20..f0ee0b3481a 100644 --- a/arch/sandbox/dts/sandbox.dtsi +++ b/arch/sandbox/dts/sandbox.dtsi @@ -16,6 +16,12 @@ stdout-path = "/serial"; }; + cedit-theme { + font-size = <30>; + menu-inset = <3>; + menuitem-gap-y = <1>; + }; + alarm_wdt: alarm-wdt { compatible = "sandbox,alarm-wdt"; timeout-sec = <5>; diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index ff9f9222e6f..b5509eee8cf 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -96,6 +96,8 @@ theme { font-size = <30>; + menu-inset = <3>; + menuitem-gap-y = <1>; }; /* @@ -139,6 +141,15 @@ }; }; + cedit: cedit { + }; + + cedit-theme { + font-size = <30>; + menu-inset = <3>; + menuitem-gap-y = <1>; + }; + fuzzing-engine { compatible = "sandbox,fuzzing-engine"; }; @@ -1828,3 +1839,5 @@ #ifdef CONFIG_SANDBOX_VPL #include "sandbox_vpl.dtsi" #endif + +#include "cedit.dtsi" diff --git a/board/advantech/imx8qm_dmsse20_a1/spl.c b/board/advantech/imx8qm_dmsse20_a1/spl.c index 7f2e972425b..f36caece7d7 100644 --- a/board/advantech/imx8qm_dmsse20_a1/spl.c +++ b/board/advantech/imx8qm_dmsse20_a1/spl.c @@ -111,7 +111,7 @@ int board_mmc_init(struct bd_info *bis) switch (i) { case 0: ret = sc_pm_set_resource_power_mode(-1, SC_R_SDHC_0, SC_PM_PW_MODE_ON); - if (ret != SC_ERR_NONE) + if (ret) return ret; imx8_iomux_setup_multiple_pads(emmc0, ARRAY_SIZE(emmc0)); @@ -120,10 +120,10 @@ int board_mmc_init(struct bd_info *bis) break; case 1: ret = sc_pm_set_resource_power_mode(-1, SC_R_SDHC_2, SC_PM_PW_MODE_ON); - if (ret != SC_ERR_NONE) + if (ret) return ret; ret = sc_pm_set_resource_power_mode(-1, SC_R_GPIO_4, SC_PM_PW_MODE_ON); - if (ret != SC_ERR_NONE) + if (ret) return ret; imx8_iomux_setup_multiple_pads(usdhc2_sd, ARRAY_SIZE(usdhc2_sd)); diff --git a/board/advantech/imx8qm_rom7720_a1/spl.c b/board/advantech/imx8qm_rom7720_a1/spl.c index b602437c35b..922bb0b7d43 100644 --- a/board/advantech/imx8qm_rom7720_a1/spl.c +++ b/board/advantech/imx8qm_rom7720_a1/spl.c @@ -112,7 +112,7 @@ int board_mmc_init(struct bd_info *bis) switch (i) { case 0: ret = sc_pm_set_resource_power_mode(-1, SC_R_SDHC_0, SC_PM_PW_MODE_ON); - if (ret != SC_ERR_NONE) + if (ret) return ret; imx8_iomux_setup_multiple_pads(emmc0, ARRAY_SIZE(emmc0)); @@ -121,10 +121,10 @@ int board_mmc_init(struct bd_info *bis) break; case 1: ret = sc_pm_set_resource_power_mode(-1, SC_R_SDHC_2, SC_PM_PW_MODE_ON); - if (ret != SC_ERR_NONE) + if (ret) return ret; ret = sc_pm_set_resource_power_mode(-1, SC_R_GPIO_4, SC_PM_PW_MODE_ON); - if (ret != SC_ERR_NONE) + if (ret) return ret; imx8_iomux_setup_multiple_pads(usdhc2_sd, ARRAY_SIZE(usdhc2_sd)); diff --git a/board/alliedtelesis/x240/MAINTAINERS b/board/alliedtelesis/x240/MAINTAINERS new file mode 100644 index 00000000000..f1f78d96167 --- /dev/null +++ b/board/alliedtelesis/x240/MAINTAINERS @@ -0,0 +1,7 @@ +X240 BOARD +M: Chris Packham <chris.packham@alliedtelesis.co.nz> +S: Maintained +F: board/alliedtelesis/x240/ +F: arch/arm/dts/ac5-98dx35xx-rd.dts +F: include/configs/x240.h +F: configs/x240_defconfig diff --git a/board/alliedtelesis/x240/Makefile b/board/alliedtelesis/x240/Makefile new file mode 100644 index 00000000000..7f20a47d6a7 --- /dev/null +++ b/board/alliedtelesis/x240/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2022 Allied Telesis +# + +obj-y += x240.o diff --git a/board/alliedtelesis/x240/x240.c b/board/alliedtelesis/x240/x240.c new file mode 100644 index 00000000000..0c4f8e03b85 --- /dev/null +++ b/board/alliedtelesis/x240/x240.c @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include <common.h> +#include <asm/global_data.h> + +DECLARE_GLOBAL_DATA_PTR; + +int board_init(void) +{ + gd->bd->bi_boot_params = CFG_SYS_SDRAM_BASE + 0x100; + + return 0; +} diff --git a/board/beacon/imx8mm/MAINTAINERS b/board/beacon/imx8mm/MAINTAINERS index e887db20a21..d48ba8605bb 100644 --- a/board/beacon/imx8mm/MAINTAINERS +++ b/board/beacon/imx8mm/MAINTAINERS @@ -5,3 +5,4 @@ S: Maintained F: board/beacon/imx8mm/ F: include/configs/imx8mm_beacon.h F: configs/imx8mm_beacon_defconfig +F: doc/board/beacon/ diff --git a/board/beacon/imx8mm/README b/board/beacon/imx8mm/README deleted file mode 100644 index 32b24bc03eb..00000000000 --- a/board/beacon/imx8mm/README +++ /dev/null @@ -1,37 +0,0 @@ -U-Boot for the Beacon EmbeddedWorks Devkit - -Quick Start -=========== -- Build the ARM Trusted firmware binary -- Get ddr firmware -- Build U-Boot -- Boot - -Get and Build the ARM Trusted firmware -====================================== -Note: $(srctree) is U-Boot source directory - -$ git clone https://github.com/nxp-imx/imx-atf -$ git lf-5.10.72-2.2.0 -$ make PLAT=imx8mm bl31 CROSS_COMPILE=aarch64-linux-gnu- -$ cp build/imx8mm/release/bl31.bin $(srctree) - -Get the DDR firmware -==================== -$ wget https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/firmware-imx-8.9.bin -$ chmod +x firmware-imx-8.9.bin -$ ./firmware-imx-8.9 -$ cp firmware-imx-8.9/firmware/ddr/synopsys/lpddr4*.bin $(srctree) - -Build U-Boot -============ -$ make imx8mm_beacon_defconfig -$ make CROSS_COMPILE=aarch64-linux-gnu- - -Burn U-Boot to microSD Card -=========================== -$ sudo dd if=flash.bin of=/dev/sd[x] bs=1024 seek=33 - -Boot -==== -Set Boot switch to SD boot diff --git a/board/beacon/imx8mm/imx8mm_beacon.env b/board/beacon/imx8mm/imx8mm_beacon.env new file mode 100644 index 00000000000..00bf67edd5b --- /dev/null +++ b/board/beacon/imx8mm/imx8mm_beacon.env @@ -0,0 +1,19 @@ +boot_fit=try +bootscript=echo Running bootscript from mmc ...; source +console=ttymxc1 +fdt_addr=0x45000000 +fdt_file=imx8mm-beacon-kit.dtb +finduuid=part uuid mmc ${mmcdev}:2 uuid +image=Image +initrd_addr=0x46000000 +loadbootscript=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script}; +loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdt_file} +loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image} +mmcargs=setenv bootargs console=${console},${baudrate} root=PARTUUID=${uuid} rootwait rw ${mtdparts} ${optargs} +mmcautodetect=yes +mmcboot=echo Booting from mmc ...; run finduuid; run mmcargs; if run loadfdt; then booti ${loadaddr} - ${fdt_addr}; else echo WARN: Cannot load the DT; fi; +netargs=setenv bootargs console=${console},${baudrate} root=/dev/nfs ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp +mmcdev=1 +mmcpart=1 +netboot=echo Booting from net ...; run netargs; if test ${ip_dyn} = yes; then setenv get_cmd dhcp; else setenv get_cmd tftp; fi; ${get_cmd} ${loadaddr} ${image}; if test ${boot_fit} = yes || test ${boot_fit} = try; then bootm ${loadaddr}; else if ${get_cmd} ${fdt_addr} ${fdt_file}; then booti ${loadaddr} - ${fdt_addr}; else echo WARN: Cannot load the DT; fi; fi; +script=boot.scr diff --git a/board/beacon/imx8mm/spl.c b/board/beacon/imx8mm/spl.c index a5f337aa17c..b2830c5223a 100644 --- a/board/beacon/imx8mm/spl.c +++ b/board/beacon/imx8mm/spl.c @@ -36,6 +36,8 @@ int spl_board_boot_device(enum boot_device boot_dev_spl) return BOOT_DEVICE_MMC2; case USB_BOOT: return BOOT_DEVICE_BOARD; + case QSPI_BOOT: + return BOOT_DEVICE_NOR; default: return BOOT_DEVICE_NONE; } @@ -46,6 +48,11 @@ static void spl_dram_init(void) ddr_init(&dram_timing); } +void spl_board_init(void) +{ + arch_misc_init(); +} + #ifdef CONFIG_SPL_LOAD_FIT int board_fit_config_name_match(const char *name) { diff --git a/board/beacon/imx8mn/README b/board/beacon/imx8mn/README deleted file mode 100644 index 49da03c8d83..00000000000 --- a/board/beacon/imx8mn/README +++ /dev/null @@ -1,38 +0,0 @@ -U-Boot for the Beacon EmbeddedWorks i.MX8M Nano Devkit - -Quick Start -=========== -- Build the ARM Trusted firmware binary -- Get ddr firmware -- Build U-Boot -- Boot - -Get and Build the ARM Trusted firmware -====================================== -Note: $(srctree) is U-Boot source directory - -$ git clone https://github.com/nxp-imx/imx-atf -$ git lf-5.10.72-2.2.0 -$ make PLAT=imx8mn bl31 CROSS_COMPILE=aarch64-linux-gnu- -$ cp build/imx8mn/release/bl31.bin $(srctree) - -Get the DDR firmware -==================== -$ wget https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/firmware-imx-8.9.bin -$ chmod +x firmware-imx-8.9.bin -$ ./firmware-imx-8.9 -$ cp firmware-imx-8.9/firmware/ddr/synopsys/lpddr4*.bin $(srctree) - -Build U-Boot -============ -$ make imx8mn_beacon_defconfig -$ make CROSS_COMPILE=aarch64-linux-gnu- - -Burn U-Boot to microSD Card -=========================== -$ sudo dd if=flash.bin of=/dev/sd[x] bs=1024 seek=32 - -Boot -==== -Set baseboard DIP switch: -S17: 1100XXXX diff --git a/board/beacon/imx8mn/imx8mn_beacon.env b/board/beacon/imx8mn/imx8mn_beacon.env new file mode 100644 index 00000000000..ca90053d477 --- /dev/null +++ b/board/beacon/imx8mn/imx8mn_beacon.env @@ -0,0 +1,25 @@ +boot_fdt=try +bootdelay=2 +bootscript=echo Running bootscript from mmc ...; source +console=ttymxc1 +fdt_addr=0x45000000 +fdt_file=imx8mn-beacon-kit.dtb +finduuid=part uuid mmc ${mmcdev}:2 uuid +image=Image +initrd_addr=0x46000000 +loadbootscript=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script}; +loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdt_file} +loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image} +loadramdisk=load mmc ${mmcdev} ${ramdisk_addr} ${ramdiskimage} +mmcargs=setenv bootargs console=${console},${baudrate} root=PARTUUID=${uuid} rootwait rw ${mtdparts} ${optargs} +mmcautodetect=yes +mmcboot=echo Booting from mmc ...; run finduuid; run mmcargs; if test ${boot_fdt} = yes || test ${boot_fdt} = try; then if run loadfdt; then booti ${loadaddr} - ${fdt_addr}; else echo WARN: Cannot load the DT; fi; else echo wait for boot; fi; +mmcdev=1 +mmcpart=1 +netargs=setenv bootargs console=${console},${baudrate} root=/dev/nfs ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp +netboot=echo Booting from net ...; run netargs; if test ${ip_dyn} = yes; then setenv get_cmd dhcp; else setenv get_cmd tftp; fi; ${get_cmd} ${loadaddr} ${image}; if test ${boot_fdt} = yes || test ${boot_fdt} = try; then if ${get_cmd} ${fdt_addr} ${fdt_file}; then booti ${loadaddr} - ${fdt_addr}; else echo WARN: Cannot load the DT; fi; else booti; fi; +ramargs=setenv bootargs console=${console},${baudrate} root=/dev/ram rw ${optargs} +ramboot=echo Booting from RAMdisk...; run loadimage; run loadfdt; fdt addr $fdt_addr; run loadramdisk; run ramargs; booti ${loadaddr} ${ramdisk_addr} ${fdt_addr} ${optargs} +ramdisk_addr=0x46000000 +ramdiskimage=rootfs.cpio.uboot +script=boot.scr diff --git a/board/congatec/cgtqmx8/cgtqmx8.c b/board/congatec/cgtqmx8/cgtqmx8.c index bedd1e03308..26189ff66f5 100644 --- a/board/congatec/cgtqmx8/cgtqmx8.c +++ b/board/congatec/cgtqmx8/cgtqmx8.c @@ -79,7 +79,7 @@ static void setup_iomux_uart(void) int board_early_init_f(void) { /* sc_ipc_t ipcHndl = 0; */ - sc_err_t scierr = 0; + int scierr; /* When start u-boot in XEN VM, directly return */ /* if (IS_ENABLED(CONFIG_XEN)) */ @@ -89,19 +89,19 @@ int board_early_init_f(void) /* Power up UART0, this is very early while power domain is not working */ scierr = sc_pm_set_resource_power_mode(-1, SC_R_UART_0, SC_PM_PW_MODE_ON); - if (scierr != SC_ERR_NONE) + if (scierr) return 0; /* Set UART0 clock root to 80 MHz */ sc_pm_clock_rate_t rate = 80000000; scierr = sc_pm_set_clock_rate(-1, SC_R_UART_0, 2, &rate); - if (scierr != SC_ERR_NONE) + if (scierr) return 0; /* Enable UART0 clock root */ scierr = sc_pm_clock_enable(-1, SC_R_UART_0, 2, true, false); - if (scierr != SC_ERR_NONE) + if (scierr) return 0; setup_iomux_uart(); diff --git a/board/data_modul/imx8mp_edm_sbc/spl.c b/board/data_modul/imx8mp_edm_sbc/spl.c index c30185e48d4..2fdd95a730c 100644 --- a/board/data_modul/imx8mp_edm_sbc/spl.c +++ b/board/data_modul/imx8mp_edm_sbc/spl.c @@ -107,6 +107,20 @@ void board_boot_order(u32 *spl_boot_list) spl_boot_list[4] = BOOT_DEVICE_NONE; } +unsigned long spl_mmc_get_uboot_raw_sector(struct mmc *mmc, unsigned long sect) +{ + const u32 boot_dev = spl_boot_device(); + int part; + + if (boot_dev == BOOT_DEVICE_MMC2) { /* eMMC */ + part = spl_mmc_emmc_boot_partition(mmc); + if (part == 1 || part == 2) /* eMMC BOOT1/BOOT2 HW partitions */ + return sect - 0x40; + } + + return sect; +} + static struct dram_timing_info *dram_timing_info[8] = { &dmo_imx8mp_sbc_dram_timing_32_32, /* 32 Gbit x32 */ NULL, /* 32 Gbit x16 */ diff --git a/board/freescale/imx8ulp_evk/spl.c b/board/freescale/imx8ulp_evk/spl.c index a0dad5f9831..66d0f68cc62 100644 --- a/board/freescale/imx8ulp_evk/spl.c +++ b/board/freescale/imx8ulp_evk/spl.c @@ -19,7 +19,7 @@ #include <asm/arch/ddr.h> #include <asm/arch/rdc.h> #include <asm/arch/upower.h> -#include <asm/mach-imx/s400_api.h> +#include <asm/mach-imx/ele_api.h> DECLARE_GLOBAL_DATA_PTR; @@ -63,9 +63,9 @@ void display_ele_fw_version(void) u32 fw_version, sha1, res; int ret; - ret = ahab_get_fw_version(&fw_version, &sha1, &res); + ret = ele_get_fw_version(&fw_version, &sha1, &res); if (ret) { - printf("ahab get firmware version failed %d, 0x%x\n", ret, res); + printf("ele get firmware version failed %d, 0x%x\n", ret, res); } else { printf("ELE firmware version %u.%u.%u-%x", (fw_version & (0x00ff0000)) >> 16, @@ -120,9 +120,19 @@ void spl_board_init(void) set_lpav_qos(); /* Enable A35 access to the CAAM */ - ret = ahab_release_caam(0x7, &res); + ret = ele_release_caam(0x7, &res); if (ret) - printf("ahab release caam failed %d, 0x%x\n", ret, res); + printf("ele release caam failed %d, 0x%x\n", ret, res); + + /* + * RNG start only available on the A1 soc revision. + * Check some JTAG register for the SoC revision. + */ + if (!is_soc_rev(CHIP_REV_1_0)) { + ret = ele_start_rng(); + if (ret) + printf("Fail to start RNG: %d\n", ret); + } } void board_init_f(ulong dummy) diff --git a/board/freescale/imx93_evk/spl.c b/board/freescale/imx93_evk/spl.c index 352ad79cb67..63883b30dd7 100644 --- a/board/freescale/imx93_evk/spl.c +++ b/board/freescale/imx93_evk/spl.c @@ -20,7 +20,6 @@ #include <asm/mach-imx/mxc_i2c.h> #include <asm/arch-mx7ulp/gpio.h> #include <asm/mach-imx/syscounter.h> -#include <asm/mach-imx/s400_api.h> #include <dm/uclass.h> #include <dm/device.h> #include <dm/uclass-internal.h> diff --git a/board/freescale/mx7dsabresd/mx7dsabresd.c b/board/freescale/mx7dsabresd/mx7dsabresd.c index 2777ae13bce..cff2e6a8717 100644 --- a/board/freescale/mx7dsabresd/mx7dsabresd.c +++ b/board/freescale/mx7dsabresd/mx7dsabresd.c @@ -292,6 +292,7 @@ int power_init_board(void) int board_late_init(void) { struct wdog_regs *wdog = (struct wdog_regs *)WDOG1_BASE_ADDR; + unsigned char eth1addr[6]; imx_iomux_v3_setup_multiple_pads(wdog_pads, ARRAY_SIZE(wdog_pads)); @@ -303,6 +304,11 @@ int board_late_init(void) */ clrsetbits_le16(&wdog->wcr, 0, 0x10); + /* Get the second MAC address */ + imx_get_mac_from_fuse(1, eth1addr); + if (!env_get("eth1addr") && is_valid_ethaddr(eth1addr)) + eth_env_set_enetaddr("eth1addr", eth1addr); + return 0; } diff --git a/board/gateworks/venice/eeprom.c b/board/gateworks/venice/eeprom.c index 6aea60ad05c..241be4ee630 100644 --- a/board/gateworks/venice/eeprom.c +++ b/board/gateworks/venice/eeprom.c @@ -218,6 +218,11 @@ const char *eeprom_get_dtb_name(int level, char *buf, int sz) int rev_base_bom = get_bom_rev(base_info.model); snprintf(buf, sz, "%s%2dxx-%dx", pre, base, som); + /* GW79xx baseboards have no build options */ + if (base == 79) { + base = (int)strtoul(base_info.model + 2, NULL, 10); + snprintf(buf, sz, "%s%4d-%dx", pre, base, som); + } switch (level) { case 0: /* full model (ie gw73xx-0x-a1a1) */ if (rev_base_bom) diff --git a/board/gateworks/venice/lpddr4_timing.h b/board/gateworks/venice/lpddr4_timing.h index 62b860610c5..d19902f10ec 100644 --- a/board/gateworks/venice/lpddr4_timing.h +++ b/board/gateworks/venice/lpddr4_timing.h @@ -16,6 +16,7 @@ extern struct dram_timing_info dram_timing_1gb_single_die; extern struct dram_timing_info dram_timing_2gb_single_die; extern struct dram_timing_info dram_timing_2gb_dual_die; #elif CONFIG_IMX8MP +extern struct dram_timing_info dram_timing_1gb_single_die; extern struct dram_timing_info dram_timing_4gb_dual_die; #endif diff --git a/board/gateworks/venice/lpddr4_timing_imx8mp.c b/board/gateworks/venice/lpddr4_timing_imx8mp.c index 2e96332f8b5..7bfd1b556bb 100644 --- a/board/gateworks/venice/lpddr4_timing_imx8mp.c +++ b/board/gateworks/venice/lpddr4_timing_imx8mp.c @@ -1315,6 +1315,538 @@ static struct dram_cfg_param ddr_phy_pie[] = { }; /* + * Generated code from MX8M_DDR_tool v3.30 using MX8MP Plus RPAv9 + * - 1GiB: ixm8mp-gw7020 1x Micron MT53E256M32D2DS 2-ch single-die per channel + */ +struct dram_cfg_param ddr_ddrc_cfg_1gb_single_die[] = { + /** Initialize DDRC registers **/ + { 0x3d400304, 0x1 }, + { 0x3d400030, 0x1 }, + { 0x3d400000, 0xa1080020 }, + { 0x3d400020, 0x1203 }, + { 0x3d400024, 0x16e3600 }, + { 0x3d400064, 0x5b0087 }, + { 0x3d400070, 0x7027f90 }, + { 0x3d400074, 0x790 }, + { 0x3d4000d0, 0xc00305ba }, + { 0x3d4000d4, 0x940000 }, + { 0x3d4000dc, 0xd4002d }, + { 0x3d4000e0, 0x310000 }, + { 0x3d4000e8, 0x660048 }, + { 0x3d4000ec, 0x160048 }, + { 0x3d400100, 0x191e1920 }, + { 0x3d400104, 0x60630 }, + { 0x3d40010c, 0xb0b000 }, + { 0x3d400110, 0xe04080e }, + { 0x3d400114, 0x2040c0c }, + { 0x3d400118, 0x1010007 }, + { 0x3d40011c, 0x402 }, + { 0x3d400130, 0x20600 }, + { 0x3d400134, 0xc100002 }, + { 0x3d400138, 0x8d }, + { 0x3d400144, 0x96004b }, + { 0x3d400180, 0x2ee0017 }, + { 0x3d400184, 0x2605b8e }, + { 0x3d400188, 0x0 }, + { 0x3d400190, 0x497820a }, + { 0x3d400194, 0x80303 }, + { 0x3d4001b4, 0x170a }, + { 0x3d4001a0, 0xe0400018 }, + { 0x3d4001a4, 0xdf00e4 }, + { 0x3d4001a8, 0x80000000 }, + { 0x3d4001b0, 0x11 }, + { 0x3d4001c0, 0x1 }, + { 0x3d4001c4, 0x1 }, + { 0x3d4000f4, 0x699 }, + { 0x3d400108, 0x70e1617 }, + { 0x3d400200, 0x1f }, + { 0x3d400208, 0x0 }, + { 0x3d40020c, 0x0 }, + { 0x3d400210, 0x1f1f }, + { 0x3d400204, 0x80808 }, + { 0x3d400214, 0x7070707 }, + { 0x3d400218, 0xf070707 }, + { 0x3d40021c, 0xf0f }, + { 0x3d400250, 0x1705 }, + { 0x3d400254, 0x2c }, + { 0x3d40025c, 0x4000030 }, + { 0x3d400264, 0x900093e7 }, + { 0x3d40026c, 0x2005574 }, + { 0x3d400400, 0x111 }, + { 0x3d400404, 0x72ff }, + { 0x3d400408, 0x72ff }, + { 0x3d400494, 0x2100e07 }, + { 0x3d400498, 0x620096 }, + { 0x3d40049c, 0x1100e07 }, + { 0x3d4004a0, 0xc8012c }, + { 0x3d402020, 0x1001 }, + { 0x3d402024, 0x30d400 }, + { 0x3d402050, 0x20d000 }, + { 0x3d402064, 0xc0012 }, + { 0x3d4020dc, 0x840000 }, + { 0x3d4020e0, 0x330000 }, + { 0x3d4020e8, 0x660048 }, + { 0x3d4020ec, 0x160048 }, + { 0x3d402100, 0xa040305 }, + { 0x3d402104, 0x30407 }, + { 0x3d402108, 0x203060b }, + { 0x3d40210c, 0x505000 }, + { 0x3d402110, 0x2040202 }, + { 0x3d402114, 0x2030202 }, + { 0x3d402118, 0x1010004 }, + { 0x3d40211c, 0x302 }, + { 0x3d402130, 0x20300 }, + { 0x3d402134, 0xa100002 }, + { 0x3d402138, 0x13 }, + { 0x3d402144, 0x14000a }, + { 0x3d402180, 0x640004 }, + { 0x3d402190, 0x3818200 }, + { 0x3d402194, 0x80303 }, + { 0x3d4021b4, 0x100 }, + { 0x3d4020f4, 0x599 }, + { 0x3d403020, 0x1001 }, + { 0x3d403024, 0xc3500 }, + { 0x3d403050, 0x20d000 }, + { 0x3d403064, 0x30005 }, + { 0x3d4030dc, 0x840000 }, + { 0x3d4030e0, 0x330000 }, + { 0x3d4030e8, 0x660048 }, + { 0x3d4030ec, 0x160048 }, + { 0x3d403100, 0xa010102 }, + { 0x3d403104, 0x30404 }, + { 0x3d403108, 0x203060b }, + { 0x3d40310c, 0x505000 }, + { 0x3d403110, 0x2040202 }, + { 0x3d403114, 0x2030202 }, + { 0x3d403118, 0x1010004 }, + { 0x3d40311c, 0x302 }, + { 0x3d403130, 0x20300 }, + { 0x3d403134, 0xa100002 }, + { 0x3d403138, 0x5 }, + { 0x3d403144, 0x50003 }, + { 0x3d403180, 0x190004 }, + { 0x3d403190, 0x3818200 }, + { 0x3d403194, 0x80303 }, + { 0x3d4031b4, 0x100 }, + { 0x3d4030f4, 0x599 }, + { 0x3d400028, 0x0 }, +}; + +/* PHY Initialize Configuration */ +struct dram_cfg_param ddr_ddrphy_cfg_1gb_single_die[] = { + { 0x100a0, 0x0 }, + { 0x100a1, 0x1 }, + { 0x100a2, 0x3 }, + { 0x100a3, 0x2 }, + { 0x100a4, 0x5 }, + { 0x100a5, 0x4 }, + { 0x100a6, 0x7 }, + { 0x100a7, 0x6 }, + { 0x110a0, 0x0 }, + { 0x110a1, 0x1 }, + { 0x110a2, 0x2 }, + { 0x110a3, 0x3 }, + { 0x110a4, 0x4 }, + { 0x110a5, 0x5 }, + { 0x110a6, 0x6 }, + { 0x110a7, 0x7 }, + { 0x120a0, 0x0 }, + { 0x120a1, 0x1 }, + { 0x120a2, 0x2 }, + { 0x120a3, 0x3 }, + { 0x120a4, 0x4 }, + { 0x120a5, 0x5 }, + { 0x120a6, 0x6 }, + { 0x120a7, 0x7 }, + { 0x130a0, 0x0 }, + { 0x130a1, 0x1 }, + { 0x130a2, 0x3 }, + { 0x130a3, 0x4 }, + { 0x130a4, 0x5 }, + { 0x130a5, 0x2 }, + { 0x130a6, 0x7 }, + { 0x130a7, 0x6 }, + { 0x1005f, 0x1ff }, + { 0x1015f, 0x1ff }, + { 0x1105f, 0x1ff }, + { 0x1115f, 0x1ff }, + { 0x1205f, 0x1ff }, + { 0x1215f, 0x1ff }, + { 0x1305f, 0x1ff }, + { 0x1315f, 0x1ff }, + { 0x11005f, 0x1ff }, + { 0x11015f, 0x1ff }, + { 0x11105f, 0x1ff }, + { 0x11115f, 0x1ff }, + { 0x11205f, 0x1ff }, + { 0x11215f, 0x1ff }, + { 0x11305f, 0x1ff }, + { 0x11315f, 0x1ff }, + { 0x21005f, 0x1ff }, + { 0x21015f, 0x1ff }, + { 0x21105f, 0x1ff }, + { 0x21115f, 0x1ff }, + { 0x21205f, 0x1ff }, + { 0x21215f, 0x1ff }, + { 0x21305f, 0x1ff }, + { 0x21315f, 0x1ff }, + { 0x55, 0x1ff }, + { 0x1055, 0x1ff }, + { 0x2055, 0x1ff }, + { 0x3055, 0x1ff }, + { 0x4055, 0x1ff }, + { 0x5055, 0x1ff }, + { 0x6055, 0x1ff }, + { 0x7055, 0x1ff }, + { 0x8055, 0x1ff }, + { 0x9055, 0x1ff }, + { 0x200c5, 0x19 }, + { 0x1200c5, 0x7 }, + { 0x2200c5, 0x7 }, + { 0x2002e, 0x2 }, + { 0x12002e, 0x2 }, + { 0x22002e, 0x2 }, + { 0x90204, 0x0 }, + { 0x190204, 0x0 }, + { 0x290204, 0x0 }, + { 0x20024, 0x1a3 }, + { 0x2003a, 0x2 }, + { 0x120024, 0x1a3 }, + { 0x2003a, 0x2 }, + { 0x220024, 0x1a3 }, + { 0x2003a, 0x2 }, + { 0x20056, 0x3 }, + { 0x120056, 0x3 }, + { 0x220056, 0x3 }, + { 0x1004d, 0xe00 }, + { 0x1014d, 0xe00 }, + { 0x1104d, 0xe00 }, + { 0x1114d, 0xe00 }, + { 0x1204d, 0xe00 }, + { 0x1214d, 0xe00 }, + { 0x1304d, 0xe00 }, + { 0x1314d, 0xe00 }, + { 0x11004d, 0xe00 }, + { 0x11014d, 0xe00 }, + { 0x11104d, 0xe00 }, + { 0x11114d, 0xe00 }, + { 0x11204d, 0xe00 }, + { 0x11214d, 0xe00 }, + { 0x11304d, 0xe00 }, + { 0x11314d, 0xe00 }, + { 0x21004d, 0xe00 }, + { 0x21014d, 0xe00 }, + { 0x21104d, 0xe00 }, + { 0x21114d, 0xe00 }, + { 0x21204d, 0xe00 }, + { 0x21214d, 0xe00 }, + { 0x21304d, 0xe00 }, + { 0x21314d, 0xe00 }, + { 0x10049, 0xeba }, + { 0x10149, 0xeba }, + { 0x11049, 0xeba }, + { 0x11149, 0xeba }, + { 0x12049, 0xeba }, + { 0x12149, 0xeba }, + { 0x13049, 0xeba }, + { 0x13149, 0xeba }, + { 0x110049, 0xeba }, + { 0x110149, 0xeba }, + { 0x111049, 0xeba }, + { 0x111149, 0xeba }, + { 0x112049, 0xeba }, + { 0x112149, 0xeba }, + { 0x113049, 0xeba }, + { 0x113149, 0xeba }, + { 0x210049, 0xeba }, + { 0x210149, 0xeba }, + { 0x211049, 0xeba }, + { 0x211149, 0xeba }, + { 0x212049, 0xeba }, + { 0x212149, 0xeba }, + { 0x213049, 0xeba }, + { 0x213149, 0xeba }, + { 0x43, 0x63 }, + { 0x1043, 0x63 }, + { 0x2043, 0x63 }, + { 0x3043, 0x63 }, + { 0x4043, 0x63 }, + { 0x5043, 0x63 }, + { 0x6043, 0x63 }, + { 0x7043, 0x63 }, + { 0x8043, 0x63 }, + { 0x9043, 0x63 }, + { 0x20018, 0x3 }, + { 0x20075, 0x4 }, + { 0x20050, 0x0 }, + { 0x20008, 0x2ee }, + { 0x120008, 0x64 }, + { 0x220008, 0x19 }, + { 0x20088, 0x9 }, + { 0x200b2, 0x104 }, + { 0x10043, 0x5a1 }, + { 0x10143, 0x5a1 }, + { 0x11043, 0x5a1 }, + { 0x11143, 0x5a1 }, + { 0x12043, 0x5a1 }, + { 0x12143, 0x5a1 }, + { 0x13043, 0x5a1 }, + { 0x13143, 0x5a1 }, + { 0x1200b2, 0x104 }, + { 0x110043, 0x5a1 }, + { 0x110143, 0x5a1 }, + { 0x111043, 0x5a1 }, + { 0x111143, 0x5a1 }, + { 0x112043, 0x5a1 }, + { 0x112143, 0x5a1 }, + { 0x113043, 0x5a1 }, + { 0x113143, 0x5a1 }, + { 0x2200b2, 0x104 }, + { 0x210043, 0x5a1 }, + { 0x210143, 0x5a1 }, + { 0x211043, 0x5a1 }, + { 0x211143, 0x5a1 }, + { 0x212043, 0x5a1 }, + { 0x212143, 0x5a1 }, + { 0x213043, 0x5a1 }, + { 0x213143, 0x5a1 }, + { 0x200fa, 0x1 }, + { 0x1200fa, 0x1 }, + { 0x2200fa, 0x1 }, + { 0x20019, 0x1 }, + { 0x120019, 0x1 }, + { 0x220019, 0x1 }, + { 0x200f0, 0x660 }, + { 0x200f1, 0x0 }, + { 0x200f2, 0x4444 }, + { 0x200f3, 0x8888 }, + { 0x200f4, 0x5665 }, + { 0x200f5, 0x0 }, + { 0x200f6, 0x0 }, + { 0x200f7, 0xf000 }, + { 0x20025, 0x0 }, + { 0x2002d, 0x0 }, + { 0x12002d, 0x0 }, + { 0x22002d, 0x0 }, + { 0x2007d, 0x212 }, + { 0x12007d, 0x212 }, + { 0x22007d, 0x212 }, + { 0x2007c, 0x61 }, + { 0x12007c, 0x61 }, + { 0x22007c, 0x61 }, + { 0x1004a, 0x500 }, + { 0x1104a, 0x500 }, + { 0x1204a, 0x500 }, + { 0x1304a, 0x500 }, + { 0x2002c, 0x0 }, +}; + +/* P0 message block paremeter for training firmware */ +struct dram_cfg_param ddr_fsp0_cfg_1gb_single_die[] = { + { 0xd0000, 0x0 }, + { 0x54003, 0xbb8 }, + { 0x54004, 0x2 }, + { 0x54005, 0x2228 }, + { 0x54006, 0x14 }, + { 0x54008, 0x131f }, + { 0x54009, 0xc8 }, + { 0x5400b, 0x2 }, + { 0x5400f, 0x100 }, + { 0x54012, 0x110 }, + { 0x54019, 0x2dd4 }, + { 0x5401a, 0x31 }, + { 0x5401b, 0x4866 }, + { 0x5401c, 0x4800 }, + { 0x5401e, 0x16 }, + { 0x5401f, 0x2dd4 }, + { 0x54020, 0x31 }, + { 0x54021, 0x4866 }, + { 0x54022, 0x4800 }, + { 0x54024, 0x16 }, + { 0x5402b, 0x1000 }, + { 0x5402c, 0x1 }, + { 0x54032, 0xd400 }, + { 0x54033, 0x312d }, + { 0x54034, 0x6600 }, + { 0x54035, 0x48 }, + { 0x54036, 0x48 }, + { 0x54037, 0x1600 }, + { 0x54038, 0xd400 }, + { 0x54039, 0x312d }, + { 0x5403a, 0x6600 }, + { 0x5403b, 0x48 }, + { 0x5403c, 0x48 }, + { 0x5403d, 0x1600 }, + { 0xd0000, 0x1 }, +}; + +/* P1 message block paremeter for training firmware */ +struct dram_cfg_param ddr_fsp1_cfg_1gb_single_die[] = { + { 0xd0000, 0x0 }, + { 0x54002, 0x101 }, + { 0x54003, 0x190 }, + { 0x54004, 0x2 }, + { 0x54005, 0x2228 }, + { 0x54006, 0x14 }, + { 0x54008, 0x121f }, + { 0x54009, 0xc8 }, + { 0x5400b, 0x2 }, + { 0x5400f, 0x100 }, + { 0x54012, 0x110 }, + { 0x54019, 0x84 }, + { 0x5401a, 0x33 }, + { 0x5401b, 0x4866 }, + { 0x5401c, 0x4800 }, + { 0x5401e, 0x16 }, + { 0x5401f, 0x84 }, + { 0x54020, 0x33 }, + { 0x54021, 0x4866 }, + { 0x54022, 0x4800 }, + { 0x54024, 0x16 }, + { 0x5402b, 0x1000 }, + { 0x5402c, 0x1 }, + { 0x54032, 0x8400 }, + { 0x54033, 0x3300 }, + { 0x54034, 0x6600 }, + { 0x54035, 0x48 }, + { 0x54036, 0x48 }, + { 0x54037, 0x1600 }, + { 0x54038, 0x8400 }, + { 0x54039, 0x3300 }, + { 0x5403a, 0x6600 }, + { 0x5403b, 0x48 }, + { 0x5403c, 0x48 }, + { 0x5403d, 0x1600 }, + { 0xd0000, 0x1 }, +}; + +/* P2 message block paremeter for training firmware */ +struct dram_cfg_param ddr_fsp2_cfg_1gb_single_die[] = { + { 0xd0000, 0x0 }, + { 0x54002, 0x102 }, + { 0x54003, 0x64 }, + { 0x54004, 0x2 }, + { 0x54005, 0x2228 }, + { 0x54006, 0x14 }, + { 0x54008, 0x121f }, + { 0x54009, 0xc8 }, + { 0x5400b, 0x2 }, + { 0x5400f, 0x100 }, + { 0x54012, 0x110 }, + { 0x54019, 0x84 }, + { 0x5401a, 0x33 }, + { 0x5401b, 0x4866 }, + { 0x5401c, 0x4800 }, + { 0x5401e, 0x16 }, + { 0x5401f, 0x84 }, + { 0x54020, 0x33 }, + { 0x54021, 0x4866 }, + { 0x54022, 0x4800 }, + { 0x54024, 0x16 }, + { 0x5402b, 0x1000 }, + { 0x5402c, 0x1 }, + { 0x54032, 0x8400 }, + { 0x54033, 0x3300 }, + { 0x54034, 0x6600 }, + { 0x54035, 0x48 }, + { 0x54036, 0x48 }, + { 0x54037, 0x1600 }, + { 0x54038, 0x8400 }, + { 0x54039, 0x3300 }, + { 0x5403a, 0x6600 }, + { 0x5403b, 0x48 }, + { 0x5403c, 0x48 }, + { 0x5403d, 0x1600 }, + { 0xd0000, 0x1 }, +}; + +/* P0 2D message block paremeter for training firmware */ +struct dram_cfg_param ddr_fsp0_2d_cfg_1gb_single_die[] = { + { 0xd0000, 0x0 }, + { 0x54003, 0xbb8 }, + { 0x54004, 0x2 }, + { 0x54005, 0x2228 }, + { 0x54006, 0x14 }, + { 0x54008, 0x61 }, + { 0x54009, 0xc8 }, + { 0x5400b, 0x2 }, + { 0x5400f, 0x100 }, + { 0x54010, 0x1f7f }, + { 0x54012, 0x110 }, + { 0x54019, 0x2dd4 }, + { 0x5401a, 0x31 }, + { 0x5401b, 0x4866 }, + { 0x5401c, 0x4800 }, + { 0x5401e, 0x16 }, + { 0x5401f, 0x2dd4 }, + { 0x54020, 0x31 }, + { 0x54021, 0x4866 }, + { 0x54022, 0x4800 }, + { 0x54024, 0x16 }, + { 0x5402b, 0x1000 }, + { 0x5402c, 0x1 }, + { 0x54032, 0xd400 }, + { 0x54033, 0x312d }, + { 0x54034, 0x6600 }, + { 0x54035, 0x48 }, + { 0x54036, 0x48 }, + { 0x54037, 0x1600 }, + { 0x54038, 0xd400 }, + { 0x54039, 0x312d }, + { 0x5403a, 0x6600 }, + { 0x5403b, 0x48 }, + { 0x5403c, 0x48 }, + { 0x5403d, 0x1600 }, + { 0xd0000, 0x1 }, +}; + +struct dram_fsp_msg ddr_dram_fsp_msg_1gb_single_die[] = { + { + /* P0 3000mts 1D */ + .drate = 3000, + .fw_type = FW_1D_IMAGE, + .fsp_cfg = ddr_fsp0_cfg_1gb_single_die, + .fsp_cfg_num = ARRAY_SIZE(ddr_fsp0_cfg_1gb_single_die), + }, + { + /* P1 400mts 1D */ + .drate = 400, + .fw_type = FW_1D_IMAGE, + .fsp_cfg = ddr_fsp1_cfg_1gb_single_die, + .fsp_cfg_num = ARRAY_SIZE(ddr_fsp1_cfg_1gb_single_die), + }, + { + /* P2 100mts 1D */ + .drate = 100, + .fw_type = FW_1D_IMAGE, + .fsp_cfg = ddr_fsp2_cfg_1gb_single_die, + .fsp_cfg_num = ARRAY_SIZE(ddr_fsp2_cfg_1gb_single_die), + }, + { + /* P0 3000mts 2D */ + .drate = 3000, + .fw_type = FW_2D_IMAGE, + .fsp_cfg = ddr_fsp0_2d_cfg_1gb_single_die, + .fsp_cfg_num = ARRAY_SIZE(ddr_fsp0_2d_cfg_1gb_single_die), + }, +}; + +/* ddr timing config params */ +struct dram_timing_info dram_timing_1gb_single_die = { + .ddrc_cfg = ddr_ddrc_cfg_1gb_single_die, + .ddrc_cfg_num = ARRAY_SIZE(ddr_ddrc_cfg_1gb_single_die), + .ddrphy_cfg = ddr_ddrphy_cfg_1gb_single_die, + .ddrphy_cfg_num = ARRAY_SIZE(ddr_ddrphy_cfg_1gb_single_die), + .fsp_msg = ddr_dram_fsp_msg_1gb_single_die, + .fsp_msg_num = ARRAY_SIZE(ddr_dram_fsp_msg_1gb_single_die), + .ddrphy_trained_csr = ddr_ddrphy_trained_csr, + .ddrphy_trained_csr_num = ARRAY_SIZE(ddr_ddrphy_trained_csr), + .ddrphy_pie = ddr_phy_pie, + .ddrphy_pie_num = ARRAY_SIZE(ddr_phy_pie), + .fsp_table = { 3000, 400, 100, }, +}; + +/* * Generated code from MX8M_DDR_tool v3.30 using MX8M Plus RPAv7 * - 4GiB: imx8mp-gw7401 1x Micron MT53D1024M32D4DT 2-ch dual-die per channel */ diff --git a/board/gateworks/venice/spl.c b/board/gateworks/venice/spl.c index 4eb7bdfcee6..5aa209578b2 100644 --- a/board/gateworks/venice/spl.c +++ b/board/gateworks/venice/spl.c @@ -71,6 +71,9 @@ static void spl_dram_init(int size) dram_timing = &dram_timing_2gb_dual_die; size = 2048; #elif CONFIG_IMX8MP + case 1024: + dram_timing = &dram_timing_1gb_single_die; + break; case 4096: dram_timing = &dram_timing_4gb_dual_die; break; @@ -83,9 +86,12 @@ static void spl_dram_init(int size) printf("DRAM : LPDDR4 "); if (size > 512) - printf("%d GiB\n", size / 1024); + printf("%d GiB", size / 1024); else - printf("%d MiB\n", size); + printf("%d MiB", size); + printf(" %dMT/s %dMHz\n", + dram_timing->fsp_msg[0].drate, + dram_timing->fsp_msg[0].drate / 2); ddr_init(dram_timing); } @@ -121,7 +127,8 @@ static int power_init_board(void) if ((!strncmp(model, "GW71", 4)) || (!strncmp(model, "GW72", 4)) || - (!strncmp(model, "GW73", 4))) { + (!strncmp(model, "GW73", 4)) || + (!strncmp(model, "GW7905", 6))) { ret = uclass_get_device_by_seq(UCLASS_I2C, 0, &bus); if (ret) { printf("PMIC : failed I2C1 probe: %d\n", ret); @@ -132,11 +139,22 @@ static int power_init_board(void) printf("PMIC : failed probe: %d\n", ret); return ret; } - puts("PMIC : MP5416\n"); +#ifdef CONFIG_IMX8MM + puts("PMIC : MP5416 (IMX8MM)\n"); /* set VDD_ARM SW3 to 0.92V for 1.6GHz */ dm_i2c_reg_write(dev, MP5416_VSET_SW3, BIT(7) | MP5416_VSET_SW3_SVAL(920000)); +#elif CONFIG_IMX8MP + puts("PMIC : MP5416 (IMX8MP)\n"); + + /* set VDD_ARM SW3 to 0.95V for 1.6GHz */ + dm_i2c_reg_write(dev, MP5416_VSET_SW3, + BIT(7) | MP5416_VSET_SW3_SVAL(950000)); + /* set VDD_SOC SW1 to 0.95V for 1.6GHz */ + dm_i2c_reg_write(dev, MP5416_VSET_SW1, + BIT(7) | MP5416_VSET_SW1_SVAL(950000)); +#endif } else if (!strncmp(model, "GW74", 4)) { @@ -327,6 +345,21 @@ int spl_board_boot_device(enum boot_device boot_dev_spl) } } +unsigned long spl_mmc_get_uboot_raw_sector(struct mmc *mmc, unsigned long raw_sect) +{ + if (!IS_SD(mmc)) { + switch (EXT_CSD_EXTRACT_BOOT_PART(mmc->part_config)) { + case 1: + case 2: + if (IS_ENABLED(CONFIG_IMX8MN) || IS_ENABLED(CONFIG_IMX8MP)) + raw_sect -= 32 * 2; + break; + } + } + + return raw_sect; +} + const char *spl_board_loader_name(u32 boot_device) { switch (boot_device) { @@ -340,3 +373,8 @@ const char *spl_board_loader_name(u32 boot_device) return NULL; } } + +void spl_board_init(void) +{ + arch_misc_init(); +} diff --git a/board/gateworks/venice/venice.c b/board/gateworks/venice/venice.c index ca62f0be6d2..a39ae58c8a0 100644 --- a/board/gateworks/venice/venice.c +++ b/board/gateworks/venice/venice.c @@ -6,9 +6,12 @@ #include <fdt_support.h> #include <init.h> #include <led.h> +#include <mmc.h> #include <miiphy.h> +#include <mmc.h> #include <asm/arch/clock.h> #include <asm/arch/sys_proto.h> +#include <asm/mach-imx/boot_mode.h> #include "eeprom.h" @@ -17,7 +20,7 @@ int board_phys_sdram_size(phys_size_t *size) if (!size) return -EINVAL; - *size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE); + *size = get_ram_size((void *)PHYS_SDRAM, (long)PHYS_SDRAM_SIZE + (long)PHYS_SDRAM_2_SIZE); return 0; } @@ -93,10 +96,12 @@ int board_init(void) int board_late_init(void) { const char *str; + struct mmc *mmc = NULL; char env[32]; int ret, i; u8 enetaddr[6]; char fdt[64]; + int bootdev; /* Set board serial/model */ if (!env_get("serial#")) @@ -131,6 +136,74 @@ int board_late_init(void) i++; } while (!ret); + /* + * set bootdev/bootblk/bootpart (used in firmware_update script) + * dynamically depending on boot device and SoC + */ + bootdev = -1; + switch (get_boot_device()) { + case SD1_BOOT: + case MMC1_BOOT: /* SDHC1 */ + bootdev = 0; + break; + case SD2_BOOT: + case MMC2_BOOT: /* SDHC2 */ + bootdev = 1; + break; + case SD3_BOOT: + case MMC3_BOOT: /* SDHC3 */ + bootdev = 2; + break; + default: + bootdev = 2; /* assume SDHC3 (eMMC) if booting over SDP */ + break; + } + if (bootdev != -1) + mmc = find_mmc_device(bootdev); + if (mmc) { + int bootblk; + + if (IS_ENABLED(CONFIG_IMX8MN) || IS_ENABLED(CONFIG_IMX8MP)) + bootblk = 32 * SZ_1K / 512; + else + bootblk = 33 * SZ_1K / 512; + mmc_init(mmc); + if (!IS_SD(mmc)) { + int bootpart; + + switch (EXT_CSD_EXTRACT_BOOT_PART(mmc->part_config)) { + case 1: /* boot0 */ + bootpart = 1; + break; + case 2: /* boot1 */ + bootpart = 2; + break; + case 7: /* user */ + default: + bootpart = 0; + break; + } + /* IMX8MP/IMX8MN BOOTROM v2 uses offset=0 for boot parts */ + if ((IS_ENABLED(CONFIG_IMX8MN) || IS_ENABLED(CONFIG_IMX8MP)) && + (bootpart == 1 || bootpart == 2)) + bootblk = 0; + env_set_hex("bootpart", bootpart); + env_set_hex("bootblk", bootblk); + } else { /* SD */ + env_set("bootpart", ""); + env_set_hex("bootblk", bootblk); + } + env_set_hex("dev", bootdev); + } + + /* override soc=imx8m to provide a more specific soc name */ + if (IS_ENABLED(CONFIG_IMX8MN)) + env_set("soc", "imx8mn"); + else if (IS_ENABLED(CONFIG_IMX8MP)) + env_set("soc", "imx8mp"); + else if (IS_ENABLED(CONFIG_IMX8MM)) + env_set("soc", "imx8mm"); + return 0; } @@ -139,6 +212,20 @@ int board_mmc_get_env_dev(int devno) return devno; } +uint mmc_get_env_part(struct mmc *mmc) +{ + if (!IS_SD(mmc)) { + switch (EXT_CSD_EXTRACT_BOOT_PART(mmc->part_config)) { + case 1: + return 1; + case 2: + return 2; + } + } + + return 0; +} + int ft_board_setup(void *fdt, struct bd_info *bd) { const char *base_model = eeprom_get_baseboard_model(); diff --git a/board/gateworks/venice/venice.env b/board/gateworks/venice/venice.env index f81804ca12c..a0d6c43325c 100644 --- a/board/gateworks/venice/venice.env +++ b/board/gateworks/venice/venice.env @@ -8,11 +8,11 @@ bootm_size=0x10000000 dev=2 preboot=gsc wd-disable console=ttymxc1,115200 -update_firmware=tftpboot $loadaddr $image && +update_firmware=tftpboot $loadaddr $dir/venice-$soc-flash.bin && setexpr blkcnt $filesize + 0x1ff && setexpr blkcnt $blkcnt / 0x200 && - mmc dev $dev && - mmc write $loadaddr $splblk $blkcnt + mmc dev $dev $bootpart && + mmc write $loadaddr $bootblk $blkcnt loadfdt=if $fsload $fdt_addr_r $dir/$fdt_file1; then echo loaded $fdt_file1; elif $fsload $fdt_addr_r $dir/$fdt_file2; @@ -31,4 +31,3 @@ update_rootfs=tftpboot $loadaddr $image && gzwrite mmc $dev $loadaddr $filesize 100000 1000000 update_all=tftpboot $loadaddr $image && gzwrite mmc $dev $loadaddr $filesize -erase_env=mmc dev $dev; mmc erase 0x7f08 0x40 diff --git a/board/kontron/sl-mx8mm/sl-mx8mm.c b/board/kontron/sl-mx8mm/sl-mx8mm.c index ddb509eb66b..8dcc2ea54f6 100644 --- a/board/kontron/sl-mx8mm/sl-mx8mm.c +++ b/board/kontron/sl-mx8mm/sl-mx8mm.c @@ -37,7 +37,7 @@ struct efi_capsule_update_info update_info = { int board_phys_sdram_size(phys_size_t *size) { - u32 ddr_size = readl(M4_BOOTROM_BASE_ADDR); + u32 ddr_size = readl(MCU_BOOTROM_BASE_ADDR); if (ddr_size == 4) { *size = 0x100000000; diff --git a/board/kontron/sl-mx8mm/spl.c b/board/kontron/sl-mx8mm/spl.c index 3a919d0a9c3..b49373442a2 100644 --- a/board/kontron/sl-mx8mm/spl.c +++ b/board/kontron/sl-mx8mm/spl.c @@ -106,7 +106,7 @@ static void spl_dram_init(void) } gd->ram_size = size; - writel(size, M4_BOOTROM_BASE_ADDR); + writel(size, MCU_BOOTROM_BASE_ADDR); } int do_board_detect(void) diff --git a/board/liebherr/xea/xea.c b/board/liebherr/xea/xea.c index 38e841c5f67..e4d2eb65cc4 100644 --- a/board/liebherr/xea/xea.c +++ b/board/liebherr/xea/xea.c @@ -62,6 +62,7 @@ static void init_clocks(void) void board_init_f(ulong arg) { init_clocks(); + spl_early_init(); preloader_console_init(); } @@ -203,5 +204,22 @@ int ft_board_setup(void *blob, struct bd_info *bd) return 0; } #endif - +/* + * NOTE: + * + * IMX28 clock "stub" DM driver! + * + * Only used for SPL stage, which is NOT using DM; serial and + * eMMC configuration. + */ +static const struct udevice_id imx28_clk_ids[] = { + { .compatible = "fsl,imx28-clkctrl", }, + { } +}; + +U_BOOT_DRIVER(fsl_imx28_clkctrl) = { + .name = "fsl_imx28_clkctrl", + .id = UCLASS_CLK, + .of_match = imx28_clk_ids, +}; #endif /* CONFIG_SPL_BUILD */ diff --git a/board/nuvoton/arbel_evb/Kconfig b/board/nuvoton/arbel_evb/Kconfig index efe85974a29..33c589f1fb3 100644 --- a/board/nuvoton/arbel_evb/Kconfig +++ b/board/nuvoton/arbel_evb/Kconfig @@ -11,8 +11,8 @@ config SYS_CONFIG_NAME config SYS_MEM_TOP_HIDE hex "Reserved TOP memory" - default 0xB000000 + default 0x0 help - Reserve memory for ECC/GFX/VCD/ECE. + Reserve memory for ECC/GFX/OPTEE/TIP/CP. endif diff --git a/board/nuvoton/arbel_evb/arbel_evb.c b/board/nuvoton/arbel_evb/arbel_evb.c index cd12ce38345..e52e0a59abc 100644 --- a/board/nuvoton/arbel_evb/arbel_evb.c +++ b/board/nuvoton/arbel_evb/arbel_evb.c @@ -8,6 +8,17 @@ #include <asm/io.h> #include <asm/arch/gcr.h> +#define SR_MII_CTRL_SWR_BIT15 15 + +#define DRAM_512MB_ECC_SIZE 0x1C000000ULL +#define DRAM_512MB_SIZE 0x20000000ULL +#define DRAM_1GB_ECC_SIZE 0x38000000ULL +#define DRAM_1GB_SIZE 0x40000000ULL +#define DRAM_2GB_ECC_SIZE 0x70000000ULL +#define DRAM_2GB_SIZE 0x80000000ULL +#define DRAM_4GB_ECC_SIZE 0xE00000000ULL +#define DRAM_4GB_SIZE 0x100000000ULL + DECLARE_GLOBAL_DATA_PTR; int board_init(void) @@ -18,12 +29,65 @@ int board_init(void) int dram_init(void) { struct npcm_gcr *gcr = (struct npcm_gcr *)NPCM_GCR_BA; + uint64_t delta = 0ULL; /* - * Get dram size from bootblock. - * The value is stored in scrpad_02 register. + * get dram active size value from bootblock. + * Value sent using scrpad_03 register. + * feature available in bootblock 0.0.6 and above. */ - gd->ram_size = readl(&gcr->scrpad_b); + + gd->ram_size = readl(&gcr->scrpad_c); + debug("%s: scrpad_c: %llx ", __func__, gd->ram_size); + + if (gd->ram_size == 0) { + gd->ram_size = readl(&gcr->scrpad_b); + debug("%s: scrpad_b: %llx ", __func__, gd->ram_size); + } else { + gd->ram_size *= 0x100000ULL; + } + + gd->bd->bi_dram[0].start = 0; + debug("ram_size: %llx ", gd->ram_size); + + switch (gd->ram_size) { + case DRAM_512MB_ECC_SIZE: + case DRAM_512MB_SIZE: + case DRAM_1GB_ECC_SIZE: + case DRAM_1GB_SIZE: + case DRAM_2GB_ECC_SIZE: + case DRAM_2GB_SIZE: + gd->bd->bi_dram[0].size = gd->ram_size; + gd->bd->bi_dram[1].start = 0; + gd->bd->bi_dram[1].size = 0; + break; + case DRAM_4GB_ECC_SIZE: + gd->bd->bi_dram[0].size = DRAM_2GB_ECC_SIZE; + gd->bd->bi_dram[1].start = DRAM_4GB_SIZE; + gd->bd->bi_dram[1].size = DRAM_2GB_SIZE; + delta = DRAM_4GB_SIZE - DRAM_2GB_ECC_SIZE; + break; + case DRAM_4GB_SIZE: + gd->bd->bi_dram[0].size = DRAM_2GB_SIZE; + gd->bd->bi_dram[1].start = DRAM_4GB_SIZE; + gd->bd->bi_dram[1].size = DRAM_2GB_SIZE; + delta = DRAM_4GB_SIZE - DRAM_2GB_SIZE; + break; + default: + gd->bd->bi_dram[0].size = DRAM_1GB_SIZE; + gd->bd->bi_dram[1].start = 0; + gd->bd->bi_dram[1].size = 0; + break; + } + + gd->ram_size -= delta; + + return 0; +} + +int dram_init_banksize(void) +{ + dram_init(); return 0; } diff --git a/board/nuvoton/poleg_evb/poleg_evb.c b/board/nuvoton/poleg_evb/poleg_evb.c index aef142a881c..2052af6649a 100644 --- a/board/nuvoton/poleg_evb/poleg_evb.c +++ b/board/nuvoton/poleg_evb/poleg_evb.c @@ -6,6 +6,7 @@ #include <common.h> #include <dm.h> +#include <env.h> #include <asm/io.h> #include <asm/arch/gcr.h> #include <asm/mach-types.h> @@ -19,6 +20,7 @@ int board_init(void) int dram_init(void) { + char value[32]; struct npcm_gcr *gcr = (struct npcm_gcr *)NPCM_GCR_BA; int ramsize = (readl(&gcr->intcr3) >> 8) & 0x7; @@ -44,5 +46,10 @@ int dram_init(void) break; } + if (gd->ram_size > 0) { + sprintf(value, "%ldM", (gd->ram_size / 0x100000)); + env_set("mem", value); + } + return 0; } diff --git a/board/openpiton/riscv64/Kconfig b/board/openpiton/riscv64/Kconfig index eb0db8a64c8..21da1dc346d 100644 --- a/board/openpiton/riscv64/Kconfig +++ b/board/openpiton/riscv64/Kconfig @@ -29,7 +29,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy select SUPPORT_SPL imply CPU_RISCV imply RISCV_TIMER - imply SPL_SIFIVE_CLINT + imply SPL_RISCV_ACLINT imply CMD_CPU imply SPL_CPU_SUPPORT imply SPL_SMP diff --git a/board/phytec/phycore_imx8mm/lpddr4_timing.c b/board/phytec/phycore_imx8mm/lpddr4_timing.c index 811ac26415a..f5a2f3268b3 100644 --- a/board/phytec/phycore_imx8mm/lpddr4_timing.c +++ b/board/phytec/phycore_imx8mm/lpddr4_timing.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2020 PHYTEC Messtechnik GmbH + * Copyright 2019 NXP + * Copyright (C) 2023 PHYTEC Messtechnik GmbH * * Generated code from MX8M_DDR_tool */ @@ -13,22 +14,22 @@ static struct dram_cfg_param ddr_ddrc_cfg[] = { {0x3d400304, 0x1}, {0x3d400030, 0x1}, {0x3d400000, 0xa1080020}, - {0x3d400020, 0x223}, + {0x3d400020, 0x222}, {0x3d400024, 0x3a980}, - {0x3d400064, 0x5b00d2}, + {0x3d400064, 0x2d00d2}, {0x3d4000d0, 0xc00305ba}, {0x3d4000d4, 0x940000}, {0x3d4000dc, 0xd4002d}, {0x3d4000e0, 0x310000}, {0x3d4000e8, 0x66004d}, {0x3d4000ec, 0x16004d}, - {0x3d400100, 0x191e1920}, + {0x3d400100, 0x191e0c20}, {0x3d400104, 0x60630}, {0x3d40010c, 0xb0b000}, {0x3d400110, 0xe04080e}, {0x3d400114, 0x2040c0c}, {0x3d400118, 0x1010007}, - {0x3d40011c, 0x401}, + {0x3d40011c, 0x402}, {0x3d400130, 0x20600}, {0x3d400134, 0xc100002}, {0x3d400138, 0xd8}, @@ -45,7 +46,7 @@ static struct dram_cfg_param ddr_ddrc_cfg[] = { {0x3d4001b0, 0x11}, {0x3d4001c0, 0x1}, {0x3d4001c4, 0x1}, - {0x3d4000f4, 0xc99}, + {0x3d4000f4, 0x699}, {0x3d400108, 0x70e1617}, {0x3d400200, 0x1f}, {0x3d40020c, 0x0}, @@ -53,6 +54,7 @@ static struct dram_cfg_param ddr_ddrc_cfg[] = { {0x3d400204, 0x80808}, {0x3d400214, 0x7070707}, {0x3d400218, 0x7070707}, + {0x3d40021c, 0xf0f}, {0x3d400250, 0x29001701}, {0x3d400254, 0x2c}, {0x3d40025c, 0x4000030}, @@ -64,22 +66,22 @@ static struct dram_cfg_param ddr_ddrc_cfg[] = { {0x3d400498, 0x620096}, {0x3d40049c, 0x1100e07}, {0x3d4004a0, 0xc8012c}, - {0x3d402020, 0x21}, + {0x3d402020, 0x20}, {0x3d402024, 0x7d00}, {0x3d402050, 0x20d040}, - {0x3d402064, 0xc001c}, + {0x3d402064, 0x6001c}, {0x3d4020dc, 0x840000}, {0x3d4020e0, 0x310000}, {0x3d4020e8, 0x66004d}, {0x3d4020ec, 0x16004d}, - {0x3d402100, 0xa040305}, + {0x3d402100, 0xa040105}, {0x3d402104, 0x30407}, {0x3d402108, 0x203060b}, {0x3d40210c, 0x505000}, {0x3d402110, 0x2040202}, {0x3d402114, 0x2030202}, {0x3d402118, 0x1010004}, - {0x3d40211c, 0x301}, + {0x3d40211c, 0x302}, {0x3d402130, 0x20300}, {0x3d402134, 0xa100002}, {0x3d402138, 0x1d}, @@ -88,8 +90,8 @@ static struct dram_cfg_param ddr_ddrc_cfg[] = { {0x3d402190, 0x3818200}, {0x3d402194, 0x80303}, {0x3d4021b4, 0x100}, - {0x3d4020f4, 0xc99}, - {0x3d403020, 0x21}, + {0x3d4020f4, 0x599}, + {0x3d403020, 0x20}, {0x3d403024, 0x1f40}, {0x3d403050, 0x20d040}, {0x3d403064, 0x30007}, @@ -104,7 +106,7 @@ static struct dram_cfg_param ddr_ddrc_cfg[] = { {0x3d403110, 0x2040202}, {0x3d403114, 0x2030202}, {0x3d403118, 0x1010004}, - {0x3d40311c, 0x301}, + {0x3d40311c, 0x302}, {0x3d403130, 0x20300}, {0x3d403134, 0xa100002}, {0x3d403138, 0x8}, @@ -113,7 +115,7 @@ static struct dram_cfg_param ddr_ddrc_cfg[] = { {0x3d403190, 0x3818200}, {0x3d403194, 0x80303}, {0x3d4031b4, 0x100}, - {0x3d4030f4, 0xc99}, + {0x3d4030f4, 0x599}, {0x3d400028, 0x0}, }; @@ -201,8 +203,8 @@ static struct dram_cfg_param ddr_ddrphy_cfg[] = { {0x220024, 0x1ab}, {0x2003a, 0x0}, {0x20056, 0x3}, - {0x120056, 0xa}, - {0x220056, 0xa}, + {0x120056, 0x3}, + {0x220056, 0x3}, {0x1004d, 0xe00}, {0x1014d, 0xe00}, {0x1104d, 0xe00}, @@ -323,727 +325,726 @@ static struct dram_cfg_param ddr_ddrphy_cfg[] = { /* ddr phy trained csr */ static struct dram_cfg_param ddr_ddrphy_trained_csr[] = { - { 0x200b2, 0x0 }, - { 0x1200b2, 0x0 }, - { 0x2200b2, 0x0 }, - { 0x200cb, 0x0 }, - { 0x10043, 0x0 }, - { 0x110043, 0x0 }, - { 0x210043, 0x0 }, - { 0x10143, 0x0 }, - { 0x110143, 0x0 }, - { 0x210143, 0x0 }, - { 0x11043, 0x0 }, - { 0x111043, 0x0 }, - { 0x211043, 0x0 }, - { 0x11143, 0x0 }, - { 0x111143, 0x0 }, - { 0x211143, 0x0 }, - { 0x12043, 0x0 }, - { 0x112043, 0x0 }, - { 0x212043, 0x0 }, - { 0x12143, 0x0 }, - { 0x112143, 0x0 }, - { 0x212143, 0x0 }, - { 0x13043, 0x0 }, - { 0x113043, 0x0 }, - { 0x213043, 0x0 }, - { 0x13143, 0x0 }, - { 0x113143, 0x0 }, - { 0x213143, 0x0 }, - { 0x80, 0x0 }, - { 0x100080, 0x0 }, - { 0x200080, 0x0 }, - { 0x1080, 0x0 }, - { 0x101080, 0x0 }, - { 0x201080, 0x0 }, - { 0x2080, 0x0 }, - { 0x102080, 0x0 }, - { 0x202080, 0x0 }, - { 0x3080, 0x0 }, - { 0x103080, 0x0 }, - { 0x203080, 0x0 }, - { 0x4080, 0x0 }, - { 0x104080, 0x0 }, - { 0x204080, 0x0 }, - { 0x5080, 0x0 }, - { 0x105080, 0x0 }, - { 0x205080, 0x0 }, - { 0x6080, 0x0 }, - { 0x106080, 0x0 }, - { 0x206080, 0x0 }, - { 0x7080, 0x0 }, - { 0x107080, 0x0 }, - { 0x207080, 0x0 }, - { 0x8080, 0x0 }, - { 0x108080, 0x0 }, - { 0x208080, 0x0 }, - { 0x9080, 0x0 }, - { 0x109080, 0x0 }, - { 0x209080, 0x0 }, - { 0x10080, 0x0 }, - { 0x110080, 0x0 }, - { 0x210080, 0x0 }, - { 0x10180, 0x0 }, - { 0x110180, 0x0 }, - { 0x210180, 0x0 }, - { 0x11080, 0x0 }, - { 0x111080, 0x0 }, - { 0x211080, 0x0 }, - { 0x11180, 0x0 }, - { 0x111180, 0x0 }, - { 0x211180, 0x0 }, - { 0x12080, 0x0 }, - { 0x112080, 0x0 }, - { 0x212080, 0x0 }, - { 0x12180, 0x0 }, - { 0x112180, 0x0 }, - { 0x212180, 0x0 }, - { 0x13080, 0x0 }, - { 0x113080, 0x0 }, - { 0x213080, 0x0 }, - { 0x13180, 0x0 }, - { 0x113180, 0x0 }, - { 0x213180, 0x0 }, - { 0x10081, 0x0 }, - { 0x110081, 0x0 }, - { 0x210081, 0x0 }, - { 0x10181, 0x0 }, - { 0x110181, 0x0 }, - { 0x210181, 0x0 }, - { 0x11081, 0x0 }, - { 0x111081, 0x0 }, - { 0x211081, 0x0 }, - { 0x11181, 0x0 }, - { 0x111181, 0x0 }, - { 0x211181, 0x0 }, - { 0x12081, 0x0 }, - { 0x112081, 0x0 }, - { 0x212081, 0x0 }, - { 0x12181, 0x0 }, - { 0x112181, 0x0 }, - { 0x212181, 0x0 }, - { 0x13081, 0x0 }, - { 0x113081, 0x0 }, - { 0x213081, 0x0 }, - { 0x13181, 0x0 }, - { 0x113181, 0x0 }, - { 0x213181, 0x0 }, - { 0x100d0, 0x0 }, - { 0x1100d0, 0x0 }, - { 0x2100d0, 0x0 }, - { 0x101d0, 0x0 }, - { 0x1101d0, 0x0 }, - { 0x2101d0, 0x0 }, - { 0x110d0, 0x0 }, - { 0x1110d0, 0x0 }, - { 0x2110d0, 0x0 }, - { 0x111d0, 0x0 }, - { 0x1111d0, 0x0 }, - { 0x2111d0, 0x0 }, - { 0x120d0, 0x0 }, - { 0x1120d0, 0x0 }, - { 0x2120d0, 0x0 }, - { 0x121d0, 0x0 }, - { 0x1121d0, 0x0 }, - { 0x2121d0, 0x0 }, - { 0x130d0, 0x0 }, - { 0x1130d0, 0x0 }, - { 0x2130d0, 0x0 }, - { 0x131d0, 0x0 }, - { 0x1131d0, 0x0 }, - { 0x2131d0, 0x0 }, - { 0x100d1, 0x0 }, - { 0x1100d1, 0x0 }, - { 0x2100d1, 0x0 }, - { 0x101d1, 0x0 }, - { 0x1101d1, 0x0 }, - { 0x2101d1, 0x0 }, - { 0x110d1, 0x0 }, - { 0x1110d1, 0x0 }, - { 0x2110d1, 0x0 }, - { 0x111d1, 0x0 }, - { 0x1111d1, 0x0 }, - { 0x2111d1, 0x0 }, - { 0x120d1, 0x0 }, - { 0x1120d1, 0x0 }, - { 0x2120d1, 0x0 }, - { 0x121d1, 0x0 }, - { 0x1121d1, 0x0 }, - { 0x2121d1, 0x0 }, - { 0x130d1, 0x0 }, - { 0x1130d1, 0x0 }, - { 0x2130d1, 0x0 }, - { 0x131d1, 0x0 }, - { 0x1131d1, 0x0 }, - { 0x2131d1, 0x0 }, - { 0x10068, 0x0 }, - { 0x10168, 0x0 }, - { 0x10268, 0x0 }, - { 0x10368, 0x0 }, - { 0x10468, 0x0 }, - { 0x10568, 0x0 }, - { 0x10668, 0x0 }, - { 0x10768, 0x0 }, - { 0x10868, 0x0 }, - { 0x11068, 0x0 }, - { 0x11168, 0x0 }, - { 0x11268, 0x0 }, - { 0x11368, 0x0 }, - { 0x11468, 0x0 }, - { 0x11568, 0x0 }, - { 0x11668, 0x0 }, - { 0x11768, 0x0 }, - { 0x11868, 0x0 }, - { 0x12068, 0x0 }, - { 0x12168, 0x0 }, - { 0x12268, 0x0 }, - { 0x12368, 0x0 }, - { 0x12468, 0x0 }, - { 0x12568, 0x0 }, - { 0x12668, 0x0 }, - { 0x12768, 0x0 }, - { 0x12868, 0x0 }, - { 0x13068, 0x0 }, - { 0x13168, 0x0 }, - { 0x13268, 0x0 }, - { 0x13368, 0x0 }, - { 0x13468, 0x0 }, - { 0x13568, 0x0 }, - { 0x13668, 0x0 }, - { 0x13768, 0x0 }, - { 0x13868, 0x0 }, - { 0x10069, 0x0 }, - { 0x10169, 0x0 }, - { 0x10269, 0x0 }, - { 0x10369, 0x0 }, - { 0x10469, 0x0 }, - { 0x10569, 0x0 }, - { 0x10669, 0x0 }, - { 0x10769, 0x0 }, - { 0x10869, 0x0 }, - { 0x11069, 0x0 }, - { 0x11169, 0x0 }, - { 0x11269, 0x0 }, - { 0x11369, 0x0 }, - { 0x11469, 0x0 }, - { 0x11569, 0x0 }, - { 0x11669, 0x0 }, - { 0x11769, 0x0 }, - { 0x11869, 0x0 }, - { 0x12069, 0x0 }, - { 0x12169, 0x0 }, - { 0x12269, 0x0 }, - { 0x12369, 0x0 }, - { 0x12469, 0x0 }, - { 0x12569, 0x0 }, - { 0x12669, 0x0 }, - { 0x12769, 0x0 }, - { 0x12869, 0x0 }, - { 0x13069, 0x0 }, - { 0x13169, 0x0 }, - { 0x13269, 0x0 }, - { 0x13369, 0x0 }, - { 0x13469, 0x0 }, - { 0x13569, 0x0 }, - { 0x13669, 0x0 }, - { 0x13769, 0x0 }, - { 0x13869, 0x0 }, - { 0x1008c, 0x0 }, - { 0x11008c, 0x0 }, - { 0x21008c, 0x0 }, - { 0x1018c, 0x0 }, - { 0x11018c, 0x0 }, - { 0x21018c, 0x0 }, - { 0x1108c, 0x0 }, - { 0x11108c, 0x0 }, - { 0x21108c, 0x0 }, - { 0x1118c, 0x0 }, - { 0x11118c, 0x0 }, - { 0x21118c, 0x0 }, - { 0x1208c, 0x0 }, - { 0x11208c, 0x0 }, - { 0x21208c, 0x0 }, - { 0x1218c, 0x0 }, - { 0x11218c, 0x0 }, - { 0x21218c, 0x0 }, - { 0x1308c, 0x0 }, - { 0x11308c, 0x0 }, - { 0x21308c, 0x0 }, - { 0x1318c, 0x0 }, - { 0x11318c, 0x0 }, - { 0x21318c, 0x0 }, - { 0x1008d, 0x0 }, - { 0x11008d, 0x0 }, - { 0x21008d, 0x0 }, - { 0x1018d, 0x0 }, - { 0x11018d, 0x0 }, - { 0x21018d, 0x0 }, - { 0x1108d, 0x0 }, - { 0x11108d, 0x0 }, - { 0x21108d, 0x0 }, - { 0x1118d, 0x0 }, - { 0x11118d, 0x0 }, - { 0x21118d, 0x0 }, - { 0x1208d, 0x0 }, - { 0x11208d, 0x0 }, - { 0x21208d, 0x0 }, - { 0x1218d, 0x0 }, - { 0x11218d, 0x0 }, - { 0x21218d, 0x0 }, - { 0x1308d, 0x0 }, - { 0x11308d, 0x0 }, - { 0x21308d, 0x0 }, - { 0x1318d, 0x0 }, - { 0x11318d, 0x0 }, - { 0x21318d, 0x0 }, - { 0x100c0, 0x0 }, - { 0x1100c0, 0x0 }, - { 0x2100c0, 0x0 }, - { 0x101c0, 0x0 }, - { 0x1101c0, 0x0 }, - { 0x2101c0, 0x0 }, - { 0x102c0, 0x0 }, - { 0x1102c0, 0x0 }, - { 0x2102c0, 0x0 }, - { 0x103c0, 0x0 }, - { 0x1103c0, 0x0 }, - { 0x2103c0, 0x0 }, - { 0x104c0, 0x0 }, - { 0x1104c0, 0x0 }, - { 0x2104c0, 0x0 }, - { 0x105c0, 0x0 }, - { 0x1105c0, 0x0 }, - { 0x2105c0, 0x0 }, - { 0x106c0, 0x0 }, - { 0x1106c0, 0x0 }, - { 0x2106c0, 0x0 }, - { 0x107c0, 0x0 }, - { 0x1107c0, 0x0 }, - { 0x2107c0, 0x0 }, - { 0x108c0, 0x0 }, - { 0x1108c0, 0x0 }, - { 0x2108c0, 0x0 }, - { 0x110c0, 0x0 }, - { 0x1110c0, 0x0 }, - { 0x2110c0, 0x0 }, - { 0x111c0, 0x0 }, - { 0x1111c0, 0x0 }, - { 0x2111c0, 0x0 }, - { 0x112c0, 0x0 }, - { 0x1112c0, 0x0 }, - { 0x2112c0, 0x0 }, - { 0x113c0, 0x0 }, - { 0x1113c0, 0x0 }, - { 0x2113c0, 0x0 }, - { 0x114c0, 0x0 }, - { 0x1114c0, 0x0 }, - { 0x2114c0, 0x0 }, - { 0x115c0, 0x0 }, - { 0x1115c0, 0x0 }, - { 0x2115c0, 0x0 }, - { 0x116c0, 0x0 }, - { 0x1116c0, 0x0 }, - { 0x2116c0, 0x0 }, - { 0x117c0, 0x0 }, - { 0x1117c0, 0x0 }, - { 0x2117c0, 0x0 }, - { 0x118c0, 0x0 }, - { 0x1118c0, 0x0 }, - { 0x2118c0, 0x0 }, - { 0x120c0, 0x0 }, - { 0x1120c0, 0x0 }, - { 0x2120c0, 0x0 }, - { 0x121c0, 0x0 }, - { 0x1121c0, 0x0 }, - { 0x2121c0, 0x0 }, - { 0x122c0, 0x0 }, - { 0x1122c0, 0x0 }, - { 0x2122c0, 0x0 }, - { 0x123c0, 0x0 }, - { 0x1123c0, 0x0 }, - { 0x2123c0, 0x0 }, - { 0x124c0, 0x0 }, - { 0x1124c0, 0x0 }, - { 0x2124c0, 0x0 }, - { 0x125c0, 0x0 }, - { 0x1125c0, 0x0 }, - { 0x2125c0, 0x0 }, - { 0x126c0, 0x0 }, - { 0x1126c0, 0x0 }, - { 0x2126c0, 0x0 }, - { 0x127c0, 0x0 }, - { 0x1127c0, 0x0 }, - { 0x2127c0, 0x0 }, - { 0x128c0, 0x0 }, - { 0x1128c0, 0x0 }, - { 0x2128c0, 0x0 }, - { 0x130c0, 0x0 }, - { 0x1130c0, 0x0 }, - { 0x2130c0, 0x0 }, - { 0x131c0, 0x0 }, - { 0x1131c0, 0x0 }, - { 0x2131c0, 0x0 }, - { 0x132c0, 0x0 }, - { 0x1132c0, 0x0 }, - { 0x2132c0, 0x0 }, - { 0x133c0, 0x0 }, - { 0x1133c0, 0x0 }, - { 0x2133c0, 0x0 }, - { 0x134c0, 0x0 }, - { 0x1134c0, 0x0 }, - { 0x2134c0, 0x0 }, - { 0x135c0, 0x0 }, - { 0x1135c0, 0x0 }, - { 0x2135c0, 0x0 }, - { 0x136c0, 0x0 }, - { 0x1136c0, 0x0 }, - { 0x2136c0, 0x0 }, - { 0x137c0, 0x0 }, - { 0x1137c0, 0x0 }, - { 0x2137c0, 0x0 }, - { 0x138c0, 0x0 }, - { 0x1138c0, 0x0 }, - { 0x2138c0, 0x0 }, - { 0x100c1, 0x0 }, - { 0x1100c1, 0x0 }, - { 0x2100c1, 0x0 }, - { 0x101c1, 0x0 }, - { 0x1101c1, 0x0 }, - { 0x2101c1, 0x0 }, - { 0x102c1, 0x0 }, - { 0x1102c1, 0x0 }, - { 0x2102c1, 0x0 }, - { 0x103c1, 0x0 }, - { 0x1103c1, 0x0 }, - { 0x2103c1, 0x0 }, - { 0x104c1, 0x0 }, - { 0x1104c1, 0x0 }, - { 0x2104c1, 0x0 }, - { 0x105c1, 0x0 }, - { 0x1105c1, 0x0 }, - { 0x2105c1, 0x0 }, - { 0x106c1, 0x0 }, - { 0x1106c1, 0x0 }, - { 0x2106c1, 0x0 }, - { 0x107c1, 0x0 }, - { 0x1107c1, 0x0 }, - { 0x2107c1, 0x0 }, - { 0x108c1, 0x0 }, - { 0x1108c1, 0x0 }, - { 0x2108c1, 0x0 }, - { 0x110c1, 0x0 }, - { 0x1110c1, 0x0 }, - { 0x2110c1, 0x0 }, - { 0x111c1, 0x0 }, - { 0x1111c1, 0x0 }, - { 0x2111c1, 0x0 }, - { 0x112c1, 0x0 }, - { 0x1112c1, 0x0 }, - { 0x2112c1, 0x0 }, - { 0x113c1, 0x0 }, - { 0x1113c1, 0x0 }, - { 0x2113c1, 0x0 }, - { 0x114c1, 0x0 }, - { 0x1114c1, 0x0 }, - { 0x2114c1, 0x0 }, - { 0x115c1, 0x0 }, - { 0x1115c1, 0x0 }, - { 0x2115c1, 0x0 }, - { 0x116c1, 0x0 }, - { 0x1116c1, 0x0 }, - { 0x2116c1, 0x0 }, - { 0x117c1, 0x0 }, - { 0x1117c1, 0x0 }, - { 0x2117c1, 0x0 }, - { 0x118c1, 0x0 }, - { 0x1118c1, 0x0 }, - { 0x2118c1, 0x0 }, - { 0x120c1, 0x0 }, - { 0x1120c1, 0x0 }, - { 0x2120c1, 0x0 }, - { 0x121c1, 0x0 }, - { 0x1121c1, 0x0 }, - { 0x2121c1, 0x0 }, - { 0x122c1, 0x0 }, - { 0x1122c1, 0x0 }, - { 0x2122c1, 0x0 }, - { 0x123c1, 0x0 }, - { 0x1123c1, 0x0 }, - { 0x2123c1, 0x0 }, - { 0x124c1, 0x0 }, - { 0x1124c1, 0x0 }, - { 0x2124c1, 0x0 }, - { 0x125c1, 0x0 }, - { 0x1125c1, 0x0 }, - { 0x2125c1, 0x0 }, - { 0x126c1, 0x0 }, - { 0x1126c1, 0x0 }, - { 0x2126c1, 0x0 }, - { 0x127c1, 0x0 }, - { 0x1127c1, 0x0 }, - { 0x2127c1, 0x0 }, - { 0x128c1, 0x0 }, - { 0x1128c1, 0x0 }, - { 0x2128c1, 0x0 }, - { 0x130c1, 0x0 }, - { 0x1130c1, 0x0 }, - { 0x2130c1, 0x0 }, - { 0x131c1, 0x0 }, - { 0x1131c1, 0x0 }, - { 0x2131c1, 0x0 }, - { 0x132c1, 0x0 }, - { 0x1132c1, 0x0 }, - { 0x2132c1, 0x0 }, - { 0x133c1, 0x0 }, - { 0x1133c1, 0x0 }, - { 0x2133c1, 0x0 }, - { 0x134c1, 0x0 }, - { 0x1134c1, 0x0 }, - { 0x2134c1, 0x0 }, - { 0x135c1, 0x0 }, - { 0x1135c1, 0x0 }, - { 0x2135c1, 0x0 }, - { 0x136c1, 0x0 }, - { 0x1136c1, 0x0 }, - { 0x2136c1, 0x0 }, - { 0x137c1, 0x0 }, - { 0x1137c1, 0x0 }, - { 0x2137c1, 0x0 }, - { 0x138c1, 0x0 }, - { 0x1138c1, 0x0 }, - { 0x2138c1, 0x0 }, - { 0x10020, 0x0 }, - { 0x110020, 0x0 }, - { 0x210020, 0x0 }, - { 0x11020, 0x0 }, - { 0x111020, 0x0 }, - { 0x211020, 0x0 }, - { 0x12020, 0x0 }, - { 0x112020, 0x0 }, - { 0x212020, 0x0 }, - { 0x13020, 0x0 }, - { 0x113020, 0x0 }, - { 0x213020, 0x0 }, - { 0x20072, 0x0 }, - { 0x20073, 0x0 }, - { 0x20074, 0x0 }, - { 0x100aa, 0x0 }, - { 0x110aa, 0x0 }, - { 0x120aa, 0x0 }, - { 0x130aa, 0x0 }, - { 0x20010, 0x0 }, - { 0x120010, 0x0 }, - { 0x220010, 0x0 }, - { 0x20011, 0x0 }, - { 0x120011, 0x0 }, - { 0x220011, 0x0 }, - { 0x100ae, 0x0 }, - { 0x1100ae, 0x0 }, - { 0x2100ae, 0x0 }, - { 0x100af, 0x0 }, - { 0x1100af, 0x0 }, - { 0x2100af, 0x0 }, - { 0x110ae, 0x0 }, - { 0x1110ae, 0x0 }, - { 0x2110ae, 0x0 }, - { 0x110af, 0x0 }, - { 0x1110af, 0x0 }, - { 0x2110af, 0x0 }, - { 0x120ae, 0x0 }, - { 0x1120ae, 0x0 }, - { 0x2120ae, 0x0 }, - { 0x120af, 0x0 }, - { 0x1120af, 0x0 }, - { 0x2120af, 0x0 }, - { 0x130ae, 0x0 }, - { 0x1130ae, 0x0 }, - { 0x2130ae, 0x0 }, - { 0x130af, 0x0 }, - { 0x1130af, 0x0 }, - { 0x2130af, 0x0 }, - { 0x20020, 0x0 }, - { 0x120020, 0x0 }, - { 0x220020, 0x0 }, - { 0x100a0, 0x0 }, - { 0x100a1, 0x0 }, - { 0x100a2, 0x0 }, - { 0x100a3, 0x0 }, - { 0x100a4, 0x0 }, - { 0x100a5, 0x0 }, - { 0x100a6, 0x0 }, - { 0x100a7, 0x0 }, - { 0x110a0, 0x0 }, - { 0x110a1, 0x0 }, - { 0x110a2, 0x0 }, - { 0x110a3, 0x0 }, - { 0x110a4, 0x0 }, - { 0x110a5, 0x0 }, - { 0x110a6, 0x0 }, - { 0x110a7, 0x0 }, - { 0x120a0, 0x0 }, - { 0x120a1, 0x0 }, - { 0x120a2, 0x0 }, - { 0x120a3, 0x0 }, - { 0x120a4, 0x0 }, - { 0x120a5, 0x0 }, - { 0x120a6, 0x0 }, - { 0x120a7, 0x0 }, - { 0x130a0, 0x0 }, - { 0x130a1, 0x0 }, - { 0x130a2, 0x0 }, - { 0x130a3, 0x0 }, - { 0x130a4, 0x0 }, - { 0x130a5, 0x0 }, - { 0x130a6, 0x0 }, - { 0x130a7, 0x0 }, - { 0x2007c, 0x0 }, - { 0x12007c, 0x0 }, - { 0x22007c, 0x0 }, - { 0x2007d, 0x0 }, - { 0x12007d, 0x0 }, - { 0x22007d, 0x0 }, - { 0x400fd, 0x0 }, - { 0x400c0, 0x0 }, - { 0x90201, 0x0 }, - { 0x190201, 0x0 }, - { 0x290201, 0x0 }, - { 0x90202, 0x0 }, - { 0x190202, 0x0 }, - { 0x290202, 0x0 }, - { 0x90203, 0x0 }, - { 0x190203, 0x0 }, - { 0x290203, 0x0 }, - { 0x90204, 0x0 }, - { 0x190204, 0x0 }, - { 0x290204, 0x0 }, - { 0x90205, 0x0 }, - { 0x190205, 0x0 }, - { 0x290205, 0x0 }, - { 0x90206, 0x0 }, - { 0x190206, 0x0 }, - { 0x290206, 0x0 }, - { 0x90207, 0x0 }, - { 0x190207, 0x0 }, - { 0x290207, 0x0 }, - { 0x90208, 0x0 }, - { 0x190208, 0x0 }, - { 0x290208, 0x0 }, - { 0x10062, 0x0 }, - { 0x10162, 0x0 }, - { 0x10262, 0x0 }, - { 0x10362, 0x0 }, - { 0x10462, 0x0 }, - { 0x10562, 0x0 }, - { 0x10662, 0x0 }, - { 0x10762, 0x0 }, - { 0x10862, 0x0 }, - { 0x11062, 0x0 }, - { 0x11162, 0x0 }, - { 0x11262, 0x0 }, - { 0x11362, 0x0 }, - { 0x11462, 0x0 }, - { 0x11562, 0x0 }, - { 0x11662, 0x0 }, - { 0x11762, 0x0 }, - { 0x11862, 0x0 }, - { 0x12062, 0x0 }, - { 0x12162, 0x0 }, - { 0x12262, 0x0 }, - { 0x12362, 0x0 }, - { 0x12462, 0x0 }, - { 0x12562, 0x0 }, - { 0x12662, 0x0 }, - { 0x12762, 0x0 }, - { 0x12862, 0x0 }, - { 0x13062, 0x0 }, - { 0x13162, 0x0 }, - { 0x13262, 0x0 }, - { 0x13362, 0x0 }, - { 0x13462, 0x0 }, - { 0x13562, 0x0 }, - { 0x13662, 0x0 }, - { 0x13762, 0x0 }, - { 0x13862, 0x0 }, - { 0x20077, 0x0 }, - { 0x10001, 0x0 }, - { 0x11001, 0x0 }, - { 0x12001, 0x0 }, - { 0x13001, 0x0 }, - { 0x10040, 0x0 }, - { 0x10140, 0x0 }, - { 0x10240, 0x0 }, - { 0x10340, 0x0 }, - { 0x10440, 0x0 }, - { 0x10540, 0x0 }, - { 0x10640, 0x0 }, - { 0x10740, 0x0 }, - { 0x10840, 0x0 }, - { 0x10030, 0x0 }, - { 0x10130, 0x0 }, - { 0x10230, 0x0 }, - { 0x10330, 0x0 }, - { 0x10430, 0x0 }, - { 0x10530, 0x0 }, - { 0x10630, 0x0 }, - { 0x10730, 0x0 }, - { 0x10830, 0x0 }, - { 0x11040, 0x0 }, - { 0x11140, 0x0 }, - { 0x11240, 0x0 }, - { 0x11340, 0x0 }, - { 0x11440, 0x0 }, - { 0x11540, 0x0 }, - { 0x11640, 0x0 }, - { 0x11740, 0x0 }, - { 0x11840, 0x0 }, - { 0x11030, 0x0 }, - { 0x11130, 0x0 }, - { 0x11230, 0x0 }, - { 0x11330, 0x0 }, - { 0x11430, 0x0 }, - { 0x11530, 0x0 }, - { 0x11630, 0x0 }, - { 0x11730, 0x0 }, - { 0x11830, 0x0 }, - { 0x12040, 0x0 }, - { 0x12140, 0x0 }, - { 0x12240, 0x0 }, - { 0x12340, 0x0 }, - { 0x12440, 0x0 }, - { 0x12540, 0x0 }, - { 0x12640, 0x0 }, - { 0x12740, 0x0 }, - { 0x12840, 0x0 }, - { 0x12030, 0x0 }, - { 0x12130, 0x0 }, - { 0x12230, 0x0 }, - { 0x12330, 0x0 }, - { 0x12430, 0x0 }, - { 0x12530, 0x0 }, - { 0x12630, 0x0 }, - { 0x12730, 0x0 }, - { 0x12830, 0x0 }, - { 0x13040, 0x0 }, - { 0x13140, 0x0 }, - { 0x13240, 0x0 }, - { 0x13340, 0x0 }, - { 0x13440, 0x0 }, - { 0x13540, 0x0 }, - { 0x13640, 0x0 }, - { 0x13740, 0x0 }, - { 0x13840, 0x0 }, - { 0x13030, 0x0 }, - { 0x13130, 0x0 }, - { 0x13230, 0x0 }, - { 0x13330, 0x0 }, - { 0x13430, 0x0 }, - { 0x13530, 0x0 }, - { 0x13630, 0x0 }, - { 0x13730, 0x0 }, - { 0x13830, 0x0 }, + {0x200b2, 0x0}, + {0x1200b2, 0x0}, + {0x2200b2, 0x0}, + {0x200cb, 0x0}, + {0x10043, 0x0}, + {0x110043, 0x0}, + {0x210043, 0x0}, + {0x10143, 0x0}, + {0x110143, 0x0}, + {0x210143, 0x0}, + {0x11043, 0x0}, + {0x111043, 0x0}, + {0x211043, 0x0}, + {0x11143, 0x0}, + {0x111143, 0x0}, + {0x211143, 0x0}, + {0x12043, 0x0}, + {0x112043, 0x0}, + {0x212043, 0x0}, + {0x12143, 0x0}, + {0x112143, 0x0}, + {0x212143, 0x0}, + {0x13043, 0x0}, + {0x113043, 0x0}, + {0x213043, 0x0}, + {0x13143, 0x0}, + {0x113143, 0x0}, + {0x213143, 0x0}, + {0x80, 0x0}, + {0x100080, 0x0}, + {0x200080, 0x0}, + {0x1080, 0x0}, + {0x101080, 0x0}, + {0x201080, 0x0}, + {0x2080, 0x0}, + {0x102080, 0x0}, + {0x202080, 0x0}, + {0x3080, 0x0}, + {0x103080, 0x0}, + {0x203080, 0x0}, + {0x4080, 0x0}, + {0x104080, 0x0}, + {0x204080, 0x0}, + {0x5080, 0x0}, + {0x105080, 0x0}, + {0x205080, 0x0}, + {0x6080, 0x0}, + {0x106080, 0x0}, + {0x206080, 0x0}, + {0x7080, 0x0}, + {0x107080, 0x0}, + {0x207080, 0x0}, + {0x8080, 0x0}, + {0x108080, 0x0}, + {0x208080, 0x0}, + {0x9080, 0x0}, + {0x109080, 0x0}, + {0x209080, 0x0}, + {0x10080, 0x0}, + {0x110080, 0x0}, + {0x210080, 0x0}, + {0x10180, 0x0}, + {0x110180, 0x0}, + {0x210180, 0x0}, + {0x11080, 0x0}, + {0x111080, 0x0}, + {0x211080, 0x0}, + {0x11180, 0x0}, + {0x111180, 0x0}, + {0x211180, 0x0}, + {0x12080, 0x0}, + {0x112080, 0x0}, + {0x212080, 0x0}, + {0x12180, 0x0}, + {0x112180, 0x0}, + {0x212180, 0x0}, + {0x13080, 0x0}, + {0x113080, 0x0}, + {0x213080, 0x0}, + {0x13180, 0x0}, + {0x113180, 0x0}, + {0x213180, 0x0}, + {0x10081, 0x0}, + {0x110081, 0x0}, + {0x210081, 0x0}, + {0x10181, 0x0}, + {0x110181, 0x0}, + {0x210181, 0x0}, + {0x11081, 0x0}, + {0x111081, 0x0}, + {0x211081, 0x0}, + {0x11181, 0x0}, + {0x111181, 0x0}, + {0x211181, 0x0}, + {0x12081, 0x0}, + {0x112081, 0x0}, + {0x212081, 0x0}, + {0x12181, 0x0}, + {0x112181, 0x0}, + {0x212181, 0x0}, + {0x13081, 0x0}, + {0x113081, 0x0}, + {0x213081, 0x0}, + {0x13181, 0x0}, + {0x113181, 0x0}, + {0x213181, 0x0}, + {0x100d0, 0x0}, + {0x1100d0, 0x0}, + {0x2100d0, 0x0}, + {0x101d0, 0x0}, + {0x1101d0, 0x0}, + {0x2101d0, 0x0}, + {0x110d0, 0x0}, + {0x1110d0, 0x0}, + {0x2110d0, 0x0}, + {0x111d0, 0x0}, + {0x1111d0, 0x0}, + {0x2111d0, 0x0}, + {0x120d0, 0x0}, + {0x1120d0, 0x0}, + {0x2120d0, 0x0}, + {0x121d0, 0x0}, + {0x1121d0, 0x0}, + {0x2121d0, 0x0}, + {0x130d0, 0x0}, + {0x1130d0, 0x0}, + {0x2130d0, 0x0}, + {0x131d0, 0x0}, + {0x1131d0, 0x0}, + {0x2131d0, 0x0}, + {0x100d1, 0x0}, + {0x1100d1, 0x0}, + {0x2100d1, 0x0}, + {0x101d1, 0x0}, + {0x1101d1, 0x0}, + {0x2101d1, 0x0}, + {0x110d1, 0x0}, + {0x1110d1, 0x0}, + {0x2110d1, 0x0}, + {0x111d1, 0x0}, + {0x1111d1, 0x0}, + {0x2111d1, 0x0}, + {0x120d1, 0x0}, + {0x1120d1, 0x0}, + {0x2120d1, 0x0}, + {0x121d1, 0x0}, + {0x1121d1, 0x0}, + {0x2121d1, 0x0}, + {0x130d1, 0x0}, + {0x1130d1, 0x0}, + {0x2130d1, 0x0}, + {0x131d1, 0x0}, + {0x1131d1, 0x0}, + {0x2131d1, 0x0}, + {0x10068, 0x0}, + {0x10168, 0x0}, + {0x10268, 0x0}, + {0x10368, 0x0}, + {0x10468, 0x0}, + {0x10568, 0x0}, + {0x10668, 0x0}, + {0x10768, 0x0}, + {0x10868, 0x0}, + {0x11068, 0x0}, + {0x11168, 0x0}, + {0x11268, 0x0}, + {0x11368, 0x0}, + {0x11468, 0x0}, + {0x11568, 0x0}, + {0x11668, 0x0}, + {0x11768, 0x0}, + {0x11868, 0x0}, + {0x12068, 0x0}, + {0x12168, 0x0}, + {0x12268, 0x0}, + {0x12368, 0x0}, + {0x12468, 0x0}, + {0x12568, 0x0}, + {0x12668, 0x0}, + {0x12768, 0x0}, + {0x12868, 0x0}, + {0x13068, 0x0}, + {0x13168, 0x0}, + {0x13268, 0x0}, + {0x13368, 0x0}, + {0x13468, 0x0}, + {0x13568, 0x0}, + {0x13668, 0x0}, + {0x13768, 0x0}, + {0x13868, 0x0}, + {0x10069, 0x0}, + {0x10169, 0x0}, + {0x10269, 0x0}, + {0x10369, 0x0}, + {0x10469, 0x0}, + {0x10569, 0x0}, + {0x10669, 0x0}, + {0x10769, 0x0}, + {0x10869, 0x0}, + {0x11069, 0x0}, + {0x11169, 0x0}, + {0x11269, 0x0}, + {0x11369, 0x0}, + {0x11469, 0x0}, + {0x11569, 0x0}, + {0x11669, 0x0}, + {0x11769, 0x0}, + {0x11869, 0x0}, + {0x12069, 0x0}, + {0x12169, 0x0}, + {0x12269, 0x0}, + {0x12369, 0x0}, + {0x12469, 0x0}, + {0x12569, 0x0}, + {0x12669, 0x0}, + {0x12769, 0x0}, + {0x12869, 0x0}, + {0x13069, 0x0}, + {0x13169, 0x0}, + {0x13269, 0x0}, + {0x13369, 0x0}, + {0x13469, 0x0}, + {0x13569, 0x0}, + {0x13669, 0x0}, + {0x13769, 0x0}, + {0x13869, 0x0}, + {0x1008c, 0x0}, + {0x11008c, 0x0}, + {0x21008c, 0x0}, + {0x1018c, 0x0}, + {0x11018c, 0x0}, + {0x21018c, 0x0}, + {0x1108c, 0x0}, + {0x11108c, 0x0}, + {0x21108c, 0x0}, + {0x1118c, 0x0}, + {0x11118c, 0x0}, + {0x21118c, 0x0}, + {0x1208c, 0x0}, + {0x11208c, 0x0}, + {0x21208c, 0x0}, + {0x1218c, 0x0}, + {0x11218c, 0x0}, + {0x21218c, 0x0}, + {0x1308c, 0x0}, + {0x11308c, 0x0}, + {0x21308c, 0x0}, + {0x1318c, 0x0}, + {0x11318c, 0x0}, + {0x21318c, 0x0}, + {0x1008d, 0x0}, + {0x11008d, 0x0}, + {0x21008d, 0x0}, + {0x1018d, 0x0}, + {0x11018d, 0x0}, + {0x21018d, 0x0}, + {0x1108d, 0x0}, + {0x11108d, 0x0}, + {0x21108d, 0x0}, + {0x1118d, 0x0}, + {0x11118d, 0x0}, + {0x21118d, 0x0}, + {0x1208d, 0x0}, + {0x11208d, 0x0}, + {0x21208d, 0x0}, + {0x1218d, 0x0}, + {0x11218d, 0x0}, + {0x21218d, 0x0}, + {0x1308d, 0x0}, + {0x11308d, 0x0}, + {0x21308d, 0x0}, + {0x1318d, 0x0}, + {0x11318d, 0x0}, + {0x21318d, 0x0}, + {0x100c0, 0x0}, + {0x1100c0, 0x0}, + {0x2100c0, 0x0}, + {0x101c0, 0x0}, + {0x1101c0, 0x0}, + {0x2101c0, 0x0}, + {0x102c0, 0x0}, + {0x1102c0, 0x0}, + {0x2102c0, 0x0}, + {0x103c0, 0x0}, + {0x1103c0, 0x0}, + {0x2103c0, 0x0}, + {0x104c0, 0x0}, + {0x1104c0, 0x0}, + {0x2104c0, 0x0}, + {0x105c0, 0x0}, + {0x1105c0, 0x0}, + {0x2105c0, 0x0}, + {0x106c0, 0x0}, + {0x1106c0, 0x0}, + {0x2106c0, 0x0}, + {0x107c0, 0x0}, + {0x1107c0, 0x0}, + {0x2107c0, 0x0}, + {0x108c0, 0x0}, + {0x1108c0, 0x0}, + {0x2108c0, 0x0}, + {0x110c0, 0x0}, + {0x1110c0, 0x0}, + {0x2110c0, 0x0}, + {0x111c0, 0x0}, + {0x1111c0, 0x0}, + {0x2111c0, 0x0}, + {0x112c0, 0x0}, + {0x1112c0, 0x0}, + {0x2112c0, 0x0}, + {0x113c0, 0x0}, + {0x1113c0, 0x0}, + {0x2113c0, 0x0}, + {0x114c0, 0x0}, + {0x1114c0, 0x0}, + {0x2114c0, 0x0}, + {0x115c0, 0x0}, + {0x1115c0, 0x0}, + {0x2115c0, 0x0}, + {0x116c0, 0x0}, + {0x1116c0, 0x0}, + {0x2116c0, 0x0}, + {0x117c0, 0x0}, + {0x1117c0, 0x0}, + {0x2117c0, 0x0}, + {0x118c0, 0x0}, + {0x1118c0, 0x0}, + {0x2118c0, 0x0}, + {0x120c0, 0x0}, + {0x1120c0, 0x0}, + {0x2120c0, 0x0}, + {0x121c0, 0x0}, + {0x1121c0, 0x0}, + {0x2121c0, 0x0}, + {0x122c0, 0x0}, + {0x1122c0, 0x0}, + {0x2122c0, 0x0}, + {0x123c0, 0x0}, + {0x1123c0, 0x0}, + {0x2123c0, 0x0}, + {0x124c0, 0x0}, + {0x1124c0, 0x0}, + {0x2124c0, 0x0}, + {0x125c0, 0x0}, + {0x1125c0, 0x0}, + {0x2125c0, 0x0}, + {0x126c0, 0x0}, + {0x1126c0, 0x0}, + {0x2126c0, 0x0}, + {0x127c0, 0x0}, + {0x1127c0, 0x0}, + {0x2127c0, 0x0}, + {0x128c0, 0x0}, + {0x1128c0, 0x0}, + {0x2128c0, 0x0}, + {0x130c0, 0x0}, + {0x1130c0, 0x0}, + {0x2130c0, 0x0}, + {0x131c0, 0x0}, + {0x1131c0, 0x0}, + {0x2131c0, 0x0}, + {0x132c0, 0x0}, + {0x1132c0, 0x0}, + {0x2132c0, 0x0}, + {0x133c0, 0x0}, + {0x1133c0, 0x0}, + {0x2133c0, 0x0}, + {0x134c0, 0x0}, + {0x1134c0, 0x0}, + {0x2134c0, 0x0}, + {0x135c0, 0x0}, + {0x1135c0, 0x0}, + {0x2135c0, 0x0}, + {0x136c0, 0x0}, + {0x1136c0, 0x0}, + {0x2136c0, 0x0}, + {0x137c0, 0x0}, + {0x1137c0, 0x0}, + {0x2137c0, 0x0}, + {0x138c0, 0x0}, + {0x1138c0, 0x0}, + {0x2138c0, 0x0}, + {0x100c1, 0x0}, + {0x1100c1, 0x0}, + {0x2100c1, 0x0}, + {0x101c1, 0x0}, + {0x1101c1, 0x0}, + {0x2101c1, 0x0}, + {0x102c1, 0x0}, + {0x1102c1, 0x0}, + {0x2102c1, 0x0}, + {0x103c1, 0x0}, + {0x1103c1, 0x0}, + {0x2103c1, 0x0}, + {0x104c1, 0x0}, + {0x1104c1, 0x0}, + {0x2104c1, 0x0}, + {0x105c1, 0x0}, + {0x1105c1, 0x0}, + {0x2105c1, 0x0}, + {0x106c1, 0x0}, + {0x1106c1, 0x0}, + {0x2106c1, 0x0}, + {0x107c1, 0x0}, + {0x1107c1, 0x0}, + {0x2107c1, 0x0}, + {0x108c1, 0x0}, + {0x1108c1, 0x0}, + {0x2108c1, 0x0}, + {0x110c1, 0x0}, + {0x1110c1, 0x0}, + {0x2110c1, 0x0}, + {0x111c1, 0x0}, + {0x1111c1, 0x0}, + {0x2111c1, 0x0}, + {0x112c1, 0x0}, + {0x1112c1, 0x0}, + {0x2112c1, 0x0}, + {0x113c1, 0x0}, + {0x1113c1, 0x0}, + {0x2113c1, 0x0}, + {0x114c1, 0x0}, + {0x1114c1, 0x0}, + {0x2114c1, 0x0}, + {0x115c1, 0x0}, + {0x1115c1, 0x0}, + {0x2115c1, 0x0}, + {0x116c1, 0x0}, + {0x1116c1, 0x0}, + {0x2116c1, 0x0}, + {0x117c1, 0x0}, + {0x1117c1, 0x0}, + {0x2117c1, 0x0}, + {0x118c1, 0x0}, + {0x1118c1, 0x0}, + {0x2118c1, 0x0}, + {0x120c1, 0x0}, + {0x1120c1, 0x0}, + {0x2120c1, 0x0}, + {0x121c1, 0x0}, + {0x1121c1, 0x0}, + {0x2121c1, 0x0}, + {0x122c1, 0x0}, + {0x1122c1, 0x0}, + {0x2122c1, 0x0}, + {0x123c1, 0x0}, + {0x1123c1, 0x0}, + {0x2123c1, 0x0}, + {0x124c1, 0x0}, + {0x1124c1, 0x0}, + {0x2124c1, 0x0}, + {0x125c1, 0x0}, + {0x1125c1, 0x0}, + {0x2125c1, 0x0}, + {0x126c1, 0x0}, + {0x1126c1, 0x0}, + {0x2126c1, 0x0}, + {0x127c1, 0x0}, + {0x1127c1, 0x0}, + {0x2127c1, 0x0}, + {0x128c1, 0x0}, + {0x1128c1, 0x0}, + {0x2128c1, 0x0}, + {0x130c1, 0x0}, + {0x1130c1, 0x0}, + {0x2130c1, 0x0}, + {0x131c1, 0x0}, + {0x1131c1, 0x0}, + {0x2131c1, 0x0}, + {0x132c1, 0x0}, + {0x1132c1, 0x0}, + {0x2132c1, 0x0}, + {0x133c1, 0x0}, + {0x1133c1, 0x0}, + {0x2133c1, 0x0}, + {0x134c1, 0x0}, + {0x1134c1, 0x0}, + {0x2134c1, 0x0}, + {0x135c1, 0x0}, + {0x1135c1, 0x0}, + {0x2135c1, 0x0}, + {0x136c1, 0x0}, + {0x1136c1, 0x0}, + {0x2136c1, 0x0}, + {0x137c1, 0x0}, + {0x1137c1, 0x0}, + {0x2137c1, 0x0}, + {0x138c1, 0x0}, + {0x1138c1, 0x0}, + {0x2138c1, 0x0}, + {0x10020, 0x0}, + {0x110020, 0x0}, + {0x210020, 0x0}, + {0x11020, 0x0}, + {0x111020, 0x0}, + {0x211020, 0x0}, + {0x12020, 0x0}, + {0x112020, 0x0}, + {0x212020, 0x0}, + {0x13020, 0x0}, + {0x113020, 0x0}, + {0x213020, 0x0}, + {0x20072, 0x0}, + {0x20073, 0x0}, + {0x20074, 0x0}, + {0x100aa, 0x0}, + {0x110aa, 0x0}, + {0x120aa, 0x0}, + {0x130aa, 0x0}, + {0x20010, 0x0}, + {0x120010, 0x0}, + {0x220010, 0x0}, + {0x20011, 0x0}, + {0x120011, 0x0}, + {0x220011, 0x0}, + {0x100ae, 0x0}, + {0x1100ae, 0x0}, + {0x2100ae, 0x0}, + {0x100af, 0x0}, + {0x1100af, 0x0}, + {0x2100af, 0x0}, + {0x110ae, 0x0}, + {0x1110ae, 0x0}, + {0x2110ae, 0x0}, + {0x110af, 0x0}, + {0x1110af, 0x0}, + {0x2110af, 0x0}, + {0x120ae, 0x0}, + {0x1120ae, 0x0}, + {0x2120ae, 0x0}, + {0x120af, 0x0}, + {0x1120af, 0x0}, + {0x2120af, 0x0}, + {0x130ae, 0x0}, + {0x1130ae, 0x0}, + {0x2130ae, 0x0}, + {0x130af, 0x0}, + {0x1130af, 0x0}, + {0x2130af, 0x0}, + {0x20020, 0x0}, + {0x120020, 0x0}, + {0x220020, 0x0}, + {0x100a0, 0x0}, + {0x100a1, 0x0}, + {0x100a2, 0x0}, + {0x100a3, 0x0}, + {0x100a4, 0x0}, + {0x100a5, 0x0}, + {0x100a6, 0x0}, + {0x100a7, 0x0}, + {0x110a0, 0x0}, + {0x110a1, 0x0}, + {0x110a2, 0x0}, + {0x110a3, 0x0}, + {0x110a4, 0x0}, + {0x110a5, 0x0}, + {0x110a6, 0x0}, + {0x110a7, 0x0}, + {0x120a0, 0x0}, + {0x120a1, 0x0}, + {0x120a2, 0x0}, + {0x120a3, 0x0}, + {0x120a4, 0x0}, + {0x120a5, 0x0}, + {0x120a6, 0x0}, + {0x120a7, 0x0}, + {0x130a0, 0x0}, + {0x130a1, 0x0}, + {0x130a2, 0x0}, + {0x130a3, 0x0}, + {0x130a4, 0x0}, + {0x130a5, 0x0}, + {0x130a6, 0x0}, + {0x130a7, 0x0}, + {0x2007c, 0x0}, + {0x12007c, 0x0}, + {0x22007c, 0x0}, + {0x2007d, 0x0}, + {0x12007d, 0x0}, + {0x22007d, 0x0}, + {0x400fd, 0x0}, + {0x400c0, 0x0}, + {0x90201, 0x0}, + {0x190201, 0x0}, + {0x290201, 0x0}, + {0x90202, 0x0}, + {0x190202, 0x0}, + {0x290202, 0x0}, + {0x90203, 0x0}, + {0x190203, 0x0}, + {0x290203, 0x0}, + {0x90204, 0x0}, + {0x190204, 0x0}, + {0x290204, 0x0}, + {0x90205, 0x0}, + {0x190205, 0x0}, + {0x290205, 0x0}, + {0x90206, 0x0}, + {0x190206, 0x0}, + {0x290206, 0x0}, + {0x90207, 0x0}, + {0x190207, 0x0}, + {0x290207, 0x0}, + {0x90208, 0x0}, + {0x190208, 0x0}, + {0x290208, 0x0}, + {0x10062, 0x0}, + {0x10162, 0x0}, + {0x10262, 0x0}, + {0x10362, 0x0}, + {0x10462, 0x0}, + {0x10562, 0x0}, + {0x10662, 0x0}, + {0x10762, 0x0}, + {0x10862, 0x0}, + {0x11062, 0x0}, + {0x11162, 0x0}, + {0x11262, 0x0}, + {0x11362, 0x0}, + {0x11462, 0x0}, + {0x11562, 0x0}, + {0x11662, 0x0}, + {0x11762, 0x0}, + {0x11862, 0x0}, + {0x12062, 0x0}, + {0x12162, 0x0}, + {0x12262, 0x0}, + {0x12362, 0x0}, + {0x12462, 0x0}, + {0x12562, 0x0}, + {0x12662, 0x0}, + {0x12762, 0x0}, + {0x12862, 0x0}, + {0x13062, 0x0}, + {0x13162, 0x0}, + {0x13262, 0x0}, + {0x13362, 0x0}, + {0x13462, 0x0}, + {0x13562, 0x0}, + {0x13662, 0x0}, + {0x13762, 0x0}, + {0x13862, 0x0}, + {0x20077, 0x0}, + {0x10001, 0x0}, + {0x11001, 0x0}, + {0x12001, 0x0}, + {0x13001, 0x0}, + {0x10040, 0x0}, + {0x10140, 0x0}, + {0x10240, 0x0}, + {0x10340, 0x0}, + {0x10440, 0x0}, + {0x10540, 0x0}, + {0x10640, 0x0}, + {0x10740, 0x0}, + {0x10840, 0x0}, + {0x10030, 0x0}, + {0x10130, 0x0}, + {0x10230, 0x0}, + {0x10330, 0x0}, + {0x10430, 0x0}, + {0x10530, 0x0}, + {0x10630, 0x0}, + {0x10730, 0x0}, + {0x10830, 0x0}, + {0x11040, 0x0}, + {0x11140, 0x0}, + {0x11240, 0x0}, + {0x11340, 0x0}, + {0x11440, 0x0}, + {0x11540, 0x0}, + {0x11640, 0x0}, + {0x11740, 0x0}, + {0x11840, 0x0}, + {0x11030, 0x0}, + {0x11130, 0x0}, + {0x11230, 0x0}, + {0x11330, 0x0}, + {0x11430, 0x0}, + {0x11530, 0x0}, + {0x11630, 0x0}, + {0x11730, 0x0}, + {0x11830, 0x0}, + {0x12040, 0x0}, + {0x12140, 0x0}, + {0x12240, 0x0}, + {0x12340, 0x0}, + {0x12440, 0x0}, + {0x12540, 0x0}, + {0x12640, 0x0}, + {0x12740, 0x0}, + {0x12840, 0x0}, + {0x12030, 0x0}, + {0x12130, 0x0}, + {0x12230, 0x0}, + {0x12330, 0x0}, + {0x12430, 0x0}, + {0x12530, 0x0}, + {0x12630, 0x0}, + {0x12730, 0x0}, + {0x12830, 0x0}, + {0x13040, 0x0}, + {0x13140, 0x0}, + {0x13240, 0x0}, + {0x13340, 0x0}, + {0x13440, 0x0}, + {0x13540, 0x0}, + {0x13640, 0x0}, + {0x13740, 0x0}, + {0x13840, 0x0}, + {0x13030, 0x0}, + {0x13130, 0x0}, + {0x13230, 0x0}, + {0x13330, 0x0}, + {0x13430, 0x0}, + {0x13530, 0x0}, + {0x13630, 0x0}, + {0x13730, 0x0}, + {0x13830, 0x0}, }; - /* P0 message block paremeter for training firmware */ struct dram_cfg_param ddr_fsp0_cfg[] = { {0xd0000, 0x0}, @@ -1054,7 +1055,6 @@ struct dram_cfg_param ddr_fsp0_cfg[] = { {0x54008, 0x131f}, {0x54009, 0xc8}, {0x5400b, 0x2}, - {0x5400d, 0x100}, {0x54012, 0x110}, {0x54019, 0x2dd4}, {0x5401a, 0x31}, @@ -1094,7 +1094,6 @@ static struct dram_cfg_param ddr_fsp1_cfg[] = { {0x54008, 0x121f}, {0x54009, 0xc8}, {0x5400b, 0x2}, - {0x5400d, 0x100}, {0x54012, 0x110}, {0x54019, 0x84}, {0x5401a, 0x31}, @@ -1134,7 +1133,6 @@ static struct dram_cfg_param ddr_fsp2_cfg[] = { {0x54008, 0x121f}, {0x54009, 0xc8}, {0x5400b, 0x2}, - {0x5400d, 0x100}, {0x54012, 0x110}, {0x54019, 0x84}, {0x5401a, 0x31}, @@ -1200,7 +1198,7 @@ static struct dram_cfg_param ddr_fsp0_2d_cfg[] = { {0x5403b, 0x4d}, {0x5403c, 0x4d}, {0x5403d, 0x1600}, - { 0xd0000, 0x1 }, + {0xd0000, 0x1}, }; /* DRAM PHY init engine image */ @@ -1693,15 +1691,15 @@ static struct dram_cfg_param ddr_phy_pie[] = { {0x400d6, 0x20a}, {0x400d7, 0x20b}, {0x2003a, 0x2}, - {0x2000b, 0x5d}, + {0x2000b, 0x34b}, {0x2000c, 0xbb}, {0x2000d, 0x753}, {0x2000e, 0x2c}, - {0x12000b, 0xc}, + {0x12000b, 0x70}, {0x12000c, 0x19}, {0x12000d, 0xfa}, {0x12000e, 0x10}, - {0x22000b, 0x3}, + {0x22000b, 0x1c}, {0x22000c, 0x6}, {0x22000d, 0x3e}, {0x22000e, 0x10}, @@ -1842,5 +1840,5 @@ struct dram_timing_info dram_timing = { .ddrphy_trained_csr_num = ARRAY_SIZE(ddr_ddrphy_trained_csr), .ddrphy_pie = ddr_phy_pie, .ddrphy_pie_num = ARRAY_SIZE(ddr_phy_pie), - .fsp_table = { 3000, 400, 100, }, + .fsp_table = { 3000, 400, 100,}, }; diff --git a/board/siemens/capricorn/board.c b/board/siemens/capricorn/board.c index a0c62e0fc4c..924c88e8fab 100644 --- a/board/siemens/capricorn/board.c +++ b/board/siemens/capricorn/board.c @@ -147,7 +147,7 @@ static void enet_device_phy_reset(void) int setup_gpr_fec(void) { sc_ipc_t ipc_handle = -1; - sc_err_t err = 0; + int err = 0; unsigned int test; /* @@ -175,35 +175,35 @@ int setup_gpr_fec(void) */ err = sc_misc_set_control(ipc_handle, SC_R_ENET_1, SC_C_TXCLK, 1); - if (err != SC_ERR_NONE) + if (err) printf("Error in setting up SC_C %d\n\r", SC_C_TXCLK); sc_misc_get_control(ipc_handle, SC_R_ENET_1, SC_C_TXCLK, &test); debug("TEST SC_C %d-->%d\n\r", SC_C_TXCLK, test); err = sc_misc_set_control(ipc_handle, SC_R_ENET_1, SC_C_CLKDIV, 0); - if (err != SC_ERR_NONE) + if (err) printf("Error in setting up SC_C %d\n\r", SC_C_CLKDIV); sc_misc_get_control(ipc_handle, SC_R_ENET_1, SC_C_CLKDIV, &test); debug("TEST SC_C %d-->%d\n\r", SC_C_CLKDIV, test); err = sc_misc_set_control(ipc_handle, SC_R_ENET_1, SC_C_DISABLE_50, 0); - if (err != SC_ERR_NONE) + if (err) printf("Error in setting up SC_C %d\n\r", SC_C_DISABLE_50); sc_misc_get_control(ipc_handle, SC_R_ENET_1, SC_C_TXCLK, &test); debug("TEST SC_C %d-->%d\n\r", SC_C_DISABLE_50, test); err = sc_misc_set_control(ipc_handle, SC_R_ENET_1, SC_C_DISABLE_125, 1); - if (err != SC_ERR_NONE) + if (err) printf("Error in setting up SC_C %d\n\r", SC_C_DISABLE_125); sc_misc_get_control(ipc_handle, SC_R_ENET_1, SC_C_TXCLK, &test); debug("TEST SC_C %d-->%d\n\r", SC_C_DISABLE_125, test); err = sc_misc_set_control(ipc_handle, SC_R_ENET_1, SC_C_SEL_125, 1); - if (err != SC_ERR_NONE) + if (err) printf("Error in setting up SC_C %d\n\r", SC_C_SEL_125); sc_misc_get_control(ipc_handle, SC_R_ENET_1, SC_C_SEL_125, &test); diff --git a/board/sipeed/maix/Kconfig b/board/sipeed/maix/Kconfig index 2d212ec5a34..d34ea4be71f 100644 --- a/board/sipeed/maix/Kconfig +++ b/board/sipeed/maix/Kconfig @@ -34,7 +34,7 @@ config BOARD_SPECIFIC_OPTIONS imply SMP imply DM_SERIAL imply SIFIVE_SERIAL - imply SIFIVE_CLINT + imply RISCV_ACLINT imply POWER_DOMAIN imply SIMPLE_PM_BUS imply CLK_K210 diff --git a/board/starfive/visionfive2/Makefile b/board/starfive/visionfive2/Makefile index 66c854df390..c7ba4f7ed67 100644 --- a/board/starfive/visionfive2/Makefile +++ b/board/starfive/visionfive2/Makefile @@ -5,3 +5,4 @@ obj-y := starfive_visionfive2.o obj-$(CONFIG_SPL_BUILD) += spl.o +obj-$(CONFIG_ID_EEPROM) += visionfive2-i2c-eeprom.o diff --git a/board/starfive/visionfive2/spl.c b/board/starfive/visionfive2/spl.c index db0b4cb4335..7acd3995aad 100644 --- a/board/starfive/visionfive2/spl.c +++ b/board/starfive/visionfive2/spl.c @@ -5,16 +5,173 @@ */ #include <common.h> +#include <asm/arch/eeprom.h> #include <asm/arch/regs.h> #include <asm/arch/spl.h> #include <asm/io.h> +#include <dt-bindings/clock/starfive,jh7110-crg.h> +#include <fdt_support.h> +#include <linux/libfdt.h> #include <log.h> #include <spl.h> +DECLARE_GLOBAL_DATA_PTR; #define JH7110_CLK_CPU_ROOT_OFFSET 0x0U #define JH7110_CLK_CPU_ROOT_SHIFT 24 #define JH7110_CLK_CPU_ROOT_MASK GENMASK(29, 24) +struct starfive_vf2_pro { + const char *path; + const char *name; + const char *value; +}; + +static const struct starfive_vf2_pro starfive_vera[] = { + {"/soc/ethernet@16030000/mdio/ethernet-phy@0", "rx-internal-delay-ps", + "1900"}, + {"/soc/ethernet@16030000/mdio/ethernet-phy@0", "tx-internal-delay-ps", + "1350"} +}; + +static const struct starfive_vf2_pro starfive_verb[] = { + {"/soc/ethernet@16030000", "starfive,tx-use-rgmii-clk", NULL}, + {"/soc/ethernet@16040000", "starfive,tx-use-rgmii-clk", NULL}, + + {"/soc/ethernet@16030000/mdio/ethernet-phy@0", + "motorcomm,tx-clk-adj-enabled", NULL}, + {"/soc/ethernet@16030000/mdio/ethernet-phy@0", + "motorcomm,tx-clk-100-inverted", NULL}, + {"/soc/ethernet@16030000/mdio/ethernet-phy@0", + "motorcomm,tx-clk-1000-inverted", NULL}, + {"/soc/ethernet@16030000/mdio/ethernet-phy@0", + "rx-internal-delay-ps", "1900"}, + {"/soc/ethernet@16030000/mdio/ethernet-phy@0", + "tx-internal-delay-ps", "1500"}, + + {"/soc/ethernet@16040000/mdio/ethernet-phy@1", + "motorcomm,tx-clk-adj-enabled", NULL}, + { "/soc/ethernet@16040000/mdio/ethernet-phy@1", + "motorcomm,tx-clk-100-inverted", NULL}, + {"/soc/ethernet@16040000/mdio/ethernet-phy@1", + "rx-internal-delay-ps", "0"}, + {"/soc/ethernet@16040000/mdio/ethernet-phy@1", + "tx-internal-delay-ps", "0"}, +}; + +void spl_fdt_fixup_version_a(void *fdt) +{ + u32 phandle; + u8 i; + int offset; + int ret; + + fdt_setprop_string(fdt, fdt_path_offset(fdt, "/"), "model", + "StarFive VisionFive 2 v1.2A"); + + offset = fdt_path_offset(fdt, "/soc/clock-controller@13020000"); + phandle = fdt_get_phandle(fdt, offset); + offset = fdt_path_offset(fdt, "/soc/ethernet@16040000"); + + fdt_setprop_u32(fdt, offset, "assigned-clocks", phandle); + fdt_appendprop_u32(fdt, offset, "assigned-clocks", JH7110_SYSCLK_GMAC1_TX); + fdt_appendprop_u32(fdt, offset, "assigned-clocks", phandle); + fdt_appendprop_u32(fdt, offset, "assigned-clocks", JH7110_SYSCLK_GMAC1_RX); + + fdt_setprop_u32(fdt, offset, "assigned-clock-parents", phandle); + fdt_appendprop_u32(fdt, offset, "assigned-clock-parents", + JH7110_SYSCLK_GMAC1_RMII_RTX); + fdt_appendprop_u32(fdt, offset, "assigned-clock-parents", phandle); + fdt_appendprop_u32(fdt, offset, "assigned-clock-parents", + JH7110_SYSCLK_GMAC1_RMII_RTX); + + fdt_setprop_string(fdt, fdt_path_offset(fdt, "/soc/ethernet@16040000"), + "phy-mode", "rmii"); + + for (i = 0; i < ARRAY_SIZE(starfive_vera); i++) { + offset = fdt_path_offset(fdt, starfive_vera[i].path); + + if (starfive_vera[i].value) + ret = fdt_setprop_u32(fdt, offset, starfive_vera[i].name, + dectoul(starfive_vera[i].value, NULL)); + else + ret = fdt_setprop_empty(fdt, offset, starfive_vera[i].name); + + if (ret) { + pr_err("%s set prop %s fail.\n", __func__, starfive_vera[i].name); + break; + } + } +} + +void spl_fdt_fixup_version_b(void *fdt) +{ + u32 phandle; + u8 i; + int offset; + int ret; + + fdt_setprop_string(fdt, fdt_path_offset(fdt, "/"), "model", + "StarFive VisionFive 2 v1.3B"); + + /* gmac0 */ + offset = fdt_path_offset(fdt, "/soc/clock-controller@17000000"); + phandle = fdt_get_phandle(fdt, offset); + offset = fdt_path_offset(fdt, "/soc/ethernet@16030000"); + + fdt_setprop_u32(fdt, offset, "assigned-clocks", phandle); + fdt_appendprop_u32(fdt, offset, "assigned-clocks", JH7110_AONCLK_GMAC0_TX); + fdt_setprop_u32(fdt, offset, "assigned-clock-parents", phandle); + fdt_appendprop_u32(fdt, offset, "assigned-clock-parents", + JH7110_AONCLK_GMAC0_RMII_RTX); + + /* gmac1 */ + offset = fdt_path_offset(fdt, "/soc/clock-controller@13020000"); + phandle = fdt_get_phandle(fdt, offset); + offset = fdt_path_offset(fdt, "/soc/ethernet@16040000"); + + fdt_setprop_u32(fdt, offset, "assigned-clocks", phandle); + fdt_appendprop_u32(fdt, offset, "assigned-clocks", JH7110_SYSCLK_GMAC1_TX); + fdt_setprop_u32(fdt, offset, "assigned-clock-parents", phandle); + fdt_appendprop_u32(fdt, offset, "assigned-clock-parents", + JH7110_SYSCLK_GMAC1_RMII_RTX); + + for (i = 0; i < ARRAY_SIZE(starfive_verb); i++) { + offset = fdt_path_offset(fdt, starfive_verb[i].path); + + if (starfive_verb[i].value) + ret = fdt_setprop_u32(fdt, offset, starfive_verb[i].name, + dectoul(starfive_verb[i].value, NULL)); + else + ret = fdt_setprop_empty(fdt, offset, starfive_verb[i].name); + + if (ret) { + pr_err("%s set prop %s fail.\n", __func__, starfive_verb[i].name); + break; + } + } +} + +void spl_perform_fixups(struct spl_image_info *spl_image) +{ + u8 version; + + version = get_pcb_revision_from_eeprom(); + switch (version) { + case 'a': + case 'A': + spl_fdt_fixup_version_a(spl_image->fdt_addr); + break; + + case 'b': + case 'B': + default: + spl_fdt_fixup_version_b(spl_image->fdt_addr); + break; + }; + + /* Update the memory size which read form eeprom or DT */ + fdt_fixup_memory(spl_image->fdt_addr, 0x40000000, gd->ram_size); +} int spl_board_init_f(void) { int ret; diff --git a/board/starfive/visionfive2/starfive_visionfive2.c b/board/starfive/visionfive2/starfive_visionfive2.c index 613fe793c43..07dcca26b30 100644 --- a/board/starfive/visionfive2/starfive_visionfive2.c +++ b/board/starfive/visionfive2/starfive_visionfive2.c @@ -6,7 +6,9 @@ #include <common.h> #include <asm/io.h> +#include <asm/sections.h> #include <cpu_func.h> +#include <dm.h> #include <linux/bitops.h> #define JH7110_L2_PREFETCHER_BASE_ADDR 0x2030000 @@ -38,3 +40,14 @@ int board_init(void) return 0; } + +void *board_fdt_blob_setup(int *err) +{ + *err = 0; + if (IS_ENABLED(CONFIG_OF_SEPARATE) || IS_ENABLED(CONFIG_OF_BOARD)) { + if (gd->arch.firmware_fdt_addr) + return (ulong *)(uintptr_t)gd->arch.firmware_fdt_addr; + } + + return (ulong *)&_end; +} diff --git a/board/starfive/visionfive2/visionfive2-i2c-eeprom.c b/board/starfive/visionfive2/visionfive2-i2c-eeprom.c new file mode 100644 index 00000000000..befe7888c40 --- /dev/null +++ b/board/starfive/visionfive2/visionfive2-i2c-eeprom.c @@ -0,0 +1,561 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2023 StarFive Technology Co., Ltd. + * Author: Yanhong Wang<yanhong.wang@starfivetech.com> + */ + +#include <common.h> +#include <command.h> +#include <env.h> +#include <i2c.h> +#include <init.h> +#include <u-boot/crc.h> +#include <linux/delay.h> + +#define FORMAT_VERSION 0x2 +#define PCB_VERSION 0xB1 +#define BOM_VERSION 'A' +/* + * BYTES_PER_EEPROM_PAGE: the 24FC04H datasheet says that data can + * only be written in page mode, which means 16 bytes at a time: + * 16-Byte Page Write Buffer + */ +#define BYTES_PER_EEPROM_PAGE 16 + +/* + * EEPROM_WRITE_DELAY_MS: the 24FC04H datasheet says it takes up to + * 5ms to complete a given write: + * Write Cycle Time (byte or page) ro Page Write Time 5 ms, Maximum + */ +#define EEPROM_WRITE_DELAY_MS 5000 +/* + * StarFive OUI. Registration Date is 20xx-xx-xx + */ +#define STARFIVE_OUI_PREFIX "6C:CF:39:" +#define STARFIVE_DEFAULT_MAC0 "6C:CF:39:6C:DE:AD" +#define STARFIVE_DEFAULT_MAC1 "6C:CF:39:6C:DE:AE" + +/* Magic number at the first four bytes of EEPROM HATs */ +#define STARFIVE_EEPROM_HATS_SIG "SFVF" /* StarFive VisionFive */ + +#define STARFIVE_EEPROM_HATS_SIZE_MAX 256 /* Header + Atom1&4(v1) */ +#define STARFIVE_EEPROM_WP_OFFSET 0 /* Read only field */ +#define STARFIVE_EEPROM_ATOM1_PSTR "VF7110A1-2228-D008E000-00000001\0" +#define STARFIVE_EEPROM_ATOM1_PSTR_SIZE 32 +#define STARFIVE_EEPROM_ATOM1_SN_OFFSET 23 +#define STARFIVE_EEPROM_ATOM1_VSTR "StarFive Technology Co., Ltd.\0\0\0" +#define STARFIVE_EEPROM_ATOM1_VSTR_SIZE 32 + +#define MAGIC_NUMBER_BYTES 4 +#define MAC_ADDR_BYTES 6 +#define MAC_ADDR_STRLEN 17 + +/* + * Atom Types + * 0x0000 = invalid + * 0x0001 = vendor info + * 0x0002 = GPIO map + * 0x0003 = Linux device tree blob + * 0x0004 = manufacturer custom data + * 0x0005-0xfffe = reserved for future use + * 0xffff = invalid + */ + +#define HATS_ATOM_INVALID 0x0000 +#define HATS_ATOM_VENDOR 0x0001 +#define HATS_ATOM_GPIO 0x0002 +#define HATS_ATOM_DTB 0x0003 +#define HATS_ATOM_CUSTOM 0x0004 +#define HATS_ATOM_INVALID_END 0xffff + +struct eeprom_header { + char signature[MAGIC_NUMBER_BYTES]; /* ASCII table signature */ + u8 version; /* EEPROM data format version */ + /* (0x00 reserved, 0x01 = first version) */ + u8 reversed; /* 0x00, Reserved field */ + u16 numatoms; /* total atoms in EEPROM */ + u32 eeplen; /* total length in bytes of all eeprom data */ + /* (including this header) */ +}; + +struct eeprom_atom_header { + u16 type; + u16 count; + u32 dlen; +}; + +struct eeprom_atom1_data { + u8 uuid[16]; + u16 pid; + u16 pver; + u8 vslen; + u8 pslen; + uchar vstr[STARFIVE_EEPROM_ATOM1_VSTR_SIZE]; + uchar pstr[STARFIVE_EEPROM_ATOM1_PSTR_SIZE]; /* product SN */ +}; + +struct starfive_eeprom_atom1 { + struct eeprom_atom_header header; + struct eeprom_atom1_data data; + u16 crc; +}; + +struct eeprom_atom4_data { + u16 version; + u8 pcb_revision; /* PCB version */ + u8 bom_revision; /* BOM version */ + u8 mac0_addr[MAC_ADDR_BYTES]; /* Ethernet0 MAC */ + u8 mac1_addr[MAC_ADDR_BYTES]; /* Ethernet1 MAC */ + u8 reserved[2]; +}; + +struct starfive_eeprom_atom4 { + struct eeprom_atom_header header; + struct eeprom_atom4_data data; + u16 crc; +}; + +struct starfive_eeprom { + struct eeprom_header header; + struct starfive_eeprom_atom1 atom1; + struct starfive_eeprom_atom4 atom4; +}; + +static union { + struct starfive_eeprom eeprom; + uchar buf[STARFIVE_EEPROM_HATS_SIZE_MAX]; +} pbuf __section(".data"); + +/* Set to 1 if we've read EEPROM into memory */ +static int has_been_read __section(".data"); + +static inline int is_match_magic(void) +{ + return strncmp(pbuf.eeprom.header.signature, STARFIVE_EEPROM_HATS_SIG, + MAGIC_NUMBER_BYTES); +} + +/* Calculate the current CRC */ +static inline u32 calculate_crc16(struct eeprom_atom_header *head) +{ + uint len = sizeof(struct eeprom_atom_header) + head->dlen - sizeof(u16); + + return crc16(0, (void *)head, len); +} + +/* This function should be called after each update to the EEPROM structure */ +static inline void update_crc(void) +{ + pbuf.eeprom.atom1.crc = calculate_crc16(&pbuf.eeprom.atom1.header); + pbuf.eeprom.atom4.crc = calculate_crc16(&pbuf.eeprom.atom4.header); +} + +static void dump_raw_eeprom(void) +{ + unsigned int i; + u32 len; + + len = sizeof(struct starfive_eeprom); + for (i = 0; i < len; i++) { + if ((i % 16) == 0) + printf("%02X: ", i); + printf("%02X ", ((u8 *)pbuf.buf)[i]); + if (((i % 16) == 15) || (i == len - 1)) + printf("\n"); + } +} + +/** + * show_eeprom - display the contents of the EEPROM + */ +static void show_eeprom(void) +{ + if (has_been_read != 1) + return; + + printf("\n--------EEPROM INFO--------\n"); + printf("Vendor : %s\n", pbuf.eeprom.atom1.data.vstr); + printf("Product full SN: %s\n", pbuf.eeprom.atom1.data.pstr); + printf("data version: 0x%x\n", pbuf.eeprom.atom4.data.version); + if (pbuf.eeprom.atom4.data.version == 2) { + printf("PCB revision: 0x%x\n", pbuf.eeprom.atom4.data.pcb_revision); + printf("BOM revision: %c\n", pbuf.eeprom.atom4.data.bom_revision); + printf("Ethernet MAC0 address: %02x:%02x:%02x:%02x:%02x:%02x\n", + pbuf.eeprom.atom4.data.mac0_addr[0], pbuf.eeprom.atom4.data.mac0_addr[1], + pbuf.eeprom.atom4.data.mac0_addr[2], pbuf.eeprom.atom4.data.mac0_addr[3], + pbuf.eeprom.atom4.data.mac0_addr[4], pbuf.eeprom.atom4.data.mac0_addr[5]); + printf("Ethernet MAC1 address: %02x:%02x:%02x:%02x:%02x:%02x\n", + pbuf.eeprom.atom4.data.mac1_addr[0], pbuf.eeprom.atom4.data.mac1_addr[1], + pbuf.eeprom.atom4.data.mac1_addr[2], pbuf.eeprom.atom4.data.mac1_addr[3], + pbuf.eeprom.atom4.data.mac1_addr[4], pbuf.eeprom.atom4.data.mac1_addr[5]); + } else { + printf("Custom data v%d is not Supported\n", pbuf.eeprom.atom4.data.version); + } + printf("--------EEPROM INFO--------\n\n"); +} + +/** + * set_mac_address() - stores a MAC address into the local EEPROM copy + * + * This function takes a pointer to MAC address string + * (i.e."XX:XX:XX:XX:XX:XX", where "XX" is a two-digit hex number), + * stores it in the MAC address field of the EEPROM local copy, and + * updates the local copy of the CRC. + */ +static void set_mac_address(char *string, int index) +{ + u8 i; + u8 *mac; + + if (strncasecmp(STARFIVE_OUI_PREFIX, string, + strlen(STARFIVE_OUI_PREFIX))) { + printf("The MAC address doesn't match StarFive OUI %s\n", + STARFIVE_OUI_PREFIX); + return; + } + mac = (index == 0) ? pbuf.eeprom.atom4.data.mac0_addr : + pbuf.eeprom.atom4.data.mac1_addr; + + for (i = 0; *string && (i < MAC_ADDR_BYTES); i++) { + mac[i] = hextoul(string, &string); + + if (*string == ':') + string++; + } + + update_crc(); +} + +/** + * init_local_copy() - initialize the in-memory EEPROM copy + * + * Initialize the in-memory EEPROM copy with the magic number. Must + * be done when preparing to initialize a blank EEPROM, or overwrite + * one with a corrupted magic number. + */ +static void init_local_copy(void) +{ + memset((void *)pbuf.buf, 0, sizeof(struct starfive_eeprom)); + memcpy(pbuf.eeprom.header.signature, STARFIVE_EEPROM_HATS_SIG, + strlen(STARFIVE_EEPROM_HATS_SIG)); + pbuf.eeprom.header.version = FORMAT_VERSION; + pbuf.eeprom.header.numatoms = 2; + pbuf.eeprom.header.eeplen = sizeof(struct starfive_eeprom); + + pbuf.eeprom.atom1.header.type = HATS_ATOM_VENDOR; + pbuf.eeprom.atom1.header.count = 1; + pbuf.eeprom.atom1.header.dlen = sizeof(struct eeprom_atom1_data) + sizeof(u16); + pbuf.eeprom.atom1.data.vslen = STARFIVE_EEPROM_ATOM1_VSTR_SIZE; + pbuf.eeprom.atom1.data.pslen = STARFIVE_EEPROM_ATOM1_PSTR_SIZE; + memcpy(pbuf.eeprom.atom1.data.vstr, STARFIVE_EEPROM_ATOM1_VSTR, + strlen(STARFIVE_EEPROM_ATOM1_VSTR)); + memcpy(pbuf.eeprom.atom1.data.pstr, STARFIVE_EEPROM_ATOM1_PSTR, + strlen(STARFIVE_EEPROM_ATOM1_PSTR)); + + pbuf.eeprom.atom4.header.type = HATS_ATOM_CUSTOM; + pbuf.eeprom.atom4.header.count = 2; + pbuf.eeprom.atom4.header.dlen = sizeof(struct eeprom_atom4_data) + sizeof(u16); + pbuf.eeprom.atom4.data.version = FORMAT_VERSION; + pbuf.eeprom.atom4.data.pcb_revision = PCB_VERSION; + pbuf.eeprom.atom4.data.bom_revision = BOM_VERSION; + set_mac_address(STARFIVE_DEFAULT_MAC0, 0); + set_mac_address(STARFIVE_DEFAULT_MAC1, 1); +} + +/** + * prog_eeprom() - write the EEPROM from memory + */ +static int prog_eeprom(unsigned int size) +{ + unsigned int i; + void *p; + uchar tmp_buff[STARFIVE_EEPROM_HATS_SIZE_MAX]; + struct udevice *dev; + int ret; + + if (is_match_magic()) { + printf("MAGIC ERROR, Please check the data@%p.\n", pbuf.buf); + return -1; + } + + ret = i2c_get_chip_for_busnum(CONFIG_SYS_EEPROM_BUS_NUM, + CONFIG_SYS_I2C_EEPROM_ADDR, + CONFIG_SYS_I2C_EEPROM_ADDR_LEN, + &dev); + if (ret) { + printf("Get i2c bus:%d addr:%d fail.\n", CONFIG_SYS_EEPROM_BUS_NUM, + CONFIG_SYS_I2C_EEPROM_ADDR); + return ret; + } + + for (i = 0, p = (u8 *)pbuf.buf; i < size; ) { + if (!ret) + ret = dm_i2c_write(dev, i, p, min((int)(size - i), + BYTES_PER_EEPROM_PAGE)); + if (ret) + break; + + udelay(EEPROM_WRITE_DELAY_MS); + i += BYTES_PER_EEPROM_PAGE; + p += BYTES_PER_EEPROM_PAGE; + } + + if (!ret) { + /* Verify the write by reading back the EEPROM and comparing */ + ret = dm_i2c_read(dev, + STARFIVE_EEPROM_WP_OFFSET, + tmp_buff, + STARFIVE_EEPROM_HATS_SIZE_MAX); + if (!ret && memcmp((void *)pbuf.buf, (void *)tmp_buff, + STARFIVE_EEPROM_HATS_SIZE_MAX)) + ret = -1; + } + + if (ret) { + has_been_read = -1; + printf("Programming failed.\n"); + return -1; + } + + printf("Programming passed.\n"); + return 0; +} + +/** + * read_eeprom() - read the EEPROM into memory, if it hasn't been read already + */ +static int read_eeprom(void) +{ + int ret; + struct udevice *dev; + + if (has_been_read == 1) + return 0; + + ret = i2c_get_chip_for_busnum(CONFIG_SYS_EEPROM_BUS_NUM, + CONFIG_SYS_I2C_EEPROM_ADDR, 1, &dev); + if (!ret) + ret = dm_i2c_read(dev, 0, (u8 *)pbuf.buf, + STARFIVE_EEPROM_HATS_SIZE_MAX); + + has_been_read = (ret == 0) ? 1 : 0; + + return ret; +} + +/** + * set_pcb_revision() - stores a StarFive PCB revision into the local EEPROM copy + * + * Takes a pointer to a string representing the numeric PCB revision in + * decimal ("0" - "255"), stores it in the pcb_revision field of the + * EEPROM local copy, and updates the CRC of the local copy. + */ +static void set_pcb_revision(char *string) +{ + u32 p; + + p = simple_strtoul(string, &string, 16); + if (p > U8_MAX) { + printf("%s must not be greater than %d\n", "PCB revision", + U8_MAX); + return; + } + + pbuf.eeprom.atom4.data.pcb_revision = p; + + update_crc(); +} + +/** + * set_bom_revision() - stores a StarFive BOM revision into the local EEPROM copy + * + * Takes a pointer to a uppercase ASCII character representing the BOM + * revision ("A" - "Z"), stores it in the bom_revision field of the + * EEPROM local copy, and updates the CRC of the local copy. + */ +static void set_bom_revision(char *string) +{ + if (string[0] < 'A' || string[0] > 'Z') { + printf("BOM revision must be an uppercase letter between A and Z\n"); + return; + } + + pbuf.eeprom.atom4.data.bom_revision = string[0]; + + update_crc(); +} + +/** + * set_product_id() - stores a StarFive product ID into the local EEPROM copy + * + * Takes a pointer to a string representing the numeric product ID in + * string ("VF7100A1-2150-D008E000-00000001\0"), stores it in the product string + * field of the EEPROM local copy, and updates the CRC of the local copy. + */ +static void set_product_id(char *string) +{ + u32 len; + + len = (strlen(string) > STARFIVE_EEPROM_ATOM1_PSTR_SIZE) ? + STARFIVE_EEPROM_ATOM1_PSTR_SIZE : strlen(string); + + memcpy((void *)pbuf.eeprom.atom1.data.pstr, (void *)string, len); + + update_crc(); +} + +static int print_usage(void) +{ + printf("display and program the system ID and MAC addresses in EEPROM\n" + "[read_eeprom|initialize|write_eeprom|mac_address|pcb_revision|bom_revision|product_id]\n" + "mac read_eeprom\n" + " - read EEPROM content into memory data structure\n" + "mac write_eeprom\n" + " - save memory data structure to the EEPROM\n" + "mac initialize\n" + " - initialize the in-memory EEPROM copy with default data\n" + "mac mac0_address <xx:xx:xx:xx:xx:xx>\n" + " - stores a MAC0 address into the local EEPROM copy\n" + "mac mac1_address <xx:xx:xx:xx:xx:xx>\n" + " - stores a MAC1 address into the local EEPROM copy\n" + "mac pcb_revision <?>\n" + " - stores a StarFive PCB revision into the local EEPROM copy\n" + "mac bom_revision <A>\n" + " - stores a StarFive BOM revision into the local EEPROM copy\n" + "mac product_id <VF7110A1-2228-D008E000-xxxxxxxx>\n" + " - stores a StarFive product ID into the local EEPROM copy\n"); + return 0; +} + +int do_mac(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) +{ + char *cmd; + + if (argc == 1) { + show_eeprom(); + return 0; + } + + if (argc > 3) + return print_usage(); + + cmd = argv[1]; + + /* Commands with no argument */ + if (!strcmp(cmd, "read_eeprom")) { + has_been_read = 0; + return read_eeprom(); + } else if (!strcmp(cmd, "initialize")) { + init_local_copy(); + return 0; + } else if (!strcmp(cmd, "write_eeprom")) { + return prog_eeprom(STARFIVE_EEPROM_HATS_SIZE_MAX); + } + + if (argc != 3) + return print_usage(); + + if (is_match_magic()) { + printf("Please read the EEPROM ('read_eeprom') and/or initialize the EEPROM ('initialize') first.\n"); + return 0; + } + + if (!strcmp(cmd, "mac0_address")) { + set_mac_address(argv[2], 0); + return 0; + } else if (!strcmp(cmd, "mac1_address")) { + set_mac_address(argv[2], 1); + return 0; + } else if (!strcmp(cmd, "pcb_revision")) { + set_pcb_revision(argv[2]); + return 0; + } else if (!strcmp(cmd, "bom_revision")) { + set_bom_revision(argv[2]); + return 0; + } else if (!strcmp(cmd, "product_id")) { + set_product_id(argv[2]); + return 0; + } + + return print_usage(); +} + +/** + * mac_read_from_eeprom() - read the MAC address & the serial number in EEPROM + * + * This function reads the MAC address and the serial number from EEPROM and + * sets the appropriate environment variables for each one read. + * + * The environment variables are only set if they haven't been set already. + * This ensures that any user-saved variables are never overwritten. + * + * If CONFIG_ID_EEPROM is enabled, this function will be called in + * "static init_fnc_t init_sequence_r[]" of u-boot/common/board_r.c. + */ +int mac_read_from_eeprom(void) +{ + /** + * try to fill the buff from EEPROM, + * always return SUCCESS, even some error happens. + */ + if (read_eeprom()) { + dump_raw_eeprom(); + return 0; + } + + // 1, setup ethaddr env + eth_env_set_enetaddr("eth0addr", pbuf.eeprom.atom4.data.mac0_addr); + eth_env_set_enetaddr("eth1addr", pbuf.eeprom.atom4.data.mac1_addr); + + /** + * 2, setup serial# env, reference to hifive-platform-i2c-eeprom.c, + * serial# can be a ASCII string, but not just a hex number, so we + * setup serial# in the 32Byte format: + * "VF7100A1-2201-D008E000-00000001;" + * "<product>-<date>-<DDR&eMMC>-<serial_number>" + * <date>: 4Byte, should be the output of `date +%y%W` + * <DDR&eMMC>: 8Byte, "D008" means 8GB, "D01T" means 1TB; + * "E000" means no eMMCļ¼"E032" means 32GB, "E01T" means 1TB. + * <serial_number>: 8Byte, the Unique Identifier of board in hex. + */ + if (!env_get("serial#")) + env_set("serial#", pbuf.eeprom.atom1.data.pstr); + + printf("StarFive EEPROM format v%u\n", pbuf.eeprom.header.version); + show_eeprom(); + return 0; +} + +/** + * get_pcb_revision_from_eeprom - get the PCB revision + * + * 1.2A return 'A'/'a', 1.3B return 'B'/'b',other values are illegal + */ +u8 get_pcb_revision_from_eeprom(void) +{ + u8 pv = 0xFF; + + if (read_eeprom()) + return pv; + + return pbuf.eeprom.atom1.data.pstr[6]; +} + +/** + * get_ddr_size_from_eeprom - get the DDR size + * pstr: VF7110A1-2228-D008E000-00000001 + * VF7110A1/VF7110B1 : VisionFive JH7110A /VisionFive JH7110B + * D008:ć8GB LPDDR4 + * E000: No emmc device, ECxx: include emmc device, xx: Capacity size[GB] + * return: the field of 'D008E000' + */ + +u32 get_ddr_size_from_eeprom(void) +{ + u32 pv = 0xFFFFFFFF; + + if (read_eeprom()) + return pv; + + return hextoul(&pbuf.eeprom.atom1.data.pstr[14], NULL); +} diff --git a/board/technexion/pico-imx8mq/pico-imx8mq.c b/board/technexion/pico-imx8mq/pico-imx8mq.c index 951e3e1985b..2be3206f78a 100644 --- a/board/technexion/pico-imx8mq/pico-imx8mq.c +++ b/board/technexion/pico-imx8mq/pico-imx8mq.c @@ -54,7 +54,7 @@ int board_early_init_f(void) int board_phys_sdram_size(phys_size_t *size) { - int ddr_size = readl(M4_BOOTROM_BASE_ADDR); + int ddr_size = readl(MCU_BOOTROM_BASE_ADDR); if (ddr_size == 0x4) { *size = 0x100000000; diff --git a/board/technexion/pico-imx8mq/spl.c b/board/technexion/pico-imx8mq/spl.c index 8b853a914e8..2afb4d37608 100644 --- a/board/technexion/pico-imx8mq/spl.c +++ b/board/technexion/pico-imx8mq/spl.c @@ -89,7 +89,7 @@ static void spl_dram_init(void) printf("%s: LPDDR4 %d GiB\n", __func__, size); ddr_init(dram_timing); - writel(size, M4_BOOTROM_BASE_ADDR); + writel(size, MCU_BOOTROM_BASE_ADDR); } #define USDHC2_CD_GPIO IMX_GPIO_NR(2, 12) diff --git a/board/thead/th1520_lpi4a/Kconfig b/board/thead/th1520_lpi4a/Kconfig new file mode 100644 index 00000000000..622246127c1 --- /dev/null +++ b/board/thead/th1520_lpi4a/Kconfig @@ -0,0 +1,42 @@ +if TARGET_TH1520_LPI4A + +config ARCH_THEAD + bool + default y + +config SYS_BOARD + default "th1520_lpi4a" + +config SYS_VENDOR + default "thead" + +config SYS_CPU + default "generic" + +config SYS_CONFIG_NAME + default "th1520_lpi4a" + +config TEXT_BASE + default 0x01b00000 if SPL + default 0x01c00000 if !RISCV_SMODE + default 0x01c00000 if RISCV_SMODE + +config SPL_TEXT_BASE + default 0x08000000 + +config SPL_OPENSBI_LOAD_ADDR + default 0x80000000 + +config BOARD_SPECIFIC_OPTIONS + def_bool y + select ARCH_EARLY_INIT_R + imply CPU + imply CPU_RISCV + imply RISCV_TIMER if RISCV_SMODE + imply CMD_CPU + imply SMP + imply SUPPORT_OF_CONTROL + imply OF_CONTROL + imply OF_REAL + +endif diff --git a/board/thead/th1520_lpi4a/MAINTAINERS b/board/thead/th1520_lpi4a/MAINTAINERS new file mode 100644 index 00000000000..36c7ab7cc30 --- /dev/null +++ b/board/thead/th1520_lpi4a/MAINTAINERS @@ -0,0 +1,7 @@ +Lichee PI 4A +M: Wei Fu <wefu@redhat.com> +M: Yixun Lan <dlan@gentoo.org> +S: Maintained +F: board/thead/th1520_lpi4a/ +F: configs/th1520_lpi4a_defconfig +F: doc/board/thead/lpi4a.rst diff --git a/board/thead/th1520_lpi4a/Makefile b/board/thead/th1520_lpi4a/Makefile new file mode 100644 index 00000000000..9671b3bbb0b --- /dev/null +++ b/board/thead/th1520_lpi4a/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (c) 2023, Yixun Lan <dlan@gentoo.org> + +obj-y += board.o diff --git a/board/thead/th1520_lpi4a/board.c b/board/thead/th1520_lpi4a/board.c new file mode 100644 index 00000000000..16c3e456b3e --- /dev/null +++ b/board/thead/th1520_lpi4a/board.c @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2023, Yixun Lan <dlan@gentoo.org> + * + */ + +#include <common.h> +#include <cpu_func.h> + +int board_init(void) +{ + enable_caches(); + + return 0; +} diff --git a/board/thecus/n2350/n2350.c b/board/thecus/n2350/n2350.c index fd8f95f9446..05b125fd7f8 100644 --- a/board/thecus/n2350/n2350.c +++ b/board/thecus/n2350/n2350.c @@ -25,7 +25,7 @@ DECLARE_GLOBAL_DATA_PTR; #define N2350_GPP_OUT_ENA_LOW (~(BIT(20) | BIT(21) | BIT(24))) #define N2350_GPP_OUT_ENA_MID (~(BIT(12) | BIT(13) | BIT(16) | BIT(19) | BIT(22))) #define N2350_GPP_OUT_VAL_LOW (BIT(21) | BIT(24)) -#define N2350_GPP_OUT_VAL_MID (BIT(0) | BIT(12) | BIT(13)) +#define N2350_GPP_OUT_VAL_MID (BIT(0) | BIT(12) | BIT(13) | BIT(16)) #define N2350_GPP_POL_LOW 0x0 #define N2350_GPP_POL_MID 0x0 diff --git a/board/toradex/apalis-imx8/apalis-imx8.c b/board/toradex/apalis-imx8/apalis-imx8.c index aa76c486eec..e2bbaba8b8c 100644 --- a/board/toradex/apalis-imx8/apalis-imx8.c +++ b/board/toradex/apalis-imx8/apalis-imx8.c @@ -85,18 +85,18 @@ static void setup_iomux_uart(void) static uint32_t do_get_tdx_user_fuse(int a, int b) { - sc_err_t sciErr; + int sciErr; u32 val_a = 0; u32 val_b = 0; sciErr = sc_misc_otp_fuse_read(-1, a, &val_a); - if (sciErr != SC_ERR_NONE) { + if (sciErr) { printf("Error reading out user fuse %d\n", a); return 0; } sciErr = sc_misc_otp_fuse_read(-1, b, &val_b); - if (sciErr != SC_ERR_NONE) { + if (sciErr) { printf("Error reading out user fuse %d\n", b); return 0; } @@ -131,9 +131,9 @@ void board_mem_get_layout(u64 *phys_sdram_1_start, { u32 is_quadplus = 0, val = 0; struct tdx_user_fuses tdxramfuses; - sc_err_t scierr = sc_misc_otp_fuse_read(-1, 6, &val); + int scierr = sc_misc_otp_fuse_read(-1, 6, &val); - if (scierr == SC_ERR_NONE) { + if (scierr) { /* QP has one A72 core disabled */ is_quadplus = ((val >> 4) & 0x3) != 0x0; } diff --git a/board/toradex/colibri-imx8x/colibri-imx8x.c b/board/toradex/colibri-imx8x/colibri-imx8x.c index 52fc7a391bb..6c0b09787c8 100644 --- a/board/toradex/colibri-imx8x/colibri-imx8x.c +++ b/board/toradex/colibri-imx8x/colibri-imx8x.c @@ -12,6 +12,7 @@ #include <asm/arch/imx8-pins.h> #include <asm/arch/iomux.h> #include <firmware/imx/sci/sci.h> +#include <asm/arch/snvs_security_sc.h> #include <asm/arch/sys_proto.h> #include <asm/gpio.h> #include <asm/io.h> @@ -43,9 +44,9 @@ static void setup_iomux_uart(void) static int is_imx8dx(void) { u32 val = 0; - sc_err_t sc_err = sc_misc_otp_fuse_read(-1, 6, &val); + int sc_err = sc_misc_otp_fuse_read(-1, 6, &val); - if (sc_err == SC_ERR_NONE) { + if (sc_err) { /* DX has two A35 cores disabled */ return (val & 0xf) != 0x0; } @@ -70,7 +71,7 @@ void board_mem_get_layout(u64 *phys_sdram_1_start, int board_early_init_f(void) { sc_pm_clock_rate_t rate; - sc_err_t err = 0; + int err; /* * This works around that having only UART3 up the baudrate is 1.2M @@ -78,13 +79,13 @@ int board_early_init_f(void) */ rate = 80000000; err = sc_pm_set_clock_rate(-1, SC_R_UART_0, SC_PM_CLK_PER, &rate); - if (err != SC_ERR_NONE) + if (err) return 0; /* Set UART3 clock root to 80 MHz and enable it */ rate = SC_80MHZ; err = sc_pm_setup_uart(SC_R_UART_3, rate); - if (err != SC_ERR_NONE) + if (err) return 0; setup_iomux_uart(); @@ -139,6 +140,13 @@ int board_init(void) { board_gpio_init(); + if (IS_ENABLED(CONFIG_IMX_SNVS_SEC_SC_AUTO)) { + int ret = snvs_security_sc_init(); + + if (ret) + return ret; + } + return 0; } @@ -170,6 +178,8 @@ int board_late_init(void) env_set("board_rev", "v1.0"); #endif + build_info(); + select_dt_from_module_version(); return 0; diff --git a/board/toradex/colibri_imx6/colibri_imx6.c b/board/toradex/colibri_imx6/colibri_imx6.c index 65e0e9a156a..677caa4a4eb 100644 --- a/board/toradex/colibri_imx6/colibri_imx6.c +++ b/board/toradex/colibri_imx6/colibri_imx6.c @@ -767,8 +767,7 @@ MX6_MMDC_P1_MPRDDQBY3DL, 0x33333333, /* * MDMISC mirroring interleaved (row/bank/col) */ -/* TODO: check what the RALAT field does */ -MX6_MMDC_P0_MDMISC, 0x00081740, +MX6_MMDC_P0_MDMISC, 0x000b17c0, /* * MDSCR con_req @@ -900,8 +899,7 @@ MX6_MMDC_P1_MPRDDQBY3DL, 0x33333333, /* * MDMISC mirroring interleaved (row/bank/col) */ -/* TODO: check what the RALAT field does */ -MX6_MMDC_P0_MDMISC, 0x00081740, +MX6_MMDC_P0_MDMISC, 0x000b17c0, /* * MDSCR con_req diff --git a/board/toradex/common/tdx-cfg-block.c b/board/toradex/common/tdx-cfg-block.c index 11f4d5e14a8..e513f4a2919 100644 --- a/board/toradex/common/tdx-cfg-block.c +++ b/board/toradex/common/tdx-cfg-block.c @@ -139,6 +139,7 @@ const struct toradex_som toradex_modules[] = { [66] = { "Verdin iMX8M Plus Quad 8GB WB", TARGET_IS_ENABLED(VERDIN_IMX8MP) }, [67] = { "Apalis iMX8QM 8GB WB IT", TARGET_IS_ENABLED(APALIS_IMX8) }, [68] = { "Verdin iMX8M Mini Quad 2GB WB IT", TARGET_IS_ENABLED(VERDIN_IMX8MM) }, + [70] = { "Verdin iMX8M Plus Quad 8GB WB IT", TARGET_IS_ENABLED(VERDIN_IMX8MP) }, }; const char * const toradex_carrier_boards[] = { diff --git a/board/toradex/common/tdx-cfg-block.h b/board/toradex/common/tdx-cfg-block.h index 32e4c6f6879..45fa04ca38a 100644 --- a/board/toradex/common/tdx-cfg-block.h +++ b/board/toradex/common/tdx-cfg-block.h @@ -94,6 +94,8 @@ enum { VERDIN_IMX8MPQ_8GB_WIFI_BT, APALIS_IMX8QM_8GB_WIFI_BT_IT, VERDIN_IMX8MMQ_WIFI_BT_IT_NO_CAN, + /* 69 */ + VERDIN_IMX8MPQ_8GB_WIFI_BT_IT = 70, /* 70 */ }; enum { diff --git a/board/toradex/verdin-imx8mm/MAINTAINERS b/board/toradex/verdin-imx8mm/MAINTAINERS index 974b3a10329..b0f4329253a 100644 --- a/board/toradex/verdin-imx8mm/MAINTAINERS +++ b/board/toradex/verdin-imx8mm/MAINTAINERS @@ -3,7 +3,6 @@ M: Marcel Ziswiler <marcel.ziswiler@toradex.com> W: https://www.toradex.com/computer-on-modules/verdin-arm-family/nxp-imx-8m-mini S: Maintained F: arch/arm/dts/imx8mm-verdin.dtsi -F: arch/arm/dts/imx8mm-verdin-dahlia.dtsi F: arch/arm/dts/imx8mm-verdin-dev.dtsi F: arch/arm/dts/imx8mm-verdin-wifi.dtsi F: arch/arm/dts/imx8mm-verdin-wifi-dev.dts diff --git a/board/toradex/verdin-imx8mp/MAINTAINERS b/board/toradex/verdin-imx8mp/MAINTAINERS index cff3c503838..ea04a83926a 100644 --- a/board/toradex/verdin-imx8mp/MAINTAINERS +++ b/board/toradex/verdin-imx8mp/MAINTAINERS @@ -1,6 +1,5 @@ Verdin iMX8M Plus F: arch/arm/dts/imx8mp-verdin.dtsi -F: arch/arm/dts/imx8mp-verdin-dahlia.dtsi F: arch/arm/dts/imx8mp-verdin-dev.dtsi F: arch/arm/dts/imx8mp-verdin-wifi.dtsi F: arch/arm/dts/imx8mp-verdin-wifi-dev.dts diff --git a/board/toradex/verdin-imx8mp/verdin-imx8mp.c b/board/toradex/verdin-imx8mp/verdin-imx8mp.c index 5490d3ed44a..e16a771e3ec 100644 --- a/board/toradex/verdin-imx8mp/verdin-imx8mp.c +++ b/board/toradex/verdin-imx8mp/verdin-imx8mp.c @@ -81,7 +81,8 @@ static void select_dt_from_module_version(void) */ is_wifi = (tdx_hw_tag.prodid == VERDIN_IMX8MPQ_WIFI_BT_IT) || (tdx_hw_tag.prodid == VERDIN_IMX8MPQ_2GB_WIFI_BT_IT) || - (tdx_hw_tag.prodid == VERDIN_IMX8MPQ_8GB_WIFI_BT); + (tdx_hw_tag.prodid == VERDIN_IMX8MPQ_8GB_WIFI_BT) || + (tdx_hw_tag.prodid == VERDIN_IMX8MPQ_8GB_WIFI_BT_IT); } if (is_wifi) diff --git a/board/variscite/imx8mn_var_som/imx8mn_var_som.c b/board/variscite/imx8mn_var_som/imx8mn_var_som.c index d40f4d01761..61b9455a8f4 100644 --- a/board/variscite/imx8mn_var_som/imx8mn_var_som.c +++ b/board/variscite/imx8mn_var_som/imx8mn_var_som.c @@ -1,11 +1,50 @@ // SPDX-License-Identifier: GPL-2.0+ /* * Copyright 2021 Collabora Ltd. + * Copyright 2018-2020 Variscite Ltd. + * Copyright 2023 DimOnOff Inc. */ #include <common.h> +#include <dm.h> #include <env.h> +#include <fdtdec.h> +#include <fdt_support.h> +#include <i2c_eeprom.h> +#include <malloc.h> #include <asm/io.h> +#include <asm/global_data.h> +#include <dt-bindings/gpio/gpio.h> +#include <linux/libfdt.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* Optional SOM features flags. */ +#define VAR_EEPROM_F_WIFI BIT(0) +#define VAR_EEPROM_F_ETH BIT(1) /* Ethernet PHY on SOM. */ +#define VAR_EEPROM_F_AUDIO BIT(2) +#define VAR_EEPROM_F_MX8M_LVDS BIT(3) /* i.MX8MM, i.MX8MN, i.MX8MQ only */ +#define VAR_EEPROM_F_MX8Q_SOC_ID BIT(3) /* 0 = i.MX8QM, 1 = i.MX8QP */ +#define VAR_EEPROM_F_NAND BIT(4) + +#define VAR_IMX8_EEPROM_MAGIC 0x384D /* "8M" */ + +/* Number of DRAM adjustment tables. */ +#define DRAM_TABLES_NUM 7 + +struct var_imx8_eeprom_info { + u16 magic; + u8 partnumber[3]; /* Part number */ + u8 assembly[10]; /* Assembly number */ + u8 date[9]; /* Build date */ + u8 mac[6]; /* MAC address */ + u8 somrev; + u8 eeprom_version; + u8 features; /* SOM features */ + u8 dramsize; /* DRAM size */ + u8 off[DRAM_TABLES_NUM + 1]; /* DRAM table offsets */ + u8 partnumber2[5]; /* Part number 2 */ +} __packed; static void setup_fec(void) { @@ -28,3 +67,178 @@ int board_mmc_get_env_dev(int devno) { return devno; } + +#if !defined(CONFIG_SPL_BUILD) + +#if defined(CONFIG_DISPLAY_BOARDINFO) + +static void display_som_infos(struct var_imx8_eeprom_info *info) +{ + char partnumber[sizeof(info->partnumber) + + sizeof(info->partnumber2) + 1]; + char assembly[sizeof(info->assembly) + 1]; + char date[sizeof(info->date) + 1]; + + /* Read first part of P/N. */ + memcpy(partnumber, info->partnumber, sizeof(info->partnumber)); + + /* Read second part of P/N. */ + if (info->eeprom_version >= 3) + memcpy(partnumber + sizeof(info->partnumber), info->partnumber2, + sizeof(info->partnumber2)); + + memcpy(assembly, info->assembly, sizeof(info->assembly)); + memcpy(date, info->date, sizeof(info->date)); + + /* Make sure strings are null terminated. */ + partnumber[sizeof(partnumber) - 1] = '\0'; + assembly[sizeof(assembly) - 1] = '\0'; + date[sizeof(date) - 1] = '\0'; + + printf("SOM board: P/N: %s, Assy: %s, Date: %s\n" + " Wifi: %s, EthPhy: %s, Rev: %d\n", + partnumber, assembly, date, + info->features & VAR_EEPROM_F_WIFI ? "yes" : "no", + info->features & VAR_EEPROM_F_ETH ? "yes" : "no", + info->somrev); +} + +static int var_read_som_eeprom(struct var_imx8_eeprom_info *info) +{ + const char *path = "eeprom-som"; + struct udevice *dev; + int ret, off; + + off = fdt_path_offset(gd->fdt_blob, path); + if (off < 0) { + pr_err("%s: fdt_path_offset() failed: %d\n", __func__, off); + return off; + } + + ret = uclass_get_device_by_of_offset(UCLASS_I2C_EEPROM, off, &dev); + if (ret) { + pr_err("%s: uclass_get_device_by_of_offset() failed: %d\n", + __func__, ret); + return ret; + } + + ret = i2c_eeprom_read(dev, 0, (uint8_t *)info, + sizeof(struct var_imx8_eeprom_info)); + if (ret) { + pr_err("%s: i2c_eeprom_read() failed: %d\n", __func__, ret); + return ret; + } + + if (htons(info->magic) != VAR_IMX8_EEPROM_MAGIC) { + /* Do not fail if the content is invalid */ + pr_err("Board: Invalid board info magic: 0x%08x, expected 0x%08x\n", + htons(info->magic), VAR_IMX8_EEPROM_MAGIC); + } + + return 0; +} + +int checkboard(void) +{ + int rc; + struct var_imx8_eeprom_info *info; + + info = malloc(sizeof(struct var_imx8_eeprom_info)); + if (!info) + return -ENOMEM; + + rc = var_read_som_eeprom(info); + if (rc) + return rc; + + display_som_infos(info); + +#if defined(CONFIG_BOARD_TYPES) + gd->board_type = info->features; +#endif /* CONFIG_BOARD_TYPES */ + + return 0; +} + +#endif /* CONFIG_DISPLAY_BOARDINFO */ + +static int insert_gpios_prop(void *blob, int node, const char *prop, + unsigned int phandle, u32 gpio, u32 flags) +{ + fdt32_t val[3] = { cpu_to_fdt32(phandle), cpu_to_fdt32(gpio), + cpu_to_fdt32(flags) }; + return fdt_setprop(blob, node, prop, &val, sizeof(val)); +} + +static int configure_phy_reset_gpios(void *blob) +{ + int node; + int phynode; + int ret; + u32 handle; + u32 gpio; + u32 flags; + char path[1024]; + const char *eth_alias = "ethernet0"; + + snprintf(path, sizeof(path), "%s/mdio/ethernet-phy@4", + fdt_get_alias(blob, eth_alias)); + + phynode = fdt_path_offset(blob, path); + if (phynode < 0) { + pr_err("%s(): unable to locate PHY node: %s\n", __func__, path); + return 0; + } + + if (gd_board_type() & VAR_EEPROM_F_ETH) { + snprintf(path, sizeof(path), "%s", + fdt_get_alias(blob, "gpio0")); /* Alias to gpio1 */ + gpio = 9; + flags = GPIO_ACTIVE_LOW; + } else { + snprintf(path, sizeof(path), "%s/gpio@20", + fdt_get_alias(blob, "i2c1")); /* Alias to i2c2 */ + gpio = 5; + flags = GPIO_ACTIVE_HIGH; + } + + node = fdt_path_offset(blob, path); + if (node < 0) { + pr_err("%s(): unable to locate GPIO node: %s\n", __func__, + path); + return 0; + } + + handle = fdt_get_phandle(blob, node); + if (handle < 0) { + pr_err("%s(): unable to locate GPIO controller handle: %s\n", + __func__, path); + } + + ret = insert_gpios_prop(blob, phynode, "reset-gpios", + handle, gpio, flags); + if (ret < 0) { + pr_err("%s(): failed to set reset-gpios property\n", __func__); + return ret; + } + + return 0; +} + +#if defined(CONFIG_OF_BOARD_FIXUP) +int board_fix_fdt(void *blob) +{ + /* Fix U-Boot device tree: */ + return configure_phy_reset_gpios(blob); +} +#endif /* CONFIG_OF_BOARD_FIXUP */ + +#if defined(CONFIG_OF_BOARD_SETUP) +int ft_board_setup(void *blob, struct bd_info *bd) +{ + /* Fix kernel device tree: */ + return configure_phy_reset_gpios(blob); +} +#endif /* CONFIG_OF_BOARD_SETUP */ + +#endif /* CONFIG_SPL_BUILD */ diff --git a/boot/Kconfig b/boot/Kconfig index a643a3d1286..c8b8f36d835 100644 --- a/boot/Kconfig +++ b/boot/Kconfig @@ -1630,4 +1630,18 @@ config SAVE_PREV_BL_INITRAMFS_START_ADDR If no initramfs was provided by previous bootloader, no env variables will be created. +menu "Configuration editor" + +config CEDIT + bool "Configuration editor" + depends on BOOTSTD + help + Provides a way to deal with board configuration and present it to + the user for adjustment. + + This is intended to provide both graphical and text-based user + interfaces, but only graphical is support at present. + +endmenu # Configuration editor + endmenu # Booting diff --git a/boot/Makefile b/boot/Makefile index f94c31d922d..f828f870a37 100644 --- a/boot/Makefile +++ b/boot/Makefile @@ -33,6 +33,7 @@ ifdef CONFIG_$(SPL_TPL_)BOOTSTD_FULL obj-$(CONFIG_CMD_BOOTEFI_BOOTMGR) += bootmeth_efi_mgr.o obj-$(CONFIG_$(SPL_TPL_)EXPO) += bootflow_menu.o obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootflow_menu.o +obj-$(CONFIG_$(SPL_TPL_)CEDIT) += cedit.o endif obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += image-fdt.o @@ -50,7 +51,7 @@ ifdef CONFIG_SPL_BUILD obj-$(CONFIG_SPL_LOAD_FIT) += common_fit.o endif -obj-$(CONFIG_$(SPL_TPL_)EXPO) += expo.o scene.o scene_menu.o +obj-$(CONFIG_$(SPL_TPL_)EXPO) += expo.o scene.o scene_menu.o expo_build.o obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_VBE) += vbe.o obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_VBE_REQUEST) += vbe_request.o diff --git a/boot/bootflow_menu.c b/boot/bootflow_menu.c index 7f06dac0af7..7c1abe5772c 100644 --- a/boot/bootflow_menu.c +++ b/boot/bootflow_menu.c @@ -124,6 +124,10 @@ int bootflow_menu_new(struct expo **expp) priv->num_bootflows++; } + ret = scene_arrange(scn); + if (ret) + return log_msg_ret("arr", ret); + *expp = exp; return 0; @@ -205,7 +209,7 @@ int bootflow_menu_run(struct bootstd_priv *std, bool text_mode, return log_msg_ret("scn", ret); if (text_mode) - exp_set_text_mode(exp, text_mode); + expo_set_text_mode(exp, text_mode); done = false; do { diff --git a/boot/bootmeth-uclass.c b/boot/bootmeth-uclass.c index 3b3e0614daf..701ee8ad1c8 100644 --- a/boot/bootmeth-uclass.c +++ b/boot/bootmeth-uclass.c @@ -301,32 +301,6 @@ int bootmeth_try_file(struct bootflow *bflow, struct blk_desc *desc, return 0; } -static int alloc_file(const char *fname, uint size, void **bufp) -{ - loff_t bytes_read; - ulong addr; - char *buf; - int ret; - - buf = malloc(size + 1); - if (!buf) - return log_msg_ret("buf", -ENOMEM); - addr = map_to_sysmem(buf); - - ret = fs_read(fname, addr, 0, size, &bytes_read); - if (ret) { - free(buf); - return log_msg_ret("read", ret); - } - if (size != bytes_read) - return log_msg_ret("bread", -EIO); - buf[size] = '\0'; - - *bufp = buf; - - return 0; -} - int bootmeth_alloc_file(struct bootflow *bflow, uint size_limit, uint align) { void *buf; @@ -338,7 +312,7 @@ int bootmeth_alloc_file(struct bootflow *bflow, uint size_limit, uint align) if (size > size_limit) return log_msg_ret("chk", -E2BIG); - ret = alloc_file(bflow->fname, bflow->size, &buf); + ret = fs_read_alloc(bflow->fname, bflow->size, align, &buf); if (ret) return log_msg_ret("all", ret); @@ -374,7 +348,7 @@ int bootmeth_alloc_other(struct bootflow *bflow, const char *fname, if (ret) return log_msg_ret("fs", ret); - ret = alloc_file(path, size, &buf); + ret = fs_read_alloc(path, size, 0, &buf); if (ret) return log_msg_ret("all", ret); diff --git a/boot/cedit.c b/boot/cedit.c new file mode 100644 index 00000000000..ee24658917b --- /dev/null +++ b/boot/cedit.c @@ -0,0 +1,163 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Implementation of configuration editor + * + * Copyright 2023 Google LLC + * Written by Simon Glass <sjg@chromium.org> + */ + +#include <common.h> +#include <cli.h> +#include <dm.h> +#include <expo.h> +#include <menu.h> +#include <video.h> +#include <linux/delay.h> +#include "scene_internal.h" + +int cedit_arange(struct expo *exp, struct video_priv *vpriv, uint scene_id) +{ + struct scene_obj_txt *txt; + struct scene_obj *obj; + struct scene *scn; + int y; + + scn = expo_lookup_scene_id(exp, scene_id); + if (!scn) + return log_msg_ret("scn", -ENOENT); + + txt = scene_obj_find_by_name(scn, "prompt"); + if (txt) + scene_obj_set_pos(scn, txt->obj.id, 0, vpriv->ysize - 50); + + txt = scene_obj_find_by_name(scn, "title"); + if (txt) + scene_obj_set_pos(scn, txt->obj.id, 200, 10); + + y = 100; + list_for_each_entry(obj, &scn->obj_head, sibling) { + if (obj->type == SCENEOBJT_MENU) { + scene_obj_set_pos(scn, obj->id, 50, y); + scene_menu_arrange(scn, (struct scene_obj_menu *)obj); + y += 50; + } + } + + return 0; +} + +int cedit_run(struct expo *exp) +{ + struct cli_ch_state s_cch, *cch = &s_cch; + struct video_priv *vid_priv; + uint scene_id; + struct udevice *dev; + struct scene *scn; + bool done; + int ret; + + cli_ch_init(cch); + + /* For now we only support a video console */ + ret = uclass_first_device_err(UCLASS_VIDEO, &dev); + if (ret) + return log_msg_ret("vid", ret); + ret = expo_set_display(exp, dev); + if (ret) + return log_msg_ret("dis", ret); + + ret = expo_first_scene_id(exp); + if (ret < 0) + return log_msg_ret("scn", ret); + scene_id = ret; + + ret = expo_set_scene_id(exp, scene_id); + if (ret) + return log_msg_ret("sid", ret); + + exp->popup = true; + + /* This is not supported for now */ + if (0) + expo_set_text_mode(exp, true); + + vid_priv = dev_get_uclass_priv(dev); + + scn = expo_lookup_scene_id(exp, scene_id); + scene_highlight_first(scn); + + cedit_arange(exp, vid_priv, scene_id); + + ret = expo_calc_dims(exp); + if (ret) + return log_msg_ret("dim", ret); + + done = false; + do { + struct expo_action act; + int ichar, key; + + ret = expo_render(exp); + if (ret) + break; + + ichar = cli_ch_process(cch, 0); + if (!ichar) { + while (!ichar && !tstc()) { + schedule(); + mdelay(2); + ichar = cli_ch_process(cch, -ETIMEDOUT); + } + if (!ichar) { + ichar = getchar(); + ichar = cli_ch_process(cch, ichar); + } + } + + key = 0; + if (ichar) { + key = bootmenu_conv_key(ichar); + if (key == BKEY_NONE) + key = ichar; + } + if (!key) + continue; + + ret = expo_send_key(exp, key); + if (ret) + break; + + ret = expo_action_get(exp, &act); + if (!ret) { + switch (act.type) { + case EXPOACT_POINT_OBJ: + scene_set_highlight_id(scn, act.select.id); + cedit_arange(exp, vid_priv, scene_id); + break; + case EXPOACT_OPEN: + scene_set_open(scn, act.select.id, true); + cedit_arange(exp, vid_priv, scene_id); + break; + case EXPOACT_CLOSE: + scene_set_open(scn, act.select.id, false); + cedit_arange(exp, vid_priv, scene_id); + break; + case EXPOACT_SELECT: + scene_set_open(scn, scn->highlight_id, false); + cedit_arange(exp, vid_priv, scene_id); + break; + case EXPOACT_QUIT: + log_debug("quitting\n"); + done = true; + break; + default: + break; + } + } + } while (!done); + + if (ret) + return log_msg_ret("end", ret); + + return 0; +} diff --git a/boot/expo.c b/boot/expo.c index 05950a17603..db837f7b492 100644 --- a/boot/expo.c +++ b/boot/expo.c @@ -6,6 +6,8 @@ * Written by Simon Glass <sjg@chromium.org> */ +#define LOG_CATEGORY LOGC_EXPO + #include <common.h> #include <dm.h> #include <expo.h> @@ -54,6 +56,22 @@ void expo_destroy(struct expo *exp) free(exp); } +uint resolve_id(struct expo *exp, uint id) +{ + log_debug("resolve id %d\n", id); + if (!id) + id = exp->next_id++; + else if (id >= exp->next_id) + exp->next_id = id + 1; + + return id; +} + +void expo_set_dynamic_start(struct expo *exp, uint dyn_start) +{ + exp->next_id = dyn_start; +} + int expo_str(struct expo *exp, const char *name, uint id, const char *str) { struct expo_string *estr; @@ -83,12 +101,45 @@ const char *expo_get_str(struct expo *exp, uint id) int expo_set_display(struct expo *exp, struct udevice *dev) { + struct udevice *cons; + int ret; + + ret = device_find_first_child_by_uclass(dev, UCLASS_VIDEO_CONSOLE, + &cons); + if (ret) + return log_msg_ret("con", ret); + exp->display = dev; + exp->cons = cons; + + return 0; +} + +int expo_calc_dims(struct expo *exp) +{ + struct scene *scn; + int ret; + + if (!exp->cons) + return log_msg_ret("dim", -ENOTSUPP); + + list_for_each_entry(scn, &exp->scene_head, sibling) { + /* + * Do the menus last so that all the menus' text objects + * are dimensioned + */ + ret = scene_calc_dims(scn, false); + if (ret) + return log_msg_ret("scn", ret); + ret = scene_calc_dims(scn, true); + if (ret) + return log_msg_ret("scn", ret); + } return 0; } -void exp_set_text_mode(struct expo *exp, bool text_mode) +void expo_set_text_mode(struct expo *exp, bool text_mode) { exp->text_mode = text_mode; } @@ -107,13 +158,33 @@ struct scene *expo_lookup_scene_id(struct expo *exp, uint scene_id) int expo_set_scene_id(struct expo *exp, uint scene_id) { - if (!expo_lookup_scene_id(exp, scene_id)) + struct scene *scn; + int ret; + + scn = expo_lookup_scene_id(exp, scene_id); + if (!scn) return log_msg_ret("id", -ENOENT); + ret = scene_arrange(scn); + if (ret) + return log_msg_ret("arr", ret); + exp->scene_id = scene_id; return 0; } +int expo_first_scene_id(struct expo *exp) +{ + struct scene *scn; + + if (list_empty(&exp->scene_head)) + return -ENOENT; + + scn = list_first_entry(&exp->scene_head, struct scene, sibling); + + return scn->id; +} + int expo_render(struct expo *exp) { struct udevice *dev = exp->display; @@ -156,6 +227,11 @@ int expo_send_key(struct expo *exp, int key) ret = scene_send_key(scn, key, &exp->action); if (ret) return log_msg_ret("key", ret); + + /* arrange it to get any changes */ + ret = scene_arrange(scn); + if (ret) + return log_msg_ret("arr", ret); } return scn ? 0 : -ECHILD; @@ -168,3 +244,25 @@ int expo_action_get(struct expo *exp, struct expo_action *act) return act->type == EXPOACT_NONE ? -EAGAIN : 0; } + +int expo_apply_theme(struct expo *exp, ofnode node) +{ + struct scene *scn; + struct expo_theme *theme = &exp->theme; + int ret; + + log_debug("Applying theme %s\n", ofnode_get_name(node)); + + memset(theme, '\0', sizeof(struct expo_theme)); + ofnode_read_u32(node, "font-size", &theme->font_size); + ofnode_read_u32(node, "menu-inset", &theme->menu_inset); + ofnode_read_u32(node, "menuitem-gap-y", &theme->menuitem_gap_y); + + list_for_each_entry(scn, &exp->scene_head, sibling) { + ret = scene_apply_theme(scn, theme); + if (ret) + return log_msg_ret("app", ret); + } + + return 0; +} diff --git a/boot/expo_build.c b/boot/expo_build.c new file mode 100644 index 00000000000..22f62eb54bc --- /dev/null +++ b/boot/expo_build.c @@ -0,0 +1,401 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Building an expo from an FDT description + * + * Copyright 2022 Google LLC + * Written by Simon Glass <sjg@chromium.org> + */ + +#define LOG_CATEGORY LOGC_EXPO + +#include <common.h> +#include <expo.h> +#include <fdtdec.h> +#include <log.h> +#include <malloc.h> +#include <dm/ofnode.h> +#include <linux/libfdt.h> + +/** + * struct build_info - Information to use when building + * + * @str_for_id: String for each ID in use, NULL if empty. The string is NULL + * if there is nothing for this ID. Since ID 0 is never used, the first + * element of this array is always NULL + * @str_count: Number of entries in @str_for_id + */ +struct build_info { + const char **str_for_id; + int str_count; +}; + +/** + * add_txt_str - Add a string or lookup its ID, then add to expo + * + * @info: Build information + * @node: Node describing scene + * @scn: Scene to add to + * @find_name: Name to look for (e.g. "title"). This will find a property called + * "title" if it exists, else will look up the string for "title-id" + * Return: ID of added string, or -ve on error + */ +int add_txt_str(struct build_info *info, ofnode node, struct scene *scn, + const char *find_name, uint obj_id) +{ + const char *text; + uint str_id; + int ret; + + text = ofnode_read_string(node, find_name); + if (!text) { + char name[40]; + u32 id; + + snprintf(name, sizeof(name), "%s-id", find_name); + ret = ofnode_read_u32(node, name, &id); + if (ret) + return log_msg_ret("id", -EINVAL); + + if (id >= info->str_count) + return log_msg_ret("id", -E2BIG); + text = info->str_for_id[id]; + if (!text) + return log_msg_ret("id", -EINVAL); + } + + ret = expo_str(scn->expo, find_name, 0, text); + if (ret < 0) + return log_msg_ret("add", ret); + str_id = ret; + + ret = scene_txt_str(scn, find_name, obj_id, str_id, text, NULL); + if (ret < 0) + return log_msg_ret("add", ret); + + return ret; +} + +/** + * add_txt_str_list - Add a list string or lookup its ID, then add to expo + * + * @info: Build information + * @node: Node describing scene + * @scn: Scene to add to + * @find_name: Name to look for (e.g. "title"). This will find a string-list + * property called "title" if it exists, else will look up the string in the + * "title-id" string list. + * Return: ID of added string, or -ve on error + */ +int add_txt_str_list(struct build_info *info, ofnode node, struct scene *scn, + const char *find_name, int index, uint obj_id) +{ + const char *text; + uint str_id; + int ret; + + ret = ofnode_read_string_index(node, find_name, index, &text); + if (ret) { + char name[40]; + u32 id; + + snprintf(name, sizeof(name), "%s-id", find_name); + ret = ofnode_read_u32_index(node, name, index, &id); + if (ret) + return log_msg_ret("id", -ENOENT); + + if (id >= info->str_count) + return log_msg_ret("id", -E2BIG); + text = info->str_for_id[id]; + if (!text) + return log_msg_ret("id", -EINVAL); + } + + ret = expo_str(scn->expo, find_name, 0, text); + if (ret < 0) + return log_msg_ret("add", ret); + str_id = ret; + + ret = scene_txt_str(scn, find_name, obj_id, str_id, text, NULL); + if (ret < 0) + return log_msg_ret("add", ret); + + return ret; +} + +/* + * build_element() - Handle creating a text object from a label + * + * Look up a property called @label or @label-id and create a string for it + */ +int build_element(void *ldtb, int node, const char *label) +{ + return 0; +} + +/** + * read_strings() - Read in the list of strings + * + * Read the strings into an ID-indexed list, so they can be used for building + * an expo. The strings are in a /strings node and each has its own subnode + * containing the ID and the string itself: + * + * example { + * id = <123>; + * value = "This is a test"; + * }; + * + * Future work may add support for unicode and multiple languages + * + * @info: Build information + * @root: Root node to read from + * Returns: 0 if OK, -ENOMEM if out of memory, -EINVAL if there is a format + * error + */ +static int read_strings(struct build_info *info, ofnode root) +{ + ofnode strings, node; + + strings = ofnode_find_subnode(root, "strings"); + if (!ofnode_valid(strings)) + return log_msg_ret("str", -EINVAL); + + ofnode_for_each_subnode(node, strings) { + const char *val; + int ret; + u32 id; + + ret = ofnode_read_u32(node, "id", &id); + if (ret) + return log_msg_ret("id", -EINVAL); + val = ofnode_read_string(node, "value"); + if (!val) + return log_msg_ret("val", -EINVAL); + + if (id >= info->str_count) { + int new_count = info->str_count + 20; + void *new_arr; + + new_arr = realloc(info->str_for_id, + new_count * sizeof(char *)); + if (!new_arr) + return log_msg_ret("id", -ENOMEM); + memset(new_arr + info->str_count, '\0', + (new_count - info->str_count) * sizeof(char *)); + info->str_for_id = new_arr; + info->str_count = new_count; + } + + info->str_for_id[id] = val; + } + + return 0; +} + +/** + * list_strings() - List the available strings with their IDs + * + * @info: Build information + */ +static void list_strings(struct build_info *info) +{ + int i; + + for (i = 0; i < info->str_count; i++) { + if (info->str_for_id[i]) + printf("%3d %s\n", i, info->str_for_id[i]); + } +} + +/** + * menu_build() - Build a menu and add it to a scene + * + * See doc/developer/expo.rst for a description of the format + * + * @info: Build information + * @node: Node containing the menu description + * @scn: Scene to add the menu to + * Returns: 0 if OK, -ENOMEM if out of memory, -EINVAL if there is a format + * error, -ENOENT if there is a references to a non-existent string + */ +static int menu_build(struct build_info *info, ofnode node, struct scene *scn) +{ + struct scene_obj_menu *menu; + uint title_id, menu_id; + const u32 *item_ids; + int ret, size, i; + const char *name; + u32 id; + + name = ofnode_get_name(node); + ret = ofnode_read_u32(node, "id", &id); + if (ret) + return log_msg_ret("id", -EINVAL); + + ret = scene_menu(scn, name, id, &menu); + if (ret < 0) + return log_msg_ret("men", ret); + menu_id = ret; + + /* Set the title */ + ret = add_txt_str(info, node, scn, "title", 0); + if (ret < 0) + return log_msg_ret("tit", ret); + title_id = ret; + ret = scene_menu_set_title(scn, menu_id, title_id); + + item_ids = ofnode_read_prop(node, "item-id", &size); + if (!item_ids) + return log_msg_ret("itm", -EINVAL); + if (!size || size % sizeof(u32)) + return log_msg_ret("isz", -EINVAL); + size /= sizeof(u32); + + for (i = 0; i < size; i++) { + struct scene_menitem *item; + uint label, key, desc; + + ret = add_txt_str_list(info, node, scn, "item-label", i, 0); + if (ret < 0 && ret != -ENOENT) + return log_msg_ret("lab", ret); + label = max(0, ret); + + ret = add_txt_str_list(info, node, scn, "key-label", i, 0); + if (ret < 0 && ret != -ENOENT) + return log_msg_ret("key", ret); + key = max(0, ret); + + ret = add_txt_str_list(info, node, scn, "desc-label", i, 0); + if (ret < 0 && ret != -ENOENT) + return log_msg_ret("lab", ret); + desc = max(0, ret); + + ret = scene_menuitem(scn, menu_id, simple_xtoa(i), + fdt32_to_cpu(item_ids[i]), key, label, + desc, 0, 0, &item); + if (ret < 0) + return log_msg_ret("mi", ret); + } + + return 0; +} + +/** + * menu_build() - Build an expo object and add it to a scene + * + * See doc/developer/expo.rst for a description of the format + * + * @info: Build information + * @node: Node containing the object description + * @scn: Scene to add the object to + * Returns: 0 if OK, -ENOMEM if out of memory, -EINVAL if there is a format + * error, -ENOENT if there is a references to a non-existent string + */ +static int obj_build(struct build_info *info, ofnode node, struct scene *scn) +{ + const char *type; + u32 id; + int ret; + + log_debug("- object %s\n", ofnode_get_name(node)); + ret = ofnode_read_u32(node, "id", &id); + if (ret) + return log_msg_ret("id", -EINVAL); + + type = ofnode_read_string(node, "type"); + if (!type) + return log_msg_ret("typ", -EINVAL); + + if (!strcmp("menu", type)) + ret = menu_build(info, node, scn); + else + ret = -EINVAL; + if (ret) + return log_msg_ret("bld", ret); + + return 0; +} + +/** + * scene_build() - Build a scene and all its objects + * + * See doc/developer/expo.rst for a description of the format + * + * @info: Build information + * @node: Node containing the scene description + * @scn: Scene to add the object to + * Returns: 0 if OK, -ENOMEM if out of memory, -EINVAL if there is a format + * error, -ENOENT if there is a references to a non-existent string + */ +static int scene_build(struct build_info *info, ofnode scn_node, + struct expo *exp) +{ + const char *name; + struct scene *scn; + uint id, title_id; + ofnode node; + int ret; + + name = ofnode_get_name(scn_node); + log_debug("Building scene %s\n", name); + ret = ofnode_read_u32(scn_node, "id", &id); + if (ret) + return log_msg_ret("id", -EINVAL); + + ret = scene_new(exp, name, id, &scn); + if (ret < 0) + return log_msg_ret("scn", ret); + + ret = add_txt_str(info, scn_node, scn, "title", 0); + if (ret < 0) + return log_msg_ret("tit", ret); + title_id = ret; + scene_title_set(scn, title_id); + + ret = add_txt_str(info, scn_node, scn, "prompt", 0); + if (ret < 0) + return log_msg_ret("pr", ret); + + ofnode_for_each_subnode(node, scn_node) { + ret = obj_build(info, node, scn); + if (ret < 0) + return log_msg_ret("mit", ret); + } + + return 0; +} + +int expo_build(ofnode root, struct expo **expp) +{ + struct build_info info; + ofnode scenes, node; + struct expo *exp; + u32 dyn_start; + int ret; + + memset(&info, '\0', sizeof(info)); + ret = read_strings(&info, root); + if (ret) + return log_msg_ret("str", ret); + if (_DEBUG) + list_strings(&info); + + ret = expo_new("name", NULL, &exp); + if (ret) + return log_msg_ret("exp", ret); + + if (!ofnode_read_u32(root, "dynamic-start", &dyn_start)) + expo_set_dynamic_start(exp, dyn_start); + + scenes = ofnode_find_subnode(root, "scenes"); + if (!ofnode_valid(scenes)) + return log_msg_ret("sno", -EINVAL); + + ofnode_for_each_subnode(node, scenes) { + ret = scene_build(&info, node, exp); + if (ret < 0) + return log_msg_ret("scn", ret); + } + *expp = exp; + + return 0; +} diff --git a/boot/scene.c b/boot/scene.c index 030f6aa2a0a..e52333371f9 100644 --- a/boot/scene.c +++ b/boot/scene.c @@ -6,26 +6,19 @@ * Written by Simon Glass <sjg@chromium.org> */ +#define LOG_CATEGORY LOGC_EXPO + #include <common.h> #include <dm.h> #include <expo.h> #include <malloc.h> #include <mapmem.h> +#include <menu.h> #include <video.h> #include <video_console.h> #include <linux/input.h> #include "scene_internal.h" -uint resolve_id(struct expo *exp, uint id) -{ - if (!id) - id = exp->next_id++; - else if (id >= exp->next_id) - exp->next_id = id + 1; - - return id; -} - int scene_new(struct expo *exp, const char *name, uint id, struct scene **scnp) { struct scene *scn; @@ -65,16 +58,12 @@ void scene_destroy(struct scene *scn) scene_obj_destroy(obj); free(scn->name); - free(scn->title); free(scn); } -int scene_title_set(struct scene *scn, const char *title) +int scene_title_set(struct scene *scn, uint id) { - free(scn->title); - scn->title = strdup(title); - if (!scn->title) - return log_msg_ret("tit", -ENOMEM); + scn->title_id = id; return 0; } @@ -103,6 +92,18 @@ void *scene_obj_find(struct scene *scn, uint id, enum scene_obj_t type) return NULL; } +void *scene_obj_find_by_name(struct scene *scn, const char *name) +{ + struct scene_obj *obj; + + list_for_each_entry(obj, &scn->obj_head, sibling) { + if (!strcmp(name, obj->name)) + return obj; + } + + return NULL; +} + int scene_obj_add(struct scene *scn, const char *name, uint id, enum scene_obj_t type, uint size, struct scene_obj **objp) { @@ -213,22 +214,46 @@ int scene_obj_set_pos(struct scene *scn, uint id, int x, int y) obj = scene_obj_find(scn, id, SCENEOBJT_NONE); if (!obj) return log_msg_ret("find", -ENOENT); - obj->x = x; - obj->y = y; - if (obj->type == SCENEOBJT_MENU) - scene_menu_arrange(scn, (struct scene_obj_menu *)obj); + obj->dim.x = x; + obj->dim.y = y; + + return 0; +} + +int scene_obj_set_size(struct scene *scn, uint id, int w, int h) +{ + struct scene_obj *obj; + + obj = scene_obj_find(scn, id, SCENEOBJT_NONE); + if (!obj) + return log_msg_ret("find", -ENOENT); + obj->dim.w = w; + obj->dim.h = h; return 0; } int scene_obj_set_hide(struct scene *scn, uint id, bool hide) { + int ret; + + ret = scene_obj_flag_clrset(scn, id, SCENEOF_HIDE, + hide ? SCENEOF_HIDE : 0); + if (ret) + return log_msg_ret("flg", ret); + + return 0; +} + +int scene_obj_flag_clrset(struct scene *scn, uint id, uint clr, uint set) +{ struct scene_obj *obj; obj = scene_obj_find(scn, id, SCENEOBJT_NONE); if (!obj) return log_msg_ret("find", -ENOENT); - obj->hide = hide; + obj->flags &= ~clr; + obj->flags |= set; return 0; } @@ -258,16 +283,30 @@ int scene_obj_get_hw(struct scene *scn, uint id, int *widthp) case SCENEOBJT_TEXT: { struct scene_obj_txt *txt = (struct scene_obj_txt *)obj; struct expo *exp = scn->expo; + struct vidconsole_bbox bbox; + const char *str; + int len, ret; + str = expo_get_str(exp, txt->str_id); + if (!str) + return log_msg_ret("str", -ENOENT); + len = strlen(str); + + /* if there is no console, make it up */ + if (!exp->cons) { + if (widthp) + *widthp = 8 * len; + return 16; + } + + ret = vidconsole_measure(scn->expo->cons, txt->font_name, + txt->font_size, str, &bbox); + if (ret) + return log_msg_ret("mea", ret); if (widthp) - *widthp = 16; /* fake value for now */ - if (txt->font_size) - return txt->font_size; - if (exp->display) - return video_default_font_height(exp->display); - - /* use a sensible default */ - return 16; + *widthp = bbox.x1; + + return bbox.y1; } } @@ -282,18 +321,13 @@ static int scene_obj_render(struct scene_obj *obj, bool text_mode) { struct scene *scn = obj->scene; struct expo *exp = scn->expo; - struct udevice *cons, *dev = exp->display; + const struct expo_theme *theme = &exp->theme; + struct udevice *dev = exp->display; + struct udevice *cons = text_mode ? NULL : exp->cons; int x, y, ret; - cons = NULL; - if (!text_mode) { - ret = device_find_first_child_by_uclass(dev, - UCLASS_VIDEO_CONSOLE, - &cons); - } - - x = obj->x; - y = obj->y; + x = obj->dim.x; + y = obj->dim.y; switch (obj->type) { case SCENEOBJT_NONE: @@ -325,14 +359,45 @@ static int scene_obj_render(struct scene_obj *obj, bool text_mode) } if (ret && ret != -ENOSYS) return log_msg_ret("font", ret); - vidconsole_set_cursor_pos(cons, x, y); str = expo_get_str(exp, txt->str_id); - if (str) + if (str) { + struct video_priv *vid_priv; + struct vidconsole_colour old; + enum colour_idx fore, back; + + if (CONFIG_IS_ENABLED(SYS_WHITE_ON_BLACK)) { + fore = VID_BLACK; + back = VID_WHITE; + } else { + fore = VID_LIGHT_GRAY; + back = VID_BLACK; + } + + vid_priv = dev_get_uclass_priv(dev); + if (obj->flags & SCENEOF_POINT) { + vidconsole_push_colour(cons, fore, back, &old); + video_fill_part(dev, x - theme->menu_inset, y, + x + obj->dim.w, + y + obj->dim.h, + vid_priv->colour_bg); + } + vidconsole_set_cursor_pos(cons, x, y); vidconsole_put_string(cons, str); + if (obj->flags & SCENEOF_POINT) + vidconsole_pop_colour(cons, &old); + } break; } case SCENEOBJT_MENU: { struct scene_obj_menu *menu = (struct scene_obj_menu *)obj; + + if (exp->popup && (obj->flags & SCENEOF_OPEN)) { + if (!cons) + return -ENOTSUPP; + + /* draw a background behind the menu items */ + scene_menu_render(menu); + } /* * With a vidconsole, the text and item pointer are rendered as * normal objects so we don't need to do anything here. The menu @@ -371,6 +436,30 @@ int scene_arrange(struct scene *scn) return 0; } +int scene_render_deps(struct scene *scn, uint id) +{ + struct scene_obj *obj; + int ret; + + if (!id) + return 0; + obj = scene_obj_find(scn, id, SCENEOBJT_NONE); + if (!obj) + return log_msg_ret("obj", -ENOENT); + + if (!(obj->flags & SCENEOF_HIDE)) { + ret = scene_obj_render(obj, false); + if (ret && ret != -ENOTSUPP) + return log_msg_ret("ren", ret); + + if (obj->type == SCENEOBJT_MENU) + scene_menu_render_deps(scn, + (struct scene_obj_menu *)obj); + } + + return 0; +} + int scene_render(struct scene *scn) { struct expo *exp = scn->expo; @@ -378,21 +467,107 @@ int scene_render(struct scene *scn) int ret; list_for_each_entry(obj, &scn->obj_head, sibling) { - if (!obj->hide) { + if (!(obj->flags & SCENEOF_HIDE)) { ret = scene_obj_render(obj, exp->text_mode); if (ret && ret != -ENOTSUPP) return log_msg_ret("ren", ret); } } + /* render any highlighted object on top of the others */ + if (scn->highlight_id && !exp->text_mode) { + ret = scene_render_deps(scn, scn->highlight_id); + if (ret && ret != -ENOTSUPP) + return log_msg_ret("dep", ret); + } + return 0; } +/** + * send_key_obj() - Handle a keypress for moving between objects + * + * @scn: Scene to receive the key + * @key: Key to send (KEYCODE_UP) + * @event: Returns resulting event from this keypress + * Returns: 0 if OK, -ve on error + */ +static void send_key_obj(struct scene *scn, struct scene_obj *obj, int key, + struct expo_action *event) +{ + switch (key) { + case BKEY_UP: + while (obj != list_first_entry(&scn->obj_head, struct scene_obj, + sibling)) { + obj = list_entry(obj->sibling.prev, + struct scene_obj, sibling); + if (obj->type == SCENEOBJT_MENU) { + event->type = EXPOACT_POINT_OBJ; + event->select.id = obj->id; + log_debug("up to obj %d\n", event->select.id); + break; + } + } + break; + case BKEY_DOWN: + while (!list_is_last(&obj->sibling, &scn->obj_head)) { + obj = list_entry(obj->sibling.next, struct scene_obj, + sibling); + if (obj->type == SCENEOBJT_MENU) { + event->type = EXPOACT_POINT_OBJ; + event->select.id = obj->id; + log_debug("down to obj %d\n", event->select.id); + break; + } + } + break; + case BKEY_SELECT: + if (obj->type == SCENEOBJT_MENU) { + event->type = EXPOACT_OPEN; + event->select.id = obj->id; + log_debug("open obj %d\n", event->select.id); + } + break; + case BKEY_QUIT: + event->type = EXPOACT_QUIT; + log_debug("obj quit\n"); + break; + } +} + int scene_send_key(struct scene *scn, int key, struct expo_action *event) { + struct scene_obj_menu *menu; struct scene_obj *obj; int ret; + event->type = EXPOACT_NONE; + + /* + * In 'popup' mode, arrow keys move betwen objects, unless a menu is + * opened + */ + if (scn->expo->popup) { + obj = NULL; + if (scn->highlight_id) { + obj = scene_obj_find(scn, scn->highlight_id, + SCENEOBJT_NONE); + } + if (!obj) + return 0; + + if (!(obj->flags & SCENEOF_OPEN)) { + send_key_obj(scn, obj, key, event); + return 0; + } + + menu = (struct scene_obj_menu *)obj, + ret = scene_menu_send_key(scn, menu, key, event); + if (ret) + return log_msg_ret("key", ret); + return 0; + } + list_for_each_entry(obj, &scn->obj_head, sibling) { if (obj->type == SCENEOBJT_MENU) { struct scene_obj_menu *menu; @@ -401,14 +576,108 @@ int scene_send_key(struct scene *scn, int key, struct expo_action *event) ret = scene_menu_send_key(scn, menu, key, event); if (ret) return log_msg_ret("key", ret); + break; + } + } - /* only allow one menu */ - ret = scene_menu_arrange(scn, menu); - if (ret) - return log_msg_ret("arr", ret); + return 0; +} + +int scene_calc_dims(struct scene *scn, bool do_menus) +{ + struct scene_obj *obj; + int ret; + + list_for_each_entry(obj, &scn->obj_head, sibling) { + switch (obj->type) { + case SCENEOBJT_NONE: + case SCENEOBJT_TEXT: + case SCENEOBJT_IMAGE: { + int width; + + if (!do_menus) { + ret = scene_obj_get_hw(scn, obj->id, &width); + if (ret < 0) + return log_msg_ret("get", ret); + obj->dim.w = width; + obj->dim.h = ret; + } + break; + } + case SCENEOBJT_MENU: { + struct scene_obj_menu *menu; + + if (do_menus) { + menu = (struct scene_obj_menu *)obj; + + ret = scene_menu_calc_dims(menu); + if (ret) + return log_msg_ret("men", ret); + } + break; + } + } + } + + return 0; +} + +int scene_apply_theme(struct scene *scn, struct expo_theme *theme) +{ + struct scene_obj *obj; + int ret; + + /* Avoid error-checking optional items */ + scene_txt_set_font(scn, scn->title_id, NULL, theme->font_size); + + list_for_each_entry(obj, &scn->obj_head, sibling) { + switch (obj->type) { + case SCENEOBJT_NONE: + case SCENEOBJT_IMAGE: + case SCENEOBJT_MENU: + break; + case SCENEOBJT_TEXT: + scene_txt_set_font(scn, obj->id, NULL, + theme->font_size); + break; + } + } + + ret = scene_arrange(scn); + if (ret) + return log_msg_ret("arr", ret); + + return 0; +} + +void scene_set_highlight_id(struct scene *scn, uint id) +{ + scn->highlight_id = id; +} + +void scene_highlight_first(struct scene *scn) +{ + struct scene_obj *obj; + + list_for_each_entry(obj, &scn->obj_head, sibling) { + switch (obj->type) { + case SCENEOBJT_MENU: + scene_set_highlight_id(scn, obj->id); + return; + default: break; } } +} + +int scene_set_open(struct scene *scn, uint id, bool open) +{ + int ret; + + ret = scene_obj_flag_clrset(scn, id, SCENEOF_OPEN, + open ? SCENEOF_OPEN : 0); + if (ret) + return log_msg_ret("flg", ret); return 0; } diff --git a/boot/scene_internal.h b/boot/scene_internal.h index e8fd765811e..fb1ea5533b9 100644 --- a/boot/scene_internal.h +++ b/boot/scene_internal.h @@ -23,7 +23,7 @@ struct scene *expo_lookup_scene_id(struct expo *exp, uint scene_id); * * @exp: Expo to use * @id: ID to use, or 0 to auto-allocate one - * @return: Either @id, or the auto-allocated ID + * Returns: Either @id, or the auto-allocated ID */ uint resolve_id(struct expo *exp, uint id); @@ -36,10 +36,19 @@ uint resolve_id(struct expo *exp, uint id); * @scn: Scene to search * @id: ID of object to find * @type: Type of the object, or SCENEOBJT_NONE to match any type + * Returns: Object found, or NULL if not found */ void *scene_obj_find(struct scene *scn, uint id, enum scene_obj_t type); /** + * scene_obj_find_by_name() - Find an object in a scene by name + * + * @scn: Scene to search + * @name: Name to search for + */ +void *scene_obj_find_by_name(struct scene *scn, const char *name); + +/** * scene_obj_add() - Add a new object to a scene * * @scn: Scene to update @@ -54,6 +63,28 @@ int scene_obj_add(struct scene *scn, const char *name, uint id, enum scene_obj_t type, uint size, struct scene_obj **objp); /** + * scene_obj_flag_clrset() - Adjust object flags + * + * @scn: Scene to update + * @id: ID of object to update + * @clr: Bits to clear in the object's flags + * @set: Bits to set in the object's flags + * Returns 0 if OK, -ENOENT if the object was not found + */ +int scene_obj_flag_clrset(struct scene *scn, uint id, uint clr, uint set); + +/** + * scene_calc_dims() - Calculate the dimensions of the scene objects + * + * Updates the width and height of all objects based on their contents + * + * @scn: Scene to update + * @do_menus: true to calculate only menus, false to calculate everything else + * Returns 0 if OK, -ENOTSUPP if there is no graphical console + */ +int scene_calc_dims(struct scene *scn, bool do_menus); + +/** * scene_menu_arrange() - Set the position of things in the menu * * This updates any items associated with a menu to make sure they are @@ -62,17 +93,27 @@ int scene_obj_add(struct scene *scn, const char *name, uint id, * * @scn: Scene to update * @menu: Menu to process + * Returns: 0 if OK, -ve on error */ int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu); /** + * scene_apply_theme() - Apply a theme to a scene + * + * @scn: Scene to update + * @theme: Theme to apply + * Returns: 0 if OK, -ve on error + */ +int scene_apply_theme(struct scene *scn, struct expo_theme *theme); + +/** * scene_menu_send_key() - Send a key to a menu for processing * * @scn: Scene to use * @menu: Menu to use * @key: Key code to send (KEY_...) * @event: Place to put any event which is generated by the key - * @return 0 if OK, -ENOTTY if there is no current menu item, other -ve on other + * Returns: 0 if OK, -ENOTTY if there is no current menu item, other -ve on other * error */ int scene_menu_send_key(struct scene *scn, struct scene_obj_menu *menu, int key, @@ -89,7 +130,7 @@ void scene_menu_destroy(struct scene_obj_menu *menu); * scene_menu_display() - Display a menu as text * * @menu: Menu to display - * @return 0 if OK, -ENOENT if @id is invalid + * Returns: 0 if OK, -ENOENT if @id is invalid */ int scene_menu_display(struct scene_obj_menu *menu); @@ -120,4 +161,41 @@ int scene_render(struct scene *scn); */ int scene_send_key(struct scene *scn, int key, struct expo_action *event); +/** + * scene_menu_render() - Render the background behind a menu + * + * @menu: Menu to render + */ +void scene_menu_render(struct scene_obj_menu *menu); + +/** + * scene_render_deps() - Render an object and its dependencies + * + * @scn: Scene to render + * @id: Object ID to render (or 0 for none) + * Returns: 0 if OK, -ve on error + */ +int scene_render_deps(struct scene *scn, uint id); + +/** + * scene_menu_render_deps() - Render a menu and its dependencies + * + * Renders the menu and all of its attached objects + * + * @scn: Scene to render + * @menu: Menu render + * Returns: 0 if OK, -ve on error + */ +int scene_menu_render_deps(struct scene *scn, struct scene_obj_menu *menu); + +/** + * scene_menu_calc_dims() - Calculate the dimensions of a menu + * + * Updates the width and height of the menu based on its contents + * + * @menu: Menu to update + * Returns 0 if OK, -ENOTSUPP if there is no graphical console + */ +int scene_menu_calc_dims(struct scene_obj_menu *menu); + #endif /* __SCENE_INTERNAL_H */ diff --git a/boot/scene_menu.c b/boot/scene_menu.c index 18998e862ab..8a355f838cc 100644 --- a/boot/scene_menu.c +++ b/boot/scene_menu.c @@ -6,7 +6,7 @@ * Written by Simon Glass <sjg@chromium.org> */ -#define LOG_CATEGORY LOGC_BOOT +#define LOG_CATEGORY LOGC_EXPO #include <common.h> #include <dm.h> @@ -33,6 +33,58 @@ void scene_menu_destroy(struct scene_obj_menu *menu) scene_menuitem_destroy(item); } +static struct scene_menitem *scene_menuitem_find(struct scene_obj_menu *menu, + int id) +{ + struct scene_menitem *item; + + list_for_each_entry(item, &menu->item_head, sibling) { + if (item->id == id) + return item; + } + + return NULL; +} + +/** + * update_pointers() - Update the pointer object and handle highlights + * + * @menu: Menu to update + * @id: ID of menu item to select/deselect + * @point: true if @id is being selected, false if it is being deselected + */ +static int update_pointers(struct scene_obj_menu *menu, uint id, bool point) +{ + struct scene *scn = menu->obj.scene; + const bool stack = scn->expo->popup; + const struct scene_menitem *item; + int ret; + + item = scene_menuitem_find(menu, id); + if (!item) + return log_msg_ret("itm", -ENOENT); + + /* adjust the pointer object to point to the selected item */ + if (menu->pointer_id && item && point) { + struct scene_obj *label; + + label = scene_obj_find(scn, item->label_id, SCENEOBJT_NONE); + + ret = scene_obj_set_pos(scn, menu->pointer_id, + menu->obj.dim.x + 200, label->dim.y); + if (ret < 0) + return log_msg_ret("ptr", ret); + } + + if (stack) { + point &= scn->highlight_id == menu->obj.id; + scene_obj_flag_clrset(scn, item->label_id, SCENEOF_POINT, + point ? SCENEOF_POINT : 0); + } + + return 0; +} + /** * menu_point_to_item() - Point to a particular menu item * @@ -40,18 +92,115 @@ void scene_menu_destroy(struct scene_obj_menu *menu) */ static void menu_point_to_item(struct scene_obj_menu *menu, uint item_id) { + if (menu->cur_item_id) + update_pointers(menu, menu->cur_item_id, false); menu->cur_item_id = item_id; + update_pointers(menu, item_id, true); +} + +static int scene_bbox_union(struct scene *scn, uint id, int inset, + struct vidconsole_bbox *bbox) +{ + struct scene_obj *obj; + + if (!id) + return 0; + obj = scene_obj_find(scn, id, SCENEOBJT_NONE); + if (!obj) + return log_msg_ret("obj", -ENOENT); + if (bbox->valid) { + bbox->x0 = min(bbox->x0, obj->dim.x - inset); + bbox->y0 = min(bbox->y0, obj->dim.y); + bbox->x1 = max(bbox->x1, obj->dim.x + obj->dim.w + inset); + bbox->y1 = max(bbox->y1, obj->dim.y + obj->dim.h); + } else { + bbox->x0 = obj->dim.x - inset; + bbox->y0 = obj->dim.y; + bbox->x1 = obj->dim.x + obj->dim.w + inset; + bbox->y1 = obj->dim.y + obj->dim.h; + bbox->valid = true; + } + + return 0; +} + +/** + * scene_menu_calc_bbox() - Calculate bounding boxes for the menu + * + * @menu: Menu to process + * @bbox: Returns bounding box of menu including prompts + * @label_bbox: Returns bounding box of labels + */ +static void scene_menu_calc_bbox(struct scene_obj_menu *menu, + struct vidconsole_bbox *bbox, + struct vidconsole_bbox *label_bbox) +{ + const struct expo_theme *theme = &menu->obj.scene->expo->theme; + const struct scene_menitem *item; + + bbox->valid = false; + scene_bbox_union(menu->obj.scene, menu->title_id, 0, bbox); + + label_bbox->valid = false; + + list_for_each_entry(item, &menu->item_head, sibling) { + scene_bbox_union(menu->obj.scene, item->label_id, + theme->menu_inset, bbox); + scene_bbox_union(menu->obj.scene, item->key_id, 0, bbox); + scene_bbox_union(menu->obj.scene, item->desc_id, 0, bbox); + scene_bbox_union(menu->obj.scene, item->preview_id, 0, bbox); + + /* Get the bounding box of all labels */ + scene_bbox_union(menu->obj.scene, item->label_id, + theme->menu_inset, label_bbox); + } + + /* + * subtract the final menuitem's gap to keep the insert the same top + * and bottom + */ + label_bbox->y1 -= theme->menuitem_gap_y; +} + +int scene_menu_calc_dims(struct scene_obj_menu *menu) +{ + struct vidconsole_bbox bbox, label_bbox; + const struct scene_menitem *item; + + scene_menu_calc_bbox(menu, &bbox, &label_bbox); + + /* Make all labels the same size */ + if (label_bbox.valid) { + list_for_each_entry(item, &menu->item_head, sibling) { + scene_obj_set_size(menu->obj.scene, item->label_id, + label_bbox.x1 - label_bbox.x0, + label_bbox.y1 - label_bbox.y0); + } + } + + if (bbox.valid) { + menu->obj.dim.w = bbox.x1 - bbox.x0; + menu->obj.dim.h = bbox.y1 - bbox.y0; + } + + return 0; } int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu) { + const bool open = menu->obj.flags & SCENEOF_OPEN; + struct expo *exp = scn->expo; + const bool stack = exp->popup; + const struct expo_theme *theme = &exp->theme; struct scene_menitem *item; - int y, cur_y; + uint sel_id; + int x, y; int ret; - y = menu->obj.y; + x = menu->obj.dim.x; + y = menu->obj.dim.y; if (menu->title_id) { - ret = scene_obj_set_pos(scn, menu->title_id, menu->obj.x, y); + ret = scene_obj_set_pos(scn, menu->title_id, menu->obj.dim.x, y); if (ret < 0) return log_msg_ret("tit", ret); @@ -59,7 +208,10 @@ int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu) if (ret < 0) return log_msg_ret("hei", ret); - y += ret * 2; + if (stack) + x += 200; + else + y += ret * 2; } /* @@ -68,11 +220,12 @@ int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu) * small. This can be updated once text measuring is supported in * vidconsole */ - cur_y = -1; + sel_id = menu->cur_item_id; list_for_each_entry(item, &menu->item_head, sibling) { + bool selected; int height; - ret = scene_obj_get_hw(scn, item->desc_id, NULL); + ret = scene_obj_get_hw(scn, item->label_id, NULL); if (ret < 0) return log_msg_ret("get", ret); height = ret; @@ -81,32 +234,33 @@ int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu) y += height; /* select an item if not done already */ - if (!menu->cur_item_id) - menu_point_to_item(menu, item->id); + if (!sel_id) + sel_id = item->id; + + selected = sel_id == item->id; /* * Put the label on the left, then leave a space for the * pointer, then the key and the description */ - if (item->label_id) { - ret = scene_obj_set_pos(scn, item->label_id, menu->obj.x, - y); - if (ret < 0) - return log_msg_ret("nam", ret); - } - - ret = scene_obj_set_pos(scn, item->key_id, menu->obj.x + 230, - y); + ret = scene_obj_set_pos(scn, item->label_id, + x + theme->menu_inset, y); if (ret < 0) - return log_msg_ret("key", ret); + return log_msg_ret("nam", ret); + scene_obj_set_hide(scn, item->label_id, + stack && !open && !selected); - ret = scene_obj_set_pos(scn, item->desc_id, menu->obj.x + 280, - y); - if (ret < 0) - return log_msg_ret("des", ret); + if (item->key_id) { + ret = scene_obj_set_pos(scn, item->key_id, x + 230, y); + if (ret < 0) + return log_msg_ret("key", ret); + } - if (menu->cur_item_id == item->id) - cur_y = y; + if (item->desc_id) { + ret = scene_obj_set_pos(scn, item->desc_id, x + 280, y); + if (ret < 0) + return log_msg_ret("des", ret); + } if (item->preview_id) { bool hide; @@ -125,19 +279,12 @@ int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu) return log_msg_ret("hid", ret); } - y += height; + if (!stack || open) + y += height + theme->menuitem_gap_y; } - if (menu->pointer_id && cur_y != -1) { - /* - * put the pointer to the right of and level with the item it - * points to - */ - ret = scene_obj_set_pos(scn, menu->pointer_id, - menu->obj.x + 200, cur_y); - if (ret < 0) - return log_msg_ret("ptr", ret); - } + if (sel_id) + menu_point_to_item(menu, sel_id); return 0; } @@ -158,10 +305,6 @@ int scene_menu(struct scene *scn, const char *name, uint id, *menup = menu; INIT_LIST_HEAD(&menu->item_head); - ret = scene_menu_arrange(scn, menu); - if (ret) - return log_msg_ret("pos", ret); - return menu->obj.id; } @@ -191,6 +334,7 @@ static struct scene_menitem *scene_menu_find_key(struct scene *scn, int scene_menu_send_key(struct scene *scn, struct scene_obj_menu *menu, int key, struct expo_action *event) { + const bool open = menu->obj.flags & SCENEOF_OPEN; struct scene_menitem *item, *cur, *key_item; cur = NULL; @@ -215,7 +359,7 @@ int scene_menu_send_key(struct scene *scn, struct scene_obj_menu *menu, int key, struct scene_menitem, sibling)) { item = list_entry(item->sibling.prev, struct scene_menitem, sibling); - event->type = EXPOACT_POINT; + event->type = EXPOACT_POINT_ITEM; event->select.id = item->id; log_debug("up to item %d\n", event->select.id); } @@ -224,7 +368,7 @@ int scene_menu_send_key(struct scene *scn, struct scene_obj_menu *menu, int key, if (!list_is_last(&item->sibling, &menu->item_head)) { item = list_entry(item->sibling.next, struct scene_menitem, sibling); - event->type = EXPOACT_POINT; + event->type = EXPOACT_POINT_ITEM; event->select.id = item->id; log_debug("down to item %d\n", event->select.id); } @@ -235,8 +379,13 @@ int scene_menu_send_key(struct scene *scn, struct scene_obj_menu *menu, int key, log_debug("select item %d\n", event->select.id); break; case BKEY_QUIT: - event->type = EXPOACT_QUIT; - log_debug("quit\n"); + if (scn->expo->popup && open) { + event->type = EXPOACT_CLOSE; + event->select.id = menu->obj.id; + } else { + event->type = EXPOACT_QUIT; + log_debug("menu quit\n"); + } break; case '0'...'9': key_item = scene_menu_find_key(scn, menu, key); @@ -258,14 +407,13 @@ int scene_menuitem(struct scene *scn, uint menu_id, const char *name, uint id, { struct scene_obj_menu *menu; struct scene_menitem *item; - int ret; menu = scene_obj_find(scn, menu_id, SCENEOBJT_MENU); if (!menu) return log_msg_ret("find", -ENOENT); /* Check that the text ID is valid */ - if (!scene_obj_find(scn, desc_id, SCENEOBJT_TEXT)) + if (!scene_obj_find(scn, label_id, SCENEOBJT_TEXT)) return log_msg_ret("txt", -EINVAL); item = calloc(1, sizeof(struct scene_obj_menu)); @@ -285,10 +433,6 @@ int scene_menuitem(struct scene *scn, uint menu_id, const char *name, uint id, item->flags = flags; list_add_tail(&item->sibling, &menu->item_head); - ret = scene_menu_arrange(scn, menu); - if (ret) - return log_msg_ret("pos", ret); - if (itemp) *itemp = item; @@ -388,3 +532,49 @@ int scene_menu_display(struct scene_obj_menu *menu) return -ENOTSUPP; } + +void scene_menu_render(struct scene_obj_menu *menu) +{ + struct expo *exp = menu->obj.scene->expo; + const struct expo_theme *theme = &exp->theme; + struct vidconsole_bbox bbox, label_bbox; + struct udevice *dev = exp->display; + struct video_priv *vid_priv; + struct udevice *cons = exp->cons; + struct vidconsole_colour old; + enum colour_idx fore, back; + + if (CONFIG_IS_ENABLED(SYS_WHITE_ON_BLACK)) { + fore = VID_BLACK; + back = VID_WHITE; + } else { + fore = VID_LIGHT_GRAY; + back = VID_BLACK; + } + + scene_menu_calc_bbox(menu, &bbox, &label_bbox); + vidconsole_push_colour(cons, fore, back, &old); + vid_priv = dev_get_uclass_priv(dev); + video_fill_part(dev, label_bbox.x0 - theme->menu_inset, + label_bbox.y0 - theme->menu_inset, + label_bbox.x1, label_bbox.y1 + theme->menu_inset, + vid_priv->colour_fg); + vidconsole_pop_colour(cons, &old); +} + +int scene_menu_render_deps(struct scene *scn, struct scene_obj_menu *menu) +{ + struct scene_menitem *item; + + scene_render_deps(scn, menu->title_id); + scene_render_deps(scn, menu->cur_item_id); + scene_render_deps(scn, menu->pointer_id); + + list_for_each_entry(item, &menu->item_head, sibling) { + scene_render_deps(scn, item->key_id); + scene_render_deps(scn, item->label_id); + scene_render_deps(scn, item->desc_id); + } + + return 0; +} diff --git a/cmd/Kconfig b/cmd/Kconfig index c1941849f98..fd76972eaa3 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -428,6 +428,15 @@ config CMD_ABOOTIMG See doc/android/boot-image.rst for details. +config CMD_CEDIT + bool "cedit - Configuration editor" + depends on CEDIT + default y + help + Provides a command to allow editing of board configuration and + providing a UI for the user to adjust settings. Subcommands allow + loading and saving of configuration as well as showing an editor. + config CMD_ELF bool "bootelf, bootvx" default y @@ -1850,7 +1859,6 @@ config CMD_RARP config CMD_NFS bool "nfs" - default y help Boot image via network using NFS protocol. diff --git a/cmd/Makefile b/cmd/Makefile index 6c37521b4e2..9f8c0b058be 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -43,6 +43,7 @@ obj-$(CONFIG_CMD_BUTTON) += button.o obj-$(CONFIG_CMD_CAT) += cat.o obj-$(CONFIG_CMD_CACHE) += cache.o obj-$(CONFIG_CMD_CBFS) += cbfs.o +obj-$(CONFIG_CMD_CEDIT) += cedit.o obj-$(CONFIG_CMD_CLK) += clk.o obj-$(CONFIG_CMD_CLS) += cls.o obj-$(CONFIG_CMD_CONFIG) += config.o diff --git a/cmd/bootmenu.c b/cmd/bootmenu.c index 6baeedc69f9..987b16889f8 100644 --- a/cmd/bootmenu.c +++ b/cmd/bootmenu.c @@ -351,8 +351,8 @@ static struct bootmenu_data *bootmenu_create(int delay) * UEFI specification requires booting from removal media using * a architecture-specific default image name such as BOOTAA64.EFI. */ - efi_ret = eficonfig_generate_media_device_boot_option(); - if (efi_ret != EFI_SUCCESS && efi_ret != EFI_NOT_FOUND) + efi_ret = efi_bootmgr_update_media_device_boot_option(); + if (efi_ret != EFI_SUCCESS) goto cleanup; ret = prepare_uefi_bootorder_entry(menu, &iter, &i); diff --git a/cmd/cat.c b/cmd/cat.c index 1273a26b145..b059080193d 100644 --- a/cmd/cat.c +++ b/cmd/cat.c @@ -17,8 +17,8 @@ static int do_cat(struct cmd_tbl *cmdtp, int flag, int argc, char *dev; char *file; char *buffer; - phys_addr_t addr; - loff_t file_size; + ulong file_size; + int ret; if (argc < 4) return CMD_RET_USAGE; @@ -27,40 +27,27 @@ static int do_cat(struct cmd_tbl *cmdtp, int flag, int argc, dev = argv[2]; file = argv[3]; + ret = fs_load_alloc(ifname, dev, file, 0, 0, (void **)&buffer, + &file_size); + // check file exists - if (fs_set_blk_dev(ifname, dev, FS_TYPE_ANY)) + switch (ret) { + case 0: + break; + case -ENOMEDIUM: return CMD_RET_FAILURE; - - if (!fs_exists(file)) { + case -ENOENT: log_err("File does not exist: ifname=%s dev=%s file=%s\n", ifname, dev, file); return CMD_RET_FAILURE; - } - - // get file size - if (fs_set_blk_dev(ifname, dev, FS_TYPE_ANY)) + case -E2BIG: + log_err("File is too large: ifname=%s dev=%s file=%s\n", ifname, dev, file); return CMD_RET_FAILURE; - - if (fs_size(file, &file_size)) { - log_err("Cannot read file size: ifname=%s dev=%s file=%s\n", ifname, dev, file); + case -ENOMEM: + log_err("Not enough memory: ifname=%s dev=%s file=%s\n", ifname, dev, file); return CMD_RET_FAILURE; - } - - // allocate memory for file content - buffer = calloc(sizeof(char), file_size + 1); - if (!buffer) { - log_err("Out of memory\n"); - return CMD_RET_FAILURE; - } - - // map pointer to system memory - addr = map_to_sysmem(buffer); - - // read file to memory - if (fs_set_blk_dev(ifname, dev, FS_TYPE_ANY)) - return CMD_RET_FAILURE; - - if (fs_read(file, addr, 0, 0, &file_size)) { - log_err("Cannot read file: ifname=%s dev=%s file=%s\n", ifname, dev, file); + default: + case -EIO: + log_err("File-read failed: ifname=%s dev=%s file=%s\n", ifname, dev, file); return CMD_RET_FAILURE; } diff --git a/cmd/cedit.c b/cmd/cedit.c new file mode 100644 index 00000000000..0cae304c4ad --- /dev/null +++ b/cmd/cedit.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * 'cedit' command + * + * Copyright 2023 Google LLC + * Written by Simon Glass <sjg@chromium.org> + */ + +#include <common.h> +#include <command.h> +#include <expo.h> +#include <fs.h> +#include <dm/ofnode.h> +#include <linux/sizes.h> + +struct expo *cur_exp; + +static int do_cedit_load(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + const char *fname; + struct expo *exp; + oftree tree; + ulong size; + void *buf; + int ret; + + if (argc < 4) + return CMD_RET_USAGE; + fname = argv[3]; + + ret = fs_load_alloc(argv[1], argv[2], argv[3], SZ_1M, 0, &buf, &size); + if (ret) { + printf("File not found\n"); + return CMD_RET_FAILURE; + } + + tree = oftree_from_fdt(buf); + if (!oftree_valid(tree)) { + printf("Cannot create oftree\n"); + return CMD_RET_FAILURE; + } + + ret = expo_build(oftree_root(tree), &exp); + oftree_dispose(tree); + if (ret) { + printf("Failed to build expo: %dE\n", ret); + return CMD_RET_FAILURE; + } + + cur_exp = exp; + + return 0; +} + +static int do_cedit_run(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + ofnode node; + int ret; + + if (!cur_exp) { + printf("No expo loaded\n"); + return CMD_RET_FAILURE; + } + + node = ofnode_path("/cedit-theme"); + if (ofnode_valid(node)) { + ret = expo_apply_theme(cur_exp, node); + if (ret) + return CMD_RET_FAILURE; + } else { + log_warning("No theme found\n"); + } + ret = cedit_run(cur_exp); + if (ret) { + log_err("Failed (err=%dE)\n", ret); + return CMD_RET_FAILURE; + } + + return 0; +} + +#ifdef CONFIG_SYS_LONGHELP +static char cedit_help_text[] = + "load <interface> <dev[:part]> <filename> - load config editor\n" + "cedit run - run config editor"; +#endif /* CONFIG_SYS_LONGHELP */ + +U_BOOT_CMD_WITH_SUBCMDS(cedit, "Configuration editor", cedit_help_text, + U_BOOT_SUBCMD_MKENT(load, 5, 1, do_cedit_load), + U_BOOT_SUBCMD_MKENT(run, 1, 1, do_cedit_run), +); diff --git a/cmd/eficonfig.c b/cmd/eficonfig.c index 720f52b48b8..e6e8a0a488e 100644 --- a/cmd/eficonfig.c +++ b/cmd/eficonfig.c @@ -1135,43 +1135,6 @@ out: } /** - * eficonfig_get_unused_bootoption() - get unused "Boot####" index - * - * @buf: pointer to the buffer to store boot option variable name - * @buf_size: buffer size - * @index: pointer to store the index in the BootOrder variable - * Return: status code - */ -efi_status_t eficonfig_get_unused_bootoption(u16 *buf, efi_uintn_t buf_size, - unsigned int *index) -{ - u32 i; - efi_status_t ret; - efi_uintn_t size; - - if (buf_size < u16_strsize(u"Boot####")) - return EFI_BUFFER_TOO_SMALL; - - for (i = 0; i <= 0xFFFF; i++) { - size = 0; - efi_create_indexed_name(buf, buf_size, "Boot", i); - ret = efi_get_variable_int(buf, &efi_global_variable_guid, - NULL, &size, NULL, NULL); - if (ret == EFI_BUFFER_TOO_SMALL) - continue; - else - break; - } - - if (i > 0xFFFF) - return EFI_OUT_OF_RESOURCES; - - *index = i; - - return EFI_SUCCESS; -} - -/** * eficonfig_set_boot_option() - set boot option * * @varname: pointer to variable name @@ -1209,46 +1172,6 @@ static efi_status_t eficonfig_set_boot_option(u16 *varname, struct efi_device_pa } /** - * eficonfig_append_bootorder() - append new boot option in BootOrder variable - * - * @index: "Boot####" index to append to BootOrder variable - * Return: status code - */ -efi_status_t eficonfig_append_bootorder(u16 index) -{ - u16 *bootorder; - efi_status_t ret; - u16 *new_bootorder = NULL; - efi_uintn_t last, size, new_size; - - /* append new boot option */ - bootorder = efi_get_var(u"BootOrder", &efi_global_variable_guid, &size); - last = size / sizeof(u16); - new_size = size + sizeof(u16); - new_bootorder = calloc(1, new_size); - if (!new_bootorder) { - ret = EFI_OUT_OF_RESOURCES; - goto out; - } - memcpy(new_bootorder, bootorder, size); - new_bootorder[last] = index; - - ret = efi_set_variable_int(u"BootOrder", &efi_global_variable_guid, - EFI_VARIABLE_NON_VOLATILE | - EFI_VARIABLE_BOOTSERVICE_ACCESS | - EFI_VARIABLE_RUNTIME_ACCESS, - new_size, new_bootorder, false); - if (ret != EFI_SUCCESS) - goto out; - -out: - free(bootorder); - free(new_bootorder); - - return ret; -} - -/** * create_boot_option_entry() - create boot option entry * * @efi_menu: pointer to the efimenu structure @@ -1619,7 +1542,7 @@ static efi_status_t eficonfig_process_add_boot_option(void *data) if (!bo) return EFI_OUT_OF_RESOURCES; - ret = eficonfig_get_unused_bootoption(varname, sizeof(varname), &bo->boot_index); + ret = efi_bootmgr_get_unused_bootoption(varname, sizeof(varname), &bo->boot_index); if (ret != EFI_SUCCESS) return ret; @@ -1627,7 +1550,7 @@ static efi_status_t eficonfig_process_add_boot_option(void *data) if (ret != EFI_SUCCESS) goto out; - ret = eficonfig_append_bootorder((u16)bo->boot_index); + ret = efi_bootmgr_append_bootorder((u16)bo->boot_index); if (ret != EFI_SUCCESS) goto out; @@ -1657,31 +1580,6 @@ static efi_status_t eficonfig_process_boot_selected(void *data) } /** - * search_bootorder() - search the boot option index in BootOrder - * - * @bootorder: pointer to the BootOrder variable - * @num: number of BootOrder entry - * @target: target boot option index to search - * @index: pointer to store the index of BootOrder variable - * Return: true if exists, false otherwise - */ -static bool search_bootorder(u16 *bootorder, efi_uintn_t num, u32 target, u32 *index) -{ - u32 i; - - for (i = 0; i < num; i++) { - if (target == bootorder[i]) { - if (index) - *index = i; - - return true; - } - } - - return false; -} - -/** * eficonfig_add_boot_selection_entry() - add boot option menu entry * * @efi_menu: pointer to store the efimenu structure @@ -1805,7 +1703,7 @@ static efi_status_t eficonfig_show_boot_selection(unsigned int *selected) if (efi_varname_is_load_option(var_name16, &index)) { /* If the index is included in the BootOrder, skip it */ - if (search_bootorder(bootorder, num, index, NULL)) + if (efi_search_bootorder(bootorder, num, index, NULL)) continue; ret = eficonfig_add_boot_selection_entry(efi_menu, index, selected); @@ -2202,7 +2100,7 @@ static efi_status_t eficonfig_create_change_boot_order_entry(struct efimenu *efi if (efi_varname_is_load_option(var_name16, &index)) { /* If the index is included in the BootOrder, skip it */ - if (search_bootorder(bootorder, num, index, NULL)) + if (efi_search_bootorder(bootorder, num, index, NULL)) continue; ret = eficonfig_add_change_boot_order_entry(efi_menu, index, false); @@ -2305,50 +2203,6 @@ out: } /** - * delete_boot_option() - delete selected boot option - * - * @boot_index: boot option index to delete - * Return: status code - */ -static efi_status_t delete_boot_option(u16 boot_index) -{ - u16 *bootorder; - u16 varname[9]; - efi_status_t ret; - unsigned int index; - efi_uintn_t num, size; - - efi_create_indexed_name(varname, sizeof(varname), - "Boot", boot_index); - ret = efi_set_variable_int(varname, &efi_global_variable_guid, - 0, 0, NULL, false); - if (ret != EFI_SUCCESS) { - log_err("delete boot option(%ls) failed\n", varname); - return ret; - } - - /* update BootOrder if necessary */ - bootorder = efi_get_var(u"BootOrder", &efi_global_variable_guid, &size); - if (!bootorder) - return EFI_SUCCESS; - - num = size / sizeof(u16); - if (!search_bootorder(bootorder, num, boot_index, &index)) - return EFI_SUCCESS; - - memmove(&bootorder[index], &bootorder[index + 1], - (num - index - 1) * sizeof(u16)); - size -= sizeof(u16); - ret = efi_set_variable_int(u"BootOrder", &efi_global_variable_guid, - EFI_VARIABLE_NON_VOLATILE | - EFI_VARIABLE_BOOTSERVICE_ACCESS | - EFI_VARIABLE_RUNTIME_ACCESS, - size, bootorder, false); - - return ret; -} - -/** * eficonfig_process_delete_boot_option() - handler to delete boot option * * @data: pointer to the data for each entry @@ -2362,7 +2216,7 @@ static efi_status_t eficonfig_process_delete_boot_option(void *data) while (1) { ret = eficonfig_show_boot_selection(&selected); if (ret == EFI_SUCCESS) - ret = delete_boot_option(selected); + ret = efi_bootmgr_delete_boot_option(selected); if (ret != EFI_SUCCESS) break; @@ -2375,256 +2229,6 @@ static efi_status_t eficonfig_process_delete_boot_option(void *data) } /** - * eficonfig_enumerate_boot_option() - enumerate the possible bootable media - * - * @opt: pointer to the media boot option structure - * @volume_handles: pointer to the efi handles - * @count: number of efi handle - * Return: status code - */ -efi_status_t eficonfig_enumerate_boot_option(struct eficonfig_media_boot_option *opt, - efi_handle_t *volume_handles, efi_status_t count) -{ - u32 i; - struct efi_handler *handler; - efi_status_t ret = EFI_SUCCESS; - - for (i = 0; i < count; i++) { - u16 *p; - u16 dev_name[BOOTMENU_DEVICE_NAME_MAX]; - char *optional_data; - struct efi_load_option lo; - char buf[BOOTMENU_DEVICE_NAME_MAX]; - struct efi_device_path *device_path; - - ret = efi_search_protocol(volume_handles[i], &efi_guid_device_path, &handler); - if (ret != EFI_SUCCESS) - continue; - ret = efi_protocol_open(handler, (void **)&device_path, - efi_root, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); - if (ret != EFI_SUCCESS) - continue; - - ret = efi_disk_get_device_name(volume_handles[i], buf, BOOTMENU_DEVICE_NAME_MAX); - if (ret != EFI_SUCCESS) - continue; - - p = dev_name; - utf8_utf16_strncpy(&p, buf, strlen(buf)); - - lo.label = dev_name; - lo.attributes = LOAD_OPTION_ACTIVE; - lo.file_path = device_path; - lo.file_path_length = efi_dp_size(device_path) + sizeof(END); - /* - * Set the dedicated guid to optional_data, it is used to identify - * the boot option that automatically generated by the bootmenu. - * efi_serialize_load_option() expects optional_data is null-terminated - * utf8 string, so set the "1234567" string to allocate enough space - * to store guid, instead of realloc the load_option. - */ - lo.optional_data = "1234567"; - opt[i].size = efi_serialize_load_option(&lo, (u8 **)&opt[i].lo); - if (!opt[i].size) { - ret = EFI_OUT_OF_RESOURCES; - goto out; - } - /* set the guid */ - optional_data = (char *)opt[i].lo + (opt[i].size - u16_strsize(u"1234567")); - memcpy(optional_data, &efi_guid_bootmenu_auto_generated, sizeof(efi_guid_t)); - } - -out: - return ret; -} - -/** - * eficonfig_delete_invalid_boot_option() - delete non-existing boot option - * - * @opt: pointer to the media boot option structure - * @count: number of media boot option structure - * Return: status code - */ -efi_status_t eficonfig_delete_invalid_boot_option(struct eficonfig_media_boot_option *opt, - efi_status_t count) -{ - efi_uintn_t size; - void *load_option; - u32 i, list_size = 0; - struct efi_load_option lo; - u16 *var_name16 = NULL; - u16 varname[] = u"Boot####"; - efi_status_t ret = EFI_SUCCESS; - u16 *delete_index_list = NULL, *p; - efi_uintn_t buf_size; - - buf_size = 128; - var_name16 = malloc(buf_size); - if (!var_name16) - return EFI_OUT_OF_RESOURCES; - - var_name16[0] = 0; - for (;;) { - int index; - efi_guid_t guid; - efi_uintn_t tmp; - - ret = efi_next_variable_name(&buf_size, &var_name16, &guid); - if (ret == EFI_NOT_FOUND) { - /* - * EFI_NOT_FOUND indicates we retrieved all EFI variables. - * This should be treated as success. - */ - ret = EFI_SUCCESS; - break; - } - if (ret != EFI_SUCCESS) - goto out; - - if (!efi_varname_is_load_option(var_name16, &index)) - continue; - - efi_create_indexed_name(varname, sizeof(varname), "Boot", index); - load_option = efi_get_var(varname, &efi_global_variable_guid, &size); - if (!load_option) - continue; - - tmp = size; - ret = efi_deserialize_load_option(&lo, load_option, &size); - if (ret != EFI_SUCCESS) - goto next; - - if (size >= sizeof(efi_guid_bootmenu_auto_generated) && - !guidcmp(lo.optional_data, &efi_guid_bootmenu_auto_generated)) { - for (i = 0; i < count; i++) { - if (opt[i].size == tmp && - memcmp(opt[i].lo, load_option, tmp) == 0) { - opt[i].exist = true; - break; - } - } - - /* - * The entire list of variables must be retrieved by - * efi_get_next_variable_name_int() before deleting the invalid - * boot option, just save the index here. - */ - if (i == count) { - p = realloc(delete_index_list, sizeof(u32) * - (list_size + 1)); - if (!p) { - ret = EFI_OUT_OF_RESOURCES; - goto out; - } - delete_index_list = p; - delete_index_list[list_size++] = index; - } - } -next: - free(load_option); - } - - /* delete all invalid boot options */ - for (i = 0; i < list_size; i++) { - ret = delete_boot_option(delete_index_list[i]); - if (ret != EFI_SUCCESS) - goto out; - } - -out: - free(var_name16); - free(delete_index_list); - - return ret; -} - -/** - * eficonfig_generate_media_device_boot_option() - generate the media device boot option - * - * This function enumerates all devices supporting EFI_SIMPLE_FILE_SYSTEM_PROTOCOL - * and generate the bootmenu entries. - * This function also provide the BOOT#### variable maintenance for - * the media device entries. - * - Automatically create the BOOT#### variable for the newly detected device, - * this BOOT#### variable is distinguished by the special GUID - * stored in the EFI_LOAD_OPTION.optional_data - * - If the device is not attached to the system, the associated BOOT#### variable - * is automatically deleted. - * - * Return: status code - */ -efi_status_t eficonfig_generate_media_device_boot_option(void) -{ - u32 i; - efi_status_t ret; - efi_uintn_t count; - efi_handle_t *volume_handles = NULL; - struct eficonfig_media_boot_option *opt = NULL; - - ret = efi_locate_handle_buffer_int(BY_PROTOCOL, &efi_simple_file_system_protocol_guid, - NULL, &count, (efi_handle_t **)&volume_handles); - if (ret != EFI_SUCCESS) - return ret; - - opt = calloc(count, sizeof(struct eficonfig_media_boot_option)); - if (!opt) - goto out; - - /* enumerate all devices supporting EFI_SIMPLE_FILE_SYSTEM_PROTOCOL */ - ret = eficonfig_enumerate_boot_option(opt, volume_handles, count); - if (ret != EFI_SUCCESS) - goto out; - - /* - * System hardware configuration may vary depending on the user setup. - * The boot option is automatically added by the bootmenu. - * If the device is not attached to the system, the boot option needs - * to be deleted. - */ - ret = eficonfig_delete_invalid_boot_option(opt, count); - if (ret != EFI_SUCCESS) - goto out; - - /* add non-existent boot option */ - for (i = 0; i < count; i++) { - u32 boot_index; - u16 var_name[9]; - - if (!opt[i].exist) { - ret = eficonfig_get_unused_bootoption(var_name, sizeof(var_name), - &boot_index); - if (ret != EFI_SUCCESS) - goto out; - - ret = efi_set_variable_int(var_name, &efi_global_variable_guid, - EFI_VARIABLE_NON_VOLATILE | - EFI_VARIABLE_BOOTSERVICE_ACCESS | - EFI_VARIABLE_RUNTIME_ACCESS, - opt[i].size, opt[i].lo, false); - if (ret != EFI_SUCCESS) - goto out; - - ret = eficonfig_append_bootorder(boot_index); - if (ret != EFI_SUCCESS) { - efi_set_variable_int(var_name, &efi_global_variable_guid, - 0, 0, NULL, false); - goto out; - } - } - } - -out: - if (opt) { - for (i = 0; i < count; i++) - free(opt[i].lo); - } - free(opt); - efi_free_pool(volume_handles); - - return ret; -} - -/** * eficonfig_init() - do required initialization for eficonfig command * * Return: status code @@ -2709,8 +2313,8 @@ static int do_eficonfig(struct cmd_tbl *cmdtp, int flag, int argc, char *const a if (ret != EFI_SUCCESS) return CMD_RET_FAILURE; - ret = eficonfig_generate_media_device_boot_option(); - if (ret != EFI_SUCCESS && ret != EFI_NOT_FOUND) + ret = efi_bootmgr_update_media_device_boot_option(); + if (ret != EFI_SUCCESS) return ret; while (1) { diff --git a/common/board_f.c b/common/board_f.c index 1688e27071f..334d04af197 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -633,8 +633,6 @@ static int init_post(void) static int reloc_fdt(void) { if (!IS_ENABLED(CONFIG_OF_EMBED)) { - if (gd->flags & GD_FLG_SKIP_RELOC) - return 0; if (gd->new_fdt) { memcpy(gd->new_fdt, gd->fdt_blob, fdt_totalsize(gd->fdt_blob)); diff --git a/common/hash.c b/common/hash.c index 9a52d6073ce..cbffdfd6db3 100644 --- a/common/hash.c +++ b/common/hash.c @@ -586,6 +586,8 @@ int hash_command(const char *algo_name, int flags, struct cmd_tbl *cmdtp, output = memalign(ARCH_DMA_MINALIGN, sizeof(uint32_t) * HASH_MAX_DIGEST_SIZE); + if (!output) + return CMD_RET_FAILURE; buf = map_sysmem(addr, len); algo->hash_func_ws(buf, len, output, algo->chunk_size); @@ -602,6 +604,7 @@ int hash_command(const char *algo_name, int flags, struct cmd_tbl *cmdtp, flags & HASH_FLAG_ENV)) { printf("ERROR: %s does not contain a valid " "%s sum\n", *argv, algo->name); + free(output); return 1; } if (memcmp(output, vsum, algo->digest_size) != 0) { @@ -612,6 +615,7 @@ int hash_command(const char *algo_name, int flags, struct cmd_tbl *cmdtp, for (i = 0; i < algo->digest_size; i++) printf("%02x", vsum[i]); puts(" ** ERROR **\n"); + free(output); return 1; } } else { @@ -622,10 +626,10 @@ int hash_command(const char *algo_name, int flags, struct cmd_tbl *cmdtp, store_result(algo, output, *argv, flags & HASH_FLAG_ENV); } - unmap_sysmem(output); - } + free(output); + /* Horrible code size hack for boards that just want crc32 */ } else { ulong crc; diff --git a/common/log.c b/common/log.c index 7cfc49bc28a..6f02a25c593 100644 --- a/common/log.c +++ b/common/log.c @@ -31,6 +31,7 @@ static const char *const log_cat_name[] = { "boot", "event", "fs", + "expo", }; _Static_assert(ARRAY_SIZE(log_cat_name) == LOGC_COUNT - LOGC_NONE, diff --git a/configs/10m50_defconfig b/configs/10m50_defconfig index 54a67c5aa98..b76f31b009f 100644 --- a/configs/10m50_defconfig +++ b/configs/10m50_defconfig @@ -26,7 +26,6 @@ CONFIG_CMD_GPIO=y # CONFIG_CMD_ITEST is not set CONFIG_CMD_DHCP=y CONFIG_BOOTP_BOOTFILESIZE=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_MII=y CONFIG_CMD_PING=y CONFIG_ENV_OVERWRITE=y diff --git a/configs/3c120_defconfig b/configs/3c120_defconfig index fc73c0613d0..13da353d7eb 100644 --- a/configs/3c120_defconfig +++ b/configs/3c120_defconfig @@ -26,7 +26,6 @@ CONFIG_CMD_GPIO=y # CONFIG_CMD_ITEST is not set CONFIG_CMD_DHCP=y CONFIG_BOOTP_BOOTFILESIZE=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_MII=y CONFIG_CMD_PING=y CONFIG_ENV_OVERWRITE=y diff --git a/configs/CMPC885_defconfig b/configs/CMPC885_defconfig index f5bc6d6c004..54873daa156 100644 --- a/configs/CMPC885_defconfig +++ b/configs/CMPC885_defconfig @@ -51,7 +51,6 @@ CONFIG_CMD_ASKENV=y CONFIG_CMD_MTD=y CONFIG_CMD_NAND=y CONFIG_CMD_DHCP=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_MII=y CONFIG_MII_INIT=y CONFIG_CMD_PING=y diff --git a/configs/CMPCPRO_defconfig b/configs/CMPCPRO_defconfig index 80913e653be..d817274a936 100644 --- a/configs/CMPCPRO_defconfig +++ b/configs/CMPCPRO_defconfig @@ -136,7 +136,6 @@ CONFIG_CMD_MTD=y CONFIG_CMD_NAND=y CONFIG_CMD_DHCP=y CONFIG_BOOTP_BOOTFILESIZE=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_MII=y CONFIG_CMD_PING=y # CONFIG_CMD_SLEEP is not set diff --git a/configs/apalis-tk1_defconfig b/configs/apalis-tk1_defconfig index 36d28a249cd..fda85c2d6ae 100644 --- a/configs/apalis-tk1_defconfig +++ b/configs/apalis-tk1_defconfig @@ -43,7 +43,6 @@ CONFIG_CMD_MMC=y CONFIG_CMD_PCI=y CONFIG_CMD_USB=y CONFIG_CMD_USB_MASS_STORAGE=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_TIME=y CONFIG_CMD_EXT4_WRITE=y # CONFIG_SPL_DOS_PARTITION is not set diff --git a/configs/apalis_imx6_defconfig b/configs/apalis_imx6_defconfig index dcee5173c1b..5f0f78191c4 100644 --- a/configs/apalis_imx6_defconfig +++ b/configs/apalis_imx6_defconfig @@ -62,7 +62,6 @@ CONFIG_CMD_MMC=y CONFIG_CMD_USB=y CONFIG_CMD_USB_SDP=y CONFIG_CMD_USB_MASS_STORAGE=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_BOOTCOUNT=y CONFIG_CMD_CACHE=y CONFIG_CMD_TIME=y diff --git a/configs/apalis_t30_defconfig b/configs/apalis_t30_defconfig index 516552584c7..83aab2450be 100644 --- a/configs/apalis_t30_defconfig +++ b/configs/apalis_t30_defconfig @@ -38,7 +38,6 @@ CONFIG_CMD_MMC=y CONFIG_CMD_PCI=y CONFIG_CMD_USB=y CONFIG_CMD_USB_MASS_STORAGE=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_EXT4_WRITE=y # CONFIG_SPL_DOS_PARTITION is not set # CONFIG_SPL_EFI_PARTITION is not set diff --git a/configs/arbel_evb_defconfig b/configs/arbel_evb_defconfig index 29c4c187b58..c27a7cdd3a2 100644 --- a/configs/arbel_evb_defconfig +++ b/configs/arbel_evb_defconfig @@ -2,7 +2,8 @@ CONFIG_ARM=y CONFIG_ARCH_NPCM=y CONFIG_SYS_MALLOC_LEN=0x240000 CONFIG_SYS_MALLOC_F_LEN=0x1000 -CONFIG_NR_DRAM_BANKS=1 +CONFIG_TEXT_BASE=0x06208000 +CONFIG_NR_DRAM_BANKS=2 CONFIG_ENV_SIZE=0x40000 CONFIG_ENV_OFFSET=0x3C0000 CONFIG_ENV_SECT_SIZE=0x1000 @@ -22,6 +23,8 @@ CONFIG_BOOTCOMMAND="run common_bootargs; run romboot" CONFIG_HUSH_PARSER=y CONFIG_SYS_MAXARGS=32 CONFIG_SYS_BOOTM_LEN=0x1400000 +CONFIG_SYS_LOAD_ADDR=0x06208000 +CONFIG_SYS_INIT_SP_ADDR=0x06208000 CONFIG_CMD_FUSE=y CONFIG_CMD_GPIO=y CONFIG_CMD_I2C=y @@ -86,3 +89,13 @@ CONFIG_USB_STORAGE=y CONFIG_LIB_HW_RAND=y CONFIG_SHA_HW_ACCEL=y # CONFIG_EFI_LOADER is not set +CONFIG_TEE=y +CONFIG_OPTEE=y +CONFIG_TPM=y +CONFIG_TPM_V2=y +CONFIG_TPM2_FTPM_TEE=y +CONFIG_CMD_TPM=y +CONFIG_SUPPORT_EMMC_RPMB=y +CONFIG_CMD_GPT=y +CONFIG_CMD_FS_GENERIC=y +CONFIG_CMD_PART=y diff --git a/configs/bayleybay_defconfig b/configs/bayleybay_defconfig index 4e59d513cdc..a44c9b714be 100644 --- a/configs/bayleybay_defconfig +++ b/configs/bayleybay_defconfig @@ -37,7 +37,6 @@ CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_DHCP=y CONFIG_BOOTP_BOOTFILESIZE=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_PING=y CONFIG_CMD_TIME=y CONFIG_CMD_BOOTSTAGE=y diff --git a/configs/beaver_defconfig b/configs/beaver_defconfig index 3820a333ecb..0d8a74be7aa 100644 --- a/configs/beaver_defconfig +++ b/configs/beaver_defconfig @@ -38,7 +38,6 @@ CONFIG_CMD_SPI=y CONFIG_CMD_USB=y CONFIG_CMD_USB_MASS_STORAGE=y # CONFIG_CMD_SETEXPR is not set -# CONFIG_CMD_NFS is not set CONFIG_CMD_EXT4_WRITE=y # CONFIG_SPL_DOS_PARTITION is not set # CONFIG_SPL_EFI_PARTITION is not set diff --git a/configs/bitmain_antminer_s9_defconfig b/configs/bitmain_antminer_s9_defconfig index c38ba15cd03..3995d41ce1b 100644 --- a/configs/bitmain_antminer_s9_defconfig +++ b/configs/bitmain_antminer_s9_defconfig @@ -55,7 +55,6 @@ CONFIG_CMD_PART=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_DHCP=y CONFIG_BOOTP_MAY_FAIL=y -# CONFIG_CMD_NFS is not set CONFIG_SYS_DISABLE_AUTOLOAD=y CONFIG_CMD_MII=y CONFIG_CMD_PING=y diff --git a/configs/brppt1_mmc_defconfig b/configs/brppt1_mmc_defconfig index 2c9b0662159..653620263cd 100644 --- a/configs/brppt1_mmc_defconfig +++ b/configs/brppt1_mmc_defconfig @@ -64,7 +64,6 @@ CONFIG_CMD_USB=y # CONFIG_CMD_ITEST is not set CONFIG_CMD_DHCP=y CONFIG_BOOTP_MAY_FAIL=y -# CONFIG_CMD_NFS is not set CONFIG_SYS_DISABLE_AUTOLOAD=y CONFIG_CMD_MII=y CONFIG_CMD_PING=y diff --git a/configs/brppt2_defconfig b/configs/brppt2_defconfig index 00ef3d9908e..05ee4c5797e 100644 --- a/configs/brppt2_defconfig +++ b/configs/brppt2_defconfig @@ -56,7 +56,6 @@ CONFIG_CMD_MMC=y CONFIG_CMD_USB=y CONFIG_CMD_DHCP=y CONFIG_BOOTP_MAY_FAIL=y -# CONFIG_CMD_NFS is not set CONFIG_SYS_DISABLE_AUTOLOAD=y CONFIG_CMD_MII=y CONFIG_CMD_CACHE=y diff --git a/configs/brsmarc1_defconfig b/configs/brsmarc1_defconfig index 1e55ed7c60d..94943fccf1a 100644 --- a/configs/brsmarc1_defconfig +++ b/configs/brsmarc1_defconfig @@ -73,7 +73,6 @@ CONFIG_CMD_USB=y # CONFIG_CMD_ITEST is not set CONFIG_CMD_DHCP=y CONFIG_BOOTP_MAY_FAIL=y -# CONFIG_CMD_NFS is not set CONFIG_SYS_DISABLE_AUTOLOAD=y CONFIG_CMD_MII=y CONFIG_CMD_PING=y diff --git a/configs/brxre1_defconfig b/configs/brxre1_defconfig index 1c437e9743c..b50aef0aad9 100644 --- a/configs/brxre1_defconfig +++ b/configs/brxre1_defconfig @@ -63,7 +63,6 @@ CONFIG_CMD_USB=y # CONFIG_CMD_ITEST is not set CONFIG_CMD_DHCP=y CONFIG_BOOTP_MAY_FAIL=y -# CONFIG_CMD_NFS is not set CONFIG_SYS_DISABLE_AUTOLOAD=y CONFIG_CMD_MII=y CONFIG_CMD_PING=y diff --git a/configs/cardhu_defconfig b/configs/cardhu_defconfig index 00fea793f92..4fe4621f037 100644 --- a/configs/cardhu_defconfig +++ b/configs/cardhu_defconfig @@ -35,7 +35,6 @@ CONFIG_CMD_PCI=y CONFIG_CMD_SPI=y CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set -# CONFIG_CMD_NFS is not set CONFIG_CMD_EXT4_WRITE=y # CONFIG_SPL_DOS_PARTITION is not set # CONFIG_SPL_EFI_PARTITION is not set diff --git a/configs/cei-tk1-som_defconfig b/configs/cei-tk1-som_defconfig index c00e6bec5a3..b920ac2ae40 100644 --- a/configs/cei-tk1-som_defconfig +++ b/configs/cei-tk1-som_defconfig @@ -41,7 +41,6 @@ CONFIG_CMD_SPI=y CONFIG_CMD_USB=y CONFIG_CMD_USB_MASS_STORAGE=y # CONFIG_CMD_SETEXPR is not set -# CONFIG_CMD_NFS is not set CONFIG_CMD_EXT4_WRITE=y # CONFIG_SPL_DOS_PARTITION is not set # CONFIG_SPL_EFI_PARTITION is not set diff --git a/configs/cherryhill_defconfig b/configs/cherryhill_defconfig index 4137b1c77e9..00799715e8f 100644 --- a/configs/cherryhill_defconfig +++ b/configs/cherryhill_defconfig @@ -28,7 +28,6 @@ CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_DHCP=y CONFIG_BOOTP_BOOTFILESIZE=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_PING=y CONFIG_CMD_TIME=y CONFIG_CMD_EXT2=y diff --git a/configs/chromebook_link64_defconfig b/configs/chromebook_link64_defconfig index 8c75d654290..558609e13d6 100644 --- a/configs/chromebook_link64_defconfig +++ b/configs/chromebook_link64_defconfig @@ -50,7 +50,6 @@ CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_DHCP=y CONFIG_BOOTP_BOOTFILESIZE=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_PING=y CONFIG_CMD_TIME=y CONFIG_CMD_BOOTSTAGE=y diff --git a/configs/chromebook_link_defconfig b/configs/chromebook_link_defconfig index 3098857d6e1..96c26f1c377 100644 --- a/configs/chromebook_link_defconfig +++ b/configs/chromebook_link_defconfig @@ -37,7 +37,6 @@ CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_DHCP=y CONFIG_BOOTP_BOOTFILESIZE=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_PING=y CONFIG_CMD_TIME=y CONFIG_CMD_SOUND=y diff --git a/configs/chromebook_samus_defconfig b/configs/chromebook_samus_defconfig index 0d20891d2bc..4019c169a4c 100644 --- a/configs/chromebook_samus_defconfig +++ b/configs/chromebook_samus_defconfig @@ -39,7 +39,6 @@ CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_DHCP=y CONFIG_BOOTP_BOOTFILESIZE=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_PING=y CONFIG_CMD_TIME=y CONFIG_CMD_SOUND=y diff --git a/configs/chromebox_panther_defconfig b/configs/chromebox_panther_defconfig index 96c739cbfbc..f050d066be4 100644 --- a/configs/chromebox_panther_defconfig +++ b/configs/chromebox_panther_defconfig @@ -32,7 +32,6 @@ CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_DHCP=y CONFIG_BOOTP_BOOTFILESIZE=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_PING=y CONFIG_CMD_TIME=y CONFIG_CMD_BOOTSTAGE=y diff --git a/configs/cm_t43_defconfig b/configs/cm_t43_defconfig index a307e83d1d4..12d010ab64b 100644 --- a/configs/cm_t43_defconfig +++ b/configs/cm_t43_defconfig @@ -62,7 +62,6 @@ CONFIG_CMD_MMC=y CONFIG_CMD_NAND=y CONFIG_CMD_SPI=y CONFIG_CMD_USB=y -# CONFIG_CMD_NFS is not set CONFIG_SYS_DISABLE_AUTOLOAD=y CONFIG_CMD_EXT4_WRITE=y CONFIG_CMD_MTDPARTS=y diff --git a/configs/colibri_imx6_defconfig b/configs/colibri_imx6_defconfig index 9d2a2018c99..be1037b6cbb 100644 --- a/configs/colibri_imx6_defconfig +++ b/configs/colibri_imx6_defconfig @@ -61,7 +61,6 @@ CONFIG_CMD_MMC=y CONFIG_CMD_USB=y CONFIG_CMD_USB_SDP=y CONFIG_CMD_USB_MASS_STORAGE=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_BOOTCOUNT=y CONFIG_CMD_CACHE=y CONFIG_CMD_TIME=y diff --git a/configs/colibri_t20_defconfig b/configs/colibri_t20_defconfig index cdf9e8b1d01..eb2e202f6f2 100644 --- a/configs/colibri_t20_defconfig +++ b/configs/colibri_t20_defconfig @@ -36,7 +36,6 @@ CONFIG_CMD_I2C=y CONFIG_CMD_MMC=y CONFIG_CMD_USB=y CONFIG_CMD_USB_MASS_STORAGE=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_CACHE=y CONFIG_CMD_PMIC=y CONFIG_CMD_REGULATOR=y diff --git a/configs/colibri_t30_defconfig b/configs/colibri_t30_defconfig index fed867a8eb2..8098ff7abc1 100644 --- a/configs/colibri_t30_defconfig +++ b/configs/colibri_t30_defconfig @@ -36,7 +36,6 @@ CONFIG_CMD_I2C=y CONFIG_CMD_MMC=y CONFIG_CMD_USB=y CONFIG_CMD_USB_MASS_STORAGE=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_EXT4_WRITE=y # CONFIG_SPL_DOS_PARTITION is not set # CONFIG_SPL_EFI_PARTITION is not set diff --git a/configs/colibri_vf_defconfig b/configs/colibri_vf_defconfig index c47bfc801a2..4d4d0e4aaf4 100644 --- a/configs/colibri_vf_defconfig +++ b/configs/colibri_vf_defconfig @@ -51,7 +51,6 @@ CONFIG_CMD_USB=y CONFIG_CMD_USB_MASS_STORAGE=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_DHCP=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_MII=y CONFIG_CMD_PING=y CONFIG_CMD_EXT4=y diff --git a/configs/conga-qeval20-qa3-e3845-internal-uart_defconfig b/configs/conga-qeval20-qa3-e3845-internal-uart_defconfig index 14f00b6212e..656d575998c 100644 --- a/configs/conga-qeval20-qa3-e3845-internal-uart_defconfig +++ b/configs/conga-qeval20-qa3-e3845-internal-uart_defconfig @@ -44,7 +44,6 @@ CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_DHCP=y CONFIG_BOOTP_BOOTFILESIZE=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_PING=y CONFIG_CMD_TIME=y CONFIG_CMD_BOOTSTAGE=y diff --git a/configs/conga-qeval20-qa3-e3845_defconfig b/configs/conga-qeval20-qa3-e3845_defconfig index 613dcd3ca59..54dc59e8a13 100644 --- a/configs/conga-qeval20-qa3-e3845_defconfig +++ b/configs/conga-qeval20-qa3-e3845_defconfig @@ -40,7 +40,6 @@ CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_DHCP=y CONFIG_BOOTP_BOOTFILESIZE=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_PING=y CONFIG_CMD_TIME=y CONFIG_CMD_BOOTSTAGE=y diff --git a/configs/coreboot64_defconfig b/configs/coreboot64_defconfig index 60a1924e9e5..8aadaa68c27 100644 --- a/configs/coreboot64_defconfig +++ b/configs/coreboot64_defconfig @@ -30,7 +30,6 @@ CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_DHCP=y CONFIG_BOOTP_BOOTFILESIZE=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_PING=y CONFIG_CMD_TIME=y CONFIG_CMD_SOUND=y diff --git a/configs/coreboot_defconfig b/configs/coreboot_defconfig index 058caf008f9..0f3512d23c6 100644 --- a/configs/coreboot_defconfig +++ b/configs/coreboot_defconfig @@ -32,7 +32,6 @@ CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_DHCP=y CONFIG_BOOTP_BOOTFILESIZE=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_PING=y CONFIG_CMD_TIME=y CONFIG_CMD_SOUND=y diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig index a8a79fd1056..d3513b94d88 100644 --- a/configs/corstone1000_defconfig +++ b/configs/corstone1000_defconfig @@ -36,7 +36,6 @@ CONFIG_CMD_LOADM=y CONFIG_CMD_MMC=y CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set -# CONFIG_CMD_NFS is not set CONFIG_CMD_CACHE=y CONFIG_CMD_RTC=y CONFIG_CMD_TIME=y diff --git a/configs/cougarcanyon2_defconfig b/configs/cougarcanyon2_defconfig index 47834bb6fef..da5ff5573d0 100644 --- a/configs/cougarcanyon2_defconfig +++ b/configs/cougarcanyon2_defconfig @@ -31,7 +31,6 @@ CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_DHCP=y CONFIG_BOOTP_BOOTFILESIZE=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_PING=y CONFIG_CMD_TIME=y CONFIG_CMD_EXT2=y diff --git a/configs/crownbay_defconfig b/configs/crownbay_defconfig index 69ad017f987..70e1a50a244 100644 --- a/configs/crownbay_defconfig +++ b/configs/crownbay_defconfig @@ -33,7 +33,6 @@ CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_DHCP=y CONFIG_BOOTP_BOOTFILESIZE=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_PING=y CONFIG_CMD_TIME=y CONFIG_CMD_SOUND=y diff --git a/configs/dalmore_defconfig b/configs/dalmore_defconfig index 936787bb39c..92f4436eebd 100644 --- a/configs/dalmore_defconfig +++ b/configs/dalmore_defconfig @@ -36,7 +36,6 @@ CONFIG_CMD_SPI=y CONFIG_CMD_USB=y CONFIG_CMD_USB_MASS_STORAGE=y # CONFIG_CMD_SETEXPR is not set -# CONFIG_CMD_NFS is not set CONFIG_CMD_EXT4_WRITE=y # CONFIG_SPL_DOS_PARTITION is not set # CONFIG_SPL_EFI_PARTITION is not set diff --git a/configs/dfi-bt700-q7x-151_defconfig b/configs/dfi-bt700-q7x-151_defconfig index 14e6e6c2d84..9313e7fbd12 100644 --- a/configs/dfi-bt700-q7x-151_defconfig +++ b/configs/dfi-bt700-q7x-151_defconfig @@ -38,7 +38,6 @@ CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_DHCP=y CONFIG_BOOTP_BOOTFILESIZE=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_PING=y CONFIG_CMD_TIME=y CONFIG_CMD_BOOTSTAGE=y diff --git a/configs/edison_defconfig b/configs/edison_defconfig index 00342aace9a..8692a8a9995 100644 --- a/configs/edison_defconfig +++ b/configs/edison_defconfig @@ -28,7 +28,6 @@ CONFIG_CMD_DFU=y CONFIG_CMD_GPT=y CONFIG_CMD_MMC=y CONFIG_CMD_PART=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_TIMER=y CONFIG_CMD_HASH=y CONFIG_CMD_EXT4=y diff --git a/configs/efi-x86_payload32_defconfig b/configs/efi-x86_payload32_defconfig index a5c629b46f3..4149eea6cf6 100644 --- a/configs/efi-x86_payload32_defconfig +++ b/configs/efi-x86_payload32_defconfig @@ -25,7 +25,6 @@ CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_DHCP=y CONFIG_BOOTP_BOOTFILESIZE=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_PING=y CONFIG_CMD_TIME=y CONFIG_CMD_EXT2=y diff --git a/configs/efi-x86_payload64_defconfig b/configs/efi-x86_payload64_defconfig index 5cde04a5ac9..d41f73cccfc 100644 --- a/configs/efi-x86_payload64_defconfig +++ b/configs/efi-x86_payload64_defconfig @@ -25,7 +25,6 @@ CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_DHCP=y CONFIG_BOOTP_BOOTFILESIZE=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_PING=y CONFIG_CMD_TIME=y CONFIG_CMD_EXT2=y diff --git a/configs/galileo_defconfig b/configs/galileo_defconfig index 0d2ebdab926..c6d989ea6ef 100644 --- a/configs/galileo_defconfig +++ b/configs/galileo_defconfig @@ -29,7 +29,6 @@ CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_DHCP=y CONFIG_BOOTP_BOOTFILESIZE=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_PING=y CONFIG_CMD_TIME=y CONFIG_CMD_EXT2=y diff --git a/configs/gazerbeam_defconfig b/configs/gazerbeam_defconfig index c8c8469d8a6..7901a195aa7 100644 --- a/configs/gazerbeam_defconfig +++ b/configs/gazerbeam_defconfig @@ -123,7 +123,6 @@ CONFIG_SYS_LOADS_BAUD_CHANGE=y CONFIG_CMD_MMC=y CONFIG_CMD_AXI=y # CONFIG_CMD_SETEXPR is not set -# CONFIG_CMD_NFS is not set CONFIG_CMD_MII=y CONFIG_CMD_PING=y CONFIG_CMD_CACHE=y diff --git a/configs/ge_bx50v3_defconfig b/configs/ge_bx50v3_defconfig index f005e91e0bc..2ef560ccaa4 100644 --- a/configs/ge_bx50v3_defconfig +++ b/configs/ge_bx50v3_defconfig @@ -34,7 +34,6 @@ CONFIG_CMD_GPIO=y CONFIG_CMD_I2C=y CONFIG_CMD_MMC=y CONFIG_CMD_PCI=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_BMP=y CONFIG_CMD_BOOTCOUNT=y CONFIG_CMD_CACHE=y diff --git a/configs/harmony_defconfig b/configs/harmony_defconfig index b1d9399b860..8b49505a650 100644 --- a/configs/harmony_defconfig +++ b/configs/harmony_defconfig @@ -31,7 +31,6 @@ CONFIG_CMD_GPIO=y CONFIG_CMD_MMC=y CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set -# CONFIG_CMD_NFS is not set CONFIG_CMD_PMIC=y CONFIG_CMD_REGULATOR=y CONFIG_CMD_EXT4_WRITE=y diff --git a/configs/imx28_xea_defconfig b/configs/imx28_xea_defconfig index 06dd6b1f0ed..96d15e89af8 100644 --- a/configs/imx28_xea_defconfig +++ b/configs/imx28_xea_defconfig @@ -14,6 +14,9 @@ CONFIG_SPL_DM_SPI=y CONFIG_DEFAULT_DEVICE_TREE="imx28-xea" CONFIG_SPL_TEXT_BASE=0x1000 CONFIG_TARGET_XEA=y +CONFIG_SPL_MXS_PMU_MINIMAL_VDD5V_CURRENT=y +CONFIG_SPL_MXS_PMU_DISABLE_BATT_CHARGE=y +# CONFIG_SPL_MXS_PMU_ENABLE_4P2_LINEAR_REGULATOR is not set CONFIG_SPL_MMC=y CONFIG_SPL_SERIAL=y CONFIG_SPL_STACK=0x20000 @@ -26,6 +29,8 @@ CONFIG_SYS_LOAD_ADDR=0x42000000 CONFIG_SPL_PAYLOAD="u-boot.img" CONFIG_FIT=y CONFIG_TIMESTAMP=y +# CONFIG_BOOTMETH_EXTLINUX is not set +# CONFIG_BOOTMETH_VBE is not set CONFIG_OF_BOARD_SETUP=y CONFIG_USE_BOOTARGS=y CONFIG_BOOTARGS="console=ttyAMA0,115200n8" @@ -95,7 +100,7 @@ CONFIG_MMC_MXS=y CONFIG_MTD=y CONFIG_DM_MTD=y CONFIG_DM_SPI_FLASH=y -CONFIG_SF_DEFAULT_BUS=3 +CONFIG_SF_DEFAULT_BUS=2 CONFIG_SPI_FLASH_SFDP_SUPPORT=y CONFIG_SPI_FLASH_ISSI=y CONFIG_SPI_FLASH_SPANSION=y @@ -113,9 +118,9 @@ CONFIG_PINCTRL_MXS=y CONFIG_DM_REGULATOR=y CONFIG_DM_REGULATOR_FIXED=y CONFIG_DM_REGULATOR_GPIO=y -CONFIG_CONS_INDEX=0 +CONFIG_SPECIFY_CONSOLE_INDEX=y +CONFIG_DM_SERIAL=y CONFIG_SPI=y CONFIG_DM_SPI=y CONFIG_MXS_SPI=y -CONFIG_FS_FAT=y # CONFIG_SPL_OF_LIBFDT is not set diff --git a/configs/imx28_xea_sb_defconfig b/configs/imx28_xea_sb_defconfig index bb7bf5d9dab..a43183444d7 100644 --- a/configs/imx28_xea_sb_defconfig +++ b/configs/imx28_xea_sb_defconfig @@ -94,7 +94,9 @@ CONFIG_PINCTRL_MXS=y CONFIG_DM_REGULATOR=y CONFIG_DM_REGULATOR_FIXED=y CONFIG_DM_REGULATOR_GPIO=y +CONFIG_SPECIFY_CONSOLE_INDEX=y CONFIG_CONS_INDEX=0 +CONFIG_DM_SERIAL=y CONFIG_SPI=y CONFIG_DM_SPI=y CONFIG_MXS_SPI=y diff --git a/configs/imx8mm_beacon_defconfig b/configs/imx8mm_beacon_defconfig index bb02b9bfcc9..52edb2ed19d 100644 --- a/configs/imx8mm_beacon_defconfig +++ b/configs/imx8mm_beacon_defconfig @@ -5,6 +5,7 @@ CONFIG_SYS_MALLOC_LEN=0x2000000 CONFIG_SPL_GPIO=y CONFIG_SPL_LIBCOMMON_SUPPORT=y CONFIG_SPL_LIBGENERIC_SUPPORT=y +CONFIG_ENV_SOURCE_FILE="imx8mm_beacon" CONFIG_SF_DEFAULT_SPEED=10000000 CONFIG_ENV_SIZE=0x2000 CONFIG_ENV_OFFSET=0xFFFFDE00 diff --git a/configs/imx8mm_beacon_fspi_defconfig b/configs/imx8mm_beacon_fspi_defconfig new file mode 100644 index 00000000000..805fd3f6715 --- /dev/null +++ b/configs/imx8mm_beacon_fspi_defconfig @@ -0,0 +1,155 @@ +CONFIG_ARM=y +CONFIG_ARCH_IMX8M=y +CONFIG_TEXT_BASE=0x40200000 +CONFIG_SYS_MALLOC_LEN=0x2000000 +CONFIG_SPL_GPIO=y +CONFIG_SPL_LIBCOMMON_SUPPORT=y +CONFIG_SPL_LIBGENERIC_SUPPORT=y +CONFIG_ENV_SIZE=0x2000 +CONFIG_ENV_OFFSET=0xFFFFDE00 +CONFIG_IMX_CONFIG="board/freescale/imx8mm_evk/imximage-8mm-lpddr4-fspi.cfg" +CONFIG_DM_GPIO=y +CONFIG_DEFAULT_DEVICE_TREE="imx8mm-beacon-kit" +CONFIG_SPL_TEXT_BASE=0x7E2000 +CONFIG_TARGET_IMX8MM_BEACON=y +CONFIG_SYS_PROMPT="u-boot=> " +CONFIG_SPL_SERIAL=y +CONFIG_SPL_DRIVERS_MISC=y +CONFIG_SPL=y +CONFIG_SYS_LOAD_ADDR=0x40480000 +CONFIG_LTO=y +CONFIG_SYS_MONITOR_LEN=524288 +CONFIG_FIT=y +CONFIG_FIT_EXTERNAL_OFFSET=0x3000 +CONFIG_SPL_LOAD_FIT=y +# CONFIG_USE_SPL_FIT_GENERATOR is not set +CONFIG_OF_SYSTEM_SETUP=y +CONFIG_USE_BOOTCOMMAND=y +CONFIG_BOOTCOMMAND="mmc dev ${mmcdev}; if mmc rescan; then if run loadbootscript; then run bootscript; else if run loadimage; then run mmcboot; else run netboot; fi; fi; fi;" +CONFIG_DEFAULT_FDT_FILE="imx8mm-beacon-kit.dtb" +CONFIG_SPL_MAX_SIZE=0x25000 +CONFIG_SPL_PAD_TO=0x0 +CONFIG_SPL_HAS_BSS_LINKER_SECTION=y +CONFIG_SPL_BSS_START_ADDR=0x910000 +CONFIG_SPL_BSS_MAX_SIZE=0x2000 +CONFIG_SPL_BOARD_INIT=y +# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set +CONFIG_SPL_STACK=0x920000 +CONFIG_SYS_SPL_MALLOC=y +CONFIG_HAS_CUSTOM_SPL_MALLOC_START=y +CONFIG_CUSTOM_SYS_SPL_MALLOC_ADDR=0x42200000 +CONFIG_SYS_SPL_MALLOC_SIZE=0x80000 +CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y +CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x300 +CONFIG_SPL_CRC32=y +CONFIG_SPL_I2C=y +CONFIG_SPL_NOR_SUPPORT=y +CONFIG_SPL_POWER=y +CONFIG_SPL_USB_HOST=y +CONFIG_SPL_USB_GADGET=y +CONFIG_SPL_USB_SDP_SUPPORT=y +CONFIG_SPL_WATCHDOG=y +CONFIG_HUSH_PARSER=y +CONFIG_SYS_MAXARGS=64 +CONFIG_SYS_CBSIZE=2048 +CONFIG_SYS_PBSIZE=2074 +CONFIG_SYS_BOOTM_LEN=0x800000 +# CONFIG_CMD_EXPORTENV is not set +# CONFIG_CMD_IMPORTENV is not set +# CONFIG_CMD_CRC32 is not set +CONFIG_CMD_CLK=y +CONFIG_CMD_FUSE=y +CONFIG_CMD_GPIO=y +CONFIG_CMD_I2C=y +CONFIG_CMD_MMC=y +CONFIG_CMD_PART=y +CONFIG_CMD_SPI=y +CONFIG_CMD_USB=y +CONFIG_CMD_USB_SDP=y +CONFIG_CMD_USB_MASS_STORAGE=y +CONFIG_CMD_DHCP=y +CONFIG_CMD_MII=y +CONFIG_CMD_PING=y +CONFIG_CMD_CACHE=y +CONFIG_CMD_PMIC=y +CONFIG_CMD_REGULATOR=y +CONFIG_CMD_EXT2=y +CONFIG_CMD_EXT4=y +CONFIG_CMD_EXT4_WRITE=y +CONFIG_CMD_FAT=y +CONFIG_OF_CONTROL=y +CONFIG_SPL_OF_CONTROL=y +CONFIG_ENV_OVERWRITE=y +CONFIG_ENV_IS_IN_MMC=y +CONFIG_SYS_RELOC_GD_ENV_ADDR=y +CONFIG_SYS_MMC_ENV_DEV=2 +CONFIG_SYS_MMC_ENV_PART=2 +CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y +CONFIG_USE_ETHPRIME=y +CONFIG_ETHPRIME="FEC" +CONFIG_NET_RANDOM_ETHADDR=y +CONFIG_SPL_DM=y +CONFIG_SPL_CLK_COMPOSITE_CCF=y +CONFIG_CLK_COMPOSITE_CCF=y +CONFIG_SPL_CLK_IMX8MM=y +CONFIG_CLK_IMX8MM=y +CONFIG_MXC_GPIO=y +CONFIG_DM_PCA953X=y +CONFIG_DM_I2C=y +CONFIG_SUPPORT_EMMC_BOOT=y +CONFIG_MMC_IO_VOLTAGE=y +CONFIG_MMC_UHS_SUPPORT=y +CONFIG_MMC_HS400_ES_SUPPORT=y +CONFIG_MMC_HS400_SUPPORT=y +CONFIG_FSL_USDHC=y +CONFIG_MTD=y +CONFIG_DM_MTD=y +CONFIG_DM_SPI_FLASH=y +CONFIG_SF_DEFAULT_MODE=0 +CONFIG_SF_DEFAULT_SPEED=40000000 +CONFIG_SPI_FLASH_BAR=y +CONFIG_SPI_FLASH_STMICRO=y +CONFIG_SPI_FLASH_MTD=y +CONFIG_PHYLIB=y +CONFIG_PHY_ATHEROS=y +CONFIG_PHY_GIGE=y +CONFIG_FEC_MXC=y +CONFIG_MII=y +CONFIG_SPL_PHY=y +CONFIG_SPL_NOP_PHY=y +CONFIG_PINCTRL=y +CONFIG_SPL_PINCTRL=y +CONFIG_PINCTRL_IMX8M=y +CONFIG_POWER_DOMAIN=y +CONFIG_IMX8M_POWER_DOMAIN=y +CONFIG_DM_PMIC=y +# CONFIG_SPL_PMIC_CHILDREN is not set +CONFIG_DM_PMIC_BD71837=y +CONFIG_SPL_DM_PMIC_BD71837=y +CONFIG_DM_REGULATOR=y +CONFIG_DM_REGULATOR_BD71837=y +CONFIG_DM_REGULATOR_FIXED=y +CONFIG_DM_REGULATOR_GPIO=y +CONFIG_DM_SERIAL=y +CONFIG_MXC_UART=y +CONFIG_SPI=y +CONFIG_DM_SPI=y +CONFIG_NXP_FSPI=y +CONFIG_SYSRESET=y +CONFIG_SPL_SYSRESET=y +CONFIG_SYSRESET_PSCI=y +CONFIG_SYSRESET_WATCHDOG=y +CONFIG_DM_THERMAL=y +CONFIG_USB=y +CONFIG_USB_EHCI_HCD=y +CONFIG_MXC_USB_OTG_HACTIVE=y +CONFIG_USB_STORAGE=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_VENDOR_NUM=0x0525 +CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5 +CONFIG_CI_UDC=y +CONFIG_SDP_LOADADDR=0x40400000 +CONFIG_USB_GADGET_DOWNLOAD=y +CONFIG_IMX_WATCHDOG=y +CONFIG_FSPI_CONF_HEADER=y +CONFIG_FSPI_CONF_FILE="fspi_header.bin" diff --git a/configs/imx8mm_venice_defconfig b/configs/imx8mm_venice_defconfig index 9d0d0ee315e..a485910a529 100644 --- a/configs/imx8mm_venice_defconfig +++ b/configs/imx8mm_venice_defconfig @@ -6,7 +6,7 @@ CONFIG_SPL_GPIO=y CONFIG_SPL_LIBCOMMON_SUPPORT=y CONFIG_SPL_LIBGENERIC_SUPPORT=y CONFIG_ENV_SIZE=0x8000 -CONFIG_ENV_OFFSET=0xff0000 +CONFIG_ENV_OFFSET=0x3f0000 CONFIG_DM_GPIO=y CONFIG_DEFAULT_DEVICE_TREE="imx8mm-venice" CONFIG_SPL_TEXT_BASE=0x7E1000 @@ -19,7 +19,7 @@ CONFIG_SPL_SERIAL=y CONFIG_SPL_DRIVERS_MISC=y CONFIG_SPL_STACK=0x920000 CONFIG_SPL=y -CONFIG_ENV_OFFSET_REDUND=0xff8000 +CONFIG_ENV_OFFSET_REDUND=0x3f8000 CONFIG_SYS_LOAD_ADDR=0x48200000 CONFIG_SYS_MEMTEST_START=0x40000000 CONFIG_SYS_MEMTEST_END=0x80000000 @@ -36,6 +36,7 @@ CONFIG_BOARD_LATE_INIT=y CONFIG_SPL_HAS_BSS_LINKER_SECTION=y CONFIG_SPL_BSS_START_ADDR=0x910000 CONFIG_SPL_BSS_MAX_SIZE=0x2000 +CONFIG_SPL_BOARD_INIT=y # CONFIG_SPL_SHARES_INIT_SP_ADDR is not set CONFIG_SYS_SPL_MALLOC=y CONFIG_HAS_CUSTOM_SPL_MALLOC_START=y @@ -51,6 +52,7 @@ CONFIG_SYS_PBSIZE=2074 CONFIG_SYS_BOOTM_LEN=0x10000000 # CONFIG_CMD_EXPORTENV is not set # CONFIG_CMD_IMPORTENV is not set +CONFIG_CMD_ERASEENV=y CONFIG_CRC32_VERIFY=y CONFIG_CMD_MD5SUM=y CONFIG_MD5SUM_VERIFY=y @@ -89,6 +91,7 @@ CONFIG_CLK_COMPOSITE_CCF=y CONFIG_SPL_CLK_IMX8MM=y CONFIG_CLK_IMX8MM=y CONFIG_GPIO_HOG=y +CONFIG_DM_GPIO_LOOKUP_LABEL=y CONFIG_MXC_GPIO=y CONFIG_DM_I2C=y CONFIG_LED=y diff --git a/configs/imx8mn_beacon_2g_defconfig b/configs/imx8mn_beacon_2g_defconfig index 494085b373c..00e7cd01c27 100644 --- a/configs/imx8mn_beacon_2g_defconfig +++ b/configs/imx8mn_beacon_2g_defconfig @@ -5,6 +5,7 @@ CONFIG_SYS_MALLOC_LEN=0x2000000 CONFIG_SPL_GPIO=y CONFIG_SPL_LIBCOMMON_SUPPORT=y CONFIG_SPL_LIBGENERIC_SUPPORT=y +CONFIG_ENV_SOURCE_FILE="imx8mn_beacon" CONFIG_NR_DRAM_BANKS=1 CONFIG_SF_DEFAULT_SPEED=40000000 CONFIG_ENV_SIZE=0x2000 diff --git a/configs/imx8mn_beacon_defconfig b/configs/imx8mn_beacon_defconfig index 629025a7eb4..d9a413f96d9 100644 --- a/configs/imx8mn_beacon_defconfig +++ b/configs/imx8mn_beacon_defconfig @@ -5,6 +5,7 @@ CONFIG_SYS_MALLOC_LEN=0x2000000 CONFIG_SPL_GPIO=y CONFIG_SPL_LIBCOMMON_SUPPORT=y CONFIG_SPL_LIBGENERIC_SUPPORT=y +CONFIG_ENV_SOURCE_FILE="imx8mn_beacon" CONFIG_NR_DRAM_BANKS=1 CONFIG_SF_DEFAULT_SPEED=40000000 CONFIG_ENV_SIZE=0x2000 diff --git a/configs/imx8mn_beacon_fspi_defconfig b/configs/imx8mn_beacon_fspi_defconfig index dade877a14e..6c626aee6a9 100644 --- a/configs/imx8mn_beacon_fspi_defconfig +++ b/configs/imx8mn_beacon_fspi_defconfig @@ -5,6 +5,7 @@ CONFIG_SYS_MALLOC_LEN=0x2000000 CONFIG_SPL_GPIO=y CONFIG_SPL_LIBCOMMON_SUPPORT=y CONFIG_SPL_LIBGENERIC_SUPPORT=y +CONFIG_ENV_SOURCE_FILE="imx8mn_beacon" CONFIG_NR_DRAM_BANKS=1 CONFIG_SF_DEFAULT_SPEED=40000000 CONFIG_ENV_SIZE=0x2000 diff --git a/configs/imx8mn_var_som_defconfig b/configs/imx8mn_var_som_defconfig index 350c0225a69..b346b14ebdd 100644 --- a/configs/imx8mn_var_som_defconfig +++ b/configs/imx8mn_var_som_defconfig @@ -23,12 +23,15 @@ CONFIG_SPL_SYS_MALLOC_F_LEN=0x2000 CONFIG_SPL=y CONFIG_SPL_IMX_ROMAPI_LOADADDR=0x48000000 CONFIG_SYS_LOAD_ADDR=0x40480000 +CONFIG_OF_BOARD_FIXUP=y CONFIG_FIT=y CONFIG_FIT_EXTERNAL_OFFSET=0x3000 CONFIG_SPL_LOAD_FIT=y +CONFIG_OF_BOARD_SETUP=y CONFIG_OF_SYSTEM_SETUP=y CONFIG_DISTRO_DEFAULTS=y CONFIG_DEFAULT_FDT_FILE="freescale/imx8mn-var-som-symphony.dtb" +CONFIG_BOARD_TYPES=y CONFIG_ARCH_MISC_INIT=y CONFIG_SPL_MAX_SIZE=0x25000 CONFIG_SPL_HAS_BSS_LINKER_SECTION=y @@ -76,6 +79,7 @@ CONFIG_FASTBOOT_FLASH=y CONFIG_FASTBOOT_UUU_SUPPORT=y CONFIG_FASTBOOT_FLASH_MMC_DEV=2 CONFIG_MXC_GPIO=y +CONFIG_DM_PCA953X=y CONFIG_DM_I2C=y CONFIG_SUPPORT_EMMC_BOOT=y CONFIG_MMC_IO_VOLTAGE=y diff --git a/configs/imx8mn_venice_defconfig b/configs/imx8mn_venice_defconfig index 3974a384d1e..39f930ae2ca 100644 --- a/configs/imx8mn_venice_defconfig +++ b/configs/imx8mn_venice_defconfig @@ -6,7 +6,7 @@ CONFIG_SPL_GPIO=y CONFIG_SPL_LIBCOMMON_SUPPORT=y CONFIG_SPL_LIBGENERIC_SUPPORT=y CONFIG_ENV_SIZE=0x8000 -CONFIG_ENV_OFFSET=0xff0000 +CONFIG_ENV_OFFSET=0x3f0000 CONFIG_DM_GPIO=y CONFIG_DEFAULT_DEVICE_TREE="imx8mn-venice" CONFIG_SPL_TEXT_BASE=0x912000 @@ -19,7 +19,7 @@ CONFIG_SPL_SERIAL=y CONFIG_SPL_DRIVERS_MISC=y CONFIG_SPL_STACK=0x980000 CONFIG_SPL=y -CONFIG_ENV_OFFSET_REDUND=0xff8000 +CONFIG_ENV_OFFSET_REDUND=0x3f8000 CONFIG_SPL_IMX_ROMAPI_LOADADDR=0x48000000 CONFIG_SYS_LOAD_ADDR=0x48200000 CONFIG_SYS_MEMTEST_START=0x40000000 @@ -38,6 +38,7 @@ CONFIG_SPL_MAX_SIZE=0x25000 CONFIG_SPL_HAS_BSS_LINKER_SECTION=y CONFIG_SPL_BSS_START_ADDR=0x950000 CONFIG_SPL_BSS_MAX_SIZE=0x2000 +CONFIG_SPL_BOARD_INIT=y CONFIG_SPL_BOOTROM_SUPPORT=y # CONFIG_SPL_SHARES_INIT_SP_ADDR is not set CONFIG_SYS_SPL_MALLOC=y @@ -54,6 +55,7 @@ CONFIG_SYS_PBSIZE=2074 CONFIG_SYS_BOOTM_LEN=0x10000000 # CONFIG_CMD_EXPORTENV is not set # CONFIG_CMD_IMPORTENV is not set +CONFIG_CMD_ERASEENV=y CONFIG_CRC32_VERIFY=y CONFIG_CMD_MD5SUM=y CONFIG_MD5SUM_VERIFY=y @@ -90,6 +92,7 @@ CONFIG_SPL_DM=y CONFIG_SPL_CLK_IMX8MN=y CONFIG_CLK_IMX8MN=y CONFIG_GPIO_HOG=y +CONFIG_DM_GPIO_LOOKUP_LABEL=y CONFIG_MXC_GPIO=y CONFIG_DM_I2C=y CONFIG_LED=y diff --git a/configs/imx8mp_beacon_defconfig b/configs/imx8mp_beacon_defconfig index 99c4043ace8..77a10b901de 100644 --- a/configs/imx8mp_beacon_defconfig +++ b/configs/imx8mp_beacon_defconfig @@ -18,6 +18,7 @@ CONFIG_SYS_HAS_ARMV8_SECURE_BASE=y CONFIG_TARGET_IMX8MP_BEACON=y CONFIG_SYS_PROMPT="u-boot=> " CONFIG_SYS_MONITOR_LEN=524288 +CONFIG_LTO=y CONFIG_SPL_MMC=y CONFIG_SPL_SERIAL=y CONFIG_SPL_DRIVERS_MISC=y diff --git a/configs/imx8mp_venice_defconfig b/configs/imx8mp_venice_defconfig index a6f6ec67c52..294206ba8b2 100644 --- a/configs/imx8mp_venice_defconfig +++ b/configs/imx8mp_venice_defconfig @@ -6,7 +6,7 @@ CONFIG_SPL_GPIO=y CONFIG_SPL_LIBCOMMON_SUPPORT=y CONFIG_SPL_LIBGENERIC_SUPPORT=y CONFIG_ENV_SIZE=0x8000 -CONFIG_ENV_OFFSET=0xff0000 +CONFIG_ENV_OFFSET=0x3f0000 CONFIG_DM_GPIO=y CONFIG_DEFAULT_DEVICE_TREE="imx8mp-venice" CONFIG_SPL_TEXT_BASE=0x920000 @@ -19,7 +19,7 @@ CONFIG_SPL_SERIAL=y CONFIG_SPL_DRIVERS_MISC=y CONFIG_SPL_STACK=0x960000 CONFIG_SPL=y -CONFIG_ENV_OFFSET_REDUND=0xff8000 +CONFIG_ENV_OFFSET_REDUND=0x3f8000 CONFIG_SPL_IMX_ROMAPI_LOADADDR=0x48000000 CONFIG_SYS_LOAD_ADDR=0x40480000 CONFIG_SYS_MEMTEST_START=0x40000000 @@ -38,6 +38,7 @@ CONFIG_SPL_MAX_SIZE=0x26000 CONFIG_SPL_HAS_BSS_LINKER_SECTION=y CONFIG_SPL_BSS_START_ADDR=0x98fc00 CONFIG_SPL_BSS_MAX_SIZE=0x400 +CONFIG_SPL_BOARD_INIT=y CONFIG_SPL_BOOTROM_SUPPORT=y # CONFIG_SPL_SHARES_INIT_SP_ADDR is not set CONFIG_SYS_SPL_MALLOC=y @@ -54,6 +55,7 @@ CONFIG_SYS_PBSIZE=2074 CONFIG_SYS_BOOTM_LEN=0x10000000 # CONFIG_CMD_EXPORTENV is not set # CONFIG_CMD_IMPORTENV is not set +CONFIG_CMD_ERASEENV=y CONFIG_CRC32_VERIFY=y CONFIG_CMD_MD5SUM=y CONFIG_MD5SUM_VERIFY=y @@ -75,7 +77,7 @@ CONFIG_CMD_EXT4_WRITE=y # CONFIG_SPL_EFI_PARTITION is not set CONFIG_OF_CONTROL=y CONFIG_SPL_OF_CONTROL=y -CONFIG_OF_LIST="imx8mp-venice imx8mp-venice-gw74xx" +CONFIG_OF_LIST="imx8mp-venice imx8mp-venice-gw74xx imx8mp-venice-gw7905-2x" CONFIG_ENV_IS_IN_MMC=y CONFIG_SYS_REDUNDAND_ENVIRONMENT=y CONFIG_SYS_MMC_ENV_DEV=2 @@ -87,6 +89,7 @@ CONFIG_SPL_DM=y CONFIG_CLK_COMPOSITE_CCF=y CONFIG_CLK_IMX8MP=y CONFIG_GPIO_HOG=y +CONFIG_DM_GPIO_LOOKUP_LABEL=y CONFIG_MXC_GPIO=y CONFIG_DM_I2C=y CONFIG_LED=y diff --git a/configs/imx93_11x11_evk_defconfig b/configs/imx93_11x11_evk_defconfig index 0de563f790b..65f473885c6 100644 --- a/configs/imx93_11x11_evk_defconfig +++ b/configs/imx93_11x11_evk_defconfig @@ -81,6 +81,7 @@ CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_DM=y CONFIG_REGMAP=y CONFIG_SYSCON=y +CONFIG_ADC_IMX93=y CONFIG_CPU=y CONFIG_CPU_IMX=y CONFIG_IMX_RGPIO2P=y diff --git a/configs/jetson-tk1_defconfig b/configs/jetson-tk1_defconfig index b2a39e0c844..d8086281582 100644 --- a/configs/jetson-tk1_defconfig +++ b/configs/jetson-tk1_defconfig @@ -40,7 +40,6 @@ CONFIG_CMD_SPI=y CONFIG_CMD_USB=y CONFIG_CMD_USB_MASS_STORAGE=y # CONFIG_CMD_SETEXPR is not set -# CONFIG_CMD_NFS is not set CONFIG_CMD_EXT4_WRITE=y # CONFIG_SPL_DOS_PARTITION is not set # CONFIG_SPL_EFI_PARTITION is not set diff --git a/configs/malta64_defconfig b/configs/malta64_defconfig index 03de1616840..a69e1934fe8 100644 --- a/configs/malta64_defconfig +++ b/configs/malta64_defconfig @@ -26,7 +26,6 @@ CONFIG_CMD_IDE=y CONFIG_CMD_PCI=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_DHCP=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_PING=y CONFIG_CMD_DATE=y # CONFIG_ISO_PARTITION is not set diff --git a/configs/malta64el_defconfig b/configs/malta64el_defconfig index 3ea9fa9857e..21a291d341c 100644 --- a/configs/malta64el_defconfig +++ b/configs/malta64el_defconfig @@ -28,7 +28,6 @@ CONFIG_CMD_IDE=y CONFIG_CMD_PCI=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_DHCP=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_PING=y CONFIG_CMD_DATE=y # CONFIG_ISO_PARTITION is not set diff --git a/configs/malta_defconfig b/configs/malta_defconfig index 317b422a6b6..8c76ebbb155 100644 --- a/configs/malta_defconfig +++ b/configs/malta_defconfig @@ -25,7 +25,6 @@ CONFIG_CMD_IDE=y CONFIG_CMD_PCI=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_DHCP=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_PING=y CONFIG_CMD_DATE=y # CONFIG_ISO_PARTITION is not set diff --git a/configs/maltael_defconfig b/configs/maltael_defconfig index 3e4d2beda2f..4abd3b15580 100644 --- a/configs/maltael_defconfig +++ b/configs/maltael_defconfig @@ -27,7 +27,6 @@ CONFIG_CMD_IDE=y CONFIG_CMD_PCI=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_DHCP=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_PING=y CONFIG_CMD_DATE=y # CONFIG_ISO_PARTITION is not set diff --git a/configs/medcom-wide_defconfig b/configs/medcom-wide_defconfig index 47fcf1574e4..e99bb8f5b52 100644 --- a/configs/medcom-wide_defconfig +++ b/configs/medcom-wide_defconfig @@ -31,7 +31,6 @@ CONFIG_CMD_GPIO=y CONFIG_CMD_MMC=y CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set -# CONFIG_CMD_NFS is not set CONFIG_CMD_PMIC=y CONFIG_CMD_REGULATOR=y CONFIG_CMD_EXT4_WRITE=y diff --git a/configs/minnowmax_defconfig b/configs/minnowmax_defconfig index 6082b8d70d6..8347a9dcecf 100644 --- a/configs/minnowmax_defconfig +++ b/configs/minnowmax_defconfig @@ -43,7 +43,6 @@ CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_DHCP=y CONFIG_BOOTP_BOOTFILESIZE=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_PING=y CONFIG_CMD_TIME=y CONFIG_CMD_BOOTSTAGE=y diff --git a/configs/mscc_jr2_defconfig b/configs/mscc_jr2_defconfig index b30b804dbf2..e3ff906098a 100644 --- a/configs/mscc_jr2_defconfig +++ b/configs/mscc_jr2_defconfig @@ -44,7 +44,6 @@ CONFIG_CMD_GPIO=y CONFIG_CMD_SPI=y CONFIG_CMD_DHCP=y # CONFIG_NET_TFTP_VARS is not set -# CONFIG_CMD_NFS is not set CONFIG_CMD_PING=y CONFIG_CMD_MTDPARTS=y CONFIG_MTDIDS_DEFAULT="nor0=spi_flash" diff --git a/configs/mscc_luton_defconfig b/configs/mscc_luton_defconfig index 9a1e0c3e064..e811bc97e1f 100644 --- a/configs/mscc_luton_defconfig +++ b/configs/mscc_luton_defconfig @@ -46,7 +46,6 @@ CONFIG_CMD_GPIO=y CONFIG_CMD_SPI=y CONFIG_CMD_DHCP=y # CONFIG_NET_TFTP_VARS is not set -# CONFIG_CMD_NFS is not set CONFIG_CMD_PING=y CONFIG_CMD_TIME=y CONFIG_CMD_MTDPARTS=y diff --git a/configs/mscc_ocelot_defconfig b/configs/mscc_ocelot_defconfig index a372b21f66b..f3246f22196 100644 --- a/configs/mscc_ocelot_defconfig +++ b/configs/mscc_ocelot_defconfig @@ -44,7 +44,6 @@ CONFIG_CMD_MTD=y CONFIG_CMD_SPI=y CONFIG_CMD_DHCP=y # CONFIG_NET_TFTP_VARS is not set -# CONFIG_CMD_NFS is not set CONFIG_CMD_PING=y CONFIG_CMD_MTDPARTS=y CONFIG_MTDIDS_DEFAULT="nor0=spi_flash" diff --git a/configs/mscc_serval_defconfig b/configs/mscc_serval_defconfig index 055ed68305a..4ff7933717b 100644 --- a/configs/mscc_serval_defconfig +++ b/configs/mscc_serval_defconfig @@ -41,7 +41,6 @@ CONFIG_CMD_GPIO=y CONFIG_CMD_SPI=y CONFIG_CMD_DHCP=y # CONFIG_NET_TFTP_VARS is not set -# CONFIG_CMD_NFS is not set CONFIG_CMD_PING=y CONFIG_CMD_MTDPARTS=y CONFIG_MTDIDS_DEFAULT="nor0=spi_flash" diff --git a/configs/mscc_servalt_defconfig b/configs/mscc_servalt_defconfig index 6e225a69389..5f6ed73c2ed 100644 --- a/configs/mscc_servalt_defconfig +++ b/configs/mscc_servalt_defconfig @@ -40,7 +40,6 @@ CONFIG_CMD_GPIO=y CONFIG_CMD_SPI=y CONFIG_CMD_DHCP=y # CONFIG_NET_TFTP_VARS is not set -# CONFIG_CMD_NFS is not set CONFIG_CMD_PING=y CONFIG_CMD_MTDPARTS=y CONFIG_MTDIDS_DEFAULT="nor0=spi_flash" diff --git a/configs/mt7620_mt7530_rfb_defconfig b/configs/mt7620_mt7530_rfb_defconfig index 96f10926b13..af9df547d57 100644 --- a/configs/mt7620_mt7530_rfb_defconfig +++ b/configs/mt7620_mt7530_rfb_defconfig @@ -38,7 +38,6 @@ CONFIG_SYS_BOOTM_LEN=0x1000000 CONFIG_CMD_GPIO=y # CONFIG_CMD_LOADS is not set CONFIG_CMD_SPI=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_MII=y # CONFIG_CMD_MDIO is not set CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clocks clock-names interrupt-parent interrupts resets reset-names" diff --git a/configs/mt7620_rfb_defconfig b/configs/mt7620_rfb_defconfig index d96da91df36..fe57fd1892d 100644 --- a/configs/mt7620_rfb_defconfig +++ b/configs/mt7620_rfb_defconfig @@ -39,7 +39,6 @@ CONFIG_CMD_GPIO=y CONFIG_CMD_MMC=y CONFIG_CMD_SPI=y CONFIG_CMD_USB=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_MII=y # CONFIG_CMD_MDIO is not set CONFIG_CMD_FAT=y diff --git a/configs/mt7621_nand_rfb_defconfig b/configs/mt7621_nand_rfb_defconfig index 5291bb300e4..368bf800968 100644 --- a/configs/mt7621_nand_rfb_defconfig +++ b/configs/mt7621_nand_rfb_defconfig @@ -49,7 +49,6 @@ CONFIG_CMD_MTD=y CONFIG_CMD_PART=y # CONFIG_CMD_PINMUX is not set CONFIG_CMD_USB=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_FAT=y CONFIG_CMD_FS_GENERIC=y # CONFIG_SPL_DOS_PARTITION is not set diff --git a/configs/mt7621_rfb_defconfig b/configs/mt7621_rfb_defconfig index b50fbec92dd..49c9e7411d8 100644 --- a/configs/mt7621_rfb_defconfig +++ b/configs/mt7621_rfb_defconfig @@ -47,7 +47,6 @@ CONFIG_CMD_MMC=y CONFIG_CMD_PART=y # CONFIG_CMD_PINMUX is not set CONFIG_CMD_SPI=y -# CONFIG_CMD_NFS is not set CONFIG_DOS_PARTITION=y # CONFIG_SPL_DOS_PARTITION is not set # CONFIG_ISO_PARTITION is not set diff --git a/configs/mt7623a_unielec_u7623_02_defconfig b/configs/mt7623a_unielec_u7623_02_defconfig index a7687b54f0c..20c84d65df7 100644 --- a/configs/mt7623a_unielec_u7623_02_defconfig +++ b/configs/mt7623a_unielec_u7623_02_defconfig @@ -31,7 +31,6 @@ CONFIG_CMD_GPT=y CONFIG_CMD_MMC=y CONFIG_CMD_READ=y # CONFIG_CMD_SETEXPR is not set -# CONFIG_CMD_NFS is not set CONFIG_ENV_IS_IN_MMC=y CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_NET_RANDOM_ETHADDR=y diff --git a/configs/mt7623n_bpir2_defconfig b/configs/mt7623n_bpir2_defconfig index 62a17f2cbc7..5e7c1fefadb 100644 --- a/configs/mt7623n_bpir2_defconfig +++ b/configs/mt7623n_bpir2_defconfig @@ -31,7 +31,6 @@ CONFIG_CMD_GPT=y CONFIG_CMD_MMC=y CONFIG_CMD_READ=y # CONFIG_CMD_SETEXPR is not set -# CONFIG_CMD_NFS is not set CONFIG_ENV_OVERWRITE=y CONFIG_ENV_IS_IN_MMC=y CONFIG_SYS_RELOC_GD_ENV_ADDR=y diff --git a/configs/mt7628_rfb_defconfig b/configs/mt7628_rfb_defconfig index 0e100fca498..7e5b76c590a 100644 --- a/configs/mt7628_rfb_defconfig +++ b/configs/mt7628_rfb_defconfig @@ -37,7 +37,6 @@ CONFIG_SYS_BOOTM_LEN=0x1000000 CONFIG_CMD_GPIO=y # CONFIG_CMD_LOADS is not set CONFIG_CMD_SPI=y -# CONFIG_CMD_NFS is not set CONFIG_ENV_IS_IN_SPI_FLASH=y CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_NET_RANDOM_ETHADDR=y diff --git a/configs/mt7629_rfb_defconfig b/configs/mt7629_rfb_defconfig index ea8d77c0a26..0e3bd4ffa7b 100644 --- a/configs/mt7629_rfb_defconfig +++ b/configs/mt7629_rfb_defconfig @@ -48,7 +48,6 @@ CONFIG_CMD_GPIO=y CONFIG_CMD_SF_TEST=y CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set -# CONFIG_CMD_NFS is not set CONFIG_CMD_PING=y CONFIG_CMD_FAT=y CONFIG_CMD_FS_GENERIC=y diff --git a/configs/mx23_olinuxino_defconfig b/configs/mx23_olinuxino_defconfig index 89b69fb3236..24968e18710 100644 --- a/configs/mx23_olinuxino_defconfig +++ b/configs/mx23_olinuxino_defconfig @@ -50,6 +50,7 @@ CONFIG_LED_STATUS_BOOT=0 CONFIG_LED_STATUS_CMD=y CONFIG_MMC_MXS=y CONFIG_CONS_INDEX=0 +CONFIG_DM_SERIAL=y CONFIG_USB=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_HOST_ETHER=y diff --git a/configs/mx23evk_defconfig b/configs/mx23evk_defconfig index 3602ead8635..7d0e7cc1e00 100644 --- a/configs/mx23evk_defconfig +++ b/configs/mx23evk_defconfig @@ -49,6 +49,7 @@ CONFIG_DM_REGULATOR=y CONFIG_DM_REGULATOR_FIXED=y CONFIG_DM_REGULATOR_GPIO=y CONFIG_CONS_INDEX=0 +CONFIG_DM_SERIAL=y CONFIG_USB=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_STORAGE=y diff --git a/configs/mx28evk_defconfig b/configs/mx28evk_defconfig index dad8839a6c1..df0cceaea71 100644 --- a/configs/mx28evk_defconfig +++ b/configs/mx28evk_defconfig @@ -62,6 +62,6 @@ CONFIG_DM_REGULATOR=y CONFIG_DM_REGULATOR_FIXED=y CONFIG_DM_REGULATOR_GPIO=y CONFIG_RTC_MXS=y -CONFIG_CONS_INDEX=0 +CONFIG_DM_SERIAL=y CONFIG_SPI=y CONFIG_USB=y diff --git a/configs/nyan-big_defconfig b/configs/nyan-big_defconfig index a9c10cdbb0b..cc64facd5f2 100644 --- a/configs/nyan-big_defconfig +++ b/configs/nyan-big_defconfig @@ -45,7 +45,6 @@ CONFIG_CMD_SPI=y CONFIG_CMD_USB=y CONFIG_CMD_USB_MASS_STORAGE=y # CONFIG_CMD_SETEXPR is not set -# CONFIG_CMD_NFS is not set CONFIG_CMD_BMP=y CONFIG_CMD_CACHE=y CONFIG_CMD_TIME=y diff --git a/configs/odroid_defconfig b/configs/odroid_defconfig index ce0c47e505d..b1943cfd39b 100644 --- a/configs/odroid_defconfig +++ b/configs/odroid_defconfig @@ -41,7 +41,6 @@ CONFIG_CMD_I2C=y CONFIG_CMD_MMC=y CONFIG_CMD_USB=y CONFIG_CMD_USB_MASS_STORAGE=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_CACHE=y # CONFIG_CMD_SLEEP is not set CONFIG_CMD_PMIC=y diff --git a/configs/omap4_panda_defconfig b/configs/omap4_panda_defconfig index e27e27d0143..5571722ea6d 100644 --- a/configs/omap4_panda_defconfig +++ b/configs/omap4_panda_defconfig @@ -33,7 +33,6 @@ CONFIG_CMD_I2C=y CONFIG_CMD_MMC=y CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set -# CONFIG_CMD_NFS is not set CONFIG_CMD_EXT4_WRITE=y CONFIG_OF_CONTROL=y CONFIG_ENV_OVERWRITE=y diff --git a/configs/omap4_sdp4430_defconfig b/configs/omap4_sdp4430_defconfig index 909f10ee790..0a8a1c77ea4 100644 --- a/configs/omap4_sdp4430_defconfig +++ b/configs/omap4_sdp4430_defconfig @@ -29,7 +29,6 @@ CONFIG_CMD_GPIO=y CONFIG_CMD_I2C=y CONFIG_CMD_MMC=y # CONFIG_CMD_SETEXPR is not set -# CONFIG_CMD_NFS is not set CONFIG_CMD_EXT4_WRITE=y # CONFIG_EFI_PARTITION is not set CONFIG_SPL_PARTITION_UUIDS=y diff --git a/configs/p2371-0000_defconfig b/configs/p2371-0000_defconfig index 7e75f44c743..dcfd3eb99a5 100644 --- a/configs/p2371-0000_defconfig +++ b/configs/p2371-0000_defconfig @@ -28,7 +28,6 @@ CONFIG_CMD_USB=y CONFIG_CMD_USB_MASS_STORAGE=y # CONFIG_CMD_SETEXPR is not set CONFIG_BOOTP_PREFER_SERVERIP=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_EXT4_WRITE=y CONFIG_ENV_OVERWRITE=y CONFIG_SYS_RELOC_GD_ENV_ADDR=y diff --git a/configs/p2371-2180_defconfig b/configs/p2371-2180_defconfig index 2543a2d11f8..5b91631367b 100644 --- a/configs/p2371-2180_defconfig +++ b/configs/p2371-2180_defconfig @@ -34,7 +34,6 @@ CONFIG_CMD_USB=y CONFIG_CMD_USB_MASS_STORAGE=y # CONFIG_CMD_SETEXPR is not set CONFIG_BOOTP_PREFER_SERVERIP=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_EXT4_WRITE=y CONFIG_OF_LIVE=y CONFIG_ENV_OVERWRITE=y diff --git a/configs/p2571_defconfig b/configs/p2571_defconfig index 47a0a62d252..7e2829e3a0d 100644 --- a/configs/p2571_defconfig +++ b/configs/p2571_defconfig @@ -29,7 +29,6 @@ CONFIG_CMD_USB=y CONFIG_CMD_USB_MASS_STORAGE=y # CONFIG_CMD_SETEXPR is not set CONFIG_BOOTP_PREFER_SERVERIP=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_EXT4_WRITE=y CONFIG_ENV_OVERWRITE=y CONFIG_SYS_RELOC_GD_ENV_ADDR=y diff --git a/configs/p2771-0000-000_defconfig b/configs/p2771-0000-000_defconfig index e3b978eb1ed..ae235058afd 100644 --- a/configs/p2771-0000-000_defconfig +++ b/configs/p2771-0000-000_defconfig @@ -27,7 +27,6 @@ CONFIG_CMD_PCI=y CONFIG_CMD_SPI=y # CONFIG_CMD_SETEXPR is not set CONFIG_BOOTP_PREFER_SERVERIP=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_EXT4_WRITE=y CONFIG_ENV_OVERWRITE=y CONFIG_SYS_RELOC_GD_ENV_ADDR=y diff --git a/configs/p2771-0000-500_defconfig b/configs/p2771-0000-500_defconfig index c99a24eef40..0ea47192dda 100644 --- a/configs/p2771-0000-500_defconfig +++ b/configs/p2771-0000-500_defconfig @@ -27,7 +27,6 @@ CONFIG_CMD_PCI=y CONFIG_CMD_SPI=y # CONFIG_CMD_SETEXPR is not set CONFIG_BOOTP_PREFER_SERVERIP=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_EXT4_WRITE=y CONFIG_ENV_OVERWRITE=y CONFIG_SYS_RELOC_GD_ENV_ADDR=y diff --git a/configs/p3450-0000_defconfig b/configs/p3450-0000_defconfig index e280be8f2ec..b0d538f0f83 100644 --- a/configs/p3450-0000_defconfig +++ b/configs/p3450-0000_defconfig @@ -35,7 +35,6 @@ CONFIG_CMD_USB=y CONFIG_CMD_USB_MASS_STORAGE=y # CONFIG_CMD_SETEXPR is not set CONFIG_BOOTP_PREFER_SERVERIP=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_EXT4_WRITE=y CONFIG_OF_LIVE=y CONFIG_ENV_OVERWRITE=y diff --git a/configs/paz00_defconfig b/configs/paz00_defconfig index fadf7fdeb07..8c125c39b2f 100644 --- a/configs/paz00_defconfig +++ b/configs/paz00_defconfig @@ -28,7 +28,6 @@ CONFIG_CMD_GPIO=y CONFIG_CMD_MMC=y CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set -# CONFIG_CMD_NFS is not set CONFIG_CMD_PMIC=y CONFIG_CMD_REGULATOR=y CONFIG_CMD_EXT4_WRITE=y diff --git a/configs/phycore-imx8mm_defconfig b/configs/phycore-imx8mm_defconfig index ffdb5cce8eb..4a27d15cb11 100644 --- a/configs/phycore-imx8mm_defconfig +++ b/configs/phycore-imx8mm_defconfig @@ -21,6 +21,7 @@ CONFIG_SPL_STACK=0x920000 CONFIG_SPL=y CONFIG_ENV_OFFSET_REDUND=0x3E0000 CONFIG_SYS_LOAD_ADDR=0x40480000 +CONFIG_LTO=y CONFIG_FIT=y CONFIG_FIT_EXTERNAL_OFFSET=0x3000 CONFIG_SPL_LOAD_FIT=y diff --git a/configs/phycore-imx8mp_defconfig b/configs/phycore-imx8mp_defconfig index 3d076204ad0..7bf404be860 100644 --- a/configs/phycore-imx8mp_defconfig +++ b/configs/phycore-imx8mp_defconfig @@ -21,6 +21,7 @@ CONFIG_SPL_STACK=0x960000 CONFIG_SPL=y CONFIG_SPL_IMX_ROMAPI_LOADADDR=0x48000000 CONFIG_SYS_LOAD_ADDR=0x40480000 +CONFIG_LTO=y CONFIG_FIT=y CONFIG_FIT_EXTERNAL_OFFSET=0x3000 CONFIG_SPL_LOAD_FIT=y diff --git a/configs/plutux_defconfig b/configs/plutux_defconfig index 4fee9df94f8..ab9aef5e478 100644 --- a/configs/plutux_defconfig +++ b/configs/plutux_defconfig @@ -32,7 +32,6 @@ CONFIG_CMD_GPIO=y CONFIG_CMD_MMC=y CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set -# CONFIG_CMD_NFS is not set CONFIG_CMD_EXT4_WRITE=y # CONFIG_SPL_DOS_PARTITION is not set # CONFIG_SPL_EFI_PARTITION is not set diff --git a/configs/poleg_evb_defconfig b/configs/poleg_evb_defconfig index b00fb48a5a7..cab589d7aa0 100644 --- a/configs/poleg_evb_defconfig +++ b/configs/poleg_evb_defconfig @@ -102,3 +102,6 @@ CONFIG_USB_GADGET_DOWNLOAD=y CONFIG_WDT_NPCM=y CONFIG_LIB_HW_RAND=y CONFIG_SHA_HW_ACCEL=y +CONFIG_FIT=y +CONFIG_SHA256=y +CONFIG_SHA512=y diff --git a/configs/qemu-x86_64_defconfig b/configs/qemu-x86_64_defconfig index f29a5aa0f81..6a539a859e0 100644 --- a/configs/qemu-x86_64_defconfig +++ b/configs/qemu-x86_64_defconfig @@ -47,7 +47,6 @@ CONFIG_CMD_SPI=y CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set CONFIG_BOOTP_BOOTFILESIZE=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_TIME=y CONFIG_CMD_QFW=y CONFIG_CMD_BOOTSTAGE=y diff --git a/configs/qemu-x86_defconfig b/configs/qemu-x86_defconfig index 9bf29647fe5..a7c37b8b0e1 100644 --- a/configs/qemu-x86_defconfig +++ b/configs/qemu-x86_defconfig @@ -28,7 +28,6 @@ CONFIG_CMD_SPI=y CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set CONFIG_BOOTP_BOOTFILESIZE=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_TIME=y CONFIG_CMD_QFW=y CONFIG_CMD_BOOTSTAGE=y diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 1ec44d5b33b..4cef6c51539 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -30,6 +30,7 @@ CONFIG_AUTOBOOT_STOP_STR_ENABLE=y CONFIG_AUTOBOOT_STOP_STR_CRYPT="$5$rounds=640000$HrpE65IkB8CM5nCL$BKT3QdF98Bo8fJpTr9tjZLZQyzqPASBY20xuK5Rent9" CONFIG_IMAGE_PRE_LOAD=y CONFIG_IMAGE_PRE_LOAD_SIG=y +CONFIG_CEDIT=y CONFIG_CONSOLE_RECORD=y CONFIG_CONSOLE_RECORD_OUT_SIZE=0x6000 CONFIG_PRE_CONSOLE_BUFFER=y diff --git a/configs/seaboard_defconfig b/configs/seaboard_defconfig index 00cca911710..f8759f25546 100644 --- a/configs/seaboard_defconfig +++ b/configs/seaboard_defconfig @@ -31,7 +31,6 @@ CONFIG_CMD_I2C=y CONFIG_CMD_MMC=y CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set -# CONFIG_CMD_NFS is not set CONFIG_CMD_PMIC=y CONFIG_CMD_REGULATOR=y CONFIG_CMD_EXT4_WRITE=y diff --git a/configs/smdkv310_defconfig b/configs/smdkv310_defconfig index cc0ecad11b3..2f466d23a54 100644 --- a/configs/smdkv310_defconfig +++ b/configs/smdkv310_defconfig @@ -27,7 +27,6 @@ CONFIG_SYS_PBSIZE=1024 # CONFIG_CMD_XIMG is not set CONFIG_CMD_GPT=y CONFIG_CMD_MMC=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_CACHE=y # CONFIG_CMD_SLEEP is not set CONFIG_CMD_EXT4_WRITE=y diff --git a/configs/sniper_defconfig b/configs/sniper_defconfig index f6b59a6e9b8..c762d75aec1 100644 --- a/configs/sniper_defconfig +++ b/configs/sniper_defconfig @@ -32,7 +32,6 @@ CONFIG_CMD_GPIO=y CONFIG_CMD_I2C=y CONFIG_CMD_MMC=y # CONFIG_CMD_SETEXPR is not set -# CONFIG_CMD_NFS is not set CONFIG_ENV_OVERWRITE=y CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_SYS_I2C_LEGACY=y diff --git a/configs/socrates_defconfig b/configs/socrates_defconfig index ba5990bfe25..33092c74613 100644 --- a/configs/socrates_defconfig +++ b/configs/socrates_defconfig @@ -57,7 +57,6 @@ CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_DHCP=y CONFIG_BOOTP_BOOTFILESIZE=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_MII=y CONFIG_CMD_PING=y CONFIG_CMD_SNTP=y diff --git a/configs/som-db5800-som-6867_defconfig b/configs/som-db5800-som-6867_defconfig index ad95274879a..4a149133db6 100644 --- a/configs/som-db5800-som-6867_defconfig +++ b/configs/som-db5800-som-6867_defconfig @@ -38,7 +38,6 @@ CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_DHCP=y CONFIG_BOOTP_BOOTFILESIZE=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_PING=y CONFIG_CMD_TIME=y CONFIG_CMD_BOOTSTAGE=y diff --git a/configs/starfive_visionfive2_defconfig b/configs/starfive_visionfive2_defconfig index ffbc4b94767..570a1f53a19 100644 --- a/configs/starfive_visionfive2_defconfig +++ b/configs/starfive_visionfive2_defconfig @@ -7,12 +7,13 @@ CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x80000000 CONFIG_SF_DEFAULT_SPEED=100000000 CONFIG_SPL_DM_SPI=y -CONFIG_DEFAULT_DEVICE_TREE="jh7110-starfive-visionfive-2-v1.3b" +CONFIG_DEFAULT_DEVICE_TREE="jh7110-starfive-visionfive-2" CONFIG_SPL_TEXT_BASE=0x8000000 CONFIG_SYS_PROMPT="StarFive #" CONFIG_OF_LIBFDT_OVERLAY=y CONFIG_DM_RESET=y CONFIG_SPL_MMC=y +CONFIG_SPL_DRIVERS_MISC=y CONFIG_SPL_STACK=0x8180000 CONFIG_SPL=y CONFIG_SPL_SPI_FLASH_SUPPORT=y @@ -23,6 +24,7 @@ CONFIG_SPL_OPENSBI_LOAD_ADDR=0x40000000 CONFIG_ARCH_RV64I=y CONFIG_CMODEL_MEDANY=y CONFIG_RISCV_SMODE=y +# CONFIG_OF_BOARD_FIXUP is not set CONFIG_FIT=y CONFIG_DISTRO_DEFAULTS=y CONFIG_QSPI_BOOT=y @@ -31,9 +33,11 @@ CONFIG_USE_BOOTARGS=y CONFIG_BOOTARGS="console=ttyS0,115200 debug rootwait earlycon=sbi" CONFIG_USE_PREBOOT=y CONFIG_PREBOOT="setenv fdt_addr ${fdtcontroladdr};fdt addr ${fdtcontroladdr};" -CONFIG_DEFAULT_FDT_FILE="starfive/jh7110-starfive-visionfive-2-v1.3b.dtb" +CONFIG_DEFAULT_FDT_FILE="starfive/jh7110-starfive-visionfive-2.dtb" CONFIG_DISPLAY_CPUINFO=y CONFIG_DISPLAY_BOARDINFO=y +CONFIG_ID_EEPROM=y +CONFIG_SYS_EEPROM_BUS_NUM=5 CONFIG_SPL_MAX_SIZE=0x40000 CONFIG_SPL_PAD_TO=0x0 CONFIG_SPL_BSS_START_ADDR=0x8040000 @@ -45,19 +49,34 @@ CONFIG_CUSTOM_SYS_SPL_MALLOC_ADDR=0x80000000 CONFIG_SYS_SPL_MALLOC_SIZE=0x400000 CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION=y CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION=0x2 +CONFIG_SPL_I2C=y CONFIG_SPL_DM_SPI_FLASH=y CONFIG_SPL_DM_RESET=y CONFIG_SPL_SPI_LOAD=y CONFIG_SYS_CBSIZE=256 CONFIG_SYS_PBSIZE=276 CONFIG_SYS_BOOTM_LEN=0x4000000 +CONFIG_CMD_EEPROM=y +CONFIG_SYS_EEPROM_SIZE=512 +CONFIG_SYS_EEPROM_PAGE_WRITE_BITS=4 +CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS=5 CONFIG_CMD_MEMINFO=y +CONFIG_CMD_I2C=y CONFIG_CMD_TFTPPUT=y +CONFIG_OF_BOARD=y CONFIG_SYS_RELOC_GD_ENV_ADDR=y +CONFIG_SPL_DM_SEQ_ALIAS=y +CONFIG_REGMAP=y +CONFIG_SYSCON=y CONFIG_SPL_CLK_COMPOSITE_CCF=y CONFIG_CLK_COMPOSITE_CCF=y CONFIG_SPL_CLK_JH7110=y -# CONFIG_I2C is not set +CONFIG_DM_I2C=y +CONFIG_SYS_I2C_DW=y +CONFIG_MISC=y +CONFIG_I2C_EEPROM=y +CONFIG_SPL_I2C_EEPROM=y +CONFIG_SYS_I2C_EEPROM_ADDR=0X50 CONFIG_MMC_HS400_SUPPORT=y CONFIG_SPL_MMC_HS400_SUPPORT=y CONFIG_MMC_DW=y @@ -66,6 +85,13 @@ CONFIG_SPI_FLASH_EON=y CONFIG_SPI_FLASH_GIGADEVICE=y CONFIG_SPI_FLASH_ISSI=y CONFIG_SPI_FLASH_MACRONIX=y +CONFIG_PHY_MOTORCOMM=y +CONFIG_DM_MDIO=y +CONFIG_DM_ETH_PHY=y +CONFIG_DWC_ETH_QOS=y +CONFIG_DWC_ETH_QOS_STARFIVE=y +CONFIG_RGMII=y +CONFIG_RMII=y CONFIG_PINCTRL=y CONFIG_PINCONF=y CONFIG_SPL_PINCTRL=y diff --git a/configs/tec-ng_defconfig b/configs/tec-ng_defconfig index 442cee33a9f..4776e92683d 100644 --- a/configs/tec-ng_defconfig +++ b/configs/tec-ng_defconfig @@ -34,7 +34,6 @@ CONFIG_CMD_MMC=y CONFIG_CMD_SPI=y CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set -# CONFIG_CMD_NFS is not set CONFIG_CMD_EXT4_WRITE=y # CONFIG_SPL_DOS_PARTITION is not set # CONFIG_SPL_EFI_PARTITION is not set diff --git a/configs/tec_defconfig b/configs/tec_defconfig index 461c46c725d..8a5d959a5c0 100644 --- a/configs/tec_defconfig +++ b/configs/tec_defconfig @@ -31,7 +31,6 @@ CONFIG_CMD_GPIO=y CONFIG_CMD_MMC=y CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set -# CONFIG_CMD_NFS is not set CONFIG_CMD_PMIC=y CONFIG_CMD_REGULATOR=y CONFIG_CMD_EXT4_WRITE=y diff --git a/configs/th1520_lpi4a_defconfig b/configs/th1520_lpi4a_defconfig new file mode 100644 index 00000000000..710ec6abf52 --- /dev/null +++ b/configs/th1520_lpi4a_defconfig @@ -0,0 +1,82 @@ +CONFIG_RISCV=y +CONFIG_SYS_MALLOC_LEN=0x800000 +CONFIG_SYS_MALLOC_F_LEN=0x3000 +CONFIG_NR_DRAM_BANKS=1 +CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y +CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x80200000 +CONFIG_DEFAULT_DEVICE_TREE="th1520-lichee-pi-4a" +CONFIG_SYS_PROMPT="LPI4A=> " +CONFIG_SYS_LOAD_ADDR=0x80200000 +# CONFIG_SMP is not set +CONFIG_TARGET_TH1520_LPI4A=y +CONFIG_ARCH_RV64I=y +CONFIG_OF_BOARD_FIXUP=y +CONFIG_SYS_BOOT_GET_CMDLINE=y +CONFIG_SYS_BOOT_GET_KBD=y +CONFIG_FIT=y +# CONFIG_FIT_FULL_CHECK is not set +# CONFIG_FIT_PRINT is not set +# CONFIG_BOOTSTD is not set +# CONFIG_LEGACY_IMAGE_FORMAT is not set +CONFIG_DISTRO_DEFAULTS=y +CONFIG_BOOTARGS_SUBST=y +CONFIG_BOOTCOMMAND="" +CONFIG_DEFAULT_FDT_FILE="thead/th1520-lichee-pi-4a.dtb" +CONFIG_LOG=y +CONFIG_DISPLAY_CPUINFO=y +CONFIG_DISPLAY_BOARDINFO=y +CONFIG_DISPLAY_BOARDINFO_LATE=y +CONFIG_SYS_CBSIZE=256 +CONFIG_SYS_PBSIZE=276 +CONFIG_CMD_CONFIG=y +CONFIG_CMD_LICENSE=y +CONFIG_CMD_BOOTZ=y +# CONFIG_BOOTM_NETBSD is not set +# CONFIG_BOOTM_PLAN9 is not set +# CONFIG_BOOTM_RTEMS is not set +# CONFIG_BOOTM_VXWORKS is not set +CONFIG_SYS_BOOTM_LEN=0x4000000 +CONFIG_CMD_BOOTMENU=y +# CONFIG_CMD_ELF is not set +# CONFIG_CMD_IMI is not set +# CONFIG_CMD_XIMG is not set +# CONFIG_CMD_EXPORTENV is not set +# CONFIG_CMD_IMPORTENV is not set +# CONFIG_CMD_EDITENV is not set +# CONFIG_CMD_SAVEENV is not set +# CONFIG_CMD_CRC32 is not set +# CONFIG_CMD_MEMORY is not set +# CONFIG_CMD_LZMADEC is not set +# CONFIG_CMD_UNLZ4 is not set +# CONFIG_CMD_UNZIP is not set +# CONFIG_CMD_LOADB is not set +# CONFIG_CMD_LOADS is not set +# CONFIG_CMD_ITEST is not set +# CONFIG_CMD_SOURCE is not set +# CONFIG_CMD_SETEXPR is not set +# CONFIG_CMD_SLEEP is not set +CONFIG_PARTITION_TYPE_GUID=y +CONFIG_SYS_RELOC_GD_ENV_ADDR=y +CONFIG_VERSION_VARIABLE=y +# CONFIG_NET is not set +# CONFIG_BLOCK_CACHE is not set +# CONFIG_GPIO is not set +# CONFIG_I2C is not set +# CONFIG_INPUT is not set +# CONFIG_DM_MMC is not set +# CONFIG_MTD is not set +# CONFIG_POWER is not set +CONFIG_SYS_NS16550=y +CONFIG_RISCV_TIMER=y +CONFIG_AES=y +CONFIG_BLAKE2=y +CONFIG_SHA512=y +CONFIG_LZ4=y +CONFIG_LZMA=y +CONFIG_LZO=y +CONFIG_ZLIB_UNCOMPRESS=y +CONFIG_BZIP2=y +CONFIG_ZSTD=y +CONFIG_LIB_RATIONAL=y +# CONFIG_EFI_LOADER is not set +# CONFIG_LMB_USE_MAX_REGIONS is not set diff --git a/configs/theadorable-x86-conga-qa3-e3845-pcie-x4_defconfig b/configs/theadorable-x86-conga-qa3-e3845-pcie-x4_defconfig index 43dab09316e..69499e17f4c 100644 --- a/configs/theadorable-x86-conga-qa3-e3845-pcie-x4_defconfig +++ b/configs/theadorable-x86-conga-qa3-e3845-pcie-x4_defconfig @@ -38,7 +38,6 @@ CONFIG_CMD_SPI=y CONFIG_CMD_USB=y CONFIG_CMD_DHCP=y CONFIG_BOOTP_BOOTFILESIZE=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_PING=y CONFIG_CMD_BMP=y CONFIG_CMD_TIME=y diff --git a/configs/theadorable-x86-conga-qa3-e3845_defconfig b/configs/theadorable-x86-conga-qa3-e3845_defconfig index 5aec52733e6..e2e64b74349 100644 --- a/configs/theadorable-x86-conga-qa3-e3845_defconfig +++ b/configs/theadorable-x86-conga-qa3-e3845_defconfig @@ -37,7 +37,6 @@ CONFIG_CMD_SPI=y CONFIG_CMD_USB=y CONFIG_CMD_DHCP=y CONFIG_BOOTP_BOOTFILESIZE=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_PING=y CONFIG_CMD_BMP=y CONFIG_CMD_TIME=y diff --git a/configs/theadorable-x86-dfi-bt700_defconfig b/configs/theadorable-x86-dfi-bt700_defconfig index d5a28a2df4b..751ae3497ec 100644 --- a/configs/theadorable-x86-dfi-bt700_defconfig +++ b/configs/theadorable-x86-dfi-bt700_defconfig @@ -35,7 +35,6 @@ CONFIG_CMD_SPI=y CONFIG_CMD_USB=y CONFIG_CMD_DHCP=y CONFIG_BOOTP_BOOTFILESIZE=y -# CONFIG_CMD_NFS is not set CONFIG_CMD_PING=y CONFIG_CMD_BMP=y CONFIG_CMD_TIME=y diff --git a/configs/trimslice_defconfig b/configs/trimslice_defconfig index d94a0b408b5..9ec08bda883 100644 --- a/configs/trimslice_defconfig +++ b/configs/trimslice_defconfig @@ -35,7 +35,6 @@ CONFIG_CMD_PCI=y CONFIG_CMD_SPI=y CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set -# CONFIG_CMD_NFS is not set CONFIG_CMD_EXT4_WRITE=y # CONFIG_SPL_DOS_PARTITION is not set # CONFIG_SPL_EFI_PARTITION is not set diff --git a/configs/venice2_defconfig b/configs/venice2_defconfig index fd538da3ac5..ebd1754fc8b 100644 --- a/configs/venice2_defconfig +++ b/configs/venice2_defconfig @@ -36,7 +36,6 @@ CONFIG_CMD_SPI=y CONFIG_CMD_USB=y CONFIG_CMD_USB_MASS_STORAGE=y # CONFIG_CMD_SETEXPR is not set -# CONFIG_CMD_NFS is not set CONFIG_CMD_EXT4_WRITE=y # CONFIG_SPL_DOS_PARTITION is not set # CONFIG_SPL_EFI_PARTITION is not set diff --git a/configs/ventana_defconfig b/configs/ventana_defconfig index 5e2ff877ca8..2da8ba94d62 100644 --- a/configs/ventana_defconfig +++ b/configs/ventana_defconfig @@ -29,7 +29,6 @@ CONFIG_CMD_GPIO=y CONFIG_CMD_MMC=y CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set -# CONFIG_CMD_NFS is not set CONFIG_CMD_PMIC=y CONFIG_CMD_REGULATOR=y CONFIG_CMD_EXT4_WRITE=y diff --git a/configs/verdin-imx8mm_defconfig b/configs/verdin-imx8mm_defconfig index 0eb18915154..09e14c6f8c4 100644 --- a/configs/verdin-imx8mm_defconfig +++ b/configs/verdin-imx8mm_defconfig @@ -98,6 +98,7 @@ CONFIG_CLK_COMPOSITE_CCF=y CONFIG_SPL_CLK_IMX8MM=y CONFIG_CLK_IMX8MM=y CONFIG_GPIO_HOG=y +CONFIG_SPL_GPIO_HOG=y CONFIG_MXC_GPIO=y CONFIG_DM_I2C=y CONFIG_MISC=y diff --git a/configs/verdin-imx8mp_defconfig b/configs/verdin-imx8mp_defconfig index f1fa2b8f496..2df0f4f3443 100644 --- a/configs/verdin-imx8mp_defconfig +++ b/configs/verdin-imx8mp_defconfig @@ -42,6 +42,7 @@ CONFIG_PREBOOT="test -n ${fdtfile} || setenv fdtfile imx8mp-verdin-${variant}-${ CONFIG_LOG=y # CONFIG_DISPLAY_BOARDINFO is not set CONFIG_DISPLAY_BOARDINFO_LATE=y +CONFIG_ARCH_MISC_INIT=y CONFIG_BOARD_EARLY_INIT_F=y CONFIG_BOARD_LATE_INIT=y CONFIG_SPL_MAX_SIZE=0x26000 @@ -108,6 +109,7 @@ CONFIG_CLK_COMPOSITE_CCF=y CONFIG_CLK_IMX8MP=y CONFIG_FSL_CAAM=y CONFIG_GPIO_HOG=y +CONFIG_SPL_GPIO_HOG=y CONFIG_MXC_GPIO=y CONFIG_DM_PCA953X=y CONFIG_DM_I2C=y diff --git a/configs/vexpress_ca9x4_defconfig b/configs/vexpress_ca9x4_defconfig index 4ee64c332b3..5cacecc7cbc 100644 --- a/configs/vexpress_ca9x4_defconfig +++ b/configs/vexpress_ca9x4_defconfig @@ -30,7 +30,6 @@ CONFIG_CMD_MMC=y # CONFIG_CMD_ITEST is not set # CONFIG_CMD_SETEXPR is not set CONFIG_BOOTP_BOOTFILESIZE=y -# CONFIG_CMD_NFS is not set # CONFIG_CMD_SLEEP is not set CONFIG_CMD_UBI=y CONFIG_OF_CONTROL=y diff --git a/configs/x240_defconfig b/configs/x240_defconfig new file mode 100644 index 00000000000..6d25c5ae3fc --- /dev/null +++ b/configs/x240_defconfig @@ -0,0 +1,86 @@ +CONFIG_ARM=y +CONFIG_ARCH_CPU_INIT=y +CONFIG_ARCH_MVEBU=y +CONFIG_TEXT_BASE=0x200000000 +CONFIG_SYS_MALLOC_LEN=0x900000 +CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y +CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x200FF0000 +CONFIG_TARGET_X240=y +CONFIG_ENV_SIZE=0x10000 +CONFIG_ENV_OFFSET=0x00f80000 +CONFIG_ENV_SECT_SIZE=0x40000 +CONFIG_DM_GPIO=y +CONFIG_DEFAULT_DEVICE_TREE="ac5-98dx35xx-atl-x240" +CONFIG_SYS_LOAD_ADDR=0x220000000 +# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set +CONFIG_FIT=y +CONFIG_BOOTDELAY=3 +CONFIG_SYS_CONSOLE_ENV_OVERWRITE=y +CONFIG_SYS_CONSOLE_INFO_QUIET=y +CONFIG_DISPLAY_BOARDINFO_LATE=y +CONFIG_CMD_BOOTZ=y +CONFIG_CMD_MEMTEST=y +# CONFIG_CMD_FLASH is not set +CONFIG_CMD_GPIO=y +CONFIG_CMD_I2C=y +CONFIG_CMD_MTD=y +CONFIG_CMD_PCI=y +CONFIG_CMD_SPI=y +CONFIG_CMD_USB=y +# CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_DHCP=y +CONFIG_CMD_PING=y +CONFIG_CMD_CACHE=y +CONFIG_CMD_TIME=y +CONFIG_CMD_REGULATOR=y +CONFIG_CMD_EXT4=y +CONFIG_CMD_FAT=y +CONFIG_CMD_FS_GENERIC=y +CONFIG_CMD_UBI=y +CONFIG_ENV_IS_IN_SPI_FLASH=y +CONFIG_CLK=y +CONFIG_CLK_MVEBU=y +CONFIG_GPIO_HOG=y +CONFIG_DM_PCA953X=y +CONFIG_DM_I2C=y +CONFIG_SYS_I2C_MVTWSI=y +CONFIG_I2C_MUX=y +CONFIG_I2C_MUX_PCA954x=y +CONFIG_LED=y +CONFIG_LED_GPIO=y +CONFIG_MISC=y +# CONFIG_MMC is not set +CONFIG_MTD=y +CONFIG_MTD_RAW_NAND=y +CONFIG_NAND_PXA3XX=y +CONFIG_SYS_NAND_ONFI_DETECTION=y +CONFIG_SPI_FLASH_SFDP_SUPPORT=y +CONFIG_SPI_FLASH_ATMEL=y +CONFIG_SPI_FLASH_GIGADEVICE=y +CONFIG_SPI_FLASH_MACRONIX=y +CONFIG_SPI_FLASH_SPANSION=y +CONFIG_SPI_FLASH_STMICRO=y +CONFIG_SPI_FLASH_SST=y +CONFIG_SPI_FLASH_WINBOND=y +CONFIG_PHY=y +CONFIG_PINCTRL=y +CONFIG_PINCTRL_ARMADA_8K=y +CONFIG_DM_REGULATOR_FIXED=y +CONFIG_DM_REGULATOR_GPIO=y +CONFIG_DM_RTC=y +CONFIG_RTC_MAX313XX=y +CONFIG_DM_SCSI=y +CONFIG_SYS_NS16550=y +CONFIG_MVEBU_A3700_SPI=y +CONFIG_DM_THERMAL=y +CONFIG_USB=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_STORAGE=y +CONFIG_USB_HOST_ETHER=y +CONFIG_USB_ETHER_ASIX=y +CONFIG_USB_ETHER_ASIX88179=y +CONFIG_USB_ETHER_MCS7830=y +CONFIG_USB_ETHER_RTL8152=y +CONFIG_USB_ETHER_SMSC95XX=y +# CONFIG_FAT_WRITE is not set diff --git a/doc/board/beacon/beacon-imx8mm.rst b/doc/board/beacon/beacon-imx8mm.rst new file mode 100644 index 00000000000..8bf983bff77 --- /dev/null +++ b/doc/board/beacon/beacon-imx8mm.rst @@ -0,0 +1,55 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +U-Boot for the Beacon EmbeddedWorks i.MX8M Mini Devkit +====================================================== + +Quick Start +----------- + +- Build the ARM Trusted firmware binary +- Get DDR firmware +- Build U-Boot +- Burn U-Boot to microSD Card +- Boot + +Get and Build the ARM Trusted firmware +-------------------------------------- + +.. code-block:: bash + + $ git clone https://github.com/nxp-imx/imx-atf.git -b v2.6 + $ make PLAT=imx8mm bl31 CROSS_COMPILE=aarch64-linux-gnu- + $ cp build/imx8mm/release/bl31.bin ../ + +Get the DDR firmware +-------------------- + +.. code-block:: bash + + $ wget https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/firmware-imx-8.15.bin + $ chmod +x firmware-imx-8.15.bin + $ ./firmware-imx-8.15 + $ cp firmware-imx-8.15/firmware/ddr/synopsys/lpddr4*.bin . + +Build U-Boot +------------ + +.. code-block:: bash + + $ make imx8mm_beacon_defconfig + $ make CROSS_COMPILE=aarch64-linux-gnu- + +Burn U-Boot to microSD Card +--------------------------- + +.. code-block:: bash + + $ sudo dd if=flash.bin of=/dev/sd[x] bs=1024 seek=33 + +Boot +---- + +Set baseboard DIP switches for micoSD Card: +- S11 (1:8) 01101000 +- S10 (1:8) 11001000 +- S17 (1:8) 0110xxxx diff --git a/doc/board/beacon/beacon-imx8mn.rst b/doc/board/beacon/beacon-imx8mn.rst new file mode 100644 index 00000000000..bb4a86369bb --- /dev/null +++ b/doc/board/beacon/beacon-imx8mn.rst @@ -0,0 +1,53 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +U-Boot for the Beacon EmbeddedWorks i.MX8M Nano Devkit +====================================================== + +Quick Start +----------- + +- Build the ARM Trusted firmware binary +- Get DDR firmware +- Build U-Boot +- Burn U-Boot to microSD Card +- Boot + +Get and Build the ARM Trusted firmware +-------------------------------------- + +.. code-block:: bash + + $ git clone https://github.com/nxp-imx/imx-atf.git -b v2.6 + $ make PLAT=imx8mn bl31 CROSS_COMPILE=aarch64-linux-gnu- + $ cp build/imx8mn/release/bl31.bin ../ + +Get the DDR firmware +-------------------- + +.. code-block:: bash + + $ wget https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/firmware-imx-8.15.bin + $ chmod +x firmware-imx-8.15.bin + $ ./firmware-imx-8.15 + $ cp firmware-imx-8.15/firmware/ddr/synopsys/lpddr4*.bin . + +Build U-Boot +------------ + +.. code-block:: bash + + $ make imx8mn_beacon_defconfig + $ make CROSS_COMPILE=aarch64-linux-gnu- + +Burn U-Boot to microSD Card +--------------------------- + +.. code-block:: bash + + $ sudo dd if=flash.bin of=/dev/sd[x] bs=1024 seek=32 + +Boot +---- + +Set baseboard DIP switches for micoSD Card: +S17 (1:8): 1100xxxx diff --git a/doc/board/beacon/index.rst b/doc/board/beacon/index.rst index 1fe1046a4ce..bf62b09fbad 100644 --- a/doc/board/beacon/index.rst +++ b/doc/board/beacon/index.rst @@ -7,3 +7,5 @@ Beacon :maxdepth: 2 beacon-imx8mp + beacon-imx8mm + beacon-imx8mn diff --git a/doc/board/gateworks/imx8mm_venice.rst b/doc/board/gateworks/imx8mm_venice.rst index f1e7e499445..ea78dfd7ae6 100644 --- a/doc/board/gateworks/imx8mm_venice.rst +++ b/doc/board/gateworks/imx8mm_venice.rst @@ -47,4 +47,6 @@ Update eMMC => tftpboot $loadaddr flash.bin => setexpr blkcnt $filesize + 0x1ff && setexpr blkcnt $blkcnt / 0x200 - => mmc dev 2 && mmc write $loadaddr 0x42 $blkcnt + => mmc dev 2 0 && mmc write $loadaddr 0x42 $blkcnt # emmc user hw part + => mmc dev 2 1 && mmc write $loadaddr 0x42 $blkcnt # or emmc boot0 hw part + => mmc dev 2 2 && mmc write $loadaddr 0x42 $blkcnt # or emmc boot1 hw part diff --git a/doc/board/gateworks/imx8mn_venice.rst b/doc/board/gateworks/imx8mn_venice.rst index 7ba953a4a85..7015f4ef31c 100644 --- a/doc/board/gateworks/imx8mn_venice.rst +++ b/doc/board/gateworks/imx8mn_venice.rst @@ -47,4 +47,6 @@ Update eMMC => tftpboot $loadaddr flash.bin => setexpr blkcnt $filesize + 0x1ff && setexpr blkcnt $blkcnt / 0x200 - => mmc dev 2 && mmc write $loadaddr 0x40 $blkcnt + => mmc dev 2 0 && mmc write $loadaddr 0x40 $blkcnt # emmc user hw part + => mmc dev 2 1 && mmc write $loadaddr 0 $blkcnt # or emmc boot0 hw part + => mmc dev 2 2 && mmc write $loadaddr 0 $blkcnt # or emmc boot1 hw part diff --git a/doc/board/gateworks/imx8mp_venice.rst b/doc/board/gateworks/imx8mp_venice.rst index 632cd742d1f..a219caadff2 100644 --- a/doc/board/gateworks/imx8mp_venice.rst +++ b/doc/board/gateworks/imx8mp_venice.rst @@ -47,4 +47,6 @@ Update eMMC => tftpboot $loadaddr flash.bin => setexpr blkcnt $filesize + 0x1ff && setexpr blkcnt $blkcnt / 0x200 - => mmc dev 2 && mmc write $loadaddr 0x40 $blkcnt + => mmc dev 2 0 && mmc write $loadaddr 0x40 $blkcnt # emmc user hw part + => mmc dev 2 1 && mmc write $loadaddr 0 $blkcnt # or emmc boot0 hw part + => mmc dev 2 2 && mmc write $loadaddr 0 $blkcnt # or emmc boot1 hw part diff --git a/doc/board/index.rst b/doc/board/index.rst index 9ef25b10915..84aa8c158ab 100644 --- a/doc/board/index.rst +++ b/doc/board/index.rst @@ -32,6 +32,7 @@ Board-specific doc nokia/index nxp/index openpiton/index + phytec/index purism/index qualcomm/index renesas/index @@ -45,6 +46,7 @@ Board-specific doc starfive/index ste/index tbs/index + thead/index ti/index toradex/index variscite/index diff --git a/doc/board/phytec/index.rst b/doc/board/phytec/index.rst new file mode 100644 index 00000000000..a5b442045ed --- /dev/null +++ b/doc/board/phytec/index.rst @@ -0,0 +1,10 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +PHYTEC +====== + +.. toctree:: + :maxdepth: 2 + + phycore-imx8mm + phycore-imx8mp diff --git a/doc/board/phytec/phycore-imx8mm.rst b/doc/board/phytec/phycore-imx8mm.rst new file mode 100644 index 00000000000..e9dc2259907 --- /dev/null +++ b/doc/board/phytec/phycore-imx8mm.rst @@ -0,0 +1,60 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +phyCORE-i.MX 8M Mini +==================== + +The phyCORE-i.MX 8M Mini with 2GB of main memory is supported. + +Quick Start +----------- + +- Build the ARM Trusted firmware binary +- Get ddr firmware +- Build U-Boot +- Boot + +Build the ARM Trusted firmware binary +------------------------------------- + +.. code-block:: bash + + $ git clone https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git + $ cd trusted-firmware-a + $ export CROSS_COMPILE=aarch64-linux-gnu + $ export IMX_BOOT_UART_BASE=0x30880000 + $ make PLAT=imx8mm bl31 + +Get the ddr firmware +-------------------- + +.. code-block:: bash + + $ wget https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/firmware-imx-8.19.bin + $ chmod +x firmware-imx-8.19.bin + $ ./firmware-imx-8.19.bin + +Build U-Boot for SD card +------------------------ + +Copy binaries +^^^^^^^^^^^^^ + +.. code-block:: bash + + $ cp <TF-A dir>/build/imx8mm/release/bl31.bin . + $ cp firmware-imx-8.19/firmware/ddr/synopsys/lpddr4*.bin . + +Build U-Boot +^^^^^^^^^^^^ + +.. code-block:: bash + + $ make phycore-imx8mm_defconfig + $ make flash.bin + +Flash SD card +^^^^^^^^^^^^^ + +.. code-block:: bash + + $ sudo dd if=flash.bin of=/dev/sd[x] bs=1024 seek=33 conv=sync diff --git a/doc/board/phytec/phycore-imx8mp.rst b/doc/board/phytec/phycore-imx8mp.rst new file mode 100644 index 00000000000..fda751aeffb --- /dev/null +++ b/doc/board/phytec/phycore-imx8mp.rst @@ -0,0 +1,60 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +phyCORE-i.MX 8M Plus +==================== + +The phyCORE-i.MX 8M Plus with 2GB of main memory is supported. + +Quick Start +----------- + +- Build the ARM Trusted firmware binary +- Get ddr firmware +- Build U-Boot +- Boot + +Build the ARM Trusted firmware binary +------------------------------------- + +.. code-block:: bash + + $ git clone https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git + $ cd trusted-firmware-a + $ export CROSS_COMPILE=aarch64-linux-gnu + $ export IMX_BOOT_UART_BASE=0x30860000 + $ make PLAT=imx8mp bl31 + +Get the ddr firmware +-------------------- + +.. code-block:: bash + + $ wget https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/firmware-imx-8.19.bin + $ chmod +x firmware-imx-8.19.bin + $ ./firmware-imx-8.19.bin + +Build U-Boot for SD card +------------------------ + +Copy binaries +^^^^^^^^^^^^^ + +.. code-block:: bash + + $ cp <TF-A dir>/build/imx8mp/release/bl31.bin . + $ cp firmware-imx-8.19/firmware/ddr/synopsys/lpddr4*.bin . + +Build U-Boot +^^^^^^^^^^^^ + +.. code-block:: bash + + $ make phycore-imx8mp_defconfig + $ make flash.bin + +Flash SD card +^^^^^^^^^^^^^ + +.. code-block:: bash + + $ sudo dd if=flash.bin of=/dev/sd[x] bs=1024 seek=32 conv=sync diff --git a/doc/board/starfive/visionfive2.rst b/doc/board/starfive/visionfive2.rst index 4d43ac9729c..951e0d80fb9 100644 --- a/doc/board/starfive/visionfive2.rst +++ b/doc/board/starfive/visionfive2.rst @@ -62,7 +62,7 @@ Now build the U-Boot SPL and U-Boot proper .. code-block:: console cd <U-Boot-dir> - make starfive_visionfive2_13b_defconfig + make starfive_visionfive2_defconfig make OPENSBI=$(opensbi_dir)/opensbi/build/platform/generic/firmware/fw_dynamic.bin This will generate spl/u-boot-spl.bin and FIT image (u-boot.itb) @@ -118,7 +118,7 @@ Program the SD card sudo cp u-boot.itb /mnt/ sudo cp Image.gz /mnt/ sudo cp initramfs.cpio.gz /mnt/ - sudo cp jh7110-starfive-visionfive-2-v1.3b.dtb /mnt/ + sudo cp jh7110-starfive-visionfive-2.dtb /mnt/ sudo umount /mnt Booting @@ -264,7 +264,7 @@ Sample boot log from StarFive VisionFive2 board StarFive #fatload mmc 1:3 ${kernel_addr_r} Image.gz 6429424 bytes read in 394 ms (15.6 MiB/s) - StarFive #fatload mmc 1:3 ${fdt_addr_r} jh7110-starfive-visionfive-2-v1.3b.dtb + StarFive #fatload mmc 1:3 ${fdt_addr_r} jh7110-starfive-visionfive-2.dtb 11285 bytes read in 5 ms (2.2 MiB/s) StarFive #fatload mmc 1:3 ${ramdisk_addr_r} initramfs.cpio.gz 152848495 bytes read in 9271 ms (15.7 MiB/s) diff --git a/doc/board/thead/index.rst b/doc/board/thead/index.rst new file mode 100644 index 00000000000..41566d3a368 --- /dev/null +++ b/doc/board/thead/index.rst @@ -0,0 +1,9 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +T-HEAD +======== + +.. toctree:: + :maxdepth: 1 + + lpi4a diff --git a/doc/board/thead/lpi4a.rst b/doc/board/thead/lpi4a.rst new file mode 100644 index 00000000000..e395c6ae12c --- /dev/null +++ b/doc/board/thead/lpi4a.rst @@ -0,0 +1,129 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Sipeed's Lichee PI 4A based on T-HEAD TH1520 SoC +================================================ + +The LicheePi4A is a high-performance RISC-V SBC based on TH1520(4xC910@1.85GHz), +comes with 4/8/16 GB RAM, and up to 128GB eMMC, and rich peripherals. + + - SoC T-HEAD TH1520 SoC + - System Memory 4GB, 8GB, or 16GB LPDDR4X + - Storage eMMC flash with 8/32/128 GB + - external microSD slot + - Networking 2x Gigabit Ethernet + - WiFi+BT + - Display HDMI2.0, 4-lane MIPI DSI + - Camera 4-lane MIPI CSI + 2x2-lane MIPI CSI + - Audio Onboard Speaker, 2xMEMS MIC, 3.5mm headphone jack + - USB 4xUSB3.0 Type-A, 1xUSB2.0 Type-C + - GPIO 2x10Pin breakout, UART/IIC/SPI + - Power DC 12V/2A, POE 5V/2.4A, USB Type-C 5V/2A + +TH1520 RISC-V SoC +----------------- + +The TH1520 SoC consist of quad-core RISC-V Xuantie C910 (RV64GCV) processor, +Xuantie C906 audio DSP, low power Xuantie E902 core, it also integrate +Imagination GPU for graphics, and 4 TOPS NPU for AI acceleration. + +Mainline support +---------------- + +The support for following drivers are already enabled: + +1. ns16550 UART Driver. + +Building +~~~~~~~~ + +1. Add the RISC-V toolchain to your PATH. +2. Setup ARCH & cross compilation environment variable: + +.. code-block:: none + + export CROSS_COMPILE=<riscv64 toolchain prefix> + +The U-Boot is capable of running in M-Mode, so we can directly build it. + +.. code-block:: console + + cd <U-Boot-dir> + make th1520_lpi4a_defconfig + make + +This will generate u-boot-dtb.bin + +Booting +~~~~~~~ + +Currently, we rely on vendor u-boot to initialize the clock, pinctrl subsystem, +and chain load the mainline u-boot image either via tftp or emmc storage, +then bootup from it. + +Sample boot log from Lichee PI 4A board via tftp +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: none + + brom_ver 8 + [APP][E] protocol_connect failed, exit. + + U-Boot SPL 2020.01-00016-g8c870a6be8 (May 20 2023 - 01:04:49 +0000) + FM[1] lpddr4x dualrank freq=3733 64bit dbi_off=n sdram init + ddr initialized, jump to uboot + image has no header + + + U-Boot 2020.01-00016-g8c870a6be8 (May 20 2023 - 01:04:49 +0000) + + CPU: rv64imafdcvsu + Model: T-HEAD c910 light + DRAM: 8 GiB + C910 CPU FREQ: 750MHz + AHB2_CPUSYS_HCLK FREQ: 250MHz + AHB3_CPUSYS_PCLK FREQ: 125MHz + PERISYS_AHB_HCLK FREQ: 250MHz + PERISYS_APB_PCLK FREQ: 62MHz + GMAC PLL POSTDIV FREQ: 1000MHZ + DPU0 PLL POSTDIV FREQ: 1188MHZ + DPU1 PLL POSTDIV FREQ: 1188MHZ + MMC: sdhci@ffe7080000: 0, sd@ffe7090000: 1 + Loading Environment from MMC... OK + Error reading output register + Warning: cannot get lcd-en GPIO + LCD panel cannot be found : -121 + splash screen startup cost 16 ms + In: serial + Out: serial + Err: serial + Net: + Warning: ethernet@ffe7070000 using MAC address from ROM + eth0: ethernet@ffe7070000ethernet@ffe7070000:0 is connected to ethernet@ffe7070000. Reconnecting to ethernet@ffe7060000 + + Warning: ethernet@ffe7060000 (eth1) using random MAC address - 42:25:d4:16:5f:fc + , eth1: ethernet@ffe7060000 + Hit any key to stop autoboot: 2 + ethernet@ffe7060000 Waiting for PHY auto negotiation to complete.. done + Speed: 1000, full duplex + Using ethernet@ffe7070000 device + TFTP from server 192.168.8.50; our IP address is 192.168.8.45 + Filename 'u-boot-dtb.bin'. + Load address: 0x1c00000 + Loading: * ######################### + 8 MiB/s + done + Bytes transferred = 376686 (5bf6e hex) + ## Starting application at 0x01C00000 ... + + U-Boot 2023.07-rc2-00004-g1befbe31c1 (May 23 2023 - 18:40:01 +0800) + + CPU: rv64imafdc + Model: Sipeed Lichee Pi 4A + DRAM: 8 GiB + Core: 13 devices, 6 uclasses, devicetree: separate + Loading Environment from <NULL>... OK + In: serial@ffe7014000 + Out: serial@ffe7014000 + Err: serial@ffe7014000 + Model: Sipeed Lichee Pi 4A + LPI4A=> diff --git a/doc/develop/expo.rst b/doc/develop/expo.rst index 32dd7f09030..2ac4af232da 100644 --- a/doc/develop/expo.rst +++ b/doc/develop/expo.rst @@ -85,6 +85,9 @@ or even the IDs of objects. Programmatic creation of many items in a loop can be handled by allocating space in the enum for a maximum number of items, then adding the loop count to the enum values to obtain unique IDs. +Where dynamic IDs are need, use expo_set_dynamic_start() to set the start value, +so that they are allocated above the starting (enum) IDs. + All text strings are stored in a structure attached to the expo, referenced by a text ID. This makes it easier at some point to implement multiple languages or to support Unicode strings. @@ -97,10 +100,13 @@ objects first, then create the menu item, passing in the relevant IDs. Creating an expo ---------------- -To create an expo, use `expo_new()` followed by `scene_new()` to create a scene. -Then add objects to the scene, using functions like `scene_txt_str()` and -`scene_menu()`. For every menu item, add text and image objects, then create -the menu item with `scene_menuitem()`, referring to those objects. +To create an expo programmatically, use `expo_new()` followed by `scene_new()` +to create a scene. Then add objects to the scene, using functions like +`scene_txt_str()` and `scene_menu()`. For every menu item, add text and image +objects, then create the menu item with `scene_menuitem()`, referring to those +objects. + +To create an expo using a description file, see :ref:`expo_format` below. Layout ------ @@ -152,8 +158,287 @@ such as scanning devices for more bootflows. Themes ------ -Expo does not itself support themes. The bootflow_menu implement supposed a -basic theme, applying font sizes to the various text objects in the expo. +Expo supports simple themes, for setting the font size, for example. Use the +expo_apply_theme() function to load a theme, passing a node with the required +properties: + +font-size + Font size to use for all text (type: u32) + +menu-inset + Number of pixels to inset the menu on the sides and top (type: u32) + +menuitem-gap-y + Number of pixels between menu items + +Pop-up mode +----------- + +Expos support two modes. The simple mode is used for selecting from a single +menu, e.g. when choosing with OS to boot. In this mode the menu items are shown +in a list (label, > pointer, key and description) and can be chosen using arrow +keys and enter:: + + U-Boot Boot Menu + + UP and DOWN to choose, ENTER to select + + mmc1 > 0 Fedora-Workstation-armhfp-31-1.9 + mmc3 1 Armbian + +The popup mode allows multiple menus to be present in a scene. Each is shown +just as its title and label, as with the `CPU Speed` and `AC Power` menus here:: + + Test Configuration + + + CPU Speed <2 GHz> (highlighted) + + AC Power Always Off + + + UP and DOWN to choose, ENTER to select + + +.. _expo_format: + +Expo Format +----------- + +It can be tedious to create a complex expo using code. Expo supports a +data-driven approach, where the expo description is in a devicetree file. This +makes it easier and faster to create and edit the description. An expo builder +is provided to convert this format into an expo structure. + +Layout of the expo scenes is handled automatically, based on a set of simple +rules. The :doc:`../usage/cmd/cedit` can be used to load a configuration +and create an expo from it. + +Top-level node +~~~~~~~~~~~~~~ + +The top-level node has the following properties: + +dynamic-start + type: u32, optional + + Specifies the start of the dynamically allocated objects. This results in + a call to expo_set_dynamic_start(). + +The top-level node has the following subnodes: + +scenes + Specifies the scenes in the expo, each one being a subnode + +strings + Specifies the strings in the expo, each one being a subnode + +`scenes` node +~~~~~~~~~~~~~ + +Contains a list of scene subnodes. The name of each subnode is passed as the +name to `scene_new()`. + +`strings` node +~~~~~~~~~~~~~~ + +Contains a list of string subnodes. The name of each subnode is ignored. + +`strings` subnodes +~~~~~~~~~~~~~~~~~~ + +Each subnode defines a string which can be used by scenes and objects. Each +string has an ID number which is used to refer to it. + +The `strings` subnodes have the following properties: + +id + type: u32, required + + Specifies the ID number for the string. + +value: + type: string, required + + Specifies the string text. For now only a single value is supported. Future + work may add support for multiple languages by using a value for each + language. + +Scene nodes (`scenes` subnodes) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Each subnode of the `scenes` node contains a scene description. + +Most properties can use either a string or a string ID. For example, a `title` +property can be used to provide the title for a menu; alternatively a `title-id` +property can provide the string ID of the title. If both are present, the +ID takes preference, except that if a string with that ID does not exist, it +falls back to using the string from the property (`title` in this example). The +description below shows these are alternative properties with the same +description. + +The scene nodes have the following properties: + +id + type: u32, required + + Specifies the ID number for the string. + +title / title-id + type: string / u32, required + + Specifies the title of the scene. This is shown at the top of the scene. + +prompt / prompt-id + type: string / u32, required + + Specifies a prompt for the scene. This is shown at the bottom of the scene. + +The scene nodes have a subnode for each object in the scene. + +Object nodes +~~~~~~~~~~~~ + +The object-node name is used as the name of the object, e.g. when calling +`scene_menu()` to create a menu. + +Object nodes have the following common properties: + +type + type: string, required + + Specifies the type of the object. Valid types are: + + "menu" + Menu containing items which can be selected by the user + +id + type: u32, required + + Specifies the ID of the object. This is used when referring to the object. + + +Menu nodes have the following additional properties: + +title / title-id + type: string / u32, required + + Specifies the title of the menu. This is shown to the left of the area for + this menu. + +item-id + type: u32 list, required + + Specifies the ID for each menu item. These are used for checking which item + has been selected. + +item-label / item-label-id + type: string list / u32 list, required + + Specifies the label for each item in the menu. These are shown to the user. + In 'popup' mode these form the items in the menu. + +key-label / key-label-id + type: string list / u32 list, optional + + Specifies the key for each item in the menu. These are currently only + intended for use in simple mode. + +desc-label / desc-label-id + type: string list / u32 list, optional + + Specifies the description for each item in the menu. These are currently + only intended for use in simple mode. + + +Expo layout +~~~~~~~~~~~ + +The `expo_arrange()` function can be called to arrange the expo objects in a +suitable manner. For each scene it puts the title at the top, the prompt at the +bottom and the objects in order from top to bottom. + +Expo format example +~~~~~~~~~~~~~~~~~~~ + +This example shows an expo with a single scene consisting of two menus. The +scene title is specified using a string from the strings table, but all other +strings are provided inline in the nodes where they are used. + +:: + + #define ID_PROMPT 1 + #define ID_SCENE1 2 + #define ID_SCENE1_TITLE 3 + + #define ID_CPU_SPEED 4 + #define ID_CPU_SPEED_TITLE 5 + #define ID_CPU_SPEED_1 6 + #define ID_CPU_SPEED_2 7 + #define ID_CPU_SPEED_3 8 + + #define ID_POWER_LOSS 9 + #define ID_AC_OFF 10 + #define ID_AC_ON 11 + #define ID_AC_MEMORY 12 + + #define ID_DYNAMIC_START 13 + + &cedit { + dynamic-start = <ID_DYNAMIC_START>; + + scenes { + main { + id = <ID_SCENE1>; + + /* value refers to the matching id in /strings */ + title-id = <ID_SCENE1_TITLE>; + + /* simple string is used as it is */ + prompt = "UP and DOWN to choose, ENTER to select"; + + /* defines a menu within the scene */ + cpu-speed { + type = "menu"; + id = <ID_CPU_SPEED>; + + /* + * has both string and ID. The string is ignored + * if the ID is present and points to a string + */ + title = "CPU speed"; + title-id = <ID_CPU_SPEED_TITLE>; + + /* menu items as simple strings */ + item-label = "2 GHz", "2.5 GHz", "3 GHz"; + + /* IDs for the menu items */ + item-id = <ID_CPU_SPEED_1 ID_CPU_SPEED_2 + ID_CPU_SPEED_3>; + }; + + power-loss { + type = "menu"; + id = <ID_POWER_LOSS>; + + title = "AC Power"; + item-label = "Always Off", "Always On", + "Memory"; + + item-id = <ID_AC_OFF ID_AC_ON ID_AC_MEMORY>; + }; + }; + }; + + strings { + title { + id = <ID_SCENE1_TITLE>; + value = "Test Configuration"; + value-es = "configuración de prueba"; + }; + }; + }; + API documentation ----------------- @@ -166,12 +451,10 @@ Future ideas Some ideas for future work: - Default menu item and a timeout -- Higher-level / automatic / more flexible layout of objects - Image formats other than BMP - Use of ANSI sequences to control a serial terminal - Colour selection -- Better support for handling lots of settings, e.g. with multiple menus and - radio/option widgets +- Support for more widgets, e.g. text, numeric, radio/option - Mouse support - Integrate Nuklear, NxWidgets or some other library for a richer UI - Optimise rendering by only updating the display with changes since last render @@ -179,10 +462,10 @@ Some ideas for future work: - Add a Kconfig option to drop the names to save code / data space - Add a Kconfig option to disable vidconsole support to save code / data space - Support both graphical and text menus at the same time on different devices -- Implement proper measurement of object bounding boxes, to permit more exact - layout. This would tidy up the layout when Truetype is not used - Support unicode - Support curses for proper serial-terminal menus +- Add support for large menus which need to scroll +- Add support for reading and writing configuration settings with cedit .. Simon Glass <sjg@chromium.org> .. 7-Oct-22 diff --git a/doc/develop/uefi/uefi.rst b/doc/develop/uefi/uefi.rst index 6626ceec52b..a7a41f2facf 100644 --- a/doc/develop/uefi/uefi.rst +++ b/doc/develop/uefi/uefi.rst @@ -552,6 +552,13 @@ update using a capsule file with --fw-version of 5, the update will fail. When the --fw-version in the capsule file is updated, lowest-supported-version in the dtb might be updated accordingly. +If user needs to enforce anti-rollback to any older version, +the lowest-supported-version property in dtb must be always updated manually. + +Note that the lowest-supported-version property specified in U-Boot's control +device tree can be changed by U-Boot fdt command. +Secure systems should not enable this command. + To insert the lowest supported version into a dtb .. code-block:: console diff --git a/doc/device-tree-bindings/config.txt b/doc/device-tree-bindings/config.txt index 3151778b2c9..f50c68bbdc3 100644 --- a/doc/device-tree-bindings/config.txt +++ b/doc/device-tree-bindings/config.txt @@ -76,6 +76,8 @@ u-boot,mmc-env-partition (int) precedence. In that case, only if the partition is not found, mmc-env-offset* will be tried. + Note that CONFIG_ENV_MMC_PARTITION overrides this device-tree setting. + u-boot,no-apm-finalize (bool) For x86 devices running on coreboot, this tells U-Boot not to lock down the Intel Management Engine (ME) registers. This allows U-Boot to diff --git a/doc/device-tree-bindings/spi/brcm,bcm63xx-hsspi.yaml b/doc/device-tree-bindings/spi/brcm,bcm63xx-hsspi.yaml new file mode 100644 index 00000000000..6554978583f --- /dev/null +++ b/doc/device-tree-bindings/spi/brcm,bcm63xx-hsspi.yaml @@ -0,0 +1,134 @@ +# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/spi/brcm,bcm63xx-hsspi.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Broadcom Broadband SoC High Speed SPI controller + +maintainers: + - William Zhang <william.zhang@broadcom.com> + - Kursad Oney <kursad.oney@broadcom.com> + - Jonas Gorski <jonas.gorski@gmail.com> + +description: | + Broadcom Broadband SoC supports High Speed SPI master controller since the + early MIPS based chips such as BCM6328 and BCM63268. This initial rev 1.0 + controller was carried over to recent ARM based chips, such as BCM63138, + BCM4908 and BCM6858. The old MIPS based chip should continue to use the + brcm,bcm6328-hsspi compatible string. The recent ARM based chip is required to + use the brcm,bcmbca-hsspi-v1.0 as part of its compatible string list as + defined below to match the specific chip along with ip revision info. + + This rev 1.0 controller has a limitation that can not keep the chip select line + active between the SPI transfers within the same SPI message. This can + terminate the transaction to some SPI devices prematurely. The issue can be + worked around by either the controller's prepend mode or using the dummy chip + select workaround. Driver automatically picks the suitable mode based on + transfer type so it is transparent to the user. + + The newer SoCs such as BCM6756, BCM4912 and BCM6855 include an updated SPI + controller rev 1.1 that add the capability to allow the driver to control chip + select explicitly. This solves the issue in the old controller. + +properties: + compatible: + oneOf: + - const: brcm,bcm6328-hsspi + - items: + - enum: + - brcm,bcm47622-hsspi + - brcm,bcm4908-hsspi + - brcm,bcm63138-hsspi + - brcm,bcm63146-hsspi + - brcm,bcm63148-hsspi + - brcm,bcm63158-hsspi + - brcm,bcm63178-hsspi + - brcm,bcm6846-hsspi + - brcm,bcm6856-hsspi + - brcm,bcm6858-hsspi + - brcm,bcm6878-hsspi + - const: brcm,bcmbca-hsspi-v1.0 + - items: + - enum: + - brcm,bcm4912-hsspi + - brcm,bcm6756-hsspi + - brcm,bcm6813-hsspi + - brcm,bcm6855-hsspi + - const: brcm,bcmbca-hsspi-v1.1 + + reg: + items: + - description: main registers + - description: miscellaneous control registers + minItems: 1 + + reg-names: + items: + - const: hsspi + - const: spim-ctrl + minItems: 1 + + clocks: + items: + - description: SPI master reference clock + - description: SPI master pll clock + + clock-names: + items: + - const: hsspi + - const: pll + + interrupts: + maxItems: 1 + +required: + - compatible + - reg + - clocks + - clock-names + - interrupts + +allOf: + - $ref: spi-controller.yaml# + - if: + properties: + compatible: + contains: + enum: + - brcm,bcm6328-hsspi + - brcm,bcmbca-hsspi-v1.0 + then: + properties: + reg: + maxItems: 1 + reg-names: + maxItems: 1 + else: + properties: + reg: + minItems: 2 + maxItems: 2 + reg-names: + minItems: 2 + maxItems: 2 + required: + - reg-names + +unevaluatedProperties: false + +examples: + - | + #include <dt-bindings/interrupt-controller/arm-gic.h> + spi@ff801000 { + compatible = "brcm,bcm6756-hsspi", "brcm,bcmbca-hsspi-v1.1"; + reg = <0xff801000 0x1000>, + <0xff802610 0x4>; + reg-names = "hsspi", "spim-ctrl"; + interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&hsspi>, <&hsspi_pll>; + clock-names = "hsspi", "pll"; + num-cs = <8>; + #address-cells = <1>; + #size-cells = <0>; + }; diff --git a/doc/device-tree-bindings/spi/soft-spi.txt b/doc/device-tree-bindings/spi/soft-spi.txt index dfb50664732..bdf7e86befb 100644 --- a/doc/device-tree-bindings/spi/soft-spi.txt +++ b/doc/device-tree-bindings/spi/soft-spi.txt @@ -9,10 +9,10 @@ The soft SPI node requires the following properties: Mandatory properties: compatible: "spi-gpio" cs-gpios: GPIOs to use for SPI chip select (output) -gpio-sck: GPIO to use for SPI clock (output) +sck-gpios: GPIO to use for SPI clock (output) And at least one of: -gpio-mosi: GPIO to use for SPI MOSI line (output) -gpio-miso: GPIO to use for SPI MISO line (input) +mosi-gpios: GPIO to use for SPI MOSI line (output) +miso-gpios: GPIO to use for SPI MISO line (input) Optional propertie: spi-delay-us: Number of microseconds of delay between each CS transition @@ -27,9 +27,9 @@ Example: soft-spi { compatible = "spi-gpio"; cs-gpios = <&gpio 235 0>; /* Y43 */ - gpio-sck = <&gpio 225 0>; /* Y31 */ - gpio-mosi = <&gpio 227 0>; /* Y33 */ - gpio-miso = <&gpio 224 0>; /* Y30 */ + sck-gpios = <&gpio 225 0>; /* Y31 */ + mosi-gpios = <&gpio 227 0>; /* Y33 */ + miso-gpios = <&gpio 224 0>; /* Y30 */ spi-delay-us = <1>; #address-cells = <1>; #size-cells = <0>; diff --git a/doc/imx/habv4/csf_examples/mx8m/csf.sh b/doc/imx/habv4/csf_examples/mx8m/csf.sh index 5b383fa982f..d87015f6c4e 100644 --- a/doc/imx/habv4/csf_examples/mx8m/csf.sh +++ b/doc/imx/habv4/csf_examples/mx8m/csf.sh @@ -22,6 +22,27 @@ cp doc/imx/habv4/csf_examples/mx8m/csf_spl.txt csf_spl.tmp cp doc/imx/habv4/csf_examples/mx8m/csf_fit.txt csf_fit.tmp +# update File Paths from env vars +if ! [ -r $CSF_KEY ]; then + echo "Error: \$CSF_KEY not found" + exit 1 +fi +if ! [ -r $IMG_KEY ]; then + echo "Error: \$IMG_KEY not found" + exit 1 +fi +if ! [ -r $SRK_TABLE ]; then + echo "Error: \$SRK_TABLE not found" + exit 1 +fi +sed -i "s:\$CSF_KEY:$CSF_KEY:" csf_spl.tmp +sed -i "s:\$IMG_KEY:$IMG_KEY:" csf_spl.tmp +sed -i "s:\$SRK_TABLE:$SRK_TABLE:" csf_spl.tmp +sed -i "s:\$CSF_KEY:$CSF_KEY:" csf_fit.tmp +sed -i "s:\$IMG_KEY:$IMG_KEY:" csf_fit.tmp +sed -i "s:\$SRK_TABLE:$SRK_TABLE:" csf_fit.tmp + +# update SPL Blocks spl_block_base=$(printf "0x%x" $(( $(sed -n "/CONFIG_SPL_TEXT_BASE=/ s@.*=@@p" .config) - 0x40)) ) spl_block_size=$(printf "0x%x" $(stat -tc %s u-boot-spl-ddr.bin)) sed -i "/Blocks = / s@.*@ Blocks = $spl_block_base 0x0 $spl_block_size \"flash.bin\"@" csf_spl.tmp diff --git a/doc/imx/habv4/csf_examples/mx8m/csf_fit.txt b/doc/imx/habv4/csf_examples/mx8m/csf_fit.txt index bbb82f69448..3d79edf2813 100644 --- a/doc/imx/habv4/csf_examples/mx8m/csf_fit.txt +++ b/doc/imx/habv4/csf_examples/mx8m/csf_fit.txt @@ -7,21 +7,21 @@ Signature Format = CMS [Install SRK] - # FIXME: Adjust path here - File = "/path/to/cst-3.3.1/crts/SRK_1_2_3_4_table.bin" + # SRK_TABLE is full path to SRK_1_2_3_4_table.bin + File = "$SRK_TABLE" Source index = 0 [Install CSFK] - # FIXME: Adjust path here - File = "/path/to/cst-3.3.1/crts/CSF1_1_sha256_4096_65537_v3_usr_crt.pem" + # CSF_KEY is full path to CSF1_1_sha256_4096_65537_v3_usr_crt.pem + File = "$CSF_KEY" [Authenticate CSF] [Install Key] Verification index = 0 Target Index = 2 - # FIXME: Adjust path here - File = "/path/to/cst-3.3.1/crts/IMG1_1_sha256_4096_65537_v3_usr_crt.pem" + # IMG_KEY is full path to IMG1_1_sha256_4096_65537_v3_usr_crt.pem + File = "$IMG_KEY" [Authenticate Data] Verification index = 2 diff --git a/doc/imx/habv4/csf_examples/mx8m/csf_spl.txt b/doc/imx/habv4/csf_examples/mx8m/csf_spl.txt index 00e34f6b1b9..88fa420a5fa 100644 --- a/doc/imx/habv4/csf_examples/mx8m/csf_spl.txt +++ b/doc/imx/habv4/csf_examples/mx8m/csf_spl.txt @@ -7,13 +7,13 @@ Signature Format = CMS [Install SRK] - # FIXME: Adjust path here - File = "/path/to/cst-3.3.1/crts/SRK_1_2_3_4_table.bin" + # SRK_TABLE is full path to SRK_1_2_3_4_table.bin + File = "$SRK_TABLE" Source index = 0 [Install CSFK] - # FIXME: Adjust path here - File = "/path/to/cst-3.3.1/crts/CSF1_1_sha256_4096_65537_v3_usr_crt.pem" + # CSF_KEY is full path to CSF1_1_sha256_4096_65537_v3_usr_crt.pem + File = "$CSF_KEY" [Authenticate CSF] @@ -24,8 +24,8 @@ [Install Key] Verification index = 0 Target Index = 2 - # FIXME: Adjust path here - File = "/path/to/cst-3.3.1/crts/IMG1_1_sha256_4096_65537_v3_usr_crt.pem" + # IMG_KEY is full path to IMG1_1_sha256_4096_65537_v3_usr_crt.pem + File = "$IMG_KEY" [Authenticate Data] Verification index = 2 diff --git a/doc/imx/habv4/guides/mx8m_spl_secure_boot.txt b/doc/imx/habv4/guides/mx8m_spl_secure_boot.txt index e79726bf2c5..e16e5410bd9 100644 --- a/doc/imx/habv4/guides/mx8m_spl_secure_boot.txt +++ b/doc/imx/habv4/guides/mx8m_spl_secure_boot.txt @@ -207,6 +207,16 @@ dd if=csf_fit.bin of=flash.bin bs=1 seek=${csf_block_offset} conv=notrunc ``` The entire script is available in doc/imx/habv4/csf_examples/mx8m/csf.sh +and can be used as follows to modify flash.bin to be signed +(adjust paths as needed): +``` +export CST_DIR=/usr/src/cst-3.3.1/ +export CSF_KEY=$CST_DIR/crts/CSF1_1_sha256_4096_65537_v3_usr_crt.pem +export IMG_KEY=$CST_DIR/crts/IMG1_1_sha256_4096_65537_v3_usr_crt.pem +export SRK_TABLE=$CST_DIR/crts/SRK_1_2_3_4_table.bin +export PATH=$CST_DIR/linux64/bin:$PATH +/bin/sh doc/imx/habv4/csf_examples/mx8m/csf.sh +``` 1.4 Closing the device ----------------------- diff --git a/doc/usage/cmd/cedit.rst b/doc/usage/cmd/cedit.rst new file mode 100644 index 00000000000..8e1110c7c77 --- /dev/null +++ b/doc/usage/cmd/cedit.rst @@ -0,0 +1,31 @@ +.. SPDX-License-Identifier: GPL-2.0+: + +cedit command +============= + +Synopis +------- + +:: + + cedit load <interface> <dev[:part]> <filename> + cedit run + +Description +----------- + +The *cedit* command is used to load a configuration-editor description and allow +the user to interact with it. + +It makes use of the expo subsystem. + +The description is in the form of a devicetree file, as documented at +:ref:`expo_format`. + +Example +------- + +:: + + => cedit load hostfs - fred.dtb + => cedit run diff --git a/doc/usage/index.rst b/doc/usage/index.rst index 388e59f1733..f2ffd2787aa 100644 --- a/doc/usage/index.rst +++ b/doc/usage/index.rst @@ -39,6 +39,7 @@ Shell commands cmd/bootz cmd/cat cmd/cbsysinfo + cmd/cedit cmd/cls cmd/cmp cmd/coninfo diff --git a/drivers/adc/Kconfig b/drivers/adc/Kconfig index e719c38bb31..4336732dee5 100644 --- a/drivers/adc/Kconfig +++ b/drivers/adc/Kconfig @@ -63,3 +63,11 @@ config STM32_ADC - core driver to deal with common resources - child driver to deal with individual ADC resources (declare ADC device and associated channels, start/stop conversions) + +config ADC_IMX93 + bool "Enable NXP IMX93 ADC driver" + help + This enables basic driver for NXP IMX93 ADC. + It provides: + - 4 analog input channels + - 12-bit resolution diff --git a/drivers/adc/Makefile b/drivers/adc/Makefile index c1387f3a346..5336c820973 100644 --- a/drivers/adc/Makefile +++ b/drivers/adc/Makefile @@ -10,3 +10,4 @@ obj-$(CONFIG_ADC_SANDBOX) += sandbox.o obj-$(CONFIG_SARADC_ROCKCHIP) += rockchip-saradc.o obj-$(CONFIG_SARADC_MESON) += meson-saradc.o obj-$(CONFIG_STM32_ADC) += stm32-adc.o stm32-adc-core.o +obj-$(CONFIG_ADC_IMX93) += imx93-adc.o diff --git a/drivers/adc/imx93-adc.c b/drivers/adc/imx93-adc.c new file mode 100644 index 00000000000..41d04e0426c --- /dev/null +++ b/drivers/adc/imx93-adc.c @@ -0,0 +1,290 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2023 ASEM Srl + * Author: Luca Ellero <l.ellero@asem.it> + * + * Originally based on NXP linux-imx kernel v5.15 drivers/iio/adc/imx93_adc.c + */ + +#include <common.h> +#include <errno.h> +#include <dm.h> +#include <linux/bitfield.h> +#include <linux/iopoll.h> +#include <clk.h> +#include <adc.h> + +#define IMX93_ADC_MCR 0x00 +#define IMX93_ADC_MSR 0x04 +#define IMX93_ADC_ISR 0x10 +#define IMX93_ADC_IMR 0x20 +#define IMX93_ADC_CIMR0 0x24 +#define IMX93_ADC_CTR0 0x94 +#define IMX93_ADC_NCMR0 0xA4 +#define IMX93_ADC_PCDR0 0x100 +#define IMX93_ADC_PCDR1 0x104 +#define IMX93_ADC_PCDR2 0x108 +#define IMX93_ADC_PCDR3 0x10c +#define IMX93_ADC_PCDR4 0x110 +#define IMX93_ADC_PCDR5 0x114 +#define IMX93_ADC_PCDR6 0x118 +#define IMX93_ADC_PCDR7 0x11c +#define IMX93_ADC_CALSTAT 0x39C + +#define IMX93_ADC_MCR_MODE_MASK BIT(29) +#define IMX93_ADC_MCR_NSTART_MASK BIT(24) +#define IMX93_ADC_MCR_CALSTART_MASK BIT(14) +#define IMX93_ADC_MCR_ADCLKSE_MASK BIT(8) +#define IMX93_ADC_MCR_PWDN_MASK BIT(0) + +#define IMX93_ADC_MSR_CALFAIL_MASK BIT(30) +#define IMX93_ADC_MSR_CALBUSY_MASK BIT(29) +#define IMX93_ADC_MSR_ADCSTATUS_MASK GENMASK(2, 0) + +#define IMX93_ADC_ISR_EOC_MASK BIT(1) + +#define IMX93_ADC_IMR_EOC_MASK BIT(1) +#define IMX93_ADC_IMR_ECH_MASK BIT(0) + +#define IMX93_ADC_PCDR_CDATA_MASK GENMASK(11, 0) + +#define IDLE 0 +#define POWER_DOWN 1 +#define WAIT_STATE 2 +#define BUSY_IN_CALIBRATION 3 +#define SAMPLE 4 +#define CONVERSION 6 + +#define IMX93_ADC_MAX_CHANNEL 3 +#define IMX93_ADC_DAT_MASK 0xfff +#define IMX93_ADC_TIMEOUT 100000 + +struct imx93_adc_priv { + int active_channel; + void __iomem *regs; + struct clk ipg_clk; +}; + +static void imx93_adc_power_down(struct imx93_adc_priv *adc) +{ + u32 mcr, msr; + int ret; + + mcr = readl(adc->regs + IMX93_ADC_MCR); + mcr |= FIELD_PREP(IMX93_ADC_MCR_PWDN_MASK, 1); + writel(mcr, adc->regs + IMX93_ADC_MCR); + + ret = readl_poll_timeout(adc->regs + IMX93_ADC_MSR, msr, + ((msr & IMX93_ADC_MSR_ADCSTATUS_MASK) == POWER_DOWN), 50); + if (ret == -ETIMEDOUT) + pr_warn("ADC not in power down mode, current MSR: %x\n", msr); +} + +static void imx93_adc_power_up(struct imx93_adc_priv *adc) +{ + u32 mcr; + + /* bring ADC out of power down state, in idle state */ + mcr = readl(adc->regs + IMX93_ADC_MCR); + mcr &= ~FIELD_PREP(IMX93_ADC_MCR_PWDN_MASK, 1); + writel(mcr, adc->regs + IMX93_ADC_MCR); +} + +static void imx93_adc_config_ad_clk(struct imx93_adc_priv *adc) +{ + u32 mcr; + + /* put adc in power down mode */ + imx93_adc_power_down(adc); + + /* config the AD_CLK equal to bus clock */ + mcr = readl(adc->regs + IMX93_ADC_MCR); + mcr |= FIELD_PREP(IMX93_ADC_MCR_ADCLKSE_MASK, 1); + writel(mcr, adc->regs + IMX93_ADC_MCR); + + /* bring ADC out of power down state, in idle state */ + imx93_adc_power_up(adc); +} + +static int imx93_adc_calibration(struct imx93_adc_priv *adc) +{ + u32 mcr, msr; + int ret; + + /* make sure ADC is in power down mode */ + imx93_adc_power_down(adc); + + /* config SAR controller operating clock */ + mcr = readl(adc->regs + IMX93_ADC_MCR); + mcr &= ~FIELD_PREP(IMX93_ADC_MCR_ADCLKSE_MASK, 1); + writel(mcr, adc->regs + IMX93_ADC_MCR); + + /* bring ADC out of power down state */ + imx93_adc_power_up(adc); + + /* + * we use the default TSAMP/NRSMPL/AVGEN in MCR, + * can add the setting of these bit if need + */ + + /* run calibration */ + mcr = readl(adc->regs + IMX93_ADC_MCR); + mcr |= FIELD_PREP(IMX93_ADC_MCR_CALSTART_MASK, 1); + writel(mcr, adc->regs + IMX93_ADC_MCR); + + /* wait calibration to be finished */ + ret = readl_poll_timeout(adc->regs + IMX93_ADC_MSR, msr, + !(msr & IMX93_ADC_MSR_CALBUSY_MASK), 2000000); + if (ret == -ETIMEDOUT) { + pr_warn("ADC calibration timeout\n"); + return ret; + } + + /* check whether calbration is successful or not */ + msr = readl(adc->regs + IMX93_ADC_MSR); + if (msr & IMX93_ADC_MSR_CALFAIL_MASK) { + pr_warn("ADC calibration failed!\n"); + return -EAGAIN; + } + + return 0; +} + +static int imx93_adc_channel_data(struct udevice *dev, int channel, + unsigned int *data) +{ + struct imx93_adc_priv *adc = dev_get_priv(dev); + u32 isr, pcda; + int ret; + + if (channel != adc->active_channel) { + pr_err("Requested channel is not active!\n"); + return -EINVAL; + } + + ret = readl_poll_timeout(adc->regs + IMX93_ADC_ISR, isr, + (isr & IMX93_ADC_ISR_EOC_MASK), IMX93_ADC_TIMEOUT); + + /* clear interrupts */ + writel(isr, adc->regs + IMX93_ADC_ISR); + + if (ret == -ETIMEDOUT) { + pr_warn("ADC conversion timeout!\n"); + return ret; + } + + pcda = readl(adc->regs + IMX93_ADC_PCDR0 + channel * 4); + + *data = FIELD_GET(IMX93_ADC_PCDR_CDATA_MASK, pcda); + + return 0; +} + +static int imx93_adc_start_channel(struct udevice *dev, int channel) +{ + struct imx93_adc_priv *adc = dev_get_priv(dev); + u32 imr, mcr; + + /* config channel mask register */ + writel(1 << channel, adc->regs + IMX93_ADC_NCMR0); + + /* config interrupt mask */ + imr = FIELD_PREP(IMX93_ADC_IMR_EOC_MASK, 1); + writel(imr, adc->regs + IMX93_ADC_IMR); + writel(1 << channel, adc->regs + IMX93_ADC_CIMR0); + + /* config one-shot mode */ + mcr = readl(adc->regs + IMX93_ADC_MCR); + mcr &= ~FIELD_PREP(IMX93_ADC_MCR_MODE_MASK, 1); + writel(mcr, adc->regs + IMX93_ADC_MCR); + + /* start normal conversion */ + mcr = readl(adc->regs + IMX93_ADC_MCR); + mcr |= FIELD_PREP(IMX93_ADC_MCR_NSTART_MASK, 1); + writel(mcr, adc->regs + IMX93_ADC_MCR); + + adc->active_channel = channel; + + return 0; +} + +static int imx93_adc_stop(struct udevice *dev) +{ + struct imx93_adc_priv *adc = dev_get_priv(dev); + + imx93_adc_power_down(adc); + + adc->active_channel = -1; + + return 0; +} + +static int imx93_adc_probe(struct udevice *dev) +{ + struct imx93_adc_priv *adc = dev_get_priv(dev); + unsigned int ret; + + ret = imx93_adc_calibration(adc); + if (ret < 0) + return ret; + + imx93_adc_config_ad_clk(adc); + + adc->active_channel = -1; + + return 0; +} + +static int imx93_adc_of_to_plat(struct udevice *dev) +{ + struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev); + struct imx93_adc_priv *adc = dev_get_priv(dev); + unsigned int ret; + + adc->regs = dev_read_addr_ptr(dev); + if (adc->regs == (struct imx93_adc *)FDT_ADDR_T_NONE) { + pr_err("Dev: %s - can't get address!", dev->name); + return -ENODATA; + } + + ret = clk_get_by_name(dev, "ipg", &adc->ipg_clk); + if (ret < 0) { + pr_err("Can't get ADC ipg clk: %d\n", ret); + return ret; + } + ret = clk_enable(&adc->ipg_clk); + if(ret) { + pr_err("Can't enable ADC ipg clk: %d\n", ret); + return ret; + } + + uc_pdata->data_mask = IMX93_ADC_DAT_MASK; + uc_pdata->data_format = ADC_DATA_FORMAT_BIN; + uc_pdata->data_timeout_us = IMX93_ADC_TIMEOUT; + + /* Mask available channel bits: [0:3] */ + uc_pdata->channel_mask = (2 << IMX93_ADC_MAX_CHANNEL) - 1; + + return 0; +} + +static const struct adc_ops imx93_adc_ops = { + .start_channel = imx93_adc_start_channel, + .channel_data = imx93_adc_channel_data, + .stop = imx93_adc_stop, +}; + +static const struct udevice_id imx93_adc_ids[] = { + { .compatible = "nxp,imx93-adc" }, + { } +}; + +U_BOOT_DRIVER(imx93_adc) = { + .name = "imx93-adc", + .id = UCLASS_ADC, + .of_match = imx93_adc_ids, + .ops = &imx93_adc_ops, + .probe = imx93_adc_probe, + .of_to_plat = imx93_adc_of_to_plat, + .priv_auto = sizeof(struct imx93_adc_priv), +}; diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 3ad5af964f3..29859cdfa15 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -160,6 +160,7 @@ config SANDBOX_CLK_CCF config CLK_SCMI bool "Enable SCMI clock driver" + depends on CLK depends on SCMI_FIRMWARE help Enable this option if you want to support clock devices exposed diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c index 09bef596f22..a21a3ce34bb 100644 --- a/drivers/clk/imx/clk-imx8mp.c +++ b/drivers/clk/imx/clk-imx8mp.c @@ -337,7 +337,8 @@ static int imx8mp_clk_probe(struct udevice *dev) clk_dm(IMX8MP_CLK_UART2_ROOT, imx_clk_gate4("uart2_root_clk", "uart2", base + 0x44a0, 0)); clk_dm(IMX8MP_CLK_UART3_ROOT, imx_clk_gate4("uart3_root_clk", "uart3", base + 0x44b0, 0)); clk_dm(IMX8MP_CLK_UART4_ROOT, imx_clk_gate4("uart4_root_clk", "uart4", base + 0x44c0, 0)); - clk_dm(IMX8MP_CLK_USB_ROOT, imx_clk_gate4("usb_root_clk", "usb_core_ref", base + 0x44d0, 0)); + clk_dm(IMX8MP_CLK_USB_ROOT, imx_clk_gate2("usb_root_clk", "hsio_axi", base + 0x44d0, 0)); + clk_dm(IMX8MP_CLK_USB_SUSP, imx_clk_gate2("usb_suspend_clk", "clock-osc-24m", base + 0x44d0, 0)); clk_dm(IMX8MP_CLK_USB_PHY_ROOT, imx_clk_gate4("usb_phy_root_clk", "usb_phy_ref", base + 0x44f0, 0)); clk_dm(IMX8MP_CLK_USDHC1_ROOT, imx_clk_gate4("usdhc1_root_clk", "usdhc1", base + 0x4510, 0)); clk_dm(IMX8MP_CLK_USDHC2_ROOT, imx_clk_gate4("usdhc2_root_clk", "usdhc2", base + 0x4520, 0)); diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index ec574c44607..8df16e56af5 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -12,6 +12,7 @@ #include <fdt_support.h> #include <log.h> #include <malloc.h> +#include <of_live.h> #include <linux/libfdt.h> #include <dm/of_access.h> #include <dm/of_addr.h> @@ -51,6 +52,20 @@ static oftree oftree_ensure(void *fdt) oftree tree; int i; + if (of_live_active()) { + struct device_node *root; + int ret; + + ret = unflatten_device_tree(fdt, &root); + if (ret) { + log_err("Failed to create live tree: err=%d\n", ret); + return oftree_null(); + } + tree = oftree_from_np(root); + + return tree; + } + if (gd->flags & GD_FLG_RELOC) { i = oftree_find(fdt); if (i == -1) { @@ -67,7 +82,7 @@ static oftree oftree_ensure(void *fdt) } } else { if (fdt != gd->fdt_blob) { - log_debug("Cannot only access control FDT before relocation\n"); + log_debug("Only the control FDT can be accessed before relocation\n"); return oftree_null(); } } @@ -77,6 +92,12 @@ static oftree oftree_ensure(void *fdt) return tree; } +void oftree_dispose(oftree tree) +{ + if (of_live_active()) + of_live_free(tree.np); +} + void *ofnode_lookup_fdt(ofnode node) { if (gd->flags & GD_FLG_RELOC) { @@ -133,6 +154,10 @@ oftree oftree_from_fdt(void *fdt) if (CONFIG_IS_ENABLED(OFNODE_MULTI_TREE)) return oftree_ensure(fdt); +#ifdef OF_CHECKS + if (of_live_active()) + return oftree_null(); +#endif tree.fdt = fdt; return tree; diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c b/drivers/firmware/scmi/scmi_agent-uclass.c index 54d563d929b..02de692d66f 100644 --- a/drivers/firmware/scmi/scmi_agent-uclass.c +++ b/drivers/firmware/scmi/scmi_agent-uclass.c @@ -46,7 +46,7 @@ int scmi_to_linux_errno(s32 scmi_code) for (n = 0; n < ARRAY_SIZE(scmi_linux_errmap); n++) if (scmi_code == scmi_linux_errmap[n].scmi) - return scmi_linux_errmap[1].errno; + return scmi_linux_errmap[n].errno; return -EPROTO; } diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c index 712119c3415..31027f3d990 100644 --- a/drivers/gpio/gpio-uclass.c +++ b/drivers/gpio/gpio-uclass.c @@ -1474,7 +1474,7 @@ static int gpio_post_bind(struct udevice *dev) } #endif - if (CONFIG_IS_ENABLED(GPIO_HOG)) { + if (CONFIG_IS_ENABLED(GPIO_HOG) && dev_has_ofnode(dev)) { struct udevice *child; ofnode node; diff --git a/drivers/led/led_bcm6753.c b/drivers/led/led_bcm6753.c index 88b650cbfca..2466d930116 100644 --- a/drivers/led/led_bcm6753.c +++ b/drivers/led/led_bcm6753.c @@ -174,57 +174,65 @@ static const struct led_ops bcm6753_led_ops = { static int bcm6753_led_probe(struct udevice *dev) { - struct led_uc_plat *uc_plat = dev_get_uclass_plat(dev); - - /* Top-level LED node */ - if (!uc_plat->label) { - void __iomem *regs; - u32 set_bits = 0; - - regs = dev_remap_addr(dev); - if (!regs) - return -EINVAL; - - if (dev_read_bool(dev, "brcm,serial-led-msb-first")) - set_bits |= CLED_CTRL_SERIAL_LED_MSB_FIRST; - if (dev_read_bool(dev, "brcm,serial-led-en-pol")) - set_bits |= CLED_CTRL_SERIAL_LED_EN_POL; - if (dev_read_bool(dev, "brcm,serial-led-clk-pol")) - set_bits |= CLED_CTRL_SERIAL_LED_CLK_POL; - if (dev_read_bool(dev, "brcm,serial-led-data-ppol")) - set_bits |= CLED_CTRL_SERIAL_LED_DATA_PPOL; - - clrsetbits_32(regs + CLED_CTRL_REG, CLED_CTRL_MASK, set_bits); - } else { - struct bcm6753_led_priv *priv = dev_get_priv(dev); - void __iomem *regs; - unsigned int pin; - - regs = dev_remap_addr(dev_get_parent(dev)); - if (!regs) - return -EINVAL; - - pin = dev_read_u32_default(dev, "reg", LEDS_MAX); - if (pin >= LEDS_MAX) - return -EINVAL; - - priv->regs = regs; - priv->pin = pin; - - /* this led is managed by software */ - clrbits_32(regs + CLED_HW_LED_EN_REG, 1 << pin); - - /* configure the polarity */ - if (dev_read_bool(dev, "active-low")) - clrbits_32(regs + CLED_PLED_OP_PPOL_REG, 1 << pin); - else - setbits_32(regs + CLED_PLED_OP_PPOL_REG, 1 << pin); - } + struct bcm6753_led_priv *priv = dev_get_priv(dev); + void __iomem *regs; + unsigned int pin; + + regs = dev_remap_addr(dev_get_parent(dev)); + if (!regs) + return -EINVAL; + + pin = dev_read_u32_default(dev, "reg", LEDS_MAX); + if (pin >= LEDS_MAX) + return -EINVAL; + + priv->regs = regs; + priv->pin = pin; + + /* this led is managed by software */ + clrbits_32(regs + CLED_HW_LED_EN_REG, 1 << pin); + + /* configure the polarity */ + if (dev_read_bool(dev, "active-low")) + clrbits_32(regs + CLED_PLED_OP_PPOL_REG, 1 << pin); + else + setbits_32(regs + CLED_PLED_OP_PPOL_REG, 1 << pin); return 0; } -static int bcm6753_led_bind(struct udevice *parent) +U_BOOT_DRIVER(bcm6753_led) = { + .name = "bcm6753-led", + .id = UCLASS_LED, + .probe = bcm6753_led_probe, + .priv_auto = sizeof(struct bcm6753_led_priv), + .ops = &bcm6753_led_ops, +}; + +static int bcm6753_led_wrap_probe(struct udevice *dev) +{ + void __iomem *regs; + u32 set_bits = 0; + + regs = dev_remap_addr(dev); + if (!regs) + return -EINVAL; + + if (dev_read_bool(dev, "brcm,serial-led-msb-first")) + set_bits |= CLED_CTRL_SERIAL_LED_MSB_FIRST; + if (dev_read_bool(dev, "brcm,serial-led-en-pol")) + set_bits |= CLED_CTRL_SERIAL_LED_EN_POL; + if (dev_read_bool(dev, "brcm,serial-led-clk-pol")) + set_bits |= CLED_CTRL_SERIAL_LED_CLK_POL; + if (dev_read_bool(dev, "brcm,serial-led-data-ppol")) + set_bits |= CLED_CTRL_SERIAL_LED_DATA_PPOL; + + clrsetbits_32(regs + CLED_CTRL_REG, CLED_CTRL_MASK, set_bits); + + return 0; +} + +static int bcm6753_led_wrap_bind(struct udevice *parent) { ofnode node; @@ -247,12 +255,10 @@ static const struct udevice_id bcm6753_led_ids[] = { { /* sentinel */ } }; -U_BOOT_DRIVER(bcm6753_led) = { - .name = "bcm6753-led", - .id = UCLASS_LED, +U_BOOT_DRIVER(bcm6753_led_wrap) = { + .name = "bcm6753_led_wrap", + .id = UCLASS_NOP, .of_match = bcm6753_led_ids, - .bind = bcm6753_led_bind, - .probe = bcm6753_led_probe, - .priv_auto = sizeof(struct bcm6753_led_priv), - .ops = &bcm6753_led_ops, + .probe = bcm6753_led_wrap_probe, + .bind = bcm6753_led_wrap_bind, }; diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 04460f1acb2..b9f5c7a37ae 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -364,8 +364,8 @@ config NPCM_OTP To compile this driver as a module, choose M here: the module will be called npcm_otp. -config IMX_SENTINEL - bool "Enable i.MX Sentinel MU driver and API" +config IMX_ELE + bool "Enable i.MX EdgeLock Enclave MU driver and API" depends on MISC && (ARCH_IMX9 || ARCH_IMX8ULP) help If you say Y here to enable Message Unit driver to work with diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 52aed096021..fd8805f34bd 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -47,7 +47,7 @@ obj-$(CONFIG_SANDBOX) += irq_sandbox.o irq_sandbox_test.o obj-$(CONFIG_$(SPL_)I2C_EEPROM) += i2c_eeprom.o obj-$(CONFIG_IHS_FPGA) += ihs_fpga.o obj-$(CONFIG_IMX8) += imx8/ -obj-$(CONFIG_IMX_SENTINEL) += sentinel/ +obj-$(CONFIG_IMX_ELE) += imx_ele/ obj-$(CONFIG_LED_STATUS) += status_led.o obj-$(CONFIG_LED_STATUS_GPIO) += gpio_led.o obj-$(CONFIG_MPC83XX_SERDES) += mpc83xx_serdes.o diff --git a/drivers/misc/imx8/scu_api.c b/drivers/misc/imx8/scu_api.c index dfede7f1d5f..3e3002ba6df 100644 --- a/drivers/misc/imx8/scu_api.c +++ b/drivers/misc/imx8/scu_api.c @@ -481,6 +481,22 @@ int sc_misc_get_temp(sc_ipc_t ipc, sc_rsrc_t resource, sc_misc_temp_t temp, return 0; } +void sc_misc_get_button_status(sc_ipc_t ipc, sc_bool_t *status) +{ + struct sc_rpc_msg_s msg; + struct udevice *dev = gd->arch.scu_dev; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SIZE(&msg) = 1U; + RPC_SVC(&msg) = (u8)(SC_RPC_SVC_MISC); + RPC_FUNC(&msg) = (u8)(MISC_FUNC_GET_BUTTON_STATUS); + + misc_call(dev, SC_FALSE, &msg, 1U, &msg, 1U); + + if (status) + *status = (sc_bool_t)(!!(RPC_U8(&msg, 0U))); +} + /* RM */ sc_bool_t sc_rm_is_memreg_owned(sc_ipc_t ipc, sc_rm_mr_t mr) { @@ -851,6 +867,21 @@ int sc_pm_cpu_start(sc_ipc_t ipc, sc_rsrc_t resource, sc_bool_t enable, return ret; } +void sc_pm_reboot(sc_ipc_t ipc, sc_pm_reset_type_t type) +{ + struct udevice *dev = gd->arch.scu_dev; + struct sc_rpc_msg_s msg; + int size = sizeof(struct sc_rpc_msg_s); + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (u8)(SC_RPC_SVC_PM); + RPC_FUNC(&msg) = (u8)(PM_FUNC_REBOOT); + RPC_U8(&msg, 0U) = (u8)(type); + RPC_SIZE(&msg) = 2U; + + misc_call(dev, SC_TRUE, &msg, size, &msg, size); +} + int sc_pm_get_resource_power_mode(sc_ipc_t ipc, sc_rsrc_t resource, sc_pm_power_mode_t *mode) { @@ -877,6 +908,28 @@ int sc_pm_get_resource_power_mode(sc_ipc_t ipc, sc_rsrc_t resource, return ret; } +int sc_timer_set_wdog_window(sc_ipc_t ipc, sc_timer_wdog_time_t window) +{ + struct udevice *dev = gd->arch.scu_dev; + struct sc_rpc_msg_s msg; + int size = sizeof(struct sc_rpc_msg_s); + int ret; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SIZE(&msg) = 2U; + RPC_SVC(&msg) = (u8)(SC_RPC_SVC_TIMER); + RPC_FUNC(&msg) = (u8)(TIMER_FUNC_SET_WDOG_WINDOW); + + RPC_U32(&msg, 0U) = (u32)(window); + + ret = misc_call(dev, SC_FALSE, &msg, size, &msg, size); + if (ret) + printf("%s: window:%u: res:%d\n", + __func__, window, RPC_R8(&msg)); + + return ret; +} + int sc_seco_authenticate(sc_ipc_t ipc, sc_seco_auth_cmd_t cmd, sc_faddr_t addr) { @@ -974,6 +1027,31 @@ void sc_seco_build_info(sc_ipc_t ipc, u32 *version, u32 *commit) *commit = RPC_U32(&msg, 4U); } +int sc_seco_v2x_build_info(sc_ipc_t ipc, u32 *version, u32 *commit) +{ + struct udevice *dev = gd->arch.scu_dev; + struct sc_rpc_msg_s msg; + int size = sizeof(struct sc_rpc_msg_s); + int ret; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SIZE(&msg) = 1U; + RPC_SVC(&msg) = (u8)(SC_RPC_SVC_SECO); + RPC_FUNC(&msg) = (u8)(SECO_FUNC_V2X_BUILD_INFO); + + ret = misc_call(dev, SC_FALSE, &msg, size, &msg, size); + if (ret) + printf("%s: res:%d\n", __func__, RPC_R8(&msg)); + + if (version) + *version = RPC_U32(&msg, 0U); + + if (commit) + *commit = RPC_U32(&msg, 4U); + + return ret; +} + int sc_seco_get_event(sc_ipc_t ipc, u8 idx, u32 *event) { struct udevice *dev = gd->arch.scu_dev; diff --git a/drivers/misc/sentinel/Makefile b/drivers/misc/imx_ele/Makefile index 446154cb201..f8d8c55f983 100644 --- a/drivers/misc/sentinel/Makefile +++ b/drivers/misc/imx_ele/Makefile @@ -1,4 +1,4 @@ # SPDX-License-Identifier: GPL-2.0+ -obj-y += s400_api.o s4mu.o +obj-y += ele_api.o ele_mu.o obj-$(CONFIG_CMD_FUSE) += fuse.o diff --git a/drivers/misc/sentinel/s400_api.c b/drivers/misc/imx_ele/ele_api.c index 6c0d0b3f18a..0c017734a49 100644 --- a/drivers/misc/sentinel/s400_api.c +++ b/drivers/misc/imx_ele/ele_api.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright 2020 NXP + * Copyright 2020, 2023 NXP * */ @@ -9,25 +9,37 @@ #include <malloc.h> #include <asm/io.h> #include <dm.h> -#include <asm/mach-imx/s400_api.h> +#include <asm/mach-imx/ele_api.h> #include <misc.h> DECLARE_GLOBAL_DATA_PTR; -int ahab_release_rdc(u8 core_id, u8 xrdc, u32 *response) +static u32 compute_crc(const struct ele_msg *msg) { - struct udevice *dev = gd->arch.s400_dev; - int size = sizeof(struct sentinel_msg); - struct sentinel_msg msg; + u32 crc = 0; + size_t i = 0; + u32 *data = (u32 *)msg; + + for (i = 0; i < (msg->size - 1); i++) + crc ^= data[i]; + + return crc; +} + +int ele_release_rdc(u8 core_id, u8 xrdc, u32 *response) +{ + struct udevice *dev = gd->arch.ele_dev; + int size = sizeof(struct ele_msg); + struct ele_msg msg; int ret; if (!dev) { - printf("s400 dev is not initialized\n"); + printf("ele dev is not initialized\n"); return -ENODEV; } - msg.version = AHAB_VERSION; - msg.tag = AHAB_CMD_TAG; + msg.version = ELE_VERSION; + msg.tag = ELE_CMD_TAG; msg.size = 2; msg.command = ELE_RELEASE_RDC_REQ; switch (xrdc) { @@ -59,20 +71,20 @@ int ahab_release_rdc(u8 core_id, u8 xrdc, u32 *response) return ret; } -int ahab_auth_oem_ctnr(ulong ctnr_addr, u32 *response) +int ele_auth_oem_ctnr(ulong ctnr_addr, u32 *response) { - struct udevice *dev = gd->arch.s400_dev; - int size = sizeof(struct sentinel_msg); - struct sentinel_msg msg; + struct udevice *dev = gd->arch.ele_dev; + int size = sizeof(struct ele_msg); + struct ele_msg msg; int ret; if (!dev) { - printf("s400 dev is not initialized\n"); + printf("ele dev is not initialized\n"); return -ENODEV; } - msg.version = AHAB_VERSION; - msg.tag = AHAB_CMD_TAG; + msg.version = ELE_VERSION; + msg.tag = ELE_CMD_TAG; msg.size = 3; msg.command = ELE_OEM_CNTN_AUTH_REQ; msg.data[0] = upper_32_bits(ctnr_addr); @@ -89,20 +101,20 @@ int ahab_auth_oem_ctnr(ulong ctnr_addr, u32 *response) return ret; } -int ahab_release_container(u32 *response) +int ele_release_container(u32 *response) { - struct udevice *dev = gd->arch.s400_dev; - int size = sizeof(struct sentinel_msg); - struct sentinel_msg msg; + struct udevice *dev = gd->arch.ele_dev; + int size = sizeof(struct ele_msg); + struct ele_msg msg; int ret; if (!dev) { - printf("s400 dev is not initialized\n"); + printf("ele dev is not initialized\n"); return -ENODEV; } - msg.version = AHAB_VERSION; - msg.tag = AHAB_CMD_TAG; + msg.version = ELE_VERSION; + msg.tag = ELE_CMD_TAG; msg.size = 1; msg.command = ELE_RELEASE_CONTAINER_REQ; @@ -117,20 +129,20 @@ int ahab_release_container(u32 *response) return ret; } -int ahab_verify_image(u32 img_id, u32 *response) +int ele_verify_image(u32 img_id, u32 *response) { - struct udevice *dev = gd->arch.s400_dev; - int size = sizeof(struct sentinel_msg); - struct sentinel_msg msg; + struct udevice *dev = gd->arch.ele_dev; + int size = sizeof(struct ele_msg); + struct ele_msg msg; int ret; if (!dev) { - printf("s400 dev is not initialized\n"); + printf("ele dev is not initialized\n"); return -ENODEV; } - msg.version = AHAB_VERSION; - msg.tag = AHAB_CMD_TAG; + msg.version = ELE_VERSION; + msg.tag = ELE_CMD_TAG; msg.size = 2; msg.command = ELE_VERIFY_IMAGE_REQ; msg.data[0] = 1 << img_id; @@ -146,20 +158,20 @@ int ahab_verify_image(u32 img_id, u32 *response) return ret; } -int ahab_forward_lifecycle(u16 life_cycle, u32 *response) +int ele_forward_lifecycle(u16 life_cycle, u32 *response) { - struct udevice *dev = gd->arch.s400_dev; - int size = sizeof(struct sentinel_msg); - struct sentinel_msg msg; + struct udevice *dev = gd->arch.ele_dev; + int size = sizeof(struct ele_msg); + struct ele_msg msg; int ret; if (!dev) { - printf("s400 dev is not initialized\n"); + printf("ele dev is not initialized\n"); return -ENODEV; } - msg.version = AHAB_VERSION; - msg.tag = AHAB_CMD_TAG; + msg.version = ELE_VERSION; + msg.tag = ELE_CMD_TAG; msg.size = 2; msg.command = ELE_FWD_LIFECYCLE_UP_REQ; msg.data[0] = life_cycle; @@ -175,15 +187,15 @@ int ahab_forward_lifecycle(u16 life_cycle, u32 *response) return ret; } -int ahab_read_common_fuse(u16 fuse_id, u32 *fuse_words, u32 fuse_num, u32 *response) +int ele_read_common_fuse(u16 fuse_id, u32 *fuse_words, u32 fuse_num, u32 *response) { - struct udevice *dev = gd->arch.s400_dev; - int size = sizeof(struct sentinel_msg); - struct sentinel_msg msg; + struct udevice *dev = gd->arch.ele_dev; + int size = sizeof(struct ele_msg); + struct ele_msg msg; int ret; if (!dev) { - printf("s400 dev is not initialized\n"); + printf("ele dev is not initialized\n"); return -ENODEV; } @@ -198,8 +210,8 @@ int ahab_read_common_fuse(u16 fuse_id, u32 *fuse_words, u32 fuse_num, u32 *respo return -EINVAL; } - msg.version = AHAB_VERSION; - msg.tag = AHAB_CMD_TAG; + msg.version = ELE_VERSION; + msg.tag = ELE_CMD_TAG; msg.size = 2; msg.command = ELE_READ_FUSE_REQ; msg.data[0] = fuse_id; @@ -223,20 +235,20 @@ int ahab_read_common_fuse(u16 fuse_id, u32 *fuse_words, u32 fuse_num, u32 *respo return ret; } -int ahab_write_fuse(u16 fuse_id, u32 fuse_val, bool lock, u32 *response) +int ele_write_fuse(u16 fuse_id, u32 fuse_val, bool lock, u32 *response) { - struct udevice *dev = gd->arch.s400_dev; - int size = sizeof(struct sentinel_msg); - struct sentinel_msg msg; + struct udevice *dev = gd->arch.ele_dev; + int size = sizeof(struct ele_msg); + struct ele_msg msg; int ret; if (!dev) { - printf("s400 dev is not initialized\n"); + printf("ele dev is not initialized\n"); return -ENODEV; } - msg.version = AHAB_VERSION; - msg.tag = AHAB_CMD_TAG; + msg.version = ELE_VERSION; + msg.tag = ELE_CMD_TAG; msg.size = 3; msg.command = ELE_WRITE_FUSE_REQ; msg.data[0] = (32 << 16) | (fuse_id << 5); @@ -256,20 +268,20 @@ int ahab_write_fuse(u16 fuse_id, u32 fuse_val, bool lock, u32 *response) return ret; } -int ahab_release_caam(u32 core_did, u32 *response) +int ele_release_caam(u32 core_did, u32 *response) { - struct udevice *dev = gd->arch.s400_dev; - int size = sizeof(struct sentinel_msg); - struct sentinel_msg msg; + struct udevice *dev = gd->arch.ele_dev; + int size = sizeof(struct ele_msg); + struct ele_msg msg; int ret; if (!dev) { - printf("s400 dev is not initialized\n"); + printf("ele dev is not initialized\n"); return -ENODEV; } - msg.version = AHAB_VERSION; - msg.tag = AHAB_CMD_TAG; + msg.version = ELE_VERSION; + msg.tag = ELE_CMD_TAG; msg.size = 2; msg.command = ELE_RELEASE_CAAM_REQ; msg.data[0] = core_did; @@ -285,15 +297,15 @@ int ahab_release_caam(u32 core_did, u32 *response) return ret; } -int ahab_get_fw_version(u32 *fw_version, u32 *sha1, u32 *response) +int ele_get_fw_version(u32 *fw_version, u32 *sha1, u32 *response) { - struct udevice *dev = gd->arch.s400_dev; - int size = sizeof(struct sentinel_msg); - struct sentinel_msg msg; + struct udevice *dev = gd->arch.ele_dev; + int size = sizeof(struct ele_msg); + struct ele_msg msg; int ret; if (!dev) { - printf("s400 dev is not initialized\n"); + printf("ele dev is not initialized\n"); return -ENODEV; } @@ -307,8 +319,8 @@ int ahab_get_fw_version(u32 *fw_version, u32 *sha1, u32 *response) return -EINVAL; } - msg.version = AHAB_VERSION; - msg.tag = AHAB_CMD_TAG; + msg.version = ELE_VERSION; + msg.tag = ELE_CMD_TAG; msg.size = 1; msg.command = ELE_GET_FW_VERSION_REQ; @@ -326,20 +338,20 @@ int ahab_get_fw_version(u32 *fw_version, u32 *sha1, u32 *response) return ret; } -int ahab_dump_buffer(u32 *buffer, u32 buffer_length) +int ele_dump_buffer(u32 *buffer, u32 buffer_length) { - struct udevice *dev = gd->arch.s400_dev; - int size = sizeof(struct sentinel_msg); - struct sentinel_msg msg; + struct udevice *dev = gd->arch.ele_dev; + int size = sizeof(struct ele_msg); + struct ele_msg msg; int ret, i = 0; if (!dev) { - printf("s400 dev is not initialized\n"); + printf("ele dev is not initialized\n"); return -ENODEV; } - msg.version = AHAB_VERSION; - msg.tag = AHAB_CMD_TAG; + msg.version = ELE_VERSION; + msg.tag = ELE_CMD_TAG; msg.size = 1; msg.command = ELE_DUMP_DEBUG_BUFFER_REQ; @@ -360,25 +372,25 @@ int ahab_dump_buffer(u32 *buffer, u32 buffer_length) return i; } -int ahab_get_info(struct sentinel_get_info_data *info, u32 *response) +int ele_get_info(struct ele_get_info_data *info, u32 *response) { - struct udevice *dev = gd->arch.s400_dev; - int size = sizeof(struct sentinel_msg); - struct sentinel_msg msg; + struct udevice *dev = gd->arch.ele_dev; + int size = sizeof(struct ele_msg); + struct ele_msg msg; int ret; if (!dev) { - printf("s400 dev is not initialized\n"); + printf("ele dev is not initialized\n"); return -ENODEV; } - msg.version = AHAB_VERSION; - msg.tag = AHAB_CMD_TAG; + msg.version = ELE_VERSION; + msg.tag = ELE_CMD_TAG; msg.size = 4; msg.command = ELE_GET_INFO_REQ; msg.data[0] = upper_32_bits((ulong)info); msg.data[1] = lower_32_bits((ulong)info); - msg.data[2] = sizeof(struct sentinel_get_info_data); + msg.data[2] = sizeof(struct ele_get_info_data); ret = misc_call(dev, false, &msg, size, &msg, size); if (ret) @@ -391,20 +403,20 @@ int ahab_get_info(struct sentinel_get_info_data *info, u32 *response) return ret; } -int ahab_get_fw_status(u32 *status, u32 *response) +int ele_get_fw_status(u32 *status, u32 *response) { - struct udevice *dev = gd->arch.s400_dev; - int size = sizeof(struct sentinel_msg); - struct sentinel_msg msg; + struct udevice *dev = gd->arch.ele_dev; + int size = sizeof(struct ele_msg); + struct ele_msg msg; int ret; if (!dev) { - printf("s400 dev is not initialized\n"); + printf("ele dev is not initialized\n"); return -ENODEV; } - msg.version = AHAB_VERSION; - msg.tag = AHAB_CMD_TAG; + msg.version = ELE_VERSION; + msg.tag = ELE_CMD_TAG; msg.size = 1; msg.command = ELE_GET_FW_STATUS_REQ; @@ -421,20 +433,20 @@ int ahab_get_fw_status(u32 *status, u32 *response) return ret; } -int ahab_release_m33_trout(void) +int ele_release_m33_trout(void) { - struct udevice *dev = gd->arch.s400_dev; - int size = sizeof(struct sentinel_msg); - struct sentinel_msg msg; + struct udevice *dev = gd->arch.ele_dev; + int size = sizeof(struct ele_msg); + struct ele_msg msg; int ret; if (!dev) { - printf("s400 dev is not initialized\n"); + printf("ele dev is not initialized\n"); return -ENODEV; } - msg.version = AHAB_VERSION; - msg.tag = AHAB_CMD_TAG; + msg.version = ELE_VERSION; + msg.tag = ELE_CMD_TAG; msg.size = 1; msg.command = ELE_ENABLE_RTC_REQ; @@ -446,16 +458,16 @@ int ahab_release_m33_trout(void) return ret; } -int ahab_get_events(u32 *events, u32 *events_cnt, u32 *response) +int ele_get_events(u32 *events, u32 *events_cnt, u32 *response) { - struct udevice *dev = gd->arch.s400_dev; - int size = sizeof(struct sentinel_msg); - struct sentinel_msg msg; + struct udevice *dev = gd->arch.ele_dev; + int size = sizeof(struct ele_msg); + struct ele_msg msg; int ret, i = 0; u32 actual_events; if (!dev) { - printf("s400 dev is not initialized\n"); + printf("ele dev is not initialized\n"); return -ENODEV; } @@ -464,8 +476,8 @@ int ahab_get_events(u32 *events, u32 *events_cnt, u32 *response) return -EINVAL; } - msg.version = AHAB_VERSION; - msg.tag = AHAB_CMD_TAG; + msg.version = ELE_VERSION; + msg.tag = ELE_CMD_TAG; msg.size = 1; msg.command = ELE_GET_EVENTS_REQ; @@ -490,3 +502,122 @@ int ahab_get_events(u32 *events, u32 *events_cnt, u32 *response) return ret; } + +int ele_start_rng(void) +{ + struct udevice *dev = gd->arch.ele_dev; + int size = sizeof(struct ele_msg); + struct ele_msg msg; + int ret; + + if (!dev) { + printf("ele dev is not initialized\n"); + return -ENODEV; + } + + msg.version = ELE_VERSION; + msg.tag = ELE_CMD_TAG; + msg.size = 1; + msg.command = ELE_START_RNG; + + ret = misc_call(dev, false, &msg, size, &msg, size); + if (ret) + printf("Error: %s: ret %d, response 0x%x\n", + __func__, ret, msg.data[0]); + + return ret; +} + +int ele_write_secure_fuse(ulong signed_msg_blk, u32 *response) +{ + struct udevice *dev = gd->arch.ele_dev; + int size = sizeof(struct ele_msg); + struct ele_msg msg; + int ret; + + if (!dev) { + printf("ele dev is not initialized\n"); + return -ENODEV; + } + + msg.version = ELE_VERSION; + msg.tag = ELE_CMD_TAG; + msg.size = 3; + msg.command = ELE_WRITE_SECURE_FUSE_REQ; + + msg.data[0] = upper_32_bits(signed_msg_blk); + msg.data[1] = lower_32_bits(signed_msg_blk); + + ret = misc_call(dev, false, &msg, size, &msg, size); + if (ret) + printf("Error: %s: ret %d, response 0x%x, failed fuse row index %u\n", + __func__, ret, msg.data[0], msg.data[1]); + + if (response) + *response = msg.data[0]; + + return ret; +} + +int ele_return_lifecycle_update(ulong signed_msg_blk, u32 *response) +{ + struct udevice *dev = gd->arch.ele_dev; + int size = sizeof(struct ele_msg); + struct ele_msg msg; + int ret; + + if (!dev) { + printf("ele dev is not initialized\n"); + return -ENODEV; + } + + msg.version = ELE_VERSION; + msg.tag = ELE_CMD_TAG; + msg.size = 3; + msg.command = ELE_RET_LIFECYCLE_UP_REQ; + + msg.data[0] = upper_32_bits(signed_msg_blk); + msg.data[1] = lower_32_bits(signed_msg_blk); + + ret = misc_call(dev, false, &msg, size, &msg, size); + if (ret) + printf("Error: %s: ret %d, response 0x%x, failed fuse row index %u\n", + __func__, ret, msg.data[0], msg.data[1]); + + if (response) + *response = msg.data[0]; + + return ret; +} + +int ele_generate_dek_blob(u32 key_id, u32 src_paddr, u32 dst_paddr, u32 max_output_size) +{ + struct udevice *dev = gd->arch.ele_dev; + int size = sizeof(struct ele_msg); + struct ele_msg msg; + int ret; + + if (!dev) { + printf("ele dev is not initialized\n"); + return -ENODEV; + } + + msg.version = ELE_VERSION; + msg.tag = ELE_CMD_TAG; + msg.size = 8; + msg.command = ELE_GENERATE_DEK_BLOB; + msg.data[0] = key_id; + msg.data[1] = 0x0; + msg.data[2] = src_paddr; + msg.data[3] = 0x0; + msg.data[4] = dst_paddr; + msg.data[5] = max_output_size; + msg.data[6] = compute_crc(&msg); + + ret = misc_call(dev, false, &msg, size, &msg, size); + if (ret) + printf("Error: %s: ret 0x%x, response 0x%x\n", + __func__, ret, msg.data[0]); + + return ret; +} diff --git a/drivers/misc/sentinel/s4mu.c b/drivers/misc/imx_ele/ele_mu.c index 794fc40c620..053cdcf0fe0 100644 --- a/drivers/misc/sentinel/s4mu.c +++ b/drivers/misc/imx_ele/ele_mu.c @@ -9,7 +9,7 @@ #include <dm/lists.h> #include <dm/root.h> #include <dm/device-internal.h> -#include <asm/mach-imx/s400_api.h> +#include <asm/mach-imx/ele_api.h> #include <asm/arch/imx-regs.h> #include <linux/iopoll.h> #include <misc.h> @@ -22,7 +22,7 @@ struct imx8ulp_mu { #define MU_SR_TE0_MASK BIT(0) #define MU_SR_RF0_MASK BIT(0) -#define MU_TR_COUNT 4 +#define MU_TR_COUNT 8 #define MU_RR_COUNT 4 void mu_hal_init(ulong base) @@ -42,7 +42,7 @@ int mu_hal_sendmsg(ulong base, u32 reg_index, u32 msg) assert(reg_index < MU_TR_COUNT); - debug("sendmsg sr 0x%x\n", readl(&mu_base->sr)); + debug("sendmsg tsr 0x%x\n", readl(&mu_base->tsr)); /* Wait TX register to be empty. */ ret = readl_poll_timeout(&mu_base->tsr, val, val & mask, 10000); @@ -64,14 +64,24 @@ int mu_hal_receivemsg(ulong base, u32 reg_index, u32 *msg) u32 mask = MU_SR_RF0_MASK << reg_index; u32 val; int ret; + u32 count = 10; - assert(reg_index < MU_TR_COUNT); + assert(reg_index < MU_RR_COUNT); - debug("receivemsg sr 0x%x\n", readl(&mu_base->sr)); + debug("receivemsg rsr 0x%x\n", readl(&mu_base->rsr)); - /* Wait RX register to be full. */ - ret = readl_poll_timeout(&mu_base->rsr, val, val & mask, 10000); - if (ret < 0) { + do { + /* Wait RX register to be full. */ + ret = readl_poll_timeout(&mu_base->rsr, val, val & mask, 1000000); + if (ret < 0) { + count--; + printf("mu receive msg wait %us\n", 10 - count); + } else { + break; + } + } while (count > 0); + + if (count == 0) { debug("%s timeout\n", __func__); return -ETIMEDOUT; } @@ -85,7 +95,7 @@ int mu_hal_receivemsg(ulong base, u32 reg_index, u32 *msg) static int imx8ulp_mu_read(struct mu_type *base, void *data) { - struct sentinel_msg *msg = (struct sentinel_msg *)data; + struct ele_msg *msg = (struct ele_msg *)data; int ret; u8 count = 0; @@ -99,7 +109,7 @@ static int imx8ulp_mu_read(struct mu_type *base, void *data) count++; /* Check size */ - if (msg->size > S400_MAX_MSG) { + if (msg->size > ELE_MAX_MSG) { *((u32 *)msg) = 0; return -EINVAL; } @@ -118,7 +128,7 @@ static int imx8ulp_mu_read(struct mu_type *base, void *data) static int imx8ulp_mu_write(struct mu_type *base, void *data) { - struct sentinel_msg *msg = (struct sentinel_msg *)data; + struct ele_msg *msg = (struct ele_msg *)data; int ret; u8 count = 0; @@ -126,7 +136,7 @@ static int imx8ulp_mu_write(struct mu_type *base, void *data) return -EINVAL; /* Check size */ - if (msg->size > S400_MAX_MSG) + if (msg->size > ELE_MAX_MSG) return -EINVAL; /* Write first word */ @@ -171,7 +181,7 @@ static int imx8ulp_mu_call(struct udevice *dev, int no_resp, void *tx_msg, return ret; } - result = ((struct sentinel_msg *)rx_msg)->data[0]; + result = ((struct ele_msg *)rx_msg)->data[0]; if ((result & 0xff) == 0xd6) return 0; @@ -196,7 +206,7 @@ static int imx8ulp_mu_probe(struct udevice *dev) /* U-Boot not enable interrupts, so need to enable RX interrupts */ mu_hal_init((ulong)priv->base); - gd->arch.s400_dev = dev; + gd->arch.ele_dev = dev; return 0; } diff --git a/drivers/misc/sentinel/fuse.c b/drivers/misc/imx_ele/fuse.c index 99342d33c06..4e4dcb42cdd 100644 --- a/drivers/misc/sentinel/fuse.c +++ b/drivers/misc/imx_ele/fuse.c @@ -10,7 +10,7 @@ #include <asm/arch/sys_proto.h> #include <asm/arch/imx-regs.h> #include <env.h> -#include <asm/mach-imx/s400_api.h> +#include <asm/mach-imx/ele_api.h> #include <asm/global_data.h> DECLARE_GLOBAL_DATA_PTR; @@ -24,11 +24,11 @@ struct fsb_map_entry { bool redundancy; }; -struct s400_map_entry { +struct ele_map_entry { s32 fuse_bank; u32 fuse_words; u32 fuse_offset; - u32 s400_index; + u32 ele_index; }; #if defined(CONFIG_IMX8ULP) @@ -65,7 +65,7 @@ u32 nonecc_fuse_banks[] = { 0, 1, 8, 12, 16, 22, 24, 25, 26, 27, 36, 41, 51, 56 }; -struct s400_map_entry s400_api_mapping_table[] = { +struct ele_map_entry ele_api_mapping_table[] = { { 1, 8 }, /* LOCK */ { 2, 8 }, /* ECID */ { 7, 4, 0, 1 }, /* OTP_UNIQ_ID */ @@ -122,7 +122,7 @@ struct fsb_map_entry fsb_mapping_table[] = { { 63, 8 }, }; -struct s400_map_entry s400_api_mapping_table[] = { +struct ele_map_entry ele_api_mapping_table[] = { { 7, 1, 7, 63 }, { 16, 8, }, { 17, 8, }, @@ -159,18 +159,18 @@ static s32 map_fsb_fuse_index(u32 bank, u32 word, bool *redundancy) return word + word_pos; } -static s32 map_s400_fuse_index(u32 bank, u32 word) +static s32 map_ele_fuse_index(u32 bank, u32 word) { - s32 size = ARRAY_SIZE(s400_api_mapping_table); + s32 size = ARRAY_SIZE(ele_api_mapping_table); s32 i; /* map the fuse from ocotp fuse map to FSB*/ for (i = 0; i < size; i++) { - if (s400_api_mapping_table[i].fuse_bank != -1 && - s400_api_mapping_table[i].fuse_bank == bank) { - if (word >= s400_api_mapping_table[i].fuse_offset && - word < (s400_api_mapping_table[i].fuse_offset + - s400_api_mapping_table[i].fuse_words)) + if (ele_api_mapping_table[i].fuse_bank != -1 && + ele_api_mapping_table[i].fuse_bank == bank) { + if (word >= ele_api_mapping_table[i].fuse_offset && + word < (ele_api_mapping_table[i].fuse_offset + + ele_api_mapping_table[i].fuse_words)) break; } } @@ -178,10 +178,10 @@ static s32 map_s400_fuse_index(u32 bank, u32 word) if (i == size) return -1; /* Failed to find */ - if (s400_api_mapping_table[i].s400_index != 0) - return s400_api_mapping_table[i].s400_index; + if (ele_api_mapping_table[i].ele_index != 0) + return ele_api_mapping_table[i].ele_index; - return s400_api_mapping_table[i].fuse_bank * 8 + word; + return ele_api_mapping_table[i].fuse_bank * 8 + word; } #if defined(CONFIG_IMX8ULP) @@ -202,7 +202,7 @@ int fuse_sense(u32 bank, u32 word, u32 *val) return 0; } - word_index = map_s400_fuse_index(bank, word); + word_index = map_ele_fuse_index(bank, word); if (word_index >= 0) { u32 data[4]; u32 res, size = 4; @@ -212,7 +212,7 @@ int fuse_sense(u32 bank, u32 word, u32 *val) if (word_index != 1) size = 1; - ret = ahab_read_common_fuse(word_index, data, size, &res); + ret = ele_read_common_fuse(word_index, data, size, &res); if (ret) { printf("ahab read fuse failed %d, 0x%x\n", ret, res); return ret; @@ -255,13 +255,13 @@ int fuse_sense(u32 bank, u32 word, u32 *val) return 0; } - word_index = map_s400_fuse_index(bank, word); + word_index = map_ele_fuse_index(bank, word); if (word_index >= 0) { u32 data; u32 res, size = 1; int ret; - ret = ahab_read_common_fuse(word_index, &data, size, &res); + ret = ele_read_common_fuse(word_index, &data, size, &res); if (ret) { printf("ahab read fuse failed %d, 0x%x\n", ret, res); return ret; @@ -304,7 +304,7 @@ int fuse_prog(u32 bank, u32 word, u32 val) lock = true; #endif - ret = ahab_write_fuse((bank * 8 + word), val, lock, &res); + ret = ele_write_fuse((bank * 8 + word), val, lock, &res); if (ret) { printf("ahab write fuse failed %d, 0x%x\n", ret, res); return ret; diff --git a/drivers/misc/npcm_host_intf.c b/drivers/misc/npcm_host_intf.c index 0244e404570..79f57f57d89 100644 --- a/drivers/misc/npcm_host_intf.c +++ b/drivers/misc/npcm_host_intf.c @@ -50,9 +50,6 @@ static int npcm_host_intf_bind(struct udevice *dev) const char *type; int ret; - /* Release host wait */ - setbits_8(SMC_CTL_REG_ADDR, SMC_CTL_HOSTWAIT); - syscon = syscon_regmap_lookup_by_phandle(dev, "syscon"); if (IS_ERR(syscon)) { dev_err(dev, "%s: unable to get syscon, dev %s\n", __func__, dev->name); @@ -93,6 +90,9 @@ static int npcm_host_intf_bind(struct udevice *dev) regmap_update_bits(syscon, MFSEL1, MFSEL1_LPCSEL, MFSEL1_LPCSEL); } + /* Release host wait */ + setbits_8(SMC_CTL_REG_ADDR, SMC_CTL_HOSTWAIT); + return 0; } diff --git a/drivers/misc/npcm_otp.c b/drivers/misc/npcm_otp.c index 304910888bb..08029724c04 100644 --- a/drivers/misc/npcm_otp.c +++ b/drivers/misc/npcm_otp.c @@ -33,7 +33,7 @@ static int npcm_otp_check_inputs(u32 arr, u32 word) if (arr >= NPCM_NUM_OF_SA) { if (IS_ENABLED(CONFIG_ARCH_NPCM8XX)) printf("\nError: npcm8XX otp includs only one bank: 0\n"); - if (IS_ENABLED(CONFIG_ARCH_NPCM7XX)) + if (IS_ENABLED(CONFIG_ARCH_NPCM7xx)) printf("\nError: npcm7XX otp includs only two banks: 0 and 1\n"); return -1; } diff --git a/drivers/mtd/nand/raw/pxa3xx_nand.c b/drivers/mtd/nand/raw/pxa3xx_nand.c index fcd1b9c6361..d502e967f92 100644 --- a/drivers/mtd/nand/raw/pxa3xx_nand.c +++ b/drivers/mtd/nand/raw/pxa3xx_nand.c @@ -125,6 +125,7 @@ DECLARE_GLOBAL_DATA_PTR; /* System control register and bit to enable NAND on some SoCs */ #define GENCONF_SOC_DEVICE_MUX 0x208 #define GENCONF_SOC_DEVICE_MUX_NFC_EN BIT(0) +#define GENCONF_SOC_DEVICE_MUX_NFC_DEVBUS_ARB_EN BIT(27) /* * This should be large enough to read 'ONFI' and 'JEDEC'. @@ -167,6 +168,7 @@ enum pxa3xx_nand_variant { PXA3XX_NAND_VARIANT_PXA, PXA3XX_NAND_VARIANT_ARMADA370, PXA3XX_NAND_VARIANT_ARMADA_8K, + PXA3XX_NAND_VARIANT_AC5, }; struct pxa3xx_nand_host { @@ -391,6 +393,10 @@ static const struct udevice_id pxa3xx_nand_dt_ids[] = { .compatible = "marvell,armada-8k-nand-controller", .data = PXA3XX_NAND_VARIANT_ARMADA_8K, }, + { + .compatible = "marvell,mvebu-ac5-pxa3xx-nand", + .data = PXA3XX_NAND_VARIANT_AC5, + }, {} }; @@ -505,6 +511,9 @@ static int pxa3xx_nand_init_timings(struct pxa3xx_nand_host *host) if (mode < 0) mode = 0; + if (info->variant == PXA3XX_NAND_VARIANT_AC5) + mode = min(mode, 3); + timings = onfi_async_timing_mode_to_sdr_timings(mode); if (IS_ERR(timings)) return PTR_ERR(timings); @@ -730,7 +739,8 @@ static irqreturn_t pxa3xx_nand_irq(struct pxa3xx_nand_info *info) /* NDCB3 register is available in NFCv2 (Armada 370/XP SoC) */ if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370 || - info->variant == PXA3XX_NAND_VARIANT_ARMADA_8K) + info->variant == PXA3XX_NAND_VARIANT_ARMADA_8K || + info->variant == PXA3XX_NAND_VARIANT_AC5) nand_writel(info, NDCB0, info->ndcb3); } @@ -1579,7 +1589,8 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) /* Device detection must be done with ECC disabled */ if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370 || - info->variant == PXA3XX_NAND_VARIANT_ARMADA_8K) + info->variant == PXA3XX_NAND_VARIANT_ARMADA_8K || + info->variant == PXA3XX_NAND_VARIANT_AC5) nand_writel(info, NDECCCTRL, 0x0); if (nand_scan_ident(mtd, 1, NULL)) @@ -1630,7 +1641,8 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) */ if (mtd->writesize > info->chunk_size) { if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370 || - info->variant == PXA3XX_NAND_VARIANT_ARMADA_8K) { + info->variant == PXA3XX_NAND_VARIANT_ARMADA_8K || + info->variant == PXA3XX_NAND_VARIANT_AC5) { chip->cmdfunc = nand_cmdfunc_extended; } else { dev_err(mtd->dev, @@ -1728,7 +1740,7 @@ static int alloc_nand_resource(struct udevice *dev, struct pxa3xx_nand_info *inf return PTR_ERR(sysctrl_base); regmap_read(sysctrl_base, GENCONF_SOC_DEVICE_MUX, ®); - reg |= GENCONF_SOC_DEVICE_MUX_NFC_EN; + reg |= GENCONF_SOC_DEVICE_MUX_NFC_EN | GENCONF_SOC_DEVICE_MUX_NFC_DEVBUS_ARB_EN; regmap_write(sysctrl_base, GENCONF_SOC_DEVICE_MUX, reg); } diff --git a/drivers/mtd/spi/spi-nor-ids.c b/drivers/mtd/spi/spi-nor-ids.c index 3f8b7967893..45872159842 100644 --- a/drivers/mtd/spi/spi-nor-ids.c +++ b/drivers/mtd/spi/spi-nor-ids.c @@ -446,6 +446,11 @@ const struct flash_info spi_nor_ids[] = { SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) }, + { + INFO("w25q256jwm", 0xef8019, 0, 64 * 1024, 512, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) + }, { INFO("w25x64", 0xef3017, 0, 64 * 1024, 128, SECT_4K) }, { INFO("w25q64dw", 0xef6017, 0, 64 * 1024, 128, @@ -528,8 +533,42 @@ const struct flash_info spi_nor_ids[] = { { INFO("XM25QH128A", 0x207018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, #endif #ifdef CONFIG_SPI_FLASH_XTX - /* XTX Technology (Shenzhen) Limited */ - { INFO("xt25f128b", 0x0b4018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + /* XTX Technology Limited */ + /* adding these 3V QSPI flash parts */ + { INFO("xt25f08", 0x0b4014, 0, 64 * 1024, 16, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("xt25f16", 0x0b4015, 0, 64 * 1024, 32, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("xt25f32", 0x0b4016, 0, 64 * 1024, 64, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("xt25f64", 0x0b4017, 0, 64 * 1024, 128, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("xt25f128", 0x0b4018, 0, 64 * 1024, 256, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("xt25f256", 0x0b4019, 0, 64 * 1024, 512, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, + /* adding these 1.8V QSPI flash parts */ + { INFO("xt25q08", 0x0b6014, 0, 64 * 1024, 16, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("xt25q16", 0x0b6015, 0, 64 * 1024, 32, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("xt25q32", 0x0b6016, 0, 64 * 1024, 64, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("xt25q64", 0x0b6017, 0, 64 * 1024, 128, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("xt25q128", 0x0b6018, 0, 64 * 1024, 256, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("xt25q256", 0x0b6019, 0, 64 * 1024, 512, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, + { INFO("xt25q512", 0x0b601A, 0, 64 * 1024, 1024, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, + { INFO("xt25q01g", 0x0b601B, 0, 64 * 1024, 2048, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, + /* adding these wide voltage QSPI flash parts */ + { INFO("xt25w512", 0x0b651A, 0, 64 * 1024, 1024, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, + { INFO("xt25w01g", 0x0b651B, 0, 64 * 1024, 2048, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, #endif { }, }; diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index d662dd34989..0ed39a61e4d 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -249,6 +249,13 @@ config DWC_ETH_QOS_QCOM The Synopsys Designware Ethernet QOS IP block with specific configuration used in Qcom QCS404 SoC. +config DWC_ETH_QOS_STARFIVE + bool "Synopsys DWC Ethernet QOS device support for STARFIVE" + depends on DWC_ETH_QOS + help + The Synopsys Designware Ethernet QOS IP block with specific + configuration used in STARFIVE JH7110 soc. + config E1000 bool "Intel PRO/1000 Gigabit Ethernet support" depends on PCI diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 46a40e2ed9f..d4af253b6f2 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_DSA_SANDBOX) += dsa_sandbox.o obj-$(CONFIG_DWC_ETH_QOS) += dwc_eth_qos.o obj-$(CONFIG_DWC_ETH_QOS_IMX) += dwc_eth_qos_imx.o obj-$(CONFIG_DWC_ETH_QOS_QCOM) += dwc_eth_qos_qcom.o +obj-$(CONFIG_DWC_ETH_QOS_STARFIVE) += dwc_eth_qos_starfive.o obj-$(CONFIG_E1000) += e1000.o obj-$(CONFIG_E1000_SPI) += e1000_spi.o obj-$(CONFIG_EEPRO100) += eepro100.o diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c index 9bbba6eed07..1e92bd9ca9c 100644 --- a/drivers/net/dwc_eth_qos.c +++ b/drivers/net/dwc_eth_qos.c @@ -1725,6 +1725,12 @@ static const struct udevice_id eqos_ids[] = { .data = (ulong)&eqos_qcom_config }, #endif +#if IS_ENABLED(CONFIG_DWC_ETH_QOS_STARFIVE) + { + .compatible = "starfive,jh7110-dwmac", + .data = (ulong)&eqos_jh7110_config + }, +#endif { } }; diff --git a/drivers/net/dwc_eth_qos.h b/drivers/net/dwc_eth_qos.h index fddbe9336c9..a6b719af809 100644 --- a/drivers/net/dwc_eth_qos.h +++ b/drivers/net/dwc_eth_qos.h @@ -289,3 +289,4 @@ int eqos_null_ops(struct udevice *dev); extern struct eqos_config eqos_imx_config; extern struct eqos_config eqos_qcom_config; +extern struct eqos_config eqos_jh7110_config; diff --git a/drivers/net/dwc_eth_qos_starfive.c b/drivers/net/dwc_eth_qos_starfive.c new file mode 100644 index 00000000000..5be8ac0f1a5 --- /dev/null +++ b/drivers/net/dwc_eth_qos_starfive.c @@ -0,0 +1,249 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2023 StarFive Technology Co., Ltd. + * Author: Yanhong Wang<yanhong.wang@starfivetech.com> + */ + +#include <common.h> +#include <asm/cache.h> +#include <asm/gpio.h> +#include <clk.h> +#include <dm.h> +#include <eth_phy.h> +#include <net.h> +#include <regmap.h> +#include <reset.h> +#include <syscon.h> + +#include "dwc_eth_qos.h" + +#define STARFIVE_DWMAC_PHY_INFT_RGMII 0x1 +#define STARFIVE_DWMAC_PHY_INFT_RMII 0x4 +#define STARFIVE_DWMAC_PHY_INFT_FIELD 0x7U + +struct starfive_platform_data { + struct regmap *regmap; + struct reset_ctl_bulk resets; + struct clk_bulk clks; + phy_interface_t interface; + u32 offset; + u32 shift; + bool tx_use_rgmii_clk; +}; + +static int eqos_interface_init_jh7110(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_plat(dev); + struct starfive_platform_data *data = pdata->priv_pdata; + struct ofnode_phandle_args args; + unsigned int mode; + int ret; + + switch (data->interface) { + case PHY_INTERFACE_MODE_RMII: + mode = STARFIVE_DWMAC_PHY_INFT_RMII; + break; + + case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_ID: + mode = STARFIVE_DWMAC_PHY_INFT_RGMII; + break; + + default: + return -EINVAL; + } + + ret = dev_read_phandle_with_args(dev, "starfive,syscon", NULL, + 2, 0, &args); + if (ret) + return ret; + + if (args.args_count != 2) + return -EINVAL; + + data->offset = args.args[0]; + data->shift = args.args[1]; + data->regmap = syscon_regmap_lookup_by_phandle(dev, "starfive,syscon"); + if (IS_ERR(data->regmap)) { + ret = PTR_ERR(data->regmap); + pr_err("Failed to get regmap: %d\n", ret); + return ret; + } + + return regmap_update_bits(data->regmap, data->offset, + STARFIVE_DWMAC_PHY_INFT_FIELD << data->shift, + mode << data->shift); +} + +static int eqos_set_tx_clk_speed_jh7110(struct udevice *dev) +{ + struct eqos_priv *eqos = dev_get_priv(dev); + struct eth_pdata *pdata = dev_get_plat(dev); + struct starfive_platform_data *data = pdata->priv_pdata; + struct clk *pclk, *c; + ulong rate; + int ret; + + /* Generally, the rgmii_tx clock is provided by the internal clock, + * which needs to match the corresponding clock frequency according + * to different speeds. If the rgmii_tx clock is provided by the + * external rgmii_rxin, there is no need to configure the clock + * internally, because rgmii_rxin will be adaptively adjusted. + */ + if (data->tx_use_rgmii_clk) + return 0; + + switch (eqos->phy->speed) { + case SPEED_1000: + rate = 125 * 1000 * 1000; + break; + case SPEED_100: + rate = 25 * 1000 * 1000; + break; + case SPEED_10: + rate = 2.5 * 1000 * 1000; + break; + default: + pr_err("invalid speed %d", eqos->phy->speed); + return -EINVAL; + } + + /* eqos->clk_tx clock has no set rate operation, so just set the parent + * clock rate directly + */ + ret = clk_get_by_id(eqos->clk_tx.id, &c); + if (ret) + return ret; + + pclk = clk_get_parent(c); + if (pclk) { + ret = clk_set_rate(pclk, rate); + if (ret < 0) { + pr_err("jh7110 (clk_tx, %lu) failed: %d", rate, ret); + return ret; + } + } + + return 0; +} + +static ulong eqos_get_tick_clk_rate_jh7110(struct udevice *dev) +{ + struct eqos_priv *eqos = dev_get_priv(dev); + + return clk_get_rate(&eqos->clk_tx); +} + +static int eqos_start_clks_jh7110(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_plat(dev); + struct starfive_platform_data *data = pdata->priv_pdata; + + return clk_enable_bulk(&data->clks); +} + +static int eqos_stop_clks_jh7110(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_plat(dev); + struct starfive_platform_data *data = pdata->priv_pdata; + + return clk_disable_bulk(&data->clks); +} + +static int eqos_start_resets_jh7110(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_plat(dev); + struct starfive_platform_data *data = pdata->priv_pdata; + + return reset_deassert_bulk(&data->resets); +} + +static int eqos_stop_resets_jh7110(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_plat(dev); + struct starfive_platform_data *data = pdata->priv_pdata; + + return reset_assert_bulk(&data->resets); +} + +static int eqos_remove_resources_jh7110(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_plat(dev); + struct starfive_platform_data *data = pdata->priv_pdata; + + reset_assert_bulk(&data->resets); + clk_disable_bulk(&data->clks); + + return 0; +} + +static int eqos_probe_resources_jh7110(struct udevice *dev) +{ + struct eqos_priv *eqos = dev_get_priv(dev); + struct eth_pdata *pdata = dev_get_plat(dev); + struct starfive_platform_data *data; + int ret; + + data = calloc(1, sizeof(struct starfive_platform_data)); + if (!data) + return -ENOMEM; + + pdata->priv_pdata = data; + data->interface = eqos->config->interface(dev); + if (data->interface == PHY_INTERFACE_MODE_NA) { + pr_err("Invalid PHY interface\n"); + return -EINVAL; + } + + ret = reset_get_bulk(dev, &data->resets); + if (ret < 0) + return ret; + + ret = clk_get_bulk(dev, &data->clks); + if (ret < 0) + return ret; + + ret = clk_get_by_name(dev, "gtx", &eqos->clk_tx); + if (ret) + return ret; + + data->tx_use_rgmii_clk = dev_read_bool(dev, "starfive,tx-use-rgmii-clk"); + + return eqos_interface_init_jh7110(dev); +} + +static struct eqos_ops eqos_jh7110_ops = { + .eqos_inval_desc = eqos_inval_desc_generic, + .eqos_flush_desc = eqos_flush_desc_generic, + .eqos_inval_buffer = eqos_inval_buffer_generic, + .eqos_flush_buffer = eqos_flush_buffer_generic, + .eqos_probe_resources = eqos_probe_resources_jh7110, + .eqos_remove_resources = eqos_remove_resources_jh7110, + .eqos_stop_resets = eqos_stop_resets_jh7110, + .eqos_start_resets = eqos_start_resets_jh7110, + .eqos_stop_clks = eqos_stop_clks_jh7110, + .eqos_start_clks = eqos_start_clks_jh7110, + .eqos_calibrate_pads = eqos_null_ops, + .eqos_disable_calibration = eqos_null_ops, + .eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_jh7110, + .eqos_get_enetaddr = eqos_null_ops, + .eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_jh7110 +}; + +/* mdio_wait: There is no need to wait after setting the MAC_MDIO_Address register + * swr_wait: Software reset bit must be read at least 4 CSR clock cycles + * after it is written to 1. + * config_mac: Enable rx queue to DCB mode. + * config_mac_mdio: CSR clock range is 250-300 Mhz. + * axi_bus_width: The width of the data bus is 64 bit. + */ +struct eqos_config __maybe_unused eqos_jh7110_config = { + .reg_access_always_ok = false, + .mdio_wait = 0, + .swr_wait = 4, + .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB, + .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_250_300, + .axi_bus_width = EQOS_AXI_WIDTH_64, + .interface = dev_read_phy_mode, + .ops = &eqos_jh7110_ops +}; diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 24158776f52..0c3c39a5504 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -220,6 +220,12 @@ config PHY_MICREL_KSZ8XXX endif # PHY_MICREL +config PHY_MOTORCOMM + tristate "Motorcomm PHYs" + help + Enables support for Motorcomm network PHYs. + Currently supports the YT8531 Gigabit Ethernet PHYs. + config PHY_MSCC bool "Microsemi Corp Ethernet PHYs support" diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 85d17f109cd..2487f366e1c 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_PHY_MARVELL_10G) += marvell10g.o obj-$(CONFIG_PHY_MICREL_KSZ8XXX) += micrel_ksz8xxx.o obj-$(CONFIG_PHY_MICREL_KSZ90X1) += micrel_ksz90x1.o obj-$(CONFIG_PHY_MESON_GXL) += meson-gxl.o +obj-$(CONFIG_PHY_MOTORCOMM) += motorcomm.o obj-$(CONFIG_PHY_NATSEMI) += natsemi.o obj-$(CONFIG_PHY_NXP_C45_TJA11XX) += nxp-c45-tja11xx.o obj-$(CONFIG_PHY_NXP_TJA11XX) += nxp-tja11xx.o diff --git a/drivers/net/phy/motorcomm.c b/drivers/net/phy/motorcomm.c new file mode 100644 index 00000000000..e822fd76f27 --- /dev/null +++ b/drivers/net/phy/motorcomm.c @@ -0,0 +1,437 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Motorcomm 8531 PHY driver. + * + * Copyright (C) 2023 StarFive Technology Co., Ltd. + */ + +#include <config.h> +#include <common.h> +#include <malloc.h> +#include <phy.h> +#include <linux/bitfield.h> + +#define PHY_ID_YT8531 0x4f51e91b +#define PHY_ID_MASK GENMASK(31, 0) + +/* Extended Register's Address Offset Register */ +#define YTPHY_PAGE_SELECT 0x1E + +/* Extended Register's Data Register */ +#define YTPHY_PAGE_DATA 0x1F + +#define YTPHY_SYNCE_CFG_REG 0xA012 + +#define YTPHY_DTS_OUTPUT_CLK_DIS 0 +#define YTPHY_DTS_OUTPUT_CLK_25M 25000000 +#define YTPHY_DTS_OUTPUT_CLK_125M 125000000 + +#define YT8531_SCR_SYNCE_ENABLE BIT(6) +/* 1b0 output 25m clock *default* + * 1b1 output 125m clock + */ +#define YT8531_SCR_CLK_FRE_SEL_125M BIT(4) +#define YT8531_SCR_CLK_SRC_MASK GENMASK(3, 1) +#define YT8531_SCR_CLK_SRC_PLL_125M 0 +#define YT8531_SCR_CLK_SRC_UTP_RX 1 +#define YT8531_SCR_CLK_SRC_SDS_RX 2 +#define YT8531_SCR_CLK_SRC_CLOCK_FROM_DIGITAL 3 +#define YT8531_SCR_CLK_SRC_REF_25M 4 +#define YT8531_SCR_CLK_SRC_SSC_25M 5 + +/* 1b0 use original tx_clk_rgmii *default* + * 1b1 use inverted tx_clk_rgmii. + */ +#define YT8531_RC1R_TX_CLK_SEL_INVERTED BIT(14) +#define YT8531_RC1R_RX_DELAY_MASK GENMASK(13, 10) +#define YT8531_RC1R_FE_TX_DELAY_MASK GENMASK(7, 4) +#define YT8531_RC1R_GE_TX_DELAY_MASK GENMASK(3, 0) +#define YT8531_RC1R_RGMII_0_000_NS 0 +#define YT8531_RC1R_RGMII_0_150_NS 1 +#define YT8531_RC1R_RGMII_0_300_NS 2 +#define YT8531_RC1R_RGMII_0_450_NS 3 +#define YT8531_RC1R_RGMII_0_600_NS 4 +#define YT8531_RC1R_RGMII_0_750_NS 5 +#define YT8531_RC1R_RGMII_0_900_NS 6 +#define YT8531_RC1R_RGMII_1_050_NS 7 +#define YT8531_RC1R_RGMII_1_200_NS 8 +#define YT8531_RC1R_RGMII_1_350_NS 9 +#define YT8531_RC1R_RGMII_1_500_NS 10 +#define YT8531_RC1R_RGMII_1_650_NS 11 +#define YT8531_RC1R_RGMII_1_800_NS 12 +#define YT8531_RC1R_RGMII_1_950_NS 13 +#define YT8531_RC1R_RGMII_2_100_NS 14 +#define YT8531_RC1R_RGMII_2_250_NS 15 + +/* Phy gmii clock gating Register */ +#define YT8531_CLOCK_GATING_REG 0xC +#define YT8531_CGR_RX_CLK_EN BIT(12) + +/* Specific Status Register */ +#define YTPHY_SPECIFIC_STATUS_REG 0x11 +#define YTPHY_DUPLEX_MASK BIT(13) +#define YTPHY_DUPLEX_SHIFT 13 +#define YTPHY_SPEED_MODE_MASK GENMASK(15, 14) +#define YTPHY_SPEED_MODE_SHIFT 14 + +#define YT8531_EXTREG_SLEEP_CONTROL1_REG 0x27 +#define YT8531_ESC1R_SLEEP_SW BIT(15) +#define YT8531_ESC1R_PLLON_SLP BIT(14) + +#define YT8531_RGMII_CONFIG1_REG 0xA003 + +#define YT8531_CHIP_CONFIG_REG 0xA001 +#define YT8531_CCR_SW_RST BIT(15) +/* 1b0 disable 1.9ns rxc clock delay *default* + * 1b1 enable 1.9ns rxc clock delay + */ +#define YT8531_CCR_RXC_DLY_EN BIT(8) +#define YT8531_CCR_RXC_DLY_1_900_NS 1900 + +/* bits in struct ytphy_plat_priv->flag */ +#define TX_CLK_ADJ_ENABLED BIT(0) +#define AUTO_SLEEP_DISABLED BIT(1) +#define KEEP_PLL_ENABLED BIT(2) +#define TX_CLK_10_INVERTED BIT(3) +#define TX_CLK_100_INVERTED BIT(4) +#define TX_CLK_1000_INVERTED BIT(5) + +struct ytphy_plat_priv { + u32 rx_delay_ps; + u32 tx_delay_ps; + u32 clk_out_frequency; + u32 flag; +}; + +/** + * struct ytphy_cfg_reg_map - map a config value to a register value + * @cfg: value in device configuration + * @reg: value in the register + */ +struct ytphy_cfg_reg_map { + u32 cfg; + u32 reg; +}; + +static const struct ytphy_cfg_reg_map ytphy_rgmii_delays[] = { + /* for tx delay / rx delay with YT8531_CCR_RXC_DLY_EN is not set. */ + { 0, YT8531_RC1R_RGMII_0_000_NS }, + { 150, YT8531_RC1R_RGMII_0_150_NS }, + { 300, YT8531_RC1R_RGMII_0_300_NS }, + { 450, YT8531_RC1R_RGMII_0_450_NS }, + { 600, YT8531_RC1R_RGMII_0_600_NS }, + { 750, YT8531_RC1R_RGMII_0_750_NS }, + { 900, YT8531_RC1R_RGMII_0_900_NS }, + { 1050, YT8531_RC1R_RGMII_1_050_NS }, + { 1200, YT8531_RC1R_RGMII_1_200_NS }, + { 1350, YT8531_RC1R_RGMII_1_350_NS }, + { 1500, YT8531_RC1R_RGMII_1_500_NS }, + { 1650, YT8531_RC1R_RGMII_1_650_NS }, + { 1800, YT8531_RC1R_RGMII_1_800_NS }, + { 1950, YT8531_RC1R_RGMII_1_950_NS }, /* default tx/rx delay */ + { 2100, YT8531_RC1R_RGMII_2_100_NS }, + { 2250, YT8531_RC1R_RGMII_2_250_NS }, + + /* only for rx delay with YT8531_CCR_RXC_DLY_EN is set. */ + { 0 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_0_000_NS }, + { 150 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_0_150_NS }, + { 300 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_0_300_NS }, + { 450 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_0_450_NS }, + { 600 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_0_600_NS }, + { 750 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_0_750_NS }, + { 900 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_0_900_NS }, + { 1050 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_1_050_NS }, + { 1200 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_1_200_NS }, + { 1350 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_1_350_NS }, + { 1500 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_1_500_NS }, + { 1650 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_1_650_NS }, + { 1800 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_1_800_NS }, + { 1950 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_1_950_NS }, + { 2100 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_2_100_NS }, + { 2250 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_2_250_NS } +}; + +static u32 ytphy_get_delay_reg_value(struct phy_device *phydev, + u32 val, + u16 *rxc_dly_en) +{ + int tb_size = ARRAY_SIZE(ytphy_rgmii_delays); + int tb_size_half = tb_size / 2; + int i; + + /* when rxc_dly_en is NULL, it is get the delay for tx, only half of + * tb_size is valid. + */ + if (!rxc_dly_en) + tb_size = tb_size_half; + + for (i = 0; i < tb_size; i++) { + if (ytphy_rgmii_delays[i].cfg == val) { + if (rxc_dly_en && i < tb_size_half) + *rxc_dly_en = 0; + return ytphy_rgmii_delays[i].reg; + } + } + + pr_warn("Unsupported value %d, using default (%u)\n", + val, YT8531_RC1R_RGMII_1_950_NS); + + /* when rxc_dly_en is not NULL, it is get the delay for rx. + * The rx default in dts and ytphy_rgmii_clk_delay_config is 1950 ps, + * so YT8531_CCR_RXC_DLY_EN should not be set. + */ + if (rxc_dly_en) + *rxc_dly_en = 0; + + return YT8531_RC1R_RGMII_1_950_NS; +} + +static int ytphy_modify_ext(struct phy_device *phydev, u16 regnum, u16 mask, + u16 set) +{ + int ret; + + ret = phy_write(phydev, MDIO_DEVAD_NONE, YTPHY_PAGE_SELECT, regnum); + if (ret < 0) + return ret; + + return phy_modify(phydev, MDIO_DEVAD_NONE, YTPHY_PAGE_DATA, mask, set); +} + +static int ytphy_rgmii_clk_delay_config(struct phy_device *phydev) +{ + struct ytphy_plat_priv *priv = phydev->priv; + u16 rxc_dly_en = YT8531_CCR_RXC_DLY_EN; + u32 rx_reg, tx_reg; + u16 mask, val = 0; + int ret; + + rx_reg = ytphy_get_delay_reg_value(phydev, priv->rx_delay_ps, + &rxc_dly_en); + tx_reg = ytphy_get_delay_reg_value(phydev, priv->tx_delay_ps, + NULL); + + switch (phydev->interface) { + case PHY_INTERFACE_MODE_RGMII: + rxc_dly_en = 0; + break; + case PHY_INTERFACE_MODE_RGMII_RXID: + val |= FIELD_PREP(YT8531_RC1R_RX_DELAY_MASK, rx_reg); + break; + case PHY_INTERFACE_MODE_RGMII_TXID: + rxc_dly_en = 0; + val |= FIELD_PREP(YT8531_RC1R_GE_TX_DELAY_MASK, tx_reg); + break; + case PHY_INTERFACE_MODE_RGMII_ID: + val |= FIELD_PREP(YT8531_RC1R_RX_DELAY_MASK, rx_reg) | + FIELD_PREP(YT8531_RC1R_GE_TX_DELAY_MASK, tx_reg); + break; + default: /* do not support other modes */ + return -EOPNOTSUPP; + } + + ret = ytphy_modify_ext(phydev, YT8531_CHIP_CONFIG_REG, + YT8531_CCR_RXC_DLY_EN, rxc_dly_en); + if (ret < 0) + return ret; + + /* Generally, it is not necessary to adjust YT8531_RC1R_FE_TX_DELAY */ + mask = YT8531_RC1R_RX_DELAY_MASK | YT8531_RC1R_GE_TX_DELAY_MASK; + return ytphy_modify_ext(phydev, YT8531_RGMII_CONFIG1_REG, mask, val); +} + +static int yt8531_parse_status(struct phy_device *phydev) +{ + int val; + int speed, speed_mode; + + val = phy_read(phydev, MDIO_DEVAD_NONE, YTPHY_SPECIFIC_STATUS_REG); + if (val < 0) + return val; + + speed_mode = (val & YTPHY_SPEED_MODE_MASK) >> YTPHY_SPEED_MODE_SHIFT; + switch (speed_mode) { + case 2: + speed = SPEED_1000; + break; + case 1: + speed = SPEED_100; + break; + default: + speed = SPEED_10; + break; + } + + phydev->speed = speed; + phydev->duplex = (val & YTPHY_DUPLEX_MASK) >> YTPHY_DUPLEX_SHIFT; + + return 0; +} + +static int yt8531_startup(struct phy_device *phydev) +{ + struct ytphy_plat_priv *priv = phydev->priv; + u16 val = 0; + int ret; + + ret = genphy_update_link(phydev); + if (ret) + return ret; + + ret = yt8531_parse_status(phydev); + if (ret) + return ret; + + if (phydev->speed < 0) + return -EINVAL; + + if (!(priv->flag & TX_CLK_ADJ_ENABLED)) + return 0; + + switch (phydev->speed) { + case SPEED_1000: + if (priv->flag & TX_CLK_1000_INVERTED) + val = YT8531_RC1R_TX_CLK_SEL_INVERTED; + break; + case SPEED_100: + if (priv->flag & TX_CLK_100_INVERTED) + val = YT8531_RC1R_TX_CLK_SEL_INVERTED; + break; + case SPEED_10: + if (priv->flag & TX_CLK_10_INVERTED) + val = YT8531_RC1R_TX_CLK_SEL_INVERTED; + break; + default: + printf("UNKNOWN SPEED\n"); + return -EINVAL; + } + + ret = ytphy_modify_ext(phydev, YT8531_RGMII_CONFIG1_REG, + YT8531_RC1R_TX_CLK_SEL_INVERTED, val); + if (ret < 0) + pr_warn("Modify TX_CLK_SEL err:%d\n", ret); + + return 0; +} + +static void ytphy_dt_parse(struct phy_device *phydev) +{ + struct ytphy_plat_priv *priv = phydev->priv; + + priv->clk_out_frequency = ofnode_read_u32_default(phydev->node, + "motorcomm,clk-out-frequency-hz", + YTPHY_DTS_OUTPUT_CLK_DIS); + priv->rx_delay_ps = ofnode_read_u32_default(phydev->node, + "rx-internal-delay-ps", + YT8531_RC1R_RGMII_1_950_NS); + priv->tx_delay_ps = ofnode_read_u32_default(phydev->node, + "tx-internal-delay-ps", + YT8531_RC1R_RGMII_1_950_NS); + + if (ofnode_read_bool(phydev->node, "motorcomm,auto-sleep-disabled")) + priv->flag |= AUTO_SLEEP_DISABLED; + + if (ofnode_read_bool(phydev->node, "motorcomm,keep-pll-enabled")) + priv->flag |= KEEP_PLL_ENABLED; + + if (ofnode_read_bool(phydev->node, "motorcomm,tx-clk-adj-enabled")) + priv->flag |= TX_CLK_ADJ_ENABLED; + + if (ofnode_read_bool(phydev->node, "motorcomm,tx-clk-10-inverted")) + priv->flag |= TX_CLK_10_INVERTED; + + if (ofnode_read_bool(phydev->node, "motorcomm,tx-clk-100-inverted")) + priv->flag |= TX_CLK_100_INVERTED; + + if (ofnode_read_bool(phydev->node, "motorcomm,tx-clk-1000-inverted")) + priv->flag |= TX_CLK_1000_INVERTED; +} + +static int yt8531_config(struct phy_device *phydev) +{ + struct ytphy_plat_priv *priv = phydev->priv; + u16 mask, val; + int ret; + + ret = genphy_config_aneg(phydev); + if (ret < 0) + return ret; + + ytphy_dt_parse(phydev); + switch (priv->clk_out_frequency) { + case YTPHY_DTS_OUTPUT_CLK_DIS: + mask = YT8531_SCR_SYNCE_ENABLE; + val = 0; + break; + case YTPHY_DTS_OUTPUT_CLK_25M: + mask = YT8531_SCR_SYNCE_ENABLE | YT8531_SCR_CLK_SRC_MASK | + YT8531_SCR_CLK_FRE_SEL_125M; + val = YT8531_SCR_SYNCE_ENABLE | + FIELD_PREP(YT8531_SCR_CLK_SRC_MASK, + YT8531_SCR_CLK_SRC_REF_25M); + break; + case YTPHY_DTS_OUTPUT_CLK_125M: + mask = YT8531_SCR_SYNCE_ENABLE | YT8531_SCR_CLK_SRC_MASK | + YT8531_SCR_CLK_FRE_SEL_125M; + val = YT8531_SCR_SYNCE_ENABLE | YT8531_SCR_CLK_FRE_SEL_125M | + FIELD_PREP(YT8531_SCR_CLK_SRC_MASK, + YT8531_SCR_CLK_SRC_PLL_125M); + break; + default: + pr_warn("Freq err:%u\n", priv->clk_out_frequency); + return -EINVAL; + } + + ret = ytphy_modify_ext(phydev, YTPHY_SYNCE_CFG_REG, mask, + val); + if (ret < 0) + return ret; + + ret = ytphy_rgmii_clk_delay_config(phydev); + if (ret < 0) + return ret; + + if (priv->flag & AUTO_SLEEP_DISABLED) { + /* disable auto sleep */ + ret = ytphy_modify_ext(phydev, + YT8531_EXTREG_SLEEP_CONTROL1_REG, + YT8531_ESC1R_SLEEP_SW, 0); + if (ret < 0) + return ret; + } + + if (priv->flag & KEEP_PLL_ENABLED) { + /* enable RXC clock when no wire plug */ + ret = ytphy_modify_ext(phydev, + YT8531_CLOCK_GATING_REG, + YT8531_CGR_RX_CLK_EN, 0); + if (ret < 0) + return ret; + } + + return 0; +} + +static int yt8531_probe(struct phy_device *phydev) +{ + struct ytphy_plat_priv *priv; + + priv = calloc(1, sizeof(struct ytphy_plat_priv)); + if (!priv) + return -ENOMEM; + + phydev->priv = priv; + + return 0; +} + +U_BOOT_PHY_DRIVER(motorcomm8531) = { + .name = "YT8531 Gigabit Ethernet", + .uid = PHY_ID_YT8531, + .mask = PHY_ID_MASK, + .features = PHY_GBIT_FEATURES, + .probe = &yt8531_probe, + .config = &yt8531_config, + .startup = &yt8531_startup, + .shutdown = &genphy_shutdown, +}; diff --git a/drivers/net/ti/am65-cpsw-nuss.c b/drivers/net/ti/am65-cpsw-nuss.c index f674b0baa35..523a4c9f919 100644 --- a/drivers/net/ti/am65-cpsw-nuss.c +++ b/drivers/net/ti/am65-cpsw-nuss.c @@ -223,6 +223,8 @@ out: return phy->link; } +#define AM65_GMII_SEL_PORT_OFFS(x) (0x4 * ((x) - 1)) + #define AM65_GMII_SEL_MODE_MII 0 #define AM65_GMII_SEL_MODE_RMII 1 #define AM65_GMII_SEL_MODE_RGMII 2 @@ -233,11 +235,12 @@ static void am65_cpsw_gmii_sel_k3(struct am65_cpsw_priv *priv, phy_interface_t phy_mode, int slave) { struct am65_cpsw_common *common = priv->cpsw_common; + fdt_addr_t gmii_sel = common->gmii_sel + AM65_GMII_SEL_PORT_OFFS(slave); u32 reg; u32 mode = 0; bool rgmii_id = false; - reg = readl(common->gmii_sel); + reg = readl(gmii_sel); dev_dbg(common->dev, "old gmii_sel: %08x\n", reg); @@ -273,9 +276,9 @@ static void am65_cpsw_gmii_sel_k3(struct am65_cpsw_priv *priv, reg = mode; dev_dbg(common->dev, "gmii_sel PHY mode: %u, new gmii_sel: %08x\n", phy_mode, reg); - writel(reg, common->gmii_sel); + writel(reg, gmii_sel); - reg = readl(common->gmii_sel); + reg = readl(gmii_sel); if (reg != mode) dev_err(common->dev, "gmii_sel PHY mode NOT SET!: requested: %08x, gmii_sel: %08x\n", diff --git a/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c b/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c index f18be08518e..7976e3b3ed5 100644 --- a/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c +++ b/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c @@ -808,6 +808,9 @@ static bool is_gpio_persist(struct udevice *dev, uint bank) status = npcm_get_reset_status(); dev_dbg(dev, "reset status: 0x%x\n", status); + if (status & PORST) + return false; + if (status & CORST) regmap_read(priv->rst_regmap, CORSTC, &val); else if (status & WD0RST) diff --git a/drivers/power/domain/imx8-power-domain-legacy.c b/drivers/power/domain/imx8-power-domain-legacy.c index 37b0f95abac..c8ca2665752 100644 --- a/drivers/power/domain/imx8-power-domain-legacy.c +++ b/drivers/power/domain/imx8-power-domain-legacy.c @@ -89,7 +89,6 @@ static int imx8_power_domain_on(struct power_domain *power_domain) struct udevice *dev = power_domain->dev; struct imx8_power_domain_plat *pdata; struct imx8_power_domain_priv *ppriv; - sc_err_t ret; int err; struct power_domain parent_domain; @@ -117,11 +116,11 @@ static int imx8_power_domain_on(struct power_domain *power_domain) if (!sc_rm_is_resource_owned(-1, pdata->resource_id)) printf("%s [%d] not owned by curr partition\n", dev->name, pdata->resource_id); - ret = sc_pm_set_resource_power_mode(-1, pdata->resource_id, + err = sc_pm_set_resource_power_mode(-1, pdata->resource_id, SC_PM_PW_MODE_ON); - if (ret) { + if (err) { printf("Error: %s Power up failed! (error = %d)\n", - dev->name, ret); + dev->name, err); return -EIO; } } @@ -139,7 +138,7 @@ static int imx8_power_domain_off_node(struct power_domain *power_domain) struct imx8_power_domain_priv *ppriv; struct imx8_power_domain_priv *child_ppriv; struct imx8_power_domain_plat *pdata; - sc_err_t ret; + int ret; ppriv = dev_get_priv(dev); pdata = dev_get_plat(dev); diff --git a/drivers/power/domain/imx8m-power-domain.c b/drivers/power/domain/imx8m-power-domain.c index 145f6ec0cd3..df5d7d69562 100644 --- a/drivers/power/domain/imx8m-power-domain.c +++ b/drivers/power/domain/imx8m-power-domain.c @@ -338,6 +338,9 @@ static int imx8m_power_domain_on(struct power_domain *power_domain) } } + /* delay for reset to propagate */ + udelay(5); + if (domain->bits.pxx) { /* request the domain to power up */ setbits_le32(base + regs->pup, domain->bits.pxx); diff --git a/drivers/ram/starfive/starfive_ddr.c b/drivers/ram/starfive/starfive_ddr.c index 553f2ce6f44..a0a3d6b33dc 100644 --- a/drivers/ram/starfive/starfive_ddr.c +++ b/drivers/ram/starfive/starfive_ddr.c @@ -72,8 +72,6 @@ static int starfive_ddr_probe(struct udevice *dev) u64 rate; int ret; - /* Read memory base and size from DT */ - fdtdec_setup_mem_size_base(); priv->info.base = gd->ram_base; priv->info.size = gd->ram_size; diff --git a/drivers/serial/serial_pl01x.c b/drivers/serial/serial_pl01x.c index f5468353e10..428a4d210de 100644 --- a/drivers/serial/serial_pl01x.c +++ b/drivers/serial/serial_pl01x.c @@ -291,8 +291,16 @@ int pl01x_serial_probe(struct udevice *dev) struct pl01x_serial_plat *plat = dev_get_plat(dev); struct pl01x_priv *priv = dev_get_priv(dev); +#if CONFIG_IS_ENABLED(OF_PLATDATA) + struct dtd_serial_pl01x *dtplat = &plat->dtplat; + + priv->regs = (struct pl01x_regs *)dtplat->reg[0]; + plat->type = dtplat->type; +#else priv->regs = (struct pl01x_regs *)plat->base; +#endif priv->type = plat->type; + if (!plat->skip_init) return pl01x_generic_serial_init(priv->regs, priv->type); else @@ -321,7 +329,7 @@ int pl01x_serial_pending(struct udevice *dev, bool input) if (input) return pl01x_tstc(priv->regs); else - return fr & UART_PL01x_FR_TXFF ? 0 : 1; + return fr & UART_PL01x_FR_TXFE ? 0 : 1; } static const struct dm_serial_ops pl01x_serial_ops = { @@ -331,7 +339,7 @@ static const struct dm_serial_ops pl01x_serial_ops = { .setbrg = pl01x_serial_setbrg, }; -#if CONFIG_IS_ENABLED(OF_CONTROL) +#if CONFIG_IS_ENABLED(OF_REAL) static const struct udevice_id pl01x_serial_id[] ={ {.compatible = "arm,pl011", .data = TYPE_PL011}, {.compatible = "arm,pl010", .data = TYPE_PL010}, @@ -380,8 +388,10 @@ int pl01x_serial_of_to_plat(struct udevice *dev) U_BOOT_DRIVER(serial_pl01x) = { .name = "serial_pl01x", .id = UCLASS_SERIAL, +#if CONFIG_IS_ENABLED(OF_REAL) .of_match = of_match_ptr(pl01x_serial_id), .of_to_plat = of_match_ptr(pl01x_serial_of_to_plat), +#endif .plat_auto = sizeof(struct pl01x_serial_plat), .probe = pl01x_serial_probe, .ops = &pl01x_serial_ops, @@ -389,6 +399,8 @@ U_BOOT_DRIVER(serial_pl01x) = { .priv_auto = sizeof(struct pl01x_priv), }; +DM_DRIVER_ALIAS(serial_pl01x, arm_pl011) +DM_DRIVER_ALIAS(serial_pl01x, arm_pl010) #endif #if defined(CONFIG_DEBUG_UART_PL010) || defined(CONFIG_DEBUG_UART_PL011) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 453a5983b2a..854b8b88daf 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -101,12 +101,21 @@ config ATMEL_SPI config BCM63XX_HSSPI bool "BCM63XX HSSPI driver" - depends on (ARCH_BMIPS || BCM6856 || BCM6858 || BCM63158) + depends on (ARCH_BMIPS || ARCH_BCMBCA) help - Enable the BCM6328 HSSPI driver. This driver can be used to + Enable the BCM63XX HSSPI driver. This driver can be used to access the SPI NOR flash on platforms embedding this Broadcom SPI core. +config BCMBCA_HSSPI + bool "BCMBCA HSSPI driver" + depends on ARCH_BCMBCA && HAVE_SPI_CS_CTRL + help + This enables support for the High Speed SPI controller present on + newer Broadcom BCMBCA SoCs. These SoCs include an updated SPI controller + that adds the capability to allow the driver to control chip select + explicitly. + config BCM63XX_SPI bool "BCM6348 SPI driver" depends on ARCH_BMIPS diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 95dba9ac455..c27b3327c33 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -25,6 +25,7 @@ obj-$(CONFIG_ATH79_SPI) += ath79_spi.o obj-$(CONFIG_ATMEL_QSPI) += atmel-quadspi.o obj-$(CONFIG_ATMEL_SPI) += atmel_spi.o obj-$(CONFIG_BCM63XX_HSSPI) += bcm63xx_hsspi.o +obj-$(CONFIG_BCMBCA_HSSPI) += bcmbca_hsspi.o obj-$(CONFIG_BCM63XX_SPI) += bcm63xx_spi.o obj-$(CONFIG_BCMSTB_SPI) += bcmstb_spi.o obj-$(CONFIG_CF_SPI) += cf_spi.o diff --git a/drivers/spi/bcm63xx_hsspi.c b/drivers/spi/bcm63xx_hsspi.c index 4d714adc4af..a24bb430cbb 100644 --- a/drivers/spi/bcm63xx_hsspi.c +++ b/drivers/spi/bcm63xx_hsspi.c @@ -20,7 +20,13 @@ #define HSSPI_PP 0 -#define SPI_MAX_SYNC_CLOCK 30000000 +/* + * The maximum frequency for SPI synchronous mode is 30MHz for some chips and + * 25MHz for some others. This depends on the chip layout and SPI signals + * distance to the pad. We use the lower of these values to cover all relevant + * chips. + */ +#define SPI_MAX_SYNC_CLOCK 25000000 /* SPI Control register */ #define SPI_CTL_REG 0x000 @@ -72,12 +78,16 @@ #define SPI_PFL_MODE_REG(x) (0x100 + (0x20 * (x)) + 0x08) #define SPI_PFL_MODE_FILL_SHIFT 0 #define SPI_PFL_MODE_FILL_MASK (0xff << SPI_PFL_MODE_FILL_SHIFT) +#define SPI_PFL_MODE_MDRDST_SHIFT 8 +#define SPI_PFL_MODE_MDWRST_SHIFT 12 #define SPI_PFL_MODE_MDRDSZ_SHIFT 16 #define SPI_PFL_MODE_MDRDSZ_MASK (1 << SPI_PFL_MODE_MDRDSZ_SHIFT) #define SPI_PFL_MODE_MDWRSZ_SHIFT 18 #define SPI_PFL_MODE_MDWRSZ_MASK (1 << SPI_PFL_MODE_MDWRSZ_SHIFT) #define SPI_PFL_MODE_3WIRE_SHIFT 20 #define SPI_PFL_MODE_3WIRE_MASK (1 << SPI_PFL_MODE_3WIRE_SHIFT) +#define SPI_PFL_MODE_PREPCNT_SHIFT 24 +#define SPI_PFL_MODE_PREPCNT_MASK (4 << SPI_PFL_MODE_PREPCNT_SHIFT) /* SPI Ping-Pong FIFO registers */ #define HSSPI_FIFO_SIZE 0x200 @@ -96,12 +106,21 @@ #define HSSPI_FIFO_OP_CODE_W (2 << HSSPI_FIFO_OP_CODE_SHIFT) #define HSSPI_FIFO_OP_CODE_R (3 << HSSPI_FIFO_OP_CODE_SHIFT) +#define HSSPI_MAX_DATA_SIZE (HSSPI_FIFO_SIZE - HSSPI_FIFO_OP_SIZE) +#define HSSPI_MAX_PREPEND_SIZE 15 + +#define HSSPI_XFER_MODE_PREPEND 0 +#define HSSPI_XFER_MODE_DUMMYCS 1 + struct bcm63xx_hsspi_priv { void __iomem *regs; ulong clk_rate; uint8_t num_cs; uint8_t cs_pols; uint speed; + uint xfer_mode; + uint32_t prepend_cnt; + uint8_t prepend_buf[HSSPI_MAX_PREPEND_SIZE]; }; static int bcm63xx_hsspi_cs_info(struct udevice *bus, uint cs, @@ -143,9 +162,16 @@ static void bcm63xx_hsspi_activate_cs(struct bcm63xx_hsspi_priv *priv, struct dm_spi_slave_plat *plat) { uint32_t clr, set; + uint speed = priv->speed; + + if (priv->xfer_mode == HSSPI_XFER_MODE_DUMMYCS && + speed > SPI_MAX_SYNC_CLOCK) { + speed = SPI_MAX_SYNC_CLOCK; + debug("Force to dummy cs mode. Reduce the speed to %dHz\n", speed); + } /* profile clock */ - set = DIV_ROUND_UP(priv->clk_rate, priv->speed); + set = DIV_ROUND_UP(priv->clk_rate, speed); set = DIV_ROUND_UP(2048, set); set &= SPI_PFL_CLK_FREQ_MASK; set |= SPI_PFL_CLK_RSTLOOP_MASK; @@ -164,7 +190,7 @@ static void bcm63xx_hsspi_activate_cs(struct bcm63xx_hsspi_priv *priv, set |= SPI_PFL_SIG_LATCHRIS_MASK; /* async clk */ - if (priv->speed > SPI_MAX_SYNC_CLOCK) + if (speed > SPI_MAX_SYNC_CLOCK) set |= SPI_PFL_SIG_ASYNCIN_MASK; clrsetbits_32(priv->regs + SPI_PFL_SIG_REG(plat->cs), clr, set); @@ -173,17 +199,24 @@ static void bcm63xx_hsspi_activate_cs(struct bcm63xx_hsspi_priv *priv, set = 0; clr = 0; - /* invert cs polarity */ - if (priv->cs_pols & BIT(plat->cs)) - clr |= BIT(plat->cs); - else - set |= BIT(plat->cs); - - /* invert dummy cs polarity */ - if (priv->cs_pols & BIT(!plat->cs)) - clr |= BIT(!plat->cs); - else - set |= BIT(!plat->cs); + if (priv->xfer_mode == HSSPI_XFER_MODE_PREPEND) { + if (priv->cs_pols & BIT(plat->cs)) + set |= BIT(plat->cs); + else + clr |= BIT(plat->cs); + } else { + /* invert cs polarity */ + if (priv->cs_pols & BIT(plat->cs)) + clr |= BIT(plat->cs); + else + set |= BIT(plat->cs); + + /* invert dummy cs polarity */ + if (priv->cs_pols & BIT(!plat->cs)) + clr |= BIT(!plat->cs); + else + set |= BIT(!plat->cs); + } clrsetbits_32(priv->regs + SPI_CTL_REG, clr, set); } @@ -212,16 +245,21 @@ static void bcm63xx_hsspi_deactivate_cs(struct bcm63xx_hsspi_priv *priv) * all the time. This hack is also used in the upstream linux driver and * allows keeping CS active between transfers even if the HW doesn't give * this possibility. + * + * This workaround only works when the dummy CS (usually CS1 when the actual + * CS is 0) pinmuxed to SPI chip select function if SPI clock is faster than + * SPI_MAX_SYNC_CLOCK. In old broadcom chip, CS1 pin is default to chip select + * function. But this is not the case for new chips. To make this function + * always work, it should be called with maximum clock of SPI_MAX_SYNC_CLOCK. */ -static int bcm63xx_hsspi_xfer(struct udevice *dev, unsigned int bitlen, - const void *dout, void *din, unsigned long flags) +static int bcm63xx_hsspi_xfer_dummy_cs(struct udevice *dev, unsigned int data_bytes, + const void *dout, void *din, unsigned long flags) { struct bcm63xx_hsspi_priv *priv = dev_get_priv(dev->parent); struct dm_spi_slave_plat *plat = dev_get_parent_plat(dev); - size_t data_bytes = bitlen / 8; size_t step_size = HSSPI_FIFO_SIZE; uint16_t opcode = 0; - uint32_t val; + uint32_t val = SPI_PFL_MODE_FILL_MASK; const uint8_t *tx = dout; uint8_t *rx = din; @@ -240,14 +278,17 @@ static int bcm63xx_hsspi_xfer(struct udevice *dev, unsigned int bitlen, step_size -= HSSPI_FIFO_OP_SIZE; /* dual mode */ - if ((opcode == HSSPI_FIFO_OP_CODE_R && plat->mode == SPI_RX_DUAL) || - (opcode == HSSPI_FIFO_OP_CODE_W && plat->mode == SPI_TX_DUAL)) + if ((opcode == HSSPI_FIFO_OP_CODE_R && (plat->mode & SPI_RX_DUAL)) || + (opcode == HSSPI_FIFO_OP_CODE_W && (plat->mode & SPI_TX_DUAL))) { opcode |= HSSPI_FIFO_OP_MBIT_MASK; - /* profile mode */ - val = SPI_PFL_MODE_FILL_MASK | - SPI_PFL_MODE_MDRDSZ_MASK | - SPI_PFL_MODE_MDWRSZ_MASK; + /* profile mode */ + if (plat->mode & SPI_RX_DUAL) + val |= SPI_PFL_MODE_MDRDSZ_MASK; + if (plat->mode & SPI_TX_DUAL) + val |= SPI_PFL_MODE_MDWRSZ_MASK; + } + if (plat->mode & SPI_3WIRE) val |= SPI_PFL_MODE_3WIRE_MASK; writel(val, priv->regs + SPI_PFL_MODE_REG(plat->cs)); @@ -301,6 +342,182 @@ static int bcm63xx_hsspi_xfer(struct udevice *dev, unsigned int bitlen, return 0; } +static int bcm63xx_prepare_prepend_transfer(struct bcm63xx_hsspi_priv *priv, + unsigned int data_bytes, const void *dout, void *din, + unsigned long flags) +{ + /* + * only support multiple half duplex write transfer + optional + * full duplex read/write at the end. + */ + if (flags & SPI_XFER_BEGIN) { + /* clear prepends */ + priv->prepend_cnt = 0; + } + + if (din) { + /* buffering reads not possible for prepend mode */ + if (!(flags & SPI_XFER_END)) { + debug("unable to buffer reads\n"); + return HSSPI_XFER_MODE_DUMMYCS; + } + + /* check rx size */ + if (data_bytes > HSSPI_MAX_DATA_SIZE) { + debug("max rx bytes exceeded\n"); + return HSSPI_XFER_MODE_DUMMYCS; + } + } + + if (dout) { + /* check tx size */ + if (flags & SPI_XFER_END) { + if (priv->prepend_cnt + data_bytes > HSSPI_MAX_DATA_SIZE) { + debug("max tx bytes exceeded\n"); + return HSSPI_XFER_MODE_DUMMYCS; + } + } else { + if (priv->prepend_cnt + data_bytes > HSSPI_MAX_PREPEND_SIZE) { + debug("max prepend bytes exceeded\n"); + return HSSPI_XFER_MODE_DUMMYCS; + } + + /* + * buffer transfer data in the prepend buf in case we have to fall + * back to dummy cs mode. + */ + memcpy(&priv->prepend_buf[priv->prepend_cnt], dout, data_bytes); + priv->prepend_cnt += data_bytes; + } + } + + return HSSPI_XFER_MODE_PREPEND; +} + +static int bcm63xx_hsspi_xfer_prepend(struct udevice *dev, unsigned int data_bytes, + const void *dout, void *din, unsigned long flags) +{ + struct bcm63xx_hsspi_priv *priv = dev_get_priv(dev->parent); + struct dm_spi_slave_plat *plat = dev_get_parent_plat(dev); + uint16_t opcode = 0; + uint32_t val, offset; + int ret; + + if (flags & SPI_XFER_END) { + offset = HSSPI_FIFO_BASE + HSSPI_FIFO_OP_SIZE; + if (priv->prepend_cnt) { + /* copy prepend data */ + memcpy_toio(priv->regs + offset, + priv->prepend_buf, priv->prepend_cnt); + } + + if (dout && data_bytes) { + /* copy tx data */ + offset += priv->prepend_cnt; + memcpy_toio(priv->regs + offset, dout, data_bytes); + } + + bcm63xx_hsspi_activate_cs(priv, plat); + if (dout && !din) { + /* all half-duplex write. merge to single write */ + data_bytes += priv->prepend_cnt; + opcode = HSSPI_FIFO_OP_CODE_W; + priv->prepend_cnt = 0; + } else if (!dout && din) { + /* half-duplex read with prepend write */ + opcode = HSSPI_FIFO_OP_CODE_R; + } else { + /* full duplex read/write */ + opcode = HSSPI_FIFO_OP_READ_WRITE; + } + + /* profile mode */ + val = SPI_PFL_MODE_FILL_MASK; + if (plat->mode & SPI_3WIRE) + val |= SPI_PFL_MODE_3WIRE_MASK; + + /* dual mode */ + if ((opcode == HSSPI_FIFO_OP_CODE_R && (plat->mode & SPI_RX_DUAL)) || + (opcode == HSSPI_FIFO_OP_CODE_W && (plat->mode & SPI_TX_DUAL))) { + opcode |= HSSPI_FIFO_OP_MBIT_MASK; + + if (plat->mode & SPI_RX_DUAL) { + val |= SPI_PFL_MODE_MDRDSZ_MASK; + val |= priv->prepend_cnt << SPI_PFL_MODE_MDRDST_SHIFT; + } + if (plat->mode & SPI_TX_DUAL) { + val |= SPI_PFL_MODE_MDWRSZ_MASK; + val |= priv->prepend_cnt << SPI_PFL_MODE_MDWRST_SHIFT; + } + } + val |= (priv->prepend_cnt << SPI_PFL_MODE_PREPCNT_SHIFT); + writel(val, priv->regs + SPI_PFL_MODE_REG(plat->cs)); + + /* set fifo operation */ + val = opcode | (data_bytes & HSSPI_FIFO_OP_BYTES_MASK); + writew(cpu_to_be16(val), + priv->regs + HSSPI_FIFO_OP_REG); + + /* issue the transfer */ + val = SPI_CMD_OP_START; + val |= (plat->cs << SPI_CMD_PFL_SHIFT) & + SPI_CMD_PFL_MASK; + val |= (plat->cs << SPI_CMD_SLAVE_SHIFT) & + SPI_CMD_SLAVE_MASK; + writel(val, priv->regs + SPI_CMD_REG); + + /* wait for completion */ + ret = wait_for_bit_32(priv->regs + SPI_STAT_REG, + SPI_STAT_SRCBUSY_MASK, false, + 1000, false); + if (ret) { + bcm63xx_hsspi_deactivate_cs(priv); + printf("spi polling timeout\n"); + return ret; + } + + /* copy rx data */ + if (din) + memcpy_fromio(din, priv->regs + HSSPI_FIFO_BASE, + data_bytes); + bcm63xx_hsspi_deactivate_cs(priv); + } + + return 0; +} + +static int bcm63xx_hsspi_xfer(struct udevice *dev, unsigned int bitlen, + const void *dout, void *din, unsigned long flags) +{ + struct bcm63xx_hsspi_priv *priv = dev_get_priv(dev->parent); + int ret; + u32 data_bytes = bitlen >> 3; + + if (priv->xfer_mode == HSSPI_XFER_MODE_PREPEND) { + priv->xfer_mode = + bcm63xx_prepare_prepend_transfer(priv, data_bytes, dout, din, flags); + } + + /* if not prependable, fall back to dummy cs mode with safe clock */ + if (priv->xfer_mode == HSSPI_XFER_MODE_DUMMYCS) { + /* For pending prepend data from previous transfers, send it first */ + if (priv->prepend_cnt) { + bcm63xx_hsspi_xfer_dummy_cs(dev, priv->prepend_cnt, + priv->prepend_buf, NULL, + (flags & ~SPI_XFER_END) | SPI_XFER_BEGIN); + priv->prepend_cnt = 0; + } + ret = bcm63xx_hsspi_xfer_dummy_cs(dev, data_bytes, dout, din, flags); + } else { + ret = bcm63xx_hsspi_xfer_prepend(dev, data_bytes, dout, din, flags); + } + + if (flags & SPI_XFER_END) + priv->xfer_mode = HSSPI_XFER_MODE_PREPEND; + + return ret; +} + static const struct dm_spi_ops bcm63xx_hsspi_ops = { .cs_info = bcm63xx_hsspi_cs_info, .set_mode = bcm63xx_hsspi_set_mode, @@ -310,6 +527,7 @@ static const struct dm_spi_ops bcm63xx_hsspi_ops = { static const struct udevice_id bcm63xx_hsspi_ids[] = { { .compatible = "brcm,bcm6328-hsspi", }, + { .compatible = "brcm,bcmbca-hsspi-v1.0", }, { /* sentinel */ } }; @@ -317,6 +535,7 @@ static int bcm63xx_hsspi_child_pre_probe(struct udevice *dev) { struct bcm63xx_hsspi_priv *priv = dev_get_priv(dev->parent); struct dm_spi_slave_plat *plat = dev_get_parent_plat(dev); + struct spi_slave *slave = dev_get_parent_priv(dev); /* check cs */ if (plat->cs >= priv->num_cs) { @@ -330,6 +549,13 @@ static int bcm63xx_hsspi_child_pre_probe(struct udevice *dev) else priv->cs_pols &= ~BIT(plat->cs); + /* + * set the max read/write size to make sure each xfer are within the + * prepend limit + */ + slave->max_read_size = HSSPI_MAX_DATA_SIZE; + slave->max_write_size = HSSPI_MAX_DATA_SIZE; + return 0; } @@ -391,6 +617,9 @@ static int bcm63xx_hsspi_probe(struct udevice *dev) priv->cs_pols = readl(priv->regs + SPI_CTL_REG) & SPI_CTL_CS_POL_MASK; + /* default in prepend mode */ + priv->xfer_mode = HSSPI_XFER_MODE_PREPEND; + return 0; } diff --git a/drivers/spi/bcmbca_hsspi.c b/drivers/spi/bcmbca_hsspi.c new file mode 100644 index 00000000000..fbe315a7d45 --- /dev/null +++ b/drivers/spi/bcmbca_hsspi.c @@ -0,0 +1,414 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017 Ćlvaro FernĆ”ndez Rojas <noltari@gmail.com> + * + * Derived from linux/drivers/spi/spi-bcm63xx-hsspi.c: + * Copyright (C) 2000-2010 Broadcom Corporation + * Copyright (C) 2012-2013 Jonas Gorski <jogo@openwrt.org> + * Copyright (C) 2021 Broadcom Ltd + */ + +#include <common.h> +#include <asm/io.h> +#include <clk.h> +#include <spi.h> +#include <reset.h> +#include <wait_bit.h> +#include <dm.h> +#include <dm/device_compat.h> + +#define HSSPI_PP 0 + +#define SPI_MAX_SYNC_CLOCK 30000000 + +/* SPI Control register */ +#define SPI_CTL_REG 0x000 +#define SPI_CTL_CS_POL_SHIFT 0 +#define SPI_CTL_CS_POL_MASK (0xff << SPI_CTL_CS_POL_SHIFT) +#define SPI_CTL_CLK_GATE_SHIFT 16 +#define SPI_CTL_CLK_GATE_MASK BIT(SPI_CTL_CLK_GATE_SHIFT) +#define SPI_CTL_CLK_POL_SHIFT 17 +#define SPI_CTL_CLK_POL_MASK BIT(SPI_CTL_CLK_POL_SHIFT) + +/* SPI Interrupts registers */ +#define SPI_IR_STAT_REG 0x008 +#define SPI_IR_ST_MASK_REG 0x00c +#define SPI_IR_MASK_REG 0x010 + +#define SPI_IR_CLEAR_ALL 0xff001f1f + +/* SPI Ping-Pong Command registers */ +#define SPI_CMD_REG (0x080 + (0x40 * (HSSPI_PP)) + 0x00) +#define SPI_CMD_OP_SHIFT 0 +#define SPI_CMD_OP_START BIT(SPI_CMD_OP_SHIFT) +#define SPI_CMD_PFL_SHIFT 8 +#define SPI_CMD_PFL_MASK (0x7 << SPI_CMD_PFL_SHIFT) +#define SPI_CMD_SLAVE_SHIFT 12 +#define SPI_CMD_SLAVE_MASK (0x7 << SPI_CMD_SLAVE_SHIFT) + +/* SPI Ping-Pong Status registers */ +#define SPI_STAT_REG (0x080 + (0x40 * (HSSPI_PP)) + 0x04) +#define SPI_STAT_SRCBUSY_SHIFT 1 +#define SPI_STAT_SRCBUSY_MASK BIT(SPI_STAT_SRCBUSY_SHIFT) + +/* SPI Profile Clock registers */ +#define SPI_PFL_CLK_REG(x) (0x100 + (0x20 * (x)) + 0x00) +#define SPI_PFL_CLK_FREQ_SHIFT 0 +#define SPI_PFL_CLK_FREQ_MASK (0x3fff << SPI_PFL_CLK_FREQ_SHIFT) +#define SPI_PFL_CLK_RSTLOOP_SHIFT 15 +#define SPI_PFL_CLK_RSTLOOP_MASK BIT(SPI_PFL_CLK_RSTLOOP_SHIFT) + +/* SPI Profile Signal registers */ +#define SPI_PFL_SIG_REG(x) (0x100 + (0x20 * (x)) + 0x04) +#define SPI_PFL_SIG_LATCHRIS_SHIFT 12 +#define SPI_PFL_SIG_LATCHRIS_MASK BIT(SPI_PFL_SIG_LATCHRIS_SHIFT) +#define SPI_PFL_SIG_LAUNCHRIS_SHIFT 13 +#define SPI_PFL_SIG_LAUNCHRIS_MASK BIT(SPI_PFL_SIG_LAUNCHRIS_SHIFT) +#define SPI_PFL_SIG_ASYNCIN_SHIFT 16 +#define SPI_PFL_SIG_ASYNCIN_MASK BIT(SPI_PFL_SIG_ASYNCIN_SHIFT) + +/* SPI Profile Mode registers */ +#define SPI_PFL_MODE_REG(x) (0x100 + (0x20 * (x)) + 0x08) +#define SPI_PFL_MODE_FILL_SHIFT 0 +#define SPI_PFL_MODE_FILL_MASK (0xff << SPI_PFL_MODE_FILL_SHIFT) +#define SPI_PFL_MODE_MDRDSZ_SHIFT 16 +#define SPI_PFL_MODE_MDRDSZ_MASK BIT(SPI_PFL_MODE_MDRDSZ_SHIFT) +#define SPI_PFL_MODE_MDWRSZ_SHIFT 18 +#define SPI_PFL_MODE_MDWRSZ_MASK BIT(SPI_PFL_MODE_MDWRSZ_SHIFT) +#define SPI_PFL_MODE_3WIRE_SHIFT 20 +#define SPI_PFL_MODE_3WIRE_MASK BIT(SPI_PFL_MODE_3WIRE_SHIFT) + +/* SPI Ping-Pong FIFO registers */ +#define HSSPI_FIFO_SIZE 0x200 +#define HSSPI_FIFO_BASE (0x200 + \ + (HSSPI_FIFO_SIZE * HSSPI_PP)) + +/* SPI Ping-Pong FIFO OP register */ +#define HSSPI_FIFO_OP_SIZE 0x2 +#define HSSPI_FIFO_OP_REG (HSSPI_FIFO_BASE + 0x00) +#define HSSPI_FIFO_OP_BYTES_SHIFT 0 +#define HSSPI_FIFO_OP_BYTES_MASK (0x3ff << HSSPI_FIFO_OP_BYTES_SHIFT) +#define HSSPI_FIFO_OP_MBIT_SHIFT 11 +#define HSSPI_FIFO_OP_MBIT_MASK BIT(HSSPI_FIFO_OP_MBIT_SHIFT) +#define HSSPI_FIFO_OP_CODE_SHIFT 13 +#define HSSPI_FIFO_OP_READ_WRITE (1 << HSSPI_FIFO_OP_CODE_SHIFT) +#define HSSPI_FIFO_OP_CODE_W (2 << HSSPI_FIFO_OP_CODE_SHIFT) +#define HSSPI_FIFO_OP_CODE_R (3 << HSSPI_FIFO_OP_CODE_SHIFT) + +#define HSSPI_MAX_DATA_SIZE (HSSPI_FIFO_SIZE - HSSPI_FIFO_OP_SIZE) + +#define SPIM_CTRL_CS_OVERRIDE_SEL_SHIFT 0 +#define SPIM_CTRL_CS_OVERRIDE_SEL_MASK 0xff +#define SPIM_CTRL_CS_OVERRIDE_VAL_SHIFT 8 +#define SPIM_CTRL_CS_OVERRIDE_VAL_MASK 0xff + +struct bcmbca_hsspi_priv { + void __iomem *regs; + void __iomem *spim_ctrl; + u32 clk_rate; + u8 num_cs; + u8 cs_pols; + u32 speed; +}; + +static int bcmbca_hsspi_cs_info(struct udevice *bus, uint cs, + struct spi_cs_info *info) +{ + struct bcmbca_hsspi_priv *priv = dev_get_priv(bus); + + if (cs >= priv->num_cs) { + dev_err(bus, "no cs %u\n", cs); + return -EINVAL; + } + + return 0; +} + +static int bcmbca_hsspi_set_mode(struct udevice *bus, uint mode) +{ + struct bcmbca_hsspi_priv *priv = dev_get_priv(bus); + + /* clock polarity */ + if (mode & SPI_CPOL) + setbits_32(priv->regs + SPI_CTL_REG, SPI_CTL_CLK_POL_MASK); + else + clrbits_32(priv->regs + SPI_CTL_REG, SPI_CTL_CLK_POL_MASK); + + return 0; +} + +static int bcmbca_hsspi_set_speed(struct udevice *bus, uint speed) +{ + struct bcmbca_hsspi_priv *priv = dev_get_priv(bus); + + priv->speed = speed; + + return 0; +} + +static void bcmbca_hsspi_setup_clock(struct bcmbca_hsspi_priv *priv, + struct dm_spi_slave_plat *plat) +{ + u32 clr, set; + + /* profile clock */ + set = DIV_ROUND_UP(priv->clk_rate, priv->speed); + set = DIV_ROUND_UP(2048, set); + set &= SPI_PFL_CLK_FREQ_MASK; + set |= SPI_PFL_CLK_RSTLOOP_MASK; + writel(set, priv->regs + SPI_PFL_CLK_REG(plat->cs)); + + /* profile signal */ + set = 0; + clr = SPI_PFL_SIG_LAUNCHRIS_MASK | + SPI_PFL_SIG_LATCHRIS_MASK | + SPI_PFL_SIG_ASYNCIN_MASK; + + /* latch/launch config */ + if (plat->mode & SPI_CPHA) + set |= SPI_PFL_SIG_LAUNCHRIS_MASK; + else + set |= SPI_PFL_SIG_LATCHRIS_MASK; + + /* async clk */ + if (priv->speed > SPI_MAX_SYNC_CLOCK) + set |= SPI_PFL_SIG_ASYNCIN_MASK; + + clrsetbits_32(priv->regs + SPI_PFL_SIG_REG(plat->cs), clr, set); + + /* global control */ + set = 0; + clr = 0; + + if (priv->cs_pols & BIT(plat->cs)) + set |= BIT(plat->cs); + else + clr |= BIT(plat->cs); + + clrsetbits_32(priv->regs + SPI_CTL_REG, clr, set); +} + +static void bcmbca_hsspi_activate_cs(struct bcmbca_hsspi_priv *priv, + struct dm_spi_slave_plat *plat) +{ + u32 val; + + /* set the override bit */ + val = readl(priv->spim_ctrl); + val |= BIT(plat->cs + SPIM_CTRL_CS_OVERRIDE_SEL_SHIFT); + writel(val, priv->spim_ctrl); +} + +static void bcmbca_hsspi_deactivate_cs(struct bcmbca_hsspi_priv *priv, + struct dm_spi_slave_plat *plat) +{ + u32 val; + + /* clear the cs override bit */ + val = readl(priv->spim_ctrl); + val &= ~BIT(plat->cs + SPIM_CTRL_CS_OVERRIDE_SEL_SHIFT); + writel(val, priv->spim_ctrl); +} + +static int bcmbca_hsspi_xfer(struct udevice *dev, unsigned int bitlen, + const void *dout, void *din, unsigned long flags) +{ + struct bcmbca_hsspi_priv *priv = dev_get_priv(dev->parent); + struct dm_spi_slave_plat *plat = dev_get_parent_plat(dev); + size_t data_bytes = bitlen / 8; + size_t step_size = HSSPI_FIFO_SIZE; + u16 opcode = 0; + u32 val = SPI_PFL_MODE_FILL_MASK; + const u8 *tx = dout; + u8 *rx = din; + u32 cs_act = 0; + + if (flags & SPI_XFER_BEGIN) + bcmbca_hsspi_setup_clock(priv, plat); + + /* fifo operation */ + if (tx && rx) + opcode = HSSPI_FIFO_OP_READ_WRITE; + else if (rx) + opcode = HSSPI_FIFO_OP_CODE_R; + else if (tx) + opcode = HSSPI_FIFO_OP_CODE_W; + + if (opcode != HSSPI_FIFO_OP_CODE_R) + step_size -= HSSPI_FIFO_OP_SIZE; + + /* dual mode */ + if ((opcode == HSSPI_FIFO_OP_CODE_R && (plat->mode & SPI_RX_DUAL)) || + (opcode == HSSPI_FIFO_OP_CODE_W && (plat->mode & SPI_TX_DUAL))) { + opcode |= HSSPI_FIFO_OP_MBIT_MASK; + + /* profile mode */ + if (plat->mode & SPI_RX_DUAL) + val |= SPI_PFL_MODE_MDRDSZ_MASK; + if (plat->mode & SPI_TX_DUAL) + val |= SPI_PFL_MODE_MDWRSZ_MASK; + } + + if (plat->mode & SPI_3WIRE) + val |= SPI_PFL_MODE_3WIRE_MASK; + writel(val, priv->regs + SPI_PFL_MODE_REG(plat->cs)); + + /* transfer loop */ + while (data_bytes > 0) { + size_t curr_step = min(step_size, data_bytes); + int ret; + + /* copy tx data */ + if (tx) { + memcpy_toio(priv->regs + HSSPI_FIFO_BASE + + HSSPI_FIFO_OP_SIZE, tx, curr_step); + tx += curr_step; + } + + /* set fifo operation */ + writew(cpu_to_be16(opcode | (curr_step & HSSPI_FIFO_OP_BYTES_MASK)), + priv->regs + HSSPI_FIFO_OP_REG); + + /* make sure we keep cs active until spi transfer is done */ + if (!cs_act) { + bcmbca_hsspi_activate_cs(priv, plat); + cs_act = 1; + } + + /* issue the transfer */ + val = SPI_CMD_OP_START; + val |= (plat->cs << SPI_CMD_PFL_SHIFT) & + SPI_CMD_PFL_MASK; + val |= (plat->cs << SPI_CMD_SLAVE_SHIFT) & + SPI_CMD_SLAVE_MASK; + writel(val, priv->regs + SPI_CMD_REG); + + /* wait for completion */ + ret = wait_for_bit_32(priv->regs + SPI_STAT_REG, + SPI_STAT_SRCBUSY_MASK, false, + 1000, false); + if (ret) { + bcmbca_hsspi_deactivate_cs(priv, plat); + dev_err(dev, "interrupt timeout\n"); + return ret; + } + + data_bytes -= curr_step; + if ((flags & SPI_XFER_END) && !data_bytes) + bcmbca_hsspi_deactivate_cs(priv, plat); + + /* copy rx data */ + if (rx) { + memcpy_fromio(rx, priv->regs + HSSPI_FIFO_BASE, + curr_step); + rx += curr_step; + } + } + + return 0; +} + +static const struct dm_spi_ops bcmbca_hsspi_ops = { + .cs_info = bcmbca_hsspi_cs_info, + .set_mode = bcmbca_hsspi_set_mode, + .set_speed = bcmbca_hsspi_set_speed, + .xfer = bcmbca_hsspi_xfer, +}; + +static const struct udevice_id bcmbca_hsspi_ids[] = { + { .compatible = "brcm,bcmbca-hsspi-v1.1", }, + { /* sentinel */ } +}; + +static int bcmbca_hsspi_child_pre_probe(struct udevice *dev) +{ + struct bcmbca_hsspi_priv *priv = dev_get_priv(dev->parent); + struct dm_spi_slave_plat *plat = dev_get_parent_plat(dev); + u32 val; + + /* check cs */ + if (plat->cs >= priv->num_cs) { + dev_err(dev, "no cs %u\n", plat->cs); + return -EINVAL; + } + + /* cs polarity */ + if (plat->mode & SPI_CS_HIGH) + priv->cs_pols |= BIT(plat->cs); + else + priv->cs_pols &= ~BIT(plat->cs); + + /* set the polarity to spim cs register */ + val = readl(priv->spim_ctrl); + val &= ~BIT(plat->cs + SPIM_CTRL_CS_OVERRIDE_VAL_SHIFT); + if (priv->cs_pols & BIT(plat->cs)) + val |= BIT(plat->cs + SPIM_CTRL_CS_OVERRIDE_VAL_SHIFT); + writel(val, priv->spim_ctrl); + + return 0; +} + +static int bcmbca_hsspi_probe(struct udevice *dev) +{ + struct bcmbca_hsspi_priv *priv = dev_get_priv(dev); + struct clk clk; + int ret; + + priv->regs = dev_remap_addr_name(dev, "hsspi"); + if (!priv->regs) + return -EINVAL; + + priv->spim_ctrl = dev_remap_addr_name(dev, "spim-ctrl"); + if (!priv->spim_ctrl) { + dev_err(dev, "misc spim ctrl register not defined in dts!\n"); + return -EINVAL; + } + + priv->num_cs = dev_read_u32_default(dev, "num-cs", 8); + + /* enable clock */ + ret = clk_get_by_name(dev, "hsspi", &clk); + if (ret < 0) + return ret; + + ret = clk_enable(&clk); + if (ret < 0 && ret != -ENOSYS) + return ret; + + clk_free(&clk); + + /* get clock rate */ + ret = clk_get_by_name(dev, "pll", &clk); + if (ret < 0 && ret != -ENOSYS) + return ret; + + priv->clk_rate = clk_get_rate(&clk); + + clk_free(&clk); + + /* initialize hardware */ + writel(0, priv->regs + SPI_IR_MASK_REG); + + /* clear pending interrupts */ + writel(SPI_IR_CLEAR_ALL, priv->regs + SPI_IR_STAT_REG); + + /* enable clk gate */ + setbits_32(priv->regs + SPI_CTL_REG, SPI_CTL_CLK_GATE_MASK); + + /* read default cs polarities */ + priv->cs_pols = readl(priv->regs + SPI_CTL_REG) & + SPI_CTL_CS_POL_MASK; + + dev_info(dev, "Broadcom BCMBCA HS SPI bus driver\n"); + return 0; +} + +U_BOOT_DRIVER(bcmbca_hsspi) = { + .name = "bcmbca_hsspi", + .id = UCLASS_SPI, + .of_match = bcmbca_hsspi_ids, + .ops = &bcmbca_hsspi_ops, + .priv_auto = sizeof(struct bcmbca_hsspi_priv), + .child_pre_probe = bcmbca_hsspi_child_pre_probe, + .probe = bcmbca_hsspi_probe, +}; diff --git a/drivers/spi/npcm_pspi.c b/drivers/spi/npcm_pspi.c index bd9ac654113..37bab709672 100644 --- a/drivers/spi/npcm_pspi.c +++ b/drivers/spi/npcm_pspi.c @@ -40,7 +40,7 @@ static inline void spi_cs_activate(struct udevice *dev) struct udevice *bus = dev->parent; struct npcm_pspi_priv *priv = dev_get_priv(bus); - dm_gpio_set_value(&priv->cs_gpio, 0); + dm_gpio_set_value(&priv->cs_gpio, 1); } static inline void spi_cs_deactivate(struct udevice *dev) @@ -48,7 +48,7 @@ static inline void spi_cs_deactivate(struct udevice *dev) struct udevice *bus = dev->parent; struct npcm_pspi_priv *priv = dev_get_priv(bus); - dm_gpio_set_value(&priv->cs_gpio, 1); + dm_gpio_set_value(&priv->cs_gpio, 0); } static inline void npcm_pspi_enable(struct npcm_pspi_priv *priv) @@ -122,6 +122,9 @@ static int npcm_pspi_xfer(struct udevice *dev, unsigned int bitlen, if (flags & SPI_XFER_END) spi_cs_deactivate(dev); + debug("npcm_pspi_xfer: slave %s:%s dout %08X din %08X bitlen %u\n", + dev->parent->name, dev->name, *(uint *)tx, *(uint *)rx, bitlen); + npcm_pspi_disable(priv); return ret; @@ -183,6 +186,7 @@ static int npcm_pspi_set_mode(struct udevice *bus, uint mode) val |= pspi_mode; writew(val, priv->base + PSPI_CTL1); + debug("%s: mode=%u\n", __func__, mode); return 0; } @@ -197,9 +201,9 @@ static int npcm_pspi_probe(struct udevice *bus) return ret; priv->base = dev_read_addr_ptr(bus); - priv->max_hz = dev_read_u32_default(bus, "spi-max-frequency", 0); + priv->max_hz = dev_read_u32_default(bus, "spi-max-frequency", 1000000); gpio_request_by_name_nodev(offset_to_ofnode(node), "cs-gpios", 0, - &priv->cs_gpio, GPIOD_IS_OUT); + &priv->cs_gpio, GPIOD_IS_OUT| GPIOD_ACTIVE_LOW); return 0; } diff --git a/drivers/spi/pl022_spi.c b/drivers/spi/pl022_spi.c index 828eab3d342..fc7388b379d 100644 --- a/drivers/spi/pl022_spi.c +++ b/drivers/spi/pl022_spi.c @@ -12,9 +12,11 @@ #include <clk.h> #include <common.h> #include <dm.h> -#include <dm/platform_data/spi_pl022.h> +#include <dm/device_compat.h> +#include <fdtdec.h> #include <linux/io.h> #include <asm/global_data.h> +#include <asm/gpio.h> #include <spi.h> #define SSP_CR0 0x000 @@ -66,6 +68,15 @@ #define SSP_SR_MASK_RFF (0x1 << 3) /* Receive FIFO full */ #define SSP_SR_MASK_BSY (0x1 << 4) /* Busy Flag */ +struct pl022_spi_pdata { + fdt_addr_t addr; + fdt_size_t size; + unsigned int freq; +#if CONFIG_IS_ENABLED(DM_GPIO) + struct gpio_desc cs_gpio; +#endif +}; + struct pl022_spi_slave { void *base; unsigned int freq; @@ -107,7 +118,7 @@ static int pl022_spi_probe(struct udevice *bus) return 0; } -static void flush(struct pl022_spi_slave *ps) +static void pl022_spi_flush(struct pl022_spi_slave *ps) { do { while (readw(ps->base + SSP_SR) & SSP_SR_MASK_RNE) @@ -126,7 +137,7 @@ static int pl022_spi_claim_bus(struct udevice *dev) reg |= SSP_CR1_MASK_SSE; writew(reg, ps->base + SSP_CR1); - flush(ps); + pl022_spi_flush(ps); return 0; } @@ -137,7 +148,7 @@ static int pl022_spi_release_bus(struct udevice *dev) struct pl022_spi_slave *ps = dev_get_priv(bus); u16 reg; - flush(ps); + pl022_spi_flush(ps); /* Disable the SPI hardware */ reg = readw(ps->base + SSP_CR1); @@ -147,6 +158,17 @@ static int pl022_spi_release_bus(struct udevice *dev) return 0; } +static void pl022_spi_set_cs(struct udevice *dev, bool on) +{ +#if CONFIG_IS_ENABLED(DM_GPIO) + struct udevice *bus = dev->parent; + struct pl022_spi_pdata *plat = dev_get_plat(bus); + + if (dm_gpio_is_valid(&plat->cs_gpio)) + dm_gpio_set_value(&plat->cs_gpio, on ? 1 : 0); +#endif +} + static int pl022_spi_xfer(struct udevice *dev, unsigned int bitlen, const void *dout, void *din, unsigned long flags) { @@ -159,7 +181,7 @@ static int pl022_spi_xfer(struct udevice *dev, unsigned int bitlen, if (bitlen == 0) /* Finish any previously submitted transfers */ - return 0; + goto done; /* * TODO: The controller can do non-multiple-of-8 bit @@ -172,9 +194,13 @@ static int pl022_spi_xfer(struct udevice *dev, unsigned int bitlen, if (bitlen % 8) { /* Errors always terminate an ongoing transfer */ flags |= SPI_XFER_END; - return -1; + ret = -1; + goto done; } + if (flags & SPI_XFER_BEGIN) + pl022_spi_set_cs(dev, true); + len = bitlen / 8; while (len_tx < len) { @@ -201,6 +227,10 @@ static int pl022_spi_xfer(struct udevice *dev, unsigned int bitlen, } } +done: + if (flags & SPI_XFER_END) + pl022_spi_set_cs(dev, false); + return ret; } @@ -303,11 +333,18 @@ static int pl022_spi_of_to_plat(struct udevice *bus) plat->freq = clk_get_rate(&clkdev); +#if CONFIG_IS_ENABLED(DM_GPIO) + ret = gpio_request_by_name(bus, "cs-gpios", 0, &plat->cs_gpio, + GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); + if (ret < 0 && ret != -ENOENT) + return ret; +#endif + return 0; } static const struct udevice_id pl022_spi_ids[] = { - { .compatible = "arm,pl022-spi" }, + { .compatible = "arm,pl022" }, { } }; #endif diff --git a/drivers/spi/soft_spi.c b/drivers/spi/soft_spi.c index f3602a25ba3..0fa14339bdc 100644 --- a/drivers/spi/soft_spi.c +++ b/drivers/spi/soft_spi.c @@ -248,20 +248,33 @@ static int soft_spi_probe(struct udevice *dev) cs_flags = (slave && slave->mode & SPI_CS_HIGH) ? 0 : GPIOD_ACTIVE_LOW; clk_flags = (slave && slave->mode & SPI_CPOL) ? GPIOD_ACTIVE_LOW : 0; - if (gpio_request_by_name(dev, "cs-gpios", 0, &plat->cs, - GPIOD_IS_OUT | cs_flags) || - gpio_request_by_name(dev, "gpio-sck", 0, &plat->sclk, - GPIOD_IS_OUT | clk_flags)) + ret = gpio_request_by_name(dev, "cs-gpios", 0, &plat->cs, + GPIOD_IS_OUT | cs_flags); + if (ret) + return -EINVAL; + + ret = gpio_request_by_name(dev, "gpio-sck", 0, &plat->sclk, + GPIOD_IS_OUT | clk_flags); + if (ret) + ret = gpio_request_by_name(dev, "sck-gpios", 0, &plat->sclk, + GPIOD_IS_OUT | clk_flags); + if (ret) return -EINVAL; ret = gpio_request_by_name(dev, "gpio-mosi", 0, &plat->mosi, GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); if (ret) + ret = gpio_request_by_name(dev, "mosi-gpios", 0, &plat->mosi, + GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); + if (ret) plat->flags |= SPI_MASTER_NO_TX; ret = gpio_request_by_name(dev, "gpio-miso", 0, &plat->miso, GPIOD_IS_IN); if (ret) + ret = gpio_request_by_name(dev, "gpio-miso", 0, &plat->miso, + GPIOD_IS_IN); + if (ret) plat->flags |= SPI_MASTER_NO_RX; if ((plat->flags & (SPI_MASTER_NO_RX | SPI_MASTER_NO_TX)) == diff --git a/drivers/spi/spi-synquacer.c b/drivers/spi/spi-synquacer.c index 0f5d0a30c39..553f9687e3b 100644 --- a/drivers/spi/spi-synquacer.c +++ b/drivers/spi/spi-synquacer.c @@ -186,7 +186,7 @@ static void synquacer_spi_config(struct udevice *dev, void *rx, const void *tx) struct udevice *bus = dev->parent; struct synquacer_spi_priv *priv = dev_get_priv(bus); struct dm_spi_slave_plat *slave_plat = dev_get_parent_plat(dev); - u32 val, div, bus_width = 1; + u32 val, div, bus_width; int rwflag; rwflag = (rx ? 1 : 0) | (tx ? 2 : 0); @@ -203,16 +203,14 @@ static void synquacer_spi_config(struct udevice *dev, void *rx, const void *tx) priv->mode = slave_plat->mode; priv->speed = slave_plat->max_hz; - if (priv->mode & SPI_TX_BYTE) - bus_width = 1; - else if (priv->mode & SPI_TX_DUAL) + if (priv->mode & SPI_TX_DUAL) bus_width = 2; else if (priv->mode & SPI_TX_QUAD) bus_width = 4; else if (priv->mode & SPI_TX_OCTAL) bus_width = 8; else - log_warning("SPI mode not configured, setting to byte mode\n"); + bus_width = 1; /* default is single bit mode */ div = DIV_ROUND_UP(125000000, priv->speed); diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile index cdc20f5e946..1ca74805fd9 100644 --- a/drivers/timer/Makefile +++ b/drivers/timer/Makefile @@ -25,7 +25,7 @@ obj-$(CONFIG_RISCV_TIMER) += riscv_timer.o obj-$(CONFIG_ROCKCHIP_TIMER) += rockchip_timer.o obj-$(CONFIG_SANDBOX_TIMER) += sandbox_timer.o obj-$(CONFIG_SP804_TIMER) += sp804_timer.o -obj-$(CONFIG_$(SPL_)SIFIVE_CLINT) += sifive_clint_timer.o +obj-$(CONFIG_$(SPL_)RISCV_ACLINT) += riscv_aclint_timer.o obj-$(CONFIG_ARM_GLOBAL_TIMER) += arm_global_timer.o obj-$(CONFIG_STM32_TIMER) += stm32_timer.o obj-$(CONFIG_TEGRA_TIMER) += tegra-timer.o diff --git a/drivers/timer/riscv_aclint_timer.c b/drivers/timer/riscv_aclint_timer.c new file mode 100644 index 00000000000..e29d527c8d7 --- /dev/null +++ b/drivers/timer/riscv_aclint_timer.c @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2020, Sean Anderson <seanga2@gmail.com> + * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com> + */ + +#include <common.h> +#include <clk.h> +#include <dm.h> +#include <timer.h> +#include <asm/io.h> +#include <dm/device-internal.h> +#include <linux/err.h> + +#define CLINT_MTIME_OFFSET 0xbff8 +#define ACLINT_MTIME_OFFSET 0 + +/* mtime register */ +#define MTIME_REG(base, offset) ((ulong)(base) + (offset)) + +static u64 notrace riscv_aclint_timer_get_count(struct udevice *dev) +{ + return readq((void __iomem *)MTIME_REG(dev_get_priv(dev), + dev_get_driver_data(dev))); +} + +#if CONFIG_IS_ENABLED(RISCV_MMODE) && IS_ENABLED(CONFIG_TIMER_EARLY) +/** + * timer_early_get_rate() - Get the timer rate before driver model + */ +unsigned long notrace timer_early_get_rate(void) +{ + return RISCV_MMODE_TIMER_FREQ; +} + +/** + * timer_early_get_count() - Get the timer count before driver model + * + */ +u64 notrace timer_early_get_count(void) +{ + return readq((void __iomem *)MTIME_REG(RISCV_MMODE_TIMERBASE, + RISCV_MMODE_TIMEROFF)); +} +#endif + +static const struct timer_ops riscv_aclint_timer_ops = { + .get_count = riscv_aclint_timer_get_count, +}; + +static int riscv_aclint_timer_probe(struct udevice *dev) +{ + dev_set_priv(dev, dev_read_addr_ptr(dev)); + if (!dev_get_priv(dev)) + return -EINVAL; + + return timer_timebase_fallback(dev); +} + +static const struct udevice_id riscv_aclint_timer_ids[] = { + { .compatible = "riscv,clint0", .data = CLINT_MTIME_OFFSET }, + { .compatible = "sifive,clint0", .data = CLINT_MTIME_OFFSET }, + { .compatible = "riscv,aclint-mtimer", .data = ACLINT_MTIME_OFFSET }, + { } +}; + +U_BOOT_DRIVER(riscv_aclint_timer) = { + .name = "riscv_aclint_timer", + .id = UCLASS_TIMER, + .of_match = riscv_aclint_timer_ids, + .probe = riscv_aclint_timer_probe, + .ops = &riscv_aclint_timer_ops, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/drivers/timer/sifive_clint_timer.c b/drivers/timer/sifive_clint_timer.c deleted file mode 100644 index 939b99d937d..00000000000 --- a/drivers/timer/sifive_clint_timer.c +++ /dev/null @@ -1,68 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (C) 2020, Sean Anderson <seanga2@gmail.com> - * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com> - */ - -#include <common.h> -#include <clk.h> -#include <dm.h> -#include <timer.h> -#include <asm/io.h> -#include <dm/device-internal.h> -#include <linux/err.h> - -/* mtime register */ -#define MTIME_REG(base) ((ulong)(base) + 0xbff8) - -static u64 notrace sifive_clint_get_count(struct udevice *dev) -{ - return readq((void __iomem *)MTIME_REG(dev_get_priv(dev))); -} - -#if CONFIG_IS_ENABLED(RISCV_MMODE) && IS_ENABLED(CONFIG_TIMER_EARLY) -/** - * timer_early_get_rate() - Get the timer rate before driver model - */ -unsigned long notrace timer_early_get_rate(void) -{ - return RISCV_MMODE_TIMER_FREQ; -} - -/** - * timer_early_get_count() - Get the timer count before driver model - * - */ -u64 notrace timer_early_get_count(void) -{ - return readq((void __iomem *)MTIME_REG(RISCV_MMODE_TIMERBASE)); -} -#endif - -static const struct timer_ops sifive_clint_ops = { - .get_count = sifive_clint_get_count, -}; - -static int sifive_clint_probe(struct udevice *dev) -{ - dev_set_priv(dev, dev_read_addr_ptr(dev)); - if (!dev_get_priv(dev)) - return -EINVAL; - - return timer_timebase_fallback(dev); -} - -static const struct udevice_id sifive_clint_ids[] = { - { .compatible = "riscv,clint0" }, - { .compatible = "sifive,clint0" }, - { } -}; - -U_BOOT_DRIVER(sifive_clint) = { - .name = "sifive_clint", - .id = UCLASS_TIMER, - .of_match = sifive_clint_ids, - .probe = sifive_clint_probe, - .ops = &sifive_clint_ops, - .flags = DM_FLAG_PRE_RELOC, -}; diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c index 8dd29edd3de..3bf1a95e7f2 100644 --- a/drivers/ufs/ufs.c +++ b/drivers/ufs/ufs.c @@ -775,7 +775,7 @@ static inline void ufshcd_prepare_utp_nop_upiu(struct ufs_hba *hba) /* command descriptor fields */ ucd_req_ptr->header.dword_0 = - UPIU_HEADER_DWORD(UPIU_TRANSACTION_NOP_OUT, 0, 0, 0x1f); + UPIU_HEADER_DWORD(UPIU_TRANSACTION_NOP_OUT, 0, 0, TASK_TAG); /* clear rest of the fields of basic header */ ucd_req_ptr->header.dword_1 = 0; ucd_req_ptr->header.dword_2 = 0; diff --git a/drivers/video/console_truetype.c b/drivers/video/console_truetype.c index 6b5390136a7..0f9bb49e44f 100644 --- a/drivers/video/console_truetype.c +++ b/drivers/video/console_truetype.c @@ -62,10 +62,43 @@ static double tt_sqrt(double value) return lo; } +static double tt_fmod(double x, double y) +{ + double rem; + + if (y == 0.0) + return 0.0; + rem = x - (x / y) * y; + + return rem; +} + +/* dummy implementation */ +static double tt_pow(double x, double y) +{ + return 0; +} + +/* dummy implementation */ +static double tt_cos(double val) +{ + return 0; +} + +/* dummy implementation */ +static double tt_acos(double val) +{ + return 0; +} + #define STBTT_ifloor tt_floor #define STBTT_iceil tt_ceil #define STBTT_fabs tt_fabs #define STBTT_sqrt tt_sqrt +#define STBTT_pow tt_pow +#define STBTT_fmod tt_fmod +#define STBTT_cos tt_cos +#define STBTT_acos tt_acos #define STBTT_malloc(size, u) ((void)(u), malloc(size)) #define STBTT_free(size, u) ((void)(u), free(size)) #define STBTT_assert(x) @@ -154,33 +187,33 @@ static int console_truetype_set_row(struct udevice *dev, uint row, int clr) end = line + met->font_size * vid_priv->line_length; switch (vid_priv->bpix) { -#ifdef CONFIG_VIDEO_BPP8 case VIDEO_BPP8: { u8 *dst; - for (dst = line; dst < (u8 *)end; ++dst) - *dst = clr; + if (IS_ENABLED(CONFIG_VIDEO_BPP8)) { + for (dst = line; dst < (u8 *)end; ++dst) + *dst = clr; + } break; } -#endif -#ifdef CONFIG_VIDEO_BPP16 case VIDEO_BPP16: { u16 *dst = line; - for (dst = line; dst < (u16 *)end; ++dst) - *dst = clr; + if (IS_ENABLED(CONFIG_VIDEO_BPP16)) { + for (dst = line; dst < (u16 *)end; ++dst) + *dst = clr; + } break; } -#endif -#ifdef CONFIG_VIDEO_BPP32 case VIDEO_BPP32: { u32 *dst = line; - for (dst = line; dst < (u32 *)end; ++dst) - *dst = clr; + if (IS_ENABLED(CONFIG_VIDEO_BPP32)) { + for (dst = line; dst < (u32 *)end; ++dst) + *dst = clr; + } break; } -#endif default: return -ENOSYS; } @@ -256,7 +289,7 @@ static int console_truetype_putc_xy(struct udevice *dev, uint x, uint y, */ x_shift = xpos - (double)tt_floor(xpos); xpos += advance * met->scale; - width_frac = (int)VID_TO_POS(xpos); + width_frac = (int)VID_TO_POS(advance * met->scale); if (x + width_frac >= vc_priv->xsize_frac) return -EAGAIN; @@ -317,52 +350,52 @@ static int console_truetype_putc_xy(struct udevice *dev, uint x, uint y, end = dst; } break; -#ifdef CONFIG_VIDEO_BPP16 case VIDEO_BPP16: { uint16_t *dst = (uint16_t *)line + xoff; int i; - for (i = 0; i < width; i++) { - int val = *bits; - int out; - - if (vid_priv->colour_bg) - val = 255 - val; - out = val >> 3 | - (val >> 2) << 5 | - (val >> 3) << 11; - if (vid_priv->colour_fg) - *dst++ |= out; - else - *dst++ &= out; - bits++; + if (IS_ENABLED(CONFIG_VIDEO_BPP16)) { + for (i = 0; i < width; i++) { + int val = *bits; + int out; + + if (vid_priv->colour_bg) + val = 255 - val; + out = val >> 3 | + (val >> 2) << 5 | + (val >> 3) << 11; + if (vid_priv->colour_fg) + *dst++ |= out; + else + *dst++ &= out; + bits++; + } + end = dst; } - end = dst; break; } -#endif -#ifdef CONFIG_VIDEO_BPP32 case VIDEO_BPP32: { u32 *dst = (u32 *)line + xoff; int i; - for (i = 0; i < width; i++) { - int val = *bits; - int out; - - if (vid_priv->colour_bg) - val = 255 - val; - out = val | val << 8 | val << 16; - if (vid_priv->colour_fg) - *dst++ |= out; - else - *dst++ &= out; - bits++; + if (IS_ENABLED(CONFIG_VIDEO_BPP32)) { + for (i = 0; i < width; i++) { + int val = *bits; + int out; + + if (vid_priv->colour_bg) + val = 255 - val; + out = val | val << 8 | val << 16; + if (vid_priv->colour_fg) + *dst++ |= out; + else + *dst++ &= out; + bits++; + } + end = dst; } - end = dst; break; } -#endif default: free(data); return -ENOSYS; @@ -379,72 +412,6 @@ static int console_truetype_putc_xy(struct udevice *dev, uint x, uint y, } /** - * console_truetype_erase() - Erase a character - * - * This is used for backspace. We erase a square of the display within the - * given bounds. - * - * @dev: Device to update - * @xstart: X start position in pixels from the left - * @ystart: Y start position in pixels from the top - * @xend: X end position in pixels from the left - * @yend: Y end position in pixels from the top - * @clr: Value to write - * Return: 0 if OK, -ENOSYS if the display depth is not supported - */ -static int console_truetype_erase(struct udevice *dev, int xstart, int ystart, - int xend, int yend, int clr) -{ - struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent); - void *start, *line; - int pixels = xend - xstart; - int row, i, ret; - - start = vid_priv->fb + ystart * vid_priv->line_length; - start += xstart * VNBYTES(vid_priv->bpix); - line = start; - for (row = ystart; row < yend; row++) { - switch (vid_priv->bpix) { -#ifdef CONFIG_VIDEO_BPP8 - case VIDEO_BPP8: { - uint8_t *dst = line; - - for (i = 0; i < pixels; i++) - *dst++ = clr; - break; - } -#endif -#ifdef CONFIG_VIDEO_BPP16 - case VIDEO_BPP16: { - uint16_t *dst = line; - - for (i = 0; i < pixels; i++) - *dst++ = clr; - break; - } -#endif -#ifdef CONFIG_VIDEO_BPP32 - case VIDEO_BPP32: { - uint32_t *dst = line; - - for (i = 0; i < pixels; i++) - *dst++ = clr; - break; - } -#endif - default: - return -ENOSYS; - } - line += vid_priv->line_length; - } - ret = vidconsole_sync_copy(dev, start, line); - if (ret) - return ret; - - return 0; -} - -/** * console_truetype_backspace() - Handle a backspace operation * * This clears the previous character so that the console looks as if it had @@ -482,9 +449,9 @@ static int console_truetype_backspace(struct udevice *dev) else xend = vid_priv->xsize; - console_truetype_erase(dev, VID_TO_PIXEL(pos->xpos_frac), pos->ypos, - xend, pos->ypos + vc_priv->y_charsize, - vid_priv->colour_bg); + video_fill_part(vid_dev, VID_TO_PIXEL(pos->xpos_frac), pos->ypos, + xend, pos->ypos + vc_priv->y_charsize, + vid_priv->colour_bg); /* Move the cursor back to where it was when we pushed this record */ vc_priv->xcur_frac = pos->xpos_frac; @@ -680,8 +647,8 @@ static void select_metrics(struct udevice *dev, struct console_tt_metrics *met) vc_priv->tab_width_frac = VID_TO_POS(met->font_size) * 8 / 2; } -static int truetype_select_font(struct udevice *dev, const char *name, - uint size) +static int get_metrics(struct udevice *dev, const char *name, uint size, + struct console_tt_metrics **metp) { struct console_tt_priv *priv = dev_get_priv(dev); struct console_tt_metrics *met; @@ -719,11 +686,70 @@ static int truetype_select_font(struct udevice *dev, const char *name, met = priv->metrics; } + *metp = met; + + return 0; +} + +static int truetype_select_font(struct udevice *dev, const char *name, + uint size) +{ + struct console_tt_metrics *met; + int ret; + + ret = get_metrics(dev, name, size, &met); + if (ret) + return log_msg_ret("sel", ret); + select_metrics(dev, met); return 0; } +int truetype_measure(struct udevice *dev, const char *name, uint size, + const char *text, struct vidconsole_bbox *bbox) +{ + struct console_tt_metrics *met; + stbtt_fontinfo *font; + int lsb, advance; + const char *s; + int width; + int last; + int ret; + + ret = get_metrics(dev, name, size, &met); + if (ret) + return log_msg_ret("sel", ret); + + bbox->valid = false; + if (!*text) + return 0; + + font = &met->font; + width = 0; + for (last = 0, s = text; *s; s++) { + int ch = *s; + + /* Used kerning to fine-tune the position of this character */ + if (last) + width += stbtt_GetCodepointKernAdvance(font, last, ch); + + /* First get some basic metrics about this character */ + stbtt_GetCodepointHMetrics(font, ch, &advance, &lsb); + + width += advance; + last = ch; + } + + bbox->valid = true; + bbox->x0 = 0; + bbox->y0 = 0; + bbox->x1 = tt_ceil((double)width * met->scale); + bbox->y1 = met->font_size; + + return 0; +} + const char *console_truetype_get_font_size(struct udevice *dev, uint *sizep) { struct console_tt_priv *priv = dev_get_priv(dev); @@ -775,6 +801,7 @@ struct vidconsole_ops console_truetype_ops = { .get_font = console_truetype_get_font, .get_font_size = console_truetype_get_font_size, .select_font = truetype_select_font, + .measure = truetype_measure, }; U_BOOT_DRIVER(vidconsole_truetype) = { diff --git a/drivers/video/stb_truetype.h b/drivers/video/stb_truetype.h index 438bfce468c..c6973bb353c 100644 --- a/drivers/video/stb_truetype.h +++ b/drivers/video/stb_truetype.h @@ -1,11 +1,21 @@ -// stb_truetype.h - v1.08 - public domain -// authored from 2009-2015 by Sean Barrett / RAD Game Tools +// stb_truetype.h - v1.26 - public domain +// authored from 2009-2021 by Sean Barrett / RAD Game Tools +// +// ======================================================================= +// +// NO SECURITY GUARANTEE -- DO NOT USE THIS ON UNTRUSTED FONT FILES +// +// This library does no range checking of the offsets found in the file, +// meaning an attacker can use it to read arbitrary memory. +// +// ======================================================================= // // This library processes TrueType files: // parse files // extract glyph metrics // extract glyph shapes // render glyphs to one-channel bitmaps with antialiasing (box filter) +// render glyphs to one-channel SDF bitmaps (signed-distance field/function) // // Todo: // non-MS cmaps @@ -20,58 +30,68 @@ // // Mikko Mononen: compound shape support, more cmap formats // Tor Andersson: kerning, subpixel rendering -// -// Bug/warning reports/fixes: -// "Zer" on mollyrocket (with fix) -// Cass Everitt -// stoiko (Haemimont Games) -// Brian Hook -// Walter van Niftrik -// David Gow -// David Given -// Ivan-Assen Ivanov -// Anthony Pesch -// Johan Duparc -// Hou Qiming -// Fabian "ryg" Giesen -// Martins Mozeiko -// Cap Petschulat -// Omar Cornut -// github:aloucks -// Peter LaValle -// Sergey Popov -// Giumo X. Clanjor -// Higor Euripedes +// Dougall Johnson: OpenType / Type 2 font handling +// Daniel Ribeiro Maciel: basic GPOS-based kerning // // Misc other: // Ryan Gordon +// Simon Glass +// github:IntellectualKitty +// Imanol Celaya +// Daniel Ribeiro Maciel +// +// Bug/warning reports/fixes: +// "Zer" on mollyrocket Fabian "ryg" Giesen github:NiLuJe +// Cass Everitt Martins Mozeiko github:aloucks +// stoiko (Haemimont Games) Cap Petschulat github:oyvindjam +// Brian Hook Omar Cornut github:vassvik +// Walter van Niftrik Ryan Griege +// David Gow Peter LaValle +// David Given Sergey Popov +// Ivan-Assen Ivanov Giumo X. Clanjor +// Anthony Pesch Higor Euripedes +// Johan Duparc Thomas Fields +// Hou Qiming Derek Vinyard +// Rob Loach Cort Stratton +// Kenney Phillis Jr. Brian Costabile +// Ken Voskuil (kaesve) // // VERSION HISTORY // +// 1.26 (2021-08-28) fix broken rasterizer +// 1.25 (2021-07-11) many fixes +// 1.24 (2020-02-05) fix warning +// 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS) +// 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined +// 1.21 (2019-02-25) fix warning +// 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics() +// 1.19 (2018-02-11) GPOS kerning, STBTT_fmod +// 1.18 (2018-01-29) add missing function +// 1.17 (2017-07-23) make more arguments const; doc fix +// 1.16 (2017-07-12) SDF support +// 1.15 (2017-03-03) make more arguments const +// 1.14 (2017-01-16) num-fonts-in-TTC function +// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts +// 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual +// 1.11 (2016-04-02) fix unused-variable warning +// 1.10 (2016-04-02) user-defined fabs(); rare memory leak; remove duplicate typedef +// 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use allocation userdata properly // 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges // 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; // variant PackFontRanges to pack and render in separate phases; // fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?); // fixed an assert() bug in the new rasterizer // replace assert() with STBTT_assert() in new rasterizer -// 1.06 (2015-07-14) performance improvements (~35% faster on x86 and x64 on test machine) -// also more precise AA rasterizer, except if shapes overlap -// remove need for STBTT_sort -// 1.05 (2015-04-15) fix misplaced definitions for STBTT_STATIC -// 1.04 (2015-04-15) typo in example -// 1.03 (2015-04-12) STBTT_STATIC, fix memory leak in new packing, various fixes // // Full history can be found at the end of this file. // // LICENSE // -// This software is in the public domain. Where that dedication is not -// recognized, you are granted a perpetual, irrevocable license to copy, -// distribute, and modify this file as you see fit. +// See end of file for license information. // // USAGE // -// Include this file in whatever places neeed to refer to it. In ONE C/C++ +// Include this file in whatever places need to refer to it. In ONE C/C++ // file, write: // #define STB_TRUETYPE_IMPLEMENTATION // before the #include of this file. This expands out the actual @@ -87,14 +107,15 @@ // Improved 3D API (more shippable): // #include "stb_rect_pack.h" -- optional, but you really want it // stbtt_PackBegin() -// stbtt_PackSetOversample() -- for improved quality on small fonts +// stbtt_PackSetOversampling() -- for improved quality on small fonts // stbtt_PackFontRanges() -- pack and renders // stbtt_PackEnd() // stbtt_GetPackedQuad() // // "Load" a font file from a memory buffer (you have to keep the buffer loaded) // stbtt_InitFont() -// stbtt_GetFontOffsetForIndex() -- use for TTC font collections +// stbtt_GetFontOffsetForIndex() -- indexing for TTC font collections +// stbtt_GetNumberOfFonts() -- number of fonts for TTC font collections // // Render a unicode codepoint to a bitmap // stbtt_GetCodepointBitmap() -- allocates and returns a bitmap @@ -104,6 +125,7 @@ // Character advance/positioning // stbtt_GetCodepointHMetrics() // stbtt_GetFontVMetrics() +// stbtt_GetFontVMetricsOS2() // stbtt_GetCodepointKernAdvance() // // Starting with version 1.06, the rasterizer was replaced with a new, @@ -159,7 +181,7 @@ // measurement for describing font size, defined as 72 points per inch. // stb_truetype provides a point API for compatibility. However, true // "per inch" conventions don't make much sense on computer displays -// since they different monitors have different number of pixels per +// since different monitors have different number of pixels per // inch. For example, Windows traditionally uses a convention that // there are 96 pixels per inch, thus making 'inch' measurements have // nothing to do with inches, and thus effectively defining a point to @@ -169,6 +191,39 @@ // for non-commercial fonts, thus making fonts scaled in points // according to the TrueType spec incoherently sized in practice. // +// DETAILED USAGE: +// +// Scale: +// Select how high you want the font to be, in points or pixels. +// Call ScaleForPixelHeight or ScaleForMappingEmToPixels to compute +// a scale factor SF that will be used by all other functions. +// +// Baseline: +// You need to select a y-coordinate that is the baseline of where +// your text will appear. Call GetFontBoundingBox to get the baseline-relative +// bounding box for all characters. SF*-y0 will be the distance in pixels +// that the worst-case character could extend above the baseline, so if +// you want the top edge of characters to appear at the top of the +// screen where y=0, then you would set the baseline to SF*-y0. +// +// Current point: +// Set the current point where the first character will appear. The +// first character could extend left of the current point; this is font +// dependent. You can either choose a current point that is the leftmost +// point and hope, or add some padding, or check the bounding box or +// left-side-bearing of the first character to be displayed and set +// the current point based on that. +// +// Displaying a character: +// Compute the bounding box of the character. It will contain signed values +// relative to <current_point, baseline>. I.e. if it returns x0,y0,x1,y1, +// then the character should be displayed in the rectangle from +// <current_point+SF*x0, baseline+SF*y0> to <current_point+SF*x1,baseline+SF*y1). +// +// Advancing for the next character: +// Call GlyphHMetrics, and compute 'current_point += SF * advance'. +// +// // ADVANCED USAGE // // Quality: @@ -203,19 +258,6 @@ // recommend it. // // -// SOURCE STATISTICS (based on v0.6c, 2050 LOC) -// -// Documentation & header file 520 LOC \___ 660 LOC documentation -// Sample code 140 LOC / -// Truetype parsing 620 LOC ---- 620 LOC TrueType -// Software rasterization 240 LOC \ . -// Curve tesselation 120 LOC \__ 550 LOC Bitmap creation -// Bitmap management 100 LOC / -// Baked bitmap interface 70 LOC / -// Font name matching & access 150 LOC ---- 150 -// C runtime library abstraction 60 LOC ---- 60 -// -// // PERFORMANCE MEASUREMENTS FOR 1.06: // // 32-bit 64-bit @@ -230,8 +272,8 @@ //// SAMPLE PROGRAMS //// // -// Incomplete text-in-3d-api example, which draws quads properly aligned to be lossless -// +// Incomplete text-in-3d-api example, which draws quads properly aligned to be lossless. +// See "tests/truetype_demo_win32.c" for a complete version. #if 0 #define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation #include "stb_truetype.h" @@ -257,6 +299,8 @@ void my_stbtt_initfont(void) void my_stbtt_print(float x, float y, char *text) { // assume orthographic projection with units = screen pixels, origin at top left + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, ftex); glBegin(GL_QUADS); @@ -264,10 +308,10 @@ void my_stbtt_print(float x, float y, char *text) if (*text >= 32 && *text < 128) { stbtt_aligned_quad q; stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);//1=opengl & d3d10+,0=d3d9 - glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y0); - glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y0); - glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y1); - glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y1); + glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y0); + glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y0); + glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y1); + glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y1); } ++text; } @@ -305,7 +349,7 @@ int main(int argc, char **argv) } return 0; } -#endif +#endif // // Output: // @@ -319,9 +363,9 @@ int main(int argc, char **argv) // :@@. M@M // @@@o@@@@ // :M@@V:@@. -// +// ////////////////////////////////////////////////////////////////////////////// -// +// // Complete program: print "Hello World!" banner, with bugs // #if 0 @@ -375,7 +419,8 @@ int main(int arg, char **argv) //// INTEGRATION WITH YOUR CODEBASE //// //// The following sections allow you to supply alternate definitions -//// of C library functions used by stb_truetype. +//// of C library functions used by stb_truetype, e.g. if you don't +//// link with the C runtime library. #ifdef STB_TRUETYPE_IMPLEMENTATION // #define your own (u)stbtt_int8/16/32 before including to override this @@ -391,7 +436,7 @@ int main(int arg, char **argv) typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1]; typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1]; - // #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h + // e.g. #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h #ifndef STBTT_ifloor #include <math.h> #define STBTT_ifloor(x) ((int) floor(x)) @@ -401,6 +446,18 @@ int main(int arg, char **argv) #ifndef STBTT_sqrt #include <math.h> #define STBTT_sqrt(x) sqrt(x) + #define STBTT_pow(x,y) pow(x,y) + #endif + + #ifndef STBTT_fmod + #include <math.h> + #define STBTT_fmod(x,y) fmod(x,y) + #endif + + #ifndef STBTT_cos + #include <math.h> + #define STBTT_cos(x) cos(x) + #define STBTT_acos(x) acos(x) #endif #ifndef STBTT_fabs @@ -452,6 +509,14 @@ int main(int arg, char **argv) extern "C" { #endif +// private structure +typedef struct +{ + unsigned char *data; + int cursor; + int size; +} stbtt__buf; + ////////////////////////////////////////////////////////////////////////////// // // TEXTURE BAKING API @@ -481,7 +546,7 @@ typedef struct float x1,y1,s1,t1; // bottom-right } stbtt_aligned_quad; -STBTT_DEF void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, // same data as above +STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, // same data as above int char_index, // character to display float *xpos, float *ypos, // pointers to current position in screen pixel space stbtt_aligned_quad *q, // output: quad to draw @@ -496,6 +561,9 @@ STBTT_DEF void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, // // // It's inefficient; you might want to c&p it and optimize it. +STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap); +// Query the font vertical metrics without having to create a font first. + ////////////////////////////////////////////////////////////////////////////// // @@ -520,7 +588,7 @@ typedef struct stbrp_rect stbrp_rect; STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int width, int height, int stride_in_bytes, int padding, void *alloc_context); // Initializes a packing context stored in the passed-in stbtt_pack_context. // Future calls using this context will pack characters into the bitmap passed -// in here: a 1-channel bitmap that is weight x height. stride_in_bytes is +// in here: a 1-channel bitmap that is width * height. stride_in_bytes is // the distance from one row to the next (or 0 to mean they are packed tightly // together). "padding" is the amount of padding to leave between each // character (normally you want '1' for bitmaps you'll use as textures with @@ -533,7 +601,7 @@ STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc); #define STBTT_POINT_SIZE(x) (-(x)) -STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, float font_size, +STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size, int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range); // Creates character bitmaps from the font_index'th font found in fontdata (use // font_index=0 if you don't know what that is). It creates num_chars_in_range @@ -558,7 +626,7 @@ typedef struct unsigned char h_oversample, v_oversample; // don't set these, they're used internally } stbtt_pack_range; -STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges); +STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges); // Creates character bitmaps from multiple ranges of characters stored in // ranges. This will usually create a better-packed bitmap than multiple // calls to stbtt_PackFontRange. Note that you can call this multiple @@ -580,19 +648,25 @@ STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h // To use with PackFontRangesGather etc., you must set it before calls // call to PackFontRangesGatherRects. -STBTT_DEF void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, int ph, // same data as above +STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip); +// If skip != 0, this tells stb_truetype to skip any codepoints for which +// there is no corresponding glyph. If skip=0, which is the default, then +// codepoints without a glyph recived the font's "missing character" glyph, +// typically an empty box by convention. + +STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, // same data as above int char_index, // character to display float *xpos, float *ypos, // pointers to current position in screen pixel space stbtt_aligned_quad *q, // output: quad to draw int align_to_integer); -STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); +STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects); -STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); +STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); // Calling these functions in sequence is roughly equivalent to calling // stbtt_PackFontRanges(). If you more control over the packing of multiple // fonts, or if you want to pack custom data into a font texture, take a look -// at the source to of stbtt_PackFontRanges() and create a custom version +// at the source to of stbtt_PackFontRanges() and create a custom version // using these functions, e.g. call GatherRects multiple times, // building up a single array of rects, then call PackRects once, // then call RenderIntoRects repeatedly. This may result in a @@ -608,6 +682,7 @@ struct stbtt_pack_context { int height; int stride_in_bytes; int padding; + int skip_missing; unsigned int h_oversample, v_oversample; unsigned char *pixels; void *nodes; @@ -619,18 +694,23 @@ struct stbtt_pack_context { // // +STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data); +// This function will determine the number of fonts in a font file. TrueType +// collection (.ttc) files may contain multiple fonts, while TrueType font +// (.ttf) files only contain one font. The number of fonts can be used for +// indexing with the previous function where the index is between zero and one +// less than the total fonts. If an error occurs, -1 is returned. + STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index); // Each .ttf/.ttc file may have more than one font. Each font has a sequential // index number starting from 0. Call this function to get the font offset for // a given index; it returns -1 if the index is out of range. A regular .ttf // file will only define one font and it always be at offset 0, so it will -// return '0' for index 0, and -1 for all other indices. You can just skip -// this step if you know it's that kind of font. +// return '0' for index 0, and -1 for all other indices. - -// The following structure is defined publically so you can declare one on +// The following structure is defined publicly so you can declare one on // the stack or as a global or etc, but you should treat it as opaque. -typedef struct stbtt_fontinfo +struct stbtt_fontinfo { void * userdata; unsigned char * data; // pointer to .ttf file @@ -638,10 +718,17 @@ typedef struct stbtt_fontinfo int numGlyphs; // number of glyphs, needed for range checking - int loca,head,glyf,hhea,hmtx,kern; // table locations as offset from start of .ttf + int loca,head,glyf,hhea,hmtx,kern,gpos,svg; // table locations as offset from start of .ttf int index_map; // a cmap mapping for our chosen character encoding int indexToLocFormat; // format needed to map from glyph index to glyph -} stbtt_fontinfo; + + stbtt__buf cff; // cff font data + stbtt__buf charstrings; // the charstring index + stbtt__buf gsubrs; // global charstring subroutines index + stbtt__buf subrs; // private charstring subroutines index + stbtt__buf fontdicts; // array of font dicts + stbtt__buf fdselect; // map from glyph to fontdict +}; STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset); // Given an offset into the file that defines a font, this function builds @@ -660,6 +747,7 @@ STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codep // and you want a speed-up, call this function with the character you're // going to process, then use glyph-based functions instead of the // codepoint-based functions. +// Returns 0 if the character codepoint is not defined in the font. ////////////////////////////////////////////////////////////////////////////// @@ -688,6 +776,12 @@ STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, in // these are expressed in unscaled coordinates, so you must multiply by // the scale factor for a given size +STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap); +// analogous to GetFontVMetrics, but returns the "typographic" values from the OS/2 +// table (specific to MS/Windows TTF files). +// +// Returns 1 on success (table present), 0 on failure. + STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1); // the bounding box around all possible characters @@ -707,6 +801,18 @@ STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); // as above, but takes one or more glyph indices for greater efficiency +typedef struct stbtt_kerningentry +{ + int glyph1; // use stbtt_FindGlyphIndex + int glyph2; + int advance; +} stbtt_kerningentry; + +STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info); +STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length); +// Retrieves a complete list of all of the kerning pairs provided by the font +// stbtt_GetKerningTable never writes more than table_length entries and returns how many entries it did write. +// The table will be sorted by (a.glyph1 == b.glyph1)?(a.glyph2 < b.glyph2):(a.glyph1 < b.glyph1) ////////////////////////////////////////////////////////////////////////////// // @@ -718,7 +824,8 @@ STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, in enum { STBTT_vmove=1, STBTT_vline, - STBTT_vcurve + STBTT_vcurve, + STBTT_vcubic }; #endif @@ -727,7 +834,7 @@ STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, in #define stbtt_vertex_type short // can't use stbtt_int16 because that's not visible in the header file typedef struct { - stbtt_vertex_type x,y,cx,cy; + stbtt_vertex_type x,y,cx,cy,cx1,cy1; unsigned char type,padding; } stbtt_vertex; #endif @@ -740,7 +847,7 @@ STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, s // returns # of vertices and fills *vertices with the pointer to them // these are expressed in "unscaled" coordinates // -// The shape is a series of countours. Each one starts with +// The shape is a series of contours. Each one starts with // a STBTT_moveto, then consists of a series of mixed // STBTT_lineto and STBTT_curveto segments. A lineto // draws a line from previous endpoint to its x,y; a curveto @@ -750,6 +857,12 @@ STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, s STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices); // frees the data allocated above +STBTT_DEF unsigned char *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl); +STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg); +STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg); +// fills svg with the character's SVG data. +// returns data size or 0 if SVG not found. + ////////////////////////////////////////////////////////////////////////////// // // BITMAP RENDERING @@ -781,6 +894,10 @@ STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, uns // same as stbtt_MakeCodepointBitmap, but you can specify a subpixel // shift for the character +STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint); +// same as stbtt_MakeCodepointBitmapSubpixel, but prefiltering +// is performed (see stbtt_PackSetOversampling) + STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); // get the bbox of the bitmap centered around the glyph origin; so the // bitmap width is ix1-ix0, height is iy1-iy0, and location to place @@ -798,6 +915,7 @@ STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff); STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph); STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph); +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int glyph); STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1); @@ -822,6 +940,64 @@ STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, // 1-channel bitmap ////////////////////////////////////////////////////////////////////////////// // +// Signed Distance Function (or Field) rendering + +STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata); +// frees the SDF bitmap allocated below + +STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); +STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); +// These functions compute a discretized SDF field for a single character, suitable for storing +// in a single-channel texture, sampling with bilinear filtering, and testing against +// larger than some threshold to produce scalable fonts. +// info -- the font +// scale -- controls the size of the resulting SDF bitmap, same as it would be creating a regular bitmap +// glyph/codepoint -- the character to generate the SDF for +// padding -- extra "pixels" around the character which are filled with the distance to the character (not 0), +// which allows effects like bit outlines +// onedge_value -- value 0-255 to test the SDF against to reconstruct the character (i.e. the isocontour of the character) +// pixel_dist_scale -- what value the SDF should increase by when moving one SDF "pixel" away from the edge (on the 0..255 scale) +// if positive, > onedge_value is inside; if negative, < onedge_value is inside +// width,height -- output height & width of the SDF bitmap (including padding) +// xoff,yoff -- output origin of the character +// return value -- a 2D array of bytes 0..255, width*height in size +// +// pixel_dist_scale & onedge_value are a scale & bias that allows you to make +// optimal use of the limited 0..255 for your application, trading off precision +// and special effects. SDF values outside the range 0..255 are clamped to 0..255. +// +// Example: +// scale = stbtt_ScaleForPixelHeight(22) +// padding = 5 +// onedge_value = 180 +// pixel_dist_scale = 180/5.0 = 36.0 +// +// This will create an SDF bitmap in which the character is about 22 pixels +// high but the whole bitmap is about 22+5+5=32 pixels high. To produce a filled +// shape, sample the SDF at each pixel and fill the pixel if the SDF value +// is greater than or equal to 180/255. (You'll actually want to antialias, +// which is beyond the scope of this example.) Additionally, you can compute +// offset outlines (e.g. to stroke the character border inside & outside, +// or only outside). For example, to fill outside the character up to 3 SDF +// pixels, you would compare against (180-36.0*3)/255 = 72/255. The above +// choice of variables maps a range from 5 pixels outside the shape to +// 2 pixels inside the shape to 0..255; this is intended primarily for apply +// outside effects only (the interior range is needed to allow proper +// antialiasing of the font at *smaller* sizes) +// +// The function computes the SDF analytically at each SDF pixel, not by e.g. +// building a higher-res bitmap and approximating it. In theory the quality +// should be as high as possible for an SDF of this size & representation, but +// unclear if this is true in practice (perhaps building a higher-res bitmap +// and computing from that can allow drop-out prevention). +// +// The algorithm has not been optimized at all, so expect it to be slow +// if computing lots of characters or very large sizes. + + + +////////////////////////////////////////////////////////////////////////////// +// // Finding the right font... // // You should really just solve this offline, keep your own tables @@ -943,6 +1119,158 @@ typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERS #define STBTT_RASTERIZER_VERSION 2 #endif +#ifdef _MSC_VER +#define STBTT__NOTUSED(v) (void)(v) +#else +#define STBTT__NOTUSED(v) (void)sizeof(v) +#endif + +////////////////////////////////////////////////////////////////////////// +// +// stbtt__buf helpers to parse data from file +// + +static stbtt_uint8 stbtt__buf_get8(stbtt__buf *b) +{ + if (b->cursor >= b->size) + return 0; + return b->data[b->cursor++]; +} + +static stbtt_uint8 stbtt__buf_peek8(stbtt__buf *b) +{ + if (b->cursor >= b->size) + return 0; + return b->data[b->cursor]; +} + +static void stbtt__buf_seek(stbtt__buf *b, int o) +{ + STBTT_assert(!(o > b->size || o < 0)); + b->cursor = (o > b->size || o < 0) ? b->size : o; +} + +static void stbtt__buf_skip(stbtt__buf *b, int o) +{ + stbtt__buf_seek(b, b->cursor + o); +} + +static stbtt_uint32 stbtt__buf_get(stbtt__buf *b, int n) +{ + stbtt_uint32 v = 0; + int i; + STBTT_assert(n >= 1 && n <= 4); + for (i = 0; i < n; i++) + v = (v << 8) | stbtt__buf_get8(b); + return v; +} + +static stbtt__buf stbtt__new_buf(const void *p, size_t size) +{ + stbtt__buf r; + STBTT_assert(size < 0x40000000); + r.data = (stbtt_uint8*) p; + r.size = (int) size; + r.cursor = 0; + return r; +} + +#define stbtt__buf_get16(b) stbtt__buf_get((b), 2) +#define stbtt__buf_get32(b) stbtt__buf_get((b), 4) + +static stbtt__buf stbtt__buf_range(const stbtt__buf *b, int o, int s) +{ + stbtt__buf r = stbtt__new_buf(NULL, 0); + if (o < 0 || s < 0 || o > b->size || s > b->size - o) return r; + r.data = b->data + o; + r.size = s; + return r; +} + +static stbtt__buf stbtt__cff_get_index(stbtt__buf *b) +{ + int count, start, offsize; + start = b->cursor; + count = stbtt__buf_get16(b); + if (count) { + offsize = stbtt__buf_get8(b); + STBTT_assert(offsize >= 1 && offsize <= 4); + stbtt__buf_skip(b, offsize * count); + stbtt__buf_skip(b, stbtt__buf_get(b, offsize) - 1); + } + return stbtt__buf_range(b, start, b->cursor - start); +} + +static stbtt_uint32 stbtt__cff_int(stbtt__buf *b) +{ + int b0 = stbtt__buf_get8(b); + if (b0 >= 32 && b0 <= 246) return b0 - 139; + else if (b0 >= 247 && b0 <= 250) return (b0 - 247)*256 + stbtt__buf_get8(b) + 108; + else if (b0 >= 251 && b0 <= 254) return -(b0 - 251)*256 - stbtt__buf_get8(b) - 108; + else if (b0 == 28) return stbtt__buf_get16(b); + else if (b0 == 29) return stbtt__buf_get32(b); + STBTT_assert(0); + return 0; +} + +static void stbtt__cff_skip_operand(stbtt__buf *b) { + int v, b0 = stbtt__buf_peek8(b); + STBTT_assert(b0 >= 28); + if (b0 == 30) { + stbtt__buf_skip(b, 1); + while (b->cursor < b->size) { + v = stbtt__buf_get8(b); + if ((v & 0xF) == 0xF || (v >> 4) == 0xF) + break; + } + } else { + stbtt__cff_int(b); + } +} + +static stbtt__buf stbtt__dict_get(stbtt__buf *b, int key) +{ + stbtt__buf_seek(b, 0); + while (b->cursor < b->size) { + int start = b->cursor, end, op; + while (stbtt__buf_peek8(b) >= 28) + stbtt__cff_skip_operand(b); + end = b->cursor; + op = stbtt__buf_get8(b); + if (op == 12) op = stbtt__buf_get8(b) | 0x100; + if (op == key) return stbtt__buf_range(b, start, end-start); + } + return stbtt__buf_range(b, 0, 0); +} + +static void stbtt__dict_get_ints(stbtt__buf *b, int key, int outcount, stbtt_uint32 *out) +{ + int i; + stbtt__buf operands = stbtt__dict_get(b, key); + for (i = 0; i < outcount && operands.cursor < operands.size; i++) + out[i] = stbtt__cff_int(&operands); +} + +static int stbtt__cff_index_count(stbtt__buf *b) +{ + stbtt__buf_seek(b, 0); + return stbtt__buf_get16(b); +} + +static stbtt__buf stbtt__cff_index_get(stbtt__buf b, int i) +{ + int count, offsize, start, end; + stbtt__buf_seek(&b, 0); + count = stbtt__buf_get16(&b); + offsize = stbtt__buf_get8(&b); + STBTT_assert(i >= 0 && i < count); + STBTT_assert(offsize >= 1 && offsize <= 4); + stbtt__buf_skip(&b, i*offsize); + start = stbtt__buf_get(&b, offsize); + end = stbtt__buf_get(&b, offsize); + return stbtt__buf_range(&b, 2+(count+1)*offsize+start, end - start); +} + ////////////////////////////////////////////////////////////////////////// // // accessors to parse data from file @@ -955,32 +1283,22 @@ typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERS #define ttCHAR(p) (* (stbtt_int8 *) (p)) #define ttFixed(p) ttLONG(p) -#if defined(STB_TRUETYPE_BIGENDIAN) && !defined(ALLOW_UNALIGNED_TRUETYPE) - - #define ttUSHORT(p) (* (stbtt_uint16 *) (p)) - #define ttSHORT(p) (* (stbtt_int16 *) (p)) - #define ttULONG(p) (* (stbtt_uint32 *) (p)) - #define ttLONG(p) (* (stbtt_int32 *) (p)) - -#else - - static stbtt_uint16 ttUSHORT(const stbtt_uint8 *p) { return p[0]*256 + p[1]; } - static stbtt_int16 ttSHORT(const stbtt_uint8 *p) { return p[0]*256 + p[1]; } - static stbtt_uint32 ttULONG(const stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } - static stbtt_int32 ttLONG(const stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } - -#endif +static stbtt_uint16 ttUSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; } +static stbtt_int16 ttSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; } +static stbtt_uint32 ttULONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } +static stbtt_int32 ttLONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } #define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3)) #define stbtt_tag(p,str) stbtt_tag4(p,str[0],str[1],str[2],str[3]) -static int stbtt__isfont(const stbtt_uint8 *font) +static int stbtt__isfont(stbtt_uint8 *font) { // check the version number if (stbtt_tag4(font, '1',0,0,0)) return 1; // TrueType 1 if (stbtt_tag(font, "typ1")) return 1; // TrueType with type 1 font -- we don't support this! if (stbtt_tag(font, "OTTO")) return 1; // OpenType with CFF if (stbtt_tag4(font, 0,1,0,0)) return 1; // OpenType 1.0 + if (stbtt_tag(font, "true")) return 1; // Apple specification for TrueType fonts return 0; } @@ -998,7 +1316,7 @@ static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart, return 0; } -STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *font_collection, int index) +static int stbtt_GetFontOffsetForIndex_internal(unsigned char *font_collection, int index) { // if it's just a font, there's only one valid index if (stbtt__isfont(font_collection)) @@ -1017,14 +1335,59 @@ STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *font_collection, return -1; } -STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data2, int fontstart) +static int stbtt_GetNumberOfFonts_internal(unsigned char *font_collection) +{ + // if it's just a font, there's only one valid font + if (stbtt__isfont(font_collection)) + return 1; + + // check if it's a TTC + if (stbtt_tag(font_collection, "ttcf")) { + // version 1? + if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) { + return ttLONG(font_collection+8); + } + } + return 0; +} + +static stbtt__buf stbtt__get_subrs(stbtt__buf cff, stbtt__buf fontdict) +{ + stbtt_uint32 subrsoff = 0, private_loc[2] = { 0, 0 }; + stbtt__buf pdict; + stbtt__dict_get_ints(&fontdict, 18, 2, private_loc); + if (!private_loc[1] || !private_loc[0]) return stbtt__new_buf(NULL, 0); + pdict = stbtt__buf_range(&cff, private_loc[1], private_loc[0]); + stbtt__dict_get_ints(&pdict, 19, 1, &subrsoff); + if (!subrsoff) return stbtt__new_buf(NULL, 0); + stbtt__buf_seek(&cff, private_loc[1]+subrsoff); + return stbtt__cff_get_index(&cff); +} + +// since most people won't use this, find this table the first time it's needed +static int stbtt__get_svg(stbtt_fontinfo *info) +{ + stbtt_uint32 t; + if (info->svg < 0) { + t = stbtt__find_table(info->data, info->fontstart, "SVG "); + if (t) { + stbtt_uint32 offset = ttULONG(info->data + t + 2); + info->svg = t + offset; + } else { + info->svg = 0; + } + } + return info->svg; +} + +static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart) { - stbtt_uint8 *data = (stbtt_uint8 *) data2; stbtt_uint32 cmap, t; stbtt_int32 i,numTables; info->data = data; info->fontstart = fontstart; + info->cff = stbtt__new_buf(NULL, 0); cmap = stbtt__find_table(data, fontstart, "cmap"); // required info->loca = stbtt__find_table(data, fontstart, "loca"); // required @@ -1033,8 +1396,62 @@ STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data2, i info->hhea = stbtt__find_table(data, fontstart, "hhea"); // required info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); // required info->kern = stbtt__find_table(data, fontstart, "kern"); // not required - if (!cmap || !info->loca || !info->head || !info->glyf || !info->hhea || !info->hmtx) + info->gpos = stbtt__find_table(data, fontstart, "GPOS"); // not required + + if (!cmap || !info->head || !info->hhea || !info->hmtx) return 0; + if (info->glyf) { + // required for truetype + if (!info->loca) return 0; + } else { + // initialization for CFF / Type2 fonts (OTF) + stbtt__buf b, topdict, topdictidx; + stbtt_uint32 cstype = 2, charstrings = 0, fdarrayoff = 0, fdselectoff = 0; + stbtt_uint32 cff; + + cff = stbtt__find_table(data, fontstart, "CFF "); + if (!cff) return 0; + + info->fontdicts = stbtt__new_buf(NULL, 0); + info->fdselect = stbtt__new_buf(NULL, 0); + + // @TODO this should use size from table (not 512MB) + info->cff = stbtt__new_buf(data+cff, 512*1024*1024); + b = info->cff; + + // read the header + stbtt__buf_skip(&b, 2); + stbtt__buf_seek(&b, stbtt__buf_get8(&b)); // hdrsize + + // @TODO the name INDEX could list multiple fonts, + // but we just use the first one. + stbtt__cff_get_index(&b); // name INDEX + topdictidx = stbtt__cff_get_index(&b); + topdict = stbtt__cff_index_get(topdictidx, 0); + stbtt__cff_get_index(&b); // string INDEX + info->gsubrs = stbtt__cff_get_index(&b); + + stbtt__dict_get_ints(&topdict, 17, 1, &charstrings); + stbtt__dict_get_ints(&topdict, 0x100 | 6, 1, &cstype); + stbtt__dict_get_ints(&topdict, 0x100 | 36, 1, &fdarrayoff); + stbtt__dict_get_ints(&topdict, 0x100 | 37, 1, &fdselectoff); + info->subrs = stbtt__get_subrs(b, topdict); + + // we only support Type 2 charstrings + if (cstype != 2) return 0; + if (charstrings == 0) return 0; + + if (fdarrayoff) { + // looks like a CID font + if (!fdselectoff) return 0; + stbtt__buf_seek(&b, fdarrayoff); + info->fontdicts = stbtt__cff_get_index(&b); + info->fdselect = stbtt__buf_range(&b, fdselectoff, b.size-fdselectoff); + } + + stbtt__buf_seek(&b, charstrings); + info->charstrings = stbtt__cff_get_index(&b); + } t = stbtt__find_table(data, fontstart, "maxp"); if (t) @@ -1042,6 +1459,8 @@ STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data2, i else info->numGlyphs = 0xffff; + info->svg = -1; + // find a cmap encoding table we understand *now* to avoid searching // later. (todo: could make this installable) // the same regardless of glyph. @@ -1125,12 +1544,12 @@ STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codep search += 2; { - stbtt_uint16 offset, start; + stbtt_uint16 offset, start, last; stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1); - STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item)); start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item); - if (unicode_codepoint < start) + last = ttUSHORT(data + endCount + 2*item); + if (unicode_codepoint < start || unicode_codepoint > last) return 0; offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item); @@ -1185,6 +1604,8 @@ static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index) { int g1,g2; + STBTT_assert(!info->cff.size); + if (glyph_index >= info->numGlyphs) return -1; // glyph index out of range if (info->indexToLocFormat >= 2) return -1; // unknown index->glyph map format @@ -1199,15 +1620,21 @@ static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index) return g1==g2 ? -1 : g1; // if length is 0, return -1 } +static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); + STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1) { - int g = stbtt__GetGlyfOffset(info, glyph_index); - if (g < 0) return 0; + if (info->cff.size) { + stbtt__GetGlyphInfoT2(info, glyph_index, x0, y0, x1, y1); + } else { + int g = stbtt__GetGlyfOffset(info, glyph_index); + if (g < 0) return 0; - if (x0) *x0 = ttSHORT(info->data + g + 2); - if (y0) *y0 = ttSHORT(info->data + g + 4); - if (x1) *x1 = ttSHORT(info->data + g + 6); - if (y1) *y1 = ttSHORT(info->data + g + 8); + if (x0) *x0 = ttSHORT(info->data + g + 2); + if (y0) *y0 = ttSHORT(info->data + g + 4); + if (x1) *x1 = ttSHORT(info->data + g + 6); + if (y1) *y1 = ttSHORT(info->data + g + 8); + } return 1; } @@ -1219,7 +1646,10 @@ STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, i STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index) { stbtt_int16 numberOfContours; - int g = stbtt__GetGlyfOffset(info, glyph_index); + int g; + if (info->cff.size) + return stbtt__GetGlyphInfoT2(info, glyph_index, NULL, NULL, NULL, NULL) == 0; + g = stbtt__GetGlyfOffset(info, glyph_index); if (g < 0) return 1; numberOfContours = ttSHORT(info->data + g); return numberOfContours == 0; @@ -1241,7 +1671,7 @@ static int stbtt__close_shape(stbtt_vertex *vertices, int num_vertices, int was_ return num_vertices; } -STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) +static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) { stbtt_int16 numberOfContours; stbtt_uint8 *endPtsOfContours; @@ -1337,7 +1767,7 @@ STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, s if (i != 0) num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); - // now start the new one + // now start the new one start_off = !(flags & 1); if (start_off) { // if we start off with an off-curve point, then when we need to find a point on the curve @@ -1379,7 +1809,7 @@ STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, s } } num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); - } else if (numberOfContours == -1) { + } else if (numberOfContours < 0) { // Compound shapes. int more = 1; stbtt_uint8 *comp = data + g + 10; @@ -1390,7 +1820,7 @@ STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, s int comp_num_verts = 0, i; stbtt_vertex *comp_verts = 0, *tmp = 0; float mtx[6] = {1,0,0,1,0,0}, m, n; - + flags = ttSHORT(comp); comp+=2; gidx = ttSHORT(comp); comp+=2; @@ -1420,7 +1850,7 @@ STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, s mtx[2] = ttSHORT(comp)/16384.0f; comp+=2; mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; } - + // Find transformation scales. m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]); n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]); @@ -1446,7 +1876,7 @@ STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, s if (comp_verts) STBTT_free(comp_verts, info->userdata); return 0; } - if (num_vertices > 0) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex)); + if (num_vertices > 0 && vertices) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex)); STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex)); if (vertices) STBTT_free(vertices, info->userdata); vertices = tmp; @@ -1456,9 +1886,6 @@ STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, s // More components ? more = flags & (1<<5); } - } else if (numberOfContours < 0) { - // @TODO other compound variations? - STBTT_assert(0); } else { // numberOfCounters == 0, do nothing } @@ -1467,6 +1894,414 @@ STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, s return num_vertices; } +typedef struct +{ + int bounds; + int started; + float first_x, first_y; + float x, y; + stbtt_int32 min_x, max_x, min_y, max_y; + + stbtt_vertex *pvertices; + int num_vertices; +} stbtt__csctx; + +#define STBTT__CSCTX_INIT(bounds) {bounds,0, 0,0, 0,0, 0,0,0,0, NULL, 0} + +static void stbtt__track_vertex(stbtt__csctx *c, stbtt_int32 x, stbtt_int32 y) +{ + if (x > c->max_x || !c->started) c->max_x = x; + if (y > c->max_y || !c->started) c->max_y = y; + if (x < c->min_x || !c->started) c->min_x = x; + if (y < c->min_y || !c->started) c->min_y = y; + c->started = 1; +} + +static void stbtt__csctx_v(stbtt__csctx *c, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy, stbtt_int32 cx1, stbtt_int32 cy1) +{ + if (c->bounds) { + stbtt__track_vertex(c, x, y); + if (type == STBTT_vcubic) { + stbtt__track_vertex(c, cx, cy); + stbtt__track_vertex(c, cx1, cy1); + } + } else { + stbtt_setvertex(&c->pvertices[c->num_vertices], type, x, y, cx, cy); + c->pvertices[c->num_vertices].cx1 = (stbtt_int16) cx1; + c->pvertices[c->num_vertices].cy1 = (stbtt_int16) cy1; + } + c->num_vertices++; +} + +static void stbtt__csctx_close_shape(stbtt__csctx *ctx) +{ + if (ctx->first_x != ctx->x || ctx->first_y != ctx->y) + stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->first_x, (int)ctx->first_y, 0, 0, 0, 0); +} + +static void stbtt__csctx_rmove_to(stbtt__csctx *ctx, float dx, float dy) +{ + stbtt__csctx_close_shape(ctx); + ctx->first_x = ctx->x = ctx->x + dx; + ctx->first_y = ctx->y = ctx->y + dy; + stbtt__csctx_v(ctx, STBTT_vmove, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0); +} + +static void stbtt__csctx_rline_to(stbtt__csctx *ctx, float dx, float dy) +{ + ctx->x += dx; + ctx->y += dy; + stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0); +} + +static void stbtt__csctx_rccurve_to(stbtt__csctx *ctx, float dx1, float dy1, float dx2, float dy2, float dx3, float dy3) +{ + float cx1 = ctx->x + dx1; + float cy1 = ctx->y + dy1; + float cx2 = cx1 + dx2; + float cy2 = cy1 + dy2; + ctx->x = cx2 + dx3; + ctx->y = cy2 + dy3; + stbtt__csctx_v(ctx, STBTT_vcubic, (int)ctx->x, (int)ctx->y, (int)cx1, (int)cy1, (int)cx2, (int)cy2); +} + +static stbtt__buf stbtt__get_subr(stbtt__buf idx, int n) +{ + int count = stbtt__cff_index_count(&idx); + int bias = 107; + if (count >= 33900) + bias = 32768; + else if (count >= 1240) + bias = 1131; + n += bias; + if (n < 0 || n >= count) + return stbtt__new_buf(NULL, 0); + return stbtt__cff_index_get(idx, n); +} + +static stbtt__buf stbtt__cid_get_glyph_subrs(const stbtt_fontinfo *info, int glyph_index) +{ + stbtt__buf fdselect = info->fdselect; + int nranges, start, end, v, fmt, fdselector = -1, i; + + stbtt__buf_seek(&fdselect, 0); + fmt = stbtt__buf_get8(&fdselect); + if (fmt == 0) { + // untested + stbtt__buf_skip(&fdselect, glyph_index); + fdselector = stbtt__buf_get8(&fdselect); + } else if (fmt == 3) { + nranges = stbtt__buf_get16(&fdselect); + start = stbtt__buf_get16(&fdselect); + for (i = 0; i < nranges; i++) { + v = stbtt__buf_get8(&fdselect); + end = stbtt__buf_get16(&fdselect); + if (glyph_index >= start && glyph_index < end) { + fdselector = v; + break; + } + start = end; + } + } + if (fdselector == -1) stbtt__new_buf(NULL, 0); + return stbtt__get_subrs(info->cff, stbtt__cff_index_get(info->fontdicts, fdselector)); +} + +static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, stbtt__csctx *c) +{ + int in_header = 1, maskbits = 0, subr_stack_height = 0, sp = 0, v, i, b0; + int has_subrs = 0, clear_stack; + float s[48]; + stbtt__buf subr_stack[10], subrs = info->subrs, b; + float f; + +#define STBTT__CSERR(s) (0) + + // this currently ignores the initial width value, which isn't needed if we have hmtx + b = stbtt__cff_index_get(info->charstrings, glyph_index); + while (b.cursor < b.size) { + i = 0; + clear_stack = 1; + b0 = stbtt__buf_get8(&b); + switch (b0) { + // @TODO implement hinting + case 0x13: // hintmask + case 0x14: // cntrmask + if (in_header) + maskbits += (sp / 2); // implicit "vstem" + in_header = 0; + stbtt__buf_skip(&b, (maskbits + 7) / 8); + break; + + case 0x01: // hstem + case 0x03: // vstem + case 0x12: // hstemhm + case 0x17: // vstemhm + maskbits += (sp / 2); + break; + + case 0x15: // rmoveto + in_header = 0; + if (sp < 2) return STBTT__CSERR("rmoveto stack"); + stbtt__csctx_rmove_to(c, s[sp-2], s[sp-1]); + break; + case 0x04: // vmoveto + in_header = 0; + if (sp < 1) return STBTT__CSERR("vmoveto stack"); + stbtt__csctx_rmove_to(c, 0, s[sp-1]); + break; + case 0x16: // hmoveto + in_header = 0; + if (sp < 1) return STBTT__CSERR("hmoveto stack"); + stbtt__csctx_rmove_to(c, s[sp-1], 0); + break; + + case 0x05: // rlineto + if (sp < 2) return STBTT__CSERR("rlineto stack"); + for (; i + 1 < sp; i += 2) + stbtt__csctx_rline_to(c, s[i], s[i+1]); + break; + + // hlineto/vlineto and vhcurveto/hvcurveto alternate horizontal and vertical + // starting from a different place. + + case 0x07: // vlineto + if (sp < 1) return STBTT__CSERR("vlineto stack"); + goto vlineto; + case 0x06: // hlineto + if (sp < 1) return STBTT__CSERR("hlineto stack"); + for (;;) { + if (i >= sp) break; + stbtt__csctx_rline_to(c, s[i], 0); + i++; + vlineto: + if (i >= sp) break; + stbtt__csctx_rline_to(c, 0, s[i]); + i++; + } + break; + + case 0x1F: // hvcurveto + if (sp < 4) return STBTT__CSERR("hvcurveto stack"); + goto hvcurveto; + case 0x1E: // vhcurveto + if (sp < 4) return STBTT__CSERR("vhcurveto stack"); + for (;;) { + if (i + 3 >= sp) break; + stbtt__csctx_rccurve_to(c, 0, s[i], s[i+1], s[i+2], s[i+3], (sp - i == 5) ? s[i + 4] : 0.0f); + i += 4; + hvcurveto: + if (i + 3 >= sp) break; + stbtt__csctx_rccurve_to(c, s[i], 0, s[i+1], s[i+2], (sp - i == 5) ? s[i+4] : 0.0f, s[i+3]); + i += 4; + } + break; + + case 0x08: // rrcurveto + if (sp < 6) return STBTT__CSERR("rcurveline stack"); + for (; i + 5 < sp; i += 6) + stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); + break; + + case 0x18: // rcurveline + if (sp < 8) return STBTT__CSERR("rcurveline stack"); + for (; i + 5 < sp - 2; i += 6) + stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); + if (i + 1 >= sp) return STBTT__CSERR("rcurveline stack"); + stbtt__csctx_rline_to(c, s[i], s[i+1]); + break; + + case 0x19: // rlinecurve + if (sp < 8) return STBTT__CSERR("rlinecurve stack"); + for (; i + 1 < sp - 6; i += 2) + stbtt__csctx_rline_to(c, s[i], s[i+1]); + if (i + 5 >= sp) return STBTT__CSERR("rlinecurve stack"); + stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); + break; + + case 0x1A: // vvcurveto + case 0x1B: // hhcurveto + if (sp < 4) return STBTT__CSERR("(vv|hh)curveto stack"); + f = 0.0; + if (sp & 1) { f = s[i]; i++; } + for (; i + 3 < sp; i += 4) { + if (b0 == 0x1B) + stbtt__csctx_rccurve_to(c, s[i], f, s[i+1], s[i+2], s[i+3], 0.0); + else + stbtt__csctx_rccurve_to(c, f, s[i], s[i+1], s[i+2], 0.0, s[i+3]); + f = 0.0; + } + break; + + case 0x0A: // callsubr + if (!has_subrs) { + if (info->fdselect.size) + subrs = stbtt__cid_get_glyph_subrs(info, glyph_index); + has_subrs = 1; + } + // FALLTHROUGH + case 0x1D: // callgsubr + if (sp < 1) return STBTT__CSERR("call(g|)subr stack"); + v = (int) s[--sp]; + if (subr_stack_height >= 10) return STBTT__CSERR("recursion limit"); + subr_stack[subr_stack_height++] = b; + b = stbtt__get_subr(b0 == 0x0A ? subrs : info->gsubrs, v); + if (b.size == 0) return STBTT__CSERR("subr not found"); + b.cursor = 0; + clear_stack = 0; + break; + + case 0x0B: // return + if (subr_stack_height <= 0) return STBTT__CSERR("return outside subr"); + b = subr_stack[--subr_stack_height]; + clear_stack = 0; + break; + + case 0x0E: // endchar + stbtt__csctx_close_shape(c); + return 1; + + case 0x0C: { // two-byte escape + float dx1, dx2, dx3, dx4, dx5, dx6, dy1, dy2, dy3, dy4, dy5, dy6; + float dx, dy; + int b1 = stbtt__buf_get8(&b); + switch (b1) { + // @TODO These "flex" implementations ignore the flex-depth and resolution, + // and always draw beziers. + case 0x22: // hflex + if (sp < 7) return STBTT__CSERR("hflex stack"); + dx1 = s[0]; + dx2 = s[1]; + dy2 = s[2]; + dx3 = s[3]; + dx4 = s[4]; + dx5 = s[5]; + dx6 = s[6]; + stbtt__csctx_rccurve_to(c, dx1, 0, dx2, dy2, dx3, 0); + stbtt__csctx_rccurve_to(c, dx4, 0, dx5, -dy2, dx6, 0); + break; + + case 0x23: // flex + if (sp < 13) return STBTT__CSERR("flex stack"); + dx1 = s[0]; + dy1 = s[1]; + dx2 = s[2]; + dy2 = s[3]; + dx3 = s[4]; + dy3 = s[5]; + dx4 = s[6]; + dy4 = s[7]; + dx5 = s[8]; + dy5 = s[9]; + dx6 = s[10]; + dy6 = s[11]; + //fd is s[12] + stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3); + stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6); + break; + + case 0x24: // hflex1 + if (sp < 9) return STBTT__CSERR("hflex1 stack"); + dx1 = s[0]; + dy1 = s[1]; + dx2 = s[2]; + dy2 = s[3]; + dx3 = s[4]; + dx4 = s[5]; + dx5 = s[6]; + dy5 = s[7]; + dx6 = s[8]; + stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, 0); + stbtt__csctx_rccurve_to(c, dx4, 0, dx5, dy5, dx6, -(dy1+dy2+dy5)); + break; + + case 0x25: // flex1 + if (sp < 11) return STBTT__CSERR("flex1 stack"); + dx1 = s[0]; + dy1 = s[1]; + dx2 = s[2]; + dy2 = s[3]; + dx3 = s[4]; + dy3 = s[5]; + dx4 = s[6]; + dy4 = s[7]; + dx5 = s[8]; + dy5 = s[9]; + dx6 = dy6 = s[10]; + dx = dx1+dx2+dx3+dx4+dx5; + dy = dy1+dy2+dy3+dy4+dy5; + if (STBTT_fabs(dx) > STBTT_fabs(dy)) + dy6 = -dy; + else + dx6 = -dx; + stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3); + stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6); + break; + + default: + return STBTT__CSERR("unimplemented"); + } + } break; + + default: + if (b0 != 255 && b0 != 28 && b0 < 32) + return STBTT__CSERR("reserved operator"); + + // push immediate + if (b0 == 255) { + f = (float)(stbtt_int32)stbtt__buf_get32(&b) / 0x10000; + } else { + stbtt__buf_skip(&b, -1); + f = (float)(stbtt_int16)stbtt__cff_int(&b); + } + if (sp >= 48) return STBTT__CSERR("push stack overflow"); + s[sp++] = f; + clear_stack = 0; + break; + } + if (clear_stack) sp = 0; + } + return STBTT__CSERR("no endchar"); + +#undef STBTT__CSERR +} + +static int stbtt__GetGlyphShapeT2(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) +{ + // runs the charstring twice, once to count and once to output (to avoid realloc) + stbtt__csctx count_ctx = STBTT__CSCTX_INIT(1); + stbtt__csctx output_ctx = STBTT__CSCTX_INIT(0); + if (stbtt__run_charstring(info, glyph_index, &count_ctx)) { + *pvertices = (stbtt_vertex*)STBTT_malloc(count_ctx.num_vertices*sizeof(stbtt_vertex), info->userdata); + output_ctx.pvertices = *pvertices; + if (stbtt__run_charstring(info, glyph_index, &output_ctx)) { + STBTT_assert(output_ctx.num_vertices == count_ctx.num_vertices); + return output_ctx.num_vertices; + } + } + *pvertices = NULL; + return 0; +} + +static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1) +{ + stbtt__csctx c = STBTT__CSCTX_INIT(1); + int r = stbtt__run_charstring(info, glyph_index, &c); + if (x0) *x0 = r ? c.min_x : 0; + if (y0) *y0 = r ? c.min_y : 0; + if (x1) *x1 = r ? c.max_x : 0; + if (y1) *y1 = r ? c.max_y : 0; + return r ? c.num_vertices : 0; +} + +STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) +{ + if (!info->cff.size) + return stbtt__GetGlyphShapeTT(info, glyph_index, pvertices); + else + return stbtt__GetGlyphShapeT2(info, glyph_index, pvertices); +} + STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing) { stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data+info->hhea + 34); @@ -1479,7 +2314,49 @@ STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_inde } } -STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) +STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info) +{ + stbtt_uint8 *data = info->data + info->kern; + + // we only look at the first table. it must be 'horizontal' and format 0. + if (!info->kern) + return 0; + if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 + return 0; + if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format + return 0; + + return ttUSHORT(data+10); +} + +STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length) +{ + stbtt_uint8 *data = info->data + info->kern; + int k, length; + + // we only look at the first table. it must be 'horizontal' and format 0. + if (!info->kern) + return 0; + if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 + return 0; + if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format + return 0; + + length = ttUSHORT(data+10); + if (table_length < length) + length = table_length; + + for (k = 0; k < length; k++) + { + table[k].glyph1 = ttUSHORT(data+18+(k*6)); + table[k].glyph2 = ttUSHORT(data+20+(k*6)); + table[k].advance = ttSHORT(data+22+(k*6)); + } + + return length; +} + +static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) { stbtt_uint8 *data = info->data + info->kern; stbtt_uint32 needle, straw; @@ -1509,9 +2386,242 @@ STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, return 0; } +static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph) +{ + stbtt_uint16 coverageFormat = ttUSHORT(coverageTable); + switch (coverageFormat) { + case 1: { + stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2); + + // Binary search. + stbtt_int32 l=0, r=glyphCount-1, m; + int straw, needle=glyph; + while (l <= r) { + stbtt_uint8 *glyphArray = coverageTable + 4; + stbtt_uint16 glyphID; + m = (l + r) >> 1; + glyphID = ttUSHORT(glyphArray + 2 * m); + straw = glyphID; + if (needle < straw) + r = m - 1; + else if (needle > straw) + l = m + 1; + else { + return m; + } + } + break; + } + + case 2: { + stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2); + stbtt_uint8 *rangeArray = coverageTable + 4; + + // Binary search. + stbtt_int32 l=0, r=rangeCount-1, m; + int strawStart, strawEnd, needle=glyph; + while (l <= r) { + stbtt_uint8 *rangeRecord; + m = (l + r) >> 1; + rangeRecord = rangeArray + 6 * m; + strawStart = ttUSHORT(rangeRecord); + strawEnd = ttUSHORT(rangeRecord + 2); + if (needle < strawStart) + r = m - 1; + else if (needle > strawEnd) + l = m + 1; + else { + stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4); + return startCoverageIndex + glyph - strawStart; + } + } + break; + } + + default: return -1; // unsupported + } + + return -1; +} + +static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph) +{ + stbtt_uint16 classDefFormat = ttUSHORT(classDefTable); + switch (classDefFormat) + { + case 1: { + stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2); + stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4); + stbtt_uint8 *classDef1ValueArray = classDefTable + 6; + + if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount) + return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID)); + break; + } + + case 2: { + stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2); + stbtt_uint8 *classRangeRecords = classDefTable + 4; + + // Binary search. + stbtt_int32 l=0, r=classRangeCount-1, m; + int strawStart, strawEnd, needle=glyph; + while (l <= r) { + stbtt_uint8 *classRangeRecord; + m = (l + r) >> 1; + classRangeRecord = classRangeRecords + 6 * m; + strawStart = ttUSHORT(classRangeRecord); + strawEnd = ttUSHORT(classRangeRecord + 2); + if (needle < strawStart) + r = m - 1; + else if (needle > strawEnd) + l = m + 1; + else + return (stbtt_int32)ttUSHORT(classRangeRecord + 4); + } + break; + } + + default: + return -1; // Unsupported definition type, return an error. + } + + // "All glyphs not assigned to a class fall into class 0". (OpenType spec) + return 0; +} + +// Define to STBTT_assert(x) if you want to break on unimplemented formats. +#define STBTT_GPOS_TODO_assert(x) + +static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) +{ + stbtt_uint16 lookupListOffset; + stbtt_uint8 *lookupList; + stbtt_uint16 lookupCount; + stbtt_uint8 *data; + stbtt_int32 i, sti; + + if (!info->gpos) return 0; + + data = info->data + info->gpos; + + if (ttUSHORT(data+0) != 1) return 0; // Major version 1 + if (ttUSHORT(data+2) != 0) return 0; // Minor version 0 + + lookupListOffset = ttUSHORT(data+8); + lookupList = data + lookupListOffset; + lookupCount = ttUSHORT(lookupList); + + for (i=0; i<lookupCount; ++i) { + stbtt_uint16 lookupOffset = ttUSHORT(lookupList + 2 + 2 * i); + stbtt_uint8 *lookupTable = lookupList + lookupOffset; + + stbtt_uint16 lookupType = ttUSHORT(lookupTable); + stbtt_uint16 subTableCount = ttUSHORT(lookupTable + 4); + stbtt_uint8 *subTableOffsets = lookupTable + 6; + if (lookupType != 2) // Pair Adjustment Positioning Subtable + continue; + + for (sti=0; sti<subTableCount; sti++) { + stbtt_uint16 subtableOffset = ttUSHORT(subTableOffsets + 2 * sti); + stbtt_uint8 *table = lookupTable + subtableOffset; + stbtt_uint16 posFormat = ttUSHORT(table); + stbtt_uint16 coverageOffset = ttUSHORT(table + 2); + stbtt_int32 coverageIndex = stbtt__GetCoverageIndex(table + coverageOffset, glyph1); + if (coverageIndex == -1) continue; + + switch (posFormat) { + case 1: { + stbtt_int32 l, r, m; + int straw, needle; + stbtt_uint16 valueFormat1 = ttUSHORT(table + 4); + stbtt_uint16 valueFormat2 = ttUSHORT(table + 6); + if (valueFormat1 == 4 && valueFormat2 == 0) { // Support more formats? + stbtt_int32 valueRecordPairSizeInBytes = 2; + stbtt_uint16 pairSetCount = ttUSHORT(table + 8); + stbtt_uint16 pairPosOffset = ttUSHORT(table + 10 + 2 * coverageIndex); + stbtt_uint8 *pairValueTable = table + pairPosOffset; + stbtt_uint16 pairValueCount = ttUSHORT(pairValueTable); + stbtt_uint8 *pairValueArray = pairValueTable + 2; + + if (coverageIndex >= pairSetCount) return 0; + + needle=glyph2; + r=pairValueCount-1; + l=0; + + // Binary search. + while (l <= r) { + stbtt_uint16 secondGlyph; + stbtt_uint8 *pairValue; + m = (l + r) >> 1; + pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m; + secondGlyph = ttUSHORT(pairValue); + straw = secondGlyph; + if (needle < straw) + r = m - 1; + else if (needle > straw) + l = m + 1; + else { + stbtt_int16 xAdvance = ttSHORT(pairValue + 2); + return xAdvance; + } + } + } else + return 0; + break; + } + + case 2: { + stbtt_uint16 valueFormat1 = ttUSHORT(table + 4); + stbtt_uint16 valueFormat2 = ttUSHORT(table + 6); + if (valueFormat1 == 4 && valueFormat2 == 0) { // Support more formats? + stbtt_uint16 classDef1Offset = ttUSHORT(table + 8); + stbtt_uint16 classDef2Offset = ttUSHORT(table + 10); + int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1); + int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2); + + stbtt_uint16 class1Count = ttUSHORT(table + 12); + stbtt_uint16 class2Count = ttUSHORT(table + 14); + stbtt_uint8 *class1Records, *class2Records; + stbtt_int16 xAdvance; + + if (glyph1class < 0 || glyph1class >= class1Count) return 0; // malformed + if (glyph2class < 0 || glyph2class >= class2Count) return 0; // malformed + + class1Records = table + 16; + class2Records = class1Records + 2 * (glyph1class * class2Count); + xAdvance = ttSHORT(class2Records + 2 * glyph2class); + return xAdvance; + } else + return 0; + break; + } + + default: + return 0; // Unsupported position format + } + } + } + + return 0; +} + +STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int g2) +{ + int xAdvance = 0; + + if (info->gpos) + xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2); + else if (info->kern) + xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2); + + return xAdvance; +} + STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2) { - if (!info->kern) // if no kerning table, don't waste time looking up both codepoint->glyphs + if (!info->kern && !info->gpos) // if no kerning table, don't waste time looking up both codepoint->glyphs return 0; return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info,ch1), stbtt_FindGlyphIndex(info,ch2)); } @@ -1528,6 +2638,17 @@ STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, in if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8); } +STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap) +{ + int tab = stbtt__find_table(info->data, info->fontstart, "OS/2"); + if (!tab) + return 0; + if (typoAscent ) *typoAscent = ttSHORT(info->data+tab + 68); + if (typoDescent) *typoDescent = ttSHORT(info->data+tab + 70); + if (typoLineGap) *typoLineGap = ttSHORT(info->data+tab + 72); + return 1; +} + STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1) { *x0 = ttSHORT(info->data + info->head + 36); @@ -1553,6 +2674,45 @@ STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v) STBTT_free(v, info->userdata); } +STBTT_DEF stbtt_uint8 *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl) +{ + int i; + stbtt_uint8 *data = info->data; + stbtt_uint8 *svg_doc_list = data + stbtt__get_svg((stbtt_fontinfo *) info); + + int numEntries = ttUSHORT(svg_doc_list); + stbtt_uint8 *svg_docs = svg_doc_list + 2; + + for(i=0; i<numEntries; i++) { + stbtt_uint8 *svg_doc = svg_docs + (12 * i); + if ((gl >= ttUSHORT(svg_doc)) && (gl <= ttUSHORT(svg_doc + 2))) + return svg_doc; + } + return 0; +} + +STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg) +{ + stbtt_uint8 *data = info->data; + stbtt_uint8 *svg_doc; + + if (info->svg == 0) + return 0; + + svg_doc = stbtt_FindSVGDoc(info, gl); + if (svg_doc != NULL) { + *svg = (char *) data + info->svg + ttULONG(svg_doc + 4); + return ttULONG(svg_doc + 8); + } else { + return 0; + } +} + +STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg) +{ + return stbtt_GetGlyphSVG(info, stbtt_FindGlyphIndex(info, unicode_codepoint), svg); +} + ////////////////////////////////////////////////////////////////////////////// // // antialiasing software rasterizer @@ -1560,7 +2720,7 @@ STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v) STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1) { - int x0,y0,x1,y1; + int x0=0,y0=0,x1,y1; // =0 suppresses compiler warning if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) { // e.g. space character if (ix0) *ix0 = 0; @@ -1624,7 +2784,7 @@ static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata) hh->num_remaining_in_head_chunk = count; } --hh->num_remaining_in_head_chunk; - return (char *) (hh->head) + size * hh->num_remaining_in_head_chunk; + return (char *) (hh->head) + sizeof(stbtt__hheap_chunk) + size * hh->num_remaining_in_head_chunk; } } @@ -1676,8 +2836,9 @@ static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, i { stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata); float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); + STBTT_assert(z != NULL); if (!z) return z; - + // round dx down to avoid overshooting if (dxdy < 0) z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy); @@ -1697,6 +2858,7 @@ static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, i { stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata); float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); + STBTT_assert(z != NULL); //STBTT_assert(e->y0 <= start_point); if (!z) return z; z->fdx = dxdy; @@ -1754,7 +2916,7 @@ static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__ac } } } - + e = e->next; } } @@ -1768,13 +2930,10 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int s; // vertical subsample index unsigned char scanline_data[512], *scanline; - if (result->w > 512) { + if (result->w > 512) scanline = (unsigned char *) STBTT_malloc(result->w, userdata); - if (!scanline) - return; - } else { + else scanline = scanline_data; - } y = off_y * vsubsample; e[n].y0 = (off_y + result->h) * (float) vsubsample + 1; @@ -1824,23 +2983,23 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, while (e->y0 <= scan_y) { if (e->y1 > scan_y) { stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y, userdata); - if (!z) - return; - // find insertion point - if (active == NULL) - active = z; - else if (z->x < active->x) { - // insert at front - z->next = active; - active = z; - } else { - // find thing to insert AFTER - stbtt__active_edge *p = active; - while (p->next && p->next->x < z->x) - p = p->next; - // at this point, p->next->x is NOT < z->x - z->next = p->next; - p->next = z; + if (z != NULL) { + // find insertion point + if (active == NULL) + active = z; + else if (z->x < active->x) { + // insert at front + z->next = active; + active = z; + } else { + // find thing to insert AFTER + stbtt__active_edge *p = active; + while (p->next && p->next->x < z->x) + p = p->next; + // at this point, p->next->x is NOT < z->x + z->next = p->next; + p->next = z; + } } } ++e; @@ -1903,6 +3062,23 @@ static void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__active_edg } } +static float stbtt__sized_trapezoid_area(float height, float top_width, float bottom_width) +{ + STBTT_assert(top_width >= 0); + STBTT_assert(bottom_width >= 0); + return (top_width + bottom_width) / 2.0f * height; +} + +static float stbtt__position_trapezoid_area(float height, float tx0, float tx1, float bx0, float bx1) +{ + return stbtt__sized_trapezoid_area(height, tx1 - tx0, bx1 - bx0); +} + +static float stbtt__sized_triangle_area(float height, float width) +{ + return height * width / 2; +} + static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top) { float y_bottom = y_top+1; @@ -1957,13 +3133,13 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, float height; // simple case, only spans one pixel int x = (int) x_top; - height = sy1 - sy0; + height = (sy1 - sy0) * e->direction; STBTT_assert(x >= 0 && x < len); - scanline[x] += e->direction * (1-((x_top - x) + (x_bottom-x))/2) * height; - scanline_fill[x] += e->direction * height; // everything right of this pixel is filled + scanline[x] += stbtt__position_trapezoid_area(height, x_top, x+1.0f, x_bottom, x+1.0f); + scanline_fill[x] += height; // everything right of this pixel is filled } else { int x,x1,x2; - float y_crossing, step, sign, area; + float y_crossing, y_final, step, sign, area; // covers 2+ pixels if (x_top > x_bottom) { // flip scanline vertically; signed area is the same @@ -1976,29 +3152,79 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, dy = -dy; t = x0, x0 = xb, xb = t; } + STBTT_assert(dy >= 0); + STBTT_assert(dx >= 0); x1 = (int) x_top; x2 = (int) x_bottom; // compute intersection with y axis at x1+1 - y_crossing = (x1+1 - x0) * dy + y_top; + y_crossing = y_top + dy * (x1+1 - x0); + + // compute intersection with y axis at x2 + y_final = y_top + dy * (x2 - x0); + + // x1 x_top x2 x_bottom + // y_top +------|-----+------------+------------+--------|---+------------+ + // | | | | | | + // | | | | | | + // sy0 | Txxxxx|............|............|............|............| + // y_crossing | *xxxxx.......|............|............|............| + // | | xxxxx..|............|............|............| + // | | /- xx*xxxx........|............|............| + // | | dy < | xxxxxx..|............|............| + // y_final | | \- | xx*xxx.........|............| + // sy1 | | | | xxxxxB...|............| + // | | | | | | + // | | | | | | + // y_bottom +------------+------------+------------+------------+------------+ + // + // goal is to measure the area covered by '.' in each pixel + + // if x2 is right at the right edge of x1, y_crossing can blow up, github #1057 + // @TODO: maybe test against sy1 rather than y_bottom? + if (y_crossing > y_bottom) + y_crossing = y_bottom; sign = e->direction; - // area of the rectangle covered from y0..y_crossing + + // area of the rectangle covered from sy0..y_crossing area = sign * (y_crossing-sy0); - // area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing) - scanline[x1] += area * (1-((x_top - x1)+(x1+1-x1))/2); - step = sign * dy; + // area of the triangle (x_top,sy0), (x1+1,sy0), (x1+1,y_crossing) + scanline[x1] += stbtt__sized_triangle_area(area, x1+1 - x_top); + + // check if final y_crossing is blown up; no test case for this + if (y_final > y_bottom) { + y_final = y_bottom; + dy = (y_final - y_crossing ) / (x2 - (x1+1)); // if denom=0, y_final = y_crossing, so y_final <= y_bottom + } + + // in second pixel, area covered by line segment found in first pixel + // is always a rectangle 1 wide * the height of that line segment; this + // is exactly what the variable 'area' stores. it also gets a contribution + // from the line segment within it. the THIRD pixel will get the first + // pixel's rectangle contribution, the second pixel's rectangle contribution, + // and its own contribution. the 'own contribution' is the same in every pixel except + // the leftmost and rightmost, a trapezoid that slides down in each pixel. + // the second pixel's contribution to the third pixel will be the + // rectangle 1 wide times the height change in the second pixel, which is dy. + + step = sign * dy * 1; // dy is dy/dx, change in y for every 1 change in x, + // which multiplied by 1-pixel-width is how much pixel area changes for each step in x + // so the area advances by 'step' every time + for (x = x1+1; x < x2; ++x) { - scanline[x] += area + step/2; + scanline[x] += area + step/2; // area of trapezoid is 1*step/2 area += step; } - y_crossing += dy * (x2 - (x1+1)); + STBTT_assert(STBTT_fabs(area) <= 1.01f); // accumulated error from area += step unless we round step down + STBTT_assert(sy1 > y_final-0.01f); - STBTT_assert(fabs(area) <= 1.01f); - - scanline[x2] += area + sign * (1-(x_bottom-x2)/2) * (sy1-y_crossing); + // area covered in the last pixel is the rectangle from all the pixels to the left, + // plus the trapezoid filled by the line segment in this pixel all the way to the right edge + scanline[x2] += area + sign * stbtt__position_trapezoid_area(sy1-y_final, (float) x2, x2+1.0f, x_bottom, x2+1.0f); + // the rest of the line is filled based on the total height of the line segment in this pixel scanline_fill[x2] += sign * (sy1-sy0); } } else { @@ -2006,6 +3232,9 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, // clipping logic. since this does not match the intended use // of this library, we use a different, very slow brute // force implementation + // note though that this does happen some of the time because + // x_top and x_bottom can be extrapolated at the top & bottom of + // the shape and actually lie outside the bounding box int x; for (x=0; x < len; ++x) { // cases: @@ -2021,19 +3250,18 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, // from the other y segment, and it might ignored as an empty segment. to avoid // that, we need to explicitly produce segments based on x positions. - // rename variables to clear pairs + // rename variables to clearly-defined pairs float y0 = y_top; float x1 = (float) (x); float x2 = (float) (x+1); float x3 = xb; float y3 = y_bottom; - float y1,y2; // x = e->x + e->dx * (y-y_top) // (y-y_top) = (x - e->x) / e->dx // y = (x - e->x) / e->dx + y_top - y1 = (x - x0) / dx + y_top; - y2 = (x+1 - x0) / dx + y_top; + float y1 = (x - x0) / dx + y_top; + float y2 = (x+1 - x0) / dx + y_top; if (x0 < x1 && x3 > x2) { // three segments descending down-right stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); @@ -2073,13 +3301,12 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int y,j=0, i; float scanline_data[129], *scanline, *scanline2; - if (result->w > 64) { + STBTT__NOTUSED(vsubsample); + + if (result->w > 64) scanline = (float *) STBTT_malloc((result->w*2+1) * sizeof(float), userdata); - if (!scanline) - return; - } else { + else scanline = scanline_data; - } scanline2 = scanline + result->w; @@ -2113,12 +3340,18 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, while (e->y0 <= scan_y_bottom) { if (e->y0 != e->y1) { stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata); - if (!z) - return; - STBTT_assert(z->ey >= scan_y_top); - // insert at front - z->next = active; - active = z; + if (z != NULL) { + if (j == 0 && off_y != 0) { + if (z->ey < scan_y_top) { + // this can happen due to subpixel positioning and some kind of fp rounding error i think + z->ey = scan_y_top; + } + } + STBTT_assert(z->ey >= scan_y_top); // if we get really unlucky a tiny bit of an edge can be out of bounds + // insert at front + z->next = active; + active = z; + } } ++e; } @@ -2183,7 +3416,7 @@ static void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n) static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n) { - /* threshhold for transitioning to insertion sort */ + /* threshold for transitioning to insertion sort */ while (n > 12) { stbtt__edge t; int c01,c12,c,m,i,j; @@ -2318,7 +3551,7 @@ static void stbtt__add_point(stbtt__point *points, int n, float x, float y) points[n].y = y; } -// tesselate until threshhold p is happy... @TODO warped to compensate for non-linear stretching +// tessellate until threshold p is happy... @TODO warped to compensate for non-linear stretching static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float objspace_flatness_squared, int n) { // midpoint @@ -2339,6 +3572,48 @@ static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x return 1; } +static void stbtt__tesselate_cubic(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float objspace_flatness_squared, int n) +{ + // @TODO this "flatness" calculation is just made-up nonsense that seems to work well enough + float dx0 = x1-x0; + float dy0 = y1-y0; + float dx1 = x2-x1; + float dy1 = y2-y1; + float dx2 = x3-x2; + float dy2 = y3-y2; + float dx = x3-x0; + float dy = y3-y0; + float longlen = (float) (STBTT_sqrt(dx0*dx0+dy0*dy0)+STBTT_sqrt(dx1*dx1+dy1*dy1)+STBTT_sqrt(dx2*dx2+dy2*dy2)); + float shortlen = (float) STBTT_sqrt(dx*dx+dy*dy); + float flatness_squared = longlen*longlen-shortlen*shortlen; + + if (n > 16) // 65536 segments on one curve better be enough! + return; + + if (flatness_squared > objspace_flatness_squared) { + float x01 = (x0+x1)/2; + float y01 = (y0+y1)/2; + float x12 = (x1+x2)/2; + float y12 = (y1+y2)/2; + float x23 = (x2+x3)/2; + float y23 = (y2+y3)/2; + + float xa = (x01+x12)/2; + float ya = (y01+y12)/2; + float xb = (x12+x23)/2; + float yb = (y12+y23)/2; + + float mx = (xa+xb)/2; + float my = (ya+yb)/2; + + stbtt__tesselate_cubic(points, num_points, x0,y0, x01,y01, xa,ya, mx,my, objspace_flatness_squared,n+1); + stbtt__tesselate_cubic(points, num_points, mx,my, xb,yb, x23,y23, x3,y3, objspace_flatness_squared,n+1); + } else { + stbtt__add_point(points, *num_points,x3,y3); + *num_points = *num_points+1; + } +} + // returns number of contours static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata) { @@ -2395,6 +3670,14 @@ static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, objspace_flatness_squared, 0); x = vertices[i].x, y = vertices[i].y; break; + case STBTT_vcubic: + stbtt__tesselate_cubic(points, &num_points, x,y, + vertices[i].cx, vertices[i].cy, + vertices[i].cx1, vertices[i].cy1, + vertices[i].x, vertices[i].y, + objspace_flatness_squared, 0); + x = vertices[i].x, y = vertices[i].y; + break; } } (*contour_lengths)[n] = num_points - start; @@ -2411,8 +3694,9 @@ error: STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata) { - float scale = scale_x > scale_y ? scale_y : scale_x; - int winding_count, *winding_lengths; + float scale = scale_x > scale_y ? scale_y : scale_x; + int winding_count = 0; + int *winding_lengths = NULL; stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata); if (windings) { stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata); @@ -2430,7 +3714,7 @@ STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info { int ix0,iy0,ix1,iy1; stbtt__bitmap gbm; - stbtt_vertex *vertices; + stbtt_vertex *vertices; int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); if (scale_x == 0) scale_x = scale_y; @@ -2453,7 +3737,7 @@ STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info if (height) *height = gbm.h; if (xoff ) *xoff = ix0; if (yoff ) *yoff = iy0; - + if (gbm.w && gbm.h) { gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata); if (gbm.pixels) { @@ -2464,7 +3748,7 @@ STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info } STBTT_free(vertices, info->userdata); return gbm.pixels; -} +} STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff) { @@ -2476,7 +3760,7 @@ STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigne int ix0,iy0; stbtt_vertex *vertices; int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); - stbtt__bitmap gbm; + stbtt__bitmap gbm; stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0); gbm.pixels = output; @@ -2498,7 +3782,12 @@ STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char * STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff) { return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff); -} +} + +STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint) +{ + stbtt_MakeGlyphBitmapSubpixelPrefilter(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, oversample_x, oversample_y, sub_x, sub_y, stbtt_FindGlyphIndex(info,codepoint)); +} STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint) { @@ -2508,7 +3797,7 @@ STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, uns STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff) { return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f,0.0f, codepoint, width,height,xoff,yoff); -} +} STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint) { @@ -2521,7 +3810,7 @@ STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned ch // // This is SUPER-CRAPPY packing to keep source code small -STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) +static int stbtt_BakeFontBitmap_internal(unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) float pixel_height, // height of font in pixels unsigned char *pixels, int pw, int ph, // bitmap to be filled in int first_char, int num_chars, // characters to bake @@ -2530,6 +3819,7 @@ STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // fo float scale; int x,y,bottom_y, i; stbtt_fontinfo f; + f.userdata = NULL; if (!stbtt_InitFont(&f, data, offset)) return -1; STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels @@ -2566,11 +3856,11 @@ STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // fo return bottom_y; } -STBTT_DEF void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule) +STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule) { float d3d_bias = opengl_fillrule ? 0 : -0.5f; float ipw = 1.0f / pw, iph = 1.0f / ph; - stbtt_bakedchar *b = chardata + char_index; + const stbtt_bakedchar *b = chardata + char_index; int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5f); int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5f); @@ -2593,11 +3883,6 @@ STBTT_DEF void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, int // #ifndef STB_RECT_PACK_VERSION -#ifdef _MSC_VER -#define STBTT__NOTUSED(v) (void)(v) -#else -#define STBTT__NOTUSED(v) (void)sizeof(v) -#endif typedef int stbrp_coord; @@ -2637,7 +3922,7 @@ static void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *no con->y = 0; con->bottom_y = 0; STBTT__NOTUSED(nodes); - STBTT__NOTUSED(num_nodes); + STBTT__NOTUSED(num_nodes); } static void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rects) @@ -2691,6 +3976,7 @@ STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, in spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw; spc->h_oversample = 1; spc->v_oversample = 1; + spc->skip_missing = 0; stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes); @@ -2716,6 +4002,11 @@ STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h spc->v_oversample = v_oversample; } +STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip) +{ + spc->skip_missing = skip; +} + #define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1) static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width) @@ -2723,6 +4014,7 @@ static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_i unsigned char buffer[STBTT_MAX_OVERSAMPLE]; int safe_w = w - kernel_width; int j; + STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze for (j=0; j < h; ++j) { int i; unsigned int total; @@ -2784,6 +4076,7 @@ static void stbtt__v_prefilter(unsigned char *pixels, int w, int h, int stride_i unsigned char buffer[STBTT_MAX_OVERSAMPLE]; int safe_h = h - kernel_width; int j; + STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze for (j=0; j < w; ++j) { int i; unsigned int total; @@ -2853,9 +4146,10 @@ static float stbtt__oversample_shift(int oversample) } // rects array must be big enough to accommodate all characters in the given ranges -STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) +STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) { int i,j,k; + int missing_glyph_added = 0; k=0; for (i=0; i < num_ranges; ++i) { @@ -2867,13 +4161,19 @@ STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, stbtt_fon int x0,y0,x1,y1; int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; int glyph = stbtt_FindGlyphIndex(info, codepoint); - stbtt_GetGlyphBitmapBoxSubpixel(info,glyph, - scale * spc->h_oversample, - scale * spc->v_oversample, - 0,0, - &x0,&y0,&x1,&y1); - rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1); - rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1); + if (glyph == 0 && (spc->skip_missing || missing_glyph_added)) { + rects[k].w = rects[k].h = 0; + } else { + stbtt_GetGlyphBitmapBoxSubpixel(info,glyph, + scale * spc->h_oversample, + scale * spc->v_oversample, + 0,0, + &x0,&y0,&x1,&y1); + rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1); + rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1); + if (glyph == 0) + missing_glyph_added = 1; + } ++k; } } @@ -2881,10 +4181,33 @@ STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, stbtt_fon return k; } +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int prefilter_x, int prefilter_y, float *sub_x, float *sub_y, int glyph) +{ + stbtt_MakeGlyphBitmapSubpixel(info, + output, + out_w - (prefilter_x - 1), + out_h - (prefilter_y - 1), + out_stride, + scale_x, + scale_y, + shift_x, + shift_y, + glyph); + + if (prefilter_x > 1) + stbtt__h_prefilter(output, out_w, out_h, out_stride, prefilter_x); + + if (prefilter_y > 1) + stbtt__v_prefilter(output, out_w, out_h, out_stride, prefilter_y); + + *sub_x = stbtt__oversample_shift(prefilter_x); + *sub_y = stbtt__oversample_shift(prefilter_y); +} + // rects array must be big enough to accommodate all characters in the given ranges -STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) +STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) { - int i,j,k, return_value = 1; + int i,j,k, missing_glyph = -1, return_value = 1; // save current values int old_h_over = spc->h_oversample; @@ -2903,7 +4226,7 @@ STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, stbtt sub_y = stbtt__oversample_shift(spc->v_oversample); for (j=0; j < ranges[i].num_chars; ++j) { stbrp_rect *r = &rects[k]; - if (r->was_packed) { + if (r->was_packed && r->w != 0 && r->h != 0) { stbtt_packedchar *bc = &ranges[i].chardata_for_range[j]; int advance, lsb, x0,y0,x1,y1; int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; @@ -2949,6 +4272,13 @@ STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, stbtt bc->yoff = (float) y0 * recip_v + sub_y; bc->xoff2 = (x0 + r->w) * recip_h + sub_x; bc->yoff2 = (y0 + r->h) * recip_v + sub_y; + + if (glyph == 0) + missing_glyph = j; + } else if (spc->skip_missing) { + return_value = 0; + } else if (r->was_packed && r->w == 0 && r->h == 0 && missing_glyph >= 0) { + ranges[i].chardata_for_range[j] = ranges[i].chardata_for_range[missing_glyph]; } else { return_value = 0; // if any fail, report failure } @@ -2969,7 +4299,7 @@ STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect stbrp_pack_rects((stbrp_context *) spc->pack_info, rects, num_rects); } -STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges) +STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges) { stbtt_fontinfo info; int i,j,n, return_value = 1; @@ -2987,24 +4317,25 @@ STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontd n = 0; for (i=0; i < num_ranges; ++i) n += ranges[i].num_chars; - + rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context); if (rects == NULL) return 0; + info.userdata = spc->user_allocator_context; stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index)); n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects); stbtt_PackFontRangesPackRects(spc, rects, n); - + return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects); STBTT_free(rects, spc->user_allocator_context); return return_value; } -STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, float font_size, +STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size, int first_unicode_codepoint_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range) { stbtt_pack_range range; @@ -3016,10 +4347,23 @@ STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char *fontda return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1); } -STBTT_DEF void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer) +STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap) +{ + int i_ascent, i_descent, i_lineGap; + float scale; + stbtt_fontinfo info; + stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata, index)); + scale = size > 0 ? stbtt_ScaleForPixelHeight(&info, size) : stbtt_ScaleForMappingEmToPixels(&info, -size); + stbtt_GetFontVMetrics(&info, &i_ascent, &i_descent, &i_lineGap); + *ascent = (float) i_ascent * scale; + *descent = (float) i_descent * scale; + *lineGap = (float) i_lineGap * scale; +} + +STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer) { float ipw = 1.0f / pw, iph = 1.0f / ph; - stbtt_packedchar *b = chardata + char_index; + const stbtt_packedchar *b = chardata + char_index; if (align_to_integer) { float x = (float) STBTT_ifloor((*xpos + b->xoff) + 0.5f); @@ -3043,6 +4387,385 @@ STBTT_DEF void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, int ph, i *xpos += b->xadvance; } +////////////////////////////////////////////////////////////////////////////// +// +// sdf computation +// + +#define STBTT_min(a,b) ((a) < (b) ? (a) : (b)) +#define STBTT_max(a,b) ((a) < (b) ? (b) : (a)) + +static int stbtt__ray_intersect_bezier(float orig[2], float ray[2], float q0[2], float q1[2], float q2[2], float hits[2][2]) +{ + float q0perp = q0[1]*ray[0] - q0[0]*ray[1]; + float q1perp = q1[1]*ray[0] - q1[0]*ray[1]; + float q2perp = q2[1]*ray[0] - q2[0]*ray[1]; + float roperp = orig[1]*ray[0] - orig[0]*ray[1]; + + float a = q0perp - 2*q1perp + q2perp; + float b = q1perp - q0perp; + float c = q0perp - roperp; + + float s0 = 0., s1 = 0.; + int num_s = 0; + + if (a != 0.0) { + float discr = b*b - a*c; + if (discr > 0.0) { + float rcpna = -1 / a; + float d = (float) STBTT_sqrt(discr); + s0 = (b+d) * rcpna; + s1 = (b-d) * rcpna; + if (s0 >= 0.0 && s0 <= 1.0) + num_s = 1; + if (d > 0.0 && s1 >= 0.0 && s1 <= 1.0) { + if (num_s == 0) s0 = s1; + ++num_s; + } + } + } else { + // 2*b*s + c = 0 + // s = -c / (2*b) + s0 = c / (-2 * b); + if (s0 >= 0.0 && s0 <= 1.0) + num_s = 1; + } + + if (num_s == 0) + return 0; + else { + float rcp_len2 = 1 / (ray[0]*ray[0] + ray[1]*ray[1]); + float rayn_x = ray[0] * rcp_len2, rayn_y = ray[1] * rcp_len2; + + float q0d = q0[0]*rayn_x + q0[1]*rayn_y; + float q1d = q1[0]*rayn_x + q1[1]*rayn_y; + float q2d = q2[0]*rayn_x + q2[1]*rayn_y; + float rod = orig[0]*rayn_x + orig[1]*rayn_y; + + float q10d = q1d - q0d; + float q20d = q2d - q0d; + float q0rd = q0d - rod; + + hits[0][0] = q0rd + s0*(2.0f - 2.0f*s0)*q10d + s0*s0*q20d; + hits[0][1] = a*s0+b; + + if (num_s > 1) { + hits[1][0] = q0rd + s1*(2.0f - 2.0f*s1)*q10d + s1*s1*q20d; + hits[1][1] = a*s1+b; + return 2; + } else { + return 1; + } + } +} + +static int equal(float *a, float *b) +{ + return (a[0] == b[0] && a[1] == b[1]); +} + +static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex *verts) +{ + int i; + float orig[2], ray[2] = { 1, 0 }; + float y_frac; + int winding = 0; + + // make sure y never passes through a vertex of the shape + y_frac = (float) STBTT_fmod(y, 1.0f); + if (y_frac < 0.01f) + y += 0.01f; + else if (y_frac > 0.99f) + y -= 0.01f; + + orig[0] = x; + orig[1] = y; + + // test a ray from (-infinity,y) to (x,y) + for (i=0; i < nverts; ++i) { + if (verts[i].type == STBTT_vline) { + int x0 = (int) verts[i-1].x, y0 = (int) verts[i-1].y; + int x1 = (int) verts[i ].x, y1 = (int) verts[i ].y; + if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { + float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; + if (x_inter < x) + winding += (y0 < y1) ? 1 : -1; + } + } + if (verts[i].type == STBTT_vcurve) { + int x0 = (int) verts[i-1].x , y0 = (int) verts[i-1].y ; + int x1 = (int) verts[i ].cx, y1 = (int) verts[i ].cy; + int x2 = (int) verts[i ].x , y2 = (int) verts[i ].y ; + int ax = STBTT_min(x0,STBTT_min(x1,x2)), ay = STBTT_min(y0,STBTT_min(y1,y2)); + int by = STBTT_max(y0,STBTT_max(y1,y2)); + if (y > ay && y < by && x > ax) { + float q0[2],q1[2],q2[2]; + float hits[2][2]; + q0[0] = (float)x0; + q0[1] = (float)y0; + q1[0] = (float)x1; + q1[1] = (float)y1; + q2[0] = (float)x2; + q2[1] = (float)y2; + if (equal(q0,q1) || equal(q1,q2)) { + x0 = (int)verts[i-1].x; + y0 = (int)verts[i-1].y; + x1 = (int)verts[i ].x; + y1 = (int)verts[i ].y; + if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { + float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; + if (x_inter < x) + winding += (y0 < y1) ? 1 : -1; + } + } else { + int num_hits = stbtt__ray_intersect_bezier(orig, ray, q0, q1, q2, hits); + if (num_hits >= 1) + if (hits[0][0] < 0) + winding += (hits[0][1] < 0 ? -1 : 1); + if (num_hits >= 2) + if (hits[1][0] < 0) + winding += (hits[1][1] < 0 ? -1 : 1); + } + } + } + } + return winding; +} + +static float stbtt__cuberoot( float x ) +{ + if (x<0) + return -(float) STBTT_pow(-x,1.0f/3.0f); + else + return (float) STBTT_pow( x,1.0f/3.0f); +} + +// x^3 + a*x^2 + b*x + c = 0 +static int stbtt__solve_cubic(float a, float b, float c, float* r) +{ + float s = -a / 3; + float p = b - a*a / 3; + float q = a * (2*a*a - 9*b) / 27 + c; + float p3 = p*p*p; + float d = q*q + 4*p3 / 27; + if (d >= 0) { + float z = (float) STBTT_sqrt(d); + float u = (-q + z) / 2; + float v = (-q - z) / 2; + u = stbtt__cuberoot(u); + v = stbtt__cuberoot(v); + r[0] = s + u + v; + return 1; + } else { + float u = (float) STBTT_sqrt(-p/3); + float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; // p3 must be negative, since d is negative + float m = (float) STBTT_cos(v); + float n = (float) STBTT_cos(v-3.141592/2)*1.732050808f; + r[0] = s + u * 2 * m; + r[1] = s - u * (m + n); + r[2] = s - u * (m - n); + + //STBTT_assert( STBTT_fabs(((r[0]+a)*r[0]+b)*r[0]+c) < 0.05f); // these asserts may not be safe at all scales, though they're in bezier t parameter units so maybe? + //STBTT_assert( STBTT_fabs(((r[1]+a)*r[1]+b)*r[1]+c) < 0.05f); + //STBTT_assert( STBTT_fabs(((r[2]+a)*r[2]+b)*r[2]+c) < 0.05f); + return 3; + } +} + +STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) +{ + float scale_x = scale, scale_y = scale; + int ix0,iy0,ix1,iy1; + int w,h; + unsigned char *data; + + if (scale == 0) return NULL; + + stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f,0.0f, &ix0,&iy0,&ix1,&iy1); + + // if empty, return NULL + if (ix0 == ix1 || iy0 == iy1) + return NULL; + + ix0 -= padding; + iy0 -= padding; + ix1 += padding; + iy1 += padding; + + w = (ix1 - ix0); + h = (iy1 - iy0); + + if (width ) *width = w; + if (height) *height = h; + if (xoff ) *xoff = ix0; + if (yoff ) *yoff = iy0; + + // invert for y-downwards bitmaps + scale_y = -scale_y; + + { + int x,y,i,j; + float *precompute; + stbtt_vertex *verts; + int num_verts = stbtt_GetGlyphShape(info, glyph, &verts); + data = (unsigned char *) STBTT_malloc(w * h, info->userdata); + precompute = (float *) STBTT_malloc(num_verts * sizeof(float), info->userdata); + + for (i=0,j=num_verts-1; i < num_verts; j=i++) { + if (verts[i].type == STBTT_vline) { + float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y; + float x1 = verts[j].x*scale_x, y1 = verts[j].y*scale_y; + float dist = (float) STBTT_sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0)); + precompute[i] = (dist == 0) ? 0.0f : 1.0f / dist; + } else if (verts[i].type == STBTT_vcurve) { + float x2 = verts[j].x *scale_x, y2 = verts[j].y *scale_y; + float x1 = verts[i].cx*scale_x, y1 = verts[i].cy*scale_y; + float x0 = verts[i].x *scale_x, y0 = verts[i].y *scale_y; + float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2; + float len2 = bx*bx + by*by; + if (len2 != 0.0f) + precompute[i] = 1.0f / (bx*bx + by*by); + else + precompute[i] = 0.0f; + } else + precompute[i] = 0.0f; + } + + for (y=iy0; y < iy1; ++y) { + for (x=ix0; x < ix1; ++x) { + float val; + float min_dist = 999999.0f; + float sx = (float) x + 0.5f; + float sy = (float) y + 0.5f; + float x_gspace = (sx / scale_x); + float y_gspace = (sy / scale_y); + + int winding = stbtt__compute_crossings_x(x_gspace, y_gspace, num_verts, verts); // @OPTIMIZE: this could just be a rasterization, but needs to be line vs. non-tesselated curves so a new path + + for (i=0; i < num_verts; ++i) { + float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y; + + if (verts[i].type == STBTT_vline && precompute[i] != 0.0f) { + float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y; + + float dist,dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy); + if (dist2 < min_dist*min_dist) + min_dist = (float) STBTT_sqrt(dist2); + + // coarse culling against bbox + //if (sx > STBTT_min(x0,x1)-min_dist && sx < STBTT_max(x0,x1)+min_dist && + // sy > STBTT_min(y0,y1)-min_dist && sy < STBTT_max(y0,y1)+min_dist) + dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i]; + STBTT_assert(i != 0); + if (dist < min_dist) { + // check position along line + // x' = x0 + t*(x1-x0), y' = y0 + t*(y1-y0) + // minimize (x'-sx)*(x'-sx)+(y'-sy)*(y'-sy) + float dx = x1-x0, dy = y1-y0; + float px = x0-sx, py = y0-sy; + // minimize (px+t*dx)^2 + (py+t*dy)^2 = px*px + 2*px*dx*t + t^2*dx*dx + py*py + 2*py*dy*t + t^2*dy*dy + // derivative: 2*px*dx + 2*py*dy + (2*dx*dx+2*dy*dy)*t, set to 0 and solve + float t = -(px*dx + py*dy) / (dx*dx + dy*dy); + if (t >= 0.0f && t <= 1.0f) + min_dist = dist; + } + } else if (verts[i].type == STBTT_vcurve) { + float x2 = verts[i-1].x *scale_x, y2 = verts[i-1].y *scale_y; + float x1 = verts[i ].cx*scale_x, y1 = verts[i ].cy*scale_y; + float box_x0 = STBTT_min(STBTT_min(x0,x1),x2); + float box_y0 = STBTT_min(STBTT_min(y0,y1),y2); + float box_x1 = STBTT_max(STBTT_max(x0,x1),x2); + float box_y1 = STBTT_max(STBTT_max(y0,y1),y2); + // coarse culling against bbox to avoid computing cubic unnecessarily + if (sx > box_x0-min_dist && sx < box_x1+min_dist && sy > box_y0-min_dist && sy < box_y1+min_dist) { + int num=0; + float ax = x1-x0, ay = y1-y0; + float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2; + float mx = x0 - sx, my = y0 - sy; + float res[3] = {0.f,0.f,0.f}; + float px,py,t,it,dist2; + float a_inv = precompute[i]; + if (a_inv == 0.0) { // if a_inv is 0, it's 2nd degree so use quadratic formula + float a = 3*(ax*bx + ay*by); + float b = 2*(ax*ax + ay*ay) + (mx*bx+my*by); + float c = mx*ax+my*ay; + if (a == 0.0) { // if a is 0, it's linear + if (b != 0.0) { + res[num++] = -c/b; + } + } else { + float discriminant = b*b - 4*a*c; + if (discriminant < 0) + num = 0; + else { + float root = (float) STBTT_sqrt(discriminant); + res[0] = (-b - root)/(2*a); + res[1] = (-b + root)/(2*a); + num = 2; // don't bother distinguishing 1-solution case, as code below will still work + } + } + } else { + float b = 3*(ax*bx + ay*by) * a_inv; // could precompute this as it doesn't depend on sample point + float c = (2*(ax*ax + ay*ay) + (mx*bx+my*by)) * a_inv; + float d = (mx*ax+my*ay) * a_inv; + num = stbtt__solve_cubic(b, c, d, res); + } + dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy); + if (dist2 < min_dist*min_dist) + min_dist = (float) STBTT_sqrt(dist2); + + if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) { + t = res[0], it = 1.0f - t; + px = it*it*x0 + 2*t*it*x1 + t*t*x2; + py = it*it*y0 + 2*t*it*y1 + t*t*y2; + dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); + if (dist2 < min_dist * min_dist) + min_dist = (float) STBTT_sqrt(dist2); + } + if (num >= 2 && res[1] >= 0.0f && res[1] <= 1.0f) { + t = res[1], it = 1.0f - t; + px = it*it*x0 + 2*t*it*x1 + t*t*x2; + py = it*it*y0 + 2*t*it*y1 + t*t*y2; + dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); + if (dist2 < min_dist * min_dist) + min_dist = (float) STBTT_sqrt(dist2); + } + if (num >= 3 && res[2] >= 0.0f && res[2] <= 1.0f) { + t = res[2], it = 1.0f - t; + px = it*it*x0 + 2*t*it*x1 + t*t*x2; + py = it*it*y0 + 2*t*it*y1 + t*t*y2; + dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); + if (dist2 < min_dist * min_dist) + min_dist = (float) STBTT_sqrt(dist2); + } + } + } + } + if (winding == 0) + min_dist = -min_dist; // if outside the shape, value is negative + val = onedge_value + pixel_dist_scale * min_dist; + if (val < 0) + val = 0; + else if (val > 255) + val = 255; + data[(y-iy0)*w+(x-ix0)] = (unsigned char) val; + } + } + STBTT_free(precompute, info->userdata); + STBTT_free(verts, info->userdata); + } + return data; +} + +STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) +{ + return stbtt_GetGlyphSDF(info, scale, stbtt_FindGlyphIndex(info, codepoint), padding, onedge_value, pixel_dist_scale, width, height, xoff, yoff); +} + +STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata) +{ + STBTT_free(bitmap, userdata); +} ////////////////////////////////////////////////////////////////////////////// // @@ -3050,7 +4773,7 @@ STBTT_DEF void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, int ph, i // // check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string -static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(const stbtt_uint8 *s1, stbtt_int32 len1, const stbtt_uint8 *s2, stbtt_int32 len2) +static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2) { stbtt_int32 i=0; @@ -3089,9 +4812,9 @@ static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(const stbtt_uint8 return i; } -STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2) +static int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2) { - return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((const stbtt_uint8*) s1, len1, (const stbtt_uint8*) s2, len2); + return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*) s1, len1, (stbtt_uint8*) s2, len2); } // returns results in whatever encoding you request... but note that 2-byte encodings @@ -3147,7 +4870,7 @@ static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name, return 1; } else if (matchlen < nlen && name[matchlen] == ' ') { ++matchlen; - if (stbtt_CompareUTF8toUTF16_bigendian((char*) (name+matchlen), nlen-matchlen, (char*)(fc+stringOffset+off),slen)) + if (stbtt_CompareUTF8toUTF16_bigendian_internal((char*) (name+matchlen), nlen-matchlen, (char*)(fc+stringOffset+off),slen)) return 1; } } else { @@ -3193,7 +4916,7 @@ static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *nam return 0; } -STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *font_collection, const char *name_utf8, stbtt_int32 flags) +static int stbtt_FindMatchingFont_internal(unsigned char *font_collection, char *name_utf8, stbtt_int32 flags) { stbtt_int32 i; for (i=0;;++i) { @@ -3204,11 +4927,71 @@ STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *font_collection, const } } +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-qual" +#endif + +STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, + float pixel_height, unsigned char *pixels, int pw, int ph, + int first_char, int num_chars, stbtt_bakedchar *chardata) +{ + return stbtt_BakeFontBitmap_internal((unsigned char *) data, offset, pixel_height, pixels, pw, ph, first_char, num_chars, chardata); +} + +STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index) +{ + return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index); +} + +STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data) +{ + return stbtt_GetNumberOfFonts_internal((unsigned char *) data); +} + +STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset) +{ + return stbtt_InitFont_internal(info, (unsigned char *) data, offset); +} + +STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags) +{ + return stbtt_FindMatchingFont_internal((unsigned char *) fontdata, (char *) name, flags); +} + +STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2) +{ + return stbtt_CompareUTF8toUTF16_bigendian_internal((char *) s1, len1, (char *) s2, len2); +} + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic pop +#endif + #endif // STB_TRUETYPE_IMPLEMENTATION // FULL VERSION HISTORY // +// 1.25 (2021-07-11) many fixes +// 1.24 (2020-02-05) fix warning +// 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS) +// 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined +// 1.21 (2019-02-25) fix warning +// 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics() +// 1.19 (2018-02-11) OpenType GPOS kerning (horizontal only), STBTT_fmod +// 1.18 (2018-01-29) add missing function +// 1.17 (2017-07-23) make more arguments const; doc fix +// 1.16 (2017-07-12) SDF support +// 1.15 (2017-03-03) make more arguments const +// 1.14 (2017-01-16) num-fonts-in-TTC function +// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts +// 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual +// 1.11 (2016-04-02) fix unused-variable warning +// 1.10 (2016-04-02) allow user-defined fabs() replacement +// fix memory leak if fontsize=0.0 +// fix warning from duplicate typedef +// 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use alloc userdata for PackFontRanges // 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges // 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; // allow PackFontRanges to pack and render in separate phases; @@ -3250,3 +5033,45 @@ STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *font_collection, const // 0.2 (2009-03-11) Fix unsigned/signed char warnings // 0.1 (2009-03-09) First public release // + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c index a21fde0e1d4..05f93047809 100644 --- a/drivers/video/vidconsole-uclass.c +++ b/drivers/video/vidconsole-uclass.c @@ -596,6 +596,48 @@ int vidconsole_select_font(struct udevice *dev, const char *name, uint size) return ops->select_font(dev, name, size); } +int vidconsole_measure(struct udevice *dev, const char *name, uint size, + const char *text, struct vidconsole_bbox *bbox) +{ + struct vidconsole_priv *priv = dev_get_uclass_priv(dev); + struct vidconsole_ops *ops = vidconsole_get_ops(dev); + int ret; + + if (ops->select_font) { + ret = ops->measure(dev, name, size, text, bbox); + if (ret != -ENOSYS) + return ret; + } + + bbox->valid = true; + bbox->x0 = 0; + bbox->y0 = 0; + bbox->x1 = priv->x_charsize * strlen(text); + bbox->y1 = priv->y_charsize; + + return 0; +} + +void vidconsole_push_colour(struct udevice *dev, enum colour_idx fg, + enum colour_idx bg, struct vidconsole_colour *old) +{ + struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent); + + old->colour_fg = vid_priv->colour_fg; + old->colour_bg = vid_priv->colour_bg; + + vid_priv->colour_fg = video_index_to_colour(vid_priv, fg); + vid_priv->colour_bg = video_index_to_colour(vid_priv, bg); +} + +void vidconsole_pop_colour(struct udevice *dev, struct vidconsole_colour *old) +{ + struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent); + + vid_priv->colour_fg = old->colour_fg; + vid_priv->colour_bg = old->colour_bg; +} + /* Set up the number of rows and colours (rotated drivers override this) */ static int vidconsole_pre_probe(struct udevice *dev) { diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c index 1b66a8061a7..95e874b770b 100644 --- a/drivers/video/video-uclass.c +++ b/drivers/video/video-uclass.c @@ -142,6 +142,58 @@ int video_reserve(ulong *addrp) return 0; } +int video_fill_part(struct udevice *dev, int xstart, int ystart, int xend, + int yend, u32 colour) +{ + struct video_priv *priv = dev_get_uclass_priv(dev); + void *start, *line; + int pixels = xend - xstart; + int row, i, ret; + + start = priv->fb + ystart * priv->line_length; + start += xstart * VNBYTES(priv->bpix); + line = start; + for (row = ystart; row < yend; row++) { + switch (priv->bpix) { + case VIDEO_BPP8: { + u8 *dst = line; + + if (IS_ENABLED(CONFIG_VIDEO_BPP8)) { + for (i = 0; i < pixels; i++) + *dst++ = colour; + } + break; + } + case VIDEO_BPP16: { + u16 *dst = line; + + if (IS_ENABLED(CONFIG_VIDEO_BPP16)) { + for (i = 0; i < pixels; i++) + *dst++ = colour; + } + break; + } + case VIDEO_BPP32: { + u32 *dst = line; + + if (IS_ENABLED(CONFIG_VIDEO_BPP32)) { + for (i = 0; i < pixels; i++) + *dst++ = colour; + } + break; + } + default: + return -ENOSYS; + } + line += priv->line_length; + } + ret = video_sync_copy(dev, start, line); + if (ret) + return ret; + + return 0; +} + int video_fill(struct udevice *dev, u32 colour) { struct video_priv *priv = dev_get_uclass_priv(dev); @@ -208,7 +260,7 @@ static const struct vid_rgb colours[VID_COLOUR_COUNT] = { { 0xff, 0xff, 0xff }, /* white */ }; -u32 video_index_to_colour(struct video_priv *priv, unsigned int idx) +u32 video_index_to_colour(struct video_priv *priv, enum colour_idx idx) { switch (priv->bpix) { case VIDEO_BPP16: diff --git a/env/Kconfig b/env/Kconfig index 7342397e169..13e32104b4c 100644 --- a/env/Kconfig +++ b/env/Kconfig @@ -662,6 +662,18 @@ config SYS_MMC_ENV_PART partition 0 or the first boot partition, which is 1 or some other defined partition. +config USE_ENV_MMC_PARTITION + bool "use the mmc environment partition name" + depends on ENV_IS_IN_MMC + +config ENV_MMC_PARTITION + string "mmc environment partition name" + depends on USE_ENV_MMC_PARTITION + help + MMC partition name used to save environment variables. + If this variable is unset, u-boot will try to get the env partition name + from the device-tree's /config node. + config ENV_MMC_USE_DT bool "Read partition name and offset in DT" depends on ENV_IS_IN_MMC && OF_CONTROL diff --git a/env/mmc.c b/env/mmc.c index 7a5836ad66c..cb14bbb58f1 100644 --- a/env/mmc.c +++ b/env/mmc.c @@ -114,8 +114,13 @@ static inline s64 mmc_offset(struct mmc *mmc, int copy) if (IS_ENABLED(CONFIG_SYS_MMC_ENV_PART)) hwpart = mmc_get_env_part(mmc); +#if defined(CONFIG_ENV_MMC_PARTITION) + str = CONFIG_ENV_MMC_PARTITION; +#else /* look for the partition in mmc CONFIG_SYS_MMC_ENV_DEV */ str = ofnode_conf_read_str(dt_prop.partition); +#endif + if (str) { /* try to place the environment at end of the partition */ err = mmc_offset_try_partition(str, copy, &val); @@ -13,6 +13,7 @@ #include <env.h> #include <lmb.h> #include <log.h> +#include <malloc.h> #include <mapmem.h> #include <part.h> #include <ext4fs.h> @@ -26,6 +27,7 @@ #include <asm/io.h> #include <div64.h> #include <linux/math64.h> +#include <linux/sizes.h> #include <efi_loader.h> #include <squashfs.h> #include <erofs.h> @@ -1008,3 +1010,59 @@ int do_fs_types(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]) puts("\n"); return CMD_RET_SUCCESS; } + +int fs_read_alloc(const char *fname, ulong size, uint align, void **bufp) +{ + loff_t bytes_read; + ulong addr; + char *buf; + int ret; + + buf = memalign(align, size + 1); + if (!buf) + return log_msg_ret("buf", -ENOMEM); + addr = map_to_sysmem(buf); + + ret = fs_read(fname, addr, 0, size, &bytes_read); + if (ret) { + free(buf); + return log_msg_ret("read", ret); + } + if (size != bytes_read) + return log_msg_ret("bread", -EIO); + buf[size] = '\0'; + + *bufp = buf; + + return 0; +} + +int fs_load_alloc(const char *ifname, const char *dev_part_str, + const char *fname, ulong max_size, ulong align, void **bufp, + ulong *sizep) +{ + loff_t size; + void *buf; + int ret; + + if (fs_set_blk_dev(ifname, dev_part_str, FS_TYPE_ANY)) + return log_msg_ret("set", -ENOMEDIUM); + + ret = fs_size(fname, &size); + if (ret) + return log_msg_ret("sz", -ENOENT); + + if (size >= (max_size ?: SZ_1G)) + return log_msg_ret("sz", -E2BIG); + + if (fs_set_blk_dev(ifname, dev_part_str, FS_TYPE_ANY)) + return log_msg_ret("set", -ENOMEDIUM); + + ret = fs_read_alloc(fname, size, align, &buf); + if (ret) + return log_msg_ret("al", ret); + *sizep = size; + *bufp = buf; + + return 0; +} diff --git a/include/configs/arbel.h b/include/configs/arbel.h index 8e27fb52a1c..891257bc93a 100644 --- a/include/configs/arbel.h +++ b/include/configs/arbel.h @@ -7,12 +7,13 @@ #define __CONFIG_ARBEL_H #define CFG_SYS_SDRAM_BASE 0x0 -#define CFG_SYS_BOOTMAPSZ (20 << 20) +#define CFG_SYS_BOOTMAPSZ (30 << 20) +#define CFG_SYS_BOOTM_LEN (20 << 20) #define CFG_SYS_INIT_RAM_ADDR CFG_SYS_SDRAM_BASE #define CFG_SYS_INIT_RAM_SIZE 0x8000 /* Default environemnt variables */ -#define CFG_EXTRA_ENV_SETTINGS "uimage_flash_addr=80200000\0" \ +#define CFG_EXTRA_ENV_SETTINGS "uimage_flash_addr=80400000\0" \ "stdin=serial\0" \ "stdout=serial\0" \ "stderr=serial\0" \ diff --git a/include/configs/imx8mm_beacon.h b/include/configs/imx8mm_beacon.h index d85ae21e231..fa20651d2df 100644 --- a/include/configs/imx8mm_beacon.h +++ b/include/configs/imx8mm_beacon.h @@ -9,8 +9,17 @@ #include <linux/sizes.h> #include <asm/arch/imx-regs.h> +#define UBOOT_ITB_OFFSET 0x57C00 +#define FSPI_CONF_BLOCK_SIZE 0x1000 +#define UBOOT_ITB_OFFSET_FSPI \ + (UBOOT_ITB_OFFSET + FSPI_CONF_BLOCK_SIZE) +#ifdef CONFIG_FSPI_CONF_HEADER +#define CFG_SYS_UBOOT_BASE \ + (QSPI0_AMBA_BASE + UBOOT_ITB_OFFSET_FSPI) +#else #define CFG_SYS_UBOOT_BASE \ (QSPI0_AMBA_BASE + CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR * 512) +#endif #ifdef CONFIG_SPL_BUILD /* malloc f used before GD_FLG_FULL_MALLOC_INIT set */ @@ -19,56 +28,6 @@ #endif -/* Initial environment variables */ -#define CFG_EXTRA_ENV_SETTINGS \ - "script=boot.scr\0" \ - "image=Image\0" \ - "console=ttymxc1,115200\0" \ - "fdt_addr=0x43000000\0" \ - "boot_fit=try\0" \ - "fdt_file=" CONFIG_DEFAULT_FDT_FILE "\0" \ - "initrd_addr=0x43800000\0" \ - "mmcdev=" __stringify(CONFIG_SYS_MMC_ENV_DEV) "\0" \ - "mmcpart=1\0" \ - "finduuid=part uuid mmc ${mmcdev}:2 uuid\0" \ - "mmcautodetect=yes\0" \ - "mmcargs=setenv bootargs console=${console},${baudrate}" \ - " root=PARTUUID=${uuid} rootwait rw ${mtdparts} ${optargs}\0" \ - "loadbootscript=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr}" \ - " ${script};\0" \ - "bootscript=echo Running bootscript from mmc ...; " \ - "source\0" \ - "loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}\0" \ - "loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdt_file}\0" \ - "mmcboot=echo Booting from mmc ...; " \ - "run finduuid; " \ - "run mmcargs; " \ - "if run loadfdt; then " \ - "booti ${loadaddr} - ${fdt_addr}; " \ - "else " \ - "echo WARN: Cannot load the DT; " \ - "fi; " \ - "netargs=setenv bootargs console=${console} " \ - "root=/dev/nfs " \ - "ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp\0" \ - "netboot=echo Booting from net ...; " \ - "run netargs; " \ - "if test ${ip_dyn} = yes; then " \ - "setenv get_cmd dhcp; " \ - "else " \ - "setenv get_cmd tftp; " \ - "fi; " \ - "${get_cmd} ${loadaddr} ${image}; " \ - "if test ${boot_fit} = yes || test ${boot_fit} = try; then " \ - "bootm ${loadaddr}; " \ - "else " \ - "if ${get_cmd} ${fdt_addr} ${fdt_file}; then " \ - "booti ${loadaddr} - ${fdt_addr}; " \ - "else " \ - "echo WARN: Cannot load the DT; " \ - "fi; " \ - "fi;\0" - /* Link Definitions */ #define CFG_SYS_INIT_RAM_ADDR 0x40000000 diff --git a/include/configs/imx8mm_venice.h b/include/configs/imx8mm_venice.h index 5579a05d165..046d5685d04 100644 --- a/include/configs/imx8mm_venice.h +++ b/include/configs/imx8mm_venice.h @@ -26,16 +26,16 @@ func(DHCP, dhcp, na) #include <config_distro_bootcmd.h> #define CFG_EXTRA_ENV_SETTINGS \ - "splblk=0x42\0" \ BOOTENV #define CFG_SYS_INIT_RAM_ADDR 0x40000000 #define CFG_SYS_INIT_RAM_SIZE SZ_2M +/* SDRAM configuration: 4GiB */ #define CFG_SYS_SDRAM_BASE 0x40000000 - -/* SDRAM configuration */ -#define PHYS_SDRAM 0x40000000 -#define PHYS_SDRAM_SIZE SZ_4G +#define PHYS_SDRAM 0x40000000 +#define PHYS_SDRAM_SIZE 0x80000000 /* 2 GB */ +#define PHYS_SDRAM_2 0xC0000000 +#define PHYS_SDRAM_2_SIZE 0x80000000 /* 2 GB */ #endif diff --git a/include/configs/imx8mn_beacon.h b/include/configs/imx8mn_beacon.h index 1880d0311e4..699e2090449 100644 --- a/include/configs/imx8mn_beacon.h +++ b/include/configs/imx8mn_beacon.h @@ -12,67 +12,6 @@ #define CFG_SYS_UBOOT_BASE \ (QSPI0_AMBA_BASE + CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR * 512) -/* Initial environment variables */ -#define CFG_EXTRA_ENV_SETTINGS \ - "script=boot.scr\0" \ - "image=Image\0" \ - "ramdiskimage=rootfs.cpio.uboot\0" \ - "console=ttymxc1,115200\0" \ - "fdt_addr=0x43000000\0" \ - "ramdisk_addr=0x44000000\0" \ - "boot_fdt=try\0" \ - "fdt_file=" CONFIG_DEFAULT_FDT_FILE "\0" \ - "initrd_addr=0x43800000\0" \ - "mmcdev=" __stringify(CONFIG_SYS_MMC_ENV_DEV) "\0" \ - "mmcpart=1\0" \ - "finduuid=part uuid mmc ${mmcdev}:2 uuid\0" \ - "mmcautodetect=yes\0" \ - "mmcargs=setenv bootargs console=${console} " \ - " root=PARTUUID=${uuid} rootwait rw ${mtdparts} ${optargs}\0" \ - "ramargs=setenv bootargs console=${console} root=/dev/ram rw " \ - " ${optargs}\0" \ - "loadbootscript=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script};\0" \ - "bootscript=echo Running bootscript from mmc ...; " \ - "source\0" \ - "loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}\0" \ - "loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdt_file}\0" \ - "loadramdisk=load mmc ${mmcdev} ${ramdisk_addr} ${ramdiskimage}\0"\ - "mmcboot=echo Booting from mmc ...; " \ - "run finduuid; run mmcargs; " \ - "if test ${boot_fdt} = yes || test ${boot_fdt} = try; then " \ - "if run loadfdt; then " \ - "booti ${loadaddr} - ${fdt_addr}; " \ - "else " \ - "echo WARN: Cannot load the DT; " \ - "fi; " \ - "else " \ - "echo wait for boot; " \ - "fi;\0" \ - "netargs=setenv bootargs console=${console} " \ - "root=/dev/nfs " \ - "ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp\0" \ - "netboot=echo Booting from net ...; " \ - "run netargs; " \ - "if test ${ip_dyn} = yes; then " \ - "setenv get_cmd dhcp; " \ - "else " \ - "setenv get_cmd tftp; " \ - "fi; " \ - "${get_cmd} ${loadaddr} ${image}; " \ - "if test ${boot_fdt} = yes || test ${boot_fdt} = try; then " \ - "if ${get_cmd} ${fdt_addr} ${fdt_file}; then " \ - "booti ${loadaddr} - ${fdt_addr}; " \ - "else " \ - "echo WARN: Cannot load the DT; " \ - "fi; " \ - "else " \ - "booti; " \ - "fi;\0" \ - "ramboot=echo Booting from RAMdisk...; "\ - "run loadimage; run loadfdt; fdt addr $fdt_addr; "\ - "run loadramdisk; run ramargs; " \ - "booti ${loadaddr} ${ramdisk_addr} ${fdt_addr} ${optargs}\0" - /* Link Definitions */ #define CFG_SYS_INIT_RAM_ADDR 0x40000000 diff --git a/include/configs/imx8mn_venice.h b/include/configs/imx8mn_venice.h index 80c2df9f30f..1cc054a82ba 100644 --- a/include/configs/imx8mn_venice.h +++ b/include/configs/imx8mn_venice.h @@ -20,16 +20,16 @@ func(DHCP, dhcp, na) #include <config_distro_bootcmd.h> #define CFG_EXTRA_ENV_SETTINGS \ - "splblk=0x40\0" \ BOOTENV #define CFG_SYS_INIT_RAM_ADDR 0x40000000 #define CFG_SYS_INIT_RAM_SIZE SZ_2M +/* SDRAM configuration: 4GiB */ #define CFG_SYS_SDRAM_BASE 0x40000000 - -/* SDRAM configuration */ -#define PHYS_SDRAM 0x40000000 -#define PHYS_SDRAM_SIZE SZ_4G +#define PHYS_SDRAM 0x40000000 +#define PHYS_SDRAM_SIZE 0x80000000 /* 2 GB */ +#define PHYS_SDRAM_2 0xC0000000 +#define PHYS_SDRAM_2_SIZE 0x80000000 /* 2 GB */ #endif diff --git a/include/configs/imx8mp_venice.h b/include/configs/imx8mp_venice.h index 4b32d5a77ef..47413ecd7fb 100644 --- a/include/configs/imx8mp_venice.h +++ b/include/configs/imx8mp_venice.h @@ -20,16 +20,16 @@ func(DHCP, dhcp, na) #include <config_distro_bootcmd.h> #define CFG_EXTRA_ENV_SETTINGS \ - "splblk=0x40\0" \ BOOTENV #define CFG_SYS_INIT_RAM_ADDR 0x40000000 #define CFG_SYS_INIT_RAM_SIZE SZ_2M +/* SDRAM configuration: 4GiB */ #define CFG_SYS_SDRAM_BASE 0x40000000 - -/* SDRAM configuration */ -#define PHYS_SDRAM 0x40000000 -#define PHYS_SDRAM_SIZE SZ_4G +#define PHYS_SDRAM 0x40000000 +#define PHYS_SDRAM_SIZE 0x80000000 /* 2 GB */ +#define PHYS_SDRAM_2 0xC0000000 +#define PHYS_SDRAM_2_SIZE 0x80000000 /* 2 GB */ #endif diff --git a/include/configs/poleg.h b/include/configs/poleg.h index c3f1d3393cb..1e96e838be4 100644 --- a/include/configs/poleg.h +++ b/include/configs/poleg.h @@ -27,6 +27,8 @@ "eth1addr=00:00:F7:A0:00:FD\0" \ "eth2addr=00:00:F7:A0:00:FE\0" \ "eth3addr=00:00:F7:A0:00:FF\0" \ + "console=ttyS0,115200n8\0" \ + "earlycon=uart8250,mmio32,0xf0000000\0" \ "common_bootargs=setenv bootargs earlycon=${earlycon} root=/dev/ram " \ "console=${console} mem=${mem} ramdisk_size=48000 basemac=${ethaddr}\0" \ "sd_prog=fatload mmc 0 10000000 image-bmc; cp.b 10000000 80000000 ${filesize}\0" \ diff --git a/include/configs/qemu-riscv.h b/include/configs/qemu-riscv.h index 20135f569eb..f6d326bda0d 100644 --- a/include/configs/qemu-riscv.h +++ b/include/configs/qemu-riscv.h @@ -11,8 +11,8 @@ #define CFG_SYS_SDRAM_BASE 0x80000000 #define RISCV_MMODE_TIMERBASE 0x2000000 +#define RISCV_MMODE_TIMEROFF 0xbff8 #define RISCV_MMODE_TIMER_FREQ 1000000 - #define RISCV_SMODE_TIMER_FREQ 1000000 /* Environment options */ diff --git a/include/configs/sifive-unleashed.h b/include/configs/sifive-unleashed.h index de3a0dcdd59..f208f5e20db 100644 --- a/include/configs/sifive-unleashed.h +++ b/include/configs/sifive-unleashed.h @@ -14,8 +14,8 @@ #define CFG_SYS_SDRAM_BASE 0x80000000 #define RISCV_MMODE_TIMERBASE 0x2000000 +#define RISCV_MMODE_TIMEROFF 0xbff8 #define RISCV_MMODE_TIMER_FREQ 1000000 - #define RISCV_SMODE_TIMER_FREQ 1000000 /* Environment options */ diff --git a/include/configs/starfive-visionfive2.h b/include/configs/starfive-visionfive2.h index 93dcc22d366..4ee02b8420f 100644 --- a/include/configs/starfive-visionfive2.h +++ b/include/configs/starfive-visionfive2.h @@ -9,6 +9,7 @@ #define _STARFIVE_VISIONFIVE2_H #define RISCV_MMODE_TIMERBASE 0x2000000 +#define RISCV_MMODE_TIMEROFF 0xbff8 #define RISCV_MMODE_TIMER_FREQ 4000000 #define RISCV_SMODE_TIMER_FREQ 4000000 diff --git a/include/configs/th1520_lpi4a.h b/include/configs/th1520_lpi4a.h new file mode 100644 index 00000000000..87496a52c4c --- /dev/null +++ b/include/configs/th1520_lpi4a.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2023 Yixun Lan <dlan@gentoo.org> + * + */ + +#ifndef __TH1520_LPI4A_H +#define __TH1520_LPI4A_H + +#include <linux/sizes.h> + +#define CFG_SYS_SDRAM_BASE 0x00000000 + +#define UART_BASE 0xffe7014000 +#define UART_REG_WIDTH 32 + +/* Environment options */ + +#define CFG_EXTRA_ENV_SETTINGS \ + "PS1=[LPi4A]# \0" + +#endif /* __TH1520_LPI4A_H */ diff --git a/include/configs/x240.h b/include/configs/x240.h new file mode 100644 index 00000000000..3601df588d5 --- /dev/null +++ b/include/configs/x240.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2022 Allied Telesis + */ + +#ifndef __X240_H_ +#define __X240_H_ + +#include <asm/arch/soc.h> + +/* additions for new ARM relocation support */ +#define CFG_SYS_SDRAM_BASE 0x200000000 + +#define CFG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, \ + 115200, 230400, 460800, 921600 } + +/* Default Env vars */ + +#define BOOT_TARGET_DEVICES(func) \ + func(USB, usb, 0) \ + func(DHCP, dhcp, na) + +#include <config_distro_bootcmd.h> + +#define CFG_EXTRA_ENV_SETTINGS \ + BOOTENV \ + "kernel_addr_r=0x202000000\0" \ + "fdt_addr_r=0x201000000\0" \ + "ramdisk_addr_r=0x206000000\0" \ + "fdtfile=marvell/" CONFIG_DEFAULT_DEVICE_TREE ".dtb\0" + +/* + * High Level Configuration Options (easy to change) + */ +#define CFG_SYS_TCLK 325000000 + +#endif /* __X240_H_ */ diff --git a/include/dm/of.h b/include/dm/of.h index fce7cef0ff6..b1c934f610d 100644 --- a/include/dm/of.h +++ b/include/dm/of.h @@ -63,6 +63,8 @@ struct device_node { struct device_node *sibling; }; +#define BAD_OF_ROOT 0xdead11e3 + #define OF_MAX_PHANDLE_ARGS 16 /** diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h index 443db6252dd..0f38b3e736d 100644 --- a/include/dm/ofnode.h +++ b/include/dm/ofnode.h @@ -353,6 +353,16 @@ static inline oftree oftree_from_np(struct device_node *root) } /** + * oftree_dispose() - Dispose of an oftree + * + * This can be used to dispose of a tree that has been created (other than + * the control FDT which must not be disposed) + * + * @tree: Tree to dispose + */ +void oftree_dispose(oftree tree); + +/** * ofnode_name_eq() - Check if the node name is equivalent to a given name * ignoring the unit address * diff --git a/include/dm/platform_data/serial_pl01x.h b/include/dm/platform_data/serial_pl01x.h index e3d4e308a14..811697ce5c6 100644 --- a/include/dm/platform_data/serial_pl01x.h +++ b/include/dm/platform_data/serial_pl01x.h @@ -20,7 +20,11 @@ enum pl01x_type { * @skip_init: Don't attempt to change port configuration (also means @clock * is ignored) */ +#include <dt-structs.h> struct pl01x_serial_plat { +#if CONFIG_IS_ENABLED(OF_PLATDATA) + struct dtd_serial_pl01x dtplat; +#endif unsigned long base; enum pl01x_type type; unsigned int clock; diff --git a/include/dm/platform_data/spi_pl022.h b/include/dm/platform_data/spi_pl022.h deleted file mode 100644 index 7f74b3cbc5c..00000000000 --- a/include/dm/platform_data/spi_pl022.h +++ /dev/null @@ -1,21 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * (C) Copyright 2018 - * Quentin Schulz, Bootlin, quentin.schulz@bootlin.com - * - * Structure for use with U_BOOT_DRVINFO for pl022 SPI devices or to use - * in of_to_plat. - */ - -#ifndef __spi_pl022_h -#define __spi_pl022_h - -#include <fdtdec.h> - -struct pl022_spi_pdata { - fdt_addr_t addr; - fdt_size_t size; - unsigned int freq; -}; - -#endif /* __spi_pl022_h */ diff --git a/include/dt-bindings/clock/imx8mp-clock.h b/include/dt-bindings/clock/imx8mp-clock.h index 9d5cc2ddde8..3f28ce685f4 100644 --- a/include/dt-bindings/clock/imx8mp-clock.h +++ b/include/dt-bindings/clock/imx8mp-clock.h @@ -324,8 +324,18 @@ #define IMX8MP_CLK_CLKOUT2_SEL 317 #define IMX8MP_CLK_CLKOUT2_DIV 318 #define IMX8MP_CLK_CLKOUT2 319 - -#define IMX8MP_CLK_END 320 +#define IMX8MP_CLK_USB_SUSP 320 +#define IMX8MP_CLK_AUDIO_AHB_ROOT IMX8MP_CLK_AUDIO_ROOT +#define IMX8MP_CLK_AUDIO_AXI_ROOT 321 +#define IMX8MP_CLK_SAI1_ROOT 322 +#define IMX8MP_CLK_SAI2_ROOT 323 +#define IMX8MP_CLK_SAI3_ROOT 324 +#define IMX8MP_CLK_SAI5_ROOT 325 +#define IMX8MP_CLK_SAI6_ROOT 326 +#define IMX8MP_CLK_SAI7_ROOT 327 +#define IMX8MP_CLK_PDM_ROOT 328 +#define IMX8MP_CLK_MEDIA_LDB_ROOT 329 +#define IMX8MP_CLK_END 330 #define IMX8MP_CLK_AUDIOMIX_SAI1_IPG 0 #define IMX8MP_CLK_AUDIOMIX_SAI1_MCLK1 1 diff --git a/include/efi_config.h b/include/efi_config.h index 01ce9b2b06d..d7c1601137e 100644 --- a/include/efi_config.h +++ b/include/efi_config.h @@ -105,11 +105,6 @@ efi_status_t eficonfig_process_common(struct efimenu *efi_menu, void (*item_data_print)(void *), char *(*item_choice)(void *)); efi_status_t eficonfig_process_select_file(void *data); -efi_status_t eficonfig_get_unused_bootoption(u16 *buf, - efi_uintn_t buf_size, u32 *index); -efi_status_t eficonfig_append_bootorder(u16 index); -efi_status_t eficonfig_generate_media_device_boot_option(void); - efi_status_t eficonfig_append_menu_entry(struct efimenu *efi_menu, char *title, eficonfig_entry_func func, void *data); diff --git a/include/efi_loader.h b/include/efi_loader.h index 11e08a804f7..604fd765f75 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -517,6 +517,17 @@ struct efi_register_notify_event { int efi_init_early(void); /* Initialize efi execution environment */ efi_status_t efi_init_obj_list(void); +/* Append new boot option in BootOrder variable */ +efi_status_t efi_bootmgr_append_bootorder(u16 index); +/* Get unused "Boot####" index */ +efi_status_t efi_bootmgr_get_unused_bootoption(u16 *buf, + efi_uintn_t buf_size, u32 *index); +/* Generate the media device boot option */ +efi_status_t efi_bootmgr_update_media_device_boot_option(void); +/* Delete selected boot option */ +efi_status_t efi_bootmgr_delete_boot_option(u16 boot_index); +/* search the boot option index in BootOrder */ +bool efi_search_bootorder(u16 *bootorder, efi_uintn_t num, u32 target, u32 *index); /* Set up console modes */ void efi_setup_console_size(void); /* Install device tree */ diff --git a/include/expo.h b/include/expo.h index d242f48e30c..0b1d944a169 100644 --- a/include/expo.h +++ b/include/expo.h @@ -7,22 +7,31 @@ #ifndef __SCENE_H #define __SCENE_H +#include <dm/ofnode_decl.h> #include <linux/list.h> struct udevice; +struct video_priv; /** * enum expoact_type - types of actions reported by the expo * * @EXPOACT_NONE: no action - * @EXPOACT_POINT: menu item was highlighted (@id indicates which) + * @EXPOACT_POINT_OBJ: object was highlighted (@id indicates which) + * @EXPOACT_POINT_ITEM: menu item was highlighted (@id indicates which) * @EXPOACT_SELECT: menu item was selected (@id indicates which) + * @EXPOACT_OPEN: menu was opened, so an item can be selected (@id indicates + * which menu object) + * @EXPOACT_CLOSE: menu was closed (@id indicates which menu object) * @EXPOACT_QUIT: request to exit the menu */ enum expoact_type { EXPOACT_NONE, - EXPOACT_POINT, + EXPOACT_POINT_OBJ, + EXPOACT_POINT_ITEM, EXPOACT_SELECT, + EXPOACT_OPEN, + EXPOACT_CLOSE, EXPOACT_QUIT, }; @@ -30,7 +39,7 @@ enum expoact_type { * struct expo_action - an action report by the expo * * @type: Action type (EXPOACT_NONE if there is no action) - * @select: Used for EXPOACT_POINT and EXPOACT_SELECT + * @select: Used for EXPOACT_POINT_ITEM and EXPOACT_SELECT * @id: ID number of the object affected. */ struct expo_action { @@ -43,6 +52,19 @@ struct expo_action { }; /** + * struct expo_theme - theme for the expo + * + * @font_size: Default font size for all text + * @menu_inset: Inset width (on each side and top/bottom) for menu items + * @menuitem_gap_y: Gap between menu items in pixels + */ +struct expo_theme { + u32 font_size; + u32 menu_inset; + u32 menuitem_gap_y; +}; + +/** * struct expo - information about an expo * * A group of scenes which can be presented to the user, typically to obtain @@ -50,23 +72,29 @@ struct expo_action { * * @name: Name of the expo (allocated) * @display: Display to use (`UCLASS_VIDEO`), or NULL to use text mode + * @cons: Console to use (`UCLASS_VIDEO_CONSOLE`), or NULL to use text mode * @scene_id: Current scene ID (0 if none) * @next_id: Next ID number to use, for automatic allocation * @action: Action selected by user. At present only one is supported, with the * type set to EXPOACT_NONE if there is no action * @text_mode: true to use text mode for the menu (no vidconsole) + * @popup: true to use popup menus, instead of showing all items * @priv: Private data for the controller + * @theme: Information about fonts styles, etc. * @scene_head: List of scenes * @str_head: list of strings */ struct expo { char *name; struct udevice *display; + struct udevice *cons; uint scene_id; uint next_id; struct expo_action action; bool text_mode; + bool popup; void *priv; + struct expo_theme theme; struct list_head scene_head; struct list_head str_head; }; @@ -92,7 +120,8 @@ struct expo_string { * @expo: Expo this scene is part of * @name: Name of the scene (allocated) * @id: ID number of the scene - * @title: Title of the scene (allocated) + * @title_id: String ID of title of the scene (allocated) + * @highlight_id: ID of highlighted object, if any * @sibling: Node to link this scene to its siblings * @obj_head: List of objects in the scene */ @@ -100,7 +129,8 @@ struct scene { struct expo *expo; char *name; uint id; - char *title; + uint title_id; + uint highlight_id; struct list_head sibling; struct list_head obj_head; }; @@ -121,15 +151,43 @@ enum scene_obj_t { }; /** + * struct scene_dim - Dimensions of an object + * + * @x: x position, in pixels from left side + * @y: y position, in pixels from top + * @w: width, in pixels + * @h: height, in pixels + */ +struct scene_dim { + int x; + int y; + int w; + int h; +}; + +/** + * enum scene_obj_flags_t - flags for objects + * + * @SCENEOF_HIDE: object should be hidden + * @SCENEOF_POINT: object should be highlighted + * @SCENEOF_OPEN: object should be opened (e.g. menu is opened so that an option + * can be selected) + */ +enum scene_obj_flags_t { + SCENEOF_HIDE = 1 << 0, + SCENEOF_POINT = 1 << 1, + SCENEOF_OPEN = 1 << 2, +}; + +/** * struct scene_obj - information about an object in a scene * * @scene: Scene that this object relates to * @name: Name of the object (allocated) * @id: ID number of the object * @type: Type of this object - * @x: x position, in pixels from left side - * @y: y position, in pixels from top - * @hide: true if the object should be hidden + * @dim: Dimensions for this object + * @flags: Flags for this object * @sibling: Node to link this object to its siblings */ struct scene_obj { @@ -137,9 +195,8 @@ struct scene_obj { char *name; uint id; enum scene_obj_t type; - int x; - int y; - bool hide; + struct scene_dim dim; + int flags; struct list_head sibling; }; @@ -256,6 +313,25 @@ int expo_new(const char *name, void *priv, struct expo **expp); void expo_destroy(struct expo *exp); /** + * expo_set_dynamic_start() - Set the start of the 'dynamic' IDs + * + * It is common for a set of 'static' IDs to be used to refer to objects in the + * expo. These typically use an enum so that they are defined in sequential + * order. + * + * Dynamic IDs (for objects not in the enum) are intended to be used for + * objects to which the code does not need to refer. These are ideally located + * above the static IDs. + * + * Use this function to set the start of the dynamic range, making sure that the + * value is higher than all the statically allocated IDs. + * + * @exp: Expo to update + * @dyn_start: Start ID that expo should use for dynamic allocation + */ +void expo_set_dynamic_start(struct expo *exp, uint dyn_start); + +/** * expo_str() - add a new string to an expo * * @exp: Expo to update @@ -285,6 +361,16 @@ const char *expo_get_str(struct expo *exp, uint id); int expo_set_display(struct expo *exp, struct udevice *dev); /** + * expo_calc_dims() - Calculate the dimensions of the objects + * + * Updates the width and height of all objects based on their contents + * + * @exp: Expo to update + * Returns 0 if OK, -ENOTSUPP if there is no graphical console + */ +int expo_calc_dims(struct expo *exp); + +/** * expo_set_scene_id() - Set the current scene ID * * @exp: Expo to update @@ -294,6 +380,14 @@ int expo_set_display(struct expo *exp, struct udevice *dev); int expo_set_scene_id(struct expo *exp, uint scene_id); /** + * expo_first_scene_id() - Get the ID of the first scene + * + * @exp: Expo to check + * Returns: Scene ID of first scene, or -ENOENT if there are no scenes + */ +int expo_first_scene_id(struct expo *exp); + +/** * expo_render() - render the expo on the display / console * * @exp: Expo to render @@ -304,12 +398,12 @@ int expo_set_scene_id(struct expo *exp, uint scene_id); int expo_render(struct expo *exp); /** - * exp_set_text_mode() - Controls whether the expo renders in text mode + * expo_set_text_mode() - Controls whether the expo renders in text mode * * @exp: Expo to update * @text_mode: true to use text mode, false to use the console */ -void exp_set_text_mode(struct expo *exp, bool text_mode); +void expo_set_text_mode(struct expo *exp, bool text_mode); /** * scene_new() - create a new scene in a expo @@ -335,13 +429,43 @@ int scene_new(struct expo *exp, const char *name, uint id, struct scene **scnp); struct scene *expo_lookup_scene_id(struct expo *exp, uint scene_id); /** + * scene_highlight_first() - Highlight the first item in a scene + * + * This highlights the first item, so that the user can see that it is pointed + * to + * + * @scn: Scene to update + */ +void scene_highlight_first(struct scene *scn); + +/** + * scene_set_highlight_id() - Set the object which is highlighted + * + * Sets a new object to highlight in the scene + * + * @scn: Scene to update + * @id: ID of object to highlight + */ +void scene_set_highlight_id(struct scene *scn, uint id); + +/** + * scene_set_open() - Set whether an item is open or not + * + * @scn: Scene to update + * @id: ID of object to update + * @open: true to open the object, false to close it + * Returns: 0 if OK, -ENOENT if @id is invalid + */ +int scene_set_open(struct scene *scn, uint id, bool open); + +/** * scene_title_set() - set the scene title * * @scn: Scene to update - * @title: Title to set, NULL if none (this is allocated by this call) - * Returns: 0 if OK, -ENOMEM if out of memory + * @title_id: Title ID to set + * Returns: 0 if OK */ -int scene_title_set(struct scene *scn, const char *title); +int scene_title_set(struct scene *scn, uint title_id); /** * scene_obj_count() - Count the number of objects in a scene @@ -426,6 +550,17 @@ int scene_txt_set_font(struct scene *scn, uint id, const char *font_name, int scene_obj_set_pos(struct scene *scn, uint id, int x, int y); /** + * scene_obj_set_size() - Set the size of an object + * + * @scn: Scene to update + * @id: ID of object to update + * @w: width in pixels + * @h: height in pixels + * Returns: 0 if OK, -ENOENT if @id is invalid + */ +int scene_obj_set_size(struct scene *scn, uint id, int w, int h); + +/** * scene_obj_set_hide() - Set whether an object is hidden * * The update happens when the expo is next rendered. @@ -519,4 +654,46 @@ int expo_send_key(struct expo *exp, int key); */ int expo_action_get(struct expo *exp, struct expo_action *act); +/** + * expo_apply_theme() - Apply a theme to an expo + * + * @exp: Expo to update + * @node: Node containing the theme + */ +int expo_apply_theme(struct expo *exp, ofnode node); + +/** + * expo_build() - Build an expo from an FDT description + * + * Build a complete expo from a description in the provided devicetree. + * + * See doc/developer/expo.rst for a description of the format + * + * @root: Root node for expo description + * @expp: Returns the new expo + * Returns: 0 if OK, -ENOMEM if out of memory, -EINVAL if there is a format + * error, -ENOENT if there is a references to a non-existent string + */ +int expo_build(ofnode root, struct expo **expp); + +/** + * cedit_arange() - Arrange objects in a configuration-editor scene + * + * @exp: Expo to update + * @vid_priv: Private info of the video device + * @scene_id: scene ID to arrange + * Returns: 0 if OK, -ve on error + */ +int cedit_arange(struct expo *exp, struct video_priv *vid_priv, uint scene_id); + +/** + * cedit_run() - Run a configuration editor + * + * This accepts input until the user quits with Escape + * + * @exp: Expo to use + * Returns: 0 if OK, -ve on error + */ +int cedit_run(struct expo *exp); + #endif /*__SCENE_H */ diff --git a/include/firmware/imx/sci/rpc.h b/include/firmware/imx/sci/rpc.h index 39de7f0e3e0..85af6f3996e 100644 --- a/include/firmware/imx/sci/rpc.h +++ b/include/firmware/imx/sci/rpc.h @@ -23,12 +23,12 @@ #define RPC_FUNC(MSG) ((MSG)->func) #define RPC_R8(MSG) ((MSG)->func) #define RPC_I64(MSG, IDX) ((s64)(RPC_U32((MSG), (IDX))) << 32ULL) | \ - (s64)(RPC_U32((MSG), (IDX) + 4U)) + (s64)(RPC_U32((MSG), (IDX) + 4U)) #define RPC_I32(MSG, IDX) ((MSG)->DATA.i32[(IDX) / 4U]) #define RPC_I16(MSG, IDX) ((MSG)->DATA.i16[(IDX) / 2U]) #define RPC_I8(MSG, IDX) ((MSG)->DATA.i8[(IDX)]) #define RPC_U64(MSG, IDX) ((u64)(RPC_U32((MSG), (IDX))) << 32ULL) | \ - (u64)(RPC_U32((MSG), (IDX) + 4U)) + (u64)(RPC_U32((MSG), (IDX) + 4U)) #define RPC_U32(MSG, IDX) ((MSG)->DATA.u32[(IDX) / 4U]) #define RPC_U16(MSG, IDX) ((MSG)->DATA.u16[(IDX) / 2U]) #define RPC_U8(MSG, IDX) ((MSG)->DATA.u8[(IDX)]) @@ -67,7 +67,9 @@ struct sc_rpc_msg_s { #define PM_FUNC_SET_SYS_POWER_MODE 19U #define PM_FUNC_SET_PARTITION_POWER_MODE 1U #define PM_FUNC_GET_SYS_POWER_MODE 2U +#define PM_FUNC_PARTITION_WAKE 28U #define PM_FUNC_SET_RESOURCE_POWER_MODE 3U +#define PM_FUNC_SET_RESOURCE_POWER_MODE_ALL 22U #define PM_FUNC_GET_RESOURCE_POWER_MODE 4U #define PM_FUNC_REQ_LOW_POWER_MODE 16U #define PM_FUNC_REQ_CPU_LOW_POWER_MODE 20U @@ -81,13 +83,16 @@ struct sc_rpc_msg_s { #define PM_FUNC_GET_CLOCK_PARENT 15U #define PM_FUNC_RESET 13U #define PM_FUNC_RESET_REASON 10U +#define PM_FUNC_GET_RESET_PART 26U #define PM_FUNC_BOOT 8U +#define PM_FUNC_SET_BOOT_PARM 27U #define PM_FUNC_REBOOT 9U #define PM_FUNC_REBOOT_PARTITION 12U +#define PM_FUNC_REBOOT_CONTINUE 25U #define PM_FUNC_CPU_START 11U #define PM_FUNC_CPU_RESET 23U #define PM_FUNC_RESOURCE_RESET 29U -#define PM_FUNC_IS_PARTITION_STARTED 24U +#define PM_FUNC_IS_PARTITION_STARTED 24U /* MISC RPC */ #define MISC_FUNC_UNKNOWN 0 @@ -95,16 +100,10 @@ struct sc_rpc_msg_s { #define MISC_FUNC_GET_CONTROL 2U #define MISC_FUNC_SET_MAX_DMA_GROUP 4U #define MISC_FUNC_SET_DMA_GROUP 5U -#define MISC_FUNC_SECO_IMAGE_LOAD 8U -#define MISC_FUNC_SECO_AUTHENTICATE 9U -#define MISC_FUNC_SECO_FUSE_WRITE 20U -#define MISC_FUNC_SECO_ENABLE_DEBUG 21U -#define MISC_FUNC_SECO_FORWARD_LIFECYCLE 22U -#define MISC_FUNC_SECO_RETURN_LIFECYCLE 23U -#define MISC_FUNC_SECO_BUILD_INFO 24U #define MISC_FUNC_DEBUG_OUT 10U #define MISC_FUNC_WAVEFORM_CAPTURE 6U #define MISC_FUNC_BUILD_INFO 15U +#define MISC_FUNC_API_VER 35U #define MISC_FUNC_UNIQUE_ID 19U #define MISC_FUNC_SET_ARI 3U #define MISC_FUNC_BOOT_STATUS 7U @@ -114,8 +113,11 @@ struct sc_rpc_msg_s { #define MISC_FUNC_SET_TEMP 12U #define MISC_FUNC_GET_TEMP 13U #define MISC_FUNC_GET_BOOT_DEV 16U +#define MISC_FUNC_GET_BOOT_TYPE 33U +#define MISC_FUNC_GET_BOOT_CONTAINER 36U #define MISC_FUNC_GET_BUTTON_STATUS 18U -#define MISC_FUNC_GET_BOOT_CONTAINER 36U +#define MISC_FUNC_ROMPATCH_CHECKSUM 26U +#define MISC_FUNC_BOARD_IOCTL 34U /* PAD RPC */ #define PAD_FUNC_UNKNOWN 0 @@ -160,6 +162,7 @@ struct sc_rpc_msg_s { #define RM_FUNC_GET_RESOURCE_INFO 16U #define RM_FUNC_MEMREG_ALLOC 17U #define RM_FUNC_MEMREG_SPLIT 29U +#define RM_FUNC_MEMREG_FRAG 32U #define RM_FUNC_MEMREG_FREE 18U #define RM_FUNC_FIND_MEMREG 30U #define RM_FUNC_ASSIGN_MEMREG 19U @@ -190,6 +193,7 @@ struct sc_rpc_msg_s { #define SECO_FUNC_UPDATE_MPMR 14U /* Index for seco_update_mpmr() RPC call */ #define SECO_FUNC_GET_MP_SIGN 15U /* Index for seco_get_mp_sign() RPC call */ #define SECO_FUNC_BUILD_INFO 16U /* Index for seco_build_info() RPC call */ +#define SECO_FUNC_V2X_BUILD_INFO 30U /* Index for sc_seco_v2x_build_info() RPC call */ #define SECO_FUNC_CHIP_INFO 17U /* Index for seco_chip_info() RPC call */ #define SECO_FUNC_ENABLE_DEBUG 18U /* Index for seco_enable_debug() RPC call */ #define SECO_FUNC_GET_EVENT 19U /* Index for seco_get_event() RPC call */ @@ -210,6 +214,7 @@ struct sc_rpc_msg_s { #define TIMER_FUNC_UNKNOWN 0 /* Unknown function */ #define TIMER_FUNC_SET_WDOG_TIMEOUT 1U /* Index for sc_timer_set_wdog_timeout() RPC call */ #define TIMER_FUNC_SET_WDOG_PRE_TIMEOUT 12U /* Index for sc_timer_set_wdog_pre_timeout() RPC call */ +#define TIMER_FUNC_SET_WDOG_WINDOW 19U /* Index for sc_timer_set_wdog_window() RPC call */ #define TIMER_FUNC_START_WDOG 2U /* Index for sc_timer_start_wdog() RPC call */ #define TIMER_FUNC_STOP_WDOG 3U /* Index for sc_timer_stop_wdog() RPC call */ #define TIMER_FUNC_PING_WDOG 4U /* Index for sc_timer_ping_wdog() RPC call */ diff --git a/include/firmware/imx/sci/sci.h b/include/firmware/imx/sci/sci.h index 61c8211b443..f832982b3de 100644 --- a/include/firmware/imx/sci/sci.h +++ b/include/firmware/imx/sci/sci.h @@ -13,6 +13,7 @@ #include <firmware/imx/sci/svc/pm/api.h> #include <firmware/imx/sci/svc/rm/api.h> #include <firmware/imx/sci/svc/seco/api.h> +#include <firmware/imx/sci/svc/timer/api.h> #include <firmware/imx/sci/rpc.h> #include <dt-bindings/soc/imx_rsrc.h> #include <linux/errno.h> @@ -73,6 +74,7 @@ int sc_pm_set_clock_parent(sc_ipc_t ipc, sc_rsrc_t resource, sc_pm_clk_t clk, sc_pm_clk_parent_t parent); int sc_pm_cpu_start(sc_ipc_t ipc, sc_rsrc_t resource, sc_bool_t enable, sc_faddr_t address); +void sc_pm_reboot(sc_ipc_t ipc, sc_pm_reset_type_t type); sc_bool_t sc_pm_is_partition_started(sc_ipc_t ipc, sc_rm_pt_t pt); int sc_pm_resource_reset(sc_ipc_t ipc, sc_rsrc_t resource); @@ -88,6 +90,7 @@ void sc_misc_build_info(sc_ipc_t ipc, u32 *build, u32 *commit); int sc_misc_otp_fuse_read(sc_ipc_t ipc, u32 word, u32 *val); int sc_misc_get_temp(sc_ipc_t ipc, sc_rsrc_t resource, sc_misc_temp_t temp, s16 *celsius, s8 *tenths); +void sc_misc_get_button_status(sc_ipc_t ipc, sc_bool_t *status); /* RM API */ sc_bool_t sc_rm_is_memreg_owned(sc_ipc_t ipc, sc_rm_mr_t mr); @@ -117,6 +120,9 @@ int sc_pad_get(sc_ipc_t ipc, sc_pad_t pad, uint32_t *val); /* SMMU API */ int sc_rm_set_master_sid(sc_ipc_t ipc, sc_rsrc_t resource, sc_rm_sid_t sid); +/* Timer API */ +int sc_timer_set_wdog_window(sc_ipc_t ipc, sc_timer_wdog_time_t window); + /* SECO API */ int sc_seco_authenticate(sc_ipc_t ipc, sc_seco_auth_cmd_t cmd, sc_faddr_t addr); @@ -124,6 +130,7 @@ int sc_seco_forward_lifecycle(sc_ipc_t ipc, u32 change); int sc_seco_chip_info(sc_ipc_t ipc, u16 *lc, u16 *monotonic, u32 *uid_l, u32 *uid_h); void sc_seco_build_info(sc_ipc_t ipc, u32 *version, u32 *commit); +int sc_seco_v2x_build_info(sc_ipc_t ipc, u32 *version, u32 *commit); int sc_seco_get_event(sc_ipc_t ipc, u8 idx, u32 *event); int sc_seco_gen_key_blob(sc_ipc_t ipc, u32 id, sc_faddr_t load_addr, sc_faddr_t export_addr, u16 max_size); @@ -374,6 +381,23 @@ static inline int sc_seco_secvio_config(sc_ipc_t ipc, u8 id, u8 access, u32 *dat return -EOPNOTSUPP; } +static inline void sc_pm_reboot(sc_ipc_t ipc, sc_pm_reset_type_t type) +{ +} + +static inline int sc_seco_v2x_build_info(sc_ipc_t ipc, u32 *version, u32 *commit) +{ + return -EOPNOTSUPP; +} + +static inline void sc_misc_get_button_status(sc_ipc_t ipc, sc_bool_t *status) +{ +} + +static inline int sc_timer_set_wdog_window(sc_ipc_t ipc, sc_timer_wdog_time_t window) +{ + return -EOPNOTSUPP; +} #endif #endif diff --git a/include/firmware/imx/sci/svc/misc/api.h b/include/firmware/imx/sci/svc/misc/api.h index 3629eb68d7a..a4b92b86cc6 100644 --- a/include/firmware/imx/sci/svc/misc/api.h +++ b/include/firmware/imx/sci/svc/misc/api.h @@ -5,27 +5,45 @@ #ifndef SC_MISC_API_H #define SC_MISC_API_H +/* Defines for type widths */ +#define SC_MISC_DMA_GRP_W 5U /* Width of sc_misc_dma_group_t */ +/* Max DMA channel priority group */ +#define SC_MISC_DMA_GRP_MAX 31U /* Defines for sc_misc_boot_status_t */ #define SC_MISC_BOOT_STATUS_SUCCESS 0U /* Success */ #define SC_MISC_BOOT_STATUS_SECURITY 1U /* Security violation */ -/* Defines for sc_misc_seco_auth_cmd_t */ -#define SC_MISC_SECO_AUTH_SECO_FW 0U /* SECO Firmware */ -#define SC_MISC_SECO_AUTH_HDMI_TX_FW 1U /* HDMI TX Firmware */ -#define SC_MISC_SECO_AUTH_HDMI_RX_FW 2U /* HDMI RX Firmware */ - /* Defines for sc_misc_temp_t */ -#define SC_MISC_TEMP 0U /* Temp sensor */ -#define SC_MISC_TEMP_HIGH 1U /* Temp high alarm */ -#define SC_MISC_TEMP_LOW 2U /* Temp low alarm */ +#define SC_MISC_TEMP 0U /* Temp sensor */ +#define SC_MISC_TEMP_HIGH 1U /* Temp high alarm */ +#define SC_MISC_TEMP_LOW 2U /* Temp low alarm */ + +/* Defines for sc_misc_bt_t */ +#define SC_MISC_BT_PRIMARY 0U /* Primary boot */ +#define SC_MISC_BT_SECONDARY 1U /* Secondary boot */ +#define SC_MISC_BT_RECOVERY 2U /* Recovery boot */ +#define SC_MISC_BT_MANUFACTURE 3U /* Manufacture boot */ +#define SC_MISC_BT_SERIAL 4U /* Serial boot */ +/* Types */ -/* Defines for sc_misc_seco_auth_cmd_t */ -#define SC_MISC_AUTH_CONTAINER 0U /* Authenticate container */ -#define SC_MISC_VERIFY_IMAGE 1U /* Verify image */ -#define SC_MISC_REL_CONTAINER 2U /* Release container */ +/* + * This type is used to store a DMA channel priority group. + */ +typedef u8 sc_misc_dma_group_t; +/* + * This type is used report boot status. + */ typedef u8 sc_misc_boot_status_t; + +/* + * This type is used report boot status. + */ typedef u8 sc_misc_temp_t; +/* + * This type is used report the boot type. + */ +typedef u8 sc_misc_bt_t; #endif /* SC_MISC_API_H */ diff --git a/include/firmware/imx/sci/svc/pm/api.h b/include/firmware/imx/sci/svc/pm/api.h index 9008b85c6f6..d1b085d7f87 100644 --- a/include/firmware/imx/sci/svc/pm/api.h +++ b/include/firmware/imx/sci/svc/pm/api.h @@ -6,6 +6,14 @@ #ifndef SC_PM_API_H #define SC_PM_API_H +#include <firmware/imx/sci/types.h> +/* Defines for type widths */ +#define SC_PM_POWER_MODE_W 2U /* Width of sc_pm_power_mode_t */ +#define SC_PM_CLOCK_MODE_W 3U /* Width of sc_pm_clock_mode_t */ +#define SC_PM_RESET_TYPE_W 2U /* Width of sc_pm_reset_type_t */ +#define SC_PM_RESET_REASON_W 4U /* Width of sc_pm_reset_reason_t */ +/* Defines for ALL parameters */ +#define SC_PM_CLK_ALL ((sc_pm_clk_t)UINT8_MAX) /* All clocks */ /* Defines for sc_pm_power_mode_t */ #define SC_PM_PW_MODE_OFF 0U /* Power off */ #define SC_PM_PW_MODE_STBY 1U /* Power in standby */ @@ -35,10 +43,96 @@ #define SC_PM_CLK_MODE_AUTOGATE_HW 4U /* Clock is in HW autogate mode */ #define SC_PM_CLK_MODE_AUTOGATE_SW_HW 5U /* Clock is in SW-HW autogate mode */ +/* Defines for sc_pm_clk_parent_t */ +#define SC_PM_PARENT_XTAL 0U /*!< Parent is XTAL. */ +#define SC_PM_PARENT_PLL0 1U /*!< Parent is PLL0 */ +#define SC_PM_PARENT_PLL1 2U /*!< Parent is PLL1 or PLL0/2 */ +#define SC_PM_PARENT_PLL2 3U /*!< Parent in PLL2 or PLL0/4 */ +#define SC_PM_PARENT_BYPS 4U /*!< Parent is a bypass clock. */ + +/* Defines for sc_pm_reset_type_t */ +#define SC_PM_RESET_TYPE_COLD 0U /* Cold reset */ +#define SC_PM_RESET_TYPE_WARM 1U /* Warm reset */ +#define SC_PM_RESET_TYPE_BOARD 2U /* Board reset */ + +/* Defines for sc_pm_reset_reason_t */ +#define SC_PM_RESET_REASON_POR 0U /* Power on reset */ +#define SC_PM_RESET_REASON_JTAG 1U /* JTAG reset */ +#define SC_PM_RESET_REASON_SW 2U /* Software reset */ +#define SC_PM_RESET_REASON_WDOG 3U /* Partition watchdog reset */ +#define SC_PM_RESET_REASON_LOCKUP 4U /* SCU lockup reset */ +#define SC_PM_RESET_REASON_SNVS 5U /* SNVS reset */ +#define SC_PM_RESET_REASON_TEMP 6U /* Temp panic reset */ +#define SC_PM_RESET_REASON_MSI 7U /* MSI reset */ +#define SC_PM_RESET_REASON_UECC 8U /* ECC reset */ +#define SC_PM_RESET_REASON_SCFW_WDOG 9U /* SCFW watchdog reset */ +#define SC_PM_RESET_REASON_ROM_WDOG 10U /* SCU ROM watchdog reset */ +#define SC_PM_RESET_REASON_SECO 11U /* SECO reset */ +#define SC_PM_RESET_REASON_SCFW_FAULT 12U /* SCFW fault reset */ + +/* Defines for sc_pm_sys_if_t */ +#define SC_PM_SYS_IF_INTERCONNECT 0U /* System interconnect */ +#define SC_PM_SYS_IF_MU 1U /* AP -> SCU message units */ +#define SC_PM_SYS_IF_OCMEM 2U /* On-chip memory (ROM/OCRAM) */ +#define SC_PM_SYS_IF_DDR 3U /* DDR memory */ + +/* Defines for sc_pm_wake_src_t */ +/* No wake source, used for self-kill */ +#define SC_PM_WAKE_SRC_NONE 0U +/* Wakeup from SCU to resume CPU (IRQSTEER & GIC powered down) */ +#define SC_PM_WAKE_SRC_SCU 1U +/* Wakeup from IRQSTEER to resume CPU (GIC powered down) */ +#define SC_PM_WAKE_SRC_IRQSTEER 2U +/* Wakeup from IRQSTEER+GIC to wake CPU (GIC clock gated) */ +#define SC_PM_WAKE_SRC_IRQSTEER_GIC 3U +/* Wakeup from GIC to wake CPU */ +#define SC_PM_WAKE_SRC_GIC 4U +/* Types */ + +/* + * This type is used to declare a power mode. Note resources only use + * SC_PM_PW_MODE_OFF and SC_PM_PW_MODE_ON. The other modes are used only + * as system power modes. + */ typedef u8 sc_pm_power_mode_t; + +/* + * This type is used to declare a clock. + */ typedef u8 sc_pm_clk_t; + +/* + * This type is used to declare a clock mode. + */ typedef u8 sc_pm_clk_mode_t; + +/* + * This type is used to declare the clock parent. + */ typedef u8 sc_pm_clk_parent_t; + +/* + * This type is used to declare clock rates. + */ typedef u32 sc_pm_clock_rate_t; +/* + * This type is used to declare a desired reset type. + */ +typedef u8 sc_pm_reset_type_t; + +/* + * This type is used to declare a reason for a reset. + */ +typedef u8 sc_pm_reset_reason_t; + +/* + * This type is used to specify a system-level interface to be power managed. + */ +typedef u8 sc_pm_sys_if_t; + +/* + * This type is used to specify a wake source for CPU resources. + */ +typedef u8 sc_pm_wake_src_t; #endif /* SC_PM_API_H */ diff --git a/include/firmware/imx/sci/svc/rm/api.h b/include/firmware/imx/sci/svc/rm/api.h index 163d81403c5..f4e9abcd9b3 100644 --- a/include/firmware/imx/sci/svc/rm/api.h +++ b/include/firmware/imx/sci/svc/rm/api.h @@ -38,32 +38,36 @@ /* Types */ -/*! +/* * This type is used to declare a resource partition. */ typedef u8 sc_rm_pt_t; -/*! +/* * This type is used to declare a memory region. */ typedef u8 sc_rm_mr_t; -/*! +/* * This type is used to declare a resource domain ID used by the * isolation HW. */ typedef u8 sc_rm_did_t; -/*! +/* * This type is used to declare an SMMU StreamID. */ typedef u16 sc_rm_sid_t; -/*! +/* * This type is a used to declare master transaction attributes. */ typedef u8 sc_rm_spa_t; +/* + * This type is used to declare a resource/memory region access permission. + * Refer to the XRDC2 Block Guide for more information. + */ typedef u8 sc_rm_perm_t; #endif /* SC_RM_API_H */ diff --git a/include/firmware/imx/sci/svc/seco/api.h b/include/firmware/imx/sci/svc/seco/api.h index 6e9c302315b..7d4b6b92e17 100644 --- a/include/firmware/imx/sci/svc/seco/api.h +++ b/include/firmware/imx/sci/svc/seco/api.h @@ -17,6 +17,7 @@ #define SC_SECO_AUTH_SECO_FW 3U /* SECO Firmware */ #define SC_SECO_AUTH_HDMI_TX_FW 4U /* HDMI TX Firmware */ #define SC_SECO_AUTH_HDMI_RX_FW 5U /* HDMI RX Firmware */ +#define SC_SECO_EVERIFY_IMAGE 6U /* Enhanced verify image */ #define SC_SECO_RNG_STAT_UNAVAILABLE 0U /* Unable to initialize the RNG */ #define SC_SECO_RNG_STAT_INPROGRESS 1U /* Initialization is on-going */ @@ -24,12 +25,12 @@ /* Types */ -/*! +/* * This type is used to issue SECO authenticate commands. */ typedef u8 sc_seco_auth_cmd_t; -/*! +/* * This type is used to return the RNG initialization status. */ typedef u32 sc_seco_rng_stat_t; diff --git a/include/firmware/imx/sci/svc/timer/api.h b/include/firmware/imx/sci/svc/timer/api.h new file mode 100644 index 00000000000..c2fe34aa751 --- /dev/null +++ b/include/firmware/imx/sci/svc/timer/api.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2018-2019 NXP + */ + +#ifndef SC_TIMER_API_H +#define SC_TIMER_API_H + +/* Defines */ + +/* Defines for type widths */ +#define SC_TIMER_ACTION_W 3U /* Width of sc_timer_wdog_action_t */ + +/* Defines for sc_timer_wdog_action_t */ +#define SC_TIMER_WDOG_ACTION_PARTITION 0U /* Reset partition */ +#define SC_TIMER_WDOG_ACTION_WARM 1U /* Warm reset system */ +#define SC_TIMER_WDOG_ACTION_COLD 2U /* Cold reset system */ +#define SC_TIMER_WDOG_ACTION_BOARD 3U /* Reset board */ +#define SC_TIMER_WDOG_ACTION_IRQ 4U /* Only generate IRQs */ + +/* Types */ + +/* + * This type is used to configure the watchdog action. + */ +typedef u8 sc_timer_wdog_action_t; + +/* + * This type is used to declare a watchdog time value in milliseconds. + */ +typedef u32 sc_timer_wdog_time_t; + +#endif /* SC_TIMER_API_H */ diff --git a/include/fs.h b/include/fs.h index 8370d88cb20..e341a0ed01b 100644 --- a/include/fs.h +++ b/include/fs.h @@ -300,4 +300,42 @@ int do_fs_type(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); */ int do_fs_types(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]); +/** + * fs_read_alloc() - Allocate space for a file and read it + * + * You must call fs_set_blk_dev() or a similar function before calling this, + * since that sets up the block device to use. + * + * The file is terminated with a nul character + * + * @fname: Filename to read + * @size: Size of file to read (must be correct!) + * @align: Alignment to use for memory allocation (0 for default) + * @bufp: On success, returns the allocated buffer with the nul-terminated file + * in it + * Return: 0 if OK, -ENOMEM if out of memory, -EIO if read failed + */ +int fs_read_alloc(const char *fname, ulong size, uint align, void **bufp); + +/** + * fs_load_alloc() - Load a file into allocated space + * + * The file is terminated with a nul character + * + * @ifname: Interface name to read from (e.g. "mmc") + * @dev_part_str: Device and partition string (e.g. "1:2") + * @fname: Filename to read + * @max_size: Maximum allowed size for the file (use 0 for 1GB) + * @align: Alignment to use for memory allocation (0 for default) + * @bufp: On success, returns the allocated buffer with the nul-terminated file + * in it + * @sizep: On success, returns the size of the file + * Return: 0 if OK, -ENOMEM if out of memory, -ENOENT if the file does not + * exist, -ENOMEDIUM if the device does not exist, -E2BIG if the file is too + * large (greater than @max_size), -EIO if read failed + */ +int fs_load_alloc(const char *ifname, const char *dev_part_str, + const char *fname, ulong max_size, ulong align, void **bufp, + ulong *sizep); + #endif /* _FS_H */ diff --git a/include/fsl_sec.h b/include/fsl_sec.h index d8861d1d0b7..9dad1d1ec47 100644 --- a/include/fsl_sec.h +++ b/include/fsl_sec.h @@ -13,8 +13,8 @@ #include <asm/io.h> #ifdef CONFIG_SYS_FSL_SEC_LE -#define sec_in32(a) in_le32((ulong *)(ulong)a) -#define sec_out32(a, v) out_le32((ulong *)(ulong)a, v) +#define sec_in32(a) in_le32((ulong *)(ulong)(a)) +#define sec_out32(a, v) out_le32((ulong *)(ulong)(a), v) #define sec_in16(a) in_le16(a) #define sec_clrbits32 clrbits_le32 #define sec_setbits32 setbits_le32 diff --git a/include/imx_sip.h b/include/imx_sip.h index ebbb3a16d7e..8a5ca34f393 100644 --- a/include/imx_sip.h +++ b/include/imx_sip.h @@ -13,8 +13,8 @@ #define IMX_SIP_BUILDINFO_GET_COMMITHASH 0x00 #define IMX_SIP_SRC 0xC2000005 -#define IMX_SIP_SRC_M4_START 0x00 -#define IMX_SIP_SRC_M4_STARTED 0x01 -#define IMX_SIP_SRC_M4_STOP 0x02 +#define IMX_SIP_SRC_MCU_START 0x00 +#define IMX_SIP_SRC_MCU_STARTED 0x01 +#define IMX_SIP_SRC_MCU_STOP 0x02 #endif diff --git a/include/log.h b/include/log.h index 3bab40b6171..6e84f080ef3 100644 --- a/include/log.h +++ b/include/log.h @@ -102,6 +102,8 @@ enum log_category_t { LOGC_EVENT, /** @LOGC_FS: Related to filesystems */ LOGC_FS, + /** @LOGC_EXPO: Related to expo handling */ + LOGC_EXPO, /** @LOGC_COUNT: Number of log categories */ LOGC_COUNT, /** @LOGC_END: Sentinel value for lists of log categories */ diff --git a/include/of_live.h b/include/of_live.h index f59d6af3350..05e86ac06b1 100644 --- a/include/of_live.h +++ b/include/of_live.h @@ -36,4 +36,14 @@ int of_live_build(const void *fdt_blob, struct device_node **rootp); */ int unflatten_device_tree(const void *blob, struct device_node **mynodes); +/** + * of_live_free() - Dispose of a livetree + * + * This frees memory used by the tree, after which @root becomes invalid and + * cannot be used + * + * @root: Tree to dispose + */ +void of_live_free(struct device_node *root); + #endif diff --git a/include/test/cedit-test.h b/include/test/cedit-test.h new file mode 100644 index 00000000000..349df75b16d --- /dev/null +++ b/include/test/cedit-test.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Binding shared between cedit.dtsi and test/boot/expo.c + * + * Copyright 2023 Google LLC + * Written by Simon Glass <sjg@chromium.org> + */ + +#ifndef __cedit_test_h +#define __cedit_test_h + +#define ID_PROMPT 1 +#define ID_SCENE1 2 +#define ID_SCENE1_TITLE 3 + +#define ID_CPU_SPEED 4 +#define ID_CPU_SPEED_TITLE 5 +#define ID_CPU_SPEED_1 6 +#define ID_CPU_SPEED_2 7 +#define ID_CPU_SPEED_3 8 + +#define ID_POWER_LOSS 9 +#define ID_AC_OFF 10 +#define ID_AC_ON 11 +#define ID_AC_MEMORY 12 + +#define ID_DYNAMIC_START 13 + +#endif diff --git a/include/test/ut.h b/include/test/ut.h index dddf9ad241f..ea6ee95d734 100644 --- a/include/test/ut.h +++ b/include/test/ut.h @@ -130,7 +130,7 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes); \ if (!(cond)) { \ ut_fail(uts, __FILE__, __LINE__, __func__, #cond); \ - __ret = CMD_RET_FAILURE; \ + return CMD_RET_FAILURE; \ } \ __ret; \ }) @@ -142,7 +142,7 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes); if (!(cond)) { \ ut_failf(uts, __FILE__, __LINE__, __func__, #cond, \ fmt, ##args); \ - __ret = CMD_RET_FAILURE; \ + return CMD_RET_FAILURE; \ } \ __ret; \ }) @@ -157,7 +157,7 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes); #expr1 " == " #expr2, \ "Expected %#x (%d), got %#x (%d)", \ _val1, _val1, _val2, _val2); \ - __ret = CMD_RET_FAILURE; \ + return CMD_RET_FAILURE; \ } \ __ret; \ }) @@ -175,7 +175,7 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes); (unsigned long long)_val1, \ (unsigned long long)_val2, \ (unsigned long long)_val2); \ - __ret = CMD_RET_FAILURE; \ + return CMD_RET_FAILURE; \ } \ __ret; \ }) @@ -189,7 +189,7 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes); ut_failf(uts, __FILE__, __LINE__, __func__, \ #expr1 " = " #expr2, \ "Expected \"%s\", got \"%s\"", _val1, _val2); \ - __ret = CMD_RET_FAILURE; \ + return CMD_RET_FAILURE; \ } \ __ret; \ }) @@ -208,7 +208,7 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes); #expr1 " = " #expr2, \ "Expected \"%.*s\", got \"%.*s\"", \ _len, _val1, _len, _val2); \ - __ret = CMD_RET_FAILURE; \ + return CMD_RET_FAILURE; \ } \ __ret; \ }) @@ -228,7 +228,7 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes); #expr1 " = " #expr2, \ "Expected \"%s\", got \"%s\"", \ __buf1, __buf2); \ - __ret = CMD_RET_FAILURE; \ + return CMD_RET_FAILURE; \ } \ __ret; \ }) @@ -242,7 +242,7 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes); ut_failf(uts, __FILE__, __LINE__, __func__, \ #expr1 " = " #expr2, \ "Expected %p, got %p", _val1, _val2); \ - __ret = CMD_RET_FAILURE; \ + return CMD_RET_FAILURE; \ } \ __ret; \ }) @@ -257,7 +257,7 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes); ut_failf(uts, __FILE__, __LINE__, __func__, \ #expr1 " = " #expr2, \ "Expected %lx, got %lx", _val1, _val2); \ - __ret = CMD_RET_FAILURE; \ + return CMD_RET_FAILURE; \ } \ __ret; \ }) @@ -271,7 +271,7 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes); ut_failf(uts, __FILE__, __LINE__, __func__, \ #expr " != NULL", \ "Expected NULL, got %p", _val); \ - __ret = CMD_RET_FAILURE; \ + return CMD_RET_FAILURE; \ } \ __ret; \ }) @@ -285,7 +285,7 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes); ut_failf(uts, __FILE__, __LINE__, __func__, \ #expr " = NULL", \ "Expected non-null, got NULL"); \ - __ret = CMD_RET_FAILURE; \ + return CMD_RET_FAILURE; \ } \ __ret; \ }) @@ -300,7 +300,7 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes); #expr " = NULL", \ "Expected pointer, got error %ld", \ PTR_ERR(_val)); \ - __ret = CMD_RET_FAILURE; \ + return CMD_RET_FAILURE; \ } \ __ret; \ }) @@ -316,7 +316,7 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes); ut_failf(uts, __FILE__, __LINE__, __func__, \ "console", "\nExpected '%s',\n got '%s'", \ uts->expect_str, uts->actual_str); \ - __ret = CMD_RET_FAILURE; \ + return CMD_RET_FAILURE; \ } \ __ret; \ }) @@ -329,7 +329,7 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes); ut_failf(uts, __FILE__, __LINE__, __func__, \ "console", "\nExpected '%s',\n got '%s'", \ uts->expect_str, uts->actual_str); \ - __ret = CMD_RET_FAILURE; \ + return CMD_RET_FAILURE; \ } \ __ret; \ }) @@ -341,7 +341,7 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes); if (ut_check_skipline(uts)) { \ ut_failf(uts, __FILE__, __LINE__, __func__, \ "console", "\nExpected a line, got end"); \ - __ret = CMD_RET_FAILURE; \ + return CMD_RET_FAILURE; \ } \ __ret; \ }) @@ -354,7 +354,7 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes); ut_failf(uts, __FILE__, __LINE__, __func__, \ "console", "\nExpected '%s',\n got to '%s'", \ uts->expect_str, uts->actual_str); \ - __ret = CMD_RET_FAILURE; \ + return CMD_RET_FAILURE; \ } \ __ret; \ }) @@ -367,7 +367,7 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes); ut_failf(uts, __FILE__, __LINE__, __func__, \ "console", "Expected no more output, got '%s'",\ uts->actual_str); \ - __ret = CMD_RET_FAILURE; \ + return CMD_RET_FAILURE; \ } \ __ret; \ }) @@ -381,7 +381,7 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes); "console", \ "Expected dump of length %x bytes, got '%s'", \ total_bytes, uts->actual_str); \ - __ret = CMD_RET_FAILURE; \ + return CMD_RET_FAILURE; \ } \ __ret; \ }) diff --git a/include/video.h b/include/video.h index 03434a81234..e98d0f9c895 100644 --- a/include/video.h +++ b/include/video.h @@ -163,11 +163,11 @@ enum colour_idx { * The caller has to guarantee that the color index is less than * VID_COLOR_COUNT. * - * @priv private data of the console device - * @idx color index + * @priv private data of the video device (UCLASS_VIDEO) + * @idx color index (e.g. VID_YELLOW) * Return: color value */ -u32 video_index_to_colour(struct video_priv *priv, unsigned int idx); +u32 video_index_to_colour(struct video_priv *priv, enum colour_idx idx); /** * video_reserve() - Reserve frame-buffer memory for video devices @@ -205,6 +205,22 @@ int video_clear(struct udevice *dev); int video_fill(struct udevice *dev, u32 colour); /** + * video_fill_part() - Erase a region + * + * Erase a rectangle of the display within the given bounds. + * + * @dev: Device to update + * @xstart: X start position in pixels from the left + * @ystart: Y start position in pixels from the top + * @xend: X end position in pixels from the left + * @yend: Y end position in pixels from the top + * @colour: Value to write + * Return: 0 if OK, -ENOSYS if the display depth is not supported + */ +int video_fill_part(struct udevice *dev, int xstart, int ystart, int xend, + int yend, u32 colour); + +/** * video_sync() - Sync a device's frame buffer with its hardware * * @vid: Device to sync diff --git a/include/video_console.h b/include/video_console.h index 3db9a7e1fb9..2694e44f6ec 100644 --- a/include/video_console.h +++ b/include/video_console.h @@ -72,6 +72,38 @@ struct vidfont_info { }; /** + * struct vidconsole_colour - Holds colour information + * + * @colour_fg: Foreground colour (pixel value) + * @colour_bg: Background colour (pixel value) + */ +struct vidconsole_colour { + u32 colour_fg; + u32 colour_bg; +}; + +/** + * struct vidconsole_bbox - Bounding box of text + * + * This describes the bounding box of something, measured in pixels. The x0/y0 + * pair is inclusive; the x1/y2 pair is exclusive, meaning that it is one pixel + * beyond the extent of the object + * + * @valid: Values are valid (bounding box is known) + * @x0: left x position, in pixels from left side + * @y0: top y position, in pixels from top + * @x1: right x position + 1 + * @y1: botton y position + 1 + */ +struct vidconsole_bbox { + bool valid; + int x0; + int y0; + int x1; + int y1; +}; + +/** * struct vidconsole_ops - Video console operations * * These operations work on either an absolute console position (measured @@ -178,6 +210,20 @@ struct vidconsole_ops { * Returns: 0 on success, -ENOENT if no such font */ int (*select_font)(struct udevice *dev, const char *name, uint size); + + /** + * measure() - Measure the bounds of some text + * + * @dev: Device to adjust + * @name: Font name to use (NULL to use default) + * @size: Font size to use (0 to use default) + * @text: Text to measure + * @bbox: Returns bounding box of text, assuming it is positioned + * at 0,0 + * Returns: 0 on success, -ENOENT if no such font + */ + int (*measure)(struct udevice *dev, const char *name, uint size, + const char *text, struct vidconsole_bbox *bbox); }; /* Get a pointer to the driver operations for a video console device */ @@ -204,6 +250,38 @@ int vidconsole_get_font(struct udevice *dev, int seq, */ int vidconsole_select_font(struct udevice *dev, const char *name, uint size); +/* + * vidconsole_measure() - Measuring the bounding box of some text + * + * @dev: Console device to use + * @name: Font name, NULL for default + * @size: Font size, ignored if @name is NULL + * @text: Text to measure + * @bbox: Returns nounding box of text + * Returns: 0 if OK, -ve on error + */ +int vidconsole_measure(struct udevice *dev, const char *name, uint size, + const char *text, struct vidconsole_bbox *bbox); + +/** + * vidconsole_push_colour() - Temporarily change the font colour + * + * @dev: Device to adjust + * @fg: Foreground colour to select + * @bg: Background colour to select + * @old: Place to store the current colour, so it can be restored + */ +void vidconsole_push_colour(struct udevice *dev, enum colour_idx fg, + enum colour_idx bg, struct vidconsole_colour *old); + +/** + * vidconsole_pop_colour() - Restore the original colour + * + * @dev: Device to adjust + * @old: Old colour to be restored + */ +void vidconsole_pop_colour(struct udevice *dev, struct vidconsole_colour *old); + /** * vidconsole_putc_xy() - write a single character to a position * diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c index 7ac5f89f76d..a40762c74c8 100644 --- a/lib/efi_loader/efi_bootmgr.c +++ b/lib/efi_loader/efi_bootmgr.c @@ -344,3 +344,388 @@ efi_status_t efi_bootmgr_load(efi_handle_t *handle, void **load_options) error: return ret; } + +/** + * efi_bootmgr_enumerate_boot_option() - enumerate the possible bootable media + * + * @opt: pointer to the media boot option structure + * @volume_handles: pointer to the efi handles + * @count: number of efi handle + * Return: status code + */ +static efi_status_t efi_bootmgr_enumerate_boot_option(struct eficonfig_media_boot_option *opt, + efi_handle_t *volume_handles, + efi_status_t count) +{ + u32 i; + struct efi_handler *handler; + efi_status_t ret = EFI_SUCCESS; + + for (i = 0; i < count; i++) { + u16 *p; + u16 dev_name[BOOTMENU_DEVICE_NAME_MAX]; + char *optional_data; + struct efi_load_option lo; + char buf[BOOTMENU_DEVICE_NAME_MAX]; + struct efi_device_path *device_path; + struct efi_device_path *short_dp; + + ret = efi_search_protocol(volume_handles[i], &efi_guid_device_path, &handler); + if (ret != EFI_SUCCESS) + continue; + ret = efi_protocol_open(handler, (void **)&device_path, + efi_root, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (ret != EFI_SUCCESS) + continue; + + ret = efi_disk_get_device_name(volume_handles[i], buf, BOOTMENU_DEVICE_NAME_MAX); + if (ret != EFI_SUCCESS) + continue; + + p = dev_name; + utf8_utf16_strncpy(&p, buf, strlen(buf)); + + /* prefer to short form device path */ + short_dp = efi_dp_shorten(device_path); + if (short_dp) + device_path = short_dp; + + lo.label = dev_name; + lo.attributes = LOAD_OPTION_ACTIVE; + lo.file_path = device_path; + lo.file_path_length = efi_dp_size(device_path) + sizeof(END); + /* + * Set the dedicated guid to optional_data, it is used to identify + * the boot option that automatically generated by the bootmenu. + * efi_serialize_load_option() expects optional_data is null-terminated + * utf8 string, so set the "1234567" string to allocate enough space + * to store guid, instead of realloc the load_option. + */ + lo.optional_data = "1234567"; + opt[i].size = efi_serialize_load_option(&lo, (u8 **)&opt[i].lo); + if (!opt[i].size) { + ret = EFI_OUT_OF_RESOURCES; + goto out; + } + /* set the guid */ + optional_data = (char *)opt[i].lo + (opt[i].size - u16_strsize(u"1234567")); + memcpy(optional_data, &efi_guid_bootmenu_auto_generated, sizeof(efi_guid_t)); + } + +out: + return ret; +} + +/** + * efi_bootmgr_delete_invalid_boot_option() - delete non-existing boot option + * + * @opt: pointer to the media boot option structure + * @count: number of media boot option structure + * Return: status code + */ +static efi_status_t efi_bootmgr_delete_invalid_boot_option(struct eficonfig_media_boot_option *opt, + efi_status_t count) +{ + efi_uintn_t size; + void *load_option; + u32 i, list_size = 0; + struct efi_load_option lo; + u16 *var_name16 = NULL; + u16 varname[] = u"Boot####"; + efi_status_t ret = EFI_SUCCESS; + u16 *delete_index_list = NULL, *p; + efi_uintn_t buf_size; + + buf_size = 128; + var_name16 = malloc(buf_size); + if (!var_name16) + return EFI_OUT_OF_RESOURCES; + + var_name16[0] = 0; + for (;;) { + int index; + efi_guid_t guid; + efi_uintn_t tmp; + + ret = efi_next_variable_name(&buf_size, &var_name16, &guid); + if (ret == EFI_NOT_FOUND) { + /* + * EFI_NOT_FOUND indicates we retrieved all EFI variables. + * This should be treated as success. + */ + ret = EFI_SUCCESS; + break; + } + + if (ret != EFI_SUCCESS) + goto out; + + if (!efi_varname_is_load_option(var_name16, &index)) + continue; + + efi_create_indexed_name(varname, sizeof(varname), "Boot", index); + load_option = efi_get_var(varname, &efi_global_variable_guid, &size); + if (!load_option) + continue; + + tmp = size; + ret = efi_deserialize_load_option(&lo, load_option, &size); + if (ret != EFI_SUCCESS) + goto next; + + if (size >= sizeof(efi_guid_bootmenu_auto_generated) && + !guidcmp(lo.optional_data, &efi_guid_bootmenu_auto_generated)) { + for (i = 0; i < count; i++) { + if (opt[i].size == tmp && + memcmp(opt[i].lo, load_option, tmp) == 0) { + opt[i].exist = true; + break; + } + } + + /* + * The entire list of variables must be retrieved by + * efi_get_next_variable_name_int() before deleting the invalid + * boot option, just save the index here. + */ + if (i == count) { + p = realloc(delete_index_list, sizeof(u32) * + (list_size + 1)); + if (!p) { + ret = EFI_OUT_OF_RESOURCES; + goto out; + } + delete_index_list = p; + delete_index_list[list_size++] = index; + } + } +next: + free(load_option); + } + + /* delete all invalid boot options */ + for (i = 0; i < list_size; i++) { + ret = efi_bootmgr_delete_boot_option(delete_index_list[i]); + if (ret != EFI_SUCCESS) + goto out; + } + +out: + free(var_name16); + free(delete_index_list); + + return ret; +} + +/** + * efi_bootmgr_get_unused_bootoption() - get unused "Boot####" index + * + * @buf: pointer to the buffer to store boot option variable name + * @buf_size: buffer size + * @index: pointer to store the index in the BootOrder variable + * Return: status code + */ +efi_status_t efi_bootmgr_get_unused_bootoption(u16 *buf, efi_uintn_t buf_size, + unsigned int *index) +{ + u32 i; + efi_status_t ret; + efi_uintn_t size; + + if (buf_size < u16_strsize(u"Boot####")) + return EFI_BUFFER_TOO_SMALL; + + for (i = 0; i <= 0xFFFF; i++) { + size = 0; + efi_create_indexed_name(buf, buf_size, "Boot", i); + ret = efi_get_variable_int(buf, &efi_global_variable_guid, + NULL, &size, NULL, NULL); + if (ret == EFI_BUFFER_TOO_SMALL) + continue; + else + break; + } + + if (i > 0xFFFF) + return EFI_OUT_OF_RESOURCES; + + *index = i; + + return EFI_SUCCESS; +} + +/** + * efi_bootmgr_append_bootorder() - append new boot option in BootOrder variable + * + * @index: "Boot####" index to append to BootOrder variable + * Return: status code + */ +efi_status_t efi_bootmgr_append_bootorder(u16 index) +{ + u16 *bootorder; + efi_status_t ret; + u16 *new_bootorder = NULL; + efi_uintn_t last, size, new_size; + + /* append new boot option */ + bootorder = efi_get_var(u"BootOrder", &efi_global_variable_guid, &size); + last = size / sizeof(u16); + new_size = size + sizeof(u16); + new_bootorder = calloc(1, new_size); + if (!new_bootorder) { + ret = EFI_OUT_OF_RESOURCES; + goto out; + } + memcpy(new_bootorder, bootorder, size); + new_bootorder[last] = index; + + ret = efi_set_variable_int(u"BootOrder", &efi_global_variable_guid, + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS, + new_size, new_bootorder, false); + if (ret != EFI_SUCCESS) + goto out; + +out: + free(bootorder); + free(new_bootorder); + + return ret; +} + +/** + * efi_bootmgr_delete_boot_option() - delete selected boot option + * + * @boot_index: boot option index to delete + * Return: status code + */ +efi_status_t efi_bootmgr_delete_boot_option(u16 boot_index) +{ + u16 *bootorder; + u16 varname[9]; + efi_status_t ret; + unsigned int index; + efi_uintn_t num, size; + + efi_create_indexed_name(varname, sizeof(varname), + "Boot", boot_index); + ret = efi_set_variable_int(varname, &efi_global_variable_guid, + 0, 0, NULL, false); + if (ret != EFI_SUCCESS) { + log_err("delete boot option(%ls) failed\n", varname); + return ret; + } + + /* update BootOrder if necessary */ + bootorder = efi_get_var(u"BootOrder", &efi_global_variable_guid, &size); + if (!bootorder) + return EFI_SUCCESS; + + num = size / sizeof(u16); + if (!efi_search_bootorder(bootorder, num, boot_index, &index)) + return EFI_SUCCESS; + + memmove(&bootorder[index], &bootorder[index + 1], + (num - index - 1) * sizeof(u16)); + size -= sizeof(u16); + ret = efi_set_variable_int(u"BootOrder", &efi_global_variable_guid, + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS, + size, bootorder, false); + + return ret; +} + +/** + * efi_bootmgr_update_media_device_boot_option() - generate the media device boot option + * + * This function enumerates all devices supporting EFI_SIMPLE_FILE_SYSTEM_PROTOCOL + * and generate the bootmenu entries. + * This function also provide the BOOT#### variable maintenance for + * the media device entries. + * - Automatically create the BOOT#### variable for the newly detected device, + * this BOOT#### variable is distinguished by the special GUID + * stored in the EFI_LOAD_OPTION.optional_data + * - If the device is not attached to the system, the associated BOOT#### variable + * is automatically deleted. + * + * Return: status code + */ +efi_status_t efi_bootmgr_update_media_device_boot_option(void) +{ + u32 i; + efi_status_t ret; + efi_uintn_t count; + efi_handle_t *volume_handles = NULL; + struct eficonfig_media_boot_option *opt = NULL; + + ret = efi_locate_handle_buffer_int(BY_PROTOCOL, + &efi_simple_file_system_protocol_guid, + NULL, &count, + (efi_handle_t **)&volume_handles); + if (ret != EFI_SUCCESS) + goto out; + + opt = calloc(count, sizeof(struct eficonfig_media_boot_option)); + if (!opt) { + ret = EFI_OUT_OF_RESOURCES; + goto out; + } + + /* enumerate all devices supporting EFI_SIMPLE_FILE_SYSTEM_PROTOCOL */ + ret = efi_bootmgr_enumerate_boot_option(opt, volume_handles, count); + if (ret != EFI_SUCCESS) + goto out; + + /* + * System hardware configuration may vary depending on the user setup. + * The boot option is automatically added by the bootmenu. + * If the device is not attached to the system, the boot option needs + * to be deleted. + */ + ret = efi_bootmgr_delete_invalid_boot_option(opt, count); + if (ret != EFI_SUCCESS) + goto out; + + /* add non-existent boot option */ + for (i = 0; i < count; i++) { + u32 boot_index; + u16 var_name[9]; + + if (!opt[i].exist) { + ret = efi_bootmgr_get_unused_bootoption(var_name, sizeof(var_name), + &boot_index); + if (ret != EFI_SUCCESS) + goto out; + + ret = efi_set_variable_int(var_name, &efi_global_variable_guid, + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS, + opt[i].size, opt[i].lo, false); + if (ret != EFI_SUCCESS) + goto out; + + ret = efi_bootmgr_append_bootorder(boot_index); + if (ret != EFI_SUCCESS) { + efi_set_variable_int(var_name, &efi_global_variable_guid, + 0, 0, NULL, false); + goto out; + } + } + } + +out: + if (opt) { + for (i = 0; i < count; i++) + free(opt[i].lo); + } + free(opt); + efi_free_pool(volume_handles); + + if (ret == EFI_NOT_FOUND) + return EFI_SUCCESS; + return ret; +} diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index d5065f296ae..2ca7359f3e1 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -97,6 +97,12 @@ static efi_status_t EFIAPI efi_disconnect_controller( efi_handle_t driver_image_handle, efi_handle_t child_handle); +static +efi_status_t EFIAPI efi_connect_controller(efi_handle_t controller_handle, + efi_handle_t *driver_image_handle, + struct efi_device_path *remain_device_path, + bool recursive); + /* Called on every callback entry */ int __efi_entry_check(void) { @@ -1298,7 +1304,7 @@ static efi_status_t efi_disconnect_all_drivers const efi_guid_t *protocol, efi_handle_t child_handle) { - efi_uintn_t number_of_drivers; + efi_uintn_t number_of_drivers, tmp; efi_handle_t *driver_handle_buffer; efi_status_t r, ret; @@ -1308,15 +1314,30 @@ static efi_status_t efi_disconnect_all_drivers return ret; if (!number_of_drivers) return EFI_SUCCESS; - ret = EFI_NOT_FOUND; + + tmp = number_of_drivers; while (number_of_drivers) { - r = EFI_CALL(efi_disconnect_controller( + ret = EFI_CALL(efi_disconnect_controller( handle, driver_handle_buffer[--number_of_drivers], child_handle)); - if (r == EFI_SUCCESS) - ret = r; + if (ret != EFI_SUCCESS) + goto reconnect; } + + free(driver_handle_buffer); + return ret; + +reconnect: + /* Reconnect all disconnected drivers */ + for (; number_of_drivers < tmp; number_of_drivers++) { + r = EFI_CALL(efi_connect_controller(handle, + &driver_handle_buffer[number_of_drivers], + NULL, true)); + if (r != EFI_SUCCESS) + EFI_PRINT("Failed to reconnect controller\n"); + } + free(driver_handle_buffer); return ret; } @@ -1352,18 +1373,26 @@ static efi_status_t efi_uninstall_protocol r = efi_search_protocol(handle, protocol, &handler); if (r != EFI_SUCCESS) goto out; + if (handler->protocol_interface != protocol_interface) + return EFI_NOT_FOUND; /* Disconnect controllers */ - efi_disconnect_all_drivers(efiobj, protocol, NULL); + r = efi_disconnect_all_drivers(efiobj, protocol, NULL); + if (r != EFI_SUCCESS) { + r = EFI_ACCESS_DENIED; + goto out; + } /* Close protocol */ list_for_each_entry_safe(item, pos, &handler->open_infos, link) { if (item->info.attributes == EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL || item->info.attributes == EFI_OPEN_PROTOCOL_GET_PROTOCOL || item->info.attributes == EFI_OPEN_PROTOCOL_TEST_PROTOCOL) - list_del(&item->link); + efi_delete_open_info(item); } + /* if agents didn't close the protocols properly */ if (!list_empty(&handler->open_infos)) { r = EFI_ACCESS_DENIED; + EFI_CALL(efi_connect_controller(handle, NULL, NULL, true)); goto out; } r = efi_remove_protocol(handle, protocol, protocol_interface); diff --git a/lib/efi_loader/efi_helper.c b/lib/efi_loader/efi_helper.c index 1f4ab2b419a..cdfd16ea774 100644 --- a/lib/efi_loader/efi_helper.c +++ b/lib/efi_loader/efi_helper.c @@ -257,3 +257,28 @@ efi_status_t efi_next_variable_name(efi_uintn_t *size, u16 **buf, efi_guid_t *gu return ret; } + +/** + * efi_search_bootorder() - search the boot option index in BootOrder + * + * @bootorder: pointer to the BootOrder variable + * @num: number of BootOrder entry + * @target: target boot option index to search + * @index: pointer to store the index of BootOrder variable + * Return: true if exists, false otherwise + */ +bool efi_search_bootorder(u16 *bootorder, efi_uintn_t num, u32 target, u32 *index) +{ + u32 i; + + for (i = 0; i < num; i++) { + if (target == bootorder[i]) { + if (index) + *index = i; + + return true; + } + } + + return false; +} diff --git a/lib/efi_selftest/efi_selftest_controllers.c b/lib/efi_selftest/efi_selftest_controllers.c index 63e674bedc0..02f19574f83 100644 --- a/lib/efi_selftest/efi_selftest_controllers.c +++ b/lib/efi_selftest/efi_selftest_controllers.c @@ -28,6 +28,7 @@ static efi_guid_t guid_child_controller = static efi_handle_t handle_controller; static efi_handle_t handle_child_controller[NUMBER_OF_CHILD_CONTROLLERS]; static efi_handle_t handle_driver; +static bool allow_removal; /* * Count child controllers @@ -85,8 +86,8 @@ static efi_status_t EFIAPI supported( controller_handle, EFI_OPEN_PROTOCOL_BY_DRIVER); switch (ret) { case EFI_ACCESS_DENIED: - case EFI_ALREADY_STARTED: return ret; + case EFI_ALREADY_STARTED: case EFI_SUCCESS: break; default: @@ -124,8 +125,8 @@ static efi_status_t EFIAPI start( controller_handle, EFI_OPEN_PROTOCOL_BY_DRIVER); switch (ret) { case EFI_ACCESS_DENIED: - case EFI_ALREADY_STARTED: return ret; + case EFI_ALREADY_STARTED: case EFI_SUCCESS: break; default: @@ -238,6 +239,9 @@ static efi_status_t EFIAPI stop( if (ret != EFI_SUCCESS) efi_st_error("Cannot free buffer\n"); + if (!allow_removal) + return EFI_DEVICE_ERROR; + /* Detach driver from controller */ ret = boottime->close_protocol( controller_handle, &guid_controller, @@ -342,6 +346,7 @@ static int execute(void) return EFI_ST_FAILURE; } /* Destroy remaining child controllers and disconnect controller */ + allow_removal = true; ret = boottime->disconnect_controller(handle_controller, NULL, NULL); if (ret != EFI_SUCCESS) { efi_st_error("Failed to disconnect controller\n"); @@ -393,7 +398,40 @@ static int execute(void) efi_st_error("Number of children %u != %u\n", (unsigned int)count, NUMBER_OF_CHILD_CONTROLLERS); } - /* Uninstall controller protocol */ + + allow_removal = false; + /* Try to uninstall controller protocol using the wrong interface */ + ret = boottime->uninstall_protocol_interface(handle_controller, + &guid_controller, + &interface1); + if (ret != EFI_NOT_FOUND) { + efi_st_error("Interface not checked when uninstalling protocol\n"); + return EFI_ST_FAILURE; + } + + /* + * Uninstall a protocol while Disconnect controller won't + * allow it. + */ + ret = boottime->uninstall_protocol_interface(handle_controller, + &guid_controller, + &interface2); + if (ret != EFI_ACCESS_DENIED) { + efi_st_error("Uninstall protocol interface failed\n"); + return EFI_ST_FAILURE; + } + /* + * Check number of child controllers and make sure children have + * been reconnected + */ + ret = count_child_controllers(handle_controller, &guid_controller, + &count); + if (ret != EFI_SUCCESS || count != NUMBER_OF_CHILD_CONTROLLERS) { + efi_st_error("Number of children %u != %u\n", + (unsigned int)count, NUMBER_OF_CHILD_CONTROLLERS); + } + + allow_removal = true; ret = boottime->uninstall_protocol_interface(handle_controller, &guid_controller, &interface2); diff --git a/lib/lzma/LzmaDec.c b/lib/lzma/LzmaDec.c index 341149f766b..a90b35c6a99 100644 --- a/lib/lzma/LzmaDec.c +++ b/lib/lzma/LzmaDec.c @@ -152,8 +152,7 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte const Byte *buf = p->buf; UInt32 range = p->range; UInt32 code = p->code; - - schedule(); + unsigned int loop = 0; do { @@ -162,6 +161,9 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte unsigned ttt; unsigned posState = processedPos & pbMask; + if (!(loop++ & 1023)) + schedule(); + prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; IF_BIT_0(prob) { @@ -177,8 +179,6 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte state -= (state < 4) ? state : 3; symbol = 1; - schedule(); - do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100); } else @@ -188,8 +188,6 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte state -= (state < 10) ? 3 : 6; symbol = 1; - schedule(); - do { unsigned bit; @@ -321,8 +319,6 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte UInt32 mask = 1; unsigned i = 1; - schedule(); - do { GET_BIT2(prob + i, i, ; , distance |= mask); @@ -335,8 +331,6 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte { numDirectBits -= kNumAlignBits; - schedule(); - do { NORMALIZE @@ -409,8 +403,6 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte const Byte *lim = dest + curLen; dicPos += curLen; - schedule(); - do *(dest) = (Byte)*(dest + src); while (++dest != lim); @@ -418,8 +410,6 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte else { - schedule(); - do { dic[dicPos++] = dic[pos]; diff --git a/lib/of_live.c b/lib/of_live.c index 1b5964d09a9..25f7af61061 100644 --- a/lib/of_live.c +++ b/lib/of_live.c @@ -287,9 +287,12 @@ int unflatten_device_tree(const void *blob, struct device_node **mynodes) debug(" size is %lx, allocating...\n", size); /* Allocate memory for the expanded device tree */ - mem = malloc(size + 4); + mem = memalign(__alignof__(struct device_node), size + 4); memset(mem, '\0', size); + /* Set up value for dm_test_livetree_align() */ + *(u32 *)mem = BAD_OF_ROOT; + *(__be32 *)(mem + size) = cpu_to_be32(0xdeadbeef); debug(" unflattening %p...\n", mem); @@ -327,3 +330,9 @@ int of_live_build(const void *fdt_blob, struct device_node **rootp) return ret; } + +void of_live_free(struct device_node *root) +{ + /* the tree is stored as a contiguous block of memory */ + free(root); +} diff --git a/lib/zlib/inflate.c b/lib/zlib/inflate.c index 30dfe155995..8f767b7b9d2 100644 --- a/lib/zlib/inflate.c +++ b/lib/zlib/inflate.c @@ -455,8 +455,9 @@ int ZEXPORT inflate(z_streamp strm, int flush) if (copy > have) copy = have; if (copy) { if (state->head != Z_NULL && - state->head->extra != Z_NULL) { - len = state->head->extra_len - state->length; + state->head->extra != Z_NULL && + (len = state->head->extra_len - state->length) < + state->head->extra_max) { zmemcpy(state->head->extra + len, next, len + copy > state->head->extra_max ? state->head->extra_max - len : copy); diff --git a/test/boot/expo.c b/test/boot/expo.c index 7104dff05e8..3898f853a75 100644 --- a/test/boot/expo.c +++ b/test/boot/expo.c @@ -5,6 +5,7 @@ */ #include <common.h> +#include <command.h> #include <dm.h> #include <expo.h> #include <menu.h> @@ -13,6 +14,7 @@ #include <test/suites.h> #include <test/ut.h> #include "bootstd_common.h" +#include <test/cedit-test.h> #include "../../boot/scene_internal.h" enum { @@ -28,6 +30,8 @@ enum { OBJ_MENU_TITLE, /* strings */ + STR_SCENE_TITLE, + STR_TEXT, STR_TEXT2, STR_MENU_TITLE, @@ -120,7 +124,7 @@ static int expo_scene(struct unit_test_state *uts) struct expo *exp; ulong start_mem; char name[100]; - int id; + int id, title_id; start_mem = ut_check_free(); @@ -141,21 +145,20 @@ static int expo_scene(struct unit_test_state *uts) ut_asserteq_str(SCENE_NAME1, scn->name); /* Set the title */ - strcpy(name, SCENE_TITLE); - ut_assertok(scene_title_set(scn, name)); - *name = '\0'; - ut_assertnonnull(scn->title); - ut_asserteq_str(SCENE_TITLE, scn->title); + title_id = expo_str(exp, "title", STR_SCENE_TITLE, SCENE_TITLE); + ut_assert(title_id >= 0); - /* Use an allocated ID */ + /* Use an allocated ID - this will be allocated after the title str */ scn = NULL; id = scene_new(exp, SCENE_NAME2, 0, &scn); ut_assertnonnull(scn); - ut_asserteq(SCENE2, id); - ut_asserteq(SCENE2 + 1, exp->next_id); + ut_assertok(scene_title_set(scn, title_id)); + ut_asserteq(STR_SCENE_TITLE + 1, id); + ut_asserteq(STR_SCENE_TITLE + 2, exp->next_id); ut_asserteq_ptr(exp, scn->expo); ut_asserteq_str(SCENE_NAME2, scn->name); + ut_asserteq(title_id, scn->title_id); expo_destroy(exp); @@ -225,7 +228,7 @@ static int expo_object(struct unit_test_state *uts) } BOOTSTD_TEST(expo_object, UT_TESTF_DM | UT_TESTF_SCAN_FDT); -/* Check setting object attributes */ +/* Check setting object attributes and using themes */ static int expo_object_attr(struct unit_test_state *uts) { struct scene_obj_menu *menu; @@ -235,6 +238,7 @@ static int expo_object_attr(struct unit_test_state *uts) struct expo *exp; ulong start_mem; char name[100]; + ofnode node; char *data; int id; @@ -249,8 +253,8 @@ static int expo_object_attr(struct unit_test_state *uts) ut_assert(id > 0); ut_assertok(scene_obj_set_pos(scn, OBJ_LOGO, 123, 456)); - ut_asserteq(123, img->obj.x); - ut_asserteq(456, img->obj.y); + ut_asserteq(123, img->obj.dim.x); + ut_asserteq(456, img->obj.dim.y); ut_asserteq(-ENOENT, scene_obj_set_pos(scn, OBJ_TEXT2, 0, 0)); @@ -272,6 +276,11 @@ static int expo_object_attr(struct unit_test_state *uts) ut_asserteq(-ENOENT, scene_menu_set_title(scn, OBJ_TEXT2, OBJ_TEXT)); ut_asserteq(-EINVAL, scene_menu_set_title(scn, OBJ_MENU, OBJ_TEXT2)); + node = ofnode_path("/bootstd/theme"); + ut_assert(ofnode_valid(node)); + ut_assertok(expo_apply_theme(exp, node)); + ut_asserteq(30, txt->font_size); + expo_destroy(exp); ut_assertok(ut_check_delta(start_mem)); @@ -306,8 +315,8 @@ static int expo_object_menu(struct unit_test_state *uts) ut_asserteq(0, menu->pointer_id); ut_assertok(scene_obj_set_pos(scn, OBJ_MENU, 50, 400)); - ut_asserteq(50, menu->obj.x); - ut_asserteq(400, menu->obj.y); + ut_asserteq(50, menu->obj.dim.x); + ut_asserteq(400, menu->obj.dim.y); id = scene_txt_str(scn, "title", OBJ_MENU_TITLE, STR_MENU_TITLE, "Main Menu", &tit); @@ -347,29 +356,31 @@ static int expo_object_menu(struct unit_test_state *uts) ut_asserteq(desc_id, item->desc_id); ut_asserteq(preview_id, item->preview_id); - /* adding an item should cause the first item to become current */ + ut_assertok(scene_arrange(scn)); + + /* arranging the scene should cause the first item to become current */ ut_asserteq(id, menu->cur_item_id); /* the title should be at the top */ - ut_asserteq(menu->obj.x, tit->obj.x); - ut_asserteq(menu->obj.y, tit->obj.y); + ut_asserteq(menu->obj.dim.x, tit->obj.dim.x); + ut_asserteq(menu->obj.dim.y, tit->obj.dim.y); /* the first item should be next */ - ut_asserteq(menu->obj.x, name1->obj.x); - ut_asserteq(menu->obj.y + 32, name1->obj.y); + ut_asserteq(menu->obj.dim.x, name1->obj.dim.x); + ut_asserteq(menu->obj.dim.y + 32, name1->obj.dim.y); - ut_asserteq(menu->obj.x + 230, key1->obj.x); - ut_asserteq(menu->obj.y + 32, key1->obj.y); + ut_asserteq(menu->obj.dim.x + 230, key1->obj.dim.x); + ut_asserteq(menu->obj.dim.y + 32, key1->obj.dim.y); - ut_asserteq(menu->obj.x + 200, ptr->obj.x); - ut_asserteq(menu->obj.y + 32, ptr->obj.y); + ut_asserteq(menu->obj.dim.x + 200, ptr->obj.dim.x); + ut_asserteq(menu->obj.dim.y + 32, ptr->obj.dim.y); - ut_asserteq(menu->obj.x + 280, desc1->obj.x); - ut_asserteq(menu->obj.y + 32, desc1->obj.y); + ut_asserteq(menu->obj.dim.x + 280, desc1->obj.dim.x); + ut_asserteq(menu->obj.dim.y + 32, desc1->obj.dim.y); - ut_asserteq(-4, prev1->obj.x); - ut_asserteq(menu->obj.y + 32, prev1->obj.y); - ut_asserteq(false, prev1->obj.hide); + ut_asserteq(-4, prev1->obj.dim.x); + ut_asserteq(menu->obj.dim.y + 32, prev1->obj.dim.y); + ut_asserteq(true, prev1->obj.flags & SCENEOF_HIDE); expo_destroy(exp); @@ -470,6 +481,48 @@ static int expo_render_image(struct unit_test_state *uts) /* render without a scene */ ut_asserteq(-ECHILD, expo_render(exp)); + ut_assertok(expo_calc_dims(exp)); + ut_assertok(scene_arrange(scn)); + + /* check dimensions of text */ + obj = scene_obj_find(scn, OBJ_TEXT, SCENEOBJT_NONE); + ut_assertnonnull(obj); + ut_asserteq(400, obj->dim.x); + ut_asserteq(100, obj->dim.y); + ut_asserteq(126, obj->dim.w); + ut_asserteq(40, obj->dim.h); + + /* check dimensions of image */ + obj = scene_obj_find(scn, OBJ_LOGO, SCENEOBJT_NONE); + ut_assertnonnull(obj); + ut_asserteq(50, obj->dim.x); + ut_asserteq(20, obj->dim.y); + ut_asserteq(160, obj->dim.w); + ut_asserteq(160, obj->dim.h); + + /* check dimensions of menu labels - both should be the same width */ + obj = scene_obj_find(scn, ITEM1_LABEL, SCENEOBJT_NONE); + ut_assertnonnull(obj); + ut_asserteq(50, obj->dim.x); + ut_asserteq(436, obj->dim.y); + ut_asserteq(29, obj->dim.w); + ut_asserteq(18, obj->dim.h); + + obj = scene_obj_find(scn, ITEM2_LABEL, SCENEOBJT_NONE); + ut_assertnonnull(obj); + ut_asserteq(50, obj->dim.x); + ut_asserteq(454, obj->dim.y); + ut_asserteq(29, obj->dim.w); + ut_asserteq(18, obj->dim.h); + + /* check dimensions of menu */ + obj = scene_obj_find(scn, OBJ_MENU, SCENEOBJT_NONE); + ut_assertnonnull(obj); + ut_asserteq(50, obj->dim.x); + ut_asserteq(400, obj->dim.y); + ut_asserteq(160, obj->dim.w); + ut_asserteq(160, obj->dim.h); + /* render it */ expo_set_scene_id(exp, SCENE1); ut_assertok(expo_render(exp)); @@ -479,16 +532,16 @@ static int expo_render_image(struct unit_test_state *uts) ut_assertok(expo_action_get(exp, &act)); - ut_asserteq(EXPOACT_POINT, act.type); + ut_asserteq(EXPOACT_POINT_ITEM, act.type); ut_asserteq(ITEM2, act.select.id); ut_assertok(expo_render(exp)); /* make sure only the preview for the second item is shown */ obj = scene_obj_find(scn, ITEM1_PREVIEW, SCENEOBJT_NONE); - ut_asserteq(true, obj->hide); + ut_asserteq(true, obj->flags & SCENEOF_HIDE); obj = scene_obj_find(scn, ITEM2_PREVIEW, SCENEOBJT_NONE); - ut_asserteq(false, obj->hide); + ut_asserteq(false, obj->flags & SCENEOF_HIDE); /* select it */ ut_assertok(expo_send_key(exp, BKEY_SELECT)); @@ -504,7 +557,7 @@ static int expo_render_image(struct unit_test_state *uts) ut_assert_console_end(); /* now try in text mode */ - exp_set_text_mode(exp, true); + expo_set_text_mode(exp, true); ut_assertok(expo_render(exp)); ut_assert_nextline("U-Boot : Boot Menu"); @@ -519,7 +572,7 @@ static int expo_render_image(struct unit_test_state *uts) ut_assertok(expo_action_get(exp, &act)); - ut_asserteq(EXPOACT_POINT, act.type); + ut_asserteq(EXPOACT_POINT_ITEM, act.type); ut_asserteq(ITEM1, act.select.id); ut_assertok(expo_render(exp)); @@ -537,3 +590,125 @@ static int expo_render_image(struct unit_test_state *uts) return 0; } BOOTSTD_TEST(expo_render_image, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check building an expo from a devicetree description */ +static int expo_test_build(struct unit_test_state *uts) +{ + struct scene_obj_menu *menu; + struct scene_menitem *item; + struct scene_obj_txt *txt; + struct scene_obj *obj; + struct scene *scn; + struct expo *exp; + int count; + ofnode node; + + node = ofnode_path("/cedit"); + ut_assert(ofnode_valid(node)); + ut_assertok(expo_build(node, &exp)); + + ut_asserteq_str("name", exp->name); + ut_asserteq(0, exp->scene_id); + ut_asserteq(ID_DYNAMIC_START + 20, exp->next_id); + ut_asserteq(false, exp->popup); + + /* check the scene */ + scn = expo_lookup_scene_id(exp, ID_SCENE1); + ut_assertnonnull(scn); + ut_asserteq_str("main", scn->name); + ut_asserteq(ID_SCENE1, scn->id); + ut_asserteq(ID_DYNAMIC_START + 1, scn->title_id); + ut_asserteq(0, scn->highlight_id); + + /* check the title */ + txt = scene_obj_find(scn, scn->title_id, SCENEOBJT_NONE); + ut_assertnonnull(txt); + obj = &txt->obj; + ut_asserteq_ptr(scn, obj->scene); + ut_asserteq_str("title", obj->name); + ut_asserteq(scn->title_id, obj->id); + ut_asserteq(SCENEOBJT_TEXT, obj->type); + ut_asserteq(0, obj->flags); + ut_asserteq_str("Test Configuration", expo_get_str(exp, txt->str_id)); + + /* check the menu */ + menu = scene_obj_find(scn, ID_CPU_SPEED, SCENEOBJT_NONE); + obj = &menu->obj; + ut_asserteq_ptr(scn, obj->scene); + ut_asserteq_str("cpu-speed", obj->name); + ut_asserteq(ID_CPU_SPEED, obj->id); + ut_asserteq(SCENEOBJT_MENU, obj->type); + ut_asserteq(0, obj->flags); + + txt = scene_obj_find(scn, menu->title_id, SCENEOBJT_NONE); + ut_asserteq_str("CPU speed", expo_get_str(exp, txt->str_id)); + + ut_asserteq(0, menu->cur_item_id); + ut_asserteq(0, menu->pointer_id); + + /* check the items */ + item = list_first_entry(&menu->item_head, struct scene_menitem, + sibling); + ut_asserteq_str("00", item->name); + ut_asserteq(ID_CPU_SPEED_1, item->id); + ut_asserteq(0, item->key_id); + ut_asserteq(0, item->desc_id); + ut_asserteq(0, item->preview_id); + ut_asserteq(0, item->flags); + + txt = scene_obj_find(scn, item->label_id, SCENEOBJT_NONE); + ut_asserteq_str("2 GHz", expo_get_str(exp, txt->str_id)); + + count = 0; + list_for_each_entry(item, &menu->item_head, sibling) + count++; + ut_asserteq(3, count); + + expo_destroy(exp); + + return 0; +} +BOOTSTD_TEST(expo_test_build, UT_TESTF_DM); + +/* Check the cedit command */ +static int expo_cedit(struct unit_test_state *uts) +{ + extern struct expo *cur_exp; + struct scene_obj_menu *menu; + struct scene_obj_txt *txt; + struct expo *exp; + struct scene *scn; + + if (!IS_ENABLED(CONFIG_CMD_CEDIT)) + return -EAGAIN; + + ut_assertok(run_command("cedit load hostfs - cedit.dtb", 0)); + + console_record_reset_enable(); + + /* + * ^N Move down to second menu + * ^M Open menu + * ^N Move down to second item + * ^M Select item + * \e Quit + */ + console_in_puts("\x0e\x0d\x0e\x0d\e"); + ut_assertok(run_command("cedit run", 0)); + + exp = cur_exp; + scn = expo_lookup_scene_id(exp, exp->scene_id); + ut_assertnonnull(scn); + + menu = scene_obj_find(scn, scn->highlight_id, SCENEOBJT_NONE); + ut_assertnonnull(menu); + + txt = scene_obj_find(scn, menu->title_id, SCENEOBJT_NONE); + ut_assertnonnull(txt); + ut_asserteq_str("AC Power", expo_get_str(exp, txt->str_id)); + + ut_asserteq(ID_AC_ON, menu->cur_item_id); + + return 0; +} +BOOTSTD_TEST(expo_cedit, UT_TESTF_DM | UT_TESTF_SCAN_FDT); diff --git a/test/boot/files/expo_layout.dts b/test/boot/files/expo_layout.dts new file mode 100644 index 00000000000..55d5c910dd5 --- /dev/null +++ b/test/boot/files/expo_layout.dts @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Sample expo screen layout + */ + +/dts-v1/; + +/* +enum { + ZERO, + ID_PROMPT, + + ID_SCENE1, + ID_SCENE1_TITLE, + + ID_CPU_SPEED, + ID_CPU_SPEED_TITLE, + ID_CPU_SPEED_1, + ID_CPU_SPEED_2, + ID_CPU_SPEED_3, + + ID_POWER_LOSS, + ID_AC_OFF, + ID_AC_ON, + ID_AC_MEMORY, + + ID_DYNAMIC_START, +}; +*/ + +/ { + dynamic-start = <ID_DYNAMIC_START>; + + scenes { + main { + id = <ID_SCENE1>; + + /* value refers to the matching id in /strings */ + title-id = <ID_SCENE1_TITLE>; + + /* simple string is used as it is */ + prompt = "UP and DOWN to choose, ENTER to select"; + + /* defines a menu within the scene */ + cpu-speed { + type = "menu"; + id = <ID_CPU_SPEED>; + + /* + * has both string and ID. The string is ignored + * if the ID is present and points to a string + */ + title = "CPU speed"; + title-id = <ID_CPU_SPEED_TITLE>; + + /* menu items as simple strings */ + item-label = "2 GHz", "2.5 GHz", "3 GHz"; + + /* IDs for the menu items */ + item-id = <ID_CPU_SPEED_1 ID_CPU_SPEED_2 + ID_CPU_SPEED_3>; + }; + + power-loss { + type = "menu"; + id = <ID_POWER_LOSS>; + + title = "AC Power"; + item-label = "Always Off", "Always On", + "Memory"; + + item-id = <ID_AC_OFF ID_AC_ON ID_AC_MEMORY>; + }; + }; + }; + + strings { + title { + id = <ID_SCENE1_TITLE>; + value = "Test Configuration"; + value-es = "configuración de prueba"; + }; + }; +}; diff --git a/test/cmd/bdinfo.c b/test/cmd/bdinfo.c index 9068df79c4f..cddf1a46d49 100644 --- a/test/cmd/bdinfo.c +++ b/test/cmd/bdinfo.c @@ -27,19 +27,25 @@ DECLARE_GLOBAL_DATA_PTR; /* Declare a new bdinfo test */ #define BDINFO_TEST(_name, _flags) UNIT_TEST(_name, _flags, bdinfo_test) -static void bdinfo_test_num_l(struct unit_test_state *uts, - const char *name, ulong value) +static int test_num_l(struct unit_test_state *uts, const char *name, + ulong value) { - ut_assert_nextline("%-12s= 0x%0*lx", name, 2 * (int)sizeof(value), value); + ut_assert_nextline("%-12s= 0x%0*lx", name, 2 * (int)sizeof(value), + value); + + return 0; } -static void bdinfo_test_num_ll(struct unit_test_state *uts, - const char *name, unsigned long long value) +static int test_num_ll(struct unit_test_state *uts, const char *name, + unsigned long long value) { - ut_assert_nextline("%-12s= 0x%.*llx", name, 2 * (int)sizeof(ulong), value); + ut_assert_nextline("%-12s= 0x%.*llx", name, 2 * (int)sizeof(ulong), + value); + + return 0; } -static void test_eth(struct unit_test_state *uts) +static int test_eth(struct unit_test_state *uts) { const int idx = eth_get_dev_index(); uchar enetaddr[6]; @@ -59,9 +65,11 @@ static void test_eth(struct unit_test_state *uts) else ut_assert_nextline("%-12s= %pM", name, enetaddr); ut_assert_nextline("IP addr = %s", env_get("ipaddr")); + + return 0; } -static void test_video_info(struct unit_test_state *uts) +static int test_video_info(struct unit_test_state *uts) { const struct udevice *dev; struct uclass *uc; @@ -73,22 +81,25 @@ static void test_video_info(struct unit_test_state *uts) struct video_priv *upriv = dev_get_uclass_priv(dev); struct video_uc_plat *plat = dev_get_uclass_plat(dev); - bdinfo_test_num_ll(uts, "FB base", (ulong)upriv->fb); + ut_assertok(test_num_ll(uts, "FB base", + (ulong)upriv->fb)); if (upriv->copy_fb) { - bdinfo_test_num_ll(uts, "FB copy", - (ulong)upriv->copy_fb); - bdinfo_test_num_l(uts, " copy size", - plat->copy_size); + ut_assertok(test_num_ll(uts, "FB copy", + (ulong)upriv->copy_fb)); + ut_assertok(test_num_l(uts, " copy size", + plat->copy_size)); } ut_assert_nextline("%-12s= %dx%dx%d", "FB size", upriv->xsize, upriv->ysize, 1 << upriv->bpix); } } + + return 0; } -static void lmb_test_dump_region(struct unit_test_state *uts, - struct lmb_region *rgn, char *name) +static int lmb_test_dump_region(struct unit_test_state *uts, + struct lmb_region *rgn, char *name) { unsigned long long base, size, end; enum lmb_flags flags; @@ -105,13 +116,17 @@ static void lmb_test_dump_region(struct unit_test_state *uts, ut_assert_nextline(" %s[%d]\t[0x%llx-0x%llx], 0x%08llx bytes flags: %x", name, i, base, end, size, flags); } + + return 0; } -static void lmb_test_dump_all(struct unit_test_state *uts, struct lmb *lmb) +static int lmb_test_dump_all(struct unit_test_state *uts, struct lmb *lmb) { ut_assert_nextline("lmb_dump_all:"); lmb_test_dump_region(uts, &lmb->memory, "memory"); lmb_test_dump_region(uts, &lmb->reserved, "reserved"); + + return 0; } static int bdinfo_test_move(struct unit_test_state *uts) @@ -123,44 +138,48 @@ static int bdinfo_test_move(struct unit_test_state *uts) ut_assertok(console_record_reset_enable()); ut_assertok(run_commandf("bdinfo")); - bdinfo_test_num_l(uts, "boot_params", 0); + ut_assertok(test_num_l(uts, "boot_params", 0)); for (i = 0; i < CONFIG_NR_DRAM_BANKS; ++i) { if (bd->bi_dram[i].size) { - bdinfo_test_num_l(uts, "DRAM bank", i); - bdinfo_test_num_ll(uts, "-> start", bd->bi_dram[i].start); - bdinfo_test_num_ll(uts, "-> size", bd->bi_dram[i].size); + ut_assertok(test_num_l(uts, "DRAM bank", i)); + ut_assertok(test_num_ll(uts, "-> start", + bd->bi_dram[i].start)); + ut_assertok(test_num_ll(uts, "-> size", + bd->bi_dram[i].size)); } } /* CONFIG_SYS_HAS_SRAM testing not supported */ - bdinfo_test_num_l(uts, "flashstart", 0); - bdinfo_test_num_l(uts, "flashsize", 0); - bdinfo_test_num_l(uts, "flashoffset", 0); + ut_assertok(test_num_l(uts, "flashstart", 0)); + ut_assertok(test_num_l(uts, "flashsize", 0)); + ut_assertok(test_num_l(uts, "flashoffset", 0)); ut_assert_nextline("baudrate = %lu bps", env_get_ulong("baudrate", 10, 1234)); - bdinfo_test_num_l(uts, "relocaddr", gd->relocaddr); - bdinfo_test_num_l(uts, "reloc off", gd->reloc_off); + ut_assertok(test_num_l(uts, "relocaddr", gd->relocaddr)); + ut_assertok(test_num_l(uts, "reloc off", gd->reloc_off)); ut_assert_nextline("%-12s= %u-bit", "Build", (uint)sizeof(void *) * 8); if (IS_ENABLED(CONFIG_CMD_NET)) - test_eth(uts); + ut_assertok(test_eth(uts)); /* * Make sure environment variable "fdtcontroladdr" address * matches mapped control DT address. */ ut_assert(map_to_sysmem(gd->fdt_blob) == env_get_hex("fdtcontroladdr", 0x1234)); - bdinfo_test_num_l(uts, "fdt_blob", (ulong)map_to_sysmem(gd->fdt_blob)); - bdinfo_test_num_l(uts, "new_fdt", (ulong)map_to_sysmem(gd->new_fdt)); - bdinfo_test_num_l(uts, "fdt_size", (ulong)gd->fdt_size); + ut_assertok(test_num_l(uts, "fdt_blob", + (ulong)map_to_sysmem(gd->fdt_blob))); + ut_assertok(test_num_l(uts, "new_fdt", + (ulong)map_to_sysmem(gd->new_fdt))); + ut_assertok(test_num_l(uts, "fdt_size", (ulong)gd->fdt_size)); if (IS_ENABLED(CONFIG_VIDEO)) test_video_info(uts); /* The gd->multi_dtb_fit may not be available, hence, #if below. */ #if CONFIG_IS_ENABLED(MULTI_DTB_FIT) - bdinfo_test_num_l(uts, "multi_dtb_fit", (ulong)gd->multi_dtb_fit); + ut_assertok(test_num_l(uts, "multi_dtb_fit", (ulong)gd->multi_dtb_fit)); #endif if (IS_ENABLED(CONFIG_LMB) && gd->fdt_blob) { diff --git a/test/dm/ofnode.c b/test/dm/ofnode.c index 473a8cef578..6fbebc7da08 100644 --- a/test/dm/ofnode.c +++ b/test/dm/ofnode.c @@ -1240,3 +1240,48 @@ static int dm_test_ofnode_copy_props_ot(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_ofnode_copy_props_ot, UT_TESTF_SCAN_FDT | UT_TESTF_OTHER_FDT); + +/* check that the livetree is aligned to a structure boundary */ +static int dm_test_livetree_align(struct unit_test_state *uts) +{ + const int align = __alignof__(struct unit_test_state); + struct device_node *node; + u32 *sentinel; + ulong start; + + start = (ulong)gd_of_root(); + ut_asserteq(start, ALIGN(start, align)); + + node = gd_of_root(); + sentinel = (void *)node - sizeof(u32); + + /* + * The sentinel should be overwritten with the root node. If it isn't, + * then the root node is not at the very start of the livetree memory + * area, and free(root) will fail to free the memory used by the + * livetree. + */ + ut_assert(*sentinel != BAD_OF_ROOT); + + return 0; +} +DM_TEST(dm_test_livetree_align, UT_TESTF_LIVE_TREE); + +/* check that it is possible to load an arbitrary livetree */ +static int dm_test_livetree_ensure(struct unit_test_state *uts) +{ + oftree tree; + ofnode node; + + /* read from other.dtb */ + ut_assertok(test_load_other_fdt(uts)); + tree = oftree_from_fdt(uts->other_fdt); + ut_assert(oftree_valid(tree)); + node = oftree_path(tree, "/node/subnode"); + ut_assert(ofnode_valid(node)); + ut_asserteq_str("sandbox-other2", + ofnode_read_string(node, "compatible")); + + return 0; +} +DM_TEST(dm_test_livetree_ensure, 0); diff --git a/test/dm/video.c b/test/dm/video.c index 30778157d94..0534ee93a3d 100644 --- a/test/dm/video.c +++ b/test/dm/video.c @@ -556,7 +556,7 @@ static int dm_test_video_truetype(struct unit_test_state *uts) ut_assertok(video_get_nologo(uts, &dev)); ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con)); vidconsole_put_string(con, test_string); - ut_asserteq(12237, compress_frame_buffer(uts, dev)); + ut_asserteq(12174, compress_frame_buffer(uts, dev)); return 0; } @@ -577,7 +577,7 @@ static int dm_test_video_truetype_scroll(struct unit_test_state *uts) ut_assertok(video_get_nologo(uts, &dev)); ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con)); vidconsole_put_string(con, test_string); - ut_asserteq(35030, compress_frame_buffer(uts, dev)); + ut_asserteq(34287, compress_frame_buffer(uts, dev)); return 0; } @@ -598,7 +598,7 @@ static int dm_test_video_truetype_bs(struct unit_test_state *uts) ut_assertok(video_get_nologo(uts, &dev)); ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con)); vidconsole_put_string(con, test_string); - ut_asserteq(29018, compress_frame_buffer(uts, dev)); + ut_asserteq(29471, compress_frame_buffer(uts, dev)); return 0; } diff --git a/test/py/tests/test_ut.py b/test/py/tests/test_ut.py index 0b45863b438..aa1d477cd56 100644 --- a/test/py/tests/test_ut.py +++ b/test/py/tests/test_ut.py @@ -282,6 +282,15 @@ label Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl) copy_prepared_image(cons, mmc_dev, fname) +def setup_cedit_file(cons): + infname = os.path.join(cons.config.source_dir, + 'test/boot/files/expo_layout.dts') + expo_tool = os.path.join(cons.config.source_dir, 'tools/expo.py') + outfname = 'cedit.dtb' + u_boot_utils.run_and_log( + cons, f'{expo_tool} -e {infname} -l {infname} -o {outfname}') + + @pytest.mark.buildconfigspec('ut_dm') def test_ut_dm_init(u_boot_console): """Initialize data for ut dm tests.""" @@ -319,6 +328,7 @@ def test_ut_dm_init_bootstd(u_boot_console): setup_bootflow_image(u_boot_console) setup_bootmenu_image(u_boot_console) + setup_cedit_file(u_boot_console) # Restart so that the new mmc1.img is picked up u_boot_console.restart_uboot() diff --git a/tools/binman/control.py b/tools/binman/control.py index 68597c4e779..7e2dd3541b9 100644 --- a/tools/binman/control.py +++ b/tools/binman/control.py @@ -9,7 +9,7 @@ from collections import OrderedDict import glob try: import importlib.resources -except ImportError: +except ImportError: # pragma: no cover # for Python 3.6 import importlib_resources import os diff --git a/tools/expo.py b/tools/expo.py new file mode 100755 index 00000000000..c6eb87aec73 --- /dev/null +++ b/tools/expo.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0+ + +""" +Expo utility - used for testing of expo features + +Copyright 2023 Google LLC +Written by Simon Glass <sjg@chromium.org> +""" + +import argparse +import collections +import io +import re +import subprocess +import sys + +#from u_boot_pylib import cros_subprocess +from u_boot_pylib import tools + +# Parse: +# SCENE1 = 7, +# or SCENE2, +RE_ENUM = re.compile(r'(\S*)(\s*= (\d))?,') + +# Parse #define <name> "string" +RE_DEF = re.compile(r'#define (\S*)\s*"(.*)"') + +def calc_ids(fname): + """Figure out the value of the enums in a C file + + Args: + fname (str): Filename to parse + + Returns: + OrderedDict(): + key (str): enum name + value (int or str): + Value of enum, if int + Value of #define, if string + """ + vals = collections.OrderedDict() + with open(fname, 'r', encoding='utf-8') as inf: + in_enum = False + cur_id = 0 + for line in inf.readlines(): + line = line.strip() + if line == 'enum {': + in_enum = True + continue + if in_enum and line == '};': + in_enum = False + + if in_enum: + if not line or line.startswith('/*'): + continue + m_enum = RE_ENUM.match(line) + if m_enum.group(3): + cur_id = int(m_enum.group(3)) + vals[m_enum.group(1)] = cur_id + cur_id += 1 + else: + m_def = RE_DEF.match(line) + if m_def: + vals[m_def.group(1)] = tools.to_bytes(m_def.group(2)) + + return vals + + +def run_expo(args): + """Run the expo program""" + ids = calc_ids(args.enum_fname) + + indata = tools.read_file(args.layout) + + outf = io.BytesIO() + + for name, val in ids.items(): + if isinstance(val, int): + outval = b'%d' % val + else: + outval = b'"%s"' % val + find_str = r'\b%s\b' % name + indata = re.sub(tools.to_bytes(find_str), outval, indata) + + outf.write(indata) + data = outf.getvalue() + + with open('/tmp/asc', 'wb') as outf: + outf.write(data) + proc = subprocess.run('dtc', input=data, capture_output=True, check=True) + edtb = proc.stdout + if proc.stderr: + print(proc.stderr) + return 1 + tools.write_file(args.outfile, edtb) + return 0 + + +def parse_args(argv): + """Parse the command-line arguments + + Args: + argv (list of str): List of string arguments + + Returns: + tuple: (options, args) with the command-line options and arugments. + options provides access to the options (e.g. option.debug) + args is a list of string arguments + """ + parser = argparse.ArgumentParser() + parser.add_argument('-e', '--enum-fname', type=str, + help='C file containing enum declaration for expo items') + parser.add_argument('-l', '--layout', type=str, + help='Devicetree file source .dts for expo layout') + parser.add_argument('-o', '--outfile', type=str, + help='Filename to write expo layout dtb') + + return parser.parse_args(argv) + +def start_expo(): + """Start the expo program""" + args = parse_args(sys.argv[1:]) + + ret_code = run_expo(args) + sys.exit(ret_code) + + +if __name__ == "__main__": + start_expo() |