提交 37cb8e1f 编写于 作者: L Linus Torvalds

Merge tag 'devicetree-for-4.15' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux

Pull DeviceTree updates from Rob Herring:
 "A bigger diffstat than usual with the kbuild changes and a tree wide
  fix in the binding documentation.

  Summary:

   - kbuild cleanups and improvements for dtbs

   - Code clean-up of overlay code and fixing for some long standing
     memory leak and race condition in applying overlays

   - Improvements to DT memory usage making sysfs/kobjects optional and
     skipping unflattening of disabled nodes. This is part of kernel
     tinification efforts.

   - Final piece of removing storing the full path for every DT node.
     The prerequisite conversion of printk's to use device_node format
     specifier happened in 4.14.

   - Sync with current upstream dtc. This brings additional checks to
     dtb compiling.

   - Binding doc tree wide removal of leading 0s from examples

   - RTC binding documentation adding missing devices and some
     consolidation of duplicated bindings

   - Vendor prefix documentation for nutsboard, Silicon Storage
     Technology, shimafuji, Tecon Microprocessor Technologies, DH
     electronics GmbH, Opal Kelly, and Next Thing"

* tag 'devicetree-for-4.15' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux: (55 commits)
  dt-bindings: usb: add #phy-cells to usb-nop-xceiv
  dt-bindings: Remove leading zeros from bindings notation
  kbuild: handle dtb-y and CONFIG_OF_ALL_DTBS natively in Makefile.lib
  MIPS: dts: remove bogus bcm96358nb4ser.dtb from dtb-y entry
  kbuild: clean up *.dtb and *.dtb.S patterns from top-level Makefile
  .gitignore: move *.dtb and *.dtb.S patterns to the top-level .gitignore
  .gitignore: sort normal pattern rules alphabetically
  dt-bindings: add vendor prefix for Next Thing Co.
  scripts/dtc: Update to upstream version v1.4.5-6-gc1e55a5513e9
  of: dynamic: fix memory leak related to properties of __of_node_dup
  of: overlay: make pr_err() string unique
  of: overlay: pr_err from return NOTIFY_OK to overlay apply/remove
  of: overlay: remove unneeded check for NULL kbasename()
  of: overlay: remove a dependency on device node full_name
  of: overlay: simplify applying symbols from an overlay
  of: overlay: avoid race condition between applying multiple overlays
  of: overlay: loosen overly strict phandle clash check
  of: overlay: expand check of whether overlay changeset can be removed
  of: overlay: detect cases where device tree may become corrupt
  of: overlay: minor restructuring
  ...
