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:
@@ -100,7 +100,7 @@ specific to ARM.
|
|||||||
"arm,cci-400-pmu,r0"
|
"arm,cci-400-pmu,r0"
|
||||||
"arm,cci-400-pmu,r1"
|
"arm,cci-400-pmu,r1"
|
||||||
"arm,cci-400-pmu" - DEPRECATED, permitted only where OS has
|
"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-500-pmu,r0"
|
||||||
"arm,cci-550-pmu,r0"
|
"arm,cci-550-pmu,r0"
|
||||||
- reg:
|
- reg:
|
||||||
|
@@ -42,7 +42,8 @@ Examples:
|
|||||||
Consumer:
|
Consumer:
|
||||||
========
|
========
|
||||||
See Documentation/devicetree/bindings/interrupt-controller/interrupts.txt and
|
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:
|
An interrupt consumer on an SoC using crossbar will use:
|
||||||
interrupts = <GIC_SPI request_number interrupt_level>
|
interrupts = <GIC_SPI request_number interrupt_level>
|
||||||
|
@@ -6,4 +6,4 @@ few properties of different peripheral controllers.
|
|||||||
misc node required properties:
|
misc node required properties:
|
||||||
|
|
||||||
- compatible Should be "st,spear1340-misc", "syscon".
|
- 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
|
see binding for arm/scu.txt
|
||||||
|
|
||||||
interrupt-controller:
|
interrupt-controller:
|
||||||
see binding for arm/gic.txt
|
see binding for interrupt-controller/arm,gic.txt
|
||||||
|
|
||||||
timer:
|
timer:
|
||||||
see binding for arm/twd.txt
|
see binding for arm/twd.txt
|
||||||
|
@@ -50,7 +50,7 @@ Required properties for I2C mode:
|
|||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
clock@0,70110000 {
|
clock@70110000 {
|
||||||
compatible = "nvidia,tegra124-dfll";
|
compatible = "nvidia,tegra124-dfll";
|
||||||
reg = <0 0x70110000 0 0x100>, /* DFLL control */
|
reg = <0 0x70110000 0 0x100>, /* DFLL control */
|
||||||
<0 0x70110000 0 0x100>, /* I2C output control */
|
<0 0x70110000 0 0x100>, /* I2C output control */
|
||||||
|
@@ -16,7 +16,7 @@ Required Properties:
|
|||||||
Optional Properties:
|
Optional Properties:
|
||||||
|
|
||||||
- rockchip,grf: phandle to the syscon managing the "general register files"
|
- 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
|
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
|
to specify the clock which they consume. All available clocks are defined as
|
||||||
|
@@ -15,7 +15,7 @@ Required Properties:
|
|||||||
Optional Properties:
|
Optional Properties:
|
||||||
|
|
||||||
- rockchip,grf: phandle to the syscon managing the "general register files"
|
- 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
|
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
|
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].
|
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
|
[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
|
||||||
[2] Documentation/devicetree/bindings/clock/st,clkgen-divmux.txt
|
[2] Documentation/devicetree/bindings/clock/st,clkgen-divmux.txt
|
||||||
|
@@ -41,7 +41,7 @@ Video interfaces:
|
|||||||
endpoint node connected from mic node (reg = 0):
|
endpoint node connected from mic node (reg = 0):
|
||||||
- remote-endpoint: specifies the endpoint in mic node. This node is required
|
- remote-endpoint: specifies the endpoint in mic node. This node is required
|
||||||
for Exynos5433 mipi dsi. So mic can access to panel node
|
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):
|
endpoint node connected to panel node (reg = 1):
|
||||||
- remote-endpoint: specifies the endpoint in panel node. This node is
|
- remote-endpoint: specifies the endpoint in panel node. This node is
|
||||||
required in all kinds of exynos mipi dsi to represent
|
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"
|
- compatible: Should be "xlnx,axi-dma-1.00.a"
|
||||||
- #dma-cells: Should be <1>, see "dmas" property below
|
- #dma-cells: Should be <1>, see "dmas" property below
|
||||||
- reg: Should contain DMA registers location and length.
|
- 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
|
two channels per device. This node specifies the properties of each
|
||||||
DMA channel (see child node properties below).
|
DMA channel (see child node properties below).
|
||||||
|
|
||||||
|
24
Documentation/devicetree/bindings/gpio/ibm,ppc4xx-gpio.txt
Normal file
24
Documentation/devicetree/bindings/gpio/ibm,ppc4xx-gpio.txt
Normal file
@@ -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
|
ti,vref-delay-usecs vref supply delay in usecs, 0 for
|
||||||
external vref (u16).
|
external vref (u16).
|
||||||
ti,vref-mv The VREF voltage, in millivolts (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).
|
(ADS7846).
|
||||||
ti,keep-vref-on set to keep vref on for differential
|
ti,keep-vref-on set to keep vref on for differential
|
||||||
measurements as well
|
measurements as well
|
||||||
|
@@ -15,7 +15,7 @@ Optional properties:
|
|||||||
- fsl,pen-debounce-ns: Pen debounce time in nanoseconds.
|
- fsl,pen-debounce-ns: Pen debounce time in nanoseconds.
|
||||||
- fsl,pen-threshold: Pen-down threshold for the touchscreen. This is a value
|
- 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
|
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
|
plates and therefore the voltage decreases with pressure so that a smaller
|
||||||
value is equivalent to a higher pressure.
|
value is equivalent to a higher pressure.
|
||||||
- fsl,settling-time-ns: Settling time in nanoseconds. The settling time is before
|
- fsl,settling-time-ns: Settling time in nanoseconds. The settling time is before
|
||||||
|
@@ -16,8 +16,7 @@ Required properties:
|
|||||||
"mediatek,mt6577-sysirq"
|
"mediatek,mt6577-sysirq"
|
||||||
"mediatek,mt2701-sysirq"
|
"mediatek,mt2701-sysirq"
|
||||||
- interrupt-controller : Identifies the node as an interrupt controller
|
- interrupt-controller : Identifies the node as an interrupt controller
|
||||||
- #interrupt-cells : Use the same format as specified by GIC in
|
- #interrupt-cells : Use the same format as specified by GIC in arm,gic.txt.
|
||||||
Documentation/devicetree/bindings/arm/gic.txt
|
|
||||||
- interrupt-parent: phandle of irq parent for sysirq. The parent must
|
- interrupt-parent: phandle of irq parent for sysirq. The parent must
|
||||||
use the same interrupt-cells format as GIC.
|
use the same interrupt-cells format as GIC.
|
||||||
- reg: Physical base address of the intpol registers and length of memory
|
- 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
|
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.
|
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
|
- compatible : should contain at least "ti,omap4-wugen-mpu" or
|
||||||
"ti,omap5-wugen-mpu"
|
"ti,omap5-wugen-mpu"
|
||||||
@@ -20,7 +20,7 @@ Notes:
|
|||||||
- Because this HW ultimately routes interrupts to the GIC, the
|
- Because this HW ultimately routes interrupts to the GIC, the
|
||||||
interrupt specifier must be that of the GIC.
|
interrupt specifier must be that of the GIC.
|
||||||
- Only SPIs can use the WUGEN as an interrupt parent. SGIs and PPIs
|
- Only SPIs can use the WUGEN as an interrupt parent. SGIs and PPIs
|
||||||
are explicitly forbiden.
|
are explicitly forbidden.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
|
@@ -190,7 +190,7 @@ be specified, according to the board documentation:
|
|||||||
Example SoC include file:
|
Example SoC include file:
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
emc@0,7001b000 {
|
emc@7001b000 {
|
||||||
compatible = "nvidia,tegra124-emc";
|
compatible = "nvidia,tegra124-emc";
|
||||||
reg = <0x0 0x7001b000 0x0 0x1000>;
|
reg = <0x0 0x7001b000 0x0 0x1000>;
|
||||||
|
|
||||||
@@ -201,7 +201,7 @@ Example SoC include file:
|
|||||||
Example board file:
|
Example board file:
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
emc@0,7001b000 {
|
emc@7001b000 {
|
||||||
emc-timings-3 {
|
emc-timings-3 {
|
||||||
nvidia,ram-code = <3>;
|
nvidia,ram-code = <3>;
|
||||||
|
|
@@ -61,7 +61,7 @@ specified, according to the board documentation:
|
|||||||
Example SoC include file:
|
Example SoC include file:
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
mc: memory-controller@0,70019000 {
|
mc: memory-controller@70019000 {
|
||||||
compatible = "nvidia,tegra124-mc";
|
compatible = "nvidia,tegra124-mc";
|
||||||
reg = <0x0 0x70019000 0x0 0x1000>;
|
reg = <0x0 0x70019000 0x0 0x1000>;
|
||||||
clocks = <&tegra_car TEGRA124_CLK_MC>;
|
clocks = <&tegra_car TEGRA124_CLK_MC>;
|
||||||
@@ -72,7 +72,7 @@ Example SoC include file:
|
|||||||
#iommu-cells = <1>;
|
#iommu-cells = <1>;
|
||||||
};
|
};
|
||||||
|
|
||||||
sdhci@0,700b0000 {
|
sdhci@700b0000 {
|
||||||
compatible = "nvidia,tegra124-sdhci";
|
compatible = "nvidia,tegra124-sdhci";
|
||||||
...
|
...
|
||||||
iommus = <&mc TEGRA_SWGROUP_SDMMC1A>;
|
iommus = <&mc TEGRA_SWGROUP_SDMMC1A>;
|
||||||
@@ -82,7 +82,7 @@ Example SoC include file:
|
|||||||
Example board file:
|
Example board file:
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
memory-controller@0,70019000 {
|
memory-controller@70019000 {
|
||||||
emc-timings-3 {
|
emc-timings-3 {
|
||||||
nvidia,ram-code = <3>;
|
nvidia,ram-code = <3>;
|
||||||
|
|
@@ -178,7 +178,7 @@ see regulator.txt - with additional custom properties described below:
|
|||||||
- qcom,force-mode:
|
- qcom,force-mode:
|
||||||
Usage: optional (default if no other qcom,force-mode is specified)
|
Usage: optional (default if no other qcom,force-mode is specified)
|
||||||
Value type: <u32>
|
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:
|
particular mode, valid values are:
|
||||||
QCOM_RPM_FORCE_MODE_NONE - do not force any mode
|
QCOM_RPM_FORCE_MODE_NONE - do not force any mode
|
||||||
QCOM_RPM_FORCE_MODE_LPM - force into low power 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:
|
- qcom,force-mode:
|
||||||
Usage: optional
|
Usage: optional
|
||||||
Value type: <u32>
|
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:
|
particular mode, valid values are:
|
||||||
QCOM_RPM_FORCE_MODE_NONE - do not force any mode
|
QCOM_RPM_FORCE_MODE_NONE - do not force any mode
|
||||||
QCOM_RPM_FORCE_MODE_LPM - force into low power mode
|
QCOM_RPM_FORCE_MODE_LPM - force into low power mode
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
* The simple eMMC hardware reset provider
|
* The simple eMMC hardware reset provider
|
||||||
|
|
||||||
The purpose of this driver is to perform standard eMMC hw reset
|
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
|
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
|
fix possible issues if bootloader has left eMMC card in initialized or
|
||||||
unknown state), and before performing complete system reboot (also in
|
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
|
v7.0. Use this property to describe the rare
|
||||||
earlier versions of this core that include WP
|
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
|
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
|
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.
|
specifies a reference to the associating hardware driver node.
|
||||||
see Documentation/devicetree/bindings/net/hisilicon-hns-dsaf.txt
|
see Documentation/devicetree/bindings/net/hisilicon-hns-dsaf.txt
|
||||||
- port-id: is the index of port provided by DSAF (the accelerator). DSAF can
|
- 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.
|
are called debug ports.
|
||||||
|
|
||||||
The remaining 6 PHYs are taken according to the mode of DSAF.
|
The remaining 6 PHYs are taken according to the mode of DSAF.
|
||||||
|
@@ -51,8 +51,8 @@ Optional properties:
|
|||||||
AXI register inside the DMA module:
|
AXI register inside the DMA module:
|
||||||
- snps,lpi_en: enable Low Power Interface
|
- snps,lpi_en: enable Low Power Interface
|
||||||
- snps,xit_frm: unlock on WoL
|
- snps,xit_frm: unlock on WoL
|
||||||
- snps,wr_osr_lmt: max write oustanding req. limit
|
- snps,wr_osr_lmt: max write outstanding req. limit
|
||||||
- snps,rd_osr_lmt: max read oustanding req. limit
|
- snps,rd_osr_lmt: max read outstanding req. limit
|
||||||
- snps,kbbe: do not cross 1KiB boundary.
|
- snps,kbbe: do not cross 1KiB boundary.
|
||||||
- snps,axi_all: align address
|
- snps,axi_all: align address
|
||||||
- snps,blen: this is a vector of supported burst length.
|
- snps,blen: this is a vector of supported burst length.
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
Required properties:
|
Required properties:
|
||||||
- reg - The ID number for the phy, usually a small integer
|
- 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
|
for applicable values
|
||||||
- ti,tx-internal-delay - RGMII Transmit Clock Delay - see dt-bindings/net/ti-dp83867.h
|
- ti,tx-internal-delay - RGMII Transmit Clock Delay - see dt-bindings/net/ti-dp83867.h
|
||||||
for applicable values
|
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
|
phandle to a OPP table in their DT node. The OPP core will use this phandle to
|
||||||
find the operating points for the device.
|
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
|
should be documented as Documentation/devicetree/bindings/power/<vendor>-opp.txt
|
||||||
and should have a compatible description like: "operating-points-v2-<vendor>".
|
and should have a compatible description like: "operating-points-v2-<vendor>".
|
||||||
|
|
||||||
|
@@ -31,7 +31,7 @@ Optional properties:
|
|||||||
|
|
||||||
Example configuration:
|
Example configuration:
|
||||||
|
|
||||||
pcie: pcie@0xdffff000 {
|
pcie: pcie@dffff000 {
|
||||||
compatible = "snps,dw-pcie";
|
compatible = "snps,dw-pcie";
|
||||||
reg = <0xdffff000 0x1000>, /* Controller registers */
|
reg = <0xdffff000 0x1000>, /* Controller registers */
|
||||||
<0xd0000000 0x2000>; /* PCI config space */
|
<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>;
|
ranges = <0x82000000 0 0x00000000 0x220 0x00000000 0 0x10000000>;
|
||||||
num-lanes = <8>;
|
num-lanes = <8>;
|
||||||
port-id = <1>;
|
port-id = <1>;
|
||||||
#interrupts-cells = <1>;
|
#interrupt-cells = <1>;
|
||||||
interrupts-map-mask = <0xf800 0 0 7>;
|
interrupt-map-mask = <0xf800 0 0 7>;
|
||||||
interrupts-map = <0x0 0 0 1 &mbigen_pcie 1 10
|
interrupt-map = <0x0 0 0 1 &mbigen_pcie 1 10
|
||||||
0x0 0 0 2 &mbigen_pcie 2 11
|
0x0 0 0 2 &mbigen_pcie 2 11
|
||||||
0x0 0 0 3 &mbigen_pcie 3 12
|
0x0 0 0 3 &mbigen_pcie 3 12
|
||||||
0x0 0 0 4 &mbigen_pcie 4 13>;
|
0x0 0 0 4 &mbigen_pcie 4 13>;
|
||||||
status = "ok";
|
status = "ok";
|
||||||
};
|
};
|
||||||
|
@@ -17,7 +17,7 @@ Example:
|
|||||||
|
|
||||||
usb2_phy: usb2phy@0 {
|
usb2_phy: usb2phy@0 {
|
||||||
compatible = "st,stih416-usb-phy";
|
compatible = "st,stih416-usb-phy";
|
||||||
#phy-cell = <0>;
|
#phy-cells = <0>;
|
||||||
st,syscfg = <&syscfg_rear>;
|
st,syscfg = <&syscfg_rear>;
|
||||||
clocks = <&clk_sysin>;
|
clocks = <&clk_sysin>;
|
||||||
clock-names = "osc_phy";
|
clock-names = "osc_phy";
|
||||||
|
@@ -85,7 +85,7 @@ Example:
|
|||||||
SoC file extract:
|
SoC file extract:
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
padctl@0,7009f000 {
|
padctl@7009f000 {
|
||||||
compatible = "nvidia,tegra124-xusb-padctl";
|
compatible = "nvidia,tegra124-xusb-padctl";
|
||||||
reg = <0x0 0x7009f000 0x0 0x1000>;
|
reg = <0x0 0x7009f000 0x0 0x1000>;
|
||||||
resets = <&tegra_car 142>;
|
resets = <&tegra_car 142>;
|
||||||
@@ -97,7 +97,7 @@ SoC file extract:
|
|||||||
Board file extract:
|
Board file extract:
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
pcie-controller@0,01003000 {
|
pcie-controller@01003000 {
|
||||||
...
|
...
|
||||||
|
|
||||||
phys = <&padctl 0>;
|
phys = <&padctl 0>;
|
||||||
@@ -108,7 +108,7 @@ Board file extract:
|
|||||||
|
|
||||||
...
|
...
|
||||||
|
|
||||||
padctl: padctl@0,7009f000 {
|
padctl: padctl@7009f000 {
|
||||||
pinctrl-0 = <&padctl_default>;
|
pinctrl-0 = <&padctl_default>;
|
||||||
pinctrl-names = "default";
|
pinctrl-names = "default";
|
||||||
|
|
||||||
|
@@ -122,7 +122,7 @@ to specify in a pin configuration subnode:
|
|||||||
2: 1.5uA (PMIC_GPIO_PULL_UP_1P5)
|
2: 1.5uA (PMIC_GPIO_PULL_UP_1P5)
|
||||||
3: 31.5uA (PMIC_GPIO_PULL_UP_31P5)
|
3: 31.5uA (PMIC_GPIO_PULL_UP_31P5)
|
||||||
4: 1.5uA + 30uA boost (PMIC_GPIO_PULL_UP_1P5_30)
|
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
|
pull up is selected
|
||||||
|
|
||||||
- bias-high-impedance:
|
- bias-high-impedance:
|
||||||
|
@@ -29,7 +29,7 @@ IC (PMIC)
|
|||||||
- qcom,charger-disable:
|
- qcom,charger-disable:
|
||||||
Usage: optional
|
Usage: optional
|
||||||
Value type: <boolean>
|
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
|
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
|
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
|
* 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:
|
Required properties:
|
||||||
- compatible : Should be from the list
|
- compatible : Should be from the list
|
||||||
ti,twl6035-pmic
|
ti,twl6035-pmic
|
||||||
@@ -8,6 +15,7 @@ Required properties:
|
|||||||
ti,tps65913-pmic
|
ti,tps65913-pmic
|
||||||
ti,tps65914-pmic
|
ti,tps65914-pmic
|
||||||
ti,tps65917-pmic
|
ti,tps65917-pmic
|
||||||
|
ti,tps659038-pmic
|
||||||
and also the generic series names
|
and also the generic series names
|
||||||
ti,palmas-pmic
|
ti,palmas-pmic
|
||||||
- interrupt-parent : The parent interrupt controller which is palmas.
|
- 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
|
battery is chargeable or not. If charging battery then driver can
|
||||||
enable the charging.
|
enable the charging.
|
||||||
- ti,backup-battery-charge-high-current: Enable high current charging in
|
- ti,backup-battery-charge-high-current: Enable high current charging in
|
||||||
backup battery. Device supports the < 100mA and > 100mA charging.
|
backup battery. Device supports the < 100uA and > 100uA charging.
|
||||||
The high current will be > 100mA. Absence of this property will
|
The high current will be > 100uA. Absence of this property will
|
||||||
charge battery to lower current i.e. < 100mA.
|
charge battery to lower current i.e. < 100uA.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
palmas: tps65913@58 {
|
palmas: tps65913@58 {
|
||||||
|
@@ -42,7 +42,7 @@ Required properties:
|
|||||||
- queue-pools : child node classifying the queue ranges into pools.
|
- queue-pools : child node classifying the queue ranges into pools.
|
||||||
Queue ranges are grouped into 3 type of pools:
|
Queue ranges are grouped into 3 type of pools:
|
||||||
- qpend : pool of qpend(interruptible) queues
|
- 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
|
as free descriptor queues or the
|
||||||
transmit DMA queues.
|
transmit DMA queues.
|
||||||
- accumulator : pool of queues on PDSP accumulator channel
|
- 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
|
-- qrange : number of queues to use per queue range, specified as
|
||||||
<"base queue #" "# of queues">.
|
<"base queue #" "# of queues">.
|
||||||
-- interrupts : Optional property to specify the interrupt mapping
|
-- 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.
|
the interrupt affinity hint based on the cpu mask.
|
||||||
-- qalloc-by-id : Optional property to specify that the queues in this
|
-- qalloc-by-id : Optional property to specify that the queues in this
|
||||||
range can only be allocated by queue id.
|
range can only be allocated by queue id.
|
||||||
@@ -80,7 +80,7 @@ Required properties:
|
|||||||
latency : time to delay the interrupt, specified
|
latency : time to delay the interrupt, specified
|
||||||
in microseconds.
|
in microseconds.
|
||||||
-- multi-queue : Optional property to specify that the channel has to
|
-- 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
|
- descriptor-regions : child node describing the memory regions for keystone
|
||||||
navigator packet DMA descriptors. The memory for
|
navigator packet DMA descriptors. The memory for
|
||||||
descriptors will be allocated by the driver.
|
descriptors will be allocated by the driver.
|
||||||
|
@@ -15,7 +15,7 @@ Required properties:
|
|||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
hda@0,70030000 {
|
hda@70030000 {
|
||||||
compatible = "nvidia,tegra124-hda", "nvidia,tegra30-hda";
|
compatible = "nvidia,tegra124-hda", "nvidia,tegra30-hda";
|
||||||
reg = <0x0 0x70030000 0x0 0x10000>;
|
reg = <0x0 0x70030000 0x0 0x10000>;
|
||||||
interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
@@ -51,7 +51,7 @@ sram: sram@5c000000 {
|
|||||||
compatible = "mmio-sram";
|
compatible = "mmio-sram";
|
||||||
reg = <0x5c000000 0x40000>; /* 256 KiB SRAM at address 0x5c000000 */
|
reg = <0x5c000000 0x40000>; /* 256 KiB SRAM at address 0x5c000000 */
|
||||||
|
|
||||||
#adress-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
ranges = <0 0x5c000000 0x40000>;
|
ranges = <0 0x5c000000 0x40000>;
|
||||||
|
|
||||||
|
@@ -29,7 +29,7 @@ Required properties :
|
|||||||
|
|
||||||
Example :
|
Example :
|
||||||
|
|
||||||
soctherm@0,700e2000 {
|
soctherm@700e2000 {
|
||||||
compatible = "nvidia,tegra124-soctherm";
|
compatible = "nvidia,tegra124-soctherm";
|
||||||
reg = <0x0 0x700e2000 0x0 0x1000>;
|
reg = <0x0 0x700e2000 0x0 0x1000>;
|
||||||
interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
|
@@ -28,6 +28,7 @@ aptina Aptina Imaging
|
|||||||
arasan Arasan Chip Systems
|
arasan Arasan Chip Systems
|
||||||
arm ARM Ltd.
|
arm ARM Ltd.
|
||||||
armadeus ARMadeus Systems SARL
|
armadeus ARMadeus Systems SARL
|
||||||
|
arrow Arrow Electronics
|
||||||
artesyn Artesyn Embedded Technologies Inc.
|
artesyn Artesyn Embedded Technologies Inc.
|
||||||
asahi-kasei Asahi Kasei Corp.
|
asahi-kasei Asahi Kasei Corp.
|
||||||
aspeed ASPEED Technology Inc.
|
aspeed ASPEED Technology Inc.
|
||||||
@@ -60,6 +61,7 @@ cnxt Conexant Systems, Inc.
|
|||||||
compulab CompuLab Ltd.
|
compulab CompuLab Ltd.
|
||||||
cortina Cortina Systems, Inc.
|
cortina Cortina Systems, Inc.
|
||||||
cosmic Cosmic Circuits
|
cosmic Cosmic Circuits
|
||||||
|
creative Creative Technology Ltd
|
||||||
crystalfontz Crystalfontz America, Inc.
|
crystalfontz Crystalfontz America, Inc.
|
||||||
cubietech Cubietech, Ltd.
|
cubietech Cubietech, Ltd.
|
||||||
cypress Cypress Semiconductor Corporation
|
cypress Cypress Semiconductor Corporation
|
||||||
@@ -79,6 +81,7 @@ ebv EBV Elektronik
|
|||||||
edt Emerging Display Technologies
|
edt Emerging Display Technologies
|
||||||
eeti eGalax_eMPIA Technology Inc
|
eeti eGalax_eMPIA Technology Inc
|
||||||
elan Elan Microelectronic Corp.
|
elan Elan Microelectronic Corp.
|
||||||
|
embest Shenzhen Embest Technology Co., Ltd.
|
||||||
emmicro EM Microelectronic
|
emmicro EM Microelectronic
|
||||||
energymicro Silicon Laboratories (formerly Energy Micro AS)
|
energymicro Silicon Laboratories (formerly Energy Micro AS)
|
||||||
epcos EPCOS AG
|
epcos EPCOS AG
|
||||||
@@ -124,6 +127,7 @@ idt Integrated Device Technologies, Inc.
|
|||||||
ifi Ingenieurburo Fur Ic-Technologie (I/F/I)
|
ifi Ingenieurburo Fur Ic-Technologie (I/F/I)
|
||||||
iom Iomega Corporation
|
iom Iomega Corporation
|
||||||
img Imagination Technologies Ltd.
|
img Imagination Technologies Ltd.
|
||||||
|
inforce Inforce Computing
|
||||||
ingenic Ingenic Semiconductor
|
ingenic Ingenic Semiconductor
|
||||||
innolux Innolux Corporation
|
innolux Innolux Corporation
|
||||||
intel Intel 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))
|
if (!overlay_data || kfree_table_add(kft, overlay_data))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
of_fdt_unflatten_tree(overlay_data, &overlay);
|
of_fdt_unflatten_tree(overlay_data, NULL, &overlay);
|
||||||
if (!overlay) {
|
if (!overlay) {
|
||||||
pr_warn("%s: Unfattening overlay tree failed\n", __func__);
|
pr_warn("%s: Unfattening overlay tree failed\n", __func__);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@@ -50,7 +50,7 @@
|
|||||||
#include "io-pgtable.h"
|
#include "io-pgtable.h"
|
||||||
|
|
||||||
/* Maximum number of stream IDs assigned to a single device */
|
/* 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 */
|
/* Maximum number of context banks per SMMU */
|
||||||
#define ARM_SMMU_MAX_CBS 128
|
#define ARM_SMMU_MAX_CBS 128
|
||||||
@@ -397,6 +397,12 @@ struct arm_smmu_domain {
|
|||||||
struct iommu_domain 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 DEFINE_SPINLOCK(arm_smmu_devices_lock);
|
||||||
static LIST_HEAD(arm_smmu_devices);
|
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,
|
static int register_smmu_master(struct arm_smmu_device *smmu,
|
||||||
struct device *dev,
|
struct device *dev,
|
||||||
struct of_phandle_args *masterspec)
|
struct arm_smmu_phandle_args *masterspec)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct arm_smmu_master *master;
|
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 arm_smmu_device *smmu;
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
struct rb_node *node;
|
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;
|
int num_irqs, i, err;
|
||||||
|
|
||||||
smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL);
|
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;
|
i = 0;
|
||||||
smmu->masters = RB_ROOT;
|
smmu->masters = RB_ROOT;
|
||||||
while (!of_parse_phandle_with_args(dev->of_node, "mmu-masters",
|
|
||||||
"#stream-id-cells", i,
|
err = -ENOMEM;
|
||||||
&masterspec)) {
|
/* No need to zero the memory for masterspec */
|
||||||
err = register_smmu_master(smmu, dev, &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) {
|
if (err) {
|
||||||
dev_err(dev, "failed to add master %s\n",
|
dev_err(dev, "failed to add master %s\n",
|
||||||
masterspec.np->name);
|
masterspec->np->name);
|
||||||
|
kfree(masterspec);
|
||||||
goto out_put_masters;
|
goto out_put_masters;
|
||||||
}
|
}
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_notice(dev, "registered %d master devices\n", i);
|
dev_notice(dev, "registered %d master devices\n", i);
|
||||||
|
|
||||||
|
kfree(masterspec);
|
||||||
|
|
||||||
parse_driver_options(smmu);
|
parse_driver_options(smmu);
|
||||||
|
|
||||||
if (smmu->version == ARM_SMMU_V2 &&
|
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
|
* before booting secondary cores. This function uses arch_match_cpu_phys_id
|
||||||
* which can be overridden by architecture specific implementation.
|
* 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)
|
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");
|
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,
|
static int __of_parse_phandle_with_args(const struct device_node *np,
|
||||||
const char *list_name,
|
const char *list_name,
|
||||||
const char *cells_name,
|
const char *cells_name,
|
||||||
int cell_count, int index,
|
int cell_count, int index,
|
||||||
struct of_phandle_args *out_args)
|
struct of_phandle_args *out_args)
|
||||||
{
|
{
|
||||||
const __be32 *list, *list_end;
|
struct of_phandle_iterator it;
|
||||||
int rc = 0, size, cur_index = 0;
|
int rc, 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);
|
|
||||||
|
|
||||||
/* Loop over the phandles until all the requested entry is found */
|
/* Loop over the phandles until all the requested entry is found */
|
||||||
while (list < list_end) {
|
of_for_each_phandle(&it, rc, np, list_name, cells_name, cell_count) {
|
||||||
rc = -EINVAL;
|
|
||||||
count = 0;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If phandle is 0, then it is an empty entry with no
|
* All of the error cases bail out of the loop, so at
|
||||||
* 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
|
|
||||||
* this point, the parsing is successful. If the requested
|
* this point, the parsing is successful. If the requested
|
||||||
* index matches, then fill the out_args structure and return,
|
* index matches, then fill the out_args structure and return,
|
||||||
* or return -ENOENT for an empty entry.
|
* or return -ENOENT for an empty entry.
|
||||||
*/
|
*/
|
||||||
rc = -ENOENT;
|
rc = -ENOENT;
|
||||||
if (cur_index == index) {
|
if (cur_index == index) {
|
||||||
if (!phandle)
|
if (!it.phandle)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (out_args) {
|
if (out_args) {
|
||||||
int i;
|
int c;
|
||||||
if (WARN_ON(count > MAX_PHANDLE_ARGS))
|
|
||||||
count = MAX_PHANDLE_ARGS;
|
c = of_phandle_iterator_args(&it,
|
||||||
out_args->np = node;
|
out_args->args,
|
||||||
out_args->args_count = count;
|
MAX_PHANDLE_ARGS);
|
||||||
for (i = 0; i < count; i++)
|
out_args->np = it.node;
|
||||||
out_args->args[i] = be32_to_cpup(list++);
|
out_args->args_count = c;
|
||||||
} else {
|
} else {
|
||||||
of_node_put(node);
|
of_node_put(it.node);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Found it! return success */
|
/* Found it! return success */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
of_node_put(node);
|
|
||||||
node = NULL;
|
|
||||||
list += count;
|
|
||||||
cur_index++;
|
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:
|
* Unlock node before returning result; will be one of:
|
||||||
* -ENOENT : index is for empty phandle
|
* -ENOENT : index is for empty phandle
|
||||||
* -EINVAL : parsing error on data
|
* -EINVAL : parsing error on data
|
||||||
* [1..n] : Number of phandle (count mode; when index = -1)
|
|
||||||
*/
|
*/
|
||||||
rc = index < 0 ? cur_index : -ENOENT;
|
|
||||||
err:
|
err:
|
||||||
if (node)
|
if (it.node)
|
||||||
of_node_put(node);
|
of_node_put(it.node);
|
||||||
return rc;
|
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,
|
int of_count_phandle_with_args(const struct device_node *np, const char *list_name,
|
||||||
const char *cells_name)
|
const char *cells_name)
|
||||||
{
|
{
|
||||||
return __of_parse_phandle_with_args(np, list_name, cells_name, 0, -1,
|
struct of_phandle_iterator it;
|
||||||
NULL);
|
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);
|
EXPORT_SYMBOL(of_count_phandle_with_args);
|
||||||
|
|
||||||
|
@@ -311,6 +311,7 @@ int of_detach_node(struct device_node *np)
|
|||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(of_detach_node);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* of_node_release() - release a dynamically allocated 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:
|
case OF_RECONFIG_UPDATE_PROPERTY:
|
||||||
rce->old_prop = ce->prop;
|
rce->old_prop = ce->prop;
|
||||||
rce->prop = ce->old_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;
|
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;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static void populate_properties(const void *blob,
|
||||||
* unflatten_dt_node - Alloc and populate a device_node from the flat tree
|
int offset,
|
||||||
* @blob: The parent device tree blob
|
void **mem,
|
||||||
* @mem: Memory chunk to use for allocating device nodes and properties
|
struct device_node *np,
|
||||||
* @poffset: pointer to node in flat tree
|
const char *nodename,
|
||||||
* @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,
|
|
||||||
bool dryrun)
|
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 device_node *np;
|
||||||
struct property *pp, **prev_pp = NULL;
|
|
||||||
const char *pathp;
|
const char *pathp;
|
||||||
unsigned int l, allocl;
|
unsigned int l, allocl;
|
||||||
static int depth;
|
|
||||||
int old_depth;
|
|
||||||
int offset;
|
|
||||||
int has_name = 0;
|
|
||||||
int new_format = 0;
|
int new_format = 0;
|
||||||
|
|
||||||
pathp = fdt_get_name(blob, *poffset, &l);
|
pathp = fdt_get_name(blob, offset, &l);
|
||||||
if (!pathp)
|
if (!pathp) {
|
||||||
return mem;
|
*pnp = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
allocl = ++l;
|
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));
|
__alignof__(struct device_node));
|
||||||
if (!dryrun) {
|
if (!dryrun) {
|
||||||
char *fn;
|
char *fn;
|
||||||
@@ -246,89 +334,15 @@ static void * unflatten_dt_node(const void *blob,
|
|||||||
}
|
}
|
||||||
memcpy(fn, pathp, l);
|
memcpy(fn, pathp, l);
|
||||||
|
|
||||||
prev_pp = &np->properties;
|
|
||||||
if (dad != NULL) {
|
if (dad != NULL) {
|
||||||
np->parent = dad;
|
np->parent = dad;
|
||||||
np->sibling = dad->child;
|
np->sibling = dad->child;
|
||||||
dad->child = np;
|
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))) {
|
populate_properties(blob, offset, mem, np, pathp, dryrun);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!dryrun) {
|
if (!dryrun) {
|
||||||
*prev_pp = NULL;
|
|
||||||
np->name = of_get_property(np, "name", NULL);
|
np->name = of_get_property(np, "name", NULL);
|
||||||
np->type = of_get_property(np, "device_type", 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>";
|
np->type = "<NULL>";
|
||||||
}
|
}
|
||||||
|
|
||||||
old_depth = depth;
|
*pnp = np;
|
||||||
*poffset = fdt_next_node(blob, *poffset, &depth);
|
return fpsize;
|
||||||
if (depth < 0)
|
}
|
||||||
depth = 0;
|
|
||||||
while (*poffset > 0 && depth > old_depth)
|
|
||||||
mem = unflatten_dt_node(blob, mem, poffset, np, NULL,
|
|
||||||
fpsize, dryrun);
|
|
||||||
|
|
||||||
if (*poffset < 0 && *poffset != -FDT_ERR_NOTFOUND)
|
static void reverse_nodes(struct device_node *parent)
|
||||||
pr_err("unflatten: error %d processing FDT\n", *poffset);
|
{
|
||||||
|
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
|
* Reverse the child list. Some drivers assumes node order matches .dts
|
||||||
* node order
|
* node order
|
||||||
*/
|
*/
|
||||||
if (!dryrun && np->child) {
|
if (!dryrun)
|
||||||
struct device_node *child = np->child;
|
reverse_nodes(root);
|
||||||
np->child = NULL;
|
|
||||||
while (child) {
|
|
||||||
struct device_node *next = child->sibling;
|
|
||||||
child->sibling = np->child;
|
|
||||||
np->child = child;
|
|
||||||
child = next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nodepp)
|
return mem - base;
|
||||||
*nodepp = np;
|
|
||||||
|
|
||||||
return mem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -378,23 +450,27 @@ static void * unflatten_dt_node(const void *blob,
|
|||||||
* pointers of the nodes so the normal device-tree walking functions
|
* pointers of the nodes so the normal device-tree walking functions
|
||||||
* can be used.
|
* can be used.
|
||||||
* @blob: The blob to expand
|
* @blob: The blob to expand
|
||||||
|
* @dad: Parent device node
|
||||||
* @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
|
||||||
|
*
|
||||||
|
* Returns NULL on failure or the memory chunk containing the unflattened
|
||||||
|
* device tree on success.
|
||||||
*/
|
*/
|
||||||
static void __unflatten_device_tree(const void *blob,
|
static void *__unflatten_device_tree(const void *blob,
|
||||||
struct device_node **mynodes,
|
struct device_node *dad,
|
||||||
void * (*dt_alloc)(u64 size, u64 align))
|
struct device_node **mynodes,
|
||||||
|
void *(*dt_alloc)(u64 size, u64 align))
|
||||||
{
|
{
|
||||||
unsigned long size;
|
int size;
|
||||||
int start;
|
|
||||||
void *mem;
|
void *mem;
|
||||||
|
|
||||||
pr_debug(" -> unflatten_device_tree()\n");
|
pr_debug(" -> unflatten_device_tree()\n");
|
||||||
|
|
||||||
if (!blob) {
|
if (!blob) {
|
||||||
pr_debug("No device tree pointer\n");
|
pr_debug("No device tree pointer\n");
|
||||||
return;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
pr_debug("Unflattening device tree:\n");
|
pr_debug("Unflattening device tree:\n");
|
||||||
@@ -404,15 +480,16 @@ static void __unflatten_device_tree(const void *blob,
|
|||||||
|
|
||||||
if (fdt_check_header(blob)) {
|
if (fdt_check_header(blob)) {
|
||||||
pr_err("Invalid device tree blob header\n");
|
pr_err("Invalid device tree blob header\n");
|
||||||
return;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* First pass, scan for size */
|
/* First pass, scan for size */
|
||||||
start = 0;
|
size = unflatten_dt_nodes(blob, NULL, dad, NULL);
|
||||||
size = (unsigned long)unflatten_dt_node(blob, NULL, &start, NULL, NULL, 0, true);
|
if (size < 0)
|
||||||
size = ALIGN(size, 4);
|
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 */
|
/* Allocate memory for the expanded device tree */
|
||||||
mem = dt_alloc(size + 4, __alignof__(struct device_node));
|
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);
|
pr_debug(" unflattening %p...\n", mem);
|
||||||
|
|
||||||
/* Second pass, do actual unflattening */
|
/* Second pass, do actual unflattening */
|
||||||
start = 0;
|
unflatten_dt_nodes(blob, mem, dad, mynodes);
|
||||||
unflatten_dt_node(blob, mem, &start, NULL, mynodes, 0, false);
|
|
||||||
if (be32_to_cpup(mem + size) != 0xdeadbeef)
|
if (be32_to_cpup(mem + size) != 0xdeadbeef)
|
||||||
pr_warning("End of tree marker overwritten: %08x\n",
|
pr_warning("End of tree marker overwritten: %08x\n",
|
||||||
be32_to_cpup(mem + size));
|
be32_to_cpup(mem + size));
|
||||||
|
|
||||||
pr_debug(" <- unflatten_device_tree()\n");
|
pr_debug(" <- unflatten_device_tree()\n");
|
||||||
|
return mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *kernel_tree_alloc(u64 size, u64 align)
|
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
|
* 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
|
* unflattens the device-tree passed by the firmware, creating the
|
||||||
* tree of struct device_node. It also fills the "name" and "type"
|
* tree of struct device_node. It also fills the "name" and "type"
|
||||||
* pointers of the nodes so the normal device-tree walking functions
|
* pointers of the nodes so the normal device-tree walking functions
|
||||||
* can be used.
|
* 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,
|
void *of_fdt_unflatten_tree(const unsigned long *blob,
|
||||||
struct device_node **mynodes)
|
struct device_node *dad,
|
||||||
|
struct device_node **mynodes)
|
||||||
{
|
{
|
||||||
|
void *mem;
|
||||||
|
|
||||||
mutex_lock(&of_fdt_unflatten_mutex);
|
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);
|
mutex_unlock(&of_fdt_unflatten_mutex);
|
||||||
|
|
||||||
|
return mem;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(of_fdt_unflatten_tree);
|
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.
|
* is set in which case we override whatever was found earlier.
|
||||||
*/
|
*/
|
||||||
#ifdef CONFIG_CMDLINE
|
#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])
|
if (!((char *)data)[0])
|
||||||
#endif
|
|
||||||
strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
|
strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
|
||||||
|
#endif
|
||||||
#endif /* CONFIG_CMDLINE */
|
#endif /* CONFIG_CMDLINE */
|
||||||
|
|
||||||
pr_debug("Command line is: %s\n", (char*)data);
|
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)
|
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);
|
early_init_dt_alloc_memory_arch);
|
||||||
|
|
||||||
/* Get pointer to "/chosen" and "/aliases" nodes for use everywhere */
|
/* Get pointer to "/chosen" and "/aliases" nodes for use everywhere */
|
||||||
|
@@ -8,7 +8,6 @@
|
|||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/hashtable.h>
|
#include <linux/hashtable.h>
|
||||||
#include <linux/module.h>
|
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/of_fdt.h>
|
#include <linux/of_fdt.h>
|
||||||
#include <linux/of_irq.h>
|
#include <linux/of_irq.h>
|
||||||
@@ -921,7 +920,7 @@ static int __init unittest_data_add(void)
|
|||||||
"not running tests\n", __func__);
|
"not running tests\n", __func__);
|
||||||
return -ENOMEM;
|
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) {
|
if (!unittest_data_node) {
|
||||||
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;
|
||||||
|
@@ -75,6 +75,23 @@ struct of_phandle_args {
|
|||||||
uint32_t args[MAX_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 of_reconfig_data {
|
||||||
struct device_node *dn;
|
struct device_node *dn;
|
||||||
struct property *prop;
|
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,
|
extern int of_count_phandle_with_args(const struct device_node *np,
|
||||||
const char *list_name, const char *cells_name);
|
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 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_id(struct device_node *np, const char *stem);
|
||||||
extern int of_alias_get_highest_id(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;
|
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)
|
static inline int of_alias_get_id(struct device_node *np, const char *stem)
|
||||||
{
|
{
|
||||||
return -ENOSYS;
|
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);
|
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) \
|
#define of_property_for_each_u32(np, propname, prop, p, u) \
|
||||||
for (prop = of_find_property(np, propname, NULL), \
|
for (prop = of_find_property(np, propname, NULL), \
|
||||||
p = of_prop_next_u32(prop, NULL, &u); \
|
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);
|
unsigned long node);
|
||||||
extern int of_fdt_match(const void *blob, unsigned long node,
|
extern int of_fdt_match(const void *blob, unsigned long node,
|
||||||
const char *const *compat);
|
const char *const *compat);
|
||||||
extern void of_fdt_unflatten_tree(const unsigned long *blob,
|
extern void *of_fdt_unflatten_tree(const unsigned long *blob,
|
||||||
struct device_node **mynodes);
|
struct device_node *dad,
|
||||||
|
struct device_node **mynodes);
|
||||||
|
|
||||||
/* TBD: Temporary export of fdt globals - remove when code fully merged */
|
/* TBD: Temporary export of fdt globals - remove when code fully merged */
|
||||||
extern int __initdata dt_root_addr_cells;
|
extern int __initdata dt_root_addr_cells;
|
||||||
|
@@ -15,6 +15,7 @@
|
|||||||
#define __LINUX_OF_GRAPH_H
|
#define __LINUX_OF_GRAPH_H
|
||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
#include <linux/errno.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct of_endpoint - the OF graph endpoint data structure
|
* 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
|
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
|
# Generate an assembly file to wrap the output of the device tree compiler
|
||||||
quiet_cmd_dt_S_dtb= DTB $@
|
quiet_cmd_dt_S_dtb= DTB $@
|
||||||
cmd_dt_S_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);
|
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,
|
static void check_property_name_chars(struct check *c, struct node *dt,
|
||||||
struct node *node, struct property *prop)
|
struct node *node, struct property *prop)
|
||||||
{
|
{
|
||||||
@@ -667,6 +691,8 @@ static struct check *check_table[] = {
|
|||||||
|
|
||||||
&addr_size_cells, ®_format, &ranges_format,
|
&addr_size_cells, ®_format, &ranges_format,
|
||||||
|
|
||||||
|
&unit_address_vs_reg,
|
||||||
|
|
||||||
&avoid_default_addr_size,
|
&avoid_default_addr_size,
|
||||||
&obsolete_chosen_interrupt_controller,
|
&obsolete_chosen_interrupt_controller,
|
||||||
|
|
||||||
|
@@ -889,7 +889,7 @@ struct boot_info *dt_from_blob(const char *fname)
|
|||||||
|
|
||||||
if (version >= 3) {
|
if (version >= 3) {
|
||||||
uint32_t size_str = fdt32_to_cpu(fdt->size_dt_strings);
|
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");
|
die("String table extends past total size\n");
|
||||||
inbuf_init(&strbuf, blob + off_str, blob + off_str + size_str);
|
inbuf_init(&strbuf, blob + off_str, blob + off_str + size_str);
|
||||||
} else {
|
} else {
|
||||||
@@ -898,7 +898,7 @@ struct boot_info *dt_from_blob(const char *fname)
|
|||||||
|
|
||||||
if (version >= 17) {
|
if (version >= 17) {
|
||||||
size_dt = fdt32_to_cpu(fdt->size_dt_struct);
|
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");
|
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);
|
prop = fdt_getprop(fdt, nodeoffset, "compatible", &len);
|
||||||
if (!prop)
|
if (!prop)
|
||||||
return len;
|
return len;
|
||||||
if (fdt_stringlist_contains(prop, len, compatible))
|
|
||||||
return 0;
|
return !fdt_stringlist_contains(prop, len, compatible);
|
||||||
else
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
|
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"
|
||||||
|
Reference in New Issue
Block a user