diff options
168 files changed, 3055 insertions, 1164 deletions
diff --git a/Documentation/devicetree/bindings/arm/samsung/pmu.txt b/Documentation/devicetree/bindings/arm/samsung/pmu.txt index bf5fc59a6938..088584a98cf4 100644 --- a/Documentation/devicetree/bindings/arm/samsung/pmu.txt +++ b/Documentation/devicetree/bindings/arm/samsung/pmu.txt @@ -62,7 +62,7 @@ pmu_system_controller: system-controller@10040000 { Example of clock consumer : -usb3503: usb3503@08 { +usb3503: usb3503@8 { /* ... */ clock-names = "refclk"; clocks = <&pmu_system_controller 0>; diff --git a/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt b/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt index 3c551894f621..fa674818e7e8 100644 --- a/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt +++ b/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt @@ -71,7 +71,7 @@ Optional nodes: - compatible: only "samsung,secure-firmware" is currently supported - reg: address of non-secure SYSRAM used for communication with firmware - firmware@0203F000 { + firmware@203F000 { compatible = "samsung,secure-firmware"; reg = <0x0203F000 0x1000>; }; diff --git a/Documentation/devicetree/bindings/arm/sp810.txt b/Documentation/devicetree/bindings/arm/sp810.txt index 6808fb5dee40..1b2ab1ff5587 100644 --- a/Documentation/devicetree/bindings/arm/sp810.txt +++ b/Documentation/devicetree/bindings/arm/sp810.txt @@ -33,7 +33,7 @@ Required properties: property with the highest frequency Example: - v2m_sysctl: sysctl@020000 { + v2m_sysctl: sysctl@20000 { compatible = "arm,sp810", "arm,primecell"; reg = <0x020000 0x1000>; clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&smbclk>; diff --git a/Documentation/devicetree/bindings/arm/vexpress-sysreg.txt b/Documentation/devicetree/bindings/arm/vexpress-sysreg.txt index 00318d083c9e..50095802fb4a 100644 --- a/Documentation/devicetree/bindings/arm/vexpress-sysreg.txt +++ b/Documentation/devicetree/bindings/arm/vexpress-sysreg.txt @@ -37,7 +37,7 @@ Example: compatible = "arm,vexpress-sysreg"; reg = <0x10000000 0x1000>; - v2m_led_gpios: sys_led@08 { + v2m_led_gpios: sys_led@8 { compatible = "arm,vexpress-sysreg,sys_led"; gpio-controller; #gpio-cells = <2>; diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.txt b/Documentation/devicetree/bindings/ata/ahci-platform.txt index fedc213b5f1a..c760ecb81381 100644 --- a/Documentation/devicetree/bindings/ata/ahci-platform.txt +++ b/Documentation/devicetree/bindings/ata/ahci-platform.txt @@ -56,7 +56,7 @@ Examples: interrupts = <115>; }; - ahci: sata@01c18000 { + ahci: sata@1c18000 { compatible = "allwinner,sun4i-a10-ahci"; reg = <0x01c18000 0x1000>; interrupts = <56>; diff --git a/Documentation/devicetree/bindings/ata/imx-sata.txt b/Documentation/devicetree/bindings/ata/imx-sata.txt index fa511db18408..a3d14719e478 100644 --- a/Documentation/devicetree/bindings/ata/imx-sata.txt +++ b/Documentation/devicetree/bindings/ata/imx-sata.txt @@ -25,7 +25,7 @@ Optional properties: Examples: -sata@02200000 { +sata@2200000 { compatible = "fsl,imx6q-ahci"; reg = <0x02200000 0x4000>; interrupts = <0 39 IRQ_TYPE_LEVEL_HIGH>; diff --git a/Documentation/devicetree/bindings/bus/imx-weim.txt b/Documentation/devicetree/bindings/bus/imx-weim.txt index 6630d842c7a3..683eaf3aed79 100644 --- a/Documentation/devicetree/bindings/bus/imx-weim.txt +++ b/Documentation/devicetree/bindings/bus/imx-weim.txt @@ -61,7 +61,7 @@ Timing property for child nodes. It is mandatory, not optional. Example for an imx6q-sabreauto board, the NOR flash connected to the WEIM: - weim: weim@021b8000 { + weim: weim@21b8000 { compatible = "fsl,imx6q-weim"; reg = <0x021b8000 0x4000>; clocks = <&clks 196>; diff --git a/Documentation/devicetree/bindings/bus/sunxi-rsb.txt b/Documentation/devicetree/bindings/bus/sunxi-rsb.txt index 3dd28343b6ce..eb3ed628c6f1 100644 --- a/Documentation/devicetree/bindings/bus/sunxi-rsb.txt +++ b/Documentation/devicetree/bindings/bus/sunxi-rsb.txt @@ -28,7 +28,7 @@ which can normally be found in the datasheet. Example: - rsb@01f03400 { + rsb@1f03400 { compatible = "allwinner,sun8i-a23-rsb"; reg = <0x01f03400 0x400>; interrupts = <0 39 4>; diff --git a/Documentation/devicetree/bindings/clock/arm-syscon-icst.txt b/Documentation/devicetree/bindings/clock/arm-syscon-icst.txt index 27468119fd94..4cd81742038f 100644 --- a/Documentation/devicetree/bindings/clock/arm-syscon-icst.txt +++ b/Documentation/devicetree/bindings/clock/arm-syscon-icst.txt @@ -59,7 +59,7 @@ syscon: syscon@10000000 { compatible = "syscon"; reg = <0x10000000 0x1000>; - oscclk0: osc0@0c { + oscclk0: osc0@c { compatible = "arm,syscon-icst307"; #clock-cells = <0>; lock-offset = <0x20>; diff --git a/Documentation/devicetree/bindings/clock/clk-exynos-audss.txt b/Documentation/devicetree/bindings/clock/clk-exynos-audss.txt index 0c3d6015868d..2cba012f5af0 100644 --- a/Documentation/devicetree/bindings/clock/clk-exynos-audss.txt +++ b/Documentation/devicetree/bindings/clock/clk-exynos-audss.txt @@ -80,7 +80,7 @@ Example 3: I2S controller node that consumes the clock generated by the clock controller. Refer to the standard clock bindings for information about 'clocks' and 'clock-names' property. -i2s0: i2s@03830000 { +i2s0: i2s@3830000 { compatible = "samsung,i2s-v5"; reg = <0x03830000 0x100>; dmas = <&pdma0 10 diff --git a/Documentation/devicetree/bindings/clock/clk-s5pv210-audss.txt b/Documentation/devicetree/bindings/clock/clk-s5pv210-audss.txt index 4fc869b69d4a..f6272dcd96f4 100644 --- a/Documentation/devicetree/bindings/clock/clk-s5pv210-audss.txt +++ b/Documentation/devicetree/bindings/clock/clk-s5pv210-audss.txt @@ -43,7 +43,7 @@ Example: I2S controller node that consumes the clock generated by the clock controller. Refer to the standard clock bindings for information about 'clocks' and 'clock-names' property. - i2s0: i2s@03830000 { + i2s0: i2s@3830000 { /* ... */ clock-names = "iis", "i2s_opclk0", "i2s_opclk1"; diff --git a/Documentation/devicetree/bindings/clock/dove-divider-clock.txt b/Documentation/devicetree/bindings/clock/dove-divider-clock.txt index e3eb0f657c5e..217871f483c0 100644 --- a/Documentation/devicetree/bindings/clock/dove-divider-clock.txt +++ b/Documentation/devicetree/bindings/clock/dove-divider-clock.txt @@ -21,7 +21,7 @@ Required properties: a size of 8. - #clock-cells : from common clock binding; shall be set to 1 -divider_clk: core-clock@0064 { +divider_clk: core-clock@64 { compatible = "marvell,dove-divider-clock"; reg = <0x0064 0x8>; #clock-cells = <1>; diff --git a/Documentation/devicetree/bindings/clock/imx1-clock.txt b/Documentation/devicetree/bindings/clock/imx1-clock.txt index b7adf4e3ea98..9823baf7acb6 100644 --- a/Documentation/devicetree/bindings/clock/imx1-clock.txt +++ b/Documentation/devicetree/bindings/clock/imx1-clock.txt @@ -10,13 +10,13 @@ ID in its "clocks" phandle cell. See include/dt-bindings/clock/imx1-clock.h for the full list of i.MX1 clock IDs. Examples: - clks: ccm@0021b000 { + clks: ccm@21b000 { #clock-cells = <1>; compatible = "fsl,imx1-ccm"; reg = <0x0021b000 0x1000>; }; - pwm: pwm@00208000 { + pwm: pwm@208000 { #pwm-cells = <2>; compatible = "fsl,imx1-pwm"; reg = <0x00208000 0x1000>; diff --git a/Documentation/devicetree/bindings/clock/imx6q-clock.txt b/Documentation/devicetree/bindings/clock/imx6q-clock.txt index aa0a4d423ef5..a45ca67a9d5f 100644 --- a/Documentation/devicetree/bindings/clock/imx6q-clock.txt +++ b/Documentation/devicetree/bindings/clock/imx6q-clock.txt @@ -14,14 +14,14 @@ Examples: #include <dt-bindings/clock/imx6qdl-clock.h> -clks: ccm@020c4000 { +clks: ccm@20c4000 { compatible = "fsl,imx6q-ccm"; reg = <0x020c4000 0x4000>; interrupts = <0 87 0x04 0 88 0x04>; #clock-cells = <1>; }; -uart1: serial@02020000 { +uart1: serial@2020000 { compatible = "fsl,imx6q-uart", "fsl,imx21-uart"; reg = <0x02020000 0x4000>; interrupts = <0 26 0x04>; diff --git a/Documentation/devicetree/bindings/clock/maxim,max77686.txt b/Documentation/devicetree/bindings/clock/maxim,max77686.txt index 8398a3a5e106..3472b461ca93 100644 --- a/Documentation/devicetree/bindings/clock/maxim,max77686.txt +++ b/Documentation/devicetree/bindings/clock/maxim,max77686.txt @@ -46,7 +46,7 @@ Example: /* ... */ Node of the MFD chip - max77686: max77686@09 { + max77686: max77686@9 { compatible = "maxim,max77686"; interrupt-parent = <&wakeup_eint>; interrupts = <26 0>; @@ -71,7 +71,7 @@ Example: /* ... */ Node of the MFD chip - max77802: max77802@09 { + max77802: max77802@9 { compatible = "maxim,max77802"; interrupt-parent = <&wakeup_eint>; interrupts = <26 0>; diff --git a/Documentation/devicetree/bindings/clock/st/st,clkgen.txt b/Documentation/devicetree/bindings/clock/st/st,clkgen.txt index c35390f60545..7364953d0d0b 100644 --- a/Documentation/devicetree/bindings/clock/st/st,clkgen.txt +++ b/Documentation/devicetree/bindings/clock/st/st,clkgen.txt @@ -42,7 +42,7 @@ Required properties: Example: - clockgen-a@090ff000 { + clockgen-a@90ff000 { compatible = "st,clkgen-c32"; reg = <0x90ff000 0x1000>; diff --git a/Documentation/devicetree/bindings/clock/sunxi-ccu.txt b/Documentation/devicetree/bindings/clock/sunxi-ccu.txt index 7eda08eb8a1e..4ca21c3a6fc9 100644 --- a/Documentation/devicetree/bindings/clock/sunxi-ccu.txt +++ b/Documentation/devicetree/bindings/clock/sunxi-ccu.txt @@ -36,7 +36,7 @@ For the PRCM CCUs on A83T/H3/A64, two more clocks are needed: - "iosc": the SoC's internal frequency oscillator Example for generic CCU: -ccu: clock@01c20000 { +ccu: clock@1c20000 { compatible = "allwinner,sun8i-h3-ccu"; reg = <0x01c20000 0x400>; clocks = <&osc24M>, <&osc32k>; @@ -46,7 +46,7 @@ ccu: clock@01c20000 { }; Example for PRCM CCU: -r_ccu: clock@01f01400 { +r_ccu: clock@1f01400 { compatible = "allwinner,sun50i-a64-r-ccu"; reg = <0x01f01400 0x100>; clocks = <&osc24M>, <&osc32k>, <&iosc>, <&ccu CLK_PLL_PERIPH0>; diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt index 8f7619d8c8d8..1a042e20b115 100644 --- a/Documentation/devicetree/bindings/clock/sunxi.txt +++ b/Documentation/devicetree/bindings/clock/sunxi.txt @@ -137,7 +137,7 @@ the address block, which is related to the overall mmc block. For example: -osc24M: clk@01c20050 { +osc24M: clk@1c20050 { #clock-cells = <0>; compatible = "allwinner,sun4i-a10-osc-clk"; reg = <0x01c20050 0x4>; @@ -145,7 +145,7 @@ osc24M: clk@01c20050 { clock-output-names = "osc24M"; }; -pll1: clk@01c20000 { +pll1: clk@1c20000 { #clock-cells = <0>; compatible = "allwinner,sun4i-a10-pll1-clk"; reg = <0x01c20000 0x4>; @@ -153,7 +153,7 @@ pll1: clk@01c20000 { clock-output-names = "pll1"; }; -pll5: clk@01c20020 { +pll5: clk@1c20020 { #clock-cells = <1>; compatible = "allwinner,sun4i-pll5-clk"; reg = <0x01c20020 0x4>; @@ -161,7 +161,7 @@ pll5: clk@01c20020 { clock-output-names = "pll5_ddr", "pll5_other"; }; -pll6: clk@01c20028 { +pll6: clk@1c20028 { #clock-cells = <1>; compatible = "allwinner,sun6i-a31-pll6-clk"; reg = <0x01c20028 0x4>; @@ -169,7 +169,7 @@ pll6: clk@01c20028 { clock-output-names = "pll6", "pll6x2"; }; -cpu: cpu@01c20054 { +cpu: cpu@1c20054 { #clock-cells = <0>; compatible = "allwinner,sun4i-a10-cpu-clk"; reg = <0x01c20054 0x4>; @@ -177,7 +177,7 @@ cpu: cpu@01c20054 { clock-output-names = "cpu"; }; -mmc0_clk: clk@01c20088 { +mmc0_clk: clk@1c20088 { #clock-cells = <1>; compatible = "allwinner,sun4i-a10-mmc-clk"; reg = <0x01c20088 0x4>; @@ -199,7 +199,7 @@ gmac_int_tx_clk: clk@3 { clock-output-names = "gmac_int_tx"; }; -gmac_clk: clk@01c20164 { +gmac_clk: clk@1c20164 { #clock-cells = <0>; compatible = "allwinner,sun7i-a20-gmac-clk"; reg = <0x01c20164 0x4>; @@ -211,7 +211,7 @@ gmac_clk: clk@01c20164 { clock-output-names = "gmac"; }; -mmc_config_clk: clk@01c13000 { +mmc_config_clk: clk@1c13000 { compatible = "allwinner,sun9i-a80-mmc-config-clk"; reg = <0x01c13000 0x10>; clocks = <&ahb0_gates 8>; diff --git a/Documentation/devicetree/bindings/clock/ti,cdce706.txt b/Documentation/devicetree/bindings/clock/ti,cdce706.txt index 616836e7e1e2..959d96632f5d 100644 --- a/Documentation/devicetree/bindings/clock/ti,cdce706.txt +++ b/Documentation/devicetree/bindings/clock/ti,cdce706.txt @@ -25,7 +25,7 @@ Example: }; }; ... - i2c0: i2c-master@0d090000 { + i2c0: i2c-master@d090000 { ... cdce706: clock-synth@69 { compatible = "ti,cdce706"; diff --git a/Documentation/devicetree/bindings/crypto/sun4i-ss.txt b/Documentation/devicetree/bindings/crypto/sun4i-ss.txt index 5d38e9b7033f..f2dc3d9bca92 100644 --- a/Documentation/devicetree/bindings/crypto/sun4i-ss.txt +++ b/Documentation/devicetree/bindings/crypto/sun4i-ss.txt @@ -14,7 +14,7 @@ Optional properties: - reset-names : must contain "ahb" Example: - crypto: crypto-engine@01c15000 { + crypto: crypto-engine@1c15000 { compatible = "allwinner,sun4i-a10-crypto"; reg = <0x01c15000 0x1000>; interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>; diff --git a/Documentation/devicetree/bindings/display/etnaviv/etnaviv-drm.txt b/Documentation/devicetree/bindings/display/etnaviv/etnaviv-drm.txt index ed5e0a7894ad..05176f1ae108 100644 --- a/Documentation/devicetree/bindings/display/etnaviv/etnaviv-drm.txt +++ b/Documentation/devicetree/bindings/display/etnaviv/etnaviv-drm.txt @@ -42,7 +42,7 @@ Optional properties: example: -gpu_3d: gpu@00130000 { +gpu_3d: gpu@130000 { compatible = "vivante,gc"; reg = <0x00130000 0x4000>; interrupts = <0 9 IRQ_TYPE_LEVEL_HIGH>; diff --git a/Documentation/devicetree/bindings/display/imx/hdmi.txt b/Documentation/devicetree/bindings/display/imx/hdmi.txt index 66a8f86e5d12..6d021e71c9cf 100644 --- a/Documentation/devicetree/bindings/display/imx/hdmi.txt +++ b/Documentation/devicetree/bindings/display/imx/hdmi.txt @@ -32,11 +32,11 @@ Optional properties Example: - gpr: iomuxc-gpr@020e0000 { + gpr: iomuxc-gpr@20e0000 { /* ... */ }; - hdmi: hdmi@0120000 { + hdmi: hdmi@120000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx6q-hdmi"; diff --git a/Documentation/devicetree/bindings/display/simple-framebuffer.txt b/Documentation/devicetree/bindings/display/simple-framebuffer.txt index 8c9e9f515c87..5a9ce511be88 100644 --- a/Documentation/devicetree/bindings/display/simple-framebuffer.txt +++ b/Documentation/devicetree/bindings/display/simple-framebuffer.txt @@ -78,7 +78,7 @@ chosen { stdout-path = "display0"; }; -soc@01c00000 { +soc@1c00000 { lcdc0: lcdc@1c0c000 { compatible = "allwinner,sun4i-a10-lcdc"; ... diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt index 92441086caba..b7faa6f6a326 100644 --- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt +++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt @@ -266,7 +266,7 @@ connector { }; }; -hdmi: hdmi@01c16000 { +hdmi: hdmi@1c16000 { compatible = "allwinner,sun5i-a10s-hdmi"; reg = <0x01c16000 0x1000>; interrupts = <58>; @@ -305,7 +305,7 @@ hdmi: hdmi@01c16000 { }; }; -tve0: tv-encoder@01c0a000 { +tve0: tv-encoder@1c0a000 { compatible = "allwinner,sun4i-a10-tv-encoder"; reg = <0x01c0a000 0x1000>; clocks = <&ahb_gates 34>; diff --git a/Documentation/devicetree/bindings/dma/sun4i-dma.txt b/Documentation/devicetree/bindings/dma/sun4i-dma.txt index 3b484380c56a..8ad556aca70b 100644 --- a/Documentation/devicetree/bindings/dma/sun4i-dma.txt +++ b/Documentation/devicetree/bindings/dma/sun4i-dma.txt @@ -12,7 +12,7 @@ Required properties: second cell holding the request line number. Example: - dma: dma-controller@01c02000 { + dma: dma-controller@1c02000 { compatible = "allwinner,sun4i-a10-dma"; reg = <0x01c02000 0x1000>; interrupts = <27>; @@ -32,7 +32,7 @@ The three cells in order are: 3. The port ID as specified in the datasheet Example: - spi2: spi@01c17000 { + spi2: spi@1c17000 { compatible = "allwinner,sun4i-a10-spi"; reg = <0x01c17000 0x1000>; interrupts = <0 12 4>; diff --git a/Documentation/devicetree/bindings/dma/sun6i-dma.txt b/Documentation/devicetree/bindings/dma/sun6i-dma.txt index 98fbe1a5c6dd..717851407fac 100644 --- a/Documentation/devicetree/bindings/dma/sun6i-dma.txt +++ b/Documentation/devicetree/bindings/dma/sun6i-dma.txt @@ -38,7 +38,7 @@ The two cells in order are: 2. The port ID as specified in the datasheet Example: -spi2: spi@01c6a000 { +spi2: spi@1c6a000 { compatible = "allwinner,sun6i-a31-spi"; reg = <0x01c6a000 0x1000>; interrupts = <0 67 4>; diff --git a/Documentation/devicetree/bindings/dma/ti-edma.txt b/Documentation/devicetree/bindings/dma/ti-edma.txt index 41f0c1a07c56..66026dcf53e1 100644 --- a/Documentation/devicetree/bindings/dma/ti-edma.txt +++ b/Documentation/devicetree/bindings/dma/ti-edma.txt @@ -142,7 +142,7 @@ mcasp0: mcasp@48038000 { }; 2. -edma1: edma@02728000 { +edma1: edma@2728000 { compatible = "ti,k2g-edma3-tpcc", "ti,edma3-tpcc"; reg = <0x02728000 0x8000>; reg-names = "edma3_cc"; @@ -165,13 +165,13 @@ edma1: edma@02728000 { power-domains = <&k2g_pds 0x4f>; }; -edma1_tptc0: tptc@027b0000 { +edma1_tptc0: tptc@27b0000 { compatible = "ti,k2g-edma3-tptc", "ti,edma3-tptc"; reg = <0x027b0000 0x400>; power-domains = <&k2g_pds 0x4f>; }; -edma1_tptc1: tptc@027b8000 { +edma1_tptc1: tptc@27b8000 { compatible = "ti, k2g-edma3-tptc", "ti,edma3-tptc"; reg = <0x027b8000 0x400>; power-domains = <&k2g_pds 0x4f>; diff --git a/Documentation/devicetree/bindings/dma/zxdma.txt b/Documentation/devicetree/bindings/dma/zxdma.txt index 3207ceb04d0b..abec59f35fde 100644 --- a/Documentation/devicetree/bindings/dma/zxdma.txt +++ b/Documentation/devicetree/bindings/dma/zxdma.txt @@ -26,7 +26,7 @@ Controller: Client: Use specific request line passing from dmax For example, spdif0 tx channel request line is 4 - spdif0: spdif0@0b004000 { + spdif0: spdif0@b004000 { #sound-dai-cells = <0>; compatible = "zte,zx296702-spdif"; reg = <0x0b004000 0x1000>; diff --git a/Documentation/devicetree/bindings/firmware/nvidia,tegra186-bpmp.txt b/Documentation/devicetree/bindings/firmware/nvidia,tegra186-bpmp.txt index e821e16ad65b..0c10802c8327 100644 --- a/Documentation/devicetree/bindings/firmware/nvidia,tegra186-bpmp.txt +++ b/Documentation/devicetree/bindings/firmware/nvidia,tegra186-bpmp.txt @@ -66,7 +66,7 @@ See ".../sram/sram.txt" for the bindings. Example: -hsp_top0: hsp@03c00000 { +hsp_top0: hsp@3c00000 { ... #mbox-cells = <2>; }; diff --git a/Documentation/devicetree/bindings/gpio/gpio-dsp-keystone.txt b/Documentation/devicetree/bindings/gpio/gpio-dsp-keystone.txt index 6c7e6c7302f5..0423699d74c7 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-dsp-keystone.txt +++ b/Documentation/devicetree/bindings/gpio/gpio-dsp-keystone.txt @@ -25,7 +25,7 @@ Please refer to gpio.txt in this directory for details of the common GPIO bindings used by client devices. Example: - dspgpio0: keystone_dsp_gpio@02620240 { + dspgpio0: keystone_dsp_gpio@2620240 { compatible = "ti,keystone-dsp-gpio"; ti,syscon-dev = <&devctrl 0x240>; gpio-controller; diff --git a/Documentation/devicetree/bindings/gpio/gpio-tz1090-pdc.txt b/Documentation/devicetree/bindings/gpio/gpio-tz1090-pdc.txt index 1fd98ffa8cb7..528f5ef5a893 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-tz1090-pdc.txt +++ b/Documentation/devicetree/bindings/gpio/gpio-tz1090-pdc.txt @@ -30,7 +30,7 @@ Optional properties: Example: - pdc_gpios: gpio-controller@02006500 { + pdc_gpios: gpio-controller@2006500 { gpio-controller; #gpio-cells = <2>; diff --git a/Documentation/devicetree/bindings/gpio/gpio-tz1090.txt b/Documentation/devicetree/bindings/gpio/gpio-tz1090.txt index 174cdf309170..b05a90e0ab29 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-tz1090.txt +++ b/Documentation/devicetree/bindings/gpio/gpio-tz1090.txt @@ -59,7 +59,7 @@ Required properties: Example: - gpios: gpio-controller@02005800 { + gpios: gpio-controller@2005800 { #address-cells = <1>; #size-cells = <0>; compatible = "img,tz1090-gpio"; diff --git a/Documentation/devicetree/bindings/i2c/i2c-axxia.txt b/Documentation/devicetree/bindings/i2c/i2c-axxia.txt index 2296d782b4c2..7d53a2b79553 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-axxia.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-axxia.txt @@ -17,7 +17,7 @@ Optional properties : Example : -i2c@02010084000 { +i2c@2010084000 { compatible = "lsi,api2c"; device_type = "i2c"; #address-cells = <1>; diff --git a/Documentation/devicetree/bindings/i2c/i2c-sunxi-p2wi.txt b/Documentation/devicetree/bindings/i2c/i2c-sunxi-p2wi.txt index 6b765485af7d..49df0053347a 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-sunxi-p2wi.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-sunxi-p2wi.txt @@ -24,7 +24,7 @@ Slave device properties: Example: - p2wi@01f03400 { + p2wi@1f03400 { compatible = "allwinner,sun6i-a31-p2wi"; reg = <0x01f03400 0x400>; interrupts = <0 39 4>; diff --git a/Documentation/devicetree/bindings/iio/magnetometer/ak8974.txt b/Documentation/devicetree/bindings/iio/magnetometer/ak8974.txt index 77d5aba1bd8c..baecc4a85197 100644 --- a/Documentation/devicetree/bindings/iio/magnetometer/ak8974.txt +++ b/Documentation/devicetree/bindings/iio/magnetometer/ak8974.txt @@ -19,7 +19,7 @@ Optional properties: Example: -ak8974@0f { +ak8974@f { compatible = "asahi-kasei,ak8974"; reg = <0x0f>; avdd-supply = <&foo_reg>; diff --git a/Documentation/devicetree/bindings/iio/magnetometer/ak8975.txt b/Documentation/devicetree/bindings/iio/magnetometer/ak8975.txt index e1e7dd3259f6..aa67ceb0d4e0 100644 --- a/Documentation/devicetree/bindings/iio/magnetometer/ak8975.txt +++ b/Documentation/devicetree/bindings/iio/magnetometer/ak8975.txt @@ -13,7 +13,7 @@ Optional properties: Example: -ak8975@0c { +ak8975@c { compatible = "asahi-kasei,ak8975"; reg = <0x0c>; gpios = <&gpj0 7 0>; diff --git a/Documentation/devicetree/bindings/input/sun4i-lradc-keys.txt b/Documentation/devicetree/bindings/input/sun4i-lradc-keys.txt index 4357e498ef04..1458c3179a63 100644 --- a/Documentation/devicetree/bindings/input/sun4i-lradc-keys.txt +++ b/Documentation/devicetree/bindings/input/sun4i-lradc-keys.txt @@ -19,7 +19,7 @@ Example: #include <dt-bindings/input/input.h> - lradc: lradc@01c22800 { + lradc: lradc@1c22800 { compatible = "allwinner,sun4i-a10-lradc-keys"; reg = <0x01c22800 0x100>; interrupts = <31>; diff --git a/Documentation/devicetree/bindings/input/touchscreen/egalax-ts.txt b/Documentation/devicetree/bindings/input/touchscreen/egalax-ts.txt index 49fa14ed155c..298e3442f143 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/egalax-ts.txt +++ b/Documentation/devicetree/bindings/input/touchscreen/egalax-ts.txt @@ -10,7 +10,7 @@ Required properties: Example: - egalax_ts@04 { + touchscreen@4 { compatible = "eeti,egalax_ts"; reg = <0x04>; interrupt-parent = <&gpio1>; diff --git a/Documentation/devicetree/bindings/input/touchscreen/imx6ul_tsc.txt b/Documentation/devicetree/bindings/input/touchscreen/imx6ul_tsc.txt index e67e58b61706..164915004424 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/imx6ul_tsc.txt +++ b/Documentation/devicetree/bindings/input/touchscreen/imx6ul_tsc.txt @@ -21,7 +21,7 @@ Optional properties: each read. Valid values are 1, 4, 8, 16 and 32. Example: - tsc: tsc@02040000 { + tsc: tsc@2040000 { compatible = "fsl,imx6ul-tsc"; reg = <0x02040000 0x4000>, <0x0219c000 0x4000>; interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>, diff --git a/Documentation/devicetree/bindings/interrupt-controller/allwinner,sunxi-nmi.txt b/Documentation/devicetree/bindings/interrupt-controller/allwinner,sunxi-nmi.txt index 4ae553eb333d..4903fb72d883 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/allwinner,sunxi-nmi.txt +++ b/Documentation/devicetree/bindings/interrupt-controller/allwinner,sunxi-nmi.txt @@ -20,7 +20,7 @@ Required properties: Example: -sc-nmi-intc@01c00030 { +sc-nmi-intc@1c00030 { compatible = "allwinner,sun7i-a20-sc-nmi"; interrupt-controller; #interrupt-cells = <2>; diff --git a/Documentation/devicetree/bindings/interrupt-controller/ti,keystone-irq.txt b/Documentation/devicetree/bindings/interrupt-controller/ti,keystone-irq.txt index d9bb106bdd16..5f94d7739d8d 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/ti,keystone-irq.txt +++ b/Documentation/devicetree/bindings/interrupt-controller/ti,keystone-irq.txt @@ -20,7 +20,7 @@ Please refer to interrupts.txt in this directory for details of the common Interrupt Controllers bindings used by client devices. Example: - kirq0: keystone_irq0@026202a0 { + kirq0: keystone_irq0@26202a0 { compatible = "ti,keystone-irq"; ti,syscon-dev = <&devctrl 0x2a0>; interrupts = <GIC_SPI 4 IRQ_TYPE_EDGE_RISING>; diff --git a/Documentation/devicetree/bindings/iommu/qcom,iommu.txt b/Documentation/devicetree/bindings/iommu/qcom,iommu.txt index b2641ceb2b40..059139abce35 100644 --- a/Documentation/devicetree/bindings/iommu/qcom,iommu.txt +++ b/Documentation/devicetree/bindings/iommu/qcom,iommu.txt @@ -115,7 +115,7 @@ to non-secure vs secure interrupt line. iommus = <&apps_iommu 4>; }; - gpu@01c00000 { + gpu@1c00000 { ... iommus = <&gpu_iommu 1>, <&gpu_iommu 2>; }; diff --git a/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt b/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt index 3ed027cfca95..857df929a654 100644 --- a/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt +++ b/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt @@ -53,7 +53,7 @@ Example: R8A7791 IPMMU-MX and VSP1-D0 bus master #iommu-cells = <1>; }; - vsp1@fe928000 { + vsp@fe928000 { ... iommus = <&ipmmu_mx 13>; ... diff --git a/Documentation/devicetree/bindings/leds/register-bit-led.txt b/Documentation/devicetree/bindings/leds/register-bit-led.txt index 59b56365f648..cf1ea403ba7a 100644 --- a/Documentation/devicetree/bindings/leds/register-bit-led.txt +++ b/Documentation/devicetree/bindings/leds/register-bit-led.txt @@ -32,7 +32,7 @@ syscon: syscon@10000000 { compatible = "arm,realview-pb1176-syscon", "syscon"; reg = <0x10000000 0x1000>; - led@08.0 { + led@8.0 { compatible = "register-bit-led"; offset = <0x08>; mask = <0x01>; @@ -40,7 +40,7 @@ syscon: syscon@10000000 { linux,default-trigger = "heartbeat"; default-state = "on"; }; - led@08.1 { + led@8.1 { compatible = "register-bit-led"; offset = <0x08>; mask = <0x02>; @@ -48,7 +48,7 @@ syscon: syscon@10000000 { linux,default-trigger = "mmc0"; default-state = "off"; }; - led@08.2 { + led@8.2 { compatible = "register-bit-led"; offset = <0x08>; mask = <0x04>; @@ -56,35 +56,35 @@ syscon: syscon@10000000 { linux,default-trigger = "cpu0"; default-state = "off"; }; - led@08.3 { + led@8.3 { compatible = "register-bit-led"; offset = <0x08>; mask = <0x08>; label = "versatile:3"; default-state = "off"; }; - led@08.4 { + led@8.4 { compatible = "register-bit-led"; offset = <0x08>; mask = <0x10>; label = "versatile:4"; default-state = "off"; }; - led@08.5 { + led@8.5 { compatible = "register-bit-led"; offset = <0x08>; mask = <0x20>; label = "versatile:5"; default-state = "off"; }; - led@08.6 { + led@8.6 { compatible = "register-bit-led"; offset = <0x08>; mask = <0x40>; label = "versatile:6"; default-state = "off"; }; - led@08.7 { + led@8.7 { compatible = "register-bit-led"; offset = <0x08>; mask = <0x80>; diff --git a/Documentation/devicetree/bindings/mailbox/ti,message-manager.txt b/Documentation/devicetree/bindings/mailbox/ti,message-manager.txt index b449d025049f..c3b55b3ede8a 100644 --- a/Documentation/devicetree/bindings/mailbox/ti,message-manager.txt +++ b/Documentation/devicetree/bindings/mailbox/ti,message-manager.txt @@ -29,7 +29,7 @@ Required properties: Example(K2G): ------------ - msgmgr: msgmgr@02a00000 { + msgmgr: msgmgr@2a00000 { compatible = "ti,k2g-message-manager"; #mbox-cells = <2>; reg-names = "queue_proxy_region", "queue_state_debug_region"; diff --git a/Documentation/devicetree/bindings/marvell.txt b/Documentation/devicetree/bindings/marvell.txt index ea2b16ced49b..7f722316458a 100644 --- a/Documentation/devicetree/bindings/marvell.txt +++ b/Documentation/devicetree/bindings/marvell.txt @@ -446,7 +446,7 @@ prefixed with the string "marvell,", for Marvell Technology Group Ltd. that services interrupts for this device. Example Discovery CPU Error node: - cpu-error@0070 { + cpu-error@70 { compatible = "marvell,mv64360-cpu-error"; reg = <0x70 0x10 0x128 0x28>; interrupts = <3>; @@ -466,7 +466,7 @@ prefixed with the string "marvell,", for Marvell Technology Group Ltd. that services interrupts for this device. Example Discovery SRAM Controller node: - sram-ctrl@0380 { + sram-ctrl@380 { compatible = "marvell,mv64360-sram-ctrl"; reg = <0x380 0x80>; interrupts = <13>; diff --git a/Documentation/devicetree/bindings/media/i2c/tc358743.txt b/Documentation/devicetree/bindings/media/i2c/tc358743.txt index 5218921629ed..49f8bcc2ea4d 100644 --- a/Documentation/devicetree/bindings/media/i2c/tc358743.txt +++ b/Documentation/devicetree/bindings/media/i2c/tc358743.txt @@ -27,7 +27,7 @@ Documentation/devicetree/bindings/media/video-interfaces.txt. Example: - tc358743@0f { + tc358743@f { compatible = "toshiba,tc358743"; reg = <0x0f>; clocks = <&hdmi_osc>; diff --git a/Documentation/devicetree/bindings/media/img-ir-rev1.txt b/Documentation/devicetree/bindings/media/img-ir-rev1.txt index 5434ce61b925..ed9ec52b77e0 100644 --- a/Documentation/devicetree/bindings/media/img-ir-rev1.txt +++ b/Documentation/devicetree/bindings/media/img-ir-rev1.txt @@ -25,7 +25,7 @@ Optional properties: Example: - ir@02006200 { + ir@2006200 { compatible = "img,ir-rev1"; reg = <0x02006200 0x100>; interrupts = <29 4>; diff --git a/Documentation/devicetree/bindings/media/renesas,vsp1.txt b/Documentation/devicetree/bindings/media/renesas,vsp1.txt index 9b695bcbf219..16427017cb45 100644 --- a/Documentation/devicetree/bindings/media/renesas,vsp1.txt +++ b/Documentation/devicetree/bindings/media/renesas,vsp1.txt @@ -22,7 +22,7 @@ Optional properties: Example: R8A7790 (R-Car H2) VSP1-S node - vsp1@fe928000 { + vsp@fe928000 { compatible = "renesas,vsp1"; reg = <0 0xfe928000 0 0x8000>; interrupts = <0 267 IRQ_TYPE_LEVEL_HIGH>; diff --git a/Documentation/devicetree/bindings/media/stih-cec.txt b/Documentation/devicetree/bindings/media/stih-cec.txt index 8be2a040c6c6..ece0832fdeaf 100644 --- a/Documentation/devicetree/bindings/media/stih-cec.txt +++ b/Documentation/devicetree/bindings/media/stih-cec.txt @@ -13,7 +13,7 @@ Required properties: Example for STIH407: -sti-cec@094a087c { +sti-cec@94a087c { compatible = "st,stih-cec"; reg = <0x94a087c 0x64>; clocks = <&clk_sysin>; diff --git a/Documentation/devicetree/bindings/media/stih407-c8sectpfe.txt b/Documentation/devicetree/bindings/media/stih407-c8sectpfe.txt index 6af3fc210ecc..c7888d6f6408 100644 --- a/Documentation/devicetree/bindings/media/stih407-c8sectpfe.txt +++ b/Documentation/devicetree/bindings/media/stih407-c8sectpfe.txt @@ -50,7 +50,7 @@ Example: /* stih410 SoC b2120 + b2004a + stv0367-pll(NIMB) + stv0367-tda18212 (NIMA) DT example) */ - c8sectpfe@08a20000 { + c8sectpfe@8a20000 { compatible = "st,stih407-c8sectpfe"; reg = <0x08a20000 0x10000>, <0x08a00000 0x4000>; reg-names = "stfe", "stfe-ram"; diff --git a/Documentation/devicetree/bindings/media/sunxi-ir.txt b/Documentation/devicetree/bindings/media/sunxi-ir.txt index 302a0b183cb8..91648c569b1e 100644 --- a/Documentation/devicetree/bindings/media/sunxi-ir.txt +++ b/Documentation/devicetree/bindings/media/sunxi-ir.txt @@ -14,7 +14,7 @@ Optional properties: Example: -ir0: ir@01c21800 { +ir0: ir@1c21800 { compatible = "allwinner,sun4i-a10-ir"; clocks = <&apb0_gates 6>, <&ir0_clk>; clock-names = "apb", "ir"; diff --git a/Documentation/devicetree/bindings/mfd/max77686.txt b/Documentation/devicetree/bindings/mfd/max77686.txt index 741e76688cf2..0f2587fa42cb 100644 --- a/Documentation/devicetree/bindings/mfd/max77686.txt +++ b/Documentation/devicetree/bindings/mfd/max77686.txt @@ -19,7 +19,7 @@ Required properties: Example: - max77686: pmic@09 { + max77686: pmic@9 { compatible = "maxim,max77686"; interrupt-parent = <&wakeup_eint>; interrupts = <26 0>; diff --git a/Documentation/devicetree/bindings/mfd/max77802.txt b/Documentation/devicetree/bindings/mfd/max77802.txt index 51fc1a60caa5..f2f3fe75901c 100644 --- a/Documentation/devicetree/bindings/mfd/max77802.txt +++ b/Documentation/devicetree/bindings/mfd/max77802.txt @@ -18,7 +18,7 @@ Required properties: Example: - max77802: pmic@09 { + max77802: pmic@9 { compatible = "maxim,max77802"; interrupt-parent = <&intc>; interrupts = <26 IRQ_TYPE_NONE>; diff --git a/Documentation/devicetree/bindings/mfd/mfd.txt b/Documentation/devicetree/bindings/mfd/mfd.txt index bcb6abb9d413..336c0495c8a3 100644 --- a/Documentation/devicetree/bindings/mfd/mfd.txt +++ b/Documentation/devicetree/bindings/mfd/mfd.txt @@ -41,7 +41,7 @@ foo@1000 { compatible = "syscon", "simple-mfd"; reg = <0x01000 0x1000>; - led@08.0 { + led@8.0 { compatible = "register-bit-led"; offset = <0x08>; mask = <0x01>; diff --git a/Documentation/devicetree/bindings/mfd/sun4i-gpadc.txt b/Documentation/devicetree/bindings/mfd/sun4i-gpadc.txt index badff3611a98..86dd8191b04c 100644 --- a/Documentation/devicetree/bindings/mfd/sun4i-gpadc.txt +++ b/Documentation/devicetree/bindings/mfd/sun4i-gpadc.txt @@ -10,7 +10,7 @@ Required properties: - #io-channel-cells: shall be 0, Example: - ths: ths@01c25000 { + ths: ths@1c25000 { compatible = "allwinner,sun8i-a33-ths"; reg = <0x01c25000 0x100>; #thermal-sensor-cells = <0>; @@ -47,7 +47,7 @@ Optional properties: Example: - rtp: rtp@01c25000 { + rtp: rtp@1c25000 { compatible = "allwinner,sun4i-a10-ts"; reg = <0x01c25000 0x100>; interrupts = <29>; diff --git a/Documentation/devicetree/bindings/mfd/sun6i-prcm.txt b/Documentation/devicetree/bindings/mfd/sun6i-prcm.txt index 03c5a551da55..dd2c06540485 100644 --- a/Documentation/devicetree/bindings/mfd/sun6i-prcm.txt +++ b/Documentation/devicetree/bindings/mfd/sun6i-prcm.txt @@ -15,7 +15,7 @@ The prcm node may contain several subdevices definitions: Example: - prcm: prcm@01f01400 { + prcm: prcm@1f01400 { compatible = "allwinner,sun6i-a31-prcm"; reg = <0x01f01400 0x200>; diff --git a/Documentation/devicetree/bindings/mfd/syscon.txt b/Documentation/devicetree/bindings/mfd/syscon.txt index 408f768686f1..8b92d4576c42 100644 --- a/Documentation/devicetree/bindings/mfd/syscon.txt +++ b/Documentation/devicetree/bindings/mfd/syscon.txt @@ -18,7 +18,7 @@ Optional property: performed on the device. Examples: -gpr: iomuxc-gpr@020e0000 { +gpr: iomuxc-gpr@20e0000 { compatible = "fsl,imx6q-iomuxc-gpr", "syscon"; reg = <0x020e0000 0x38>; }; diff --git a/Documentation/devicetree/bindings/mmc/mmc.txt b/Documentation/devicetree/bindings/mmc/mmc.txt index b32ade645ad9..5934157cf2cd 100644 --- a/Documentation/devicetree/bindings/mmc/mmc.txt +++ b/Documentation/devicetree/bindings/mmc/mmc.txt @@ -143,7 +143,7 @@ sdhci@ab000000 { Example with sdio function subnode: -mmc3: mmc@01c12000 { +mmc3: mmc@1c12000 { #address-cells = <1>; #size-cells = <0>; diff --git a/Documentation/devicetree/bindings/mmc/sdhci-st.txt b/Documentation/devicetree/bindings/mmc/sdhci-st.txt index e35645598315..6b3d40ca395e 100644 --- a/Documentation/devicetree/bindings/mmc/sdhci-st.txt +++ b/Documentation/devicetree/bindings/mmc/sdhci-st.txt @@ -74,7 +74,7 @@ mmc0: sdhci@fe81e000 { /* Example SD stih407 family configuration */ -mmc1: sdhci@09080000 { +mmc1: sdhci@9080000 { compatible = "st,sdhci-stih407", "st,sdhci"; reg = <0x09080000 0x7ff>; reg-names = "mmc"; @@ -90,7 +90,7 @@ mmc1: sdhci@09080000 { /* Example eMMC stih407 family configuration */ -mmc0: sdhci@09060000 { +mmc0: sdhci@9060000 { compatible = "st,sdhci-stih407", "st,sdhci"; reg = <0x09060000 0x7ff>, <0x9061008 0x20>; reg-names = "mmc", "top-mmc-delay"; diff --git a/Documentation/devicetree/bindings/mmc/sunxi-mmc.txt b/Documentation/devicetree/bindings/mmc/sunxi-mmc.txt index 63b57e2a10fb..132e0007d7d6 100644 --- a/Documentation/devicetree/bindings/mmc/sunxi-mmc.txt +++ b/Documentation/devicetree/bindings/mmc/sunxi-mmc.txt @@ -29,7 +29,7 @@ Optional properties: Examples: - Within .dtsi: - mmc0: mmc@01c0f000 { + mmc0: mmc@1c0f000 { compatible = "allwinner,sun5i-a13-mmc"; reg = <0x01c0f000 0x1000>; clocks = <&ahb_gates 8>, <&mmc0_clk>, <&mmc0_output_clk>, <&mmc0_sample_clk>; @@ -39,7 +39,7 @@ Examples: }; - Within dts: - mmc0: mmc@01c0f000 { + mmc0: mmc@1c0f000 { pinctrl-names = "default", "default"; pinctrl-0 = <&mmc0_pins_a>; pinctrl-1 = <&mmc0_cd_pin_reference_design>; diff --git a/Documentation/devicetree/bindings/mtd/sunxi-nand.txt b/Documentation/devicetree/bindings/mtd/sunxi-nand.txt index a37c67bcb43b..5e13a5cdff03 100644 --- a/Documentation/devicetree/bindings/mtd/sunxi-nand.txt +++ b/Documentation/devicetree/bindings/mtd/sunxi-nand.txt @@ -31,7 +31,7 @@ see Documentation/devicetree/bindings/mtd/nand.txt for generic bindings. Examples: -nfc: nand@01c03000 { +nfc: nand@1c03000 { compatible = "allwinner,sun4i-a10-nand"; reg = <0x01c03000 0x1000>; interrupts = <0 37 1>; diff --git a/Documentation/devicetree/bindings/net/allwinner,sun4i-emac.txt b/Documentation/devicetree/bindings/net/allwinner,sun4i-emac.txt index 10640b17c866..e98118aef5f6 100644 --- a/Documentation/devicetree/bindings/net/allwinner,sun4i-emac.txt +++ b/Documentation/devicetree/bindings/net/allwinner,sun4i-emac.txt @@ -10,7 +10,7 @@ Required properties: Example: -emac: ethernet@01c0b000 { +emac: ethernet@1c0b000 { compatible = "allwinner,sun4i-a10-emac"; reg = <0x01c0b000 0x1000>; interrupts = <55>; diff --git a/Documentation/devicetree/bindings/net/allwinner,sun4i-mdio.txt b/Documentation/devicetree/bindings/net/allwinner,sun4i-mdio.txt index 4ec56413779d..ab5b8613b0ef 100644 --- a/Documentation/devicetree/bindings/net/allwinner,sun4i-mdio.txt +++ b/Documentation/devicetree/bindings/net/allwinner,sun4i-mdio.txt @@ -9,7 +9,7 @@ Optional properties: - phy-supply: phandle to a regulator if the PHY needs one Example at the SoC level: -mdio@01c0b080 { +mdio@1c0b080 { compatible = "allwinner,sun4i-a10-mdio"; reg = <0x01c0b080 0x14>; #address-cells = <1>; @@ -18,7 +18,7 @@ mdio@01c0b080 { And at the board level: -mdio@01c0b080 { +mdio@1c0b080 { phy-supply = <®_emac_3v3>; phy0: ethernet-phy@0 { diff --git a/Documentation/devicetree/bindings/net/allwinner,sun7i-a20-gmac.txt b/Documentation/devicetree/bindings/net/allwinner,sun7i-a20-gmac.txt index ea4d752389a2..8b3f953656e3 100644 --- a/Documentation/devicetree/bindings/net/allwinner,sun7i-a20-gmac.txt +++ b/Documentation/devicetree/bindings/net/allwinner,sun7i-a20-gmac.txt @@ -15,7 +15,7 @@ Optional properties: Examples: - gmac: ethernet@01c50000 { + gmac: ethernet@1c50000 { compatible = "allwinner,sun7i-a20-gmac"; reg = <0x01c50000 0x10000>, <0x01c20164 0x4>; diff --git a/Documentation/devicetree/bindings/net/brcm,bcmgenet.txt b/Documentation/devicetree/bindings/net/brcm,bcmgenet.txt index 26c77d985faf..3956af1d30f3 100644 --- a/Documentation/devicetree/bindings/net/brcm,bcmgenet.txt +++ b/Documentation/devicetree/bindings/net/brcm,bcmgenet.txt @@ -109,7 +109,7 @@ ethernet@f0ba0000 { reg = <0xf0ba0000 0xfc4c>; interrupts = <0x0 0x18 0x0>, <0x0 0x19 0x0>; - mdio@0e14 { + mdio@e14 { compatible = "brcm,genet-mdio-v4"; #address-cells = <0x1>; #size-cells = <0x0>; diff --git a/Documentation/devicetree/bindings/net/can/m_can.txt b/Documentation/devicetree/bindings/net/can/m_can.txt index 78138333ff7a..63e90421d029 100644 --- a/Documentation/devicetree/bindings/net/can/m_can.txt +++ b/Documentation/devicetree/bindings/net/can/m_can.txt @@ -45,7 +45,7 @@ Required properties: Example: SoC dtsi: -m_can1: can@020e8000 { +m_can1: can@20e8000 { compatible = "bosch,m_can"; reg = <0x020e8000 0x4000>, <0x02298000 0x4000>; reg-names = "m_can", "message_ram"; diff --git a/Documentation/devicetree/bindings/net/can/sun4i_can.txt b/Documentation/devicetree/bindings/net/can/sun4i_can.txt index 84ed1909df76..f69845e6feaf 100644 --- a/Documentation/devicetree/bindings/net/can/sun4i_can.txt +++ b/Documentation/devicetree/bindings/net/can/sun4i_can.txt @@ -19,7 +19,7 @@ SoC common .dtsi file: allwinner,pull = <0>; }; ... - can0: can@01c2bc00 { + can0: can@1c2bc00 { compatible = "allwinner,sun4i-a10-can"; reg = <0x01c2bc00 0x400>; interrupts = <0 26 4>; @@ -29,7 +29,7 @@ SoC common .dtsi file: Board specific .dts file: - can0: can@01c2bc00 { + can0: can@1c2bc00 { pinctrl-names = "default"; pinctrl-0 = <&can0_pins_a>; status = "okay"; diff --git a/Documentation/devicetree/bindings/net/wireless/brcm,bcm43xx-fmac.txt b/Documentation/devicetree/bindings/net/wireless/brcm,bcm43xx-fmac.txt index b2bd4704f859..86602f264dce 100644 --- a/Documentation/devicetree/bindings/net/wireless/brcm,bcm43xx-fmac.txt +++ b/Documentation/devicetree/bindings/net/wireless/brcm,bcm43xx-fmac.txt @@ -20,7 +20,7 @@ Optional properties: Example: -mmc3: mmc@01c12000 { +mmc3: mmc@1c12000 { #address-cells = <1>; #size-cells = <0>; diff --git a/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt b/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt index ef06d061913c..081c49c0dac0 100644 --- a/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt +++ b/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt @@ -13,13 +13,13 @@ Are child nodes of qfprom, bindings of which as described in bindings/nvmem/nvmem.txt Example for sun4i: - sid@01c23800 { + sid@1c23800 { compatible = "allwinner,sun4i-a10-sid"; reg = <0x01c23800 0x10> }; Example for sun7i: - sid@01c23800 { + sid@1c23800 { compatible = "allwinner,sun7i-a20-sid"; reg = <0x01c23800 0x200> }; diff --git a/Documentation/devicetree/bindings/nvmem/brcm,ocotp.txt b/Documentation/devicetree/bindings/nvmem/brcm,ocotp.txt index 6462e12d8de6..0415265c215a 100644 --- a/Documentation/devicetree/bindings/nvmem/brcm,ocotp.txt +++ b/Documentation/devicetree/bindings/nvmem/brcm,ocotp.txt @@ -10,7 +10,7 @@ Required Properties: Example: -otp: otp@0301c800 { +otp: otp@301c800 { compatible = "brcm,ocotp"; reg = <0x0301c800 0x2c>; brcm,ocotp-size = <2048>; diff --git a/Documentation/devicetree/bindings/nvmem/imx-ocotp.txt b/Documentation/devicetree/bindings/nvmem/imx-ocotp.txt index 70d791b03ea1..f162c72b4e36 100644 --- a/Documentation/devicetree/bindings/nvmem/imx-ocotp.txt +++ b/Documentation/devicetree/bindings/nvmem/imx-ocotp.txt @@ -19,7 +19,7 @@ Optional properties: Example: - ocotp: ocotp@021bc000 { + ocotp: ocotp@21bc000 { compatible = "fsl,imx6q-ocotp", "syscon"; reg = <0x021bc000 0x4000>; clocks = <&clks IMX6QDL_CLK_IIM>; diff --git a/Documentation/devicetree/bindings/nvmem/nvmem.txt b/Documentation/devicetree/bindings/nvmem/nvmem.txt index b52bc11e9597..fd06c09b822b 100644 --- a/Documentation/devicetree/bindings/nvmem/nvmem.txt +++ b/Documentation/devicetree/bindings/nvmem/nvmem.txt @@ -33,7 +33,7 @@ bits: Is pair of bit location and number of bits, which specifies offset For example: /* Provider */ - qfprom: qfprom@00700000 { + qfprom: qfprom@700000 { ... /* Data cells */ diff --git a/Documentation/devicetree/bindings/nvmem/qfprom.txt b/Documentation/devicetree/bindings/nvmem/qfprom.txt index 4ad68b7f5c18..26fe878d5c86 100644 --- a/Documentation/devicetree/bindings/nvmem/qfprom.txt +++ b/Documentation/devicetree/bindings/nvmem/qfprom.txt @@ -12,7 +12,7 @@ bindings/nvmem/nvmem.txt Example: - qfprom: qfprom@00700000 { + qfprom: qfprom@700000 { compatible = "qcom,qfprom"; reg = <0x00700000 0x8000>; ... diff --git a/Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt b/Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt index 982a74ea6df9..1b4d2803dad1 100644 --- a/Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt +++ b/Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt @@ -255,7 +255,7 @@ Tegra30: SoC DTSI: - pcie-controller@00003000 { + pcie-controller@3000 { compatible = "nvidia,tegra30-pcie"; device_type = "pci"; reg = <0x00003000 0x00000800 /* PADS registers */ @@ -334,7 +334,7 @@ SoC DTSI: Board DTS: - pcie-controller@00003000 { + pcie-controller@3000 { status = "okay"; avdd-pexa-supply = <&ldo1_reg>; @@ -360,7 +360,7 @@ Tegra124: SoC DTSI: - pcie-controller@01003000 { + pcie-controller@1003000 { compatible = "nvidia,tegra124-pcie"; device_type = "pci"; reg = <0x0 0x01003000 0x0 0x00000800 /* PADS registers */ @@ -425,7 +425,7 @@ SoC DTSI: Board DTS: - pcie-controller@01003000 { + pcie-controller@1003000 { status = "okay"; avddio-pex-supply = <&vdd_1v05_run>; @@ -456,7 +456,7 @@ Tegra210: SoC DTSI: - pcie-controller@01003000 { + pcie-controller@1003000 { compatible = "nvidia,tegra210-pcie"; device_type = "pci"; reg = <0x0 0x01003000 0x0 0x00000800 /* PADS registers */ @@ -521,7 +521,7 @@ SoC DTSI: Board DTS: - pcie-controller@01003000 { + pcie-controller@1003000 { status = "okay"; avdd-pll-uerefe-supply = <&avdd_1v05_pll>; diff --git a/Documentation/devicetree/bindings/phy/brcm,cygnus-pcie-phy.txt b/Documentation/devicetree/bindings/phy/brcm,cygnus-pcie-phy.txt index 761c4bc24a9b..10efff28b52b 100644 --- a/Documentation/devicetree/bindings/phy/brcm,cygnus-pcie-phy.txt +++ b/Documentation/devicetree/bindings/phy/brcm,cygnus-pcie-phy.txt @@ -15,7 +15,7 @@ Required properties For the child node: - #phy-cells: must be 0 Example: - pcie_phy: phy@0301d0a0 { + pcie_phy: phy@301d0a0 { compatible = "brcm,cygnus-pcie-phy"; reg = <0x0301d0a0 0x14>; diff --git a/Documentation/devicetree/bindings/phy/mxs-usb-phy.txt b/Documentation/devicetree/bindings/phy/mxs-usb-phy.txt index 1d25b04cd05e..6ac98b3b5f57 100644 --- a/Documentation/devicetree/bindings/phy/mxs-usb-phy.txt +++ b/Documentation/devicetree/bindings/phy/mxs-usb-phy.txt @@ -23,7 +23,7 @@ Optional properties: the 17.78mA TX reference current. Default: 100 Example: -usbphy1: usbphy@020c9000 { +usbphy1: usbphy@20c9000 { compatible = "fsl,imx6q-usbphy", "fsl,imx23-usbphy"; reg = <0x020c9000 0x1000>; interrupts = <0 44 0x04>; diff --git a/Documentation/devicetree/bindings/phy/sun9i-usb-phy.txt b/Documentation/devicetree/bindings/phy/sun9i-usb-phy.txt index f9853156e311..64f7109aea1f 100644 --- a/Documentation/devicetree/bindings/phy/sun9i-usb-phy.txt +++ b/Documentation/devicetree/bindings/phy/sun9i-usb-phy.txt @@ -25,7 +25,7 @@ It is recommended to list all clocks and resets available. The driver will only use those matching the phy_type. Example: - usbphy1: phy@00a01800 { + usbphy1: phy@a01800 { compatible = "allwinner,sun9i-a80-usb-phy"; reg = <0x00a01800 0x4>; clocks = <&usb_phy_clk 2>, <&usb_phy_clk 10>, diff --git a/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt index 6f2ec9af0de2..09789fdfa749 100644 --- a/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt +++ b/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt @@ -89,7 +89,7 @@ Optional subnode-properties: Examples: -pio: pinctrl@01c20800 { +pio: pinctrl@1c20800 { compatible = "allwinner,sun5i-a13-pinctrl"; reg = <0x01c20800 0x400>; #address-cells = <1>; diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,imx-pinctrl.txt index 42d74f8a1bcc..a1050b5982ec 100644 --- a/Documentation/devicetree/bindings/pinctrl/fsl,imx-pinctrl.txt +++ b/Documentation/devicetree/bindings/pinctrl/fsl,imx-pinctrl.txt @@ -58,14 +58,14 @@ Some requirements for using fsl,imx-pinctrl binding: configurations by referring to the phandle of that pin configuration node. Examples: -usdhc@0219c000 { /* uSDHC4 */ +usdhc@219c000 { /* uSDHC4 */ non-removable; vmmc-supply = <®_3p3v>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc4_1>; }; -iomuxc@020e0000 { +iomuxc@20e0000 { compatible = "fsl,imx6q-iomuxc"; reg = <0x020e0000 0x4000>; diff --git a/Documentation/devicetree/bindings/pinctrl/img,tz1090-pdc-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/img,tz1090-pdc-pinctrl.txt index 51b943cc9770..cf9ccdff4455 100644 --- a/Documentation/devicetree/bindings/pinctrl/img,tz1090-pdc-pinctrl.txt +++ b/Documentation/devicetree/bindings/pinctrl/img,tz1090-pdc-pinctrl.txt @@ -89,7 +89,7 @@ Valid values for pin and group names are: Example: - pinctrl_pdc: pinctrl@02006500 { + pinctrl_pdc: pinctrl@2006500 { #gpio-range-cells = <3>; compatible = "img,tz1090-pdc-pinctrl"; reg = <0x02006500 0x100>; @@ -121,7 +121,7 @@ Example board file extracts: }; }; - ir: ir@02006200 { + ir: ir@2006200 { pinctrl-names = "default"; pinctrl-0 = <&irmod_default>; }; diff --git a/Documentation/devicetree/bindings/pinctrl/img,tz1090-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/img,tz1090-pinctrl.txt index 509faa87ad0e..2dfd9a3fc1e4 100644 --- a/Documentation/devicetree/bindings/pinctrl/img,tz1090-pinctrl.txt +++ b/Documentation/devicetree/bindings/pinctrl/img,tz1090-pinctrl.txt @@ -197,7 +197,7 @@ Valid values for pin and group names are: Example: - pinctrl: pinctrl@02005800 { + pinctrl: pinctrl@2005800 { #gpio-range-cells = <3>; compatible = "img,tz1090-pinctrl"; reg = <0x02005800 0xe4>; @@ -221,7 +221,7 @@ Example board file extract: }; }; - uart@02004b00 { + uart@2004b00 { pinctrl-names = "default"; pinctrl-0 = <&uart0_default>; }; diff --git a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt index 4048f43a9d29..02e971c39d81 100644 --- a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt +++ b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt @@ -97,7 +97,7 @@ SoC file extract: Board file extract: ------------------- - pcie-controller@01003000 { + pcie-controller@1003000 { ... phys = <&padctl 0>; diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-mt65xx.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-mt65xx.txt index 37d744750579..231fa1db7c5e 100644 --- a/Documentation/devicetree/bindings/pinctrl/pinctrl-mt65xx.txt +++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-mt65xx.txt @@ -86,7 +86,7 @@ Examples: reg = <0 0x1020C020 0 0x1000>; }; - pinctrl@01c20800 { + pinctrl@1c20800 { compatible = "mediatek,mt8135-pinctrl"; reg = <0 0x1000B000 0 0x1000>; mediatek,pctl-regmap = <&syscfg_pctl_a &syscfg_pctl_b>; diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-st.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-st.txt index 013c675b5b64..48b9be48af18 100644 --- a/Documentation/devicetree/bindings/pinctrl/pinctrl-st.txt +++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-st.txt @@ -89,7 +89,7 @@ Example: interrupt-names = "irqmux"; ranges = <0 0x09610000 0x6000>; - pio0: gpio@09610000 { + pio0: gpio@9610000 { gpio-controller; #gpio-cells = <2>; interrupt-controller; diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,msm8996-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/qcom,msm8996-pinctrl.txt index e312a71b2f94..aaf01e929eea 100644 --- a/Documentation/devicetree/bindings/pinctrl/qcom,msm8996-pinctrl.txt +++ b/Documentation/devicetree/bindings/pinctrl/qcom,msm8996-pinctrl.txt @@ -175,7 +175,7 @@ to specify in a pin configuration subnode: Example: - tlmm: pinctrl@01010000 { + tlmm: pinctrl@1010000 { compatible = "qcom,msm8996-pinctrl"; reg = <0x01010000 0x300000>; interrupts = <0 208 0>; diff --git a/Documentation/devicetree/bindings/power/fsl,imx-gpc.txt b/Documentation/devicetree/bindings/power/fsl,imx-gpc.txt index 6c1498958d48..e371b262d709 100644 --- a/Documentation/devicetree/bindings/power/fsl,imx-gpc.txt +++ b/Documentation/devicetree/bindings/power/fsl,imx-gpc.txt @@ -40,7 +40,7 @@ Optional properties: Example: - gpc: gpc@020dc000 { + gpc: gpc@20dc000 { compatible = "fsl,imx6q-gpc"; reg = <0x020dc000 0x4000>; interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>, @@ -80,7 +80,7 @@ that is a phandle pointing to the power domain the device belongs to. Example of a device that is part of the PU power domain: - vpu: vpu@02040000 { + vpu: vpu@2040000 { reg = <0x02040000 0x3c000>; /* ... */ power-domains = <&pd_pu>; diff --git a/Documentation/devicetree/bindings/power/reset/imx-snvs-poweroff.txt b/Documentation/devicetree/bindings/power/reset/imx-snvs-poweroff.txt index dc7c9bad63ea..1b81fcd9fb72 100644 --- a/Documentation/devicetree/bindings/power/reset/imx-snvs-poweroff.txt +++ b/Documentation/devicetree/bindings/power/reset/imx-snvs-poweroff.txt @@ -10,7 +10,7 @@ Required Properties: -reg: Specifies the physical address of the SNVS_LPCR register Example: - snvs@020cc000 { + snvs@20cc000 { compatible = "fsl,sec-v4.0-mon", "simple-bus"; #address-cells = <1>; #size-cells = <1>; diff --git a/Documentation/devicetree/bindings/power/reset/keystone-reset.txt b/Documentation/devicetree/bindings/power/reset/keystone-reset.txt index c82f12e2d85c..c5c03789ed1e 100644 --- a/Documentation/devicetree/bindings/power/reset/keystone-reset.txt +++ b/Documentation/devicetree/bindings/power/reset/keystone-reset.txt @@ -37,12 +37,12 @@ Example 1: Setup keystone reset so that in case software reset or WDT0 is triggered it issues hard reset for SoC. -pllctrl: pll-controller@02310000 { +pllctrl: pll-controller@2310000 { compatible = "ti,keystone-pllctrl", "syscon"; reg = <0x02310000 0x200>; }; -devctrl: device-state-control@02620000 { +devctrl: device-state-control@2620000 { compatible = "ti,keystone-devctrl", "syscon"; reg = <0x02620000 0x1000>; }; diff --git a/Documentation/devicetree/bindings/powerpc/fsl/mcu-mpc8349emitx.txt b/Documentation/devicetree/bindings/powerpc/fsl/mcu-mpc8349emitx.txt index 0f766333b6eb..37f91fa57654 100644 --- a/Documentation/devicetree/bindings/powerpc/fsl/mcu-mpc8349emitx.txt +++ b/Documentation/devicetree/bindings/powerpc/fsl/mcu-mpc8349emitx.txt @@ -8,7 +8,7 @@ Required properties: Example: -mcu@0a { +mcu@a { #gpio-cells = <2>; compatible = "fsl,mc9s08qg8-mpc8349emitx", "fsl,mcu-mpc8349emitx"; diff --git a/Documentation/devicetree/bindings/pwm/pwm-sun4i.txt b/Documentation/devicetree/bindings/pwm/pwm-sun4i.txt index c5171660eaf9..51ff54c8b8ef 100644 --- a/Documentation/devicetree/bindings/pwm/pwm-sun4i.txt +++ b/Documentation/devicetree/bindings/pwm/pwm-sun4i.txt @@ -14,7 +14,7 @@ Required properties: Example: - pwm: pwm@01c20e00 { + pwm: pwm@1c20e00 { compatible = "allwinner,sun7i-a20-pwm"; reg = <0x01c20e00 0xc>; clocks = <&osc24M>; diff --git a/Documentation/devicetree/bindings/regulator/max77686.txt b/Documentation/devicetree/bindings/regulator/max77686.txt index 0dded64d89d3..e9f7578ca09a 100644 --- a/Documentation/devicetree/bindings/regulator/max77686.txt +++ b/Documentation/devicetree/bindings/regulator/max77686.txt @@ -40,7 +40,7 @@ to get matched with their hardware counterparts as follow: Example: - max77686: pmic@09 { + max77686: pmic@9 { compatible = "maxim,max77686"; interrupt-parent = <&wakeup_eint>; interrupts = <26 IRQ_TYPE_NONE>; diff --git a/Documentation/devicetree/bindings/regulator/max77802.txt b/Documentation/devicetree/bindings/regulator/max77802.txt index 879e98d3b9aa..b82943d83677 100644 --- a/Documentation/devicetree/bindings/regulator/max77802.txt +++ b/Documentation/devicetree/bindings/regulator/max77802.txt @@ -71,7 +71,7 @@ has not been disabled for that state using "regulator-off-in-suspend". Example: - max77802@09 { + max77802@9 { compatible = "maxim,max77802"; interrupt-parent = <&wakeup_eint>; interrupts = <26 0>; diff --git a/Documentation/devicetree/bindings/reset/allwinner,sunxi-clock-reset.txt b/Documentation/devicetree/bindings/reset/allwinner,sunxi-clock-reset.txt index c8f775714887..4ca66c96fe97 100644 --- a/Documentation/devicetree/bindings/reset/allwinner,sunxi-clock-reset.txt +++ b/Documentation/devicetree/bindings/reset/allwinner,sunxi-clock-reset.txt @@ -14,7 +14,7 @@ Required properties: example: -ahb1_rst: reset@01c202c0 { +ahb1_rst: reset@1c202c0 { #reset-cells = <1>; compatible = "allwinner,sun6i-a31-ahb1-reset"; reg = <0x01c202c0 0xc>; diff --git a/Documentation/devicetree/bindings/reset/fsl,imx-src.txt b/Documentation/devicetree/bindings/reset/fsl,imx-src.txt index 13301777e11c..6ed79e60248a 100644 --- a/Documentation/devicetree/bindings/reset/fsl,imx-src.txt +++ b/Documentation/devicetree/bindings/reset/fsl,imx-src.txt @@ -14,7 +14,7 @@ Required properties: example: -src: src@020d8000 { +src: src@20d8000 { compatible = "fsl,imx6q-src"; reg = <0x020d8000 0x4000>; interrupts = <0 91 0x04 0 96 0x04>; @@ -33,10 +33,10 @@ reset.txt example: - ipu1: ipu@02400000 { + ipu1: ipu@2400000 { resets = <&src 2>; }; - ipu2: ipu@02800000 { + ipu2: ipu@2800000 { resets = <&src 4>; }; diff --git a/Documentation/devicetree/bindings/reset/ti-syscon-reset.txt b/Documentation/devicetree/bindings/reset/ti-syscon-reset.txt index c516d24959f2..86945502ccb5 100644 --- a/Documentation/devicetree/bindings/reset/ti-syscon-reset.txt +++ b/Documentation/devicetree/bindings/reset/ti-syscon-reset.txt @@ -67,7 +67,7 @@ using the syscon node, and a consumer (a DSP device) on the TI Keystone 2 / { soc { - psc: power-sleep-controller@02350000 { + psc: power-sleep-controller@2350000 { compatible = "syscon", "simple-mfd"; reg = <0x02350000 0x1000>; diff --git a/Documentation/devicetree/bindings/rtc/dallas,ds1339.txt b/Documentation/devicetree/bindings/rtc/dallas,ds1339.txt deleted file mode 100644 index 916f57601a8f..000000000000 --- a/Documentation/devicetree/bindings/rtc/dallas,ds1339.txt +++ /dev/null @@ -1,18 +0,0 @@ -* Dallas DS1339 I2C Serial Real-Time Clock - -Required properties: -- compatible: Should contain "dallas,ds1339". -- reg: I2C address for chip - -Optional properties: -- trickle-resistor-ohms : Selected resistor for trickle charger - Values usable for ds1339 are 250, 2000, 4000 - Should be given if trickle charger should be enabled -- trickle-diode-disable : Do not use internal trickle charger diode - Should be given if internal trickle charger diode should be disabled -Example: - ds1339: rtc@68 { - compatible = "dallas,ds1339"; - trickle-resistor-ohms = <250>; - reg = <0x68>; - }; diff --git a/Documentation/devicetree/bindings/rtc/rtc-ds1307.txt b/Documentation/devicetree/bindings/rtc/rtc-ds1307.txt new file mode 100644 index 000000000000..d28d6e7f6ae8 --- /dev/null +++ b/Documentation/devicetree/bindings/rtc/rtc-ds1307.txt @@ -0,0 +1,44 @@ +Dallas DS1307 and compatible RTC + +Required properties: +- compatible: should be one of: + "dallas,ds1307", + "dallas,ds1308", + "dallas,ds1337", + "dallas,ds1338", + "dallas,ds1339", + "dallas,ds1388", + "dallas,ds1340", + "dallas,ds1341", + "maxim,ds3231", + "st,m41t0", + "st,m41t00", + "microchip,mcp7940x", + "microchip,mcp7941x", + "pericom,pt7c4338", + "epson,rx8025", + "isil,isl12057" +- reg: I2C bus address of the device + +Optional properties: +- interrupt-parent: phandle for the interrupt controller. +- interrupts: rtc alarm interrupt. +- clock-output-names: From common clock binding to override the default output + clock name +- wakeup-source: Enables wake up of host system on alarm +- trickle-resistor-ohms : ds1339, ds1340 and ds 1388 only + Selected resistor for trickle charger + Possible values are 250, 2000, 4000 + Should be given if trickle charger should be enabled +- trickle-diode-disable : ds1339, ds1340 and ds 1388 only + Do not use internal trickle charger diode + Should be given if internal trickle charger diode should be disabled + +Example: + rtc1: ds1339@68 { + compatible = "dallas,ds1339"; + reg = <0x68>; + interrupt-parent = <&gpio4>; + interrupts = <20 0>; + trickle-resistor-ohms = <250>; + }; diff --git a/Documentation/devicetree/bindings/rtc/rtc-m41t80.txt b/Documentation/devicetree/bindings/rtc/rtc-m41t80.txt new file mode 100644 index 000000000000..717d93860af1 --- /dev/null +++ b/Documentation/devicetree/bindings/rtc/rtc-m41t80.txt @@ -0,0 +1,31 @@ +ST M41T80 family of RTC and compatible + +Required properties: +- compatible: should be one of: + "st,m41t62", + "st,m41t65", + "st,m41t80", + "st,m41t81", + "st,m41t81s", + "st,m41t82", + "st,m41t83", + "st,m41t84", + "st,m41t85", + "st,m41t87", + "microcrystal,rv4162", +- reg: I2C bus address of the device + +Optional properties: +- interrupt-parent: phandle for the interrupt controller. +- interrupts: rtc alarm interrupt. +- clock-output-names: From common clock binding to override the default output + clock name +- wakeup-source: Enables wake up of host system on alarm + +Example: + rtc@68 { + compatible = "st,m41t80"; + reg = <0x68>; + interrupt-parent = <&UIC0>; + interrupts = <0x9 0x8>; + }; diff --git a/Documentation/devicetree/bindings/rtc/sirf,prima2-sysrtc.txt b/Documentation/devicetree/bindings/rtc/sirf,prima2-sysrtc.txt new file mode 100644 index 000000000000..58885b55da21 --- /dev/null +++ b/Documentation/devicetree/bindings/rtc/sirf,prima2-sysrtc.txt @@ -0,0 +1,13 @@ +SiRFSoC Real Time Clock + +Required properties: +- compatible: must be "sirf,prima2-sysrtc" +- reg: address range of rtc register set. +- interrupts: rtc alarm interrupts. + +Example: + rtc@2000 { + compatible = "sirf,prima2-sysrtc"; + reg = <0x2000 0x1000>; + interrupts = <52 53 54>; + }; diff --git a/Documentation/devicetree/bindings/rtc/stericsson,coh901331.txt b/Documentation/devicetree/bindings/rtc/stericsson,coh901331.txt new file mode 100644 index 000000000000..3ebeb311335f --- /dev/null +++ b/Documentation/devicetree/bindings/rtc/stericsson,coh901331.txt @@ -0,0 +1,17 @@ +ST-Ericsson COH 901 331 Real Time Clock + +Required properties: +- compatible: must be "stericsson,coh901331" +- reg: address range of rtc register set. +- interrupt-parent: phandle for the interrupt controller. +- interrupts: rtc alarm interrupt. +- clocks: phandle to the rtc clock source + +Example: + rtc: rtc@c0017000 { + compatible = "stericsson,coh901331"; + reg = <0xc0017000 0x1000>; + interrupt-parent = <&vicb>; + interrupts = <10>; + clocks = <&rtc_clk>; + }; diff --git a/Documentation/devicetree/bindings/rtc/sun6i-rtc.txt b/Documentation/devicetree/bindings/rtc/sun6i-rtc.txt index d5e26d313f62..12c083c1140a 100644 --- a/Documentation/devicetree/bindings/rtc/sun6i-rtc.txt +++ b/Documentation/devicetree/bindings/rtc/sun6i-rtc.txt @@ -17,7 +17,7 @@ Required properties for new device trees Example: -rtc: rtc@01f00000 { +rtc: rtc@1f00000 { compatible = "allwinner,sun6i-a31-rtc"; reg = <0x01f00000 0x54>; interrupts = <0 40 4>, <0 41 4>; diff --git a/Documentation/devicetree/bindings/rtc/sunxi-rtc.txt b/Documentation/devicetree/bindings/rtc/sunxi-rtc.txt index 6983aad376c3..4a8d79c1cf08 100644 --- a/Documentation/devicetree/bindings/rtc/sunxi-rtc.txt +++ b/Documentation/devicetree/bindings/rtc/sunxi-rtc.txt @@ -10,7 +10,7 @@ Required properties: Example: -rtc: rtc@01c20d00 { +rtc: rtc@1c20d00 { compatible = "allwinner,sun4i-a10-rtc"; reg = <0x01c20d00 0x20>; interrupts = <24>; diff --git a/Documentation/devicetree/bindings/soc/fsl/cpm_qe/qe/par_io.txt b/Documentation/devicetree/bindings/soc/fsl/cpm_qe/qe/par_io.txt index 60984260207b..09b1b05fa677 100644 --- a/Documentation/devicetree/bindings/soc/fsl/cpm_qe/qe/par_io.txt +++ b/Documentation/devicetree/bindings/soc/fsl/cpm_qe/qe/par_io.txt @@ -18,7 +18,7 @@ par_io@1400 { #size-cells = <0>; device_type = "par_io"; num-ports = <7>; - ucc_pin@01 { + ucc_pin@1 { ...... }; diff --git a/Documentation/devicetree/bindings/soc/fsl/cpm_qe/qe/pincfg.txt b/Documentation/devicetree/bindings/soc/fsl/cpm_qe/qe/pincfg.txt index ec6ee2e864a2..5bde8b98a8c9 100644 --- a/Documentation/devicetree/bindings/soc/fsl/cpm_qe/qe/pincfg.txt +++ b/Documentation/devicetree/bindings/soc/fsl/cpm_qe/qe/pincfg.txt @@ -26,7 +26,7 @@ Required properties: interrupts. Example: - ucc_pin@01 { + ucc_pin@1 { pio-map = < /* port pin dir open_drain assignment has_irq */ 0 3 1 0 1 0 /* TxD0 */ diff --git a/Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt b/Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt index 66e6265fb0aa..f7b00a7c0f68 100644 --- a/Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt +++ b/Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt @@ -51,7 +51,7 @@ of valid identifiers for k2g. Example (K2G): -------------------- - uart0: serial@02530c00 { + uart0: serial@2530c00 { compatible = "ns16550a"; ... power-domains = <&k2g_pds 0x002c>; diff --git a/Documentation/devicetree/bindings/sound/cdns,xtfpga-i2s.txt b/Documentation/devicetree/bindings/sound/cdns,xtfpga-i2s.txt index befd125d18bb..860fc0da39c0 100644 --- a/Documentation/devicetree/bindings/sound/cdns,xtfpga-i2s.txt +++ b/Documentation/devicetree/bindings/sound/cdns,xtfpga-i2s.txt @@ -9,7 +9,7 @@ Required properties: Examples: - i2s0: xtfpga-i2s@0d080000 { + i2s0: xtfpga-i2s@d080000 { #sound-dai-cells = <0>; compatible = "cdns,xtfpga-i2s"; reg = <0x0d080000 0x40>; diff --git a/Documentation/devicetree/bindings/sound/fsl,asrc.txt b/Documentation/devicetree/bindings/sound/fsl,asrc.txt index 65979b205893..f5a14115b459 100644 --- a/Documentation/devicetree/bindings/sound/fsl,asrc.txt +++ b/Documentation/devicetree/bindings/sound/fsl,asrc.txt @@ -41,7 +41,7 @@ Required properties: Example: -asrc: asrc@02034000 { +asrc: asrc@2034000 { compatible = "fsl,imx53-asrc"; reg = <0x02034000 0x4000>; interrupts = <0 50 IRQ_TYPE_LEVEL_HIGH>; diff --git a/Documentation/devicetree/bindings/sound/fsl,esai.txt b/Documentation/devicetree/bindings/sound/fsl,esai.txt index 21c401e2ccda..cacd18bb9ba6 100644 --- a/Documentation/devicetree/bindings/sound/fsl,esai.txt +++ b/Documentation/devicetree/bindings/sound/fsl,esai.txt @@ -48,7 +48,7 @@ Required properties: Example: -esai: esai@02024000 { +esai: esai@2024000 { compatible = "fsl,imx35-esai"; reg = <0x02024000 0x4000>; interrupts = <0 51 0x04>; diff --git a/Documentation/devicetree/bindings/sound/fsl,spdif.txt b/Documentation/devicetree/bindings/sound/fsl,spdif.txt index 0f97e54c3d43..38cfa7573441 100644 --- a/Documentation/devicetree/bindings/sound/fsl,spdif.txt +++ b/Documentation/devicetree/bindings/sound/fsl,spdif.txt @@ -39,7 +39,7 @@ Required properties: Example: -spdif: spdif@02004000 { +spdif: spdif@2004000 { compatible = "fsl,imx35-spdif"; reg = <0x02004000 0x4000>; interrupts = <0 52 0x04>; diff --git a/Documentation/devicetree/bindings/sound/imx-audmux.txt b/Documentation/devicetree/bindings/sound/imx-audmux.txt index b30a737e209e..2db4dcbee1b9 100644 --- a/Documentation/devicetree/bindings/sound/imx-audmux.txt +++ b/Documentation/devicetree/bindings/sound/imx-audmux.txt @@ -22,7 +22,7 @@ Required properties of optional child nodes: Example: -audmux@021d8000 { +audmux@21d8000 { compatible = "fsl,imx6q-audmux", "fsl,imx31-audmux"; reg = <0x021d8000 0x4000>; }; diff --git a/Documentation/devicetree/bindings/sound/samsung-i2s.txt b/Documentation/devicetree/bindings/sound/samsung-i2s.txt index 09e0e18591ae..bf100cd0d0f7 100644 --- a/Documentation/devicetree/bindings/sound/samsung-i2s.txt +++ b/Documentation/devicetree/bindings/sound/samsung-i2s.txt @@ -63,7 +63,7 @@ Optional SoC Specific Properties: Example: -i2s0: i2s@03830000 { +i2s0: i2s@3830000 { compatible = "samsung,s5pv210-i2s"; reg = <0x03830000 0x100>; dmas = <&pdma0 10 diff --git a/Documentation/devicetree/bindings/sound/sun4i-codec.txt b/Documentation/devicetree/bindings/sound/sun4i-codec.txt index 2d4e10deb6f4..66579bbd3294 100644 --- a/Documentation/devicetree/bindings/sound/sun4i-codec.txt +++ b/Documentation/devicetree/bindings/sound/sun4i-codec.txt @@ -62,7 +62,7 @@ Required properties for the following compatibles: block in the PRCM. Example: -codec: codec@01c22c00 { +codec: codec@1c22c00 { #sound-dai-cells = <0>; compatible = "allwinner,sun7i-a20-codec"; reg = <0x01c22c00 0x40>; @@ -73,7 +73,7 @@ codec: codec@01c22c00 { dma-names = "rx", "tx"; }; -codec: codec@01c22c00 { +codec: codec@1c22c00 { #sound-dai-cells = <0>; compatible = "allwinner,sun6i-a31-codec"; reg = <0x01c22c00 0x98>; diff --git a/Documentation/devicetree/bindings/sound/sun4i-i2s.txt b/Documentation/devicetree/bindings/sound/sun4i-i2s.txt index fc5da6080759..05d7135a8d2f 100644 --- a/Documentation/devicetree/bindings/sound/sun4i-i2s.txt +++ b/Documentation/devicetree/bindings/sound/sun4i-i2s.txt @@ -28,7 +28,7 @@ Required properties for the following compatibles: Example: -i2s0: i2s@01c22400 { +i2s0: i2s@1c22400 { #sound-dai-cells = <0>; compatible = "allwinner,sun4i-a10-i2s"; reg = <0x01c22400 0x400>; diff --git a/Documentation/devicetree/bindings/sound/sun8i-a33-codec.txt b/Documentation/devicetree/bindings/sound/sun8i-a33-codec.txt index 399b1b4bae22..2ca3d138528e 100644 --- a/Documentation/devicetree/bindings/sound/sun8i-a33-codec.txt +++ b/Documentation/devicetree/bindings/sound/sun8i-a33-codec.txt @@ -48,7 +48,7 @@ are similar to A33 using simple-card: sound-dai = <&codec>; }; - soc@01c00000 { + soc@1c00000 { [...] audio-codec@1c22e00 { diff --git a/Documentation/devicetree/bindings/sound/sun8i-codec-analog.txt b/Documentation/devicetree/bindings/sound/sun8i-codec-analog.txt index 1b6e7c4e50ab..07356758bd91 100644 --- a/Documentation/devicetree/bindings/sound/sun8i-codec-analog.txt +++ b/Documentation/devicetree/bindings/sound/sun8i-codec-analog.txt @@ -10,7 +10,7 @@ Required properties if not a sub-node of the PRCM node: - reg: must contain the registers location and length Example: -prcm: prcm@01f01400 { +prcm: prcm@1f01400 { codec_analog: codec-analog { compatible = "allwinner,sun8i-a23-codec-analog"; }; diff --git a/Documentation/devicetree/bindings/sound/sunxi,sun4i-spdif.txt b/Documentation/devicetree/bindings/sound/sunxi,sun4i-spdif.txt index 70ee177901d3..0c64a209c2e9 100644 --- a/Documentation/devicetree/bindings/sound/sunxi,sun4i-spdif.txt +++ b/Documentation/devicetree/bindings/sound/sunxi,sun4i-spdif.txt @@ -31,7 +31,7 @@ Required properties: Example: -spdif: spdif@01c21000 { +spdif: spdif@1c21000 { compatible = "allwinner,sun4i-a10-spdif"; reg = <0x01c21000 0x40>; interrupts = <13>; diff --git a/Documentation/devicetree/bindings/sound/zte,zx-spdif.txt b/Documentation/devicetree/bindings/sound/zte,zx-spdif.txt index b5a5ca4502f9..09231d7586b2 100644 --- a/Documentation/devicetree/bindings/sound/zte,zx-spdif.txt +++ b/Documentation/devicetree/bindings/sound/zte,zx-spdif.txt @@ -16,7 +16,7 @@ please check: * dma/dma.txt Example: - spdif0: spdif0@0b004000 { + spdif0: spdif0@b004000 { compatible = "zte,zx296702-spdif"; reg = <0x0b004000 0x1000>; clocks = <&lsp0clk ZX296702_SPDIF0_DIV>; diff --git a/Documentation/devicetree/bindings/spi/spi-sun4i.txt b/Documentation/devicetree/bindings/spi/spi-sun4i.txt index 484bbff5337e..c75d604a8290 100644 --- a/Documentation/devicetree/bindings/spi/spi-sun4i.txt +++ b/Documentation/devicetree/bindings/spi/spi-sun4i.txt @@ -12,7 +12,7 @@ Required properties: Example: -spi1: spi@01c06000 { +spi1: spi@1c06000 { compatible = "allwinner,sun4i-a10-spi"; reg = <0x01c06000 0x1000>; interrupts = <11>; diff --git a/Documentation/devicetree/bindings/spi/spi-sun6i.txt b/Documentation/devicetree/bindings/spi/spi-sun6i.txt index ab1811354cce..435a8e0731ac 100644 --- a/Documentation/devicetree/bindings/spi/spi-sun6i.txt +++ b/Documentation/devicetree/bindings/spi/spi-sun6i.txt @@ -19,7 +19,7 @@ Optional properties: Example: -spi1: spi@01c69000 { +spi1: spi@1c69000 { compatible = "allwinner,sun6i-a31-spi"; reg = <0x01c69000 0x1000>; interrupts = <0 66 4>; @@ -28,7 +28,7 @@ spi1: spi@01c69000 { resets = <&ahb1_rst 21>; }; -spi0: spi@01c68000 { +spi0: spi@1c68000 { compatible = "allwinner,sun8i-h3-spi"; reg = <0x01c68000 0x1000>; interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>; diff --git a/Documentation/devicetree/bindings/sram/samsung-sram.txt b/Documentation/devicetree/bindings/sram/samsung-sram.txt index 6bc474b2b885..61a9bbed303d 100644 --- a/Documentation/devicetree/bindings/sram/samsung-sram.txt +++ b/Documentation/devicetree/bindings/sram/samsung-sram.txt @@ -19,7 +19,7 @@ found in Documentation/devicetree/bindings/sram/sram.txt Example: - sysram@02020000 { + sysram@2020000 { compatible = "mmio-sram"; reg = <0x02020000 0x54000>; #address-cells = <1>; diff --git a/Documentation/devicetree/bindings/sram/sunxi-sram.txt b/Documentation/devicetree/bindings/sram/sunxi-sram.txt index 6bb92a1df753..d087f04a4d7f 100644 --- a/Documentation/devicetree/bindings/sram/sunxi-sram.txt +++ b/Documentation/devicetree/bindings/sram/sunxi-sram.txt @@ -47,7 +47,7 @@ This valid values for this argument are: Example ------- -sram-controller@01c00000 { +sram-controller@1c00000 { compatible = "allwinner,sun4i-a10-sram-controller"; reg = <0x01c00000 0x30>; #address-cells = <1>; @@ -68,7 +68,7 @@ sram-controller@01c00000 { }; }; -emac: ethernet@01c0b000 { +emac: ethernet@1c0b000 { compatible = "allwinner,sun4i-a10-emac"; ... diff --git a/Documentation/devicetree/bindings/timer/allwinner,sun5i-a13-hstimer.txt b/Documentation/devicetree/bindings/timer/allwinner,sun5i-a13-hstimer.txt index 8d6e4fd2468e..2c5c1be78360 100644 --- a/Documentation/devicetree/bindings/timer/allwinner,sun5i-a13-hstimer.txt +++ b/Documentation/devicetree/bindings/timer/allwinner,sun5i-a13-hstimer.txt @@ -14,7 +14,7 @@ Optional properties: Example: -timer@01c60000 { +timer@1c60000 { compatible = "allwinner,sun7i-a20-hstimer"; reg = <0x01c60000 0x1000>; interrupts = <0 51 1>, diff --git a/Documentation/devicetree/bindings/trivial-devices.txt b/Documentation/devicetree/bindings/trivial-devices.txt index af284fbd4d23..4b169caab0eb 100644 --- a/Documentation/devicetree/bindings/trivial-devices.txt +++ b/Documentation/devicetree/bindings/trivial-devices.txt @@ -36,11 +36,9 @@ atmel,at97sc3204t i2c trusted platform module (TPM) capella,cm32181 CM32181: Ambient Light Sensor capella,cm3232 CM3232: Ambient Light Sensor cirrus,cs42l51 Cirrus Logic CS42L51 audio codec -dallas,ds1307 64 x 8, Serial, I2C Real-Time Clock -dallas,ds1338 I2C RTC with 56-Byte NV RAM -dallas,ds1340 I2C RTC with Trickle Charger dallas,ds1374 I2C, 32-Bit Binary Counter Watchdog RTC with Trickle Charger and Reset Input/Output dallas,ds1631 High-Precision Digital Thermometer +dallas,ds1672 Dallas DS1672 Real-time Clock dallas,ds1682 Total-Elapsed-Time Recorder with Alarm dallas,ds1775 Tiny Digital Thermometer and Thermostat dallas,ds3232 Extremely Accurate I²C RTC with Integrated Crystal and SRAM @@ -54,8 +52,8 @@ dlg,da9063 DA9063: system PMIC for quad-core application processors domintech,dmard09 DMARD09: 3-axis Accelerometer domintech,dmard10 DMARD10: 3-axis Accelerometer epson,rx8010 I2C-BUS INTERFACE REAL TIME CLOCK MODULE -epson,rx8025 High-Stability. I2C-Bus INTERFACE REAL TIME CLOCK MODULE epson,rx8581 I2C-BUS INTERFACE REAL TIME CLOCK MODULE +emmicro,em3027 EM Microelectronic EM3027 Real-time Clock fsl,mag3110 MAG3110: Xtrinsic High Accuracy, 3D Magnetometer fsl,mc13892 MC13892: Power Management Integrated Circuit (PMIC) for i.MX35/51 fsl,mma7660 MMA7660FC: 3-Axis Orientation/Motion Detection Sensor @@ -67,6 +65,8 @@ gmt,g751 G751: Digital Temperature Sensor and Thermal Watchdog with Two-Wire In infineon,slb9635tt Infineon SLB9635 (Soft-) I2C TPM (old protocol, max 100khz) infineon,slb9645tt Infineon SLB9645 I2C TPM (new protocol, max 400khz) isil,isl1208 Intersil ISL1208 Low Power RTC with Battery Backed SRAM +isil,isl1218 Intersil ISL1218 Low Power RTC with Battery Backed SRAM +isil,isl12022 Intersil ISL12022 Real-time Clock isil,isl29028 Intersil ISL29028 Ambient Light and Proximity Sensor isil,isl29030 Intersil ISL29030 Ambient Light and Proximity Sensor maxim,ds1050 5 Bit Programmable, Pulse-Width Modulator @@ -155,6 +155,7 @@ nxp,pca9556 Octal SMBus and I2C registered interface nxp,pca9557 8-bit I2C-bus and SMBus I/O port with reset nxp,pcf2127 Real-time clock nxp,pcf2129 Real-time clock +nxp,pcf8523 Real-time Clock nxp,pcf8563 Real-time clock/calendar nxp,pcf85063 Tiny Real-Time Clock oki,ml86v7667 OKI ML86V7667 video decoder @@ -174,10 +175,6 @@ sii,s35390a 2-wire CMOS real-time clock silabs,si7020 Relative Humidity and Temperature Sensors skyworks,sky81452 Skyworks SKY81452: Six-Channel White LED Driver with Touch Panel Bias Supply st,24c256 i2c serial eeprom (24cxx) -st,m41t0 Serial real-time clock (RTC) -st,m41t00 Serial real-time clock (RTC) -st,m41t62 Serial real-time clock (RTC) with alarm -st,m41t80 M41T80 - SERIAL ACCESS RTC WITH ALARMS taos,tsl2550 Ambient Light Sensor with SMBUS/Two Wire Serial Interface ti,ads7828 8-Channels, 12-bit ADC ti,ads7830 8-Channels, 8-bit ADC diff --git a/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.txt b/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.txt index cb2bd83fa89a..50abb20fe319 100644 --- a/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.txt +++ b/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.txt @@ -16,7 +16,7 @@ Required properties: Example: - usb_otg: usb@01c13000 { + usb_otg: usb@1c13000 { compatible = "allwinner,sun4i-a10-musb"; reg = <0x01c13000 0x0400>; clocks = <&ahb_gates 0>; diff --git a/Documentation/devicetree/bindings/usb/am33xx-usb.txt b/Documentation/devicetree/bindings/usb/am33xx-usb.txt index 16920d78e1b8..7a33f22c815a 100644 --- a/Documentation/devicetree/bindings/usb/am33xx-usb.txt +++ b/Documentation/devicetree/bindings/usb/am33xx-usb.txt @@ -181,7 +181,7 @@ usb: usb@47400000 { "tx14", "tx15"; }; - cppi41dma: dma-controller@07402000 { + cppi41dma: dma-controller@7402000 { compatible = "ti,am3359-cppi41"; reg = <0x47400000 0x1000 0x47402000 0x1000 diff --git a/Documentation/devicetree/bindings/usb/atmel-usb.txt b/Documentation/devicetree/bindings/usb/atmel-usb.txt index ad8ea56a9ed3..44e80153b148 100644 --- a/Documentation/devicetree/bindings/usb/atmel-usb.txt +++ b/Documentation/devicetree/bindings/usb/atmel-usb.txt @@ -18,7 +18,7 @@ Required properties: - atmel,oc-gpio: If present, specifies a gpio that needs to be activated for the overcurrent detection. -usb0: ohci@00500000 { +usb0: ohci@500000 { compatible = "atmel,at91rm9200-ohci", "usb-ohci"; reg = <0x00500000 0x100000>; clocks = <&uhphs_clk>, <&uhphs_clk>, <&uhpck>; @@ -39,7 +39,7 @@ Required properties: "ehci_clk" for the peripheral clock "usb_clk" for the UTMI clock -usb1: ehci@00800000 { +usb1: ehci@800000 { compatible = "atmel,at91sam9g45-ehci", "usb-ehci"; reg = <0x00800000 0x100000>; interrupts = <22 4>; diff --git a/Documentation/devicetree/bindings/usb/ohci-da8xx.txt b/Documentation/devicetree/bindings/usb/ohci-da8xx.txt index 2dc8f67eda39..24a826d5015e 100644 --- a/Documentation/devicetree/bindings/usb/ohci-da8xx.txt +++ b/Documentation/devicetree/bindings/usb/ohci-da8xx.txt @@ -13,7 +13,7 @@ Optional properties: Example: -ohci: usb@0225000 { +ohci: usb@225000 { compatible = "ti,da830-ohci"; reg = <0x225000 0x1000>; interrupts = <59>; diff --git a/Documentation/devicetree/bindings/usb/usb-ehci.txt b/Documentation/devicetree/bindings/usb/usb-ehci.txt index a12d6012a40f..3efde12b5d68 100644 --- a/Documentation/devicetree/bindings/usb/usb-ehci.txt +++ b/Documentation/devicetree/bindings/usb/usb-ehci.txt @@ -30,7 +30,7 @@ Example (Sequoia 440EPx): }; Example (Allwinner sun4i A10 SoC): - ehci0: usb@01c14000 { + ehci0: usb@1c14000 { compatible = "allwinner,sun4i-a10-ehci", "generic-ehci"; reg = <0x01c14000 0x100>; interrupts = <39>; diff --git a/Documentation/devicetree/bindings/usb/usb-ohci.txt b/Documentation/devicetree/bindings/usb/usb-ohci.txt index e8766b08c93b..09e70c875bc6 100644 --- a/Documentation/devicetree/bindings/usb/usb-ohci.txt +++ b/Documentation/devicetree/bindings/usb/usb-ohci.txt @@ -19,7 +19,7 @@ Optional properties: Example: - ohci0: usb@01c14400 { + ohci0: usb@1c14400 { compatible = "allwinner,sun4i-a10-ohci", "generic-ohci"; reg = <0x01c14400 0x100>; interrupts = <64>; diff --git a/Documentation/devicetree/bindings/usb/usb3503.txt b/Documentation/devicetree/bindings/usb/usb3503.txt index c1a0a9191d26..057dd384d473 100644 --- a/Documentation/devicetree/bindings/usb/usb3503.txt +++ b/Documentation/devicetree/bindings/usb/usb3503.txt @@ -26,7 +26,7 @@ Optional properties: clock frequencies table is used) Examples: - usb3503@08 { + usb3503@8 { compatible = "smsc,usb3503"; reg = <0x08>; connect-gpios = <&gpx3 0 1>; diff --git a/Documentation/devicetree/bindings/usb/usbmisc-imx.txt b/Documentation/devicetree/bindings/usb/usbmisc-imx.txt index f1e27faf528e..a85a631ec434 100644 --- a/Documentation/devicetree/bindings/usb/usbmisc-imx.txt +++ b/Documentation/devicetree/bindings/usb/usbmisc-imx.txt @@ -10,7 +10,7 @@ Required properties: - reg: Should contain registers location and length Examples: -usbmisc@02184800 { +usbmisc@2184800 { #index-cells = <1>; compatible = "fsl,imx6q-usbmisc"; reg = <0x02184800 0x200>; diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 1ea1fd4232ab..b2c1b8d80367 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -83,6 +83,7 @@ davicom DAVICOM Semiconductor, Inc. delta Delta Electronics, Inc. denx Denx Software Engineering devantech Devantech, Ltd. +dh DH electronics GmbH digi Digi International Inc. digilent Diglent, Inc. dioo Dioo Microcircuit Co., Ltd @@ -229,12 +230,14 @@ netlogic Broadcom Corporation (formerly NetLogic Microsystems) netron-dy Netron DY netxeon Shenzhen Netxeon Technology CO., LTD nexbox Nexbox +nextthing Next Thing Co. newhaven Newhaven Display International ni National Instruments nintendo Nintendo nlt NLT Technologies, Ltd. nokia Nokia nordic Nordic Semiconductor +nutsboard NutsBoard nuvoton Nuvoton Technology Corporation nvd New Vision Display nvidia NVIDIA @@ -245,6 +248,7 @@ olimex OLIMEX Ltd. onion Onion Corporation onnn ON Semiconductor Corp. ontat On Tat Industrial Company +opalkelly Opal Kelly Incorporated opencores OpenCores.org option Option NV ORCL Oracle Corporation @@ -296,6 +300,7 @@ sensirion Sensirion AG sff Small Form Factor Committee sgx SGX Sensortech sharp Sharp Corporation +shimafuji Shimafuji Electric, Inc. si-en Si-En Technology Ltd. sigma Sigma Designs, Inc. sii Seiko Instruments, Inc. @@ -317,6 +322,7 @@ solomon Solomon Systech Limited sony Sony Corporation spansion Spansion Inc. sprd Spreadtrum Communications Inc. +sst Silicon Storage Technology, Inc. st STMicroelectronics starry Starry Electronic Technology (ShenZhen) Co., LTD startek Startek @@ -338,6 +344,7 @@ thine THine Electronics, Inc. ti Texas Instruments tianma Tianma Micro-electronics Co., Ltd. tlm Trusted Logic Mobility +tmt Tecon Microprocessor Technologies, LLC. topeet Topeet toradex Toradex AG toshiba Toshiba Corporation diff --git a/Documentation/devicetree/bindings/watchdog/mtk-wdt.txt b/Documentation/devicetree/bindings/watchdog/mtk-wdt.txt index 235de0683bb6..5b38a30e608c 100644 --- a/Documentation/devicetree/bindings/watchdog/mtk-wdt.txt +++ b/Documentation/devicetree/bindings/watchdog/mtk-wdt.txt @@ -13,7 +13,7 @@ Required properties: Example: -wdt: watchdog@010000000 { +wdt: watchdog@10000000 { compatible = "mediatek,mt6589-wdt"; reg = <0x10000000 0x18>; }; diff --git a/Documentation/devicetree/bindings/watchdog/sunxi-wdt.txt b/Documentation/devicetree/bindings/watchdog/sunxi-wdt.txt index b8f75c51453a..62dd5baad70e 100644 --- a/Documentation/devicetree/bindings/watchdog/sunxi-wdt.txt +++ b/Documentation/devicetree/bindings/watchdog/sunxi-wdt.txt @@ -8,7 +8,7 @@ Required properties: Example: -wdt: watchdog@01c20c90 { +wdt: watchdog@1c20c90 { compatible = "allwinner,sun4i-a10-wdt"; reg = <0x01c20c90 0x10>; }; diff --git a/Documentation/devicetree/overlay-notes.txt b/Documentation/devicetree/overlay-notes.txt index eb7f2685fda1..c4aa0adf13ec 100644 --- a/Documentation/devicetree/overlay-notes.txt +++ b/Documentation/devicetree/overlay-notes.txt @@ -87,15 +87,15 @@ Overlay in-kernel API The API is quite easy to use. -1. Call of_overlay_create() to create and apply an overlay. The return value -is a cookie identifying this overlay. +1. Call of_overlay_apply() to create and apply an overlay changeset. The return +value is an error or a cookie identifying this overlay. -2. Call of_overlay_destroy() to remove and cleanup the overlay previously -created via the call to of_overlay_create(). Removal of an overlay that -is stacked by another will not be permitted. +2. Call of_overlay_remove() to remove and cleanup the overlay changeset +previously created via the call to of_overlay_apply(). Removal of an overlay +changeset that is stacked by another will not be permitted. Finally, if you need to remove all overlays in one-go, just call -of_overlay_destroy_all() which will remove every single one in the correct +of_overlay_remove_all() which will remove every single one in the correct order. Overlay DTS Format diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c index 783f36364690..2e2efb1af511 100644 --- a/arch/powerpc/platforms/pseries/dlpar.c +++ b/arch/powerpc/platforms/pseries/dlpar.c @@ -75,24 +75,17 @@ static struct property *dlpar_parse_cc_property(struct cc_workarea *ccwa) return prop; } -static struct device_node *dlpar_parse_cc_node(struct cc_workarea *ccwa, - const char *path) +static struct device_node *dlpar_parse_cc_node(struct cc_workarea *ccwa) { struct device_node *dn; - char *name; - - /* If parent node path is "/" advance path to NULL terminator to - * prevent double leading slashs in full_name. - */ - if (!path[1]) - path++; + const char *name; dn = kzalloc(sizeof(*dn), GFP_KERNEL); if (!dn) return NULL; - name = (char *)ccwa + be32_to_cpu(ccwa->name_offset); - dn->full_name = kasprintf(GFP_KERNEL, "%s/%s", path, name); + name = (const char *)ccwa + be32_to_cpu(ccwa->name_offset); + dn->full_name = kstrdup(name, GFP_KERNEL); if (!dn->full_name) { kfree(dn); return NULL; @@ -148,7 +141,6 @@ struct device_node *dlpar_configure_connector(__be32 drc_index, struct property *last_property = NULL; struct cc_workarea *ccwa; char *data_buf; - const char *parent_path = parent->full_name; int cc_token; int rc = -1; @@ -182,7 +174,7 @@ struct device_node *dlpar_configure_connector(__be32 drc_index, break; case NEXT_SIBLING: - dn = dlpar_parse_cc_node(ccwa, parent_path); + dn = dlpar_parse_cc_node(ccwa); if (!dn) goto cc_error; @@ -192,10 +184,7 @@ struct device_node *dlpar_configure_connector(__be32 drc_index, break; case NEXT_CHILD: - if (first_dn) - parent_path = last_dn->full_name; - - dn = dlpar_parse_cc_node(ccwa, parent_path); + dn = dlpar_parse_cc_node(ccwa); if (!dn) goto cc_error; @@ -226,7 +215,6 @@ struct device_node *dlpar_configure_connector(__be32 drc_index, case PREV_PARENT: last_dn = last_dn->parent; - parent_path = last_dn->parent->full_name; break; case CALL_AGAIN: diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index 296c188fd5ca..f24d8159c9e1 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c @@ -33,7 +33,7 @@ static int pSeries_reconfig_add_node(const char *path, struct property *proplist if (!np) goto out_err; - np->full_name = kstrdup(path, GFP_KERNEL); + np->full_name = kstrdup(kbasename(path), GFP_KERNEL); if (!np->full_name) goto out_err; diff --git a/drivers/base/core.c b/drivers/base/core.c index 12ebd055724c..c07b47059538 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1571,7 +1571,7 @@ static int device_add_class_symlinks(struct device *dev) int error; if (of_node) { - error = sysfs_create_link(&dev->kobj, &of_node->kobj,"of_node"); + error = sysfs_create_link(&dev->kobj, of_node_kobj(of_node), "of_node"); if (error) dev_warn(dev, "Error %d creating of_node link\n",error); /* An error here doesn't warrant bringing down the device */ diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c b/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c index 623a9140493c..54025af534d4 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c @@ -145,7 +145,6 @@ static struct device_node * __init tilcdc_get_overlay(struct kfree_table *kft) __dtb_tilcdc_slave_compat_begin; static void *overlay_data; struct device_node *overlay; - int ret; if (!size) { pr_warn("%s: No overlay data\n", __func__); @@ -164,11 +163,6 @@ static struct device_node * __init tilcdc_get_overlay(struct kfree_table *kft) } of_node_set_flag(overlay, OF_DETACHED); - ret = of_resolve_phandles(overlay); - if (ret) { - pr_err("%s: Failed to resolve phandles: %d\n", __func__, ret); - return NULL; - } return overlay; } @@ -204,7 +198,7 @@ static void __init tilcdc_convert_slave_node(void) /* For all memory needed for the overlay tree. This memory can be freed after the overlay has been applied. */ struct kfree_table kft; - int ret; + int ovcs_id, ret; if (kfree_table_init(&kft)) return; @@ -247,9 +241,11 @@ static void __init tilcdc_convert_slave_node(void) tilcdc_node_disable(slave); - ret = of_overlay_create(overlay); + ovcs_id = 0; + ret = of_overlay_apply(overlay, &ovcs_id); if (ret) - pr_err("%s: Creating overlay failed: %d\n", __func__, ret); + pr_err("%s: Applying overlay changeset failed: %d\n", + __func__, ret); else pr_info("%s: ti,tilcdc,slave node successfully converted\n", __func__); diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index ba7b034b2b91..ad9a9578f9c4 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig @@ -46,10 +46,14 @@ config OF_EARLY_FLATTREE config OF_PROMTREE bool +config OF_KOBJ + def_bool SYSFS + # Hardly any platforms need this. It is safe to select, but only do so if you # need it. config OF_DYNAMIC bool "Support for dynamic device trees" if OF_UNITTEST + select OF_KOBJ help On some platforms, the device tree can be manipulated at runtime. While this option is selected automatically on such platforms, you diff --git a/drivers/of/Makefile b/drivers/of/Makefile index 97dc01c81438..83d61a7c5e82 100644 --- a/drivers/of/Makefile +++ b/drivers/of/Makefile @@ -1,4 +1,5 @@ obj-y = base.o device.o platform.o property.o +obj-$(CONFIG_OF_KOBJ) += kobj.o obj-$(CONFIG_OF_DYNAMIC) += dynamic.o obj-$(CONFIG_OF_FLATTREE) += fdt.o obj-$(CONFIG_OF_EARLY_FLATTREE) += fdt_address.o diff --git a/drivers/of/base.c b/drivers/of/base.c index 260d33c0f26c..3de07e6e82a0 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -95,108 +95,6 @@ int __weak of_node_to_nid(struct device_node *np) } #endif -#ifndef CONFIG_OF_DYNAMIC -static void of_node_release(struct kobject *kobj) -{ - /* Without CONFIG_OF_DYNAMIC, no nodes gets freed */ -} -#endif /* CONFIG_OF_DYNAMIC */ - -struct kobj_type of_node_ktype = { - .release = of_node_release, -}; - -static ssize_t of_node_property_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, char *buf, - loff_t offset, size_t count) -{ - struct property *pp = container_of(bin_attr, struct property, attr); - return memory_read_from_buffer(buf, count, &offset, pp->value, pp->length); -} - -/* always return newly allocated name, caller must free after use */ -static const char *safe_name(struct kobject *kobj, const char *orig_name) -{ - const char *name = orig_name; - struct kernfs_node *kn; - int i = 0; - - /* don't be a hero. After 16 tries give up */ - while (i < 16 && (kn = sysfs_get_dirent(kobj->sd, name))) { - sysfs_put(kn); - if (name != orig_name) - kfree(name); - name = kasprintf(GFP_KERNEL, "%s#%i", orig_name, ++i); - } - - if (name == orig_name) { - name = kstrdup(orig_name, GFP_KERNEL); - } else { - pr_warn("Duplicate name in %s, renamed to \"%s\"\n", - kobject_name(kobj), name); - } - return name; -} - -int __of_add_property_sysfs(struct device_node *np, struct property *pp) -{ - int rc; - - /* Important: Don't leak passwords */ - bool secure = strncmp(pp->name, "security-", 9) == 0; - - if (!IS_ENABLED(CONFIG_SYSFS)) - return 0; - - if (!of_kset || !of_node_is_attached(np)) - return 0; - - sysfs_bin_attr_init(&pp->attr); - pp->attr.attr.name = safe_name(&np->kobj, pp->name); - pp->attr.attr.mode = secure ? 0400 : 0444; - pp->attr.size = secure ? 0 : pp->length; - pp->attr.read = of_node_property_read; - - rc = sysfs_create_bin_file(&np->kobj, &pp->attr); - WARN(rc, "error adding attribute %s to node %pOF\n", pp->name, np); - return rc; -} - -int __of_attach_node_sysfs(struct device_node *np) -{ - const char *name; - struct kobject *parent; - struct property *pp; - int rc; - - if (!IS_ENABLED(CONFIG_SYSFS)) - return 0; - - if (!of_kset) - return 0; - - np->kobj.kset = of_kset; - if (!np->parent) { - /* Nodes without parents are new top level trees */ - name = safe_name(&of_kset->kobj, "base"); - parent = NULL; - } else { - name = safe_name(&np->parent->kobj, kbasename(np->full_name)); - parent = &np->parent->kobj; - } - if (!name) - return -ENOMEM; - rc = kobject_add(&np->kobj, parent, "%s", name); - kfree(name); - if (rc) - return rc; - - for_each_property_of_node(np, pp) - __of_add_property_sysfs(np, pp); - - return 0; -} - void __init of_core_init(void) { struct device_node *np; @@ -760,7 +658,7 @@ struct device_node *of_get_child_by_name(const struct device_node *node, } EXPORT_SYMBOL(of_get_child_by_name); -static struct device_node *__of_find_node_by_path(struct device_node *parent, +struct device_node *__of_find_node_by_path(struct device_node *parent, const char *path) { struct device_node *child; @@ -1504,22 +1402,6 @@ int __of_remove_property(struct device_node *np, struct property *prop) return 0; } -void __of_sysfs_remove_bin_file(struct device_node *np, struct property *prop) -{ - sysfs_remove_bin_file(&np->kobj, &prop->attr); - kfree(prop->attr.attr.name); -} - -void __of_remove_property_sysfs(struct device_node *np, struct property *prop) -{ - if (!IS_ENABLED(CONFIG_SYSFS)) - return; - - /* at early boot, bail here and defer setup to of_init() */ - if (of_kset && of_node_is_attached(np)) - __of_sysfs_remove_bin_file(np, prop); -} - /** * of_remove_property - Remove a property from a node. * @@ -1579,21 +1461,6 @@ int __of_update_property(struct device_node *np, struct property *newprop, return 0; } -void __of_update_property_sysfs(struct device_node *np, struct property *newprop, - struct property *oldprop) -{ - if (!IS_ENABLED(CONFIG_SYSFS)) - return; - - /* At early boot, bail out and defer setup to of_init() */ - if (!of_kset) - return; - - if (oldprop) - __of_sysfs_remove_bin_file(np, oldprop); - __of_add_property_sysfs(np, newprop); -} - /* * of_update_property - Update a property in a node, if the property does * not exist, add it. diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c index 301b6db2b48d..c454941b34ec 100644 --- a/drivers/of/dynamic.c +++ b/drivers/of/dynamic.c @@ -16,6 +16,11 @@ #include "of_private.h" +static struct device_node *kobj_to_device_node(struct kobject *kobj) +{ + return container_of(kobj, struct device_node, kobj); +} + /** * of_node_get() - Increment refcount of a node * @node: Node to inc refcount, NULL is supported to simplify writing of @@ -43,28 +48,6 @@ void of_node_put(struct device_node *node) } EXPORT_SYMBOL(of_node_put); -void __of_detach_node_sysfs(struct device_node *np) -{ - struct property *pp; - - if (!IS_ENABLED(CONFIG_SYSFS)) - return; - - BUG_ON(!of_node_is_initialized(np)); - if (!of_kset) - return; - - /* only remove properties if on sysfs */ - if (of_node_is_attached(np)) { - for_each_property_of_node(np, pp) - __of_sysfs_remove_bin_file(np, pp); - kobject_del(&np->kobj); - } - - /* finally remove the kobj_init ref */ - of_node_put(np); -} - static BLOCKING_NOTIFIER_HEAD(of_reconfig_chain); int of_reconfig_notifier_register(struct notifier_block *nb) @@ -315,6 +298,18 @@ int of_detach_node(struct device_node *np) } EXPORT_SYMBOL_GPL(of_detach_node); +static void property_list_free(struct property *prop_list) +{ + struct property *prop, *next; + + for (prop = prop_list; prop != NULL; prop = next) { + next = prop->next; + kfree(prop->name); + kfree(prop->value); + kfree(prop); + } +} + /** * of_node_release() - release a dynamically allocated node * @kref: kref element of the node to be released @@ -324,7 +319,6 @@ EXPORT_SYMBOL_GPL(of_detach_node); void of_node_release(struct kobject *kobj) { struct device_node *node = kobj_to_device_node(kobj); - struct property *prop = node->properties; /* We should never be releasing nodes that haven't been detached. */ if (!of_node_check_flag(node, OF_DETACHED)) { @@ -335,18 +329,9 @@ void of_node_release(struct kobject *kobj) if (!of_node_check_flag(node, OF_DYNAMIC)) return; - while (prop) { - struct property *next = prop->next; - kfree(prop->name); - kfree(prop->value); - kfree(prop); - prop = next; + property_list_free(node->properties); + property_list_free(node->deadprops); - if (!prop) { - prop = node->deadprops; - node->deadprops = NULL; - } - } kfree(node->full_name); kfree(node->data); kfree(node); @@ -508,11 +493,12 @@ static void __of_changeset_entry_invert(struct of_changeset_entry *ce, } } -static void __of_changeset_entry_notify(struct of_changeset_entry *ce, bool revert) +static int __of_changeset_entry_notify(struct of_changeset_entry *ce, + bool revert) { struct of_reconfig_data rd; struct of_changeset_entry ce_inverted; - int ret; + int ret = 0; if (revert) { __of_changeset_entry_invert(ce, &ce_inverted); @@ -534,11 +520,12 @@ static void __of_changeset_entry_notify(struct of_changeset_entry *ce, bool reve default: pr_err("invalid devicetree changeset action: %i\n", (int)ce->action); - return; + ret = -EINVAL; } if (ret) pr_err("changeset notifier error @%pOF\n", ce->np); + return ret; } static int __of_changeset_entry_apply(struct of_changeset_entry *ce) @@ -672,32 +659,82 @@ void of_changeset_destroy(struct of_changeset *ocs) } EXPORT_SYMBOL_GPL(of_changeset_destroy); -int __of_changeset_apply(struct of_changeset *ocs) +/* + * Apply the changeset entries in @ocs. + * If apply fails, an attempt is made to revert the entries that were + * successfully applied. + * + * If multiple revert errors occur then only the final revert error is reported. + * + * Returns 0 on success, a negative error value in case of an error. + * If a revert error occurs, it is returned in *ret_revert. + */ +int __of_changeset_apply_entries(struct of_changeset *ocs, int *ret_revert) { struct of_changeset_entry *ce; - int ret; + int ret, ret_tmp; - /* perform the rest of the work */ pr_debug("changeset: applying...\n"); list_for_each_entry(ce, &ocs->entries, node) { ret = __of_changeset_entry_apply(ce); if (ret) { pr_err("Error applying changeset (%d)\n", ret); - list_for_each_entry_continue_reverse(ce, &ocs->entries, node) - __of_changeset_entry_revert(ce); + list_for_each_entry_continue_reverse(ce, &ocs->entries, + node) { + ret_tmp = __of_changeset_entry_revert(ce); + if (ret_tmp) + *ret_revert = ret_tmp; + } return ret; } } - pr_debug("changeset: applied, emitting notifiers.\n"); + + return 0; +} + +/* + * Returns 0 on success, a negative error value in case of an error. + * + * If multiple changset entry notification errors occur then only the + * final notification error is reported. + */ +int __of_changeset_apply_notify(struct of_changeset *ocs) +{ + struct of_changeset_entry *ce; + int ret = 0, ret_tmp; + + pr_debug("changeset: emitting notifiers.\n"); /* drop the global lock while emitting notifiers */ mutex_unlock(&of_mutex); - list_for_each_entry(ce, &ocs->entries, node) - __of_changeset_entry_notify(ce, 0); + list_for_each_entry(ce, &ocs->entries, node) { + ret_tmp = __of_changeset_entry_notify(ce, 0); + if (ret_tmp) + ret = ret_tmp; + } mutex_lock(&of_mutex); pr_debug("changeset: notifiers sent.\n"); - return 0; + return ret; +} + +/* + * Returns 0 on success, a negative error value in case of an error. + * + * If a changeset entry apply fails, an attempt is made to revert any + * previous entries in the changeset. If any of the reverts fails, + * that failure is not reported. Thus the state of the device tree + * is unknown if an apply error occurs. + */ +static int __of_changeset_apply(struct of_changeset *ocs) +{ + int ret, ret_revert = 0; + + ret = __of_changeset_apply_entries(ocs, &ret_revert); + if (!ret) + ret = __of_changeset_apply_notify(ocs); + + return ret; } /** @@ -724,31 +761,74 @@ int of_changeset_apply(struct of_changeset *ocs) } EXPORT_SYMBOL_GPL(of_changeset_apply); -int __of_changeset_revert(struct of_changeset *ocs) +/* + * Revert the changeset entries in @ocs. + * If revert fails, an attempt is made to re-apply the entries that were + * successfully removed. + * + * If multiple re-apply errors occur then only the final apply error is + * reported. + * + * Returns 0 on success, a negative error value in case of an error. + * If an apply error occurs, it is returned in *ret_apply. + */ +int __of_changeset_revert_entries(struct of_changeset *ocs, int *ret_apply) { struct of_changeset_entry *ce; - int ret; + int ret, ret_tmp; pr_debug("changeset: reverting...\n"); list_for_each_entry_reverse(ce, &ocs->entries, node) { ret = __of_changeset_entry_revert(ce); if (ret) { pr_err("Error reverting changeset (%d)\n", ret); - list_for_each_entry_continue(ce, &ocs->entries, node) - __of_changeset_entry_apply(ce); + list_for_each_entry_continue(ce, &ocs->entries, node) { + ret_tmp = __of_changeset_entry_apply(ce); + if (ret_tmp) + *ret_apply = ret_tmp; + } return ret; } } - pr_debug("changeset: reverted, emitting notifiers.\n"); + + return 0; +} + +/* + * If multiple changset entry notification errors occur then only the + * final notification error is reported. + */ +int __of_changeset_revert_notify(struct of_changeset *ocs) +{ + struct of_changeset_entry *ce; + int ret = 0, ret_tmp; + + pr_debug("changeset: emitting notifiers.\n"); /* drop the global lock while emitting notifiers */ mutex_unlock(&of_mutex); - list_for_each_entry_reverse(ce, &ocs->entries, node) - __of_changeset_entry_notify(ce, 1); + list_for_each_entry_reverse(ce, &ocs->entries, node) { + ret_tmp = __of_changeset_entry_notify(ce, 1); + if (ret_tmp) + ret = ret_tmp; + } mutex_lock(&of_mutex); pr_debug("changeset: notifiers sent.\n"); - return 0; + return ret; +} + +static int __of_changeset_revert(struct of_changeset *ocs) +{ + int ret, ret_reply; + + ret_reply = 0; + ret = __of_changeset_revert_entries(ocs, &ret_reply); + + if (!ret) + ret = __of_changeset_revert_notify(ocs); + + return ret; } /** @@ -775,7 +855,7 @@ int of_changeset_revert(struct of_changeset *ocs) EXPORT_SYMBOL_GPL(of_changeset_revert); /** - * of_changeset_action - Perform a changeset action + * of_changeset_action - Add an action to the tail of the changeset list * * @ocs: changeset pointer * @action: action to perform diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index ce30c9a588a4..4675e5ac4d11 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -132,6 +132,19 @@ bool of_fdt_is_big_endian(const void *blob, unsigned long node) return false; } +static bool of_fdt_device_is_available(const void *blob, unsigned long node) +{ + const char *status = fdt_getprop(blob, node, "status", NULL); + + if (!status) + return true; + + if (!strcmp(status, "ok") || !strcmp(status, "okay")) + return true; + + return false; +} + /** * of_fdt_match - Return true if node matches a list of compatible values */ @@ -266,74 +279,32 @@ static void populate_properties(const void *blob, *pprev = NULL; } -static unsigned int populate_node(const void *blob, - int offset, - void **mem, - struct device_node *dad, - unsigned int fpsize, - struct device_node **pnp, - bool dryrun) +static bool populate_node(const void *blob, + int offset, + void **mem, + struct device_node *dad, + struct device_node **pnp, + bool dryrun) { struct device_node *np; const char *pathp; unsigned int l, allocl; - int new_format = 0; pathp = fdt_get_name(blob, offset, &l); if (!pathp) { *pnp = NULL; - return 0; + return false; } allocl = ++l; - /* version 0x10 has a more compact unit name here instead of the full - * path. we accumulate the full path size using "fpsize", we'll rebuild - * it later. We detect this because the first character of the name is - * not '/'. - */ - if ((*pathp) != '/') { - new_format = 1; - if (fpsize == 0) { - /* root node: special case. fpsize accounts for path - * plus terminating zero. root node only has '/', so - * fpsize should be 2, but we want to avoid the first - * level nodes to have two '/' so we use fpsize 1 here - */ - fpsize = 1; - allocl = 2; - l = 1; - pathp = ""; - } else { - /* account for '/' and path size minus terminal 0 - * already in 'l' - */ - fpsize += l; - allocl = fpsize; - } - } - np = unflatten_dt_alloc(mem, sizeof(struct device_node) + allocl, __alignof__(struct device_node)); if (!dryrun) { char *fn; of_node_init(np); np->full_name = fn = ((char *)np) + sizeof(*np); - if (new_format) { - /* rebuild full path for new format */ - if (dad && dad->parent) { - strcpy(fn, dad->full_name); -#ifdef DEBUG - if ((strlen(fn) + l + 1) != allocl) { - pr_debug("%s: p: %d, l: %d, a: %d\n", - pathp, (int)strlen(fn), - l, allocl); - } -#endif - fn += strlen(fn); - } - *(fn++) = '/'; - } + memcpy(fn, pathp, l); if (dad != NULL) { @@ -355,7 +326,7 @@ static unsigned int populate_node(const void *blob, } *pnp = np; - return fpsize; + return true; } static void reverse_nodes(struct device_node *parent) @@ -399,7 +370,6 @@ static int unflatten_dt_nodes(const void *blob, struct device_node *root; int offset = 0, depth = 0, initial_depth = 0; #define FDT_MAX_DEPTH 64 - unsigned int fpsizes[FDT_MAX_DEPTH]; struct device_node *nps[FDT_MAX_DEPTH]; void *base = mem; bool dryrun = !base; @@ -418,7 +388,6 @@ static int unflatten_dt_nodes(const void *blob, depth = initial_depth = 1; root = dad; - fpsizes[depth] = dad ? strlen(of_node_full_name(dad)) : 0; nps[depth] = dad; for (offset = 0; @@ -427,11 +396,12 @@ static int unflatten_dt_nodes(const void *blob, if (WARN_ON_ONCE(depth >= FDT_MAX_DEPTH)) continue; - fpsizes[depth+1] = populate_node(blob, offset, &mem, - nps[depth], - fpsizes[depth], - &nps[depth+1], dryrun); - if (!fpsizes[depth+1]) + if (!IS_ENABLED(CONFIG_OF_KOBJ) && + !of_fdt_device_is_available(blob, offset)) + continue; + + if (!populate_node(blob, offset, &mem, nps[depth], + &nps[depth+1], dryrun)) return mem - base; if (!dryrun && nodepp && !*nodepp) @@ -467,6 +437,7 @@ static int unflatten_dt_nodes(const void *blob, * @mynodes: The device_node tree created by the call * @dt_alloc: An allocator that provides a virtual address to memory * for the resulting tree + * @detached: if true set OF_DETACHED on @mynodes * * Returns NULL on failure or the memory chunk containing the unflattened * device tree on success. @@ -652,7 +623,6 @@ static int __init __fdt_scan_reserved_mem(unsigned long node, const char *uname, int depth, void *data) { static int found; - const char *status; int err; if (!found && depth == 1 && strcmp(uname, "reserved-memory") == 0) { @@ -672,8 +642,7 @@ static int __init __fdt_scan_reserved_mem(unsigned long node, const char *uname, return 1; } - status = of_get_flat_dt_prop(node, "status", NULL); - if (status && strcmp(status, "okay") != 0 && strcmp(status, "ok") != 0) + if (!of_fdt_device_is_available(initial_boot_params, node)) return 0; err = __reserved_mem_reserve_reg(node, uname); diff --git a/drivers/of/kobj.c b/drivers/of/kobj.c new file mode 100644 index 000000000000..250fc7bb550f --- /dev/null +++ b/drivers/of/kobj.c @@ -0,0 +1,164 @@ +#include <linux/of.h> +#include <linux/slab.h> + +#include "of_private.h" + +/* true when node is initialized */ +static int of_node_is_initialized(struct device_node *node) +{ + return node && node->kobj.state_initialized; +} + +/* true when node is attached (i.e. present on sysfs) */ +int of_node_is_attached(struct device_node *node) +{ + return node && node->kobj.state_in_sysfs; +} + + +#ifndef CONFIG_OF_DYNAMIC +static void of_node_release(struct kobject *kobj) +{ + /* Without CONFIG_OF_DYNAMIC, no nodes gets freed */ +} +#endif /* CONFIG_OF_DYNAMIC */ + +struct kobj_type of_node_ktype = { + .release = of_node_release, +}; + +static ssize_t of_node_property_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, char *buf, + loff_t offset, size_t count) +{ + struct property *pp = container_of(bin_attr, struct property, attr); + return memory_read_from_buffer(buf, count, &offset, pp->value, pp->length); +} + +/* always return newly allocated name, caller must free after use */ +static const char *safe_name(struct kobject *kobj, const char *orig_name) +{ + const char *name = orig_name; + struct kernfs_node *kn; + int i = 0; + + /* don't be a hero. After 16 tries give up */ + while (i < 16 && (kn = sysfs_get_dirent(kobj->sd, name))) { + sysfs_put(kn); + if (name != orig_name) + kfree(name); + name = kasprintf(GFP_KERNEL, "%s#%i", orig_name, ++i); + } + + if (name == orig_name) { + name = kstrdup(orig_name, GFP_KERNEL); + } else { + pr_warn("Duplicate name in %s, renamed to \"%s\"\n", + kobject_name(kobj), name); + } + return name; +} + +int __of_add_property_sysfs(struct device_node *np, struct property *pp) +{ + int rc; + + /* Important: Don't leak passwords */ + bool secure = strncmp(pp->name, "security-", 9) == 0; + + if (!IS_ENABLED(CONFIG_SYSFS)) + return 0; + + if (!of_kset || !of_node_is_attached(np)) + return 0; + + sysfs_bin_attr_init(&pp->attr); + pp->attr.attr.name = safe_name(&np->kobj, pp->name); + pp->attr.attr.mode = secure ? 0400 : 0444; + pp->attr.size = secure ? 0 : pp->length; + pp->attr.read = of_node_property_read; + + rc = sysfs_create_bin_file(&np->kobj, &pp->attr); + WARN(rc, "error adding attribute %s to node %pOF\n", pp->name, np); + return rc; +} + +void __of_sysfs_remove_bin_file(struct device_node *np, struct property *prop) +{ + if (!IS_ENABLED(CONFIG_SYSFS)) + return; + + sysfs_remove_bin_file(&np->kobj, &prop->attr); + kfree(prop->attr.attr.name); +} + +void __of_remove_property_sysfs(struct device_node *np, struct property *prop) +{ + /* at early boot, bail here and defer setup to of_init() */ + if (of_kset && of_node_is_attached(np)) + __of_sysfs_remove_bin_file(np, prop); +} + +void __of_update_property_sysfs(struct device_node *np, struct property *newprop, + struct property *oldprop) +{ + /* At early boot, bail out and defer setup to of_init() */ + if (!of_kset) + return; + + if (oldprop) + __of_sysfs_remove_bin_file(np, oldprop); + __of_add_property_sysfs(np, newprop); +} + +int __of_attach_node_sysfs(struct device_node *np) +{ + const char *name; + struct kobject *parent; + struct property *pp; + int rc; + + if (!of_kset) + return 0; + + np->kobj.kset = of_kset; + if (!np->parent) { + /* Nodes without parents are new top level trees */ + name = safe_name(&of_kset->kobj, "base"); + parent = NULL; + } else { + name = safe_name(&np->parent->kobj, kbasename(np->full_name)); + parent = &np->parent->kobj; + } + if (!name) + return -ENOMEM; + rc = kobject_add(&np->kobj, parent, "%s", name); + kfree(name); + if (rc) + return rc; + + for_each_property_of_node(np, pp) + __of_add_property_sysfs(np, pp); + + return 0; +} + +void __of_detach_node_sysfs(struct device_node *np) +{ + struct property *pp; + + BUG_ON(!of_node_is_initialized(np)); + if (!of_kset) + return; + + /* only remove properties if on sysfs */ + if (of_node_is_attached(np)) { + for_each_property_of_node(np, pp) + __of_sysfs_remove_bin_file(np, pp); + kobject_del(&np->kobj); + } + + /* finally remove the kobj_init ref */ + of_node_put(np); +} + diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h index 3ae12ffbf547..92a9a3687446 100644 --- a/drivers/of/of_private.h +++ b/drivers/of/of_private.h @@ -35,18 +35,16 @@ extern struct mutex of_mutex; extern struct list_head aliases_lookup; extern struct kset *of_kset; - -static inline struct device_node *kobj_to_device_node(struct kobject *kobj) -{ - return container_of(kobj, struct device_node, kobj); -} - #if defined(CONFIG_OF_DYNAMIC) extern int of_property_notify(int action, struct device_node *np, struct property *prop, struct property *old_prop); extern void of_node_release(struct kobject *kobj); -extern int __of_changeset_apply(struct of_changeset *ocs); -extern int __of_changeset_revert(struct of_changeset *ocs); +extern int __of_changeset_apply_entries(struct of_changeset *ocs, + int *ret_revert); +extern int __of_changeset_apply_notify(struct of_changeset *ocs); +extern int __of_changeset_revert_entries(struct of_changeset *ocs, + int *ret_apply); +extern int __of_changeset_revert_notify(struct of_changeset *ocs); #else /* CONFIG_OF_DYNAMIC */ static inline int of_property_notify(int action, struct device_node *np, struct property *prop, struct property *old_prop) @@ -55,6 +53,41 @@ static inline int of_property_notify(int action, struct device_node *np, } #endif /* CONFIG_OF_DYNAMIC */ +#if defined(CONFIG_OF_KOBJ) +int of_node_is_attached(struct device_node *node); +int __of_add_property_sysfs(struct device_node *np, struct property *pp); +void __of_remove_property_sysfs(struct device_node *np, struct property *prop); +void __of_update_property_sysfs(struct device_node *np, struct property *newprop, + struct property *oldprop); +int __of_attach_node_sysfs(struct device_node *np); +void __of_detach_node_sysfs(struct device_node *np); +#else +static inline int __of_add_property_sysfs(struct device_node *np, struct property *pp) +{ + return 0; +} +static inline void __of_remove_property_sysfs(struct device_node *np, struct property *prop) {} +static inline void __of_update_property_sysfs(struct device_node *np, + struct property *newprop, struct property *oldprop) {} +static inline int __of_attach_node_sysfs(struct device_node *np) +{ + return 0; +} +static inline void __of_detach_node_sysfs(struct device_node *np) {} +#endif + +#if defined(CONFIG_OF_RESOLVE) +int of_resolve_phandles(struct device_node *tree); +#endif + +#if defined(CONFIG_OF_OVERLAY) +void of_overlay_mutex_lock(void); +void of_overlay_mutex_unlock(void); +#else +static inline void of_overlay_mutex_lock(void) {}; +static inline void of_overlay_mutex_unlock(void) {}; +#endif + #if defined(CONFIG_OF_UNITTEST) && defined(CONFIG_OF_OVERLAY) extern void __init unittest_unflatten_overlay_base(void); #else @@ -77,6 +110,8 @@ extern void *__unflatten_device_tree(const void *blob, struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags); __printf(2, 3) struct device_node *__of_node_dup(const struct device_node *np, const char *fmt, ...); +struct device_node *__of_find_node_by_path(struct device_node *parent, + const char *path); struct device_node *__of_find_node_by_full_path(struct device_node *node, const char *path); diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c index 8ecfee31ab6d..c150abb9049d 100644 --- a/drivers/of/overlay.c +++ b/drivers/of/overlay.c @@ -25,252 +25,378 @@ #include "of_private.h" /** - * struct of_overlay_info - Holds a single overlay info + * struct fragment - info about fragment nodes in overlay expanded device tree * @target: target of the overlay operation - * @overlay: pointer to the overlay contents node - * - * Holds a single overlay state, including all the overlay logs & - * records. + * @overlay: pointer to the __overlay__ node */ -struct of_overlay_info { +struct fragment { struct device_node *target; struct device_node *overlay; - bool is_symbols_node; }; /** - * struct of_overlay - Holds a complete overlay transaction - * @node: List on which we are located - * @count: Count of ovinfo structures - * @ovinfo_tab: Overlay info table (count sized) - * @cset: Changeset to be used - * - * Holds a complete overlay transaction + * struct overlay_changeset + * @ovcs_list: list on which we are located + * @overlay_tree: expanded device tree that contains the fragment nodes + * @count: count of fragment structures + * @fragments: fragment nodes in the overlay expanded device tree + * @symbols_fragment: last element of @fragments[] is the __symbols__ node + * @cset: changeset to apply fragments to live device tree */ -struct of_overlay { +struct overlay_changeset { int id; - struct list_head node; + struct list_head ovcs_list; + struct device_node *overlay_tree; int count; - struct of_overlay_info *ovinfo_tab; + struct fragment *fragments; + bool symbols_fragment; struct of_changeset cset; }; -static int of_overlay_apply_one(struct of_overlay *ov, - struct device_node *target, const struct device_node *overlay, - bool is_symbols_node); +/* flags are sticky - once set, do not reset */ +static int devicetree_state_flags; +#define DTSF_APPLY_FAIL 0x01 +#define DTSF_REVERT_FAIL 0x02 + +/* + * If a changeset apply or revert encounters an error, an attempt will + * be made to undo partial changes, but may fail. If the undo fails + * we do not know the state of the devicetree. + */ +static int devicetree_corrupt(void) +{ + return devicetree_state_flags & + (DTSF_APPLY_FAIL | DTSF_REVERT_FAIL); +} + +static int build_changeset_next_level(struct overlay_changeset *ovcs, + struct device_node *target_node, + const struct device_node *overlay_node); + +/* + * of_resolve_phandles() finds the largest phandle in the live tree. + * of_overlay_apply() may add a larger phandle to the live tree. + * Do not allow race between two overlays being applied simultaneously: + * mutex_lock(&of_overlay_phandle_mutex) + * of_resolve_phandles() + * of_overlay_apply() + * mutex_unlock(&of_overlay_phandle_mutex) + */ +static DEFINE_MUTEX(of_overlay_phandle_mutex); + +void of_overlay_mutex_lock(void) +{ + mutex_lock(&of_overlay_phandle_mutex); +} + +void of_overlay_mutex_unlock(void) +{ + mutex_unlock(&of_overlay_phandle_mutex); +} -static BLOCKING_NOTIFIER_HEAD(of_overlay_chain); + +static LIST_HEAD(ovcs_list); +static DEFINE_IDR(ovcs_idr); + +static BLOCKING_NOTIFIER_HEAD(overlay_notify_chain); int of_overlay_notifier_register(struct notifier_block *nb) { - return blocking_notifier_chain_register(&of_overlay_chain, nb); + return blocking_notifier_chain_register(&overlay_notify_chain, nb); } EXPORT_SYMBOL_GPL(of_overlay_notifier_register); int of_overlay_notifier_unregister(struct notifier_block *nb) { - return blocking_notifier_chain_unregister(&of_overlay_chain, nb); + return blocking_notifier_chain_unregister(&overlay_notify_chain, nb); } EXPORT_SYMBOL_GPL(of_overlay_notifier_unregister); -static int of_overlay_notify(struct of_overlay *ov, - enum of_overlay_notify_action action) +static char *of_overlay_action_name[] = { + "pre-apply", + "post-apply", + "pre-remove", + "post-remove", +}; + +static int overlay_notify(struct overlay_changeset *ovcs, + enum of_overlay_notify_action action) { struct of_overlay_notify_data nd; int i, ret; - for (i = 0; i < ov->count; i++) { - struct of_overlay_info *ovinfo = &ov->ovinfo_tab[i]; + for (i = 0; i < ovcs->count; i++) { + struct fragment *fragment = &ovcs->fragments[i]; - nd.target = ovinfo->target; - nd.overlay = ovinfo->overlay; + nd.target = fragment->target; + nd.overlay = fragment->overlay; - ret = blocking_notifier_call_chain(&of_overlay_chain, + ret = blocking_notifier_call_chain(&overlay_notify_chain, action, &nd); - if (ret) - return notifier_to_errno(ret); + if (ret == NOTIFY_OK || ret == NOTIFY_STOP) + return 0; + if (ret) { + ret = notifier_to_errno(ret); + pr_err("overlay changeset %s notifier error %d, target: %pOF\n", + of_overlay_action_name[action], ret, nd.target); + return ret; + } } return 0; } -static struct property *dup_and_fixup_symbol_prop(struct of_overlay *ov, - const struct property *prop) +/* + * The values of properties in the "/__symbols__" node are paths in + * the ovcs->overlay_tree. When duplicating the properties, the paths + * need to be adjusted to be the correct path for the live device tree. + * + * The paths refer to a node in the subtree of a fragment node's "__overlay__" + * node, for example "/fragment@0/__overlay__/symbol_path_tail", + * where symbol_path_tail can be a single node or it may be a multi-node path. + * + * The duplicated property value will be modified by replacing the + * "/fragment_name/__overlay/" portion of the value with the target + * path from the fragment node. + */ +static struct property *dup_and_fixup_symbol_prop( + struct overlay_changeset *ovcs, const struct property *prop) { - struct of_overlay_info *ovinfo; - struct property *new; - const char *overlay_name; - char *label_path; - char *symbol_path; + struct fragment *fragment; + struct property *new_prop; + struct device_node *fragment_node; + struct device_node *overlay_node; + const char *path; + const char *path_tail; const char *target_path; int k; - int label_path_len; int overlay_name_len; + int path_len; + int path_tail_len; int target_path_len; if (!prop->value) return NULL; - symbol_path = prop->value; - - new = kzalloc(sizeof(*new), GFP_KERNEL); - if (!new) + if (strnlen(prop->value, prop->length) >= prop->length) return NULL; + path = prop->value; + path_len = strlen(path); - for (k = 0; k < ov->count; k++) { - ovinfo = &ov->ovinfo_tab[k]; - overlay_name = ovinfo->overlay->full_name; - overlay_name_len = strlen(overlay_name); - if (!strncasecmp(symbol_path, overlay_name, overlay_name_len)) + if (path_len < 1) + return NULL; + fragment_node = __of_find_node_by_path(ovcs->overlay_tree, path + 1); + overlay_node = __of_find_node_by_path(fragment_node, "__overlay__/"); + of_node_put(fragment_node); + of_node_put(overlay_node); + + for (k = 0; k < ovcs->count; k++) { + fragment = &ovcs->fragments[k]; + if (fragment->overlay == overlay_node) break; } + if (k >= ovcs->count) + return NULL; + + overlay_name_len = snprintf(NULL, 0, "%pOF", fragment->overlay); - if (k >= ov->count) - goto err_free; + if (overlay_name_len > path_len) + return NULL; + path_tail = path + overlay_name_len; + path_tail_len = strlen(path_tail); - target_path = ovinfo->target->full_name; + target_path = kasprintf(GFP_KERNEL, "%pOF", fragment->target); + if (!target_path) + return NULL; target_path_len = strlen(target_path); - label_path = symbol_path + overlay_name_len; - label_path_len = strlen(label_path); + new_prop = kzalloc(sizeof(*new_prop), GFP_KERNEL); + if (!new_prop) + goto err_free_target_path; - new->name = kstrdup(prop->name, GFP_KERNEL); - new->length = target_path_len + label_path_len + 1; - new->value = kzalloc(new->length, GFP_KERNEL); + new_prop->name = kstrdup(prop->name, GFP_KERNEL); + new_prop->length = target_path_len + path_tail_len + 1; + new_prop->value = kzalloc(new_prop->length, GFP_KERNEL); + if (!new_prop->name || !new_prop->value) + goto err_free_new_prop; - if (!new->name || !new->value) - goto err_free; + strcpy(new_prop->value, target_path); + strcpy(new_prop->value + target_path_len, path_tail); - strcpy(new->value, target_path); - strcpy(new->value + target_path_len, label_path); + of_property_set_flag(new_prop, OF_DYNAMIC); - /* mark the property as dynamic */ - of_property_set_flag(new, OF_DYNAMIC); + return new_prop; - return new; +err_free_new_prop: + kfree(new_prop->name); + kfree(new_prop->value); + kfree(new_prop); +err_free_target_path: + kfree(target_path); - err_free: - kfree(new->name); - kfree(new->value); - kfree(new); return NULL; - - } -static int of_overlay_apply_single_property(struct of_overlay *ov, - struct device_node *target, struct property *prop, - bool is_symbols_node) +/** + * add_changeset_property() - add @overlay_prop to overlay changeset + * @ovcs: overlay changeset + * @target_node: where to place @overlay_prop in live tree + * @overlay_prop: property to add or update, from overlay tree + * @is_symbols_prop: 1 if @overlay_prop is from node "/__symbols__" + * + * If @overlay_prop does not already exist in @target_node, add changeset entry + * to add @overlay_prop in @target_node, else add changeset entry to update + * value of @overlay_prop. + * + * Some special properties are not updated (no error returned). + * + * Update of property in symbols node is not allowed. + * + * Returns 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if + * invalid @overlay. + */ +static int add_changeset_property(struct overlay_changeset *ovcs, + struct device_node *target_node, + struct property *overlay_prop, + bool is_symbols_prop) { - struct property *propn = NULL, *tprop; + struct property *new_prop = NULL, *prop; + int ret = 0; - /* NOTE: Multiple changes of single properties not supported */ - tprop = of_find_property(target, prop->name, NULL); + prop = of_find_property(target_node, overlay_prop->name, NULL); - /* special properties are not meant to be updated (silent NOP) */ - if (of_prop_cmp(prop->name, "name") == 0 || - of_prop_cmp(prop->name, "phandle") == 0 || - of_prop_cmp(prop->name, "linux,phandle") == 0) + if (!of_prop_cmp(overlay_prop->name, "name") || + !of_prop_cmp(overlay_prop->name, "phandle") || + !of_prop_cmp(overlay_prop->name, "linux,phandle")) return 0; - if (is_symbols_node) { - /* changing a property in __symbols__ node not allowed */ - if (tprop) + if (is_symbols_prop) { + if (prop) return -EINVAL; - propn = dup_and_fixup_symbol_prop(ov, prop); + new_prop = dup_and_fixup_symbol_prop(ovcs, overlay_prop); } else { - propn = __of_prop_dup(prop, GFP_KERNEL); + new_prop = __of_prop_dup(overlay_prop, GFP_KERNEL); } - if (propn == NULL) + if (!new_prop) return -ENOMEM; - /* not found? add */ - if (tprop == NULL) - return of_changeset_add_property(&ov->cset, target, propn); - - /* found? update */ - return of_changeset_update_property(&ov->cset, target, propn); + if (!prop) + ret = of_changeset_add_property(&ovcs->cset, target_node, + new_prop); + else + ret = of_changeset_update_property(&ovcs->cset, target_node, + new_prop); + + if (ret) { + kfree(new_prop->name); + kfree(new_prop->value); + kfree(new_prop); + } + return ret; } -static int of_overlay_apply_single_device_node(struct of_overlay *ov, - struct device_node *target, struct device_node *child) +/** + * add_changeset_node() - add @node (and children) to overlay changeset + * @ovcs: overlay changeset + * @target_node: where to place @node in live tree + * @node: node from within overlay device tree fragment + * + * If @node does not already exist in @target_node, add changeset entry + * to add @node in @target_node. + * + * If @node already exists in @target_node, and the existing node has + * a phandle, the overlay node is not allowed to have a phandle. + * + * If @node has child nodes, add the children recursively via + * build_changeset_next_level(). + * + * NOTE: Multiple mods of created nodes not supported. + * If more than one fragment contains a node that does not already exist + * in the live tree, then for each fragment of_changeset_attach_node() + * will add a changeset entry to add the node. When the changeset is + * applied, __of_attach_node() will attach the node twice (once for + * each fragment). At this point the device tree will be corrupted. + * + * TODO: add integrity check to ensure that multiple fragments do not + * create the same node. + * + * Returns 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if + * invalid @overlay. + */ +static int add_changeset_node(struct overlay_changeset *ovcs, + struct device_node *target_node, struct device_node *node) { - const char *cname; + const char *node_kbasename; struct device_node *tchild; int ret = 0; - cname = kbasename(child->full_name); - if (cname == NULL) - return -ENOMEM; + node_kbasename = kbasename(node->full_name); - /* NOTE: Multiple mods of created nodes not supported */ - for_each_child_of_node(target, tchild) - if (!of_node_cmp(cname, kbasename(tchild->full_name))) + for_each_child_of_node(target_node, tchild) + if (!of_node_cmp(node_kbasename, kbasename(tchild->full_name))) break; - if (tchild != NULL) { - /* new overlay phandle value conflicts with existing value */ - if (child->phandle) - return -EINVAL; - - /* apply overlay recursively */ - ret = of_overlay_apply_one(ov, tchild, child, 0); - of_node_put(tchild); - } else { - /* create empty tree as a target */ - tchild = __of_node_dup(child, "%pOF/%s", target, cname); + if (!tchild) { + tchild = __of_node_dup(node, "%pOF/%s", + target_node, node_kbasename); if (!tchild) return -ENOMEM; - /* point to parent */ - tchild->parent = target; + tchild->parent = target_node; - ret = of_changeset_attach_node(&ov->cset, tchild); + ret = of_changeset_attach_node(&ovcs->cset, tchild); if (ret) return ret; - ret = of_overlay_apply_one(ov, tchild, child, 0); - if (ret) - return ret; + return build_changeset_next_level(ovcs, tchild, node); } + if (node->phandle && tchild->phandle) + ret = -EINVAL; + else + ret = build_changeset_next_level(ovcs, tchild, node); + of_node_put(tchild); + return ret; } -/* - * Apply a single overlay node recursively. +/** + * build_changeset_next_level() - add level of overlay changeset + * @ovcs: overlay changeset + * @target_node: where to place @overlay_node in live tree + * @overlay_node: node from within an overlay device tree fragment + * + * Add the properties (if any) and nodes (if any) from @overlay_node to the + * @ovcs->cset changeset. If an added node has child nodes, they will + * be added recursively. * - * Note that the in case of an error the target node is left - * in a inconsistent state. Error recovery should be performed - * by using the changeset. + * Do not allow symbols node to have any children. + * + * Returns 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if + * invalid @overlay_node. */ -static int of_overlay_apply_one(struct of_overlay *ov, - struct device_node *target, const struct device_node *overlay, - bool is_symbols_node) +static int build_changeset_next_level(struct overlay_changeset *ovcs, + struct device_node *target_node, + const struct device_node *overlay_node) { struct device_node *child; struct property *prop; int ret; - for_each_property_of_node(overlay, prop) { - ret = of_overlay_apply_single_property(ov, target, prop, - is_symbols_node); + for_each_property_of_node(overlay_node, prop) { + ret = add_changeset_property(ovcs, target_node, prop, 0); if (ret) { - pr_err("Failed to apply prop @%pOF/%s\n", - target, prop->name); + pr_debug("Failed to apply prop @%pOF/%s, err=%d\n", + target_node, prop->name, ret); return ret; } } - /* do not allow symbols node to have any children */ - if (is_symbols_node) - return 0; - - for_each_child_of_node(overlay, child) { - ret = of_overlay_apply_single_device_node(ov, target, child); - if (ret != 0) { - pr_err("Failed to apply single node @%pOF/%s\n", - target, child->name); + for_each_child_of_node(overlay_node, child) { + ret = add_changeset_node(ovcs, target_node, child); + if (ret) { + pr_debug("Failed to apply node @%pOF/%s, err=%d\n", + target_node, child->name, ret); of_node_put(child); return ret; } @@ -279,28 +405,72 @@ static int of_overlay_apply_one(struct of_overlay *ov, return 0; } +/* + * Add the properties from __overlay__ node to the @ovcs->cset changeset. + */ +static int build_changeset_symbols_node(struct overlay_changeset *ovcs, + struct device_node *target_node, + const struct device_node *overlay_symbols_node) +{ + struct property *prop; + int ret; + + for_each_property_of_node(overlay_symbols_node, prop) { + ret = add_changeset_property(ovcs, target_node, prop, 1); + if (ret) { + pr_debug("Failed to apply prop @%pOF/%s, err=%d\n", + target_node, prop->name, ret); + return ret; + } + } + + return 0; +} + /** - * of_overlay_apply() - Apply @count overlays pointed at by @ovinfo_tab - * @ov: Overlay to apply + * build_changeset() - populate overlay changeset in @ovcs from @ovcs->fragments + * @ovcs: Overlay changeset * - * Applies the overlays given, while handling all error conditions - * appropriately. Either the operation succeeds, or if it fails the - * live tree is reverted to the state before the attempt. - * Returns 0, or an error if the overlay attempt failed. + * Create changeset @ovcs->cset to contain the nodes and properties of the + * overlay device tree fragments in @ovcs->fragments[]. If an error occurs, + * any portions of the changeset that were successfully created will remain + * in @ovcs->cset. + * + * Returns 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if + * invalid overlay in @ovcs->fragments[]. */ -static int of_overlay_apply(struct of_overlay *ov) +static int build_changeset(struct overlay_changeset *ovcs) { - int i, err; - - /* first we apply the overlays atomically */ - for (i = 0; i < ov->count; i++) { - struct of_overlay_info *ovinfo = &ov->ovinfo_tab[i]; + struct fragment *fragment; + int fragments_count, i, ret; + + /* + * if there is a symbols fragment in ovcs->fragments[i] it is + * the final element in the array + */ + if (ovcs->symbols_fragment) + fragments_count = ovcs->count - 1; + else + fragments_count = ovcs->count; + + for (i = 0; i < fragments_count; i++) { + fragment = &ovcs->fragments[i]; + + ret = build_changeset_next_level(ovcs, fragment->target, + fragment->overlay); + if (ret) { + pr_debug("apply failed '%pOF'\n", fragment->target); + return ret; + } + } - err = of_overlay_apply_one(ov, ovinfo->target, ovinfo->overlay, - ovinfo->is_symbols_node); - if (err != 0) { - pr_err("apply failed '%pOF'\n", ovinfo->target); - return err; + if (ovcs->symbols_fragment) { + fragment = &ovcs->fragments[ovcs->count - 1]; + ret = build_changeset_symbols_node(ovcs, fragment->target, + fragment->overlay); + if (ret) { + pr_debug("apply failed '%pOF'\n", fragment->target); + return ret; } } @@ -309,10 +479,10 @@ static int of_overlay_apply(struct of_overlay *ov) /* * Find the target node using a number of different strategies - * in order of preference + * in order of preference: * - * "target" property containing the phandle of the target - * "target-path" property containing the path of the target + * 1) "target" property containing the phandle of the target + * 2) "target-path" property containing the path of the target */ static struct device_node *find_target_node(struct device_node *info_node) { @@ -320,14 +490,12 @@ static struct device_node *find_target_node(struct device_node *info_node) u32 val; int ret; - /* first try to go by using the target as a phandle */ ret = of_property_read_u32(info_node, "target", &val); - if (ret == 0) + if (!ret) return of_find_node_by_phandle(val); - /* now try to locate by path */ ret = of_property_read_string(info_node, "target-path", &path); - if (ret == 0) + if (!ret) return of_find_node_by_path(path); pr_err("Failed to find target for node %p (%s)\n", @@ -337,228 +505,290 @@ static struct device_node *find_target_node(struct device_node *info_node) } /** - * of_fill_overlay_info() - Fill an overlay info structure - * @ov Overlay to fill - * @info_node: Device node containing the overlay - * @ovinfo: Pointer to the overlay info structure to fill - * - * Fills an overlay info structure with the overlay information - * from a device node. This device node must have a target property - * which contains a phandle of the overlay target node, and an - * __overlay__ child node which has the overlay contents. - * Both ovinfo->target & ovinfo->overlay have their references taken. - * - * Returns 0 on success, or a negative error value. + * init_overlay_changeset() - initialize overlay changeset from overlay tree + * @ovcs Overlay changeset to build + * @tree: Contains all the overlay fragments and overlay fixup nodes + * + * Initialize @ovcs. Populate @ovcs->fragments with node information from + * the top level of @tree. The relevant top level nodes are the fragment + * nodes and the __symbols__ node. Any other top level node will be ignored. + * + * Returns 0 on success, -ENOMEM if memory allocation failure, -EINVAL if error + * detected in @tree, or -ENOSPC if idr_alloc() error. */ -static int of_fill_overlay_info(struct of_overlay *ov, - struct device_node *info_node, struct of_overlay_info *ovinfo) +static int init_overlay_changeset(struct overlay_changeset *ovcs, + struct device_node *tree) { - ovinfo->overlay = of_get_child_by_name(info_node, "__overlay__"); - if (ovinfo->overlay == NULL) - goto err_fail; + struct device_node *node, *overlay_node; + struct fragment *fragment; + struct fragment *fragments; + int cnt, ret; - ovinfo->target = find_target_node(info_node); - if (ovinfo->target == NULL) - goto err_fail; + /* + * Warn for some issues. Can not return -EINVAL for these until + * of_unittest_apply_overlay() is fixed to pass these checks. + */ + if (!of_node_check_flag(tree, OF_DYNAMIC)) + pr_debug("%s() tree is not dynamic\n", __func__); - return 0; + if (!of_node_check_flag(tree, OF_DETACHED)) + pr_debug("%s() tree is not detached\n", __func__); -err_fail: - of_node_put(ovinfo->target); - of_node_put(ovinfo->overlay); + if (!of_node_is_root(tree)) + pr_debug("%s() tree is not root\n", __func__); - memset(ovinfo, 0, sizeof(*ovinfo)); - return -EINVAL; -} + ovcs->overlay_tree = tree; -/** - * of_build_overlay_info() - Build an overlay info array - * @ov Overlay to build - * @tree: Device node containing all the overlays - * - * Helper function that given a tree containing overlay information, - * allocates and builds an overlay info array containing it, ready - * for use using of_overlay_apply. - * - * Returns 0 on success with the @cntp @ovinfop pointers valid, - * while on error a negative error value is returned. - */ -static int of_build_overlay_info(struct of_overlay *ov, - struct device_node *tree) -{ - struct device_node *node; - struct of_overlay_info *ovinfo; - int cnt, err; + INIT_LIST_HEAD(&ovcs->ovcs_list); + + of_changeset_init(&ovcs->cset); + + ovcs->id = idr_alloc(&ovcs_idr, ovcs, 1, 0, GFP_KERNEL); + if (ovcs->id <= 0) + return ovcs->id; - /* worst case; every child is a node */ cnt = 0; - for_each_child_of_node(tree, node) - cnt++; - if (of_get_child_by_name(tree, "__symbols__")) + /* fragment nodes */ + for_each_child_of_node(tree, node) { + overlay_node = of_get_child_by_name(node, "__overlay__"); + if (overlay_node) { + cnt++; + of_node_put(overlay_node); + } + } + + node = of_get_child_by_name(tree, "__symbols__"); + if (node) { cnt++; + of_node_put(node); + } - ovinfo = kcalloc(cnt, sizeof(*ovinfo), GFP_KERNEL); - if (ovinfo == NULL) - return -ENOMEM; + fragments = kcalloc(cnt, sizeof(*fragments), GFP_KERNEL); + if (!fragments) { + ret = -ENOMEM; + goto err_free_idr; + } cnt = 0; for_each_child_of_node(tree, node) { - err = of_fill_overlay_info(ov, node, &ovinfo[cnt]); - if (err == 0) - cnt++; + fragment = &fragments[cnt]; + fragment->overlay = of_get_child_by_name(node, "__overlay__"); + if (fragment->overlay) { + fragment->target = find_target_node(node); + if (!fragment->target) { + of_node_put(fragment->overlay); + ret = -EINVAL; + goto err_free_fragments; + } else { + cnt++; + } + } } + /* + * if there is a symbols fragment in ovcs->fragments[i] it is + * the final element in the array + */ node = of_get_child_by_name(tree, "__symbols__"); if (node) { - ovinfo[cnt].overlay = node; - ovinfo[cnt].target = of_find_node_by_path("/__symbols__"); - ovinfo[cnt].is_symbols_node = 1; - - if (!ovinfo[cnt].target) { - pr_err("no symbols in root of device tree.\n"); - return -EINVAL; + ovcs->symbols_fragment = 1; + fragment = &fragments[cnt]; + fragment->overlay = node; + fragment->target = of_find_node_by_path("/__symbols__"); + + if (!fragment->target) { + pr_err("symbols in overlay, but not in live tree\n"); + ret = -EINVAL; + goto err_free_fragments; } cnt++; } - /* if nothing filled, return error */ - if (cnt == 0) { - kfree(ovinfo); - return -ENODEV; + if (!cnt) { + ret = -EINVAL; + goto err_free_fragments; } - ov->count = cnt; - ov->ovinfo_tab = ovinfo; + ovcs->count = cnt; + ovcs->fragments = fragments; return 0; + +err_free_fragments: + kfree(fragments); +err_free_idr: + idr_remove(&ovcs_idr, ovcs->id); + + pr_err("%s() failed, ret = %d\n", __func__, ret); + + return ret; } -/** - * of_free_overlay_info() - Free an overlay info array - * @ov Overlay to free the overlay info from - * @ovinfo_tab: Array of overlay_info's to free - * - * Releases the memory of a previously allocated ovinfo array - * by of_build_overlay_info. - * Returns 0, or an error if the arguments are bogus. - */ -static int of_free_overlay_info(struct of_overlay *ov) +static void free_overlay_changeset(struct overlay_changeset *ovcs) { - struct of_overlay_info *ovinfo; int i; - /* do it in reverse */ - for (i = ov->count - 1; i >= 0; i--) { - ovinfo = &ov->ovinfo_tab[i]; + if (!ovcs->cset.entries.next) + return; + of_changeset_destroy(&ovcs->cset); + + if (ovcs->id) + idr_remove(&ovcs_idr, ovcs->id); - of_node_put(ovinfo->target); - of_node_put(ovinfo->overlay); + for (i = 0; i < ovcs->count; i++) { + of_node_put(ovcs->fragments[i].target); + of_node_put(ovcs->fragments[i].overlay); } - kfree(ov->ovinfo_tab); + kfree(ovcs->fragments); - return 0; + kfree(ovcs); } -static LIST_HEAD(ov_list); -static DEFINE_IDR(ov_idr); - /** - * of_overlay_create() - Create and apply an overlay - * @tree: Device node containing all the overlays + * of_overlay_apply() - Create and apply an overlay changeset + * @tree: Expanded overlay device tree + * @ovcs_id: Pointer to overlay changeset id * - * Creates and applies an overlay while also keeping track - * of the overlay in a list. This list can be used to prevent - * illegal overlay removals. + * Creates and applies an overlay changeset. + * + * If an error occurs in a pre-apply notifier, then no changes are made + * to the device tree. + * + + * A non-zero return value will not have created the changeset if error is from: + * - parameter checks + * - building the changeset + * - overlay changset pre-apply notifier * - * Returns the id of the created overlay, or a negative error number + * If an error is returned by an overlay changeset pre-apply notifier + * then no further overlay changeset pre-apply notifier will be called. + * + * A non-zero return value will have created the changeset if error is from: + * - overlay changeset entry notifier + * - overlay changset post-apply notifier + * + * If an error is returned by an overlay changeset post-apply notifier + * then no further overlay changeset post-apply notifier will be called. + * + * If more than one notifier returns an error, then the last notifier + * error to occur is returned. + * + * If an error occurred while applying the overlay changeset, then an + * attempt is made to revert any changes that were made to the + * device tree. If there were any errors during the revert attempt + * then the state of the device tree can not be determined, and any + * following attempt to apply or remove an overlay changeset will be + * refused. + * + * Returns 0 on success, or a negative error number. Overlay changeset + * id is returned to *ovcs_id. */ -int of_overlay_create(struct device_node *tree) + +int of_overlay_apply(struct device_node *tree, int *ovcs_id) { - struct of_overlay *ov; - int err, id; + struct overlay_changeset *ovcs; + int ret = 0, ret_revert, ret_tmp; - /* allocate the overlay structure */ - ov = kzalloc(sizeof(*ov), GFP_KERNEL); - if (ov == NULL) - return -ENOMEM; - ov->id = -1; + *ovcs_id = 0; + + if (devicetree_corrupt()) { + pr_err("devicetree state suspect, refuse to apply overlay\n"); + ret = -EBUSY; + goto out; + } + + ovcs = kzalloc(sizeof(*ovcs), GFP_KERNEL); + if (!ovcs) { + ret = -ENOMEM; + goto out; + } - INIT_LIST_HEAD(&ov->node); + of_overlay_mutex_lock(); - of_changeset_init(&ov->cset); + ret = of_resolve_phandles(tree); + if (ret) + goto err_overlay_unlock; mutex_lock(&of_mutex); - id = idr_alloc(&ov_idr, ov, 0, 0, GFP_KERNEL); - if (id < 0) { - err = id; - goto err_destroy_trans; - } - ov->id = id; + ret = init_overlay_changeset(ovcs, tree); + if (ret) + goto err_free_overlay_changeset; - /* build the overlay info structures */ - err = of_build_overlay_info(ov, tree); - if (err) { - pr_err("of_build_overlay_info() failed for tree@%pOF\n", - tree); - goto err_free_idr; + ret = overlay_notify(ovcs, OF_OVERLAY_PRE_APPLY); + if (ret) { + pr_err("overlay changeset pre-apply notify error %d\n", ret); + goto err_free_overlay_changeset; } - err = of_overlay_notify(ov, OF_OVERLAY_PRE_APPLY); - if (err < 0) { - pr_err("%s: Pre-apply notifier failed (err=%d)\n", - __func__, err); - goto err_free_idr; + ret = build_changeset(ovcs); + if (ret) + goto err_free_overlay_changeset; + + ret_revert = 0; + ret = __of_changeset_apply_entries(&ovcs->cset, &ret_revert); + if (ret) { + if (ret_revert) { + pr_debug("overlay changeset revert error %d\n", + ret_revert); + devicetree_state_flags |= DTSF_APPLY_FAIL; + } + goto err_free_overlay_changeset; + } else { + ret = __of_changeset_apply_notify(&ovcs->cset); + if (ret) + pr_err("overlay changeset entry notify error %d\n", + ret); + /* fall through */ } - /* apply the overlay */ - err = of_overlay_apply(ov); - if (err) - goto err_abort_trans; - - /* apply the changeset */ - err = __of_changeset_apply(&ov->cset); - if (err) - goto err_revert_overlay; + list_add_tail(&ovcs->ovcs_list, &ovcs_list); + *ovcs_id = ovcs->id; + ret_tmp = overlay_notify(ovcs, OF_OVERLAY_POST_APPLY); + if (ret_tmp) { + pr_err("overlay changeset post-apply notify error %d\n", + ret_tmp); + if (!ret) + ret = ret_tmp; + } - /* add to the tail of the overlay list */ - list_add_tail(&ov->node, &ov_list); + mutex_unlock(&of_mutex); + of_overlay_mutex_unlock(); - of_overlay_notify(ov, OF_OVERLAY_POST_APPLY); + goto out; - mutex_unlock(&of_mutex); +err_overlay_unlock: + of_overlay_mutex_unlock(); - return id; +err_free_overlay_changeset: + free_overlay_changeset(ovcs); -err_revert_overlay: -err_abort_trans: - of_free_overlay_info(ov); -err_free_idr: - idr_remove(&ov_idr, ov->id); -err_destroy_trans: - of_changeset_destroy(&ov->cset); - kfree(ov); mutex_unlock(&of_mutex); - return err; +out: + pr_debug("%s() err=%d\n", __func__, ret); + + return ret; } -EXPORT_SYMBOL_GPL(of_overlay_create); +EXPORT_SYMBOL_GPL(of_overlay_apply); -/* check whether the given node, lies under the given tree */ -static int overlay_subtree_check(struct device_node *tree, - struct device_node *dn) +/* + * Find @np in @tree. + * + * Returns 1 if @np is @tree or is contained in @tree, else 0 + */ +static int find_node(struct device_node *tree, struct device_node *np) { struct device_node *child; - /* match? */ - if (tree == dn) + if (tree == np) return 1; for_each_child_of_node(tree, child) { - if (overlay_subtree_check(child, dn)) { + if (find_node(child, np)) { of_node_put(child); return 1; } @@ -567,29 +797,39 @@ static int overlay_subtree_check(struct device_node *tree, return 0; } -/* check whether this overlay is the topmost */ -static int overlay_is_topmost(struct of_overlay *ov, struct device_node *dn) +/* + * Is @remove_ce_node a child of, a parent of, or the same as any + * node in an overlay changeset more topmost than @remove_ovcs? + * + * Returns 1 if found, else 0 + */ +static int node_overlaps_later_cs(struct overlay_changeset *remove_ovcs, + struct device_node *remove_ce_node) { - struct of_overlay *ovt; + struct overlay_changeset *ovcs; struct of_changeset_entry *ce; - list_for_each_entry_reverse(ovt, &ov_list, node) { - /* if we hit ourselves, we're done */ - if (ovt == ov) + list_for_each_entry_reverse(ovcs, &ovcs_list, ovcs_list) { + if (ovcs == remove_ovcs) break; - /* check against each subtree affected by this overlay */ - list_for_each_entry(ce, &ovt->cset.entries, node) { - if (overlay_subtree_check(ce->np, dn)) { - pr_err("%s: #%d clashes #%d @%pOF\n", - __func__, ov->id, ovt->id, dn); - return 0; + list_for_each_entry(ce, &ovcs->cset.entries, node) { + if (find_node(ce->np, remove_ce_node)) { + pr_err("%s: #%d overlaps with #%d @%pOF\n", + __func__, remove_ovcs->id, ovcs->id, + remove_ce_node); + return 1; + } + if (find_node(remove_ce_node, ce->np)) { + pr_err("%s: #%d overlaps with #%d @%pOF\n", + __func__, remove_ovcs->id, ovcs->id, + remove_ce_node); + return 1; } } } - /* overlay is topmost */ - return 1; + return 0; } /* @@ -602,13 +842,13 @@ static int overlay_is_topmost(struct of_overlay *ov, struct device_node *dn) * the one closest to the tail. If another overlay has affected this * device node and is closest to the tail, then removal is not permited. */ -static int overlay_removal_is_ok(struct of_overlay *ov) +static int overlay_removal_is_ok(struct overlay_changeset *remove_ovcs) { - struct of_changeset_entry *ce; + struct of_changeset_entry *remove_ce; - list_for_each_entry(ce, &ov->cset.entries, node) { - if (!overlay_is_topmost(ov, ce->np)) { - pr_err("overlay #%d is not topmost\n", ov->id); + list_for_each_entry(remove_ce, &remove_ovcs->cset.entries, node) { + if (node_overlaps_later_cs(remove_ovcs, remove_ce->np)) { + pr_err("overlay #%d is not topmost\n", remove_ovcs->id); return 0; } } @@ -617,75 +857,130 @@ static int overlay_removal_is_ok(struct of_overlay *ov) } /** - * of_overlay_destroy() - Removes an overlay - * @id: Overlay id number returned by a previous call to of_overlay_create + * of_overlay_remove() - Revert and free an overlay changeset + * @ovcs_id: Pointer to overlay changeset id * - * Removes an overlay if it is permissible. + * Removes an overlay if it is permissible. @ovcs_id was previously returned + * by of_overlay_apply(). * - * Returns 0 on success, or a negative error number + * If an error occurred while attempting to revert the overlay changeset, + * then an attempt is made to re-apply any changeset entry that was + * reverted. If an error occurs on re-apply then the state of the device + * tree can not be determined, and any following attempt to apply or remove + * an overlay changeset will be refused. + * + * A non-zero return value will not revert the changeset if error is from: + * - parameter checks + * - overlay changset pre-remove notifier + * - overlay changeset entry revert + * + * If an error is returned by an overlay changeset pre-remove notifier + * then no further overlay changeset pre-remove notifier will be called. + * + * If more than one notifier returns an error, then the last notifier + * error to occur is returned. + * + * A non-zero return value will revert the changeset if error is from: + * - overlay changeset entry notifier + * - overlay changset post-remove notifier + * + * If an error is returned by an overlay changeset post-remove notifier + * then no further overlay changeset post-remove notifier will be called. + * + * Returns 0 on success, or a negative error number. *ovcs_id is set to + * zero after reverting the changeset, even if a subsequent error occurs. */ -int of_overlay_destroy(int id) +int of_overlay_remove(int *ovcs_id) { - struct of_overlay *ov; - int err; + struct overlay_changeset *ovcs; + int ret, ret_apply, ret_tmp; - mutex_lock(&of_mutex); + ret = 0; - ov = idr_find(&ov_idr, id); - if (ov == NULL) { - err = -ENODEV; - pr_err("destroy: Could not find overlay #%d\n", id); + if (devicetree_corrupt()) { + pr_err("suspect devicetree state, refuse to remove overlay\n"); + ret = -EBUSY; goto out; } - /* check whether the overlay is safe to remove */ - if (!overlay_removal_is_ok(ov)) { - err = -EBUSY; - goto out; + mutex_lock(&of_mutex); + + ovcs = idr_find(&ovcs_idr, *ovcs_id); + if (!ovcs) { + ret = -ENODEV; + pr_err("remove: Could not find overlay #%d\n", *ovcs_id); + goto out_unlock; } - of_overlay_notify(ov, OF_OVERLAY_PRE_REMOVE); - list_del(&ov->node); - __of_changeset_revert(&ov->cset); - of_overlay_notify(ov, OF_OVERLAY_POST_REMOVE); - of_free_overlay_info(ov); - idr_remove(&ov_idr, id); - of_changeset_destroy(&ov->cset); - kfree(ov); + if (!overlay_removal_is_ok(ovcs)) { + ret = -EBUSY; + goto out_unlock; + } - err = 0; + ret = overlay_notify(ovcs, OF_OVERLAY_PRE_REMOVE); + if (ret) { + pr_err("overlay changeset pre-remove notify error %d\n", ret); + goto out_unlock; + } -out: + list_del(&ovcs->ovcs_list); + + ret_apply = 0; + ret = __of_changeset_revert_entries(&ovcs->cset, &ret_apply); + if (ret) { + if (ret_apply) + devicetree_state_flags |= DTSF_REVERT_FAIL; + goto out_unlock; + } else { + ret = __of_changeset_revert_notify(&ovcs->cset); + if (ret) { + pr_err("overlay changeset entry notify error %d\n", + ret); + /* fall through - changeset was reverted */ + } + } + + *ovcs_id = 0; + + ret_tmp = overlay_notify(ovcs, OF_OVERLAY_POST_REMOVE); + if (ret_tmp) { + pr_err("overlay changeset post-remove notify error %d\n", + ret_tmp); + if (!ret) + ret = ret_tmp; + } + + free_overlay_changeset(ovcs); + +out_unlock: mutex_unlock(&of_mutex); - return err; +out: + pr_debug("%s() err=%d\n", __func__, ret); + + return ret; } -EXPORT_SYMBOL_GPL(of_overlay_destroy); +EXPORT_SYMBOL_GPL(of_overlay_remove); /** - * of_overlay_destroy_all() - Removes all overlays from the system + * of_overlay_remove_all() - Reverts and frees all overlay changesets * * Removes all overlays from the system in the correct order. * * Returns 0 on success, or a negative error number */ -int of_overlay_destroy_all(void) +int of_overlay_remove_all(void) { - struct of_overlay *ov, *ovn; - - mutex_lock(&of_mutex); + struct overlay_changeset *ovcs, *ovcs_n; + int ret; /* the tail of list is guaranteed to be safe to remove */ - list_for_each_entry_safe_reverse(ov, ovn, &ov_list, node) { - list_del(&ov->node); - __of_changeset_revert(&ov->cset); - of_free_overlay_info(ov); - idr_remove(&ov_idr, ov->id); - kfree(ov); + list_for_each_entry_safe_reverse(ovcs, ovcs_n, &ovcs_list, ovcs_list) { + ret = of_overlay_remove(&ovcs->id); + if (ret) + return ret; } - mutex_unlock(&of_mutex); - return 0; } -EXPORT_SYMBOL_GPL(of_overlay_destroy_all); +EXPORT_SYMBOL_GPL(of_overlay_remove_all); diff --git a/drivers/of/resolver.c b/drivers/of/resolver.c index 99309cb7d372..cfaeef5f6cb1 100644 --- a/drivers/of/resolver.c +++ b/drivers/of/resolver.c @@ -84,10 +84,9 @@ static int update_usages_of_a_phandle_reference(struct device_node *overlay, int offset, len; int err = 0; - value = kmalloc(prop_fixup->length, GFP_KERNEL); + value = kmemdup(prop_fixup->value, prop_fixup->length, GFP_KERNEL); if (!value) return -ENOMEM; - memcpy(value, prop_fixup->value, prop_fixup->length); /* prop_fixup contains a list of tuples of path:property_name:offset */ end = value + prop_fixup->length; @@ -165,7 +164,6 @@ static int adjust_local_phandle_references(struct device_node *local_fixups, struct property *prop_fix, *prop; int err, i, count; unsigned int off; - phandle phandle; if (!local_fixups) return 0; @@ -195,9 +193,7 @@ static int adjust_local_phandle_references(struct device_node *local_fixups, if ((off + 4) > prop->length) return -EINVAL; - phandle = be32_to_cpu(*(__be32 *)(prop->value + off)); - phandle += phandle_delta; - *(__be32 *)(prop->value + off) = cpu_to_be32(phandle); + be32_add_cpu(prop->value + off, phandle_delta); } } @@ -275,11 +271,18 @@ int of_resolve_phandles(struct device_node *overlay) err = -EINVAL; goto out; } + +#if 0 + Temporarily disable check so that old style overlay unittests + do not fail when of_resolve_phandles() is moved into + of_overlay_apply(). + if (!of_node_check_flag(overlay, OF_DETACHED)) { pr_err("overlay not detached\n"); err = -EINVAL; goto out; } +#endif phandle_delta = live_tree_max_phandle() + 1; adjust_overlay_phandles(overlay, phandle_delta); diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index 29a35cb1da64..273d78c1520b 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -993,10 +993,17 @@ static int __init unittest_data_add(void) pr_warn("%s: No tree to attach; not running tests\n", __func__); return -ENODATA; } - of_node_set_flag(unittest_data_node, OF_DETACHED); + + /* + * This lock normally encloses of_overlay_apply() as well as + * of_resolve_phandles(). + */ + of_overlay_mutex_lock(); + rc = of_resolve_phandles(unittest_data_node); if (rc) { pr_err("%s: Failed to resolve phandles (rc=%i)\n", __func__, rc); + of_overlay_mutex_unlock(); return -EINVAL; } @@ -1006,6 +1013,7 @@ static int __init unittest_data_add(void) __of_attach_node_sysfs(np); of_aliases = of_find_node_by_path("/aliases"); of_chosen = of_find_node_by_path("/chosen"); + of_overlay_mutex_unlock(); return 0; } @@ -1018,6 +1026,9 @@ static int __init unittest_data_add(void) attach_node_and_children(np); np = next; } + + of_overlay_mutex_unlock(); + return 0; } @@ -1218,7 +1229,7 @@ static void of_unittest_untrack_overlay(int id) static void of_unittest_destroy_tracked_overlays(void) { - int id, ret, defers; + int id, ret, defers, ovcs_id; if (overlay_first_id < 0) return; @@ -1231,7 +1242,8 @@ static void of_unittest_destroy_tracked_overlays(void) if (!(overlay_id_bits[BIT_WORD(id)] & BIT_MASK(id))) continue; - ret = of_overlay_destroy(id + overlay_first_id); + ovcs_id = id + overlay_first_id; + ret = of_overlay_remove(&ovcs_id); if (ret == -ENODEV) { pr_warn("%s: no overlay to destroy for #%d\n", __func__, id + overlay_first_id); @@ -1253,7 +1265,7 @@ static int of_unittest_apply_overlay(int overlay_nr, int unittest_nr, int *overlay_id) { struct device_node *np = NULL; - int ret, id = -1; + int ret; np = of_find_node_by_path(overlay_path(overlay_nr)); if (np == NULL) { @@ -1263,23 +1275,20 @@ static int of_unittest_apply_overlay(int overlay_nr, int unittest_nr, goto out; } - ret = of_overlay_create(np); + *overlay_id = 0; + ret = of_overlay_apply(np, overlay_id); if (ret < 0) { unittest(0, "could not create overlay from \"%s\"\n", overlay_path(overlay_nr)); goto out; } - id = ret; - of_unittest_track_overlay(id); + of_unittest_track_overlay(*overlay_id); ret = 0; out: of_node_put(np); - if (overlay_id) - *overlay_id = id; - return ret; } @@ -1287,7 +1296,7 @@ out: static int of_unittest_apply_overlay_check(int overlay_nr, int unittest_nr, int before, int after, enum overlay_type ovtype) { - int ret; + int ret, ovcs_id; /* unittest device must not be in before state */ if (of_unittest_device_exists(unittest_nr, ovtype) != before) { @@ -1298,7 +1307,8 @@ static int of_unittest_apply_overlay_check(int overlay_nr, int unittest_nr, return -EINVAL; } - ret = of_unittest_apply_overlay(overlay_nr, unittest_nr, NULL); + ovcs_id = 0; + ret = of_unittest_apply_overlay(overlay_nr, unittest_nr, &ovcs_id); if (ret != 0) { /* of_unittest_apply_overlay already called unittest() */ return ret; @@ -1321,7 +1331,7 @@ static int of_unittest_apply_revert_overlay_check(int overlay_nr, int unittest_nr, int before, int after, enum overlay_type ovtype) { - int ret, ov_id; + int ret, ovcs_id; /* unittest device must be in before state */ if (of_unittest_device_exists(unittest_nr, ovtype) != before) { @@ -1333,7 +1343,8 @@ static int of_unittest_apply_revert_overlay_check(int overlay_nr, } /* apply the overlay */ - ret = of_unittest_apply_overlay(overlay_nr, unittest_nr, &ov_id); + ovcs_id = 0; + ret = of_unittest_apply_overlay(overlay_nr, unittest_nr, &ovcs_id); if (ret != 0) { /* of_unittest_apply_overlay already called unittest() */ return ret; @@ -1348,7 +1359,7 @@ static int of_unittest_apply_revert_overlay_check(int overlay_nr, return -EINVAL; } - ret = of_overlay_destroy(ov_id); + ret = of_overlay_remove(&ovcs_id); if (ret != 0) { unittest(0, "overlay @\"%s\" failed to be destroyed @\"%s\"\n", overlay_path(overlay_nr), @@ -1450,7 +1461,7 @@ static void of_unittest_overlay_5(void) static void of_unittest_overlay_6(void) { struct device_node *np; - int ret, i, ov_id[2]; + int ret, i, ov_id[2], ovcs_id; int overlay_nr = 6, unittest_nr = 6; int before = 0, after = 1; @@ -1477,13 +1488,14 @@ static void of_unittest_overlay_6(void) return; } - ret = of_overlay_create(np); + ovcs_id = 0; + ret = of_overlay_apply(np, &ovcs_id); if (ret < 0) { unittest(0, "could not create overlay from \"%s\"\n", overlay_path(overlay_nr + i)); return; } - ov_id[i] = ret; + ov_id[i] = ovcs_id; of_unittest_track_overlay(ov_id[i]); } @@ -1501,7 +1513,8 @@ static void of_unittest_overlay_6(void) } for (i = 1; i >= 0; i--) { - ret = of_overlay_destroy(ov_id[i]); + ovcs_id = ov_id[i]; + ret = of_overlay_remove(&ovcs_id); if (ret != 0) { unittest(0, "overlay @\"%s\" failed destroy @\"%s\"\n", overlay_path(overlay_nr + i), @@ -1532,7 +1545,7 @@ static void of_unittest_overlay_6(void) static void of_unittest_overlay_8(void) { struct device_node *np; - int ret, i, ov_id[2]; + int ret, i, ov_id[2], ovcs_id; int overlay_nr = 8, unittest_nr = 8; /* we don't care about device state in this test */ @@ -1547,18 +1560,20 @@ static void of_unittest_overlay_8(void) return; } - ret = of_overlay_create(np); + ovcs_id = 0; + ret = of_overlay_apply(np, &ovcs_id); if (ret < 0) { unittest(0, "could not create overlay from \"%s\"\n", overlay_path(overlay_nr + i)); return; } - ov_id[i] = ret; + ov_id[i] = ovcs_id; of_unittest_track_overlay(ov_id[i]); } /* now try to remove first overlay (it should fail) */ - ret = of_overlay_destroy(ov_id[0]); + ovcs_id = ov_id[0]; + ret = of_overlay_remove(&ovcs_id); if (ret == 0) { unittest(0, "overlay @\"%s\" was destroyed @\"%s\"\n", overlay_path(overlay_nr + 0), @@ -1569,7 +1584,8 @@ static void of_unittest_overlay_8(void) /* removing them in order should work */ for (i = 1; i >= 0; i--) { - ret = of_overlay_destroy(ov_id[i]); + ovcs_id = ov_id[i]; + ret = of_overlay_remove(&ovcs_id); if (ret != 0) { unittest(0, "overlay @\"%s\" not destroyed @\"%s\"\n", overlay_path(overlay_nr + i), @@ -2143,21 +2159,13 @@ static int __init overlay_data_add(int onum) ret = 0; goto out_free_data; } - of_node_set_flag(info->np_overlay, OF_DETACHED); - ret = of_resolve_phandles(info->np_overlay); - if (ret) { - pr_err("resolve ot phandles (ret=%d), %d\n", ret, onum); - goto out_free_np_overlay; - } - - ret = of_overlay_create(info->np_overlay); + info->overlay_id = 0; + ret = of_overlay_apply(info->np_overlay, &info->overlay_id); if (ret < 0) { - pr_err("of_overlay_create() (ret=%d), %d\n", ret, onum); + pr_err("of_overlay_apply() (ret=%d), %d\n", ret, onum); + of_overlay_mutex_unlock(); goto out_free_np_overlay; - } else { - info->overlay_id = ret; - ret = 0; } pr_debug("__dtb_overlay_begin applied, overlay id %d\n", ret); @@ -2206,7 +2214,10 @@ static __init void of_unittest_overlay_high_level(void) * Could not fixup phandles in unittest_unflatten_overlay_base() * because kmalloc() was not yet available. */ + of_overlay_mutex_lock(); of_resolve_phandles(overlay_base_root); + of_overlay_mutex_unlock(); + /* * do not allow overlay_base to duplicate any node already in diff --git a/include/linux/of.h b/include/linux/of.h index cfc34117fc92..ef4c9ff5955a 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -37,9 +37,15 @@ struct property { int length; void *value; struct property *next; +#if defined(CONFIG_OF_DYNAMIC) || defined(CONFIG_SPARC) unsigned long _flags; +#endif +#if defined(CONFIG_OF_PROMTREE) unsigned int unique_id; +#endif +#if defined(CONFIG_OF_KOBJ) struct bin_attribute attr; +#endif }; #if defined(CONFIG_SPARC) @@ -58,7 +64,9 @@ struct device_node { struct device_node *parent; struct device_node *child; struct device_node *sibling; +#if defined(CONFIG_OF_KOBJ) struct kobject kobj; +#endif unsigned long _flags; void *data; #if defined(CONFIG_SPARC) @@ -103,21 +111,17 @@ extern struct kobj_type of_node_ktype; extern const struct fwnode_operations of_fwnode_ops; static inline void of_node_init(struct device_node *node) { +#if defined(CONFIG_OF_KOBJ) kobject_init(&node->kobj, &of_node_ktype); +#endif node->fwnode.ops = &of_fwnode_ops; } -/* true when node is initialized */ -static inline int of_node_is_initialized(struct device_node *node) -{ - return node && node->kobj.state_initialized; -} - -/* true when node is attached (i.e. present on sysfs) */ -static inline int of_node_is_attached(struct device_node *node) -{ - return node && node->kobj.state_in_sysfs; -} +#if defined(CONFIG_OF_KOBJ) +#define of_node_kobj(n) (&(n)->kobj) +#else +#define of_node_kobj(n) NULL +#endif #ifdef CONFIG_OF_DYNAMIC extern struct device_node *of_node_get(struct device_node *node); @@ -203,6 +207,7 @@ static inline void of_node_clear_flag(struct device_node *n, unsigned long flag) clear_bit(flag, &n->_flags); } +#if defined(CONFIG_OF_DYNAMIC) || defined(CONFIG_SPARC) static inline int of_property_check_flag(struct property *p, unsigned long flag) { return test_bit(flag, &p->_flags); @@ -217,6 +222,7 @@ static inline void of_property_clear_flag(struct property *p, unsigned long flag { clear_bit(flag, &p->_flags); } +#endif extern struct device_node *__of_find_all_nodes(struct device_node *prev); extern struct device_node *of_find_all_nodes(struct device_node *prev); @@ -1273,9 +1279,6 @@ static inline int of_reconfig_get_state_change(unsigned long action, } #endif /* CONFIG_OF_DYNAMIC */ -/* CONFIG_OF_RESOLVE api */ -extern int of_resolve_phandles(struct device_node *tree); - /** * of_device_is_system_power_controller - Tells if system-power-controller is found for device_node * @np: Pointer to the given device_node @@ -1292,7 +1295,7 @@ static inline bool of_device_is_system_power_controller(const struct device_node */ enum of_overlay_notify_action { - OF_OVERLAY_PRE_APPLY, + OF_OVERLAY_PRE_APPLY = 0, OF_OVERLAY_POST_APPLY, OF_OVERLAY_PRE_REMOVE, OF_OVERLAY_POST_REMOVE, @@ -1306,26 +1309,26 @@ struct of_overlay_notify_data { #ifdef CONFIG_OF_OVERLAY /* ID based overlays; the API for external users */ -int of_overlay_create(struct device_node *tree); -int of_overlay_destroy(int id); -int of_overlay_destroy_all(void); +int of_overlay_apply(struct device_node *tree, int *ovcs_id); +int of_overlay_remove(int *ovcs_id); +int of_overlay_remove_all(void); int of_overlay_notifier_register(struct notifier_block *nb); int of_overlay_notifier_unregister(struct notifier_block *nb); #else -static inline int of_overlay_create(struct device_node *tree) +static inline int of_overlay_apply(struct device_node *tree, int *ovcs_id) { return -ENOTSUPP; } -static inline int of_overlay_destroy(int id) +static inline int of_overlay_remove(int *ovcs_id) { return -ENOTSUPP; } -static inline int of_overlay_destroy_all(void) +static inline int of_overlay_remove_all(void) { return -ENOTSUPP; } diff --git a/scripts/dtc/checks.c b/scripts/dtc/checks.c index 62ea8f83d4a0..e66138449886 100644 --- a/scripts/dtc/checks.c +++ b/scripts/dtc/checks.c @@ -873,7 +873,7 @@ static void check_simple_bus_reg(struct check *c, struct dt_info *dti, struct no while (size--) reg = (reg << 32) | fdt32_to_cpu(*(cells++)); - snprintf(unit_addr, sizeof(unit_addr), "%llx", (unsigned long long)reg); + 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); @@ -956,6 +956,274 @@ static void check_obsolete_chosen_interrupt_controller(struct check *c, WARNING(obsolete_chosen_interrupt_controller, check_obsolete_chosen_interrupt_controller, NULL); +struct provider { + const char *prop_name; + const char *cell_name; + bool optional; +}; + +static void check_property_phandle_args(struct check *c, + struct dt_info *dti, + struct node *node, + struct property *prop, + const struct provider *provider) +{ + struct node *root = dti->dt; + int cell, cellsize = 0; + + if (prop->val.len % sizeof(cell_t)) { + FAIL(c, dti, "property '%s' size (%d) is invalid, expected multiple of %zu in node %s", + prop->name, prop->val.len, sizeof(cell_t), node->fullpath); + return; + } + + for (cell = 0; cell < prop->val.len / sizeof(cell_t); cell += cellsize + 1) { + struct node *provider_node; + struct property *cellprop; + int phandle; + + phandle = propval_cell_n(prop, cell); + /* + * Some bindings use a cell value 0 or -1 to skip over optional + * entries when each index position has a specific definition. + */ + if (phandle == 0 || phandle == -1) { + /* Give up if this is an overlay with external references */ + if (dti->dtsflags & DTSF_PLUGIN) + break; + + cellsize = 0; + continue; + } + + /* If we have markers, verify the current cell is a phandle */ + if (prop->val.markers) { + struct marker *m = prop->val.markers; + for_each_marker_of_type(m, REF_PHANDLE) { + if (m->offset == (cell * sizeof(cell_t))) + break; + } + if (!m) + FAIL(c, dti, "Property '%s', cell %d is not a phandle reference in %s", + prop->name, cell, node->fullpath); + } + + provider_node = get_node_by_phandle(root, phandle); + if (!provider_node) { + FAIL(c, dti, "Could not get phandle node for %s:%s(cell %d)", + node->fullpath, prop->name, cell); + break; + } + + cellprop = get_property(provider_node, provider->cell_name); + if (cellprop) { + cellsize = propval_cell(cellprop); + } else if (provider->optional) { + cellsize = 0; + } else { + FAIL(c, dti, "Missing property '%s' in node %s or bad phandle (referred from %s:%s[%d])", + provider->cell_name, + provider_node->fullpath, + node->fullpath, prop->name, cell); + break; + } + + if (prop->val.len < ((cell + cellsize + 1) * sizeof(cell_t))) { + FAIL(c, dti, "%s property size (%d) too small for cell size %d in %s", + prop->name, prop->val.len, cellsize, node->fullpath); + } + } +} + +static void check_provider_cells_property(struct check *c, + struct dt_info *dti, + struct node *node) +{ + struct provider *provider = c->data; + struct property *prop; + + prop = get_property(node, provider->prop_name); + if (!prop) + return; + + check_property_phandle_args(c, dti, node, prop, provider); +} +#define WARNING_PROPERTY_PHANDLE_CELLS(nm, propname, cells_name, ...) \ + static struct provider nm##_provider = { (propname), (cells_name), __VA_ARGS__ }; \ + WARNING(nm##_property, check_provider_cells_property, &nm##_provider, &phandle_references); + +WARNING_PROPERTY_PHANDLE_CELLS(clocks, "clocks", "#clock-cells"); +WARNING_PROPERTY_PHANDLE_CELLS(cooling_device, "cooling-device", "#cooling-cells"); +WARNING_PROPERTY_PHANDLE_CELLS(dmas, "dmas", "#dma-cells"); +WARNING_PROPERTY_PHANDLE_CELLS(hwlocks, "hwlocks", "#hwlock-cells"); +WARNING_PROPERTY_PHANDLE_CELLS(interrupts_extended, "interrupts-extended", "#interrupt-cells"); +WARNING_PROPERTY_PHANDLE_CELLS(io_channels, "io-channels", "#io-channel-cells"); +WARNING_PROPERTY_PHANDLE_CELLS(iommus, "iommus", "#iommu-cells"); +WARNING_PROPERTY_PHANDLE_CELLS(mboxes, "mboxes", "#mbox-cells"); +WARNING_PROPERTY_PHANDLE_CELLS(msi_parent, "msi-parent", "#msi-cells", true); +WARNING_PROPERTY_PHANDLE_CELLS(mux_controls, "mux-controls", "#mux-control-cells"); +WARNING_PROPERTY_PHANDLE_CELLS(phys, "phys", "#phy-cells"); +WARNING_PROPERTY_PHANDLE_CELLS(power_domains, "power-domains", "#power-domain-cells"); +WARNING_PROPERTY_PHANDLE_CELLS(pwms, "pwms", "#pwm-cells"); +WARNING_PROPERTY_PHANDLE_CELLS(resets, "resets", "#reset-cells"); +WARNING_PROPERTY_PHANDLE_CELLS(sound_dais, "sound-dais", "#sound-dai-cells"); +WARNING_PROPERTY_PHANDLE_CELLS(thermal_sensors, "thermal-sensors", "#thermal-sensor-cells"); + +static bool prop_is_gpio(struct property *prop) +{ + char *str; + + /* + * *-gpios and *-gpio can appear in property names, + * so skip over any false matches (only one known ATM) + */ + if (strstr(prop->name, "nr-gpio")) + return false; + + str = strrchr(prop->name, '-'); + if (str) + str++; + else + str = prop->name; + if (!(streq(str, "gpios") || streq(str, "gpio"))) + return false; + + return true; +} + +static void check_gpios_property(struct check *c, + struct dt_info *dti, + struct node *node) +{ + struct property *prop; + + /* Skip GPIO hog nodes which have 'gpios' property */ + if (get_property(node, "gpio-hog")) + return; + + for_each_property(node, prop) { + struct provider provider; + + if (!prop_is_gpio(prop)) + continue; + + provider.prop_name = prop->name; + provider.cell_name = "#gpio-cells"; + provider.optional = false; + check_property_phandle_args(c, dti, node, prop, &provider); + } + +} +WARNING(gpios_property, check_gpios_property, NULL, &phandle_references); + +static void check_deprecated_gpio_property(struct check *c, + struct dt_info *dti, + struct node *node) +{ + struct property *prop; + + for_each_property(node, prop) { + char *str; + + if (!prop_is_gpio(prop)) + continue; + + str = strstr(prop->name, "gpio"); + if (!streq(str, "gpio")) + continue; + + FAIL(c, dti, "'[*-]gpio' is deprecated, use '[*-]gpios' instead for %s:%s", + node->fullpath, prop->name); + } + +} +CHECK(deprecated_gpio_property, check_deprecated_gpio_property, NULL); + +static bool node_is_interrupt_provider(struct node *node) +{ + struct property *prop; + + prop = get_property(node, "interrupt-controller"); + if (prop) + return true; + + prop = get_property(node, "interrupt-map"); + if (prop) + return true; + + return false; +} +static void check_interrupts_property(struct check *c, + struct dt_info *dti, + struct node *node) +{ + struct node *root = dti->dt; + struct node *irq_node = NULL, *parent = node; + struct property *irq_prop, *prop = NULL; + int irq_cells, phandle; + + irq_prop = get_property(node, "interrupts"); + if (!irq_prop) + return; + + if (irq_prop->val.len % sizeof(cell_t)) + FAIL(c, dti, "property '%s' size (%d) is invalid, expected multiple of %zu in node %s", + irq_prop->name, irq_prop->val.len, sizeof(cell_t), + node->fullpath); + + while (parent && !prop) { + if (parent != node && node_is_interrupt_provider(parent)) { + irq_node = parent; + break; + } + + prop = get_property(parent, "interrupt-parent"); + if (prop) { + phandle = propval_cell(prop); + /* Give up if this is an overlay with external references */ + if ((phandle == 0 || phandle == -1) && + (dti->dtsflags & DTSF_PLUGIN)) + return; + + irq_node = get_node_by_phandle(root, phandle); + if (!irq_node) { + FAIL(c, dti, "Bad interrupt-parent phandle for %s", + node->fullpath); + return; + } + if (!node_is_interrupt_provider(irq_node)) + FAIL(c, dti, + "Missing interrupt-controller or interrupt-map property in %s", + irq_node->fullpath); + + break; + } + + parent = parent->parent; + } + + if (!irq_node) { + FAIL(c, dti, "Missing interrupt-parent for %s", node->fullpath); + return; + } + + prop = get_property(irq_node, "#interrupt-cells"); + if (!prop) { + FAIL(c, dti, "Missing #interrupt-cells in interrupt-parent %s", + irq_node->fullpath); + return; + } + + irq_cells = propval_cell(prop); + if (irq_prop->val.len % (irq_cells * sizeof(cell_t))) { + FAIL(c, dti, + "interrupts size is (%d), expected multiple of %d in %s", + irq_prop->val.len, (int)(irq_cells * sizeof(cell_t)), + node->fullpath); + } +} +WARNING(interrupts_property, check_interrupts_property, &phandle_references); + static struct check *check_table[] = { &duplicate_node_names, &duplicate_property_names, &node_name_chars, &node_name_format, &property_name_chars, @@ -987,6 +1255,27 @@ static struct check *check_table[] = { &avoid_default_addr_size, &obsolete_chosen_interrupt_controller, + &clocks_property, + &cooling_device_property, + &dmas_property, + &hwlocks_property, + &interrupts_extended_property, + &io_channels_property, + &iommus_property, + &mboxes_property, + &msi_parent_property, + &mux_controls_property, + &phys_property, + &power_domains_property, + &pwms_property, + &resets_property, + &sound_dais_property, + &thermal_sensors_property, + + &deprecated_gpio_property, + &gpios_property, + &interrupts_property, + &always_fail, }; diff --git a/scripts/dtc/dtc-lexer.lex.c_shipped b/scripts/dtc/dtc-lexer.lex.c_shipped index 64c243772398..011bb9632ff2 100644 --- a/scripts/dtc/dtc-lexer.lex.c_shipped +++ b/scripts/dtc/dtc-lexer.lex.c_shipped @@ -1397,7 +1397,7 @@ static int yy_get_next_buffer (void) { char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; char *source = (yytext_ptr); - yy_size_t number_to_move, i; + int number_to_move, i; int ret_val; if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) @@ -1426,7 +1426,7 @@ static int yy_get_next_buffer (void) /* Try to read more data. */ /* First move last chars to start of buffer. */ - number_to_move = (yy_size_t) ((yy_c_buf_p) - (yytext_ptr)) - 1; + number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr) - 1); for ( i = 0; i < number_to_move; ++i ) *(dest++) = *(source++); @@ -1508,7 +1508,7 @@ static int yy_get_next_buffer (void) else ret_val = EOB_ACT_CONTINUE_SCAN; - if ((int) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + if (((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { /* Extend the array by 50%, plus the number we really need. */ int 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 ); @@ -1987,10 +1987,10 @@ YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len ) YY_BUFFER_STATE b; char *buf; yy_size_t n; - yy_size_t i; + int i; /* Get memory for full buffer, including space for trailing EOB's. */ - n = (yy_size_t) _yybytes_len + 2; + n = (yy_size_t) (_yybytes_len + 2); buf = (char *) yyalloc(n ); if ( ! buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); diff --git a/scripts/dtc/dtc-parser.tab.c_shipped b/scripts/dtc/dtc-parser.tab.c_shipped index 0a7a5ed86f04..aea514fa6928 100644 --- a/scripts/dtc/dtc-parser.tab.c_shipped +++ b/scripts/dtc/dtc-parser.tab.c_shipped @@ -448,7 +448,7 @@ union yyalloc /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 30 /* YYNRULES -- Number of rules. */ -#define YYNRULES 84 +#define YYNRULES 85 /* YYNSTATES -- Number of states. */ #define YYNSTATES 149 @@ -499,14 +499,14 @@ static const yytype_uint8 yytranslate[] = 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 + 153, 161, 165, 170, 181, 200, 213, 220, 228, 231, + 238, 242, 246, 250, 258, 262, 266, 270, 274, 290, + 300, 308, 311, 315, 322, 338, 343, 362, 376, 383, + 384, 385, 392, 396, 397, 401, 402, 406, 407, 411, + 412, 416, 417, 421, 422, 426, 427, 428, 432, 433, + 434, 435, 436, 440, 441, 442, 446, 447, 448, 452, + 453, 462, 471, 475, 476, 477, 478, 483, 486, 490, + 498, 501, 505, 513, 517, 521 }; #endif @@ -582,20 +582,20 @@ static const yytype_int8 yypact[] = 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, + 16, 7, 0, 39, 40, 0, 0, 10, 0, 2, + 8, 4, 0, 0, 0, 73, 0, 42, 43, 45, + 47, 49, 51, 53, 55, 58, 65, 68, 72, 0, + 18, 11, 0, 0, 0, 0, 74, 75, 76, 41, 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 + 80, 0, 0, 14, 12, 46, 0, 48, 50, 52, + 54, 56, 57, 61, 62, 60, 59, 63, 64, 66, + 67, 70, 69, 71, 0, 0, 0, 0, 19, 0, + 80, 15, 13, 0, 0, 0, 21, 31, 83, 23, + 85, 0, 82, 81, 44, 22, 84, 0, 0, 17, + 30, 20, 32, 0, 24, 33, 27, 0, 77, 35, + 0, 0, 0, 0, 38, 37, 25, 36, 34, 0, + 78, 79, 26, 0, 29, 0, 0, 0, 28 }; /* YYPGOTO[NTERM-NUM]. */ @@ -678,28 +678,28 @@ static const yytype_uint8 yystos[] = 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 + 53, 54, 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 + 2, 2, 3, 4, 3, 4, 0, 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 }; @@ -1572,17 +1572,26 @@ yyreduce: { struct node *target = get_node_by_ref((yyvsp[-2].node), (yyvsp[-1].labelref)); - if (target) + if (target) { merge_nodes(target, (yyvsp[0].node)); - else - ERROR(&(yylsp[-1]), "Label or path %s not found", (yyvsp[-1].labelref)); + } else { + /* + * We rely on the rule being always: + * versioninfo plugindecl memreserves devicetree + * so $-1 is what we want (plugindecl) + */ + if ((yyvsp[(-1) - (3)].flags) & DTSF_PLUGIN) + add_orphan_node((yyvsp[-2].node), (yyvsp[0].node), (yyvsp[-1].labelref)); + else + ERROR(&(yylsp[-1]), "Label or path %s not found", (yyvsp[-1].labelref)); + } (yyval.node) = (yyvsp[-2].node); } -#line 1582 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1591 "dtc-parser.tab.c" /* yacc.c:1646 */ break; case 15: -#line 192 "dtc-parser.y" /* yacc.c:1646 */ +#line 201 "dtc-parser.y" /* yacc.c:1646 */ { struct node *target = get_node_by_ref((yyvsp[-3].node), (yyvsp[-1].labelref)); @@ -1594,100 +1603,109 @@ yyreduce: (yyval.node) = (yyvsp[-3].node); } -#line 1598 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1607 "dtc-parser.tab.c" /* yacc.c:1646 */ break; case 16: -#line 207 "dtc-parser.y" /* yacc.c:1646 */ +#line 213 "dtc-parser.y" /* yacc.c:1646 */ { - (yyval.node) = build_node((yyvsp[-3].proplist), (yyvsp[-2].nodelist)); + /* build empty node */ + (yyval.node) = name_node(build_node(NULL, NULL), ""); } -#line 1606 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1616 "dtc-parser.tab.c" /* yacc.c:1646 */ break; case 17: -#line 214 "dtc-parser.y" /* yacc.c:1646 */ +#line 221 "dtc-parser.y" /* yacc.c:1646 */ { - (yyval.proplist) = NULL; + (yyval.node) = build_node((yyvsp[-3].proplist), (yyvsp[-2].nodelist)); } -#line 1614 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1624 "dtc-parser.tab.c" /* yacc.c:1646 */ break; case 18: -#line 218 "dtc-parser.y" /* yacc.c:1646 */ +#line 228 "dtc-parser.y" /* yacc.c:1646 */ { - (yyval.proplist) = chain_property((yyvsp[0].prop), (yyvsp[-1].proplist)); + (yyval.proplist) = NULL; } -#line 1622 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1632 "dtc-parser.tab.c" /* yacc.c:1646 */ break; case 19: -#line 225 "dtc-parser.y" /* yacc.c:1646 */ +#line 232 "dtc-parser.y" /* yacc.c:1646 */ { - (yyval.prop) = build_property((yyvsp[-3].propnodename), (yyvsp[-1].data)); + (yyval.proplist) = chain_property((yyvsp[0].prop), (yyvsp[-1].proplist)); } -#line 1630 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1640 "dtc-parser.tab.c" /* yacc.c:1646 */ break; case 20: -#line 229 "dtc-parser.y" /* yacc.c:1646 */ +#line 239 "dtc-parser.y" /* yacc.c:1646 */ { - (yyval.prop) = build_property((yyvsp[-1].propnodename), empty_data); + (yyval.prop) = build_property((yyvsp[-3].propnodename), (yyvsp[-1].data)); } -#line 1638 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1648 "dtc-parser.tab.c" /* yacc.c:1646 */ break; case 21: -#line 233 "dtc-parser.y" /* yacc.c:1646 */ +#line 243 "dtc-parser.y" /* yacc.c:1646 */ { - (yyval.prop) = build_property_delete((yyvsp[-1].propnodename)); + (yyval.prop) = build_property((yyvsp[-1].propnodename), empty_data); } -#line 1646 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1656 "dtc-parser.tab.c" /* yacc.c:1646 */ break; case 22: -#line 237 "dtc-parser.y" /* yacc.c:1646 */ +#line 247 "dtc-parser.y" /* yacc.c:1646 */ + { + (yyval.prop) = build_property_delete((yyvsp[-1].propnodename)); + } +#line 1664 "dtc-parser.tab.c" /* yacc.c:1646 */ + break; + + case 23: +#line 251 "dtc-parser.y" /* yacc.c:1646 */ { add_label(&(yyvsp[0].prop)->labels, (yyvsp[-1].labelref)); (yyval.prop) = (yyvsp[0].prop); } -#line 1655 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1673 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 23: -#line 245 "dtc-parser.y" /* yacc.c:1646 */ + case 24: +#line 259 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.data) = data_merge((yyvsp[-1].data), (yyvsp[0].data)); } -#line 1663 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1681 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 24: -#line 249 "dtc-parser.y" /* yacc.c:1646 */ + case 25: +#line 263 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.data) = data_merge((yyvsp[-2].data), (yyvsp[-1].array).data); } -#line 1671 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1689 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 25: -#line 253 "dtc-parser.y" /* yacc.c:1646 */ + case 26: +#line 267 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.data) = data_merge((yyvsp[-3].data), (yyvsp[-1].data)); } -#line 1679 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1697 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 26: -#line 257 "dtc-parser.y" /* yacc.c:1646 */ + case 27: +#line 271 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.data) = data_add_marker((yyvsp[-1].data), REF_PATH, (yyvsp[0].labelref)); } -#line 1687 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1705 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 27: -#line 261 "dtc-parser.y" /* yacc.c:1646 */ + case 28: +#line 275 "dtc-parser.y" /* yacc.c:1646 */ { FILE *f = srcfile_relative_open((yyvsp[-5].data).val, NULL); struct data d; @@ -1703,11 +1721,11 @@ yyreduce: (yyval.data) = data_merge((yyvsp[-8].data), d); fclose(f); } -#line 1707 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1725 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 28: -#line 277 "dtc-parser.y" /* yacc.c:1646 */ + case 29: +#line 291 "dtc-parser.y" /* yacc.c:1646 */ { FILE *f = srcfile_relative_open((yyvsp[-1].data).val, NULL); struct data d = empty_data; @@ -1717,43 +1735,43 @@ yyreduce: (yyval.data) = data_merge((yyvsp[-4].data), d); fclose(f); } -#line 1721 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1739 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 29: -#line 287 "dtc-parser.y" /* yacc.c:1646 */ + case 30: +#line 301 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.data) = data_add_marker((yyvsp[-1].data), LABEL, (yyvsp[0].labelref)); } -#line 1729 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1747 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 30: -#line 294 "dtc-parser.y" /* yacc.c:1646 */ + case 31: +#line 308 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.data) = empty_data; } -#line 1737 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1755 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 31: -#line 298 "dtc-parser.y" /* yacc.c:1646 */ + case 32: +#line 312 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.data) = (yyvsp[-1].data); } -#line 1745 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1763 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 32: -#line 302 "dtc-parser.y" /* yacc.c:1646 */ + case 33: +#line 316 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.data) = data_add_marker((yyvsp[-1].data), LABEL, (yyvsp[0].labelref)); } -#line 1753 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1771 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 33: -#line 309 "dtc-parser.y" /* yacc.c:1646 */ + case 34: +#line 323 "dtc-parser.y" /* yacc.c:1646 */ { unsigned long long bits; @@ -1769,20 +1787,20 @@ yyreduce: (yyval.array).data = empty_data; (yyval.array).bits = bits; } -#line 1773 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1791 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 34: -#line 325 "dtc-parser.y" /* yacc.c:1646 */ + case 35: +#line 339 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.array).data = empty_data; (yyval.array).bits = 32; } -#line 1782 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1800 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 35: -#line 330 "dtc-parser.y" /* yacc.c:1646 */ + case 36: +#line 344 "dtc-parser.y" /* yacc.c:1646 */ { if ((yyvsp[-1].array).bits < 64) { uint64_t mask = (1ULL << (yyvsp[-1].array).bits) - 1; @@ -1801,11 +1819,11 @@ yyreduce: (yyval.array).data = data_append_integer((yyvsp[-1].array).data, (yyvsp[0].integer), (yyvsp[-1].array).bits); } -#line 1805 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1823 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 36: -#line 349 "dtc-parser.y" /* yacc.c:1646 */ + case 37: +#line 363 "dtc-parser.y" /* yacc.c:1646 */ { uint64_t val = ~0ULL >> (64 - (yyvsp[-1].array).bits); @@ -1819,129 +1837,129 @@ yyreduce: (yyval.array).data = data_append_integer((yyvsp[-1].array).data, val, (yyvsp[-1].array).bits); } -#line 1823 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1841 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 37: -#line 363 "dtc-parser.y" /* yacc.c:1646 */ + case 38: +#line 377 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.array).data = data_add_marker((yyvsp[-1].array).data, LABEL, (yyvsp[0].labelref)); } -#line 1831 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1849 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 40: -#line 372 "dtc-parser.y" /* yacc.c:1646 */ + case 41: +#line 386 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.integer) = (yyvsp[-1].integer); } -#line 1839 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1857 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 43: -#line 383 "dtc-parser.y" /* yacc.c:1646 */ + case 44: +#line 397 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.integer) = (yyvsp[-4].integer) ? (yyvsp[-2].integer) : (yyvsp[0].integer); } -#line 1845 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1863 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 45: -#line 388 "dtc-parser.y" /* yacc.c:1646 */ + case 46: +#line 402 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.integer) = (yyvsp[-2].integer) || (yyvsp[0].integer); } -#line 1851 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1869 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 47: -#line 393 "dtc-parser.y" /* yacc.c:1646 */ + case 48: +#line 407 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.integer) = (yyvsp[-2].integer) && (yyvsp[0].integer); } -#line 1857 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1875 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 49: -#line 398 "dtc-parser.y" /* yacc.c:1646 */ + case 50: +#line 412 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.integer) = (yyvsp[-2].integer) | (yyvsp[0].integer); } -#line 1863 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1881 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 51: -#line 403 "dtc-parser.y" /* yacc.c:1646 */ + case 52: +#line 417 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.integer) = (yyvsp[-2].integer) ^ (yyvsp[0].integer); } -#line 1869 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1887 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 53: -#line 408 "dtc-parser.y" /* yacc.c:1646 */ + case 54: +#line 422 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.integer) = (yyvsp[-2].integer) & (yyvsp[0].integer); } -#line 1875 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1893 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 55: -#line 413 "dtc-parser.y" /* yacc.c:1646 */ + case 56: +#line 427 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.integer) = (yyvsp[-2].integer) == (yyvsp[0].integer); } -#line 1881 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1899 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 56: -#line 414 "dtc-parser.y" /* yacc.c:1646 */ + case 57: +#line 428 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.integer) = (yyvsp[-2].integer) != (yyvsp[0].integer); } -#line 1887 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1905 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 58: -#line 419 "dtc-parser.y" /* yacc.c:1646 */ + case 59: +#line 433 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.integer) = (yyvsp[-2].integer) < (yyvsp[0].integer); } -#line 1893 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1911 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 59: -#line 420 "dtc-parser.y" /* yacc.c:1646 */ + case 60: +#line 434 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.integer) = (yyvsp[-2].integer) > (yyvsp[0].integer); } -#line 1899 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1917 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 60: -#line 421 "dtc-parser.y" /* yacc.c:1646 */ + case 61: +#line 435 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.integer) = (yyvsp[-2].integer) <= (yyvsp[0].integer); } -#line 1905 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1923 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 61: -#line 422 "dtc-parser.y" /* yacc.c:1646 */ + case 62: +#line 436 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.integer) = (yyvsp[-2].integer) >= (yyvsp[0].integer); } -#line 1911 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1929 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 62: -#line 426 "dtc-parser.y" /* yacc.c:1646 */ + case 63: +#line 440 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.integer) = (yyvsp[-2].integer) << (yyvsp[0].integer); } -#line 1917 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1935 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 63: -#line 427 "dtc-parser.y" /* yacc.c:1646 */ + case 64: +#line 441 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.integer) = (yyvsp[-2].integer) >> (yyvsp[0].integer); } -#line 1923 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1941 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 65: -#line 432 "dtc-parser.y" /* yacc.c:1646 */ + case 66: +#line 446 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.integer) = (yyvsp[-2].integer) + (yyvsp[0].integer); } -#line 1929 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1947 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 66: -#line 433 "dtc-parser.y" /* yacc.c:1646 */ + case 67: +#line 447 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.integer) = (yyvsp[-2].integer) - (yyvsp[0].integer); } -#line 1935 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1953 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 68: -#line 438 "dtc-parser.y" /* yacc.c:1646 */ + case 69: +#line 452 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.integer) = (yyvsp[-2].integer) * (yyvsp[0].integer); } -#line 1941 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1959 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 69: -#line 440 "dtc-parser.y" /* yacc.c:1646 */ + case 70: +#line 454 "dtc-parser.y" /* yacc.c:1646 */ { if ((yyvsp[0].integer) != 0) { (yyval.integer) = (yyvsp[-2].integer) / (yyvsp[0].integer); @@ -1950,11 +1968,11 @@ yyreduce: (yyval.integer) = 0; } } -#line 1954 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1972 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 70: -#line 449 "dtc-parser.y" /* yacc.c:1646 */ + case 71: +#line 463 "dtc-parser.y" /* yacc.c:1646 */ { if ((yyvsp[0].integer) != 0) { (yyval.integer) = (yyvsp[-2].integer) % (yyvsp[0].integer); @@ -1963,103 +1981,103 @@ yyreduce: (yyval.integer) = 0; } } -#line 1967 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1985 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 73: -#line 462 "dtc-parser.y" /* yacc.c:1646 */ + case 74: +#line 476 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.integer) = -(yyvsp[0].integer); } -#line 1973 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1991 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 74: -#line 463 "dtc-parser.y" /* yacc.c:1646 */ + case 75: +#line 477 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.integer) = ~(yyvsp[0].integer); } -#line 1979 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1997 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 75: -#line 464 "dtc-parser.y" /* yacc.c:1646 */ + case 76: +#line 478 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.integer) = !(yyvsp[0].integer); } -#line 1985 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 2003 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 76: -#line 469 "dtc-parser.y" /* yacc.c:1646 */ + case 77: +#line 483 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.data) = empty_data; } -#line 1993 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 2011 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 77: -#line 473 "dtc-parser.y" /* yacc.c:1646 */ + case 78: +#line 487 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.data) = data_append_byte((yyvsp[-1].data), (yyvsp[0].byte)); } -#line 2001 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 2019 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 78: -#line 477 "dtc-parser.y" /* yacc.c:1646 */ + case 79: +#line 491 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.data) = data_add_marker((yyvsp[-1].data), LABEL, (yyvsp[0].labelref)); } -#line 2009 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 2027 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 79: -#line 484 "dtc-parser.y" /* yacc.c:1646 */ + case 80: +#line 498 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.nodelist) = NULL; } -#line 2017 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 2035 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 80: -#line 488 "dtc-parser.y" /* yacc.c:1646 */ + case 81: +#line 502 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.nodelist) = chain_node((yyvsp[-1].node), (yyvsp[0].nodelist)); } -#line 2025 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 2043 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 81: -#line 492 "dtc-parser.y" /* yacc.c:1646 */ + case 82: +#line 506 "dtc-parser.y" /* yacc.c:1646 */ { ERROR(&(yylsp[0]), "Properties must precede subnodes"); YYERROR; } -#line 2034 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 2052 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 82: -#line 500 "dtc-parser.y" /* yacc.c:1646 */ + case 83: +#line 514 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.node) = name_node((yyvsp[0].node), (yyvsp[-1].propnodename)); } -#line 2042 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 2060 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 83: -#line 504 "dtc-parser.y" /* yacc.c:1646 */ + case 84: +#line 518 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.node) = name_node(build_node_delete(), (yyvsp[-1].propnodename)); } -#line 2050 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 2068 "dtc-parser.tab.c" /* yacc.c:1646 */ break; - case 84: -#line 508 "dtc-parser.y" /* yacc.c:1646 */ + case 85: +#line 522 "dtc-parser.y" /* yacc.c:1646 */ { add_label(&(yyvsp[0].node)->labels, (yyvsp[-1].labelref)); (yyval.node) = (yyvsp[0].node); } -#line 2059 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 2077 "dtc-parser.tab.c" /* yacc.c:1646 */ break; -#line 2063 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 2081 "dtc-parser.tab.c" /* yacc.c:1646 */ default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -2294,7 +2312,7 @@ yyreturn: #endif return yyresult; } -#line 514 "dtc-parser.y" /* yacc.c:1906 */ +#line 528 "dtc-parser.y" /* yacc.c:1906 */ void yyerror(char const *s) diff --git a/scripts/dtc/dtc-parser.y b/scripts/dtc/dtc-parser.y index ca3f5003427c..affc81a8f9ab 100644 --- a/scripts/dtc/dtc-parser.y +++ b/scripts/dtc/dtc-parser.y @@ -182,10 +182,19 @@ devicetree: { struct node *target = get_node_by_ref($1, $2); - if (target) + if (target) { merge_nodes(target, $3); - else - ERROR(&@2, "Label or path %s not found", $2); + } else { + /* + * We rely on the rule being always: + * versioninfo plugindecl memreserves devicetree + * so $-1 is what we want (plugindecl) + */ + if ($<flags>-1 & DTSF_PLUGIN) + add_orphan_node($1, $3, $2); + else + ERROR(&@2, "Label or path %s not found", $2); + } $$ = $1; } | devicetree DT_DEL_NODE DT_REF ';' @@ -200,6 +209,11 @@ devicetree: $$ = $1; } + | /* empty */ + { + /* build empty node */ + $$ = name_node(build_node(NULL, NULL), ""); + } ; nodedef: diff --git a/scripts/dtc/dtc.c b/scripts/dtc/dtc.c index f5eed9d72c02..5ed873c72ad1 100644 --- a/scripts/dtc/dtc.c +++ b/scripts/dtc/dtc.c @@ -31,7 +31,7 @@ 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_BOTH; /* Use linux,phandle or phandle properties */ +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 */ diff --git a/scripts/dtc/dtc.h b/scripts/dtc/dtc.h index fc24e17510fd..35cf926cc14a 100644 --- a/scripts/dtc/dtc.h +++ b/scripts/dtc/dtc.h @@ -31,6 +31,7 @@ #include <ctype.h> #include <errno.h> #include <unistd.h> +#include <inttypes.h> #include <libfdt_env.h> #include <fdt.h> @@ -202,6 +203,7 @@ 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_orphan_node(struct node *old_node, struct node *new_node, char *ref); void add_property(struct node *node, struct property *prop); void delete_property_by_name(struct node *node, char *name); @@ -215,6 +217,7 @@ void append_to_property(struct node *node, const char *get_unitname(struct node *node); struct property *get_property(struct node *node, const char *propname); cell_t propval_cell(struct property *prop); +cell_t propval_cell_n(struct property *prop, int n); 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, diff --git a/scripts/dtc/libfdt/fdt_addresses.c b/scripts/dtc/libfdt/fdt_addresses.c new file mode 100644 index 000000000000..eff4dbcc729d --- /dev/null +++ b/scripts/dtc/libfdt/fdt_addresses.c @@ -0,0 +1,96 @@ +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2014 David Gibson <david@gibson.dropbear.id.au> + * + * 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_address_cells(const void *fdt, int nodeoffset) +{ + const fdt32_t *ac; + int val; + int len; + + ac = fdt_getprop(fdt, nodeoffset, "#address-cells", &len); + if (!ac) + return 2; + + if (len != sizeof(*ac)) + return -FDT_ERR_BADNCELLS; + + val = fdt32_to_cpu(*ac); + if ((val <= 0) || (val > FDT_MAX_NCELLS)) + return -FDT_ERR_BADNCELLS; + + return val; +} + +int fdt_size_cells(const void *fdt, int nodeoffset) +{ + const fdt32_t *sc; + int val; + int len; + + sc = fdt_getprop(fdt, nodeoffset, "#size-cells", &len); + if (!sc) + return 2; + + if (len != sizeof(*sc)) + return -FDT_ERR_BADNCELLS; + + val = fdt32_to_cpu(*sc); + if ((val < 0) || (val > FDT_MAX_NCELLS)) + return -FDT_ERR_BADNCELLS; + + return val; +} diff --git a/scripts/dtc/libfdt/fdt_empty_tree.c b/scripts/dtc/libfdt/fdt_empty_tree.c index f72d13b1d19c..f2ae9b77c285 100644 --- a/scripts/dtc/libfdt/fdt_empty_tree.c +++ b/scripts/dtc/libfdt/fdt_empty_tree.c @@ -81,4 +81,3 @@ int fdt_create_empty_tree(void *buf, int bufsize) return fdt_open_into(buf, buf, bufsize); } - diff --git a/scripts/dtc/libfdt/fdt_overlay.c b/scripts/dtc/libfdt/fdt_overlay.c new file mode 100644 index 000000000000..bd81241e6658 --- /dev/null +++ b/scripts/dtc/libfdt/fdt_overlay.c @@ -0,0 +1,861 @@ +#include "libfdt_env.h" + +#include <fdt.h> +#include <libfdt.h> + +#include "libfdt_internal.h" + +/** + * overlay_get_target_phandle - retrieves the target phandle of a fragment + * @fdto: pointer to the device tree overlay blob + * @fragment: node offset of the fragment in the overlay + * + * overlay_get_target_phandle() retrieves the target phandle of an + * overlay fragment when that fragment uses a phandle (target + * property) instead of a path (target-path property). + * + * returns: + * the phandle pointed by the target property + * 0, if the phandle was not found + * -1, if the phandle was malformed + */ +static uint32_t overlay_get_target_phandle(const void *fdto, int fragment) +{ + const fdt32_t *val; + int len; + + val = fdt_getprop(fdto, fragment, "target", &len); + if (!val) + return 0; + + if ((len != sizeof(*val)) || (fdt32_to_cpu(*val) == (uint32_t)-1)) + return (uint32_t)-1; + + return fdt32_to_cpu(*val); +} + +/** + * overlay_get_target - retrieves the offset of a fragment's target + * @fdt: Base device tree blob + * @fdto: Device tree overlay blob + * @fragment: node offset of the fragment in the overlay + * @pathp: pointer which receives the path of the target (or NULL) + * + * overlay_get_target() retrieves the target offset in the base + * device tree of a fragment, no matter how the actual targetting is + * done (through a phandle or a path) + * + * returns: + * the targetted node offset in the base device tree + * Negative error code on error + */ +static int overlay_get_target(const void *fdt, const void *fdto, + int fragment, char const **pathp) +{ + uint32_t phandle; + const char *path = NULL; + int path_len = 0, ret; + + /* Try first to do a phandle based lookup */ + phandle = overlay_get_target_phandle(fdto, fragment); + if (phandle == (uint32_t)-1) + return -FDT_ERR_BADPHANDLE; + + /* no phandle, try path */ + if (!phandle) { + /* And then a path based lookup */ + path = fdt_getprop(fdto, fragment, "target-path", &path_len); + if (path) + ret = fdt_path_offset(fdt, path); + else + ret = path_len; + } else + ret = fdt_node_offset_by_phandle(fdt, phandle); + + /* + * If we haven't found either a target or a + * target-path property in a node that contains a + * __overlay__ subnode (we wouldn't be called + * otherwise), consider it a improperly written + * overlay + */ + if (ret < 0 && path_len == -FDT_ERR_NOTFOUND) + ret = -FDT_ERR_BADOVERLAY; + + /* return on error */ + if (ret < 0) + return ret; + + /* return pointer to path (if available) */ + if (pathp) + *pathp = path ? path : NULL; + + return ret; +} + +/** + * overlay_phandle_add_offset - Increases a phandle by an offset + * @fdt: Base device tree blob + * @node: Device tree overlay blob + * @name: Name of the property to modify (phandle or linux,phandle) + * @delta: offset to apply + * + * overlay_phandle_add_offset() increments a node phandle by a given + * offset. + * + * returns: + * 0 on success. + * Negative error code on error + */ +static int overlay_phandle_add_offset(void *fdt, int node, + const char *name, uint32_t delta) +{ + const fdt32_t *val; + uint32_t adj_val; + int len; + + val = fdt_getprop(fdt, node, name, &len); + if (!val) + return len; + + if (len != sizeof(*val)) + return -FDT_ERR_BADPHANDLE; + + adj_val = fdt32_to_cpu(*val); + if ((adj_val + delta) < adj_val) + return -FDT_ERR_NOPHANDLES; + + adj_val += delta; + if (adj_val == (uint32_t)-1) + return -FDT_ERR_NOPHANDLES; + + return fdt_setprop_inplace_u32(fdt, node, name, adj_val); +} + +/** + * overlay_adjust_node_phandles - Offsets the phandles of a node + * @fdto: Device tree overlay blob + * @node: Offset of the node we want to adjust + * @delta: Offset to shift the phandles of + * + * overlay_adjust_node_phandles() adds a constant to all the phandles + * of a given node. This is mainly use as part of the overlay + * application process, when we want to update all the overlay + * phandles to not conflict with the overlays of the base device tree. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_adjust_node_phandles(void *fdto, int node, + uint32_t delta) +{ + int child; + int ret; + + ret = overlay_phandle_add_offset(fdto, node, "phandle", delta); + if (ret && ret != -FDT_ERR_NOTFOUND) + return ret; + + ret = overlay_phandle_add_offset(fdto, node, "linux,phandle", delta); + if (ret && ret != -FDT_ERR_NOTFOUND) + return ret; + + fdt_for_each_subnode(child, fdto, node) { + ret = overlay_adjust_node_phandles(fdto, child, delta); + if (ret) + return ret; + } + + return 0; +} + +/** + * overlay_adjust_local_phandles - Adjust the phandles of a whole overlay + * @fdto: Device tree overlay blob + * @delta: Offset to shift the phandles of + * + * overlay_adjust_local_phandles() adds a constant to all the + * phandles of an overlay. This is mainly use as part of the overlay + * application process, when we want to update all the overlay + * phandles to not conflict with the overlays of the base device tree. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_adjust_local_phandles(void *fdto, uint32_t delta) +{ + /* + * Start adjusting the phandles from the overlay root + */ + return overlay_adjust_node_phandles(fdto, 0, delta); +} + +/** + * overlay_update_local_node_references - Adjust the overlay references + * @fdto: Device tree overlay blob + * @tree_node: Node offset of the node to operate on + * @fixup_node: Node offset of the matching local fixups node + * @delta: Offset to shift the phandles of + * + * overlay_update_local_nodes_references() update the phandles + * pointing to a node within the device tree overlay by adding a + * constant delta. + * + * This is mainly used as part of a device tree application process, + * where you want the device tree overlays phandles to not conflict + * with the ones from the base device tree before merging them. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_update_local_node_references(void *fdto, + int tree_node, + int fixup_node, + uint32_t delta) +{ + int fixup_prop; + int fixup_child; + int ret; + + fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) { + const fdt32_t *fixup_val; + const char *tree_val; + const char *name; + int fixup_len; + int tree_len; + int i; + + fixup_val = fdt_getprop_by_offset(fdto, fixup_prop, + &name, &fixup_len); + if (!fixup_val) + return fixup_len; + + if (fixup_len % sizeof(uint32_t)) + return -FDT_ERR_BADOVERLAY; + + tree_val = fdt_getprop(fdto, tree_node, name, &tree_len); + if (!tree_val) { + if (tree_len == -FDT_ERR_NOTFOUND) + return -FDT_ERR_BADOVERLAY; + + return tree_len; + } + + for (i = 0; i < (fixup_len / sizeof(uint32_t)); i++) { + fdt32_t adj_val; + uint32_t poffset; + + poffset = fdt32_to_cpu(fixup_val[i]); + + /* + * phandles to fixup can be unaligned. + * + * Use a memcpy for the architectures that do + * not support unaligned accesses. + */ + memcpy(&adj_val, tree_val + poffset, sizeof(adj_val)); + + adj_val = cpu_to_fdt32(fdt32_to_cpu(adj_val) + delta); + + ret = fdt_setprop_inplace_namelen_partial(fdto, + tree_node, + name, + strlen(name), + poffset, + &adj_val, + sizeof(adj_val)); + if (ret == -FDT_ERR_NOSPACE) + return -FDT_ERR_BADOVERLAY; + + if (ret) + return ret; + } + } + + fdt_for_each_subnode(fixup_child, fdto, fixup_node) { + const char *fixup_child_name = fdt_get_name(fdto, fixup_child, + NULL); + int tree_child; + + tree_child = fdt_subnode_offset(fdto, tree_node, + fixup_child_name); + if (tree_child == -FDT_ERR_NOTFOUND) + return -FDT_ERR_BADOVERLAY; + if (tree_child < 0) + return tree_child; + + ret = overlay_update_local_node_references(fdto, + tree_child, + fixup_child, + delta); + if (ret) + return ret; + } + + return 0; +} + +/** + * overlay_update_local_references - Adjust the overlay references + * @fdto: Device tree overlay blob + * @delta: Offset to shift the phandles of + * + * overlay_update_local_references() update all the phandles pointing + * to a node within the device tree overlay by adding a constant + * delta to not conflict with the base overlay. + * + * This is mainly used as part of a device tree application process, + * where you want the device tree overlays phandles to not conflict + * with the ones from the base device tree before merging them. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_update_local_references(void *fdto, uint32_t delta) +{ + int fixups; + + fixups = fdt_path_offset(fdto, "/__local_fixups__"); + if (fixups < 0) { + /* There's no local phandles to adjust, bail out */ + if (fixups == -FDT_ERR_NOTFOUND) + return 0; + + return fixups; + } + + /* + * Update our local references from the root of the tree + */ + return overlay_update_local_node_references(fdto, 0, fixups, + delta); +} + +/** + * overlay_fixup_one_phandle - Set an overlay phandle to the base one + * @fdt: Base Device Tree blob + * @fdto: Device tree overlay blob + * @symbols_off: Node offset of the symbols node in the base device tree + * @path: Path to a node holding a phandle in the overlay + * @path_len: number of path characters to consider + * @name: Name of the property holding the phandle reference in the overlay + * @name_len: number of name characters to consider + * @poffset: Offset within the overlay property where the phandle is stored + * @label: Label of the node referenced by the phandle + * + * overlay_fixup_one_phandle() resolves an overlay phandle pointing to + * a node in the base device tree. + * + * This is part of the device tree overlay application process, when + * you want all the phandles in the overlay to point to the actual + * base dt nodes. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_fixup_one_phandle(void *fdt, void *fdto, + int symbols_off, + const char *path, uint32_t path_len, + const char *name, uint32_t name_len, + int poffset, const char *label) +{ + const char *symbol_path; + uint32_t phandle; + fdt32_t phandle_prop; + int symbol_off, fixup_off; + int prop_len; + + if (symbols_off < 0) + return symbols_off; + + symbol_path = fdt_getprop(fdt, symbols_off, label, + &prop_len); + if (!symbol_path) + return prop_len; + + symbol_off = fdt_path_offset(fdt, symbol_path); + if (symbol_off < 0) + return symbol_off; + + phandle = fdt_get_phandle(fdt, symbol_off); + if (!phandle) + return -FDT_ERR_NOTFOUND; + + fixup_off = fdt_path_offset_namelen(fdto, path, path_len); + if (fixup_off == -FDT_ERR_NOTFOUND) + return -FDT_ERR_BADOVERLAY; + if (fixup_off < 0) + return fixup_off; + + phandle_prop = cpu_to_fdt32(phandle); + return fdt_setprop_inplace_namelen_partial(fdto, fixup_off, + name, name_len, poffset, + &phandle_prop, + sizeof(phandle_prop)); +}; + +/** + * overlay_fixup_phandle - Set an overlay phandle to the base one + * @fdt: Base Device Tree blob + * @fdto: Device tree overlay blob + * @symbols_off: Node offset of the symbols node in the base device tree + * @property: Property offset in the overlay holding the list of fixups + * + * overlay_fixup_phandle() resolves all the overlay phandles pointed + * to in a __fixups__ property, and updates them to match the phandles + * in use in the base device tree. + * + * This is part of the device tree overlay application process, when + * you want all the phandles in the overlay to point to the actual + * base dt nodes. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off, + int property) +{ + const char *value; + const char *label; + int len; + + value = fdt_getprop_by_offset(fdto, property, + &label, &len); + if (!value) { + if (len == -FDT_ERR_NOTFOUND) + return -FDT_ERR_INTERNAL; + + return len; + } + + do { + const char *path, *name, *fixup_end; + const char *fixup_str = value; + uint32_t path_len, name_len; + uint32_t fixup_len; + char *sep, *endptr; + int poffset, ret; + + fixup_end = memchr(value, '\0', len); + if (!fixup_end) + return -FDT_ERR_BADOVERLAY; + fixup_len = fixup_end - fixup_str; + + len -= fixup_len + 1; + value += fixup_len + 1; + + path = fixup_str; + sep = memchr(fixup_str, ':', fixup_len); + if (!sep || *sep != ':') + return -FDT_ERR_BADOVERLAY; + + path_len = sep - path; + if (path_len == (fixup_len - 1)) + return -FDT_ERR_BADOVERLAY; + + fixup_len -= path_len + 1; + name = sep + 1; + sep = memchr(name, ':', fixup_len); + if (!sep || *sep != ':') + return -FDT_ERR_BADOVERLAY; + + name_len = sep - name; + if (!name_len) + return -FDT_ERR_BADOVERLAY; + + poffset = strtoul(sep + 1, &endptr, 10); + if ((*endptr != '\0') || (endptr <= (sep + 1))) + return -FDT_ERR_BADOVERLAY; + + ret = overlay_fixup_one_phandle(fdt, fdto, symbols_off, + path, path_len, name, name_len, + poffset, label); + if (ret) + return ret; + } while (len > 0); + + return 0; +} + +/** + * overlay_fixup_phandles - Resolve the overlay phandles to the base + * device tree + * @fdt: Base Device Tree blob + * @fdto: Device tree overlay blob + * + * overlay_fixup_phandles() resolves all the overlay phandles pointing + * to nodes in the base device tree. + * + * This is one of the steps of the device tree overlay application + * process, when you want all the phandles in the overlay to point to + * the actual base dt nodes. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_fixup_phandles(void *fdt, void *fdto) +{ + int fixups_off, symbols_off; + int property; + + /* We can have overlays without any fixups */ + fixups_off = fdt_path_offset(fdto, "/__fixups__"); + if (fixups_off == -FDT_ERR_NOTFOUND) + return 0; /* nothing to do */ + if (fixups_off < 0) + return fixups_off; + + /* And base DTs without symbols */ + symbols_off = fdt_path_offset(fdt, "/__symbols__"); + if ((symbols_off < 0 && (symbols_off != -FDT_ERR_NOTFOUND))) + return symbols_off; + + fdt_for_each_property_offset(property, fdto, fixups_off) { + int ret; + + ret = overlay_fixup_phandle(fdt, fdto, symbols_off, property); + if (ret) + return ret; + } + + return 0; +} + +/** + * overlay_apply_node - Merges a node into the base device tree + * @fdt: Base Device Tree blob + * @target: Node offset in the base device tree to apply the fragment to + * @fdto: Device tree overlay blob + * @node: Node offset in the overlay holding the changes to merge + * + * overlay_apply_node() merges a node into a target base device tree + * node pointed. + * + * This is part of the final step in the device tree overlay + * application process, when all the phandles have been adjusted and + * resolved and you just have to merge overlay into the base device + * tree. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_apply_node(void *fdt, int target, + void *fdto, int node) +{ + int property; + int subnode; + + fdt_for_each_property_offset(property, fdto, node) { + const char *name; + const void *prop; + int prop_len; + int ret; + + prop = fdt_getprop_by_offset(fdto, property, &name, + &prop_len); + if (prop_len == -FDT_ERR_NOTFOUND) + return -FDT_ERR_INTERNAL; + if (prop_len < 0) + return prop_len; + + ret = fdt_setprop(fdt, target, name, prop, prop_len); + if (ret) + return ret; + } + + fdt_for_each_subnode(subnode, fdto, node) { + const char *name = fdt_get_name(fdto, subnode, NULL); + int nnode; + int ret; + + nnode = fdt_add_subnode(fdt, target, name); + if (nnode == -FDT_ERR_EXISTS) { + nnode = fdt_subnode_offset(fdt, target, name); + if (nnode == -FDT_ERR_NOTFOUND) + return -FDT_ERR_INTERNAL; + } + + if (nnode < 0) + return nnode; + + ret = overlay_apply_node(fdt, nnode, fdto, subnode); + if (ret) + return ret; + } + + return 0; +} + +/** + * overlay_merge - Merge an overlay into its base device tree + * @fdt: Base Device Tree blob + * @fdto: Device tree overlay blob + * + * overlay_merge() merges an overlay into its base device tree. + * + * This is the next to last step in the device tree overlay application + * process, when all the phandles have been adjusted and resolved and + * you just have to merge overlay into the base device tree. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_merge(void *fdt, void *fdto) +{ + int fragment; + + fdt_for_each_subnode(fragment, fdto, 0) { + int overlay; + int target; + int ret; + + /* + * Each fragments will have an __overlay__ node. If + * they don't, it's not supposed to be merged + */ + overlay = fdt_subnode_offset(fdto, fragment, "__overlay__"); + if (overlay == -FDT_ERR_NOTFOUND) + continue; + + if (overlay < 0) + return overlay; + + target = overlay_get_target(fdt, fdto, fragment, NULL); + if (target < 0) + return target; + + ret = overlay_apply_node(fdt, target, fdto, overlay); + if (ret) + return ret; + } + + return 0; +} + +static int get_path_len(const void *fdt, int nodeoffset) +{ + int len = 0, namelen; + const char *name; + + FDT_CHECK_HEADER(fdt); + + for (;;) { + name = fdt_get_name(fdt, nodeoffset, &namelen); + if (!name) + return namelen; + + /* root? we're done */ + if (namelen == 0) + break; + + nodeoffset = fdt_parent_offset(fdt, nodeoffset); + if (nodeoffset < 0) + return nodeoffset; + len += namelen + 1; + } + + /* in case of root pretend it's "/" */ + if (len == 0) + len++; + return len; +} + +/** + * overlay_symbol_update - Update the symbols of base tree after a merge + * @fdt: Base Device Tree blob + * @fdto: Device tree overlay blob + * + * overlay_symbol_update() updates the symbols of the base tree with the + * symbols of the applied overlay + * + * This is the last step in the device tree overlay application + * process, allowing the reference of overlay symbols by subsequent + * overlay operations. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_symbol_update(void *fdt, void *fdto) +{ + int root_sym, ov_sym, prop, path_len, fragment, target; + int len, frag_name_len, ret, rel_path_len; + const char *s, *e; + const char *path; + const char *name; + const char *frag_name; + const char *rel_path; + const char *target_path; + char *buf; + void *p; + + ov_sym = fdt_subnode_offset(fdto, 0, "__symbols__"); + + /* if no overlay symbols exist no problem */ + if (ov_sym < 0) + return 0; + + root_sym = fdt_subnode_offset(fdt, 0, "__symbols__"); + + /* it no root symbols exist we should create them */ + if (root_sym == -FDT_ERR_NOTFOUND) + root_sym = fdt_add_subnode(fdt, 0, "__symbols__"); + + /* any error is fatal now */ + if (root_sym < 0) + return root_sym; + + /* iterate over each overlay symbol */ + fdt_for_each_property_offset(prop, fdto, ov_sym) { + path = fdt_getprop_by_offset(fdto, prop, &name, &path_len); + if (!path) + return path_len; + + /* verify it's a string property (terminated by a single \0) */ + if (path_len < 1 || memchr(path, '\0', path_len) != &path[path_len - 1]) + return -FDT_ERR_BADVALUE; + + /* keep end marker to avoid strlen() */ + e = path + path_len; + + /* format: /<fragment-name>/__overlay__/<relative-subnode-path> */ + + if (*path != '/') + return -FDT_ERR_BADVALUE; + + /* get fragment name first */ + s = strchr(path + 1, '/'); + if (!s) + return -FDT_ERR_BADOVERLAY; + + frag_name = path + 1; + frag_name_len = s - path - 1; + + /* verify format; safe since "s" lies in \0 terminated prop */ + len = sizeof("/__overlay__/") - 1; + if ((e - s) < len || memcmp(s, "/__overlay__/", len)) + return -FDT_ERR_BADOVERLAY; + + rel_path = s + len; + rel_path_len = e - rel_path; + + /* find the fragment index in which the symbol lies */ + ret = fdt_subnode_offset_namelen(fdto, 0, frag_name, + frag_name_len); + /* not found? */ + if (ret < 0) + return -FDT_ERR_BADOVERLAY; + fragment = ret; + + /* an __overlay__ subnode must exist */ + ret = fdt_subnode_offset(fdto, fragment, "__overlay__"); + if (ret < 0) + return -FDT_ERR_BADOVERLAY; + + /* get the target of the fragment */ + ret = overlay_get_target(fdt, fdto, fragment, &target_path); + if (ret < 0) + return ret; + target = ret; + + /* if we have a target path use */ + if (!target_path) { + ret = get_path_len(fdt, target); + if (ret < 0) + return ret; + len = ret; + } else { + len = strlen(target_path); + } + + ret = fdt_setprop_placeholder(fdt, root_sym, name, + len + (len > 1) + rel_path_len + 1, &p); + if (ret < 0) + return ret; + + if (!target_path) { + /* again in case setprop_placeholder changed it */ + ret = overlay_get_target(fdt, fdto, fragment, &target_path); + if (ret < 0) + return ret; + target = ret; + } + + buf = p; + if (len > 1) { /* target is not root */ + if (!target_path) { + ret = fdt_get_path(fdt, target, buf, len + 1); + if (ret < 0) + return ret; + } else + memcpy(buf, target_path, len + 1); + + } else + len--; + + buf[len] = '/'; + memcpy(buf + len + 1, rel_path, rel_path_len); + buf[len + 1 + rel_path_len] = '\0'; + } + + return 0; +} + +int fdt_overlay_apply(void *fdt, void *fdto) +{ + uint32_t delta = fdt_get_max_phandle(fdt); + int ret; + + FDT_CHECK_HEADER(fdt); + FDT_CHECK_HEADER(fdto); + + ret = overlay_adjust_local_phandles(fdto, delta); + if (ret) + goto err; + + ret = overlay_update_local_references(fdto, delta); + if (ret) + goto err; + + ret = overlay_fixup_phandles(fdt, fdto); + if (ret) + goto err; + + ret = overlay_merge(fdt, fdto); + if (ret) + goto err; + + ret = overlay_symbol_update(fdt, fdto); + if (ret) + goto err; + + /* + * The overlay has been damaged, erase its magic. + */ + fdt_set_magic(fdto, ~0); + + return 0; + +err: + /* + * The overlay might have been damaged, erase its magic. + */ + fdt_set_magic(fdto, ~0); + + /* + * The base device tree might have been damaged, erase its + * magic. + */ + fdt_set_magic(fdt, ~0); + + return ret; +} diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c index 3d00d2eee0e3..08de2cce674d 100644 --- a/scripts/dtc/libfdt/fdt_ro.c +++ b/scripts/dtc/libfdt/fdt_ro.c @@ -60,7 +60,7 @@ static int _fdt_nodename_eq(const void *fdt, int offset, { const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1); - if (! p) + if (!p) /* short match */ return 0; @@ -327,7 +327,7 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, const struct fdt_property *prop; prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp); - if (! prop) + if (!prop) return NULL; return prop->data; diff --git a/scripts/dtc/libfdt/fdt_rw.c b/scripts/dtc/libfdt/fdt_rw.c index 3fd5847377c9..5c3a2bb0bc6b 100644 --- a/scripts/dtc/libfdt/fdt_rw.c +++ b/scripts/dtc/libfdt/fdt_rw.c @@ -207,7 +207,7 @@ static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name, int err; *prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); - if (! (*prop)) + if (!*prop) return oldlen; if ((err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen), @@ -269,8 +269,8 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name) return 0; } -int fdt_setprop(void *fdt, int nodeoffset, const char *name, - const void *val, int len) +int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name, + int len, void **prop_data) { struct fdt_property *prop; int err; @@ -283,8 +283,22 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name, 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); + memcpy(prop_data, val, len); return 0; } @@ -323,7 +337,7 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name) FDT_RW_CHECK_HEADER(fdt); prop = fdt_get_property_w(fdt, nodeoffset, name, &len); - if (! prop) + if (!prop) return len; proplen = sizeof(*prop) + FDT_TAGALIGN(len); diff --git a/scripts/dtc/libfdt/fdt_sw.c b/scripts/dtc/libfdt/fdt_sw.c index 6a804859fd0c..2bd15e7aef87 100644 --- a/scripts/dtc/libfdt/fdt_sw.c +++ b/scripts/dtc/libfdt/fdt_sw.c @@ -220,7 +220,7 @@ static int _fdt_find_add_string(void *fdt, const char *s) return offset; } -int fdt_property(void *fdt, const char *name, const void *val, int len) +int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp) { struct fdt_property *prop; int nameoff; @@ -238,7 +238,19 @@ int fdt_property(void *fdt, const char *name, const void *val, int len) prop->tag = cpu_to_fdt32(FDT_PROP); prop->nameoff = cpu_to_fdt32(nameoff); prop->len = cpu_to_fdt32(len); - memcpy(prop->data, val, 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; } diff --git a/scripts/dtc/libfdt/fdt_wip.c b/scripts/dtc/libfdt/fdt_wip.c index 6aaab399929c..5e859198622b 100644 --- a/scripts/dtc/libfdt/fdt_wip.c +++ b/scripts/dtc/libfdt/fdt_wip.c @@ -82,7 +82,7 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, int proplen; propval = fdt_getprop(fdt, nodeoffset, name, &proplen); - if (! propval) + if (!propval) return proplen; if (proplen != len) @@ -107,7 +107,7 @@ int fdt_nop_property(void *fdt, int nodeoffset, const char *name) int len; prop = fdt_get_property_w(fdt, nodeoffset, name, &len); - if (! prop) + if (!prop) return len; _fdt_nop_region(prop, len + sizeof(*prop)); diff --git a/scripts/dtc/libfdt/libfdt.h b/scripts/dtc/libfdt/libfdt.h index ba86caa73d01..7f83023ee109 100644 --- a/scripts/dtc/libfdt/libfdt.h +++ b/scripts/dtc/libfdt/libfdt.h @@ -1314,6 +1314,22 @@ 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); @@ -1433,6 +1449,37 @@ 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 diff --git a/scripts/dtc/livetree.c b/scripts/dtc/livetree.c index 3673de07e4e5..6846ad2fd6d2 100644 --- a/scripts/dtc/livetree.c +++ b/scripts/dtc/livetree.c @@ -216,6 +216,28 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node) return old_node; } +void add_orphan_node(struct node *dt, struct node *new_node, char *ref) +{ + static unsigned int next_orphan_fragment = 0; + struct node *node; + struct property *p; + struct data d = empty_data; + char *name; + + d = data_add_marker(d, REF_PHANDLE, ref); + d = data_append_integer(d, 0xffffffff, 32); + + p = build_property("target", d); + + xasprintf(&name, "fragment@%u", + next_orphan_fragment++); + name_node(new_node, "__overlay__"); + node = build_node(p, new_node); + name_node(node, name); + + add_child(dt, node); +} + struct node *chain_node(struct node *first, struct node *list) { assert(first->next_sibling == NULL); @@ -396,6 +418,12 @@ cell_t propval_cell(struct property *prop) return fdt32_to_cpu(*((fdt32_t *)prop->val.val)); } +cell_t propval_cell_n(struct property *prop, int n) +{ + assert(prop->val.len / sizeof(cell_t) >= n); + return fdt32_to_cpu(*((fdt32_t *)prop->val.val + n)); +} + struct property *get_property_by_label(struct node *tree, const char *label, struct node **node) { @@ -478,7 +506,8 @@ struct node *get_node_by_path(struct node *tree, const char *path) p = strchr(path, '/'); for_each_child(tree, child) { - if (p && strneq(path, child->name, p-path)) + 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; diff --git a/scripts/dtc/update-dtc-source.sh b/scripts/dtc/update-dtc-source.sh index b8ebcc6722d2..f3e5c596050a 100755 --- a/scripts/dtc/update-dtc-source.sh +++ b/scripts/dtc/update-dtc-source.sh @@ -34,7 +34,9 @@ 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" +LIBFDT_SOURCE="Makefile.libfdt fdt.c fdt.h fdt_addresses.c fdt_empty_tree.c \ + fdt_overlay.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/' diff --git a/scripts/dtc/version_gen.h b/scripts/dtc/version_gen.h index 1229e07b4912..6a4e84798966 100644 --- a/scripts/dtc/version_gen.h +++ b/scripts/dtc/version_gen.h @@ -1 +1 @@ -#define DTC_VERSION "DTC 1.4.4-g756ffc4f" +#define DTC_VERSION "DTC 1.4.5-gc1e55a55" |