Devicetree for 4.7:
- Rewrite of the unflattening code to avoid recursion and lessen the stack usage. - Rewrite of the phandle args parsing code to get rid of the fixed args size. This is needed for IOMMU code. - Sync to latest dtc which adds more dts style checking. These warnings are enabled with "W=1" compiles. - Tegra documentation updates related to the above warnings. - A bunch of spelling and other doc fixes. - Various vendor prefix additions. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJXP3OZAAoJEPr7XbWNvGHDEUAQAJLbR9Js7RENPGX/u0NSJNaJ yQhyNVsz/BkAWFfWT6YEfyNnDY0UcRs2N9RHb+z65TsX1jvJJxLRDLRfz+rExfiZ cA1RJaF77kPOdA0eZapJIzPvAf97Zik+nzKLsqUPUSYaIzghV5rN6aR2AjXN5AYv TMQP41NwNQkxfO5I+NOssEB8IBH+DlAzg0LYXw8wNsAJc8o+DgEQjU8cxCqR0NgE SbpbJNF8tRXEJckZRC+Q7Gyn2J7VglmM/5VTFbBBwgIly2lcLADPVuX/Z6hZE3OH K7mhNWBu61vI5lU6u7q64ePeb63j+Ut/RR0tTPgjsLg0Qg0ue+6iZ66S9ZHEicbU wT4A/hjSImvZoQGGMrtUF5HGcaoMHGLGFgFc/Ouox8OQflntQBzuEx/gOQpPXcIT vdwITNW8/OGV3rgtmRO9mbdSZiAHPsydoTkIl+Ucod3nTrlEEOwgQARYO+2CfSRj sknndj26Kf+0n0tSv2d4JAEdEozp2ZPyfiAfpPXW74jOmOxeswUb3Kxx8YMwhCEl +s96rm1vtpNmJzXtuPV3eB0TydWMQ/3NXN6XOS7qEN/5y1AbQqKEoIyJOziBQMxe c9Eh/YSjsm4uw3Q0wHOI3s4hTwWfuBmwpIsANJVKrRbftPF58bMUBYU/44ReTtA8 iMsrqJpnSCcAyS8doWRY =s+gW -----END PGP SIGNATURE----- Merge tag 'devicetree-for-4.7' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux Pull devicetree updates from Rob Herring: - Rewrite of the unflattening code to avoid recursion and lessen the stack usage. - Rewrite of the phandle args parsing code to get rid of the fixed args size. This is needed for IOMMU code. - Sync to latest dtc which adds more dts style checking. These warnings are enabled with "W=1" compiles. - Tegra documentation updates related to the above warnings. - A bunch of spelling and other doc fixes. - Various vendor prefix additions. * tag 'devicetree-for-4.7' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux: (52 commits) devicetree: Add Creative Technology vendor id gpio: dt-bindings: add ibm,ppc4xx-gpio binding of/unittest: Remove unnecessary module.h header inclusion drivers/of: Fix build warning in populate_node() drivers/of: Fix depth when unflattening devicetree of: dynamic: changeset prop-update revert fix drivers/of: Export of_detach_node() drivers/of: Return allocated memory from of_fdt_unflatten_tree() drivers/of: Specify parent node in of_fdt_unflatten_tree() drivers/of: Rename unflatten_dt_node() drivers/of: Avoid recursively calling unflatten_dt_node() drivers/of: Split unflatten_dt_node() of: include errno.h in of_graph.h of: document refcount incrementation of of_get_cpu_node() Documentation: dt: soc: fix spelling mistakes Documentation: dt: power: fix spelling mistake Documentation: dt: pinctrl: fix spelling mistake Documentation: dt: opp: fix spelling mistake Documentation: dt: net: fix spelling mistakes Documentation: dt: mtd: fix spelling mistake ...
This commit is contained in:
commit
e7f44b65b5
|
@ -100,7 +100,7 @@ specific to ARM.
|
|||
"arm,cci-400-pmu,r0"
|
||||
"arm,cci-400-pmu,r1"
|
||||
"arm,cci-400-pmu" - DEPRECATED, permitted only where OS has
|
||||
secure acces to CCI registers
|
||||
secure access to CCI registers
|
||||
"arm,cci-500-pmu,r0"
|
||||
"arm,cci-550-pmu,r0"
|
||||
- reg:
|
||||
|
|
|
@ -42,7 +42,8 @@ Examples:
|
|||
Consumer:
|
||||
========
|
||||
See Documentation/devicetree/bindings/interrupt-controller/interrupts.txt and
|
||||
Documentation/devicetree/bindings/arm/gic.txt for further details.
|
||||
Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt for
|
||||
further details.
|
||||
|
||||
An interrupt consumer on an SoC using crossbar will use:
|
||||
interrupts = <GIC_SPI request_number interrupt_level>
|
||||
|
|
|
@ -6,4 +6,4 @@ few properties of different peripheral controllers.
|
|||
misc node required properties:
|
||||
|
||||
- compatible Should be "st,spear1340-misc", "syscon".
|
||||
- reg: Address range of misc space upto 8K
|
||||
- reg: Address range of misc space up to 8K
|
||||
|
|
|
@ -23,7 +23,7 @@ scu:
|
|||
see binding for arm/scu.txt
|
||||
|
||||
interrupt-controller:
|
||||
see binding for arm/gic.txt
|
||||
see binding for interrupt-controller/arm,gic.txt
|
||||
|
||||
timer:
|
||||
see binding for arm/twd.txt
|
||||
|
|
|
@ -50,7 +50,7 @@ Required properties for I2C mode:
|
|||
|
||||
Example:
|
||||
|
||||
clock@0,70110000 {
|
||||
clock@70110000 {
|
||||
compatible = "nvidia,tegra124-dfll";
|
||||
reg = <0 0x70110000 0 0x100>, /* DFLL control */
|
||||
<0 0x70110000 0 0x100>, /* I2C output control */
|
||||
|
|
|
@ -16,7 +16,7 @@ Required Properties:
|
|||
Optional Properties:
|
||||
|
||||
- rockchip,grf: phandle to the syscon managing the "general register files"
|
||||
If missing pll rates are not changable, due to the missing pll lock status.
|
||||
If missing pll rates are not changeable, due to the missing pll lock status.
|
||||
|
||||
Each clock is assigned an identifier and client nodes can use this identifier
|
||||
to specify the clock which they consume. All available clocks are defined as
|
||||
|
|
|
@ -15,7 +15,7 @@ Required Properties:
|
|||
Optional Properties:
|
||||
|
||||
- rockchip,grf: phandle to the syscon managing the "general register files"
|
||||
If missing pll rates are not changable, due to the missing pll lock status.
|
||||
If missing pll rates are not changeable, due to the missing pll lock status.
|
||||
|
||||
Each clock is assigned an identifier and client nodes can use this identifier
|
||||
to specify the clock which they consume. All available clocks are defined as
|
||||
|
|
|
@ -40,7 +40,7 @@ address is common of all subnode.
|
|||
};
|
||||
|
||||
This binding uses the common clock binding[1].
|
||||
Each subnode should use the binding discribe in [2]..[7]
|
||||
Each subnode should use the binding described in [2]..[7]
|
||||
|
||||
[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
|
||||
[2] Documentation/devicetree/bindings/clock/st,clkgen-divmux.txt
|
||||
|
|
|
@ -41,7 +41,7 @@ Video interfaces:
|
|||
endpoint node connected from mic node (reg = 0):
|
||||
- remote-endpoint: specifies the endpoint in mic node. This node is required
|
||||
for Exynos5433 mipi dsi. So mic can access to panel node
|
||||
thoughout this dsi node.
|
||||
throughout this dsi node.
|
||||
endpoint node connected to panel node (reg = 1):
|
||||
- remote-endpoint: specifies the endpoint in panel node. This node is
|
||||
required in all kinds of exynos mipi dsi to represent
|
||||
|
|
|
@ -7,7 +7,7 @@ Required properties:
|
|||
- compatible: Should be "xlnx,axi-dma-1.00.a"
|
||||
- #dma-cells: Should be <1>, see "dmas" property below
|
||||
- reg: Should contain DMA registers location and length.
|
||||
- dma-channel child node: Should have atleast one channel and can have upto
|
||||
- dma-channel child node: Should have at least one channel and can have up to
|
||||
two channels per device. This node specifies the properties of each
|
||||
DMA channel (see child node properties below).
|
||||
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
* IBM/AMCC/APM GPIO Controller for PowerPC 4XX series and compatible SoCs
|
||||
|
||||
All GPIOs are pin-shared with other functions. DCRs control whether a
|
||||
particular pin that has GPIO capabilities acts as a GPIO or is used for
|
||||
another purpose. GPIO outputs are separately programmable to emulate
|
||||
an open-drain driver.
|
||||
|
||||
Required properties:
|
||||
- compatible: must be "ibm,ppc4xx-gpio"
|
||||
- reg: address and length of the register set for the device
|
||||
- #gpio-cells: must be set to 2. The first cell is the pin number
|
||||
and the second cell is used to specify the gpio polarity:
|
||||
0 = active high
|
||||
1 = active low
|
||||
- gpio-controller: marks the device node as a gpio controller.
|
||||
|
||||
Example:
|
||||
|
||||
GPIO0: gpio@ef600b00 {
|
||||
compatible = "ibm,ppc4xx-gpio";
|
||||
reg = <0xef600b00 0x00000048>;
|
||||
#gpio-cells = <2>;
|
||||
gpio-controller;
|
||||
};
|
|
@ -29,7 +29,7 @@ Optional properties:
|
|||
ti,vref-delay-usecs vref supply delay in usecs, 0 for
|
||||
external vref (u16).
|
||||
ti,vref-mv The VREF voltage, in millivolts (u16).
|
||||
Set to 0 to use internal refernce
|
||||
Set to 0 to use internal references
|
||||
(ADS7846).
|
||||
ti,keep-vref-on set to keep vref on for differential
|
||||
measurements as well
|
||||
|
|
|
@ -15,7 +15,7 @@ Optional properties:
|
|||
- fsl,pen-debounce-ns: Pen debounce time in nanoseconds.
|
||||
- fsl,pen-threshold: Pen-down threshold for the touchscreen. This is a value
|
||||
between 1 and 4096. It is the ratio between the internal reference voltage
|
||||
and the measured voltage after the plate was precharged. Resistence between
|
||||
and the measured voltage after the plate was precharged. Resistance between
|
||||
plates and therefore the voltage decreases with pressure so that a smaller
|
||||
value is equivalent to a higher pressure.
|
||||
- fsl,settling-time-ns: Settling time in nanoseconds. The settling time is before
|
||||
|
|
|
@ -16,8 +16,7 @@ Required properties:
|
|||
"mediatek,mt6577-sysirq"
|
||||
"mediatek,mt2701-sysirq"
|
||||
- interrupt-controller : Identifies the node as an interrupt controller
|
||||
- #interrupt-cells : Use the same format as specified by GIC in
|
||||
Documentation/devicetree/bindings/arm/gic.txt
|
||||
- #interrupt-cells : Use the same format as specified by GIC in arm,gic.txt.
|
||||
- interrupt-parent: phandle of irq parent for sysirq. The parent must
|
||||
use the same interrupt-cells format as GIC.
|
||||
- reg: Physical base address of the intpol registers and length of memory
|
||||
|
|
|
@ -4,7 +4,7 @@ All TI OMAP4/5 (and their derivatives) an interrupt controller that
|
|||
routes interrupts to the GIC, and also serves as a wakeup source. It
|
||||
is also referred to as "WUGEN-MPU", hence the name of the binding.
|
||||
|
||||
Reguired properties:
|
||||
Required properties:
|
||||
|
||||
- compatible : should contain at least "ti,omap4-wugen-mpu" or
|
||||
"ti,omap5-wugen-mpu"
|
||||
|
@ -20,7 +20,7 @@ Notes:
|
|||
- Because this HW ultimately routes interrupts to the GIC, the
|
||||
interrupt specifier must be that of the GIC.
|
||||
- Only SPIs can use the WUGEN as an interrupt parent. SGIs and PPIs
|
||||
are explicitly forbiden.
|
||||
are explicitly forbidden.
|
||||
|
||||
Example:
|
||||
|
||||
|
|
|
@ -190,7 +190,7 @@ be specified, according to the board documentation:
|
|||
Example SoC include file:
|
||||
|
||||
/ {
|
||||
emc@0,7001b000 {
|
||||
emc@7001b000 {
|
||||
compatible = "nvidia,tegra124-emc";
|
||||
reg = <0x0 0x7001b000 0x0 0x1000>;
|
||||
|
||||
|
@ -201,7 +201,7 @@ Example SoC include file:
|
|||
Example board file:
|
||||
|
||||
/ {
|
||||
emc@0,7001b000 {
|
||||
emc@7001b000 {
|
||||
emc-timings-3 {
|
||||
nvidia,ram-code = <3>;
|
||||
|
|
@ -61,7 +61,7 @@ specified, according to the board documentation:
|
|||
Example SoC include file:
|
||||
|
||||
/ {
|
||||
mc: memory-controller@0,70019000 {
|
||||
mc: memory-controller@70019000 {
|
||||
compatible = "nvidia,tegra124-mc";
|
||||
reg = <0x0 0x70019000 0x0 0x1000>;
|
||||
clocks = <&tegra_car TEGRA124_CLK_MC>;
|
||||
|
@ -72,7 +72,7 @@ Example SoC include file:
|
|||
#iommu-cells = <1>;
|
||||
};
|
||||
|
||||
sdhci@0,700b0000 {
|
||||
sdhci@700b0000 {
|
||||
compatible = "nvidia,tegra124-sdhci";
|
||||
...
|
||||
iommus = <&mc TEGRA_SWGROUP_SDMMC1A>;
|
||||
|
@ -82,7 +82,7 @@ Example SoC include file:
|
|||
Example board file:
|
||||
|
||||
/ {
|
||||
memory-controller@0,70019000 {
|
||||
memory-controller@70019000 {
|
||||
emc-timings-3 {
|
||||
nvidia,ram-code = <3>;
|
||||
|
|
@ -178,7 +178,7 @@ see regulator.txt - with additional custom properties described below:
|
|||
- qcom,force-mode:
|
||||
Usage: optional (default if no other qcom,force-mode is specified)
|
||||
Value type: <u32>
|
||||
Defintion: indicates that the regulator should be forced to a
|
||||
Definition: indicates that the regulator should be forced to a
|
||||
particular mode, valid values are:
|
||||
QCOM_RPM_FORCE_MODE_NONE - do not force any mode
|
||||
QCOM_RPM_FORCE_MODE_LPM - force into low power mode
|
||||
|
@ -204,7 +204,7 @@ see regulator.txt - with additional custom properties described below:
|
|||
- qcom,force-mode:
|
||||
Usage: optional
|
||||
Value type: <u32>
|
||||
Defintion: indicates that the regulator should not be forced to any
|
||||
Definition: indicates that the regulator should not be forced to any
|
||||
particular mode, valid values are:
|
||||
QCOM_RPM_FORCE_MODE_NONE - do not force any mode
|
||||
QCOM_RPM_FORCE_MODE_LPM - force into low power mode
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
* The simple eMMC hardware reset provider
|
||||
|
||||
The purpose of this driver is to perform standard eMMC hw reset
|
||||
procedure, as descibed by Jedec 4.4 specification. This procedure is
|
||||
procedure, as described by Jedec 4.4 specification. This procedure is
|
||||
performed just after MMC core enabled power to the given mmc host (to
|
||||
fix possible issues if bootloader has left eMMC card in initialized or
|
||||
unknown state), and before performing complete system reboot (also in
|
||||
|
|
|
@ -52,7 +52,7 @@ Optional properties:
|
|||
v7.0. Use this property to describe the rare
|
||||
earlier versions of this core that include WP
|
||||
|
||||
-- Additonal SoC-specific NAND controller properties --
|
||||
-- Additional SoC-specific NAND controller properties --
|
||||
|
||||
The NAND controller is integrated differently on the variety of SoCs on which it
|
||||
is found. Part of this integration involves providing status and enable bits
|
||||
|
|
|
@ -8,7 +8,7 @@ Required properties:
|
|||
specifies a reference to the associating hardware driver node.
|
||||
see Documentation/devicetree/bindings/net/hisilicon-hns-dsaf.txt
|
||||
- port-id: is the index of port provided by DSAF (the accelerator). DSAF can
|
||||
connect to 8 PHYs. Port 0 to 1 are both used for adminstration purpose. They
|
||||
connect to 8 PHYs. Port 0 to 1 are both used for administration purpose. They
|
||||
are called debug ports.
|
||||
|
||||
The remaining 6 PHYs are taken according to the mode of DSAF.
|
||||
|
|
|
@ -51,8 +51,8 @@ Optional properties:
|
|||
AXI register inside the DMA module:
|
||||
- snps,lpi_en: enable Low Power Interface
|
||||
- snps,xit_frm: unlock on WoL
|
||||
- snps,wr_osr_lmt: max write oustanding req. limit
|
||||
- snps,rd_osr_lmt: max read oustanding req. limit
|
||||
- snps,wr_osr_lmt: max write outstanding req. limit
|
||||
- snps,rd_osr_lmt: max read outstanding req. limit
|
||||
- snps,kbbe: do not cross 1KiB boundary.
|
||||
- snps,axi_all: align address
|
||||
- snps,blen: this is a vector of supported burst length.
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Required properties:
|
||||
- reg - The ID number for the phy, usually a small integer
|
||||
- ti,rx-internal-delay - RGMII Recieve Clock Delay - see dt-bindings/net/ti-dp83867.h
|
||||
- ti,rx-internal-delay - RGMII Receive Clock Delay - see dt-bindings/net/ti-dp83867.h
|
||||
for applicable values
|
||||
- ti,tx-internal-delay - RGMII Transmit Clock Delay - see dt-bindings/net/ti-dp83867.h
|
||||
for applicable values
|
||||
|
|
|
@ -45,7 +45,7 @@ Devices supporting OPPs must set their "operating-points-v2" property with
|
|||
phandle to a OPP table in their DT node. The OPP core will use this phandle to
|
||||
find the operating points for the device.
|
||||
|
||||
If required, this can be extended for SoC vendor specfic bindings. Such bindings
|
||||
If required, this can be extended for SoC vendor specific bindings. Such bindings
|
||||
should be documented as Documentation/devicetree/bindings/power/<vendor>-opp.txt
|
||||
and should have a compatible description like: "operating-points-v2-<vendor>".
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ Optional properties:
|
|||
|
||||
Example configuration:
|
||||
|
||||
pcie: pcie@0xdffff000 {
|
||||
pcie: pcie@dffff000 {
|
||||
compatible = "snps,dw-pcie";
|
||||
reg = <0xdffff000 0x1000>, /* Controller registers */
|
||||
<0xd0000000 0x2000>; /* PCI config space */
|
||||
|
|
|
@ -34,11 +34,11 @@ Hip05 Example (note that Hip06 is the same except compatible):
|
|||
ranges = <0x82000000 0 0x00000000 0x220 0x00000000 0 0x10000000>;
|
||||
num-lanes = <8>;
|
||||
port-id = <1>;
|
||||
#interrupts-cells = <1>;
|
||||
interrupts-map-mask = <0xf800 0 0 7>;
|
||||
interrupts-map = <0x0 0 0 1 &mbigen_pcie 1 10
|
||||
0x0 0 0 2 &mbigen_pcie 2 11
|
||||
0x0 0 0 3 &mbigen_pcie 3 12
|
||||
0x0 0 0 4 &mbigen_pcie 4 13>;
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-map-mask = <0xf800 0 0 7>;
|
||||
interrupt-map = <0x0 0 0 1 &mbigen_pcie 1 10
|
||||
0x0 0 0 2 &mbigen_pcie 2 11
|
||||
0x0 0 0 3 &mbigen_pcie 3 12
|
||||
0x0 0 0 4 &mbigen_pcie 4 13>;
|
||||
status = "ok";
|
||||
};
|
||||
|
|
|
@ -17,7 +17,7 @@ Example:
|
|||
|
||||
usb2_phy: usb2phy@0 {
|
||||
compatible = "st,stih416-usb-phy";
|
||||
#phy-cell = <0>;
|
||||
#phy-cells = <0>;
|
||||
st,syscfg = <&syscfg_rear>;
|
||||
clocks = <&clk_sysin>;
|
||||
clock-names = "osc_phy";
|
||||
|
|
|
@ -85,7 +85,7 @@ Example:
|
|||
SoC file extract:
|
||||
-----------------
|
||||
|
||||
padctl@0,7009f000 {
|
||||
padctl@7009f000 {
|
||||
compatible = "nvidia,tegra124-xusb-padctl";
|
||||
reg = <0x0 0x7009f000 0x0 0x1000>;
|
||||
resets = <&tegra_car 142>;
|
||||
|
@ -97,7 +97,7 @@ SoC file extract:
|
|||
Board file extract:
|
||||
-------------------
|
||||
|
||||
pcie-controller@0,01003000 {
|
||||
pcie-controller@01003000 {
|
||||
...
|
||||
|
||||
phys = <&padctl 0>;
|
||||
|
@ -108,7 +108,7 @@ Board file extract:
|
|||
|
||||
...
|
||||
|
||||
padctl: padctl@0,7009f000 {
|
||||
padctl: padctl@7009f000 {
|
||||
pinctrl-0 = <&padctl_default>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
|
|
|
@ -122,7 +122,7 @@ to specify in a pin configuration subnode:
|
|||
2: 1.5uA (PMIC_GPIO_PULL_UP_1P5)
|
||||
3: 31.5uA (PMIC_GPIO_PULL_UP_31P5)
|
||||
4: 1.5uA + 30uA boost (PMIC_GPIO_PULL_UP_1P5_30)
|
||||
If this property is ommited 30uA strength will be used if
|
||||
If this property is omitted 30uA strength will be used if
|
||||
pull up is selected
|
||||
|
||||
- bias-high-impedance:
|
||||
|
|
|
@ -29,7 +29,7 @@ IC (PMIC)
|
|||
- qcom,charger-disable:
|
||||
Usage: optional
|
||||
Value type: <boolean>
|
||||
Definition: definining this property disables charging
|
||||
Definition: defining this property disables charging
|
||||
|
||||
This charger is a sub-node of one of the 8941 PMIC blocks, and is specified
|
||||
as a child node in DTS of that node. See ../mfd/qcom,spmi-pmic.txt and
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
* palmas regulator IP block devicetree bindings
|
||||
|
||||
The tps659038 for the AM57x class have OTP spins that
|
||||
have different part numbers but the same functionality. There
|
||||
is not a need to add the OTP spins to the palmas driver. The
|
||||
spin devices should use the tps659038 as it's compatible value.
|
||||
This is the list of those devices:
|
||||
tps659037
|
||||
|
||||
Required properties:
|
||||
- compatible : Should be from the list
|
||||
ti,twl6035-pmic
|
||||
|
@ -8,6 +15,7 @@ Required properties:
|
|||
ti,tps65913-pmic
|
||||
ti,tps65914-pmic
|
||||
ti,tps65917-pmic
|
||||
ti,tps659038-pmic
|
||||
and also the generic series names
|
||||
ti,palmas-pmic
|
||||
- interrupt-parent : The parent interrupt controller which is palmas.
|
||||
|
|
|
@ -15,9 +15,9 @@ Optional properties:
|
|||
battery is chargeable or not. If charging battery then driver can
|
||||
enable the charging.
|
||||
- ti,backup-battery-charge-high-current: Enable high current charging in
|
||||
backup battery. Device supports the < 100mA and > 100mA charging.
|
||||
The high current will be > 100mA. Absence of this property will
|
||||
charge battery to lower current i.e. < 100mA.
|
||||
backup battery. Device supports the < 100uA and > 100uA charging.
|
||||
The high current will be > 100uA. Absence of this property will
|
||||
charge battery to lower current i.e. < 100uA.
|
||||
|
||||
Example:
|
||||
palmas: tps65913@58 {
|
||||
|
|
|
@ -42,7 +42,7 @@ Required properties:
|
|||
- queue-pools : child node classifying the queue ranges into pools.
|
||||
Queue ranges are grouped into 3 type of pools:
|
||||
- qpend : pool of qpend(interruptible) queues
|
||||
- general-purpose : pool of general queues, primarly used
|
||||
- general-purpose : pool of general queues, primarily used
|
||||
as free descriptor queues or the
|
||||
transmit DMA queues.
|
||||
- accumulator : pool of queues on PDSP accumulator channel
|
||||
|
@ -50,7 +50,7 @@ Required properties:
|
|||
-- qrange : number of queues to use per queue range, specified as
|
||||
<"base queue #" "# of queues">.
|
||||
-- interrupts : Optional property to specify the interrupt mapping
|
||||
for interruptible queues. The driver additionaly sets
|
||||
for interruptible queues. The driver additionally sets
|
||||
the interrupt affinity hint based on the cpu mask.
|
||||
-- qalloc-by-id : Optional property to specify that the queues in this
|
||||
range can only be allocated by queue id.
|
||||
|
@ -80,7 +80,7 @@ Required properties:
|
|||
latency : time to delay the interrupt, specified
|
||||
in microseconds.
|
||||
-- multi-queue : Optional property to specify that the channel has to
|
||||
monitor upto 32 queues starting at the base queue #.
|
||||
monitor up to 32 queues starting at the base queue #.
|
||||
- descriptor-regions : child node describing the memory regions for keystone
|
||||
navigator packet DMA descriptors. The memory for
|
||||
descriptors will be allocated by the driver.
|
||||
|
|
|
@ -15,7 +15,7 @@ Required properties:
|
|||
|
||||
Example:
|
||||
|
||||
hda@0,70030000 {
|
||||
hda@70030000 {
|
||||
compatible = "nvidia,tegra124-hda", "nvidia,tegra30-hda";
|
||||
reg = <0x0 0x70030000 0x0 0x10000>;
|
||||
interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
|
|
@ -51,7 +51,7 @@ sram: sram@5c000000 {
|
|||
compatible = "mmio-sram";
|
||||
reg = <0x5c000000 0x40000>; /* 256 KiB SRAM at address 0x5c000000 */
|
||||
|
||||
#adress-cells = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges = <0 0x5c000000 0x40000>;
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ Required properties :
|
|||
|
||||
Example :
|
||||
|
||||
soctherm@0,700e2000 {
|
||||
soctherm@700e2000 {
|
||||
compatible = "nvidia,tegra124-soctherm";
|
||||
reg = <0x0 0x700e2000 0x0 0x1000>;
|
||||
interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
|
|
@ -28,6 +28,7 @@ aptina Aptina Imaging
|
|||
arasan Arasan Chip Systems
|
||||
arm ARM Ltd.
|
||||
armadeus ARMadeus Systems SARL
|
||||
arrow Arrow Electronics
|
||||
artesyn Artesyn Embedded Technologies Inc.
|
||||
asahi-kasei Asahi Kasei Corp.
|
||||
aspeed ASPEED Technology Inc.
|
||||
|
@ -60,6 +61,7 @@ cnxt Conexant Systems, Inc.
|
|||
compulab CompuLab Ltd.
|
||||
cortina Cortina Systems, Inc.
|
||||
cosmic Cosmic Circuits
|
||||
creative Creative Technology Ltd
|
||||
crystalfontz Crystalfontz America, Inc.
|
||||
cubietech Cubietech, Ltd.
|
||||
cypress Cypress Semiconductor Corporation
|
||||
|
@ -79,6 +81,7 @@ ebv EBV Elektronik
|
|||
edt Emerging Display Technologies
|
||||
eeti eGalax_eMPIA Technology Inc
|
||||
elan Elan Microelectronic Corp.
|
||||
embest Shenzhen Embest Technology Co., Ltd.
|
||||
emmicro EM Microelectronic
|
||||
energymicro Silicon Laboratories (formerly Energy Micro AS)
|
||||
epcos EPCOS AG
|
||||
|
@ -124,6 +127,7 @@ idt Integrated Device Technologies, Inc.
|
|||
ifi Ingenieurburo Fur Ic-Technologie (I/F/I)
|
||||
iom Iomega Corporation
|
||||
img Imagination Technologies Ltd.
|
||||
inforce Inforce Computing
|
||||
ingenic Ingenic Semiconductor
|
||||
innolux Innolux Corporation
|
||||
intel Intel Corporation
|
||||
|
|
|
@ -157,7 +157,7 @@ struct device_node * __init tilcdc_get_overlay(struct kfree_table *kft)
|
|||
if (!overlay_data || kfree_table_add(kft, overlay_data))
|
||||
return NULL;
|
||||
|
||||
of_fdt_unflatten_tree(overlay_data, &overlay);
|
||||
of_fdt_unflatten_tree(overlay_data, NULL, &overlay);
|
||||
if (!overlay) {
|
||||
pr_warn("%s: Unfattening overlay tree failed\n", __func__);
|
||||
return NULL;
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
#include "io-pgtable.h"
|
||||
|
||||
/* Maximum number of stream IDs assigned to a single device */
|
||||
#define MAX_MASTER_STREAMIDS MAX_PHANDLE_ARGS
|
||||
#define MAX_MASTER_STREAMIDS 128
|
||||
|
||||
/* Maximum number of context banks per SMMU */
|
||||
#define ARM_SMMU_MAX_CBS 128
|
||||
|
@ -397,6 +397,12 @@ struct arm_smmu_domain {
|
|||
struct iommu_domain domain;
|
||||
};
|
||||
|
||||
struct arm_smmu_phandle_args {
|
||||
struct device_node *np;
|
||||
int args_count;
|
||||
uint32_t args[MAX_MASTER_STREAMIDS];
|
||||
};
|
||||
|
||||
static DEFINE_SPINLOCK(arm_smmu_devices_lock);
|
||||
static LIST_HEAD(arm_smmu_devices);
|
||||
|
||||
|
@ -506,7 +512,7 @@ static int insert_smmu_master(struct arm_smmu_device *smmu,
|
|||
|
||||
static int register_smmu_master(struct arm_smmu_device *smmu,
|
||||
struct device *dev,
|
||||
struct of_phandle_args *masterspec)
|
||||
struct arm_smmu_phandle_args *masterspec)
|
||||
{
|
||||
int i;
|
||||
struct arm_smmu_master *master;
|
||||
|
@ -1875,7 +1881,8 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
|
|||
struct arm_smmu_device *smmu;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct rb_node *node;
|
||||
struct of_phandle_args masterspec;
|
||||
struct of_phandle_iterator it;
|
||||
struct arm_smmu_phandle_args *masterspec;
|
||||
int num_irqs, i, err;
|
||||
|
||||
smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL);
|
||||
|
@ -1938,20 +1945,35 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
|
|||
|
||||
i = 0;
|
||||
smmu->masters = RB_ROOT;
|
||||
while (!of_parse_phandle_with_args(dev->of_node, "mmu-masters",
|
||||
"#stream-id-cells", i,
|
||||
&masterspec)) {
|
||||
err = register_smmu_master(smmu, dev, &masterspec);
|
||||
|
||||
err = -ENOMEM;
|
||||
/* No need to zero the memory for masterspec */
|
||||
masterspec = kmalloc(sizeof(*masterspec), GFP_KERNEL);
|
||||
if (!masterspec)
|
||||
goto out_put_masters;
|
||||
|
||||
of_for_each_phandle(&it, err, dev->of_node,
|
||||
"mmu-masters", "#stream-id-cells", 0) {
|
||||
int count = of_phandle_iterator_args(&it, masterspec->args,
|
||||
MAX_MASTER_STREAMIDS);
|
||||
masterspec->np = of_node_get(it.node);
|
||||
masterspec->args_count = count;
|
||||
|
||||
err = register_smmu_master(smmu, dev, masterspec);
|
||||
if (err) {
|
||||
dev_err(dev, "failed to add master %s\n",
|
||||
masterspec.np->name);
|
||||
masterspec->np->name);
|
||||
kfree(masterspec);
|
||||
goto out_put_masters;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
dev_notice(dev, "registered %d master devices\n", i);
|
||||
|
||||
kfree(masterspec);
|
||||
|
||||
parse_driver_options(smmu);
|
||||
|
||||
if (smmu->version == ARM_SMMU_V2 &&
|
||||
|
|
|
@ -394,7 +394,8 @@ bool __weak arch_find_n_match_cpu_physical_id(struct device_node *cpun,
|
|||
* before booting secondary cores. This function uses arch_match_cpu_phys_id
|
||||
* which can be overridden by architecture specific implementation.
|
||||
*
|
||||
* Returns a node pointer for the logical cpu if found, else NULL.
|
||||
* Returns a node pointer for the logical cpu with refcount incremented, use
|
||||
* of_node_put() on it when done. Returns NULL if not found.
|
||||
*/
|
||||
struct device_node *of_get_cpu_node(int cpu, unsigned int *thread)
|
||||
{
|
||||
|
@ -1440,106 +1441,155 @@ void of_print_phandle_args(const char *msg, const struct of_phandle_args *args)
|
|||
printk("\n");
|
||||
}
|
||||
|
||||
int of_phandle_iterator_init(struct of_phandle_iterator *it,
|
||||
const struct device_node *np,
|
||||
const char *list_name,
|
||||
const char *cells_name,
|
||||
int cell_count)
|
||||
{
|
||||
const __be32 *list;
|
||||
int size;
|
||||
|
||||
memset(it, 0, sizeof(*it));
|
||||
|
||||
list = of_get_property(np, list_name, &size);
|
||||
if (!list)
|
||||
return -ENOENT;
|
||||
|
||||
it->cells_name = cells_name;
|
||||
it->cell_count = cell_count;
|
||||
it->parent = np;
|
||||
it->list_end = list + size / sizeof(*list);
|
||||
it->phandle_end = list;
|
||||
it->cur = list;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int of_phandle_iterator_next(struct of_phandle_iterator *it)
|
||||
{
|
||||
uint32_t count = 0;
|
||||
|
||||
if (it->node) {
|
||||
of_node_put(it->node);
|
||||
it->node = NULL;
|
||||
}
|
||||
|
||||
if (!it->cur || it->phandle_end >= it->list_end)
|
||||
return -ENOENT;
|
||||
|
||||
it->cur = it->phandle_end;
|
||||
|
||||
/* If phandle is 0, then it is an empty entry with no arguments. */
|
||||
it->phandle = be32_to_cpup(it->cur++);
|
||||
|
||||
if (it->phandle) {
|
||||
|
||||
/*
|
||||
* Find the provider node and parse the #*-cells property to
|
||||
* determine the argument length.
|
||||
*/
|
||||
it->node = of_find_node_by_phandle(it->phandle);
|
||||
|
||||
if (it->cells_name) {
|
||||
if (!it->node) {
|
||||
pr_err("%s: could not find phandle\n",
|
||||
it->parent->full_name);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (of_property_read_u32(it->node, it->cells_name,
|
||||
&count)) {
|
||||
pr_err("%s: could not get %s for %s\n",
|
||||
it->parent->full_name,
|
||||
it->cells_name,
|
||||
it->node->full_name);
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
count = it->cell_count;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure that the arguments actually fit in the remaining
|
||||
* property data length
|
||||
*/
|
||||
if (it->cur + count > it->list_end) {
|
||||
pr_err("%s: arguments longer than property\n",
|
||||
it->parent->full_name);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
it->phandle_end = it->cur + count;
|
||||
it->cur_count = count;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
if (it->node) {
|
||||
of_node_put(it->node);
|
||||
it->node = NULL;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int of_phandle_iterator_args(struct of_phandle_iterator *it,
|
||||
uint32_t *args,
|
||||
int size)
|
||||
{
|
||||
int i, count;
|
||||
|
||||
count = it->cur_count;
|
||||
|
||||
if (WARN_ON(size < count))
|
||||
count = size;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
args[i] = be32_to_cpup(it->cur++);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int __of_parse_phandle_with_args(const struct device_node *np,
|
||||
const char *list_name,
|
||||
const char *cells_name,
|
||||
int cell_count, int index,
|
||||
struct of_phandle_args *out_args)
|
||||
{
|
||||
const __be32 *list, *list_end;
|
||||
int rc = 0, size, cur_index = 0;
|
||||
uint32_t count = 0;
|
||||
struct device_node *node = NULL;
|
||||
phandle phandle;
|
||||
|
||||
/* Retrieve the phandle list property */
|
||||
list = of_get_property(np, list_name, &size);
|
||||
if (!list)
|
||||
return -ENOENT;
|
||||
list_end = list + size / sizeof(*list);
|
||||
struct of_phandle_iterator it;
|
||||
int rc, cur_index = 0;
|
||||
|
||||
/* Loop over the phandles until all the requested entry is found */
|
||||
while (list < list_end) {
|
||||
rc = -EINVAL;
|
||||
count = 0;
|
||||
|
||||
of_for_each_phandle(&it, rc, np, list_name, cells_name, cell_count) {
|
||||
/*
|
||||
* If phandle is 0, then it is an empty entry with no
|
||||
* arguments. Skip forward to the next entry.
|
||||
*/
|
||||
phandle = be32_to_cpup(list++);
|
||||
if (phandle) {
|
||||
/*
|
||||
* Find the provider node and parse the #*-cells
|
||||
* property to determine the argument length.
|
||||
*
|
||||
* This is not needed if the cell count is hard-coded
|
||||
* (i.e. cells_name not set, but cell_count is set),
|
||||
* except when we're going to return the found node
|
||||
* below.
|
||||
*/
|
||||
if (cells_name || cur_index == index) {
|
||||
node = of_find_node_by_phandle(phandle);
|
||||
if (!node) {
|
||||
pr_err("%s: could not find phandle\n",
|
||||
np->full_name);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (cells_name) {
|
||||
if (of_property_read_u32(node, cells_name,
|
||||
&count)) {
|
||||
pr_err("%s: could not get %s for %s\n",
|
||||
np->full_name, cells_name,
|
||||
node->full_name);
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
count = cell_count;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure that the arguments actually fit in the
|
||||
* remaining property data length
|
||||
*/
|
||||
if (list + count > list_end) {
|
||||
pr_err("%s: arguments longer than property\n",
|
||||
np->full_name);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* All of the error cases above bail out of the loop, so at
|
||||
* All of the error cases bail out of the loop, so at
|
||||
* this point, the parsing is successful. If the requested
|
||||
* index matches, then fill the out_args structure and return,
|
||||
* or return -ENOENT for an empty entry.
|
||||
*/
|
||||
rc = -ENOENT;
|
||||
if (cur_index == index) {
|
||||
if (!phandle)
|
||||
if (!it.phandle)
|
||||
goto err;
|
||||
|
||||
if (out_args) {
|
||||
int i;
|
||||
if (WARN_ON(count > MAX_PHANDLE_ARGS))
|
||||
count = MAX_PHANDLE_ARGS;
|
||||
out_args->np = node;
|
||||
out_args->args_count = count;
|
||||
for (i = 0; i < count; i++)
|
||||
out_args->args[i] = be32_to_cpup(list++);
|
||||
int c;
|
||||
|
||||
c = of_phandle_iterator_args(&it,
|
||||
out_args->args,
|
||||
MAX_PHANDLE_ARGS);
|
||||
out_args->np = it.node;
|
||||
out_args->args_count = c;
|
||||
} else {
|
||||
of_node_put(node);
|
||||
of_node_put(it.node);
|
||||
}
|
||||
|
||||
/* Found it! return success */
|
||||
return 0;
|
||||
}
|
||||
|
||||
of_node_put(node);
|
||||
node = NULL;
|
||||
list += count;
|
||||
cur_index++;
|
||||
}
|
||||
|
||||
|
@ -1547,12 +1597,11 @@ static int __of_parse_phandle_with_args(const struct device_node *np,
|
|||
* Unlock node before returning result; will be one of:
|
||||
* -ENOENT : index is for empty phandle
|
||||
* -EINVAL : parsing error on data
|
||||
* [1..n] : Number of phandle (count mode; when index = -1)
|
||||
*/
|
||||
rc = index < 0 ? cur_index : -ENOENT;
|
||||
|
||||
err:
|
||||
if (node)
|
||||
of_node_put(node);
|
||||
if (it.node)
|
||||
of_node_put(it.node);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -1684,8 +1733,20 @@ EXPORT_SYMBOL(of_parse_phandle_with_fixed_args);
|
|||
int of_count_phandle_with_args(const struct device_node *np, const char *list_name,
|
||||
const char *cells_name)
|
||||
{
|
||||
return __of_parse_phandle_with_args(np, list_name, cells_name, 0, -1,
|
||||
NULL);
|
||||
struct of_phandle_iterator it;
|
||||
int rc, cur_index = 0;
|
||||
|
||||
rc = of_phandle_iterator_init(&it, np, list_name, cells_name, 0);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
while ((rc = of_phandle_iterator_next(&it)) == 0)
|
||||
cur_index += 1;
|
||||
|
||||
if (rc != -ENOENT)
|
||||
return rc;
|
||||
|
||||
return cur_index;
|
||||
}
|
||||
EXPORT_SYMBOL(of_count_phandle_with_args);
|
||||
|
||||
|
|
|
@ -311,6 +311,7 @@ int of_detach_node(struct device_node *np)
|
|||
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_detach_node);
|
||||
|
||||
/**
|
||||
* of_node_release() - release a dynamically allocated node
|
||||
|
@ -497,6 +498,11 @@ static void __of_changeset_entry_invert(struct of_changeset_entry *ce,
|
|||
case OF_RECONFIG_UPDATE_PROPERTY:
|
||||
rce->old_prop = ce->prop;
|
||||
rce->prop = ce->old_prop;
|
||||
/* update was used but original property did not exist */
|
||||
if (!rce->prop) {
|
||||
rce->action = OF_RECONFIG_REMOVE_PROPERTY;
|
||||
rce->prop = ce->prop;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
382
drivers/of/fdt.c
382
drivers/of/fdt.c
|
@ -161,39 +161,127 @@ static void *unflatten_dt_alloc(void **mem, unsigned long size,
|
|||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* unflatten_dt_node - Alloc and populate a device_node from the flat tree
|
||||
* @blob: The parent device tree blob
|
||||
* @mem: Memory chunk to use for allocating device nodes and properties
|
||||
* @poffset: pointer to node in flat tree
|
||||
* @dad: Parent struct device_node
|
||||
* @nodepp: The device_node tree created by the call
|
||||
* @fpsize: Size of the node path up at the current depth.
|
||||
* @dryrun: If true, do not allocate device nodes but still calculate needed
|
||||
* memory size
|
||||
*/
|
||||
static void * unflatten_dt_node(const void *blob,
|
||||
void *mem,
|
||||
int *poffset,
|
||||
struct device_node *dad,
|
||||
struct device_node **nodepp,
|
||||
unsigned long fpsize,
|
||||
static void populate_properties(const void *blob,
|
||||
int offset,
|
||||
void **mem,
|
||||
struct device_node *np,
|
||||
const char *nodename,
|
||||
bool dryrun)
|
||||
{
|
||||
const __be32 *p;
|
||||
struct property *pp, **pprev = NULL;
|
||||
int cur;
|
||||
bool has_name = false;
|
||||
|
||||
pprev = &np->properties;
|
||||
for (cur = fdt_first_property_offset(blob, offset);
|
||||
cur >= 0;
|
||||
cur = fdt_next_property_offset(blob, cur)) {
|
||||
const __be32 *val;
|
||||
const char *pname;
|
||||
u32 sz;
|
||||
|
||||
val = fdt_getprop_by_offset(blob, cur, &pname, &sz);
|
||||
if (!val) {
|
||||
pr_warn("%s: Cannot locate property at 0x%x\n",
|
||||
__func__, cur);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!pname) {
|
||||
pr_warn("%s: Cannot find property name at 0x%x\n",
|
||||
__func__, cur);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(pname, "name"))
|
||||
has_name = true;
|
||||
|
||||
pp = unflatten_dt_alloc(mem, sizeof(struct property),
|
||||
__alignof__(struct property));
|
||||
if (dryrun)
|
||||
continue;
|
||||
|
||||
/* We accept flattened tree phandles either in
|
||||
* ePAPR-style "phandle" properties, or the
|
||||
* legacy "linux,phandle" properties. If both
|
||||
* appear and have different values, things
|
||||
* will get weird. Don't do that.
|
||||
*/
|
||||
if (!strcmp(pname, "phandle") ||
|
||||
!strcmp(pname, "linux,phandle")) {
|
||||
if (!np->phandle)
|
||||
np->phandle = be32_to_cpup(val);
|
||||
}
|
||||
|
||||
/* And we process the "ibm,phandle" property
|
||||
* used in pSeries dynamic device tree
|
||||
* stuff
|
||||
*/
|
||||
if (!strcmp(pname, "ibm,phandle"))
|
||||
np->phandle = be32_to_cpup(val);
|
||||
|
||||
pp->name = (char *)pname;
|
||||
pp->length = sz;
|
||||
pp->value = (__be32 *)val;
|
||||
*pprev = pp;
|
||||
pprev = &pp->next;
|
||||
}
|
||||
|
||||
/* With version 0x10 we may not have the name property,
|
||||
* recreate it here from the unit name if absent
|
||||
*/
|
||||
if (!has_name) {
|
||||
const char *p = nodename, *ps = p, *pa = NULL;
|
||||
int len;
|
||||
|
||||
while (*p) {
|
||||
if ((*p) == '@')
|
||||
pa = p;
|
||||
else if ((*p) == '/')
|
||||
ps = p + 1;
|
||||
p++;
|
||||
}
|
||||
|
||||
if (pa < ps)
|
||||
pa = p;
|
||||
len = (pa - ps) + 1;
|
||||
pp = unflatten_dt_alloc(mem, sizeof(struct property) + len,
|
||||
__alignof__(struct property));
|
||||
if (!dryrun) {
|
||||
pp->name = "name";
|
||||
pp->length = len;
|
||||
pp->value = pp + 1;
|
||||
*pprev = pp;
|
||||
pprev = &pp->next;
|
||||
memcpy(pp->value, ps, len - 1);
|
||||
((char *)pp->value)[len - 1] = 0;
|
||||
pr_debug("fixed up name for %s -> %s\n",
|
||||
nodename, (char *)pp->value);
|
||||
}
|
||||
}
|
||||
|
||||
if (!dryrun)
|
||||
*pprev = NULL;
|
||||
}
|
||||
|
||||
static unsigned int populate_node(const void *blob,
|
||||
int offset,
|
||||
void **mem,
|
||||
struct device_node *dad,
|
||||
unsigned int fpsize,
|
||||
struct device_node **pnp,
|
||||
bool dryrun)
|
||||
{
|
||||
struct device_node *np;
|
||||
struct property *pp, **prev_pp = NULL;
|
||||
const char *pathp;
|
||||
unsigned int l, allocl;
|
||||
static int depth;
|
||||
int old_depth;
|
||||
int offset;
|
||||
int has_name = 0;
|
||||
int new_format = 0;
|
||||
|
||||
pathp = fdt_get_name(blob, *poffset, &l);
|
||||
if (!pathp)
|
||||
return mem;
|
||||
pathp = fdt_get_name(blob, offset, &l);
|
||||
if (!pathp) {
|
||||
*pnp = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
allocl = ++l;
|
||||
|
||||
|
@ -223,7 +311,7 @@ static void * unflatten_dt_node(const void *blob,
|
|||
}
|
||||
}
|
||||
|
||||
np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl,
|
||||
np = unflatten_dt_alloc(mem, sizeof(struct device_node) + allocl,
|
||||
__alignof__(struct device_node));
|
||||
if (!dryrun) {
|
||||
char *fn;
|
||||
|
@ -246,89 +334,15 @@ static void * unflatten_dt_node(const void *blob,
|
|||
}
|
||||
memcpy(fn, pathp, l);
|
||||
|
||||
prev_pp = &np->properties;
|
||||
if (dad != NULL) {
|
||||
np->parent = dad;
|
||||
np->sibling = dad->child;
|
||||
dad->child = np;
|
||||
}
|
||||
}
|
||||
/* process properties */
|
||||
for (offset = fdt_first_property_offset(blob, *poffset);
|
||||
(offset >= 0);
|
||||
(offset = fdt_next_property_offset(blob, offset))) {
|
||||
const char *pname;
|
||||
u32 sz;
|
||||
|
||||
if (!(p = fdt_getprop_by_offset(blob, offset, &pname, &sz))) {
|
||||
offset = -FDT_ERR_INTERNAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (pname == NULL) {
|
||||
pr_info("Can't find property name in list !\n");
|
||||
break;
|
||||
}
|
||||
if (strcmp(pname, "name") == 0)
|
||||
has_name = 1;
|
||||
pp = unflatten_dt_alloc(&mem, sizeof(struct property),
|
||||
__alignof__(struct property));
|
||||
if (!dryrun) {
|
||||
/* We accept flattened tree phandles either in
|
||||
* ePAPR-style "phandle" properties, or the
|
||||
* legacy "linux,phandle" properties. If both
|
||||
* appear and have different values, things
|
||||
* will get weird. Don't do that. */
|
||||
if ((strcmp(pname, "phandle") == 0) ||
|
||||
(strcmp(pname, "linux,phandle") == 0)) {
|
||||
if (np->phandle == 0)
|
||||
np->phandle = be32_to_cpup(p);
|
||||
}
|
||||
/* And we process the "ibm,phandle" property
|
||||
* used in pSeries dynamic device tree
|
||||
* stuff */
|
||||
if (strcmp(pname, "ibm,phandle") == 0)
|
||||
np->phandle = be32_to_cpup(p);
|
||||
pp->name = (char *)pname;
|
||||
pp->length = sz;
|
||||
pp->value = (__be32 *)p;
|
||||
*prev_pp = pp;
|
||||
prev_pp = &pp->next;
|
||||
}
|
||||
}
|
||||
/* with version 0x10 we may not have the name property, recreate
|
||||
* it here from the unit name if absent
|
||||
*/
|
||||
if (!has_name) {
|
||||
const char *p1 = pathp, *ps = pathp, *pa = NULL;
|
||||
int sz;
|
||||
|
||||
while (*p1) {
|
||||
if ((*p1) == '@')
|
||||
pa = p1;
|
||||
if ((*p1) == '/')
|
||||
ps = p1 + 1;
|
||||
p1++;
|
||||
}
|
||||
if (pa < ps)
|
||||
pa = p1;
|
||||
sz = (pa - ps) + 1;
|
||||
pp = unflatten_dt_alloc(&mem, sizeof(struct property) + sz,
|
||||
__alignof__(struct property));
|
||||
if (!dryrun) {
|
||||
pp->name = "name";
|
||||
pp->length = sz;
|
||||
pp->value = pp + 1;
|
||||
*prev_pp = pp;
|
||||
prev_pp = &pp->next;
|
||||
memcpy(pp->value, ps, sz - 1);
|
||||
((char *)pp->value)[sz - 1] = 0;
|
||||
pr_debug("fixed up name for %s -> %s\n", pathp,
|
||||
(char *)pp->value);
|
||||
}
|
||||
}
|
||||
populate_properties(blob, offset, mem, np, pathp, dryrun);
|
||||
if (!dryrun) {
|
||||
*prev_pp = NULL;
|
||||
np->name = of_get_property(np, "name", NULL);
|
||||
np->type = of_get_property(np, "device_type", NULL);
|
||||
|
||||
|
@ -338,36 +352,94 @@ static void * unflatten_dt_node(const void *blob,
|
|||
np->type = "<NULL>";
|
||||
}
|
||||
|
||||
old_depth = depth;
|
||||
*poffset = fdt_next_node(blob, *poffset, &depth);
|
||||
if (depth < 0)
|
||||
depth = 0;
|
||||
while (*poffset > 0 && depth > old_depth)
|
||||
mem = unflatten_dt_node(blob, mem, poffset, np, NULL,
|
||||
fpsize, dryrun);
|
||||
*pnp = np;
|
||||
return fpsize;
|
||||
}
|
||||
|
||||
if (*poffset < 0 && *poffset != -FDT_ERR_NOTFOUND)
|
||||
pr_err("unflatten: error %d processing FDT\n", *poffset);
|
||||
static void reverse_nodes(struct device_node *parent)
|
||||
{
|
||||
struct device_node *child, *next;
|
||||
|
||||
/* In-depth first */
|
||||
child = parent->child;
|
||||
while (child) {
|
||||
reverse_nodes(child);
|
||||
|
||||
child = child->sibling;
|
||||
}
|
||||
|
||||
/* Reverse the nodes in the child list */
|
||||
child = parent->child;
|
||||
parent->child = NULL;
|
||||
while (child) {
|
||||
next = child->sibling;
|
||||
|
||||
child->sibling = parent->child;
|
||||
parent->child = child;
|
||||
child = next;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* unflatten_dt_nodes - Alloc and populate a device_node from the flat tree
|
||||
* @blob: The parent device tree blob
|
||||
* @mem: Memory chunk to use for allocating device nodes and properties
|
||||
* @dad: Parent struct device_node
|
||||
* @nodepp: The device_node tree created by the call
|
||||
*
|
||||
* It returns the size of unflattened device tree or error code
|
||||
*/
|
||||
static int unflatten_dt_nodes(const void *blob,
|
||||
void *mem,
|
||||
struct device_node *dad,
|
||||
struct device_node **nodepp)
|
||||
{
|
||||
struct device_node *root;
|
||||
int offset = 0, depth = 0;
|
||||
#define FDT_MAX_DEPTH 64
|
||||
unsigned int fpsizes[FDT_MAX_DEPTH];
|
||||
struct device_node *nps[FDT_MAX_DEPTH];
|
||||
void *base = mem;
|
||||
bool dryrun = !base;
|
||||
|
||||
if (nodepp)
|
||||
*nodepp = NULL;
|
||||
|
||||
root = dad;
|
||||
fpsizes[depth] = dad ? strlen(of_node_full_name(dad)) : 0;
|
||||
nps[depth] = dad;
|
||||
for (offset = 0;
|
||||
offset >= 0 && depth >= 0;
|
||||
offset = fdt_next_node(blob, offset, &depth)) {
|
||||
if (WARN_ON_ONCE(depth >= FDT_MAX_DEPTH))
|
||||
continue;
|
||||
|
||||
fpsizes[depth+1] = populate_node(blob, offset, &mem,
|
||||
nps[depth],
|
||||
fpsizes[depth],
|
||||
&nps[depth+1], dryrun);
|
||||
if (!fpsizes[depth+1])
|
||||
return mem - base;
|
||||
|
||||
if (!dryrun && nodepp && !*nodepp)
|
||||
*nodepp = nps[depth+1];
|
||||
if (!dryrun && !root)
|
||||
root = nps[depth+1];
|
||||
}
|
||||
|
||||
if (offset < 0 && offset != -FDT_ERR_NOTFOUND) {
|
||||
pr_err("%s: Error %d processing FDT\n", __func__, offset);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reverse the child list. Some drivers assumes node order matches .dts
|
||||
* node order
|
||||
*/
|
||||
if (!dryrun && np->child) {
|
||||
struct device_node *child = np->child;
|
||||
np->child = NULL;
|
||||
while (child) {
|
||||
struct device_node *next = child->sibling;
|
||||
child->sibling = np->child;
|
||||
np->child = child;
|
||||
child = next;
|
||||
}
|
||||
}
|
||||
if (!dryrun)
|
||||
reverse_nodes(root);
|
||||
|
||||
if (nodepp)
|
||||
*nodepp = np;
|
||||
|
||||
return mem;
|
||||
return mem - base;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -378,23 +450,27 @@ static void * unflatten_dt_node(const void *blob,
|
|||
* pointers of the nodes so the normal device-tree walking functions
|
||||
* can be used.
|
||||
* @blob: The blob to expand
|
||||
* @dad: Parent device node
|
||||
* @mynodes: The device_node tree created by the call
|
||||
* @dt_alloc: An allocator that provides a virtual address to memory
|
||||
* for the resulting tree
|
||||
*
|
||||
* Returns NULL on failure or the memory chunk containing the unflattened
|
||||
* device tree on success.
|
||||
*/
|
||||
static void __unflatten_device_tree(const void *blob,
|
||||
struct device_node **mynodes,
|
||||
void * (*dt_alloc)(u64 size, u64 align))
|
||||
static void *__unflatten_device_tree(const void *blob,
|
||||
struct device_node *dad,
|
||||
struct device_node **mynodes,
|
||||
void *(*dt_alloc)(u64 size, u64 align))
|
||||
{
|
||||
unsigned long size;
|
||||
int start;
|
||||
int size;
|
||||
void *mem;
|
||||
|
||||
pr_debug(" -> unflatten_device_tree()\n");
|
||||
|
||||
if (!blob) {
|
||||
pr_debug("No device tree pointer\n");
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pr_debug("Unflattening device tree:\n");
|
||||
|
@ -404,15 +480,16 @@ static void __unflatten_device_tree(const void *blob,
|
|||
|
||||
if (fdt_check_header(blob)) {
|
||||
pr_err("Invalid device tree blob header\n");
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* First pass, scan for size */
|
||||
start = 0;
|
||||
size = (unsigned long)unflatten_dt_node(blob, NULL, &start, NULL, NULL, 0, true);
|
||||
size = ALIGN(size, 4);
|
||||
size = unflatten_dt_nodes(blob, NULL, dad, NULL);
|
||||
if (size < 0)
|
||||
return NULL;
|
||||
|
||||
pr_debug(" size is %lx, allocating...\n", size);
|
||||
size = ALIGN(size, 4);
|
||||
pr_debug(" size is %d, allocating...\n", size);
|
||||
|
||||
/* Allocate memory for the expanded device tree */
|
||||
mem = dt_alloc(size + 4, __alignof__(struct device_node));
|
||||
|
@ -423,13 +500,13 @@ static void __unflatten_device_tree(const void *blob,
|
|||
pr_debug(" unflattening %p...\n", mem);
|
||||
|
||||
/* Second pass, do actual unflattening */
|
||||
start = 0;
|
||||
unflatten_dt_node(blob, mem, &start, NULL, mynodes, 0, false);
|
||||
unflatten_dt_nodes(blob, mem, dad, mynodes);
|
||||
if (be32_to_cpup(mem + size) != 0xdeadbeef)
|
||||
pr_warning("End of tree marker overwritten: %08x\n",
|
||||
be32_to_cpup(mem + size));
|
||||
|
||||
pr_debug(" <- unflatten_device_tree()\n");
|
||||
return mem;
|
||||
}
|
||||
|
||||
static void *kernel_tree_alloc(u64 size, u64 align)
|
||||
|
@ -441,18 +518,29 @@ static DEFINE_MUTEX(of_fdt_unflatten_mutex);
|
|||
|
||||
/**
|
||||
* of_fdt_unflatten_tree - create tree of device_nodes from flat blob
|
||||
* @blob: Flat device tree blob
|
||||
* @dad: Parent device node
|
||||
* @mynodes: The device tree created by the call
|
||||
*
|
||||
* unflattens the device-tree passed by the firmware, creating the
|
||||
* tree of struct device_node. It also fills the "name" and "type"
|
||||
* pointers of the nodes so the normal device-tree walking functions
|
||||
* can be used.
|
||||
*
|
||||
* Returns NULL on failure or the memory chunk containing the unflattened
|
||||
* device tree on success.
|
||||
*/
|
||||
void of_fdt_unflatten_tree(const unsigned long *blob,
|
||||
struct device_node **mynodes)
|
||||
void *of_fdt_unflatten_tree(const unsigned long *blob,
|
||||
struct device_node *dad,
|
||||
struct device_node **mynodes)
|
||||
{
|
||||
void *mem;
|
||||
|
||||
mutex_lock(&of_fdt_unflatten_mutex);
|
||||
__unflatten_device_tree(blob, mynodes, &kernel_tree_alloc);
|
||||
mem = __unflatten_device_tree(blob, dad, mynodes, &kernel_tree_alloc);
|
||||
mutex_unlock(&of_fdt_unflatten_mutex);
|
||||
|
||||
return mem;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_fdt_unflatten_tree);
|
||||
|
||||
|
@ -969,10 +1057,16 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
|
|||
* is set in which case we override whatever was found earlier.
|
||||
*/
|
||||
#ifdef CONFIG_CMDLINE
|
||||
#ifndef CONFIG_CMDLINE_FORCE
|
||||
#if defined(CONFIG_CMDLINE_EXTEND)
|
||||
strlcat(data, " ", COMMAND_LINE_SIZE);
|
||||
strlcat(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
|
||||
#elif defined(CONFIG_CMDLINE_FORCE)
|
||||
strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
|
||||
#else
|
||||
/* No arguments from boot loader, use kernel's cmdl*/
|
||||
if (!((char *)data)[0])
|
||||
#endif
|
||||
strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
|
||||
#endif
|
||||
#endif /* CONFIG_CMDLINE */
|
||||
|
||||
pr_debug("Command line is: %s\n", (char*)data);
|
||||
|
@ -1118,7 +1212,7 @@ bool __init early_init_dt_scan(void *params)
|
|||
*/
|
||||
void __init unflatten_device_tree(void)
|
||||
{
|
||||
__unflatten_device_tree(initial_boot_params, &of_root,
|
||||
__unflatten_device_tree(initial_boot_params, NULL, &of_root,
|
||||
early_init_dt_alloc_memory_arch);
|
||||
|
||||
/* Get pointer to "/chosen" and "/aliases" nodes for use everywhere */
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#include <linux/err.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/hashtable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/of_irq.h>
|
||||
|
@ -921,7 +920,7 @@ static int __init unittest_data_add(void)
|
|||
"not running tests\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
of_fdt_unflatten_tree(unittest_data, &unittest_data_node);
|
||||
of_fdt_unflatten_tree(unittest_data, NULL, &unittest_data_node);
|
||||
if (!unittest_data_node) {
|
||||
pr_warn("%s: No tree to attach; not running tests\n", __func__);
|
||||
return -ENODATA;
|
||||
|
|
|
@ -75,6 +75,23 @@ struct of_phandle_args {
|
|||
uint32_t args[MAX_PHANDLE_ARGS];
|
||||
};
|
||||
|
||||
struct of_phandle_iterator {
|
||||
/* Common iterator information */
|
||||
const char *cells_name;
|
||||
int cell_count;
|
||||
const struct device_node *parent;
|
||||
|
||||
/* List size information */
|
||||
const __be32 *list_end;
|
||||
const __be32 *phandle_end;
|
||||
|
||||
/* Current position state */
|
||||
const __be32 *cur;
|
||||
uint32_t cur_count;
|
||||
phandle phandle;
|
||||
struct device_node *node;
|
||||
};
|
||||
|
||||
struct of_reconfig_data {
|
||||
struct device_node *dn;
|
||||
struct property *prop;
|
||||
|
@ -334,6 +351,18 @@ extern int of_parse_phandle_with_fixed_args(const struct device_node *np,
|
|||
extern int of_count_phandle_with_args(const struct device_node *np,
|
||||
const char *list_name, const char *cells_name);
|
||||
|
||||
/* phandle iterator functions */
|
||||
extern int of_phandle_iterator_init(struct of_phandle_iterator *it,
|
||||
const struct device_node *np,
|
||||
const char *list_name,
|
||||
const char *cells_name,
|
||||
int cell_count);
|
||||
|
||||
extern int of_phandle_iterator_next(struct of_phandle_iterator *it);
|
||||
extern int of_phandle_iterator_args(struct of_phandle_iterator *it,
|
||||
uint32_t *args,
|
||||
int size);
|
||||
|
||||
extern void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align));
|
||||
extern int of_alias_get_id(struct device_node *np, const char *stem);
|
||||
extern int of_alias_get_highest_id(const char *stem);
|
||||
|
@ -608,6 +637,27 @@ static inline int of_count_phandle_with_args(struct device_node *np,
|
|||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int of_phandle_iterator_init(struct of_phandle_iterator *it,
|
||||
const struct device_node *np,
|
||||
const char *list_name,
|
||||
const char *cells_name,
|
||||
int cell_count)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int of_phandle_iterator_next(struct of_phandle_iterator *it)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int of_phandle_iterator_args(struct of_phandle_iterator *it,
|
||||
uint32_t *args,
|
||||
int size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int of_alias_get_id(struct device_node *np, const char *stem)
|
||||
{
|
||||
return -ENOSYS;
|
||||
|
@ -877,6 +927,12 @@ static inline int of_property_read_s32(const struct device_node *np,
|
|||
return of_property_read_u32(np, propname, (u32*) out_value);
|
||||
}
|
||||
|
||||
#define of_for_each_phandle(it, err, np, ln, cn, cc) \
|
||||
for (of_phandle_iterator_init((it), (np), (ln), (cn), (cc)), \
|
||||
err = of_phandle_iterator_next(it); \
|
||||
err == 0; \
|
||||
err = of_phandle_iterator_next(it))
|
||||
|
||||
#define of_property_for_each_u32(np, propname, prop, p, u) \
|
||||
for (prop = of_find_property(np, propname, NULL), \
|
||||
p = of_prop_next_u32(prop, NULL, &u); \
|
||||
|
|
|
@ -37,8 +37,9 @@ extern bool of_fdt_is_big_endian(const void *blob,
|
|||
unsigned long node);
|
||||
extern int of_fdt_match(const void *blob, unsigned long node,
|
||||
const char *const *compat);
|
||||
extern void of_fdt_unflatten_tree(const unsigned long *blob,
|
||||
struct device_node **mynodes);
|
||||
extern void *of_fdt_unflatten_tree(const unsigned long *blob,
|
||||
struct device_node *dad,
|
||||
struct device_node **mynodes);
|
||||
|
||||
/* TBD: Temporary export of fdt globals - remove when code fully merged */
|
||||
extern int __initdata dt_root_addr_cells;
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#define __LINUX_OF_GRAPH_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
/**
|
||||
* struct of_endpoint - the OF graph endpoint data structure
|
||||
|
|
|
@ -277,6 +277,11 @@ cmd_gzip = (cat $(filter-out FORCE,$^) | gzip -n -f -9 > $@) || \
|
|||
# ---------------------------------------------------------------------------
|
||||
DTC ?= $(objtree)/scripts/dtc/dtc
|
||||
|
||||
# Disable noisy checks by default
|
||||
ifeq ($(KBUILD_ENABLE_EXTRA_GCC_CHECKS),)
|
||||
DTC_FLAGS += -Wno-unit_address_vs_reg
|
||||
endif
|
||||
|
||||
# Generate an assembly file to wrap the output of the device tree compiler
|
||||
quiet_cmd_dt_S_dtb= DTB $@
|
||||
cmd_dt_S_dtb= \
|
||||
|
|
|
@ -294,6 +294,30 @@ static void check_node_name_format(struct check *c, struct node *dt,
|
|||
}
|
||||
NODE_ERROR(node_name_format, NULL, &node_name_chars);
|
||||
|
||||
static void check_unit_address_vs_reg(struct check *c, struct node *dt,
|
||||
struct node *node)
|
||||
{
|
||||
const char *unitname = get_unitname(node);
|
||||
struct property *prop = get_property(node, "reg");
|
||||
|
||||
if (!prop) {
|
||||
prop = get_property(node, "ranges");
|
||||
if (prop && !prop->val.len)
|
||||
prop = NULL;
|
||||
}
|
||||
|
||||
if (prop) {
|
||||
if (!unitname[0])
|
||||
FAIL(c, "Node %s has a reg or ranges property, but no unit name",
|
||||
node->fullpath);
|
||||
} else {
|
||||
if (unitname[0])
|
||||
FAIL(c, "Node %s has a unit name, but no reg property",
|
||||
node->fullpath);
|
||||
}
|
||||
}
|
||||
NODE_WARNING(unit_address_vs_reg, NULL);
|
||||
|
||||
static void check_property_name_chars(struct check *c, struct node *dt,
|
||||
struct node *node, struct property *prop)
|
||||
{
|
||||
|
@ -667,6 +691,8 @@ static struct check *check_table[] = {
|
|||
|
||||
&addr_size_cells, ®_format, &ranges_format,
|
||||
|
||||
&unit_address_vs_reg,
|
||||
|
||||
&avoid_default_addr_size,
|
||||
&obsolete_chosen_interrupt_controller,
|
||||
|
||||
|
|
|
@ -889,7 +889,7 @@ struct boot_info *dt_from_blob(const char *fname)
|
|||
|
||||
if (version >= 3) {
|
||||
uint32_t size_str = fdt32_to_cpu(fdt->size_dt_strings);
|
||||
if (off_str+size_str > totalsize)
|
||||
if ((off_str+size_str < off_str) || (off_str+size_str > totalsize))
|
||||
die("String table extends past total size\n");
|
||||
inbuf_init(&strbuf, blob + off_str, blob + off_str + size_str);
|
||||
} else {
|
||||
|
@ -898,7 +898,7 @@ struct boot_info *dt_from_blob(const char *fname)
|
|||
|
||||
if (version >= 17) {
|
||||
size_dt = fdt32_to_cpu(fdt->size_dt_struct);
|
||||
if (off_dt+size_dt > totalsize)
|
||||
if ((off_dt+size_dt < off_dt) || (off_dt+size_dt > totalsize))
|
||||
die("Structure block extends past total size\n");
|
||||
}
|
||||
|
||||
|
|
|
@ -647,10 +647,8 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset,
|
|||
prop = fdt_getprop(fdt, nodeoffset, "compatible", &len);
|
||||
if (!prop)
|
||||
return len;
|
||||
if (fdt_stringlist_contains(prop, len, compatible))
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
|
||||
return !fdt_stringlist_contains(prop, len, compatible);
|
||||
}
|
||||
|
||||
int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
|
||||
|
|
|
@ -1 +1 @@
|
|||
#define DTC_VERSION "DTC 1.4.1-gb06e55c8"
|
||||
#define DTC_VERSION "DTC 1.4.1-g53bf130b"
|
||||
|
|
Loading…
Reference in New Issue