diff options
367 files changed, 27912 insertions, 973 deletions
diff --git a/.travis.yml b/.travis.yml index b81d733695..00b2a73a5e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,11 +26,9 @@ addons: - grub-efi-ia32-bin - rpm2cpio - wget + - device-tree-compiler install: - # install latest device tree compiler - - git clone --depth=1 git://git.kernel.org/pub/scm/utils/dtc/dtc.git /tmp/dtc - - make -j4 -C /tmp/dtc # Clone uboot-test-hooks - git clone --depth=1 git://github.com/swarren/uboot-test-hooks.git /tmp/uboot-test-hooks - ln -s travis-ci /tmp/uboot-test-hooks/bin/`hostname` @@ -51,7 +49,7 @@ install: env: global: - - PATH=/tmp/dtc:/tmp/qemu-install/bin:/tmp/uboot-test-hooks/bin:/usr/bin:/bin + - PATH=/tmp/qemu-install/bin:/tmp/uboot-test-hooks/bin:/usr/bin:/bin - PYTHONPATH=/tmp/uboot-test-hooks/py/travis-ci - BUILD_DIR=build - HOSTCC="cc" diff --git a/MAINTAINERS b/MAINTAINERS index 0b7b2bbeb2..b167b028ec 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -420,6 +420,7 @@ F: arch/arm/mach-omap2/omap5/sec-fxns.c F: arch/arm/mach-omap2/sec-common.c F: arch/arm/mach-omap2/config_secure.mk F: configs/am335x_hs_evm_defconfig +F: configs/am335x_hs_evm_uart_defconfig F: configs/am43xx_hs_evm_defconfig F: configs/am57xx_hs_evm_defconfig F: configs/dra7xx_hs_evm_defconfig @@ -349,7 +349,7 @@ OBJDUMP = $(CROSS_COMPILE)objdump AWK = awk PERL = perl PYTHON ?= python -DTC ?= dtc +DTC ?= $(objtree)/scripts/dtc/dtc CHECK = sparse CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ \ @@ -872,7 +872,7 @@ endif PHONY += dtbs dtbs: dts/dt.dtb @: -dts/dt.dtb: checkdtc u-boot +dts/dt.dtb: u-boot $(Q)$(MAKE) $(build)=dts dtbs quiet_cmd_copy = COPY $@ @@ -1447,12 +1447,6 @@ SYSTEM_MAP = \ System.map: u-boot @$(call SYSTEM_MAP,$<) > $@ -checkdtc: - @if test $(call dtc-version) -lt 0104; then \ - echo '*** Your dtc is too old, please upgrade to dtc 1.4 or newer'; \ - false; \ - fi - ######################################################################### # ARM relocations should all be R_ARM_RELATIVE (32-bit) or diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index bb64b9c160..fca23b4e64 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -588,6 +588,7 @@ config ARCH_OMAP2PLUS bool "TI OMAP2+" select CPU_V7 select SPL_BOARD_INIT if SPL + select SPL_STACK_R if SPL select SUPPORT_SPL imply FIT diff --git a/arch/arm/cpu/armv8/fsl-layerscape/soc.c b/arch/arm/cpu/armv8/fsl-layerscape/soc.c index 6698c0467d..a90ee0afd7 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/soc.c +++ b/arch/arm/cpu/armv8/fsl-layerscape/soc.c @@ -260,8 +260,8 @@ static void erratum_rcw_src(void) #ifdef CONFIG_SYS_FSL_ERRATUM_A009203 static void erratum_a009203(void) { - u8 __iomem *ptr; #ifdef CONFIG_SYS_I2C + u8 __iomem *ptr; #ifdef I2C1_BASE_ADDR ptr = (u8 __iomem *)(I2C1_BASE_ADDR + I2C_DEBUG_REG); @@ -297,7 +297,9 @@ void bypass_smmu(void) void fsl_lsch3_early_init_f(void) { erratum_rcw_src(); +#ifdef CONFIG_FSL_IFC init_early_memctl_regs(); /* tighten IFC timing */ +#endif #ifdef CONFIG_SYS_FSL_ERRATUM_A009203 erratum_a009203(); #endif @@ -323,11 +325,14 @@ int sata_init(void) { struct ccsr_ahci __iomem *ccsr_ahci; +#ifdef CONFIG_SYS_SATA2 ccsr_ahci = (void *)CONFIG_SYS_SATA2; out_le32(&ccsr_ahci->ppcfg, AHCI_PORT_PHY_1_CFG); out_le32(&ccsr_ahci->ptc, AHCI_PORT_TRANS_CFG); out_le32(&ccsr_ahci->axicc, AHCI_PORT_AXICC_CFG); +#endif +#ifdef CONFIG_SYS_SATA1 ccsr_ahci = (void *)CONFIG_SYS_SATA1; out_le32(&ccsr_ahci->ppcfg, AHCI_PORT_PHY_1_CFG); out_le32(&ccsr_ahci->ptc, AHCI_PORT_TRANS_CFG); @@ -335,6 +340,7 @@ int sata_init(void) ahci_init((void __iomem *)CONFIG_SYS_SATA1); scsi_scan(false); +#endif return 0; } diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index 85ce68789a..7c062f0cad 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -41,6 +41,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \ rk3288-veyron-jerry.dtb \ rk3288-veyron-mickey.dtb \ rk3288-veyron-minnie.dtb \ + rk3288-vyasa.dtb \ rk3328-evb.dtb \ rk3368-lion.dtb \ rk3368-sheep.dtb \ @@ -205,6 +206,8 @@ dtb-$(CONFIG_ARCH_SNAPDRAGON) += dragonboard410c.dtb dtb-$(CONFIG_STM32F7) += stm32f746-disco.dtb \ stm32f769-disco.dtb +dtb-$(CONFIG_STM32H7) += stm32h743i-disco.dtb \ + stm32h743i-eval.dtb dtb-$(CONFIG_MACH_SUN4I) += \ sun4i-a10-a1000.dtb \ diff --git a/arch/arm/dts/am3517-evm-u-boot.dtsi b/arch/arm/dts/am3517-evm-u-boot.dtsi new file mode 100644 index 0000000000..24a67dbd1e --- /dev/null +++ b/arch/arm/dts/am3517-evm-u-boot.dtsi @@ -0,0 +1,12 @@ +/* + * Copyright (C) 2017 + * Logic PD - http://www.logicpd.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/ { + chosen { + stdout-path = &uart3; + }; +}; diff --git a/arch/arm/dts/am3517-evm.dts b/arch/arm/dts/am3517-evm.dts new file mode 100644 index 0000000000..0e4a125f78 --- /dev/null +++ b/arch/arm/dts/am3517-evm.dts @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +/dts-v1/; + +#include "am3517.dtsi" + +/ { + model = "TI AM3517 EVM (AM3517/05 TMDSEVM3517)"; + compatible = "ti,am3517-evm", "ti,am3517", "ti,omap3"; + + memory@80000000 { + device_type = "memory"; + reg = <0x80000000 0x10000000>; /* 256 MB */ + }; + + vmmc_fixed: vmmc { + compatible = "regulator-fixed"; + regulator-name = "vmmc_fixed"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; +}; + +&davinci_emac { + status = "okay"; +}; + +&davinci_mdio { + status = "okay"; +}; + +&i2c1 { + clock-frequency = <400000>; +}; + +&i2c2 { + clock-frequency = <400000>; +}; + +&i2c3 { + clock-frequency = <400000>; +}; + +&mmc1 { + vmmc-supply = <&vmmc_fixed>; + bus-width = <4>; +}; + +&mmc2 { + status = "disabled"; +}; + +&mmc3 { + status = "disabled"; +}; + diff --git a/arch/arm/dts/am3517-u-boot.dtsi b/arch/arm/dts/am3517-u-boot.dtsi new file mode 100644 index 0000000000..219005210d --- /dev/null +++ b/arch/arm/dts/am3517-u-boot.dtsi @@ -0,0 +1,10 @@ +/* + * Copyright (C) 2017 + * Logic PD - http://www.logicpd.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +&uart4 { + reg-shift = <2>; +}; diff --git a/arch/arm/dts/am3517.dtsi b/arch/arm/dts/am3517.dtsi new file mode 100644 index 0000000000..00da3f2c40 --- /dev/null +++ b/arch/arm/dts/am3517.dtsi @@ -0,0 +1,107 @@ +/* + * Device Tree Source for am3517 SoC + * + * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/ + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#include "omap3.dtsi" + +/ { + aliases { + serial3 = &uart4; + can = &hecc; + }; + + ocp@68000000 { + am35x_otg_hs: am35x_otg_hs@5c040000 { + compatible = "ti,omap3-musb"; + ti,hwmods = "am35x_otg_hs"; + status = "disabled"; + reg = <0x5c040000 0x1000>; + interrupts = <71>; + interrupt-names = "mc"; + }; + + davinci_emac: ethernet@0x5c000000 { + compatible = "ti,am3517-emac"; + ti,hwmods = "davinci_emac"; + status = "disabled"; + reg = <0x5c000000 0x30000>; + interrupts = <67 68 69 70>; + syscon = <&scm_conf>; + ti,davinci-ctrl-reg-offset = <0x10000>; + ti,davinci-ctrl-mod-reg-offset = <0>; + ti,davinci-ctrl-ram-offset = <0x20000>; + ti,davinci-ctrl-ram-size = <0x2000>; + ti,davinci-rmii-en = /bits/ 8 <1>; + local-mac-address = [ 00 00 00 00 00 00 ]; + }; + + davinci_mdio: ethernet@0x5c030000 { + compatible = "ti,davinci_mdio"; + ti,hwmods = "davinci_mdio"; + status = "disabled"; + reg = <0x5c030000 0x1000>; + bus_freq = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + + uart4: serial@4809e000 { + compatible = "ti,omap3-uart"; + ti,hwmods = "uart4"; + status = "disabled"; + reg = <0x4809e000 0x400>; + interrupts = <84>; + dmas = <&sdma 55 &sdma 54>; + dma-names = "tx", "rx"; + clock-frequency = <48000000>; + }; + + omap3_pmx_core2: pinmux@480025d8 { + compatible = "ti,omap3-padconf", "pinctrl-single"; + reg = <0x480025d8 0x24>; + #address-cells = <1>; + #size-cells = <0>; + #pinctrl-cells = <1>; + #interrupt-cells = <1>; + interrupt-controller; + pinctrl-single,register-width = <16>; + pinctrl-single,function-mask = <0xff1f>; + }; + + hecc: can@5c050000 { + compatible = "ti,am3517-hecc"; + status = "disabled"; + reg = <0x5c050000 0x80>, + <0x5c053000 0x180>, + <0x5c052000 0x200>; + reg-names = "hecc", "hecc-ram", "mbx"; + interrupts = <24>; + clocks = <&hecc_ck>; + }; + }; +}; + +&iva { + status = "disabled"; +}; + +&mailbox { + status = "disabled"; +}; + +&mmu_isp { + status = "disabled"; +}; + +&smartreflex_mpu_iva { + status = "disabled"; +}; + +/include/ "am35xx-clocks.dtsi" +/include/ "omap36xx-am35xx-omap3430es2plus-clocks.dtsi" diff --git a/arch/arm/dts/am35xx-clocks.dtsi b/arch/arm/dts/am35xx-clocks.dtsi new file mode 100644 index 0000000000..00dd1f091b --- /dev/null +++ b/arch/arm/dts/am35xx-clocks.dtsi @@ -0,0 +1,128 @@ +/* + * Device Tree Source for OMAP3 clock data + * + * Copyright (C) 2013 Texas Instruments, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +&scm_clocks { + emac_ick: emac_ick@32c { + #clock-cells = <0>; + compatible = "ti,am35xx-gate-clock"; + clocks = <&ipss_ick>; + reg = <0x032c>; + ti,bit-shift = <1>; + }; + + emac_fck: emac_fck@32c { + #clock-cells = <0>; + compatible = "ti,gate-clock"; + clocks = <&rmii_ck>; + reg = <0x032c>; + ti,bit-shift = <9>; + }; + + vpfe_ick: vpfe_ick@32c { + #clock-cells = <0>; + compatible = "ti,am35xx-gate-clock"; + clocks = <&ipss_ick>; + reg = <0x032c>; + ti,bit-shift = <2>; + }; + + vpfe_fck: vpfe_fck@32c { + #clock-cells = <0>; + compatible = "ti,gate-clock"; + clocks = <&pclk_ck>; + reg = <0x032c>; + ti,bit-shift = <10>; + }; + + hsotgusb_ick_am35xx: hsotgusb_ick_am35xx@32c { + #clock-cells = <0>; + compatible = "ti,am35xx-gate-clock"; + clocks = <&ipss_ick>; + reg = <0x032c>; + ti,bit-shift = <0>; + }; + + hsotgusb_fck_am35xx: hsotgusb_fck_am35xx@32c { + #clock-cells = <0>; + compatible = "ti,gate-clock"; + clocks = <&sys_ck>; + reg = <0x032c>; + ti,bit-shift = <8>; + }; + + hecc_ck: hecc_ck@32c { + #clock-cells = <0>; + compatible = "ti,am35xx-gate-clock"; + clocks = <&sys_ck>; + reg = <0x032c>; + ti,bit-shift = <3>; + }; +}; +&cm_clocks { + ipss_ick: ipss_ick@a10 { + #clock-cells = <0>; + compatible = "ti,am35xx-interface-clock"; + clocks = <&core_l3_ick>; + reg = <0x0a10>; + ti,bit-shift = <4>; + }; + + rmii_ck: rmii_ck { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <50000000>; + }; + + pclk_ck: pclk_ck { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <27000000>; + }; + + uart4_ick_am35xx: uart4_ick_am35xx@a10 { + #clock-cells = <0>; + compatible = "ti,omap3-interface-clock"; + clocks = <&core_l4_ick>; + reg = <0x0a10>; + ti,bit-shift = <23>; + }; + + uart4_fck_am35xx: uart4_fck_am35xx@a00 { + #clock-cells = <0>; + compatible = "ti,wait-gate-clock"; + clocks = <&core_48m_fck>; + reg = <0x0a00>; + ti,bit-shift = <23>; + }; +}; + +&cm_clockdomains { + core_l3_clkdm: core_l3_clkdm { + compatible = "ti,clockdomain"; + clocks = <&sdrc_ick>, <&ipss_ick>, <&emac_ick>, <&vpfe_ick>, + <&hsotgusb_ick_am35xx>, <&hsotgusb_fck_am35xx>, + <&hecc_ck>; + }; + + core_l4_clkdm: core_l4_clkdm { + compatible = "ti,clockdomain"; + clocks = <&cpefuse_fck>, <&ts_fck>, <&usbtll_fck>, + <&usbtll_ick>, <&mmchs3_ick>, <&mmchs3_fck>, + <&mmchs2_fck>, <&mmchs1_fck>, <&i2c3_fck>, <&i2c2_fck>, + <&i2c1_fck>, <&mcspi4_fck>, <&mcspi3_fck>, + <&mcspi2_fck>, <&mcspi1_fck>, <&uart2_fck>, + <&uart1_fck>, <&hdq_fck>, <&mmchs2_ick>, <&mmchs1_ick>, + <&hdq_ick>, <&mcspi4_ick>, <&mcspi3_ick>, + <&mcspi2_ick>, <&mcspi1_ick>, <&i2c3_ick>, <&i2c2_ick>, + <&i2c1_ick>, <&uart2_ick>, <&uart1_ick>, <&gpt11_ick>, + <&gpt10_ick>, <&mcbsp5_ick>, <&mcbsp1_ick>, + <&omapctrl_ick>, <&aes2_ick>, <&sha12_ick>, + <&uart4_ick_am35xx>, <&uart4_fck_am35xx>; + }; +}; diff --git a/arch/arm/dts/da850-evm-u-boot.dtsi b/arch/arm/dts/da850-evm-u-boot.dtsi new file mode 100644 index 0000000000..5cc5a81f6f --- /dev/null +++ b/arch/arm/dts/da850-evm-u-boot.dtsi @@ -0,0 +1,23 @@ +/* + * da850-evm U-Boot Additions + * + * Copyright (C) 2017 Logic PD, Inc. + * Copyright (C) Adam Ford + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/ { + chosen { + stdout-path = &serial2; + }; + + aliases { + i2c0 = &i2c0; + spi0 = &spi1; + }; +}; + +&flash { + compatible = "m25p64", "spi-flash"; +}; diff --git a/arch/arm/dts/da850-evm.dts b/arch/arm/dts/da850-evm.dts new file mode 100644 index 0000000000..67e72bc72e --- /dev/null +++ b/arch/arm/dts/da850-evm.dts @@ -0,0 +1,304 @@ +/* + * Device Tree for DA850 EVM board + * + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, version 2. + */ +/dts-v1/; +#include "da850.dtsi" +#include <dt-bindings/gpio/gpio.h> + +/ { + compatible = "ti,da850-evm", "ti,da850"; + model = "DA850/AM1808/OMAP-L138 EVM"; + + soc@1c00000 { + pmx_core: pinmux@14120 { + status = "okay"; + + mcasp0_pins: pinmux_mcasp0_pins { + pinctrl-single,bits = < + /* + * AHCLKX, ACLKX, AFSX, AHCLKR, ACLKR, + * AFSR, AMUTE + */ + 0x00 0x11111111 0xffffffff + /* AXR11, AXR12 */ + 0x04 0x00011000 0x000ff000 + >; + }; + nand_pins: nand_pins { + pinctrl-single,bits = < + /* EMA_WAIT[0], EMA_OE, EMA_WE, EMA_CS[4], EMA_CS[3] */ + 0x1c 0x10110110 0xf0ff0ff0 + /* + * EMA_D[0], EMA_D[1], EMA_D[2], + * EMA_D[3], EMA_D[4], EMA_D[5], + * EMA_D[6], EMA_D[7] + */ + 0x24 0x11111111 0xffffffff + /* EMA_A[1], EMA_A[2] */ + 0x30 0x01100000 0x0ff00000 + >; + }; + }; + serial0: serial@42000 { + status = "okay"; + }; + serial1: serial@10c000 { + status = "okay"; + }; + serial2: serial@10d000 { + status = "okay"; + }; + rtc0: rtc@23000 { + status = "okay"; + }; + i2c0: i2c@22000 { + status = "okay"; + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + + tps: tps@48 { + reg = <0x48>; + }; + tlv320aic3106: tlv320aic3106@18 { + #sound-dai-cells = <0>; + compatible = "ti,tlv320aic3106"; + reg = <0x18>; + status = "okay"; + + /* Regulators */ + IOVDD-supply = <&vdcdc2_reg>; + /* Derived from VBAT: Baseboard 3.3V / 1.8V */ + AVDD-supply = <&vbat>; + DRVDD-supply = <&vbat>; + DVDD-supply = <&vbat>; + }; + tca6416: gpio@20 { + compatible = "ti,tca6416"; + reg = <0x20>; + gpio-controller; + #gpio-cells = <2>; + }; + }; + wdt: wdt@21000 { + status = "okay"; + }; + mmc0: mmc@40000 { + max-frequency = <50000000>; + bus-width = <4>; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins>; + }; + spi1: spi@30e000 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&spi1_pins &spi1_cs0_pin>; + flash: m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "m25p64"; + spi-max-frequency = <30000000>; + m25p,fast-read; + reg = <0>; + partition@0 { + label = "U-Boot-SPL"; + reg = <0x00000000 0x00010000>; + read-only; + }; + partition@1 { + label = "U-Boot"; + reg = <0x00010000 0x00080000>; + read-only; + }; + partition@2 { + label = "U-Boot-Env"; + reg = <0x00090000 0x00010000>; + read-only; + }; + partition@3 { + label = "Kernel"; + reg = <0x000a0000 0x00280000>; + }; + partition@4 { + label = "Filesystem"; + reg = <0x00320000 0x00400000>; + }; + partition@5 { + label = "MAC-Address"; + reg = <0x007f0000 0x00010000>; + read-only; + }; + }; + }; + mdio: mdio@224000 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&mdio_pins>; + bus_freq = <2200000>; + }; + eth0: ethernet@220000 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&mii_pins>; + }; + gpio: gpio@226000 { + status = "okay"; + }; + }; + vbat: fixedregulator0 { + compatible = "regulator-fixed"; + regulator-name = "vbat"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-boot-on; + }; + + sound { + compatible = "simple-audio-card"; + simple-audio-card,name = "DA850/OMAP-L138 EVM"; + simple-audio-card,widgets = + "Line", "Line In", + "Line", "Line Out"; + simple-audio-card,routing = + "LINE1L", "Line In", + "LINE1R", "Line In", + "Line Out", "LLOUT", + "Line Out", "RLOUT"; + simple-audio-card,format = "dsp_b"; + simple-audio-card,bitclock-master = <&link0_codec>; + simple-audio-card,frame-master = <&link0_codec>; + simple-audio-card,bitclock-inversion; + + simple-audio-card,cpu { + sound-dai = <&mcasp0>; + system-clock-frequency = <24576000>; + }; + + link0_codec: simple-audio-card,codec { + sound-dai = <&tlv320aic3106>; + system-clock-frequency = <24576000>; + }; + }; +}; + +/include/ "tps6507x.dtsi" + +&tps { + vdcdc1_2-supply = <&vbat>; + vdcdc3-supply = <&vbat>; + vldo1_2-supply = <&vbat>; + + regulators { + vdcdc1_reg: regulator@0 { + regulator-name = "VDCDC1_3.3V"; + regulator-min-microvolt = <3150000>; + regulator-max-microvolt = <3450000>; + regulator-always-on; + regulator-boot-on; + }; + + vdcdc2_reg: regulator@1 { + regulator-name = "VDCDC2_3.3V"; + regulator-min-microvolt = <1710000>; + regulator-max-microvolt = <3450000>; + regulator-always-on; + regulator-boot-on; + ti,defdcdc_default = <1>; + }; + + vdcdc3_reg: regulator@2 { + regulator-name = "VDCDC3_1.2V"; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-boot-on; + ti,defdcdc_default = <1>; + }; + + ldo1_reg: regulator@3 { + regulator-name = "LDO1_1.8V"; + regulator-min-microvolt = <1710000>; + regulator-max-microvolt = <1890000>; + regulator-always-on; + regulator-boot-on; + }; + + ldo2_reg: regulator@4 { + regulator-name = "LDO2_1.2V"; + regulator-min-microvolt = <1140000>; + regulator-max-microvolt = <1320000>; + regulator-always-on; + regulator-boot-on; + }; + }; +}; + +&mcasp0 { + #sound-dai-cells = <0>; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&mcasp0_pins>; + + op-mode = <0>; /* MCASP_IIS_MODE */ + tdm-slots = <2>; + /* 4 serializer */ + serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */ + 0 0 0 0 + 0 0 0 0 + 0 0 0 1 + 2 0 0 0 + >; + tx-num-evt = <32>; + rx-num-evt = <32>; +}; + +&edma0 { + ti,edma-reserved-slot-ranges = <32 50>; +}; + +&edma1 { + ti,edma-reserved-slot-ranges = <32 90>; +}; + +&aemif { + pinctrl-names = "default"; + pinctrl-0 = <&nand_pins>; + status = "ok"; + cs3 { + #address-cells = <2>; + #size-cells = <1>; + clock-ranges; + ranges; + + ti,cs-chipselect = <3>; + + nand@2000000,0 { + compatible = "ti,davinci-nand"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0 0x02000000 0x02000000 + 1 0x00000000 0x00008000>; + + ti,davinci-chipselect = <1>; + ti,davinci-mask-ale = <0>; + ti,davinci-mask-cle = <0>; + ti,davinci-mask-chipsel = <0>; + ti,davinci-ecc-mode = "hw"; + ti,davinci-ecc-bits = <4>; + ti,davinci-nand-use-bbt; + }; + }; +}; + +&vpif { + pinctrl-names = "default"; + pinctrl-0 = <&vpif_capture_pins>, <&vpif_display_pins>; + status = "okay"; +}; diff --git a/arch/arm/dts/da850.dtsi b/arch/arm/dts/da850.dtsi new file mode 100644 index 0000000000..02e2f8f258 --- /dev/null +++ b/arch/arm/dts/da850.dtsi @@ -0,0 +1,581 @@ +/* + * Copyright 2012 DENX Software Engineering GmbH + * Heiko Schocher <hs@denx.de> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include "skeleton.dtsi" +#include <dt-bindings/interrupt-controller/irq.h> + +/ { + arm { + #address-cells = <1>; + #size-cells = <1>; + ranges; + intc: interrupt-controller@fffee000 { + compatible = "ti,cp-intc"; + interrupt-controller; + #interrupt-cells = <1>; + ti,intc-size = <101>; + reg = <0xfffee000 0x2000>; + }; + }; + + aliases { + spi0 = &spi0; + }; + + soc@1c00000 { + compatible = "simple-bus"; + model = "da850"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x01c00000 0x400000>; + interrupt-parent = <&intc>; + + pmx_core: pinmux@14120 { + compatible = "pinctrl-single"; + reg = <0x14120 0x50>; + #address-cells = <1>; + #size-cells = <0>; + #pinctrl-cells = <2>; + pinctrl-single,bit-per-mux; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0xf>; + status = "disabled"; + + serial0_rtscts_pins: pinmux_serial0_rtscts_pins { + pinctrl-single,bits = < + /* UART0_RTS UART0_CTS */ + 0x0c 0x22000000 0xff000000 + >; + }; + serial0_rxtx_pins: pinmux_serial0_rxtx_pins { + pinctrl-single,bits = < + /* UART0_TXD UART0_RXD */ + 0x0c 0x00220000 0x00ff0000 + >; + }; + serial1_rtscts_pins: pinmux_serial1_rtscts_pins { + pinctrl-single,bits = < + /* UART1_CTS UART1_RTS */ + 0x00 0x00440000 0x00ff0000 + >; + }; + serial1_rxtx_pins: pinmux_serial1_rxtx_pins { + pinctrl-single,bits = < + /* UART1_TXD UART1_RXD */ + 0x10 0x22000000 0xff000000 + >; + }; + serial2_rtscts_pins: pinmux_serial2_rtscts_pins { + pinctrl-single,bits = < + /* UART2_CTS UART2_RTS */ + 0x00 0x44000000 0xff000000 + >; + }; + serial2_rxtx_pins: pinmux_serial2_rxtx_pins { + pinctrl-single,bits = < + /* UART2_TXD UART2_RXD */ + 0x10 0x00220000 0x00ff0000 + >; + }; + i2c0_pins: pinmux_i2c0_pins { + pinctrl-single,bits = < + /* I2C0_SDA,I2C0_SCL */ + 0x10 0x00002200 0x0000ff00 + >; + }; + i2c1_pins: pinmux_i2c1_pins { + pinctrl-single,bits = < + /* I2C1_SDA, I2C1_SCL */ + 0x10 0x00440000 0x00ff0000 + >; + }; + mmc0_pins: pinmux_mmc_pins { + pinctrl-single,bits = < + /* MMCSD0_DAT[3] MMCSD0_DAT[2] + * MMCSD0_DAT[1] MMCSD0_DAT[0] + * MMCSD0_CMD MMCSD0_CLK + */ + 0x28 0x00222222 0x00ffffff + >; + }; + ehrpwm0a_pins: pinmux_ehrpwm0a_pins { + pinctrl-single,bits = < + /* EPWM0A */ + 0xc 0x00000002 0x0000000f + >; + }; + ehrpwm0b_pins: pinmux_ehrpwm0b_pins { + pinctrl-single,bits = < + /* EPWM0B */ + 0xc 0x00000020 0x000000f0 + >; + }; + ehrpwm1a_pins: pinmux_ehrpwm1a_pins { + pinctrl-single,bits = < + /* EPWM1A */ + 0x14 0x00000002 0x0000000f + >; + }; + ehrpwm1b_pins: pinmux_ehrpwm1b_pins { + pinctrl-single,bits = < + /* EPWM1B */ + 0x14 0x00000020 0x000000f0 + >; + }; + ecap0_pins: pinmux_ecap0_pins { + pinctrl-single,bits = < + /* ECAP0_APWM0 */ + 0x8 0x20000000 0xf0000000 + >; + }; + ecap1_pins: pinmux_ecap1_pins { + pinctrl-single,bits = < + /* ECAP1_APWM1 */ + 0x4 0x40000000 0xf0000000 + >; + }; + ecap2_pins: pinmux_ecap2_pins { + pinctrl-single,bits = < + /* ECAP2_APWM2 */ + 0x4 0x00000004 0x0000000f + >; + }; + spi0_pins: pinmux_spi0_pins { + pinctrl-single,bits = < + /* SIMO, SOMI, CLK */ + 0xc 0x00001101 0x0000ff0f + >; + }; + spi0_cs0_pin: pinmux_spi0_cs0 { + pinctrl-single,bits = < + /* CS0 */ + 0x10 0x00000010 0x000000f0 + >; + }; + spi0_cs3_pin: pinmux_spi0_cs3_pin { + pinctrl-single,bits = < + /* CS3 */ + 0xc 0x01000000 0x0f000000 + >; + }; + spi1_pins: pinmux_spi1_pins { + pinctrl-single,bits = < + /* SIMO, SOMI, CLK */ + 0x14 0x00110100 0x00ff0f00 + >; + }; + spi1_cs0_pin: pinmux_spi1_cs0 { + pinctrl-single,bits = < + /* CS0 */ + 0x14 0x00000010 0x000000f0 + >; + }; + mdio_pins: pinmux_mdio_pins { + pinctrl-single,bits = < + /* MDIO_CLK, MDIO_D */ + 0x10 0x00000088 0x000000ff + >; + }; + mii_pins: pinmux_mii_pins { + pinctrl-single,bits = < + /* + * MII_TXEN, MII_TXCLK, MII_COL + * MII_TXD_3, MII_TXD_2, MII_TXD_1 + * MII_TXD_0 + */ + 0x8 0x88888880 0xfffffff0 + /* + * MII_RXER, MII_CRS, MII_RXCLK + * MII_RXDV, MII_RXD_3, MII_RXD_2 + * MII_RXD_1, MII_RXD_0 + */ + 0xc 0x88888888 0xffffffff + >; + }; + lcd_pins: pinmux_lcd_pins { + pinctrl-single,bits = < + /* + * LCD_D[2], LCD_D[3], LCD_D[4], LCD_D[5], + * LCD_D[6], LCD_D[7] + */ + 0x40 0x22222200 0xffffff00 + /* + * LCD_D[10], LCD_D[11], LCD_D[12], LCD_D[13], + * LCD_D[14], LCD_D[15], LCD_D[0], LCD_D[1] + */ + 0x44 0x22222222 0xffffffff + /* LCD_D[8], LCD_D[9] */ + 0x48 0x00000022 0x000000ff + + /* LCD_PCLK */ + 0x48 0x02000000 0x0f000000 + /* LCD_AC_ENB_CS, LCD_VSYNC, LCD_HSYNC */ + 0x4c 0x02000022 0x0f0000ff + >; + }; + vpif_capture_pins: vpif_capture_pins { + pinctrl-single,bits = < + /* VP_DIN[2..7], VP_CLKIN1, VP_CLKIN0 */ + 0x38 0x11111111 0xffffffff + /* VP_DIN[10..15,0..1] */ + 0x3c 0x11111111 0xffffffff + /* VP_DIN[8..9] */ + 0x40 0x00000011 0x000000ff + >; + }; + vpif_display_pins: vpif_display_pins { + pinctrl-single,bits = < + /* VP_DOUT[2..7] */ + 0x40 0x11111100 0xffffff00 + /* VP_DOUT[10..15,0..1] */ + 0x44 0x11111111 0xffffffff + /* VP_DOUT[8..9] */ + 0x48 0x00000011 0x000000ff + /* + * VP_CLKOUT3, VP_CLKIN3, + * VP_CLKOUT2, VP_CLKIN2 + */ + 0x4c 0x00111100 0x00ffff00 + >; + }; + }; + prictrl: priority-controller@14110 { + compatible = "ti,da850-mstpri"; + reg = <0x14110 0x0c>; + status = "disabled"; + }; + cfgchip: chip-controller@1417c { + compatible = "ti,da830-cfgchip", "syscon", "simple-mfd"; + reg = <0x1417c 0x14>; + + usb_phy: usb-phy { + compatible = "ti,da830-usb-phy"; + #phy-cells = <1>; + status = "disabled"; + }; + }; + edma0: edma@0 { + compatible = "ti,edma3-tpcc"; + /* eDMA3 CC0: 0x01c0 0000 - 0x01c0 7fff */ + reg = <0x0 0x8000>; + reg-names = "edma3_cc"; + interrupts = <11 12>; + interrupt-names = "edma3_ccint", "edma3_ccerrint"; + #dma-cells = <2>; + + ti,tptcs = <&edma0_tptc0 7>, <&edma0_tptc1 0>; + }; + edma0_tptc0: tptc@8000 { + compatible = "ti,edma3-tptc"; + reg = <0x8000 0x400>; + interrupts = <13>; + interrupt-names = "edm3_tcerrint"; + }; + edma0_tptc1: tptc@8400 { + compatible = "ti,edma3-tptc"; + reg = <0x8400 0x400>; + interrupts = <32>; + interrupt-names = "edm3_tcerrint"; + }; + edma1: edma@230000 { + compatible = "ti,edma3-tpcc"; + /* eDMA3 CC1: 0x01e3 0000 - 0x01e3 7fff */ + reg = <0x230000 0x8000>; + reg-names = "edma3_cc"; + interrupts = <93 94>; + interrupt-names = "edma3_ccint", "edma3_ccerrint"; + #dma-cells = <2>; + + ti,tptcs = <&edma1_tptc0 7>; + }; + edma1_tptc0: tptc@238000 { + compatible = "ti,edma3-tptc"; + reg = <0x238000 0x400>; + interrupts = <95>; + interrupt-names = "edm3_tcerrint"; + }; + serial0: serial@42000 { + compatible = "ti,da830-uart", "ns16550a"; + reg = <0x42000 0x100>; + reg-io-width = <4>; + reg-shift = <2>; + interrupts = <25>; + status = "disabled"; + }; + serial1: serial@10c000 { + compatible = "ti,da830-uart", "ns16550a"; + reg = <0x10c000 0x100>; + reg-io-width = <4>; + reg-shift = <2>; + interrupts = <53>; + status = "disabled"; + }; + serial2: serial@10d000 { + compatible = "ti,da830-uart", "ns16550a"; + reg = <0x10d000 0x100>; + reg-io-width = <4>; + reg-shift = <2>; + interrupts = <61>; + status = "disabled"; + }; + rtc0: rtc@23000 { + compatible = "ti,da830-rtc"; + reg = <0x23000 0x1000>; + interrupts = <19 + 19>; + status = "disabled"; + }; + i2c0: i2c@22000 { + compatible = "ti,davinci-i2c"; + reg = <0x22000 0x1000>; + interrupts = <15>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + i2c1: i2c@228000 { + compatible = "ti,davinci-i2c"; + reg = <0x228000 0x1000>; + interrupts = <51>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + wdt: wdt@21000 { + compatible = "ti,davinci-wdt"; + reg = <0x21000 0x1000>; + status = "disabled"; + }; + mmc0: mmc@40000 { + compatible = "ti,da830-mmc"; + reg = <0x40000 0x1000>; + cap-sd-highspeed; + cap-mmc-highspeed; + interrupts = <16>; + dmas = <&edma0 16 0>, <&edma0 17 0>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + vpif: video@217000 { + compatible = "ti,da850-vpif"; + reg = <0x217000 0x1000>; + interrupts = <92>; + status = "disabled"; + + /* VPIF capture port */ + port@0 { + #address-cells = <1>; + #size-cells = <0>; + }; + + /* VPIF display port */ + port@1 { + #address-cells = <1>; + #size-cells = <0>; + }; + }; + mmc1: mmc@21b000 { + compatible = "ti,da830-mmc"; + reg = <0x21b000 0x1000>; + cap-sd-highspeed; + cap-mmc-highspeed; + interrupts = <72>; + dmas = <&edma1 28 0>, <&edma1 29 0>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + ehrpwm0: pwm@300000 { + compatible = "ti,da850-ehrpwm", "ti,am3352-ehrpwm", + "ti,am33xx-ehrpwm"; + #pwm-cells = <3>; + reg = <0x300000 0x2000>; + status = "disabled"; + }; + ehrpwm1: pwm@302000 { + compatible = "ti,da850-ehrpwm", "ti,am3352-ehrpwm", + "ti,am33xx-ehrpwm"; + #pwm-cells = <3>; + reg = <0x302000 0x2000>; + status = "disabled"; + }; + ecap0: ecap@306000 { + compatible = "ti,da850-ecap", "ti,am3352-ecap", + "ti,am33xx-ecap"; + #pwm-cells = <3>; + reg = <0x306000 0x80>; + status = "disabled"; + }; + ecap1: ecap@307000 { + compatible = "ti,da850-ecap", "ti,am3352-ecap", + "ti,am33xx-ecap"; + #pwm-cells = <3>; + reg = <0x307000 0x80>; + status = "disabled"; + }; + ecap2: ecap@308000 { + compatible = "ti,da850-ecap", "ti,am3352-ecap", + "ti,am33xx-ecap"; + #pwm-cells = <3>; + reg = <0x308000 0x80>; + status = "disabled"; + }; + spi0: spi@41000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "ti,da830-spi"; + reg = <0x41000 0x1000>; + num-cs = <6>; + ti,davinci-spi-intr-line = <1>; + interrupts = <20>; + dmas = <&edma0 14 0>, <&edma0 15 0>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + spi1: spi@30e000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "ti,da830-spi"; + reg = <0x30e000 0x1000>; + num-cs = <4>; + ti,davinci-spi-intr-line = <1>; + interrupts = <56>; + dmas = <&edma0 18 0>, <&edma0 19 0>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + usb0: usb@200000 { + compatible = "ti,da830-musb"; + reg = <0x200000 0x1000>; + ranges; + interrupts = <58>; + interrupt-names = "mc"; + dr_mode = "otg"; + phys = <&usb_phy 0>; + phy-names = "usb-phy"; + status = "disabled"; + + #address-cells = <1>; + #size-cells = <1>; + + dmas = <&cppi41dma 0 0 &cppi41dma 1 0 + &cppi41dma 2 0 &cppi41dma 3 0 + &cppi41dma 0 1 &cppi41dma 1 1 + &cppi41dma 2 1 &cppi41dma 3 1>; + dma-names = + "rx1", "rx2", "rx3", "rx4", + "tx1", "tx2", "tx3", "tx4"; + + cppi41dma: dma-controller@201000 { + compatible = "ti,da830-cppi41"; + reg = <0x201000 0x1000 + 0x202000 0x1000 + 0x204000 0x4000>; + reg-names = "controller", + "scheduler", "queuemgr"; + interrupts = <58>; + #dma-cells = <2>; + #dma-channels = <4>; + status = "okay"; + }; + }; + sata: sata@218000 { + compatible = "ti,da850-ahci"; + reg = <0x218000 0x2000>, <0x22c018 0x4>; + interrupts = <67>; + status = "disabled"; + }; + mdio: mdio@224000 { + compatible = "ti,davinci_mdio"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x224000 0x1000>; + status = "disabled"; + }; + eth0: ethernet@220000 { + compatible = "ti,davinci-dm6467-emac"; + reg = <0x220000 0x4000>; + ti,davinci-ctrl-reg-offset = <0x3000>; + ti,davinci-ctrl-mod-reg-offset = <0x2000>; + ti,davinci-ctrl-ram-offset = <0>; + ti,davinci-ctrl-ram-size = <0x2000>; + local-mac-address = [ 00 00 00 00 00 00 ]; + interrupts = <33 + 34 + 35 + 36 + >; + status = "disabled"; + }; + usb1: usb@225000 { + compatible = "ti,da830-ohci"; + reg = <0x225000 0x1000>; + interrupts = <59>; + phys = <&usb_phy 1>; + phy-names = "usb-phy"; + status = "disabled"; + }; + gpio: gpio@226000 { + compatible = "ti,dm6441-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x226000 0x1000>; + interrupts = <42 IRQ_TYPE_EDGE_BOTH + 43 IRQ_TYPE_EDGE_BOTH 44 IRQ_TYPE_EDGE_BOTH + 45 IRQ_TYPE_EDGE_BOTH 46 IRQ_TYPE_EDGE_BOTH + 47 IRQ_TYPE_EDGE_BOTH 48 IRQ_TYPE_EDGE_BOTH + 49 IRQ_TYPE_EDGE_BOTH 50 IRQ_TYPE_EDGE_BOTH>; + ti,ngpio = <144>; + ti,davinci-gpio-unbanked = <0>; + status = "disabled"; + interrupt-controller; + #interrupt-cells = <2>; + }; + pinconf: pin-controller@22c00c { + compatible = "ti,da850-pupd"; + reg = <0x22c00c 0x8>; + status = "disabled"; + }; + + mcasp0: mcasp@100000 { + compatible = "ti,da830-mcasp-audio"; + reg = <0x100000 0x2000>, + <0x102000 0x400000>; + reg-names = "mpu", "dat"; + interrupts = <54>; + interrupt-names = "common"; + status = "disabled"; + dmas = <&edma0 1 1>, + <&edma0 0 1>; + dma-names = "tx", "rx"; + }; + + lcdc: display@213000 { + compatible = "ti,da850-tilcdc"; + reg = <0x213000 0x1000>; + interrupts = <52>; + max-pixelclock = <37500>; + status = "disabled"; + }; + }; + aemif: aemif@68000000 { + compatible = "ti,da850-aemif"; + #address-cells = <2>; + #size-cells = <1>; + + reg = <0x68000000 0x00008000>; + ranges = <0 0 0x60000000 0x08000000 + 1 0 0x68000000 0x00008000>; + status = "disabled"; + }; + memctrl: memory-controller@b0000000 { + compatible = "ti,da850-ddr-controller"; + reg = <0xb0000000 0xe8>; + status = "disabled"; + }; +}; diff --git a/arch/arm/dts/fsl-ls2081a-rdb.dts b/arch/arm/dts/fsl-ls2081a-rdb.dts index 6489362fc0..aa4aa68c9c 100644 --- a/arch/arm/dts/fsl-ls2081a-rdb.dts +++ b/arch/arm/dts/fsl-ls2081a-rdb.dts @@ -41,7 +41,7 @@ bus-num = <0>; status = "okay"; - qflash0: n25q512a@0 { + qflash0: s25fs512s@0 { #address-cells = <1>; #size-cells = <1>; compatible = "spi-flash"; @@ -49,7 +49,7 @@ reg = <0>; }; - qflash1: n25q512a@1 { + qflash1: s25fs512s@1 { #address-cells = <1>; #size-cells = <1>; compatible = "spi-flash"; diff --git a/arch/arm/dts/omap3.dtsi b/arch/arm/dts/omap3.dtsi index e6f9c9a6dd..56c94729bb 100644 --- a/arch/arm/dts/omap3.dtsi +++ b/arch/arm/dts/omap3.dtsi @@ -716,14 +716,12 @@ usbhsohci: ohci@48064400 { compatible = "ti,ohci-omap3"; reg = <0x48064400 0x400>; - interrupt-parent = <&intc>; interrupts = <76>; }; usbhsehci: ehci@48064800 { compatible = "ti,ehci-omap"; reg = <0x48064800 0x400>; - interrupt-parent = <&intc>; interrupts = <77>; }; }; @@ -834,7 +832,6 @@ reg-names = "tx", "rx"; - interrupt-parent = <&intc>; interrupts = <67>, <68>; }; @@ -847,7 +844,6 @@ reg-names = "tx", "rx"; - interrupt-parent = <&intc>; interrupts = <69>, <70>; }; diff --git a/arch/arm/dts/omap5-u-boot.dtsi b/arch/arm/dts/omap5-u-boot.dtsi index 2eeed6f4a0..fdaa69297c 100644 --- a/arch/arm/dts/omap5-u-boot.dtsi +++ b/arch/arm/dts/omap5-u-boot.dtsi @@ -60,10 +60,30 @@ }; }; +&gpio1 { + u-boot,dm-spl; +}; + &gpio2 { u-boot,dm-spl; }; +&gpio3 { + u-boot,dm-spl; +}; + +&gpio4 { + u-boot,dm-spl; +}; + +&gpio5 { + u-boot,dm-spl; +}; + +&gpio6 { + u-boot,dm-spl; +}; + &gpio7 { u-boot,dm-spl; }; diff --git a/arch/arm/dts/rk3288-vyasa.dts b/arch/arm/dts/rk3288-vyasa.dts new file mode 100644 index 0000000000..93a9c5ee09 --- /dev/null +++ b/arch/arm/dts/rk3288-vyasa.dts @@ -0,0 +1,327 @@ +/* + * Copyright (C) 2017 Jagan Teki <jagan@amarulasolutions.com> + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) 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. + */ + +/dts-v1/; +#include "rk3288.dtsi" + +/ { + model = "Amarula Vyasa-RK3288"; + compatible = "amarula,vyasa-rk3288", "rockchip,rk3288"; + + chosen { + stdout-path = &uart2; + }; + + memory { + device_type = "memory"; + reg = <0 0x80000000>; + }; + + vcc_sd: sdmmc-regulator { + compatible = "regulator-fixed"; + gpio = <&gpio7 RK_PB3 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc_pwr>; + regulator-name = "vcc_sd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + startup-delay-us = <100000>; + vin-supply = <&vcc_io>; + }; + + vcc_sys: vsys-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_sys"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + regulator-boot-on; + }; +}; + +&dmc { + rockchip,pctl-timing = <0x29a 0xc8 0x1f8 0x42 0x4e 0x4 0xea 0xa + 0x5 0x0 0xa 0x7 0x19 0x24 0xa 0x7 + 0x5 0xa 0x5 0x200 0x5 0x10 0x40 0x0 + 0x1 0x7 0x7 0x4 0xc 0x43 0x100 0x0 + 0x5 0x0>; + rockchip,phy-timing = <0x48f9aab4 0xea0910 0x1002c200 + 0xa60 0x40 0x10 0x0>; + /* Add a dummy value to cause of-platdata think this is bytes */ + rockchip,sdram-params = <0x30B25564 0x627 3 666000000 3 9 1>; +}; + +&cpu0 { + cpu0-supply = <&vdd_cpu>; +}; + +&i2c0 { + clock-frequency = <400000>; + status = "okay"; + + rk808: pmic@1b { + compatible = "rockchip,rk808"; + reg = <0x1b>; + interrupt-parent = <&gpio0>; + interrupts = <RK_PA4 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int &global_pwroff>; + wakeup-source; + rockchip,system-power-controller; + #clock-cells = <1>; + clock-output-names = "xin32k", "rk808-clkout2"; + + vcc1-supply = <&vcc_sys>; + vcc2-supply = <&vcc_sys>; + vcc3-supply = <&vcc_sys>; + vcc4-supply = <&vcc_sys>; + vcc6-supply = <&vcc_sys>; + vcc7-supply = <&vcc_sys>; + vcc8-supply = <&vcc_io>; + vcc9-supply = <&vcc_sys>; + vcc10-supply = <&vcc_sys>; + vcc11-supply = <&vcc_sys>; + vcc12-supply = <&vcc_io>; + + regulators { + vdd_cpu: vdd_log: DCDC_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <1350000>; + regulator-name = "vdd_log"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_gpu: DCDC_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <1250000>; + regulator-name = "vdd_gpu"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vcc_ddr"; + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_io: DCDC_REG4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc_io"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcca_tp: LDO_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc_tp"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_codec: LDO_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc_codec"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_10: LDO_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-name = "vdd_10"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vcc_gps: LDO_REG4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc_gps"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vccio_sd: LDO_REG5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vccio_sd"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc10_lcd: LDO_REG6 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-name = "vcc10_lcd"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcc_18: LDO_REG7 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc_18"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcc18_lcd: LDO_REG8 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc18_lcd"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcc33_sd: SWITCH_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc33_sd"; + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_lan: SWITCH_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc_lan"; + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + }; + }; +}; + +&sdmmc { + u-boot,dm-pre-reloc; + status = "okay"; + + bus-width = <4>; + cap-mmc-highspeed; + cap-sd-highspeed; + card-detect-delay = <200>; + disable-wp; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc_clk>, <&sdmmc_cmd>, <&sdmmc_cd>, <&sdmmc_bus4>; + vmmc-supply = <&vcc_sd>; + vqmmc-supply = <&vccio_sd>; +}; + +&uart2 { + u-boot,dm-pre-reloc; + status = "okay"; +}; + +&wdt { + status = "okay"; +}; + +&pinctrl { + u-boot,dm-pre-reloc; + pmic { + pmic_int: pmic-int { + rockchip,pins = <RK_GPIO0 4 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + sdmmc { + sdmmc_pwr: sdmmc-pwr { + rockchip,pins = <7 11 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; diff --git a/arch/arm/dts/rk3368-lion-u-boot.dtsi b/arch/arm/dts/rk3368-lion-u-boot.dtsi index 6052e8a8d3..a9b7f81c62 100644 --- a/arch/arm/dts/rk3368-lion-u-boot.dtsi +++ b/arch/arm/dts/rk3368-lion-u-boot.dtsi @@ -13,6 +13,7 @@ chosen { stdout-path = "serial0:115200n8"; u-boot,spl-boot-order = &emmc, &sdmmc; + tick-timer = "/timer@ff810000"; }; }; @@ -70,24 +71,25 @@ }; &emmc { - u-boot,dm-pre-reloc; + u-boot,dm-spl; }; &sdmmc { - u-boot,dm-pre-reloc; + u-boot,dm-spl; }; &spi1 { - u-boot,dm-pre-reloc; + u-boot,dm-spl; spiflash: w25q32dw@0 { - u-boot,dm-pre-reloc; + u-boot,dm-spl; }; }; &timer0 { u-boot,dm-pre-reloc; clock-frequency = <24000000>; + status = "okay"; }; diff --git a/arch/arm/dts/rk3399-puma.dtsi b/arch/arm/dts/rk3399-puma.dtsi index dd1baea704..a04878e223 100644 --- a/arch/arm/dts/rk3399-puma.dtsi +++ b/arch/arm/dts/rk3399-puma.dtsi @@ -89,6 +89,17 @@ }; }; + usbhub_enable: usbhub_enable { + compatible = "regulator-fixed"; + regulator-name = "usbhub_enable"; + enable-active-low; + gpio = <&gpio4 3 GPIO_ACTIVE_HIGH>; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + vccadc_ref: vccadc-ref { compatible = "regulator-fixed"; regulator-name = "vcc1v8_sys"; @@ -514,7 +525,6 @@ }; &dwc3_typec1 { - rockchip,vbus-gpio = <&gpio4 3 GPIO_ACTIVE_LOW>; status = "okay"; }; diff --git a/arch/arm/dts/rv1108-evb.dts b/arch/arm/dts/rv1108-evb.dts index 0128dd8b1d..2b221b6d61 100644 --- a/arch/arm/dts/rv1108-evb.dts +++ b/arch/arm/dts/rv1108-evb.dts @@ -20,6 +20,15 @@ chosen { stdout-path = "serial2:1500000n8"; }; + + vcc5v0_otg: vcc5v0-otg-drv { + compatible = "regulator-fixed"; + enable-active-high; + regulator-name = "vcc5v0_otg"; + gpio = <&gpio0 RK_PB0 GPIO_ACTIVE_HIGH>; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; }; &gmac { @@ -52,3 +61,16 @@ &uart2 { status = "okay"; }; + +&usb20_otg { + vbus-supply = <&vcc5v0_otg>; + status = "okay"; +}; + +&usb_host_ehci { + status = "okay"; +}; + +&usb_host_ohci { + status = "okay"; +}; diff --git a/arch/arm/dts/rv1108.dtsi b/arch/arm/dts/rv1108.dtsi index 77ca24e7f3..3153dfe658 100644 --- a/arch/arm/dts/rv1108.dtsi +++ b/arch/arm/dts/rv1108.dtsi @@ -175,6 +175,30 @@ status = "disabled"; }; + usb_host_ehci: usb@30140000 { + compatible = "generic-ehci"; + reg = <0x30140000 0x20000>; + interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + usb_host_ohci: usb@30160000 { + compatible = "generic-ohci"; + reg = <0x30160000 0x20000>; + interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + usb20_otg: usb@30180000 { + compatible = "rockchip,rv1108-usb", "rockchip,rk3288-usb", + "snps,dwc2"; + reg = <0x30180000 0x40000>; + interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>; + hnp-srp-disable; + dr_mode = "otg"; + status = "disabled"; + }; + sfc: sfc@301c0000 { compatible = "rockchip,sfc"; reg = <0x301c0000 0x200>; diff --git a/arch/arm/dts/stih407-family.dtsi b/arch/arm/dts/stih407-family.dtsi index af66b53471..6c6de58029 100644 --- a/arch/arm/dts/stih407-family.dtsi +++ b/arch/arm/dts/stih407-family.dtsi @@ -563,6 +563,7 @@ clocks = <&clk_s_c0_flexgen CLK_MMC_1>, <&clk_s_c0_flexgen CLK_RX_ICN_HVA>; resets = <&softreset STIH407_MMC1_SOFTRESET>; + reset-names = "softreset"; bus-width = <4>; }; @@ -654,7 +655,7 @@ compatible = "snps,dwc3"; reg = <0x09900000 0x100000>; interrupts = <GIC_SPI 155 IRQ_TYPE_NONE>; - dr_mode = "host"; + dr_mode = "peripheral"; phy-names = "usb2-phy", "usb3-phy"; phys = <&usb2_picophy0>, <&phy_port2 PHY_TYPE_USB3>; diff --git a/arch/arm/dts/stih410.dtsi b/arch/arm/dts/stih410.dtsi index f118a9e51c..b59b110989 100644 --- a/arch/arm/dts/stih410.dtsi +++ b/arch/arm/dts/stih410.dtsi @@ -83,7 +83,7 @@ }; ohci0: usb@9a03c00 { - compatible = "st,st-ohci-300x"; + compatible = "generic-ohci"; reg = <0x9a03c00 0x100>; interrupts = <GIC_SPI 180 IRQ_TYPE_NONE>; clocks = <&clk_s_c0_flexgen CLK_TX_ICN_DISP_0>, @@ -91,6 +91,7 @@ resets = <&powerdown STIH407_USB2_PORT0_POWERDOWN>, <&softreset STIH407_USB2_PORT0_SOFTRESET>; reset-names = "power", "softreset"; + phys = <&usb2_picophy1>; phy-names = "usb"; @@ -98,7 +99,7 @@ }; ehci0: usb@9a03e00 { - compatible = "st,st-ehci-300x"; + compatible = "generic-ehci"; reg = <0x9a03e00 0x100>; interrupts = <GIC_SPI 151 IRQ_TYPE_NONE>; pinctrl-names = "default"; @@ -115,7 +116,7 @@ }; ohci1: usb@9a83c00 { - compatible = "st,st-ohci-300x"; + compatible = "generic-ohci"; reg = <0x9a83c00 0x100>; interrupts = <GIC_SPI 181 IRQ_TYPE_NONE>; clocks = <&clk_s_c0_flexgen CLK_TX_ICN_DISP_0>, @@ -123,6 +124,7 @@ resets = <&powerdown STIH407_USB2_PORT1_POWERDOWN>, <&softreset STIH407_USB2_PORT1_SOFTRESET>; reset-names = "power", "softreset"; + phys = <&usb2_picophy2>; phy-names = "usb"; @@ -130,7 +132,7 @@ }; ehci1: usb@9a83e00 { - compatible = "st,st-ehci-300x"; + compatible = "generic-ehci"; reg = <0x9a83e00 0x100>; interrupts = <GIC_SPI 153 IRQ_TYPE_NONE>; pinctrl-names = "default"; @@ -140,6 +142,7 @@ resets = <&powerdown STIH407_USB2_PORT1_POWERDOWN>, <&softreset STIH407_USB2_PORT1_SOFTRESET>; reset-names = "power", "softreset"; + phys = <&usb2_picophy2>; phy-names = "usb"; diff --git a/arch/arm/dts/stm32h7-u-boot.dtsi b/arch/arm/dts/stm32h7-u-boot.dtsi new file mode 100644 index 0000000000..2525035da1 --- /dev/null +++ b/arch/arm/dts/stm32h7-u-boot.dtsi @@ -0,0 +1,88 @@ +/{ + clocks { + u-boot,dm-pre-reloc; + }; + + soc { + u-boot,dm-pre-reloc; + pin-controller { + u-boot,dm-pre-reloc; + }; + }; +}; + +&clk_hse { + u-boot,dm-pre-reloc; +}; + +&clk_lse { + u-boot,dm-pre-reloc; +}; + +&clk_i2s { + u-boot,dm-pre-reloc; +}; + +&pwrcfg { + u-boot,dm-pre-reloc; +}; + +&rcc { + u-boot,dm-pre-reloc; +}; + +&fmc { + u-boot,dm-pre-reloc; +}; + +&clk_hsi { + u-boot,dm-pre-reloc; +}; + +&clk_csi { + u-boot,dm-pre-reloc; +}; + +&gpioa { + u-boot,dm-pre-reloc; +}; + +&gpiob { + u-boot,dm-pre-reloc; +}; + +&gpioc { + u-boot,dm-pre-reloc; +}; + +&gpiod { + u-boot,dm-pre-reloc; +}; + +&gpioe { + u-boot,dm-pre-reloc; +}; + +&gpiof { + u-boot,dm-pre-reloc; +}; + +&gpiog { + u-boot,dm-pre-reloc; +}; + +&gpioh { + u-boot,dm-pre-reloc; +}; + +&gpioi { + u-boot,dm-pre-reloc; +}; + +&gpioj { + u-boot,dm-pre-reloc; +}; + +&gpiok { + u-boot,dm-pre-reloc; +}; diff --git a/arch/arm/dts/stm32h743-pinctrl.dtsi b/arch/arm/dts/stm32h743-pinctrl.dtsi new file mode 100644 index 0000000000..d3e11d53ab --- /dev/null +++ b/arch/arm/dts/stm32h743-pinctrl.dtsi @@ -0,0 +1,249 @@ +/* + * Copyright 2017 - Alexandre Torgue <alexandre.torgue@st.com> + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) 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. + */ + +#include <dt-bindings/pinctrl/stm32h7-pinfunc.h> + +/ { + soc { + pin-controller { + #address-cells = <1>; + #size-cells = <1>; + compatible = "st,stm32h743-pinctrl"; + ranges = <0 0x58020000 0x3000>; + pins-are-numbered; + + gpioa: gpio@58020000 { + gpio-controller; + #gpio-cells = <2>; + compatible = "st,stm32-gpio"; + reg = <0x0 0x400>; + clocks = <&rcc GPIOA_CK>; + st,bank-name = "GPIOA"; + }; + + gpiob: gpio@58020400 { + gpio-controller; + #gpio-cells = <2>; + compatible = "st,stm32-gpio"; + reg = <0x400 0x400>; + clocks = <&rcc GPIOB_CK>; + st,bank-name = "GPIOB"; + }; + + gpioc: gpio@58020800 { + gpio-controller; + #gpio-cells = <2>; + compatible = "st,stm32-gpio"; + reg = <0x800 0x400>; + clocks = <&rcc GPIOC_CK>; + st,bank-name = "GPIOC"; + }; + + gpiod: gpio@58020c00 { + gpio-controller; + #gpio-cells = <2>; + compatible = "st,stm32-gpio"; + reg = <0xc00 0x400>; + clocks = <&rcc GPIOD_CK>; + st,bank-name = "GPIOD"; + }; + + gpioe: gpio@58021000 { + gpio-controller; + #gpio-cells = <2>; + compatible = "st,stm32-gpio"; + reg = <0x1000 0x400>; + clocks = <&rcc GPIOE_CK>; + st,bank-name = "GPIOE"; + }; + + gpiof: gpio@58021400 { + gpio-controller; + #gpio-cells = <2>; + compatible = "st,stm32-gpio"; + reg = <0x1400 0x400>; + clocks = <&rcc GPIOF_CK>; + st,bank-name = "GPIOF"; + }; + + gpiog: gpio@58021800 { + gpio-controller; + #gpio-cells = <2>; + compatible = "st,stm32-gpio"; + reg = <0x1800 0x400>; + clocks = <&rcc GPIOG_CK>; + st,bank-name = "GPIOG"; + }; + + gpioh: gpio@58021c00 { + gpio-controller; + #gpio-cells = <2>; + compatible = "st,stm32-gpio"; + reg = <0x1c00 0x400>; + clocks = <&rcc GPIOH_CK>; + st,bank-name = "GPIOH"; + }; + + gpioi: gpio@58022000 { + gpio-controller; + #gpio-cells = <2>; + compatible = "st,stm32-gpio"; + reg = <0x2000 0x400>; + clocks = <&rcc GPIOI_CK>; + st,bank-name = "GPIOI"; + }; + + gpioj: gpio@58022400 { + gpio-controller; + #gpio-cells = <2>; + compatible = "st,stm32-gpio"; + reg = <0x2400 0x400>; + clocks = <&rcc GPIOJ_CK>; + st,bank-name = "GPIOJ"; + }; + + gpiok: gpio@58022800 { + gpio-controller; + #gpio-cells = <2>; + compatible = "st,stm32-gpio"; + reg = <0x2800 0x400>; + clocks = <&rcc GPIOK_CK>; + st,bank-name = "GPIOK"; + }; + + usart1_pins: usart1@0 { + pins1 { + pinmux = <STM32H7_PB14_FUNC_USART1_TX>; + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = <STM32H7_PB15_FUNC_USART1_RX>; + bias-disable; + }; + }; + + usart2_pins: usart2@0 { + pins1 { + pinmux = <STM32H7_PD5_FUNC_USART2_TX>; + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = <STM32H7_PD6_FUNC_USART2_RX>; + bias-disable; + }; + }; + + fmc_pins: fmc@0 { + pins { + pinmux = <STM32H7_PD0_FUNC_FMC_D2_FMC_DA2>, + <STM32H7_PD1_FUNC_FMC_D3_FMC_DA3>, + <STM32H7_PD8_FUNC_FMC_D13_FMC_DA13>, + <STM32H7_PD9_FUNC_FMC_D14_FMC_DA14>, + <STM32H7_PD10_FUNC_FMC_D15_FMC_DA15>, + <STM32H7_PD14_FUNC_FMC_D0_FMC_DA0>, + <STM32H7_PD15_FUNC_FMC_D1_FMC_DA1>, + + <STM32H7_PE0_FUNC_FMC_NBL0>, + <STM32H7_PE1_FUNC_FMC_NBL1>, + <STM32H7_PE7_FUNC_FMC_D4_FMC_DA4>, + <STM32H7_PE8_FUNC_FMC_D5_FMC_DA5>, + <STM32H7_PE9_FUNC_FMC_D6_FMC_DA6>, + <STM32H7_PE10_FUNC_FMC_D7_FMC_DA7>, + <STM32H7_PE11_FUNC_FMC_D8_FMC_DA8>, + <STM32H7_PE12_FUNC_FMC_D9_FMC_DA9>, + <STM32H7_PE13_FUNC_FMC_D10_FMC_DA10>, + <STM32H7_PE14_FUNC_FMC_D11_FMC_DA11>, + <STM32H7_PE15_FUNC_FMC_D12_FMC_DA12>, + + <STM32H7_PF0_FUNC_FMC_A0>, + <STM32H7_PF1_FUNC_FMC_A1>, + <STM32H7_PF2_FUNC_FMC_A2>, + <STM32H7_PF3_FUNC_FMC_A3>, + <STM32H7_PF4_FUNC_FMC_A4>, + <STM32H7_PF5_FUNC_FMC_A5>, + <STM32H7_PF11_FUNC_FMC_SDNRAS>, + <STM32H7_PF12_FUNC_FMC_A6>, + <STM32H7_PF13_FUNC_FMC_A7>, + <STM32H7_PF14_FUNC_FMC_A8>, + <STM32H7_PF15_FUNC_FMC_A9>, + + <STM32H7_PG0_FUNC_FMC_A10>, + <STM32H7_PG1_FUNC_FMC_A11>, + <STM32H7_PG2_FUNC_FMC_A12>, + <STM32H7_PG4_FUNC_FMC_A14_FMC_BA0>, + <STM32H7_PG5_FUNC_FMC_A15_FMC_BA1>, + <STM32H7_PG8_FUNC_FMC_SDCLK>, + <STM32H7_PG15_FUNC_FMC_SDNCAS>, + + <STM32H7_PH5_FUNC_FMC_SDNWE>, + <STM32H7_PH6_FUNC_FMC_SDNE1>, + <STM32H7_PH7_FUNC_FMC_SDCKE1>, + <STM32H7_PH8_FUNC_FMC_D16>, + <STM32H7_PH9_FUNC_FMC_D17>, + <STM32H7_PH10_FUNC_FMC_D18>, + <STM32H7_PH11_FUNC_FMC_D19>, + <STM32H7_PH12_FUNC_FMC_D20>, + <STM32H7_PH13_FUNC_FMC_D21>, + <STM32H7_PH14_FUNC_FMC_D22>, + <STM32H7_PH15_FUNC_FMC_D23>, + + <STM32H7_PI0_FUNC_FMC_D24>, + <STM32H7_PI1_FUNC_FMC_D25>, + <STM32H7_PI2_FUNC_FMC_D26>, + <STM32H7_PI3_FUNC_FMC_D27>, + <STM32H7_PI4_FUNC_FMC_NBL2>, + <STM32H7_PI5_FUNC_FMC_NBL3>, + <STM32H7_PI6_FUNC_FMC_D28>, + <STM32H7_PI7_FUNC_FMC_D29>, + <STM32H7_PI9_FUNC_FMC_D30>, + <STM32H7_PI10_FUNC_FMC_D31>; + + slew-rate = <3>; + }; + }; + }; + }; +}; diff --git a/arch/arm/dts/stm32h743.dtsi b/arch/arm/dts/stm32h743.dtsi new file mode 100644 index 0000000000..16e93089d7 --- /dev/null +++ b/arch/arm/dts/stm32h743.dtsi @@ -0,0 +1,129 @@ +/* + * Copyright 2017 - Alexandre Torgue <alexandre.torgue@st.com> + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) 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. + */ + +#include "skeleton.dtsi" +#include "armv7-m.dtsi" +#include <dt-bindings/clock/stm32h7-clks.h> + +/ { + clocks { + clk_hse: clk-hse { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <25000000>; + }; + + clk_lse: clk-lse { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32768>; + }; + + clk_i2s: i2s_ckin { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <0>; + }; + }; + + soc { + rcc: rcc@58024400 { + #clock-cells = <1>; + #reset-cells = <1>; + compatible = "st,stm32h743-rcc", "st,stm32-rcc"; + reg = <0x58024400 0x400>; + clocks = <&clk_hse>, <&clk_lse>, <&clk_i2s>, <&clk_hsi>, <&clk_csi>; + st,syscfg = <&pwrcfg>; + }; + + usart1: serial@40011000 { + compatible = "st,stm32h7-usart", "st,stm32h7-uart"; + reg = <0x40011000 0x400>; + interrupts = <37>; + status = "disabled"; + clocks = <&rcc USART1_CK>; + }; + + usart2: serial@40004400 { + compatible = "st,stm32h7-usart", "st,stm32h7-uart"; + reg = <0x40004400 0x400>; + interrupts = <38>; + status = "disabled"; + clocks = <&rcc USART2_CK>; + }; + + timer5: timer@40000c00 { + compatible = "st,stm32-timer"; + reg = <0x40000c00 0x400>; + interrupts = <50>; + clocks = <&rcc TIM5_CK>; + }; + + pwrcfg: power-config@58024800 { + compatible = "syscon"; + reg = <0x58024800 0x400>; + }; + + fmc: fmc@52004000 { + compatible = "st,stm32h7-fmc"; + reg = <0x52004000 0x1000>; + clocks = <&rcc FMC_CK>; + }; + + clk_hsi: clk-hsi { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <64000000>; + }; + + clk_csi: clk-csi { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <4000000>; + }; + }; +}; + +&systick { + clock-frequency = <250000000>; + status = "okay"; +}; diff --git a/arch/arm/dts/stm32h743i-disco.dts b/arch/arm/dts/stm32h743i-disco.dts new file mode 100644 index 0000000000..bef7e90f20 --- /dev/null +++ b/arch/arm/dts/stm32h743i-disco.dts @@ -0,0 +1,100 @@ +/* + * Copyright 2017 - Patrice Chotard <patrice.chotard@st.com> + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) 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. + */ + +/dts-v1/; +#include "stm32h743.dtsi" +#include "stm32h743-pinctrl.dtsi" +#include <dt-bindings/memory/stm32-sdram.h> + +/ { + model = "STMicroelectronics STM32H743i-Discovery board"; + compatible = "st,stm32h743i-disco", "st,stm32h743"; + + chosen { + bootargs = "root=/dev/ram"; + stdout-path = "serial0:115200n8"; + }; + + memory { + reg = <0xd0000000 0x2000000>; + }; + + aliases { + serial0 = &usart2; + gpio0 = &gpioa; + gpio1 = &gpiob; + gpio2 = &gpioc; + gpio3 = &gpiod; + gpio4 = &gpioe; + gpio5 = &gpiof; + gpio6 = &gpiog; + gpio7 = &gpioh; + gpio8 = &gpioi; + gpio9 = &gpioj; + gpio10 = &gpiok; + }; +}; + +&usart2 { + pinctrl-0 = <&usart2_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&fmc { + pinctrl-0 = <&fmc_pins>; + pinctrl-names = "default"; + status = "okay"; + + /* + * Memory configuration from sdram datasheet IS42S32800G-6BLI + * firsct bank is bank@0 + * second bank is bank@1 + */ + bank1: bank@1 { + st,sdram-control = /bits/ 8 <NO_COL_9 NO_ROW_12 MWIDTH_32 BANKS_4 + CAS_2 SDCLK_3 RD_BURST_EN RD_PIPE_DL_0>; + st,sdram-timing = /bits/ 8 <TMRD_1 TXSR_1 TRAS_1 TRC_6 TRP_2 + TWR_1 TRCD_1>; + st,sdram-refcount = <1539>; + }; +}; diff --git a/arch/arm/dts/stm32h743i-eval.dts b/arch/arm/dts/stm32h743i-eval.dts new file mode 100644 index 0000000000..0e01ce51ab --- /dev/null +++ b/arch/arm/dts/stm32h743i-eval.dts @@ -0,0 +1,100 @@ +/* + * Copyright 2017 - Alexandre Torgue <alexandre.torgue@st.com> + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) 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. + */ + +/dts-v1/; +#include "stm32h743.dtsi" +#include "stm32h743-pinctrl.dtsi" +#include <dt-bindings/memory/stm32-sdram.h> + +/ { + model = "STMicroelectronics STM32H743i-EVAL board"; + compatible = "st,stm32h743i-eval", "st,stm32h743"; + + chosen { + bootargs = "root=/dev/ram"; + stdout-path = "serial0:115200n8"; + }; + + memory { + reg = <0xd0000000 0x2000000>; + }; + + aliases { + serial0 = &usart1; + gpio0 = &gpioa; + gpio1 = &gpiob; + gpio2 = &gpioc; + gpio3 = &gpiod; + gpio4 = &gpioe; + gpio5 = &gpiof; + gpio6 = &gpiog; + gpio7 = &gpioh; + gpio8 = &gpioi; + gpio9 = &gpioj; + gpio10 = &gpiok; + }; +}; + +&usart1 { + pinctrl-0 = <&usart1_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&fmc { + pinctrl-0 = <&fmc_pins>; + pinctrl-names = "default"; + status = "okay"; + + /* + * Memory configuration from sdram datasheet IS42S32800G-6BLI + * firsct bank is bank@0 + * second bank is bank@1 + */ + bank2: bank@1 { + st,sdram-control = /bits/ 8 <NO_COL_9 NO_ROW_12 MWIDTH_32 BANKS_4 + CAS_2 SDCLK_3 RD_BURST_EN RD_PIPE_DL_0>; + st,sdram-timing = /bits/ 8 <TMRD_1 TXSR_1 TRAS_1 TRC_6 TRP_2 + TWR_1 TRCD_1>; + st,sdram-refcount = <1539>; + }; +}; diff --git a/arch/arm/dts/tps6507x.dtsi b/arch/arm/dts/tps6507x.dtsi new file mode 100644 index 0000000000..4c326e591e --- /dev/null +++ b/arch/arm/dts/tps6507x.dtsi @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* + * Integrated Power Management Chip + * http://www.ti.com/lit/ds/symlink/tps65070.pdf + */ + +&tps { + compatible = "ti,tps6507x"; + + regulators { + #address-cells = <1>; + #size-cells = <0>; + + vdcdc1_reg: regulator@0 { + reg = <0>; + regulator-compatible = "VDCDC1"; + }; + + vdcdc2_reg: regulator@1 { + reg = <1>; + regulator-compatible = "VDCDC2"; + }; + + vdcdc3_reg: regulator@2 { + reg = <2>; + regulator-compatible = "VDCDC3"; + }; + + ldo1_reg: regulator@3 { + reg = <3>; + regulator-compatible = "LDO1"; + }; + + ldo2_reg: regulator@4 { + reg = <4>; + regulator-compatible = "LDO2"; + }; + + }; +}; diff --git a/arch/arm/include/asm/arch-fsl-layerscape/cpu.h b/arch/arm/include/asm/arch-fsl-layerscape/cpu.h index a0dac86bab..4d7992465a 100644 --- a/arch/arm/include/asm/arch-fsl-layerscape/cpu.h +++ b/arch/arm/include/asm/arch-fsl-layerscape/cpu.h @@ -106,6 +106,7 @@ static struct mm_region early_map[] = { { CONFIG_SYS_FSL_QSPI_BASE1, CONFIG_SYS_FSL_QSPI_BASE1, CONFIG_SYS_FSL_QSPI_SIZE1, PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_NON_SHARE}, +#ifdef CONFIG_FSL_IFC /* For IFC Region #1, only the first 4MB is cache-enabled */ { CONFIG_SYS_FSL_IFC_BASE1, CONFIG_SYS_FSL_IFC_BASE1, CONFIG_SYS_FSL_IFC_SIZE1_1, @@ -120,6 +121,7 @@ static struct mm_region early_map[] = { CONFIG_SYS_FSL_IFC_SIZE1, PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE }, +#endif { CONFIG_SYS_FSL_DRAM_BASE1, CONFIG_SYS_FSL_DRAM_BASE1, CONFIG_SYS_FSL_DRAM_SIZE1, #if defined(CONFIG_SPL) && !defined(CONFIG_SPL_BUILD) @@ -129,11 +131,13 @@ static struct mm_region early_map[] = { #endif PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS }, +#ifdef CONFIG_FSL_IFC /* Map IFC region #2 up to CONFIG_SYS_FLASH_BASE for NAND boot */ { CONFIG_SYS_FSL_IFC_BASE2, CONFIG_SYS_FSL_IFC_BASE2, CONFIG_SYS_FLASH_BASE - CONFIG_SYS_FSL_IFC_BASE2, PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE }, +#endif { CONFIG_SYS_FSL_DCSR_BASE, CONFIG_SYS_FSL_DCSR_BASE, CONFIG_SYS_FSL_DCSR_SIZE, PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | @@ -163,10 +167,12 @@ static struct mm_region early_map[] = { CONFIG_SYS_FSL_QSPI_SIZE, PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE }, +#ifdef CONFIG_FSL_IFC { CONFIG_SYS_FSL_IFC_BASE, CONFIG_SYS_FSL_IFC_BASE, CONFIG_SYS_FSL_IFC_SIZE, PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE }, +#endif { CONFIG_SYS_FSL_DRAM_BASE1, CONFIG_SYS_FSL_DRAM_BASE1, CONFIG_SYS_FSL_DRAM_SIZE1, #if defined(CONFIG_SPL) && !defined(CONFIG_SPL_BUILD) @@ -211,11 +217,13 @@ static struct mm_region final_map[] = { PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN }, +#ifdef CONFIG_FSL_IFC { CONFIG_SYS_FSL_IFC_BASE2, CONFIG_SYS_FSL_IFC_BASE2, CONFIG_SYS_FSL_IFC_SIZE2, PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN }, +#endif { CONFIG_SYS_FSL_DCSR_BASE, CONFIG_SYS_FSL_DCSR_BASE, CONFIG_SYS_FSL_DCSR_SIZE, PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | @@ -310,10 +318,12 @@ static struct mm_region final_map[] = { PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN }, +#ifdef CONFIG_FSL_IFC { CONFIG_SYS_FSL_IFC_BASE, CONFIG_SYS_FSL_IFC_BASE, CONFIG_SYS_FSL_IFC_SIZE, PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE }, +#endif { CONFIG_SYS_FSL_DRAM_BASE1, CONFIG_SYS_FSL_DRAM_BASE1, CONFIG_SYS_FSL_DRAM_SIZE1, PTE_BLOCK_MEMTYPE(MT_NORMAL) | diff --git a/arch/arm/include/asm/arch-mx6/sys_proto.h b/arch/arm/include/asm/arch-mx6/sys_proto.h index 14f5d948c9..ba73943260 100644 --- a/arch/arm/include/asm/arch-mx6/sys_proto.h +++ b/arch/arm/include/asm/arch-mx6/sys_proto.h @@ -6,3 +6,10 @@ */ #include <asm/mach-imx/sys_proto.h> + +#define USBPHY_PWD 0x00000000 + +#define USBPHY_PWD_RXPWDRX (1 << 20) /* receiver block power down */ + +#define is_usbotg_phy_active(void) (!(readl(USB_PHY0_BASE_ADDR + USBPHY_PWD) & \ + USBPHY_PWD_RXPWDRX)) diff --git a/arch/arm/include/asm/arch-mx7/clock.h b/arch/arm/include/asm/arch-mx7/clock.h index 688d2361df..3b115ad57c 100644 --- a/arch/arm/include/asm/arch-mx7/clock.h +++ b/arch/arm/include/asm/arch-mx7/clock.h @@ -318,9 +318,9 @@ struct clk_root_map { }; enum enet_freq { - ENET_25MHz, - ENET_50MHz, - ENET_125MHz, + ENET_25MHZ, + ENET_50MHZ, + ENET_125MHZ, }; u32 get_root_clk(enum clk_root_index clock_id); diff --git a/arch/arm/include/asm/arch-rockchip/grf_rk322x.h b/arch/arm/include/asm/arch-rockchip/grf_rk322x.h index 26071c8ec8..c0c0d84cf1 100644 --- a/arch/arm/include/asm/arch-rockchip/grf_rk322x.h +++ b/arch/arm/include/asm/arch-rockchip/grf_rk322x.h @@ -54,6 +54,32 @@ struct rk322x_grf { unsigned int os_reg[8]; unsigned int reserved9[(0x604 - 0x5e4) / 4 - 1]; unsigned int ddrc_stat; + unsigned int reserved10[(0x680 - 0x604) / 4 - 1]; + unsigned int sig_detect_con[2]; + unsigned int reserved11[(0x690 - 0x684) / 4 - 1]; + unsigned int sig_detect_status[2]; + unsigned int reserved12[(0x6a0 - 0x694) / 4 - 1]; + unsigned int sig_detect_clr[2]; + unsigned int reserved13[(0x6b0 - 0x6a4) / 4 - 1]; + unsigned int emmc_det; + unsigned int reserved14[(0x700 - 0x6b0) / 4 - 1]; + unsigned int host0_con[3]; + unsigned int reserved15; + unsigned int host1_con[3]; + unsigned int reserved16; + unsigned int host2_con[3]; + unsigned int reserved17[(0x760 - 0x728) / 4 - 1]; + unsigned int usbphy0_con[27]; + unsigned int reserved18[(0x800 - 0x7c8) / 4 - 1]; + unsigned int usbphy1_con[27]; + unsigned int reserved19[(0x880 - 0x868) / 4 - 1]; + unsigned int otg_con0; + unsigned int uoc_status0; + unsigned int reserved20[(0x900 - 0x884) / 4 - 1]; + unsigned int mac_con[2]; + unsigned int reserved21[(0xb00 - 0x904) / 4 - 1]; + unsigned int macphy_con[4]; + unsigned int macphy_status; }; check_member(rk322x_grf, ddrc_stat, 0x604); @@ -516,4 +542,10 @@ enum { CON_IOMUX_PWM0SEL_SHIFT = 0, CON_IOMUX_PWM0SEL_MASK = 1 << CON_IOMUX_PWM0SEL_SHIFT, }; + +/* GRF_MACPHY_CON0 */ +enum { + MACPHY_CFG_ENABLE_SHIFT = 0, + MACPHY_CFG_ENABLE_MASK = 1 << MACPHY_CFG_ENABLE_SHIFT, +}; #endif diff --git a/arch/arm/include/asm/arch-stih410/sys_proto.h b/arch/arm/include/asm/arch-stih410/sys_proto.h new file mode 100644 index 0000000000..5c40d3b0a4 --- /dev/null +++ b/arch/arm/include/asm/arch-stih410/sys_proto.h @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2017 + * Patrice Chotard <patrice.chotard@st.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _ASM_ARCH_SYS_PROTO_H +#define _ASM_ARCH_SYS_PROTO_H + +#endif /* _ASM_ARCH_SYS_PROTO_H */ diff --git a/arch/arm/include/asm/arch-stm32h7/gpio.h b/arch/arm/include/asm/arch-stm32h7/gpio.h new file mode 100644 index 0000000000..450784cb21 --- /dev/null +++ b/arch/arm/include/asm/arch-stm32h7/gpio.h @@ -0,0 +1,126 @@ +/* + * Copyright (C) STMicroelectronics SA 2017 + * Author(s): Patrice CHOTARD, <patrice.chotard@st.com> for STMicroelectronics. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _STM32_GPIO_H_ +#define _STM32_GPIO_H_ +#include <asm/gpio.h> + +enum stm32_gpio_port { + STM32_GPIO_PORT_A = 0, + STM32_GPIO_PORT_B, + STM32_GPIO_PORT_C, + STM32_GPIO_PORT_D, + STM32_GPIO_PORT_E, + STM32_GPIO_PORT_F, + STM32_GPIO_PORT_G, + STM32_GPIO_PORT_H, + STM32_GPIO_PORT_I +}; + +enum stm32_gpio_pin { + STM32_GPIO_PIN_0 = 0, + STM32_GPIO_PIN_1, + STM32_GPIO_PIN_2, + STM32_GPIO_PIN_3, + STM32_GPIO_PIN_4, + STM32_GPIO_PIN_5, + STM32_GPIO_PIN_6, + STM32_GPIO_PIN_7, + STM32_GPIO_PIN_8, + STM32_GPIO_PIN_9, + STM32_GPIO_PIN_10, + STM32_GPIO_PIN_11, + STM32_GPIO_PIN_12, + STM32_GPIO_PIN_13, + STM32_GPIO_PIN_14, + STM32_GPIO_PIN_15 +}; + +enum stm32_gpio_mode { + STM32_GPIO_MODE_IN = 0, + STM32_GPIO_MODE_OUT, + STM32_GPIO_MODE_AF, + STM32_GPIO_MODE_AN +}; + +enum stm32_gpio_otype { + STM32_GPIO_OTYPE_PP = 0, + STM32_GPIO_OTYPE_OD +}; + +enum stm32_gpio_speed { + STM32_GPIO_SPEED_2M = 0, + STM32_GPIO_SPEED_25M, + STM32_GPIO_SPEED_50M, + STM32_GPIO_SPEED_100M +}; + +enum stm32_gpio_pupd { + STM32_GPIO_PUPD_NO = 0, + STM32_GPIO_PUPD_UP, + STM32_GPIO_PUPD_DOWN +}; + +enum stm32_gpio_af { + STM32_GPIO_AF0 = 0, + STM32_GPIO_AF1, + STM32_GPIO_AF2, + STM32_GPIO_AF3, + STM32_GPIO_AF4, + STM32_GPIO_AF5, + STM32_GPIO_AF6, + STM32_GPIO_AF7, + STM32_GPIO_AF8, + STM32_GPIO_AF9, + STM32_GPIO_AF10, + STM32_GPIO_AF11, + STM32_GPIO_AF12, + STM32_GPIO_AF13, + STM32_GPIO_AF14, + STM32_GPIO_AF15 +}; + +struct stm32_gpio_dsc { + enum stm32_gpio_port port; + enum stm32_gpio_pin pin; +}; + +struct stm32_gpio_ctl { + enum stm32_gpio_mode mode; + enum stm32_gpio_otype otype; + enum stm32_gpio_speed speed; + enum stm32_gpio_pupd pupd; + enum stm32_gpio_af af; +}; + +struct stm32_gpio_regs { + u32 moder; /* GPIO port mode */ + u32 otyper; /* GPIO port output type */ + u32 ospeedr; /* GPIO port output speed */ + u32 pupdr; /* GPIO port pull-up/pull-down */ + u32 idr; /* GPIO port input data */ + u32 odr; /* GPIO port output data */ + u32 bsrr; /* GPIO port bit set/reset */ + u32 lckr; /* GPIO port configuration lock */ + u32 afr[2]; /* GPIO alternate function */ +}; + +struct stm32_gpio_priv { + struct stm32_gpio_regs *regs; +}; + +static inline unsigned stm32_gpio_to_port(unsigned gpio) +{ + return gpio / 16; +} + +static inline unsigned stm32_gpio_to_pin(unsigned gpio) +{ + return gpio % 16; +} + +#endif /* _STM32_GPIO_H_ */ diff --git a/arch/arm/include/asm/arch-stm32h7/stm32.h b/arch/arm/include/asm/arch-stm32h7/stm32.h new file mode 100644 index 0000000000..9ff1f13735 --- /dev/null +++ b/arch/arm/include/asm/arch-stm32h7/stm32.h @@ -0,0 +1,21 @@ +/* + * Copyright (C) STMicroelectronics SA 2017 + * Author(s): Patrice CHOTARD, <patrice.chotard@st.com> for STMicroelectronics. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _ASM_ARCH_HARDWARE_H +#define _ASM_ARCH_HARDWARE_H + +/* + * This empty files is needed to not break compilation + * Some common drivers to STM32F4/F7 and H7 include a stm32.h file + * Some cleanup need to be done to communalize all the following + * stm32.h files: + * + * arch/arm/include/asm/arch-stm32f1/stm32.h + * arch/arm/include/asm/arch-stm32f4/stm32.h + * arch/arm/include/asm/arch-stm32f7/stm32.h + */ +#endif /* _ASM_ARCH_HARDWARE_H */ diff --git a/arch/arm/mach-imx/mx7/clock.c b/arch/arm/mach-imx/mx7/clock.c index 2cfde46a55..8150faa1a3 100644 --- a/arch/arm/mach-imx/mx7/clock.c +++ b/arch/arm/mach-imx/mx7/clock.c @@ -966,15 +966,15 @@ int set_clk_enet(enum enet_freq type) clock_enable(CCGR_ENET2, 0); switch (type) { - case ENET_125MHz: + case ENET_125MHZ: enet1_ref = ENET1_REF_CLK_ROOT_FROM_PLL_ENET_MAIN_125M_CLK; enet2_ref = ENET2_REF_CLK_ROOT_FROM_PLL_ENET_MAIN_125M_CLK; break; - case ENET_50MHz: + case ENET_50MHZ: enet1_ref = ENET1_REF_CLK_ROOT_FROM_PLL_ENET_MAIN_50M_CLK; enet2_ref = ENET2_REF_CLK_ROOT_FROM_PLL_ENET_MAIN_50M_CLK; break; - case ENET_25MHz: + case ENET_25MHZ: enet1_ref = ENET1_REF_CLK_ROOT_FROM_PLL_ENET_MAIN_25M_CLK; enet2_ref = ENET2_REF_CLK_ROOT_FROM_PLL_ENET_MAIN_25M_CLK; break; diff --git a/arch/arm/mach-imx/spl.c b/arch/arm/mach-imx/spl.c index 258578ac25..5944f99482 100644 --- a/arch/arm/mach-imx/spl.c +++ b/arch/arm/mach-imx/spl.c @@ -14,6 +14,7 @@ #include <asm/spl.h> #include <spl.h> #include <asm/mach-imx/hab.h> +#include <g_dnl.h> DECLARE_GLOBAL_DATA_PTR; @@ -31,6 +32,18 @@ u32 spl_boot_device(void) if (((bmode >> 24) & 0x03) == 0x01) /* Serial Downloader */ return BOOT_DEVICE_BOARD; + /* + * The above method does not detect that the boot ROM used + * serial downloader in case the boot ROM decided to use the + * serial downloader as a fall back (primary boot source failed). + * + * Infer that the boot ROM used the USB serial downloader by + * checking whether the USB PHY is currently active... This + * assumes that SPL did not (yet) initialize the USB PHY... + */ + if (is_usbotg_phy_active()) + return BOOT_DEVICE_BOARD; + /* BOOT_CFG1[7:4] - see IMX6DQRM Table 8-8 */ switch ((reg & IMX6_BMODE_MASK) >> IMX6_BMODE_SHIFT) { /* EIM: See 8.5.1, Table 8-9 */ @@ -82,6 +95,15 @@ u32 spl_boot_device(void) } return BOOT_DEVICE_NONE; } + +#ifdef CONFIG_SPL_USB_GADGET_SUPPORT +int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name) +{ + put_unaligned(CONFIG_G_DNL_PRODUCT_NUM + 0xfff, &dev->idProduct); + + return 0; +} +#endif #endif #if defined(CONFIG_SPL_MMC_SUPPORT) diff --git a/arch/arm/mach-mvebu/cpu.c b/arch/arm/mach-mvebu/cpu.c index 14457317ce..74a63dd656 100644 --- a/arch/arm/mach-mvebu/cpu.c +++ b/arch/arm/mach-mvebu/cpu.c @@ -62,6 +62,11 @@ int mvebu_soc_family(void) case SOC_88F6820_ID: case SOC_88F6828_ID: return MVEBU_SOC_A38X; + + case SOC_98DX3236_ID: + case SOC_98DX3336_ID: + case SOC_98DX4251_ID: + return MVEBU_SOC_MSYS; } return MVEBU_SOC_UNKNOWN; @@ -107,13 +112,15 @@ static const struct sar_freq_modes sar_freq_tab[] = { #elif defined(CONFIG_ARMADA_38X) /* SAR frequency values for Armada 38x */ static const struct sar_freq_modes sar_freq_tab[] = { - { 0x0, 0x0, 666, 333, 333 }, - { 0x2, 0x0, 800, 400, 400 }, - { 0x4, 0x0, 1066, 533, 533 }, - { 0x6, 0x0, 1200, 600, 600 }, - { 0x8, 0x0, 1332, 666, 666 }, - { 0xc, 0x0, 1600, 800, 800 }, - { 0xff, 0xff, 0, 0, 0 } /* 0xff marks end of array */ + { 0x0, 0x0, 666, 333, 333 }, + { 0x2, 0x0, 800, 400, 400 }, + { 0x4, 0x0, 1066, 533, 533 }, + { 0x6, 0x0, 1200, 600, 600 }, + { 0x8, 0x0, 1332, 666, 666 }, + { 0xc, 0x0, 1600, 800, 800 }, + { 0x10, 0x0, 1866, 933, 933 }, + { 0x13, 0x0, 2000, 1000, 933 }, + { 0xff, 0xff, 0, 0, 0 } /* 0xff marks end of array */ }; #else /* SAR frequency values for Armada XP */ @@ -208,6 +215,15 @@ int print_cpuinfo(void) case SOC_88F6828_ID: puts("MV88F6828-"); break; + case SOC_98DX3236_ID: + puts("98DX3236-"); + break; + case SOC_98DX3336_ID: + puts("98DX3336-"); + break; + case SOC_98DX4251_ID: + puts("98DX4251-"); + break; default: puts("Unknown-"); break; diff --git a/arch/arm/mach-mvebu/dram.c b/arch/arm/mach-mvebu/dram.c index e3f304c366..e634905618 100644 --- a/arch/arm/mach-mvebu/dram.c +++ b/arch/arm/mach-mvebu/dram.c @@ -179,11 +179,11 @@ static void dram_ecc_scrubbing(void) reg_write(REG_SDRAM_CONFIG_ADDR, temp); for (cs = 0; cs < CONFIG_NR_DRAM_BANKS; cs++) { - size = mvebu_sdram_bs(cs) - 1; + size = mvebu_sdram_bs(cs); if (size == 0) continue; - total = (u64)size + 1; + total = (u64)size; total_mem += (u32)(total / (1 << 30)); start_addr = 0; mv_xor_init2(cs); @@ -194,7 +194,7 @@ static void dram_ecc_scrubbing(void) size -= start_addr; } - mv_xor_mem_init(SCRB_XOR_CHAN, start_addr, size, + mv_xor_mem_init(SCRB_XOR_CHAN, start_addr, size - 1, SCRUB_MAGIC, SCRUB_MAGIC); /* Wait for previous transfer completion */ @@ -216,6 +216,35 @@ static int ecc_enabled(void) return 0; } + +/* Return the width of the DRAM bus, or 0 for unknown. */ +static int bus_width(void) +{ + int full_width = 0; + + if (reg_read(REG_SDRAM_CONFIG_ADDR) & (1 << REG_SDRAM_CONFIG_WIDTH_OFFS)) + full_width = 1; + + switch (mvebu_soc_family()) { + case MVEBU_SOC_AXP: + return full_width ? 64 : 32; + break; + case MVEBU_SOC_A375: + case MVEBU_SOC_A38X: + case MVEBU_SOC_MSYS: + return full_width ? 32 : 16; + default: + return 0; + } +} + +static int cycle_mode(void) +{ + int val = reg_read(REG_DUNIT_CTRL_LOW_ADDR); + + return (val >> REG_DUNIT_CTRL_LOW_2T_OFFS) & REG_DUNIT_CTRL_LOW_2T_MASK; +} + #else static void dram_ecc_scrubbing(void) { @@ -295,10 +324,26 @@ int dram_init_banksize(void) void board_add_ram_info(int use_default) { struct sar_freq_modes sar_freq; + int mode; + int width; get_sar_freq(&sar_freq); printf(" (%d MHz, ", sar_freq.d_clk); + width = bus_width(); + if (width) + printf("%d-bit, ", width); + + mode = cycle_mode(); + /* Mode 0 = Single cycle + * Mode 1 = Two cycles (2T) + * Mode 2 = Three cycles (3T) + */ + if (mode == 1) + printf("2T, "); + if (mode == 2) + printf("3T, "); + if (ecc_enabled()) printf("ECC"); else diff --git a/arch/arm/mach-mvebu/include/mach/config.h b/arch/arm/mach-mvebu/include/mach/config.h index 2dc9b1dea3..cfd0952470 100644 --- a/arch/arm/mach-mvebu/include/mach/config.h +++ b/arch/arm/mach-mvebu/include/mach/config.h @@ -76,9 +76,6 @@ */ #ifdef CONFIG_CMD_NET #define CONFIG_MII /* expose smi ove miiphy interface */ -#if !defined(CONFIG_ARMADA_375) -#define CONFIG_MVNETA /* Enable Marvell Gbe Controller Driver */ -#endif #define CONFIG_ENV_OVERWRITE /* ethaddr can be reprogrammed */ #define CONFIG_ARP_TIMEOUT 200 #define CONFIG_NET_RETRY_COUNT 50 diff --git a/arch/arm/mach-mvebu/include/mach/cpu.h b/arch/arm/mach-mvebu/include/mach/cpu.h index d241eea956..b67b77ae0d 100644 --- a/arch/arm/mach-mvebu/include/mach/cpu.h +++ b/arch/arm/mach-mvebu/include/mach/cpu.h @@ -65,6 +65,7 @@ enum { MVEBU_SOC_AXP, MVEBU_SOC_A375, MVEBU_SOC_A38X, + MVEBU_SOC_MSYS, MVEBU_SOC_UNKNOWN, }; diff --git a/arch/arm/mach-mvebu/include/mach/soc.h b/arch/arm/mach-mvebu/include/mach/soc.h index 0900e4008c..1d302761f0 100644 --- a/arch/arm/mach-mvebu/include/mach/soc.h +++ b/arch/arm/mach-mvebu/include/mach/soc.h @@ -18,6 +18,9 @@ #define SOC_88F6810_ID 0x6810 #define SOC_88F6820_ID 0x6820 #define SOC_88F6828_ID 0x6828 +#define SOC_98DX3236_ID 0xf410 +#define SOC_98DX3336_ID 0xf400 +#define SOC_98DX4251_ID 0xfc00 /* A375 revisions */ #define MV_88F67XX_A0_ID 0x3 @@ -139,6 +142,7 @@ #define BOOT_DEV_SEL_MASK (0x3f << BOOT_DEV_SEL_OFFS) #define BOOT_FROM_UART 0x28 +#define BOOT_FROM_UART_ALT 0x3f #define BOOT_FROM_SPI 0x32 #define BOOT_FROM_MMC 0x30 #define BOOT_FROM_MMC_ALT 0x31 diff --git a/arch/arm/mach-mvebu/spl.c b/arch/arm/mach-mvebu/spl.c index 3cf02a54ce..a72a769f7c 100644 --- a/arch/arm/mach-mvebu/spl.c +++ b/arch/arm/mach-mvebu/spl.c @@ -42,6 +42,9 @@ static u32 get_boot_device(void) return BOOT_DEVICE_MMC1; #endif case BOOT_FROM_UART: +#ifdef BOOT_FROM_UART_ALT + case BOOT_FROM_UART_ALT: +#endif return BOOT_DEVICE_UART; case BOOT_FROM_SPI: default: diff --git a/arch/arm/mach-omap2/am33xx/mux.c b/arch/arm/mach-omap2/am33xx/mux.c index 2ded47228d..aad3ec8556 100644 --- a/arch/arm/mach-omap2/am33xx/mux.c +++ b/arch/arm/mach-omap2/am33xx/mux.c @@ -31,3 +31,17 @@ void configure_module_pin_mux(struct module_pin_mux *mod_pin_mux) for (i = 0; mod_pin_mux[i].reg_offset != -1; i++) MUX_CFG(mod_pin_mux[i].val, mod_pin_mux[i].reg_offset); } + +/* + * provide a default over-writable definition +*/ +void __weak set_uart_mux_conf(void) +{ +} + +/* +* provide a default over-writable definition +*/ +void __weak set_mux_conf_regs(void) +{ +} diff --git a/arch/arm/mach-omap2/omap3/Kconfig b/arch/arm/mach-omap2/omap3/Kconfig index 11f5f058b9..4dbf9a27da 100644 --- a/arch/arm/mach-omap2/omap3/Kconfig +++ b/arch/arm/mach-omap2/omap3/Kconfig @@ -22,6 +22,11 @@ choice config TARGET_AM3517_EVM bool "AM3517 EVM" + select DM + select DM_SERIAL + select DM_GPIO + select DM_I2C + select DM_MMC config TARGET_MT_VENTOUX bool "TeeJet Mt.Ventoux" diff --git a/arch/arm/mach-omap2/sec-common.c b/arch/arm/mach-omap2/sec-common.c index 52e1785b4a..2630e7d316 100644 --- a/arch/arm/mach-omap2/sec-common.c +++ b/arch/arm/mach-omap2/sec-common.c @@ -41,6 +41,9 @@ #define PPA_SERV_HAL_SETUP_EMIF_FW_REGION (PPA_HAL_SERVICES_START_INDEX + 26) #define PPA_SERV_HAL_LOCK_EMIF_FW (PPA_HAL_SERVICES_START_INDEX + 27) +/* Offset of header size if image is signed as ISW */ +#define HEADER_SIZE_OFFSET (0x6D) + int tee_loaded = 0; /* Argument for PPA_SERV_HAL_TEE_LOAD_MASTER */ @@ -125,6 +128,9 @@ int secure_boot_verify_image(void **image, size_t *size) } *size = sig_addr - cert_addr; /* Subtract out the signature size */ + /* Subtract header if present */ + if (strncmp((char *)sig_addr, "CERT_ISW_", 9) == 0) + *size = ((u32 *)*image)[HEADER_SIZE_OFFSET]; cert_size = *size; /* Check if image load address is 32-bit aligned */ diff --git a/arch/arm/mach-rockchip/rk322x-board.c b/arch/arm/mach-rockchip/rk322x-board.c index c0ac2e9b56..dcd8cf805f 100644 --- a/arch/arm/mach-rockchip/rk322x-board.c +++ b/arch/arm/mach-rockchip/rk322x-board.c @@ -7,6 +7,7 @@ #include <clk.h> #include <dm.h> #include <ram.h> +#include <syscon.h> #include <asm/io.h> #include <asm/arch/clock.h> #include <asm/arch/periph.h> @@ -67,6 +68,14 @@ int board_init(void) CON_IOMUX_UART2SEL_MASK, CON_IOMUX_UART2SEL_21 << CON_IOMUX_UART2SEL_SHIFT); + /* + * The integrated macphy is enabled by default, disable it + * for saving power consuming. + */ + rk_clrsetreg(&grf->macphy_con[0], + MACPHY_CFG_ENABLE_MASK, + 0 << MACPHY_CFG_ENABLE_SHIFT); + return 0; } @@ -136,3 +145,17 @@ int board_usb_cleanup(int index, enum usb_init_type init) return 0; } #endif + +#if defined(CONFIG_USB_FUNCTION_FASTBOOT) +int fb_set_reboot_flag(void) +{ + struct rk322x_grf *grf; + + printf("Setting reboot to fastboot flag ...\n"); + grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); + /* Set boot mode to fastboot */ + writel(BOOT_FASTBOOT, &grf->os_reg[0]); + + return 0; +} +#endif diff --git a/arch/arm/mach-rockchip/rk3288/Kconfig b/arch/arm/mach-rockchip/rk3288/Kconfig index 53cc9a0dcd..4ad2940069 100644 --- a/arch/arm/mach-rockchip/rk3288/Kconfig +++ b/arch/arm/mach-rockchip/rk3288/Kconfig @@ -84,6 +84,15 @@ config TARGET_POPMETAL_RK3288 2GB DDR3. Expansion connectors provide access to I2C, SPI, UART, GPIOs and display interface. +config TARGET_VYASA_RK3288 + bool "Vyasa-RK3288" + select BOARD_LATE_INIT + help + Vyasa is a RK3288-based development board with 2 USB ports, + HDMI, VGA, micro-SD card, audio, WiFi and Gigabit Ethernet, It + also includes on-board eMMC and 2GB of SDRAM. Expansion connectors + provide access to display pins, I2C, SPI, UART and GPIOs. + config TARGET_ROCK2 bool "Radxa Rock 2" select BOARD_LATE_INIT @@ -129,6 +138,8 @@ config SPL_LIBGENERIC_SUPPORT config SPL_SERIAL_SUPPORT default y +source "board/amarula/vyasa-rk3288/Kconfig" + source "board/chipspark/popmetal_rk3288/Kconfig" source "board/firefly/firefly-rk3288/Kconfig" diff --git a/arch/arm/mach-rockchip/rk3399-board-spl.c b/arch/arm/mach-rockchip/rk3399-board-spl.c index d6bf74f7ad..3406156447 100644 --- a/arch/arm/mach-rockchip/rk3399-board-spl.c +++ b/arch/arm/mach-rockchip/rk3399-board-spl.c @@ -5,19 +5,17 @@ */ #include <common.h> -#include <debug_uart.h> -#include <dm.h> -#include <ram.h> -#include <spl.h> -#include <asm/gpio.h> -#include <asm/io.h> #include <asm/arch/clock.h> +#include <asm/arch/grf_rk3399.h> #include <asm/arch/hardware.h> #include <asm/arch/periph.h> -#include <asm/arch/sdram.h> -#include <asm/arch/timer.h> +#include <asm/io.h> +#include <debug_uart.h> +#include <dm.h> #include <dm/pinctrl.h> -#include <power/regulator.h> +#include <ram.h> +#include <spl.h> +#include <syscon.h> DECLARE_GLOBAL_DATA_PTR; @@ -53,7 +51,6 @@ void secure_timer_init(void) void board_debug_uart_init(void) { -#include <asm/arch/grf_rk3399.h> #define GRF_BASE 0xff770000 struct rk3399_grf_regs * const grf = (void *)GRF_BASE; @@ -80,13 +77,12 @@ void board_debug_uart_init(void) #endif } -#define GRF_EMMCCORE_CON11 0xff77f02c -#define SGRF_DDR_RGN_CON16 0xff330040 -#define SGRF_SLV_SECURE_CON4 0xff33e3d0 void board_init_f(ulong dummy) { struct udevice *pinctrl; struct udevice *dev; + struct rk3399_pmusgrf_regs *sgrf; + struct rk3399_grf_regs *grf; int ret; #define EARLY_UART @@ -103,9 +99,6 @@ void board_init_f(ulong dummy) printascii("U-Boot SPL board init"); #endif - /* Emmc clock generator: disable the clock multipilier */ - rk_clrreg(GRF_EMMCCORE_CON11, 0x0ff); - ret = spl_early_init(); if (ret) { debug("spl_early_init() failed: %d\n", ret); @@ -121,8 +114,13 @@ void board_init_f(ulong dummy) * driver, which tries to DMA from/to the stack (likely) * located in this range. */ - rk_clrsetreg(SGRF_DDR_RGN_CON16, 0x1FF, 0); - rk_clrreg(SGRF_SLV_SECURE_CON4, 0x2000); + sgrf = syscon_get_first_range(ROCKCHIP_SYSCON_PMUSGRF); + rk_clrsetreg(&sgrf->ddr_rgn_con[16], 0x1ff, 0); + rk_clrreg(&sgrf->slv_secure_con4, 0x2000); + + /* eMMC clock generator: disable the clock multipilier */ + grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); + rk_clrreg(&grf->emmccore_con[11], 0x0ff); secure_timer_init(); diff --git a/arch/arm/mach-rockchip/rk3399/sdram_rk3399.c b/arch/arm/mach-rockchip/rk3399/sdram_rk3399.c index 63342ab5c9..5ed4b03837 100644 --- a/arch/arm/mach-rockchip/rk3399/sdram_rk3399.c +++ b/arch/arm/mach-rockchip/rk3399/sdram_rk3399.c @@ -1115,7 +1115,7 @@ static int conv_of_platdata(struct udevice *dev) int ret; ret = regmap_init_mem_platdata(dev, dtplat->reg, - ARRAY_SIZE(dtplat->reg) / 4, + ARRAY_SIZE(dtplat->reg) / 2, &plat->map); if (ret) return ret; diff --git a/arch/arm/mach-socfpga/misc_gen5.c b/arch/arm/mach-socfpga/misc_gen5.c index 2f1da740fb..91ddb79f73 100644 --- a/arch/arm/mach-socfpga/misc_gen5.c +++ b/arch/arm/mach-socfpga/misc_gen5.c @@ -144,7 +144,7 @@ static const struct { const u16 pn; const char *name; const char *var; -} const socfpga_fpga_model[] = { +} socfpga_fpga_model[] = { /* Cyclone V E */ { 0x2b15, "Cyclone V, E/A2", "cv_e_a2" }, { 0x2b05, "Cyclone V, E/A4", "cv_e_a4" }, diff --git a/arch/arm/mach-stm32/Kconfig b/arch/arm/mach-stm32/Kconfig index 947ce5f1ce..b618b60795 100644 --- a/arch/arm/mach-stm32/Kconfig +++ b/arch/arm/mach-stm32/Kconfig @@ -25,7 +25,24 @@ config STM32F7 select SPL_SYS_MALLOC_SIMPLE select SPL_XIP_SUPPORT +config STM32H7 + bool "stm32h7 family" + select CLK + select DM_GPIO + select DM_RESET + select MISC + select PINCTRL + select PINCTRL_STM32 + select RAM + select REGMAP + select STM32_SDRAM + select STM32_RCC + select STM32_RESET + select STM32X7_SERIAL + select SYSCON + source "arch/arm/mach-stm32/stm32f4/Kconfig" source "arch/arm/mach-stm32/stm32f7/Kconfig" +source "arch/arm/mach-stm32/stm32h7/Kconfig" endif diff --git a/arch/arm/mach-stm32/Makefile b/arch/arm/mach-stm32/Makefile index 6b7694471f..0f5ac37168 100644 --- a/arch/arm/mach-stm32/Makefile +++ b/arch/arm/mach-stm32/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_STM32F4) += stm32f4/ obj-$(CONFIG_STM32F7) += stm32f7/ +obj-$(CONFIG_STM32H7) += stm32h7/ diff --git a/arch/arm/mach-stm32/stm32h7/Kconfig b/arch/arm/mach-stm32/stm32h7/Kconfig new file mode 100644 index 0000000000..55e6217950 --- /dev/null +++ b/arch/arm/mach-stm32/stm32h7/Kconfig @@ -0,0 +1,12 @@ +if STM32H7 + +config TARGET_STM32H743_DISCO + bool "STM32H743 Discovery board" + +config TARGET_STM32H743_EVAL + bool "STM32H743 Evaluation board" + +source "board/st/stm32h743-eval/Kconfig" +source "board/st/stm32h743-disco/Kconfig" + +endif diff --git a/arch/arm/mach-stm32/stm32h7/Makefile b/arch/arm/mach-stm32/stm32h7/Makefile new file mode 100644 index 0000000000..97f92f74ca --- /dev/null +++ b/arch/arm/mach-stm32/stm32h7/Makefile @@ -0,0 +1,8 @@ +# +# Copyright (c) 2017 +# Patrice Chotard <patrice.chotard@st.com> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += soc.o diff --git a/arch/arm/mach-stm32/stm32h7/soc.c b/arch/arm/mach-stm32/stm32h7/soc.c new file mode 100644 index 0000000000..a65fab6d2e --- /dev/null +++ b/arch/arm/mach-stm32/stm32h7/soc.c @@ -0,0 +1,59 @@ +/* + * Copyright (C) STMicroelectronics SA 2017 + * Author(s): Patrice CHOTARD, <patrice.chotard@st.com> for STMicroelectronics. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/armv7m_mpu.h> + +u32 get_cpu_rev(void) +{ + return 0; +} + +int arch_cpu_init(void) +{ + int i; + + struct mpu_region_config stm32_region_config[] = { + /* + * Make all 4GB cacheable & executable. We are overriding it + * with next region for any requirement. e.g. below region1, + * 2 etc. + * In other words, the area not coming in following + * regions configuration is the one configured here in region_0 + * (cacheable & executable). + */ + { 0x00000000, REGION_0, XN_DIS, PRIV_RW_USR_RW, + O_I_WB_RD_WR_ALLOC, REGION_4GB }, + + /* Code area, executable & strongly ordered */ + { 0xD0000000, REGION_1, XN_EN, PRIV_RW_USR_RW, + STRONG_ORDER, REGION_8MB }, + + /* Device area in all H7 : Not executable */ + { 0x40000000, REGION_2, XN_EN, PRIV_RW_USR_RW, + DEVICE_NON_SHARED, REGION_512MB }, + + /* + * Armv7m fixed configuration: strongly ordered & not + * executable, not cacheable + */ + { 0xE0000000, REGION_4, XN_EN, PRIV_RW_USR_RW, + STRONG_ORDER, REGION_512MB }, + }; + + disable_mpu(); + for (i = 0; i < ARRAY_SIZE(stm32_region_config); i++) + mpu_config(&stm32_region_config[i]); + enable_mpu(); + + return 0; +} + +void s_init(void) +{ +} diff --git a/arch/arm/mach-uniphier/Kconfig b/arch/arm/mach-uniphier/Kconfig index ee22112412..c8b5ab4d32 100644 --- a/arch/arm/mach-uniphier/Kconfig +++ b/arch/arm/mach-uniphier/Kconfig @@ -12,18 +12,14 @@ config ARCH_UNIPHIER_32BIT choice prompt "UniPhier SoC select" - default ARCH_UNIPHIER_PRO4 + default ARCH_UNIPHIER_V8_MULTI config ARCH_UNIPHIER_LD4_SLD8 bool "UniPhier LD4/sLD8 SoCs" select ARCH_UNIPHIER_32BIT -config ARCH_UNIPHIER_PRO4 - bool "UniPhier Pro4 SoC" - select ARCH_UNIPHIER_32BIT - -config ARCH_UNIPHIER_PRO5_PXS2_LD6B - bool "UniPhier Pro5/PXs2/LD6b SoCs" +config ARCH_UNIPHIER_V7_MULTI + bool "UniPhier Pro4/Pro5/PXs2/LD6b SoCs" select ARCH_UNIPHIER_32BIT config ARCH_UNIPHIER_V8_MULTI @@ -44,19 +40,24 @@ config ARCH_UNIPHIER_SLD8 depends on ARCH_UNIPHIER_LD4_SLD8 default y +config ARCH_UNIPHIER_PRO4 + bool "Enable UniPhier Pro4 SoC support" + depends on ARCH_UNIPHIER_V7_MULTI + default y + config ARCH_UNIPHIER_PRO5 bool "Enable UniPhier Pro5 SoC support" - depends on ARCH_UNIPHIER_PRO5_PXS2_LD6B + depends on ARCH_UNIPHIER_V7_MULTI default y config ARCH_UNIPHIER_PXS2 bool "Enable UniPhier Pxs2 SoC support" - depends on ARCH_UNIPHIER_PRO5_PXS2_LD6B + depends on ARCH_UNIPHIER_V7_MULTI default y config ARCH_UNIPHIER_LD6B bool "Enable UniPhier LD6b SoC support" - depends on ARCH_UNIPHIER_PRO5_PXS2_LD6B + depends on ARCH_UNIPHIER_V7_MULTI default y config ARCH_UNIPHIER_LD11 diff --git a/arch/arm/mach-uniphier/clk/clk-ld11.c b/arch/arm/mach-uniphier/clk/clk-ld11.c index 0266e7e66b..a4b7419e54 100644 --- a/arch/arm/mach-uniphier/clk/clk-ld11.c +++ b/arch/arm/mach-uniphier/clk/clk-ld11.c @@ -40,7 +40,7 @@ void uniphier_ld11_clk_init(void) int ch; tmp = readl(SC_CLKCTRL4); - tmp |= SC_CLKCTRL4_MIO | SC_CLKCTRL4_STDMAC; + tmp |= BIT(10) | BIT(8); /* MIO, STDMAC */ writel(tmp, SC_CLKCTRL4); for (ch = 0; ch < 3; ch++) { diff --git a/arch/arm/mach-uniphier/clk/clk-ld20.c b/arch/arm/mach-uniphier/clk/clk-ld20.c index 5bb560cafe..f79fb38535 100644 --- a/arch/arm/mach-uniphier/clk/clk-ld20.c +++ b/arch/arm/mach-uniphier/clk/clk-ld20.c @@ -4,14 +4,26 @@ * SPDX-License-Identifier: GPL-2.0+ */ +#include <linux/bitops.h> #include <linux/io.h> #include "../init.h" +#include "../sc64-regs.h" #define SDCTRL_EMMC_HW_RESET 0x59810280 void uniphier_ld20_clk_init(void) { + u32 tmp; + + tmp = readl(SC_RSTCTRL6); + tmp |= BIT(8); /* Mali */ + writel(tmp, SC_RSTCTRL6); + + tmp = readl(SC_CLKCTRL6); + tmp |= BIT(8); /* Mali */ + writel(tmp, SC_CLKCTRL6); + /* TODO: use "mmc-pwrseq-emmc" */ writel(1, SDCTRL_EMMC_HW_RESET); } diff --git a/arch/arm/mach-uniphier/clk/clk-pxs3.c b/arch/arm/mach-uniphier/clk/clk-pxs3.c index 2dee857a18..3b9cc626f1 100644 --- a/arch/arm/mach-uniphier/clk/clk-pxs3.c +++ b/arch/arm/mach-uniphier/clk/clk-pxs3.c @@ -4,14 +4,26 @@ * SPDX-License-Identifier: GPL-2.0+ */ +#include <linux/bitops.h> #include <linux/io.h> #include "../init.h" +#include "../sc64-regs.h" #define SDCTRL_EMMC_HW_RESET 0x59810280 void uniphier_pxs3_clk_init(void) { + u32 tmp; + + tmp = readl(SC_RSTCTRL6); + tmp |= BIT(8); /* Mali */ + writel(tmp, SC_RSTCTRL6); + + tmp = readl(SC_CLKCTRL6); + tmp |= BIT(8); /* Mali */ + writel(tmp, SC_CLKCTRL6); + /* TODO: use "mmc-pwrseq-emmc" */ writel(1, SDCTRL_EMMC_HW_RESET); } diff --git a/arch/arm/mach-uniphier/sc64-regs.h b/arch/arm/mach-uniphier/sc64-regs.h index d0a51f239c..80efb4e4e3 100644 --- a/arch/arm/mach-uniphier/sc64-regs.h +++ b/arch/arm/mach-uniphier/sc64-regs.h @@ -15,34 +15,16 @@ #define SC_RSTCTRL (SC_BASE_ADDR | 0x2000) #define SC_RSTCTRL3 (SC_BASE_ADDR | 0x2008) #define SC_RSTCTRL4 (SC_BASE_ADDR | 0x200c) -#define SC_RSTCTRL4_ETHER (1 << 6) -#define SC_RSTCTRL4_NAND (1 << 0) #define SC_RSTCTRL5 (SC_BASE_ADDR | 0x2010) #define SC_RSTCTRL6 (SC_BASE_ADDR | 0x2014) #define SC_RSTCTRL7 (SC_BASE_ADDR | 0x2018) -#define SC_RSTCTRL7_UMCSB (1 << 16) -#define SC_RSTCTRL7_UMCA2 (1 << 10) -#define SC_RSTCTRL7_UMCA1 (1 << 9) -#define SC_RSTCTRL7_UMCA0 (1 << 8) -#define SC_RSTCTRL7_UMC32 (1 << 2) -#define SC_RSTCTRL7_UMC31 (1 << 1) -#define SC_RSTCTRL7_UMC30 (1 << 0) #define SC_CLKCTRL (SC_BASE_ADDR | 0x2100) #define SC_CLKCTRL3 (SC_BASE_ADDR | 0x2108) #define SC_CLKCTRL4 (SC_BASE_ADDR | 0x210c) -#define SC_CLKCTRL4_MIO (1 << 10) -#define SC_CLKCTRL4_STDMAC (1 << 8) -#define SC_CLKCTRL4_PERI (1 << 7) -#define SC_CLKCTRL4_ETHER (1 << 6) -#define SC_CLKCTRL4_NAND (1 << 0) #define SC_CLKCTRL5 (SC_BASE_ADDR | 0x2110) #define SC_CLKCTRL6 (SC_BASE_ADDR | 0x2114) #define SC_CLKCTRL7 (SC_BASE_ADDR | 0x2118) -#define SC_CLKCTRL7_UMCSB (1 << 16) -#define SC_CLKCTRL7_UMC32 (1 << 2) -#define SC_CLKCTRL7_UMC31 (1 << 1) -#define SC_CLKCTRL7_UMC30 (1 << 0) #define SC_CA72_GEARST (SC_BASE_ADDR | 0x8000) #define SC_CA72_GEARSET (SC_BASE_ADDR | 0x8004) diff --git a/arch/nds32/cpu/n1213/start.S b/arch/nds32/cpu/n1213/start.S index f9f999902c..0d98d03fc3 100644 --- a/arch/nds32/cpu/n1213/start.S +++ b/arch/nds32/cpu/n1213/start.S @@ -119,19 +119,46 @@ set_ivb: /* set IVIC, vector size: 4 bytes, base: 0x0 */ mtsr $r0, $ivb /* - * MMU_CTL NTC0 Cacheable/Write-Back + * MMU_CTL NTC0 Non-cacheable */ + li $r0, ~0x6 + mfsr $r1, $mr0 + and $r1, $r1, $r0 + mtsr $r1, $mr0 + li $r0, ~0x3 mfsr $r1, $mr8 and $r1, $r1, $r0 mtsr $r1, $mr8 #if (!defined(CONFIG_SYS_ICACHE_OFF) || !defined(CONFIG_SYS_DCACHE_OFF)) +/* + * MMU_CTL NTC0 Cacheable/Write-Back + */ li $r0, 0x4 mfsr $r1, $mr0 or $r1, $r1, $r0 mtsr $r1, $mr0 #endif +#ifndef CONFIG_SYS_DCACHE_OFF +#ifdef CONFIG_ARCH_MAP_SYSMEM +/* + * MMU_CTL NTC1 Non-cacheable + */ + li $r0, ~0x18 + mfsr $r1, $mr0 + and $r1, $r1, $r0 + mtsr $r1, $mr0 +/* + * MMU_CTL NTM1 mapping for partition 0 + */ + li $r0, ~0x6000 + mfsr $r1, $mr0 + and $r1, $r1, $r0 + mtsr $r1, $mr0 +#endif +#endif + #if !defined(CONFIG_SYS_ICACHE_OFF) li $r0, 0x1 mfsr $r1, $mr8 diff --git a/arch/nds32/dts/ae3xx.dts b/arch/nds32/dts/ae3xx.dts index 4221e4bf9a..fbe6d74437 100644 --- a/arch/nds32/dts/ae3xx.dts +++ b/arch/nds32/dts/ae3xx.dts @@ -8,6 +8,7 @@ aliases { uart0 = &serial0; ethernet0 = &mac0; + spi0 = &spi; } ; chosen { @@ -22,6 +23,12 @@ reg = <0x00000000 0x40000000>; }; + spiclk: virt_100mhz { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <100000000>; + }; + cpus { #address-cells = <1>; #size-cells = <0>; @@ -69,4 +76,20 @@ device-width = <1>; }; + spi: spi@f0b00000 { + compatible = "andestech,atcspi200"; + reg = <0xf0b00000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + num-cs = <1>; + clocks = <&spiclk>; + interrupts = <3 4>; + flash@0 { + compatible = "spi-flash"; + spi-max-frequency = <50000000>; + reg = <0>; + spi-cpol; + spi-cpha; + }; + }; }; diff --git a/arch/nds32/include/asm/bootm.h b/arch/nds32/include/asm/bootm.h index 6b10c078df..2e2fe01f0e 100644 --- a/arch/nds32/include/asm/bootm.h +++ b/arch/nds32/include/asm/bootm.h @@ -11,6 +11,8 @@ #ifndef NDS32_BOOTM_H #define NDS32_BOOTM_H +#include <asm/setup.h> + extern void udc_disconnect(void); #if defined(CONFIG_SETUP_MEMORY_TAGS) || \ diff --git a/arch/nds32/include/asm/io.h b/arch/nds32/include/asm/io.h index b2c4d0ef8c..25ef9a46c6 100644 --- a/arch/nds32/include/asm/io.h +++ b/arch/nds32/include/asm/io.h @@ -48,6 +48,27 @@ static inline void sync(void) #define MAP_WRBACK (0) #define MAP_WRTHROUGH (0) +#ifdef CONFIG_ARCH_MAP_SYSMEM +static inline void *map_sysmem(phys_addr_t paddr, unsigned long len) +{ + if(paddr <PHYS_SDRAM_0_SIZE + PHYS_SDRAM_1_SIZE) + paddr = paddr | 0x40000000; + return (void *)(uintptr_t)paddr; +} + +static inline void *unmap_sysmem(const void *vaddr) +{ + phys_addr_t paddr = (phys_addr_t)vaddr; + paddr = paddr & ~0x40000000; + return (void *)(uintptr_t)paddr; +} + +static inline phys_addr_t map_to_sysmem(const void *ptr) +{ + return (phys_addr_t)(uintptr_t)ptr; +} +#endif + static inline void * map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags) { @@ -104,26 +125,26 @@ extern void __raw_readsl(unsigned int addr, void *data, int longlen); #define __iormb() dmb() #define __iowmb() dmb() -static inline void writeb(unsigned char val, unsigned char *addr) +static inline void writeb(u8 val, volatile void __iomem *addr) { __iowmb(); __arch_putb(val, addr); } -static inline void writew(unsigned short val, unsigned short *addr) +static inline void writew(u16 val, volatile void __iomem *addr) { __iowmb(); __arch_putw(val, addr); } -static inline void writel(unsigned int val, unsigned int *addr) +static inline void writel(u32 val, volatile void __iomem *addr) { __iowmb(); __arch_putl(val, addr); } -static inline unsigned char readb(unsigned char *addr) +static inline u8 readb(const volatile void __iomem *addr) { u8 val; @@ -132,7 +153,7 @@ static inline unsigned char readb(unsigned char *addr) return val; } -static inline unsigned short readw(unsigned short *addr) +static inline u16 readw(const volatile void __iomem *addr) { u16 val; @@ -141,7 +162,7 @@ static inline unsigned short readw(unsigned short *addr) return val; } -static inline unsigned int readl(unsigned int *addr) +static inline u32 readl(const volatile void __iomem *addr) { u32 val; diff --git a/arch/nds32/lib/bootm.c b/arch/nds32/lib/bootm.c index e834329e0b..42b15dfcbf 100644 --- a/arch/nds32/lib/bootm.c +++ b/arch/nds32/lib/bootm.c @@ -12,7 +12,6 @@ #include <u-boot/zlib.h> #include <asm/byteorder.h> #include <asm/bootm.h> -#include <asm/setup.h> DECLARE_GLOBAL_DATA_PTR; diff --git a/board/AndesTech/adp-ae3xx/adp-ae3xx.c b/board/AndesTech/adp-ae3xx/adp-ae3xx.c index 98ed4d9589..8cffb6ba8b 100644 --- a/board/AndesTech/adp-ae3xx/adp-ae3xx.c +++ b/board/AndesTech/adp-ae3xx/adp-ae3xx.c @@ -6,6 +6,7 @@ * SPDX-License-Identifier: GPL-2.0+ */ +#include <asm/mach-types.h> #include <common.h> #if defined(CONFIG_FTMAC100) && !defined(CONFIG_DM_ETH) #include <netdev.h> diff --git a/board/amarula/vyasa-rk3288/Kconfig b/board/amarula/vyasa-rk3288/Kconfig new file mode 100644 index 0000000000..8b8c30835e --- /dev/null +++ b/board/amarula/vyasa-rk3288/Kconfig @@ -0,0 +1,12 @@ +if TARGET_VYASA_RK3288 + +config SYS_BOARD + default "vyasa-rk3288" + +config SYS_VENDOR + default "amarula" + +config SYS_CONFIG_NAME + default "vyasa-rk3288" + +endif diff --git a/board/amarula/vyasa-rk3288/MAINTAINERS b/board/amarula/vyasa-rk3288/MAINTAINERS new file mode 100644 index 0000000000..10397fcb4b --- /dev/null +++ b/board/amarula/vyasa-rk3288/MAINTAINERS @@ -0,0 +1,6 @@ +VYASA RK3288 +M: Jagan Teki <jagan@amarulasolutions.com> +S: Maintained +F: board/amarula/vyasa-rk3288 +F: include/configs/vyasa-rk3288.h +F: configs/vyasa-rk3288_defconfig diff --git a/board/amarula/vyasa-rk3288/Makefile b/board/amarula/vyasa-rk3288/Makefile new file mode 100644 index 0000000000..7c0d5c0316 --- /dev/null +++ b/board/amarula/vyasa-rk3288/Makefile @@ -0,0 +1,7 @@ +# +# Copyright (C) 2017 Amarula Solutions +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += vyasa-rk3288.o diff --git a/board/amarula/vyasa-rk3288/vyasa-rk3288.c b/board/amarula/vyasa-rk3288/vyasa-rk3288.c new file mode 100644 index 0000000000..ceee42c16e --- /dev/null +++ b/board/amarula/vyasa-rk3288/vyasa-rk3288.c @@ -0,0 +1,7 @@ +/* + * Copyright (C) 2017 Amarula Solutions + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> diff --git a/board/bachmann/ot1200/ot1200_spl.c b/board/bachmann/ot1200/ot1200_spl.c index 9d28da4ba4..f3dff95710 100644 --- a/board/bachmann/ot1200/ot1200_spl.c +++ b/board/bachmann/ot1200/ot1200_spl.c @@ -151,10 +151,4 @@ void board_init_f(ulong dummy) /* configure MMDC for SDRAM width/size and per-model calibration */ ot1200_spl_dram_init(); - - /* Clear the BSS. */ - memset(__bss_start, 0, __bss_end - __bss_start); - - /* load/boot image from boot device */ - board_init_r(NULL, 0); } diff --git a/board/compulab/cm_fx6/spl.c b/board/compulab/cm_fx6/spl.c index bba977ff8e..56aac60239 100644 --- a/board/compulab/cm_fx6/spl.c +++ b/board/compulab/cm_fx6/spl.c @@ -336,9 +336,6 @@ void board_init_f(ulong dummy) puts("!!!ERROR!!! DRAM detection failed!!!\n"); hang(); } - - memset(__bss_start, 0, __bss_end - __bss_start); - board_init_r(NULL, 0); } void board_boot_order(u32 *spl_boot_list) diff --git a/board/davinci/da8xxevm/Kconfig b/board/davinci/da8xxevm/Kconfig index bb1188b4ea..e0df97ca0e 100644 --- a/board/davinci/da8xxevm/Kconfig +++ b/board/davinci/da8xxevm/Kconfig @@ -33,6 +33,8 @@ config MAC_ADDR_IN_EEPROM endif +source "board/ti/common/Kconfig" + endif if TARGET_OMAPL138_LCDK diff --git a/board/davinci/da8xxevm/da850evm.c b/board/davinci/da8xxevm/da850evm.c index 516d86df50..83c9f2940f 100644 --- a/board/davinci/da8xxevm/da850evm.c +++ b/board/davinci/da8xxevm/da850evm.c @@ -60,7 +60,7 @@ static int get_mac_addr(u8 *addr) return -1; } - ret = spi_flash_read(flash, CFG_MAC_ADDR_OFFSET, 6, addr); + ret = spi_flash_read(flash, (CFG_MAC_ADDR_OFFSET) + 1, 7, addr); if (ret) { printf("Error - unable to read MAC address from SPI flash.\n"); return -1; @@ -140,6 +140,7 @@ int misc_init_r(void) uchar buff[6]; spi_mac_read = get_mac_addr(buff); + buff[0] = 0; /* * MAC address not present in the environment diff --git a/board/engicam/common/spl.c b/board/engicam/common/spl.c index 6964c131d9..8711418fb4 100644 --- a/board/engicam/common/spl.c +++ b/board/engicam/common/spl.c @@ -384,10 +384,4 @@ void board_init_f(ulong dummy) /* DDR initialization */ spl_dram_init(); - - /* Clear the BSS. */ - memset(__bss_start, 0, __bss_end - __bss_start); - - /* load/boot image from boot device */ - board_init_r(NULL, 0); } diff --git a/board/freescale/ls2080ardb/ls2080ardb.c b/board/freescale/ls2080ardb/ls2080ardb.c index 666562d106..827bfad521 100644 --- a/board/freescale/ls2080ardb/ls2080ardb.c +++ b/board/freescale/ls2080ardb/ls2080ardb.c @@ -251,6 +251,8 @@ int misc_init_r(void) char *env_hwconfig; u32 __iomem *dcfg_ccsr = (u32 __iomem *)DCFG_BASE; u32 val; + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + u32 svr = gur_in32(&gur->svr); val = in_le32(dcfg_ccsr + DCFG_RCWSR13 / 4); @@ -278,6 +280,16 @@ int misc_init_r(void) if (adjust_vdd(0)) printf("Warning: Adjusting core voltage failed.\n"); + /* + * Default value of board env is based on filename which is + * ls2080ardb. Modify board env for other supported SoCs + */ + if ((SVR_SOC_VER(svr) == SVR_LS2088A) || + (SVR_SOC_VER(svr) == SVR_LS2048A)) + env_set("board", "ls2088ardb"); + else if ((SVR_SOC_VER(svr) == SVR_LS2081A) || + (SVR_SOC_VER(svr) == SVR_LS2041A)) + env_set("board", "ls2081ardb"); return 0; } diff --git a/board/freescale/mx7dsabresd/mx7dsabresd.c b/board/freescale/mx7dsabresd/mx7dsabresd.c index a681ecef3a..5819b1825d 100644 --- a/board/freescale/mx7dsabresd/mx7dsabresd.c +++ b/board/freescale/mx7dsabresd/mx7dsabresd.c @@ -260,7 +260,7 @@ static int setup_fec(void) (IOMUXC_GPR_GPR1_GPR_ENET1_TX_CLK_SEL_MASK | IOMUXC_GPR_GPR1_GPR_ENET1_CLK_DIR_MASK), 0); - return set_clk_enet(ENET_125MHz); + return set_clk_enet(ENET_125MHZ); } diff --git a/board/gateworks/gw_ventana/gw_ventana_spl.c b/board/gateworks/gw_ventana/gw_ventana_spl.c index c2e370ba0b..bdbe5e7027 100644 --- a/board/gateworks/gw_ventana/gw_ventana_spl.c +++ b/board/gateworks/gw_ventana/gw_ventana_spl.c @@ -626,9 +626,6 @@ void board_init_f(ulong dummy) spl_dram_init(8 << ventana_info.sdram_width, 16 << ventana_info.sdram_size, board_model); - - /* Clear the BSS. */ - memset(__bss_start, 0, __bss_end - __bss_start); } void board_boot_order(u32 *spl_boot_list) diff --git a/board/ge/bx50v3/Makefile b/board/ge/bx50v3/Makefile index bcd149f5b0..2fff27bc77 100644 --- a/board/ge/bx50v3/Makefile +++ b/board/ge/bx50v3/Makefile @@ -5,4 +5,4 @@ # SPDX-License-Identifier: GPL-2.0+ # -obj-y := bx50v3.o +obj-y := bx50v3.o vpd_reader.o diff --git a/board/ge/bx50v3/bx50v3.c b/board/ge/bx50v3/bx50v3.c index b25c634bb5..c7df4ce847 100644 --- a/board/ge/bx50v3/bx50v3.c +++ b/board/ge/bx50v3/bx50v3.c @@ -26,8 +26,19 @@ #include <asm/arch/sys_proto.h> #include <i2c.h> #include <pwm.h> +#include <stdlib.h> +#include "vpd_reader.h" DECLARE_GLOBAL_DATA_PTR; +#ifndef CONFIG_SYS_I2C_EEPROM_ADDR +# define CONFIG_SYS_I2C_EEPROM_ADDR 0x50 +# define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 1 +#endif + +#ifndef CONFIG_SYS_I2C_EEPROM_BUS +#define CONFIG_SYS_I2C_EEPROM_BUS 2 +#endif + #define NC_PAD_CTRL (PAD_CTL_PUS_100K_UP | \ PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | \ PAD_CTL_HYS) @@ -528,6 +539,102 @@ int overwrite_console(void) return 1; } +#define VPD_TYPE_INVALID 0x00 +#define VPD_BLOCK_NETWORK 0x20 +#define VPD_BLOCK_HWID 0x44 +#define VPD_PRODUCT_B850 1 +#define VPD_PRODUCT_B650 2 +#define VPD_PRODUCT_B450 3 + +struct vpd_cache { + uint8_t product_id; + uint8_t macbits; + unsigned char mac1[6]; +}; + +/* + * Extracts MAC and product information from the VPD. + */ +static int vpd_callback( + void *userdata, + uint8_t id, + uint8_t version, + uint8_t type, + size_t size, + uint8_t const *data) +{ + struct vpd_cache *vpd = (struct vpd_cache *)userdata; + + if ( id == VPD_BLOCK_HWID + && version == 1 + && type != VPD_TYPE_INVALID + && size >= 1) { + vpd->product_id = data[0]; + + } else if ( id == VPD_BLOCK_NETWORK + && version == 1 + && type != VPD_TYPE_INVALID + && size >= 6) { + vpd->macbits |= 1; + memcpy(vpd->mac1, data, 6); + } + + return 0; +} + +static void set_eth0_mac_address(unsigned char * mac) +{ + uint32_t *ENET_TCR = (uint32_t*)0x21880c4; + uint32_t *ENET_PALR = (uint32_t*)0x21880e4; + uint32_t *ENET_PAUR = (uint32_t*)0x21880e8; + + *ENET_TCR |= 0x100; /* ADDINS */ + *ENET_PALR |= (mac[0] << 24) | (mac[1] << 16) | (mac[2] << 8) | mac[3]; + *ENET_PAUR |= (mac[4] << 24) | (mac[5] << 16); +} + +static void process_vpd(struct vpd_cache *vpd) +{ + if ( vpd->product_id == VPD_PRODUCT_B850 + || vpd->product_id == VPD_PRODUCT_B650 + || vpd->product_id == VPD_PRODUCT_B450) { + if (vpd->macbits & 1) { + set_eth0_mac_address(vpd->mac1); + } + } +} + +static int read_vpd(uint eeprom_bus) +{ + struct vpd_cache vpd; + int res; + int size = 1024; + uint8_t *data; + unsigned int current_i2c_bus = i2c_get_bus_num(); + + res = i2c_set_bus_num(eeprom_bus); + if (res < 0) + return res; + + data = (uint8_t *)malloc(size); + if (!data) + return -ENOMEM; + + res = i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, 0, + CONFIG_SYS_I2C_EEPROM_ADDR_LEN, data, size); + + if (res == 0) { + memset(&vpd, 0, sizeof(vpd)); + vpd_reader(size, data, &vpd, vpd_callback); + process_vpd(&vpd); + } + + free(data); + + i2c_set_bus_num(current_i2c_bus); + return res; +} + int board_eth_init(bd_t *bis) { setup_iomux_enet(); @@ -586,6 +693,8 @@ int board_init(void) setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info2); setup_i2c(3, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info3); + read_vpd(CONFIG_SYS_I2C_EEPROM_BUS); + return 0; } diff --git a/board/ge/bx50v3/vpd_reader.c b/board/ge/bx50v3/vpd_reader.c new file mode 100644 index 0000000000..98da893d2c --- /dev/null +++ b/board/ge/bx50v3/vpd_reader.c @@ -0,0 +1,228 @@ +/* + * Copyright 2016 General Electric Company + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include "vpd_reader.h" + +#include <linux/bch.h> +#include <stdlib.h> + + +/* BCH configuration */ + +const struct { + int header_ecc_capability_bits; + int data_ecc_capability_bits; + unsigned int prim_poly; + struct { + int min; + int max; + } galois_field_order; +} bch_configuration = { + .header_ecc_capability_bits = 4, + .data_ecc_capability_bits = 16, + .prim_poly = 0, + .galois_field_order = { + .min = 5, + .max = 15, + }, +}; + +static int calculate_galois_field_order(size_t source_length) +{ + int gfo = bch_configuration.galois_field_order.min; + + for (; gfo < bch_configuration.galois_field_order.max && + ((((1 << gfo) - 1) - ((int)source_length * 8)) < 0); + gfo++) { + } + + if (gfo == bch_configuration.galois_field_order.max) { + return -1; + } + + return gfo + 1; +} + +static int verify_bch(int ecc_bits, unsigned int prim_poly, + uint8_t * data, size_t data_length, + const uint8_t * ecc, size_t ecc_length) +{ + int gfo = calculate_galois_field_order(data_length); + if (gfo < 0) { + return -1; + } + + struct bch_control * bch = init_bch(gfo, ecc_bits, prim_poly); + if (!bch) { + return -1; + } + + if (bch->ecc_bytes != ecc_length) { + free_bch(bch); + return -1; + } + + unsigned * errloc = (unsigned *)calloc(data_length, sizeof(unsigned)); + int errors = decode_bch( + bch, data, data_length, ecc, NULL, NULL, errloc); + free_bch(bch); + if (errors < 0) { + free(errloc); + return -1; + } + + if (errors > 0) { + for (int n = 0; n < errors; n++) { + if (errloc[n] >= 8 * data_length) { + /* n-th error located in ecc (no need for data correction) */ + } else { + /* n-th error located in data */ + data[errloc[n] / 8] ^= 1 << (errloc[n] % 8); + } + } + } + + free(errloc); + return 0; +} + + +static const int ID = 0; +static const int LEN = 1; +static const int VER = 2; +static const int TYP = 3; +static const int BLOCK_SIZE = 4; + +static const uint8_t HEADER_BLOCK_ID = 0x00; +static const uint8_t HEADER_BLOCK_LEN = 18; +static const uint32_t HEADER_BLOCK_MAGIC = 0xca53ca53; +static const size_t HEADER_BLOCK_VERIFY_LEN = 14; +static const size_t HEADER_BLOCK_ECC_OFF = 14; +static const size_t HEADER_BLOCK_ECC_LEN = 4; + +static const uint8_t ECC_BLOCK_ID = 0xFF; + +int vpd_reader( + size_t size, + uint8_t * data, + void * userdata, + int (*fn)( + void * userdata, + uint8_t id, + uint8_t version, + uint8_t type, + size_t size, + uint8_t const * data)) +{ + if ( size < HEADER_BLOCK_LEN + || data == NULL + || fn == NULL) { + return -EINVAL; + } + + /* + * +--------------------+--------------------+--//--+--------------------+ + * | header block | data block | ... | ecc block | + * +--------------------+--------------------+--//--+--------------------+ + * : : : + * +------+-------+-----+ +------+-------------+ + * | id | magic | ecc | | ... | ecc | + * | len | off | | +------+-------------+ + * | ver | size | | : + * | type | | | : + * +------+-------+-----+ : + * : : : : + * <----- [1] ----> <----------- [2] -----------> + * + * Repair (if necessary) the contents of header block [1] by using a + * 4 byte ECC located at the end of the header block. A successful + * return value means that we can trust the header. + */ + int ret = verify_bch( + bch_configuration.header_ecc_capability_bits, + bch_configuration.prim_poly, + data, + HEADER_BLOCK_VERIFY_LEN, + &data[HEADER_BLOCK_ECC_OFF], + HEADER_BLOCK_ECC_LEN); + if (ret < 0) { + return ret; + } + + /* Validate header block { id, length, version, type }. */ + if ( data[ID] != HEADER_BLOCK_ID + || data[LEN] != HEADER_BLOCK_LEN + || data[VER] != 0 + || data[TYP] != 0 + || ntohl(*(uint32_t *)(&data[4])) != HEADER_BLOCK_MAGIC) { + return -EINVAL; + } + + uint32_t offset = ntohl(*(uint32_t *)(&data[8])); + uint16_t size_bits = ntohs(*(uint16_t *)(&data[12])); + + /* Check that ECC header fits. */ + if (offset + 3 >= size) { + return -EINVAL; + } + + /* Validate ECC block. */ + uint8_t * ecc = &data[offset]; + if ( ecc[ID] != ECC_BLOCK_ID + || ecc[LEN] < BLOCK_SIZE + || ecc[LEN] + offset > size + || ecc[LEN] - BLOCK_SIZE != size_bits / 8 + || ecc[VER] != 1 + || ecc[TYP] != 1) { + return -EINVAL; + } + + /* + * Use the header block to locate the ECC block and verify the data + * blocks [2] against the ecc block ECC. + */ + ret = verify_bch( + bch_configuration.data_ecc_capability_bits, + bch_configuration.prim_poly, + &data[data[LEN]], + offset - data[LEN], + &data[offset + BLOCK_SIZE], + ecc[LEN] - BLOCK_SIZE); + if (ret < 0) { + return ret; + } + + /* Stop after ECC. Ignore possible zero padding. */ + size = offset; + + for (;;) { + /* Move to next block. */ + size -= data[LEN]; + data += data[LEN]; + + if (size == 0) { + /* Finished iterating through blocks. */ + return 0; + } + + if ( size < BLOCK_SIZE + || data[LEN] < BLOCK_SIZE) { + /* Not enough data for a header, or short header. */ + return -EINVAL; + } + + ret = fn( + userdata, + data[ID], + data[VER], + data[TYP], + data[LEN] - BLOCK_SIZE, + &data[BLOCK_SIZE]); + if (ret) { + return ret; + } + } +} diff --git a/board/ge/bx50v3/vpd_reader.h b/board/ge/bx50v3/vpd_reader.h new file mode 100644 index 0000000000..efa172a915 --- /dev/null +++ b/board/ge/bx50v3/vpd_reader.h @@ -0,0 +1,25 @@ +/* + * Copyright 2016 General Electric Company + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include "common.h" + +/* + * Read VPD from given data, verify content, and call callback + * for each vital product data block. + * + * Returns Non-zero on error. Negative numbers encode errno. + */ +int vpd_reader( + size_t size, + uint8_t * data, + void * userdata, + int (*fn)( + void * userdata, + uint8_t id, + uint8_t version, + uint8_t type, + size_t size, + uint8_t const * data)); diff --git a/board/kosagi/novena/novena_spl.c b/board/kosagi/novena/novena_spl.c index 512f06da76..b4a68da88f 100644 --- a/board/kosagi/novena/novena_spl.c +++ b/board/kosagi/novena/novena_spl.c @@ -596,10 +596,4 @@ void board_init_f(ulong dummy) udelay(100); mmdc_do_write_level_calibration(&novena_ddr_info); mmdc_do_dqs_calibration(&novena_ddr_info); - - /* Clear the BSS. */ - memset(__bss_start, 0, __bss_end - __bss_start); - - /* load/boot image from boot device */ - board_init_r(NULL, 0); } diff --git a/board/liebherr/mccmon6/spl.c b/board/liebherr/mccmon6/spl.c index a2f804db8f..196da46df9 100644 --- a/board/liebherr/mccmon6/spl.c +++ b/board/liebherr/mccmon6/spl.c @@ -296,11 +296,5 @@ void board_init_f(ulong dummy) /* DDR initialization */ spl_dram_init(); - - /* Clear the BSS. */ - memset(__bss_start, 0, __bss_end - __bss_start); - - /* load/boot image from boot device */ - board_init_r(NULL, 0); } #endif diff --git a/board/logicpd/am3517evm/am3517evm.c b/board/logicpd/am3517evm/am3517evm.c index c18a5a3140..29f136a530 100644 --- a/board/logicpd/am3517evm/am3517evm.c +++ b/board/logicpd/am3517evm/am3517evm.c @@ -12,6 +12,8 @@ */ #include <common.h> +#include <dm.h> +#include <ns16550.h> #include <asm/io.h> #include <asm/omap_musb.h> #include <asm/arch/am35x_def.h> @@ -34,6 +36,22 @@ DECLARE_GLOBAL_DATA_PTR; #define AM3517_IP_SW_RESET 0x48002598 #define CPGMACSS_SW_RST (1 << 1) +#define PHY_GPIO 30 + +/* This is only needed until SPL gets OF support */ +#ifdef CONFIG_SPL_BUILD +static const struct ns16550_platdata am3517_serial = { + .base = OMAP34XX_UART3, + .reg_shift = 2, + .clock = V_NS16550_CLK, + .fcr = UART_FCR_DEFVAL, +}; + +U_BOOT_DEVICE(am3517_uart) = { + "ns16550_serial", + &am3517_serial +}; +#endif /* * Routine: board_init @@ -113,30 +131,35 @@ int misc_init_r(void) am3517_evm_musb_init(); - /* activate PHY reset */ - gpio_direction_output(30, 0); - gpio_set_value(30, 0); - - ctr = 0; - do { - udelay(1000); - ctr++; - } while (ctr < 300); - - /* deactivate PHY reset */ - gpio_set_value(30, 1); - - /* allow the PHY to stabilize and settle down */ - ctr = 0; - do { - udelay(1000); - ctr++; - } while (ctr < 300); - - /* ensure that the module is out of reset */ - reset = readl(AM3517_IP_SW_RESET); - reset &= (~CPGMACSS_SW_RST); - writel(reset,AM3517_IP_SW_RESET); + if (gpio_request(PHY_GPIO, "gpio_30") == 0) { + /* activate PHY reset */ + gpio_direction_output(PHY_GPIO, 0); + gpio_set_value(PHY_GPIO, 0); + + ctr = 0; + do { + udelay(1000); + ctr++; + } while (ctr < 300); + + /* deactivate PHY reset */ + gpio_set_value(PHY_GPIO, 1); + + /* allow the PHY to stabilize and settle down */ + ctr = 0; + do { + udelay(1000); + ctr++; + } while (ctr < 300); + + /* ensure that the module is out of reset */ + reset = readl(AM3517_IP_SW_RESET); + reset &= (~CPGMACSS_SW_RST); + writel(reset, AM3517_IP_SW_RESET); + + /* Free requested GPIO */ + gpio_free(PHY_GPIO); + } return 0; } diff --git a/board/solidrun/clearfog/README b/board/solidrun/clearfog/README index 2cfa5bfc86..ef1e3bf426 100644 --- a/board/solidrun/clearfog/README +++ b/board/solidrun/clearfog/README @@ -16,3 +16,23 @@ $ sudo dd if=u-boot-spl.kwb of=/dev/sdX bs=512 seek=1 Please use the correct device node for your setup instead of "/dev/sdX" here! + +Boot from UART: +--------------- + +Connect the on-board micro-USB (CF Pro: CON11, CF Base: CON5) +to your host. + +Set the SW1 DIP switches to UART boot (0: OFF, 1: ON): + + ClearFog Base: 01001 + ClearFog Pro: 11110 + +Run the following command to initiate U-Boot download: + + ./tools/kwboot -b u-boot-spl.kwb /dev/ttyUSBX + +Use the correct UART device node for /dev/ttyUSBX. + +When download finishes start your favorite terminal emulator +on /dev/ttyUSBX. diff --git a/board/solidrun/mx6cuboxi/mx6cuboxi.c b/board/solidrun/mx6cuboxi/mx6cuboxi.c index 986abc5772..1e4da4a6b1 100644 --- a/board/solidrun/mx6cuboxi/mx6cuboxi.c +++ b/board/solidrun/mx6cuboxi/mx6cuboxi.c @@ -349,6 +349,7 @@ static bool is_hummingboard(void) * Machine selection - * Machine val1, val2 * ------------------------- + * HB2 x x * HB rev 3.x x 0 * CBi 0 1 * HB 1 1 @@ -362,9 +363,37 @@ static bool is_hummingboard(void) return true; } +static bool is_hummingboard2(void) +{ + int val1; + + SETUP_IOMUX_PADS(hb_cbi_sense); + + gpio_direction_input(IMX_GPIO_NR(2, 8)); + + val1 = gpio_get_value(IMX_GPIO_NR(2, 8)); + + /* + * Machine selection - + * Machine val1 + * ------------------- + * HB2 0 + * HB rev 3.x x + * CBi x + * HB x + */ + + if (val1 == 0) + return true; + else + return false; +} + int checkboard(void) { - if (is_hummingboard()) + if (is_hummingboard2()) + puts("Board: MX6 Hummingboard2\n"); + else if (is_hummingboard()) puts("Board: MX6 Hummingboard\n"); else puts("Board: MX6 Cubox-i\n"); @@ -375,7 +404,9 @@ int checkboard(void) int board_late_init(void) { #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG - if (is_hummingboard()) + if (is_hummingboard2()) + env_set("board_name", "HUMMINGBOARD2"); + else if (is_hummingboard()) env_set("board_name", "HUMMINGBOARD"); else env_set("board_name", "CUBOXI"); diff --git a/board/st/stih410-b2260/board.c b/board/st/stih410-b2260/board.c index 92b0695593..d6cbbb866a 100644 --- a/board/st/stih410-b2260/board.c +++ b/board/st/stih410-b2260/board.c @@ -7,6 +7,10 @@ */ #include <common.h> +#include <linux/usb/otg.h> +#include <dwc3-sti-glue.h> +#include <dwc3-uboot.h> +#include <usb.h> DECLARE_GLOBAL_DATA_PTR; @@ -36,3 +40,41 @@ int board_init(void) { return 0; } + +#ifdef CONFIG_USB_DWC3 +static struct dwc3_device dwc3_device_data = { + .maximum_speed = USB_SPEED_HIGH, + .dr_mode = USB_DR_MODE_PERIPHERAL, + .index = 0, +}; + +int usb_gadget_handle_interrupts(int index) +{ + dwc3_uboot_handle_interrupt(index); + return 0; +} + +int board_usb_init(int index, enum usb_init_type init) +{ + int node; + const void *blob = gd->fdt_blob; + + /* find the snps,dwc3 node */ + node = fdt_node_offset_by_compatible(blob, -1, "snps,dwc3"); + + dwc3_device_data.base = fdtdec_get_addr(blob, node, "reg"); + + return dwc3_uboot_init(&dwc3_device_data); +} + +int board_usb_cleanup(int index, enum usb_init_type init) +{ + dwc3_uboot_exit(index); + return 0; +} + +int g_dnl_board_usb_cable_connected(void) +{ + return 1; +} +#endif diff --git a/board/st/stm32h743-disco/Kconfig b/board/st/stm32h743-disco/Kconfig new file mode 100644 index 0000000000..7d6ec1d958 --- /dev/null +++ b/board/st/stm32h743-disco/Kconfig @@ -0,0 +1,19 @@ +if TARGET_STM32H743_DISCO + +config SYS_BOARD + string + default "stm32h743-disco" + +config SYS_VENDOR + string + default "st" + +config SYS_SOC + string + default "stm32h7" + +config SYS_CONFIG_NAME + string + default "stm32h743-disco" + +endif diff --git a/board/st/stm32h743-disco/MAINTAINERS b/board/st/stm32h743-disco/MAINTAINERS new file mode 100644 index 0000000000..e5e0b5a6f2 --- /dev/null +++ b/board/st/stm32h743-disco/MAINTAINERS @@ -0,0 +1,7 @@ +STM32H743 DISCOVERY BOARD +M: Patrice Chotard <patrice.chotard@st.com> +S: Maintained +F: board/st/stm32h743-disco +F: include/configs/stm32h743-disco.h +F: configs/stm32h743-disco_defconfig +F: arch/arm/dts/stm32h7* diff --git a/board/st/stm32h743-disco/Makefile b/board/st/stm32h743-disco/Makefile new file mode 100644 index 0000000000..778fe1c97f --- /dev/null +++ b/board/st/stm32h743-disco/Makefile @@ -0,0 +1,8 @@ +# +# Copyright (C) STMicroelectronics SA 2017 +# Author(s): Patrice CHOTARD, <patrice.chotard@st.com> for STMicroelectronics.# +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y := stm32h743-disco.o diff --git a/board/st/stm32h743-disco/stm32h743-disco.c b/board/st/stm32h743-disco/stm32h743-disco.c new file mode 100644 index 0000000000..625b3a077b --- /dev/null +++ b/board/st/stm32h743-disco/stm32h743-disco.c @@ -0,0 +1,56 @@ +/* + * Copyright (C) STMicroelectronics SA 2017 + * Author(s): Patrice CHOTARD, <patrice.chotard@st.com> for STMicroelectronics. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> + +DECLARE_GLOBAL_DATA_PTR; + +int dram_init(void) +{ + struct udevice *dev; + int ret; + + ret = uclass_get_device(UCLASS_RAM, 0, &dev); + if (ret) { + debug("DRAM init failed: %d\n", ret); + return ret; + } + + if (fdtdec_setup_memory_size() != 0) + ret = -EINVAL; + + return ret; +} + +int dram_init_banksize(void) +{ + fdtdec_setup_memory_banksize(); + + return 0; +} + +int board_early_init_f(void) +{ + return 0; +} + +u32 get_board_rev(void) +{ + return 0; +} + +int board_late_init(void) +{ + return 0; +} + +int board_init(void) +{ + gd->bd->bi_boot_params = gd->bd->bi_dram[0].start + 0x100; + return 0; +} diff --git a/board/st/stm32h743-eval/Kconfig b/board/st/stm32h743-eval/Kconfig new file mode 100644 index 0000000000..ea879b13c8 --- /dev/null +++ b/board/st/stm32h743-eval/Kconfig @@ -0,0 +1,19 @@ +if TARGET_STM32H743_EVAL + +config SYS_BOARD + string + default "stm32h743-eval" + +config SYS_VENDOR + string + default "st" + +config SYS_SOC + string + default "stm32h7" + +config SYS_CONFIG_NAME + string + default "stm32h743-eval" + +endif diff --git a/board/st/stm32h743-eval/MAINTAINERS b/board/st/stm32h743-eval/MAINTAINERS new file mode 100644 index 0000000000..3029c56023 --- /dev/null +++ b/board/st/stm32h743-eval/MAINTAINERS @@ -0,0 +1,6 @@ +STM32H743 EVALUATION BOARD +M: Patrice Chotard <patrice.chotard@st.com> +S: Maintained +F: board/st/stm32h743-eval +F: include/configs/stm32h743-eval.h +F: configs/stm32h743-eval_defconfig diff --git a/board/st/stm32h743-eval/Makefile b/board/st/stm32h743-eval/Makefile new file mode 100644 index 0000000000..4f25b2d96b --- /dev/null +++ b/board/st/stm32h743-eval/Makefile @@ -0,0 +1,8 @@ +# +# (C) Copyright 2017 +# Patrice Chotard, <patrice.chotard@st.com> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y := stm32h743-eval.o diff --git a/board/st/stm32h743-eval/stm32h743-eval.c b/board/st/stm32h743-eval/stm32h743-eval.c new file mode 100644 index 0000000000..625b3a077b --- /dev/null +++ b/board/st/stm32h743-eval/stm32h743-eval.c @@ -0,0 +1,56 @@ +/* + * Copyright (C) STMicroelectronics SA 2017 + * Author(s): Patrice CHOTARD, <patrice.chotard@st.com> for STMicroelectronics. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> + +DECLARE_GLOBAL_DATA_PTR; + +int dram_init(void) +{ + struct udevice *dev; + int ret; + + ret = uclass_get_device(UCLASS_RAM, 0, &dev); + if (ret) { + debug("DRAM init failed: %d\n", ret); + return ret; + } + + if (fdtdec_setup_memory_size() != 0) + ret = -EINVAL; + + return ret; +} + +int dram_init_banksize(void) +{ + fdtdec_setup_memory_banksize(); + + return 0; +} + +int board_early_init_f(void) +{ + return 0; +} + +u32 get_board_rev(void) +{ + return 0; +} + +int board_late_init(void) +{ + return 0; +} + +int board_init(void) +{ + gd->bd->bi_boot_params = gd->bd->bi_dram[0].start + 0x100; + return 0; +} diff --git a/board/technexion/pico-imx7d/README b/board/technexion/pico-imx7d/README index a2805ee080..8af4effa78 100644 --- a/board/technexion/pico-imx7d/README +++ b/board/technexion/pico-imx7d/README @@ -47,3 +47,20 @@ Remove power from the pico board. Put pico board into normal boot mode. Power up the board and the new updated U-Boot should boot from eMMC. + +Building U-Boot to boot with NXP 4.1 kernel: + +The NXP 4.1 kernel boots only in secure boot mode on mx7. + +Follow the next steps to enable secure boot: + +$ make mrproper +$ make pico-imx7d_defconfig +$ make menuconfig + -> ARM architecture + -> [*] Enable support for booting in non-secure mode + -> [*] Boot in secure mode by default + -> Exit +$ make + +Flash u-boot.imx using the imx_usb_loader tool. diff --git a/board/technexion/pico-imx7d/pico-imx7d.c b/board/technexion/pico-imx7d/pico-imx7d.c index b4c9be7378..67bab51dfd 100644 --- a/board/technexion/pico-imx7d/pico-imx7d.c +++ b/board/technexion/pico-imx7d/pico-imx7d.c @@ -182,7 +182,7 @@ static int setup_fec(void) (IOMUXC_GPR_GPR1_GPR_ENET1_TX_CLK_SEL_MASK | IOMUXC_GPR_GPR1_GPR_ENET1_CLK_DIR_MASK), 0); - return set_clk_enet(ENET_125MHz); + return set_clk_enet(ENET_125MHZ); } int board_phy_config(struct phy_device *phydev) diff --git a/board/theadorable/MAINTAINERS b/board/theadorable/MAINTAINERS index 5ae6b6487c..1e8df93d37 100644 --- a/board/theadorable/MAINTAINERS +++ b/board/theadorable/MAINTAINERS @@ -4,4 +4,3 @@ S: Maintained F: board/theadorable/ F: include/configs/theadorable.h F: configs/theadorable_debug_defconfig -F: configs/theadorable_defconfig diff --git a/board/theobroma-systems/lion_rk3368/README b/board/theobroma-systems/lion_rk3368/README index 47304fcba6..83e4332984 100644 --- a/board/theobroma-systems/lion_rk3368/README +++ b/board/theobroma-systems/lion_rk3368/README @@ -26,12 +26,32 @@ Build the full U-Boot and a FIT image including the ATF > make CROSS_COMPILE=aarch64-unknown-elf- ARCH=arm u-boot.itb -Write to a SD-card -================== +Flash the image +=============== + +Copy the SPL to offset 32k and the FIT image containing the payloads +(U-Boot proper, ATF, devicetree) to offset 256k card. + +SD-Card +------- > dd if=spl-3368.img of=/dev/sdb seek=64 > dd if=u-boot.itb of=/dev/sdb seek=512 +eMMC +---- + +rkdeveloptool allows to flash the on-board eMMC via the USB OTG interface with +help of the Rockchip loader binary. + + > git clone https://github.com/rockchip-linux/rkdeveloptool + > cd rkdeveloptool + > autoreconf -i && && ./configure && make + > git clone https://github.com/rockchip-linux/rkbin.git + > ./rkdeveloptool db rkbin/rk33/rk3368_loader_v2.00.256.bin + > ./rkdeveloptool wl 64 ../spl.img + > ./rkdeveloptool wl 512 ../u-boot.itb + If everything went according to plan, you should see the following output on UART0: diff --git a/board/theobroma-systems/puma_rk3399/README b/board/theobroma-systems/puma_rk3399/README index 214281a329..f67dfb451f 100644 --- a/board/theobroma-systems/puma_rk3399/README +++ b/board/theobroma-systems/puma_rk3399/README @@ -55,18 +55,53 @@ Compile the U-Boot Package the image ================= - > tools/mkimage -n rk3399 -T rksd -d spl/u-boot-spl.bin spl.img - > make CROSS_COMPILE=aarch64-linux-gnu- u-boot.itb +Creating a SPL image for SD-Card/eMMC + > tools/mkimage -n rk3399 -T rksd -d spl/u-boot-spl.bin spl_mmc.img +Creating a SPL image for SPI-NOR + > tools/mkimage -n rk3399 -T rkspi -d spl/u-boot-spl.bin spl_nor.img +Create the FIT image containing U-Boot proper, ATF, M0 Firmware, devicetree + > make CROSS_COMPILE=aarch64-linux-gnu- u-boot.itb Flash the image =============== -Copy the SPL to offset 32k and the FIT image containing the payloads -(U-Boot proper, ATF, M0 Firmware, devicetree) to offset 256k on a SD -card. +Copy the SPL to offset 32k for SD/eMMC, offset 0 for NOR-Flash and the FIT +image to offset 256k card. - > dd if=spl.img of=/dev/sdb seek=64 +SD-Card +------- + + > dd if=spl_mmc.img of=/dev/sdb seek=64 > dd if=u-boot.itb of=/dev/sdb seek=512 -After powering up the board (with the inserted SD card), you should see -a U-Boot console on UART0 (115200n8). +eMMC +---- + +rkdeveloptool allows to flash the on-board eMMC via the USB OTG interface with +help of the Rockchip loader binary. + + > git clone https://github.com/rockchip-linux/rkdeveloptool + > cd rkdeveloptool + > autoreconf -i && ./configure && make + > git clone https://github.com/rockchip-linux/rkbin.git + > ./rkdeveloptool db rkbin/rk33/rk3399_loader_v1.08.106.bin + > ./rkdeveloptool wl 64 ../spl_mmc.img + > ./rkdeveloptool wl 512 ../u-boot.itb + +NOR-Flash +--------- + +Writing the SPI NOR Flash requires a running U-Boot. For the sake of simplicity +we assume you have a SD-Card with a partition containing the required files +ready. + + > load mmc 1:1 ${kernel_addr_r} spl_nor.img + > sf probe + > sf erase 0 +$filesize + > sf write $kernel_addr_r 0 ${filesize} + > load mmc 1:1 ${kernel_addr_r} u-boot.itb + > sf erase 0x40000 +$filesize + > sf write $kernel_addr_r 0x40000 ${filesize} + + +Reboot the system and you should see a U-Boot console on UART0 (115200n8). diff --git a/board/theobroma-systems/puma_rk3399/puma-rk3399.c b/board/theobroma-systems/puma_rk3399/puma-rk3399.c index c6f8eed0c9..45d56cd99e 100644 --- a/board/theobroma-systems/puma_rk3399/puma-rk3399.c +++ b/board/theobroma-systems/puma_rk3399/puma-rk3399.c @@ -107,7 +107,7 @@ static void setup_serial(void) u8 low[cpuid_length/2], high[cpuid_length/2]; char cpuid_str[cpuid_length * 2 + 1]; u64 serialno; - char serialno_str[16]; + char serialno_str[17]; /* retrieve the device */ ret = uclass_get_device_by_driver(UCLASS_MISC, diff --git a/board/toradex/apalis_imx6/apalis_imx6.c b/board/toradex/apalis_imx6/apalis_imx6.c index ebc6c12cbc..628a61dae0 100644 --- a/board/toradex/apalis_imx6/apalis_imx6.c +++ b/board/toradex/apalis_imx6/apalis_imx6.c @@ -29,7 +29,6 @@ #include <dm/platform_data/serial_mxc.h> #include <dm/platdata.h> #include <fsl_esdhc.h> -#include <g_dnl.h> #include <i2c.h> #include <imx_thermal.h> #include <linux/errno.h> @@ -1224,18 +1223,6 @@ void reset_cpu(ulong addr) { } -#ifdef CONFIG_SPL_USB_GADGET_SUPPORT -int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name) -{ - unsigned short usb_pid; - - usb_pid = TORADEX_USB_PRODUCT_NUM_OFFSET + 0xfff; - put_unaligned(usb_pid, &dev->idProduct); - - return 0; -} -#endif - #endif static struct mxc_serial_platdata mxc_serial_plat = { diff --git a/board/toradex/colibri_imx6/colibri_imx6.c b/board/toradex/colibri_imx6/colibri_imx6.c index 669d9123ca..756e3f39df 100644 --- a/board/toradex/colibri_imx6/colibri_imx6.c +++ b/board/toradex/colibri_imx6/colibri_imx6.c @@ -28,7 +28,6 @@ #include <dm/platform_data/serial_mxc.h> #include <dm/platdata.h> #include <fsl_esdhc.h> -#include <g_dnl.h> #include <i2c.h> #include <imx_thermal.h> #include <linux/errno.h> @@ -1108,18 +1107,6 @@ void reset_cpu(ulong addr) { } -#ifdef CONFIG_SPL_USB_GADGET_SUPPORT -int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name) -{ - unsigned short usb_pid; - - usb_pid = TORADEX_USB_PRODUCT_NUM_OFFSET + 0xfff; - put_unaligned(usb_pid, &dev->idProduct); - - return 0; -} -#endif - #endif static struct mxc_serial_platdata mxc_serial_plat = { diff --git a/board/toradex/colibri_imx7/colibri_imx7.c b/board/toradex/colibri_imx7/colibri_imx7.c index 5cb14b43de..13b2b5785b 100644 --- a/board/toradex/colibri_imx7/colibri_imx7.c +++ b/board/toradex/colibri_imx7/colibri_imx7.c @@ -280,7 +280,7 @@ static int setup_fec(void) IOMUXC_GPR_GPR1_GPR_ENET1_TX_CLK_SEL_MASK); #endif - return set_clk_enet(ENET_50MHz); + return set_clk_enet(ENET_50MHZ); } int board_phy_config(struct phy_device *phydev) diff --git a/board/udoo/udoo_spl.c b/board/udoo/udoo_spl.c index 3645969e43..694055bd2e 100644 --- a/board/udoo/udoo_spl.c +++ b/board/udoo/udoo_spl.c @@ -252,11 +252,5 @@ void board_init_f(ulong dummy) /* DDR initialization */ spl_dram_init(); - - /* Clear the BSS. */ - memset(__bss_start, 0, __bss_end - __bss_start); - - /* load/boot image from boot device */ - board_init_r(NULL, 0); } #endif diff --git a/board/wandboard/spl.c b/board/wandboard/spl.c index 99a02865ec..00c75d0682 100644 --- a/board/wandboard/spl.c +++ b/board/wandboard/spl.c @@ -300,11 +300,5 @@ void board_init_f(ulong dummy) /* DDR initialization */ spl_dram_init(); - - /* Clear the BSS. */ - memset(__bss_start, 0, __bss_end - __bss_start); - - /* load/boot image from boot device */ - board_init_r(NULL, 0); } #endif @@ -190,10 +190,9 @@ static void del_gpt_info(void) static struct disk_part *allocate_disk_part(disk_partition_t *info, int partnum) { struct disk_part *newpart; - newpart = malloc(sizeof(*newpart)); + newpart = calloc(1, sizeof(struct disk_part)); if (!newpart) return ERR_PTR(-ENOMEM); - memset(newpart, '\0', sizeof(newpart)); newpart->gpt_part_info.start = info->start; newpart->gpt_part_info.size = info->size; diff --git a/common/Makefile b/common/Makefile index 1b56cf9a70..801ea3191f 100644 --- a/common/Makefile +++ b/common/Makefile @@ -63,7 +63,7 @@ obj-$(CONFIG_CMDLINE) += cli_readline.o cli_simple.o endif # !CONFIG_SPL_BUILD -obj-$(CONFIG_$(SPL_)BOOTSTAGE) += bootstage.o +obj-$(CONFIG_$(SPL_TPL_)BOOTSTAGE) += bootstage.o ifdef CONFIG_SPL_BUILD obj-$(CONFIG_SPL_DFU_SUPPORT) += dfu.o diff --git a/common/spl/Kconfig b/common/spl/Kconfig index b05ec21ed6..0bd8370337 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -94,6 +94,7 @@ config SPL_STACK_R config SPL_STACK_R_ADDR depends on SPL_STACK_R hex "SDRAM location for SPL stack" + default 0x82000000 if ARCH_OMAP2PLUS help Specify the address in SDRAM for the SPL stack. This will be set up before board_init_r() is called. diff --git a/common/spl/spl.c b/common/spl/spl.c index ce9819e4db..4afbe97fc1 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -424,13 +424,6 @@ void board_init_r(gd_t *dummy1, ulong dummy2) debug("SPL malloc() used %#lx bytes (%ld KB)\n", gd->malloc_ptr, gd->malloc_ptr / 1024); #endif - - if (CONFIG_IS_ENABLED(ATF_SUPPORT)) { - debug("loaded - jumping to U-Boot via ATF BL31.\n"); - bl31_entry(); - } - - debug("loaded - jumping to U-Boot...\n"); #ifdef CONFIG_BOOTSTAGE_STASH int ret; @@ -440,6 +433,13 @@ void board_init_r(gd_t *dummy1, ulong dummy2) if (ret) debug("Failed to stash bootstage: err=%d\n", ret); #endif + + if (CONFIG_IS_ENABLED(ATF_SUPPORT)) { + debug("loaded - jumping to U-Boot via ATF BL31.\n"); + bl31_entry(); + } + + debug("loaded - jumping to U-Boot...\n"); spl_board_prepare_for_boot(); jump_to_image_no_args(&spl_image); } diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index 49ccf1c17b..32d9ee5901 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -135,6 +135,7 @@ static int spl_load_fit_image(struct spl_load_info *info, ulong sector, int offset; size_t length; int len; + ulong size; ulong load_addr, load_ptr; void *src; ulong overhead; @@ -197,11 +198,13 @@ static int spl_load_fit_image(struct spl_load_info *info, ulong sector, IS_ENABLED(CONFIG_SPL_GZIP) && image_comp == IH_COMP_GZIP && type == IH_TYPE_KERNEL) { + size = length; if (gunzip((void *)load_addr, CONFIG_SYS_BOOTM_LEN, - src, &length)) { + src, &size)) { puts("Uncompressing error\n"); return -EIO; } + length = size; } else { memcpy((void *)load_addr, src, length); } diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c index b2cccc6c6e..b57e0b04e4 100644 --- a/common/spl/spl_mmc.c +++ b/common/spl/spl_mmc.c @@ -52,8 +52,9 @@ static ulong h_spl_load_read(struct spl_load_info *load, ulong sector, return blk_dread(mmc_get_blk_desc(mmc), sector, count, buf); } -static int mmc_load_image_raw_sector(struct spl_image_info *spl_image, - struct mmc *mmc, unsigned long sector) +static __maybe_unused +int mmc_load_image_raw_sector(struct spl_image_info *spl_image, + struct mmc *mmc, unsigned long sector) { unsigned long count; struct image_header *header; diff --git a/common/usb_storage.c b/common/usb_storage.c index df0b057308..a57570b73f 100644 --- a/common/usb_storage.c +++ b/common/usb_storage.c @@ -98,19 +98,9 @@ struct us_data { struct scsi_cmd *srb; /* current srb */ trans_reset transport_reset; /* reset routine */ trans_cmnd transport; /* transport routine */ + unsigned short max_xfer_blk; /* maximum transfer blocks */ }; -#ifdef CONFIG_USB_EHCI_HCD -/* - * The U-Boot EHCI driver can handle any transfer length as long as there is - * enough free heap space left, but the SCSI READ(10) and WRITE(10) commands are - * limited to 65535 blocks. - */ -#define USB_MAX_XFER_BLK 65535 -#else -#define USB_MAX_XFER_BLK 20 -#endif - #ifndef CONFIG_BLK static struct us_data usb_stor[USB_MAX_STOR_DEV]; #endif @@ -949,6 +939,38 @@ do_retry: return USB_STOR_TRANSPORT_FAILED; } +static void usb_stor_set_max_xfer_blk(struct usb_device *udev, + struct us_data *us) +{ + unsigned short blk; + size_t __maybe_unused size; + int __maybe_unused ret; + +#ifndef CONFIG_DM_USB +#ifdef CONFIG_USB_EHCI_HCD + /* + * The U-Boot EHCI driver can handle any transfer length as long as + * there is enough free heap space left, but the SCSI READ(10) and + * WRITE(10) commands are limited to 65535 blocks. + */ + blk = USHRT_MAX; +#else + blk = 20; +#endif +#else + ret = usb_get_max_xfer_size(udev, (size_t *)&size); + if (ret < 0) { + /* unimplemented, let's use default 20 */ + blk = 20; + } else { + if (size > USHRT_MAX * 512) + blk = USHRT_MAX; + blk = size / 512; + } +#endif + + us->max_xfer_blk = blk; +} static int usb_inquiry(struct scsi_cmd *srb, struct us_data *ss) { @@ -1150,12 +1172,12 @@ static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr, /* XXX need some comment here */ retry = 2; srb->pdata = (unsigned char *)buf_addr; - if (blks > USB_MAX_XFER_BLK) - smallblks = USB_MAX_XFER_BLK; + if (blks > ss->max_xfer_blk) + smallblks = ss->max_xfer_blk; else smallblks = (unsigned short) blks; retry_it: - if (smallblks == USB_MAX_XFER_BLK) + if (smallblks == ss->max_xfer_blk) usb_show_progress(); srb->datalen = block_dev->blksz * smallblks; srb->pdata = (unsigned char *)buf_addr; @@ -1178,7 +1200,7 @@ retry_it: start, smallblks, buf_addr); usb_disable_asynch(0); /* asynch transfer allowed */ - if (blkcnt >= USB_MAX_XFER_BLK) + if (blkcnt >= ss->max_xfer_blk) debug("\n"); return blkcnt; } @@ -1236,12 +1258,12 @@ static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr, */ retry = 2; srb->pdata = (unsigned char *)buf_addr; - if (blks > USB_MAX_XFER_BLK) - smallblks = USB_MAX_XFER_BLK; + if (blks > ss->max_xfer_blk) + smallblks = ss->max_xfer_blk; else smallblks = (unsigned short) blks; retry_it: - if (smallblks == USB_MAX_XFER_BLK) + if (smallblks == ss->max_xfer_blk) usb_show_progress(); srb->datalen = block_dev->blksz * smallblks; srb->pdata = (unsigned char *)buf_addr; @@ -1263,7 +1285,7 @@ retry_it: PRIxPTR "\n", start, smallblks, buf_addr); usb_disable_asynch(0); /* asynch transfer allowed */ - if (blkcnt >= USB_MAX_XFER_BLK) + if (blkcnt >= ss->max_xfer_blk) debug("\n"); return blkcnt; @@ -1384,6 +1406,10 @@ int usb_storage_probe(struct usb_device *dev, unsigned int ifnum, ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe); dev->irq_handle = usb_stor_irq; } + + /* Set the maximum transfer size per host controller setting */ + usb_stor_set_max_xfer_blk(dev, ss); + dev->privptr = (void *)ss; return 1; } diff --git a/configs/Cyrus_P5020_defconfig b/configs/Cyrus_P5020_defconfig index 82da854386..37f78a4811 100644 --- a/configs/Cyrus_P5020_defconfig +++ b/configs/Cyrus_P5020_defconfig @@ -34,5 +34,4 @@ CONFIG_FSL_ESPI=y CONFIG_USB=y CONFIG_USB_STORAGE=y CONFIG_USB_KEYBOARD=y -CONFIG_SYS_USB_EVENT_POLL=y CONFIG_OF_LIBFDT=y diff --git a/configs/Cyrus_P5040_defconfig b/configs/Cyrus_P5040_defconfig index 0fc9a07548..d33b514ee0 100644 --- a/configs/Cyrus_P5040_defconfig +++ b/configs/Cyrus_P5040_defconfig @@ -34,5 +34,4 @@ CONFIG_FSL_ESPI=y CONFIG_USB=y CONFIG_USB_STORAGE=y CONFIG_USB_KEYBOARD=y -CONFIG_SYS_USB_EVENT_POLL=y CONFIG_OF_LIBFDT=y diff --git a/configs/MPC8610HPCD_defconfig b/configs/MPC8610HPCD_defconfig index fde837c011..c71d5b18e1 100644 --- a/configs/MPC8610HPCD_defconfig +++ b/configs/MPC8610HPCD_defconfig @@ -22,5 +22,4 @@ CONFIG_SCSI=y CONFIG_SYS_NS16550=y CONFIG_USB=y CONFIG_USB_KEYBOARD=y -CONFIG_SYS_USB_EVENT_POLL=y CONFIG_OF_LIBFDT=y diff --git a/configs/MPC8641HPCN_36BIT_defconfig b/configs/MPC8641HPCN_36BIT_defconfig index 7318e723a8..9949e8b699 100644 --- a/configs/MPC8641HPCN_36BIT_defconfig +++ b/configs/MPC8641HPCN_36BIT_defconfig @@ -21,5 +21,4 @@ CONFIG_PHYLIB=y CONFIG_SYS_NS16550=y CONFIG_USB=y CONFIG_USB_KEYBOARD=y -CONFIG_SYS_USB_EVENT_POLL=y CONFIG_OF_LIBFDT=y diff --git a/configs/MPC8641HPCN_defconfig b/configs/MPC8641HPCN_defconfig index def36e4171..c8440d2584 100644 --- a/configs/MPC8641HPCN_defconfig +++ b/configs/MPC8641HPCN_defconfig @@ -21,5 +21,4 @@ CONFIG_PHYLIB=y CONFIG_SYS_NS16550=y CONFIG_USB=y CONFIG_USB_KEYBOARD=y -CONFIG_SYS_USB_EVENT_POLL=y CONFIG_OF_LIBFDT=y diff --git a/configs/adp-ae3xx_defconfig b/configs/adp-ae3xx_defconfig index 9e1e5ecb47..c1053958c4 100644 --- a/configs/adp-ae3xx_defconfig +++ b/configs/adp-ae3xx_defconfig @@ -5,6 +5,8 @@ CONFIG_FIT=y CONFIG_BOOTDELAY=3 CONFIG_SYS_PROMPT="NDS32 # " CONFIG_CMD_MMC=y +CONFIG_CMD_SF=y +CONFIG_CMD_SF_TEST=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_DHCP=y CONFIG_CMD_PING=y @@ -13,17 +15,23 @@ CONFIG_CMD_DATE=y CONFIG_CMD_EXT2=y CONFIG_CMD_FAT=y CONFIG_OF_CONTROL=y -CONFIG_ENV_IS_IN_FLASH=y +CONFIG_ENV_IS_IN_SPI_FLASH=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_DM=y +CONFIG_CLK=y CONFIG_MMC=y CONFIG_MTD=y CONFIG_MTD_NOR_FLASH=y CONFIG_CFI_FLASH=y +CONFIG_DM_SPI_FLASH=y +CONFIG_SPI_FLASH=y +CONFIG_SPI_FLASH_MACRONIX=y CONFIG_DM_ETH=y CONFIG_FTMAC100=y CONFIG_BAUDRATE=38400 CONFIG_DM_SERIAL=y CONFIG_SYS_NS16550=y +CONFIG_DM_SPI=y +CONFIG_NDS_AE3XX_SPI=y CONFIG_TIMER=y CONFIG_AE3XX_TIMER=y diff --git a/configs/am335x_baltos_defconfig b/configs/am335x_baltos_defconfig index eb8338f0f1..2842694dbc 100644 --- a/configs/am335x_baltos_defconfig +++ b/configs/am335x_baltos_defconfig @@ -10,7 +10,6 @@ CONFIG_SPL_SERIAL_SUPPORT=y CONFIG_SPL_LIBDISK_SUPPORT=y CONFIG_SPL_NAND_SUPPORT=y CONFIG_SPL_WATCHDOG_SUPPORT=y -CONFIG_SPL_STACK_R_ADDR=0x82000000 CONFIG_SPL_FAT_SUPPORT=y CONFIG_FIT_VERBOSE=y CONFIG_OF_BOARD_SETUP=y @@ -18,7 +17,6 @@ CONFIG_SYS_CONSOLE_INFO_QUIET=y CONFIG_VERSION_VARIABLE=y CONFIG_ARCH_MISC_INIT=y CONFIG_SPL=y -CONFIG_SPL_STACK_R=y CONFIG_SPL_EXT_SUPPORT=y CONFIG_SPL_I2C_SUPPORT=y CONFIG_SPL_MTD_SUPPORT=y diff --git a/configs/am335x_boneblack_defconfig b/configs/am335x_boneblack_defconfig index b8526fc15e..2fc25fbaab 100644 --- a/configs/am335x_boneblack_defconfig +++ b/configs/am335x_boneblack_defconfig @@ -3,14 +3,12 @@ CONFIG_ARCH_OMAP2PLUS=y CONFIG_TI_COMMON_CMD_OPTIONS=y CONFIG_AM33XX=y # CONFIG_SPL_NAND_SUPPORT is not set -CONFIG_SPL_STACK_R_ADDR=0x82000000 CONFIG_DISTRO_DEFAULTS=y CONFIG_SYS_EXTRA_OPTIONS="EMMC_BOOT" CONFIG_SYS_CONSOLE_INFO_QUIET=y CONFIG_VERSION_VARIABLE=y CONFIG_ARCH_MISC_INIT=y CONFIG_SPL=y -CONFIG_SPL_STACK_R=y CONFIG_SPL_MUSB_NEW_SUPPORT=y CONFIG_SPL_OS_BOOT=y CONFIG_AUTOBOOT_KEYED=y diff --git a/configs/am335x_boneblack_vboot_defconfig b/configs/am335x_boneblack_vboot_defconfig index 0a239bb733..e8bcb6d0c8 100644 --- a/configs/am335x_boneblack_vboot_defconfig +++ b/configs/am335x_boneblack_vboot_defconfig @@ -3,7 +3,6 @@ CONFIG_ARCH_OMAP2PLUS=y CONFIG_TI_COMMON_CMD_OPTIONS=y CONFIG_AM33XX=y # CONFIG_SPL_NAND_SUPPORT is not set -CONFIG_SPL_STACK_R_ADDR=0x82000000 CONFIG_DEFAULT_DEVICE_TREE="am335x-boneblack" CONFIG_DISTRO_DEFAULTS=y CONFIG_FIT_SIGNATURE=y @@ -13,7 +12,6 @@ CONFIG_SYS_CONSOLE_INFO_QUIET=y CONFIG_VERSION_VARIABLE=y CONFIG_ARCH_MISC_INIT=y CONFIG_SPL=y -CONFIG_SPL_STACK_R=y CONFIG_SPL_MUSB_NEW_SUPPORT=y CONFIG_SPL_OS_BOOT=y CONFIG_AUTOBOOT_KEYED=y diff --git a/configs/am335x_evm_defconfig b/configs/am335x_evm_defconfig index 00c1af4344..b6a7cf0e5c 100644 --- a/configs/am335x_evm_defconfig +++ b/configs/am335x_evm_defconfig @@ -2,7 +2,6 @@ CONFIG_ARM=y CONFIG_ARCH_OMAP2PLUS=y CONFIG_TI_COMMON_CMD_OPTIONS=y CONFIG_AM33XX=y -CONFIG_SPL_STACK_R_ADDR=0x82000000 CONFIG_DEFAULT_DEVICE_TREE="am335x-evm" CONFIG_DISTRO_DEFAULTS=y CONFIG_SPL_LOAD_FIT=y @@ -10,7 +9,6 @@ CONFIG_SYS_CONSOLE_INFO_QUIET=y CONFIG_VERSION_VARIABLE=y CONFIG_ARCH_MISC_INIT=y CONFIG_SPL=y -CONFIG_SPL_STACK_R=y CONFIG_SPL_MTD_SUPPORT=y CONFIG_SPL_MUSB_NEW_SUPPORT=y CONFIG_SPL_OS_BOOT=y diff --git a/configs/am335x_evm_nor_defconfig b/configs/am335x_evm_nor_defconfig index 9f08edff4c..e2fc822c2f 100644 --- a/configs/am335x_evm_nor_defconfig +++ b/configs/am335x_evm_nor_defconfig @@ -3,13 +3,11 @@ CONFIG_ARCH_OMAP2PLUS=y CONFIG_TI_COMMON_CMD_OPTIONS=y CONFIG_AM33XX=y CONFIG_NOR=y -CONFIG_SPL_STACK_R_ADDR=0x82000000 CONFIG_DISTRO_DEFAULTS=y CONFIG_SYS_CONSOLE_INFO_QUIET=y CONFIG_VERSION_VARIABLE=y CONFIG_ARCH_MISC_INIT=y CONFIG_SPL=y -CONFIG_SPL_STACK_R=y CONFIG_SPL_MTD_SUPPORT=y CONFIG_SPL_MUSB_NEW_SUPPORT=y CONFIG_SPL_OS_BOOT=y diff --git a/configs/am335x_evm_spiboot_defconfig b/configs/am335x_evm_spiboot_defconfig index 501fb2b90f..a53e5aee83 100644 --- a/configs/am335x_evm_spiboot_defconfig +++ b/configs/am335x_evm_spiboot_defconfig @@ -5,7 +5,6 @@ CONFIG_AM33XX=y # CONFIG_SPL_NAND_SUPPORT is not set CONFIG_SPL_SPI_FLASH_SUPPORT=y CONFIG_SPL_SPI_SUPPORT=y -CONFIG_SPL_STACK_R_ADDR=0x82000000 CONFIG_DISTRO_DEFAULTS=y CONFIG_SYS_EXTRA_OPTIONS="SPI_BOOT" CONFIG_SPI_BOOT=y @@ -13,7 +12,6 @@ CONFIG_SYS_CONSOLE_INFO_QUIET=y CONFIG_VERSION_VARIABLE=y CONFIG_ARCH_MISC_INIT=y CONFIG_SPL=y -CONFIG_SPL_STACK_R=y CONFIG_SPL_MUSB_NEW_SUPPORT=y CONFIG_FASTBOOT=y CONFIG_USB_FUNCTION_FASTBOOT=y diff --git a/configs/am335x_evm_usbspl_defconfig b/configs/am335x_evm_usbspl_defconfig index 7c351382d9..7b003ee777 100644 --- a/configs/am335x_evm_usbspl_defconfig +++ b/configs/am335x_evm_usbspl_defconfig @@ -3,14 +3,12 @@ CONFIG_ARCH_OMAP2PLUS=y CONFIG_TI_COMMON_CMD_OPTIONS=y CONFIG_AM33XX=y # CONFIG_SPL_NAND_SUPPORT is not set -CONFIG_SPL_STACK_R_ADDR=0x82000000 CONFIG_DISTRO_DEFAULTS=y # CONFIG_ANDROID_BOOT_IMAGE is not set CONFIG_SYS_CONSOLE_INFO_QUIET=y CONFIG_VERSION_VARIABLE=y CONFIG_ARCH_MISC_INIT=y CONFIG_SPL=y -CONFIG_SPL_STACK_R=y CONFIG_SPL_MUSB_NEW_SUPPORT=y CONFIG_SPL_NET_SUPPORT=y CONFIG_SPL_OS_BOOT=y diff --git a/configs/am335x_hs_evm_defconfig b/configs/am335x_hs_evm_defconfig index acdd56b435..af5233c5fc 100644 --- a/configs/am335x_hs_evm_defconfig +++ b/configs/am335x_hs_evm_defconfig @@ -5,7 +5,6 @@ CONFIG_AM33XX=y CONFIG_TI_SECURE_DEVICE=y CONFIG_ISW_ENTRY_ADDR=0x40300350 # CONFIG_SPL_NAND_SUPPORT is not set -CONFIG_SPL_STACK_R_ADDR=0x82000000 CONFIG_DEFAULT_DEVICE_TREE="am335x-evm" CONFIG_DISTRO_DEFAULTS=y CONFIG_ANDROID_BOOT_IMAGE=y @@ -16,7 +15,6 @@ CONFIG_SYS_CONSOLE_INFO_QUIET=y CONFIG_VERSION_VARIABLE=y CONFIG_ARCH_MISC_INIT=y CONFIG_SPL=y -CONFIG_SPL_STACK_R=y # CONFIG_SPL_ENV_SUPPORT is not set # CONFIG_SPL_EXT_SUPPORT is not set CONFIG_SPL_MTD_SUPPORT=y diff --git a/configs/am335x_hs_evm_uart_defconfig b/configs/am335x_hs_evm_uart_defconfig new file mode 100644 index 0000000000..1c453fb23a --- /dev/null +++ b/configs/am335x_hs_evm_uart_defconfig @@ -0,0 +1,67 @@ +CONFIG_ARM=y +CONFIG_ARCH_OMAP2PLUS=y +CONFIG_TI_COMMON_CMD_OPTIONS=y +CONFIG_AM33XX=y +# CONFIG_SPL_FAT_SUPPORT is not set +# CONFIG_SPL_LIBDISK_SUPPORT is not set +# CONFIG_SPL_MMC_SUPPORT is not set +# CONFIG_SPL_NAND_SUPPORT is not set +CONFIG_TI_SECURE_DEVICE=y +CONFIG_ISW_ENTRY_ADDR=0x40301950 +CONFIG_SPL_STACK_R_ADDR=0x82000000 +CONFIG_DEFAULT_DEVICE_TREE="am335x-evm" +CONFIG_DISTRO_DEFAULTS=y +CONFIG_FIT_IMAGE_POST_PROCESS=y +CONFIG_SPL_LOAD_FIT=y +CONFIG_SPL_FIT_IMAGE_POST_PROCESS=y +CONFIG_SYS_CONSOLE_INFO_QUIET=y +CONFIG_VERSION_VARIABLE=y +CONFIG_ARCH_MISC_INIT=y +CONFIG_SPL=y +CONFIG_SPL_SYS_MALLOC_SIMPLE=y +CONFIG_SPL_STACK_R=y +# CONFIG_SPL_ENV_SUPPORT is not set +# CONFIG_SPL_EXT_SUPPORT is not set +CONFIG_SPL_MTD_SUPPORT=y +# CONFIG_SPL_YMODEM_SUPPORT is not set +# CONFIG_CMD_IMLS is not set +# CONFIG_CMD_FLASH is not set +CONFIG_CMD_NAND=y +# CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_MTDPARTS=y +# CONFIG_SPL_EFI_PARTITION is not set +CONFIG_OF_CONTROL=y +CONFIG_OF_LIST="am335x-evm am335x-bone am335x-boneblack am335x-evmsk am335x-bonegreen am335x-icev2" +# CONFIG_BLK is not set +CONFIG_DFU_MMC=y +CONFIG_DFU_NAND=y +CONFIG_DFU_RAM=y +CONFIG_DM_I2C=y +CONFIG_MISC=y +CONFIG_DM_MMC=y +CONFIG_MMC_OMAP_HS=y +CONFIG_NAND=y +CONFIG_SPI_FLASH=y +CONFIG_SPI_FLASH_WINBOND=y +CONFIG_PHYLIB=y +CONFIG_DM_ETH=y +CONFIG_PHY_GIGE=y +CONFIG_SYS_NS16550=y +CONFIG_OMAP3_SPI=y +CONFIG_TIMER=y +CONFIG_OMAP_TIMER=y +CONFIG_USB=y +CONFIG_DM_USB=y +CONFIG_USB_MUSB_HOST=y +CONFIG_USB_MUSB_GADGET=y +CONFIG_USB_MUSB_TI=y +CONFIG_USB_STORAGE=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_DOWNLOAD=y +CONFIG_G_DNL_MANUFACTURER="Texas Instruments" +CONFIG_G_DNL_VENDOR_NUM=0x0451 +CONFIG_G_DNL_PRODUCT_NUM=0xd022 +CONFIG_USE_TINY_PRINTF=y +CONFIG_RSA=y +CONFIG_LZO=y +CONFIG_OF_LIBFDT_OVERLAY=y diff --git a/configs/am335x_igep003x_defconfig b/configs/am335x_igep003x_defconfig index 1b03c334b4..f344a7367d 100644 --- a/configs/am335x_igep003x_defconfig +++ b/configs/am335x_igep003x_defconfig @@ -11,14 +11,12 @@ CONFIG_SPL_SERIAL_SUPPORT=y CONFIG_SPL_LIBDISK_SUPPORT=y CONFIG_SPL_NAND_SUPPORT=y CONFIG_SPL_WATCHDOG_SUPPORT=y -CONFIG_SPL_STACK_R_ADDR=0x82000000 CONFIG_SPL_FAT_SUPPORT=y CONFIG_OF_BOARD_SETUP=y CONFIG_SYS_EXTRA_OPTIONS="MACH_TYPE=MACH_TYPE_IGEP0033" CONFIG_SYS_CONSOLE_INFO_QUIET=y CONFIG_VERSION_VARIABLE=y CONFIG_SPL=y -CONFIG_SPL_STACK_R=y CONFIG_SPL_EXT_SUPPORT=y CONFIG_SPL_I2C_SUPPORT=y CONFIG_SPL_MTD_SUPPORT=y diff --git a/configs/am335x_shc_defconfig b/configs/am335x_shc_defconfig index c63e388ff5..0b29290cf5 100644 --- a/configs/am335x_shc_defconfig +++ b/configs/am335x_shc_defconfig @@ -9,13 +9,11 @@ CONFIG_SPL_MMC_SUPPORT=y CONFIG_SPL_SERIAL_SUPPORT=y CONFIG_SPL_LIBDISK_SUPPORT=y CONFIG_SPL_WATCHDOG_SUPPORT=y -CONFIG_SPL_STACK_R_ADDR=0x82000000 CONFIG_SPL_FAT_SUPPORT=y CONFIG_SERIES=y CONFIG_SYS_CONSOLE_INFO_QUIET=y CONFIG_VERSION_VARIABLE=y CONFIG_SPL=y -CONFIG_SPL_STACK_R=y CONFIG_SPL_EXT_SUPPORT=y CONFIG_SPL_I2C_SUPPORT=y CONFIG_SPL_OS_BOOT=y diff --git a/configs/am335x_shc_ict_defconfig b/configs/am335x_shc_ict_defconfig index 1bcf683e35..73e0d2857f 100644 --- a/configs/am335x_shc_ict_defconfig +++ b/configs/am335x_shc_ict_defconfig @@ -9,14 +9,12 @@ CONFIG_SPL_MMC_SUPPORT=y CONFIG_SPL_SERIAL_SUPPORT=y CONFIG_SPL_LIBDISK_SUPPORT=y CONFIG_SPL_WATCHDOG_SUPPORT=y -CONFIG_SPL_STACK_R_ADDR=0x82000000 CONFIG_SPL_FAT_SUPPORT=y CONFIG_SHC_ICT=y CONFIG_SERIES=y CONFIG_SYS_CONSOLE_INFO_QUIET=y CONFIG_VERSION_VARIABLE=y CONFIG_SPL=y -CONFIG_SPL_STACK_R=y CONFIG_SPL_EXT_SUPPORT=y CONFIG_SPL_I2C_SUPPORT=y CONFIG_SPL_OS_BOOT=y diff --git a/configs/am335x_shc_netboot_defconfig b/configs/am335x_shc_netboot_defconfig index 9528a8cd5c..c4f2f55d05 100644 --- a/configs/am335x_shc_netboot_defconfig +++ b/configs/am335x_shc_netboot_defconfig @@ -9,14 +9,12 @@ CONFIG_SPL_MMC_SUPPORT=y CONFIG_SPL_SERIAL_SUPPORT=y CONFIG_SPL_LIBDISK_SUPPORT=y CONFIG_SPL_WATCHDOG_SUPPORT=y -CONFIG_SPL_STACK_R_ADDR=0x82000000 CONFIG_SPL_FAT_SUPPORT=y CONFIG_SHC_NETBOOT=y CONFIG_SERIES=y CONFIG_SYS_CONSOLE_INFO_QUIET=y CONFIG_VERSION_VARIABLE=y CONFIG_SPL=y -CONFIG_SPL_STACK_R=y CONFIG_SPL_ENV_SUPPORT=y CONFIG_SPL_EXT_SUPPORT=y CONFIG_SPL_I2C_SUPPORT=y diff --git a/configs/am335x_shc_prompt_defconfig b/configs/am335x_shc_prompt_defconfig index 8519282ecf..4eac21b4eb 100644 --- a/configs/am335x_shc_prompt_defconfig +++ b/configs/am335x_shc_prompt_defconfig @@ -9,13 +9,11 @@ CONFIG_SPL_MMC_SUPPORT=y CONFIG_SPL_SERIAL_SUPPORT=y CONFIG_SPL_LIBDISK_SUPPORT=y CONFIG_SPL_WATCHDOG_SUPPORT=y -CONFIG_SPL_STACK_R_ADDR=0x82000000 CONFIG_SPL_FAT_SUPPORT=y CONFIG_SERIES=y CONFIG_SYS_CONSOLE_INFO_QUIET=y CONFIG_VERSION_VARIABLE=y CONFIG_SPL=y -CONFIG_SPL_STACK_R=y CONFIG_SPL_EXT_SUPPORT=y CONFIG_SPL_I2C_SUPPORT=y CONFIG_SPL_OS_BOOT=y diff --git a/configs/am335x_shc_sdboot_defconfig b/configs/am335x_shc_sdboot_defconfig index b00d6f6b22..e3a37db04a 100644 --- a/configs/am335x_shc_sdboot_defconfig +++ b/configs/am335x_shc_sdboot_defconfig @@ -9,14 +9,12 @@ CONFIG_SPL_MMC_SUPPORT=y CONFIG_SPL_SERIAL_SUPPORT=y CONFIG_SPL_LIBDISK_SUPPORT=y CONFIG_SPL_WATCHDOG_SUPPORT=y -CONFIG_SPL_STACK_R_ADDR=0x82000000 CONFIG_SPL_FAT_SUPPORT=y CONFIG_SHC_SDBOOT=y CONFIG_SERIES=y CONFIG_SYS_CONSOLE_INFO_QUIET=y CONFIG_VERSION_VARIABLE=y CONFIG_SPL=y -CONFIG_SPL_STACK_R=y CONFIG_SPL_EXT_SUPPORT=y CONFIG_SPL_I2C_SUPPORT=y CONFIG_SPL_OS_BOOT=y diff --git a/configs/am335x_shc_sdboot_prompt_defconfig b/configs/am335x_shc_sdboot_prompt_defconfig index b00d6f6b22..e3a37db04a 100644 --- a/configs/am335x_shc_sdboot_prompt_defconfig +++ b/configs/am335x_shc_sdboot_prompt_defconfig @@ -9,14 +9,12 @@ CONFIG_SPL_MMC_SUPPORT=y CONFIG_SPL_SERIAL_SUPPORT=y CONFIG_SPL_LIBDISK_SUPPORT=y CONFIG_SPL_WATCHDOG_SUPPORT=y -CONFIG_SPL_STACK_R_ADDR=0x82000000 CONFIG_SPL_FAT_SUPPORT=y CONFIG_SHC_SDBOOT=y CONFIG_SERIES=y CONFIG_SYS_CONSOLE_INFO_QUIET=y CONFIG_VERSION_VARIABLE=y CONFIG_SPL=y -CONFIG_SPL_STACK_R=y CONFIG_SPL_EXT_SUPPORT=y CONFIG_SPL_I2C_SUPPORT=y CONFIG_SPL_OS_BOOT=y diff --git a/configs/am335x_sl50_defconfig b/configs/am335x_sl50_defconfig index 3fa5d5e5cc..e9ca0d640f 100644 --- a/configs/am335x_sl50_defconfig +++ b/configs/am335x_sl50_defconfig @@ -9,14 +9,12 @@ CONFIG_SPL_MMC_SUPPORT=y CONFIG_SPL_SERIAL_SUPPORT=y CONFIG_SPL_LIBDISK_SUPPORT=y CONFIG_SPL_WATCHDOG_SUPPORT=y -CONFIG_SPL_STACK_R_ADDR=0x82000000 CONFIG_SPL_FAT_SUPPORT=y CONFIG_DISTRO_DEFAULTS=y CONFIG_SYS_EXTRA_OPTIONS="EMMC_BOOT" CONFIG_SYS_CONSOLE_INFO_QUIET=y CONFIG_VERSION_VARIABLE=y CONFIG_SPL=y -CONFIG_SPL_STACK_R=y CONFIG_SPL_ENV_SUPPORT=y CONFIG_SPL_EXT_SUPPORT=y CONFIG_SPL_I2C_SUPPORT=y diff --git a/configs/am3517_evm_defconfig b/configs/am3517_evm_defconfig index 920c61c391..8ab018656d 100644 --- a/configs/am3517_evm_defconfig +++ b/configs/am3517_evm_defconfig @@ -4,11 +4,14 @@ CONFIG_ARCH_OMAP2PLUS=y CONFIG_SYS_TEXT_BASE=0x80100000 CONFIG_TI_COMMON_CMD_OPTIONS=y # CONFIG_SPL_GPIO_SUPPORT is not set +CONFIG_SYS_MALLOC_F_LEN=0x2000 CONFIG_TARGET_AM3517_EVM=y CONFIG_EMIF4=y +CONFIG_DEFAULT_DEVICE_TREE="am3517-evm" CONFIG_BOOTDELAY=10 CONFIG_VERSION_VARIABLE=y CONFIG_SPL=y +CONFIG_SPL_SYS_MALLOC_SIMPLE=y # CONFIG_SPL_EXT_SUPPORT is not set CONFIG_SPL_MTD_SUPPORT=y CONFIG_HUSH_PARSER=y @@ -27,13 +30,12 @@ CONFIG_CMD_CACHE=y # CONFIG_CMD_TIME is not set CONFIG_CMD_UBI=y CONFIG_SPL_PARTITION_UUIDS=y +CONFIG_OF_CONTROL=y CONFIG_ENV_IS_IN_NAND=y CONFIG_MMC_OMAP_HS=y CONFIG_NAND=y CONFIG_SYS_NS16550=y CONFIG_USB=y CONFIG_USB_MUSB_HOST=y -CONFIG_USB_STORAGE=y # CONFIG_FAT_WRITE is not set CONFIG_BCH=y -CONFIG_OF_LIBFDT=y diff --git a/configs/am43xx_evm_defconfig b/configs/am43xx_evm_defconfig index 15c25d39f1..352ae16a9e 100644 --- a/configs/am43xx_evm_defconfig +++ b/configs/am43xx_evm_defconfig @@ -3,14 +3,12 @@ CONFIG_ARCH_OMAP2PLUS=y CONFIG_TI_COMMON_CMD_OPTIONS=y CONFIG_SYS_MALLOC_F_LEN=0x2000 CONFIG_AM43XX=y -CONFIG_SPL_STACK_R_ADDR=0x82000000 CONFIG_DEFAULT_DEVICE_TREE="am437x-gp-evm" CONFIG_SPL_LOAD_FIT=y CONFIG_SYS_EXTRA_OPTIONS="CONS_INDEX=1" CONFIG_SYS_CONSOLE_INFO_QUIET=y CONFIG_VERSION_VARIABLE=y CONFIG_SPL=y -CONFIG_SPL_STACK_R=y CONFIG_SPL_MTD_SUPPORT=y CONFIG_SPL_OS_BOOT=y CONFIG_HUSH_PARSER=y diff --git a/configs/am43xx_evm_usbhost_boot_defconfig b/configs/am43xx_evm_usbhost_boot_defconfig index 0bed335722..1a4856ca9e 100644 --- a/configs/am43xx_evm_usbhost_boot_defconfig +++ b/configs/am43xx_evm_usbhost_boot_defconfig @@ -3,14 +3,12 @@ CONFIG_ARCH_OMAP2PLUS=y CONFIG_SYS_MALLOC_F_LEN=0x2000 CONFIG_AM43XX=y CONFIG_ISW_ENTRY_ADDR=0x40300350 -CONFIG_SPL_STACK_R_ADDR=0x82000000 CONFIG_DEFAULT_DEVICE_TREE="am437x-gp-evm" CONFIG_SPL_LOAD_FIT=y CONFIG_SYS_EXTRA_OPTIONS="SERIAL1,CONS_INDEX=1" CONFIG_SYS_CONSOLE_INFO_QUIET=y CONFIG_VERSION_VARIABLE=y CONFIG_SPL=y -CONFIG_SPL_STACK_R=y CONFIG_SPL_MTD_SUPPORT=y CONFIG_SPL_OS_BOOT=y CONFIG_SPL_USB_HOST_SUPPORT=y diff --git a/configs/am43xx_hs_evm_defconfig b/configs/am43xx_hs_evm_defconfig index a4d23e10b6..9b2b1d7196 100644 --- a/configs/am43xx_hs_evm_defconfig +++ b/configs/am43xx_hs_evm_defconfig @@ -8,7 +8,6 @@ CONFIG_TI_SECURE_EMIF_REGION_START=0xbdb00000 CONFIG_TI_SECURE_EMIF_TOTAL_REGION_SIZE=0x02000000 CONFIG_TI_SECURE_EMIF_PROTECTED_REGION_SIZE=0x01c00000 CONFIG_ISW_ENTRY_ADDR=0x403018e0 -CONFIG_SPL_STACK_R_ADDR=0x82000000 CONFIG_DEFAULT_DEVICE_TREE="am437x-gp-evm" CONFIG_FIT_IMAGE_POST_PROCESS=y CONFIG_SPL_LOAD_FIT=y @@ -18,7 +17,6 @@ CONFIG_SYS_EXTRA_OPTIONS="CONS_INDEX=1" CONFIG_SYS_CONSOLE_INFO_QUIET=y CONFIG_VERSION_VARIABLE=y CONFIG_SPL=y -CONFIG_SPL_STACK_R=y CONFIG_SPL_ETH_SUPPORT=y CONFIG_SPL_MTD_SUPPORT=y CONFIG_SPL_NET_SUPPORT=y diff --git a/configs/am57xx_evm_defconfig b/configs/am57xx_evm_defconfig index 0e4679abed..0c9daed5f5 100644 --- a/configs/am57xx_evm_defconfig +++ b/configs/am57xx_evm_defconfig @@ -7,7 +7,6 @@ CONFIG_TARGET_AM57XX_EVM=y # CONFIG_SPL_NAND_SUPPORT is not set CONFIG_SPL_SPI_FLASH_SUPPORT=y CONFIG_SPL_SPI_SUPPORT=y -CONFIG_SPL_STACK_R_ADDR=0x82000000 CONFIG_ARMV7_LPAE=y CONFIG_DEFAULT_DEVICE_TREE="am572x-idk" CONFIG_SPL_LOAD_FIT=y @@ -19,7 +18,6 @@ CONFIG_VERSION_VARIABLE=y CONFIG_BOARD_EARLY_INIT_F=y CONFIG_SPL=y CONFIG_SPL_SYS_MALLOC_SIMPLE=y -CONFIG_SPL_STACK_R=y CONFIG_SPL_SEPARATE_BSS=y CONFIG_SPL_DMA_SUPPORT=y CONFIG_SPL_OS_BOOT=y diff --git a/configs/am57xx_hs_evm_defconfig b/configs/am57xx_hs_evm_defconfig index e7638b88c2..b527e18463 100644 --- a/configs/am57xx_hs_evm_defconfig +++ b/configs/am57xx_hs_evm_defconfig @@ -11,7 +11,6 @@ CONFIG_TARGET_AM57XX_EVM=y # CONFIG_SPL_NAND_SUPPORT is not set CONFIG_SPL_SPI_FLASH_SUPPORT=y CONFIG_SPL_SPI_SUPPORT=y -CONFIG_SPL_STACK_R_ADDR=0x82000000 CONFIG_ARMV7_LPAE=y CONFIG_DEFAULT_DEVICE_TREE="am57xx-beagle-x15" CONFIG_FIT_IMAGE_POST_PROCESS=y @@ -25,7 +24,6 @@ CONFIG_VERSION_VARIABLE=y CONFIG_BOARD_EARLY_INIT_F=y CONFIG_SPL=y CONFIG_SPL_SYS_MALLOC_SIMPLE=y -CONFIG_SPL_STACK_R=y CONFIG_SPL_SEPARATE_BSS=y CONFIG_SPL_DMA_SUPPORT=y CONFIG_HUSH_PARSER=y diff --git a/configs/apalis_imx6_defconfig b/configs/apalis_imx6_defconfig index b2284acc34..13f2a3b849 100644 --- a/configs/apalis_imx6_defconfig +++ b/configs/apalis_imx6_defconfig @@ -54,7 +54,6 @@ CONFIG_NETDEVICES=y CONFIG_USB=y CONFIG_USB_STORAGE=y CONFIG_USB_KEYBOARD=y -CONFIG_SYS_USB_EVENT_POLL=y CONFIG_USB_GADGET=y CONFIG_CI_UDC=y CONFIG_USB_GADGET_DOWNLOAD=y diff --git a/configs/apalis_imx6_nospl_com_defconfig b/configs/apalis_imx6_nospl_com_defconfig index 239605dadf..7165749cfb 100644 --- a/configs/apalis_imx6_nospl_com_defconfig +++ b/configs/apalis_imx6_nospl_com_defconfig @@ -43,7 +43,6 @@ CONFIG_NETDEVICES=y CONFIG_USB=y CONFIG_USB_STORAGE=y CONFIG_USB_KEYBOARD=y -CONFIG_SYS_USB_EVENT_POLL=y CONFIG_USB_GADGET=y CONFIG_CI_UDC=y CONFIG_USB_GADGET_DOWNLOAD=y diff --git a/configs/apalis_imx6_nospl_it_defconfig b/configs/apalis_imx6_nospl_it_defconfig index 1bc05d7266..0ad7674ee5 100644 --- a/configs/apalis_imx6_nospl_it_defconfig +++ b/configs/apalis_imx6_nospl_it_defconfig @@ -43,7 +43,6 @@ CONFIG_NETDEVICES=y CONFIG_USB=y CONFIG_USB_STORAGE=y CONFIG_USB_KEYBOARD=y -CONFIG_SYS_USB_EVENT_POLL=y CONFIG_USB_GADGET=y CONFIG_CI_UDC=y CONFIG_USB_GADGET_DOWNLOAD=y diff --git a/configs/chiliboard_defconfig b/configs/chiliboard_defconfig index ea729b0155..d0f6f5fa11 100644 --- a/configs/chiliboard_defconfig +++ b/configs/chiliboard_defconfig @@ -9,12 +9,10 @@ CONFIG_SPL_SERIAL_SUPPORT=y CONFIG_SPL_LIBDISK_SUPPORT=y CONFIG_SPL_NAND_SUPPORT=y CONFIG_SPL_WATCHDOG_SUPPORT=y -CONFIG_SPL_STACK_R_ADDR=0x82000000 CONFIG_SPL_FAT_SUPPORT=y CONFIG_BOOTDELAY=1 CONFIG_SYS_CONSOLE_INFO_QUIET=y CONFIG_SPL=y -CONFIG_SPL_STACK_R=y CONFIG_SPL_I2C_SUPPORT=y CONFIG_SPL_POWER_SUPPORT=y CONFIG_HUSH_PARSER=y diff --git a/configs/clearfog_defconfig b/configs/clearfog_defconfig index 580eaf3e57..5eceacf491 100644 --- a/configs/clearfog_defconfig +++ b/configs/clearfog_defconfig @@ -35,8 +35,8 @@ CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_SDMA=y CONFIG_MMC_SDHCI_MV=y CONFIG_SPI_FLASH=y -CONFIG_PHYLIB=y CONFIG_PHY_GIGE=y +CONFIG_MVNETA=y CONFIG_PCI=y CONFIG_DEBUG_UART_BASE=0xd0012000 CONFIG_DEBUG_UART_CLOCK=250000000 diff --git a/configs/colibri_imx6_defconfig b/configs/colibri_imx6_defconfig index 7d1e709d4c..7e100869a4 100644 --- a/configs/colibri_imx6_defconfig +++ b/configs/colibri_imx6_defconfig @@ -52,7 +52,6 @@ CONFIG_PHY_MICREL=y CONFIG_USB=y CONFIG_USB_STORAGE=y CONFIG_USB_KEYBOARD=y -CONFIG_SYS_USB_EVENT_POLL=y CONFIG_USB_GADGET=y CONFIG_CI_UDC=y CONFIG_USB_GADGET_DOWNLOAD=y diff --git a/configs/colibri_imx6_nospl_defconfig b/configs/colibri_imx6_nospl_defconfig index 6877993088..ba4b2dd9d4 100644 --- a/configs/colibri_imx6_nospl_defconfig +++ b/configs/colibri_imx6_nospl_defconfig @@ -41,7 +41,6 @@ CONFIG_PHY_MICREL=y CONFIG_USB=y CONFIG_USB_STORAGE=y CONFIG_USB_KEYBOARD=y -CONFIG_SYS_USB_EVENT_POLL=y CONFIG_USB_GADGET=y CONFIG_CI_UDC=y CONFIG_USB_GADGET_DOWNLOAD=y diff --git a/configs/controlcenterdc_defconfig b/configs/controlcenterdc_defconfig index 836e00b2b5..04f622a574 100644 --- a/configs/controlcenterdc_defconfig +++ b/configs/controlcenterdc_defconfig @@ -46,8 +46,8 @@ CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_MV=y CONFIG_SPI_FLASH=y CONFIG_SPI_FLASH_STMICRO=y -CONFIG_PHYLIB=y CONFIG_PHY_GIGE=y +CONFIG_MVNETA=y CONFIG_SCSI=y CONFIG_DEBUG_UART_BASE=0xd0012000 CONFIG_DEBUG_UART_CLOCK=250000000 diff --git a/configs/da850_am18xxevm_defconfig b/configs/da850_am18xxevm_defconfig index 27370e7c0c..0c60fef098 100644 --- a/configs/da850_am18xxevm_defconfig +++ b/configs/da850_am18xxevm_defconfig @@ -1,17 +1,16 @@ CONFIG_ARM=y CONFIG_ARCH_DAVINCI=y CONFIG_TARGET_DA850EVM=y -CONFIG_TI_COMMON_CMD_OPTIONS=y CONFIG_MAC_ADDR_IN_EEPROM=y +CONFIG_TI_COMMON_CMD_OPTIONS=y CONFIG_SPL_LIBCOMMON_SUPPORT=y CONFIG_SPL_LIBGENERIC_SUPPORT=y CONFIG_SPL_SERIAL_SUPPORT=y CONFIG_SPL_SPI_FLASH_SUPPORT=y CONFIG_SPL_SPI_SUPPORT=y +CONFIG_DEFAULT_DEVICE_TREE="da850-evm" CONFIG_SYS_EXTRA_OPTIONS="DA850_AM18X_EVM,SYS_I2C_EEPROM_ADDR_LEN=2,SYS_I2C_EEPROM_ADDR=0x50" CONFIG_BOOTDELAY=3 -CONFIG_USE_BOOTARGS=y -CONFIG_BOOTARGS="mem=32M console=ttyS2,115200n8 root=/dev/mtdblock2 rw noinitrd ip=dhcp" CONFIG_VERSION_VARIABLE=y # CONFIG_DISPLAY_CPUINFO is not set # CONFIG_DISPLAY_BOARDINFO is not set @@ -19,24 +18,29 @@ CONFIG_BOARD_EARLY_INIT_F=y CONFIG_SPL=y CONFIG_SPL_BOARD_INIT=y CONFIG_HUSH_PARSER=y -# CONFIG_CMD_BOOTZ is not set +CONFIG_SYS_PROMPT="U-Boot > " # CONFIG_CMD_IMLS is not set CONFIG_CRC32_VERIFY=y # CONFIG_CMD_EEPROM is not set # CONFIG_CMD_FLASH is not set # CONFIG_CMD_GPIO is not set # CONFIG_CMD_GPT is not set -# CONFIG_CMD_I2C is not set # CONFIG_CMD_PART is not set # CONFIG_CMD_SETEXPR is not set # CONFIG_CMD_TIME is not set # CONFIG_CMD_EXT4 is not set # CONFIG_CMD_FS_GENERIC is not set CONFIG_CMD_DIAG=y +CONFIG_OF_CONTROL=y CONFIG_ENV_IS_IN_SPI_FLASH=y +CONFIG_DM=y +CONFIG_DM_I2C=y +CONFIG_DM_I2C_COMPAT=y +CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y CONFIG_SPI_FLASH_STMICRO=y CONFIG_SPI_FLASH_WINBOND=y +CONFIG_DM_SERIAL=y CONFIG_SYS_NS16550=y +CONFIG_DM_SPI=y # CONFIG_FAT_WRITE is not set -CONFIG_OF_LIBFDT=y diff --git a/configs/da850evm_defconfig b/configs/da850evm_defconfig index bfa5ea1c4b..d6eb4a5ba2 100644 --- a/configs/da850evm_defconfig +++ b/configs/da850evm_defconfig @@ -7,9 +7,9 @@ CONFIG_SPL_LIBGENERIC_SUPPORT=y CONFIG_SPL_SERIAL_SUPPORT=y CONFIG_SPL_SPI_FLASH_SUPPORT=y CONFIG_SPL_SPI_SUPPORT=y +CONFIG_DEFAULT_DEVICE_TREE="da850-evm" +CONFIG_SYS_EXTRA_OPTIONS="MAC_ADDR_IN_SPIFLASH" CONFIG_BOOTDELAY=3 -CONFIG_USE_BOOTARGS=y -CONFIG_BOOTARGS="mem=32M console=ttyS2,115200n8 root=/dev/mtdblock2 rw noinitrd ip=dhcp" CONFIG_VERSION_VARIABLE=y # CONFIG_DISPLAY_CPUINFO is not set # CONFIG_DISPLAY_BOARDINFO is not set @@ -24,17 +24,24 @@ CONFIG_CRC32_VERIFY=y # CONFIG_CMD_FLASH is not set # CONFIG_CMD_GPIO is not set # CONFIG_CMD_GPT is not set -# CONFIG_CMD_I2C is not set # CONFIG_CMD_PART is not set # CONFIG_CMD_SETEXPR is not set # CONFIG_CMD_TIME is not set # CONFIG_CMD_EXT4 is not set # CONFIG_CMD_FS_GENERIC is not set +CONFIG_CMD_MTDPARTS=y CONFIG_CMD_DIAG=y +CONFIG_OF_CONTROL=y CONFIG_ENV_IS_IN_SPI_FLASH=y +CONFIG_DM=y +CONFIG_DM_I2C=y +CONFIG_DM_I2C_COMPAT=y +CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y CONFIG_SPI_FLASH_STMICRO=y CONFIG_SPI_FLASH_WINBOND=y +CONFIG_SPI_FLASH_MTD=y +CONFIG_DM_SERIAL=y CONFIG_SYS_NS16550=y +CONFIG_DM_SPI=y # CONFIG_FAT_WRITE is not set -CONFIG_OF_LIBFDT=y diff --git a/configs/da850evm_direct_nor_defconfig b/configs/da850evm_direct_nor_defconfig index 24ab89224d..3c8e7ad15a 100644 --- a/configs/da850evm_direct_nor_defconfig +++ b/configs/da850evm_direct_nor_defconfig @@ -2,6 +2,8 @@ CONFIG_ARM=y CONFIG_ARCH_DAVINCI=y CONFIG_TARGET_DA850EVM=y CONFIG_TI_COMMON_CMD_OPTIONS=y +CONFIG_DEFAULT_DEVICE_TREE="da850-evm" +# CONFIG_SYS_MALLOC_F is not set CONFIG_SYS_EXTRA_OPTIONS="USE_NOR,DIRECT_NOR_BOOT" CONFIG_BOOTDELAY=3 CONFIG_USE_BOOTARGS=y @@ -17,7 +19,6 @@ CONFIG_CRC32_VERIFY=y # CONFIG_CMD_EEPROM is not set # CONFIG_CMD_GPIO is not set # CONFIG_CMD_GPT is not set -# CONFIG_CMD_I2C is not set # CONFIG_CMD_MMC is not set # CONFIG_CMD_PART is not set # CONFIG_CMD_SPI is not set @@ -28,11 +29,16 @@ CONFIG_CRC32_VERIFY=y # CONFIG_CMD_FAT is not set # CONFIG_CMD_FS_GENERIC is not set CONFIG_CMD_DIAG=y +CONFIG_OF_CONTROL=y CONFIG_ENV_IS_IN_FLASH=y +CONFIG_DM=y +CONFIG_DM_I2C=y +CONFIG_DM_I2C_COMPAT=y # CONFIG_MMC is not set CONFIG_MTD_NOR_FLASH=y +CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y CONFIG_SPI_FLASH_STMICRO=y CONFIG_SPI_FLASH_WINBOND=y CONFIG_SYS_NS16550=y -CONFIG_OF_LIBFDT=y +CONFIG_DM_SPI=y diff --git a/configs/db-88f6820-amc_defconfig b/configs/db-88f6820-amc_defconfig index 3074994ec6..e73d883cbe 100644 --- a/configs/db-88f6820-amc_defconfig +++ b/configs/db-88f6820-amc_defconfig @@ -47,8 +47,8 @@ CONFIG_SPI_FLASH=y CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_STMICRO=y -CONFIG_PHYLIB=y CONFIG_PHY_GIGE=y +CONFIG_MVNETA=y CONFIG_PCI=y CONFIG_DEBUG_UART_BASE=0xd0012000 CONFIG_DEBUG_UART_CLOCK=200000000 diff --git a/configs/db-88f6820-gp_defconfig b/configs/db-88f6820-gp_defconfig index 9d1771d292..d63992573c 100644 --- a/configs/db-88f6820-gp_defconfig +++ b/configs/db-88f6820-gp_defconfig @@ -45,8 +45,8 @@ CONFIG_MMC_SDHCI_MV=y CONFIG_SPI_FLASH=y CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_STMICRO=y -CONFIG_PHYLIB=y CONFIG_PHY_GIGE=y +CONFIG_MVNETA=y CONFIG_PCI=y CONFIG_SCSI=y CONFIG_DEBUG_UART_BASE=0xd0012000 diff --git a/configs/db-mv784mp-gp_defconfig b/configs/db-mv784mp-gp_defconfig index 9458f8c438..03035d1e36 100644 --- a/configs/db-mv784mp-gp_defconfig +++ b/configs/db-mv784mp-gp_defconfig @@ -44,8 +44,8 @@ CONFIG_NAND_PXA3XX=y CONFIG_SPI_FLASH=y CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_STMICRO=y -CONFIG_PHYLIB=y CONFIG_PHY_GIGE=y +CONFIG_MVNETA=y CONFIG_PCI=y CONFIG_DEBUG_UART_BASE=0xd0012000 CONFIG_DEBUG_UART_CLOCK=250000000 diff --git a/configs/dra7xx_evm_defconfig b/configs/dra7xx_evm_defconfig index 53903bf730..215fc61dc6 100644 --- a/configs/dra7xx_evm_defconfig +++ b/configs/dra7xx_evm_defconfig @@ -7,7 +7,6 @@ CONFIG_TARGET_DRA7XX_EVM=y # CONFIG_SPL_NAND_SUPPORT is not set CONFIG_SPL_SPI_FLASH_SUPPORT=y CONFIG_SPL_SPI_SUPPORT=y -CONFIG_SPL_STACK_R_ADDR=0x82000000 CONFIG_ARMV7_LPAE=y CONFIG_DEFAULT_DEVICE_TREE="dra7-evm" CONFIG_SPL_LOAD_FIT=y @@ -19,7 +18,6 @@ CONFIG_VERSION_VARIABLE=y CONFIG_BOARD_EARLY_INIT_F=y CONFIG_SPL=y CONFIG_SPL_SYS_MALLOC_SIMPLE=y -CONFIG_SPL_STACK_R=y CONFIG_SPL_SEPARATE_BSS=y CONFIG_SPL_DMA_SUPPORT=y CONFIG_SPL_OS_BOOT=y diff --git a/configs/dra7xx_hs_evm_defconfig b/configs/dra7xx_hs_evm_defconfig index 06d8834119..c88229cead 100644 --- a/configs/dra7xx_hs_evm_defconfig +++ b/configs/dra7xx_hs_evm_defconfig @@ -11,7 +11,6 @@ CONFIG_TARGET_DRA7XX_EVM=y # CONFIG_SPL_NAND_SUPPORT is not set CONFIG_SPL_SPI_FLASH_SUPPORT=y CONFIG_SPL_SPI_SUPPORT=y -CONFIG_SPL_STACK_R_ADDR=0x82000000 CONFIG_ARMV7_LPAE=y CONFIG_DEFAULT_DEVICE_TREE="dra7-evm" CONFIG_FIT_IMAGE_POST_PROCESS=y @@ -25,7 +24,6 @@ CONFIG_VERSION_VARIABLE=y CONFIG_BOARD_EARLY_INIT_F=y CONFIG_SPL=y CONFIG_SPL_SYS_MALLOC_SIMPLE=y -CONFIG_SPL_STACK_R=y CONFIG_SPL_SEPARATE_BSS=y CONFIG_SPL_DMA_SUPPORT=y CONFIG_HUSH_PARSER=y diff --git a/configs/ds414_defconfig b/configs/ds414_defconfig index 96bdbeb0ea..f05ddd0de8 100644 --- a/configs/ds414_defconfig +++ b/configs/ds414_defconfig @@ -38,8 +38,8 @@ CONFIG_SPL_OF_TRANSLATE=y CONFIG_SPI_FLASH=y CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_STMICRO=y -CONFIG_PHYLIB=y CONFIG_PHY_GIGE=y +CONFIG_MVNETA=y CONFIG_PCI=y CONFIG_DEBUG_UART_BASE=0xd0012000 CONFIG_DEBUG_UART_CLOCK=250000000 diff --git a/configs/evb-rv1108_defconfig b/configs/evb-rv1108_defconfig index ab4276ac8c..7036f433ee 100644 --- a/configs/evb-rv1108_defconfig +++ b/configs/evb-rv1108_defconfig @@ -5,8 +5,16 @@ CONFIG_TARGET_EVB_RV1108=y CONFIG_DEFAULT_DEVICE_TREE="rv1108-evb" CONFIG_DEBUG_UART=y # CONFIG_DISPLAY_CPUINFO is not set +CONFIG_FASTBOOT=y +CONFIG_USB_FUNCTION_FASTBOOT=y +CONFIG_CMD_FASTBOOT=y +CONFIG_FASTBOOT_BUF_ADDR=0x62000000 +CONFIG_FASTBOOT_BUF_SIZE=0x08000000 +CONFIG_FASTBOOT_FLASH=y +CONFIG_FASTBOOT_FLASH_MMC_DEV=1 # CONFIG_CMD_IMLS is not set CONFIG_CMD_SF=y +CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_CACHE=y CONFIG_CMD_TIME=y @@ -26,6 +34,7 @@ CONFIG_ETH_DESIGNWARE=y CONFIG_GMAC_ROCKCHIP=y CONFIG_PINCTRL=y CONFIG_PINCTRL_ROCKCHIP_RV1108=y +CONFIG_DM_REGULATOR_FIXED=y CONFIG_BAUDRATE=1500000 # CONFIG_SPL_SERIAL_PRESENT is not set CONFIG_DEBUG_UART_BASE=0x10210000 @@ -33,4 +42,16 @@ CONFIG_DEBUG_UART_CLOCK=24000000 CONFIG_DEBUG_UART_SHIFT=2 CONFIG_SYSRESET=y CONFIG_USB=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_GENERIC=y +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_GENERIC=y +CONFIG_USB_DWC2=y +CONFIG_USB_STORAGE=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_DWC2_OTG=y +CONFIG_USB_GADGET_DOWNLOAD=y +CONFIG_G_DNL_MANUFACTURER="Rockchip" +CONFIG_G_DNL_VENDOR_NUM=0x2207 +CONFIG_G_DNL_PRODUCT_NUM=0x110a CONFIG_ERRNO_STR=y diff --git a/configs/firefly-rk3288_defconfig b/configs/firefly-rk3288_defconfig index 82da6016e6..178c879e26 100644 --- a/configs/firefly-rk3288_defconfig +++ b/configs/firefly-rk3288_defconfig @@ -73,7 +73,6 @@ CONFIG_USB=y CONFIG_USB_DWC2=y CONFIG_USB_STORAGE=y CONFIG_USB_KEYBOARD=y -CONFIG_SYS_USB_EVENT_POLL=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_DWC2_OTG=y CONFIG_USB_GADGET_DOWNLOAD=y diff --git a/configs/lion-rk3368_defconfig b/configs/lion-rk3368_defconfig index 45a12a8b27..c7ee7b3f97 100644 --- a/configs/lion-rk3368_defconfig +++ b/configs/lion-rk3368_defconfig @@ -19,6 +19,11 @@ CONFIG_FIT=y CONFIG_FIT_VERBOSE=y CONFIG_SPL_LOAD_FIT=y CONFIG_SPL_FIT_SOURCE="board/theobroma-systems/lion_rk3368/fit_spl_atf.its" +CONFIG_BOOTSTAGE=y +CONFIG_SPL_BOOTSTAGE=y +CONFIG_BOOTSTAGE_REPORT=y +CONFIG_BOOTSTAGE_FDT=y +CONFIG_ENV_IS_IN_MMC=y # CONFIG_DISPLAY_CPUINFO is not set CONFIG_ARCH_EARLY_INIT_R=y CONFIG_SPL=y @@ -37,10 +42,12 @@ CONFIG_TPL_DRIVERS_MISC_SUPPORT=y CONFIG_CMD_GPIO=y CONFIG_CMD_MMC=y CONFIG_CMD_SF=y +CONFIG_CMD_BOOTSTAGE=y CONFIG_CMD_REGULATOR=y CONFIG_CMD_MTDPARTS=y CONFIG_SPL_OF_CONTROL=y CONFIG_TPL_OF_CONTROL=y +CONFIG_OF_LIVE=y CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names interrupt-parent" CONFIG_TPL_OF_PLATDATA=y CONFIG_ENV_IS_IN_MMC=y diff --git a/configs/ls1043ardb_sdcard_defconfig b/configs/ls1043ardb_sdcard_defconfig index efdaaa3d69..f6ea06bfb0 100644 --- a/configs/ls1043ardb_sdcard_defconfig +++ b/configs/ls1043ardb_sdcard_defconfig @@ -3,7 +3,6 @@ CONFIG_TARGET_LS1043ARDB=y CONFIG_SPL_LIBCOMMON_SUPPORT=y CONFIG_SPL_LIBGENERIC_SUPPORT=y CONFIG_FSL_LS_PPA=y -CONFIG_SPL_FSL_LS_PPA=y CONFIG_SPL_MMC_SUPPORT=y CONFIG_SPL_SERIAL_SUPPORT=y CONFIG_SPL_DRIVERS_MISC_SUPPORT=y diff --git a/configs/ls1046ardb_sdcard_defconfig b/configs/ls1046ardb_sdcard_defconfig index 600990ea60..1d7ed3b23a 100644 --- a/configs/ls1046ardb_sdcard_defconfig +++ b/configs/ls1046ardb_sdcard_defconfig @@ -1,7 +1,6 @@ CONFIG_ARM=y CONFIG_TARGET_LS1046ARDB=y CONFIG_FSL_LS_PPA=y -CONFIG_SPL_FSL_LS_PPA=y CONFIG_DEFAULT_DEVICE_TREE="fsl-ls1046a-rdb" CONFIG_DISTRO_DEFAULTS=y CONFIG_FIT_VERBOSE=y diff --git a/configs/maxbcm_defconfig b/configs/maxbcm_defconfig index 131d5e1d8e..5efaff3b28 100644 --- a/configs/maxbcm_defconfig +++ b/configs/maxbcm_defconfig @@ -32,8 +32,8 @@ CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_SPANSION=y CONFIG_SPI_FLASH_STMICRO=y -CONFIG_PHYLIB=y CONFIG_PHY_GIGE=y +CONFIG_MVNETA=y CONFIG_DEBUG_UART_BASE=0xd0012000 CONFIG_DEBUG_UART_CLOCK=250000000 CONFIG_DEBUG_UART_SHIFT=2 diff --git a/configs/mx6cuboxi_defconfig b/configs/mx6cuboxi_defconfig index 5490e3546b..27171fbddf 100644 --- a/configs/mx6cuboxi_defconfig +++ b/configs/mx6cuboxi_defconfig @@ -34,6 +34,5 @@ CONFIG_DM_THERMAL=y CONFIG_USB=y CONFIG_USB_STORAGE=y CONFIG_USB_KEYBOARD=y -CONFIG_SYS_USB_EVENT_POLL=y # CONFIG_VIDEO_SW_CURSOR is not set CONFIG_OF_LIBFDT=y diff --git a/configs/mx6sabresd_defconfig b/configs/mx6sabresd_defconfig index 0e49e69c8c..ad5d448539 100644 --- a/configs/mx6sabresd_defconfig +++ b/configs/mx6sabresd_defconfig @@ -18,6 +18,9 @@ CONFIG_SPL=y CONFIG_SPL_EXT_SUPPORT=y CONFIG_SPL_I2C_SUPPORT=y CONFIG_SPL_OS_BOOT=y +CONFIG_SPL_USB_HOST_SUPPORT=y +CONFIG_SPL_USB_GADGET_SUPPORT=y +CONFIG_SPL_USB_SDP_SUPPORT=y CONFIG_HUSH_PARSER=y CONFIG_CMD_BOOTZ=y # CONFIG_CMD_IMLS is not set @@ -31,6 +34,7 @@ CONFIG_CMD_PART=y CONFIG_CMD_PCI=y CONFIG_CMD_SF=y CONFIG_CMD_USB=y +CONFIG_CMD_USB_SDP=y CONFIG_CMD_DHCP=y CONFIG_CMD_MII=y CONFIG_CMD_PING=y diff --git a/configs/omap3_evm_defconfig b/configs/omap3_evm_defconfig index 962ffa0729..bae67de718 100644 --- a/configs/omap3_evm_defconfig +++ b/configs/omap3_evm_defconfig @@ -5,7 +5,6 @@ CONFIG_SYS_TEXT_BASE=0x80100000 CONFIG_SYS_MALLOC_F_LEN=0x2000 CONFIG_SYS_MPUCLK=720 CONFIG_TARGET_OMAP3_EVM=y -CONFIG_SPL_STACK_R_ADDR=0x82000000 CONFIG_DISTRO_DEFAULTS=y CONFIG_BOOTDELAY=3 CONFIG_SYS_CONSOLE_INFO_QUIET=y @@ -13,7 +12,6 @@ CONFIG_DEFAULT_FDT_FILE="omap3-evm.dtb" CONFIG_VERSION_VARIABLE=y CONFIG_SPL=y CONFIG_SPL_SYS_MALLOC_SIMPLE=y -CONFIG_SPL_STACK_R=y # CONFIG_SPL_EXT_SUPPORT is not set CONFIG_SPL_MTD_SUPPORT=y CONFIG_SYS_PROMPT="OMAP3_EVM # " diff --git a/configs/omap3_logic_defconfig b/configs/omap3_logic_defconfig index b8f25883d8..adffcd981c 100644 --- a/configs/omap3_logic_defconfig +++ b/configs/omap3_logic_defconfig @@ -3,13 +3,11 @@ CONFIG_ARCH_OMAP2PLUS=y CONFIG_TI_COMMON_CMD_OPTIONS=y CONFIG_SYS_MALLOC_F_LEN=0x2000 CONFIG_TARGET_OMAP3_LOGIC=y -CONFIG_SPL_STACK_R_ADDR=0x82000000 CONFIG_DEFAULT_DEVICE_TREE="logicpd-torpedo-37xx-devkit" CONFIG_SYS_CONSOLE_INFO_QUIET=y CONFIG_VERSION_VARIABLE=y CONFIG_SPL=y CONFIG_SPL_SYS_MALLOC_SIMPLE=y -CONFIG_SPL_STACK_R=y CONFIG_SPL_MTD_SUPPORT=y CONFIG_SPL_OS_BOOT=y CONFIG_HUSH_PARSER=y diff --git a/configs/omap3_overo_defconfig b/configs/omap3_overo_defconfig index 5d1cbe993a..4043c42e4b 100644 --- a/configs/omap3_overo_defconfig +++ b/configs/omap3_overo_defconfig @@ -2,12 +2,10 @@ CONFIG_ARM=y CONFIG_ARCH_OMAP2PLUS=y CONFIG_SYS_MALLOC_F_LEN=0x2000 CONFIG_TARGET_OMAP3_OVERO=y -CONFIG_SPL_STACK_R_ADDR=0x82000000 CONFIG_SYS_CONSOLE_INFO_QUIET=y CONFIG_VERSION_VARIABLE=y CONFIG_SPL=y CONFIG_SPL_SYS_MALLOC_SIMPLE=y -CONFIG_SPL_STACK_R=y CONFIG_SPL_MTD_SUPPORT=y CONFIG_SPL_OS_BOOT=y CONFIG_HUSH_PARSER=y diff --git a/configs/puma-rk3399_defconfig b/configs/puma-rk3399_defconfig index 1badf80beb..2ab2516c01 100644 --- a/configs/puma-rk3399_defconfig +++ b/configs/puma-rk3399_defconfig @@ -35,6 +35,7 @@ CONFIG_CMD_TIME=y CONFIG_CMD_PMIC=y CONFIG_CMD_REGULATOR=y CONFIG_SPL_OF_CONTROL=y +CONFIG_OF_LIVE=y CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" CONFIG_ENV_IS_IN_MMC=y CONFIG_REGMAP=y diff --git a/configs/rpi_2_defconfig b/configs/rpi_2_defconfig index 2345697701..03705975bf 100644 --- a/configs/rpi_2_defconfig +++ b/configs/rpi_2_defconfig @@ -26,7 +26,6 @@ CONFIG_DM_USB=y CONFIG_USB_DWC2=y CONFIG_USB_STORAGE=y CONFIG_USB_KEYBOARD=y -CONFIG_SYS_USB_EVENT_POLL=y CONFIG_USB_HOST_ETHER=y CONFIG_USB_ETHER_SMSC95XX=y CONFIG_DM_VIDEO=y diff --git a/configs/rpi_3_32b_defconfig b/configs/rpi_3_32b_defconfig index bb56a9e4e1..31d67ccdc9 100644 --- a/configs/rpi_3_32b_defconfig +++ b/configs/rpi_3_32b_defconfig @@ -28,7 +28,6 @@ CONFIG_DM_USB=y CONFIG_USB_DWC2=y CONFIG_USB_STORAGE=y CONFIG_USB_KEYBOARD=y -CONFIG_SYS_USB_EVENT_POLL=y CONFIG_USB_HOST_ETHER=y CONFIG_USB_ETHER_SMSC95XX=y CONFIG_DM_VIDEO=y diff --git a/configs/rpi_3_defconfig b/configs/rpi_3_defconfig index 6edacd69a2..1ac3a96e25 100644 --- a/configs/rpi_3_defconfig +++ b/configs/rpi_3_defconfig @@ -28,7 +28,6 @@ CONFIG_DM_USB=y CONFIG_USB_DWC2=y CONFIG_USB_STORAGE=y CONFIG_USB_KEYBOARD=y -CONFIG_SYS_USB_EVENT_POLL=y CONFIG_USB_HOST_ETHER=y CONFIG_USB_ETHER_SMSC95XX=y CONFIG_DM_VIDEO=y diff --git a/configs/rpi_defconfig b/configs/rpi_defconfig index 2e81966c14..87e88223ee 100644 --- a/configs/rpi_defconfig +++ b/configs/rpi_defconfig @@ -26,7 +26,6 @@ CONFIG_DM_USB=y CONFIG_USB_DWC2=y CONFIG_USB_STORAGE=y CONFIG_USB_KEYBOARD=y -CONFIG_SYS_USB_EVENT_POLL=y CONFIG_USB_HOST_ETHER=y CONFIG_USB_ETHER_SMSC95XX=y CONFIG_DM_VIDEO=y diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 310b8acc29..632e0aa0ee 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -175,7 +175,6 @@ CONFIG_DM_USB=y CONFIG_USB_EMUL=y CONFIG_USB_STORAGE=y CONFIG_USB_KEYBOARD=y -CONFIG_SYS_USB_EVENT_POLL=y CONFIG_DM_VIDEO=y CONFIG_CONSOLE_ROTATION=y CONFIG_CONSOLE_TRUETYPE=y diff --git a/configs/sandbox_flattree_defconfig b/configs/sandbox_flattree_defconfig index 50ea35e64b..b1a341551f 100644 --- a/configs/sandbox_flattree_defconfig +++ b/configs/sandbox_flattree_defconfig @@ -160,7 +160,6 @@ CONFIG_DM_USB=y CONFIG_USB_EMUL=y CONFIG_USB_STORAGE=y CONFIG_USB_KEYBOARD=y -CONFIG_SYS_USB_EVENT_POLL=y CONFIG_DM_VIDEO=y CONFIG_CONSOLE_ROTATION=y CONFIG_CONSOLE_TRUETYPE=y diff --git a/configs/sandbox_noblk_defconfig b/configs/sandbox_noblk_defconfig index 693c14bc60..39101741b1 100644 --- a/configs/sandbox_noblk_defconfig +++ b/configs/sandbox_noblk_defconfig @@ -168,7 +168,6 @@ CONFIG_DM_USB=y CONFIG_USB_EMUL=y CONFIG_USB_STORAGE=y CONFIG_USB_KEYBOARD=y -CONFIG_SYS_USB_EVENT_POLL=y CONFIG_DM_VIDEO=y CONFIG_CONSOLE_ROTATION=y CONFIG_CONSOLE_TRUETYPE=y diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig index db9129456b..7f03c6ed03 100644 --- a/configs/sandbox_spl_defconfig +++ b/configs/sandbox_spl_defconfig @@ -178,7 +178,6 @@ CONFIG_DM_USB=y CONFIG_USB_EMUL=y CONFIG_USB_STORAGE=y CONFIG_USB_KEYBOARD=y -CONFIG_SYS_USB_EVENT_POLL=y CONFIG_DM_VIDEO=y CONFIG_CONSOLE_ROTATION=y CONFIG_CONSOLE_TRUETYPE=y diff --git a/configs/seaboard_defconfig b/configs/seaboard_defconfig index ea4546bce4..810cfaa498 100644 --- a/configs/seaboard_defconfig +++ b/configs/seaboard_defconfig @@ -36,7 +36,6 @@ CONFIG_USB_ULPI_VIEWPORT=y CONFIG_USB_ULPI=y CONFIG_USB_STORAGE=y CONFIG_USB_KEYBOARD=y -CONFIG_SYS_USB_EVENT_POLL=y CONFIG_USB_HOST_ETHER=y CONFIG_USB_ETHER_ASIX=y CONFIG_DM_VIDEO=y diff --git a/configs/sheep-rk3368_defconfig b/configs/sheep-rk3368_defconfig index b862a14751..a7991afae2 100644 --- a/configs/sheep-rk3368_defconfig +++ b/configs/sheep-rk3368_defconfig @@ -2,6 +2,7 @@ CONFIG_ARM=y CONFIG_ARCH_ROCKCHIP=y CONFIG_SYS_MALLOC_F_LEN=0x1000 CONFIG_ROCKCHIP_RK3368=y +CONFIG_TARGET_SHEEP=y CONFIG_DEFAULT_DEVICE_TREE="rk3368-sheep" CONFIG_DEBUG_UART=y CONFIG_ANDROID_BOOT_IMAGE=y @@ -14,6 +15,7 @@ CONFIG_CLK=y CONFIG_MMC_DW=y CONFIG_MMC_DW_ROCKCHIP=y CONFIG_PINCTRL=y +CONFIG_PINCTRL_ROCKCHIP_RK3368=y CONFIG_RAM=y CONFIG_DEBUG_UART_BASE=0xFF1b0000 CONFIG_DEBUG_UART_CLOCK=24000000 diff --git a/configs/socfpga_de0_nano_soc_defconfig b/configs/socfpga_de0_nano_soc_defconfig index 0bb9121c26..b4fd29d207 100644 --- a/configs/socfpga_de0_nano_soc_defconfig +++ b/configs/socfpga_de0_nano_soc_defconfig @@ -12,6 +12,7 @@ CONFIG_DEFAULT_FDT_FILE="socfpga_cyclone5_de0_nano_soc.dtb" CONFIG_VERSION_VARIABLE=y # CONFIG_DISPLAY_BOARDINFO is not set CONFIG_SPL=y +# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set CONFIG_SPL_SYS_MALLOC_SIMPLE=y CONFIG_SPL_STACK_R=y CONFIG_HUSH_PARSER=y @@ -24,6 +25,7 @@ CONFIG_CMD_DFU=y CONFIG_CMD_GPIO=y CONFIG_CMD_I2C=y CONFIG_CMD_MMC=y +CONFIG_CMD_PART=y CONFIG_CMD_SF=y CONFIG_CMD_SPI=y CONFIG_CMD_USB=y @@ -38,6 +40,7 @@ CONFIG_CMD_FAT=y CONFIG_CMD_FS_GENERIC=y CONFIG_CMD_UBI=y CONFIG_ENV_IS_IN_MMC=y +CONFIG_EFI_PARTITION=y CONFIG_SPL_DM=y CONFIG_DFU_MMC=y CONFIG_FPGA_SOCFPGA=y diff --git a/configs/stih410-b2260_defconfig b/configs/stih410-b2260_defconfig index 10e1a2d06d..8fd1ff26a2 100644 --- a/configs/stih410-b2260_defconfig +++ b/configs/stih410-b2260_defconfig @@ -2,27 +2,58 @@ CONFIG_ARM=y CONFIG_ARCH_STI=y CONFIG_IDENT_STRING="STMicroelectronics STiH410-B2260" CONFIG_DEFAULT_DEVICE_TREE="stih410-b2260" +CONFIG_DISTRO_DEFAULTS=y CONFIG_FIT=y CONFIG_FIT_VERBOSE=y CONFIG_USE_BOOTARGS=y CONFIG_BOOTARGS="console=ttyS0,115200 earlyprintk consoleblank=0 ignore_loglevel" # CONFIG_DISPLAY_CPUINFO is not set CONFIG_SYS_PROMPT="stih410-b2260 => " +CONFIG_FASTBOOT=y +CONFIG_USB_FUNCTION_FASTBOOT=y +CONFIG_CMD_FASTBOOT=y +CONFIG_ANDROID_BOOT_IMAGE=y +CONFIG_FASTBOOT_BUF_ADDR=0x40000000 +CONFIG_FASTBOOT_BUF_SIZE=0x3DF00000 +CONFIG_FASTBOOT_FLASH=y +CONFIG_FASTBOOT_FLASH_MMC_DEV=0 # CONFIG_CMD_IMLS is not set +CONFIG_CMD_GPT=y CONFIG_CMD_MMC=y +CONFIG_CMD_USB=y CONFIG_CMD_TIME=y CONFIG_CMD_TIMER=y -CONFIG_CMD_EXT2=y -CONFIG_CMD_EXT4=y -CONFIG_CMD_FAT=y -CONFIG_CMD_FS_GENERIC=y +CONFIG_CMD_EXT4_WRITE=y +# CONFIG_ISO_PARTITION is not set CONFIG_OF_CONTROL=y CONFIG_REGMAP=y CONFIG_SYSCON=y +CONFIG_CLK=y +CONFIG_MISC=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_STI=y +CONFIG_PHY=y +CONFIG_STI_USB_PHY=y CONFIG_PINCTRL=y +CONFIG_STI_RESET=y CONFIG_STI_ASC_SERIAL=y CONFIG_SYSRESET=y CONFIG_TIMER=y +CONFIG_USB=y +CONFIG_DM_USB=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_DWC3=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_GENERIC=y +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_GENERIC=y +CONFIG_USB_DWC3=y +CONFIG_USB_DWC3_GADGET=y +CONFIG_USB_STORAGE=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_DOWNLOAD=y +CONFIG_G_DNL_MANUFACTURER="STMicroelectronics" +CONFIG_G_DNL_VENDOR_NUM=0x483 +CONFIG_G_DNL_PRODUCT_NUM=0x7270 +CONFIG_OF_LIBFDT_OVERLAY=y CONFIG_SPL_OF_LIBFDT=y diff --git a/configs/stm32h743-disco_defconfig b/configs/stm32h743-disco_defconfig new file mode 100644 index 0000000000..eed921d24b --- /dev/null +++ b/configs/stm32h743-disco_defconfig @@ -0,0 +1,30 @@ +CONFIG_ARM=y +CONFIG_STM32=y +CONFIG_SYS_MALLOC_F_LEN=0xF00 +CONFIG_STM32H7=y +CONFIG_TARGET_STM32H743_DISCO=y +CONFIG_DEFAULT_DEVICE_TREE="stm32h743i-disco" +CONFIG_BOOTDELAY=3 +CONFIG_DEFAULT_FDT_FILE="stm32h743i-disco" +# CONFIG_DISPLAY_CPUINFO is not set +CONFIG_BOARD_EARLY_INIT_F=y +CONFIG_HUSH_PARSER=y +CONFIG_SYS_PROMPT="U-Boot > " +CONFIG_AUTOBOOT_KEYED=y +CONFIG_AUTOBOOT_PROMPT="Hit SPACE in %d seconds to stop autoboot.\n" +CONFIG_AUTOBOOT_STOP_STR=" " +CONFIG_CMD_BOOTZ=y +# CONFIG_CMD_IMLS is not set +# CONFIG_CMD_FPGA is not set +# CONFIG_CMD_SETEXPR is not set +# CONFIG_CMD_NET is not set +# CONFIG_CMD_NFS is not set +CONFIG_CMD_TIMER=y +CONFIG_OF_CONTROL=y +CONFIG_OF_EMBED=y +# CONFIG_PINCTRL_FULL is not set +# CONFIG_SPL_SERIAL_PRESENT is not set +CONFIG_REGEX=y +CONFIG_LIB_RAND=y +CONFIG_OF_LIBFDT_OVERLAY=y +# CONFIG_EFI_LOADER is not set diff --git a/configs/stm32h743-eval_defconfig b/configs/stm32h743-eval_defconfig new file mode 100644 index 0000000000..61e702e001 --- /dev/null +++ b/configs/stm32h743-eval_defconfig @@ -0,0 +1,30 @@ +CONFIG_ARM=y +CONFIG_STM32=y +CONFIG_SYS_MALLOC_F_LEN=0xF00 +CONFIG_STM32H7=y +CONFIG_TARGET_STM32H743_EVAL=y +CONFIG_DEFAULT_DEVICE_TREE="stm32h743i-eval" +CONFIG_BOOTDELAY=3 +CONFIG_DEFAULT_FDT_FILE="stm32h743i-eval" +# CONFIG_DISPLAY_CPUINFO is not set +CONFIG_BOARD_EARLY_INIT_F=y +CONFIG_HUSH_PARSER=y +CONFIG_SYS_PROMPT="U-Boot > " +CONFIG_AUTOBOOT_KEYED=y +CONFIG_AUTOBOOT_PROMPT="Hit SPACE in %d seconds to stop autoboot.\n" +CONFIG_AUTOBOOT_STOP_STR=" " +CONFIG_CMD_BOOTZ=y +# CONFIG_CMD_IMLS is not set +# CONFIG_CMD_FPGA is not set +# CONFIG_CMD_SETEXPR is not set +# CONFIG_CMD_NET is not set +# CONFIG_CMD_NFS is not set +CONFIG_CMD_TIMER=y +CONFIG_OF_CONTROL=y +CONFIG_OF_EMBED=y +# CONFIG_PINCTRL_FULL is not set +# CONFIG_SPL_SERIAL_PRESENT is not set +CONFIG_REGEX=y +CONFIG_LIB_RAND=y +CONFIG_OF_LIBFDT_OVERLAY=y +# CONFIG_EFI_LOADER is not set diff --git a/configs/theadorable_debug_defconfig b/configs/theadorable_debug_defconfig index a39497984b..0b4025c228 100644 --- a/configs/theadorable_debug_defconfig +++ b/configs/theadorable_debug_defconfig @@ -51,8 +51,8 @@ CONFIG_DM_GPIO=y CONFIG_SPI_FLASH=y CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_STMICRO=y -CONFIG_PHYLIB=y CONFIG_PHY_GIGE=y +CONFIG_MVNETA=y CONFIG_PCI=y CONFIG_DEBUG_UART_BASE=0xd0012000 CONFIG_DEBUG_UART_CLOCK=250000000 diff --git a/configs/theadorable_defconfig b/configs/theadorable_defconfig deleted file mode 100644 index 0639f81328..0000000000 --- a/configs/theadorable_defconfig +++ /dev/null @@ -1,54 +0,0 @@ -CONFIG_ARM=y -CONFIG_ARCH_MVEBU=y -CONFIG_SPL_LIBCOMMON_SUPPORT=y -CONFIG_SPL_LIBGENERIC_SUPPORT=y -CONFIG_SYS_MALLOC_F_LEN=0x2000 -CONFIG_TARGET_THEADORABLE=y -CONFIG_SPL_SERIAL_SUPPORT=y -CONFIG_SPL_SPI_FLASH_SUPPORT=y -CONFIG_SPL_SPI_SUPPORT=y -CONFIG_VIDEO=y -CONFIG_DEFAULT_DEVICE_TREE="armada-xp-theadorable" -CONFIG_DEBUG_UART=y -# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set -CONFIG_FIT=y -CONFIG_BOOTDELAY=3 -# CONFIG_CONSOLE_MUX is not set -CONFIG_SYS_CONSOLE_INFO_QUIET=y -# CONFIG_DISPLAY_BOARDINFO is not set -CONFIG_SPL=y -CONFIG_SPL_I2C_SUPPORT=y -CONFIG_HUSH_PARSER=y -CONFIG_CMD_BOOTZ=y -# CONFIG_CMD_IMLS is not set -# CONFIG_CMD_FLASH is not set -CONFIG_CMD_I2C=y -CONFIG_CMD_SF=y -# CONFIG_CMD_SETEXPR is not set -# CONFIG_CMD_NET is not set -# CONFIG_CMD_NFS is not set -CONFIG_CMD_BMP=y -CONFIG_CMD_CACHE=y -CONFIG_CMD_TIME=y -CONFIG_CMD_EXT2=y -CONFIG_CMD_EXT4=y -CONFIG_CMD_FAT=y -CONFIG_CMD_FS_GENERIC=y -CONFIG_EFI_PARTITION=y -# CONFIG_PARTITION_UUIDS is not set -# CONFIG_SPL_PARTITION_UUIDS is not set -CONFIG_SPL_OF_TRANSLATE=y -CONFIG_FPGA_ALTERA=y -CONFIG_DM_GPIO=y -# CONFIG_MMC is not set -CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_MACRONIX=y -CONFIG_SPI_FLASH_STMICRO=y -CONFIG_DEBUG_UART_BASE=0xd0012000 -CONFIG_DEBUG_UART_CLOCK=250000000 -CONFIG_DEBUG_UART_SHIFT=2 -CONFIG_SYS_NS16550=y -CONFIG_VIDEO_MVEBU=y -# CONFIG_VIDEO_SW_CURSOR is not set -CONFIG_REGEX=y -CONFIG_LIB_RAND=y diff --git a/configs/ti816x_evm_defconfig b/configs/ti816x_evm_defconfig index 4341d8d01f..d269e3641a 100644 --- a/configs/ti816x_evm_defconfig +++ b/configs/ti816x_evm_defconfig @@ -9,7 +9,6 @@ CONFIG_SPL_MMC_SUPPORT=y CONFIG_SPL_SERIAL_SUPPORT=y CONFIG_SPL_LIBDISK_SUPPORT=y CONFIG_SPL_NAND_SUPPORT=y -CONFIG_SPL_STACK_R_ADDR=0x82000000 CONFIG_SPL_FAT_SUPPORT=y CONFIG_DEFAULT_DEVICE_TREE="dm8168-evm" CONFIG_DISTRO_DEFAULTS=y @@ -20,7 +19,6 @@ CONFIG_SYS_CONSOLE_INFO_QUIET=y CONFIG_VERSION_VARIABLE=y # CONFIG_DISPLAY_BOARDINFO is not set CONFIG_SPL=y -CONFIG_SPL_STACK_R=y CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x300 # CONFIG_CMD_IMLS is not set diff --git a/configs/turris_omnia_defconfig b/configs/turris_omnia_defconfig index a3834acb96..870cfd51ad 100644 --- a/configs/turris_omnia_defconfig +++ b/configs/turris_omnia_defconfig @@ -33,8 +33,8 @@ CONFIG_MISC=y CONFIG_ATSHA204A=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_MV=y -CONFIG_PHYLIB=y CONFIG_PHY_GIGE=y +CONFIG_MVNETA=y CONFIG_DEBUG_UART_BASE=0xd0012000 CONFIG_DEBUG_UART_CLOCK=250000000 CONFIG_DEBUG_UART_SHIFT=2 diff --git a/configs/uniphier_pro4_defconfig b/configs/uniphier_pro4_defconfig deleted file mode 100644 index 7348675f80..0000000000 --- a/configs/uniphier_pro4_defconfig +++ /dev/null @@ -1,49 +0,0 @@ -CONFIG_ARM=y -CONFIG_ARCH_UNIPHIER=y -CONFIG_SYS_TEXT_BASE=0x84000000 -CONFIG_SYS_MALLOC_F_LEN=0x2000 -CONFIG_SPL_MMC_SUPPORT=y -CONFIG_SPL_SERIAL_SUPPORT=y -CONFIG_SPL_NAND_SUPPORT=y -CONFIG_MICRO_SUPPORT_CARD=y -CONFIG_DEFAULT_DEVICE_TREE="uniphier-pro4-ref" -# CONFIG_ARCH_FIXUP_FDT_MEMORY is not set -CONFIG_SPL=y -CONFIG_SPL_NOR_SUPPORT=y -CONFIG_HUSH_PARSER=y -CONFIG_CMD_CONFIG=y -CONFIG_CMD_BOOTZ=y -# CONFIG_CMD_XIMG is not set -# CONFIG_CMD_ENV_EXISTS is not set -# CONFIG_CMD_FPGA is not set -CONFIG_CMD_GPIO=y -CONFIG_CMD_GPT=y -CONFIG_CMD_I2C=y -CONFIG_CMD_MMC=y -CONFIG_CMD_USB=y -CONFIG_CMD_TFTPPUT=y -CONFIG_CMD_PING=y -CONFIG_CMD_CACHE=y -CONFIG_CMD_TIME=y -# CONFIG_CMD_MISC is not set -CONFIG_CMD_FAT=y -CONFIG_CMD_FS_GENERIC=y -# CONFIG_SPL_DOS_PARTITION is not set -# CONFIG_SPL_EFI_PARTITION is not set -CONFIG_NET_RANDOM_ETHADDR=y -CONFIG_GPIO_UNIPHIER=y -CONFIG_MISC=y -CONFIG_I2C_EEPROM=y -CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS=10 -CONFIG_MMC_UNIPHIER=y -CONFIG_NAND=y -CONFIG_NAND_DENALI=y -CONFIG_NAND_DENALI_DT=y -CONFIG_SYS_NAND_DENALI_64BIT=y -CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8 -CONFIG_SPL_NAND_DENALI=y -CONFIG_USB=y -CONFIG_USB_XHCI_HCD=y -CONFIG_USB_EHCI_HCD=y -CONFIG_USB_EHCI_GENERIC=y -CONFIG_USB_STORAGE=y diff --git a/configs/uniphier_pxs2_ld6b_defconfig b/configs/uniphier_v7_defconfig index c242776d9c..3c25484939 100644 --- a/configs/uniphier_pxs2_ld6b_defconfig +++ b/configs/uniphier_v7_defconfig @@ -5,7 +5,7 @@ CONFIG_SYS_MALLOC_F_LEN=0x2000 CONFIG_SPL_MMC_SUPPORT=y CONFIG_SPL_SERIAL_SUPPORT=y CONFIG_SPL_NAND_SUPPORT=y -CONFIG_ARCH_UNIPHIER_PRO5_PXS2_LD6B=y +CONFIG_ARCH_UNIPHIER_V7_MULTI=y CONFIG_MICRO_SUPPORT_CARD=y CONFIG_DEFAULT_DEVICE_TREE="uniphier-pxs2-vodka" # CONFIG_ARCH_FIXUP_FDT_MEMORY is not set @@ -45,4 +45,6 @@ CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8 CONFIG_SPL_NAND_DENALI=y CONFIG_USB=y CONFIG_USB_XHCI_HCD=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_GENERIC=y CONFIG_USB_STORAGE=y diff --git a/configs/ventana_defconfig b/configs/ventana_defconfig index 42353f034e..b11dab1196 100644 --- a/configs/ventana_defconfig +++ b/configs/ventana_defconfig @@ -34,7 +34,6 @@ CONFIG_USB_ULPI_VIEWPORT=y CONFIG_USB_ULPI=y CONFIG_USB_STORAGE=y CONFIG_USB_KEYBOARD=y -CONFIG_SYS_USB_EVENT_POLL=y CONFIG_USB_HOST_ETHER=y CONFIG_USB_ETHER_ASIX=y CONFIG_DM_VIDEO=y diff --git a/configs/vyasa-rk3288_defconfig b/configs/vyasa-rk3288_defconfig new file mode 100644 index 0000000000..7db7b0b6f9 --- /dev/null +++ b/configs/vyasa-rk3288_defconfig @@ -0,0 +1,63 @@ +CONFIG_ARM=y +CONFIG_ARCH_ROCKCHIP=y +CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_ROCKCHIP_RK3288=y +CONFIG_TARGET_VYASA_RK3288=y +CONFIG_SPL_STACK_R_ADDR=0x80000 +CONFIG_DEFAULT_DEVICE_TREE="rk3288-vyasa" +CONFIG_DEBUG_UART=y +CONFIG_ENV_IS_IN_MMC=y +CONFIG_SILENT_CONSOLE=y +# CONFIG_DISPLAY_CPUINFO is not set +CONFIG_SPL_STACK_R=y +CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x2000 +# CONFIG_CMD_IMLS is not set +CONFIG_CMD_GPT=y +CONFIG_CMD_MMC=y +CONFIG_CMD_I2C=y +CONFIG_CMD_GPIO=y +# CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_CACHE=y +CONFIG_CMD_TIME=y +CONFIG_CMD_PMIC=y +CONFIG_CMD_REGULATOR=y +# CONFIG_SPL_DOS_PARTITION is not set +# CONFIG_SPL_ISO_PARTITION is not set +# CONFIG_SPL_EFI_PARTITION is not set +CONFIG_SPL_PARTITION_UUIDS=y +CONFIG_SPL_OF_CONTROL=y +CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" +CONFIG_REGMAP=y +CONFIG_SPL_REGMAP=y +CONFIG_SYSCON=y +CONFIG_SPL_SYSCON=y +# CONFIG_SPL_SIMPLE_BUS is not set +CONFIG_CLK=y +CONFIG_SPL_CLK=y +CONFIG_ROCKCHIP_GPIO=y +CONFIG_SYS_I2C_ROCKCHIP=y +CONFIG_LED=y +CONFIG_LED_GPIO=y +CONFIG_MMC_DW=y +CONFIG_MMC_DW_ROCKCHIP=y +CONFIG_PINCTRL=y +CONFIG_SPL_PINCTRL=y +# CONFIG_SPL_PINCTRL_FULL is not set +CONFIG_PINCTRL_ROCKCHIP_RK3288=y +CONFIG_DM_PMIC=y +# CONFIG_SPL_PMIC_CHILDREN is not set +CONFIG_PMIC_RK8XX=y +CONFIG_REGULATOR_RK8XX=y +CONFIG_DM_REGULATOR_FIXED=y +CONFIG_PWM_ROCKCHIP=y +CONFIG_RAM=y +CONFIG_SPL_RAM=y +CONFIG_DEBUG_UART_BASE=0xff690000 +CONFIG_DEBUG_UART_CLOCK=24000000 +CONFIG_DEBUG_UART_SHIFT=2 +CONFIG_SYS_NS16550=y +CONFIG_SYSRESET=y +CONFIG_CONSOLE_SCROLL_LINES=10 +CONFIG_USE_TINY_PRINTF=y +CONFIG_CMD_DHRYSTONE=y +CONFIG_ERRNO_STR=y diff --git a/doc/README.uniphier b/doc/README.uniphier index fa1f9bcc96..e4fd9a3e3f 100644 --- a/doc/README.uniphier +++ b/doc/README.uniphier @@ -27,17 +27,17 @@ The following tables show <defconfig> and <device-tree> for each board. 32bit SoC boards: - Board | <defconfig> | <device-tree> ----------------|------------------------------|------------------------------ -LD4 reference | uniphier_ld4_sld8_defconfig | uniphier-ld4-ref (default) -sld8 reference | uniphier_ld4_sld8_defconfig | uniphier-sld8-def -Pro4 reference | uniphier_pro4_defconfig | uniphier-pro4-ref (default) -Pro4 Ace | uniphier_pro4_defconfig | uniphier-pro4-ace -Pro4 Sanji | uniphier_pro4_defconfig | uniphier-pro4-sanji -Pro5 4KBOX | uniphier_pxs2_ld6b_defconfig | uniphier-pro5-4kbox -PXs2 Gentil | uniphier_pxs2_ld6b_defconfig | uniphier-pxs2-gentil -PXs2 Vodka | uniphier_pxs2_ld6b_defconfig | uniphier-pxs2-vodka (default) -LD6b reference | uniphier_pxs2_ld6b_defconfig | uniphier-ld6b-ref + Board | <defconfig> | <device-tree> +---------------|-----------------------------|------------------------------ +LD4 reference | uniphier_ld4_sld8_defconfig | uniphier-ld4-ref (default) +sld8 reference | uniphier_ld4_sld8_defconfig | uniphier-sld8-def +Pro4 reference | uniphier_v7_defconfig | uniphier-pro4-ref +Pro4 Ace | uniphier_v7_defconfig | uniphier-pro4-ace +Pro4 Sanji | uniphier_v7_defconfig | uniphier-pro4-sanji +Pro5 4KBOX | uniphier_v7_defconfig | uniphier-pro5-4kbox +PXs2 Gentil | uniphier_v7_defconfig | uniphier-pxs2-gentil +PXs2 Vodka | uniphier_v7_defconfig | uniphier-pxs2-vodka (default) +LD6b reference | uniphier_v7_defconfig | uniphier-ld6b-ref 64bit SoC boards: @@ -47,17 +47,18 @@ LD11 reference | uniphier_v8_defconfig | uniphier-ld11-ref LD11 Global | uniphier_v8_defconfig | uniphier-ld11-global LD20 reference | uniphier_v8_defconfig | uniphier-ld20-ref (default) LD20 Global | uniphier_v8_defconfig | uniphier-ld20-global +PXs3 reference | uniphier_v8_defconfig | uniphier-pxs3-ref For example, to compile the source for PXs2 Vodka board, run the following: - $ make uniphier_pxs2_ld6b_defconfig + $ make uniphier_v7_defconfig $ make CROSS_COMPILE=arm-linux-gnueabihf- DEVICE_TREE=uniphier-pxs2-vodka The device tree marked as (default) can be omitted. `uniphier-pxs2-vodka` is -the default device tree for the configuration `uniphier_pxs2_ld6b_defconfig`, -so the following gives the same result. +the default device tree for the configuration `uniphier_v7_defconfig`, so the +following gives the same result. - $ make uniphier_pxs2_ld6b_defconfig + $ make uniphier_v7_defconfig $ make CROSS_COMPILE=arm-linux-gnueabihf- @@ -178,4 +179,4 @@ newer SoCs. Even if it is, EA[25] is not connected on most of the boards. -- Masahiro Yamada <yamada.masahiro@socionext.com> -Jul. 2017 +Sep. 2017 diff --git a/doc/device-tree-bindings/clock/st,stm32h7-rcc.txt b/doc/device-tree-bindings/clock/st,stm32h7-rcc.txt new file mode 100644 index 0000000000..9d4b5873d9 --- /dev/null +++ b/doc/device-tree-bindings/clock/st,stm32h7-rcc.txt @@ -0,0 +1,152 @@ +STMicroelectronics STM32H7 Reset and Clock Controller +===================================================== + +The RCC IP is both a reset and a clock controller. + +Please refer to clock-bindings.txt for common clock controller binding usage. +Please also refer to reset.txt for common reset controller binding usage. + +Required properties: +- compatible: Should be: + "st,stm32h743-rcc" + +- reg: should be register base and length as documented in the + datasheet + +- #reset-cells: 1, see below + +- #clock-cells : from common clock binding; shall be set to 1 + +- clocks: External oscillator clock phandle + - high speed external clock signal (HSE) + - low speed external clock signal (LSE) + - external I2S clock (I2S_CKIN) + +- st,syscfg: phandle for pwrcfg, mandatory to disable/enable backup domain + write protection (RTC clock). + +- pll x node: Allow to register a pll with specific parameters. + Please see PLL section below. + +Example: + + rcc: rcc@58024400 { + #reset-cells = <1>; + #clock-cells = <2> + compatible = "st,stm32h743-rcc", "st,stm32-rcc"; + reg = <0x58024400 0x400>; + clocks = <&clk_hse>, <&clk_lse>, <&clk_i2s_ckin>; + + st,syscfg = <&pwrcfg>; + + #address-cells = <1>; + #size-cells = <0>; + + vco1@58024430 { + #clock-cells = <0>; + compatible = "stm32,pll"; + reg = <0>; + }; + + vco2@58024438 { + #clock-cells = <0>; + compatible = "stm32,pll"; + reg = <1>; + st,clock-div = <2>; + st,clock-mult = <40>; + st,frac-status = <0>; + st,frac = <0>; + st,vcosel = <1>; + st,pllrge = <2>; + }; + }; + + +STM32H7 PLL +----------- + +The VCO of STM32 PLL could be reprensented like this: + + Vref --------- -------- + ---->| / DIVM |---->| x DIVN | ------> VCO + --------- -------- + ^ + | + ------- + | FRACN | + ------- + +When the PLL is configured in integer mode: +- VCO = ( Vref / DIVM ) * DIVN + +When the PLL is configured in fractional mode: +- VCO = ( Vref / DIVM ) * ( DIVN + FRACN / 2^13) + + +Required properties for pll node: +- compatible: Should be: + "stm32,pll" + +- #clock-cells: from common clock binding; shall be set to 0 +- reg: Should be the pll number. + +Optional properties: +- st,clock-div: DIVM division factor : <1..63> +- st,clock-mult: DIVN multiplication factor : <4..512> + +- st,frac-status: + - 0 Pll is configured in integer mode + - 1 Pll is configure in fractional mode + +- st,frac: Fractional part of the multiplication factor : <0..8191> + +- st,vcosel: VCO selection + - 0: Wide VCO range:192 to 836 MHz + - 1: Medium VCO range:150 to 420 MHz + +- st,pllrge: PLL input frequency range + - 0: The PLL input (Vref / DIVM) clock range frequency is between 1 and 2 MHz + - 1: The PLL input (Vref / DIVM) clock range frequency is between 2 and 4 MHz + - 2: The PLL input (Vref / DIVM) clock range frequency is between 4 and 8 MHz + - 3: The PLL input (Vref / DIVM) clock range frequency is between 8 and 16 MHz + + +The peripheral clock consumer should specify the desired clock by +having the clock ID in its "clocks" phandle cell. + +All available clocks are defined as preprocessor macros in +dt-bindings/clock/stm32h7-clks.h header and can be used in device +tree sources. + +Example: + + timer5: timer@40000c00 { + compatible = "st,stm32-timer"; + reg = <0x40000c00 0x400>; + interrupts = <50>; + clocks = <&rcc TIM5_CK>; + + }; + +Specifying softreset control of devices +======================================= + +Device nodes should specify the reset channel required in their "resets" +property, containing a phandle to the reset device node and an index specifying +which channel to use. +The index is the bit number within the RCC registers bank, starting from RCC +base address. +It is calculated as: index = register_offset / 4 * 32 + bit_offset. +Where bit_offset is the bit offset within the register. + +For example, for CRC reset: + crc = AHB4RSTR_offset / 4 * 32 + CRCRST_bit_offset = 0x88 / 4 * 32 + 19 = 1107 + +All available preprocessor macros for reset are defined dt-bindings//mfd/stm32h7-rcc.h +header and can be used in device tree sources. + +example: + + timer2 { + resets = <&rcc STM32H7_APB1L_RESET(TIM2)>; + }; diff --git a/doc/device-tree-bindings/phy/phy-stih407-usb.txt b/doc/device-tree-bindings/phy/phy-stih407-usb.txt new file mode 100644 index 0000000000..371a7fec0a --- /dev/null +++ b/doc/device-tree-bindings/phy/phy-stih407-usb.txt @@ -0,0 +1,24 @@ +ST STiH407 USB PHY controller + +This file documents the dt bindings for the usb picoPHY driver which is the PHY for both USB2 and USB3 +host controllers (when controlling usb2/1.1 devices) available on STiH407 SoC family from STMicroelectronics. + +Required properties: +- compatible : should be "st,stih407-usb2-phy" +- st,syscfg : phandle of sysconfig bank plus integer array containing phyparam and phyctrl register offsets +- resets : list of phandle and reset specifier pairs. There should be two entries, one + for the whole phy and one for the port +- reset-names : list of reset signal names. Should be "global" and "port" +See: Documentation/devicetree/bindings/reset/st,sti-powerdown.txt +See: Documentation/devicetree/bindings/reset/reset.txt + +Example: + +usb2_picophy0: usbpicophy { + compatible = "st,stih407-usb2-phy"; + #phy-cells = <0>; + st,syscfg = <&syscfg_core 0x100 0xf4>; + resets = <&softreset STIH407_PICOPHY_SOFTRESET>, + <&picophyreset STIH407_PICOPHY0_RESET>; + reset-names = "global", "port"; +}; diff --git a/doc/device-tree-bindings/reset/st,stm32-rcc.txt b/doc/device-tree-bindings/reset/st,stm32-rcc.txt new file mode 100644 index 0000000000..01db343751 --- /dev/null +++ b/doc/device-tree-bindings/reset/st,stm32-rcc.txt @@ -0,0 +1,6 @@ +STMicroelectronics STM32 Peripheral Reset Controller +==================================================== + +The RCC IP is both a reset and a clock controller. + +Please see Documentation/devicetree/bindings/clock/st,stm32-rcc.txt diff --git a/doc/device-tree-bindings/usb/dwc3-st.txt b/doc/device-tree-bindings/usb/dwc3-st.txt new file mode 100644 index 0000000000..a26a1397ed --- /dev/null +++ b/doc/device-tree-bindings/usb/dwc3-st.txt @@ -0,0 +1,60 @@ +ST DWC3 glue logic + +This file documents the parameters for the dwc3-st driver. +This driver controls the glue logic used to configure the dwc3 core on +STiH407 based platforms. + +Required properties: + - compatible : must be "st,stih407-dwc3" + - reg : glue logic base address and USB syscfg ctrl register offset + - reg-names : should be "reg-glue" and "syscfg-reg" + - st,syscon : should be phandle to system configuration node which + encompasses the glue registers + - resets : list of phandle and reset specifier pairs. There should be two entries, one + for the powerdown and softreset lines of the usb3 IP + - reset-names : list of reset signal names. Names should be "powerdown" and "softreset" + + - #address-cells, #size-cells : should be '1' if the device has sub-nodes + with 'reg' property + + - pinctl-names : A pinctrl state named "default" must be defined + + - pinctrl-0 : Pin control group + + - ranges : allows valid 1:1 translation between child's address space and + parent's address space + +Sub-nodes: +The dwc3 core should be added as subnode to ST DWC3 glue as shown in the +example below. + +NB: The dr_mode property is NOT optional for this driver, as the default value +is "otg", which isn't supported by this SoC. Valid dr_mode values for dwc3-st are +either "host" or "device". + +Example: + +st_dwc3: dwc3@8f94000 { + status = "disabled"; + compatible = "st,stih407-dwc3"; + reg = <0x08f94000 0x1000>, <0x110 0x4>; + reg-names = "reg-glue", "syscfg-reg"; + st,syscfg = <&syscfg_core>; + resets = <&powerdown STIH407_USB3_POWERDOWN>, + <&softreset STIH407_MIPHY2_SOFTRESET>; + reset-names = "powerdown", "softreset"; + #address-cells = <1>; + #size-cells = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usb3>; + ranges; + + dwc3: dwc3@9900000 { + compatible = "snps,dwc3"; + reg = <0x09900000 0x100000>; + interrupts = <GIC_SPI 155 IRQ_TYPE_NONE>; + dr_mode = "host"; + phy-names = "usb2-phy", "usb3-phy"; + phys = <&usb2_picophy2>, <&phy_port2 PHY_TYPE_USB3>; + }; +}; diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index b7735933be..83fe88ce9f 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -22,3 +22,4 @@ obj-$(CONFIG_CLK_BCM6345) += clk_bcm6345.o obj-$(CONFIG_CLK_BOSTON) += clk_boston.o obj-$(CONFIG_ARCH_ASPEED) += aspeed/ obj-$(CONFIG_STM32F7) += clk_stm32f7.o +obj-$(CONFIG_STM32H7) += clk_stm32h7.o diff --git a/drivers/clk/clk_stm32f7.c b/drivers/clk/clk_stm32f7.c index 255a583c95..68d6ba0461 100644 --- a/drivers/clk/clk_stm32f7.c +++ b/drivers/clk/clk_stm32f7.c @@ -310,10 +310,11 @@ static const struct udevice_id stm32_clk_ids[] = { }; U_BOOT_DRIVER(stm32f7_clk) = { - .name = "stm32f7_clk", - .id = UCLASS_CLK, - .of_match = stm32_clk_ids, - .ops = &stm32_clk_ops, - .probe = stm32_clk_probe, - .flags = DM_FLAG_PRE_RELOC, + .name = "stm32f7_clk", + .id = UCLASS_CLK, + .of_match = stm32_clk_ids, + .ops = &stm32_clk_ops, + .probe = stm32_clk_probe, + .priv_auto_alloc_size = sizeof(struct stm32_clk), + .flags = DM_FLAG_PRE_RELOC, }; diff --git a/drivers/clk/clk_stm32h7.c b/drivers/clk/clk_stm32h7.c new file mode 100644 index 0000000000..fd0e3ab100 --- /dev/null +++ b/drivers/clk/clk_stm32h7.c @@ -0,0 +1,802 @@ +/* + * Copyright (C) STMicroelectronics SA 2017 + * Author(s): Patrice CHOTARD, <patrice.chotard@st.com> for STMicroelectronics. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <clk-uclass.h> +#include <dm.h> +#include <regmap.h> +#include <syscon.h> +#include <asm/io.h> +#include <dm/root.h> + +#include <dt-bindings/clock/stm32h7-clks.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* RCC CR specific definitions */ +#define RCC_CR_HSION BIT(0) +#define RCC_CR_HSIRDY BIT(2) + +#define RCC_CR_HSEON BIT(16) +#define RCC_CR_HSERDY BIT(17) +#define RCC_CR_HSEBYP BIT(18) +#define RCC_CR_PLL1ON BIT(24) +#define RCC_CR_PLL1RDY BIT(25) + +#define RCC_CR_HSIDIV_MASK GENMASK(4, 3) +#define RCC_CR_HSIDIV_SHIFT 3 + +#define RCC_CFGR_SW_MASK GENMASK(2, 0) +#define RCC_CFGR_SW_HSI 0 +#define RCC_CFGR_SW_CSI 1 +#define RCC_CFGR_SW_HSE 2 +#define RCC_CFGR_SW_PLL1 3 + +#define RCC_PLLCKSELR_PLLSRC_HSI 0 +#define RCC_PLLCKSELR_PLLSRC_CSI 1 +#define RCC_PLLCKSELR_PLLSRC_HSE 2 +#define RCC_PLLCKSELR_PLLSRC_NO_CLK 3 + +#define RCC_PLLCKSELR_PLLSRC_MASK GENMASK(1, 0) + +#define RCC_PLLCKSELR_DIVM1_SHIFT 4 +#define RCC_PLLCKSELR_DIVM1_MASK GENMASK(9, 4) + +#define RCC_PLL1DIVR_DIVN1_MASK GENMASK(8, 0) + +#define RCC_PLL1DIVR_DIVP1_SHIFT 9 +#define RCC_PLL1DIVR_DIVP1_MASK GENMASK(15, 9) + +#define RCC_PLL1DIVR_DIVQ1_SHIFT 16 +#define RCC_PLL1DIVR_DIVQ1_MASK GENMASK(22, 16) + +#define RCC_PLL1DIVR_DIVR1_SHIFT 24 +#define RCC_PLL1DIVR_DIVR1_MASK GENMASK(30, 24) + +#define RCC_PLL1FRACR_FRACN1_SHIFT 3 +#define RCC_PLL1FRACR_FRACN1_MASK GENMASK(15, 3) + +#define RCC_PLLCFGR_PLL1RGE_SHIFT 2 +#define PLL1RGE_1_2_MHZ 0 +#define PLL1RGE_2_4_MHZ 1 +#define PLL1RGE_4_8_MHZ 2 +#define PLL1RGE_8_16_MHZ 3 +#define RCC_PLLCFGR_DIVP1EN BIT(16) +#define RCC_PLLCFGR_DIVQ1EN BIT(17) +#define RCC_PLLCFGR_DIVR1EN BIT(18) + +#define RCC_D1CFGR_HPRE_MASK GENMASK(3, 0) +#define RCC_D1CFGR_HPRE_DIVIDED BIT(3) +#define RCC_D1CFGR_HPRE_DIVIDER GENMASK(2, 0) + +#define RCC_D1CFGR_HPRE_DIV2 8 + +#define RCC_D1CFGR_D1PPRE_SHIFT 4 +#define RCC_D1CFGR_D1PPRE_DIVIDED BIT(6) +#define RCC_D1CFGR_D1PPRE_DIVIDER GENMASK(5, 4) + +#define RCC_D1CFGR_D1CPRE_SHIFT 8 +#define RCC_D1CFGR_D1CPRE_DIVIDER GENMASK(10, 8) +#define RCC_D1CFGR_D1CPRE_DIVIDED BIT(11) + +#define RCC_D2CFGR_D2PPRE1_SHIFT 4 +#define RCC_D2CFGR_D2PPRE1_DIVIDED BIT(6) +#define RCC_D2CFGR_D2PPRE1_DIVIDER GENMASK(5, 4) + +#define RCC_D2CFGR_D2PPRE2_SHIFT 8 +#define RCC_D2CFGR_D2PPRE2_DIVIDED BIT(10) +#define RCC_D2CFGR_D2PPRE2_DIVIDER GENMASK(9, 8) + +#define RCC_D3CFGR_D3PPRE_SHIFT 4 +#define RCC_D3CFGR_D3PPRE_DIVIDED BIT(6) +#define RCC_D3CFGR_D3PPRE_DIVIDER GENMASK(5, 4) + +#define RCC_D1CCIPR_FMCSRC_MASK GENMASK(1, 0) +#define FMCSRC_HCLKD1 0 +#define FMCSRC_PLL1_Q_CK 1 +#define FMCSRC_PLL2_R_CK 2 +#define FMCSRC_PER_CK 3 + +#define RCC_D1CCIPR_QSPISRC_MASK GENMASK(5, 4) +#define RCC_D1CCIPR_QSPISRC_SHIFT 4 +#define QSPISRC_HCLKD1 0 +#define QSPISRC_PLL1_Q_CK 1 +#define QSPISRC_PLL2_R_CK 2 +#define QSPISRC_PER_CK 3 + +#define PWR_CR3 0x0c +#define PWR_CR3_SDEN BIT(2) +#define PWR_D3CR 0x18 +#define PWR_D3CR_VOS_MASK GENMASK(15, 14) +#define PWR_D3CR_VOS_SHIFT 14 +#define VOS_SCALE_3 1 +#define VOS_SCALE_2 2 +#define VOS_SCALE_1 3 +#define PWR_D3CR_VOSREADY BIT(13) + +struct stm32_rcc_regs { + u32 cr; /* 0x00 Source Control Register */ + u32 icscr; /* 0x04 Internal Clock Source Calibration Register */ + u32 crrcr; /* 0x08 Clock Recovery RC Register */ + u32 reserved1; /* 0x0c reserved */ + u32 cfgr; /* 0x10 Clock Configuration Register */ + u32 reserved2; /* 0x14 reserved */ + u32 d1cfgr; /* 0x18 Domain 1 Clock Configuration Register */ + u32 d2cfgr; /* 0x1c Domain 2 Clock Configuration Register */ + u32 d3cfgr; /* 0x20 Domain 3 Clock Configuration Register */ + u32 reserved3; /* 0x24 reserved */ + u32 pllckselr; /* 0x28 PLLs Clock Source Selection Register */ + u32 pllcfgr; /* 0x2c PLLs Configuration Register */ + u32 pll1divr; /* 0x30 PLL1 Dividers Configuration Register */ + u32 pll1fracr; /* 0x34 PLL1 Fractional Divider Register */ + u32 pll2divr; /* 0x38 PLL2 Dividers Configuration Register */ + u32 pll2fracr; /* 0x3c PLL2 Fractional Divider Register */ + u32 pll3divr; /* 0x40 PLL3 Dividers Configuration Register */ + u32 pll3fracr; /* 0x44 PLL3 Fractional Divider Register */ + u32 reserved4; /* 0x48 reserved */ + u32 d1ccipr; /* 0x4c Domain 1 Kernel Clock Configuration Register */ + u32 d2ccip1r; /* 0x50 Domain 2 Kernel Clock Configuration Register */ + u32 d2ccip2r; /* 0x54 Domain 2 Kernel Clock Configuration Register */ + u32 d3ccipr; /* 0x58 Domain 3 Kernel Clock Configuration Register */ + u32 reserved5; /* 0x5c reserved */ + u32 cier; /* 0x60 Clock Source Interrupt Enable Register */ + u32 cifr; /* 0x64 Clock Source Interrupt Flag Register */ + u32 cicr; /* 0x68 Clock Source Interrupt Clear Register */ + u32 reserved6; /* 0x6c reserved */ + u32 bdcr; /* 0x70 Backup Domain Control Register */ + u32 csr; /* 0x74 Clock Control and Status Register */ + u32 reserved7; /* 0x78 reserved */ + + u32 ahb3rstr; /* 0x7c AHB3 Peripheral Reset Register */ + u32 ahb1rstr; /* 0x80 AHB1 Peripheral Reset Register */ + u32 ahb2rstr; /* 0x84 AHB2 Peripheral Reset Register */ + u32 ahb4rstr; /* 0x88 AHB4 Peripheral Reset Register */ + + u32 apb3rstr; /* 0x8c APB3 Peripheral Reset Register */ + u32 apb1lrstr; /* 0x90 APB1 low Peripheral Reset Register */ + u32 apb1hrstr; /* 0x94 APB1 high Peripheral Reset Register */ + u32 apb2rstr; /* 0x98 APB2 Clock Register */ + u32 apb4rstr; /* 0x9c APB4 Clock Register */ + + u32 gcr; /* 0xa0 Global Control Register */ + u32 reserved8; /* 0xa4 reserved */ + u32 d3amr; /* 0xa8 D3 Autonomous mode Register */ + u32 reserved9[9];/* 0xac to 0xcc reserved */ + u32 rsr; /* 0xd0 Reset Status Register */ + u32 ahb3enr; /* 0xd4 AHB3 Clock Register */ + u32 ahb1enr; /* 0xd8 AHB1 Clock Register */ + u32 ahb2enr; /* 0xdc AHB2 Clock Register */ + u32 ahb4enr; /* 0xe0 AHB4 Clock Register */ + + u32 apb3enr; /* 0xe4 APB3 Clock Register */ + u32 apb1lenr; /* 0xe8 APB1 low Clock Register */ + u32 apb1henr; /* 0xec APB1 high Clock Register */ + u32 apb2enr; /* 0xf0 APB2 Clock Register */ + u32 apb4enr; /* 0xf4 APB4 Clock Register */ +}; + +#define RCC_AHB3ENR offsetof(struct stm32_rcc_regs, ahb3enr) +#define RCC_AHB1ENR offsetof(struct stm32_rcc_regs, ahb1enr) +#define RCC_AHB2ENR offsetof(struct stm32_rcc_regs, ahb2enr) +#define RCC_AHB4ENR offsetof(struct stm32_rcc_regs, ahb4enr) +#define RCC_APB3ENR offsetof(struct stm32_rcc_regs, apb3enr) +#define RCC_APB1LENR offsetof(struct stm32_rcc_regs, apb1lenr) +#define RCC_APB1HENR offsetof(struct stm32_rcc_regs, apb1henr) +#define RCC_APB2ENR offsetof(struct stm32_rcc_regs, apb2enr) +#define RCC_APB4ENR offsetof(struct stm32_rcc_regs, apb4enr) + +struct clk_cfg { + u32 gate_offset; + u8 gate_bit_idx; + const char *name; +}; + +#define CLK(_gate_offset, _bit_idx, _name) \ +{ \ + .gate_offset = _gate_offset,\ + .gate_bit_idx = _bit_idx,\ + .name = _name,\ +} + +/* + * the way all these entries are sorted in this array could seem + * unlogical, but we are dependant of kernel DT_bindings, + * where clocks are separate in 2 banks, peripheral clocks and + * kernel clocks. + */ + +static const struct clk_cfg clk_map[] = { + CLK(RCC_AHB3ENR, 31, "d1sram1"), /* peripheral clocks */ + CLK(RCC_AHB3ENR, 30, "itcm"), + CLK(RCC_AHB3ENR, 29, "dtcm2"), + CLK(RCC_AHB3ENR, 28, "dtcm1"), + CLK(RCC_AHB3ENR, 8, "flitf"), + CLK(RCC_AHB3ENR, 5, "jpgdec"), + CLK(RCC_AHB3ENR, 4, "dma2d"), + CLK(RCC_AHB3ENR, 0, "mdma"), + CLK(RCC_AHB1ENR, 28, "usb2ulpi"), + CLK(RCC_AHB1ENR, 17, "eth1rx"), + CLK(RCC_AHB1ENR, 16, "eth1tx"), + CLK(RCC_AHB1ENR, 15, "eth1mac"), + CLK(RCC_AHB1ENR, 14, "art"), + CLK(RCC_AHB1ENR, 26, "usb1ulpi"), + CLK(RCC_AHB1ENR, 1, "dma2"), + CLK(RCC_AHB1ENR, 0, "dma1"), + CLK(RCC_AHB2ENR, 31, "d2sram3"), + CLK(RCC_AHB2ENR, 30, "d2sram2"), + CLK(RCC_AHB2ENR, 29, "d2sram1"), + CLK(RCC_AHB2ENR, 5, "hash"), + CLK(RCC_AHB2ENR, 4, "crypt"), + CLK(RCC_AHB2ENR, 0, "camitf"), + CLK(RCC_AHB4ENR, 28, "bkpram"), + CLK(RCC_AHB4ENR, 25, "hsem"), + CLK(RCC_AHB4ENR, 21, "bdma"), + CLK(RCC_AHB4ENR, 19, "crc"), + CLK(RCC_AHB4ENR, 10, "gpiok"), + CLK(RCC_AHB4ENR, 9, "gpioj"), + CLK(RCC_AHB4ENR, 8, "gpioi"), + CLK(RCC_AHB4ENR, 7, "gpioh"), + CLK(RCC_AHB4ENR, 6, "gpiog"), + CLK(RCC_AHB4ENR, 5, "gpiof"), + CLK(RCC_AHB4ENR, 4, "gpioe"), + CLK(RCC_AHB4ENR, 3, "gpiod"), + CLK(RCC_AHB4ENR, 2, "gpioc"), + CLK(RCC_AHB4ENR, 1, "gpiob"), + CLK(RCC_AHB4ENR, 0, "gpioa"), + CLK(RCC_APB3ENR, 6, "wwdg1"), + CLK(RCC_APB1LENR, 29, "dac12"), + CLK(RCC_APB1LENR, 11, "wwdg2"), + CLK(RCC_APB1LENR, 8, "tim14"), + CLK(RCC_APB1LENR, 7, "tim13"), + CLK(RCC_APB1LENR, 6, "tim12"), + CLK(RCC_APB1LENR, 5, "tim7"), + CLK(RCC_APB1LENR, 4, "tim6"), + CLK(RCC_APB1LENR, 3, "tim5"), + CLK(RCC_APB1LENR, 2, "tim4"), + CLK(RCC_APB1LENR, 1, "tim3"), + CLK(RCC_APB1LENR, 0, "tim2"), + CLK(RCC_APB1HENR, 5, "mdios"), + CLK(RCC_APB1HENR, 4, "opamp"), + CLK(RCC_APB1HENR, 1, "crs"), + CLK(RCC_APB2ENR, 18, "tim17"), + CLK(RCC_APB2ENR, 17, "tim16"), + CLK(RCC_APB2ENR, 16, "tim15"), + CLK(RCC_APB2ENR, 1, "tim8"), + CLK(RCC_APB2ENR, 0, "tim1"), + CLK(RCC_APB4ENR, 26, "tmpsens"), + CLK(RCC_APB4ENR, 16, "rtcapb"), + CLK(RCC_APB4ENR, 15, "vref"), + CLK(RCC_APB4ENR, 14, "comp12"), + CLK(RCC_APB4ENR, 1, "syscfg"), + CLK(RCC_AHB3ENR, 16, "sdmmc1"), /* kernel clocks */ + CLK(RCC_AHB3ENR, 14, "quadspi"), + CLK(RCC_AHB3ENR, 12, "fmc"), + CLK(RCC_AHB1ENR, 27, "usb2otg"), + CLK(RCC_AHB1ENR, 25, "usb1otg"), + CLK(RCC_AHB1ENR, 5, "adc12"), + CLK(RCC_AHB2ENR, 9, "sdmmc2"), + CLK(RCC_AHB2ENR, 6, "rng"), + CLK(RCC_AHB4ENR, 24, "adc3"), + CLK(RCC_APB3ENR, 4, "dsi"), + CLK(RCC_APB3ENR, 3, "ltdc"), + CLK(RCC_APB1LENR, 31, "usart8"), + CLK(RCC_APB1LENR, 30, "usart7"), + CLK(RCC_APB1LENR, 27, "hdmicec"), + CLK(RCC_APB1LENR, 23, "i2c3"), + CLK(RCC_APB1LENR, 22, "i2c2"), + CLK(RCC_APB1LENR, 21, "i2c1"), + CLK(RCC_APB1LENR, 20, "uart5"), + CLK(RCC_APB1LENR, 19, "uart4"), + CLK(RCC_APB1LENR, 18, "usart3"), + CLK(RCC_APB1LENR, 17, "usart2"), + CLK(RCC_APB1LENR, 16, "spdifrx"), + CLK(RCC_APB1LENR, 15, "spi3"), + CLK(RCC_APB1LENR, 14, "spi2"), + CLK(RCC_APB1LENR, 9, "lptim1"), + CLK(RCC_APB1HENR, 8, "fdcan"), + CLK(RCC_APB1HENR, 2, "swp"), + CLK(RCC_APB2ENR, 29, "hrtim"), + CLK(RCC_APB2ENR, 28, "dfsdm1"), + CLK(RCC_APB2ENR, 24, "sai3"), + CLK(RCC_APB2ENR, 23, "sai2"), + CLK(RCC_APB2ENR, 22, "sai1"), + CLK(RCC_APB2ENR, 20, "spi5"), + CLK(RCC_APB2ENR, 13, "spi4"), + CLK(RCC_APB2ENR, 12, "spi1"), + CLK(RCC_APB2ENR, 5, "usart6"), + CLK(RCC_APB2ENR, 4, "usart1"), + CLK(RCC_APB4ENR, 21, "sai4a"), + CLK(RCC_APB4ENR, 21, "sai4b"), + CLK(RCC_APB4ENR, 12, "lptim5"), + CLK(RCC_APB4ENR, 11, "lptim4"), + CLK(RCC_APB4ENR, 10, "lptim3"), + CLK(RCC_APB4ENR, 9, "lptim2"), + CLK(RCC_APB4ENR, 7, "i2c4"), + CLK(RCC_APB4ENR, 5, "spi6"), + CLK(RCC_APB4ENR, 3, "lpuart1"), +}; + +struct stm32_clk { + struct stm32_rcc_regs *rcc_base; + struct regmap *pwr_regmap; +}; + +struct pll_psc { + u8 divm; + u16 divn; + u8 divp; + u8 divq; + u8 divr; +}; + +/* + * OSC_HSE = 25 MHz + * VCO = 500MHz + * pll1_p = 250MHz / pll1_q = 250MHz pll1_r = 250Mhz + */ +struct pll_psc sys_pll_psc = { + .divm = 4, + .divn = 80, + .divp = 2, + .divq = 2, + .divr = 2, +}; + +int configure_clocks(struct udevice *dev) +{ + struct stm32_clk *priv = dev_get_priv(dev); + struct stm32_rcc_regs *regs = priv->rcc_base; + uint8_t *pwr_base = (uint8_t *)regmap_get_range(priv->pwr_regmap, 0); + uint32_t pllckselr = 0; + uint32_t pll1divr = 0; + uint32_t pllcfgr = 0; + + /* Switch on HSI */ + setbits_le32(®s->cr, RCC_CR_HSION); + while (!(readl(®s->cr) & RCC_CR_HSIRDY)) + ; + + /* Reset CFGR, now HSI is the default system clock */ + writel(0, ®s->cfgr); + + /* Set all kernel domain clock registers to reset value*/ + writel(0x0, ®s->d1ccipr); + writel(0x0, ®s->d2ccip1r); + writel(0x0, ®s->d2ccip2r); + + /* Set voltage scaling at scale 1 */ + clrsetbits_le32(pwr_base + PWR_D3CR, PWR_D3CR_VOS_MASK, + VOS_SCALE_1 << PWR_D3CR_VOS_SHIFT); + /* disable step down converter */ + clrbits_le32(pwr_base + PWR_CR3, PWR_CR3_SDEN); + while (!(readl(pwr_base + PWR_D3CR) & PWR_D3CR_VOSREADY)) + ; + + /* disable HSE to configure it */ + clrbits_le32(®s->cr, RCC_CR_HSEON); + while ((readl(®s->cr) & RCC_CR_HSERDY)) + ; + + /* clear HSE bypass and set it ON */ + clrbits_le32(®s->cr, RCC_CR_HSEBYP); + /* Switch on HSE */ + setbits_le32(®s->cr, RCC_CR_HSEON); + while (!(readl(®s->cr) & RCC_CR_HSERDY)) + ; + + /* pll setup, disable it */ + clrbits_le32(®s->cr, RCC_CR_PLL1ON); + while ((readl(®s->cr) & RCC_CR_PLL1RDY)) + ; + + /* Select HSE as PLL clock source */ + pllckselr |= RCC_PLLCKSELR_PLLSRC_HSE; + pllckselr |= sys_pll_psc.divm << RCC_PLLCKSELR_DIVM1_SHIFT; + writel(pllckselr, ®s->pllckselr); + + pll1divr |= (sys_pll_psc.divr - 1) << RCC_PLL1DIVR_DIVR1_SHIFT; + pll1divr |= (sys_pll_psc.divq - 1) << RCC_PLL1DIVR_DIVQ1_SHIFT; + pll1divr |= (sys_pll_psc.divp - 1) << RCC_PLL1DIVR_DIVP1_SHIFT; + pll1divr |= (sys_pll_psc.divn - 1); + writel(pll1divr, ®s->pll1divr); + + pllcfgr |= PLL1RGE_4_8_MHZ << RCC_PLLCFGR_PLL1RGE_SHIFT; + pllcfgr |= RCC_PLLCFGR_DIVP1EN; + pllcfgr |= RCC_PLLCFGR_DIVQ1EN; + pllcfgr |= RCC_PLLCFGR_DIVR1EN; + writel(pllcfgr, ®s->pllcfgr); + + /* pll setup, enable it */ + setbits_le32(®s->cr, RCC_CR_PLL1ON); + + /* set HPRE (/2) DI clk --> 125MHz */ + clrsetbits_le32(®s->d1cfgr, RCC_D1CFGR_HPRE_MASK, + RCC_D1CFGR_HPRE_DIV2); + + /* select PLL1 as system clock source (sys_ck)*/ + clrsetbits_le32(®s->cfgr, RCC_CFGR_SW_MASK, RCC_CFGR_SW_PLL1); + while ((readl(®s->cfgr) & RCC_CFGR_SW_MASK) != RCC_CFGR_SW_PLL1) + ; + + /* sdram: use pll1_q as fmc_k clk */ + clrsetbits_le32(®s->d1ccipr, RCC_D1CCIPR_FMCSRC_MASK, + FMCSRC_PLL1_Q_CK); + + return 0; +} + +static u32 stm32_get_HSI_divider(struct stm32_rcc_regs *regs) +{ + u32 divider; + + /* get HSI divider value */ + divider = readl(®s->cr) & RCC_CR_HSIDIV_MASK; + divider = divider >> RCC_CR_HSIDIV_SHIFT; + + return divider; +}; + +enum pllsrc { + HSE, + LSE, + HSI, + CSI, + I2S, + TIMER, + PLLSRC_NB, +}; + +static const char * const pllsrc_name[PLLSRC_NB] = { + [HSE] = "clk-hse", + [LSE] = "clk-lse", + [HSI] = "clk-hsi", + [CSI] = "clk-csi", + [I2S] = "clk-i2s", + [TIMER] = "timer-clk" +}; + +static ulong stm32_get_rate(struct stm32_rcc_regs *regs, enum pllsrc pllsrc) +{ + struct clk clk; + struct udevice *fixed_clock_dev = NULL; + u32 divider; + int ret; + const char *name = pllsrc_name[pllsrc]; + + debug("%s name %s\n", __func__, name); + + clk.id = 0; + ret = uclass_get_device_by_name(UCLASS_CLK, name, &fixed_clock_dev); + if (ret) { + error("Can't find clk %s (%d)", name, ret); + return 0; + } + + ret = clk_request(fixed_clock_dev, &clk); + if (ret) { + error("Can't request %s clk (%d)", name, ret); + return 0; + } + + divider = 0; + if (pllsrc == HSI) + divider = stm32_get_HSI_divider(regs); + + debug("%s divider %d rate %ld\n", __func__, + divider, clk_get_rate(&clk)); + + return clk_get_rate(&clk) >> divider; +}; + +enum pll1_output { + PLL1_P_CK, + PLL1_Q_CK, + PLL1_R_CK, +}; + +static u32 stm32_get_PLL1_rate(struct stm32_rcc_regs *regs, + enum pll1_output output) +{ + ulong pllsrc = 0; + u32 divm1, divn1, divp1, divq1, divr1, fracn1; + ulong vco, rate; + + /* get the PLLSRC */ + switch (readl(®s->pllckselr) & RCC_PLLCKSELR_PLLSRC_MASK) { + case RCC_PLLCKSELR_PLLSRC_HSI: + pllsrc = stm32_get_rate(regs, HSI); + break; + case RCC_PLLCKSELR_PLLSRC_CSI: + pllsrc = stm32_get_rate(regs, CSI); + break; + case RCC_PLLCKSELR_PLLSRC_HSE: + pllsrc = stm32_get_rate(regs, HSE); + break; + case RCC_PLLCKSELR_PLLSRC_NO_CLK: + /* shouldn't happen */ + error("wrong value for RCC_PLLCKSELR register\n"); + pllsrc = 0; + break; + } + + /* pllsrc = 0 ? no need to go ahead */ + if (!pllsrc) + return pllsrc; + + /* get divm1, divp1, divn1 and divr1 */ + divm1 = readl(®s->pllckselr) & RCC_PLLCKSELR_DIVM1_MASK; + divm1 = divm1 >> RCC_PLLCKSELR_DIVM1_SHIFT; + + divn1 = (readl(®s->pll1divr) & RCC_PLL1DIVR_DIVN1_MASK) + 1; + + divp1 = readl(®s->pll1divr) & RCC_PLL1DIVR_DIVP1_MASK; + divp1 = (divp1 >> RCC_PLL1DIVR_DIVP1_SHIFT) + 1; + + divq1 = readl(®s->pll1divr) & RCC_PLL1DIVR_DIVQ1_MASK; + divq1 = (divq1 >> RCC_PLL1DIVR_DIVQ1_SHIFT) + 1; + + divr1 = readl(®s->pll1divr) & RCC_PLL1DIVR_DIVR1_MASK; + divr1 = (divr1 >> RCC_PLL1DIVR_DIVR1_SHIFT) + 1; + + fracn1 = readl(®s->pll1fracr) & RCC_PLL1DIVR_DIVR1_MASK; + fracn1 = fracn1 & RCC_PLL1DIVR_DIVR1_SHIFT; + + vco = (pllsrc / divm1) * divn1; + rate = (pllsrc * fracn1) / (divm1 * 8192); + + debug("%s divm1 = %d divn1 = %d divp1 = %d divq1 = %d divr1 = %d\n", + __func__, divm1, divn1, divp1, divq1, divr1); + debug("%s fracn1 = %d vco = %ld rate = %ld\n", + __func__, fracn1, vco, rate); + + switch (output) { + case PLL1_P_CK: + return (vco + rate) / divp1; + break; + case PLL1_Q_CK: + return (vco + rate) / divq1; + break; + + case PLL1_R_CK: + return (vco + rate) / divr1; + break; + } + + return -EINVAL; +} + +static ulong stm32_clk_get_rate(struct clk *clk) +{ + struct stm32_clk *priv = dev_get_priv(clk->dev); + struct stm32_rcc_regs *regs = priv->rcc_base; + ulong sysclk = 0; + u32 gate_offset; + u32 d1cfgr; + /* prescaler table lookups for clock computation */ + u16 prescaler_table[8] = {2, 4, 8, 16, 64, 128, 256, 512}; + u8 source, idx; + + /* + * get system clock (sys_ck) source + * can be HSI_CK, CSI_CK, HSE_CK or pll1_p_ck + */ + source = readl(®s->cfgr) & RCC_CFGR_SW_MASK; + switch (source) { + case RCC_CFGR_SW_PLL1: + sysclk = stm32_get_PLL1_rate(regs, PLL1_P_CK); + break; + case RCC_CFGR_SW_HSE: + sysclk = stm32_get_rate(regs, HSE); + break; + + case RCC_CFGR_SW_CSI: + sysclk = stm32_get_rate(regs, CSI); + break; + + case RCC_CFGR_SW_HSI: + sysclk = stm32_get_rate(regs, HSI); + break; + } + + /* sysclk = 0 ? no need to go ahead */ + if (!sysclk) + return sysclk; + + debug("%s system clock: source = %d freq = %ld\n", + __func__, source, sysclk); + + d1cfgr = readl(®s->d1cfgr); + + if (d1cfgr & RCC_D1CFGR_D1CPRE_DIVIDED) { + /* get D1 domain Core prescaler */ + idx = (d1cfgr & RCC_D1CFGR_D1CPRE_DIVIDER) >> + RCC_D1CFGR_D1CPRE_SHIFT; + sysclk = sysclk / prescaler_table[idx]; + } + + if (d1cfgr & RCC_D1CFGR_HPRE_DIVIDED) { + /* get D1 domain AHB prescaler */ + idx = d1cfgr & RCC_D1CFGR_HPRE_DIVIDER; + sysclk = sysclk / prescaler_table[idx]; + } + + gate_offset = clk_map[clk->id].gate_offset; + + debug("%s clk->id=%ld gate_offset=0x%x sysclk=%ld\n", + __func__, clk->id, gate_offset, sysclk); + + switch (gate_offset) { + case RCC_AHB3ENR: + case RCC_AHB1ENR: + case RCC_AHB2ENR: + case RCC_AHB4ENR: + return sysclk; + break; + + case RCC_APB3ENR: + if (d1cfgr & RCC_D1CFGR_D1PPRE_DIVIDED) { + /* get D1 domain APB3 prescaler */ + idx = (d1cfgr & RCC_D1CFGR_D1PPRE_DIVIDER) >> + RCC_D1CFGR_D1PPRE_SHIFT; + sysclk = sysclk / prescaler_table[idx]; + } + + debug("%s system clock: freq after APB3 prescaler = %ld\n", + __func__, sysclk); + + return sysclk; + break; + + case RCC_APB4ENR: + if (d1cfgr & RCC_D3CFGR_D3PPRE_DIVIDED) { + /* get D3 domain APB4 prescaler */ + idx = (d1cfgr & RCC_D3CFGR_D3PPRE_DIVIDER) >> + RCC_D3CFGR_D3PPRE_SHIFT; + sysclk = sysclk / prescaler_table[idx]; + } + + debug("%s system clock: freq after APB4 prescaler = %ld\n", + __func__, sysclk); + + return sysclk; + break; + + case RCC_APB1LENR: + case RCC_APB1HENR: + if (d1cfgr & RCC_D2CFGR_D2PPRE1_DIVIDED) { + /* get D2 domain APB1 prescaler */ + idx = (d1cfgr & RCC_D2CFGR_D2PPRE1_DIVIDER) >> + RCC_D2CFGR_D2PPRE1_SHIFT; + sysclk = sysclk / prescaler_table[idx]; + } + + debug("%s system clock: freq after APB1 prescaler = %ld\n", + __func__, sysclk); + + return sysclk; + break; + + case RCC_APB2ENR: + if (d1cfgr & RCC_D2CFGR_D2PPRE2_DIVIDED) { + /* get D2 domain APB1 prescaler */ + idx = (d1cfgr & RCC_D2CFGR_D2PPRE2_DIVIDER) >> + RCC_D2CFGR_D2PPRE2_SHIFT; + sysclk = sysclk / prescaler_table[idx]; + } + + debug("%s system clock: freq after APB2 prescaler = %ld\n", + __func__, sysclk); + + return sysclk; + break; + + default: + error("unexpected gate_offset value (0x%x)\n", gate_offset); + return -EINVAL; + break; + } +} + +static int stm32_clk_enable(struct clk *clk) +{ + struct stm32_clk *priv = dev_get_priv(clk->dev); + struct stm32_rcc_regs *regs = priv->rcc_base; + u32 gate_offset; + u32 gate_bit_index; + unsigned long clk_id = clk->id; + + gate_offset = clk_map[clk_id].gate_offset; + gate_bit_index = clk_map[clk_id].gate_bit_idx; + + debug("%s: clkid=%ld gate offset=0x%x bit_index=%d name=%s\n", + __func__, clk->id, gate_offset, gate_bit_index, + clk_map[clk_id].name); + + setbits_le32(®s->cr + (gate_offset / 4), BIT(gate_bit_index)); + + return 0; +} + +static int stm32_clk_probe(struct udevice *dev) +{ + struct stm32_clk *priv = dev_get_priv(dev); + struct udevice *syscon; + fdt_addr_t addr; + int err; + + addr = dev_read_addr(dev); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + priv->rcc_base = (struct stm32_rcc_regs *)addr; + + /* get corresponding syscon phandle */ + err = uclass_get_device_by_phandle(UCLASS_SYSCON, dev, + "st,syscfg", &syscon); + + if (err) { + error("unable to find syscon device\n"); + return err; + } + + priv->pwr_regmap = syscon_get_regmap(syscon); + if (!priv->pwr_regmap) { + error("unable to find regmap\n"); + return -ENODEV; + } + + configure_clocks(dev); + + return 0; +} + +static int stm32_clk_of_xlate(struct clk *clk, + struct ofnode_phandle_args *args) +{ + if (args->args_count != 1) { + debug("Invaild args_count: %d\n", args->args_count); + return -EINVAL; + } + + if (args->args_count) { + clk->id = args->args[0]; + /* + * this computation convert DT clock index which is used to + * point into 2 separate clock arrays (peripheral and kernel + * clocks bank) (see include/dt-bindings/clock/stm32h7-clks.h) + * into index to point into only one array where peripheral + * and kernel clocks are consecutive + */ + if (clk->id >= KERN_BANK) { + clk->id -= KERN_BANK; + clk->id += LAST_PERIF_BANK - PERIF_BANK + 1; + } else { + clk->id -= PERIF_BANK; + } + } else { + clk->id = 0; + } + + debug("%s clk->id %ld\n", __func__, clk->id); + + return 0; +} + +static struct clk_ops stm32_clk_ops = { + .of_xlate = stm32_clk_of_xlate, + .enable = stm32_clk_enable, + .get_rate = stm32_clk_get_rate, +}; + +U_BOOT_DRIVER(stm32h7_clk) = { + .name = "stm32h7_rcc_clock", + .id = UCLASS_CLK, + .ops = &stm32_clk_ops, + .probe = stm32_clk_probe, + .priv_auto_alloc_size = sizeof(struct stm32_clk), + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/drivers/clk/rockchip/clk_rk3368.c b/drivers/clk/rockchip/clk_rk3368.c index 0160d50c03..e2747816b9 100644 --- a/drivers/clk/rockchip/clk_rk3368.c +++ b/drivers/clk/rockchip/clk_rk3368.c @@ -485,7 +485,7 @@ static int rk3368_clk_ofdata_to_platdata(struct udevice *dev) #if !CONFIG_IS_ENABLED(OF_PLATDATA) struct rk3368_clk_priv *priv = dev_get_priv(dev); - priv->cru = (struct rk3368_cru *)devfdt_get_addr(dev); + priv->cru = dev_read_addr_ptr(dev); #endif return 0; diff --git a/drivers/clk/rockchip/clk_rk3399.c b/drivers/clk/rockchip/clk_rk3399.c index 7232806724..9d963be552 100644 --- a/drivers/clk/rockchip/clk_rk3399.c +++ b/drivers/clk/rockchip/clk_rk3399.c @@ -950,9 +950,24 @@ static ulong rk3399_clk_set_rate(struct clk *clk, ulong rate) return ret; } +static int rk3399_clk_enable(struct clk *clk) +{ + switch (clk->id) { + case HCLK_HOST0: + case HCLK_HOST0_ARB: + case HCLK_HOST1: + case HCLK_HOST1_ARB: + return 0; + } + + debug("%s: unsupported clk %ld\n", __func__, clk->id); + return -ENOENT; +} + static struct clk_ops rk3399_clk_ops = { .get_rate = rk3399_clk_get_rate, .set_rate = rk3399_clk_set_rate, + .enable = rk3399_clk_enable, }; static int rk3399_clk_probe(struct udevice *dev) @@ -975,7 +990,7 @@ static int rk3399_clk_ofdata_to_platdata(struct udevice *dev) #if !CONFIG_IS_ENABLED(OF_PLATDATA) struct rk3399_clk_priv *priv = dev_get_priv(dev); - priv->cru = (struct rk3399_cru *)devfdt_get_addr(dev); + priv->cru = dev_read_addr_ptr(dev); #endif return 0; } @@ -1159,7 +1174,7 @@ static int rk3399_pmuclk_ofdata_to_platdata(struct udevice *dev) #if !CONFIG_IS_ENABLED(OF_PLATDATA) struct rk3399_pmuclk_priv *priv = dev_get_priv(dev); - priv->pmucru = (struct rk3399_pmucru *)devfdt_get_addr(dev); + priv->pmucru = dev_read_addr_ptr(dev); #endif return 0; } diff --git a/drivers/core/read.c b/drivers/core/read.c index 6acb33388f..eacf1716fd 100644 --- a/drivers/core/read.c +++ b/drivers/core/read.c @@ -57,6 +57,13 @@ fdt_addr_t dev_read_addr(struct udevice *dev) return dev_read_addr_index(dev, 0); } +void *dev_read_addr_ptr(struct udevice *dev) +{ + fdt_addr_t addr = dev_read_addr(dev); + + return (addr == FDT_ADDR_T_NONE) ? NULL : (void *)addr; +} + fdt_addr_t dev_read_addr_size(struct udevice *dev, const char *property, fdt_size_t *sizep) { @@ -74,6 +81,17 @@ int dev_read_stringlist_search(struct udevice *dev, const char *property, return ofnode_stringlist_search(dev_ofnode(dev), property, string); } +int dev_read_string_index(struct udevice *dev, const char *propname, int index, + const char **outp) +{ + return ofnode_read_string_index(dev_ofnode(dev), propname, index, outp); +} + +int dev_read_string_count(struct udevice *dev, const char *propname) +{ + return ofnode_read_string_count(dev_ofnode(dev), propname); +} + int dev_read_phandle_with_args(struct udevice *dev, const char *list_name, const char *cells_name, int cell_count, int index, diff --git a/drivers/gpio/rk_gpio.c b/drivers/gpio/rk_gpio.c index 6f7366acba..11fc3e26bd 100644 --- a/drivers/gpio/rk_gpio.c +++ b/drivers/gpio/rk_gpio.c @@ -103,8 +103,7 @@ static int rockchip_gpio_probe(struct udevice *dev) char *end; int ret; - /* This only supports RK3288 at present */ - priv->regs = (struct rockchip_gpio_regs *)devfdt_get_addr(dev); + priv->regs = dev_read_addr_ptr(dev); ret = uclass_first_device_err(UCLASS_PINCTRL, &priv->pinctrl); if (ret) return ret; diff --git a/drivers/i2c/rk_i2c.c b/drivers/i2c/rk_i2c.c index 68e66536e4..840b3f6046 100644 --- a/drivers/i2c/rk_i2c.c +++ b/drivers/i2c/rk_i2c.c @@ -382,7 +382,7 @@ static int rockchip_i2c_probe(struct udevice *bus) { struct rk_i2c *priv = dev_get_priv(bus); - priv->regs = (void *)devfdt_get_addr(bus); + priv->regs = dev_read_addr_ptr(bus); return 0; } diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 4133017e32..f1c15cb9fa 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -158,6 +158,15 @@ config PCA9551_I2C_ADDR help The I2C address of the PCA9551 LED controller. +config STM32_RCC + bool "Enable RCC driver for the STM32 SoC's family" + depends on STM32 && MISC + help + Enable the STM32 RCC driver. The RCC block (Reset and Clock Control + block) is responsible of the management of the clock and reset + generation. + This driver is similar to an MFD driver in the Linux kernel. + config TEGRA_CAR bool "Enable support for the Tegra CAR driver" depends on TEGRA_NO_BPMP diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 21f7e6c6f5..ada7624417 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -52,3 +52,4 @@ obj-$(CONFIG_FSL_DEVICE_DISABLE) += fsl_devdis.o obj-$(CONFIG_WINBOND_W83627) += winbond_w83627.o obj-$(CONFIG_QFW) += qfw.o obj-$(CONFIG_ROCKCHIP_EFUSE) += rockchip-efuse.o +obj-$(CONFIG_STM32_RCC) += stm32_rcc.o diff --git a/drivers/misc/rockchip-efuse.c b/drivers/misc/rockchip-efuse.c index 2e3bc9137a..a2203bf37b 100644 --- a/drivers/misc/rockchip-efuse.c +++ b/drivers/misc/rockchip-efuse.c @@ -142,7 +142,7 @@ static int rockchip_efuse_ofdata_to_platdata(struct udevice *dev) { struct rockchip_efuse_platdata *plat = dev_get_platdata(dev); - plat->base = (void *)dev_read_addr(dev); + plat->base = dev_read_addr_ptr(dev); return 0; } diff --git a/drivers/misc/stm32_rcc.c b/drivers/misc/stm32_rcc.c new file mode 100644 index 0000000000..a6c2a757ec --- /dev/null +++ b/drivers/misc/stm32_rcc.c @@ -0,0 +1,45 @@ +/* + * Copyright (C) STMicroelectronics SA 2017 + * Author(s): Patrice CHOTARD, <patrice.chotard@st.com> for STMicroelectronics. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <misc.h> +#include <dm/lists.h> + +static int stm32_rcc_bind(struct udevice *dev) +{ + int ret; + struct udevice *child; + + debug("%s(dev=%p)\n", __func__, dev); + + ret = device_bind_driver_to_node(dev, "stm32h7_rcc_clock", + "stm32h7_rcc_clock", + dev_ofnode(dev), &child); + if (ret) + return ret; + + return device_bind_driver_to_node(dev, "stm32_rcc_reset", + "stm32_rcc_reset", + dev_ofnode(dev), &child); +} + +static const struct misc_ops stm32_rcc_ops = { +}; + +static const struct udevice_id stm32_rcc_ids[] = { + {.compatible = "st,stm32h743-rcc"}, + { } +}; + +U_BOOT_DRIVER(stm32_rcc) = { + .name = "stm32-rcc", + .id = UCLASS_MISC, + .of_match = stm32_rcc_ids, + .bind = stm32_rcc_bind, + .ops = &stm32_rcc_ops, +}; diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index 6de927b8c6..24b4eadd2a 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -136,6 +136,7 @@ config MMC_PCI config MMC_OMAP_HS bool "TI OMAP High Speed Multimedia Card Interface support" select DM_REGULATOR_PBIAS if DM_MMC && DM_REGULATOR + select DM_REGULATOR_PBIAS if DM_MMC && DM_REGULATOR help This selects the TI OMAP High Speed Multimedia card Interface. If you have an omap2plus board with a Multimedia Card slot, @@ -162,12 +163,13 @@ config SH_SDHI Support for the on-chip SDHI host controller on SuperH/Renesas ARM SoCs platform config MMC_UNIPHIER - bool "UniPhier SD/MMC Host Controller support" - depends on ARCH_UNIPHIER + bool "UniPhier/RCar SD/MMC Host Controller support" + depends on ARCH_UNIPHIER || ARCH_RMOBILE depends on BLK && DM_MMC depends on OF_CONTROL help - This selects support for the SD/MMC Host Controller on UniPhier SoCs. + This selects support for the Matsushita SD/MMC Host Controller on + SocioNext UniPhier and Renesas RCar SoCs. config MMC_SANDBOX bool "Sandbox MMC support" @@ -382,6 +384,14 @@ config GENERIC_ATMEL_MCI the SD Memory Card Specification V2.0, the SDIO V2.0 specification and CE-ATA V1.1. +config STM32_SDMMC2 + bool "STMicroelectronics STM32H7 SD/MMC Host Controller support" + depends on DM_MMC && BLK && OF_CONTROL && DM_MMC_OPS + help + This selects support for the SD/MMC controller on STM32H7 SoCs. + If you have a board based on such a SoC and with a SD/MMC slot, + say Y or M here. + endif config TEGRA124_MMC_DISABLE_EXT_LOOPBACK diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index a6becb2309..d505f37f01 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -43,6 +43,7 @@ obj-$(CONFIG_SUPPORT_EMMC_RPMB) += rpmb.o obj-$(CONFIG_MMC_SANDBOX) += sandbox_mmc.o obj-$(CONFIG_SH_MMCIF) += sh_mmcif.o obj-$(CONFIG_SH_SDHI) += sh_sdhi.o +obj-$(CONFIG_STM32_SDMMC2) += stm32_sdmmc2.o # SDHCI obj-$(CONFIG_MMC_SDHCI) += sdhci.o diff --git a/drivers/mmc/rockchip_dw_mmc.c b/drivers/mmc/rockchip_dw_mmc.c index e7fcf89f73..807dc9e72f 100644 --- a/drivers/mmc/rockchip_dw_mmc.c +++ b/drivers/mmc/rockchip_dw_mmc.c @@ -58,7 +58,7 @@ static int rockchip_dwmmc_ofdata_to_platdata(struct udevice *dev) struct dwmci_host *host = &priv->host; host->name = dev->name; - host->ioaddr = (void *)devfdt_get_addr(dev); + host->ioaddr = dev_read_addr_ptr(dev); host->buswidth = dev_read_u32_default(dev, "bus-width", 4); host->get_mmc_clk = rockchip_dwmmc_get_mmc_clk; host->priv = dev; diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c index f31d329c81..0f31dfc3fd 100644 --- a/drivers/mmc/rockchip_sdhci.c +++ b/drivers/mmc/rockchip_sdhci.c @@ -9,7 +9,6 @@ #include <common.h> #include <dm.h> #include <dt-structs.h> -#include <fdtdec.h> #include <libfdt.h> #include <malloc.h> #include <mapmem.h> @@ -46,7 +45,7 @@ static int arasan_sdhci_probe(struct udevice *dev) struct dtd_rockchip_rk3399_sdhci_5_1 *dtplat = &plat->dtplat; host->name = dev->name; - host->ioaddr = map_sysmem(dtplat->reg[1], dtplat->reg[3]); + host->ioaddr = map_sysmem(dtplat->reg[0], dtplat->reg[1]); max_frequency = dtplat->max_frequency; ret = clk_get_by_index_platdata(dev, 0, dtplat->clocks, &clk); #else @@ -82,7 +81,7 @@ static int arasan_sdhci_ofdata_to_platdata(struct udevice *dev) struct sdhci_host *host = dev_get_priv(dev); host->name = dev->name; - host->ioaddr = devfdt_get_addr_ptr(dev); + host->ioaddr = dev_read_addr_ptr(dev); #endif return 0; diff --git a/drivers/mmc/sdhci-cadence.c b/drivers/mmc/sdhci-cadence.c index f83c1d7241..72d1c646a2 100644 --- a/drivers/mmc/sdhci-cadence.c +++ b/drivers/mmc/sdhci-cadence.c @@ -23,6 +23,18 @@ #define SDHCI_CDNS_HRS04_WDATA_SHIFT 8 #define SDHCI_CDNS_HRS04_ADDR_SHIFT 0 +#define SDHCI_CDNS_HRS06 0x18 /* eMMC control */ +#define SDHCI_CDNS_HRS06_TUNE_UP BIT(15) +#define SDHCI_CDNS_HRS06_TUNE_SHIFT 8 +#define SDHCI_CDNS_HRS06_TUNE_MASK 0x3f +#define SDHCI_CDNS_HRS06_MODE_MASK 0x7 +#define SDHCI_CDNS_HRS06_MODE_SD 0x0 +#define SDHCI_CDNS_HRS06_MODE_MMC_SDR 0x2 +#define SDHCI_CDNS_HRS06_MODE_MMC_DDR 0x3 +#define SDHCI_CDNS_HRS06_MODE_MMC_HS200 0x4 +#define SDHCI_CDNS_HRS06_MODE_MMC_HS400 0x5 +#define SDHCI_CDNS_HRS06_MODE_MMC_HS400ES 0x6 + /* SRS - Slot Register Set (SDHCI-compatible) */ #define SDHCI_CDNS_SRS_BASE 0x200 @@ -111,6 +123,44 @@ static int sdhci_cdns_phy_init(struct sdhci_cdns_plat *plat, return 0; } +static void sdhci_cdns_set_control_reg(struct sdhci_host *host) +{ + struct mmc *mmc = host->mmc; + struct sdhci_cdns_plat *plat = dev_get_platdata(mmc->dev); + unsigned int clock = mmc->clock; + u32 mode, tmp; + + /* + * REVISIT: + * The mode should be decided by MMC_TIMING_* like Linux, but + * U-Boot does not support timing. Use the clock frequency instead. + */ + if (clock <= 26000000) + mode = SDHCI_CDNS_HRS06_MODE_SD; /* use this for Legacy */ + else if (clock <= 52000000) { + if (mmc->ddr_mode) + mode = SDHCI_CDNS_HRS06_MODE_MMC_DDR; + else + mode = SDHCI_CDNS_HRS06_MODE_MMC_SDR; + } else { + /* + * REVISIT: + * The IP supports HS200/HS400, revisit once U-Boot support it + */ + printf("unsupported frequency %d\n", clock); + return; + } + + tmp = readl(plat->hrs_addr + SDHCI_CDNS_HRS06); + tmp &= ~SDHCI_CDNS_HRS06_MODE_MASK; + tmp |= mode; + writel(tmp, plat->hrs_addr + SDHCI_CDNS_HRS06); +} + +static const struct sdhci_ops sdhci_cdns_ops = { + .set_control_reg = sdhci_cdns_set_control_reg, +}; + static int sdhci_cdns_bind(struct udevice *dev) { struct sdhci_cdns_plat *plat = dev_get_platdata(dev); @@ -137,6 +187,7 @@ static int sdhci_cdns_probe(struct udevice *dev) host->name = dev->name; host->ioaddr = plat->hrs_addr + SDHCI_CDNS_SRS_BASE; + host->ops = &sdhci_cdns_ops; host->quirks |= SDHCI_QUIRK_WAIT_SEND_CMD; ret = sdhci_cdns_phy_init(plat, gd->fdt_blob, dev_of_offset(dev)); diff --git a/drivers/mmc/sti_sdhci.c b/drivers/mmc/sti_sdhci.c index f85f6b4db6..d8b5888b7c 100644 --- a/drivers/mmc/sti_sdhci.c +++ b/drivers/mmc/sti_sdhci.c @@ -8,6 +8,7 @@ #include <common.h> #include <dm.h> #include <mmc.h> +#include <reset-uclass.h> #include <sdhci.h> #include <asm/arch/sdhci.h> @@ -16,18 +17,14 @@ DECLARE_GLOBAL_DATA_PTR; struct sti_sdhci_plat { struct mmc_config cfg; struct mmc mmc; + struct reset_ctl reset; + int instance; }; -/* - * used to get access to MMC1 reset, - * will be removed when STi reset driver will be available - */ -#define STIH410_SYSCONF5_BASE 0x092b0000 - /** * sti_mmc_core_config: configure the Arasan HC - * @regbase: base address - * @mmc_instance: mmc instance id + * @dev : udevice + * * Description: this function is to configure the Arasan MMC HC. * This should be called when the system starts in case of, on the SoC, * it is needed to configure the host controller. @@ -36,33 +33,39 @@ struct sti_sdhci_plat { * W/o these settings the SDHCI could configure and use the embedded controller * with limited features. */ -static void sti_mmc_core_config(const u32 regbase, int mmc_instance) +static int sti_mmc_core_config(struct udevice *dev) { - unsigned long *sysconf; + struct sti_sdhci_plat *plat = dev_get_platdata(dev); + struct sdhci_host *host = dev_get_priv(dev); + int ret; /* only MMC1 has a reset line */ - if (mmc_instance) { - sysconf = (unsigned long *)(STIH410_SYSCONF5_BASE + - ST_MMC_CCONFIG_REG_5); - generic_set_bit(SYSCONF_MMC1_ENABLE_BIT, sysconf); + if (plat->instance) { + ret = reset_deassert(&plat->reset); + if (ret < 0) { + error("MMC1 deassert failed: %d", ret); + return ret; + } } writel(STI_FLASHSS_MMC_CORE_CONFIG_1, - regbase + FLASHSS_MMC_CORE_CONFIG_1); + host->ioaddr + FLASHSS_MMC_CORE_CONFIG_1); - if (mmc_instance) { + if (plat->instance) { writel(STI_FLASHSS_MMC_CORE_CONFIG2, - regbase + FLASHSS_MMC_CORE_CONFIG_2); + host->ioaddr + FLASHSS_MMC_CORE_CONFIG_2); writel(STI_FLASHSS_MMC_CORE_CONFIG3, - regbase + FLASHSS_MMC_CORE_CONFIG_3); + host->ioaddr + FLASHSS_MMC_CORE_CONFIG_3); } else { writel(STI_FLASHSS_SDCARD_CORE_CONFIG2, - regbase + FLASHSS_MMC_CORE_CONFIG_2); + host->ioaddr + FLASHSS_MMC_CORE_CONFIG_2); writel(STI_FLASHSS_SDCARD_CORE_CONFIG3, - regbase + FLASHSS_MMC_CORE_CONFIG_3); + host->ioaddr + FLASHSS_MMC_CORE_CONFIG_3); } writel(STI_FLASHSS_MMC_CORE_CONFIG4, - regbase + FLASHSS_MMC_CORE_CONFIG_4); + host->ioaddr + FLASHSS_MMC_CORE_CONFIG_4); + + return 0; } static int sti_sdhci_probe(struct udevice *dev) @@ -70,20 +73,25 @@ static int sti_sdhci_probe(struct udevice *dev) struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); struct sti_sdhci_plat *plat = dev_get_platdata(dev); struct sdhci_host *host = dev_get_priv(dev); - int ret, mmc_instance; + int ret; /* * identify current mmc instance, mmc1 has a reset, not mmc0 * MMC0 is wired to the SD slot, * MMC1 is wired on the high speed connector */ - - if (fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "resets", NULL)) - mmc_instance = 1; + ret = reset_get_by_index(dev, 0, &plat->reset); + if (!ret) + plat->instance = 1; else - mmc_instance = 0; + if (ret == -ENOENT) + plat->instance = 0; + else + return ret; - sti_mmc_core_config((const u32) host->ioaddr, mmc_instance); + ret = sti_mmc_core_config(dev); + if (ret) + return ret; host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_32BIT_DMA_ADDR | diff --git a/drivers/mmc/stm32_sdmmc2.c b/drivers/mmc/stm32_sdmmc2.c new file mode 100644 index 0000000000..0e1f40b569 --- /dev/null +++ b/drivers/mmc/stm32_sdmmc2.c @@ -0,0 +1,608 @@ +/* + * Copyright (C) STMicroelectronics SA 2017 + * Author(s): Patrice CHOTARD, <patrice.chotard@st.com> for STMicroelectronics. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <clk.h> +#include <dm.h> +#include <fdtdec.h> +#include <libfdt.h> +#include <mmc.h> +#include <reset.h> +#include <asm/io.h> +#include <asm/gpio.h> +#include <linux/iopoll.h> + +struct stm32_sdmmc2_plat { + struct mmc_config cfg; + struct mmc mmc; +}; + +struct stm32_sdmmc2_priv { + fdt_addr_t base; + struct clk clk; + struct reset_ctl reset_ctl; + struct gpio_desc cd_gpio; + u32 clk_reg_msk; + u32 pwr_reg_msk; +}; + +struct stm32_sdmmc2_ctx { + u32 cache_start; + u32 cache_end; + u32 data_length; + bool dpsm_abort; +}; + +/* SDMMC REGISTERS OFFSET */ +#define SDMMC_POWER 0x00 /* SDMMC power control */ +#define SDMMC_CLKCR 0x04 /* SDMMC clock control */ +#define SDMMC_ARG 0x08 /* SDMMC argument */ +#define SDMMC_CMD 0x0C /* SDMMC command */ +#define SDMMC_RESP1 0x14 /* SDMMC response 1 */ +#define SDMMC_RESP2 0x18 /* SDMMC response 2 */ +#define SDMMC_RESP3 0x1C /* SDMMC response 3 */ +#define SDMMC_RESP4 0x20 /* SDMMC response 4 */ +#define SDMMC_DTIMER 0x24 /* SDMMC data timer */ +#define SDMMC_DLEN 0x28 /* SDMMC data length */ +#define SDMMC_DCTRL 0x2C /* SDMMC data control */ +#define SDMMC_DCOUNT 0x30 /* SDMMC data counter */ +#define SDMMC_STA 0x34 /* SDMMC status */ +#define SDMMC_ICR 0x38 /* SDMMC interrupt clear */ +#define SDMMC_MASK 0x3C /* SDMMC mask */ +#define SDMMC_IDMACTRL 0x50 /* SDMMC DMA control */ +#define SDMMC_IDMABASE0 0x58 /* SDMMC DMA buffer 0 base address */ + +/* SDMMC_POWER register */ +#define SDMMC_POWER_PWRCTRL GENMASK(1, 0) +#define SDMMC_POWER_VSWITCH BIT(2) +#define SDMMC_POWER_VSWITCHEN BIT(3) +#define SDMMC_POWER_DIRPOL BIT(4) + +/* SDMMC_CLKCR register */ +#define SDMMC_CLKCR_CLKDIV GENMASK(9, 0) +#define SDMMC_CLKCR_CLKDIV_MAX SDMMC_CLKCR_CLKDIV +#define SDMMC_CLKCR_PWRSAV BIT(12) +#define SDMMC_CLKCR_WIDBUS_4 BIT(14) +#define SDMMC_CLKCR_WIDBUS_8 BIT(15) +#define SDMMC_CLKCR_NEGEDGE BIT(16) +#define SDMMC_CLKCR_HWFC_EN BIT(17) +#define SDMMC_CLKCR_DDR BIT(18) +#define SDMMC_CLKCR_BUSSPEED BIT(19) +#define SDMMC_CLKCR_SELCLKRX GENMASK(21, 20) + +/* SDMMC_CMD register */ +#define SDMMC_CMD_CMDINDEX GENMASK(5, 0) +#define SDMMC_CMD_CMDTRANS BIT(6) +#define SDMMC_CMD_CMDSTOP BIT(7) +#define SDMMC_CMD_WAITRESP GENMASK(9, 8) +#define SDMMC_CMD_WAITRESP_0 BIT(8) +#define SDMMC_CMD_WAITRESP_1 BIT(9) +#define SDMMC_CMD_WAITINT BIT(10) +#define SDMMC_CMD_WAITPEND BIT(11) +#define SDMMC_CMD_CPSMEN BIT(12) +#define SDMMC_CMD_DTHOLD BIT(13) +#define SDMMC_CMD_BOOTMODE BIT(14) +#define SDMMC_CMD_BOOTEN BIT(15) +#define SDMMC_CMD_CMDSUSPEND BIT(16) + +/* SDMMC_DCTRL register */ +#define SDMMC_DCTRL_DTEN BIT(0) +#define SDMMC_DCTRL_DTDIR BIT(1) +#define SDMMC_DCTRL_DTMODE GENMASK(3, 2) +#define SDMMC_DCTRL_DBLOCKSIZE GENMASK(7, 4) +#define SDMMC_DCTRL_DBLOCKSIZE_SHIFT 4 +#define SDMMC_DCTRL_RWSTART BIT(8) +#define SDMMC_DCTRL_RWSTOP BIT(9) +#define SDMMC_DCTRL_RWMOD BIT(10) +#define SDMMC_DCTRL_SDMMCEN BIT(11) +#define SDMMC_DCTRL_BOOTACKEN BIT(12) +#define SDMMC_DCTRL_FIFORST BIT(13) + +/* SDMMC_STA register */ +#define SDMMC_STA_CCRCFAIL BIT(0) +#define SDMMC_STA_DCRCFAIL BIT(1) +#define SDMMC_STA_CTIMEOUT BIT(2) +#define SDMMC_STA_DTIMEOUT BIT(3) +#define SDMMC_STA_TXUNDERR BIT(4) +#define SDMMC_STA_RXOVERR BIT(5) +#define SDMMC_STA_CMDREND BIT(6) +#define SDMMC_STA_CMDSENT BIT(7) +#define SDMMC_STA_DATAEND BIT(8) +#define SDMMC_STA_DHOLD BIT(9) +#define SDMMC_STA_DBCKEND BIT(10) +#define SDMMC_STA_DABORT BIT(11) +#define SDMMC_STA_DPSMACT BIT(12) +#define SDMMC_STA_CPSMACT BIT(13) +#define SDMMC_STA_TXFIFOHE BIT(14) +#define SDMMC_STA_RXFIFOHF BIT(15) +#define SDMMC_STA_TXFIFOF BIT(16) +#define SDMMC_STA_RXFIFOF BIT(17) +#define SDMMC_STA_TXFIFOE BIT(18) +#define SDMMC_STA_RXFIFOE BIT(19) +#define SDMMC_STA_BUSYD0 BIT(20) +#define SDMMC_STA_BUSYD0END BIT(21) +#define SDMMC_STA_SDMMCIT BIT(22) +#define SDMMC_STA_ACKFAIL BIT(23) +#define SDMMC_STA_ACKTIMEOUT BIT(24) +#define SDMMC_STA_VSWEND BIT(25) +#define SDMMC_STA_CKSTOP BIT(26) +#define SDMMC_STA_IDMATE BIT(27) +#define SDMMC_STA_IDMABTC BIT(28) + +/* SDMMC_ICR register */ +#define SDMMC_ICR_CCRCFAILC BIT(0) +#define SDMMC_ICR_DCRCFAILC BIT(1) +#define SDMMC_ICR_CTIMEOUTC BIT(2) +#define SDMMC_ICR_DTIMEOUTC BIT(3) +#define SDMMC_ICR_TXUNDERRC BIT(4) +#define SDMMC_ICR_RXOVERRC BIT(5) +#define SDMMC_ICR_CMDRENDC BIT(6) +#define SDMMC_ICR_CMDSENTC BIT(7) +#define SDMMC_ICR_DATAENDC BIT(8) +#define SDMMC_ICR_DHOLDC BIT(9) +#define SDMMC_ICR_DBCKENDC BIT(10) +#define SDMMC_ICR_DABORTC BIT(11) +#define SDMMC_ICR_BUSYD0ENDC BIT(21) +#define SDMMC_ICR_SDMMCITC BIT(22) +#define SDMMC_ICR_ACKFAILC BIT(23) +#define SDMMC_ICR_ACKTIMEOUTC BIT(24) +#define SDMMC_ICR_VSWENDC BIT(25) +#define SDMMC_ICR_CKSTOPC BIT(26) +#define SDMMC_ICR_IDMATEC BIT(27) +#define SDMMC_ICR_IDMABTCC BIT(28) +#define SDMMC_ICR_STATIC_FLAGS ((GENMASK(28, 21)) | (GENMASK(11, 0))) + +/* SDMMC_MASK register */ +#define SDMMC_MASK_CCRCFAILIE BIT(0) +#define SDMMC_MASK_DCRCFAILIE BIT(1) +#define SDMMC_MASK_CTIMEOUTIE BIT(2) +#define SDMMC_MASK_DTIMEOUTIE BIT(3) +#define SDMMC_MASK_TXUNDERRIE BIT(4) +#define SDMMC_MASK_RXOVERRIE BIT(5) +#define SDMMC_MASK_CMDRENDIE BIT(6) +#define SDMMC_MASK_CMDSENTIE BIT(7) +#define SDMMC_MASK_DATAENDIE BIT(8) +#define SDMMC_MASK_DHOLDIE BIT(9) +#define SDMMC_MASK_DBCKENDIE BIT(10) +#define SDMMC_MASK_DABORTIE BIT(11) +#define SDMMC_MASK_TXFIFOHEIE BIT(14) +#define SDMMC_MASK_RXFIFOHFIE BIT(15) +#define SDMMC_MASK_RXFIFOFIE BIT(17) +#define SDMMC_MASK_TXFIFOEIE BIT(18) +#define SDMMC_MASK_BUSYD0ENDIE BIT(21) +#define SDMMC_MASK_SDMMCITIE BIT(22) +#define SDMMC_MASK_ACKFAILIE BIT(23) +#define SDMMC_MASK_ACKTIMEOUTIE BIT(24) +#define SDMMC_MASK_VSWENDIE BIT(25) +#define SDMMC_MASK_CKSTOPIE BIT(26) +#define SDMMC_MASK_IDMABTCIE BIT(28) + +/* SDMMC_IDMACTRL register */ +#define SDMMC_IDMACTRL_IDMAEN BIT(0) + +#define SDMMC_CMD_TIMEOUT 0xFFFFFFFF + +DECLARE_GLOBAL_DATA_PTR; + +static void stm32_sdmmc2_start_data(struct stm32_sdmmc2_priv *priv, + struct mmc_data *data, + struct stm32_sdmmc2_ctx *ctx) +{ + u32 data_ctrl, idmabase0; + + /* Configure the SDMMC DPSM (Data Path State Machine) */ + data_ctrl = (__ilog2(data->blocksize) << + SDMMC_DCTRL_DBLOCKSIZE_SHIFT) & + SDMMC_DCTRL_DBLOCKSIZE; + + if (data->flags & MMC_DATA_READ) { + data_ctrl |= SDMMC_DCTRL_DTDIR; + idmabase0 = (u32)data->dest; + } else { + idmabase0 = (u32)data->src; + } + + /* Set the SDMMC Data TimeOut value */ + writel(SDMMC_CMD_TIMEOUT, priv->base + SDMMC_DTIMER); + + /* Set the SDMMC DataLength value */ + writel(ctx->data_length, priv->base + SDMMC_DLEN); + + /* Write to SDMMC DCTRL */ + writel(data_ctrl, priv->base + SDMMC_DCTRL); + + /* Cache align */ + ctx->cache_start = rounddown(idmabase0, ARCH_DMA_MINALIGN); + ctx->cache_end = roundup(idmabase0 + ctx->data_length, + ARCH_DMA_MINALIGN); + + /* + * Flush data cache before DMA start (clean and invalidate) + * Clean also needed for read + * Avoid issue on buffer not cached-aligned + */ + flush_dcache_range(ctx->cache_start, ctx->cache_end); + + /* Enable internal DMA */ + writel(idmabase0, priv->base + SDMMC_IDMABASE0); + writel(SDMMC_IDMACTRL_IDMAEN, priv->base + SDMMC_IDMACTRL); +} + +static void stm32_sdmmc2_start_cmd(struct stm32_sdmmc2_priv *priv, + struct mmc_cmd *cmd, u32 cmd_param) +{ + if (readl(priv->base + SDMMC_ARG) & SDMMC_CMD_CPSMEN) + writel(0, priv->base + SDMMC_ARG); + + cmd_param |= cmd->cmdidx | SDMMC_CMD_CPSMEN; + if (cmd->resp_type & MMC_RSP_PRESENT) { + if (cmd->resp_type & MMC_RSP_136) + cmd_param |= SDMMC_CMD_WAITRESP; + else if (cmd->resp_type & MMC_RSP_CRC) + cmd_param |= SDMMC_CMD_WAITRESP_0; + else + cmd_param |= SDMMC_CMD_WAITRESP_1; + } + + /* Clear flags */ + writel(SDMMC_ICR_STATIC_FLAGS, priv->base + SDMMC_ICR); + + /* Set SDMMC argument value */ + writel(cmd->cmdarg, priv->base + SDMMC_ARG); + + /* Set SDMMC command parameters */ + writel(cmd_param, priv->base + SDMMC_CMD); +} + +static int stm32_sdmmc2_end_cmd(struct stm32_sdmmc2_priv *priv, + struct mmc_cmd *cmd, + struct stm32_sdmmc2_ctx *ctx) +{ + u32 mask = SDMMC_STA_CTIMEOUT; + u32 status; + int ret; + + if (cmd->resp_type & MMC_RSP_PRESENT) { + mask |= SDMMC_STA_CMDREND; + if (cmd->resp_type & MMC_RSP_CRC) + mask |= SDMMC_STA_CCRCFAIL; + } else { + mask |= SDMMC_STA_CMDSENT; + } + + /* Polling status register */ + ret = readl_poll_timeout(priv->base + SDMMC_STA, status, status & mask, + 300); + + if (ret < 0) { + debug("%s: timeout reading SDMMC_STA register\n", __func__); + ctx->dpsm_abort = true; + return ret; + } + + /* Check status */ + if (status & SDMMC_STA_CTIMEOUT) { + debug("%s: error SDMMC_STA_CTIMEOUT (0x%x) for cmd %d\n", + __func__, status, cmd->cmdidx); + ctx->dpsm_abort = true; + return -ETIMEDOUT; + } + + if (status & SDMMC_STA_CCRCFAIL && cmd->resp_type & MMC_RSP_CRC) { + debug("%s: error SDMMC_STA_CCRCFAIL (0x%x) for cmd %d\n", + __func__, status, cmd->cmdidx); + ctx->dpsm_abort = true; + return -EILSEQ; + } + + if (status & SDMMC_STA_CMDREND && cmd->resp_type & MMC_RSP_PRESENT) { + cmd->response[0] = readl(priv->base + SDMMC_RESP1); + if (cmd->resp_type & MMC_RSP_136) { + cmd->response[1] = readl(priv->base + SDMMC_RESP2); + cmd->response[2] = readl(priv->base + SDMMC_RESP3); + cmd->response[3] = readl(priv->base + SDMMC_RESP4); + } + } + + return 0; +} + +static int stm32_sdmmc2_end_data(struct stm32_sdmmc2_priv *priv, + struct mmc_cmd *cmd, + struct mmc_data *data, + struct stm32_sdmmc2_ctx *ctx) +{ + u32 mask = SDMMC_STA_DCRCFAIL | SDMMC_STA_DTIMEOUT | + SDMMC_STA_IDMATE | SDMMC_STA_DATAEND; + u32 status; + + if (data->flags & MMC_DATA_READ) + mask |= SDMMC_STA_RXOVERR; + else + mask |= SDMMC_STA_TXUNDERR; + + status = readl(priv->base + SDMMC_STA); + while (!(status & mask)) + status = readl(priv->base + SDMMC_STA); + + /* + * Need invalidate the dcache again to avoid any + * cache-refill during the DMA operations (pre-fetching) + */ + if (data->flags & MMC_DATA_READ) + invalidate_dcache_range(ctx->cache_start, ctx->cache_end); + + if (status & SDMMC_STA_DCRCFAIL) { + debug("%s: error SDMMC_STA_DCRCFAIL (0x%x) for cmd %d\n", + __func__, status, cmd->cmdidx); + if (readl(priv->base + SDMMC_DCOUNT)) + ctx->dpsm_abort = true; + return -EILSEQ; + } + + if (status & SDMMC_STA_DTIMEOUT) { + debug("%s: error SDMMC_STA_DTIMEOUT (0x%x) for cmd %d\n", + __func__, status, cmd->cmdidx); + ctx->dpsm_abort = true; + return -ETIMEDOUT; + } + + if (status & SDMMC_STA_TXUNDERR) { + debug("%s: error SDMMC_STA_TXUNDERR (0x%x) for cmd %d\n", + __func__, status, cmd->cmdidx); + ctx->dpsm_abort = true; + return -EIO; + } + + if (status & SDMMC_STA_RXOVERR) { + debug("%s: error SDMMC_STA_RXOVERR (0x%x) for cmd %d\n", + __func__, status, cmd->cmdidx); + ctx->dpsm_abort = true; + return -EIO; + } + + if (status & SDMMC_STA_IDMATE) { + debug("%s: error SDMMC_STA_IDMATE (0x%x) for cmd %d\n", + __func__, status, cmd->cmdidx); + ctx->dpsm_abort = true; + return -EIO; + } + + return 0; +} + +static int stm32_sdmmc2_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, + struct mmc_data *data) +{ + struct stm32_sdmmc2_priv *priv = dev_get_priv(dev); + struct stm32_sdmmc2_ctx ctx; + u32 cmdat = data ? SDMMC_CMD_CMDTRANS : 0; + int ret, retry = 3; + +retry_cmd: + ctx.data_length = 0; + ctx.dpsm_abort = false; + + if (data) { + ctx.data_length = data->blocks * data->blocksize; + stm32_sdmmc2_start_data(priv, data, &ctx); + } + + stm32_sdmmc2_start_cmd(priv, cmd, cmdat); + + debug("%s: send cmd %d data: 0x%x @ 0x%x\n", + __func__, cmd->cmdidx, + data ? ctx.data_length : 0, (unsigned int)data); + + ret = stm32_sdmmc2_end_cmd(priv, cmd, &ctx); + + if (data && !ret) + ret = stm32_sdmmc2_end_data(priv, cmd, data, &ctx); + + /* Clear flags */ + writel(SDMMC_ICR_STATIC_FLAGS, priv->base + SDMMC_ICR); + if (data) + writel(0x0, priv->base + SDMMC_IDMACTRL); + + /* + * To stop Data Path State Machine, a stop_transmission command + * shall be send on cmd or data errors. + */ + if (ctx.dpsm_abort && (cmd->cmdidx != MMC_CMD_STOP_TRANSMISSION)) { + struct mmc_cmd stop_cmd; + + stop_cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION; + stop_cmd.cmdarg = 0; + stop_cmd.resp_type = MMC_RSP_R1b; + + debug("%s: send STOP command to abort dpsm treatments\n", + __func__); + + stm32_sdmmc2_start_cmd(priv, &stop_cmd, SDMMC_CMD_CMDSTOP); + stm32_sdmmc2_end_cmd(priv, &stop_cmd, &ctx); + + writel(SDMMC_ICR_STATIC_FLAGS, priv->base + SDMMC_ICR); + } + + if ((ret != -ETIMEDOUT) && (ret != 0) && retry) { + printf("%s: cmd %d failed, retrying ...\n", + __func__, cmd->cmdidx); + retry--; + goto retry_cmd; + } + + debug("%s: end for CMD %d, ret = %d\n", __func__, cmd->cmdidx, ret); + + return ret; +} + +static void stm32_sdmmc2_pwron(struct stm32_sdmmc2_priv *priv) +{ + /* Reset */ + reset_assert(&priv->reset_ctl); + udelay(2); + reset_deassert(&priv->reset_ctl); + + udelay(1000); + + /* Set Power State to ON */ + writel(SDMMC_POWER_PWRCTRL | priv->pwr_reg_msk, priv->base + SDMMC_POWER); + + /* + * 1ms: required power up waiting time before starting the + * SD initialization sequence + */ + udelay(1000); +} + +#define IS_RISING_EDGE(reg) (reg & SDMMC_CLKCR_NEGEDGE ? 0 : 1) +static int stm32_sdmmc2_set_ios(struct udevice *dev) +{ + struct mmc *mmc = mmc_get_mmc_dev(dev); + struct stm32_sdmmc2_priv *priv = dev_get_priv(dev); + struct stm32_sdmmc2_plat *plat = dev_get_platdata(dev); + struct mmc_config *cfg = &plat->cfg; + u32 desired = mmc->clock; + u32 sys_clock = clk_get_rate(&priv->clk); + u32 clk = 0; + + debug("%s: bus_with = %d, clock = %d\n", __func__, + mmc->bus_width, mmc->clock); + + if ((mmc->bus_width == 1) && (desired == cfg->f_min)) + stm32_sdmmc2_pwron(priv); + + /* + * clk_div = 0 => command and data generated on SDMMCCLK falling edge + * clk_div > 0 and NEGEDGE = 0 => command and data generated on + * SDMMCCLK rising edge + * clk_div > 0 and NEGEDGE = 1 => command and data generated on + * SDMMCCLK falling edge + */ + if (desired && ((sys_clock > desired) || + IS_RISING_EDGE(priv->clk_reg_msk))) { + clk = DIV_ROUND_UP(sys_clock, 2 * desired); + if (clk > SDMMC_CLKCR_CLKDIV_MAX) + clk = SDMMC_CLKCR_CLKDIV_MAX; + } + + if (mmc->bus_width == 4) + clk |= SDMMC_CLKCR_WIDBUS_4; + if (mmc->bus_width == 8) + clk |= SDMMC_CLKCR_WIDBUS_8; + + writel(clk | priv->clk_reg_msk, priv->base + SDMMC_CLKCR); + + return 0; +} + +static int stm32_sdmmc2_getcd(struct udevice *dev) +{ + struct stm32_sdmmc2_priv *priv = dev_get_priv(dev); + + debug("stm32_sdmmc2_getcd called\n"); + + if (dm_gpio_is_valid(&priv->cd_gpio)) + return dm_gpio_get_value(&priv->cd_gpio); + + return 1; +} + +static const struct dm_mmc_ops stm32_sdmmc2_ops = { + .send_cmd = stm32_sdmmc2_send_cmd, + .set_ios = stm32_sdmmc2_set_ios, + .get_cd = stm32_sdmmc2_getcd, +}; + +static int stm32_sdmmc2_probe(struct udevice *dev) +{ + struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); + struct stm32_sdmmc2_plat *plat = dev_get_platdata(dev); + struct stm32_sdmmc2_priv *priv = dev_get_priv(dev); + struct mmc_config *cfg = &plat->cfg; + int ret; + + priv->base = dev_read_addr(dev); + if (priv->base == FDT_ADDR_T_NONE) + return -EINVAL; + + if (dev_read_bool(dev, "st,negedge")) + priv->clk_reg_msk |= SDMMC_CLKCR_NEGEDGE; + if (dev_read_bool(dev, "st,dirpol")) + priv->pwr_reg_msk |= SDMMC_POWER_DIRPOL; + + ret = clk_get_by_index(dev, 0, &priv->clk); + if (ret) + return ret; + + ret = clk_enable(&priv->clk); + if (ret) + goto clk_free; + + ret = reset_get_by_index(dev, 0, &priv->reset_ctl); + if (ret) + goto clk_disable; + + gpio_request_by_name(dev, "cd-gpios", 0, &priv->cd_gpio, + GPIOD_IS_IN); + + cfg->f_min = 400000; + cfg->f_max = dev_read_u32_default(dev, "max-frequency", 52000000); + cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; + cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; + cfg->name = "STM32 SDMMC2"; + + cfg->host_caps = 0; + if (cfg->f_max > 25000000) + cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS; + + switch (dev_read_u32_default(dev, "bus-width", 1)) { + case 8: + cfg->host_caps |= MMC_MODE_8BIT; + case 4: + cfg->host_caps |= MMC_MODE_4BIT; + break; + case 1: + break; + default: + error("invalid \"bus-width\" property, force to 1\n"); + } + + upriv->mmc = &plat->mmc; + + return 0; + +clk_disable: + clk_disable(&priv->clk); +clk_free: + clk_free(&priv->clk); + + return ret; +} + +int stm32_sdmmc_bind(struct udevice *dev) +{ + struct stm32_sdmmc2_plat *plat = dev_get_platdata(dev); + + return mmc_bind(dev, &plat->mmc, &plat->cfg); +} + +static const struct udevice_id stm32_sdmmc2_ids[] = { + { .compatible = "st,stm32-sdmmc2" }, + { } +}; + +U_BOOT_DRIVER(stm32_sdmmc2) = { + .name = "stm32_sdmmc2", + .id = UCLASS_MMC, + .of_match = stm32_sdmmc2_ids, + .ops = &stm32_sdmmc2_ops, + .probe = stm32_sdmmc2_probe, + .bind = stm32_sdmmc_bind, + .priv_auto_alloc_size = sizeof(struct stm32_sdmmc2_priv), + .platdata_auto_alloc_size = sizeof(struct stm32_sdmmc2_plat), +}; diff --git a/drivers/mmc/uniphier-sd.c b/drivers/mmc/uniphier-sd.c index 721b75fdda..0d1203cb76 100644 --- a/drivers/mmc/uniphier-sd.c +++ b/drivers/mmc/uniphier-sd.c @@ -14,6 +14,7 @@ #include <linux/dma-direction.h> #include <linux/io.h> #include <linux/sizes.h> +#include <power/regulator.h> #include <asm/unaligned.h> DECLARE_GLOBAL_DATA_PTR; @@ -132,8 +133,43 @@ struct uniphier_sd_priv { #define UNIPHIER_SD_CAP_NONREMOVABLE BIT(0) /* Nonremovable e.g. eMMC */ #define UNIPHIER_SD_CAP_DMA_INTERNAL BIT(1) /* have internal DMA engine */ #define UNIPHIER_SD_CAP_DIV1024 BIT(2) /* divisor 1024 is available */ +#define UNIPHIER_SD_CAP_64BIT BIT(3) /* Controller is 64bit */ }; +static u64 uniphier_sd_readq(struct uniphier_sd_priv *priv, unsigned int reg) +{ + if (priv->caps & UNIPHIER_SD_CAP_64BIT) + return readq(priv->regbase + (reg << 1)); + else + return readq(priv->regbase + reg); +} + +static void uniphier_sd_writeq(struct uniphier_sd_priv *priv, + u64 val, unsigned int reg) +{ + if (priv->caps & UNIPHIER_SD_CAP_64BIT) + writeq(val, priv->regbase + (reg << 1)); + else + writeq(val, priv->regbase + reg); +} + +static u32 uniphier_sd_readl(struct uniphier_sd_priv *priv, unsigned int reg) +{ + if (priv->caps & UNIPHIER_SD_CAP_64BIT) + return readl(priv->regbase + (reg << 1)); + else + return readl(priv->regbase + reg); +} + +static void uniphier_sd_writel(struct uniphier_sd_priv *priv, + u32 val, unsigned int reg) +{ + if (priv->caps & UNIPHIER_SD_CAP_64BIT) + writel(val, priv->regbase + (reg << 1)); + else + writel(val, priv->regbase + reg); +} + static dma_addr_t __dma_map_single(void *ptr, size_t size, enum dma_data_direction dir) { @@ -157,7 +193,7 @@ static void __dma_unmap_single(dma_addr_t addr, size_t size, static int uniphier_sd_check_error(struct udevice *dev) { struct uniphier_sd_priv *priv = dev_get_priv(dev); - u32 info2 = readl(priv->regbase + UNIPHIER_SD_INFO2); + u32 info2 = uniphier_sd_readl(priv, UNIPHIER_SD_INFO2); if (info2 & UNIPHIER_SD_INFO2_ERR_RTO) { /* @@ -195,7 +231,7 @@ static int uniphier_sd_wait_for_irq(struct udevice *dev, unsigned int reg, long wait = 1000000; int ret; - while (!(readl(priv->regbase + reg) & flag)) { + while (!(uniphier_sd_readl(priv, reg) & flag)) { if (wait-- < 0) { dev_err(dev, "timeout\n"); return -ETIMEDOUT; @@ -211,7 +247,7 @@ static int uniphier_sd_wait_for_irq(struct udevice *dev, unsigned int reg, return 0; } -static int uniphier_sd_pio_read_one_block(struct udevice *dev, u32 **pbuf, +static int uniphier_sd_pio_read_one_block(struct udevice *dev, char *pbuf, uint blocksize) { struct uniphier_sd_priv *priv = dev_get_priv(dev); @@ -227,22 +263,44 @@ static int uniphier_sd_pio_read_one_block(struct udevice *dev, u32 **pbuf, * Clear the status flag _before_ read the buffer out because * UNIPHIER_SD_INFO2_BRE is edge-triggered, not level-triggered. */ - writel(0, priv->regbase + UNIPHIER_SD_INFO2); - - if (likely(IS_ALIGNED((unsigned long)*pbuf, 4))) { - for (i = 0; i < blocksize / 4; i++) - *(*pbuf)++ = readl(priv->regbase + UNIPHIER_SD_BUF); + uniphier_sd_writel(priv, 0, UNIPHIER_SD_INFO2); + + if (priv->caps & UNIPHIER_SD_CAP_64BIT) { + u64 *buf = (u64 *)pbuf; + if (likely(IS_ALIGNED((uintptr_t)buf, 8))) { + for (i = 0; i < blocksize / 8; i++) { + *buf++ = uniphier_sd_readq(priv, + UNIPHIER_SD_BUF); + } + } else { + for (i = 0; i < blocksize / 8; i++) { + u64 data; + data = uniphier_sd_readq(priv, + UNIPHIER_SD_BUF); + put_unaligned(data, buf++); + } + } } else { - for (i = 0; i < blocksize / 4; i++) - put_unaligned(readl(priv->regbase + UNIPHIER_SD_BUF), - (*pbuf)++); + u32 *buf = (u32 *)pbuf; + if (likely(IS_ALIGNED((uintptr_t)buf, 4))) { + for (i = 0; i < blocksize / 4; i++) { + *buf++ = uniphier_sd_readl(priv, + UNIPHIER_SD_BUF); + } + } else { + for (i = 0; i < blocksize / 4; i++) { + u32 data; + data = uniphier_sd_readl(priv, UNIPHIER_SD_BUF); + put_unaligned(data, buf++); + } + } } return 0; } static int uniphier_sd_pio_write_one_block(struct udevice *dev, - const u32 **pbuf, uint blocksize) + const char *pbuf, uint blocksize) { struct uniphier_sd_priv *priv = dev_get_priv(dev); int i, ret; @@ -253,15 +311,36 @@ static int uniphier_sd_pio_write_one_block(struct udevice *dev, if (ret) return ret; - writel(0, priv->regbase + UNIPHIER_SD_INFO2); - - if (likely(IS_ALIGNED((unsigned long)*pbuf, 4))) { - for (i = 0; i < blocksize / 4; i++) - writel(*(*pbuf)++, priv->regbase + UNIPHIER_SD_BUF); + uniphier_sd_writel(priv, 0, UNIPHIER_SD_INFO2); + + if (priv->caps & UNIPHIER_SD_CAP_64BIT) { + const u64 *buf = (const u64 *)pbuf; + if (likely(IS_ALIGNED((uintptr_t)buf, 8))) { + for (i = 0; i < blocksize / 8; i++) { + uniphier_sd_writeq(priv, *buf++, + UNIPHIER_SD_BUF); + } + } else { + for (i = 0; i < blocksize / 8; i++) { + u64 data = get_unaligned(buf++); + uniphier_sd_writeq(priv, data, + UNIPHIER_SD_BUF); + } + } } else { - for (i = 0; i < blocksize / 4; i++) - writel(get_unaligned((*pbuf)++), - priv->regbase + UNIPHIER_SD_BUF); + const u32 *buf = (const u32 *)pbuf; + if (likely(IS_ALIGNED((uintptr_t)buf, 4))) { + for (i = 0; i < blocksize / 4; i++) { + uniphier_sd_writel(priv, *buf++, + UNIPHIER_SD_BUF); + } + } else { + for (i = 0; i < blocksize / 4; i++) { + u32 data = get_unaligned(buf++); + uniphier_sd_writel(priv, data, + UNIPHIER_SD_BUF); + } + } } return 0; @@ -269,19 +348,24 @@ static int uniphier_sd_pio_write_one_block(struct udevice *dev, static int uniphier_sd_pio_xfer(struct udevice *dev, struct mmc_data *data) { - u32 *dest = (u32 *)data->dest; - const u32 *src = (const u32 *)data->src; + const char *src = data->src; + char *dest = data->dest; int i, ret; for (i = 0; i < data->blocks; i++) { if (data->flags & MMC_DATA_READ) - ret = uniphier_sd_pio_read_one_block(dev, &dest, + ret = uniphier_sd_pio_read_one_block(dev, dest, data->blocksize); else - ret = uniphier_sd_pio_write_one_block(dev, &src, + ret = uniphier_sd_pio_write_one_block(dev, src, data->blocksize); if (ret) return ret; + + if (data->flags & MMC_DATA_READ) + dest += data->blocksize; + else + src += data->blocksize; } return 0; @@ -292,22 +376,22 @@ static void uniphier_sd_dma_start(struct uniphier_sd_priv *priv, { u32 tmp; - writel(0, priv->regbase + UNIPHIER_SD_DMA_INFO1); - writel(0, priv->regbase + UNIPHIER_SD_DMA_INFO2); + uniphier_sd_writel(priv, 0, UNIPHIER_SD_DMA_INFO1); + uniphier_sd_writel(priv, 0, UNIPHIER_SD_DMA_INFO2); /* enable DMA */ - tmp = readl(priv->regbase + UNIPHIER_SD_EXTMODE); + tmp = uniphier_sd_readl(priv, UNIPHIER_SD_EXTMODE); tmp |= UNIPHIER_SD_EXTMODE_DMA_EN; - writel(tmp, priv->regbase + UNIPHIER_SD_EXTMODE); + uniphier_sd_writel(priv, tmp, UNIPHIER_SD_EXTMODE); - writel(dma_addr & U32_MAX, priv->regbase + UNIPHIER_SD_DMA_ADDR_L); + uniphier_sd_writel(priv, dma_addr & U32_MAX, UNIPHIER_SD_DMA_ADDR_L); /* suppress the warning "right shift count >= width of type" */ dma_addr >>= min_t(int, 32, 8 * sizeof(dma_addr)); - writel(dma_addr & U32_MAX, priv->regbase + UNIPHIER_SD_DMA_ADDR_H); + uniphier_sd_writel(priv, dma_addr & U32_MAX, UNIPHIER_SD_DMA_ADDR_H); - writel(UNIPHIER_SD_DMA_CTL_START, priv->regbase + UNIPHIER_SD_DMA_CTL); + uniphier_sd_writel(priv, UNIPHIER_SD_DMA_CTL_START, UNIPHIER_SD_DMA_CTL); } static int uniphier_sd_dma_wait_for_irq(struct udevice *dev, u32 flag, @@ -316,7 +400,7 @@ static int uniphier_sd_dma_wait_for_irq(struct udevice *dev, u32 flag, struct uniphier_sd_priv *priv = dev_get_priv(dev); long wait = 1000000 + 10 * blocks; - while (!(readl(priv->regbase + UNIPHIER_SD_DMA_INFO1) & flag)) { + while (!(uniphier_sd_readl(priv, UNIPHIER_SD_DMA_INFO1) & flag)) { if (wait-- < 0) { dev_err(dev, "timeout during DMA\n"); return -ETIMEDOUT; @@ -325,7 +409,7 @@ static int uniphier_sd_dma_wait_for_irq(struct udevice *dev, u32 flag, udelay(10); } - if (readl(priv->regbase + UNIPHIER_SD_DMA_INFO2)) { + if (uniphier_sd_readl(priv, UNIPHIER_SD_DMA_INFO2)) { dev_err(dev, "error during DMA\n"); return -EIO; } @@ -343,7 +427,7 @@ static int uniphier_sd_dma_xfer(struct udevice *dev, struct mmc_data *data) u32 poll_flag, tmp; int ret; - tmp = readl(priv->regbase + UNIPHIER_SD_DMA_MODE); + tmp = uniphier_sd_readl(priv, UNIPHIER_SD_DMA_MODE); if (data->flags & MMC_DATA_READ) { buf = data->dest; @@ -357,7 +441,7 @@ static int uniphier_sd_dma_xfer(struct udevice *dev, struct mmc_data *data) tmp &= ~UNIPHIER_SD_DMA_MODE_DIR_RD; } - writel(tmp, priv->regbase + UNIPHIER_SD_DMA_MODE); + uniphier_sd_writel(priv, tmp, UNIPHIER_SD_DMA_MODE); dma_addr = __dma_map_single(buf, len, dir); @@ -396,27 +480,27 @@ static int uniphier_sd_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, int ret; u32 tmp; - if (readl(priv->regbase + UNIPHIER_SD_INFO2) & UNIPHIER_SD_INFO2_CBSY) { + if (uniphier_sd_readl(priv, UNIPHIER_SD_INFO2) & UNIPHIER_SD_INFO2_CBSY) { dev_err(dev, "command busy\n"); return -EBUSY; } /* clear all status flags */ - writel(0, priv->regbase + UNIPHIER_SD_INFO1); - writel(0, priv->regbase + UNIPHIER_SD_INFO2); + uniphier_sd_writel(priv, 0, UNIPHIER_SD_INFO1); + uniphier_sd_writel(priv, 0, UNIPHIER_SD_INFO2); /* disable DMA once */ - tmp = readl(priv->regbase + UNIPHIER_SD_EXTMODE); + tmp = uniphier_sd_readl(priv, UNIPHIER_SD_EXTMODE); tmp &= ~UNIPHIER_SD_EXTMODE_DMA_EN; - writel(tmp, priv->regbase + UNIPHIER_SD_EXTMODE); + uniphier_sd_writel(priv, tmp, UNIPHIER_SD_EXTMODE); - writel(cmd->cmdarg, priv->regbase + UNIPHIER_SD_ARG); + uniphier_sd_writel(priv, cmd->cmdarg, UNIPHIER_SD_ARG); tmp = cmd->cmdidx; if (data) { - writel(data->blocksize, priv->regbase + UNIPHIER_SD_SIZE); - writel(data->blocks, priv->regbase + UNIPHIER_SD_SECCNT); + uniphier_sd_writel(priv, data->blocksize, UNIPHIER_SD_SIZE); + uniphier_sd_writel(priv, data->blocks, UNIPHIER_SD_SECCNT); /* Do not send CMD12 automatically */ tmp |= UNIPHIER_SD_CMD_NOSTOP | UNIPHIER_SD_CMD_DATA; @@ -457,7 +541,7 @@ static int uniphier_sd_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, dev_dbg(dev, "sending CMD%d (SD_CMD=%08x, SD_ARG=%08x)\n", cmd->cmdidx, tmp, cmd->cmdarg); - writel(tmp, priv->regbase + UNIPHIER_SD_CMD); + uniphier_sd_writel(priv, tmp, UNIPHIER_SD_CMD); ret = uniphier_sd_wait_for_irq(dev, UNIPHIER_SD_INFO1, UNIPHIER_SD_INFO1_RSP); @@ -465,10 +549,10 @@ static int uniphier_sd_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, return ret; if (cmd->resp_type & MMC_RSP_136) { - u32 rsp_127_104 = readl(priv->regbase + UNIPHIER_SD_RSP76); - u32 rsp_103_72 = readl(priv->regbase + UNIPHIER_SD_RSP54); - u32 rsp_71_40 = readl(priv->regbase + UNIPHIER_SD_RSP32); - u32 rsp_39_8 = readl(priv->regbase + UNIPHIER_SD_RSP10); + u32 rsp_127_104 = uniphier_sd_readl(priv, UNIPHIER_SD_RSP76); + u32 rsp_103_72 = uniphier_sd_readl(priv, UNIPHIER_SD_RSP54); + u32 rsp_71_40 = uniphier_sd_readl(priv, UNIPHIER_SD_RSP32); + u32 rsp_39_8 = uniphier_sd_readl(priv, UNIPHIER_SD_RSP10); cmd->response[0] = ((rsp_127_104 & 0x00ffffff) << 8) | ((rsp_103_72 & 0xff000000) >> 24); @@ -479,7 +563,7 @@ static int uniphier_sd_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, cmd->response[3] = (rsp_39_8 & 0xffffff) << 8; } else { /* bit 39-8 */ - cmd->response[0] = readl(priv->regbase + UNIPHIER_SD_RSP10); + cmd->response[0] = uniphier_sd_readl(priv, UNIPHIER_SD_RSP10); } if (data) { @@ -518,10 +602,10 @@ static int uniphier_sd_set_bus_width(struct uniphier_sd_priv *priv, return -EINVAL; } - tmp = readl(priv->regbase + UNIPHIER_SD_OPTION); + tmp = uniphier_sd_readl(priv, UNIPHIER_SD_OPTION); tmp &= ~UNIPHIER_SD_OPTION_WIDTH_MASK; tmp |= val; - writel(tmp, priv->regbase + UNIPHIER_SD_OPTION); + uniphier_sd_writel(priv, tmp, UNIPHIER_SD_OPTION); return 0; } @@ -531,12 +615,12 @@ static void uniphier_sd_set_ddr_mode(struct uniphier_sd_priv *priv, { u32 tmp; - tmp = readl(priv->regbase + UNIPHIER_SD_IF_MODE); + tmp = uniphier_sd_readl(priv, UNIPHIER_SD_IF_MODE); if (mmc->ddr_mode) tmp |= UNIPHIER_SD_IF_MODE_DDR; else tmp &= ~UNIPHIER_SD_IF_MODE_DDR; - writel(tmp, priv->regbase + UNIPHIER_SD_IF_MODE); + uniphier_sd_writel(priv, tmp, UNIPHIER_SD_IF_MODE); } static void uniphier_sd_set_clk_rate(struct uniphier_sd_priv *priv, @@ -573,21 +657,21 @@ static void uniphier_sd_set_clk_rate(struct uniphier_sd_priv *priv, else val = UNIPHIER_SD_CLKCTL_DIV1024; - tmp = readl(priv->regbase + UNIPHIER_SD_CLKCTL); + tmp = uniphier_sd_readl(priv, UNIPHIER_SD_CLKCTL); if (tmp & UNIPHIER_SD_CLKCTL_SCLKEN && (tmp & UNIPHIER_SD_CLKCTL_DIV_MASK) == val) return; /* stop the clock before changing its rate to avoid a glitch signal */ tmp &= ~UNIPHIER_SD_CLKCTL_SCLKEN; - writel(tmp, priv->regbase + UNIPHIER_SD_CLKCTL); + uniphier_sd_writel(priv, tmp, UNIPHIER_SD_CLKCTL); tmp &= ~UNIPHIER_SD_CLKCTL_DIV_MASK; tmp |= val | UNIPHIER_SD_CLKCTL_OFFEN; - writel(tmp, priv->regbase + UNIPHIER_SD_CLKCTL); + uniphier_sd_writel(priv, tmp, UNIPHIER_SD_CLKCTL); tmp |= UNIPHIER_SD_CLKCTL_SCLKEN; - writel(tmp, priv->regbase + UNIPHIER_SD_CLKCTL); + uniphier_sd_writel(priv, tmp, UNIPHIER_SD_CLKCTL); udelay(1000); } @@ -617,7 +701,7 @@ static int uniphier_sd_get_cd(struct udevice *dev) if (priv->caps & UNIPHIER_SD_CAP_NONREMOVABLE) return 1; - return !!(readl(priv->regbase + UNIPHIER_SD_INFO1) & + return !!(uniphier_sd_readl(priv, UNIPHIER_SD_INFO1) & UNIPHIER_SD_INFO1_CD); } @@ -632,28 +716,28 @@ static void uniphier_sd_host_init(struct uniphier_sd_priv *priv) u32 tmp; /* soft reset of the host */ - tmp = readl(priv->regbase + UNIPHIER_SD_SOFT_RST); + tmp = uniphier_sd_readl(priv, UNIPHIER_SD_SOFT_RST); tmp &= ~UNIPHIER_SD_SOFT_RST_RSTX; - writel(tmp, priv->regbase + UNIPHIER_SD_SOFT_RST); + uniphier_sd_writel(priv, tmp, UNIPHIER_SD_SOFT_RST); tmp |= UNIPHIER_SD_SOFT_RST_RSTX; - writel(tmp, priv->regbase + UNIPHIER_SD_SOFT_RST); + uniphier_sd_writel(priv, tmp, UNIPHIER_SD_SOFT_RST); /* FIXME: implement eMMC hw_reset */ - writel(UNIPHIER_SD_STOP_SEC, priv->regbase + UNIPHIER_SD_STOP); + uniphier_sd_writel(priv, UNIPHIER_SD_STOP_SEC, UNIPHIER_SD_STOP); /* * Connected to 32bit AXI. * This register dropped backward compatibility at version 0x10. * Write an appropriate value depending on the IP version. */ - writel(priv->version >= 0x10 ? 0x00000101 : 0x00000000, - priv->regbase + UNIPHIER_SD_HOST_MODE); + uniphier_sd_writel(priv, priv->version >= 0x10 ? 0x00000101 : 0x00000000, + UNIPHIER_SD_HOST_MODE); if (priv->caps & UNIPHIER_SD_CAP_DMA_INTERNAL) { - tmp = readl(priv->regbase + UNIPHIER_SD_DMA_MODE); + tmp = uniphier_sd_readl(priv, UNIPHIER_SD_DMA_MODE); tmp |= UNIPHIER_SD_DMA_MODE_ADDR_INC; - writel(tmp, priv->regbase + UNIPHIER_SD_DMA_MODE); + uniphier_sd_writel(priv, tmp, UNIPHIER_SD_DMA_MODE); } } @@ -669,9 +753,13 @@ static int uniphier_sd_probe(struct udevice *dev) struct uniphier_sd_plat *plat = dev_get_platdata(dev); struct uniphier_sd_priv *priv = dev_get_priv(dev); struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); + const u32 quirks = dev_get_driver_data(dev); fdt_addr_t base; struct clk clk; int ret; +#ifdef CONFIG_DM_REGULATOR + struct udevice *vqmmc_dev; +#endif base = devfdt_get_addr(dev); if (base == FDT_ADDR_T_NONE) @@ -681,6 +769,15 @@ static int uniphier_sd_probe(struct udevice *dev) if (!priv->regbase) return -ENOMEM; +#ifdef CONFIG_DM_REGULATOR + ret = device_get_supply_regulator(dev, "vqmmc-supply", &vqmmc_dev); + if (!ret) { + /* Set the regulator to 3.3V until we support 1.8V modes */ + regulator_set_value(vqmmc_dev, 3300000); + regulator_set_enable(vqmmc_dev, true); + } +#endif + ret = clk_get_by_index(dev, 0, &clk); if (ret < 0) { dev_err(dev, "failed to get host clock\n"); @@ -720,18 +817,22 @@ static int uniphier_sd_probe(struct udevice *dev) return -EINVAL; } + if (quirks) { + priv->caps = quirks; + } else { + priv->version = uniphier_sd_readl(priv, UNIPHIER_SD_VERSION) & + UNIPHIER_SD_VERSION_IP; + dev_dbg(dev, "version %x\n", priv->version); + if (priv->version >= 0x10) { + priv->caps |= UNIPHIER_SD_CAP_DMA_INTERNAL; + priv->caps |= UNIPHIER_SD_CAP_DIV1024; + } + } + if (fdt_get_property(gd->fdt_blob, dev_of_offset(dev), "non-removable", NULL)) priv->caps |= UNIPHIER_SD_CAP_NONREMOVABLE; - priv->version = readl(priv->regbase + UNIPHIER_SD_VERSION) & - UNIPHIER_SD_VERSION_IP; - dev_dbg(dev, "version %x\n", priv->version); - if (priv->version >= 0x10) { - priv->caps |= UNIPHIER_SD_CAP_DMA_INTERNAL; - priv->caps |= UNIPHIER_SD_CAP_DIV1024; - } - uniphier_sd_host_init(priv); plat->cfg.voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34; @@ -746,7 +847,9 @@ static int uniphier_sd_probe(struct udevice *dev) } static const struct udevice_id uniphier_sd_match[] = { - { .compatible = "socionext,uniphier-sdhc" }, + { .compatible = "renesas,sdhi-r8a7795", .data = UNIPHIER_SD_CAP_64BIT }, + { .compatible = "renesas,sdhi-r8a7796", .data = UNIPHIER_SD_CAP_64BIT }, + { .compatible = "socionext,uniphier-sdhc", .data = 0 }, { /* sentinel */ } }; diff --git a/drivers/mtd/cfi_flash.c b/drivers/mtd/cfi_flash.c index f3bb72788a..8a5babea7b 100644 --- a/drivers/mtd/cfi_flash.c +++ b/drivers/mtd/cfi_flash.c @@ -111,11 +111,9 @@ static void cfi_flash_init_dm(void) } } -static phys_addr_t cfi_flash_base[CFI_MAX_FLASH_BANKS]; - phys_addr_t cfi_flash_bank_addr(int i) { - return cfi_flash_base[i]; + return flash_info[i].base; } #else __weak phys_addr_t cfi_flash_bank_addr(int i) @@ -546,7 +544,16 @@ static int flash_is_busy (flash_info_t * info, flash_sect_t sect) #ifdef CONFIG_FLASH_CFI_LEGACY case CFI_CMDSET_AMD_LEGACY: #endif - retval = flash_toggle (info, sect, 0, AMD_STATUS_TOGGLE); + if (info->sr_supported) { + flash_write_cmd (info, sect, info->addr_unlock1, + FLASH_CMD_READ_STATUS); + retval = !flash_isset (info, sect, 0, + FLASH_STATUS_DONE); + } else { + retval = flash_toggle (info, sect, 0, + AMD_STATUS_TOGGLE); + } + break; default: retval = 0; @@ -1687,6 +1694,7 @@ static void cmdset_amd_read_jedec_ids(flash_info_t *info) { ushort bankId = 0; uchar manuId; + uchar lsbits; flash_write_cmd(info, 0, 0, AMD_CMD_RESET); flash_unlock_seq(info, 0); @@ -1702,6 +1710,9 @@ static void cmdset_amd_read_jedec_ids(flash_info_t *info) } info->manufacturer_id = manuId; + lsbits = flash_read_uchar(info, FLASH_OFFSET_LOWER_SW_BITS); + info->sr_supported = lsbits & BIT(0); + switch (info->chipwidth){ case FLASH_CFI_8BIT: info->device_id = flash_read_uchar (info, @@ -2458,10 +2469,12 @@ static int cfi_flash_probe(struct udevice *dev) while (idx < len) { addr = fdt_translate_address((void *)blob, node, cell + idx); - cfi_flash_base[cfi_flash_num_flash_banks++] = addr; + flash_info[cfi_flash_num_flash_banks].dev = dev; + flash_info[cfi_flash_num_flash_banks].base = addr; + cfi_flash_num_flash_banks++; idx += addrc + sizec; } - gd->bd->bi_flashstart = cfi_flash_base[0]; + gd->bd->bi_flashstart = flash_info[0].base; return 0; } diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index 47cf37d1d9..54718f418c 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c @@ -10,7 +10,7 @@ #include <malloc.h> #include <nand.h> #include <linux/errno.h> -#include <asm/io.h> +#include <linux/io.h> #include "denali.h" @@ -433,17 +433,13 @@ static void find_valid_banks(struct denali_nand_info *denali) */ static void detect_max_banks(struct denali_nand_info *denali) { - uint32_t features = readl(denali->flash_reg + FEATURES); - /* - * Read the revision register, so we can calculate the max_banks - * properly: the encoding changed from rev 5.0 to 5.1 - */ - u32 revision = MAKE_COMPARABLE_REVISION( - readl(denali->flash_reg + REVISION)); - if (revision < REVISION_5_1) - denali->max_banks = 2 << (features & FEATURES__N_BANKS); - else - denali->max_banks = 1 << (features & FEATURES__N_BANKS); + uint32_t features = ioread32(denali->flash_reg + FEATURES); + + denali->max_banks = 1 << (features & FEATURES__N_BANKS); + + /* the encoding changed from rev 5.0 to 5.1 */ + if (denali->revision < 0x0501) + denali->max_banks <<= 1; } static void detect_partition_feature(struct denali_nand_info *denali) @@ -1154,6 +1150,13 @@ static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col, static void denali_hw_init(struct denali_nand_info *denali) { /* + * The REVISION register may not be reliable. Platforms are allowed to + * override it. + */ + if (!denali->revision) + denali->revision = swab16(ioread32(denali->flash_reg + REVISION)); + + /* * tell driver how many bit controller will skip before writing * ECC code in OOB. This is normally used for bad block marker */ diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h index 694bce53a9..08db48843d 100644 --- a/drivers/mtd/nand/denali.h +++ b/drivers/mtd/nand/denali.h @@ -166,8 +166,6 @@ #define REVISION 0x370 #define REVISION__VALUE 0xffff -#define MAKE_COMPARABLE_REVISION(x) swab16((x) & REVISION__VALUE) -#define REVISION_5_1 0x00000501 #define ONFI_DEVICE_FEATURES 0x380 #define ONFI_DEVICE_FEATURES__VALUE 0x003f @@ -462,8 +460,13 @@ struct denali_nand_info { uint32_t blksperchip; uint32_t bbtskipbytes; uint32_t max_banks; + unsigned int revision; + unsigned int caps; }; +#define DENALI_CAP_HW_ECC_FIXUP BIT(0) +#define DENALI_CAP_DMA_64BIT BIT(1) + int denali_init(struct denali_nand_info *denali); #endif /* __DENALI_H__ */ diff --git a/drivers/mtd/nand/denali_dt.c b/drivers/mtd/nand/denali_dt.c index 0a6155c748..4afd679a04 100644 --- a/drivers/mtd/nand/denali_dt.c +++ b/drivers/mtd/nand/denali_dt.c @@ -12,15 +12,38 @@ #include "denali.h" +struct denali_dt_data { + unsigned int revision; + unsigned int caps; +}; + +static const struct denali_dt_data denali_socfpga_data = { + .caps = DENALI_CAP_HW_ECC_FIXUP, +}; + +static const struct denali_dt_data denali_uniphier_v5a_data = { + .caps = DENALI_CAP_HW_ECC_FIXUP | + DENALI_CAP_DMA_64BIT, +}; + +static const struct denali_dt_data denali_uniphier_v5b_data = { + .revision = 0x0501, + .caps = DENALI_CAP_HW_ECC_FIXUP | + DENALI_CAP_DMA_64BIT, +}; + static const struct udevice_id denali_nand_dt_ids[] = { { .compatible = "altr,socfpga-denali-nand", + .data = (unsigned long)&denali_socfpga_data, }, { .compatible = "socionext,uniphier-denali-nand-v5a", + .data = (unsigned long)&denali_uniphier_v5a_data, }, { .compatible = "socionext,uniphier-denali-nand-v5b", + .data = (unsigned long)&denali_uniphier_v5b_data, }, { /* sentinel */ } }; @@ -28,9 +51,16 @@ static const struct udevice_id denali_nand_dt_ids[] = { static int denali_dt_probe(struct udevice *dev) { struct denali_nand_info *denali = dev_get_priv(dev); + const struct denali_dt_data *data; struct resource res; int ret; + data = (void *)dev_get_driver_data(dev); + if (data) { + denali->revision = data->revision; + denali->caps = data->caps; + } + ret = dev_read_resource_byname(dev, "denali_reg", &res); if (ret) return ret; diff --git a/drivers/mtd/spi/spi_flash_ids.c b/drivers/mtd/spi/spi_flash_ids.c index c4ccf48af4..13f64e773f 100644 --- a/drivers/mtd/spi/spi_flash_ids.c +++ b/drivers/mtd/spi/spi_flash_ids.c @@ -83,6 +83,7 @@ const struct spi_flash_info spi_flash_ids[] = { {"mx25l51235f", INFO(0xc2201a, 0x0, 64 * 1024, 1024, RD_FULL | WR_QPP) }, {"mx25u6435f", INFO(0xc22537, 0x0, 64 * 1024, 128, RD_FULL | WR_QPP) }, {"mx25l12855e", INFO(0xc22618, 0x0, 64 * 1024, 256, RD_FULL | WR_QPP) }, + {"mx25u1635e", INFO(0xc22535, 0x0, 64 * 1024, 32, SECT_4K) }, {"mx66u51235f", INFO(0xc2253a, 0x0, 64 * 1024, 1024, RD_FULL | WR_QPP) }, {"mx66l1g45g", INFO(0xc2201b, 0x0, 64 * 1024, 2048, RD_FULL | WR_QPP) }, #endif @@ -91,7 +92,7 @@ const struct spi_flash_info spi_flash_ids[] = { {"s25fl016a", INFO(0x010214, 0x0, 64 * 1024, 32, 0) }, {"s25fl032a", INFO(0x010215, 0x0, 64 * 1024, 64, 0) }, {"s25fl064a", INFO(0x010216, 0x0, 64 * 1024, 128, 0) }, - {"s25fl116k", INFO(0x014015, 0x0, 64 * 1024, 128, 0) }, + {"s25fl116k", INFO(0x014015, 0x0, 64 * 1024, 32, 0) }, {"s25fl164k", INFO(0x014017, 0x0140, 64 * 1024, 128, 0) }, {"s25fl128p_256k", INFO(0x012018, 0x0300, 256 * 1024, 64, RD_FULL | WR_QPP) }, {"s25fl128p_64k", INFO(0x012018, 0x0301, 64 * 1024, 256, RD_FULL | WR_QPP) }, @@ -100,8 +101,8 @@ const struct spi_flash_info spi_flash_ids[] = { {"s25fl128s_256k", INFO(0x012018, 0x4d00, 256 * 1024, 64, RD_FULL | WR_QPP) }, {"s25fl128s_64k", INFO(0x012018, 0x4d01, 64 * 1024, 256, RD_FULL | WR_QPP) }, {"s25fl256s_256k", INFO(0x010219, 0x4d00, 256 * 1024, 128, RD_FULL | WR_QPP) }, - {"s25fl256s_64k", INFO(0x010219, 0x4d01, 64 * 1024, 512, RD_FULL | WR_QPP) }, {"s25fs256s_64k", INFO6(0x010219, 0x4d0181, 64 * 1024, 512, RD_FULL | WR_QPP | SECT_4K) }, + {"s25fl256s_64k", INFO(0x010219, 0x4d01, 64 * 1024, 512, RD_FULL | WR_QPP) }, {"s25fs512s", INFO6(0x010220, 0x4d0081, 128 * 1024, 512, RD_FULL | WR_QPP | SECT_4K) }, {"s25fl512s_256k", INFO(0x010220, 0x4d00, 256 * 1024, 256, RD_FULL | WR_QPP) }, {"s25fl512s_64k", INFO(0x010220, 0x4d01, 64 * 1024, 1024, RD_FULL | WR_QPP) }, @@ -134,6 +135,7 @@ const struct spi_flash_info spi_flash_ids[] = { {"n25q1024a", INFO(0x20bb21, 0x0, 64 * 1024, 2048, RD_FULL | WR_QPP | E_FSR | SECT_4K) }, {"mt25qu02g", INFO(0x20bb22, 0x0, 64 * 1024, 4096, RD_FULL | WR_QPP | E_FSR | SECT_4K) }, {"mt25ql02g", INFO(0x20ba22, 0x0, 64 * 1024, 4096, RD_FULL | WR_QPP | E_FSR | SECT_4K) }, + {"mt35xu512g", INFO6(0x2c5b1a, 0x104100, 128 * 1024, 512, E_FSR | SECT_4K) }, #endif #ifdef CONFIG_SPI_FLASH_SST /* SST */ {"sst25vf040b", INFO(0xbf258d, 0x0, 64 * 1024, 8, SECT_4K | SST_WR) }, diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 5ceea44c60..d67927cd3b 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -159,6 +159,14 @@ config FTMAC100 help This MAC is present in Andestech SoCs. +config MVNETA + bool "Marvell Armada 385 network interface support" + depends on ARMADA_XP || ARMADA_38X + select PHYLIB + help + This driver supports the network interface units in the + Marvell ARMADA XP and 38X SoCs + config MVPP2 bool "Marvell Armada 375/7K/8K network interface support" depends on ARMADA_375 || ARMADA_8K diff --git a/drivers/net/designware.c b/drivers/net/designware.c index 521e4dde41..036d231071 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -737,16 +737,14 @@ int designware_eth_ofdata_to_platdata(struct udevice *dev) #endif struct eth_pdata *pdata = &dw_pdata->eth_pdata; const char *phy_mode; - const fdt32_t *cell; #ifdef CONFIG_DM_GPIO int reset_flags = GPIOD_IS_OUT; #endif int ret = 0; - pdata->iobase = devfdt_get_addr(dev); + pdata->iobase = dev_read_addr(dev); pdata->phy_interface = -1; - phy_mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "phy-mode", - NULL); + phy_mode = dev_read_string(dev, "phy-mode"); if (phy_mode) pdata->phy_interface = phy_get_interface_by_name(phy_mode); if (pdata->phy_interface == -1) { @@ -754,10 +752,7 @@ int designware_eth_ofdata_to_platdata(struct udevice *dev) return -EINVAL; } - pdata->max_speed = 0; - cell = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "max-speed", NULL); - if (cell) - pdata->max_speed = fdt32_to_cpu(*cell); + pdata->max_speed = dev_read_u32_default(dev, "max-speed", 0); #ifdef CONFIG_DM_GPIO if (dev_read_bool(dev, "snps,reset-active-low")) diff --git a/drivers/net/ftmac100.c b/drivers/net/ftmac100.c index f231e6b33b..e64bf3d651 100644 --- a/drivers/net/ftmac100.c +++ b/drivers/net/ftmac100.c @@ -40,7 +40,12 @@ static void ftmac100_reset(struct ftmac100_data *priv) writel (FTMAC100_MACCR_SW_RST, &ftmac100->maccr); while (readl (&ftmac100->maccr) & FTMAC100_MACCR_SW_RST) - ; + mdelay(1); + /* + * When soft reset complete, write mac address immediately maybe fail somehow + * Wait for a while can avoid this problem + */ + mdelay(1); } /* @@ -79,7 +84,6 @@ static int _ftmac100_init(struct ftmac100_data *priv, unsigned char enetaddr[6]) struct ftmac100_rxdes *rxdes = priv->rxdes; unsigned int maccr; int i; - debug ("%s()\n", __func__); ftmac100_reset(priv); @@ -156,7 +160,6 @@ static int __ftmac100_recv(struct ftmac100_data *priv) unsigned short rxlen; curr_des = &priv->rxdes[priv->rx_index]; - if (curr_des->rxdes0 & FTMAC100_RXDES0_RXDMA_OWN) return 0; @@ -169,7 +172,7 @@ static int __ftmac100_recv(struct ftmac100_data *priv) } rxlen = FTMAC100_RXDES0_RFL (curr_des->rxdes0); - + invalidate_dcache_range(curr_des->rxdes2,curr_des->rxdes2+rxlen); debug ("%s(): RX buffer %d, %x received\n", __func__, priv->rx_index, rxlen); @@ -196,6 +199,7 @@ static int _ftmac100_send(struct ftmac100_data *priv, void *packet, int length) /* initiate a transmit sequence */ + flush_dcache_range((u32)packet,(u32)packet+length); curr_des->txdes2 = (unsigned int)packet; /* TXBUF_BADR */ curr_des->txdes1 &= FTMAC100_TXDES1_EDOTR; diff --git a/drivers/net/phy/micrel_ksz90x1.c b/drivers/net/phy/micrel_ksz90x1.c index 0bb99e6bc6..b350a61aa6 100644 --- a/drivers/net/phy/micrel_ksz90x1.c +++ b/drivers/net/phy/micrel_ksz90x1.c @@ -9,11 +9,11 @@ * (C) Copyright 2017 Adaptrum, Inc. * Written by Alexandru Gagniuc <alex.g@adaptrum.com> for Adaptrum, Inc. */ + #include <config.h> #include <common.h> #include <dm.h> #include <errno.h> -#include <fdtdec.h> #include <micrel.h> #include <phy.h> @@ -120,8 +120,7 @@ static int ksz90x1_of_config_group(struct phy_device *phydev, return -EOPNOTSUPP; for (i = 0; i < ofcfg->grpsz; i++) { - val[i] = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev), - ofcfg->grp[i].name, -1); + val[i] = dev_read_u32_default(dev, ofcfg->grp[i].name, ~0); offset = ofcfg->grp[i].off; if (val[i] == -1) { /* Default register value for KSZ9021 */ diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index e2a1c0a409..8af2470268 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -35,7 +35,6 @@ config PCI_PNP config PCIE_DW_MVEBU bool "Enable Armada-8K PCIe driver (DesignWare core)" - default n depends on DM_PCI depends on ARMADA_8K help diff --git a/drivers/pci/pci_tegra.c b/drivers/pci/pci_tegra.c index cb5cf8b043..7d920d423d 100644 --- a/drivers/pci/pci_tegra.c +++ b/drivers/pci/pci_tegra.c @@ -218,8 +218,6 @@ struct tegra_pcie_soc { }; struct tegra_pcie { - struct pci_controller hose; - struct resource pads; struct resource afi; struct resource cs; diff --git a/drivers/pci/pcie_layerscape.h b/drivers/pci/pcie_layerscape.h index 782e3ab7ad..3a6cecb07d 100644 --- a/drivers/pci/pcie_layerscape.h +++ b/drivers/pci/pcie_layerscape.h @@ -145,7 +145,6 @@ struct ls_pcie { bool big_endian; bool enabled; int next_lut_index; - struct pci_controller hose; }; extern struct list_head ls_pcie_list; diff --git a/drivers/pci/pcie_layerscape_fixup.c b/drivers/pci/pcie_layerscape_fixup.c index 9e6c2f5dfc..3dae20103d 100644 --- a/drivers/pci/pcie_layerscape_fixup.c +++ b/drivers/pci/pcie_layerscape_fixup.c @@ -130,19 +130,28 @@ static void fdt_pcie_set_iommu_map_entry(void *blob, struct ls_pcie *pcie, u32 iommu_map[4]; int nodeoffset; int lenp; + uint svr; + char *compat = NULL; /* find pci controller node */ nodeoffset = fdt_node_offset_by_compat_reg(blob, "fsl,ls-pcie", pcie->dbi_res.start); if (nodeoffset < 0) { #ifdef CONFIG_FSL_PCIE_COMPAT /* Compatible with older version of dts node */ - nodeoffset = fdt_node_offset_by_compat_reg(blob, - CONFIG_FSL_PCIE_COMPAT, pcie->dbi_res.start); + svr = (get_svr() >> SVR_VAR_PER_SHIFT) & 0xFFFFFE; + if (svr == SVR_LS2088A || svr == SVR_LS2084A || + svr == SVR_LS2048A || svr == SVR_LS2044A || + svr == SVR_LS2081A || svr == SVR_LS2041A) + compat = "fsl,ls2088a-pcie"; + else + compat = CONFIG_FSL_PCIE_COMPAT; + + if (compat) + nodeoffset = fdt_node_offset_by_compat_reg(blob, + compat, pcie->dbi_res.start); +#endif if (nodeoffset < 0) return; -#else - return; -#endif } /* get phandle to iommu controller */ diff --git a/drivers/pci/pcie_xilinx.c b/drivers/pci/pcie_xilinx.c index 08e2e93445..4ba32df516 100644 --- a/drivers/pci/pcie_xilinx.c +++ b/drivers/pci/pcie_xilinx.c @@ -14,11 +14,9 @@ /** * struct xilinx_pcie - Xilinx PCIe controller state - * @hose: The parent classes PCI controller state * @cfg_base: The base address of memory mapped configuration space */ struct xilinx_pcie { - struct pci_controller hose; void *cfg_base; }; @@ -87,7 +85,7 @@ static int pcie_xilinx_config_address(struct xilinx_pcie *pcie, pci_dev_t bdf, /** * pcie_xilinx_read_config() - Read from configuration space - * @pcie: Pointer to the PCI controller state + * @bus: Pointer to the PCI bus * @bdf: Identifies the PCIe device to access * @offset: The offset into the device's configuration space * @valuep: A pointer at which to store the read value @@ -130,7 +128,7 @@ static int pcie_xilinx_read_config(struct udevice *bus, pci_dev_t bdf, /** * pcie_xilinx_write_config() - Write to configuration space - * @pcie: Pointer to the PCI controller state + * @bus: Pointer to the PCI bus * @bdf: Identifies the PCIe device to access * @offset: The offset into the device's configuration space * @value: The value to write diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 98f2a1b047..3b9a09ce18 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -77,4 +77,12 @@ config SPL_PIPE3_PHY This PHY is found on omap devices supporting SATA such as dra7, am57x and omap5 +config STI_USB_PHY + bool "STMicroelectronics USB2 picoPHY driver for STiH407 family" + depends on PHY && ARCH_STI + help + This is the generic phy driver for the picoPHY ports + used by USB2 and USB3 Host controllers available on + STiH407 SoC families. + endmenu diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index ab56c46bb4..668040b0bb 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -9,3 +9,4 @@ obj-$(CONFIG_$(SPL_)PHY) += phy-uclass.o obj-$(CONFIG_$(SPL_)NOP_PHY) += nop-phy.o obj-$(CONFIG_PHY_SANDBOX) += sandbox-phy.o obj-$(CONFIG_$(SPL_)PIPE3_PHY) += ti-pipe3-phy.o +obj-$(CONFIG_STI_USB_PHY) += sti_usb_phy.o diff --git a/drivers/phy/sti_usb_phy.c b/drivers/phy/sti_usb_phy.c new file mode 100644 index 0000000000..0e0b1c02d2 --- /dev/null +++ b/drivers/phy/sti_usb_phy.c @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2017 + * Patrice Chotard <patrice.chotard@st.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <bitfield.h> +#include <dm.h> +#include <errno.h> +#include <fdtdec.h> +#include <generic-phy.h> +#include <libfdt.h> +#include <regmap.h> +#include <reset-uclass.h> +#include <syscon.h> +#include <wait_bit.h> + +#include <linux/bitops.h> +#include <linux/compat.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* Default PHY_SEL and REFCLKSEL configuration */ +#define STIH407_USB_PICOPHY_CTRL_PORT_CONF 0x6 + +/* ports parameters overriding */ +#define STIH407_USB_PICOPHY_PARAM_DEF 0x39a4dc + +#define PHYPARAM_REG 1 +#define PHYCTRL_REG 2 +#define PHYPARAM_NB 3 + +struct sti_usb_phy { + struct regmap *regmap; + struct reset_ctl global_ctl; + struct reset_ctl port_ctl; + int param; + int ctrl; +}; + +static int sti_usb_phy_deassert(struct sti_usb_phy *phy) +{ + int ret; + + ret = reset_deassert(&phy->global_ctl); + if (ret < 0) { + error("PHY global deassert failed: %d", ret); + return ret; + } + + ret = reset_deassert(&phy->port_ctl); + if (ret < 0) + error("PHY port deassert failed: %d", ret); + + return ret; +} + +static int sti_usb_phy_init(struct phy *usb_phy) +{ + struct udevice *dev = usb_phy->dev; + struct sti_usb_phy *phy = dev_get_priv(dev); + void __iomem *reg; + + /* set ctrl picophy value */ + reg = (void __iomem *)phy->regmap->base + phy->ctrl; + /* CTRL_PORT mask is 0x1f */ + clrsetbits_le32(reg, 0x1f, STIH407_USB_PICOPHY_CTRL_PORT_CONF); + + /* set ports parameters overriding */ + reg = (void __iomem *)phy->regmap->base + phy->param; + /* PARAM_DEF mask is 0xffffffff */ + clrsetbits_le32(reg, 0xffffffff, STIH407_USB_PICOPHY_PARAM_DEF); + + return sti_usb_phy_deassert(phy); +} + +static int sti_usb_phy_exit(struct phy *usb_phy) +{ + struct udevice *dev = usb_phy->dev; + struct sti_usb_phy *phy = dev_get_priv(dev); + int ret; + + ret = reset_assert(&phy->port_ctl); + if (ret < 0) { + error("PHY port assert failed: %d", ret); + return ret; + } + + ret = reset_assert(&phy->global_ctl); + if (ret < 0) + error("PHY global assert failed: %d", ret); + + return ret; +} + +struct phy_ops sti_usb_phy_ops = { + .init = sti_usb_phy_init, + .exit = sti_usb_phy_exit, +}; + +int sti_usb_phy_probe(struct udevice *dev) +{ + struct sti_usb_phy *priv = dev_get_priv(dev); + struct udevice *syscon; + struct ofnode_phandle_args syscfg_phandle; + u32 cells[PHYPARAM_NB]; + int ret, count; + + /* get corresponding syscon phandle */ + ret = dev_read_phandle_with_args(dev, "st,syscfg", NULL, 0, 0, + &syscfg_phandle); + + if (ret < 0) { + error("Can't get syscfg phandle: %d\n", ret); + return ret; + } + + ret = uclass_get_device_by_ofnode(UCLASS_SYSCON, syscfg_phandle.node, + &syscon); + if (ret) { + error("unable to find syscon device (%d)\n", ret); + return ret; + } + + priv->regmap = syscon_get_regmap(syscon); + if (!priv->regmap) { + error("unable to find regmap\n"); + return -ENODEV; + } + + /* get phy param offset */ + count = fdtdec_get_int_array_count(gd->fdt_blob, dev_of_offset(dev), + "st,syscfg", cells, + ARRAY_SIZE(cells)); + + if (count < 0) { + error("Bad PHY st,syscfg property %d\n", count); + return -EINVAL; + } + + if (count > PHYPARAM_NB) { + error("Unsupported PHY param count %d\n", count); + return -EINVAL; + } + + priv->param = cells[PHYPARAM_REG]; + priv->ctrl = cells[PHYCTRL_REG]; + + /* get global reset control */ + ret = reset_get_by_name(dev, "global", &priv->global_ctl); + if (ret) { + error("can't get global reset for %s (%d)", dev->name, ret); + return ret; + } + + /* get port reset control */ + ret = reset_get_by_name(dev, "port", &priv->port_ctl); + if (ret) { + error("can't get port reset for %s (%d)", dev->name, ret); + return ret; + } + + return 0; +} + +static const struct udevice_id sti_usb_phy_ids[] = { + { .compatible = "st,stih407-usb2-phy" }, + { } +}; + +U_BOOT_DRIVER(sti_usb_phy) = { + .name = "sti_usb_phy", + .id = UCLASS_PHY, + .of_match = sti_usb_phy_ids, + .probe = sti_usb_phy_probe, + .ops = &sti_usb_phy_ops, + .priv_auto_alloc_size = sizeof(struct sti_usb_phy), +}; diff --git a/drivers/pinctrl/pinctrl_stm32.c b/drivers/pinctrl/pinctrl_stm32.c index fb2593c690..bf2a86c636 100644 --- a/drivers/pinctrl/pinctrl_stm32.c +++ b/drivers/pinctrl/pinctrl_stm32.c @@ -183,6 +183,7 @@ static struct pinctrl_ops stm32_pinctrl_ops = { static const struct udevice_id stm32_pinctrl_ids[] = { { .compatible = "st,stm32f746-pinctrl" }, + { .compatible = "st,stm32h743-pinctrl" }, { } }; diff --git a/drivers/pinctrl/rockchip/pinctrl_rk3368.c b/drivers/pinctrl/rockchip/pinctrl_rk3368.c index 81ce2e31a7..b1f5704164 100644 --- a/drivers/pinctrl/rockchip/pinctrl_rk3368.c +++ b/drivers/pinctrl/rockchip/pinctrl_rk3368.c @@ -632,8 +632,7 @@ static int rk3368_pinctrl_get_periph_id(struct udevice *dev, u32 cell[3]; int ret; - ret = fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(periph), - "interrupts", cell, ARRAY_SIZE(cell)); + ret = dev_read_u32_array(periph, "interrupts", cell, ARRAY_SIZE(cell)); if (ret < 0) return -EINVAL; diff --git a/drivers/power/pmic/rk8xx.c b/drivers/power/pmic/rk8xx.c index eb3ec0f601..735046dc43 100644 --- a/drivers/power/pmic/rk8xx.c +++ b/drivers/power/pmic/rk8xx.c @@ -8,8 +8,6 @@ #include <common.h> #include <dm.h> #include <errno.h> -#include <fdtdec.h> -#include <libfdt.h> #include <power/rk8xx_pmic.h> #include <power/pmic.h> diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig index c82a936e8a..2cfade1cb2 100644 --- a/drivers/power/regulator/Kconfig +++ b/drivers/power/regulator/Kconfig @@ -151,6 +151,19 @@ config DM_REGULATOR_PALMAS features for REGULATOR PALMAS and the family of PALMAS PMICs. The driver implements get/set api for: value and enable. +config DM_REGULATOR_PBIAS + bool "Enable driver for PBIAS regulator" + depends on DM_REGULATOR + select REGMAP + select SYSCON + ---help--- + This enables implementation of driver-model regulator uclass + features for pseudo-regulator PBIAS found in the OMAP SOCs. + This pseudo-regulator is used to provide a BIAS voltage to MMC1 + signal pads and must be configured properly during a voltage switch. + Voltage switching is required by some operating modes of SDcards and + eMMC. + config DM_REGULATOR_LP873X bool "Enable driver for LP873X PMIC regulators" depends on PMIC_LP873X diff --git a/drivers/power/regulator/Makefile b/drivers/power/regulator/Makefile index 18fb870e43..6c149a9263 100644 --- a/drivers/power/regulator/Makefile +++ b/drivers/power/regulator/Makefile @@ -18,5 +18,6 @@ obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o obj-$(CONFIG_DM_REGULATOR_SANDBOX) += sandbox.o obj-$(CONFIG_REGULATOR_TPS65090) += tps65090_regulator.o obj-$(CONFIG_$(SPL_)DM_REGULATOR_PALMAS) += palmas_regulator.o +obj-$(CONFIG_$(SPL_)DM_REGULATOR_PBIAS) += pbias_regulator.o obj-$(CONFIG_$(SPL_)DM_REGULATOR_LP873X) += lp873x_regulator.o obj-$(CONFIG_$(SPL_)DM_REGULATOR_LP87565) += lp87565_regulator.o diff --git a/drivers/power/regulator/pbias_regulator.c b/drivers/power/regulator/pbias_regulator.c new file mode 100644 index 0000000000..914500b729 --- /dev/null +++ b/drivers/power/regulator/pbias_regulator.c @@ -0,0 +1,301 @@ +/* + * (C) Copyright 2016 Texas Instruments Incorporated, <www.ti.com> + * Jean-Jacques Hiblot <jjhiblot@ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <errno.h> +#include <dm.h> +#include <power/pmic.h> +#include <power/regulator.h> +#include <regmap.h> +#include <syscon.h> +#include <linux/bitops.h> +#include <linux/ioport.h> +#include <dm/read.h> + +DECLARE_GLOBAL_DATA_PTR; + +struct pbias_reg_info { + u32 enable; + u32 enable_mask; + u32 disable_val; + u32 vmode; + unsigned int enable_time; + char *name; +}; + +struct pbias_priv { + struct regmap *regmap; + int offset; +}; + +static const struct pmic_child_info pmic_children_info[] = { + { .prefix = "pbias", .driver = "pbias_regulator"}, + { }, +}; + +static int pbias_write(struct udevice *dev, uint reg, const uint8_t *buff, + int len) +{ + struct pbias_priv *priv = dev_get_priv(dev); + u32 val = *(u32 *)buff; + + if (len != 4) + return -EINVAL; + + return regmap_write(priv->regmap, priv->offset, val); +} + +static int pbias_read(struct udevice *dev, uint reg, uint8_t *buff, int len) +{ + struct pbias_priv *priv = dev_get_priv(dev); + + if (len != 4) + return -EINVAL; + + return regmap_read(priv->regmap, priv->offset, (u32 *)buff); +} + +static int pbias_ofdata_to_platdata(struct udevice *dev) +{ + struct pbias_priv *priv = dev_get_priv(dev); + struct udevice *syscon; + struct regmap *regmap; + struct resource res; + int err; + + err = uclass_get_device_by_phandle(UCLASS_SYSCON, dev, + "syscon", &syscon); + if (err) { + error("%s: unable to find syscon device (%d)\n", __func__, + err); + return err; + } + + regmap = syscon_get_regmap(syscon); + if (IS_ERR(regmap)) { + error("%s: unable to find regmap (%ld)\n", __func__, + PTR_ERR(regmap)); + return PTR_ERR(regmap); + } + priv->regmap = regmap; + + err = dev_read_resource(dev, 0, &res); + if (err) { + error("%s: unable to find offset (%d)\n", __func__, err); + return err; + } + priv->offset = res.start; + + return 0; +} + +static int pbias_bind(struct udevice *dev) +{ + int children; + + children = pmic_bind_children(dev, dev->node, pmic_children_info); + if (!children) + debug("%s: %s - no child found\n", __func__, dev->name); + + return 0; +} + +static struct dm_pmic_ops pbias_ops = { + .read = pbias_read, + .write = pbias_write, +}; + +static const struct udevice_id pbias_ids[] = { + { .compatible = "ti,pbias-dra7" }, + { } +}; + +U_BOOT_DRIVER(pbias_pmic) = { + .name = "pbias_pmic", + .id = UCLASS_PMIC, + .of_match = pbias_ids, + .bind = pbias_bind, + .ops = &pbias_ops, + .ofdata_to_platdata = pbias_ofdata_to_platdata, + .priv_auto_alloc_size = sizeof(struct pbias_priv), +}; + +static const struct pbias_reg_info pbias_mmc_omap2430 = { + .enable = BIT(1), + .enable_mask = BIT(1), + .vmode = BIT(0), + .disable_val = 0, + .enable_time = 100, + .name = "pbias_mmc_omap2430" +}; + +static const struct pbias_reg_info pbias_sim_omap3 = { + .enable = BIT(9), + .enable_mask = BIT(9), + .vmode = BIT(8), + .enable_time = 100, + .name = "pbias_sim_omap3" +}; + +static const struct pbias_reg_info pbias_mmc_omap4 = { + .enable = BIT(26) | BIT(22), + .enable_mask = BIT(26) | BIT(25) | BIT(22), + .disable_val = BIT(25), + .vmode = BIT(21), + .enable_time = 100, + .name = "pbias_mmc_omap4" +}; + +static const struct pbias_reg_info pbias_mmc_omap5 = { + .enable = BIT(27) | BIT(26), + .enable_mask = BIT(27) | BIT(25) | BIT(26), + .disable_val = BIT(25), + .vmode = BIT(21), + .enable_time = 100, + .name = "pbias_mmc_omap5" +}; + +static const struct pbias_reg_info *pbias_reg_infos[] = { + &pbias_mmc_omap5, + &pbias_mmc_omap4, + &pbias_sim_omap3, + &pbias_mmc_omap2430, + NULL +}; + +static int pbias_regulator_probe(struct udevice *dev) +{ + const struct pbias_reg_info **p = pbias_reg_infos; + struct dm_regulator_uclass_platdata *uc_pdata; + + uc_pdata = dev_get_uclass_platdata(dev); + + while (*p) { + int rc; + + rc = dev_read_stringlist_search(dev, "regulator-name", + (*p)->name); + if (rc >= 0) { + debug("found regulator %s\n", (*p)->name); + break; + } else if (rc != -ENODATA) { + return rc; + } + p++; + } + if (!*p) { + int i = 0; + const char *s; + + debug("regulator "); + while (dev_read_string_index(dev, "regulator-name", i++, &s) >= 0) + debug("%s'%s' ", (i > 1) ? ", " : "", s); + debug("%s not supported\n", (i > 2) ? "are" : "is"); + return -EINVAL; + } + + uc_pdata->type = REGULATOR_TYPE_OTHER; + dev->priv = (void *)*p; + + return 0; +} + +static int pbias_regulator_get_value(struct udevice *dev) +{ + const struct pbias_reg_info *p = dev_get_priv(dev); + int rc; + u32 reg; + + rc = pmic_read(dev->parent, 0, (uint8_t *)®, sizeof(reg)); + if (rc) + return rc; + + debug("%s voltage id %s\n", p->name, + (reg & p->vmode) ? "3.0v" : "1.8v"); + return (reg & p->vmode) ? 3000000 : 1800000; +} + +static int pbias_regulator_set_value(struct udevice *dev, int uV) +{ + const struct pbias_reg_info *p = dev_get_priv(dev); + int rc; + u32 reg; + + debug("Setting %s voltage to %s\n", p->name, + (reg & p->vmode) ? "3.0v" : "1.8v"); + + rc = pmic_read(dev->parent, 0, (uint8_t *)®, sizeof(reg)); + if (rc) + return rc; + + if (uV == 3000000) + reg |= p->vmode; + else if (uV == 1800000) + reg &= ~p->vmode; + else + return -EINVAL; + + return pmic_write(dev->parent, 0, (uint8_t *)®, sizeof(reg)); +} + +static int pbias_regulator_get_enable(struct udevice *dev) +{ + const struct pbias_reg_info *p = dev_get_priv(dev); + int rc; + u32 reg; + + rc = pmic_read(dev->parent, 0, (uint8_t *)®, sizeof(reg)); + if (rc) + return rc; + + debug("%s id %s\n", p->name, + (reg & p->enable_mask) == (p->disable_val) ? "on" : "off"); + + return (reg & p->enable_mask) == (p->disable_val); +} + +static int pbias_regulator_set_enable(struct udevice *dev, bool enable) +{ + const struct pbias_reg_info *p = dev_get_priv(dev); + int rc; + u32 reg; + + debug("Turning %s %s\n", enable ? "on" : "off", p->name); + + rc = pmic_read(dev->parent, 0, (uint8_t *)®, sizeof(reg)); + if (rc) + return rc; + + reg &= ~p->enable_mask; + if (enable) + reg |= p->enable; + else + reg |= p->disable_val; + + rc = pmic_write(dev->parent, 0, (uint8_t *)®, sizeof(reg)); + if (rc) + return rc; + + if (enable) + udelay(p->enable_time); + + return 0; +} + +static const struct dm_regulator_ops pbias_regulator_ops = { + .get_value = pbias_regulator_get_value, + .set_value = pbias_regulator_set_value, + .get_enable = pbias_regulator_get_enable, + .set_enable = pbias_regulator_set_enable, +}; + +U_BOOT_DRIVER(pbias_regulator) = { + .name = "pbias_regulator", + .id = UCLASS_REGULATOR, + .ops = &pbias_regulator_ops, + .probe = pbias_regulator_probe, +}; diff --git a/drivers/ram/rockchip/dmc-rk3368.c b/drivers/ram/rockchip/dmc-rk3368.c index ca7b1ff0c8..7577ff0363 100644 --- a/drivers/ram/rockchip/dmc-rk3368.c +++ b/drivers/ram/rockchip/dmc-rk3368.c @@ -893,18 +893,11 @@ static int conv_of_platdata(struct udevice *dev) { struct rk3368_sdram_params *plat = dev_get_platdata(dev); struct dtd_rockchip_rk3368_dmc *of_plat = &plat->of_plat; - int ret; plat->ddr_freq = of_plat->rockchip_ddr_frequency; plat->ddr_speed_bin = of_plat->rockchip_ddr_speed_bin; plat->memory_schedule = of_plat->rockchip_memory_schedule; - ret = regmap_init_mem_platdata(dev, of_plat->reg, - ARRAY_SIZE(of_plat->reg) / 2, - &plat->map); - if (ret) - return ret; - return 0; } #endif @@ -933,8 +926,8 @@ static int rk3368_dmc_probe(struct udevice *dev) debug("%s: pmugrf=%p\n", __func__, priv->pmugrf); #ifdef CONFIG_TPL_BUILD - pctl = regmap_get_range(plat->map, 0); - ddrphy = regmap_get_range(plat->map, 1); + pctl = (struct rk3368_ddr_pctl *)plat->of_plat.reg[0]; + ddrphy = (struct rk3368_ddrphy *)plat->of_plat.reg[2]; msch = syscon_get_first_range(ROCKCHIP_SYSCON_MSCH); grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index e6af7da8fe..ce46e2752c 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -28,6 +28,13 @@ config STI_RESET Say Y if you want to control reset signals provided by system config block. +config STM32_RESET + bool "Enable the STM32 reset" + depends on STM32 + help + Support for reset controllers on STMicroelectronics STM32 family SoCs. + This resset driver is compatible with STM32 F4/F7 and H7 SoCs. + config TEGRA_CAR_RESET bool "Enable Tegra CAR-based reset driver" depends on TEGRA_CAR diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index d5e06c2241..252cefeed5 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_DM_RESET) += reset-uclass.o obj-$(CONFIG_SANDBOX_MBOX) += sandbox-reset.o obj-$(CONFIG_SANDBOX_MBOX) += sandbox-reset-test.o obj-$(CONFIG_STI_RESET) += sti-reset.o +obj-$(CONFIG_STM32_RESET) += stm32-reset.o obj-$(CONFIG_TEGRA_CAR_RESET) += tegra-car-reset.o obj-$(CONFIG_TEGRA186_RESET) += tegra186-reset.o obj-$(CONFIG_RESET_BCM6345) += reset-bcm6345.o diff --git a/drivers/reset/stm32-reset.c b/drivers/reset/stm32-reset.c new file mode 100644 index 0000000000..9c627d879f --- /dev/null +++ b/drivers/reset/stm32-reset.c @@ -0,0 +1,80 @@ +/* + * Copyright (C) STMicroelectronics SA 2017 + * Author(s): Patrice CHOTARD, <patrice.chotard@st.com> for STMicroelectronics. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <reset-uclass.h> +#include <asm/io.h> + +DECLARE_GLOBAL_DATA_PTR; + +struct stm32_reset_priv { + fdt_addr_t base; +}; + +static int stm32_reset_request(struct reset_ctl *reset_ctl) +{ + return 0; +} + +static int stm32_reset_free(struct reset_ctl *reset_ctl) +{ + return 0; +} + +static int stm32_reset_assert(struct reset_ctl *reset_ctl) +{ + struct stm32_reset_priv *priv = dev_get_priv(reset_ctl->dev); + int bank = (reset_ctl->id / BITS_PER_LONG) * 4; + int offset = reset_ctl->id % BITS_PER_LONG; + debug("%s: reset id = %ld bank = %d offset = %d)\n", __func__, + reset_ctl->id, bank, offset); + + setbits_le32(priv->base + bank, BIT(offset)); + + return 0; +} + +static int stm32_reset_deassert(struct reset_ctl *reset_ctl) +{ + struct stm32_reset_priv *priv = dev_get_priv(reset_ctl->dev); + int bank = (reset_ctl->id / BITS_PER_LONG) * 4; + int offset = reset_ctl->id % BITS_PER_LONG; + debug("%s: reset id = %ld bank = %d offset = %d)\n", __func__, + reset_ctl->id, bank, offset); + + clrbits_le32(priv->base + bank, BIT(offset)); + + return 0; +} + +static const struct reset_ops stm32_reset_ops = { + .request = stm32_reset_request, + .free = stm32_reset_free, + .rst_assert = stm32_reset_assert, + .rst_deassert = stm32_reset_deassert, +}; + +static int stm32_reset_probe(struct udevice *dev) +{ + struct stm32_reset_priv *priv = dev_get_priv(dev); + + priv->base = devfdt_get_addr(dev); + if (priv->base == FDT_ADDR_T_NONE) + return -EINVAL; + + return 0; +} + +U_BOOT_DRIVER(stm32_rcc_reset) = { + .name = "stm32_rcc_reset", + .id = UCLASS_RESET, + .probe = stm32_reset_probe, + .priv_auto_alloc_size = sizeof(struct stm32_reset_priv), + .ops = &stm32_reset_ops, +}; diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 13b2550d3b..9bf2e26e9d 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -531,10 +531,11 @@ config STI_ASC_SERIAL config STM32X7_SERIAL bool "STMicroelectronics STM32 SoCs on-chip UART" - depends on DM_SERIAL && STM32F7 + depends on DM_SERIAL && (STM32F7 || STM32H7) help - If you have a machine based on a STM32 F7 you can enable its - onboard serial ports, say Y to this option. If unsure, say N. + If you have a machine based on a STM32 F7 or H7 SoC you can + enable its onboard serial ports, say Y to this option. + If unsure, say N. config MPC8XX_CONS bool "Console driver for MPC8XX" diff --git a/drivers/serial/serial_stm32x7.c b/drivers/serial/serial_stm32x7.c index bf118a78cf..2f4eafa885 100644 --- a/drivers/serial/serial_stm32x7.c +++ b/drivers/serial/serial_stm32x7.c @@ -112,6 +112,8 @@ static int stm32_serial_probe(struct udevice *dev) static const struct udevice_id stm32_serial_id[] = { {.compatible = "st,stm32f7-usart"}, {.compatible = "st,stm32f7-uart"}, + {.compatible = "st,stm32h7-usart"}, + {.compatible = "st,stm32h7-uart"}, {} }; diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 3c5582a950..88da9a4c8e 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -210,6 +210,13 @@ config FSL_QSPI used to access the SPI NOR flash on platforms embedding this Freescale IP core. +config NDS_AE3XX_SPI + bool "Andestech AE3XX SPI driver" + help + Enable the Andestech AE3XX SPI driver. This driver can be + used to access the SPI flash on platforms embedding this + Andestech IP core. + config TI_QSPI bool "TI QSPI driver" help diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 9f8b86de76..cd7c7556a7 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -35,6 +35,7 @@ obj-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o obj-$(CONFIG_MVEBU_A3700_SPI) += mvebu_a3700_spi.o obj-$(CONFIG_MXC_SPI) += mxc_spi.o obj-$(CONFIG_MXS_SPI) += mxs_spi.o +obj-$(CONFIG_NDS_AE3XX_SPI) += nds_ae3xx_spi.o obj-$(CONFIG_OMAP3_SPI) += omap3_spi.o obj-$(CONFIG_PIC32_SPI) += pic32_spi.o obj-$(CONFIG_ROCKCHIP_SPI) += rk_spi.o diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c index 291ef9576a..eda252d0b3 100644 --- a/drivers/spi/davinci_spi.c +++ b/drivers/spi/davinci_spi.c @@ -563,6 +563,7 @@ static const struct dm_spi_ops davinci_spi_ops = { static const struct udevice_id davinci_spi_ids[] = { { .compatible = "ti,keystone-spi" }, { .compatible = "ti,dm6441-spi" }, + { .compatible = "ti,da830-spi" }, { } }; diff --git a/drivers/spi/fsl_qspi.c b/drivers/spi/fsl_qspi.c index 1dfa89afc9..0f3f7d97f0 100644 --- a/drivers/spi/fsl_qspi.c +++ b/drivers/spi/fsl_qspi.c @@ -14,6 +14,7 @@ #include <dm.h> #include <errno.h> #include <watchdog.h> +#include <wait_bit.h> #include "fsl_qspi.h" DECLARE_GLOBAL_DATA_PTR; @@ -663,22 +664,20 @@ static void qspi_op_write(struct fsl_qspi_priv *priv, u8 *txbuf, u32 len) tx_size = (len > TX_BUFFER_SIZE) ? TX_BUFFER_SIZE : len; - size = tx_size / 4; - for (i = 0; i < size; i++) { + size = tx_size / 16; + /* + * There must be atleast 128bit data + * available in TX FIFO for any pop operation + */ + if (tx_size % 16) + size++; + for (i = 0; i < size * 4; i++) { memcpy(&data, txbuf, 4); data = qspi_endian_xchg(data); qspi_write32(priv->flags, ®s->tbdr, data); txbuf += 4; } - size = tx_size % 4; - if (size) { - data = 0; - memcpy(&data, txbuf, size); - data = qspi_endian_xchg(data); - qspi_write32(priv->flags, ®s->tbdr, data); - } - qspi_write32(priv->flags, ®s->ipcr, (seqid << QSPI_IPCR_SEQID_SHIFT) | tx_size); while (qspi_read32(priv->flags, ®s->sr) & QSPI_SR_BUSY_MASK) @@ -991,7 +990,7 @@ static int fsl_qspi_probe(struct udevice *bus) struct fsl_qspi_platdata *plat = dev_get_platdata(bus); struct fsl_qspi_priv *priv = dev_get_priv(bus); struct dm_spi_bus *dm_spi_bus; - int i; + int i, ret; dm_spi_bus = bus->uclass_priv; @@ -1011,6 +1010,18 @@ static int fsl_qspi_probe(struct udevice *bus) priv->flash_num = plat->flash_num; priv->num_chipselect = plat->num_chipselect; + /* make sure controller is not busy anywhere */ + ret = wait_for_bit(__func__, &priv->regs->sr, + QSPI_SR_BUSY_MASK | + QSPI_SR_AHB_ACC_MASK | + QSPI_SR_IP_ACC_MASK, + false, 100, false); + + if (ret) { + debug("ERROR : The controller is busy\n"); + return ret; + } + mcr_val = qspi_read32(priv->flags, &priv->regs->mcr); qspi_write32(priv->flags, &priv->regs->mcr, QSPI_MCR_RESERVED_MASK | QSPI_MCR_MDIS_MASK | @@ -1156,10 +1167,23 @@ static int fsl_qspi_claim_bus(struct udevice *dev) struct fsl_qspi_priv *priv; struct udevice *bus; struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev); + int ret; bus = dev->parent; priv = dev_get_priv(bus); + /* make sure controller is not busy anywhere */ + ret = wait_for_bit(__func__, &priv->regs->sr, + QSPI_SR_BUSY_MASK | + QSPI_SR_AHB_ACC_MASK | + QSPI_SR_IP_ACC_MASK, + false, 100, false); + + if (ret) { + debug("ERROR : The controller is busy\n"); + return ret; + } + priv->cur_amba_base = priv->amba_base[slave_plat->cs]; qspi_module_disable(priv, 0); diff --git a/drivers/spi/fsl_qspi.h b/drivers/spi/fsl_qspi.h index 6cb361018b..e468eb2529 100644 --- a/drivers/spi/fsl_qspi.h +++ b/drivers/spi/fsl_qspi.h @@ -105,6 +105,10 @@ struct fsl_qspi_regs { #define QSPI_RBCT_RXBRD_SHIFT 8 #define QSPI_RBCT_RXBRD_USEIPS (1 << QSPI_RBCT_RXBRD_SHIFT) +#define QSPI_SR_AHB_ACC_SHIFT 2 +#define QSPI_SR_AHB_ACC_MASK (1 << QSPI_SR_AHB_ACC_SHIFT) +#define QSPI_SR_IP_ACC_SHIFT 1 +#define QSPI_SR_IP_ACC_MASK (1 << QSPI_SR_IP_ACC_SHIFT) #define QSPI_SR_BUSY_SHIFT 0 #define QSPI_SR_BUSY_MASK (1 << QSPI_SR_BUSY_SHIFT) diff --git a/drivers/spi/mxc_spi.c b/drivers/spi/mxc_spi.c index e1562c36b7..41f0cfcd6b 100644 --- a/drivers/spi/mxc_spi.c +++ b/drivers/spi/mxc_spi.c @@ -5,6 +5,7 @@ */ #include <common.h> +#include <dm.h> #include <malloc.h> #include <spi.h> #include <linux/errno.h> @@ -14,6 +15,8 @@ #include <asm/arch/clock.h> #include <asm/mach-imx/spi.h> +DECLARE_GLOBAL_DATA_PTR; + #ifdef CONFIG_MX27 /* i.MX27 has a completely wrong register layout and register definitions in the * datasheet, the correct one is in the Freescale's Linux driver */ @@ -22,10 +25,6 @@ "See linux mxc_spi driver from Freescale for details." #endif -static unsigned long spi_bases[] = { - MXC_SPI_BASE_ADDRESSES -}; - __weak int board_spi_cs_gpio(unsigned bus, unsigned cs) { return -1; @@ -51,6 +50,7 @@ struct mxc_spi_slave { int ss_pol; unsigned int max_hz; unsigned int mode; + struct gpio_desc ss; }; static inline struct mxc_spi_slave *to_mxc_spi_slave(struct spi_slave *slave) @@ -58,19 +58,24 @@ static inline struct mxc_spi_slave *to_mxc_spi_slave(struct spi_slave *slave) return container_of(slave, struct mxc_spi_slave, slave); } -void spi_cs_activate(struct spi_slave *slave) +static void mxc_spi_cs_activate(struct mxc_spi_slave *mxcs) { - struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave); - if (mxcs->gpio > 0) - gpio_set_value(mxcs->gpio, mxcs->ss_pol); + if (CONFIG_IS_ENABLED(DM_SPI)) { + dm_gpio_set_value(&mxcs->ss, mxcs->ss_pol); + } else { + if (mxcs->gpio > 0) + gpio_set_value(mxcs->gpio, mxcs->ss_pol); + } } -void spi_cs_deactivate(struct spi_slave *slave) +static void mxc_spi_cs_deactivate(struct mxc_spi_slave *mxcs) { - struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave); - if (mxcs->gpio > 0) - gpio_set_value(mxcs->gpio, - !(mxcs->ss_pol)); + if (CONFIG_IS_ENABLED(DM_SPI)) { + dm_gpio_set_value(&mxcs->ss, !(mxcs->ss_pol)); + } else { + if (mxcs->gpio > 0) + gpio_set_value(mxcs->gpio, !(mxcs->ss_pol)); + } } u32 get_cspi_div(u32 div) @@ -211,10 +216,9 @@ static s32 spi_cfg_mxc(struct mxc_spi_slave *mxcs, unsigned int cs) } #endif -int spi_xchg_single(struct spi_slave *slave, unsigned int bitlen, +int spi_xchg_single(struct mxc_spi_slave *mxcs, unsigned int bitlen, const u8 *dout, u8 *din, unsigned long flags) { - struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave); int nbytes = DIV_ROUND_UP(bitlen, 8); u32 data, cnt, i; struct cspi_regs *regs = (struct cspi_regs *)mxcs->base; @@ -327,8 +331,9 @@ int spi_xchg_single(struct spi_slave *slave, unsigned int bitlen, } -int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, - void *din, unsigned long flags) +static int mxc_spi_xfer_internal(struct mxc_spi_slave *mxcs, + unsigned int bitlen, const void *dout, + void *din, unsigned long flags) { int n_bytes = DIV_ROUND_UP(bitlen, 8); int n_bits; @@ -337,11 +342,11 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, u8 *p_outbuf = (u8 *)dout; u8 *p_inbuf = (u8 *)din; - if (!slave) - return -1; + if (!mxcs) + return -EINVAL; if (flags & SPI_XFER_BEGIN) - spi_cs_activate(slave); + mxc_spi_cs_activate(mxcs); while (n_bytes > 0) { if (n_bytes < MAX_SPI_BYTES) @@ -351,7 +356,7 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, n_bits = blk_size * 8; - ret = spi_xchg_single(slave, n_bits, p_outbuf, p_inbuf, 0); + ret = spi_xchg_single(mxcs, n_bits, p_outbuf, p_inbuf, 0); if (ret) return ret; @@ -363,12 +368,39 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, } if (flags & SPI_XFER_END) { - spi_cs_deactivate(slave); + mxc_spi_cs_deactivate(mxcs); } return 0; } +static int mxc_spi_claim_bus_internal(struct mxc_spi_slave *mxcs, int cs) +{ + struct cspi_regs *regs = (struct cspi_regs *)mxcs->base; + int ret; + + reg_write(®s->rxdata, 1); + udelay(1); + ret = spi_cfg_mxc(mxcs, cs); + if (ret) { + printf("mxc_spi: cannot setup SPI controller\n"); + return ret; + } + reg_write(®s->period, MXC_CSPIPERIOD_32KHZ); + reg_write(®s->intr, 0); + + return 0; +} + +#ifndef CONFIG_DM_SPI +int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, + void *din, unsigned long flags) +{ + struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave); + + return mxc_spi_xfer_internal(mxcs, bitlen, dout, din, flags); +} + void spi_init(void) { } @@ -390,6 +422,7 @@ static int setup_cs_gpio(struct mxc_spi_slave *mxcs, if (mxcs->gpio == -1) return 0; + gpio_request(mxcs->gpio, "spi-cs"); ret = gpio_direction_output(mxcs->gpio, !(mxcs->ss_pol)); if (ret) { printf("mxc_spi: cannot setup gpio %d\n", mxcs->gpio); @@ -399,6 +432,10 @@ static int setup_cs_gpio(struct mxc_spi_slave *mxcs, return 0; } +static unsigned long spi_bases[] = { + MXC_SPI_BASE_ADDRESSES +}; + struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, unsigned int max_hz, unsigned int mode) { @@ -443,24 +480,104 @@ void spi_free_slave(struct spi_slave *slave) int spi_claim_bus(struct spi_slave *slave) { - int ret; struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave); - struct cspi_regs *regs = (struct cspi_regs *)mxcs->base; - reg_write(®s->rxdata, 1); - udelay(1); - ret = spi_cfg_mxc(mxcs, slave->cs); + return mxc_spi_claim_bus_internal(mxcs, slave->cs); +} + +void spi_release_bus(struct spi_slave *slave) +{ + /* TODO: Shut the controller down */ +} +#else + +static int mxc_spi_probe(struct udevice *bus) +{ + struct mxc_spi_slave *plat = bus->platdata; + struct mxc_spi_slave *mxcs = dev_get_platdata(bus); + int node = dev_of_offset(bus); + const void *blob = gd->fdt_blob; + int ret; + + if (gpio_request_by_name(bus, "cs-gpios", 0, &plat->ss, + GPIOD_IS_OUT)) { + dev_err(bus, "No cs-gpios property\n"); + return -EINVAL; + } + + plat->base = dev_get_addr(bus); + if (plat->base == FDT_ADDR_T_NONE) + return -ENODEV; + + ret = dm_gpio_set_value(&plat->ss, !(mxcs->ss_pol)); if (ret) { - printf("mxc_spi: cannot setup SPI controller\n"); + dev_err(bus, "Setting cs error\n"); return ret; } - reg_write(®s->period, MXC_CSPIPERIOD_32KHZ); - reg_write(®s->intr, 0); + + mxcs->max_hz = fdtdec_get_int(blob, node, "spi-max-frequency", + 20000000); return 0; } -void spi_release_bus(struct spi_slave *slave) +static int mxc_spi_xfer(struct udevice *dev, unsigned int bitlen, + const void *dout, void *din, unsigned long flags) { - /* TODO: Shut the controller down */ + struct mxc_spi_slave *mxcs = dev_get_platdata(dev->parent); + + + return mxc_spi_xfer_internal(mxcs, bitlen, dout, din, flags); +} + +static int mxc_spi_claim_bus(struct udevice *dev) +{ + struct mxc_spi_slave *mxcs = dev_get_platdata(dev->parent); + struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev); + + return mxc_spi_claim_bus_internal(mxcs, slave_plat->cs); } + +static int mxc_spi_release_bus(struct udevice *dev) +{ + return 0; +} + +static int mxc_spi_set_speed(struct udevice *bus, uint speed) +{ + /* Nothing to do */ + return 0; +} + +static int mxc_spi_set_mode(struct udevice *bus, uint mode) +{ + struct mxc_spi_slave *mxcs = dev_get_platdata(bus); + + mxcs->mode = mode; + mxcs->ss_pol = (mode & SPI_CS_HIGH) ? 1 : 0; + + return 0; +} + +static const struct dm_spi_ops mxc_spi_ops = { + .claim_bus = mxc_spi_claim_bus, + .release_bus = mxc_spi_release_bus, + .xfer = mxc_spi_xfer, + .set_speed = mxc_spi_set_speed, + .set_mode = mxc_spi_set_mode, +}; + +static const struct udevice_id mxc_spi_ids[] = { + { .compatible = "fsl,imx51-ecspi" }, + { } +}; + +U_BOOT_DRIVER(mxc_spi) = { + .name = "mxc_spi", + .id = UCLASS_SPI, + .of_match = mxc_spi_ids, + .ops = &mxc_spi_ops, + .platdata_auto_alloc_size = sizeof(struct mxc_spi_slave), + .probe = mxc_spi_probe, +}; +#endif diff --git a/drivers/spi/nds_ae3xx_spi.c b/drivers/spi/nds_ae3xx_spi.c new file mode 100644 index 0000000000..f5bd99a605 --- /dev/null +++ b/drivers/spi/nds_ae3xx_spi.c @@ -0,0 +1,499 @@ +/* + * NDS SPI controller driver. + * + * Copyright 2017 Andes Technology, Inc. + * Author: Rick Chen (rick@andestech.com) + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <clk.h> +#include <common.h> +#include <malloc.h> +#include <spi.h> +#include <asm/io.h> +#include <dm.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define MAX_TRANSFER_LEN 512 +#define CHUNK_SIZE 1 +#define SPI_TIMEOUT 0x100000 +#define SPI0_BUS 0 +#define SPI1_BUS 1 +#define SPI0_BASE 0xf0b00000 +#define SPI1_BASE 0xf0f00000 +#define NSPI_MAX_CS_NUM 1 + +struct ae3xx_spi_regs { + u32 rev; + u32 reserve1[3]; + u32 format; /* 0x10 */ +#define DATA_LENGTH(x) ((x-1)<<8) + u32 pio; + u32 reserve2[2]; + u32 tctrl; /* 0x20 */ +#define TRAMODE_OFFSET 24 +#define TRAMODE_MASK (0x0F<<TRAMODE_OFFSET) +#define TRAMODE_WR_SYNC (0<<TRAMODE_OFFSET) +#define TRAMODE_WO (1<<TRAMODE_OFFSET) +#define TRAMODE_RO (2<<TRAMODE_OFFSET) +#define TRAMODE_WR (3<<TRAMODE_OFFSET) +#define TRAMODE_RW (4<<TRAMODE_OFFSET) +#define TRAMODE_WDR (5<<TRAMODE_OFFSET) +#define TRAMODE_RDW (6<<TRAMODE_OFFSET) +#define TRAMODE_NONE (7<<TRAMODE_OFFSET) +#define TRAMODE_DW (8<<TRAMODE_OFFSET) +#define TRAMODE_DR (9<<TRAMODE_OFFSET) +#define WCNT_OFFSET 12 +#define WCNT_MASK (0x1FF<<WCNT_OFFSET) +#define RCNT_OFFSET 0 +#define RCNT_MASK (0x1FF<<RCNT_OFFSET) + u32 cmd; + u32 addr; + u32 data; + u32 ctrl; /* 0x30 */ +#define TXFTH_OFFSET 16 +#define RXFTH_OFFSET 8 +#define TXDMAEN (1<<4) +#define RXDMAEN (1<<3) +#define TXFRST (1<<2) +#define RXFRST (1<<1) +#define SPIRST (1<<0) + u32 status; +#define TXFFL (1<<23) +#define TXEPTY (1<<22) +#define TXFVE_MASK (0x1F<<16) +#define RXFEM (1<<14) +#define RXFVE_OFFSET (8) +#define RXFVE_MASK (0x1F<<RXFVE_OFFSET) +#define SPIBSY (1<<0) + u32 inten; + u32 intsta; + u32 timing; /* 0x40 */ +#define SCLK_DIV_MASK 0xFF +}; + +struct nds_spi_slave { +#ifndef CONFIG_DM_SPI + struct spi_slave slave; +#endif + volatile struct ae3xx_spi_regs *regs; + int to; + unsigned int freq; + ulong clock; + unsigned int mode; + u8 num_cs; + unsigned int mtiming; + size_t cmd_len; + u8 cmd_buf[16]; + size_t data_len; + size_t tran_len; + u8 *din; + u8 *dout; + unsigned int max_transfer_length; +}; + +static int __ae3xx_spi_set_speed(struct nds_spi_slave *ns) +{ + u32 tm; + u8 div; + tm = ns->regs->timing; + tm &= ~SCLK_DIV_MASK; + + if(ns->freq >= ns->clock) + div =0xff; + else{ + for (div = 0; div < 0xff; div++) { + if (ns->freq >= ns->clock / (2 * (div + 1))) + break; + } + } + + tm |= div; + ns->regs->timing = tm; + + return 0; + +} + +static int __ae3xx_spi_claim_bus(struct nds_spi_slave *ns) +{ + unsigned int format=0; + ns->regs->ctrl |= (TXFRST|RXFRST|SPIRST); + while((ns->regs->ctrl &(TXFRST|RXFRST|SPIRST))&&(ns->to--)) + if(!ns->to) + return -EINVAL; + + ns->cmd_len = 0; + format = ns->mode|DATA_LENGTH(8); + ns->regs->format = format; + __ae3xx_spi_set_speed(ns); + + return 0; +} + +static int __ae3xx_spi_release_bus(struct nds_spi_slave *ns) +{ + /* do nothing */ + return 0; +} + +static int __ae3xx_spi_start(struct nds_spi_slave *ns) +{ + int i,olen=0; + int tc = ns->regs->tctrl; + + tc &= ~(WCNT_MASK|RCNT_MASK|TRAMODE_MASK); + if ((ns->din)&&(ns->cmd_len)) + tc |= TRAMODE_WR; + else if (ns->din) + tc |= TRAMODE_RO; + else + tc |= TRAMODE_WO; + + if(ns->dout) + olen = ns->tran_len; + tc |= (ns->cmd_len+olen-1) << WCNT_OFFSET; + + if(ns->din) + tc |= (ns->tran_len-1) << RCNT_OFFSET; + + ns->regs->tctrl = tc; + ns->regs->cmd = 1; + + for (i=0;i<ns->cmd_len;i++) + ns->regs->data = ns->cmd_buf[i]; + + return 0; +} + +static int __ae3xx_spi_stop(struct nds_spi_slave *ns) +{ + ns->regs->timing = ns->mtiming; + while ((ns->regs->status & SPIBSY)&&(ns->to--)) + if (!ns->to) + return -EINVAL; + + return 0; +} + +static void __nspi_espi_tx(struct nds_spi_slave *ns, const void *dout) +{ + ns->regs->data = *(u8 *)dout; +} + +static int __nspi_espi_rx(struct nds_spi_slave *ns, void *din, unsigned int bytes) +{ + *(u8 *)din = ns->regs->data; + return bytes; +} + + +static int __ae3xx_spi_xfer(struct nds_spi_slave *ns, + unsigned int bitlen, const void *data_out, void *data_in, + unsigned long flags) +{ + unsigned int event, rx_bytes; + const void *dout = NULL; + void *din = NULL; + int num_blks, num_chunks, max_tran_len, tran_len; + int num_bytes; + u8 *cmd_buf = ns->cmd_buf; + size_t cmd_len = ns->cmd_len; + size_t data_len = bitlen / 8; + int rf_cnt; + int ret = 0; + + max_tran_len = ns->max_transfer_length; + switch (flags) { + case SPI_XFER_BEGIN: + cmd_len = ns->cmd_len = data_len; + memcpy(cmd_buf, data_out, cmd_len); + return 0; + + case 0: + case SPI_XFER_END: + if (bitlen == 0) { + return 0; + } + ns->data_len = data_len; + ns->din = (u8 *)data_in; + ns->dout = (u8 *)data_out; + break; + + case SPI_XFER_BEGIN | SPI_XFER_END: + ns->data_len = 0; + ns->din = 0; + ns->dout = 0; + cmd_len = ns->cmd_len = data_len; + memcpy(cmd_buf, data_out, cmd_len); + data_out = 0; + data_len = 0; + __ae3xx_spi_start(ns); + break; + } + debug("spi_xfer: data_out %08X(%p) data_in %08X(%p) data_len %u\n", + *(uint *)data_out, data_out, *(uint *)data_in, data_in, data_len); + num_chunks = DIV_ROUND_UP(data_len, max_tran_len); + din = data_in; + dout = data_out; + while (num_chunks--) { + tran_len = min(data_len, (size_t)max_tran_len); + ns->tran_len = tran_len; + num_blks = DIV_ROUND_UP(tran_len , CHUNK_SIZE); + num_bytes = (tran_len) % CHUNK_SIZE; + if(num_bytes == 0) + num_bytes = CHUNK_SIZE; + __ae3xx_spi_start(ns); + + while (num_blks) { + event = in_le32(&ns->regs->status); + if ((event & TXEPTY) && (data_out)) { + __nspi_espi_tx(ns, dout); + num_blks -= CHUNK_SIZE; + dout += CHUNK_SIZE; + } + + if ((event & RXFVE_MASK) && (data_in)) { + rf_cnt = ((event & RXFVE_MASK)>> RXFVE_OFFSET); + if (rf_cnt >= CHUNK_SIZE) + rx_bytes = CHUNK_SIZE; + else if (num_blks == 1 && rf_cnt == num_bytes) + rx_bytes = num_bytes; + else + continue; + + if (__nspi_espi_rx(ns, din, rx_bytes) == rx_bytes) { + num_blks -= CHUNK_SIZE; + din = (unsigned char *)din + rx_bytes; + } + } + } + + data_len -= tran_len; + if(data_len) + { + ns->cmd_buf[1] += ((tran_len>>16)&0xff); + ns->cmd_buf[2] += ((tran_len>>8)&0xff); + ns->cmd_buf[3] += ((tran_len)&0xff); + ns->data_len = data_len; + } + ret = __ae3xx_spi_stop(ns); + } + ret = __ae3xx_spi_stop(ns); + + return ret; +} + +#ifndef CONFIG_DM_SPI +#define to_nds_spi_slave(s) container_of(s, struct nds_spi_slave, slave) +struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, + unsigned int max_hz, unsigned int mode) +{ + struct nds_spi_slave *ns; + + if (!spi_cs_is_valid(bus, cs)) + return NULL; + + ns = spi_alloc_slave(struct nds_spi_slave, bus, cs); + + switch (bus) { + case SPI0_BUS: + ns->regs = (struct ae3xx_spi_regs *)SPI0_BASE; + break; + + case SPI1_BUS: + ns->regs = (struct ae3xx_spi_regs *)SPI1_BASE; + break; + + default: + return NULL; + } + + ns->freq= max_hz; + ns->mode = mode; + ns->to = SPI_TIMEOUT; + ns->max_transfer_length = MAX_TRANSFER_LEN; + ns->slave.max_write_size = MAX_TRANSFER_LEN; + if (!ns) + return NULL; + + return &ns->slave; +} + +void spi_free_slave(struct spi_slave *slave) +{ + struct nds_spi_slave *ns = to_nds_spi_slave(slave); + free(ns); +} + +void spi_init(void) +{ + /* do nothing */ +} + +int spi_claim_bus(struct spi_slave *slave) +{ + struct nds_spi_slave *ns = to_nds_spi_slave(slave); + return __ae3xx_spi_claim_bus(ns); +} + +void spi_release_bus(struct spi_slave *slave) +{ + struct nds_spi_slave *ns = to_nds_spi_slave(slave); + __ae3xx_spi_release_bus(ns); +} + +int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *data_out, + void *data_in, unsigned long flags) +{ + struct nds_spi_slave *ns = to_nds_spi_slave(slave); + return __ae3xx_spi_xfer(ns, bitlen, data_out, data_in, flags); +} + +int spi_cs_is_valid(unsigned int bus, unsigned int cs) +{ + return bus == 0 && cs < NSPI_MAX_CS_NUM; +} + +void spi_cs_activate(struct spi_slave *slave) +{ + struct nds_spi_slave *ns = to_nds_spi_slave(slave); + __ae3xx_spi_start(ns); +} + +void spi_cs_deactivate(struct spi_slave *slave) +{ + struct nds_spi_slave *ns = to_nds_spi_slave(slave); + __ae3xx_spi_stop(ns); +} +#else +static int ae3xx_spi_set_speed(struct udevice *bus, uint max_hz) +{ + struct nds_spi_slave *ns = dev_get_priv(bus); + + debug("%s speed %u\n", __func__, max_hz); + + ns->freq = max_hz; + __ae3xx_spi_set_speed(ns); + + return 0; +} + +static int ae3xx_spi_set_mode(struct udevice *bus, uint mode) +{ + struct nds_spi_slave *ns = dev_get_priv(bus); + + debug("%s mode %u\n", __func__, mode); + ns->mode = mode; + + return 0; +} + +static int ae3xx_spi_claim_bus(struct udevice *dev) +{ + struct dm_spi_slave_platdata *slave_plat = + dev_get_parent_platdata(dev); + struct udevice *bus = dev->parent; + struct nds_spi_slave *ns = dev_get_priv(bus); + + if (slave_plat->cs >= ns->num_cs) { + printf("Invalid SPI chipselect\n"); + return -EINVAL; + } + + return __ae3xx_spi_claim_bus(ns); +} + +static int ae3xx_spi_release_bus(struct udevice *dev) +{ + struct nds_spi_slave *ns = dev_get_priv(dev->parent); + + return __ae3xx_spi_release_bus(ns); +} + +static int ae3xx_spi_xfer(struct udevice *dev, unsigned int bitlen, + const void *dout, void *din, + unsigned long flags) +{ + struct udevice *bus = dev->parent; + struct nds_spi_slave *ns = dev_get_priv(bus); + + return __ae3xx_spi_xfer(ns, bitlen, dout, din, flags); +} + +static int ae3xx_spi_get_clk(struct udevice *bus) +{ + struct nds_spi_slave *ns = dev_get_priv(bus); + struct clk clk; + ulong clk_rate; + int ret; + + ret = clk_get_by_index(bus, 0, &clk); + if (ret) + return -EINVAL; + + clk_rate = clk_get_rate(&clk); + if (!clk_rate) + return -EINVAL; + + ns->clock = clk_rate; + clk_free(&clk); + + return 0; +} + +static int ae3xx_spi_probe(struct udevice *bus) +{ + struct nds_spi_slave *ns = dev_get_priv(bus); + + ns->to = SPI_TIMEOUT; + ns->max_transfer_length = MAX_TRANSFER_LEN; + ns->mtiming = ns->regs->timing; + ae3xx_spi_get_clk(bus); + + return 0; +} + +static int ae3xx_ofdata_to_platadata(struct udevice *bus) +{ + struct nds_spi_slave *ns = dev_get_priv(bus); + const void *blob = gd->fdt_blob; + int node = dev_of_offset(bus); + + ns->regs = map_physmem(devfdt_get_addr(bus), + sizeof(struct ae3xx_spi_regs), + MAP_NOCACHE); + if (!ns->regs) { + printf("%s: could not map device address\n", __func__); + return -EINVAL; + } + ns->num_cs = fdtdec_get_int(blob, node, "num-cs", 4); + + return 0; +} + +static const struct dm_spi_ops ae3xx_spi_ops = { + .claim_bus = ae3xx_spi_claim_bus, + .release_bus = ae3xx_spi_release_bus, + .xfer = ae3xx_spi_xfer, + .set_speed = ae3xx_spi_set_speed, + .set_mode = ae3xx_spi_set_mode, +}; + +static const struct udevice_id ae3xx_spi_ids[] = { + { .compatible = "andestech,atcspi200" }, + { } +}; + +U_BOOT_DRIVER(ae3xx_spi) = { + .name = "ae3xx_spi", + .id = UCLASS_SPI, + .of_match = ae3xx_spi_ids, + .ops = &ae3xx_spi_ops, + .ofdata_to_platdata = ae3xx_ofdata_to_platadata, + .priv_auto_alloc_size = sizeof(struct nds_spi_slave), + .probe = ae3xx_spi_probe, +}; +#endif diff --git a/drivers/spi/rk_spi.c b/drivers/spi/rk_spi.c index c70d636277..b18db74e7e 100644 --- a/drivers/spi/rk_spi.c +++ b/drivers/spi/rk_spi.c @@ -184,7 +184,7 @@ static int rockchip_spi_ofdata_to_platdata(struct udevice *bus) struct rockchip_spi_priv *priv = dev_get_priv(bus); int ret; - plat->base = devfdt_get_addr(bus); + plat->base = dev_read_addr(bus); ret = clk_get_by_index(bus, 0, &priv->clk); if (ret < 0) { diff --git a/drivers/sysreset/Makefile b/drivers/sysreset/Makefile index a5200d377d..476d361297 100644 --- a/drivers/sysreset/Makefile +++ b/drivers/sysreset/Makefile @@ -13,6 +13,7 @@ ifndef CONFIG_SPL_BUILD obj-$(CONFIG_ROCKCHIP_RK3036) += sysreset_rk3036.o endif obj-$(CONFIG_ROCKCHIP_RK3188) += sysreset_rk3188.o +obj-$(CONFIG_ROCKCHIP_RK322X) += sysreset_rk322x.o obj-$(CONFIG_ROCKCHIP_RK3288) += sysreset_rk3288.o obj-$(CONFIG_ROCKCHIP_RK3328) += sysreset_rk3328.o obj-$(CONFIG_ROCKCHIP_RK3368) += sysreset_rk3368.o diff --git a/drivers/timer/rockchip_timer.c b/drivers/timer/rockchip_timer.c index eb44965a19..07d14482d6 100644 --- a/drivers/timer/rockchip_timer.c +++ b/drivers/timer/rockchip_timer.c @@ -6,6 +6,7 @@ #include <common.h> #include <dm.h> +#include <dm/ofnode.h> #include <mapmem.h> #include <asm/arch/timer.h> #include <dt-structs.h> @@ -25,17 +26,72 @@ struct rockchip_timer_priv { struct rk_timer *timer; }; -static int rockchip_timer_get_count(struct udevice *dev, u64 *count) +static inline int64_t rockchip_timer_get_curr_value(struct rk_timer *timer) { - struct rockchip_timer_priv *priv = dev_get_priv(dev); uint64_t timebase_h, timebase_l; uint64_t cntr; - timebase_l = readl(&priv->timer->timer_curr_value0); - timebase_h = readl(&priv->timer->timer_curr_value1); + timebase_l = readl(&timer->timer_curr_value0); + timebase_h = readl(&timer->timer_curr_value1); - /* timers are down-counting */ cntr = timebase_h << 32 | timebase_l; + return cntr; +} + +#if CONFIG_IS_ENABLED(BOOTSTAGE) +ulong timer_get_boot_us(void) +{ + uint64_t ticks = 0; + uint32_t rate; + uint64_t us; + int ret; + + ret = dm_timer_init(); + + if (!ret) { + /* The timer is available */ + rate = timer_get_rate(gd->timer); + timer_get_count(gd->timer, &ticks); +#if !CONFIG_IS_ENABLED(OF_PLATDATA) + } else if (ret == -EAGAIN) { + /* We have been called so early that the DM is not ready,... */ + ofnode node = offset_to_ofnode(-1); + struct rk_timer *timer = NULL; + + /* + * ... so we try to access the raw timer, if it is specified + * via the tick-timer property in /chosen. + */ + node = ofnode_get_chosen_node("tick-timer"); + if (!ofnode_valid(node)) { + debug("%s: no /chosen/tick-timer\n", __func__); + return 0; + } + + timer = (struct rk_timer *)ofnode_get_addr(node); + + /* This timer is down-counting */ + ticks = ~0uLL - rockchip_timer_get_curr_value(timer); + if (ofnode_read_u32(node, "clock-frequency", &rate)) { + debug("%s: could not read clock-frequency\n", __func__); + return 0; + } +#endif + } else { + return 0; + } + + us = (ticks * 1000) / rate; + return us; +} +#endif + +static int rockchip_timer_get_count(struct udevice *dev, u64 *count) +{ + struct rockchip_timer_priv *priv = dev_get_priv(dev); + uint64_t cntr = rockchip_timer_get_curr_value(priv->timer); + + /* timers are down-counting */ *count = ~0ull - cntr; return 0; } @@ -45,7 +101,9 @@ static int rockchip_clk_ofdata_to_platdata(struct udevice *dev) #if !CONFIG_IS_ENABLED(OF_PLATDATA) struct rockchip_timer_priv *priv = dev_get_priv(dev); - priv->timer = (struct rk_timer *)devfdt_get_addr(dev); + priv->timer = dev_read_addr_ptr(dev); + if (!priv->timer) + return -ENOENT; #endif return 0; @@ -58,6 +116,12 @@ static int rockchip_timer_start(struct udevice *dev) const uint32_t reload_val_l = reload_val & 0xffffffff; const uint32_t reload_val_h = reload_val >> 32; + /* don't reinit, if the timer is already running and set up */ + if ((readl(&priv->timer->timer_ctrl_reg) & 1) == 1 && + (readl(&priv->timer->timer_load_count0) == reload_val_l) && + (readl(&priv->timer->timer_load_count1) == reload_val_h)) + return 0; + /* disable timer and reset all control */ writel(0, &priv->timer->timer_ctrl_reg); /* write reload value */ @@ -76,7 +140,7 @@ static int rockchip_timer_probe(struct udevice *dev) struct rockchip_timer_priv *priv = dev_get_priv(dev); struct rockchip_timer_plat *plat = dev_get_platdata(dev); - priv->timer = map_sysmem(plat->dtd.reg[1], plat->dtd.reg[3]); + priv->timer = map_sysmem(plat->dtd.reg[0], plat->dtd.reg[1]); uc_priv->clock_rate = plat->dtd.clock_frequency; #endif diff --git a/drivers/timer/timer-uclass.c b/drivers/timer/timer-uclass.c index a84755f4c5..45397b230f 100644 --- a/drivers/timer/timer-uclass.c +++ b/drivers/timer/timer-uclass.c @@ -8,6 +8,7 @@ #include <dm.h> #include <dm/lists.h> #include <dm/device-internal.h> +#include <dm/root.h> #include <clk.h> #include <errno.h> #include <timer.h> @@ -54,9 +55,10 @@ static int timer_pre_probe(struct udevice *dev) if (IS_ERR_VALUE(ret)) return ret; uc_priv->clock_rate = ret; - } else - uc_priv->clock_rate = fdtdec_get_int(gd->fdt_blob, - dev_of_offset(dev), "clock-frequency", 0); + } else { + uc_priv->clock_rate = + dev_read_u32_default(dev, "clock-frequency", 0); + } #endif return 0; @@ -83,37 +85,43 @@ u64 timer_conv_64(u32 count) int notrace dm_timer_init(void) { - __maybe_unused const void *blob = gd->fdt_blob; struct udevice *dev = NULL; - int node = -ENOENT; + __maybe_unused ofnode node; int ret; if (gd->timer) return 0; + /* + * Directly access gd->dm_root to suppress error messages, if the + * virtual root driver does not yet exist. + */ + if (gd->dm_root == NULL) + return -EAGAIN; + #if !CONFIG_IS_ENABLED(OF_PLATDATA) /* Check for a chosen timer to be used for tick */ - node = fdtdec_get_chosen_node(blob, "tick-timer"); + node = ofnode_get_chosen_node("tick-timer"); + + if (ofnode_valid(node) && + uclass_get_device_by_ofnode(UCLASS_TIMER, node, &dev)) { + /* + * If the timer is not marked to be bound before + * relocation, bind it anyway. + */ + if (!lists_bind_fdt(dm_root(), node, &dev)) { + ret = device_probe(dev); + if (ret) + return ret; + } + } #endif - if (node < 0) { - /* No chosen timer, trying first available timer */ + + if (!dev) { + /* Fall back to the first available timer */ ret = uclass_first_device_err(UCLASS_TIMER, &dev); if (ret) return ret; - } else { - if (uclass_get_device_by_of_offset(UCLASS_TIMER, node, &dev)) { - /* - * If the timer is not marked to be bound before - * relocation, bind it anyway. - */ - if (node > 0 && - !lists_bind_fdt(gd->dm_root, offset_to_ofnode(node), - &dev)) { - ret = device_probe(dev); - if (ret) - return ret; - } - } } if (dev) { diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 62126aad2f..e7658b4d95 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -75,7 +75,7 @@ if USB_KEYBOARD choice prompt "USB keyboard polling" - optional + default SYS_USB_EVENT_POLL ---help--- Enable a polling mechanism for USB keyboard. diff --git a/drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c b/drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c index 0d6d2fba8a..b6164afa92 100644 --- a/drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c +++ b/drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c @@ -111,7 +111,8 @@ static int setdma_rx(struct dwc2_ep *ep, struct dwc2_request *req) ctrl = readl(®->out_endp[ep_num].doepctl); invalidate_dcache_range((unsigned long) ep->dma_buf, - (unsigned long) ep->dma_buf + ep->len); + (unsigned long) ep->dma_buf + + ROUND(ep->len, CONFIG_SYS_CACHELINE_SIZE)); writel((unsigned int) ep->dma_buf, ®->out_endp[ep_num].doepdma); writel(DOEPT_SIZ_PKT_CNT(pktcnt) | DOEPT_SIZ_XFER_SIZE(length), diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index eb035a476b..f797a2568c 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -47,6 +47,15 @@ config USB_XHCI_ROCKCHIP help Enables support for the on-chip xHCI controller on Rockchip SoCs. +config USB_XHCI_STI + bool "Support for STMicroelectronics STiH407 family on-chip xHCI USB controller" + depends on ARCH_STI + default y + help + Enables support for the on-chip xHCI controller on STMicroelectronics + STiH407 family SoCs. This is a driver for the dwc3 to provide the glue logic + to configure the controller. + config USB_XHCI_ZYNQMP bool "Support for Xilinx ZynqMP on-chip xHCI USB controller" depends on ARCH_ZYNQMP diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index ab5a99faa8..29afb7cf1d 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -60,6 +60,7 @@ obj-$(CONFIG_USB_XHCI_FSL) += xhci-fsl.o obj-$(CONFIG_USB_XHCI_MVEBU) += xhci-mvebu.o obj-$(CONFIG_USB_XHCI_OMAP) += xhci-omap.o obj-$(CONFIG_USB_XHCI_PCI) += xhci-pci.o +obj-$(CONFIG_USB_XHCI_STI) += dwc3-sti-glue.o # designware obj-$(CONFIG_USB_DWC2) += dwc2.o diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c index 64c42ac471..0ed72d5ae7 100644 --- a/drivers/usb/host/dwc2.c +++ b/drivers/usb/host/dwc2.c @@ -1245,7 +1245,7 @@ static int dwc2_usb_ofdata_to_platdata(struct udevice *dev) struct dwc2_priv *priv = dev_get_priv(dev); fdt_addr_t addr; - addr = devfdt_get_addr(dev); + addr = dev_read_addr(dev); if (addr == FDT_ADDR_T_NONE) return -EINVAL; priv->regs = (struct dwc2_core_regs *)addr; diff --git a/drivers/usb/host/dwc3-sti-glue.c b/drivers/usb/host/dwc3-sti-glue.c new file mode 100644 index 0000000000..02ad3115df --- /dev/null +++ b/drivers/usb/host/dwc3-sti-glue.c @@ -0,0 +1,257 @@ +/* + * STiH407 family DWC3 specific Glue layer + * + * Copyright (c) 2017 + * Patrice Chotard <patrice.chotard@st.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <dm.h> +#include <errno.h> +#include <fdtdec.h> +#include <libfdt.h> +#include <dm/lists.h> +#include <regmap.h> +#include <reset-uclass.h> +#include <syscon.h> +#include <usb.h> + +#include <linux/usb/dwc3.h> +#include <linux/usb/otg.h> +#include <dwc3-sti-glue.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* + * struct sti_dwc3_glue_platdata - dwc3 STi glue driver private structure + * @syscfg_base: addr for the glue syscfg + * @glue_base: addr for the glue registers + * @syscfg_offset: usb syscfg control offset + * @powerdown_ctl: rest controller for powerdown signal + * @softreset_ctl: reset controller for softreset signal + * @mode: drd static host/device config + */ +struct sti_dwc3_glue_platdata { + phys_addr_t syscfg_base; + phys_addr_t glue_base; + phys_addr_t syscfg_offset; + struct reset_ctl powerdown_ctl; + struct reset_ctl softreset_ctl; + enum usb_dr_mode mode; +}; + +static int sti_dwc3_glue_drd_init(struct sti_dwc3_glue_platdata *plat) +{ + unsigned long val; + + val = readl(plat->syscfg_base + plat->syscfg_offset); + + val &= USB3_CONTROL_MASK; + + switch (plat->mode) { + case USB_DR_MODE_PERIPHERAL: + val &= ~(USB3_DELAY_VBUSVALID + | USB3_SEL_FORCE_OPMODE | USB3_FORCE_OPMODE(0x3) + | USB3_SEL_FORCE_DPPULLDOWN2 | USB3_FORCE_DPPULLDOWN2 + | USB3_SEL_FORCE_DMPULLDOWN2 | USB3_FORCE_DMPULLDOWN2); + + val |= USB3_DEVICE_NOT_HOST | USB3_FORCE_VBUSVALID; + break; + + case USB_DR_MODE_HOST: + val &= ~(USB3_DEVICE_NOT_HOST | USB3_FORCE_VBUSVALID + | USB3_SEL_FORCE_OPMODE | USB3_FORCE_OPMODE(0x3) + | USB3_SEL_FORCE_DPPULLDOWN2 | USB3_FORCE_DPPULLDOWN2 + | USB3_SEL_FORCE_DMPULLDOWN2 | USB3_FORCE_DMPULLDOWN2); + + val |= USB3_DELAY_VBUSVALID; + break; + + default: + error("Unsupported mode of operation %d\n", plat->mode); + return -EINVAL; + } + writel(val, plat->syscfg_base + plat->syscfg_offset); + + return 0; +} + +static void sti_dwc3_glue_init(struct sti_dwc3_glue_platdata *plat) +{ + unsigned long reg; + + reg = readl(plat->glue_base + CLKRST_CTRL); + + reg |= AUX_CLK_EN | EXT_CFG_RESET_N | XHCI_REVISION; + reg &= ~SW_PIPEW_RESET_N; + + writel(reg, plat->glue_base + CLKRST_CTRL); + + /* configure mux for vbus, powerpresent and bvalid signals */ + reg = readl(plat->glue_base + USB2_VBUS_MNGMNT_SEL1); + + reg |= SEL_OVERRIDE_VBUSVALID(USB2_VBUS_UTMIOTG) | + SEL_OVERRIDE_POWERPRESENT(USB2_VBUS_UTMIOTG) | + SEL_OVERRIDE_BVALID(USB2_VBUS_UTMIOTG); + + writel(reg, plat->glue_base + USB2_VBUS_MNGMNT_SEL1); + + setbits_le32(plat->glue_base + CLKRST_CTRL, SW_PIPEW_RESET_N); +} + +static int sti_dwc3_glue_ofdata_to_platdata(struct udevice *dev) +{ + struct sti_dwc3_glue_platdata *plat = dev_get_platdata(dev); + struct udevice *syscon; + struct regmap *regmap; + int ret; + u32 reg[4]; + + ret = fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(dev), + "reg", reg, ARRAY_SIZE(reg)); + if (ret) { + error("unable to find st,stih407-dwc3 reg property(%d)\n", ret); + return ret; + } + + plat->glue_base = reg[0]; + plat->syscfg_offset = reg[2]; + + /* get corresponding syscon phandle */ + ret = uclass_get_device_by_phandle(UCLASS_SYSCON, dev, "st,syscfg", + &syscon); + if (ret) { + error("unable to find syscon device (%d)\n", ret); + return ret; + } + + /* get syscfg-reg base address */ + regmap = syscon_get_regmap(syscon); + if (!regmap) { + error("unable to find regmap\n"); + return -ENODEV; + } + plat->syscfg_base = regmap->base; + + /* get powerdown reset */ + ret = reset_get_by_name(dev, "powerdown", &plat->powerdown_ctl); + if (ret) { + error("can't get powerdown reset for %s (%d)", dev->name, ret); + return ret; + } + + /* get softreset reset */ + ret = reset_get_by_name(dev, "softreset", &plat->softreset_ctl); + if (ret) + error("can't get soft reset for %s (%d)", dev->name, ret); + + return ret; +}; + +static int sti_dwc3_glue_bind(struct udevice *dev) +{ + struct sti_dwc3_glue_platdata *plat = dev_get_platdata(dev); + int dwc3_node; + + /* check if one subnode is present */ + dwc3_node = fdt_first_subnode(gd->fdt_blob, dev_of_offset(dev)); + if (dwc3_node <= 0) { + error("Can't find subnode for %s\n", dev->name); + return -ENODEV; + } + + /* check if the subnode compatible string is the dwc3 one*/ + if (fdt_node_check_compatible(gd->fdt_blob, dwc3_node, + "snps,dwc3") != 0) { + error("Can't find dwc3 subnode for %s\n", dev->name); + return -ENODEV; + } + + /* retrieve the DWC3 dual role mode */ + plat->mode = usb_get_dr_mode(dwc3_node); + if (plat->mode == USB_DR_MODE_UNKNOWN) + /* by default set dual role mode to HOST */ + plat->mode = USB_DR_MODE_HOST; + + return dm_scan_fdt_dev(dev); +} + +static int sti_dwc3_glue_probe(struct udevice *dev) +{ + struct sti_dwc3_glue_platdata *plat = dev_get_platdata(dev); + int ret; + + /* deassert both powerdown and softreset */ + ret = reset_deassert(&plat->powerdown_ctl); + if (ret < 0) { + error("DWC3 powerdown reset deassert failed: %d", ret); + return ret; + } + + ret = reset_deassert(&plat->softreset_ctl); + if (ret < 0) { + error("DWC3 soft reset deassert failed: %d", ret); + goto softreset_err; + } + + ret = sti_dwc3_glue_drd_init(plat); + if (ret) + goto init_err; + + sti_dwc3_glue_init(plat); + + return 0; + +init_err: + ret = reset_assert(&plat->softreset_ctl); + if (ret < 0) { + error("DWC3 soft reset deassert failed: %d", ret); + return ret; + } + +softreset_err: + ret = reset_assert(&plat->powerdown_ctl); + if (ret < 0) + error("DWC3 powerdown reset deassert failed: %d", ret); + + return ret; +} + +static int sti_dwc3_glue_remove(struct udevice *dev) +{ + struct sti_dwc3_glue_platdata *plat = dev_get_platdata(dev); + int ret; + + /* assert both powerdown and softreset */ + ret = reset_assert(&plat->powerdown_ctl); + if (ret < 0) { + error("DWC3 powerdown reset deassert failed: %d", ret); + return ret; + } + + ret = reset_assert(&plat->softreset_ctl); + if (ret < 0) + error("DWC3 soft reset deassert failed: %d", ret); + + return ret; +} + +static const struct udevice_id sti_dwc3_glue_ids[] = { + { .compatible = "st,stih407-dwc3" }, + { } +}; + +U_BOOT_DRIVER(dwc3_sti_glue) = { + .name = "dwc3_sti_glue", + .id = UCLASS_MISC, + .of_match = sti_dwc3_glue_ids, + .ofdata_to_platdata = sti_dwc3_glue_ofdata_to_platdata, + .probe = sti_dwc3_glue_probe, + .remove = sti_dwc3_glue_remove, + .bind = sti_dwc3_glue_bind, + .platdata_auto_alloc_size = sizeof(struct sti_dwc3_glue_platdata), + .flags = DM_FLAG_ALLOC_PRIV_DMA, +}; diff --git a/drivers/usb/host/ehci-generic.c b/drivers/usb/host/ehci-generic.c index 03f8d321af..18e1e0ee88 100644 --- a/drivers/usb/host/ehci-generic.c +++ b/drivers/usb/host/ehci-generic.c @@ -108,7 +108,7 @@ static int ehci_usb_probe(struct udevice *dev) } } - hccr = map_physmem(devfdt_get_addr(dev), 0x100, MAP_NOCACHE); + hccr = map_physmem(dev_read_addr(dev), 0x100, MAP_NOCACHE); hcor = (struct ehci_hcor *)((uintptr_t)hccr + HC_LENGTH(ehci_readl(&hccr->cr_capbase))); diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 3243c1d1cf..be3e842dcc 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -1596,6 +1596,17 @@ static int ehci_destroy_int_queue(struct udevice *dev, struct usb_device *udev, return _ehci_destroy_int_queue(udev, queue); } +static int ehci_get_max_xfer_size(struct udevice *dev, size_t *size) +{ + /* + * EHCD can handle any transfer length as long as there is enough + * free heap space left, hence set the theoretical max number here. + */ + *size = SIZE_MAX; + + return 0; +} + int ehci_register(struct udevice *dev, struct ehci_hccr *hccr, struct ehci_hcor *hcor, const struct ehci_ops *ops, uint tweaks, enum usb_init_type init) @@ -1658,6 +1669,7 @@ struct dm_usb_ops ehci_usb_ops = { .create_int_queue = ehci_create_int_queue, .poll_int_queue = ehci_poll_int_queue, .destroy_int_queue = ehci_destroy_int_queue, + .get_max_xfer_size = ehci_get_max_xfer_size, }; #endif diff --git a/drivers/usb/host/usb-uclass.c b/drivers/usb/host/usb-uclass.c index 0b8a501ce8..bc44fc3394 100644 --- a/drivers/usb/host/usb-uclass.c +++ b/drivers/usb/host/usb-uclass.c @@ -150,6 +150,17 @@ int usb_update_hub_device(struct usb_device *udev) return ops->update_hub_device(bus, udev); } +int usb_get_max_xfer_size(struct usb_device *udev, size_t *size) +{ + struct udevice *bus = udev->controller_dev; + struct dm_usb_ops *ops = usb_get_ops(bus); + + if (!ops->get_max_xfer_size) + return -ENOSYS; + + return ops->get_max_xfer_size(bus, size); +} + int usb_stop(void) { struct udevice *bus; diff --git a/drivers/usb/host/xhci-rockchip.c b/drivers/usb/host/xhci-rockchip.c index ec55f4e59f..ca3abffba0 100644 --- a/drivers/usb/host/xhci-rockchip.c +++ b/drivers/usb/host/xhci-rockchip.c @@ -6,8 +6,6 @@ */ #include <common.h> #include <dm.h> -#include <fdtdec.h> -#include <libfdt.h> #include <malloc.h> #include <usb.h> #include <watchdog.h> @@ -46,7 +44,7 @@ static int xhci_usb_ofdata_to_platdata(struct udevice *dev) /* * Get the base address for XHCI controller from the device node */ - plat->hcd_base = devfdt_get_addr(dev); + plat->hcd_base = dev_read_addr(dev); if (plat->hcd_base == FDT_ADDR_T_NONE) { error("Can't get the XHCI register base address\n"); return -ENXIO; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 9b82ee5c60..04eb1eb14d 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1228,6 +1228,20 @@ static int xhci_update_hub_device(struct udevice *dev, struct usb_device *udev) return xhci_configure_endpoints(udev, false); } +static int xhci_get_max_xfer_size(struct udevice *dev, size_t *size) +{ + /* + * xHCD allocates one segment which includes 64 TRBs for each endpoint + * and the last TRB in this segment is configured as a link TRB to form + * a TRB ring. Each TRB can transfer up to 64K bytes, however data + * buffers referenced by transfer TRBs shall not span 64KB boundaries. + * Hence the maximum number of TRBs we can use in one transfer is 62. + */ + *size = (TRBS_PER_SEGMENT - 2) * TRB_MAX_BUFF_SIZE; + + return 0; +} + int xhci_register(struct udevice *dev, struct xhci_hccr *hccr, struct xhci_hcor *hcor) { @@ -1281,6 +1295,7 @@ struct dm_usb_ops xhci_usb_ops = { .interrupt = xhci_submit_int_msg, .alloc_device = xhci_alloc_device, .update_hub_device = xhci_update_hub_device, + .get_max_xfer_size = xhci_get_max_xfer_size, }; #endif diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index a497d9d830..3377450fca 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1045,9 +1045,9 @@ struct xhci_scratchpad { * (1K bytes * 8bytes/bit) / (4*32 bits) = 64 segment entries in the table, * meaning 64 ring segments. * Initial allocated size of the ERST, in number of entries */ -#define ERST_NUM_SEGS 3 +#define ERST_NUM_SEGS 1 /* Initial number of event segment rings allocated */ -#define ERST_ENTRIES 3 +#define ERST_ENTRIES 1 /* Initial allocated size of the ERST, in number of entries */ #define ERST_SIZE 64 /* Poll every 60 seconds */ diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 082cc4a528..7ba7b580db 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -14,6 +14,27 @@ config DM_VIDEO option compiles in the video uclass and routes all LCD/video access through this. +config BACKLIGHT_PWM + bool "Generic PWM based Backlight Driver" + depends on DM_VIDEO && DM_PWM + default y + help + If you have a LCD backlight adjustable by PWM, say Y to enable + this driver. + This driver can be use with "simple-panel" and + it understands the standard device tree + (leds/backlight/pwm-backlight.txt) + +config BACKLIGHT_GPIO + bool "Generic GPIO based Backlight Driver" + depends on DM_VIDEO + help + If you have a LCD backlight adjustable by GPIO, say Y to enable + this driver. + This driver can be used with "simple-panel" and + it understands the standard device tree + (leds/backlight/gpio-backlight.txt) + config VIDEO_BPP8 bool "Support 8-bit-per-pixel displays" depends on DM_VIDEO @@ -98,6 +119,14 @@ config SYS_WHITE_ON_BLACK better in low-light situations or to reduce eye strain in some cases. +config NO_FB_CLEAR + bool "Skip framebuffer clear" + help + If firmware (whatever loads u-boot) has already put a splash image + on screen, you might want to preserve it until whatever u-boot + loads takes over the screen. This, for example, can be used to + keep splash image on screen until grub graphical boot menu starts. + source "drivers/video/fonts/Kconfig" config VIDCONSOLE_AS_LCD @@ -436,6 +465,8 @@ config VIDEO_SANDBOX_SDL console device and can display stdout output. Within U-Boot is is a normal bitmap display and can display images as well as text. +source "drivers/video/stm32/Kconfig" + config VIDEO_TEGRA20 bool "Enable LCD support on Tegra20" depends on OF_CONTROL @@ -601,4 +632,14 @@ config VIDEO_DW_HDMI rather requires a SoC-specific glue driver to call it), it can not be enabled from the configuration menu. +config VIDEO_SIMPLE + bool "Simple display driver for preconfigured display" + help + Enables a simple generic display driver which utilizes the + simple-framebuffer devicetree bindings. + + This driver assumes that the display hardware has been initialized + before u-boot starts, and u-boot will simply render to the pre- + allocated frame buffer surface. + endmenu diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 5cf8909295..dfafe08fc5 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -11,9 +11,8 @@ obj-$(CONFIG_DM_VIDEO) += backlight-uclass.o obj-$(CONFIG_DM_VIDEO) += panel-uclass.o simple_panel.o obj-$(CONFIG_DM_VIDEO) += video-uclass.o vidconsole-uclass.o obj-$(CONFIG_DM_VIDEO) += video_bmp.o -ifdef CONFIG_DM_VIDEO -obj-$(CONFIG_DM_PWM) += pwm_backlight.o -endif +obj-$(CONFIG_BACKLIGHT_PWM) += pwm_backlight.o +obj-$(CONFIG_BACKLIGHT_GPIO) += backlight_gpio.o obj-$(CONFIG_CONSOLE_NORMAL) += console_normal.o obj-$(CONFIG_CONSOLE_ROTATION) += console_rotate.o obj-$(CONFIG_CONSOLE_TRUETYPE) += console_truetype.o fonts/ @@ -53,10 +52,11 @@ obj-$(CONFIG_FORMIKE) += formike.o obj-$(CONFIG_LG4573) += lg4573.o obj-$(CONFIG_AM335X_LCD) += am335x-fb.o obj-$(CONFIG_VIDEO_DW_HDMI) += dw_hdmi.o - +obj-$(CONFIG_VIDEO_SIMPLE) += simplefb.o obj-${CONFIG_VIDEO_TEGRA124} += tegra124/ obj-${CONFIG_EXYNOS_FB} += exynos/ obj-${CONFIG_VIDEO_ROCKCHIP} += rockchip/ +obj-${CONFIG_VIDEO_STM32} += stm32/ obj-y += bridge/ obj-y += sunxi/ diff --git a/drivers/video/backlight_gpio.c b/drivers/video/backlight_gpio.c new file mode 100644 index 0000000000..772df5d302 --- /dev/null +++ b/drivers/video/backlight_gpio.c @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2017, STMicroelectronics - All Rights Reserved + * Author: Patrick Delaunay <patrick.delaunay@st.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <backlight.h> +#include <asm/gpio.h> + +DECLARE_GLOBAL_DATA_PTR; + +struct gpio_backlight_priv { + struct gpio_desc gpio; + bool def_value; +}; + +static int gpio_backlight_enable(struct udevice *dev) +{ + struct gpio_backlight_priv *priv = dev_get_priv(dev); + + dm_gpio_set_value(&priv->gpio, 1); + + return 0; +} + +static int gpio_backlight_ofdata_to_platdata(struct udevice *dev) +{ + struct gpio_backlight_priv *priv = dev_get_priv(dev); + int ret; + + ret = gpio_request_by_name(dev, "gpios", 0, &priv->gpio, + GPIOD_IS_OUT); + if (ret) { + debug("%s: Warning: cannot get GPIO: ret=%d\n", + __func__, ret); + return ret; + } + + priv->def_value = dev_read_bool(dev, "default-on"); + + return 0; +} + +static int gpio_backlight_probe(struct udevice *dev) +{ + struct gpio_backlight_priv *priv = dev_get_priv(dev); + + if (priv->def_value) + gpio_backlight_enable(dev); + + return 0; +} + +static const struct backlight_ops gpio_backlight_ops = { + .enable = gpio_backlight_enable, +}; + +static const struct udevice_id gpio_backlight_ids[] = { + { .compatible = "gpio-backlight" }, + { } +}; + +U_BOOT_DRIVER(gpio_backlight) = { + .name = "gpio_backlight", + .id = UCLASS_PANEL_BACKLIGHT, + .of_match = gpio_backlight_ids, + .ops = &gpio_backlight_ops, + .ofdata_to_platdata = gpio_backlight_ofdata_to_platdata, + .probe = gpio_backlight_probe, + .priv_auto_alloc_size = sizeof(struct gpio_backlight_priv), +}; diff --git a/drivers/video/cfb_console.c b/drivers/video/cfb_console.c index 6c5425c195..74cc20d653 100644 --- a/drivers/video/cfb_console.c +++ b/drivers/video/cfb_console.c @@ -2081,7 +2081,8 @@ static int cfg_video_init(void) } eorx = fgx ^ bgx; - video_clear(); + if (!CONFIG_IS_ENABLED(NO_FB_CLEAR)) + video_clear(); #ifdef CONFIG_VIDEO_LOGO /* Plot the logo and get start point of console */ diff --git a/drivers/video/simplefb.c b/drivers/video/simplefb.c new file mode 100644 index 0000000000..850a279d64 --- /dev/null +++ b/drivers/video/simplefb.c @@ -0,0 +1,73 @@ +/* + * (C) Copyright 2017 Rob Clark + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <fdtdec.h> +#include <fdt_support.h> +#include <video.h> + +static int simple_video_probe(struct udevice *dev) +{ + struct video_uc_platdata *plat = dev_get_uclass_platdata(dev); + struct video_priv *uc_priv = dev_get_uclass_priv(dev); + const void *blob = gd->fdt_blob; + const int node = dev_of_offset(dev); + const char *format; + fdt_addr_t base; + fdt_size_t size; + + base = fdtdec_get_addr_size_auto_parent(blob, dev_of_offset(dev->parent), + node, "reg", 0, &size, false); + if (base == FDT_ADDR_T_NONE) { + debug("%s: Failed to decode memory region\n", __func__); + return -EINVAL; + } + + debug("%s: base=%llx, size=%llu\n", __func__, base, size); + + /* + * TODO is there some way to reserve the framebuffer + * region so it isn't clobbered? + */ + plat->base = base; + plat->size = size; + + video_set_flush_dcache(dev, true); + + debug("%s: Query resolution...\n", __func__); + + uc_priv->xsize = fdtdec_get_uint(blob, node, "width", 0); + uc_priv->ysize = fdtdec_get_uint(blob, node, "height", 0); + uc_priv->rot = 0; + + format = fdt_getprop(blob, node, "format", NULL); + debug("%s: %dx%d@%s\n", __func__, uc_priv->xsize, uc_priv->ysize, format); + + if (strcmp(format, "r5g6b5") == 0) { + uc_priv->bpix = VIDEO_BPP16; + } else if (strcmp(format, "a8b8g8r8") == 0) { + uc_priv->bpix = VIDEO_BPP32; + } else { + printf("%s: invalid format: %s\n", __func__, format); + return -EINVAL; + } + + return 0; +} + +static const struct udevice_id simple_video_ids[] = { + { .compatible = "simple-framebuffer" }, + { } +}; + +U_BOOT_DRIVER(simple_video) = { + .name = "simple_video", + .id = UCLASS_VIDEO, + .of_match = simple_video_ids, + .probe = simple_video_probe, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/drivers/video/stm32/Kconfig b/drivers/video/stm32/Kconfig new file mode 100644 index 0000000000..113a2bbb33 --- /dev/null +++ b/drivers/video/stm32/Kconfig @@ -0,0 +1,44 @@ +# +# Copyright (C) STMicroelectronics SA 2017 +# +# Authors: Philippe Cornu <philippe.cornu@st.com> +# Yannick Fertre <yannick.fertre@st.com> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +menuconfig VIDEO_STM32 + bool "Enable STM32 video support" + depends on DM_VIDEO + help + STM32 supports many video output options including RGB and + DSI. This option enables these supports which can be used on + devices which have RGB TFT or DSI display connected. + +config VIDEO_STM32_MAX_XRES + int "Maximum horizontal resolution (for memory allocation purposes)" + depends on VIDEO_STM32 + default 640 + help + The maximum horizontal resolution to support for the framebuffer. + This configuration is used for reserving/allocating memory for the + framebuffer during device-model binding/probing. + +config VIDEO_STM32_MAX_YRES + int "Maximum vertical resolution (for memory allocation purposes)" + depends on VIDEO_STM32 + default 480 + help + The maximum vertical resolution to support for the framebuffer. + This configuration is used for reserving/allocating memory for the + framebuffer during device-model binding/probing. + +config VIDEO_STM32_MAX_BPP + int "Maximum bits per pixel (for memory allocation purposes)" + depends on VIDEO_STM32 + default 16 + help + The maximum bits per pixel to support for the framebuffer. + This configuration is used for reserving/allocating memory for the + framebuffer during device-model binding/probing. + diff --git a/drivers/video/stm32/Makefile b/drivers/video/stm32/Makefile new file mode 100644 index 0000000000..372a2e10c6 --- /dev/null +++ b/drivers/video/stm32/Makefile @@ -0,0 +1,10 @@ +# +# Copyright (C) STMicroelectronics SA 2017 +# +# Authors: Philippe Cornu <philippe.cornu@st.com> +# Yannick Fertre <yannick.fertre@st.com> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-${CONFIG_VIDEO_STM32} = stm32_ltdc.o diff --git a/drivers/video/stm32/stm32_ltdc.c b/drivers/video/stm32/stm32_ltdc.c new file mode 100644 index 0000000000..b417ac260a --- /dev/null +++ b/drivers/video/stm32/stm32_ltdc.c @@ -0,0 +1,406 @@ +/* + * Copyright (C) STMicroelectronics SA 2017 + * + * Authors: Philippe Cornu <philippe.cornu@st.com> + * Yannick Fertre <yannick.fertre@st.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <clk.h> +#include <dm.h> +#include <panel.h> +#include <video.h> +#include <asm/io.h> +#include <asm/arch/gpio.h> +#include <dm/device-internal.h> + +DECLARE_GLOBAL_DATA_PTR; + +struct stm32_ltdc_priv { + void __iomem *regs; + struct display_timing timing; + enum video_log2_bpp l2bpp; + u32 bg_col_argb; + u32 crop_x, crop_y, crop_w, crop_h; + u32 alpha; +}; + +/* LTDC main registers */ +#define LTDC_IDR 0x00 /* IDentification */ +#define LTDC_LCR 0x04 /* Layer Count */ +#define LTDC_SSCR 0x08 /* Synchronization Size Configuration */ +#define LTDC_BPCR 0x0C /* Back Porch Configuration */ +#define LTDC_AWCR 0x10 /* Active Width Configuration */ +#define LTDC_TWCR 0x14 /* Total Width Configuration */ +#define LTDC_GCR 0x18 /* Global Control */ +#define LTDC_GC1R 0x1C /* Global Configuration 1 */ +#define LTDC_GC2R 0x20 /* Global Configuration 2 */ +#define LTDC_SRCR 0x24 /* Shadow Reload Configuration */ +#define LTDC_GACR 0x28 /* GAmma Correction */ +#define LTDC_BCCR 0x2C /* Background Color Configuration */ +#define LTDC_IER 0x34 /* Interrupt Enable */ +#define LTDC_ISR 0x38 /* Interrupt Status */ +#define LTDC_ICR 0x3C /* Interrupt Clear */ +#define LTDC_LIPCR 0x40 /* Line Interrupt Position Conf. */ +#define LTDC_CPSR 0x44 /* Current Position Status */ +#define LTDC_CDSR 0x48 /* Current Display Status */ + +/* LTDC layer 1 registers */ +#define LTDC_L1LC1R 0x80 /* L1 Layer Configuration 1 */ +#define LTDC_L1LC2R 0x84 /* L1 Layer Configuration 2 */ +#define LTDC_L1CR 0x84 /* L1 Control */ +#define LTDC_L1WHPCR 0x88 /* L1 Window Hor Position Config */ +#define LTDC_L1WVPCR 0x8C /* L1 Window Vert Position Config */ +#define LTDC_L1CKCR 0x90 /* L1 Color Keying Configuration */ +#define LTDC_L1PFCR 0x94 /* L1 Pixel Format Configuration */ +#define LTDC_L1CACR 0x98 /* L1 Constant Alpha Config */ +#define LTDC_L1DCCR 0x9C /* L1 Default Color Configuration */ +#define LTDC_L1BFCR 0xA0 /* L1 Blend Factors Configuration */ +#define LTDC_L1FBBCR 0xA4 /* L1 FrameBuffer Bus Control */ +#define LTDC_L1AFBCR 0xA8 /* L1 AuxFB Control */ +#define LTDC_L1CFBAR 0xAC /* L1 Color FrameBuffer Address */ +#define LTDC_L1CFBLR 0xB0 /* L1 Color FrameBuffer Length */ +#define LTDC_L1CFBLNR 0xB4 /* L1 Color FrameBuffer Line Nb */ +#define LTDC_L1AFBAR 0xB8 /* L1 AuxFB Address */ +#define LTDC_L1AFBLR 0xBC /* L1 AuxFB Length */ +#define LTDC_L1AFBLNR 0xC0 /* L1 AuxFB Line Number */ +#define LTDC_L1CLUTWR 0xC4 /* L1 CLUT Write */ + +/* Bit definitions */ +#define SSCR_VSH GENMASK(10, 0) /* Vertical Synchronization Height */ +#define SSCR_HSW GENMASK(27, 16) /* Horizontal Synchronization Width */ + +#define BPCR_AVBP GENMASK(10, 0) /* Accumulated Vertical Back Porch */ +#define BPCR_AHBP GENMASK(27, 16) /* Accumulated Horizontal Back Porch */ + +#define AWCR_AAH GENMASK(10, 0) /* Accumulated Active Height */ +#define AWCR_AAW GENMASK(27, 16) /* Accumulated Active Width */ + +#define TWCR_TOTALH GENMASK(10, 0) /* TOTAL Height */ +#define TWCR_TOTALW GENMASK(27, 16) /* TOTAL Width */ + +#define GCR_LTDCEN BIT(0) /* LTDC ENable */ +#define GCR_DEN BIT(16) /* Dither ENable */ +#define GCR_PCPOL BIT(28) /* Pixel Clock POLarity-Inverted */ +#define GCR_DEPOL BIT(29) /* Data Enable POLarity-High */ +#define GCR_VSPOL BIT(30) /* Vertical Synchro POLarity-High */ +#define GCR_HSPOL BIT(31) /* Horizontal Synchro POLarity-High */ + +#define GC1R_WBCH GENMASK(3, 0) /* Width of Blue CHannel output */ +#define GC1R_WGCH GENMASK(7, 4) /* Width of Green Channel output */ +#define GC1R_WRCH GENMASK(11, 8) /* Width of Red Channel output */ +#define GC1R_PBEN BIT(12) /* Precise Blending ENable */ +#define GC1R_DT GENMASK(15, 14) /* Dithering Technique */ +#define GC1R_GCT GENMASK(19, 17) /* Gamma Correction Technique */ +#define GC1R_SHREN BIT(21) /* SHadow Registers ENabled */ +#define GC1R_BCP BIT(22) /* Background Colour Programmable */ +#define GC1R_BBEN BIT(23) /* Background Blending ENabled */ +#define GC1R_LNIP BIT(24) /* Line Number IRQ Position */ +#define GC1R_TP BIT(25) /* Timing Programmable */ +#define GC1R_IPP BIT(26) /* IRQ Polarity Programmable */ +#define GC1R_SPP BIT(27) /* Sync Polarity Programmable */ +#define GC1R_DWP BIT(28) /* Dither Width Programmable */ +#define GC1R_STREN BIT(29) /* STatus Registers ENabled */ +#define GC1R_BMEN BIT(31) /* Blind Mode ENabled */ + +#define GC2R_EDCA BIT(0) /* External Display Control Ability */ +#define GC2R_STSAEN BIT(1) /* Slave Timing Sync Ability ENabled */ +#define GC2R_DVAEN BIT(2) /* Dual-View Ability ENabled */ +#define GC2R_DPAEN BIT(3) /* Dual-Port Ability ENabled */ +#define GC2R_BW GENMASK(6, 4) /* Bus Width (log2 of nb of bytes) */ +#define GC2R_EDCEN BIT(7) /* External Display Control ENabled */ + +#define SRCR_IMR BIT(0) /* IMmediate Reload */ +#define SRCR_VBR BIT(1) /* Vertical Blanking Reload */ + +#define LXCR_LEN BIT(0) /* Layer ENable */ +#define LXCR_COLKEN BIT(1) /* Color Keying Enable */ +#define LXCR_CLUTEN BIT(4) /* Color Look-Up Table ENable */ + +#define LXWHPCR_WHSTPOS GENMASK(11, 0) /* Window Horizontal StarT POSition */ +#define LXWHPCR_WHSPPOS GENMASK(27, 16) /* Window Horizontal StoP POSition */ + +#define LXWVPCR_WVSTPOS GENMASK(10, 0) /* Window Vertical StarT POSition */ +#define LXWVPCR_WVSPPOS GENMASK(26, 16) /* Window Vertical StoP POSition */ + +#define LXPFCR_PF GENMASK(2, 0) /* Pixel Format */ + +#define LXCACR_CONSTA GENMASK(7, 0) /* CONSTant Alpha */ + +#define LXBFCR_BF2 GENMASK(2, 0) /* Blending Factor 2 */ +#define LXBFCR_BF1 GENMASK(10, 8) /* Blending Factor 1 */ + +#define LXCFBLR_CFBLL GENMASK(12, 0) /* Color Frame Buffer Line Length */ +#define LXCFBLR_CFBP GENMASK(28, 16) /* Color Frame Buffer Pitch in bytes */ + +#define LXCFBLNR_CFBLN GENMASK(10, 0) /* Color Frame Buffer Line Number */ + +#define BF1_PAXCA 0x600 /* Pixel Alpha x Constant Alpha */ +#define BF2_1PAXCA 0x007 /* 1 - (Pixel Alpha x Constant Alpha) */ + +enum stm32_ltdc_pix_fmt { + PF_ARGB8888 = 0, + PF_RGB888, + PF_RGB565, + PF_ARGB1555, + PF_ARGB4444, + PF_L8, + PF_AL44, + PF_AL88 +}; + +/* TODO add more color format support */ +static u32 stm32_ltdc_get_pixel_format(enum video_log2_bpp l2bpp) +{ + enum stm32_ltdc_pix_fmt pf; + + switch (l2bpp) { + case VIDEO_BPP16: + pf = PF_RGB565; + break; + + case VIDEO_BPP1: + case VIDEO_BPP2: + case VIDEO_BPP4: + case VIDEO_BPP8: + case VIDEO_BPP32: + default: + debug("%s: warning %dbpp not supported yet, %dbpp instead\n", + __func__, VNBITS(l2bpp), VNBITS(VIDEO_BPP16)); + pf = PF_RGB565; + break; + } + + debug("%s: %d bpp -> ltdc pf %d\n", __func__, VNBITS(l2bpp), pf); + + return (u32)pf; +} + +static void stm32_ltdc_enable(struct stm32_ltdc_priv *priv) +{ + /* Reload configuration immediately & enable LTDC */ + setbits_le32(priv->regs + LTDC_SRCR, SRCR_IMR); + setbits_le32(priv->regs + LTDC_GCR, GCR_LTDCEN); +} + +static void stm32_ltdc_set_mode(struct stm32_ltdc_priv *priv) +{ + void __iomem *regs = priv->regs; + struct display_timing *timing = &priv->timing; + u32 hsync, vsync, acc_hbp, acc_vbp, acc_act_w, acc_act_h; + u32 total_w, total_h; + u32 val; + + /* Convert video timings to ltdc timings */ + hsync = timing->hsync_len.typ - 1; + vsync = timing->vsync_len.typ - 1; + acc_hbp = hsync + timing->hback_porch.typ; + acc_vbp = vsync + timing->vback_porch.typ; + acc_act_w = acc_hbp + timing->hactive.typ; + acc_act_h = acc_vbp + timing->vactive.typ; + total_w = acc_act_w + timing->hfront_porch.typ; + total_h = acc_act_h + timing->vfront_porch.typ; + + /* Synchronization sizes */ + val = (hsync << 16) | vsync; + clrsetbits_le32(regs + LTDC_SSCR, SSCR_VSH | SSCR_HSW, val); + + /* Accumulated back porch */ + val = (acc_hbp << 16) | acc_vbp; + clrsetbits_le32(regs + LTDC_BPCR, BPCR_AVBP | BPCR_AHBP, val); + + /* Accumulated active width */ + val = (acc_act_w << 16) | acc_act_h; + clrsetbits_le32(regs + LTDC_AWCR, AWCR_AAW | AWCR_AAH, val); + + /* Total width & height */ + val = (total_w << 16) | total_h; + clrsetbits_le32(regs + LTDC_TWCR, TWCR_TOTALH | TWCR_TOTALW, val); + + /* Signal polarities */ + val = 0; + debug("%s: timing->flags 0x%08x\n", __func__, timing->flags); + if (timing->flags & DISPLAY_FLAGS_HSYNC_HIGH) + val |= GCR_HSPOL; + if (timing->flags & DISPLAY_FLAGS_VSYNC_HIGH) + val |= GCR_VSPOL; + if (timing->flags & DISPLAY_FLAGS_DE_HIGH) + val |= GCR_DEPOL; + if (timing->flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE) + val |= GCR_PCPOL; + clrsetbits_le32(regs + LTDC_GCR, + GCR_HSPOL | GCR_VSPOL | GCR_DEPOL | GCR_PCPOL, val); + + /* Overall background color */ + writel(priv->bg_col_argb, priv->regs + LTDC_BCCR); +} + +static void stm32_ltdc_set_layer1(struct stm32_ltdc_priv *priv, ulong fb_addr) +{ + void __iomem *regs = priv->regs; + u32 x0, x1, y0, y1; + u32 pitch_in_bytes; + u32 line_length; + u32 bus_width; + u32 val, tmp, bpp; + + x0 = priv->crop_x; + x1 = priv->crop_x + priv->crop_w - 1; + y0 = priv->crop_y; + y1 = priv->crop_y + priv->crop_h - 1; + + /* Horizontal start and stop position */ + tmp = (readl(regs + LTDC_BPCR) & BPCR_AHBP) >> 16; + val = ((x1 + 1 + tmp) << 16) + (x0 + 1 + tmp); + clrsetbits_le32(regs + LTDC_L1WHPCR, LXWHPCR_WHSTPOS | LXWHPCR_WHSPPOS, + val); + + /* Vertical start & stop position */ + tmp = readl(regs + LTDC_BPCR) & BPCR_AVBP; + val = ((y1 + 1 + tmp) << 16) + (y0 + 1 + tmp); + clrsetbits_le32(regs + LTDC_L1WVPCR, LXWVPCR_WVSTPOS | LXWVPCR_WVSPPOS, + val); + + /* Layer background color */ + writel(priv->bg_col_argb, regs + LTDC_L1DCCR); + + /* Color frame buffer pitch in bytes & line length */ + bpp = VNBITS(priv->l2bpp); + pitch_in_bytes = priv->crop_w * (bpp >> 3); + bus_width = 8 << ((readl(regs + LTDC_GC2R) & GC2R_BW) >> 4); + line_length = ((bpp >> 3) * priv->crop_w) + (bus_width >> 3) - 1; + val = (pitch_in_bytes << 16) | line_length; + clrsetbits_le32(regs + LTDC_L1CFBLR, LXCFBLR_CFBLL | LXCFBLR_CFBP, val); + + /* Pixel format */ + val = stm32_ltdc_get_pixel_format(priv->l2bpp); + clrsetbits_le32(regs + LTDC_L1PFCR, LXPFCR_PF, val); + + /* Constant alpha value */ + clrsetbits_le32(regs + LTDC_L1CACR, LXCACR_CONSTA, priv->alpha); + + /* Blending factors */ + clrsetbits_le32(regs + LTDC_L1BFCR, LXBFCR_BF2 | LXBFCR_BF1, + BF1_PAXCA | BF2_1PAXCA); + + /* Frame buffer line number */ + clrsetbits_le32(regs + LTDC_L1CFBLNR, LXCFBLNR_CFBLN, priv->crop_h); + + /* Frame buffer address */ + writel(fb_addr, regs + LTDC_L1CFBAR); + + /* Enable layer 1 */ + setbits_le32(priv->regs + LTDC_L1CR, LXCR_LEN); +} + +static int stm32_ltdc_probe(struct udevice *dev) +{ + struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev); + struct video_priv *uc_priv = dev_get_uclass_priv(dev); + struct stm32_ltdc_priv *priv = dev_get_priv(dev); + struct udevice *panel; + struct clk pclk, pxclk; + int ret; + + priv->regs = (void *)dev_read_addr(dev); + if ((fdt_addr_t)priv->regs == FDT_ADDR_T_NONE) { + debug("%s: ltdc dt register address error\n", __func__); + return -EINVAL; + } + + ret = uclass_first_device(UCLASS_PANEL, &panel); + if (ret) { + debug("%s: panel device error %d\n", __func__, ret); + return ret; + } + + ret = panel_enable_backlight(panel); + if (ret) { + debug("%s: panel %s enable backlight error %d\n", + __func__, panel->name, ret); + return ret; + } + + ret = fdtdec_decode_display_timing(gd->fdt_blob, dev_of_offset(dev), + 0, &priv->timing); + if (ret) { + debug("%s: decode display timing error %d\n", __func__, ret); + return -EINVAL; + } + + ret = clk_get_by_name(dev, "pclk", &pclk); + if (ret) { + debug("%s: peripheral clock get error %d\n", __func__, ret); + return ret; + } + + ret = clk_enable(&pclk); + if (ret) { + debug("%s: peripheral clock enable error %d\n", __func__, ret); + return ret; + } + + /* Verify pixel clock value if any & inform user accordingly */ + ret = clk_get_by_name(dev, "pxclk", &pxclk); + if (!ret) { + if (clk_get_rate(&pxclk) != priv->timing.pixelclock.typ) + printf("Warning: please adjust ltdc pixel clock\n"); + } + + /* TODO Below parameters are hard-coded for the moment... */ + priv->l2bpp = VIDEO_BPP16; + priv->bg_col_argb = 0xFFFFFFFF; /* white no transparency */ + priv->crop_x = 0; + priv->crop_y = 0; + priv->crop_w = priv->timing.hactive.typ; + priv->crop_h = priv->timing.vactive.typ; + priv->alpha = 0xFF; + + debug("%s: %dx%d %dbpp frame buffer at 0x%lx\n", __func__, + priv->timing.hactive.typ, priv->timing.vactive.typ, + VNBITS(priv->l2bpp), uc_plat->base); + debug("%s: crop %d,%d %dx%d bg 0x%08x alpha %d\n", __func__, + priv->crop_x, priv->crop_y, priv->crop_w, priv->crop_h, + priv->bg_col_argb, priv->alpha); + + /* Configure & start LTDC */ + stm32_ltdc_set_mode(priv); + stm32_ltdc_set_layer1(priv, uc_plat->base); + stm32_ltdc_enable(priv); + + uc_priv->xsize = priv->timing.hactive.typ; + uc_priv->ysize = priv->timing.vactive.typ; + uc_priv->bpix = priv->l2bpp; + + video_set_flush_dcache(dev, true); + + return 0; +} + +static int stm32_ltdc_bind(struct udevice *dev) +{ + struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev); + + uc_plat->size = CONFIG_VIDEO_STM32_MAX_XRES * + CONFIG_VIDEO_STM32_MAX_YRES * + (CONFIG_VIDEO_STM32_MAX_BPP >> 3); + debug("%s: frame buffer max size %d bytes\n", __func__, uc_plat->size); + + return 0; +} + +static const struct udevice_id stm32_ltdc_ids[] = { + { .compatible = "st,stm32-ltdc" }, + { } +}; + +U_BOOT_DRIVER(stm32_ltdc) = { + .name = "stm32_ltdc", + .id = UCLASS_VIDEO, + .of_match = stm32_ltdc_ids, + .probe = stm32_ltdc_probe, + .bind = stm32_ltdc_bind, + .priv_auto_alloc_size = sizeof(struct stm32_ltdc_priv), +}; diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c index 3036e3a1f2..dfa39b0d1b 100644 --- a/drivers/video/video-uclass.c +++ b/drivers/video/video-uclass.c @@ -199,7 +199,9 @@ static int video_post_probe(struct udevice *dev) #else priv->colour_bg = 0xffffff; #endif - video_clear(dev); + + if (!CONFIG_IS_ENABLED(NO_FB_CLEAR)) + video_clear(dev); /* * Create a text console device. For now we always do this, although diff --git a/dts/Kconfig b/dts/Kconfig index b4b7ddc144..4ee0510943 100644 --- a/dts/Kconfig +++ b/dts/Kconfig @@ -5,11 +5,15 @@ config SUPPORT_OF_CONTROL bool +config DTC + bool + menu "Device Tree Control" depends on SUPPORT_OF_CONTROL config OF_CONTROL bool "Run-time configuration via Device Tree" + select DTC help This feature provides for run-time configuration of U-Boot via a flattened device tree. @@ -166,3 +170,12 @@ config TPL_OF_PLATDATA information. endmenu + +config MKIMAGE_DTC_PATH + string "Path to dtc binary for use within mkimage" + default "dtc" + help + The mkimage host tool will, in order to generate FIT images make + calls to the dtc application in order to create the output. In + some cases the system dtc may not support all required features + and the path to a different version should be given here. diff --git a/fs/fat/fat.c b/fs/fat/fat.c index f0284398b4..36a309c73c 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -1034,24 +1034,27 @@ int file_fat_detectfs(void) int fat_exists(const char *filename) { fsdata fsdata; - fat_itr itrblock, *itr = &itrblock; + fat_itr *itr; int ret; + itr = malloc(sizeof(fat_itr)); ret = fat_itr_root(itr, &fsdata); if (ret) return 0; ret = fat_itr_resolve(itr, filename, TYPE_ANY); free(fsdata.fatbuf); + free(itr); return ret == 0; } int fat_size(const char *filename, loff_t *size) { fsdata fsdata; - fat_itr itrblock, *itr = &itrblock; + fat_itr *itr; int ret; + itr = malloc(sizeof(fat_itr)); ret = fat_itr_root(itr, &fsdata); if (ret) return ret; @@ -1072,8 +1075,9 @@ int fat_size(const char *filename, loff_t *size) } *size = FAT2CPU32(itr->dent->size); -out: free(fsdata.fatbuf); +out: + free(itr); return ret; } @@ -1081,9 +1085,10 @@ int file_fat_read_at(const char *filename, loff_t pos, void *buffer, loff_t maxsize, loff_t *actread) { fsdata fsdata; - fat_itr itrblock, *itr = &itrblock; + fat_itr *itr; int ret; + itr = malloc(sizeof(fat_itr)); ret = fat_itr_root(itr, &fsdata); if (ret) return ret; @@ -1097,6 +1102,7 @@ int file_fat_read_at(const char *filename, loff_t pos, void *buffer, out: free(fsdata.fatbuf); + free(itr); return ret; } diff --git a/include/configs/adp-ae3xx.h b/include/configs/adp-ae3xx.h index f47e45b433..6946029333 100644 --- a/include/configs/adp-ae3xx.h +++ b/include/configs/adp-ae3xx.h @@ -23,8 +23,7 @@ #define CONFIG_CMDLINE_EDITING #define CONFIG_PANIC_HANG -#define CONFIG_SYS_ICACHE_OFF -#define CONFIG_SYS_DCACHE_OFF +#define CONFIG_ARCH_MAP_SYSMEM #define CONFIG_BOOTP_SEND_HOSTNAME #define CONFIG_BOOTP_SERVERIP @@ -221,14 +220,25 @@ /* max number of sectors on one chip */ #define CONFIG_FLASH_SECTOR_SIZE (0x10000*2) -#define CONFIG_ENV_SECT_SIZE CONFIG_FLASH_SECTOR_SIZE #define CONFIG_SYS_MAX_FLASH_SECT 512 /* environments */ -#define CONFIG_ENV_ADDR (CONFIG_SYS_MONITOR_BASE + 0x140000) +#define CONFIG_ENV_SPI_BUS 0 +#define CONFIG_ENV_SPI_CS 0 +#define CONFIG_ENV_SPI_MAX_HZ 50000000 +#define CONFIG_ENV_SPI_MODE 0 +#define CONFIG_ENV_SECT_SIZE 0x1000 +#define CONFIG_ENV_OFFSET 0x140000 #define CONFIG_ENV_SIZE 8192 #define CONFIG_ENV_OVERWRITE + +/* SPI FLASH */ +#define CONFIG_SF_DEFAULT_BUS 0 +#define CONFIG_SF_DEFAULT_CS 0 +#define CONFIG_SF_DEFAULT_SPEED 1000000 +#define CONFIG_SF_DEFAULT_MODE 0 + /* * For booting Linux, the board info and command line data * have to be in the first 16 MB of memory, since this is diff --git a/include/configs/adp-ag101p.h b/include/configs/adp-ag101p.h index bf713b806d..fad4d308e0 100644 --- a/include/configs/adp-ag101p.h +++ b/include/configs/adp-ag101p.h @@ -22,8 +22,7 @@ #define CONFIG_CMDLINE_EDITING -#define CONFIG_SYS_ICACHE_OFF -#define CONFIG_SYS_DCACHE_OFF +#define CONFIG_ARCH_MAP_SYSMEM #define CONFIG_BOOTP_SEND_HOSTNAME #define CONFIG_BOOTP_SERVERIP diff --git a/include/configs/am3517_evm.h b/include/configs/am3517_evm.h index 708a98f827..adb33a9e3e 100644 --- a/include/configs/am3517_evm.h +++ b/include/configs/am3517_evm.h @@ -21,6 +21,7 @@ * header. That is 0x800FFFC0--0x80100000 should not be used for any * other needs. */ + #define CONFIG_SYS_TEXT_BASE 0x80100000 #define CONFIG_SYS_SPL_MALLOC_START 0x80208000 #define CONFIG_SYS_SPL_MALLOC_SIZE 0x100000 @@ -33,16 +34,6 @@ /* Hardware drivers */ -/* NS16550 Configuration */ -#define CONFIG_SYS_NS16550_SERIAL -#define CONFIG_SYS_NS16550_REG_SIZE (-4) - -/* select serial console configuration */ -#define CONFIG_CONS_INDEX 3 -#define CONFIG_SYS_NS16550_COM3 OMAP34XX_UART3 -#define CONFIG_SERIAL3 3 /* UART3 on AM3517 EVM */ - - /* allow to overwrite serial and ethaddr */ #define CONFIG_ENV_OVERWRITE @@ -72,7 +63,6 @@ #endif /* CONFIG_USB_MUSB_AM35X */ /* I2C */ -#define CONFIG_SYS_I2C #define CONFIG_SYS_OMAP24_I2C_SPEED 100000 #define CONFIG_SYS_OMAP24_I2C_SLAVE 1 @@ -250,8 +240,6 @@ #define CONFIG_SPL_FRAMEWORK #undef CONFIG_SPL_TEXT_BASE #define CONFIG_SPL_TEXT_BASE 0x40200000 -#define CONFIG_SPL_MAX_SIZE (SRAM_SCRATCH_SPACE_ADDR - \ - CONFIG_SPL_TEXT_BASE) #undef CONFIG_SPL_BSS_START_ADDR #define CONFIG_SPL_BSS_START_ADDR 0x80000000 diff --git a/include/configs/am43xx_evm.h b/include/configs/am43xx_evm.h index b84f6e3480..7ee69b0c78 100644 --- a/include/configs/am43xx_evm.h +++ b/include/configs/am43xx_evm.h @@ -326,4 +326,9 @@ #define NANDBOOT #endif /* CONFIG_NAND */ +#if defined(CONFIG_TI_SECURE_DEVICE) +/* Avoid relocating onto firewalled area at end of DRAM */ +#define CONFIG_PRAM (64 * 1024) +#endif /* CONFIG_TI_SECURE_DEVICE */ + #endif /* __CONFIG_AM43XX_EVM_H */ diff --git a/include/configs/am57xx_evm.h b/include/configs/am57xx_evm.h index 0c70c53050..bf555ccdc2 100644 --- a/include/configs/am57xx_evm.h +++ b/include/configs/am57xx_evm.h @@ -44,7 +44,8 @@ #define PARTS_DEFAULT \ /* Linux partitions */ \ "uuid_disk=${uuid_gpt_disk};" \ - "name=rootfs,start=2MiB,size=-,uuid=${uuid_gpt_rootfs}\0" \ + "name=bootloader,start=384K,size=1792K,uuid=${uuid_gpt_bootloader};" \ + "name=rootfs,start=2688K,size=-,uuid=${uuid_gpt_rootfs}\0" \ /* Android partitions */ \ "partitions_android=" \ "uuid_disk=${uuid_gpt_disk};" \ diff --git a/include/configs/da850evm.h b/include/configs/da850evm.h index c05c64cad7..821b1fe534 100644 --- a/include/configs/da850evm.h +++ b/include/configs/da850evm.h @@ -21,6 +21,16 @@ #endif /* +* Disable DM_* for SPL build and can be re-enabled after adding +* DM support in SPL +*/ +#ifdef CONFIG_SPL_BUILD +#undef CONFIG_DM_SPI +#undef CONFIG_DM_SPI_FLASH +#undef CONFIG_DM_I2C +#undef CONFIG_DM_I2C_COMPAT +#endif +/* * SoC Configuration */ #define CONFIG_MACH_DAVINCI_DA850_EVM @@ -130,18 +140,23 @@ /* * Serial Driver info */ + +#if defined(CONFIG_SPL_BUILD) || defined(CONFIG_DIRECT_NOR_BOOT) #define CONFIG_SYS_NS16550_SERIAL #define CONFIG_SYS_NS16550_REG_SIZE -4 /* NS16550 register size */ #define CONFIG_SYS_NS16550_COM1 DAVINCI_UART2_BASE /* Base address of UART2 */ +#endif #define CONFIG_SYS_NS16550_CLK clk_get(DAVINCI_UART2_CLKID) #define CONFIG_CONS_INDEX 1 /* use UART0 for console */ #define CONFIG_SPI #define CONFIG_DAVINCI_SPI -#define CONFIG_SYS_SPI_BASE DAVINCI_SPI1_BASE #define CONFIG_SYS_SPI_CLK clk_get(DAVINCI_SPI1_CLKID) +#ifdef CONFIG_SPL_BUILD +#define CONFIG_SYS_SPI_BASE DAVINCI_SPI1_BASE #define CONFIG_SF_DEFAULT_SPEED 30000000 #define CONFIG_ENV_SPI_MAX_HZ CONFIG_SF_DEFAULT_SPEED +#endif #ifdef CONFIG_USE_SPIFLASH #define CONFIG_SPL_SPI_LOAD @@ -152,11 +167,10 @@ /* * I2C Configuration */ -#define CONFIG_SYS_I2C +#ifndef CONFIG_SPL_BUILD #define CONFIG_SYS_I2C_DAVINCI -#define CONFIG_SYS_DAVINCI_I2C_SPEED 25000 -#define CONFIG_SYS_DAVINCI_I2C_SLAVE 10 /* Bogus, master-only in U-Boot */ #define CONFIG_SYS_I2C_EXPANDER_ADDR 0x20 +#endif /* * Flash & Environment @@ -234,6 +248,17 @@ #define CONFIG_ENV_SIZE (64 << 10) #define CONFIG_ENV_OFFSET (512 << 10) #define CONFIG_ENV_SECT_SIZE (64 << 10) +#ifdef CONFIG_SPL_BUILD +#undef CONFIG_SPI_FLASH_MTD +#endif +#define CONFIG_MTD_DEVICE /* needed for mtdparts commands */ +#define CONFIG_MTD_PARTITIONS /* required for UBI partition support */ +#define MTDIDS_DEFAULT "nor0=spi0.0" +#define MTDPARTS_DEFAULT "mtdparts=spi0.0:"\ + "512k(u-boot.ais),"\ + "64k(u-boot-env),"\ + "7552k(kernel-spare),"\ + "64k(MAC-Address)" #endif /* @@ -257,7 +282,29 @@ #define CONFIG_CMDLINE_TAG #define CONFIG_REVISION_TAG #define CONFIG_SETUP_MEMORY_TAGS -#define CONFIG_EXTRA_ENV_SETTINGS "hwconfig=dsp:wake=yes" + +#define CONFIG_BOOTCOMMAND \ + "run envboot; " \ + "run mmcboot; " + +#define DEFAULT_LINUX_BOOT_ENV \ + "loadaddr=0xc0700000\0" \ + "fdtaddr=0xc0600000\0" \ + "scriptaddr=0xc0600000\0" + +#include <environment/ti/mmc.h> + +#define CONFIG_EXTRA_ENV_SETTINGS \ + DEFAULT_LINUX_BOOT_ENV \ + DEFAULT_MMC_TI_ARGS \ + "bootpart=0:2\0" \ + "bootdir=/boot\0" \ + "bootfile=zImage\0" \ + "fdtfile=da850-evm.dtb\0" \ + "boot_fdt=yes\0" \ + "boot_fit=0\0" \ + "console=ttyS2,115200n8\0" \ + "hwconfig=dsp:wake=yes" #ifdef CONFIG_CMD_BDI #define CONFIG_CLOCKS diff --git a/include/configs/dra7xx_evm.h b/include/configs/dra7xx_evm.h index 6c0fc35d3a..1555fc1b50 100644 --- a/include/configs/dra7xx_evm.h +++ b/include/configs/dra7xx_evm.h @@ -51,7 +51,8 @@ #define PARTS_DEFAULT \ /* Linux partitions */ \ "uuid_disk=${uuid_gpt_disk};" \ - "name=rootfs,start=2MiB,size=-,uuid=${uuid_gpt_rootfs}\0" \ + "name=bootloader,start=384K,size=1792K,uuid=${uuid_gpt_bootloader};" \ + "name=rootfs,start=2688K,size=-,uuid=${uuid_gpt_rootfs}\0" \ /* Android partitions */ \ "partitions_android=" \ "uuid_disk=${uuid_gpt_disk};" \ diff --git a/include/configs/ge_bx50v3.h b/include/configs/ge_bx50v3.h index a0468d204b..33f5101c14 100644 --- a/include/configs/ge_bx50v3.h +++ b/include/configs/ge_bx50v3.h @@ -299,4 +299,19 @@ #define CONFIG_SYS_I2C_MXC_I2C2 #define CONFIG_SYS_I2C_MXC_I2C3 +#define CONFIG_SYS_NUM_I2C_BUSES 9 +#define CONFIG_SYS_I2C_MAX_HOPS 1 +#define CONFIG_SYS_I2C_BUSES { {0, {I2C_NULL_HOP} }, \ + {0, {{I2C_MUX_PCA9547, 0x70, 0} } }, \ + {0, {{I2C_MUX_PCA9547, 0x70, 1} } }, \ + {0, {{I2C_MUX_PCA9547, 0x70, 2} } }, \ + {0, {{I2C_MUX_PCA9547, 0x70, 3} } }, \ + {0, {{I2C_MUX_PCA9547, 0x70, 4} } }, \ + {0, {{I2C_MUX_PCA9547, 0x70, 5} } }, \ + {0, {{I2C_MUX_PCA9547, 0x70, 6} } }, \ + {0, {{I2C_MUX_PCA9547, 0x70, 7} } }, \ + } + +#define CONFIG_BCH + #endif /* __GE_BX50V3_CONFIG_H */ diff --git a/include/configs/k2g_evm.h b/include/configs/k2g_evm.h index 1950740405..df81c09d86 100644 --- a/include/configs/k2g_evm.h +++ b/include/configs/k2g_evm.h @@ -38,7 +38,7 @@ "setenv name_fdt keystone-k2g-ice.dtb; " \ "else if test $name_fdt = undefined; then " \ "echo WARNING: Could not determine device tree to use;"\ - "fi;fi;fi;\0" \ + "fi;fi;fi; setenv fdtfile ${name_fdt}\0" \ "name_mon=skern-k2g.bin\0" \ "name_ubi=k2g-evm-ubifs.ubi\0" \ "name_uboot=u-boot-spi-k2g-evm.gph\0" \ diff --git a/include/configs/ls1043a_common.h b/include/configs/ls1043a_common.h index 002830c27e..1f9efffa56 100644 --- a/include/configs/ls1043a_common.h +++ b/include/configs/ls1043a_common.h @@ -22,7 +22,7 @@ #if (defined(CONFIG_SPL_BUILD) && defined(CONFIG_NAND_BOOT)) #define SPL_NO_MMC #endif -#if (defined(CONFIG_SPL_BUILD) && defined(CONFIG_SD_BOOT)) +#if (defined(CONFIG_SPL_BUILD) && defined(CONFIG_SD_BOOT_QSPI)) #define SPL_NO_IFC #endif diff --git a/include/configs/ls2080ardb.h b/include/configs/ls2080ardb.h index 145b285685..9e9979e1c7 100644 --- a/include/configs/ls2080ardb.h +++ b/include/configs/ls2080ardb.h @@ -18,7 +18,6 @@ #define CONFIG_QIXIS_I2C_ACCESS #endif #define CONFIG_SYS_I2C_EARLY_INIT -#define CONFIG_DISPLAY_BOARDINFO_LATE #endif #define I2C_MUX_CH_VOL_MONITOR 0xa @@ -289,19 +288,15 @@ unsigned long get_board_sys_clk(void); /* SPI */ #if defined(CONFIG_FSL_QSPI) || defined(CONFIG_FSL_DSPI) #define CONFIG_SPI_FLASH -#ifdef CONFIG_FSL_QSPI +#ifdef CONFIG_FSL_DSPI #define CONFIG_SPI_FLASH_STMICRO #endif #ifdef CONFIG_FSL_QSPI -#ifdef CONFIG_TARGET_LS2081ARDB -#define CONFIG_SPI_FLASH_STMICRO -#else #define CONFIG_SPI_FLASH_SPANSION #endif #define FSL_QSPI_FLASH_SIZE SZ_64M /* 64MB */ #define FSL_QSPI_FLASH_NUM 2 #endif -#endif /* * RTC configuration @@ -392,6 +387,7 @@ unsigned long get_board_sys_clk(void); "load_addr=0xa0000000\0" \ "kernel_size=0x2800000\0" \ "console=ttyAMA0,38400n8\0" \ + "mcmemsize=0x70000000\0" \ MC_INIT_CMD \ BOOTENV \ "boot_scripts=ls2088ardb_boot.scr\0" \ diff --git a/include/configs/mvebu_armada-37xx.h b/include/configs/mvebu_armada-37xx.h index 66c7001f09..1b2e0d71b4 100644 --- a/include/configs/mvebu_armada-37xx.h +++ b/include/configs/mvebu_armada-37xx.h @@ -84,7 +84,6 @@ /* * Ethernet Driver configuration */ -#define CONFIG_MVNETA /* Enable Marvell Gbe Controller Driver */ #define CONFIG_ENV_OVERWRITE /* ethaddr can be reprogrammed */ #define CONFIG_ARP_TIMEOUT 200 #define CONFIG_NET_RETRY_COUNT 50 diff --git a/include/configs/mx6cuboxi.h b/include/configs/mx6cuboxi.h index 4e12de1212..7fefe8edcb 100644 --- a/include/configs/mx6cuboxi.h +++ b/include/configs/mx6cuboxi.h @@ -106,6 +106,10 @@ "fi; " \ "fi\0" \ "findfdt="\ + "if test $board_name = HUMMINGBOARD2 && test $board_rev = MX6Q ; then " \ + "setenv fdtfile imx6q-hummingboard2.dtb; fi; " \ + "if test $board_name = HUMMINGBOARD2 && test $board_rev = MX6DL ; then " \ + "setenv fdtfile imx6dl-hummingboard2.dtb; fi; " \ "if test $board_name = HUMMINGBOARD && test $board_rev = MX6Q ; then " \ "setenv fdtfile imx6q-hummingboard.dtb; fi; " \ "if test $board_name = HUMMINGBOARD && test $board_rev = MX6DL ; then " \ diff --git a/include/configs/rk3368_common.h b/include/configs/rk3368_common.h index 8cba92c56d..8b4155f37c 100644 --- a/include/configs/rk3368_common.h +++ b/include/configs/rk3368_common.h @@ -51,6 +51,7 @@ #include <config_distro_bootcmd.h> #define CONFIG_EXTRA_ENV_SETTINGS \ + ENV_MEM_LAYOUT_SETTINGS \ BOOTENV #endif diff --git a/include/configs/rv1108_common.h b/include/configs/rv1108_common.h index 04779162d0..5ee45594a3 100644 --- a/include/configs/rv1108_common.h +++ b/include/configs/rv1108_common.h @@ -28,4 +28,7 @@ #define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_TEXT_BASE + 0x100000) #define CONFIG_SYS_LOAD_ADDR (CONFIG_SYS_SDRAM_BASE + 0x2000000) +/* rockchip ohci host driver */ +#define CONFIG_USB_OHCI_NEW +#define CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS 1 #endif diff --git a/include/configs/socfpga_common.h b/include/configs/socfpga_common.h index 9897e11b59..7b5417a75b 100644 --- a/include/configs/socfpga_common.h +++ b/include/configs/socfpga_common.h @@ -142,12 +142,10 @@ */ #ifdef CONFIG_NAND_DENALI #define CONFIG_SYS_MAX_NAND_DEVICE 1 -#define CONFIG_SYS_NAND_MAX_CHIPS 1 #define CONFIG_SYS_NAND_ONFI_DETECTION #define CONFIG_NAND_DENALI_ECC_SIZE 512 #define CONFIG_SYS_NAND_REGS_BASE SOCFPGA_NANDREGS_ADDRESS #define CONFIG_SYS_NAND_DATA_BASE SOCFPGA_NANDDATA_ADDRESS -#define CONFIG_SYS_NAND_BASE (CONFIG_SYS_NAND_DATA_BASE + 0x10) #endif /* diff --git a/include/configs/stih410-b2260.h b/include/configs/stih410-b2260.h index e07dd0e103..372c083601 100644 --- a/include/configs/stih410-b2260.h +++ b/include/configs/stih410-b2260.h @@ -45,4 +45,19 @@ #define CONFIG_SKIP_LOWLEVEL_INIT +/* USB Configs */ +#define CONFIG_USB_OHCI_NEW +#define CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS 2 + +#define CONFIG_USB_HOST_ETHER +#define CONFIG_USB_ETHER_ASIX +#define CONFIG_USB_ETHER_MCS7830 +#define CONFIG_USB_ETHER_SMSC95XX + +/* NET Configs */ +#define CONFIG_BOOTP_SUBNETMASK +#define CONFIG_BOOTP_GATEWAY +#define CONFIG_BOOTP_HOSTNAME +#define CONFIG_BOOTP_BOOTPATH + #endif /* __CONFIG_H */ diff --git a/include/configs/stm32h743-disco.h b/include/configs/stm32h743-disco.h new file mode 100644 index 0000000000..b0061cd0de --- /dev/null +++ b/include/configs/stm32h743-disco.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) STMicroelectronics SA 2017 + * Author(s): Patrice CHOTARD, <patrice.chotard@st.com> for STMicroelectronics. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +#include <config.h> + +#define CONFIG_SYS_FLASH_BASE 0x08000000 +#define CONFIG_SYS_INIT_SP_ADDR 0x30020000 +#define CONFIG_SYS_TEXT_BASE 0x08000000 + +/* + * Configuration of the external SDRAM memory + */ +#define CONFIG_NR_DRAM_BANKS 1 +#define CONFIG_SYS_RAM_BASE 0xD0000000 +#define CONFIG_SYS_SDRAM_BASE CONFIG_SYS_RAM_BASE +#define CONFIG_SYS_LOAD_ADDR 0xD0400000 +#define CONFIG_LOADADDR 0xD0400000 + +#define CONFIG_ENV_SIZE (8 << 10) + +#define CONFIG_SYS_ARCH_TIMER +#define CONFIG_SYS_HZ_CLOCK 250000000 + +#define CONFIG_CMDLINE_TAG +#define CONFIG_SETUP_MEMORY_TAGS +#define CONFIG_INITRD_TAG +#define CONFIG_REVISION_TAG + +#define CONFIG_SYS_MAXARGS 16 +#define CONFIG_SYS_MALLOC_LEN (1 * 1024 * 1024) + +#define CONFIG_BOOTARGS \ + "console=ttyS0,115200 earlyprintk consoleblank=0 ignore_loglevel" + +/* + * Command line configuration. + */ +#define CONFIG_SYS_LONGHELP +#define CONFIG_AUTO_COMPLETE +#define CONFIG_CMDLINE_EDITING +#define CONFIG_CMD_CACHE +#define CONFIG_BOARD_LATE_INIT + +#endif /* __CONFIG_H */ diff --git a/include/configs/stm32h743-eval.h b/include/configs/stm32h743-eval.h new file mode 100644 index 0000000000..b0061cd0de --- /dev/null +++ b/include/configs/stm32h743-eval.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) STMicroelectronics SA 2017 + * Author(s): Patrice CHOTARD, <patrice.chotard@st.com> for STMicroelectronics. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +#include <config.h> + +#define CONFIG_SYS_FLASH_BASE 0x08000000 +#define CONFIG_SYS_INIT_SP_ADDR 0x30020000 +#define CONFIG_SYS_TEXT_BASE 0x08000000 + +/* + * Configuration of the external SDRAM memory + */ +#define CONFIG_NR_DRAM_BANKS 1 +#define CONFIG_SYS_RAM_BASE 0xD0000000 +#define CONFIG_SYS_SDRAM_BASE CONFIG_SYS_RAM_BASE +#define CONFIG_SYS_LOAD_ADDR 0xD0400000 +#define CONFIG_LOADADDR 0xD0400000 + +#define CONFIG_ENV_SIZE (8 << 10) + +#define CONFIG_SYS_ARCH_TIMER +#define CONFIG_SYS_HZ_CLOCK 250000000 + +#define CONFIG_CMDLINE_TAG +#define CONFIG_SETUP_MEMORY_TAGS +#define CONFIG_INITRD_TAG +#define CONFIG_REVISION_TAG + +#define CONFIG_SYS_MAXARGS 16 +#define CONFIG_SYS_MALLOC_LEN (1 * 1024 * 1024) + +#define CONFIG_BOOTARGS \ + "console=ttyS0,115200 earlyprintk consoleblank=0 ignore_loglevel" + +/* + * Command line configuration. + */ +#define CONFIG_SYS_LONGHELP +#define CONFIG_AUTO_COMPLETE +#define CONFIG_CMDLINE_EDITING +#define CONFIG_CMD_CACHE +#define CONFIG_BOARD_LATE_INIT + +#endif /* __CONFIG_H */ diff --git a/include/configs/ti_armv7_keystone2.h b/include/configs/ti_armv7_keystone2.h index 2b2b85d085..53046a2110 100644 --- a/include/configs/ti_armv7_keystone2.h +++ b/include/configs/ti_armv7_keystone2.h @@ -270,7 +270,7 @@ "${bootdir}/${fit_bootfile}\0" \ "get_uboot_net=dhcp ${loadaddr} ${tftp_root}/${name_uboot}\0" \ "get_uboot_nfs=nfs ${loadaddr} ${nfs_root}/boot/${name_uboot}\0" \ - "burn_uboot_spi=sf probe; sf erase 0 0x80000; " \ + "burn_uboot_spi=sf probe; sf erase 0 0x90000; " \ "sf write ${loadaddr} 0 ${filesize}\0" \ "burn_uboot_nand=nand erase 0 0x100000; " \ "nand write ${loadaddr} 0 ${filesize}\0" \ diff --git a/include/configs/vyasa-rk3288.h b/include/configs/vyasa-rk3288.h new file mode 100644 index 0000000000..9d6c80f549 --- /dev/null +++ b/include/configs/vyasa-rk3288.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2017 Amarula Solutions + * + * Configuration settings for Amarula Vyasa RK3288. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +#define ROCKCHIP_DEVICE_SETTINGS +#include <configs/rk3288_common.h> + +#undef BOOT_TARGET_DEVICES + +#define BOOT_TARGET_DEVICES(func) \ + func(MMC, mmc, 1) \ + +#define CONFIG_SYS_MMC_ENV_DEV 1 +#undef CONFIG_CMD_USB_MASS_STORAGE + +#endif diff --git a/include/dm/read.h b/include/dm/read.h index 49d69c990f..8114037e97 100644 --- a/include/dm/read.h +++ b/include/dm/read.h @@ -113,6 +113,16 @@ fdt_addr_t dev_read_addr_index(struct udevice *dev, int index); fdt_addr_t dev_read_addr(struct udevice *dev); /** + * dev_read_addr_ptr() - Get the reg property of a device + * as a pointer + * + * @dev: Device to read from + * + * @return pointer or NULL if not found + */ +void *dev_read_addr_ptr(struct udevice *dev); + +/** * dev_read_addr_size() - get address and size from a device property * * This does no address translation. It simply reads an property that contains @@ -156,6 +166,29 @@ int dev_read_stringlist_search(struct udevice *dev, const char *property, const char *string); /** + * dev_read_string_index() - obtain an indexed string from a string list + * + * @dev: device to examine + * @propname: name of the property containing the string list + * @index: index of the string to return + * @out: return location for the string + * + * @return: + * length of string, if found or -ve error value if not found + */ +int dev_read_string_index(struct udevice *dev, const char *propname, int index, + const char **outp); + +/** + * dev_read_string_count() - find the number of strings in a string list + * + * @dev: device to examine + * @propname: name of the property containing the string list + * @return: + * number of strings in the list, or -ve error value if not found + */ +int dev_read_string_count(struct udevice *dev, const char *propname); +/** * dev_read_phandle_with_args() - Find a node pointed by phandle in a list * * This function is useful to parse lists of phandles and their arguments. @@ -417,6 +450,11 @@ static inline fdt_addr_t dev_read_addr(struct udevice *dev) return devfdt_get_addr(dev); } +static inline void *dev_read_addr_ptr(struct udevice *dev) +{ + return devfdt_get_addr_ptr(dev); +} + static inline fdt_addr_t dev_read_addr_size(struct udevice *dev, const char *propname, fdt_size_t *sizep) @@ -436,6 +474,19 @@ static inline int dev_read_stringlist_search(struct udevice *dev, return ofnode_stringlist_search(dev_ofnode(dev), propname, string); } +static inline int dev_read_string_index(struct udevice *dev, + const char *propname, int index, + const char **outp) +{ + return ofnode_read_string_index(dev_ofnode(dev), propname, index, outp); +} + +static inline int dev_read_string_count(struct udevice *dev, + const char *propname) +{ + return ofnode_read_string_count(dev_ofnode(dev), propname); +} + static inline int dev_read_phandle_with_args(struct udevice *dev, const char *list_name, const char *cells_name, int cell_count, int index, struct ofnode_phandle_args *out_args) diff --git a/include/dt-bindings/clock/stm32h7-clks.h b/include/dt-bindings/clock/stm32h7-clks.h new file mode 100644 index 0000000000..4d87e7ebc3 --- /dev/null +++ b/include/dt-bindings/clock/stm32h7-clks.h @@ -0,0 +1,167 @@ +/* SYS, CORE AND BUS CLOCKS */ +#define SYS_D1CPRE 0 +#define HCLK 1 +#define PCLK1 2 +#define PCLK2 3 +#define PCLK3 4 +#define PCLK4 5 +#define HSI_DIV 6 +#define HSE_1M 7 +#define I2S_CKIN 8 +#define CK_DSI_PHY 9 +#define HSE_CK 10 +#define LSE_CK 11 +#define CSI_KER_DIV122 12 +#define RTC_CK 13 +#define CPU_SYSTICK 14 + +/* OSCILLATOR BANK */ +#define OSC_BANK 18 +#define HSI_CK 18 +#define HSI_KER_CK 19 +#define CSI_CK 20 +#define CSI_KER_CK 21 +#define RC48_CK 22 +#define LSI_CK 23 + +/* MCLOCK BANK */ +#define MCLK_BANK 28 +#define PER_CK 28 +#define PLLSRC 29 +#define SYS_CK 30 +#define TRACEIN_CK 31 + +/* ODF BANK */ +#define ODF_BANK 32 +#define PLL1_P 32 +#define PLL1_Q 33 +#define PLL1_R 34 +#define PLL2_P 35 +#define PLL2_Q 36 +#define PLL2_R 37 +#define PLL3_P 38 +#define PLL3_Q 39 +#define PLL3_R 40 + +/* MCO BANK */ +#define MCO_BANK 41 +#define MCO1 41 +#define MCO2 42 + +/* PERIF BANK */ +#define PERIF_BANK 50 +#define D1SRAM1_CK 50 +#define ITCM_CK 51 +#define DTCM2_CK 52 +#define DTCM1_CK 53 +#define FLITF_CK 54 +#define JPGDEC_CK 55 +#define DMA2D_CK 56 +#define MDMA_CK 57 +#define USB2ULPI_CK 58 +#define USB1ULPI_CK 59 +#define ETH1RX_CK 60 +#define ETH1TX_CK 61 +#define ETH1MAC_CK 62 +#define ART_CK 63 +#define DMA2_CK 64 +#define DMA1_CK 65 +#define D2SRAM3_CK 66 +#define D2SRAM2_CK 67 +#define D2SRAM1_CK 68 +#define HASH_CK 69 +#define CRYPT_CK 70 +#define CAMITF_CK 71 +#define BKPRAM_CK 72 +#define HSEM_CK 73 +#define BDMA_CK 74 +#define CRC_CK 75 +#define GPIOK_CK 76 +#define GPIOJ_CK 77 +#define GPIOI_CK 78 +#define GPIOH_CK 79 +#define GPIOG_CK 80 +#define GPIOF_CK 81 +#define GPIOE_CK 82 +#define GPIOD_CK 83 +#define GPIOC_CK 84 +#define GPIOB_CK 85 +#define GPIOA_CK 86 +#define WWDG1_CK 87 +#define DAC12_CK 88 +#define WWDG2_CK 89 +#define TIM14_CK 90 +#define TIM13_CK 91 +#define TIM12_CK 92 +#define TIM7_CK 93 +#define TIM6_CK 94 +#define TIM5_CK 95 +#define TIM4_CK 96 +#define TIM3_CK 97 +#define TIM2_CK 98 +#define MDIOS_CK 99 +#define OPAMP_CK 100 +#define CRS_CK 101 +#define TIM17_CK 102 +#define TIM16_CK 103 +#define TIM15_CK 104 +#define TIM8_CK 105 +#define TIM1_CK 106 +#define TMPSENS_CK 107 +#define RTCAPB_CK 108 +#define VREF_CK 109 +#define COMP12_CK 110 +#define SYSCFG_CK 111 +/* must be equal to last peripheral clock index */ +#define LAST_PERIF_BANK SYSCFG_CK + +/* KERNEL BANK */ +#define KERN_BANK 120 +#define SDMMC1_CK 120 +#define QUADSPI_CK 121 +#define FMC_CK 122 +#define USB2OTG_CK 123 +#define USB1OTG_CK 124 +#define ADC12_CK 125 +#define SDMMC2_CK 126 +#define RNG_CK 127 +#define ADC3_CK 128 +#define DSI_CK 129 +#define LTDC_CK 130 +#define USART8_CK 131 +#define USART7_CK 132 +#define HDMICEC_CK 133 +#define I2C3_CK 134 +#define I2C2_CK 135 +#define I2C1_CK 136 +#define UART5_CK 137 +#define UART4_CK 138 +#define USART3_CK 139 +#define USART2_CK 140 +#define SPDIFRX_CK 141 +#define SPI3_CK 142 +#define SPI2_CK 143 +#define LPTIM1_CK 144 +#define FDCAN_CK 145 +#define SWP_CK 146 +#define HRTIM_CK 147 +#define DFSDM1_CK 148 +#define SAI3_CK 149 +#define SAI2_CK 150 +#define SAI1_CK 151 +#define SPI5_CK 152 +#define SPI4_CK 153 +#define SPI1_CK 154 +#define USART6_CK 155 +#define USART1_CK 156 +#define SAI4B_CK 157 +#define SAI4A_CK 158 +#define LPTIM5_CK 159 +#define LPTIM4_CK 160 +#define LPTIM3_CK 161 +#define LPTIM2_CK 162 +#define I2C4_CK 163 +#define SPI6_CK 164 +#define LPUART1_CK 165 + +#define STM32H7_MAX_CLKS 166 diff --git a/include/dt-bindings/memory/stm32-sdram.h b/include/dt-bindings/memory/stm32-sdram.h index 89b719af53..c2b911febf 100644 --- a/include/dt-bindings/memory/stm32-sdram.h +++ b/include/dt-bindings/memory/stm32-sdram.h @@ -18,7 +18,9 @@ #define CAS_1 0x1 #define CAS_2 0x2 #define CAS_3 0x3 +#define SDCLK_DIS 0x0 #define SDCLK_2 0x2 +#define SDCLK_3 0x3 #define RD_BURST_EN 0x1 #define RD_BURST_DIS 0x0 #define RD_PIPE_DL_0 0x0 @@ -26,12 +28,17 @@ #define RD_PIPE_DL_2 0x2 /* Timing = value +1 cycles */ +#define TMRD_1 (1 - 1) #define TMRD_2 (2 - 1) +#define TXSR_1 (1 - 1) #define TXSR_6 (6 - 1) +#define TRAS_1 (1 - 1) #define TRAS_4 (4 - 1) #define TRC_6 (6 - 1) +#define TWR_1 (1 - 1) #define TWR_2 (2 - 1) #define TRP_2 (2 - 1) +#define TRCD_1 (1 - 1) #define TRCD_2 (2 - 1) #endif diff --git a/include/dt-bindings/mfd/stm32h7-rcc.h b/include/dt-bindings/mfd/stm32h7-rcc.h new file mode 100644 index 0000000000..b96b3c3ac1 --- /dev/null +++ b/include/dt-bindings/mfd/stm32h7-rcc.h @@ -0,0 +1,138 @@ +/* + * This header provides constants for the STM32H7 RCC IP + */ + +#ifndef _DT_BINDINGS_MFD_STM32H7_RCC_H +#define _DT_BINDINGS_MFD_STM32H7_RCC_H + +/* AHB3 */ +#define STM32H7_RCC_AHB3_MDMA 0 +#define STM32H7_RCC_AHB3_DMA2D 4 +#define STM32H7_RCC_AHB3_JPGDEC 5 +#define STM32H7_RCC_AHB3_FMC 12 +#define STM32H7_RCC_AHB3_QUADSPI 14 +#define STM32H7_RCC_AHB3_SDMMC1 16 +#define STM32H7_RCC_AHB3_CPU1 31 + +#define STM32H7_AHB3_RESET(bit) (STM32H7_RCC_AHB3_##bit + (0x7C * 8)) + +/* AHB1 */ +#define STM32H7_RCC_AHB1_DMA1 0 +#define STM32H7_RCC_AHB1_DMA2 1 +#define STM32H7_RCC_AHB1_ADC12 5 +#define STM32H7_RCC_AHB1_ART 14 +#define STM32H7_RCC_AHB1_ETH1MAC 15 +#define STM32H7_RCC_AHB1_USB1OTG 25 +#define STM32H7_RCC_AHB1_USB2OTG 27 +#define STM32H7_RCC_AHB1_CPU2 31 + +#define STM32H7_AHB1_RESET(bit) (STM32H7_RCC_AHB1_##bit + (0x80 * 8)) + +/* AHB2 */ +#define STM32H7_RCC_AHB2_CAMITF 0 +#define STM32H7_RCC_AHB2_CRYPT 4 +#define STM32H7_RCC_AHB2_HASH 5 +#define STM32H7_RCC_AHB2_RNG 6 +#define STM32H7_RCC_AHB2_SDMMC2 9 + +#define STM32H7_AHB2_RESET(bit) (STM32H7_RCC_AHB2_##bit + (0x84 * 8)) + +/* AHB4 */ +#define STM32H7_RCC_AHB4_GPIOA 0 +#define STM32H7_RCC_AHB4_GPIOB 1 +#define STM32H7_RCC_AHB4_GPIOC 2 +#define STM32H7_RCC_AHB4_GPIOD 3 +#define STM32H7_RCC_AHB4_GPIOE 4 +#define STM32H7_RCC_AHB4_GPIOF 5 +#define STM32H7_RCC_AHB4_GPIOG 6 +#define STM32H7_RCC_AHB4_GPIOH 7 +#define STM32H7_RCC_AHB4_GPIOI 8 +#define STM32H7_RCC_AHB4_GPIOJ 9 +#define STM32H7_RCC_AHB4_GPIOK 10 +#define STM32H7_RCC_AHB4_CRC 19 +#define STM32H7_RCC_AHB4_BDMA 21 +#define STM32H7_RCC_AHB4_ADC3 24 +#define STM32H7_RCC_AHB4_HSEM 25 + +#define STM32H7_AHB4_RESET(bit) (STM32H7_RCC_AHB4_##bit + (0x88 * 8)) + + +/* APB3 */ +#define STM32H7_RCC_APB3_LTDC 3 +#define STM32H7_RCC_APB3_DSI 4 + +#define STM32H7_APB3_RESET(bit) (STM32H7_RCC_APB3_##bit + (0x8C * 8)) + +/* APB1L */ +#define STM32H7_RCC_APB1L_TIM2 0 +#define STM32H7_RCC_APB1L_TIM3 1 +#define STM32H7_RCC_APB1L_TIM4 2 +#define STM32H7_RCC_APB1L_TIM5 3 +#define STM32H7_RCC_APB1L_TIM6 4 +#define STM32H7_RCC_APB1L_TIM7 5 +#define STM32H7_RCC_APB1L_TIM12 6 +#define STM32H7_RCC_APB1L_TIM13 7 +#define STM32H7_RCC_APB1L_TIM14 8 +#define STM32H7_RCC_APB1L_LPTIM1 9 +#define STM32H7_RCC_APB1L_SPI2 14 +#define STM32H7_RCC_APB1L_SPI3 15 +#define STM32H7_RCC_APB1L_SPDIF_RX 16 +#define STM32H7_RCC_APB1L_USART2 17 +#define STM32H7_RCC_APB1L_USART3 18 +#define STM32H7_RCC_APB1L_UART4 19 +#define STM32H7_RCC_APB1L_UART5 20 +#define STM32H7_RCC_APB1L_I2C1 21 +#define STM32H7_RCC_APB1L_I2C2 22 +#define STM32H7_RCC_APB1L_I2C3 23 +#define STM32H7_RCC_APB1L_HDMICEC 27 +#define STM32H7_RCC_APB1L_DAC12 29 +#define STM32H7_RCC_APB1L_USART7 30 +#define STM32H7_RCC_APB1L_USART8 31 + +#define STM32H7_APB1L_RESET(bit) (STM32H7_RCC_APB1L_##bit + (0x90 * 8)) + +/* APB1H */ +#define STM32H7_RCC_APB1H_CRS 1 +#define STM32H7_RCC_APB1H_SWP 2 +#define STM32H7_RCC_APB1H_OPAMP 4 +#define STM32H7_RCC_APB1H_MDIOS 5 +#define STM32H7_RCC_APB1H_FDCAN 8 + +#define STM32H7_APB1H_RESET(bit) (STM32H7_RCC_APB1H_##bit + (0x94 * 8)) + +/* APB2 */ +#define STM32H7_RCC_APB2_TIM1 0 +#define STM32H7_RCC_APB2_TIM8 1 +#define STM32H7_RCC_APB2_USART1 4 +#define STM32H7_RCC_APB2_USART6 5 +#define STM32H7_RCC_APB2_SPI1 12 +#define STM32H7_RCC_APB2_SPI4 13 +#define STM32H7_RCC_APB2_TIM15 16 +#define STM32H7_RCC_APB2_TIM16 17 +#define STM32H7_RCC_APB2_TIM17 18 +#define STM32H7_RCC_APB2_SPI5 20 +#define STM32H7_RCC_APB2_SAI1 22 +#define STM32H7_RCC_APB2_SAI2 23 +#define STM32H7_RCC_APB2_SAI3 24 +#define STM32H7_RCC_APB2_DFSDM1 28 +#define STM32H7_RCC_APB2_HRTIM 29 + +#define STM32H7_APB2_RESET(bit) (STM32H7_RCC_APB2_##bit + (0x98 * 8)) + +/* APB4 */ +#define STM32H7_RCC_APB4_SYSCFG 1 +#define STM32H7_RCC_APB4_LPUART1 3 +#define STM32H7_RCC_APB4_SPI6 5 +#define STM32H7_RCC_APB4_I2C4 7 +#define STM32H7_RCC_APB4_LPTIM2 9 +#define STM32H7_RCC_APB4_LPTIM3 10 +#define STM32H7_RCC_APB4_LPTIM4 11 +#define STM32H7_RCC_APB4_LPTIM5 12 +#define STM32H7_RCC_APB4_COMP12 14 +#define STM32H7_RCC_APB4_VREF 15 +#define STM32H7_RCC_APB4_SAI4 21 +#define STM32H7_RCC_APB4_TMPSENS 26 + +#define STM32H7_APB4_RESET(bit) (STM32H7_RCC_APB4_##bit + (0x9C * 8)) + +#endif /* _DT_BINDINGS_MFD_STM32H7_RCC_H */ diff --git a/include/dt-bindings/pinctrl/stm32h7-pinfunc.h b/include/dt-bindings/pinctrl/stm32h7-pinfunc.h new file mode 100644 index 0000000000..cb673b5e8e --- /dev/null +++ b/include/dt-bindings/pinctrl/stm32h7-pinfunc.h @@ -0,0 +1,1612 @@ +#ifndef _DT_BINDINGS_STM32H7_PINFUNC_H +#define _DT_BINDINGS_STM32H7_PINFUNC_H + +#define STM32H7_PA0_FUNC_GPIO 0x0 +#define STM32H7_PA0_FUNC_TIM2_CH1_TIM2_ETR 0x2 +#define STM32H7_PA0_FUNC_TIM5_CH1 0x3 +#define STM32H7_PA0_FUNC_TIM8_ETR 0x4 +#define STM32H7_PA0_FUNC_TIM15_BKIN 0x5 +#define STM32H7_PA0_FUNC_USART2_CTS_NSS 0x8 +#define STM32H7_PA0_FUNC_UART4_TX 0x9 +#define STM32H7_PA0_FUNC_SDMMC2_CMD 0xa +#define STM32H7_PA0_FUNC_SAI2_SD_B 0xb +#define STM32H7_PA0_FUNC_ETH_MII_CRS 0xc +#define STM32H7_PA0_FUNC_EVENTOUT 0x10 +#define STM32H7_PA0_FUNC_ANALOG 0x11 + +#define STM32H7_PA1_FUNC_GPIO 0x100 +#define STM32H7_PA1_FUNC_TIM2_CH2 0x102 +#define STM32H7_PA1_FUNC_TIM5_CH2 0x103 +#define STM32H7_PA1_FUNC_LPTIM3_OUT 0x104 +#define STM32H7_PA1_FUNC_TIM15_CH1N 0x105 +#define STM32H7_PA1_FUNC_USART2_RTS 0x108 +#define STM32H7_PA1_FUNC_UART4_RX 0x109 +#define STM32H7_PA1_FUNC_QUADSPI_BK1_IO3 0x10a +#define STM32H7_PA1_FUNC_SAI2_MCK_B 0x10b +#define STM32H7_PA1_FUNC_ETH_MII_RX_CLK_ETH_RMII_REF_CLK 0x10c +#define STM32H7_PA1_FUNC_LCD_R2 0x10f +#define STM32H7_PA1_FUNC_EVENTOUT 0x110 +#define STM32H7_PA1_FUNC_ANALOG 0x111 + +#define STM32H7_PA2_FUNC_GPIO 0x200 +#define STM32H7_PA2_FUNC_TIM2_CH3 0x202 +#define STM32H7_PA2_FUNC_TIM5_CH3 0x203 +#define STM32H7_PA2_FUNC_LPTIM4_OUT 0x204 +#define STM32H7_PA2_FUNC_TIM15_CH1 0x205 +#define STM32H7_PA2_FUNC_USART2_TX 0x208 +#define STM32H7_PA2_FUNC_SAI2_SCK_B 0x209 +#define STM32H7_PA2_FUNC_ETH_MDIO 0x20c +#define STM32H7_PA2_FUNC_MDIOS_MDIO 0x20d +#define STM32H7_PA2_FUNC_LCD_R1 0x20f +#define STM32H7_PA2_FUNC_EVENTOUT 0x210 +#define STM32H7_PA2_FUNC_ANALOG 0x211 + +#define STM32H7_PA3_FUNC_GPIO 0x300 +#define STM32H7_PA3_FUNC_TIM2_CH4 0x302 +#define STM32H7_PA3_FUNC_TIM5_CH4 0x303 +#define STM32H7_PA3_FUNC_LPTIM5_OUT 0x304 +#define STM32H7_PA3_FUNC_TIM15_CH2 0x305 +#define STM32H7_PA3_FUNC_USART2_RX 0x308 +#define STM32H7_PA3_FUNC_LCD_B2 0x30a +#define STM32H7_PA3_FUNC_OTG_HS_ULPI_D0 0x30b +#define STM32H7_PA3_FUNC_ETH_MII_COL 0x30c +#define STM32H7_PA3_FUNC_LCD_B5 0x30f +#define STM32H7_PA3_FUNC_EVENTOUT 0x310 +#define STM32H7_PA3_FUNC_ANALOG 0x311 + +#define STM32H7_PA4_FUNC_GPIO 0x400 +#define STM32H7_PA4_FUNC_TIM5_ETR 0x403 +#define STM32H7_PA4_FUNC_SPI1_NSS_I2S1_WS 0x406 +#define STM32H7_PA4_FUNC_SPI3_NSS_I2S3_WS 0x407 +#define STM32H7_PA4_FUNC_USART2_CK 0x408 +#define STM32H7_PA4_FUNC_SPI6_NSS 0x409 +#define STM32H7_PA4_FUNC_OTG_HS_SOF 0x40d +#define STM32H7_PA4_FUNC_DCMI_HSYNC 0x40e +#define STM32H7_PA4_FUNC_LCD_VSYNC 0x40f +#define STM32H7_PA4_FUNC_EVENTOUT 0x410 +#define STM32H7_PA4_FUNC_ANALOG 0x411 + +#define STM32H7_PA5_FUNC_GPIO 0x500 +#define STM32H7_PA5_FUNC_TIM2_CH1_TIM2_ETR 0x502 +#define STM32H7_PA5_FUNC_TIM8_CH1N 0x504 +#define STM32H7_PA5_FUNC_SPI1_SCK_I2S1_CK 0x506 +#define STM32H7_PA5_FUNC_SPI6_SCK 0x509 +#define STM32H7_PA5_FUNC_OTG_HS_ULPI_CK 0x50b +#define STM32H7_PA5_FUNC_LCD_R4 0x50f +#define STM32H7_PA5_FUNC_EVENTOUT 0x510 +#define STM32H7_PA5_FUNC_ANALOG 0x511 + +#define STM32H7_PA6_FUNC_GPIO 0x600 +#define STM32H7_PA6_FUNC_TIM1_BKIN 0x602 +#define STM32H7_PA6_FUNC_TIM3_CH1 0x603 +#define STM32H7_PA6_FUNC_TIM8_BKIN 0x604 +#define STM32H7_PA6_FUNC_SPI1_MISO_I2S1_SDI 0x606 +#define STM32H7_PA6_FUNC_SPI6_MISO 0x609 +#define STM32H7_PA6_FUNC_TIM13_CH1 0x60a +#define STM32H7_PA6_FUNC_TIM8_BKIN_COMP12 0x60b +#define STM32H7_PA6_FUNC_MDIOS_MDC 0x60c +#define STM32H7_PA6_FUNC_TIM1_BKIN_COMP12 0x60d +#define STM32H7_PA6_FUNC_DCMI_PIXCLK 0x60e +#define STM32H7_PA6_FUNC_LCD_G2 0x60f +#define STM32H7_PA6_FUNC_EVENTOUT 0x610 +#define STM32H7_PA6_FUNC_ANALOG 0x611 + +#define STM32H7_PA7_FUNC_GPIO 0x700 +#define STM32H7_PA7_FUNC_TIM1_CH1N 0x702 +#define STM32H7_PA7_FUNC_TIM3_CH2 0x703 +#define STM32H7_PA7_FUNC_TIM8_CH1N 0x704 +#define STM32H7_PA7_FUNC_SPI1_MOSI_I2S1_SDO 0x706 +#define STM32H7_PA7_FUNC_SPI6_MOSI 0x709 +#define STM32H7_PA7_FUNC_TIM14_CH1 0x70a +#define STM32H7_PA7_FUNC_ETH_MII_RX_DV_ETH_RMII_CRS_DV 0x70c +#define STM32H7_PA7_FUNC_FMC_SDNWE 0x70d +#define STM32H7_PA7_FUNC_EVENTOUT 0x710 +#define STM32H7_PA7_FUNC_ANALOG 0x711 + +#define STM32H7_PA8_FUNC_GPIO 0x800 +#define STM32H7_PA8_FUNC_MCO1 0x801 +#define STM32H7_PA8_FUNC_TIM1_CH1 0x802 +#define STM32H7_PA8_FUNC_HRTIM_CHB2 0x803 +#define STM32H7_PA8_FUNC_TIM8_BKIN2 0x804 +#define STM32H7_PA8_FUNC_I2C3_SCL 0x805 +#define STM32H7_PA8_FUNC_USART1_CK 0x808 +#define STM32H7_PA8_FUNC_OTG_FS_SOF 0x80b +#define STM32H7_PA8_FUNC_UART7_RX 0x80c +#define STM32H7_PA8_FUNC_TIM8_BKIN2_COMP12 0x80d +#define STM32H7_PA8_FUNC_LCD_B3 0x80e +#define STM32H7_PA8_FUNC_LCD_R6 0x80f +#define STM32H7_PA8_FUNC_EVENTOUT 0x810 +#define STM32H7_PA8_FUNC_ANALOG 0x811 + +#define STM32H7_PA9_FUNC_GPIO 0x900 +#define STM32H7_PA9_FUNC_TIM1_CH2 0x902 +#define STM32H7_PA9_FUNC_HRTIM_CHC1 0x903 +#define STM32H7_PA9_FUNC_LPUART1_TX 0x904 +#define STM32H7_PA9_FUNC_I2C3_SMBA 0x905 +#define STM32H7_PA9_FUNC_SPI2_SCK_I2S2_CK 0x906 +#define STM32H7_PA9_FUNC_USART1_TX 0x908 +#define STM32H7_PA9_FUNC_CAN1_RXFD 0x90a +#define STM32H7_PA9_FUNC_ETH_TX_ER 0x90c +#define STM32H7_PA9_FUNC_DCMI_D0 0x90e +#define STM32H7_PA9_FUNC_LCD_R5 0x90f +#define STM32H7_PA9_FUNC_EVENTOUT 0x910 +#define STM32H7_PA9_FUNC_ANALOG 0x911 + +#define STM32H7_PA10_FUNC_GPIO 0xa00 +#define STM32H7_PA10_FUNC_TIM1_CH3 0xa02 +#define STM32H7_PA10_FUNC_HRTIM_CHC2 0xa03 +#define STM32H7_PA10_FUNC_LPUART1_RX 0xa04 +#define STM32H7_PA10_FUNC_USART1_RX 0xa08 +#define STM32H7_PA10_FUNC_CAN1_TXFD 0xa0a +#define STM32H7_PA10_FUNC_OTG_FS_ID 0xa0b +#define STM32H7_PA10_FUNC_MDIOS_MDIO 0xa0c +#define STM32H7_PA10_FUNC_LCD_B4 0xa0d +#define STM32H7_PA10_FUNC_DCMI_D1 0xa0e +#define STM32H7_PA10_FUNC_LCD_B1 0xa0f +#define STM32H7_PA10_FUNC_EVENTOUT 0xa10 +#define STM32H7_PA10_FUNC_ANALOG 0xa11 + +#define STM32H7_PA11_FUNC_GPIO 0xb00 +#define STM32H7_PA11_FUNC_TIM1_CH4 0xb02 +#define STM32H7_PA11_FUNC_HRTIM_CHD1 0xb03 +#define STM32H7_PA11_FUNC_LPUART1_CTS 0xb04 +#define STM32H7_PA11_FUNC_SPI2_NSS_I2S2_WS 0xb06 +#define STM32H7_PA11_FUNC_UART4_RX 0xb07 +#define STM32H7_PA11_FUNC_USART1_CTS_NSS 0xb08 +#define STM32H7_PA11_FUNC_CAN1_RX 0xb0a +#define STM32H7_PA11_FUNC_OTG_FS_DM 0xb0b +#define STM32H7_PA11_FUNC_LCD_R4 0xb0f +#define STM32H7_PA11_FUNC_EVENTOUT 0xb10 +#define STM32H7_PA11_FUNC_ANALOG 0xb11 + +#define STM32H7_PA12_FUNC_GPIO 0xc00 +#define STM32H7_PA12_FUNC_TIM1_ETR 0xc02 +#define STM32H7_PA12_FUNC_HRTIM_CHD2 0xc03 +#define STM32H7_PA12_FUNC_LPUART1_RTS 0xc04 +#define STM32H7_PA12_FUNC_SPI2_SCK_I2S2_CK 0xc06 +#define STM32H7_PA12_FUNC_UART4_TX 0xc07 +#define STM32H7_PA12_FUNC_USART1_RTS 0xc08 +#define STM32H7_PA12_FUNC_SAI2_FS_B 0xc09 +#define STM32H7_PA12_FUNC_CAN1_TX 0xc0a +#define STM32H7_PA12_FUNC_OTG_FS_DP 0xc0b +#define STM32H7_PA12_FUNC_LCD_R5 0xc0f +#define STM32H7_PA12_FUNC_EVENTOUT 0xc10 +#define STM32H7_PA12_FUNC_ANALOG 0xc11 + +#define STM32H7_PA13_FUNC_GPIO 0xd00 +#define STM32H7_PA13_FUNC_JTMS_SWDIO 0xd01 +#define STM32H7_PA13_FUNC_EVENTOUT 0xd10 +#define STM32H7_PA13_FUNC_ANALOG 0xd11 + +#define STM32H7_PA14_FUNC_GPIO 0xe00 +#define STM32H7_PA14_FUNC_JTCK_SWCLK 0xe01 +#define STM32H7_PA14_FUNC_EVENTOUT 0xe10 +#define STM32H7_PA14_FUNC_ANALOG 0xe11 + +#define STM32H7_PA15_FUNC_GPIO 0xf00 +#define STM32H7_PA15_FUNC_JTDI 0xf01 +#define STM32H7_PA15_FUNC_TIM2_CH1_TIM2_ETR 0xf02 +#define STM32H7_PA15_FUNC_HRTIM_FLT1 0xf03 +#define STM32H7_PA15_FUNC_HDMI_CEC 0xf05 +#define STM32H7_PA15_FUNC_SPI1_NSS_I2S1_WS 0xf06 +#define STM32H7_PA15_FUNC_SPI3_NSS_I2S3_WS 0xf07 +#define STM32H7_PA15_FUNC_SPI6_NSS 0xf08 +#define STM32H7_PA15_FUNC_UART4_RTS 0xf09 +#define STM32H7_PA15_FUNC_UART7_TX 0xf0c +#define STM32H7_PA15_FUNC_DSI_TE 0xf0e +#define STM32H7_PA15_FUNC_EVENTOUT 0xf10 +#define STM32H7_PA15_FUNC_ANALOG 0xf11 + +#define STM32H7_PB0_FUNC_GPIO 0x1000 +#define STM32H7_PB0_FUNC_TIM1_CH2N 0x1002 +#define STM32H7_PB0_FUNC_TIM3_CH3 0x1003 +#define STM32H7_PB0_FUNC_TIM8_CH2N 0x1004 +#define STM32H7_PB0_FUNC_DFSDM_CKOUT 0x1007 +#define STM32H7_PB0_FUNC_UART4_CTS 0x1009 +#define STM32H7_PB0_FUNC_LCD_R3 0x100a +#define STM32H7_PB0_FUNC_OTG_HS_ULPI_D1 0x100b +#define STM32H7_PB0_FUNC_ETH_MII_RXD2 0x100c +#define STM32H7_PB0_FUNC_LCD_G1 0x100f +#define STM32H7_PB0_FUNC_EVENTOUT 0x1010 +#define STM32H7_PB0_FUNC_ANALOG 0x1011 + +#define STM32H7_PB1_FUNC_GPIO 0x1100 +#define STM32H7_PB1_FUNC_TIM1_CH3N 0x1102 +#define STM32H7_PB1_FUNC_TIM3_CH4 0x1103 +#define STM32H7_PB1_FUNC_TIM8_CH3N 0x1104 +#define STM32H7_PB1_FUNC_DFSDM_DATIN1 0x1107 +#define STM32H7_PB1_FUNC_LCD_R6 0x110a +#define STM32H7_PB1_FUNC_OTG_HS_ULPI_D2 0x110b +#define STM32H7_PB1_FUNC_ETH_MII_RXD3 0x110c +#define STM32H7_PB1_FUNC_LCD_G0 0x110f +#define STM32H7_PB1_FUNC_EVENTOUT 0x1110 +#define STM32H7_PB1_FUNC_ANALOG 0x1111 + +#define STM32H7_PB2_FUNC_GPIO 0x1200 +#define STM32H7_PB2_FUNC_SAI1_D1 0x1203 +#define STM32H7_PB2_FUNC_DFSDM_CKIN1 0x1205 +#define STM32H7_PB2_FUNC_SAI1_SD_A 0x1207 +#define STM32H7_PB2_FUNC_SPI3_MOSI_I2S3_SDO 0x1208 +#define STM32H7_PB2_FUNC_SAI4_SD_A 0x1209 +#define STM32H7_PB2_FUNC_QUADSPI_CLK 0x120a +#define STM32H7_PB2_FUNC_SAI4_D1 0x120b +#define STM32H7_PB2_FUNC_ETH_TX_ER 0x120c +#define STM32H7_PB2_FUNC_EVENTOUT 0x1210 +#define STM32H7_PB2_FUNC_ANALOG 0x1211 + +#define STM32H7_PB3_FUNC_GPIO 0x1300 +#define STM32H7_PB3_FUNC_JTDO_TRACESWO 0x1301 +#define STM32H7_PB3_FUNC_TIM2_CH2 0x1302 +#define STM32H7_PB3_FUNC_HRTIM_FLT4 0x1303 +#define STM32H7_PB3_FUNC_SPI1_SCK_I2S1_CK 0x1306 +#define STM32H7_PB3_FUNC_SPI3_SCK_I2S3_CK 0x1307 +#define STM32H7_PB3_FUNC_SPI6_SCK 0x1309 +#define STM32H7_PB3_FUNC_SDMMC2_D2 0x130a +#define STM32H7_PB3_FUNC_UART7_RX 0x130c +#define STM32H7_PB3_FUNC_EVENTOUT 0x1310 +#define STM32H7_PB3_FUNC_ANALOG 0x1311 + +#define STM32H7_PB4_FUNC_GPIO 0x1400 +#define STM32H7_PB4_FUNC_NJTRST 0x1401 +#define STM32H7_PB4_FUNC_TIM16_BKIN 0x1402 +#define STM32H7_PB4_FUNC_TIM3_CH1 0x1403 +#define STM32H7_PB4_FUNC_HRTIM_EEV6 0x1404 +#define STM32H7_PB4_FUNC_SPI1_MISO_I2S1_SDI 0x1406 +#define STM32H7_PB4_FUNC_SPI3_MISO_I2S3_SDI 0x1407 +#define STM32H7_PB4_FUNC_SPI2_NSS_I2S2_WS 0x1408 +#define STM32H7_PB4_FUNC_SPI6_MISO 0x1409 +#define STM32H7_PB4_FUNC_SDMMC2_D3 0x140a +#define STM32H7_PB4_FUNC_UART7_TX 0x140c +#define STM32H7_PB4_FUNC_EVENTOUT 0x1410 +#define STM32H7_PB4_FUNC_ANALOG 0x1411 + +#define STM32H7_PB5_FUNC_GPIO 0x1500 +#define STM32H7_PB5_FUNC_TIM17_BKIN 0x1502 +#define STM32H7_PB5_FUNC_TIM3_CH2 0x1503 +#define STM32H7_PB5_FUNC_HRTIM_EEV7 0x1504 +#define STM32H7_PB5_FUNC_I2C1_SMBA 0x1505 +#define STM32H7_PB5_FUNC_SPI1_MOSI_I2S1_SDO 0x1506 +#define STM32H7_PB5_FUNC_I2C4_SMBA 0x1507 +#define STM32H7_PB5_FUNC_SPI3_MOSI_I2S3_SDO 0x1508 +#define STM32H7_PB5_FUNC_SPI6_MOSI 0x1509 +#define STM32H7_PB5_FUNC_CAN2_RX 0x150a +#define STM32H7_PB5_FUNC_OTG_HS_ULPI_D7 0x150b +#define STM32H7_PB5_FUNC_ETH_PPS_OUT 0x150c +#define STM32H7_PB5_FUNC_FMC_SDCKE1 0x150d +#define STM32H7_PB5_FUNC_DCMI_D10 0x150e +#define STM32H7_PB5_FUNC_UART5_RX 0x150f +#define STM32H7_PB5_FUNC_EVENTOUT 0x1510 +#define STM32H7_PB5_FUNC_ANALOG 0x1511 + +#define STM32H7_PB6_FUNC_GPIO 0x1600 +#define STM32H7_PB6_FUNC_TIM16_CH1N 0x1602 +#define STM32H7_PB6_FUNC_TIM4_CH1 0x1603 +#define STM32H7_PB6_FUNC_HRTIM_EEV8 0x1604 +#define STM32H7_PB6_FUNC_I2C1_SCL 0x1605 +#define STM32H7_PB6_FUNC_HDMI_CEC 0x1606 +#define STM32H7_PB6_FUNC_I2C4_SCL 0x1607 +#define STM32H7_PB6_FUNC_USART1_TX 0x1608 +#define STM32H7_PB6_FUNC_LPUART1_TX 0x1609 +#define STM32H7_PB6_FUNC_CAN2_TX 0x160a +#define STM32H7_PB6_FUNC_QUADSPI_BK1_NCS 0x160b +#define STM32H7_PB6_FUNC_DFSDM_DATIN5 0x160c +#define STM32H7_PB6_FUNC_FMC_SDNE1 0x160d +#define STM32H7_PB6_FUNC_DCMI_D5 0x160e +#define STM32H7_PB6_FUNC_UART5_TX 0x160f +#define STM32H7_PB6_FUNC_EVENTOUT 0x1610 +#define STM32H7_PB6_FUNC_ANALOG 0x1611 + +#define STM32H7_PB7_FUNC_GPIO 0x1700 +#define STM32H7_PB7_FUNC_TIM17_CH1N 0x1702 +#define STM32H7_PB7_FUNC_TIM4_CH2 0x1703 +#define STM32H7_PB7_FUNC_HRTIM_EEV9 0x1704 +#define STM32H7_PB7_FUNC_I2C1_SDA 0x1705 +#define STM32H7_PB7_FUNC_I2C4_SDA 0x1707 +#define STM32H7_PB7_FUNC_USART1_RX 0x1708 +#define STM32H7_PB7_FUNC_LPUART1_RX 0x1709 +#define STM32H7_PB7_FUNC_CAN2_TXFD 0x170a +#define STM32H7_PB7_FUNC_DFSDM_CKIN5 0x170c +#define STM32H7_PB7_FUNC_FMC_NL 0x170d +#define STM32H7_PB7_FUNC_DCMI_VSYNC 0x170e +#define STM32H7_PB7_FUNC_EVENTOUT 0x1710 +#define STM32H7_PB7_FUNC_ANALOG 0x1711 + +#define STM32H7_PB8_FUNC_GPIO 0x1800 +#define STM32H7_PB8_FUNC_TIM16_CH1 0x1802 +#define STM32H7_PB8_FUNC_TIM4_CH3 0x1803 +#define STM32H7_PB8_FUNC_DFSDM_CKIN7 0x1804 +#define STM32H7_PB8_FUNC_I2C1_SCL 0x1805 +#define STM32H7_PB8_FUNC_I2C4_SCL 0x1807 +#define STM32H7_PB8_FUNC_SDMMC1_CKIN 0x1808 +#define STM32H7_PB8_FUNC_UART4_RX 0x1809 +#define STM32H7_PB8_FUNC_CAN1_RX 0x180a +#define STM32H7_PB8_FUNC_SDMMC2_D4 0x180b +#define STM32H7_PB8_FUNC_ETH_MII_TXD3 0x180c +#define STM32H7_PB8_FUNC_SDMMC1_D4 0x180d +#define STM32H7_PB8_FUNC_DCMI_D6 0x180e +#define STM32H7_PB8_FUNC_LCD_B6 0x180f +#define STM32H7_PB8_FUNC_EVENTOUT 0x1810 +#define STM32H7_PB8_FUNC_ANALOG 0x1811 + +#define STM32H7_PB9_FUNC_GPIO 0x1900 +#define STM32H7_PB9_FUNC_TIM17_CH1 0x1902 +#define STM32H7_PB9_FUNC_TIM4_CH4 0x1903 +#define STM32H7_PB9_FUNC_DFSDM_DATIN7 0x1904 +#define STM32H7_PB9_FUNC_I2C1_SDA 0x1905 +#define STM32H7_PB9_FUNC_SPI2_NSS_I2S2_WS 0x1906 +#define STM32H7_PB9_FUNC_I2C4_SDA 0x1907 +#define STM32H7_PB9_FUNC_SDMMC1_CDIR 0x1908 +#define STM32H7_PB9_FUNC_UART4_TX 0x1909 +#define STM32H7_PB9_FUNC_CAN1_TX 0x190a +#define STM32H7_PB9_FUNC_SDMMC2_D5 0x190b +#define STM32H7_PB9_FUNC_I2C4_SMBA 0x190c +#define STM32H7_PB9_FUNC_SDMMC1_D5 0x190d +#define STM32H7_PB9_FUNC_DCMI_D7 0x190e +#define STM32H7_PB9_FUNC_LCD_B7 0x190f +#define STM32H7_PB9_FUNC_EVENTOUT 0x1910 +#define STM32H7_PB9_FUNC_ANALOG 0x1911 + +#define STM32H7_PB10_FUNC_GPIO 0x1a00 +#define STM32H7_PB10_FUNC_TIM2_CH3 0x1a02 +#define STM32H7_PB10_FUNC_HRTIM_SCOUT 0x1a03 +#define STM32H7_PB10_FUNC_LPTIM2_IN1 0x1a04 +#define STM32H7_PB10_FUNC_I2C2_SCL 0x1a05 +#define STM32H7_PB10_FUNC_SPI2_SCK_I2S2_CK 0x1a06 +#define STM32H7_PB10_FUNC_DFSDM_DATIN7 0x1a07 +#define STM32H7_PB10_FUNC_USART3_TX 0x1a08 +#define STM32H7_PB10_FUNC_QUADSPI_BK1_NCS 0x1a0a +#define STM32H7_PB10_FUNC_OTG_HS_ULPI_D3 0x1a0b +#define STM32H7_PB10_FUNC_ETH_MII_RX_ER 0x1a0c +#define STM32H7_PB10_FUNC_LCD_G4 0x1a0f +#define STM32H7_PB10_FUNC_EVENTOUT 0x1a10 +#define STM32H7_PB10_FUNC_ANALOG 0x1a11 + +#define STM32H7_PB11_FUNC_GPIO 0x1b00 +#define STM32H7_PB11_FUNC_TIM2_CH4 0x1b02 +#define STM32H7_PB11_FUNC_HRTIM_SCIN 0x1b03 +#define STM32H7_PB11_FUNC_LPTIM2_ETR 0x1b04 +#define STM32H7_PB11_FUNC_I2C2_SDA 0x1b05 +#define STM32H7_PB11_FUNC_DFSDM_CKIN7 0x1b07 +#define STM32H7_PB11_FUNC_USART3_RX 0x1b08 +#define STM32H7_PB11_FUNC_OTG_HS_ULPI_D4 0x1b0b +#define STM32H7_PB11_FUNC_ETH_MII_TX_EN_ETH_RMII_TX_EN 0x1b0c +#define STM32H7_PB11_FUNC_DSI_TE 0x1b0e +#define STM32H7_PB11_FUNC_LCD_G5 0x1b0f +#define STM32H7_PB11_FUNC_EVENTOUT 0x1b10 +#define STM32H7_PB11_FUNC_ANALOG 0x1b11 + +#define STM32H7_PB12_FUNC_GPIO 0x1c00 +#define STM32H7_PB12_FUNC_TIM1_BKIN 0x1c02 +#define STM32H7_PB12_FUNC_I2C2_SMBA 0x1c05 +#define STM32H7_PB12_FUNC_SPI2_NSS_I2S2_WS 0x1c06 +#define STM32H7_PB12_FUNC_DFSDM_DATIN1 0x1c07 +#define STM32H7_PB12_FUNC_USART3_CK 0x1c08 +#define STM32H7_PB12_FUNC_CAN2_RX 0x1c0a +#define STM32H7_PB12_FUNC_OTG_HS_ULPI_D5 0x1c0b +#define STM32H7_PB12_FUNC_ETH_MII_TXD0_ETH_RMII_TXD0 0x1c0c +#define STM32H7_PB12_FUNC_OTG_HS_ID 0x1c0d +#define STM32H7_PB12_FUNC_TIM1_BKIN_COMP12 0x1c0e +#define STM32H7_PB12_FUNC_UART5_RX 0x1c0f +#define STM32H7_PB12_FUNC_EVENTOUT 0x1c10 +#define STM32H7_PB12_FUNC_ANALOG 0x1c11 + +#define STM32H7_PB13_FUNC_GPIO 0x1d00 +#define STM32H7_PB13_FUNC_TIM1_CH1N 0x1d02 +#define STM32H7_PB13_FUNC_LPTIM2_OUT 0x1d04 +#define STM32H7_PB13_FUNC_SPI2_SCK_I2S2_CK 0x1d06 +#define STM32H7_PB13_FUNC_DFSDM_CKIN1 0x1d07 +#define STM32H7_PB13_FUNC_USART3_CTS_NSS 0x1d08 +#define STM32H7_PB13_FUNC_CAN2_TX 0x1d0a +#define STM32H7_PB13_FUNC_OTG_HS_ULPI_D6 0x1d0b +#define STM32H7_PB13_FUNC_ETH_MII_TXD1_ETH_RMII_TXD1 0x1d0c +#define STM32H7_PB13_FUNC_UART5_TX 0x1d0f +#define STM32H7_PB13_FUNC_EVENTOUT 0x1d10 +#define STM32H7_PB13_FUNC_ANALOG 0x1d11 + +#define STM32H7_PB14_FUNC_GPIO 0x1e00 +#define STM32H7_PB14_FUNC_TIM1_CH2N 0x1e02 +#define STM32H7_PB14_FUNC_TIM8_CH2N 0x1e04 +#define STM32H7_PB14_FUNC_USART1_TX 0x1e05 +#define STM32H7_PB14_FUNC_SPI2_MISO_I2S2_SDI 0x1e06 +#define STM32H7_PB14_FUNC_DFSDM_DATIN2 0x1e07 +#define STM32H7_PB14_FUNC_USART3_RTS 0x1e08 +#define STM32H7_PB14_FUNC_UART4_RTS 0x1e09 +#define STM32H7_PB14_FUNC_SDMMC2_D0 0x1e0a +#define STM32H7_PB14_FUNC_OTG_HS_DM 0x1e0d +#define STM32H7_PB14_FUNC_EVENTOUT 0x1e10 +#define STM32H7_PB14_FUNC_ANALOG 0x1e11 + +#define STM32H7_PB15_FUNC_GPIO 0x1f00 +#define STM32H7_PB15_FUNC_RTC_REFIN 0x1f01 +#define STM32H7_PB15_FUNC_TIM1_CH3N 0x1f02 +#define STM32H7_PB15_FUNC_TIM8_CH3N 0x1f04 +#define STM32H7_PB15_FUNC_USART1_RX 0x1f05 +#define STM32H7_PB15_FUNC_SPI2_MOSI_I2S2_SDO 0x1f06 +#define STM32H7_PB15_FUNC_DFSDM_CKIN2 0x1f07 +#define STM32H7_PB15_FUNC_UART4_CTS 0x1f09 +#define STM32H7_PB15_FUNC_SDMMC2_D1 0x1f0a +#define STM32H7_PB15_FUNC_OTG_HS_DP 0x1f0d +#define STM32H7_PB15_FUNC_EVENTOUT 0x1f10 +#define STM32H7_PB15_FUNC_ANALOG 0x1f11 + +#define STM32H7_PC0_FUNC_GPIO 0x2000 +#define STM32H7_PC0_FUNC_DFSDM_CKIN0 0x2004 +#define STM32H7_PC0_FUNC_DFSDM_DATIN4 0x2007 +#define STM32H7_PC0_FUNC_SAI2_FS_B 0x2009 +#define STM32H7_PC0_FUNC_OTG_HS_ULPI_STP 0x200b +#define STM32H7_PC0_FUNC_FMC_SDNWE 0x200d +#define STM32H7_PC0_FUNC_LCD_R5 0x200f +#define STM32H7_PC0_FUNC_EVENTOUT 0x2010 +#define STM32H7_PC0_FUNC_ANALOG 0x2011 + +#define STM32H7_PC1_FUNC_GPIO 0x2100 +#define STM32H7_PC1_FUNC_TRACED0 0x2101 +#define STM32H7_PC1_FUNC_SAI1_D1 0x2103 +#define STM32H7_PC1_FUNC_DFSDM_DATIN0 0x2104 +#define STM32H7_PC1_FUNC_DFSDM_CKIN4 0x2105 +#define STM32H7_PC1_FUNC_SPI2_MOSI_I2S2_SDO 0x2106 +#define STM32H7_PC1_FUNC_SAI1_SD_A 0x2107 +#define STM32H7_PC1_FUNC_SAI4_SD_A 0x2109 +#define STM32H7_PC1_FUNC_SDMMC2_CK 0x210a +#define STM32H7_PC1_FUNC_SAI4_D1 0x210b +#define STM32H7_PC1_FUNC_ETH_MDC 0x210c +#define STM32H7_PC1_FUNC_MDIOS_MDC 0x210d +#define STM32H7_PC1_FUNC_EVENTOUT 0x2110 +#define STM32H7_PC1_FUNC_ANALOG 0x2111 + +#define STM32H7_PC2_FUNC_GPIO 0x2200 +#define STM32H7_PC2_FUNC_DFSDM_CKIN1 0x2204 +#define STM32H7_PC2_FUNC_SPI2_MISO_I2S2_SDI 0x2206 +#define STM32H7_PC2_FUNC_DFSDM_CKOUT 0x2207 +#define STM32H7_PC2_FUNC_OTG_HS_ULPI_DIR 0x220b +#define STM32H7_PC2_FUNC_ETH_MII_TXD2 0x220c +#define STM32H7_PC2_FUNC_FMC_SDNE0 0x220d +#define STM32H7_PC2_FUNC_EVENTOUT 0x2210 +#define STM32H7_PC2_FUNC_ANALOG 0x2211 + +#define STM32H7_PC3_FUNC_GPIO 0x2300 +#define STM32H7_PC3_FUNC_DFSDM_DATIN1 0x2304 +#define STM32H7_PC3_FUNC_SPI2_MOSI_I2S2_SDO 0x2306 +#define STM32H7_PC3_FUNC_OTG_HS_ULPI_NXT 0x230b +#define STM32H7_PC3_FUNC_ETH_MII_TX_CLK 0x230c +#define STM32H7_PC3_FUNC_FMC_SDCKE0 0x230d +#define STM32H7_PC3_FUNC_EVENTOUT 0x2310 +#define STM32H7_PC3_FUNC_ANALOG 0x2311 + +#define STM32H7_PC4_FUNC_GPIO 0x2400 +#define STM32H7_PC4_FUNC_DFSDM_CKIN2 0x2404 +#define STM32H7_PC4_FUNC_I2S1_MCK 0x2406 +#define STM32H7_PC4_FUNC_SPDIFRX_IN2 0x240a +#define STM32H7_PC4_FUNC_ETH_MII_RXD0_ETH_RMII_RXD0 0x240c +#define STM32H7_PC4_FUNC_FMC_SDNE0 0x240d +#define STM32H7_PC4_FUNC_EVENTOUT 0x2410 +#define STM32H7_PC4_FUNC_ANALOG 0x2411 + +#define STM32H7_PC5_FUNC_GPIO 0x2500 +#define STM32H7_PC5_FUNC_SAI1_D3 0x2503 +#define STM32H7_PC5_FUNC_DFSDM_DATIN2 0x2504 +#define STM32H7_PC5_FUNC_SPDIFRX_IN3 0x250a +#define STM32H7_PC5_FUNC_SAI4_D3 0x250b +#define STM32H7_PC5_FUNC_ETH_MII_RXD1_ETH_RMII_RXD1 0x250c +#define STM32H7_PC5_FUNC_FMC_SDCKE0 0x250d +#define STM32H7_PC5_FUNC_COMP_1_OUT 0x250e +#define STM32H7_PC5_FUNC_EVENTOUT 0x2510 +#define STM32H7_PC5_FUNC_ANALOG 0x2511 + +#define STM32H7_PC6_FUNC_GPIO 0x2600 +#define STM32H7_PC6_FUNC_HRTIM_CHA1 0x2602 +#define STM32H7_PC6_FUNC_TIM3_CH1 0x2603 +#define STM32H7_PC6_FUNC_TIM8_CH1 0x2604 +#define STM32H7_PC6_FUNC_DFSDM_CKIN3 0x2605 +#define STM32H7_PC6_FUNC_I2S2_MCK 0x2606 +#define STM32H7_PC6_FUNC_USART6_TX 0x2608 +#define STM32H7_PC6_FUNC_SDMMC1_D0DIR 0x2609 +#define STM32H7_PC6_FUNC_FMC_NWAIT 0x260a +#define STM32H7_PC6_FUNC_SDMMC2_D6 0x260b +#define STM32H7_PC6_FUNC_SDMMC1_D6 0x260d +#define STM32H7_PC6_FUNC_DCMI_D0 0x260e +#define STM32H7_PC6_FUNC_LCD_HSYNC 0x260f +#define STM32H7_PC6_FUNC_EVENTOUT 0x2610 +#define STM32H7_PC6_FUNC_ANALOG 0x2611 + +#define STM32H7_PC7_FUNC_GPIO 0x2700 +#define STM32H7_PC7_FUNC_TRGIO 0x2701 +#define STM32H7_PC7_FUNC_HRTIM_CHA2 0x2702 +#define STM32H7_PC7_FUNC_TIM3_CH2 0x2703 +#define STM32H7_PC7_FUNC_TIM8_CH2 0x2704 +#define STM32H7_PC7_FUNC_DFSDM_DATIN3 0x2705 +#define STM32H7_PC7_FUNC_I2S3_MCK 0x2707 +#define STM32H7_PC7_FUNC_USART6_RX 0x2708 +#define STM32H7_PC7_FUNC_SDMMC1_D123DIR 0x2709 +#define STM32H7_PC7_FUNC_FMC_NE1 0x270a +#define STM32H7_PC7_FUNC_SDMMC2_D7 0x270b +#define STM32H7_PC7_FUNC_SWPMI_TX 0x270c +#define STM32H7_PC7_FUNC_SDMMC1_D7 0x270d +#define STM32H7_PC7_FUNC_DCMI_D1 0x270e +#define STM32H7_PC7_FUNC_LCD_G6 0x270f +#define STM32H7_PC7_FUNC_EVENTOUT 0x2710 +#define STM32H7_PC7_FUNC_ANALOG 0x2711 + +#define STM32H7_PC8_FUNC_GPIO 0x2800 +#define STM32H7_PC8_FUNC_TRACED1 0x2801 +#define STM32H7_PC8_FUNC_HRTIM_CHB1 0x2802 +#define STM32H7_PC8_FUNC_TIM3_CH3 0x2803 +#define STM32H7_PC8_FUNC_TIM8_CH3 0x2804 +#define STM32H7_PC8_FUNC_USART6_CK 0x2808 +#define STM32H7_PC8_FUNC_UART5_RTS 0x2809 +#define STM32H7_PC8_FUNC_FMC_NE2_FMC_NCE 0x280a +#define STM32H7_PC8_FUNC_SWPMI_RX 0x280c +#define STM32H7_PC8_FUNC_SDMMC1_D0 0x280d +#define STM32H7_PC8_FUNC_DCMI_D2 0x280e +#define STM32H7_PC8_FUNC_EVENTOUT 0x2810 +#define STM32H7_PC8_FUNC_ANALOG 0x2811 + +#define STM32H7_PC9_FUNC_GPIO 0x2900 +#define STM32H7_PC9_FUNC_MCO2 0x2901 +#define STM32H7_PC9_FUNC_TIM3_CH4 0x2903 +#define STM32H7_PC9_FUNC_TIM8_CH4 0x2904 +#define STM32H7_PC9_FUNC_I2C3_SDA 0x2905 +#define STM32H7_PC9_FUNC_I2S_CKIN 0x2906 +#define STM32H7_PC9_FUNC_UART5_CTS 0x2909 +#define STM32H7_PC9_FUNC_QUADSPI_BK1_IO0 0x290a +#define STM32H7_PC9_FUNC_LCD_G3 0x290b +#define STM32H7_PC9_FUNC_SWPMI_SUSPEND 0x290c +#define STM32H7_PC9_FUNC_SDMMC1_D1 0x290d +#define STM32H7_PC9_FUNC_DCMI_D3 0x290e +#define STM32H7_PC9_FUNC_LCD_B2 0x290f +#define STM32H7_PC9_FUNC_EVENTOUT 0x2910 +#define STM32H7_PC9_FUNC_ANALOG 0x2911 + +#define STM32H7_PC10_FUNC_GPIO 0x2a00 +#define STM32H7_PC10_FUNC_HRTIM_EEV1 0x2a03 +#define STM32H7_PC10_FUNC_DFSDM_CKIN5 0x2a04 +#define STM32H7_PC10_FUNC_SPI3_SCK_I2S3_CK 0x2a07 +#define STM32H7_PC10_FUNC_USART3_TX 0x2a08 +#define STM32H7_PC10_FUNC_UART4_TX 0x2a09 +#define STM32H7_PC10_FUNC_QUADSPI_BK1_IO1 0x2a0a +#define STM32H7_PC10_FUNC_SDMMC1_D2 0x2a0d +#define STM32H7_PC10_FUNC_DCMI_D8 0x2a0e +#define STM32H7_PC10_FUNC_LCD_R2 0x2a0f +#define STM32H7_PC10_FUNC_EVENTOUT 0x2a10 +#define STM32H7_PC10_FUNC_ANALOG 0x2a11 + +#define STM32H7_PC11_FUNC_GPIO 0x2b00 +#define STM32H7_PC11_FUNC_HRTIM_FLT2 0x2b03 +#define STM32H7_PC11_FUNC_DFSDM_DATIN5 0x2b04 +#define STM32H7_PC11_FUNC_SPI3_MISO_I2S3_SDI 0x2b07 +#define STM32H7_PC11_FUNC_USART3_RX 0x2b08 +#define STM32H7_PC11_FUNC_UART4_RX 0x2b09 +#define STM32H7_PC11_FUNC_QUADSPI_BK2_NCS 0x2b0a +#define STM32H7_PC11_FUNC_SDMMC1_D3 0x2b0d +#define STM32H7_PC11_FUNC_DCMI_D4 0x2b0e +#define STM32H7_PC11_FUNC_EVENTOUT 0x2b10 +#define STM32H7_PC11_FUNC_ANALOG 0x2b11 + +#define STM32H7_PC12_FUNC_GPIO 0x2c00 +#define STM32H7_PC12_FUNC_TRACED3 0x2c01 +#define STM32H7_PC12_FUNC_HRTIM_EEV2 0x2c03 +#define STM32H7_PC12_FUNC_SPI3_MOSI_I2S3_SDO 0x2c07 +#define STM32H7_PC12_FUNC_USART3_CK 0x2c08 +#define STM32H7_PC12_FUNC_UART5_TX 0x2c09 +#define STM32H7_PC12_FUNC_SDMMC1_CK 0x2c0d +#define STM32H7_PC12_FUNC_DCMI_D9 0x2c0e +#define STM32H7_PC12_FUNC_EVENTOUT 0x2c10 +#define STM32H7_PC12_FUNC_ANALOG 0x2c11 + +#define STM32H7_PC13_FUNC_GPIO 0x2d00 +#define STM32H7_PC13_FUNC_EVENTOUT 0x2d10 +#define STM32H7_PC13_FUNC_ANALOG 0x2d11 + +#define STM32H7_PC14_FUNC_GPIO 0x2e00 +#define STM32H7_PC14_FUNC_EVENTOUT 0x2e10 +#define STM32H7_PC14_FUNC_ANALOG 0x2e11 + +#define STM32H7_PC15_FUNC_GPIO 0x2f00 +#define STM32H7_PC15_FUNC_EVENTOUT 0x2f10 +#define STM32H7_PC15_FUNC_ANALOG 0x2f11 + +#define STM32H7_PD0_FUNC_GPIO 0x3000 +#define STM32H7_PD0_FUNC_DFSDM_CKIN6 0x3004 +#define STM32H7_PD0_FUNC_SAI3_SCK_A 0x3007 +#define STM32H7_PD0_FUNC_UART4_RX 0x3009 +#define STM32H7_PD0_FUNC_CAN1_RX 0x300a +#define STM32H7_PD0_FUNC_FMC_D2_FMC_DA2 0x300d +#define STM32H7_PD0_FUNC_EVENTOUT 0x3010 +#define STM32H7_PD0_FUNC_ANALOG 0x3011 + +#define STM32H7_PD1_FUNC_GPIO 0x3100 +#define STM32H7_PD1_FUNC_DFSDM_DATIN6 0x3104 +#define STM32H7_PD1_FUNC_SAI3_SD_A 0x3107 +#define STM32H7_PD1_FUNC_UART4_TX 0x3109 +#define STM32H7_PD1_FUNC_CAN1_TX 0x310a +#define STM32H7_PD1_FUNC_FMC_D3_FMC_DA3 0x310d +#define STM32H7_PD1_FUNC_EVENTOUT 0x3110 +#define STM32H7_PD1_FUNC_ANALOG 0x3111 + +#define STM32H7_PD2_FUNC_GPIO 0x3200 +#define STM32H7_PD2_FUNC_TRACED2 0x3201 +#define STM32H7_PD2_FUNC_TIM3_ETR 0x3203 +#define STM32H7_PD2_FUNC_UART5_RX 0x3209 +#define STM32H7_PD2_FUNC_SDMMC1_CMD 0x320d +#define STM32H7_PD2_FUNC_DCMI_D11 0x320e +#define STM32H7_PD2_FUNC_EVENTOUT 0x3210 +#define STM32H7_PD2_FUNC_ANALOG 0x3211 + +#define STM32H7_PD3_FUNC_GPIO 0x3300 +#define STM32H7_PD3_FUNC_DFSDM_CKOUT 0x3304 +#define STM32H7_PD3_FUNC_SPI2_SCK_I2S2_CK 0x3306 +#define STM32H7_PD3_FUNC_USART2_CTS_NSS 0x3308 +#define STM32H7_PD3_FUNC_FMC_CLK 0x330d +#define STM32H7_PD3_FUNC_DCMI_D5 0x330e +#define STM32H7_PD3_FUNC_LCD_G7 0x330f +#define STM32H7_PD3_FUNC_EVENTOUT 0x3310 +#define STM32H7_PD3_FUNC_ANALOG 0x3311 + +#define STM32H7_PD4_FUNC_GPIO 0x3400 +#define STM32H7_PD4_FUNC_HRTIM_FLT3 0x3403 +#define STM32H7_PD4_FUNC_SAI3_FS_A 0x3407 +#define STM32H7_PD4_FUNC_USART2_RTS 0x3408 +#define STM32H7_PD4_FUNC_CAN1_RXFD 0x340a +#define STM32H7_PD4_FUNC_FMC_NOE 0x340d +#define STM32H7_PD4_FUNC_EVENTOUT 0x3410 +#define STM32H7_PD4_FUNC_ANALOG 0x3411 + +#define STM32H7_PD5_FUNC_GPIO 0x3500 +#define STM32H7_PD5_FUNC_HRTIM_EEV3 0x3503 +#define STM32H7_PD5_FUNC_USART2_TX 0x3508 +#define STM32H7_PD5_FUNC_CAN1_TXFD 0x350a +#define STM32H7_PD5_FUNC_FMC_NWE 0x350d +#define STM32H7_PD5_FUNC_EVENTOUT 0x3510 +#define STM32H7_PD5_FUNC_ANALOG 0x3511 + +#define STM32H7_PD6_FUNC_GPIO 0x3600 +#define STM32H7_PD6_FUNC_SAI1_D1 0x3603 +#define STM32H7_PD6_FUNC_DFSDM_CKIN4 0x3604 +#define STM32H7_PD6_FUNC_DFSDM_DATIN1 0x3605 +#define STM32H7_PD6_FUNC_SPI3_MOSI_I2S3_SDO 0x3606 +#define STM32H7_PD6_FUNC_SAI1_SD_A 0x3607 +#define STM32H7_PD6_FUNC_USART2_RX 0x3608 +#define STM32H7_PD6_FUNC_SAI4_SD_A 0x3609 +#define STM32H7_PD6_FUNC_CAN2_RXFD 0x360a +#define STM32H7_PD6_FUNC_SAI4_D1 0x360b +#define STM32H7_PD6_FUNC_SDMMC2_CK 0x360c +#define STM32H7_PD6_FUNC_FMC_NWAIT 0x360d +#define STM32H7_PD6_FUNC_DCMI_D10 0x360e +#define STM32H7_PD6_FUNC_LCD_B2 0x360f +#define STM32H7_PD6_FUNC_EVENTOUT 0x3610 +#define STM32H7_PD6_FUNC_ANALOG 0x3611 + +#define STM32H7_PD7_FUNC_GPIO 0x3700 +#define STM32H7_PD7_FUNC_DFSDM_DATIN4 0x3704 +#define STM32H7_PD7_FUNC_SPI1_MOSI_I2S1_SDO 0x3706 +#define STM32H7_PD7_FUNC_DFSDM_CKIN1 0x3707 +#define STM32H7_PD7_FUNC_USART2_CK 0x3708 +#define STM32H7_PD7_FUNC_SPDIFRX_IN0 0x370a +#define STM32H7_PD7_FUNC_SDMMC2_CMD 0x370c +#define STM32H7_PD7_FUNC_FMC_NE1 0x370d +#define STM32H7_PD7_FUNC_EVENTOUT 0x3710 +#define STM32H7_PD7_FUNC_ANALOG 0x3711 + +#define STM32H7_PD8_FUNC_GPIO 0x3800 +#define STM32H7_PD8_FUNC_DFSDM_CKIN3 0x3804 +#define STM32H7_PD8_FUNC_SAI3_SCK_B 0x3807 +#define STM32H7_PD8_FUNC_USART3_TX 0x3808 +#define STM32H7_PD8_FUNC_SPDIFRX_IN1 0x380a +#define STM32H7_PD8_FUNC_FMC_D13_FMC_DA13 0x380d +#define STM32H7_PD8_FUNC_EVENTOUT 0x3810 +#define STM32H7_PD8_FUNC_ANALOG 0x3811 + +#define STM32H7_PD9_FUNC_GPIO 0x3900 +#define STM32H7_PD9_FUNC_DFSDM_DATIN3 0x3904 +#define STM32H7_PD9_FUNC_SAI3_SD_B 0x3907 +#define STM32H7_PD9_FUNC_USART3_RX 0x3908 +#define STM32H7_PD9_FUNC_CAN2_RXFD 0x390a +#define STM32H7_PD9_FUNC_FMC_D14_FMC_DA14 0x390d +#define STM32H7_PD9_FUNC_EVENTOUT 0x3910 +#define STM32H7_PD9_FUNC_ANALOG 0x3911 + +#define STM32H7_PD10_FUNC_GPIO 0x3a00 +#define STM32H7_PD10_FUNC_DFSDM_CKOUT 0x3a04 +#define STM32H7_PD10_FUNC_SAI3_FS_B 0x3a07 +#define STM32H7_PD10_FUNC_USART3_CK 0x3a08 +#define STM32H7_PD10_FUNC_CAN2_TXFD 0x3a0a +#define STM32H7_PD10_FUNC_FMC_D15_FMC_DA15 0x3a0d +#define STM32H7_PD10_FUNC_LCD_B3 0x3a0f +#define STM32H7_PD10_FUNC_EVENTOUT 0x3a10 +#define STM32H7_PD10_FUNC_ANALOG 0x3a11 + +#define STM32H7_PD11_FUNC_GPIO 0x3b00 +#define STM32H7_PD11_FUNC_LPTIM2_IN2 0x3b04 +#define STM32H7_PD11_FUNC_I2C4_SMBA 0x3b05 +#define STM32H7_PD11_FUNC_USART3_CTS_NSS 0x3b08 +#define STM32H7_PD11_FUNC_QUADSPI_BK1_IO0 0x3b0a +#define STM32H7_PD11_FUNC_SAI2_SD_A 0x3b0b +#define STM32H7_PD11_FUNC_FMC_A16 0x3b0d +#define STM32H7_PD11_FUNC_EVENTOUT 0x3b10 +#define STM32H7_PD11_FUNC_ANALOG 0x3b11 + +#define STM32H7_PD12_FUNC_GPIO 0x3c00 +#define STM32H7_PD12_FUNC_LPTIM1_IN1 0x3c02 +#define STM32H7_PD12_FUNC_TIM4_CH1 0x3c03 +#define STM32H7_PD12_FUNC_LPTIM2_IN1 0x3c04 +#define STM32H7_PD12_FUNC_I2C4_SCL 0x3c05 +#define STM32H7_PD12_FUNC_USART3_RTS 0x3c08 +#define STM32H7_PD12_FUNC_QUADSPI_BK1_IO1 0x3c0a +#define STM32H7_PD12_FUNC_SAI2_FS_A 0x3c0b +#define STM32H7_PD12_FUNC_FMC_A17 0x3c0d +#define STM32H7_PD12_FUNC_EVENTOUT 0x3c10 +#define STM32H7_PD12_FUNC_ANALOG 0x3c11 + +#define STM32H7_PD13_FUNC_GPIO 0x3d00 +#define STM32H7_PD13_FUNC_LPTIM1_OUT 0x3d02 +#define STM32H7_PD13_FUNC_TIM4_CH2 0x3d03 +#define STM32H7_PD13_FUNC_I2C4_SDA 0x3d05 +#define STM32H7_PD13_FUNC_QUADSPI_BK1_IO3 0x3d0a +#define STM32H7_PD13_FUNC_SAI2_SCK_A 0x3d0b +#define STM32H7_PD13_FUNC_FMC_A18 0x3d0d +#define STM32H7_PD13_FUNC_EVENTOUT 0x3d10 +#define STM32H7_PD13_FUNC_ANALOG 0x3d11 + +#define STM32H7_PD14_FUNC_GPIO 0x3e00 +#define STM32H7_PD14_FUNC_TIM4_CH3 0x3e03 +#define STM32H7_PD14_FUNC_SAI3_MCLK_B 0x3e07 +#define STM32H7_PD14_FUNC_UART8_CTS 0x3e09 +#define STM32H7_PD14_FUNC_FMC_D0_FMC_DA0 0x3e0d +#define STM32H7_PD14_FUNC_EVENTOUT 0x3e10 +#define STM32H7_PD14_FUNC_ANALOG 0x3e11 + +#define STM32H7_PD15_FUNC_GPIO 0x3f00 +#define STM32H7_PD15_FUNC_TIM4_CH4 0x3f03 +#define STM32H7_PD15_FUNC_SAI3_MCLK_A 0x3f07 +#define STM32H7_PD15_FUNC_UART8_RTS 0x3f09 +#define STM32H7_PD15_FUNC_FMC_D1_FMC_DA1 0x3f0d +#define STM32H7_PD15_FUNC_EVENTOUT 0x3f10 +#define STM32H7_PD15_FUNC_ANALOG 0x3f11 + +#define STM32H7_PE0_FUNC_GPIO 0x4000 +#define STM32H7_PE0_FUNC_LPTIM1_ETR 0x4002 +#define STM32H7_PE0_FUNC_TIM4_ETR 0x4003 +#define STM32H7_PE0_FUNC_HRTIM_SCIN 0x4004 +#define STM32H7_PE0_FUNC_LPTIM2_ETR 0x4005 +#define STM32H7_PE0_FUNC_UART8_RX 0x4009 +#define STM32H7_PE0_FUNC_CAN1_RXFD 0x400a +#define STM32H7_PE0_FUNC_SAI2_MCK_A 0x400b +#define STM32H7_PE0_FUNC_FMC_NBL0 0x400d +#define STM32H7_PE0_FUNC_DCMI_D2 0x400e +#define STM32H7_PE0_FUNC_EVENTOUT 0x4010 +#define STM32H7_PE0_FUNC_ANALOG 0x4011 + +#define STM32H7_PE1_FUNC_GPIO 0x4100 +#define STM32H7_PE1_FUNC_LPTIM1_IN2 0x4102 +#define STM32H7_PE1_FUNC_HRTIM_SCOUT 0x4104 +#define STM32H7_PE1_FUNC_UART8_TX 0x4109 +#define STM32H7_PE1_FUNC_CAN1_TXFD 0x410a +#define STM32H7_PE1_FUNC_FMC_NBL1 0x410d +#define STM32H7_PE1_FUNC_DCMI_D3 0x410e +#define STM32H7_PE1_FUNC_EVENTOUT 0x4110 +#define STM32H7_PE1_FUNC_ANALOG 0x4111 + +#define STM32H7_PE2_FUNC_GPIO 0x4200 +#define STM32H7_PE2_FUNC_TRACECLK 0x4201 +#define STM32H7_PE2_FUNC_SAI1_CK1 0x4203 +#define STM32H7_PE2_FUNC_SPI4_SCK 0x4206 +#define STM32H7_PE2_FUNC_SAI1_MCLK_A 0x4207 +#define STM32H7_PE2_FUNC_SAI4_MCLK_A 0x4209 +#define STM32H7_PE2_FUNC_QUADSPI_BK1_IO2 0x420a +#define STM32H7_PE2_FUNC_SAI4_CK1 0x420b +#define STM32H7_PE2_FUNC_ETH_MII_TXD3 0x420c +#define STM32H7_PE2_FUNC_FMC_A23 0x420d +#define STM32H7_PE2_FUNC_EVENTOUT 0x4210 +#define STM32H7_PE2_FUNC_ANALOG 0x4211 + +#define STM32H7_PE3_FUNC_GPIO 0x4300 +#define STM32H7_PE3_FUNC_TRACED0 0x4301 +#define STM32H7_PE3_FUNC_TIM15_BKIN 0x4305 +#define STM32H7_PE3_FUNC_SAI1_SD_B 0x4307 +#define STM32H7_PE3_FUNC_SAI4_SD_B 0x4309 +#define STM32H7_PE3_FUNC_FMC_A19 0x430d +#define STM32H7_PE3_FUNC_EVENTOUT 0x4310 +#define STM32H7_PE3_FUNC_ANALOG 0x4311 + +#define STM32H7_PE4_FUNC_GPIO 0x4400 +#define STM32H7_PE4_FUNC_TRACED1 0x4401 +#define STM32H7_PE4_FUNC_SAI1_D2 0x4403 +#define STM32H7_PE4_FUNC_DFSDM_DATIN3 0x4404 +#define STM32H7_PE4_FUNC_TIM15_CH1N 0x4405 +#define STM32H7_PE4_FUNC_SPI4_NSS 0x4406 +#define STM32H7_PE4_FUNC_SAI1_FS_A 0x4407 +#define STM32H7_PE4_FUNC_SAI4_FS_A 0x4409 +#define STM32H7_PE4_FUNC_SAI4_D2 0x440b +#define STM32H7_PE4_FUNC_FMC_A20 0x440d +#define STM32H7_PE4_FUNC_DCMI_D4 0x440e +#define STM32H7_PE4_FUNC_LCD_B0 0x440f +#define STM32H7_PE4_FUNC_EVENTOUT 0x4410 +#define STM32H7_PE4_FUNC_ANALOG 0x4411 + +#define STM32H7_PE5_FUNC_GPIO 0x4500 +#define STM32H7_PE5_FUNC_TRACED2 0x4501 +#define STM32H7_PE5_FUNC_SAI1_CK2 0x4503 +#define STM32H7_PE5_FUNC_DFSDM_CKIN3 0x4504 +#define STM32H7_PE5_FUNC_TIM15_CH1 0x4505 +#define STM32H7_PE5_FUNC_SPI4_MISO 0x4506 +#define STM32H7_PE5_FUNC_SAI1_SCK_A 0x4507 +#define STM32H7_PE5_FUNC_SAI4_SCK_A 0x4509 +#define STM32H7_PE5_FUNC_SAI4_CK2 0x450b +#define STM32H7_PE5_FUNC_FMC_A21 0x450d +#define STM32H7_PE5_FUNC_DCMI_D6 0x450e +#define STM32H7_PE5_FUNC_LCD_G0 0x450f +#define STM32H7_PE5_FUNC_EVENTOUT 0x4510 +#define STM32H7_PE5_FUNC_ANALOG 0x4511 + +#define STM32H7_PE6_FUNC_GPIO 0x4600 +#define STM32H7_PE6_FUNC_TRACED3 0x4601 +#define STM32H7_PE6_FUNC_TIM1_BKIN2 0x4602 +#define STM32H7_PE6_FUNC_SAI1_D1 0x4603 +#define STM32H7_PE6_FUNC_TIM15_CH2 0x4605 +#define STM32H7_PE6_FUNC_SPI4_MOSI 0x4606 +#define STM32H7_PE6_FUNC_SAI1_SD_A 0x4607 +#define STM32H7_PE6_FUNC_SAI4_SD_A 0x4609 +#define STM32H7_PE6_FUNC_SAI4_D1 0x460a +#define STM32H7_PE6_FUNC_SAI2_MCK_B 0x460b +#define STM32H7_PE6_FUNC_TIM1_BKIN2_COMP12 0x460c +#define STM32H7_PE6_FUNC_FMC_A22 0x460d +#define STM32H7_PE6_FUNC_DCMI_D7 0x460e +#define STM32H7_PE6_FUNC_LCD_G1 0x460f +#define STM32H7_PE6_FUNC_EVENTOUT 0x4610 +#define STM32H7_PE6_FUNC_ANALOG 0x4611 + +#define STM32H7_PE7_FUNC_GPIO 0x4700 +#define STM32H7_PE7_FUNC_TIM1_ETR 0x4702 +#define STM32H7_PE7_FUNC_DFSDM_DATIN2 0x4704 +#define STM32H7_PE7_FUNC_UART7_RX 0x4708 +#define STM32H7_PE7_FUNC_QUADSPI_BK2_IO0 0x470b +#define STM32H7_PE7_FUNC_FMC_D4_FMC_DA4 0x470d +#define STM32H7_PE7_FUNC_EVENTOUT 0x4710 +#define STM32H7_PE7_FUNC_ANALOG 0x4711 + +#define STM32H7_PE8_FUNC_GPIO 0x4800 +#define STM32H7_PE8_FUNC_TIM1_CH1N 0x4802 +#define STM32H7_PE8_FUNC_DFSDM_CKIN2 0x4804 +#define STM32H7_PE8_FUNC_UART7_TX 0x4808 +#define STM32H7_PE8_FUNC_QUADSPI_BK2_IO1 0x480b +#define STM32H7_PE8_FUNC_FMC_D5_FMC_DA5 0x480d +#define STM32H7_PE8_FUNC_COMP_2_OUT 0x480e +#define STM32H7_PE8_FUNC_EVENTOUT 0x4810 +#define STM32H7_PE8_FUNC_ANALOG 0x4811 + +#define STM32H7_PE9_FUNC_GPIO 0x4900 +#define STM32H7_PE9_FUNC_TIM1_CH1 0x4902 +#define STM32H7_PE9_FUNC_DFSDM_CKOUT 0x4904 +#define STM32H7_PE9_FUNC_UART7_RTS 0x4908 +#define STM32H7_PE9_FUNC_QUADSPI_BK2_IO2 0x490b +#define STM32H7_PE9_FUNC_FMC_D6_FMC_DA6 0x490d +#define STM32H7_PE9_FUNC_EVENTOUT 0x4910 +#define STM32H7_PE9_FUNC_ANALOG 0x4911 + +#define STM32H7_PE10_FUNC_GPIO 0x4a00 +#define STM32H7_PE10_FUNC_TIM1_CH2N 0x4a02 +#define STM32H7_PE10_FUNC_DFSDM_DATIN4 0x4a04 +#define STM32H7_PE10_FUNC_UART7_CTS 0x4a08 +#define STM32H7_PE10_FUNC_QUADSPI_BK2_IO3 0x4a0b +#define STM32H7_PE10_FUNC_FMC_D7_FMC_DA7 0x4a0d +#define STM32H7_PE10_FUNC_EVENTOUT 0x4a10 +#define STM32H7_PE10_FUNC_ANALOG 0x4a11 + +#define STM32H7_PE11_FUNC_GPIO 0x4b00 +#define STM32H7_PE11_FUNC_TIM1_CH2 0x4b02 +#define STM32H7_PE11_FUNC_DFSDM_CKIN4 0x4b04 +#define STM32H7_PE11_FUNC_SPI4_NSS 0x4b06 +#define STM32H7_PE11_FUNC_SAI2_SD_B 0x4b0b +#define STM32H7_PE11_FUNC_FMC_D8_FMC_DA8 0x4b0d +#define STM32H7_PE11_FUNC_LCD_G3 0x4b0f +#define STM32H7_PE11_FUNC_EVENTOUT 0x4b10 +#define STM32H7_PE11_FUNC_ANALOG 0x4b11 + +#define STM32H7_PE12_FUNC_GPIO 0x4c00 +#define STM32H7_PE12_FUNC_TIM1_CH3N 0x4c02 +#define STM32H7_PE12_FUNC_DFSDM_DATIN5 0x4c04 +#define STM32H7_PE12_FUNC_SPI4_SCK 0x4c06 +#define STM32H7_PE12_FUNC_SAI2_SCK_B 0x4c0b +#define STM32H7_PE12_FUNC_FMC_D9_FMC_DA9 0x4c0d +#define STM32H7_PE12_FUNC_COMP_1_OUT 0x4c0e +#define STM32H7_PE12_FUNC_LCD_B4 0x4c0f +#define STM32H7_PE12_FUNC_EVENTOUT 0x4c10 +#define STM32H7_PE12_FUNC_ANALOG 0x4c11 + +#define STM32H7_PE13_FUNC_GPIO 0x4d00 +#define STM32H7_PE13_FUNC_TIM1_CH3 0x4d02 +#define STM32H7_PE13_FUNC_DFSDM_CKIN5 0x4d04 +#define STM32H7_PE13_FUNC_SPI4_MISO 0x4d06 +#define STM32H7_PE13_FUNC_SAI2_FS_B 0x4d0b +#define STM32H7_PE13_FUNC_FMC_D10_FMC_DA10 0x4d0d +#define STM32H7_PE13_FUNC_COMP_2_OUT 0x4d0e +#define STM32H7_PE13_FUNC_LCD_DE 0x4d0f +#define STM32H7_PE13_FUNC_EVENTOUT 0x4d10 +#define STM32H7_PE13_FUNC_ANALOG 0x4d11 + +#define STM32H7_PE14_FUNC_GPIO 0x4e00 +#define STM32H7_PE14_FUNC_TIM1_CH4 0x4e02 +#define STM32H7_PE14_FUNC_SPI4_MOSI 0x4e06 +#define STM32H7_PE14_FUNC_SAI2_MCK_B 0x4e0b +#define STM32H7_PE14_FUNC_FMC_D11_FMC_DA11 0x4e0d +#define STM32H7_PE14_FUNC_LCD_CLK 0x4e0f +#define STM32H7_PE14_FUNC_EVENTOUT 0x4e10 +#define STM32H7_PE14_FUNC_ANALOG 0x4e11 + +#define STM32H7_PE15_FUNC_GPIO 0x4f00 +#define STM32H7_PE15_FUNC_TIM1_BKIN 0x4f02 +#define STM32H7_PE15_FUNC_HDMI__TIM1_BKIN 0x4f06 +#define STM32H7_PE15_FUNC_FMC_D12_FMC_DA12 0x4f0d +#define STM32H7_PE15_FUNC_TIM1_BKIN_COMP12 0x4f0e +#define STM32H7_PE15_FUNC_LCD_R7 0x4f0f +#define STM32H7_PE15_FUNC_EVENTOUT 0x4f10 +#define STM32H7_PE15_FUNC_ANALOG 0x4f11 + +#define STM32H7_PF0_FUNC_GPIO 0x5000 +#define STM32H7_PF0_FUNC_I2C2_SDA 0x5005 +#define STM32H7_PF0_FUNC_FMC_A0 0x500d +#define STM32H7_PF0_FUNC_EVENTOUT 0x5010 +#define STM32H7_PF0_FUNC_ANALOG 0x5011 + +#define STM32H7_PF1_FUNC_GPIO 0x5100 +#define STM32H7_PF1_FUNC_I2C2_SCL 0x5105 +#define STM32H7_PF1_FUNC_FMC_A1 0x510d +#define STM32H7_PF1_FUNC_EVENTOUT 0x5110 +#define STM32H7_PF1_FUNC_ANALOG 0x5111 + +#define STM32H7_PF2_FUNC_GPIO 0x5200 +#define STM32H7_PF2_FUNC_I2C2_SMBA 0x5205 +#define STM32H7_PF2_FUNC_FMC_A2 0x520d +#define STM32H7_PF2_FUNC_EVENTOUT 0x5210 +#define STM32H7_PF2_FUNC_ANALOG 0x5211 + +#define STM32H7_PF3_FUNC_GPIO 0x5300 +#define STM32H7_PF3_FUNC_FMC_A3 0x530d +#define STM32H7_PF3_FUNC_EVENTOUT 0x5310 +#define STM32H7_PF3_FUNC_ANALOG 0x5311 + +#define STM32H7_PF4_FUNC_GPIO 0x5400 +#define STM32H7_PF4_FUNC_FMC_A4 0x540d +#define STM32H7_PF4_FUNC_EVENTOUT 0x5410 +#define STM32H7_PF4_FUNC_ANALOG 0x5411 + +#define STM32H7_PF5_FUNC_GPIO 0x5500 +#define STM32H7_PF5_FUNC_FMC_A5 0x550d +#define STM32H7_PF5_FUNC_EVENTOUT 0x5510 +#define STM32H7_PF5_FUNC_ANALOG 0x5511 + +#define STM32H7_PF6_FUNC_GPIO 0x5600 +#define STM32H7_PF6_FUNC_TIM16_CH1 0x5602 +#define STM32H7_PF6_FUNC_SPI5_NSS 0x5606 +#define STM32H7_PF6_FUNC_SAI1_SD_B 0x5607 +#define STM32H7_PF6_FUNC_UART7_RX 0x5608 +#define STM32H7_PF6_FUNC_SAI4_SD_B 0x5609 +#define STM32H7_PF6_FUNC_QUADSPI_BK1_IO3 0x560a +#define STM32H7_PF6_FUNC_EVENTOUT 0x5610 +#define STM32H7_PF6_FUNC_ANALOG 0x5611 + +#define STM32H7_PF7_FUNC_GPIO 0x5700 +#define STM32H7_PF7_FUNC_TIM17_CH1 0x5702 +#define STM32H7_PF7_FUNC_SPI5_SCK 0x5706 +#define STM32H7_PF7_FUNC_SAI1_MCLK_B 0x5707 +#define STM32H7_PF7_FUNC_UART7_TX 0x5708 +#define STM32H7_PF7_FUNC_SAI4_MCLK_B 0x5709 +#define STM32H7_PF7_FUNC_QUADSPI_BK1_IO2 0x570a +#define STM32H7_PF7_FUNC_EVENTOUT 0x5710 +#define STM32H7_PF7_FUNC_ANALOG 0x5711 + +#define STM32H7_PF8_FUNC_GPIO 0x5800 +#define STM32H7_PF8_FUNC_TIM16_CH1N 0x5802 +#define STM32H7_PF8_FUNC_SPI5_MISO 0x5806 +#define STM32H7_PF8_FUNC_SAI1_SCK_B 0x5807 +#define STM32H7_PF8_FUNC_UART7_RTS 0x5808 +#define STM32H7_PF8_FUNC_SAI4_SCK_B 0x5809 +#define STM32H7_PF8_FUNC_TIM13_CH1 0x580a +#define STM32H7_PF8_FUNC_QUADSPI_BK1_IO0 0x580b +#define STM32H7_PF8_FUNC_EVENTOUT 0x5810 +#define STM32H7_PF8_FUNC_ANALOG 0x5811 + +#define STM32H7_PF9_FUNC_GPIO 0x5900 +#define STM32H7_PF9_FUNC_TIM17_CH1N 0x5902 +#define STM32H7_PF9_FUNC_SPI5_MOSI 0x5906 +#define STM32H7_PF9_FUNC_SAI1_FS_B 0x5907 +#define STM32H7_PF9_FUNC_UART7_CTS 0x5908 +#define STM32H7_PF9_FUNC_SAI4_FS_B 0x5909 +#define STM32H7_PF9_FUNC_TIM14_CH1 0x590a +#define STM32H7_PF9_FUNC_QUADSPI_BK1_IO1 0x590b +#define STM32H7_PF9_FUNC_EVENTOUT 0x5910 +#define STM32H7_PF9_FUNC_ANALOG 0x5911 + +#define STM32H7_PF10_FUNC_GPIO 0x5a00 +#define STM32H7_PF10_FUNC_TIM16_BKIN 0x5a02 +#define STM32H7_PF10_FUNC_SAI1_D3 0x5a03 +#define STM32H7_PF10_FUNC_QUADSPI_CLK 0x5a0a +#define STM32H7_PF10_FUNC_SAI4_D3 0x5a0b +#define STM32H7_PF10_FUNC_DCMI_D11 0x5a0e +#define STM32H7_PF10_FUNC_LCD_DE 0x5a0f +#define STM32H7_PF10_FUNC_EVENTOUT 0x5a10 +#define STM32H7_PF10_FUNC_ANALOG 0x5a11 + +#define STM32H7_PF11_FUNC_GPIO 0x5b00 +#define STM32H7_PF11_FUNC_SPI5_MOSI 0x5b06 +#define STM32H7_PF11_FUNC_SAI2_SD_B 0x5b0b +#define STM32H7_PF11_FUNC_FMC_SDNRAS 0x5b0d +#define STM32H7_PF11_FUNC_DCMI_D12 0x5b0e +#define STM32H7_PF11_FUNC_EVENTOUT 0x5b10 +#define STM32H7_PF11_FUNC_ANALOG 0x5b11 + +#define STM32H7_PF12_FUNC_GPIO 0x5c00 +#define STM32H7_PF12_FUNC_FMC_A6 0x5c0d +#define STM32H7_PF12_FUNC_EVENTOUT 0x5c10 +#define STM32H7_PF12_FUNC_ANALOG 0x5c11 + +#define STM32H7_PF13_FUNC_GPIO 0x5d00 +#define STM32H7_PF13_FUNC_DFSDM_DATIN6 0x5d04 +#define STM32H7_PF13_FUNC_I2C4_SMBA 0x5d05 +#define STM32H7_PF13_FUNC_FMC_A7 0x5d0d +#define STM32H7_PF13_FUNC_EVENTOUT 0x5d10 +#define STM32H7_PF13_FUNC_ANALOG 0x5d11 + +#define STM32H7_PF14_FUNC_GPIO 0x5e00 +#define STM32H7_PF14_FUNC_DFSDM_CKIN6 0x5e04 +#define STM32H7_PF14_FUNC_I2C4_SCL 0x5e05 +#define STM32H7_PF14_FUNC_FMC_A8 0x5e0d +#define STM32H7_PF14_FUNC_EVENTOUT 0x5e10 +#define STM32H7_PF14_FUNC_ANALOG 0x5e11 + +#define STM32H7_PF15_FUNC_GPIO 0x5f00 +#define STM32H7_PF15_FUNC_I2C4_SDA 0x5f05 +#define STM32H7_PF15_FUNC_FMC_A9 0x5f0d +#define STM32H7_PF15_FUNC_EVENTOUT 0x5f10 +#define STM32H7_PF15_FUNC_ANALOG 0x5f11 + +#define STM32H7_PG0_FUNC_GPIO 0x6000 +#define STM32H7_PG0_FUNC_FMC_A10 0x600d +#define STM32H7_PG0_FUNC_EVENTOUT 0x6010 +#define STM32H7_PG0_FUNC_ANALOG 0x6011 + +#define STM32H7_PG1_FUNC_GPIO 0x6100 +#define STM32H7_PG1_FUNC_FMC_A11 0x610d +#define STM32H7_PG1_FUNC_EVENTOUT 0x6110 +#define STM32H7_PG1_FUNC_ANALOG 0x6111 + +#define STM32H7_PG2_FUNC_GPIO 0x6200 +#define STM32H7_PG2_FUNC_TIM8_BKIN 0x6204 +#define STM32H7_PG2_FUNC_TIM8_BKIN_COMP12 0x620c +#define STM32H7_PG2_FUNC_FMC_A12 0x620d +#define STM32H7_PG2_FUNC_EVENTOUT 0x6210 +#define STM32H7_PG2_FUNC_ANALOG 0x6211 + +#define STM32H7_PG3_FUNC_GPIO 0x6300 +#define STM32H7_PG3_FUNC_TIM8_BKIN2 0x6304 +#define STM32H7_PG3_FUNC_TIM8_BKIN2_COMP12 0x630c +#define STM32H7_PG3_FUNC_FMC_A13 0x630d +#define STM32H7_PG3_FUNC_EVENTOUT 0x6310 +#define STM32H7_PG3_FUNC_ANALOG 0x6311 + +#define STM32H7_PG4_FUNC_GPIO 0x6400 +#define STM32H7_PG4_FUNC_TIM1_BKIN2 0x6402 +#define STM32H7_PG4_FUNC_TIM1_BKIN2_COMP12 0x640c +#define STM32H7_PG4_FUNC_FMC_A14_FMC_BA0 0x640d +#define STM32H7_PG4_FUNC_EVENTOUT 0x6410 +#define STM32H7_PG4_FUNC_ANALOG 0x6411 + +#define STM32H7_PG5_FUNC_GPIO 0x6500 +#define STM32H7_PG5_FUNC_TIM1_ETR 0x6502 +#define STM32H7_PG5_FUNC_FMC_A15_FMC_BA1 0x650d +#define STM32H7_PG5_FUNC_EVENTOUT 0x6510 +#define STM32H7_PG5_FUNC_ANALOG 0x6511 + +#define STM32H7_PG6_FUNC_GPIO 0x6600 +#define STM32H7_PG6_FUNC_TIM17_BKIN 0x6602 +#define STM32H7_PG6_FUNC_HRTIM_CHE1 0x6603 +#define STM32H7_PG6_FUNC_QUADSPI_BK1_NCS 0x660b +#define STM32H7_PG6_FUNC_FMC_NE3 0x660d +#define STM32H7_PG6_FUNC_DCMI_D12 0x660e +#define STM32H7_PG6_FUNC_LCD_R7 0x660f +#define STM32H7_PG6_FUNC_EVENTOUT 0x6610 +#define STM32H7_PG6_FUNC_ANALOG 0x6611 + +#define STM32H7_PG7_FUNC_GPIO 0x6700 +#define STM32H7_PG7_FUNC_HRTIM_CHE2 0x6703 +#define STM32H7_PG7_FUNC_SAI1_MCLK_A 0x6707 +#define STM32H7_PG7_FUNC_USART6_CK 0x6708 +#define STM32H7_PG7_FUNC_FMC_INT 0x670d +#define STM32H7_PG7_FUNC_DCMI_D13 0x670e +#define STM32H7_PG7_FUNC_LCD_CLK 0x670f +#define STM32H7_PG7_FUNC_EVENTOUT 0x6710 +#define STM32H7_PG7_FUNC_ANALOG 0x6711 + +#define STM32H7_PG8_FUNC_GPIO 0x6800 +#define STM32H7_PG8_FUNC_TIM8_ETR 0x6804 +#define STM32H7_PG8_FUNC_SPI6_NSS 0x6806 +#define STM32H7_PG8_FUNC_USART6_RTS 0x6808 +#define STM32H7_PG8_FUNC_SPDIFRX_IN2 0x6809 +#define STM32H7_PG8_FUNC_ETH_PPS_OUT 0x680c +#define STM32H7_PG8_FUNC_FMC_SDCLK 0x680d +#define STM32H7_PG8_FUNC_LCD_G7 0x680f +#define STM32H7_PG8_FUNC_EVENTOUT 0x6810 +#define STM32H7_PG8_FUNC_ANALOG 0x6811 + +#define STM32H7_PG9_FUNC_GPIO 0x6900 +#define STM32H7_PG9_FUNC_SPI1_MISO_I2S1_SDI 0x6906 +#define STM32H7_PG9_FUNC_USART6_RX 0x6908 +#define STM32H7_PG9_FUNC_SPDIFRX_IN3 0x6909 +#define STM32H7_PG9_FUNC_QUADSPI_BK2_IO2 0x690a +#define STM32H7_PG9_FUNC_SAI2_FS_B 0x690b +#define STM32H7_PG9_FUNC_FMC_NE2_FMC_NCE 0x690d +#define STM32H7_PG9_FUNC_DCMI_VSYNC 0x690e +#define STM32H7_PG9_FUNC_EVENTOUT 0x6910 +#define STM32H7_PG9_FUNC_ANALOG 0x6911 + +#define STM32H7_PG10_FUNC_GPIO 0x6a00 +#define STM32H7_PG10_FUNC_HRTIM_FLT5 0x6a03 +#define STM32H7_PG10_FUNC_SPI1_NSS_I2S1_WS 0x6a06 +#define STM32H7_PG10_FUNC_LCD_G3 0x6a0a +#define STM32H7_PG10_FUNC_SAI2_SD_B 0x6a0b +#define STM32H7_PG10_FUNC_FMC_NE3 0x6a0d +#define STM32H7_PG10_FUNC_DCMI_D2 0x6a0e +#define STM32H7_PG10_FUNC_LCD_B2 0x6a0f +#define STM32H7_PG10_FUNC_EVENTOUT 0x6a10 +#define STM32H7_PG10_FUNC_ANALOG 0x6a11 + +#define STM32H7_PG11_FUNC_GPIO 0x6b00 +#define STM32H7_PG11_FUNC_HRTIM_EEV4 0x6b03 +#define STM32H7_PG11_FUNC_SPI1_SCK_I2S1_CK 0x6b06 +#define STM32H7_PG11_FUNC_SPDIFRX_IN0 0x6b09 +#define STM32H7_PG11_FUNC_SDMMC2_D2 0x6b0b +#define STM32H7_PG11_FUNC_ETH_MII_TX_EN_ETH_RMII_TX_EN 0x6b0c +#define STM32H7_PG11_FUNC_DCMI_D3 0x6b0e +#define STM32H7_PG11_FUNC_LCD_B3 0x6b0f +#define STM32H7_PG11_FUNC_EVENTOUT 0x6b10 +#define STM32H7_PG11_FUNC_ANALOG 0x6b11 + +#define STM32H7_PG12_FUNC_GPIO 0x6c00 +#define STM32H7_PG12_FUNC_LPTIM1_IN1 0x6c02 +#define STM32H7_PG12_FUNC_HRTIM_EEV5 0x6c03 +#define STM32H7_PG12_FUNC_SPI6_MISO 0x6c06 +#define STM32H7_PG12_FUNC_USART6_RTS 0x6c08 +#define STM32H7_PG12_FUNC_SPDIFRX_IN1 0x6c09 +#define STM32H7_PG12_FUNC_LCD_B4 0x6c0a +#define STM32H7_PG12_FUNC_ETH_MII_TXD1_ETH_RMII_TXD1 0x6c0c +#define STM32H7_PG12_FUNC_FMC_NE4 0x6c0d +#define STM32H7_PG12_FUNC_LCD_B1 0x6c0f +#define STM32H7_PG12_FUNC_EVENTOUT 0x6c10 +#define STM32H7_PG12_FUNC_ANALOG 0x6c11 + +#define STM32H7_PG13_FUNC_GPIO 0x6d00 +#define STM32H7_PG13_FUNC_TRACED0 0x6d01 +#define STM32H7_PG13_FUNC_LPTIM1_OUT 0x6d02 +#define STM32H7_PG13_FUNC_HRTIM_EEV10 0x6d03 +#define STM32H7_PG13_FUNC_SPI6_SCK 0x6d06 +#define STM32H7_PG13_FUNC_USART6_CTS_NSS 0x6d08 +#define STM32H7_PG13_FUNC_ETH_MII_TXD0_ETH_RMII_TXD0 0x6d0c +#define STM32H7_PG13_FUNC_FMC_A24 0x6d0d +#define STM32H7_PG13_FUNC_LCD_R0 0x6d0f +#define STM32H7_PG13_FUNC_EVENTOUT 0x6d10 +#define STM32H7_PG13_FUNC_ANALOG 0x6d11 + +#define STM32H7_PG14_FUNC_GPIO 0x6e00 +#define STM32H7_PG14_FUNC_TRACED1 0x6e01 +#define STM32H7_PG14_FUNC_LPTIM1_ETR 0x6e02 +#define STM32H7_PG14_FUNC_SPI6_MOSI 0x6e06 +#define STM32H7_PG14_FUNC_USART6_TX 0x6e08 +#define STM32H7_PG14_FUNC_QUADSPI_BK2_IO3 0x6e0a +#define STM32H7_PG14_FUNC_ETH_MII_TXD1_ETH_RMII_TXD1 0x6e0c +#define STM32H7_PG14_FUNC_FMC_A25 0x6e0d +#define STM32H7_PG14_FUNC_LCD_B0 0x6e0f +#define STM32H7_PG14_FUNC_EVENTOUT 0x6e10 +#define STM32H7_PG14_FUNC_ANALOG 0x6e11 + +#define STM32H7_PG15_FUNC_GPIO 0x6f00 +#define STM32H7_PG15_FUNC_USART6_CTS_NSS 0x6f08 +#define STM32H7_PG15_FUNC_FMC_SDNCAS 0x6f0d +#define STM32H7_PG15_FUNC_DCMI_D13 0x6f0e +#define STM32H7_PG15_FUNC_EVENTOUT 0x6f10 +#define STM32H7_PG15_FUNC_ANALOG 0x6f11 + +#define STM32H7_PH0_FUNC_GPIO 0x7000 +#define STM32H7_PH0_FUNC_EVENTOUT 0x7010 +#define STM32H7_PH0_FUNC_ANALOG 0x7011 + +#define STM32H7_PH1_FUNC_GPIO 0x7100 +#define STM32H7_PH1_FUNC_EVENTOUT 0x7110 +#define STM32H7_PH1_FUNC_ANALOG 0x7111 + +#define STM32H7_PH2_FUNC_GPIO 0x7200 +#define STM32H7_PH2_FUNC_LPTIM1_IN2 0x7202 +#define STM32H7_PH2_FUNC_QUADSPI_BK2_IO0 0x720a +#define STM32H7_PH2_FUNC_SAI2_SCK_B 0x720b +#define STM32H7_PH2_FUNC_ETH_MII_CRS 0x720c +#define STM32H7_PH2_FUNC_FMC_SDCKE0 0x720d +#define STM32H7_PH2_FUNC_LCD_R0 0x720f +#define STM32H7_PH2_FUNC_EVENTOUT 0x7210 +#define STM32H7_PH2_FUNC_ANALOG 0x7211 + +#define STM32H7_PH3_FUNC_GPIO 0x7300 +#define STM32H7_PH3_FUNC_QUADSPI_BK2_IO1 0x730a +#define STM32H7_PH3_FUNC_SAI2_MCK_B 0x730b +#define STM32H7_PH3_FUNC_ETH_MII_COL 0x730c +#define STM32H7_PH3_FUNC_FMC_SDNE0 0x730d +#define STM32H7_PH3_FUNC_LCD_R1 0x730f +#define STM32H7_PH3_FUNC_EVENTOUT 0x7310 +#define STM32H7_PH3_FUNC_ANALOG 0x7311 + +#define STM32H7_PH4_FUNC_GPIO 0x7400 +#define STM32H7_PH4_FUNC_I2C2_SCL 0x7405 +#define STM32H7_PH4_FUNC_LCD_G5 0x740a +#define STM32H7_PH4_FUNC_OTG_HS_ULPI_NXT 0x740b +#define STM32H7_PH4_FUNC_LCD_G4 0x740f +#define STM32H7_PH4_FUNC_EVENTOUT 0x7410 +#define STM32H7_PH4_FUNC_ANALOG 0x7411 + +#define STM32H7_PH5_FUNC_GPIO 0x7500 +#define STM32H7_PH5_FUNC_I2C2_SDA 0x7505 +#define STM32H7_PH5_FUNC_SPI5_NSS 0x7506 +#define STM32H7_PH5_FUNC_FMC_SDNWE 0x750d +#define STM32H7_PH5_FUNC_EVENTOUT 0x7510 +#define STM32H7_PH5_FUNC_ANALOG 0x7511 + +#define STM32H7_PH6_FUNC_GPIO 0x7600 +#define STM32H7_PH6_FUNC_I2C2_SMBA 0x7605 +#define STM32H7_PH6_FUNC_SPI5_SCK 0x7606 +#define STM32H7_PH6_FUNC_ETH_MII_RXD2 0x760c +#define STM32H7_PH6_FUNC_FMC_SDNE1 0x760d +#define STM32H7_PH6_FUNC_DCMI_D8 0x760e +#define STM32H7_PH6_FUNC_EVENTOUT 0x7610 +#define STM32H7_PH6_FUNC_ANALOG 0x7611 + +#define STM32H7_PH7_FUNC_GPIO 0x7700 +#define STM32H7_PH7_FUNC_I2C3_SCL 0x7705 +#define STM32H7_PH7_FUNC_SPI5_MISO 0x7706 +#define STM32H7_PH7_FUNC_ETH_MII_RXD3 0x770c +#define STM32H7_PH7_FUNC_FMC_SDCKE1 0x770d +#define STM32H7_PH7_FUNC_DCMI_D9 0x770e +#define STM32H7_PH7_FUNC_EVENTOUT 0x7710 +#define STM32H7_PH7_FUNC_ANALOG 0x7711 + +#define STM32H7_PH8_FUNC_GPIO 0x7800 +#define STM32H7_PH8_FUNC_TIM5_ETR 0x7803 +#define STM32H7_PH8_FUNC_I2C3_SDA 0x7805 +#define STM32H7_PH8_FUNC_FMC_D16 0x780d +#define STM32H7_PH8_FUNC_DCMI_HSYNC 0x780e +#define STM32H7_PH8_FUNC_LCD_R2 0x780f +#define STM32H7_PH8_FUNC_EVENTOUT 0x7810 +#define STM32H7_PH8_FUNC_ANALOG 0x7811 + +#define STM32H7_PH9_FUNC_GPIO 0x7900 +#define STM32H7_PH9_FUNC_I2C3_SMBA 0x7905 +#define STM32H7_PH9_FUNC_FMC_D17 0x790d +#define STM32H7_PH9_FUNC_DCMI_D0 0x790e +#define STM32H7_PH9_FUNC_LCD_R3 0x790f +#define STM32H7_PH9_FUNC_EVENTOUT 0x7910 +#define STM32H7_PH9_FUNC_ANALOG 0x7911 + +#define STM32H7_PH10_FUNC_GPIO 0x7a00 +#define STM32H7_PH10_FUNC_TIM5_CH1 0x7a03 +#define STM32H7_PH10_FUNC_I2C4_SMBA 0x7a05 +#define STM32H7_PH10_FUNC_FMC_D18 0x7a0d +#define STM32H7_PH10_FUNC_DCMI_D1 0x7a0e +#define STM32H7_PH10_FUNC_LCD_R4 0x7a0f +#define STM32H7_PH10_FUNC_EVENTOUT 0x7a10 +#define STM32H7_PH10_FUNC_ANALOG 0x7a11 + +#define STM32H7_PH11_FUNC_GPIO 0x7b00 +#define STM32H7_PH11_FUNC_TIM5_CH2 0x7b03 +#define STM32H7_PH11_FUNC_I2C4_SCL 0x7b05 +#define STM32H7_PH11_FUNC_FMC_D19 0x7b0d +#define STM32H7_PH11_FUNC_DCMI_D2 0x7b0e +#define STM32H7_PH11_FUNC_LCD_R5 0x7b0f +#define STM32H7_PH11_FUNC_EVENTOUT 0x7b10 +#define STM32H7_PH11_FUNC_ANALOG 0x7b11 + +#define STM32H7_PH12_FUNC_GPIO 0x7c00 +#define STM32H7_PH12_FUNC_TIM5_CH3 0x7c03 +#define STM32H7_PH12_FUNC_I2C4_SDA 0x7c05 +#define STM32H7_PH12_FUNC_FMC_D20 0x7c0d +#define STM32H7_PH12_FUNC_DCMI_D3 0x7c0e +#define STM32H7_PH12_FUNC_LCD_R6 0x7c0f +#define STM32H7_PH12_FUNC_EVENTOUT 0x7c10 +#define STM32H7_PH12_FUNC_ANALOG 0x7c11 + +#define STM32H7_PH13_FUNC_GPIO 0x7d00 +#define STM32H7_PH13_FUNC_TIM8_CH1N 0x7d04 +#define STM32H7_PH13_FUNC_UART4_TX 0x7d09 +#define STM32H7_PH13_FUNC_CAN1_TX 0x7d0a +#define STM32H7_PH13_FUNC_FMC_D21 0x7d0d +#define STM32H7_PH13_FUNC_LCD_G2 0x7d0f +#define STM32H7_PH13_FUNC_EVENTOUT 0x7d10 +#define STM32H7_PH13_FUNC_ANALOG 0x7d11 + +#define STM32H7_PH14_FUNC_GPIO 0x7e00 +#define STM32H7_PH14_FUNC_TIM8_CH2N 0x7e04 +#define STM32H7_PH14_FUNC_UART4_RX 0x7e09 +#define STM32H7_PH14_FUNC_CAN1_RX 0x7e0a +#define STM32H7_PH14_FUNC_FMC_D22 0x7e0d +#define STM32H7_PH14_FUNC_DCMI_D4 0x7e0e +#define STM32H7_PH14_FUNC_LCD_G3 0x7e0f +#define STM32H7_PH14_FUNC_EVENTOUT 0x7e10 +#define STM32H7_PH14_FUNC_ANALOG 0x7e11 + +#define STM32H7_PH15_FUNC_GPIO 0x7f00 +#define STM32H7_PH15_FUNC_TIM8_CH3N 0x7f04 +#define STM32H7_PH15_FUNC_CAN1_TXFD 0x7f0a +#define STM32H7_PH15_FUNC_FMC_D23 0x7f0d +#define STM32H7_PH15_FUNC_DCMI_D11 0x7f0e +#define STM32H7_PH15_FUNC_LCD_G4 0x7f0f +#define STM32H7_PH15_FUNC_EVENTOUT 0x7f10 +#define STM32H7_PH15_FUNC_ANALOG 0x7f11 + +#define STM32H7_PI0_FUNC_GPIO 0x8000 +#define STM32H7_PI0_FUNC_TIM5_CH4 0x8003 +#define STM32H7_PI0_FUNC_SPI2_NSS_I2S2_WS 0x8006 +#define STM32H7_PI0_FUNC_CAN1_RXFD 0x800a +#define STM32H7_PI0_FUNC_FMC_D24 0x800d +#define STM32H7_PI0_FUNC_DCMI_D13 0x800e +#define STM32H7_PI0_FUNC_LCD_G5 0x800f +#define STM32H7_PI0_FUNC_EVENTOUT 0x8010 +#define STM32H7_PI0_FUNC_ANALOG 0x8011 + +#define STM32H7_PI1_FUNC_GPIO 0x8100 +#define STM32H7_PI1_FUNC_TIM8_BKIN2 0x8104 +#define STM32H7_PI1_FUNC_SPI2_SCK_I2S2_CK 0x8106 +#define STM32H7_PI1_FUNC_TIM8_BKIN2_COMP12 0x810c +#define STM32H7_PI1_FUNC_FMC_D25 0x810d +#define STM32H7_PI1_FUNC_DCMI_D8 0x810e +#define STM32H7_PI1_FUNC_LCD_G6 0x810f +#define STM32H7_PI1_FUNC_EVENTOUT 0x8110 +#define STM32H7_PI1_FUNC_ANALOG 0x8111 + +#define STM32H7_PI2_FUNC_GPIO 0x8200 +#define STM32H7_PI2_FUNC_TIM8_CH4 0x8204 +#define STM32H7_PI2_FUNC_SPI2_MISO_I2S2_SDI 0x8206 +#define STM32H7_PI2_FUNC_FMC_D26 0x820d +#define STM32H7_PI2_FUNC_DCMI_D9 0x820e +#define STM32H7_PI2_FUNC_LCD_G7 0x820f +#define STM32H7_PI2_FUNC_EVENTOUT 0x8210 +#define STM32H7_PI2_FUNC_ANALOG 0x8211 + +#define STM32H7_PI3_FUNC_GPIO 0x8300 +#define STM32H7_PI3_FUNC_TIM8_ETR 0x8304 +#define STM32H7_PI3_FUNC_SPI2_MOSI_I2S2_SDO 0x8306 +#define STM32H7_PI3_FUNC_FMC_D27 0x830d +#define STM32H7_PI3_FUNC_DCMI_D10 0x830e +#define STM32H7_PI3_FUNC_EVENTOUT 0x8310 +#define STM32H7_PI3_FUNC_ANALOG 0x8311 + +#define STM32H7_PI4_FUNC_GPIO 0x8400 +#define STM32H7_PI4_FUNC_TIM8_BKIN 0x8404 +#define STM32H7_PI4_FUNC_SAI2_MCK_A 0x840b +#define STM32H7_PI4_FUNC_TIM8_BKIN_COMP12 0x840c +#define STM32H7_PI4_FUNC_FMC_NBL2 0x840d +#define STM32H7_PI4_FUNC_DCMI_D5 0x840e +#define STM32H7_PI4_FUNC_LCD_B4 0x840f +#define STM32H7_PI4_FUNC_EVENTOUT 0x8410 +#define STM32H7_PI4_FUNC_ANALOG 0x8411 + +#define STM32H7_PI5_FUNC_GPIO 0x8500 +#define STM32H7_PI5_FUNC_TIM8_CH1 0x8504 +#define STM32H7_PI5_FUNC_SAI2_SCK_A 0x850b +#define STM32H7_PI5_FUNC_FMC_NBL3 0x850d +#define STM32H7_PI5_FUNC_DCMI_VSYNC 0x850e +#define STM32H7_PI5_FUNC_LCD_B5 0x850f +#define STM32H7_PI5_FUNC_EVENTOUT 0x8510 +#define STM32H7_PI5_FUNC_ANALOG 0x8511 + +#define STM32H7_PI6_FUNC_GPIO 0x8600 +#define STM32H7_PI6_FUNC_TIM8_CH2 0x8604 +#define STM32H7_PI6_FUNC_SAI2_SD_A 0x860b +#define STM32H7_PI6_FUNC_FMC_D28 0x860d +#define STM32H7_PI6_FUNC_DCMI_D6 0x860e +#define STM32H7_PI6_FUNC_LCD_B6 0x860f +#define STM32H7_PI6_FUNC_EVENTOUT 0x8610 +#define STM32H7_PI6_FUNC_ANALOG 0x8611 + +#define STM32H7_PI7_FUNC_GPIO 0x8700 +#define STM32H7_PI7_FUNC_TIM8_CH3 0x8704 +#define STM32H7_PI7_FUNC_SAI2_FS_A 0x870b +#define STM32H7_PI7_FUNC_FMC_D29 0x870d +#define STM32H7_PI7_FUNC_DCMI_D7 0x870e +#define STM32H7_PI7_FUNC_LCD_B7 0x870f +#define STM32H7_PI7_FUNC_EVENTOUT 0x8710 +#define STM32H7_PI7_FUNC_ANALOG 0x8711 + +#define STM32H7_PI8_FUNC_GPIO 0x8800 +#define STM32H7_PI8_FUNC_EVENTOUT 0x8810 +#define STM32H7_PI8_FUNC_ANALOG 0x8811 + +#define STM32H7_PI9_FUNC_GPIO 0x8900 +#define STM32H7_PI9_FUNC_UART4_RX 0x8909 +#define STM32H7_PI9_FUNC_CAN1_RX 0x890a +#define STM32H7_PI9_FUNC_FMC_D30 0x890d +#define STM32H7_PI9_FUNC_LCD_VSYNC 0x890f +#define STM32H7_PI9_FUNC_EVENTOUT 0x8910 +#define STM32H7_PI9_FUNC_ANALOG 0x8911 + +#define STM32H7_PI10_FUNC_GPIO 0x8a00 +#define STM32H7_PI10_FUNC_CAN1_RXFD 0x8a0a +#define STM32H7_PI10_FUNC_ETH_MII_RX_ER 0x8a0c +#define STM32H7_PI10_FUNC_FMC_D31 0x8a0d +#define STM32H7_PI10_FUNC_LCD_HSYNC 0x8a0f +#define STM32H7_PI10_FUNC_EVENTOUT 0x8a10 +#define STM32H7_PI10_FUNC_ANALOG 0x8a11 + +#define STM32H7_PI11_FUNC_GPIO 0x8b00 +#define STM32H7_PI11_FUNC_LCD_G6 0x8b0a +#define STM32H7_PI11_FUNC_OTG_HS_ULPI_DIR 0x8b0b +#define STM32H7_PI11_FUNC_EVENTOUT 0x8b10 +#define STM32H7_PI11_FUNC_ANALOG 0x8b11 + +#define STM32H7_PI12_FUNC_GPIO 0x8c00 +#define STM32H7_PI12_FUNC_ETH_TX_ER 0x8c0c +#define STM32H7_PI12_FUNC_LCD_HSYNC 0x8c0f +#define STM32H7_PI12_FUNC_EVENTOUT 0x8c10 +#define STM32H7_PI12_FUNC_ANALOG 0x8c11 + +#define STM32H7_PI13_FUNC_GPIO 0x8d00 +#define STM32H7_PI13_FUNC_LCD_VSYNC 0x8d0f +#define STM32H7_PI13_FUNC_EVENTOUT 0x8d10 +#define STM32H7_PI13_FUNC_ANALOG 0x8d11 + +#define STM32H7_PI14_FUNC_GPIO 0x8e00 +#define STM32H7_PI14_FUNC_LCD_CLK 0x8e0f +#define STM32H7_PI14_FUNC_EVENTOUT 0x8e10 +#define STM32H7_PI14_FUNC_ANALOG 0x8e11 + +#define STM32H7_PI15_FUNC_GPIO 0x8f00 +#define STM32H7_PI15_FUNC_LCD_G2 0x8f0a +#define STM32H7_PI15_FUNC_LCD_R0 0x8f0f +#define STM32H7_PI15_FUNC_EVENTOUT 0x8f10 +#define STM32H7_PI15_FUNC_ANALOG 0x8f11 + +#define STM32H7_PJ0_FUNC_GPIO 0x9000 +#define STM32H7_PJ0_FUNC_LCD_R7 0x900a +#define STM32H7_PJ0_FUNC_LCD_R1 0x900f +#define STM32H7_PJ0_FUNC_EVENTOUT 0x9010 +#define STM32H7_PJ0_FUNC_ANALOG 0x9011 + +#define STM32H7_PJ1_FUNC_GPIO 0x9100 +#define STM32H7_PJ1_FUNC_LCD_R2 0x910f +#define STM32H7_PJ1_FUNC_EVENTOUT 0x9110 +#define STM32H7_PJ1_FUNC_ANALOG 0x9111 + +#define STM32H7_PJ2_FUNC_GPIO 0x9200 +#define STM32H7_PJ2_FUNC_DSI_TE 0x920e +#define STM32H7_PJ2_FUNC_LCD_R3 0x920f +#define STM32H7_PJ2_FUNC_EVENTOUT 0x9210 +#define STM32H7_PJ2_FUNC_ANALOG 0x9211 + +#define STM32H7_PJ3_FUNC_GPIO 0x9300 +#define STM32H7_PJ3_FUNC_LCD_R4 0x930f +#define STM32H7_PJ3_FUNC_EVENTOUT 0x9310 +#define STM32H7_PJ3_FUNC_ANALOG 0x9311 + +#define STM32H7_PJ4_FUNC_GPIO 0x9400 +#define STM32H7_PJ4_FUNC_LCD_R5 0x940f +#define STM32H7_PJ4_FUNC_EVENTOUT 0x9410 +#define STM32H7_PJ4_FUNC_ANALOG 0x9411 + +#define STM32H7_PJ5_FUNC_GPIO 0x9500 +#define STM32H7_PJ5_FUNC_LCD_R6 0x950f +#define STM32H7_PJ5_FUNC_EVENTOUT 0x9510 +#define STM32H7_PJ5_FUNC_ANALOG 0x9511 + +#define STM32H7_PJ6_FUNC_GPIO 0x9600 +#define STM32H7_PJ6_FUNC_TIM8_CH2 0x9604 +#define STM32H7_PJ6_FUNC_LCD_R7 0x960f +#define STM32H7_PJ6_FUNC_EVENTOUT 0x9610 +#define STM32H7_PJ6_FUNC_ANALOG 0x9611 + +#define STM32H7_PJ7_FUNC_GPIO 0x9700 +#define STM32H7_PJ7_FUNC_TRGIN 0x9701 +#define STM32H7_PJ7_FUNC_TIM8_CH2N 0x9704 +#define STM32H7_PJ7_FUNC_LCD_G0 0x970f +#define STM32H7_PJ7_FUNC_EVENTOUT 0x9710 +#define STM32H7_PJ7_FUNC_ANALOG 0x9711 + +#define STM32H7_PJ8_FUNC_GPIO 0x9800 +#define STM32H7_PJ8_FUNC_TIM1_CH3N 0x9802 +#define STM32H7_PJ8_FUNC_TIM8_CH1 0x9804 +#define STM32H7_PJ8_FUNC_UART8_TX 0x9809 +#define STM32H7_PJ8_FUNC_LCD_G1 0x980f +#define STM32H7_PJ8_FUNC_EVENTOUT 0x9810 +#define STM32H7_PJ8_FUNC_ANALOG 0x9811 + +#define STM32H7_PJ9_FUNC_GPIO 0x9900 +#define STM32H7_PJ9_FUNC_TIM1_CH3 0x9902 +#define STM32H7_PJ9_FUNC_TIM8_CH1N 0x9904 +#define STM32H7_PJ9_FUNC_UART8_RX 0x9909 +#define STM32H7_PJ9_FUNC_LCD_G2 0x990f +#define STM32H7_PJ9_FUNC_EVENTOUT 0x9910 +#define STM32H7_PJ9_FUNC_ANALOG 0x9911 + +#define STM32H7_PJ10_FUNC_GPIO 0x9a00 +#define STM32H7_PJ10_FUNC_TIM1_CH2N 0x9a02 +#define STM32H7_PJ10_FUNC_TIM8_CH2 0x9a04 +#define STM32H7_PJ10_FUNC_SPI5_MOSI 0x9a06 +#define STM32H7_PJ10_FUNC_LCD_G3 0x9a0f +#define STM32H7_PJ10_FUNC_EVENTOUT 0x9a10 +#define STM32H7_PJ10_FUNC_ANALOG 0x9a11 + +#define STM32H7_PJ11_FUNC_GPIO 0x9b00 +#define STM32H7_PJ11_FUNC_TIM1_CH2 0x9b02 +#define STM32H7_PJ11_FUNC_TIM8_CH2N 0x9b04 +#define STM32H7_PJ11_FUNC_SPI5_MISO 0x9b06 +#define STM32H7_PJ11_FUNC_LCD_G4 0x9b0f +#define STM32H7_PJ11_FUNC_EVENTOUT 0x9b10 +#define STM32H7_PJ11_FUNC_ANALOG 0x9b11 + +#define STM32H7_PJ12_FUNC_GPIO 0x9c00 +#define STM32H7_PJ12_FUNC_TRGOUT 0x9c01 +#define STM32H7_PJ12_FUNC_LCD_G3 0x9c0a +#define STM32H7_PJ12_FUNC_LCD_B0 0x9c0f +#define STM32H7_PJ12_FUNC_EVENTOUT 0x9c10 +#define STM32H7_PJ12_FUNC_ANALOG 0x9c11 + +#define STM32H7_PJ13_FUNC_GPIO 0x9d00 +#define STM32H7_PJ13_FUNC_LCD_B4 0x9d0a +#define STM32H7_PJ13_FUNC_LCD_B1 0x9d0f +#define STM32H7_PJ13_FUNC_EVENTOUT 0x9d10 +#define STM32H7_PJ13_FUNC_ANALOG 0x9d11 + +#define STM32H7_PJ14_FUNC_GPIO 0x9e00 +#define STM32H7_PJ14_FUNC_LCD_B2 0x9e0f +#define STM32H7_PJ14_FUNC_EVENTOUT 0x9e10 +#define STM32H7_PJ14_FUNC_ANALOG 0x9e11 + +#define STM32H7_PJ15_FUNC_GPIO 0x9f00 +#define STM32H7_PJ15_FUNC_LCD_B3 0x9f0f +#define STM32H7_PJ15_FUNC_EVENTOUT 0x9f10 +#define STM32H7_PJ15_FUNC_ANALOG 0x9f11 + +#define STM32H7_PK0_FUNC_GPIO 0xa000 +#define STM32H7_PK0_FUNC_TIM1_CH1N 0xa002 +#define STM32H7_PK0_FUNC_TIM8_CH3 0xa004 +#define STM32H7_PK0_FUNC_SPI5_SCK 0xa006 +#define STM32H7_PK0_FUNC_LCD_G5 0xa00f +#define STM32H7_PK0_FUNC_EVENTOUT 0xa010 +#define STM32H7_PK0_FUNC_ANALOG 0xa011 + +#define STM32H7_PK1_FUNC_GPIO 0xa100 +#define STM32H7_PK1_FUNC_TIM1_CH1 0xa102 +#define STM32H7_PK1_FUNC_TIM8_CH3N 0xa104 +#define STM32H7_PK1_FUNC_SPI5_NSS 0xa106 +#define STM32H7_PK1_FUNC_LCD_G6 0xa10f +#define STM32H7_PK1_FUNC_EVENTOUT 0xa110 +#define STM32H7_PK1_FUNC_ANALOG 0xa111 + +#define STM32H7_PK2_FUNC_GPIO 0xa200 +#define STM32H7_PK2_FUNC_TIM1_BKIN 0xa202 +#define STM32H7_PK2_FUNC_TIM8_BKIN 0xa204 +#define STM32H7_PK2_FUNC_TIM8_BKIN_COMP12 0xa20b +#define STM32H7_PK2_FUNC_TIM1_BKIN_COMP12 0xa20c +#define STM32H7_PK2_FUNC_LCD_G7 0xa20f +#define STM32H7_PK2_FUNC_EVENTOUT 0xa210 +#define STM32H7_PK2_FUNC_ANALOG 0xa211 + +#define STM32H7_PK3_FUNC_GPIO 0xa300 +#define STM32H7_PK3_FUNC_LCD_B4 0xa30f +#define STM32H7_PK3_FUNC_EVENTOUT 0xa310 +#define STM32H7_PK3_FUNC_ANALOG 0xa311 + +#define STM32H7_PK4_FUNC_GPIO 0xa400 +#define STM32H7_PK4_FUNC_LCD_B5 0xa40f +#define STM32H7_PK4_FUNC_EVENTOUT 0xa410 +#define STM32H7_PK4_FUNC_ANALOG 0xa411 + +#define STM32H7_PK5_FUNC_GPIO 0xa500 +#define STM32H7_PK5_FUNC_LCD_B6 0xa50f +#define STM32H7_PK5_FUNC_EVENTOUT 0xa510 +#define STM32H7_PK5_FUNC_ANALOG 0xa511 + +#define STM32H7_PK6_FUNC_GPIO 0xa600 +#define STM32H7_PK6_FUNC_LCD_B7 0xa60f +#define STM32H7_PK6_FUNC_EVENTOUT 0xa610 +#define STM32H7_PK6_FUNC_ANALOG 0xa611 + +#define STM32H7_PK7_FUNC_GPIO 0xa700 +#define STM32H7_PK7_FUNC_LCD_DE 0xa70f +#define STM32H7_PK7_FUNC_EVENTOUT 0xa710 +#define STM32H7_PK7_FUNC_ANALOG 0xa711 + +#endif /* _DT_BINDINGS_STM32H7_PINFUNC_H */ diff --git a/include/dwc3-sti-glue.h b/include/dwc3-sti-glue.h new file mode 100644 index 0000000000..98e76961b6 --- /dev/null +++ b/include/dwc3-sti-glue.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2017 + * Patrice Chotard <patrice.chotard@st.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __DWC3_STI_UBOOT_H_ +#define __DWC3_STI_UBOOT_H_ + +/* glue registers */ +#define CLKRST_CTRL 0x00 +#define AUX_CLK_EN BIT(0) +#define SW_PIPEW_RESET_N BIT(4) +#define EXT_CFG_RESET_N BIT(8) + +#define XHCI_REVISION BIT(12) + +#define USB2_VBUS_MNGMNT_SEL1 0x2C +#define USB2_VBUS_UTMIOTG 0x1 + +#define SEL_OVERRIDE_VBUSVALID(n) ((n) << 0) +#define SEL_OVERRIDE_POWERPRESENT(n) ((n) << 4) +#define SEL_OVERRIDE_BVALID(n) ((n) << 8) + +/* Static DRD configuration */ +#define USB3_CONTROL_MASK 0xf77 + +#define USB3_DEVICE_NOT_HOST BIT(0) +#define USB3_FORCE_VBUSVALID BIT(1) +#define USB3_DELAY_VBUSVALID BIT(2) +#define USB3_SEL_FORCE_OPMODE BIT(4) +#define USB3_FORCE_OPMODE(n) ((n) << 5) +#define USB3_SEL_FORCE_DPPULLDOWN2 BIT(8) +#define USB3_FORCE_DPPULLDOWN2 BIT(9) +#define USB3_SEL_FORCE_DMPULLDOWN2 BIT(10) +#define USB3_FORCE_DMPULLDOWN2 BIT(11) + +int sti_dwc3_init(enum usb_dr_mode mode); + +#endif /* __DWC3_STI_UBOOT_H_ */ diff --git a/include/environment/ti/boot.h b/include/environment/ti/boot.h index 5b1b97bafe..799d9840aa 100644 --- a/include/environment/ti/boot.h +++ b/include/environment/ti/boot.h @@ -29,7 +29,14 @@ "partitions=" PARTS_DEFAULT "\0" \ "optargs=\0" \ "dofastboot=0\0" \ + "emmc_linux_boot=" \ + "echo Trying to boot Linux from eMMC ...; " \ + "setenv mmcdev 1; " \ + "setenv bootpart 1:2; " \ + "setenv mmcroot /dev/mmcblk0p2 rw; " \ + "run mmcboot;\0" \ "emmc_android_boot=" \ + "echo Trying to boot Android from eMMC ...; " \ "setenv eval_bootargs setenv bootargs $bootargs; " \ "run eval_bootargs; " \ "setenv mmcdev 1; " \ @@ -44,7 +51,6 @@ "part size mmc ${mmcdev} ${boot_part} boot_size; " \ "mmc read ${fdtaddr} ${fdt_start} ${fdt_size}; " \ "mmc read ${loadaddr} ${boot_start} ${boot_size}; " \ - "echo Booting from eMMC ...; " \ "bootm $loadaddr $loadaddr $fdtaddr;\0" #ifdef CONFIG_OMAP54XX @@ -93,10 +99,7 @@ "run findfdt; " \ "run envboot; " \ "run mmcboot;" \ - "setenv mmcdev 1; " \ - "setenv bootpart 1:2; " \ - "setenv mmcroot /dev/mmcblk0p2 rw; " \ - "run mmcboot;" \ + "run emmc_linux_boot; " \ "run emmc_android_boot; " \ "" diff --git a/include/flash.h b/include/flash.h index f53fe91349..dc67cb2df6 100644 --- a/include/flash.h +++ b/include/flash.h @@ -42,11 +42,16 @@ typedef struct { ushort cfi_offset; /* offset for cfi query */ ulong addr_unlock1; /* unlock address 1 for AMD flash roms */ ulong addr_unlock2; /* unlock address 2 for AMD flash roms */ + uchar sr_supported; /* status register supported */ const char *name; /* human-readable name */ #endif #ifdef CONFIG_MTD struct mtd_info *mtd; #endif +#ifdef CONFIG_CFI_FLASH /* DM-specific parts */ + struct udevice *dev; + phys_addr_t base; +#endif } flash_info_t; extern flash_info_t flash_info[]; /* info for FLASH chips */ diff --git a/include/mtd/cfi_flash.h b/include/mtd/cfi_flash.h index eade2b3614..095725a805 100644 --- a/include/mtd/cfi_flash.h +++ b/include/mtd/cfi_flash.h @@ -62,6 +62,7 @@ #define FLASH_OFFSET_MANUFACTURER_ID 0x00 #define FLASH_OFFSET_DEVICE_ID 0x01 +#define FLASH_OFFSET_LOWER_SW_BITS 0x0C #define FLASH_OFFSET_DEVICE_ID2 0x0E #define FLASH_OFFSET_DEVICE_ID3 0x0F #define FLASH_OFFSET_CFI 0x55 diff --git a/include/usb.h b/include/usb.h index fad04016a3..0ddc0822b4 100644 --- a/include/usb.h +++ b/include/usb.h @@ -766,6 +766,14 @@ struct dm_usb_ops { * representation of this hub can be updated (xHCI) */ int (*update_hub_device)(struct udevice *bus, struct usb_device *udev); + + /** + * get_max_xfer_size() - Get HCD's maximum transfer bytes + * + * The HCD may have limitation on the maximum bytes to be transferred + * in a USB transfer. USB class driver needs to be aware of this. + */ + int (*get_max_xfer_size)(struct udevice *bus, size_t *size); }; #define usb_get_ops(dev) ((struct dm_usb_ops *)(dev)->driver->ops) @@ -939,7 +947,7 @@ int usb_new_device(struct usb_device *dev); int usb_alloc_device(struct usb_device *dev); /** - * update_hub_device() - Update HCD's internal representation of hub + * usb_update_hub_device() - Update HCD's internal representation of hub * * After a hub descriptor is fetched, notify HCD so that its internal * representation of this hub can be updated. @@ -950,6 +958,18 @@ int usb_alloc_device(struct usb_device *dev); int usb_update_hub_device(struct usb_device *dev); /** + * usb_get_max_xfer_size() - Get HCD's maximum transfer bytes + * + * The HCD may have limitation on the maximum bytes to be transferred + * in a USB transfer. USB class driver needs to be aware of this. + * + * @dev: USB device + * @size: maximum transfer bytes + * @return 0 if OK, -ve on error + */ +int usb_get_max_xfer_size(struct usb_device *dev, size_t *size); + +/** * usb_emul_setup_device() - Set up a new USB device emulation * * This is normally called when a new emulation device is bound. It tells diff --git a/include/usb/ehci-ci.h b/include/usb/ehci-ci.h index cd3eb47da4..59bfc14df6 100644 --- a/include/usb/ehci-ci.h +++ b/include/usb/ehci-ci.h @@ -156,7 +156,7 @@ #elif defined(CONFIG_MPC85xx) #define CONFIG_SYS_FSL_USB1_ADDR CONFIG_SYS_MPC85xx_USB1_ADDR #define CONFIG_SYS_FSL_USB2_ADDR CONFIG_SYS_MPC85xx_USB2_ADDR -#elif defined(CONFIG_LS102XA) || defined(CONFIG_ARCH_LS1012A) +#elif defined(CONFIG_ARCH_LS1021A) || defined(CONFIG_ARCH_LS1012A) #define CONFIG_SYS_FSL_USB1_ADDR CONFIG_SYS_EHCI_USB1_ADDR #define CONFIG_SYS_FSL_USB2_ADDR 0 #endif diff --git a/net/tftp.c b/net/tftp.c index a5ed8c5d0a..6671b1f7ca 100644 --- a/net/tftp.c +++ b/net/tftp.c @@ -805,7 +805,9 @@ void tftp_start(enum proto_t protocol) printf("Load address: 0x%lx\n", load_addr); puts("Loading: *\b"); tftp_state = STATE_SEND_RRQ; +#ifdef CONFIG_CMD_BOOTEFI efi_set_bootdev("Net", "", tftp_filename); +#endif } time_start = get_timer(0); diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include index a3a5c59d0d..2c7918ad37 100644 --- a/scripts/Kbuild.include +++ b/scripts/Kbuild.include @@ -172,11 +172,6 @@ ld-version = $(shell $(LD) --version | $(srctree)/scripts/ld-version.sh) # Usage: $(call ld-ifversion, -ge, 22252, y) ld-ifversion = $(shell [ $(ld-version) $(1) $(2) ] && echo $(3) || echo $(4)) -# dtc-option -# Usage: DTC_FLAGS += $(call dtc-option,-Wno-unit_address_vs_reg) -dtc-option = $(call try-run,\ - echo '/dts-v1/; / {};' | $(DTC) $(1),$(1),$(2)) - ###### ### diff --git a/scripts/Makefile b/scripts/Makefile index 3e10c16d59..9d55241463 100644 --- a/scripts/Makefile +++ b/scripts/Makefile @@ -21,3 +21,4 @@ build_docproc: $(obj)/docproc # Let clean descend into subdirs subdir- += basic kconfig +subdir-$(CONFIG_DTC) += dtc diff --git a/scripts/Makefile.extrawarn b/scripts/Makefile.extrawarn index 90dc149df3..1d3a570594 100644 --- a/scripts/Makefile.extrawarn +++ b/scripts/Makefile.extrawarn @@ -58,8 +58,8 @@ endif KBUILD_CFLAGS += $(warning) -dtc-warning-2 += $(call dtc-option,-Wnode_name_chars_strict) -dtc-warning-2 += $(call dtc-option,-Wproperty_name_chars_strict) +dtc-warning-2 += -Wnode_name_chars_strict +dtc-warning-2 += -Wproperty_name_chars_strict dtc-warning := $(dtc-warning-$(findstring 1, $(KBUILD_ENABLE_EXTRA_GCC_CHECKS))) dtc-warning += $(dtc-warning-$(findstring 2, $(KBUILD_ENABLE_EXTRA_GCC_CHECKS))) @@ -70,11 +70,11 @@ DTC_FLAGS += $(dtc-warning) else # Disable noisy checks by default -DTC_FLAGS += $(call dtc-option,-Wno-unit_address_vs_reg) -DTC_FLAGS += $(call dtc-option,-Wno-simple_bus_reg) -DTC_FLAGS += $(call dtc-option,-Wno-unit_address_format) -DTC_FLAGS += $(call dtc-option,-Wno-pci_bridge) -DTC_FLAGS += $(call dtc-option,-Wno-pci_device_bus_num) -DTC_FLAGS += $(call dtc-option,-Wno-pci_device_reg) +DTC_FLAGS += -Wno-unit_address_vs_reg +DTC_FLAGS += -Wno-simple_bus_reg +DTC_FLAGS += -Wno-unit_address_format +DTC_FLAGS += -Wno-pci_bridge +DTC_FLAGS += -Wno-pci_device_bus_num +DTC_FLAGS += -Wno-pci_device_reg endif diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt index 56bb639091..db5d88b4b5 100644 --- a/scripts/config_whitelist.txt +++ b/scripts/config_whitelist.txt @@ -1497,7 +1497,6 @@ CONFIG_MVEBU_MMC CONFIG_MVGBE CONFIG_MVGBE_PORTS CONFIG_MVMFP_V2 -CONFIG_MVNETA CONFIG_MVS CONFIG_MVSATA_IDE CONFIG_MVSATA_IDE_USE_PORT0 diff --git a/scripts/dtc-version.sh b/scripts/dtc-version.sh index e8c94d390b..0744c39eb0 100755 --- a/scripts/dtc-version.sh +++ b/scripts/dtc-version.sh @@ -2,8 +2,8 @@ # # dtc-version dtc-command # -# Prints the dtc version of `dtc-command' in a canonical 4-digit form -# such as `0222' for binutils 2.22 +# Prints the dtc version of `dtc-command' in a canonical 6-digit form +# such as `010404' for dtc 1.4.4 # dtc="$*" @@ -16,5 +16,6 @@ fi MAJOR=$($dtc -v | head -1 | awk '{print $NF}' | cut -d . -f 1) MINOR=$($dtc -v | head -1 | awk '{print $NF}' | cut -d . -f 2) +PATCH=$($dtc -v | head -1 | awk '{print $NF}' | cut -d . -f 3 | cut -d - -f 1) -printf "%02d%02d\\n" $MAJOR $MINOR +printf "%02d%02d%02d\\n" $MAJOR $MINOR $PATCH diff --git a/scripts/dtc/Makefile b/scripts/dtc/Makefile new file mode 100644 index 0000000000..2a48022c41 --- /dev/null +++ b/scripts/dtc/Makefile @@ -0,0 +1,31 @@ +# scripts/dtc makefile + +hostprogs-y := dtc +always := $(hostprogs-y) + +dtc-objs := dtc.o flattree.o fstree.o data.o livetree.o treesource.o \ + srcpos.o checks.o util.o +dtc-objs += dtc-lexer.lex.o dtc-parser.tab.o + +# Source files need to get at the userspace version of libfdt_env.h to compile + +HOSTCFLAGS_DTC := -I$(src) -I$(src)/libfdt + +HOSTCFLAGS_checks.o := $(HOSTCFLAGS_DTC) +HOSTCFLAGS_data.o := $(HOSTCFLAGS_DTC) +HOSTCFLAGS_dtc.o := $(HOSTCFLAGS_DTC) +HOSTCFLAGS_flattree.o := $(HOSTCFLAGS_DTC) +HOSTCFLAGS_fstree.o := $(HOSTCFLAGS_DTC) +HOSTCFLAGS_livetree.o := $(HOSTCFLAGS_DTC) +HOSTCFLAGS_srcpos.o := $(HOSTCFLAGS_DTC) +HOSTCFLAGS_treesource.o := $(HOSTCFLAGS_DTC) +HOSTCFLAGS_util.o := $(HOSTCFLAGS_DTC) + +HOSTCFLAGS_dtc-lexer.lex.o := $(HOSTCFLAGS_DTC) +HOSTCFLAGS_dtc-parser.tab.o := $(HOSTCFLAGS_DTC) + +# dependencies on generated files need to be listed explicitly +$(obj)/dtc-lexer.lex.o: $(obj)/dtc-parser.tab.h + +# generated files need to be cleaned explicitly +clean-files := dtc-lexer.lex.c dtc-parser.tab.c dtc-parser.tab.h diff --git a/scripts/dtc/Makefile.dtc b/scripts/dtc/Makefile.dtc new file mode 100644 index 0000000000..bece49b355 --- /dev/null +++ b/scripts/dtc/Makefile.dtc @@ -0,0 +1,18 @@ +# Makefile.dtc +# +# This is not a complete Makefile of itself. Instead, it is designed to +# be easily embeddable into other systems of Makefiles. +# +DTC_SRCS = \ + checks.c \ + data.c \ + dtc.c \ + flattree.c \ + fstree.c \ + livetree.c \ + srcpos.c \ + treesource.c \ + util.c + +DTC_GEN_SRCS = dtc-lexer.lex.c dtc-parser.tab.c +DTC_OBJS = $(DTC_SRCS:%.c=%.o) $(DTC_GEN_SRCS:%.c=%.o) diff --git a/scripts/dtc/checks.c b/scripts/dtc/checks.c new file mode 100644 index 0000000000..afabf64337 --- /dev/null +++ b/scripts/dtc/checks.c @@ -0,0 +1,1076 @@ +/* + * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2007. + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#include "dtc.h" + +#ifdef TRACE_CHECKS +#define TRACE(c, ...) \ + do { \ + fprintf(stderr, "=== %s: ", (c)->name); \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n"); \ + } while (0) +#else +#define TRACE(c, fmt, ...) do { } while (0) +#endif + +enum checkstatus { + UNCHECKED = 0, + PREREQ, + PASSED, + FAILED, +}; + +struct check; + +typedef void (*check_fn)(struct check *c, struct dt_info *dti, struct node *node); + +struct check { + const char *name; + check_fn fn; + void *data; + bool warn, error; + enum checkstatus status; + bool inprogress; + int num_prereqs; + struct check **prereq; +}; + +#define CHECK_ENTRY(_nm, _fn, _d, _w, _e, ...) \ + static struct check *_nm##_prereqs[] = { __VA_ARGS__ }; \ + static struct check _nm = { \ + .name = #_nm, \ + .fn = (_fn), \ + .data = (_d), \ + .warn = (_w), \ + .error = (_e), \ + .status = UNCHECKED, \ + .num_prereqs = ARRAY_SIZE(_nm##_prereqs), \ + .prereq = _nm##_prereqs, \ + }; +#define WARNING(_nm, _fn, _d, ...) \ + CHECK_ENTRY(_nm, _fn, _d, true, false, __VA_ARGS__) +#define ERROR(_nm, _fn, _d, ...) \ + CHECK_ENTRY(_nm, _fn, _d, false, true, __VA_ARGS__) +#define CHECK(_nm, _fn, _d, ...) \ + CHECK_ENTRY(_nm, _fn, _d, false, false, __VA_ARGS__) + +static inline void PRINTF(3, 4) check_msg(struct check *c, struct dt_info *dti, + const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + + if ((c->warn && (quiet < 1)) + || (c->error && (quiet < 2))) { + fprintf(stderr, "%s: %s (%s): ", + strcmp(dti->outname, "-") ? dti->outname : "<stdout>", + (c->error) ? "ERROR" : "Warning", c->name); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + } + va_end(ap); +} + +#define FAIL(c, dti, ...) \ + do { \ + TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__); \ + (c)->status = FAILED; \ + check_msg((c), dti, __VA_ARGS__); \ + } while (0) + +static void check_nodes_props(struct check *c, struct dt_info *dti, struct node *node) +{ + struct node *child; + + TRACE(c, "%s", node->fullpath); + if (c->fn) + c->fn(c, dti, node); + + for_each_child(node, child) + check_nodes_props(c, dti, child); +} + +static bool run_check(struct check *c, struct dt_info *dti) +{ + struct node *dt = dti->dt; + bool error = false; + int i; + + assert(!c->inprogress); + + if (c->status != UNCHECKED) + goto out; + + c->inprogress = true; + + for (i = 0; i < c->num_prereqs; i++) { + struct check *prq = c->prereq[i]; + error = error || run_check(prq, dti); + if (prq->status != PASSED) { + c->status = PREREQ; + check_msg(c, dti, "Failed prerequisite '%s'", + c->prereq[i]->name); + } + } + + if (c->status != UNCHECKED) + goto out; + + check_nodes_props(c, dti, dt); + + if (c->status == UNCHECKED) + c->status = PASSED; + + TRACE(c, "\tCompleted, status %d", c->status); + +out: + c->inprogress = false; + if ((c->status != PASSED) && (c->error)) + error = true; + return error; +} + +/* + * Utility check functions + */ + +/* A check which always fails, for testing purposes only */ +static inline void check_always_fail(struct check *c, struct dt_info *dti, + struct node *node) +{ + FAIL(c, dti, "always_fail check"); +} +CHECK(always_fail, check_always_fail, NULL); + +static void check_is_string(struct check *c, struct dt_info *dti, + struct node *node) +{ + struct property *prop; + char *propname = c->data; + + prop = get_property(node, propname); + if (!prop) + return; /* Not present, assumed ok */ + + if (!data_is_one_string(prop->val)) + FAIL(c, dti, "\"%s\" property in %s is not a string", + propname, node->fullpath); +} +#define WARNING_IF_NOT_STRING(nm, propname) \ + WARNING(nm, check_is_string, (propname)) +#define ERROR_IF_NOT_STRING(nm, propname) \ + ERROR(nm, check_is_string, (propname)) + +static void check_is_cell(struct check *c, struct dt_info *dti, + struct node *node) +{ + struct property *prop; + char *propname = c->data; + + prop = get_property(node, propname); + if (!prop) + return; /* Not present, assumed ok */ + + if (prop->val.len != sizeof(cell_t)) + FAIL(c, dti, "\"%s\" property in %s is not a single cell", + propname, node->fullpath); +} +#define WARNING_IF_NOT_CELL(nm, propname) \ + WARNING(nm, check_is_cell, (propname)) +#define ERROR_IF_NOT_CELL(nm, propname) \ + ERROR(nm, check_is_cell, (propname)) + +/* + * Structural check functions + */ + +static void check_duplicate_node_names(struct check *c, struct dt_info *dti, + struct node *node) +{ + struct node *child, *child2; + + for_each_child(node, child) + for (child2 = child->next_sibling; + child2; + child2 = child2->next_sibling) + if (streq(child->name, child2->name)) + FAIL(c, dti, "Duplicate node name %s", + child->fullpath); +} +ERROR(duplicate_node_names, check_duplicate_node_names, NULL); + +static void check_duplicate_property_names(struct check *c, struct dt_info *dti, + struct node *node) +{ + struct property *prop, *prop2; + + for_each_property(node, prop) { + for (prop2 = prop->next; prop2; prop2 = prop2->next) { + if (prop2->deleted) + continue; + if (streq(prop->name, prop2->name)) + FAIL(c, dti, "Duplicate property name %s in %s", + prop->name, node->fullpath); + } + } +} +ERROR(duplicate_property_names, check_duplicate_property_names, NULL); + +#define LOWERCASE "abcdefghijklmnopqrstuvwxyz" +#define UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +#define DIGITS "0123456789" +#define PROPNODECHARS LOWERCASE UPPERCASE DIGITS ",._+*#?-" +#define PROPNODECHARSSTRICT LOWERCASE UPPERCASE DIGITS ",-" + +static void check_node_name_chars(struct check *c, struct dt_info *dti, + struct node *node) +{ + int n = strspn(node->name, c->data); + + if (n < strlen(node->name)) + FAIL(c, dti, "Bad character '%c' in node %s", + node->name[n], node->fullpath); +} +ERROR(node_name_chars, check_node_name_chars, PROPNODECHARS "@"); + +static void check_node_name_chars_strict(struct check *c, struct dt_info *dti, + struct node *node) +{ + int n = strspn(node->name, c->data); + + if (n < node->basenamelen) + FAIL(c, dti, "Character '%c' not recommended in node %s", + node->name[n], node->fullpath); +} +CHECK(node_name_chars_strict, check_node_name_chars_strict, PROPNODECHARSSTRICT); + +static void check_node_name_format(struct check *c, struct dt_info *dti, + struct node *node) +{ + if (strchr(get_unitname(node), '@')) + FAIL(c, dti, "Node %s has multiple '@' characters in name", + node->fullpath); +} +ERROR(node_name_format, check_node_name_format, NULL, &node_name_chars); + +static void check_unit_address_vs_reg(struct check *c, struct dt_info *dti, + struct node *node) +{ + const char *unitname = get_unitname(node); + struct property *prop = get_property(node, "reg"); + + if (!prop) { + prop = get_property(node, "ranges"); + if (prop && !prop->val.len) + prop = NULL; + } + + if (prop) { + if (!unitname[0]) + FAIL(c, dti, "Node %s has a reg or ranges property, but no unit name", + node->fullpath); + } else { + if (unitname[0]) + FAIL(c, dti, "Node %s has a unit name, but no reg property", + node->fullpath); + } +} +WARNING(unit_address_vs_reg, check_unit_address_vs_reg, NULL); + +static void check_property_name_chars(struct check *c, struct dt_info *dti, + struct node *node) +{ + struct property *prop; + + for_each_property(node, prop) { + int n = strspn(prop->name, c->data); + + if (n < strlen(prop->name)) + FAIL(c, dti, "Bad character '%c' in property name \"%s\", node %s", + prop->name[n], prop->name, node->fullpath); + } +} +ERROR(property_name_chars, check_property_name_chars, PROPNODECHARS); + +static void check_property_name_chars_strict(struct check *c, + struct dt_info *dti, + struct node *node) +{ + struct property *prop; + + for_each_property(node, prop) { + const char *name = prop->name; + int n = strspn(name, c->data); + + if (n == strlen(prop->name)) + continue; + + /* Certain names are whitelisted */ + if (streq(name, "device_type")) + continue; + + /* + * # is only allowed at the beginning of property names not counting + * the vendor prefix. + */ + if (name[n] == '#' && ((n == 0) || (name[n-1] == ','))) { + name += n + 1; + n = strspn(name, c->data); + } + if (n < strlen(name)) + FAIL(c, dti, "Character '%c' not recommended in property name \"%s\", node %s", + name[n], prop->name, node->fullpath); + } +} +CHECK(property_name_chars_strict, check_property_name_chars_strict, PROPNODECHARSSTRICT); + +#define DESCLABEL_FMT "%s%s%s%s%s" +#define DESCLABEL_ARGS(node,prop,mark) \ + ((mark) ? "value of " : ""), \ + ((prop) ? "'" : ""), \ + ((prop) ? (prop)->name : ""), \ + ((prop) ? "' in " : ""), (node)->fullpath + +static void check_duplicate_label(struct check *c, struct dt_info *dti, + const char *label, struct node *node, + struct property *prop, struct marker *mark) +{ + struct node *dt = dti->dt; + struct node *othernode = NULL; + struct property *otherprop = NULL; + struct marker *othermark = NULL; + + othernode = get_node_by_label(dt, label); + + if (!othernode) + otherprop = get_property_by_label(dt, label, &othernode); + if (!othernode) + othermark = get_marker_label(dt, label, &othernode, + &otherprop); + + if (!othernode) + return; + + if ((othernode != node) || (otherprop != prop) || (othermark != mark)) + FAIL(c, dti, "Duplicate label '%s' on " DESCLABEL_FMT + " and " DESCLABEL_FMT, + label, DESCLABEL_ARGS(node, prop, mark), + DESCLABEL_ARGS(othernode, otherprop, othermark)); +} + +static void check_duplicate_label_node(struct check *c, struct dt_info *dti, + struct node *node) +{ + struct label *l; + struct property *prop; + + for_each_label(node->labels, l) + check_duplicate_label(c, dti, l->label, node, NULL, NULL); + + for_each_property(node, prop) { + struct marker *m = prop->val.markers; + + for_each_label(prop->labels, l) + check_duplicate_label(c, dti, l->label, node, prop, NULL); + + for_each_marker_of_type(m, LABEL) + check_duplicate_label(c, dti, m->ref, node, prop, m); + } +} +ERROR(duplicate_label, check_duplicate_label_node, NULL); + +static cell_t check_phandle_prop(struct check *c, struct dt_info *dti, + struct node *node, const char *propname) +{ + struct node *root = dti->dt; + struct property *prop; + struct marker *m; + cell_t phandle; + + prop = get_property(node, propname); + if (!prop) + return 0; + + if (prop->val.len != sizeof(cell_t)) { + FAIL(c, dti, "%s has bad length (%d) %s property", + node->fullpath, prop->val.len, prop->name); + return 0; + } + + m = prop->val.markers; + for_each_marker_of_type(m, REF_PHANDLE) { + assert(m->offset == 0); + if (node != get_node_by_ref(root, m->ref)) + /* "Set this node's phandle equal to some + * other node's phandle". That's nonsensical + * by construction. */ { + FAIL(c, dti, "%s in %s is a reference to another node", + prop->name, node->fullpath); + } + /* But setting this node's phandle equal to its own + * phandle is allowed - that means allocate a unique + * phandle for this node, even if it's not otherwise + * referenced. The value will be filled in later, so + * we treat it as having no phandle data for now. */ + return 0; + } + + phandle = propval_cell(prop); + + if ((phandle == 0) || (phandle == -1)) { + FAIL(c, dti, "%s has bad value (0x%x) in %s property", + node->fullpath, phandle, prop->name); + return 0; + } + + return phandle; +} + +static void check_explicit_phandles(struct check *c, struct dt_info *dti, + struct node *node) +{ + struct node *root = dti->dt; + struct node *other; + cell_t phandle, linux_phandle; + + /* Nothing should have assigned phandles yet */ + assert(!node->phandle); + + phandle = check_phandle_prop(c, dti, node, "phandle"); + + linux_phandle = check_phandle_prop(c, dti, node, "linux,phandle"); + + if (!phandle && !linux_phandle) + /* No valid phandles; nothing further to check */ + return; + + if (linux_phandle && phandle && (phandle != linux_phandle)) + FAIL(c, dti, "%s has mismatching 'phandle' and 'linux,phandle'" + " properties", node->fullpath); + + if (linux_phandle && !phandle) + phandle = linux_phandle; + + other = get_node_by_phandle(root, phandle); + if (other && (other != node)) { + FAIL(c, dti, "%s has duplicated phandle 0x%x (seen before at %s)", + node->fullpath, phandle, other->fullpath); + return; + } + + node->phandle = phandle; +} +ERROR(explicit_phandles, check_explicit_phandles, NULL); + +static void check_name_properties(struct check *c, struct dt_info *dti, + struct node *node) +{ + struct property **pp, *prop = NULL; + + for (pp = &node->proplist; *pp; pp = &((*pp)->next)) + if (streq((*pp)->name, "name")) { + prop = *pp; + break; + } + + if (!prop) + return; /* No name property, that's fine */ + + if ((prop->val.len != node->basenamelen+1) + || (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) { + FAIL(c, dti, "\"name\" property in %s is incorrect (\"%s\" instead" + " of base node name)", node->fullpath, prop->val.val); + } else { + /* The name property is correct, and therefore redundant. + * Delete it */ + *pp = prop->next; + free(prop->name); + data_free(prop->val); + free(prop); + } +} +ERROR_IF_NOT_STRING(name_is_string, "name"); +ERROR(name_properties, check_name_properties, NULL, &name_is_string); + +/* + * Reference fixup functions + */ + +static void fixup_phandle_references(struct check *c, struct dt_info *dti, + struct node *node) +{ + struct node *dt = dti->dt; + struct property *prop; + + for_each_property(node, prop) { + struct marker *m = prop->val.markers; + struct node *refnode; + cell_t phandle; + + for_each_marker_of_type(m, REF_PHANDLE) { + assert(m->offset + sizeof(cell_t) <= prop->val.len); + + refnode = get_node_by_ref(dt, m->ref); + if (! refnode) { + if (!(dti->dtsflags & DTSF_PLUGIN)) + FAIL(c, dti, "Reference to non-existent node or " + "label \"%s\"\n", m->ref); + else /* mark the entry as unresolved */ + *((fdt32_t *)(prop->val.val + m->offset)) = + cpu_to_fdt32(0xffffffff); + continue; + } + + phandle = get_node_phandle(dt, refnode); + *((fdt32_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle); + } + } +} +ERROR(phandle_references, fixup_phandle_references, NULL, + &duplicate_node_names, &explicit_phandles); + +static void fixup_path_references(struct check *c, struct dt_info *dti, + struct node *node) +{ + struct node *dt = dti->dt; + struct property *prop; + + for_each_property(node, prop) { + struct marker *m = prop->val.markers; + struct node *refnode; + char *path; + + for_each_marker_of_type(m, REF_PATH) { + assert(m->offset <= prop->val.len); + + refnode = get_node_by_ref(dt, m->ref); + if (!refnode) { + FAIL(c, dti, "Reference to non-existent node or label \"%s\"\n", + m->ref); + continue; + } + + path = refnode->fullpath; + prop->val = data_insert_at_marker(prop->val, m, path, + strlen(path) + 1); + } + } +} +ERROR(path_references, fixup_path_references, NULL, &duplicate_node_names); + +/* + * Semantic checks + */ +WARNING_IF_NOT_CELL(address_cells_is_cell, "#address-cells"); +WARNING_IF_NOT_CELL(size_cells_is_cell, "#size-cells"); +WARNING_IF_NOT_CELL(interrupt_cells_is_cell, "#interrupt-cells"); + +WARNING_IF_NOT_STRING(device_type_is_string, "device_type"); +WARNING_IF_NOT_STRING(model_is_string, "model"); +WARNING_IF_NOT_STRING(status_is_string, "status"); + +static void fixup_addr_size_cells(struct check *c, struct dt_info *dti, + struct node *node) +{ + struct property *prop; + + node->addr_cells = -1; + node->size_cells = -1; + + prop = get_property(node, "#address-cells"); + if (prop) + node->addr_cells = propval_cell(prop); + + prop = get_property(node, "#size-cells"); + if (prop) + node->size_cells = propval_cell(prop); +} +WARNING(addr_size_cells, fixup_addr_size_cells, NULL, + &address_cells_is_cell, &size_cells_is_cell); + +#define node_addr_cells(n) \ + (((n)->addr_cells == -1) ? 2 : (n)->addr_cells) +#define node_size_cells(n) \ + (((n)->size_cells == -1) ? 1 : (n)->size_cells) + +static void check_reg_format(struct check *c, struct dt_info *dti, + struct node *node) +{ + struct property *prop; + int addr_cells, size_cells, entrylen; + + prop = get_property(node, "reg"); + if (!prop) + return; /* No "reg", that's fine */ + + if (!node->parent) { + FAIL(c, dti, "Root node has a \"reg\" property"); + return; + } + + if (prop->val.len == 0) + FAIL(c, dti, "\"reg\" property in %s is empty", node->fullpath); + + addr_cells = node_addr_cells(node->parent); + size_cells = node_size_cells(node->parent); + entrylen = (addr_cells + size_cells) * sizeof(cell_t); + + if (!entrylen || (prop->val.len % entrylen) != 0) + FAIL(c, dti, "\"reg\" property in %s has invalid length (%d bytes) " + "(#address-cells == %d, #size-cells == %d)", + node->fullpath, prop->val.len, addr_cells, size_cells); +} +WARNING(reg_format, check_reg_format, NULL, &addr_size_cells); + +static void check_ranges_format(struct check *c, struct dt_info *dti, + struct node *node) +{ + struct property *prop; + int c_addr_cells, p_addr_cells, c_size_cells, p_size_cells, entrylen; + + prop = get_property(node, "ranges"); + if (!prop) + return; + + if (!node->parent) { + FAIL(c, dti, "Root node has a \"ranges\" property"); + return; + } + + p_addr_cells = node_addr_cells(node->parent); + p_size_cells = node_size_cells(node->parent); + c_addr_cells = node_addr_cells(node); + c_size_cells = node_size_cells(node); + entrylen = (p_addr_cells + c_addr_cells + c_size_cells) * sizeof(cell_t); + + if (prop->val.len == 0) { + if (p_addr_cells != c_addr_cells) + FAIL(c, dti, "%s has empty \"ranges\" property but its " + "#address-cells (%d) differs from %s (%d)", + node->fullpath, c_addr_cells, node->parent->fullpath, + p_addr_cells); + if (p_size_cells != c_size_cells) + FAIL(c, dti, "%s has empty \"ranges\" property but its " + "#size-cells (%d) differs from %s (%d)", + node->fullpath, c_size_cells, node->parent->fullpath, + p_size_cells); + } else if ((prop->val.len % entrylen) != 0) { + FAIL(c, dti, "\"ranges\" property in %s has invalid length (%d bytes) " + "(parent #address-cells == %d, child #address-cells == %d, " + "#size-cells == %d)", node->fullpath, prop->val.len, + p_addr_cells, c_addr_cells, c_size_cells); + } +} +WARNING(ranges_format, check_ranges_format, NULL, &addr_size_cells); + +static const struct bus_type pci_bus = { + .name = "PCI", +}; + +static void check_pci_bridge(struct check *c, struct dt_info *dti, struct node *node) +{ + struct property *prop; + cell_t *cells; + + prop = get_property(node, "device_type"); + if (!prop || !streq(prop->val.val, "pci")) + return; + + node->bus = &pci_bus; + + if (!strneq(node->name, "pci", node->basenamelen) && + !strneq(node->name, "pcie", node->basenamelen)) + FAIL(c, dti, "Node %s node name is not \"pci\" or \"pcie\"", + node->fullpath); + + prop = get_property(node, "ranges"); + if (!prop) + FAIL(c, dti, "Node %s missing ranges for PCI bridge (or not a bridge)", + node->fullpath); + + if (node_addr_cells(node) != 3) + FAIL(c, dti, "Node %s incorrect #address-cells for PCI bridge", + node->fullpath); + if (node_size_cells(node) != 2) + FAIL(c, dti, "Node %s incorrect #size-cells for PCI bridge", + node->fullpath); + + prop = get_property(node, "bus-range"); + if (!prop) { + FAIL(c, dti, "Node %s missing bus-range for PCI bridge", + node->fullpath); + return; + } + if (prop->val.len != (sizeof(cell_t) * 2)) { + FAIL(c, dti, "Node %s bus-range must be 2 cells", + node->fullpath); + return; + } + cells = (cell_t *)prop->val.val; + if (fdt32_to_cpu(cells[0]) > fdt32_to_cpu(cells[1])) + FAIL(c, dti, "Node %s bus-range 1st cell must be less than or equal to 2nd cell", + node->fullpath); + if (fdt32_to_cpu(cells[1]) > 0xff) + FAIL(c, dti, "Node %s bus-range maximum bus number must be less than 256", + node->fullpath); +} +WARNING(pci_bridge, check_pci_bridge, NULL, + &device_type_is_string, &addr_size_cells); + +static void check_pci_device_bus_num(struct check *c, struct dt_info *dti, struct node *node) +{ + struct property *prop; + unsigned int bus_num, min_bus, max_bus; + cell_t *cells; + + if (!node->parent || (node->parent->bus != &pci_bus)) + return; + + prop = get_property(node, "reg"); + if (!prop) + return; + + cells = (cell_t *)prop->val.val; + bus_num = (fdt32_to_cpu(cells[0]) & 0x00ff0000) >> 16; + + prop = get_property(node->parent, "bus-range"); + if (!prop) { + min_bus = max_bus = 0; + } else { + cells = (cell_t *)prop->val.val; + min_bus = fdt32_to_cpu(cells[0]); + max_bus = fdt32_to_cpu(cells[0]); + } + if ((bus_num < min_bus) || (bus_num > max_bus)) + FAIL(c, dti, "Node %s PCI bus number %d out of range, expected (%d - %d)", + node->fullpath, bus_num, min_bus, max_bus); +} +WARNING(pci_device_bus_num, check_pci_device_bus_num, NULL, ®_format, &pci_bridge); + +static void check_pci_device_reg(struct check *c, struct dt_info *dti, struct node *node) +{ + struct property *prop; + const char *unitname = get_unitname(node); + char unit_addr[5]; + unsigned int dev, func, reg; + cell_t *cells; + + if (!node->parent || (node->parent->bus != &pci_bus)) + return; + + prop = get_property(node, "reg"); + if (!prop) { + FAIL(c, dti, "Node %s missing PCI reg property", node->fullpath); + return; + } + + cells = (cell_t *)prop->val.val; + if (cells[1] || cells[2]) + FAIL(c, dti, "Node %s PCI reg config space address cells 2 and 3 must be 0", + node->fullpath); + + reg = fdt32_to_cpu(cells[0]); + dev = (reg & 0xf800) >> 11; + func = (reg & 0x700) >> 8; + + if (reg & 0xff000000) + FAIL(c, dti, "Node %s PCI reg address is not configuration space", + node->fullpath); + if (reg & 0x000000ff) + FAIL(c, dti, "Node %s PCI reg config space address register number must be 0", + node->fullpath); + + if (func == 0) { + snprintf(unit_addr, sizeof(unit_addr), "%x", dev); + if (streq(unitname, unit_addr)) + return; + } + + snprintf(unit_addr, sizeof(unit_addr), "%x,%x", dev, func); + if (streq(unitname, unit_addr)) + return; + + FAIL(c, dti, "Node %s PCI unit address format error, expected \"%s\"", + node->fullpath, unit_addr); +} +WARNING(pci_device_reg, check_pci_device_reg, NULL, ®_format, &pci_bridge); + +static const struct bus_type simple_bus = { + .name = "simple-bus", +}; + +static bool node_is_compatible(struct node *node, const char *compat) +{ + struct property *prop; + const char *str, *end; + + prop = get_property(node, "compatible"); + if (!prop) + return false; + + for (str = prop->val.val, end = str + prop->val.len; str < end; + str += strnlen(str, end - str) + 1) { + if (strneq(str, compat, end - str)) + return true; + } + return false; +} + +static void check_simple_bus_bridge(struct check *c, struct dt_info *dti, struct node *node) +{ + if (node_is_compatible(node, "simple-bus")) + node->bus = &simple_bus; +} +WARNING(simple_bus_bridge, check_simple_bus_bridge, NULL, &addr_size_cells); + +static void check_simple_bus_reg(struct check *c, struct dt_info *dti, struct node *node) +{ + struct property *prop; + const char *unitname = get_unitname(node); + char unit_addr[17]; + unsigned int size; + uint64_t reg = 0; + cell_t *cells = NULL; + + if (!node->parent || (node->parent->bus != &simple_bus)) + return; + + prop = get_property(node, "reg"); + if (prop) + cells = (cell_t *)prop->val.val; + else { + prop = get_property(node, "ranges"); + if (prop && prop->val.len) + /* skip of child address */ + cells = ((cell_t *)prop->val.val) + node_addr_cells(node); + } + + if (!cells) { + if (node->parent->parent && !(node->bus == &simple_bus)) + FAIL(c, dti, "Node %s missing or empty reg/ranges property", node->fullpath); + return; + } + + size = node_addr_cells(node->parent); + while (size--) + reg = (reg << 32) | fdt32_to_cpu(*(cells++)); + + snprintf(unit_addr, sizeof(unit_addr), "%"PRIx64, reg); + if (!streq(unitname, unit_addr)) + FAIL(c, dti, "Node %s simple-bus unit address format error, expected \"%s\"", + node->fullpath, unit_addr); +} +WARNING(simple_bus_reg, check_simple_bus_reg, NULL, ®_format, &simple_bus_bridge); + +static void check_unit_address_format(struct check *c, struct dt_info *dti, + struct node *node) +{ + const char *unitname = get_unitname(node); + + if (node->parent && node->parent->bus) + return; + + if (!unitname[0]) + return; + + if (!strncmp(unitname, "0x", 2)) { + FAIL(c, dti, "Node %s unit name should not have leading \"0x\"", + node->fullpath); + /* skip over 0x for next test */ + unitname += 2; + } + if (unitname[0] == '0' && isxdigit(unitname[1])) + FAIL(c, dti, "Node %s unit name should not have leading 0s", + node->fullpath); +} +WARNING(unit_address_format, check_unit_address_format, NULL, + &node_name_format, &pci_bridge, &simple_bus_bridge); + +/* + * Style checks + */ +static void check_avoid_default_addr_size(struct check *c, struct dt_info *dti, + struct node *node) +{ + struct property *reg, *ranges; + + if (!node->parent) + return; /* Ignore root node */ + + reg = get_property(node, "reg"); + ranges = get_property(node, "ranges"); + + if (!reg && !ranges) + return; + + if (node->parent->addr_cells == -1) + FAIL(c, dti, "Relying on default #address-cells value for %s", + node->fullpath); + + if (node->parent->size_cells == -1) + FAIL(c, dti, "Relying on default #size-cells value for %s", + node->fullpath); +} +WARNING(avoid_default_addr_size, check_avoid_default_addr_size, NULL, + &addr_size_cells); + +static void check_obsolete_chosen_interrupt_controller(struct check *c, + struct dt_info *dti, + struct node *node) +{ + struct node *dt = dti->dt; + struct node *chosen; + struct property *prop; + + if (node != dt) + return; + + + chosen = get_node_by_path(dt, "/chosen"); + if (!chosen) + return; + + prop = get_property(chosen, "interrupt-controller"); + if (prop) + FAIL(c, dti, "/chosen has obsolete \"interrupt-controller\" " + "property"); +} +WARNING(obsolete_chosen_interrupt_controller, + check_obsolete_chosen_interrupt_controller, NULL); + +static struct check *check_table[] = { + &duplicate_node_names, &duplicate_property_names, + &node_name_chars, &node_name_format, &property_name_chars, + &name_is_string, &name_properties, + + &duplicate_label, + + &explicit_phandles, + &phandle_references, &path_references, + + &address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell, + &device_type_is_string, &model_is_string, &status_is_string, + + &property_name_chars_strict, + &node_name_chars_strict, + + &addr_size_cells, ®_format, &ranges_format, + + &unit_address_vs_reg, + &unit_address_format, + + &pci_bridge, + &pci_device_reg, + &pci_device_bus_num, + + &simple_bus_bridge, + &simple_bus_reg, + + &avoid_default_addr_size, + &obsolete_chosen_interrupt_controller, + + &always_fail, +}; + +static void enable_warning_error(struct check *c, bool warn, bool error) +{ + int i; + + /* Raising level, also raise it for prereqs */ + if ((warn && !c->warn) || (error && !c->error)) + for (i = 0; i < c->num_prereqs; i++) + enable_warning_error(c->prereq[i], warn, error); + + c->warn = c->warn || warn; + c->error = c->error || error; +} + +static void disable_warning_error(struct check *c, bool warn, bool error) +{ + int i; + + /* Lowering level, also lower it for things this is the prereq + * for */ + if ((warn && c->warn) || (error && c->error)) { + for (i = 0; i < ARRAY_SIZE(check_table); i++) { + struct check *cc = check_table[i]; + int j; + + for (j = 0; j < cc->num_prereqs; j++) + if (cc->prereq[j] == c) + disable_warning_error(cc, warn, error); + } + } + + c->warn = c->warn && !warn; + c->error = c->error && !error; +} + +void parse_checks_option(bool warn, bool error, const char *arg) +{ + int i; + const char *name = arg; + bool enable = true; + + if ((strncmp(arg, "no-", 3) == 0) + || (strncmp(arg, "no_", 3) == 0)) { + name = arg + 3; + enable = false; + } + + for (i = 0; i < ARRAY_SIZE(check_table); i++) { + struct check *c = check_table[i]; + + if (streq(c->name, name)) { + if (enable) + enable_warning_error(c, warn, error); + else + disable_warning_error(c, warn, error); + return; + } + } + + die("Unrecognized check name \"%s\"\n", name); +} + +void process_checks(bool force, struct dt_info *dti) +{ + int i; + int error = 0; + + for (i = 0; i < ARRAY_SIZE(check_table); i++) { + struct check *c = check_table[i]; + + if (c->warn || c->error) + error = error || run_check(c, dti); + } + + if (error) { + if (!force) { + fprintf(stderr, "ERROR: Input tree has errors, aborting " + "(use -f to force output)\n"); + exit(2); + } else if (quiet < 3) { + fprintf(stderr, "Warning: Input tree has errors, " + "output forced\n"); + } + } +} diff --git a/scripts/dtc/data.c b/scripts/dtc/data.c new file mode 100644 index 0000000000..aa37a16c88 --- /dev/null +++ b/scripts/dtc/data.c @@ -0,0 +1,269 @@ +/* + * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005. + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#include "dtc.h" + +void data_free(struct data d) +{ + struct marker *m, *nm; + + m = d.markers; + while (m) { + nm = m->next; + free(m->ref); + free(m); + m = nm; + } + + if (d.val) + free(d.val); +} + +struct data data_grow_for(struct data d, int xlen) +{ + struct data nd; + int newsize; + + if (xlen == 0) + return d; + + nd = d; + + newsize = xlen; + + while ((d.len + xlen) > newsize) + newsize *= 2; + + nd.val = xrealloc(d.val, newsize); + + return nd; +} + +struct data data_copy_mem(const char *mem, int len) +{ + struct data d; + + d = data_grow_for(empty_data, len); + + d.len = len; + memcpy(d.val, mem, len); + + return d; +} + +struct data data_copy_escape_string(const char *s, int len) +{ + int i = 0; + struct data d; + char *q; + + d = data_grow_for(empty_data, len + 1); + + q = d.val; + while (i < len) { + char c = s[i++]; + + if (c == '\\') + c = get_escape_char(s, &i); + + q[d.len++] = c; + } + + q[d.len++] = '\0'; + return d; +} + +struct data data_copy_file(FILE *f, size_t maxlen) +{ + struct data d = empty_data; + + while (!feof(f) && (d.len < maxlen)) { + size_t chunksize, ret; + + if (maxlen == -1) + chunksize = 4096; + else + chunksize = maxlen - d.len; + + d = data_grow_for(d, chunksize); + ret = fread(d.val + d.len, 1, chunksize, f); + + if (ferror(f)) + die("Error reading file into data: %s", strerror(errno)); + + if (d.len + ret < d.len) + die("Overflow reading file into data\n"); + + d.len += ret; + } + + return d; +} + +struct data data_append_data(struct data d, const void *p, int len) +{ + d = data_grow_for(d, len); + memcpy(d.val + d.len, p, len); + d.len += len; + return d; +} + +struct data data_insert_at_marker(struct data d, struct marker *m, + const void *p, int len) +{ + d = data_grow_for(d, len); + memmove(d.val + m->offset + len, d.val + m->offset, d.len - m->offset); + memcpy(d.val + m->offset, p, len); + d.len += len; + + /* Adjust all markers after the one we're inserting at */ + m = m->next; + for_each_marker(m) + m->offset += len; + return d; +} + +static struct data data_append_markers(struct data d, struct marker *m) +{ + struct marker **mp = &d.markers; + + /* Find the end of the markerlist */ + while (*mp) + mp = &((*mp)->next); + *mp = m; + return d; +} + +struct data data_merge(struct data d1, struct data d2) +{ + struct data d; + struct marker *m2 = d2.markers; + + d = data_append_markers(data_append_data(d1, d2.val, d2.len), m2); + + /* Adjust for the length of d1 */ + for_each_marker(m2) + m2->offset += d1.len; + + d2.markers = NULL; /* So data_free() doesn't clobber them */ + data_free(d2); + + return d; +} + +struct data data_append_integer(struct data d, uint64_t value, int bits) +{ + uint8_t value_8; + fdt16_t value_16; + fdt32_t value_32; + fdt64_t value_64; + + switch (bits) { + case 8: + value_8 = value; + return data_append_data(d, &value_8, 1); + + case 16: + value_16 = cpu_to_fdt16(value); + return data_append_data(d, &value_16, 2); + + case 32: + value_32 = cpu_to_fdt32(value); + return data_append_data(d, &value_32, 4); + + case 64: + value_64 = cpu_to_fdt64(value); + return data_append_data(d, &value_64, 8); + + default: + die("Invalid literal size (%d)\n", bits); + } +} + +struct data data_append_re(struct data d, uint64_t address, uint64_t size) +{ + struct fdt_reserve_entry re; + + re.address = cpu_to_fdt64(address); + re.size = cpu_to_fdt64(size); + + return data_append_data(d, &re, sizeof(re)); +} + +struct data data_append_cell(struct data d, cell_t word) +{ + return data_append_integer(d, word, sizeof(word) * 8); +} + +struct data data_append_addr(struct data d, uint64_t addr) +{ + return data_append_integer(d, addr, sizeof(addr) * 8); +} + +struct data data_append_byte(struct data d, uint8_t byte) +{ + return data_append_data(d, &byte, 1); +} + +struct data data_append_zeroes(struct data d, int len) +{ + d = data_grow_for(d, len); + + memset(d.val + d.len, 0, len); + d.len += len; + return d; +} + +struct data data_append_align(struct data d, int align) +{ + int newlen = ALIGN(d.len, align); + return data_append_zeroes(d, newlen - d.len); +} + +struct data data_add_marker(struct data d, enum markertype type, char *ref) +{ + struct marker *m; + + m = xmalloc(sizeof(*m)); + m->offset = d.len; + m->type = type; + m->ref = ref; + m->next = NULL; + + return data_append_markers(d, m); +} + +bool data_is_one_string(struct data d) +{ + int i; + int len = d.len; + + if (len == 0) + return false; + + for (i = 0; i < len-1; i++) + if (d.val[i] == '\0') + return false; + + if (d.val[len-1] != '\0') + return false; + + return true; +} diff --git a/scripts/dtc/dtc-lexer.l b/scripts/dtc/dtc-lexer.l new file mode 100644 index 0000000000..fd825ebba6 --- /dev/null +++ b/scripts/dtc/dtc-lexer.l @@ -0,0 +1,306 @@ +/* + * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005. + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +%option noyywrap nounput noinput never-interactive + +%x BYTESTRING +%x PROPNODENAME +%s V1 + +PROPNODECHAR [a-zA-Z0-9,._+*#?@-] +PATHCHAR ({PROPNODECHAR}|[/]) +LABEL [a-zA-Z_][a-zA-Z0-9_]* +STRING \"([^\\"]|\\.)*\" +CHAR_LITERAL '([^']|\\')*' +WS [[:space:]] +COMMENT "/*"([^*]|\*+[^*/])*\*+"/" +LINECOMMENT "//".*\n + +%{ +#include "dtc.h" +#include "srcpos.h" +#include "dtc-parser.tab.h" + +YYLTYPE yylloc; +extern bool treesource_error; + +/* CAUTION: this will stop working if we ever use yyless() or yyunput() */ +#define YY_USER_ACTION \ + { \ + srcpos_update(&yylloc, yytext, yyleng); \ + } + +/*#define LEXDEBUG 1*/ + +#ifdef LEXDEBUG +#define DPRINT(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__) +#else +#define DPRINT(fmt, ...) do { } while (0) +#endif + +static int dts_version = 1; + +#define BEGIN_DEFAULT() DPRINT("<V1>\n"); \ + BEGIN(V1); \ + +static void push_input_file(const char *filename); +static bool pop_input_file(void); +static void PRINTF(1, 2) lexical_error(const char *fmt, ...); + +%} + +%% +<*>"/include/"{WS}*{STRING} { + char *name = strchr(yytext, '\"') + 1; + yytext[yyleng-1] = '\0'; + push_input_file(name); + } + +<*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)? { + char *line, *fnstart, *fnend; + struct data fn; + /* skip text before line # */ + line = yytext; + while (!isdigit((unsigned char)*line)) + line++; + + /* regexp ensures that first and list " + * in the whole yytext are those at + * beginning and end of the filename string */ + fnstart = memchr(yytext, '"', yyleng); + for (fnend = yytext + yyleng - 1; + *fnend != '"'; fnend--) + ; + assert(fnstart && fnend && (fnend > fnstart)); + + fn = data_copy_escape_string(fnstart + 1, + fnend - fnstart - 1); + + /* Don't allow nuls in filenames */ + if (memchr(fn.val, '\0', fn.len - 1)) + lexical_error("nul in line number directive"); + + /* -1 since #line is the number of the next line */ + srcpos_set_line(xstrdup(fn.val), atoi(line) - 1); + data_free(fn); + } + +<*><<EOF>> { + if (!pop_input_file()) { + yyterminate(); + } + } + +<*>{STRING} { + DPRINT("String: %s\n", yytext); + yylval.data = data_copy_escape_string(yytext+1, + yyleng-2); + return DT_STRING; + } + +<*>"/dts-v1/" { + DPRINT("Keyword: /dts-v1/\n"); + dts_version = 1; + BEGIN_DEFAULT(); + return DT_V1; + } + +<*>"/plugin/" { + DPRINT("Keyword: /plugin/\n"); + return DT_PLUGIN; + } + +<*>"/memreserve/" { + DPRINT("Keyword: /memreserve/\n"); + BEGIN_DEFAULT(); + return DT_MEMRESERVE; + } + +<*>"/bits/" { + DPRINT("Keyword: /bits/\n"); + BEGIN_DEFAULT(); + return DT_BITS; + } + +<*>"/delete-property/" { + DPRINT("Keyword: /delete-property/\n"); + DPRINT("<PROPNODENAME>\n"); + BEGIN(PROPNODENAME); + return DT_DEL_PROP; + } + +<*>"/delete-node/" { + DPRINT("Keyword: /delete-node/\n"); + DPRINT("<PROPNODENAME>\n"); + BEGIN(PROPNODENAME); + return DT_DEL_NODE; + } + +<*>{LABEL}: { + DPRINT("Label: %s\n", yytext); + yylval.labelref = xstrdup(yytext); + yylval.labelref[yyleng-1] = '\0'; + return DT_LABEL; + } + +<V1>([0-9]+|0[xX][0-9a-fA-F]+)(U|L|UL|LL|ULL)? { + char *e; + DPRINT("Integer Literal: '%s'\n", yytext); + + errno = 0; + yylval.integer = strtoull(yytext, &e, 0); + + if (*e && e[strspn(e, "UL")]) { + lexical_error("Bad integer literal '%s'", + yytext); + } + + if (errno == ERANGE) + lexical_error("Integer literal '%s' out of range", + yytext); + else + /* ERANGE is the only strtoull error triggerable + * by strings matching the pattern */ + assert(errno == 0); + return DT_LITERAL; + } + +<*>{CHAR_LITERAL} { + struct data d; + DPRINT("Character literal: %s\n", yytext); + + d = data_copy_escape_string(yytext+1, yyleng-2); + if (d.len == 1) { + lexical_error("Empty character literal"); + yylval.integer = 0; + } else { + yylval.integer = (unsigned char)d.val[0]; + + if (d.len > 2) + lexical_error("Character literal has %d" + " characters instead of 1", + d.len - 1); + } + + data_free(d); + return DT_CHAR_LITERAL; + } + +<*>\&{LABEL} { /* label reference */ + DPRINT("Ref: %s\n", yytext+1); + yylval.labelref = xstrdup(yytext+1); + return DT_REF; + } + +<*>"&{/"{PATHCHAR}*\} { /* new-style path reference */ + yytext[yyleng-1] = '\0'; + DPRINT("Ref: %s\n", yytext+2); + yylval.labelref = xstrdup(yytext+2); + return DT_REF; + } + +<BYTESTRING>[0-9a-fA-F]{2} { + yylval.byte = strtol(yytext, NULL, 16); + DPRINT("Byte: %02x\n", (int)yylval.byte); + return DT_BYTE; + } + +<BYTESTRING>"]" { + DPRINT("/BYTESTRING\n"); + BEGIN_DEFAULT(); + return ']'; + } + +<PROPNODENAME>\\?{PROPNODECHAR}+ { + DPRINT("PropNodeName: %s\n", yytext); + yylval.propnodename = xstrdup((yytext[0] == '\\') ? + yytext + 1 : yytext); + BEGIN_DEFAULT(); + return DT_PROPNODENAME; + } + +"/incbin/" { + DPRINT("Binary Include\n"); + return DT_INCBIN; + } + +<*>{WS}+ /* eat whitespace */ +<*>{COMMENT}+ /* eat C-style comments */ +<*>{LINECOMMENT}+ /* eat C++-style comments */ + +<*>"<<" { return DT_LSHIFT; }; +<*>">>" { return DT_RSHIFT; }; +<*>"<=" { return DT_LE; }; +<*>">=" { return DT_GE; }; +<*>"==" { return DT_EQ; }; +<*>"!=" { return DT_NE; }; +<*>"&&" { return DT_AND; }; +<*>"||" { return DT_OR; }; + +<*>. { + DPRINT("Char: %c (\\x%02x)\n", yytext[0], + (unsigned)yytext[0]); + if (yytext[0] == '[') { + DPRINT("<BYTESTRING>\n"); + BEGIN(BYTESTRING); + } + if ((yytext[0] == '{') + || (yytext[0] == ';')) { + DPRINT("<PROPNODENAME>\n"); + BEGIN(PROPNODENAME); + } + return yytext[0]; + } + +%% + +static void push_input_file(const char *filename) +{ + assert(filename); + + srcfile_push(filename); + + yyin = current_srcfile->f; + + yypush_buffer_state(yy_create_buffer(yyin, YY_BUF_SIZE)); +} + + +static bool pop_input_file(void) +{ + if (srcfile_pop() == 0) + return false; + + yypop_buffer_state(); + yyin = current_srcfile->f; + + return true; +} + +static void lexical_error(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + srcpos_verror(&yylloc, "Lexical error", fmt, ap); + va_end(ap); + + treesource_error = true; +} diff --git a/scripts/dtc/dtc-lexer.lex.c_shipped b/scripts/dtc/dtc-lexer.lex.c_shipped new file mode 100644 index 0000000000..3934d8624d --- /dev/null +++ b/scripts/dtc/dtc-lexer.lex.c_shipped @@ -0,0 +1,2255 @@ +#line 2 "dtc-lexer.lex.c" + +#line 4 "dtc-lexer.lex.c" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 +#define YY_FLEX_SUBMINOR_VERSION 35 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <stdlib.h> + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include <inttypes.h> +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#endif /* ! C99 */ + +#endif /* ! FLEXINT_H */ + +#ifdef __cplusplus + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +/* C99 requires __STDC__ to be defined as 1. */ +#if defined (__STDC__) + +#define YY_USE_CONST + +#endif /* defined (__STDC__) */ +#endif /* ! __cplusplus */ + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN (yy_start) = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START (((yy_start) - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart(yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k. + * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. + * Ditto for the __ia64__ case accordingly. + */ +#define YY_BUF_SIZE 32768 +#else +#define YY_BUF_SIZE 16384 +#endif /* __ia64__ */ +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +extern int yyleng; + +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + #define YY_LESS_LINENO(n) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = (yy_hold_char); \ + YY_RESTORE_YY_MORE_OFFSET \ + (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, (yytext_ptr) ) + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* Stack of input buffers. */ +static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ +static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ +static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ + ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ + : NULL) + +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; +static int yy_n_chars; /* number of characters read into yy_ch_buf */ +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 0; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart (FILE *input_file ); +void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ); +YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ); +void yy_delete_buffer (YY_BUFFER_STATE b ); +void yy_flush_buffer (YY_BUFFER_STATE b ); +void yypush_buffer_state (YY_BUFFER_STATE new_buffer ); +void yypop_buffer_state (void ); + +static void yyensure_buffer_stack (void ); +static void yy_load_buffer_state (void ); +static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ); + +#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ) + +YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ); +YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ); +YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len ); + +void *yyalloc (yy_size_t ); +void *yyrealloc (void *,yy_size_t ); +void yyfree (void * ); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + yyensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer(yyin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + yyensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer(yyin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +/* Begin user sect3 */ + +#define yywrap(n) 1 +#define YY_SKIP_YYWRAP + +typedef unsigned char YY_CHAR; + +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; + +typedef int yy_state_type; + +extern int yylineno; + +int yylineno = 1; + +extern char *yytext; +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state (void ); +static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); +static int yy_get_next_buffer (void ); +static void yy_fatal_error (yyconst char msg[] ); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + (yytext_ptr) = yy_bp; \ + yyleng = (size_t) (yy_cp - yy_bp); \ + (yy_hold_char) = *yy_cp; \ + *yy_cp = '\0'; \ + (yy_c_buf_p) = yy_cp; + +#define YY_NUM_RULES 31 +#define YY_END_OF_BUFFER 32 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static yyconst flex_int16_t yy_accept[166] = + { 0, + 0, 0, 0, 0, 0, 0, 0, 0, 32, 30, + 19, 19, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 16, 17, 17, 30, + 17, 11, 11, 19, 27, 0, 3, 0, 28, 13, + 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, + 0, 22, 24, 26, 25, 23, 0, 10, 29, 0, + 0, 0, 15, 15, 17, 17, 17, 11, 11, 11, + 0, 13, 0, 12, 0, 0, 0, 21, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 17, 11, 11, + 11, 0, 14, 20, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 17, 7, 0, 0, 0, + 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 18, 0, 0, 5, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 6, 9, 0, + 0, 0, 0, 8, 0 + } ; + +static yyconst flex_int32_t yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 5, 6, 7, 1, 1, 8, 9, 1, + 1, 10, 11, 11, 12, 11, 13, 14, 15, 16, + 16, 16, 16, 16, 16, 16, 16, 17, 1, 18, + 19, 20, 11, 11, 21, 21, 21, 21, 21, 21, + 22, 22, 22, 22, 22, 23, 22, 22, 22, 22, + 22, 22, 22, 22, 24, 22, 22, 25, 22, 22, + 1, 26, 27, 1, 22, 1, 21, 28, 29, 30, + + 31, 21, 32, 22, 33, 22, 22, 34, 35, 36, + 37, 38, 22, 39, 40, 41, 42, 43, 22, 25, + 44, 22, 45, 46, 47, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst flex_int32_t yy_meta[48] = + { 0, + 1, 1, 1, 1, 1, 1, 2, 3, 1, 2, + 2, 2, 4, 5, 5, 5, 6, 1, 1, 1, + 7, 8, 8, 8, 8, 1, 1, 7, 7, 7, + 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 3, 1, 4 + } ; + +static yyconst flex_int16_t yy_base[180] = + { 0, + 0, 393, 35, 392, 66, 391, 38, 107, 397, 401, + 55, 113, 377, 112, 111, 111, 114, 42, 376, 106, + 377, 347, 126, 120, 0, 147, 401, 0, 124, 0, + 137, 158, 170, 163, 401, 153, 401, 389, 401, 0, + 378, 120, 401, 131, 380, 386, 355, 139, 351, 355, + 351, 401, 401, 401, 401, 401, 367, 401, 401, 185, + 350, 346, 401, 364, 0, 185, 347, 189, 356, 355, + 0, 0, 330, 180, 366, 141, 372, 361, 332, 338, + 331, 341, 334, 326, 205, 331, 337, 329, 401, 341, + 167, 316, 401, 349, 348, 320, 328, 346, 180, 318, + + 324, 209, 324, 320, 322, 342, 338, 309, 306, 315, + 305, 315, 312, 192, 342, 341, 401, 293, 306, 282, + 268, 252, 255, 203, 285, 282, 272, 268, 252, 233, + 232, 239, 208, 107, 401, 401, 238, 211, 401, 211, + 212, 208, 228, 203, 215, 207, 233, 222, 212, 211, + 203, 227, 401, 237, 225, 204, 185, 401, 401, 149, + 128, 88, 42, 401, 401, 253, 259, 267, 271, 275, + 281, 288, 292, 300, 308, 312, 318, 326, 334 + } ; + +static yyconst flex_int16_t yy_def[180] = + { 0, + 165, 1, 1, 3, 165, 5, 1, 1, 165, 165, + 165, 165, 165, 166, 167, 168, 165, 165, 165, 165, + 169, 165, 165, 165, 170, 169, 165, 171, 172, 171, + 171, 165, 165, 165, 165, 166, 165, 166, 165, 173, + 165, 168, 165, 168, 174, 175, 165, 165, 165, 165, + 165, 165, 165, 165, 165, 165, 169, 165, 165, 165, + 165, 165, 165, 169, 171, 172, 171, 165, 165, 165, + 176, 173, 177, 168, 174, 174, 175, 165, 165, 165, + 165, 165, 165, 165, 165, 165, 165, 171, 165, 165, + 176, 177, 165, 165, 165, 165, 165, 165, 165, 165, + + 165, 165, 165, 165, 171, 165, 165, 165, 165, 165, + 165, 165, 165, 178, 165, 171, 165, 165, 165, 165, + 165, 165, 165, 178, 165, 178, 165, 165, 165, 165, + 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, + 165, 165, 165, 165, 165, 165, 165, 179, 165, 165, + 165, 179, 165, 179, 165, 165, 165, 165, 165, 165, + 165, 165, 165, 165, 0, 165, 165, 165, 165, 165, + 165, 165, 165, 165, 165, 165, 165, 165, 165 + } ; + +static yyconst flex_int16_t yy_nxt[449] = + { 0, + 10, 11, 12, 11, 13, 14, 10, 15, 16, 10, + 10, 10, 17, 10, 10, 10, 10, 18, 19, 20, + 21, 21, 21, 21, 21, 10, 10, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 10, 22, 10, 24, 25, 25, + 25, 32, 33, 33, 164, 26, 34, 34, 34, 52, + 53, 27, 26, 26, 26, 26, 10, 11, 12, 11, + 13, 14, 28, 15, 16, 28, 28, 28, 24, 28, + 28, 28, 10, 18, 19, 20, 29, 29, 29, 29, + 29, 30, 10, 29, 29, 29, 29, 29, 29, 29, + + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 10, 22, 10, 23, 34, 34, 34, 37, 39, 43, + 32, 33, 33, 45, 55, 56, 46, 60, 43, 45, + 65, 163, 46, 65, 65, 65, 44, 38, 60, 74, + 58, 47, 141, 48, 142, 44, 49, 47, 50, 48, + 76, 51, 62, 94, 50, 41, 44, 51, 37, 61, + 64, 64, 64, 58, 34, 34, 34, 64, 162, 80, + 67, 68, 68, 68, 64, 64, 64, 64, 38, 81, + 69, 70, 71, 68, 68, 68, 60, 161, 43, 69, + 70, 65, 69, 70, 65, 65, 65, 125, 85, 85, + + 85, 58, 68, 68, 68, 44, 102, 110, 125, 133, + 102, 69, 70, 111, 114, 160, 159, 126, 85, 85, + 85, 140, 140, 140, 140, 140, 140, 153, 126, 147, + 147, 147, 153, 148, 147, 147, 147, 158, 148, 165, + 157, 156, 155, 151, 150, 149, 146, 154, 145, 144, + 143, 139, 154, 36, 36, 36, 36, 36, 36, 36, + 36, 40, 138, 137, 136, 40, 40, 42, 42, 42, + 42, 42, 42, 42, 42, 57, 57, 57, 57, 63, + 135, 63, 65, 134, 165, 65, 133, 65, 65, 66, + 132, 131, 66, 66, 66, 66, 72, 130, 72, 72, + + 75, 75, 75, 75, 75, 75, 75, 75, 77, 77, + 77, 77, 77, 77, 77, 77, 91, 129, 91, 92, + 128, 92, 92, 127, 92, 92, 124, 124, 124, 124, + 124, 124, 124, 124, 152, 152, 152, 152, 152, 152, + 152, 152, 60, 60, 123, 122, 121, 120, 119, 118, + 117, 45, 116, 111, 115, 113, 112, 109, 108, 107, + 46, 106, 93, 89, 105, 104, 103, 101, 100, 99, + 98, 97, 96, 95, 78, 76, 93, 90, 89, 88, + 58, 87, 86, 58, 84, 83, 82, 79, 78, 76, + 73, 165, 59, 58, 54, 35, 165, 31, 23, 23, + + 9, 165, 165, 165, 165, 165, 165, 165, 165, 165, + 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, + 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, + 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, + 165, 165, 165, 165, 165, 165, 165, 165 + } ; + +static yyconst flex_int16_t yy_chk[449] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, + 3, 7, 7, 7, 163, 3, 11, 11, 11, 18, + 18, 3, 3, 3, 3, 3, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 8, 12, 12, 12, 14, 15, 16, + 8, 8, 8, 17, 20, 20, 17, 23, 42, 24, + 29, 162, 24, 29, 29, 29, 16, 14, 31, 44, + 29, 17, 134, 17, 134, 42, 17, 24, 17, 24, + 76, 17, 24, 76, 24, 15, 44, 24, 36, 23, + 26, 26, 26, 26, 34, 34, 34, 26, 161, 48, + 31, 32, 32, 32, 26, 26, 26, 26, 36, 48, + 32, 32, 32, 33, 33, 33, 60, 160, 74, 91, + 91, 66, 33, 33, 66, 66, 66, 114, 60, 60, + + 60, 66, 68, 68, 68, 74, 85, 99, 124, 133, + 102, 68, 68, 99, 102, 157, 156, 114, 85, 85, + 85, 133, 133, 133, 140, 140, 140, 148, 124, 143, + 143, 143, 152, 143, 147, 147, 147, 155, 147, 154, + 151, 150, 149, 146, 145, 144, 142, 148, 141, 138, + 137, 132, 152, 166, 166, 166, 166, 166, 166, 166, + 166, 167, 131, 130, 129, 167, 167, 168, 168, 168, + 168, 168, 168, 168, 168, 169, 169, 169, 169, 170, + 128, 170, 171, 127, 126, 171, 125, 171, 171, 172, + 123, 122, 172, 172, 172, 172, 173, 121, 173, 173, + + 174, 174, 174, 174, 174, 174, 174, 174, 175, 175, + 175, 175, 175, 175, 175, 175, 176, 120, 176, 177, + 119, 177, 177, 118, 177, 177, 178, 178, 178, 178, + 178, 178, 178, 178, 179, 179, 179, 179, 179, 179, + 179, 179, 116, 115, 113, 112, 111, 110, 109, 108, + 107, 106, 105, 104, 103, 101, 100, 98, 97, 96, + 95, 94, 92, 90, 88, 87, 86, 84, 83, 82, + 81, 80, 79, 78, 77, 75, 73, 70, 69, 67, + 64, 62, 61, 57, 51, 50, 49, 47, 46, 45, + 41, 38, 22, 21, 19, 13, 9, 6, 4, 2, + + 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, + 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, + 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, + 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, + 165, 165, 165, 165, 165, 165, 165, 165 + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +extern int yy_flex_debug; +int yy_flex_debug = 0; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *yytext; +#line 1 "dtc-lexer.l" +/* + * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005. + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ +#define YY_NO_INPUT 1 + + + +#line 37 "dtc-lexer.l" +#include "dtc.h" +#include "srcpos.h" +#include "dtc-parser.tab.h" + +YYLTYPE yylloc; +extern bool treesource_error; + +/* CAUTION: this will stop working if we ever use yyless() or yyunput() */ +#define YY_USER_ACTION \ + { \ + srcpos_update(&yylloc, yytext, yyleng); \ + } + +/*#define LEXDEBUG 1*/ + +#ifdef LEXDEBUG +#define DPRINT(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__) +#else +#define DPRINT(fmt, ...) do { } while (0) +#endif + +static int dts_version = 1; + +#define BEGIN_DEFAULT() DPRINT("<V1>\n"); \ + BEGIN(V1); \ + +static void push_input_file(const char *filename); +static bool pop_input_file(void); +static void PRINTF(1, 2) lexical_error(const char *fmt, ...); + +#line 669 "dtc-lexer.lex.c" + +#define INITIAL 0 +#define BYTESTRING 1 +#define PROPNODENAME 2 +#define V1 3 + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include <unistd.h> +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +static int yy_init_globals (void ); + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int yylex_destroy (void ); + +int yyget_debug (void ); + +void yyset_debug (int debug_flag ); + +YY_EXTRA_TYPE yyget_extra (void ); + +void yyset_extra (YY_EXTRA_TYPE user_defined ); + +FILE *yyget_in (void ); + +void yyset_in (FILE * in_str ); + +FILE *yyget_out (void ); + +void yyset_out (FILE * out_str ); + +int yyget_leng (void ); + +char *yyget_text (void ); + +int yyget_lineno (void ); + +void yyset_lineno (int line_number ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap (void ); +#else +extern int yywrap (void ); +#endif +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy (char *,yyconst char *,int ); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * ); +#endif + +#ifndef YY_NO_INPUT + +#ifdef __cplusplus +static int yyinput (void ); +#else +static int input (void ); +#endif + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k */ +#define YY_READ_BUF_SIZE 16384 +#else +#define YY_READ_BUF_SIZE 8192 +#endif /* __ia64__ */ +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ + { \ + int c = '*'; \ + size_t n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else \ + { \ + errno=0; \ + while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(yyin); \ + } \ + }\ +\ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int yylex (void); + +#define YY_DECL int yylex (void) +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + if ( yyleng > 0 ) \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \ + (yytext[yyleng - 1] == '\n'); \ + YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +#line 69 "dtc-lexer.l" + +#line 862 "dtc-lexer.lex.c" + + if ( !(yy_init) ) + { + (yy_init) = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! (yy_start) ) + (yy_start) = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! YY_CURRENT_BUFFER ) { + yyensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer(yyin,YY_BUF_SIZE ); + } + + yy_load_buffer_state( ); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = (yy_c_buf_p); + + /* Support of yytext. */ + *yy_cp = (yy_hold_char); + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = (yy_start); + yy_current_state += YY_AT_BOL(); +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 166 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_current_state != 165 ); + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + + YY_DO_BEFORE_ACTION; + +do_action: /* This label is used only to access EOF actions. */ + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = (yy_hold_char); + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + goto yy_find_action; + +case 1: +/* rule 1 can match eol */ +YY_RULE_SETUP +#line 70 "dtc-lexer.l" +{ + char *name = strchr(yytext, '\"') + 1; + yytext[yyleng-1] = '\0'; + push_input_file(name); + } + YY_BREAK +case 2: +/* rule 2 can match eol */ +YY_RULE_SETUP +#line 76 "dtc-lexer.l" +{ + char *line, *fnstart, *fnend; + struct data fn; + /* skip text before line # */ + line = yytext; + while (!isdigit((unsigned char)*line)) + line++; + + /* regexp ensures that first and list " + * in the whole yytext are those at + * beginning and end of the filename string */ + fnstart = memchr(yytext, '"', yyleng); + for (fnend = yytext + yyleng - 1; + *fnend != '"'; fnend--) + ; + assert(fnstart && fnend && (fnend > fnstart)); + + fn = data_copy_escape_string(fnstart + 1, + fnend - fnstart - 1); + + /* Don't allow nuls in filenames */ + if (memchr(fn.val, '\0', fn.len - 1)) + lexical_error("nul in line number directive"); + + /* -1 since #line is the number of the next line */ + srcpos_set_line(xstrdup(fn.val), atoi(line) - 1); + data_free(fn); + } + YY_BREAK +case YY_STATE_EOF(INITIAL): +case YY_STATE_EOF(BYTESTRING): +case YY_STATE_EOF(PROPNODENAME): +case YY_STATE_EOF(V1): +#line 105 "dtc-lexer.l" +{ + if (!pop_input_file()) { + yyterminate(); + } + } + YY_BREAK +case 3: +/* rule 3 can match eol */ +YY_RULE_SETUP +#line 111 "dtc-lexer.l" +{ + DPRINT("String: %s\n", yytext); + yylval.data = data_copy_escape_string(yytext+1, + yyleng-2); + return DT_STRING; + } + YY_BREAK +case 4: +YY_RULE_SETUP +#line 118 "dtc-lexer.l" +{ + DPRINT("Keyword: /dts-v1/\n"); + dts_version = 1; + BEGIN_DEFAULT(); + return DT_V1; + } + YY_BREAK +case 5: +YY_RULE_SETUP +#line 125 "dtc-lexer.l" +{ + DPRINT("Keyword: /plugin/\n"); + return DT_PLUGIN; + } + YY_BREAK +case 6: +YY_RULE_SETUP +#line 130 "dtc-lexer.l" +{ + DPRINT("Keyword: /memreserve/\n"); + BEGIN_DEFAULT(); + return DT_MEMRESERVE; + } + YY_BREAK +case 7: +YY_RULE_SETUP +#line 136 "dtc-lexer.l" +{ + DPRINT("Keyword: /bits/\n"); + BEGIN_DEFAULT(); + return DT_BITS; + } + YY_BREAK +case 8: +YY_RULE_SETUP +#line 142 "dtc-lexer.l" +{ + DPRINT("Keyword: /delete-property/\n"); + DPRINT("<PROPNODENAME>\n"); + BEGIN(PROPNODENAME); + return DT_DEL_PROP; + } + YY_BREAK +case 9: +YY_RULE_SETUP +#line 149 "dtc-lexer.l" +{ + DPRINT("Keyword: /delete-node/\n"); + DPRINT("<PROPNODENAME>\n"); + BEGIN(PROPNODENAME); + return DT_DEL_NODE; + } + YY_BREAK +case 10: +YY_RULE_SETUP +#line 156 "dtc-lexer.l" +{ + DPRINT("Label: %s\n", yytext); + yylval.labelref = xstrdup(yytext); + yylval.labelref[yyleng-1] = '\0'; + return DT_LABEL; + } + YY_BREAK +case 11: +YY_RULE_SETUP +#line 163 "dtc-lexer.l" +{ + char *e; + DPRINT("Integer Literal: '%s'\n", yytext); + + errno = 0; + yylval.integer = strtoull(yytext, &e, 0); + + if (*e && e[strspn(e, "UL")]) { + lexical_error("Bad integer literal '%s'", + yytext); + } + + if (errno == ERANGE) + lexical_error("Integer literal '%s' out of range", + yytext); + else + /* ERANGE is the only strtoull error triggerable + * by strings matching the pattern */ + assert(errno == 0); + return DT_LITERAL; + } + YY_BREAK +case 12: +/* rule 12 can match eol */ +YY_RULE_SETUP +#line 185 "dtc-lexer.l" +{ + struct data d; + DPRINT("Character literal: %s\n", yytext); + + d = data_copy_escape_string(yytext+1, yyleng-2); + if (d.len == 1) { + lexical_error("Empty character literal"); + yylval.integer = 0; + } else { + yylval.integer = (unsigned char)d.val[0]; + + if (d.len > 2) + lexical_error("Character literal has %d" + " characters instead of 1", + d.len - 1); + } + + data_free(d); + return DT_CHAR_LITERAL; + } + YY_BREAK +case 13: +YY_RULE_SETUP +#line 206 "dtc-lexer.l" +{ /* label reference */ + DPRINT("Ref: %s\n", yytext+1); + yylval.labelref = xstrdup(yytext+1); + return DT_REF; + } + YY_BREAK +case 14: +YY_RULE_SETUP +#line 212 "dtc-lexer.l" +{ /* new-style path reference */ + yytext[yyleng-1] = '\0'; + DPRINT("Ref: %s\n", yytext+2); + yylval.labelref = xstrdup(yytext+2); + return DT_REF; + } + YY_BREAK +case 15: +YY_RULE_SETUP +#line 219 "dtc-lexer.l" +{ + yylval.byte = strtol(yytext, NULL, 16); + DPRINT("Byte: %02x\n", (int)yylval.byte); + return DT_BYTE; + } + YY_BREAK +case 16: +YY_RULE_SETUP +#line 225 "dtc-lexer.l" +{ + DPRINT("/BYTESTRING\n"); + BEGIN_DEFAULT(); + return ']'; + } + YY_BREAK +case 17: +YY_RULE_SETUP +#line 231 "dtc-lexer.l" +{ + DPRINT("PropNodeName: %s\n", yytext); + yylval.propnodename = xstrdup((yytext[0] == '\\') ? + yytext + 1 : yytext); + BEGIN_DEFAULT(); + return DT_PROPNODENAME; + } + YY_BREAK +case 18: +YY_RULE_SETUP +#line 239 "dtc-lexer.l" +{ + DPRINT("Binary Include\n"); + return DT_INCBIN; + } + YY_BREAK +case 19: +/* rule 19 can match eol */ +YY_RULE_SETUP +#line 244 "dtc-lexer.l" +/* eat whitespace */ + YY_BREAK +case 20: +/* rule 20 can match eol */ +YY_RULE_SETUP +#line 245 "dtc-lexer.l" +/* eat C-style comments */ + YY_BREAK +case 21: +/* rule 21 can match eol */ +YY_RULE_SETUP +#line 246 "dtc-lexer.l" +/* eat C++-style comments */ + YY_BREAK +case 22: +YY_RULE_SETUP +#line 248 "dtc-lexer.l" +{ return DT_LSHIFT; }; + YY_BREAK +case 23: +YY_RULE_SETUP +#line 249 "dtc-lexer.l" +{ return DT_RSHIFT; }; + YY_BREAK +case 24: +YY_RULE_SETUP +#line 250 "dtc-lexer.l" +{ return DT_LE; }; + YY_BREAK +case 25: +YY_RULE_SETUP +#line 251 "dtc-lexer.l" +{ return DT_GE; }; + YY_BREAK +case 26: +YY_RULE_SETUP +#line 252 "dtc-lexer.l" +{ return DT_EQ; }; + YY_BREAK +case 27: +YY_RULE_SETUP +#line 253 "dtc-lexer.l" +{ return DT_NE; }; + YY_BREAK +case 28: +YY_RULE_SETUP +#line 254 "dtc-lexer.l" +{ return DT_AND; }; + YY_BREAK +case 29: +YY_RULE_SETUP +#line 255 "dtc-lexer.l" +{ return DT_OR; }; + YY_BREAK +case 30: +YY_RULE_SETUP +#line 257 "dtc-lexer.l" +{ + DPRINT("Char: %c (\\x%02x)\n", yytext[0], + (unsigned)yytext[0]); + if (yytext[0] == '[') { + DPRINT("<BYTESTRING>\n"); + BEGIN(BYTESTRING); + } + if ((yytext[0] == '{') + || (yytext[0] == ';')) { + DPRINT("<PROPNODENAME>\n"); + BEGIN(PROPNODENAME); + } + return yytext[0]; + } + YY_BREAK +case 31: +YY_RULE_SETUP +#line 272 "dtc-lexer.l" +ECHO; + YY_BREAK +#line 1260 "dtc-lexer.lex.c" + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = (yy_hold_char); + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++(yy_c_buf_p); + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_END_OF_FILE: + { + (yy_did_buffer_switch_on_eof) = 0; + + if ( yywrap( ) ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = + (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + (yy_c_buf_p) = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ +} /* end of yylex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +static int yy_get_next_buffer (void) +{ + register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + register char *source = (yytext_ptr); + register int number_to_move, i; + int ret_val; + + if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; + + else + { + int num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER; + + int yy_c_buf_p_offset = + (int) ((yy_c_buf_p) - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + number_to_move - 1; + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + (yy_n_chars), (size_t) num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + if ( (yy_n_chars) == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart(yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + /* Extend the array by 50%, plus the number we really need. */ + yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); + if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); + } + + (yy_n_chars) += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; + + (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + + static yy_state_type yy_get_previous_state (void) +{ + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = (yy_start); + yy_current_state += YY_AT_BOL(); + + for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 166 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) +{ + register int yy_is_jam; + register char *yy_cp = (yy_c_buf_p); + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 166 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 165); + + return yy_is_jam ? 0 : yy_current_state; +} + +#ifndef YY_NO_INPUT +#ifdef __cplusplus + static int yyinput (void) +#else + static int input (void) +#endif + +{ + int c; + + *(yy_c_buf_p) = (yy_hold_char); + + if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + /* This was really a NUL. */ + *(yy_c_buf_p) = '\0'; + + else + { /* need more input */ + int offset = (yy_c_buf_p) - (yytext_ptr); + ++(yy_c_buf_p); + + switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart(yyin ); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: + { + if ( yywrap( ) ) + return EOF; + + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = (yytext_ptr) + offset; + break; + } + } + } + + c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ + *(yy_c_buf_p) = '\0'; /* preserve yytext */ + (yy_hold_char) = *++(yy_c_buf_p); + + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n'); + + return c; +} +#endif /* ifndef YY_NO_INPUT */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * + * @note This function does not reset the start condition to @c INITIAL . + */ + void yyrestart (FILE * input_file ) +{ + + if ( ! YY_CURRENT_BUFFER ){ + yyensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer(yyin,YY_BUF_SIZE ); + } + + yy_init_buffer(YY_CURRENT_BUFFER,input_file ); + yy_load_buffer_state( ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * + */ + void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) +{ + + /* TODO. We should be able to replace this entire function body + * with + * yypop_buffer_state(); + * yypush_buffer_state(new_buffer); + */ + yyensure_buffer_stack (); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + yy_load_buffer_state( ); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + (yy_did_buffer_switch_on_eof) = 1; +} + +static void yy_load_buffer_state (void) +{ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + (yy_hold_char) = *(yy_c_buf_p); +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * + * @return the allocated buffer state. + */ + YY_BUFFER_STATE yy_create_buffer (FILE * file, int size ) +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer(b,file ); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with yy_create_buffer() + * + */ + void yy_delete_buffer (YY_BUFFER_STATE b ) +{ + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yyfree((void *) b->yy_ch_buf ); + + yyfree((void *) b ); +} + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a yyrestart() or at EOF. + */ + static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file ) + +{ + int oerrno = errno; + + yy_flush_buffer(b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then yy_init_buffer was _probably_ + * called from yyrestart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + b->yy_is_interactive = 0; + + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * + */ + void yy_flush_buffer (YY_BUFFER_STATE b ) +{ + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + yy_load_buffer_state( ); +} + +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * + */ +void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) +{ + if (new_buffer == NULL) + return; + + yyensure_buffer_stack(); + + /* This block is copied from yy_switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + (yy_buffer_stack_top)++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from yy_switch_to_buffer. */ + yy_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; +} + +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * + */ +void yypop_buffer_state (void) +{ + if (!YY_CURRENT_BUFFER) + return; + + yy_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + if ((yy_buffer_stack_top) > 0) + --(yy_buffer_stack_top); + + if (YY_CURRENT_BUFFER) { + yy_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; + } +} + +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void yyensure_buffer_stack (void) +{ + int num_to_alloc; + + if (!(yy_buffer_stack)) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; + (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + (yy_buffer_stack_max) = num_to_alloc; + (yy_buffer_stack_top) = 0; + return; + } + + if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + int grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = (yy_buffer_stack_max) + grow_size; + (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc + ((yy_buffer_stack), + num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + /* zero only the new slots.*/ + memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); + (yy_buffer_stack_max) = num_to_alloc; + } +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer(b ); + + return b; +} + +/** Setup the input buffer state to scan a string. The next call to yylex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * yy_scan_bytes() instead. + */ +YY_BUFFER_STATE yy_scan_string (yyconst char * yystr ) +{ + + return yy_scan_bytes(yystr,strlen(yystr) ); +} + +/** Setup the input buffer state to scan the given bytes. The next call to yylex() will + * scan from a @e copy of @a bytes. + * @param yybytes the byte buffer to scan + * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len ) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = _yybytes_len + 2; + buf = (char *) yyalloc(n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < _yybytes_len; ++i ) + buf[i] = yybytes[i]; + + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer(buf,n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +static void yy_fatal_error (yyconst char* msg ) +{ + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + yytext[yyleng] = (yy_hold_char); \ + (yy_c_buf_p) = yytext + yyless_macro_arg; \ + (yy_hold_char) = *(yy_c_buf_p); \ + *(yy_c_buf_p) = '\0'; \ + yyleng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/** Get the current line number. + * + */ +int yyget_lineno (void) +{ + + return yylineno; +} + +/** Get the input stream. + * + */ +FILE *yyget_in (void) +{ + return yyin; +} + +/** Get the output stream. + * + */ +FILE *yyget_out (void) +{ + return yyout; +} + +/** Get the length of the current token. + * + */ +int yyget_leng (void) +{ + return yyleng; +} + +/** Get the current token. + * + */ + +char *yyget_text (void) +{ + return yytext; +} + +/** Set the current line number. + * @param line_number + * + */ +void yyset_lineno (int line_number ) +{ + + yylineno = line_number; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param in_str A readable stream. + * + * @see yy_switch_to_buffer + */ +void yyset_in (FILE * in_str ) +{ + yyin = in_str ; +} + +void yyset_out (FILE * out_str ) +{ + yyout = out_str ; +} + +int yyget_debug (void) +{ + return yy_flex_debug; +} + +void yyset_debug (int bdebug ) +{ + yy_flex_debug = bdebug ; +} + +static int yy_init_globals (void) +{ + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from yylex_destroy(), so don't allocate here. + */ + + (yy_buffer_stack) = 0; + (yy_buffer_stack_top) = 0; + (yy_buffer_stack_max) = 0; + (yy_c_buf_p) = (char *) 0; + (yy_init) = 0; + (yy_start) = 0; + +/* Defined in main.c */ +#ifdef YY_STDINIT + yyin = stdin; + yyout = stdout; +#else + yyin = (FILE *) 0; + yyout = (FILE *) 0; +#endif + + /* For future reference: Set errno on error, since we are called by + * yylex_init() + */ + return 0; +} + +/* yylex_destroy is for both reentrant and non-reentrant scanners. */ +int yylex_destroy (void) +{ + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + yy_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + yypop_buffer_state(); + } + + /* Destroy the stack itself. */ + yyfree((yy_buffer_stack) ); + (yy_buffer_stack) = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * yylex() is called, initialization will occur. */ + yy_init_globals( ); + + return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) +{ + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * s ) +{ + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +void *yyalloc (yy_size_t size ) +{ + return (void *) malloc( size ); +} + +void *yyrealloc (void * ptr, yy_size_t size ) +{ + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); +} + +void yyfree (void * ptr ) +{ + free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ +} + +#define YYTABLES_NAME "yytables" + +#line 272 "dtc-lexer.l" + + + +static void push_input_file(const char *filename) +{ + assert(filename); + + srcfile_push(filename); + + yyin = current_srcfile->f; + + yypush_buffer_state(yy_create_buffer(yyin,YY_BUF_SIZE)); +} + + +static bool pop_input_file(void) +{ + if (srcfile_pop() == 0) + return false; + + yypop_buffer_state(); + yyin = current_srcfile->f; + + return true; +} + +static void lexical_error(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + srcpos_verror(&yylloc, "Lexical error", fmt, ap); + va_end(ap); + + treesource_error = true; +} + diff --git a/scripts/dtc/dtc-parser.tab.c_shipped b/scripts/dtc/dtc-parser.tab.c_shipped new file mode 100644 index 0000000000..4d10814b3f --- /dev/null +++ b/scripts/dtc/dtc-parser.tab.c_shipped @@ -0,0 +1,2301 @@ +/* A Bison parser, made by GNU Bison 3.0.2. */ + +/* Bison implementation for Yacc-like parsers in C + + Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Bison version. */ +#define YYBISON_VERSION "3.0.2" + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 0 + +/* Push parsers. */ +#define YYPUSH 0 + +/* Pull parsers. */ +#define YYPULL 1 + + + + +/* Copy the first part of user declarations. */ +#line 20 "dtc-parser.y" /* yacc.c:339 */ + +#include <stdio.h> +#include <inttypes.h> + +#include "dtc.h" +#include "srcpos.h" + +extern int yylex(void); +extern void yyerror(char const *s); +#define ERROR(loc, ...) \ + do { \ + srcpos_error((loc), "Error", __VA_ARGS__); \ + treesource_error = true; \ + } while (0) + +extern struct dt_info *parser_output; +extern bool treesource_error; + +#line 85 "dtc-parser.tab.c" /* yacc.c:339 */ + +# ifndef YY_NULLPTR +# if defined __cplusplus && 201103L <= __cplusplus +# define YY_NULLPTR nullptr +# else +# define YY_NULLPTR 0 +# endif +# endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +/* In a future release of Bison, this section will be replaced + by #include "dtc-parser.tab.h". */ +#ifndef YY_YY_DTC_PARSER_TAB_H_INCLUDED +# define YY_YY_DTC_PARSER_TAB_H_INCLUDED +/* Debug traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif +#if YYDEBUG +extern int yydebug; +#endif + +/* Token type. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + enum yytokentype + { + DT_V1 = 258, + DT_PLUGIN = 259, + DT_MEMRESERVE = 260, + DT_LSHIFT = 261, + DT_RSHIFT = 262, + DT_LE = 263, + DT_GE = 264, + DT_EQ = 265, + DT_NE = 266, + DT_AND = 267, + DT_OR = 268, + DT_BITS = 269, + DT_DEL_PROP = 270, + DT_DEL_NODE = 271, + DT_PROPNODENAME = 272, + DT_LITERAL = 273, + DT_CHAR_LITERAL = 274, + DT_BYTE = 275, + DT_STRING = 276, + DT_LABEL = 277, + DT_REF = 278, + DT_INCBIN = 279 + }; +#endif + +/* Value type. */ +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef union YYSTYPE YYSTYPE; +union YYSTYPE +{ +#line 39 "dtc-parser.y" /* yacc.c:355 */ + + char *propnodename; + char *labelref; + uint8_t byte; + struct data data; + + struct { + struct data data; + int bits; + } array; + + struct property *prop; + struct property *proplist; + struct node *node; + struct node *nodelist; + struct reserve_info *re; + uint64_t integer; + unsigned int flags; + +#line 170 "dtc-parser.tab.c" /* yacc.c:355 */ +}; +# define YYSTYPE_IS_TRIVIAL 1 +# define YYSTYPE_IS_DECLARED 1 +#endif + +/* Location type. */ +#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED +typedef struct YYLTYPE YYLTYPE; +struct YYLTYPE +{ + int first_line; + int first_column; + int last_line; + int last_column; +}; +# define YYLTYPE_IS_DECLARED 1 +# define YYLTYPE_IS_TRIVIAL 1 +#endif + + +extern YYSTYPE yylval; +extern YYLTYPE yylloc; +int yyparse (void); + +#endif /* !YY_YY_DTC_PARSER_TAB_H_INCLUDED */ + +/* Copy the second part of user declarations. */ + +#line 199 "dtc-parser.tab.c" /* yacc.c:358 */ + +#ifdef short +# undef short +#endif + +#ifdef YYTYPE_UINT8 +typedef YYTYPE_UINT8 yytype_uint8; +#else +typedef unsigned char yytype_uint8; +#endif + +#ifdef YYTYPE_INT8 +typedef YYTYPE_INT8 yytype_int8; +#else +typedef signed char yytype_int8; +#endif + +#ifdef YYTYPE_UINT16 +typedef YYTYPE_UINT16 yytype_uint16; +#else +typedef unsigned short int yytype_uint16; +#endif + +#ifdef YYTYPE_INT16 +typedef YYTYPE_INT16 yytype_int16; +#else +typedef short int yytype_int16; +#endif + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif ! defined YYSIZE_T +# include <stddef.h> /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned int +# endif +#endif + +#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) + +#ifndef YY_ +# if defined YYENABLE_NLS && YYENABLE_NLS +# if ENABLE_NLS +# include <libintl.h> /* INFRINGES ON USER NAME SPACE */ +# define YY_(Msgid) dgettext ("bison-runtime", Msgid) +# endif +# endif +# ifndef YY_ +# define YY_(Msgid) Msgid +# endif +#endif + +#ifndef YY_ATTRIBUTE +# if (defined __GNUC__ \ + && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \ + || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C +# define YY_ATTRIBUTE(Spec) __attribute__(Spec) +# else +# define YY_ATTRIBUTE(Spec) /* empty */ +# endif +#endif + +#ifndef YY_ATTRIBUTE_PURE +# define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__)) +#endif + +#ifndef YY_ATTRIBUTE_UNUSED +# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__)) +#endif + +#if !defined _Noreturn \ + && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112) +# if defined _MSC_VER && 1200 <= _MSC_VER +# define _Noreturn __declspec (noreturn) +# else +# define _Noreturn YY_ATTRIBUTE ((__noreturn__)) +# endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YYUSE(E) ((void) (E)) +#else +# define YYUSE(E) /* empty */ +#endif + +#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ +/* Suppress an incorrect diagnostic about yylval being uninitialized. */ +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\ + _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ + _Pragma ("GCC diagnostic pop") +#else +# define YY_INITIAL_VALUE(Value) Value +#endif +#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_END +#endif +#ifndef YY_INITIAL_VALUE +# define YY_INITIAL_VALUE(Value) /* Nothing. */ +#endif + + +#if ! defined yyoverflow || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include <alloca.h> /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include <malloc.h> /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca +# else +# define YYSTACK_ALLOC alloca +# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS +# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ + /* Use EXIT_SUCCESS as a witness for stdlib.h. */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's 'empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && ! defined EXIT_SUCCESS \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) +# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if ! defined malloc && ! defined EXIT_SUCCESS +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if ! defined free && ! defined EXIT_SUCCESS +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# endif +#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ + + +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \ + && defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + yytype_int16 yyss_alloc; + YYSTYPE yyvs_alloc; + YYLTYPE yyls_alloc; +}; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \ + + 2 * YYSTACK_GAP_MAXIMUM) + +# define YYCOPY_NEEDED 1 + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ + Stack = &yyptr->Stack_alloc; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (0) + +#endif + +#if defined YYCOPY_NEEDED && YYCOPY_NEEDED +/* Copy COUNT objects from SRC to DST. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(Dst, Src, Count) \ + __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src))) +# else +# define YYCOPY(Dst, Src, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (Dst)[yyi] = (Src)[yyi]; \ + } \ + while (0) +# endif +# endif +#endif /* !YYCOPY_NEEDED */ + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 6 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 138 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 48 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 30 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 84 +/* YYNSTATES -- Number of states. */ +#define YYNSTATES 149 + +/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned + by yylex, with out-of-bounds checking. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 279 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM + as returned by yylex, without out-of-bounds checking. */ +static const yytype_uint8 yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 47, 2, 2, 2, 45, 41, 2, + 33, 35, 44, 42, 34, 43, 2, 26, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 38, 25, + 36, 29, 30, 37, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 31, 2, 32, 40, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 27, 39, 28, 46, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 +}; + +#if YYDEBUG + /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ +static const yytype_uint16 yyrline[] = +{ + 0, 109, 109, 117, 121, 128, 129, 139, 142, 149, + 153, 161, 165, 170, 181, 191, 206, 214, 217, 224, + 228, 232, 236, 244, 248, 252, 256, 260, 276, 286, + 294, 297, 301, 308, 324, 329, 348, 362, 369, 370, + 371, 378, 382, 383, 387, 388, 392, 393, 397, 398, + 402, 403, 407, 408, 412, 413, 414, 418, 419, 420, + 421, 422, 426, 427, 428, 432, 433, 434, 438, 439, + 448, 457, 461, 462, 463, 464, 469, 472, 476, 484, + 487, 491, 499, 503, 507 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE || 0 +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "DT_V1", "DT_PLUGIN", "DT_MEMRESERVE", + "DT_LSHIFT", "DT_RSHIFT", "DT_LE", "DT_GE", "DT_EQ", "DT_NE", "DT_AND", + "DT_OR", "DT_BITS", "DT_DEL_PROP", "DT_DEL_NODE", "DT_PROPNODENAME", + "DT_LITERAL", "DT_CHAR_LITERAL", "DT_BYTE", "DT_STRING", "DT_LABEL", + "DT_REF", "DT_INCBIN", "';'", "'/'", "'{'", "'}'", "'='", "'>'", "'['", + "']'", "'('", "','", "')'", "'<'", "'?'", "':'", "'|'", "'^'", "'&'", + "'+'", "'-'", "'*'", "'%'", "'~'", "'!'", "$accept", "sourcefile", + "header", "headers", "memreserves", "memreserve", "devicetree", + "nodedef", "proplist", "propdef", "propdata", "propdataprefix", + "arrayprefix", "integer_prim", "integer_expr", "integer_trinary", + "integer_or", "integer_and", "integer_bitor", "integer_bitxor", + "integer_bitand", "integer_eq", "integer_rela", "integer_shift", + "integer_add", "integer_mul", "integer_unary", "bytestring", "subnodes", + "subnode", YY_NULLPTR +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[NUM] -- (External) token number corresponding to the + (internal) symbol number NUM (which must be that of a token). */ +static const yytype_uint16 yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 277, 278, 279, 59, 47, 123, 125, 61, + 62, 91, 93, 40, 44, 41, 60, 63, 58, 124, + 94, 38, 43, 45, 42, 37, 126, 33 +}; +# endif + +#define YYPACT_NINF -44 + +#define yypact_value_is_default(Yystate) \ + (!!((Yystate) == (-44))) + +#define YYTABLE_NINF -1 + +#define yytable_value_is_error(Yytable_value) \ + 0 + + /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +static const yytype_int8 yypact[] = +{ + 14, 27, 61, 14, 8, 18, -44, -44, 37, 8, + 40, 8, 64, -44, -44, -12, 37, -44, 50, 52, + -44, -44, -12, -12, -12, -44, 51, -44, -4, 78, + 53, 54, 55, 17, 2, 30, 38, -3, -44, 66, + -44, -44, 70, 72, 50, 50, -44, -44, -44, -44, + -12, -12, -12, -12, -12, -12, -12, -12, -12, -12, + -12, -12, -12, -12, -12, -12, -12, -12, -12, -44, + 3, 73, 50, -44, -44, 78, 59, 53, 54, 55, + 17, 2, 2, 30, 30, 30, 30, 38, 38, -3, + -3, -44, -44, -44, 82, 83, 44, 3, -44, 74, + 3, -44, -44, -12, 76, 79, -44, -44, -44, -44, + -44, 80, -44, -44, -44, -44, -44, -10, 36, -44, + -44, -44, -44, 85, -44, -44, -44, 75, -44, -44, + 21, 71, 88, -6, -44, -44, -44, -44, -44, 11, + -44, -44, -44, 37, -44, 77, 37, 81, -44 +}; + + /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. + Performed when YYTABLE does not specify something else to do. Zero + means the default is an error. */ +static const yytype_uint8 yydefact[] = +{ + 0, 0, 0, 5, 7, 3, 1, 6, 0, 0, + 0, 7, 0, 38, 39, 0, 0, 10, 0, 2, + 8, 4, 0, 0, 0, 72, 0, 41, 42, 44, + 46, 48, 50, 52, 54, 57, 64, 67, 71, 0, + 17, 11, 0, 0, 0, 0, 73, 74, 75, 40, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, + 79, 0, 0, 14, 12, 45, 0, 47, 49, 51, + 53, 55, 56, 60, 61, 59, 58, 62, 63, 65, + 66, 69, 68, 70, 0, 0, 0, 0, 18, 0, + 79, 15, 13, 0, 0, 0, 20, 30, 82, 22, + 84, 0, 81, 80, 43, 21, 83, 0, 0, 16, + 29, 19, 31, 0, 23, 32, 26, 0, 76, 34, + 0, 0, 0, 0, 37, 36, 24, 35, 33, 0, + 77, 78, 25, 0, 28, 0, 0, 0, 27 +}; + + /* YYPGOTO[NTERM-NUM]. */ +static const yytype_int8 yypgoto[] = +{ + -44, -44, -44, 103, 99, 104, -44, -43, -44, -21, + -44, -44, -44, -8, 63, 9, -44, 65, 67, 68, + 69, 62, 26, 4, 22, 23, -19, -44, 20, 28 +}; + + /* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int16 yydefgoto[] = +{ + -1, 2, 3, 4, 10, 11, 19, 41, 70, 98, + 117, 118, 130, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 133, 99, 100 +}; + + /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule whose + number is the opposite. If YYTABLE_NINF, syntax error. */ +static const yytype_uint8 yytable[] = +{ + 16, 73, 74, 46, 47, 48, 13, 14, 39, 50, + 58, 59, 120, 8, 140, 121, 141, 1, 94, 95, + 96, 15, 12, 66, 122, 97, 142, 56, 57, 102, + 9, 22, 60, 51, 23, 24, 62, 63, 61, 13, + 14, 67, 68, 134, 135, 143, 144, 91, 92, 93, + 123, 136, 5, 108, 15, 13, 14, 124, 125, 126, + 127, 6, 83, 84, 85, 86, 18, 128, 42, 106, + 15, 40, 129, 107, 43, 44, 109, 40, 45, 112, + 64, 65, 81, 82, 87, 88, 49, 89, 90, 21, + 52, 69, 53, 71, 54, 72, 55, 103, 101, 104, + 105, 115, 111, 131, 116, 119, 7, 138, 132, 139, + 20, 146, 114, 17, 76, 75, 148, 80, 0, 77, + 113, 78, 137, 79, 0, 110, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 145, 0, 0, 147 +}; + +static const yytype_int16 yycheck[] = +{ + 8, 44, 45, 22, 23, 24, 18, 19, 16, 13, + 8, 9, 22, 5, 20, 25, 22, 3, 15, 16, + 17, 33, 4, 26, 34, 22, 32, 10, 11, 72, + 22, 43, 30, 37, 46, 47, 6, 7, 36, 18, + 19, 44, 45, 22, 23, 34, 35, 66, 67, 68, + 14, 30, 25, 96, 33, 18, 19, 21, 22, 23, + 24, 0, 58, 59, 60, 61, 26, 31, 16, 25, + 33, 27, 36, 29, 22, 23, 97, 27, 26, 100, + 42, 43, 56, 57, 62, 63, 35, 64, 65, 25, + 12, 25, 39, 23, 40, 23, 41, 38, 25, 17, + 17, 25, 28, 18, 25, 25, 3, 36, 33, 21, + 11, 34, 103, 9, 51, 50, 35, 55, -1, 52, + 100, 53, 130, 54, -1, 97, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 143, -1, -1, 146 +}; + + /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const yytype_uint8 yystos[] = +{ + 0, 3, 49, 50, 51, 25, 0, 51, 5, 22, + 52, 53, 4, 18, 19, 33, 61, 53, 26, 54, + 52, 25, 43, 46, 47, 61, 62, 63, 64, 65, + 66, 67, 68, 69, 70, 71, 72, 73, 74, 61, + 27, 55, 16, 22, 23, 26, 74, 74, 74, 35, + 13, 37, 12, 39, 40, 41, 10, 11, 8, 9, + 30, 36, 6, 7, 42, 43, 26, 44, 45, 25, + 56, 23, 23, 55, 55, 65, 62, 66, 67, 68, + 69, 70, 70, 71, 71, 71, 71, 72, 72, 73, + 73, 74, 74, 74, 15, 16, 17, 22, 57, 76, + 77, 25, 55, 38, 17, 17, 25, 29, 55, 57, + 77, 28, 57, 76, 63, 25, 25, 58, 59, 25, + 22, 25, 34, 14, 21, 22, 23, 24, 31, 36, + 60, 18, 33, 75, 22, 23, 30, 61, 36, 21, + 20, 22, 32, 34, 35, 61, 34, 61, 35 +}; + + /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const yytype_uint8 yyr1[] = +{ + 0, 48, 49, 50, 50, 51, 51, 52, 52, 53, + 53, 54, 54, 54, 54, 54, 55, 56, 56, 57, + 57, 57, 57, 58, 58, 58, 58, 58, 58, 58, + 59, 59, 59, 60, 60, 60, 60, 60, 61, 61, + 61, 62, 63, 63, 64, 64, 65, 65, 66, 66, + 67, 67, 68, 68, 69, 69, 69, 70, 70, 70, + 70, 70, 71, 71, 71, 72, 72, 72, 73, 73, + 73, 73, 74, 74, 74, 74, 75, 75, 75, 76, + 76, 76, 77, 77, 77 +}; + + /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ +static const yytype_uint8 yyr2[] = +{ + 0, 2, 3, 2, 4, 1, 2, 0, 2, 4, + 2, 2, 3, 4, 3, 4, 5, 0, 2, 4, + 2, 3, 2, 2, 3, 4, 2, 9, 5, 2, + 0, 2, 2, 3, 1, 2, 2, 2, 1, 1, + 3, 1, 1, 5, 1, 3, 1, 3, 1, 3, + 1, 3, 1, 3, 1, 3, 3, 1, 3, 3, + 3, 3, 3, 3, 1, 3, 3, 1, 3, 3, + 3, 1, 1, 2, 2, 2, 0, 2, 2, 0, + 2, 2, 2, 3, 2 +}; + + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + YYPOPSTACK (yylen); \ + yystate = *yyssp; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ +while (0) + +/* Error token number */ +#define YYTERROR 1 +#define YYERRCODE 256 + + +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. + If N is 0, then set CURRENT to the empty location which ends + the previous symbol: RHS[0] (always defined). */ + +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (N) \ + { \ + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + } \ + else \ + { \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC (Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC (Rhs, 0).last_column; \ + } \ + while (0) +#endif + +#define YYRHSLOC(Rhs, K) ((Rhs)[K]) + + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include <stdio.h> /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (0) + + +/* YY_LOCATION_PRINT -- Print the location on the stream. + This macro was not mandated originally: define only if we know + we won't break user code: when these are the locations we know. */ + +#ifndef YY_LOCATION_PRINT +# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL + +/* Print *YYLOCP on YYO. Private, do not rely on its existence. */ + +YY_ATTRIBUTE_UNUSED +static unsigned +yy_location_print_ (FILE *yyo, YYLTYPE const * const yylocp) +{ + unsigned res = 0; + int end_col = 0 != yylocp->last_column ? yylocp->last_column - 1 : 0; + if (0 <= yylocp->first_line) + { + res += YYFPRINTF (yyo, "%d", yylocp->first_line); + if (0 <= yylocp->first_column) + res += YYFPRINTF (yyo, ".%d", yylocp->first_column); + } + if (0 <= yylocp->last_line) + { + if (yylocp->first_line < yylocp->last_line) + { + res += YYFPRINTF (yyo, "-%d", yylocp->last_line); + if (0 <= end_col) + res += YYFPRINTF (yyo, ".%d", end_col); + } + else if (0 <= end_col && yylocp->first_column < end_col) + res += YYFPRINTF (yyo, "-%d", end_col); + } + return res; + } + +# define YY_LOCATION_PRINT(File, Loc) \ + yy_location_print_ (File, &(Loc)) + +# else +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +# endif +#endif + + +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Type, Value, Location); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (0) + + +/*----------------------------------------. +| Print this symbol's value on YYOUTPUT. | +`----------------------------------------*/ + +static void +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp) +{ + FILE *yyo = yyoutput; + YYUSE (yyo); + YYUSE (yylocationp); + if (!yyvaluep) + return; +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# endif + YYUSE (yytype); +} + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +static void +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp) +{ + YYFPRINTF (yyoutput, "%s %s (", + yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]); + + YY_LOCATION_PRINT (yyoutput, *yylocationp); + YYFPRINTF (yyoutput, ": "); + yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp); + YYFPRINTF (yyoutput, ")"); +} + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +static void +yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) +{ + YYFPRINTF (stderr, "Stack now"); + for (; yybottom <= yytop; yybottom++) + { + int yybot = *yybottom; + YYFPRINTF (stderr, " %d", yybot); + } + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (0) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +static void +yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule) +{ + unsigned long int yylno = yyrline[yyrule]; + int yynrhs = yyr2[yyrule]; + int yyi; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + YYFPRINTF (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, + yystos[yyssp[yyi + 1 - yynrhs]], + &(yyvsp[(yyi + 1) - (yynrhs)]) + , &(yylsp[(yyi + 1) - (yynrhs)]) ); + YYFPRINTF (stderr, "\n"); + } +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyssp, yyvsp, yylsp, Rule); \ +} while (0) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined __GLIBC__ && defined _STRING_H +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +static YYSIZE_T +yystrlen (const char *yystr) +{ + YYSIZE_T yylen; + for (yylen = 0; yystr[yylen]; yylen++) + continue; + return yylen; +} +# endif +# endif + +# ifndef yystpcpy +# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +static char * +yystpcpy (char *yydest, const char *yysrc) +{ + char *yyd = yydest; + const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +# ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYSIZE_T +yytnamerr (char *yyres, const char *yystr) +{ + if (*yystr == '"') + { + YYSIZE_T yyn = 0; + char const *yyp = yystr; + + for (;;) + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } + do_not_strip_quotes: ; + } + + if (! yyres) + return yystrlen (yystr); + + return yystpcpy (yyres, yystr) - yyres; +} +# endif + +/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message + about the unexpected token YYTOKEN for the state stack whose top is + YYSSP. + + Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is + not large enough to hold the message. In that case, also set + *YYMSG_ALLOC to the required number of bytes. Return 2 if the + required number of bytes is too large to store. */ +static int +yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, + yytype_int16 *yyssp, int yytoken) +{ + YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]); + YYSIZE_T yysize = yysize0; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + /* Internationalized format string. */ + const char *yyformat = YY_NULLPTR; + /* Arguments of yyformat. */ + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + /* Number of reported tokens (one for the "unexpected", one per + "expected"). */ + int yycount = 0; + + /* There are many possibilities here to consider: + - If this state is a consistent state with a default action, then + the only way this function was invoked is if the default action + is an error action. In that case, don't check for expected + tokens because there are none. + - The only way there can be no lookahead present (in yychar) is if + this state is a consistent state with a default action. Thus, + detecting the absence of a lookahead is sufficient to determine + that there is no unexpected or expected token to report. In that + case, just report a simple "syntax error". + - Don't assume there isn't a lookahead just because this state is a + consistent state with a default action. There might have been a + previous inconsistent state, consistent state with a non-default + action, or user semantic action that manipulated yychar. + - Of course, the expected token list depends on states to have + correct lookahead information, and it depends on the parser not + to perform extra reductions after fetching a lookahead from the + scanner and before detecting a syntax error. Thus, state merging + (from LALR or IELR) and default reductions corrupt the expected + token list. However, the list is correct for canonical LR with + one exception: it will still contain any token that will not be + accepted due to an error action in a later state. + */ + if (yytoken != YYEMPTY) + { + int yyn = yypact[*yyssp]; + yyarg[yycount++] = yytname[yytoken]; + if (!yypact_value_is_default (yyn)) + { + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. In other words, skip the first -YYN actions for + this state because they are default actions. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yyx; + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR + && !yytable_value_is_error (yytable[yyx + yyn])) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + break; + } + yyarg[yycount++] = yytname[yyx]; + { + YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]); + if (! (yysize <= yysize1 + && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } + } + } + } + + switch (yycount) + { +# define YYCASE_(N, S) \ + case N: \ + yyformat = S; \ + break + YYCASE_(0, YY_("syntax error")); + YYCASE_(1, YY_("syntax error, unexpected %s")); + YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); + YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); + YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); + YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); +# undef YYCASE_ + } + + { + YYSIZE_T yysize1 = yysize + yystrlen (yyformat); + if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } + + if (*yymsg_alloc < yysize) + { + *yymsg_alloc = 2 * yysize; + if (! (yysize <= *yymsg_alloc + && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) + *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; + return 1; + } + + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + { + char *yyp = *yymsg; + int yyi = 0; + while ((*yyp = *yyformat) != '\0') + if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyformat += 2; + } + else + { + yyp++; + yyformat++; + } + } + return 0; +} +#endif /* YYERROR_VERBOSE */ + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +static void +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp) +{ + YYUSE (yyvaluep); + YYUSE (yylocationp); + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); + + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + YYUSE (yytype); + YY_IGNORE_MAYBE_UNINITIALIZED_END +} + + + + +/* The lookahead symbol. */ +int yychar; + +/* The semantic value of the lookahead symbol. */ +YYSTYPE yylval; +/* Location data for the lookahead symbol. */ +YYLTYPE yylloc +# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL + = { 1, 1, 1, 1 } +# endif +; +/* Number of syntax errors so far. */ +int yynerrs; + + +/*----------. +| yyparse. | +`----------*/ + +int +yyparse (void) +{ + int yystate; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + + /* The stacks and their tools: + 'yyss': related to states. + 'yyvs': related to semantic values. + 'yyls': related to locations. + + Refer to the stacks through separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss; + yytype_int16 *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs; + YYSTYPE *yyvsp; + + /* The location stack. */ + YYLTYPE yylsa[YYINITDEPTH]; + YYLTYPE *yyls; + YYLTYPE *yylsp; + + /* The locations where the error started and ended. */ + YYLTYPE yyerror_range[3]; + + YYSIZE_T yystacksize; + + int yyn; + int yyresult; + /* Lookahead token as an internal (translated) token number. */ + int yytoken = 0; + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + YYLTYPE yyloc; + +#if YYERROR_VERBOSE + /* Buffer for error messages, and its allocated size. */ + char yymsgbuf[128]; + char *yymsg = yymsgbuf; + YYSIZE_T yymsg_alloc = sizeof yymsgbuf; +#endif + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N), yylsp -= (N)) + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; + + yyssp = yyss = yyssa; + yyvsp = yyvs = yyvsa; + yylsp = yyls = yylsa; + yystacksize = YYINITDEPTH; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + yylsp[0] = yylloc; + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + yytype_int16 *yyss1 = yyss; + YYLTYPE *yyls1 = yyls; + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + &yyls1, yysize * sizeof (*yylsp), + &yystacksize); + + yyls = yyls1; + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyexhaustedlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyexhaustedlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + yytype_int16 *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE (yyss_alloc, yyss); + YYSTACK_RELOCATE (yyvs_alloc, yyvs); + YYSTACK_RELOCATE (yyls_alloc, yyls); +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + yylsp = yyls + yysize - 1; + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + if (yystate == YYFINAL) + YYACCEPT; + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + + /* Do appropriate processing given the current state. Read a + lookahead token if we need one and don't already have one. */ + + /* First try to decide what to do without reference to lookahead token. */ + yyn = yypact[yystate]; + if (yypact_value_is_default (yyn)) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = yylex (); + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yytable_value_is_error (yyn)) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + /* Shift the lookahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + + /* Discard the shifted token. */ + yychar = YYEMPTY; + + yystate = yyn; + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END + *++yylsp = yylloc; + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + '$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + /* Default location. */ + YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen); + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 2: +#line 110 "dtc-parser.y" /* yacc.c:1646 */ + { + parser_output = build_dt_info((yyvsp[-2].flags), (yyvsp[-1].re), (yyvsp[0].node), + guess_boot_cpuid((yyvsp[0].node))); + } +#line 1476 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 3: +#line 118 "dtc-parser.y" /* yacc.c:1646 */ + { + (yyval.flags) = DTSF_V1; + } +#line 1484 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 4: +#line 122 "dtc-parser.y" /* yacc.c:1646 */ + { + (yyval.flags) = DTSF_V1 | DTSF_PLUGIN; + } +#line 1492 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 6: +#line 130 "dtc-parser.y" /* yacc.c:1646 */ + { + if ((yyvsp[0].flags) != (yyvsp[-1].flags)) + ERROR(&(yylsp[0]), "Header flags don't match earlier ones"); + (yyval.flags) = (yyvsp[-1].flags); + } +#line 1502 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 7: +#line 139 "dtc-parser.y" /* yacc.c:1646 */ + { + (yyval.re) = NULL; + } +#line 1510 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 8: +#line 143 "dtc-parser.y" /* yacc.c:1646 */ + { + (yyval.re) = chain_reserve_entry((yyvsp[-1].re), (yyvsp[0].re)); + } +#line 1518 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 9: +#line 150 "dtc-parser.y" /* yacc.c:1646 */ + { + (yyval.re) = build_reserve_entry((yyvsp[-2].integer), (yyvsp[-1].integer)); + } +#line 1526 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 10: +#line 154 "dtc-parser.y" /* yacc.c:1646 */ + { + add_label(&(yyvsp[0].re)->labels, (yyvsp[-1].labelref)); + (yyval.re) = (yyvsp[0].re); + } +#line 1535 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 11: +#line 162 "dtc-parser.y" /* yacc.c:1646 */ + { + (yyval.node) = name_node((yyvsp[0].node), ""); + } +#line 1543 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 12: +#line 166 "dtc-parser.y" /* yacc.c:1646 */ + { + (yyval.node) = merge_nodes((yyvsp[-2].node), (yyvsp[0].node)); + } +#line 1551 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 13: +#line 171 "dtc-parser.y" /* yacc.c:1646 */ + { + struct node *target = get_node_by_ref((yyvsp[-3].node), (yyvsp[-1].labelref)); + + if (target) { + add_label(&target->labels, (yyvsp[-2].labelref)); + merge_nodes(target, (yyvsp[0].node)); + } else + ERROR(&(yylsp[-1]), "Label or path %s not found", (yyvsp[-1].labelref)); + (yyval.node) = (yyvsp[-3].node); + } +#line 1566 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 14: +#line 182 "dtc-parser.y" /* yacc.c:1646 */ + { + struct node *target = get_node_by_ref((yyvsp[-2].node), (yyvsp[-1].labelref)); + + if (target) + merge_nodes(target, (yyvsp[0].node)); + else + ERROR(&(yylsp[-1]), "Label or path %s not found", (yyvsp[-1].labelref)); + (yyval.node) = (yyvsp[-2].node); + } +#line 1580 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 15: +#line 192 "dtc-parser.y" /* yacc.c:1646 */ + { + struct node *target = get_node_by_ref((yyvsp[-3].node), (yyvsp[-1].labelref)); + + if (target) + delete_node(target); + else + ERROR(&(yylsp[-1]), "Label or path %s not found", (yyvsp[-1].labelref)); + + + (yyval.node) = (yyvsp[-3].node); + } +#line 1596 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 16: +#line 207 "dtc-parser.y" /* yacc.c:1646 */ + { + (yyval.node) = build_node((yyvsp[-3].proplist), (yyvsp[-2].nodelist)); + } +#line 1604 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 17: +#line 214 "dtc-parser.y" /* yacc.c:1646 */ + { + (yyval.proplist) = NULL; + } +#line 1612 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 18: +#line 218 "dtc-parser.y" /* yacc.c:1646 */ + { + (yyval.proplist) = chain_property((yyvsp[0].prop), (yyvsp[-1].proplist)); + } +#line 1620 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 19: +#line 225 "dtc-parser.y" /* yacc.c:1646 */ + { + (yyval.prop) = build_property((yyvsp[-3].propnodename), (yyvsp[-1].data)); + } +#line 1628 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 20: +#line 229 "dtc-parser.y" /* yacc.c:1646 */ + { + (yyval.prop) = build_property((yyvsp[-1].propnodename), empty_data); + } +#line 1636 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 21: +#line 233 "dtc-parser.y" /* yacc.c:1646 */ + { + (yyval.prop) = build_property_delete((yyvsp[-1].propnodename)); + } +#line 1644 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 22: +#line 237 "dtc-parser.y" /* yacc.c:1646 */ + { + add_label(&(yyvsp[0].prop)->labels, (yyvsp[-1].labelref)); + (yyval.prop) = (yyvsp[0].prop); + } +#line 1653 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 23: +#line 245 "dtc-parser.y" /* yacc.c:1646 */ + { + (yyval.data) = data_merge((yyvsp[-1].data), (yyvsp[0].data)); + } +#line 1661 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 24: +#line 249 "dtc-parser.y" /* yacc.c:1646 */ + { + (yyval.data) = data_merge((yyvsp[-2].data), (yyvsp[-1].array).data); + } +#line 1669 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 25: +#line 253 "dtc-parser.y" /* yacc.c:1646 */ + { + (yyval.data) = data_merge((yyvsp[-3].data), (yyvsp[-1].data)); + } +#line 1677 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 26: +#line 257 "dtc-parser.y" /* yacc.c:1646 */ + { + (yyval.data) = data_add_marker((yyvsp[-1].data), REF_PATH, (yyvsp[0].labelref)); + } +#line 1685 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 27: +#line 261 "dtc-parser.y" /* yacc.c:1646 */ + { + FILE *f = srcfile_relative_open((yyvsp[-5].data).val, NULL); + struct data d; + + if ((yyvsp[-3].integer) != 0) + if (fseek(f, (yyvsp[-3].integer), SEEK_SET) != 0) + die("Couldn't seek to offset %llu in \"%s\": %s", + (unsigned long long)(yyvsp[-3].integer), (yyvsp[-5].data).val, + strerror(errno)); + + d = data_copy_file(f, (yyvsp[-1].integer)); + + (yyval.data) = data_merge((yyvsp[-8].data), d); + fclose(f); + } +#line 1705 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 28: +#line 277 "dtc-parser.y" /* yacc.c:1646 */ + { + FILE *f = srcfile_relative_open((yyvsp[-1].data).val, NULL); + struct data d = empty_data; + + d = data_copy_file(f, -1); + + (yyval.data) = data_merge((yyvsp[-4].data), d); + fclose(f); + } +#line 1719 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 29: +#line 287 "dtc-parser.y" /* yacc.c:1646 */ + { + (yyval.data) = data_add_marker((yyvsp[-1].data), LABEL, (yyvsp[0].labelref)); + } +#line 1727 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 30: +#line 294 "dtc-parser.y" /* yacc.c:1646 */ + { + (yyval.data) = empty_data; + } +#line 1735 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 31: +#line 298 "dtc-parser.y" /* yacc.c:1646 */ + { + (yyval.data) = (yyvsp[-1].data); + } +#line 1743 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 32: +#line 302 "dtc-parser.y" /* yacc.c:1646 */ + { + (yyval.data) = data_add_marker((yyvsp[-1].data), LABEL, (yyvsp[0].labelref)); + } +#line 1751 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 33: +#line 309 "dtc-parser.y" /* yacc.c:1646 */ + { + unsigned long long bits; + + bits = (yyvsp[-1].integer); + + if ((bits != 8) && (bits != 16) && + (bits != 32) && (bits != 64)) { + ERROR(&(yylsp[-1]), "Array elements must be" + " 8, 16, 32 or 64-bits"); + bits = 32; + } + + (yyval.array).data = empty_data; + (yyval.array).bits = bits; + } +#line 1771 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 34: +#line 325 "dtc-parser.y" /* yacc.c:1646 */ + { + (yyval.array).data = empty_data; + (yyval.array).bits = 32; + } +#line 1780 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 35: +#line 330 "dtc-parser.y" /* yacc.c:1646 */ + { + if ((yyvsp[-1].array).bits < 64) { + uint64_t mask = (1ULL << (yyvsp[-1].array).bits) - 1; + /* + * Bits above mask must either be all zero + * (positive within range of mask) or all one + * (negative and sign-extended). The second + * condition is true if when we set all bits + * within the mask to one (i.e. | in the + * mask), all bits are one. + */ + if (((yyvsp[0].integer) > mask) && (((yyvsp[0].integer) | mask) != -1ULL)) + ERROR(&(yylsp[0]), "Value out of range for" + " %d-bit array element", (yyvsp[-1].array).bits); + } + + (yyval.array).data = data_append_integer((yyvsp[-1].array).data, (yyvsp[0].integer), (yyvsp[-1].array).bits); + } +#line 1803 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 36: +#line 349 "dtc-parser.y" /* yacc.c:1646 */ + { + uint64_t val = ~0ULL >> (64 - (yyvsp[-1].array).bits); + + if ((yyvsp[-1].array).bits == 32) + (yyvsp[-1].array).data = data_add_marker((yyvsp[-1].array).data, + REF_PHANDLE, + (yyvsp[0].labelref)); + else + ERROR(&(yylsp[0]), "References are only allowed in " + "arrays with 32-bit elements."); + + (yyval.array).data = data_append_integer((yyvsp[-1].array).data, val, (yyvsp[-1].array).bits); + } +#line 1821 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 37: +#line 363 "dtc-parser.y" /* yacc.c:1646 */ + { + (yyval.array).data = data_add_marker((yyvsp[-1].array).data, LABEL, (yyvsp[0].labelref)); + } +#line 1829 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 40: +#line 372 "dtc-parser.y" /* yacc.c:1646 */ + { + (yyval.integer) = (yyvsp[-1].integer); + } +#line 1837 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 43: +#line 383 "dtc-parser.y" /* yacc.c:1646 */ + { (yyval.integer) = (yyvsp[-4].integer) ? (yyvsp[-2].integer) : (yyvsp[0].integer); } +#line 1843 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 45: +#line 388 "dtc-parser.y" /* yacc.c:1646 */ + { (yyval.integer) = (yyvsp[-2].integer) || (yyvsp[0].integer); } +#line 1849 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 47: +#line 393 "dtc-parser.y" /* yacc.c:1646 */ + { (yyval.integer) = (yyvsp[-2].integer) && (yyvsp[0].integer); } +#line 1855 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 49: +#line 398 "dtc-parser.y" /* yacc.c:1646 */ + { (yyval.integer) = (yyvsp[-2].integer) | (yyvsp[0].integer); } +#line 1861 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 51: +#line 403 "dtc-parser.y" /* yacc.c:1646 */ + { (yyval.integer) = (yyvsp[-2].integer) ^ (yyvsp[0].integer); } +#line 1867 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 53: +#line 408 "dtc-parser.y" /* yacc.c:1646 */ + { (yyval.integer) = (yyvsp[-2].integer) & (yyvsp[0].integer); } +#line 1873 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 55: +#line 413 "dtc-parser.y" /* yacc.c:1646 */ + { (yyval.integer) = (yyvsp[-2].integer) == (yyvsp[0].integer); } +#line 1879 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 56: +#line 414 "dtc-parser.y" /* yacc.c:1646 */ + { (yyval.integer) = (yyvsp[-2].integer) != (yyvsp[0].integer); } +#line 1885 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 58: +#line 419 "dtc-parser.y" /* yacc.c:1646 */ + { (yyval.integer) = (yyvsp[-2].integer) < (yyvsp[0].integer); } +#line 1891 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 59: +#line 420 "dtc-parser.y" /* yacc.c:1646 */ + { (yyval.integer) = (yyvsp[-2].integer) > (yyvsp[0].integer); } +#line 1897 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 60: +#line 421 "dtc-parser.y" /* yacc.c:1646 */ + { (yyval.integer) = (yyvsp[-2].integer) <= (yyvsp[0].integer); } +#line 1903 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 61: +#line 422 "dtc-parser.y" /* yacc.c:1646 */ + { (yyval.integer) = (yyvsp[-2].integer) >= (yyvsp[0].integer); } +#line 1909 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 62: +#line 426 "dtc-parser.y" /* yacc.c:1646 */ + { (yyval.integer) = (yyvsp[-2].integer) << (yyvsp[0].integer); } +#line 1915 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 63: +#line 427 "dtc-parser.y" /* yacc.c:1646 */ + { (yyval.integer) = (yyvsp[-2].integer) >> (yyvsp[0].integer); } +#line 1921 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 65: +#line 432 "dtc-parser.y" /* yacc.c:1646 */ + { (yyval.integer) = (yyvsp[-2].integer) + (yyvsp[0].integer); } +#line 1927 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 66: +#line 433 "dtc-parser.y" /* yacc.c:1646 */ + { (yyval.integer) = (yyvsp[-2].integer) - (yyvsp[0].integer); } +#line 1933 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 68: +#line 438 "dtc-parser.y" /* yacc.c:1646 */ + { (yyval.integer) = (yyvsp[-2].integer) * (yyvsp[0].integer); } +#line 1939 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 69: +#line 440 "dtc-parser.y" /* yacc.c:1646 */ + { + if ((yyvsp[0].integer) != 0) { + (yyval.integer) = (yyvsp[-2].integer) / (yyvsp[0].integer); + } else { + ERROR(&(yyloc), "Division by zero"); + (yyval.integer) = 0; + } + } +#line 1952 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 70: +#line 449 "dtc-parser.y" /* yacc.c:1646 */ + { + if ((yyvsp[0].integer) != 0) { + (yyval.integer) = (yyvsp[-2].integer) % (yyvsp[0].integer); + } else { + ERROR(&(yyloc), "Division by zero"); + (yyval.integer) = 0; + } + } +#line 1965 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 73: +#line 462 "dtc-parser.y" /* yacc.c:1646 */ + { (yyval.integer) = -(yyvsp[0].integer); } +#line 1971 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 74: +#line 463 "dtc-parser.y" /* yacc.c:1646 */ + { (yyval.integer) = ~(yyvsp[0].integer); } +#line 1977 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 75: +#line 464 "dtc-parser.y" /* yacc.c:1646 */ + { (yyval.integer) = !(yyvsp[0].integer); } +#line 1983 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 76: +#line 469 "dtc-parser.y" /* yacc.c:1646 */ + { + (yyval.data) = empty_data; + } +#line 1991 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 77: +#line 473 "dtc-parser.y" /* yacc.c:1646 */ + { + (yyval.data) = data_append_byte((yyvsp[-1].data), (yyvsp[0].byte)); + } +#line 1999 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 78: +#line 477 "dtc-parser.y" /* yacc.c:1646 */ + { + (yyval.data) = data_add_marker((yyvsp[-1].data), LABEL, (yyvsp[0].labelref)); + } +#line 2007 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 79: +#line 484 "dtc-parser.y" /* yacc.c:1646 */ + { + (yyval.nodelist) = NULL; + } +#line 2015 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 80: +#line 488 "dtc-parser.y" /* yacc.c:1646 */ + { + (yyval.nodelist) = chain_node((yyvsp[-1].node), (yyvsp[0].nodelist)); + } +#line 2023 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 81: +#line 492 "dtc-parser.y" /* yacc.c:1646 */ + { + ERROR(&(yylsp[0]), "Properties must precede subnodes"); + YYERROR; + } +#line 2032 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 82: +#line 500 "dtc-parser.y" /* yacc.c:1646 */ + { + (yyval.node) = name_node((yyvsp[0].node), (yyvsp[-1].propnodename)); + } +#line 2040 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 83: +#line 504 "dtc-parser.y" /* yacc.c:1646 */ + { + (yyval.node) = name_node(build_node_delete(), (yyvsp[-1].propnodename)); + } +#line 2048 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 84: +#line 508 "dtc-parser.y" /* yacc.c:1646 */ + { + add_label(&(yyvsp[0].node)->labels, (yyvsp[-1].labelref)); + (yyval.node) = (yyvsp[0].node); + } +#line 2057 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + +#line 2061 "dtc-parser.tab.c" /* yacc.c:1646 */ + default: break; + } + /* User semantic actions sometimes alter yychar, and that requires + that yytoken be updated with the new translation. We take the + approach of translating immediately before every use of yytoken. + One alternative is translating here after every semantic action, + but that translation would be missed if the semantic action invokes + YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or + if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an + incorrect destructor might then be invoked immediately. In the + case of YYERROR or YYBACKUP, subsequent parser actions might lead + to an incorrect destructor call or verbose syntax error message + before the lookahead is translated. */ + YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); + + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + *++yylsp = yyloc; + + /* Now 'shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*--------------------------------------. +| yyerrlab -- here on detecting error. | +`--------------------------------------*/ +yyerrlab: + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); + + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if ! YYERROR_VERBOSE + yyerror (YY_("syntax error")); +#else +# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ + yyssp, yytoken) + { + char const *yymsgp = YY_("syntax error"); + int yysyntax_error_status; + yysyntax_error_status = YYSYNTAX_ERROR; + if (yysyntax_error_status == 0) + yymsgp = yymsg; + else if (yysyntax_error_status == 1) + { + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); + if (!yymsg) + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + yysyntax_error_status = 2; + } + else + { + yysyntax_error_status = YYSYNTAX_ERROR; + yymsgp = yymsg; + } + } + yyerror (yymsgp); + if (yysyntax_error_status == 2) + goto yyexhaustedlab; + } +# undef YYSYNTAX_ERROR +#endif + } + + yyerror_range[1] = yylloc; + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct ("Error: discarding", + yytoken, &yylval, &yylloc); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + + /* Pacify compilers like GCC when the user code never invokes + YYERROR and the label yyerrorlab therefore never appears in user + code. */ + if (/*CONSTCOND*/ 0) + goto yyerrorlab; + + yyerror_range[1] = yylsp[1-yylen]; + /* Do not reclaim the symbols of the rule whose action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (!yypact_value_is_default (yyn)) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + yyerror_range[1] = *yylsp; + yydestruct ("Error: popping", + yystos[yystate], yyvsp, yylsp); + YYPOPSTACK (1); + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END + + yyerror_range[2] = yylloc; + /* Using YYLLOC is tempting, but would change the location of + the lookahead. YYLOC is available though. */ + YYLLOC_DEFAULT (yyloc, yyerror_range, 2); + *++yylsp = yyloc; + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#if !defined yyoverflow || YYERROR_VERBOSE +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror (YY_("memory exhausted")); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: + if (yychar != YYEMPTY) + { + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = YYTRANSLATE (yychar); + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval, &yylloc); + } + /* Do not reclaim the symbols of the rule whose action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + yystos[*yyssp], yyvsp, yylsp); + YYPOPSTACK (1); + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif +#if YYERROR_VERBOSE + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); +#endif + return yyresult; +} +#line 514 "dtc-parser.y" /* yacc.c:1906 */ + + +void yyerror(char const *s) +{ + ERROR(&yylloc, "%s", s); +} diff --git a/scripts/dtc/dtc-parser.tab.h_shipped b/scripts/dtc/dtc-parser.tab.h_shipped new file mode 100644 index 0000000000..e7b04dd016 --- /dev/null +++ b/scripts/dtc/dtc-parser.tab.h_shipped @@ -0,0 +1,123 @@ +/* A Bison parser, made by GNU Bison 3.0.2. */ + +/* Bison interface for Yacc-like parsers in C + + Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +#ifndef YY_YY_DTC_PARSER_TAB_H_INCLUDED +# define YY_YY_DTC_PARSER_TAB_H_INCLUDED +/* Debug traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif +#if YYDEBUG +extern int yydebug; +#endif + +/* Token type. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + enum yytokentype + { + DT_V1 = 258, + DT_PLUGIN = 259, + DT_MEMRESERVE = 260, + DT_LSHIFT = 261, + DT_RSHIFT = 262, + DT_LE = 263, + DT_GE = 264, + DT_EQ = 265, + DT_NE = 266, + DT_AND = 267, + DT_OR = 268, + DT_BITS = 269, + DT_DEL_PROP = 270, + DT_DEL_NODE = 271, + DT_PROPNODENAME = 272, + DT_LITERAL = 273, + DT_CHAR_LITERAL = 274, + DT_BYTE = 275, + DT_STRING = 276, + DT_LABEL = 277, + DT_REF = 278, + DT_INCBIN = 279 + }; +#endif + +/* Value type. */ +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef union YYSTYPE YYSTYPE; +union YYSTYPE +{ +#line 39 "dtc-parser.y" /* yacc.c:1909 */ + + char *propnodename; + char *labelref; + uint8_t byte; + struct data data; + + struct { + struct data data; + int bits; + } array; + + struct property *prop; + struct property *proplist; + struct node *node; + struct node *nodelist; + struct reserve_info *re; + uint64_t integer; + unsigned int flags; + +#line 99 "dtc-parser.tab.h" /* yacc.c:1909 */ +}; +# define YYSTYPE_IS_TRIVIAL 1 +# define YYSTYPE_IS_DECLARED 1 +#endif + +/* Location type. */ +#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED +typedef struct YYLTYPE YYLTYPE; +struct YYLTYPE +{ + int first_line; + int first_column; + int last_line; + int last_column; +}; +# define YYLTYPE_IS_DECLARED 1 +# define YYLTYPE_IS_TRIVIAL 1 +#endif + + +extern YYSTYPE yylval; +extern YYLTYPE yylloc; +int yyparse (void); + +#endif /* !YY_YY_DTC_PARSER_TAB_H_INCLUDED */ diff --git a/scripts/dtc/dtc-parser.y b/scripts/dtc/dtc-parser.y new file mode 100644 index 0000000000..ca3f500342 --- /dev/null +++ b/scripts/dtc/dtc-parser.y @@ -0,0 +1,519 @@ +/* + * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005. + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ +%{ +#include <stdio.h> +#include <inttypes.h> + +#include "dtc.h" +#include "srcpos.h" + +extern int yylex(void); +extern void yyerror(char const *s); +#define ERROR(loc, ...) \ + do { \ + srcpos_error((loc), "Error", __VA_ARGS__); \ + treesource_error = true; \ + } while (0) + +extern struct dt_info *parser_output; +extern bool treesource_error; +%} + +%union { + char *propnodename; + char *labelref; + uint8_t byte; + struct data data; + + struct { + struct data data; + int bits; + } array; + + struct property *prop; + struct property *proplist; + struct node *node; + struct node *nodelist; + struct reserve_info *re; + uint64_t integer; + unsigned int flags; +} + +%token DT_V1 +%token DT_PLUGIN +%token DT_MEMRESERVE +%token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR +%token DT_BITS +%token DT_DEL_PROP +%token DT_DEL_NODE +%token <propnodename> DT_PROPNODENAME +%token <integer> DT_LITERAL +%token <integer> DT_CHAR_LITERAL +%token <byte> DT_BYTE +%token <data> DT_STRING +%token <labelref> DT_LABEL +%token <labelref> DT_REF +%token DT_INCBIN + +%type <data> propdata +%type <data> propdataprefix +%type <flags> header +%type <flags> headers +%type <re> memreserve +%type <re> memreserves +%type <array> arrayprefix +%type <data> bytestring +%type <prop> propdef +%type <proplist> proplist + +%type <node> devicetree +%type <node> nodedef +%type <node> subnode +%type <nodelist> subnodes + +%type <integer> integer_prim +%type <integer> integer_unary +%type <integer> integer_mul +%type <integer> integer_add +%type <integer> integer_shift +%type <integer> integer_rela +%type <integer> integer_eq +%type <integer> integer_bitand +%type <integer> integer_bitxor +%type <integer> integer_bitor +%type <integer> integer_and +%type <integer> integer_or +%type <integer> integer_trinary +%type <integer> integer_expr + +%% + +sourcefile: + headers memreserves devicetree + { + parser_output = build_dt_info($1, $2, $3, + guess_boot_cpuid($3)); + } + ; + +header: + DT_V1 ';' + { + $$ = DTSF_V1; + } + | DT_V1 ';' DT_PLUGIN ';' + { + $$ = DTSF_V1 | DTSF_PLUGIN; + } + ; + +headers: + header + | header headers + { + if ($2 != $1) + ERROR(&@2, "Header flags don't match earlier ones"); + $$ = $1; + } + ; + +memreserves: + /* empty */ + { + $$ = NULL; + } + | memreserve memreserves + { + $$ = chain_reserve_entry($1, $2); + } + ; + +memreserve: + DT_MEMRESERVE integer_prim integer_prim ';' + { + $$ = build_reserve_entry($2, $3); + } + | DT_LABEL memreserve + { + add_label(&$2->labels, $1); + $$ = $2; + } + ; + +devicetree: + '/' nodedef + { + $$ = name_node($2, ""); + } + | devicetree '/' nodedef + { + $$ = merge_nodes($1, $3); + } + + | devicetree DT_LABEL DT_REF nodedef + { + struct node *target = get_node_by_ref($1, $3); + + if (target) { + add_label(&target->labels, $2); + merge_nodes(target, $4); + } else + ERROR(&@3, "Label or path %s not found", $3); + $$ = $1; + } + | devicetree DT_REF nodedef + { + struct node *target = get_node_by_ref($1, $2); + + if (target) + merge_nodes(target, $3); + else + ERROR(&@2, "Label or path %s not found", $2); + $$ = $1; + } + | devicetree DT_DEL_NODE DT_REF ';' + { + struct node *target = get_node_by_ref($1, $3); + + if (target) + delete_node(target); + else + ERROR(&@3, "Label or path %s not found", $3); + + + $$ = $1; + } + ; + +nodedef: + '{' proplist subnodes '}' ';' + { + $$ = build_node($2, $3); + } + ; + +proplist: + /* empty */ + { + $$ = NULL; + } + | proplist propdef + { + $$ = chain_property($2, $1); + } + ; + +propdef: + DT_PROPNODENAME '=' propdata ';' + { + $$ = build_property($1, $3); + } + | DT_PROPNODENAME ';' + { + $$ = build_property($1, empty_data); + } + | DT_DEL_PROP DT_PROPNODENAME ';' + { + $$ = build_property_delete($2); + } + | DT_LABEL propdef + { + add_label(&$2->labels, $1); + $$ = $2; + } + ; + +propdata: + propdataprefix DT_STRING + { + $$ = data_merge($1, $2); + } + | propdataprefix arrayprefix '>' + { + $$ = data_merge($1, $2.data); + } + | propdataprefix '[' bytestring ']' + { + $$ = data_merge($1, $3); + } + | propdataprefix DT_REF + { + $$ = data_add_marker($1, REF_PATH, $2); + } + | propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')' + { + FILE *f = srcfile_relative_open($4.val, NULL); + struct data d; + + if ($6 != 0) + if (fseek(f, $6, SEEK_SET) != 0) + die("Couldn't seek to offset %llu in \"%s\": %s", + (unsigned long long)$6, $4.val, + strerror(errno)); + + d = data_copy_file(f, $8); + + $$ = data_merge($1, d); + fclose(f); + } + | propdataprefix DT_INCBIN '(' DT_STRING ')' + { + FILE *f = srcfile_relative_open($4.val, NULL); + struct data d = empty_data; + + d = data_copy_file(f, -1); + + $$ = data_merge($1, d); + fclose(f); + } + | propdata DT_LABEL + { + $$ = data_add_marker($1, LABEL, $2); + } + ; + +propdataprefix: + /* empty */ + { + $$ = empty_data; + } + | propdata ',' + { + $$ = $1; + } + | propdataprefix DT_LABEL + { + $$ = data_add_marker($1, LABEL, $2); + } + ; + +arrayprefix: + DT_BITS DT_LITERAL '<' + { + unsigned long long bits; + + bits = $2; + + if ((bits != 8) && (bits != 16) && + (bits != 32) && (bits != 64)) { + ERROR(&@2, "Array elements must be" + " 8, 16, 32 or 64-bits"); + bits = 32; + } + + $$.data = empty_data; + $$.bits = bits; + } + | '<' + { + $$.data = empty_data; + $$.bits = 32; + } + | arrayprefix integer_prim + { + if ($1.bits < 64) { + uint64_t mask = (1ULL << $1.bits) - 1; + /* + * Bits above mask must either be all zero + * (positive within range of mask) or all one + * (negative and sign-extended). The second + * condition is true if when we set all bits + * within the mask to one (i.e. | in the + * mask), all bits are one. + */ + if (($2 > mask) && (($2 | mask) != -1ULL)) + ERROR(&@2, "Value out of range for" + " %d-bit array element", $1.bits); + } + + $$.data = data_append_integer($1.data, $2, $1.bits); + } + | arrayprefix DT_REF + { + uint64_t val = ~0ULL >> (64 - $1.bits); + + if ($1.bits == 32) + $1.data = data_add_marker($1.data, + REF_PHANDLE, + $2); + else + ERROR(&@2, "References are only allowed in " + "arrays with 32-bit elements."); + + $$.data = data_append_integer($1.data, val, $1.bits); + } + | arrayprefix DT_LABEL + { + $$.data = data_add_marker($1.data, LABEL, $2); + } + ; + +integer_prim: + DT_LITERAL + | DT_CHAR_LITERAL + | '(' integer_expr ')' + { + $$ = $2; + } + ; + +integer_expr: + integer_trinary + ; + +integer_trinary: + integer_or + | integer_or '?' integer_expr ':' integer_trinary { $$ = $1 ? $3 : $5; } + ; + +integer_or: + integer_and + | integer_or DT_OR integer_and { $$ = $1 || $3; } + ; + +integer_and: + integer_bitor + | integer_and DT_AND integer_bitor { $$ = $1 && $3; } + ; + +integer_bitor: + integer_bitxor + | integer_bitor '|' integer_bitxor { $$ = $1 | $3; } + ; + +integer_bitxor: + integer_bitand + | integer_bitxor '^' integer_bitand { $$ = $1 ^ $3; } + ; + +integer_bitand: + integer_eq + | integer_bitand '&' integer_eq { $$ = $1 & $3; } + ; + +integer_eq: + integer_rela + | integer_eq DT_EQ integer_rela { $$ = $1 == $3; } + | integer_eq DT_NE integer_rela { $$ = $1 != $3; } + ; + +integer_rela: + integer_shift + | integer_rela '<' integer_shift { $$ = $1 < $3; } + | integer_rela '>' integer_shift { $$ = $1 > $3; } + | integer_rela DT_LE integer_shift { $$ = $1 <= $3; } + | integer_rela DT_GE integer_shift { $$ = $1 >= $3; } + ; + +integer_shift: + integer_shift DT_LSHIFT integer_add { $$ = $1 << $3; } + | integer_shift DT_RSHIFT integer_add { $$ = $1 >> $3; } + | integer_add + ; + +integer_add: + integer_add '+' integer_mul { $$ = $1 + $3; } + | integer_add '-' integer_mul { $$ = $1 - $3; } + | integer_mul + ; + +integer_mul: + integer_mul '*' integer_unary { $$ = $1 * $3; } + | integer_mul '/' integer_unary + { + if ($3 != 0) { + $$ = $1 / $3; + } else { + ERROR(&@$, "Division by zero"); + $$ = 0; + } + } + | integer_mul '%' integer_unary + { + if ($3 != 0) { + $$ = $1 % $3; + } else { + ERROR(&@$, "Division by zero"); + $$ = 0; + } + } + | integer_unary + ; + +integer_unary: + integer_prim + | '-' integer_unary { $$ = -$2; } + | '~' integer_unary { $$ = ~$2; } + | '!' integer_unary { $$ = !$2; } + ; + +bytestring: + /* empty */ + { + $$ = empty_data; + } + | bytestring DT_BYTE + { + $$ = data_append_byte($1, $2); + } + | bytestring DT_LABEL + { + $$ = data_add_marker($1, LABEL, $2); + } + ; + +subnodes: + /* empty */ + { + $$ = NULL; + } + | subnode subnodes + { + $$ = chain_node($1, $2); + } + | subnode propdef + { + ERROR(&@2, "Properties must precede subnodes"); + YYERROR; + } + ; + +subnode: + DT_PROPNODENAME nodedef + { + $$ = name_node($2, $1); + } + | DT_DEL_NODE DT_PROPNODENAME ';' + { + $$ = name_node(build_node_delete(), $2); + } + | DT_LABEL subnode + { + add_label(&$2->labels, $1); + $$ = $2; + } + ; + +%% + +void yyerror(char const *s) +{ + ERROR(&yylloc, "%s", s); +} diff --git a/scripts/dtc/dtc.c b/scripts/dtc/dtc.c new file mode 100644 index 0000000000..5ed873c72a --- /dev/null +++ b/scripts/dtc/dtc.c @@ -0,0 +1,365 @@ +/* + * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005. + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#include <sys/stat.h> + +#include "dtc.h" +#include "srcpos.h" + +/* + * Command line options + */ +int quiet; /* Level of quietness */ +int reservenum; /* Number of memory reservation slots */ +int minsize; /* Minimum blob size */ +int padsize; /* Additional padding to blob */ +int alignsize; /* Additional padding to blob accroding to the alignsize */ +int phandle_format = PHANDLE_EPAPR; /* Use linux,phandle or phandle properties */ +int generate_symbols; /* enable symbols & fixup support */ +int generate_fixups; /* suppress generation of fixups on symbol support */ +int auto_label_aliases; /* auto generate labels -> aliases */ + +static int is_power_of_2(int x) +{ + return (x > 0) && ((x & (x - 1)) == 0); +} + +static void fill_fullpaths(struct node *tree, const char *prefix) +{ + struct node *child; + const char *unit; + + tree->fullpath = join_path(prefix, tree->name); + + unit = strchr(tree->name, '@'); + if (unit) + tree->basenamelen = unit - tree->name; + else + tree->basenamelen = strlen(tree->name); + + for_each_child(tree, child) + fill_fullpaths(child, tree->fullpath); +} + +/* Usage related data. */ +#define FDT_VERSION(version) _FDT_VERSION(version) +#define _FDT_VERSION(version) #version +static const char usage_synopsis[] = "dtc [options] <input file>"; +static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@Ahv"; +static struct option const usage_long_opts[] = { + {"quiet", no_argument, NULL, 'q'}, + {"in-format", a_argument, NULL, 'I'}, + {"out", a_argument, NULL, 'o'}, + {"out-format", a_argument, NULL, 'O'}, + {"out-version", a_argument, NULL, 'V'}, + {"out-dependency", a_argument, NULL, 'd'}, + {"reserve", a_argument, NULL, 'R'}, + {"space", a_argument, NULL, 'S'}, + {"pad", a_argument, NULL, 'p'}, + {"align", a_argument, NULL, 'a'}, + {"boot-cpu", a_argument, NULL, 'b'}, + {"force", no_argument, NULL, 'f'}, + {"include", a_argument, NULL, 'i'}, + {"sort", no_argument, NULL, 's'}, + {"phandle", a_argument, NULL, 'H'}, + {"warning", a_argument, NULL, 'W'}, + {"error", a_argument, NULL, 'E'}, + {"symbols", no_argument, NULL, '@'}, + {"auto-alias", no_argument, NULL, 'A'}, + {"help", no_argument, NULL, 'h'}, + {"version", no_argument, NULL, 'v'}, + {NULL, no_argument, NULL, 0x0}, +}; +static const char * const usage_opts_help[] = { + "\n\tQuiet: -q suppress warnings, -qq errors, -qqq all", + "\n\tInput formats are:\n" + "\t\tdts - device tree source text\n" + "\t\tdtb - device tree blob\n" + "\t\tfs - /proc/device-tree style directory", + "\n\tOutput file", + "\n\tOutput formats are:\n" + "\t\tdts - device tree source text\n" + "\t\tdtb - device tree blob\n" + "\t\tasm - assembler source", + "\n\tBlob version to produce, defaults to "FDT_VERSION(DEFAULT_FDT_VERSION)" (for dtb and asm output)", + "\n\tOutput dependency file", + "\n\tMake space for <number> reserve map entries (for dtb and asm output)", + "\n\tMake the blob at least <bytes> long (extra space)", + "\n\tAdd padding to the blob of <bytes> long (extra space)", + "\n\tMake the blob align to the <bytes> (extra space)", + "\n\tSet the physical boot cpu", + "\n\tTry to produce output even if the input tree has errors", + "\n\tAdd a path to search for include files", + "\n\tSort nodes and properties before outputting (useful for comparing trees)", + "\n\tValid phandle formats are:\n" + "\t\tlegacy - \"linux,phandle\" properties only\n" + "\t\tepapr - \"phandle\" properties only\n" + "\t\tboth - Both \"linux,phandle\" and \"phandle\" properties", + "\n\tEnable/disable warnings (prefix with \"no-\")", + "\n\tEnable/disable errors (prefix with \"no-\")", + "\n\tEnable generation of symbols", + "\n\tEnable auto-alias of labels", + "\n\tPrint this help and exit", + "\n\tPrint version and exit", + NULL, +}; + +static const char *guess_type_by_name(const char *fname, const char *fallback) +{ + const char *s; + + s = strrchr(fname, '.'); + if (s == NULL) + return fallback; + if (!strcasecmp(s, ".dts")) + return "dts"; + if (!strcasecmp(s, ".dtb")) + return "dtb"; + return fallback; +} + +static const char *guess_input_format(const char *fname, const char *fallback) +{ + struct stat statbuf; + fdt32_t magic; + FILE *f; + + if (stat(fname, &statbuf) != 0) + return fallback; + + if (S_ISDIR(statbuf.st_mode)) + return "fs"; + + if (!S_ISREG(statbuf.st_mode)) + return fallback; + + f = fopen(fname, "r"); + if (f == NULL) + return fallback; + if (fread(&magic, 4, 1, f) != 1) { + fclose(f); + return fallback; + } + fclose(f); + + if (fdt32_to_cpu(magic) == FDT_MAGIC) + return "dtb"; + + return guess_type_by_name(fname, fallback); +} + +int main(int argc, char *argv[]) +{ + struct dt_info *dti; + const char *inform = NULL; + const char *outform = NULL; + const char *outname = "-"; + const char *depname = NULL; + bool force = false, sort = false; + const char *arg; + int opt; + FILE *outf = NULL; + int outversion = DEFAULT_FDT_VERSION; + long long cmdline_boot_cpuid = -1; + + quiet = 0; + reservenum = 0; + minsize = 0; + padsize = 0; + alignsize = 0; + + while ((opt = util_getopt_long()) != EOF) { + switch (opt) { + case 'I': + inform = optarg; + break; + case 'O': + outform = optarg; + break; + case 'o': + outname = optarg; + break; + case 'V': + outversion = strtol(optarg, NULL, 0); + break; + case 'd': + depname = optarg; + break; + case 'R': + reservenum = strtol(optarg, NULL, 0); + break; + case 'S': + minsize = strtol(optarg, NULL, 0); + break; + case 'p': + padsize = strtol(optarg, NULL, 0); + break; + case 'a': + alignsize = strtol(optarg, NULL, 0); + if (!is_power_of_2(alignsize)) + die("Invalid argument \"%d\" to -a option\n", + alignsize); + break; + case 'f': + force = true; + break; + case 'q': + quiet++; + break; + case 'b': + cmdline_boot_cpuid = strtoll(optarg, NULL, 0); + break; + case 'i': + srcfile_add_search_path(optarg); + break; + case 'v': + util_version(); + case 'H': + if (streq(optarg, "legacy")) + phandle_format = PHANDLE_LEGACY; + else if (streq(optarg, "epapr")) + phandle_format = PHANDLE_EPAPR; + else if (streq(optarg, "both")) + phandle_format = PHANDLE_BOTH; + else + die("Invalid argument \"%s\" to -H option\n", + optarg); + break; + + case 's': + sort = true; + break; + + case 'W': + parse_checks_option(true, false, optarg); + break; + + case 'E': + parse_checks_option(false, true, optarg); + break; + + case '@': + generate_symbols = 1; + break; + case 'A': + auto_label_aliases = 1; + break; + + case 'h': + usage(NULL); + default: + usage("unknown option"); + } + } + + if (argc > (optind+1)) + usage("missing files"); + else if (argc < (optind+1)) + arg = "-"; + else + arg = argv[optind]; + + /* minsize and padsize are mutually exclusive */ + if (minsize && padsize) + die("Can't set both -p and -S\n"); + + if (depname) { + depfile = fopen(depname, "w"); + if (!depfile) + die("Couldn't open dependency file %s: %s\n", depname, + strerror(errno)); + fprintf(depfile, "%s:", outname); + } + + if (inform == NULL) + inform = guess_input_format(arg, "dts"); + if (outform == NULL) { + outform = guess_type_by_name(outname, NULL); + if (outform == NULL) { + if (streq(inform, "dts")) + outform = "dtb"; + else + outform = "dts"; + } + } + if (streq(inform, "dts")) + dti = dt_from_source(arg); + else if (streq(inform, "fs")) + dti = dt_from_fs(arg); + else if(streq(inform, "dtb")) + dti = dt_from_blob(arg); + else + die("Unknown input format \"%s\"\n", inform); + + dti->outname = outname; + + if (depfile) { + fputc('\n', depfile); + fclose(depfile); + } + + if (cmdline_boot_cpuid != -1) + dti->boot_cpuid_phys = cmdline_boot_cpuid; + + fill_fullpaths(dti->dt, ""); + process_checks(force, dti); + + /* on a plugin, generate by default */ + if (dti->dtsflags & DTSF_PLUGIN) { + generate_fixups = 1; + } + + if (auto_label_aliases) + generate_label_tree(dti, "aliases", false); + + if (generate_symbols) + generate_label_tree(dti, "__symbols__", true); + + if (generate_fixups) { + generate_fixups_tree(dti, "__fixups__"); + generate_local_fixups_tree(dti, "__local_fixups__"); + } + + if (sort) + sort_tree(dti); + + if (streq(outname, "-")) { + outf = stdout; + } else { + outf = fopen(outname, "wb"); + if (! outf) + die("Couldn't open output file %s: %s\n", + outname, strerror(errno)); + } + + if (streq(outform, "dts")) { + dt_to_source(outf, dti); + } else if (streq(outform, "dtb")) { + dt_to_blob(outf, dti, outversion); + } else if (streq(outform, "asm")) { + dt_to_asm(outf, dti, outversion); + } else if (streq(outform, "null")) { + /* do nothing */ + } else { + die("Unknown output format \"%s\"\n", outform); + } + + exit(0); +} diff --git a/scripts/dtc/dtc.h b/scripts/dtc/dtc.h new file mode 100644 index 0000000000..409db76c94 --- /dev/null +++ b/scripts/dtc/dtc.h @@ -0,0 +1,290 @@ +#ifndef _DTC_H +#define _DTC_H + +/* + * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005. + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <stdint.h> +#include <stdbool.h> +#include <stdarg.h> +#include <assert.h> +#include <ctype.h> +#include <errno.h> +#include <unistd.h> +#include <inttypes.h> + +#include <libfdt_env.h> +#include <fdt.h> + +#include "util.h" + +#ifdef DEBUG +#define debug(...) printf(__VA_ARGS__) +#else +#define debug(...) +#endif + +#define DEFAULT_FDT_VERSION 17 + +/* + * Command line options + */ +extern int quiet; /* Level of quietness */ +extern int reservenum; /* Number of memory reservation slots */ +extern int minsize; /* Minimum blob size */ +extern int padsize; /* Additional padding to blob */ +extern int alignsize; /* Additional padding to blob accroding to the alignsize */ +extern int phandle_format; /* Use linux,phandle or phandle properties */ +extern int generate_symbols; /* generate symbols for nodes with labels */ +extern int generate_fixups; /* generate fixups */ +extern int auto_label_aliases; /* auto generate labels -> aliases */ + +#define PHANDLE_LEGACY 0x1 +#define PHANDLE_EPAPR 0x2 +#define PHANDLE_BOTH 0x3 + +typedef uint32_t cell_t; + + +#define streq(a, b) (strcmp((a), (b)) == 0) +#define strneq(a, b, n) (strncmp((a), (b), (n)) == 0) + +#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) + +/* Data blobs */ +enum markertype { + REF_PHANDLE, + REF_PATH, + LABEL, +}; + +struct marker { + enum markertype type; + int offset; + char *ref; + struct marker *next; +}; + +struct data { + int len; + char *val; + struct marker *markers; +}; + + +#define empty_data ((struct data){ 0 /* all .members = 0 or NULL */ }) + +#define for_each_marker(m) \ + for (; (m); (m) = (m)->next) +#define for_each_marker_of_type(m, t) \ + for_each_marker(m) \ + if ((m)->type == (t)) + +void data_free(struct data d); + +struct data data_grow_for(struct data d, int xlen); + +struct data data_copy_mem(const char *mem, int len); +struct data data_copy_escape_string(const char *s, int len); +struct data data_copy_file(FILE *f, size_t len); + +struct data data_append_data(struct data d, const void *p, int len); +struct data data_insert_at_marker(struct data d, struct marker *m, + const void *p, int len); +struct data data_merge(struct data d1, struct data d2); +struct data data_append_cell(struct data d, cell_t word); +struct data data_append_integer(struct data d, uint64_t word, int bits); +struct data data_append_re(struct data d, uint64_t address, uint64_t size); +struct data data_append_addr(struct data d, uint64_t addr); +struct data data_append_byte(struct data d, uint8_t byte); +struct data data_append_zeroes(struct data d, int len); +struct data data_append_align(struct data d, int align); + +struct data data_add_marker(struct data d, enum markertype type, char *ref); + +bool data_is_one_string(struct data d); + +/* DT constraints */ + +#define MAX_PROPNAME_LEN 31 +#define MAX_NODENAME_LEN 31 + +/* Live trees */ +struct label { + bool deleted; + char *label; + struct label *next; +}; + +struct bus_type { + const char *name; +}; + +struct property { + bool deleted; + char *name; + struct data val; + + struct property *next; + + struct label *labels; +}; + +struct node { + bool deleted; + char *name; + struct property *proplist; + struct node *children; + + struct node *parent; + struct node *next_sibling; + + char *fullpath; + int basenamelen; + + cell_t phandle; + int addr_cells, size_cells; + + struct label *labels; + const struct bus_type *bus; +}; + +#define for_each_label_withdel(l0, l) \ + for ((l) = (l0); (l); (l) = (l)->next) + +#define for_each_label(l0, l) \ + for_each_label_withdel(l0, l) \ + if (!(l)->deleted) + +#define for_each_property_withdel(n, p) \ + for ((p) = (n)->proplist; (p); (p) = (p)->next) + +#define for_each_property(n, p) \ + for_each_property_withdel(n, p) \ + if (!(p)->deleted) + +#define for_each_child_withdel(n, c) \ + for ((c) = (n)->children; (c); (c) = (c)->next_sibling) + +#define for_each_child(n, c) \ + for_each_child_withdel(n, c) \ + if (!(c)->deleted) + +void add_label(struct label **labels, char *label); +void delete_labels(struct label **labels); + +struct property *build_property(char *name, struct data val); +struct property *build_property_delete(char *name); +struct property *chain_property(struct property *first, struct property *list); +struct property *reverse_properties(struct property *first); + +struct node *build_node(struct property *proplist, struct node *children); +struct node *build_node_delete(void); +struct node *name_node(struct node *node, char *name); +struct node *chain_node(struct node *first, struct node *list); +struct node *merge_nodes(struct node *old_node, struct node *new_node); + +void add_property(struct node *node, struct property *prop); +void delete_property_by_name(struct node *node, char *name); +void delete_property(struct property *prop); +void add_child(struct node *parent, struct node *child); +void delete_node_by_name(struct node *parent, char *name); +void delete_node(struct node *node); +void append_to_property(struct node *node, + char *name, const void *data, int len); + +const char *get_unitname(struct node *node); +struct property *get_property(struct node *node, const char *propname); +cell_t propval_cell(struct property *prop); +struct property *get_property_by_label(struct node *tree, const char *label, + struct node **node); +struct marker *get_marker_label(struct node *tree, const char *label, + struct node **node, struct property **prop); +struct node *get_subnode(struct node *node, const char *nodename); +struct node *get_node_by_path(struct node *tree, const char *path); +struct node *get_node_by_label(struct node *tree, const char *label); +struct node *get_node_by_phandle(struct node *tree, cell_t phandle); +struct node *get_node_by_ref(struct node *tree, const char *ref); +cell_t get_node_phandle(struct node *root, struct node *node); + +uint32_t guess_boot_cpuid(struct node *tree); + +/* Boot info (tree plus memreserve information */ + +struct reserve_info { + uint64_t address, size; + + struct reserve_info *next; + + struct label *labels; +}; + +struct reserve_info *build_reserve_entry(uint64_t start, uint64_t len); +struct reserve_info *chain_reserve_entry(struct reserve_info *first, + struct reserve_info *list); +struct reserve_info *add_reserve_entry(struct reserve_info *list, + struct reserve_info *new); + + +struct dt_info { + unsigned int dtsflags; + struct reserve_info *reservelist; + uint32_t boot_cpuid_phys; + struct node *dt; /* the device tree */ + const char *outname; /* filename being written to, "-" for stdout */ +}; + +/* DTS version flags definitions */ +#define DTSF_V1 0x0001 /* /dts-v1/ */ +#define DTSF_PLUGIN 0x0002 /* /plugin/ */ + +struct dt_info *build_dt_info(unsigned int dtsflags, + struct reserve_info *reservelist, + struct node *tree, uint32_t boot_cpuid_phys); +void sort_tree(struct dt_info *dti); +void generate_label_tree(struct dt_info *dti, char *name, bool allocph); +void generate_fixups_tree(struct dt_info *dti, char *name); +void generate_local_fixups_tree(struct dt_info *dti, char *name); + +/* Checks */ + +void parse_checks_option(bool warn, bool error, const char *arg); +void process_checks(bool force, struct dt_info *dti); + +/* Flattened trees */ + +void dt_to_blob(FILE *f, struct dt_info *dti, int version); +void dt_to_asm(FILE *f, struct dt_info *dti, int version); + +struct dt_info *dt_from_blob(const char *fname); + +/* Tree source */ + +void dt_to_source(FILE *f, struct dt_info *dti); +struct dt_info *dt_from_source(const char *f); + +/* FS trees */ + +struct dt_info *dt_from_fs(const char *dirname); + +#endif /* _DTC_H */ diff --git a/scripts/dtc/flattree.c b/scripts/dtc/flattree.c new file mode 100644 index 0000000000..fcf71541d8 --- /dev/null +++ b/scripts/dtc/flattree.c @@ -0,0 +1,940 @@ +/* + * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005. + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#include "dtc.h" +#include "srcpos.h" + +#define FTF_FULLPATH 0x1 +#define FTF_VARALIGN 0x2 +#define FTF_NAMEPROPS 0x4 +#define FTF_BOOTCPUID 0x8 +#define FTF_STRTABSIZE 0x10 +#define FTF_STRUCTSIZE 0x20 +#define FTF_NOPS 0x40 + +static struct version_info { + int version; + int last_comp_version; + int hdr_size; + int flags; +} version_table[] = { + {1, 1, FDT_V1_SIZE, + FTF_FULLPATH|FTF_VARALIGN|FTF_NAMEPROPS}, + {2, 1, FDT_V2_SIZE, + FTF_FULLPATH|FTF_VARALIGN|FTF_NAMEPROPS|FTF_BOOTCPUID}, + {3, 1, FDT_V3_SIZE, + FTF_FULLPATH|FTF_VARALIGN|FTF_NAMEPROPS|FTF_BOOTCPUID|FTF_STRTABSIZE}, + {16, 16, FDT_V3_SIZE, + FTF_BOOTCPUID|FTF_STRTABSIZE|FTF_NOPS}, + {17, 16, FDT_V17_SIZE, + FTF_BOOTCPUID|FTF_STRTABSIZE|FTF_STRUCTSIZE|FTF_NOPS}, +}; + +struct emitter { + void (*cell)(void *, cell_t); + void (*string)(void *, const char *, int); + void (*align)(void *, int); + void (*data)(void *, struct data); + void (*beginnode)(void *, struct label *labels); + void (*endnode)(void *, struct label *labels); + void (*property)(void *, struct label *labels); +}; + +static void bin_emit_cell(void *e, cell_t val) +{ + struct data *dtbuf = e; + + *dtbuf = data_append_cell(*dtbuf, val); +} + +static void bin_emit_string(void *e, const char *str, int len) +{ + struct data *dtbuf = e; + + if (len == 0) + len = strlen(str); + + *dtbuf = data_append_data(*dtbuf, str, len); + *dtbuf = data_append_byte(*dtbuf, '\0'); +} + +static void bin_emit_align(void *e, int a) +{ + struct data *dtbuf = e; + + *dtbuf = data_append_align(*dtbuf, a); +} + +static void bin_emit_data(void *e, struct data d) +{ + struct data *dtbuf = e; + + *dtbuf = data_append_data(*dtbuf, d.val, d.len); +} + +static void bin_emit_beginnode(void *e, struct label *labels) +{ + bin_emit_cell(e, FDT_BEGIN_NODE); +} + +static void bin_emit_endnode(void *e, struct label *labels) +{ + bin_emit_cell(e, FDT_END_NODE); +} + +static void bin_emit_property(void *e, struct label *labels) +{ + bin_emit_cell(e, FDT_PROP); +} + +static struct emitter bin_emitter = { + .cell = bin_emit_cell, + .string = bin_emit_string, + .align = bin_emit_align, + .data = bin_emit_data, + .beginnode = bin_emit_beginnode, + .endnode = bin_emit_endnode, + .property = bin_emit_property, +}; + +static void emit_label(FILE *f, const char *prefix, const char *label) +{ + fprintf(f, "\t.globl\t%s_%s\n", prefix, label); + fprintf(f, "%s_%s:\n", prefix, label); + fprintf(f, "_%s_%s:\n", prefix, label); +} + +static void emit_offset_label(FILE *f, const char *label, int offset) +{ + fprintf(f, "\t.globl\t%s\n", label); + fprintf(f, "%s\t= . + %d\n", label, offset); +} + +#define ASM_EMIT_BELONG(f, fmt, ...) \ + { \ + fprintf((f), "\t.byte\t((" fmt ") >> 24) & 0xff\n", __VA_ARGS__); \ + fprintf((f), "\t.byte\t((" fmt ") >> 16) & 0xff\n", __VA_ARGS__); \ + fprintf((f), "\t.byte\t((" fmt ") >> 8) & 0xff\n", __VA_ARGS__); \ + fprintf((f), "\t.byte\t(" fmt ") & 0xff\n", __VA_ARGS__); \ + } + +static void asm_emit_cell(void *e, cell_t val) +{ + FILE *f = e; + + fprintf(f, "\t.byte 0x%02x; .byte 0x%02x; .byte 0x%02x; .byte 0x%02x\n", + (val >> 24) & 0xff, (val >> 16) & 0xff, + (val >> 8) & 0xff, val & 0xff); +} + +static void asm_emit_string(void *e, const char *str, int len) +{ + FILE *f = e; + + if (len != 0) + fprintf(f, "\t.string\t\"%.*s\"\n", len, str); + else + fprintf(f, "\t.string\t\"%s\"\n", str); +} + +static void asm_emit_align(void *e, int a) +{ + FILE *f = e; + + fprintf(f, "\t.balign\t%d, 0\n", a); +} + +static void asm_emit_data(void *e, struct data d) +{ + FILE *f = e; + int off = 0; + struct marker *m = d.markers; + + for_each_marker_of_type(m, LABEL) + emit_offset_label(f, m->ref, m->offset); + + while ((d.len - off) >= sizeof(uint32_t)) { + asm_emit_cell(e, fdt32_to_cpu(*((fdt32_t *)(d.val+off)))); + off += sizeof(uint32_t); + } + + while ((d.len - off) >= 1) { + fprintf(f, "\t.byte\t0x%hhx\n", d.val[off]); + off += 1; + } + + assert(off == d.len); +} + +static void asm_emit_beginnode(void *e, struct label *labels) +{ + FILE *f = e; + struct label *l; + + for_each_label(labels, l) { + fprintf(f, "\t.globl\t%s\n", l->label); + fprintf(f, "%s:\n", l->label); + } + fprintf(f, "\t/* FDT_BEGIN_NODE */\n"); + asm_emit_cell(e, FDT_BEGIN_NODE); +} + +static void asm_emit_endnode(void *e, struct label *labels) +{ + FILE *f = e; + struct label *l; + + fprintf(f, "\t/* FDT_END_NODE */\n"); + asm_emit_cell(e, FDT_END_NODE); + for_each_label(labels, l) { + fprintf(f, "\t.globl\t%s_end\n", l->label); + fprintf(f, "%s_end:\n", l->label); + } +} + +static void asm_emit_property(void *e, struct label *labels) +{ + FILE *f = e; + struct label *l; + + for_each_label(labels, l) { + fprintf(f, "\t.globl\t%s\n", l->label); + fprintf(f, "%s:\n", l->label); + } + fprintf(f, "\t/* FDT_PROP */\n"); + asm_emit_cell(e, FDT_PROP); +} + +static struct emitter asm_emitter = { + .cell = asm_emit_cell, + .string = asm_emit_string, + .align = asm_emit_align, + .data = asm_emit_data, + .beginnode = asm_emit_beginnode, + .endnode = asm_emit_endnode, + .property = asm_emit_property, +}; + +static int stringtable_insert(struct data *d, const char *str) +{ + int i; + + /* FIXME: do this more efficiently? */ + + for (i = 0; i < d->len; i++) { + if (streq(str, d->val + i)) + return i; + } + + *d = data_append_data(*d, str, strlen(str)+1); + return i; +} + +static void flatten_tree(struct node *tree, struct emitter *emit, + void *etarget, struct data *strbuf, + struct version_info *vi) +{ + struct property *prop; + struct node *child; + bool seen_name_prop = false; + + if (tree->deleted) + return; + + emit->beginnode(etarget, tree->labels); + + if (vi->flags & FTF_FULLPATH) + emit->string(etarget, tree->fullpath, 0); + else + emit->string(etarget, tree->name, 0); + + emit->align(etarget, sizeof(cell_t)); + + for_each_property(tree, prop) { + int nameoff; + + if (streq(prop->name, "name")) + seen_name_prop = true; + + nameoff = stringtable_insert(strbuf, prop->name); + + emit->property(etarget, prop->labels); + emit->cell(etarget, prop->val.len); + emit->cell(etarget, nameoff); + + if ((vi->flags & FTF_VARALIGN) && (prop->val.len >= 8)) + emit->align(etarget, 8); + + emit->data(etarget, prop->val); + emit->align(etarget, sizeof(cell_t)); + } + + if ((vi->flags & FTF_NAMEPROPS) && !seen_name_prop) { + emit->property(etarget, NULL); + emit->cell(etarget, tree->basenamelen+1); + emit->cell(etarget, stringtable_insert(strbuf, "name")); + + if ((vi->flags & FTF_VARALIGN) && ((tree->basenamelen+1) >= 8)) + emit->align(etarget, 8); + + emit->string(etarget, tree->name, tree->basenamelen); + emit->align(etarget, sizeof(cell_t)); + } + + for_each_child(tree, child) { + flatten_tree(child, emit, etarget, strbuf, vi); + } + + emit->endnode(etarget, tree->labels); +} + +static struct data flatten_reserve_list(struct reserve_info *reservelist, + struct version_info *vi) +{ + struct reserve_info *re; + struct data d = empty_data; + int j; + + for (re = reservelist; re; re = re->next) { + d = data_append_re(d, re->address, re->size); + } + /* + * Add additional reserved slots if the user asked for them. + */ + for (j = 0; j < reservenum; j++) { + d = data_append_re(d, 0, 0); + } + + return d; +} + +static void make_fdt_header(struct fdt_header *fdt, + struct version_info *vi, + int reservesize, int dtsize, int strsize, + int boot_cpuid_phys) +{ + int reserve_off; + + reservesize += sizeof(struct fdt_reserve_entry); + + memset(fdt, 0xff, sizeof(*fdt)); + + fdt->magic = cpu_to_fdt32(FDT_MAGIC); + fdt->version = cpu_to_fdt32(vi->version); + fdt->last_comp_version = cpu_to_fdt32(vi->last_comp_version); + + /* Reserve map should be doubleword aligned */ + reserve_off = ALIGN(vi->hdr_size, 8); + + fdt->off_mem_rsvmap = cpu_to_fdt32(reserve_off); + fdt->off_dt_struct = cpu_to_fdt32(reserve_off + reservesize); + fdt->off_dt_strings = cpu_to_fdt32(reserve_off + reservesize + + dtsize); + fdt->totalsize = cpu_to_fdt32(reserve_off + reservesize + dtsize + strsize); + + if (vi->flags & FTF_BOOTCPUID) + fdt->boot_cpuid_phys = cpu_to_fdt32(boot_cpuid_phys); + if (vi->flags & FTF_STRTABSIZE) + fdt->size_dt_strings = cpu_to_fdt32(strsize); + if (vi->flags & FTF_STRUCTSIZE) + fdt->size_dt_struct = cpu_to_fdt32(dtsize); +} + +void dt_to_blob(FILE *f, struct dt_info *dti, int version) +{ + struct version_info *vi = NULL; + int i; + struct data blob = empty_data; + struct data reservebuf = empty_data; + struct data dtbuf = empty_data; + struct data strbuf = empty_data; + struct fdt_header fdt; + int padlen = 0; + + for (i = 0; i < ARRAY_SIZE(version_table); i++) { + if (version_table[i].version == version) + vi = &version_table[i]; + } + if (!vi) + die("Unknown device tree blob version %d\n", version); + + flatten_tree(dti->dt, &bin_emitter, &dtbuf, &strbuf, vi); + bin_emit_cell(&dtbuf, FDT_END); + + reservebuf = flatten_reserve_list(dti->reservelist, vi); + + /* Make header */ + make_fdt_header(&fdt, vi, reservebuf.len, dtbuf.len, strbuf.len, + dti->boot_cpuid_phys); + + /* + * If the user asked for more space than is used, adjust the totalsize. + */ + if (minsize > 0) { + padlen = minsize - fdt32_to_cpu(fdt.totalsize); + if (padlen < 0) { + padlen = 0; + if (quiet < 1) + fprintf(stderr, + "Warning: blob size %d >= minimum size %d\n", + fdt32_to_cpu(fdt.totalsize), minsize); + } + } + + if (padsize > 0) + padlen = padsize; + + if (alignsize > 0) + padlen = ALIGN(fdt32_to_cpu(fdt.totalsize) + padlen, alignsize) + - fdt32_to_cpu(fdt.totalsize); + + if (padlen > 0) { + int tsize = fdt32_to_cpu(fdt.totalsize); + tsize += padlen; + fdt.totalsize = cpu_to_fdt32(tsize); + } + + /* + * Assemble the blob: start with the header, add with alignment + * the reserve buffer, add the reserve map terminating zeroes, + * the device tree itself, and finally the strings. + */ + blob = data_append_data(blob, &fdt, vi->hdr_size); + blob = data_append_align(blob, 8); + blob = data_merge(blob, reservebuf); + blob = data_append_zeroes(blob, sizeof(struct fdt_reserve_entry)); + blob = data_merge(blob, dtbuf); + blob = data_merge(blob, strbuf); + + /* + * If the user asked for more space than is used, pad out the blob. + */ + if (padlen > 0) + blob = data_append_zeroes(blob, padlen); + + if (fwrite(blob.val, blob.len, 1, f) != 1) { + if (ferror(f)) + die("Error writing device tree blob: %s\n", + strerror(errno)); + else + die("Short write on device tree blob\n"); + } + + /* + * data_merge() frees the right-hand element so only the blob + * remains to be freed. + */ + data_free(blob); +} + +static void dump_stringtable_asm(FILE *f, struct data strbuf) +{ + const char *p; + int len; + + p = strbuf.val; + + while (p < (strbuf.val + strbuf.len)) { + len = strlen(p); + fprintf(f, "\t.string \"%s\"\n", p); + p += len+1; + } +} + +void dt_to_asm(FILE *f, struct dt_info *dti, int version) +{ + struct version_info *vi = NULL; + int i; + struct data strbuf = empty_data; + struct reserve_info *re; + const char *symprefix = "dt"; + + for (i = 0; i < ARRAY_SIZE(version_table); i++) { + if (version_table[i].version == version) + vi = &version_table[i]; + } + if (!vi) + die("Unknown device tree blob version %d\n", version); + + fprintf(f, "/* autogenerated by dtc, do not edit */\n\n"); + + emit_label(f, symprefix, "blob_start"); + emit_label(f, symprefix, "header"); + fprintf(f, "\t/* magic */\n"); + asm_emit_cell(f, FDT_MAGIC); + fprintf(f, "\t/* totalsize */\n"); + ASM_EMIT_BELONG(f, "_%s_blob_abs_end - _%s_blob_start", + symprefix, symprefix); + fprintf(f, "\t/* off_dt_struct */\n"); + ASM_EMIT_BELONG(f, "_%s_struct_start - _%s_blob_start", + symprefix, symprefix); + fprintf(f, "\t/* off_dt_strings */\n"); + ASM_EMIT_BELONG(f, "_%s_strings_start - _%s_blob_start", + symprefix, symprefix); + fprintf(f, "\t/* off_mem_rsvmap */\n"); + ASM_EMIT_BELONG(f, "_%s_reserve_map - _%s_blob_start", + symprefix, symprefix); + fprintf(f, "\t/* version */\n"); + asm_emit_cell(f, vi->version); + fprintf(f, "\t/* last_comp_version */\n"); + asm_emit_cell(f, vi->last_comp_version); + + if (vi->flags & FTF_BOOTCPUID) { + fprintf(f, "\t/* boot_cpuid_phys */\n"); + asm_emit_cell(f, dti->boot_cpuid_phys); + } + + if (vi->flags & FTF_STRTABSIZE) { + fprintf(f, "\t/* size_dt_strings */\n"); + ASM_EMIT_BELONG(f, "_%s_strings_end - _%s_strings_start", + symprefix, symprefix); + } + + if (vi->flags & FTF_STRUCTSIZE) { + fprintf(f, "\t/* size_dt_struct */\n"); + ASM_EMIT_BELONG(f, "_%s_struct_end - _%s_struct_start", + symprefix, symprefix); + } + + /* + * Reserve map entries. + * Align the reserve map to a doubleword boundary. + * Each entry is an (address, size) pair of u64 values. + * Always supply a zero-sized temination entry. + */ + asm_emit_align(f, 8); + emit_label(f, symprefix, "reserve_map"); + + fprintf(f, "/* Memory reserve map from source file */\n"); + + /* + * Use .long on high and low halfs of u64s to avoid .quad + * as it appears .quad isn't available in some assemblers. + */ + for (re = dti->reservelist; re; re = re->next) { + struct label *l; + + for_each_label(re->labels, l) { + fprintf(f, "\t.globl\t%s\n", l->label); + fprintf(f, "%s:\n", l->label); + } + ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->address >> 32)); + ASM_EMIT_BELONG(f, "0x%08x", + (unsigned int)(re->address & 0xffffffff)); + ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->size >> 32)); + ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->size & 0xffffffff)); + } + for (i = 0; i < reservenum; i++) { + fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n"); + } + + fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n"); + + emit_label(f, symprefix, "struct_start"); + flatten_tree(dti->dt, &asm_emitter, f, &strbuf, vi); + + fprintf(f, "\t/* FDT_END */\n"); + asm_emit_cell(f, FDT_END); + emit_label(f, symprefix, "struct_end"); + + emit_label(f, symprefix, "strings_start"); + dump_stringtable_asm(f, strbuf); + emit_label(f, symprefix, "strings_end"); + + emit_label(f, symprefix, "blob_end"); + + /* + * If the user asked for more space than is used, pad it out. + */ + if (minsize > 0) { + fprintf(f, "\t.space\t%d - (_%s_blob_end - _%s_blob_start), 0\n", + minsize, symprefix, symprefix); + } + if (padsize > 0) { + fprintf(f, "\t.space\t%d, 0\n", padsize); + } + if (alignsize > 0) + asm_emit_align(f, alignsize); + emit_label(f, symprefix, "blob_abs_end"); + + data_free(strbuf); +} + +struct inbuf { + char *base, *limit, *ptr; +}; + +static void inbuf_init(struct inbuf *inb, void *base, void *limit) +{ + inb->base = base; + inb->limit = limit; + inb->ptr = inb->base; +} + +static void flat_read_chunk(struct inbuf *inb, void *p, int len) +{ + if ((inb->ptr + len) > inb->limit) + die("Premature end of data parsing flat device tree\n"); + + memcpy(p, inb->ptr, len); + + inb->ptr += len; +} + +static uint32_t flat_read_word(struct inbuf *inb) +{ + fdt32_t val; + + assert(((inb->ptr - inb->base) % sizeof(val)) == 0); + + flat_read_chunk(inb, &val, sizeof(val)); + + return fdt32_to_cpu(val); +} + +static void flat_realign(struct inbuf *inb, int align) +{ + int off = inb->ptr - inb->base; + + inb->ptr = inb->base + ALIGN(off, align); + if (inb->ptr > inb->limit) + die("Premature end of data parsing flat device tree\n"); +} + +static char *flat_read_string(struct inbuf *inb) +{ + int len = 0; + const char *p = inb->ptr; + char *str; + + do { + if (p >= inb->limit) + die("Premature end of data parsing flat device tree\n"); + len++; + } while ((*p++) != '\0'); + + str = xstrdup(inb->ptr); + + inb->ptr += len; + + flat_realign(inb, sizeof(uint32_t)); + + return str; +} + +static struct data flat_read_data(struct inbuf *inb, int len) +{ + struct data d = empty_data; + + if (len == 0) + return empty_data; + + d = data_grow_for(d, len); + d.len = len; + + flat_read_chunk(inb, d.val, len); + + flat_realign(inb, sizeof(uint32_t)); + + return d; +} + +static char *flat_read_stringtable(struct inbuf *inb, int offset) +{ + const char *p; + + p = inb->base + offset; + while (1) { + if (p >= inb->limit || p < inb->base) + die("String offset %d overruns string table\n", + offset); + + if (*p == '\0') + break; + + p++; + } + + return xstrdup(inb->base + offset); +} + +static struct property *flat_read_property(struct inbuf *dtbuf, + struct inbuf *strbuf, int flags) +{ + uint32_t proplen, stroff; + char *name; + struct data val; + + proplen = flat_read_word(dtbuf); + stroff = flat_read_word(dtbuf); + + name = flat_read_stringtable(strbuf, stroff); + + if ((flags & FTF_VARALIGN) && (proplen >= 8)) + flat_realign(dtbuf, 8); + + val = flat_read_data(dtbuf, proplen); + + return build_property(name, val); +} + + +static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb) +{ + struct reserve_info *reservelist = NULL; + struct reserve_info *new; + struct fdt_reserve_entry re; + + /* + * Each entry is a pair of u64 (addr, size) values for 4 cell_t's. + * List terminates at an entry with size equal to zero. + * + * First pass, count entries. + */ + while (1) { + uint64_t address, size; + + flat_read_chunk(inb, &re, sizeof(re)); + address = fdt64_to_cpu(re.address); + size = fdt64_to_cpu(re.size); + if (size == 0) + break; + + new = build_reserve_entry(address, size); + reservelist = add_reserve_entry(reservelist, new); + } + + return reservelist; +} + + +static char *nodename_from_path(const char *ppath, const char *cpath) +{ + int plen; + + plen = strlen(ppath); + + if (!strneq(ppath, cpath, plen)) + die("Path \"%s\" is not valid as a child of \"%s\"\n", + cpath, ppath); + + /* root node is a special case */ + if (!streq(ppath, "/")) + plen++; + + return xstrdup(cpath + plen); +} + +static struct node *unflatten_tree(struct inbuf *dtbuf, + struct inbuf *strbuf, + const char *parent_flatname, int flags) +{ + struct node *node; + char *flatname; + uint32_t val; + + node = build_node(NULL, NULL); + + flatname = flat_read_string(dtbuf); + + if (flags & FTF_FULLPATH) + node->name = nodename_from_path(parent_flatname, flatname); + else + node->name = flatname; + + do { + struct property *prop; + struct node *child; + + val = flat_read_word(dtbuf); + switch (val) { + case FDT_PROP: + if (node->children) + fprintf(stderr, "Warning: Flat tree input has " + "subnodes preceding a property.\n"); + prop = flat_read_property(dtbuf, strbuf, flags); + add_property(node, prop); + break; + + case FDT_BEGIN_NODE: + child = unflatten_tree(dtbuf,strbuf, flatname, flags); + add_child(node, child); + break; + + case FDT_END_NODE: + break; + + case FDT_END: + die("Premature FDT_END in device tree blob\n"); + break; + + case FDT_NOP: + if (!(flags & FTF_NOPS)) + fprintf(stderr, "Warning: NOP tag found in flat tree" + " version <16\n"); + + /* Ignore */ + break; + + default: + die("Invalid opcode word %08x in device tree blob\n", + val); + } + } while (val != FDT_END_NODE); + + if (node->name != flatname) { + free(flatname); + } + + return node; +} + + +struct dt_info *dt_from_blob(const char *fname) +{ + FILE *f; + fdt32_t magic_buf, totalsize_buf; + uint32_t magic, totalsize, version, size_dt, boot_cpuid_phys; + uint32_t off_dt, off_str, off_mem_rsvmap; + int rc; + char *blob; + struct fdt_header *fdt; + char *p; + struct inbuf dtbuf, strbuf; + struct inbuf memresvbuf; + int sizeleft; + struct reserve_info *reservelist; + struct node *tree; + uint32_t val; + int flags = 0; + + f = srcfile_relative_open(fname, NULL); + + rc = fread(&magic_buf, sizeof(magic_buf), 1, f); + if (ferror(f)) + die("Error reading DT blob magic number: %s\n", + strerror(errno)); + if (rc < 1) { + if (feof(f)) + die("EOF reading DT blob magic number\n"); + else + die("Mysterious short read reading magic number\n"); + } + + magic = fdt32_to_cpu(magic_buf); + if (magic != FDT_MAGIC) + die("Blob has incorrect magic number\n"); + + rc = fread(&totalsize_buf, sizeof(totalsize_buf), 1, f); + if (ferror(f)) + die("Error reading DT blob size: %s\n", strerror(errno)); + if (rc < 1) { + if (feof(f)) + die("EOF reading DT blob size\n"); + else + die("Mysterious short read reading blob size\n"); + } + + totalsize = fdt32_to_cpu(totalsize_buf); + if (totalsize < FDT_V1_SIZE) + die("DT blob size (%d) is too small\n", totalsize); + + blob = xmalloc(totalsize); + + fdt = (struct fdt_header *)blob; + fdt->magic = cpu_to_fdt32(magic); + fdt->totalsize = cpu_to_fdt32(totalsize); + + sizeleft = totalsize - sizeof(magic) - sizeof(totalsize); + p = blob + sizeof(magic) + sizeof(totalsize); + + while (sizeleft) { + if (feof(f)) + die("EOF before reading %d bytes of DT blob\n", + totalsize); + + rc = fread(p, 1, sizeleft, f); + if (ferror(f)) + die("Error reading DT blob: %s\n", + strerror(errno)); + + sizeleft -= rc; + p += rc; + } + + off_dt = fdt32_to_cpu(fdt->off_dt_struct); + off_str = fdt32_to_cpu(fdt->off_dt_strings); + off_mem_rsvmap = fdt32_to_cpu(fdt->off_mem_rsvmap); + version = fdt32_to_cpu(fdt->version); + boot_cpuid_phys = fdt32_to_cpu(fdt->boot_cpuid_phys); + + if (off_mem_rsvmap >= totalsize) + die("Mem Reserve structure offset exceeds total size\n"); + + if (off_dt >= totalsize) + die("DT structure offset exceeds total size\n"); + + if (off_str > totalsize) + die("String table offset exceeds total size\n"); + + if (version >= 3) { + uint32_t size_str = fdt32_to_cpu(fdt->size_dt_strings); + if ((off_str+size_str < off_str) || (off_str+size_str > totalsize)) + die("String table extends past total size\n"); + inbuf_init(&strbuf, blob + off_str, blob + off_str + size_str); + } else { + inbuf_init(&strbuf, blob + off_str, blob + totalsize); + } + + if (version >= 17) { + size_dt = fdt32_to_cpu(fdt->size_dt_struct); + if ((off_dt+size_dt < off_dt) || (off_dt+size_dt > totalsize)) + die("Structure block extends past total size\n"); + } + + if (version < 16) { + flags |= FTF_FULLPATH | FTF_NAMEPROPS | FTF_VARALIGN; + } else { + flags |= FTF_NOPS; + } + + inbuf_init(&memresvbuf, + blob + off_mem_rsvmap, blob + totalsize); + inbuf_init(&dtbuf, blob + off_dt, blob + totalsize); + + reservelist = flat_read_mem_reserve(&memresvbuf); + + val = flat_read_word(&dtbuf); + + if (val != FDT_BEGIN_NODE) + die("Device tree blob doesn't begin with FDT_BEGIN_NODE (begins with 0x%08x)\n", val); + + tree = unflatten_tree(&dtbuf, &strbuf, "", flags); + + val = flat_read_word(&dtbuf); + if (val != FDT_END) + die("Device tree blob doesn't end with FDT_END\n"); + + free(blob); + + fclose(f); + + return build_dt_info(DTSF_V1, reservelist, tree, boot_cpuid_phys); +} diff --git a/scripts/dtc/fstree.c b/scripts/dtc/fstree.c new file mode 100644 index 0000000000..ae7d06c3c4 --- /dev/null +++ b/scripts/dtc/fstree.c @@ -0,0 +1,90 @@ +/* + * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005. + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#include "dtc.h" + +#include <dirent.h> +#include <sys/stat.h> + +static struct node *read_fstree(const char *dirname) +{ + DIR *d; + struct dirent *de; + struct stat st; + struct node *tree; + + d = opendir(dirname); + if (!d) + die("Couldn't opendir() \"%s\": %s\n", dirname, strerror(errno)); + + tree = build_node(NULL, NULL); + + while ((de = readdir(d)) != NULL) { + char *tmpname; + + if (streq(de->d_name, ".") + || streq(de->d_name, "..")) + continue; + + tmpname = join_path(dirname, de->d_name); + + if (lstat(tmpname, &st) < 0) + die("stat(%s): %s\n", tmpname, strerror(errno)); + + if (S_ISREG(st.st_mode)) { + struct property *prop; + FILE *pfile; + + pfile = fopen(tmpname, "rb"); + if (! pfile) { + fprintf(stderr, + "WARNING: Cannot open %s: %s\n", + tmpname, strerror(errno)); + } else { + prop = build_property(xstrdup(de->d_name), + data_copy_file(pfile, + st.st_size)); + add_property(tree, prop); + fclose(pfile); + } + } else if (S_ISDIR(st.st_mode)) { + struct node *newchild; + + newchild = read_fstree(tmpname); + newchild = name_node(newchild, xstrdup(de->d_name)); + add_child(tree, newchild); + } + + free(tmpname); + } + + closedir(d); + return tree; +} + +struct dt_info *dt_from_fs(const char *dirname) +{ + struct node *tree; + + tree = read_fstree(dirname); + tree = name_node(tree, ""); + + return build_dt_info(DTSF_V1, NULL, tree, guess_boot_cpuid(tree)); +} diff --git a/scripts/dtc/libfdt/Makefile.libfdt b/scripts/dtc/libfdt/Makefile.libfdt new file mode 100644 index 0000000000..098b3f36e6 --- /dev/null +++ b/scripts/dtc/libfdt/Makefile.libfdt @@ -0,0 +1,11 @@ +# Makefile.libfdt +# +# This is not a complete Makefile of itself. Instead, it is designed to +# be easily embeddable into other systems of Makefiles. +# +LIBFDT_soname = libfdt.$(SHAREDLIB_EXT).1 +LIBFDT_INCLUDES = fdt.h libfdt.h libfdt_env.h +LIBFDT_VERSION = version.lds +LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c fdt_empty_tree.c \ + fdt_addresses.c fdt_overlay.c +LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o) diff --git a/scripts/dtc/libfdt/fdt.c b/scripts/dtc/libfdt/fdt.c new file mode 100644 index 0000000000..22286a1aae --- /dev/null +++ b/scripts/dtc/libfdt/fdt.c @@ -0,0 +1,251 @@ +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * libfdt is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Alternatively, + * + * b) Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "libfdt_env.h" + +#include <fdt.h> +#include <libfdt.h> + +#include "libfdt_internal.h" + +int fdt_check_header(const void *fdt) +{ + if (fdt_magic(fdt) == FDT_MAGIC) { + /* Complete tree */ + if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) + return -FDT_ERR_BADVERSION; + if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION) + return -FDT_ERR_BADVERSION; + } else if (fdt_magic(fdt) == FDT_SW_MAGIC) { + /* Unfinished sequential-write blob */ + if (fdt_size_dt_struct(fdt) == 0) + return -FDT_ERR_BADSTATE; + } else { + return -FDT_ERR_BADMAGIC; + } + + return 0; +} + +const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len) +{ + unsigned absoffset = offset + fdt_off_dt_struct(fdt); + + if ((absoffset < offset) + || ((absoffset + len) < absoffset) + || (absoffset + len) > fdt_totalsize(fdt)) + return NULL; + + if (fdt_version(fdt) >= 0x11) + if (((offset + len) < offset) + || ((offset + len) > fdt_size_dt_struct(fdt))) + return NULL; + + return _fdt_offset_ptr(fdt, offset); +} + +uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) +{ + const fdt32_t *tagp, *lenp; + uint32_t tag; + int offset = startoffset; + const char *p; + + *nextoffset = -FDT_ERR_TRUNCATED; + tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE); + if (!tagp) + return FDT_END; /* premature end */ + tag = fdt32_to_cpu(*tagp); + offset += FDT_TAGSIZE; + + *nextoffset = -FDT_ERR_BADSTRUCTURE; + switch (tag) { + case FDT_BEGIN_NODE: + /* skip name */ + do { + p = fdt_offset_ptr(fdt, offset++, 1); + } while (p && (*p != '\0')); + if (!p) + return FDT_END; /* premature end */ + break; + + case FDT_PROP: + lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp)); + if (!lenp) + return FDT_END; /* premature end */ + /* skip-name offset, length and value */ + offset += sizeof(struct fdt_property) - FDT_TAGSIZE + + fdt32_to_cpu(*lenp); + break; + + case FDT_END: + case FDT_END_NODE: + case FDT_NOP: + break; + + default: + return FDT_END; + } + + if (!fdt_offset_ptr(fdt, startoffset, offset - startoffset)) + return FDT_END; /* premature end */ + + *nextoffset = FDT_TAGALIGN(offset); + return tag; +} + +int _fdt_check_node_offset(const void *fdt, int offset) +{ + if ((offset < 0) || (offset % FDT_TAGSIZE) + || (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE)) + return -FDT_ERR_BADOFFSET; + + return offset; +} + +int _fdt_check_prop_offset(const void *fdt, int offset) +{ + if ((offset < 0) || (offset % FDT_TAGSIZE) + || (fdt_next_tag(fdt, offset, &offset) != FDT_PROP)) + return -FDT_ERR_BADOFFSET; + + return offset; +} + +int fdt_next_node(const void *fdt, int offset, int *depth) +{ + int nextoffset = 0; + uint32_t tag; + + if (offset >= 0) + if ((nextoffset = _fdt_check_node_offset(fdt, offset)) < 0) + return nextoffset; + + do { + offset = nextoffset; + tag = fdt_next_tag(fdt, offset, &nextoffset); + + switch (tag) { + case FDT_PROP: + case FDT_NOP: + break; + + case FDT_BEGIN_NODE: + if (depth) + (*depth)++; + break; + + case FDT_END_NODE: + if (depth && ((--(*depth)) < 0)) + return nextoffset; + break; + + case FDT_END: + if ((nextoffset >= 0) + || ((nextoffset == -FDT_ERR_TRUNCATED) && !depth)) + return -FDT_ERR_NOTFOUND; + else + return nextoffset; + } + } while (tag != FDT_BEGIN_NODE); + + return offset; +} + +int fdt_first_subnode(const void *fdt, int offset) +{ + int depth = 0; + + offset = fdt_next_node(fdt, offset, &depth); + if (offset < 0 || depth != 1) + return -FDT_ERR_NOTFOUND; + + return offset; +} + +int fdt_next_subnode(const void *fdt, int offset) +{ + int depth = 1; + + /* + * With respect to the parent, the depth of the next subnode will be + * the same as the last. + */ + do { + offset = fdt_next_node(fdt, offset, &depth); + if (offset < 0 || depth < 1) + return -FDT_ERR_NOTFOUND; + } while (depth > 1); + + return offset; +} + +const char *_fdt_find_string(const char *strtab, int tabsize, const char *s) +{ + int len = strlen(s) + 1; + const char *last = strtab + tabsize - len; + const char *p; + + for (p = strtab; p <= last; p++) + if (memcmp(p, s, len) == 0) + return p; + return NULL; +} + +int fdt_move(const void *fdt, void *buf, int bufsize) +{ + FDT_CHECK_HEADER(fdt); + + if (fdt_totalsize(fdt) > bufsize) + return -FDT_ERR_NOSPACE; + + memmove(buf, fdt, fdt_totalsize(fdt)); + return 0; +} diff --git a/scripts/dtc/libfdt/fdt.h b/scripts/dtc/libfdt/fdt.h new file mode 100644 index 0000000000..526aedb515 --- /dev/null +++ b/scripts/dtc/libfdt/fdt.h @@ -0,0 +1,111 @@ +#ifndef _FDT_H +#define _FDT_H +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * Copyright 2012 Kim Phillips, Freescale Semiconductor. + * + * libfdt is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Alternatively, + * + * b) Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __ASSEMBLY__ + +struct fdt_header { + fdt32_t magic; /* magic word FDT_MAGIC */ + fdt32_t totalsize; /* total size of DT block */ + fdt32_t off_dt_struct; /* offset to structure */ + fdt32_t off_dt_strings; /* offset to strings */ + fdt32_t off_mem_rsvmap; /* offset to memory reserve map */ + fdt32_t version; /* format version */ + fdt32_t last_comp_version; /* last compatible version */ + + /* version 2 fields below */ + fdt32_t boot_cpuid_phys; /* Which physical CPU id we're + booting on */ + /* version 3 fields below */ + fdt32_t size_dt_strings; /* size of the strings block */ + + /* version 17 fields below */ + fdt32_t size_dt_struct; /* size of the structure block */ +}; + +struct fdt_reserve_entry { + fdt64_t address; + fdt64_t size; +}; + +struct fdt_node_header { + fdt32_t tag; + char name[0]; +}; + +struct fdt_property { + fdt32_t tag; + fdt32_t len; + fdt32_t nameoff; + char data[0]; +}; + +#endif /* !__ASSEMBLY */ + +#define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */ +#define FDT_TAGSIZE sizeof(fdt32_t) + +#define FDT_BEGIN_NODE 0x1 /* Start node: full name */ +#define FDT_END_NODE 0x2 /* End node */ +#define FDT_PROP 0x3 /* Property: name off, + size, content */ +#define FDT_NOP 0x4 /* nop */ +#define FDT_END 0x9 + +#define FDT_V1_SIZE (7*sizeof(fdt32_t)) +#define FDT_V2_SIZE (FDT_V1_SIZE + sizeof(fdt32_t)) +#define FDT_V3_SIZE (FDT_V2_SIZE + sizeof(fdt32_t)) +#define FDT_V16_SIZE FDT_V3_SIZE +#define FDT_V17_SIZE (FDT_V16_SIZE + sizeof(fdt32_t)) + +#endif /* _FDT_H */ diff --git a/scripts/dtc/libfdt/fdt_empty_tree.c b/scripts/dtc/libfdt/fdt_empty_tree.c new file mode 100644 index 0000000000..f2ae9b77c2 --- /dev/null +++ b/scripts/dtc/libfdt/fdt_empty_tree.c @@ -0,0 +1,83 @@ +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2012 David Gibson, IBM Corporation. + * + * libfdt is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Alternatively, + * + * b) Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "libfdt_env.h" + +#include <fdt.h> +#include <libfdt.h> + +#include "libfdt_internal.h" + +int fdt_create_empty_tree(void *buf, int bufsize) +{ + int err; + + err = fdt_create(buf, bufsize); + if (err) + return err; + + err = fdt_finish_reservemap(buf); + if (err) + return err; + + err = fdt_begin_node(buf, ""); + if (err) + return err; + + err = fdt_end_node(buf); + if (err) + return err; + + err = fdt_finish(buf); + if (err) + return err; + + return fdt_open_into(buf, buf, bufsize); +} diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c new file mode 100644 index 0000000000..08de2cce67 --- /dev/null +++ b/scripts/dtc/libfdt/fdt_ro.c @@ -0,0 +1,703 @@ +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * libfdt is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Alternatively, + * + * b) Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "libfdt_env.h" + +#include <fdt.h> +#include <libfdt.h> + +#include "libfdt_internal.h" + +static int _fdt_nodename_eq(const void *fdt, int offset, + const char *s, int len) +{ + const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1); + + if (!p) + /* short match */ + return 0; + + if (memcmp(p, s, len) != 0) + return 0; + + if (p[len] == '\0') + return 1; + else if (!memchr(s, '@', len) && (p[len] == '@')) + return 1; + else + return 0; +} + +const char *fdt_string(const void *fdt, int stroffset) +{ + return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset; +} + +static int _fdt_string_eq(const void *fdt, int stroffset, + const char *s, int len) +{ + const char *p = fdt_string(fdt, stroffset); + + return (strlen(p) == len) && (memcmp(p, s, len) == 0); +} + +uint32_t fdt_get_max_phandle(const void *fdt) +{ + uint32_t max_phandle = 0; + int offset; + + for (offset = fdt_next_node(fdt, -1, NULL);; + offset = fdt_next_node(fdt, offset, NULL)) { + uint32_t phandle; + + if (offset == -FDT_ERR_NOTFOUND) + return max_phandle; + + if (offset < 0) + return (uint32_t)-1; + + phandle = fdt_get_phandle(fdt, offset); + if (phandle == (uint32_t)-1) + continue; + + if (phandle > max_phandle) + max_phandle = phandle; + } + + return 0; +} + +int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) +{ + FDT_CHECK_HEADER(fdt); + *address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address); + *size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size); + return 0; +} + +int fdt_num_mem_rsv(const void *fdt) +{ + int i = 0; + + while (fdt64_to_cpu(_fdt_mem_rsv(fdt, i)->size) != 0) + i++; + return i; +} + +static int _nextprop(const void *fdt, int offset) +{ + uint32_t tag; + int nextoffset; + + do { + tag = fdt_next_tag(fdt, offset, &nextoffset); + + switch (tag) { + case FDT_END: + if (nextoffset >= 0) + return -FDT_ERR_BADSTRUCTURE; + else + return nextoffset; + + case FDT_PROP: + return offset; + } + offset = nextoffset; + } while (tag == FDT_NOP); + + return -FDT_ERR_NOTFOUND; +} + +int fdt_subnode_offset_namelen(const void *fdt, int offset, + const char *name, int namelen) +{ + int depth; + + FDT_CHECK_HEADER(fdt); + + for (depth = 0; + (offset >= 0) && (depth >= 0); + offset = fdt_next_node(fdt, offset, &depth)) + if ((depth == 1) + && _fdt_nodename_eq(fdt, offset, name, namelen)) + return offset; + + if (depth < 0) + return -FDT_ERR_NOTFOUND; + return offset; /* error */ +} + +int fdt_subnode_offset(const void *fdt, int parentoffset, + const char *name) +{ + return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name)); +} + +int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen) +{ + const char *end = path + namelen; + const char *p = path; + int offset = 0; + + FDT_CHECK_HEADER(fdt); + + /* see if we have an alias */ + if (*path != '/') { + const char *q = memchr(path, '/', end - p); + + if (!q) + q = end; + + p = fdt_get_alias_namelen(fdt, p, q - p); + if (!p) + return -FDT_ERR_BADPATH; + offset = fdt_path_offset(fdt, p); + + p = q; + } + + while (p < end) { + const char *q; + + while (*p == '/') { + p++; + if (p == end) + return offset; + } + q = memchr(p, '/', end - p); + if (! q) + q = end; + + offset = fdt_subnode_offset_namelen(fdt, offset, p, q-p); + if (offset < 0) + return offset; + + p = q; + } + + return offset; +} + +int fdt_path_offset(const void *fdt, const char *path) +{ + return fdt_path_offset_namelen(fdt, path, strlen(path)); +} + +const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) +{ + const struct fdt_node_header *nh = _fdt_offset_ptr(fdt, nodeoffset); + int err; + + if (((err = fdt_check_header(fdt)) != 0) + || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0)) + goto fail; + + if (len) + *len = strlen(nh->name); + + return nh->name; + + fail: + if (len) + *len = err; + return NULL; +} + +int fdt_first_property_offset(const void *fdt, int nodeoffset) +{ + int offset; + + if ((offset = _fdt_check_node_offset(fdt, nodeoffset)) < 0) + return offset; + + return _nextprop(fdt, offset); +} + +int fdt_next_property_offset(const void *fdt, int offset) +{ + if ((offset = _fdt_check_prop_offset(fdt, offset)) < 0) + return offset; + + return _nextprop(fdt, offset); +} + +const struct fdt_property *fdt_get_property_by_offset(const void *fdt, + int offset, + int *lenp) +{ + int err; + const struct fdt_property *prop; + + if ((err = _fdt_check_prop_offset(fdt, offset)) < 0) { + if (lenp) + *lenp = err; + return NULL; + } + + prop = _fdt_offset_ptr(fdt, offset); + + if (lenp) + *lenp = fdt32_to_cpu(prop->len); + + return prop; +} + +const struct fdt_property *fdt_get_property_namelen(const void *fdt, + int offset, + const char *name, + int namelen, int *lenp) +{ + for (offset = fdt_first_property_offset(fdt, offset); + (offset >= 0); + (offset = fdt_next_property_offset(fdt, offset))) { + const struct fdt_property *prop; + + if (!(prop = fdt_get_property_by_offset(fdt, offset, lenp))) { + offset = -FDT_ERR_INTERNAL; + break; + } + if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff), + name, namelen)) + return prop; + } + + if (lenp) + *lenp = offset; + return NULL; +} + +const struct fdt_property *fdt_get_property(const void *fdt, + int nodeoffset, + const char *name, int *lenp) +{ + return fdt_get_property_namelen(fdt, nodeoffset, name, + strlen(name), lenp); +} + +const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, + const char *name, int namelen, int *lenp) +{ + const struct fdt_property *prop; + + prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp); + if (!prop) + return NULL; + + return prop->data; +} + +const void *fdt_getprop_by_offset(const void *fdt, int offset, + const char **namep, int *lenp) +{ + const struct fdt_property *prop; + + prop = fdt_get_property_by_offset(fdt, offset, lenp); + if (!prop) + return NULL; + if (namep) + *namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff)); + return prop->data; +} + +const void *fdt_getprop(const void *fdt, int nodeoffset, + const char *name, int *lenp) +{ + return fdt_getprop_namelen(fdt, nodeoffset, name, strlen(name), lenp); +} + +uint32_t fdt_get_phandle(const void *fdt, int nodeoffset) +{ + const fdt32_t *php; + int len; + + /* FIXME: This is a bit sub-optimal, since we potentially scan + * over all the properties twice. */ + php = fdt_getprop(fdt, nodeoffset, "phandle", &len); + if (!php || (len != sizeof(*php))) { + php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len); + if (!php || (len != sizeof(*php))) + return 0; + } + + return fdt32_to_cpu(*php); +} + +const char *fdt_get_alias_namelen(const void *fdt, + const char *name, int namelen) +{ + int aliasoffset; + + aliasoffset = fdt_path_offset(fdt, "/aliases"); + if (aliasoffset < 0) + return NULL; + + return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL); +} + +const char *fdt_get_alias(const void *fdt, const char *name) +{ + return fdt_get_alias_namelen(fdt, name, strlen(name)); +} + +int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) +{ + int pdepth = 0, p = 0; + int offset, depth, namelen; + const char *name; + + FDT_CHECK_HEADER(fdt); + + if (buflen < 2) + return -FDT_ERR_NOSPACE; + + for (offset = 0, depth = 0; + (offset >= 0) && (offset <= nodeoffset); + offset = fdt_next_node(fdt, offset, &depth)) { + while (pdepth > depth) { + do { + p--; + } while (buf[p-1] != '/'); + pdepth--; + } + + if (pdepth >= depth) { + name = fdt_get_name(fdt, offset, &namelen); + if (!name) + return namelen; + if ((p + namelen + 1) <= buflen) { + memcpy(buf + p, name, namelen); + p += namelen; + buf[p++] = '/'; + pdepth++; + } + } + + if (offset == nodeoffset) { + if (pdepth < (depth + 1)) + return -FDT_ERR_NOSPACE; + + if (p > 1) /* special case so that root path is "/", not "" */ + p--; + buf[p] = '\0'; + return 0; + } + } + + if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) + return -FDT_ERR_BADOFFSET; + else if (offset == -FDT_ERR_BADOFFSET) + return -FDT_ERR_BADSTRUCTURE; + + return offset; /* error from fdt_next_node() */ +} + +int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, + int supernodedepth, int *nodedepth) +{ + int offset, depth; + int supernodeoffset = -FDT_ERR_INTERNAL; + + FDT_CHECK_HEADER(fdt); + + if (supernodedepth < 0) + return -FDT_ERR_NOTFOUND; + + for (offset = 0, depth = 0; + (offset >= 0) && (offset <= nodeoffset); + offset = fdt_next_node(fdt, offset, &depth)) { + if (depth == supernodedepth) + supernodeoffset = offset; + + if (offset == nodeoffset) { + if (nodedepth) + *nodedepth = depth; + + if (supernodedepth > depth) + return -FDT_ERR_NOTFOUND; + else + return supernodeoffset; + } + } + + if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) + return -FDT_ERR_BADOFFSET; + else if (offset == -FDT_ERR_BADOFFSET) + return -FDT_ERR_BADSTRUCTURE; + + return offset; /* error from fdt_next_node() */ +} + +int fdt_node_depth(const void *fdt, int nodeoffset) +{ + int nodedepth; + int err; + + err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth); + if (err) + return (err < 0) ? err : -FDT_ERR_INTERNAL; + return nodedepth; +} + +int fdt_parent_offset(const void *fdt, int nodeoffset) +{ + int nodedepth = fdt_node_depth(fdt, nodeoffset); + + if (nodedepth < 0) + return nodedepth; + return fdt_supernode_atdepth_offset(fdt, nodeoffset, + nodedepth - 1, NULL); +} + +int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, + const char *propname, + const void *propval, int proplen) +{ + int offset; + const void *val; + int len; + + FDT_CHECK_HEADER(fdt); + + /* FIXME: The algorithm here is pretty horrible: we scan each + * property of a node in fdt_getprop(), then if that didn't + * find what we want, we scan over them again making our way + * to the next node. Still it's the easiest to implement + * approach; performance can come later. */ + for (offset = fdt_next_node(fdt, startoffset, NULL); + offset >= 0; + offset = fdt_next_node(fdt, offset, NULL)) { + val = fdt_getprop(fdt, offset, propname, &len); + if (val && (len == proplen) + && (memcmp(val, propval, len) == 0)) + return offset; + } + + return offset; /* error from fdt_next_node() */ +} + +int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) +{ + int offset; + + if ((phandle == 0) || (phandle == -1)) + return -FDT_ERR_BADPHANDLE; + + FDT_CHECK_HEADER(fdt); + + /* FIXME: The algorithm here is pretty horrible: we + * potentially scan each property of a node in + * fdt_get_phandle(), then if that didn't find what + * we want, we scan over them again making our way to the next + * node. Still it's the easiest to implement approach; + * performance can come later. */ + for (offset = fdt_next_node(fdt, -1, NULL); + offset >= 0; + offset = fdt_next_node(fdt, offset, NULL)) { + if (fdt_get_phandle(fdt, offset) == phandle) + return offset; + } + + return offset; /* error from fdt_next_node() */ +} + +int fdt_stringlist_contains(const char *strlist, int listlen, const char *str) +{ + int len = strlen(str); + const char *p; + + while (listlen >= len) { + if (memcmp(str, strlist, len+1) == 0) + return 1; + p = memchr(strlist, '\0', listlen); + if (!p) + return 0; /* malformed strlist.. */ + listlen -= (p-strlist) + 1; + strlist = p + 1; + } + return 0; +} + +int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property) +{ + const char *list, *end; + int length, count = 0; + + list = fdt_getprop(fdt, nodeoffset, property, &length); + if (!list) + return length; + + end = list + length; + + while (list < end) { + length = strnlen(list, end - list) + 1; + + /* Abort if the last string isn't properly NUL-terminated. */ + if (list + length > end) + return -FDT_ERR_BADVALUE; + + list += length; + count++; + } + + return count; +} + +int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property, + const char *string) +{ + int length, len, idx = 0; + const char *list, *end; + + list = fdt_getprop(fdt, nodeoffset, property, &length); + if (!list) + return length; + + len = strlen(string) + 1; + end = list + length; + + while (list < end) { + length = strnlen(list, end - list) + 1; + + /* Abort if the last string isn't properly NUL-terminated. */ + if (list + length > end) + return -FDT_ERR_BADVALUE; + + if (length == len && memcmp(list, string, length) == 0) + return idx; + + list += length; + idx++; + } + + return -FDT_ERR_NOTFOUND; +} + +const char *fdt_stringlist_get(const void *fdt, int nodeoffset, + const char *property, int idx, + int *lenp) +{ + const char *list, *end; + int length; + + list = fdt_getprop(fdt, nodeoffset, property, &length); + if (!list) { + if (lenp) + *lenp = length; + + return NULL; + } + + end = list + length; + + while (list < end) { + length = strnlen(list, end - list) + 1; + + /* Abort if the last string isn't properly NUL-terminated. */ + if (list + length > end) { + if (lenp) + *lenp = -FDT_ERR_BADVALUE; + + return NULL; + } + + if (idx == 0) { + if (lenp) + *lenp = length - 1; + + return list; + } + + list += length; + idx--; + } + + if (lenp) + *lenp = -FDT_ERR_NOTFOUND; + + return NULL; +} + +int fdt_node_check_compatible(const void *fdt, int nodeoffset, + const char *compatible) +{ + const void *prop; + int len; + + prop = fdt_getprop(fdt, nodeoffset, "compatible", &len); + if (!prop) + return len; + + return !fdt_stringlist_contains(prop, len, compatible); +} + +int fdt_node_offset_by_compatible(const void *fdt, int startoffset, + const char *compatible) +{ + int offset, err; + + FDT_CHECK_HEADER(fdt); + + /* FIXME: The algorithm here is pretty horrible: we scan each + * property of a node in fdt_node_check_compatible(), then if + * that didn't find what we want, we scan over them again + * making our way to the next node. Still it's the easiest to + * implement approach; performance can come later. */ + for (offset = fdt_next_node(fdt, startoffset, NULL); + offset >= 0; + offset = fdt_next_node(fdt, offset, NULL)) { + err = fdt_node_check_compatible(fdt, offset, compatible); + if ((err < 0) && (err != -FDT_ERR_NOTFOUND)) + return err; + else if (err == 0) + return offset; + } + + return offset; /* error from fdt_next_node() */ +} diff --git a/scripts/dtc/libfdt/fdt_rw.c b/scripts/dtc/libfdt/fdt_rw.c new file mode 100644 index 0000000000..5c3a2bb0bc --- /dev/null +++ b/scripts/dtc/libfdt/fdt_rw.c @@ -0,0 +1,505 @@ +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * libfdt is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Alternatively, + * + * b) Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "libfdt_env.h" + +#include <fdt.h> +#include <libfdt.h> + +#include "libfdt_internal.h" + +static int _fdt_blocks_misordered(const void *fdt, + int mem_rsv_size, int struct_size) +{ + return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8)) + || (fdt_off_dt_struct(fdt) < + (fdt_off_mem_rsvmap(fdt) + mem_rsv_size)) + || (fdt_off_dt_strings(fdt) < + (fdt_off_dt_struct(fdt) + struct_size)) + || (fdt_totalsize(fdt) < + (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt))); +} + +static int _fdt_rw_check_header(void *fdt) +{ + FDT_CHECK_HEADER(fdt); + + if (fdt_version(fdt) < 17) + return -FDT_ERR_BADVERSION; + if (_fdt_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry), + fdt_size_dt_struct(fdt))) + return -FDT_ERR_BADLAYOUT; + if (fdt_version(fdt) > 17) + fdt_set_version(fdt, 17); + + return 0; +} + +#define FDT_RW_CHECK_HEADER(fdt) \ + { \ + int __err; \ + if ((__err = _fdt_rw_check_header(fdt)) != 0) \ + return __err; \ + } + +static inline int _fdt_data_size(void *fdt) +{ + return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); +} + +static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen) +{ + char *p = splicepoint; + char *end = (char *)fdt + _fdt_data_size(fdt); + + if (((p + oldlen) < p) || ((p + oldlen) > end)) + return -FDT_ERR_BADOFFSET; + if ((p < (char *)fdt) || ((end - oldlen + newlen) < (char *)fdt)) + return -FDT_ERR_BADOFFSET; + if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt))) + return -FDT_ERR_NOSPACE; + memmove(p + newlen, p + oldlen, end - p - oldlen); + return 0; +} + +static int _fdt_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p, + int oldn, int newn) +{ + int delta = (newn - oldn) * sizeof(*p); + int err; + err = _fdt_splice(fdt, p, oldn * sizeof(*p), newn * sizeof(*p)); + if (err) + return err; + fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta); + fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta); + return 0; +} + +static int _fdt_splice_struct(void *fdt, void *p, + int oldlen, int newlen) +{ + int delta = newlen - oldlen; + int err; + + if ((err = _fdt_splice(fdt, p, oldlen, newlen))) + return err; + + fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta); + fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta); + return 0; +} + +static int _fdt_splice_string(void *fdt, int newlen) +{ + void *p = (char *)fdt + + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); + int err; + + if ((err = _fdt_splice(fdt, p, 0, newlen))) + return err; + + fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen); + return 0; +} + +static int _fdt_find_add_string(void *fdt, const char *s) +{ + char *strtab = (char *)fdt + fdt_off_dt_strings(fdt); + const char *p; + char *new; + int len = strlen(s) + 1; + int err; + + p = _fdt_find_string(strtab, fdt_size_dt_strings(fdt), s); + if (p) + /* found it */ + return (p - strtab); + + new = strtab + fdt_size_dt_strings(fdt); + err = _fdt_splice_string(fdt, len); + if (err) + return err; + + memcpy(new, s, len); + return (new - strtab); +} + +int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size) +{ + struct fdt_reserve_entry *re; + int err; + + FDT_RW_CHECK_HEADER(fdt); + + re = _fdt_mem_rsv_w(fdt, fdt_num_mem_rsv(fdt)); + err = _fdt_splice_mem_rsv(fdt, re, 0, 1); + if (err) + return err; + + re->address = cpu_to_fdt64(address); + re->size = cpu_to_fdt64(size); + return 0; +} + +int fdt_del_mem_rsv(void *fdt, int n) +{ + struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n); + + FDT_RW_CHECK_HEADER(fdt); + + if (n >= fdt_num_mem_rsv(fdt)) + return -FDT_ERR_NOTFOUND; + + return _fdt_splice_mem_rsv(fdt, re, 1, 0); +} + +static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name, + int len, struct fdt_property **prop) +{ + int oldlen; + int err; + + *prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); + if (!*prop) + return oldlen; + + if ((err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen), + FDT_TAGALIGN(len)))) + return err; + + (*prop)->len = cpu_to_fdt32(len); + return 0; +} + +static int _fdt_add_property(void *fdt, int nodeoffset, const char *name, + int len, struct fdt_property **prop) +{ + int proplen; + int nextoffset; + int namestroff; + int err; + + if ((nextoffset = _fdt_check_node_offset(fdt, nodeoffset)) < 0) + return nextoffset; + + namestroff = _fdt_find_add_string(fdt, name); + if (namestroff < 0) + return namestroff; + + *prop = _fdt_offset_ptr_w(fdt, nextoffset); + proplen = sizeof(**prop) + FDT_TAGALIGN(len); + + err = _fdt_splice_struct(fdt, *prop, 0, proplen); + if (err) + return err; + + (*prop)->tag = cpu_to_fdt32(FDT_PROP); + (*prop)->nameoff = cpu_to_fdt32(namestroff); + (*prop)->len = cpu_to_fdt32(len); + return 0; +} + +int fdt_set_name(void *fdt, int nodeoffset, const char *name) +{ + char *namep; + int oldlen, newlen; + int err; + + FDT_RW_CHECK_HEADER(fdt); + + namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen); + if (!namep) + return oldlen; + + newlen = strlen(name); + + err = _fdt_splice_struct(fdt, namep, FDT_TAGALIGN(oldlen+1), + FDT_TAGALIGN(newlen+1)); + if (err) + return err; + + memcpy(namep, name, newlen+1); + return 0; +} + +int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name, + int len, void **prop_data) +{ + struct fdt_property *prop; + int err; + + FDT_RW_CHECK_HEADER(fdt); + + err = _fdt_resize_property(fdt, nodeoffset, name, len, &prop); + if (err == -FDT_ERR_NOTFOUND) + err = _fdt_add_property(fdt, nodeoffset, name, len, &prop); + if (err) + return err; + + *prop_data = prop->data; + return 0; +} + +int fdt_setprop(void *fdt, int nodeoffset, const char *name, + const void *val, int len) +{ + void *prop_data; + int err; + + err = fdt_setprop_placeholder(fdt, nodeoffset, name, len, &prop_data); + if (err) + return err; + + if (len) + memcpy(prop_data, val, len); + return 0; +} + +int fdt_appendprop(void *fdt, int nodeoffset, const char *name, + const void *val, int len) +{ + struct fdt_property *prop; + int err, oldlen, newlen; + + FDT_RW_CHECK_HEADER(fdt); + + prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); + if (prop) { + newlen = len + oldlen; + err = _fdt_splice_struct(fdt, prop->data, + FDT_TAGALIGN(oldlen), + FDT_TAGALIGN(newlen)); + if (err) + return err; + prop->len = cpu_to_fdt32(newlen); + memcpy(prop->data + oldlen, val, len); + } else { + err = _fdt_add_property(fdt, nodeoffset, name, len, &prop); + if (err) + return err; + memcpy(prop->data, val, len); + } + return 0; +} + +int fdt_delprop(void *fdt, int nodeoffset, const char *name) +{ + struct fdt_property *prop; + int len, proplen; + + FDT_RW_CHECK_HEADER(fdt); + + prop = fdt_get_property_w(fdt, nodeoffset, name, &len); + if (!prop) + return len; + + proplen = sizeof(*prop) + FDT_TAGALIGN(len); + return _fdt_splice_struct(fdt, prop, proplen, 0); +} + +int fdt_add_subnode_namelen(void *fdt, int parentoffset, + const char *name, int namelen) +{ + struct fdt_node_header *nh; + int offset, nextoffset; + int nodelen; + int err; + uint32_t tag; + fdt32_t *endtag; + + FDT_RW_CHECK_HEADER(fdt); + + offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen); + if (offset >= 0) + return -FDT_ERR_EXISTS; + else if (offset != -FDT_ERR_NOTFOUND) + return offset; + + /* Try to place the new node after the parent's properties */ + fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */ + do { + offset = nextoffset; + tag = fdt_next_tag(fdt, offset, &nextoffset); + } while ((tag == FDT_PROP) || (tag == FDT_NOP)); + + nh = _fdt_offset_ptr_w(fdt, offset); + nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE; + + err = _fdt_splice_struct(fdt, nh, 0, nodelen); + if (err) + return err; + + nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); + memset(nh->name, 0, FDT_TAGALIGN(namelen+1)); + memcpy(nh->name, name, namelen); + endtag = (fdt32_t *)((char *)nh + nodelen - FDT_TAGSIZE); + *endtag = cpu_to_fdt32(FDT_END_NODE); + + return offset; +} + +int fdt_add_subnode(void *fdt, int parentoffset, const char *name) +{ + return fdt_add_subnode_namelen(fdt, parentoffset, name, strlen(name)); +} + +int fdt_del_node(void *fdt, int nodeoffset) +{ + int endoffset; + + FDT_RW_CHECK_HEADER(fdt); + + endoffset = _fdt_node_end_offset(fdt, nodeoffset); + if (endoffset < 0) + return endoffset; + + return _fdt_splice_struct(fdt, _fdt_offset_ptr_w(fdt, nodeoffset), + endoffset - nodeoffset, 0); +} + +static void _fdt_packblocks(const char *old, char *new, + int mem_rsv_size, int struct_size) +{ + int mem_rsv_off, struct_off, strings_off; + + mem_rsv_off = FDT_ALIGN(sizeof(struct fdt_header), 8); + struct_off = mem_rsv_off + mem_rsv_size; + strings_off = struct_off + struct_size; + + memmove(new + mem_rsv_off, old + fdt_off_mem_rsvmap(old), mem_rsv_size); + fdt_set_off_mem_rsvmap(new, mem_rsv_off); + + memmove(new + struct_off, old + fdt_off_dt_struct(old), struct_size); + fdt_set_off_dt_struct(new, struct_off); + fdt_set_size_dt_struct(new, struct_size); + + memmove(new + strings_off, old + fdt_off_dt_strings(old), + fdt_size_dt_strings(old)); + fdt_set_off_dt_strings(new, strings_off); + fdt_set_size_dt_strings(new, fdt_size_dt_strings(old)); +} + +int fdt_open_into(const void *fdt, void *buf, int bufsize) +{ + int err; + int mem_rsv_size, struct_size; + int newsize; + const char *fdtstart = fdt; + const char *fdtend = fdtstart + fdt_totalsize(fdt); + char *tmp; + + FDT_CHECK_HEADER(fdt); + + mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) + * sizeof(struct fdt_reserve_entry); + + if (fdt_version(fdt) >= 17) { + struct_size = fdt_size_dt_struct(fdt); + } else { + struct_size = 0; + while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END) + ; + if (struct_size < 0) + return struct_size; + } + + if (!_fdt_blocks_misordered(fdt, mem_rsv_size, struct_size)) { + /* no further work necessary */ + err = fdt_move(fdt, buf, bufsize); + if (err) + return err; + fdt_set_version(buf, 17); + fdt_set_size_dt_struct(buf, struct_size); + fdt_set_totalsize(buf, bufsize); + return 0; + } + + /* Need to reorder */ + newsize = FDT_ALIGN(sizeof(struct fdt_header), 8) + mem_rsv_size + + struct_size + fdt_size_dt_strings(fdt); + + if (bufsize < newsize) + return -FDT_ERR_NOSPACE; + + /* First attempt to build converted tree at beginning of buffer */ + tmp = buf; + /* But if that overlaps with the old tree... */ + if (((tmp + newsize) > fdtstart) && (tmp < fdtend)) { + /* Try right after the old tree instead */ + tmp = (char *)(uintptr_t)fdtend; + if ((tmp + newsize) > ((char *)buf + bufsize)) + return -FDT_ERR_NOSPACE; + } + + _fdt_packblocks(fdt, tmp, mem_rsv_size, struct_size); + memmove(buf, tmp, newsize); + + fdt_set_magic(buf, FDT_MAGIC); + fdt_set_totalsize(buf, bufsize); + fdt_set_version(buf, 17); + fdt_set_last_comp_version(buf, 16); + fdt_set_boot_cpuid_phys(buf, fdt_boot_cpuid_phys(fdt)); + + return 0; +} + +int fdt_pack(void *fdt) +{ + int mem_rsv_size; + + FDT_RW_CHECK_HEADER(fdt); + + mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) + * sizeof(struct fdt_reserve_entry); + _fdt_packblocks(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt)); + fdt_set_totalsize(fdt, _fdt_data_size(fdt)); + + return 0; +} diff --git a/scripts/dtc/libfdt/fdt_strerror.c b/scripts/dtc/libfdt/fdt_strerror.c new file mode 100644 index 0000000000..9677a1887e --- /dev/null +++ b/scripts/dtc/libfdt/fdt_strerror.c @@ -0,0 +1,102 @@ +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * libfdt is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Alternatively, + * + * b) Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "libfdt_env.h" + +#include <fdt.h> +#include <libfdt.h> + +#include "libfdt_internal.h" + +struct fdt_errtabent { + const char *str; +}; + +#define FDT_ERRTABENT(val) \ + [(val)] = { .str = #val, } + +static struct fdt_errtabent fdt_errtable[] = { + FDT_ERRTABENT(FDT_ERR_NOTFOUND), + FDT_ERRTABENT(FDT_ERR_EXISTS), + FDT_ERRTABENT(FDT_ERR_NOSPACE), + + FDT_ERRTABENT(FDT_ERR_BADOFFSET), + FDT_ERRTABENT(FDT_ERR_BADPATH), + FDT_ERRTABENT(FDT_ERR_BADPHANDLE), + FDT_ERRTABENT(FDT_ERR_BADSTATE), + + FDT_ERRTABENT(FDT_ERR_TRUNCATED), + FDT_ERRTABENT(FDT_ERR_BADMAGIC), + FDT_ERRTABENT(FDT_ERR_BADVERSION), + FDT_ERRTABENT(FDT_ERR_BADSTRUCTURE), + FDT_ERRTABENT(FDT_ERR_BADLAYOUT), + FDT_ERRTABENT(FDT_ERR_INTERNAL), + FDT_ERRTABENT(FDT_ERR_BADNCELLS), + FDT_ERRTABENT(FDT_ERR_BADVALUE), + FDT_ERRTABENT(FDT_ERR_BADOVERLAY), + FDT_ERRTABENT(FDT_ERR_NOPHANDLES), +}; +#define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0])) + +const char *fdt_strerror(int errval) +{ + if (errval > 0) + return "<valid offset/length>"; + else if (errval == 0) + return "<no error>"; + else if (errval > -FDT_ERRTABSIZE) { + const char *s = fdt_errtable[-errval].str; + + if (s) + return s; + } + + return "<unknown error>"; +} diff --git a/scripts/dtc/libfdt/fdt_sw.c b/scripts/dtc/libfdt/fdt_sw.c new file mode 100644 index 0000000000..2bd15e7aef --- /dev/null +++ b/scripts/dtc/libfdt/fdt_sw.c @@ -0,0 +1,300 @@ +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * libfdt is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Alternatively, + * + * b) Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "libfdt_env.h" + +#include <fdt.h> +#include <libfdt.h> + +#include "libfdt_internal.h" + +static int _fdt_sw_check_header(void *fdt) +{ + if (fdt_magic(fdt) != FDT_SW_MAGIC) + return -FDT_ERR_BADMAGIC; + /* FIXME: should check more details about the header state */ + return 0; +} + +#define FDT_SW_CHECK_HEADER(fdt) \ + { \ + int err; \ + if ((err = _fdt_sw_check_header(fdt)) != 0) \ + return err; \ + } + +static void *_fdt_grab_space(void *fdt, size_t len) +{ + int offset = fdt_size_dt_struct(fdt); + int spaceleft; + + spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt) + - fdt_size_dt_strings(fdt); + + if ((offset + len < offset) || (offset + len > spaceleft)) + return NULL; + + fdt_set_size_dt_struct(fdt, offset + len); + return _fdt_offset_ptr_w(fdt, offset); +} + +int fdt_create(void *buf, int bufsize) +{ + void *fdt = buf; + + if (bufsize < sizeof(struct fdt_header)) + return -FDT_ERR_NOSPACE; + + memset(buf, 0, bufsize); + + fdt_set_magic(fdt, FDT_SW_MAGIC); + fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION); + fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION); + fdt_set_totalsize(fdt, bufsize); + + fdt_set_off_mem_rsvmap(fdt, FDT_ALIGN(sizeof(struct fdt_header), + sizeof(struct fdt_reserve_entry))); + fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt)); + fdt_set_off_dt_strings(fdt, bufsize); + + return 0; +} + +int fdt_resize(void *fdt, void *buf, int bufsize) +{ + size_t headsize, tailsize; + char *oldtail, *newtail; + + FDT_SW_CHECK_HEADER(fdt); + + headsize = fdt_off_dt_struct(fdt); + tailsize = fdt_size_dt_strings(fdt); + + if ((headsize + tailsize) > bufsize) + return -FDT_ERR_NOSPACE; + + oldtail = (char *)fdt + fdt_totalsize(fdt) - tailsize; + newtail = (char *)buf + bufsize - tailsize; + + /* Two cases to avoid clobbering data if the old and new + * buffers partially overlap */ + if (buf <= fdt) { + memmove(buf, fdt, headsize); + memmove(newtail, oldtail, tailsize); + } else { + memmove(newtail, oldtail, tailsize); + memmove(buf, fdt, headsize); + } + + fdt_set_off_dt_strings(buf, bufsize); + fdt_set_totalsize(buf, bufsize); + + return 0; +} + +int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size) +{ + struct fdt_reserve_entry *re; + int offset; + + FDT_SW_CHECK_HEADER(fdt); + + if (fdt_size_dt_struct(fdt)) + return -FDT_ERR_BADSTATE; + + offset = fdt_off_dt_struct(fdt); + if ((offset + sizeof(*re)) > fdt_totalsize(fdt)) + return -FDT_ERR_NOSPACE; + + re = (struct fdt_reserve_entry *)((char *)fdt + offset); + re->address = cpu_to_fdt64(addr); + re->size = cpu_to_fdt64(size); + + fdt_set_off_dt_struct(fdt, offset + sizeof(*re)); + + return 0; +} + +int fdt_finish_reservemap(void *fdt) +{ + return fdt_add_reservemap_entry(fdt, 0, 0); +} + +int fdt_begin_node(void *fdt, const char *name) +{ + struct fdt_node_header *nh; + int namelen = strlen(name) + 1; + + FDT_SW_CHECK_HEADER(fdt); + + nh = _fdt_grab_space(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen)); + if (! nh) + return -FDT_ERR_NOSPACE; + + nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); + memcpy(nh->name, name, namelen); + return 0; +} + +int fdt_end_node(void *fdt) +{ + fdt32_t *en; + + FDT_SW_CHECK_HEADER(fdt); + + en = _fdt_grab_space(fdt, FDT_TAGSIZE); + if (! en) + return -FDT_ERR_NOSPACE; + + *en = cpu_to_fdt32(FDT_END_NODE); + return 0; +} + +static int _fdt_find_add_string(void *fdt, const char *s) +{ + char *strtab = (char *)fdt + fdt_totalsize(fdt); + const char *p; + int strtabsize = fdt_size_dt_strings(fdt); + int len = strlen(s) + 1; + int struct_top, offset; + + p = _fdt_find_string(strtab - strtabsize, strtabsize, s); + if (p) + return p - strtab; + + /* Add it */ + offset = -strtabsize - len; + struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); + if (fdt_totalsize(fdt) + offset < struct_top) + return 0; /* no more room :( */ + + memcpy(strtab + offset, s, len); + fdt_set_size_dt_strings(fdt, strtabsize + len); + return offset; +} + +int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp) +{ + struct fdt_property *prop; + int nameoff; + + FDT_SW_CHECK_HEADER(fdt); + + nameoff = _fdt_find_add_string(fdt, name); + if (nameoff == 0) + return -FDT_ERR_NOSPACE; + + prop = _fdt_grab_space(fdt, sizeof(*prop) + FDT_TAGALIGN(len)); + if (! prop) + return -FDT_ERR_NOSPACE; + + prop->tag = cpu_to_fdt32(FDT_PROP); + prop->nameoff = cpu_to_fdt32(nameoff); + prop->len = cpu_to_fdt32(len); + *valp = prop->data; + return 0; +} + +int fdt_property(void *fdt, const char *name, const void *val, int len) +{ + void *ptr; + int ret; + + ret = fdt_property_placeholder(fdt, name, len, &ptr); + if (ret) + return ret; + memcpy(ptr, val, len); + return 0; +} + +int fdt_finish(void *fdt) +{ + char *p = (char *)fdt; + fdt32_t *end; + int oldstroffset, newstroffset; + uint32_t tag; + int offset, nextoffset; + + FDT_SW_CHECK_HEADER(fdt); + + /* Add terminator */ + end = _fdt_grab_space(fdt, sizeof(*end)); + if (! end) + return -FDT_ERR_NOSPACE; + *end = cpu_to_fdt32(FDT_END); + + /* Relocate the string table */ + oldstroffset = fdt_totalsize(fdt) - fdt_size_dt_strings(fdt); + newstroffset = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); + memmove(p + newstroffset, p + oldstroffset, fdt_size_dt_strings(fdt)); + fdt_set_off_dt_strings(fdt, newstroffset); + + /* Walk the structure, correcting string offsets */ + offset = 0; + while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) { + if (tag == FDT_PROP) { + struct fdt_property *prop = + _fdt_offset_ptr_w(fdt, offset); + int nameoff; + + nameoff = fdt32_to_cpu(prop->nameoff); + nameoff += fdt_size_dt_strings(fdt); + prop->nameoff = cpu_to_fdt32(nameoff); + } + offset = nextoffset; + } + if (nextoffset < 0) + return nextoffset; + + /* Finally, adjust the header */ + fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt)); + fdt_set_magic(fdt, FDT_MAGIC); + return 0; +} diff --git a/scripts/dtc/libfdt/fdt_wip.c b/scripts/dtc/libfdt/fdt_wip.c new file mode 100644 index 0000000000..5e85919862 --- /dev/null +++ b/scripts/dtc/libfdt/fdt_wip.c @@ -0,0 +1,139 @@ +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * libfdt is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Alternatively, + * + * b) Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "libfdt_env.h" + +#include <fdt.h> +#include <libfdt.h> + +#include "libfdt_internal.h" + +int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset, + const char *name, int namelen, + uint32_t idx, const void *val, + int len) +{ + void *propval; + int proplen; + + propval = fdt_getprop_namelen_w(fdt, nodeoffset, name, namelen, + &proplen); + if (!propval) + return proplen; + + if (proplen < (len + idx)) + return -FDT_ERR_NOSPACE; + + memcpy((char *)propval + idx, val, len); + return 0; +} + +int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, + const void *val, int len) +{ + const void *propval; + int proplen; + + propval = fdt_getprop(fdt, nodeoffset, name, &proplen); + if (!propval) + return proplen; + + if (proplen != len) + return -FDT_ERR_NOSPACE; + + return fdt_setprop_inplace_namelen_partial(fdt, nodeoffset, name, + strlen(name), 0, + val, len); +} + +static void _fdt_nop_region(void *start, int len) +{ + fdt32_t *p; + + for (p = start; (char *)p < ((char *)start + len); p++) + *p = cpu_to_fdt32(FDT_NOP); +} + +int fdt_nop_property(void *fdt, int nodeoffset, const char *name) +{ + struct fdt_property *prop; + int len; + + prop = fdt_get_property_w(fdt, nodeoffset, name, &len); + if (!prop) + return len; + + _fdt_nop_region(prop, len + sizeof(*prop)); + + return 0; +} + +int _fdt_node_end_offset(void *fdt, int offset) +{ + int depth = 0; + + while ((offset >= 0) && (depth >= 0)) + offset = fdt_next_node(fdt, offset, &depth); + + return offset; +} + +int fdt_nop_node(void *fdt, int nodeoffset) +{ + int endoffset; + + endoffset = _fdt_node_end_offset(fdt, nodeoffset); + if (endoffset < 0) + return endoffset; + + _fdt_nop_region(fdt_offset_ptr_w(fdt, nodeoffset, 0), + endoffset - nodeoffset); + return 0; +} diff --git a/scripts/dtc/libfdt/libfdt.h b/scripts/dtc/libfdt/libfdt.h new file mode 100644 index 0000000000..7f83023ee1 --- /dev/null +++ b/scripts/dtc/libfdt/libfdt.h @@ -0,0 +1,1899 @@ +#ifndef _LIBFDT_H +#define _LIBFDT_H +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * libfdt is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Alternatively, + * + * b) Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "libfdt_env.h" +#include "fdt.h" + +#define FDT_FIRST_SUPPORTED_VERSION 0x10 +#define FDT_LAST_SUPPORTED_VERSION 0x11 + +/* Error codes: informative error codes */ +#define FDT_ERR_NOTFOUND 1 + /* FDT_ERR_NOTFOUND: The requested node or property does not exist */ +#define FDT_ERR_EXISTS 2 + /* FDT_ERR_EXISTS: Attempted to create a node or property which + * already exists */ +#define FDT_ERR_NOSPACE 3 + /* FDT_ERR_NOSPACE: Operation needed to expand the device + * tree, but its buffer did not have sufficient space to + * contain the expanded tree. Use fdt_open_into() to move the + * device tree to a buffer with more space. */ + +/* Error codes: codes for bad parameters */ +#define FDT_ERR_BADOFFSET 4 + /* FDT_ERR_BADOFFSET: Function was passed a structure block + * offset which is out-of-bounds, or which points to an + * unsuitable part of the structure for the operation. */ +#define FDT_ERR_BADPATH 5 + /* FDT_ERR_BADPATH: Function was passed a badly formatted path + * (e.g. missing a leading / for a function which requires an + * absolute path) */ +#define FDT_ERR_BADPHANDLE 6 + /* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle. + * This can be caused either by an invalid phandle property + * length, or the phandle value was either 0 or -1, which are + * not permitted. */ +#define FDT_ERR_BADSTATE 7 + /* FDT_ERR_BADSTATE: Function was passed an incomplete device + * tree created by the sequential-write functions, which is + * not sufficiently complete for the requested operation. */ + +/* Error codes: codes for bad device tree blobs */ +#define FDT_ERR_TRUNCATED 8 + /* FDT_ERR_TRUNCATED: Structure block of the given device tree + * ends without an FDT_END tag. */ +#define FDT_ERR_BADMAGIC 9 + /* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a + * device tree at all - it is missing the flattened device + * tree magic number. */ +#define FDT_ERR_BADVERSION 10 + /* FDT_ERR_BADVERSION: Given device tree has a version which + * can't be handled by the requested operation. For + * read-write functions, this may mean that fdt_open_into() is + * required to convert the tree to the expected version. */ +#define FDT_ERR_BADSTRUCTURE 11 + /* FDT_ERR_BADSTRUCTURE: Given device tree has a corrupt + * structure block or other serious error (e.g. misnested + * nodes, or subnodes preceding properties). */ +#define FDT_ERR_BADLAYOUT 12 + /* FDT_ERR_BADLAYOUT: For read-write functions, the given + * device tree has it's sub-blocks in an order that the + * function can't handle (memory reserve map, then structure, + * then strings). Use fdt_open_into() to reorganize the tree + * into a form suitable for the read-write operations. */ + +/* "Can't happen" error indicating a bug in libfdt */ +#define FDT_ERR_INTERNAL 13 + /* FDT_ERR_INTERNAL: libfdt has failed an internal assertion. + * Should never be returned, if it is, it indicates a bug in + * libfdt itself. */ + +/* Errors in device tree content */ +#define FDT_ERR_BADNCELLS 14 + /* FDT_ERR_BADNCELLS: Device tree has a #address-cells, #size-cells + * or similar property with a bad format or value */ + +#define FDT_ERR_BADVALUE 15 + /* FDT_ERR_BADVALUE: Device tree has a property with an unexpected + * value. For example: a property expected to contain a string list + * is not NUL-terminated within the length of its value. */ + +#define FDT_ERR_BADOVERLAY 16 + /* FDT_ERR_BADOVERLAY: The device tree overlay, while + * correctly structured, cannot be applied due to some + * unexpected or missing value, property or node. */ + +#define FDT_ERR_NOPHANDLES 17 + /* FDT_ERR_NOPHANDLES: The device tree doesn't have any + * phandle available anymore without causing an overflow */ + +#define FDT_ERR_MAX 17 + +/**********************************************************************/ +/* Low-level functions (you probably don't need these) */ +/**********************************************************************/ + +#ifndef SWIG /* This function is not useful in Python */ +const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen); +#endif +static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen) +{ + return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen); +} + +uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset); + +/**********************************************************************/ +/* Traversal functions */ +/**********************************************************************/ + +int fdt_next_node(const void *fdt, int offset, int *depth); + +/** + * fdt_first_subnode() - get offset of first direct subnode + * + * @fdt: FDT blob + * @offset: Offset of node to check + * @return offset of first subnode, or -FDT_ERR_NOTFOUND if there is none + */ +int fdt_first_subnode(const void *fdt, int offset); + +/** + * fdt_next_subnode() - get offset of next direct subnode + * + * After first calling fdt_first_subnode(), call this function repeatedly to + * get direct subnodes of a parent node. + * + * @fdt: FDT blob + * @offset: Offset of previous subnode + * @return offset of next subnode, or -FDT_ERR_NOTFOUND if there are no more + * subnodes + */ +int fdt_next_subnode(const void *fdt, int offset); + +/** + * fdt_for_each_subnode - iterate over all subnodes of a parent + * + * @node: child node (int, lvalue) + * @fdt: FDT blob (const void *) + * @parent: parent node (int) + * + * This is actually a wrapper around a for loop and would be used like so: + * + * fdt_for_each_subnode(node, fdt, parent) { + * Use node + * ... + * } + * + * if ((node < 0) && (node != -FDT_ERR_NOT_FOUND)) { + * Error handling + * } + * + * Note that this is implemented as a macro and @node is used as + * iterator in the loop. The parent variable be constant or even a + * literal. + * + */ +#define fdt_for_each_subnode(node, fdt, parent) \ + for (node = fdt_first_subnode(fdt, parent); \ + node >= 0; \ + node = fdt_next_subnode(fdt, node)) + +/**********************************************************************/ +/* General functions */ +/**********************************************************************/ +#define fdt_get_header(fdt, field) \ + (fdt32_to_cpu(((const struct fdt_header *)(fdt))->field)) +#define fdt_magic(fdt) (fdt_get_header(fdt, magic)) +#define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize)) +#define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct)) +#define fdt_off_dt_strings(fdt) (fdt_get_header(fdt, off_dt_strings)) +#define fdt_off_mem_rsvmap(fdt) (fdt_get_header(fdt, off_mem_rsvmap)) +#define fdt_version(fdt) (fdt_get_header(fdt, version)) +#define fdt_last_comp_version(fdt) (fdt_get_header(fdt, last_comp_version)) +#define fdt_boot_cpuid_phys(fdt) (fdt_get_header(fdt, boot_cpuid_phys)) +#define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings)) +#define fdt_size_dt_struct(fdt) (fdt_get_header(fdt, size_dt_struct)) + +#define __fdt_set_hdr(name) \ + static inline void fdt_set_##name(void *fdt, uint32_t val) \ + { \ + struct fdt_header *fdth = (struct fdt_header *)fdt; \ + fdth->name = cpu_to_fdt32(val); \ + } +__fdt_set_hdr(magic); +__fdt_set_hdr(totalsize); +__fdt_set_hdr(off_dt_struct); +__fdt_set_hdr(off_dt_strings); +__fdt_set_hdr(off_mem_rsvmap); +__fdt_set_hdr(version); +__fdt_set_hdr(last_comp_version); +__fdt_set_hdr(boot_cpuid_phys); +__fdt_set_hdr(size_dt_strings); +__fdt_set_hdr(size_dt_struct); +#undef __fdt_set_hdr + +/** + * fdt_check_header - sanity check a device tree or possible device tree + * @fdt: pointer to data which might be a flattened device tree + * + * fdt_check_header() checks that the given buffer contains what + * appears to be a flattened device tree with sane information in its + * header. + * + * returns: + * 0, if the buffer appears to contain a valid device tree + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, standard meanings, as above + */ +int fdt_check_header(const void *fdt); + +/** + * fdt_move - move a device tree around in memory + * @fdt: pointer to the device tree to move + * @buf: pointer to memory where the device is to be moved + * @bufsize: size of the memory space at buf + * + * fdt_move() relocates, if possible, the device tree blob located at + * fdt to the buffer at buf of size bufsize. The buffer may overlap + * with the existing device tree blob at fdt. Therefore, + * fdt_move(fdt, fdt, fdt_totalsize(fdt)) + * should always succeed. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, bufsize is insufficient to contain the device tree + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, standard meanings + */ +int fdt_move(const void *fdt, void *buf, int bufsize); + +/**********************************************************************/ +/* Read-only functions */ +/**********************************************************************/ + +/** + * fdt_string - retrieve a string from the strings block of a device tree + * @fdt: pointer to the device tree blob + * @stroffset: offset of the string within the strings block (native endian) + * + * fdt_string() retrieves a pointer to a single string from the + * strings block of the device tree blob at fdt. + * + * returns: + * a pointer to the string, on success + * NULL, if stroffset is out of bounds + */ +const char *fdt_string(const void *fdt, int stroffset); + +/** + * fdt_get_max_phandle - retrieves the highest phandle in a tree + * @fdt: pointer to the device tree blob + * + * fdt_get_max_phandle retrieves the highest phandle in the given + * device tree. This will ignore badly formatted phandles, or phandles + * with a value of 0 or -1. + * + * returns: + * the highest phandle on success + * 0, if no phandle was found in the device tree + * -1, if an error occurred + */ +uint32_t fdt_get_max_phandle(const void *fdt); + +/** + * fdt_num_mem_rsv - retrieve the number of memory reserve map entries + * @fdt: pointer to the device tree blob + * + * Returns the number of entries in the device tree blob's memory + * reservation map. This does not include the terminating 0,0 entry + * or any other (0,0) entries reserved for expansion. + * + * returns: + * the number of entries + */ +int fdt_num_mem_rsv(const void *fdt); + +/** + * fdt_get_mem_rsv - retrieve one memory reserve map entry + * @fdt: pointer to the device tree blob + * @address, @size: pointers to 64-bit variables + * + * On success, *address and *size will contain the address and size of + * the n-th reserve map entry from the device tree blob, in + * native-endian format. + * + * returns: + * 0, on success + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, standard meanings + */ +int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size); + +/** + * fdt_subnode_offset_namelen - find a subnode based on substring + * @fdt: pointer to the device tree blob + * @parentoffset: structure block offset of a node + * @name: name of the subnode to locate + * @namelen: number of characters of name to consider + * + * Identical to fdt_subnode_offset(), but only examine the first + * namelen characters of name for matching the subnode name. This is + * useful for finding subnodes based on a portion of a larger string, + * such as a full path. + */ +#ifndef SWIG /* Not available in Python */ +int fdt_subnode_offset_namelen(const void *fdt, int parentoffset, + const char *name, int namelen); +#endif +/** + * fdt_subnode_offset - find a subnode of a given node + * @fdt: pointer to the device tree blob + * @parentoffset: structure block offset of a node + * @name: name of the subnode to locate + * + * fdt_subnode_offset() finds a subnode of the node at structure block + * offset parentoffset with the given name. name may include a unit + * address, in which case fdt_subnode_offset() will find the subnode + * with that unit address, or the unit address may be omitted, in + * which case fdt_subnode_offset() will find an arbitrary subnode + * whose name excluding unit address matches the given name. + * + * returns: + * structure block offset of the requested subnode (>=0), on success + * -FDT_ERR_NOTFOUND, if the requested subnode does not exist + * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE + * tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings. + */ +int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name); + +/** + * fdt_path_offset_namelen - find a tree node by its full path + * @fdt: pointer to the device tree blob + * @path: full path of the node to locate + * @namelen: number of characters of path to consider + * + * Identical to fdt_path_offset(), but only consider the first namelen + * characters of path as the path name. + */ +#ifndef SWIG /* Not available in Python */ +int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen); +#endif + +/** + * fdt_path_offset - find a tree node by its full path + * @fdt: pointer to the device tree blob + * @path: full path of the node to locate + * + * fdt_path_offset() finds a node of a given path in the device tree. + * Each path component may omit the unit address portion, but the + * results of this are undefined if any such path component is + * ambiguous (that is if there are multiple nodes at the relevant + * level matching the given component, differentiated only by unit + * address). + * + * returns: + * structure block offset of the node with the requested path (>=0), on + * success + * -FDT_ERR_BADPATH, given path does not begin with '/' or is invalid + * -FDT_ERR_NOTFOUND, if the requested node does not exist + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings. + */ +int fdt_path_offset(const void *fdt, const char *path); + +/** + * fdt_get_name - retrieve the name of a given node + * @fdt: pointer to the device tree blob + * @nodeoffset: structure block offset of the starting node + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * fdt_get_name() retrieves the name (including unit address) of the + * device tree node at structure block offset nodeoffset. If lenp is + * non-NULL, the length of this name is also returned, in the integer + * pointed to by lenp. + * + * returns: + * pointer to the node's name, on success + * If lenp is non-NULL, *lenp contains the length of that name + * (>=0) + * NULL, on error + * if lenp is non-NULL *lenp contains an error code (<0): + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE + * tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, standard meanings + */ +const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp); + +/** + * fdt_first_property_offset - find the offset of a node's first property + * @fdt: pointer to the device tree blob + * @nodeoffset: structure block offset of a node + * + * fdt_first_property_offset() finds the first property of the node at + * the given structure block offset. + * + * returns: + * structure block offset of the property (>=0), on success + * -FDT_ERR_NOTFOUND, if the requested node has no properties + * -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings. + */ +int fdt_first_property_offset(const void *fdt, int nodeoffset); + +/** + * fdt_next_property_offset - step through a node's properties + * @fdt: pointer to the device tree blob + * @offset: structure block offset of a property + * + * fdt_next_property_offset() finds the property immediately after the + * one at the given structure block offset. This will be a property + * of the same node as the given property. + * + * returns: + * structure block offset of the next property (>=0), on success + * -FDT_ERR_NOTFOUND, if the given property is the last in its node + * -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_PROP tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings. + */ +int fdt_next_property_offset(const void *fdt, int offset); + +/** + * fdt_for_each_property_offset - iterate over all properties of a node + * + * @property_offset: property offset (int, lvalue) + * @fdt: FDT blob (const void *) + * @node: node offset (int) + * + * This is actually a wrapper around a for loop and would be used like so: + * + * fdt_for_each_property_offset(property, fdt, node) { + * Use property + * ... + * } + * + * if ((property < 0) && (property != -FDT_ERR_NOT_FOUND)) { + * Error handling + * } + * + * Note that this is implemented as a macro and property is used as + * iterator in the loop. The node variable can be constant or even a + * literal. + */ +#define fdt_for_each_property_offset(property, fdt, node) \ + for (property = fdt_first_property_offset(fdt, node); \ + property >= 0; \ + property = fdt_next_property_offset(fdt, property)) + +/** + * fdt_get_property_by_offset - retrieve the property at a given offset + * @fdt: pointer to the device tree blob + * @offset: offset of the property to retrieve + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * fdt_get_property_by_offset() retrieves a pointer to the + * fdt_property structure within the device tree blob at the given + * offset. If lenp is non-NULL, the length of the property value is + * also returned, in the integer pointed to by lenp. + * + * returns: + * pointer to the structure representing the property + * if lenp is non-NULL, *lenp contains the length of the property + * value (>=0) + * NULL, on error + * if lenp is non-NULL, *lenp contains an error code (<0): + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +const struct fdt_property *fdt_get_property_by_offset(const void *fdt, + int offset, + int *lenp); + +/** + * fdt_get_property_namelen - find a property based on substring + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to find + * @name: name of the property to find + * @namelen: number of characters of name to consider + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * Identical to fdt_get_property(), but only examine the first namelen + * characters of name for matching the property name. + */ +#ifndef SWIG /* Not available in Python */ +const struct fdt_property *fdt_get_property_namelen(const void *fdt, + int nodeoffset, + const char *name, + int namelen, int *lenp); +#endif + +/** + * fdt_get_property - find a given property in a given node + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to find + * @name: name of the property to find + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * fdt_get_property() retrieves a pointer to the fdt_property + * structure within the device tree blob corresponding to the property + * named 'name' of the node at offset nodeoffset. If lenp is + * non-NULL, the length of the property value is also returned, in the + * integer pointed to by lenp. + * + * returns: + * pointer to the structure representing the property + * if lenp is non-NULL, *lenp contains the length of the property + * value (>=0) + * NULL, on error + * if lenp is non-NULL, *lenp contains an error code (<0): + * -FDT_ERR_NOTFOUND, node does not have named property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE + * tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +const struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset, + const char *name, int *lenp); +static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset, + const char *name, + int *lenp) +{ + return (struct fdt_property *)(uintptr_t) + fdt_get_property(fdt, nodeoffset, name, lenp); +} + +/** + * fdt_getprop_by_offset - retrieve the value of a property at a given offset + * @fdt: pointer to the device tree blob + * @ffset: offset of the property to read + * @namep: pointer to a string variable (will be overwritten) or NULL + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * fdt_getprop_by_offset() retrieves a pointer to the value of the + * property at structure block offset 'offset' (this will be a pointer + * to within the device blob itself, not a copy of the value). If + * lenp is non-NULL, the length of the property value is also + * returned, in the integer pointed to by lenp. If namep is non-NULL, + * the property's namne will also be returned in the char * pointed to + * by namep (this will be a pointer to within the device tree's string + * block, not a new copy of the name). + * + * returns: + * pointer to the property's value + * if lenp is non-NULL, *lenp contains the length of the property + * value (>=0) + * if namep is non-NULL *namep contiains a pointer to the property + * name. + * NULL, on error + * if lenp is non-NULL, *lenp contains an error code (<0): + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +#ifndef SWIG /* This function is not useful in Python */ +const void *fdt_getprop_by_offset(const void *fdt, int offset, + const char **namep, int *lenp); +#endif + +/** + * fdt_getprop_namelen - get property value based on substring + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to find + * @name: name of the property to find + * @namelen: number of characters of name to consider + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * Identical to fdt_getprop(), but only examine the first namelen + * characters of name for matching the property name. + */ +#ifndef SWIG /* Not available in Python */ +const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, + const char *name, int namelen, int *lenp); +static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset, + const char *name, int namelen, + int *lenp) +{ + return (void *)(uintptr_t)fdt_getprop_namelen(fdt, nodeoffset, name, + namelen, lenp); +} +#endif + +/** + * fdt_getprop - retrieve the value of a given property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to find + * @name: name of the property to find + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * fdt_getprop() retrieves a pointer to the value of the property + * named 'name' of the node at offset nodeoffset (this will be a + * pointer to within the device blob itself, not a copy of the value). + * If lenp is non-NULL, the length of the property value is also + * returned, in the integer pointed to by lenp. + * + * returns: + * pointer to the property's value + * if lenp is non-NULL, *lenp contains the length of the property + * value (>=0) + * NULL, on error + * if lenp is non-NULL, *lenp contains an error code (<0): + * -FDT_ERR_NOTFOUND, node does not have named property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE + * tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +const void *fdt_getprop(const void *fdt, int nodeoffset, + const char *name, int *lenp); +static inline void *fdt_getprop_w(void *fdt, int nodeoffset, + const char *name, int *lenp) +{ + return (void *)(uintptr_t)fdt_getprop(fdt, nodeoffset, name, lenp); +} + +/** + * fdt_get_phandle - retrieve the phandle of a given node + * @fdt: pointer to the device tree blob + * @nodeoffset: structure block offset of the node + * + * fdt_get_phandle() retrieves the phandle of the device tree node at + * structure block offset nodeoffset. + * + * returns: + * the phandle of the node at nodeoffset, on success (!= 0, != -1) + * 0, if the node has no phandle, or another error occurs + */ +uint32_t fdt_get_phandle(const void *fdt, int nodeoffset); + +/** + * fdt_get_alias_namelen - get alias based on substring + * @fdt: pointer to the device tree blob + * @name: name of the alias th look up + * @namelen: number of characters of name to consider + * + * Identical to fdt_get_alias(), but only examine the first namelen + * characters of name for matching the alias name. + */ +#ifndef SWIG /* Not available in Python */ +const char *fdt_get_alias_namelen(const void *fdt, + const char *name, int namelen); +#endif + +/** + * fdt_get_alias - retrieve the path referenced by a given alias + * @fdt: pointer to the device tree blob + * @name: name of the alias th look up + * + * fdt_get_alias() retrieves the value of a given alias. That is, the + * value of the property named 'name' in the node /aliases. + * + * returns: + * a pointer to the expansion of the alias named 'name', if it exists + * NULL, if the given alias or the /aliases node does not exist + */ +const char *fdt_get_alias(const void *fdt, const char *name); + +/** + * fdt_get_path - determine the full path of a node + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose path to find + * @buf: character buffer to contain the returned path (will be overwritten) + * @buflen: size of the character buffer at buf + * + * fdt_get_path() computes the full path of the node at offset + * nodeoffset, and records that path in the buffer at buf. + * + * NOTE: This function is expensive, as it must scan the device tree + * structure from the start to nodeoffset. + * + * returns: + * 0, on success + * buf contains the absolute path of the node at + * nodeoffset, as a NUL-terminated string. + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_NOSPACE, the path of the given node is longer than (bufsize-1) + * characters and will not fit in the given buffer. + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ +int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen); + +/** + * fdt_supernode_atdepth_offset - find a specific ancestor of a node + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose parent to find + * @supernodedepth: depth of the ancestor to find + * @nodedepth: pointer to an integer variable (will be overwritten) or NULL + * + * fdt_supernode_atdepth_offset() finds an ancestor of the given node + * at a specific depth from the root (where the root itself has depth + * 0, its immediate subnodes depth 1 and so forth). So + * fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, NULL); + * will always return 0, the offset of the root node. If the node at + * nodeoffset has depth D, then: + * fdt_supernode_atdepth_offset(fdt, nodeoffset, D, NULL); + * will return nodeoffset itself. + * + * NOTE: This function is expensive, as it must scan the device tree + * structure from the start to nodeoffset. + * + * returns: + * structure block offset of the node at node offset's ancestor + * of depth supernodedepth (>=0), on success + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of + * nodeoffset + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ +int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, + int supernodedepth, int *nodedepth); + +/** + * fdt_node_depth - find the depth of a given node + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose parent to find + * + * fdt_node_depth() finds the depth of a given node. The root node + * has depth 0, its immediate subnodes depth 1 and so forth. + * + * NOTE: This function is expensive, as it must scan the device tree + * structure from the start to nodeoffset. + * + * returns: + * depth of the node at nodeoffset (>=0), on success + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ +int fdt_node_depth(const void *fdt, int nodeoffset); + +/** + * fdt_parent_offset - find the parent of a given node + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose parent to find + * + * fdt_parent_offset() locates the parent node of a given node (that + * is, it finds the offset of the node which contains the node at + * nodeoffset as a subnode). + * + * NOTE: This function is expensive, as it must scan the device tree + * structure from the start to nodeoffset, *twice*. + * + * returns: + * structure block offset of the parent of the node at nodeoffset + * (>=0), on success + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ +int fdt_parent_offset(const void *fdt, int nodeoffset); + +/** + * fdt_node_offset_by_prop_value - find nodes with a given property value + * @fdt: pointer to the device tree blob + * @startoffset: only find nodes after this offset + * @propname: property name to check + * @propval: property value to search for + * @proplen: length of the value in propval + * + * fdt_node_offset_by_prop_value() returns the offset of the first + * node after startoffset, which has a property named propname whose + * value is of length proplen and has value equal to propval; or if + * startoffset is -1, the very first such node in the tree. + * + * To iterate through all nodes matching the criterion, the following + * idiom can be used: + * offset = fdt_node_offset_by_prop_value(fdt, -1, propname, + * propval, proplen); + * while (offset != -FDT_ERR_NOTFOUND) { + * // other code here + * offset = fdt_node_offset_by_prop_value(fdt, offset, propname, + * propval, proplen); + * } + * + * Note the -1 in the first call to the function, if 0 is used here + * instead, the function will never locate the root node, even if it + * matches the criterion. + * + * returns: + * structure block offset of the located node (>= 0, >startoffset), + * on success + * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the + * tree after startoffset + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ +int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, + const char *propname, + const void *propval, int proplen); + +/** + * fdt_node_offset_by_phandle - find the node with a given phandle + * @fdt: pointer to the device tree blob + * @phandle: phandle value + * + * fdt_node_offset_by_phandle() returns the offset of the node + * which has the given phandle value. If there is more than one node + * in the tree with the given phandle (an invalid tree), results are + * undefined. + * + * returns: + * structure block offset of the located node (>= 0), on success + * -FDT_ERR_NOTFOUND, no node with that phandle exists + * -FDT_ERR_BADPHANDLE, given phandle value was invalid (0 or -1) + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ +int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle); + +/** + * fdt_node_check_compatible: check a node's compatible property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of a tree node + * @compatible: string to match against + * + * + * fdt_node_check_compatible() returns 0 if the given node contains a + * 'compatible' property with the given string as one of its elements, + * it returns non-zero otherwise, or on error. + * + * returns: + * 0, if the node has a 'compatible' property listing the given string + * 1, if the node has a 'compatible' property, but it does not list + * the given string + * -FDT_ERR_NOTFOUND, if the given node has no 'compatible' property + * -FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ +int fdt_node_check_compatible(const void *fdt, int nodeoffset, + const char *compatible); + +/** + * fdt_node_offset_by_compatible - find nodes with a given 'compatible' value + * @fdt: pointer to the device tree blob + * @startoffset: only find nodes after this offset + * @compatible: 'compatible' string to match against + * + * fdt_node_offset_by_compatible() returns the offset of the first + * node after startoffset, which has a 'compatible' property which + * lists the given compatible string; or if startoffset is -1, the + * very first such node in the tree. + * + * To iterate through all nodes matching the criterion, the following + * idiom can be used: + * offset = fdt_node_offset_by_compatible(fdt, -1, compatible); + * while (offset != -FDT_ERR_NOTFOUND) { + * // other code here + * offset = fdt_node_offset_by_compatible(fdt, offset, compatible); + * } + * + * Note the -1 in the first call to the function, if 0 is used here + * instead, the function will never locate the root node, even if it + * matches the criterion. + * + * returns: + * structure block offset of the located node (>= 0, >startoffset), + * on success + * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the + * tree after startoffset + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ +int fdt_node_offset_by_compatible(const void *fdt, int startoffset, + const char *compatible); + +/** + * fdt_stringlist_contains - check a string list property for a string + * @strlist: Property containing a list of strings to check + * @listlen: Length of property + * @str: String to search for + * + * This is a utility function provided for convenience. The list contains + * one or more strings, each terminated by \0, as is found in a device tree + * "compatible" property. + * + * @return: 1 if the string is found in the list, 0 not found, or invalid list + */ +int fdt_stringlist_contains(const char *strlist, int listlen, const char *str); + +/** + * fdt_stringlist_count - count the number of strings in a string list + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of a tree node + * @property: name of the property containing the string list + * @return: + * the number of strings in the given property + * -FDT_ERR_BADVALUE if the property value is not NUL-terminated + * -FDT_ERR_NOTFOUND if the property does not exist + */ +int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property); + +/** + * fdt_stringlist_search - find a string in a string list and return its index + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of a tree node + * @property: name of the property containing the string list + * @string: string to look up in the string list + * + * Note that it is possible for this function to succeed on property values + * that are not NUL-terminated. That's because the function will stop after + * finding the first occurrence of @string. This can for example happen with + * small-valued cell properties, such as #address-cells, when searching for + * the empty string. + * + * @return: + * the index of the string in the list of strings + * -FDT_ERR_BADVALUE if the property value is not NUL-terminated + * -FDT_ERR_NOTFOUND if the property does not exist or does not contain + * the given string + */ +int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property, + const char *string); + +/** + * fdt_stringlist_get() - obtain the string at a given index in a string list + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of a tree node + * @property: name of the property containing the string list + * @index: index of the string to return + * @lenp: return location for the string length or an error code on failure + * + * Note that this will successfully extract strings from properties with + * non-NUL-terminated values. For example on small-valued cell properties + * this function will return the empty string. + * + * If non-NULL, the length of the string (on success) or a negative error-code + * (on failure) will be stored in the integer pointer to by lenp. + * + * @return: + * A pointer to the string at the given index in the string list or NULL on + * failure. On success the length of the string will be stored in the memory + * location pointed to by the lenp parameter, if non-NULL. On failure one of + * the following negative error codes will be returned in the lenp parameter + * (if non-NULL): + * -FDT_ERR_BADVALUE if the property value is not NUL-terminated + * -FDT_ERR_NOTFOUND if the property does not exist + */ +const char *fdt_stringlist_get(const void *fdt, int nodeoffset, + const char *property, int index, + int *lenp); + +/**********************************************************************/ +/* Read-only functions (addressing related) */ +/**********************************************************************/ + +/** + * FDT_MAX_NCELLS - maximum value for #address-cells and #size-cells + * + * This is the maximum value for #address-cells, #size-cells and + * similar properties that will be processed by libfdt. IEE1275 + * requires that OF implementations handle values up to 4. + * Implementations may support larger values, but in practice higher + * values aren't used. + */ +#define FDT_MAX_NCELLS 4 + +/** + * fdt_address_cells - retrieve address size for a bus represented in the tree + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node to find the address size for + * + * When the node has a valid #address-cells property, returns its value. + * + * returns: + * 0 <= n < FDT_MAX_NCELLS, on success + * 2, if the node has no #address-cells property + * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid + * #address-cells property + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_address_cells(const void *fdt, int nodeoffset); + +/** + * fdt_size_cells - retrieve address range size for a bus represented in the + * tree + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node to find the address range size for + * + * When the node has a valid #size-cells property, returns its value. + * + * returns: + * 0 <= n < FDT_MAX_NCELLS, on success + * 2, if the node has no #address-cells property + * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid + * #size-cells property + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_size_cells(const void *fdt, int nodeoffset); + + +/**********************************************************************/ +/* Write-in-place functions */ +/**********************************************************************/ + +/** + * fdt_setprop_inplace_namelen_partial - change a property's value, + * but not its size + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @namelen: number of characters of name to consider + * @idx: index of the property to change in the array + * @val: pointer to data to replace the property value with + * @len: length of the property value + * + * Identical to fdt_setprop_inplace(), but modifies the given property + * starting from the given index, and using only the first characters + * of the name. It is useful when you want to manipulate only one value of + * an array and you have a string that doesn't end with \0. + */ +#ifndef SWIG /* Not available in Python */ +int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset, + const char *name, int namelen, + uint32_t idx, const void *val, + int len); +#endif + +/** + * fdt_setprop_inplace - change a property's value, but not its size + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: pointer to data to replace the property value with + * @len: length of the property value + * + * fdt_setprop_inplace() replaces the value of a given property with + * the data in val, of length len. This function cannot change the + * size of a property, and so will only work if len is equal to the + * current length of the property. + * + * This function will alter only the bytes in the blob which contain + * the given property value, and will not alter or move any other part + * of the tree. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, if len is not equal to the property's current length + * -FDT_ERR_NOTFOUND, node does not have the named property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +#ifndef SWIG /* Not available in Python */ +int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, + const void *val, int len); +#endif + +/** + * fdt_setprop_inplace_u32 - change the value of a 32-bit integer property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: 32-bit integer value to replace the property with + * + * fdt_setprop_inplace_u32() replaces the value of a given property + * with the 32-bit integer value in val, converting val to big-endian + * if necessary. This function cannot change the size of a property, + * and so will only work if the property already exists and has length + * 4. + * + * This function will alter only the bytes in the blob which contain + * the given property value, and will not alter or move any other part + * of the tree. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, if the property's length is not equal to 4 + * -FDT_ERR_NOTFOUND, node does not have the named property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +static inline int fdt_setprop_inplace_u32(void *fdt, int nodeoffset, + const char *name, uint32_t val) +{ + fdt32_t tmp = cpu_to_fdt32(val); + return fdt_setprop_inplace(fdt, nodeoffset, name, &tmp, sizeof(tmp)); +} + +/** + * fdt_setprop_inplace_u64 - change the value of a 64-bit integer property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: 64-bit integer value to replace the property with + * + * fdt_setprop_inplace_u64() replaces the value of a given property + * with the 64-bit integer value in val, converting val to big-endian + * if necessary. This function cannot change the size of a property, + * and so will only work if the property already exists and has length + * 8. + * + * This function will alter only the bytes in the blob which contain + * the given property value, and will not alter or move any other part + * of the tree. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, if the property's length is not equal to 8 + * -FDT_ERR_NOTFOUND, node does not have the named property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +static inline int fdt_setprop_inplace_u64(void *fdt, int nodeoffset, + const char *name, uint64_t val) +{ + fdt64_t tmp = cpu_to_fdt64(val); + return fdt_setprop_inplace(fdt, nodeoffset, name, &tmp, sizeof(tmp)); +} + +/** + * fdt_setprop_inplace_cell - change the value of a single-cell property + * + * This is an alternative name for fdt_setprop_inplace_u32() + */ +static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset, + const char *name, uint32_t val) +{ + return fdt_setprop_inplace_u32(fdt, nodeoffset, name, val); +} + +/** + * fdt_nop_property - replace a property with nop tags + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to nop + * @name: name of the property to nop + * + * fdt_nop_property() will replace a given property's representation + * in the blob with FDT_NOP tags, effectively removing it from the + * tree. + * + * This function will alter only the bytes in the blob which contain + * the property, and will not alter or move any other part of the + * tree. + * + * returns: + * 0, on success + * -FDT_ERR_NOTFOUND, node does not have the named property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_nop_property(void *fdt, int nodeoffset, const char *name); + +/** + * fdt_nop_node - replace a node (subtree) with nop tags + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node to nop + * + * fdt_nop_node() will replace a given node's representation in the + * blob, including all its subnodes, if any, with FDT_NOP tags, + * effectively removing it from the tree. + * + * This function will alter only the bytes in the blob which contain + * the node and its properties and subnodes, and will not alter or + * move any other part of the tree. + * + * returns: + * 0, on success + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_nop_node(void *fdt, int nodeoffset); + +/**********************************************************************/ +/* Sequential write functions */ +/**********************************************************************/ + +int fdt_create(void *buf, int bufsize); +int fdt_resize(void *fdt, void *buf, int bufsize); +int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size); +int fdt_finish_reservemap(void *fdt); +int fdt_begin_node(void *fdt, const char *name); +int fdt_property(void *fdt, const char *name, const void *val, int len); +static inline int fdt_property_u32(void *fdt, const char *name, uint32_t val) +{ + fdt32_t tmp = cpu_to_fdt32(val); + return fdt_property(fdt, name, &tmp, sizeof(tmp)); +} +static inline int fdt_property_u64(void *fdt, const char *name, uint64_t val) +{ + fdt64_t tmp = cpu_to_fdt64(val); + return fdt_property(fdt, name, &tmp, sizeof(tmp)); +} +static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val) +{ + return fdt_property_u32(fdt, name, val); +} + +/** + * fdt_property_placeholder - add a new property and return a ptr to its value + * + * @fdt: pointer to the device tree blob + * @name: name of property to add + * @len: length of property value in bytes + * @valp: returns a pointer to where where the value should be placed + * + * returns: + * 0, on success + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_NOSPACE, standard meanings + */ +int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp); + +#define fdt_property_string(fdt, name, str) \ + fdt_property(fdt, name, str, strlen(str)+1) +int fdt_end_node(void *fdt); +int fdt_finish(void *fdt); + +/**********************************************************************/ +/* Read-write functions */ +/**********************************************************************/ + +int fdt_create_empty_tree(void *buf, int bufsize); +int fdt_open_into(const void *fdt, void *buf, int bufsize); +int fdt_pack(void *fdt); + +/** + * fdt_add_mem_rsv - add one memory reserve map entry + * @fdt: pointer to the device tree blob + * @address, @size: 64-bit values (native endian) + * + * Adds a reserve map entry to the given blob reserving a region at + * address address of length size. + * + * This function will insert data into the reserve map and will + * therefore change the indexes of some entries in the table. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new reservation entry + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size); + +/** + * fdt_del_mem_rsv - remove a memory reserve map entry + * @fdt: pointer to the device tree blob + * @n: entry to remove + * + * fdt_del_mem_rsv() removes the n-th memory reserve map entry from + * the blob. + * + * This function will delete data from the reservation table and will + * therefore change the indexes of some entries in the table. + * + * returns: + * 0, on success + * -FDT_ERR_NOTFOUND, there is no entry of the given index (i.e. there + * are less than n+1 reserve map entries) + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_del_mem_rsv(void *fdt, int n); + +/** + * fdt_set_name - change the name of a given node + * @fdt: pointer to the device tree blob + * @nodeoffset: structure block offset of a node + * @name: name to give the node + * + * fdt_set_name() replaces the name (including unit address, if any) + * of the given node with the given string. NOTE: this function can't + * efficiently check if the new name is unique amongst the given + * node's siblings; results are undefined if this function is invoked + * with a name equal to one of the given node's siblings. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob + * to contain the new name + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, standard meanings + */ +int fdt_set_name(void *fdt, int nodeoffset, const char *name); + +/** + * fdt_setprop - create or change a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: pointer to data to set the property value to + * @len: length of the property value + * + * fdt_setprop() sets the value of the named property in the given + * node to the given value and length, creating the property if it + * does not already exist. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_setprop(void *fdt, int nodeoffset, const char *name, + const void *val, int len); + +/** + * fdt_setprop _placeholder - allocate space for a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @len: length of the property value + * @prop_data: return pointer to property data + * + * fdt_setprop_placeholer() allocates the named property in the given node. + * If the property exists it is resized. In either case a pointer to the + * property data is returned. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name, + int len, void **prop_data); + +/** + * fdt_setprop_u32 - set a property to a 32-bit integer + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: 32-bit integer value for the property (native endian) + * + * fdt_setprop_u32() sets the value of the named property in the given + * node to the given 32-bit integer value (converting to big-endian if + * necessary), or creates a new property with that value if it does + * not already exist. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +static inline int fdt_setprop_u32(void *fdt, int nodeoffset, const char *name, + uint32_t val) +{ + fdt32_t tmp = cpu_to_fdt32(val); + return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); +} + +/** + * fdt_setprop_u64 - set a property to a 64-bit integer + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: 64-bit integer value for the property (native endian) + * + * fdt_setprop_u64() sets the value of the named property in the given + * node to the given 64-bit integer value (converting to big-endian if + * necessary), or creates a new property with that value if it does + * not already exist. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +static inline int fdt_setprop_u64(void *fdt, int nodeoffset, const char *name, + uint64_t val) +{ + fdt64_t tmp = cpu_to_fdt64(val); + return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); +} + +/** + * fdt_setprop_cell - set a property to a single cell value + * + * This is an alternative name for fdt_setprop_u32() + */ +static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name, + uint32_t val) +{ + return fdt_setprop_u32(fdt, nodeoffset, name, val); +} + +/** + * fdt_setprop_string - set a property to a string value + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @str: string value for the property + * + * fdt_setprop_string() sets the value of the named property in the + * given node to the given string value (using the length of the + * string to determine the new length of the property), or creates a + * new property with that value if it does not already exist. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +#define fdt_setprop_string(fdt, nodeoffset, name, str) \ + fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) + + +/** + * fdt_setprop_empty - set a property to an empty value + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * + * fdt_setprop_empty() sets the value of the named property in the + * given node to an empty (zero length) value, or creates a new empty + * property if it does not already exist. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +#define fdt_setprop_empty(fdt, nodeoffset, name) \ + fdt_setprop((fdt), (nodeoffset), (name), NULL, 0) + +/** + * fdt_appendprop - append to or create a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to append to + * @val: pointer to data to append to the property value + * @len: length of the data to append to the property value + * + * fdt_appendprop() appends the value to the named property in the + * given node, creating the property if it does not already exist. + * + * This function may insert data into the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_appendprop(void *fdt, int nodeoffset, const char *name, + const void *val, int len); + +/** + * fdt_appendprop_u32 - append a 32-bit integer value to a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: 32-bit integer value to append to the property (native endian) + * + * fdt_appendprop_u32() appends the given 32-bit integer value + * (converting to big-endian if necessary) to the value of the named + * property in the given node, or creates a new property with that + * value if it does not already exist. + * + * This function may insert data into the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +static inline int fdt_appendprop_u32(void *fdt, int nodeoffset, + const char *name, uint32_t val) +{ + fdt32_t tmp = cpu_to_fdt32(val); + return fdt_appendprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); +} + +/** + * fdt_appendprop_u64 - append a 64-bit integer value to a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: 64-bit integer value to append to the property (native endian) + * + * fdt_appendprop_u64() appends the given 64-bit integer value + * (converting to big-endian if necessary) to the value of the named + * property in the given node, or creates a new property with that + * value if it does not already exist. + * + * This function may insert data into the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +static inline int fdt_appendprop_u64(void *fdt, int nodeoffset, + const char *name, uint64_t val) +{ + fdt64_t tmp = cpu_to_fdt64(val); + return fdt_appendprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); +} + +/** + * fdt_appendprop_cell - append a single cell value to a property + * + * This is an alternative name for fdt_appendprop_u32() + */ +static inline int fdt_appendprop_cell(void *fdt, int nodeoffset, + const char *name, uint32_t val) +{ + return fdt_appendprop_u32(fdt, nodeoffset, name, val); +} + +/** + * fdt_appendprop_string - append a string to a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @str: string value to append to the property + * + * fdt_appendprop_string() appends the given string to the value of + * the named property in the given node, or creates a new property + * with that value if it does not already exist. + * + * This function may insert data into the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +#define fdt_appendprop_string(fdt, nodeoffset, name, str) \ + fdt_appendprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) + +/** + * fdt_delprop - delete a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to nop + * @name: name of the property to nop + * + * fdt_del_property() will delete the given property. + * + * This function will delete data from the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOTFOUND, node does not have the named property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_delprop(void *fdt, int nodeoffset, const char *name); + +/** + * fdt_add_subnode_namelen - creates a new node based on substring + * @fdt: pointer to the device tree blob + * @parentoffset: structure block offset of a node + * @name: name of the subnode to locate + * @namelen: number of characters of name to consider + * + * Identical to fdt_add_subnode(), but use only the first namelen + * characters of name as the name of the new node. This is useful for + * creating subnodes based on a portion of a larger string, such as a + * full path. + */ +#ifndef SWIG /* Not available in Python */ +int fdt_add_subnode_namelen(void *fdt, int parentoffset, + const char *name, int namelen); +#endif + +/** + * fdt_add_subnode - creates a new node + * @fdt: pointer to the device tree blob + * @parentoffset: structure block offset of a node + * @name: name of the subnode to locate + * + * fdt_add_subnode() creates a new node as a subnode of the node at + * structure block offset parentoffset, with the given name (which + * should include the unit address, if any). + * + * This function will insert data into the blob, and will therefore + * change the offsets of some existing nodes. + + * returns: + * structure block offset of the created nodeequested subnode (>=0), on + * success + * -FDT_ERR_NOTFOUND, if the requested subnode does not exist + * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE + * tag + * -FDT_ERR_EXISTS, if the node at parentoffset already has a subnode of + * the given name + * -FDT_ERR_NOSPACE, if there is insufficient free space in the + * blob to contain the new node + * -FDT_ERR_NOSPACE + * -FDT_ERR_BADLAYOUT + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings. + */ +int fdt_add_subnode(void *fdt, int parentoffset, const char *name); + +/** + * fdt_del_node - delete a node (subtree) + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node to nop + * + * fdt_del_node() will remove the given node, including all its + * subnodes if any, from the blob. + * + * This function will delete data from the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_del_node(void *fdt, int nodeoffset); + +/** + * fdt_overlay_apply - Applies a DT overlay on a base DT + * @fdt: pointer to the base device tree blob + * @fdto: pointer to the device tree overlay blob + * + * fdt_overlay_apply() will apply the given device tree overlay on the + * given base device tree. + * + * Expect the base device tree to be modified, even if the function + * returns an error. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there's not enough space in the base device tree + * -FDT_ERR_NOTFOUND, the overlay points to some inexistant nodes or + * properties in the base DT + * -FDT_ERR_BADPHANDLE, + * -FDT_ERR_BADOVERLAY, + * -FDT_ERR_NOPHANDLES, + * -FDT_ERR_INTERNAL, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADOFFSET, + * -FDT_ERR_BADPATH, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_overlay_apply(void *fdt, void *fdto); + +/**********************************************************************/ +/* Debugging / informational functions */ +/**********************************************************************/ + +const char *fdt_strerror(int errval); + +#endif /* _LIBFDT_H */ diff --git a/scripts/dtc/libfdt/libfdt_env.h b/scripts/dtc/libfdt/libfdt_env.h new file mode 100644 index 0000000000..952056cddf --- /dev/null +++ b/scripts/dtc/libfdt/libfdt_env.h @@ -0,0 +1,112 @@ +#ifndef _LIBFDT_ENV_H +#define _LIBFDT_ENV_H +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * Copyright 2012 Kim Phillips, Freescale Semiconductor. + * + * libfdt is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Alternatively, + * + * b) Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stddef.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +#ifdef __CHECKER__ +#define FDT_FORCE __attribute__((force)) +#define FDT_BITWISE __attribute__((bitwise)) +#else +#define FDT_FORCE +#define FDT_BITWISE +#endif + +typedef uint16_t FDT_BITWISE fdt16_t; +typedef uint32_t FDT_BITWISE fdt32_t; +typedef uint64_t FDT_BITWISE fdt64_t; + +#define EXTRACT_BYTE(x, n) ((unsigned long long)((uint8_t *)&x)[n]) +#define CPU_TO_FDT16(x) ((EXTRACT_BYTE(x, 0) << 8) | EXTRACT_BYTE(x, 1)) +#define CPU_TO_FDT32(x) ((EXTRACT_BYTE(x, 0) << 24) | (EXTRACT_BYTE(x, 1) << 16) | \ + (EXTRACT_BYTE(x, 2) << 8) | EXTRACT_BYTE(x, 3)) +#define CPU_TO_FDT64(x) ((EXTRACT_BYTE(x, 0) << 56) | (EXTRACT_BYTE(x, 1) << 48) | \ + (EXTRACT_BYTE(x, 2) << 40) | (EXTRACT_BYTE(x, 3) << 32) | \ + (EXTRACT_BYTE(x, 4) << 24) | (EXTRACT_BYTE(x, 5) << 16) | \ + (EXTRACT_BYTE(x, 6) << 8) | EXTRACT_BYTE(x, 7)) + +static inline uint16_t fdt16_to_cpu(fdt16_t x) +{ + return (FDT_FORCE uint16_t)CPU_TO_FDT16(x); +} +static inline fdt16_t cpu_to_fdt16(uint16_t x) +{ + return (FDT_FORCE fdt16_t)CPU_TO_FDT16(x); +} + +static inline uint32_t fdt32_to_cpu(fdt32_t x) +{ + return (FDT_FORCE uint32_t)CPU_TO_FDT32(x); +} +static inline fdt32_t cpu_to_fdt32(uint32_t x) +{ + return (FDT_FORCE fdt32_t)CPU_TO_FDT32(x); +} + +static inline uint64_t fdt64_to_cpu(fdt64_t x) +{ + return (FDT_FORCE uint64_t)CPU_TO_FDT64(x); +} +static inline fdt64_t cpu_to_fdt64(uint64_t x) +{ + return (FDT_FORCE fdt64_t)CPU_TO_FDT64(x); +} +#undef CPU_TO_FDT64 +#undef CPU_TO_FDT32 +#undef CPU_TO_FDT16 +#undef EXTRACT_BYTE + +#endif /* _LIBFDT_ENV_H */ diff --git a/scripts/dtc/libfdt/libfdt_internal.h b/scripts/dtc/libfdt/libfdt_internal.h new file mode 100644 index 0000000000..02cfa6fb61 --- /dev/null +++ b/scripts/dtc/libfdt/libfdt_internal.h @@ -0,0 +1,95 @@ +#ifndef _LIBFDT_INTERNAL_H +#define _LIBFDT_INTERNAL_H +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * libfdt is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Alternatively, + * + * b) Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include <fdt.h> + +#define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) +#define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE)) + +#define FDT_CHECK_HEADER(fdt) \ + { \ + int __err; \ + if ((__err = fdt_check_header(fdt)) != 0) \ + return __err; \ + } + +int _fdt_check_node_offset(const void *fdt, int offset); +int _fdt_check_prop_offset(const void *fdt, int offset); +const char *_fdt_find_string(const char *strtab, int tabsize, const char *s); +int _fdt_node_end_offset(void *fdt, int nodeoffset); + +static inline const void *_fdt_offset_ptr(const void *fdt, int offset) +{ + return (const char *)fdt + fdt_off_dt_struct(fdt) + offset; +} + +static inline void *_fdt_offset_ptr_w(void *fdt, int offset) +{ + return (void *)(uintptr_t)_fdt_offset_ptr(fdt, offset); +} + +static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int n) +{ + const struct fdt_reserve_entry *rsv_table = + (const struct fdt_reserve_entry *) + ((const char *)fdt + fdt_off_mem_rsvmap(fdt)); + + return rsv_table + n; +} +static inline struct fdt_reserve_entry *_fdt_mem_rsv_w(void *fdt, int n) +{ + return (void *)(uintptr_t)_fdt_mem_rsv(fdt, n); +} + +#define FDT_SW_MAGIC (~FDT_MAGIC) + +#endif /* _LIBFDT_INTERNAL_H */ diff --git a/scripts/dtc/livetree.c b/scripts/dtc/livetree.c new file mode 100644 index 0000000000..aecd27875f --- /dev/null +++ b/scripts/dtc/livetree.c @@ -0,0 +1,981 @@ +/* + * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005. + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#include "dtc.h" + +/* + * Tree building functions + */ + +void add_label(struct label **labels, char *label) +{ + struct label *new; + + /* Make sure the label isn't already there */ + for_each_label_withdel(*labels, new) + if (streq(new->label, label)) { + new->deleted = 0; + return; + } + + new = xmalloc(sizeof(*new)); + memset(new, 0, sizeof(*new)); + new->label = label; + new->next = *labels; + *labels = new; +} + +void delete_labels(struct label **labels) +{ + struct label *label; + + for_each_label(*labels, label) + label->deleted = 1; +} + +struct property *build_property(char *name, struct data val) +{ + struct property *new = xmalloc(sizeof(*new)); + + memset(new, 0, sizeof(*new)); + + new->name = name; + new->val = val; + + return new; +} + +struct property *build_property_delete(char *name) +{ + struct property *new = xmalloc(sizeof(*new)); + + memset(new, 0, sizeof(*new)); + + new->name = name; + new->deleted = 1; + + return new; +} + +struct property *chain_property(struct property *first, struct property *list) +{ + assert(first->next == NULL); + + first->next = list; + return first; +} + +struct property *reverse_properties(struct property *first) +{ + struct property *p = first; + struct property *head = NULL; + struct property *next; + + while (p) { + next = p->next; + p->next = head; + head = p; + p = next; + } + return head; +} + +struct node *build_node(struct property *proplist, struct node *children) +{ + struct node *new = xmalloc(sizeof(*new)); + struct node *child; + + memset(new, 0, sizeof(*new)); + + new->proplist = reverse_properties(proplist); + new->children = children; + + for_each_child(new, child) { + child->parent = new; + } + + return new; +} + +struct node *build_node_delete(void) +{ + struct node *new = xmalloc(sizeof(*new)); + + memset(new, 0, sizeof(*new)); + + new->deleted = 1; + + return new; +} + +struct node *name_node(struct node *node, char *name) +{ + assert(node->name == NULL); + + node->name = name; + + return node; +} + +struct node *merge_nodes(struct node *old_node, struct node *new_node) +{ + struct property *new_prop, *old_prop; + struct node *new_child, *old_child; + struct label *l; + + old_node->deleted = 0; + + /* Add new node labels to old node */ + for_each_label_withdel(new_node->labels, l) + add_label(&old_node->labels, l->label); + + /* Move properties from the new node to the old node. If there + * is a collision, replace the old value with the new */ + while (new_node->proplist) { + /* Pop the property off the list */ + new_prop = new_node->proplist; + new_node->proplist = new_prop->next; + new_prop->next = NULL; + + if (new_prop->deleted) { + delete_property_by_name(old_node, new_prop->name); + free(new_prop); + continue; + } + + /* Look for a collision, set new value if there is */ + for_each_property_withdel(old_node, old_prop) { + if (streq(old_prop->name, new_prop->name)) { + /* Add new labels to old property */ + for_each_label_withdel(new_prop->labels, l) + add_label(&old_prop->labels, l->label); + + old_prop->val = new_prop->val; + old_prop->deleted = 0; + free(new_prop); + new_prop = NULL; + break; + } + } + + /* if no collision occurred, add property to the old node. */ + if (new_prop) + add_property(old_node, new_prop); + } + + /* Move the override child nodes into the primary node. If + * there is a collision, then merge the nodes. */ + while (new_node->children) { + /* Pop the child node off the list */ + new_child = new_node->children; + new_node->children = new_child->next_sibling; + new_child->parent = NULL; + new_child->next_sibling = NULL; + + if (new_child->deleted) { + delete_node_by_name(old_node, new_child->name); + free(new_child); + continue; + } + + /* Search for a collision. Merge if there is */ + for_each_child_withdel(old_node, old_child) { + if (streq(old_child->name, new_child->name)) { + merge_nodes(old_child, new_child); + new_child = NULL; + break; + } + } + + /* if no collision occurred, add child to the old node. */ + if (new_child) + add_child(old_node, new_child); + } + + /* The new node contents are now merged into the old node. Free + * the new node. */ + free(new_node); + + return old_node; +} + +struct node *chain_node(struct node *first, struct node *list) +{ + assert(first->next_sibling == NULL); + + first->next_sibling = list; + return first; +} + +void add_property(struct node *node, struct property *prop) +{ + struct property **p; + + prop->next = NULL; + + p = &node->proplist; + while (*p) + p = &((*p)->next); + + *p = prop; +} + +void delete_property_by_name(struct node *node, char *name) +{ + struct property *prop = node->proplist; + + while (prop) { + if (streq(prop->name, name)) { + delete_property(prop); + return; + } + prop = prop->next; + } +} + +void delete_property(struct property *prop) +{ + prop->deleted = 1; + delete_labels(&prop->labels); +} + +void add_child(struct node *parent, struct node *child) +{ + struct node **p; + + child->next_sibling = NULL; + child->parent = parent; + + p = &parent->children; + while (*p) + p = &((*p)->next_sibling); + + *p = child; +} + +void delete_node_by_name(struct node *parent, char *name) +{ + struct node *node = parent->children; + + while (node) { + if (streq(node->name, name)) { + delete_node(node); + return; + } + node = node->next_sibling; + } +} + +void delete_node(struct node *node) +{ + struct property *prop; + struct node *child; + + node->deleted = 1; + for_each_child(node, child) + delete_node(child); + for_each_property(node, prop) + delete_property(prop); + delete_labels(&node->labels); +} + +void append_to_property(struct node *node, + char *name, const void *data, int len) +{ + struct data d; + struct property *p; + + p = get_property(node, name); + if (p) { + d = data_append_data(p->val, data, len); + p->val = d; + } else { + d = data_append_data(empty_data, data, len); + p = build_property(name, d); + add_property(node, p); + } +} + +struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size) +{ + struct reserve_info *new = xmalloc(sizeof(*new)); + + memset(new, 0, sizeof(*new)); + + new->address = address; + new->size = size; + + return new; +} + +struct reserve_info *chain_reserve_entry(struct reserve_info *first, + struct reserve_info *list) +{ + assert(first->next == NULL); + + first->next = list; + return first; +} + +struct reserve_info *add_reserve_entry(struct reserve_info *list, + struct reserve_info *new) +{ + struct reserve_info *last; + + new->next = NULL; + + if (! list) + return new; + + for (last = list; last->next; last = last->next) + ; + + last->next = new; + + return list; +} + +struct dt_info *build_dt_info(unsigned int dtsflags, + struct reserve_info *reservelist, + struct node *tree, uint32_t boot_cpuid_phys) +{ + struct dt_info *dti; + + dti = xmalloc(sizeof(*dti)); + dti->dtsflags = dtsflags; + dti->reservelist = reservelist; + dti->dt = tree; + dti->boot_cpuid_phys = boot_cpuid_phys; + + return dti; +} + +/* + * Tree accessor functions + */ + +const char *get_unitname(struct node *node) +{ + if (node->name[node->basenamelen] == '\0') + return ""; + else + return node->name + node->basenamelen + 1; +} + +struct property *get_property(struct node *node, const char *propname) +{ + struct property *prop; + + for_each_property(node, prop) + if (streq(prop->name, propname)) + return prop; + + return NULL; +} + +cell_t propval_cell(struct property *prop) +{ + assert(prop->val.len == sizeof(cell_t)); + return fdt32_to_cpu(*((fdt32_t *)prop->val.val)); +} + +struct property *get_property_by_label(struct node *tree, const char *label, + struct node **node) +{ + struct property *prop; + struct node *c; + + *node = tree; + + for_each_property(tree, prop) { + struct label *l; + + for_each_label(prop->labels, l) + if (streq(l->label, label)) + return prop; + } + + for_each_child(tree, c) { + prop = get_property_by_label(c, label, node); + if (prop) + return prop; + } + + *node = NULL; + return NULL; +} + +struct marker *get_marker_label(struct node *tree, const char *label, + struct node **node, struct property **prop) +{ + struct marker *m; + struct property *p; + struct node *c; + + *node = tree; + + for_each_property(tree, p) { + *prop = p; + m = p->val.markers; + for_each_marker_of_type(m, LABEL) + if (streq(m->ref, label)) + return m; + } + + for_each_child(tree, c) { + m = get_marker_label(c, label, node, prop); + if (m) + return m; + } + + *prop = NULL; + *node = NULL; + return NULL; +} + +struct node *get_subnode(struct node *node, const char *nodename) +{ + struct node *child; + + for_each_child(node, child) + if (streq(child->name, nodename)) + return child; + + return NULL; +} + +struct node *get_node_by_path(struct node *tree, const char *path) +{ + const char *p; + struct node *child; + + if (!path || ! (*path)) { + if (tree->deleted) + return NULL; + return tree; + } + + while (path[0] == '/') + path++; + + p = strchr(path, '/'); + + for_each_child(tree, child) { + if (p && (strlen(child->name) == p-path) && + strneq(path, child->name, p-path)) + return get_node_by_path(child, p+1); + else if (!p && streq(path, child->name)) + return child; + } + + return NULL; +} + +struct node *get_node_by_label(struct node *tree, const char *label) +{ + struct node *child, *node; + struct label *l; + + assert(label && (strlen(label) > 0)); + + for_each_label(tree->labels, l) + if (streq(l->label, label)) + return tree; + + for_each_child(tree, child) { + node = get_node_by_label(child, label); + if (node) + return node; + } + + return NULL; +} + +struct node *get_node_by_phandle(struct node *tree, cell_t phandle) +{ + struct node *child, *node; + + assert((phandle != 0) && (phandle != -1)); + + if (tree->phandle == phandle) { + if (tree->deleted) + return NULL; + return tree; + } + + for_each_child(tree, child) { + node = get_node_by_phandle(child, phandle); + if (node) + return node; + } + + return NULL; +} + +struct node *get_node_by_ref(struct node *tree, const char *ref) +{ + if (streq(ref, "/")) + return tree; + else if (ref[0] == '/') + return get_node_by_path(tree, ref); + else + return get_node_by_label(tree, ref); +} + +cell_t get_node_phandle(struct node *root, struct node *node) +{ + static cell_t phandle = 1; /* FIXME: ick, static local */ + + if ((node->phandle != 0) && (node->phandle != -1)) + return node->phandle; + + while (get_node_by_phandle(root, phandle)) + phandle++; + + node->phandle = phandle; + + if (!get_property(node, "linux,phandle") + && (phandle_format & PHANDLE_LEGACY)) + add_property(node, + build_property("linux,phandle", + data_append_cell(empty_data, phandle))); + + if (!get_property(node, "phandle") + && (phandle_format & PHANDLE_EPAPR)) + add_property(node, + build_property("phandle", + data_append_cell(empty_data, phandle))); + + /* If the node *does* have a phandle property, we must + * be dealing with a self-referencing phandle, which will be + * fixed up momentarily in the caller */ + + return node->phandle; +} + +uint32_t guess_boot_cpuid(struct node *tree) +{ + struct node *cpus, *bootcpu; + struct property *reg; + + cpus = get_node_by_path(tree, "/cpus"); + if (!cpus) + return 0; + + + bootcpu = cpus->children; + if (!bootcpu) + return 0; + + reg = get_property(bootcpu, "reg"); + if (!reg || (reg->val.len != sizeof(uint32_t))) + return 0; + + /* FIXME: Sanity check node? */ + + return propval_cell(reg); +} + +static int cmp_reserve_info(const void *ax, const void *bx) +{ + const struct reserve_info *a, *b; + + a = *((const struct reserve_info * const *)ax); + b = *((const struct reserve_info * const *)bx); + + if (a->address < b->address) + return -1; + else if (a->address > b->address) + return 1; + else if (a->size < b->size) + return -1; + else if (a->size > b->size) + return 1; + else + return 0; +} + +static void sort_reserve_entries(struct dt_info *dti) +{ + struct reserve_info *ri, **tbl; + int n = 0, i = 0; + + for (ri = dti->reservelist; + ri; + ri = ri->next) + n++; + + if (n == 0) + return; + + tbl = xmalloc(n * sizeof(*tbl)); + + for (ri = dti->reservelist; + ri; + ri = ri->next) + tbl[i++] = ri; + + qsort(tbl, n, sizeof(*tbl), cmp_reserve_info); + + dti->reservelist = tbl[0]; + for (i = 0; i < (n-1); i++) + tbl[i]->next = tbl[i+1]; + tbl[n-1]->next = NULL; + + free(tbl); +} + +static int cmp_prop(const void *ax, const void *bx) +{ + const struct property *a, *b; + + a = *((const struct property * const *)ax); + b = *((const struct property * const *)bx); + + return strcmp(a->name, b->name); +} + +static void sort_properties(struct node *node) +{ + int n = 0, i = 0; + struct property *prop, **tbl; + + for_each_property_withdel(node, prop) + n++; + + if (n == 0) + return; + + tbl = xmalloc(n * sizeof(*tbl)); + + for_each_property_withdel(node, prop) + tbl[i++] = prop; + + qsort(tbl, n, sizeof(*tbl), cmp_prop); + + node->proplist = tbl[0]; + for (i = 0; i < (n-1); i++) + tbl[i]->next = tbl[i+1]; + tbl[n-1]->next = NULL; + + free(tbl); +} + +static int cmp_subnode(const void *ax, const void *bx) +{ + const struct node *a, *b; + + a = *((const struct node * const *)ax); + b = *((const struct node * const *)bx); + + return strcmp(a->name, b->name); +} + +static void sort_subnodes(struct node *node) +{ + int n = 0, i = 0; + struct node *subnode, **tbl; + + for_each_child_withdel(node, subnode) + n++; + + if (n == 0) + return; + + tbl = xmalloc(n * sizeof(*tbl)); + + for_each_child_withdel(node, subnode) + tbl[i++] = subnode; + + qsort(tbl, n, sizeof(*tbl), cmp_subnode); + + node->children = tbl[0]; + for (i = 0; i < (n-1); i++) + tbl[i]->next_sibling = tbl[i+1]; + tbl[n-1]->next_sibling = NULL; + + free(tbl); +} + +static void sort_node(struct node *node) +{ + struct node *c; + + sort_properties(node); + sort_subnodes(node); + for_each_child_withdel(node, c) + sort_node(c); +} + +void sort_tree(struct dt_info *dti) +{ + sort_reserve_entries(dti); + sort_node(dti->dt); +} + +/* utility helper to avoid code duplication */ +static struct node *build_and_name_child_node(struct node *parent, char *name) +{ + struct node *node; + + node = build_node(NULL, NULL); + name_node(node, xstrdup(name)); + add_child(parent, node); + + return node; +} + +static struct node *build_root_node(struct node *dt, char *name) +{ + struct node *an; + + an = get_subnode(dt, name); + if (!an) + an = build_and_name_child_node(dt, name); + + if (!an) + die("Could not build root node /%s\n", name); + + return an; +} + +static bool any_label_tree(struct dt_info *dti, struct node *node) +{ + struct node *c; + + if (node->labels) + return true; + + for_each_child(node, c) + if (any_label_tree(dti, c)) + return true; + + return false; +} + +static void generate_label_tree_internal(struct dt_info *dti, + struct node *an, struct node *node, + bool allocph) +{ + struct node *dt = dti->dt; + struct node *c; + struct property *p; + struct label *l; + + /* if there are labels */ + if (node->labels) { + + /* now add the label in the node */ + for_each_label(node->labels, l) { + + /* check whether the label already exists */ + p = get_property(an, l->label); + if (p) { + fprintf(stderr, "WARNING: label %s already" + " exists in /%s", l->label, + an->name); + continue; + } + + /* insert it */ + p = build_property(l->label, + data_copy_mem(node->fullpath, + strlen(node->fullpath) + 1)); + add_property(an, p); + } + + /* force allocation of a phandle for this node */ + if (allocph) + (void)get_node_phandle(dt, node); + } + + for_each_child(node, c) + generate_label_tree_internal(dti, an, c, allocph); +} + +static bool any_fixup_tree(struct dt_info *dti, struct node *node) +{ + struct node *c; + struct property *prop; + struct marker *m; + + for_each_property(node, prop) { + m = prop->val.markers; + for_each_marker_of_type(m, REF_PHANDLE) { + if (!get_node_by_ref(dti->dt, m->ref)) + return true; + } + } + + for_each_child(node, c) { + if (any_fixup_tree(dti, c)) + return true; + } + + return false; +} + +static void add_fixup_entry(struct dt_info *dti, struct node *fn, + struct node *node, struct property *prop, + struct marker *m) +{ + char *entry; + + /* m->ref can only be a REF_PHANDLE, but check anyway */ + assert(m->type == REF_PHANDLE); + + /* there shouldn't be any ':' in the arguments */ + if (strchr(node->fullpath, ':') || strchr(prop->name, ':')) + die("arguments should not contain ':'\n"); + + xasprintf(&entry, "%s:%s:%u", + node->fullpath, prop->name, m->offset); + append_to_property(fn, m->ref, entry, strlen(entry) + 1); + + free(entry); +} + +static void generate_fixups_tree_internal(struct dt_info *dti, + struct node *fn, + struct node *node) +{ + struct node *dt = dti->dt; + struct node *c; + struct property *prop; + struct marker *m; + struct node *refnode; + + for_each_property(node, prop) { + m = prop->val.markers; + for_each_marker_of_type(m, REF_PHANDLE) { + refnode = get_node_by_ref(dt, m->ref); + if (!refnode) + add_fixup_entry(dti, fn, node, prop, m); + } + } + + for_each_child(node, c) + generate_fixups_tree_internal(dti, fn, c); +} + +static bool any_local_fixup_tree(struct dt_info *dti, struct node *node) +{ + struct node *c; + struct property *prop; + struct marker *m; + + for_each_property(node, prop) { + m = prop->val.markers; + for_each_marker_of_type(m, REF_PHANDLE) { + if (get_node_by_ref(dti->dt, m->ref)) + return true; + } + } + + for_each_child(node, c) { + if (any_local_fixup_tree(dti, c)) + return true; + } + + return false; +} + +static void add_local_fixup_entry(struct dt_info *dti, + struct node *lfn, struct node *node, + struct property *prop, struct marker *m, + struct node *refnode) +{ + struct node *wn, *nwn; /* local fixup node, walk node, new */ + fdt32_t value_32; + char **compp; + int i, depth; + + /* walk back retreiving depth */ + depth = 0; + for (wn = node; wn; wn = wn->parent) + depth++; + + /* allocate name array */ + compp = xmalloc(sizeof(*compp) * depth); + + /* store names in the array */ + for (wn = node, i = depth - 1; wn; wn = wn->parent, i--) + compp[i] = wn->name; + + /* walk the path components creating nodes if they don't exist */ + for (wn = lfn, i = 1; i < depth; i++, wn = nwn) { + /* if no node exists, create it */ + nwn = get_subnode(wn, compp[i]); + if (!nwn) + nwn = build_and_name_child_node(wn, compp[i]); + } + + free(compp); + + value_32 = cpu_to_fdt32(m->offset); + append_to_property(wn, prop->name, &value_32, sizeof(value_32)); +} + +static void generate_local_fixups_tree_internal(struct dt_info *dti, + struct node *lfn, + struct node *node) +{ + struct node *dt = dti->dt; + struct node *c; + struct property *prop; + struct marker *m; + struct node *refnode; + + for_each_property(node, prop) { + m = prop->val.markers; + for_each_marker_of_type(m, REF_PHANDLE) { + refnode = get_node_by_ref(dt, m->ref); + if (refnode) + add_local_fixup_entry(dti, lfn, node, prop, m, refnode); + } + } + + for_each_child(node, c) + generate_local_fixups_tree_internal(dti, lfn, c); +} + +void generate_label_tree(struct dt_info *dti, char *name, bool allocph) +{ + if (!any_label_tree(dti, dti->dt)) + return; + generate_label_tree_internal(dti, build_root_node(dti->dt, name), + dti->dt, allocph); +} + +void generate_fixups_tree(struct dt_info *dti, char *name) +{ + if (!any_fixup_tree(dti, dti->dt)) + return; + generate_fixups_tree_internal(dti, build_root_node(dti->dt, name), + dti->dt); +} + +void generate_local_fixups_tree(struct dt_info *dti, char *name) +{ + if (!any_local_fixup_tree(dti, dti->dt)) + return; + generate_local_fixups_tree_internal(dti, build_root_node(dti->dt, name), + dti->dt); +} diff --git a/scripts/dtc/srcpos.c b/scripts/dtc/srcpos.c new file mode 100644 index 0000000000..9d38459902 --- /dev/null +++ b/scripts/dtc/srcpos.c @@ -0,0 +1,302 @@ +/* + * Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#define _GNU_SOURCE + +#include <stdio.h> + +#include "dtc.h" +#include "srcpos.h" + +/* A node in our list of directories to search for source/include files */ +struct search_path { + struct search_path *next; /* next node in list, NULL for end */ + const char *dirname; /* name of directory to search */ +}; + +/* This is the list of directories that we search for source files */ +static struct search_path *search_path_head, **search_path_tail; + + +static char *get_dirname(const char *path) +{ + const char *slash = strrchr(path, '/'); + + if (slash) { + int len = slash - path; + char *dir = xmalloc(len + 1); + + memcpy(dir, path, len); + dir[len] = '\0'; + return dir; + } + return NULL; +} + +FILE *depfile; /* = NULL */ +struct srcfile_state *current_srcfile; /* = NULL */ + +/* Detect infinite include recursion. */ +#define MAX_SRCFILE_DEPTH (100) +static int srcfile_depth; /* = 0 */ + + +/** + * Try to open a file in a given directory. + * + * If the filename is an absolute path, then dirname is ignored. If it is a + * relative path, then we look in that directory for the file. + * + * @param dirname Directory to look in, or NULL for none + * @param fname Filename to look for + * @param fp Set to NULL if file did not open + * @return allocated filename on success (caller must free), NULL on failure + */ +static char *try_open(const char *dirname, const char *fname, FILE **fp) +{ + char *fullname; + + if (!dirname || fname[0] == '/') + fullname = xstrdup(fname); + else + fullname = join_path(dirname, fname); + + *fp = fopen(fullname, "rb"); + if (!*fp) { + free(fullname); + fullname = NULL; + } + + return fullname; +} + +/** + * Open a file for read access + * + * If it is a relative filename, we search the full search path for it. + * + * @param fname Filename to open + * @param fp Returns pointer to opened FILE, or NULL on failure + * @return pointer to allocated filename, which caller must free + */ +static char *fopen_any_on_path(const char *fname, FILE **fp) +{ + const char *cur_dir = NULL; + struct search_path *node; + char *fullname; + + /* Try current directory first */ + assert(fp); + if (current_srcfile) + cur_dir = current_srcfile->dir; + fullname = try_open(cur_dir, fname, fp); + + /* Failing that, try each search path in turn */ + for (node = search_path_head; !*fp && node; node = node->next) + fullname = try_open(node->dirname, fname, fp); + + return fullname; +} + +FILE *srcfile_relative_open(const char *fname, char **fullnamep) +{ + FILE *f; + char *fullname; + + if (streq(fname, "-")) { + f = stdin; + fullname = xstrdup("<stdin>"); + } else { + fullname = fopen_any_on_path(fname, &f); + if (!f) + die("Couldn't open \"%s\": %s\n", fname, + strerror(errno)); + } + + if (depfile) + fprintf(depfile, " %s", fullname); + + if (fullnamep) + *fullnamep = fullname; + else + free(fullname); + + return f; +} + +void srcfile_push(const char *fname) +{ + struct srcfile_state *srcfile; + + if (srcfile_depth++ >= MAX_SRCFILE_DEPTH) + die("Includes nested too deeply"); + + srcfile = xmalloc(sizeof(*srcfile)); + + srcfile->f = srcfile_relative_open(fname, &srcfile->name); + srcfile->dir = get_dirname(srcfile->name); + srcfile->prev = current_srcfile; + + srcfile->lineno = 1; + srcfile->colno = 1; + + current_srcfile = srcfile; +} + +bool srcfile_pop(void) +{ + struct srcfile_state *srcfile = current_srcfile; + + assert(srcfile); + + current_srcfile = srcfile->prev; + + if (fclose(srcfile->f)) + die("Error closing \"%s\": %s\n", srcfile->name, + strerror(errno)); + + /* FIXME: We allow the srcfile_state structure to leak, + * because it could still be referenced from a location + * variable being carried through the parser somewhere. To + * fix this we could either allocate all the files from a + * table, or use a pool allocator. */ + + return current_srcfile ? true : false; +} + +void srcfile_add_search_path(const char *dirname) +{ + struct search_path *node; + + /* Create the node */ + node = xmalloc(sizeof(*node)); + node->next = NULL; + node->dirname = xstrdup(dirname); + + /* Add to the end of our list */ + if (search_path_tail) + *search_path_tail = node; + else + search_path_head = node; + search_path_tail = &node->next; +} + +/* + * The empty source position. + */ + +struct srcpos srcpos_empty = { + .first_line = 0, + .first_column = 0, + .last_line = 0, + .last_column = 0, + .file = NULL, +}; + +#define TAB_SIZE 8 + +void srcpos_update(struct srcpos *pos, const char *text, int len) +{ + int i; + + pos->file = current_srcfile; + + pos->first_line = current_srcfile->lineno; + pos->first_column = current_srcfile->colno; + + for (i = 0; i < len; i++) + if (text[i] == '\n') { + current_srcfile->lineno++; + current_srcfile->colno = 1; + } else if (text[i] == '\t') { + current_srcfile->colno = + ALIGN(current_srcfile->colno, TAB_SIZE); + } else { + current_srcfile->colno++; + } + + pos->last_line = current_srcfile->lineno; + pos->last_column = current_srcfile->colno; +} + +struct srcpos * +srcpos_copy(struct srcpos *pos) +{ + struct srcpos *pos_new; + + pos_new = xmalloc(sizeof(struct srcpos)); + memcpy(pos_new, pos, sizeof(struct srcpos)); + + return pos_new; +} + +char * +srcpos_string(struct srcpos *pos) +{ + const char *fname = "<no-file>"; + char *pos_str; + + if (pos->file && pos->file->name) + fname = pos->file->name; + + + if (pos->first_line != pos->last_line) + xasprintf(&pos_str, "%s:%d.%d-%d.%d", fname, + pos->first_line, pos->first_column, + pos->last_line, pos->last_column); + else if (pos->first_column != pos->last_column) + xasprintf(&pos_str, "%s:%d.%d-%d", fname, + pos->first_line, pos->first_column, + pos->last_column); + else + xasprintf(&pos_str, "%s:%d.%d", fname, + pos->first_line, pos->first_column); + + return pos_str; +} + +void srcpos_verror(struct srcpos *pos, const char *prefix, + const char *fmt, va_list va) +{ + char *srcstr; + + srcstr = srcpos_string(pos); + + fprintf(stderr, "%s: %s ", prefix, srcstr); + vfprintf(stderr, fmt, va); + fprintf(stderr, "\n"); + + free(srcstr); +} + +void srcpos_error(struct srcpos *pos, const char *prefix, + const char *fmt, ...) +{ + va_list va; + + va_start(va, fmt); + srcpos_verror(pos, prefix, fmt, va); + va_end(va); +} + +void srcpos_set_line(char *f, int l) +{ + current_srcfile->name = f; + current_srcfile->lineno = l; +} diff --git a/scripts/dtc/srcpos.h b/scripts/dtc/srcpos.h new file mode 100644 index 0000000000..7caca8257c --- /dev/null +++ b/scripts/dtc/srcpos.h @@ -0,0 +1,117 @@ +/* + * Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#ifndef _SRCPOS_H_ +#define _SRCPOS_H_ + +#include <stdio.h> +#include <stdbool.h> +#include "util.h" + +struct srcfile_state { + FILE *f; + char *name; + char *dir; + int lineno, colno; + struct srcfile_state *prev; +}; + +extern FILE *depfile; /* = NULL */ +extern struct srcfile_state *current_srcfile; /* = NULL */ + +/** + * Open a source file. + * + * If the source file is a relative pathname, then it is searched for in the + * current directory (the directory of the last source file read) and after + * that in the search path. + * + * We work through the search path in order from the first path specified to + * the last. + * + * If the file is not found, then this function does not return, but calls + * die(). + * + * @param fname Filename to search + * @param fullnamep If non-NULL, it is set to the allocated filename of the + * file that was opened. The caller is then responsible + * for freeing the pointer. + * @return pointer to opened FILE + */ +FILE *srcfile_relative_open(const char *fname, char **fullnamep); + +void srcfile_push(const char *fname); +bool srcfile_pop(void); + +/** + * Add a new directory to the search path for input files + * + * The new path is added at the end of the list. + * + * @param dirname Directory to add + */ +void srcfile_add_search_path(const char *dirname); + +struct srcpos { + int first_line; + int first_column; + int last_line; + int last_column; + struct srcfile_state *file; +}; + +#define YYLTYPE struct srcpos + +#define YYLLOC_DEFAULT(Current, Rhs, N) \ + do { \ + if (N) { \ + (Current).first_line = YYRHSLOC(Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC(Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC(Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + (Current).file = YYRHSLOC(Rhs, N).file; \ + } else { \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC(Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC(Rhs, 0).last_column; \ + (Current).file = YYRHSLOC (Rhs, 0).file; \ + } \ + } while (0) + + +/* + * Fictional source position used for IR nodes that are + * created without otherwise knowing a true source position. + * For example,constant definitions from the command line. + */ +extern struct srcpos srcpos_empty; + +extern void srcpos_update(struct srcpos *pos, const char *text, int len); +extern struct srcpos *srcpos_copy(struct srcpos *pos); +extern char *srcpos_string(struct srcpos *pos); + +extern void PRINTF(3, 0) srcpos_verror(struct srcpos *pos, const char *prefix, + const char *fmt, va_list va); +extern void PRINTF(3, 4) srcpos_error(struct srcpos *pos, const char *prefix, + const char *fmt, ...); + +extern void srcpos_set_line(char *f, int l); + +#endif /* _SRCPOS_H_ */ diff --git a/scripts/dtc/treesource.c b/scripts/dtc/treesource.c new file mode 100644 index 0000000000..2461a3d068 --- /dev/null +++ b/scripts/dtc/treesource.c @@ -0,0 +1,284 @@ +/* + * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005. + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#include "dtc.h" +#include "srcpos.h" + +extern FILE *yyin; +extern int yyparse(void); +extern YYLTYPE yylloc; + +struct dt_info *parser_output; +bool treesource_error; + +struct dt_info *dt_from_source(const char *fname) +{ + parser_output = NULL; + treesource_error = false; + + srcfile_push(fname); + yyin = current_srcfile->f; + yylloc.file = current_srcfile; + + if (yyparse() != 0) + die("Unable to parse input tree\n"); + + if (treesource_error) + die("Syntax error parsing input tree\n"); + + return parser_output; +} + +static void write_prefix(FILE *f, int level) +{ + int i; + + for (i = 0; i < level; i++) + fputc('\t', f); +} + +static bool isstring(char c) +{ + return (isprint((unsigned char)c) + || (c == '\0') + || strchr("\a\b\t\n\v\f\r", c)); +} + +static void write_propval_string(FILE *f, struct data val) +{ + const char *str = val.val; + int i; + struct marker *m = val.markers; + + assert(str[val.len-1] == '\0'); + + while (m && (m->offset == 0)) { + if (m->type == LABEL) + fprintf(f, "%s: ", m->ref); + m = m->next; + } + fprintf(f, "\""); + + for (i = 0; i < (val.len-1); i++) { + char c = str[i]; + + switch (c) { + case '\a': + fprintf(f, "\\a"); + break; + case '\b': + fprintf(f, "\\b"); + break; + case '\t': + fprintf(f, "\\t"); + break; + case '\n': + fprintf(f, "\\n"); + break; + case '\v': + fprintf(f, "\\v"); + break; + case '\f': + fprintf(f, "\\f"); + break; + case '\r': + fprintf(f, "\\r"); + break; + case '\\': + fprintf(f, "\\\\"); + break; + case '\"': + fprintf(f, "\\\""); + break; + case '\0': + fprintf(f, "\", "); + while (m && (m->offset <= (i + 1))) { + if (m->type == LABEL) { + assert(m->offset == (i+1)); + fprintf(f, "%s: ", m->ref); + } + m = m->next; + } + fprintf(f, "\""); + break; + default: + if (isprint((unsigned char)c)) + fprintf(f, "%c", c); + else + fprintf(f, "\\x%02hhx", c); + } + } + fprintf(f, "\""); + + /* Wrap up any labels at the end of the value */ + for_each_marker_of_type(m, LABEL) { + assert (m->offset == val.len); + fprintf(f, " %s:", m->ref); + } +} + +static void write_propval_cells(FILE *f, struct data val) +{ + void *propend = val.val + val.len; + fdt32_t *cp = (fdt32_t *)val.val; + struct marker *m = val.markers; + + fprintf(f, "<"); + for (;;) { + while (m && (m->offset <= ((char *)cp - val.val))) { + if (m->type == LABEL) { + assert(m->offset == ((char *)cp - val.val)); + fprintf(f, "%s: ", m->ref); + } + m = m->next; + } + + fprintf(f, "0x%x", fdt32_to_cpu(*cp++)); + if ((void *)cp >= propend) + break; + fprintf(f, " "); + } + + /* Wrap up any labels at the end of the value */ + for_each_marker_of_type(m, LABEL) { + assert (m->offset == val.len); + fprintf(f, " %s:", m->ref); + } + fprintf(f, ">"); +} + +static void write_propval_bytes(FILE *f, struct data val) +{ + void *propend = val.val + val.len; + const char *bp = val.val; + struct marker *m = val.markers; + + fprintf(f, "["); + for (;;) { + while (m && (m->offset == (bp-val.val))) { + if (m->type == LABEL) + fprintf(f, "%s: ", m->ref); + m = m->next; + } + + fprintf(f, "%02hhx", (unsigned char)(*bp++)); + if ((const void *)bp >= propend) + break; + fprintf(f, " "); + } + + /* Wrap up any labels at the end of the value */ + for_each_marker_of_type(m, LABEL) { + assert (m->offset == val.len); + fprintf(f, " %s:", m->ref); + } + fprintf(f, "]"); +} + +static void write_propval(FILE *f, struct property *prop) +{ + int len = prop->val.len; + const char *p = prop->val.val; + struct marker *m = prop->val.markers; + int nnotstring = 0, nnul = 0; + int nnotstringlbl = 0, nnotcelllbl = 0; + int i; + + if (len == 0) { + fprintf(f, ";\n"); + return; + } + + for (i = 0; i < len; i++) { + if (! isstring(p[i])) + nnotstring++; + if (p[i] == '\0') + nnul++; + } + + for_each_marker_of_type(m, LABEL) { + if ((m->offset > 0) && (prop->val.val[m->offset - 1] != '\0')) + nnotstringlbl++; + if ((m->offset % sizeof(cell_t)) != 0) + nnotcelllbl++; + } + + fprintf(f, " = "); + if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul)) + && (nnotstringlbl == 0)) { + write_propval_string(f, prop->val); + } else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) { + write_propval_cells(f, prop->val); + } else { + write_propval_bytes(f, prop->val); + } + + fprintf(f, ";\n"); +} + +static void write_tree_source_node(FILE *f, struct node *tree, int level) +{ + struct property *prop; + struct node *child; + struct label *l; + + write_prefix(f, level); + for_each_label(tree->labels, l) + fprintf(f, "%s: ", l->label); + if (tree->name && (*tree->name)) + fprintf(f, "%s {\n", tree->name); + else + fprintf(f, "/ {\n"); + + for_each_property(tree, prop) { + write_prefix(f, level+1); + for_each_label(prop->labels, l) + fprintf(f, "%s: ", l->label); + fprintf(f, "%s", prop->name); + write_propval(f, prop); + } + for_each_child(tree, child) { + fprintf(f, "\n"); + write_tree_source_node(f, child, level+1); + } + write_prefix(f, level); + fprintf(f, "};\n"); +} + + +void dt_to_source(FILE *f, struct dt_info *dti) +{ + struct reserve_info *re; + + fprintf(f, "/dts-v1/;\n\n"); + + for (re = dti->reservelist; re; re = re->next) { + struct label *l; + + for_each_label(re->labels, l) + fprintf(f, "%s: ", l->label); + fprintf(f, "/memreserve/\t0x%016llx 0x%016llx;\n", + (unsigned long long)re->address, + (unsigned long long)re->size); + } + + write_tree_source_node(f, dti->dt, 0); +} + diff --git a/scripts/dtc/update-dtc-source.sh b/scripts/dtc/update-dtc-source.sh new file mode 100755 index 0000000000..b8ebcc6722 --- /dev/null +++ b/scripts/dtc/update-dtc-source.sh @@ -0,0 +1,81 @@ +#!/bin/sh +# Simple script to update the version of DTC carried by the Linux kernel +# +# This script assumes that the dtc and the linux git trees are in the +# same directory. After building dtc in the dtc directory, it copies the +# source files and generated source files into the scripts/dtc directory +# in the kernel and creates a git commit updating them to the new +# version. +# +# Usage: from the top level Linux source tree, run: +# $ ./scripts/dtc/update-dtc-source.sh +# +# The script will change into the dtc tree, build and test dtc, copy the +# relevant files into the kernel tree and create a git commit. The commit +# message will need to be modified to reflect the version of DTC being +# imported +# +# TODO: +# This script is pretty basic, but it is seldom used so a few manual tasks +# aren't a big deal. If anyone is interested in making it more robust, the +# the following would be nice: +# * Actually fail to complete if any testcase fails. +# - The dtc "make check" target needs to return a failure +# * Extract the version number from the dtc repo for the commit message +# * Build dtc in the kernel tree +# * run 'make check" on dtc built from the kernel tree + +set -ev + +DTC_UPSTREAM_PATH=`pwd`/../dtc +DTC_LINUX_PATH=`pwd`/scripts/dtc + +DTC_SOURCE="checks.c data.c dtc.c dtc.h flattree.c fstree.c livetree.c srcpos.c \ + srcpos.h treesource.c util.c util.h version_gen.h Makefile.dtc \ + dtc-lexer.l dtc-parser.y" +DTC_GENERATED="dtc-lexer.lex.c dtc-parser.tab.c dtc-parser.tab.h" +LIBFDT_SOURCE="Makefile.libfdt fdt.c fdt.h fdt_empty_tree.c fdt_ro.c fdt_rw.c fdt_strerror.c fdt_sw.c fdt_wip.c libfdt.h libfdt_env.h libfdt_internal.h" + +get_last_dtc_version() { + git log --oneline scripts/dtc/ | grep 'upstream' | head -1 | sed -e 's/^.* \(.*\)/\1/' +} + +last_dtc_ver=$(get_last_dtc_version) + +# Build DTC +cd $DTC_UPSTREAM_PATH +make clean +make check +dtc_version=$(git describe HEAD) +dtc_log=$(git log --oneline ${last_dtc_ver}..) + + +# Copy the files into the Linux tree +cd $DTC_LINUX_PATH +for f in $DTC_SOURCE; do + cp ${DTC_UPSTREAM_PATH}/${f} ${f} + git add ${f} +done +for f in $DTC_GENERATED; do + cp ${DTC_UPSTREAM_PATH}/$f ${f}_shipped + git add ${f}_shipped +done +for f in $LIBFDT_SOURCE; do + cp ${DTC_UPSTREAM_PATH}/libfdt/${f} libfdt/${f} + git add libfdt/${f} +done + +sed -i -- 's/#include <libfdt_env.h>/#include "libfdt_env.h"/g' ./libfdt/libfdt.h +sed -i -- 's/#include <fdt.h>/#include "fdt.h"/g' ./libfdt/libfdt.h +git add ./libfdt/libfdt.h + +commit_msg=$(cat << EOF +scripts/dtc: Update to upstream version ${dtc_version} + +This adds the following commits from upstream: + +${dtc_log} +EOF +) + +git commit -e -v -s -m "${commit_msg}" diff --git a/scripts/dtc/util.c b/scripts/dtc/util.c new file mode 100644 index 0000000000..9953c32a02 --- /dev/null +++ b/scripts/dtc/util.c @@ -0,0 +1,474 @@ +/* + * Copyright 2011 The Chromium Authors, All Rights Reserved. + * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc. + * + * util_is_printable_string contributed by + * Pantelis Antoniou <pantelis.antoniou AT gmail.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <assert.h> + +#include <errno.h> +#include <fcntl.h> +#include <unistd.h> + +#include "libfdt.h" +#include "util.h" +#include "version_gen.h" + +char *xstrdup(const char *s) +{ + int len = strlen(s) + 1; + char *d = xmalloc(len); + + memcpy(d, s, len); + + return d; +} + +/* based in part from (3) vsnprintf */ +int xasprintf(char **strp, const char *fmt, ...) +{ + int n, size = 128; /* start with 128 bytes */ + char *p; + va_list ap; + + /* initial pointer is NULL making the fist realloc to be malloc */ + p = NULL; + while (1) { + p = xrealloc(p, size); + + /* Try to print in the allocated space. */ + va_start(ap, fmt); + n = vsnprintf(p, size, fmt, ap); + va_end(ap); + + /* If that worked, return the string. */ + if (n > -1 && n < size) + break; + /* Else try again with more space. */ + if (n > -1) /* glibc 2.1 */ + size = n + 1; /* precisely what is needed */ + else /* glibc 2.0 */ + size *= 2; /* twice the old size */ + } + *strp = p; + return strlen(p); +} + +char *join_path(const char *path, const char *name) +{ + int lenp = strlen(path); + int lenn = strlen(name); + int len; + int needslash = 1; + char *str; + + len = lenp + lenn + 2; + if ((lenp > 0) && (path[lenp-1] == '/')) { + needslash = 0; + len--; + } + + str = xmalloc(len); + memcpy(str, path, lenp); + if (needslash) { + str[lenp] = '/'; + lenp++; + } + memcpy(str+lenp, name, lenn+1); + return str; +} + +bool util_is_printable_string(const void *data, int len) +{ + const char *s = data; + const char *ss, *se; + + /* zero length is not */ + if (len == 0) + return 0; + + /* must terminate with zero */ + if (s[len - 1] != '\0') + return 0; + + se = s + len; + + while (s < se) { + ss = s; + while (s < se && *s && isprint((unsigned char)*s)) + s++; + + /* not zero, or not done yet */ + if (*s != '\0' || s == ss) + return 0; + + s++; + } + + return 1; +} + +/* + * Parse a octal encoded character starting at index i in string s. The + * resulting character will be returned and the index i will be updated to + * point at the character directly after the end of the encoding, this may be + * the '\0' terminator of the string. + */ +static char get_oct_char(const char *s, int *i) +{ + char x[4]; + char *endx; + long val; + + x[3] = '\0'; + strncpy(x, s + *i, 3); + + val = strtol(x, &endx, 8); + + assert(endx > x); + + (*i) += endx - x; + return val; +} + +/* + * Parse a hexadecimal encoded character starting at index i in string s. The + * resulting character will be returned and the index i will be updated to + * point at the character directly after the end of the encoding, this may be + * the '\0' terminator of the string. + */ +static char get_hex_char(const char *s, int *i) +{ + char x[3]; + char *endx; + long val; + + x[2] = '\0'; + strncpy(x, s + *i, 2); + + val = strtol(x, &endx, 16); + if (!(endx > x)) + die("\\x used with no following hex digits\n"); + + (*i) += endx - x; + return val; +} + +char get_escape_char(const char *s, int *i) +{ + char c = s[*i]; + int j = *i + 1; + char val; + + switch (c) { + case 'a': + val = '\a'; + break; + case 'b': + val = '\b'; + break; + case 't': + val = '\t'; + break; + case 'n': + val = '\n'; + break; + case 'v': + val = '\v'; + break; + case 'f': + val = '\f'; + break; + case 'r': + val = '\r'; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + j--; /* need to re-read the first digit as + * part of the octal value */ + val = get_oct_char(s, &j); + break; + case 'x': + val = get_hex_char(s, &j); + break; + default: + val = c; + } + + (*i) = j; + return val; +} + +int utilfdt_read_err_len(const char *filename, char **buffp, off_t *len) +{ + int fd = 0; /* assume stdin */ + char *buf = NULL; + off_t bufsize = 1024, offset = 0; + int ret = 0; + + *buffp = NULL; + if (strcmp(filename, "-") != 0) { + fd = open(filename, O_RDONLY); + if (fd < 0) + return errno; + } + + /* Loop until we have read everything */ + buf = xmalloc(bufsize); + do { + /* Expand the buffer to hold the next chunk */ + if (offset == bufsize) { + bufsize *= 2; + buf = xrealloc(buf, bufsize); + } + + ret = read(fd, &buf[offset], bufsize - offset); + if (ret < 0) { + ret = errno; + break; + } + offset += ret; + } while (ret != 0); + + /* Clean up, including closing stdin; return errno on error */ + close(fd); + if (ret) + free(buf); + else + *buffp = buf; + *len = bufsize; + return ret; +} + +int utilfdt_read_err(const char *filename, char **buffp) +{ + off_t len; + return utilfdt_read_err_len(filename, buffp, &len); +} + +char *utilfdt_read_len(const char *filename, off_t *len) +{ + char *buff; + int ret = utilfdt_read_err_len(filename, &buff, len); + + if (ret) { + fprintf(stderr, "Couldn't open blob from '%s': %s\n", filename, + strerror(ret)); + return NULL; + } + /* Successful read */ + return buff; +} + +char *utilfdt_read(const char *filename) +{ + off_t len; + return utilfdt_read_len(filename, &len); +} + +int utilfdt_write_err(const char *filename, const void *blob) +{ + int fd = 1; /* assume stdout */ + int totalsize; + int offset; + int ret = 0; + const char *ptr = blob; + + if (strcmp(filename, "-") != 0) { + fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666); + if (fd < 0) + return errno; + } + + totalsize = fdt_totalsize(blob); + offset = 0; + + while (offset < totalsize) { + ret = write(fd, ptr + offset, totalsize - offset); + if (ret < 0) { + ret = -errno; + break; + } + offset += ret; + } + /* Close the file/stdin; return errno on error */ + if (fd != 1) + close(fd); + return ret < 0 ? -ret : 0; +} + + +int utilfdt_write(const char *filename, const void *blob) +{ + int ret = utilfdt_write_err(filename, blob); + + if (ret) { + fprintf(stderr, "Couldn't write blob to '%s': %s\n", filename, + strerror(ret)); + } + return ret ? -1 : 0; +} + +int utilfdt_decode_type(const char *fmt, int *type, int *size) +{ + int qualifier = 0; + + if (!*fmt) + return -1; + + /* get the conversion qualifier */ + *size = -1; + if (strchr("hlLb", *fmt)) { + qualifier = *fmt++; + if (qualifier == *fmt) { + switch (*fmt++) { +/* TODO: case 'l': qualifier = 'L'; break;*/ + case 'h': + qualifier = 'b'; + break; + } + } + } + + /* we should now have a type */ + if ((*fmt == '\0') || !strchr("iuxs", *fmt)) + return -1; + + /* convert qualifier (bhL) to byte size */ + if (*fmt != 's') + *size = qualifier == 'b' ? 1 : + qualifier == 'h' ? 2 : + qualifier == 'l' ? 4 : -1; + *type = *fmt++; + + /* that should be it! */ + if (*fmt) + return -1; + return 0; +} + +void utilfdt_print_data(const char *data, int len) +{ + int i; + const char *s; + + /* no data, don't print */ + if (len == 0) + return; + + if (util_is_printable_string(data, len)) { + printf(" = "); + + s = data; + do { + printf("\"%s\"", s); + s += strlen(s) + 1; + if (s < data + len) + printf(", "); + } while (s < data + len); + + } else if ((len % 4) == 0) { + const fdt32_t *cell = (const fdt32_t *)data; + + printf(" = <"); + for (i = 0, len /= 4; i < len; i++) + printf("0x%08x%s", fdt32_to_cpu(cell[i]), + i < (len - 1) ? " " : ""); + printf(">"); + } else { + const unsigned char *p = (const unsigned char *)data; + printf(" = ["); + for (i = 0; i < len; i++) + printf("%02x%s", *p++, i < len - 1 ? " " : ""); + printf("]"); + } +} + +void NORETURN util_version(void) +{ + printf("Version: %s\n", DTC_VERSION); + exit(0); +} + +void NORETURN util_usage(const char *errmsg, const char *synopsis, + const char *short_opts, + struct option const long_opts[], + const char * const opts_help[]) +{ + FILE *fp = errmsg ? stderr : stdout; + const char a_arg[] = "<arg>"; + size_t a_arg_len = strlen(a_arg) + 1; + size_t i; + int optlen; + + fprintf(fp, + "Usage: %s\n" + "\n" + "Options: -[%s]\n", synopsis, short_opts); + + /* prescan the --long opt length to auto-align */ + optlen = 0; + for (i = 0; long_opts[i].name; ++i) { + /* +1 is for space between --opt and help text */ + int l = strlen(long_opts[i].name) + 1; + if (long_opts[i].has_arg == a_argument) + l += a_arg_len; + if (optlen < l) + optlen = l; + } + + for (i = 0; long_opts[i].name; ++i) { + /* helps when adding new applets or options */ + assert(opts_help[i] != NULL); + + /* first output the short flag if it has one */ + if (long_opts[i].val > '~') + fprintf(fp, " "); + else + fprintf(fp, " -%c, ", long_opts[i].val); + + /* then the long flag */ + if (long_opts[i].has_arg == no_argument) + fprintf(fp, "--%-*s", optlen, long_opts[i].name); + else + fprintf(fp, "--%s %s%*s", long_opts[i].name, a_arg, + (int)(optlen - strlen(long_opts[i].name) - a_arg_len), ""); + + /* finally the help text */ + fprintf(fp, "%s\n", opts_help[i]); + } + + if (errmsg) { + fprintf(fp, "\nError: %s\n", errmsg); + exit(EXIT_FAILURE); + } else + exit(EXIT_SUCCESS); +} diff --git a/scripts/dtc/util.h b/scripts/dtc/util.h new file mode 100644 index 0000000000..ad5f41199e --- /dev/null +++ b/scripts/dtc/util.h @@ -0,0 +1,263 @@ +#ifndef _UTIL_H +#define _UTIL_H + +#include <stdarg.h> +#include <stdbool.h> +#include <getopt.h> + +/* + * Copyright 2011 The Chromium Authors, All Rights Reserved. + * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#ifdef __GNUC__ +#define PRINTF(i, j) __attribute__((format (printf, i, j))) +#define NORETURN __attribute__((noreturn)) +#else +#define PRINTF(i, j) +#define NORETURN +#endif + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + +static inline void NORETURN PRINTF(1, 2) die(const char *str, ...) +{ + va_list ap; + + va_start(ap, str); + fprintf(stderr, "FATAL ERROR: "); + vfprintf(stderr, str, ap); + va_end(ap); + exit(1); +} + +static inline void *xmalloc(size_t len) +{ + void *new = malloc(len); + + if (!new) + die("malloc() failed\n"); + + return new; +} + +static inline void *xrealloc(void *p, size_t len) +{ + void *new = realloc(p, len); + + if (!new) + die("realloc() failed (len=%zd)\n", len); + + return new; +} + +extern char *xstrdup(const char *s); + +extern int PRINTF(2, 3) xasprintf(char **strp, const char *fmt, ...); +extern char *join_path(const char *path, const char *name); + +/** + * Check a property of a given length to see if it is all printable and + * has a valid terminator. The property can contain either a single string, + * or multiple strings each of non-zero length. + * + * @param data The string to check + * @param len The string length including terminator + * @return 1 if a valid printable string, 0 if not + */ +bool util_is_printable_string(const void *data, int len); + +/* + * Parse an escaped character starting at index i in string s. The resulting + * character will be returned and the index i will be updated to point at the + * character directly after the end of the encoding, this may be the '\0' + * terminator of the string. + */ +char get_escape_char(const char *s, int *i); + +/** + * Read a device tree file into a buffer. This will report any errors on + * stderr. + * + * @param filename The filename to read, or - for stdin + * @return Pointer to allocated buffer containing fdt, or NULL on error + */ +char *utilfdt_read(const char *filename); + +/** + * Like utilfdt_read(), but also passes back the size of the file read. + * + * @param len If non-NULL, the amount of data we managed to read + */ +char *utilfdt_read_len(const char *filename, off_t *len); + +/** + * Read a device tree file into a buffer. Does not report errors, but only + * returns them. The value returned can be passed to strerror() to obtain + * an error message for the user. + * + * @param filename The filename to read, or - for stdin + * @param buffp Returns pointer to buffer containing fdt + * @return 0 if ok, else an errno value representing the error + */ +int utilfdt_read_err(const char *filename, char **buffp); + +/** + * Like utilfdt_read_err(), but also passes back the size of the file read. + * + * @param len If non-NULL, the amount of data we managed to read + */ +int utilfdt_read_err_len(const char *filename, char **buffp, off_t *len); + +/** + * Write a device tree buffer to a file. This will report any errors on + * stderr. + * + * @param filename The filename to write, or - for stdout + * @param blob Poiner to buffer containing fdt + * @return 0 if ok, -1 on error + */ +int utilfdt_write(const char *filename, const void *blob); + +/** + * Write a device tree buffer to a file. Does not report errors, but only + * returns them. The value returned can be passed to strerror() to obtain + * an error message for the user. + * + * @param filename The filename to write, or - for stdout + * @param blob Poiner to buffer containing fdt + * @return 0 if ok, else an errno value representing the error + */ +int utilfdt_write_err(const char *filename, const void *blob); + +/** + * Decode a data type string. The purpose of this string + * + * The string consists of an optional character followed by the type: + * Modifier characters: + * hh or b 1 byte + * h 2 byte + * l 4 byte, default + * + * Type character: + * s string + * i signed integer + * u unsigned integer + * x hex + * + * TODO: Implement ll modifier (8 bytes) + * TODO: Implement o type (octal) + * + * @param fmt Format string to process + * @param type Returns type found(s/d/u/x), or 0 if none + * @param size Returns size found(1,2,4,8) or 4 if none + * @return 0 if ok, -1 on error (no type given, or other invalid format) + */ +int utilfdt_decode_type(const char *fmt, int *type, int *size); + +/* + * This is a usage message fragment for the -t option. It is the format + * supported by utilfdt_decode_type. + */ + +#define USAGE_TYPE_MSG \ + "<type>\ts=string, i=int, u=unsigned, x=hex\n" \ + "\tOptional modifier prefix:\n" \ + "\t\thh or b=byte, h=2 byte, l=4 byte (default)"; + +/** + * Print property data in a readable format to stdout + * + * Properties that look like strings will be printed as strings. Otherwise + * the data will be displayed either as cells (if len is a multiple of 4 + * bytes) or bytes. + * + * If len is 0 then this function does nothing. + * + * @param data Pointers to property data + * @param len Length of property data + */ +void utilfdt_print_data(const char *data, int len); + +/** + * Show source version and exit + */ +void NORETURN util_version(void); + +/** + * Show usage and exit + * + * This helps standardize the output of various utils. You most likely want + * to use the usage() helper below rather than call this. + * + * @param errmsg If non-NULL, an error message to display + * @param synopsis The initial example usage text (and possible examples) + * @param short_opts The string of short options + * @param long_opts The structure of long options + * @param opts_help An array of help strings (should align with long_opts) + */ +void NORETURN util_usage(const char *errmsg, const char *synopsis, + const char *short_opts, + struct option const long_opts[], + const char * const opts_help[]); + +/** + * Show usage and exit + * + * If you name all your usage variables with usage_xxx, then you can call this + * help macro rather than expanding all arguments yourself. + * + * @param errmsg If non-NULL, an error message to display + */ +#define usage(errmsg) \ + util_usage(errmsg, usage_synopsis, usage_short_opts, \ + usage_long_opts, usage_opts_help) + +/** + * Call getopt_long() with standard options + * + * Since all util code runs getopt in the same way, provide a helper. + */ +#define util_getopt_long() getopt_long(argc, argv, usage_short_opts, \ + usage_long_opts, NULL) + +/* Helper for aligning long_opts array */ +#define a_argument required_argument + +/* Helper for usage_short_opts string constant */ +#define USAGE_COMMON_SHORT_OPTS "hV" + +/* Helper for usage_long_opts option array */ +#define USAGE_COMMON_LONG_OPTS \ + {"help", no_argument, NULL, 'h'}, \ + {"version", no_argument, NULL, 'V'}, \ + {NULL, no_argument, NULL, 0x0} + +/* Helper for usage_opts_help array */ +#define USAGE_COMMON_OPTS_HELP \ + "Print this help and exit", \ + "Print version and exit", \ + NULL + +/* Helper for getopt case statements */ +#define case_USAGE_COMMON_FLAGS \ + case 'h': usage(NULL); \ + case 'V': util_version(); \ + case '?': usage("unknown option"); + +#endif /* _UTIL_H */ diff --git a/scripts/dtc/version_gen.h b/scripts/dtc/version_gen.h new file mode 100644 index 0000000000..b5ed715ecc --- /dev/null +++ b/scripts/dtc/version_gen.h @@ -0,0 +1 @@ +#define DTC_VERSION "DTC 1.4.4-gfe50bd1e" diff --git a/scripts/spelling.txt b/scripts/spelling.txt new file mode 100644 index 0000000000..400ef35169 --- /dev/null +++ b/scripts/spelling.txt @@ -0,0 +1,1217 @@ +# Originally from Debian's Lintian tool. Various false positives have been +# removed, and various additions have been made as they've been discovered +# in the kernel source. +# +# License: GPLv2 +# +# The format of each line is: +# mistake||correction +# +abandonning||abandoning +abigious||ambiguous +abitrate||arbitrate +abov||above +abreviated||abbreviated +absense||absence +absolut||absolute +absoulte||absolute +acccess||access +acceess||access +acceleratoin||acceleration +accelleration||acceleration +accesing||accessing +accesnt||accent +accessable||accessible +accesss||access +accidentaly||accidentally +accidentually||accidentally +accoding||according +accomodate||accommodate +accomodates||accommodates +accordign||according +accoring||according +accout||account +accquire||acquire +accquired||acquired +accross||across +acessable||accessible +acess||access +achitecture||architecture +acient||ancient +acitions||actions +acitve||active +acknowldegement||acknowledgment +acknowledgement||acknowledgment +ackowledge||acknowledge +ackowledged||acknowledged +acording||according +activete||activate +actived||activated +actualy||actually +acumulating||accumulating +acumulator||accumulator +adapater||adapter +addional||additional +additionaly||additionally +addres||address +adddress||address +addreses||addresses +addresss||address +aditional||additional +aditionally||additionally +aditionaly||additionally +adminstrative||administrative +adress||address +adresses||addresses +adviced||advised +afecting||affecting +againt||against +agaist||against +albumns||albums +alegorical||allegorical +algined||aligned +algorith||algorithm +algorithmical||algorithmically +algoritm||algorithm +algoritms||algorithms +algorrithm||algorithm +algorritm||algorithm +aligment||alignment +alignement||alignment +allign||align +alligned||aligned +allocatote||allocate +allocatrd||allocated +allocte||allocate +allpication||application +alocate||allocate +alogirhtms||algorithms +alogrithm||algorithm +alot||a lot +alow||allow +alows||allows +altough||although +alue||value +ambigious||ambiguous +amoung||among +amout||amount +an union||a union +an user||a user +an userspace||a userspace +an one||a one +analysator||analyzer +ang||and +anniversery||anniversary +annoucement||announcement +anomolies||anomalies +anomoly||anomaly +anway||anyway +aplication||application +appearence||appearance +applicaion||application +appliction||application +applictions||applications +applys||applies +appplications||applications +appropiate||appropriate +appropriatly||appropriately +approriate||appropriate +approriately||appropriately +apropriate||appropriate +aquainted||acquainted +aquired||acquired +aquisition||acquisition +arbitary||arbitrary +architechture||architecture +arguement||argument +arguements||arguments +aritmetic||arithmetic +arne't||aren't +arraival||arrival +artifical||artificial +artillary||artillery +asign||assign +asser||assert +assertation||assertion +assiged||assigned +assigment||assignment +assigments||assignments +assistent||assistant +assocation||association +associcated||associated +assotiated||associated +assum||assume +assumtpion||assumption +asuming||assuming +asycronous||asynchronous +asynchnous||asynchronous +atomatically||automatically +atomicly||atomically +atempt||attempt +attachement||attachment +attched||attached +attemps||attempts +attemping||attempting +attruibutes||attributes +authentification||authentication +automaticaly||automatically +automaticly||automatically +automatize||automate +automatized||automated +automatizes||automates +autonymous||autonomous +auxillary||auxiliary +auxilliary||auxiliary +avaiable||available +avaible||available +availabe||available +availabled||available +availablity||availability +availale||available +availavility||availability +availble||available +availiable||available +avalable||available +avaliable||available +aysnc||async +backgroud||background +backword||backward +backwords||backwards +bahavior||behavior +bakup||backup +baloon||balloon +baloons||balloons +bandwith||bandwidth +banlance||balance +batery||battery +beacuse||because +becasue||because +becomming||becoming +becuase||because +beeing||being +befor||before +begining||beginning +beter||better +betweeen||between +bianries||binaries +bitmast||bitmask +boardcast||broadcast +borad||board +boundry||boundary +brievely||briefly +broadcat||broadcast +cacluated||calculated +caculation||calculation +calender||calendar +calle||called +callibration||calibration +calucate||calculate +calulate||calculate +cancelation||cancellation +cancle||cancel +capabilites||capabilities +capabitilies||capabilities +capatibilities||capabilities +capapbilities||capabilities +carefuly||carefully +cariage||carriage +catagory||category +cehck||check +challange||challenge +challanges||challenges +chanell||channel +changable||changeable +chanined||chained +channle||channel +channnel||channel +charachter||character +charachters||characters +charactor||character +charater||character +charaters||characters +charcter||character +chcek||check +chck||check +checksuming||checksumming +childern||children +childs||children +chiled||child +chked||checked +chnage||change +chnages||changes +chnnel||channel +choosen||chosen +chouse||chose +circumvernt||circumvent +claread||cleared +clared||cleared +closeing||closing +clustred||clustered +coexistance||coexistence +collapsable||collapsible +colorfull||colorful +comand||command +comit||commit +commerical||commercial +comming||coming +comminucation||communication +commited||committed +commiting||committing +committ||commit +commoditiy||commodity +comsume||consume +comsumer||consumer +comsuming||consuming +compability||compatibility +compaibility||compatibility +compatability||compatibility +compatable||compatible +compatibiliy||compatibility +compatibilty||compatibility +compatiblity||compatibility +competion||completion +compilant||compliant +compleatly||completely +completition||completion +completly||completely +complient||compliant +componnents||components +compoment||component +compres||compress +compresion||compression +comression||compression +comunication||communication +conbination||combination +conditionaly||conditionally +conected||connected +connecetd||connected +configuartion||configuration +configuratoin||configuration +configuraton||configuration +configuretion||configuration +configutation||configuration +conider||consider +conjuction||conjunction +connectinos||connections +connnection||connection +connnections||connections +consistancy||consistency +consistant||consistent +containes||contains +containts||contains +contaisn||contains +contant||contact +contence||contents +continous||continuous +continously||continuously +continueing||continuing +contraints||constraints +contol||control +contoller||controller +controled||controlled +controler||controller +controll||control +contruction||construction +contry||country +conuntry||country +convertion||conversion +convertor||converter +convienient||convenient +convinient||convenient +corected||corrected +correponding||corresponding +correponds||corresponds +correspoding||corresponding +cotrol||control +cound||could +couter||counter +coutner||counter +cryptocraphic||cryptographic +cunter||counter +curently||currently +cylic||cyclic +dafault||default +deafult||default +deamon||daemon +decompres||decompress +decription||description +dectected||detected +defailt||default +defferred||deferred +definate||definite +definately||definitely +defintion||definition +defintions||definitions +defualt||default +defult||default +deintializing||deinitializing +deintialize||deinitialize +deintialized||deinitialized +deivce||device +delared||declared +delare||declare +delares||declares +delaring||declaring +delemiter||delimiter +demodualtor||demodulator +demension||dimension +dependancies||dependencies +dependancy||dependency +dependant||dependent +depreacted||deprecated +depreacte||deprecate +desactivate||deactivate +desciptor||descriptor +desciptors||descriptors +descripton||description +descrition||description +descritptor||descriptor +desctiptor||descriptor +desriptor||descriptor +desriptors||descriptors +destionation||destination +destory||destroy +destoryed||destroyed +destorys||destroys +destroied||destroyed +detabase||database +deteced||detected +develope||develop +developement||development +developped||developed +developpement||development +developper||developer +developpment||development +deveolpment||development +devided||divided +deviece||device +diable||disable +dictionnary||dictionary +didnt||didn't +diferent||different +differrence||difference +diffrent||different +diffrentiate||differentiate +difinition||definition +diplay||display +direectly||directly +disassocation||disassociation +disapear||disappear +disapeared||disappeared +disappared||disappeared +disble||disable +disbled||disabled +disconnet||disconnect +discontinous||discontinuous +dispertion||dispersion +dissapears||disappears +distiction||distinction +docuentation||documentation +documantation||documentation +documentaion||documentation +documment||document +doesnt||doesn't +dorp||drop +dosen||doesn +downlad||download +downlads||downloads +druing||during +dynmaic||dynamic +easilly||easily +ecspecially||especially +edditable||editable +editting||editing +efective||effective +efficently||efficiently +ehther||ether +eigth||eight +elementry||elementary +eletronic||electronic +embeded||embedded +enabledi||enabled +enchanced||enhanced +encorporating||incorporating +encrupted||encrypted +encrypiton||encryption +encryptio||encryption +endianess||endianness +enhaced||enhanced +enlightnment||enlightenment +entrys||entries +enocded||encoded +enterily||entirely +enviroiment||environment +enviroment||environment +environement||environment +environent||environment +eqivalent||equivalent +equiped||equipped +equivelant||equivalent +equivilant||equivalent +eror||error +estbalishment||establishment +etsablishment||establishment +etsbalishment||establishment +excecutable||executable +exceded||exceeded +excellant||excellent +exeed||exceed +existance||existence +existant||existent +exixt||exist +exlcude||exclude +exlcusive||exclusive +exmaple||example +expecially||especially +explicite||explicit +explicitely||explicitly +explict||explicit +explictely||explicitly +explictly||explicitly +expresion||expression +exprimental||experimental +extened||extended +extensability||extensibility +extention||extension +extracter||extractor +falied||failed +faild||failed +faill||fail +failied||failed +faillure||failure +failue||failure +failuer||failure +faireness||fairness +falied||failed +faliure||failure +fallbck||fallback +familar||familiar +fatser||faster +feauture||feature +feautures||features +fetaure||feature +fetaures||features +fileystem||filesystem +fimware||firmware +finanize||finalize +findn||find +finilizes||finalizes +finsih||finish +flusing||flushing +folloing||following +followign||following +followings||following +follwing||following +forseeable||foreseeable +forse||force +fortan||fortran +forwardig||forwarding +framming||framing +framwork||framework +frequncy||frequency +frome||from +fucntion||function +fuction||function +fuctions||functions +funcion||function +functionallity||functionality +functionaly||functionally +functionnality||functionality +functonality||functionality +funtion||function +funtions||functions +furthur||further +futhermore||furthermore +futrue||future +gaurenteed||guaranteed +generiously||generously +genereate||generate +genric||generic +globel||global +grabing||grabbing +grahical||graphical +grahpical||graphical +grapic||graphic +guage||gauge +guarenteed||guaranteed +guarentee||guarantee +halfs||halves +hander||handler +handfull||handful +hanled||handled +happend||happened +harware||hardware +heirarchically||hierarchically +helpfull||helpful +hierachy||hierarchy +hierarchie||hierarchy +howver||however +hsould||should +hypervior||hypervisor +hypter||hyper +identidier||identifier +iligal||illegal +illigal||illegal +imblance||imbalance +immeadiately||immediately +immedaite||immediate +immediatelly||immediately +immediatly||immediately +immidiate||immediate +impelentation||implementation +impementated||implemented +implemantation||implementation +implemenation||implementation +implementaiton||implementation +implementated||implemented +implemention||implementation +implemetation||implementation +implemntation||implementation +implentation||implementation +implmentation||implementation +implmenting||implementing +incomming||incoming +incompatabilities||incompatibilities +incompatable||incompatible +inconsistant||inconsistent +increas||increase +incrment||increment +indendation||indentation +indended||intended +independant||independent +independantly||independently +independed||independent +indiate||indicate +indicat||indicate +inexpect||inexpected +infomation||information +informatiom||information +informations||information +informtion||information +infromation||information +ingore||ignore +inital||initial +initalized||initialized +initalised||initialized +initalise||initialize +initalize||initialize +initation||initiation +initators||initiators +initialiazation||initialization +initializiation||initialization +initialzed||initialized +initilization||initialization +initilize||initialize +inofficial||unofficial +insititute||institute +instal||install +instanciated||instantiated +inteface||interface +integreated||integrated +integrety||integrity +integrey||integrity +intendet||intended +intented||intended +interanl||internal +interchangable||interchangeable +interferring||interfering +interger||integer +intermittant||intermittent +internel||internal +interoprability||interoperability +interrface||interface +interrrupt||interrupt +interrup||interrupt +interrups||interrupts +interruptted||interrupted +interupted||interrupted +interupt||interrupt +intial||initial +intialisation||initialisation +intialised||initialised +intialise||initialise +intialization||initialization +intialized||initialized +intialize||initialize +intregral||integral +intrrupt||interrupt +intterrupt||interrupt +intuative||intuitive +invaid||invalid +invalde||invalid +invalide||invalid +invalud||invalid +invididual||individual +invokation||invocation +invokations||invocations +irrelevent||irrelevant +isnt||isn't +isssue||issue +iternations||iterations +itertation||iteration +itslef||itself +jave||java +jeffies||jiffies +juse||just +jus||just +kown||known +langage||language +langauage||language +langauge||language +langugage||language +lauch||launch +layed||laid +leightweight||lightweight +lengh||length +lenght||length +lenth||length +lesstiff||lesstif +libaries||libraries +libary||library +librairies||libraries +libraris||libraries +licenceing||licencing +loggging||logging +loggin||login +logile||logfile +loosing||losing +losted||lost +machinary||machinery +maintainance||maintenance +maintainence||maintenance +maintan||maintain +makeing||making +malplaced||misplaced +malplace||misplace +managable||manageable +managment||management +mangement||management +manoeuvering||maneuvering +mappping||mapping +mathimatical||mathematical +mathimatic||mathematic +mathimatics||mathematics +maxium||maximum +mechamism||mechanism +meetign||meeting +ment||meant +mergable||mergeable +mesage||message +messags||messages +messgaes||messages +messsage||message +messsages||messages +micropone||microphone +microprocesspr||microprocessor +milliseonds||milliseconds +minium||minimum +minimam||minimum +minumum||minimum +misalinged||misaligned +miscelleneous||miscellaneous +misformed||malformed +mispelled||misspelled +mispelt||misspelt +mising||missing +missmanaged||mismanaged +missmatch||mismatch +miximum||maximum +mmnemonic||mnemonic +mnay||many +modulues||modules +momery||memory +memomry||memory +monochorome||monochrome +monochromo||monochrome +monocrome||monochrome +mopdule||module +mroe||more +mulitplied||multiplied +multidimensionnal||multidimensional +multple||multiple +mumber||number +muticast||multicast +mutiple||multiple +mutli||multi +nams||names +navagating||navigating +nead||need +neccecary||necessary +neccesary||necessary +neccessary||necessary +necesary||necessary +neded||needed +negaive||negative +negoitation||negotiation +negotation||negotiation +nerver||never +nescessary||necessary +nessessary||necessary +noticable||noticeable +notications||notifications +notifed||notified +numebr||number +numner||number +obtaion||obtain +occassionally||occasionally +occationally||occasionally +occurance||occurrence +occurances||occurrences +occured||occurred +occurence||occurrence +occure||occurred +occured||occurred +occuring||occurring +offet||offset +omited||omitted +omiting||omitting +omitt||omit +ommiting||omitting +ommitted||omitted +onself||oneself +ony||only +operatione||operation +opertaions||operations +optionnal||optional +optmizations||optimizations +orientatied||orientated +orientied||oriented +orignal||original +otherise||otherwise +ouput||output +oustanding||outstanding +overaall||overall +overhread||overhead +overlaping||overlapping +overide||override +overrided||overridden +overriden||overridden +overun||overrun +overwritting||overwriting +overwriten||overwritten +pacakge||package +pachage||package +packacge||package +packege||package +packge||package +packtes||packets +pakage||package +pallette||palette +paln||plan +paramameters||parameters +paramaters||parameters +paramater||parameter +parametes||parameters +parametised||parametrised +paramter||parameter +paramters||parameters +particuarly||particularly +particularily||particularly +partiton||partition +pased||passed +passin||passing +pathes||paths +pecularities||peculiarities +peformance||performance +peice||piece +pendantic||pedantic +peprocessor||preprocessor +perfoming||performing +permissons||permissions +peroid||period +persistance||persistence +persistant||persistent +plalform||platform +platfrom||platform +plattform||platform +pleaes||please +ploting||plotting +plugable||pluggable +poinnter||pointer +pointeur||pointer +poiter||pointer +posible||possible +positon||position +possibilites||possibilities +powerfull||powerful +preapre||prepare +preceeded||preceded +preceeding||preceding +preceed||precede +precendence||precedence +precission||precision +preemptable||preemptible +prefered||preferred +prefferably||preferably +premption||preemption +prepaired||prepared +pressre||pressure +primative||primitive +princliple||principle +priorty||priority +privilaged||privileged +privilage||privilege +priviledge||privilege +priviledges||privileges +probaly||probably +procceed||proceed +proccesors||processors +procesed||processed +proces||process +procesing||processing +processessing||processing +processess||processes +processpr||processor +processsed||processed +processsing||processing +procteted||protected +prodecure||procedure +progams||programs +progess||progress +programers||programmers +programm||program +programms||programs +progresss||progress +promiscous||promiscuous +promps||prompts +pronnounced||pronounced +prononciation||pronunciation +pronouce||pronounce +pronunce||pronounce +propery||property +propigate||propagate +propigation||propagation +propogate||propagate +prosess||process +protable||portable +protcol||protocol +protecion||protection +protocoll||protocol +promixity||proximity +psudo||pseudo +psuedo||pseudo +psychadelic||psychedelic +pwoer||power +quering||querying +randomally||randomly +raoming||roaming +reasearcher||researcher +reasearchers||researchers +reasearch||research +recepient||recipient +receving||receiving +recieved||received +recieve||receive +reciever||receiver +recieves||receives +recogniced||recognised +recognizeable||recognizable +recommanded||recommended +recyle||recycle +redircet||redirect +redirectrion||redirection +reename||rename +refcounf||refcount +refence||reference +refered||referred +referenace||reference +refering||referring +refernces||references +refernnce||reference +refrence||reference +registerd||registered +registeresd||registered +registerred||registered +registes||registers +registraration||registration +regsiter||register +regster||register +regualar||regular +reguator||regulator +regulamentations||regulations +reigstration||registration +releated||related +relevent||relevant +remoote||remote +remore||remote +removeable||removable +repectively||respectively +replacable||replaceable +replacments||replacements +replys||replies +reponse||response +representaion||representation +reqeust||request +requestied||requested +requiere||require +requirment||requirement +requred||required +requried||required +requst||request +reseting||resetting +resizeable||resizable +resouce||resource +resouces||resources +resoures||resources +responce||response +ressizes||resizes +ressource||resource +ressources||resources +retransmited||retransmitted +retreived||retrieved +retreive||retrieve +retrive||retrieve +retuned||returned +reudce||reduce +reuest||request +reuqest||request +reutnred||returned +revsion||revision +rmeoved||removed +rmeove||remove +rmeoves||removes +rountine||routine +routins||routines +rquest||request +runing||running +runned||ran +runnning||running +runtine||runtime +sacrifying||sacrificing +safly||safely +safty||safety +savable||saveable +scaned||scanned +scaning||scanning +scarch||search +seach||search +searchs||searches +secquence||sequence +secund||second +segement||segment +senarios||scenarios +sentivite||sensitive +separatly||separately +sepcify||specify +sepc||spec +seperated||separated +seperately||separately +seperate||separate +seperatly||separately +seperator||separator +sepperate||separate +sequece||sequence +sequencial||sequential +serveral||several +setts||sets +settting||setting +shotdown||shutdown +shoud||should +shouldnt||shouldn't +shoule||should +shrinked||shrunk +siginificantly||significantly +signabl||signal +similary||similarly +similiar||similar +simlar||similar +simliar||similar +simpified||simplified +singaled||signaled +singal||signal +singed||signed +sleeped||slept +softwares||software +speach||speech +specfic||specific +speciefied||specified +specifc||specific +specifed||specified +specificatin||specification +specificaton||specification +specifing||specifying +specifiying||specifying +speficied||specified +speicify||specify +speling||spelling +spinlcok||spinlock +spinock||spinlock +splitted||split +spreaded||spread +spurrious||spurious +sructure||structure +stablilization||stabilization +staically||statically +staion||station +standardss||standards +standartization||standardization +standart||standard +staticly||statically +stoped||stopped +stoppped||stopped +straming||streaming +struc||struct +structres||structures +stuct||struct +strucuture||structure +stucture||structure +sturcture||structure +subdirectoires||subdirectories +suble||subtle +substract||subtract +succesfully||successfully +succesful||successful +successed||succeeded +successfull||successful +successfuly||successfully +sucessfully||successfully +sucess||success +superflous||superfluous +superseeded||superseded +suplied||supplied +suported||supported +suport||support +supportet||supported +suppored||supported +supportin||supporting +suppoted||supported +suppported||supported +suppport||support +supress||suppress +surpresses||suppresses +susbsystem||subsystem +suspeneded||suspended +suspicously||suspiciously +swaping||swapping +switchs||switches +swith||switch +swithable||switchable +swithc||switch +swithced||switched +swithcing||switching +swithed||switched +swithing||switching +symetric||symmetric +synax||syntax +synchonized||synchronized +syncronize||synchronize +syncronized||synchronized +syncronizing||synchronizing +syncronus||synchronous +syste||system +sytem||system +sythesis||synthesis +taht||that +targetted||targeted +targetting||targeting +teh||the +temorary||temporary +temproarily||temporarily +therfore||therefore +thier||their +threds||threads +threshhold||threshold +throught||through +thses||these +tiggered||triggered +tipically||typically +timout||timeout +tmis||this +torerable||tolerable +tramsmitted||transmitted +tramsmit||transmit +tranfer||transfer +transciever||transceiver +transferd||transferred +transfered||transferred +transfering||transferring +transision||transition +transmittd||transmitted +transormed||transformed +trasfer||transfer +trasmission||transmission +treshold||threshold +trigerring||triggering +trun||turn +ture||true +tyep||type +udpate||update +uesd||used +uncommited||uncommitted +unconditionaly||unconditionally +underun||underrun +unecessary||unnecessary +unexecpted||unexpected +unexepected||unexpected +unexpcted||unexpected +unexpectd||unexpected +unexpeted||unexpected +unexpexted||unexpected +unfortunatelly||unfortunately +unifiy||unify +unintialized||uninitialized +unkmown||unknown +unknonw||unknown +unknow||unknown +unkown||unknown +unneded||unneeded +unneedingly||unnecessarily +unnsupported||unsupported +unmached||unmatched +unregester||unregister +unresgister||unregister +unrgesiter||unregister +unsinged||unsigned +unstabel||unstable +unsolicitied||unsolicited +unsuccessfull||unsuccessful +unsuported||unsupported +untill||until +unuseful||useless +upate||update +usefule||useful +usefull||useful +usege||usage +usera||users +usualy||usually +utilites||utilities +utillities||utilities +utilties||utilities +utiltity||utility +utitity||utility +utitlty||utility +vaid||valid +vaild||valid +valide||valid +variantions||variations +varible||variable +varient||variant +vaule||value +verbse||verbose +verisons||versions +verison||version +verson||version +vicefersa||vice-versa +virtal||virtual +virtaul||virtual +virtiual||virtual +visiters||visitors +vitual||virtual +wakeus||wakeups +wating||waiting +wether||whether +whataver||whatever +whcih||which +whenver||whenever +wheter||whether +whe||when +wierd||weird +wiil||will +wirte||write +withing||within +wnat||want +workarould||workaround +writeing||writing +writting||writing +zombe||zombie +zomebie||zombie diff --git a/test/py/README.md b/test/py/README.md index 829c7efbb2..ea4b66a41c 100644 --- a/test/py/README.md +++ b/test/py/README.md @@ -22,12 +22,17 @@ need to implement various "hook" scripts that are called by the test suite at the appropriate time. On Debian or Debian-like distributions, the following packages are required. -Similar package names should exist in other distributions. +Some packages are required to execute any test, and others only for specific +tests. Similar package names should exist in other distributions. | Package | Version tested (Ubuntu 14.04) | | -------------- | ----------------------------- | | python | 2.7.5-5ubuntu3 | | python-pytest | 2.5.1-1 | +| gdisk | 0.8.8-1ubuntu0.1 | +| dfu-util | 0.5-1 | +| dtc | 1.4.0+dfsg-1 | +| openssl | 1.0.1f-1ubuntu2.22 | The test script supports either: diff --git a/test/py/conftest.py b/test/py/conftest.py index 65e1d75626..6e66a48c15 100644 --- a/test/py/conftest.py +++ b/test/py/conftest.py @@ -429,12 +429,12 @@ def setup_boardspec(item): for board in mark.args: if board.startswith('!'): if ubconfig.board_type == board[1:]: - pytest.skip('board not supported') + pytest.skip('board "%s" not supported' % ubconfig.board_type) return else: required_boards.append(board) if required_boards and ubconfig.board_type not in required_boards: - pytest.skip('board not supported') + pytest.skip('board "%s" not supported' % ubconfig.board_type) def setup_buildconfigspec(item): """Process any 'buildconfigspec' marker for a test. @@ -455,7 +455,35 @@ def setup_buildconfigspec(item): return for option in mark.args: if not ubconfig.buildconfig.get('config_' + option.lower(), None): - pytest.skip('.config feature not enabled') + pytest.skip('.config feature "%s" not enabled' % option.lower()) + +def tool_is_in_path(tool): + for path in os.environ["PATH"].split(os.pathsep): + fn = os.path.join(path, tool) + if os.path.isfile(fn) and os.access(fn, os.X_OK): + return True + return False + +def setup_requiredtool(item): + """Process any 'requiredtool' marker for a test. + + Such a marker lists some external tool (binary, executable, application) + that the test requires. If tests are being executed on a system that + doesn't have the required tool, the test is marked to be skipped. + + Args: + item: The pytest test item. + + Returns: + Nothing. + """ + + mark = item.get_marker('requiredtool') + if not mark: + return + for tool in mark.args: + if not tool_is_in_path(tool): + pytest.skip('tool "%s" not in $PATH' % tool) def start_test_section(item): anchors[item.name] = log.start_section(item.name) @@ -476,6 +504,7 @@ def pytest_runtest_setup(item): start_test_section(item) setup_boardspec(item) setup_buildconfigspec(item) + setup_requiredtool(item) def pytest_runtest_protocol(item, nextitem): """pytest hook: Called to execute a test. diff --git a/test/py/multiplexed_log.py b/test/py/multiplexed_log.py index bf926c3e77..5bc1bc49d4 100644 --- a/test/py/multiplexed_log.py +++ b/test/py/multiplexed_log.py @@ -365,13 +365,13 @@ $(document).ready(function () { self._terminate_stream() self.f.write('<div class="' + note_type + '">\n') - if anchor: - self.f.write('<a href="#%s">\n' % anchor) self.f.write('<pre>') + if anchor: + self.f.write('<a href="#%s">' % anchor) self.f.write(self._escape(msg)) - self.f.write('\n</pre>\n') if anchor: - self.f.write('</a>\n') + self.f.write('</a>') + self.f.write('\n</pre>\n') self.f.write('</div>\n') def start_section(self, marker, anchor=None): diff --git a/test/py/tests/test_dfu.py b/test/py/tests/test_dfu.py index fba67d585b..8f6877c5c2 100644 --- a/test/py/tests/test_dfu.py +++ b/test/py/tests/test_dfu.py @@ -113,6 +113,7 @@ test_sizes_default = ( first_usb_dev_port = None @pytest.mark.buildconfigspec('cmd_dfu') +@pytest.mark.requiredtool('dfu-util') def test_dfu(u_boot_console, env__usb_dev_port, env__dfu_config): """Test the "dfu" command; the host system must be able to enumerate a USB device when "dfu" is running, various DFU transfers are tested, and the diff --git a/test/py/tests/test_fit.py b/test/py/tests/test_fit.py index 7e6b96dae4..4b32bb18b8 100755 --- a/test/py/tests/test_fit.py +++ b/test/py/tests/test_fit.py @@ -111,6 +111,7 @@ sb save hostfs 0 %(loadables2_addr)x %(loadables2_out)s %(loadables2_size)x @pytest.mark.boardspec('sandbox') @pytest.mark.buildconfigspec('fit_signature') +@pytest.mark.requiredtool('dtc') def test_fit(u_boot_console): def make_fname(leaf): """Make a temporary filename diff --git a/test/py/tests/test_gpt.py b/test/py/tests/test_gpt.py index e2bbd08e6d..ec25fbbc5a 100644 --- a/test/py/tests/test_gpt.py +++ b/test/py/tests/test_gpt.py @@ -38,15 +38,14 @@ class GptTestDiskImage(object): fd = os.open(self.path, os.O_RDWR | os.O_CREAT) os.ftruncate(fd, 4194304) os.close(fd) - sgdisk = '/sbin/sgdisk' - cmd = (sgdisk, '-U', '375a56f7-d6c9-4e81-b5f0-09d41ca89efe', + cmd = ('sgdisk', '-U', '375a56f7-d6c9-4e81-b5f0-09d41ca89efe', self.path) u_boot_utils.run_and_log(u_boot_console, cmd) - cmd = (sgdisk, '--new=1:2048:2560', self.path) + cmd = ('sgdisk', '--new=1:2048:2560', self.path) u_boot_utils.run_and_log(u_boot_console, cmd) - cmd = (sgdisk, '--new=2:4096:4608', self.path) + cmd = ('sgdisk', '--new=2:4096:4608', self.path) u_boot_utils.run_and_log(u_boot_console, cmd) - cmd = (sgdisk, '-l', self.path) + cmd = ('sgdisk', '-l', self.path) u_boot_utils.run_and_log(u_boot_console, cmd) gtdi = None @@ -64,6 +63,7 @@ def state_disk_image(u_boot_console): @pytest.mark.boardspec('sandbox') @pytest.mark.buildconfigspec('cmd_gpt') +@pytest.mark.requiredtool('sgdisk') def test_gpt_guid(state_disk_image, u_boot_console): """Test the gpt guid command.""" @@ -73,6 +73,7 @@ def test_gpt_guid(state_disk_image, u_boot_console): @pytest.mark.boardspec('sandbox') @pytest.mark.buildconfigspec('cmd_gpt') +@pytest.mark.requiredtool('sgdisk') def test_gpt_save_guid(state_disk_image, u_boot_console): """Test the gpt guid command to save GUID into a string.""" @@ -86,6 +87,7 @@ def test_gpt_save_guid(state_disk_image, u_boot_console): @pytest.mark.boardspec('sandbox') @pytest.mark.buildconfigspec('cmd_gpt') @pytest.mark.buildconfigspec('cmd_gpt_rename') +@pytest.mark.requiredtool('sgdisk') def test_gpt_rename_partition(state_disk_image, u_boot_console): """Test the gpt rename command to write partition names.""" @@ -101,6 +103,7 @@ def test_gpt_rename_partition(state_disk_image, u_boot_console): @pytest.mark.buildconfigspec('cmd_gpt') @pytest.mark.buildconfigspec('cmd_gpt_rename') @pytest.mark.buildconfigspec('cmd_part') +@pytest.mark.requiredtool('sgdisk') def test_gpt_swap_partitions(state_disk_image, u_boot_console): """Test the gpt swap command to exchange two partition names.""" diff --git a/test/py/tests/test_vboot.py b/test/py/tests/test_vboot.py index 6e62820743..c4da79d114 100644 --- a/test/py/tests/test_vboot.py +++ b/test/py/tests/test_vboot.py @@ -31,6 +31,10 @@ import u_boot_utils as util @pytest.mark.boardspec('sandbox') @pytest.mark.buildconfigspec('fit_signature') +@pytest.mark.requiredtool('dtc') +@pytest.mark.requiredtool('fdtget') +@pytest.mark.requiredtool('fdtput') +@pytest.mark.requiredtool('openssl') def test_vboot(u_boot_console): """Test verified boot signing with mkimage and verification with 'bootm'. diff --git a/tools/Makefile b/tools/Makefile index a0db19d6b0..c16477459d 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -175,7 +175,7 @@ HOSTCFLAGS_rsa-sign.o += -Wno-deprecated-declarations endif endif -HOSTCFLAGS_fit_image.o += -DMKIMAGE_DTC=\"$(DTC)\" +HOSTCFLAGS_fit_image.o += -DMKIMAGE_DTC=\"$(CONFIG_MKIMAGE_DTC_PATH)\" HOSTLOADLIBES_dumpimage := $(HOSTLOADLIBES_mkimage) HOSTLOADLIBES_fit_info := $(HOSTLOADLIBES_mkimage) diff --git a/tools/buildman/kconfiglib.py b/tools/buildman/kconfiglib.py index 352ad438ee..68b470a3a7 100644 --- a/tools/buildman/kconfiglib.py +++ b/tools/buildman/kconfiglib.py @@ -73,6 +73,7 @@ email service. Don't wrestle with internal APIs. Tell me what you need and I might add it in a safe way as a client API instead.""" import os +import platform import re import sys @@ -137,10 +138,8 @@ class Config(object): # The set of all symbols, indexed by name (a string) self.syms = {} # Python 2/3 compatibility hack. This is the only one needed. - if sys.version_info[0] >= 3: - self.syms_iter = self.syms.values - else: - self.syms_iter = self.syms.itervalues + self.syms_iter = self.syms.values if sys.version_info[0] >= 3 else \ + self.syms.itervalues # The set of all defined symbols in the configuration in the order they # appear in the Kconfig files. This excludes the special symbols n, m, @@ -173,7 +172,7 @@ class Config(object): self.m = register_special_symbol(TRISTATE, "m", "m") self.y = register_special_symbol(TRISTATE, "y", "y") # DEFCONFIG_LIST uses this - register_special_symbol(STRING, "UNAME_RELEASE", os.uname()[2]) + register_special_symbol(STRING, "UNAME_RELEASE", platform.uname()[2]) # The symbol with "option defconfig_list" set, containing a list of # default .config files @@ -183,16 +182,20 @@ class Config(object): self.arch = os.environ.get("ARCH") self.srcarch = os.environ.get("SRCARCH") + # If you set CONFIG_ in the environment, Kconfig will prefix all symbols + # with its value when saving the configuration, instead of using the default, "CONFIG_". + self.config_prefix = os.environ.get("CONFIG_") + if self.config_prefix is None: + self.config_prefix = "CONFIG_" + # See Config.__init__(). We need this for get_defconfig_filename(). self.srctree = os.environ.get("srctree") if self.srctree is None: self.srctree = "." self.filename = filename - if base_dir is None: - self.base_dir = self.srctree - else: - self.base_dir = os.path.expandvars(base_dir) + self.base_dir = self.srctree if base_dir is None else \ + os.path.expandvars(base_dir) # The 'mainmenu' text self.mainmenu_text = None @@ -222,7 +225,8 @@ class Config(object): self._transform_m = None # Parse the Kconfig files - self.top_block = self._parse_file(filename, None, None, None) + self.top_block = [] + self._parse_file(filename, None, None, None, self.top_block) # Build Symbol.dep for all symbols self._build_dep() @@ -405,6 +409,10 @@ class Config(object): """ self._warnings = [] + # Regular expressions for parsing .config files + _set_re_match = re.compile(r"{}(\w+)=(.*)".format(self.config_prefix)).match + _unset_re_match = re.compile(r"# {}(\w+) is not set".format(self.config_prefix)).match + # Put this first so that a missing file doesn't screw up our state filename = os.path.expandvars(filename) line_feeder = _FileFeed(filename) @@ -524,14 +532,12 @@ class Config(object): with open(filename, "w") as f: # Write header if header is not None: - f.write(_comment(header)) - f.write("\n") + f.write(_comment(header) + "\n") # Build and write configuration conf_strings = [] _make_block_conf(self.top_block, conf_strings.append) - f.write("\n".join(conf_strings)) - f.write("\n") + f.write("\n".join(conf_strings) + "\n") def eval(self, s): """Returns the value of the expression 's' -- where 's' is represented @@ -609,16 +615,18 @@ class Config(object): # Kconfig parsing # - def _parse_file(self, filename, parent, deps, visible_if_deps, res=None): - """Parses the Kconfig file 'filename'. Returns a list with the Items in - the file. See _parse_block() for the meaning of the parameters.""" - return self._parse_block(_FileFeed(filename), None, parent, deps, - visible_if_deps, res) + def _parse_file(self, filename, parent, deps, visible_if_deps, block): + """Parses the Kconfig file 'filename'. Appends the Items in the file + (and any file it sources) to the list passed in the 'block' parameter. + See _parse_block() for the meaning of the parameters.""" + self._parse_block(_FileFeed(filename), None, parent, deps, + visible_if_deps, block) def _parse_block(self, line_feeder, end_marker, parent, deps, - visible_if_deps, res=None): + visible_if_deps, block): """Parses a block, which is the contents of either a file or an if, - menu, or choice statement. Returns a list with the Items in the block. + menu, or choice statement. Appends the Items to the list passed in the + 'block' parameter. line_feeder: A _FileFeed instance feeding lines from a file. The Kconfig language is line-based in practice. @@ -634,10 +642,7 @@ class Config(object): visible_if_deps (default: None): 'visible if' dependencies from enclosing menus. - res (default: None): The list to add items to. If None, a new list is - created to hold the items.""" - - block = [] if res is None else res + block: The list to add items to.""" while 1: # Do we already have a tokenized line that we determined wasn't @@ -656,7 +661,7 @@ class Config(object): if end_marker is not None: raise Kconfig_Syntax_Error("Unexpected end of file {0}" .format(line_feeder.filename)) - return block + return tokens = self._tokenize(line, False, line_feeder.filename, line_feeder.linenr) @@ -679,14 +684,13 @@ class Config(object): # choice statements, the choice statement takes precedence. if not sym.is_defined_ or isinstance(parent, Choice): sym.parent = parent - sym.is_defined_ = True + self._parse_properties(line_feeder, sym, deps, visible_if_deps) + self.kconfig_syms.append(sym) block.append(sym) - self._parse_properties(line_feeder, sym, deps, visible_if_deps) - elif t0 == T_SOURCE: kconfig_file = tokens.get_next() exp_kconfig_file = self._expand_sym_refs(kconfig_file) @@ -705,7 +709,7 @@ class Config(object): elif t0 == end_marker: # We have reached the end of the block - return block + return elif t0 == T_IF: # If statements are treated as syntactic sugar for adding @@ -722,38 +726,39 @@ class Config(object): elif t0 == T_COMMENT: comment = Comment() - comment.config = self comment.parent = parent comment.filename = line_feeder.filename comment.linenr = line_feeder.linenr comment.text = tokens.get_next() - self.comments.append(comment) - block.append(comment) - self._parse_properties(line_feeder, comment, deps, visible_if_deps) + self.comments.append(comment) + block.append(comment) + elif t0 == T_MENU: menu = Menu() - menu.config = self menu.parent = parent menu.filename = line_feeder.filename menu.linenr = line_feeder.linenr menu.title = tokens.get_next() - self.menus.append(menu) - block.append(menu) - - # Parse properties and contents self._parse_properties(line_feeder, menu, deps, visible_if_deps) - menu.block = self._parse_block(line_feeder, T_ENDMENU, menu, - menu.dep_expr, - _make_and(visible_if_deps, - menu.visible_if_expr)) + + # This needs to go before _parse_block() so that we get the + # proper menu ordering in the case of nested functions + self.menus.append(menu) + # Parse contents and put Items in menu.block + self._parse_block(line_feeder, T_ENDMENU, menu, menu.dep_expr, + _make_and(visible_if_deps, + menu.visible_if_expr), + menu.block) + + block.append(menu) elif t0 == T_CHOICE: name = tokens.get_next() @@ -775,11 +780,12 @@ class Config(object): choice.def_locations.append((line_feeder.filename, line_feeder.linenr)) - # Parse properties and contents self._parse_properties(line_feeder, choice, deps, visible_if_deps) - choice.block = self._parse_block(line_feeder, T_ENDCHOICE, - choice, deps, visible_if_deps) + + # Parse contents and put Items in choice.block + self._parse_block(line_feeder, T_ENDCHOICE, choice, deps, + visible_if_deps, choice.block) choice._determine_actual_symbols() @@ -819,19 +825,19 @@ class Config(object): """Parses '<expr1> if <expr2>' constructs, where the 'if' part is optional. Returns a tuple containing the parsed expressions, with None as the second element if the 'if' part is missing.""" - val = self._parse_expr(tokens, stmt, line, filename, linenr, False) - if tokens.check(T_IF): - return (val, self._parse_expr(tokens, stmt, line, filename, - linenr)) - return (val, None) + return (self._parse_expr(tokens, stmt, line, filename, linenr, + False), + self._parse_expr(tokens, stmt, line, filename, linenr) + if tokens.check(T_IF) else None) # In case the symbol is defined in multiple locations, we need to - # remember what prompts, defaults, and selects are new for this - # definition, as "depends on" should only apply to the local + # remember what prompts, defaults, selects, and implies are new for + # this definition, as "depends on" should only apply to the local # definition. new_prompt = None new_def_exprs = [] new_selects = [] + new_implies = [] # Dependencies from 'depends on' statements depends_on_expr = None @@ -897,18 +903,27 @@ class Config(object): line_feeder.unget() - elif t0 == T_SELECT or t0 == T_IMPLY: + elif t0 == T_SELECT: target = tokens.get_next() stmt.referenced_syms.add(target) stmt.selected_syms.add(target) - if tokens.check(T_IF): - new_selects.append((target, - self._parse_expr(tokens, stmt, line, - filename, linenr))) - else: - new_selects.append((target, None)) + new_selects.append( + (target, + self._parse_expr(tokens, stmt, line, filename, linenr) + if tokens.check(T_IF) else None)) + + elif t0 == T_IMPLY: + target = tokens.get_next() + + stmt.referenced_syms.add(target) + stmt.implied_syms.add(target) + + new_implies.append( + (target, + self._parse_expr(tokens, stmt, line, filename, linenr) + if tokens.check(T_IF) else None)) elif t0 in (T_BOOL, T_TRISTATE, T_INT, T_HEX, T_STRING): stmt.type = TOKEN_TO_TYPE[t0] @@ -939,12 +954,10 @@ class Config(object): stmt.referenced_syms.add(low) stmt.referenced_syms.add(high) - if tokens.check(T_IF): - stmt.ranges.append((low, high, - self._parse_expr(tokens, stmt, line, - filename, linenr))) - else: - stmt.ranges.append((low, high, None)) + stmt.ranges.append( + (low, high, + self._parse_expr(tokens, stmt, line, filename, linenr) + if tokens.check(T_IF) else None)) elif t0 == T_DEF_TRISTATE: stmt.type = TRISTATE @@ -1051,21 +1064,20 @@ class Config(object): # Symbol or Choice # See comment for 'menu_dep' - stmt.menu_dep = depends_on_expr + stmt.menu_dep = _make_and(deps, depends_on_expr) # Propagate dependencies to prompts if new_prompt is not None: - # Propagate 'visible if' dependencies from enclosing menus prompt, cond_expr = new_prompt - cond_expr = _make_and(cond_expr, visible_if_deps) - # Propagate 'depends on' dependencies - new_prompt = (prompt, _make_and(cond_expr, depends_on_expr)) + # Propagate 'visible if' dependencies from menus and local + # 'depends on' dependencies + cond_expr = _make_and(_make_and(cond_expr, visible_if_deps), + depends_on_expr) # Save original - stmt.orig_prompts.append(new_prompt) + stmt.orig_prompts.append((prompt, cond_expr)) # Finalize with dependencies from enclosing menus and ifs - stmt.prompts.append((new_prompt[0], - _make_and(new_prompt[1], deps))) + stmt.prompts.append((prompt, _make_and(cond_expr, deps))) # Propagate dependencies to defaults @@ -1078,20 +1090,27 @@ class Config(object): stmt.def_exprs.extend([(val_expr, _make_and(cond_expr, deps)) for val_expr, cond_expr in new_def_exprs]) - # Propagate dependencies to selects + # Propagate dependencies to selects and implies - # Only symbols can select + # Only symbols can select and imply if isinstance(stmt, Symbol): # Propagate 'depends on' dependencies new_selects = [(target, _make_and(cond_expr, depends_on_expr)) for target, cond_expr in new_selects] + new_implies = [(target, _make_and(cond_expr, depends_on_expr)) + for target, cond_expr in new_implies] # Save original stmt.orig_selects.extend(new_selects) + stmt.orig_implies.extend(new_implies) # Finalize with dependencies from enclosing menus and ifs for target, cond in new_selects: - target.rev_dep = _make_or(target.rev_dep, - _make_and(stmt, - _make_and(cond, deps))) + target.rev_dep = \ + _make_or(target.rev_dep, + _make_and(stmt, _make_and(cond, deps))) + for target, cond in new_implies: + target.weak_rev_dep = \ + _make_or(target.weak_rev_dep, + _make_and(stmt, _make_and(cond, deps))) def _parse_expr(self, feed, cur_item, line, filename=None, linenr=None, transform_m=True): @@ -1483,7 +1502,8 @@ class Config(object): # The directly dependent symbols of a symbol are: # - Any symbols whose prompts, default values, rev_dep (select - # condition), or ranges depend on the symbol + # condition), weak_rev_dep (imply condition) or ranges depend on the + # symbol # - Any symbols that belong to the same choice statement as the symbol # (these won't be included in 'dep' as that makes the dependency # graph unwieldy, but Symbol._get_dependent() will include them) @@ -1497,6 +1517,7 @@ class Config(object): add_expr_deps(e, sym) add_expr_deps(sym.rev_dep, sym) + add_expr_deps(sym.weak_rev_dep, sym) for l, u, e in sym.ranges: add_expr_deps(l, sym) @@ -1625,20 +1646,16 @@ class Config(object): else: prompts_str_rows = [] for prompt, cond_expr in sc.orig_prompts: - if cond_expr is None: - prompts_str_rows.append(' "{0}"'.format(prompt)) - else: - prompts_str_rows.append( - ' "{0}" if {1}'.format(prompt, - self._expr_val_str(cond_expr))) + prompts_str_rows.append( + ' "{0}"'.format(prompt) if cond_expr is None else + ' "{0}" if {1}'.format(prompt, + self._expr_val_str(cond_expr))) prompts_str = "\n".join(prompts_str_rows) # Build locations string - if not sc.def_locations: - locations_str = "(no locations)" - else: - locations_str = " ".join(["{0}:{1}".format(filename, linenr) for - (filename, linenr) in sc.def_locations]) + locations_str = "(no locations)" if not sc.def_locations else \ + " ".join(["{0}:{1}".format(filename, linenr) for + filename, linenr in sc.def_locations]) # Build additional-dependencies-from-menus-and-ifs string additional_deps_str = " " + \ @@ -1657,13 +1674,11 @@ class Config(object): else: ranges_str_rows = [] for l, u, cond_expr in sc.ranges: - if cond_expr is None: - ranges_str_rows.append(" [{0}, {1}]".format(s(l), - s(u))) - else: - ranges_str_rows.append(" [{0}, {1}] if {2}" - .format(s(l), s(u), - self._expr_val_str(cond_expr))) + ranges_str_rows.append( + " [{0}, {1}]".format(s(l), s(u)) + if cond_expr is None else + " [{0}, {1}] if {2}" + .format(s(l), s(u), self._expr_val_str(cond_expr))) ranges_str = "\n".join(ranges_str_rows) # Build default values string @@ -1685,14 +1700,24 @@ class Config(object): else: selects_str_rows = [] for target, cond_expr in sc.orig_selects: - if cond_expr is None: - selects_str_rows.append(" {0}".format(target.name)) - else: - selects_str_rows.append( - " {0} if {1}".format(target.name, - self._expr_val_str(cond_expr))) + selects_str_rows.append( + " {0}".format(target.name) if cond_expr is None else + " {0} if {1}".format(target.name, + self._expr_val_str(cond_expr))) selects_str = "\n".join(selects_str_rows) + # Build implies string + if not sc.orig_implies: + implies_str = " (no implies)" + else: + implies_str_rows = [] + for target, cond_expr in sc.orig_implies: + implies_str_rows.append( + " {0}".format(target.name) if cond_expr is None else + " {0} if {1}".format(target.name, + self._expr_val_str(cond_expr))) + implies_str = "\n".join(implies_str_rows) + res = _lines("Symbol " + ("(no name)" if sc.name is None else sc.name), "Type : " + TYPENAME[sc.type], @@ -1711,9 +1736,16 @@ class Config(object): defaults_str, "Selects:", selects_str, + "Implies:", + implies_str, "Reverse (select-related) dependencies:", - " (no reverse dependencies)" if sc.rev_dep == "n" - else " " + self._expr_val_str(sc.rev_dep), + " (no reverse dependencies)" + if sc.rev_dep == "n" + else " " + self._expr_val_str(sc.rev_dep), + "Weak reverse (imply-related) dependencies:", + " (no weak reverse dependencies)" + if sc.weak_rev_dep == "n" + else " " + self._expr_val_str(sc.weak_rev_dep), "Additional dependencies from enclosing menus " "and ifs:", additional_deps_str, @@ -1735,11 +1767,10 @@ class Config(object): else: defaults_str_rows = [] for sym, cond_expr in sc.orig_def_exprs: - if cond_expr is None: - defaults_str_rows.append(" {0}".format(sym.name)) - else: - defaults_str_rows.append(" {0} if {1}".format(sym.name, - self._expr_val_str(cond_expr))) + defaults_str_rows.append( + " {0}".format(sym.name) if cond_expr is None else + " {0} if {1}".format(sym.name, + self._expr_val_str(cond_expr))) defaults_str = "\n".join(defaults_str_rows) # Build contained symbols string @@ -1919,26 +1950,25 @@ class Symbol(Item): self.write_to_conf = (mode != "n") if mode == "y": - if choice.get_selection() is self: - new_val = "y" - else: - new_val = "n" + new_val = "y" if choice.get_selection() is self \ + else "n" elif mode == "m": if self.user_val == "m" or self.user_val == "y": new_val = "m" else: # If the symbol is visible and has a user value, use that. - # Otherwise, look at defaults. - use_defaults = True + # Otherwise, look at defaults and weak reverse dependencies + # (implies). + use_defaults_and_weak_rev_deps = True if vis != "n": self.write_to_conf = True if self.user_val is not None: new_val = self.config._eval_min(self.user_val, vis) - use_defaults = False + use_defaults_and_weak_rev_deps = False - if use_defaults: + if use_defaults_and_weak_rev_deps: for val_expr, cond_expr in self.def_exprs: cond_eval = self.config._eval_expr(cond_expr) if cond_eval != "n": @@ -1947,14 +1977,25 @@ class Symbol(Item): cond_eval) break + weak_rev_dep_val = \ + self.config._eval_expr(self.weak_rev_dep) + if weak_rev_dep_val != "n": + self.write_to_conf = True + new_val = self.config._eval_max(new_val, + weak_rev_dep_val) + # Reverse (select-related) dependencies take precedence rev_dep_val = self.config._eval_expr(self.rev_dep) if rev_dep_val != "n": self.write_to_conf = True new_val = self.config._eval_max(new_val, rev_dep_val) - # Promote "m" to "y" for booleans - if new_val == "m" and self.type == BOOL: + # We need to promote "m" to "y" in two circumstances: + # 1) If our type is boolean + # 2) If our weak_rev_dep (from IMPLY) is "y" + if new_val == "m" and \ + (self.type == BOOL or + self.config._eval_expr(self.weak_rev_dep) == "y"): new_val = "y" elif self.type == INT or self.type == HEX: @@ -2189,6 +2230,13 @@ class Symbol(Item): get_referenced_symbols().""" return self.selected_syms + def get_implied_symbols(self): + """Returns the set() of all symbols X for which this symbol has an + 'imply X' or 'imply X if Y' (regardless of whether Y is satisfied or + not). This is a subset of the symbols returned by + get_referenced_symbols().""" + return self.implied_syms + def set_user_value(self, v): """Sets the user value of the symbol. @@ -2304,16 +2352,18 @@ class Symbol(Item): self.ranges = [] # 'range' properties (for int and hex) self.help = None # Help text self.rev_dep = "n" # Reverse (select-related) dependencies + self.weak_rev_dep = "n" # Weak reverse (imply-related) dependencies self.config = None self.parent = None self.user_val = None # Value set by user - # The prompt, default value and select conditions without any + # The prompt, default value, select, and imply conditions without any # dependencies from menus and ifs propagated to them self.orig_prompts = [] self.orig_def_exprs = [] self.orig_selects = [] + self.orig_implies = [] # Dependencies inherited from containing menus and ifs self.deps_from_containing = None @@ -2323,13 +2373,15 @@ class Symbol(Item): # The set of symbols selected by this symbol (see # get_selected_symbols()) self.selected_syms = set() + # The set of symbols implied by this symbol (see get_implied_symbols()) + self.implied_syms = set() # Like 'referenced_syms', but includes symbols from # dependencies inherited from enclosing menus and ifs self.all_referenced_syms = set() - # This records only dependencies specified with 'depends on'. Needed - # when determining actual choice items (hrrrr...). See also - # Choice._determine_actual_symbols(). + # This records only dependencies from enclosing ifs and menus together + # with local 'depends on' dependencies. Needed when determining actual + # choice items (hrrrr...). See Choice._determine_actual_symbols(). self.menu_dep = None # See Symbol.get_ref/def_locations(). @@ -2470,18 +2522,17 @@ class Symbol(Item): return if self.type == BOOL or self.type == TRISTATE: - if val == "y" or val == "m": - append_fn("CONFIG_{0}={1}".format(self.name, val)) - else: - append_fn("# CONFIG_{0} is not set".format(self.name)) + append_fn("{0}{1}={2}".format(self.config.config_prefix, self.name, val) + if val == "y" or val == "m" else + "# {0}{1} is not set".format(self.config.config_prefix, self.name)) elif self.type == INT or self.type == HEX: - append_fn("CONFIG_{0}={1}".format(self.name, val)) + append_fn("{0}{1}={2}".format(self.config.config_prefix, self.name, val)) elif self.type == STRING: # Escape \ and " - append_fn('CONFIG_{0}="{1}"' - .format(self.name, + append_fn('{0}{1}="{2}"' + .format(self.config.config_prefix, self.name, val.replace("\\", "\\\\").replace('"', '\\"'))) else: @@ -2635,7 +2686,7 @@ class Menu(Item): self.title = None self.dep_expr = None self.visible_if_expr = None - self.block = None + self.block = [] # List of contained items self.config = None self.parent = None @@ -2852,7 +2903,7 @@ class Choice(Item): self.prompts = [] self.def_exprs = [] # 'default' properties self.help = None # Help text - self.block = None # List of contained items + self.block = [] # List of contained items self.config = None self.parent = None @@ -3177,7 +3228,13 @@ def _get_visibility(sc): vis = sc.config._eval_max(vis, cond_expr) if isinstance(sc, Symbol) and sc.is_choice_sym: - vis = sc.config._eval_min(vis, _get_visibility(sc.parent)) + if sc.type == TRISTATE and vis == "m" and \ + sc.parent.get_mode() == "y": + # Choice symbols with visibility "m" are not visible if the + # choice has mode "y" + vis = "n" + else: + vis = sc.config._eval_min(vis, _get_visibility(sc.parent)) # Promote "m" to "y" if we're dealing with a non-tristate if vis == "m" and sc.type != TRISTATE: @@ -3434,7 +3491,7 @@ _get_keyword = \ "prompt": T_PROMPT, "default": T_DEFAULT, "bool": T_BOOL, "boolean": T_BOOL, "tristate": T_TRISTATE, "int": T_INT, "hex": T_HEX, "def_bool": T_DEF_BOOL, "def_tristate": T_DEF_TRISTATE, "string": T_STRING, "select": T_SELECT, - "imply": T_IMPLY, "range": T_RANGE, "option": T_OPTION, + "imply" : T_IMPLY, "range": T_RANGE, "option": T_OPTION, "allnoconfig_y": T_ALLNOCONFIG_Y, "env": T_ENV, "defconfig_list": T_DEFCONFIG_LIST, "modules": T_MODULES, "visible": T_VISIBLE}.get @@ -3455,10 +3512,6 @@ _initial_token_re_match = re.compile(r"[^\w]*(\w+)\s*").match # trailing whitespace as an optimization. _id_keyword_re_match = re.compile(r"\s*([\w./-]+)\s*").match -# Regular expressions for parsing .config files -_set_re_match = re.compile(r"CONFIG_(\w+)=(.*)").match -_unset_re_match = re.compile(r"# CONFIG_(\w+) is not set").match - # Regular expression for finding $-references to symbols in strings _sym_ref_re_search = re.compile(r"\$[A-Za-z0-9_]+").search diff --git a/tools/moveconfig.py b/tools/moveconfig.py index 6f549a51c1..e3116461ba 100755 --- a/tools/moveconfig.py +++ b/tools/moveconfig.py @@ -1472,7 +1472,7 @@ def find_kconfig_rules(kconf, config, imply_config): """ sym = kconf.get_symbol(imply_config) if sym: - for sel in sym.get_selected_symbols(): + for sel in sym.get_selected_symbols() | sym.get_implied_symbols(): if sel.get_name() == config: return sym return None |