...@@ -7,38 +7,40 @@ ...@@ -7,38 +7,40 @@
# command after changing this file, to see if there are # command after changing this file, to see if there are
# any tracked files which get ignored after the change. # any tracked files which get ignored after the change.
# #
# Normal rules # Normal rules (sorted alphabetically)
# #
.* .*
*.a
*.bin
*.bz2
*.c.[012]*.*
*.dtb
*.dtb.S
*.dwo
*.elf
*.gcno
*.gz
*.i
*.ko
*.ll
*.lst
*.lz4
*.lzma
*.lzo
*.mod.c
*.o *.o
*.o.* *.o.*
*.a *.order
*.patch
*.s *.s
*.ko
*.so *.so
*.so.dbg *.so.dbg
*.mod.c *.su
*.i
*.lst
*.symtypes *.symtypes
*.order
*.elf
*.bin
*.tar *.tar
*.gz
*.bz2
*.lzma
*.xz *.xz
*.lz4
*.lzo
*.patch
*.gcno
*.ll
modules.builtin
Module.symvers Module.symvers
*.dwo modules.builtin
*.su
*.c.[012]*.*
# #
# Top-level generic files # Top-level generic files
......
...@@ -62,7 +62,7 @@ pmu_system_controller: system-controller@10040000 { ...@@ -62,7 +62,7 @@ pmu_system_controller: system-controller@10040000 {
Example of clock consumer : Example of clock consumer :
usb3503: usb3503@08 { usb3503: usb3503@8 {
/* ... */ /* ... */
clock-names = "refclk"; clock-names = "refclk";
clocks = <&pmu_system_controller 0>; clocks = <&pmu_system_controller 0>;
......
...@@ -71,7 +71,7 @@ Optional nodes: ...@@ -71,7 +71,7 @@ Optional nodes:
- compatible: only "samsung,secure-firmware" is currently supported - compatible: only "samsung,secure-firmware" is currently supported
- reg: address of non-secure SYSRAM used for communication with firmware - reg: address of non-secure SYSRAM used for communication with firmware
firmware@0203F000 { firmware@203F000 {
compatible = "samsung,secure-firmware"; compatible = "samsung,secure-firmware";
reg = <0x0203F000 0x1000>; reg = <0x0203F000 0x1000>;
}; };
...@@ -33,7 +33,7 @@ Required properties: ...@@ -33,7 +33,7 @@ Required properties:
property with the highest frequency property with the highest frequency
Example: Example:
v2m_sysctl: sysctl@020000 { v2m_sysctl: sysctl@20000 {
compatible = "arm,sp810", "arm,primecell"; compatible = "arm,sp810", "arm,primecell";
reg = <0x020000 0x1000>; reg = <0x020000 0x1000>;
clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&smbclk>; clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&smbclk>;
......
...@@ -37,7 +37,7 @@ Example: ...@@ -37,7 +37,7 @@ Example:
compatible = "arm,vexpress-sysreg"; compatible = "arm,vexpress-sysreg";
reg = <0x10000000 0x1000>; reg = <0x10000000 0x1000>;
v2m_led_gpios: sys_led@08 { v2m_led_gpios: sys_led@8 {
compatible = "arm,vexpress-sysreg,sys_led"; compatible = "arm,vexpress-sysreg,sys_led";
gpio-controller; gpio-controller;
#gpio-cells = <2>; #gpio-cells = <2>;
......
...@@ -56,7 +56,7 @@ Examples: ...@@ -56,7 +56,7 @@ Examples:
interrupts = <115>; interrupts = <115>;
}; };
ahci: sata@01c18000 { ahci: sata@1c18000 {
compatible = "allwinner,sun4i-a10-ahci"; compatible = "allwinner,sun4i-a10-ahci";
reg = <0x01c18000 0x1000>; reg = <0x01c18000 0x1000>;
interrupts = <56>; interrupts = <56>;
......
...@@ -25,7 +25,7 @@ Optional properties: ...@@ -25,7 +25,7 @@ Optional properties:
Examples: Examples:
sata@02200000 { sata@2200000 {
compatible = "fsl,imx6q-ahci"; compatible = "fsl,imx6q-ahci";
reg = <0x02200000 0x4000>; reg = <0x02200000 0x4000>;
interrupts = <0 39 IRQ_TYPE_LEVEL_HIGH>; interrupts = <0 39 IRQ_TYPE_LEVEL_HIGH>;
......
...@@ -61,7 +61,7 @@ Timing property for child nodes. It is mandatory, not optional. ...@@ -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: Example for an imx6q-sabreauto board, the NOR flash connected to the WEIM:
weim: weim@021b8000 { weim: weim@21b8000 {
compatible = "fsl,imx6q-weim"; compatible = "fsl,imx6q-weim";
reg = <0x021b8000 0x4000>; reg = <0x021b8000 0x4000>;
clocks = <&clks 196>; clocks = <&clks 196>;
......
...@@ -28,7 +28,7 @@ which can normally be found in the datasheet. ...@@ -28,7 +28,7 @@ which can normally be found in the datasheet.
Example: Example:
rsb@01f03400 { rsb@1f03400 {
compatible = "allwinner,sun8i-a23-rsb"; compatible = "allwinner,sun8i-a23-rsb";
reg = <0x01f03400 0x400>; reg = <0x01f03400 0x400>;
interrupts = <0 39 4>; interrupts = <0 39 4>;
......
...@@ -59,7 +59,7 @@ syscon: syscon@10000000 { ...@@ -59,7 +59,7 @@ syscon: syscon@10000000 {
compatible = "syscon"; compatible = "syscon";
reg = <0x10000000 0x1000>; reg = <0x10000000 0x1000>;
oscclk0: osc0@0c { oscclk0: osc0@c {
compatible = "arm,syscon-icst307"; compatible = "arm,syscon-icst307";
#clock-cells = <0>; #clock-cells = <0>;
lock-offset = <0x20>; lock-offset = <0x20>;
......
...@@ -80,7 +80,7 @@ Example 3: I2S controller node that consumes the clock generated by the clock ...@@ -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 controller. Refer to the standard clock bindings for information
about 'clocks' and 'clock-names' property. about 'clocks' and 'clock-names' property.
i2s0: i2s@03830000 { i2s0: i2s@3830000 {
compatible = "samsung,i2s-v5"; compatible = "samsung,i2s-v5";
reg = <0x03830000 0x100>; reg = <0x03830000 0x100>;
dmas = <&pdma0 10 dmas = <&pdma0 10
......
...@@ -43,7 +43,7 @@ Example: I2S controller node that consumes the clock generated by the clock ...@@ -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 controller. Refer to the standard clock bindings for information
about 'clocks' and 'clock-names' property. about 'clocks' and 'clock-names' property.
i2s0: i2s@03830000 { i2s0: i2s@3830000 {
/* ... */ /* ... */
clock-names = "iis", "i2s_opclk0", clock-names = "iis", "i2s_opclk0",
"i2s_opclk1"; "i2s_opclk1";
......
...@@ -21,7 +21,7 @@ Required properties: ...@@ -21,7 +21,7 @@ Required properties:
a size of 8. a size of 8.
- #clock-cells : from common clock binding; shall be set to 1 - #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"; compatible = "marvell,dove-divider-clock";
reg = <0x0064 0x8>; reg = <0x0064 0x8>;
#clock-cells = <1>; #clock-cells = <1>;
......
...@@ -10,13 +10,13 @@ ID in its "clocks" phandle cell. See include/dt-bindings/clock/imx1-clock.h ...@@ -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. for the full list of i.MX1 clock IDs.
Examples: Examples:
clks: ccm@0021b000 { clks: ccm@21b000 {
#clock-cells = <1>; #clock-cells = <1>;
compatible = "fsl,imx1-ccm"; compatible = "fsl,imx1-ccm";
reg = <0x0021b000 0x1000>; reg = <0x0021b000 0x1000>;
}; };
pwm: pwm@00208000 { pwm: pwm@208000 {
#pwm-cells = <2>; #pwm-cells = <2>;
compatible = "fsl,imx1-pwm"; compatible = "fsl,imx1-pwm";
reg = <0x00208000 0x1000>; reg = <0x00208000 0x1000>;
......
...@@ -14,14 +14,14 @@ Examples: ...@@ -14,14 +14,14 @@ Examples:
#include <dt-bindings/clock/imx6qdl-clock.h> #include <dt-bindings/clock/imx6qdl-clock.h>
clks: ccm@020c4000 { clks: ccm@20c4000 {
compatible = "fsl,imx6q-ccm"; compatible = "fsl,imx6q-ccm";
reg = <0x020c4000 0x4000>; reg = <0x020c4000 0x4000>;
interrupts = <0 87 0x04 0 88 0x04>; interrupts = <0 87 0x04 0 88 0x04>;
#clock-cells = <1>; #clock-cells = <1>;
}; };
uart1: serial@02020000 { uart1: serial@2020000 {
compatible = "fsl,imx6q-uart", "fsl,imx21-uart"; compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
reg = <0x02020000 0x4000>; reg = <0x02020000 0x4000>;
interrupts = <0 26 0x04>; interrupts = <0 26 0x04>;
......
...@@ -46,7 +46,7 @@ Example: ...@@ -46,7 +46,7 @@ Example:
/* ... */ /* ... */
Node of the MFD chip Node of the MFD chip
max77686: max77686@09 { max77686: max77686@9 {
compatible = "maxim,max77686"; compatible = "maxim,max77686";
interrupt-parent = <&wakeup_eint>; interrupt-parent = <&wakeup_eint>;
interrupts = <26 0>; interrupts = <26 0>;
...@@ -71,7 +71,7 @@ Example: ...@@ -71,7 +71,7 @@ Example:
/* ... */ /* ... */
Node of the MFD chip Node of the MFD chip
max77802: max77802@09 { max77802: max77802@9 {
compatible = "maxim,max77802"; compatible = "maxim,max77802";
interrupt-parent = <&wakeup_eint>; interrupt-parent = <&wakeup_eint>;
interrupts = <26 0>; interrupts = <26 0>;
......
...@@ -42,7 +42,7 @@ Required properties: ...@@ -42,7 +42,7 @@ Required properties:
Example: Example:
clockgen-a@090ff000 { clockgen-a@90ff000 {
compatible = "st,clkgen-c32"; compatible = "st,clkgen-c32";
reg = <0x90ff000 0x1000>; reg = <0x90ff000 0x1000>;
......
...@@ -36,7 +36,7 @@ For the PRCM CCUs on A83T/H3/A64, two more clocks are needed: ...@@ -36,7 +36,7 @@ For the PRCM CCUs on A83T/H3/A64, two more clocks are needed:
- "iosc": the SoC's internal frequency oscillator - "iosc": the SoC's internal frequency oscillator
Example for generic CCU: Example for generic CCU:
ccu: clock@01c20000 { ccu: clock@1c20000 {
compatible = "allwinner,sun8i-h3-ccu"; compatible = "allwinner,sun8i-h3-ccu";
reg = <0x01c20000 0x400>; reg = <0x01c20000 0x400>;
clocks = <&osc24M>, <&osc32k>; clocks = <&osc24M>, <&osc32k>;
...@@ -46,7 +46,7 @@ ccu: clock@01c20000 { ...@@ -46,7 +46,7 @@ ccu: clock@01c20000 {
}; };
Example for PRCM CCU: Example for PRCM CCU:
r_ccu: clock@01f01400 { r_ccu: clock@1f01400 {
compatible = "allwinner,sun50i-a64-r-ccu"; compatible = "allwinner,sun50i-a64-r-ccu";
reg = <0x01f01400 0x100>; reg = <0x01f01400 0x100>;
clocks = <&osc24M>, <&osc32k>, <&iosc>, <&ccu CLK_PLL_PERIPH0>; clocks = <&osc24M>, <&osc32k>, <&iosc>, <&ccu CLK_PLL_PERIPH0>;
......
...@@ -137,7 +137,7 @@ the address block, which is related to the overall mmc block. ...@@ -137,7 +137,7 @@ the address block, which is related to the overall mmc block.
For example: For example:
osc24M: clk@01c20050 { osc24M: clk@1c20050 {
#clock-cells = <0>; #clock-cells = <0>;
compatible = "allwinner,sun4i-a10-osc-clk"; compatible = "allwinner,sun4i-a10-osc-clk";
reg = <0x01c20050 0x4>; reg = <0x01c20050 0x4>;
...@@ -145,7 +145,7 @@ osc24M: clk@01c20050 { ...@@ -145,7 +145,7 @@ osc24M: clk@01c20050 {
clock-output-names = "osc24M"; clock-output-names = "osc24M";
}; };
pll1: clk@01c20000 { pll1: clk@1c20000 {
#clock-cells = <0>; #clock-cells = <0>;
compatible = "allwinner,sun4i-a10-pll1-clk"; compatible = "allwinner,sun4i-a10-pll1-clk";
reg = <0x01c20000 0x4>; reg = <0x01c20000 0x4>;
...@@ -153,7 +153,7 @@ pll1: clk@01c20000 { ...@@ -153,7 +153,7 @@ pll1: clk@01c20000 {
clock-output-names = "pll1"; clock-output-names = "pll1";
}; };
pll5: clk@01c20020 { pll5: clk@1c20020 {
#clock-cells = <1>; #clock-cells = <1>;
compatible = "allwinner,sun4i-pll5-clk"; compatible = "allwinner,sun4i-pll5-clk";
reg = <0x01c20020 0x4>; reg = <0x01c20020 0x4>;
...@@ -161,7 +161,7 @@ pll5: clk@01c20020 { ...@@ -161,7 +161,7 @@ pll5: clk@01c20020 {
clock-output-names = "pll5_ddr", "pll5_other"; clock-output-names = "pll5_ddr", "pll5_other";
}; };
pll6: clk@01c20028 { pll6: clk@1c20028 {
#clock-cells = <1>; #clock-cells = <1>;
compatible = "allwinner,sun6i-a31-pll6-clk"; compatible = "allwinner,sun6i-a31-pll6-clk";
reg = <0x01c20028 0x4>; reg = <0x01c20028 0x4>;
...@@ -169,7 +169,7 @@ pll6: clk@01c20028 { ...@@ -169,7 +169,7 @@ pll6: clk@01c20028 {
clock-output-names = "pll6", "pll6x2"; clock-output-names = "pll6", "pll6x2";
}; };
cpu: cpu@01c20054 { cpu: cpu@1c20054 {
#clock-cells = <0>; #clock-cells = <0>;
compatible = "allwinner,sun4i-a10-cpu-clk"; compatible = "allwinner,sun4i-a10-cpu-clk";
reg = <0x01c20054 0x4>; reg = <0x01c20054 0x4>;
...@@ -177,7 +177,7 @@ cpu: cpu@01c20054 { ...@@ -177,7 +177,7 @@ cpu: cpu@01c20054 {
clock-output-names = "cpu"; clock-output-names = "cpu";
}; };
mmc0_clk: clk@01c20088 { mmc0_clk: clk@1c20088 {
#clock-cells = <1>; #clock-cells = <1>;
compatible = "allwinner,sun4i-a10-mmc-clk"; compatible = "allwinner,sun4i-a10-mmc-clk";
reg = <0x01c20088 0x4>; reg = <0x01c20088 0x4>;
...@@ -199,7 +199,7 @@ gmac_int_tx_clk: clk@3 { ...@@ -199,7 +199,7 @@ gmac_int_tx_clk: clk@3 {
clock-output-names = "gmac_int_tx"; clock-output-names = "gmac_int_tx";
}; };
gmac_clk: clk@01c20164 { gmac_clk: clk@1c20164 {
#clock-cells = <0>; #clock-cells = <0>;
compatible = "allwinner,sun7i-a20-gmac-clk"; compatible = "allwinner,sun7i-a20-gmac-clk";
reg = <0x01c20164 0x4>; reg = <0x01c20164 0x4>;
...@@ -211,7 +211,7 @@ gmac_clk: clk@01c20164 { ...@@ -211,7 +211,7 @@ gmac_clk: clk@01c20164 {
clock-output-names = "gmac"; clock-output-names = "gmac";
}; };
mmc_config_clk: clk@01c13000 { mmc_config_clk: clk@1c13000 {
compatible = "allwinner,sun9i-a80-mmc-config-clk"; compatible = "allwinner,sun9i-a80-mmc-config-clk";
reg = <0x01c13000 0x10>; reg = <0x01c13000 0x10>;
clocks = <&ahb0_gates 8>; clocks = <&ahb0_gates 8>;
......
...@@ -25,7 +25,7 @@ Example: ...@@ -25,7 +25,7 @@ Example:
}; };
}; };
... ...
i2c0: i2c-master@0d090000 { i2c0: i2c-master@d090000 {
... ...
cdce706: clock-synth@69 { cdce706: clock-synth@69 {
compatible = "ti,cdce706"; compatible = "ti,cdce706";
......
...@@ -14,7 +14,7 @@ Optional properties: ...@@ -14,7 +14,7 @@ Optional properties:
- reset-names : must contain "ahb" - reset-names : must contain "ahb"
Example: Example:
crypto: crypto-engine@01c15000 { crypto: crypto-engine@1c15000 {
compatible = "allwinner,sun4i-a10-crypto"; compatible = "allwinner,sun4i-a10-crypto";
reg = <0x01c15000 0x1000>; reg = <0x01c15000 0x1000>;
interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>; interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
......
...@@ -42,7 +42,7 @@ Optional properties: ...@@ -42,7 +42,7 @@ Optional properties:
example: example:
gpu_3d: gpu@00130000 { gpu_3d: gpu@130000 {
compatible = "vivante,gc"; compatible = "vivante,gc";
reg = <0x00130000 0x4000>; reg = <0x00130000 0x4000>;
interrupts = <0 9 IRQ_TYPE_LEVEL_HIGH>; interrupts = <0 9 IRQ_TYPE_LEVEL_HIGH>;
......
...@@ -32,11 +32,11 @@ Optional properties ...@@ -32,11 +32,11 @@ Optional properties
Example: Example:
gpr: iomuxc-gpr@020e0000 { gpr: iomuxc-gpr@20e0000 {
/* ... */ /* ... */
}; };
hdmi: hdmi@0120000 { hdmi: hdmi@120000 {
#address-cells = <1>; #address-cells = <1>;
#size-cells = <0>; #size-cells = <0>;
compatible = "fsl,imx6q-hdmi"; compatible = "fsl,imx6q-hdmi";
......
...@@ -78,7 +78,7 @@ chosen { ...@@ -78,7 +78,7 @@ chosen {
stdout-path = "display0"; stdout-path = "display0";
}; };
soc@01c00000 { soc@1c00000 {
lcdc0: lcdc@1c0c000 { lcdc0: lcdc@1c0c000 {
compatible = "allwinner,sun4i-a10-lcdc"; compatible = "allwinner,sun4i-a10-lcdc";
... ...
......
...@@ -266,7 +266,7 @@ connector { ...@@ -266,7 +266,7 @@ connector {
}; };
}; };
hdmi: hdmi@01c16000 { hdmi: hdmi@1c16000 {
compatible = "allwinner,sun5i-a10s-hdmi"; compatible = "allwinner,sun5i-a10s-hdmi";
reg = <0x01c16000 0x1000>; reg = <0x01c16000 0x1000>;
interrupts = <58>; interrupts = <58>;
...@@ -305,7 +305,7 @@ hdmi: hdmi@01c16000 { ...@@ -305,7 +305,7 @@ hdmi: hdmi@01c16000 {
}; };
}; };
tve0: tv-encoder@01c0a000 { tve0: tv-encoder@1c0a000 {
compatible = "allwinner,sun4i-a10-tv-encoder"; compatible = "allwinner,sun4i-a10-tv-encoder";
reg = <0x01c0a000 0x1000>; reg = <0x01c0a000 0x1000>;
clocks = <&ahb_gates 34>; clocks = <&ahb_gates 34>;
......
...@@ -12,7 +12,7 @@ Required properties: ...@@ -12,7 +12,7 @@ Required properties:
second cell holding the request line number. second cell holding the request line number.
Example: Example:
dma: dma-controller@01c02000 { dma: dma-controller@1c02000 {
compatible = "allwinner,sun4i-a10-dma"; compatible = "allwinner,sun4i-a10-dma";
reg = <0x01c02000 0x1000>; reg = <0x01c02000 0x1000>;
interrupts = <27>; interrupts = <27>;
...@@ -32,7 +32,7 @@ The three cells in order are: ...@@ -32,7 +32,7 @@ The three cells in order are:
3. The port ID as specified in the datasheet 3. The port ID as specified in the datasheet
Example: Example:
spi2: spi@01c17000 { spi2: spi@1c17000 {
compatible = "allwinner,sun4i-a10-spi"; compatible = "allwinner,sun4i-a10-spi";
reg = <0x01c17000 0x1000>; reg = <0x01c17000 0x1000>;
interrupts = <0 12 4>; interrupts = <0 12 4>;
......
...@@ -64,7 +64,7 @@ The two cells in order are: ...@@ -64,7 +64,7 @@ The two cells in order are:
2. The port ID as specified in the datasheet 2. The port ID as specified in the datasheet
Example: Example:
spi2: spi@01c6a000 { spi2: spi@1c6a000 {
compatible = "allwinner,sun6i-a31-spi"; compatible = "allwinner,sun6i-a31-spi";
reg = <0x01c6a000 0x1000>; reg = <0x01c6a000 0x1000>;
interrupts = <0 67 4>; interrupts = <0 67 4>;
......
...@@ -142,7 +142,7 @@ mcasp0: mcasp@48038000 { ...@@ -142,7 +142,7 @@ mcasp0: mcasp@48038000 {
}; };
2. 2.
edma1: edma@02728000 { edma1: edma@2728000 {
compatible = "ti,k2g-edma3-tpcc", "ti,edma3-tpcc"; compatible = "ti,k2g-edma3-tpcc", "ti,edma3-tpcc";
reg = <0x02728000 0x8000>; reg = <0x02728000 0x8000>;
reg-names = "edma3_cc"; reg-names = "edma3_cc";
...@@ -165,13 +165,13 @@ edma1: edma@02728000 { ...@@ -165,13 +165,13 @@ edma1: edma@02728000 {
power-domains = <&k2g_pds 0x4f>; power-domains = <&k2g_pds 0x4f>;
}; };
edma1_tptc0: tptc@027b0000 { edma1_tptc0: tptc@27b0000 {
compatible = "ti,k2g-edma3-tptc", "ti,edma3-tptc"; compatible = "ti,k2g-edma3-tptc", "ti,edma3-tptc";
reg = <0x027b0000 0x400>; reg = <0x027b0000 0x400>;
power-domains = <&k2g_pds 0x4f>; power-domains = <&k2g_pds 0x4f>;
}; };
edma1_tptc1: tptc@027b8000 { edma1_tptc1: tptc@27b8000 {
compatible = "ti, k2g-edma3-tptc", "ti,edma3-tptc"; compatible = "ti, k2g-edma3-tptc", "ti,edma3-tptc";
reg = <0x027b8000 0x400>; reg = <0x027b8000 0x400>;
power-domains = <&k2g_pds 0x4f>; power-domains = <&k2g_pds 0x4f>;
......
...@@ -26,7 +26,7 @@ Controller: ...@@ -26,7 +26,7 @@ Controller:
Client: Client:
Use specific request line passing from dmax Use specific request line passing from dmax
For example, spdif0 tx channel request line is 4 For example, spdif0 tx channel request line is 4
spdif0: spdif0@0b004000 { spdif0: spdif0@b004000 {
#sound-dai-cells = <0>; #sound-dai-cells = <0>;
compatible = "zte,zx296702-spdif"; compatible = "zte,zx296702-spdif";
reg = <0x0b004000 0x1000>; reg = <0x0b004000 0x1000>;
......
...@@ -66,7 +66,7 @@ See ".../sram/sram.txt" for the bindings. ...@@ -66,7 +66,7 @@ See ".../sram/sram.txt" for the bindings.
Example: Example:
hsp_top0: hsp@03c00000 { hsp_top0: hsp@3c00000 {
... ...
#mbox-cells = <2>; #mbox-cells = <2>;
}; };
......
...@@ -25,7 +25,7 @@ Please refer to gpio.txt in this directory for details of the common GPIO ...@@ -25,7 +25,7 @@ Please refer to gpio.txt in this directory for details of the common GPIO
bindings used by client devices. bindings used by client devices.
Example: Example:
dspgpio0: keystone_dsp_gpio@02620240 { dspgpio0: keystone_dsp_gpio@2620240 {
compatible = "ti,keystone-dsp-gpio"; compatible = "ti,keystone-dsp-gpio";
ti,syscon-dev = <&devctrl 0x240>; ti,syscon-dev = <&devctrl 0x240>;
gpio-controller; gpio-controller;
......
...@@ -30,7 +30,7 @@ Optional properties: ...@@ -30,7 +30,7 @@ Optional properties:
Example: Example:
pdc_gpios: gpio-controller@02006500 { pdc_gpios: gpio-controller@2006500 {
gpio-controller; gpio-controller;
#gpio-cells = <2>; #gpio-cells = <2>;
......
...@@ -59,7 +59,7 @@ Required properties: ...@@ -59,7 +59,7 @@ Required properties:
Example: Example:
gpios: gpio-controller@02005800 { gpios: gpio-controller@2005800 {
#address-cells = <1>; #address-cells = <1>;
#size-cells = <0>; #size-cells = <0>;
compatible = "img,tz1090-gpio"; compatible = "img,tz1090-gpio";
......
...@@ -17,7 +17,7 @@ Optional properties : ...@@ -17,7 +17,7 @@ Optional properties :
Example : Example :
i2c@02010084000 { i2c@2010084000 {
compatible = "lsi,api2c"; compatible = "lsi,api2c";
device_type = "i2c"; device_type = "i2c";
#address-cells = <1>; #address-cells = <1>;
......
...@@ -24,7 +24,7 @@ Slave device properties: ...@@ -24,7 +24,7 @@ Slave device properties:
Example: Example:
p2wi@01f03400 { p2wi@1f03400 {
compatible = "allwinner,sun6i-a31-p2wi"; compatible = "allwinner,sun6i-a31-p2wi";
reg = <0x01f03400 0x400>; reg = <0x01f03400 0x400>;
interrupts = <0 39 4>; interrupts = <0 39 4>;
......
...@@ -19,7 +19,7 @@ Optional properties: ...@@ -19,7 +19,7 @@ Optional properties:
Example: Example:
ak8974@0f { ak8974@f {
compatible = "asahi-kasei,ak8974"; compatible = "asahi-kasei,ak8974";
reg = <0x0f>; reg = <0x0f>;
avdd-supply = <&foo_reg>; avdd-supply = <&foo_reg>;
......
...@@ -13,7 +13,7 @@ Optional properties: ...@@ -13,7 +13,7 @@ Optional properties:
Example: Example:
ak8975@0c { ak8975@c {
compatible = "asahi-kasei,ak8975"; compatible = "asahi-kasei,ak8975";
reg = <0x0c>; reg = <0x0c>;
gpios = <&gpj0 7 0>; gpios = <&gpj0 7 0>;
......
...@@ -19,7 +19,7 @@ Example: ...@@ -19,7 +19,7 @@ Example:
#include <dt-bindings/input/input.h> #include <dt-bindings/input/input.h>
lradc: lradc@01c22800 { lradc: lradc@1c22800 {
compatible = "allwinner,sun4i-a10-lradc-keys"; compatible = "allwinner,sun4i-a10-lradc-keys";
reg = <0x01c22800 0x100>; reg = <0x01c22800 0x100>;
interrupts = <31>; interrupts = <31>;
......
...@@ -10,7 +10,7 @@ Required properties: ...@@ -10,7 +10,7 @@ Required properties:
Example: Example:
egalax_ts@04 { touchscreen@4 {
compatible = "eeti,egalax_ts"; compatible = "eeti,egalax_ts";
reg = <0x04>; reg = <0x04>;
interrupt-parent = <&gpio1>; interrupt-parent = <&gpio1>;
......
...@@ -21,7 +21,7 @@ Optional properties: ...@@ -21,7 +21,7 @@ Optional properties:
each read. Valid values are 1, 4, 8, 16 and 32. each read. Valid values are 1, 4, 8, 16 and 32.
Example: Example:
tsc: tsc@02040000 { tsc: tsc@2040000 {
compatible = "fsl,imx6ul-tsc"; compatible = "fsl,imx6ul-tsc";
reg = <0x02040000 0x4000>, <0x0219c000 0x4000>; reg = <0x02040000 0x4000>, <0x0219c000 0x4000>;
interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>, interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>,
......
...@@ -20,7 +20,7 @@ Required properties: ...@@ -20,7 +20,7 @@ Required properties:
Example: Example:
sc-nmi-intc@01c00030 { sc-nmi-intc@1c00030 {
compatible = "allwinner,sun7i-a20-sc-nmi"; compatible = "allwinner,sun7i-a20-sc-nmi";
interrupt-controller; interrupt-controller;
#interrupt-cells = <2>; #interrupt-cells = <2>;
......
...@@ -20,7 +20,7 @@ Please refer to interrupts.txt in this directory for details of the common ...@@ -20,7 +20,7 @@ Please refer to interrupts.txt in this directory for details of the common
Interrupt Controllers bindings used by client devices. Interrupt Controllers bindings used by client devices.
Example: Example:
kirq0: keystone_irq0@026202a0 { kirq0: keystone_irq0@26202a0 {
compatible = "ti,keystone-irq"; compatible = "ti,keystone-irq";
ti,syscon-dev = <&devctrl 0x2a0>; ti,syscon-dev = <&devctrl 0x2a0>;
interrupts = <GIC_SPI 4 IRQ_TYPE_EDGE_RISING>; interrupts = <GIC_SPI 4 IRQ_TYPE_EDGE_RISING>;
......
...@@ -115,7 +115,7 @@ to non-secure vs secure interrupt line. ...@@ -115,7 +115,7 @@ to non-secure vs secure interrupt line.
iommus = <&apps_iommu 4>; iommus = <&apps_iommu 4>;
}; };
gpu@01c00000 { gpu@1c00000 {
... ...
iommus = <&gpu_iommu 1>, <&gpu_iommu 2>; iommus = <&gpu_iommu 1>, <&gpu_iommu 2>;
}; };
...@@ -53,7 +53,7 @@ Example: R8A7791 IPMMU-MX and VSP1-D0 bus master ...@@ -53,7 +53,7 @@ Example: R8A7791 IPMMU-MX and VSP1-D0 bus master
#iommu-cells = <1>; #iommu-cells = <1>;
}; };
vsp1@fe928000 { vsp@fe928000 {
... ...
iommus = <&ipmmu_mx 13>; iommus = <&ipmmu_mx 13>;
... ...
......
...@@ -32,7 +32,7 @@ syscon: syscon@10000000 { ...@@ -32,7 +32,7 @@ syscon: syscon@10000000 {
compatible = "arm,realview-pb1176-syscon", "syscon"; compatible = "arm,realview-pb1176-syscon", "syscon";
reg = <0x10000000 0x1000>; reg = <0x10000000 0x1000>;
led@08.0 { led@8.0 {
compatible = "register-bit-led"; compatible = "register-bit-led";
offset = <0x08>; offset = <0x08>;
mask = <0x01>; mask = <0x01>;
...@@ -40,7 +40,7 @@ syscon: syscon@10000000 { ...@@ -40,7 +40,7 @@ syscon: syscon@10000000 {
linux,default-trigger = "heartbeat"; linux,default-trigger = "heartbeat";
default-state = "on"; default-state = "on";
}; };
led@08.1 { led@8.1 {
compatible = "register-bit-led"; compatible = "register-bit-led";
offset = <0x08>; offset = <0x08>;
mask = <0x02>; mask = <0x02>;
...@@ -48,7 +48,7 @@ syscon: syscon@10000000 { ...@@ -48,7 +48,7 @@ syscon: syscon@10000000 {
linux,default-trigger = "mmc0"; linux,default-trigger = "mmc0";
default-state = "off"; default-state = "off";
}; };
led@08.2 { led@8.2 {
compatible = "register-bit-led"; compatible = "register-bit-led";
offset = <0x08>; offset = <0x08>;
mask = <0x04>; mask = <0x04>;
...@@ -56,35 +56,35 @@ syscon: syscon@10000000 { ...@@ -56,35 +56,35 @@ syscon: syscon@10000000 {
linux,default-trigger = "cpu0"; linux,default-trigger = "cpu0";
default-state = "off"; default-state = "off";
}; };
led@08.3 { led@8.3 {
compatible = "register-bit-led"; compatible = "register-bit-led";
offset = <0x08>; offset = <0x08>;
mask = <0x08>; mask = <0x08>;
label = "versatile:3"; label = "versatile:3";
default-state = "off"; default-state = "off";
}; };
led@08.4 { led@8.4 {
compatible = "register-bit-led"; compatible = "register-bit-led";
offset = <0x08>; offset = <0x08>;
mask = <0x10>; mask = <0x10>;
label = "versatile:4"; label = "versatile:4";
default-state = "off"; default-state = "off";
}; };
led@08.5 { led@8.5 {
compatible = "register-bit-led"; compatible = "register-bit-led";
offset = <0x08>; offset = <0x08>;
mask = <0x20>; mask = <0x20>;
label = "versatile:5"; label = "versatile:5";
default-state = "off"; default-state = "off";
}; };
led@08.6 { led@8.6 {
compatible = "register-bit-led"; compatible = "register-bit-led";
offset = <0x08>; offset = <0x08>;
mask = <0x40>; mask = <0x40>;
label = "versatile:6"; label = "versatile:6";
default-state = "off"; default-state = "off";
}; };
led@08.7 { led@8.7 {
compatible = "register-bit-led"; compatible = "register-bit-led";
offset = <0x08>; offset = <0x08>;
mask = <0x80>; mask = <0x80>;
......
...@@ -29,7 +29,7 @@ Required properties: ...@@ -29,7 +29,7 @@ Required properties:
Example(K2G): Example(K2G):
------------ ------------
msgmgr: msgmgr@02a00000 { msgmgr: msgmgr@2a00000 {
compatible = "ti,k2g-message-manager"; compatible = "ti,k2g-message-manager";
#mbox-cells = <2>; #mbox-cells = <2>;
reg-names = "queue_proxy_region", "queue_state_debug_region"; reg-names = "queue_proxy_region", "queue_state_debug_region";
......
...@@ -446,7 +446,7 @@ prefixed with the string "marvell,", for Marvell Technology Group Ltd. ...@@ -446,7 +446,7 @@ prefixed with the string "marvell,", for Marvell Technology Group Ltd.
that services interrupts for this device. that services interrupts for this device.
Example Discovery CPU Error node: Example Discovery CPU Error node:
cpu-error@0070 { cpu-error@70 {
compatible = "marvell,mv64360-cpu-error"; compatible = "marvell,mv64360-cpu-error";
reg = <0x70 0x10 0x128 0x28>; reg = <0x70 0x10 0x128 0x28>;
interrupts = <3>; interrupts = <3>;
...@@ -466,7 +466,7 @@ prefixed with the string "marvell,", for Marvell Technology Group Ltd. ...@@ -466,7 +466,7 @@ prefixed with the string "marvell,", for Marvell Technology Group Ltd.
that services interrupts for this device. that services interrupts for this device.
Example Discovery SRAM Controller node: Example Discovery SRAM Controller node:
sram-ctrl@0380 { sram-ctrl@380 {
compatible = "marvell,mv64360-sram-ctrl"; compatible = "marvell,mv64360-sram-ctrl";
reg = <0x380 0x80>; reg = <0x380 0x80>;
interrupts = <13>; interrupts = <13>;
......
...@@ -27,7 +27,7 @@ Documentation/devicetree/bindings/media/video-interfaces.txt. ...@@ -27,7 +27,7 @@ Documentation/devicetree/bindings/media/video-interfaces.txt.
Example: Example:
tc358743@0f { tc358743@f {
compatible = "toshiba,tc358743"; compatible = "toshiba,tc358743";
reg = <0x0f>; reg = <0x0f>;
clocks = <&hdmi_osc>; clocks = <&hdmi_osc>;
......
...@@ -25,7 +25,7 @@ Optional properties: ...@@ -25,7 +25,7 @@ Optional properties:
Example: Example:
ir@02006200 { ir@2006200 {
compatible = "img,ir-rev1"; compatible = "img,ir-rev1";
reg = <0x02006200 0x100>; reg = <0x02006200 0x100>;
interrupts = <29 4>; interrupts = <29 4>;
......
...@@ -22,7 +22,7 @@ Optional properties: ...@@ -22,7 +22,7 @@ Optional properties:
Example: R8A7790 (R-Car H2) VSP1-S node Example: R8A7790 (R-Car H2) VSP1-S node
vsp1@fe928000 { vsp@fe928000 {
compatible = "renesas,vsp1"; compatible = "renesas,vsp1";
reg = <0 0xfe928000 0 0x8000>; reg = <0 0xfe928000 0 0x8000>;
interrupts = <0 267 IRQ_TYPE_LEVEL_HIGH>; interrupts = <0 267 IRQ_TYPE_LEVEL_HIGH>;
......
...@@ -13,7 +13,7 @@ Required properties: ...@@ -13,7 +13,7 @@ Required properties:
Example for STIH407: Example for STIH407:
sti-cec@094a087c { sti-cec@94a087c {
compatible = "st,stih-cec"; compatible = "st,stih-cec";
reg = <0x94a087c 0x64>; reg = <0x94a087c 0x64>;
clocks = <&clk_sysin>; clocks = <&clk_sysin>;
......
...@@ -50,7 +50,7 @@ Example: ...@@ -50,7 +50,7 @@ Example:
/* stih410 SoC b2120 + b2004a + stv0367-pll(NIMB) + stv0367-tda18212 (NIMA) DT example) */ /* stih410 SoC b2120 + b2004a + stv0367-pll(NIMB) + stv0367-tda18212 (NIMA) DT example) */
c8sectpfe@08a20000 { c8sectpfe@8a20000 {
compatible = "st,stih407-c8sectpfe"; compatible = "st,stih407-c8sectpfe";
reg = <0x08a20000 0x10000>, <0x08a00000 0x4000>; reg = <0x08a20000 0x10000>, <0x08a00000 0x4000>;
reg-names = "stfe", "stfe-ram"; reg-names = "stfe", "stfe-ram";
......
...@@ -14,7 +14,7 @@ Optional properties: ...@@ -14,7 +14,7 @@ Optional properties:
Example: Example:
ir0: ir@01c21800 { ir0: ir@1c21800 {
compatible = "allwinner,sun4i-a10-ir"; compatible = "allwinner,sun4i-a10-ir";
clocks = <&apb0_gates 6>, <&ir0_clk>; clocks = <&apb0_gates 6>, <&ir0_clk>;
clock-names = "apb", "ir"; clock-names = "apb", "ir";
......
...@@ -19,7 +19,7 @@ Required properties: ...@@ -19,7 +19,7 @@ Required properties:
Example: Example:
max77686: pmic@09 { max77686: pmic@9 {
compatible = "maxim,max77686"; compatible = "maxim,max77686";
interrupt-parent = <&wakeup_eint>; interrupt-parent = <&wakeup_eint>;
interrupts = <26 0>; interrupts = <26 0>;
......
...@@ -18,7 +18,7 @@ Required properties: ...@@ -18,7 +18,7 @@ Required properties:
Example: Example:
max77802: pmic@09 { max77802: pmic@9 {
compatible = "maxim,max77802"; compatible = "maxim,max77802";
interrupt-parent = <&intc>; interrupt-parent = <&intc>;
interrupts = <26 IRQ_TYPE_NONE>; interrupts = <26 IRQ_TYPE_NONE>;
......
...@@ -41,7 +41,7 @@ foo@1000 { ...@@ -41,7 +41,7 @@ foo@1000 {
compatible = "syscon", "simple-mfd"; compatible = "syscon", "simple-mfd";
reg = <0x01000 0x1000>; reg = <0x01000 0x1000>;
led@08.0 { led@8.0 {
compatible = "register-bit-led"; compatible = "register-bit-led";
offset = <0x08>; offset = <0x08>;
mask = <0x01>; mask = <0x01>;
......
...@@ -10,7 +10,7 @@ Required properties: ...@@ -10,7 +10,7 @@ Required properties:
- #io-channel-cells: shall be 0, - #io-channel-cells: shall be 0,
Example: Example:
ths: ths@01c25000 { ths: ths@1c25000 {
compatible = "allwinner,sun8i-a33-ths"; compatible = "allwinner,sun8i-a33-ths";
reg = <0x01c25000 0x100>; reg = <0x01c25000 0x100>;
#thermal-sensor-cells = <0>; #thermal-sensor-cells = <0>;
...@@ -47,7 +47,7 @@ Optional properties: ...@@ -47,7 +47,7 @@ Optional properties:
Example: Example:
rtp: rtp@01c25000 { rtp: rtp@1c25000 {
compatible = "allwinner,sun4i-a10-ts"; compatible = "allwinner,sun4i-a10-ts";
reg = <0x01c25000 0x100>; reg = <0x01c25000 0x100>;
interrupts = <29>; interrupts = <29>;
......
...@@ -15,7 +15,7 @@ The prcm node may contain several subdevices definitions: ...@@ -15,7 +15,7 @@ The prcm node may contain several subdevices definitions:
Example: Example:
prcm: prcm@01f01400 { prcm: prcm@1f01400 {
compatible = "allwinner,sun6i-a31-prcm"; compatible = "allwinner,sun6i-a31-prcm";
reg = <0x01f01400 0x200>; reg = <0x01f01400 0x200>;
......
...@@ -18,7 +18,7 @@ Optional property: ...@@ -18,7 +18,7 @@ Optional property:
performed on the device. performed on the device.
Examples: Examples:
gpr: iomuxc-gpr@020e0000 { gpr: iomuxc-gpr@20e0000 {
compatible = "fsl,imx6q-iomuxc-gpr", "syscon"; compatible = "fsl,imx6q-iomuxc-gpr", "syscon";
reg = <0x020e0000 0x38>; reg = <0x020e0000 0x38>;
}; };
...@@ -146,7 +146,7 @@ sdhci@ab000000 { ...@@ -146,7 +146,7 @@ sdhci@ab000000 {
Example with sdio function subnode: Example with sdio function subnode:
mmc3: mmc@01c12000 { mmc3: mmc@1c12000 {
#address-cells = <1>; #address-cells = <1>;
#size-cells = <0>; #size-cells = <0>;
......
...@@ -74,7 +74,7 @@ mmc0: sdhci@fe81e000 { ...@@ -74,7 +74,7 @@ mmc0: sdhci@fe81e000 {
/* Example SD stih407 family configuration */ /* Example SD stih407 family configuration */
mmc1: sdhci@09080000 { mmc1: sdhci@9080000 {
compatible = "st,sdhci-stih407", "st,sdhci"; compatible = "st,sdhci-stih407", "st,sdhci";
reg = <0x09080000 0x7ff>; reg = <0x09080000 0x7ff>;
reg-names = "mmc"; reg-names = "mmc";
...@@ -90,7 +90,7 @@ mmc1: sdhci@09080000 { ...@@ -90,7 +90,7 @@ mmc1: sdhci@09080000 {
/* Example eMMC stih407 family configuration */ /* Example eMMC stih407 family configuration */
mmc0: sdhci@09060000 { mmc0: sdhci@9060000 {
compatible = "st,sdhci-stih407", "st,sdhci"; compatible = "st,sdhci-stih407", "st,sdhci";
reg = <0x09060000 0x7ff>, <0x9061008 0x20>; reg = <0x09060000 0x7ff>, <0x9061008 0x20>;
reg-names = "mmc", "top-mmc-delay"; reg-names = "mmc", "top-mmc-delay";
......
...@@ -29,7 +29,7 @@ Optional properties: ...@@ -29,7 +29,7 @@ Optional properties:
Examples: Examples:
- Within .dtsi: - Within .dtsi:
mmc0: mmc@01c0f000 { mmc0: mmc@1c0f000 {
compatible = "allwinner,sun5i-a13-mmc"; compatible = "allwinner,sun5i-a13-mmc";
reg = <0x01c0f000 0x1000>; reg = <0x01c0f000 0x1000>;
clocks = <&ahb_gates 8>, <&mmc0_clk>, <&mmc0_output_clk>, <&mmc0_sample_clk>; clocks = <&ahb_gates 8>, <&mmc0_clk>, <&mmc0_output_clk>, <&mmc0_sample_clk>;
...@@ -39,7 +39,7 @@ Examples: ...@@ -39,7 +39,7 @@ Examples:
}; };
- Within dts: - Within dts:
mmc0: mmc@01c0f000 { mmc0: mmc@1c0f000 {
pinctrl-names = "default", "default"; pinctrl-names = "default", "default";
pinctrl-0 = <&mmc0_pins_a>; pinctrl-0 = <&mmc0_pins_a>;
pinctrl-1 = <&mmc0_cd_pin_reference_design>; pinctrl-1 = <&mmc0_cd_pin_reference_design>;
......
...@@ -31,7 +31,7 @@ see Documentation/devicetree/bindings/mtd/nand.txt for generic bindings. ...@@ -31,7 +31,7 @@ see Documentation/devicetree/bindings/mtd/nand.txt for generic bindings.
Examples: Examples:
nfc: nand@01c03000 { nfc: nand@1c03000 {
compatible = "allwinner,sun4i-a10-nand"; compatible = "allwinner,sun4i-a10-nand";
reg = <0x01c03000 0x1000>; reg = <0x01c03000 0x1000>;
interrupts = <0 37 1>; interrupts = <0 37 1>;
......
...@@ -10,7 +10,7 @@ Required properties: ...@@ -10,7 +10,7 @@ Required properties:
Example: Example:
emac: ethernet@01c0b000 { emac: ethernet@1c0b000 {
compatible = "allwinner,sun4i-a10-emac"; compatible = "allwinner,sun4i-a10-emac";
reg = <0x01c0b000 0x1000>; reg = <0x01c0b000 0x1000>;
interrupts = <55>; interrupts = <55>;
......
...@@ -9,7 +9,7 @@ Optional properties: ...@@ -9,7 +9,7 @@ Optional properties:
- phy-supply: phandle to a regulator if the PHY needs one - phy-supply: phandle to a regulator if the PHY needs one
Example at the SoC level: Example at the SoC level:
mdio@01c0b080 { mdio@1c0b080 {
compatible = "allwinner,sun4i-a10-mdio"; compatible = "allwinner,sun4i-a10-mdio";
reg = <0x01c0b080 0x14>; reg = <0x01c0b080 0x14>;
#address-cells = <1>; #address-cells = <1>;
...@@ -18,7 +18,7 @@ mdio@01c0b080 { ...@@ -18,7 +18,7 @@ mdio@01c0b080 {
And at the board level: And at the board level:
mdio@01c0b080 { mdio@1c0b080 {
phy-supply = <&reg_emac_3v3>; phy-supply = <&reg_emac_3v3>;
phy0: ethernet-phy@0 { phy0: ethernet-phy@0 {
......
...@@ -15,7 +15,7 @@ Optional properties: ...@@ -15,7 +15,7 @@ Optional properties:
Examples: Examples:
gmac: ethernet@01c50000 { gmac: ethernet@1c50000 {
compatible = "allwinner,sun7i-a20-gmac"; compatible = "allwinner,sun7i-a20-gmac";
reg = <0x01c50000 0x10000>, reg = <0x01c50000 0x10000>,
<0x01c20164 0x4>; <0x01c20164 0x4>;
......
...@@ -109,7 +109,7 @@ ethernet@f0ba0000 { ...@@ -109,7 +109,7 @@ ethernet@f0ba0000 {
reg = <0xf0ba0000 0xfc4c>; reg = <0xf0ba0000 0xfc4c>;
interrupts = <0x0 0x18 0x0>, <0x0 0x19 0x0>; interrupts = <0x0 0x18 0x0>, <0x0 0x19 0x0>;
mdio@0e14 { mdio@e14 {
compatible = "brcm,genet-mdio-v4"; compatible = "brcm,genet-mdio-v4";
#address-cells = <0x1>; #address-cells = <0x1>;
#size-cells = <0x0>; #size-cells = <0x0>;
......
...@@ -45,7 +45,7 @@ Required properties: ...@@ -45,7 +45,7 @@ Required properties:
Example: Example:
SoC dtsi: SoC dtsi:
m_can1: can@020e8000 { m_can1: can@20e8000 {
compatible = "bosch,m_can"; compatible = "bosch,m_can";
reg = <0x020e8000 0x4000>, <0x02298000 0x4000>; reg = <0x020e8000 0x4000>, <0x02298000 0x4000>;
reg-names = "m_can", "message_ram"; reg-names = "m_can", "message_ram";
......
...@@ -19,7 +19,7 @@ SoC common .dtsi file: ...@@ -19,7 +19,7 @@ SoC common .dtsi file:
allwinner,pull = <0>; allwinner,pull = <0>;
}; };
... ...
can0: can@01c2bc00 { can0: can@1c2bc00 {
compatible = "allwinner,sun4i-a10-can"; compatible = "allwinner,sun4i-a10-can";
reg = <0x01c2bc00 0x400>; reg = <0x01c2bc00 0x400>;
interrupts = <0 26 4>; interrupts = <0 26 4>;
...@@ -29,7 +29,7 @@ SoC common .dtsi file: ...@@ -29,7 +29,7 @@ SoC common .dtsi file:
Board specific .dts file: Board specific .dts file:
can0: can@01c2bc00 { can0: can@1c2bc00 {
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&can0_pins_a>; pinctrl-0 = <&can0_pins_a>;
status = "okay"; status = "okay";
......
...@@ -20,7 +20,7 @@ Optional properties: ...@@ -20,7 +20,7 @@ Optional properties:
Example: Example:
mmc3: mmc@01c12000 { mmc3: mmc@1c12000 {
#address-cells = <1>; #address-cells = <1>;
#size-cells = <0>; #size-cells = <0>;
......
...@@ -13,13 +13,13 @@ Are child nodes of qfprom, bindings of which as described in ...@@ -13,13 +13,13 @@ Are child nodes of qfprom, bindings of which as described in
bindings/nvmem/nvmem.txt bindings/nvmem/nvmem.txt
Example for sun4i: Example for sun4i:
sid@01c23800 { sid@1c23800 {
compatible = "allwinner,sun4i-a10-sid"; compatible = "allwinner,sun4i-a10-sid";
reg = <0x01c23800 0x10> reg = <0x01c23800 0x10>
}; };
Example for sun7i: Example for sun7i:
sid@01c23800 { sid@1c23800 {
compatible = "allwinner,sun7i-a20-sid"; compatible = "allwinner,sun7i-a20-sid";
reg = <0x01c23800 0x200> reg = <0x01c23800 0x200>
}; };
...@@ -10,7 +10,7 @@ Required Properties: ...@@ -10,7 +10,7 @@ Required Properties:
Example: Example:
otp: otp@0301c800 { otp: otp@301c800 {
compatible = "brcm,ocotp"; compatible = "brcm,ocotp";
reg = <0x0301c800 0x2c>; reg = <0x0301c800 0x2c>;
brcm,ocotp-size = <2048>; brcm,ocotp-size = <2048>;
......
...@@ -19,7 +19,7 @@ Optional properties: ...@@ -19,7 +19,7 @@ Optional properties:
Example: Example:
ocotp: ocotp@021bc000 { ocotp: ocotp@21bc000 {
compatible = "fsl,imx6q-ocotp", "syscon"; compatible = "fsl,imx6q-ocotp", "syscon";
reg = <0x021bc000 0x4000>; reg = <0x021bc000 0x4000>;
clocks = <&clks IMX6QDL_CLK_IIM>; clocks = <&clks IMX6QDL_CLK_IIM>;
......
...@@ -33,7 +33,7 @@ bits: Is pair of bit location and number of bits, which specifies offset ...@@ -33,7 +33,7 @@ bits: Is pair of bit location and number of bits, which specifies offset
For example: For example:
/* Provider */ /* Provider */
qfprom: qfprom@00700000 { qfprom: qfprom@700000 {
... ...
/* Data cells */ /* Data cells */
......
...@@ -12,7 +12,7 @@ bindings/nvmem/nvmem.txt ...@@ -12,7 +12,7 @@ bindings/nvmem/nvmem.txt
Example: Example:
qfprom: qfprom@00700000 { qfprom: qfprom@700000 {
compatible = "qcom,qfprom"; compatible = "qcom,qfprom";
reg = <0x00700000 0x8000>; reg = <0x00700000 0x8000>;
... ...
......
...@@ -255,7 +255,7 @@ Tegra30: ...@@ -255,7 +255,7 @@ Tegra30:
SoC DTSI: SoC DTSI:
pcie-controller@00003000 { pcie-controller@3000 {
compatible = "nvidia,tegra30-pcie"; compatible = "nvidia,tegra30-pcie";
device_type = "pci"; device_type = "pci";
reg = <0x00003000 0x00000800 /* PADS registers */ reg = <0x00003000 0x00000800 /* PADS registers */
...@@ -334,7 +334,7 @@ SoC DTSI: ...@@ -334,7 +334,7 @@ SoC DTSI:
Board DTS: Board DTS:
pcie-controller@00003000 { pcie-controller@3000 {
status = "okay"; status = "okay";
avdd-pexa-supply = <&ldo1_reg>; avdd-pexa-supply = <&ldo1_reg>;
...@@ -360,7 +360,7 @@ Tegra124: ...@@ -360,7 +360,7 @@ Tegra124:
SoC DTSI: SoC DTSI:
pcie-controller@01003000 { pcie-controller@1003000 {
compatible = "nvidia,tegra124-pcie"; compatible = "nvidia,tegra124-pcie";
device_type = "pci"; device_type = "pci";
reg = <0x0 0x01003000 0x0 0x00000800 /* PADS registers */ reg = <0x0 0x01003000 0x0 0x00000800 /* PADS registers */
...@@ -425,7 +425,7 @@ SoC DTSI: ...@@ -425,7 +425,7 @@ SoC DTSI:
Board DTS: Board DTS:
pcie-controller@01003000 { pcie-controller@1003000 {
status = "okay"; status = "okay";
avddio-pex-supply = <&vdd_1v05_run>; avddio-pex-supply = <&vdd_1v05_run>;
...@@ -456,7 +456,7 @@ Tegra210: ...@@ -456,7 +456,7 @@ Tegra210:
SoC DTSI: SoC DTSI:
pcie-controller@01003000 { pcie-controller@1003000 {
compatible = "nvidia,tegra210-pcie"; compatible = "nvidia,tegra210-pcie";
device_type = "pci"; device_type = "pci";
reg = <0x0 0x01003000 0x0 0x00000800 /* PADS registers */ reg = <0x0 0x01003000 0x0 0x00000800 /* PADS registers */
...@@ -521,7 +521,7 @@ SoC DTSI: ...@@ -521,7 +521,7 @@ SoC DTSI:
Board DTS: Board DTS:
pcie-controller@01003000 { pcie-controller@1003000 {
status = "okay"; status = "okay";
avdd-pll-uerefe-supply = <&avdd_1v05_pll>; avdd-pll-uerefe-supply = <&avdd_1v05_pll>;
......
...@@ -15,7 +15,7 @@ Required properties For the child node: ...@@ -15,7 +15,7 @@ Required properties For the child node:
- #phy-cells: must be 0 - #phy-cells: must be 0
Example: Example:
pcie_phy: phy@0301d0a0 { pcie_phy: phy@301d0a0 {
compatible = "brcm,cygnus-pcie-phy"; compatible = "brcm,cygnus-pcie-phy";
reg = <0x0301d0a0 0x14>; reg = <0x0301d0a0 0x14>;
......
...@@ -23,7 +23,7 @@ Optional properties: ...@@ -23,7 +23,7 @@ Optional properties:
the 17.78mA TX reference current. Default: 100 the 17.78mA TX reference current. Default: 100
Example: Example:
usbphy1: usbphy@020c9000 { usbphy1: usbphy@20c9000 {
compatible = "fsl,imx6q-usbphy", "fsl,imx23-usbphy"; compatible = "fsl,imx6q-usbphy", "fsl,imx23-usbphy";
reg = <0x020c9000 0x1000>; reg = <0x020c9000 0x1000>;
interrupts = <0 44 0x04>; interrupts = <0 44 0x04>;
......
...@@ -25,7 +25,7 @@ It is recommended to list all clocks and resets available. ...@@ -25,7 +25,7 @@ It is recommended to list all clocks and resets available.
The driver will only use those matching the phy_type. The driver will only use those matching the phy_type.
Example: Example:
usbphy1: phy@00a01800 { usbphy1: phy@a01800 {
compatible = "allwinner,sun9i-a80-usb-phy"; compatible = "allwinner,sun9i-a80-usb-phy";
reg = <0x00a01800 0x4>; reg = <0x00a01800 0x4>;
clocks = <&usb_phy_clk 2>, <&usb_phy_clk 10>, clocks = <&usb_phy_clk 2>, <&usb_phy_clk 10>,
......
...@@ -89,7 +89,7 @@ Optional subnode-properties: ...@@ -89,7 +89,7 @@ Optional subnode-properties:
Examples: Examples:
pio: pinctrl@01c20800 { pio: pinctrl@1c20800 {
compatible = "allwinner,sun5i-a13-pinctrl"; compatible = "allwinner,sun5i-a13-pinctrl";
reg = <0x01c20800 0x400>; reg = <0x01c20800 0x400>;
#address-cells = <1>; #address-cells = <1>;
......
...@@ -58,14 +58,14 @@ Some requirements for using fsl,imx-pinctrl binding: ...@@ -58,14 +58,14 @@ Some requirements for using fsl,imx-pinctrl binding:
configurations by referring to the phandle of that pin configuration node. configurations by referring to the phandle of that pin configuration node.
Examples: Examples:
usdhc@0219c000 { /* uSDHC4 */ usdhc@219c000 { /* uSDHC4 */
non-removable; non-removable;
vmmc-supply = <&reg_3p3v>; vmmc-supply = <&reg_3p3v>;
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc4_1>; pinctrl-0 = <&pinctrl_usdhc4_1>;
}; };
iomuxc@020e0000 { iomuxc@20e0000 {
compatible = "fsl,imx6q-iomuxc"; compatible = "fsl,imx6q-iomuxc";
reg = <0x020e0000 0x4000>; reg = <0x020e0000 0x4000>;
......
...@@ -89,7 +89,7 @@ Valid values for pin and group names are: ...@@ -89,7 +89,7 @@ Valid values for pin and group names are:
Example: Example:
pinctrl_pdc: pinctrl@02006500 { pinctrl_pdc: pinctrl@2006500 {
#gpio-range-cells = <3>; #gpio-range-cells = <3>;
compatible = "img,tz1090-pdc-pinctrl"; compatible = "img,tz1090-pdc-pinctrl";
reg = <0x02006500 0x100>; reg = <0x02006500 0x100>;
...@@ -121,7 +121,7 @@ Example board file extracts: ...@@ -121,7 +121,7 @@ Example board file extracts:
}; };
}; };
ir: ir@02006200 { ir: ir@2006200 {
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&irmod_default>; pinctrl-0 = <&irmod_default>;
}; };
...@@ -197,7 +197,7 @@ Valid values for pin and group names are: ...@@ -197,7 +197,7 @@ Valid values for pin and group names are:
Example: Example:
pinctrl: pinctrl@02005800 { pinctrl: pinctrl@2005800 {
#gpio-range-cells = <3>; #gpio-range-cells = <3>;
compatible = "img,tz1090-pinctrl"; compatible = "img,tz1090-pinctrl";
reg = <0x02005800 0xe4>; reg = <0x02005800 0xe4>;
...@@ -221,7 +221,7 @@ Example board file extract: ...@@ -221,7 +221,7 @@ Example board file extract:
}; };
}; };
uart@02004b00 { uart@2004b00 {
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&uart0_default>; pinctrl-0 = <&uart0_default>;
}; };
...@@ -97,7 +97,7 @@ SoC file extract: ...@@ -97,7 +97,7 @@ SoC file extract:
Board file extract: Board file extract:
------------------- -------------------
pcie-controller@01003000 { pcie-controller@1003000 {
... ...
phys = <&padctl 0>; phys = <&padctl 0>;
......
...@@ -86,7 +86,7 @@ Examples: ...@@ -86,7 +86,7 @@ Examples:
reg = <0 0x1020C020 0 0x1000>; reg = <0 0x1020C020 0 0x1000>;
}; };
pinctrl@01c20800 { pinctrl@1c20800 {
compatible = "mediatek,mt8135-pinctrl"; compatible = "mediatek,mt8135-pinctrl";
reg = <0 0x1000B000 0 0x1000>; reg = <0 0x1000B000 0 0x1000>;
mediatek,pctl-regmap = <&syscfg_pctl_a &syscfg_pctl_b>; mediatek,pctl-regmap = <&syscfg_pctl_a &syscfg_pctl_b>;
......
...@@ -89,7 +89,7 @@ Example: ...@@ -89,7 +89,7 @@ Example:
interrupt-names = "irqmux"; interrupt-names = "irqmux";
ranges = <0 0x09610000 0x6000>; ranges = <0 0x09610000 0x6000>;
pio0: gpio@09610000 { pio0: gpio@9610000 {
gpio-controller; gpio-controller;
#gpio-cells = <2>; #gpio-cells = <2>;
interrupt-controller; interrupt-controller;
......
...@@ -175,7 +175,7 @@ to specify in a pin configuration subnode: ...@@ -175,7 +175,7 @@ to specify in a pin configuration subnode:
Example: Example:
tlmm: pinctrl@01010000 { tlmm: pinctrl@1010000 {
compatible = "qcom,msm8996-pinctrl"; compatible = "qcom,msm8996-pinctrl";
reg = <0x01010000 0x300000>; reg = <0x01010000 0x300000>;
interrupts = <0 208 0>; interrupts = <0 208 0>;
......
...@@ -40,7 +40,7 @@ Optional properties: ...@@ -40,7 +40,7 @@ Optional properties:
Example: Example:
gpc: gpc@020dc000 { gpc: gpc@20dc000 {
compatible = "fsl,imx6q-gpc"; compatible = "fsl,imx6q-gpc";
reg = <0x020dc000 0x4000>; reg = <0x020dc000 0x4000>;
interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>, interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>,
...@@ -80,7 +80,7 @@ that is a phandle pointing to the power domain the device belongs to. ...@@ -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: Example of a device that is part of the PU power domain:
vpu: vpu@02040000 { vpu: vpu@2040000 {
reg = <0x02040000 0x3c000>; reg = <0x02040000 0x3c000>;
/* ... */ /* ... */
power-domains = <&pd_pu>; power-domains = <&pd_pu>;
......
...@@ -10,7 +10,7 @@ Required Properties: ...@@ -10,7 +10,7 @@ Required Properties:
-reg: Specifies the physical address of the SNVS_LPCR register -reg: Specifies the physical address of the SNVS_LPCR register
Example: Example:
snvs@020cc000 { snvs@20cc000 {
compatible = "fsl,sec-v4.0-mon", "simple-bus"; compatible = "fsl,sec-v4.0-mon", "simple-bus";
#address-cells = <1>; #address-cells = <1>;
#size-cells = <1>; #size-cells = <1>;
......
...@@ -37,12 +37,12 @@ Example 1: ...@@ -37,12 +37,12 @@ Example 1:
Setup keystone reset so that in case software reset or Setup keystone reset so that in case software reset or
WDT0 is triggered it issues hard reset for SoC. WDT0 is triggered it issues hard reset for SoC.
pllctrl: pll-controller@02310000 { pllctrl: pll-controller@2310000 {
compatible = "ti,keystone-pllctrl", "syscon"; compatible = "ti,keystone-pllctrl", "syscon";
reg = <0x02310000 0x200>; reg = <0x02310000 0x200>;
}; };
devctrl: device-state-control@02620000 { devctrl: device-state-control@2620000 {
compatible = "ti,keystone-devctrl", "syscon"; compatible = "ti,keystone-devctrl", "syscon";
reg = <0x02620000 0x1000>; reg = <0x02620000 0x1000>;
}; };
......
...@@ -8,7 +8,7 @@ Required properties: ...@@ -8,7 +8,7 @@ Required properties:
Example: Example:
mcu@0a { mcu@a {
#gpio-cells = <2>; #gpio-cells = <2>;
compatible = "fsl,mc9s08qg8-mpc8349emitx", compatible = "fsl,mc9s08qg8-mpc8349emitx",
"fsl,mcu-mpc8349emitx"; "fsl,mcu-mpc8349emitx";
......
...@@ -14,7 +14,7 @@ Required properties: ...@@ -14,7 +14,7 @@ Required properties:
Example: Example:
pwm: pwm@01c20e00 { pwm: pwm@1c20e00 {
compatible = "allwinner,sun7i-a20-pwm"; compatible = "allwinner,sun7i-a20-pwm";
reg = <0x01c20e00 0xc>; reg = <0x01c20e00 0xc>;
clocks = <&osc24M>; clocks = <&osc24M>;
......
...@@ -40,7 +40,7 @@ to get matched with their hardware counterparts as follow: ...@@ -40,7 +40,7 @@ to get matched with their hardware counterparts as follow:
Example: Example:
max77686: pmic@09 { max77686: pmic@9 {
compatible = "maxim,max77686"; compatible = "maxim,max77686";
interrupt-parent = <&wakeup_eint>; interrupt-parent = <&wakeup_eint>;
interrupts = <26 IRQ_TYPE_NONE>; interrupts = <26 IRQ_TYPE_NONE>;
......
...@@ -71,7 +71,7 @@ has not been disabled for that state using "regulator-off-in-suspend". ...@@ -71,7 +71,7 @@ has not been disabled for that state using "regulator-off-in-suspend".
Example: Example:
max77802@09 { max77802@9 {
compatible = "maxim,max77802"; compatible = "maxim,max77802";
interrupt-parent = <&wakeup_eint>; interrupt-parent = <&wakeup_eint>;
interrupts = <26 0>; interrupts = <26 0>;
......
...@@ -14,7 +14,7 @@ Required properties: ...@@ -14,7 +14,7 @@ Required properties:
example: example:
ahb1_rst: reset@01c202c0 { ahb1_rst: reset@1c202c0 {
#reset-cells = <1>; #reset-cells = <1>;
compatible = "allwinner,sun6i-a31-ahb1-reset"; compatible = "allwinner,sun6i-a31-ahb1-reset";
reg = <0x01c202c0 0xc>; reg = <0x01c202c0 0xc>;
......
...@@ -14,7 +14,7 @@ Required properties: ...@@ -14,7 +14,7 @@ Required properties:
example: example:
src: src@020d8000 { src: src@20d8000 {
compatible = "fsl,imx6q-src"; compatible = "fsl,imx6q-src";
reg = <0x020d8000 0x4000>; reg = <0x020d8000 0x4000>;
interrupts = <0 91 0x04 0 96 0x04>; interrupts = <0 91 0x04 0 96 0x04>;
...@@ -33,10 +33,10 @@ reset.txt ...@@ -33,10 +33,10 @@ reset.txt
example: example:
ipu1: ipu@02400000 { ipu1: ipu@2400000 {
resets = <&src 2>; resets = <&src 2>;
}; };
ipu2: ipu@02800000 { ipu2: ipu@2800000 {
resets = <&src 4>; resets = <&src 4>;
}; };
......
...@@ -67,7 +67,7 @@ using the syscon node, and a consumer (a DSP device) on the TI Keystone 2 ...@@ -67,7 +67,7 @@ using the syscon node, and a consumer (a DSP device) on the TI Keystone 2
/ { / {
soc { soc {
psc: power-sleep-controller@02350000 { psc: power-sleep-controller@2350000 {
compatible = "syscon", "simple-mfd"; compatible = "syscon", "simple-mfd";
reg = <0x02350000 0x1000>; reg = <0x02350000 0x1000>;
......
* 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>;
};
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>;
};
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>;
};
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>;
};
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>;
};
...@@ -17,7 +17,7 @@ Required properties for new device trees ...@@ -17,7 +17,7 @@ Required properties for new device trees
Example: Example:
rtc: rtc@01f00000 { rtc: rtc@1f00000 {
compatible = "allwinner,sun6i-a31-rtc"; compatible = "allwinner,sun6i-a31-rtc";
reg = <0x01f00000 0x54>; reg = <0x01f00000 0x54>;
interrupts = <0 40 4>, <0 41 4>; interrupts = <0 40 4>, <0 41 4>;
......
...@@ -10,7 +10,7 @@ Required properties: ...@@ -10,7 +10,7 @@ Required properties:
Example: Example:
rtc: rtc@01c20d00 { rtc: rtc@1c20d00 {
compatible = "allwinner,sun4i-a10-rtc"; compatible = "allwinner,sun4i-a10-rtc";
reg = <0x01c20d00 0x20>; reg = <0x01c20d00 0x20>;
interrupts = <24>; interrupts = <24>;
......
...@@ -18,7 +18,7 @@ par_io@1400 { ...@@ -18,7 +18,7 @@ par_io@1400 {
#size-cells = <0>; #size-cells = <0>;
device_type = "par_io"; device_type = "par_io";
num-ports = <7>; num-ports = <7>;
ucc_pin@01 { ucc_pin@1 {
...... ......
}; };
......
...@@ -26,7 +26,7 @@ Required properties: ...@@ -26,7 +26,7 @@ Required properties:
interrupts. interrupts.
Example: Example:
ucc_pin@01 { ucc_pin@1 {
pio-map = < pio-map = <
/* port pin dir open_drain assignment has_irq */ /* port pin dir open_drain assignment has_irq */
0 3 1 0 1 0 /* TxD0 */ 0 3 1 0 1 0 /* TxD0 */
......
...@@ -51,7 +51,7 @@ of valid identifiers for k2g. ...@@ -51,7 +51,7 @@ of valid identifiers for k2g.
Example (K2G): Example (K2G):
-------------------- --------------------
uart0: serial@02530c00 { uart0: serial@2530c00 {
compatible = "ns16550a"; compatible = "ns16550a";
... ...
power-domains = <&k2g_pds 0x002c>; power-domains = <&k2g_pds 0x002c>;
......
...@@ -9,7 +9,7 @@ Required properties: ...@@ -9,7 +9,7 @@ Required properties:
Examples: Examples:
i2s0: xtfpga-i2s@0d080000 { i2s0: xtfpga-i2s@d080000 {
#sound-dai-cells = <0>; #sound-dai-cells = <0>;
compatible = "cdns,xtfpga-i2s"; compatible = "cdns,xtfpga-i2s";
reg = <0x0d080000 0x40>; reg = <0x0d080000 0x40>;
......
...@@ -41,7 +41,7 @@ Required properties: ...@@ -41,7 +41,7 @@ Required properties:
Example: Example:
asrc: asrc@02034000 { asrc: asrc@2034000 {
compatible = "fsl,imx53-asrc"; compatible = "fsl,imx53-asrc";
reg = <0x02034000 0x4000>; reg = <0x02034000 0x4000>;
interrupts = <0 50 IRQ_TYPE_LEVEL_HIGH>; interrupts = <0 50 IRQ_TYPE_LEVEL_HIGH>;
......
...@@ -48,7 +48,7 @@ Required properties: ...@@ -48,7 +48,7 @@ Required properties:
Example: Example:
esai: esai@02024000 { esai: esai@2024000 {
compatible = "fsl,imx35-esai"; compatible = "fsl,imx35-esai";
reg = <0x02024000 0x4000>; reg = <0x02024000 0x4000>;
interrupts = <0 51 0x04>; interrupts = <0 51 0x04>;
......
...@@ -39,7 +39,7 @@ Required properties: ...@@ -39,7 +39,7 @@ Required properties:
Example: Example:
spdif: spdif@02004000 { spdif: spdif@2004000 {
compatible = "fsl,imx35-spdif"; compatible = "fsl,imx35-spdif";
reg = <0x02004000 0x4000>; reg = <0x02004000 0x4000>;
interrupts = <0 52 0x04>; interrupts = <0 52 0x04>;
......
...@@ -22,7 +22,7 @@ Required properties of optional child nodes: ...@@ -22,7 +22,7 @@ Required properties of optional child nodes:
Example: Example:
audmux@021d8000 { audmux@21d8000 {
compatible = "fsl,imx6q-audmux", "fsl,imx31-audmux"; compatible = "fsl,imx6q-audmux", "fsl,imx31-audmux";
reg = <0x021d8000 0x4000>; reg = <0x021d8000 0x4000>;
}; };
...@@ -63,7 +63,7 @@ Optional SoC Specific Properties: ...@@ -63,7 +63,7 @@ Optional SoC Specific Properties:
Example: Example:
i2s0: i2s@03830000 { i2s0: i2s@3830000 {
compatible = "samsung,s5pv210-i2s"; compatible = "samsung,s5pv210-i2s";
reg = <0x03830000 0x100>; reg = <0x03830000 0x100>;
dmas = <&pdma0 10 dmas = <&pdma0 10
......
...@@ -62,7 +62,7 @@ Required properties for the following compatibles: ...@@ -62,7 +62,7 @@ Required properties for the following compatibles:
block in the PRCM. block in the PRCM.
Example: Example:
codec: codec@01c22c00 { codec: codec@1c22c00 {
#sound-dai-cells = <0>; #sound-dai-cells = <0>;
compatible = "allwinner,sun7i-a20-codec"; compatible = "allwinner,sun7i-a20-codec";
reg = <0x01c22c00 0x40>; reg = <0x01c22c00 0x40>;
...@@ -73,7 +73,7 @@ codec: codec@01c22c00 { ...@@ -73,7 +73,7 @@ codec: codec@01c22c00 {
dma-names = "rx", "tx"; dma-names = "rx", "tx";
}; };
codec: codec@01c22c00 { codec: codec@1c22c00 {
#sound-dai-cells = <0>; #sound-dai-cells = <0>;
compatible = "allwinner,sun6i-a31-codec"; compatible = "allwinner,sun6i-a31-codec";
reg = <0x01c22c00 0x98>; reg = <0x01c22c00 0x98>;
......
...@@ -28,7 +28,7 @@ Required properties for the following compatibles: ...@@ -28,7 +28,7 @@ Required properties for the following compatibles:
Example: Example:
i2s0: i2s@01c22400 { i2s0: i2s@1c22400 {
#sound-dai-cells = <0>; #sound-dai-cells = <0>;
compatible = "allwinner,sun4i-a10-i2s"; compatible = "allwinner,sun4i-a10-i2s";
reg = <0x01c22400 0x400>; reg = <0x01c22400 0x400>;
......
...@@ -48,7 +48,7 @@ are similar to A33 using simple-card: ...@@ -48,7 +48,7 @@ are similar to A33 using simple-card:
sound-dai = <&codec>; sound-dai = <&codec>;
}; };
soc@01c00000 { soc@1c00000 {
[...] [...]
audio-codec@1c22e00 { audio-codec@1c22e00 {
......
...@@ -10,7 +10,7 @@ Required properties if not a sub-node of the PRCM node: ...@@ -10,7 +10,7 @@ Required properties if not a sub-node of the PRCM node:
- reg: must contain the registers location and length - reg: must contain the registers location and length
Example: Example:
prcm: prcm@01f01400 { prcm: prcm@1f01400 {
codec_analog: codec-analog { codec_analog: codec-analog {
compatible = "allwinner,sun8i-a23-codec-analog"; compatible = "allwinner,sun8i-a23-codec-analog";
}; };
......
...@@ -31,7 +31,7 @@ Required properties: ...@@ -31,7 +31,7 @@ Required properties:
Example: Example:
spdif: spdif@01c21000 { spdif: spdif@1c21000 {
compatible = "allwinner,sun4i-a10-spdif"; compatible = "allwinner,sun4i-a10-spdif";
reg = <0x01c21000 0x40>; reg = <0x01c21000 0x40>;
interrupts = <13>; interrupts = <13>;
......
...@@ -16,7 +16,7 @@ please check: ...@@ -16,7 +16,7 @@ please check:
* dma/dma.txt * dma/dma.txt
Example: Example:
spdif0: spdif0@0b004000 { spdif0: spdif0@b004000 {
compatible = "zte,zx296702-spdif"; compatible = "zte,zx296702-spdif";
reg = <0x0b004000 0x1000>; reg = <0x0b004000 0x1000>;
clocks = <&lsp0clk ZX296702_SPDIF0_DIV>; clocks = <&lsp0clk ZX296702_SPDIF0_DIV>;
......
...@@ -12,7 +12,7 @@ Required properties: ...@@ -12,7 +12,7 @@ Required properties:
Example: Example:
spi1: spi@01c06000 { spi1: spi@1c06000 {
compatible = "allwinner,sun4i-a10-spi"; compatible = "allwinner,sun4i-a10-spi";
reg = <0x01c06000 0x1000>; reg = <0x01c06000 0x1000>;
interrupts = <11>; interrupts = <11>;
......
...@@ -19,7 +19,7 @@ Optional properties: ...@@ -19,7 +19,7 @@ Optional properties:
Example: Example:
spi1: spi@01c69000 { spi1: spi@1c69000 {
compatible = "allwinner,sun6i-a31-spi"; compatible = "allwinner,sun6i-a31-spi";
reg = <0x01c69000 0x1000>; reg = <0x01c69000 0x1000>;
interrupts = <0 66 4>; interrupts = <0 66 4>;
...@@ -28,7 +28,7 @@ spi1: spi@01c69000 { ...@@ -28,7 +28,7 @@ spi1: spi@01c69000 {
resets = <&ahb1_rst 21>; resets = <&ahb1_rst 21>;
}; };
spi0: spi@01c68000 { spi0: spi@1c68000 {
compatible = "allwinner,sun8i-h3-spi"; compatible = "allwinner,sun8i-h3-spi";
reg = <0x01c68000 0x1000>; reg = <0x01c68000 0x1000>;
interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>; interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
......
...@@ -19,7 +19,7 @@ found in Documentation/devicetree/bindings/sram/sram.txt ...@@ -19,7 +19,7 @@ found in Documentation/devicetree/bindings/sram/sram.txt
Example: Example:
sysram@02020000 { sysram@2020000 {
compatible = "mmio-sram"; compatible = "mmio-sram";
reg = <0x02020000 0x54000>; reg = <0x02020000 0x54000>;
#address-cells = <1>; #address-cells = <1>;
......
...@@ -47,7 +47,7 @@ This valid values for this argument are: ...@@ -47,7 +47,7 @@ This valid values for this argument are:
Example Example
------- -------
sram-controller@01c00000 { sram-controller@1c00000 {
compatible = "allwinner,sun4i-a10-sram-controller"; compatible = "allwinner,sun4i-a10-sram-controller";
reg = <0x01c00000 0x30>; reg = <0x01c00000 0x30>;
#address-cells = <1>; #address-cells = <1>;
...@@ -68,7 +68,7 @@ sram-controller@01c00000 { ...@@ -68,7 +68,7 @@ sram-controller@01c00000 {
}; };
}; };
emac: ethernet@01c0b000 { emac: ethernet@1c0b000 {
compatible = "allwinner,sun4i-a10-emac"; compatible = "allwinner,sun4i-a10-emac";
... ...
......
...@@ -14,7 +14,7 @@ Optional properties: ...@@ -14,7 +14,7 @@ Optional properties:
Example: Example:
timer@01c60000 { timer@1c60000 {
compatible = "allwinner,sun7i-a20-hstimer"; compatible = "allwinner,sun7i-a20-hstimer";
reg = <0x01c60000 0x1000>; reg = <0x01c60000 0x1000>;
interrupts = <0 51 1>, interrupts = <0 51 1>,
......
...@@ -36,11 +36,9 @@ atmel,at97sc3204t i2c trusted platform module (TPM) ...@@ -36,11 +36,9 @@ atmel,at97sc3204t i2c trusted platform module (TPM)
capella,cm32181 CM32181: Ambient Light Sensor capella,cm32181 CM32181: Ambient Light Sensor
capella,cm3232 CM3232: Ambient Light Sensor capella,cm3232 CM3232: Ambient Light Sensor
cirrus,cs42l51 Cirrus Logic CS42L51 audio codec 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,ds1374 I2C, 32-Bit Binary Counter Watchdog RTC with Trickle Charger and Reset Input/Output
dallas,ds1631 High-Precision Digital Thermometer dallas,ds1631 High-Precision Digital Thermometer
dallas,ds1672 Dallas DS1672 Real-time Clock
dallas,ds1682 Total-Elapsed-Time Recorder with Alarm dallas,ds1682 Total-Elapsed-Time Recorder with Alarm
dallas,ds1775 Tiny Digital Thermometer and Thermostat dallas,ds1775 Tiny Digital Thermometer and Thermostat
dallas,ds3232 Extremely Accurate I²C RTC with Integrated Crystal and SRAM 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 ...@@ -54,8 +52,8 @@ dlg,da9063 DA9063: system PMIC for quad-core application processors
domintech,dmard09 DMARD09: 3-axis Accelerometer domintech,dmard09 DMARD09: 3-axis Accelerometer
domintech,dmard10 DMARD10: 3-axis Accelerometer domintech,dmard10 DMARD10: 3-axis Accelerometer
epson,rx8010 I2C-BUS INTERFACE REAL TIME CLOCK MODULE 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 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,mag3110 MAG3110: Xtrinsic High Accuracy, 3D Magnetometer
fsl,mc13892 MC13892: Power Management Integrated Circuit (PMIC) for i.MX35/51 fsl,mc13892 MC13892: Power Management Integrated Circuit (PMIC) for i.MX35/51
fsl,mma7660 MMA7660FC: 3-Axis Orientation/Motion Detection Sensor 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 ...@@ -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,slb9635tt Infineon SLB9635 (Soft-) I2C TPM (old protocol, max 100khz)
infineon,slb9645tt Infineon SLB9645 I2C TPM (new protocol, max 400khz) infineon,slb9645tt Infineon SLB9645 I2C TPM (new protocol, max 400khz)
isil,isl1208 Intersil ISL1208 Low Power RTC with Battery Backed SRAM 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,isl29028 Intersil ISL29028 Ambient Light and Proximity Sensor
isil,isl29030 Intersil ISL29030 Ambient Light and Proximity Sensor isil,isl29030 Intersil ISL29030 Ambient Light and Proximity Sensor
maxim,ds1050 5 Bit Programmable, Pulse-Width Modulator maxim,ds1050 5 Bit Programmable, Pulse-Width Modulator
...@@ -156,6 +156,7 @@ nxp,pca9556 Octal SMBus and I2C registered interface ...@@ -156,6 +156,7 @@ nxp,pca9556 Octal SMBus and I2C registered interface
nxp,pca9557 8-bit I2C-bus and SMBus I/O port with reset nxp,pca9557 8-bit I2C-bus and SMBus I/O port with reset
nxp,pcf2127 Real-time clock nxp,pcf2127 Real-time clock
nxp,pcf2129 Real-time clock nxp,pcf2129 Real-time clock
nxp,pcf8523 Real-time Clock
nxp,pcf8563 Real-time clock/calendar nxp,pcf8563 Real-time clock/calendar
nxp,pcf85063 Tiny Real-Time Clock nxp,pcf85063 Tiny Real-Time Clock
oki,ml86v7667 OKI ML86V7667 video decoder oki,ml86v7667 OKI ML86V7667 video decoder
...@@ -175,10 +176,6 @@ sii,s35390a 2-wire CMOS real-time clock ...@@ -175,10 +176,6 @@ sii,s35390a 2-wire CMOS real-time clock
silabs,si7020 Relative Humidity and Temperature Sensors silabs,si7020 Relative Humidity and Temperature Sensors
skyworks,sky81452 Skyworks SKY81452: Six-Channel White LED Driver with Touch Panel Bias Supply skyworks,sky81452 Skyworks SKY81452: Six-Channel White LED Driver with Touch Panel Bias Supply
st,24c256 i2c serial eeprom (24cxx) 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 taos,tsl2550 Ambient Light Sensor with SMBUS/Two Wire Serial Interface
ti,ads7828 8-Channels, 12-bit ADC ti,ads7828 8-Channels, 12-bit ADC
ti,ads7830 8-Channels, 8-bit ADC ti,ads7830 8-Channels, 8-bit ADC
......
...@@ -16,7 +16,7 @@ Required properties: ...@@ -16,7 +16,7 @@ Required properties:
Example: Example:
usb_otg: usb@01c13000 { usb_otg: usb@1c13000 {
compatible = "allwinner,sun4i-a10-musb"; compatible = "allwinner,sun4i-a10-musb";
reg = <0x01c13000 0x0400>; reg = <0x01c13000 0x0400>;
clocks = <&ahb_gates 0>; clocks = <&ahb_gates 0>;
......
...@@ -181,7 +181,7 @@ usb: usb@47400000 { ...@@ -181,7 +181,7 @@ usb: usb@47400000 {
"tx14", "tx15"; "tx14", "tx15";
}; };
cppi41dma: dma-controller@07402000 { cppi41dma: dma-controller@7402000 {
compatible = "ti,am3359-cppi41"; compatible = "ti,am3359-cppi41";
reg = <0x47400000 0x1000 reg = <0x47400000 0x1000
0x47402000 0x1000 0x47402000 0x1000
......
...@@ -18,7 +18,7 @@ Required properties: ...@@ -18,7 +18,7 @@ Required properties:
- atmel,oc-gpio: If present, specifies a gpio that needs to be - atmel,oc-gpio: If present, specifies a gpio that needs to be
activated for the overcurrent detection. activated for the overcurrent detection.
usb0: ohci@00500000 { usb0: ohci@500000 {
compatible = "atmel,at91rm9200-ohci", "usb-ohci"; compatible = "atmel,at91rm9200-ohci", "usb-ohci";
reg = <0x00500000 0x100000>; reg = <0x00500000 0x100000>;
clocks = <&uhphs_clk>, <&uhphs_clk>, <&uhpck>; clocks = <&uhphs_clk>, <&uhphs_clk>, <&uhpck>;
...@@ -39,7 +39,7 @@ Required properties: ...@@ -39,7 +39,7 @@ Required properties:
"ehci_clk" for the peripheral clock "ehci_clk" for the peripheral clock
"usb_clk" for the UTMI clock "usb_clk" for the UTMI clock
usb1: ehci@00800000 { usb1: ehci@800000 {
compatible = "atmel,at91sam9g45-ehci", "usb-ehci"; compatible = "atmel,at91sam9g45-ehci", "usb-ehci";
reg = <0x00800000 0x100000>; reg = <0x00800000 0x100000>;
interrupts = <22 4>; interrupts = <22 4>;
......
...@@ -13,7 +13,7 @@ Optional properties: ...@@ -13,7 +13,7 @@ Optional properties:
Example: Example:
ohci: usb@0225000 { ohci: usb@225000 {
compatible = "ti,da830-ohci"; compatible = "ti,da830-ohci";
reg = <0x225000 0x1000>; reg = <0x225000 0x1000>;
interrupts = <59>; interrupts = <59>;
......
...@@ -30,7 +30,7 @@ Example (Sequoia 440EPx): ...@@ -30,7 +30,7 @@ Example (Sequoia 440EPx):
}; };
Example (Allwinner sun4i A10 SoC): Example (Allwinner sun4i A10 SoC):
ehci0: usb@01c14000 { ehci0: usb@1c14000 {
compatible = "allwinner,sun4i-a10-ehci", "generic-ehci"; compatible = "allwinner,sun4i-a10-ehci", "generic-ehci";
reg = <0x01c14000 0x100>; reg = <0x01c14000 0x100>;
interrupts = <39>; interrupts = <39>;
......
...@@ -2,6 +2,7 @@ USB NOP PHY ...@@ -2,6 +2,7 @@ USB NOP PHY
Required properties: Required properties:
- compatible: should be usb-nop-xceiv - compatible: should be usb-nop-xceiv
- #phy-cells: Must be 0
Optional properties: Optional properties:
- clocks: phandle to the PHY clock. Use as per Documentation/devicetree - clocks: phandle to the PHY clock. Use as per Documentation/devicetree
...@@ -33,6 +34,7 @@ Example: ...@@ -33,6 +34,7 @@ Example:
reset-gpios = <&gpio1 7 GPIO_ACTIVE_LOW>; reset-gpios = <&gpio1 7 GPIO_ACTIVE_LOW>;
vbus-detect-gpio = <&gpio2 13 GPIO_ACTIVE_HIGH>; vbus-detect-gpio = <&gpio2 13 GPIO_ACTIVE_HIGH>;
vbus-regulator = <&vbus_regulator>; vbus-regulator = <&vbus_regulator>;
#phy-cells = <0>;
}; };
hsusb1_phy is a NOP USB PHY device that gets its clock from an oscillator hsusb1_phy is a NOP USB PHY device that gets its clock from an oscillator
......
...@@ -19,7 +19,7 @@ Optional properties: ...@@ -19,7 +19,7 @@ Optional properties:
Example: Example:
ohci0: usb@01c14400 { ohci0: usb@1c14400 {
compatible = "allwinner,sun4i-a10-ohci", "generic-ohci"; compatible = "allwinner,sun4i-a10-ohci", "generic-ohci";
reg = <0x01c14400 0x100>; reg = <0x01c14400 0x100>;
interrupts = <64>; interrupts = <64>;
......
...@@ -26,7 +26,7 @@ Optional properties: ...@@ -26,7 +26,7 @@ Optional properties:
clock frequencies table is used) clock frequencies table is used)
Examples: Examples:
usb3503@08 { usb3503@8 {
compatible = "smsc,usb3503"; compatible = "smsc,usb3503";
reg = <0x08>; reg = <0x08>;
connect-gpios = <&gpx3 0 1>; connect-gpios = <&gpx3 0 1>;
......
...@@ -10,7 +10,7 @@ Required properties: ...@@ -10,7 +10,7 @@ Required properties:
- reg: Should contain registers location and length - reg: Should contain registers location and length
Examples: Examples:
usbmisc@02184800 { usbmisc@2184800 {
#index-cells = <1>; #index-cells = <1>;
compatible = "fsl,imx6q-usbmisc"; compatible = "fsl,imx6q-usbmisc";
reg = <0x02184800 0x200>; reg = <0x02184800 0x200>;
......
...@@ -83,6 +83,7 @@ davicom DAVICOM Semiconductor, Inc. ...@@ -83,6 +83,7 @@ davicom DAVICOM Semiconductor, Inc.
delta Delta Electronics, Inc. delta Delta Electronics, Inc.
denx Denx Software Engineering denx Denx Software Engineering
devantech Devantech, Ltd. devantech Devantech, Ltd.
dh DH electronics GmbH
digi Digi International Inc. digi Digi International Inc.
digilent Diglent, Inc. digilent Diglent, Inc.
dioo Dioo Microcircuit Co., Ltd dioo Dioo Microcircuit Co., Ltd
...@@ -230,12 +231,14 @@ netlogic Broadcom Corporation (formerly NetLogic Microsystems) ...@@ -230,12 +231,14 @@ netlogic Broadcom Corporation (formerly NetLogic Microsystems)
netron-dy Netron DY netron-dy Netron DY
netxeon Shenzhen Netxeon Technology CO., LTD netxeon Shenzhen Netxeon Technology CO., LTD
nexbox Nexbox nexbox Nexbox
nextthing Next Thing Co.
newhaven Newhaven Display International newhaven Newhaven Display International
ni National Instruments ni National Instruments
nintendo Nintendo nintendo Nintendo
nlt NLT Technologies, Ltd. nlt NLT Technologies, Ltd.
nokia Nokia nokia Nokia
nordic Nordic Semiconductor nordic Nordic Semiconductor
nutsboard NutsBoard
nuvoton Nuvoton Technology Corporation nuvoton Nuvoton Technology Corporation
nvd New Vision Display nvd New Vision Display
nvidia NVIDIA nvidia NVIDIA
...@@ -246,6 +249,7 @@ olimex OLIMEX Ltd. ...@@ -246,6 +249,7 @@ olimex OLIMEX Ltd.
onion Onion Corporation onion Onion Corporation
onnn ON Semiconductor Corp. onnn ON Semiconductor Corp.
ontat On Tat Industrial Company ontat On Tat Industrial Company
opalkelly Opal Kelly Incorporated
opencores OpenCores.org opencores OpenCores.org
openrisc OpenRISC.io openrisc OpenRISC.io
option Option NV option Option NV
...@@ -298,6 +302,7 @@ sensirion Sensirion AG ...@@ -298,6 +302,7 @@ sensirion Sensirion AG
sff Small Form Factor Committee sff Small Form Factor Committee
sgx SGX Sensortech sgx SGX Sensortech
sharp Sharp Corporation sharp Sharp Corporation
shimafuji Shimafuji Electric, Inc.
si-en Si-En Technology Ltd. si-en Si-En Technology Ltd.
sigma Sigma Designs, Inc. sigma Sigma Designs, Inc.
sii Seiko Instruments, Inc. sii Seiko Instruments, Inc.
...@@ -319,6 +324,7 @@ solomon Solomon Systech Limited ...@@ -319,6 +324,7 @@ solomon Solomon Systech Limited
sony Sony Corporation sony Sony Corporation
spansion Spansion Inc. spansion Spansion Inc.
sprd Spreadtrum Communications Inc. sprd Spreadtrum Communications Inc.
sst Silicon Storage Technology, Inc.
st STMicroelectronics st STMicroelectronics
starry Starry Electronic Technology (ShenZhen) Co., LTD starry Starry Electronic Technology (ShenZhen) Co., LTD
startek Startek startek Startek
...@@ -340,6 +346,7 @@ thine THine Electronics, Inc. ...@@ -340,6 +346,7 @@ thine THine Electronics, Inc.
ti Texas Instruments ti Texas Instruments
tianma Tianma Micro-electronics Co., Ltd. tianma Tianma Micro-electronics Co., Ltd.
tlm Trusted Logic Mobility tlm Trusted Logic Mobility
tmt Tecon Microprocessor Technologies, LLC.
topeet Topeet topeet Topeet
toradex Toradex AG toradex Toradex AG
toshiba Toshiba Corporation toshiba Toshiba Corporation
......
...@@ -13,7 +13,7 @@ Required properties: ...@@ -13,7 +13,7 @@ Required properties:
Example: Example:
wdt: watchdog@010000000 { wdt: watchdog@10000000 {
compatible = "mediatek,mt6589-wdt"; compatible = "mediatek,mt6589-wdt";
reg = <0x10000000 0x18>; reg = <0x10000000 0x18>;
}; };
...@@ -8,7 +8,7 @@ Required properties: ...@@ -8,7 +8,7 @@ Required properties:
Example: Example:
wdt: watchdog@01c20c90 { wdt: watchdog@1c20c90 {
compatible = "allwinner,sun4i-a10-wdt"; compatible = "allwinner,sun4i-a10-wdt";
reg = <0x01c20c90 0x10>; reg = <0x01c20c90 0x10>;
}; };
...@@ -87,15 +87,15 @@ Overlay in-kernel API ...@@ -87,15 +87,15 @@ Overlay in-kernel API
The API is quite easy to use. The API is quite easy to use.
1. Call of_overlay_create() to create and apply an overlay. The return value 1. Call of_overlay_apply() to create and apply an overlay changeset. The return
is a cookie identifying this overlay. value is an error or a cookie identifying this overlay.
2. Call of_overlay_destroy() to remove and cleanup the overlay previously 2. Call of_overlay_remove() to remove and cleanup the overlay changeset
created via the call to of_overlay_create(). Removal of an overlay that previously created via the call to of_overlay_apply(). Removal of an overlay
is stacked by another will not be permitted. changeset that is stacked by another will not be permitted.
Finally, if you need to remove all overlays in one-go, just call 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. order.
Overlay DTS Format Overlay DTS Format
......
...@@ -1158,7 +1158,6 @@ When kbuild executes, the following steps are followed (roughly): ...@@ -1158,7 +1158,6 @@ When kbuild executes, the following steps are followed (roughly):
Example: Example:
targets += $(dtb-y) targets += $(dtb-y)
clean-files += *.dtb
DTC_FLAGS ?= -p 1024 DTC_FLAGS ?= -p 1024
--- 6.8 Custom kbuild commands --- 6.8 Custom kbuild commands
......
...@@ -1550,7 +1550,7 @@ clean: $(clean-dirs) ...@@ -1550,7 +1550,7 @@ clean: $(clean-dirs)
$(call cmd,rmfiles) $(call cmd,rmfiles)
@find $(if $(KBUILD_EXTMOD), $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \ @find $(if $(KBUILD_EXTMOD), $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \
\( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \ \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
-o -name '*.ko.*' \ -o -name '*.ko.*' -o -name '*.dtb' -o -name '*.dtb.S' \
-o -name '*.dwo' \ -o -name '*.dwo' \
-o -name '*.su' \ -o -name '*.su' \
-o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \ -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \
......
...@@ -11,8 +11,6 @@ dtb-y := $(builtindtb-y).dtb ...@@ -11,8 +11,6 @@ dtb-y := $(builtindtb-y).dtb
.SECONDARY: $(obj)/$(builtindtb-y).dtb.S .SECONDARY: $(obj)/$(builtindtb-y).dtb.S
# for CONFIG_OF_ALL_DTBS test
dtstree := $(srctree)/$(src) dtstree := $(srctree)/$(src)
dtb-$(CONFIG_OF_ALL_DTBS) := $(patsubst $(dtstree)/%.dts,%.dtb, $(wildcard $(dtstree)/*.dts)) dtb- := $(patsubst $(dtstree)/%.dts,%.dtb, $(wildcard $(dtstree)/*.dts))
always := $(dtb-y)
clean-files := *.dtb *.dtb.S
...@@ -3,4 +3,3 @@ zImage ...@@ -3,4 +3,3 @@ zImage
xipImage xipImage
bootpImage bootpImage
uImage uImage
*.dtb
...@@ -1070,9 +1070,3 @@ dtb-$(CONFIG_ARCH_ASPEED) += aspeed-bmc-opp-palmetto.dtb \ ...@@ -1070,9 +1070,3 @@ dtb-$(CONFIG_ARCH_ASPEED) += aspeed-bmc-opp-palmetto.dtb \
aspeed-bmc-opp-romulus.dtb \ aspeed-bmc-opp-romulus.dtb \
aspeed-ast2500-evb.dtb aspeed-ast2500-evb.dtb
endif endif
dtstree := $(srctree)/$(src)
dtb-$(CONFIG_OF_ALL_DTBS) := $(patsubst $(dtstree)/%.dts,%.dtb, $(wildcard $(dtstree)/*.dts))
always := $(dtb-y)
clean-files := *.dtb
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
dts-dirs += actions subdir-y += actions
dts-dirs += al subdir-y += al
dts-dirs += allwinner subdir-y += allwinner
dts-dirs += altera subdir-y += altera
dts-dirs += amd subdir-y += amd
dts-dirs += amlogic subdir-y += amlogic
dts-dirs += apm subdir-y += apm
dts-dirs += arm subdir-y += arm
dts-dirs += broadcom subdir-y += broadcom
dts-dirs += cavium subdir-y += cavium
dts-dirs += exynos subdir-y += exynos
dts-dirs += freescale subdir-y += freescale
dts-dirs += hisilicon subdir-y += hisilicon
dts-dirs += marvell subdir-y += marvell
dts-dirs += mediatek subdir-y += mediatek
dts-dirs += nvidia subdir-y += nvidia
dts-dirs += qcom subdir-y += qcom
dts-dirs += realtek subdir-y += realtek
dts-dirs += renesas subdir-y += renesas
dts-dirs += rockchip subdir-y += rockchip
dts-dirs += socionext subdir-y += socionext
dts-dirs += sprd subdir-y += sprd
dts-dirs += xilinx subdir-y += xilinx
dts-dirs += lg subdir-y += lg
dts-dirs += zte subdir-y += zte
subdir-y := $(dts-dirs)
dtstree := $(srctree)/$(src)
dtb-$(CONFIG_OF_ALL_DTBS) := $(patsubst $(dtstree)/%.dts,%.dtb, $(foreach d,$(dts-dirs), $(wildcard $(dtstree)/$(d)/*.dts)))
always := $(dtb-y)
dtb-$(CONFIG_ARCH_ACTIONS) += s900-bubblegum-96.dtb dtb-$(CONFIG_ARCH_ACTIONS) += s900-bubblegum-96.dtb
always := $(dtb-y)
subdir-y := $(dts-dirs)
clean-files := *.dtb
dtb-$(CONFIG_ARCH_ALPINE) += alpine-v2-evp.dtb dtb-$(CONFIG_ARCH_ALPINE) += alpine-v2-evp.dtb
always := $(dtb-y)
subdir-y := $(dts-dirs)
clean-files := *.dtb
...@@ -9,7 +9,3 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-orangepi-pc2.dtb ...@@ -9,7 +9,3 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-orangepi-pc2.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-orangepi-prime.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-orangepi-prime.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-orangepi-zero-plus2.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-orangepi-zero-plus2.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-nanopi-neo2.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-nanopi-neo2.dtb
always := $(dtb-y)
subdir-y := $(dts-dirs)
clean-files := *.dtb
dtb-$(CONFIG_ARCH_STRATIX10) += socfpga_stratix10_socdk.dtb dtb-$(CONFIG_ARCH_STRATIX10) += socfpga_stratix10_socdk.dtb
always := $(dtb-y)
subdir-y := $(dts-dirs)
clean-files := *.dtb
...@@ -2,7 +2,3 @@ ...@@ -2,7 +2,3 @@
dtb-$(CONFIG_ARCH_SEATTLE) += amd-overdrive.dtb \ dtb-$(CONFIG_ARCH_SEATTLE) += amd-overdrive.dtb \
amd-overdrive-rev-b0.dtb amd-overdrive-rev-b1.dtb \ amd-overdrive-rev-b0.dtb amd-overdrive-rev-b1.dtb \
husky.dtb husky.dtb
always := $(dtb-y)
subdir-y := $(dts-dirs)
clean-files := *.dtb
...@@ -20,7 +20,3 @@ dtb-$(CONFIG_ARCH_MESON) += meson-gxm-nexbox-a1.dtb ...@@ -20,7 +20,3 @@ dtb-$(CONFIG_ARCH_MESON) += meson-gxm-nexbox-a1.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-gxm-q200.dtb dtb-$(CONFIG_ARCH_MESON) += meson-gxm-q200.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-gxm-q201.dtb dtb-$(CONFIG_ARCH_MESON) += meson-gxm-q201.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-gxm-rbox-pro.dtb dtb-$(CONFIG_ARCH_MESON) += meson-gxm-rbox-pro.dtb
always := $(dtb-y)
subdir-y := $(dts-dirs)
clean-files := *.dtb
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
dtb-$(CONFIG_ARCH_XGENE) += apm-mustang.dtb dtb-$(CONFIG_ARCH_XGENE) += apm-mustang.dtb
dtb-$(CONFIG_ARCH_XGENE) += apm-merlin.dtb dtb-$(CONFIG_ARCH_XGENE) += apm-merlin.dtb
always := $(dtb-y)
subdir-y := $(dts-dirs)
clean-files := *.dtb
...@@ -3,7 +3,3 @@ dtb-$(CONFIG_ARCH_VEXPRESS) += foundation-v8.dtb foundation-v8-gicv3.dtb ...@@ -3,7 +3,3 @@ dtb-$(CONFIG_ARCH_VEXPRESS) += foundation-v8.dtb foundation-v8-gicv3.dtb
dtb-$(CONFIG_ARCH_VEXPRESS) += juno.dtb juno-r1.dtb juno-r2.dtb dtb-$(CONFIG_ARCH_VEXPRESS) += juno.dtb juno-r1.dtb juno-r2.dtb
dtb-$(CONFIG_ARCH_VEXPRESS) += rtsm_ve-aemv8a.dtb dtb-$(CONFIG_ARCH_VEXPRESS) += rtsm_ve-aemv8a.dtb
dtb-$(CONFIG_ARCH_VEXPRESS) += vexpress-v2f-1xv7-ca53x2.dtb dtb-$(CONFIG_ARCH_VEXPRESS) += vexpress-v2f-1xv7-ca53x2.dtb
always := $(dtb-y)
subdir-y := $(dts-dirs)
clean-files := *.dtb
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
dtb-$(CONFIG_ARCH_BCM2835) += bcm2837-rpi-3-b.dtb dtb-$(CONFIG_ARCH_BCM2835) += bcm2837-rpi-3-b.dtb
dts-dirs += northstar2 subdir-y += northstar2
dts-dirs += stingray subdir-y += stingray
always := $(dtb-y)
subdir-y := $(dts-dirs)
clean-files := *.dtb
dtb-$(CONFIG_ARCH_BCM_IPROC) += ns2-svk.dtb dtb-$(CONFIG_ARCH_BCM_IPROC) += ns2-svk.dtb
dtb-$(CONFIG_ARCH_BCM_IPROC) += ns2-xmc.dtb dtb-$(CONFIG_ARCH_BCM_IPROC) += ns2-xmc.dtb
always := $(dtb-y)
subdir-y := $(dts-dirs)
clean-files := *.dtb
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
dtb-$(CONFIG_ARCH_BCM_IPROC) += bcm958742k.dtb dtb-$(CONFIG_ARCH_BCM_IPROC) += bcm958742k.dtb
dtb-$(CONFIG_ARCH_BCM_IPROC) += bcm958742t.dtb dtb-$(CONFIG_ARCH_BCM_IPROC) += bcm958742t.dtb
always := $(dtb-y)
subdir-y := $(dts-dirs)
clean-files := *.dtb
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
dtb-$(CONFIG_ARCH_THUNDER) += thunder-88xx.dtb dtb-$(CONFIG_ARCH_THUNDER) += thunder-88xx.dtb
dtb-$(CONFIG_ARCH_THUNDER2) += thunder2-99xx.dtb dtb-$(CONFIG_ARCH_THUNDER2) += thunder2-99xx.dtb
always := $(dtb-y)
subdir-y := $(dts-dirs)
clean-files := *.dtb
...@@ -3,7 +3,3 @@ dtb-$(CONFIG_ARCH_EXYNOS) += \ ...@@ -3,7 +3,3 @@ dtb-$(CONFIG_ARCH_EXYNOS) += \
exynos5433-tm2.dtb \ exynos5433-tm2.dtb \
exynos5433-tm2e.dtb \ exynos5433-tm2e.dtb \
exynos7-espresso.dtb exynos7-espresso.dtb
always := $(dtb-y)
subdir-y := $(dts-dirs)
clean-files := *.dtb
...@@ -13,7 +13,3 @@ dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2080a-rdb.dtb ...@@ -13,7 +13,3 @@ dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2080a-rdb.dtb
dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2080a-simu.dtb dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2080a-simu.dtb
dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2088a-qds.dtb dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2088a-qds.dtb
dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2088a-rdb.dtb dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2088a-rdb.dtb
always := $(dtb-y)
subdir-y := $(dts-dirs)
clean-files := *.dtb
...@@ -5,7 +5,3 @@ dtb-$(CONFIG_ARCH_HISI) += hi6220-hikey.dtb ...@@ -5,7 +5,3 @@ dtb-$(CONFIG_ARCH_HISI) += hi6220-hikey.dtb
dtb-$(CONFIG_ARCH_HISI) += hip05-d02.dtb dtb-$(CONFIG_ARCH_HISI) += hip05-d02.dtb
dtb-$(CONFIG_ARCH_HISI) += hip06-d03.dtb dtb-$(CONFIG_ARCH_HISI) += hip06-d03.dtb
dtb-$(CONFIG_ARCH_HISI) += hip07-d05.dtb dtb-$(CONFIG_ARCH_HISI) += hip07-d05.dtb
always := $(dtb-y)
subdir-y := $(dts-dirs)
clean-files := *.dtb
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
dtb-$(CONFIG_ARCH_LG1K) += lg1312-ref.dtb dtb-$(CONFIG_ARCH_LG1K) += lg1312-ref.dtb
dtb-$(CONFIG_ARCH_LG1K) += lg1313-ref.dtb dtb-$(CONFIG_ARCH_LG1K) += lg1313-ref.dtb
always := $(dtb-y)
subdir-y := $(dts-dirs)
clean-files := *.dtb
...@@ -10,7 +10,3 @@ dtb-$(CONFIG_ARCH_MVEBU) += armada-7040-db.dtb ...@@ -10,7 +10,3 @@ dtb-$(CONFIG_ARCH_MVEBU) += armada-7040-db.dtb
dtb-$(CONFIG_ARCH_MVEBU) += armada-8040-db.dtb dtb-$(CONFIG_ARCH_MVEBU) += armada-8040-db.dtb
dtb-$(CONFIG_ARCH_MVEBU) += armada-8040-mcbin.dtb dtb-$(CONFIG_ARCH_MVEBU) += armada-8040-mcbin.dtb
dtb-$(CONFIG_ARCH_MVEBU) += armada-8080-db.dtb dtb-$(CONFIG_ARCH_MVEBU) += armada-8080-db.dtb
always := $(dtb-y)
subdir-y := $(dts-dirs)
clean-files := *.dtb
...@@ -5,7 +5,3 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += mt6795-evb.dtb ...@@ -5,7 +5,3 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += mt6795-evb.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt6797-evb.dtb dtb-$(CONFIG_ARCH_MEDIATEK) += mt6797-evb.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt7622-rfb1.dtb dtb-$(CONFIG_ARCH_MEDIATEK) += mt7622-rfb1.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8173-evb.dtb dtb-$(CONFIG_ARCH_MEDIATEK) += mt8173-evb.dtb
always := $(dtb-y)
subdir-y := $(dts-dirs)
clean-files := *.dtb
...@@ -5,6 +5,3 @@ dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2371-2180.dtb ...@@ -5,6 +5,3 @@ dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2371-2180.dtb
dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2571.dtb dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2571.dtb
dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-smaug.dtb dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-smaug.dtb
dtb-$(CONFIG_ARCH_TEGRA_186_SOC) += tegra186-p2771-0000.dtb dtb-$(CONFIG_ARCH_TEGRA_186_SOC) += tegra186-p2771-0000.dtb
always := $(dtb-y)
clean-files := *.dtb
...@@ -6,7 +6,3 @@ dtb-$(CONFIG_ARCH_QCOM) += msm8916-mtp.dtb ...@@ -6,7 +6,3 @@ dtb-$(CONFIG_ARCH_QCOM) += msm8916-mtp.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8992-bullhead-rev-101.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8992-bullhead-rev-101.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8994-angler-rev-101.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8994-angler-rev-101.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8996-mtp.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8996-mtp.dtb
always := $(dtb-y)
subdir-y := $(dts-dirs)
clean-files := *.dtb
dtb-$(CONFIG_ARCH_REALTEK) += rtd1295-zidoo-x9s.dtb dtb-$(CONFIG_ARCH_REALTEK) += rtd1295-zidoo-x9s.dtb
always := $(dtb-y)
subdir-y := $(dts-dirs)
clean-files := *.dtb
...@@ -4,6 +4,3 @@ dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-salvator-xs.dtb ...@@ -4,6 +4,3 @@ dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-salvator-xs.dtb
dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-salvator-x.dtb r8a7795-es1-h3ulcb.dtb dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-salvator-x.dtb r8a7795-es1-h3ulcb.dtb
dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-x.dtb r8a7796-m3ulcb.dtb dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-x.dtb r8a7796-m3ulcb.dtb
dtb-$(CONFIG_ARCH_R8A77995) += r8a77995-draak.dtb dtb-$(CONFIG_ARCH_R8A77995) += r8a77995-draak.dtb
always := $(dtb-y)
clean-files := *.dtb
...@@ -11,7 +11,3 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-firefly.dtb ...@@ -11,7 +11,3 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-firefly.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-gru-kevin.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-gru-kevin.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-puma-haikou.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-puma-haikou.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-sapphire-excavator.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-sapphire-excavator.dtb
always := $(dtb-y)
subdir-y := $(dts-dirs)
clean-files := *.dtb
...@@ -5,6 +5,3 @@ dtb-$(CONFIG_ARCH_UNIPHIER) += \ ...@@ -5,6 +5,3 @@ dtb-$(CONFIG_ARCH_UNIPHIER) += \
uniphier-ld20-global.dtb \ uniphier-ld20-global.dtb \
uniphier-ld20-ref.dtb \ uniphier-ld20-ref.dtb \
uniphier-pxs3-ref.dtb uniphier-pxs3-ref.dtb
always := $(dtb-y)
clean-files := *.dtb
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
dtb-$(CONFIG_ARCH_SPRD) += sc9836-openphone.dtb \ dtb-$(CONFIG_ARCH_SPRD) += sc9836-openphone.dtb \
sp9860g-1h10.dtb sp9860g-1h10.dtb
always := $(dtb-y)
subdir-y := $(dts-dirs)
clean-files := *.dtb
dtb-$(CONFIG_ARCH_ZYNQMP) += zynqmp-ep108.dtb dtb-$(CONFIG_ARCH_ZYNQMP) += zynqmp-ep108.dtb
always := $(dtb-y)
subdir-y := $(dts-dirs)
clean-files := *.dtb
dtb-$(CONFIG_ARCH_ZX) += zx296718-evb.dtb dtb-$(CONFIG_ARCH_ZX) += zx296718-evb.dtb
dtb-$(CONFIG_ARCH_ZX) += zx296718-pcbox.dtb dtb-$(CONFIG_ARCH_ZX) += zx296718-pcbox.dtb
always := $(dtb-y)
subdir-y := $(dts-dirs)
clean-files := *.dtb
...@@ -17,5 +17,3 @@ $(obj)/builtin.dtb: $(obj)/$(DTB).dtb ...@@ -17,5 +17,3 @@ $(obj)/builtin.dtb: $(obj)/$(DTB).dtb
$(call if_changed,cp) $(call if_changed,cp)
$(obj)/linked_dtb.o: $(obj)/builtin.dtb $(obj)/linked_dtb.o: $(obj)/builtin.dtb
clean-files := *.dtb
...@@ -3,5 +3,3 @@ BUILTIN_DTB := $(patsubst "%",%,$(CONFIG_BUILTIN_DTB)).dtb.o ...@@ -3,5 +3,3 @@ BUILTIN_DTB := $(patsubst "%",%,$(CONFIG_BUILTIN_DTB)).dtb.o
ifneq ($(CONFIG_BUILTIN_DTB),"") ifneq ($(CONFIG_BUILTIN_DTB),"")
obj-$(CONFIG_OF) += $(BUILTIN_DTB) obj-$(CONFIG_OF) += $(BUILTIN_DTB)
endif endif
clean-files := *.dtb.S
...@@ -8,9 +8,3 @@ obj-y += $(BUILTIN_DTB) ...@@ -8,9 +8,3 @@ obj-y += $(BUILTIN_DTB)
dtb-$(CONFIG_H8300H_SIM) := h8300h_sim.dtb dtb-$(CONFIG_H8300H_SIM) := h8300h_sim.dtb
dtb-$(CONFIG_H8S_SIM) := h8s_sim.dtb dtb-$(CONFIG_H8S_SIM) := h8s_sim.dtb
dtb-$(CONFIG_H8S_EDOSK2674) := edosk2674.dtb dtb-$(CONFIG_H8S_EDOSK2674) := edosk2674.dtb
dtstree := $(srctree)/$(src)
dtb-$(CONFIG_OF_ALL_DTBS) := $(patsubst $(dtstree)/%.dts,%.dtb, $(wildcard $(dtstree)/*.dts))
always := $(dtb-y)
clean-files := *.dtb.S *.dtb
vmlinux* vmlinux*
uImage* uImage*
ramdisk.* ramdisk.*
*.dtb*
...@@ -13,10 +13,4 @@ endif ...@@ -13,10 +13,4 @@ endif
dtb-$(CONFIG_METAG_BUILTIN_DTB) += $(builtindtb-y).dtb dtb-$(CONFIG_METAG_BUILTIN_DTB) += $(builtindtb-y).dtb
obj-$(CONFIG_METAG_BUILTIN_DTB) += $(builtindtb-y).dtb.o obj-$(CONFIG_METAG_BUILTIN_DTB) += $(builtindtb-y).dtb.o
dtstree := $(srctree)/$(src)
dtb-$(CONFIG_OF_ALL_DTBS) := $(patsubst $(dtstree)/%.dts,%.dtb, $(wildcard $(dtstree)/*.dts))
.SECONDARY: $(obj)/$(builtindtb-y).dtb.S .SECONDARY: $(obj)/$(builtindtb-y).dtb.S
always += $(dtb-y)
clean-files += *.dtb *.dtb.S
*.dtb
linux.bin* linux.bin*
simpleImage.* simpleImage.*
...@@ -35,4 +35,4 @@ $(obj)/simpleImage.%: vmlinux FORCE ...@@ -35,4 +35,4 @@ $(obj)/simpleImage.%: vmlinux FORCE
$(call if_changed,strip) $(call if_changed,strip)
@echo 'Kernel: $@ is ready' ' (#'`cat .version`')' @echo 'Kernel: $@ is ready' ' (#'`cat .version`')'
clean-files += simpleImage.*.unstrip linux.bin.ub dts/*.dtb clean-files += simpleImage.*.unstrip linux.bin.ub
...@@ -5,4 +5,3 @@ zImage ...@@ -5,4 +5,3 @@ zImage
zImage.tmp zImage.tmp
calc_vmlinuz_load_addr calc_vmlinuz_load_addr
uImage uImage
*.dtb
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
dts-dirs += brcm subdir-y += brcm
dts-dirs += cavium-octeon subdir-y += cavium-octeon
dts-dirs += img subdir-y += img
dts-dirs += ingenic subdir-y += ingenic
dts-dirs += lantiq subdir-y += lantiq
dts-dirs += mti subdir-y += mti
dts-dirs += netlogic subdir-y += netlogic
dts-dirs += ni subdir-y += ni
dts-dirs += pic32 subdir-y += pic32
dts-dirs += qca subdir-y += qca
dts-dirs += ralink subdir-y += ralink
dts-dirs += xilfpga subdir-y += xilfpga
obj-y := $(addsuffix /, $(dts-dirs)) obj-$(CONFIG_BUILTIN_DTB) := $(addsuffix /, $(subdir-y))
dtstree := $(srctree)/$(src)
dtb-$(CONFIG_OF_ALL_DTBS) := $(patsubst $(dtstree)/%.dts,%.dtb, $(foreach d,$(dts-dirs), $(wildcard $(dtstree)/$(d)/*.dts)))
always := $(dtb-y)
subdir-y := $(dts-dirs)
clean-files := *.dtb *.dtb.S
...@@ -23,7 +23,6 @@ dtb-$(CONFIG_DT_NONE) += \ ...@@ -23,7 +23,6 @@ dtb-$(CONFIG_DT_NONE) += \
bcm63268-comtrend-vr-3032u.dtb \ bcm63268-comtrend-vr-3032u.dtb \
bcm93384wvg.dtb \ bcm93384wvg.dtb \
bcm93384wvg_viper.dtb \ bcm93384wvg_viper.dtb \
bcm96358nb4ser.dtb \
bcm96368mvwg.dtb \ bcm96368mvwg.dtb \
bcm9ejtagprb.dtb \ bcm9ejtagprb.dtb \
bcm97125cbmb.dtb \ bcm97125cbmb.dtb \
...@@ -39,6 +38,3 @@ obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y)) ...@@ -39,6 +38,3 @@ obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y))
# Force kbuild to make empty built-in.o if necessary # Force kbuild to make empty built-in.o if necessary
obj- += dummy.o obj- += dummy.o
always := $(dtb-y)
clean-files := *.dtb *.dtb.S
...@@ -5,6 +5,3 @@ obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y)) ...@@ -5,6 +5,3 @@ obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y))
# Force kbuild to make empty built-in.o if necessary # Force kbuild to make empty built-in.o if necessary
obj- += dummy.o obj- += dummy.o
always := $(dtb-y)
clean-files := *.dtb *.dtb.S
...@@ -6,6 +6,3 @@ obj-$(CONFIG_MACH_PISTACHIO) += pistachio_marduk.dtb.o ...@@ -6,6 +6,3 @@ obj-$(CONFIG_MACH_PISTACHIO) += pistachio_marduk.dtb.o
# Force kbuild to make empty built-in.o if necessary # Force kbuild to make empty built-in.o if necessary
obj- += dummy.o obj- += dummy.o
always := $(dtb-y)
clean-files := *.dtb *.dtb.S
...@@ -6,6 +6,3 @@ obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y)) ...@@ -6,6 +6,3 @@ obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y))
# Force kbuild to make empty built-in.o if necessary # Force kbuild to make empty built-in.o if necessary
obj- += dummy.o obj- += dummy.o
always := $(dtb-y)
clean-files := *.dtb *.dtb.S
...@@ -5,6 +5,3 @@ obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y)) ...@@ -5,6 +5,3 @@ obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y))
# Force kbuild to make empty built-in.o if necessary # Force kbuild to make empty built-in.o if necessary
obj- += dummy.o obj- += dummy.o
always := $(dtb-y)
clean-files := *.dtb *.dtb.S
...@@ -6,6 +6,3 @@ obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y)) ...@@ -6,6 +6,3 @@ obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y))
# Force kbuild to make empty built-in.o if necessary # Force kbuild to make empty built-in.o if necessary
obj- += dummy.o obj- += dummy.o
always := $(dtb-y)
clean-files := *.dtb *.dtb.S
...@@ -9,6 +9,3 @@ obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y)) ...@@ -9,6 +9,3 @@ obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y))
# Force kbuild to make empty built-in.o if necessary # Force kbuild to make empty built-in.o if necessary
obj- += dummy.o obj- += dummy.o
always := $(dtb-y)
clean-files := *.dtb *.dtb.S
...@@ -2,6 +2,3 @@ dtb-$(CONFIG_FIT_IMAGE_FDT_NI169445) += 169445.dtb ...@@ -2,6 +2,3 @@ dtb-$(CONFIG_FIT_IMAGE_FDT_NI169445) += 169445.dtb
# Force kbuild to make empty built-in.o if necessary # Force kbuild to make empty built-in.o if necessary
obj- += dummy.o obj- += dummy.o
always := $(dtb-y)
clean-files := *.dtb *.dtb.S
...@@ -8,6 +8,3 @@ obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y)) ...@@ -8,6 +8,3 @@ obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y))
# Force kbuild to make empty built-in.o if necessary # Force kbuild to make empty built-in.o if necessary
obj- += dummy.o obj- += dummy.o
always := $(dtb-y)
clean-files := *.dtb *.dtb.S
...@@ -8,6 +8,3 @@ dtb-$(CONFIG_ATH79) += ar9331_tl_mr3020.dtb ...@@ -8,6 +8,3 @@ dtb-$(CONFIG_ATH79) += ar9331_tl_mr3020.dtb
# Force kbuild to make empty built-in.o if necessary # Force kbuild to make empty built-in.o if necessary
obj- += dummy.o obj- += dummy.o
always := $(dtb-y)
clean-files := *.dtb *.dtb.S
...@@ -10,6 +10,3 @@ obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y)) ...@@ -10,6 +10,3 @@ obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y))
# Force kbuild to make empty built-in.o if necessary # Force kbuild to make empty built-in.o if necessary
obj- += dummy.o obj- += dummy.o
always := $(dtb-y)
clean-files := *.dtb *.dtb.S
...@@ -5,6 +5,3 @@ obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y)) ...@@ -5,6 +5,3 @@ obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y))
# Force kbuild to make empty built-in.o if necessary # Force kbuild to make empty built-in.o if necessary
obj- += dummy.o obj- += dummy.o
always := $(dtb-y)
clean-files := *.dtb *.dtb.S
...@@ -53,7 +53,5 @@ $(obj)/%.dtb: $(src)/dts/%.dts FORCE ...@@ -53,7 +53,5 @@ $(obj)/%.dtb: $(src)/dts/%.dts FORCE
$(obj)/dtbs: $(addprefix $(obj)/, $(dtb-y)) $(obj)/dtbs: $(addprefix $(obj)/, $(dtb-y))
clean-files := *.dtb
install: install:
sh $(srctree)/$(src)/install.sh $(KERNELRELEASE) $(BOOTIMAGE) System.map "$(INSTALL_PATH)" sh $(srctree)/$(src)/install.sh $(KERNELRELEASE) $(BOOTIMAGE) System.map "$(INSTALL_PATH)"
...@@ -6,6 +6,4 @@ BUILTIN_DTB := ...@@ -6,6 +6,4 @@ BUILTIN_DTB :=
endif endif
obj-y += $(BUILTIN_DTB) obj-y += $(BUILTIN_DTB)
clean-files := *.dtb.S
#DTC_FLAGS ?= -p 1024 #DTC_FLAGS ?= -p 1024
...@@ -18,7 +18,6 @@ otheros.bld ...@@ -18,7 +18,6 @@ otheros.bld
uImage uImage
cuImage.* cuImage.*
dtbImage.* dtbImage.*
*.dtb
treeImage.* treeImage.*
vmlinux.strip vmlinux.strip
zImage zImage
......
...@@ -440,7 +440,7 @@ zInstall: $(CONFIGURE) $(addprefix $(obj)/, $(image-y)) ...@@ -440,7 +440,7 @@ zInstall: $(CONFIGURE) $(addprefix $(obj)/, $(image-y))
clean-files += $(image-) $(initrd-) cuImage.* dtbImage.* treeImage.* \ clean-files += $(image-) $(initrd-) cuImage.* dtbImage.* treeImage.* \
zImage zImage.initrd zImage.chrp zImage.coff zImage.holly \ zImage zImage.initrd zImage.chrp zImage.coff zImage.holly \
zImage.miboot zImage.pmac zImage.pseries \ zImage.miboot zImage.pmac zImage.pseries \
zImage.maple simpleImage.* otheros.bld *.dtb zImage.maple simpleImage.* otheros.bld
# clean up files cached by wrapper # clean up files cached by wrapper
clean-kernel-base := vmlinux.strip vmlinux.bin clean-kernel-base := vmlinux.strip vmlinux.bin
......
...@@ -75,24 +75,17 @@ static struct property *dlpar_parse_cc_property(struct cc_workarea *ccwa) ...@@ -75,24 +75,17 @@ static struct property *dlpar_parse_cc_property(struct cc_workarea *ccwa)
return prop; return prop;
} }
static struct device_node *dlpar_parse_cc_node(struct cc_workarea *ccwa, static struct device_node *dlpar_parse_cc_node(struct cc_workarea *ccwa)
const char *path)
{ {
struct device_node *dn; struct device_node *dn;
char *name; const char *name;
/* If parent node path is "/" advance path to NULL terminator to
* prevent double leading slashs in full_name.
*/
if (!path[1])
path++;
dn = kzalloc(sizeof(*dn), GFP_KERNEL); dn = kzalloc(sizeof(*dn), GFP_KERNEL);
if (!dn) if (!dn)
return NULL; return NULL;
name = (char *)ccwa + be32_to_cpu(ccwa->name_offset); name = (const char *)ccwa + be32_to_cpu(ccwa->name_offset);
dn->full_name = kasprintf(GFP_KERNEL, "%s/%s", path, name); dn->full_name = kstrdup(name, GFP_KERNEL);
if (!dn->full_name) { if (!dn->full_name) {
kfree(dn); kfree(dn);
return NULL; return NULL;
...@@ -148,7 +141,6 @@ struct device_node *dlpar_configure_connector(__be32 drc_index, ...@@ -148,7 +141,6 @@ struct device_node *dlpar_configure_connector(__be32 drc_index,
struct property *last_property = NULL; struct property *last_property = NULL;
struct cc_workarea *ccwa; struct cc_workarea *ccwa;
char *data_buf; char *data_buf;
const char *parent_path = parent->full_name;
int cc_token; int cc_token;
int rc = -1; int rc = -1;
...@@ -182,7 +174,7 @@ struct device_node *dlpar_configure_connector(__be32 drc_index, ...@@ -182,7 +174,7 @@ struct device_node *dlpar_configure_connector(__be32 drc_index,
break; break;
case NEXT_SIBLING: case NEXT_SIBLING:
dn = dlpar_parse_cc_node(ccwa, parent_path); dn = dlpar_parse_cc_node(ccwa);
if (!dn) if (!dn)
goto cc_error; goto cc_error;
...@@ -192,10 +184,7 @@ struct device_node *dlpar_configure_connector(__be32 drc_index, ...@@ -192,10 +184,7 @@ struct device_node *dlpar_configure_connector(__be32 drc_index,
break; break;
case NEXT_CHILD: case NEXT_CHILD:
if (first_dn) dn = dlpar_parse_cc_node(ccwa);
parent_path = last_dn->full_name;
dn = dlpar_parse_cc_node(ccwa, parent_path);
if (!dn) if (!dn)
goto cc_error; goto cc_error;
...@@ -226,7 +215,6 @@ struct device_node *dlpar_configure_connector(__be32 drc_index, ...@@ -226,7 +215,6 @@ struct device_node *dlpar_configure_connector(__be32 drc_index,
case PREV_PARENT: case PREV_PARENT:
last_dn = last_dn->parent; last_dn = last_dn->parent;
parent_path = last_dn->parent->full_name;
break; break;
case CALL_AGAIN: case CALL_AGAIN:
......
...@@ -33,7 +33,7 @@ static int pSeries_reconfig_add_node(const char *path, struct property *proplist ...@@ -33,7 +33,7 @@ static int pSeries_reconfig_add_node(const char *path, struct property *proplist
if (!np) if (!np)
goto out_err; goto out_err;
np->full_name = kstrdup(path, GFP_KERNEL); np->full_name = kstrdup(kbasename(path), GFP_KERNEL);
if (!np->full_name) if (!np->full_name)
goto out_err; goto out_err;
......
obj-$(CONFIG_USE_BUILTIN_DTB) += $(patsubst "%",%,$(CONFIG_BUILTIN_DTB_SOURCE)).dtb.o obj-$(CONFIG_USE_BUILTIN_DTB) += $(patsubst "%",%,$(CONFIG_BUILTIN_DTB_SOURCE)).dtb.o
clean-files := *.dtb.S
uImage uImage
zImage.redboot zImage.redboot
*.dtb
...@@ -12,9 +12,6 @@ ifneq ($(CONFIG_BUILTIN_DTB),"") ...@@ -12,9 +12,6 @@ ifneq ($(CONFIG_BUILTIN_DTB),"")
obj-$(CONFIG_OF) += $(BUILTIN_DTB) obj-$(CONFIG_OF) += $(BUILTIN_DTB)
endif endif
# for CONFIG_OF_ALL_DTBS test
dtstree := $(srctree)/$(src) dtstree := $(srctree)/$(src)
dtb-$(CONFIG_OF_ALL_DTBS) := $(patsubst $(dtstree)/%.dts,%.dtb, $(wildcard $(dtstree)/*.dts)) dtb- := $(patsubst $(dtstree)/%.dts,%.dtb, $(wildcard $(dtstree)/*.dts))
always += $(dtb-y)
clean-files += *.dtb *.dtb.S
...@@ -1571,7 +1571,7 @@ static int device_add_class_symlinks(struct device *dev) ...@@ -1571,7 +1571,7 @@ static int device_add_class_symlinks(struct device *dev)
int error; int error;
if (of_node) { 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) if (error)
dev_warn(dev, "Error %d creating of_node link\n",error); dev_warn(dev, "Error %d creating of_node link\n",error);
/* An error here doesn't warrant bringing down the device */ /* An error here doesn't warrant bringing down the device */
......
...@@ -145,7 +145,6 @@ static struct device_node * __init tilcdc_get_overlay(struct kfree_table *kft) ...@@ -145,7 +145,6 @@ static struct device_node * __init tilcdc_get_overlay(struct kfree_table *kft)
__dtb_tilcdc_slave_compat_begin; __dtb_tilcdc_slave_compat_begin;
static void *overlay_data; static void *overlay_data;
struct device_node *overlay; struct device_node *overlay;
int ret;
if (!size) { if (!size) {
pr_warn("%s: No overlay data\n", __func__); pr_warn("%s: No overlay data\n", __func__);
...@@ -164,11 +163,6 @@ static struct device_node * __init tilcdc_get_overlay(struct kfree_table *kft) ...@@ -164,11 +163,6 @@ static struct device_node * __init tilcdc_get_overlay(struct kfree_table *kft)
} }
of_node_set_flag(overlay, OF_DETACHED); 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; return overlay;
} }
...@@ -204,7 +198,7 @@ static void __init tilcdc_convert_slave_node(void) ...@@ -204,7 +198,7 @@ static void __init tilcdc_convert_slave_node(void)
/* For all memory needed for the overlay tree. This memory can /* For all memory needed for the overlay tree. This memory can
be freed after the overlay has been applied. */ be freed after the overlay has been applied. */
struct kfree_table kft; struct kfree_table kft;
int ret; int ovcs_id, ret;
if (kfree_table_init(&kft)) if (kfree_table_init(&kft))
return; return;
...@@ -247,9 +241,11 @@ static void __init tilcdc_convert_slave_node(void) ...@@ -247,9 +241,11 @@ static void __init tilcdc_convert_slave_node(void)
tilcdc_node_disable(slave); tilcdc_node_disable(slave);
ret = of_overlay_create(overlay); ovcs_id = 0;
ret = of_overlay_apply(overlay, &ovcs_id);
if (ret) if (ret)
pr_err("%s: Creating overlay failed: %d\n", __func__, ret); pr_err("%s: Applying overlay changeset failed: %d\n",
__func__, ret);
else else
pr_info("%s: ti,tilcdc,slave node successfully converted\n", pr_info("%s: ti,tilcdc,slave node successfully converted\n",
__func__); __func__);
......
...@@ -46,10 +46,14 @@ config OF_EARLY_FLATTREE ...@@ -46,10 +46,14 @@ config OF_EARLY_FLATTREE
config OF_PROMTREE config OF_PROMTREE
bool bool
config OF_KOBJ
def_bool SYSFS
# Hardly any platforms need this. It is safe to select, but only do so if you # Hardly any platforms need this. It is safe to select, but only do so if you
# need it. # need it.
config OF_DYNAMIC config OF_DYNAMIC
bool "Support for dynamic device trees" if OF_UNITTEST bool "Support for dynamic device trees" if OF_UNITTEST
select OF_KOBJ
help help
On some platforms, the device tree can be manipulated at runtime. On some platforms, the device tree can be manipulated at runtime.
While this option is selected automatically on such platforms, you While this option is selected automatically on such platforms, you
......
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
obj-y = base.o device.o platform.o property.o 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_DYNAMIC) += dynamic.o
obj-$(CONFIG_OF_FLATTREE) += fdt.o obj-$(CONFIG_OF_FLATTREE) += fdt.o
obj-$(CONFIG_OF_EARLY_FLATTREE) += fdt_address.o obj-$(CONFIG_OF_EARLY_FLATTREE) += fdt_address.o
......
...@@ -95,108 +95,6 @@ int __weak of_node_to_nid(struct device_node *np) ...@@ -95,108 +95,6 @@ int __weak of_node_to_nid(struct device_node *np)
} }
#endif #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) void __init of_core_init(void)
{ {
struct device_node *np; struct device_node *np;
...@@ -760,7 +658,7 @@ struct device_node *of_get_child_by_name(const struct device_node *node, ...@@ -760,7 +658,7 @@ struct device_node *of_get_child_by_name(const struct device_node *node,
} }
EXPORT_SYMBOL(of_get_child_by_name); 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) const char *path)
{ {
struct device_node *child; struct device_node *child;
...@@ -1504,22 +1402,6 @@ int __of_remove_property(struct device_node *np, struct property *prop) ...@@ -1504,22 +1402,6 @@ int __of_remove_property(struct device_node *np, struct property *prop)
return 0; 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. * of_remove_property - Remove a property from a node.
* *
...@@ -1579,21 +1461,6 @@ int __of_update_property(struct device_node *np, struct property *newprop, ...@@ -1579,21 +1461,6 @@ int __of_update_property(struct device_node *np, struct property *newprop,
return 0; 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 * of_update_property - Update a property in a node, if the property does
* not exist, add it. * not exist, add it.
......
...@@ -16,6 +16,11 @@ ...@@ -16,6 +16,11 @@
#include "of_private.h" #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 * of_node_get() - Increment refcount of a node
* @node: Node to inc refcount, NULL is supported to simplify writing of * @node: Node to inc refcount, NULL is supported to simplify writing of
...@@ -43,28 +48,6 @@ void of_node_put(struct device_node *node) ...@@ -43,28 +48,6 @@ void of_node_put(struct device_node *node)
} }
EXPORT_SYMBOL(of_node_put); 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); static BLOCKING_NOTIFIER_HEAD(of_reconfig_chain);
int of_reconfig_notifier_register(struct notifier_block *nb) int of_reconfig_notifier_register(struct notifier_block *nb)
...@@ -315,6 +298,18 @@ int of_detach_node(struct device_node *np) ...@@ -315,6 +298,18 @@ int of_detach_node(struct device_node *np)
} }
EXPORT_SYMBOL_GPL(of_detach_node); 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 * of_node_release() - release a dynamically allocated node
* @kref: kref element of the node to be released * @kref: kref element of the node to be released
...@@ -324,7 +319,6 @@ EXPORT_SYMBOL_GPL(of_detach_node); ...@@ -324,7 +319,6 @@ EXPORT_SYMBOL_GPL(of_detach_node);
void of_node_release(struct kobject *kobj) void of_node_release(struct kobject *kobj)
{ {
struct device_node *node = kobj_to_device_node(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. */ /* We should never be releasing nodes that haven't been detached. */
if (!of_node_check_flag(node, OF_DETACHED)) { if (!of_node_check_flag(node, OF_DETACHED)) {
...@@ -335,18 +329,9 @@ void of_node_release(struct kobject *kobj) ...@@ -335,18 +329,9 @@ void of_node_release(struct kobject *kobj)
if (!of_node_check_flag(node, OF_DYNAMIC)) if (!of_node_check_flag(node, OF_DYNAMIC))
return; return;
while (prop) { property_list_free(node->properties);
struct property *next = prop->next; property_list_free(node->deadprops);
kfree(prop->name);
kfree(prop->value);
kfree(prop);
prop = next;
if (!prop) {
prop = node->deadprops;
node->deadprops = NULL;
}
}
kfree(node->full_name); kfree(node->full_name);
kfree(node->data); kfree(node->data);
kfree(node); kfree(node);
...@@ -508,11 +493,12 @@ static void __of_changeset_entry_invert(struct of_changeset_entry *ce, ...@@ -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_reconfig_data rd;
struct of_changeset_entry ce_inverted; struct of_changeset_entry ce_inverted;
int ret; int ret = 0;
if (revert) { if (revert) {
__of_changeset_entry_invert(ce, &ce_inverted); __of_changeset_entry_invert(ce, &ce_inverted);
...@@ -534,11 +520,12 @@ static void __of_changeset_entry_notify(struct of_changeset_entry *ce, bool reve ...@@ -534,11 +520,12 @@ static void __of_changeset_entry_notify(struct of_changeset_entry *ce, bool reve
default: default:
pr_err("invalid devicetree changeset action: %i\n", pr_err("invalid devicetree changeset action: %i\n",
(int)ce->action); (int)ce->action);
return; ret = -EINVAL;
} }
if (ret) if (ret)
pr_err("changeset notifier error @%pOF\n", ce->np); pr_err("changeset notifier error @%pOF\n", ce->np);
return ret;
} }
static int __of_changeset_entry_apply(struct of_changeset_entry *ce) static int __of_changeset_entry_apply(struct of_changeset_entry *ce)
...@@ -672,32 +659,82 @@ void of_changeset_destroy(struct of_changeset *ocs) ...@@ -672,32 +659,82 @@ void of_changeset_destroy(struct of_changeset *ocs)
} }
EXPORT_SYMBOL_GPL(of_changeset_destroy); 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; struct of_changeset_entry *ce;
int ret; int ret, ret_tmp;
/* perform the rest of the work */
pr_debug("changeset: applying...\n"); pr_debug("changeset: applying...\n");
list_for_each_entry(ce, &ocs->entries, node) { list_for_each_entry(ce, &ocs->entries, node) {
ret = __of_changeset_entry_apply(ce); ret = __of_changeset_entry_apply(ce);
if (ret) { if (ret) {
pr_err("Error applying changeset (%d)\n", ret); pr_err("Error applying changeset (%d)\n", ret);
list_for_each_entry_continue_reverse(ce, &ocs->entries, node) list_for_each_entry_continue_reverse(ce, &ocs->entries,
__of_changeset_entry_revert(ce); node) {
ret_tmp = __of_changeset_entry_revert(ce);
if (ret_tmp)
*ret_revert = ret_tmp;
}
return ret; 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 */ /* drop the global lock while emitting notifiers */
mutex_unlock(&of_mutex); mutex_unlock(&of_mutex);
list_for_each_entry(ce, &ocs->entries, node) list_for_each_entry(ce, &ocs->entries, node) {
__of_changeset_entry_notify(ce, 0); ret_tmp = __of_changeset_entry_notify(ce, 0);
if (ret_tmp)
ret = ret_tmp;
}
mutex_lock(&of_mutex); mutex_lock(&of_mutex);
pr_debug("changeset: notifiers sent.\n"); 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) ...@@ -724,31 +761,74 @@ int of_changeset_apply(struct of_changeset *ocs)
} }
EXPORT_SYMBOL_GPL(of_changeset_apply); 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; struct of_changeset_entry *ce;
int ret; int ret, ret_tmp;
pr_debug("changeset: reverting...\n"); pr_debug("changeset: reverting...\n");
list_for_each_entry_reverse(ce, &ocs->entries, node) { list_for_each_entry_reverse(ce, &ocs->entries, node) {
ret = __of_changeset_entry_revert(ce); ret = __of_changeset_entry_revert(ce);
if (ret) { if (ret) {
pr_err("Error reverting changeset (%d)\n", ret); pr_err("Error reverting changeset (%d)\n", ret);
list_for_each_entry_continue(ce, &ocs->entries, node) list_for_each_entry_continue(ce, &ocs->entries, node) {
__of_changeset_entry_apply(ce); ret_tmp = __of_changeset_entry_apply(ce);
if (ret_tmp)
*ret_apply = ret_tmp;
}
return ret; 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 */ /* drop the global lock while emitting notifiers */
mutex_unlock(&of_mutex); mutex_unlock(&of_mutex);
list_for_each_entry_reverse(ce, &ocs->entries, node) list_for_each_entry_reverse(ce, &ocs->entries, node) {
__of_changeset_entry_notify(ce, 1); ret_tmp = __of_changeset_entry_notify(ce, 1);
if (ret_tmp)
ret = ret_tmp;
}
mutex_lock(&of_mutex); mutex_lock(&of_mutex);
pr_debug("changeset: notifiers sent.\n"); 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) ...@@ -775,7 +855,7 @@ int of_changeset_revert(struct of_changeset *ocs)
EXPORT_SYMBOL_GPL(of_changeset_revert); 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 * @ocs: changeset pointer
* @action: action to perform * @action: action to perform
......
...@@ -132,6 +132,19 @@ bool of_fdt_is_big_endian(const void *blob, unsigned long node) ...@@ -132,6 +132,19 @@ bool of_fdt_is_big_endian(const void *blob, unsigned long node)
return false; 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 * of_fdt_match - Return true if node matches a list of compatible values
*/ */
...@@ -266,74 +279,32 @@ static void populate_properties(const void *blob, ...@@ -266,74 +279,32 @@ static void populate_properties(const void *blob,
*pprev = NULL; *pprev = NULL;
} }
static unsigned int populate_node(const void *blob, static bool populate_node(const void *blob,
int offset, int offset,
void **mem, void **mem,
struct device_node *dad, struct device_node *dad,
unsigned int fpsize,
struct device_node **pnp, struct device_node **pnp,
bool dryrun) bool dryrun)
{ {
struct device_node *np; struct device_node *np;
const char *pathp; const char *pathp;
unsigned int l, allocl; unsigned int l, allocl;
int new_format = 0;
pathp = fdt_get_name(blob, offset, &l); pathp = fdt_get_name(blob, offset, &l);
if (!pathp) { if (!pathp) {
*pnp = NULL; *pnp = NULL;
return 0; return false;
} }
allocl = ++l; 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, np = unflatten_dt_alloc(mem, sizeof(struct device_node) + allocl,
__alignof__(struct device_node)); __alignof__(struct device_node));
if (!dryrun) { if (!dryrun) {
char *fn; char *fn;
of_node_init(np); of_node_init(np);
np->full_name = fn = ((char *)np) + sizeof(*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); memcpy(fn, pathp, l);
if (dad != NULL) { if (dad != NULL) {
...@@ -355,7 +326,7 @@ static unsigned int populate_node(const void *blob, ...@@ -355,7 +326,7 @@ static unsigned int populate_node(const void *blob,
} }
*pnp = np; *pnp = np;
return fpsize; return true;
} }
static void reverse_nodes(struct device_node *parent) static void reverse_nodes(struct device_node *parent)
...@@ -399,7 +370,6 @@ static int unflatten_dt_nodes(const void *blob, ...@@ -399,7 +370,6 @@ static int unflatten_dt_nodes(const void *blob,
struct device_node *root; struct device_node *root;
int offset = 0, depth = 0, initial_depth = 0; int offset = 0, depth = 0, initial_depth = 0;
#define FDT_MAX_DEPTH 64 #define FDT_MAX_DEPTH 64
unsigned int fpsizes[FDT_MAX_DEPTH];
struct device_node *nps[FDT_MAX_DEPTH]; struct device_node *nps[FDT_MAX_DEPTH];
void *base = mem; void *base = mem;
bool dryrun = !base; bool dryrun = !base;
...@@ -418,7 +388,6 @@ static int unflatten_dt_nodes(const void *blob, ...@@ -418,7 +388,6 @@ static int unflatten_dt_nodes(const void *blob,
depth = initial_depth = 1; depth = initial_depth = 1;
root = dad; root = dad;
fpsizes[depth] = dad ? strlen(of_node_full_name(dad)) : 0;
nps[depth] = dad; nps[depth] = dad;
for (offset = 0; for (offset = 0;
...@@ -427,11 +396,12 @@ static int unflatten_dt_nodes(const void *blob, ...@@ -427,11 +396,12 @@ static int unflatten_dt_nodes(const void *blob,
if (WARN_ON_ONCE(depth >= FDT_MAX_DEPTH)) if (WARN_ON_ONCE(depth >= FDT_MAX_DEPTH))
continue; continue;
fpsizes[depth+1] = populate_node(blob, offset, &mem, if (!IS_ENABLED(CONFIG_OF_KOBJ) &&
nps[depth], !of_fdt_device_is_available(blob, offset))
fpsizes[depth], continue;
&nps[depth+1], dryrun);
if (!fpsizes[depth+1]) if (!populate_node(blob, offset, &mem, nps[depth],
&nps[depth+1], dryrun))
return mem - base; return mem - base;
if (!dryrun && nodepp && !*nodepp) if (!dryrun && nodepp && !*nodepp)
...@@ -467,6 +437,7 @@ static int unflatten_dt_nodes(const void *blob, ...@@ -467,6 +437,7 @@ static int unflatten_dt_nodes(const void *blob,
* @mynodes: The device_node tree created by the call * @mynodes: The device_node tree created by the call
* @dt_alloc: An allocator that provides a virtual address to memory * @dt_alloc: An allocator that provides a virtual address to memory
* for the resulting tree * for the resulting tree
* @detached: if true set OF_DETACHED on @mynodes
* *
* Returns NULL on failure or the memory chunk containing the unflattened * Returns NULL on failure or the memory chunk containing the unflattened
* device tree on success. * device tree on success.
...@@ -652,7 +623,6 @@ static int __init __fdt_scan_reserved_mem(unsigned long node, const char *uname, ...@@ -652,7 +623,6 @@ static int __init __fdt_scan_reserved_mem(unsigned long node, const char *uname,
int depth, void *data) int depth, void *data)
{ {
static int found; static int found;
const char *status;
int err; int err;
if (!found && depth == 1 && strcmp(uname, "reserved-memory") == 0) { 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, ...@@ -672,8 +642,7 @@ static int __init __fdt_scan_reserved_mem(unsigned long node, const char *uname,
return 1; return 1;
} }
status = of_get_flat_dt_prop(node, "status", NULL); if (!of_fdt_device_is_available(initial_boot_params, node))
if (status && strcmp(status, "okay") != 0 && strcmp(status, "ok") != 0)
return 0; return 0;
err = __reserved_mem_reserve_reg(node, uname); err = __reserved_mem_reserve_reg(node, uname);
......
#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);
}
...@@ -35,18 +35,16 @@ extern struct mutex of_mutex; ...@@ -35,18 +35,16 @@ extern struct mutex of_mutex;
extern struct list_head aliases_lookup; extern struct list_head aliases_lookup;
extern struct kset *of_kset; 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) #if defined(CONFIG_OF_DYNAMIC)
extern int of_property_notify(int action, struct device_node *np, extern int of_property_notify(int action, struct device_node *np,
struct property *prop, struct property *old_prop); struct property *prop, struct property *old_prop);
extern void of_node_release(struct kobject *kobj); extern void of_node_release(struct kobject *kobj);
extern int __of_changeset_apply(struct of_changeset *ocs); extern int __of_changeset_apply_entries(struct of_changeset *ocs,
extern int __of_changeset_revert(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 */ #else /* CONFIG_OF_DYNAMIC */
static inline int of_property_notify(int action, struct device_node *np, static inline int of_property_notify(int action, struct device_node *np,
struct property *prop, struct property *old_prop) struct property *prop, struct property *old_prop)
...@@ -55,6 +53,41 @@ static inline int of_property_notify(int action, struct device_node *np, ...@@ -55,6 +53,41 @@ static inline int of_property_notify(int action, struct device_node *np,
} }
#endif /* CONFIG_OF_DYNAMIC */ #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) #if defined(CONFIG_OF_UNITTEST) && defined(CONFIG_OF_OVERLAY)
extern void __init unittest_unflatten_overlay_base(void); extern void __init unittest_unflatten_overlay_base(void);
#else #else
...@@ -77,6 +110,8 @@ extern void *__unflatten_device_tree(const void *blob, ...@@ -77,6 +110,8 @@ extern void *__unflatten_device_tree(const void *blob,
struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags); 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, ...); __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, struct device_node *__of_find_node_by_full_path(struct device_node *node,
const char *path); const char *path);
......
...@@ -25,253 +25,401 @@ ...@@ -25,253 +25,401 @@
#include "of_private.h" #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 * @target: target of the overlay operation
* @overlay: pointer to the overlay contents node * @overlay: pointer to the __overlay__ node
*
* Holds a single overlay state, including all the overlay logs &
* records.
*/ */
struct of_overlay_info { struct fragment {
struct device_node *target; struct device_node *target;
struct device_node *overlay; struct device_node *overlay;
bool is_symbols_node;
}; };
/** /**
* struct of_overlay - Holds a complete overlay transaction * struct overlay_changeset
* @node: List on which we are located * @ovcs_list: list on which we are located
* @count: Count of ovinfo structures * @overlay_tree: expanded device tree that contains the fragment nodes
* @ovinfo_tab: Overlay info table (count sized) * @count: count of fragment structures
* @cset: Changeset to be used * @fragments: fragment nodes in the overlay expanded device tree
* * @symbols_fragment: last element of @fragments[] is the __symbols__ node
* Holds a complete overlay transaction * @cset: changeset to apply fragments to live device tree
*/ */
struct of_overlay { struct overlay_changeset {
int id; int id;
struct list_head node; struct list_head ovcs_list;
struct device_node *overlay_tree;
int count; int count;
struct of_overlay_info *ovinfo_tab; struct fragment *fragments;
bool symbols_fragment;
struct of_changeset cset; struct of_changeset cset;
}; };
static int of_overlay_apply_one(struct of_overlay *ov, /* flags are sticky - once set, do not reset */
struct device_node *target, const struct device_node *overlay, static int devicetree_state_flags;
bool is_symbols_node); #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) 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); EXPORT_SYMBOL_GPL(of_overlay_notifier_register);
int of_overlay_notifier_unregister(struct notifier_block *nb) 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); EXPORT_SYMBOL_GPL(of_overlay_notifier_unregister);
static int of_overlay_notify(struct of_overlay *ov, 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) enum of_overlay_notify_action action)
{ {
struct of_overlay_notify_data nd; struct of_overlay_notify_data nd;
int i, ret; int i, ret;
for (i = 0; i < ov->count; i++) { for (i = 0; i < ovcs->count; i++) {
struct of_overlay_info *ovinfo = &ov->ovinfo_tab[i]; struct fragment *fragment = &ovcs->fragments[i];
nd.target = ovinfo->target; nd.target = fragment->target;
nd.overlay = ovinfo->overlay; nd.overlay = fragment->overlay;
ret = blocking_notifier_call_chain(&of_overlay_chain, ret = blocking_notifier_call_chain(&overlay_notify_chain,
action, &nd); action, &nd);
if (ret) if (ret == NOTIFY_OK || ret == NOTIFY_STOP)
return notifier_to_errno(ret); 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; 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 fragment *fragment;
struct property *new; struct property *new_prop;
const char *overlay_name; struct device_node *fragment_node;
char *label_path; struct device_node *overlay_node;
char *symbol_path; const char *path;
const char *path_tail;
const char *target_path; const char *target_path;
int k; int k;
int label_path_len;
int overlay_name_len; int overlay_name_len;
int path_len;
int path_tail_len;
int target_path_len; int target_path_len;
if (!prop->value) if (!prop->value)
return NULL; return NULL;
symbol_path = prop->value; if (strnlen(prop->value, prop->length) >= prop->length)
new = kzalloc(sizeof(*new), GFP_KERNEL);
if (!new)
return NULL; return NULL;
path = prop->value;
path_len = strlen(path);
for (k = 0; k < ov->count; k++) { if (path_len < 1)
ovinfo = &ov->ovinfo_tab[k]; return NULL;
overlay_name = ovinfo->overlay->full_name; fragment_node = __of_find_node_by_path(ovcs->overlay_tree, path + 1);
overlay_name_len = strlen(overlay_name); overlay_node = __of_find_node_by_path(fragment_node, "__overlay__/");
if (!strncasecmp(symbol_path, overlay_name, overlay_name_len)) 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; break;
} }
if (k >= ovcs->count)
return NULL;
overlay_name_len = snprintf(NULL, 0, "%pOF", fragment->overlay);
if (k >= ov->count) if (overlay_name_len > path_len)
goto err_free; 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); target_path_len = strlen(target_path);
label_path = symbol_path + overlay_name_len; new_prop = kzalloc(sizeof(*new_prop), GFP_KERNEL);
label_path_len = strlen(label_path); if (!new_prop)
goto err_free_target_path;
new->name = kstrdup(prop->name, GFP_KERNEL); new_prop->name = kstrdup(prop->name, GFP_KERNEL);
new->length = target_path_len + label_path_len + 1; new_prop->length = target_path_len + path_tail_len + 1;
new->value = kzalloc(new->length, GFP_KERNEL); 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) strcpy(new_prop->value, target_path);
goto err_free; strcpy(new_prop->value + target_path_len, path_tail);
strcpy(new->value, target_path); of_property_set_flag(new_prop, OF_DYNAMIC);
strcpy(new->value + target_path_len, label_path);
/* mark the property as dynamic */ return new_prop;
of_property_set_flag(new, OF_DYNAMIC);
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; return NULL;
} }
static int of_overlay_apply_single_property(struct of_overlay *ov, /**
struct device_node *target, struct property *prop, * add_changeset_property() - add @overlay_prop to overlay changeset
bool is_symbols_node) * @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 */ prop = of_find_property(target_node, overlay_prop->name, NULL);
tprop = of_find_property(target, prop->name, NULL);
/* special properties are not meant to be updated (silent NOP) */ if (!of_prop_cmp(overlay_prop->name, "name") ||
if (of_prop_cmp(prop->name, "name") == 0 || !of_prop_cmp(overlay_prop->name, "phandle") ||
of_prop_cmp(prop->name, "phandle") == 0 || !of_prop_cmp(overlay_prop->name, "linux,phandle"))
of_prop_cmp(prop->name, "linux,phandle") == 0)
return 0; return 0;
if (is_symbols_node) { if (is_symbols_prop) {
/* changing a property in __symbols__ node not allowed */ if (prop)
if (tprop)
return -EINVAL; return -EINVAL;
propn = dup_and_fixup_symbol_prop(ov, prop); new_prop = dup_and_fixup_symbol_prop(ovcs, overlay_prop);
} else { } 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; return -ENOMEM;
/* not found? add */ if (!prop)
if (tprop == NULL) ret = of_changeset_add_property(&ovcs->cset, target_node,
return of_changeset_add_property(&ov->cset, target, propn); new_prop);
else
ret = of_changeset_update_property(&ovcs->cset, target_node,
new_prop);
/* found? update */ if (ret) {
return of_changeset_update_property(&ov->cset, target, propn); 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; struct device_node *tchild;
int ret = 0; int ret = 0;
cname = kbasename(child->full_name); node_kbasename = kbasename(node->full_name);
if (cname == NULL)
return -ENOMEM;
/* NOTE: Multiple mods of created nodes not supported */ for_each_child_of_node(target_node, tchild)
for_each_child_of_node(target, tchild) if (!of_node_cmp(node_kbasename, kbasename(tchild->full_name)))
if (!of_node_cmp(cname, kbasename(tchild->full_name)))
break; break;
if (tchild != NULL) { if (!tchild) {
/* new overlay phandle value conflicts with existing value */ tchild = __of_node_dup(node, "%pOF/%s",
if (child->phandle) target_node, node_kbasename);
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) if (!tchild)
return -ENOMEM; return -ENOMEM;
/* point to parent */ tchild->parent = target_node;
tchild->parent = target;
ret = of_changeset_attach_node(&ov->cset, tchild); ret = of_changeset_attach_node(&ovcs->cset, tchild);
if (ret) if (ret)
return ret; return ret;
ret = of_overlay_apply_one(ov, tchild, child, 0); return build_changeset_next_level(ovcs, tchild, node);
if (ret)
return ret;
} }
if (node->phandle && tchild->phandle)
ret = -EINVAL;
else
ret = build_changeset_next_level(ovcs, tchild, node);
of_node_put(tchild);
return ret; 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.
*
* Do not allow symbols node to have any children.
* *
* Note that the in case of an error the target node is left * Returns 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if
* in a inconsistent state. Error recovery should be performed * invalid @overlay_node.
* by using the changeset.
*/ */
static int of_overlay_apply_one(struct of_overlay *ov, static int build_changeset_next_level(struct overlay_changeset *ovcs,
struct device_node *target, const struct device_node *overlay, struct device_node *target_node,
bool is_symbols_node) const struct device_node *overlay_node)
{ {
struct device_node *child; struct device_node *child;
struct property *prop; struct property *prop;
int ret; int ret;
for_each_property_of_node(overlay, prop) { for_each_property_of_node(overlay_node, prop) {
ret = of_overlay_apply_single_property(ov, target, prop, ret = add_changeset_property(ovcs, target_node, prop, 0);
is_symbols_node);
if (ret) { if (ret) {
pr_err("Failed to apply prop @%pOF/%s\n", pr_debug("Failed to apply prop @%pOF/%s, err=%d\n",
target, prop->name); target_node, prop->name, ret);
return ret;
}
}
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; return ret;
} }
} }
/* do not allow symbols node to have any children */
if (is_symbols_node)
return 0; return 0;
}
for_each_child_of_node(overlay, child) { /*
ret = of_overlay_apply_single_device_node(ov, target, child); * Add the properties from __overlay__ node to the @ovcs->cset changeset.
if (ret != 0) { */
pr_err("Failed to apply single node @%pOF/%s\n", static int build_changeset_symbols_node(struct overlay_changeset *ovcs,
target, child->name); struct device_node *target_node,
of_node_put(child); 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 ret;
} }
} }
...@@ -280,27 +428,49 @@ static int of_overlay_apply_one(struct of_overlay *ov, ...@@ -280,27 +428,49 @@ static int of_overlay_apply_one(struct of_overlay *ov,
} }
/** /**
* of_overlay_apply() - Apply @count overlays pointed at by @ovinfo_tab * build_changeset() - populate overlay changeset in @ovcs from @ovcs->fragments
* @ov: Overlay to apply * @ovcs: Overlay changeset
*
* 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.
* *
* Applies the overlays given, while handling all error conditions * Returns 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if
* appropriately. Either the operation succeeds, or if it fails the * invalid overlay in @ovcs->fragments[].
* live tree is reverted to the state before the attempt.
* Returns 0, or an error if the overlay attempt failed.
*/ */
static int of_overlay_apply(struct of_overlay *ov) static int build_changeset(struct overlay_changeset *ovcs)
{ {
int i, err; 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;
/* first we apply the overlays atomically */ for (i = 0; i < fragments_count; i++) {
for (i = 0; i < ov->count; i++) { fragment = &ovcs->fragments[i];
struct of_overlay_info *ovinfo = &ov->ovinfo_tab[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, if (ovcs->symbols_fragment) {
ovinfo->is_symbols_node); fragment = &ovcs->fragments[ovcs->count - 1];
if (err != 0) { ret = build_changeset_symbols_node(ovcs, fragment->target,
pr_err("apply failed '%pOF'\n", ovinfo->target); fragment->overlay);
return err; 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) ...@@ -309,10 +479,10 @@ static int of_overlay_apply(struct of_overlay *ov)
/* /*
* Find the target node using a number of different strategies * 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 * 1) "target" property containing the phandle of the target
* "target-path" property containing the path 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) 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) ...@@ -320,14 +490,12 @@ static struct device_node *find_target_node(struct device_node *info_node)
u32 val; u32 val;
int ret; int ret;
/* first try to go by using the target as a phandle */
ret = of_property_read_u32(info_node, "target", &val); ret = of_property_read_u32(info_node, "target", &val);
if (ret == 0) if (!ret)
return of_find_node_by_phandle(val); return of_find_node_by_phandle(val);
/* now try to locate by path */
ret = of_property_read_string(info_node, "target-path", &path); ret = of_property_read_string(info_node, "target-path", &path);
if (ret == 0) if (!ret)
return of_find_node_by_path(path); return of_find_node_by_path(path);
pr_err("Failed to find target for node %p (%s)\n", 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) ...@@ -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 * init_overlay_changeset() - initialize overlay changeset from overlay tree
* @ov Overlay to fill * @ovcs Overlay changeset to build
* @info_node: Device node containing the overlay * @tree: Contains all the overlay fragments and overlay fixup nodes
* @ovinfo: Pointer to the overlay info structure to fill *
* * Initialize @ovcs. Populate @ovcs->fragments with node information from
* Fills an overlay info structure with the overlay information * the top level of @tree. The relevant top level nodes are the fragment
* from a device node. This device node must have a target property * nodes and the __symbols__ node. Any other top level node will be ignored.
* which contains a phandle of the overlay target node, and an *
* __overlay__ child node which has the overlay contents. * Returns 0 on success, -ENOMEM if memory allocation failure, -EINVAL if error
* Both ovinfo->target & ovinfo->overlay have their references taken. * detected in @tree, or -ENOSPC if idr_alloc() error.
*
* Returns 0 on success, or a negative error value.
*/ */
static int of_fill_overlay_info(struct of_overlay *ov, static int init_overlay_changeset(struct overlay_changeset *ovcs,
struct device_node *info_node, struct of_overlay_info *ovinfo) struct device_node *tree)
{ {
ovinfo->overlay = of_get_child_by_name(info_node, "__overlay__"); struct device_node *node, *overlay_node;
if (ovinfo->overlay == NULL) struct fragment *fragment;
goto err_fail; struct fragment *fragments;
int cnt, ret;
/*
* 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__);
ovinfo->target = find_target_node(info_node); if (!of_node_check_flag(tree, OF_DETACHED))
if (ovinfo->target == NULL) pr_debug("%s() tree is not detached\n", __func__);
goto err_fail;
return 0; if (!of_node_is_root(tree))
pr_debug("%s() tree is not root\n", __func__);
err_fail: ovcs->overlay_tree = tree;
of_node_put(ovinfo->target);
of_node_put(ovinfo->overlay);
memset(ovinfo, 0, sizeof(*ovinfo)); INIT_LIST_HEAD(&ovcs->ovcs_list);
return -EINVAL;
}
/** of_changeset_init(&ovcs->cset);
* of_build_overlay_info() - Build an overlay info array
* @ov Overlay to build ovcs->id = idr_alloc(&ovcs_idr, ovcs, 1, 0, GFP_KERNEL);
* @tree: Device node containing all the overlays if (ovcs->id <= 0)
* return ovcs->id;
* 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;
/* worst case; every child is a node */
cnt = 0; cnt = 0;
for_each_child_of_node(tree, node)
/* fragment nodes */
for_each_child_of_node(tree, node) {
overlay_node = of_get_child_by_name(node, "__overlay__");
if (overlay_node) {
cnt++; cnt++;
of_node_put(overlay_node);
}
}
if (of_get_child_by_name(tree, "__symbols__")) node = of_get_child_by_name(tree, "__symbols__");
if (node) {
cnt++; cnt++;
of_node_put(node);
}
ovinfo = kcalloc(cnt, sizeof(*ovinfo), GFP_KERNEL); fragments = kcalloc(cnt, sizeof(*fragments), GFP_KERNEL);
if (ovinfo == NULL) if (!fragments) {
return -ENOMEM; ret = -ENOMEM;
goto err_free_idr;
}
cnt = 0; cnt = 0;
for_each_child_of_node(tree, node) { for_each_child_of_node(tree, node) {
err = of_fill_overlay_info(ov, node, &ovinfo[cnt]); fragment = &fragments[cnt];
if (err == 0) 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++; 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__"); node = of_get_child_by_name(tree, "__symbols__");
if (node) { if (node) {
ovinfo[cnt].overlay = node; ovcs->symbols_fragment = 1;
ovinfo[cnt].target = of_find_node_by_path("/__symbols__"); fragment = &fragments[cnt];
ovinfo[cnt].is_symbols_node = 1; fragment->overlay = node;
fragment->target = of_find_node_by_path("/__symbols__");
if (!ovinfo[cnt].target) {
pr_err("no symbols in root of device tree.\n"); if (!fragment->target) {
return -EINVAL; pr_err("symbols in overlay, but not in live tree\n");
ret = -EINVAL;
goto err_free_fragments;
} }
cnt++; cnt++;
} }
/* if nothing filled, return error */ if (!cnt) {
if (cnt == 0) { ret = -EINVAL;
kfree(ovinfo); goto err_free_fragments;
return -ENODEV;
} }
ov->count = cnt; ovcs->count = cnt;
ov->ovinfo_tab = ovinfo; ovcs->fragments = fragments;
return 0; 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;
} }
/** static void free_overlay_changeset(struct overlay_changeset *ovcs)
* 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)
{ {
struct of_overlay_info *ovinfo;
int i; int i;
/* do it in reverse */ if (!ovcs->cset.entries.next)
for (i = ov->count - 1; i >= 0; i--) { return;
ovinfo = &ov->ovinfo_tab[i]; of_changeset_destroy(&ovcs->cset);
if (ovcs->id)
idr_remove(&ovcs_idr, ovcs->id);
of_node_put(ovinfo->target); for (i = 0; i < ovcs->count; i++) {
of_node_put(ovinfo->overlay); 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 * of_overlay_apply() - Create and apply an overlay changeset
* @tree: Device node containing all the overlays * @tree: Expanded overlay device tree
* @ovcs_id: Pointer to overlay changeset id
*
* 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
*
* 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.
* *
* Creates and applies an overlay while also keeping track * If more than one notifier returns an error, then the last notifier
* of the overlay in a list. This list can be used to prevent * error to occur is returned.
* illegal overlay removals.
* *
* Returns the id of the created overlay, or a negative error number * 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; struct overlay_changeset *ovcs;
int err, id; int ret = 0, ret_revert, ret_tmp;
/* allocate the overlay structure */ *ovcs_id = 0;
ov = kzalloc(sizeof(*ov), GFP_KERNEL);
if (ov == NULL)
return -ENOMEM;
ov->id = -1;
INIT_LIST_HEAD(&ov->node); if (devicetree_corrupt()) {
pr_err("devicetree state suspect, refuse to apply overlay\n");
ret = -EBUSY;
goto out;
}
of_changeset_init(&ov->cset); ovcs = kzalloc(sizeof(*ovcs), GFP_KERNEL);
if (!ovcs) {
ret = -ENOMEM;
goto out;
}
of_overlay_mutex_lock();
ret = of_resolve_phandles(tree);
if (ret)
goto err_overlay_unlock;
mutex_lock(&of_mutex); mutex_lock(&of_mutex);
id = idr_alloc(&ov_idr, ov, 0, 0, GFP_KERNEL); ret = init_overlay_changeset(ovcs, tree);
if (id < 0) { if (ret)
err = id; goto err_free_overlay_changeset;
goto err_destroy_trans;
}
ov->id = id;
/* build the overlay info structures */ ret = overlay_notify(ovcs, OF_OVERLAY_PRE_APPLY);
err = of_build_overlay_info(ov, tree); if (ret) {
if (err) { pr_err("overlay changeset pre-apply notify error %d\n", ret);
pr_err("of_build_overlay_info() failed for tree@%pOF\n", goto err_free_overlay_changeset;
tree);
goto err_free_idr;
} }
err = of_overlay_notify(ov, OF_OVERLAY_PRE_APPLY); ret = build_changeset(ovcs);
if (err < 0) { if (ret)
pr_err("%s: Pre-apply notifier failed (err=%d)\n", goto err_free_overlay_changeset;
__func__, err);
goto err_free_idr;
}
/* apply the overlay */ ret_revert = 0;
err = of_overlay_apply(ov); ret = __of_changeset_apply_entries(&ovcs->cset, &ret_revert);
if (err) if (ret) {
goto err_abort_trans; 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 changeset */ list_add_tail(&ovcs->ovcs_list, &ovcs_list);
err = __of_changeset_apply(&ov->cset); *ovcs_id = ovcs->id;
if (err)
goto err_revert_overlay;
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 */ mutex_unlock(&of_mutex);
list_add_tail(&ov->node, &ov_list); 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); 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, * Find @np in @tree.
struct device_node *dn) *
* 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; struct device_node *child;
/* match? */ if (tree == np)
if (tree == dn)
return 1; return 1;
for_each_child_of_node(tree, child) { for_each_child_of_node(tree, child) {
if (overlay_subtree_check(child, dn)) { if (find_node(child, np)) {
of_node_put(child); of_node_put(child);
return 1; return 1;
} }
...@@ -567,29 +797,39 @@ static int overlay_subtree_check(struct device_node *tree, ...@@ -567,29 +797,39 @@ static int overlay_subtree_check(struct device_node *tree,
return 0; 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; struct of_changeset_entry *ce;
list_for_each_entry_reverse(ovt, &ov_list, node) { list_for_each_entry_reverse(ovcs, &ovcs_list, ovcs_list) {
/* if we hit ourselves, we're done */ if (ovcs == remove_ovcs)
if (ovt == ov)
break; break;
/* check against each subtree affected by this overlay */ list_for_each_entry(ce, &ovcs->cset.entries, node) {
list_for_each_entry(ce, &ovt->cset.entries, node) { if (find_node(ce->np, remove_ce_node)) {
if (overlay_subtree_check(ce->np, dn)) { pr_err("%s: #%d overlaps with #%d @%pOF\n",
pr_err("%s: #%d clashes #%d @%pOF\n", __func__, remove_ovcs->id, ovcs->id,
__func__, ov->id, ovt->id, dn); remove_ce_node);
return 0; 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 0;
return 1;
} }
/* /*
...@@ -602,13 +842,13 @@ static int overlay_is_topmost(struct of_overlay *ov, struct device_node *dn) ...@@ -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 * 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. * 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) { list_for_each_entry(remove_ce, &remove_ovcs->cset.entries, node) {
if (!overlay_is_topmost(ov, ce->np)) { if (node_overlaps_later_cs(remove_ovcs, remove_ce->np)) {
pr_err("overlay #%d is not topmost\n", ov->id); pr_err("overlay #%d is not topmost\n", remove_ovcs->id);
return 0; return 0;
} }
} }
...@@ -617,75 +857,130 @@ static int overlay_removal_is_ok(struct of_overlay *ov) ...@@ -617,75 +857,130 @@ static int overlay_removal_is_ok(struct of_overlay *ov)
} }
/** /**
* of_overlay_destroy() - Removes an overlay * of_overlay_remove() - Revert and free an overlay changeset
* @id: Overlay id number returned by a previous call to of_overlay_create * @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; struct overlay_changeset *ovcs;
int err; int ret, ret_apply, ret_tmp;
mutex_lock(&of_mutex); ret = 0;
ov = idr_find(&ov_idr, id); if (devicetree_corrupt()) {
if (ov == NULL) { pr_err("suspect devicetree state, refuse to remove overlay\n");
err = -ENODEV; ret = -EBUSY;
pr_err("destroy: Could not find overlay #%d\n", id);
goto out; goto out;
} }
/* check whether the overlay is safe to remove */ mutex_lock(&of_mutex);
if (!overlay_removal_is_ok(ov)) {
err = -EBUSY; ovcs = idr_find(&ovcs_idr, *ovcs_id);
goto out; 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); if (!overlay_removal_is_ok(ovcs)) {
list_del(&ov->node); ret = -EBUSY;
__of_changeset_revert(&ov->cset); goto out_unlock;
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);
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); 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. * Removes all overlays from the system in the correct order.
* *
* Returns 0 on success, or a negative error number * 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; struct overlay_changeset *ovcs, *ovcs_n;
int ret;
mutex_lock(&of_mutex);
/* the tail of list is guaranteed to be safe to remove */ /* the tail of list is guaranteed to be safe to remove */
list_for_each_entry_safe_reverse(ov, ovn, &ov_list, node) { list_for_each_entry_safe_reverse(ovcs, ovcs_n, &ovcs_list, ovcs_list) {
list_del(&ov->node); ret = of_overlay_remove(&ovcs->id);
__of_changeset_revert(&ov->cset); if (ret)
of_free_overlay_info(ov); return ret;
idr_remove(&ov_idr, ov->id);
kfree(ov);
} }
mutex_unlock(&of_mutex);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(of_overlay_destroy_all); EXPORT_SYMBOL_GPL(of_overlay_remove_all);
...@@ -84,10 +84,9 @@ static int update_usages_of_a_phandle_reference(struct device_node *overlay, ...@@ -84,10 +84,9 @@ static int update_usages_of_a_phandle_reference(struct device_node *overlay,
int offset, len; int offset, len;
int err = 0; int err = 0;
value = kmalloc(prop_fixup->length, GFP_KERNEL); value = kmemdup(prop_fixup->value, prop_fixup->length, GFP_KERNEL);
if (!value) if (!value)
return -ENOMEM; return -ENOMEM;
memcpy(value, prop_fixup->value, prop_fixup->length);
/* prop_fixup contains a list of tuples of path:property_name:offset */ /* prop_fixup contains a list of tuples of path:property_name:offset */
end = value + prop_fixup->length; end = value + prop_fixup->length;
...@@ -165,7 +164,6 @@ static int adjust_local_phandle_references(struct device_node *local_fixups, ...@@ -165,7 +164,6 @@ static int adjust_local_phandle_references(struct device_node *local_fixups,
struct property *prop_fix, *prop; struct property *prop_fix, *prop;
int err, i, count; int err, i, count;
unsigned int off; unsigned int off;
phandle phandle;
if (!local_fixups) if (!local_fixups)
return 0; return 0;
...@@ -195,9 +193,7 @@ static int adjust_local_phandle_references(struct device_node *local_fixups, ...@@ -195,9 +193,7 @@ static int adjust_local_phandle_references(struct device_node *local_fixups,
if ((off + 4) > prop->length) if ((off + 4) > prop->length)
return -EINVAL; return -EINVAL;
phandle = be32_to_cpu(*(__be32 *)(prop->value + off)); be32_add_cpu(prop->value + off, phandle_delta);
phandle += phandle_delta;
*(__be32 *)(prop->value + off) = cpu_to_be32(phandle);
} }
} }
...@@ -275,11 +271,18 @@ int of_resolve_phandles(struct device_node *overlay) ...@@ -275,11 +271,18 @@ int of_resolve_phandles(struct device_node *overlay)
err = -EINVAL; err = -EINVAL;
goto out; 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)) { if (!of_node_check_flag(overlay, OF_DETACHED)) {
pr_err("overlay not detached\n"); pr_err("overlay not detached\n");
err = -EINVAL; err = -EINVAL;
goto out; goto out;
} }
#endif
phandle_delta = live_tree_max_phandle() + 1; phandle_delta = live_tree_max_phandle() + 1;
adjust_overlay_phandles(overlay, phandle_delta); adjust_overlay_phandles(overlay, phandle_delta);
......
...@@ -994,10 +994,17 @@ static int __init unittest_data_add(void) ...@@ -994,10 +994,17 @@ static int __init unittest_data_add(void)
pr_warn("%s: No tree to attach; not running tests\n", __func__); pr_warn("%s: No tree to attach; not running tests\n", __func__);
return -ENODATA; 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); rc = of_resolve_phandles(unittest_data_node);
if (rc) { if (rc) {
pr_err("%s: Failed to resolve phandles (rc=%i)\n", __func__, rc); pr_err("%s: Failed to resolve phandles (rc=%i)\n", __func__, rc);
of_overlay_mutex_unlock();
return -EINVAL; return -EINVAL;
} }
...@@ -1007,6 +1014,7 @@ static int __init unittest_data_add(void) ...@@ -1007,6 +1014,7 @@ static int __init unittest_data_add(void)
__of_attach_node_sysfs(np); __of_attach_node_sysfs(np);
of_aliases = of_find_node_by_path("/aliases"); of_aliases = of_find_node_by_path("/aliases");
of_chosen = of_find_node_by_path("/chosen"); of_chosen = of_find_node_by_path("/chosen");
of_overlay_mutex_unlock();
return 0; return 0;
} }
...@@ -1019,6 +1027,9 @@ static int __init unittest_data_add(void) ...@@ -1019,6 +1027,9 @@ static int __init unittest_data_add(void)
attach_node_and_children(np); attach_node_and_children(np);
np = next; np = next;
} }
of_overlay_mutex_unlock();
return 0; return 0;
} }
...@@ -1219,7 +1230,7 @@ static void of_unittest_untrack_overlay(int id) ...@@ -1219,7 +1230,7 @@ static void of_unittest_untrack_overlay(int id)
static void of_unittest_destroy_tracked_overlays(void) static void of_unittest_destroy_tracked_overlays(void)
{ {
int id, ret, defers; int id, ret, defers, ovcs_id;
if (overlay_first_id < 0) if (overlay_first_id < 0)
return; return;
...@@ -1232,7 +1243,8 @@ static void of_unittest_destroy_tracked_overlays(void) ...@@ -1232,7 +1243,8 @@ static void of_unittest_destroy_tracked_overlays(void)
if (!(overlay_id_bits[BIT_WORD(id)] & BIT_MASK(id))) if (!(overlay_id_bits[BIT_WORD(id)] & BIT_MASK(id)))
continue; continue;
ret = of_overlay_destroy(id + overlay_first_id); ovcs_id = id + overlay_first_id;
ret = of_overlay_remove(&ovcs_id);
if (ret == -ENODEV) { if (ret == -ENODEV) {
pr_warn("%s: no overlay to destroy for #%d\n", pr_warn("%s: no overlay to destroy for #%d\n",
__func__, id + overlay_first_id); __func__, id + overlay_first_id);
...@@ -1254,7 +1266,7 @@ static int of_unittest_apply_overlay(int overlay_nr, int unittest_nr, ...@@ -1254,7 +1266,7 @@ static int of_unittest_apply_overlay(int overlay_nr, int unittest_nr,
int *overlay_id) int *overlay_id)
{ {
struct device_node *np = NULL; struct device_node *np = NULL;
int ret, id = -1; int ret;
np = of_find_node_by_path(overlay_path(overlay_nr)); np = of_find_node_by_path(overlay_path(overlay_nr));
if (np == NULL) { if (np == NULL) {
...@@ -1264,23 +1276,20 @@ static int of_unittest_apply_overlay(int overlay_nr, int unittest_nr, ...@@ -1264,23 +1276,20 @@ static int of_unittest_apply_overlay(int overlay_nr, int unittest_nr,
goto out; goto out;
} }
ret = of_overlay_create(np); *overlay_id = 0;
ret = of_overlay_apply(np, overlay_id);
if (ret < 0) { if (ret < 0) {
unittest(0, "could not create overlay from \"%s\"\n", unittest(0, "could not create overlay from \"%s\"\n",
overlay_path(overlay_nr)); overlay_path(overlay_nr));
goto out; goto out;
} }
id = ret; of_unittest_track_overlay(*overlay_id);
of_unittest_track_overlay(id);
ret = 0; ret = 0;
out: out:
of_node_put(np); of_node_put(np);
if (overlay_id)
*overlay_id = id;
return ret; return ret;
} }
...@@ -1288,7 +1297,7 @@ static int of_unittest_apply_overlay(int overlay_nr, int unittest_nr, ...@@ -1288,7 +1297,7 @@ static int of_unittest_apply_overlay(int overlay_nr, int unittest_nr,
static int of_unittest_apply_overlay_check(int overlay_nr, int unittest_nr, static int of_unittest_apply_overlay_check(int overlay_nr, int unittest_nr,
int before, int after, enum overlay_type ovtype) int before, int after, enum overlay_type ovtype)
{ {
int ret; int ret, ovcs_id;
/* unittest device must not be in before state */ /* unittest device must not be in before state */
if (of_unittest_device_exists(unittest_nr, ovtype) != before) { if (of_unittest_device_exists(unittest_nr, ovtype) != before) {
...@@ -1299,7 +1308,8 @@ static int of_unittest_apply_overlay_check(int overlay_nr, int unittest_nr, ...@@ -1299,7 +1308,8 @@ static int of_unittest_apply_overlay_check(int overlay_nr, int unittest_nr,
return -EINVAL; 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) { if (ret != 0) {
/* of_unittest_apply_overlay already called unittest() */ /* of_unittest_apply_overlay already called unittest() */
return ret; return ret;
...@@ -1322,7 +1332,7 @@ static int of_unittest_apply_revert_overlay_check(int overlay_nr, ...@@ -1322,7 +1332,7 @@ static int of_unittest_apply_revert_overlay_check(int overlay_nr,
int unittest_nr, int before, int after, int unittest_nr, int before, int after,
enum overlay_type ovtype) enum overlay_type ovtype)
{ {
int ret, ov_id; int ret, ovcs_id;
/* unittest device must be in before state */ /* unittest device must be in before state */
if (of_unittest_device_exists(unittest_nr, ovtype) != before) { if (of_unittest_device_exists(unittest_nr, ovtype) != before) {
...@@ -1334,7 +1344,8 @@ static int of_unittest_apply_revert_overlay_check(int overlay_nr, ...@@ -1334,7 +1344,8 @@ static int of_unittest_apply_revert_overlay_check(int overlay_nr,
} }
/* apply the overlay */ /* 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) { if (ret != 0) {
/* of_unittest_apply_overlay already called unittest() */ /* of_unittest_apply_overlay already called unittest() */
return ret; return ret;
...@@ -1349,7 +1360,7 @@ static int of_unittest_apply_revert_overlay_check(int overlay_nr, ...@@ -1349,7 +1360,7 @@ static int of_unittest_apply_revert_overlay_check(int overlay_nr,
return -EINVAL; return -EINVAL;
} }
ret = of_overlay_destroy(ov_id); ret = of_overlay_remove(&ovcs_id);
if (ret != 0) { if (ret != 0) {
unittest(0, "overlay @\"%s\" failed to be destroyed @\"%s\"\n", unittest(0, "overlay @\"%s\" failed to be destroyed @\"%s\"\n",
overlay_path(overlay_nr), overlay_path(overlay_nr),
...@@ -1451,7 +1462,7 @@ static void of_unittest_overlay_5(void) ...@@ -1451,7 +1462,7 @@ static void of_unittest_overlay_5(void)
static void of_unittest_overlay_6(void) static void of_unittest_overlay_6(void)
{ {
struct device_node *np; 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 overlay_nr = 6, unittest_nr = 6;
int before = 0, after = 1; int before = 0, after = 1;
...@@ -1478,13 +1489,14 @@ static void of_unittest_overlay_6(void) ...@@ -1478,13 +1489,14 @@ static void of_unittest_overlay_6(void)
return; return;
} }
ret = of_overlay_create(np); ovcs_id = 0;
ret = of_overlay_apply(np, &ovcs_id);
if (ret < 0) { if (ret < 0) {
unittest(0, "could not create overlay from \"%s\"\n", unittest(0, "could not create overlay from \"%s\"\n",
overlay_path(overlay_nr + i)); overlay_path(overlay_nr + i));
return; return;
} }
ov_id[i] = ret; ov_id[i] = ovcs_id;
of_unittest_track_overlay(ov_id[i]); of_unittest_track_overlay(ov_id[i]);
} }
...@@ -1502,7 +1514,8 @@ static void of_unittest_overlay_6(void) ...@@ -1502,7 +1514,8 @@ static void of_unittest_overlay_6(void)
} }
for (i = 1; i >= 0; i--) { 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) { if (ret != 0) {
unittest(0, "overlay @\"%s\" failed destroy @\"%s\"\n", unittest(0, "overlay @\"%s\" failed destroy @\"%s\"\n",
overlay_path(overlay_nr + i), overlay_path(overlay_nr + i),
...@@ -1533,7 +1546,7 @@ static void of_unittest_overlay_6(void) ...@@ -1533,7 +1546,7 @@ static void of_unittest_overlay_6(void)
static void of_unittest_overlay_8(void) static void of_unittest_overlay_8(void)
{ {
struct device_node *np; 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; int overlay_nr = 8, unittest_nr = 8;
/* we don't care about device state in this test */ /* we don't care about device state in this test */
...@@ -1548,18 +1561,20 @@ static void of_unittest_overlay_8(void) ...@@ -1548,18 +1561,20 @@ static void of_unittest_overlay_8(void)
return; return;
} }
ret = of_overlay_create(np); ovcs_id = 0;
ret = of_overlay_apply(np, &ovcs_id);
if (ret < 0) { if (ret < 0) {
unittest(0, "could not create overlay from \"%s\"\n", unittest(0, "could not create overlay from \"%s\"\n",
overlay_path(overlay_nr + i)); overlay_path(overlay_nr + i));
return; return;
} }
ov_id[i] = ret; ov_id[i] = ovcs_id;
of_unittest_track_overlay(ov_id[i]); of_unittest_track_overlay(ov_id[i]);
} }
/* now try to remove first overlay (it should fail) */ /* 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) { if (ret == 0) {
unittest(0, "overlay @\"%s\" was destroyed @\"%s\"\n", unittest(0, "overlay @\"%s\" was destroyed @\"%s\"\n",
overlay_path(overlay_nr + 0), overlay_path(overlay_nr + 0),
...@@ -1570,7 +1585,8 @@ static void of_unittest_overlay_8(void) ...@@ -1570,7 +1585,8 @@ static void of_unittest_overlay_8(void)
/* removing them in order should work */ /* removing them in order should work */
for (i = 1; i >= 0; i--) { 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) { if (ret != 0) {
unittest(0, "overlay @\"%s\" not destroyed @\"%s\"\n", unittest(0, "overlay @\"%s\" not destroyed @\"%s\"\n",
overlay_path(overlay_nr + i), overlay_path(overlay_nr + i),
...@@ -2144,21 +2160,13 @@ static int __init overlay_data_add(int onum) ...@@ -2144,21 +2160,13 @@ static int __init overlay_data_add(int onum)
ret = 0; ret = 0;
goto out_free_data; goto out_free_data;
} }
of_node_set_flag(info->np_overlay, OF_DETACHED);
ret = of_resolve_phandles(info->np_overlay); info->overlay_id = 0;
if (ret) { ret = of_overlay_apply(info->np_overlay, &info->overlay_id);
pr_err("resolve ot phandles (ret=%d), %d\n", ret, onum);
goto out_free_np_overlay;
}
ret = of_overlay_create(info->np_overlay);
if (ret < 0) { 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; goto out_free_np_overlay;
} else {
info->overlay_id = ret;
ret = 0;
} }
pr_debug("__dtb_overlay_begin applied, overlay id %d\n", ret); pr_debug("__dtb_overlay_begin applied, overlay id %d\n", ret);
...@@ -2207,7 +2215,10 @@ static __init void of_unittest_overlay_high_level(void) ...@@ -2207,7 +2215,10 @@ static __init void of_unittest_overlay_high_level(void)
* Could not fixup phandles in unittest_unflatten_overlay_base() * Could not fixup phandles in unittest_unflatten_overlay_base()
* because kmalloc() was not yet available. * because kmalloc() was not yet available.
*/ */
of_overlay_mutex_lock();
of_resolve_phandles(overlay_base_root); of_resolve_phandles(overlay_base_root);
of_overlay_mutex_unlock();
/* /*
* do not allow overlay_base to duplicate any node already in * do not allow overlay_base to duplicate any node already in
......
...@@ -37,9 +37,15 @@ struct property { ...@@ -37,9 +37,15 @@ struct property {
int length; int length;
void *value; void *value;
struct property *next; struct property *next;
#if defined(CONFIG_OF_DYNAMIC) || defined(CONFIG_SPARC)
unsigned long _flags; unsigned long _flags;
#endif
#if defined(CONFIG_OF_PROMTREE)
unsigned int unique_id; unsigned int unique_id;
#endif
#if defined(CONFIG_OF_KOBJ)
struct bin_attribute attr; struct bin_attribute attr;
#endif
}; };
#if defined(CONFIG_SPARC) #if defined(CONFIG_SPARC)
...@@ -58,7 +64,9 @@ struct device_node { ...@@ -58,7 +64,9 @@ struct device_node {
struct device_node *parent; struct device_node *parent;
struct device_node *child; struct device_node *child;
struct device_node *sibling; struct device_node *sibling;
#if defined(CONFIG_OF_KOBJ)
struct kobject kobj; struct kobject kobj;
#endif
unsigned long _flags; unsigned long _flags;
void *data; void *data;
#if defined(CONFIG_SPARC) #if defined(CONFIG_SPARC)
...@@ -103,21 +111,17 @@ extern struct kobj_type of_node_ktype; ...@@ -103,21 +111,17 @@ extern struct kobj_type of_node_ktype;
extern const struct fwnode_operations of_fwnode_ops; extern const struct fwnode_operations of_fwnode_ops;
static inline void of_node_init(struct device_node *node) static inline void of_node_init(struct device_node *node)
{ {
#if defined(CONFIG_OF_KOBJ)
kobject_init(&node->kobj, &of_node_ktype); kobject_init(&node->kobj, &of_node_ktype);
#endif
node->fwnode.ops = &of_fwnode_ops; node->fwnode.ops = &of_fwnode_ops;
} }
/* true when node is initialized */ #if defined(CONFIG_OF_KOBJ)
static inline int of_node_is_initialized(struct device_node *node) #define of_node_kobj(n) (&(n)->kobj)
{ #else
return node && node->kobj.state_initialized; #define of_node_kobj(n) NULL
} #endif
/* 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;
}
#ifdef CONFIG_OF_DYNAMIC #ifdef CONFIG_OF_DYNAMIC
extern struct device_node *of_node_get(struct device_node *node); 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) ...@@ -203,6 +207,7 @@ static inline void of_node_clear_flag(struct device_node *n, unsigned long flag)
clear_bit(flag, &n->_flags); 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) static inline int of_property_check_flag(struct property *p, unsigned long flag)
{ {
return test_bit(flag, &p->_flags); return test_bit(flag, &p->_flags);
...@@ -217,6 +222,7 @@ static inline void of_property_clear_flag(struct property *p, unsigned long flag ...@@ -217,6 +222,7 @@ static inline void of_property_clear_flag(struct property *p, unsigned long flag
{ {
clear_bit(flag, &p->_flags); 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);
extern struct device_node *of_find_all_nodes(struct device_node *prev); extern struct device_node *of_find_all_nodes(struct device_node *prev);
...@@ -1283,9 +1289,6 @@ static inline int of_reconfig_get_state_change(unsigned long action, ...@@ -1283,9 +1289,6 @@ static inline int of_reconfig_get_state_change(unsigned long action,
} }
#endif /* CONFIG_OF_DYNAMIC */ #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 * of_device_is_system_power_controller - Tells if system-power-controller is found for device_node
* @np: Pointer to the given device_node * @np: Pointer to the given device_node
...@@ -1302,7 +1305,7 @@ static inline bool of_device_is_system_power_controller(const struct device_node ...@@ -1302,7 +1305,7 @@ static inline bool of_device_is_system_power_controller(const struct device_node
*/ */
enum of_overlay_notify_action { enum of_overlay_notify_action {
OF_OVERLAY_PRE_APPLY, OF_OVERLAY_PRE_APPLY = 0,
OF_OVERLAY_POST_APPLY, OF_OVERLAY_POST_APPLY,
OF_OVERLAY_PRE_REMOVE, OF_OVERLAY_PRE_REMOVE,
OF_OVERLAY_POST_REMOVE, OF_OVERLAY_POST_REMOVE,
...@@ -1316,26 +1319,26 @@ struct of_overlay_notify_data { ...@@ -1316,26 +1319,26 @@ struct of_overlay_notify_data {
#ifdef CONFIG_OF_OVERLAY #ifdef CONFIG_OF_OVERLAY
/* ID based overlays; the API for external users */ /* ID based overlays; the API for external users */
int of_overlay_create(struct device_node *tree); int of_overlay_apply(struct device_node *tree, int *ovcs_id);
int of_overlay_destroy(int id); int of_overlay_remove(int *ovcs_id);
int of_overlay_destroy_all(void); int of_overlay_remove_all(void);
int of_overlay_notifier_register(struct notifier_block *nb); int of_overlay_notifier_register(struct notifier_block *nb);
int of_overlay_notifier_unregister(struct notifier_block *nb); int of_overlay_notifier_unregister(struct notifier_block *nb);
#else #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; return -ENOTSUPP;
} }
static inline int of_overlay_destroy(int id) static inline int of_overlay_remove(int *ovcs_id)
{ {
return -ENOTSUPP; return -ENOTSUPP;
} }
static inline int of_overlay_destroy_all(void) static inline int of_overlay_remove_all(void)
{ {
return -ENOTSUPP; return -ENOTSUPP;
} }
......
...@@ -6,8 +6,6 @@ ...@@ -6,8 +6,6 @@
# INSTALL_DTBS_PATH directory or the default location: # INSTALL_DTBS_PATH directory or the default location:
# #
# $INSTALL_PATH/dtbs/$KERNELRELEASE # $INSTALL_PATH/dtbs/$KERNELRELEASE
#
# Traverse through subdirectories listed in $(dts-dirs).
# ========================================================================== # ==========================================================================
src := $(obj) src := $(obj)
...@@ -21,8 +19,8 @@ include include/config/auto.conf ...@@ -21,8 +19,8 @@ include include/config/auto.conf
include scripts/Kbuild.include include scripts/Kbuild.include
include $(src)/Makefile include $(src)/Makefile
dtbinst-files := $(dtb-y) dtbinst-files := $(sort $(dtb-y) $(if $(CONFIG_OF_ALL_DTBS), $(dtb-)))
dtbinst-dirs := $(dts-dirs) dtbinst-dirs := $(subdir-y) $(subdir-m)
# Helper targets for Installing DTBs into the boot directory # Helper targets for Installing DTBs into the boot directory
quiet_cmd_dtb_install = INSTALL $< quiet_cmd_dtb_install = INSTALL $<
......
...@@ -70,6 +70,11 @@ obj-dirs := $(dir $(multi-objs) $(obj-y)) ...@@ -70,6 +70,11 @@ obj-dirs := $(dir $(multi-objs) $(obj-y))
real-objs-y := $(foreach m, $(filter-out $(subdir-obj-y), $(obj-y)), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))),$($(m:.o=-objs)) $($(m:.o=-y)),$(m))) $(extra-y) real-objs-y := $(foreach m, $(filter-out $(subdir-obj-y), $(obj-y)), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))),$($(m:.o=-objs)) $($(m:.o=-y)),$(m))) $(extra-y)
real-objs-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y)) $($(m:.o=-m))),$($(m:.o=-objs)) $($(m:.o=-y)) $($(m:.o=-m)),$(m))) real-objs-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y)) $($(m:.o=-m))),$($(m:.o=-objs)) $($(m:.o=-y)) $($(m:.o=-m)),$(m)))
# DTB
# If CONFIG_OF_ALL_DTBS is enabled, all DT blobs are built
extra-y += $(dtb-y)
extra-$(CONFIG_OF_ALL_DTBS) += $(dtb-)
# Add subdir path # Add subdir path
extra-y := $(addprefix $(obj)/,$(extra-y)) extra-y := $(addprefix $(obj)/,$(extra-y))
......
...@@ -873,7 +873,7 @@ static void check_simple_bus_reg(struct check *c, struct dt_info *dti, struct no ...@@ -873,7 +873,7 @@ static void check_simple_bus_reg(struct check *c, struct dt_info *dti, struct no
while (size--) while (size--)
reg = (reg << 32) | fdt32_to_cpu(*(cells++)); 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)) if (!streq(unitname, unit_addr))
FAIL(c, dti, "Node %s simple-bus unit address format error, expected \"%s\"", FAIL(c, dti, "Node %s simple-bus unit address format error, expected \"%s\"",
node->fullpath, unit_addr); node->fullpath, unit_addr);
...@@ -956,6 +956,274 @@ static void check_obsolete_chosen_interrupt_controller(struct check *c, ...@@ -956,6 +956,274 @@ static void check_obsolete_chosen_interrupt_controller(struct check *c,
WARNING(obsolete_chosen_interrupt_controller, WARNING(obsolete_chosen_interrupt_controller,
check_obsolete_chosen_interrupt_controller, NULL); 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[] = { static struct check *check_table[] = {
&duplicate_node_names, &duplicate_property_names, &duplicate_node_names, &duplicate_property_names,
&node_name_chars, &node_name_format, &property_name_chars, &node_name_chars, &node_name_format, &property_name_chars,
...@@ -987,6 +1255,27 @@ static struct check *check_table[] = { ...@@ -987,6 +1255,27 @@ static struct check *check_table[] = {
&avoid_default_addr_size, &avoid_default_addr_size,
&obsolete_chosen_interrupt_controller, &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, &always_fail,
}; };
......
...@@ -1397,7 +1397,7 @@ static int yy_get_next_buffer (void) ...@@ -1397,7 +1397,7 @@ static int yy_get_next_buffer (void)
{ {
char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
char *source = (yytext_ptr); char *source = (yytext_ptr);
yy_size_t number_to_move, i; int number_to_move, i;
int ret_val; int ret_val;
if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) 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) ...@@ -1426,7 +1426,7 @@ static int yy_get_next_buffer (void)
/* Try to read more data. */ /* Try to read more data. */
/* First move last chars to start of buffer. */ /* 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 ) for ( i = 0; i < number_to_move; ++i )
*(dest++) = *(source++); *(dest++) = *(source++);
...@@ -1508,7 +1508,7 @@ static int yy_get_next_buffer (void) ...@@ -1508,7 +1508,7 @@ static int yy_get_next_buffer (void)
else else
ret_val = EOB_ACT_CONTINUE_SCAN; 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. */ /* Extend the array by 50%, plus the number we really need. */
int new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); 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 ); 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 ) ...@@ -1987,10 +1987,10 @@ YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len )
YY_BUFFER_STATE b; YY_BUFFER_STATE b;
char *buf; char *buf;
yy_size_t n; yy_size_t n;
yy_size_t i; int i;
/* Get memory for full buffer, including space for trailing EOB's. */ /* 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 ); buf = (char *) yyalloc(n );
if ( ! buf ) if ( ! buf )
YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
......
...@@ -448,7 +448,7 @@ union yyalloc ...@@ -448,7 +448,7 @@ union yyalloc
/* YYNNTS -- Number of nonterminals. */ /* YYNNTS -- Number of nonterminals. */
#define YYNNTS 30 #define YYNNTS 30
/* YYNRULES -- Number of rules. */ /* YYNRULES -- Number of rules. */
#define YYNRULES 84 #define YYNRULES 85
/* YYNSTATES -- Number of states. */ /* YYNSTATES -- Number of states. */
#define YYNSTATES 149 #define YYNSTATES 149
...@@ -499,14 +499,14 @@ static const yytype_uint8 yytranslate[] = ...@@ -499,14 +499,14 @@ static const yytype_uint8 yytranslate[] =
static const yytype_uint16 yyrline[] = static const yytype_uint16 yyrline[] =
{ {
0, 109, 109, 117, 121, 128, 129, 139, 142, 149, 0, 109, 109, 117, 121, 128, 129, 139, 142, 149,
153, 161, 165, 170, 181, 191, 206, 214, 217, 224, 153, 161, 165, 170, 181, 200, 213, 220, 228, 231,
228, 232, 236, 244, 248, 252, 256, 260, 276, 286, 238, 242, 246, 250, 258, 262, 266, 270, 274, 290,
294, 297, 301, 308, 324, 329, 348, 362, 369, 370, 300, 308, 311, 315, 322, 338, 343, 362, 376, 383,
371, 378, 382, 383, 387, 388, 392, 393, 397, 398, 384, 385, 392, 396, 397, 401, 402, 406, 407, 411,
402, 403, 407, 408, 412, 413, 414, 418, 419, 420, 412, 416, 417, 421, 422, 426, 427, 428, 432, 433,
421, 422, 426, 427, 428, 432, 433, 434, 438, 439, 434, 435, 436, 440, 441, 442, 446, 447, 448, 452,
448, 457, 461, 462, 463, 464, 469, 472, 476, 484, 453, 462, 471, 475, 476, 477, 478, 483, 486, 490,
487, 491, 499, 503, 507 498, 501, 505, 513, 517, 521
}; };
#endif #endif
...@@ -582,20 +582,20 @@ static const yytype_int8 yypact[] = ...@@ -582,20 +582,20 @@ static const yytype_int8 yypact[] =
static const yytype_uint8 yydefact[] = static const yytype_uint8 yydefact[] =
{ {
0, 0, 0, 5, 7, 3, 1, 6, 0, 0, 0, 0, 0, 5, 7, 3, 1, 6, 0, 0,
0, 7, 0, 38, 39, 0, 0, 10, 0, 2, 16, 7, 0, 39, 40, 0, 0, 10, 0, 2,
8, 4, 0, 0, 0, 72, 0, 41, 42, 44, 8, 4, 0, 0, 0, 73, 0, 42, 43, 45,
46, 48, 50, 52, 54, 57, 64, 67, 71, 0, 47, 49, 51, 53, 55, 58, 65, 68, 72, 0,
17, 11, 0, 0, 0, 0, 73, 74, 75, 40, 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, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,
79, 0, 0, 14, 12, 45, 0, 47, 49, 51, 80, 0, 0, 14, 12, 46, 0, 48, 50, 52,
53, 55, 56, 60, 61, 59, 58, 62, 63, 65, 54, 56, 57, 61, 62, 60, 59, 63, 64, 66,
66, 69, 68, 70, 0, 0, 0, 0, 18, 0, 67, 70, 69, 71, 0, 0, 0, 0, 19, 0,
79, 15, 13, 0, 0, 0, 20, 30, 82, 22, 80, 15, 13, 0, 0, 0, 21, 31, 83, 23,
84, 0, 81, 80, 43, 21, 83, 0, 0, 16, 85, 0, 82, 81, 44, 22, 84, 0, 0, 17,
29, 19, 31, 0, 23, 32, 26, 0, 76, 34, 30, 20, 32, 0, 24, 33, 27, 0, 77, 35,
0, 0, 0, 0, 37, 36, 24, 35, 33, 0, 0, 0, 0, 0, 38, 37, 25, 36, 34, 0,
77, 78, 25, 0, 28, 0, 0, 0, 27 78, 79, 26, 0, 29, 0, 0, 0, 28
}; };
/* YYPGOTO[NTERM-NUM]. */ /* YYPGOTO[NTERM-NUM]. */
...@@ -678,28 +678,28 @@ static const yytype_uint8 yystos[] = ...@@ -678,28 +678,28 @@ static const yytype_uint8 yystos[] =
static const yytype_uint8 yyr1[] = static const yytype_uint8 yyr1[] =
{ {
0, 48, 49, 50, 50, 51, 51, 52, 52, 53, 0, 48, 49, 50, 50, 51, 51, 52, 52, 53,
53, 54, 54, 54, 54, 54, 55, 56, 56, 57, 53, 54, 54, 54, 54, 54, 54, 55, 56, 56,
57, 57, 57, 58, 58, 58, 58, 58, 58, 58, 57, 57, 57, 57, 58, 58, 58, 58, 58, 58,
59, 59, 59, 60, 60, 60, 60, 60, 61, 61, 58, 59, 59, 59, 60, 60, 60, 60, 60, 61,
61, 62, 63, 63, 64, 64, 65, 65, 66, 66, 61, 61, 62, 63, 63, 64, 64, 65, 65, 66,
67, 67, 68, 68, 69, 69, 69, 70, 70, 70, 66, 67, 67, 68, 68, 69, 69, 69, 70, 70,
70, 70, 71, 71, 71, 72, 72, 72, 73, 73, 70, 70, 70, 71, 71, 71, 72, 72, 72, 73,
73, 73, 74, 74, 74, 74, 75, 75, 75, 76, 73, 73, 73, 74, 74, 74, 74, 75, 75, 75,
76, 76, 77, 77, 77 76, 76, 76, 77, 77, 77
}; };
/* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */
static const yytype_uint8 yyr2[] = static const yytype_uint8 yyr2[] =
{ {
0, 2, 3, 2, 4, 1, 2, 0, 2, 4, 0, 2, 3, 2, 4, 1, 2, 0, 2, 4,
2, 2, 3, 4, 3, 4, 5, 0, 2, 4, 2, 2, 3, 4, 3, 4, 0, 5, 0, 2,
2, 3, 2, 2, 3, 4, 2, 9, 5, 2, 4, 2, 3, 2, 2, 3, 4, 2, 9, 5,
0, 2, 2, 3, 1, 2, 2, 2, 1, 1, 2, 0, 2, 2, 3, 1, 2, 2, 2, 1,
3, 1, 1, 5, 1, 3, 1, 3, 1, 3, 1, 3, 1, 1, 5, 1, 3, 1, 3, 1,
1, 3, 1, 3, 1, 3, 3, 1, 3, 3, 3, 1, 3, 1, 3, 1, 3, 3, 1, 3,
3, 3, 3, 3, 1, 3, 3, 1, 3, 3, 3, 3, 3, 3, 3, 1, 3, 3, 1, 3,
3, 1, 1, 2, 2, 2, 0, 2, 2, 0, 3, 3, 1, 1, 2, 2, 2, 0, 2, 2,
2, 2, 2, 3, 2 0, 2, 2, 2, 3, 2
}; };
...@@ -1572,17 +1572,26 @@ yyreduce: ...@@ -1572,17 +1572,26 @@ yyreduce:
{ {
struct node *target = get_node_by_ref((yyvsp[-2].node), (yyvsp[-1].labelref)); struct node *target = get_node_by_ref((yyvsp[-2].node), (yyvsp[-1].labelref));
if (target) if (target) {
merge_nodes(target, (yyvsp[0].node)); merge_nodes(target, (yyvsp[0].node));
} 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 else
ERROR(&(yylsp[-1]), "Label or path %s not found", (yyvsp[-1].labelref)); ERROR(&(yylsp[-1]), "Label or path %s not found", (yyvsp[-1].labelref));
}
(yyval.node) = (yyvsp[-2].node); (yyval.node) = (yyvsp[-2].node);
} }
#line 1582 "dtc-parser.tab.c" /* yacc.c:1646 */ #line 1591 "dtc-parser.tab.c" /* yacc.c:1646 */
break; break;
case 15: 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)); struct node *target = get_node_by_ref((yyvsp[-3].node), (yyvsp[-1].labelref));
...@@ -1594,100 +1603,109 @@ yyreduce: ...@@ -1594,100 +1603,109 @@ yyreduce:
(yyval.node) = (yyvsp[-3].node); (yyval.node) = (yyvsp[-3].node);
} }
#line 1598 "dtc-parser.tab.c" /* yacc.c:1646 */ #line 1607 "dtc-parser.tab.c" /* yacc.c:1646 */
break; break;
case 16: 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; break;
case 17: 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; break;
case 18: 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; break;
case 19: 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; break;
case 20: 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; break;
case 21: 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; break;
case 22: 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)); add_label(&(yyvsp[0].prop)->labels, (yyvsp[-1].labelref));
(yyval.prop) = (yyvsp[0].prop); (yyval.prop) = (yyvsp[0].prop);
} }
#line 1655 "dtc-parser.tab.c" /* yacc.c:1646 */ #line 1673 "dtc-parser.tab.c" /* yacc.c:1646 */
break; break;
case 23: case 24:
#line 245 "dtc-parser.y" /* yacc.c:1646 */ #line 259 "dtc-parser.y" /* yacc.c:1646 */
{ {
(yyval.data) = data_merge((yyvsp[-1].data), (yyvsp[0].data)); (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; break;
case 24: case 25:
#line 249 "dtc-parser.y" /* yacc.c:1646 */ #line 263 "dtc-parser.y" /* yacc.c:1646 */
{ {
(yyval.data) = data_merge((yyvsp[-2].data), (yyvsp[-1].array).data); (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; break;
case 25: case 26:
#line 253 "dtc-parser.y" /* yacc.c:1646 */ #line 267 "dtc-parser.y" /* yacc.c:1646 */
{ {
(yyval.data) = data_merge((yyvsp[-3].data), (yyvsp[-1].data)); (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; break;
case 26: case 27:
#line 257 "dtc-parser.y" /* yacc.c:1646 */ #line 271 "dtc-parser.y" /* yacc.c:1646 */
{ {
(yyval.data) = data_add_marker((yyvsp[-1].data), REF_PATH, (yyvsp[0].labelref)); (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; break;
case 27: case 28:
#line 261 "dtc-parser.y" /* yacc.c:1646 */ #line 275 "dtc-parser.y" /* yacc.c:1646 */
{ {
FILE *f = srcfile_relative_open((yyvsp[-5].data).val, NULL); FILE *f = srcfile_relative_open((yyvsp[-5].data).val, NULL);
struct data d; struct data d;
...@@ -1703,11 +1721,11 @@ yyreduce: ...@@ -1703,11 +1721,11 @@ yyreduce:
(yyval.data) = data_merge((yyvsp[-8].data), d); (yyval.data) = data_merge((yyvsp[-8].data), d);
fclose(f); fclose(f);
} }
#line 1707 "dtc-parser.tab.c" /* yacc.c:1646 */ #line 1725 "dtc-parser.tab.c" /* yacc.c:1646 */
break; break;
case 28: case 29:
#line 277 "dtc-parser.y" /* yacc.c:1646 */ #line 291 "dtc-parser.y" /* yacc.c:1646 */
{ {
FILE *f = srcfile_relative_open((yyvsp[-1].data).val, NULL); FILE *f = srcfile_relative_open((yyvsp[-1].data).val, NULL);
struct data d = empty_data; struct data d = empty_data;
...@@ -1717,43 +1735,43 @@ yyreduce: ...@@ -1717,43 +1735,43 @@ yyreduce:
(yyval.data) = data_merge((yyvsp[-4].data), d); (yyval.data) = data_merge((yyvsp[-4].data), d);
fclose(f); fclose(f);
} }
#line 1721 "dtc-parser.tab.c" /* yacc.c:1646 */ #line 1739 "dtc-parser.tab.c" /* yacc.c:1646 */
break; break;
case 29: case 30:
#line 287 "dtc-parser.y" /* yacc.c:1646 */ #line 301 "dtc-parser.y" /* yacc.c:1646 */
{ {
(yyval.data) = data_add_marker((yyvsp[-1].data), LABEL, (yyvsp[0].labelref)); (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; break;
case 30: case 31:
#line 294 "dtc-parser.y" /* yacc.c:1646 */ #line 308 "dtc-parser.y" /* yacc.c:1646 */
{ {
(yyval.data) = empty_data; (yyval.data) = empty_data;
} }
#line 1737 "dtc-parser.tab.c" /* yacc.c:1646 */ #line 1755 "dtc-parser.tab.c" /* yacc.c:1646 */
break; break;
case 31: case 32:
#line 298 "dtc-parser.y" /* yacc.c:1646 */ #line 312 "dtc-parser.y" /* yacc.c:1646 */
{ {
(yyval.data) = (yyvsp[-1].data); (yyval.data) = (yyvsp[-1].data);
} }
#line 1745 "dtc-parser.tab.c" /* yacc.c:1646 */ #line 1763 "dtc-parser.tab.c" /* yacc.c:1646 */
break; break;
case 32: case 33:
#line 302 "dtc-parser.y" /* yacc.c:1646 */ #line 316 "dtc-parser.y" /* yacc.c:1646 */
{ {
(yyval.data) = data_add_marker((yyvsp[-1].data), LABEL, (yyvsp[0].labelref)); (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; break;
case 33: case 34:
#line 309 "dtc-parser.y" /* yacc.c:1646 */ #line 323 "dtc-parser.y" /* yacc.c:1646 */
{ {
unsigned long long bits; unsigned long long bits;
...@@ -1769,20 +1787,20 @@ yyreduce: ...@@ -1769,20 +1787,20 @@ yyreduce:
(yyval.array).data = empty_data; (yyval.array).data = empty_data;
(yyval.array).bits = bits; (yyval.array).bits = bits;
} }
#line 1773 "dtc-parser.tab.c" /* yacc.c:1646 */ #line 1791 "dtc-parser.tab.c" /* yacc.c:1646 */
break; break;
case 34: case 35:
#line 325 "dtc-parser.y" /* yacc.c:1646 */ #line 339 "dtc-parser.y" /* yacc.c:1646 */
{ {
(yyval.array).data = empty_data; (yyval.array).data = empty_data;
(yyval.array).bits = 32; (yyval.array).bits = 32;
} }
#line 1782 "dtc-parser.tab.c" /* yacc.c:1646 */ #line 1800 "dtc-parser.tab.c" /* yacc.c:1646 */
break; break;
case 35: case 36:
#line 330 "dtc-parser.y" /* yacc.c:1646 */ #line 344 "dtc-parser.y" /* yacc.c:1646 */
{ {
if ((yyvsp[-1].array).bits < 64) { if ((yyvsp[-1].array).bits < 64) {
uint64_t mask = (1ULL << (yyvsp[-1].array).bits) - 1; uint64_t mask = (1ULL << (yyvsp[-1].array).bits) - 1;
...@@ -1801,11 +1819,11 @@ yyreduce: ...@@ -1801,11 +1819,11 @@ yyreduce:
(yyval.array).data = data_append_integer((yyvsp[-1].array).data, (yyvsp[0].integer), (yyvsp[-1].array).bits); (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; break;
case 36: case 37:
#line 349 "dtc-parser.y" /* yacc.c:1646 */ #line 363 "dtc-parser.y" /* yacc.c:1646 */
{ {
uint64_t val = ~0ULL >> (64 - (yyvsp[-1].array).bits); uint64_t val = ~0ULL >> (64 - (yyvsp[-1].array).bits);
...@@ -1819,129 +1837,129 @@ yyreduce: ...@@ -1819,129 +1837,129 @@ yyreduce:
(yyval.array).data = data_append_integer((yyvsp[-1].array).data, val, (yyvsp[-1].array).bits); (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; break;
case 37: case 38:
#line 363 "dtc-parser.y" /* yacc.c:1646 */ #line 377 "dtc-parser.y" /* yacc.c:1646 */
{ {
(yyval.array).data = data_add_marker((yyvsp[-1].array).data, LABEL, (yyvsp[0].labelref)); (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; break;
case 40: case 41:
#line 372 "dtc-parser.y" /* yacc.c:1646 */ #line 386 "dtc-parser.y" /* yacc.c:1646 */
{ {
(yyval.integer) = (yyvsp[-1].integer); (yyval.integer) = (yyvsp[-1].integer);
} }
#line 1839 "dtc-parser.tab.c" /* yacc.c:1646 */ #line 1857 "dtc-parser.tab.c" /* yacc.c:1646 */
break; break;
case 43: case 44:
#line 383 "dtc-parser.y" /* yacc.c:1646 */ #line 397 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = (yyvsp[-4].integer) ? (yyvsp[-2].integer) : (yyvsp[0].integer); } { (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; break;
case 45: case 46:
#line 388 "dtc-parser.y" /* yacc.c:1646 */ #line 402 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = (yyvsp[-2].integer) || (yyvsp[0].integer); } { (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; break;
case 47: case 48:
#line 393 "dtc-parser.y" /* yacc.c:1646 */ #line 407 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = (yyvsp[-2].integer) && (yyvsp[0].integer); } { (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; break;
case 49: case 50:
#line 398 "dtc-parser.y" /* yacc.c:1646 */ #line 412 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = (yyvsp[-2].integer) | (yyvsp[0].integer); } { (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; break;
case 51: case 52:
#line 403 "dtc-parser.y" /* yacc.c:1646 */ #line 417 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = (yyvsp[-2].integer) ^ (yyvsp[0].integer); } { (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; break;
case 53: case 54:
#line 408 "dtc-parser.y" /* yacc.c:1646 */ #line 422 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = (yyvsp[-2].integer) & (yyvsp[0].integer); } { (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; break;
case 55: case 56:
#line 413 "dtc-parser.y" /* yacc.c:1646 */ #line 427 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = (yyvsp[-2].integer) == (yyvsp[0].integer); } { (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; break;
case 56: case 57:
#line 414 "dtc-parser.y" /* yacc.c:1646 */ #line 428 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = (yyvsp[-2].integer) != (yyvsp[0].integer); } { (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; break;
case 58: case 59:
#line 419 "dtc-parser.y" /* yacc.c:1646 */ #line 433 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = (yyvsp[-2].integer) < (yyvsp[0].integer); } { (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; break;
case 59: case 60:
#line 420 "dtc-parser.y" /* yacc.c:1646 */ #line 434 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = (yyvsp[-2].integer) > (yyvsp[0].integer); } { (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; break;
case 60: case 61:
#line 421 "dtc-parser.y" /* yacc.c:1646 */ #line 435 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = (yyvsp[-2].integer) <= (yyvsp[0].integer); } { (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; break;
case 61: case 62:
#line 422 "dtc-parser.y" /* yacc.c:1646 */ #line 436 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = (yyvsp[-2].integer) >= (yyvsp[0].integer); } { (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; break;
case 62: case 63:
#line 426 "dtc-parser.y" /* yacc.c:1646 */ #line 440 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = (yyvsp[-2].integer) << (yyvsp[0].integer); } { (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; break;
case 63: case 64:
#line 427 "dtc-parser.y" /* yacc.c:1646 */ #line 441 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = (yyvsp[-2].integer) >> (yyvsp[0].integer); } { (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; break;
case 65: case 66:
#line 432 "dtc-parser.y" /* yacc.c:1646 */ #line 446 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = (yyvsp[-2].integer) + (yyvsp[0].integer); } { (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; break;
case 66: case 67:
#line 433 "dtc-parser.y" /* yacc.c:1646 */ #line 447 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = (yyvsp[-2].integer) - (yyvsp[0].integer); } { (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; break;
case 68: case 69:
#line 438 "dtc-parser.y" /* yacc.c:1646 */ #line 452 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = (yyvsp[-2].integer) * (yyvsp[0].integer); } { (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; break;
case 69: case 70:
#line 440 "dtc-parser.y" /* yacc.c:1646 */ #line 454 "dtc-parser.y" /* yacc.c:1646 */
{ {
if ((yyvsp[0].integer) != 0) { if ((yyvsp[0].integer) != 0) {
(yyval.integer) = (yyvsp[-2].integer) / (yyvsp[0].integer); (yyval.integer) = (yyvsp[-2].integer) / (yyvsp[0].integer);
...@@ -1950,11 +1968,11 @@ yyreduce: ...@@ -1950,11 +1968,11 @@ yyreduce:
(yyval.integer) = 0; (yyval.integer) = 0;
} }
} }
#line 1954 "dtc-parser.tab.c" /* yacc.c:1646 */ #line 1972 "dtc-parser.tab.c" /* yacc.c:1646 */
break; break;
case 70: case 71:
#line 449 "dtc-parser.y" /* yacc.c:1646 */ #line 463 "dtc-parser.y" /* yacc.c:1646 */
{ {
if ((yyvsp[0].integer) != 0) { if ((yyvsp[0].integer) != 0) {
(yyval.integer) = (yyvsp[-2].integer) % (yyvsp[0].integer); (yyval.integer) = (yyvsp[-2].integer) % (yyvsp[0].integer);
...@@ -1963,103 +1981,103 @@ yyreduce: ...@@ -1963,103 +1981,103 @@ yyreduce:
(yyval.integer) = 0; (yyval.integer) = 0;
} }
} }
#line 1967 "dtc-parser.tab.c" /* yacc.c:1646 */ #line 1985 "dtc-parser.tab.c" /* yacc.c:1646 */
break; break;
case 73: case 74:
#line 462 "dtc-parser.y" /* yacc.c:1646 */ #line 476 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = -(yyvsp[0].integer); } { (yyval.integer) = -(yyvsp[0].integer); }
#line 1973 "dtc-parser.tab.c" /* yacc.c:1646 */ #line 1991 "dtc-parser.tab.c" /* yacc.c:1646 */
break; break;
case 74: case 75:
#line 463 "dtc-parser.y" /* yacc.c:1646 */ #line 477 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = ~(yyvsp[0].integer); } { (yyval.integer) = ~(yyvsp[0].integer); }
#line 1979 "dtc-parser.tab.c" /* yacc.c:1646 */ #line 1997 "dtc-parser.tab.c" /* yacc.c:1646 */
break; break;
case 75: case 76:
#line 464 "dtc-parser.y" /* yacc.c:1646 */ #line 478 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = !(yyvsp[0].integer); } { (yyval.integer) = !(yyvsp[0].integer); }
#line 1985 "dtc-parser.tab.c" /* yacc.c:1646 */ #line 2003 "dtc-parser.tab.c" /* yacc.c:1646 */
break; break;
case 76: case 77:
#line 469 "dtc-parser.y" /* yacc.c:1646 */ #line 483 "dtc-parser.y" /* yacc.c:1646 */
{ {
(yyval.data) = empty_data; (yyval.data) = empty_data;
} }
#line 1993 "dtc-parser.tab.c" /* yacc.c:1646 */ #line 2011 "dtc-parser.tab.c" /* yacc.c:1646 */
break; break;
case 77: case 78:
#line 473 "dtc-parser.y" /* yacc.c:1646 */ #line 487 "dtc-parser.y" /* yacc.c:1646 */
{ {
(yyval.data) = data_append_byte((yyvsp[-1].data), (yyvsp[0].byte)); (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; break;
case 78: case 79:
#line 477 "dtc-parser.y" /* yacc.c:1646 */ #line 491 "dtc-parser.y" /* yacc.c:1646 */
{ {
(yyval.data) = data_add_marker((yyvsp[-1].data), LABEL, (yyvsp[0].labelref)); (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; break;
case 79: case 80:
#line 484 "dtc-parser.y" /* yacc.c:1646 */ #line 498 "dtc-parser.y" /* yacc.c:1646 */
{ {
(yyval.nodelist) = NULL; (yyval.nodelist) = NULL;
} }
#line 2017 "dtc-parser.tab.c" /* yacc.c:1646 */ #line 2035 "dtc-parser.tab.c" /* yacc.c:1646 */
break; break;
case 80: case 81:
#line 488 "dtc-parser.y" /* yacc.c:1646 */ #line 502 "dtc-parser.y" /* yacc.c:1646 */
{ {
(yyval.nodelist) = chain_node((yyvsp[-1].node), (yyvsp[0].nodelist)); (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; break;
case 81: case 82:
#line 492 "dtc-parser.y" /* yacc.c:1646 */ #line 506 "dtc-parser.y" /* yacc.c:1646 */
{ {
ERROR(&(yylsp[0]), "Properties must precede subnodes"); ERROR(&(yylsp[0]), "Properties must precede subnodes");
YYERROR; YYERROR;
} }
#line 2034 "dtc-parser.tab.c" /* yacc.c:1646 */ #line 2052 "dtc-parser.tab.c" /* yacc.c:1646 */
break; break;
case 82: case 83:
#line 500 "dtc-parser.y" /* yacc.c:1646 */ #line 514 "dtc-parser.y" /* yacc.c:1646 */
{ {
(yyval.node) = name_node((yyvsp[0].node), (yyvsp[-1].propnodename)); (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; break;
case 83: case 84:
#line 504 "dtc-parser.y" /* yacc.c:1646 */ #line 518 "dtc-parser.y" /* yacc.c:1646 */
{ {
(yyval.node) = name_node(build_node_delete(), (yyvsp[-1].propnodename)); (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; break;
case 84: case 85:
#line 508 "dtc-parser.y" /* yacc.c:1646 */ #line 522 "dtc-parser.y" /* yacc.c:1646 */
{ {
add_label(&(yyvsp[0].node)->labels, (yyvsp[-1].labelref)); add_label(&(yyvsp[0].node)->labels, (yyvsp[-1].labelref));
(yyval.node) = (yyvsp[0].node); (yyval.node) = (yyvsp[0].node);
} }
#line 2059 "dtc-parser.tab.c" /* yacc.c:1646 */ #line 2077 "dtc-parser.tab.c" /* yacc.c:1646 */
break; break;
#line 2063 "dtc-parser.tab.c" /* yacc.c:1646 */ #line 2081 "dtc-parser.tab.c" /* yacc.c:1646 */
default: break; default: break;
} }
/* User semantic actions sometimes alter yychar, and that requires /* User semantic actions sometimes alter yychar, and that requires
...@@ -2294,7 +2312,7 @@ yyreturn: ...@@ -2294,7 +2312,7 @@ yyreturn:
#endif #endif
return yyresult; return yyresult;
} }
#line 514 "dtc-parser.y" /* yacc.c:1906 */ #line 528 "dtc-parser.y" /* yacc.c:1906 */
void yyerror(char const *s) void yyerror(char const *s)
......
...@@ -182,10 +182,19 @@ devicetree: ...@@ -182,10 +182,19 @@ devicetree:
{ {
struct node *target = get_node_by_ref($1, $2); struct node *target = get_node_by_ref($1, $2);
if (target) if (target) {
merge_nodes(target, $3); merge_nodes(target, $3);
} 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 else
ERROR(&@2, "Label or path %s not found", $2); ERROR(&@2, "Label or path %s not found", $2);
}
$$ = $1; $$ = $1;
} }
| devicetree DT_DEL_NODE DT_REF ';' | devicetree DT_DEL_NODE DT_REF ';'
...@@ -200,6 +209,11 @@ devicetree: ...@@ -200,6 +209,11 @@ devicetree:
$$ = $1; $$ = $1;
} }
| /* empty */
{
/* build empty node */
$$ = name_node(build_node(NULL, NULL), "");
}
; ;
nodedef: nodedef:
......
...@@ -31,7 +31,7 @@ int reservenum; /* Number of memory reservation slots */ ...@@ -31,7 +31,7 @@ int reservenum; /* Number of memory reservation slots */
int minsize; /* Minimum blob size */ int minsize; /* Minimum blob size */
int padsize; /* Additional padding to blob */ int padsize; /* Additional padding to blob */
int alignsize; /* Additional padding to blob accroding to the alignsize */ 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_symbols; /* enable symbols & fixup support */
int generate_fixups; /* suppress generation of fixups on symbol support */ int generate_fixups; /* suppress generation of fixups on symbol support */
int auto_label_aliases; /* auto generate labels -> aliases */ int auto_label_aliases; /* auto generate labels -> aliases */
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
#include <unistd.h> #include <unistd.h>
#include <inttypes.h>
#include <libfdt_env.h> #include <libfdt_env.h>
#include <fdt.h> #include <fdt.h>
...@@ -202,6 +203,7 @@ struct node *build_node_delete(void); ...@@ -202,6 +203,7 @@ struct node *build_node_delete(void);
struct node *name_node(struct node *node, char *name); struct node *name_node(struct node *node, char *name);
struct node *chain_node(struct node *first, struct node *list); struct node *chain_node(struct node *first, struct node *list);
struct node *merge_nodes(struct node *old_node, struct node *new_node); 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 add_property(struct node *node, struct property *prop);
void delete_property_by_name(struct node *node, char *name); void delete_property_by_name(struct node *node, char *name);
...@@ -215,6 +217,7 @@ void append_to_property(struct node *node, ...@@ -215,6 +217,7 @@ void append_to_property(struct node *node,
const char *get_unitname(struct node *node); const char *get_unitname(struct node *node);
struct property *get_property(struct node *node, const char *propname); struct property *get_property(struct node *node, const char *propname);
cell_t propval_cell(struct property *prop); 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 property *get_property_by_label(struct node *tree, const char *label,
struct node **node); struct node **node);
struct marker *get_marker_label(struct node *tree, const char *label, struct marker *get_marker_label(struct node *tree, const char *label,
......
/*
* 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;
}
...@@ -81,4 +81,3 @@ int fdt_create_empty_tree(void *buf, int bufsize) ...@@ -81,4 +81,3 @@ int fdt_create_empty_tree(void *buf, int bufsize)
return fdt_open_into(buf, buf, bufsize); return fdt_open_into(buf, buf, bufsize);
} }
#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;
}
...@@ -60,7 +60,7 @@ static int _fdt_nodename_eq(const void *fdt, int offset, ...@@ -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); const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1);
if (! p) if (!p)
/* short match */ /* short match */
return 0; return 0;
...@@ -327,7 +327,7 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, ...@@ -327,7 +327,7 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
const struct fdt_property *prop; const struct fdt_property *prop;
prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp); prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp);
if (! prop) if (!prop)
return NULL; return NULL;
return prop->data; return prop->data;
......
...@@ -207,7 +207,7 @@ static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name, ...@@ -207,7 +207,7 @@ static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name,
int err; int err;
*prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); *prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
if (! (*prop)) if (!*prop)
return oldlen; return oldlen;
if ((err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(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) ...@@ -269,8 +269,8 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name)
return 0; return 0;
} }
int fdt_setprop(void *fdt, int nodeoffset, const char *name, int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name,
const void *val, int len) int len, void **prop_data)
{ {
struct fdt_property *prop; struct fdt_property *prop;
int err; int err;
...@@ -283,8 +283,22 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name, ...@@ -283,8 +283,22 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name,
if (err) if (err)
return 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) if (len)
memcpy(prop->data, val, len); memcpy(prop_data, val, len);
return 0; return 0;
} }
...@@ -323,7 +337,7 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name) ...@@ -323,7 +337,7 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name)
FDT_RW_CHECK_HEADER(fdt); FDT_RW_CHECK_HEADER(fdt);
prop = fdt_get_property_w(fdt, nodeoffset, name, &len); prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
if (! prop) if (!prop)
return len; return len;
proplen = sizeof(*prop) + FDT_TAGALIGN(len); proplen = sizeof(*prop) + FDT_TAGALIGN(len);
......
...@@ -220,7 +220,7 @@ static int _fdt_find_add_string(void *fdt, const char *s) ...@@ -220,7 +220,7 @@ static int _fdt_find_add_string(void *fdt, const char *s)
return offset; 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; struct fdt_property *prop;
int nameoff; int nameoff;
...@@ -238,7 +238,19 @@ int fdt_property(void *fdt, const char *name, const void *val, int len) ...@@ -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->tag = cpu_to_fdt32(FDT_PROP);
prop->nameoff = cpu_to_fdt32(nameoff); prop->nameoff = cpu_to_fdt32(nameoff);
prop->len = cpu_to_fdt32(len); 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; return 0;
} }
......
...@@ -82,7 +82,7 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, ...@@ -82,7 +82,7 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
int proplen; int proplen;
propval = fdt_getprop(fdt, nodeoffset, name, &proplen); propval = fdt_getprop(fdt, nodeoffset, name, &proplen);
if (! propval) if (!propval)
return proplen; return proplen;
if (proplen != len) if (proplen != len)
...@@ -107,7 +107,7 @@ int fdt_nop_property(void *fdt, int nodeoffset, const char *name) ...@@ -107,7 +107,7 @@ int fdt_nop_property(void *fdt, int nodeoffset, const char *name)
int len; int len;
prop = fdt_get_property_w(fdt, nodeoffset, name, &len); prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
if (! prop) if (!prop)
return len; return len;
_fdt_nop_region(prop, len + sizeof(*prop)); _fdt_nop_region(prop, len + sizeof(*prop));
......
...@@ -1314,6 +1314,22 @@ static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val) ...@@ -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); 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) \ #define fdt_property_string(fdt, name, str) \
fdt_property(fdt, name, str, strlen(str)+1) fdt_property(fdt, name, str, strlen(str)+1)
int fdt_end_node(void *fdt); int fdt_end_node(void *fdt);
...@@ -1432,6 +1448,37 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name); ...@@ -1432,6 +1448,37 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name);
int fdt_setprop(void *fdt, int nodeoffset, const char *name, int fdt_setprop(void *fdt, int nodeoffset, const char *name,
const void *val, int len); 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_setprop_u32 - set a property to a 32-bit integer
* @fdt: pointer to the device tree blob * @fdt: pointer to the device tree blob
......
...@@ -216,6 +216,28 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node) ...@@ -216,6 +216,28 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
return old_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) struct node *chain_node(struct node *first, struct node *list)
{ {
assert(first->next_sibling == NULL); assert(first->next_sibling == NULL);
...@@ -396,6 +418,12 @@ cell_t propval_cell(struct property *prop) ...@@ -396,6 +418,12 @@ cell_t propval_cell(struct property *prop)
return fdt32_to_cpu(*((fdt32_t *)prop->val.val)); 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 property *get_property_by_label(struct node *tree, const char *label,
struct node **node) struct node **node)
{ {
...@@ -478,7 +506,8 @@ struct node *get_node_by_path(struct node *tree, const char *path) ...@@ -478,7 +506,8 @@ struct node *get_node_by_path(struct node *tree, const char *path)
p = strchr(path, '/'); p = strchr(path, '/');
for_each_child(tree, child) { 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); return get_node_by_path(child, p+1);
else if (!p && streq(path, child->name)) else if (!p && streq(path, child->name))
return child; return child;
......
...@@ -35,7 +35,9 @@ DTC_SOURCE="checks.c data.c dtc.c dtc.h flattree.c fstree.c livetree.c srcpos.c ...@@ -35,7 +35,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 \ srcpos.h treesource.c util.c util.h version_gen.h Makefile.dtc \
dtc-lexer.l dtc-parser.y" dtc-lexer.l dtc-parser.y"
DTC_GENERATED="dtc-lexer.lex.c dtc-parser.tab.c dtc-parser.tab.h" 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() { get_last_dtc_version() {
git log --oneline scripts/dtc/ | grep 'upstream' | head -1 | sed -e 's/^.* \(.*\)/\1/' git log --oneline scripts/dtc/ | grep 'upstream' | head -1 | sed -e 's/^.* \(.*\)/\1/'
......
#define DTC_VERSION "DTC 1.4.4-g756ffc4f" #define DTC_VERSION "DTC 1.4.5-gc1e55a55"
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册