diff --git a/.gitignore b/.gitignore
index c2ed4ec..0544d50 100644
--- a/.gitignore
+++ b/.gitignore
@@ -114,3 +114,7 @@ all.config
# Kdevelop4
*.kdev4
+
+# dtb objects
+*.dtb
+*.dtbo
diff --git b/Documentation/ABI/testing/sysfs-devices-platform-bone_capemgr b/Documentation/ABI/testing/sysfs-devices-platform-bone_capemgr
new file mode 100644
index 0000000..e2df613
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-devices-platform-bone_capemgr
@@ -0,0 +1,63 @@
+What: /sys/devices/platform/bone_capemgr/slots
+Date: May 2015
+KernelVersion: 4.0
+Contact: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
+Description:
+ READ:
+ Describe the state of all the slots of the beaglebone capemgr.
+ Each line of the output describes a slot:
+ The slot format is as following:
+ <slot-id>: [P-][F-][O-][l-][L-][D-] \
+ <overlay-id> <board-name>,<version>,
+ <manufacturer>,<part-number>
+
+ Where the flags are:
+ P: Slot has been probed
+ F: Slot has failed probing (i.e. no EEPROM detected)
+ O: Slot has been overridden by the user
+ l: Slot is current loading
+ L: Slot has completed loading and is ready
+ D: Slot has been disabled
+
+ Example:
+ 0: P---L- -1 BeagleBone RS232 CAPE,00A1,Beagleboardtoys,BB-BONE-SERL-03
+ 1: PF---- -1
+ 2: PF---- -1
+ 3: PF---- -1
+
+ WRITE:
+ Writing a string of the form <part-number>[:version] issues a request to
+ load a firmware blob containing an overlay. The name of the firmware blob
+ is <part-number>-[version|00A0].dtbo. This act is defined as a slot override.
+
+ Writing a negative slot id removes the slot if it was an overridden one, or
+ unloads a slot that was probed.
+
+What: /sys/devices/platform/bone_capemgr/baseboard/<eeprom-field>
+Date: May 2015
+KernelVersion: 4.0
+Contact: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
+Description: Contains the probed base board EEPROM field; one of:
+ board-name - board-name as stored in cape EEPROM
+ dc-supplied - whether the cape draws or supplies DC
+ eeprom-format-revision - EEPROM format rev, only 00A0 supported
+ header - header; should be 'aa 55 33 ee'
+ manufacturer - manufacturer string
+ part-number - part-number of the cape
+ serial-number - serial number of the cape
+ version - version of the cape, i.e. 00A0
+ number-of-pins - displayed but ignored
+ pin-usage - displayed but ignored
+ sys-5v - displayed but ignored
+ vdd-3v3exp - displayed but ignored
+ vdd-5v - displayed but ignored
+What: /sys/devices/platform/bone_capemgr/slot-<n>/<eeprom-field>
+Date: May 2015
+KernelVersion: 4.0
+Contact: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
+Description: Contains the probed cape's EEPROM field; the field is one of:
+ board-name - baseboard name i.e. A335BNLT
+ header - header; should be 'aa 55 33 ee'
+ revision - baseboard revision
+ serial-number - baseboard serial number
+ config-option - displayed but ignored
diff --git b/Documentation/ABI/testing/sysfs-firmware-devicetree-overlays b/Documentation/ABI/testing/sysfs-firmware-devicetree-overlays
new file mode 100644
index 0000000..88d1549
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-firmware-devicetree-overlays
@@ -0,0 +1,52 @@
+What: /sys/firmware/devicetree/overlays/
+Date: October 2015
+Contact: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
+Description:
+ This directory contains the applied device tree overlays of
+ the running system, as directories of the overlay id.
+
+What: /sys/firmware/devicetree/overlays/enable
+Date: October 2015
+Contact: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
+Description:
+ The master enable switch, by default is 1, and when
+ set to 0 it cannot be re-enabled for security reasons.
+
+ The discussion about this switch takes place in:
+ http://comments.gmane.org/gmane.linux.drivers.devicetree/101871
+
+ Kees Cook:
+ "Coming from the perspective of drawing a bright line between
+ kernel and the root user (which tends to start with disabling
+ kernel module loading), I would say that there at least needs
+ to be a high-level one-way "off" switch for the interface so
+ that systems that have this interface can choose to turn it off
+ during initial boot, etc."
+
+What: /sys/firmware/devicetree/overlays/<id>
+Date: October 2015
+Contact: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
+Description:
+ Each directory represents an applied overlay, containing
+ the following attribute files.
+
+What: /sys/firmware/devicetree/overlays/<id>/can_remove
+Date: October 2015
+Contact: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
+Description:
+ The attribute set to 1 means that the overlay can be removed,
+ while 0 means that the overlay is being overlapped therefore
+ removal is prohibited.
+
+What: /sys/firmware/devicetree/overlays/<id>/<fragment-name>/
+Date: October 2015
+Contact: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
+Description:
+ Each of these directories contain information about of the
+ particular overlay fragment.
+
+What: /sys/firmware/devicetree/overlays/<id>/<fragment-name>/target
+Date: October 2015
+Contact: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
+Description:
+ The full-path of the target of the fragment
diff --git a/Documentation/devicetree/bindings/arm/omap/omap.txt b/Documentation/devicetree/bindings/arm/omap/omap.txt
index f53e2ee..29bc4fe 100644
--- a/Documentation/devicetree/bindings/arm/omap/omap.txt
+++ b/Documentation/devicetree/bindings/arm/omap/omap.txt
@@ -24,6 +24,8 @@ Optional properties:
- ti,no-reset-on-init: When present, the module should not be reset at init
- ti,no-idle-on-init: When present, the module should not be idled at init
- ti,no-idle: When present, the module is never allowed to idle.
+- ti,deassert-hard-reset: list of hwmod and hardware reset line name pairs
+ (ascii strings) to be deasserted upon device instantiation.
Example:
diff --git b/Documentation/devicetree/bindings/cpufreq/ti-cpufreq.txt b/Documentation/devicetree/bindings/cpufreq/ti-cpufreq.txt
new file mode 100644
index 0000000..7a31864
--- /dev/null
+++ b/Documentation/devicetree/bindings/cpufreq/ti-cpufreq.txt
@@ -0,0 +1,132 @@
+TI CPUFreq and OPP bindings
+================================
+
+Certain TI SoCs, like those in the am335x, am437x, am57xx, and dra7xx
+families support different OPPs depending on the silicon variant in use.
+The ti_cpufreq driver can use revision and an efuse value from the SoC to
+provide the OPP framework with supported hardware information. This is
+used to determine which OPPs from the operating-points-v2 table get enabled
+when it is parsed by the OPP framework.
+
+Required properties:
+--------------------
+In 'cpus' nodes:
+- operating-points-v2: Phandle to the operating-points-v2 table to use.
+
+In 'operating-points-v2' table:
+- compatible: Should be
+ - 'operating-points-v2-ti' for am335x, am43xx, and dra7xx/am57xx SoCs
+- ti,syscon-efuse: Syscon phandle, offset to efuse register, efuse register
+ mask, and efuse register shift to get the relevant bits
+ that describe OPP availability.
+- ti,syscon-rev: Syscon and offset used to look up revision value on SoC.
+
+Optional properties:
+--------------------
+For each opp entry in 'operating-points-v2' table:
+- opp-supported-hw: Two bitfields indicating:
+ 1. Which revision of the SoC the OPP is supported by
+ 2. Which eFuse bits indicate this OPP is available
+
+ A bitwise AND is performed against these values and if any bit
+ matches, the OPP gets enabled. Not providing the property for an
+ entry indicates that an OPP is always supported.
+
+Example:
+--------
+
+/* From arch/arm/boot/dts/am33xx.dtsi */
+cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cpu@0 {
+ compatible = "arm,cortex-a8";
+ device_type = "cpu";
+ reg = <0>;
+
+ operating-points-v2 = <&cpu0_opp_table>;
+
+ clocks = <&dpll_mpu_ck>;
+ clock-names = "cpu";
+
+ clock-latency = <300000>; /* From omap-cpufreq driver */
+ };
+};
+
+/*
+ * cpu0 has different OPPs depending on SoC revision and some on revisions
+ * 0x2 and 0x4 have eFuse bits that indicate if they are available or not
+ */
+cpu0_opp_table: opp_table0 {
+ compatible = "operating-points-v2-ti-am3352-cpu";
+ ti,syscon-efuse = <&scm_conf 0x7fc 0x1fff 0>;
+ ti,syscon-rev = <&scm_conf 0x600>;
+
+ /*
+ * The three following nodes are marked with opp-suspend
+ * because they can not be enabled simultaneously on a
+ * single SoC.
+ */
+ opp50@300000000 {
+ opp-hz = /bits/ 64 <300000000>;
+ opp-microvolt = <950000 931000 969000>;
+ opp-supported-hw = <0x06 0x0010>;
+ opp-suspend;
+ };
+
+ opp100@275000000 {
+ opp-hz = /bits/ 64 <275000000>;
+ opp-microvolt = <1100000 1078000 1122000>;
+ opp-supported-hw = <0x01 0x00FF>;
+ opp-suspend;
+ };
+
+ opp100@300000000 {
+ opp-hz = /bits/ 64 <300000000>;
+ opp-microvolt = <1100000 1078000 1122000>;
+ opp-supported-hw = <0x06 0x0020>;
+ opp-suspend;
+ };
+
+ opp100@500000000 {
+ opp-hz = /bits/ 64 <500000000>;
+ opp-microvolt = <1100000 1078000 1122000>;
+ opp-supported-hw = <0x01 0xFFFF>;
+ };
+
+ opp100@600000000 {
+ opp-hz = /bits/ 64 <600000000>;
+ opp-microvolt = <1100000 1078000 1122000>;
+ opp-supported-hw = <0x06 0x0040>;
+ };
+
+ opp120@600000000 {
+ opp-hz = /bits/ 64 <600000000>;
+ opp-microvolt = <1200000 1176000 1224000>;
+ opp-supported-hw = <0x01 0xFFFF>;
+ };
+
+ opp120@720000000 {
+ opp-hz = /bits/ 64 <720000000>;
+ opp-microvolt = <1200000 1176000 1224000>;
+ opp-supported-hw = <0x06 0x0080>;
+ };
+
+ oppturbo@720000000 {
+ opp-hz = /bits/ 64 <720000000>;
+ opp-microvolt = <1260000 1234800 1285200>;
+ opp-supported-hw = <0x01 0xFFFF>;
+ };
+
+ oppturbo@800000000 {
+ opp-hz = /bits/ 64 <800000000>;
+ opp-microvolt = <1260000 1234800 1285200>;
+ opp-supported-hw = <0x06 0x0100>;
+ };
+
+ oppnitro@1000000000 {
+ opp-hz = /bits/ 64 <1000000000>;
+ opp-microvolt = <1325000 1298500 1351500>;
+ opp-supported-hw = <0x04 0x0200>;
+ };
+};
diff --git b/Documentation/devicetree/bindings/misc/bone_capemgr.txt b/Documentation/devicetree/bindings/misc/bone_capemgr.txt
new file mode 100644
index 0000000..7e4fbc9
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/bone_capemgr.txt
@@ -0,0 +1,111 @@
+* Beaglebone cape manager driver
+
+Required properties:
+- compatible: "ti,bone-capemgr"
+- eeprom: phandle to the EEPROM baseboard.
+ The EEPROM framework interface is use to obtain the data.
+
+Required children nodes:
+
+- baseboardmaps: Contains nodes, which each of the them defines a mapping from
+ the baseboard EEPROM board-name ID to a DT friendly compatible
+ string.
+
+ - board-name: The baseboard EEPROM board name, i.e. A335BONE for the
+ original beaglebone white.
+ - compatible-name: The DT friendly compatible string to be used for matching
+ compatible capes, i.e. "ti,beaglebone"
+
+
+ - nvmem-cells: Defines the phandles of the nvmem cells of the baseboard and the
+ slots.
+ - nvmem-cells: Defines the names of the nvmem cells. Required to have at
+ least a baseboard cell name.
+
+ - #slots: Defines how many slots are there.
+
+- Example of a beaglebone cape-manager:
+
+bone_capemgr {
+ compatible = "ti,bone-capemgr";
+ status = "okay";
+
+ nvmem-cell = <&baseboard_data
+ &cape0_data &cape1_data &cape2_data &cape3_data>;
+ nvmem-cell-names = "baseboard", "slot0", "slot1", "slot2", "slot3";
+
+ #slots = <4>;
+
+ /* map board revisions to compatible definitions */
+ baseboardmaps {
+ baseboard_beaglebone: board@0 {
+ board-name = "A335BONE";
+ compatible-name = "ti,beaglebone";
+ };
+
+ baseboard_beaglebone_black: board@1 {
+ board-name = "A335BNLT";
+ compatible-name = "ti,beaglebone-black";
+ };
+ };
+};
+
+The format of the cape to be loaded is in a standard overlay format with
+the following root properties that are interpreted by the cape manager:
+
+Required properties:
+ - compatible: Should be compatible to the baseboard according to the
+ baseboard map value, i.e. "ti,beaglebone".
+ - part-numer: Should contain the part-number as stored in the EEPROM.
+ - version: Should contain a list of all the version that are supported
+ by the single cape dtbo, i.e. "00A1".
+
+Optional properties:
+ - exclusive-use: A string list which state the resources this cape requires.
+ No processing or matching to anything regarding the internal
+ kernel state is performed; it's purpose is to guard against
+ conflicts with other capes.
+ - priority: A priority to be assigned when loading a cape. A lower value
+ has higher priority. The purpose of the priority is to control
+ which cape is loaded first in case of a conflict.
+
+- Example of a serial cape:
+
+/dts-v1/;
+/plugin/;
+/ {
+ compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+ /* identification */
+ part-number = "BB-BONE-SERL-03";
+ version = "00A1";
+
+ /* state the resources this cape uses */
+ exclusive-use =
+ /* the pin header uses */
+ "P9.21", /* uart2_txd */
+ "P9.22", /* uart2_rxd */
+ /* the hardware ip uses */
+ "uart2";
+
+ fragment@0 {
+ target = <&am33xx_pinmux>;
+ __overlay__ {
+ bb_uart2_pins: pinmux_bb_uart2_pins {
+ pinctrl-single,pins = <
+ 0x150 0x21 /* spi0_sclk.uart2_rxd | MODE1 */
+ 0x154 0x01 /* spi0_d0.uart2_txd | MODE1 */
+ >;
+ };
+ };
+ };
+
+ fragment@1 {
+ target = <&uart2>;
+ __overlay__ {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&bb_uart2_pins>;
+ };
+ };
+};
diff --git b/Documentation/devicetree/bindings/net/allwinner,sun8i-emac.txt b/Documentation/devicetree/bindings/net/allwinner,sun8i-emac.txt
new file mode 100644
index 0000000..4bf4e53
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/allwinner,sun8i-emac.txt
@@ -0,0 +1,65 @@
+* Allwinner sun8i EMAC ethernet controller
+
+Required properties:
+- compatible: "allwinner,sun8i-a83t-emac", "allwinner,sun8i-h3-emac",
+ or "allwinner,sun50i-a64-emac"
+- reg: address and length of the register sets for the device.
+- reg-names: should be "emac" and "syscon", matching the register sets
+- interrupts: interrupt for the device
+- clocks: A phandle to the reference clock for this device
+- clock-names: should be "ahb"
+- resets: A phandle to the reset control for this device
+- reset-names: should be "ahb"
+- phy-mode: See ethernet.txt
+- phy or phy-handle: See ethernet.txt
+- #address-cells: shall be 1
+- #size-cells: shall be 0
+
+"allwinner,sun8i-h3-emac" also requires:
+- clocks: an extra phandle to the reference clock for the EPHY
+- clock-names: an extra "ephy" entry matching the clocks property
+- resets: an extra phandle to the reset control for the EPHY
+- resets-names: an extra "ephy" entry matching the resets property
+
+See ethernet.txt in the same directory for generic bindings for ethernet
+controllers.
+
+The device node referenced by "phy" or "phy-handle" should be a child node
+of this node. See phy.txt for the generic PHY bindings.
+
+Optional properties:
+- phy-supply: phandle to a regulator if the PHY needs one
+- phy-io-supply: phandle to a regulator if the PHY needs a another one for I/O.
+ This is sometimes found with RGMII PHYs, which use a second
+ regulator for the lower I/O voltage.
+- allwinner,tx-delay: The setting of the TX clock delay chain
+- allwinner,rx-delay: The setting of the RX clock delay chain
+
+The TX/RX clock delay chain settings are board specific.
+
+Optional properties for "allwinner,sun8i-h3-emac":
+- allwinner,use-internal-phy: Use the H3 SoC's internal E(thernet) PHY
+- allwinner,leds-active-low: EPHY LEDs are active low
+
+When the internal PHY is requested, the implementation shall configure the
+internal PHY to use the address specified in the child PHY node.
+
+Example:
+
+emac: ethernet@01c0b000 {
+ compatible = "allwinner,sun8i-h3-emac";
+ reg = <0x01c0b000 0x104>, <0x01c00030 0x4>;
+ reg-names = "emac", "syscon";
+ interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&bus_gates 17>, <&bus_gates 128>;
+ clock-names = "ahb", "ephy";
+ resets = <&ahb_rst 17>, <&ahb_rst 66>;
+ reset-names = "ahb", "ephy";
+ phy = <&phy1>;
+ allwinner,use-internal-phy;
+ allwinner,leds-active-low;
+
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+};
diff --git a/Documentation/devicetree/bindings/opp/opp.txt b/Documentation/devicetree/bindings/opp/opp.txt
index ee91cbd..9f5ca44 100644
--- a/Documentation/devicetree/bindings/opp/opp.txt
+++ b/Documentation/devicetree/bindings/opp/opp.txt
@@ -86,8 +86,14 @@ Optional properties:
Single entry is for target voltage and three entries are for <target min max>
voltages.
- Entries for multiple regulators must be present in the same order as
- regulators are specified in device's DT node.
+ Entries for multiple regulators shall be provided in the same field separated
+ by angular brackets <>. The OPP binding doesn't provide any provisions to
+ relate the values to their power supplies or the order in which the supplies
+ need to be configured and that is left for the implementation specific
+ binding.
+
+ Entries for all regulators shall be of the same size, i.e. either all use a
+ single value or triplets.
- opp-microvolt-<name>: Named opp-microvolt property. This is exactly similar to
the above opp-microvolt property, but allows multiple voltage ranges to be
@@ -104,10 +110,13 @@ Optional properties:
Should only be set if opp-microvolt is set for the OPP.
- Entries for multiple regulators must be present in the same order as
- regulators are specified in device's DT node. If this property isn't required
- for few regulators, then this should be marked as zero for them. If it isn't
- required for any regulator, then this property need not be present.
+ Entries for multiple regulators shall be provided in the same field separated
+ by angular brackets <>. If current values aren't required for a regulator,
+ then it shall be filled with 0. If current values aren't required for any of
+ the regulators, then this field is not required. The OPP binding doesn't
+ provide any provisions to relate the values to their power supplies or the
+ order in which the supplies need to be configured and that is left for the
+ implementation specific binding.
- opp-microamp-<name>: Named opp-microamp property. Similar to
opp-microvolt-<name> property, but for microamp instead.
@@ -386,10 +395,12 @@ Example 4: Handling multiple regulators
/ {
cpus {
cpu@0 {
- compatible = "arm,cortex-a7";
+ compatible = "vendor,cpu-type";
...
- cpu-supply = <&cpu_supply0>, <&cpu_supply1>, <&cpu_supply2>;
+ vcc0-supply = <&cpu_supply0>;
+ vcc1-supply = <&cpu_supply1>;
+ vcc2-supply = <&cpu_supply2>;
operating-points-v2 = <&cpu0_opp_table>;
};
};
diff --git b/Documentation/devicetree/bindings/pinctrl/ti,iodelay-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/ti,iodelay-pinctrl.txt
new file mode 100644
index 0000000..e12f4e5
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/ti,iodelay-pinctrl.txt
@@ -0,0 +1,86 @@
+Texas Instruments I/O Delay module configuration pinctrl definition
+
+Used in conjunction with Documentation/devicetree/bindings/pinctrl/ti,omap-pinctrl.txt
+
+Required Properties:
+- compatible: Should be:
+ "ti,dra7-iodelay" - I/O delay configuration for DRA7
+- reg - must be the register address range of IODelay module
+- #address-cells = <1>;
+- #size-cells = <0>;
+
+Important note: Use of "ti,dra7-iodelay" compatible definition need to be
+carefully evaluated due to the expectation of glitch during configuration.
+
+Example:
+
+dra7_iodelay_core: padconf@4844a000 {
+ compatible = "ti,dra7-iodelay";
+ reg = <0x4844a000 0x0d1c>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+};
+
+Configuration definition follows similar model as the pinctrl-single:
+The groups of pin configuration are defined under "pinctrl-single,pins"
+
+&dra7_iodelay_core {
+ mmc2_iodelay_3v3_conf: mmc2_iodelay_3v3_conf {
+ pinctrl-single,pins = <
+ 0x18c (A_DELAY(0) | G_DELAY(120)) /* CFG_GPMC_A19_IN */
+ 0x1a4 (A_DELAY(265) | G_DELAY(360)) /* CFG_GPMC_A20_IN */
+ 0x1b0 (A_DELAY(0) | G_DELAY(120)) /* CFG_GPMC_A21_IN */
+ 0x1bc (A_DELAY(0) | G_DELAY(120)) /* CFG_GPMC_A22_IN */
+ 0x1c8 (A_DELAY(287) | G_DELAY(420)) /* CFG_GPMC_A23_IN */
+ 0x1d4 (A_DELAY(144) | G_DELAY(240)) /* CFG_GPMC_A24_IN */
+ 0x1e0 (A_DELAY(0) | G_DELAY(0)) /* CFG_GPMC_A25_IN */
+ 0x1ec (A_DELAY(120) | G_DELAY(0)) /* CFG_GPMC_A26_IN */
+ 0x1f8 (A_DELAY(120) | G_DELAY(180)) /* CFG_GPMC_A27_IN */
+ 0x360 (A_DELAY(0) | G_DELAY(0)) /* CFG_GPMC_CS1_IN */
+ >;
+ };
+};
+
+Usage in conjunction with pinctrl single:
+
+For a complete description of the pins both the regular muxing as well as the
+iodelay configuration is necessary. For example:
+
+&dra7_pmx_core {
+ mmc2_pins_default: mmc2_pins_default {
+ pinctrl-single,pins = <
+ 0x9c (PIN_INPUT_PULLUP | MANUAL_MODE | MUX_MODE1) /* gpmc_a23.mmc2_clk */
+ 0xb0 (PIN_INPUT_PULLUP | MANUAL_MODE | MUX_MODE1) /* gpmc_cs1.mmc2_cmd */
+ 0xa0 (PIN_INPUT_PULLUP | MANUAL_MODE | MUX_MODE1) /* gpmc_a24.mmc2_dat0 */
+ 0xa4 (PIN_INPUT_PULLUP | MANUAL_MODE | MUX_MODE1) /* gpmc_a25.mmc2_dat1 */
+ 0xa8 (PIN_INPUT_PULLUP | MANUAL_MODE | MUX_MODE1) /* gpmc_a26.mmc2_dat2 */
+ 0xac (PIN_INPUT_PULLUP | MANUAL_MODE | MUX_MODE1) /* gpmc_a27.mmc2_dat3 */
+ 0x8c (PIN_INPUT_PULLUP | MANUAL_MODE | MUX_MODE1) /* gpmc_a19.mmc2_dat4 */
+ 0x90 (PIN_INPUT_PULLUP | MANUAL_MODE | MUX_MODE1) /* gpmc_a20.mmc2_dat5 */
+ 0x94 (PIN_INPUT_PULLUP | MANUAL_MODE | MUX_MODE1) /* gpmc_a21.mmc2_dat6 */
+ 0x98 (PIN_INPUT_PULLUP | MANUAL_MODE | MUX_MODE1) /* gpmc_a22.mmc2_dat7 */
+ >;
+ };
+};
+
+&dra7_iodelay_core {
+ mmc2_iodelay_3v3_conf: mmc2_iodelay_3v3_conf {
+ pinctrl-single,pins = <
+ 0x18c (A_DELAY(0) | G_DELAY(120)) /* CFG_GPMC_A19_IN */
+ 0x1a4 (A_DELAY(265) | G_DELAY(360)) /* CFG_GPMC_A20_IN */
+ 0x1b0 (A_DELAY(0) | G_DELAY(120)) /* CFG_GPMC_A21_IN */
+ 0x1bc (A_DELAY(0) | G_DELAY(120)) /* CFG_GPMC_A22_IN */
+ 0x1c8 (A_DELAY(287) | G_DELAY(420)) /* CFG_GPMC_A23_IN */
+ 0x1d4 (A_DELAY(144) | G_DELAY(240)) /* CFG_GPMC_A24_IN */
+ 0x1e0 (A_DELAY(0) | G_DELAY(0)) /* CFG_GPMC_A25_IN */
+ 0x1ec (A_DELAY(120) | G_DELAY(0)) /* CFG_GPMC_A26_IN */
+ 0x1f8 (A_DELAY(120) | G_DELAY(180)) /* CFG_GPMC_A27_IN */
+ 0x360 (A_DELAY(0) | G_DELAY(0)) /* CFG_GPMC_CS1_IN */
+ >;
+ };
+};
+
+&mmc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc2_pins_default &mmc2_iodelay_3v3_conf>;
+};
diff --git b/Documentation/devicetree/bindings/power/pwrseq/pwrseq-generic.txt b/Documentation/devicetree/bindings/power/pwrseq/pwrseq-generic.txt
new file mode 100644
index 0000000..ebf0d47
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/pwrseq/pwrseq-generic.txt
@@ -0,0 +1,48 @@
+The generic power sequence library
+
+Some hard-wired devices (eg USB/MMC) need to do power sequence before
+the device can be enumerated on the bus, the typical power sequence
+like: enable USB PHY clock, toggle reset pin, etc. But current
+Linux device driver lacks of such code to do it, it may cause some
+hard-wired devices works abnormal or can't be recognized by
+controller at all. The power sequence will be done before this device
+can be found at the bus.
+
+The power sequence properties is under the device node.
+
+Optional properties:
+- clocks: the input clocks for device.
+- reset-gpios: Should specify the GPIO for reset.
+- reset-duration-us: the duration in microsecond for assert reset signal.
+
+Below is the example of USB power sequence properties on USB device
+nodes which have two level USB hubs.
+
+&usbotg1 {
+ vbus-supply = <®_usb_otg1_vbus>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb_otg1_id>;
+ status = "okay";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+ genesys: hub@1 {
+ compatible = "usb5e3,608";
+ reg = <1>;
+
+ clocks = <&clks IMX6SX_CLK_CKO>;
+ reset-gpios = <&gpio4 5 GPIO_ACTIVE_LOW>; /* hub reset pin */
+ reset-duration-us = <10>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+ asix: ethernet@1 {
+ compatible = "usbb95,1708";
+ reg = <1>;
+
+ clocks = <&clks IMX6SX_CLK_IPG>;
+ reset-gpios = <&gpio4 6 GPIO_ACTIVE_LOW>; /* ethernet_rst */
+ reset-duration-us = <15>;
+ };
+ };
+};
diff --git a/Documentation/devicetree/bindings/usb/usb-device.txt b/Documentation/devicetree/bindings/usb/usb-device.txt
index 1c35e7b..3661dd2 100644
--- a/Documentation/devicetree/bindings/usb/usb-device.txt
+++ b/Documentation/devicetree/bindings/usb/usb-device.txt
@@ -13,6 +13,10 @@ Required properties:
- reg: the port number which this device is connecting to, the range
is 1-31.
+Optional properties:
+power sequence properties, see
+Documentation/devicetree/bindings/power/pwrseq/pwrseq-generic.txt for detail
+
Example:
&usb1 {
@@ -21,8 +25,12 @@ Example:
#address-cells = <1>;
#size-cells = <0>;
- hub: genesys@1 {
+ genesys: hub@1 {
compatible = "usb5e3,608";
reg = <1>;
+
+ clocks = <&clks IMX6SX_CLK_CKO>;
+ reset-gpios = <&gpio4 5 GPIO_ACTIVE_LOW>; /* hub reset pin */
+ reset-duration-us = <10>;
};
}
diff --git b/Documentation/devicetree/configfs-overlays.txt b/Documentation/devicetree/configfs-overlays.txt
new file mode 100644
index 0000000..5fa43e0
--- /dev/null
+++ b/Documentation/devicetree/configfs-overlays.txt
@@ -0,0 +1,31 @@
+Howto use the configfs overlay interface.
+
+A device-tree configfs entry is created in /config/device-tree/overlays
+and and it is manipulated using standard file system I/O.
+Note that this is a debug level interface, for use by developers and
+not necessarily something accessed by normal users due to the
+security implications of having direct access to the kernel's device tree.
+
+* To create an overlay you mkdir the directory:
+
+ # mkdir /config/device-tree/overlays/foo
+
+* Either you echo the overlay firmware file to the path property file.
+
+ # echo foo.dtbo >/config/device-tree/overlays/foo/path
+
+* Or you cat the contents of the overlay to the dtbo file
+
+ # cat foo.dtbo >/config/device-tree/overlays/foo/dtbo
+
+The overlay file will be applied, and devices will be created/destroyed
+as required.
+
+To remove it simply rmdir the directory.
+
+ # rmdir /config/device-tree/overlays/foo
+
+The rationalle of the dual interface (firmware & direct copy) is that each is
+better suited to different use patterns. The firmware interface is what's
+intended to be used by hardware managers in the kernel, while the copy interface
+make sense for developers (since it avoids problems with namespaces).
diff --git a/Documentation/devicetree/overlay-notes.txt b/Documentation/devicetree/overlay-notes.txt
index d418a6c..3e8df30 100644
--- a/Documentation/devicetree/overlay-notes.txt
+++ b/Documentation/devicetree/overlay-notes.txt
@@ -100,6 +100,14 @@ Finally, if you need to remove all overlays in one-go, just call
of_overlay_destroy_all() which will remove every single one in the correct
order.
+If your board has multiple slots/places where a single overlay can work
+and each slot is defined by a node, you can use the
+of_overlay_create_target_index() method to select the target.
+
+For overlays on probeable busses, use the of_overlay_create_target_root() method
+in which you supply a device node as a target root, and which all target
+references in the overlay are performed relative to that node.
+
Overlay DTS Format
------------------
@@ -110,9 +118,11 @@ The DTS of an overlay should have the following format:
fragment@0 { /* first child node */
- target=<phandle>; /* phandle target of the overlay */
+ /* phandle target of the overlay */
+ target=<phandle> [, <phandle>, ...];
or
- target-path="/path"; /* target path of the overlay */
+ /* target path of the overlay */
+ target-path="/path" [ , "/path", ...];
__overlay__ {
property-a; /* add property-a to the target */
@@ -131,3 +141,11 @@ Using the non-phandle based target method allows one to use a base DT which does
not contain a __symbols__ node, i.e. it was not compiled with the -@ option.
The __symbols__ node is only required for the target=<phandle> method, since it
contains the information required to map from a phandle to a tree location.
+
+Using a target index requires the use of a selector target on the call to
+of_overlay_create_target_index(). I.e. passing an index of 0 will select the
+target in the foo node, an index of 1 the bar node, etc.
+
+Note that when using the target root create method all target references must
+lie under the target root node. I.e. the overlay is not allowed to 'break' out
+of the root.
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 65b05ba..de20a81 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -121,6 +121,7 @@ parameter is applicable:
NET Appropriate network support is enabled.
NUMA NUMA support is enabled.
NFS Appropriate NFS support is enabled.
+ OF Open Firmware support (device tree) is enabled.
OSS OSS sound support is enabled.
PV_OPS A paravirtualized kernel is enabled.
PARIDE The ParIDE (parallel port IDE) subsystem is enabled.
@@ -2862,6 +2863,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
This can be set from sysctl after boot.
See Documentation/sysctl/vm.txt for details.
+ of_overlay_disable [OF] Disable device tree overlays at boot time.
+
ohci1394_dma=early [HW] enable debugging via the ohci1394 driver.
See Documentation/debugging-via-ohci1394.txt for more
info.
diff --git b/Documentation/misc-devices/bone_capemgr.txt b/Documentation/misc-devices/bone_capemgr.txt
new file mode 100644
index 0000000..2a8c766
--- /dev/null
+++ b/Documentation/misc-devices/bone_capemgr.txt
@@ -0,0 +1,63 @@
+---------------------------
+ Beaglebone Cape-Manager
+---------------------------
+
+The beaglebone cape manager driver allows the automatic use of external
+peripheral capes to be automatically supported by Linux without any manual
+setup required by the user.
+
+Each beaglebone cape should contain an EEPROM that describes
+it in a fixed I2C address on the i2c2 bus of the baseboard.
+The format of the EEPROM is defined in the beaglebone reference
+manual at:
+http://beagleboard.org/static/beaglebone/latest/Docs/Hardware/BONE_SRM.pdf
+
+Reading the part number and revision information the manager
+requests a firmware file formatted as a device tree overlay blob.
+
+Applying the overlay the devices are instantiated and the cape is
+ready to be used.
+
+For instance if the part-number is BB-BONE-SERL-03 and the version is 00A1
+the firmware file requested will be BB-BONE-SERL-03-00A1-00A1.dtbo
+It will be located by the in-kernel firmware
+loader in the usual place, i.e. /lib/firmware/`uname -r`, /lib/firmware etc.
+
+The driver supports the following parameters (either as part of the kernel
+command line or supplied at module insertion time).
+
+disable_partno: A comma delimited list of PART-NUMBER[:REV] of
+ disabled capes.
+enable_partno: A comma delimited list of PART-NUMBER[:REV[:PRIO]] of
+ enabled capes.
+boot_scan_period: The boot scan period in ms. When the cape manager is built-in
+ the kernel image, the firmware loader cannot find the files
+ before the rootfs is mounted. This parameter controls the
+ period with which the boot state is checked in that case.
+
+There's a sysfs control interface which is defined at the ABI documentation
+area.
+
+Theory of operation:
+--------------------
+
+On driver probe the I2C EEPROM of the baseboard is read and information about
+the current baseboard is retrieved. This information includes the mapping from
+baseboard board name to DT friendly compatible string. I.e. the "A335BONE" board
+name from EEPROM is mapped to the "ti,beaglebone" compatible string which should
+be present in the dtbo to be loaded.
+
+Afterwards the EEPROMs declared in each slot are probed, and the EEPROMs found
+are decoded keeping track the cape part-number and version data.
+
+Using the part-number and version a firmware file is requested (the firmware
+file requested is <part-number>-<version>.dtbo).
+
+The dtbo is unflattend and the resulting device tree is matched against a
+compatible baseboard, and in case of multiple parallel loading capes the
+priorities defined are honored. That means that when there are multiple capes
+being loaded in parallel the ones with the lowest priority number are loaded
+first.
+
+Applying the device tree overlay makes the cape operational, as if it was part
+of the kernel's booting device tree.
diff --git a/Documentation/printk-formats.txt b/Documentation/printk-formats.txt
index 5962949..d1ba882 100644
--- a/Documentation/printk-formats.txt
+++ b/Documentation/printk-formats.txt
@@ -324,10 +324,49 @@ Network device features:
Passed by reference.
+Command from struct task_struct
+
+ %pT ls
+
+ For printing executable name excluding path from struct
+ task_struct.
+
+ Passed by reference.
+
+Device tree nodes:
+
+ %pO[fnpPcCFr]
+
+ For printing device tree nodes. The optional arguments are:
+ f device node full_name
+ n device node name
+ p device node phandle
+ P device node path spec (name + @unit)
+ F device node flags
+ c major compatible string
+ C full compatible string
+ r node reference count
+ Without any arguments prints full_name (same as %pOf)
+ The separator when using multiple arguments is '|'
+
+ Examples:
+
+ %pO /foo/bar@0 - Node full name
+ %pOf /foo/bar@0 - Same as above
+ %pOfp /foo/bar@0|10 - Node full name + phandle
+ %pOfcF /foo/bar@0|foo,device|--P- - Node full name +
+ major compatible string +
+ node flags
+ D - dynamic
+ d - detached
+ P - Populated
+ B - Populated bus
+
+ Passed by reference
+
If you add other %p extensions, please extend lib/test_printf.c with
one or more test cases, if at all feasible.
-
Thank you for your cooperation and attention.
diff --git a/MAINTAINERS b/MAINTAINERS
index 63cefa6..d49fd46 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -597,6 +597,12 @@ S: Maintained
F: Documentation/i2c/busses/i2c-ali1563
F: drivers/i2c/busses/i2c-ali1563.c
+ALLWINNER SUN8I-EMAC ETHERNET DRIVER
+M: Corentin Labbe <clabbe.montjoie@gmail.com>
+L: netdev@vger.kernel.org
+S: Maintained
+F: drivers/net/ethernet/allwinner/sun8i-emac.c
+
ALLWINNER SECURITY SYSTEM
M: Corentin Labbe <clabbe.montjoie@gmail.com>
L: linux-crypto@vger.kernel.org
@@ -2401,6 +2407,14 @@ W: https://linuxtv.org
S: Supported
F: drivers/media/platform/sti/bdisp
+BEAGLEBONE CAPEMANAGER
+M: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
+S: Maintained
+F: drivers/misc/beaglebone-capemgr.c
+F: Documentation/misc-devices/bone_capemgr.txt
+F: Documentation/devicetree/bindings/misc/bone_capemgr.txt
+F: Documentation/ABI/testing/sysfs-devices-platform-bone_capemgr
+
BEFS FILE SYSTEM
M: Luis de Bethencourt <luisbg@osg.samsung.com>
M: Salah Triki <salah.triki@gmail.com>
@@ -9635,6 +9649,15 @@ F: include/linux/pm_*
F: include/linux/powercap.h
F: drivers/powercap/
+POWER SEQUENCE LIBRARY
+M: Peter Chen <Peter.Chen@nxp.com>
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb.git
+L: linux-pm@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/power/pwrseq/
+F: drivers/power/pwrseq/
+F: include/linux/power/pwrseq.h/
+
POWER SUPPLY CLASS/SUBSYSTEM and DRIVERS
M: Sebastian Reichel <sre@kernel.org>
L: linux-pm@vger.kernel.org
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 5715844..2ee9181 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1497,8 +1497,7 @@ source kernel/Kconfig.preempt
config HZ_FIXED
int
- default 200 if ARCH_EBSA110 || ARCH_S3C24XX || \
- ARCH_S5PV210 || ARCH_EXYNOS4
+ default 200 if ARCH_EBSA110
default 128 if SOC_AT91RM9200
default 0
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 6be9ee1..6deeab7 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -13,7 +13,12 @@
# Ensure linker flags are correct
LDFLAGS :=
-LDFLAGS_vmlinux :=-p --no-undefined -X --pic-veneer
+GCCVERSIONISGTE5 := $(shell expr `$(HOSTCC) -dumpversion | cut -f1 -d.` \>= 5)
+ifeq "$(GCCVERSIONISGTE5)" "1"
+LDFLAGS_vmlinux :=-p --no-undefined -X
+else
+LDFLAGS_vmlinux :=-p --no-undefined -X --pic-veneer
+endif
ifeq ($(CONFIG_CPU_ENDIAN_BE8),y)
LDFLAGS_vmlinux += --be8
LDFLAGS_MODULE += --be8
diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile
index 50f8d1b..2c30c44 100644
--- a/arch/arm/boot/Makefile
+++ b/arch/arm/boot/Makefile
@@ -29,6 +29,10 @@ export ZRELADDR INITRD_PHYS PARAMS_PHYS
targets := Image zImage xipImage bootpImage uImage
+ifeq ($(CONFIG_OF_OVERLAY),y)
+DTC_FLAGS += -@
+endif
+
ifeq ($(CONFIG_XIP_KERNEL),y)
$(obj)/xipImage: vmlinux FORCE
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 7037201..aabd736 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -1,11 +1,17 @@
ifeq ($(CONFIG_OF),y)
+ifeq ($(CONFIG_OF_OVERLAY),y)
+DTC_FLAGS += -@
+endif
+
dtb-$(CONFIG_ARCH_ALPINE) += \
alpine-db.dtb
dtb-$(CONFIG_MACH_ARTPEC6) += \
artpec6-devboard.dtb
+
dtb-$(CONFIG_MACH_ASM9260) += \
alphascale-asm9260-devkit.dtb
+
# Keep at91 dtb files sorted alphabetically for each SoC
dtb-$(CONFIG_SOC_AT91RM9200) += \
at91rm9200ek.dtb \
@@ -155,6 +161,7 @@ dtb-$(CONFIG_ARCH_EXYNOS5) += \
exynos5420-arndale-octa.dtb \
exynos5420-peach-pit.dtb \
exynos5420-smdk5420.dtb \
+ exynos5422-artik10-eval.dtb \
exynos5422-odroidxu3.dtb \
exynos5422-odroidxu3-lite.dtb \
exynos5422-odroidxu4.dtb \
@@ -366,6 +373,7 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
imx6q-b650v3.dtb \
imx6q-b850v3.dtb \
imx6q-cm-fx6.dtb \
+ imx6q-ccimx6sbc.dtb \
imx6q-cubox-i.dtb \
imx6q-dfi-fs700-m60.dtb \
imx6q-dmo-edmqmx6.dtb \
@@ -419,6 +427,7 @@ dtb-$(CONFIG_SOC_IMX6SX) += \
imx6sx-sdb.dtb
dtb-$(CONFIG_SOC_IMX6UL) += \
imx6ul-14x14-evk.dtb \
+ imx6ul-14x14-evk-ism43362-b81-evb.dtb \
imx6ul-geam-kit.dtb \
imx6ul-pico-hobbit.dtb \
imx6ul-tx6ul-0010.dtb \
@@ -548,6 +557,28 @@ dtb-$(CONFIG_SOC_AM33XX) += \
am335x-base0033.dtb \
am335x-bone.dtb \
am335x-boneblack.dtb \
+ am335x-boneblack-uboot.dtb \
+ am335x-sancloud-bbe.dtb \
+ am335x-boneblack-wireless-roboticscape.dtb \
+ am335x-boneblack-roboticscape.dtb \
+ am335x-boneblue.dtb \
+ am335x-boneblack-wireless-emmc-overlay.dtb \
+ am335x-boneblack-wireless.dtb \
+ am335x-bonegreen-wireless.dtb \
+ am335x-boneblack-audio.dtb \
+ am335x-boneblack-bbb-exp-r.dtb \
+ am335x-boneblack-bbb-exp-c.dtb \
+ am335x-boneblack-bbbmini.dtb \
+ am335x-boneblack-wl1835mod.dtb \
+ am335x-boneblack-cape-bone-argus.dtb \
+ am335x-bone-cape-bone-argus.dtb \
+ am335x-olimex-som.dtb \
+ am335x-abbbi.dtb \
+ am335x-bonegreen-overlay.dtb \
+ am335x-boneblack-overlay.dtb \
+ am335x-boneblack-nhdmi-overlay.dtb \
+ am335x-boneblack-hdmi-overlay.dtb \
+ am335x-boneblack-emmc-overlay.dtb \
am335x-bonegreen.dtb \
am335x-chiliboard.dtb \
am335x-cm-t335.dtb \
@@ -567,6 +598,7 @@ dtb-$(CONFIG_ARCH_OMAP4) += \
omap4-panda.dtb \
omap4-panda-a4.dtb \
omap4-panda-es.dtb \
+ omap4-panda-es-b3.dtb \
omap4-sdp.dtb \
omap4-sdp-es23plus.dtb \
omap4-var-dvk-om44.dtb \
diff --git b/arch/arm/boot/dts/am335x-abbbi.dts b/arch/arm/boot/dts/am335x-abbbi.dts
new file mode 100644
index 0000000..43efead
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-abbbi.dts
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ * Copyright 2015 Konsulko Group
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include "am335x-bone-common.dtsi"
+
+
+/ {
+ model = "Arrow BeagleBone Black Industrial";
+ compatible = "arrow,am335x-abbbi", "ti,am335x-bone", "ti,am33xx";
+};
+
+&ldo3_reg {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+};
+
+&mmc1 {
+ vmmc-supply = <&vmmcsd_fixed>;
+};
+
+&mmc2 {
+ vmmc-supply = <&vmmcsd_fixed>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&emmc_pins>;
+ bus-width = <8>;
+ status = "okay";
+};
+
+&am33xx_pinmux {
+ adi_hdmi_bbbi_pins: adi_hdmi_bbbi_pins {
+ pinctrl-single,pins = <
+ AM33XX_IOPAD(0x9b0, PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* xdma_event_intr0 */
+ AM33XX_IOPAD(0x8a0, PIN_OUTPUT | MUX_MODE0) /* lcd_data0.lcd_data0 */
+ AM33XX_IOPAD(0x8a4, PIN_OUTPUT | MUX_MODE0) /* lcd_data1.lcd_data1 */
+ AM33XX_IOPAD(0x8a8, PIN_OUTPUT | MUX_MODE0) /* lcd_data2.lcd_data2 */
+ AM33XX_IOPAD(0x8ac, PIN_OUTPUT | MUX_MODE0) /* lcd_data3.lcd_data3 */
+ AM33XX_IOPAD(0x8b0, PIN_OUTPUT | MUX_MODE0) /* lcd_data4.lcd_data4 */
+ AM33XX_IOPAD(0x8b4, PIN_OUTPUT | MUX_MODE0) /* lcd_data5.lcd_data5 */
+ AM33XX_IOPAD(0x8b8, PIN_OUTPUT | MUX_MODE0) /* lcd_data6.lcd_data6 */
+ AM33XX_IOPAD(0x8bc, PIN_OUTPUT | MUX_MODE0) /* lcd_data7.lcd_data7 */
+ AM33XX_IOPAD(0x8c0, PIN_OUTPUT | MUX_MODE0) /* lcd_data8.lcd_data8 */
+ AM33XX_IOPAD(0x8c4, PIN_OUTPUT | MUX_MODE0) /* lcd_data9.lcd_data9 */
+ AM33XX_IOPAD(0x8c8, PIN_OUTPUT | MUX_MODE0) /* lcd_data10.lcd_data10 */
+ AM33XX_IOPAD(0x8cc, PIN_OUTPUT | MUX_MODE0) /* lcd_data11.lcd_data11 */
+ AM33XX_IOPAD(0x8d0, PIN_OUTPUT | MUX_MODE0) /* lcd_data12.lcd_data12 */
+ AM33XX_IOPAD(0x8d4, PIN_OUTPUT | MUX_MODE0) /* lcd_data13.lcd_data13 */
+ AM33XX_IOPAD(0x8d8, PIN_OUTPUT | MUX_MODE0) /* lcd_data14.lcd_data14 */
+ AM33XX_IOPAD(0x8dc, PIN_OUTPUT | MUX_MODE0) /* lcd_data15.lcd_data15 */
+ AM33XX_IOPAD(0x8e0, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* lcd_vsync.lcd_vsync */
+ AM33XX_IOPAD(0x8e4, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* lcd_hsync.lcd_hsync */
+ AM33XX_IOPAD(0x8e8, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* lcd_pclk.lcd_pclk */
+ AM33XX_IOPAD(0x8ec, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* lcd_ac_bias_en.lcd_ac_bias_en */
+ >;
+ };
+ adi_hdmi_bbbi_off_pins: adi_hdmi_bbbi_off_pins {
+ pinctrl-single,pins = <
+ AM33XX_IOPAD(0x9b0, PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* xdma_event_intr0 */
+ >;
+ };
+
+ mcasp0_pins: mcasp0_pins {
+ pinctrl-single,pins = <
+ 0x1ac (PIN_INPUT_PULLUP | MUX_MODE0) /* mcasp0_ahclkx.mcasp0_ahclkx */
+ 0x19c (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mcasp0_ahclkr.mcasp0_axr2 */
+ 0x194 (PIN_OUTPUT_PULLUP | MUX_MODE0) /* mcasp0_fsx.mcasp0_fsx */
+ 0x190 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mcasp0_aclkx.mcasp0_aclkx */
+ 0x06c (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a11.GPIO1_27 */
+ >;
+ };
+
+ mcasp0_pins_sleep: mcasp0_pins_sleep {
+ pinctrl-single,pins = <
+ 0x1ac (PIN_INPUT_PULLDOWN | MUX_MODE7) /* mcasp0_ahclkx.mcasp0_ahclkx */
+ 0x19c (PIN_INPUT_PULLDOWN | MUX_MODE7) /* mcasp0_ahclkr.mcasp0_axr2 */
+ 0x194 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* mcasp0_fsx.mcasp0_fsx */
+ 0x190 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* mcasp0_aclkx.mcasp0_aclkx */
+ 0x06c (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_a11.GPIO1_27 */
+ >;
+ };
+};
+
+&lcdc {
+ status = "okay";
+ port {
+ lcdc_0: endpoint@0 {
+ remote-endpoint = <&hdmi_0>;
+ };
+ };
+};
+
+&i2c0 {
+ adv7511w {
+ compatible = "adi,adv7511w";
+ reg = <0x39>;
+ pinctrl-names = "default", "off";
+ pinctrl-0 = <&adi_hdmi_bbbi_pins>;
+ pinctrl-1 = <&adi_hdmi_bbbi_off_pins>;
+
+ port {
+ hdmi_0: endpoint@0 {
+ remote-endpoint = <&lcdc_0>;
+ };
+ };
+ };
+};
+
+&mcasp0 {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&mcasp0_pins>;
+ pinctrl-1 = <&mcasp0_pins_sleep>;
+ status = "okay";
+ op-mode = <0>; /* MCASP_IIS_MODE */
+ tdm-slots = <2>;
+ serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */
+ 0 0 1 0
+ >;
+ tx-num-evt = <1>;
+ rx-num-evt = <1>;
+};
+
+/ {
+ clk_mcasp0_fixed: clk_mcasp0_fixed {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <24576000>;
+ };
+
+ clk_mcasp0: clk_mcasp0 {
+ #clock-cells = <0>;
+ compatible = "gpio-gate-clock";
+ clocks = <&clk_mcasp0_fixed>;
+ enable-gpios = <&gpio1 27 0>; /* BeagleBone Black Clk enable on GPIO1_27 */
+ };
+
+ hdmi_audio: hdmi_audio@0 {
+ compatible = "linux,hdmi-audio";
+ status = "okay";
+ };
+
+ sound {
+ compatible = "ti,beaglebone-black-audio";
+ ti,model = "TI BeagleBone Black";
+ ti,audio-codec = <&hdmi_audio>;
+ ti,mcasp-controller = <&mcasp0>;
+ ti,audio-routing =
+ "HDMI Out", "TX";
+ clocks = <&clk_mcasp0>;
+ clock-names = "mclk";
+ };
+};
+
+&rtc {
+ system-power-controller;
+};
diff --git b/arch/arm/boot/dts/am335x-bone-argus.dtsi b/arch/arm/boot/dts/am335x-bone-argus.dtsi
new file mode 100644
index 0000000..21afad3
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-bone-argus.dtsi
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <dt-bindings/board/am335x-bbw-bbb-base.h>
+
+/ {
+ ocp {
+ P8_07_pinmux {
+ /* gpio2[2] */
+ status = "disabled";
+ };
+ P8_08_pinmux {
+ /* gpio2[3] */
+ status = "disabled";
+ };
+ P8_09_pinmux {
+ /* gpio2[5] */
+ status = "disabled";
+ };
+ P8_10_pinmux {
+ /* gpio2[4] */
+ status = "disabled";
+ };
+ P9_11_pinmux {
+ /* gpio0[30] */
+ status = "disabled";
+ };
+ P9_17_pinmux {
+ /* gpio0[5] */
+ status = "disabled";
+ };
+ P9_18_pinmux {
+ /* gpio0[4] */
+ status = "disabled";
+ };
+ P9_41_pinmux {
+ /* gpio0[20] */
+ status = "disabled";
+ };
+ P9_42_pinmux {
+ /* gpio0[7] */
+ status = "disabled";
+ };
+ };
+};
+
+/ {
+ argus-ups {
+ compatible = "argus-ups";
+ status = "okay";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&argus_ups_pins>; /* Refer to previous label */
+ /* This section communicates the gpio numbers to the driver module */
+ /* Note that gpio controllers appear to be numbered from 1-n here rather than 0-(n-1)????? */
+ gpios = <&gpio0 30 0>, /* Request */
+ <&gpio0 5 0>, /* Acknowledge */
+ <&gpio0 4 0>, /* Watchdog */
+ <&gpio2 2 0>, /* LED 1 Green */
+ <&gpio2 3 0>, /* LED 1 Red */
+ <&gpio2 5 0>, /* LED 2 Green */
+ <&gpio2 4 0>, /* LED 2 Red */
+ <&gpio0 20 0>, /* General Output #1 */
+ <&gpio0 7 0>; /* General Output #2 */
+ debug = <1>;
+ shutdown = <1>;
+ };
+};
+
+&am33xx_pinmux {
+ argus_ups_pins: pinmux_argus_ups_pins { /* Set up pinmux */
+ pinctrl-single,pins = <
+ 0x070 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_wait0.gpio0_30 */
+ 0x15c (PIN_OUTPUT_PULLUP | MUX_MODE7) /* spi0_cs0.gpio0_5 */
+ 0x158 (PIN_OUTPUT_PULLUP | MUX_MODE7) /* spi0_d1.gpio0_4 */
+ 0x090 (PIN_OUTPUT_PULLUP | MUX_MODE7) /* gpmc_advn_ale.gpio_2 */
+ 0x094 (PIN_OUTPUT_PULLUP | MUX_MODE7) /* gpmc_oen_ren.gpio2_3 */
+ 0x09c (PIN_OUTPUT_PULLUP | MUX_MODE7) /* gpmc_ben0_cle.gpio2_5 */
+ 0x098 (PIN_OUTPUT_PULLUP | MUX_MODE7) /* gpmc_gpmc_wen.gpio2_4 */
+ 0x1b4 (PIN_OUTPUT_PULLUP | MUX_MODE7) /* xdma_event_intr1.gpio0_20 */
+ 0x164 (PIN_OUTPUT_PULLUP | MUX_MODE7) /* ecap0_in_pwm0_out.gpio0_7 */
+ >;
+ };
+
+ i2c2_pins: pinmux_i2c2_pins {
+ pinctrl-single,pins = <
+ BONE_P9_20 0x73 /* (SLEWCTRL_SLOW | PIN_INPUT_PULLUP | MUX_MODE3) uart1_ctsn.i2c2_sda */
+ BONE_P9_19 0x73 /* (SLEWCTRL_SLOW | PIN_INPUT_PULLUP | MUX_MODE3) uart1_rtsn.i2c2_scl */
+ >;
+ };
+};
+
+&i2c2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c2_pins>;
+
+ status = "okay";
+ clock-frequency = <100000>;
+
+ rtc@68 {
+ compatible = "maxim,ds1307";
+ reg = <0x68>;
+ };
+};
diff --git b/arch/arm/boot/dts/am335x-bone-cape-bone-argus.dts b/arch/arm/boot/dts/am335x-bone-cape-bone-argus.dts
new file mode 100644
index 0000000..82218f5
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-bone-cape-bone-argus.dts
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include "am335x-bone-common-no-capemgr.dtsi"
+
+/ {
+ model = "TI AM335x BeagleBone";
+ compatible = "ti,am335x-bone", "ti,am33xx";
+};
+
+&ldo3_reg {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+};
+
+&mmc1 {
+ vmmc-supply = <&ldo3_reg>;
+};
+
+#include "am335x-bone-argus.dtsi"
diff --git b/arch/arm/boot/dts/am335x-bone-common-no-capemgr.dtsi b/arch/arm/boot/dts/am335x-bone-common-no-capemgr.dtsi
new file mode 100644
index 0000000..56b9ccf
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-bone-common-no-capemgr.dtsi
@@ -0,0 +1,362 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <dt-bindings/mfd/tps65217.h>
+
+/ {
+ cpus {
+ cpu@0 {
+ cpu0-supply = <&dcdc2_reg>;
+ };
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0x80000000 0x10000000>; /* 256 MB */
+ };
+
+ chosen {
+ stdout-path = &uart0;
+ };
+
+ leds {
+ pinctrl-names = "default";
+ pinctrl-0 = <&user_leds_s0>;
+
+ compatible = "gpio-leds";
+
+ led2 {
+ label = "beaglebone:green:usr0";
+ gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "heartbeat";
+ default-state = "off";
+ };
+
+ led3 {
+ label = "beaglebone:green:usr1";
+ gpios = <&gpio1 22 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "mmc0";
+ default-state = "off";
+ };
+
+ led4 {
+ label = "beaglebone:green:usr2";
+ gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "cpu0";
+ default-state = "off";
+ };
+
+ led5 {
+ label = "beaglebone:green:usr3";
+ gpios = <&gpio1 24 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "mmc1";
+ default-state = "off";
+ };
+ };
+
+ vmmcsd_fixed: fixedregulator0 {
+ compatible = "regulator-fixed";
+ regulator-name = "vmmcsd_fixed";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+};
+
+&am33xx_pinmux {
+ user_leds_s0: user_leds_s0 {
+ pinctrl-single,pins = <
+ AM33XX_IOPAD(0x854, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a5.gpio1_21 */
+ AM33XX_IOPAD(0x858, PIN_OUTPUT_PULLUP | MUX_MODE7) /* gpmc_a6.gpio1_22 */
+ AM33XX_IOPAD(0x85c, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a7.gpio1_23 */
+ AM33XX_IOPAD(0x860, PIN_OUTPUT_PULLUP | MUX_MODE7) /* gpmc_a8.gpio1_24 */
+ >;
+ };
+
+ i2c0_pins: pinmux_i2c0_pins {
+ pinctrl-single,pins = <
+ AM33XX_IOPAD(0x988, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_sda.i2c0_sda */
+ AM33XX_IOPAD(0x98c, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_scl.i2c0_scl */
+ >;
+ };
+
+ i2c2_pins: pinmux_i2c2_pins {
+ pinctrl-single,pins = <
+ AM33XX_IOPAD(0x978, PIN_INPUT_PULLUP | MUX_MODE3) /* uart1_ctsn.i2c2_sda */
+ AM33XX_IOPAD(0x97c, PIN_INPUT_PULLUP | MUX_MODE3) /* uart1_rtsn.i2c2_scl */
+ >;
+ };
+
+ uart0_pins: pinmux_uart0_pins {
+ pinctrl-single,pins = <
+ AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0) /* uart0_rxd.uart0_rxd */
+ AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */
+ >;
+ };
+
+ cpsw_default: cpsw_default {
+ pinctrl-single,pins = <
+ /* Slave 1 */
+ 0x108 (PIN_INPUT | MUX_MODE0) /* mii1_col.mii1_col */
+ 0x10c (PIN_INPUT | MUX_MODE0) /* mii1_crs.mii1_crs */
+ AM33XX_IOPAD(0x910, PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxerr.mii1_rxerr */
+ AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txen.mii1_txen */
+ AM33XX_IOPAD(0x918, PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxdv.mii1_rxdv */
+ AM33XX_IOPAD(0x91c, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd3.mii1_txd3 */
+ AM33XX_IOPAD(0x920, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd2.mii1_txd2 */
+ AM33XX_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd1.mii1_txd1 */
+ AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd0.mii1_txd0 */
+ AM33XX_IOPAD(0x92c, PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_txclk.mii1_txclk */
+ AM33XX_IOPAD(0x930, PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxclk.mii1_rxclk */
+ AM33XX_IOPAD(0x934, PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxd3.mii1_rxd3 */
+ AM33XX_IOPAD(0x938, PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxd2.mii1_rxd2 */
+ AM33XX_IOPAD(0x93c, PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxd1.mii1_rxd1 */
+ AM33XX_IOPAD(0x940, PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxd0.mii1_rxd0 */
+ >;
+ };
+
+ cpsw_sleep: cpsw_sleep {
+ pinctrl-single,pins = <
+ /* Slave 1 reset value */
+ 0x108 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x10c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE7)
+ AM33XX_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7)
+ AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE7)
+ AM33XX_IOPAD(0x91c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+ AM33XX_IOPAD(0x920, PIN_INPUT_PULLDOWN | MUX_MODE7)
+ AM33XX_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE7)
+ AM33XX_IOPAD(0x928, PIN_INPUT_PULLDOWN | MUX_MODE7)
+ AM33XX_IOPAD(0x92c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+ AM33XX_IOPAD(0x930, PIN_INPUT_PULLDOWN | MUX_MODE7)
+ AM33XX_IOPAD(0x934, PIN_INPUT_PULLDOWN | MUX_MODE7)
+ AM33XX_IOPAD(0x938, PIN_INPUT_PULLDOWN | MUX_MODE7)
+ AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+ AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE7)
+ >;
+ };
+
+ davinci_mdio_default: davinci_mdio_default {
+ pinctrl-single,pins = <
+ /* MDIO */
+ AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */
+ AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_clk.mdio_clk */
+ >;
+ };
+
+ davinci_mdio_sleep: davinci_mdio_sleep {
+ pinctrl-single,pins = <
+ /* MDIO reset value */
+ AM33XX_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7)
+ AM33XX_IOPAD(0x94c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+ >;
+ };
+
+ mmc1_pins: pinmux_mmc1_pins {
+ pinctrl-single,pins = <
+ AM33XX_IOPAD(0x960, PIN_INPUT | MUX_MODE7) /* GPIO0_6 */
+ >;
+ };
+
+ emmc_pins: pinmux_emmc_pins {
+ pinctrl-single,pins = <
+ AM33XX_IOPAD(0x880, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn1.mmc1_clk */
+ AM33XX_IOPAD(0x884, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn2.mmc1_cmd */
+ AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad0.mmc1_dat0 */
+ AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad1.mmc1_dat1 */
+ AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad2.mmc1_dat2 */
+ AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad3.mmc1_dat3 */
+ AM33XX_IOPAD(0x810, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad4.mmc1_dat4 */
+ AM33XX_IOPAD(0x814, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad5.mmc1_dat5 */
+ AM33XX_IOPAD(0x818, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad6.mmc1_dat6 */
+ AM33XX_IOPAD(0x81c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad7.mmc1_dat7 */
+ >;
+ };
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pins>;
+
+ status = "okay";
+};
+
+&usb {
+ status = "okay";
+};
+
+&usb_ctrl_mod {
+ status = "okay";
+};
+
+&usb0_phy {
+ status = "okay";
+};
+
+&usb1_phy {
+ status = "okay";
+};
+
+&usb0 {
+ status = "okay";
+ dr_mode = "peripheral";
+};
+
+&usb1 {
+ status = "okay";
+ dr_mode = "host";
+};
+
+&cppi41dma {
+ status = "okay";
+};
+
+&i2c0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins>;
+
+ status = "okay";
+ clock-frequency = <400000>;
+
+ tps: tps@24 {
+ reg = <0x24>;
+ };
+
+ baseboard_eeprom: baseboard_eeprom@50 {
+ compatible = "at,24c256";
+ reg = <0x50>;
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+ baseboard_data: baseboard_data@0 {
+ reg = <0 0x100>;
+ };
+ };
+};
+
+/include/ "tps65217.dtsi"
+
+&tps {
+ /*
+ * Configure pmic to enter OFF-state instead of SLEEP-state ("RTC-only
+ * mode") at poweroff. Most BeagleBone versions do not support RTC-only
+ * mode and risk hardware damage if this mode is entered.
+ *
+ * For details, see linux-omap mailing list May 2015 thread
+ * [PATCH] ARM: dts: am335x-bone* enable pmic-shutdown-controller
+ * In particular, messages:
+ * http://www.spinics.net/lists/linux-omap/msg118585.html
+ * http://www.spinics.net/lists/linux-omap/msg118615.html
+ *
+ * You can override this later with
+ * &tps { /delete-property/ ti,pmic-shutdown-controller; }
+ * if you want to use RTC-only mode and made sure you are not affected
+ * by the hardware problems. (Tip: double-check by performing a current
+ * measurement after shutdown: it should be less than 1 mA.)
+ */
+
+ interrupts = <7>; /* NMI */
+ interrupt-parent = <&intc>;
+
+ ti,pmic-shutdown-controller;
+
+ charger {
+ interrupts = <TPS65217_IRQ_AC>, <TPS65217_IRQ_USB>;
+ interrupts-names = "AC", "USB";
+ status = "okay";
+ };
+
+ pwrbutton {
+ interrupts = <TPS65217_IRQ_PB>;
+ status = "okay";
+ };
+
+ regulators {
+ dcdc1_reg: regulator@0 {
+ regulator-name = "vdds_dpr";
+ regulator-always-on;
+ };
+
+ dcdc2_reg: regulator@1 {
+ /* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
+ regulator-name = "vdd_mpu";
+ regulator-min-microvolt = <925000>;
+ regulator-max-microvolt = <1351500>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ dcdc3_reg: regulator@2 {
+ /* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
+ regulator-name = "vdd_core";
+ regulator-min-microvolt = <925000>;
+ regulator-max-microvolt = <1150000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo1_reg: regulator@3 {
+ regulator-name = "vio,vrtc,vdds";
+ regulator-always-on;
+ };
+
+ ldo2_reg: regulator@4 {
+ regulator-name = "vdd_3v3aux";
+ regulator-always-on;
+ };
+
+ ldo3_reg: regulator@5 {
+ regulator-name = "vdd_1v8";
+ regulator-always-on;
+ };
+
+ ldo4_reg: regulator@6 {
+ regulator-name = "vdd_3v3a";
+ regulator-always-on;
+ };
+ };
+};
+
+&cpsw_emac0 {
+ phy_id = <&davinci_mdio>, <0>;
+ phy-mode = "mii";
+};
+
+&mac {
+ slaves = <1>;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&cpsw_default>;
+ pinctrl-1 = <&cpsw_sleep>;
+ status = "okay";
+};
+
+&davinci_mdio {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&davinci_mdio_default>;
+ pinctrl-1 = <&davinci_mdio_sleep>;
+ status = "okay";
+};
+
+&mmc1 {
+ status = "okay";
+ bus-width = <0x4>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc1_pins>;
+ cd-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
+};
+
+&aes {
+ status = "okay";
+};
+
+&sham {
+ status = "okay";
+};
+
+&rtc {
+ system-power-controller;
+};
diff --git b/arch/arm/boot/dts/am335x-bone-common-universal-pins.dtsi b/arch/arm/boot/dts/am335x-bone-common-universal-pins.dtsi
new file mode 100644
index 0000000..e4d4971
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-bone-common-universal-pins.dtsi
@@ -0,0 +1,941 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+&am33xx_pinmux {
+ /************************/
+ /* P8 Header */
+ /************************/
+
+ /* P8_01 GND */
+ /* P8_02 GND */
+ /* P8_03 (ZCZ ball R9 ) emmc */
+ /* P8_04 (ZCZ ball T9 ) emmc */
+ /* P8_05 (ZCZ ball R8 ) emmc */
+ /* P8_06 (ZCZ ball T8 ) emmc */
+
+ /* P8_07 (ZCZ ball R7 ) */
+ P8_07_default_pin: pinmux_P8_07_default_pin {
+ pinctrl-single,pins = <0x090 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_07_gpio_pin: pinmux_P8_07_gpio_pin {
+ pinctrl-single,pins = <0x090 0x2F>; }; /* Mode 7, RxActive */
+ P8_07_gpio_pu_pin: pinmux_P8_07_gpio_pu_pin {
+ pinctrl-single,pins = <0x090 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_07_gpio_pd_pin: pinmux_P8_07_gpio_pd_pin {
+ pinctrl-single,pins = <0x090 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_07_timer_pin: pinmux_P8_07_timer_pin {
+ pinctrl-single,pins = <0x090 0x32>; }; /* Mode 2, Pull-Up, RxActive */
+
+ /* P8_08 (ZCZ ball T7 ) */
+ P8_08_default_pin: pinmux_P8_08_default_pin {
+ pinctrl-single,pins = <0x094 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_08_gpio_pin: pinmux_P8_08_gpio_pin {
+ pinctrl-single,pins = <0x094 0x2F>; }; /* Mode 7, RxActive */
+ P8_08_gpio_pu_pin: pinmux_P8_08_gpio_pu_pin {
+ pinctrl-single,pins = <0x094 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_08_gpio_pd_pin: pinmux_P8_08_gpio_pd_pin {
+ pinctrl-single,pins = <0x094 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_08_timer_pin: pinmux_P8_08_timer_pin {
+ pinctrl-single,pins = <0x094 0x32>; }; /* Mode 2, Pull-Up, RxActive */
+
+ /* P8_09 (ZCZ ball T6 ) */
+ P8_09_default_pin: pinmux_P8_09_default_pin {
+ pinctrl-single,pins = <0x09c 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_09_gpio_pin: pinmux_P8_09_gpio_pin {
+ pinctrl-single,pins = <0x09c 0x2F>; }; /* Mode 7, RxActive */
+ P8_09_gpio_pu_pin: pinmux_P8_09_gpio_pu_pin {
+ pinctrl-single,pins = <0x09c 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_09_gpio_pd_pin: pinmux_P8_09_gpio_pd_pin {
+ pinctrl-single,pins = <0x09c 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_09_timer_pin: pinmux_P8_09_timer_pin {
+ pinctrl-single,pins = <0x09c 0x32>; }; /* Mode 2, Pull-Up, RxActive */
+
+ /* P8_10 (ZCZ ball U6 ) */
+ P8_10_default_pin: pinmux_P8_10_default_pin {
+ pinctrl-single,pins = <0x098 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_10_gpio_pin: pinmux_P8_10_gpio_pin {
+ pinctrl-single,pins = <0x098 0x2F>; }; /* Mode 7, RxActive */
+ P8_10_gpio_pu_pin: pinmux_P8_10_gpio_pu_pin {
+ pinctrl-single,pins = <0x098 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_10_gpio_pd_pin: pinmux_P8_10_gpio_pd_pin {
+ pinctrl-single,pins = <0x098 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_10_timer_pin: pinmux_P8_10_timer_pin {
+ pinctrl-single,pins = <0x098 0x32>; }; /* Mode 2, Pull-Up, RxActive */
+
+ /* P8_11 (ZCZ ball R12) */
+ P8_11_default_pin: pinmux_P8_11_default_pin {
+ pinctrl-single,pins = <0x034 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_11_gpio_pin: pinmux_P8_11_gpio_pin {
+ pinctrl-single,pins = <0x034 0x2F>; }; /* Mode 7, RxActive */
+ P8_11_gpio_pu_pin: pinmux_P8_11_gpio_pu_pin {
+ pinctrl-single,pins = <0x034 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_11_gpio_pd_pin: pinmux_P8_11_gpio_pd_pin {
+ pinctrl-single,pins = <0x034 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_11_pruout_pin: pinmux_P8_11_pruout_pin {
+ pinctrl-single,pins = <0x034 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+ P8_11_qep_pin: pinmux_P8_11_qep_pin {
+ pinctrl-single,pins = <0x034 0x24>; }; /* Mode 4, Pull-Down, RxActive */
+
+ /* P8_12 (ZCZ ball T12) */
+ P8_12_default_pin: pinmux_P8_12_default_pin {
+ pinctrl-single,pins = <0x030 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_12_gpio_pin: pinmux_P8_12_gpio_pin {
+ pinctrl-single,pins = <0x030 0x2F>; }; /* Mode 7, RxActive */
+ P8_12_gpio_pu_pin: pinmux_P8_12_gpio_pu_pin {
+ pinctrl-single,pins = <0x030 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_12_gpio_pd_pin: pinmux_P8_12_gpio_pd_pin {
+ pinctrl-single,pins = <0x030 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_12_pruout_pin: pinmux_P8_12_pruout_pin {
+ pinctrl-single,pins = <0x030 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+ P8_12_qep_pin: pinmux_P8_12_qep_pin {
+ pinctrl-single,pins = <0x030 0x24>; }; /* Mode 4, Pull-Down, RxActive */
+
+ /* P8_13 (ZCZ ball T10) */
+ P8_13_default_pin: pinmux_P8_13_default_pin {
+ pinctrl-single,pins = <0x024 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_13_gpio_pin: pinmux_P8_13_gpio_pin {
+ pinctrl-single,pins = <0x024 0x2F>; }; /* Mode 7, RxActive */
+ P8_13_gpio_pu_pin: pinmux_P8_13_gpio_pu_pin {
+ pinctrl-single,pins = <0x024 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_13_gpio_pd_pin: pinmux_P8_13_gpio_pd_pin {
+ pinctrl-single,pins = <0x024 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_13_pwm_pin: pinmux_P8_13_pwm_pin {
+ pinctrl-single,pins = <0x024 0x24>; }; /* Mode 4, Pull-Down, RxActive */
+
+ /* P8_14 (ZCZ ball T11) */
+ P8_14_default_pin: pinmux_P8_14_default_pin {
+ pinctrl-single,pins = <0x028 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_14_gpio_pin: pinmux_P8_14_gpio_pin {
+ pinctrl-single,pins = <0x028 0x2F>; }; /* Mode 7, RxActive */
+ P8_14_gpio_pu_pin: pinmux_P8_14_gpio_pu_pin {
+ pinctrl-single,pins = <0x028 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_14_gpio_pd_pin: pinmux_P8_14_gpio_pd_pin {
+ pinctrl-single,pins = <0x028 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_14_pwm_pin: pinmux_P8_14_pwm_pin {
+ pinctrl-single,pins = <0x028 0x24>; }; /* Mode 4, Pull-Down, RxActive */
+
+ /* P8_15 (ZCZ ball U13) */
+ P8_15_default_pin: pinmux_P8_15_default_pin {
+ pinctrl-single,pins = <0x03c 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_15_gpio_pin: pinmux_P8_15_gpio_pin {
+ pinctrl-single,pins = <0x03c 0x2F>; }; /* Mode 7, RxActive */
+ P8_15_gpio_pu_pin: pinmux_P8_15_gpio_pu_pin {
+ pinctrl-single,pins = <0x03c 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_15_gpio_pd_pin: pinmux_P8_15_gpio_pd_pin {
+ pinctrl-single,pins = <0x03c 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_15_pruin_pin: pinmux_P8_15_pruin_pin {
+ pinctrl-single,pins = <0x03c 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+ P8_15_qep_pin: pinmux_P8_15_qep_pin {
+ pinctrl-single,pins = <0x03c 0x24>; }; /* Mode 4, Pull-Down, RxActive */
+
+ /* P8_16 (ZCZ ball V13) */
+ P8_16_default_pin: pinmux_P8_16_default_pin {
+ pinctrl-single,pins = <0x038 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_16_gpio_pin: pinmux_P8_16_gpio_pin {
+ pinctrl-single,pins = <0x038 0x2F>; }; /* Mode 7, RxActive */
+ P8_16_gpio_pu_pin: pinmux_P8_16_gpio_pu_pin {
+ pinctrl-single,pins = <0x038 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_16_gpio_pd_pin: pinmux_P8_16_gpio_pd_pin {
+ pinctrl-single,pins = <0x038 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_16_pruin_pin: pinmux_P8_16_pruin_pin {
+ pinctrl-single,pins = <0x038 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+ P8_16_qep_pin: pinmux_P8_16_qep_pin {
+ pinctrl-single,pins = <0x038 0x24>; }; /* Mode 4, Pull-Down, RxActive */
+
+ /* P8_17 (ZCZ ball U12) */
+ P8_17_default_pin: pinmux_P8_17_default_pin {
+ pinctrl-single,pins = <0x02c 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_17_gpio_pin: pinmux_P8_17_gpio_pin {
+ pinctrl-single,pins = <0x02c 0x2F>; }; /* Mode 7, RxActive */
+ P8_17_gpio_pu_pin: pinmux_P8_17_gpio_pu_pin {
+ pinctrl-single,pins = <0x02c 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_17_gpio_pd_pin: pinmux_P8_17_gpio_pd_pin {
+ pinctrl-single,pins = <0x02c 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_17_pwm_pin: pinmux_P8_17_pwm_pin {
+ pinctrl-single,pins = <0x02c 0x24>; }; /* Mode 4, Pull-Down, RxActive */
+
+ /* P8_18 (ZCZ ball V12) */
+ P8_18_default_pin: pinmux_P8_18_default_pin {
+ pinctrl-single,pins = <0x08c 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_18_gpio_pin: pinmux_P8_18_gpio_pin {
+ pinctrl-single,pins = <0x08c 0x2F>; }; /* Mode 7, RxActive */
+ P8_18_gpio_pu_pin: pinmux_P8_18_gpio_pu_pin {
+ pinctrl-single,pins = <0x08c 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_18_gpio_pd_pin: pinmux_P8_18_gpio_pd_pin {
+ pinctrl-single,pins = <0x08c 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+
+ /* P8_19 (ZCZ ball U10) */
+ P8_19_default_pin: pinmux_P8_19_default_pin {
+ pinctrl-single,pins = <0x020 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_19_gpio_pin: pinmux_P8_19_gpio_pin {
+ pinctrl-single,pins = <0x020 0x2F>; }; /* Mode 7, RxActive */
+ P8_19_gpio_pu_pin: pinmux_P8_19_gpio_pu_pin {
+ pinctrl-single,pins = <0x020 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_19_gpio_pd_pin: pinmux_P8_19_gpio_pd_pin {
+ pinctrl-single,pins = <0x020 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_19_pwm_pin: pinmux_P8_19_pwm_pin {
+ pinctrl-single,pins = <0x020 0x24>; }; /* Mode 4, Pull-Down, RxActive */
+
+ /* P8_20 (ZCZ ball V9 ) emmc */
+ /* P8_21 (ZCZ ball U9 ) emmc */
+ /* P8_22 (ZCZ ball V8 ) emmc */
+ /* P8_23 (ZCZ ball U8 ) emmc */
+ /* P8_24 (ZCZ ball V7 ) emmc */
+ /* P8_25 (ZCZ ball U7 ) emmc */
+
+ /* P8_26 (ZCZ ball V6 ) */
+ P8_26_default_pin: pinmux_P8_26_default_pin {
+ pinctrl-single,pins = <0x07c 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_26_gpio_pin: pinmux_P8_26_gpio_pin {
+ pinctrl-single,pins = <0x07c 0x2F>; }; /* Mode 7, RxActive */
+ P8_26_gpio_pu_pin: pinmux_P8_26_gpio_pu_pin {
+ pinctrl-single,pins = <0x07c 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_26_gpio_pd_pin: pinmux_P8_26_gpio_pd_pin {
+ pinctrl-single,pins = <0x07c 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+
+ /* P8_27 (ZCZ ball U5 ) hdmi */
+ P8_27_default_pin: pinmux_P8_27_default_pin {
+ pinctrl-single,pins = <0x0e0 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_27_gpio_pin: pinmux_P8_27_gpio_pin {
+ pinctrl-single,pins = <0x0e0 0x2F>; }; /* Mode 7, RxActive */
+ P8_27_gpio_pu_pin: pinmux_P8_27_gpio_pu_pin {
+ pinctrl-single,pins = <0x0e0 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_27_gpio_pd_pin: pinmux_P8_27_gpio_pd_pin {
+ pinctrl-single,pins = <0x0e0 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_27_pruout_pin: pinmux_P8_27_pruout_pin {
+ pinctrl-single,pins = <0x0e0 0x05>; }; /* Mode 5, Pull-Down*/
+ P8_27_pruin_pin: pinmux_P8_27_pruin_pin {
+ pinctrl-single,pins = <0x0e0 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+ P8_27_hdmi_pin: pinmux_P8_27_hdmi_pin {
+ pinctrl-single,pins = <0x0e0 0x00>; }; /* lcd_vsync.lcd_vsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+
+ /* P8_28 (ZCZ ball V5 ) hdmi */
+ P8_28_default_pin: pinmux_P8_28_default_pin {
+ pinctrl-single,pins = <0x0e8 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_28_gpio_pin: pinmux_P8_28_gpio_pin {
+ pinctrl-single,pins = <0x0e8 0x2F>; }; /* Mode 7, RxActive */
+ P8_28_gpio_pu_pin: pinmux_P8_28_gpio_pu_pin {
+ pinctrl-single,pins = <0x0e8 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_28_gpio_pd_pin: pinmux_P8_28_gpio_pd_pin {
+ pinctrl-single,pins = <0x0e8 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_28_pruout_pin: pinmux_P8_28_pruout_pin {
+ pinctrl-single,pins = <0x0e8 0x05>; }; /* Mode 5, Pull-Down */
+ P8_28_pruin_pin: pinmux_P8_28_pruin_pin {
+ pinctrl-single,pins = <0x0e8 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+ P8_28_hdmi_pin: pinmux_P8_28_hdmi_pin {
+ pinctrl-single,pins = <0x0e8 0x00>; }; /* lcd_pclk.lcd_pclk, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+
+ /* P8_29 (ZCZ ball R5 ) hdmi */
+ P8_29_default_pin: pinmux_P8_29_default_pin {
+ pinctrl-single,pins = <0x0e4 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_29_gpio_pin: pinmux_P8_29_gpio_pin {
+ pinctrl-single,pins = <0x0e4 0x2F>; }; /* Mode 7, RxActive */
+ P8_29_gpio_pu_pin: pinmux_P8_29_gpio_pu_pin {
+ pinctrl-single,pins = <0x0e4 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_29_gpio_pd_pin: pinmux_P8_29_gpio_pd_pin {
+ pinctrl-single,pins = <0x0e4 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_29_pruout_pin: pinmux_P8_29_pruout_pin {
+ pinctrl-single,pins = <0x0e4 0x05>; }; /* Mode 5, Pull-Down*/
+ P8_29_pruin_pin: pinmux_P8_29_pruin_pin {
+ pinctrl-single,pins = <0x0e4 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+ P8_29_hdmi_pin: pinmux_P8_29_hdmi_pin {
+ pinctrl-single,pins = <0x0e4 0x00>; }; /* lcd_hsync.lcd_hsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+
+ /* P8_30 (ZCZ ball R6 ) hdmi */
+ P8_30_default_pin: pinmux_P8_30_default_pin {
+ pinctrl-single,pins = <0x0ec 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_30_gpio_pin: pinmux_P8_30_gpio_pin {
+ pinctrl-single,pins = <0x0ec 0x2F>; }; /* Mode 7, RxActive */
+ P8_30_gpio_pu_pin: pinmux_P8_30_gpio_pu_pin {
+ pinctrl-single,pins = <0x0ec 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_30_gpio_pd_pin: pinmux_P8_30_gpio_pd_pin {
+ pinctrl-single,pins = <0x0ec 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_30_pruout_pin: pinmux_P8_30_pruout_pin {
+ pinctrl-single,pins = <0x0ec 0x05>; }; /* Mode 5, Pull-Down*/
+ P8_30_pruin_pin: pinmux_P8_30_pruin_pin {
+ pinctrl-single,pins = <0x0ec 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+ P8_30_hdmi_pin: pinmux_P8_30_hdmi_pin {
+ pinctrl-single,pins = <0x0ec 0x00>; }; /* lcd_ac_bias_en.lcd_ac_bias_en, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+
+ /* P8_31 (ZCZ ball V4 ) hdmi */
+ P8_31_default_pin: pinmux_P8_31_default_pin {
+ pinctrl-single,pins = <0x0d8 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_31_gpio_pin: pinmux_P8_31_gpio_pin {
+ pinctrl-single,pins = <0x0d8 0x2F>; }; /* Mode 7, RxActive */
+ P8_31_gpio_pu_pin: pinmux_P8_31_gpio_pu_pin {
+ pinctrl-single,pins = <0x0d8 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_31_gpio_pd_pin: pinmux_P8_31_gpio_pd_pin {
+ pinctrl-single,pins = <0x0d8 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_31_uart_pin: pinmux_P8_31_uart_pin {
+ pinctrl-single,pins = <0x0d8 0x24>; }; /* Mode 4, Pull-Down, RxActive */
+ P8_31_hdmi_pin: pinmux_P8_31_hdmi_pin {
+ pinctrl-single,pins = <0x0d8 0x08>; }; /* lcd_data14.lcd_data14, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+
+ /* P8_32 (ZCZ ball T5 ) hdmi */
+ P8_32_default_pin: pinmux_P8_32_default_pin {
+ pinctrl-single,pins = <0x0dc 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_32_gpio_pin: pinmux_P8_32_gpio_pin {
+ pinctrl-single,pins = <0x0dc 0x2F>; }; /* Mode 7, RxActive */
+ P8_32_gpio_pu_pin: pinmux_P8_32_gpio_pu_pin {
+ pinctrl-single,pins = <0x0dc 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_32_gpio_pd_pin: pinmux_P8_32_gpio_pd_pin {
+ pinctrl-single,pins = <0x0dc 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_32_uart_pin: pinmux_P8_32_uart_pin {
+ pinctrl-single,pins = <0x0dc 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+ P8_32_hdmi_pin: pinmux_P8_32_hdmi_pin {
+ pinctrl-single,pins = <0x0dc 0x08>; }; /* lcd_data15.lcd_data15, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+
+ /* P8_33 (ZCZ ball V3 ) hdmi */
+ P8_33_default_pin: pinmux_P8_33_default_pin {
+ pinctrl-single,pins = <0x0d4 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_33_gpio_pin: pinmux_P8_33_gpio_pin {
+ pinctrl-single,pins = <0x0d4 0x2F>; }; /* Mode 7, RxActive */
+ P8_33_gpio_pu_pin: pinmux_P8_33_gpio_pu_pin {
+ pinctrl-single,pins = <0x0d4 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_33_gpio_pd_pin: pinmux_P8_33_gpio_pd_pin {
+ pinctrl-single,pins = <0x0d4 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_33_hdmi_pin: pinmux_P8_33_hdmi_pin {
+ pinctrl-single,pins = <0x0d4 0x08>; }; /* lcd_data13.lcd_data13, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ P8_33_qep_pin: pinmux_P8_33_qep_pin {
+ pinctrl-single,pins = <0x0d4 0x22>; }; /* Mode 2, Pull-Down, RxActive */
+
+ /* P8_34 (ZCZ ball U4 ) hdmi */
+ P8_34_default_pin: pinmux_P8_34_default_pin {
+ pinctrl-single,pins = <0x0cc 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_34_gpio_pin: pinmux_P8_34_gpio_pin {
+ pinctrl-single,pins = <0x0cc 0x2F>; }; /* Mode 7, RxActive */
+ P8_34_gpio_pu_pin: pinmux_P8_34_gpio_pu_pin {
+ pinctrl-single,pins = <0x0cc 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_34_gpio_pd_pin: pinmux_P8_34_gpio_pd_pin {
+ pinctrl-single,pins = <0x0cc 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_34_pwm_pin: pinmux_P8_34_pwm_pin {
+ pinctrl-single,pins = <0x0cc 0x22>; }; /* Mode 2, Pull-Down, RxActive */
+ P8_34_hdmi_pin: pinmux_P8_34_hdmi_pin {
+ pinctrl-single,pins = <0x0cc 0x08>; }; /* lcd_data11.lcd_data11, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+
+ /* P8_35 (ZCZ ball V2 ) hdmi */
+ P8_35_default_pin: pinmux_P8_35_default_pin {
+ pinctrl-single,pins = <0x0d0 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_35_gpio_pin: pinmux_P8_35_gpio_pin {
+ pinctrl-single,pins = <0x0d0 0x2F>; }; /* Mode 7, RxActive */
+ P8_35_gpio_pu_pin: pinmux_P8_35_gpio_pu_pin {
+ pinctrl-single,pins = <0x0d0 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_35_gpio_pd_pin: pinmux_P8_35_gpio_pd_pin {
+ pinctrl-single,pins = <0x0d0 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_35_hdmi_pin: pinmux_P8_35_hdmi_pin {
+ pinctrl-single,pins = <0x0d0 0x08>; }; /* lcd_data12.lcd_data12, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ P8_35_qep_pin: pinmux_P8_35_qep_pin {
+ pinctrl-single,pins = <0x0d0 0x22>; }; /* Mode 2, Pull-Down, RxActive */
+
+ /* P8_36 (ZCZ ball U3 ) hdmi */
+ P8_36_default_pin: pinmux_P8_36_default_pin {
+ pinctrl-single,pins = <0x0c8 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_36_gpio_pin: pinmux_P8_36_gpio_pin {
+ pinctrl-single,pins = <0x0c8 0x2F>; }; /* Mode 7, RxActive */
+ P8_36_gpio_pu_pin: pinmux_P8_36_gpio_pu_pin {
+ pinctrl-single,pins = <0x0c8 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_36_gpio_pd_pin: pinmux_P8_36_gpio_pd_pin {
+ pinctrl-single,pins = <0x0c8 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_36_pwm_pin: pinmux_P8_36_pwm_pin {
+ pinctrl-single,pins = <0x0c8 0x22>; }; /* Mode 2, Pull-Down, RxActive */
+ P8_36_hdmi_pin: pinmux_P8_36_hdmi_pin {
+ pinctrl-single,pins = <0x0c8 0x08>; }; /* lcd_data10.lcd_data10, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+
+ /* P8_37 (ZCZ ball U1 ) hdmi */
+ P8_37_default_pin: pinmux_P8_37_default_pin {
+ pinctrl-single,pins = <0x0c0 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_37_gpio_pin: pinmux_P8_37_gpio_pin {
+ pinctrl-single,pins = <0x0c0 0x2F>; }; /* Mode 7, RxActive */
+ P8_37_gpio_pu_pin: pinmux_P8_37_gpio_pu_pin {
+ pinctrl-single,pins = <0x0c0 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_37_gpio_pd_pin: pinmux_P8_37_gpio_pd_pin {
+ pinctrl-single,pins = <0x0c0 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_37_uart_pin: pinmux_P8_37_uart_pin {
+ pinctrl-single,pins = <0x0c0 0x04>; }; /* Mode 4, Pull-Down*/
+ P8_37_pwm_pin: pinmux_P8_37_pwm_pin {
+ pinctrl-single,pins = <0x0c0 0x02>; }; /* Mode 2, Pull-Down*/
+ P8_37_hdmi_pin: pinmux_P8_37_hdmi_pin {
+ pinctrl-single,pins = <0x0c0 0x08>; }; /* lcd_data8.lcd_data8, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+
+
+ /* P8_38 (ZCZ ball U2 ) hdmi */
+ P8_38_default_pin: pinmux_P8_38_default_pin {
+ pinctrl-single,pins = <0x0c4 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_38_gpio_pin: pinmux_P8_38_gpio_pin {
+ pinctrl-single,pins = <0x0c4 0x2F>; }; /* Mode 7, RxActive */
+ P8_38_gpio_pu_pin: pinmux_P8_38_gpio_pu_pin {
+ pinctrl-single,pins = <0x0c4 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_38_gpio_pd_pin: pinmux_P8_38_gpio_pd_pin {
+ pinctrl-single,pins = <0x0c4 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_38_uart_pin: pinmux_P8_38_uart_pin {
+ pinctrl-single,pins = <0x0c4 0x24>; }; /* Mode 4, Pull-Down, RxActive */
+ P8_38_pwm_pin: pinmux_P8_38_pwm_pin {
+ pinctrl-single,pins = <0x0c4 0x22>; }; /* Mode 2, Pull-Down, RxActive */
+ P8_38_hdmi_pin: pinmux_P8_38_hdmi_pin {
+ pinctrl-single,pins = <0x0c4 0x08>; }; /* lcd_data9.lcd_data9, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+
+
+ /* P8_39 (ZCZ ball T3 ) hdmi */
+ P8_39_default_pin: pinmux_P8_39_default_pin {
+ pinctrl-single,pins = <0x0b8 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_39_gpio_pin: pinmux_P8_39_gpio_pin {
+ pinctrl-single,pins = <0x0b8 0x2F>; }; /* Mode 7, RxActive */
+ P8_39_gpio_pu_pin: pinmux_P8_39_gpio_pu_pin {
+ pinctrl-single,pins = <0x0b8 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_39_gpio_pd_pin: pinmux_P8_39_gpio_pd_pin {
+ pinctrl-single,pins = <0x0b8 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_39_pruout_pin: pinmux_P8_39_pruout_pin {
+ pinctrl-single,pins = <0x0b8 0x05>; }; /* Mode 5, Pull-Down*/
+ P8_39_pruin_pin: pinmux_P8_39_pruin_pin {
+ pinctrl-single,pins = <0x0b8 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+ P8_39_hdmi_pin: pinmux_P8_39_hdmi_pin {
+ pinctrl-single,pins = <0x0b8 0x08>; }; /* lcd_data6.lcd_data6, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+
+ /* P8_40 (ZCZ ball T4 ) hdmi */
+ P8_40_default_pin: pinmux_P8_40_default_pin {
+ pinctrl-single,pins = <0x0bc 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_40_gpio_pin: pinmux_P8_40_gpio_pin {
+ pinctrl-single,pins = <0x0bc 0x2F>; }; /* Mode 7, RxActive */
+ P8_40_gpio_pu_pin: pinmux_P8_40_gpio_pu_pin {
+ pinctrl-single,pins = <0x0bc 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_40_gpio_pd_pin: pinmux_P8_40_gpio_pd_pin {
+ pinctrl-single,pins = <0x0bc 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_40_pruout_pin: pinmux_P8_40_pruout_pin {
+ pinctrl-single,pins = <0x0bc 0x05>; }; /* Mode 5, Pull-Down*/
+ P8_40_pruin_pin: pinmux_P8_40_pruin_pin {
+ pinctrl-single,pins = <0x0bc 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+ P8_40_hdmi_pin: pinmux_P8_40_hdmi_pin {
+ pinctrl-single,pins = <0x0bc 0x08>; }; /* lcd_data7.lcd_data7, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+
+ /* P8_41 (ZCZ ball T1 ) hdmi */
+ P8_41_default_pin: pinmux_P8_41_default_pin {
+ pinctrl-single,pins = <0x0b0 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_41_gpio_pin: pinmux_P8_41_gpio_pin {
+ pinctrl-single,pins = <0x0b0 0x2F>; }; /* Mode 7, RxActive */
+ P8_41_gpio_pu_pin: pinmux_P8_41_gpio_pu_pin {
+ pinctrl-single,pins = <0x0b0 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_41_gpio_pd_pin: pinmux_P8_41_gpio_pd_pin {
+ pinctrl-single,pins = <0x0b0 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_41_pruout_pin: pinmux_P8_41_pruout_pin {
+ pinctrl-single,pins = <0x0b0 0x05>; }; /* Mode 5, Pull-Down*/
+ P8_41_pruin_pin: pinmux_P8_41_pruin_pin {
+ pinctrl-single,pins = <0x0b0 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+ P8_41_hdmi_pin: pinmux_P8_41_hdmi_pin {
+ pinctrl-single,pins = <0x0b0 0x08>; }; /* lcd_data4.lcd_data4, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+
+ /* P8_42 (ZCZ ball T2 ) hdmi */
+ P8_42_default_pin: pinmux_P8_42_default_pin {
+ pinctrl-single,pins = <0x0b4 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_42_gpio_pin: pinmux_P8_42_gpio_pin {
+ pinctrl-single,pins = <0x0b4 0x2F>; }; /* Mode 7, RxActive */
+ P8_42_gpio_pu_pin: pinmux_P8_42_gpio_pu_pin {
+ pinctrl-single,pins = <0x0b4 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_42_gpio_pd_pin: pinmux_P8_42_gpio_pd_pin {
+ pinctrl-single,pins = <0x0b4 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_42_pruout_pin: pinmux_P8_42_pruout_pin {
+ pinctrl-single,pins = <0x0b4 0x05>; }; /* Mode 5, Pull-Down*/
+ P8_42_pruin_pin: pinmux_P8_42_pruin_pin {
+ pinctrl-single,pins = <0x0b4 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+ P8_42_hdmi_pin: pinmux_P8_42_hdmi_pin {
+ pinctrl-single,pins = <0x0b4 0x08>; }; /* lcd_data5.lcd_data5, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+
+ /* P8_43 (ZCZ ball R3 ) hdmi */
+ P8_43_default_pin: pinmux_P8_43_default_pin {
+ pinctrl-single,pins = <0x0a8 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_43_gpio_pin: pinmux_P8_43_gpio_pin {
+ pinctrl-single,pins = <0x0a8 0x2F>; }; /* Mode 7, RxActive */
+ P8_43_gpio_pu_pin: pinmux_P8_43_gpio_pu_pin {
+ pinctrl-single,pins = <0x0a8 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_43_gpio_pd_pin: pinmux_P8_43_gpio_pd_pin {
+ pinctrl-single,pins = <0x0a8 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_43_pruout_pin: pinmux_P8_43_pruout_pin {
+ pinctrl-single,pins = <0x0a8 0x05>; }; /* Mode 5, Pull-Down*/
+ P8_43_pruin_pin: pinmux_P8_43_pruin_pin {
+ pinctrl-single,pins = <0x0a8 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+ P8_43_pwm_pin: pinmux_P8_43_pwm_pin {
+ pinctrl-single,pins = <0x0a8 0x03>; }; /* Mode 3, Pull-Down */
+ P8_43_hdmi_pin: pinmux_P8_43_hdmi_pin {
+ pinctrl-single,pins = <0x0a8 0x08>; }; /* lcd_data2.lcd_data2, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+
+ /* P8_44 (ZCZ ball R4 ) hdmi */
+ P8_44_default_pin: pinmux_P8_44_default_pin {
+ pinctrl-single,pins = <0x0ac 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_44_gpio_pin: pinmux_P8_44_gpio_pin {
+ pinctrl-single,pins = <0x0ac 0x2F>; }; /* Mode 7, RxActive */
+ P8_44_gpio_pu_pin: pinmux_P8_44_gpio_pu_pin {
+ pinctrl-single,pins = <0x0ac 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_44_gpio_pd_pin: pinmux_P8_44_gpio_pd_pin {
+ pinctrl-single,pins = <0x0ac 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_44_pruout_pin: pinmux_P8_44_pruout_pin {
+ pinctrl-single,pins = <0x0ac 0x05>; }; /* Mode 5, Pull-Down*/
+ P8_44_pruin_pin: pinmux_P8_44_pruin_pin {
+ pinctrl-single,pins = <0x0ac 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+ P8_44_pwm_pin: pinmux_P8_44_pwm_pin {
+ pinctrl-single,pins = <0x0ac 0x23>; }; /* Mode 3, Pull-Down, RxActive */
+ P8_44_hdmi_pin: pinmux_P8_44_hdmi_pin {
+ pinctrl-single,pins = <0x0ac 0x08>; }; /* lcd_data3.lcd_data3, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+
+ /* P8_45 (ZCZ ball R1 ) hdmi */
+ P8_45_default_pin: pinmux_P8_45_default_pin {
+ pinctrl-single,pins = <0x0a0 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_45_gpio_pin: pinmux_P8_45_gpio_pin {
+ pinctrl-single,pins = <0x0a0 0x2F>; }; /* Mode 7, RxActive */
+ P8_45_gpio_pu_pin: pinmux_P8_45_gpio_pu_pin {
+ pinctrl-single,pins = <0x0a0 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_45_gpio_pd_pin: pinmux_P8_45_gpio_pd_pin {
+ pinctrl-single,pins = <0x0a0 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_45_pruout_pin: pinmux_P8_45_pruout_pin {
+ pinctrl-single,pins = <0x0a0 0x05>; }; /* Mode 5, Pull-Down*/
+ P8_45_pruin_pin: pinmux_P8_45_pruin_pin {
+ pinctrl-single,pins = <0x0a0 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+ P8_45_pwm_pin: pinmux_P8_45_pwm_pin {
+ pinctrl-single,pins = <0x0a0 0x03>; }; /* Mode 3, Pull-Down*/
+ P8_45_hdmi_pin: pinmux_P8_45_hdmi_pin {
+ pinctrl-single,pins = <0x0a0 0x08>; }; /* lcd_data0.lcd_data0, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+
+ /* P8_46 (ZCZ ball R2 ) hdmi */
+ P8_46_default_pin: pinmux_P8_46_default_pin {
+ pinctrl-single,pins = <0x0a4 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_46_gpio_pin: pinmux_P8_46_gpio_pin {
+ pinctrl-single,pins = <0x0a4 0x2F>; }; /* Mode 7, RxActive */
+ P8_46_gpio_pu_pin: pinmux_P8_46_gpio_pu_pin {
+ pinctrl-single,pins = <0x0a4 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_46_gpio_pd_pin: pinmux_P8_46_gpio_pd_pin {
+ pinctrl-single,pins = <0x0a4 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_46_pruout_pin: pinmux_P8_46_pruout_pin {
+ pinctrl-single,pins = <0x0a4 0x05>; }; /* Mode 5, Pull-Down*/
+ P8_46_pruin_pin: pinmux_P8_46_pruin_pin {
+ pinctrl-single,pins = <0x0a4 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+ P8_46_pwm_pin: pinmux_P8_46_pwm_pin {
+ pinctrl-single,pins = <0x0a4 0x03>; }; /* Mode 3, Pull-Down*/
+ P8_46_hdmi_pin: pinmux_P8_46_hdmi_pin {
+ pinctrl-single,pins = <0x0a4 0x08>; }; /* lcd_data1.lcd_data1, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+
+ /************************/
+ /* P9 Header */
+ /************************/
+
+ /* P9_01 GND */
+ /* P9_02 GND */
+ /* P9_03 3.3V */
+ /* P9_04 3.3V */
+ /* P9_05 VDD_5V */
+ /* P9_06 VDD_5V */
+ /* P9_07 SYS_5V */
+ /* P9_08 SYS_5V */
+ /* P9_09 PWR_BUT */
+ /* P9_10 (ZCZ ball A10) RESETn */
+
+ /* P9_11 (ZCZ ball T17) */
+ P9_11_default_pin: pinmux_P9_11_default_pin {
+ pinctrl-single,pins = <0x070 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_11_gpio_pin: pinmux_P9_11_gpio_pin {
+ pinctrl-single,pins = <0x070 0x2F>; }; /* Mode 7, RxActive */
+ P9_11_gpio_pu_pin: pinmux_P9_11_gpio_pu_pin {
+ pinctrl-single,pins = <0x070 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_11_gpio_pd_pin: pinmux_P9_11_gpio_pd_pin {
+ pinctrl-single,pins = <0x070 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_11_uart_pin: pinmux_P9_11_uart_pin {
+ pinctrl-single,pins = <0x070 0x36>; }; /* Mode 6, Pull-Up, RxActive */
+
+ /* P9_12 (ZCZ ball U18) */
+ P9_12_default_pin: pinmux_P9_12_default_pin {
+ pinctrl-single,pins = <0x078 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_12_gpio_pin: pinmux_P9_12_gpio_pin {
+ pinctrl-single,pins = <0x078 0x2F>; }; /* Mode 7, RxActive */
+ P9_12_gpio_pu_pin: pinmux_P9_12_gpio_pu_pin {
+ pinctrl-single,pins = <0x078 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_12_gpio_pd_pin: pinmux_P9_12_gpio_pd_pin {
+ pinctrl-single,pins = <0x078 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+
+ /* P9_13 (ZCZ ball U17) */
+ P9_13_default_pin: pinmux_P9_13_default_pin {
+ pinctrl-single,pins = <0x074 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_13_gpio_pin: pinmux_P9_13_gpio_pin {
+ pinctrl-single,pins = <0x074 0x2F>; }; /* Mode 7, RxActive */
+ P9_13_gpio_pu_pin: pinmux_P9_13_gpio_pu_pin {
+ pinctrl-single,pins = <0x074 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_13_gpio_pd_pin: pinmux_P9_13_gpio_pd_pin {
+ pinctrl-single,pins = <0x074 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_13_uart_pin: pinmux_P9_13_uart_pin {
+ pinctrl-single,pins = <0x074 0x36>; }; /* Mode 6, Pull-Up, RxActive */
+
+ /* P9_14 (ZCZ ball U14) */
+ P9_14_default_pin: pinmux_P9_14_default_pin {
+ pinctrl-single,pins = <0x048 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_14_gpio_pin: pinmux_P9_14_gpio_pin {
+ pinctrl-single,pins = <0x048 0x2F>; }; /* Mode 7, RxActive */
+ P9_14_gpio_pu_pin: pinmux_P9_14_gpio_pu_pin {
+ pinctrl-single,pins = <0x048 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_14_gpio_pd_pin: pinmux_P9_14_gpio_pd_pin {
+ pinctrl-single,pins = <0x048 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_14_pwm_pin: pinmux_P9_14_pwm_pin {
+ pinctrl-single,pins = <0x048 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+
+ /* P9_15 (ZCZ ball R13) */
+ P9_15_default_pin: pinmux_P9_15_default_pin {
+ pinctrl-single,pins = <0x040 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_15_gpio_pin: pinmux_P9_15_gpio_pin {
+ pinctrl-single,pins = <0x040 0x2F>; }; /* Mode 7, RxActive */
+ P9_15_gpio_pu_pin: pinmux_P9_15_gpio_pu_pin {
+ pinctrl-single,pins = <0x040 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_15_gpio_pd_pin: pinmux_P9_15_gpio_pd_pin {
+ pinctrl-single,pins = <0x040 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_15_pwm_pin: pinmux_P9_15_pwm_pin {
+ pinctrl-single,pins = <0x040 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+
+ /* P9_16 (ZCZ ball T14) */
+ P9_16_default_pin: pinmux_P9_16_default_pin {
+ pinctrl-single,pins = <0x04c 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_16_gpio_pin: pinmux_P9_16_gpio_pin {
+ pinctrl-single,pins = <0x04c 0x2F>; }; /* Mode 7, RxActive */
+ P9_16_gpio_pu_pin: pinmux_P9_16_gpio_pu_pin {
+ pinctrl-single,pins = <0x04c 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_16_gpio_pd_pin: pinmux_P9_16_gpio_pd_pin {
+ pinctrl-single,pins = <0x04c 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_16_pwm_pin: pinmux_P9_16_pwm_pin {
+ pinctrl-single,pins = <0x04c 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+
+ /* P9_17 (ZCZ ball A16) */
+ P9_17_default_pin: pinmux_P9_17_default_pin {
+ pinctrl-single,pins = <0x15c 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_17_gpio_pin: pinmux_P9_17_gpio_pin {
+ pinctrl-single,pins = <0x15c 0x2F>; }; /* Mode 7, RxActive */
+ P9_17_gpio_pu_pin: pinmux_P9_17_gpio_pu_pin {
+ pinctrl-single,pins = <0x15c 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_17_gpio_pd_pin: pinmux_P9_17_gpio_pd_pin {
+ pinctrl-single,pins = <0x15c 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_17_spi_pin: pinmux_P9_17_spi_pin {
+ pinctrl-single,pins = <0x15c 0x30>; }; /* Mode 0, Pull-Up, RxActive */
+ P9_17_i2c_pin: pinmux_P9_17_i2c_pin {
+ pinctrl-single,pins = <0x15c 0x32>; }; /* Mode 2, Pull-Up, RxActive */
+ P9_17_pwm_pin: pinmux_P9_17_pwm_pin {
+ pinctrl-single,pins = <0x15c 0x33>; }; /* Mode 3, Pull-Up, RxActive */
+
+ /* P9_18 (ZCZ ball B16) */
+ P9_18_default_pin: pinmux_P9_18_default_pin {
+ pinctrl-single,pins = <0x158 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_18_gpio_pin: pinmux_P9_18_gpio_pin {
+ pinctrl-single,pins = <0x158 0x2F>; }; /* Mode 7, RxActive */
+ P9_18_gpio_pu_pin: pinmux_P9_18_gpio_pu_pin {
+ pinctrl-single,pins = <0x158 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_18_gpio_pd_pin: pinmux_P9_18_gpio_pd_pin {
+ pinctrl-single,pins = <0x158 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_18_spi_pin: pinmux_P9_18_spi_pin {
+ pinctrl-single,pins = <0x158 0x30>; }; /* Mode 0, Pull-Up, RxActive */
+ P9_18_i2c_pin: pinmux_P9_18_i2c_pin {
+ pinctrl-single,pins = <0x158 0x32>; }; /* Mode 2, Pull-Up, RxActive */
+ P9_18_pwm_pin: pinmux_P9_18_pwm_pin {
+ pinctrl-single,pins = <0x158 0x33>; }; /* Mode 3, Pull-Up, RxActive */
+
+ /* P9_19 (ZCZ ball D17) */
+ P9_19_default_pin: pinmux_P9_19_default_pin {
+ pinctrl-single,pins = <0x17c 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_19_gpio_pin: pinmux_P9_19_gpio_pin {
+ pinctrl-single,pins = <0x17c 0x2F>; }; /* Mode 7, RxActive */
+ P9_19_gpio_pu_pin: pinmux_P9_19_gpio_pu_pin {
+ pinctrl-single,pins = <0x17c 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_19_gpio_pd_pin: pinmux_P9_19_gpio_pd_pin {
+ pinctrl-single,pins = <0x17c 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_19_can_pin: pinmux_P9_19_can_pin {
+ pinctrl-single,pins = <0x17c 0x32>; }; /* Mode 2, Pull-Up, RxActive */
+ P9_19_i2c_pin: pinmux_P9_19_i2c_pin {
+ pinctrl-single,pins = <0x17c 0x73>; }; /* (SLEWCTRL_SLOW | PIN_INPUT_PULLUP | MUX_MODE3) */
+
+ /* P9_20 (ZCZ ball D18) */
+ P9_20_default_pin: pinmux_P9_20_default_pin {
+ pinctrl-single,pins = <0x178 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_20_gpio_pin: pinmux_P9_20_gpio_pin {
+ pinctrl-single,pins = <0x178 0x2F>; }; /* Mode 7, RxActive */
+ P9_20_gpio_pu_pin: pinmux_P9_20_gpio_pu_pin {
+ pinctrl-single,pins = <0x178 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_20_gpio_pd_pin: pinmux_P9_20_gpio_pd_pin {
+ pinctrl-single,pins = <0x178 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_20_can_pin: pinmux_P9_20_can_pin {
+ pinctrl-single,pins = <0x178 0x12>; }; /* Mode 2, Pull-Up, RxActive */
+ P9_20_i2c_pin: pinmux_P9_20_i2c_pin {
+ pinctrl-single,pins = <0x178 0x73>; }; /* (SLEWCTRL_SLOW | PIN_INPUT_PULLUP | MUX_MODE3) */
+
+ /* P9_21 (ZCZ ball B17) */
+ P9_21_default_pin: pinmux_P9_21_default_pin {
+ pinctrl-single,pins = <0x154 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_21_gpio_pin: pinmux_P9_21_gpio_pin {
+ pinctrl-single,pins = <0x154 0x2F>; }; /* Mode 7, RxActive */
+ P9_21_gpio_pu_pin: pinmux_P9_21_gpio_pu_pin {
+ pinctrl-single,pins = <0x154 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_21_gpio_pd_pin: pinmux_P9_21_gpio_pd_pin {
+ pinctrl-single,pins = <0x154 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_21_spi_pin: pinmux_P9_21_spi_pin {
+ pinctrl-single,pins = <0x154 0x30>; }; /* Mode 0, Pull-Up, RxActive */
+ P9_21_uart_pin: pinmux_P9_21_uart_pin {
+ pinctrl-single,pins = <0x154 0x31>; }; /* Mode 1, Pull-Up, RxActive */
+ P9_21_i2c_pin: pinmux_P9_21_i2c_pin {
+ pinctrl-single,pins = <0x154 0x32>; }; /* Mode 2, Pull-Up, RxActive */
+ P9_21_pwm_pin: pinmux_P9_21_pwm_pin {
+ pinctrl-single,pins = <0x154 0x33>; }; /* Mode 3, Pull-Up, RxActive */
+
+ /* P9_22 (ZCZ ball A17) */
+ P9_22_default_pin: pinmux_P9_22_default_pin {
+ pinctrl-single,pins = <0x150 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_22_gpio_pin: pinmux_P9_22_gpio_pin {
+ pinctrl-single,pins = <0x150 0x2F>; }; /* Mode 7, RxActive */
+ P9_22_gpio_pu_pin: pinmux_P9_22_gpio_pu_pin {
+ pinctrl-single,pins = <0x150 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_22_gpio_pd_pin: pinmux_P9_22_gpio_pd_pin {
+ pinctrl-single,pins = <0x150 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_22_spi_pin: pinmux_P9_22_spi_pin {
+ pinctrl-single,pins = <0x150 0x30>; }; /* Mode 0, Pull-Up, RxActive */
+ P9_22_uart_pin: pinmux_P9_22_uart_pin {
+ pinctrl-single,pins = <0x150 0x31>; }; /* Mode 1, Pull-Up, RxActive */
+ P9_22_i2c_pin: pinmux_P9_22_i2c_pin {
+ pinctrl-single,pins = <0x150 0x32>; }; /* Mode 2, Pull-Up, RxActive */
+ P9_22_pwm_pin: pinmux_P9_22_pwm_pin {
+ pinctrl-single,pins = <0x150 0x33>; }; /* Mode 3, Pull-Up, RxActive */
+
+ /* P9_23 (ZCZ ball V14) */
+ P9_23_default_pin: pinmux_P9_23_default_pin {
+ pinctrl-single,pins = <0x044 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_23_gpio_pin: pinmux_P9_23_gpio_pin {
+ pinctrl-single,pins = <0x044 0x2F>; }; /* Mode 7, RxActive */
+ P9_23_gpio_pu_pin: pinmux_P9_23_gpio_pu_pin {
+ pinctrl-single,pins = <0x044 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_23_gpio_pd_pin: pinmux_P9_23_gpio_pd_pin {
+ pinctrl-single,pins = <0x044 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_23_pwm_pin: pinmux_P9_23_pwm_pin {
+ pinctrl-single,pins = <0x044 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+
+ /* P9_24 (ZCZ ball D15) */
+ P9_24_default_pin: pinmux_P9_24_default_pin {
+ pinctrl-single,pins = <0x184 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_24_gpio_pin: pinmux_P9_24_gpio_pin {
+ pinctrl-single,pins = <0x184 0x2F>; }; /* Mode 7, RxActive */
+ P9_24_gpio_pu_pin: pinmux_P9_24_gpio_pu_pin {
+ pinctrl-single,pins = <0x184 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_24_gpio_pd_pin: pinmux_P9_24_gpio_pd_pin {
+ pinctrl-single,pins = <0x184 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_24_uart_pin: pinmux_P9_24_uart_pin {
+ pinctrl-single,pins = <0x184 0x30>; }; /* Mode 0, Pull-Up, RxActive */
+ P9_24_can_pin: pinmux_P9_24_can_pin {
+ pinctrl-single,pins = <0x184 0x32>; }; /* Mode 2, Pull-Up, RxActive */
+ P9_24_i2c_pin: pinmux_P9_24_i2c_pin {
+ pinctrl-single,pins = <0x184 0x33>; }; /* Mode 3, Pull-Up, RxActive */
+ P9_24_pruin_pin: pinmux_P9_24_pruin_pin {
+ pinctrl-single,pins = <0x184 0x36>; }; /* Mode 6, Pull-Up, RxActive */
+
+ /* P9_25 (ZCZ ball A14) Audio */
+ P9_25_default_pin: pinmux_P9_25_default_pin {
+ pinctrl-single,pins = <0x1ac 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_25_gpio_pin: pinmux_P9_25_gpio_pin {
+ pinctrl-single,pins = <0x1ac 0x2F>; }; /* Mode 7, RxActive */
+ P9_25_gpio_pu_pin: pinmux_P9_25_gpio_pu_pin {
+ pinctrl-single,pins = <0x1ac 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_25_gpio_pd_pin: pinmux_P9_25_gpio_pd_pin {
+ pinctrl-single,pins = <0x1ac 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_25_qep_pin: pinmux_P9_25_qep_pin {
+ pinctrl-single,pins = <0x1ac 0x21>; }; /* Mode 1, Pull-Down, RxActive */
+ P9_25_pruout_pin: pinmux_P9_25_pruout_pin {
+ pinctrl-single,pins = <0x1ac 0x25>; }; /* Mode 5, Pull-Down, RxActive */
+ P9_25_pruin_pin: pinmux_P9_25_pruin_pin {
+ pinctrl-single,pins = <0x1ac 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+ P9_25_audio_pin: pinmux_P9_25_audio_pin {
+ pinctrl-single,pins = <0x1ac (PIN_INPUT_PULLUP | MUX_MODE0)>; }; /* mcasp0_ahclkx.mcasp0_ahclkx */
+
+ /* P9_26 (ZCZ ball D16) */
+ P9_26_default_pin: pinmux_P9_26_default_pin {
+ pinctrl-single,pins = <0x180 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_26_gpio_pin: pinmux_P9_26_gpio_pin {
+ pinctrl-single,pins = <0x180 0x2F>; }; /* Mode 7, RxActive */
+ P9_26_gpio_pu_pin: pinmux_P9_26_gpio_pu_pin {
+ pinctrl-single,pins = <0x180 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_26_gpio_pd_pin: pinmux_P9_26_gpio_pd_pin {
+ pinctrl-single,pins = <0x180 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_26_uart_pin: pinmux_P9_26_uart_pin {
+ pinctrl-single,pins = <0x180 0x30>; }; /* Mode 0, Pull-Up, RxActive */
+ P9_26_can_pin: pinmux_P9_26_can_pin {
+ pinctrl-single,pins = <0x180 0x12>; }; /* Mode 2, Pull-Up, RxActive */
+ P9_26_i2c_pin: pinmux_P9_26_i2c_pin {
+ pinctrl-single,pins = <0x180 0x33>; }; /* Mode 3, Pull-Up, RxActive */
+ P9_26_pruin_pin: pinmux_P9_26_pruin_pin {
+ pinctrl-single,pins = <0x180 0x36>; }; /* Mode 6, Pull-Up, RxActive */
+
+ /* P9_27 (ZCZ ball C13) */
+ P9_27_default_pin: pinmux_P9_27_default_pin {
+ pinctrl-single,pins = <0x1a4 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_27_gpio_pin: pinmux_P9_27_gpio_pin {
+ pinctrl-single,pins = <0x1a4 0x2F>; }; /* Mode 7, RxActive */
+ P9_27_gpio_pu_pin: pinmux_P9_27_gpio_pu_pin {
+ pinctrl-single,pins = <0x1a4 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_27_gpio_pd_pin: pinmux_P9_27_gpio_pd_pin {
+ pinctrl-single,pins = <0x1a4 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_27_qep_pin: pinmux_P9_27_qep_pin {
+ pinctrl-single,pins = <0x1a4 0x21>; }; /* Mode 1, Pull-Down, RxActive */
+ P9_27_pruout_pin: pinmux_P9_27_pruout_pin {
+ pinctrl-single,pins = <0x1a4 0x25>; }; /* Mode 5, Pull-Down, RxActive */
+ P9_27_pruin_pin: pinmux_P9_27_pruin_pin {
+ pinctrl-single,pins = <0x1a4 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+
+ /* P9_28 (ZCZ ball C12) Audio */
+ P9_28_default_pin: pinmux_P9_28_default_pin {
+ pinctrl-single,pins = <0x19c 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_28_gpio_pin: pinmux_P9_28_gpio_pin {
+ pinctrl-single,pins = <0x19c 0x2F>; }; /* Mode 7, RxActive */
+ P9_28_gpio_pu_pin: pinmux_P9_28_gpio_pu_pin {
+ pinctrl-single,pins = <0x19c 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_28_gpio_pd_pin: pinmux_P9_28_gpio_pd_pin {
+ pinctrl-single,pins = <0x19c 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_28_pwm_pin: pinmux_P9_28_pwm_pin {
+ pinctrl-single,pins = <0x19c 0x21>; }; /* Mode 1, Pull-Down, RxActive */
+ P9_28_spi_pin: pinmux_P9_28_spi_pin {
+ pinctrl-single,pins = <0x19c 0x23>; }; /* Mode 3, Pull-Down, RxActive */
+ P9_28_pwm2_pin: pinmux_P9_28_pwm2_pin {
+ pinctrl-single,pins = <0x19c 0x24>; }; /* Mode 4, Pull-Down, RxActive */
+ P9_28_pruout_pin: pinmux_P9_28_pruout_pin {
+ pinctrl-single,pins = <0x19c 0x25>; }; /* Mode 5, Pull-Down, RxActive */
+ P9_28_pruin_pin: pinmux_P9_28_pruin_pin {
+ pinctrl-single,pins = <0x19c 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+ P9_28_audio_pin: pinmux_P9_28_audio_pin {
+ pinctrl-single,pins = <0x19c (PIN_OUTPUT_PULLDOWN | MUX_MODE2)>; }; /* mcasp0_ahclkr.mcasp0_axr2 */
+
+ /* P9_29 (ZCZ ball B13) Audio */
+ P9_29_default_pin: pinmux_P9_29_default_pin {
+ pinctrl-single,pins = <0x194 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_29_gpio_pin: pinmux_P9_29_gpio_pin {
+ pinctrl-single,pins = <0x194 0x2F>; }; /* Mode 7, RxActive */
+ P9_29_gpio_pu_pin: pinmux_P9_29_gpio_pu_pin {
+ pinctrl-single,pins = <0x194 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_29_gpio_pd_pin: pinmux_P9_29_gpio_pd_pin {
+ pinctrl-single,pins = <0x194 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_29_pwm_pin: pinmux_P9_29_pwm_pin {
+ pinctrl-single,pins = <0x194 0x21>; }; /* Mode 1, Pull-Down, RxActive */
+ P9_29_spi_pin: pinmux_P9_29_spi_pin {
+ pinctrl-single,pins = <0x194 0x23>; }; /* Mode 3, Pull-Down, RxActive */
+ P9_29_pruout_pin: pinmux_P9_29_pruout_pin {
+ pinctrl-single,pins = <0x194 0x25>; }; /* Mode 5, Pull-Down, RxActive */
+ P9_29_pruin_pin: pinmux_P9_29_pruin_pin {
+ pinctrl-single,pins = <0x194 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+ P9_29_audio_pin: pinmux_P9_29_audio_pin {
+ pinctrl-single,pins = <0x194 (PIN_OUTPUT_PULLUP | MUX_MODE0)>; }; /* mcasp0_fsx.mcasp0_fsx */
+
+ /* P9_30 (ZCZ ball D12) */
+ P9_30_default_pin: pinmux_P9_30_default_pin {
+ pinctrl-single,pins = <0x198 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_30_gpio_pin: pinmux_P9_30_gpio_pin {
+ pinctrl-single,pins = <0x198 0x2F>; }; /* Mode 7, RxActive */
+ P9_30_gpio_pu_pin: pinmux_P9_30_gpio_pu_pin {
+ pinctrl-single,pins = <0x198 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_30_gpio_pd_pin: pinmux_P9_30_gpio_pd_pin {
+ pinctrl-single,pins = <0x198 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_30_pwm_pin: pinmux_P9_30_pwm_pin {
+ pinctrl-single,pins = <0x198 0x21>; }; /* Mode 1, Pull-Down, RxActive */
+ P9_30_spi_pin: pinmux_P9_30_spi_pin {
+ pinctrl-single,pins = <0x198 0x23>; }; /* Mode 3, Pull-Down, RxActive */
+ P9_30_pruout_pin: pinmux_P9_30_pruout_pin {
+ pinctrl-single,pins = <0x198 0x25>; }; /* Mode 5, Pull-Down, RxActive */
+ P9_30_pruin_pin: pinmux_P9_30_pruin_pin {
+ pinctrl-single,pins = <0x198 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+
+ /* P9_31 (ZCZ ball A13) Audio */
+ P9_31_default_pin: pinmux_P9_31_default_pin {
+ pinctrl-single,pins = <0x190 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_31_gpio_pin: pinmux_P9_31_gpio_pin {
+ pinctrl-single,pins = <0x190 0x2F>; }; /* Mode 7, RxActive */
+ P9_31_gpio_pu_pin: pinmux_P9_31_gpio_pu_pin {
+ pinctrl-single,pins = <0x190 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_31_gpio_pd_pin: pinmux_P9_31_gpio_pd_pin {
+ pinctrl-single,pins = <0x190 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_31_pwm_pin: pinmux_P9_31_pwm_pin {
+ pinctrl-single,pins = <0x190 0x21>; }; /* Mode 1, Pull-Down, RxActive */
+ P9_31_spi_pin: pinmux_P9_31_spi_pin {
+ pinctrl-single,pins = <0x190 0x23>; }; /* Mode 3, Pull-Down, RxActive */
+ P9_31_pruout_pin: pinmux_P9_31_pruout_pin {
+ pinctrl-single,pins = <0x190 0x25>; }; /* Mode 5, Pull-Down, RxActive */
+ P9_31_pruin_pin: pinmux_P9_31_pruin_pin {
+ pinctrl-single,pins = <0x190 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+ P9_31_audio_pin: pinmux_P9_31_audio_pin {
+ pinctrl-single,pins = <0x190 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)>; }; /* mcasp0_aclkx.mcasp0_aclkx */
+
+ /* P9_32 VADC */
+ /* P9_33 (ZCZ ball C8 ) AIN4 */
+ /* P9_34 AGND */
+ /* P9_35 (ZCZ ball A8 ) AIN6 */
+ /* P9_36 (ZCZ ball B8 ) AIN5 */
+ /* P9_37 (ZCZ ball B7 ) AIN2 */
+ /* P9_38 (ZCZ ball A7 ) AIN3 */
+ /* P9_39 (ZCZ ball B6 ) AIN0 */
+ /* P9_40 (ZCZ ball C7 ) AIN1 */
+
+ /* P9_41 (ZCZ ball D14) */
+ P9_41_default_pin: pinmux_P9_41_default_pin {
+ pinctrl-single,pins = <0x1b4 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_41_gpio_pin: pinmux_P9_41_gpio_pin {
+ pinctrl-single,pins = <0x1b4 0x2F>; }; /* Mode 7, RxActive */
+ P9_41_gpio_pu_pin: pinmux_P9_41_gpio_pu_pin {
+ pinctrl-single,pins = <0x1b4 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_41_gpio_pd_pin: pinmux_P9_41_gpio_pd_pin {
+ pinctrl-single,pins = <0x1b4 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_41_timer_pin: pinmux_P9_41_timer_pin {
+ pinctrl-single,pins = <0x1b4 0x24>; }; /* Mode 4, Pull-Down, RxActive */
+ P9_41_pruin_pin: pinmux_P9_41_pruin_pin {
+ pinctrl-single,pins = <0x1b4 0x25>; }; /* Mode 5, Pull-Down, RxActive */
+
+ /* P9_41.1 */
+ /* P9_91 (ZCZ ball D13) */
+ P9_91_default_pin: pinmux_P9_91_default_pin {
+ pinctrl-single,pins = <0x1a8 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_91_gpio_pin: pinmux_P9_91_gpio_pin {
+ pinctrl-single,pins = <0x1a8 0x2F>; }; /* Mode 7, RxActive */
+ P9_91_gpio_pu_pin: pinmux_P9_91_gpio_pu_pin {
+ pinctrl-single,pins = <0x1a8 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_91_gpio_pd_pin: pinmux_P9_91_gpio_pd_pin {
+ pinctrl-single,pins = <0x1a8 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_91_qep_pin: pinmux_P9_91_qep_pin {
+ pinctrl-single,pins = <0x1a8 0x21>; }; /* Mode 1, Pull-Down, RxActive */
+ P9_91_pruout_pin: pinmux_P9_91_pruout_pin {
+ pinctrl-single,pins = <0x1a8 0x25>; }; /* Mode 5, Pull-Down, RxActive */
+ P9_91_pruin_pin: pinmux_P9_91_pruin_pin {
+ pinctrl-single,pins = <0x1a8 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+
+ /* P9_42 (ZCZ ball C18) */
+ P9_42_default_pin: pinmux_P9_42_default_pin {
+ pinctrl-single,pins = <0x164 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_42_gpio_pin: pinmux_P9_42_gpio_pin {
+ pinctrl-single,pins = <0x164 0x2F>; }; /* Mode 7, RxActive */
+ P9_42_gpio_pu_pin: pinmux_P9_42_gpio_pu_pin {
+ pinctrl-single,pins = <0x164 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_42_gpio_pd_pin: pinmux_P9_42_gpio_pd_pin {
+ pinctrl-single,pins = <0x164 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_42_pwm_pin: pinmux_P9_42_pwm_pin {
+ pinctrl-single,pins = <0x164 0x20>; }; /* Mode 0, Pull-Down, RxActive */
+ P9_42_uart_pin: pinmux_P9_42_uart_pin {
+ pinctrl-single,pins = <0x164 0x21>; }; /* Mode 1, Pull-Down, RxActive */
+ P9_42_spics_pin: pinmux_P9_42_spics_pin {
+ pinctrl-single,pins = <0x164 0x22>; }; /* Mode 2, Pull-Down, RxActive */
+ P9_42_spiclk_pin: pinmux_P9_42_spiclk_pin {
+ pinctrl-single,pins = <0x164 0x24>; }; /* Mode 4, Pull-Down, RxActive */
+
+ /* P9_42.1 */
+ /* P9_92 (ZCZ ball B12) */
+ P9_92_default_pin: pinmux_P9_92_default_pin {
+ pinctrl-single,pins = <0x1a0 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_92_gpio_pin: pinmux_P9_92_gpio_pin {
+ pinctrl-single,pins = <0x1a0 0x2F>; }; /* Mode 7, RxActive */
+ P9_92_gpio_pu_pin: pinmux_P9_92_gpio_pu_pin {
+ pinctrl-single,pins = <0x1a0 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_92_gpio_pd_pin: pinmux_P9_92_gpio_pd_pin {
+ pinctrl-single,pins = <0x1a0 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_92_qep_pin: pinmux_P9_92_qep_pin {
+ pinctrl-single,pins = <0x1a0 0x21>; }; /* Mode 1, Pull-Down, RxActive */
+ P9_92_pruout_pin: pinmux_P9_92_pruout_pin {
+ pinctrl-single,pins = <0x1a0 0x25>; }; /* Mode 5, Pull-Down, RxActive */
+ P9_92_pruin_pin: pinmux_P9_92_pruin_pin {
+ pinctrl-single,pins = <0x1a0 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+
+ /* P9_43 GND */
+ /* P9_44 GND */
+ /* P9_45 GND */
+ /* P9_46 GND */
+};
diff --git b/arch/arm/boot/dts/am335x-bone-common-universal.dtsi b/arch/arm/boot/dts/am335x-bone-common-universal.dtsi
new file mode 100644
index 0000000..781e33f
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-bone-common-universal.dtsi
@@ -0,0 +1,2052 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+&am33xx_pinmux {
+ /************************/
+ /* P8 Header */
+ /************************/
+
+ /* P8_01 GND */
+ /* P8_02 GND */
+ /* P8_03 (ZCZ ball R9 ) emmc */
+ /* P8_04 (ZCZ ball T9 ) emmc */
+ /* P8_05 (ZCZ ball R8 ) emmc */
+ /* P8_06 (ZCZ ball T8 ) emmc */
+
+ /* P8_07 (ZCZ ball R7 ) */
+ P8_07_default_pin: pinmux_P8_07_default_pin {
+ pinctrl-single,pins = <0x090 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_07_gpio_pin: pinmux_P8_07_gpio_pin {
+ pinctrl-single,pins = <0x090 0x2F>; }; /* Mode 7, RxActive */
+ P8_07_gpio_pu_pin: pinmux_P8_07_gpio_pu_pin {
+ pinctrl-single,pins = <0x090 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_07_gpio_pd_pin: pinmux_P8_07_gpio_pd_pin {
+ pinctrl-single,pins = <0x090 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_07_timer_pin: pinmux_P8_07_timer_pin {
+ pinctrl-single,pins = <0x090 0x32>; }; /* Mode 2, Pull-Up, RxActive */
+
+ /* P8_08 (ZCZ ball T7 ) */
+ P8_08_default_pin: pinmux_P8_08_default_pin {
+ pinctrl-single,pins = <0x094 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_08_gpio_pin: pinmux_P8_08_gpio_pin {
+ pinctrl-single,pins = <0x094 0x2F>; }; /* Mode 7, RxActive */
+ P8_08_gpio_pu_pin: pinmux_P8_08_gpio_pu_pin {
+ pinctrl-single,pins = <0x094 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_08_gpio_pd_pin: pinmux_P8_08_gpio_pd_pin {
+ pinctrl-single,pins = <0x094 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_08_timer_pin: pinmux_P8_08_timer_pin {
+ pinctrl-single,pins = <0x094 0x32>; }; /* Mode 2, Pull-Up, RxActive */
+
+ /* P8_09 (ZCZ ball T6 ) */
+ P8_09_default_pin: pinmux_P8_09_default_pin {
+ pinctrl-single,pins = <0x09c 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_09_gpio_pin: pinmux_P8_09_gpio_pin {
+ pinctrl-single,pins = <0x09c 0x2F>; }; /* Mode 7, RxActive */
+ P8_09_gpio_pu_pin: pinmux_P8_09_gpio_pu_pin {
+ pinctrl-single,pins = <0x09c 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_09_gpio_pd_pin: pinmux_P8_09_gpio_pd_pin {
+ pinctrl-single,pins = <0x09c 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_09_timer_pin: pinmux_P8_09_timer_pin {
+ pinctrl-single,pins = <0x09c 0x32>; }; /* Mode 2, Pull-Up, RxActive */
+
+ /* P8_10 (ZCZ ball U6 ) */
+ P8_10_default_pin: pinmux_P8_10_default_pin {
+ pinctrl-single,pins = <0x098 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_10_gpio_pin: pinmux_P8_10_gpio_pin {
+ pinctrl-single,pins = <0x098 0x2F>; }; /* Mode 7, RxActive */
+ P8_10_gpio_pu_pin: pinmux_P8_10_gpio_pu_pin {
+ pinctrl-single,pins = <0x098 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_10_gpio_pd_pin: pinmux_P8_10_gpio_pd_pin {
+ pinctrl-single,pins = <0x098 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_10_timer_pin: pinmux_P8_10_timer_pin {
+ pinctrl-single,pins = <0x098 0x32>; }; /* Mode 2, Pull-Up, RxActive */
+
+ /* P8_11 (ZCZ ball R12) */
+ P8_11_default_pin: pinmux_P8_11_default_pin {
+ pinctrl-single,pins = <0x034 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_11_gpio_pin: pinmux_P8_11_gpio_pin {
+ pinctrl-single,pins = <0x034 0x2F>; }; /* Mode 7, RxActive */
+ P8_11_gpio_pu_pin: pinmux_P8_11_gpio_pu_pin {
+ pinctrl-single,pins = <0x034 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_11_gpio_pd_pin: pinmux_P8_11_gpio_pd_pin {
+ pinctrl-single,pins = <0x034 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_11_pruout_pin: pinmux_P8_11_pruout_pin {
+ pinctrl-single,pins = <0x034 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+ P8_11_qep_pin: pinmux_P8_11_qep_pin {
+ pinctrl-single,pins = <0x034 0x24>; }; /* Mode 4, Pull-Down, RxActive */
+
+ /* P8_12 (ZCZ ball T12) */
+ P8_12_default_pin: pinmux_P8_12_default_pin {
+ pinctrl-single,pins = <0x030 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_12_gpio_pin: pinmux_P8_12_gpio_pin {
+ pinctrl-single,pins = <0x030 0x2F>; }; /* Mode 7, RxActive */
+ P8_12_gpio_pu_pin: pinmux_P8_12_gpio_pu_pin {
+ pinctrl-single,pins = <0x030 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_12_gpio_pd_pin: pinmux_P8_12_gpio_pd_pin {
+ pinctrl-single,pins = <0x030 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_12_pruout_pin: pinmux_P8_12_pruout_pin {
+ pinctrl-single,pins = <0x030 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+ P8_12_qep_pin: pinmux_P8_12_qep_pin {
+ pinctrl-single,pins = <0x030 0x24>; }; /* Mode 4, Pull-Down, RxActive */
+
+ /* P8_13 (ZCZ ball T10) */
+ P8_13_default_pin: pinmux_P8_13_default_pin {
+ pinctrl-single,pins = <0x024 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_13_gpio_pin: pinmux_P8_13_gpio_pin {
+ pinctrl-single,pins = <0x024 0x2F>; }; /* Mode 7, RxActive */
+ P8_13_gpio_pu_pin: pinmux_P8_13_gpio_pu_pin {
+ pinctrl-single,pins = <0x024 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_13_gpio_pd_pin: pinmux_P8_13_gpio_pd_pin {
+ pinctrl-single,pins = <0x024 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_13_pwm_pin: pinmux_P8_13_pwm_pin {
+ pinctrl-single,pins = <0x024 0x24>; }; /* Mode 4, Pull-Down, RxActive */
+
+ /* P8_14 (ZCZ ball T11) */
+ P8_14_default_pin: pinmux_P8_14_default_pin {
+ pinctrl-single,pins = <0x028 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_14_gpio_pin: pinmux_P8_14_gpio_pin {
+ pinctrl-single,pins = <0x028 0x2F>; }; /* Mode 7, RxActive */
+ P8_14_gpio_pu_pin: pinmux_P8_14_gpio_pu_pin {
+ pinctrl-single,pins = <0x028 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_14_gpio_pd_pin: pinmux_P8_14_gpio_pd_pin {
+ pinctrl-single,pins = <0x028 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_14_pwm_pin: pinmux_P8_14_pwm_pin {
+ pinctrl-single,pins = <0x028 0x24>; }; /* Mode 4, Pull-Down, RxActive */
+
+ /* P8_15 (ZCZ ball U13) */
+ P8_15_default_pin: pinmux_P8_15_default_pin {
+ pinctrl-single,pins = <0x03c 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_15_gpio_pin: pinmux_P8_15_gpio_pin {
+ pinctrl-single,pins = <0x03c 0x2F>; }; /* Mode 7, RxActive */
+ P8_15_gpio_pu_pin: pinmux_P8_15_gpio_pu_pin {
+ pinctrl-single,pins = <0x03c 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_15_gpio_pd_pin: pinmux_P8_15_gpio_pd_pin {
+ pinctrl-single,pins = <0x03c 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_15_pruin_pin: pinmux_P8_15_pruin_pin {
+ pinctrl-single,pins = <0x03c 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+ P8_15_qep_pin: pinmux_P8_15_qep_pin {
+ pinctrl-single,pins = <0x03c 0x24>; }; /* Mode 4, Pull-Down, RxActive */
+
+ /* P8_16 (ZCZ ball V13) */
+ P8_16_default_pin: pinmux_P8_16_default_pin {
+ pinctrl-single,pins = <0x038 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_16_gpio_pin: pinmux_P8_16_gpio_pin {
+ pinctrl-single,pins = <0x038 0x2F>; }; /* Mode 7, RxActive */
+ P8_16_gpio_pu_pin: pinmux_P8_16_gpio_pu_pin {
+ pinctrl-single,pins = <0x038 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_16_gpio_pd_pin: pinmux_P8_16_gpio_pd_pin {
+ pinctrl-single,pins = <0x038 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_16_pruin_pin: pinmux_P8_16_pruin_pin {
+ pinctrl-single,pins = <0x038 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+ P8_16_qep_pin: pinmux_P8_16_qep_pin {
+ pinctrl-single,pins = <0x038 0x24>; }; /* Mode 4, Pull-Down, RxActive */
+
+ /* P8_17 (ZCZ ball U12) */
+ P8_17_default_pin: pinmux_P8_17_default_pin {
+ pinctrl-single,pins = <0x02c 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_17_gpio_pin: pinmux_P8_17_gpio_pin {
+ pinctrl-single,pins = <0x02c 0x2F>; }; /* Mode 7, RxActive */
+ P8_17_gpio_pu_pin: pinmux_P8_17_gpio_pu_pin {
+ pinctrl-single,pins = <0x02c 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_17_gpio_pd_pin: pinmux_P8_17_gpio_pd_pin {
+ pinctrl-single,pins = <0x02c 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_17_pwm_pin: pinmux_P8_17_pwm_pin {
+ pinctrl-single,pins = <0x02c 0x24>; }; /* Mode 4, Pull-Down, RxActive */
+
+ /* P8_18 (ZCZ ball V12) */
+ P8_18_default_pin: pinmux_P8_18_default_pin {
+ pinctrl-single,pins = <0x08c 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_18_gpio_pin: pinmux_P8_18_gpio_pin {
+ pinctrl-single,pins = <0x08c 0x2F>; }; /* Mode 7, RxActive */
+ P8_18_gpio_pu_pin: pinmux_P8_18_gpio_pu_pin {
+ pinctrl-single,pins = <0x08c 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_18_gpio_pd_pin: pinmux_P8_18_gpio_pd_pin {
+ pinctrl-single,pins = <0x08c 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+
+ /* P8_19 (ZCZ ball U10) */
+ P8_19_default_pin: pinmux_P8_19_default_pin {
+ pinctrl-single,pins = <0x020 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_19_gpio_pin: pinmux_P8_19_gpio_pin {
+ pinctrl-single,pins = <0x020 0x2F>; }; /* Mode 7, RxActive */
+ P8_19_gpio_pu_pin: pinmux_P8_19_gpio_pu_pin {
+ pinctrl-single,pins = <0x020 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_19_gpio_pd_pin: pinmux_P8_19_gpio_pd_pin {
+ pinctrl-single,pins = <0x020 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_19_pwm_pin: pinmux_P8_19_pwm_pin {
+ pinctrl-single,pins = <0x020 0x24>; }; /* Mode 4, Pull-Down, RxActive */
+
+ /* P8_20 (ZCZ ball V9 ) emmc */
+ /* P8_21 (ZCZ ball U9 ) emmc */
+ /* P8_22 (ZCZ ball V8 ) emmc */
+ /* P8_23 (ZCZ ball U8 ) emmc */
+ /* P8_24 (ZCZ ball V7 ) emmc */
+ /* P8_25 (ZCZ ball U7 ) emmc */
+
+ /* P8_26 (ZCZ ball V6 ) */
+ P8_26_default_pin: pinmux_P8_26_default_pin {
+ pinctrl-single,pins = <0x07c 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_26_gpio_pin: pinmux_P8_26_gpio_pin {
+ pinctrl-single,pins = <0x07c 0x2F>; }; /* Mode 7, RxActive */
+ P8_26_gpio_pu_pin: pinmux_P8_26_gpio_pu_pin {
+ pinctrl-single,pins = <0x07c 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_26_gpio_pd_pin: pinmux_P8_26_gpio_pd_pin {
+ pinctrl-single,pins = <0x07c 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+
+ /* P8_27 (ZCZ ball U5 ) hdmi */
+ P8_27_default_pin: pinmux_P8_27_default_pin {
+ pinctrl-single,pins = <0x0e0 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_27_gpio_pin: pinmux_P8_27_gpio_pin {
+ pinctrl-single,pins = <0x0e0 0x2F>; }; /* Mode 7, RxActive */
+ P8_27_gpio_pu_pin: pinmux_P8_27_gpio_pu_pin {
+ pinctrl-single,pins = <0x0e0 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_27_gpio_pd_pin: pinmux_P8_27_gpio_pd_pin {
+ pinctrl-single,pins = <0x0e0 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_27_pruout_pin: pinmux_P8_27_pruout_pin {
+ pinctrl-single,pins = <0x0e0 0x05>; }; /* Mode 5, Pull-Down*/
+ P8_27_pruin_pin: pinmux_P8_27_pruin_pin {
+ pinctrl-single,pins = <0x0e0 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+ P8_27_hdmi_pin: pinmux_P8_27_hdmi_pin {
+ pinctrl-single,pins = <0x0e0 0x00>; }; /* lcd_vsync.lcd_vsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+
+ /* P8_28 (ZCZ ball V5 ) hdmi */
+ P8_28_default_pin: pinmux_P8_28_default_pin {
+ pinctrl-single,pins = <0x0e8 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_28_gpio_pin: pinmux_P8_28_gpio_pin {
+ pinctrl-single,pins = <0x0e8 0x2F>; }; /* Mode 7, RxActive */
+ P8_28_gpio_pu_pin: pinmux_P8_28_gpio_pu_pin {
+ pinctrl-single,pins = <0x0e8 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_28_gpio_pd_pin: pinmux_P8_28_gpio_pd_pin {
+ pinctrl-single,pins = <0x0e8 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_28_pruout_pin: pinmux_P8_28_pruout_pin {
+ pinctrl-single,pins = <0x0e8 0x05>; }; /* Mode 5, Pull-Down */
+ P8_28_pruin_pin: pinmux_P8_28_pruin_pin {
+ pinctrl-single,pins = <0x0e8 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+ P8_28_hdmi_pin: pinmux_P8_28_hdmi_pin {
+ pinctrl-single,pins = <0x0e8 0x00>; }; /* lcd_pclk.lcd_pclk, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+
+ /* P8_29 (ZCZ ball R5 ) hdmi */
+ P8_29_default_pin: pinmux_P8_29_default_pin {
+ pinctrl-single,pins = <0x0e4 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_29_gpio_pin: pinmux_P8_29_gpio_pin {
+ pinctrl-single,pins = <0x0e4 0x2F>; }; /* Mode 7, RxActive */
+ P8_29_gpio_pu_pin: pinmux_P8_29_gpio_pu_pin {
+ pinctrl-single,pins = <0x0e4 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_29_gpio_pd_pin: pinmux_P8_29_gpio_pd_pin {
+ pinctrl-single,pins = <0x0e4 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_29_pruout_pin: pinmux_P8_29_pruout_pin {
+ pinctrl-single,pins = <0x0e4 0x05>; }; /* Mode 5, Pull-Down*/
+ P8_29_pruin_pin: pinmux_P8_29_pruin_pin {
+ pinctrl-single,pins = <0x0e4 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+ P8_29_hdmi_pin: pinmux_P8_29_hdmi_pin {
+ pinctrl-single,pins = <0x0e4 0x00>; }; /* lcd_hsync.lcd_hsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+
+ /* P8_30 (ZCZ ball R6 ) hdmi */
+ P8_30_default_pin: pinmux_P8_30_default_pin {
+ pinctrl-single,pins = <0x0ec 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_30_gpio_pin: pinmux_P8_30_gpio_pin {
+ pinctrl-single,pins = <0x0ec 0x2F>; }; /* Mode 7, RxActive */
+ P8_30_gpio_pu_pin: pinmux_P8_30_gpio_pu_pin {
+ pinctrl-single,pins = <0x0ec 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_30_gpio_pd_pin: pinmux_P8_30_gpio_pd_pin {
+ pinctrl-single,pins = <0x0ec 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_30_pruout_pin: pinmux_P8_30_pruout_pin {
+ pinctrl-single,pins = <0x0ec 0x05>; }; /* Mode 5, Pull-Down*/
+ P8_30_pruin_pin: pinmux_P8_30_pruin_pin {
+ pinctrl-single,pins = <0x0ec 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+ P8_30_hdmi_pin: pinmux_P8_30_hdmi_pin {
+ pinctrl-single,pins = <0x0ec 0x00>; }; /* lcd_ac_bias_en.lcd_ac_bias_en, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+
+ /* P8_31 (ZCZ ball V4 ) hdmi */
+ P8_31_default_pin: pinmux_P8_31_default_pin {
+ pinctrl-single,pins = <0x0d8 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_31_gpio_pin: pinmux_P8_31_gpio_pin {
+ pinctrl-single,pins = <0x0d8 0x2F>; }; /* Mode 7, RxActive */
+ P8_31_gpio_pu_pin: pinmux_P8_31_gpio_pu_pin {
+ pinctrl-single,pins = <0x0d8 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_31_gpio_pd_pin: pinmux_P8_31_gpio_pd_pin {
+ pinctrl-single,pins = <0x0d8 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_31_uart_pin: pinmux_P8_31_uart_pin {
+ pinctrl-single,pins = <0x0d8 0x24>; }; /* Mode 4, Pull-Down, RxActive */
+ P8_31_hdmi_pin: pinmux_P8_31_hdmi_pin {
+ pinctrl-single,pins = <0x0d8 0x08>; }; /* lcd_data14.lcd_data14, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+
+ /* P8_32 (ZCZ ball T5 ) hdmi */
+ P8_32_default_pin: pinmux_P8_32_default_pin {
+ pinctrl-single,pins = <0x0dc 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_32_gpio_pin: pinmux_P8_32_gpio_pin {
+ pinctrl-single,pins = <0x0dc 0x2F>; }; /* Mode 7, RxActive */
+ P8_32_gpio_pu_pin: pinmux_P8_32_gpio_pu_pin {
+ pinctrl-single,pins = <0x0dc 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_32_gpio_pd_pin: pinmux_P8_32_gpio_pd_pin {
+ pinctrl-single,pins = <0x0dc 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_32_uart_pin: pinmux_P8_32_uart_pin {
+ pinctrl-single,pins = <0x0dc 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+ P8_32_hdmi_pin: pinmux_P8_32_hdmi_pin {
+ pinctrl-single,pins = <0x0dc 0x08>; }; /* lcd_data15.lcd_data15, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+
+ /* P8_33 (ZCZ ball V3 ) hdmi */
+ P8_33_default_pin: pinmux_P8_33_default_pin {
+ pinctrl-single,pins = <0x0d4 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_33_gpio_pin: pinmux_P8_33_gpio_pin {
+ pinctrl-single,pins = <0x0d4 0x2F>; }; /* Mode 7, RxActive */
+ P8_33_gpio_pu_pin: pinmux_P8_33_gpio_pu_pin {
+ pinctrl-single,pins = <0x0d4 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_33_gpio_pd_pin: pinmux_P8_33_gpio_pd_pin {
+ pinctrl-single,pins = <0x0d4 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_33_hdmi_pin: pinmux_P8_33_hdmi_pin {
+ pinctrl-single,pins = <0x0d4 0x08>; }; /* lcd_data13.lcd_data13, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+
+ /* P8_34 (ZCZ ball U4 ) hdmi */
+ P8_34_default_pin: pinmux_P8_34_default_pin {
+ pinctrl-single,pins = <0x0cc 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_34_gpio_pin: pinmux_P8_34_gpio_pin {
+ pinctrl-single,pins = <0x0cc 0x2F>; }; /* Mode 7, RxActive */
+ P8_34_gpio_pu_pin: pinmux_P8_34_gpio_pu_pin {
+ pinctrl-single,pins = <0x0cc 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_34_gpio_pd_pin: pinmux_P8_34_gpio_pd_pin {
+ pinctrl-single,pins = <0x0cc 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_34_pwm_pin: pinmux_P8_34_pwm_pin {
+ pinctrl-single,pins = <0x0cc 0x22>; }; /* Mode 2, Pull-Down, RxActive */
+ P8_34_hdmi_pin: pinmux_P8_34_hdmi_pin {
+ pinctrl-single,pins = <0x0cc 0x08>; }; /* lcd_data11.lcd_data11, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+
+ /* P8_35 (ZCZ ball V2 ) hdmi */
+ P8_35_default_pin: pinmux_P8_35_default_pin {
+ pinctrl-single,pins = <0x0d0 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_35_gpio_pin: pinmux_P8_35_gpio_pin {
+ pinctrl-single,pins = <0x0d0 0x2F>; }; /* Mode 7, RxActive */
+ P8_35_gpio_pu_pin: pinmux_P8_35_gpio_pu_pin {
+ pinctrl-single,pins = <0x0d0 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_35_gpio_pd_pin: pinmux_P8_35_gpio_pd_pin {
+ pinctrl-single,pins = <0x0d0 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_35_hdmi_pin: pinmux_P8_35_hdmi_pin {
+ pinctrl-single,pins = <0x0d0 0x08>; }; /* lcd_data12.lcd_data12, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+
+ /* P8_36 (ZCZ ball U3 ) hdmi */
+ P8_36_default_pin: pinmux_P8_36_default_pin {
+ pinctrl-single,pins = <0x0c8 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_36_gpio_pin: pinmux_P8_36_gpio_pin {
+ pinctrl-single,pins = <0x0c8 0x2F>; }; /* Mode 7, RxActive */
+ P8_36_gpio_pu_pin: pinmux_P8_36_gpio_pu_pin {
+ pinctrl-single,pins = <0x0c8 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_36_gpio_pd_pin: pinmux_P8_36_gpio_pd_pin {
+ pinctrl-single,pins = <0x0c8 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_36_pwm_pin: pinmux_P8_36_pwm_pin {
+ pinctrl-single,pins = <0x0c8 0x22>; }; /* Mode 2, Pull-Down, RxActive */
+ P8_36_hdmi_pin: pinmux_P8_36_hdmi_pin {
+ pinctrl-single,pins = <0x0c8 0x08>; }; /* lcd_data10.lcd_data10, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+
+ /* P8_37 (ZCZ ball U1 ) hdmi */
+ P8_37_default_pin: pinmux_P8_37_default_pin {
+ pinctrl-single,pins = <0x0c0 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_37_gpio_pin: pinmux_P8_37_gpio_pin {
+ pinctrl-single,pins = <0x0c0 0x2F>; }; /* Mode 7, RxActive */
+ P8_37_gpio_pu_pin: pinmux_P8_37_gpio_pu_pin {
+ pinctrl-single,pins = <0x0c0 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_37_gpio_pd_pin: pinmux_P8_37_gpio_pd_pin {
+ pinctrl-single,pins = <0x0c0 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_37_uart_pin: pinmux_P8_37_uart_pin {
+ pinctrl-single,pins = <0x0c0 0x04>; }; /* Mode 4, Pull-Down*/
+ P8_37_pwm_pin: pinmux_P8_37_pwm_pin {
+ pinctrl-single,pins = <0x0c0 0x02>; }; /* Mode 2, Pull-Down*/
+ P8_37_hdmi_pin: pinmux_P8_37_hdmi_pin {
+ pinctrl-single,pins = <0x0c0 0x08>; }; /* lcd_data8.lcd_data8, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+
+
+ /* P8_38 (ZCZ ball U2 ) hdmi */
+ P8_38_default_pin: pinmux_P8_38_default_pin {
+ pinctrl-single,pins = <0x0c4 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_38_gpio_pin: pinmux_P8_38_gpio_pin {
+ pinctrl-single,pins = <0x0c4 0x2F>; }; /* Mode 7, RxActive */
+ P8_38_gpio_pu_pin: pinmux_P8_38_gpio_pu_pin {
+ pinctrl-single,pins = <0x0c4 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_38_gpio_pd_pin: pinmux_P8_38_gpio_pd_pin {
+ pinctrl-single,pins = <0x0c4 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_38_uart_pin: pinmux_P8_38_uart_pin {
+ pinctrl-single,pins = <0x0c4 0x24>; }; /* Mode 4, Pull-Down, RxActive */
+ P8_38_pwm_pin: pinmux_P8_38_pwm_pin {
+ pinctrl-single,pins = <0x0c4 0x22>; }; /* Mode 2, Pull-Down, RxActive */
+ P8_38_hdmi_pin: pinmux_P8_38_hdmi_pin {
+ pinctrl-single,pins = <0x0c4 0x08>; }; /* lcd_data9.lcd_data9, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+
+
+ /* P8_39 (ZCZ ball T3 ) hdmi */
+ P8_39_default_pin: pinmux_P8_39_default_pin {
+ pinctrl-single,pins = <0x0b8 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_39_gpio_pin: pinmux_P8_39_gpio_pin {
+ pinctrl-single,pins = <0x0b8 0x2F>; }; /* Mode 7, RxActive */
+ P8_39_gpio_pu_pin: pinmux_P8_39_gpio_pu_pin {
+ pinctrl-single,pins = <0x0b8 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_39_gpio_pd_pin: pinmux_P8_39_gpio_pd_pin {
+ pinctrl-single,pins = <0x0b8 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_39_pruout_pin: pinmux_P8_39_pruout_pin {
+ pinctrl-single,pins = <0x0b8 0x05>; }; /* Mode 5, Pull-Down*/
+ P8_39_pruin_pin: pinmux_P8_39_pruin_pin {
+ pinctrl-single,pins = <0x0b8 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+ P8_39_hdmi_pin: pinmux_P8_39_hdmi_pin {
+ pinctrl-single,pins = <0x0b8 0x08>; }; /* lcd_data6.lcd_data6, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+
+ /* P8_40 (ZCZ ball T4 ) hdmi */
+ P8_40_default_pin: pinmux_P8_40_default_pin {
+ pinctrl-single,pins = <0x0bc 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_40_gpio_pin: pinmux_P8_40_gpio_pin {
+ pinctrl-single,pins = <0x0bc 0x2F>; }; /* Mode 7, RxActive */
+ P8_40_gpio_pu_pin: pinmux_P8_40_gpio_pu_pin {
+ pinctrl-single,pins = <0x0bc 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_40_gpio_pd_pin: pinmux_P8_40_gpio_pd_pin {
+ pinctrl-single,pins = <0x0bc 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_40_pruout_pin: pinmux_P8_40_pruout_pin {
+ pinctrl-single,pins = <0x0bc 0x05>; }; /* Mode 5, Pull-Down*/
+ P8_40_pruin_pin: pinmux_P8_40_pruin_pin {
+ pinctrl-single,pins = <0x0bc 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+ P8_40_hdmi_pin: pinmux_P8_40_hdmi_pin {
+ pinctrl-single,pins = <0x0bc 0x08>; }; /* lcd_data7.lcd_data7, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+
+ /* P8_41 (ZCZ ball T1 ) hdmi */
+ P8_41_default_pin: pinmux_P8_41_default_pin {
+ pinctrl-single,pins = <0x0b0 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_41_gpio_pin: pinmux_P8_41_gpio_pin {
+ pinctrl-single,pins = <0x0b0 0x2F>; }; /* Mode 7, RxActive */
+ P8_41_gpio_pu_pin: pinmux_P8_41_gpio_pu_pin {
+ pinctrl-single,pins = <0x0b0 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_41_gpio_pd_pin: pinmux_P8_41_gpio_pd_pin {
+ pinctrl-single,pins = <0x0b0 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_41_pruout_pin: pinmux_P8_41_pruout_pin {
+ pinctrl-single,pins = <0x0b0 0x05>; }; /* Mode 5, Pull-Down*/
+ P8_41_pruin_pin: pinmux_P8_41_pruin_pin {
+ pinctrl-single,pins = <0x0b0 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+ P8_41_hdmi_pin: pinmux_P8_41_hdmi_pin {
+ pinctrl-single,pins = <0x0b0 0x08>; }; /* lcd_data4.lcd_data4, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+
+ /* P8_42 (ZCZ ball T2 ) hdmi */
+ P8_42_default_pin: pinmux_P8_42_default_pin {
+ pinctrl-single,pins = <0x0b4 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_42_gpio_pin: pinmux_P8_42_gpio_pin {
+ pinctrl-single,pins = <0x0b4 0x2F>; }; /* Mode 7, RxActive */
+ P8_42_gpio_pu_pin: pinmux_P8_42_gpio_pu_pin {
+ pinctrl-single,pins = <0x0b4 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_42_gpio_pd_pin: pinmux_P8_42_gpio_pd_pin {
+ pinctrl-single,pins = <0x0b4 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_42_pruout_pin: pinmux_P8_42_pruout_pin {
+ pinctrl-single,pins = <0x0b4 0x05>; }; /* Mode 5, Pull-Down*/
+ P8_42_pruin_pin: pinmux_P8_42_pruin_pin {
+ pinctrl-single,pins = <0x0b4 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+ P8_42_hdmi_pin: pinmux_P8_42_hdmi_pin {
+ pinctrl-single,pins = <0x0b4 0x08>; }; /* lcd_data5.lcd_data5, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+
+ /* P8_43 (ZCZ ball R3 ) hdmi */
+ P8_43_default_pin: pinmux_P8_43_default_pin {
+ pinctrl-single,pins = <0x0a8 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_43_gpio_pin: pinmux_P8_43_gpio_pin {
+ pinctrl-single,pins = <0x0a8 0x2F>; }; /* Mode 7, RxActive */
+ P8_43_gpio_pu_pin: pinmux_P8_43_gpio_pu_pin {
+ pinctrl-single,pins = <0x0a8 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_43_gpio_pd_pin: pinmux_P8_43_gpio_pd_pin {
+ pinctrl-single,pins = <0x0a8 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_43_pruout_pin: pinmux_P8_43_pruout_pin {
+ pinctrl-single,pins = <0x0a8 0x05>; }; /* Mode 5, Pull-Down*/
+ P8_43_pruin_pin: pinmux_P8_43_pruin_pin {
+ pinctrl-single,pins = <0x0a8 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+ P8_43_pwm_pin: pinmux_P8_43_pwm_pin {
+ pinctrl-single,pins = <0x0a8 0x03>; }; /* Mode 3, Pull-Down */
+ P8_43_hdmi_pin: pinmux_P8_43_hdmi_pin {
+ pinctrl-single,pins = <0x0a8 0x08>; }; /* lcd_data2.lcd_data2, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+
+ /* P8_44 (ZCZ ball R4 ) hdmi */
+ P8_44_default_pin: pinmux_P8_44_default_pin {
+ pinctrl-single,pins = <0x0ac 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_44_gpio_pin: pinmux_P8_44_gpio_pin {
+ pinctrl-single,pins = <0x0ac 0x2F>; }; /* Mode 7, RxActive */
+ P8_44_gpio_pu_pin: pinmux_P8_44_gpio_pu_pin {
+ pinctrl-single,pins = <0x0ac 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_44_gpio_pd_pin: pinmux_P8_44_gpio_pd_pin {
+ pinctrl-single,pins = <0x0ac 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_44_pruout_pin: pinmux_P8_44_pruout_pin {
+ pinctrl-single,pins = <0x0ac 0x05>; }; /* Mode 5, Pull-Down*/
+ P8_44_pruin_pin: pinmux_P8_44_pruin_pin {
+ pinctrl-single,pins = <0x0ac 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+ P8_44_pwm_pin: pinmux_P8_44_pwm_pin {
+ pinctrl-single,pins = <0x0ac 0x23>; }; /* Mode 3, Pull-Down, RxActive */
+ P8_44_hdmi_pin: pinmux_P8_44_hdmi_pin {
+ pinctrl-single,pins = <0x0ac 0x08>; }; /* lcd_data3.lcd_data3, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+
+ /* P8_45 (ZCZ ball R1 ) hdmi */
+ P8_45_default_pin: pinmux_P8_45_default_pin {
+ pinctrl-single,pins = <0x0a0 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_45_gpio_pin: pinmux_P8_45_gpio_pin {
+ pinctrl-single,pins = <0x0a0 0x2F>; }; /* Mode 7, RxActive */
+ P8_45_gpio_pu_pin: pinmux_P8_45_gpio_pu_pin {
+ pinctrl-single,pins = <0x0a0 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_45_gpio_pd_pin: pinmux_P8_45_gpio_pd_pin {
+ pinctrl-single,pins = <0x0a0 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_45_pruout_pin: pinmux_P8_45_pruout_pin {
+ pinctrl-single,pins = <0x0a0 0x05>; }; /* Mode 5, Pull-Down*/
+ P8_45_pruin_pin: pinmux_P8_45_pruin_pin {
+ pinctrl-single,pins = <0x0a0 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+ P8_45_pwm_pin: pinmux_P8_45_pwm_pin {
+ pinctrl-single,pins = <0x0a0 0x03>; }; /* Mode 3, Pull-Down*/
+ P8_45_hdmi_pin: pinmux_P8_45_hdmi_pin {
+ pinctrl-single,pins = <0x0a0 0x08>; }; /* lcd_data0.lcd_data0, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+
+ /* P8_46 (ZCZ ball R2 ) hdmi */
+ P8_46_default_pin: pinmux_P8_46_default_pin {
+ pinctrl-single,pins = <0x0a4 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_46_gpio_pin: pinmux_P8_46_gpio_pin {
+ pinctrl-single,pins = <0x0a4 0x2F>; }; /* Mode 7, RxActive */
+ P8_46_gpio_pu_pin: pinmux_P8_46_gpio_pu_pin {
+ pinctrl-single,pins = <0x0a4 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P8_46_gpio_pd_pin: pinmux_P8_46_gpio_pd_pin {
+ pinctrl-single,pins = <0x0a4 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P8_46_pruout_pin: pinmux_P8_46_pruout_pin {
+ pinctrl-single,pins = <0x0a4 0x05>; }; /* Mode 5, Pull-Down*/
+ P8_46_pruin_pin: pinmux_P8_46_pruin_pin {
+ pinctrl-single,pins = <0x0a4 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+ P8_46_pwm_pin: pinmux_P8_46_pwm_pin {
+ pinctrl-single,pins = <0x0a4 0x03>; }; /* Mode 3, Pull-Down*/
+ P8_46_hdmi_pin: pinmux_P8_46_hdmi_pin {
+ pinctrl-single,pins = <0x0a4 0x08>; }; /* lcd_data1.lcd_data1, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+
+ /************************/
+ /* P9 Header */
+ /************************/
+
+ /* P9_01 GND */
+ /* P9_02 GND */
+ /* P9_03 3.3V */
+ /* P9_04 3.3V */
+ /* P9_05 VDD_5V */
+ /* P9_06 VDD_5V */
+ /* P9_07 SYS_5V */
+ /* P9_08 SYS_5V */
+ /* P9_09 PWR_BUT */
+ /* P9_10 (ZCZ ball A10) RESETn */
+
+ /* P9_11 (ZCZ ball T17) */
+ P9_11_default_pin: pinmux_P9_11_default_pin {
+ pinctrl-single,pins = <0x070 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_11_gpio_pin: pinmux_P9_11_gpio_pin {
+ pinctrl-single,pins = <0x070 0x2F>; }; /* Mode 7, RxActive */
+ P9_11_gpio_pu_pin: pinmux_P9_11_gpio_pu_pin {
+ pinctrl-single,pins = <0x070 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_11_gpio_pd_pin: pinmux_P9_11_gpio_pd_pin {
+ pinctrl-single,pins = <0x070 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_11_uart_pin: pinmux_P9_11_uart_pin {
+ pinctrl-single,pins = <0x070 0x36>; }; /* Mode 6, Pull-Up, RxActive */
+
+ /* P9_12 (ZCZ ball U18) */
+ P9_12_default_pin: pinmux_P9_12_default_pin {
+ pinctrl-single,pins = <0x078 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_12_gpio_pin: pinmux_P9_12_gpio_pin {
+ pinctrl-single,pins = <0x078 0x2F>; }; /* Mode 7, RxActive */
+ P9_12_gpio_pu_pin: pinmux_P9_12_gpio_pu_pin {
+ pinctrl-single,pins = <0x078 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_12_gpio_pd_pin: pinmux_P9_12_gpio_pd_pin {
+ pinctrl-single,pins = <0x078 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+
+ /* P9_13 (ZCZ ball U17) */
+ P9_13_default_pin: pinmux_P9_13_default_pin {
+ pinctrl-single,pins = <0x074 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_13_gpio_pin: pinmux_P9_13_gpio_pin {
+ pinctrl-single,pins = <0x074 0x2F>; }; /* Mode 7, RxActive */
+ P9_13_gpio_pu_pin: pinmux_P9_13_gpio_pu_pin {
+ pinctrl-single,pins = <0x074 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_13_gpio_pd_pin: pinmux_P9_13_gpio_pd_pin {
+ pinctrl-single,pins = <0x074 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_13_uart_pin: pinmux_P9_13_uart_pin {
+ pinctrl-single,pins = <0x074 0x36>; }; /* Mode 6, Pull-Up, RxActive */
+
+ /* P9_14 (ZCZ ball U14) */
+ P9_14_default_pin: pinmux_P9_14_default_pin {
+ pinctrl-single,pins = <0x048 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_14_gpio_pin: pinmux_P9_14_gpio_pin {
+ pinctrl-single,pins = <0x048 0x2F>; }; /* Mode 7, RxActive */
+ P9_14_gpio_pu_pin: pinmux_P9_14_gpio_pu_pin {
+ pinctrl-single,pins = <0x048 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_14_gpio_pd_pin: pinmux_P9_14_gpio_pd_pin {
+ pinctrl-single,pins = <0x048 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_14_pwm_pin: pinmux_P9_14_pwm_pin {
+ pinctrl-single,pins = <0x048 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+
+ /* P9_15 (ZCZ ball R13) */
+ P9_15_default_pin: pinmux_P9_15_default_pin {
+ pinctrl-single,pins = <0x040 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_15_gpio_pin: pinmux_P9_15_gpio_pin {
+ pinctrl-single,pins = <0x040 0x2F>; }; /* Mode 7, RxActive */
+ P9_15_gpio_pu_pin: pinmux_P9_15_gpio_pu_pin {
+ pinctrl-single,pins = <0x040 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_15_gpio_pd_pin: pinmux_P9_15_gpio_pd_pin {
+ pinctrl-single,pins = <0x040 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_15_pwm_pin: pinmux_P9_15_pwm_pin {
+ pinctrl-single,pins = <0x040 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+
+ /* P9_16 (ZCZ ball T14) */
+ P9_16_default_pin: pinmux_P9_16_default_pin {
+ pinctrl-single,pins = <0x04c 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_16_gpio_pin: pinmux_P9_16_gpio_pin {
+ pinctrl-single,pins = <0x04c 0x2F>; }; /* Mode 7, RxActive */
+ P9_16_gpio_pu_pin: pinmux_P9_16_gpio_pu_pin {
+ pinctrl-single,pins = <0x04c 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_16_gpio_pd_pin: pinmux_P9_16_gpio_pd_pin {
+ pinctrl-single,pins = <0x04c 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_16_pwm_pin: pinmux_P9_16_pwm_pin {
+ pinctrl-single,pins = <0x04c 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+
+ /* P9_17 (ZCZ ball A16) */
+ P9_17_default_pin: pinmux_P9_17_default_pin {
+ pinctrl-single,pins = <0x15c 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_17_gpio_pin: pinmux_P9_17_gpio_pin {
+ pinctrl-single,pins = <0x15c 0x2F>; }; /* Mode 7, RxActive */
+ P9_17_gpio_pu_pin: pinmux_P9_17_gpio_pu_pin {
+ pinctrl-single,pins = <0x15c 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_17_gpio_pd_pin: pinmux_P9_17_gpio_pd_pin {
+ pinctrl-single,pins = <0x15c 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_17_spi_pin: pinmux_P9_17_spi_pin {
+ pinctrl-single,pins = <0x15c 0x30>; }; /* Mode 0, Pull-Up, RxActive */
+ P9_17_i2c_pin: pinmux_P9_17_i2c_pin {
+ pinctrl-single,pins = <0x15c 0x32>; }; /* Mode 2, Pull-Up, RxActive */
+ P9_17_pwm_pin: pinmux_P9_17_pwm_pin {
+ pinctrl-single,pins = <0x15c 0x33>; }; /* Mode 3, Pull-Up, RxActive */
+
+ /* P9_18 (ZCZ ball B16) */
+ P9_18_default_pin: pinmux_P9_18_default_pin {
+ pinctrl-single,pins = <0x158 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_18_gpio_pin: pinmux_P9_18_gpio_pin {
+ pinctrl-single,pins = <0x158 0x2F>; }; /* Mode 7, RxActive */
+ P9_18_gpio_pu_pin: pinmux_P9_18_gpio_pu_pin {
+ pinctrl-single,pins = <0x158 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_18_gpio_pd_pin: pinmux_P9_18_gpio_pd_pin {
+ pinctrl-single,pins = <0x158 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_18_spi_pin: pinmux_P9_18_spi_pin {
+ pinctrl-single,pins = <0x158 0x30>; }; /* Mode 0, Pull-Up, RxActive */
+ P9_18_i2c_pin: pinmux_P9_18_i2c_pin {
+ pinctrl-single,pins = <0x158 0x32>; }; /* Mode 2, Pull-Up, RxActive */
+ P9_18_pwm_pin: pinmux_P9_18_pwm_pin {
+ pinctrl-single,pins = <0x158 0x33>; }; /* Mode 3, Pull-Up, RxActive */
+
+ /* P9_19 (ZCZ ball D17) */
+ P9_19_default_pin: pinmux_P9_19_default_pin {
+ pinctrl-single,pins = <0x17c 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_19_gpio_pin: pinmux_P9_19_gpio_pin {
+ pinctrl-single,pins = <0x17c 0x2F>; }; /* Mode 7, RxActive */
+ P9_19_gpio_pu_pin: pinmux_P9_19_gpio_pu_pin {
+ pinctrl-single,pins = <0x17c 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_19_gpio_pd_pin: pinmux_P9_19_gpio_pd_pin {
+ pinctrl-single,pins = <0x17c 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_19_can_pin: pinmux_P9_19_can_pin {
+ pinctrl-single,pins = <0x17c 0x32>; }; /* Mode 2, Pull-Up, RxActive */
+ P9_19_i2c_pin: pinmux_P9_19_i2c_pin {
+ pinctrl-single,pins = <0x17c 0x73>; }; /* (SLEWCTRL_SLOW | PIN_INPUT_PULLUP | MUX_MODE3) */
+
+ /* P9_20 (ZCZ ball D18) */
+ P9_20_default_pin: pinmux_P9_20_default_pin {
+ pinctrl-single,pins = <0x178 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_20_gpio_pin: pinmux_P9_20_gpio_pin {
+ pinctrl-single,pins = <0x178 0x2F>; }; /* Mode 7, RxActive */
+ P9_20_gpio_pu_pin: pinmux_P9_20_gpio_pu_pin {
+ pinctrl-single,pins = <0x178 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_20_gpio_pd_pin: pinmux_P9_20_gpio_pd_pin {
+ pinctrl-single,pins = <0x178 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_20_can_pin: pinmux_P9_20_can_pin {
+ pinctrl-single,pins = <0x178 0x12>; }; /* Mode 2, Pull-Up, RxActive */
+ P9_20_i2c_pin: pinmux_P9_20_i2c_pin {
+ pinctrl-single,pins = <0x178 0x73>; }; /* (SLEWCTRL_SLOW | PIN_INPUT_PULLUP | MUX_MODE3) */
+
+ /* P9_21 (ZCZ ball B17) */
+ P9_21_default_pin: pinmux_P9_21_default_pin {
+ pinctrl-single,pins = <0x154 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_21_gpio_pin: pinmux_P9_21_gpio_pin {
+ pinctrl-single,pins = <0x154 0x2F>; }; /* Mode 7, RxActive */
+ P9_21_gpio_pu_pin: pinmux_P9_21_gpio_pu_pin {
+ pinctrl-single,pins = <0x154 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_21_gpio_pd_pin: pinmux_P9_21_gpio_pd_pin {
+ pinctrl-single,pins = <0x154 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_21_spi_pin: pinmux_P9_21_spi_pin {
+ pinctrl-single,pins = <0x154 0x30>; }; /* Mode 0, Pull-Up, RxActive */
+ P9_21_uart_pin: pinmux_P9_21_uart_pin {
+ pinctrl-single,pins = <0x154 0x31>; }; /* Mode 1, Pull-Up, RxActive */
+ P9_21_i2c_pin: pinmux_P9_21_i2c_pin {
+ pinctrl-single,pins = <0x154 0x32>; }; /* Mode 2, Pull-Up, RxActive */
+ P9_21_pwm_pin: pinmux_P9_21_pwm_pin {
+ pinctrl-single,pins = <0x154 0x33>; }; /* Mode 3, Pull-Up, RxActive */
+
+ /* P9_22 (ZCZ ball A17) */
+ P9_22_default_pin: pinmux_P9_22_default_pin {
+ pinctrl-single,pins = <0x150 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_22_gpio_pin: pinmux_P9_22_gpio_pin {
+ pinctrl-single,pins = <0x150 0x2F>; }; /* Mode 7, RxActive */
+ P9_22_gpio_pu_pin: pinmux_P9_22_gpio_pu_pin {
+ pinctrl-single,pins = <0x150 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_22_gpio_pd_pin: pinmux_P9_22_gpio_pd_pin {
+ pinctrl-single,pins = <0x150 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_22_spi_pin: pinmux_P9_22_spi_pin {
+ pinctrl-single,pins = <0x150 0x30>; }; /* Mode 0, Pull-Up, RxActive */
+ P9_22_uart_pin: pinmux_P9_22_uart_pin {
+ pinctrl-single,pins = <0x150 0x31>; }; /* Mode 1, Pull-Up, RxActive */
+ P9_22_i2c_pin: pinmux_P9_22_i2c_pin {
+ pinctrl-single,pins = <0x150 0x32>; }; /* Mode 2, Pull-Up, RxActive */
+ P9_22_pwm_pin: pinmux_P9_22_pwm_pin {
+ pinctrl-single,pins = <0x150 0x33>; }; /* Mode 3, Pull-Up, RxActive */
+
+ /* P9_23 (ZCZ ball V14) */
+ P9_23_default_pin: pinmux_P9_23_default_pin {
+ pinctrl-single,pins = <0x044 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_23_gpio_pin: pinmux_P9_23_gpio_pin {
+ pinctrl-single,pins = <0x044 0x2F>; }; /* Mode 7, RxActive */
+ P9_23_gpio_pu_pin: pinmux_P9_23_gpio_pu_pin {
+ pinctrl-single,pins = <0x044 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_23_gpio_pd_pin: pinmux_P9_23_gpio_pd_pin {
+ pinctrl-single,pins = <0x044 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_23_pwm_pin: pinmux_P9_23_pwm_pin {
+ pinctrl-single,pins = <0x044 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+
+ /* P9_24 (ZCZ ball D15) */
+ P9_24_default_pin: pinmux_P9_24_default_pin {
+ pinctrl-single,pins = <0x184 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_24_gpio_pin: pinmux_P9_24_gpio_pin {
+ pinctrl-single,pins = <0x184 0x2F>; }; /* Mode 7, RxActive */
+ P9_24_gpio_pu_pin: pinmux_P9_24_gpio_pu_pin {
+ pinctrl-single,pins = <0x184 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_24_gpio_pd_pin: pinmux_P9_24_gpio_pd_pin {
+ pinctrl-single,pins = <0x184 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_24_uart_pin: pinmux_P9_24_uart_pin {
+ pinctrl-single,pins = <0x184 0x30>; }; /* Mode 0, Pull-Up, RxActive */
+ P9_24_can_pin: pinmux_P9_24_can_pin {
+ pinctrl-single,pins = <0x184 0x32>; }; /* Mode 2, Pull-Up, RxActive */
+ P9_24_i2c_pin: pinmux_P9_24_i2c_pin {
+ pinctrl-single,pins = <0x184 0x33>; }; /* Mode 3, Pull-Up, RxActive */
+ P9_24_pruin_pin: pinmux_P9_24_pruin_pin {
+ pinctrl-single,pins = <0x184 0x36>; }; /* Mode 6, Pull-Up, RxActive */
+
+ /* P9_25 (ZCZ ball A14) Audio */
+ P9_25_default_pin: pinmux_P9_25_default_pin {
+ pinctrl-single,pins = <0x1ac 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_25_gpio_pin: pinmux_P9_25_gpio_pin {
+ pinctrl-single,pins = <0x1ac 0x2F>; }; /* Mode 7, RxActive */
+ P9_25_gpio_pu_pin: pinmux_P9_25_gpio_pu_pin {
+ pinctrl-single,pins = <0x1ac 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_25_gpio_pd_pin: pinmux_P9_25_gpio_pd_pin {
+ pinctrl-single,pins = <0x1ac 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_25_qep_pin: pinmux_P9_25_qep_pin {
+ pinctrl-single,pins = <0x1ac 0x21>; }; /* Mode 1, Pull-Down, RxActive */
+ P9_25_pruout_pin: pinmux_P9_25_pruout_pin {
+ pinctrl-single,pins = <0x1ac 0x25>; }; /* Mode 5, Pull-Down, RxActive */
+ P9_25_pruin_pin: pinmux_P9_25_pruin_pin {
+ pinctrl-single,pins = <0x1ac 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+ P9_25_audio_pin: pinmux_P9_25_audio_pin {
+ pinctrl-single,pins = <0x1ac (PIN_INPUT_PULLUP | MUX_MODE0)>; }; /* mcasp0_ahclkx.mcasp0_ahclkx */
+
+ /* P9_26 (ZCZ ball D16) */
+ P9_26_default_pin: pinmux_P9_26_default_pin {
+ pinctrl-single,pins = <0x180 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_26_gpio_pin: pinmux_P9_26_gpio_pin {
+ pinctrl-single,pins = <0x180 0x2F>; }; /* Mode 7, RxActive */
+ P9_26_gpio_pu_pin: pinmux_P9_26_gpio_pu_pin {
+ pinctrl-single,pins = <0x180 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_26_gpio_pd_pin: pinmux_P9_26_gpio_pd_pin {
+ pinctrl-single,pins = <0x180 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_26_uart_pin: pinmux_P9_26_uart_pin {
+ pinctrl-single,pins = <0x180 0x30>; }; /* Mode 0, Pull-Up, RxActive */
+ P9_26_can_pin: pinmux_P9_26_can_pin {
+ pinctrl-single,pins = <0x180 0x12>; }; /* Mode 2, Pull-Up, RxActive */
+ P9_26_i2c_pin: pinmux_P9_26_i2c_pin {
+ pinctrl-single,pins = <0x180 0x33>; }; /* Mode 3, Pull-Up, RxActive */
+ P9_26_pruin_pin: pinmux_P9_26_pruin_pin {
+ pinctrl-single,pins = <0x180 0x36>; }; /* Mode 6, Pull-Up, RxActive */
+
+ /* P9_27 (ZCZ ball C13) */
+ P9_27_default_pin: pinmux_P9_27_default_pin {
+ pinctrl-single,pins = <0x1a4 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_27_gpio_pin: pinmux_P9_27_gpio_pin {
+ pinctrl-single,pins = <0x1a4 0x2F>; }; /* Mode 7, RxActive */
+ P9_27_gpio_pu_pin: pinmux_P9_27_gpio_pu_pin {
+ pinctrl-single,pins = <0x1a4 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_27_gpio_pd_pin: pinmux_P9_27_gpio_pd_pin {
+ pinctrl-single,pins = <0x1a4 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_27_qep_pin: pinmux_P9_27_qep_pin {
+ pinctrl-single,pins = <0x1a4 0x21>; }; /* Mode 1, Pull-Down, RxActive */
+ P9_27_pruout_pin: pinmux_P9_27_pruout_pin {
+ pinctrl-single,pins = <0x1a4 0x25>; }; /* Mode 5, Pull-Down, RxActive */
+ P9_27_pruin_pin: pinmux_P9_27_pruin_pin {
+ pinctrl-single,pins = <0x1a4 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+
+ /* P9_28 (ZCZ ball C12) Audio */
+ P9_28_default_pin: pinmux_P9_28_default_pin {
+ pinctrl-single,pins = <0x19c 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_28_gpio_pin: pinmux_P9_28_gpio_pin {
+ pinctrl-single,pins = <0x19c 0x2F>; }; /* Mode 7, RxActive */
+ P9_28_gpio_pu_pin: pinmux_P9_28_gpio_pu_pin {
+ pinctrl-single,pins = <0x19c 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_28_gpio_pd_pin: pinmux_P9_28_gpio_pd_pin {
+ pinctrl-single,pins = <0x19c 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_28_pwm_pin: pinmux_P9_28_pwm_pin {
+ pinctrl-single,pins = <0x19c 0x21>; }; /* Mode 1, Pull-Down, RxActive */
+ P9_28_spi_pin: pinmux_P9_28_spi_pin {
+ pinctrl-single,pins = <0x19c 0x23>; }; /* Mode 3, Pull-Down, RxActive */
+ P9_28_pwm2_pin: pinmux_P9_28_pwm2_pin {
+ pinctrl-single,pins = <0x19c 0x24>; }; /* Mode 4, Pull-Down, RxActive */
+ P9_28_pruout_pin: pinmux_P9_28_pruout_pin {
+ pinctrl-single,pins = <0x19c 0x25>; }; /* Mode 5, Pull-Down, RxActive */
+ P9_28_pruin_pin: pinmux_P9_28_pruin_pin {
+ pinctrl-single,pins = <0x19c 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+ P9_28_audio_pin: pinmux_P9_28_audio_pin {
+ pinctrl-single,pins = <0x19c (PIN_OUTPUT_PULLDOWN | MUX_MODE2)>; }; /* mcasp0_ahclkr.mcasp0_axr2 */
+
+ /* P9_29 (ZCZ ball B13) Audio */
+ P9_29_default_pin: pinmux_P9_29_default_pin {
+ pinctrl-single,pins = <0x194 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_29_gpio_pin: pinmux_P9_29_gpio_pin {
+ pinctrl-single,pins = <0x194 0x2F>; }; /* Mode 7, RxActive */
+ P9_29_gpio_pu_pin: pinmux_P9_29_gpio_pu_pin {
+ pinctrl-single,pins = <0x194 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_29_gpio_pd_pin: pinmux_P9_29_gpio_pd_pin {
+ pinctrl-single,pins = <0x194 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_29_pwm_pin: pinmux_P9_29_pwm_pin {
+ pinctrl-single,pins = <0x194 0x21>; }; /* Mode 1, Pull-Down, RxActive */
+ P9_29_spi_pin: pinmux_P9_29_spi_pin {
+ pinctrl-single,pins = <0x194 0x23>; }; /* Mode 3, Pull-Down, RxActive */
+ P9_29_pruout_pin: pinmux_P9_29_pruout_pin {
+ pinctrl-single,pins = <0x194 0x25>; }; /* Mode 5, Pull-Down, RxActive */
+ P9_29_pruin_pin: pinmux_P9_29_pruin_pin {
+ pinctrl-single,pins = <0x194 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+ P9_29_audio_pin: pinmux_P9_29_audio_pin {
+ pinctrl-single,pins = <0x194 (PIN_OUTPUT_PULLUP | MUX_MODE0)>; }; /* mcasp0_fsx.mcasp0_fsx */
+
+ /* P9_30 (ZCZ ball D12) */
+ P9_30_default_pin: pinmux_P9_30_default_pin {
+ pinctrl-single,pins = <0x198 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_30_gpio_pin: pinmux_P9_30_gpio_pin {
+ pinctrl-single,pins = <0x198 0x2F>; }; /* Mode 7, RxActive */
+ P9_30_gpio_pu_pin: pinmux_P9_30_gpio_pu_pin {
+ pinctrl-single,pins = <0x198 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_30_gpio_pd_pin: pinmux_P9_30_gpio_pd_pin {
+ pinctrl-single,pins = <0x198 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_30_pwm_pin: pinmux_P9_30_pwm_pin {
+ pinctrl-single,pins = <0x198 0x21>; }; /* Mode 1, Pull-Down, RxActive */
+ P9_30_spi_pin: pinmux_P9_30_spi_pin {
+ pinctrl-single,pins = <0x198 0x23>; }; /* Mode 3, Pull-Down, RxActive */
+ P9_30_pruout_pin: pinmux_P9_30_pruout_pin {
+ pinctrl-single,pins = <0x198 0x25>; }; /* Mode 5, Pull-Down, RxActive */
+ P9_30_pruin_pin: pinmux_P9_30_pruin_pin {
+ pinctrl-single,pins = <0x198 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+
+ /* P9_31 (ZCZ ball A13) Audio */
+ P9_31_default_pin: pinmux_P9_31_default_pin {
+ pinctrl-single,pins = <0x190 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_31_gpio_pin: pinmux_P9_31_gpio_pin {
+ pinctrl-single,pins = <0x190 0x2F>; }; /* Mode 7, RxActive */
+ P9_31_gpio_pu_pin: pinmux_P9_31_gpio_pu_pin {
+ pinctrl-single,pins = <0x190 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_31_gpio_pd_pin: pinmux_P9_31_gpio_pd_pin {
+ pinctrl-single,pins = <0x190 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_31_pwm_pin: pinmux_P9_31_pwm_pin {
+ pinctrl-single,pins = <0x190 0x21>; }; /* Mode 1, Pull-Down, RxActive */
+ P9_31_spi_pin: pinmux_P9_31_spi_pin {
+ pinctrl-single,pins = <0x190 0x23>; }; /* Mode 3, Pull-Down, RxActive */
+ P9_31_pruout_pin: pinmux_P9_31_pruout_pin {
+ pinctrl-single,pins = <0x190 0x25>; }; /* Mode 5, Pull-Down, RxActive */
+ P9_31_pruin_pin: pinmux_P9_31_pruin_pin {
+ pinctrl-single,pins = <0x190 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+ P9_31_audio_pin: pinmux_P9_31_audio_pin {
+ pinctrl-single,pins = <0x190 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)>; }; /* mcasp0_aclkx.mcasp0_aclkx */
+
+ /* P9_32 VADC */
+ /* P9_33 (ZCZ ball C8 ) AIN4 */
+ /* P9_34 AGND */
+ /* P9_35 (ZCZ ball A8 ) AIN6 */
+ /* P9_36 (ZCZ ball B8 ) AIN5 */
+ /* P9_37 (ZCZ ball B7 ) AIN2 */
+ /* P9_38 (ZCZ ball A7 ) AIN3 */
+ /* P9_39 (ZCZ ball B6 ) AIN0 */
+ /* P9_40 (ZCZ ball C7 ) AIN1 */
+
+ /* P9_41 (ZCZ ball D14) */
+ P9_41_default_pin: pinmux_P9_41_default_pin {
+ pinctrl-single,pins = <0x1b4 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_41_gpio_pin: pinmux_P9_41_gpio_pin {
+ pinctrl-single,pins = <0x1b4 0x2F>; }; /* Mode 7, RxActive */
+ P9_41_gpio_pu_pin: pinmux_P9_41_gpio_pu_pin {
+ pinctrl-single,pins = <0x1b4 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_41_gpio_pd_pin: pinmux_P9_41_gpio_pd_pin {
+ pinctrl-single,pins = <0x1b4 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_41_timer_pin: pinmux_P9_41_timer_pin {
+ pinctrl-single,pins = <0x1b4 0x24>; }; /* Mode 4, Pull-Down, RxActive */
+ P9_41_pruin_pin: pinmux_P9_41_pruin_pin {
+ pinctrl-single,pins = <0x1b4 0x25>; }; /* Mode 5, Pull-Down, RxActive */
+
+ /* P9_41.1 */
+ /* P9_91 (ZCZ ball D13) */
+ P9_91_default_pin: pinmux_P9_91_default_pin {
+ pinctrl-single,pins = <0x1a8 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_91_gpio_pin: pinmux_P9_91_gpio_pin {
+ pinctrl-single,pins = <0x1a8 0x2F>; }; /* Mode 7, RxActive */
+ P9_91_gpio_pu_pin: pinmux_P9_91_gpio_pu_pin {
+ pinctrl-single,pins = <0x1a8 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_91_gpio_pd_pin: pinmux_P9_91_gpio_pd_pin {
+ pinctrl-single,pins = <0x1a8 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_91_qep_pin: pinmux_P9_91_qep_pin {
+ pinctrl-single,pins = <0x1a8 0x21>; }; /* Mode 1, Pull-Down, RxActive */
+ P9_91_pruout_pin: pinmux_P9_91_pruout_pin {
+ pinctrl-single,pins = <0x1a8 0x25>; }; /* Mode 5, Pull-Down, RxActive */
+ P9_91_pruin_pin: pinmux_P9_91_pruin_pin {
+ pinctrl-single,pins = <0x1a8 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+
+ /* P9_42 (ZCZ ball C18) */
+ P9_42_default_pin: pinmux_P9_42_default_pin {
+ pinctrl-single,pins = <0x164 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_42_gpio_pin: pinmux_P9_42_gpio_pin {
+ pinctrl-single,pins = <0x164 0x2F>; }; /* Mode 7, RxActive */
+ P9_42_gpio_pu_pin: pinmux_P9_42_gpio_pu_pin {
+ pinctrl-single,pins = <0x164 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_42_gpio_pd_pin: pinmux_P9_42_gpio_pd_pin {
+ pinctrl-single,pins = <0x164 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_42_pwm_pin: pinmux_P9_42_pwm_pin {
+ pinctrl-single,pins = <0x164 0x20>; }; /* Mode 0, Pull-Down, RxActive */
+ P9_42_uart_pin: pinmux_P9_42_uart_pin {
+ pinctrl-single,pins = <0x164 0x21>; }; /* Mode 1, Pull-Down, RxActive */
+ P9_42_spics_pin: pinmux_P9_42_spics_pin {
+ pinctrl-single,pins = <0x164 0x22>; }; /* Mode 2, Pull-Down, RxActive */
+ P9_42_spiclk_pin: pinmux_P9_42_spiclk_pin {
+ pinctrl-single,pins = <0x164 0x24>; }; /* Mode 4, Pull-Down, RxActive */
+
+ /* P9_42.1 */
+ /* P9_92 (ZCZ ball B12) */
+ P9_92_default_pin: pinmux_P9_92_default_pin {
+ pinctrl-single,pins = <0x1a0 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_92_gpio_pin: pinmux_P9_92_gpio_pin {
+ pinctrl-single,pins = <0x1a0 0x2F>; }; /* Mode 7, RxActive */
+ P9_92_gpio_pu_pin: pinmux_P9_92_gpio_pu_pin {
+ pinctrl-single,pins = <0x1a0 0x37>; }; /* Mode 7, Pull-Up, RxActive */
+ P9_92_gpio_pd_pin: pinmux_P9_92_gpio_pd_pin {
+ pinctrl-single,pins = <0x1a0 0x27>; }; /* Mode 7, Pull-Down, RxActive */
+ P9_92_qep_pin: pinmux_P9_92_qep_pin {
+ pinctrl-single,pins = <0x1a0 0x21>; }; /* Mode 1, Pull-Down, RxActive */
+ P9_92_pruout_pin: pinmux_P9_92_pruout_pin {
+ pinctrl-single,pins = <0x1a0 0x25>; }; /* Mode 5, Pull-Down, RxActive */
+ P9_92_pruin_pin: pinmux_P9_92_pruin_pin {
+ pinctrl-single,pins = <0x1a0 0x26>; }; /* Mode 6, Pull-Down, RxActive */
+
+ /* P9_43 GND */
+ /* P9_44 GND */
+ /* P9_45 GND */
+ /* P9_46 GND */
+};
+
+/**********************************************************************/
+/* Pin Multiplex Helpers */
+/* */
+/* These provide userspace runtime pin configuration for the */
+/* BeagleBone cape expansion headers */
+/**********************************************************************/
+
+&ocp {
+ /************************/
+ /* P8 Header */
+ /************************/
+
+ P8_07_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "timer";
+ pinctrl-0 = <&P8_07_default_pin>;
+ pinctrl-1 = <&P8_07_gpio_pin>;
+ pinctrl-2 = <&P8_07_gpio_pu_pin>;
+ pinctrl-3 = <&P8_07_gpio_pd_pin>;
+ pinctrl-4 = <&P8_07_timer_pin>;
+ };
+
+ P8_08_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "timer";
+ pinctrl-0 = <&P8_08_default_pin>;
+ pinctrl-1 = <&P8_08_gpio_pin>;
+ pinctrl-2 = <&P8_08_gpio_pu_pin>;
+ pinctrl-3 = <&P8_08_gpio_pd_pin>;
+ pinctrl-4 = <&P8_08_timer_pin>;
+ };
+
+ P8_09_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "timer";
+ pinctrl-0 = <&P8_09_default_pin>;
+ pinctrl-1 = <&P8_09_gpio_pin>;
+ pinctrl-2 = <&P8_09_gpio_pu_pin>;
+ pinctrl-3 = <&P8_09_gpio_pd_pin>;
+ pinctrl-4 = <&P8_09_timer_pin>;
+ };
+
+ P8_10_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "timer";
+ pinctrl-0 = <&P8_10_default_pin>;
+ pinctrl-1 = <&P8_10_gpio_pin>;
+ pinctrl-2 = <&P8_10_gpio_pu_pin>;
+ pinctrl-3 = <&P8_10_gpio_pd_pin>;
+ pinctrl-4 = <&P8_10_timer_pin>;
+ };
+
+ P8_11_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "qep";
+ pinctrl-0 = <&P8_11_default_pin>;
+ pinctrl-1 = <&P8_11_gpio_pin>;
+ pinctrl-2 = <&P8_11_gpio_pu_pin>;
+ pinctrl-3 = <&P8_11_gpio_pd_pin>;
+ pinctrl-4 = <&P8_11_pruout_pin>;
+ pinctrl-5 = <&P8_11_qep_pin>;
+ };
+
+ P8_12_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "qep";
+ pinctrl-0 = <&P8_12_default_pin>;
+ pinctrl-1 = <&P8_12_gpio_pin>;
+ pinctrl-2 = <&P8_12_gpio_pu_pin>;
+ pinctrl-3 = <&P8_12_gpio_pd_pin>;
+ pinctrl-4 = <&P8_12_pruout_pin>;
+ pinctrl-5 = <&P8_12_qep_pin>;
+ };
+
+ P8_13_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm";
+ pinctrl-0 = <&P8_13_default_pin>;
+ pinctrl-1 = <&P8_13_gpio_pin>;
+ pinctrl-2 = <&P8_13_gpio_pu_pin>;
+ pinctrl-3 = <&P8_13_gpio_pd_pin>;
+ pinctrl-4 = <&P8_13_pwm_pin>;
+ };
+
+ P8_14_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm";
+ pinctrl-0 = <&P8_14_default_pin>;
+ pinctrl-1 = <&P8_14_gpio_pin>;
+ pinctrl-2 = <&P8_14_gpio_pu_pin>;
+ pinctrl-3 = <&P8_14_gpio_pd_pin>;
+ pinctrl-4 = <&P8_14_pwm_pin>;
+ };
+
+ P8_15_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruin", "qep";
+ pinctrl-0 = <&P8_15_default_pin>;
+ pinctrl-1 = <&P8_15_gpio_pin>;
+ pinctrl-2 = <&P8_15_gpio_pu_pin>;
+ pinctrl-3 = <&P8_15_gpio_pd_pin>;
+ pinctrl-4 = <&P8_15_pruin_pin>;
+ pinctrl-5 = <&P8_15_qep_pin>;
+ };
+
+ P8_16_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruin", "qep";
+ pinctrl-0 = <&P8_16_default_pin>;
+ pinctrl-1 = <&P8_16_gpio_pin>;
+ pinctrl-2 = <&P8_16_gpio_pu_pin>;
+ pinctrl-3 = <&P8_16_gpio_pd_pin>;
+ pinctrl-4 = <&P8_16_pruin_pin>;
+ pinctrl-5 = <&P8_16_qep_pin>;
+ };
+
+ P8_17_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm";
+ pinctrl-0 = <&P8_17_default_pin>;
+ pinctrl-1 = <&P8_17_gpio_pin>;
+ pinctrl-2 = <&P8_17_gpio_pu_pin>;
+ pinctrl-3 = <&P8_17_gpio_pd_pin>;
+ pinctrl-4 = <&P8_17_pwm_pin>;
+ };
+
+ P8_18_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio";
+ pinctrl-0 = <&P8_18_default_pin>;
+ pinctrl-1 = <&P8_18_gpio_pin>;
+ pinctrl-2 = <&P8_18_gpio_pu_pin>;
+ pinctrl-3 = <&P8_18_gpio_pd_pin>;
+ };
+
+ P8_19_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm";
+ pinctrl-0 = <&P8_19_default_pin>;
+ pinctrl-1 = <&P8_19_gpio_pin>;
+ pinctrl-2 = <&P8_19_gpio_pu_pin>;
+ pinctrl-3 = <&P8_19_gpio_pd_pin>;
+ pinctrl-4 = <&P8_19_pwm_pin>;
+ };
+
+ P8_26_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio";
+ pinctrl-0 = <&P8_26_default_pin>;
+ pinctrl-1 = <&P8_26_gpio_pin>;
+ pinctrl-2 = <&P8_26_gpio_pu_pin>;
+ pinctrl-3 = <&P8_26_gpio_pd_pin>;
+ };
+
+ P8_27_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "pruin", "hdmi";
+ pinctrl-0 = <&P8_27_default_pin>;
+ pinctrl-1 = <&P8_27_gpio_pin>;
+ pinctrl-2 = <&P8_27_gpio_pu_pin>;
+ pinctrl-3 = <&P8_27_gpio_pd_pin>;
+ pinctrl-4 = <&P8_27_pruout_pin>;
+ pinctrl-5 = <&P8_27_pruin_pin>;
+ pinctrl-6 = <&P8_27_hdmi_pin>;
+ };
+
+ P8_28_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "pruin", "hdmi";
+ pinctrl-0 = <&P8_28_default_pin>;
+ pinctrl-1 = <&P8_28_gpio_pin>;
+ pinctrl-2 = <&P8_28_gpio_pu_pin>;
+ pinctrl-3 = <&P8_28_gpio_pd_pin>;
+ pinctrl-4 = <&P8_28_pruout_pin>;
+ pinctrl-5 = <&P8_28_pruin_pin>;
+ pinctrl-6 = <&P8_28_hdmi_pin>;
+ };
+
+ P8_29_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "pruin", "hdmi";
+ pinctrl-0 = <&P8_29_default_pin>;
+ pinctrl-1 = <&P8_29_gpio_pin>;
+ pinctrl-2 = <&P8_29_gpio_pu_pin>;
+ pinctrl-3 = <&P8_29_gpio_pd_pin>;
+ pinctrl-4 = <&P8_29_pruout_pin>;
+ pinctrl-5 = <&P8_29_pruin_pin>;
+ pinctrl-6 = <&P8_29_hdmi_pin>;
+ };
+
+ P8_30_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "pruin", "hdmi";
+ pinctrl-0 = <&P8_30_default_pin>;
+ pinctrl-1 = <&P8_30_gpio_pin>;
+ pinctrl-2 = <&P8_30_gpio_pu_pin>;
+ pinctrl-3 = <&P8_30_gpio_pd_pin>;
+ pinctrl-4 = <&P8_30_pruout_pin>;
+ pinctrl-5 = <&P8_30_pruin_pin>;
+ pinctrl-6 = <&P8_30_hdmi_pin>;
+ };
+
+ P8_31_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd","uart", "hdmi";
+ pinctrl-0 = <&P8_31_default_pin>;
+ pinctrl-1 = <&P8_31_gpio_pin>;
+ pinctrl-2 = <&P8_31_gpio_pu_pin>;
+ pinctrl-3 = <&P8_31_gpio_pd_pin>;
+ pinctrl-4 = <&P8_31_uart_pin>;
+ pinctrl-5 = <&P8_31_hdmi_pin>;
+ };
+
+ P8_32_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "hdmi";
+ pinctrl-0 = <&P8_32_default_pin>;
+ pinctrl-1 = <&P8_32_gpio_pin>;
+ pinctrl-2 = <&P8_32_gpio_pu_pin>;
+ pinctrl-3 = <&P8_32_gpio_pd_pin>;
+ pinctrl-4 = <&P8_32_hdmi_pin>;
+ };
+
+ P8_33_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "hdmi";
+ pinctrl-0 = <&P8_33_default_pin>;
+ pinctrl-1 = <&P8_33_gpio_pin>;
+ pinctrl-2 = <&P8_33_gpio_pu_pin>;
+ pinctrl-3 = <&P8_33_gpio_pd_pin>;
+ pinctrl-4 = <&P8_33_hdmi_pin>;
+ };
+
+ P8_34_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd","pwm", "hdmi";
+ pinctrl-0 = <&P8_34_default_pin>;
+ pinctrl-1 = <&P8_34_gpio_pin>;
+ pinctrl-2 = <&P8_34_gpio_pu_pin>;
+ pinctrl-3 = <&P8_34_gpio_pd_pin>;
+ pinctrl-4 = <&P8_34_pwm_pin>;
+ pinctrl-5 = <&P8_34_hdmi_pin>;
+ };
+
+ P8_35_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "hdmi";
+ pinctrl-0 = <&P8_35_default_pin>;
+ pinctrl-1 = <&P8_35_gpio_pin>;
+ pinctrl-2 = <&P8_35_gpio_pu_pin>;
+ pinctrl-3 = <&P8_35_gpio_pd_pin>;
+ pinctrl-4 = <&P8_35_hdmi_pin>;
+ };
+
+ P8_36_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd","pwm", "hdmi";
+ pinctrl-0 = <&P8_36_default_pin>;
+ pinctrl-1 = <&P8_36_gpio_pin>;
+ pinctrl-2 = <&P8_36_gpio_pu_pin>;
+ pinctrl-3 = <&P8_36_gpio_pd_pin>;
+ pinctrl-4 = <&P8_36_pwm_pin>;
+ pinctrl-5 = <&P8_36_hdmi_pin>;
+ };
+
+ P8_37_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd","uart","pwm", "hdmi";
+ pinctrl-0 = <&P8_37_default_pin>;
+ pinctrl-1 = <&P8_37_gpio_pin>;
+ pinctrl-2 = <&P8_37_gpio_pu_pin>;
+ pinctrl-3 = <&P8_37_gpio_pd_pin>;
+ pinctrl-4 = <&P8_37_uart_pin>;
+ pinctrl-5 = <&P8_37_pwm_pin>;
+ pinctrl-6 = <&P8_37_hdmi_pin>;
+ };
+
+ P8_38_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd","uart","pwm", "hdmi";
+ pinctrl-0 = <&P8_38_default_pin>;
+ pinctrl-1 = <&P8_38_gpio_pin>;
+ pinctrl-2 = <&P8_38_gpio_pu_pin>;
+ pinctrl-3 = <&P8_38_gpio_pd_pin>;
+ pinctrl-4 = <&P8_38_uart_pin>;
+ pinctrl-5 = <&P8_38_pwm_pin>;
+ pinctrl-6 = <&P8_38_hdmi_pin>;
+ };
+
+ P8_39_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "pruin", "hdmi";
+ pinctrl-0 = <&P8_39_default_pin>;
+ pinctrl-1 = <&P8_39_gpio_pin>;
+ pinctrl-2 = <&P8_39_gpio_pu_pin>;
+ pinctrl-3 = <&P8_39_gpio_pd_pin>;
+ pinctrl-4 = <&P8_39_pruout_pin>;
+ pinctrl-5 = <&P8_39_pruin_pin>;
+ pinctrl-6 = <&P8_39_hdmi_pin>;
+ };
+
+ P8_40_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "pruin", "hdmi";
+ pinctrl-0 = <&P8_40_default_pin>;
+ pinctrl-1 = <&P8_40_gpio_pin>;
+ pinctrl-2 = <&P8_40_gpio_pu_pin>;
+ pinctrl-3 = <&P8_40_gpio_pd_pin>;
+ pinctrl-4 = <&P8_40_pruout_pin>;
+ pinctrl-5 = <&P8_40_pruin_pin>;
+ pinctrl-6 = <&P8_40_hdmi_pin>;
+ };
+
+ P8_41_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "pruin", "hdmi";
+ pinctrl-0 = <&P8_41_default_pin>;
+ pinctrl-1 = <&P8_41_gpio_pin>;
+ pinctrl-2 = <&P8_41_gpio_pu_pin>;
+ pinctrl-3 = <&P8_41_gpio_pd_pin>;
+ pinctrl-4 = <&P8_41_pruout_pin>;
+ pinctrl-5 = <&P8_41_pruin_pin>;
+ pinctrl-6 = <&P8_41_hdmi_pin>;
+ };
+
+ P8_42_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "pruin", "hdmi";
+ pinctrl-0 = <&P8_42_default_pin>;
+ pinctrl-1 = <&P8_42_gpio_pin>;
+ pinctrl-2 = <&P8_42_gpio_pu_pin>;
+ pinctrl-3 = <&P8_42_gpio_pd_pin>;
+ pinctrl-4 = <&P8_42_pruout_pin>;
+ pinctrl-5 = <&P8_42_pruin_pin>;
+ pinctrl-6 = <&P8_42_hdmi_pin>;
+ };
+
+ P8_43_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "pruin","pwm", "hdmi";
+ pinctrl-0 = <&P8_43_default_pin>;
+ pinctrl-1 = <&P8_43_gpio_pin>;
+ pinctrl-2 = <&P8_43_gpio_pu_pin>;
+ pinctrl-3 = <&P8_43_gpio_pd_pin>;
+ pinctrl-4 = <&P8_43_pruout_pin>;
+ pinctrl-5 = <&P8_43_pruin_pin>;
+ pinctrl-6 = <&P8_43_pwm_pin>;
+ pinctrl-7 = <&P8_43_hdmi_pin>;
+ };
+
+ P8_44_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "pruin","pwm", "hdmi";
+ pinctrl-0 = <&P8_44_default_pin>;
+ pinctrl-1 = <&P8_44_gpio_pin>;
+ pinctrl-2 = <&P8_44_gpio_pu_pin>;
+ pinctrl-3 = <&P8_44_gpio_pd_pin>;
+ pinctrl-4 = <&P8_44_pruout_pin>;
+ pinctrl-5 = <&P8_44_pruin_pin>;
+ pinctrl-6 = <&P8_44_pwm_pin>;
+ pinctrl-7 = <&P8_44_hdmi_pin>;
+ };
+
+ P8_45_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "pruin","pwm", "hdmi";
+ pinctrl-0 = <&P8_45_default_pin>;
+ pinctrl-1 = <&P8_45_gpio_pin>;
+ pinctrl-2 = <&P8_45_gpio_pu_pin>;
+ pinctrl-3 = <&P8_45_gpio_pd_pin>;
+ pinctrl-4 = <&P8_45_pruout_pin>;
+ pinctrl-5 = <&P8_45_pruin_pin>;
+ pinctrl-6 = <&P8_45_pwm_pin>;
+ pinctrl-7 = <&P8_45_hdmi_pin>;
+ };
+
+ P8_46_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "pruin","pwm", "hdmi";
+ pinctrl-0 = <&P8_46_default_pin>;
+ pinctrl-1 = <&P8_46_gpio_pin>;
+ pinctrl-2 = <&P8_46_gpio_pu_pin>;
+ pinctrl-3 = <&P8_46_gpio_pd_pin>;
+ pinctrl-4 = <&P8_46_pruout_pin>;
+ pinctrl-5 = <&P8_46_pruin_pin>;
+ pinctrl-6 = <&P8_46_pwm_pin>;
+ pinctrl-7 = <&P8_46_hdmi_pin>;
+ };
+
+ /************************/
+ /* P9 Header */
+ /************************/
+
+ P9_11_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart";
+ pinctrl-0 = <&P9_11_default_pin>;
+ pinctrl-1 = <&P9_11_gpio_pin>;
+ pinctrl-2 = <&P9_11_gpio_pu_pin>;
+ pinctrl-3 = <&P9_11_gpio_pd_pin>;
+ pinctrl-4 = <&P9_11_uart_pin>;
+ };
+
+ P9_12_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio";
+ pinctrl-0 = <&P9_12_default_pin>;
+ pinctrl-1 = <&P9_12_gpio_pin>;
+ pinctrl-2 = <&P9_12_gpio_pu_pin>;
+ pinctrl-3 = <&P9_12_gpio_pd_pin>;
+ };
+
+ P9_13_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart";
+ pinctrl-0 = <&P9_13_default_pin>;
+ pinctrl-1 = <&P9_13_gpio_pin>;
+ pinctrl-2 = <&P9_13_gpio_pu_pin>;
+ pinctrl-3 = <&P9_13_gpio_pd_pin>;
+ pinctrl-4 = <&P9_13_uart_pin>;
+ };
+
+ P9_14_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm";
+ pinctrl-0 = <&P9_14_default_pin>;
+ pinctrl-1 = <&P9_14_gpio_pin>;
+ pinctrl-2 = <&P9_14_gpio_pu_pin>;
+ pinctrl-3 = <&P9_14_gpio_pd_pin>;
+ pinctrl-4 = <&P9_14_pwm_pin>;
+ };
+
+ P9_15_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm";
+ pinctrl-0 = <&P9_15_default_pin>;
+ pinctrl-1 = <&P9_15_gpio_pin>;
+ pinctrl-2 = <&P9_15_gpio_pu_pin>;
+ pinctrl-3 = <&P9_15_gpio_pd_pin>;
+ pinctrl-4 = <&P9_15_pwm_pin>;
+ };
+
+ P9_16_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm";
+ pinctrl-0 = <&P9_16_default_pin>;
+ pinctrl-1 = <&P9_16_gpio_pin>;
+ pinctrl-2 = <&P9_16_gpio_pu_pin>;
+ pinctrl-3 = <&P9_16_gpio_pd_pin>;
+ pinctrl-4 = <&P9_16_pwm_pin>;
+ };
+
+ P9_17_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi", "i2c", "pwm";
+ pinctrl-0 = <&P9_17_default_pin>;
+ pinctrl-1 = <&P9_17_gpio_pin>;
+ pinctrl-2 = <&P9_17_gpio_pu_pin>;
+ pinctrl-3 = <&P9_17_gpio_pd_pin>;
+ pinctrl-4 = <&P9_17_spi_pin>;
+ pinctrl-5 = <&P9_17_i2c_pin>;
+ pinctrl-6 = <&P9_17_pwm_pin>;
+ };
+
+ P9_18_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi", "i2c", "pwm";
+ pinctrl-0 = <&P9_18_default_pin>;
+ pinctrl-1 = <&P9_18_gpio_pin>;
+ pinctrl-2 = <&P9_18_gpio_pu_pin>;
+ pinctrl-3 = <&P9_18_gpio_pd_pin>;
+ pinctrl-4 = <&P9_18_spi_pin>;
+ pinctrl-5 = <&P9_18_i2c_pin>;
+ pinctrl-6 = <&P9_18_pwm_pin>;
+ };
+
+ P9_19_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "can", "i2c";
+ pinctrl-0 = <&P9_19_default_pin>;
+ pinctrl-1 = <&P9_19_gpio_pin>;
+ pinctrl-2 = <&P9_19_gpio_pu_pin>;
+ pinctrl-3 = <&P9_19_gpio_pd_pin>;
+ pinctrl-4 = <&P9_19_can_pin>;
+ pinctrl-5 = <&P9_19_i2c_pin>;
+ };
+
+ P9_20_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "can", "i2c";
+ pinctrl-0 = <&P9_20_default_pin>;
+ pinctrl-1 = <&P9_20_gpio_pin>;
+ pinctrl-2 = <&P9_20_gpio_pu_pin>;
+ pinctrl-3 = <&P9_20_gpio_pd_pin>;
+ pinctrl-4 = <&P9_20_can_pin>;
+ pinctrl-5 = <&P9_20_i2c_pin>;
+ };
+
+ P9_21_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi", "uart", "i2c", "pwm";
+ pinctrl-0 = <&P9_21_default_pin>;
+ pinctrl-1 = <&P9_21_gpio_pin>;
+ pinctrl-2 = <&P9_21_gpio_pu_pin>;
+ pinctrl-3 = <&P9_21_gpio_pd_pin>;
+ pinctrl-4 = <&P9_21_spi_pin>;
+ pinctrl-5 = <&P9_21_uart_pin>;
+ pinctrl-6 = <&P9_21_i2c_pin>;
+ pinctrl-7 = <&P9_21_pwm_pin>;
+ };
+
+ P9_22_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi", "uart", "i2c", "pwm";
+ pinctrl-0 = <&P9_22_default_pin>;
+ pinctrl-1 = <&P9_22_gpio_pin>;
+ pinctrl-2 = <&P9_22_gpio_pu_pin>;
+ pinctrl-3 = <&P9_22_gpio_pd_pin>;
+ pinctrl-4 = <&P9_22_spi_pin>;
+ pinctrl-5 = <&P9_22_uart_pin>;
+ pinctrl-6 = <&P9_22_i2c_pin>;
+ pinctrl-7 = <&P9_22_pwm_pin>;
+ };
+
+ P9_23_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm";
+ pinctrl-0 = <&P9_23_default_pin>;
+ pinctrl-1 = <&P9_23_gpio_pin>;
+ pinctrl-2 = <&P9_23_gpio_pu_pin>;
+ pinctrl-3 = <&P9_23_gpio_pd_pin>;
+ pinctrl-4 = <&P9_23_pwm_pin>;
+ };
+
+ P9_24_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart", "can", "i2c", "pruin";
+ pinctrl-0 = <&P9_24_default_pin>;
+ pinctrl-1 = <&P9_24_gpio_pin>;
+ pinctrl-2 = <&P9_24_gpio_pu_pin>;
+ pinctrl-3 = <&P9_24_gpio_pd_pin>;
+ pinctrl-4 = <&P9_24_uart_pin>;
+ pinctrl-5 = <&P9_24_can_pin>;
+ pinctrl-6 = <&P9_24_i2c_pin>;
+ pinctrl-7 = <&P9_24_pruin_pin>;
+ };
+
+ P9_25_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "qep", "pruout", "pruin", "audio";
+ pinctrl-0 = <&P9_25_default_pin>;
+ pinctrl-1 = <&P9_25_gpio_pin>;
+ pinctrl-2 = <&P9_25_gpio_pu_pin>;
+ pinctrl-3 = <&P9_25_gpio_pd_pin>;
+ pinctrl-4 = <&P9_25_qep_pin>;
+ pinctrl-5 = <&P9_25_pruout_pin>;
+ pinctrl-6 = <&P9_25_pruin_pin>;
+ pinctrl-7 = <&P9_25_audio_pin>;
+ };
+
+ P9_26_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart", "can", "i2c", "pruin";
+ pinctrl-0 = <&P9_26_default_pin>;
+ pinctrl-1 = <&P9_26_gpio_pin>;
+ pinctrl-2 = <&P9_26_gpio_pu_pin>;
+ pinctrl-3 = <&P9_26_gpio_pd_pin>;
+ pinctrl-4 = <&P9_26_uart_pin>;
+ pinctrl-5 = <&P9_26_can_pin>;
+ pinctrl-6 = <&P9_26_i2c_pin>;
+ pinctrl-7 = <&P9_26_pruin_pin>;
+ };
+
+ P9_27_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "qep", "pruout", "pruin";
+ pinctrl-0 = <&P9_27_default_pin>;
+ pinctrl-1 = <&P9_27_gpio_pin>;
+ pinctrl-2 = <&P9_27_gpio_pu_pin>;
+ pinctrl-3 = <&P9_27_gpio_pd_pin>;
+ pinctrl-4 = <&P9_27_qep_pin>;
+ pinctrl-5 = <&P9_27_pruout_pin>;
+ pinctrl-6 = <&P9_27_pruin_pin>;
+ };
+
+ P9_28_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm", "spi", "pwm2", "pruout", "pruin", "audio";
+ pinctrl-0 = <&P9_28_default_pin>;
+ pinctrl-1 = <&P9_28_gpio_pin>;
+ pinctrl-2 = <&P9_28_gpio_pu_pin>;
+ pinctrl-3 = <&P9_28_gpio_pd_pin>;
+ pinctrl-4 = <&P9_28_pwm_pin>;
+ pinctrl-5 = <&P9_28_spi_pin>;
+ pinctrl-6 = <&P9_28_pwm2_pin>;
+ pinctrl-7 = <&P9_28_pruout_pin>;
+ pinctrl-8 = <&P9_28_pruin_pin>;
+ pinctrl-9 = <&P9_28_audio_pin>;
+ };
+
+ P9_29_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm", "spi", "pruout", "pruin", "audio";
+ pinctrl-0 = <&P9_29_default_pin>;
+ pinctrl-1 = <&P9_29_gpio_pin>;
+ pinctrl-2 = <&P9_29_gpio_pu_pin>;
+ pinctrl-3 = <&P9_29_gpio_pd_pin>;
+ pinctrl-4 = <&P9_29_pwm_pin>;
+ pinctrl-5 = <&P9_29_spi_pin>;
+ pinctrl-6 = <&P9_29_pruout_pin>;
+ pinctrl-7 = <&P9_29_pruin_pin>;
+ pinctrl-8 = <&P9_29_audio_pin>;
+ };
+
+ P9_30_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm", "spi", "pruout", "pruin";
+ pinctrl-0 = <&P9_30_default_pin>;
+ pinctrl-1 = <&P9_30_gpio_pin>;
+ pinctrl-2 = <&P9_30_gpio_pu_pin>;
+ pinctrl-3 = <&P9_30_gpio_pd_pin>;
+ pinctrl-4 = <&P9_30_pwm_pin>;
+ pinctrl-5 = <&P9_30_spi_pin>;
+ pinctrl-6 = <&P9_30_pruout_pin>;
+ pinctrl-7 = <&P9_30_pruin_pin>;
+ };
+
+ P9_31_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm", "spi", "pruout", "pruin", "audio";
+ pinctrl-0 = <&P9_31_default_pin>;
+ pinctrl-1 = <&P9_31_gpio_pin>;
+ pinctrl-2 = <&P9_31_gpio_pu_pin>;
+ pinctrl-3 = <&P9_31_gpio_pd_pin>;
+ pinctrl-4 = <&P9_31_pwm_pin>;
+ pinctrl-5 = <&P9_31_spi_pin>;
+ pinctrl-6 = <&P9_31_pruout_pin>;
+ pinctrl-7 = <&P9_31_pruin_pin>;
+ pinctrl-8 = <&P9_31_audio_pin>;
+ };
+
+ P9_41_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "timer", "pruin";
+ pinctrl-0 = <&P9_41_default_pin>;
+ pinctrl-1 = <&P9_41_gpio_pin>;
+ pinctrl-2 = <&P9_41_gpio_pu_pin>;
+ pinctrl-3 = <&P9_41_gpio_pd_pin>;
+ pinctrl-4 = <&P9_41_timer_pin>;
+ pinctrl-5 = <&P9_41_pruin_pin>;
+ };
+
+ P9_91_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "qep", "pruout", "pruin";
+ pinctrl-0 = <&P9_91_default_pin>;
+ pinctrl-1 = <&P9_91_gpio_pin>;
+ pinctrl-2 = <&P9_91_gpio_pu_pin>;
+ pinctrl-3 = <&P9_91_gpio_pd_pin>;
+ pinctrl-4 = <&P9_91_qep_pin>;
+ pinctrl-5 = <&P9_91_pruout_pin>;
+ pinctrl-6 = <&P9_91_pruin_pin>;
+ };
+
+ P9_42_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm", "uart", "spics", "spiclk";
+ pinctrl-0 = <&P9_42_default_pin>;
+ pinctrl-1 = <&P9_42_gpio_pin>;
+ pinctrl-2 = <&P9_42_gpio_pu_pin>;
+ pinctrl-3 = <&P9_42_gpio_pd_pin>;
+ pinctrl-4 = <&P9_42_pwm_pin>;
+ pinctrl-5 = <&P9_42_uart_pin>;
+ pinctrl-6 = <&P9_42_spics_pin>;
+ pinctrl-7 = <&P9_42_spiclk_pin>;
+ };
+
+ P9_92_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "qep", "pruout", "pruin";
+ pinctrl-0 = <&P9_92_default_pin>;
+ pinctrl-1 = <&P9_92_gpio_pin>;
+ pinctrl-2 = <&P9_92_gpio_pu_pin>;
+ pinctrl-3 = <&P9_92_gpio_pd_pin>;
+ pinctrl-4 = <&P9_92_qep_pin>;
+ pinctrl-5 = <&P9_92_pruout_pin>;
+ pinctrl-6 = <&P9_92_pruin_pin>;
+ };
+
+ cape-universal {
+ compatible = "gpio-of-helper";
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <>;
+
+ P8_07 {
+ gpio-name = "P8_07";
+ gpio = <&gpio2 2 0>;
+ input;
+ dir-changeable;
+ };
+ P8_08 {
+ gpio-name = "P8_08";
+ gpio = <&gpio2 3 0>;
+ input;
+ dir-changeable;
+ };
+ P8_09 {
+ gpio-name = "P8_09";
+ gpio = <&gpio2 5 0>;
+ input;
+ dir-changeable;
+ };
+ P8_10 {
+ gpio-name = "P8_10";
+ gpio = <&gpio2 4 0>;
+ input;
+ dir-changeable;
+ };
+ P8_11 {
+ gpio-name = "P8_11";
+ gpio = <&gpio1 13 0>;
+ input;
+ dir-changeable;
+ };
+ P8_12 {
+ gpio-name = "P8_12";
+ gpio = <&gpio1 12 0>;
+ input;
+ dir-changeable;
+ };
+ P8_13 {
+ gpio-name = "P8_13";
+ gpio = <&gpio0 23 0>;
+ input;
+ dir-changeable;
+ };
+ P8_14 {
+ gpio-name = "P8_14";
+ gpio = <&gpio0 26 0>;
+ input;
+ dir-changeable;
+ };
+ P8_15 {
+ gpio-name = "P8_15";
+ gpio = <&gpio1 15 0>;
+ input;
+ dir-changeable;
+ };
+ P8_16 {
+ gpio-name = "P8_16";
+ gpio = <&gpio1 14 0>;
+ input;
+ dir-changeable;
+ };
+ P8_17 {
+ gpio-name = "P8_17";
+ gpio = <&gpio0 27 0>;
+ input;
+ dir-changeable;
+ };
+ P8_18 {
+ gpio-name = "P8_18";
+ gpio = <&gpio2 1 0>;
+ input;
+ dir-changeable;
+ };
+ P8_19 {
+ gpio-name = "P8_19";
+ gpio = <&gpio0 22 0>;
+ input;
+ dir-changeable;
+ };
+
+ P8_26 {
+ gpio-name = "P8_26";
+ gpio = <&gpio1 29 0>;
+ input;
+ dir-changeable;
+ };
+ P8_27 {
+ gpio-name = "P8_27";
+ gpio = <&gpio2 22 0>;
+ input;
+ dir-changeable;
+ };
+ P8_28 {
+ gpio-name = "P8_28";
+ gpio = <&gpio2 24 0>;
+ input;
+ dir-changeable;
+ };
+ P8_29 {
+ gpio-name = "P8_29";
+ gpio = <&gpio2 23 0>;
+ input;
+ dir-changeable;
+ };
+ P8_30 {
+ gpio-name = "P8_30";
+ gpio = <&gpio2 25 0>;
+ input;
+ dir-changeable;
+ };
+ P8_31 {
+ gpio-name = "P8_31";
+ gpio = <&gpio0 10 0>;
+ input;
+ dir-changeable;
+ };
+ P8_32 {
+ gpio-name = "P8_32";
+ gpio = <&gpio0 11 0>;
+ input;
+ dir-changeable;
+ };
+ P8_33 {
+ gpio-name = "P8_33";
+ gpio = <&gpio0 9 0>;
+ input;
+ dir-changeable;
+ };
+ P8_34 {
+ gpio-name = "P8_34";
+ gpio = <&gpio2 17 0>;
+ input;
+ dir-changeable;
+ };
+ P8_35 {
+ gpio-name = "P8_35";
+ gpio = <&gpio0 8 0>;
+ input;
+ dir-changeable;
+ };
+ P8_36 {
+ gpio-name = "P8_36";
+ gpio = <&gpio2 16 0>;
+ input;
+ dir-changeable;
+ };
+ P8_37 {
+ gpio-name = "P8_37";
+ gpio = <&gpio2 14 0>;
+ input;
+ dir-changeable;
+ };
+ P8_38 {
+ gpio-name = "P8_38";
+ gpio = <&gpio2 15 0>;
+ input;
+ dir-changeable;
+ };
+ P8_39 {
+ gpio-name = "P8_39";
+ gpio = <&gpio2 12 0>;
+ input;
+ dir-changeable;
+ };
+ P8_40 {
+ gpio-name = "P8_40";
+ gpio = <&gpio2 13 0>;
+ input;
+ dir-changeable;
+ };
+ P8_41 {
+ gpio-name = "P8_41";
+ gpio = <&gpio2 10 0>;
+ input;
+ dir-changeable;
+ };
+ P8_42 {
+ gpio-name = "P8_42";
+ gpio = <&gpio2 11 0>;
+ input;
+ dir-changeable;
+ };
+ P8_43 {
+ gpio-name = "P8_43";
+ gpio = <&gpio2 8 0>;
+ input;
+ dir-changeable;
+ };
+ P8_44 {
+ gpio-name = "P8_44";
+ gpio = <&gpio2 9 0>;
+ input;
+ dir-changeable;
+ };
+ P8_45 {
+ gpio-name = "P8_45";
+ gpio = <&gpio2 6 0>;
+ input;
+ dir-changeable;
+ };
+ P8_46 {
+ gpio-name = "P8_46";
+ gpio = <&gpio2 7 0>;
+ input;
+ dir-changeable;
+ };
+
+
+ P9_11 {
+ gpio-name = "P9_11";
+ gpio = <&gpio0 30 0>;
+ input;
+ dir-changeable;
+ };
+ P9_12 {
+ gpio-name = "P9_12";
+ gpio = <&gpio1 28 0>;
+ input;
+ dir-changeable;
+ };
+ P9_13 {
+ gpio-name = "P9_13";
+ gpio = <&gpio0 31 0>;
+ input;
+ dir-changeable;
+ };
+ P9_14 {
+ gpio-name = "P9_14";
+ gpio = <&gpio1 18 0>;
+ input;
+ dir-changeable;
+ };
+ P9_15 {
+ gpio-name = "P9_15";
+ gpio = <&gpio1 16 0>;
+ input;
+ dir-changeable;
+ };
+ P9_16 {
+ gpio-name = "P9_16";
+ gpio = <&gpio1 19 0>;
+ input;
+ dir-changeable;
+ };
+ P9_17 {
+ gpio-name = "P9_17";
+ gpio = <&gpio0 5 0>;
+ input;
+ dir-changeable;
+ };
+ P9_18 {
+ gpio-name = "P9_18";
+ gpio = <&gpio0 4 0>;
+ input;
+ dir-changeable;
+ };
+ P9_19 {
+ gpio-name = "P9_19";
+ gpio = <&gpio0 13 0>;
+ input;
+ dir-changeable;
+ };
+ P9_20 {
+ gpio-name = "P9_20";
+ gpio = <&gpio0 12 0>;
+ input;
+ dir-changeable;
+ };
+ P9_21 {
+ gpio-name = "P9_21";
+ gpio = <&gpio0 3 0>;
+ input;
+ dir-changeable;
+ };
+ P9_22 {
+ gpio-name = "P9_22";
+ gpio = <&gpio0 2 0>;
+ input;
+ dir-changeable;
+ };
+ P9_23 {
+ gpio-name = "P9_23";
+ gpio = <&gpio1 17 0>;
+ input;
+ dir-changeable;
+ };
+ P9_24 {
+ gpio-name = "P9_24";
+ gpio = <&gpio0 15 0>;
+ input;
+ dir-changeable;
+ };
+ P9_25 {
+ gpio-name = "P9_25";
+ gpio = <&gpio3 21 0>;
+ input;
+ dir-changeable;
+ };
+ P9_26 {
+ gpio-name = "P9_26";
+ gpio = <&gpio0 14 0>;
+ input;
+ dir-changeable;
+ };
+ P9_27 {
+ gpio-name = "P9_27";
+ gpio = <&gpio3 19 0>;
+ input;
+ dir-changeable;
+ };
+ P9_28 {
+ gpio-name = "P9_28";
+ gpio = <&gpio3 17 0>;
+ input;
+ dir-changeable;
+ };
+ P9_29 {
+ gpio-name = "P9_29";
+ gpio = <&gpio3 15 0>;
+ input;
+ dir-changeable;
+ };
+ P9_30 {
+ gpio-name = "P9_30";
+ gpio = <&gpio3 16 0>;
+ input;
+ dir-changeable;
+ };
+ P9_31 {
+ gpio-name = "P9_31";
+ gpio = <&gpio3 14 0>;
+ input;
+ dir-changeable;
+ };
+ P9_41 {
+ gpio-name = "P9_41";
+ gpio = <&gpio0 20 0>;
+ input;
+ dir-changeable;
+ };
+ P9_91 {
+ gpio-name = "P9_91";
+ gpio = <&gpio3 20 0>;
+ input;
+ dir-changeable;
+ };
+ P9_42 {
+ gpio-name = "P9_42";
+ gpio = <&gpio0 7 0>;
+ input;
+ dir-changeable;
+ };
+ P9_92 {
+ gpio-name = "P9_92";
+ gpio = <&gpio3 18 0>;
+ input;
+ dir-changeable;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
index 007b5e5..54a3b8d 100644
--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
+++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
@@ -6,6 +6,8 @@
* published by the Free Software Foundation.
*/
+#include <dt-bindings/mfd/tps65217.h>
+
/ {
cpus {
cpu@0 {
@@ -29,14 +31,14 @@
compatible = "gpio-leds";
led2 {
- label = "beaglebone:green:heartbeat";
+ label = "beaglebone:green:usr0";
gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "heartbeat";
default-state = "off";
};
led3 {
- label = "beaglebone:green:mmc0";
+ label = "beaglebone:green:usr1";
gpios = <&gpio1 22 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "mmc0";
default-state = "off";
@@ -66,9 +68,6 @@
};
&am33xx_pinmux {
- pinctrl-names = "default";
- pinctrl-0 = <&clkout2_pin>;
-
user_leds_s0: user_leds_s0 {
pinctrl-single,pins = <
AM33XX_IOPAD(0x854, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a5.gpio1_21 */
@@ -99,15 +98,11 @@
>;
};
- clkout2_pin: pinmux_clkout2_pin {
- pinctrl-single,pins = <
- AM33XX_IOPAD(0x9b4, PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* xdma_event_intr1.clkout2 */
- >;
- };
-
cpsw_default: cpsw_default {
pinctrl-single,pins = <
/* Slave 1 */
+ 0x108 (PIN_INPUT | MUX_MODE0) /* mii1_col.mii1_col */
+ 0x10c (PIN_INPUT | MUX_MODE0) /* mii1_crs.mii1_crs */
AM33XX_IOPAD(0x910, PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxerr.mii1_rxerr */
AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txen.mii1_txen */
AM33XX_IOPAD(0x918, PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxdv.mii1_rxdv */
@@ -127,6 +122,8 @@
cpsw_sleep: cpsw_sleep {
pinctrl-single,pins = <
/* Slave 1 reset value */
+ 0x108 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x10c (PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE7)
@@ -310,8 +307,23 @@
* by the hardware problems. (Tip: double-check by performing a current
* measurement after shutdown: it should be less than 1 mA.)
*/
+
+ interrupts = <7>; /* NMI */
+ interrupt-parent = <&intc>;
+
ti,pmic-shutdown-controller;
+ charger {
+ interrupts = <TPS65217_IRQ_AC>, <TPS65217_IRQ_USB>;
+ interrupts-names = "AC", "USB";
+ status = "okay";
+ };
+
+ pwrbutton {
+ interrupts = <TPS65217_IRQ_PB>;
+ status = "okay";
+ };
+
regulators {
dcdc1_reg: regulator@0 {
regulator-name = "vdds_dpr";
@@ -393,3 +405,32 @@
&sham {
status = "okay";
};
+
+&rtc {
+ system-power-controller;
+};
+
+/* the cape manager */
+/ {
+ bone_capemgr {
+ compatible = "ti,bone-capemgr";
+ status = "okay";
+
+ nvmem-cells = <&baseboard_data &cape0_data &cape1_data &cape2_data &cape3_data>;
+ nvmem-cell-names = "baseboard", "slot0", "slot1", "slot2", "slot3";
+ #slots = <4>;
+
+ /* map board revisions to compatible definitions */
+ baseboardmaps {
+ baseboard_beaglebone: board@0 {
+ board-name = "A335BONE";
+ compatible-name = "ti,beaglebone";
+ };
+
+ baseboard_beaglebone_black: board@1 {
+ board-name = "A335BNLT";
+ compatible-name = "ti,beaglebone-black";
+ };
+ };
+ };
+};
diff --git b/arch/arm/boot/dts/am335x-bone-emmc-in-reset.dtsi b/arch/arm/boot/dts/am335x-bone-emmc-in-reset.dtsi
new file mode 100644
index 0000000..7d8f673
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-bone-emmc-in-reset.dtsi
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* standard */
+
+&gpio1 {
+ emmc_rst {
+ gpio-hog;
+ gpios = <20 0>;
+ output-high;
+ line-name = "EMMC ResetN";
+ };
+};
diff --git b/arch/arm/boot/dts/am335x-bone-jtag.dtsi b/arch/arm/boot/dts/am335x-bone-jtag.dtsi
new file mode 100644
index 0000000..603ef0a
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-bone-jtag.dtsi
@@ -0,0 +1,20 @@
+/*
+ * Device Tree Source for bone jtag
+ *
+ * Copyright (C) 2015 Robert Nelson <robertcnelson@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+&am33xx_pinmux {
+ pinctrl-names = "default";
+ pinctrl-0 = <&clkout2_pin>;
+
+ clkout2_pin: pinmux_clkout2_pin {
+ pinctrl-single,pins = <
+ AM33XX_IOPAD(0x9b4, PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* xdma_event_intr1.clkout2 */
+ >;
+ };
+};
diff --git b/arch/arm/boot/dts/am335x-bone-pinmux-can0.dtsi b/arch/arm/boot/dts/am335x-bone-pinmux-can0.dtsi
new file mode 100644
index 0000000..0961216
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-bone-pinmux-can0.dtsi
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <dt-bindings/board/am335x-bbw-bbb-base.h>
+#include "am335x-peripheral-can0.dtsi"
+
+/* cape universal */
+
+/*
+ *&ocp {
+ * P9_19_pinmux {
+ * mode = "can";
+ * };
+ * P9_20_pinmux {
+ * mode = "can";
+ * };
+ *};
+ *
+ *&dcan0 {
+ * pinctrl-0 = <>;
+ *};
+ *
+ */
+
+/* standard */
+
+&am33xx_pinmux {
+ dcan0_pins: pinmux_dcan0_pins {
+ pinctrl-single,pins = <
+ /* P9_20: uart1_ctsn.d_can0_tx */
+ BONE_P9_20 (PIN_OUTPUT_PULLUP | MUX_MODE2)
+ /* P9_19: uart1_rtsn.d_can0_rx */
+ BONE_P9_19 (PIN_INPUT_PULLUP | MUX_MODE2)
+ >;
+ };
+};
+
+&dcan0 {
+ pinctrl-0 = <&dcan0_pins>;
+};
diff --git b/arch/arm/boot/dts/am335x-bone-pinmux-can1.dtsi b/arch/arm/boot/dts/am335x-bone-pinmux-can1.dtsi
new file mode 100644
index 0000000..9e26413
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-bone-pinmux-can1.dtsi
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <dt-bindings/board/am335x-bbw-bbb-base.h>
+#include "am335x-peripheral-can1.dtsi"
+
+/* cape universal */
+
+/*
+ *&ocp {
+ * P9_24_pinmux {
+ * mode = "can";
+ * };
+ * P9_26_pinmux {
+ * mode = "can";
+ * };
+ *};
+ *
+ *&dcan1 {
+ * pinctrl-0 = <>;
+ *};
+ *
+ */
+
+/* standard */
+
+&am33xx_pinmux {
+ dcan1_pins: pinmux_dcan1_pins {
+ pinctrl-single,pins = <
+ /* P9_26: uart1_rxd.d_can1_tx */
+ BONE_P9_26 (PIN_OUTPUT_PULLUP | MUX_MODE2)
+ /* P9_24: uart1_txd.d_can1_rx */
+ BONE_P9_24 (PIN_INPUT_PULLUP | MUX_MODE2)
+ >;
+ };
+};
+
+&dcan1 {
+ pinctrl-0 = <&dcan1_pins>;
+};
diff --git b/arch/arm/boot/dts/am335x-bone-pinmux-emmc.dtsi b/arch/arm/boot/dts/am335x-bone-pinmux-emmc.dtsi
new file mode 100644
index 0000000..22cf462
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-bone-pinmux-emmc.dtsi
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* Testing */
+/* lsblk */
+
+#include <dt-bindings/board/am335x-bbw-bbb-base.h>
+#include "am335x-peripheral-emmc.dtsi"
+
+/* cape universal */
+
+/*
+ *&ocp {
+ * P8_21_pinmux {
+ * state = "disabled";
+ * };
+ * P8_20_pinmux {
+ * state = "disabled";
+ * };
+ * P8_25_pinmux {
+ * state = "disabled";
+ * };
+ * P8_24_pinmux {
+ * state = "disabled";
+ * };
+ * P8_05_pinmux {
+ * state = "disabled";
+ * };
+ * P8_06_pinmux {
+ * state = "disabled";
+ * };
+ * P8_23_pinmux {
+ * state = "disabled";
+ * };
+ * P8_22_pinmux {
+ * state = "disabled";
+ * };
+ * P8_03_pinmux {
+ * state = "disabled";
+ * };
+ * P8_04_pinmux {
+ * state = "disabled";
+ * };
+ *};
+ *
+ *&mmc2 {
+ * pinctrl-0 = <>;
+ *};
+ *
+ */
+
+/* standard */
+
+&am33xx_pinmux {
+ emmc_pins: pinmux_emmc_pins {
+ pinctrl-single,pins = <
+ /* P8_21: gpmc_csn1.mmc1_clk */
+ BONE_P8_21 (PIN_INPUT_PULLUP | MUX_MODE2)
+ /* P8_20: gpmc_csn2.mmc1_cmd */
+ BONE_P8_20 (PIN_INPUT_PULLUP | MUX_MODE2)
+ /* P8_25: gpmc_ad0.mmc1_dat0 */
+ BONE_P8_25 (PIN_INPUT_PULLUP | MUX_MODE1)
+ /* P8_24: gpmc_ad1.mmc1_dat1 */
+ BONE_P8_24 (PIN_INPUT_PULLUP | MUX_MODE1)
+ /* P8_05: gpmc_ad2.mmc1_dat2 */
+ BONE_P8_05 (PIN_INPUT_PULLUP | MUX_MODE1)
+ /* P8_06: gpmc_ad3.mmc1_dat3 */
+ BONE_P8_06 (PIN_INPUT_PULLUP | MUX_MODE1)
+ /* P8_23: gpmc_ad4.mmc1_dat4 */
+ BONE_P8_23 (PIN_INPUT_PULLUP | MUX_MODE1)
+ /* P8_22: gpmc_ad5.mmc1_dat5 */
+ BONE_P8_22 (PIN_INPUT_PULLUP | MUX_MODE1)
+ /* P8_03: gpmc_ad6.mmc1_dat6 */
+ BONE_P8_03 (PIN_INPUT_PULLUP | MUX_MODE1)
+ /* P8_04: gpmc_ad7.mmc1_dat7 */
+ BONE_P8_04 (PIN_INPUT_PULLUP | MUX_MODE1)
+ >;
+ };
+};
+
+&mmc2 {
+ pinctrl-0 = <&emmc_pins>;
+};
diff --git b/arch/arm/boot/dts/am335x-bone-pinmux-i2c2.dtsi b/arch/arm/boot/dts/am335x-bone-pinmux-i2c2.dtsi
new file mode 100644
index 0000000..abf3b57
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-bone-pinmux-i2c2.dtsi
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <dt-bindings/board/am335x-bbw-bbb-base.h>
+#include "am335x-peripheral-i2c2.dtsi"
+
+/* cape universal */
+
+/*
+ *&ocp {
+ * P9_19_pinmux {
+ * mode = "i2c";
+ * };
+ * P9_20_pinmux {
+ * mode = "i2c";
+ * };
+ *};
+ *
+ *&dcan0 {
+ * pinctrl-0 = <>;
+ *};
+ *
+ */
+
+/* standard */
+
+&am33xx_pinmux {
+ i2c2_pins: pinmux_i2c2_pins {
+ pinctrl-single,pins = <
+ /* P9_20: uart1_ctsn.i2c2_sda */
+ BONE_P9_20 (SLEWCTRL_SLOW | PIN_INPUT_PULLUP | MUX_MODE3)
+ /* P9_19: uart1_rtsn.i2c2_scl */
+ BONE_P9_19 (SLEWCTRL_SLOW | PIN_INPUT_PULLUP | MUX_MODE3)
+ >;
+ };
+};
+
+&i2c2 {
+ pinctrl-0 = <&i2c2_pins>;
+};
diff --git b/arch/arm/boot/dts/am335x-bone-pinmux-nxp-hdmi.dtsi b/arch/arm/boot/dts/am335x-bone-pinmux-nxp-hdmi.dtsi
new file mode 100644
index 0000000..5205fa0
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-bone-pinmux-nxp-hdmi.dtsi
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "am335x-peripheral-nxp-hdmi.dtsi"
+
+/* cape universal */
+
+/*
+ *&ocp {
+ * P8_27_pinmux {
+ * state = "disabled";
+ * };
+ * P8_28_pinmux {
+ * state = "disabled";
+ * };
+ * P8_29_pinmux {
+ * state = "disabled";
+ * };
+ * P8_30_pinmux {
+ * state = "disabled";
+ * };
+ * P8_31_pinmux {
+ * state = "disabled";
+ * };
+ * P8_32_pinmux {
+ * state = "disabled";
+ * };
+ * P8_33_pinmux {
+ * state = "disabled";
+ * };
+ * P8_34_pinmux {
+ * state = "disabled";
+ * };
+ * P8_35_pinmux {
+ * state = "disabled";
+ * };
+ * P8_36_pinmux {
+ * state = "disabled";
+ * };
+ * P8_37_pinmux {
+ * state = "disabled";
+ * };
+ * P8_38_pinmux {
+ * state = "disabled";
+ * };
+ * P8_39_pinmux {
+ * state = "disabled";
+ * };
+ * P8_40_pinmux {
+ * state = "disabled";
+ * };
+ * P8_41_pinmux {
+ * state = "disabled";
+ * };
+ * P8_42_pinmux {
+ * state = "disabled";
+ * };
+ * P8_43_pinmux {
+ * state = "disabled";
+ * };
+ * P8_44_pinmux {
+ * state = "disabled";
+ * };
+ * P8_45_pinmux {
+ * state = "disabled";
+ * };
+ * P8_46_pinmux {
+ * state = "disabled";
+ * };
+ *};
+ */
+
+/* standard */
+
+&am33xx_pinmux {
+ nxp_hdmi_pins: pinmux_nxp_hdmi_pins {
+ pinctrl-single,pins = <
+ AM33XX_IOPAD(0x9b0, PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* xdma_event_intr0 */
+ AM33XX_IOPAD(0x8a0, PIN_OUTPUT | MUX_MODE0) /* lcd_data0.lcd_data0 */
+ AM33XX_IOPAD(0x8a4, PIN_OUTPUT | MUX_MODE0) /* lcd_data1.lcd_data1 */
+ AM33XX_IOPAD(0x8a8, PIN_OUTPUT | MUX_MODE0) /* lcd_data2.lcd_data2 */
+ AM33XX_IOPAD(0x8ac, PIN_OUTPUT | MUX_MODE0) /* lcd_data3.lcd_data3 */
+ AM33XX_IOPAD(0x8b0, PIN_OUTPUT | MUX_MODE0) /* lcd_data4.lcd_data4 */
+ AM33XX_IOPAD(0x8b4, PIN_OUTPUT | MUX_MODE0) /* lcd_data5.lcd_data5 */
+ AM33XX_IOPAD(0x8b8, PIN_OUTPUT | MUX_MODE0) /* lcd_data6.lcd_data6 */
+ AM33XX_IOPAD(0x8bc, PIN_OUTPUT | MUX_MODE0) /* lcd_data7.lcd_data7 */
+ AM33XX_IOPAD(0x8c0, PIN_OUTPUT | MUX_MODE0) /* lcd_data8.lcd_data8 */
+ AM33XX_IOPAD(0x8c4, PIN_OUTPUT | MUX_MODE0) /* lcd_data9.lcd_data9 */
+ AM33XX_IOPAD(0x8c8, PIN_OUTPUT | MUX_MODE0) /* lcd_data10.lcd_data10 */
+ AM33XX_IOPAD(0x8cc, PIN_OUTPUT | MUX_MODE0) /* lcd_data11.lcd_data11 */
+ AM33XX_IOPAD(0x8d0, PIN_OUTPUT | MUX_MODE0) /* lcd_data12.lcd_data12 */
+ AM33XX_IOPAD(0x8d4, PIN_OUTPUT | MUX_MODE0) /* lcd_data13.lcd_data13 */
+ AM33XX_IOPAD(0x8d8, PIN_OUTPUT | MUX_MODE0) /* lcd_data14.lcd_data14 */
+ AM33XX_IOPAD(0x8dc, PIN_OUTPUT | MUX_MODE0) /* lcd_data15.lcd_data15 */
+ AM33XX_IOPAD(0x8e0, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* lcd_vsync.lcd_vsync */
+ AM33XX_IOPAD(0x8e4, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* lcd_hsync.lcd_hsync */
+ AM33XX_IOPAD(0x8e8, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* lcd_pclk.lcd_pclk */
+ AM33XX_IOPAD(0x8ec, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* lcd_ac_bias_en.lcd_ac_bias_en */
+ >;
+ };
+
+ nxp_hdmi_off_pins: nxp_hdmi_off_pins {
+ pinctrl-single,pins = <
+ AM33XX_IOPAD(0x9b0, PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* xdma_event_intr0 */
+ >;
+ };
+};
+
+&i2c0 {
+ tda19988 {
+ pinctrl-names = "default", "off";
+ pinctrl-0 = <&nxp_hdmi_bonelt_pins>;
+ pinctrl-1 = <&nxp_hdmi_bonelt_off_pins>;
+ };
+};
diff --git b/arch/arm/boot/dts/am335x-bone-pinmux-panel-1024x600-24bit.dtsi b/arch/arm/boot/dts/am335x-bone-pinmux-panel-1024x600-24bit.dtsi
new file mode 100644
index 0000000..65e5fbb
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-bone-pinmux-panel-1024x600-24bit.dtsi
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <dt-bindings/board/am335x-bbw-bbb-base.h>
+#include "am335x-peripheral-panel-1024x600-24bit.dtsi"
+
+/* cape universal */
+
+/*
+ *&ocp {
+ * P8_27_pinmux {
+ * state = "disabled";
+ * };
+ * P8_28_pinmux {
+ * state = "disabled";
+ * };
+ * P8_29_pinmux {
+ * state = "disabled";
+ * };
+ * P8_30_pinmux {
+ * state = "disabled";
+ * };
+ * P8_31_pinmux {
+ * state = "disabled";
+ * };
+ * P8_32_pinmux {
+ * state = "disabled";
+ * };
+ * P8_33_pinmux {
+ * state = "disabled";
+ * };
+ * P8_34_pinmux {
+ * state = "disabled";
+ * };
+ * P8_35_pinmux {
+ * state = "disabled";
+ * };
+ * P8_36_pinmux {
+ * state = "disabled";
+ * };
+ * P8_37_pinmux {
+ * state = "disabled";
+ * };
+ * P8_38_pinmux {
+ * state = "disabled";
+ * };
+ * P8_39_pinmux {
+ * state = "disabled";
+ * };
+ * P8_40_pinmux {
+ * state = "disabled";
+ * };
+ * P8_41_pinmux {
+ * state = "disabled";
+ * };
+ * P8_42_pinmux {
+ * state = "disabled";
+ * };
+ * P8_43_pinmux {
+ * state = "disabled";
+ * };
+ * P8_44_pinmux {
+ * state = "disabled";
+ * };
+ * P8_45_pinmux {
+ * state = "disabled";
+ * };
+ * P8_46_pinmux {
+ * state = "disabled";
+ * };
+ *};
+ */
+
+/* standard */
+
+&am33xx_pinmux {
+ lcd_24bit_pins: pinmux_lcd_24bit_pins {
+ pinctrl-single,pins = <
+
+ /* P8_45: lcd_data0.lcd_data0 */
+ BONE_P8_45 (PIN_OUTPUT | MUX_MODE0)
+ /* P8_46: lcd_data1.lcd_data1 */
+ BONE_P8_46 (PIN_OUTPUT | MUX_MODE0)
+ /* P8_43: lcd_data2.lcd_data2 */
+ BONE_P8_43 (PIN_OUTPUT | MUX_MODE0)
+ /* P8_44: lcd_data3.lcd_data3 */
+ BONE_P8_44 (PIN_OUTPUT | MUX_MODE0)
+ /* P8_41: lcd_data4.lcd_data4 */
+ BONE_P8_41 (PIN_OUTPUT | MUX_MODE0)
+ /* P8_42: lcd_data5.lcd_data5 */
+ BONE_P8_42 (PIN_OUTPUT | MUX_MODE0)
+ /* P8_39: lcd_data6.lcd_data6 */
+ BONE_P8_39 (PIN_OUTPUT | MUX_MODE0)
+ /* P8_40: lcd_data7.lcd_data7 */
+ BONE_P8_40 (PIN_OUTPUT | MUX_MODE0)
+ /* P8_37: lcd_data8.lcd_data8 */
+ BONE_P8_37 (PIN_OUTPUT | MUX_MODE0)
+ /* P8_38: lcd_data9.lcd_data9 */
+ BONE_P8_38 (PIN_OUTPUT | MUX_MODE0)
+ /* P8_36: lcd_data10.lcd_data10 */
+ BONE_P8_36 (PIN_OUTPUT | MUX_MODE0)
+ /* P8_34: lcd_data11.lcd_data11 */
+ BONE_P8_34 (PIN_OUTPUT | MUX_MODE0)
+ /* P8_35: lcd_data12.lcd_data12 */
+ BONE_P8_35 (PIN_OUTPUT | MUX_MODE0)
+ /* P8_33: lcd_data13.lcd_data13 */
+ BONE_P8_33 (PIN_OUTPUT | MUX_MODE0)
+ /* P8_31: lcd_data14.lcd_data14 */
+ BONE_P8_31 (PIN_OUTPUT | MUX_MODE0)
+ /* P8_32: lcd_data15.lcd_data15 */
+ BONE_P8_32 (PIN_OUTPUT | MUX_MODE0)
+
+ /* gpmc_ad15.lcd_data16 */
+ BONE_P8_15 (PIN_OUTPUT | MUX_MODE1)
+ /* gpmc_ad14.lcd_data17 */
+ BONE_P8_16 (PIN_OUTPUT | MUX_MODE1)
+ /* gpmc_ad13.lcd_data18 */
+ BONE_P8_11 (PIN_OUTPUT | MUX_MODE1)
+ /* gpmc_ad12.lcd_data19 */
+ BONE_P8_12 (PIN_OUTPUT | MUX_MODE1)
+ /* gpmc_ad11.lcd_data20 */
+ BONE_P8_17 (PIN_OUTPUT | MUX_MODE1)
+ /* gpmc_ad10.lcd_data21 */
+ BONE_P8_14 (PIN_OUTPUT | MUX_MODE1)
+ /* gpmc_ad9.lcd_data22 */
+ BONE_P8_13 (PIN_OUTPUT | MUX_MODE1)
+ /* gpmc_ad8.lcd_data23 */
+ BONE_P8_19 (PIN_OUTPUT | MUX_MODE1)
+
+ /* P8_27: lcd_vsync.lcd_vsync */
+ BONE_P8_27 (PIN_OUTPUT | MUX_MODE0)
+ /* P8_29: lcd_hsync.lcd_hsync */
+ BONE_P8_29 (PIN_OUTPUT | MUX_MODE0)
+ /* P8_28: lcd_pclk.lcd_pclk*/
+ BONE_P8_28 (PIN_OUTPUT | MUX_MODE0)
+ /* P8_30: lcd_ac_bias_en.lcd_ac_bias_en */
+ BONE_P8_30 (PIN_OUTPUT | MUX_MODE0)
+ >;
+ };
+};
+
+/ {
+ panel {
+ pinctrl-0 = <&lcd_24bit_pins>;
+ };
+};
diff --git b/arch/arm/boot/dts/am335x-bone-pinmux-spi0.dtsi b/arch/arm/boot/dts/am335x-bone-pinmux-spi0.dtsi
new file mode 100644
index 0000000..354e66a
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-bone-pinmux-spi0.dtsi
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <dt-bindings/board/am335x-bbw-bbb-base.h>
+#include "am335x-peripheral-spi0.dtsi"
+
+/* cape universal */
+
+/*
+ *&ocp {
+ * P9_17_pinmux {
+ * status = "disabled";
+ * };
+ * P9_18_pinmux {
+ * status = "disabled";
+ * };
+ * P9_21_pinmux {
+ * status = "disabled";
+ * };
+ * P9_22_pinmux {
+ * status = "disabled";
+ * };
+ *};
+ *
+ *&spi0 {
+ * pinctrl-0 = <>;
+ *};
+ *
+ */
+
+/* standard */
+
+&am33xx_pinmux {
+ spi0_pins: pinmux_spi0_pins {
+ pinctrl-single,pins = <
+ 0x150 (PIN_INPUT_PULLUP | MUX_MODE0) /* spi0_sclk.spi0_sclk */
+ 0x154 (PIN_INPUT_PULLUP | MUX_MODE0) /* spi0_d0.spi0_d0 */
+ 0x158 (PIN_OUTPUT_PULLUP | MUX_MODE0) /* spi0_d1.spi0_d1 */
+ 0x15c (PIN_OUTPUT_PULLUP | MUX_MODE0) /* spi0_cs0.spi0_cs0 */
+ >;
+ };
+};
+
+&spi0 {
+ pinctrl-0 = <&spi0_pins>;
+};
diff --git b/arch/arm/boot/dts/am335x-bone-pinmux-spi1.dtsi b/arch/arm/boot/dts/am335x-bone-pinmux-spi1.dtsi
new file mode 100644
index 0000000..bff7f8d
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-bone-pinmux-spi1.dtsi
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <dt-bindings/board/am335x-bbw-bbb-base.h>
+#include "am335x-peripheral-spi1.dtsi"
+
+/* standard */
+
+&am33xx_pinmux {
+ spi1_pins: pinmux_spi1_pins {
+ pinctrl-single,pins = <
+ 0x190 0x33 /* mcasp0_aclkx.spi1_sclk, INPUT_PULLUP | MODE3 */
+ 0x194 0x33 /* mcasp0_fsx.spi1_d0, INPUT_PULLUP | MODE3 */
+ 0x198 0x13 /* mcasp0_axr0.spi1_d1, OUTPUT_PULLUP | MODE3 */
+ 0x19c 0x13 /* mcasp0_ahclkr.spi1_cs0, OUTPUT_PULLUP | MODE3 */
+ // 0x164 0x12 /* eCAP0_in_PWM0_out.spi1_cs1 OUTPUT_PULLUP | MODE2 */ >;
+ };
+};
+
+&spi1 {
+ pinctrl-0 = <&spi1_pins>;
+};
diff --git b/arch/arm/boot/dts/am335x-bone-pinmux-spi1a.dtsi b/arch/arm/boot/dts/am335x-bone-pinmux-spi1a.dtsi
new file mode 100644
index 0000000..62874c8
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-bone-pinmux-spi1a.dtsi
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <dt-bindings/board/am335x-bbw-bbb-base.h>
+#include "am335x-peripheral-spi1.dtsi"
+
+/* standard */
+
+&am33xx_pinmux {
+ spi1a_pins: pinmux_spi1a_pins {
+ pinctrl-single,pins = <
+ 0x164 0x34 /* eCAP0_in_PWM0_out.spi1_sclk, INPUT_PULLUP | MODE4 */
+ /* NOTE: P9.42 is connected to two pads */
+ // 0x1A0 0x27 /* set the other pad to gpio input */
+ 0x194 0x33 /* mcasp0_fsx.spi1_d0, INPUT_PULLUP | MODE3 */
+ 0x198 0x13 /* mcasp0_axr0.spi1_d1, OUTPUT_PULLUP | MODE3 */
+ 0x178 0x14 /* uart1_ctsn.spi1_cs0, OUTPUT_PULLUP | MODE4 */ >;
+ };
+};
+
+&spi1 {
+ pinctrl-0 = <&spi1a_pins>;
+};
diff --git b/arch/arm/boot/dts/am335x-bone-pinmux-ttyS1.dtsi b/arch/arm/boot/dts/am335x-bone-pinmux-ttyS1.dtsi
new file mode 100644
index 0000000..ae5b813
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-bone-pinmux-ttyS1.dtsi
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* Testing */
+/* sudo /sbin/getty -L ttyS1 115200 vt102 */
+
+#include <dt-bindings/board/am335x-bbw-bbb-base.h>
+#include "am335x-peripheral-ttyS1.dtsi"
+
+/* cape universal */
+
+/*
+ *&ocp {
+ * P9_24_pinmux {
+ * mode = "uart";
+ * };
+ * P9_26_pinmux {
+ * mode = "uart";
+ * };
+ *};
+ *
+ *&uart1 {
+ * pinctrl-0 = <>;
+ *};
+ *
+ */
+
+/* standard */
+
+&am33xx_pinmux {
+ uart1_pins: pinmux_uart1_pins {
+ pinctrl-single,pins = <
+ /* P9_24: uart1_txd.uart1_txd */
+ BONE_P9_24 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)
+ /* P9_26: uart1_rxd.uart1_rxd */
+ BONE_P9_26 (PIN_INPUT_PULLUP | MUX_MODE0)
+ >;
+ };
+};
+
+&uart1 {
+ pinctrl-0 = <&uart1_pins>;
+};
diff --git b/arch/arm/boot/dts/am335x-bone-pinmux-ttyS2.dtsi b/arch/arm/boot/dts/am335x-bone-pinmux-ttyS2.dtsi
new file mode 100644
index 0000000..5fa593a
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-bone-pinmux-ttyS2.dtsi
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* Testing */
+/* sudo /sbin/getty -L ttyS2 115200 vt102 */
+
+#include <dt-bindings/board/am335x-bbw-bbb-base.h>
+#include "am335x-peripheral-ttyS2.dtsi"
+
+/* cape universal */
+
+/*
+ *&ocp {
+ * P9_21_pinmux {
+ * mode = "uart";
+ * };
+ * P9_22_pinmux {
+ * mode = "uart";
+ * };
+ *};
+ *
+ *&uart2 {
+ * pinctrl-0 = <>;
+ *};
+ *
+ */
+
+/* standard */
+
+&am33xx_pinmux {
+ uart2_pins: pinmux_uart2_pins {
+ pinctrl-single,pins = <
+ /* P9_21: spi0_d0.uart2_txd */
+ BONE_P9_21 (PIN_OUTPUT_PULLDOWN | MUX_MODE1)
+ /* P9_22: spi0_sclk.uart2_rxd */
+ BONE_P9_22 (PIN_INPUT_PULLUP | MUX_MODE1)
+ >;
+ };
+};
+
+&uart2 {
+ pinctrl-0 = <&uart2_pins>;
+};
diff --git b/arch/arm/boot/dts/am335x-bone-pinmux-ttyS4.dtsi b/arch/arm/boot/dts/am335x-bone-pinmux-ttyS4.dtsi
new file mode 100644
index 0000000..1d22a95
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-bone-pinmux-ttyS4.dtsi
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* Testing */
+/* sudo /sbin/getty -L ttyS4 115200 vt102 */
+
+#include <dt-bindings/board/am335x-bbw-bbb-base.h>
+#include "am335x-peripheral-ttyS4.dtsi"
+
+/* cape universal */
+
+/*
+ *&ocp {
+ * P9_11_pinmux {
+ * mode = "uart";
+ * };
+ * P9_13_pinmux {
+ * mode = "uart";
+ * };
+ *};
+ *
+ *&uart4 {
+ * pinctrl-0 = <>;
+ *};
+ *
+ */
+
+/* standard */
+
+&am33xx_pinmux {
+ uart4_pins: pinmux_uart4_pins {
+ pinctrl-single,pins = <
+ /* P9_11: gpmc_wait0.uart4_rxd_mux2 */
+ BONE_P9_11 (PIN_INPUT_PULLUP | MUX_MODE6)
+ /* P9_13: gpmc_wpn.uart4_txd_mux2 */
+ BONE_P9_13 (PIN_OUTPUT_PULLDOWN | MUX_MODE6)
+ >;
+ };
+};
+
+&uart4 {
+ pinctrl-0 = <&uart4_pins>;
+};
diff --git b/arch/arm/boot/dts/am335x-bone-pinmux-ttyS5.dtsi b/arch/arm/boot/dts/am335x-bone-pinmux-ttyS5.dtsi
new file mode 100644
index 0000000..01d0aec
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-bone-pinmux-ttyS5.dtsi
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* Testing */
+/* sudo /sbin/getty -L ttyS5 115200 vt102 */
+
+#include <dt-bindings/board/am335x-bbw-bbb-base.h>
+#include "am335x-peripheral-ttyS5.dtsi"
+
+/* cape universal */
+
+/*
+ *&ocp {
+ * P8_37_pinmux {
+ * mode = "uart";
+ * };
+ * P8_38_pinmux {
+ * mode = "uart";
+ * };
+ *};
+ *
+ *&uart5 {
+ * pinctrl-0 = <>;
+ *};
+ *
+ */
+
+/* standard */
+
+&am33xx_pinmux {
+ uart5_pins: pinmux_uart5_pins {
+ pinctrl-single,pins = <
+ /* P8_38: lcd_data9.uart5_rxd */
+ BONE_P8_38 (PIN_INPUT_PULLUP | MUX_MODE4)
+ /* P8_37: lcd_data8.uart5_txd */
+ BONE_P8_37 (PIN_OUTPUT_PULLDOWN | MUX_MODE4)
+ >;
+ };
+};
+
+&uart5 {
+ pinctrl-0 = <&uart5_pins>;
+};
diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
index 6b84937..3688fff 100644
--- a/arch/arm/boot/dts/am335x-bone.dts
+++ b/arch/arm/boot/dts/am335x-bone.dts
@@ -9,6 +9,7 @@
#include "am33xx.dtsi"
#include "am335x-bone-common.dtsi"
+/* #include "am335x-bone-jtag.dtsi" */
/ {
model = "TI AM335x BeagleBone";
diff --git b/arch/arm/boot/dts/am335x-boneblack-audio.dts b/arch/arm/boot/dts/am335x-boneblack-audio.dts
new file mode 100644
index 0000000..cac3626
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-boneblack-audio.dts
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include "am335x-bone-common.dtsi"
+
+/ {
+ model = "TI AM335x BeagleBone Black";
+ compatible = "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
+
+ clk_mcasp0_fixed: clk_mcasp0_fixed {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <24576000>;
+ };
+
+ clk_mcasp0: clk_mcasp0 {
+ #clock-cells = <0>;
+ compatible = "gpio-gate-clock";
+ clocks = <&clk_mcasp0_fixed>;
+ enable-gpios = <&gpio1 27 GPIO_ACTIVE_HIGH>; /* BeagleBone Black Clk enable on GPIO1_27 */
+ };
+};
+
+&ldo3_reg {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+};
+
+&mmc1 {
+ vmmc-supply = <&vmmcsd_fixed>;
+};
diff --git b/arch/arm/boot/dts/am335x-boneblack-bbb-exp-c.dts b/arch/arm/boot/dts/am335x-boneblack-bbb-exp-c.dts
new file mode 100644
index 0000000..8d795c0
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-boneblack-bbb-exp-c.dts
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include "am335x-bone-common-no-capemgr.dtsi"
+
+/ {
+ model = "TI AM335x BeagleBone Black";
+ compatible = "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
+};
+
+&ldo3_reg {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+};
+
+&mmc1 {
+ vmmc-supply = <&vmmcsd_fixed>;
+};
+
+&mmc2 {
+ vmmc-supply = <&vmmcsd_fixed>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&emmc_pins>;
+ bus-width = <8>;
+ status = "okay";
+};
+
+&cpu0_opp_table {
+ /*
+ * All PG 2.0 silicon may not support 1GHz but some of the early
+ * BeagleBone Blacks have PG 2.0 silicon which is guaranteed
+ * to support 1GHz OPP so enable it for PG 2.0 on this board.
+ */
+ oppnitro@1000000000 {
+ opp-supported-hw = <0x06 0x0100>;
+ };
+};
+
+#include "am335x-cape-bbb-exp-c.dtsi"
diff --git b/arch/arm/boot/dts/am335x-boneblack-bbb-exp-r.dts b/arch/arm/boot/dts/am335x-boneblack-bbb-exp-r.dts
new file mode 100644
index 0000000..5df881e
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-boneblack-bbb-exp-r.dts
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include "am335x-bone-common-no-capemgr.dtsi"
+
+/ {
+ model = "TI AM335x BeagleBone Black";
+ compatible = "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
+};
+
+&ldo3_reg {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+};
+
+&mmc1 {
+ vmmc-supply = <&vmmcsd_fixed>;
+};
+
+&mmc2 {
+ vmmc-supply = <&vmmcsd_fixed>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&emmc_pins>;
+ bus-width = <8>;
+ status = "okay";
+};
+
+&cpu0_opp_table {
+ /*
+ * All PG 2.0 silicon may not support 1GHz but some of the early
+ * BeagleBone Blacks have PG 2.0 silicon which is guaranteed
+ * to support 1GHz OPP so enable it for PG 2.0 on this board.
+ */
+ oppnitro@1000000000 {
+ opp-supported-hw = <0x06 0x0100>;
+ };
+};
+
+#include "am335x-cape-bbb-exp-r.dtsi"
diff --git b/arch/arm/boot/dts/am335x-boneblack-bbbmini.dts b/arch/arm/boot/dts/am335x-boneblack-bbbmini.dts
new file mode 100644
index 0000000..5ed89a2
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-boneblack-bbbmini.dts
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ * Modified by Mirko Denecke <mirkix@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include "am335x-bone-common.dtsi"
+
+#include <dt-bindings/board/am335x-bbw-bbb-base.h>
+#include <dt-bindings/pinctrl/am33xx.h>
+
+/ {
+ model = "TI AM335x BeagleBone Black";
+ compatible = "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
+};
+
+&ldo3_reg {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+};
+
+&mmc1 {
+ vmmc-supply = <&vmmcsd_fixed>;
+};
+
+&mmc2 {
+ vmmc-supply = <&vmmcsd_fixed>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&emmc_pins>;
+ bus-width = <8>;
+ status = "okay";
+};
+
+&cpu0_opp_table {
+ /*
+ * All PG 2.0 silicon may not support 1GHz but some of the early
+ * BeagleBone Blacks have PG 2.0 silicon which is guaranteed
+ * to support 1GHz OPP so enable it for PG 2.0 on this board.
+ */
+ oppnitro@1000000000 {
+ opp-supported-hw = <0x06 0x0100>;
+ };
+};
+
+&am33xx_pinmux {
+ dcan1_pins: pinmux_dcan1_pins {
+ pinctrl-single,pins = <
+ /* P9_26: uart1_rxd.d_can1_tx */
+ BONE_P9_26 (PIN_OUTPUT_PULLUP | MUX_MODE2)
+ /* P9_24: uart1_txd.d_can1_rx */
+ BONE_P9_24 (PIN_INPUT_PULLUP | MUX_MODE2)
+ >;
+ };
+
+ pru_pins: pinmux_pru_pins {
+ pinctrl-single,pins = <
+ 0x03c 0x35 /* ecap0_in_pwm0_out.pr1_ecap0_ecap_capin, MODE5 | INPUT_PULLUP | PRU, PPM-sum, SBUS, DSM */
+
+ 0x0e8 0x25 /* lcd_pclk.pr1_pru1_pru_r30_10, MODE5 | OUTPUT | PRU, CH_1 */
+ 0x0e0 0x25 /* lcd_vsync.pr1_pru1_pru_r30_8, MODE5 | OUTPUT | PRU, CH_2 */
+ 0x0ec 0x25 /* lcd_ac_bias_en.pr1_pru1_pru_r30_11, MODE5 | OUTPUT | PRU, CH_3 */
+ 0x0e4 0x25 /* lcd_hsync.pr1_pru1_pru_r30_9, MODE5 | OUTPUT | PRU, CH_4 */
+ 0x0bc 0x25 /* lcd_data7.pr1_pru1_pru_r30_7, MODE5 | OUTPUT | PRU, CH_5 */
+ 0x0b8 0x25 /* lcd_data6.pr1_pru1_pru_r30_6, MODE5 | OUTPUT | PRU, CH_6 */
+ 0x0b4 0x25 /* lcd_data5.pr1_pru1_pru_r30_5, MODE5 | OUTPUT | PRU, CH_7 */
+ 0x0b0 0x25 /* lcd_data4.pr1_pru1_pru_r30_4, MODE5 | OUTPUT | PRU, CH_8 */
+ 0x0ac 0x25 /* lcd_data3.pr1_pru1_pru_r30_3, MODE5 | OUTPUT | PRU, CH_9 */
+ 0x0a8 0x25 /* lcd_data2.pr1_pru1_pru_r30_2, MODE5 | OUTPUT | PRU, CH_10 */
+ 0x0a4 0x25 /* lcd_data1.pr1_pru1_pru_r30_1, MODE5 | OUTPUT | PRU, CH_11 */
+ 0x0a0 0x25 /* lcd_data0.pr1_pru1_pru_r30_0, MODE5 | OUTPUT | PRU, CH_12 */
+
+ BONE_P8_12 (PIN_OUTPUT_PULLDOWN | MUX_MODE6) /* HC-SR04 TRIG */
+ BONE_P8_16 (PIN_INPUT_PULLDOWN | MUX_MODE6) /* HC-SR04 ECHO */
+
+ BONE_P9_25 (PIN_INPUT_PULLDOWN | MUX_MODE6) /* MPU9250 INT */
+ >;
+ };
+
+ spi0_pins: pinmux_spi0_pins {
+ pinctrl-single,pins = <
+ /* P9_22: spi0_sclk.spi0_sclk */
+ BONE_P9_22 (PIN_INPUT_PULLUP | MUX_MODE0)
+ /* P9_21: spi0_d0.spi0_d0 */
+ BONE_P9_21 (PIN_INPUT_PULLUP | MUX_MODE0)
+ /* P9_18: spi0_d1.spi0_d1 */
+ BONE_P9_18 (PIN_OUTPUT_PULLUP | MUX_MODE0)
+ /* P9_17: spi0_cs0.spi0_cs0 */
+ BONE_P9_17 (PIN_OUTPUT_PULLUP | MUX_MODE0)
+ >;
+ };
+
+ spi1_pins: pinmux_spi1_pins {
+ pinctrl-single,pins = <
+ /* P9_31: mcasp0_aclkx.spi1_sclk */
+ BONE_P9_31 (PIN_INPUT_PULLUP | MUX_MODE3)
+
+ /* P9_29: mcasp0_fsx.spi1_d0 */
+ BONE_P9_29 (PIN_INPUT_PULLUP | MUX_MODE3)
+
+ /* P9_30: mcasp0_axr0.spi1_d1 */
+ BONE_P9_30 (PIN_OUTPUT_PULLUP | MUX_MODE3)
+
+ /* P9_28: mcasp0_ahclkr.spi1_cs0 */
+ BONE_P9_28 (PIN_OUTPUT_PULLUP | MUX_MODE3)
+
+ /* P9_19: uart1_rtsn.spi1_cs1 */
+/* BONE_P9_19 (PIN_OUTPUT_PULLUP | MUX_MODE4)*/
+
+ /* P9_42: ecap0_in_pwm0_out.spi1_cs1 */
+ BONE_P9_42A (PIN_OUTPUT_PULLUP | MUX_MODE2)
+ >;
+ };
+
+ uart4_pins: pinmux_uart4_pins {
+ pinctrl-single,pins = <
+ /* P9_11: gpmc_wait0.uart4_rxd_mux2 */
+ BONE_P9_11 (PIN_INPUT_PULLUP | MUX_MODE6)
+ /* P9_13: gpmc_wpn.uart4_txd_mux2 */
+ BONE_P9_13 (PIN_OUTPUT_PULLDOWN | MUX_MODE6)
+ >;
+ };
+
+ uart5_pins: pinmux_uart5_pins {
+ pinctrl-single,pins = <
+ /* P8_38: lcd_data9.uart5_rxd */
+ BONE_P8_38 (PIN_INPUT_PULLUP | MUX_MODE4)
+ /* P8_37: lcd_data8.uart5_txd */
+ BONE_P8_37 (PIN_OUTPUT_PULLDOWN | MUX_MODE4)
+ >;
+ };
+};
+
+&dcan1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&dcan1_pins>;
+ status = "okay";
+};
+
+&i2c2 {
+ clock-frequency = <400000>;
+};
+
+&spi0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi0_pins>;
+ status = "okay";
+
+ spi0_0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ spi-max-frequency = <24000000>;
+ reg = <0>;
+ compatible = "spidev";
+ };
+};
+
+&spi1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi1_pins>;
+ status = "okay";
+
+ spi1_0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ spi-max-frequency = <24000000>;
+ compatible = "spidev";
+ };
+
+ spi1_1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ spi-max-frequency = <24000000>;
+ compatible = "spidev";
+ };
+};
+
+&tscadc {
+ adc {
+ ti,adc-channels = <0 1>;
+ };
+};
+
+&pruss {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pru_pins>;
+ status = "okay";
+};
+
+&uart4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart4_pins>;
+ status = "okay";
+};
+
+&uart5 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart5_pins>;
+ status = "okay";
+};
diff --git b/arch/arm/boot/dts/am335x-boneblack-cape-bone-argus.dts b/arch/arm/boot/dts/am335x-boneblack-cape-bone-argus.dts
new file mode 100644
index 0000000..c97c912
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-boneblack-cape-bone-argus.dts
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include "am335x-bone-common-no-capemgr.dtsi"
+
+/ {
+ model = "TI AM335x BeagleBone Black";
+ compatible = "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
+};
+
+&ldo3_reg {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+};
+
+&mmc1 {
+ vmmc-supply = <&vmmcsd_fixed>;
+};
+
+&mmc2 {
+ vmmc-supply = <&vmmcsd_fixed>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&emmc_pins>;
+ bus-width = <8>;
+ status = "okay";
+};
+
+&cpu0_opp_table {
+ /*
+ * All PG 2.0 silicon may not support 1GHz but some of the early
+ * BeagleBone Blacks have PG 2.0 silicon which is guaranteed
+ * to support 1GHz OPP so enable it for PG 2.0 on this board.
+ */
+ oppnitro@1000000000 {
+ opp-supported-hw = <0x06 0x0100>;
+ };
+};
+
+&am33xx_pinmux {
+ nxp_hdmi_bonelt_pins: nxp_hdmi_bonelt_pins {
+ pinctrl-single,pins = <
+ AM33XX_IOPAD(0x9b0, PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* xdma_event_intr0 */
+ AM33XX_IOPAD(0x8a0, PIN_OUTPUT | MUX_MODE0) /* lcd_data0.lcd_data0 */
+ AM33XX_IOPAD(0x8a4, PIN_OUTPUT | MUX_MODE0) /* lcd_data1.lcd_data1 */
+ AM33XX_IOPAD(0x8a8, PIN_OUTPUT | MUX_MODE0) /* lcd_data2.lcd_data2 */
+ AM33XX_IOPAD(0x8ac, PIN_OUTPUT | MUX_MODE0) /* lcd_data3.lcd_data3 */
+ AM33XX_IOPAD(0x8b0, PIN_OUTPUT | MUX_MODE0) /* lcd_data4.lcd_data4 */
+ AM33XX_IOPAD(0x8b4, PIN_OUTPUT | MUX_MODE0) /* lcd_data5.lcd_data5 */
+ AM33XX_IOPAD(0x8b8, PIN_OUTPUT | MUX_MODE0) /* lcd_data6.lcd_data6 */
+ AM33XX_IOPAD(0x8bc, PIN_OUTPUT | MUX_MODE0) /* lcd_data7.lcd_data7 */
+ AM33XX_IOPAD(0x8c0, PIN_OUTPUT | MUX_MODE0) /* lcd_data8.lcd_data8 */
+ AM33XX_IOPAD(0x8c4, PIN_OUTPUT | MUX_MODE0) /* lcd_data9.lcd_data9 */
+ AM33XX_IOPAD(0x8c8, PIN_OUTPUT | MUX_MODE0) /* lcd_data10.lcd_data10 */
+ AM33XX_IOPAD(0x8cc, PIN_OUTPUT | MUX_MODE0) /* lcd_data11.lcd_data11 */
+ AM33XX_IOPAD(0x8d0, PIN_OUTPUT | MUX_MODE0) /* lcd_data12.lcd_data12 */
+ AM33XX_IOPAD(0x8d4, PIN_OUTPUT | MUX_MODE0) /* lcd_data13.lcd_data13 */
+ AM33XX_IOPAD(0x8d8, PIN_OUTPUT | MUX_MODE0) /* lcd_data14.lcd_data14 */
+ AM33XX_IOPAD(0x8dc, PIN_OUTPUT | MUX_MODE0) /* lcd_data15.lcd_data15 */
+ AM33XX_IOPAD(0x8e0, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* lcd_vsync.lcd_vsync */
+ AM33XX_IOPAD(0x8e4, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* lcd_hsync.lcd_hsync */
+ AM33XX_IOPAD(0x8e8, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* lcd_pclk.lcd_pclk */
+ AM33XX_IOPAD(0x8ec, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* lcd_ac_bias_en.lcd_ac_bias_en */
+ >;
+ };
+ nxp_hdmi_bonelt_off_pins: nxp_hdmi_bonelt_off_pins {
+ pinctrl-single,pins = <
+ AM33XX_IOPAD(0x9b0, PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* xdma_event_intr0 */
+ >;
+ };
+};
+
+&lcdc {
+ status = "okay";
+ port {
+ lcdc_0: endpoint@0 {
+ remote-endpoint = <&hdmi_0>;
+ };
+ };
+};
+
+&i2c0 {
+ tda19988 {
+ compatible = "nxp,tda998x";
+ reg = <0x70>;
+ pinctrl-names = "default", "off";
+ pinctrl-0 = <&nxp_hdmi_bonelt_pins>;
+ pinctrl-1 = <&nxp_hdmi_bonelt_off_pins>;
+
+ port {
+ hdmi_0: endpoint@0 {
+ remote-endpoint = <&lcdc_0>;
+ };
+ };
+ };
+};
+
+#include "am335x-bone-argus.dtsi"
diff --git b/arch/arm/boot/dts/am335x-boneblack-emmc-overlay.dts b/arch/arm/boot/dts/am335x-boneblack-emmc-overlay.dts
new file mode 100644
index 0000000..ccd358e
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-boneblack-emmc-overlay.dts
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include "am335x-bone-common.dtsi"
+/* #include <dt-bindings/display/tda998x.h> */
+/* #include "am335x-bone-jtag.dtsi" */
+
+/ {
+ model = "TI AM335x BeagleBone Black";
+ compatible = "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
+};
+
+&ldo3_reg {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+};
+
+&mmc1 {
+ vmmc-supply = <&vmmcsd_fixed>;
+};
+
+&mmc2 {
+ vmmc-supply = <&vmmcsd_fixed>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&emmc_pins>;
+ bus-width = <8>;
+ status = "okay";
+};
+
+&cpu0_opp_table {
+ /*
+ * All PG 2.0 silicon may not support 1GHz but some of the early
+ * BeagleBone Blacks have PG 2.0 silicon which is guaranteed
+ * to support 1GHz OPP so enable it for PG 2.0 on this board.
+ */
+ oppnitro@1000000000 {
+ opp-supported-hw = <0x06 0x0100>;
+ };
+};
diff --git b/arch/arm/boot/dts/am335x-boneblack-hdmi-overlay.dts b/arch/arm/boot/dts/am335x-boneblack-hdmi-overlay.dts
new file mode 100644
index 0000000..0582e57
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-boneblack-hdmi-overlay.dts
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include "am335x-bone-common.dtsi"
+#include <dt-bindings/display/tda998x.h>
+/* #include "am335x-bone-jtag.dtsi" */
+
+/ {
+ model = "TI AM335x BeagleBone Black";
+ compatible = "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
+};
+
+&ldo3_reg {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+};
+
+&mmc1 {
+ vmmc-supply = <&vmmcsd_fixed>;
+};
+
+/* EMMC in reset */
+&gpio1 {
+ emmc_rst {
+ gpio-hog;
+ gpios = <20 0>;
+ output-high;
+ line-name = "EMMC ResetN";
+ };
+};
+
+&cpu0_opp_table {
+ /*
+ * All PG 2.0 silicon may not support 1GHz but some of the early
+ * BeagleBone Blacks have PG 2.0 silicon which is guaranteed
+ * to support 1GHz OPP so enable it for PG 2.0 on this board.
+ */
+ oppnitro@1000000000 {
+ opp-supported-hw = <0x06 0x0100>;
+ };
+};
+
+&am33xx_pinmux {
+ nxp_hdmi_bonelt_pins: nxp_hdmi_bonelt_pins {
+ pinctrl-single,pins = <
+ AM33XX_IOPAD(0x9b0, PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* xdma_event_intr0 */
+ AM33XX_IOPAD(0x8a0, PIN_OUTPUT | MUX_MODE0) /* lcd_data0.lcd_data0 */
+ AM33XX_IOPAD(0x8a4, PIN_OUTPUT | MUX_MODE0) /* lcd_data1.lcd_data1 */
+ AM33XX_IOPAD(0x8a8, PIN_OUTPUT | MUX_MODE0) /* lcd_data2.lcd_data2 */
+ AM33XX_IOPAD(0x8ac, PIN_OUTPUT | MUX_MODE0) /* lcd_data3.lcd_data3 */
+ AM33XX_IOPAD(0x8b0, PIN_OUTPUT | MUX_MODE0) /* lcd_data4.lcd_data4 */
+ AM33XX_IOPAD(0x8b4, PIN_OUTPUT | MUX_MODE0) /* lcd_data5.lcd_data5 */
+ AM33XX_IOPAD(0x8b8, PIN_OUTPUT | MUX_MODE0) /* lcd_data6.lcd_data6 */
+ AM33XX_IOPAD(0x8bc, PIN_OUTPUT | MUX_MODE0) /* lcd_data7.lcd_data7 */
+ AM33XX_IOPAD(0x8c0, PIN_OUTPUT | MUX_MODE0) /* lcd_data8.lcd_data8 */
+ AM33XX_IOPAD(0x8c4, PIN_OUTPUT | MUX_MODE0) /* lcd_data9.lcd_data9 */
+ AM33XX_IOPAD(0x8c8, PIN_OUTPUT | MUX_MODE0) /* lcd_data10.lcd_data10 */
+ AM33XX_IOPAD(0x8cc, PIN_OUTPUT | MUX_MODE0) /* lcd_data11.lcd_data11 */
+ AM33XX_IOPAD(0x8d0, PIN_OUTPUT | MUX_MODE0) /* lcd_data12.lcd_data12 */
+ AM33XX_IOPAD(0x8d4, PIN_OUTPUT | MUX_MODE0) /* lcd_data13.lcd_data13 */
+ AM33XX_IOPAD(0x8d8, PIN_OUTPUT | MUX_MODE0) /* lcd_data14.lcd_data14 */
+ AM33XX_IOPAD(0x8dc, PIN_OUTPUT | MUX_MODE0) /* lcd_data15.lcd_data15 */
+ AM33XX_IOPAD(0x8e0, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* lcd_vsync.lcd_vsync */
+ AM33XX_IOPAD(0x8e4, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* lcd_hsync.lcd_hsync */
+ AM33XX_IOPAD(0x8e8, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* lcd_pclk.lcd_pclk */
+ AM33XX_IOPAD(0x8ec, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* lcd_ac_bias_en.lcd_ac_bias_en */
+ >;
+ };
+ nxp_hdmi_bonelt_off_pins: nxp_hdmi_bonelt_off_pins {
+ pinctrl-single,pins = <
+ AM33XX_IOPAD(0x9b0, PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* xdma_event_intr0 */
+ >;
+ };
+
+ mcasp0_pins: mcasp0_pins {
+ pinctrl-single,pins = <
+ AM33XX_IOPAD(0x9ac, PIN_INPUT_PULLUP | MUX_MODE0) /* mcasp0_ahcklx.mcasp0_ahclkx */
+ AM33XX_IOPAD(0x99c, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mcasp0_ahclkr.mcasp0_axr2*/
+ AM33XX_IOPAD(0x994, PIN_OUTPUT_PULLUP | MUX_MODE0) /* mcasp0_fsx.mcasp0_fsx */
+ AM33XX_IOPAD(0x990, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mcasp0_aclkx.mcasp0_aclkx */
+ AM33XX_IOPAD(0x86c, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a11.GPIO1_27 */
+ >;
+ };
+};
+
+&lcdc {
+ status = "okay";
+ port {
+ lcdc_0: endpoint@0 {
+ remote-endpoint = <&hdmi_0>;
+ };
+ };
+};
+
+&i2c0 {
+ tda19988: tda19988 {
+ compatible = "nxp,tda998x";
+ reg = <0x70>;
+
+ pinctrl-names = "default", "off";
+ pinctrl-0 = <&nxp_hdmi_bonelt_pins>;
+ pinctrl-1 = <&nxp_hdmi_bonelt_off_pins>;
+
+ #sound-dai-cells = <0>;
+ audio-ports = < TDA998x_I2S 0x03>;
+
+ ports {
+ port@0 {
+ hdmi_0: endpoint@0 {
+ remote-endpoint = <&lcdc_0>;
+ };
+ };
+ };
+ };
+};
+
+&mcasp0 {
+ #sound-dai-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&mcasp0_pins>;
+ status = "okay";
+ op-mode = <0>; /* MCASP_IIS_MODE */
+ tdm-slots = <2>;
+ serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */
+ 0 0 1 0
+ >;
+ tx-num-evt = <32>;
+ rx-num-evt = <32>;
+};
+
+/ {
+ clk_mcasp0_fixed: clk_mcasp0_fixed {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <24576000>;
+ };
+
+ clk_mcasp0: clk_mcasp0 {
+ #clock-cells = <0>;
+ compatible = "gpio-gate-clock";
+ clocks = <&clk_mcasp0_fixed>;
+ enable-gpios = <&gpio1 27 0>; /* BeagleBone Black Clk enable on GPIO1_27 */
+ };
+
+ sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "TI BeagleBone Black";
+ simple-audio-card,format = "i2s";
+ simple-audio-card,bitclock-master = <&dailink0_master>;
+ simple-audio-card,frame-master = <&dailink0_master>;
+
+ dailink0_master: simple-audio-card,cpu {
+ sound-dai = <&mcasp0>;
+ clocks = <&clk_mcasp0>;
+ };
+
+ simple-audio-card,codec {
+ sound-dai = <&tda19988>;
+ };
+ };
+};
diff --git b/arch/arm/boot/dts/am335x-boneblack-nhdmi-overlay.dts b/arch/arm/boot/dts/am335x-boneblack-nhdmi-overlay.dts
new file mode 100644
index 0000000..c166c90
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-boneblack-nhdmi-overlay.dts
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include "am335x-bone-common.dtsi"
+#include <dt-bindings/display/tda998x.h>
+/* #include "am335x-bone-jtag.dtsi" */
+
+/ {
+ model = "TI AM335x BeagleBone Black";
+ compatible = "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
+};
+
+&ldo3_reg {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+};
+
+&mmc1 {
+ vmmc-supply = <&vmmcsd_fixed>;
+};
+
+/* EMMC in reset */
+&gpio1 {
+ emmc_rst {
+ gpio-hog;
+ gpios = <20 0>;
+ output-high;
+ line-name = "EMMC ResetN";
+ };
+};
+
+&cpu0_opp_table {
+ /*
+ * All PG 2.0 silicon may not support 1GHz but some of the early
+ * BeagleBone Blacks have PG 2.0 silicon which is guaranteed
+ * to support 1GHz OPP so enable it for PG 2.0 on this board.
+ */
+ oppnitro@1000000000 {
+ opp-supported-hw = <0x06 0x0100>;
+ };
+};
+
+&am33xx_pinmux {
+ nxp_hdmi_bonelt_pins: nxp_hdmi_bonelt_pins {
+ pinctrl-single,pins = <
+ AM33XX_IOPAD(0x9b0, PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* xdma_event_intr0 */
+ AM33XX_IOPAD(0x8a0, PIN_OUTPUT | MUX_MODE0) /* lcd_data0.lcd_data0 */
+ AM33XX_IOPAD(0x8a4, PIN_OUTPUT | MUX_MODE0) /* lcd_data1.lcd_data1 */
+ AM33XX_IOPAD(0x8a8, PIN_OUTPUT | MUX_MODE0) /* lcd_data2.lcd_data2 */
+ AM33XX_IOPAD(0x8ac, PIN_OUTPUT | MUX_MODE0) /* lcd_data3.lcd_data3 */
+ AM33XX_IOPAD(0x8b0, PIN_OUTPUT | MUX_MODE0) /* lcd_data4.lcd_data4 */
+ AM33XX_IOPAD(0x8b4, PIN_OUTPUT | MUX_MODE0) /* lcd_data5.lcd_data5 */
+ AM33XX_IOPAD(0x8b8, PIN_OUTPUT | MUX_MODE0) /* lcd_data6.lcd_data6 */
+ AM33XX_IOPAD(0x8bc, PIN_OUTPUT | MUX_MODE0) /* lcd_data7.lcd_data7 */
+ AM33XX_IOPAD(0x8c0, PIN_OUTPUT | MUX_MODE0) /* lcd_data8.lcd_data8 */
+ AM33XX_IOPAD(0x8c4, PIN_OUTPUT | MUX_MODE0) /* lcd_data9.lcd_data9 */
+ AM33XX_IOPAD(0x8c8, PIN_OUTPUT | MUX_MODE0) /* lcd_data10.lcd_data10 */
+ AM33XX_IOPAD(0x8cc, PIN_OUTPUT | MUX_MODE0) /* lcd_data11.lcd_data11 */
+ AM33XX_IOPAD(0x8d0, PIN_OUTPUT | MUX_MODE0) /* lcd_data12.lcd_data12 */
+ AM33XX_IOPAD(0x8d4, PIN_OUTPUT | MUX_MODE0) /* lcd_data13.lcd_data13 */
+ AM33XX_IOPAD(0x8d8, PIN_OUTPUT | MUX_MODE0) /* lcd_data14.lcd_data14 */
+ AM33XX_IOPAD(0x8dc, PIN_OUTPUT | MUX_MODE0) /* lcd_data15.lcd_data15 */
+ AM33XX_IOPAD(0x8e0, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* lcd_vsync.lcd_vsync */
+ AM33XX_IOPAD(0x8e4, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* lcd_hsync.lcd_hsync */
+ AM33XX_IOPAD(0x8e8, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* lcd_pclk.lcd_pclk */
+ AM33XX_IOPAD(0x8ec, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* lcd_ac_bias_en.lcd_ac_bias_en */
+ >;
+ };
+ nxp_hdmi_bonelt_off_pins: nxp_hdmi_bonelt_off_pins {
+ pinctrl-single,pins = <
+ AM33XX_IOPAD(0x9b0, PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* xdma_event_intr0 */
+ >;
+ };
+};
+
+&lcdc {
+ status = "okay";
+ port {
+ lcdc_0: endpoint@0 {
+ remote-endpoint = <&hdmi_0>;
+ };
+ };
+};
+
+&i2c0 {
+ tda19988: tda19988 {
+ compatible = "nxp,tda998x";
+ reg = <0x70>;
+
+ pinctrl-names = "default", "off";
+ pinctrl-0 = <&nxp_hdmi_bonelt_pins>;
+ pinctrl-1 = <&nxp_hdmi_bonelt_off_pins>;
+
+ ports {
+ port@0 {
+ hdmi_0: endpoint@0 {
+ remote-endpoint = <&lcdc_0>;
+ };
+ };
+ };
+ };
+};
diff --git b/arch/arm/boot/dts/am335x-boneblack-overlay.dts b/arch/arm/boot/dts/am335x-boneblack-overlay.dts
new file mode 100644
index 0000000..e9bbd93
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-boneblack-overlay.dts
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include "am335x-bone-common.dtsi"
+/* #include <dt-bindings/display/tda998x.h> */
+/* #include "am335x-bone-jtag.dtsi" */
+
+/ {
+ model = "TI AM335x BeagleBone Black";
+ compatible = "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
+};
+
+&ldo3_reg {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+};
+
+&mmc1 {
+ vmmc-supply = <&vmmcsd_fixed>;
+};
+
+/* EMMC in reset */
+&gpio1 {
+ emmc_rst {
+ gpio-hog;
+ gpios = <20 0>;
+ output-high;
+ line-name = "EMMC ResetN";
+ };
+};
+
+&cpu0_opp_table {
+ /*
+ * All PG 2.0 silicon may not support 1GHz but some of the early
+ * BeagleBone Blacks have PG 2.0 silicon which is guaranteed
+ * to support 1GHz OPP so enable it for PG 2.0 on this board.
+ */
+ oppnitro@1000000000 {
+ opp-supported-hw = <0x06 0x0100>;
+ };
+};
diff --git b/arch/arm/boot/dts/am335x-boneblack-roboticscape.dts b/arch/arm/boot/dts/am335x-boneblack-roboticscape.dts
new file mode 100644
index 0000000..16e9376
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-boneblack-roboticscape.dts
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+ /******************************************************************************
+ * This device tree serves to replace the need for an overlay when using
+ * the RoboticsCape. It is similar to the boneblue tree but preserves
+ * pin config for the black.
+ ******************************************************************************/
+
+
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include "am335x-bone-common-no-capemgr.dtsi"
+#include "am335x-bone-common-universal-pins.dtsi"
+/* #include "am33xx-pruss-rproc.dtsi" */
+#include "am335x-roboticscape.dtsi"
+
+/ {
+ model = "TI AM335x BeagleBone Black";
+ compatible = "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
+};
+
+&ldo3_reg {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+};
+
+&mmc1 {
+ vmmc-supply = <&vmmcsd_fixed>;
+};
+
+&mmc2 {
+ vmmc-supply = <&vmmcsd_fixed>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&emmc_pins>;
+ bus-width = <8>;
+ status = "okay";
+};
+
+&cpu0_opp_table {
+ /*
+ * All PG 2.0 silicon may not support 1GHz but some of the early
+ * BeagleBone Blacks have PG 2.0 silicon which is guaranteed
+ * to support 1GHz OPP so enable it for PG 2.0 on this board.
+ */
+ oppnitro@1000000000 {
+ opp-supported-hw = <0x06 0x0100>;
+ };
+};
diff --git b/arch/arm/boot/dts/am335x-boneblack-uboot.dts b/arch/arm/boot/dts/am335x-boneblack-uboot.dts
new file mode 100644
index 0000000..b2f6e36
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-boneblack-uboot.dts
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include "am335x-bone-common.dtsi"
+
+/ {
+ model = "TI AM335x BeagleBone Black";
+ compatible = "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
+};
+
+&ldo3_reg {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+};
+
+&mmc1 {
+ vmmc-supply = <&vmmcsd_fixed>;
+};
diff --git b/arch/arm/boot/dts/am335x-boneblack-wireless-emmc-overlay.dts b/arch/arm/boot/dts/am335x-boneblack-wireless-emmc-overlay.dts
new file mode 100644
index 0000000..78f63bf
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-boneblack-wireless-emmc-overlay.dts
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include "am335x-bone-common.dtsi"
+/* #include <dt-bindings/display/tda998x.h> */
+#include "am335x-boneblack-wl1835.dtsi"
+/* #include "am335x-bone-jtag.dtsi" */
+
+/ {
+ model = "TI AM335x BeagleBone Black Wireless";
+ compatible = "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
+};
+
+&ldo3_reg {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+};
+
+&mmc1 {
+ vmmc-supply = <&vmmcsd_fixed>;
+};
+
+&mmc2 {
+ vmmc-supply = <&vmmcsd_fixed>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&emmc_pins>;
+ bus-width = <8>;
+ status = "okay";
+};
+
+&mac {
+ status = "disabled";
+};
+
+&mmc3 {
+ status = "okay";
+};
diff --git b/arch/arm/boot/dts/am335x-boneblack-wireless-roboticscape.dts b/arch/arm/boot/dts/am335x-boneblack-wireless-roboticscape.dts
new file mode 100644
index 0000000..4a72d56
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-boneblack-wireless-roboticscape.dts
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+ /******************************************************************************
+ * This device tree serves to replace the need for an overlay when using
+ * the RoboticsCape. It is similar to the boneblue tree but preserves
+ * pin config for the black.
+ ******************************************************************************/
+
+
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include "am335x-bone-common-no-capemgr.dtsi"
+#include "am335x-bone-common-universal-pins.dtsi"
+/* #include "am33xx-pruss-rproc.dtsi" */
+#include "am335x-boneblack-wl1835.dtsi"
+#include "am335x-roboticscape.dtsi"
+
+/ {
+ model = "TI AM335x BeagleBone Black Wireless";
+ compatible = "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
+};
+
+&ldo3_reg {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+};
+
+&mmc1 {
+ vmmc-supply = <&vmmcsd_fixed>;
+};
+
+&mmc2 {
+ vmmc-supply = <&vmmcsd_fixed>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&emmc_pins>;
+ bus-width = <8>;
+ status = "okay";
+};
diff --git b/arch/arm/boot/dts/am335x-boneblack-wireless.dts b/arch/arm/boot/dts/am335x-boneblack-wireless.dts
new file mode 100644
index 0000000..9b39648
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-boneblack-wireless.dts
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include "am335x-bone-common.dtsi"
+#include <dt-bindings/display/tda998x.h>
+#include "am335x-boneblack-wl1835.dtsi"
+/* #include "am335x-bone-jtag.dtsi" */
+
+/ {
+ model = "TI AM335x BeagleBone Black Wireless";
+ compatible = "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
+};
+
+&ldo3_reg {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+};
+
+&mmc1 {
+ vmmc-supply = <&vmmcsd_fixed>;
+};
+
+&mmc2 {
+ vmmc-supply = <&vmmcsd_fixed>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&emmc_pins>;
+ bus-width = <8>;
+ status = "okay";
+};
+
+&mac {
+ status = "disabled";
+};
+
+&mmc3 {
+ status = "okay";
+};
+
+&am33xx_pinmux {
+ nxp_hdmi_bonelt_pins: nxp_hdmi_bonelt_pins {
+ pinctrl-single,pins = <
+ AM33XX_IOPAD(0x9b0, PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* xdma_event_intr0 */
+ AM33XX_IOPAD(0x8a0, PIN_OUTPUT | MUX_MODE0) /* lcd_data0.lcd_data0 */
+ AM33XX_IOPAD(0x8a4, PIN_OUTPUT | MUX_MODE0) /* lcd_data1.lcd_data1 */
+ AM33XX_IOPAD(0x8a8, PIN_OUTPUT | MUX_MODE0) /* lcd_data2.lcd_data2 */
+ AM33XX_IOPAD(0x8ac, PIN_OUTPUT | MUX_MODE0) /* lcd_data3.lcd_data3 */
+ AM33XX_IOPAD(0x8b0, PIN_OUTPUT | MUX_MODE0) /* lcd_data4.lcd_data4 */
+ AM33XX_IOPAD(0x8b4, PIN_OUTPUT | MUX_MODE0) /* lcd_data5.lcd_data5 */
+ AM33XX_IOPAD(0x8b8, PIN_OUTPUT | MUX_MODE0) /* lcd_data6.lcd_data6 */
+ AM33XX_IOPAD(0x8bc, PIN_OUTPUT | MUX_MODE0) /* lcd_data7.lcd_data7 */
+ AM33XX_IOPAD(0x8c0, PIN_OUTPUT | MUX_MODE0) /* lcd_data8.lcd_data8 */
+ AM33XX_IOPAD(0x8c4, PIN_OUTPUT | MUX_MODE0) /* lcd_data9.lcd_data9 */
+ AM33XX_IOPAD(0x8c8, PIN_OUTPUT | MUX_MODE0) /* lcd_data10.lcd_data10 */
+ AM33XX_IOPAD(0x8cc, PIN_OUTPUT | MUX_MODE0) /* lcd_data11.lcd_data11 */
+ AM33XX_IOPAD(0x8d0, PIN_OUTPUT | MUX_MODE0) /* lcd_data12.lcd_data12 */
+ AM33XX_IOPAD(0x8d4, PIN_OUTPUT | MUX_MODE0) /* lcd_data13.lcd_data13 */
+ AM33XX_IOPAD(0x8d8, PIN_OUTPUT | MUX_MODE0) /* lcd_data14.lcd_data14 */
+ AM33XX_IOPAD(0x8dc, PIN_OUTPUT | MUX_MODE0) /* lcd_data15.lcd_data15 */
+ AM33XX_IOPAD(0x8e0, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* lcd_vsync.lcd_vsync */
+ AM33XX_IOPAD(0x8e4, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* lcd_hsync.lcd_hsync */
+ AM33XX_IOPAD(0x8e8, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* lcd_pclk.lcd_pclk */
+ AM33XX_IOPAD(0x8ec, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* lcd_ac_bias_en.lcd_ac_bias_en */
+ >;
+ };
+ nxp_hdmi_bonelt_off_pins: nxp_hdmi_bonelt_off_pins {
+ pinctrl-single,pins = <
+ AM33XX_IOPAD(0x9b0, PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* xdma_event_intr0 */
+ >;
+ };
+
+ mcasp0_pins: mcasp0_pins {
+ pinctrl-single,pins = <
+ AM33XX_IOPAD(0x9ac, PIN_INPUT_PULLUP | MUX_MODE0) /* mcasp0_ahcklx.mcasp0_ahclkx */
+ AM33XX_IOPAD(0x99c, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mcasp0_ahclkr.mcasp0_axr2*/
+ AM33XX_IOPAD(0x994, PIN_OUTPUT_PULLUP | MUX_MODE0) /* mcasp0_fsx.mcasp0_fsx */
+ AM33XX_IOPAD(0x990, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mcasp0_aclkx.mcasp0_aclkx */
+ AM33XX_IOPAD(0x86c, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a11.GPIO1_27 */
+ >;
+ };
+};
+
+&lcdc {
+ status = "okay";
+ port {
+ lcdc_0: endpoint@0 {
+ remote-endpoint = <&hdmi_0>;
+ };
+ };
+};
+
+&i2c0 {
+ tda19988: tda19988 {
+ compatible = "nxp,tda998x";
+ reg = <0x70>;
+
+ pinctrl-names = "default", "off";
+ pinctrl-0 = <&nxp_hdmi_bonelt_pins>;
+ pinctrl-1 = <&nxp_hdmi_bonelt_off_pins>;
+
+ #sound-dai-cells = <0>;
+ audio-ports = < TDA998x_I2S 0x03>;
+
+ ports {
+ port@0 {
+ hdmi_0: endpoint@0 {
+ remote-endpoint = <&lcdc_0>;
+ };
+ };
+ };
+ };
+};
+
+&mcasp0 {
+ #sound-dai-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&mcasp0_pins>;
+ status = "okay";
+ op-mode = <0>; /* MCASP_IIS_MODE */
+ tdm-slots = <2>;
+ serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */
+ 0 0 1 0
+ >;
+ tx-num-evt = <32>;
+ rx-num-evt = <32>;
+};
+
+/ {
+ clk_mcasp0_fixed: clk_mcasp0_fixed {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <24576000>;
+ };
+
+ clk_mcasp0: clk_mcasp0 {
+ #clock-cells = <0>;
+ compatible = "gpio-gate-clock";
+ clocks = <&clk_mcasp0_fixed>;
+ enable-gpios = <&gpio1 27 0>; /* BeagleBone Black Clk enable on GPIO1_27 */
+ };
+
+ sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "TI BeagleBone Black";
+ simple-audio-card,format = "i2s";
+ simple-audio-card,bitclock-master = <&dailink0_master>;
+ simple-audio-card,frame-master = <&dailink0_master>;
+
+ dailink0_master: simple-audio-card,cpu {
+ sound-dai = <&mcasp0>;
+ clocks = <&clk_mcasp0>;
+ };
+
+ simple-audio-card,codec {
+ sound-dai = <&tda19988>;
+ };
+ };
+};
diff --git b/arch/arm/boot/dts/am335x-boneblack-wl1835.dtsi b/arch/arm/boot/dts/am335x-boneblack-wl1835.dtsi
new file mode 100644
index 0000000..ec6c0e4
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-boneblack-wl1835.dtsi
@@ -0,0 +1,143 @@
+
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+ wlan_en_reg: fixedregulator@2 {
+ compatible = "regulator-fixed";
+ regulator-name = "wlan-en-regulator";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ startup-delay-us= <70000>;
+
+ /* WL_EN */
+ gpio = <&gpio3 9 0>;
+ enable-active-high;
+ };
+
+ leds {
+ pinctrl-names = "default";
+ pinctrl-0 = <&wl18xx_pins>;
+ compatible = "gpio-leds";
+
+ wl18xx_bt_en {
+ label = "wl18xx_bt_en";
+ gpios = <&gpio0 28 GPIO_ACTIVE_HIGH>;
+ default-state = "off";
+ };
+ };
+
+ btwilink {
+ compatible = "btwilink";
+ };
+};
+
+&am33xx_pinmux {
+ wl18xx_pins: pinmux_wl18xx_pins {
+ pinctrl-single,pins = <
+ 0x128 (PIN_OUTPUT_PULLUP | MUX_MODE7) /* (K17) gmii1_txd0.gpio0[28] - BT_EN */
+ >;
+ };
+
+ wlbtbuf_pin: pinmux_wlbtbuf_pin {
+ pinctrl-single,pins = <
+ 0x130 ( PIN_OUTPUT_PULLUP | MUX_MODE7 ) /* (L18) gmii1_rxclk.gpio3[10] - LS_BUF_EN */
+ >;
+ };
+
+ mmc3_pins: pinmux_mmc3_pins {
+ pinctrl-single,pins = <
+ 0x13c ( PIN_INPUT_PULLUP | MUX_MODE6 ) /* (L15) gmii1_rxd1.mmc2_clk */
+ 0x114 ( PIN_INPUT_PULLUP | MUX_MODE6 ) /* (J16) gmii1_txen.mmc2_cmd */
+ 0x118 ( PIN_INPUT_PULLUP | MUX_MODE5 ) /* (J17) gmii1_rxdv.mmc2_dat0 */
+ 0x11c ( PIN_INPUT_PULLUP | MUX_MODE5 ) /* (J18) gmii1_txd3.mmc2_dat1 */
+ 0x120 ( PIN_INPUT_PULLUP | MUX_MODE5 ) /* (K15) gmii1_txd2.mmc2_dat2 */
+ 0x108 ( PIN_INPUT_PULLUP | MUX_MODE5 ) /* (H16) gmii1_col.mmc2_dat3 */
+ >;
+ };
+
+ mmc3_pins_sleep: pinmux_mmc3_pins_sleep {
+ pinctrl-single,pins = <
+ 0x13c ( PIN_INPUT_PULLDOWN | MUX_MODE6 ) /* (L15) gmii1_rxd1.mmc2_clk */
+ 0x114 ( PIN_INPUT_PULLDOWN | MUX_MODE6 ) /* (J16) gmii1_txen.mmc2_cmd */
+ 0x118 ( PIN_INPUT_PULLDOWN | MUX_MODE5 ) /* (J17) gmii1_rxdv.mmc2_dat0 */
+ 0x11c ( PIN_INPUT_PULLDOWN | MUX_MODE5 ) /* (J18) gmii1_txd3.mmc2_dat1 */
+ 0x120 ( PIN_INPUT_PULLDOWN | MUX_MODE5 ) /* (K15) gmii1_txd2.mmc2_dat2 */
+ 0x108 ( PIN_INPUT_PULLDOWN | MUX_MODE5 ) /* (H16) gmii1_col.mmc2_dat3 */
+ >;
+ };
+
+ /* wl18xx card enable/irq GPIOs. */
+ wlan_pins: pinmux_wlan_pins {
+ pinctrl-single,pins = <
+ 0x12c (PIN_OUTPUT_PULLDOWN | MUX_MODE7 ) /* (K18) gmii1_txclk.gpio3[9] - WL_EN */
+ 0x144 (PIN_INPUT_PULLDOWN | MUX_MODE7 ) /* (H18) rmii1_refclk.gpio0[29] - WL_IRQ */
+ >;
+ };
+
+ /* wl18xx card enable/irq GPIOs. */
+ wlan_pins_sleep: pinmux_wlan_pins_sleep {
+ pinctrl-single,pins = <
+ 0x12c (PIN_OUTPUT_PULLDOWN | MUX_MODE7 ) /* (K18) gmii1_txclk.gpio3[9] - WL_EN */
+ 0x144 (PIN_INPUT_PULLDOWN | MUX_MODE7 ) /* (H18) rmii1_refclk.gpio0[29] - WL_IRQ */
+ >;
+ };
+
+ uart3_pins_default: pinmux_uart3_pins_default {
+ pinctrl-single,pins = <
+ 0x134 ( PIN_INPUT_PULLUP | MUX_MODE1 ) /* (L17) gmii1_rxd3.uart3_rxd */
+ 0x138 ( PIN_OUTPUT_PULLDOWN | MUX_MODE1 ) /* (L16) gmii1_rxd2.uart3_txd */
+ 0x148 ( PIN_INPUT | MUX_MODE3 ) /* (M17) mdio_data.uart3_ctsn */
+ 0x14c ( PIN_OUTPUT_PULLDOWN | MUX_MODE3 ) /* (M18) mdio_clk.uart3_rtsn */
+ >;
+ };
+
+ uart3_pins_sleep: pinmux_uart3_pins_sleep {
+ pinctrl-single,pins = <
+ 0x134 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* (L17) gmii1_rxd3.uart3_rxd */
+ 0x138 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* (L16) gmii1_rxd2.uart3_txd */
+ 0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* (M17) mdio_data.uart3_ctsn */
+ 0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7) /* (M18) mdio_clk.uart3_rtsn */
+ >;
+ };
+};
+
+&mmc3 {
+ dmas = <&edma_xbar 12 0 1
+ &edma_xbar 13 0 2>;
+ dma-names = "tx", "rx";
+ status = "okay";
+ vmmc-supply = <&wlan_en_reg>;
+ bus-width = <4>;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&mmc3_pins &wlan_pins &wlbtbuf_pin>;
+ pinctrl-1 = <&mmc3_pins_sleep &wlan_pins_sleep &wlbtbuf_pin>;
+ ti,non-removable;
+ ti,needs-special-hs-handling;
+ cap-power-off-card;
+ keep-power-in-suspend;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+ wlcore: wlcore@0 {
+ compatible = "ti,wl1835";
+ reg = <2>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <29 IRQ_TYPE_EDGE_RISING>;
+ };
+};
+
+&uart3 {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&uart3_pins_default>;
+ pinctrl-1 = <&uart3_pins_sleep>;
+ status = "okay";
+};
+
+&gpio3 {
+ ls_buf_en {
+ gpio-hog;
+ gpios = <10 GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "LS_BUF_EN";
+ };
+};
diff --git b/arch/arm/boot/dts/am335x-boneblack-wl1835mod-cape.dtsi b/arch/arm/boot/dts/am335x-boneblack-wl1835mod-cape.dtsi
new file mode 100644
index 0000000..94caa22
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-boneblack-wl1835mod-cape.dtsi
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+ wlan_en_reg: fixedregulator@2 {
+ compatible = "regulator-fixed";
+ regulator-name = "wlan-en-regulator";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ /* WL_EN */
+ gpio = <&gpio0 26 0>;
+ enable-active-high;
+ };
+
+ kim {
+ compatible = "kim";
+ nshutdown_gpio = <44>; /* Bank1, pin12 */
+ dev_name = "/dev/ttyO4";
+ flow_cntrl = <1>;
+ baud_rate = <3000000>;
+ };
+
+ btwilink {
+ compatible = "btwilink";
+ };
+};
+
+&am33xx_pinmux {
+ bt_pins: pinmux_bt_pins {
+ pinctrl-single,pins = <
+ 0x30 (PIN_OUTPUT_PULLUP | MUX_MODE7) /* gpmc_ad12.gpio1_12 */
+ >;
+ };
+
+ mmc2_pins: pinmux_mmc2_pins {
+ pinctrl-single,pins = <
+ 0x80 (PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn1.mmc1_clk */
+ 0x84 (PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn2.mmc1_cmd */
+ 0x00 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad0.mmc1_dat0 */
+ 0x04 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad1.mmc1_dat1 */
+ 0x08 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad2.mmc1_dat2 */
+ 0x0c (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad3.mmc1_dat3 */
+ >;
+ };
+
+ mmc2_pins_sleep: pinmux_mmc2_pins_sleep {
+ pinctrl-single,pins = <
+ 0x80 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_csn1.mmc1_clk */
+ 0x84 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_csn2.mmc1_cmd */
+ 0x00 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad0.mmc1_dat0 */
+ 0x04 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad1.mmc1_dat1 */
+ 0x08 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad2.mmc1_dat2 */
+ 0x0c (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad3.mmc1_dat3 */
+ >;
+ };
+
+ /* wl18xx card enable/irq GPIOs. */
+ wlan_pins: pinmux_wlan_pins {
+ pinctrl-single,pins = <
+ 0x28 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad10.gpio0_26 WL_EN*/
+ 0x2C (PIN_INPUT_PULLUP | MUX_MODE7) /* gpmc_ad11.gpio0_27 WL_IRQ*/
+ 0x7C (PIN_OUTPUT_PULLUP | MUX_MODE0) /* gpmc_csn0.gpio1_29 BF_EN*/
+ >;
+ };
+
+ /* wl18xx card enable/irq GPIOs. */
+ wlan_pins_sleep: pinmux_wlan_pins_sleep {
+ pinctrl-single,pins = <
+ 0x28 (PIN_OUTPUT_PULLUP | MUX_MODE7) /* gpmc_ad10.gpio0_26 WL_EN*/
+ 0x2C (PIN_INPUT_PULLUP | MUX_MODE7) /* gpmc_ad11.gpio0_27 WL_IRQ*/
+ 0x7C (PIN_OUTPUT_PULLUP | MUX_MODE0) /* gpmc_csn0.gpio1_29 BF_EN*/
+ >;
+ };
+
+ uart4_pins_default: pinmux_uart4_pins_default {
+ pinctrl-single,pins = <
+ 0xD0 (PIN_INPUT | MUX_MODE6) /* lcd_data12.uart4_cts */
+ 0xD4 (PIN_OUTPUT_PULLDOWN | MUX_MODE6) /* lcd_data13.uart4_rts */
+ 0x70 (PIN_INPUT_PULLUP | MUX_MODE6) /* gpmc_wait0.uart4_rxd */
+ 0x74 (PIN_OUTPUT_PULLDOWN | MUX_MODE6) /* gpmc_wpn.uart4_txd */
+ >;
+ };
+
+ uart4_pins_sleep: pinmux_uart4_pins_sleep {
+ pinctrl-single,pins = <
+ 0xD0 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* lcd_data12.uart4_cts */
+ 0xD4 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* lcd_data13.uart4_rts */
+ 0x70 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_wait0.uart4_rxd */
+ 0x74 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_wpn.uart4_txd */
+ >;
+ };
+};
+
+&mmc2 {
+ status = "okay";
+ vmmc-supply = <&wlan_en_reg>;
+ bus-width = <4>;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&mmc2_pins &wlan_pins>;
+ pinctrl-1 = <&mmc2_pins_sleep &wlan_pins_sleep>;
+ ti,non-removable;
+ ti,needs-special-hs-handling;
+ cap-power-off-card;
+ keep-power-in-suspend;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+ wlcore: wlcore@0 {
+ compatible = "ti,wl1835";
+ reg = <2>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <27 IRQ_TYPE_LEVEL_HIGH>;
+ };
+};
+
+&uart4 {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&uart4_pins_default>;
+ pinctrl-1 = <&uart4_pins_sleep>;
+ status = "okay";
+};
diff --git b/arch/arm/boot/dts/am335x-boneblack-wl1835mod.dts b/arch/arm/boot/dts/am335x-boneblack-wl1835mod.dts
new file mode 100644
index 0000000..f35b64a
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-boneblack-wl1835mod.dts
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include "am335x-bone-common-no-capemgr.dtsi"
+
+/ {
+ model = "TI AM335x BeagleBone Black";
+ compatible = "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
+};
+
+&ldo3_reg {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+};
+
+&mmc1 {
+ vmmc-supply = <&vmmcsd_fixed>;
+};
+
+/* EMMC in reset */
+&gpio1 {
+ emmc_rst {
+ gpio-hog;
+ gpios = <20 0>;
+ output-high;
+ line-name = "EMMC ResetN";
+ };
+};
+
+&cpu0_opp_table {
+ /*
+ * All PG 2.0 silicon may not support 1GHz but some of the early
+ * BeagleBone Blacks have PG 2.0 silicon which is guaranteed
+ * to support 1GHz OPP so enable it for PG 2.0 on this board.
+ */
+ oppnitro@1000000000 {
+ opp-supported-hw = <0x06 0x0100>;
+ };
+};
+
+#include "am335x-boneblack-wl1835mod-cape.dtsi"
diff --git a/arch/arm/boot/dts/am335x-boneblack.dts b/arch/arm/boot/dts/am335x-boneblack.dts
index 6bbb1fe..8f5d559 100644
--- a/arch/arm/boot/dts/am335x-boneblack.dts
+++ b/arch/arm/boot/dts/am335x-boneblack.dts
@@ -10,6 +10,7 @@
#include "am33xx.dtsi"
#include "am335x-bone-common.dtsi"
#include <dt-bindings/display/tda998x.h>
+/* #include "am335x-bone-jtag.dtsi" */
/ {
model = "TI AM335x BeagleBone Black";
@@ -34,6 +35,17 @@
status = "okay";
};
+&cpu0_opp_table {
+ /*
+ * All PG 2.0 silicon may not support 1GHz but some of the early
+ * BeagleBone Blacks have PG 2.0 silicon which is guaranteed
+ * to support 1GHz OPP so enable it for PG 2.0 on this board.
+ */
+ oppnitro@1000000000 {
+ opp-supported-hw = <0x06 0x0100>;
+ };
+};
+
&am33xx_pinmux {
nxp_hdmi_bonelt_pins: nxp_hdmi_bonelt_pins {
pinctrl-single,pins = <
@@ -108,10 +120,6 @@
};
};
-&rtc {
- system-power-controller;
-};
-
&mcasp0 {
#sound-dai-cells = <0>;
pinctrl-names = "default";
diff --git b/arch/arm/boot/dts/am335x-boneblue-wl1835.dtsi b/arch/arm/boot/dts/am335x-boneblue-wl1835.dtsi
new file mode 100644
index 0000000..64731b0
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-boneblue-wl1835.dtsi
@@ -0,0 +1,143 @@
+
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+ wlan_en_reg: fixedregulator@2 {
+ compatible = "regulator-fixed";
+ regulator-name = "wlan-en-regulator";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ startup-delay-us= <70000>;
+
+ /* WL_EN */
+ gpio = <&gpio3 9 0>;
+ enable-active-high;
+ };
+
+ leds {
+ pinctrl-names = "default";
+ pinctrl-0 = <&wl18xx_pins>;
+ compatible = "gpio-leds";
+
+ wl18xx_bt_en {
+ label = "wl18xx_bt_en";
+ gpios = <&gpio0 28 GPIO_ACTIVE_HIGH>;
+ default-state = "off";
+ };
+ };
+
+ btwilink {
+ compatible = "btwilink";
+ };
+};
+
+&am33xx_pinmux {
+ wl18xx_pins: pinmux_wl18xx_pins {
+ pinctrl-single,pins = <
+ 0x128 (PIN_OUTPUT_PULLUP | MUX_MODE7) /* (K17) gmii1_txd0.gpio0[28] - BT_EN */
+ >;
+ };
+
+ wlbtbuf_pin: pinmux_wlbtbuf_pin {
+ pinctrl-single,pins = <
+ 0x130 ( PIN_OUTPUT_PULLUP | MUX_MODE7 ) /* (L18) gmii1_rxclk.gpio3[10] - LS_BUF_EN */
+ >;
+ };
+
+ mmc3_pins: pinmux_mmc3_pins {
+ pinctrl-single,pins = <
+ 0x13c ( PIN_INPUT_PULLUP | MUX_MODE6 ) /* (L15) gmii1_rxd1.mmc2_clk */
+ 0x114 ( PIN_INPUT_PULLUP | MUX_MODE6 ) /* (J16) gmii1_txen.mmc2_cmd */
+ 0x118 ( PIN_INPUT_PULLUP | MUX_MODE5 ) /* (J17) gmii1_rxdv.mmc2_dat0 */
+ 0x11c ( PIN_INPUT_PULLUP | MUX_MODE5 ) /* (J18) gmii1_txd3.mmc2_dat1 */
+ 0x120 ( PIN_INPUT_PULLUP | MUX_MODE5 ) /* (K15) gmii1_txd2.mmc2_dat2 */
+ 0x108 ( PIN_INPUT_PULLUP | MUX_MODE5 ) /* (H16) gmii1_col.mmc2_dat3 */
+ >;
+ };
+
+ mmc3_pins_sleep: pinmux_mmc3_pins_sleep {
+ pinctrl-single,pins = <
+ 0x13c ( PIN_INPUT_PULLDOWN | MUX_MODE6 ) /* (L15) gmii1_rxd1.mmc2_clk */
+ 0x114 ( PIN_INPUT_PULLDOWN | MUX_MODE6 ) /* (J16) gmii1_txen.mmc2_cmd */
+ 0x118 ( PIN_INPUT_PULLDOWN | MUX_MODE5 ) /* (J17) gmii1_rxdv.mmc2_dat0 */
+ 0x11c ( PIN_INPUT_PULLDOWN | MUX_MODE5 ) /* (J18) gmii1_txd3.mmc2_dat1 */
+ 0x120 ( PIN_INPUT_PULLDOWN | MUX_MODE5 ) /* (K15) gmii1_txd2.mmc2_dat2 */
+ 0x108 ( PIN_INPUT_PULLDOWN | MUX_MODE5 ) /* (H16) gmii1_col.mmc2_dat3 */
+ >;
+ };
+
+ /* wl18xx card enable/irq GPIOs. */
+ wlan_pins: pinmux_wlan_pins {
+ pinctrl-single,pins = <
+ 0x12c (PIN_OUTPUT_PULLDOWN | MUX_MODE7 ) /* (K18) gmii1_txclk.gpio3[9] - WL_EN */
+ 0x124 (PIN_INPUT_PULLUP | MUX_MODE7 ) /* (K16) gmii1_txd1.gpio0[21] - WL_IRQ */
+ >;
+ };
+
+ /* wl18xx card enable/irq GPIOs. */
+ wlan_pins_sleep: pinmux_wlan_pins_sleep {
+ pinctrl-single,pins = <
+ 0x12c (PIN_OUTPUT_PULLDOWN | MUX_MODE7 ) /* (K18) gmii1_txclk.gpio3[9] - WL_EN */
+ 0x124 (PIN_INPUT_PULLUP | MUX_MODE7 ) /* (K16) gmii1_txd1.gpio0[21] - WL_IRQ */
+ >;
+ };
+
+ uart3_pins_default: pinmux_uart3_pins_default {
+ pinctrl-single,pins = <
+ 0x134 ( PIN_INPUT_PULLUP | MUX_MODE1 ) /* (L17) gmii1_rxd3.uart3_rxd */
+ 0x138 ( PIN_OUTPUT_PULLDOWN | MUX_MODE1 ) /* (L16) gmii1_rxd2.uart3_txd */
+ 0x148 ( PIN_INPUT | MUX_MODE3 ) /* (M17) mdio_data.uart3_ctsn */
+ 0x14c ( PIN_OUTPUT_PULLDOWN | MUX_MODE3 ) /* (M18) mdio_clk.uart3_rtsn */
+ >;
+ };
+
+ uart3_pins_sleep: pinmux_uart3_pins_sleep {
+ pinctrl-single,pins = <
+ 0x134 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* (L17) gmii1_rxd3.uart3_rxd */
+ 0x138 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* (L16) gmii1_rxd2.uart3_txd */
+ 0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* (M17) mdio_data.uart3_ctsn */
+ 0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7) /* (M18) mdio_clk.uart3_rtsn */
+ >;
+ };
+};
+
+&mmc3 {
+ dmas = <&edma_xbar 12 0 1
+ &edma_xbar 13 0 2>;
+ dma-names = "tx", "rx";
+ status = "okay";
+ vmmc-supply = <&wlan_en_reg>;
+ bus-width = <4>;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&mmc3_pins &wlan_pins &wlbtbuf_pin>;
+ pinctrl-1 = <&mmc3_pins_sleep &wlan_pins_sleep &wlbtbuf_pin>;
+ ti,non-removable;
+ ti,needs-special-hs-handling;
+ cap-power-off-card;
+ keep-power-in-suspend;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+ wlcore: wlcore@0 {
+ compatible = "ti,wl1835";
+ reg = <2>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <21 IRQ_TYPE_EDGE_RISING>;
+ };
+};
+
+&uart3 {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&uart3_pins_default>;
+ pinctrl-1 = <&uart3_pins_sleep>;
+ status = "okay";
+};
+
+&gpio3 {
+ ls_buf_en {
+ gpio-hog;
+ gpios = <10 GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "LS_BUF_EN";
+ };
+};
diff --git b/arch/arm/boot/dts/am335x-boneblue.dts b/arch/arm/boot/dts/am335x-boneblue.dts
new file mode 100644
index 0000000..e2a2fb5
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-boneblue.dts
@@ -0,0 +1,569 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include "am335x-bone-common-no-capemgr.dtsi"
+#include "am335x-bone-common-universal-pins.dtsi"
+#include "am335x-boneblue-wl1835.dtsi"
+/* #include "am33xx-pruss-rproc.dtsi" */
+
+#define BLUE_IO(x, y) AM33XX_IOPAD((x)*4+0x800, (y)) /* not used anymore */
+
+
+/ {
+ model = "TI AM335x BeagleBone Blue";
+ compatible = "ti,am335x-bone-blue", "ti,am335x-bone", "ti,am33xx";
+};
+
+&ldo3_reg {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+};
+
+&mmc1 {
+ vmmc-supply = <&vmmcsd_fixed>;
+};
+
+&mmc2 {
+ vmmc-supply = <&vmmcsd_fixed>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&emmc_pins>;
+ bus-width = <8>;
+ status = "okay";
+};
+
+&mac {
+ status = "disabled";
+};
+
+/*******************************************************************************
+* Pin Muxing
+*******************************************************************************/
+&am33xx_pinmux {
+
+ /***************************************************************************
+ * Static Pinmux
+ ***************************************************************************/
+ mux_helper_pins: pins {
+ pinctrl-single,pins = <
+
+ /* GPIO Inputs */
+ 0x09c 0x37 /*P8.9 Pause BUTTON, input pullup*/
+ 0x098 0x37 /*P8.10 MODE BUTTON input pullup*/
+ 0x1AC 0x37 /*P9.25 MPU-9150 INTERRUPT IN*/
+
+ /* LEDs GPIO Out*/
+ 0x090 0x0F /* P8.7 R7 LED_RED */
+ 0x094 0x0F /* P8.8 T7 LED_GREEN */
+ 0x02C 0x0F /* P8.17 U12 BATT_LED_1 */
+ 0x0DC 0x0F /* P8.32 T5 BATT_LED_2 diff from cape! */
+ 0x07c 0x0F /* P8.26 V6 BATT_LED_3 */
+ 0x028 0x0F /* P8.14 T11 BATT_LED_4 */
+
+ /* Motor Control GPIO Out*/
+ 0x0a8 0x0F /*P8.43 MDIR_3B*/
+ 0x0ac 0x0F /*P8.44 MDIR_3A*/
+ 0x0a0 0x0F /*P8.45 MDIR_4A*/
+ 0x0a4 0x0F /*P8.46 MDIR_4B*/
+ 0x074 0x0F /*P9.13 MDIR_1B*/
+ 0x040 0x0F /*P9.15 MDIR_2A*/
+ 0x1b4 0x0F /*P9.41 MOT_STBY*/
+ 0x088 0x0F /*T13 MDIR_1A different from cape! */
+ 0x0D8 0x0F /*P8.31 MDIR_2B different from cape! */
+
+ /* HRPWM 1 */
+ 0x048 0x6 /* P9_14 | MODE 6 */
+ 0x04c 0x6 /* P9_16 | MODE 6 */
+
+ /* HRPWM 2 */
+ 0x020 0x4 /* P8_19 | MODE 4 */
+ 0x024 0x4 /* P8_13 | MODE 4 */
+
+ /* EQEP */
+ 0x1A0 0x31 /* P9_42,EQEP0A, MODE1 */
+ 0x1A4 0x31 /* P9_27,EQEP0B, MODE1 */
+ 0x0D4 0x32 /* P8_33,EQEP1B, MODE2 */
+ 0x0D0 0x32 /* P8_35,EQEP1A, MODE2 */
+ 0x030 0x34 /* P8_12,EQEP2A, MODE4 */
+ 0x034 0x34 /* P8_11,EQEP2B, MODE4 */
+
+ /* PRU encoder input */
+ 0x03c 0x36 /* P8_15,PRU0_r31_15,MODE6 */
+ 0x038 0x36 /* P8_16,PRU0_r31_16,MODE6 */
+
+ /* PRU Servo output */
+ 0x0e0 0x05 /*pru1_pru_r30_8, MODE5*/
+ 0x0e8 0x05 /*pru1_pru_r30_10, MODE5 */
+ 0x0e4 0x05 /*pr1_pru1_pru_r30_9, MODE5 */
+ 0x0ec 0x05 /*pru1_pru_r30_11, MODE5 */
+ 0x0b8 0x05 /*pru1_pru_r30_6, MODE5 */
+ 0x0bc 0x05 /*pru1_pru_r30_7, MODE5 */
+ 0x0b0 0x05 /*pru1_pru_r30_4, MODE5 */
+ 0x0b4 0x05 /*pru1_pru_r30_5, MODE5 */
+ 0x0C8 0x0F /*P8.36, SERVO_PWR GPIO OUT*/
+
+ /* I2C1 */
+ 0x15C 0x32 /* P9.17,i2c1_scl,INPUT_PULLUP,MODE2 */
+ 0x158 0x32 /* P9.18,i2c1_sda,INPUT_PULLUP,MODE2 */
+
+ /* I2C2 */
+ 0x17c 0x73 /* P9.19, i2c2_sda, mode 3 */
+ 0x178 0x73 /* P9.20, i2c2_sda, mode 3 */
+
+ /* UART5 */
+ 0x0C4 0x34 /* P8.38,uart5_rxd,MODE4 */
+ 0x0C0 0x14 /* P8.37,uart5_txd,MODE4 */
+
+ /* WILINK 8 */
+ 0x08c 0x0F /*P8.18 V12 A2DP FSYNC */
+ 0x078 0x0F /*P9.12 A2DP_CLOCK*/
+
+ /* DCAN */
+ 0x16c ( PIN_INPUT | MUX_MODE2 ) /* (E17) uart0_rtsn.dcan1_rx */
+ 0x168 ( PIN_OUTPUT | MUX_MODE2 ) /* (E18) uart0_ctsn.dcan1_tx */
+ >;
+
+ /***********************************************************************
+ * New configurable pinmux modes for pins not on Black headers
+ ***********************************************************************/
+ /* H18 SPI1_SS1 */
+ H18_default_pin: pinmux_H18_default_pin {
+ pinctrl-single,pins = < 0x144 ( PIN_OUTPUT | MUX_MODE4 ) >; };
+ H18_gpio_pin: pinmux_H18_gpio_pin {
+ pinctrl-single,pins = < 0x144 ( PIN_OUTPUT | MUX_MODE7 ) >; };
+ H18_gpio_pu_pin: pinmux_H18_gpio_pu_pin {
+ pinctrl-single,pins = < 0x144 ( PIN_INPUT_PULLUP | MUX_MODE7 ) >; };
+ H18_gpio_pd_pin: pinmux_H18_gpio_pd_pin {
+ pinctrl-single,pins = < 0x144 ( PIN_INPUT_PULLDOWN | MUX_MODE7 ) >; };
+ H18_spi_pin: pinmux_H18_spi_pin {
+ pinctrl-single,pins = < 0x144 ( PIN_OUTPUT | MUX_MODE2 ) >; };
+
+ /* C18 SPI1_SS2 */
+ C18_default_pin: pinmux_C18_default_pin {
+ pinctrl-single,pins = < 0x164 ( PIN_OUTPUT | MUX_MODE4 ) >; };
+ C18_gpio_pin: pinmux_C18_gpio_pin {
+ pinctrl-single,pins = < 0x164 ( PIN_OUTPUT | MUX_MODE7 ) >; };
+ C18_gpio_pu_pin: pinmux_C18_gpio_pu_pin {
+ pinctrl-single,pins = < 0x164 ( PIN_INPUT_PULLUP | MUX_MODE7 ) >; };
+ C18_gpio_pd_pin: pinmux_C18_gpio_pd_pin {
+ pinctrl-single,pins = < 0x164 ( PIN_INPUT_PULLDOWN | MUX_MODE7 ) >; };
+ C18_spi_pin: pinmux_C18_spi_pin {
+ pinctrl-single,pins = < 0x164 ( PIN_OUTPUT | MUX_MODE2 ) >; };
+
+ /* U16 BLUE_GP0_PIN_3 gpio 1_25 */
+ U16_default_pin: pinmux_U16_default_pin {
+ pinctrl-single,pins = < 0x064 ( PIN_INPUT_PULLUP | MUX_MODE7 ) >; };
+ U16_gpio_pin: pinmux_U16_gpio_pin {
+ pinctrl-single,pins = < 0x064 ( PIN_OUTPUT | MUX_MODE7 ) >; };
+ U16_gpio_pu_pin: pinmux_U16_gpio_pu_pin {
+ pinctrl-single,pins = < 0x064 ( PIN_INPUT_PULLUP | MUX_MODE7 ) >; };
+ U16_gpio_pd_pin: pinmux_U16_gpio_pd_pin {
+ pinctrl-single,pins = < 0x064 ( PIN_INPUT_PULLDOWN | MUX_MODE7 ) >; };
+
+ /* D13 BLUE_GP0_PIN_5 gpio 3_20 */
+ D13_default_pin: pinmux_D13_default_pin {
+ pinctrl-single,pins = < 0x1A8 ( PIN_INPUT_PULLUP | MUX_MODE7 ) >; };
+ D13_gpio_pin: pinmux_D13_gpio_pin {
+ pinctrl-single,pins = < 0x1A8 ( PIN_OUTPUT | MUX_MODE7 ) >; };
+ D13_gpio_pu_pin: pinmux_D13_gpio_pu_pin {
+ pinctrl-single,pins = < 0x1A8 ( PIN_INPUT_PULLUP | MUX_MODE7 ) >; };
+ D13_gpio_pd_pin: pinmux_D13_gpio_pd_pin {
+ pinctrl-single,pins = < 0x1A8 ( PIN_INPUT_PULLDOWN | MUX_MODE7 ) >; };
+
+ /* J15 BLUE_GP1_PIN_3 gpio 3_2 */
+ J15_default_pin: pinmux_J15_default_pin {
+ pinctrl-single,pins = < 0x110 ( PIN_INPUT_PULLUP | MUX_MODE7 ) >; };
+ J15_gpio_pin: pinmux_J15_gpio_pin {
+ pinctrl-single,pins = < 0x110 ( PIN_OUTPUT | MUX_MODE7 ) >; };
+ J15_gpio_pu_pin: pinmux_J15_gpio_pu_pin {
+ pinctrl-single,pins = < 0x110 ( PIN_INPUT_PULLUP | MUX_MODE7 ) >; };
+ J15_gpio_pd_pin: pinmux_J15_gpio_pd_pin {
+ pinctrl-single,pins = < 0x110 ( PIN_INPUT_PULLDOWN | MUX_MODE7 ) >; };
+
+ /* H17 BLUE_GP1_PIN_4 gpio 3_1 */
+ H17_default_pin: pinmux_H17_default_pin {
+ pinctrl-single,pins = < 0x10C ( PIN_INPUT_PULLUP | MUX_MODE7 ) >; };
+ H17_gpio_pin: pinmux_H17_gpio_pin {
+ pinctrl-single,pins = < 0x10C ( PIN_OUTPUT | MUX_MODE7 ) >; };
+ H17_gpio_pu_pin: pinmux_H17_gpio_pu_pin {
+ pinctrl-single,pins = < 0x10C ( PIN_INPUT_PULLUP | MUX_MODE7 ) >; };
+ H17_gpio_pd_pin: pinmux_H17_gpio_pd_pin {
+ pinctrl-single,pins = < 0x10C ( PIN_INPUT_PULLDOWN | MUX_MODE7 ) >; };
+ };
+
+};
+
+
+/*******************************************************************************
+* apply static and dynamic pinmux modes listed above. Pins shared with the black
+* header pins get the modes from am335x-boneblack-common-universal-pins.dtsi
+*******************************************************************************/
+&ocp {
+ /* activate the static pinmux helper list of pin modes above */
+ test_helper: helper {
+ compatible = "bone-pinmux-helper";
+ pinctrl-names = "default";
+ pinctrl-0 = <&mux_helper_pins>;
+
+ status = "okay";
+ };
+
+ /* UART4 RX DSM */
+ P9_11_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart";
+ pinctrl-0 = <&P9_11_default_pin>;
+ pinctrl-1 = <&P9_11_gpio_pin>;
+ pinctrl-2 = <&P9_11_gpio_pu_pin>;
+ pinctrl-3 = <&P9_11_gpio_pd_pin>;
+ pinctrl-4 = <&P9_11_uart_pin>;
+ };
+
+ /* UART 2 TX GPS*/
+ P9_21_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi", "uart", "i2c", "pwm";
+ pinctrl-0 = <&P9_21_default_pin>;
+ pinctrl-1 = <&P9_21_gpio_pin>;
+ pinctrl-2 = <&P9_21_gpio_pu_pin>;
+ pinctrl-3 = <&P9_21_gpio_pd_pin>;
+ pinctrl-4 = <&P9_21_spi_pin>;
+ pinctrl-5 = <&P9_21_uart_pin>;
+ pinctrl-6 = <&P9_21_i2c_pin>;
+ pinctrl-7 = <&P9_21_pwm_pin>;
+ };
+
+ /* UART 2 RX GPS */
+ P9_22_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi", "uart", "i2c", "pwm";
+ pinctrl-0 = <&P9_22_default_pin>;
+ pinctrl-1 = <&P9_22_gpio_pin>;
+ pinctrl-2 = <&P9_22_gpio_pu_pin>;
+ pinctrl-3 = <&P9_22_gpio_pd_pin>;
+ pinctrl-4 = <&P9_22_spi_pin>;
+ pinctrl-5 = <&P9_22_uart_pin>;
+ pinctrl-6 = <&P9_22_i2c_pin>;
+ pinctrl-7 = <&P9_22_pwm_pin>;
+ };
+
+ /* SPI MISO */
+ P9_29_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm", "spi", "pruout", "pruin";
+ pinctrl-0 = <&P9_29_default_pin>;
+ pinctrl-1 = <&P9_29_gpio_pin>;
+ pinctrl-2 = <&P9_29_gpio_pu_pin>;
+ pinctrl-3 = <&P9_29_gpio_pd_pin>;
+ pinctrl-4 = <&P9_29_pwm_pin>;
+ pinctrl-5 = <&P9_29_spi_pin>;
+ pinctrl-6 = <&P9_29_pruout_pin>;
+ pinctrl-7 = <&P9_29_pruin_pin>;
+ };
+
+ /* SPI MOSI */
+ P9_30_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm", "spi", "pruout", "pruin";
+ pinctrl-0 = <&P9_30_default_pin>;
+ pinctrl-1 = <&P9_30_gpio_pin>;
+ pinctrl-2 = <&P9_30_gpio_pu_pin>;
+ pinctrl-3 = <&P9_30_gpio_pd_pin>;
+ pinctrl-4 = <&P9_30_pwm_pin>;
+ pinctrl-5 = <&P9_30_spi_pin>;
+ pinctrl-6 = <&P9_30_pruout_pin>;
+ pinctrl-7 = <&P9_30_pruin_pin>;
+ };
+
+ /* SPI SCK */
+ P9_31_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm", "spi", "pruout", "pruin";
+ pinctrl-0 = <&P9_31_default_pin>;
+ pinctrl-1 = <&P9_31_gpio_pin>;
+ pinctrl-2 = <&P9_31_gpio_pu_pin>;
+ pinctrl-3 = <&P9_31_gpio_pd_pin>;
+ pinctrl-4 = <&P9_31_pwm_pin>;
+ pinctrl-5 = <&P9_31_spi_pin>;
+ pinctrl-6 = <&P9_31_pruout_pin>;
+ pinctrl-7 = <&P9_31_pruin_pin>;
+ };
+
+ /* SPI SS1 */
+ H18_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi";
+ pinctrl-0 = <&H18_default_pin>;
+ pinctrl-1 = <&H18_gpio_pin>;
+ pinctrl-2 = <&H18_gpio_pu_pin>;
+ pinctrl-3 = <&H18_gpio_pd_pin>;
+ pinctrl-4 = <&H18_spi_pin>;
+ };
+
+ /* SPI SS2 */
+ C18_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi";
+ pinctrl-0 = <&C18_default_pin>;
+ pinctrl-1 = <&C18_gpio_pin>;
+ pinctrl-2 = <&C18_gpio_pu_pin>;
+ pinctrl-3 = <&C18_gpio_pd_pin>;
+ pinctrl-4 = <&C18_spi_pin>;
+ };
+
+ /* UART 1 TX */
+ P9_24_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart", "can", "i2c", "pruin";
+ pinctrl-0 = <&P9_24_default_pin>;
+ pinctrl-1 = <&P9_24_gpio_pin>;
+ pinctrl-2 = <&P9_24_gpio_pu_pin>;
+ pinctrl-3 = <&P9_24_gpio_pd_pin>;
+ pinctrl-4 = <&P9_24_uart_pin>;
+ pinctrl-5 = <&P9_24_can_pin>;
+ pinctrl-6 = <&P9_24_i2c_pin>;
+ pinctrl-7 = <&P9_24_pruin_pin>;
+ };
+
+ /* UART 1 RX */
+ P9_26_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart", "can", "i2c", "pruin";
+ pinctrl-0 = <&P9_26_default_pin>;
+ pinctrl-1 = <&P9_26_gpio_pin>;
+ pinctrl-2 = <&P9_26_gpio_pu_pin>;
+ pinctrl-3 = <&P9_26_gpio_pd_pin>;
+ pinctrl-4 = <&P9_26_uart_pin>;
+ pinctrl-5 = <&P9_26_can_pin>;
+ pinctrl-6 = <&P9_26_i2c_pin>;
+ pinctrl-7 = <&P9_26_pruin_pin>;
+ };
+
+ /* U16 BLUE_GP0_PIN_3 gpio 1_25*/
+ U16_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd";
+ pinctrl-0 = <&U16_default_pin>;
+ pinctrl-1 = <&U16_gpio_pin>;
+ pinctrl-2 = <&U16_gpio_pu_pin>;
+ pinctrl-3 = <&U16_gpio_pd_pin>;
+ };
+
+
+ /* BLUE_GP0_PIN_3 gpio1_17*/
+ P9_23_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm";
+ pinctrl-0 = <&P9_23_default_pin>;
+ pinctrl-1 = <&P9_23_gpio_pin>;
+ pinctrl-2 = <&P9_23_gpio_pu_pin>;
+ pinctrl-3 = <&P9_23_gpio_pd_pin>;
+ pinctrl-4 = <&P9_23_pwm_pin>;
+ };
+
+ /* BLUE_GP0_PIN_5 gpio3_20 */
+ D13_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd";
+ pinctrl-0 = <&D13_default_pin>;
+ pinctrl-1 = <&D13_gpio_pin>;
+ pinctrl-2 = <&D13_gpio_pu_pin>;
+ pinctrl-3 = <&D13_gpio_pd_pin>;
+ };
+
+ /* BLUE_GP0_PIN_6 gpio3_17 */
+ P9_28_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm", "spi", "pwm2", "pruout", "pruin";
+ pinctrl-0 = <&P9_28_default_pin>;
+ pinctrl-1 = <&P9_28_gpio_pin>;
+ pinctrl-2 = <&P9_28_gpio_pu_pin>;
+ pinctrl-3 = <&P9_28_gpio_pd_pin>;
+ pinctrl-4 = <&P9_28_pwm_pin>;
+ pinctrl-5 = <&P9_28_spi_pin>;
+ pinctrl-6 = <&P9_28_pwm2_pin>;
+ pinctrl-7 = <&P9_28_pruout_pin>;
+ pinctrl-8 = <&P9_28_pruin_pin>;
+ };
+
+ /* BLUE_GP1_PIN_3 gpio3_2 */
+ J15_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd";
+ pinctrl-0 = <&J15_default_pin>;
+ pinctrl-1 = <&J15_gpio_pin>;
+ pinctrl-2 = <&J15_gpio_pu_pin>;
+ pinctrl-3 = <&J15_gpio_pd_pin>;
+ };
+
+ /* BLUE_GP1_PIN_4 gpio3_1 */
+ H17_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd";
+ pinctrl-0 = <&H17_default_pin>;
+ pinctrl-1 = <&H17_gpio_pin>;
+ pinctrl-2 = <&H17_gpio_pu_pin>;
+ pinctrl-3 = <&H17_gpio_pd_pin>;
+ };
+
+
+
+};
+
+
+/*******************************************************************************
+* PWMSS
+*******************************************************************************/
+&epwmss0 {
+ status = "okay";
+};
+
+&epwmss1 {
+ status = "okay";
+};
+
+&epwmss2 {
+ status = "okay";
+};
+
+&ehrpwm0 {
+ status = "okay";
+};
+
+&ehrpwm1 {
+ status = "okay";
+};
+
+&ehrpwm2 {
+ status = "okay";
+};
+
+
+/*******************************************************************************
+* EQEP
+*******************************************************************************/
+&eqep0 {
+ count_mode = <0>; /* 0 - Quadrature mode, normal 90 phase offset cha & chb. 1 - Direction mode. cha input = clock, chb input = direction */
+ swap_inputs = <0>; /* Are channel A and channel B swapped? (0 - no, 1 - yes) */
+ invert_qa = <1>; /* Should we invert the channel A input? */
+ invert_qb = <1>; /* Should we invert the channel B input? I invert these because my encoder outputs drive transistors that pull down the pins */
+ invert_qi = <0>; /* Should we invert the index input? */
+ invert_qs = <0>; /* Should we invert the strobe input? */
+ status = "okay";
+};
+
+&eqep1 {
+ count_mode = <0>; /* 0 - Quadrature mode, normal 90 phase offset cha & chb. 1 - Direction mode. cha input = clock, chb input = direction */
+ swap_inputs = <0>; /* Are channel A and channel B swapped? (0 - no, 1 - yes) */
+ invert_qa = <1>; /* Should we invert the channel A input? */
+ invert_qb = <1>; /* Should we invert the channel B input? I invert these because my encoder outputs drive transistors that pull down the pins */
+ invert_qi = <0>; /* Should we invert the index input? */
+ invert_qs = <0>; /* Should we invert the strobe input? */
+ status = "okay";
+};
+
+&eqep2 {
+ count_mode = <0>; /* 0 - Quadrature mode, normal 90 phase offset cha & chb. 1 - Direction mode. cha input = clock, chb input = direction */
+ swap_inputs = <0>; /* Are channel A and channel B swapped? (0 - no, 1 - yes) */
+ invert_qa = <1>; /* Should we invert the channel A input? */
+ invert_qb = <1>; /* Should we invert the channel B input? I invert these because my encoder outputs drive transistors that pull down the pins */
+ invert_qi = <0>; /* Should we invert the index input? */
+ invert_qs = <0>; /* Should we invert the strobe input? */
+ status = "okay";
+};
+
+
+/*******************************************************************************
+ UART
+*******************************************************************************/
+
+&uart1 {
+ status = "okay";
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&uart4 {
+ status = "okay";
+};
+
+&uart5 {
+ status = "okay";
+};
+
+
+/*******************************************************************************
+ PRU
+*******************************************************************************/
+&pruss {
+ status = "okay";
+};
+
+
+/*******************************************************************************
+ I2C
+*******************************************************************************/
+&i2c1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+ clock-frequency = <400000>;
+};
+
+&i2c2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+ clock-frequency = <400000>;
+};
+
+/*******************************************************************************
+ SPI
+*******************************************************************************/
+&spi1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+
+ channel@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "spidev";
+ reg = <0>;
+ spi-max-frequency = <24000000>;
+ };
+
+ channel@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "spidev";
+ reg = <1>;
+ spi-max-frequency = <24000000>;
+ };
+};
diff --git b/arch/arm/boot/dts/am335x-bonegreen-overlay.dts b/arch/arm/boot/dts/am335x-bonegreen-overlay.dts
new file mode 100644
index 0000000..a703fcd
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-bonegreen-overlay.dts
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include "am335x-bone-common.dtsi"
+
+/ {
+ model = "TI AM335x BeagleBone Green";
+ compatible = "ti,am335x-bone-green", "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
+};
+
+&ldo3_reg {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+};
+
+&mmc1 {
+ vmmc-supply = <&vmmcsd_fixed>;
+};
+
+/* EMMC in reset */
+&gpio1 {
+ emmc_rst {
+ gpio-hog;
+ gpios = <20 0>;
+ output-high;
+ line-name = "EMMC ResetN";
+ };
+};
diff --git b/arch/arm/boot/dts/am335x-bonegreen-wireless.dts b/arch/arm/boot/dts/am335x-bonegreen-wireless.dts
new file mode 100644
index 0000000..f37f39e
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-bonegreen-wireless.dts
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include "am335x-bone-common.dtsi"
+#include "am335x-bonegreen-wl1835.dtsi"
+/* #include "am335x-bone-jtag.dtsi" */
+
+/ {
+ model = "TI AM335x BeagleBone Green Wireless";
+ compatible = "ti,am335x-bone-green", "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
+};
+
+&ldo3_reg {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+};
+
+&mmc1 {
+ vmmc-supply = <&vmmcsd_fixed>;
+};
+
+&mmc2 {
+ vmmc-supply = <&vmmcsd_fixed>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&emmc_pins>;
+ bus-width = <8>;
+ status = "okay";
+};
+
+&uart3 {
+ status = "okay";
+};
+
+&mmc3 {
+ status = "okay";
+};
+
+&mac {
+ status = "disabled";
+};
diff --git b/arch/arm/boot/dts/am335x-bonegreen-wl1835.dtsi b/arch/arm/boot/dts/am335x-bonegreen-wl1835.dtsi
new file mode 100644
index 0000000..0d4798d
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-bonegreen-wl1835.dtsi
@@ -0,0 +1,147 @@
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+ wlan_en_reg: fixedregulator@2 {
+ compatible = "regulator-fixed";
+ regulator-name = "wlan-en-regulator";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ startup-delay-us= <70000>;
+
+ /* WL_EN */
+ gpio = <&gpio0 26 0>;
+ enable-active-high;
+ };
+
+ btwilink {
+ compatible = "btwilink";
+ };
+
+ wilink8_pcm: wilink8_pcm {
+ compatible = "ti,wilink8_bt";
+ status = "okay";
+ };
+
+ sound{
+ compatible = "ti,wilink8-bt-audio";
+ ti,model = "WILINK8_BT";
+ ti,audio-codec = <&wilink8_pcm>;
+ ti,mcasp-controller = <&mcasp0>;
+ ti,codec-clock-rate = <24000000>;
+ };
+};
+
+&am33xx_pinmux {
+ bt_pins: pinmux_bt_pins {
+ pinctrl-single,pins = <
+ 0x78 (PIN_OUTPUT | MUX_MODE7) /* gpmc_ad12.gpio1_28 BT_EN*/
+ >;
+ };
+
+ mmc3_pins: pinmux_mmc3_pins {
+ pinctrl-single,pins = <
+ 0x8c ( PIN_INPUT_PULLUP | MUX_MODE3 ) /* gpio2_1 gpmc_clk.mmc2_clk */
+ 0x88 ( PIN_INPUT_PULLUP | MUX_MODE3) /* gpio2_0 gpmc_csn3.mmc2_cmd */
+ 0x30 ( PIN_INPUT_PULLUP | MUX_MODE3 ) /* gpio1_12 gpmc_ad12.mmc2_dat0 */
+ 0x34 ( PIN_INPUT_PULLUP | MUX_MODE3 ) /* gpio1_13 gpmc_ad13.mmc2_dat1 */
+ 0x38 ( PIN_INPUT_PULLUP | MUX_MODE3 ) /* gpio1_14 gpmc_ad14.mmc2_dat2 */
+ 0x3c ( PIN_INPUT_PULLUP | MUX_MODE3 ) /* gpio1_15 gpmc_ad15.mmc2_dat3 */
+ >;
+ };
+
+ mmc3_pins_sleep: pinmux_mmc3_pins_sleep {
+ pinctrl-single,pins = <
+ 0x8c (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpio2_1 gpmc_clk.mmc2_clk */
+ 0x88 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpio2_0 gpmc_csn3.mmc2_cmd */
+ 0x30 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpio1_12 gpmc_ad12.mmc2_dat0 */
+ 0x34 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpio1_13 gpmc_ad13.mmc2_dat1 */
+ 0x38 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpio1_14 gpmc_ad14.mmc2_dat2 */
+ 0x3c (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpio1_15 gpmc_ad15.mmc2_dat3 */
+ >;
+ };
+
+ /* wl18xx card enable/irq GPIOs. */
+ wlan_pins: pinmux_wlan_pins {
+ pinctrl-single,pins = <
+ 0x28 (PIN_OUTPUT_PULLDOWN| MUX_MODE7) /* gpmc_ad10.gpio0_26 WL_EN*/
+ 0x2C (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad11.gpio0_27 WL_IRQ*/
+ 0x7C (PIN_OUTPUT_PULLUP | MUX_MODE0) /* gpmc_csn0.gpio1_29 Cape_Buffer_EN*/
+ >;
+ };
+
+ /* wl18xx card enable/irq GPIOs. */
+ wlan_pins_sleep: pinmux_wlan_pins_sleep {
+ pinctrl-single,pins = <
+ 0x28 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad10.gpio0_26 WL_EN*/
+ 0x2C (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad11.gpio0_27 WL_IRQ*/
+ 0x7C (PIN_OUTPUT_PULLUP | MUX_MODE0) /* gpmc_csn0.gpio1_29 Cape_Buffer_EN*/
+ >;
+ };
+
+ uart3_pins_default: pinmux_uart3_pins_default {
+ pinctrl-single,pins = <
+ 0x134 ( PIN_INPUT_PULLUP | MUX_MODE1 ) /* (L17) gmii1_rxd3.uart3_rxd */
+ 0x138 ( PIN_OUTPUT_PULLDOWN | MUX_MODE1 ) /* (L16) gmii1_rxd2.uart3_txd */
+ 0x148 ( PIN_INPUT | MUX_MODE3 ) /* (M17) mdio_data.uart3_ctsn */
+ 0x14c ( PIN_OUTPUT_PULLDOWN | MUX_MODE3 ) /* (M18) mdio_clk.uart3_rtsn */
+ >;
+ };
+
+ uart3_pins_sleep: pinmux_uart3_pins_sleep {
+ pinctrl-single,pins = <
+ 0x134 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* (L17) gmii1_rxd3.uart3_rxd */
+ 0x138 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* (L16) gmii1_rxd2.uart3_txd */
+ 0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* (M17) mdio_data.uart3_ctsn */
+ 0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7) /* (M18) mdio_clk.uart3_rtsn */
+ >;
+ };
+};
+
+&mmc3 {
+ dmas = <&edma_xbar 12 0 1
+ &edma_xbar 13 0 2>;
+ dma-names = "tx", "rx";
+ status = "okay";
+ vmmc-supply = <&wlan_en_reg>;
+ bus-width = <4>;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&mmc3_pins &wlan_pins>;
+ pinctrl-1 = <&mmc3_pins_sleep &wlan_pins_sleep>;
+ ti,non-removable;
+ ti,needs-special-hs-handling;
+ cap-power-off-card;
+ keep-power-in-suspend;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+ wlcore: wlcore@0 {
+ compatible = "ti,wl1835";
+ reg = <2>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <27 IRQ_TYPE_EDGE_RISING>;
+ };
+};
+
+&uart3 {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&uart3_pins_default &bt_pins>;
+ pinctrl-1 = <&uart3_pins_sleep &bt_pins>;
+ status = "okay";
+};
+
+/* BT_AUD_OUT from wl1835 has to be pulled low when WL_EN is activated. */
+/* in case it isn't, wilink8 ends up in one of the test modes that */
+/* intruces various issues (elp wkaeup timeouts etc.) */
+/* On the BBGW this pin is routed through the level shifter (U21) that */
+/* introduces a pullup on the line and wilink8 ends up in a bad state. */
+/* use a gpio hog to force this pin low. An alternative may be adding */
+/* an external pulldown on U21 pin 4. */
+
+&gpio3 {
+ bt_aud_in {
+ gpio-hog;
+ gpios = <16 GPIO_ACTIVE_HIGH>;
+ output-low;
+ line-name = "MCASP0_AXR0";
+ };
+};
diff --git a/arch/arm/boot/dts/am335x-bonegreen.dts b/arch/arm/boot/dts/am335x-bonegreen.dts
index dce3c86..647d4bf 100644
--- a/arch/arm/boot/dts/am335x-bonegreen.dts
+++ b/arch/arm/boot/dts/am335x-bonegreen.dts
@@ -9,6 +9,7 @@
#include "am33xx.dtsi"
#include "am335x-bone-common.dtsi"
+/* #include "am335x-bone-jtag.dtsi" */
/ {
model = "TI AM335x BeagleBone Green";
@@ -32,22 +33,3 @@
bus-width = <8>;
status = "okay";
};
-
-&am33xx_pinmux {
- uart2_pins: uart2_pins {
- pinctrl-single,pins = <
- AM33XX_IOPAD(0x950, PIN_INPUT | MUX_MODE1) /* spi0_sclk.uart2_rxd */
- AM33XX_IOPAD(0x954, PIN_OUTPUT | MUX_MODE1) /* spi0_d0.uart2_txd */
- >;
- };
-};
-
-&uart2 {
- pinctrl-names = "default";
- pinctrl-0 = <&uart2_pins>;
- status = "okay";
-};
-
-&rtc {
- system-power-controller;
-};
diff --git b/arch/arm/boot/dts/am335x-cape-bbb-exp-c.dtsi b/arch/arm/boot/dts/am335x-cape-bbb-exp-c.dtsi
new file mode 100644
index 0000000..01f9cde
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-cape-bbb-exp-c.dtsi
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <dt-bindings/board/am335x-bbw-bbb-base.h>
+
+#include "am335x-peripheral-can0.dtsi"
+#include "am335x-bone-pinmux-can0.dtsi"
+
+#include "am335x-peripheral-ttyS1.dtsi"
+#include "am335x-bone-pinmux-ttyS1.dtsi"
+
+#include "am335x-peripheral-ttyS2.dtsi"
+#include "am335x-bone-pinmux-ttyS2.dtsi"
+
+#include "am335x-peripheral-ttyS4.dtsi"
+#include "am335x-bone-pinmux-ttyS4.dtsi"
+
+&am33xx_pinmux {
+ user_leds_s1: user_leds_s1 {
+ pinctrl-single,pins = <
+ 0x98 0x7 /* gpmc_wen.gpio2_4, OUTPUT | MODE7 */
+ 0x9c 0x7 /* gpmc_ben0_cle.gpio2_5, OUTPUT | MODE7 */
+ >;
+ };
+
+ bb_lcd_pwm_backlight_pins: pinmux_bb_lcd_pwm_backlight_pins {
+ pinctrl-single,pins = <
+ BONE_P9_14 (PIN_OUTPUT_PULLDOWN | MUX_MODE6) /* gpmc_a2.ehrpwm1a */
+ >;
+ };
+
+ keymap3_pins: pinmux_keymap3_pins {
+ pinctrl-single,pins = <
+ 0x040 0x2f /* KEY_UP gpmc_a0.gpio1_16, INPUT | PULLDIS | MODE7 */
+ 0x04c 0x2f /* KEY_DOWN gpmc_a3.gpio1_19, INPUT | PULLDIS | MODE7 */
+ 0x078 0x2f /* KEY_RIGHT gpmc_ben1.gpio1_28, INPUT | PULLDIS | MODE7 */
+ 0x164 0x2f /* KEY_LEFT ecap0_in_pwm0_out.gpio0_7, INPUT | PULLDIS | MODE7 */
+ 0x1a4 0x2f /* KEY_ENTER mcasp0_fxr.gpio3_19, INPUT | PULLDIS | MODE7 */
+ >;
+ };
+
+ edt_ft5306_ts_pins: pinmux_edt_ft5306_ts_pins {
+ pinctrl-single,pins = <
+ /* CAP_TSC gpmc_a1.gpio1_17, INPUT | MODE7 */
+ BONE_P9_23 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ >;
+ };
+
+ i2c1_pins: pinmux_i2c1_pins {
+ pinctrl-single,pins = <
+ /* spi0_d1.i2c1_sda, SLEWCTRL_SLOW | INPUT_PULLUP | MODE2 */
+ BONE_P9_18 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE2)
+ /* spi0_cs0.i2c1_scl, SLEWCTRL_SLOW | INPUT_PULLUP | MODE2 */
+ BONE_P9_17 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE2)
+ >;
+ };
+
+ mcasp0_pins: pinmux_mcasp0_pins {
+ pinctrl-single,pins = <
+ 0x190 0x20 /* mcasp0_aclkx.mcasp0_aclkx, INPUT | MODE0 */
+ 0x194 0x20 /* mcasp0_fsx.mcasp0_fsx, INPUT | MODE0 */
+ 0x198 0x20 /* mcasp0_axr0.mcasp0_axr0, INPUT | MODE0 */
+ 0x19c 0x22 /* mcasp0_ahclkr.mcasp0_axr2, INPUT | MODE2 */
+ >;
+ };
+};
+
+&epwmss1 {
+ status = "okay";
+};
+
+
+&ehrpwm1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&bb_lcd_pwm_backlight_pins>;
+ status = "okay";
+};
+
+&i2c1 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c1_pins>;
+ clock-frequency = <400000>;
+
+ edt-ft5306@38 {
+ status = "okay";
+ compatible = "edt,edt-ft5306", "edt,edt-ft5x06";
+ pinctrl-names = "default";
+ pinctrl-0 = <&edt_ft5306_ts_pins>;
+
+ reg = <0x38>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <17 0>;
+
+ touchscreen-size-x = <1024>;
+ touchscreen-size-y = <600>;
+ };
+
+ tlv320aic3x: tlv320aic3x@1b {
+ compatible = "ti,tlv320aic3x";
+ reg = <0x1b>;
+ status = "okay";
+ };
+};
+
+&mcasp0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mcasp0_pins>;
+
+ status = "okay";
+
+ op-mode = <0>; /* MCASP_IIS_MODE */
+ tdm-slots = <2>;
+ num-serializer = <16>;
+ serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */
+ 1 0 2 0
+ 0 0 0 0
+ 0 0 0 0
+ 0 0 0 0
+ >;
+ tx-num-evt = <1>;
+ rx-num-evt = <1>;
+};
+
+/ {
+ backlight {
+ status = "okay";
+ compatible = "pwm-backlight";
+ pwms = <&ehrpwm1 0 50000 0>;
+ brightness-levels = <0 51 53 56 62 75 101 152 255>;
+ default-brightness-level = <8>;
+ };
+
+ gpio_keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&keymap3_pins>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ button@1 {
+ debounce_interval = <50>;
+ linux,code = <105>;
+ label = "left";
+ gpios = <&gpio0 7 0x1>;
+ gpio-key,wakeup;
+ autorepeat;
+ };
+ button@2 {
+ debounce_interval = <50>;
+ linux,code = <106>;
+ label = "right";
+ gpios = <&gpio1 28 0x1>;
+ gpio-key,wakeup;
+ autorepeat;
+ };
+ button@3 {
+ debounce_interval = <50>;
+ linux,code = <103>;
+ label = "up";
+ gpios = <&gpio1 16 0x1>;
+ gpio-key,wakeup;
+ autorepeat;
+ };
+ button@4 {
+ debounce_interval = <50>;
+ linux,code = <108>;
+ label = "down";
+ gpios = <&gpio1 19 0x1>;
+ gpio-key,wakeup;
+ autorepeat;
+ };
+ button@5 {
+ debounce_interval = <50>;
+ linux,code = <28>;
+ label = "enter";
+ gpios = <&gpio3 19 0x1>;
+ gpio-key,wakeup;
+ };
+ };
+
+ gpio-leds-cape-lcd {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+
+ pinctrl-0 = <&user_leds_s1>;
+
+ lcd-led0 {
+ label = "lcd:green:usr0";
+ gpios = <&gpio2 4 0>;
+ linux,default-trigger = "heartbeat";
+ default-state = "off";
+ };
+
+ lcd-led1 {
+ label = "lcd:green:usr1";
+ gpios = <&gpio2 5 0>;
+ linux,default-trigger = "mmc0";
+ default-state = "off";
+ };
+ };
+
+ sound {
+ compatible = "ti,da830-evm-audio";
+ ti,model = "DA830 EVM";
+ ti,audio-codec = <&tlv320aic3x>;
+ ti,mcasp-controller = <&mcasp0>;
+ ti,codec-clock-rate = <12000000>;
+ ti,audio-routing =
+ "Headphone Jack", "HPLOUT",
+ "Headphone Jack", "HPROUT",
+ "MIC3L", "Mic Jack",
+ "MIC3R", "Mic Jack";
+ };
+};
+
+#include "am335x-peripheral-panel-1024x600-24bit.dtsi"
+#include "am335x-bone-pinmux-panel-1024x600-24bit.dtsi"
diff --git b/arch/arm/boot/dts/am335x-cape-bbb-exp-r.dtsi b/arch/arm/boot/dts/am335x-cape-bbb-exp-r.dtsi
new file mode 100644
index 0000000..539409c
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-cape-bbb-exp-r.dtsi
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <dt-bindings/board/am335x-bbw-bbb-base.h>
+
+#include "am335x-peripheral-can0.dtsi"
+#include "am335x-bone-pinmux-can0.dtsi"
+
+#include "am335x-peripheral-ttyS1.dtsi"
+#include "am335x-bone-pinmux-ttyS1.dtsi"
+
+#include "am335x-peripheral-ttyS2.dtsi"
+#include "am335x-bone-pinmux-ttyS2.dtsi"
+
+#include "am335x-peripheral-ttyS4.dtsi"
+#include "am335x-bone-pinmux-ttyS4.dtsi"
+
+&am33xx_pinmux {
+ user_leds_s1: user_leds_s1 {
+ pinctrl-single,pins = <
+ 0x98 0x7 /* gpmc_wen.gpio2_4, OUTPUT | MODE7 */
+ 0x9c 0x7 /* gpmc_ben0_cle.gpio2_5, OUTPUT | MODE7 */
+ >;
+ };
+
+ bb_lcd_pwm_backlight_pins: pinmux_bb_lcd_pwm_backlight_pins {
+ pinctrl-single,pins = <
+ BONE_P9_14 (PIN_OUTPUT_PULLDOWN | MUX_MODE6) /* gpmc_a2.ehrpwm1a */
+ >;
+ };
+
+ keymap3_pins: pinmux_keymap3_pins {
+ pinctrl-single,pins = <
+ 0x040 0x2f /* KEY_UP gpmc_a0.gpio1_16, INPUT | PULLDIS | MODE7 */
+ 0x04c 0x2f /* KEY_DOWN gpmc_a3.gpio1_19, INPUT | PULLDIS | MODE7 */
+ 0x078 0x2f /* KEY_RIGHT gpmc_ben1.gpio1_28, INPUT | PULLDIS | MODE7 */
+ 0x164 0x2f /* KEY_LEFT ecap0_in_pwm0_out.gpio0_7, INPUT | PULLDIS | MODE7 */
+ 0x1a4 0x2f /* KEY_ENTER mcasp0_fxr.gpio3_19, INPUT | PULLDIS | MODE7 */
+ >;
+ };
+
+ i2c1_pins: pinmux_i2c1_pins {
+ pinctrl-single,pins = <
+ /* spi0_d1.i2c1_sda, SLEWCTRL_SLOW | INPUT_PULLUP | MODE2 */
+ BONE_P9_18 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE2)
+ /* spi0_cs0.i2c1_scl, SLEWCTRL_SLOW | INPUT_PULLUP | MODE2 */
+ BONE_P9_17 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE2)
+ >;
+ };
+
+ mcasp0_pins: pinmux_mcasp0_pins {
+ pinctrl-single,pins = <
+ 0x190 0x20 /* mcasp0_aclkx.mcasp0_aclkx, INPUT | MODE0 */
+ 0x194 0x20 /* mcasp0_fsx.mcasp0_fsx, INPUT | MODE0 */
+ 0x198 0x20 /* mcasp0_axr0.mcasp0_axr0, INPUT | MODE0 */
+ 0x19c 0x22 /* mcasp0_ahclkr.mcasp0_axr2, INPUT | MODE2 */
+ >;
+ };
+};
+
+&epwmss1 {
+ status = "okay";
+};
+
+
+&ehrpwm1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&bb_lcd_pwm_backlight_pins>;
+ status = "okay";
+};
+
+&i2c1 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c1_pins>;
+ clock-frequency = <400000>;
+
+ tlv320aic3x: tlv320aic3x@1b {
+ compatible = "ti,tlv320aic3x";
+ reg = <0x1b>;
+ status = "okay";
+ };
+};
+
+&mcasp0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mcasp0_pins>;
+
+ status = "okay";
+
+ op-mode = <0>; /* MCASP_IIS_MODE */
+ tdm-slots = <2>;
+ num-serializer = <16>;
+ serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */
+ 1 0 2 0
+ 0 0 0 0
+ 0 0 0 0
+ 0 0 0 0
+ >;
+ tx-num-evt = <1>;
+ rx-num-evt = <1>;
+};
+
+&tscadc {
+ status = "okay";
+ tsc {
+ ti,wires = <4>;
+ ti,x-plate-resistance = <200>;
+ ti,coordinate-readouts = <5>;
+ ti,wire-config = <0x00 0x11 0x22 0x33>;
+ };
+
+ adc {
+ ti,adc-channels = <4 5 6 7>;
+ };
+};
+
+/ {
+ backlight {
+ status = "okay";
+ compatible = "pwm-backlight";
+ pwms = <&ehrpwm1 0 50000 0>;
+ brightness-levels = <0 51 53 56 62 75 101 152 255>;
+ default-brightness-level = <8>;
+ };
+
+ gpio_keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&keymap3_pins>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ button@1 {
+ debounce_interval = <50>;
+ linux,code = <105>;
+ label = "left";
+ gpios = <&gpio0 7 0x1>;
+ gpio-key,wakeup;
+ autorepeat;
+ };
+ button@2 {
+ debounce_interval = <50>;
+ linux,code = <106>;
+ label = "right";
+ gpios = <&gpio1 28 0x1>;
+ gpio-key,wakeup;
+ autorepeat;
+ };
+ button@3 {
+ debounce_interval = <50>;
+ linux,code = <103>;
+ label = "up";
+ gpios = <&gpio1 16 0x1>;
+ gpio-key,wakeup;
+ autorepeat;
+ };
+ button@4 {
+ debounce_interval = <50>;
+ linux,code = <108>;
+ label = "down";
+ gpios = <&gpio1 19 0x1>;
+ gpio-key,wakeup;
+ autorepeat;
+ };
+ button@5 {
+ debounce_interval = <50>;
+ linux,code = <28>;
+ label = "enter";
+ gpios = <&gpio3 19 0x1>;
+ gpio-key,wakeup;
+ };
+ };
+
+ gpio-leds-cape-lcd {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+
+ pinctrl-0 = <&user_leds_s1>;
+
+ lcd-led0 {
+ label = "lcd:green:usr0";
+ gpios = <&gpio2 4 0>;
+ linux,default-trigger = "heartbeat";
+ default-state = "off";
+ };
+
+ lcd-led1 {
+ label = "lcd:green:usr1";
+ gpios = <&gpio2 5 0>;
+ linux,default-trigger = "mmc0";
+ default-state = "off";
+ };
+ };
+
+ sound {
+ compatible = "ti,da830-evm-audio";
+ ti,model = "DA830 EVM";
+ ti,audio-codec = <&tlv320aic3x>;
+ ti,mcasp-controller = <&mcasp0>;
+ ti,codec-clock-rate = <12000000>;
+ ti,audio-routing =
+ "Headphone Jack", "HPLOUT",
+ "Headphone Jack", "HPROUT",
+ "MIC3L", "Mic Jack",
+ "MIC3R", "Mic Jack";
+ };
+};
+
+#include "am335x-peripheral-panel-1024x600-24bit.dtsi"
+#include "am335x-bone-pinmux-panel-1024x600-24bit.dtsi"
diff --git b/arch/arm/boot/dts/am335x-cape-rtc-ds1307.dtsi b/arch/arm/boot/dts/am335x-cape-rtc-ds1307.dtsi
new file mode 100644
index 0000000..bce6ac5
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-cape-rtc-ds1307.dtsi
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <dt-bindings/board/am335x-bbw-bbb-base.h>
+
+&am33xx_pinmux {
+ i2c2_pins: pinmux_i2c2_pins {
+ pinctrl-single,pins = <
+ BONE_P9_20 0x73 /* (SLEWCTRL_SLOW | PIN_INPUT_PULLUP | MUX_MODE3) uart1_ctsn.i2c2_sda */
+ BONE_P9_19 0x73 /* (SLEWCTRL_SLOW | PIN_INPUT_PULLUP | MUX_MODE3) uart1_rtsn.i2c2_scl */
+ >;
+ };
+};
+
+&i2c2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c2_pins>;
+
+ status = "okay";
+ clock-frequency = <100000>;
+
+ rtc@68 {
+ compatible = "maxim,ds1307";
+ reg = <0x68>;
+ };
+};
diff --git b/arch/arm/boot/dts/am335x-olimex-som.dts b/arch/arm/boot/dts/am335x-olimex-som.dts
new file mode 100644
index 0000000..2b00ad2
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-olimex-som.dts
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include "am335x-som-common.dtsi"
+
+/ {
+ model = "Olimex AM335x SOM";
+ compatible = "olimex,am335x-olimex-som", "ti,am33xx";
+};
+
+&ldo3_reg {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+};
+
+&mmc1 {
+ vmmc-supply = <&vmmcsd_fixed>;
+};
+
+&am33xx_pinmux {
+ lcd_pins_default: lcd_pins_default {
+ pinctrl-single,pins = <
+ 0x20 0x01 /* gpmc_ad8.lcd_data16, OUTPUT | MODE1 */
+ 0x24 0x01 /* gpmc_ad9.lcd_data17, OUTPUT | MODE1 */
+ 0x28 0x01 /* gpmc_ad10.lcd_data18, OUTPUT | MODE1 */
+ 0x2c 0x01 /* gpmc_ad11.lcd_data19, OUTPUT | MODE1 */
+ 0x30 0x01 /* gpmc_ad12.lcd_data20, OUTPUT | MODE1 */
+ 0x34 0x01 /* gpmc_ad13.lcd_data21, OUTPUT | MODE1 */
+ 0x38 0x01 /* gpmc_ad14.lcd_data22, OUTPUT | MODE1 */
+ 0x3c 0x01 /* gpmc_ad15.lcd_data23, OUTPUT | MODE1 */
+ 0xa0 0x00 /* lcd_data0.lcd_data0, OUTPUT | MODE0 */
+ 0xa4 0x00 /* lcd_data1.lcd_data1, OUTPUT | MODE0 */
+ 0xa8 0x00 /* lcd_data2.lcd_data2, OUTPUT | MODE0 */
+ 0xac 0x00 /* lcd_data3.lcd_data3, OUTPUT | MODE0 */
+ 0xb0 0x00 /* lcd_data4.lcd_data4, OUTPUT | MODE0 */
+ 0xb4 0x00 /* lcd_data5.lcd_data5, OUTPUT | MODE0 */
+ 0xb8 0x00 /* lcd_data6.lcd_data6, OUTPUT | MODE0 */
+ 0xbc 0x00 /* lcd_data7.lcd_data7, OUTPUT | MODE0 */
+ 0xc0 0x00 /* lcd_data8.lcd_data8, OUTPUT | MODE0 */
+ 0xc4 0x00 /* lcd_data9.lcd_data9, OUTPUT | MODE0 */
+ 0xc8 0x00 /* lcd_data10.lcd_data10, OUTPUT | MODE0 */
+ 0xcc 0x00 /* lcd_data11.lcd_data11, OUTPUT | MODE0 */
+ 0xd0 0x00 /* lcd_data12.lcd_data12, OUTPUT | MODE0 */
+ 0xd4 0x00 /* lcd_data13.lcd_data13, OUTPUT | MODE0 */
+ 0xd8 0x00 /* lcd_data14.lcd_data14, OUTPUT | MODE0 */
+ 0xdc 0x00 /* lcd_data15.lcd_data15, OUTPUT | MODE0 */
+ 0xe0 0x00 /* lcd_vsync.lcd_vsync, OUTPUT | MODE0 */
+ 0xe4 0x00 /* lcd_hsync.lcd_hsync, OUTPUT | MODE0 */
+ 0xe8 0x00 /* lcd_pclk.lcd_pclk, OUTPUT | MODE0 */
+ 0xec 0x00 /* lcd_ac_bias_en.lcd_ac_bias_en, OUTPUT | MODE0 */
+ >;
+ };
+
+ lcd_pins_sleep: lcd_pins_sleep {
+ pinctrl-single,pins = <
+ 0x20 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad8.lcd_data16 */
+ 0x24 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad9.lcd_data17 */
+ 0x28 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad10.lcd_data18 */
+ 0x2c (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad11.lcd_data19 */
+ 0x30 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad12.lcd_data20 */
+ 0x34 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad13.lcd_data21 */
+ 0x38 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad14.lcd_data22 */
+ 0x3c (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad15.lcd_data23 */
+ 0xa0 (PULL_DISABLE | MUX_MODE7) /* lcd_data0.lcd_data0 */
+ 0xa4 (PULL_DISABLE | MUX_MODE7) /* lcd_data1.lcd_data1 */
+ 0xa8 (PULL_DISABLE | MUX_MODE7) /* lcd_data2.lcd_data2 */
+ 0xac (PULL_DISABLE | MUX_MODE7) /* lcd_data3.lcd_data3 */
+ 0xb0 (PULL_DISABLE | MUX_MODE7) /* lcd_data4.lcd_data4 */
+ 0xb4 (PULL_DISABLE | MUX_MODE7) /* lcd_data5.lcd_data5 */
+ 0xb8 (PULL_DISABLE | MUX_MODE7) /* lcd_data6.lcd_data6 */
+ 0xbc (PULL_DISABLE | MUX_MODE7) /* lcd_data7.lcd_data7 */
+ 0xc0 (PULL_DISABLE | MUX_MODE7) /* lcd_data8.lcd_data8 */
+ 0xc4 (PULL_DISABLE | MUX_MODE7) /* lcd_data9.lcd_data9 */
+ 0xc8 (PULL_DISABLE | MUX_MODE7) /* lcd_data10.lcd_data10 */
+ 0xcc (PULL_DISABLE | MUX_MODE7) /* lcd_data11.lcd_data11 */
+ 0xd0 (PULL_DISABLE | MUX_MODE7) /* lcd_data12.lcd_data12 */
+ 0xd4 (PULL_DISABLE | MUX_MODE7) /* lcd_data13.lcd_data13 */
+ 0xd8 (PULL_DISABLE | MUX_MODE7) /* lcd_data14.lcd_data14 */
+ 0xdc (PULL_DISABLE | MUX_MODE7) /* lcd_data15.lcd_data15 */
+ /* lcd_vsync.lcd_vsync,OUTPUT | MODE0 */
+ 0xe0 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0xe4 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* lcd_hsync.lcd_hsync */
+ 0xe8 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* lcd_pclk.lcd_pclk */
+ /* lcd_ac_bias_en.lcd_ac_bias_en */
+ 0xec (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ >;
+ };
+
+};
+
+&lcdc {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&lcd_pins_default>;
+ pinctrl-1 = <&lcd_pins_sleep>;
+ status = "okay";
+ /* display-timings {
+ 480x272 {
+ hactive = <480>;
+ vactive = <272>;
+ hback-porch = <43>;
+ hfront-porch = <8>;
+ hsync-len = <4>;
+ vback-porch = <12>;
+ vfront-porch = <4>;
+ vsync-len = <10>;
+ clock-frequency = <9000000>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ };
+ };*/
+
+ display-timings {
+ native-mode = <&vga1024x768>;
+ lcd4: 480x272 {
+ clock-frequency = <9000000>;
+ hactive = <480>;
+ vactive = <272>;
+ hfront-porch = <3>;
+ hback-porch = <40>;
+ vback-porch = <8>;
+ vfront-porch = <7>;
+ hsync-len = <2>;
+ vsync-len = <1>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ };
+ lcd7: 800x480 {
+ clock-frequency = <33300000>;
+ hactive = <800>;
+ vactive = <480>;
+ hfront-porch = <210>;
+ hback-porch = <40>;
+ vback-porch = <23>;
+ vfront-porch = <20>;
+ hsync-len = <6>;
+ vsync-len = <2>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ };
+ lcd10: 1024x600 {
+ clock-frequency = <51200000>;
+ hactive = <1024>;
+ vactive = <600>;
+ hfront-porch = <160>;
+ hback-porch = <140>;
+ vback-porch = <20>;
+ vfront-porch = <12>;
+ hsync-len = <20>;
+ vsync-len = <3>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ };
+
+ vga800x600: 800x600 {
+ clock-frequency = <40000000>;
+ hactive = <800>;
+ vactive = <600>;
+ hfront-porch = <40>;
+ hback-porch = <88>;
+ vfront-porch = <1>;
+ vback-porch = <23>;
+ hsync-len = <128>;
+ vsync-len = <4>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ };
+ vga1024x768: 1024x768 {
+ clock-frequency = <65000000>;
+ hactive = <1024>;
+ hfront-porch = <24>;
+ hback-porch = <160>;
+ hsync-len = <136>;
+ vactive = <768>;
+ vfront-porch = <3>;
+ vback-porch = <29>;
+ vsync-len = <6>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ };
+ };
+};
diff --git b/arch/arm/boot/dts/am335x-peripheral-can0.dtsi b/arch/arm/boot/dts/am335x-peripheral-can0.dtsi
new file mode 100644
index 0000000..4335e39
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-peripheral-can0.dtsi
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+&dcan0 {
+ pinctrl-names = "default";
+
+ status = "okay";
+};
diff --git b/arch/arm/boot/dts/am335x-peripheral-can1.dtsi b/arch/arm/boot/dts/am335x-peripheral-can1.dtsi
new file mode 100644
index 0000000..02b5bd1
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-peripheral-can1.dtsi
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+&dcan1 {
+ pinctrl-names = "default";
+
+ status = "okay";
+};
diff --git b/arch/arm/boot/dts/am335x-peripheral-emmc.dtsi b/arch/arm/boot/dts/am335x-peripheral-emmc.dtsi
new file mode 100644
index 0000000..603f34e
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-peripheral-emmc.dtsi
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+&mmc2 {
+ vmmc-supply = <&vmmcsd_fixed>;
+ pinctrl-names = "default";
+
+ bus-width = <8>;
+ status = "okay";
+};
diff --git b/arch/arm/boot/dts/am335x-peripheral-i2c2.dtsi b/arch/arm/boot/dts/am335x-peripheral-i2c2.dtsi
new file mode 100644
index 0000000..ed9a0b5
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-peripheral-i2c2.dtsi
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+&i2c2 {
+ pinctrl-names = "default";
+
+ status = "okay";
+};
diff --git b/arch/arm/boot/dts/am335x-peripheral-nxp-hdmi.dtsi b/arch/arm/boot/dts/am335x-peripheral-nxp-hdmi.dtsi
new file mode 100644
index 0000000..1dfd26a
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-peripheral-nxp-hdmi.dtsi
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+&lcdc {
+ status = "okay";
+ port {
+ lcdc_0: endpoint@0 {
+ remote-endpoint = <&hdmi_0>;
+ };
+ };
+};
+
+&i2c0 {
+ tda19988 {
+ compatible = "nxp,tda998x";
+ reg = <0x70>;
+
+ port {
+ hdmi_0: endpoint@0 {
+ remote-endpoint = <&lcdc_0>;
+ };
+ };
+ };
+};
diff --git b/arch/arm/boot/dts/am335x-peripheral-panel-1024x600-24bit.dtsi b/arch/arm/boot/dts/am335x-peripheral-panel-1024x600-24bit.dtsi
new file mode 100644
index 0000000..74ddc12
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-peripheral-panel-1024x600-24bit.dtsi
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+&lcdc {
+ status = "okay";
+};
+
+/ {
+ panel {
+ status = "okay";
+ compatible = "ti,tilcdc,panel";
+ pinctrl-names = "default";
+
+ panel-info {
+ ac-bias = <255>;
+ ac-bias-intrpt = <0>;
+ dma-burst-sz = <16>;
+ bpp = <32>;
+ fdd = <0x80>;
+ sync-edge = <0>;
+ sync-ctrl = <0>;
+ raster-order = <1>;
+ fifo-th = <0>;
+ };
+ display-timings {
+ native-mode = <&timing0>;
+ timing0: 1024x600 {
+ clock-frequency = <36000000>;
+ hactive = <1024>;
+ vactive = <600>;
+ hfront-porch = <1>;
+ hback-porch = <45>;
+ hsync-len = <30>;
+ vback-porch = <22>;
+ vfront-porch = <12>;
+ vsync-len = <2>;
+ hsync-active = <1>;
+ vsync-active = <1>;
+ de-active = <1>;
+ pixelclk-active = <0>;
+ };
+ };
+ };
+};
diff --git b/arch/arm/boot/dts/am335x-peripheral-spi0.dtsi b/arch/arm/boot/dts/am335x-peripheral-spi0.dtsi
new file mode 100644
index 0000000..969e352
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-peripheral-spi0.dtsi
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+&spi0 {
+ pinctrl-names = "default";
+
+ status = "okay";
+};
diff --git b/arch/arm/boot/dts/am335x-peripheral-spi1.dtsi b/arch/arm/boot/dts/am335x-peripheral-spi1.dtsi
new file mode 100644
index 0000000..ac5fe97
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-peripheral-spi1.dtsi
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+&spi1 {
+ pinctrl-names = "default";
+
+ status = "okay";
+};
diff --git b/arch/arm/boot/dts/am335x-peripheral-spi1a.dtsi b/arch/arm/boot/dts/am335x-peripheral-spi1a.dtsi
new file mode 100644
index 0000000..ac5fe97
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-peripheral-spi1a.dtsi
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+&spi1 {
+ pinctrl-names = "default";
+
+ status = "okay";
+};
diff --git b/arch/arm/boot/dts/am335x-peripheral-ttyS1.dtsi b/arch/arm/boot/dts/am335x-peripheral-ttyS1.dtsi
new file mode 100644
index 0000000..f59fa4c
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-peripheral-ttyS1.dtsi
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+&uart1 {
+ pinctrl-names = "default";
+
+ status = "okay";
+};
diff --git b/arch/arm/boot/dts/am335x-peripheral-ttyS2.dtsi b/arch/arm/boot/dts/am335x-peripheral-ttyS2.dtsi
new file mode 100644
index 0000000..a25d6cf
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-peripheral-ttyS2.dtsi
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+&uart2 {
+ pinctrl-names = "default";
+
+ status = "okay";
+};
diff --git b/arch/arm/boot/dts/am335x-peripheral-ttyS4.dtsi b/arch/arm/boot/dts/am335x-peripheral-ttyS4.dtsi
new file mode 100644
index 0000000..adc89f0
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-peripheral-ttyS4.dtsi
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+&uart4 {
+ pinctrl-names = "default";
+
+ status = "okay";
+};
diff --git b/arch/arm/boot/dts/am335x-peripheral-ttyS5.dtsi b/arch/arm/boot/dts/am335x-peripheral-ttyS5.dtsi
new file mode 100644
index 0000000..8b42fb0
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-peripheral-ttyS5.dtsi
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+&uart5 {
+ pinctrl-names = "default";
+
+ status = "okay";
+};
diff --git b/arch/arm/boot/dts/am335x-roboticscape.dtsi b/arch/arm/boot/dts/am335x-roboticscape.dtsi
new file mode 100644
index 0000000..77d815a
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-roboticscape.dtsi
@@ -0,0 +1,395 @@
+/*******************************************************************************
+* pinmux and modules used by roboticscape
+* included in:
+* am335x-boneblack-roboticscape.dts
+* am335x-boneblack-wireless-roboticscape.dts
+*******************************************************************************/
+
+
+
+/*******************************************************************************
+* Pin Muxing
+*******************************************************************************/
+&am33xx_pinmux {
+
+ /***************************************************************************
+ * Static Pinmux
+ ***************************************************************************/
+ mux_helper_pins: pins {
+ pinctrl-single,pins = <
+
+ /* GPIO Input Pullup */
+ 0x09c 0x37 /*P8.9 T6 PAUSE_BTN */
+ 0x098 0x37 /*P8.10 U6 MODE_BTN */
+ 0x1AC 0x37 /*P9.25 A14 IMU_INT */
+
+ /* LEDs GPIO Out*/
+ 0x090 0x0F /* P8.7 R7 LED_RED */
+ 0x094 0x0F /* P8.8 T7 LED_GREEN */
+ 0x028 0x0F /*P8.14 T11 BATT_LED_4 */
+ 0x02C 0x0F /*P8.17 U12 BATT_LED_1 */
+ 0x08c 0x0F /*P8.18 V12 BATT_LED_2 */
+ 0x07c 0x0F /*P8.26 V6 BATT_LED_3 */
+
+ /* Motor Control GPIO Out*/
+ 0x0cc 0x0F /*P8.34 MDIR_2B different from blue!!*/
+ 0x0a8 0x0F /*P8.43 MDIR_3B*/
+ 0x0ac 0x0F /*P8.44 MDIR_3A*/
+ 0x0a0 0x0F /*P8.45 MDIR_4A*/
+ 0x0a4 0x0F /*P8.46 MDIR_4B*/
+ 0x078 0x0F /*P9.12 MDIR_1A different from blue!!*/
+ 0x074 0x0F /*P9.13 MDIR_1B*/
+ 0x040 0x0F /*P9.15 MDIR_2A*/
+ 0x1b4 0x0F /*P9.41 MOT_STBY*/
+
+ /* HRPWM 1 */
+ 0x048 0x6 /* P9_14 | MODE 6 */
+ 0x04c 0x6 /* P9_16 | MODE 6 */
+
+ /* HRPWM 2 */
+ 0x020 0x4 /* P8_19 | MODE 4 */
+ 0x024 0x4 /* P8_13 | MODE 4 */
+
+ /* EQEP */
+ 0x1A0 0x31 /* P9_42,EQEP0A, MODE1 */
+ 0x1A4 0x31 /* P9_27,EQEP0B, MODE1 */
+ 0x0D4 0x32 /* P8_33,EQEP1B, MODE2 */
+ 0x0D0 0x32 /* P8_35,EQEP1A, MODE2 */
+ 0x030 0x34 /* P8_12,EQEP2A, MODE4 */
+ 0x034 0x34 /* P8_11,EQEP2B, MODE4 */
+
+ /* PRU encoder input */
+ 0x03c 0x36 /* P8_15,PRU0_r31_15,MODE6 */
+ 0x038 0x36 /* P8_16,PRU0_r31_16,MODE6 */
+
+ /* PRU Servo output */
+ 0x0e0 0x05 /*pru1_pru_r30_8, MODE5*/
+ 0x0e8 0x05 /*pru1_pru_r30_10, MODE5 */
+ 0x0e4 0x05 /*pr1_pru1_pru_r30_9, MODE5 */
+ 0x0ec 0x05 /*pru1_pru_r30_11, MODE5 */
+ 0x0b8 0x05 /*pru1_pru_r30_6, MODE5 */
+ 0x0bc 0x05 /*pru1_pru_r30_7, MODE5 */
+ 0x0b0 0x05 /*pru1_pru_r30_4, MODE5 */
+ 0x0b4 0x05 /*pru1_pru_r30_5, MODE5 */
+ 0x0C8 0x0F /*P8.36, SERVO_PWR GPIO OUT*/
+
+ /* I2C1 */
+ 0x15C 0x32 /* P9.17,i2c1_scl,INPUT_PULLUP,MODE2 */
+ 0x158 0x32 /* P9.18,i2c1_sda,INPUT_PULLUP,MODE2 */
+
+ /* I2C2 */
+ 0x17c 0x73 /* P9.19, i2c2_sda, mode 3 */
+ 0x178 0x73 /* P9.20, i2c2_sda, mode 3 */
+
+ /* UART5 */
+ 0x0C4 0x34 /* P8.38,uart5_rxd,MODE4 */
+ 0x0C0 0x14 /* P8.37,uart5_txd,MODE4 */
+
+ >;
+ };
+
+};
+
+
+/*******************************************************************************
+* apply static and dynamic pinmux modes listed above. Configurable pins get the
+* modes from am335x-boneblack-common-universal-pins.dtsi
+*******************************************************************************/
+&ocp {
+ /* activate the static pinmux helper list of pin modes above */
+ test_helper: helper {
+ compatible = "bone-pinmux-helper";
+ pinctrl-names = "default";
+ pinctrl-0 = <&mux_helper_pins>;
+
+ status = "okay";
+ };
+
+ /* UART4 RX DSM */
+ P9_11_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart";
+ pinctrl-0 = <&P9_11_default_pin>;
+ pinctrl-1 = <&P9_11_gpio_pin>;
+ pinctrl-2 = <&P9_11_gpio_pu_pin>;
+ pinctrl-3 = <&P9_11_gpio_pd_pin>;
+ pinctrl-4 = <&P9_11_uart_pin>;
+ };
+
+ /* UART 2 TX GPS*/
+ P9_21_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi", "uart", "i2c", "pwm";
+ pinctrl-0 = <&P9_21_default_pin>;
+ pinctrl-1 = <&P9_21_gpio_pin>;
+ pinctrl-2 = <&P9_21_gpio_pu_pin>;
+ pinctrl-3 = <&P9_21_gpio_pd_pin>;
+ pinctrl-4 = <&P9_21_spi_pin>;
+ pinctrl-5 = <&P9_21_uart_pin>;
+ pinctrl-6 = <&P9_21_i2c_pin>;
+ pinctrl-7 = <&P9_21_pwm_pin>;
+ };
+
+ /* UART 2 RX GPS */
+ P9_22_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi", "uart", "i2c", "pwm";
+ pinctrl-0 = <&P9_22_default_pin>;
+ pinctrl-1 = <&P9_22_gpio_pin>;
+ pinctrl-2 = <&P9_22_gpio_pu_pin>;
+ pinctrl-3 = <&P9_22_gpio_pd_pin>;
+ pinctrl-4 = <&P9_22_spi_pin>;
+ pinctrl-5 = <&P9_22_uart_pin>;
+ pinctrl-6 = <&P9_22_i2c_pin>;
+ pinctrl-7 = <&P9_22_pwm_pin>;
+ };
+
+ /* SPI MISO */
+ P9_29_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm", "spi", "pruout", "pruin";
+ pinctrl-0 = <&P9_29_default_pin>;
+ pinctrl-1 = <&P9_29_gpio_pin>;
+ pinctrl-2 = <&P9_29_gpio_pu_pin>;
+ pinctrl-3 = <&P9_29_gpio_pd_pin>;
+ pinctrl-4 = <&P9_29_pwm_pin>;
+ pinctrl-5 = <&P9_29_spi_pin>;
+ pinctrl-6 = <&P9_29_pruout_pin>;
+ pinctrl-7 = <&P9_29_pruin_pin>;
+ };
+
+ /* SPI MOSI */
+ P9_30_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm", "spi", "pruout", "pruin";
+ pinctrl-0 = <&P9_30_default_pin>;
+ pinctrl-1 = <&P9_30_gpio_pin>;
+ pinctrl-2 = <&P9_30_gpio_pu_pin>;
+ pinctrl-3 = <&P9_30_gpio_pd_pin>;
+ pinctrl-4 = <&P9_30_pwm_pin>;
+ pinctrl-5 = <&P9_30_spi_pin>;
+ pinctrl-6 = <&P9_30_pruout_pin>;
+ pinctrl-7 = <&P9_30_pruin_pin>;
+ };
+
+ /* SPI SCK */
+ P9_31_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm", "spi", "pruout", "pruin";
+ pinctrl-0 = <&P9_31_default_pin>;
+ pinctrl-1 = <&P9_31_gpio_pin>;
+ pinctrl-2 = <&P9_31_gpio_pu_pin>;
+ pinctrl-3 = <&P9_31_gpio_pd_pin>;
+ pinctrl-4 = <&P9_31_pwm_pin>;
+ pinctrl-5 = <&P9_31_spi_pin>;
+ pinctrl-6 = <&P9_31_pruout_pin>;
+ pinctrl-7 = <&P9_31_pruin_pin>;
+ };
+
+ /* SPI SS1 GPIO3_17*/
+ P9_28_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm", "spi", "pwm2", "pruout", "pruin";
+ pinctrl-0 = <&P9_28_default_pin>;
+ pinctrl-1 = <&P9_28_gpio_pin>;
+ pinctrl-2 = <&P9_28_gpio_pu_pin>;
+ pinctrl-3 = <&P9_28_gpio_pd_pin>;
+ pinctrl-4 = <&P9_28_pwm_pin>;
+ pinctrl-5 = <&P9_28_spi_pin>;
+ pinctrl-6 = <&P9_28_pwm2_pin>;
+ pinctrl-7 = <&P9_28_pruout_pin>;
+ pinctrl-8 = <&P9_28_pruin_pin>;
+ };
+
+ /* SPI SS1 GPIO1_17*/
+ P9_23_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm";
+ pinctrl-0 = <&P9_23_default_pin>;
+ pinctrl-1 = <&P9_23_gpio_pin>;
+ pinctrl-2 = <&P9_23_gpio_pu_pin>;
+ pinctrl-3 = <&P9_23_gpio_pd_pin>;
+ pinctrl-4 = <&P9_23_pwm_pin>;
+ };
+
+ /* UART 1 TX */
+ P9_24_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart", "can", "i2c", "pruin";
+ pinctrl-0 = <&P9_24_default_pin>;
+ pinctrl-1 = <&P9_24_gpio_pin>;
+ pinctrl-2 = <&P9_24_gpio_pu_pin>;
+ pinctrl-3 = <&P9_24_gpio_pd_pin>;
+ pinctrl-4 = <&P9_24_uart_pin>;
+ pinctrl-5 = <&P9_24_can_pin>;
+ pinctrl-6 = <&P9_24_i2c_pin>;
+ pinctrl-7 = <&P9_24_pruin_pin>;
+ };
+
+ /* UART 1 RX */
+ P9_26_pinmux {
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart", "can", "i2c", "pruin";
+ pinctrl-0 = <&P9_26_default_pin>;
+ pinctrl-1 = <&P9_26_gpio_pin>;
+ pinctrl-2 = <&P9_26_gpio_pu_pin>;
+ pinctrl-3 = <&P9_26_gpio_pd_pin>;
+ pinctrl-4 = <&P9_26_uart_pin>;
+ pinctrl-5 = <&P9_26_can_pin>;
+ pinctrl-6 = <&P9_26_i2c_pin>;
+ pinctrl-7 = <&P9_26_pruin_pin>;
+ };
+
+
+};
+
+
+/*******************************************************************************
+* PWMSS
+*******************************************************************************/
+&epwmss0 {
+ status = "okay";
+};
+
+&epwmss1 {
+ status = "okay";
+};
+
+&epwmss2 {
+ status = "okay";
+};
+
+&ehrpwm0 {
+ status = "okay";
+};
+
+&ehrpwm1 {
+ status = "okay";
+};
+
+&ehrpwm2 {
+ status = "okay";
+};
+
+/*******************************************************************************
+* EQEP
+*******************************************************************************/
+&eqep0 {
+ count_mode = <0>; /* 0 - Quadrature mode, normal 90 phase offset cha & chb. 1 - Direction mode. cha input = clock, chb input = direction */
+ swap_inputs = <0>; /* Are channel A and channel B swapped? (0 - no, 1 - yes) */
+ invert_qa = <1>; /* Should we invert the channel A input? */
+ invert_qb = <1>; /* Should we invert the channel B input? I invert these because my encoder outputs drive transistors that pull down the pins */
+ invert_qi = <0>; /* Should we invert the index input? */
+ invert_qs = <0>; /* Should we invert the strobe input? */
+
+ status = "okay";
+};
+
+&eqep1 {
+ count_mode = <0>; /* 0 - Quadrature mode, normal 90 phase offset cha & chb. 1 - Direction mode. cha input = clock, chb input = direction */
+ swap_inputs = <0>; /* Are channel A and channel B swapped? (0 - no, 1 - yes) */
+ invert_qa = <1>; /* Should we invert the channel A input? */
+ invert_qb = <1>; /* Should we invert the channel B input? I invert these because my encoder outputs drive transistors that pull down the pins */
+ invert_qi = <0>; /* Should we invert the index input? */
+ invert_qs = <0>; /* Should we invert the strobe input? */
+
+ status = "okay";
+};
+
+&eqep2 {
+ count_mode = <0>; /* 0 - Quadrature mode, normal 90 phase offset cha & chb. 1 - Direction mode. cha input = clock, chb input = direction */
+ swap_inputs = <0>; /* Are channel A and channel B swapped? (0 - no, 1 - yes) */
+ invert_qa = <1>; /* Should we invert the channel A input? */
+ invert_qb = <1>; /* Should we invert the channel B input? I invert these because my encoder outputs drive transistors that pull down the pins */
+ invert_qi = <0>; /* Should we invert the index input? */
+ invert_qs = <0>; /* Should we invert the strobe input? */
+
+ status = "okay";
+};
+
+
+/*******************************************************************************
+* UART
+*******************************************************************************/
+&uart1 {
+ status = "okay";
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&uart4 {
+ status = "okay";
+};
+
+&uart5 {
+ status = "okay";
+};
+
+
+/*******************************************************************************
+* PRU Encoder and Servos
+*******************************************************************************/
+&pruss {
+ status = "okay";
+};
+
+
+/*******************************************************************************
+* I2C
+*******************************************************************************/
+&i2c1 {
+ status = "okay";
+ clock-frequency = <400000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+};
+
+&i2c2 {
+ status = "okay";
+ clock-frequency = <400000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+};
+
+
+/*******************************************************************************
+* SPI
+*******************************************************************************/
+&spi1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+
+ channel@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ compatible = "spidev";
+
+ reg = <0>;
+ spi-max-frequency = <16000000>;
+ spi-cpha;
+ };
+
+ channel@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ compatible = "spidev";
+
+ reg = <1>;
+ spi-max-frequency = <16000000>;
+ };
+};
diff --git b/arch/arm/boot/dts/am335x-sancloud-bbe.dts b/arch/arm/boot/dts/am335x-sancloud-bbe.dts
new file mode 100644
index 0000000..a36b04b
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-sancloud-bbe.dts
@@ -0,0 +1,264 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include "am335x-bone-common.dtsi"
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/display/tda998x.h>
+/* #include "am335x-bone-jtag.dtsi" */
+
+/ {
+ model = "SanCloud BeagleBone Enhanced";
+ compatible = "sancloud,am335x-boneenhanced", "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
+};
+
+&ldo3_reg {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+};
+
+&mmc1 {
+ vmmc-supply = <&vmmcsd_fixed>;
+};
+
+&mmc2 {
+ vmmc-supply = <&vmmcsd_fixed>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&emmc_pins>;
+ bus-width = <8>;
+ status = "okay";
+ ti,vcc-aux-disable-is-sleep;
+};
+
+&am33xx_pinmux {
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb_hub_ctrl>;
+
+ nxp_hdmi_bonelt_pins: nxp_hdmi_bonelt_pins {
+ pinctrl-single,pins = <
+ AM33XX_IOPAD(0x9b0, PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* xdma_event_intr0 */
+ AM33XX_IOPAD(0x8a0, PIN_OUTPUT | MUX_MODE0) /* lcd_data0.lcd_data0 */
+ AM33XX_IOPAD(0x8a4, PIN_OUTPUT | MUX_MODE0) /* lcd_data1.lcd_data1 */
+ AM33XX_IOPAD(0x8a8, PIN_OUTPUT | MUX_MODE0) /* lcd_data2.lcd_data2 */
+ AM33XX_IOPAD(0x8ac, PIN_OUTPUT | MUX_MODE0) /* lcd_data3.lcd_data3 */
+ AM33XX_IOPAD(0x8b0, PIN_OUTPUT | MUX_MODE0) /* lcd_data4.lcd_data4 */
+ AM33XX_IOPAD(0x8b4, PIN_OUTPUT | MUX_MODE0) /* lcd_data5.lcd_data5 */
+ AM33XX_IOPAD(0x8b8, PIN_OUTPUT | MUX_MODE0) /* lcd_data6.lcd_data6 */
+ AM33XX_IOPAD(0x8bc, PIN_OUTPUT | MUX_MODE0) /* lcd_data7.lcd_data7 */
+ AM33XX_IOPAD(0x8c0, PIN_OUTPUT | MUX_MODE0) /* lcd_data8.lcd_data8 */
+ AM33XX_IOPAD(0x8c4, PIN_OUTPUT | MUX_MODE0) /* lcd_data9.lcd_data9 */
+ AM33XX_IOPAD(0x8c8, PIN_OUTPUT | MUX_MODE0) /* lcd_data10.lcd_data10 */
+ AM33XX_IOPAD(0x8cc, PIN_OUTPUT | MUX_MODE0) /* lcd_data11.lcd_data11 */
+ AM33XX_IOPAD(0x8d0, PIN_OUTPUT | MUX_MODE0) /* lcd_data12.lcd_data12 */
+ AM33XX_IOPAD(0x8d4, PIN_OUTPUT | MUX_MODE0) /* lcd_data13.lcd_data13 */
+ AM33XX_IOPAD(0x8d8, PIN_OUTPUT | MUX_MODE0) /* lcd_data14.lcd_data14 */
+ AM33XX_IOPAD(0x8dc, PIN_OUTPUT | MUX_MODE0) /* lcd_data15.lcd_data15 */
+ AM33XX_IOPAD(0x8e0, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* lcd_vsync.lcd_vsync */
+ AM33XX_IOPAD(0x8e4, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* lcd_hsync.lcd_hsync */
+ AM33XX_IOPAD(0x8e8, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* lcd_pclk.lcd_pclk */
+ AM33XX_IOPAD(0x8ec, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* lcd_ac_bias_en.lcd_ac_bias_en */
+ >;
+ };
+ nxp_hdmi_bonelt_off_pins: nxp_hdmi_bonelt_off_pins {
+ pinctrl-single,pins = <
+ AM33XX_IOPAD(0x9b0, PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* xdma_event_intr0 */
+ >;
+ };
+
+ cpsw_default: cpsw_default {
+ pinctrl-single,pins = <
+ /* Slave 1 */
+ 0x114 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txen.rgmii1_tctl */
+ 0x118 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxdv.rgmii1_rctl */
+ 0x11c (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd3.rgmii1_td3 */
+ 0x120 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd2.rgmii1_td2 */
+ 0x124 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd1.rgmii1_td1 */
+ 0x128 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd0.rgmii1_td0 */
+ 0x12c (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txclk.rgmii1_tclk */
+ 0x130 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxclk.rgmii1_rclk */
+ 0x134 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd3.rgmii1_rd3 */
+ 0x138 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd2.rgmii1_rd2 */
+ 0x13c (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd1.rgmii1_rd1 */
+ 0x140 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd0.rgmii1_rd0 */
+ >;
+ };
+
+ cpsw_sleep: cpsw_sleep {
+ pinctrl-single,pins = <
+ /* Slave 1 reset value */
+ 0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x118 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x11c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x120 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x12c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x130 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x134 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x138 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ >;
+ };
+
+ davinci_mdio_default: davinci_mdio_default {
+ pinctrl-single,pins = <
+ /* MDIO */
+ 0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */
+ 0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_clk.mdio_clk */
+ >;
+ };
+
+ davinci_mdio_sleep: davinci_mdio_sleep {
+ pinctrl-single,pins = <
+ /* MDIO reset value */
+ 0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ >;
+ };
+
+ usb_hub_ctrl: usb_hub_ctrl {
+ pinctrl-single,pins = <
+ 0x144 (PIN_OUTPUT_PULLUP | MUX_MODE7) /* mcasp0_ahclkr.gpio3_17 */
+ >;
+ };
+
+ mpu6050_pins: pinmux_mpu6050_pins {
+ pinctrl-single,pins = <
+ 0x168 (PIN_INPUT | MUX_MODE7) /* spi0_sclk.gpio0_2 */
+ >;
+ };
+
+ lps3331ap_pins: pinmux_lps3331ap_pins {
+ pinctrl-single,pins = <
+ 0x6C (PIN_INPUT | MUX_MODE7) /* conf_gpmc_a11.gpio1_27 */
+ >;
+ };
+
+ mcasp0_pins: mcasp0_pins {
+ pinctrl-single,pins = <
+ AM33XX_IOPAD(0x9ac, PIN_INPUT_PULLUP | MUX_MODE0) /* mcasp0_ahcklx.mcasp0_ahclkx */
+ AM33XX_IOPAD(0x99c, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mcasp0_ahclkr.mcasp0_axr2*/
+ AM33XX_IOPAD(0x994, PIN_OUTPUT_PULLUP | MUX_MODE0) /* mcasp0_fsx.mcasp0_fsx */
+ AM33XX_IOPAD(0x990, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mcasp0_aclkx.mcasp0_aclkx */
+ AM33XX_IOPAD(0x86c, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a11.GPIO1_27 */
+ >;
+ };
+};
+
+&lcdc {
+ status = "okay";
+ port {
+ lcdc_0: endpoint@0 {
+ remote-endpoint = <&hdmi_0>;
+ };
+ };
+};
+
+&mac {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&cpsw_default>;
+ pinctrl-1 = <&cpsw_sleep>;
+};
+
+&davinci_mdio {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&davinci_mdio_default>;
+ pinctrl-1 = <&davinci_mdio_sleep>;
+};
+
+&cpsw_emac0 {
+ phy_id = <&davinci_mdio>, <0>;
+ phy-mode = "rgmii-txid";
+};
+
+&i2c0 {
+ tda19988: tda19988 {
+ compatible = "nxp,tda998x";
+ reg = <0x70>;
+
+ pinctrl-names = "default", "off";
+ pinctrl-0 = <&nxp_hdmi_bonelt_pins>;
+ pinctrl-1 = <&nxp_hdmi_bonelt_off_pins>;
+
+ #sound-dai-cells = <0>;
+ audio-ports = < TDA998x_I2S 0x03>;
+
+ ports {
+ port@0 {
+ hdmi_0: endpoint@0 {
+ remote-endpoint = <&lcdc_0>;
+ };
+ };
+ };
+ };
+
+ lps331ap: lps331ap@5C {
+ compatible = "st,lps331ap";
+ st,drdy-int-pin = <1>;
+ reg = <0x5C>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <27 IRQ_TYPE_EDGE_RISING>;
+ };
+
+ mpu6050: mpu6050@68 {
+ compatible = "invensense,mpu6050";
+ reg = <0x68>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <2 IRQ_TYPE_EDGE_RISING>;
+ //orientation = <0xff 0 0 0 1 0 0 0 0xff>;
+ };
+};
+
+&mcasp0 {
+ #sound-dai-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&mcasp0_pins>;
+ status = "okay";
+ op-mode = <0>; /* MCASP_IIS_MODE */
+ tdm-slots = <2>;
+ serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */
+ 0 0 1 0
+ >;
+ tx-num-evt = <32>;
+ rx-num-evt = <32>;
+};
+
+/ {
+ clk_mcasp0_fixed: clk_mcasp0_fixed {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <24576000>;
+ };
+
+ clk_mcasp0: clk_mcasp0 {
+ #clock-cells = <0>;
+ compatible = "gpio-gate-clock";
+ clocks = <&clk_mcasp0_fixed>;
+ enable-gpios = <&gpio1 27 0>; /* BeagleBone Black Clk enable on GPIO1_27 */
+ };
+
+ sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "TI BeagleBone Black";
+ simple-audio-card,format = "i2s";
+ simple-audio-card,bitclock-master = <&dailink0_master>;
+ simple-audio-card,frame-master = <&dailink0_master>;
+
+ dailink0_master: simple-audio-card,cpu {
+ sound-dai = <&mcasp0>;
+ clocks = <&clk_mcasp0>;
+ };
+
+ simple-audio-card,codec {
+ sound-dai = <&tda19988>;
+ };
+ };
+};
diff --git b/arch/arm/boot/dts/am335x-som-common.dtsi b/arch/arm/boot/dts/am335x-som-common.dtsi
new file mode 100644
index 0000000..fb4399b
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-som-common.dtsi
@@ -0,0 +1,465 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/ {
+
+ cpus {
+ cpu@0 {
+ cpu0-supply = <&dcdc2_fixed>;
+ };
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x80000000 0x20000000>; /* 512 MB */
+ };
+
+ ocp {
+ uart0: serial@44e09000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pins>;
+
+ status = "okay";
+ };
+ uart1: serial@48022000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart1_pins>;
+ status = "okay";
+
+ };
+ uart4: serial@481a8000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart4_pins>;
+ status = "okay";
+ };
+
+ epwmss0: epwmss@48300000 {
+ status = "okay";
+
+ ecap0: ecap@48300100 {
+ status = "okay";
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&ecap0_pins_default>;
+ pinctrl-1 = <&ecap0_pins_sleep>;
+ };
+ };
+
+ musb: usb@47400000 {
+ status = "okay";
+
+ control@44e10000 {
+ status = "okay";
+ };
+
+ usb-phy@47401300 {
+ status = "okay";
+ };
+
+ usb-phy@47401b00 {
+ status = "okay";
+ };
+
+ usb@47401000 {
+ status = "okay";
+ dr_mode = "otg";
+ };
+
+ usb@47401800 {
+ status = "okay";
+ dr_mode = "host";
+ };
+
+ dma-controller@07402000 {
+ status = "okay";
+ };
+ };
+
+ i2c0: i2c@44e0b000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins>;
+ status = "okay";
+ clock-frequency = <100000>;
+
+ tps: tps@24 {
+ reg = <0x24>;
+ };
+ };
+ };
+
+ vmmcsd_fixed: fixedregulator@0 {
+ compatible = "regulator-fixed";
+ regulator-name = "vmmcsd_fixed";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ dcdc2_fixed: fixedregulator@1 {
+ /* VDD_MPU voltage limits 0.95V - 1.325V with +/-4% tolerance */
+ compatible = "regulator-fixed";
+ regulator-name = "dcdc2_fixed";
+
+ regulator-min-microvolt = <1378000>;
+ regulator-max-microvolt = <1378000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ leds {
+ pinctrl-names = "default";
+ pinctrl-0 = <&user_leds_s0>;
+
+ compatible = "gpio-leds";
+
+ led@1 {
+ label = "led1:green:heartbeat";
+ gpios = <&gpio0 19 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "heartbeat";
+ };
+
+ led@2 {
+ label = "led2:red:heartbeat";
+ gpios = <&gpio3 20 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "heartbeat";
+ };
+
+ led@3 {
+ label = "led3:yello:heartbeat";
+ gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "heartbeat";
+ };
+
+ led@4 {
+ label = "bkl";
+ gpios = <&gpio3 19 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "default-on";
+ };
+ };
+
+ backlight {
+ compatible = "pwm-backlight";
+ pwms = <&ecap0 0 500000 1>;
+ brightness-levels = <
+ 0 1 2 3 4 5 6 7 8 9
+ 10 11 12 13 14 15 16 17 18 19
+ 20 21 22 23 24 25 26 27 28 29
+ 30 31 32 33 34 35 36 37 38 39
+ 40 41 42 43 44 45 46 47 48 49
+ 50 51 52 53 54 55 56 57 58 59
+ 60 61 62 63 64 65 66 67 68 69
+ 70 71 72 73 74 75 76 77 78 79
+ 80 81 82 83 84 85 86 87 88 89
+ 90 91 92 93 94 95 96 97 98 99
+ 100
+ >;
+ default-brightness-level = <50>;
+ };
+};
+
+&am33xx_pinmux {
+ pinctrl-names = "default";
+ pinctrl-0 = <&clkout2_pin>;
+
+ user_leds_s0: user_leds_s0 {
+ pinctrl-single,pins = <
+ 0x1b0 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* xdma_event_intr0.gpio0_19 */
+ 0x198 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* mcasp0_axr0.gpio3_20 */
+ 0x1a8 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* mcasp0_axr1.gpio3_21 */
+ 0x1a4 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* mcasp0_fsr.gpio3[19], INPUT_PULLDOWN | MODE7 */
+ >;
+ };
+
+ i2c0_pins: pinmux_i2c0_pins {
+ pinctrl-single,pins = <
+ 0x188 (PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_sda.i2c0_sda */
+ 0x18c (PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_scl.i2c0_scl */
+ >;
+ };
+
+ uart0_pins: pinmux_uart0_pins {
+ pinctrl-single,pins = <
+ 0x170 (PIN_INPUT_PULLUP | MUX_MODE0) /* uart0_rxd.uart0_rxd */
+ 0x174 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */
+ >;
+ };
+
+ uart1_pins: pinmux_uart1_pins {
+ pinctrl-single,pins = <
+ 0x168 (PIN_INPUT_PULLUP | MUX_MODE1)
+ 0x16c (PIN_OUTPUT_PULLDOWN | MUX_MODE1)
+ >;
+ };
+
+ uart4_pins: pinmux_uart4_pins {
+ pinctrl-single,pins = <
+ 0x180 (PIN_INPUT_PULLUP | MUX_MODE0)
+ 0x184 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)
+ >;
+ };
+
+
+
+ clkout2_pin: pinmux_clkout2_pin {
+ pinctrl-single,pins = <
+ 0x1b4 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* xdma_event_intr1.clkout2 */
+ >;
+ };
+
+ cpsw_default: cpsw_default {
+ pinctrl-single,pins = <
+ /* Slave 1 */
+ 0x110 (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxerr.mii1_rxerr */
+ 0x114 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txen.mii1_txen */
+ 0x118 (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxdv.mii1_rxdv */
+ 0x11c (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd3.mii1_txd3 */
+ 0x120 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd2.mii1_txd2 */
+ 0x124 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd1.mii1_txd1 */
+ 0x128 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd0.mii1_txd0 */
+ 0x12c (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_txclk.mii1_txclk */
+ 0x130 (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxclk.mii1_rxclk */
+ 0x134 (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxd3.mii1_rxd3 */
+ 0x138 (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxd2.mii1_rxd2 */
+ 0x13c (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxd1.mii1_rxd1 */
+ 0x140 (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxd0.mii1_rxd0 */
+
+ 0x040 (PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* gpmc_a0.gmii2_txen, OUTPUT_PULLDOWN | MODE1 */
+ 0x044 (PIN_INPUT_PULLDOWN | MUX_MODE1 ) /* gpmc_a1.gmii2_rxdv, INPUT_PULLDOWN | MODE1 */
+ 0x048 (PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* gpmc_a2.gmii2_txd3, OUTPUT_PULLDOWN | MODE1 */
+ 0x04c (PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* gpmc_a3.gmii2_txd2, OUTPUT_PULLDOWN | MODE1 */
+ 0x050 (PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* gpmc_a4.gmii2_txd1, OUTPUT_PULLDOWN | MODE1 */
+ 0x054 (PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* gpmc_a5.gmii2_txd0, OUTPUT_PULLDOWN | MODE1 */
+ 0x058 (PIN_INPUT_PULLDOWN | MUX_MODE1 ) /* gpmc_a6.gmii2_txclk, INPUT_PULLDOWN | MODE1 */
+ 0x05c (PIN_INPUT_PULLDOWN | MUX_MODE1 ) /* gpmc_a7.gmii2_rxclk, INPUT_PULLDOWN | MODE1 */
+ 0x060 (PIN_INPUT_PULLDOWN | MUX_MODE1 ) /* gpmc_a8.gmii2_rxd3, INPUT_PULLDOWN | MODE1 */
+ 0x064 (PIN_INPUT_PULLDOWN | MUX_MODE1 ) /* gpmc_a9.gmii2_rxd2, INPUT_PULLDOWN | MODE1 */
+ 0x068 (PIN_INPUT_PULLDOWN | MUX_MODE1 ) /* gpmc_a10.gmii2_rxd1, INPUT_PULLDOWN | MODE1 */
+ 0x06c (PIN_INPUT_PULLDOWN | MUX_MODE1 ) /* gpmc_a11.gmii2_rxd0, INPUT_PULLDOWN | MODE1 */
+ 0x070 (PIN_INPUT_PULLUP | MUX_MODE1 ) /* gpmc_wait0.gmii2_crs, INPUT_PULLUP | MODE1 */
+ 0x074 (PIN_INPUT_PULLUP | MUX_MODE1 ) /* gpmc_wpn.gmii2_rxer, INPUT_PULLUP | MODE1 */
+ 0x078 (PIN_INPUT_PULLUP | MUX_MODE1 ) /* gpmc_ben1.gmii2_col, INPUT_PULLUP | MODE1 */
+ >;
+ };
+
+ cpsw_sleep: cpsw_sleep {
+ pinctrl-single,pins = <
+ /* Slave 1 reset value */
+ 0x110 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x118 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x11c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x120 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x12c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x130 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x134 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x138 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+
+ 0x40 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x44 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x48 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x4c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x50 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x54 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x58 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x5c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x60 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x64 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x68 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x6c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x070 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x074 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x078 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ >;
+ };
+
+ davinci_mdio_default: davinci_mdio_default {
+ pinctrl-single,pins = <
+ /* MDIO */
+ 0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */
+ 0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_clk.mdio_clk */
+ >;
+ };
+
+ davinci_mdio_sleep: davinci_mdio_sleep {
+ pinctrl-single,pins = <
+ /* MDIO reset value */
+ 0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ >;
+ };
+
+ mmc1_pins_default: pinmux_mmc1_pins {
+ pinctrl-single,pins = <
+ 0x0F0 (PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat3.mmc0_dat3 */
+ 0x0F4 (PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat2.mmc0_dat2 */
+ 0x0F8 (PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat1.mmc0_dat1 */
+ 0x0FC (PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat0.mmc0_dat0 */
+ 0x100 (PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_clk.mmc0_clk */
+ 0x104 (PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_cmd.mmc0_cmd */
+ 0x1A0 (PIN_INPUT_PULLUP | MUX_MODE7) /* mcasp0_aclkr.gpio3_18 */
+ 0x160 (PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */
+ >;
+ };
+
+ mmc1_pins_sleep: pinmux_mmc1_pins_sleep {
+ pinctrl-single,pins = <
+ 0x0F0 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x0F4 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x0F8 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x0FC (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x100 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x104 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x1A0 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x160 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ >;
+ };
+
+ emmc_pins: pinmux_emmc_pins {
+ pinctrl-single,pins = <
+ 0x80 (PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn1.mmc1_clk */
+ 0x84 (PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn2.mmc1_cmd */
+ 0x00 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad0.mmc1_dat0 */
+ 0x04 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad1.mmc1_dat1 */
+ 0x08 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad2.mmc1_dat2 */
+ 0x0c (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad3.mmc1_dat3 */
+ 0x10 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad4.mmc1_dat4 */
+ 0x14 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad5.mmc1_dat5 */
+ 0x18 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad6.mmc1_dat6 */
+ 0x1c (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad7.mmc1_dat7 */
+ >;
+ };
+
+ ecap0_pins_default: backlight_pins {
+ pinctrl-single,pins = <
+ 0x164 0x0 /* eCAP0_in_PWM0_out.eCAP0_in_PWM0_out MODE0 */
+ >;
+ };
+
+ ecap0_pins_sleep: ecap0_pins_sleep {
+ pinctrl-single,pins = <
+ 0x164 (PULL_DISABLE | MUX_MODE7) /* eCAP0_in_PWM0_out.eCAP0_in_PWM0_out */
+ >;
+ };
+ dcan0_default: dcan0_default_pins {
+ pinctrl-single,pins = <
+ 0x178 0x0a /* uart1_ctsn.dcan0_tx_mux2, OUTPUT | MODE2 */
+ 0x17c 0x2a /* uart1_rtsn.dcan0_rx_mux2, INPUT | MODE2 */
+ >;
+ };
+ };
+
+&tps {
+ compatible = "ti,tps65217";
+ regulators {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ dcdc1_reg: regulator@0 {
+ reg = <0>;
+ regulator-always-on;
+ };
+
+ dcdc2_reg: regulator@1 {
+ reg = <1>;
+ /* VDD_MPU voltage limits 0.95V - 1.325V with +/-4% tolerance */
+ regulator-name = "vdd_mpu";
+ regulator-min-microvolt = <925000>;
+ regulator-max-microvolt = <1378000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ dcdc3_reg: regulator@2 {
+ reg = <2>;
+ /* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
+ regulator-name = "vdd_core";
+ regulator-min-microvolt = <925000>;
+ regulator-max-microvolt = <1150000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo1_reg: regulator@3 {
+ reg = <3>;
+ regulator-always-on;
+ };
+
+ ldo2_reg: regulator@4 {
+ reg = <4>;
+ regulator-always-on;
+ };
+
+ ldo3_reg: regulator@5 {
+ reg = <5>;
+ regulator-always-on;
+ };
+
+ ldo4_reg: regulator@6 {
+ reg = <6>;
+ regulator-always-on;
+ };
+ };
+};
+
+&cpsw_emac0 {
+ phy_id = <&davinci_mdio>, <0>;
+ phy-mode = "mii";
+};
+
+&cpsw_emac1 {
+ phy_id = <&davinci_mdio>, <1>;
+ phy-mode = "mii";
+};
+
+&mac {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&cpsw_default>;
+ pinctrl-1 = <&cpsw_sleep>;
+ slaves = <2>;
+ dual_emac = <1>;
+ status = "okay";
+};
+
+&davinci_mdio {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&davinci_mdio_default>;
+ pinctrl-1 = <&davinci_mdio_sleep>;
+ status = "okay";
+};
+
+&mmc1 {
+ status = "okay";
+ bus-width = <0x4>;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&mmc1_pins_default>;
+ pinctrl-1 = <&mmc1_pins_sleep>;
+ cd-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>;
+ cd-inverted;
+};
+
+&dcan0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&dcan0_default>;
+ status = "okay";
+};
+
+&tscadc {
+ status = "okay";
+ tsc {
+ ti,wires = <4>;
+ ti,x-plate-resistance = <200>;
+ ti,coordinate-readouts = <5>;
+ ti,wire-config = <0x00 0x11 0x22 0x33>;
+ };
+
+ adc {
+ ti,adc-channels = <0 1 2 3>;
+ };
+};
diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
index f3d51f4..e051b96 100644
--- a/arch/arm/boot/dts/am33xx.dtsi
+++ b/arch/arm/boot/dts/am33xx.dtsi
@@ -36,6 +36,9 @@
phy1 = &usb1_phy;
ethernet0 = &cpsw_emac0;
ethernet1 = &cpsw_emac1;
+ mmc0 = &mmc1;
+ mmc1 = &mmc2;
+ mmc2 = &mmc3;
};
cpus {
@@ -46,19 +49,7 @@
device_type = "cpu";
reg = <0>;
- /*
- * To consider voltage drop between PMIC and SoC,
- * tolerance value is reduced to 2% from 4% and
- * voltage value is increased as a precaution.
- */
- operating-points = <
- /* kHz uV */
- 720000 1285000
- 600000 1225000
- 500000 1125000
- 275000 1125000
- >;
- voltage-tolerance = <2>; /* 2 percentage */
+ operating-points-v2 = <&cpu0_opp_table>;
clocks = <&dpll_mpu_ck>;
clock-names = "cpu";
@@ -67,6 +58,80 @@
};
};
+ cpu0_opp_table: opp_table0 {
+ compatible = "operating-points-v2-ti-cpu";
+ ti,syscon-efuse = <&scm_conf 0x7fc 0x1fff 0>;
+ ti,syscon-rev = <&scm_conf 0x600>;
+
+ /*
+ * The three following nodes are marked with opp-suspend
+ * because the can not be enabled simultaneously on a
+ * single SoC.
+ */
+ opp50@300000000 {
+ opp-hz = /bits/ 64 <300000000>;
+ opp-microvolt = <950000 931000 969000>;
+ opp-supported-hw = <0x06 0x0010>;
+ opp-suspend;
+ };
+
+ opp100@275000000 {
+ opp-hz = /bits/ 64 <275000000>;
+ opp-microvolt = <1100000 1078000 1122000>;
+ opp-supported-hw = <0x01 0x00FF>;
+ opp-suspend;
+ };
+
+ opp100@300000000 {
+ opp-hz = /bits/ 64 <300000000>;
+ opp-microvolt = <1100000 1078000 1122000>;
+ opp-supported-hw = <0x06 0x0020>;
+ opp-suspend;
+ };
+
+ opp100@500000000 {
+ opp-hz = /bits/ 64 <500000000>;
+ opp-microvolt = <1100000 1078000 1122000>;
+ opp-supported-hw = <0x01 0xFFFF>;
+ };
+
+ opp100@600000000 {
+ opp-hz = /bits/ 64 <600000000>;
+ opp-microvolt = <1100000 1078000 1122000>;
+ opp-supported-hw = <0x06 0x0040>;
+ };
+
+ opp120@600000000 {
+ opp-hz = /bits/ 64 <600000000>;
+ opp-microvolt = <1200000 1176000 1224000>;
+ opp-supported-hw = <0x01 0xFFFF>;
+ };
+
+ opp120@720000000 {
+ opp-hz = /bits/ 64 <720000000>;
+ opp-microvolt = <1200000 1176000 1224000>;
+ opp-supported-hw = <0x06 0x0080>;
+ };
+
+ oppturbo@720000000 {
+ opp-hz = /bits/ 64 <720000000>;
+ opp-microvolt = <1260000 1234800 1285200>;
+ opp-supported-hw = <0x01 0xFFFF>;
+ };
+
+ oppturbo@800000000 {
+ opp-hz = /bits/ 64 <800000000>;
+ opp-microvolt = <1260000 1234800 1285200>;
+ opp-supported-hw = <0x06 0x0100>;
+ };
+
+ oppnitro@1000000000 {
+ opp-hz = /bits/ 64 <1000000000>;
+ opp-microvolt = <1325000 1298500 1351500>;
+ opp-supported-hw = <0x04 0x0200>;
+ };
+ };
+
pmu {
compatible = "arm,cortex-a8-pmu";
interrupts = <3>;
@@ -91,7 +156,7 @@
* for the moment, just use a fake OCP bus entry to represent
* the whole bus hierarchy.
*/
- ocp {
+ ocp: ocp {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
@@ -500,12 +565,25 @@
ti,timer-pwm;
};
+ pruss: pruss@4a300000 {
+ compatible = "ti,pruss-v2";
+ ti,hwmods = "pruss";
+ ti,deassert-hard-reset = "pruss", "pruss";
+ reg = <0x4a300000 0x080000>;
+ ti,pintc-offset = <0x20000>;
+ interrupt-parent = <&intc>;
+ status = "disabled";
+ interrupts = <20 21 22 23 24 25 26 27>;
+ };
+
rtc: rtc@44e3e000 {
compatible = "ti,am3352-rtc", "ti,da830-rtc";
reg = <0x44e3e000 0x1000>;
interrupts = <75
76>;
ti,hwmods = "rtc";
+ ti,no-reset-on-init;
+ ti,no-idle-on-init;
};
spi0: spi@48030000 {
@@ -691,6 +769,16 @@
status = "disabled";
};
+ eqep0: eqep@0x48300180 {
+ compatible = "ti,am33xx-eqep";
+ reg = <0x48300180 0x80>;
+ clocks = <&l4ls_gclk>;
+ clock-names = "fck";
+ interrupt-parent = <&intc>;
+ interrupts = <79>;
+ status = "disabled";
+ };
+
ehrpwm0: pwm@48300200 {
compatible = "ti,am3352-ehrpwm",
"ti,am33xx-ehrpwm";
@@ -725,6 +813,17 @@
status = "disabled";
};
+
+ eqep1: eqep@0x48302180 {
+ compatible = "ti,am33xx-eqep";
+ reg = <0x48302180 0x80>;
+ clocks = <&l4ls_gclk>;
+ clock-names = "fck";
+ interrupt-parent = <&intc>;
+ interrupts = <88>;
+ status = "disabled";
+ };
+
ehrpwm1: pwm@48302200 {
compatible = "ti,am3352-ehrpwm",
"ti,am33xx-ehrpwm";
@@ -759,6 +858,16 @@
status = "disabled";
};
+ eqep2: eqep@0x48304180 {
+ compatible = "ti,am33xx-eqep";
+ reg = <0x48304180 0x80>;
+ clocks = <&l4ls_gclk>;
+ clock-names = "fck";
+ interrupt-parent = <&intc>;
+ interrupts = <89>;
+ status = "disabled";
+ };
+
ehrpwm2: pwm@48304200 {
compatible = "ti,am3352-ehrpwm",
"ti,am33xx-ehrpwm";
diff --git a/arch/arm/boot/dts/am4372.dtsi b/arch/arm/boot/dts/am4372.dtsi
index 9435b6c..e2d77fd 100644
--- a/arch/arm/boot/dts/am4372.dtsi
+++ b/arch/arm/boot/dts/am4372.dtsi
@@ -50,15 +50,15 @@
clock-names = "cpu";
operating-points-v2 = <&cpu0_opp_table>;
- ti,syscon-efuse = <&scm_conf 0x610 0x3f 0>;
- ti,syscon-rev = <&scm_conf 0x600>;
clock-latency = <300000>; /* From omap-cpufreq driver */
};
};
cpu0_opp_table: opp_table0 {
- compatible = "operating-points-v2";
+ compatible = "operating-points-v2-ti-cpu";
+ ti,syscon-efuse = <&scm_conf 0x610 0x3f 0>;
+ ti,syscon-rev = <&scm_conf 0x600>;
opp50@300000000 {
opp-hz = /bits/ 64 <300000000>;
diff --git a/arch/arm/boot/dts/am57xx-beagle-x15-common.dtsi b/arch/arm/boot/dts/am57xx-beagle-x15-common.dtsi
index 6df7829..a2e4c29 100644
--- a/arch/arm/boot/dts/am57xx-beagle-x15-common.dtsi
+++ b/arch/arm/boot/dts/am57xx-beagle-x15-common.dtsi
@@ -190,6 +190,11 @@
>;
};
};
+
+&bb2d {
+ status = "okay";
+};
+
&i2c1 {
status = "okay";
clock-frequency = <400000>;
diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi
index 064d84f..6e63e28 100644
--- a/arch/arm/boot/dts/dra7.dtsi
+++ b/arch/arm/boot/dts/dra7.dtsi
@@ -81,11 +81,7 @@
compatible = "arm,cortex-a15";
reg = <0>;
- operating-points = <
- /* kHz uV */
- 1000000 1060000
- 1176000 1160000
- >;
+ operating-points-v2 = <&cpu0_opp_table>;
clocks = <&dpll_mpu_ck>;
clock-names = "cpu";
@@ -99,6 +95,25 @@
};
};
+ cpu0_opp_table: opp_table0 {
+ compatible = "operating-points-v2-ti-cpu";
+ ti,syscon-efuse = <&scm_wkup 0x20c 0xf80000 19>;
+ ti,syscon-rev = <&scm_wkup 0x204>;
+
+ opp_nom@1000000000 {
+ opp-hz = /bits/ 64 <1000000000>;
+ opp-microvolt = <1060000 850000 1150000>;
+ opp-supported-hw = <0xFF 0x01>;
+ opp-suspend;
+ };
+
+ opp_od@1176000000 {
+ opp-hz = /bits/ 64 <1176000000>;
+ opp-microvolt = <1160000 885000 1160000>;
+ opp-supported-hw = <0xFF 0x02>;
+ };
+ };
+
/*
* The soc node represents the soc top level view. It is used for IPs
* that are not memory mapped in the MPU view or for the MPU itself.
@@ -401,6 +416,13 @@
reg = <0x40d00000 0x100>;
};
+ dra7_iodelay_core: padconf@4844a000 {
+ compatible = "ti,dra7-iodelay";
+ reg = <0x4844a000 0x0d1c>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
sdma: dma-controller@4a056000 {
compatible = "ti,omap4430-sdma";
reg = <0x4a056000 0x1000>;
@@ -959,6 +981,16 @@
ti,hwmods = "dmm";
};
+ bb2d: bb2d@59000000 {
+ compatible = "ti,dra7-bb2d","vivante,gc";
+ reg = <0x59000000 0x0700>;
+ interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
+ ti,hwmods = "bb2d";
+ clocks = <&dpll_core_h24x2_ck>;
+ clock-names = "fclk";
+ status = "disabled";
+ };
+
i2c1: i2c@48070000 {
compatible = "ti,omap4-i2c";
reg = <0x48070000 0x100>;
@@ -1970,6 +2002,12 @@
};
};
+ gpu-subsystem {
+ compatible = "vivante,gc-gpu-subsystem";
+ cores = <&bb2d>;
+ status = "okay";
+ };
+
thermal_zones: thermal-zones {
#include "omap4-cpu-thermal.dtsi"
#include "omap5-gpu-thermal.dtsi"
diff --git a/arch/arm/boot/dts/dra74x.dtsi b/arch/arm/boot/dts/dra74x.dtsi
index 0a78347..24e6746 100644
--- a/arch/arm/boot/dts/dra74x.dtsi
+++ b/arch/arm/boot/dts/dra74x.dtsi
@@ -17,6 +17,7 @@
device_type = "cpu";
compatible = "arm,cortex-a15";
reg = <1>;
+ operating-points-v2 = <&cpu0_opp_table>;
};
};
@@ -79,6 +80,10 @@
};
};
+&cpu0_opp_table {
+ opp-shared;
+};
+
&dss {
reg = <0x58000000 0x80>,
<0x58004054 0x4>,
diff --git b/arch/arm/boot/dts/exynos5422-artik10-eval.dts b/arch/arm/boot/dts/exynos5422-artik10-eval.dts
new file mode 100644
index 0000000..1001255
--- /dev/null
+++ b/arch/arm/boot/dts/exynos5422-artik10-eval.dts
@@ -0,0 +1,278 @@
+/*
+ * SAMSUNG ARTIK10 board device tree source
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/dts-v1/;
+
+#include <dt-bindings/clock/samsung,s2mps11.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/sound/samsung-i2s.h>
+#include "exynos5800.dtsi"
+#include "exynos5422-cpus.dtsi"
+#include "exynos-mfc-reserved-memory.dtsi"
+
+/ {
+ model = "Samsung ARTIK10 board based on EXYNOS5422";
+ compatible = "samsung,artik10", "samsung,exynos5422", "samsung,exynos5";
+
+ memory@40000000 {
+ device_type = "memory";
+ reg = <0x40000000 0x7EA00000>;
+ };
+
+ chosen {
+ stdout-path = "serial2:115200n8";
+ };
+
+ firmware@02073000 {
+ compatible = "samsung,secure-firmware";
+ reg = <0x02073000 0x1000>;
+ };
+
+ fixed-rate-clocks {
+ oscclk {
+ compatible = "samsung,exynos5420-oscclk";
+ clock-frequency = <24000000>;
+ };
+ };
+
+ rtc {
+ status = "okay";
+ };
+};
+
+&cpu0 {
+ cpu-supply = <&buck6_reg>;
+};
+
+&cpu4 {
+ cpu-supply = <&buck2_reg>;
+};
+
+&pinctrl_0 {
+ s2mps11_irq: s2mps11-irq {
+ samsung,pins = "gpx3-2";
+ samsung,pin-pud = <3>;
+ samsung,pin-drv = <3>;
+ };
+};
+
+&hsi2c_4 {
+ clock-frequency = <400000>;
+ status = "okay";
+
+ s2mps11_pmic@66 {
+ compatible = "samsung,s2mps11-pmic";
+ interrupt-parent = <&gpx3>;
+ interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
+ reg = <0x66>;
+
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&s2mps11_irq>;
+
+ s2mps11_osc: clocks {
+ #clock-cells = <1>;
+ clock-output-names = "s2mps11_ap",
+ "s2mps11_cp", "s2mps11_bt";
+ };
+
+ regulators {
+ ldo4_reg: LDO4 {
+ regulator-name = "vdd_adc";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ ldo6_reg: LDO6 {
+ regulator-name = "vdd_ldo6";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-always-on;
+ };
+
+ ldo7_reg: LDO7 {
+ regulator-name = "vdd_ldo7";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ ldo13_reg: LDO13 {
+ regulator-name = "vqmmc";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ ldo17_reg: LDO17 {
+ regulator-name = "vdd_ldo17";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ };
+
+ ldo18_reg: LDO18 {
+ regulator-name = "vdd_ldo18";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ ldo19_reg: LDO19 {
+ regulator-name = "vmmc";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ ldo20_reg: LDO20 {
+ regulator-name = "vdd_ldo20";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ ldo23_reg: LDO23 {
+ regulator-name = "vdd_mifs";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-always-on;
+ };
+
+ ldo24_reg: LDO24 {
+ regulator-name = "vdd_ldo24";
+ regulator-min-microvolt = <2400000>;
+ regulator-max-microvolt = <2400000>;
+ };
+
+ ldo25_reg: LDO25 {
+ regulator-name = "vdd_ldo25";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ ldo27_reg: LDO27 {
+ regulator-name = "vdd_g3ds";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-always-on;
+ };
+
+ ldo28_reg: LDO28 {
+ regulator-name = "vdd_ldo28";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ };
+
+ ldo32_reg: LDO32 {
+ regulator-name = "vdd_lcd_1v8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ ldo38_reg: LDO38 {
+ regulator-name = "vdd_ldo38";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-always-on;
+ };
+
+ buck1_reg: BUCK1 {
+ regulator-name = "vdd_mif";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-always-on;
+ };
+
+ buck2_reg: BUCK2 {
+ regulator-name = "vdd_eagle";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1500000>;
+ regulator-always-on;
+ };
+
+ buck3_reg: BUCK3 {
+ regulator-name = "vdd_int";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1400000>;
+ regulator-always-on;
+ };
+
+ buck4_reg: BUCK4 {
+ regulator-name = "vdd_g3d";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1400000>;
+ regulator-always-on;
+ };
+
+ buck6_reg: BUCK6 {
+ regulator-name = "vdd_kfc";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1500000>;
+ regulator-always-on;
+ };
+
+ buck10_reg: BUCK10 {
+ regulator-name = "vdd_cam_isp_1.0v";
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <1500000>;
+ regulator-always-on;
+ };
+ };
+ };
+};
+
+&mmc_0 {
+ status = "okay";
+ broken-cd;
+ card-detect-delay = <200>;
+ samsung,dw-mshc-ciu-div = <3>;
+ samsung,dw-mshc-sdr-timing = <0 4>;
+ samsung,dw-mshc-ddr-timing = <0 2>;
+ samsung,dw-mshc-hs400-timing = <0 2>;
+ samsung,read-strobe-delay = <90>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus1 &sd0_bus4 &sd0_bus8
+ &sd0_rclk>;
+ bus-width = <8>;
+ cap-mmc-highspeed;
+ keep-power-in-suspend;
+ non-removable;
+};
+
+&mmc_2 {
+ status = "okay";
+ card-detect-delay = <200>;
+ samsung,dw-mshc-ciu-div = <3>;
+ samsung,dw-mshc-sdr-timing = <2 3>;
+ samsung,dw-mshc-ddr-timing = <1 2>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus1 &sd2_bus4>;
+ bus-width = <4>;
+ cap-sd-highspeed;
+ vmmc-supply = <&ldo28_reg>;
+};
+
+&nocp_mem0_0 {
+ status = "okay";
+};
+
+&nocp_mem0_1 {
+ status = "okay";
+};
+
+&nocp_mem1_0 {
+ status = "okay";
+};
+
+&nocp_mem1_1 {
+ status = "okay";
+};
diff --git b/arch/arm/boot/dts/imx6q-ccimx6sbc.dts b/arch/arm/boot/dts/imx6q-ccimx6sbc.dts
new file mode 100644
index 0000000..d249240
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-ccimx6sbc.dts
@@ -0,0 +1,303 @@
+/*
+ * Copyright (C) 2015 Robert Nelson (robertcnelson@gmail.com)
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ * a) This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License.
+ *
+ * This file is distributed in the hope that it will be useful
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ * b) Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+/dts-v1/;
+
+#include "imx6q.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+ model = "Digi ConnectCore-i.MX6 SBC Board";
+ compatible = "digi,connectcore/q", "fsl,imx6q";
+
+ chosen {
+ stdout-path = &uart4;
+ };
+
+ memory {
+ reg = <0x10000000 0x40000000>;
+ };
+
+ regulators {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg_usbh1_reset: regulator@1 {
+ compatible = "regulator-fixed";
+ reg = <1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbh1>;
+ regulator-name = "usbh1_reset";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio3 10 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_usb_otg_vbus: regulator@2 {
+ compatible = "regulator-fixed";
+ reg = <2>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbotg>;
+ regulator-name = "usb_otg_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio3 22 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+ };
+};
+
+&fec {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet>;
+ phy-mode = "rgmii";
+ phy-reset-gpios = <&gpio1 25 GPIO_ACTIVE_LOW>;
+ status = "okay";
+};
+
+&hdmi {
+ ddc-i2c-bus = <&i2c3>;
+ status = "okay";
+};
+
+&i2c2 {
+ clock-frequency = <400000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2>;
+ status = "okay";
+
+ pmic@58 {
+ compatible = "dlg,da9063";
+ reg = <0x58>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <17 0x8>; /* active-low GPIO0_17 */
+
+ regulators {
+ vdd_3v3_reg: bperi {
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ ldo3_reg: ldo3 {
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ ldo4_reg: ldo4 {
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ ldo6_reg: ldo6 {
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ ldo7_reg: ldo7 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ ldo8_reg: ldo8 {
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+ };
+ };
+};
+
+&i2c3 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c3>;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog>;
+
+ imx6qdl-ccimx6sbc {
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ /* da9063*/
+ MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x80000000
+ >;
+ };
+
+ pinctrl_enet: enetgrp {
+ fsl,pins = <
+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x100b0
+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x100b0
+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x100b0
+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x100b0
+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x100b0
+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x100b0
+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x100b0
+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x100b0
+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x100b0
+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0
+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0
+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0
+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0
+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0
+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
+ /* Phy reset */
+ MX6QDL_PAD_ENET_CRS_DV__GPIO1_IO25 0x000b0
+ >;
+ };
+
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
+ >;
+ };
+
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_5__I2C3_SCL 0x4001b8b1
+ MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1
+ >;
+ };
+
+ pinctrl_uart4: uart4grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1
+ MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA 0x1b0b1
+ >;
+ };
+
+ pinctrl_usbh1: usbh1grp {
+ fsl,pins = <
+ /* need to force low for hub reset */
+ MX6QDL_PAD_EIM_DA10__GPIO3_IO10 0x10b0
+ >;
+ };
+
+ pinctrl_usbotg: usbotggrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
+ MX6QDL_PAD_EIM_D21__USB_OTG_OC 0x1b0b0
+ /* power enable, high active */
+ MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x10b0
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
+ >;
+ };
+
+ pinctrl_usdhc4: usdhc4grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059
+ MX6QDL_PAD_SD4_CLK__SD4_CLK 0x10059
+ MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059
+ MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059
+ MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059
+ MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059
+ MX6QDL_PAD_SD4_DAT4__SD4_DATA4 0x17059
+ MX6QDL_PAD_SD4_DAT5__SD4_DATA5 0x17059
+ MX6QDL_PAD_SD4_DAT6__SD4_DATA6 0x17059
+ MX6QDL_PAD_SD4_DAT7__SD4_DATA7 0x17059
+ >;
+ };
+ };
+};
+
+&sata {
+ status = "okay";
+};
+
+&ssi1 {
+ status = "okay";
+};
+
+&uart4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart4>;
+ status = "okay";
+};
+
+&usbh1 {
+ vbus-supply = <®_usbh1_reset>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbh1>;
+ status = "okay";
+};
+
+&usbotg {
+ vbus-supply = <®_usb_otg_vbus>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbotg>;
+ status = "okay";
+};
+
+&usdhc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc2>;
+ bus-width = <4>;
+ broken-cd; /* cd & wp, is not wired up on this board */
+ status = "okay";
+};
+
+&usdhc4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc4>;
+ bus-width = <8>;
+ non-removable;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6q-evi.dts b/arch/arm/boot/dts/imx6q-evi.dts
index 6de21ff..3277a06 100644
--- a/arch/arm/boot/dts/imx6q-evi.dts
+++ b/arch/arm/boot/dts/imx6q-evi.dts
@@ -54,18 +54,6 @@
reg = <0x10000000 0x40000000>;
};
- reg_usbh1_vbus: regulator-usbhubreset {
- compatible = "regulator-fixed";
- regulator-name = "usbh1_vbus";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- enable-active-high;
- startup-delay-us = <2>;
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_usbh1_hubreset>;
- gpio = <&gpio7 12 GPIO_ACTIVE_HIGH>;
- };
-
reg_usb_otg_vbus: regulator-usbotgvbus {
compatible = "regulator-fixed";
regulator-name = "usb_otg_vbus";
@@ -207,12 +195,18 @@
};
&usbh1 {
- vbus-supply = <®_usbh1_vbus>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usbh1>;
dr_mode = "host";
disable-over-current;
status = "okay";
+
+ usb2415host: hub@1 {
+ compatible = "usb424,2513";
+ reg = <1>;
+ reset-gpios = <&gpio7 12 GPIO_ACTIVE_LOW>;
+ reset-duration-us = <3000>;
+ };
};
&usbotg {
@@ -471,11 +465,6 @@
MX6QDL_PAD_GPIO_3__USB_H1_OC 0x1b0b0
/* usbh1_b OC */
MX6QDL_PAD_GPIO_0__GPIO1_IO00 0x1b0b0
- >;
- };
-
- pinctrl_usbh1_hubreset: usbh1hubresetgrp {
- fsl,pins = <
MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x1b0b0
>;
};
diff --git a/arch/arm/boot/dts/imx6qdl-udoo.dtsi b/arch/arm/boot/dts/imx6qdl-udoo.dtsi
index c96c91d..a173de2 100644
--- a/arch/arm/boot/dts/imx6qdl-udoo.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-udoo.dtsi
@@ -9,6 +9,8 @@
*
*/
+#include <dt-bindings/gpio/gpio.h>
+
/ {
aliases {
backlight = &backlight;
@@ -58,17 +60,6 @@
#address-cells = <1>;
#size-cells = <0>;
- reg_usb_h1_vbus: regulator@0 {
- compatible = "regulator-fixed";
- reg = <0>;
- regulator-name = "usb_h1_vbus";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- enable-active-high;
- startup-delay-us = <2>; /* USB2415 requires a POR of 1 us minimum */
- gpio = <&gpio7 12 0>;
- };
-
reg_panel: regulator@1 {
compatible = "regulator-fixed";
reg = <1>;
@@ -188,7 +179,7 @@
pinctrl_usbh: usbhgrp {
fsl,pins = <
- MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x80000000
+ MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x1b0b0
MX6QDL_PAD_NANDF_CS2__CCM_CLKO2 0x130b0
>;
};
@@ -259,9 +250,16 @@
&usbh1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usbh>;
- vbus-supply = <®_usb_h1_vbus>;
- clocks = <&clks IMX6QDL_CLK_CKO>;
status = "okay";
+
+ usb2415: hub@1 {
+ compatible = "usb424,2514";
+ reg = <1>;
+
+ clocks = <&clks IMX6QDL_CLK_CKO>;
+ reset-gpios = <&gpio7 12 GPIO_ACTIVE_LOW>;
+ reset-duration-us = <3000>;
+ };
};
&usdhc3 {
diff --git a/arch/arm/boot/dts/imx6qdl-wandboard-revb1.dtsi b/arch/arm/boot/dts/imx6qdl-wandboard-revb1.dtsi
index ef7fa62..b5d0f58 100644
--- a/arch/arm/boot/dts/imx6qdl-wandboard-revb1.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-wandboard-revb1.dtsi
@@ -11,6 +11,24 @@
#include "imx6qdl-wandboard.dtsi"
+/ {
+ rfkill {
+ compatible = "wand,imx6qdl-wandboard-rfkill";
+ pinctrl-names = "default";
+ pinctrl-0 = <>;
+
+ bluetooth-on = <&gpio3 13 0>;
+ bluetooth-wake = <&gpio3 14 0>;
+ bluetooth-host-wake = <&gpio3 15 0>;
+
+ wifi-ref-on = <&gpio2 29 0>;
+ wifi-rst-n = <&gpio5 2 0>;
+ wifi-reg-on = <&gpio1 26 0>;
+ wifi-host-wake = <&gpio1 29 0>;
+ wifi-wake = <&gpio1 30 0>;
+ };
+};
+
&iomuxc {
pinctrl-0 = <&pinctrl_hog>;
@@ -37,6 +55,5 @@
&usdhc2 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc2>;
- non-removable;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6qdl-wandboard-revc1.dtsi b/arch/arm/boot/dts/imx6qdl-wandboard-revc1.dtsi
index 8d893a7..b2097ef 100644
--- a/arch/arm/boot/dts/imx6qdl-wandboard-revc1.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-wandboard-revc1.dtsi
@@ -11,6 +11,24 @@
#include "imx6qdl-wandboard.dtsi"
+/ {
+ rfkill {
+ compatible = "wand,imx6qdl-wandboard-rfkill";
+ pinctrl-names = "default";
+ pinctrl-0 = <>;
+
+ bluetooth-on = <&gpio5 21 0>;
+ bluetooth-wake = <&gpio5 30 0>;
+ bluetooth-host-wake = <&gpio5 20 0>;
+
+ wifi-ref-on = <&gpio5 31 0>; /* Wifi Power Enable */
+ wifi-rst-n = <&gpio6 0 0>; /* WIFI_ON reset */
+ wifi-reg-on = <&gpio1 26 0>; /* WL_REG_ON */
+ wifi-host-wake = <&gpio1 29 0>; /* WL_HOST_WAKE */
+ wifi-wake = <&gpio1 30 0>; /* WL_WAKE */
+ };
+};
+
&iomuxc {
pinctrl-0 = <&pinctrl_hog>;
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index be2e747..b946245 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -935,6 +935,8 @@
usbh1: usb@02184200 {
compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
+ #address-cells = <1>;
+ #size-cells = <0>;
reg = <0x02184200 0x200>;
interrupts = <0 40 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6QDL_CLK_USBOH3>;
@@ -949,6 +951,8 @@
usbh2: usb@02184400 {
compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
+ #address-cells = <1>;
+ #size-cells = <0>;
reg = <0x02184400 0x200>;
interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6QDL_CLK_USBOH3>;
@@ -962,6 +966,8 @@
usbh3: usb@02184600 {
compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
+ #address-cells = <1>;
+ #size-cells = <0>;
reg = <0x02184600 0x200>;
interrupts = <0 42 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6QDL_CLK_USBOH3>;
diff --git b/arch/arm/boot/dts/imx6ul-14x14-evk-ism43362-b81-evb.dts b/arch/arm/boot/dts/imx6ul-14x14-evk-ism43362-b81-evb.dts
new file mode 100644
index 0000000..9ba86b8
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ul-14x14-evk-ism43362-b81-evb.dts
@@ -0,0 +1,516 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/dts-v1/;
+
+#include "imx6ul.dtsi"
+
+/ {
+ model = "Freescale i.MX6 UltraLite 14x14 EVK Board";
+ compatible = "fsl,imx6ul-14x14-evk", "fsl,imx6ul";
+
+ chosen {
+ stdout-path = &uart1;
+ };
+
+ memory {
+ reg = <0x80000000 0x20000000>;
+ };
+
+ backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm1 0 5000000>;
+ brightness-levels = <0 4 8 16 32 64 128 255>;
+ default-brightness-level = <6>;
+ status = "okay";
+ };
+
+ regulators {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg_sd1_vmmc: sd1_regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "VSD_3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ wlreg_on: fixedregulator@100 {
+ compatible = "regulator-fixed";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-name = "wlreg_on";
+ gpio = <&gpio5 1 GPIO_ACTIVE_HIGH>;
+ startup-delay-us = <100>;
+ enable-active-high;
+ };
+ };
+
+ sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "mx6ul-wm8960";
+ simple-audio-card,format = "i2s";
+ simple-audio-card,bitclock-master = <&dailink_master>;
+ simple-audio-card,frame-master = <&dailink_master>;
+ simple-audio-card,widgets =
+ "Microphone", "Mic Jack",
+ "Line", "Line In",
+ "Line", "Line Out",
+ "Speaker", "Speaker",
+ "Headphone", "Headphone Jack";
+ simple-audio-card,routing =
+ "Headphone Jack", "HP_L",
+ "Headphone Jack", "HP_R",
+ "Speaker", "SPK_LP",
+ "Speaker", "SPK_LN",
+ "Speaker", "SPK_RP",
+ "Speaker", "SPK_RN",
+ "LINPUT1", "Mic Jack",
+ "LINPUT3", "Mic Jack",
+ "RINPUT1", "Mic Jack",
+ "RINPUT2", "Mic Jack";
+
+ simple-audio-card,cpu {
+ sound-dai = <&sai2>;
+ };
+
+ dailink_master: simple-audio-card,codec {
+ sound-dai = <&codec>;
+ clocks = <&clks IMX6UL_CLK_SAI2>;
+ };
+ };
+};
+
+&clks {
+ assigned-clocks = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
+ assigned-clock-rates = <786432000>;
+};
+
+&cpu0 {
+ arm-supply = <®_arm>;
+ soc-supply = <®_soc>;
+};
+
+&i2c2 {
+ clock_frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2>;
+ status = "okay";
+
+ codec: wm8960@1a {
+ #sound-dai-cells = <0>;
+ compatible = "wlf,wm8960";
+ reg = <0x1a>;
+ wlf,shared-lrclk;
+ };
+};
+
+&fec1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet1>;
+ phy-mode = "rmii";
+ phy-handle = <ðphy0>;
+ status = "okay";
+};
+
+&fec2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet2>;
+ phy-mode = "rmii";
+ phy-handle = <ðphy1>;
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy0: ethernet-phy@2 {
+ reg = <2>;
+ };
+
+ ethphy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+ };
+};
+
+
+&lcdif {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lcdif_dat
+ &pinctrl_lcdif_ctrl>;
+ display = <&display0>;
+ status = "okay";
+
+ display0: display {
+ bits-per-pixel = <16>;
+ bus-width = <24>;
+
+ display-timings {
+ native-mode = <&timing0>;
+
+ timing0: timing0 {
+ clock-frequency = <9200000>;
+ hactive = <480>;
+ vactive = <272>;
+ hfront-porch = <8>;
+ hback-porch = <4>;
+ hsync-len = <41>;
+ vback-porch = <2>;
+ vfront-porch = <4>;
+ vsync-len = <10>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <0>;
+ };
+ };
+ };
+};
+
+&pwm1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm1>;
+ status = "okay";
+};
+
+&qspi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_qspi>;
+ status = "okay";
+
+ flash0: n25q256a@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "micron,n25q256a";
+ spi-max-frequency = <29000000>;
+ reg = <0>;
+ };
+};
+
+&sai2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sai2>;
+ assigned-clocks = <&clks IMX6UL_CLK_SAI2_SEL>,
+ <&clks IMX6UL_CLK_SAI2>;
+ assigned-clock-parents = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
+ assigned-clock-rates = <0>, <12288000>;
+ fsl,sai-mclk-direction-output;
+ status = "okay";
+};
+
+&snvs_poweroff {
+ status = "okay";
+};
+
+&tsc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_tsc>;
+ xnur-gpio = <&gpio1 3 GPIO_ACTIVE_LOW>;
+ measure-delay-time = <0xffff>;
+ pre-charge-time = <0xfff>;
+ status = "okay";
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ status = "okay";
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2>;
+ uart-has-rtscts;
+ status = "okay";
+};
+
+&usbotg1 {
+ dr_mode = "peripheral";
+ status = "okay";
+};
+
+&usbotg2 {
+ dr_mode = "host";
+ disable-over-current;
+ status = "okay";
+};
+
+®_sd1_vmmc {
+ regulator-always-on;
+};
+
+&usdhc1 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc1>;
+ pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
+ cd-gpios = <&gpio1 19 GPIO_ACTIVE_LOW>;
+ no-1-8-v;
+ keep-power-in-suspend;
+ wakeup-source;
+ vmmc-supply = <®_sd1_vmmc>;
+ status = "okay";
+};
+
+&usdhc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc2>;
+ no-1-8-v;
+ keep-power-in-suspend;
+ wakeup-source;
+ status = "okay";
+};
+
+&wdog1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wdog>;
+ fsl,ext-reset-output;
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+
+ pinctrl_csi1: csi1grp {
+ fsl,pins = <
+ MX6UL_PAD_CSI_MCLK__CSI_MCLK 0x1b088
+ MX6UL_PAD_CSI_PIXCLK__CSI_PIXCLK 0x1b088
+ MX6UL_PAD_CSI_VSYNC__CSI_VSYNC 0x1b088
+ MX6UL_PAD_CSI_HSYNC__CSI_HSYNC 0x1b088
+ MX6UL_PAD_CSI_DATA00__CSI_DATA02 0x1b088
+ MX6UL_PAD_CSI_DATA01__CSI_DATA03 0x1b088
+ MX6UL_PAD_CSI_DATA02__CSI_DATA04 0x1b088
+ MX6UL_PAD_CSI_DATA03__CSI_DATA05 0x1b088
+ MX6UL_PAD_CSI_DATA04__CSI_DATA06 0x1b088
+ MX6UL_PAD_CSI_DATA05__CSI_DATA07 0x1b088
+ MX6UL_PAD_CSI_DATA06__CSI_DATA08 0x1b088
+ MX6UL_PAD_CSI_DATA07__CSI_DATA09 0x1b088
+ >;
+ };
+
+ pinctrl_enet1: enet1grp {
+ fsl,pins = <
+ MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN 0x1b0b0
+ MX6UL_PAD_ENET1_RX_ER__ENET1_RX_ER 0x1b0b0
+ MX6UL_PAD_ENET1_RX_DATA0__ENET1_RDATA00 0x1b0b0
+ MX6UL_PAD_ENET1_RX_DATA1__ENET1_RDATA01 0x1b0b0
+ MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN 0x1b0b0
+ MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00 0x1b0b0
+ MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01 0x1b0b0
+ MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 0x4001b031
+ >;
+ };
+
+ pinctrl_enet2: enet2grp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO07__ENET2_MDC 0x1b0b0
+ MX6UL_PAD_GPIO1_IO06__ENET2_MDIO 0x1b0b0
+ MX6UL_PAD_ENET2_RX_EN__ENET2_RX_EN 0x1b0b0
+ MX6UL_PAD_ENET2_RX_ER__ENET2_RX_ER 0x1b0b0
+ MX6UL_PAD_ENET2_RX_DATA0__ENET2_RDATA00 0x1b0b0
+ MX6UL_PAD_ENET2_RX_DATA1__ENET2_RDATA01 0x1b0b0
+ MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN 0x1b0b0
+ MX6UL_PAD_ENET2_TX_DATA0__ENET2_TDATA00 0x1b0b0
+ MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01 0x1b0b0
+ MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2 0x4001b031
+ MX6UL_PAD_SNVS_TAMPER0__GPIO5_IO00 0x17059
+ >;
+ };
+
+ pinctrl_flexcan1: flexcan1grp{
+ fsl,pins = <
+ MX6UL_PAD_UART3_RTS_B__FLEXCAN1_RX 0x1b020
+ MX6UL_PAD_UART3_CTS_B__FLEXCAN1_TX 0x1b020
+ >;
+ };
+
+ pinctrl_flexcan2: flexcan2grp{
+ fsl,pins = <
+ MX6UL_PAD_UART2_RTS_B__FLEXCAN2_RX 0x1b020
+ MX6UL_PAD_UART2_CTS_B__FLEXCAN2_TX 0x1b020
+ >;
+ };
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX6UL_PAD_UART4_TX_DATA__I2C1_SCL 0x4001b8b0
+ MX6UL_PAD_UART4_RX_DATA__I2C1_SDA 0x4001b8b0
+ >;
+ };
+
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX6UL_PAD_UART5_TX_DATA__I2C2_SCL 0x4001b8b0
+ MX6UL_PAD_UART5_RX_DATA__I2C2_SDA 0x4001b8b0
+ >;
+ };
+
+ pinctrl_lcdif_dat: lcdifdatgrp {
+ fsl,pins = <
+ MX6UL_PAD_LCD_DATA00__LCDIF_DATA00 0x79
+ MX6UL_PAD_LCD_DATA01__LCDIF_DATA01 0x79
+ MX6UL_PAD_LCD_DATA02__LCDIF_DATA02 0x79
+ MX6UL_PAD_LCD_DATA03__LCDIF_DATA03 0x79
+ MX6UL_PAD_LCD_DATA04__LCDIF_DATA04 0x79
+ MX6UL_PAD_LCD_DATA05__LCDIF_DATA05 0x79
+ MX6UL_PAD_LCD_DATA06__LCDIF_DATA06 0x79
+ MX6UL_PAD_LCD_DATA07__LCDIF_DATA07 0x79
+ MX6UL_PAD_LCD_DATA08__LCDIF_DATA08 0x79
+ MX6UL_PAD_LCD_DATA09__LCDIF_DATA09 0x79
+ MX6UL_PAD_LCD_DATA10__LCDIF_DATA10 0x79
+ MX6UL_PAD_LCD_DATA11__LCDIF_DATA11 0x79
+ MX6UL_PAD_LCD_DATA12__LCDIF_DATA12 0x79
+ MX6UL_PAD_LCD_DATA13__LCDIF_DATA13 0x79
+ MX6UL_PAD_LCD_DATA14__LCDIF_DATA14 0x79
+ MX6UL_PAD_LCD_DATA15__LCDIF_DATA15 0x79
+ MX6UL_PAD_LCD_DATA16__LCDIF_DATA16 0x79
+ MX6UL_PAD_LCD_DATA17__LCDIF_DATA17 0x79
+ MX6UL_PAD_LCD_DATA18__LCDIF_DATA18 0x79
+ MX6UL_PAD_LCD_DATA19__LCDIF_DATA19 0x79
+ MX6UL_PAD_LCD_DATA20__LCDIF_DATA20 0x79
+ MX6UL_PAD_LCD_DATA21__LCDIF_DATA21 0x79
+ MX6UL_PAD_LCD_DATA22__LCDIF_DATA22 0x79
+ MX6UL_PAD_LCD_DATA23__LCDIF_DATA23 0x79
+ >;
+ };
+
+ pinctrl_lcdif_ctrl: lcdifctrlgrp {
+ fsl,pins = <
+ MX6UL_PAD_LCD_CLK__LCDIF_CLK 0x79
+ MX6UL_PAD_LCD_ENABLE__LCDIF_ENABLE 0x79
+ MX6UL_PAD_LCD_HSYNC__LCDIF_HSYNC 0x79
+ MX6UL_PAD_LCD_VSYNC__LCDIF_VSYNC 0x79
+ /* used for lcd reset */
+ MX6UL_PAD_SNVS_TAMPER9__GPIO5_IO09 0x79
+ >;
+ };
+
+ pinctrl_qspi: qspigrp {
+ fsl,pins = <
+ MX6UL_PAD_NAND_WP_B__QSPI_A_SCLK 0x70a1
+ MX6UL_PAD_NAND_READY_B__QSPI_A_DATA00 0x70a1
+ MX6UL_PAD_NAND_CE0_B__QSPI_A_DATA01 0x70a1
+ MX6UL_PAD_NAND_CE1_B__QSPI_A_DATA02 0x70a1
+ MX6UL_PAD_NAND_CLE__QSPI_A_DATA03 0x70a1
+ MX6UL_PAD_NAND_DQS__QSPI_A_SS0_B 0x70a1
+ >;
+ };
+
+ pinctrl_sai2: sai2grp {
+ fsl,pins = <
+ MX6UL_PAD_JTAG_TDI__SAI2_TX_BCLK 0x17088
+ MX6UL_PAD_JTAG_TDO__SAI2_TX_SYNC 0x17088
+ MX6UL_PAD_JTAG_TRST_B__SAI2_TX_DATA 0x11088
+ MX6UL_PAD_JTAG_TCK__SAI2_RX_DATA 0x11088
+ MX6UL_PAD_JTAG_TMS__SAI2_MCLK 0x17088
+ MX6UL_PAD_SNVS_TAMPER4__GPIO5_IO04 0x17059
+ >;
+ };
+
+ pinctrl_pwm1: pwm1grp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO08__PWM1_OUT 0x110b0
+ >;
+ };
+
+ pinctrl_sim2: sim2grp {
+ fsl,pins = <
+ MX6UL_PAD_CSI_DATA03__SIM2_PORT1_PD 0xb808
+ MX6UL_PAD_CSI_DATA04__SIM2_PORT1_CLK 0x31
+ MX6UL_PAD_CSI_DATA05__SIM2_PORT1_RST_B 0xb808
+ MX6UL_PAD_CSI_DATA06__SIM2_PORT1_SVEN 0xb808
+ MX6UL_PAD_CSI_DATA07__SIM2_PORT1_TRXD 0xb809
+ MX6UL_PAD_CSI_DATA02__GPIO4_IO23 0x3008
+ >;
+ };
+
+ pinctrl_tsc: tscgrp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO01__GPIO1_IO01 0xb0
+ MX6UL_PAD_GPIO1_IO02__GPIO1_IO02 0xb0
+ MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 0xb0
+ MX6UL_PAD_GPIO1_IO04__GPIO1_IO04 0xb0
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX 0x1b0b1
+ MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX6UL_PAD_UART2_TX_DATA__UART2_DCE_TX 0x1b0b1
+ MX6UL_PAD_UART2_RX_DATA__UART2_DCE_RX 0x1b0b1
+ MX6UL_PAD_UART3_RX_DATA__UART2_DCE_RTS 0x1b0b1
+ MX6UL_PAD_UART3_TX_DATA__UART2_DCE_CTS 0x1b0b1
+ >;
+ };
+
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x17059
+ MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x10071
+ MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x17059
+ MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x17059
+ MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x17059
+ MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x17059
+ MX6UL_PAD_UART1_RTS_B__GPIO1_IO19 0x17059 /* SD1 CD */
+ MX6UL_PAD_GPIO1_IO05__USDHC1_VSELECT 0x17059 /* SD1 VSELECT */
+ MX6UL_PAD_GPIO1_IO09__GPIO1_IO09 0x17059 /* SD1 RESET */
+ MX6UL_PAD_SNVS_TAMPER1__GPIO5_IO01 0x3029
+ >;
+ };
+
+ pinctrl_usdhc1_100mhz: usdhc1grp100mhz {
+ fsl,pins = <
+ MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x170b9
+ MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x100b9
+ MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x170b9
+ MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x170b9
+ MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x170b9
+ MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x170b9
+ MX6UL_PAD_SNVS_TAMPER1__GPIO5_IO01 0x3029
+ >;
+ };
+
+ pinctrl_usdhc1_200mhz: usdhc1grp200mhz {
+ fsl,pins = <
+ MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x170f9
+ MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x100f9
+ MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x170f9
+ MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x170f9
+ MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x170f9
+ MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x170f9
+ MX6UL_PAD_SNVS_TAMPER1__GPIO5_IO01 0x3029
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x17059
+ MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x17059
+ MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x17059
+ MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x17059
+ MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x17059
+ MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x17059
+ >;
+ };
+
+ pinctrl_wdog: wdoggrp {
+ fsl,pins = <
+ MX6UL_PAD_LCD_RESET__WDOG1_WDOG_ANY 0x30b0
+ >;
+ };
+};
diff --git a/arch/arm/boot/dts/omap3-beagle-xm.dts b/arch/arm/boot/dts/omap3-beagle-xm.dts
index 85e297e..226b833 100644
--- a/arch/arm/boot/dts/omap3-beagle-xm.dts
+++ b/arch/arm/boot/dts/omap3-beagle-xm.dts
@@ -27,6 +27,7 @@
aliases {
display0 = &dvi0;
display1 = &tv0;
+ ethernet = ðernet;
};
leds {
@@ -146,6 +147,7 @@
};
etb@5401b000 {
+ status = "disabled";
compatible = "arm,coresight-etb10", "arm,primecell";
reg = <0x5401b000 0x1000>;
@@ -160,6 +162,7 @@
};
etm@54010000 {
+ status = "disabled";
compatible = "arm,coresight-etm3x", "arm,primecell";
reg = <0x54010000 0x1000>;
@@ -205,6 +208,25 @@
>;
};
+ spi3_pins: pinmux_spi3_pins {
+ pinctrl-single,pins = <
+ 0x128 (PIN_INPUT | MUX_MODE1) /* sdmmc2_clk.mcspi3_clk gpio_130 */
+ 0x12a (PIN_OUTPUT | MUX_MODE1) /* sdmmc2_cmd.mcspi3_simo gpio_131 */
+ 0x12c (PIN_INPUT_PULLUP | MUX_MODE1) /* sdmmc2_dat0.mcspi3_somi gpio_132 */
+ 0x130 (PIN_OUTPUT | MUX_MODE1) /* sdmmc2_dat2.mcspi3_cs1 gpio_134 */
+ 0x132 (PIN_OUTPUT | MUX_MODE1) /* sdmmc2_dat3.mcspi3_cs0 gpio_135 */
+ >;
+ };
+
+ spi4_pins: pinmux_spi4_pins {
+ pinctrl-single,pins = <
+ 0x15c (PIN_INPUT | MUX_MODE1) /* mcbsp1_clkr.mcspi4_clk gpio_156 */
+ 0x160 (PIN_OUTPUT | MUX_MODE1) /* mcbsp1_dx.mcspi4_simo gpio_158 */
+ 0x162 (PIN_INPUT_PULLUP | MUX_MODE1) /* mcbsp1_dr.mcspi4_somi gpio_159 */
+ 0x166 (PIN_OUTPUT | MUX_MODE1) /* mcbsp1_fsx.mcspi4_cs0 gpio_161 */
+ >;
+ };
+
hsusb2_pins: pinmux_hsusb2_pins {
pinctrl-single,pins = <
OMAP3_CORE1_IOPAD(0x21d4, PIN_INPUT_PULLDOWN | MUX_MODE3) /* mcspi1_cs3.hsusb2_data2 */
@@ -279,7 +301,7 @@
};
twl_power: power {
- compatible = "ti,twl4030-power-beagleboard-xm", "ti,twl4030-power-idle-osc-off";
+ compatible = "ti,twl4030-power-reset";
ti,use_poweroff;
};
};
@@ -310,6 +332,36 @@
status = "disabled";
};
+&mcspi3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi3_pins>;
+ status = "okay";
+
+ spidev0: spi@0 {
+ compatible = "spidev";
+ reg = <0>;
+ spi-max-frequency = <48000000>;
+ };
+
+ spidev1: spi@1 {
+ compatible = "spidev";
+ reg = <1>;
+ spi-max-frequency = <48000000>;
+ };
+};
+
+&mcspi4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi4_pins>;
+ status = "okay";
+
+ spidev2: spi@0 {
+ compatible = "spidev";
+ reg = <0>;
+ spi-max-frequency = <48000000>;
+ };
+};
+
&twl_gpio {
ti,use-leds;
/* pullups: BIT(1) */
@@ -348,6 +400,21 @@
&usbhsehci {
phys = <0 &hsusb2_phy>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ hub@2 {
+ compatible = "usb424,9514";
+ reg = <2>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethernet: usbether@1 {
+ compatible = "usb424,ec00";
+ reg = <1>;
+ };
+ };
};
&vaux2 {
diff --git a/arch/arm/boot/dts/omap3-beagle.dts b/arch/arm/boot/dts/omap3-beagle.dts
index 4be85ce..049b5e1 100644
--- a/arch/arm/boot/dts/omap3-beagle.dts
+++ b/arch/arm/boot/dts/omap3-beagle.dts
@@ -141,6 +141,7 @@
};
etb@540000000 {
+ status = "disabled";
compatible = "arm,coresight-etb10", "arm,primecell";
reg = <0x5401b000 0x1000>;
@@ -155,6 +156,7 @@
};
etm@54010000 {
+ status = "disabled";
compatible = "arm,coresight-etm3x", "arm,primecell";
reg = <0x54010000 0x1000>;
@@ -271,9 +273,18 @@
codec {
};
};
+
+ twl_power: power {
+ compatible = "ti,twl4030-power-reset";
+ ti,use_poweroff;
+ };
};
};
+&i2c2 {
+ clock-frequency = <400000>;
+};
+
#include "twl4030.dtsi"
#include "twl4030_omap3.dtsi"
diff --git a/arch/arm/boot/dts/omap4-panda-a4.dts b/arch/arm/boot/dts/omap4-panda-a4.dts
index 78d3631..67ee5b4 100644
--- a/arch/arm/boot/dts/omap4-panda-a4.dts
+++ b/arch/arm/boot/dts/omap4-panda-a4.dts
@@ -10,6 +10,18 @@
#include "omap443x.dtsi"
#include "omap4-panda-common.dtsi"
+&emif1 {
+ cs1-used;
+ device-handle = <&elpida_ECB240ABACN>;
+ status = "ok";
+};
+
+&emif2 {
+ cs1-used;
+ device-handle = <&elpida_ECB240ABACN>;
+ status = "ok";
+};
+
/* Pandaboard Rev A4+ have external pullups on SCL & SDA */
&dss_hdmi_pins {
pinctrl-single,pins = <
diff --git a/arch/arm/boot/dts/omap4-panda-common.dtsi b/arch/arm/boot/dts/omap4-panda-common.dtsi
index 1673689..c6b90f0 100644
--- a/arch/arm/boot/dts/omap4-panda-common.dtsi
+++ b/arch/arm/boot/dts/omap4-panda-common.dtsi
@@ -463,16 +463,6 @@
};
};
-&emif1 {
- cs1-used;
- device-handle = <&elpida_ECB240ABACN>;
-};
-
-&emif2 {
- cs1-used;
- device-handle = <&elpida_ECB240ABACN>;
-};
-
&mcbsp1 {
pinctrl-names = "default";
pinctrl-0 = <&mcbsp1_pins>;
diff --git b/arch/arm/boot/dts/omap4-panda-es-b3.dts b/arch/arm/boot/dts/omap4-panda-es-b3.dts
new file mode 100644
index 0000000..2f1dabc
--- /dev/null
+++ b/arch/arm/boot/dts/omap4-panda-es-b3.dts
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "omap4460.dtsi"
+#include "omap4-panda-common.dtsi"
+
+/ {
+ model = "TI OMAP4 PandaBoard-ES";
+ compatible = "ti,omap4-panda-es", "ti,omap4-panda", "ti,omap4460", "ti,omap4430", "ti,omap4";
+};
+
+/* Audio routing is differnet between PandaBoard4430 and PandaBoardES */
+&sound {
+ ti,model = "PandaBoardES";
+
+ /* Audio routing */
+ ti,audio-routing =
+ "Headset Stereophone", "HSOL",
+ "Headset Stereophone", "HSOR",
+ "Ext Spk", "HFL",
+ "Ext Spk", "HFR",
+ "Line Out", "AUXL",
+ "Line Out", "AUXR",
+ "AFML", "Line In",
+ "AFMR", "Line In";
+};
+
+/* PandaboardES has external pullups on SCL & SDA */
+&dss_hdmi_pins {
+ pinctrl-single,pins = <
+ 0x5a (PIN_INPUT_PULLUP | MUX_MODE0) /* hdmi_cec.hdmi_cec */
+ 0x5c (PIN_INPUT | MUX_MODE0) /* hdmi_scl.hdmi_scl */
+ 0x5e (PIN_INPUT | MUX_MODE0) /* hdmi_sda.hdmi_sda */
+ >;
+};
+
+&omap4_pmx_core {
+ led_gpio_pins: gpio_led_pmx {
+ pinctrl-single,pins = <
+ 0xb6 (PIN_OUTPUT | MUX_MODE3) /* gpio_110 */
+ >;
+ };
+};
+
+&led_wkgpio_pins {
+ pinctrl-single,pins = <
+ 0x1c (PIN_OUTPUT | MUX_MODE3) /* gpio_wk8 */
+ >;
+};
+
+&leds {
+ pinctrl-0 = <
+ &led_gpio_pins
+ &led_wkgpio_pins
+ >;
+
+ heartbeat {
+ gpios = <&gpio4 14 GPIO_ACTIVE_HIGH>;
+ };
+ mmc {
+ gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>;
+ };
+};
+
+&gpio1 {
+ ti,no-reset-on-init;
+};
diff --git a/arch/arm/boot/dts/omap4-panda-es.dts b/arch/arm/boot/dts/omap4-panda-es.dts
index 119f8e6..5c54ccf 100644
--- a/arch/arm/boot/dts/omap4-panda-es.dts
+++ b/arch/arm/boot/dts/omap4-panda-es.dts
@@ -15,6 +15,18 @@
compatible = "ti,omap4-panda-es", "ti,omap4-panda", "ti,omap4460", "ti,omap4430", "ti,omap4";
};
+&emif1 {
+ cs1-used;
+ device-handle = <&elpida_ECB240ABACN>;
+ status = "ok";
+};
+
+&emif2 {
+ cs1-used;
+ device-handle = <&elpida_ECB240ABACN>;
+ status = "ok";
+};
+
/* Audio routing is differnet between PandaBoard4430 and PandaBoardES */
&sound {
ti,model = "PandaBoardES";
diff --git a/arch/arm/boot/dts/omap4-panda.dts b/arch/arm/boot/dts/omap4-panda.dts
index a0e28b2..3ee41ef 100644
--- a/arch/arm/boot/dts/omap4-panda.dts
+++ b/arch/arm/boot/dts/omap4-panda.dts
@@ -14,3 +14,15 @@
model = "TI OMAP4 PandaBoard";
compatible = "ti,omap4-panda", "ti,omap4430", "ti,omap4";
};
+
+&emif1 {
+ cs1-used;
+ device-handle = <&elpida_ECB240ABACN>;
+ status = "ok";
+};
+
+&emif2 {
+ cs1-used;
+ device-handle = <&elpida_ECB240ABACN>;
+ status = "ok";
+};
diff --git a/arch/arm/boot/dts/omap4-sdp.dts b/arch/arm/boot/dts/omap4-sdp.dts
index d728ec9..fb2cda4 100644
--- a/arch/arm/boot/dts/omap4-sdp.dts
+++ b/arch/arm/boot/dts/omap4-sdp.dts
@@ -502,11 +502,13 @@
&emif1 {
cs1-used;
device-handle = <&elpida_ECB240ABACN>;
+ status = "ok";
};
&emif2 {
cs1-used;
device-handle = <&elpida_ECB240ABACN>;
+ status = "ok";
};
&keypad {
diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi
index 9c289dd..ea0b76b 100644
--- a/arch/arm/boot/dts/omap4.dtsi
+++ b/arch/arm/boot/dts/omap4.dtsi
@@ -696,6 +696,7 @@
hw-caps-read-idle-ctrl;
hw-caps-ll-interface;
hw-caps-temp-alert;
+ status = "disabled";
};
emif2: emif@4d000000 {
@@ -708,6 +709,7 @@
hw-caps-read-idle-ctrl;
hw-caps-ll-interface;
hw-caps-temp-alert;
+ status = "disabled";
};
ocp2scp@4a0ad000 {
diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts
index 5c9b5bf..7c9335d 100644
--- a/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts
+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts
@@ -94,6 +94,17 @@
status = "okay";
};
+&emac {
+ phy = <&phy1>;
+ phy-mode = "mii";
+ allwinner,use-internal-phy;
+ allwinner,leds-active-low;
+ status = "okay";
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+};
+
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts
index 3ec9712..21acd8a 100644
--- a/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts
+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts
@@ -183,3 +183,14 @@
/* USB VBUS is always on */
status = "okay";
};
+
+&emac {
+ phy = <&phy1>;
+ phy-mode = "mii";
+ allwinner,use-internal-phy;
+ allwinner,leds-active-low;
+ status = "okay";
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+};
diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi
index f4ba088..43c4a5c 100644
--- a/arch/arm/boot/dts/sun8i-h3.dtsi
+++ b/arch/arm/boot/dts/sun8i-h3.dtsi
@@ -50,6 +50,10 @@
/ {
interrupt-parent = <&gic>;
+ aliases {
+ ethernet0 = &emac;
+ };
+
cpus {
#address-cells = <1>;
#size-cells = <0>;
@@ -530,6 +534,20 @@
#size-cells = <0>;
};
+ emac: ethernet@1c30000 {
+ compatible = "allwinner,sun8i-h3-emac";
+ reg = <0x01c30000 0x104>, <0x01c00030 0x4>;
+ reg-names = "emac", "syscon";
+ interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
+ resets = <&ccu RST_BUS_EMAC>, <&ccu RST_BUS_EPHY>;
+ reset-names = "ahb", "ephy";
+ clocks = <&ccu CLK_BUS_EMAC>, <&ccu CLK_BUS_EPHY>;
+ clock-names = "ahb", "ephy";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
gic: interrupt-controller@01c81000 {
compatible = "arm,cortex-a7-gic", "arm,cortex-a15-gic";
reg = <0x01c81000 0x1000>,
diff --git a/arch/arm/boot/dts/tps65217.dtsi b/arch/arm/boot/dts/tps65217.dtsi
index a632724..02de56b 100644
--- a/arch/arm/boot/dts/tps65217.dtsi
+++ b/arch/arm/boot/dts/tps65217.dtsi
@@ -13,6 +13,18 @@
&tps {
compatible = "ti,tps65217";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ charger {
+ compatible = "ti,tps65217-charger";
+ status = "disabled";
+ };
+
+ pwrbutton {
+ compatible = "ti,tps65217-pwrbutton";
+ status = "disabled";
+ };
regulators {
#address-cells = <1>;
diff --git a/arch/arm/mach-imx/devices/Kconfig b/arch/arm/mach-imx/devices/Kconfig
index 6ffe572..bb7bd88 100644
--- a/arch/arm/mach-imx/devices/Kconfig
+++ b/arch/arm/mach-imx/devices/Kconfig
@@ -68,3 +68,9 @@ config IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
config IMX_HAVE_PLATFORM_SPI_IMX
bool
+
+config WAND_RFKILL
+ tristate "Wandboard RF Kill support"
+ depends on SOC_IMX6Q
+ default m
+ select RFKILL
diff --git a/arch/arm/mach-imx/devices/Makefile b/arch/arm/mach-imx/devices/Makefile
index aa6cee8..800ce9b 100644
--- a/arch/arm/mach-imx/devices/Makefile
+++ b/arch/arm/mach-imx/devices/Makefile
@@ -25,3 +25,4 @@ obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_W1) += platform-mxc_w1.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX) += platform-sdhci-esdhc-imx.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_SPI_IMX) += platform-spi_imx.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_MX2_EMMA) += platform-mx2-emma.o
+obj-$(CONFIG_WAND_RFKILL) += wand-rfkill.o
diff --git b/arch/arm/mach-imx/devices/wand-rfkill.c b/arch/arm/mach-imx/devices/wand-rfkill.c
new file mode 100644
index 0000000..da7ef9f
--- /dev/null
+++ b/arch/arm/mach-imx/devices/wand-rfkill.c
@@ -0,0 +1,290 @@
+/*
+ * arch/arm/mach-imx/devices/wand-rfkill.c
+ *
+ * Copyright (C) 2013 Vladimir Ermakov <vooon341@gmail.com>
+ *
+ * based on net/rfkill/rfkill-gpio.c
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/platform_device.h>
+#include <linux/rfkill.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+
+struct wand_rfkill_data {
+ struct rfkill *rfkill_dev;
+ int shutdown_gpio;
+ const char *shutdown_name;
+};
+
+static int wand_rfkill_set_block(void *data, bool blocked)
+{
+ struct wand_rfkill_data *rfkill = data;
+
+ pr_debug("wandboard-rfkill: set block %d\n", blocked);
+
+ if (blocked) {
+ if (gpio_is_valid(rfkill->shutdown_gpio))
+ gpio_direction_output(rfkill->shutdown_gpio, 0);
+ } else {
+ if (gpio_is_valid(rfkill->shutdown_gpio))
+ gpio_direction_output(rfkill->shutdown_gpio, 1);
+ }
+
+ return 0;
+}
+
+static const struct rfkill_ops wand_rfkill_ops = {
+ .set_block = wand_rfkill_set_block,
+};
+
+static int wand_rfkill_wifi_probe(struct device *dev,
+ struct device_node *np,
+ struct wand_rfkill_data *rfkill)
+{
+ int ret;
+ int wl_ref_on, wl_rst_n, wl_reg_on, wl_wake, wl_host_wake;
+
+ wl_ref_on = of_get_named_gpio(np, "wifi-ref-on", 0);
+ wl_rst_n = of_get_named_gpio(np, "wifi-rst-n", 0);
+ wl_reg_on = of_get_named_gpio(np, "wifi-reg-on", 0);
+ wl_wake = of_get_named_gpio(np, "wifi-wake", 0);
+ wl_host_wake = of_get_named_gpio(np, "wifi-host-wake", 0);
+
+ if (!gpio_is_valid(wl_rst_n) || !gpio_is_valid(wl_ref_on) ||
+ !gpio_is_valid(wl_reg_on) || !gpio_is_valid(wl_wake) ||
+ !gpio_is_valid(wl_host_wake)) {
+
+ dev_err(dev, "incorrect wifi gpios (%d %d %d %d %d)\n",
+ wl_rst_n, wl_ref_on, wl_reg_on, wl_wake, wl_host_wake);
+ return -EINVAL;
+ }
+
+ dev_info(dev, "initialize wifi chip\n");
+
+ gpio_request(wl_rst_n, "wl_rst_n");
+ gpio_direction_output(wl_rst_n, 0);
+ msleep(11);
+ gpio_set_value(wl_rst_n, 1);
+
+ gpio_request(wl_ref_on, "wl_ref_on");
+ gpio_direction_output(wl_ref_on, 1);
+
+ gpio_request(wl_reg_on, "wl_reg_on");
+ gpio_direction_output(wl_reg_on, 1);
+
+ gpio_request(wl_wake, "wl_wake");
+ gpio_direction_output(wl_wake, 1);
+
+ gpio_request(wl_host_wake, "wl_host_wake");
+ gpio_direction_input(wl_host_wake);
+
+ rfkill->shutdown_name = "wifi_shutdown";
+ rfkill->shutdown_gpio = wl_wake;
+
+ rfkill->rfkill_dev = rfkill_alloc("wifi-rfkill", dev, RFKILL_TYPE_WLAN,
+ &wand_rfkill_ops, rfkill);
+ if (!rfkill->rfkill_dev) {
+ ret = -ENOMEM;
+ goto wifi_fail_free_gpio;
+ }
+
+ ret = rfkill_register(rfkill->rfkill_dev);
+ if (ret < 0)
+ goto wifi_fail_unregister;
+
+ dev_info(dev, "wifi-rfkill registered.\n");
+
+ return 0;
+
+wifi_fail_unregister:
+ rfkill_destroy(rfkill->rfkill_dev);
+wifi_fail_free_gpio:
+ if (gpio_is_valid(wl_rst_n)) gpio_free(wl_rst_n);
+ if (gpio_is_valid(wl_ref_on)) gpio_free(wl_ref_on);
+ if (gpio_is_valid(wl_reg_on)) gpio_free(wl_reg_on);
+ if (gpio_is_valid(wl_wake)) gpio_free(wl_wake);
+ if (gpio_is_valid(wl_host_wake)) gpio_free(wl_host_wake);
+
+ return ret;
+}
+
+static int wand_rfkill_bt_probe(struct device *dev,
+ struct device_node *np,
+ struct wand_rfkill_data *rfkill)
+{
+ int ret;
+ int bt_on, bt_wake, bt_host_wake;
+
+ bt_on = of_get_named_gpio(np, "bluetooth-on", 0);
+ bt_wake = of_get_named_gpio(np, "bluetooth-wake", 0);
+ bt_host_wake = of_get_named_gpio(np, "bluetooth-host-wake", 0);
+
+ if (!gpio_is_valid(bt_on) || !gpio_is_valid(bt_wake) ||
+ !gpio_is_valid(bt_host_wake)) {
+
+ dev_err(dev, "incorrect bt gpios (%d %d %d)\n",
+ bt_on, bt_wake, bt_host_wake);
+ return -EINVAL;
+ }
+
+ dev_info(dev, "initialize bluetooth chip\n");
+
+ gpio_request(bt_on, "bt_on");
+ gpio_direction_output(bt_on, 0);
+ msleep(11);
+ gpio_set_value(bt_on, 1);
+
+ gpio_request(bt_wake, "bt_wake");
+ gpio_direction_output(bt_wake, 1);
+
+ gpio_request(bt_host_wake, "bt_host_wake");
+ gpio_direction_input(bt_host_wake);
+
+ rfkill->shutdown_name = "bluetooth_shutdown";
+ rfkill->shutdown_gpio = bt_wake;
+
+ rfkill->rfkill_dev = rfkill_alloc("bluetooth-rfkill", dev, RFKILL_TYPE_BLUETOOTH,
+ &wand_rfkill_ops, rfkill);
+ if (!rfkill->rfkill_dev) {
+ ret = -ENOMEM;
+ goto bt_fail_free_gpio;
+ }
+
+ ret = rfkill_register(rfkill->rfkill_dev);
+ if (ret < 0)
+ goto bt_fail_unregister;
+
+ dev_info(dev, "bluetooth-rfkill registered.\n");
+
+ return 0;
+
+bt_fail_unregister:
+ rfkill_destroy(rfkill->rfkill_dev);
+bt_fail_free_gpio:
+ if (gpio_is_valid(bt_on)) gpio_free(bt_on);
+ if (gpio_is_valid(bt_wake)) gpio_free(bt_wake);
+ if (gpio_is_valid(bt_host_wake)) gpio_free(bt_host_wake);
+
+ return ret;
+}
+
+static int wand_rfkill_probe(struct platform_device *pdev)
+{
+ struct wand_rfkill_data *rfkill;
+ struct pinctrl *pinctrl;
+ int ret;
+
+ dev_info(&pdev->dev, "Wandboard rfkill initialization\n");
+
+ if (!pdev->dev.of_node) {
+ dev_err(&pdev->dev, "no device tree node\n");
+ return -ENODEV;
+ }
+
+ rfkill = kzalloc(sizeof(*rfkill) * 2, GFP_KERNEL);
+ if (!rfkill)
+ return -ENOMEM;
+
+ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+ if (IS_ERR(pinctrl)) {
+ int ret = PTR_ERR(pinctrl);
+ dev_err(&pdev->dev, "failed to get default pinctrl: %d\n", ret);
+ return ret;
+ }
+
+ /* setup WiFi */
+ ret = wand_rfkill_wifi_probe(&pdev->dev, pdev->dev.of_node, &rfkill[0]);
+ if (ret < 0)
+ goto fail_free_rfkill;
+
+ /* setup bluetooth */
+ ret = wand_rfkill_bt_probe(&pdev->dev, pdev->dev.of_node, &rfkill[1]);
+ if (ret < 0)
+ goto fail_unregister_wifi;
+
+ platform_set_drvdata(pdev, rfkill);
+
+ return 0;
+
+fail_unregister_wifi:
+ if (rfkill[1].rfkill_dev) {
+ rfkill_unregister(rfkill[1].rfkill_dev);
+ rfkill_destroy(rfkill[1].rfkill_dev);
+ }
+
+ /* TODO free gpio */
+
+fail_free_rfkill:
+ kfree(rfkill);
+
+ return ret;
+}
+
+static int wand_rfkill_remove(struct platform_device *pdev)
+{
+ struct wand_rfkill_data *rfkill = platform_get_drvdata(pdev);
+
+ dev_info(&pdev->dev, "Module unloading\n");
+
+ if (!rfkill)
+ return 0;
+
+ /* WiFi */
+ if (gpio_is_valid(rfkill[0].shutdown_gpio))
+ gpio_free(rfkill[0].shutdown_gpio);
+
+ rfkill_unregister(rfkill[0].rfkill_dev);
+ rfkill_destroy(rfkill[0].rfkill_dev);
+
+ /* Bt */
+ if (gpio_is_valid(rfkill[1].shutdown_gpio))
+ gpio_free(rfkill[1].shutdown_gpio);
+
+ rfkill_unregister(rfkill[1].rfkill_dev);
+ rfkill_destroy(rfkill[1].rfkill_dev);
+
+ kfree(rfkill);
+
+ return 0;
+}
+
+static struct of_device_id wand_rfkill_match[] = {
+ { .compatible = "wand,imx6q-wandboard-rfkill", },
+ { .compatible = "wand,imx6dl-wandboard-rfkill", },
+ { .compatible = "wand,imx6qdl-wandboard-rfkill", },
+ {}
+};
+
+static struct platform_driver wand_rfkill_driver = {
+ .driver = {
+ .name = "wandboard-rfkill",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(wand_rfkill_match),
+ },
+ .probe = wand_rfkill_probe,
+ .remove = wand_rfkill_remove
+};
+
+module_platform_driver(wand_rfkill_driver);
+
+MODULE_AUTHOR("Vladimir Ermakov <vooon341@gmail.com>");
+MODULE_DESCRIPTION("Wandboard rfkill driver");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c
index e920dd8..f5eff35 100644
--- a/arch/arm/mach-omap2/omap_device.c
+++ b/arch/arm/mach-omap2/omap_device.c
@@ -138,8 +138,8 @@ static int omap_device_build_from_dt(struct platform_device *pdev)
struct omap_device *od;
struct omap_hwmod *oh;
struct device_node *node = pdev->dev.of_node;
- const char *oh_name;
- int oh_cnt, i, ret = 0;
+ const char *oh_name, *rst_name;
+ int oh_cnt, dstr_cnt, i, ret = 0;
bool device_active = false;
oh_cnt = of_property_count_strings(node, "ti,hwmods");
@@ -190,6 +190,26 @@ static int omap_device_build_from_dt(struct platform_device *pdev)
omap_device_enable(pdev);
pm_runtime_set_active(&pdev->dev);
}
+ dstr_cnt =
+ of_property_count_strings(node, "ti,deassert-hard-reset");
+ if (dstr_cnt > 0) {
+ for (i = 0; i < dstr_cnt; i += 2) {
+ of_property_read_string_index(
+ node, "ti,deassert-hard-reset", i,
+ &oh_name);
+ of_property_read_string_index(
+ node, "ti,deassert-hard-reset", i+1,
+ &rst_name);
+ oh = omap_hwmod_lookup(oh_name);
+ if (!oh) {
+ dev_warn(&pdev->dev,
+ "Cannot parse deassert property for '%s'\n",
+ oh_name);
+ break;
+ }
+ omap_hwmod_deassert_hardreset(oh, rst_name);
+ }
+ }
odbfd_exit1:
kfree(hwmods);
@@ -206,12 +226,21 @@ static int _omap_device_notifier_call(struct notifier_block *nb,
{
struct platform_device *pdev = to_platform_device(dev);
struct omap_device *od;
- int err;
+ int i, err;
switch (event) {
case BUS_NOTIFY_REMOVED_DEVICE:
- if (pdev->archdata.od)
- omap_device_delete(pdev->archdata.od);
+ od = to_omap_device(pdev);
+ if (!od)
+ break;
+
+ for (i = 0; i < od->hwmods_cnt; i++) {
+ /* shutdown hwmods */
+ omap_hwmod_shutdown(od->hwmods[i]);
+ /* we don't remove clocks cause there's no API to do so */
+ /* no harm done, since they will not be created next time */
+ }
+ omap_device_delete(od);
break;
case BUS_NOTIFY_UNBOUND_DRIVER:
od = to_omap_device(pdev);
@@ -785,6 +814,8 @@ int omap_device_idle(struct platform_device *pdev)
struct omap_device *od;
od = to_omap_device(pdev);
+ if (!od)
+ return 0;
if (od->_state != OMAP_DEVICE_STATE_ENABLED) {
dev_warn(&pdev->dev,
diff --git a/drivers/base/power/opp/core.c b/drivers/base/power/opp/core.c
index 6441dfd..f7a5fb4 100644
--- a/drivers/base/power/opp/core.c
+++ b/drivers/base/power/opp/core.c
@@ -93,6 +93,8 @@ struct opp_table *_find_opp_table(struct device *dev)
* Return: voltage in micro volt corresponding to the opp, else
* return 0
*
+ * This is useful only for devices with single power supply.
+ *
* Locking: This function must be called under rcu_read_lock(). opp is a rcu
* protected pointer. This means that opp which could have been fetched by
* opp_find_freq_{exact,ceil,floor} functions is valid as long as we are
@@ -112,7 +114,7 @@ unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp)
if (IS_ERR_OR_NULL(tmp_opp))
pr_err("%s: Invalid parameters\n", __func__);
else
- v = tmp_opp->u_volt;
+ v = tmp_opp->supplies[0].u_volt;
return v;
}
@@ -210,6 +212,24 @@ unsigned long dev_pm_opp_get_max_clock_latency(struct device *dev)
}
EXPORT_SYMBOL_GPL(dev_pm_opp_get_max_clock_latency);
+static int _get_regulator_count(struct device *dev)
+{
+ struct opp_table *opp_table;
+ int count;
+
+ rcu_read_lock();
+
+ opp_table = _find_opp_table(dev);
+ if (!IS_ERR(opp_table))
+ count = opp_table->regulator_count;
+ else
+ count = 0;
+
+ rcu_read_unlock();
+
+ return count;
+}
+
/**
* dev_pm_opp_get_max_volt_latency() - Get max voltage latency in nanoseconds
* @dev: device for which we do this operation
@@ -222,34 +242,51 @@ unsigned long dev_pm_opp_get_max_volt_latency(struct device *dev)
{
struct opp_table *opp_table;
struct dev_pm_opp *opp;
- struct regulator *reg;
+ struct regulator *reg, **regulators;
unsigned long latency_ns = 0;
- unsigned long min_uV = ~0, max_uV = 0;
- int ret;
+ int ret, i, count;
+ struct {
+ unsigned long min;
+ unsigned long max;
+ } *uV;
+
+ count = _get_regulator_count(dev);
+
+ /* Regulator may not be required for the device */
+ if (!count)
+ return 0;
+
+ regulators = kmalloc_array(count, sizeof(*regulators), GFP_KERNEL);
+ if (!regulators)
+ return 0;
+
+ uV = kmalloc_array(count, sizeof(*uV), GFP_KERNEL);
+ if (!uV)
+ goto free_regulators;
rcu_read_lock();
opp_table = _find_opp_table(dev);
if (IS_ERR(opp_table)) {
rcu_read_unlock();
- return 0;
+ goto free_uV;
}
- reg = opp_table->regulator;
- if (IS_ERR(reg)) {
- /* Regulator may not be required for device */
- rcu_read_unlock();
- return 0;
- }
+ memcpy(regulators, opp_table->regulators, count * sizeof(*regulators));
- list_for_each_entry_rcu(opp, &opp_table->opp_list, node) {
- if (!opp->available)
- continue;
+ for (i = 0; i < count; i++) {
+ uV[i].min = ~0;
+ uV[i].max = 0;
- if (opp->u_volt_min < min_uV)
- min_uV = opp->u_volt_min;
- if (opp->u_volt_max > max_uV)
- max_uV = opp->u_volt_max;
+ list_for_each_entry_rcu(opp, &opp_table->opp_list, node) {
+ if (!opp->available)
+ continue;
+
+ if (opp->supplies[i].u_volt_min < uV[i].min)
+ uV[i].min = opp->supplies[i].u_volt_min;
+ if (opp->supplies[i].u_volt_max > uV[i].max)
+ uV[i].max = opp->supplies[i].u_volt_max;
+ }
}
rcu_read_unlock();
@@ -258,9 +295,16 @@ unsigned long dev_pm_opp_get_max_volt_latency(struct device *dev)
* The caller needs to ensure that opp_table (and hence the regulator)
* isn't freed, while we are executing this routine.
*/
- ret = regulator_set_voltage_time(reg, min_uV, max_uV);
- if (ret > 0)
- latency_ns = ret * 1000;
+ for (i = 0; reg = regulators[i], i < count; i++) {
+ ret = regulator_set_voltage_time(reg, uV[i].min, uV[i].max);
+ if (ret > 0)
+ latency_ns += ret * 1000;
+ }
+
+free_uV:
+ kfree(uV);
+free_regulators:
+ kfree(regulators);
return latency_ns;
}
@@ -542,8 +586,7 @@ static struct clk *_get_opp_clk(struct device *dev)
}
static int _set_opp_voltage(struct device *dev, struct regulator *reg,
- unsigned long u_volt, unsigned long u_volt_min,
- unsigned long u_volt_max)
+ struct dev_pm_opp_supply *supply)
{
int ret;
@@ -554,14 +597,78 @@ static int _set_opp_voltage(struct device *dev, struct regulator *reg,
return 0;
}
- dev_dbg(dev, "%s: voltages (mV): %lu %lu %lu\n", __func__, u_volt_min,
- u_volt, u_volt_max);
+ dev_dbg(dev, "%s: voltages (mV): %lu %lu %lu\n", __func__,
+ supply->u_volt_min, supply->u_volt, supply->u_volt_max);
- ret = regulator_set_voltage_triplet(reg, u_volt_min, u_volt,
- u_volt_max);
+ ret = regulator_set_voltage_triplet(reg, supply->u_volt_min,
+ supply->u_volt, supply->u_volt_max);
if (ret)
dev_err(dev, "%s: failed to set voltage (%lu %lu %lu mV): %d\n",
- __func__, u_volt_min, u_volt, u_volt_max, ret);
+ __func__, supply->u_volt_min, supply->u_volt,
+ supply->u_volt_max, ret);
+
+ return ret;
+}
+
+static inline int
+_generic_set_opp_clk_only(struct device *dev, struct clk *clk,
+ unsigned long old_freq, unsigned long freq)
+{
+ int ret;
+
+ ret = clk_set_rate(clk, freq);
+ if (ret) {
+ dev_err(dev, "%s: failed to set clock rate: %d\n", __func__,
+ ret);
+ }
+
+ return ret;
+}
+
+static int _generic_set_opp(struct dev_pm_set_opp_data *data)
+{
+ struct dev_pm_opp_supply *old_supply = data->old_opp.supplies;
+ struct dev_pm_opp_supply *new_supply = data->new_opp.supplies;
+ unsigned long old_freq = data->old_opp.rate, freq = data->new_opp.rate;
+ struct regulator *reg = data->regulators[0];
+ struct device *dev= data->dev;
+ int ret;
+
+ /* This function only supports single regulator per device */
+ if (WARN_ON(data->regulator_count > 1)) {
+ dev_err(dev, "multiple regulators are not supported\n");
+ return -EINVAL;
+ }
+
+ /* Scaling up? Scale voltage before frequency */
+ if (freq > old_freq) {
+ ret = _set_opp_voltage(dev, reg, new_supply);
+ if (ret)
+ goto restore_voltage;
+ }
+
+ /* Change frequency */
+ ret = _generic_set_opp_clk_only(dev, data->clk, old_freq, freq);
+ if (ret)
+ goto restore_voltage;
+
+ /* Scaling down? Scale voltage after frequency */
+ if (freq < old_freq) {
+ ret = _set_opp_voltage(dev, reg, new_supply);
+ if (ret)
+ goto restore_freq;
+ }
+
+ return 0;
+
+restore_freq:
+ if (_generic_set_opp_clk_only(dev, data->clk, freq, old_freq))
+ dev_err(dev, "%s: failed to restore old-freq (%lu Hz)\n",
+ __func__, old_freq);
+restore_voltage:
+ /* This shouldn't harm even if the voltages weren't updated earlier */
+ if (old_supply->u_volt)
+ _set_opp_voltage(dev, reg, old_supply);
return ret;
}
@@ -579,13 +686,13 @@ static int _set_opp_voltage(struct device *dev, struct regulator *reg,
int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq)
{
struct opp_table *opp_table;
+ unsigned long freq, old_freq;
+ int (*set_opp)(struct dev_pm_set_opp_data *data);
struct dev_pm_opp *old_opp, *opp;
- struct regulator *reg;
+ struct regulator **regulators;
+ struct dev_pm_set_opp_data *data;
struct clk *clk;
- unsigned long freq, old_freq;
- unsigned long u_volt, u_volt_min, u_volt_max;
- unsigned long old_u_volt, old_u_volt_min, old_u_volt_max;
- int ret;
+ int ret, size;
if (unlikely(!target_freq)) {
dev_err(dev, "%s: Invalid target frequency %lu\n", __func__,
@@ -634,64 +741,54 @@ int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq)
return ret;
}
- if (IS_ERR(old_opp)) {
- old_u_volt = 0;
- } else {
- old_u_volt = old_opp->u_volt;
- old_u_volt_min = old_opp->u_volt_min;
- old_u_volt_max = old_opp->u_volt_max;
- }
-
- u_volt = opp->u_volt;
- u_volt_min = opp->u_volt_min;
- u_volt_max = opp->u_volt_max;
-
- reg = opp_table->regulator;
+ dev_dbg(dev, "%s: switching OPP: %lu Hz --> %lu Hz\n", __func__,
+ old_freq, freq);
- rcu_read_unlock();
+ regulators = opp_table->regulators;
- /* Scaling up? Scale voltage before frequency */
- if (freq > old_freq) {
- ret = _set_opp_voltage(dev, reg, u_volt, u_volt_min,
- u_volt_max);
- if (ret)
- goto restore_voltage;
- }
+ /* Only frequency scaling */
+ if (!regulators) {
+ unsigned long u_volt = opp->supplies[0].u_volt;
- /* Change frequency */
+ rcu_read_unlock();
- dev_dbg(dev, "%s: switching OPP: %lu Hz --> %lu Hz\n",
- __func__, old_freq, freq);
+ /*
+ * DT contained supply ratings? Consider platform failed to set
+ * regulators.
+ */
+ if (unlikely(u_volt)) {
+ dev_err(dev, "%s: Regulator not registered with OPP core\n",
+ __func__);
+ return -EINVAL;
+ }
- ret = clk_set_rate(clk, freq);
- if (ret) {
- dev_err(dev, "%s: failed to set clock rate: %d\n", __func__,
- ret);
- goto restore_voltage;
+ return _generic_set_opp_clk_only(dev, clk, old_freq, freq);
}
- /* Scaling down? Scale voltage after frequency */
- if (freq < old_freq) {
- ret = _set_opp_voltage(dev, reg, u_volt, u_volt_min,
- u_volt_max);
- if (ret)
- goto restore_freq;
- }
+ if (opp_table->set_opp)
+ set_opp = opp_table->set_opp;
+ else
+ set_opp = _generic_set_opp;
+
+ data = opp_table->set_opp_data;
+ data->regulators = regulators;
+ data->regulator_count = opp_table->regulator_count;
+ data->clk = clk;
+ data->dev = dev;
+
+ data->old_opp.rate = old_freq;
+ size = sizeof(*opp->supplies) * opp_table->regulator_count;
+ if (IS_ERR(old_opp))
+ memset(data->old_opp.supplies, 0, size);
+ else
+ memcpy(data->old_opp.supplies, old_opp->supplies, size);
- return 0;
+ data->new_opp.rate = freq;
+ memcpy(data->new_opp.supplies, opp->supplies, size);
-restore_freq:
- if (clk_set_rate(clk, old_freq))
- dev_err(dev, "%s: failed to restore old-freq (%lu Hz)\n",
- __func__, old_freq);
-restore_voltage:
- /* This shouldn't harm even if the voltages weren't updated earlier */
- if (old_u_volt) {
- _set_opp_voltage(dev, reg, old_u_volt, old_u_volt_min,
- old_u_volt_max);
- }
+ rcu_read_unlock();
- return ret;
+ return set_opp(data);
}
EXPORT_SYMBOL_GPL(dev_pm_opp_set_rate);
@@ -774,9 +871,6 @@ static struct opp_table *_add_opp_table(struct device *dev)
_of_init_opp_table(opp_table, dev);
- /* Set regulator to a non-NULL error value */
- opp_table->regulator = ERR_PTR(-ENXIO);
-
/* Find clk for the device */
opp_table->clk = clk_get(dev, NULL);
if (IS_ERR(opp_table->clk)) {
@@ -825,7 +919,10 @@ static void _remove_opp_table(struct opp_table *opp_table)
if (opp_table->prop_name)
return;
- if (!IS_ERR(opp_table->regulator))
+ if (opp_table->regulators)
+ return;
+
+ if (opp_table->set_opp)
return;
/* Release clk */
@@ -934,34 +1031,50 @@ struct dev_pm_opp *_allocate_opp(struct device *dev,
struct opp_table **opp_table)
{
struct dev_pm_opp *opp;
+ int count, supply_size;
+ struct opp_table *table;
- /* allocate new OPP node */
- opp = kzalloc(sizeof(*opp), GFP_KERNEL);
- if (!opp)
+ table = _add_opp_table(dev);
+ if (!table)
return NULL;
- INIT_LIST_HEAD(&opp->node);
+ /* Allocate space for at least one supply */
+ count = table->regulator_count ? table->regulator_count : 1;
+ supply_size = sizeof(*opp->supplies) * count;
- *opp_table = _add_opp_table(dev);
- if (!*opp_table) {
- kfree(opp);
+ /* allocate new OPP node and supplies structures */
+ opp = kzalloc(sizeof(*opp) + supply_size, GFP_KERNEL);
+ if (!opp) {
+ kfree(table);
return NULL;
}
+ /* Put the supplies at the end of the OPP structure as an empty array */
+ opp->supplies = (struct dev_pm_opp_supply *)(opp + 1);
+ INIT_LIST_HEAD(&opp->node);
+
+ *opp_table = table;
+
return opp;
}
static bool _opp_supported_by_regulators(struct dev_pm_opp *opp,
struct opp_table *opp_table)
{
- struct regulator *reg = opp_table->regulator;
-
- if (!IS_ERR(reg) &&
- !regulator_is_supported_voltage(reg, opp->u_volt_min,
- opp->u_volt_max)) {
- pr_warn("%s: OPP minuV: %lu maxuV: %lu, not supported by regulator\n",
- __func__, opp->u_volt_min, opp->u_volt_max);
- return false;
+ struct regulator *reg;
+ int i;
+
+ for (i = 0; i < opp_table->regulator_count; i++) {
+ reg = opp_table->regulators[i];
+
+ if (!regulator_is_supported_voltage(reg,
+ opp->supplies[i].u_volt_min,
+ opp->supplies[i].u_volt_max)) {
+ pr_warn("%s: OPP minuV: %lu maxuV: %lu, not supported by regulator\n",
+ __func__, opp->supplies[i].u_volt_min,
+ opp->supplies[i].u_volt_max);
+ return false;
+ }
}
return true;
@@ -993,11 +1106,13 @@ int _opp_add(struct device *dev, struct dev_pm_opp *new_opp,
/* Duplicate OPPs */
dev_warn(dev, "%s: duplicate OPPs detected. Existing: freq: %lu, volt: %lu, enabled: %d. New: freq: %lu, volt: %lu, enabled: %d\n",
- __func__, opp->rate, opp->u_volt, opp->available,
- new_opp->rate, new_opp->u_volt, new_opp->available);
+ __func__, opp->rate, opp->supplies[0].u_volt,
+ opp->available, new_opp->rate,
+ new_opp->supplies[0].u_volt, new_opp->available);
- return opp->available && new_opp->u_volt == opp->u_volt ?
- 0 : -EEXIST;
+ /* Should we compare voltages for all regulators here ? */
+ return opp->available &&
+ new_opp->supplies[0].u_volt == opp->supplies[0].u_volt ? 0 : -EEXIST;
}
new_opp->opp_table = opp_table;
@@ -1064,9 +1179,9 @@ int _opp_add_v1(struct device *dev, unsigned long freq, long u_volt,
/* populate the opp table */
new_opp->rate = freq;
tol = u_volt * opp_table->voltage_tolerance_v1 / 100;
- new_opp->u_volt = u_volt;
- new_opp->u_volt_min = u_volt - tol;
- new_opp->u_volt_max = u_volt + tol;
+ new_opp->supplies[0].u_volt = u_volt;
+ new_opp->supplies[0].u_volt_min = u_volt - tol;
+ new_opp->supplies[0].u_volt_max = u_volt + tol;
new_opp->available = true;
new_opp->dynamic = dynamic;
@@ -1310,13 +1425,47 @@ void dev_pm_opp_put_prop_name(struct device *dev)
}
EXPORT_SYMBOL_GPL(dev_pm_opp_put_prop_name);
+static int _allocate_set_opp_data(struct opp_table *opp_table)
+{
+ struct dev_pm_set_opp_data *data;
+ int len, count = opp_table->regulator_count;
+
+ if (WARN_ON(!count))
+ return -EINVAL;
+
+ /* space for set_opp_data */
+ len = sizeof(*data);
+
+ /* space for old_opp.supplies and new_opp.supplies */
+ len += 2 * sizeof(struct dev_pm_opp_supply) * count;
+
+ data = kzalloc(len, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->old_opp.supplies = (void *)(data + 1);
+ data->new_opp.supplies = data->old_opp.supplies + count;
+
+ opp_table->set_opp_data = data;
+
+ return 0;
+}
+
+static void _free_set_opp_data(struct opp_table *opp_table)
+{
+ kfree(opp_table->set_opp_data);
+ opp_table->set_opp_data = NULL;
+}
+
/**
- * dev_pm_opp_set_regulator() - Set regulator name for the device
+ * dev_pm_opp_set_regulators() - Set regulator names for the device
* @dev: Device for which regulator name is being set.
- * @name: Name of the regulator.
+ * @names: Array of pointers to the names of the regulator.
+ * @count: Number of regulators.
*
* In order to support OPP switching, OPP layer needs to know the name of the
- * device's regulator, as the core would be required to switch voltages as well.
+ * device's regulators, as the core would be required to switch voltages as
+ * well.
*
* This must be called before any OPPs are initialized for the device.
*
@@ -1326,11 +1475,12 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_put_prop_name);
* that this function is *NOT* called under RCU protection or in contexts where
* mutex cannot be locked.
*/
-struct opp_table *dev_pm_opp_set_regulator(struct device *dev, const char *name)
+int dev_pm_opp_set_regulators(struct device *dev, const char * const names[],
+ unsigned int count)
{
struct opp_table *opp_table;
struct regulator *reg;
- int ret;
+ int ret, i;
mutex_lock(&opp_table_lock);
@@ -1346,38 +1496,62 @@ struct opp_table *dev_pm_opp_set_regulator(struct device *dev, const char *name)
goto err;
}
- /* Already have a regulator set */
- if (WARN_ON(!IS_ERR(opp_table->regulator))) {
+ /* Already have regulators set */
+ if (opp_table->regulators) {
ret = -EBUSY;
goto err;
}
- /* Allocate the regulator */
- reg = regulator_get_optional(dev, name);
- if (IS_ERR(reg)) {
- ret = PTR_ERR(reg);
- if (ret != -EPROBE_DEFER)
- dev_err(dev, "%s: no regulator (%s) found: %d\n",
- __func__, name, ret);
+
+ opp_table->regulators = kmalloc_array(count,
+ sizeof(*opp_table->regulators),
+ GFP_KERNEL);
+ if (!opp_table->regulators) {
+ ret = -ENOMEM;
goto err;
}
- opp_table->regulator = reg;
+ for (i = 0; i < count; i++) {
+ reg = regulator_get_optional(dev, names[i]);
+ if (IS_ERR(reg)) {
+ ret = PTR_ERR(reg);
+ if (ret != -EPROBE_DEFER)
+ dev_err(dev, "%s: regulator (%s) not found: %d\n",
+ __func__, names[i], ret);
+ goto free_regulators;
+ }
+
+ opp_table->regulators[i] = reg;
+ }
+
+ opp_table->regulator_count = count;
+
+ /* Allocate block only once to pass to set_opp() routines */
+ ret = _allocate_set_opp_data(opp_table);
+ if (ret)
+ goto free_regulators;
mutex_unlock(&opp_table_lock);
- return opp_table;
+ return 0;
+free_regulators:
+ while (i != 0)
+ regulator_put(opp_table->regulators[--i]);
+
+ kfree(opp_table->regulators);
+ opp_table->regulators = NULL;
+ opp_table->regulator_count = 0;
err:
_remove_opp_table(opp_table);
unlock:
mutex_unlock(&opp_table_lock);
- return ERR_PTR(ret);
+ return ret;
}
-EXPORT_SYMBOL_GPL(dev_pm_opp_set_regulator);
+EXPORT_SYMBOL_GPL(dev_pm_opp_set_regulators);
/**
- * dev_pm_opp_put_regulator() - Releases resources blocked for regulator
- * @opp_table: OPP table returned from dev_pm_opp_set_regulator().
+ * dev_pm_opp_put_regulators() - Releases resources blocked for regulators
+ * @dev: Device for which regulators were set.
*
* Locking: The internal opp_table and opp structures are RCU protected.
* Hence this function internally uses RCU updater strategy with mutex locks
@@ -1385,20 +1559,140 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_set_regulator);
* that this function is *NOT* called under RCU protection or in contexts where
* mutex cannot be locked.
*/
-void dev_pm_opp_put_regulator(struct opp_table *opp_table)
+void dev_pm_opp_put_regulators(struct device *dev)
{
+ struct opp_table *opp_table;
+ int i;
+
mutex_lock(&opp_table_lock);
- if (IS_ERR(opp_table->regulator)) {
- pr_err("%s: Doesn't have regulator set\n", __func__);
+ /* Check for existing table for 'dev' first */
+ opp_table = _find_opp_table(dev);
+ if (IS_ERR(opp_table)) {
+ dev_err(dev, "Failed to find opp_table: %ld\n",
+ PTR_ERR(opp_table));
+ goto unlock;
+ }
+
+ if (!opp_table->regulators) {
+ dev_err(dev, "%s: Doesn't have regulators set\n", __func__);
+ goto unlock;
+ }
+
+ /* Make sure there are no concurrent readers while updating opp_table */
+ WARN_ON(!list_empty(&opp_table->opp_list));
+
+ for (i = opp_table->regulator_count - 1; i >= 0; i--)
+ regulator_put(opp_table->regulators[i]);
+
+ _free_set_opp_data(opp_table);
+
+ kfree(opp_table->regulators);
+ opp_table->regulators = NULL;
+ opp_table->regulator_count = 0;
+
+ /* Try freeing opp_table if this was the last blocking resource */
+ _remove_opp_table(opp_table);
+
+unlock:
+ mutex_unlock(&opp_table_lock);
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_put_regulators);
+
+/**
+ * dev_pm_opp_register_set_opp_helper() - Register custom set OPP helper
+ * @dev: Device for which the helper is getting registered.
+ * @set_opp: Custom set OPP helper.
+ *
+ * This is useful to support complex platforms (like platforms with multiple
+ * regulators per device), instead of the generic OPP set rate helper.
+ *
+ * This must be called before any OPPs are initialized for the device.
+ *
+ * Locking: The internal opp_table and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ */
+int dev_pm_opp_register_set_opp_helper(struct device *dev,
+ int (*set_opp)(struct dev_pm_set_opp_data *data))
+{
+ struct opp_table *opp_table;
+ int ret;
+
+ if (!set_opp)
+ return -EINVAL;
+
+ mutex_lock(&opp_table_lock);
+
+ opp_table = _add_opp_table(dev);
+ if (!opp_table) {
+ ret = -ENOMEM;
+ goto unlock;
+ }
+
+ /* This should be called before OPPs are initialized */
+ if (WARN_ON(!list_empty(&opp_table->opp_list))) {
+ ret = -EBUSY;
+ goto err;
+ }
+
+ /* Already have custom set_opp helper */
+ if (WARN_ON(opp_table->set_opp)) {
+ ret = -EBUSY;
+ goto err;
+ }
+
+ opp_table->set_opp = set_opp;
+
+ mutex_unlock(&opp_table_lock);
+ return 0;
+
+err:
+ _remove_opp_table(opp_table);
+unlock:
+ mutex_unlock(&opp_table_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_register_set_opp_helper);
+
+/**
+ * dev_pm_opp_register_put_opp_helper() - Releases resources blocked for
+ * set_opp helper
+ * @dev: Device for which custom set_opp helper has to be cleared.
+ *
+ * Locking: The internal opp_table and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ */
+void dev_pm_opp_register_put_opp_helper(struct device *dev)
+{
+ struct opp_table *opp_table;
+
+ mutex_lock(&opp_table_lock);
+
+ /* Check for existing table for 'dev' first */
+ opp_table = _find_opp_table(dev);
+ if (IS_ERR(opp_table)) {
+ dev_err(dev, "Failed to find opp_table: %ld\n",
+ PTR_ERR(opp_table));
+ goto unlock;
+ }
+
+ if (!opp_table->set_opp) {
+ dev_err(dev, "%s: Doesn't have custom set_opp helper set\n",
+ __func__);
goto unlock;
}
/* Make sure there are no concurrent readers while updating opp_table */
WARN_ON(!list_empty(&opp_table->opp_list));
- regulator_put(opp_table->regulator);
- opp_table->regulator = ERR_PTR(-ENXIO);
+ opp_table->set_opp = NULL;
/* Try freeing opp_table if this was the last blocking resource */
_remove_opp_table(opp_table);
@@ -1406,7 +1700,7 @@ void dev_pm_opp_put_regulator(struct opp_table *opp_table)
unlock:
mutex_unlock(&opp_table_lock);
}
-EXPORT_SYMBOL_GPL(dev_pm_opp_put_regulator);
+EXPORT_SYMBOL_GPL(dev_pm_opp_register_put_opp_helper);
/**
* dev_pm_opp_add() - Add an OPP table from a table definitions
diff --git a/drivers/base/power/opp/debugfs.c b/drivers/base/power/opp/debugfs.c
index ef1ae6b..95f433d 100644
--- a/drivers/base/power/opp/debugfs.c
+++ b/drivers/base/power/opp/debugfs.c
@@ -15,6 +15,7 @@
#include <linux/err.h>
#include <linux/init.h>
#include <linux/limits.h>
+#include <linux/slab.h>
#include "opp.h"
@@ -34,6 +35,46 @@ void opp_debug_remove_one(struct dev_pm_opp *opp)
debugfs_remove_recursive(opp->dentry);
}
+static bool opp_debug_create_supplies(struct dev_pm_opp *opp,
+ struct opp_table *opp_table,
+ struct dentry *pdentry)
+{
+ struct dentry *d;
+ int i = 0;
+ char *name;
+
+ /* Always create at least supply-0 directory */
+ do {
+ name = kasprintf(GFP_KERNEL, "supply-%d", i);
+
+ /* Create per-opp directory */
+ d = debugfs_create_dir(name, pdentry);
+
+ kfree(name);
+
+ if (!d)
+ return false;
+
+ if (!debugfs_create_ulong("u_volt_target", S_IRUGO, d,
+ &opp->supplies[i].u_volt))
+ return false;
+
+ if (!debugfs_create_ulong("u_volt_min", S_IRUGO, d,
+ &opp->supplies[i].u_volt_min))
+ return false;
+
+ if (!debugfs_create_ulong("u_volt_max", S_IRUGO, d,
+ &opp->supplies[i].u_volt_max))
+ return false;
+
+ if (!debugfs_create_ulong("u_amp", S_IRUGO, d,
+ &opp->supplies[i].u_amp))
+ return false;
+ } while (++i < opp_table->regulator_count);
+
+ return true;
+}
+
int opp_debug_create_one(struct dev_pm_opp *opp, struct opp_table *opp_table)
{
struct dentry *pdentry = opp_table->dentry;
@@ -63,16 +104,7 @@ int opp_debug_create_one(struct dev_pm_opp *opp, struct opp_table *opp_table)
if (!debugfs_create_ulong("rate_hz", S_IRUGO, d, &opp->rate))
return -ENOMEM;
- if (!debugfs_create_ulong("u_volt_target", S_IRUGO, d, &opp->u_volt))
- return -ENOMEM;
-
- if (!debugfs_create_ulong("u_volt_min", S_IRUGO, d, &opp->u_volt_min))
- return -ENOMEM;
-
- if (!debugfs_create_ulong("u_volt_max", S_IRUGO, d, &opp->u_volt_max))
- return -ENOMEM;
-
- if (!debugfs_create_ulong("u_amp", S_IRUGO, d, &opp->u_amp))
+ if (!opp_debug_create_supplies(opp, opp_table, d))
return -ENOMEM;
if (!debugfs_create_ulong("clock_latency_ns", S_IRUGO, d,
diff --git a/drivers/base/power/opp/of.c b/drivers/base/power/opp/of.c
index 5552211..8c869aa 100644
--- a/drivers/base/power/opp/of.c
+++ b/drivers/base/power/opp/of.c
@@ -17,6 +17,7 @@
#include <linux/errno.h>
#include <linux/device.h>
#include <linux/of.h>
+#include <linux/slab.h>
#include <linux/export.h>
#include "opp.h"
@@ -101,16 +102,16 @@ static bool _opp_is_supported(struct device *dev, struct opp_table *opp_table,
return true;
}
-/* TODO: Support multiple regulators */
static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev,
struct opp_table *opp_table)
{
- u32 microvolt[3] = {0};
- u32 val;
- int count, ret;
+ u32 *microvolt, *microamp = NULL;
+ int supplies, vcount, icount, ret, i, j;
struct property *prop = NULL;
char name[NAME_MAX];
+ supplies = opp_table->regulator_count ? opp_table->regulator_count : 1;
+
/* Search for "opp-microvolt-<name>" */
if (opp_table->prop_name) {
snprintf(name, sizeof(name), "opp-microvolt-%s",
@@ -128,34 +129,29 @@ static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev,
return 0;
}
- count = of_property_count_u32_elems(opp->np, name);
- if (count < 0) {
+ vcount = of_property_count_u32_elems(opp->np, name);
+ if (vcount < 0) {
dev_err(dev, "%s: Invalid %s property (%d)\n",
- __func__, name, count);
- return count;
+ __func__, name, vcount);
+ return vcount;
}
- /* There can be one or three elements here */
- if (count != 1 && count != 3) {
- dev_err(dev, "%s: Invalid number of elements in %s property (%d)\n",
- __func__, name, count);
+ /* There can be one or three elements per supply */
+ if (vcount != supplies && vcount != supplies * 3) {
+ dev_err(dev, "%s: Invalid number of elements in %s property (%d) with supplies (%d)\n",
+ __func__, name, vcount, supplies);
return -EINVAL;
}
- ret = of_property_read_u32_array(opp->np, name, microvolt, count);
+ microvolt = kmalloc_array(vcount, sizeof(*microvolt), GFP_KERNEL);
+ if (!microvolt)
+ return -ENOMEM;
+
+ ret = of_property_read_u32_array(opp->np, name, microvolt, vcount);
if (ret) {
dev_err(dev, "%s: error parsing %s: %d\n", __func__, name, ret);
- return -EINVAL;
- }
-
- opp->u_volt = microvolt[0];
-
- if (count == 1) {
- opp->u_volt_min = opp->u_volt;
- opp->u_volt_max = opp->u_volt;
- } else {
- opp->u_volt_min = microvolt[1];
- opp->u_volt_max = microvolt[2];
+ ret = -EINVAL;
+ goto free_microvolt;
}
/* Search for "opp-microamp-<name>" */
@@ -172,10 +168,59 @@ static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev,
prop = of_find_property(opp->np, name, NULL);
}
- if (prop && !of_property_read_u32(opp->np, name, &val))
- opp->u_amp = val;
+ if (prop) {
+ icount = of_property_count_u32_elems(opp->np, name);
+ if (icount < 0) {
+ dev_err(dev, "%s: Invalid %s property (%d)\n", __func__,
+ name, icount);
+ ret = icount;
+ goto free_microvolt;
+ }
- return 0;
+ if (icount != supplies) {
+ dev_err(dev, "%s: Invalid number of elements in %s property (%d) with supplies (%d)\n",
+ __func__, name, icount, supplies);
+ ret = -EINVAL;
+ goto free_microvolt;
+ }
+
+ microamp = kmalloc_array(icount, sizeof(*microamp), GFP_KERNEL);
+ if (!microamp) {
+ ret = -EINVAL;
+ goto free_microvolt;
+ }
+
+ ret = of_property_read_u32_array(opp->np, name, microamp,
+ icount);
+ if (ret) {
+ dev_err(dev, "%s: error parsing %s: %d\n", __func__,
+ name, ret);
+ ret = -EINVAL;
+ goto free_microamp;
+ }
+ }
+
+ for (i = 0, j = 0; i < supplies; i++) {
+ opp->supplies[i].u_volt = microvolt[j++];
+
+ if (vcount == supplies) {
+ opp->supplies[i].u_volt_min = opp->supplies[i].u_volt;
+ opp->supplies[i].u_volt_max = opp->supplies[i].u_volt;
+ } else {
+ opp->supplies[i].u_volt_min = microvolt[j++];
+ opp->supplies[i].u_volt_max = microvolt[j++];
+ }
+
+ if (microamp)
+ opp->supplies[i].u_amp = microamp[i];
+ }
+
+free_microamp:
+ kfree(microamp);
+free_microvolt:
+ kfree(microvolt);
+
+ return ret;
}
/**
@@ -198,7 +243,7 @@ void dev_pm_opp_of_remove_table(struct device *dev)
EXPORT_SYMBOL_GPL(dev_pm_opp_of_remove_table);
/* Returns opp descriptor node for a device, caller must do of_node_put() */
-struct device_node *_of_get_opp_desc_node(struct device *dev)
+struct device_node *dev_pm_opp_of_get_opp_desc_node(struct device *dev)
{
/*
* TODO: Support for multiple OPP tables.
@@ -209,6 +254,7 @@ struct device_node *_of_get_opp_desc_node(struct device *dev)
return of_parse_phandle(dev->of_node, "operating-points-v2", 0);
}
+EXPORT_SYMBOL_GPL(dev_pm_opp_of_get_opp_desc_node);
/**
* _opp_add_static_v2() - Allocate static OPPs (As per 'v2' DT bindings)
@@ -303,9 +349,9 @@ static int _opp_add_static_v2(struct device *dev, struct device_node *np)
mutex_unlock(&opp_table_lock);
pr_debug("%s: turbo:%d rate:%lu uv:%lu uvmin:%lu uvmax:%lu latency:%lu\n",
- __func__, new_opp->turbo, new_opp->rate, new_opp->u_volt,
- new_opp->u_volt_min, new_opp->u_volt_max,
- new_opp->clock_latency_ns);
+ __func__, new_opp->turbo, new_opp->rate,
+ new_opp->supplies[0].u_volt, new_opp->supplies[0].u_volt_min,
+ new_opp->supplies[0].u_volt_max, new_opp->clock_latency_ns);
/*
* Notify the changes in the availability of the operable
@@ -450,7 +496,7 @@ int dev_pm_opp_of_add_table(struct device *dev)
* OPPs have two version of bindings now. The older one is deprecated,
* try for the new binding first.
*/
- opp_np = _of_get_opp_desc_node(dev);
+ opp_np = dev_pm_opp_of_get_opp_desc_node(dev);
if (!opp_np) {
/*
* Try old-deprecated bindings for backward compatibility with
@@ -560,7 +606,7 @@ int dev_pm_opp_of_get_sharing_cpus(struct device *cpu_dev,
int cpu, ret = 0;
/* Get OPP descriptor node */
- np = _of_get_opp_desc_node(cpu_dev);
+ np = dev_pm_opp_of_get_opp_desc_node(cpu_dev);
if (!np) {
dev_dbg(cpu_dev, "%s: Couldn't find cpu_dev node.\n", __func__);
return -ENOENT;
@@ -585,7 +631,7 @@ int dev_pm_opp_of_get_sharing_cpus(struct device *cpu_dev,
}
/* Get OPP descriptor node */
- tmp_np = _of_get_opp_desc_node(tcpu_dev);
+ tmp_np = dev_pm_opp_of_get_opp_desc_node(tcpu_dev);
if (!tmp_np) {
dev_err(tcpu_dev, "%s: Couldn't find tcpu_dev node.\n",
__func__);
diff --git a/drivers/base/power/opp/opp.h b/drivers/base/power/opp/opp.h
index fabd5ca..af9f2b8 100644
--- a/drivers/base/power/opp/opp.h
+++ b/drivers/base/power/opp/opp.h
@@ -61,10 +61,7 @@ extern struct list_head opp_tables;
* @turbo: true if turbo (boost) OPP
* @suspend: true if suspend OPP
* @rate: Frequency in hertz
- * @u_volt: Target voltage in microvolts corresponding to this OPP
- * @u_volt_min: Minimum voltage in microvolts corresponding to this OPP
- * @u_volt_max: Maximum voltage in microvolts corresponding to this OPP
- * @u_amp: Maximum current drawn by the device in microamperes
+ * @supplies: Power supplies voltage/current values
* @clock_latency_ns: Latency (in nanoseconds) of switching to this OPP's
* frequency from any other OPP's frequency.
* @opp_table: points back to the opp_table struct this opp belongs to
@@ -83,10 +80,8 @@ struct dev_pm_opp {
bool suspend;
unsigned long rate;
- unsigned long u_volt;
- unsigned long u_volt_min;
- unsigned long u_volt_max;
- unsigned long u_amp;
+ struct dev_pm_opp_supply *supplies;
+
unsigned long clock_latency_ns;
struct opp_table *opp_table;
@@ -144,7 +139,10 @@ enum opp_table_access {
* @supported_hw_count: Number of elements in supported_hw array.
* @prop_name: A name to postfix to many DT properties, while parsing them.
* @clk: Device's clock handle
- * @regulator: Supply regulator
+ * @regulators: Supply regulators
+ * @regulator_count: Number of power supply regulators
+ * @set_opp: Platform specific set_opp callback
+ * @set_opp_data: Data to be passed to set_opp callback
* @dentry: debugfs dentry pointer of the real device directory (not links).
* @dentry_name: Name of the real dentry.
*
@@ -179,7 +177,11 @@ struct opp_table {
unsigned int supported_hw_count;
const char *prop_name;
struct clk *clk;
- struct regulator *regulator;
+ struct regulator **regulators;
+ unsigned int regulator_count;
+
+ int (*set_opp)(struct dev_pm_set_opp_data *data);
+ struct dev_pm_set_opp_data *set_opp_data;
#ifdef CONFIG_DEBUG_FS
struct dentry *dentry;
@@ -190,7 +192,6 @@ struct opp_table {
/* Routines internal to opp core */
struct opp_table *_find_opp_table(struct device *dev);
struct opp_device *_add_opp_dev(const struct device *dev, struct opp_table *opp_table);
-struct device_node *_of_get_opp_desc_node(struct device *dev);
void _dev_pm_opp_remove_table(struct device *dev, bool remove_all);
struct dev_pm_opp *_allocate_opp(struct device *dev, struct opp_table **opp_table);
int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, struct opp_table *opp_table);
diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
index 7875105..bbd5afd 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -120,7 +120,6 @@ config QCOM_EBI2
config SIMPLE_PM_BUS
bool "Simple Power-Managed Bus Driver"
depends on OF && PM
- depends on ARCH_RENESAS || COMPILE_TEST
help
Driver for transparent busses that don't need a real driver, but
where the bus controller is part of a PM domain, or under the control
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index d89b8af..665f11d 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -234,6 +234,17 @@ config ARM_TEGRA124_CPUFREQ
help
This adds the CPUFreq driver support for Tegra124 SOCs.
+config ARM_TI_CPUFREQ
+ bool "Texas Instruments CPUFreq support"
+ depends on ARCH_OMAP2PLUS
+ help
+ This driver enables valid OPPs on the running platform based on
+ values contained within the SoC in use. Enable this in order to
+ use the cpufreq-dt driver on all Texas Instruments platforms that
+ provide dt based operating-points-v2 tables with opp-supported-hw
+ data provided. Required for cpufreq support on AM335x, AM437x,
+ DRA7x, and AM57x platforms.
+
config ARM_PXA2xx_CPUFREQ
tristate "Intel PXA2xx CPUfreq driver"
depends on PXA27x || PXA25x
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 0a9b6a0..5b1b6ec 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -77,6 +77,7 @@ obj-$(CONFIG_ARM_SPEAR_CPUFREQ) += spear-cpufreq.o
obj-$(CONFIG_ARM_STI_CPUFREQ) += sti-cpufreq.o
obj-$(CONFIG_ARM_TEGRA20_CPUFREQ) += tegra20-cpufreq.o
obj-$(CONFIG_ARM_TEGRA124_CPUFREQ) += tegra124-cpufreq.o
+obj-$(CONFIG_ARM_TI_CPUFREQ) += ti-cpufreq.o
obj-$(CONFIG_ARM_VEXPRESS_SPC_CPUFREQ) += vexpress-spc-cpufreq.o
obj-$(CONFIG_ACPI_CPPC_CPUFREQ) += cppc_cpufreq.o
obj-$(CONFIG_MACH_MVEBU_V7) += mvebu-cpufreq.o
diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
index 7126762..d2637e1 100644
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -72,8 +72,6 @@ static const struct of_device_id machines[] __initconst = {
{ .compatible = "sigma,tango4" },
- { .compatible = "ti,am33xx", },
- { .compatible = "ti,dra7", },
{ .compatible = "ti,omap2", },
{ .compatible = "ti,omap3", },
{ .compatible = "ti,omap4", },
diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c
index 4d3ec92..15cb261 100644
--- a/drivers/cpufreq/cpufreq-dt.c
+++ b/drivers/cpufreq/cpufreq-dt.c
@@ -28,7 +28,6 @@
#include "cpufreq-dt.h"
struct private_data {
- struct opp_table *opp_table;
struct device *cpu_dev;
struct thermal_cooling_device *cdev;
const char *reg_name;
@@ -144,7 +143,6 @@ static int resources_available(void)
static int cpufreq_init(struct cpufreq_policy *policy)
{
struct cpufreq_frequency_table *freq_table;
- struct opp_table *opp_table = NULL;
struct private_data *priv;
struct device *cpu_dev;
struct clk *cpu_clk;
@@ -188,9 +186,11 @@ static int cpufreq_init(struct cpufreq_policy *policy)
*/
name = find_supply_name(cpu_dev);
if (name) {
- opp_table = dev_pm_opp_set_regulator(cpu_dev, name);
- if (IS_ERR(opp_table)) {
- ret = PTR_ERR(opp_table);
+ const char *names[] = {name};
+
+ ret = dev_pm_opp_set_regulators(cpu_dev, names,
+ ARRAY_SIZE(names));
+ if (ret) {
dev_err(cpu_dev, "Failed to set regulator for cpu%d: %d\n",
policy->cpu, ret);
goto out_put_clk;
@@ -240,7 +240,6 @@ static int cpufreq_init(struct cpufreq_policy *policy)
}
priv->reg_name = name;
- priv->opp_table = opp_table;
ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table);
if (ret) {
@@ -289,7 +288,7 @@ static int cpufreq_init(struct cpufreq_policy *policy)
out_free_opp:
dev_pm_opp_of_cpumask_remove_table(policy->cpus);
if (name)
- dev_pm_opp_put_regulator(opp_table);
+ dev_pm_opp_put_regulators(cpu_dev);
out_put_clk:
clk_put(cpu_clk);
@@ -304,7 +303,7 @@ static int cpufreq_exit(struct cpufreq_policy *policy)
dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
dev_pm_opp_of_cpumask_remove_table(policy->related_cpus);
if (priv->reg_name)
- dev_pm_opp_put_regulator(priv->opp_table);
+ dev_pm_opp_put_regulators(priv->cpu_dev);
clk_put(policy->clk);
kfree(priv);
diff --git b/drivers/cpufreq/ti-cpufreq.c b/drivers/cpufreq/ti-cpufreq.c
new file mode 100644
index 0000000..afbaef9
--- /dev/null
+++ b/drivers/cpufreq/ti-cpufreq.c
@@ -0,0 +1,288 @@
+/*
+ * TI CPUFreq/OPP hw-supported driver
+ *
+ * Copyright (C) 2016 Texas Instruments, Inc.
+ * Dave Gerlach <d-gerlach@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/cpu.h>
+#include <linux/io.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/pm_opp.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#define REVISION_MASK 0xF
+#define REVISION_SHIFT 28
+
+#define AM33XX_800M_ARM_MPU_MAX_FREQ 0x1E2F
+#define AM43XX_600M_ARM_MPU_MAX_FREQ 0xFFA
+
+#define DRA7_EFUSE_HAS_OD_MPU_OPP 11
+#define DRA7_EFUSE_HAS_HIGH_MPU_OPP 15
+#define DRA7_EFUSE_HAS_ALL_MPU_OPP 23
+
+#define DRA7_EFUSE_NOM_MPU_OPP BIT(0)
+#define DRA7_EFUSE_OD_MPU_OPP BIT(1)
+#define DRA7_EFUSE_HIGH_MPU_OPP BIT(2)
+
+#define VERSION_COUNT 2
+
+struct ti_cpufreq_data;
+
+struct ti_cpufreq_soc_data {
+ unsigned long (*efuse_xlate)(struct ti_cpufreq_data *opp_data,
+ unsigned long efuse);
+ unsigned long efuse_fallback;
+};
+
+struct ti_cpufreq_data {
+ struct device *cpu_dev;
+ struct device_node *opp_node;
+ struct regmap *opp_efuse;
+ struct regmap *revision;
+ const struct ti_cpufreq_soc_data *soc_data;
+};
+
+static unsigned long amx3_efuse_xlate(struct ti_cpufreq_data *opp_data,
+ unsigned long efuse)
+{
+ if (!efuse)
+ efuse = opp_data->soc_data->efuse_fallback;
+ /* AM335x and AM437x use "OPP disable" bits, so invert */
+ return ~efuse;
+}
+
+static unsigned long dra7_efuse_xlate(struct ti_cpufreq_data *opp_data,
+ unsigned long efuse)
+{
+ unsigned long calculated_efuse = DRA7_EFUSE_NOM_MPU_OPP;
+
+ /*
+ * The efuse on dra7 and am57 parts contains a specific
+ * value indicating the highest available OPP.
+ */
+
+ switch (efuse) {
+ case DRA7_EFUSE_HAS_ALL_MPU_OPP:
+ case DRA7_EFUSE_HAS_HIGH_MPU_OPP:
+ calculated_efuse |= DRA7_EFUSE_HIGH_MPU_OPP;
+ case DRA7_EFUSE_HAS_OD_MPU_OPP:
+ calculated_efuse |= DRA7_EFUSE_OD_MPU_OPP;
+ }
+
+ return calculated_efuse;
+}
+
+static struct ti_cpufreq_soc_data am3x_soc_data = {
+ .efuse_xlate = amx3_efuse_xlate,
+ .efuse_fallback = AM33XX_800M_ARM_MPU_MAX_FREQ,
+};
+
+static struct ti_cpufreq_soc_data am4x_soc_data = {
+ .efuse_xlate = amx3_efuse_xlate,
+ .efuse_fallback = AM43XX_600M_ARM_MPU_MAX_FREQ,
+};
+
+static struct ti_cpufreq_soc_data dra7_soc_data = {
+ .efuse_xlate = dra7_efuse_xlate,
+};
+
+/**
+ * ti_cpufreq_get_efuse() - Parse and return efuse value present on SoC
+ * @opp_data: pointer to ti_cpufreq_data context
+ * @efuse_value: Set to the value parsed from efuse
+ *
+ * Returns error code if efuse not read properly.
+ */
+static int ti_cpufreq_get_efuse(struct ti_cpufreq_data *opp_data,
+ u32 *efuse_value)
+{
+ struct device *dev = opp_data->cpu_dev;
+ struct device_node *np = opp_data->opp_node;
+ unsigned int efuse_offset;
+ u32 efuse, efuse_mask, efuse_shift, vals[4];
+ int ret;
+
+ ret = of_property_read_u32_array(np, "ti,syscon-efuse", vals, 4);
+ if (ret) {
+ dev_err(dev, "ti,syscon-efuse cannot be read %s: %d\n",
+ np->full_name, ret);
+ return ret;
+ }
+
+ efuse_offset = vals[1];
+ efuse_mask = vals[2];
+ efuse_shift = vals[3];
+
+ ret = regmap_read(opp_data->opp_efuse, efuse_offset, &efuse);
+ if (ret) {
+ dev_err(dev,
+ "Failed to read the efuse value from syscon: %d\n",
+ ret);
+ return ret;
+ }
+
+ efuse = (efuse & efuse_mask) >> efuse_shift;
+
+ *efuse_value = opp_data->soc_data->efuse_xlate(opp_data, efuse);
+
+ return 0;
+}
+
+/**
+ * ti_cpufreq_get_rev() - Parse and return rev value present on SoC
+ * @opp_data: pointer to ti_cpufreq_data context
+ * @revision_value: Set to the value parsed from revision register
+ *
+ * Returns error code if revision not read properly.
+ */
+static int ti_cpufreq_get_rev(struct ti_cpufreq_data *opp_data,
+ u32 *revision_value)
+{
+ struct device *dev = opp_data->cpu_dev;
+ struct device_node *np = opp_data->opp_node;
+ unsigned int revision_offset;
+ u32 revision;
+ int ret;
+
+ ret = of_property_read_u32_index(np, "ti,syscon-rev",
+ 1, &revision_offset);
+ if (ret) {
+ dev_err(dev,
+ "No revision offset provided %s [%d]\n",
+ np->full_name, ret);
+ return ret;
+ }
+
+ ret = regmap_read(opp_data->revision, revision_offset, &revision);
+ if (ret) {
+ dev_err(dev,
+ "Failed to read the revision number from syscon: %d\n",
+ ret);
+ return ret;
+ }
+
+ *revision_value = BIT((revision >> REVISION_SHIFT) & REVISION_MASK);
+
+ return 0;
+}
+
+static int ti_cpufreq_setup_syscon_registers(struct ti_cpufreq_data *opp_data)
+{
+ struct device *dev = opp_data->cpu_dev;
+ struct device_node *np = opp_data->opp_node;
+
+ opp_data->opp_efuse = syscon_regmap_lookup_by_phandle(np,
+ "ti,syscon-efuse");
+ if (IS_ERR(opp_data->opp_efuse)) {
+ dev_err(dev,
+ "\"ti,syscon-efuse\" is missing, cannot use OPPv2 table.\n");
+ return PTR_ERR(opp_data->opp_efuse);
+ }
+
+ opp_data->revision = syscon_regmap_lookup_by_phandle(np,
+ "ti,syscon-rev");
+ if (IS_ERR(opp_data->revision)) {
+ dev_err(dev,
+ "\"ti,syscon-rev\" is missing, cannot use OPPv2 table.\n");
+ return PTR_ERR(opp_data->revision);
+ }
+
+ return 0;
+}
+
+static const struct of_device_id ti_cpufreq_of_match[] = {
+ { .compatible = "ti,am33xx", .data = &am3x_soc_data, },
+ { .compatible = "ti,am4372", .data = &am4x_soc_data, },
+ { .compatible = "ti,dra7", .data = &dra7_soc_data },
+ {},
+};
+
+static int ti_cpufreq_init(void)
+{
+ u32 version[VERSION_COUNT];
+ struct device_node *np;
+ const struct of_device_id *match;
+ struct ti_cpufreq_data *opp_data;
+ int ret;
+
+ np = of_find_node_by_path("/");
+ match = of_match_node(ti_cpufreq_of_match, np);
+ if (!match)
+ return -ENODEV;
+
+ opp_data = kzalloc(sizeof(*opp_data), GFP_KERNEL);
+ if (!opp_data)
+ return -ENOMEM;
+
+ opp_data->soc_data = match->data;
+
+ opp_data->cpu_dev = get_cpu_device(0);
+ if (!opp_data->cpu_dev) {
+ pr_err("%s: Failed to get device for CPU0\n", __func__);
+ return -ENODEV;
+ }
+
+ opp_data->opp_node = dev_pm_opp_of_get_opp_desc_node(opp_data->cpu_dev);
+ if (!opp_data->opp_node) {
+ dev_info(opp_data->cpu_dev,
+ "OPP-v2 not supported, cpufreq-dt will attempt to use legacy tables.\n");
+ goto register_cpufreq_dt;
+ }
+
+ ret = ti_cpufreq_setup_syscon_registers(opp_data);
+ if (ret)
+ goto fail_put_node;
+
+ /*
+ * OPPs determine whether or not they are supported based on
+ * two metrics:
+ * 0 - SoC Revision
+ * 1 - eFuse value
+ */
+ ret = ti_cpufreq_get_rev(opp_data, &version[0]);
+ if (ret)
+ goto fail_put_node;
+
+ ret = ti_cpufreq_get_efuse(opp_data, &version[1]);
+ if (ret)
+ goto fail_put_node;
+
+ of_node_put(opp_data->opp_node);
+
+ ret = dev_pm_opp_set_supported_hw(opp_data->cpu_dev, version,
+ VERSION_COUNT);
+ if (ret) {
+ dev_err(opp_data->cpu_dev,
+ "Failed to set supported hardware\n");
+ goto fail_put_node;
+ }
+
+register_cpufreq_dt:
+ platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
+
+ return 0;
+
+fail_put_node:
+ of_node_put(opp_data->opp_node);
+
+ return ret;
+}
+module_init(ti_cpufreq_init);
+
+MODULE_DESCRIPTION("TI CPUFreq/OPP hw-supported driver");
+MODULE_AUTHOR("Dave Gerlach <d-gerlach@ti.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index ed37e59..a118ef6 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -61,6 +61,20 @@ config GPIO_SYSFS
Kernel drivers may also request that a particular GPIO be
exported to userspace; this can be useful when debugging.
+config GPIO_OF_HELPER
+ bool "GPIO OF helper device (EXPERIMENTAL)"
+ depends on OF_GPIO
+ help
+ Say Y here to add an GPIO OF helper driver
+
+ Allows you specify a GPIO helper based on OF
+ which allows simple export of GPIO functionality
+ in user-space.
+
+ Features include, value set/get, direction control,
+ interrupt/value change poll support, event counting
+ and others.
+
config GPIO_GENERIC
depends on HAS_IOMEM # Only for IOMEM drivers
tristate
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index d074c22..e4e13b8 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_GPIOLIB) += gpiolib-legacy.o
obj-$(CONFIG_OF_GPIO) += gpiolib-of.o
obj-$(CONFIG_GPIO_SYSFS) += gpiolib-sysfs.o
obj-$(CONFIG_GPIO_ACPI) += gpiolib-acpi.o
+obj-$(CONFIG_GPIO_OF_HELPER) += gpio-of-helper.o
# Device drivers. Generally keep list sorted alphabetically
obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o
diff --git b/drivers/gpio/gpio-of-helper.c b/drivers/gpio/gpio-of-helper.c
new file mode 100644
index 0000000..83f362f
--- /dev/null
+++ b/drivers/gpio/gpio-of-helper.c
@@ -0,0 +1,435 @@
+/*
+ * GPIO OF based helper
+ *
+ * A simple DT based driver to provide access to GPIO functionality
+ * to user-space via sysfs.
+ *
+ * Copyright (C) 2013 Pantelis Antoniou <panto@antoniou-consulting.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/atomic.h>
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/math64.h>
+#include <linux/atomic.h>
+#include <linux/idr.h>
+
+/* fwd decl. */
+struct gpio_of_helper_info;
+
+enum gpio_type {
+ GPIO_TYPE_INPUT = 0,
+ GPIO_TYPE_OUTPUT = 1,
+};
+
+struct gpio_of_entry {
+ int id;
+ struct gpio_of_helper_info *info;
+ struct device_node *node;
+ enum gpio_type type;
+ int gpio;
+ int irq;
+ const char *name;
+ atomic64_t counter;
+ unsigned int count_flags;
+#define COUNT_RISING_EDGE (1 << 0)
+#define COUNT_FALLING_EDGE (1 << 1)
+};
+
+struct gpio_of_helper_info {
+ struct platform_device *pdev;
+ struct idr idr;
+};
+
+static const struct of_device_id gpio_of_helper_of_match[] = {
+ {
+ .compatible = "gpio-of-helper",
+ },
+ { },
+};
+MODULE_DEVICE_TABLE(of, gpio_of_helper_of_match);
+
+static ssize_t gpio_of_helper_show_status(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct gpio_of_helper_info *info = platform_get_drvdata(pdev);
+ struct gpio_of_entry *entry;
+ char *p, *e;
+ int id, n;
+
+ p = buf;
+ e = p + PAGE_SIZE;
+ n = 0;
+ idr_for_each_entry(&info->idr, entry, id) {
+ switch (entry->type) {
+ case GPIO_TYPE_INPUT:
+ n = snprintf(p, e - p, "%2d %-24s %3d %-3s %llu\n",
+ entry->id, entry->name, entry->gpio, "IN",
+ (unsigned long long)
+ atomic64_read(&entry->counter));
+ break;
+ case GPIO_TYPE_OUTPUT:
+ n = snprintf(p, e - p, "%2d %-24s %3d %-3s\n",
+ entry->id, entry->name, entry->gpio, "OUT");
+ break;
+ }
+ p += n;
+ }
+
+ return p - buf;
+}
+
+static DEVICE_ATTR(status, S_IRUGO,
+ gpio_of_helper_show_status, NULL);
+
+static irqreturn_t gpio_of_helper_handler(int irq, void *ptr)
+{
+ struct gpio_of_entry *entry = ptr;
+
+ /* caution - low speed interfaces only! */
+ atomic64_inc(&entry->counter);
+
+ return IRQ_HANDLED;
+}
+
+static struct gpio_of_entry *
+gpio_of_entry_create(struct gpio_of_helper_info *info,
+ struct device_node *node)
+{
+ struct platform_device *pdev = info->pdev;
+ struct device *dev = &pdev->dev;
+ struct gpio_of_entry *entry;
+ int err, gpio, irq;
+ unsigned int req_flags, count_flags, irq_flags;
+ enum gpio_type type;
+ enum of_gpio_flags gpio_flags;
+ const char *name;
+
+ /* get the type of the node first */
+ if (of_property_read_bool(node, "input"))
+ type = GPIO_TYPE_INPUT;
+ else if (of_property_read_bool(node, "output")
+ || of_property_read_bool(node, "init-low")
+ || of_property_read_bool(node, "init-high"))
+ type = GPIO_TYPE_OUTPUT;
+ else {
+ dev_err(dev, "Not valid gpio node type\n");
+ err = -EINVAL;
+ goto err_bad_node;
+ }
+
+ /* get the name */
+ if (of_property_read_string(node, "line-name", &name))
+ if (of_property_read_string(node, "gpio-name", &name))
+ name = node->name;
+
+ err = of_get_named_gpio_flags(node, "gpio", 0, &gpio_flags);
+ if (IS_ERR_VALUE(err)) {
+ dev_err(dev, "Failed to get gpio property of '%s'\n", name);
+ goto err_bad_node;
+ }
+ gpio = err;
+
+ req_flags = 0;
+ count_flags = 0;
+
+ /* set the request flags */
+ switch (type) {
+ case GPIO_TYPE_INPUT:
+ req_flags = GPIOF_DIR_IN | GPIOF_EXPORT;
+ if (of_property_read_bool(node, "count-falling-edge"))
+ count_flags |= COUNT_FALLING_EDGE;
+ if (of_property_read_bool(node, "count-rising-edge"))
+ count_flags |= COUNT_RISING_EDGE;
+ break;
+ case GPIO_TYPE_OUTPUT:
+ req_flags = GPIOF_DIR_OUT | GPIOF_EXPORT;
+ if (of_property_read_bool(node, "init-high"))
+ req_flags |= GPIOF_OUT_INIT_HIGH;
+ else if (of_property_read_bool(node, "init-low"))
+ req_flags |= GPIOF_OUT_INIT_LOW;
+ break;
+ }
+ if (of_property_read_bool(node, "dir-changeable"))
+ req_flags |= GPIOF_EXPORT_CHANGEABLE;
+ if (gpio_flags & OF_GPIO_ACTIVE_LOW)
+ req_flags |= GPIOF_ACTIVE_LOW;
+ if (gpio_flags & OF_GPIO_SINGLE_ENDED) {
+ if (gpio_flags & OF_GPIO_ACTIVE_LOW)
+ req_flags |= GPIOF_OPEN_DRAIN;
+ else
+ req_flags |= GPIOF_OPEN_SOURCE;
+ }
+
+ /* request the gpio */
+ err = devm_gpio_request_one(dev, gpio, req_flags, name);
+ if (err != 0) {
+ dev_err(dev, "Failed to request gpio '%s'\n", name);
+ goto err_bad_node;
+ }
+
+ irq = -1;
+ irq_flags = 0;
+
+ /* counter mode requested - need an interrupt */
+ if (count_flags != 0) {
+ irq = gpio_to_irq(gpio);
+ if (IS_ERR_VALUE(irq)) {
+ dev_err(dev, "Failed to request gpio '%s'\n", name);
+ goto err_bad_node;
+ }
+
+ if (count_flags & COUNT_RISING_EDGE)
+ irq_flags |= IRQF_TRIGGER_RISING;
+ if (count_flags & COUNT_FALLING_EDGE)
+ irq_flags |= IRQF_TRIGGER_FALLING;
+ }
+
+// if (!idr_pre_get(&info->idr, GFP_KERNEL)) {
+// dev_err(dev, "Failed on idr_pre_get of '%s'\n", name);
+// err = -ENOMEM;
+// goto err_no_mem;
+// }
+
+ idr_preload(GFP_KERNEL);
+
+ entry = devm_kzalloc(dev, sizeof(*entry), GFP_KERNEL);
+ if (entry == NULL) {
+ dev_err(dev, "Failed to allocate gpio entry of '%s'\n", name);
+ err = -ENOMEM;
+ goto err_no_mem;
+ }
+
+ entry->id = -1;
+ entry->info = info;
+ entry->node = of_node_get(node); /* get node reference */
+ entry->type = type;
+ entry->gpio = gpio;
+ entry->irq = irq;
+ entry->name = name;
+
+ /* interrupt enable is last thing done */
+ if (irq >= 0) {
+ atomic64_set(&entry->counter, 0);
+ entry->count_flags = count_flags;
+ err = devm_request_irq(dev, irq, gpio_of_helper_handler,
+ irq_flags, name, entry);
+ if (err != 0) {
+ dev_err(dev, "Failed to request irq of '%s'\n", name);
+ goto err_no_irq;
+ }
+ }
+
+ /* all done; insert */
+// err = idr_get_new(&info->idr, entry, &entry->id);
+// if (IS_ERR_VALUE(err)) {
+// dev_err(dev, "Failed to idr_get_new of '%s'\n", name);
+// goto err_fail_idr;
+// }
+
+ err = idr_alloc(&info->idr, entry, 0, 0, GFP_NOWAIT);
+ if (err >= 0)
+ entry->id = err;
+
+ idr_preload_end();
+
+ if (err < 0) {
+ dev_err(dev, "Failed to idr_get_new of '%s'\n", name);
+ goto err_fail_idr;
+ }
+
+ dev_dbg(dev, "Allocated GPIO id=%d name='%s'\n", entry->id, name);
+
+ return entry;
+
+err_fail_idr:
+ /* nothing to do */
+err_no_irq:
+ /* release node ref */
+ of_node_put(node);
+ /* nothing else needs to be done, devres handles it */
+err_no_mem:
+err_bad_node:
+ return ERR_PTR(err);
+}
+
+static int gpio_of_entry_destroy(struct gpio_of_entry *entry)
+{
+ struct gpio_of_helper_info *info = entry->info;
+ struct platform_device *pdev = info->pdev;
+ struct device *dev = &pdev->dev;
+
+ dev_dbg(dev, "Destroying GPIO id=%d\n", entry->id);
+
+ /* remove from the IDR */
+ idr_remove(&info->idr, entry->id);
+
+ /* remove node ref */
+ of_node_put(entry->node);
+
+ /* free gpio */
+ devm_gpio_free(dev, entry->gpio);
+
+ /* gree irq */
+ if (entry->irq >= 0)
+ devm_free_irq(dev, entry->irq, entry);
+
+ /* and free */
+ devm_kfree(dev, entry);
+
+ return 0;
+}
+
+static int gpio_of_helper_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct gpio_of_helper_info *info;
+ struct gpio_of_entry *entry;
+ struct device_node *pnode = pdev->dev.of_node;
+ struct device_node *cnode;
+ struct pinctrl *pinctrl;
+ int err;
+
+ /* we only support OF */
+ if (pnode == NULL) {
+ dev_err(&pdev->dev, "No platform of_node!\n");
+ return -ENODEV;
+ }
+
+ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+ if (IS_ERR(pinctrl)) {
+ /* special handling for probe defer */
+ if (PTR_ERR(pinctrl) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+
+ dev_warn(&pdev->dev,
+ "pins are not configured from the driver\n");
+ }
+
+ info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+ if (info == NULL) {
+ dev_err(&pdev->dev, "Failed to allocate info\n");
+ err = -ENOMEM;
+ goto err_no_mem;
+ }
+ platform_set_drvdata(pdev, info);
+ info->pdev = pdev;
+
+ idr_init(&info->idr);
+
+ err = device_create_file(dev, &dev_attr_status);
+ if (err != 0) {
+ dev_err(dev, "Failed to create status sysfs attribute\n");
+ goto err_no_sysfs;
+ }
+
+ for_each_child_of_node(pnode, cnode) {
+
+ entry = gpio_of_entry_create(info, cnode);
+ if (IS_ERR_OR_NULL(entry)) {
+ dev_err(dev, "Failed to create gpio entry\n");
+ err = PTR_ERR(entry);
+ goto err_fail_entry;
+ }
+ }
+
+ dev_info(&pdev->dev, "ready\n");
+
+ return 0;
+err_fail_entry:
+ device_remove_file(&pdev->dev, &dev_attr_status);
+err_no_sysfs:
+err_no_mem:
+ return err;
+}
+
+static int gpio_of_helper_remove(struct platform_device *pdev)
+{
+ struct gpio_of_helper_info *info = platform_get_drvdata(pdev);
+ struct gpio_of_entry *entry;
+ int id;
+
+ dev_info(&pdev->dev, "removing\n");
+
+ device_remove_file(&pdev->dev, &dev_attr_status);
+
+ id = 0;
+ idr_for_each_entry(&info->idr, entry, id) {
+ /* destroy each and every one */
+ gpio_of_entry_destroy(entry);
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+//#ifdef CONFIG_PM_RUNTIME
+static int gpio_of_helper_runtime_suspend(struct device *dev)
+{
+ /* place holder */
+ return 0;
+}
+
+static int gpio_of_helper_runtime_resume(struct device *dev)
+{
+ /* place holder */
+ return 0;
+}
+//#endif /* CONFIG_PM_RUNTIME */
+
+static struct dev_pm_ops gpio_of_helper_pm_ops = {
+ SET_RUNTIME_PM_OPS(gpio_of_helper_runtime_suspend,
+ gpio_of_helper_runtime_resume, NULL)
+};
+#define GPIO_OF_HELPER_PM_OPS (&gpio_of_helper_pm_ops)
+#else
+#define GPIO_OF_HELPER_PM_OPS NULL
+#endif /* CONFIG_PM */
+
+struct platform_driver gpio_of_helper_driver = {
+ .probe = gpio_of_helper_probe,
+ .remove = gpio_of_helper_remove,
+ .driver = {
+ .name = "gpio-of-helper",
+ .owner = THIS_MODULE,
+ .pm = GPIO_OF_HELPER_PM_OPS,
+ .of_match_table = gpio_of_helper_of_match,
+ },
+};
+
+module_platform_driver(gpio_of_helper_driver);
+
+MODULE_AUTHOR("Pantelis Antoniou <panto@antoniou-consulting.com>");
+MODULE_DESCRIPTION("GPIO OF Helper driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:gpio-of-helper");
diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c
index 4b44dd9..9c6de28 100644
--- a/drivers/gpio/gpiolib-sysfs.c
+++ b/drivers/gpio/gpiolib-sysfs.c
@@ -35,10 +35,10 @@ static DEFINE_MUTEX(sysfs_lock);
/*
* /sys/class/gpio/gpioN... only for GPIOs that are exported
* /direction
- * * MAY BE OMITTED if kernel won't allow direction changes
* * is read/write as "in" or "out"
* * may also be written as "high" or "low", initializing
* output value as specified ("out" implies "low")
+ * * read-only if kernel won't allow direction changes
* /value
* * always readable, subject to hardware behavior
* * may be writable, as zero/nonzero
@@ -51,6 +51,8 @@ static DEFINE_MUTEX(sysfs_lock);
* * is read/write as zero/nonzero
* * also affects existing and subsequent "falling" and "rising"
* /edge configuration
+ * /label
+ * * descriptor label
*/
static ssize_t direction_show(struct device *dev,
@@ -81,7 +83,9 @@ static ssize_t direction_store(struct device *dev,
mutex_lock(&data->mutex);
- if (sysfs_streq(buf, "high"))
+ if (!data->direction_can_change)
+ status = -EPERM;
+ else if (sysfs_streq(buf, "high"))
status = gpiod_direction_output_raw(desc, 1);
else if (sysfs_streq(buf, "out") || sysfs_streq(buf, "low"))
status = gpiod_direction_output_raw(desc, 0);
@@ -350,6 +354,23 @@ static ssize_t active_low_store(struct device *dev,
}
static DEVICE_ATTR_RW(active_low);
+static ssize_t label_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct gpiod_data *data = dev_get_drvdata(dev);
+ struct gpio_desc *desc = data->desc;
+ ssize_t status;
+
+ mutex_lock(&data->mutex);
+
+ status = sprintf(buf, "%s\n", desc->label);
+
+ mutex_unlock(&data->mutex);
+
+ return status;
+}
+static DEVICE_ATTR_RO(label);
+
static umode_t gpio_is_visible(struct kobject *kobj, struct attribute *attr,
int n)
{
@@ -361,12 +382,15 @@ static umode_t gpio_is_visible(struct kobject *kobj, struct attribute *attr,
if (attr == &dev_attr_direction.attr) {
if (!show_direction)
- mode = 0;
+ mode &= 0444;
} else if (attr == &dev_attr_edge.attr) {
if (gpiod_to_irq(desc) < 0)
mode = 0;
if (!show_direction && test_bit(FLAG_IS_OUT, &desc->flags))
mode = 0;
+ } else if (attr == &dev_attr_value.attr) {
+ if (!show_direction && !test_bit(FLAG_IS_OUT, &desc->flags))
+ mode &= 0444;
}
return mode;
@@ -377,6 +401,7 @@ static struct attribute *gpio_attrs[] = {
&dev_attr_edge.attr,
&dev_attr_value.attr,
&dev_attr_active_low.attr,
+ &dev_attr_label.attr,
NULL,
};
@@ -390,6 +415,10 @@ static const struct attribute_group *gpio_groups[] = {
NULL
};
+/* bwlegh, a second device in the same file... get out of my namespace! */
+#define dev_attr_label dev_attr_chip_label
+#define label_show chip_label_show
+
/*
* /sys/class/gpio/gpiochipN/
* /base ... matching gpio_chip.base (N)
diff --git a/drivers/gpu/drm/etnaviv/Kconfig b/drivers/gpu/drm/etnaviv/Kconfig
index 2cde7a5..b776f41 100644
--- a/drivers/gpu/drm/etnaviv/Kconfig
+++ b/drivers/gpu/drm/etnaviv/Kconfig
@@ -2,7 +2,7 @@
config DRM_ETNAVIV
tristate "ETNAVIV (DRM support for Vivante GPU IP cores)"
depends on DRM
- depends on ARCH_MXC || ARCH_DOVE
+ depends on ARCH_MXC || ARCH_DOVE || ARCH_OMAP2PLUS
select SHMEM
select TMPFS
select IOMMU_API
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
index aa68766..20d20ca 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
@@ -654,6 +654,7 @@ static int etnaviv_pdev_remove(struct platform_device *pdev)
static const struct of_device_id dt_match[] = {
{ .compatible = "fsl,imx-gpu-subsystem" },
{ .compatible = "marvell,dove-gpu-subsystem" },
+ { .compatible = "vivante,gc-gpu-subsystem"},
{}
};
MODULE_DEVICE_TABLE(of, dt_match);
diff --git a/drivers/gpu/drm/i2c/Kconfig b/drivers/gpu/drm/i2c/Kconfig
index a6c92be..66ff8e3 100644
--- a/drivers/gpu/drm/i2c/Kconfig
+++ b/drivers/gpu/drm/i2c/Kconfig
@@ -1,6 +1,12 @@
menu "I2C encoder or helper chips"
depends on DRM && DRM_KMS_HELPER && I2C
+config DRM_I2C_ADIHDMI
+ tristate "ADI HDMI encoder"
+ default m if DRM_TILCDC
+ help
+ Support for ADI HDMI encoder.
+
config DRM_I2C_CH7006
tristate "Chrontel ch7006 TV encoder"
default m if DRM_NOUVEAU
diff --git a/drivers/gpu/drm/i2c/Makefile b/drivers/gpu/drm/i2c/Makefile
index 43aa33b..62a4eea 100644
--- a/drivers/gpu/drm/i2c/Makefile
+++ b/drivers/gpu/drm/i2c/Makefile
@@ -8,3 +8,6 @@ obj-$(CONFIG_DRM_I2C_SIL164) += sil164.o
tda998x-y := tda998x_drv.o
obj-$(CONFIG_DRM_I2C_NXP_TDA998X) += tda998x.o
+
+adihdmi-y := adihdmi_drv.o
+obj-$(CONFIG_DRM_I2C_ADIHDMI) += adihdmi.o
diff --git b/drivers/gpu/drm/i2c/adihdmi.h b/drivers/gpu/drm/i2c/adihdmi.h
new file mode 100644
index 0000000..58d9a2b
--- /dev/null
+++ b/drivers/gpu/drm/i2c/adihdmi.h
@@ -0,0 +1,289 @@
+/*
+ * Analog Devices ADIHDMI HDMI transmitter driver
+ *
+ * Copyright 2012 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#ifndef __DRM_I2C_ADIHDMI_H__
+#define __DRM_I2C_ADIHDMI_H__
+
+#include <linux/hdmi.h>
+
+#define ADIHDMI_REG_CHIP_REVISION 0x00
+#define ADIHDMI_REG_N0 0x01
+#define ADIHDMI_REG_N1 0x02
+#define ADIHDMI_REG_N2 0x03
+#define ADIHDMI_REG_SPDIF_FREQ 0x04
+#define ADIHDMI_REG_CTS_AUTOMATIC1 0x05
+#define ADIHDMI_REG_CTS_AUTOMATIC2 0x06
+#define ADIHDMI_REG_CTS_MANUAL0 0x07
+#define ADIHDMI_REG_CTS_MANUAL1 0x08
+#define ADIHDMI_REG_CTS_MANUAL2 0x09
+#define ADIHDMI_REG_AUDIO_SOURCE 0x0a
+#define ADIHDMI_REG_AUDIO_CONFIG 0x0b
+#define ADIHDMI_REG_I2S_CONFIG 0x0c
+#define ADIHDMI_REG_I2S_WIDTH 0x0d
+#define ADIHDMI_REG_AUDIO_SUB_SRC0 0x0e
+#define ADIHDMI_REG_AUDIO_SUB_SRC1 0x0f
+#define ADIHDMI_REG_AUDIO_SUB_SRC2 0x10
+#define ADIHDMI_REG_AUDIO_SUB_SRC3 0x11
+#define ADIHDMI_REG_AUDIO_CFG1 0x12
+#define ADIHDMI_REG_AUDIO_CFG2 0x13
+#define ADIHDMI_REG_AUDIO_CFG3 0x14
+#define ADIHDMI_REG_I2C_FREQ_ID_CFG 0x15
+#define ADIHDMI_REG_VIDEO_INPUT_CFG1 0x16
+#define ADIHDMI_REG_CSC_UPPER(x) (0x18 + (x) * 2)
+#define ADIHDMI_REG_CSC_LOWER(x) (0x19 + (x) * 2)
+#define ADIHDMI_REG_SYNC_DECODER(x) (0x30 + (x))
+#define ADIHDMI_REG_DE_GENERATOR (0x35 + (x))
+#define ADIHDMI_REG_PIXEL_REPETITION 0x3b
+#define ADIHDMI_REG_VIC_MANUAL 0x3c
+#define ADIHDMI_REG_VIC_SEND 0x3d
+#define ADIHDMI_REG_VIC_DETECTED 0x3e
+#define ADIHDMI_REG_AUX_VIC_DETECTED 0x3f
+#define ADIHDMI_REG_PACKET_ENABLE0 0x40
+#define ADIHDMI_REG_POWER 0x41
+#define ADIHDMI_REG_STATUS 0x42
+#define ADIHDMI_REG_EDID_I2C_ADDR 0x43
+#define ADIHDMI_REG_PACKET_ENABLE1 0x44
+#define ADIHDMI_REG_PACKET_I2C_ADDR 0x45
+#define ADIHDMI_REG_DSD_ENABLE 0x46
+#define ADIHDMI_REG_VIDEO_INPUT_CFG2 0x48
+#define ADIHDMI_REG_INFOFRAME_UPDATE 0x4a
+#define ADIHDMI_REG_GC(x) (0x4b + (x)) /* 0x4b - 0x51 */
+#define ADIHDMI_REG_AVI_INFOFRAME_VERSION 0x52
+#define ADIHDMI_REG_AVI_INFOFRAME_LENGTH 0x53
+#define ADIHDMI_REG_AVI_INFOFRAME_CHECKSUM 0x54
+#define ADIHDMI_REG_AVI_INFOFRAME(x) (0x55 + (x)) /* 0x55 - 0x6f */
+#define ADIHDMI_REG_AUDIO_INFOFRAME_VERSION 0x70
+#define ADIHDMI_REG_AUDIO_INFOFRAME_LENGTH 0x71
+#define ADIHDMI_REG_AUDIO_INFOFRAME_CHECKSUM 0x72
+#define ADIHDMI_REG_AUDIO_INFOFRAME(x) (0x73 + (x)) /* 0x73 - 0x7c */
+#define ADIHDMI_REG_INT_ENABLE(x) (0x94 + (x))
+#define ADIHDMI_REG_INT(x) (0x96 + (x))
+#define ADIHDMI_REG_INPUT_CLK_DIV 0x9d
+#define ADIHDMI_REG_PLL_STATUS 0x9e
+#define ADIHDMI_REG_HDMI_POWER 0xa1
+#define ADIHDMI_REG_HDCP_HDMI_CFG 0xaf
+#define ADIHDMI_REG_AN(x) (0xb0 + (x)) /* 0xb0 - 0xb7 */
+#define ADIHDMI_REG_HDCP_STATUS 0xb8
+#define ADIHDMI_REG_BCAPS 0xbe
+#define ADIHDMI_REG_BKSV(x) (0xc0 + (x)) /* 0xc0 - 0xc3 */
+#define ADIHDMI_REG_EDID_SEGMENT 0xc4
+#define ADIHDMI_REG_DDC_STATUS 0xc8
+#define ADIHDMI_REG_EDID_READ_CTRL 0xc9
+#define ADIHDMI_REG_BSTATUS(x) (0xca + (x)) /* 0xca - 0xcb */
+#define ADIHDMI_REG_TIMING_GEN_SEQ 0xd0
+#define ADIHDMI_REG_POWER2 0xd6
+#define ADIHDMI_REG_HSYNC_PLACEMENT_MSB 0xfa
+
+#define ADIHDMI_REG_SYNC_ADJUSTMENT(x) (0xd7 + (x)) /* 0xd7 - 0xdc */
+#define ADIHDMI_REG_TMDS_CLOCK_INV 0xde
+#define ADIHDMI_REG_ARC_CTRL 0xdf
+#define ADIHDMI_REG_CEC_I2C_ADDR 0xe1
+#define ADIHDMI_REG_CEC_CTRL 0xe2
+#define ADIHDMI_REG_CHIP_ID_HIGH 0xf5
+#define ADIHDMI_REG_CHIP_ID_LOW 0xf6
+
+#define ADIHDMI_CSC_ENABLE BIT(7)
+#define ADIHDMI_CSC_UPDATE_MODE BIT(5)
+
+#define ADIHDMI_INT0_HDP BIT(7)
+#define ADIHDMI_INT0_VSYNC BIT(5)
+#define ADIHDMI_INT0_AUDIO_FIFO_FULL BIT(4)
+#define ADIHDMI_INT0_EDID_READY BIT(2)
+#define ADIHDMI_INT0_HDCP_AUTHENTICATED BIT(1)
+
+#define ADIHDMI_INT1_DDC_ERROR BIT(7)
+#define ADIHDMI_INT1_BKSV BIT(6)
+#define ADIHDMI_INT1_CEC_TX_READY BIT(5)
+#define ADIHDMI_INT1_CEC_TX_ARBIT_LOST BIT(4)
+#define ADIHDMI_INT1_CEC_TX_RETRY_TIMEOUT BIT(3)
+#define ADIHDMI_INT1_CEC_RX_READY3 BIT(2)
+#define ADIHDMI_INT1_CEC_RX_READY2 BIT(1)
+#define ADIHDMI_INT1_CEC_RX_READY1 BIT(0)
+
+#define ADIHDMI_ARC_CTRL_POWER_DOWN BIT(0)
+
+#define ADIHDMI_CEC_CTRL_POWER_DOWN BIT(0)
+
+#define ADIHDMI_POWER_POWER_DOWN BIT(6)
+
+#define ADIHDMI_HDMI_CFG_MODE_MASK 0x2
+#define ADIHDMI_HDMI_CFG_MODE_DVI 0x0
+#define ADIHDMI_HDMI_CFG_MODE_HDMI 0x2
+
+#define ADIHDMI_AUDIO_SELECT_I2C 0x0
+#define ADIHDMI_AUDIO_SELECT_SPDIF 0x1
+#define ADIHDMI_AUDIO_SELECT_DSD 0x2
+#define ADIHDMI_AUDIO_SELECT_HBR 0x3
+#define ADIHDMI_AUDIO_SELECT_DST 0x4
+
+#define ADIHDMI_I2S_SAMPLE_LEN_16 0x2
+#define ADIHDMI_I2S_SAMPLE_LEN_20 0x3
+#define ADIHDMI_I2S_SAMPLE_LEN_18 0x4
+#define ADIHDMI_I2S_SAMPLE_LEN_22 0x5
+#define ADIHDMI_I2S_SAMPLE_LEN_19 0x8
+#define ADIHDMI_I2S_SAMPLE_LEN_23 0x9
+#define ADIHDMI_I2S_SAMPLE_LEN_24 0xb
+#define ADIHDMI_I2S_SAMPLE_LEN_17 0xc
+#define ADIHDMI_I2S_SAMPLE_LEN_21 0xd
+
+#define ADIHDMI_SAMPLE_FREQ_44100 0x0
+#define ADIHDMI_SAMPLE_FREQ_48000 0x2
+#define ADIHDMI_SAMPLE_FREQ_32000 0x3
+#define ADIHDMI_SAMPLE_FREQ_88200 0x8
+#define ADIHDMI_SAMPLE_FREQ_96000 0xa
+#define ADIHDMI_SAMPLE_FREQ_176400 0xc
+#define ADIHDMI_SAMPLE_FREQ_192000 0xe
+
+#define ADIHDMI_STATUS_POWER_DOWN_POLARITY BIT(7)
+#define ADIHDMI_STATUS_HPD BIT(6)
+#define ADIHDMI_STATUS_MONITOR_SENSE BIT(5)
+#define ADIHDMI_STATUS_I2S_32BIT_MODE BIT(3)
+
+#define ADIHDMI_PACKET_ENABLE_N_CTS BIT(8+6)
+#define ADIHDMI_PACKET_ENABLE_AUDIO_SAMPLE BIT(8+5)
+#define ADIHDMI_PACKET_ENABLE_AVI_INFOFRAME BIT(8+4)
+#define ADIHDMI_PACKET_ENABLE_AUDIO_INFOFRAME BIT(8+3)
+#define ADIHDMI_PACKET_ENABLE_GC BIT(7)
+#define ADIHDMI_PACKET_ENABLE_SPD BIT(6)
+#define ADIHDMI_PACKET_ENABLE_MPEG BIT(5)
+#define ADIHDMI_PACKET_ENABLE_ACP BIT(4)
+#define ADIHDMI_PACKET_ENABLE_ISRC BIT(3)
+#define ADIHDMI_PACKET_ENABLE_GM BIT(2)
+#define ADIHDMI_PACKET_ENABLE_SPARE2 BIT(1)
+#define ADIHDMI_PACKET_ENABLE_SPARE1 BIT(0)
+
+#define ADIHDMI_REG_POWER2_HDP_SRC_MASK 0xc0
+#define ADIHDMI_REG_POWER2_HDP_SRC_BOTH 0x00
+#define ADIHDMI_REG_POWER2_HDP_SRC_HDP 0x40
+#define ADIHDMI_REG_POWER2_HDP_SRC_CEC 0x80
+#define ADIHDMI_REG_POWER2_HDP_SRC_NONE 0xc0
+#define ADIHDMI_REG_POWER2_TDMS_ENABLE BIT(4)
+#define ADIHDMI_REG_POWER2_GATE_INPUT_CLK BIT(0)
+
+#define ADIHDMI_LOW_REFRESH_RATE_NONE 0x0
+#define ADIHDMI_LOW_REFRESH_RATE_24HZ 0x1
+#define ADIHDMI_LOW_REFRESH_RATE_25HZ 0x2
+#define ADIHDMI_LOW_REFRESH_RATE_30HZ 0x3
+
+#define ADIHDMI_AUDIO_CFG3_LEN_MASK 0x0f
+#define ADIHDMI_I2C_FREQ_ID_CFG_RATE_MASK 0xf0
+
+#define ADIHDMI_AUDIO_SOURCE_I2S 0
+#define ADIHDMI_AUDIO_SOURCE_SPDIF 1
+
+#define ADIHDMI_I2S_FORMAT_I2S 0
+#define ADIHDMI_I2S_FORMAT_RIGHT_J 1
+#define ADIHDMI_I2S_FORMAT_LEFT_J 2
+
+#define ADIHDMI_PACKET(p, x) ((p) * 0x20 + (x))
+#define ADIHDMI_PACKET_SDP(x) ADIHDMI_PACKET(0, x)
+#define ADIHDMI_PACKET_MPEG(x) ADIHDMI_PACKET(1, x)
+#define ADIHDMI_PACKET_ACP(x) ADIHDMI_PACKET(2, x)
+#define ADIHDMI_PACKET_ISRC1(x) ADIHDMI_PACKET(3, x)
+#define ADIHDMI_PACKET_ISRC2(x) ADIHDMI_PACKET(4, x)
+#define ADIHDMI_PACKET_GM(x) ADIHDMI_PACKET(5, x)
+#define ADIHDMI_PACKET_SPARE(x) ADIHDMI_PACKET(6, x)
+
+enum adihdmi_input_clock {
+ ADIHDMI_INPUT_CLOCK_1X,
+ ADIHDMI_INPUT_CLOCK_2X,
+ ADIHDMI_INPUT_CLOCK_DDR,
+};
+
+enum adihdmi_input_justification {
+ ADIHDMI_INPUT_JUSTIFICATION_EVENLY = 0,
+ ADIHDMI_INPUT_JUSTIFICATION_RIGHT = 1,
+ ADIHDMI_INPUT_JUSTIFICATION_LEFT = 2,
+};
+
+enum adihdmi_input_sync_pulse {
+ ADIHDMI_INPUT_SYNC_PULSE_DE = 0,
+ ADIHDMI_INPUT_SYNC_PULSE_HSYNC = 1,
+ ADIHDMI_INPUT_SYNC_PULSE_VSYNC = 2,
+ ADIHDMI_INPUT_SYNC_PULSE_NONE = 3,
+};
+
+/**
+ * enum adihdmi_sync_polarity - Polarity for the input sync signals
+ * @ADIHDMI_SYNC_POLARITY_PASSTHROUGH: Sync polarity matches that of
+ * the currently configured mode.
+ * @ADIHDMI_SYNC_POLARITY_LOW: Sync polarity is low
+ * @ADIHDMI_SYNC_POLARITY_HIGH: Sync polarity is high
+ *
+ * If the polarity is set to either LOW or HIGH the driver will configure the
+ * ADIHDMI to internally invert the sync signal if required to match the sync
+ * polarity setting for the currently selected output mode.
+ *
+ * If the polarity is set to PASSTHROUGH, the ADIHDMI will route the signal
+ * unchanged. This is used when the upstream graphics core already generates
+ * the sync signals with the correct polarity.
+ */
+enum adihdmi_sync_polarity {
+ ADIHDMI_SYNC_POLARITY_PASSTHROUGH,
+ ADIHDMI_SYNC_POLARITY_LOW,
+ ADIHDMI_SYNC_POLARITY_HIGH,
+};
+
+/**
+ * struct adihdmi_link_config - Describes adihdmi hardware configuration
+ * @input_color_depth: Number of bits per color component (8, 10 or 12)
+ * @input_colorspace: The input colorspace (RGB, YUV444, YUV422)
+ * @input_clock: The input video clock style (1x, 2x, DDR)
+ * @input_style: The input component arrangement variant
+ * @input_justification: Video input format bit justification
+ * @clock_delay: Clock delay for the input clock (in ps)
+ * @embedded_sync: Video input uses BT.656-style embedded sync
+ * @sync_pulse: Select the sync pulse
+ * @vsync_polarity: vsync input signal configuration
+ * @hsync_polarity: hsync input signal configuration
+ */
+struct adihdmi_link_config {
+ unsigned int input_color_depth;
+ enum hdmi_colorspace input_colorspace;
+ enum adihdmi_input_clock input_clock;
+ unsigned int input_style;
+ enum adihdmi_input_justification input_justification;
+
+ int clock_delay;
+
+ bool embedded_sync;
+ enum adihdmi_input_sync_pulse sync_pulse;
+ enum adihdmi_sync_polarity vsync_polarity;
+ enum adihdmi_sync_polarity hsync_polarity;
+};
+
+/**
+ * enum adihdmi_csc_scaling - Scaling factor for the ADIHDMI CSC
+ * @ADIHDMI_CSC_SCALING_1: CSC results are not scaled
+ * @ADIHDMI_CSC_SCALING_2: CSC results are scaled by a factor of two
+ * @ADIHDMI_CSC_SCALING_4: CSC results are scalled by a factor of four
+ */
+enum adihdmi_csc_scaling {
+ ADIHDMI_CSC_SCALING_1 = 0,
+ ADIHDMI_CSC_SCALING_2 = 1,
+ ADIHDMI_CSC_SCALING_4 = 2,
+};
+
+/**
+ * struct adihdmi_video_config - Describes adihdmi hardware configuration
+ * @csc_enable: Whether to enable color space conversion
+ * @csc_scaling_factor: Color space conversion scaling factor
+ * @csc_coefficents: Color space conversion coefficents
+ * @hdmi_mode: Whether to use HDMI or DVI output mode
+ * @avi_infoframe: HDMI infoframe
+ */
+struct adihdmi_video_config {
+ bool csc_enable;
+ enum adihdmi_csc_scaling csc_scaling_factor;
+ const uint16_t *csc_coefficents;
+
+ bool hdmi_mode;
+ struct hdmi_avi_infoframe avi_infoframe;
+};
+
+#endif /* __DRM_I2C_ADIHDMI_H__ */
diff --git b/drivers/gpu/drm/i2c/adihdmi_drv.c b/drivers/gpu/drm/i2c/adihdmi_drv.c
new file mode 100644
index 0000000..6792224
--- /dev/null
+++ b/drivers/gpu/drm/i2c/adihdmi_drv.c
@@ -0,0 +1,1268 @@
+/*
+ * Analog Devices ADIHDMI HDMI transmitter driver
+ *
+ * Copyright 2012 Analog Devices Inc.
+ * Copyright 2015 Konsulko Group
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/component.h>
+#include <linux/device.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_encoder_slave.h>
+#include <drm_of.h>
+
+#include "adihdmi.h"
+
+#define ADIHDMI_INFOFRAME_PACKETS (0x7900)
+
+struct adihdmi {
+ struct i2c_client *i2c_main;
+ struct i2c_client *i2c_edid;
+
+ struct regmap *regmap;
+ struct regmap *packet_memory_regmap;
+ enum drm_connector_status status;
+ bool powered;
+
+ unsigned int f_tmds;
+
+ unsigned int current_edid_segment;
+ uint8_t edid_buf[256];
+ bool edid_read;
+
+ wait_queue_head_t wq;
+ struct drm_encoder *encoder;
+
+ bool embedded_sync;
+ enum adihdmi_sync_polarity vsync_polarity;
+ enum adihdmi_sync_polarity hsync_polarity;
+ bool rgb;
+
+ struct edid *edid;
+
+ struct gpio_desc *gpio_pd;
+};
+
+struct adihdmi2 {
+ struct adihdmi base;
+ struct drm_encoder encoder;
+ struct drm_connector connector;
+};
+
+/* ADI recommended values for proper operation. */
+static const struct reg_sequence adihdmi_fixed_registers[] = {
+ { 0x98, 0x03 },
+ { 0x9a, 0xe0 },
+ { 0x9c, 0x30 },
+ { 0x9d, 0x61 },
+ { 0xa2, 0xa4 },
+ { 0xa3, 0xa4 },
+ { 0xe0, 0xd0 },
+ { 0xf9, 0x00 },
+ { 0x55, 0x02 },
+};
+
+/* -----------------------------------------------------------------------------
+ * Register access
+ */
+
+static const uint8_t adihdmi_register_defaults[] = {
+ 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 00 */
+ 0x00, 0x00, 0x01, 0x0e, 0xbc, 0x18, 0x01, 0x13,
+ 0x25, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 10 */
+ 0x46, 0x62, 0x04, 0xa8, 0x00, 0x00, 0x1c, 0x84,
+ 0x1c, 0xbf, 0x04, 0xa8, 0x1e, 0x70, 0x02, 0x1e, /* 20 */
+ 0x00, 0x00, 0x04, 0xa8, 0x08, 0x12, 0x1b, 0xac,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 30 */
+ 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xb0,
+ 0x00, 0x50, 0x90, 0x7e, 0x79, 0x70, 0x00, 0x00, /* 40 */
+ 0x00, 0xa8, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x0d, 0x00, 0x00, 0x00, 0x00, /* 50 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 60 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 70 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 80 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, /* 90 */
+ 0x0b, 0x02, 0x00, 0x18, 0x5a, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x80, 0x08, 0x04, 0x00, 0x00, /* a0 */
+ 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x14,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* b0 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* c0 */
+ 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x01, 0x04,
+ 0x30, 0xff, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, /* d0 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01,
+ 0x80, 0x75, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, /* e0 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x11, 0x00, /* f0 */
+ 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static bool adihdmi_register_volatile(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case ADIHDMI_REG_CHIP_REVISION:
+ case ADIHDMI_REG_SPDIF_FREQ:
+ case ADIHDMI_REG_CTS_AUTOMATIC1:
+ case ADIHDMI_REG_CTS_AUTOMATIC2:
+ case ADIHDMI_REG_VIC_DETECTED:
+ case ADIHDMI_REG_VIC_SEND:
+ case ADIHDMI_REG_AUX_VIC_DETECTED:
+ case ADIHDMI_REG_STATUS:
+ case ADIHDMI_REG_GC(1):
+ case ADIHDMI_REG_INT(0):
+ case ADIHDMI_REG_INT(1):
+ case ADIHDMI_REG_PLL_STATUS:
+ case ADIHDMI_REG_AN(0):
+ case ADIHDMI_REG_AN(1):
+ case ADIHDMI_REG_AN(2):
+ case ADIHDMI_REG_AN(3):
+ case ADIHDMI_REG_AN(4):
+ case ADIHDMI_REG_AN(5):
+ case ADIHDMI_REG_AN(6):
+ case ADIHDMI_REG_AN(7):
+ case ADIHDMI_REG_HDCP_STATUS:
+ case ADIHDMI_REG_BCAPS:
+ case ADIHDMI_REG_BKSV(0):
+ case ADIHDMI_REG_BKSV(1):
+ case ADIHDMI_REG_BKSV(2):
+ case ADIHDMI_REG_BKSV(3):
+ case ADIHDMI_REG_BKSV(4):
+ case ADIHDMI_REG_DDC_STATUS:
+ case ADIHDMI_REG_BSTATUS(0):
+ case ADIHDMI_REG_BSTATUS(1):
+ case ADIHDMI_REG_CHIP_ID_HIGH:
+ case ADIHDMI_REG_CHIP_ID_LOW:
+ return true;
+ }
+
+ return false;
+}
+
+static const struct regmap_config adihdmi_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = 0xff,
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults_raw = adihdmi_register_defaults,
+ .num_reg_defaults_raw = ARRAY_SIZE(adihdmi_register_defaults),
+
+ .volatile_reg = adihdmi_register_volatile,
+};
+
+/* -----------------------------------------------------------------------------
+ * Hardware configuration
+ */
+
+ static void adihdmi_audio_setup(struct adihdmi * adihdmi)
+{
+ /* Select I2S. */
+ regmap_write(adihdmi->regmap, ADIHDMI_REG_AUDIO_SOURCE, 0x01);
+ regmap_write(adihdmi->regmap, ADIHDMI_REG_I2S_CONFIG, 0x84);
+
+ /* Setup clocks for 48KHz. */
+ regmap_write(adihdmi->regmap, ADIHDMI_REG_N0, 0x00);
+ regmap_write(adihdmi->regmap, ADIHDMI_REG_N1, 0x18);
+ regmap_write(adihdmi->regmap, ADIHDMI_REG_N2, 0x00);
+ regmap_update_bits(adihdmi->regmap, ADIHDMI_REG_I2C_FREQ_ID_CFG, 0xF0, 0x20);
+
+ /* Set audio word length to 24 bits. */
+ regmap_update_bits(adihdmi->regmap, ADIHDMI_REG_AUDIO_CFG3, 0x0F, 0x0B);
+
+ /* Update audio infoframe. */
+ regmap_update_bits(adihdmi->regmap, ADIHDMI_REG_INFOFRAME_UPDATE, 0x20, 0x20);
+ regmap_update_bits(adihdmi->regmap, ADIHDMI_REG_AUDIO_INFOFRAME(0), 0x07, 0x01);
+ regmap_update_bits(adihdmi->regmap, ADIHDMI_REG_AUDIO_INFOFRAME(3), 0x1F, 0x00);
+ regmap_update_bits(adihdmi->regmap, ADIHDMI_REG_INFOFRAME_UPDATE, 0x20, 0x00);
+}
+
+static void adihdmi_set_colormap(struct adihdmi *adihdmi, bool enable,
+ const uint16_t *coeff,
+ unsigned int scaling_factor)
+{
+ unsigned int i;
+
+ regmap_update_bits(adihdmi->regmap, ADIHDMI_REG_CSC_UPPER(1),
+ ADIHDMI_CSC_UPDATE_MODE, ADIHDMI_CSC_UPDATE_MODE);
+
+ if (enable) {
+ for (i = 0; i < 12; ++i) {
+ regmap_update_bits(adihdmi->regmap,
+ ADIHDMI_REG_CSC_UPPER(i),
+ 0x1f, coeff[i] >> 8);
+ regmap_write(adihdmi->regmap,
+ ADIHDMI_REG_CSC_LOWER(i),
+ coeff[i] & 0xff);
+ }
+ }
+
+ if (enable)
+ regmap_update_bits(adihdmi->regmap, ADIHDMI_REG_CSC_UPPER(0),
+ 0xe0, 0x80 | (scaling_factor << 5));
+ else
+ regmap_update_bits(adihdmi->regmap, ADIHDMI_REG_CSC_UPPER(0),
+ 0x80, 0x00);
+
+ regmap_update_bits(adihdmi->regmap, ADIHDMI_REG_CSC_UPPER(1),
+ ADIHDMI_CSC_UPDATE_MODE, 0);
+}
+
+static int adihdmi_packet_enable(struct adihdmi *adihdmi, unsigned int packet)
+{
+ if (packet & 0xff)
+ regmap_update_bits(adihdmi->regmap, ADIHDMI_REG_PACKET_ENABLE0,
+ packet, 0xff);
+
+ if (packet & 0xff00) {
+ packet >>= 8;
+ regmap_update_bits(adihdmi->regmap, ADIHDMI_REG_PACKET_ENABLE1,
+ packet, 0xff);
+ }
+
+ return 0;
+}
+
+static int adihdmi_packet_disable(struct adihdmi *adihdmi, unsigned int packet)
+{
+ if (packet & 0xff)
+ regmap_update_bits(adihdmi->regmap, ADIHDMI_REG_PACKET_ENABLE0,
+ packet, 0x00);
+
+ if (packet & 0xff00) {
+ packet >>= 8;
+ regmap_update_bits(adihdmi->regmap, ADIHDMI_REG_PACKET_ENABLE1,
+ packet, 0x00);
+ }
+
+ return 0;
+}
+
+/* Coefficients for adihdmi color space conversion */
+static const uint16_t adihdmi_csc_ycbcr_to_rgb[] = {
+ 0x0734, 0x04ad, 0x0000, 0x1c1b,
+ 0x1ddc, 0x04ad, 0x1f24, 0x0135,
+ 0x0000, 0x04ad, 0x087c, 0x1b77,
+};
+
+static void adihdmi_set_config_csc(struct adihdmi *adihdmi,
+ struct drm_connector *connector,
+ bool rgb)
+{
+ struct adihdmi_video_config config;
+ bool output_format_422, output_format_ycbcr;
+ unsigned int mode;
+ uint8_t infoframe[17];
+
+ if (adihdmi->edid)
+ config.hdmi_mode = drm_detect_hdmi_monitor(adihdmi->edid);
+ else
+ config.hdmi_mode = false;
+
+ hdmi_avi_infoframe_init(&config.avi_infoframe);
+
+ config.avi_infoframe.scan_mode = HDMI_SCAN_MODE_UNDERSCAN;
+
+ if (rgb) {
+ config.csc_enable = false;
+ config.avi_infoframe.colorspace = HDMI_COLORSPACE_RGB;
+ } else {
+ config.csc_scaling_factor = ADIHDMI_CSC_SCALING_4;
+ config.csc_coefficents = adihdmi_csc_ycbcr_to_rgb;
+
+ if ((connector->display_info.color_formats &
+ DRM_COLOR_FORMAT_YCRCB422) &&
+ config.hdmi_mode) {
+ config.csc_enable = false;
+ config.avi_infoframe.colorspace =
+ HDMI_COLORSPACE_YUV422;
+ } else {
+ config.csc_enable = true;
+ config.avi_infoframe.colorspace = HDMI_COLORSPACE_RGB;
+ }
+ }
+
+ if (config.hdmi_mode) {
+ mode = ADIHDMI_HDMI_CFG_MODE_HDMI;
+
+ switch (config.avi_infoframe.colorspace) {
+ case HDMI_COLORSPACE_YUV444:
+ output_format_422 = false;
+ output_format_ycbcr = true;
+ break;
+ case HDMI_COLORSPACE_YUV422:
+ output_format_422 = true;
+ output_format_ycbcr = true;
+ break;
+ default:
+ output_format_422 = false;
+ output_format_ycbcr = false;
+ break;
+ }
+ } else {
+ mode = ADIHDMI_HDMI_CFG_MODE_DVI;
+ output_format_422 = false;
+ output_format_ycbcr = false;
+ }
+
+ adihdmi_packet_disable(adihdmi, ADIHDMI_INFOFRAME_PACKETS);
+
+ adihdmi_set_colormap(adihdmi, config.csc_enable,
+ config.csc_coefficents,
+ config.csc_scaling_factor);
+
+ regmap_update_bits(adihdmi->regmap, ADIHDMI_REG_VIDEO_INPUT_CFG1, 0x81,
+ (output_format_422 << 7) | output_format_ycbcr);
+
+ regmap_update_bits(adihdmi->regmap, ADIHDMI_REG_HDCP_HDMI_CFG,
+ ADIHDMI_HDMI_CFG_MODE_MASK, mode);
+
+ hdmi_avi_infoframe_pack(&config.avi_infoframe, infoframe,
+ sizeof(infoframe));
+
+ /* The AVI infoframe id is not configurable */
+ regmap_bulk_write(adihdmi->regmap, ADIHDMI_REG_AVI_INFOFRAME_VERSION,
+ infoframe + 1, sizeof(infoframe) - 1);
+
+ adihdmi_packet_enable(adihdmi, ADIHDMI_INFOFRAME_PACKETS);
+}
+
+static void adihdmi_set_link_config(struct adihdmi *adihdmi,
+ const struct adihdmi_link_config *config)
+{
+ /*
+ * The input style values documented in the datasheet don't match the
+ * hardware register field values :-(
+ */
+ static const unsigned int input_styles[4] = { 0, 2, 1, 3 };
+
+ unsigned int clock_delay;
+ unsigned int color_depth;
+ unsigned int input_id;
+
+ clock_delay = (config->clock_delay + 1200) / 400;
+ color_depth = config->input_color_depth == 8 ? 3
+ : (config->input_color_depth == 10 ? 1 : 2);
+
+ /* TODO Support input ID 6 */
+ if (config->input_colorspace != HDMI_COLORSPACE_YUV422)
+ input_id = config->input_clock == ADIHDMI_INPUT_CLOCK_DDR
+ ? 5 : 0;
+ else if (config->input_clock == ADIHDMI_INPUT_CLOCK_DDR)
+ input_id = config->embedded_sync ? 8 : 7;
+ else if (config->input_clock == ADIHDMI_INPUT_CLOCK_2X)
+ input_id = config->embedded_sync ? 4 : 3;
+ else
+ input_id = config->embedded_sync ? 2 : 1;
+
+ regmap_update_bits(adihdmi->regmap, ADIHDMI_REG_I2C_FREQ_ID_CFG, 0xf,
+ input_id);
+ regmap_update_bits(adihdmi->regmap, ADIHDMI_REG_VIDEO_INPUT_CFG1, 0x7e,
+ (color_depth << 4) |
+ (input_styles[config->input_style] << 2));
+ regmap_write(adihdmi->regmap, ADIHDMI_REG_VIDEO_INPUT_CFG2,
+ config->input_justification << 3);
+ regmap_write(adihdmi->regmap, ADIHDMI_REG_TIMING_GEN_SEQ,
+ config->sync_pulse << 2);
+
+ regmap_write(adihdmi->regmap, 0xba, clock_delay << 5);
+
+ adihdmi->embedded_sync = config->embedded_sync;
+ adihdmi->hsync_polarity = config->hsync_polarity;
+ adihdmi->vsync_polarity = config->vsync_polarity;
+ adihdmi->rgb = config->input_colorspace == HDMI_COLORSPACE_RGB;
+}
+
+static void adihdmi_power_on(struct adihdmi *adihdmi)
+{
+ adihdmi->current_edid_segment = -1;
+
+ regmap_write(adihdmi->regmap, ADIHDMI_REG_INT(0),
+ ADIHDMI_INT0_EDID_READY);
+ regmap_write(adihdmi->regmap, ADIHDMI_REG_INT(1),
+ ADIHDMI_INT1_DDC_ERROR);
+ regmap_update_bits(adihdmi->regmap, ADIHDMI_REG_POWER,
+ ADIHDMI_POWER_POWER_DOWN, 0);
+
+ /*
+ * Per spec it is allowed to pulse the HDP signal to indicate that the
+ * EDID information has changed. Some monitors do this when they wakeup
+ * from standby or are enabled. When the HDP goes low the adihdmi is
+ * reset and the outputs are disabled which might cause the monitor to
+ * go to standby again. To avoid this we ignore the HDP pin for the
+ * first few seconds after enabling the output.
+ */
+ regmap_update_bits(adihdmi->regmap, ADIHDMI_REG_POWER2,
+ ADIHDMI_REG_POWER2_HDP_SRC_MASK,
+ ADIHDMI_REG_POWER2_HDP_SRC_NONE);
+
+ /*
+ * Most of the registers are reset during power down or when HPD is low.
+ */
+ regcache_sync(adihdmi->regmap);
+
+ adihdmi->powered = true;
+}
+
+static void adihdmi_power_off(struct adihdmi *adihdmi)
+{
+ /* TODO: setup additional power down modes */
+ regmap_update_bits(adihdmi->regmap, ADIHDMI_REG_POWER,
+ ADIHDMI_POWER_POWER_DOWN,
+ ADIHDMI_POWER_POWER_DOWN);
+ regcache_mark_dirty(adihdmi->regmap);
+
+ adihdmi->powered = false;
+}
+
+/* -----------------------------------------------------------------------------
+ * Interrupt and hotplug detection
+ */
+
+static bool adihdmi_hpd(struct adihdmi *adihdmi)
+{
+ unsigned int irq0;
+ int ret;
+
+ ret = regmap_read(adihdmi->regmap, ADIHDMI_REG_INT(0), &irq0);
+ if (ret < 0)
+ return false;
+
+ if (irq0 & ADIHDMI_INT0_HDP) {
+ regmap_write(adihdmi->regmap, ADIHDMI_REG_INT(0),
+ ADIHDMI_INT0_HDP);
+ return true;
+ }
+
+ return false;
+}
+
+static int adihdmi_irq_process(struct adihdmi *adihdmi)
+{
+ unsigned int irq0, irq1;
+ int ret;
+
+ ret = regmap_read(adihdmi->regmap, ADIHDMI_REG_INT(0), &irq0);
+ if (ret < 0)
+ return ret;
+
+ ret = regmap_read(adihdmi->regmap, ADIHDMI_REG_INT(1), &irq1);
+ if (ret < 0)
+ return ret;
+
+ regmap_write(adihdmi->regmap, ADIHDMI_REG_INT(0), irq0);
+ regmap_write(adihdmi->regmap, ADIHDMI_REG_INT(1), irq1);
+
+ if (irq0 & ADIHDMI_INT0_HDP)
+ drm_helper_hpd_irq_event(adihdmi->encoder->dev);
+
+ if (irq0 & ADIHDMI_INT0_EDID_READY || irq1 & ADIHDMI_INT1_DDC_ERROR) {
+ adihdmi->edid_read = true;
+
+ if (adihdmi->i2c_main->irq)
+ wake_up_all(&adihdmi->wq);
+ }
+
+ return 0;
+}
+
+static irqreturn_t adihdmi_irq_handler(int irq, void *devid)
+{
+ struct adihdmi *adihdmi = devid;
+ int ret;
+
+ ret = adihdmi_irq_process(adihdmi);
+ return ret < 0 ? IRQ_NONE : IRQ_HANDLED;
+}
+
+/* -----------------------------------------------------------------------------
+ * EDID retrieval
+ */
+
+static int adihdmi_wait_for_edid(struct adihdmi *adihdmi, int timeout)
+{
+ int ret;
+
+ if (adihdmi->i2c_main->irq) {
+ ret = wait_event_interruptible_timeout(adihdmi->wq,
+ adihdmi->edid_read, msecs_to_jiffies(timeout));
+ } else {
+ for (; timeout > 0; timeout -= 25) {
+ ret = adihdmi_irq_process(adihdmi);
+ if (ret < 0)
+ break;
+
+ if (adihdmi->edid_read)
+ break;
+
+ msleep(25);
+ }
+ }
+
+ return adihdmi->edid_read ? 0 : -EIO;
+}
+
+static int adihdmi_get_edid_block(void *data, u8 *buf, unsigned int block,
+ size_t len)
+{
+ struct adihdmi *adihdmi = data;
+ struct i2c_msg xfer[2];
+ uint8_t offset;
+ unsigned int i;
+ int ret;
+
+ if (len > 128)
+ return -EINVAL;
+
+ if (adihdmi->current_edid_segment != block / 2) {
+ unsigned int status;
+
+ ret = regmap_read(adihdmi->regmap, ADIHDMI_REG_DDC_STATUS,
+ &status);
+ if (ret < 0)
+ return ret;
+
+ if (status != 2) {
+ adihdmi->edid_read = false;
+ regmap_write(adihdmi->regmap, ADIHDMI_REG_EDID_SEGMENT,
+ block);
+ ret = adihdmi_wait_for_edid(adihdmi, 200);
+ if (ret < 0)
+ return ret;
+ }
+
+ /* Break this apart, hopefully more I2C controllers will
+ * support 64 byte transfers than 256 byte transfers
+ */
+
+ xfer[0].addr = adihdmi->i2c_edid->addr;
+ xfer[0].flags = 0;
+ xfer[0].len = 1;
+ xfer[0].buf = &offset;
+ xfer[1].addr = adihdmi->i2c_edid->addr;
+ xfer[1].flags = I2C_M_RD;
+ xfer[1].len = 64;
+ xfer[1].buf = adihdmi->edid_buf;
+
+ offset = 0;
+
+ for (i = 0; i < 4; ++i) {
+ ret = i2c_transfer(adihdmi->i2c_edid->adapter, xfer,
+ ARRAY_SIZE(xfer));
+ if (ret < 0)
+ return ret;
+ else if (ret != 2)
+ return -EIO;
+
+ xfer[1].buf += 64;
+ offset += 64;
+ }
+
+ adihdmi->current_edid_segment = block / 2;
+ }
+
+ if (block % 2 == 0)
+ memcpy(buf, adihdmi->edid_buf, len);
+ else
+ memcpy(buf, adihdmi->edid_buf + 128, len);
+
+ return 0;
+}
+
+static int adihdmi_mode_valid(struct drm_display_mode *mode)
+{
+ if (mode->clock > 165000)
+ return MODE_CLOCK_HIGH;
+
+ return MODE_OK;
+}
+
+/* -----------------------------------------------------------------------------
+ * DT and private structure operations
+ */
+
+#define conn_to_adihdmi2(x) \
+ container_of(x, struct adihdmi2, connector);
+
+#define enc_to_adihdmi2(x) \
+ container_of(x, struct adihdmi2, encoder);
+
+#define enc_to_adihdmi(x) \
+ (&(container_of(x, struct adihdmi2, encoder)->base))
+
+static int adihdmi_parse_dt(struct device_node *np,
+ struct adihdmi_link_config *config)
+{
+ memset(config, 0, sizeof(*config));
+
+ config->input_color_depth = 8;
+
+ config->input_colorspace = HDMI_COLORSPACE_RGB;
+ //config->input_colorspace = HDMI_COLORSPACE_YUV422;
+ //config->input_colorspace = HDMI_COLORSPACE_YUV444;
+
+ config->input_clock = ADIHDMI_INPUT_CLOCK_1X;
+ //config->input_clock = ADIHDMI_INPUT_CLOCK_2X;
+ //config->input_clock = ADIHDMI_INPUT_CLOCK_DDR;
+
+ if (config->input_colorspace == HDMI_COLORSPACE_YUV422 ||
+ config->input_clock != ADIHDMI_INPUT_CLOCK_1X) {
+
+ config->input_style = 1;
+ //config->input_justification = ADIHDMI_INPUT_JUSTIFICATION_LEFT;
+ config->input_justification = ADIHDMI_INPUT_JUSTIFICATION_EVENLY;
+ //config->input_justification = ADIHDMI_INPUT_JUSTIFICATION_RIGHT;
+
+ } else {
+ config->input_style = 1;
+ config->input_justification = ADIHDMI_INPUT_JUSTIFICATION_LEFT;
+ }
+
+ config->clock_delay = 0;
+ config->embedded_sync = 0;
+
+ /* Hardcode the sync pulse configurations for now. */
+ config->sync_pulse = ADIHDMI_INPUT_SYNC_PULSE_NONE;
+ config->vsync_polarity = ADIHDMI_SYNC_POLARITY_PASSTHROUGH;
+ config->hsync_polarity = ADIHDMI_SYNC_POLARITY_PASSTHROUGH;
+
+ return 0;
+}
+
+static const int edid_i2c_addr = 0x7e;
+static const int packet_i2c_addr = 0x70;
+static const int cec_i2c_addr = 0x78;
+
+static int adihdmi_create(struct i2c_client *i2c, struct adihdmi *adihdmi)
+{
+ struct adihdmi_link_config link_config;
+ struct device *dev = &i2c->dev;
+ unsigned int val;
+ int ret;
+
+ adihdmi->powered = false;
+ adihdmi->status = connector_status_disconnected;
+
+ ret = adihdmi_parse_dt(NULL, &link_config);
+ if (ret)
+ {
+ pr_err("%s - %d - Bad parse\n", __FUNCTION__, __LINE__);
+ return -EINVAL;
+ }
+
+ /*
+ * The power down GPIO is optional. If present, toggle it from active to
+ * inactive to wake up the encoder.
+ */
+ adihdmi->gpio_pd = devm_gpiod_get_optional(dev, "pd", GPIOD_OUT_HIGH);
+ if (IS_ERR(adihdmi->gpio_pd))
+ {
+ pr_err("%s - %d - Bad PD GPIO\n", __FUNCTION__, __LINE__);
+ return PTR_ERR(adihdmi->gpio_pd);
+ }
+
+ if (adihdmi->gpio_pd) {
+ mdelay(5);
+ gpiod_set_value_cansleep(adihdmi->gpio_pd, 0);
+ }
+
+ adihdmi->regmap = devm_regmap_init_i2c(i2c, &adihdmi_regmap_config);
+ if (IS_ERR(adihdmi->regmap))
+ {
+ pr_err("%s - %d - Bad reg map init\n", __FUNCTION__, __LINE__);
+ return PTR_ERR(adihdmi->regmap);
+ }
+
+ ret = regmap_read(adihdmi->regmap, ADIHDMI_REG_CHIP_REVISION, &val);
+ if (ret)
+ {
+ pr_err("%s - %d - Bad reg map read\n", __FUNCTION__, __LINE__);
+ return ret;
+ }
+ dev_dbg(dev, "Rev. %d\n", val);
+
+ ret = regmap_register_patch(adihdmi->regmap, adihdmi_fixed_registers,
+ ARRAY_SIZE(adihdmi_fixed_registers));
+ if (ret)
+ {
+ pr_err("%s - %d - Bad reg map patch\n", __FUNCTION__, __LINE__);
+ return ret;
+ }
+
+ regmap_write(adihdmi->regmap, ADIHDMI_REG_EDID_I2C_ADDR, edid_i2c_addr);
+ regmap_write(adihdmi->regmap, ADIHDMI_REG_PACKET_I2C_ADDR,
+ packet_i2c_addr);
+ regmap_write(adihdmi->regmap, ADIHDMI_REG_CEC_I2C_ADDR, cec_i2c_addr);
+ adihdmi_packet_disable(adihdmi, 0xffff);
+
+ adihdmi->i2c_main = i2c;
+ adihdmi->i2c_edid = i2c_new_dummy(i2c->adapter, edid_i2c_addr >> 1);
+ if (!adihdmi->i2c_edid)
+ {
+ pr_err("%s - %d - No mem for EDID\n", __FUNCTION__, __LINE__);
+ return -ENOMEM;
+ }
+
+ if (i2c->irq) {
+ init_waitqueue_head(&adihdmi->wq);
+
+ ret = devm_request_threaded_irq(dev, i2c->irq, NULL,
+ adihdmi_irq_handler,
+ IRQF_ONESHOT, dev_name(dev),
+ adihdmi);
+ if (ret)
+ {
+ pr_err("%s - %d - Bad IRQ thread request\n", __FUNCTION__, __LINE__);
+ goto err_i2c_unregister_device;
+ }
+ }
+
+ /* CEC is unused for now */
+ regmap_write(adihdmi->regmap, ADIHDMI_REG_CEC_CTRL,
+ ADIHDMI_CEC_CTRL_POWER_DOWN);
+
+ adihdmi_power_off(adihdmi);
+
+ adihdmi_set_link_config(adihdmi, &link_config);
+
+ adihdmi_audio_setup(adihdmi);
+
+ return 0;
+
+err_i2c_unregister_device:
+ i2c_unregister_device(adihdmi->i2c_edid);
+
+ return ret;
+}
+
+static void adihdmi_destroy(struct adihdmi *priv)
+{
+ i2c_unregister_device(priv->i2c_edid);
+}
+
+/* -----------------------------------------------------------------------------
+ * Encoder operations
+ */
+
+static int adihdmi_encoder_get_modes(struct adihdmi *adihdmi,
+ struct drm_connector *connector)
+{
+ struct edid *edid;
+ unsigned int count;
+
+ /* Reading the EDID only works if the device is powered */
+ if (!adihdmi->powered) {
+ regmap_write(adihdmi->regmap, ADIHDMI_REG_INT(0),
+ ADIHDMI_INT0_EDID_READY);
+ regmap_write(adihdmi->regmap, ADIHDMI_REG_INT(1),
+ ADIHDMI_INT1_DDC_ERROR);
+ regmap_update_bits(adihdmi->regmap, ADIHDMI_REG_POWER,
+ ADIHDMI_POWER_POWER_DOWN, 0);
+ adihdmi->current_edid_segment = -1;
+ }
+
+ edid = drm_do_get_edid(connector, adihdmi_get_edid_block, adihdmi);
+
+ if (!adihdmi->powered)
+ regmap_update_bits(adihdmi->regmap, ADIHDMI_REG_POWER,
+ ADIHDMI_POWER_POWER_DOWN,
+ ADIHDMI_POWER_POWER_DOWN);
+
+ kfree(adihdmi->edid);
+ adihdmi->edid = edid;
+ if (!edid)
+ {
+ pr_err("%s - %d - No EDID\n", __FUNCTION__, __LINE__);
+ return 0;
+ }
+
+ drm_mode_connector_update_edid_property(connector, edid);
+ count = drm_add_edid_modes(connector, edid);
+
+ adihdmi_set_config_csc(adihdmi, connector, adihdmi->rgb);
+
+ return count;
+}
+
+static void adihdmi_encoder_dpms(struct drm_encoder *encoder, int mode)
+{
+ struct adihdmi2 *priv2 = enc_to_adihdmi2(encoder);
+
+ if (mode == DRM_MODE_DPMS_ON)
+ adihdmi_power_on(&priv2->base);
+ else
+ adihdmi_power_off(&priv2->base);
+}
+
+ static enum drm_connector_status
+adihdmi_encoder_detect(struct adihdmi *adihdmi,
+ struct drm_connector *connector)
+{
+ enum drm_connector_status status;
+ unsigned int val;
+ bool hpd;
+ int ret;
+
+ ret = regmap_read(adihdmi->regmap, ADIHDMI_REG_STATUS, &val);
+ if (ret < 0)
+ {
+ pr_err("%s - %d - Disconnected\n", __FUNCTION__, __LINE__);
+ return connector_status_disconnected;
+ }
+
+ if (val & ADIHDMI_STATUS_HPD)
+ status = connector_status_connected;
+ else
+ status = connector_status_disconnected;
+
+ hpd = adihdmi_hpd(adihdmi);
+
+ /* The chip resets itself when the cable is disconnected, so in case
+ * there is a pending HPD interrupt and the cable is connected there was
+ * at least one transition from disconnected to connected and the chip
+ * has to be reinitialized. */
+ if (status == connector_status_connected && hpd && adihdmi->powered) {
+ regcache_mark_dirty(adihdmi->regmap);
+ adihdmi_power_on(adihdmi);
+ adihdmi_encoder_get_modes(adihdmi, connector);
+ if (adihdmi->status == connector_status_connected)
+ status = connector_status_disconnected;
+ } else {
+ /* Renable HDP sensing */
+ regmap_update_bits(adihdmi->regmap, ADIHDMI_REG_POWER2,
+ ADIHDMI_REG_POWER2_HDP_SRC_MASK,
+ ADIHDMI_REG_POWER2_HDP_SRC_BOTH);
+ }
+
+ adihdmi->status = status;
+ return status;
+}
+
+static bool adihdmi_encoder_mode_fixup(struct drm_encoder *encoder, const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode)
+{
+ return true;
+}
+
+static int adihdmi_encoder_mode_valid(struct drm_encoder *encoder, struct drm_display_mode *mode)
+{
+ return adihdmi_mode_valid(mode);
+}
+
+static void adihdmi_encoder_mode_set(struct drm_encoder *encoder,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adj_mode)
+{
+ unsigned int low_refresh_rate;
+ unsigned int hsync_polarity = 0;
+ unsigned int vsync_polarity = 0;
+ struct adihdmi *adihdmi = enc_to_adihdmi(encoder);
+
+ if (adihdmi->embedded_sync) {
+ unsigned int hsync_offset, hsync_len;
+ unsigned int vsync_offset, vsync_len;
+
+ hsync_offset = adj_mode->crtc_hsync_start -
+ adj_mode->crtc_hdisplay;
+ vsync_offset = adj_mode->crtc_vsync_start -
+ adj_mode->crtc_vdisplay;
+ hsync_len = adj_mode->crtc_hsync_end -
+ adj_mode->crtc_hsync_start;
+ vsync_len = adj_mode->crtc_vsync_end -
+ adj_mode->crtc_vsync_start;
+
+ /* The hardware vsync generator has a off-by-one bug */
+ vsync_offset += 1;
+
+ regmap_write(adihdmi->regmap, ADIHDMI_REG_HSYNC_PLACEMENT_MSB,
+ ((hsync_offset >> 10) & 0x7) << 5);
+ regmap_write(adihdmi->regmap, ADIHDMI_REG_SYNC_DECODER(0),
+ (hsync_offset >> 2) & 0xff);
+ regmap_write(adihdmi->regmap, ADIHDMI_REG_SYNC_DECODER(1),
+ ((hsync_offset & 0x3) << 6) |
+ ((hsync_len >> 4) & 0x3f));
+ regmap_write(adihdmi->regmap, ADIHDMI_REG_SYNC_DECODER(2),
+ ((hsync_len & 0xf) << 4) |
+ ((vsync_offset >> 6) & 0xf));
+ regmap_write(adihdmi->regmap, ADIHDMI_REG_SYNC_DECODER(3),
+ ((vsync_offset & 0x3f) << 2) |
+ ((vsync_len >> 8) & 0x3));
+ regmap_write(adihdmi->regmap, ADIHDMI_REG_SYNC_DECODER(4),
+ vsync_len & 0xff);
+
+ hsync_polarity = !(adj_mode->flags & DRM_MODE_FLAG_PHSYNC);
+ vsync_polarity = !(adj_mode->flags & DRM_MODE_FLAG_PVSYNC);
+ } else {
+ enum adihdmi_sync_polarity mode_hsync_polarity;
+ enum adihdmi_sync_polarity mode_vsync_polarity;
+
+ /**
+ * If the input signal is always low or always high we want to
+ * invert or let it passthrough depending on the polarity of the
+ * current mode.
+ **/
+ if (adj_mode->flags & DRM_MODE_FLAG_NHSYNC)
+ mode_hsync_polarity = ADIHDMI_SYNC_POLARITY_LOW;
+ else
+ mode_hsync_polarity = ADIHDMI_SYNC_POLARITY_HIGH;
+
+ if (adj_mode->flags & DRM_MODE_FLAG_NVSYNC)
+ mode_vsync_polarity = ADIHDMI_SYNC_POLARITY_LOW;
+ else
+ mode_vsync_polarity = ADIHDMI_SYNC_POLARITY_HIGH;
+
+ if (adihdmi->hsync_polarity != mode_hsync_polarity &&
+ adihdmi->hsync_polarity !=
+ ADIHDMI_SYNC_POLARITY_PASSTHROUGH)
+ hsync_polarity = 1;
+
+ if (adihdmi->vsync_polarity != mode_vsync_polarity &&
+ adihdmi->vsync_polarity !=
+ ADIHDMI_SYNC_POLARITY_PASSTHROUGH)
+ vsync_polarity = 1;
+ }
+
+ if (mode->vrefresh <= 24000)
+ low_refresh_rate = ADIHDMI_LOW_REFRESH_RATE_24HZ;
+ else if (mode->vrefresh <= 25000)
+ low_refresh_rate = ADIHDMI_LOW_REFRESH_RATE_25HZ;
+ else if (mode->vrefresh <= 30000)
+ low_refresh_rate = ADIHDMI_LOW_REFRESH_RATE_30HZ;
+ else
+ low_refresh_rate = ADIHDMI_LOW_REFRESH_RATE_NONE;
+
+ regmap_update_bits(adihdmi->regmap, 0xfb,
+ 0x6, low_refresh_rate << 1);
+ regmap_update_bits(adihdmi->regmap, 0x17,
+ 0x60, (vsync_polarity << 6) | (hsync_polarity << 5));
+
+ /*
+ * TODO Test first order 4:2:2 to 4:4:4 up conversion method, which is
+ * supposed to give better results.
+ */
+
+ adihdmi->f_tmds = mode->clock;
+}
+
+static void adihdmi_encoder_prepare(struct drm_encoder *encoder)
+{
+ adihdmi_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
+}
+
+static void adihdmi_encoder_commit(struct drm_encoder *encoder)
+{
+ adihdmi_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
+}
+
+static struct drm_encoder_helper_funcs adihdmi_encoder_helper_funcs = {
+ .dpms = adihdmi_encoder_dpms,
+ .mode_fixup = adihdmi_encoder_mode_fixup,
+ .prepare = adihdmi_encoder_prepare,
+ .commit = adihdmi_encoder_commit,
+ .mode_set = adihdmi_encoder_mode_set,
+};
+
+static void adihdmi_encoder_destroy(struct drm_encoder *encoder)
+{
+ struct adihdmi2 *priv = enc_to_adihdmi2(encoder);
+
+ adihdmi_destroy(&priv->base);
+ drm_encoder_cleanup(encoder);
+}
+
+static const struct drm_encoder_funcs adihdmi_encoder_funcs = {
+ .destroy = adihdmi_encoder_destroy,
+};
+
+/* -----------------------------------------------------------------------------
+ * Slave operations
+ */
+
+static int adihdmi_encoder_slave_create_resources(struct drm_encoder *encoder, struct drm_connector *connector)
+{
+ pr_debug("%s - %d\n", __FUNCTION__, __LINE__);
+ return 0;
+}
+
+static void adihdmi_encoder_slave_destroy(struct drm_encoder *encoder)
+{
+ pr_debug("%s - %d\n", __FUNCTION__, __LINE__);
+}
+
+ static enum drm_connector_status
+adihdmi_encoder_slave_detect(struct drm_encoder *encoder,
+ struct drm_connector *connector)
+{
+ return adihdmi_encoder_detect(enc_to_adihdmi(encoder),
+ connector);
+}
+
+static int adihdmi_encoder_slave_get_modes(struct drm_encoder *encoder,
+ struct drm_connector *connector)
+{
+ return adihdmi_encoder_get_modes(enc_to_adihdmi(encoder),
+ connector);
+}
+
+
+static void adihdmi_encoder_slave_set_config(struct drm_encoder *encoder, void *params)
+{
+ pr_debug("%s - %d\n", __FUNCTION__, __LINE__);
+}
+
+static int adihdmi_encoder_set_property(struct drm_encoder *encoder, struct drm_connector *connector, struct drm_property *property, uint64_t val)
+{
+ pr_debug("%s - %d\n", __FUNCTION__, __LINE__);
+ return 0;
+}
+
+static struct drm_encoder_slave_funcs adihdmi_encoder_slave_funcs = {
+ .create_resources = adihdmi_encoder_slave_create_resources,
+ .destroy = adihdmi_encoder_slave_destroy,
+ .detect = adihdmi_encoder_slave_detect,
+ .dpms = adihdmi_encoder_dpms,
+ .get_modes = adihdmi_encoder_slave_get_modes,
+ .mode_fixup = adihdmi_encoder_mode_fixup,
+ .mode_set = adihdmi_encoder_mode_set,
+ .mode_valid = adihdmi_encoder_mode_valid,
+ .set_config = adihdmi_encoder_slave_set_config,
+ .set_property = adihdmi_encoder_set_property,
+};
+
+/* -----------------------------------------------------------------------------
+ * Connector operations
+ */
+
+static int adihdmi_connector_get_modes(struct drm_connector *connector)
+{
+ struct adihdmi2 *priv = conn_to_adihdmi2(connector);
+
+ return adihdmi_encoder_get_modes(&priv->base, connector);
+}
+
+static int adihdmi_connector_mode_valid(struct drm_connector *connector,
+ struct drm_display_mode *mode)
+{
+ return adihdmi_mode_valid(mode);
+}
+
+ static struct drm_encoder *
+adihdmi_connector_best_encoder(struct drm_connector *connector)
+{
+ struct adihdmi2 *priv = conn_to_adihdmi2(connector);
+
+ return &priv->encoder;
+}
+
+static struct drm_connector_helper_funcs adihdmi_connector_helper_funcs = {
+ .get_modes = adihdmi_connector_get_modes,
+ .mode_valid = adihdmi_connector_mode_valid,
+ .best_encoder = adihdmi_connector_best_encoder,
+};
+
+ static enum drm_connector_status
+adihdmi_connector_detect(struct drm_connector *connector, bool force)
+{
+ struct adihdmi2 *priv = conn_to_adihdmi2(connector);
+
+ return adihdmi_encoder_detect(&priv->base, connector);
+}
+
+static void adihdmi_connector_destroy(struct drm_connector *connector)
+{
+ drm_connector_unregister(connector);
+ drm_connector_cleanup(connector);
+}
+
+static struct drm_connector_funcs adihdmi_connector_funcs = {
+ .dpms = drm_helper_connector_dpms,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .detect = adihdmi_connector_detect,
+ .destroy = adihdmi_connector_destroy,
+};
+
+/* -----------------------------------------------------------------------------
+ * Component operations
+ */
+
+static int adihdmi_bind(struct device *dev, struct device *master, void *data)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct drm_device *drm = data;
+ struct adihdmi2 *priv;
+ uint32_t crtcs = 0;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ {
+ pr_err("%s - %d - No memory for ADIHDMI\n", __FUNCTION__, __LINE__);
+ return -ENOMEM;
+ }
+
+ dev_set_drvdata(dev, priv);
+
+ if (dev->of_node)
+ crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
+
+ /* If no CRTCs were found, fall back to our old behaviour */
+ if (crtcs == 0) {
+ dev_warn(dev, "Falling back to first CRTC\n");
+ crtcs = 1 << 0;
+ }
+
+ priv->base.encoder = &priv->encoder;
+ priv->connector.interlace_allowed = 1;
+ priv->encoder.possible_crtcs = crtcs;
+
+ ret = adihdmi_create(client, &priv->base);
+ if (ret)
+ return ret;
+
+ drm_encoder_helper_add(&priv->encoder, &adihdmi_encoder_helper_funcs);
+ ret = drm_encoder_init(drm, &priv->encoder, &adihdmi_encoder_funcs,
+ DRM_MODE_ENCODER_TMDS, NULL);
+ if (ret)
+ goto err_encoder;
+
+ drm_connector_helper_add(&priv->connector,
+ &adihdmi_connector_helper_funcs);
+ ret = drm_connector_init(drm, &priv->connector,
+ &adihdmi_connector_funcs,
+ DRM_MODE_CONNECTOR_HDMIA);
+ if (ret)
+ goto err_connector;
+
+ ret = drm_connector_register(&priv->connector);
+ if (ret)
+ goto err_sysfs;
+
+ priv->connector.encoder = &priv->encoder;
+ drm_mode_connector_attach_encoder(&priv->connector, &priv->encoder);
+
+ return 0;
+
+err_sysfs:
+ drm_connector_cleanup(&priv->connector);
+err_connector:
+ drm_encoder_cleanup(&priv->encoder);
+err_encoder:
+ adihdmi_destroy(&priv->base);
+ return ret;
+
+
+}
+
+static void adihdmi_unbind(struct device *dev, struct device *master, void *data)
+{
+ struct adihdmi2 *priv = dev_get_drvdata(dev);
+
+ drm_connector_cleanup(&priv->connector);
+ drm_encoder_cleanup(&priv->encoder);
+ adihdmi_destroy(&priv->base);
+}
+
+static const struct component_ops adihdmi_ops =
+{
+ .bind = adihdmi_bind,
+ .unbind = adihdmi_unbind,
+};
+
+/* -----------------------------------------------------------------------------
+ * Init operations
+ */
+
+static int adihdmi_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
+{
+ return component_add(&i2c->dev, &adihdmi_ops);
+}
+
+static int adihdmi_remove(struct i2c_client *i2c)
+{
+ component_del(&i2c->dev, &adihdmi_ops);
+
+ return 0;
+}
+
+static int adihdmi_encoder_init(struct i2c_client *i2c, struct drm_device *dev,
+ struct drm_encoder_slave *encoder_slave)
+{
+
+ struct adihdmi *adihdmi;
+ int ret;
+
+ adihdmi = kzalloc(sizeof(*adihdmi), GFP_KERNEL);
+ if (!adihdmi)
+ return -ENOMEM;
+
+ adihdmi->encoder = &encoder_slave->base;
+
+ ret = adihdmi_create(i2c, adihdmi);
+ if (ret) {
+ kfree(adihdmi);
+ return ret;
+ }
+
+ encoder_slave->slave_priv = adihdmi;
+ encoder_slave->slave_funcs = &adihdmi_encoder_slave_funcs;
+
+ return 0;
+}
+
+static const struct i2c_device_id adihdmi_i2c_ids[] = {
+ { "adv7511", 0 },
+ { "adv7511w", 0 },
+ { "adv7513", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, adihdmi_i2c_ids);
+
+static const struct of_device_id adihdmi_of_ids[] = {
+ { .compatible = "adi,adv7511", },
+ { .compatible = "adi,adv7511w", },
+ { .compatible = "adi,adv7513", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, adihdmi_of_ids);
+
+static struct drm_i2c_encoder_driver adihdmi_driver = {
+ .i2c_driver = {
+ .driver = {
+ .name = "adihdmi",
+ .of_match_table = adihdmi_of_ids,
+ },
+ .id_table = adihdmi_i2c_ids,
+ .probe = adihdmi_probe,
+ .remove = adihdmi_remove,
+ },
+
+ .encoder_init = adihdmi_encoder_init,
+};
+
+static int __init adihdmi_init(void)
+{
+ return drm_i2c_encoder_register(THIS_MODULE, &adihdmi_driver);
+}
+module_init(adihdmi_init);
+
+static void __exit adihdmi_exit(void)
+{
+ drm_i2c_encoder_unregister(&adihdmi_driver);
+}
+module_exit(adihdmi_exit);
+
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("ADIHDMI HDMI transmitter driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c b/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c
index 46855c8..d189426 100644
--- a/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c
+++ b/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c
@@ -234,25 +234,30 @@ static int tpd_probe(struct platform_device *pdev)
if (r)
return r;
-
gpio = devm_gpiod_get_index_optional(&pdev->dev, NULL, 0,
GPIOD_OUT_LOW);
- if (IS_ERR(gpio))
+ if (IS_ERR(gpio)) {
+ r = PTR_ERR(gpio);
goto err_gpio;
+ }
ddata->ct_cp_hpd_gpio = gpio;
gpio = devm_gpiod_get_index_optional(&pdev->dev, NULL, 1,
GPIOD_OUT_LOW);
- if (IS_ERR(gpio))
+ if (IS_ERR(gpio)) {
+ r = PTR_ERR(gpio);
goto err_gpio;
+ }
ddata->ls_oe_gpio = gpio;
gpio = devm_gpiod_get_index(&pdev->dev, NULL, 2,
GPIOD_IN);
- if (IS_ERR(gpio))
+ if (IS_ERR(gpio)) {
+ r = PTR_ERR(gpio);
goto err_gpio;
+ }
ddata->hpd_gpio = gpio;
diff --git a/drivers/input/misc/tps65218-pwrbutton.c b/drivers/input/misc/tps65218-pwrbutton.c
index 3273217..6f26022 100644
--- a/drivers/input/misc/tps65218-pwrbutton.c
+++ b/drivers/input/misc/tps65218-pwrbutton.c
@@ -36,7 +36,7 @@ struct tps6521x_data {
static const struct tps6521x_data tps65217_data = {
.reg_status = TPS65217_REG_STATUS,
.pb_mask = TPS65217_STATUS_PB,
- .name = "tps65217_pwrbutton",
+ .name = "tps65217_pwr_but",
};
static const struct tps6521x_data tps65218_data = {
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 215e91e..62abf02 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -775,6 +775,36 @@ config PANEL_BOOT_MESSAGE
An empty message will only clear the display at driver init time. Any other
printf()-formatted message is valid with newline and escape codes.
+config BONE_CAPEMGR
+ tristate "Beaglebone cape manager"
+ depends on ARCH_OMAP2PLUS && OF
+ select EEPROM
+ select OF_OVERLAY
+ help
+ Say Y here to include support for automatic loading of
+ beaglebone capes. Select M to build as a module which
+ will be named bone_capemgr.
+
+config DEV_OVERLAYMGR
+ tristate "Device overlay manager"
+ depends on OF
+ select OF_OVERLAY
+ default n
+ help
+ Say Y here to include support for the automagical dev
+ overlay manager.
+
+config TIEQEP
+ tristate "EQEP Hardware quadrature encoder controller"
+ depends on SOC_AM33XX
+ select PWM_TIPWMSS
+ help
+ Driver support for the EQEP quadrature encoder controller AM33XX
+ TI SOC
+
+ To compile this driver as a module, choose M here: the module
+ will be called tieqep.
+
source "drivers/misc/c2port/Kconfig"
source "drivers/misc/eeprom/Kconfig"
source "drivers/misc/cb710/Kconfig"
@@ -784,7 +814,9 @@ source "drivers/misc/altera-stapl/Kconfig"
source "drivers/misc/mei/Kconfig"
source "drivers/misc/vmw_vmci/Kconfig"
source "drivers/misc/mic/Kconfig"
+source "drivers/misc/cape_bone_argus/Kconfig"
source "drivers/misc/genwqe/Kconfig"
+source "drivers/misc/cape/Kconfig"
source "drivers/misc/echo/Kconfig"
source "drivers/misc/cxl/Kconfig"
endmenu
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 3198336..7fc8cfd 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -48,11 +48,16 @@ obj-$(CONFIG_VMWARE_VMCI) += vmw_vmci/
obj-$(CONFIG_LATTICE_ECP3_CONFIG) += lattice-ecp3-config.o
obj-$(CONFIG_SRAM) += sram.o
obj-y += mic/
+obj-y += cape_bone_argus/
obj-$(CONFIG_GENWQE) += genwqe/
+obj-y += cape/
obj-$(CONFIG_ECHO) += echo/
obj-$(CONFIG_VEXPRESS_SYSCFG) += vexpress-syscfg.o
obj-$(CONFIG_CXL_BASE) += cxl/
obj-$(CONFIG_PANEL) += panel.o
+obj-$(CONFIG_TIEQEP) += tieqep.o
+obj-$(CONFIG_BONE_CAPEMGR) += bone_capemgr.o
+obj-$(CONFIG_DEV_OVERLAYMGR) += devovmgr.o
lkdtm-$(CONFIG_LKDTM) += lkdtm_core.o
lkdtm-$(CONFIG_LKDTM) += lkdtm_bugs.o
diff --git b/drivers/misc/bone_capemgr.c b/drivers/misc/bone_capemgr.c
new file mode 100644
index 0000000..f82623d
--- /dev/null
+++ b/drivers/misc/bone_capemgr.c
@@ -0,0 +1,1885 @@
+/*
+ * TI Beaglebone cape manager
+ *
+ * Copyright (C) 2012 Texas Instruments Inc.
+ * Copyright (C) 2012-2015 Konsulko Group.
+ * Author: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/completion.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_fdt.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/firmware.h>
+#include <linux/err.h>
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/memory.h>
+#include <linux/kthread.h>
+#include <linux/wait.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/nvmem-consumer.h>
+
+/* disabled capes */
+static char *disable_partno;
+module_param(disable_partno, charp, 0444);
+MODULE_PARM_DESC(disable_partno,
+ "Comma delimited list of PART-NUMBER[:REV] of disabled capes");
+
+/* enable capes */
+static char *enable_partno;
+module_param(enable_partno, charp, 0444);
+MODULE_PARM_DESC(enable_partno,
+ "Comma delimited list of PART-NUMBER[:REV] of enabled capes");
+
+/* delay to scan on boot until rootfs appears */
+static int boot_scan_period = 1000;
+module_param(boot_scan_period, int, 0444);
+MODULE_PARM_DESC(boot_scan_period,
+ "boot scan period until rootfs firmware is available");
+
+struct capemgr_info;
+
+struct slot_ee_attribute {
+ struct device_attribute devattr;
+ unsigned int field;
+ struct bone_cape_slot *slot; /* this is filled when instantiated */
+};
+#define to_slot_ee_attribute(x) \
+ container_of((x), struct slot_ee_attribute, devattr)
+
+struct bbrd_ee_attribute {
+ struct device_attribute devattr;
+ unsigned int field;
+};
+#define to_bbrd_ee_attribute(x) \
+ container_of((x), struct bbrd_ee_attribute, devattr)
+
+struct bone_cape_slot {
+ struct list_head node;
+ struct capemgr_info *info;
+ int slotno;
+ struct nvmem_cell *nvmem_cell;
+
+ char text_id[256];
+ char signature[256];
+ /* quick access */
+ char board_name[32+1];
+ char version[4+1];
+ char manufacturer[16+1];
+ char part_number[16+1];
+
+ /* attribute group */
+ char *ee_attr_name;
+ int ee_attrs_count;
+ struct slot_ee_attribute *ee_attrs;
+ struct attribute **ee_attrs_tab;
+ struct attribute_group attrgroup;
+
+ /* state flags */
+ unsigned int probed : 1;
+ unsigned int probe_failed : 1;
+ unsigned int override : 1;
+ unsigned int loading : 1;
+ unsigned int loaded : 1;
+ unsigned int retry_loading : 1;
+ unsigned int disabled : 1;
+
+ char *dtbo;
+ const struct firmware *fw;
+ struct device_node *overlay;
+ int overlay_id;
+
+ /* loader thread */
+ struct task_struct *loader_thread;
+
+ /* load priority */
+ int priority;
+};
+
+struct bone_baseboard {
+
+ /* from the matched boardmap node */
+ char *compatible_name;
+
+ /* filled in by reading the eeprom */
+ char signature[256];
+ char text_id[64+1];
+
+ /* quick access */
+ char board_name[8+1];
+ char revision[4+1];
+ char serial_number[12+1];
+
+ /* access to the eeprom */
+ struct nvmem_cell *nvmem_cell;
+};
+
+struct capemgr_info {
+ struct platform_device *pdev;
+
+ atomic_t next_slot_nr;
+ struct list_head slot_list;
+ struct mutex slots_list_mutex;
+
+ /* baseboard EEPROM data */
+ struct bone_baseboard baseboard;
+
+ /* wait queue for keeping the priorities straight */
+ wait_queue_head_t load_wq;
+};
+
+static int bone_slot_fill_override(struct bone_cape_slot *slot,
+ const char *part_number, const char *version);
+static struct bone_cape_slot *capemgr_add_slot(
+ struct capemgr_info *info, const char *slot_name,
+ const char *part_number, const char *version, int prio);
+static int capemgr_remove_slot_no_lock(struct bone_cape_slot *slot);
+static int capemgr_remove_slot(struct bone_cape_slot *slot);
+static int capemgr_load_slot(struct bone_cape_slot *slot);
+static int capemgr_unload_slot(struct bone_cape_slot *slot);
+
+/* baseboard EEPROM field definition */
+#define BBRD_EE_FIELD_HEADER 0
+#define BBRD_EE_FIELD_BOARD_NAME 1
+#define BBRD_EE_FIELD_REVISION 2
+#define BBRD_EE_FIELD_SERIAL_NUMBER 3
+#define BBRD_EE_FIELD_CONFIG_OPTION 4
+#define BBRD_EE_FILED_RSVD1 5
+#define BBRD_EE_FILED_RSVD2 6
+#define BBRD_EE_FILED_RSVD3 7
+
+/* cape EEPROM field definitions */
+#define CAPE_EE_FIELD_HEADER 0
+#define CAPE_EE_FIELD_EEPROM_REV 1
+#define CAPE_EE_FIELD_BOARD_NAME 2
+#define CAPE_EE_FIELD_VERSION 3
+#define CAPE_EE_FIELD_MANUFACTURER 4
+#define CAPE_EE_FIELD_PART_NUMBER 5
+#define CAPE_EE_FIELD_NUMBER_OF_PINS 6
+#define CAPE_EE_FIELD_SERIAL_NUMBER 7
+#define CAPE_EE_FIELD_PIN_USAGE 8
+#define CAPE_EE_FIELD_VDD_3V3EXP 9
+#define CAPE_EE_FIELD_VDD_5V 10
+#define CAPE_EE_FIELD_SYS_5V 11
+#define CAPE_EE_FIELD_DC_SUPPLIED 12
+#define CAPE_EE_FIELD_FIELDS_NR 13
+
+#define EE_FIELD_MAKE_HEADER(p) \
+ ({ \
+ const u8 *_p = (p); \
+ (((u32)_p[0] << 24) | ((u32)_p[1] << 16) | \
+ ((u32)_p[2] << 8) | (u32)_p[3]); \
+ })
+
+#define EE_FIELD_HEADER_VALID 0xaa5533ee
+
+struct ee_field {
+ const char *name;
+ int start;
+ int size;
+ unsigned int ascii : 1;
+ unsigned int strip_trailing_dots : 1;
+ const char *override;
+};
+
+/* baseboard EEPROM definitions */
+static const struct ee_field bbrd_sig_fields[] = {
+ [BBRD_EE_FIELD_HEADER] = {
+ .name = "header",
+ .start = 0,
+ .size = 4,
+ .ascii = 0,
+ .override = "\xaa\x55\x33\xee", /* AA 55 33 EE */
+ },
+ [BBRD_EE_FIELD_BOARD_NAME] = {
+ .name = "board-name",
+ .start = 4,
+ .size = 8,
+ .ascii = 1,
+ .strip_trailing_dots = 1,
+ .override = "Board Name",
+ },
+ [BBRD_EE_FIELD_REVISION] = {
+ .name = "revision",
+ .start = 12,
+ .size = 4,
+ .ascii = 1,
+ .override = "00A0",
+ },
+ [BBRD_EE_FIELD_SERIAL_NUMBER] = {
+ .name = "serial-number",
+ .start = 16,
+ .size = 12,
+ .ascii = 1,
+ .override = "0000000000",
+ },
+ [BBRD_EE_FIELD_CONFIG_OPTION] = {
+ .name = "config-option",
+ .start = 28,
+ .size = 32,
+ },
+};
+
+/* cape EEPROM definitions */
+static const struct ee_field cape_sig_fields[] = {
+ [CAPE_EE_FIELD_HEADER] = {
+ .name = "header",
+ .start = 0,
+ .size = 4,
+ .ascii = 0,
+ .override = "\xaa\x55\x33\xee", /* AA 55 33 EE */
+ },
+ [CAPE_EE_FIELD_EEPROM_REV] = {
+ .name = "eeprom-format-revision",
+ .start = 4,
+ .size = 2,
+ .ascii = 1,
+ .override = "A0",
+ },
+ [CAPE_EE_FIELD_BOARD_NAME] = {
+ .name = "board-name",
+ .start = 6,
+ .size = 32,
+ .ascii = 1,
+ .strip_trailing_dots = 1,
+ .override = "Override Board Name",
+ },
+ [CAPE_EE_FIELD_VERSION] = {
+ .name = "version",
+ .start = 38,
+ .size = 4,
+ .ascii = 1,
+ .override = "00A0",
+ },
+ [CAPE_EE_FIELD_MANUFACTURER] = {
+ .name = "manufacturer",
+ .start = 42,
+ .size = 16,
+ .ascii = 1,
+ .strip_trailing_dots = 1,
+ .override = "Override Manuf",
+ },
+ [CAPE_EE_FIELD_PART_NUMBER] = {
+ .name = "part-number",
+ .start = 58,
+ .size = 16,
+ .ascii = 1,
+ .strip_trailing_dots = 1,
+ .override = "Override Part#",
+ },
+ [CAPE_EE_FIELD_NUMBER_OF_PINS] = {
+ .name = "number-of-pins",
+ .start = 74,
+ .size = 2,
+ .ascii = 0,
+ .override = NULL,
+ },
+ [CAPE_EE_FIELD_SERIAL_NUMBER] = {
+ .name = "serial-number",
+ .start = 76,
+ .size = 12,
+ .ascii = 1,
+ .override = "0000000000",
+ },
+ [CAPE_EE_FIELD_PIN_USAGE] = {
+ .name = "pin-usage",
+ .start = 88,
+ .size = 140,
+ .ascii = 0,
+ .override = NULL,
+ },
+ [CAPE_EE_FIELD_VDD_3V3EXP] = {
+ .name = "vdd-3v3exp",
+ .start = 228,
+ .size = 2,
+ .ascii = 0,
+ .override = NULL,
+ },
+ [CAPE_EE_FIELD_VDD_5V] = {
+ .name = "vdd-5v",
+ .start = 230,
+ .size = 2,
+ .ascii = 0,
+ .override = NULL,
+ },
+ [CAPE_EE_FIELD_SYS_5V] = {
+ .name = "sys-5v",
+ .start = 232,
+ .size = 2,
+ .ascii = 0,
+ .override = NULL,
+ },
+ [CAPE_EE_FIELD_DC_SUPPLIED] = {
+ .name = "dc-supplied",
+ .start = 234,
+ .size = 2,
+ .ascii = 0,
+ .override = NULL,
+ },
+};
+
+static char *ee_field_get(const struct ee_field *sig_field,
+ const void *data, int field, char *buf, int bufsz)
+{
+ int len;
+
+ /* enough space? */
+ if (bufsz < sig_field->size + sig_field->ascii)
+ return NULL;
+
+ memcpy(buf, (char *)data + sig_field->start, sig_field->size);
+
+ /* terminate ascii field */
+ if (sig_field->ascii)
+ buf[sig_field->size] = '\0';
+
+ if (sig_field->strip_trailing_dots) {
+ len = strlen(buf);
+ while (len > 1 && buf[len - 1] == '.')
+ buf[--len] = '\0';
+ }
+
+ return buf;
+}
+
+char *bbrd_ee_field_get(const void *data,
+ int field, char *buf, int bufsz)
+{
+ if ((unsigned int)field >= ARRAY_SIZE(bbrd_sig_fields))
+ return NULL;
+
+ return ee_field_get(&bbrd_sig_fields[field], data, field, buf, bufsz);
+}
+
+char *cape_ee_field_get(const void *data,
+ int field, char *buf, int bufsz)
+{
+ if ((unsigned int)field >= ARRAY_SIZE(cape_sig_fields))
+ return NULL;
+
+ return ee_field_get(&cape_sig_fields[field], data, field, buf, bufsz);
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id capemgr_of_match[] = {
+ {
+ .compatible = "ti,bone-capemgr",
+ },
+ { },
+};
+MODULE_DEVICE_TABLE(of, capemgr_of_match);
+
+#endif
+
+static int bone_baseboard_scan(struct bone_baseboard *bbrd)
+{
+ struct capemgr_info *info = container_of(bbrd,
+ struct capemgr_info, baseboard);
+ const u8 *p;
+ int ret;
+ size_t len;
+
+ p = nvmem_cell_read(bbrd->nvmem_cell, &len);
+ if (IS_ERR(p)) {
+ ret = PTR_ERR(p);
+ dev_err(&info->pdev->dev,
+ "Cannot read cell (ret=%d)\n", ret);
+ return ret;
+ }
+ if (len < sizeof(bbrd->signature)) {
+ dev_info(&info->pdev->dev,
+ "Short read %d (should be >= %d bytes)\n",
+ len, sizeof(bbrd->signature));
+ return -EINVAL;
+ }
+ memcpy(bbrd->signature, p, sizeof(bbrd->signature));
+
+ p = bbrd->signature;
+ if (EE_FIELD_MAKE_HEADER(p) != EE_FIELD_HEADER_VALID) {
+ dev_err(&info->pdev->dev, "Invalid board signature '%08x'\n",
+ EE_FIELD_MAKE_HEADER(p));
+ return -ENODEV;
+ }
+
+ bbrd_ee_field_get(bbrd->signature,
+ BBRD_EE_FIELD_BOARD_NAME,
+ bbrd->board_name, sizeof(bbrd->board_name));
+ bbrd_ee_field_get(bbrd->signature,
+ BBRD_EE_FIELD_REVISION,
+ bbrd->revision, sizeof(bbrd->revision));
+ bbrd_ee_field_get(bbrd->signature,
+ BBRD_EE_FIELD_SERIAL_NUMBER,
+ bbrd->serial_number, sizeof(bbrd->serial_number));
+
+ /* board_name,version,manufacturer,part_number */
+ snprintf(bbrd->text_id, sizeof(bbrd->text_id) - 1,
+ "%s,%s,%s", bbrd->board_name, bbrd->revision,
+ bbrd->serial_number);
+
+ /* terminate always */
+ bbrd->text_id[sizeof(bbrd->text_id) - 1] = '\0';
+
+ return 0;
+}
+
+static int bone_slot_scan(struct bone_cape_slot *slot)
+{
+ struct capemgr_info *info = slot->info;
+ const u8 *p;
+ int r;
+ ssize_t len;
+
+ /* need to read EEPROM? */
+ if (slot->probed)
+ goto slot_fail_check;
+
+ slot->probed = 1;
+
+ if (!slot->override) {
+
+ p = nvmem_cell_read(slot->nvmem_cell, &len);
+ if (IS_ERR(p)) {
+ r = PTR_ERR(p);
+ slot->probe_failed = 1;
+
+ /* timeout is normal when no cape is present */
+ if (r != -ETIMEDOUT)
+ dev_err(&info->pdev->dev,
+ "Cannot read cell (ret=%d)\n", r);
+ return r;
+ }
+ if (len < sizeof(slot->signature)) {
+ dev_info(&info->pdev->dev,
+ "Short read %d (should be >= %d bytes)\n",
+ len, sizeof(slot->signature));
+ return -EINVAL;
+ }
+ memcpy(slot->signature, p, sizeof(slot->signature));
+
+ } else
+ dev_info(&info->pdev->dev,
+ "Using override eeprom data at slot %d\n",
+ slot->slotno);
+
+ p = slot->signature;
+ if (EE_FIELD_MAKE_HEADER(p) != EE_FIELD_HEADER_VALID) {
+ dev_err(&info->pdev->dev,
+ "Invalid signature '%08x' at slot %d\n",
+ EE_FIELD_MAKE_HEADER(p), slot->slotno);
+ slot->probe_failed = 1;
+ return -ENODEV;
+ }
+
+ cape_ee_field_get(slot->signature,
+ CAPE_EE_FIELD_BOARD_NAME,
+ slot->board_name, sizeof(slot->board_name));
+ cape_ee_field_get(slot->signature,
+ CAPE_EE_FIELD_VERSION,
+ slot->version, sizeof(slot->version));
+ cape_ee_field_get(slot->signature,
+ CAPE_EE_FIELD_MANUFACTURER,
+ slot->manufacturer, sizeof(slot->manufacturer));
+ cape_ee_field_get(slot->signature,
+ CAPE_EE_FIELD_PART_NUMBER,
+ slot->part_number, sizeof(slot->part_number));
+
+ /* board_name,version,manufacturer,part_number */
+ snprintf(slot->text_id, sizeof(slot->text_id) - 1,
+ "%s,%s,%s,%s", slot->board_name, slot->version,
+ slot->manufacturer, slot->part_number);
+
+ /* terminate always */
+ slot->text_id[sizeof(slot->text_id) - 1] = '\0';
+
+slot_fail_check:
+ /* slot has failed and we don't support hotpluging */
+ if (slot->probe_failed)
+ return -ENODEV;
+
+ return 0;
+}
+
+/* return 0 if not matched,, 1 if matched */
+static int bone_match_cape(const char *match,
+ const char *part_number, const char *version)
+{
+ char *tmp_part_number, *tmp_version;
+ char *buf, *s, *e, *sn;
+ int found;
+
+ if (match == NULL || part_number == NULL)
+ return 0;
+
+ /* copy the argument to work on it */
+ buf = kstrdup(match, GFP_KERNEL);
+
+ /* no memory, too bad... */
+ if (buf == NULL)
+ return 0;
+
+ found = 0;
+ s = buf;
+ e = s + strlen(s);
+ while (s < e) {
+ /* find comma separator */
+ sn = strchr(s, ',');
+ if (sn != NULL)
+ *sn++ = '\0';
+ else
+ sn = e;
+ tmp_part_number = s;
+ tmp_version = strchr(tmp_part_number, ':');
+ if (tmp_version != NULL)
+ *tmp_version++ = '\0';
+ s = sn;
+
+ /* the part names must match */
+ if (strcmp(tmp_part_number, part_number) != 0)
+ continue;
+
+ /* if there's no version, match any */
+ if (version == NULL || tmp_version == NULL ||
+ strcmp(version, tmp_version) == 0) {
+ found = 1;
+ break;
+ }
+ }
+
+ kfree(buf);
+
+ return found;
+}
+
+/* helper method */
+static int of_multi_prop_cmp(const struct property *prop, const char *value)
+{
+ const char *cp;
+ int cplen, vlen, l;
+
+ /* check if it's directly compatible */
+ cp = prop->value;
+ cplen = prop->length;
+ vlen = strlen(value);
+
+ while (cplen > 0) {
+ /* compatible? */
+ if (of_compat_cmp(cp, value, vlen) == 0)
+ return 0;
+ l = strlen(cp) + 1;
+ cp += l;
+ cplen -= l;
+ }
+ return -1;
+}
+
+static ssize_t slot_ee_attr_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct slot_ee_attribute *ee_attr = to_slot_ee_attribute(attr);
+ struct bone_cape_slot *slot = ee_attr->slot;
+ const struct ee_field *sig_field;
+ int i, len;
+ char *p, *s;
+ u16 val;
+
+ /* add newline for ascii fields */
+ sig_field = &cape_sig_fields[ee_attr->field];
+
+ len = sig_field->size + sig_field->ascii;
+ p = kmalloc(len, GFP_KERNEL);
+ if (p == NULL)
+ return -ENOMEM;
+
+ s = cape_ee_field_get(slot->signature, ee_attr->field, p, len);
+ if (s == NULL)
+ return -EINVAL;
+
+ /* add newline for ascii fields and return */
+ if (sig_field->ascii) {
+ len = sprintf(buf, "%s\n", s);
+ goto out;
+ }
+
+ /* case by case handling */
+ switch (ee_attr->field) {
+ case CAPE_EE_FIELD_HEADER:
+ len = sprintf(buf, "%02x %02x %02x %02x\n",
+ s[0], s[1], s[2], s[3]);
+ break;
+
+ /* 2 bytes */
+ case CAPE_EE_FIELD_NUMBER_OF_PINS:
+ case CAPE_EE_FIELD_VDD_3V3EXP:
+ case CAPE_EE_FIELD_VDD_5V:
+ case CAPE_EE_FIELD_SYS_5V:
+ case CAPE_EE_FIELD_DC_SUPPLIED:
+ /* the bone is LE */
+ val = s[0] & (s[1] << 8);
+ len = sprintf(buf, "%u\n", (unsigned int)val & 0xffff);
+ break;
+
+ case CAPE_EE_FIELD_PIN_USAGE:
+
+ len = 0;
+ for (i = 0; i < sig_field->size / 2; i++) {
+ /* the bone is LE */
+ val = s[0] & (s[1] << 8);
+ sprintf(buf, "%04x\n", val);
+ buf += 5;
+ len += 5;
+ s += 2;
+ }
+
+ break;
+
+ default:
+ *buf = '\0';
+ len = 0;
+ break;
+ }
+
+out:
+ kfree(p);
+
+ return len;
+}
+
+#define SLOT_EE_ATTR(_name, _field) \
+ { \
+ .devattr = __ATTR(_name, S_IRUGO, slot_ee_attr_show, NULL), \
+ .field = CAPE_EE_FIELD_##_field, \
+ .slot = NULL, \
+ }
+
+static const struct slot_ee_attribute slot_ee_attrs[] = {
+ SLOT_EE_ATTR(header, HEADER),
+ SLOT_EE_ATTR(eeprom-format-revision, EEPROM_REV),
+ SLOT_EE_ATTR(board-name, BOARD_NAME),
+ SLOT_EE_ATTR(version, VERSION),
+ SLOT_EE_ATTR(manufacturer, MANUFACTURER),
+ SLOT_EE_ATTR(part-number, PART_NUMBER),
+ SLOT_EE_ATTR(number-of-pins, NUMBER_OF_PINS),
+ SLOT_EE_ATTR(serial-number, SERIAL_NUMBER),
+ SLOT_EE_ATTR(pin-usage, PIN_USAGE),
+ SLOT_EE_ATTR(vdd-3v3exp, VDD_3V3EXP),
+ SLOT_EE_ATTR(vdd-5v, VDD_5V),
+ SLOT_EE_ATTR(sys-5v, SYS_5V),
+ SLOT_EE_ATTR(dc-supplied, DC_SUPPLIED),
+};
+
+static int bone_cape_slot_sysfs_register(struct bone_cape_slot *slot)
+{
+ struct capemgr_info *info = slot->info;
+ struct device *dev = &info->pdev->dev;
+ struct slot_ee_attribute *ee_attr;
+ struct attribute_group *attrgroup;
+ int i, err, sz;
+
+ slot->ee_attr_name = kasprintf(GFP_KERNEL, "slot-%d", slot->slotno);
+ if (slot->ee_attr_name == NULL) {
+ dev_err(dev, "slot #%d: Failed to allocate ee_attr_name\n",
+ slot->slotno);
+ err = -ENOMEM;
+ goto err_fail_no_ee_attr_name;
+ }
+
+ slot->ee_attrs_count = ARRAY_SIZE(slot_ee_attrs);
+
+ sz = slot->ee_attrs_count * sizeof(*slot->ee_attrs);
+ slot->ee_attrs = kmalloc(sz, GFP_KERNEL);
+ if (slot->ee_attrs == NULL) {
+ dev_err(dev, "slot #%d: Failed to allocate ee_attrs\n",
+ slot->slotno);
+ err = -ENOMEM;
+ goto err_fail_no_ee_attrs;
+ }
+
+ attrgroup = &slot->attrgroup;
+ memset(attrgroup, 0, sizeof(*attrgroup));
+ attrgroup->name = slot->ee_attr_name;
+
+ sz = sizeof(*slot->ee_attrs_tab) * (slot->ee_attrs_count + 1);
+ attrgroup->attrs = kmalloc(sz, GFP_KERNEL);
+ if (attrgroup->attrs == NULL) {
+ dev_err(dev, "slot #%d: Failed to allocate ee_attrs_tab\n",
+ slot->slotno);
+ err = -ENOMEM;
+ goto err_fail_no_ee_attrs_tab;
+ }
+ /* copy everything over */
+ memcpy(slot->ee_attrs, slot_ee_attrs, sizeof(slot_ee_attrs));
+
+ /* bind this attr to the slot */
+ for (i = 0; i < slot->ee_attrs_count; i++) {
+ ee_attr = &slot->ee_attrs[i];
+ ee_attr->slot = slot;
+ attrgroup->attrs[i] = &ee_attr->devattr.attr;
+ }
+ attrgroup->attrs[i] = NULL;
+
+ /* make lockdep happy */
+ for (i = 0; i < slot->ee_attrs_count; i++) {
+ ee_attr = &slot->ee_attrs[i];
+ sysfs_attr_init(&ee_attr->devattr.attr);
+ }
+
+ err = sysfs_create_group(&dev->kobj, attrgroup);
+ if (err != 0) {
+ dev_err(dev, "slot #%d: Failed to allocate ee_attrs_tab\n",
+ slot->slotno);
+ err = -ENOMEM;
+ goto err_fail_no_ee_attrs_group;
+ }
+
+ return 0;
+
+err_fail_no_ee_attrs_group:
+ kfree(slot->ee_attrs_tab);
+err_fail_no_ee_attrs_tab:
+ kfree(slot->ee_attrs);
+err_fail_no_ee_attrs:
+ kfree(slot->ee_attr_name);
+err_fail_no_ee_attr_name:
+ return err;
+}
+
+static void bone_cape_slot_sysfs_unregister(struct bone_cape_slot *slot)
+{
+ struct capemgr_info *info = slot->info;
+ struct device *dev = &info->pdev->dev;
+
+ sysfs_remove_group(&dev->kobj, &slot->attrgroup);
+ kfree(slot->ee_attrs_tab);
+ kfree(slot->ee_attrs);
+ kfree(slot->ee_attr_name);
+}
+
+static ssize_t bbrd_ee_attr_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct bbrd_ee_attribute *ee_attr = to_bbrd_ee_attribute(attr);
+ struct platform_device *pdev = to_platform_device(dev);
+ struct capemgr_info *info = platform_get_drvdata(pdev);
+ struct bone_baseboard *bbrd = &info->baseboard;
+ const struct ee_field *sig_field;
+ u16 val;
+ int i, len;
+ char *p, *s;
+
+ /* add newline for ascii fields */
+ sig_field = &bbrd_sig_fields[ee_attr->field];
+
+ len = sig_field->size + sig_field->ascii;
+ p = kmalloc(len, GFP_KERNEL);
+ if (p == NULL)
+ return -ENOMEM;
+
+ s = bbrd_ee_field_get(bbrd->signature, ee_attr->field, p, len);
+ if (s == NULL)
+ return -EINVAL;
+
+ /* add newline for ascii fields and return */
+ if (sig_field->ascii) {
+ len = sprintf(buf, "%s\n", s);
+ goto out;
+ }
+
+ /* case by case handling */
+ switch (ee_attr->field) {
+ case BBRD_EE_FIELD_HEADER:
+ len = sprintf(buf, "%02x %02x %02x %02x\n",
+ s[0], s[1], s[2], s[3]);
+ break;
+
+ case BBRD_EE_FIELD_CONFIG_OPTION:
+ len = 0;
+ for (i = 0; i < sig_field->size / 2; i++) {
+ /* the bone is LE */
+ val = s[0] & (s[1] << 8);
+ sprintf(buf, "%04x\n", val);
+ buf += 5;
+ len += 5;
+ s += 2;
+ }
+ break;
+
+ default:
+ *buf = '\0';
+ len = 0;
+ break;
+ }
+
+out:
+ kfree(p);
+
+ return len;
+}
+
+#define BBRD_EE_ATTR(_name, _field) \
+ { \
+ .devattr = __ATTR(_name, 0440, bbrd_ee_attr_show, NULL), \
+ .field = BBRD_EE_FIELD_##_field, \
+ }
+
+static struct bbrd_ee_attribute bbrd_ee_attrs[] = {
+ BBRD_EE_ATTR(header, HEADER),
+ BBRD_EE_ATTR(board-name, BOARD_NAME),
+ BBRD_EE_ATTR(revision, REVISION),
+ BBRD_EE_ATTR(serial-number, SERIAL_NUMBER),
+ BBRD_EE_ATTR(config-option, CONFIG_OPTION),
+};
+
+static struct attribute *bbrd_attrs_flat[] = {
+ &bbrd_ee_attrs[BBRD_EE_FIELD_HEADER].devattr.attr,
+ &bbrd_ee_attrs[BBRD_EE_FIELD_BOARD_NAME].devattr.attr,
+ &bbrd_ee_attrs[BBRD_EE_FIELD_REVISION].devattr.attr,
+ &bbrd_ee_attrs[BBRD_EE_FIELD_SERIAL_NUMBER].devattr.attr,
+ &bbrd_ee_attrs[BBRD_EE_FIELD_CONFIG_OPTION].devattr.attr,
+ NULL,
+};
+
+static const struct attribute_group bbrd_attr_group = {
+ .name = "baseboard",
+ .attrs = bbrd_attrs_flat,
+};
+
+static ssize_t slots_show(struct device *dev, struct device_attribute *attr,
+ char *buf);
+static ssize_t slots_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count);
+
+static DEVICE_ATTR(slots, 0644, slots_show, slots_store);
+
+static struct attribute *root_attrs_flat[] = {
+ &dev_attr_slots.attr,
+ NULL,
+};
+
+static const struct attribute_group root_attr_group = {
+ .attrs = root_attrs_flat,
+};
+
+static const struct attribute_group *attr_groups[] = {
+ &root_attr_group,
+ &bbrd_attr_group,
+ NULL,
+};
+
+static ssize_t slots_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct capemgr_info *info = platform_get_drvdata(pdev);
+ struct bone_cape_slot *slot;
+ ssize_t len, sz;
+
+ mutex_lock(&info->slots_list_mutex);
+ sz = 0;
+ list_for_each_entry(slot, &info->slot_list, node) {
+
+ len = sprintf(buf, "%2d: %c%c%c%c%c%c %3d %s\n",
+ slot->slotno,
+ slot->probed ? 'P' : '-',
+ slot->probe_failed ? 'F' : '-',
+ slot->override ? 'O' : '-',
+ slot->loading ? 'l' : '-',
+ slot->loaded ? 'L' : '-',
+ slot->disabled ? 'D' : '-',
+ slot->overlay_id, slot->text_id);
+
+ buf += len;
+ sz += len;
+ }
+ mutex_unlock(&info->slots_list_mutex);
+
+ return sz;
+}
+
+static ssize_t slots_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct capemgr_info *info = platform_get_drvdata(pdev);
+ struct bone_cape_slot *slot;
+ struct device_node *pnode, *node;
+ char *s, *part_number, *version;
+ int ret;
+ int slotno;
+
+ /* check for remove slot */
+ if (strlen(buf) > 0 && buf[0] == '-') {
+ ret = kstrtoint(buf + 1, 10, &slotno);
+ if (ret != 0)
+ return ret;
+
+ /* now load each (take lock to be sure */
+ mutex_lock(&info->slots_list_mutex);
+ list_for_each_entry(slot, &info->slot_list, node) {
+ if (slotno == slot->slotno)
+ goto found;
+ }
+
+ mutex_unlock(&info->slots_list_mutex);
+ return -ENODEV;
+found:
+ /* the hardware slots just get unloaded */
+ if (!slot->override) {
+ ret = capemgr_unload_slot(slot);
+ if (ret == 0)
+ dev_info(&pdev->dev,
+ "Unloaded slot #%d\n", slotno);
+ else
+ dev_err(&pdev->dev,
+ "Failed to unload slot #%d\n", slotno);
+ } else {
+ ret = capemgr_remove_slot_no_lock(slot);
+ if (ret == 0)
+ dev_info(&pdev->dev,
+ "Removed slot #%d\n", slotno);
+ else
+ dev_err(&pdev->dev,
+ "Failed to remove slot #%d\n", slotno);
+ }
+ mutex_unlock(&info->slots_list_mutex);
+
+ return ret == 0 ? strlen(buf) : ret;
+ }
+
+ part_number = kstrdup(buf, GFP_KERNEL);
+ if (part_number == NULL)
+ return -ENOMEM;
+
+ /* remove trailing spaces dots and newlines */
+ s = part_number + strlen(part_number);
+ while (s > part_number &&
+ (isspace(s[-1]) || s[-1] == '\n' || s[-1] == '.'))
+ *--s = '\0';
+
+ version = strchr(part_number, ':');
+ if (version != NULL)
+ *version++ = '\0';
+
+ dev_info(&pdev->dev, "part_number '%s', version '%s'\n",
+ part_number, version ? version : "N/A");
+
+ pnode = pdev->dev.of_node;
+ node = NULL;
+ slot = NULL;
+ ret = 0;
+
+ /* no specific slot found, try immediate */
+ slot = capemgr_add_slot(info, NULL, part_number, version, 0);
+
+ if (IS_ERR_OR_NULL(slot)) {
+ dev_err(&pdev->dev, "Failed to add slot #%d\n",
+ atomic_read(&info->next_slot_nr) - 1);
+ ret = slot ? PTR_ERR(slot) : -ENODEV;
+ slot = NULL;
+ goto err_fail;
+ }
+
+ kfree(part_number);
+
+ ret = capemgr_load_slot(slot);
+ if (ret != 0)
+ capemgr_remove_slot(slot);
+
+ return ret == 0 ? strlen(buf) : ret;
+err_fail:
+ of_node_put(node);
+ kfree(part_number);
+ return ret;
+}
+
+/* verify the overlay */
+static int capemgr_verify_overlay(struct bone_cape_slot *slot)
+{
+ struct capemgr_info *info = slot->info;
+ struct device *dev = &info->pdev->dev;
+ struct bone_baseboard *bbrd = &info->baseboard;
+ struct device_node *node = slot->overlay;
+ struct property *prop;
+ struct bone_cape_slot *slotn;
+ int err, counta, countb, i, j;
+ const char *ra, *rb;
+
+ /* validate */
+ if (node == NULL) {
+ dev_err(dev, "slot #%d: No overlay for '%s'\n",
+ slot->slotno, slot->part_number);
+ return -EINVAL;
+ }
+
+ /* check if the slot is compatible with the board */
+ prop = of_find_property(node, "compatible", NULL);
+
+ /* no compatible property? */
+ if (prop == NULL) {
+ dev_err(dev, "slot #%d: No compatible property for '%s'\n",
+ slot->slotno, slot->part_number);
+ return -EINVAL;
+ }
+
+ /* verify that the cape is baseboard compatible */
+ if (of_multi_prop_cmp(prop, bbrd->compatible_name) != 0) {
+ dev_err(dev, "slot #%d: Incompatible with baseboard for '%s'\n",
+ slot->slotno, slot->part_number);
+ return -EINVAL;
+ }
+
+ /* count the strings */
+ counta = of_property_count_strings(node, "exclusive-use");
+ /* no valid property, or no resources; no matter, it's OK */
+ if (counta <= 0)
+ return 0;
+
+ /* and now check if there's a resource conflict */
+ err = 0;
+ mutex_lock(&info->slots_list_mutex);
+ for (i = 0; i < counta; i++) {
+
+ ra = NULL;
+ err = of_property_read_string_index(node, "exclusive-use",
+ i, &ra);
+ if (err != 0) {
+ dev_err(dev, "slot #%d: Could not read string #%d\n",
+ slot->slotno, i);
+ break;
+ }
+
+ list_for_each_entry(slotn, &info->slot_list, node) {
+
+ /* don't check against self */
+ if (slot == slotn)
+ continue;
+
+ /* only check against loaded or loading slots */
+ if (!slotn->loaded && !slotn->loading)
+ continue;
+
+ countb = of_property_count_strings(slotn->overlay,
+ "exclusive-use");
+ /* no valid property, or resources; it's OK */
+ if (countb <= 0)
+ continue;
+
+
+ for (j = 0; j < countb; j++) {
+
+ /* count the resources */
+ rb = NULL;
+ err = of_property_read_string_index(
+ slotn->overlay, "exclusive-use",
+ j, &rb);
+ if (err != 0) {
+ /* error, but we don't care */
+ err = 0;
+ break;
+ }
+
+ /* ignore case; just in case ;) */
+ if (strcasecmp(ra, rb) == 0) {
+
+ /* resource conflict */
+ err = -EEXIST;
+ dev_err(dev,
+ "slot #%d: %s conflict %s (#%d:%s)\n",
+ slot->slotno,
+ slot->part_number, ra,
+ slotn->slotno,
+ slotn->part_number);
+ goto out;
+ }
+ }
+ }
+ }
+out:
+ mutex_unlock(&info->slots_list_mutex);
+
+ return err;
+}
+
+static int capemgr_load_slot(struct bone_cape_slot *slot)
+{
+ struct capemgr_info *info = slot->info;
+ struct device *dev = &info->pdev->dev;
+ const char *dtbo;
+ int err;
+
+ if (slot->probe_failed) {
+ dev_err(dev, "slot #%d: probe failed for '%s'\n",
+ slot->slotno, slot->part_number);
+ return -ENODEV;
+ }
+
+ if (slot->loaded) {
+ dev_err(dev, "slot #%d: already loaded for '%s'\n",
+ slot->slotno, slot->part_number);
+ return -EAGAIN;
+ }
+
+ /* make sure we don't leak this on repeated calls */
+ kfree(slot->dtbo);
+ slot->dtbo = NULL;
+
+ dev_dbg(dev, "slot #%d: Requesting part number/version based '%s-%s.dtbo\n",
+ slot->slotno, slot->part_number, slot->version);
+
+ /* request the part number + .dtbo*/
+ slot->dtbo = kasprintf(GFP_KERNEL, "%s-%s.dtbo",
+ slot->part_number, slot->version);
+ if (slot->dtbo == NULL) {
+ dev_err(dev, "slot #%d: Failed to get dtbo '%s'\n",
+ slot->slotno, dtbo);
+ return -ENOMEM;
+ }
+
+ dev_dbg(dev, "slot #%d: Requesting firmware '%s' for board-name '%s', version '%s'%s\n",
+ slot->slotno,
+ slot->dtbo, slot->board_name, slot->version,
+ system_state == SYSTEM_BOOTING ? " - booting" : "");
+
+ err = request_firmware_direct(&slot->fw, slot->dtbo, dev);
+ if (err != 0) {
+ dev_dbg(dev, "failed to load firmware '%s'\n", slot->dtbo);
+ goto err_fail_no_fw;
+ }
+
+ dev_dbg(dev, "slot #%d: dtbo '%s' loaded; converting to live tree\n",
+ slot->slotno, slot->dtbo);
+
+ of_fdt_unflatten_tree((unsigned long *)slot->fw->data, NULL,
+ &slot->overlay);
+ if (slot->overlay == NULL) {
+ dev_err(dev, "slot #%d: Failed to unflatten\n",
+ slot->slotno);
+ err = -EINVAL;
+ goto err_fail;
+ }
+
+ /* mark it as detached */
+ of_node_set_flag(slot->overlay, OF_DETACHED);
+
+ /* perform resolution */
+ err = of_resolve_phandles(slot->overlay);
+ if (err != 0) {
+ dev_err(dev, "slot #%d: Failed to resolve tree\n",
+ slot->slotno);
+ goto err_fail;
+ }
+
+ err = capemgr_verify_overlay(slot);
+ if (err != 0) {
+ dev_err(dev, "slot #%d: Failed verification\n",
+ slot->slotno);
+ goto err_fail;
+ }
+
+ err = of_overlay_create(slot->overlay);
+ if (err < 0) {
+ dev_err(dev, "slot #%d: Failed to create overlay\n",
+ slot->slotno);
+ goto err_fail;
+ }
+ slot->overlay_id = err;
+
+ slot->loading = 0;
+ slot->loaded = 1;
+
+ dev_info(dev, "slot #%d: dtbo '%s' loaded; overlay id #%d\n",
+ slot->slotno, slot->dtbo, slot->overlay_id);
+
+ return 0;
+
+err_fail:
+
+ /* TODO: free the overlay, we can't right now cause
+ * the unflatten method does not track it */
+ slot->overlay = NULL;
+
+ release_firmware(slot->fw);
+ slot->fw = NULL;
+
+err_fail_no_fw:
+ slot->loading = 0;
+ return err;
+}
+
+static int capemgr_unload_slot(struct bone_cape_slot *slot)
+{
+ if (!slot->loaded || slot->overlay_id == -1)
+ return -EINVAL;
+
+ of_overlay_destroy(slot->overlay_id);
+ slot->overlay_id = -1;
+
+ slot->loaded = 0;
+
+ return 0;
+
+}
+
+/* slots_list_mutex must be taken */
+static int capemgr_remove_slot_no_lock(struct bone_cape_slot *slot)
+{
+ struct capemgr_info *info = slot->info;
+ struct device *dev = &info->pdev->dev;
+ int ret;
+
+ if (slot == NULL)
+ return 0;
+
+ if (slot->loaded && slot->overlay_id >= 0) {
+ /* unload just in case */
+ ret = capemgr_unload_slot(slot);
+ if (ret != 0) {
+ dev_err(dev, "Unable to unload slot #%d\n",
+ slot->slotno);
+ return ret;
+ }
+ }
+
+ /* if probed OK, remove the sysfs nodes */
+ if (slot->probed && !slot->probe_failed)
+ bone_cape_slot_sysfs_unregister(slot);
+
+ /* remove it from the list */
+ list_del(&slot->node);
+
+ if (slot->nvmem_cell)
+ nvmem_cell_put(slot->nvmem_cell);
+ devm_kfree(dev, slot);
+ return 0;
+}
+
+static int capemgr_remove_slot(struct bone_cape_slot *slot)
+{
+ struct capemgr_info *info = slot->info;
+ int ret;
+
+ mutex_lock(&info->slots_list_mutex);
+ ret = capemgr_remove_slot_no_lock(slot);
+ mutex_unlock(&info->slots_list_mutex);
+
+ return ret;
+}
+
+static int bone_slot_fill_override(struct bone_cape_slot *slot,
+ const char *part_number, const char *version)
+{
+ const struct ee_field *sig_field;
+ int i, len, has_part_number;
+ char *p;
+
+ slot->probe_failed = 0;
+ slot->probed = 0;
+
+ /* zero out signature */
+ memset(slot->signature, 0,
+ sizeof(slot->signature));
+
+ /* first, fill in all with override defaults */
+ for (i = 0; i < ARRAY_SIZE(cape_sig_fields); i++) {
+
+ sig_field = &cape_sig_fields[i];
+
+ /* point to the entry */
+ p = slot->signature + sig_field->start;
+
+ if (sig_field->override)
+ memcpy(p, sig_field->override,
+ sig_field->size);
+ else
+ memset(p, 0, sig_field->size);
+ }
+
+ /* if a part_number is supplied use it */
+ len = part_number ? strlen(part_number) : 0;
+ if (len > 0) {
+ sig_field = &cape_sig_fields[CAPE_EE_FIELD_PART_NUMBER];
+
+ /* point to the entry */
+ p = slot->signature + sig_field->start;
+
+ /* copy and zero out any remainder */
+ if (len > sig_field->size)
+ len = sig_field->size;
+ memcpy(p, part_number, len);
+ if (len < sig_field->size)
+ memset(p + len, 0, sig_field->size - len);
+
+ has_part_number = 1;
+ }
+
+ /* if a version is supplied use it */
+ len = version ? strlen(version) : 0;
+ if (len > 0) {
+ sig_field = &cape_sig_fields[CAPE_EE_FIELD_VERSION];
+
+ /* point to the entry */
+ p = slot->signature + sig_field->start;
+
+ /* copy and zero out any remainder */
+ if (len > sig_field->size)
+ len = sig_field->size;
+ memcpy(p, version, len);
+ if (len < sig_field->size)
+ memset(p + len, 0, sig_field->size - len);
+ }
+
+ /* we must have a part number */
+ if (!has_part_number)
+ return -EINVAL;
+
+ slot->override = 1;
+
+ return 0;
+}
+
+static struct bone_cape_slot *
+capemgr_add_slot(struct capemgr_info *info, const char *slot_name,
+ const char *part_number, const char *version, int prio)
+{
+ struct bone_cape_slot *slot;
+ struct device *dev = &info->pdev->dev;
+ int slotno;
+ int ret;
+
+ slotno = atomic_inc_return(&info->next_slot_nr) - 1;
+
+ slot = devm_kzalloc(dev, sizeof(*slot), GFP_KERNEL);
+ if (slot == NULL)
+ return ERR_PTR(-ENOMEM);
+
+ slot->info = info;
+ slot->slotno = slotno;
+ slot->priority = prio;
+ slot->overlay_id = -1;
+
+ if (slot_name) {
+ slot->nvmem_cell = nvmem_cell_get(dev, slot_name);
+ if (IS_ERR(slot->nvmem_cell)) {
+ ret = PTR_ERR(slot->nvmem_cell);
+ if (ret != -EPROBE_DEFER)
+ dev_err(dev, "Failed to get slot eeprom cell\n");
+ slot->nvmem_cell = NULL;
+ goto err_out;
+ }
+ } else {
+ dev_info(dev, "slot #%d: override\n", slotno);
+
+ /* fill in everything with defaults first */
+ ret = bone_slot_fill_override(slot, part_number, version);
+ if (ret != 0) {
+ dev_err(dev, "slot #%d: override failed\n", slotno);
+ goto err_out;
+ }
+ }
+
+ ret = bone_slot_scan(slot);
+ if (ret != 0) {
+
+ if (!slot->probe_failed) {
+ dev_err(dev, "slot #%d: scan failed\n",
+ slotno);
+ goto err_out;
+ }
+
+ dev_err(dev, "slot #%d: No cape found\n", slotno);
+ /* but all is fine */
+ } else {
+
+ dev_info(dev, "slot #%d: '%s'\n",
+ slotno, slot->text_id);
+
+ ret = bone_cape_slot_sysfs_register(slot);
+ if (ret != 0) {
+ dev_err(dev, "slot #%d: sysfs register failed\n",
+ slotno);
+ goto err_out;
+ }
+
+ }
+
+ /* add to the slot list */
+ mutex_lock(&info->slots_list_mutex);
+ list_add_tail(&slot->node, &info->slot_list);
+ mutex_unlock(&info->slots_list_mutex);
+
+ return slot;
+
+err_out:
+ if (slot->nvmem_cell)
+ nvmem_cell_put(slot->nvmem_cell);
+ devm_kfree(dev, slot);
+ return ERR_PTR(ret);
+}
+
+/* return 1 if it makes sense to retry loading */
+static int retry_loading_condition(struct bone_cape_slot *slot)
+{
+ struct capemgr_info *info = slot->info;
+ struct device *dev = &info->pdev->dev;
+ struct bone_cape_slot *slotn;
+ int ret;
+
+ dev_dbg(dev, "loader: retry_loading slot-%d %s:%s (prio %d)\n",
+ slot->slotno, slot->part_number, slot->version,
+ slot->priority);
+
+ mutex_lock(&info->slots_list_mutex);
+ ret = 0;
+ list_for_each_entry(slotn, &info->slot_list, node) {
+ /* if same slot or not loading skip */
+ if (!slotn->loading || slotn->retry_loading)
+ continue;
+ /* at least one cape is still loading (without retrying) */
+ ret = 1;
+ }
+ mutex_unlock(&info->slots_list_mutex);
+ return ret;
+}
+
+/* return 1 if this slot is clear to try to load now */
+static int clear_to_load_condition(struct bone_cape_slot *slot)
+{
+ struct capemgr_info *info = slot->info;
+ int my_prio = slot->priority;
+ struct device *dev = &info->pdev->dev;
+ int ret;
+
+ dev_dbg(dev, "loader: check slot-%d %s:%s (prio %d)\n", slot->slotno,
+ slot->part_number, slot->version, slot->priority);
+
+ mutex_lock(&info->slots_list_mutex);
+ ret = 1;
+ list_for_each_entry(slot, &info->slot_list, node) {
+ /* if any slot is loading with lowest priority */
+ if (!slot->loading)
+ continue;
+ if (slot->priority < my_prio) {
+ ret = 0;
+ break;
+ }
+ }
+ mutex_unlock(&info->slots_list_mutex);
+ return ret;
+}
+
+static int capemgr_loader(void *data)
+{
+ struct bone_cape_slot *slot = data;
+ struct capemgr_info *info = slot->info;
+ struct device *dev = &info->pdev->dev;
+ int ret, done, other_loading, booting;
+
+ done = 0;
+
+ slot->retry_loading = 0;
+
+ dev_dbg(dev, "loader: before slot-%d %s:%s (prio %d)\n", slot->slotno,
+ slot->part_number, slot->version, slot->priority);
+
+ /*
+ * We have a basic priority based arbitration system
+ * Slots have priorities, so the lower priority ones
+ * should start loading first. So each time we end up
+ * here.
+ */
+ ret = wait_event_interruptible(info->load_wq,
+ clear_to_load_condition(slot));
+ if (ret < 0) {
+ dev_warn(dev, "loader, Signal pending\n");
+ return ret;
+ }
+
+ dev_dbg(dev, "loader: after slot-%d %s:%s (prio %d)\n", slot->slotno,
+ slot->part_number, slot->version, slot->priority);
+
+ /* using the return value */
+ ret = capemgr_load_slot(slot);
+
+ /* wake up all just in case */
+ wake_up_interruptible_all(&info->load_wq);
+
+ if (ret == 0)
+ goto done;
+
+ dev_dbg(dev, "loader: retrying slot-%d %s:%s (prio %d)\n", slot->slotno,
+ slot->part_number, slot->version, slot->priority);
+
+ /* first attempt has failed; now try each time there's any change */
+ slot->retry_loading = 1;
+
+ for (;;) {
+ booting = (system_state == SYSTEM_BOOTING);
+ other_loading = retry_loading_condition(slot);
+ if (!booting && !other_loading)
+ break;
+
+ /* simple wait for someone to kick us */
+ if (other_loading) {
+ DEFINE_WAIT(__wait);
+
+ prepare_to_wait(&info->load_wq, &__wait,
+ TASK_INTERRUPTIBLE);
+ finish_wait(&info->load_wq, &__wait);
+ } else {
+ /* always delay when booting */
+ msleep(boot_scan_period);
+ }
+
+ if (signal_pending(current)) {
+ dev_warn(dev, "loader, Signal pending\n");
+ ret = -ERESTARTSYS;
+ goto done;
+ }
+
+ /* using the return value */
+ ret = capemgr_load_slot(slot);
+ if (ret == 0)
+ goto done;
+
+ /* wake up all just in case */
+ wake_up_interruptible_all(&info->load_wq);
+ }
+
+done:
+ slot->loading = 0;
+ slot->retry_loading = 0;
+
+ if (ret == 0) {
+ dev_dbg(dev, "loader: done slot-%d %s:%s (prio %d)\n",
+ slot->slotno, slot->part_number, slot->version,
+ slot->priority);
+ } else {
+ dev_err(dev, "loader: failed to load slot-%d %s:%s (prio %d)\n",
+ slot->slotno, slot->part_number, slot->version,
+ slot->priority);
+
+ /* if it's a override slot remove it */
+ if (slot->override)
+ capemgr_remove_slot(slot);
+ }
+
+ return ret;
+}
+
+static int
+capemgr_probe(struct platform_device *pdev)
+{
+ struct capemgr_info *info;
+ struct bone_baseboard *bbrd;
+ struct bone_cape_slot *slot;
+ struct device_node *pnode = pdev->dev.of_node;
+ struct device_node *baseboardmaps_node;
+ struct device_node *node;
+ const char *part_number;
+ const char *version;
+ const char *board_name;
+ const char *compatible_name;
+ char slot_name[16];
+ u32 slots_nr;
+ int i, ret, len, prio;
+ long val;
+ char *wbuf, *s, *p, *e;
+
+ /* we don't use platform_data at all; we require OF */
+ if (pnode == NULL)
+ return -ENOTSUPP;
+
+ info = devm_kzalloc(&pdev->dev,
+ sizeof(struct capemgr_info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ info->pdev = pdev;
+ platform_set_drvdata(pdev, info);
+
+ atomic_set(&info->next_slot_nr, 0);
+ INIT_LIST_HEAD(&info->slot_list);
+ mutex_init(&info->slots_list_mutex);
+
+ init_waitqueue_head(&info->load_wq);
+
+ baseboardmaps_node = NULL;
+
+ /* find the baseboard */
+ bbrd = &info->baseboard;
+
+ baseboardmaps_node = of_get_child_by_name(pnode, "baseboardmaps");
+ if (baseboardmaps_node == NULL) {
+ dev_err(&pdev->dev, "Failed to get baseboardmaps node");
+ ret = -ENODEV;
+ goto err_exit;
+ }
+
+ bbrd->nvmem_cell = nvmem_cell_get(&pdev->dev, "baseboard");
+ if (IS_ERR(bbrd->nvmem_cell)) {
+ ret = PTR_ERR(bbrd->nvmem_cell);
+ if (ret != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "Failed to get baseboard eeprom cell\n");
+ bbrd->nvmem_cell = NULL;
+ goto err_exit;
+ }
+
+ ret = bone_baseboard_scan(bbrd);
+ if (ret != 0) {
+ dev_err(&pdev->dev, "Failed to scan baseboard eeprom\n");
+ goto err_exit;
+ }
+
+ dev_info(&pdev->dev, "Baseboard: '%s'\n", bbrd->text_id);
+
+ board_name = NULL;
+ compatible_name = NULL;
+ for_each_child_of_node(baseboardmaps_node, node) {
+ /* there must be board-name */
+ if (of_property_read_string(node, "board-name",
+ &board_name) != 0 ||
+ of_property_read_string(node, "compatible-name",
+ &compatible_name) != 0)
+ continue;
+
+ if (strcmp(bbrd->board_name, board_name) == 0)
+ break;
+ }
+ of_node_put(baseboardmaps_node);
+ baseboardmaps_node = NULL;
+
+ if (node == NULL) {
+ dev_err(&pdev->dev, "Failed to find compatible map for %s\n",
+ bbrd->board_name);
+ ret = -ENODEV;
+ goto err_exit;
+ }
+ bbrd->compatible_name = kstrdup(compatible_name, GFP_KERNEL);
+ if (bbrd->compatible_name == NULL) {
+ ret = -ENOMEM;
+ goto err_exit;
+ }
+ of_node_put(node);
+
+ /* get slot number */
+ ret = of_property_read_u32(pnode, "#slots", &slots_nr);
+ if (ret != 0)
+ slots_nr = 0;
+
+ dev_info(&pdev->dev, "compatible-baseboard=%s - #slots=%d\n",
+ bbrd->compatible_name, slots_nr);
+
+ for (i = 0; i < slots_nr; i++) {
+ snprintf(slot_name, sizeof(slot_name), "slot%d", i);
+ slot = capemgr_add_slot(info, slot_name, NULL, NULL, 0);
+ if (IS_ERR(slot)) {
+ dev_err(&pdev->dev, "Failed to add slot #%d\n",
+ atomic_read(&info->next_slot_nr));
+ ret = PTR_ERR(slot);
+ goto err_exit;
+ }
+ }
+
+ /* iterate over enable_partno (if there) */
+ if (enable_partno && strlen(enable_partno) > 0) {
+
+ /* allocate a temporary buffer */
+ wbuf = devm_kzalloc(&pdev->dev, PAGE_SIZE, GFP_KERNEL);
+ if (wbuf == NULL) {
+ ret = -ENOMEM;
+ goto err_exit;
+ }
+
+ /* add any enable_partno capes */
+ s = enable_partno;
+ while (*s) {
+ /* form is PART[:REV[:PRIO]],PART.. */
+ p = strchr(s, ',');
+ if (p == NULL)
+ e = s + strlen(s);
+ else
+ e = p;
+
+ /* copy to temp buffer */
+ len = e - s;
+ if (len >= PAGE_SIZE - 1)
+ len = PAGE_SIZE - 1;
+ memcpy(wbuf, s, len);
+ wbuf[len] = '\0';
+
+ /* move to the next */
+ s = *e ? e + 1 : e;
+
+ part_number = wbuf;
+
+ /* default version is NULL & prio is 0 */
+ version = NULL;
+ prio = 0;
+
+ /* now split the rev & prio part */
+ p = strchr(wbuf, ':');
+ if (p != NULL) {
+ *p++ = '\0';
+ if (*p != ':')
+ version = p;
+ p = strchr(p, ':');
+ if (p != NULL) {
+ *p++ = '\0';
+ ret = kstrtol(p, 10, &val);
+ if (ret == 0)
+ prio = val;
+ }
+ }
+
+ dev_info(&pdev->dev,
+ "enabled_partno PARTNO '%s' VER '%s' PR '%d'\n",
+ part_number,
+ version ? version : "N/A", prio);
+
+ /* only immediate slots are allowed here */
+ slot = capemgr_add_slot(info, NULL,
+ part_number, version, prio);
+
+ /* we continue even in case of an error */
+ if (IS_ERR_OR_NULL(slot)) {
+ dev_warn(&pdev->dev, "Failed to add slot #%d\n",
+ atomic_read(&info->next_slot_nr) - 1);
+ }
+ }
+
+ devm_kfree(&pdev->dev, wbuf);
+ }
+
+ pm_runtime_enable(&pdev->dev);
+ ret = pm_runtime_get_sync(&pdev->dev);
+ if (IS_ERR_VALUE(ret)) {
+ dev_err(&pdev->dev, "Failed to pm_runtime_get_sync()\n");
+ goto err_exit;
+ }
+
+ pm_runtime_put(&pdev->dev);
+
+ /* it is safe to create the attribute groups */
+ ret = sysfs_create_groups(&pdev->dev.kobj, attr_groups);
+ if (ret != 0) {
+ dev_err(&pdev->dev, "Failed to create sysfs attributes\n");
+ goto err_exit;
+ }
+ /* automatically cleared by driver core now */
+ pdev->dev.groups = attr_groups;
+
+ /* now load each (take lock to be sure */
+ mutex_lock(&info->slots_list_mutex);
+
+ list_for_each_entry(slot, &info->slot_list, node) {
+
+ /* if matches the disabled ones skip */
+ if (bone_match_cape(disable_partno, slot->part_number,
+ slot->version)) {
+ dev_info(&pdev->dev,
+ "Skipping loading of disabled cape with part# %s\n",
+ slot->part_number);
+ slot->disabled = 1;
+ continue;
+ }
+
+ if (!slot->probe_failed && !slot->loaded)
+ slot->loading = 1;
+ }
+
+ /* now start the loader thread(s) (all at once) */
+ list_for_each_entry(slot, &info->slot_list, node) {
+
+ if (!slot->loading)
+ continue;
+
+ slot->loader_thread = kthread_run(capemgr_loader,
+ slot, "capemgr-loader-%d",
+ slot->slotno);
+ if (IS_ERR(slot->loader_thread)) {
+ dev_warn(&pdev->dev, "slot #%d: Failed to start loader\n",
+ slot->slotno);
+ slot->loader_thread = NULL;
+ }
+ }
+ mutex_unlock(&info->slots_list_mutex);
+
+ dev_info(&pdev->dev, "initialized OK.\n");
+
+ return 0;
+
+err_exit:
+ if (bbrd->nvmem_cell)
+ nvmem_cell_put(bbrd->nvmem_cell);
+ of_node_put(baseboardmaps_node);
+ platform_set_drvdata(pdev, NULL);
+ devm_kfree(&pdev->dev, info);
+
+ return ret;
+}
+
+static int capemgr_remove(struct platform_device *pdev)
+{
+ struct capemgr_info *info = platform_get_drvdata(pdev);
+ struct bone_baseboard *bbrd = &info->baseboard;
+ struct bone_cape_slot *slot, *slotn;
+ int ret;
+
+ mutex_lock(&info->slots_list_mutex);
+ list_for_each_entry_safe(slot, slotn, &info->slot_list, node)
+ capemgr_remove_slot_no_lock(slot);
+ mutex_unlock(&info->slots_list_mutex);
+
+ platform_set_drvdata(pdev, NULL);
+
+ ret = pm_runtime_get_sync(&pdev->dev);
+ if (IS_ERR_VALUE(ret))
+ return ret;
+
+ pm_runtime_put(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+
+ if (bbrd->nvmem_cell)
+ nvmem_cell_put(bbrd->nvmem_cell);
+ devm_kfree(&pdev->dev, info);
+
+ return 0;
+}
+
+static struct platform_driver capemgr_driver = {
+ .probe = capemgr_probe,
+ .remove = capemgr_remove,
+ .driver = {
+ .name = "bone_capemgr",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(capemgr_of_match),
+ },
+};
+
+module_platform_driver(capemgr_driver);
+
+MODULE_AUTHOR("Pantelis Antoniou");
+MODULE_DESCRIPTION("Beaglebone cape manager");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:bone_capemgr");
diff --git b/drivers/misc/cape/Kconfig b/drivers/misc/cape/Kconfig
new file mode 100644
index 0000000..a2ef85e
--- /dev/null
+++ b/drivers/misc/cape/Kconfig
@@ -0,0 +1,5 @@
+#
+# Capes
+#
+
+source "drivers/misc/cape/beaglebone/Kconfig"
diff --git b/drivers/misc/cape/Makefile b/drivers/misc/cape/Makefile
new file mode 100644
index 0000000..7c4eb96
--- /dev/null
+++ b/drivers/misc/cape/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for cape like devices
+#
+
+obj-y += beaglebone/
diff --git b/drivers/misc/cape/beaglebone/Kconfig b/drivers/misc/cape/beaglebone/Kconfig
new file mode 100644
index 0000000..eeb6782
--- /dev/null
+++ b/drivers/misc/cape/beaglebone/Kconfig
@@ -0,0 +1,10 @@
+#
+# Beaglebone capes
+#
+
+config BEAGLEBONE_PINMUX_HELPER
+ tristate "Beaglebone Pinmux Helper"
+ depends on ARCH_OMAP2PLUS && OF
+ default n
+ help
+ Say Y here to include support for the pinmux helper
diff --git b/drivers/misc/cape/beaglebone/Makefile b/drivers/misc/cape/beaglebone/Makefile
new file mode 100644
index 0000000..7f4617a
--- /dev/null
+++ b/drivers/misc/cape/beaglebone/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for beaglebone capes
+#
+
+obj-$(CONFIG_BEAGLEBONE_PINMUX_HELPER) += bone-pinmux-helper.o
diff --git b/drivers/misc/cape/beaglebone/bone-pinmux-helper.c b/drivers/misc/cape/beaglebone/bone-pinmux-helper.c
new file mode 100644
index 0000000..d81363a
--- /dev/null
+++ b/drivers/misc/cape/beaglebone/bone-pinmux-helper.c
@@ -0,0 +1,242 @@
+/*
+ * Pinmux helper driver
+ *
+ * Copyright (C) 2013 Pantelis Antoniou <panto@antoniou-consulting.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/slab.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/consumer.h>
+
+static const struct of_device_id bone_pinmux_helper_of_match[] = {
+ {
+ .compatible = "bone-pinmux-helper",
+ },
+ { },
+};
+MODULE_DEVICE_TABLE(of, bone_pinmux_helper_of_match);
+
+struct pinmux_helper_data {
+ struct pinctrl *pinctrl;
+ char *selected_state_name;
+};
+
+static ssize_t pinmux_helper_show_state(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct pinmux_helper_data *data = platform_get_drvdata(pdev);
+ const char *name;
+
+ name = data->selected_state_name;
+ if (name == NULL || strlen(name) == 0)
+ name = "none";
+ return sprintf(buf, "%s\n", name);
+}
+
+static ssize_t pinmux_helper_store_state(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct pinmux_helper_data *data = platform_get_drvdata(pdev);
+ struct pinctrl_state *state;
+ char *state_name;
+ char *s;
+ int err;
+
+ /* duplicate (as a null terminated string) */
+ state_name = kmalloc(count + 1, GFP_KERNEL);
+ if (state_name == NULL)
+ return -ENOMEM;
+ memcpy(state_name, buf, count);
+ state_name[count] = '\0';
+
+ /* and chop off newline */
+ s = strchr(state_name, '\n');
+ if (s != NULL)
+ *s = '\0';
+
+ /* try to select default state at first (if it exists) */
+ state = pinctrl_lookup_state(data->pinctrl, state_name);
+ if (!IS_ERR(state)) {
+ err = pinctrl_select_state(data->pinctrl, state);
+ if (err != 0)
+ dev_err(dev, "Failed to select state %s\n",
+ state_name);
+ } else {
+ dev_err(dev, "Failed to find state %s\n", state_name);
+ err = PTR_RET(state);
+ }
+
+ if (err == 0) {
+ kfree(data->selected_state_name);
+ data->selected_state_name = state_name;
+ }
+
+ return err ? err : count;
+}
+
+static DEVICE_ATTR(state, S_IWUSR | S_IRUGO,
+ pinmux_helper_show_state, pinmux_helper_store_state);
+
+static struct attribute *pinmux_helper_attributes[] = {
+ &dev_attr_state.attr,
+ NULL
+};
+
+static const struct attribute_group pinmux_helper_attr_group = {
+ .attrs = pinmux_helper_attributes,
+};
+
+static int bone_pinmux_helper_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct pinmux_helper_data *data;
+ struct pinctrl_state *state;
+ char *state_name;
+ const char *mode_name;
+ int mode_len;
+ int err;
+
+ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+ if (data == NULL) {
+ dev_err(dev, "Failed to allocate data\n");
+ err = -ENOMEM;
+ goto err_no_mem;
+ }
+
+ state_name = kmalloc(strlen(PINCTRL_STATE_DEFAULT) + 1,
+ GFP_KERNEL);
+ if (state_name == NULL) {
+ dev_err(dev, "Failed to allocate state name\n");
+ err = -ENOMEM;
+ goto err_no_state_mem;
+ }
+ data->selected_state_name = state_name;
+ strcpy(data->selected_state_name, PINCTRL_STATE_DEFAULT);
+
+ platform_set_drvdata(pdev, data);
+
+ data->pinctrl = devm_pinctrl_get(dev);
+ if (IS_ERR(data->pinctrl)) {
+ dev_err(dev, "Failed to get pinctrl\n");
+ err = PTR_RET(data->pinctrl);
+ goto err_no_pinctrl;
+ }
+
+ /* See if an initial mode is specified in the device tree */
+ mode_name = of_get_property(dev->of_node, "mode", &mode_len);
+
+ err = -1;
+ if (mode_name != NULL ) {
+ state_name = kmalloc(mode_len + 1, GFP_KERNEL);
+ if (state_name == NULL) {
+ dev_err(dev, "Failed to allocate state name\n");
+ err = -ENOMEM;
+ goto err_no_mode_mem;
+ }
+ strncpy(state_name, mode_name, mode_len);
+
+ /* try to select requested mode */
+ state = pinctrl_lookup_state(data->pinctrl, state_name);
+ if (!IS_ERR(state)) {
+ err = pinctrl_select_state(data->pinctrl, state);
+ if (err != 0) {
+ dev_warn(dev, "Unable to select requested mode %s\n", state_name);
+ kfree(state_name);
+ } else {
+ kfree(data->selected_state_name);
+ data->selected_state_name = state_name;
+ dev_notice(dev, "Set initial pinmux mode to %s\n", state_name);
+ }
+ }
+ }
+
+ /* try to select default state if mode_name failed */
+ if ( err != 0) {
+ state = pinctrl_lookup_state(data->pinctrl,
+ data->selected_state_name);
+ if (!IS_ERR(state)) {
+ err = pinctrl_select_state(data->pinctrl, state);
+ if (err != 0) {
+ dev_err(dev, "Failed to select default state\n");
+ goto err_no_state;
+ }
+ } else {
+ data->selected_state_name = '\0';
+ }
+ }
+
+ /* Register sysfs hooks */
+ err = sysfs_create_group(&dev->kobj, &pinmux_helper_attr_group);
+ if (err) {
+ dev_err(dev, "Failed to create sysfs group\n");
+ goto err_no_sysfs;
+ }
+
+ return 0;
+
+err_no_sysfs:
+err_no_state:
+err_no_mode_mem:
+ devm_pinctrl_put(data->pinctrl);
+err_no_pinctrl:
+ devm_kfree(dev, data->selected_state_name);
+err_no_state_mem:
+ devm_kfree(dev, data);
+err_no_mem:
+ return err;
+}
+
+static int bone_pinmux_helper_remove(struct platform_device *pdev)
+{
+ struct pinmux_helper_data *data = platform_get_drvdata(pdev);
+ struct device *dev = &pdev->dev;
+
+ sysfs_remove_group(&dev->kobj, &pinmux_helper_attr_group);
+ kfree(data->selected_state_name);
+ devm_pinctrl_put(data->pinctrl);
+ devm_kfree(dev, data);
+
+ return 0;
+}
+
+struct platform_driver bone_pinmux_helper_driver = {
+ .probe = bone_pinmux_helper_probe,
+ .remove = bone_pinmux_helper_remove,
+ .driver = {
+ .name = "bone-pinmux-helper",
+ .owner = THIS_MODULE,
+ .of_match_table = bone_pinmux_helper_of_match,
+ },
+};
+
+module_platform_driver(bone_pinmux_helper_driver);
+
+MODULE_AUTHOR("Pantelis Antoniou");
+MODULE_DESCRIPTION("Beaglebone pinmux helper driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:bone-pinmux-helper");
diff --git b/drivers/misc/cape_bone_argus/Kconfig b/drivers/misc/cape_bone_argus/Kconfig
new file mode 100644
index 0000000..1b39661
--- /dev/null
+++ b/drivers/misc/cape_bone_argus/Kconfig
@@ -0,0 +1,7 @@
+comment "Argus cape driver for beaglebone black"
+
+config CAPE_BONE_ARGUS
+ tristate "Argus Cape Driver"
+ default M
+ help
+ Argus Cape Driver
diff --git b/drivers/misc/cape_bone_argus/Makefile b/drivers/misc/cape_bone_argus/Makefile
new file mode 100644
index 0000000..5482562
--- /dev/null
+++ b/drivers/misc/cape_bone_argus/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for Argus cape
+#
+
+obj-$(CONFIG_CAPE_BONE_ARGUS) += cape_bone_argus.o
diff --git b/drivers/misc/cape_bone_argus/cape_bone_argus.c b/drivers/misc/cape_bone_argus/cape_bone_argus.c
new file mode 100644
index 0000000..c434218
--- /dev/null
+++ b/drivers/misc/cape_bone_argus/cape_bone_argus.c
@@ -0,0 +1,415 @@
+/* -*- linux-c -*- */
+
+/* Linux Kernel Module for Breakaway Systems UPS control.
+ *
+ * PUBLIC DOMAIN
+ */
+
+#include <linux/syscalls.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/reboot.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/mount.h>
+#include <linux/workqueue.h>
+#include <linux/cdev.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/of_gpio.h>
+
+/* Module to sync file systems leaving them mounted read-only,
+ * then signal the UPS that it is safe to remove
+ * power, and finally halt the processor.
+ * Also to allow kicking the watchdog from user mode.
+ */
+#undef DEBUG_ARGUS
+
+#define N_GPIOS 9 /* Total number of GPIOS used */
+
+#define REQ_GPIO_IDX 0 /* Indices got GPIOS */
+#define ACK_GPIO_IDX 1
+#define WDG_GPIO_IDX 2
+#define LED1_GREEN_IDX 3
+#define LED1_RED_IDX 4
+#define LED2_GREEN_IDX 5
+#define LED2_RED_IDX 6
+#define GEN_OUT1_IDX 7
+#define GEN_OUT2_IDX 8
+
+static struct argus_ups_info { /* As there is only one UPS device we can make this static */
+ struct fasync_struct *async_queue; /* asynchronous readers */
+ struct platform_device *pdev;
+ struct pwm_device *pwm_dev;
+ struct gpio gpios[N_GPIOS];
+} info = {NULL, NULL, NULL, /* Some fields filled in by device tree, probe, etc. */
+ {
+ {-1, GPIOF_IN, "Powerdown request"},
+ {-1, GPIOF_OUT_INIT_LOW, "Powerdown acknowledge" },
+ {-1, GPIOF_OUT_INIT_LOW, "Watchdog"},
+ {-1, GPIOF_OUT_INIT_LOW, "LED 1 Green"},
+ {-1, GPIOF_OUT_INIT_LOW, "LED 1 Red"},
+ {-1, GPIOF_OUT_INIT_LOW, "LED 2 Green"},
+ {-1, GPIOF_OUT_INIT_LOW, "LED 2 Red"},
+ {-1, GPIOF_OUT_INIT_LOW, "General Output #1"},
+ {-1, GPIOF_OUT_INIT_LOW, "General Output #2"}
+ },
+};
+
+
+static const struct of_device_id argus_ups_of_ids[] = {
+ { .compatible = "argus-ups" },
+ { }
+};
+
+static int argus_ups_major; /* Major device number */
+
+static struct class *argus_ups_class; /* /sys/class */
+
+dev_t argus_ups_dev; /* Device number */
+
+static struct cdev *argus_ups_cdev; /* Character device details */
+
+static void argus_ups_function(struct work_struct *ignored); /* Work function */
+
+static DECLARE_DELAYED_WORK(argus_ups_work, argus_ups_function); /* Kernel workqueue glue */
+
+static struct workqueue_struct *argus_ups_workqueue; /* Kernel workqueue */
+
+static int debug = 0;
+module_param(debug, int, S_IRUGO);
+MODULE_PARM_DESC(debug, "Debug flag");
+
+static int shutdown = 1;
+module_param(shutdown, int, S_IRUGO);
+MODULE_PARM_DESC(shutdown, "Shutdown flag");
+
+#ifdef DEBUG_ARGUS
+static char* fs_type_names[] = {"vfat", "ext4"}; /* File system names that may need syncing. */
+#endif
+
+/* Just kick watchdog */
+
+static ssize_t argus_ups_write(struct file *filp, const char __user *buf, size_t count,
+ loff_t *f_pos)
+{
+ int i;
+ if (debug >= 3) {
+ printk("Writing to watchdog - count:%d\n", count);
+ }
+ for (i = 0; i < count; i++) {
+ gpio_set_value(info.gpios[WDG_GPIO_IDX].gpio, 1); /* Set it */
+ msleep(10); /* Wait */
+ gpio_set_value(info.gpios[WDG_GPIO_IDX].gpio, 0); /* End clearing it */
+ msleep(10);
+ }
+ return count; /* Always returns what we sent, regardsless */
+}
+
+static long argus_ups_ioctl(struct file *file,
+ unsigned int ioctl,
+ unsigned long param)
+{
+ if (debug >= 4) {
+ printk(KERN_ERR "ioctl: %d, param: %ld\n", ioctl, param);
+ }
+ switch(ioctl) {
+ case 10001: {
+ debug = param;
+ printk("Debug set to %d\n", debug);
+ break;
+ }
+ case 10002: {
+ unsigned char value = param & 0x0F;
+ unsigned char mask = (param >> 4) & 0x0F;
+ int i; /* Loop iterator */
+ if (mask == 0) {
+ printk(KERN_ERR "Pointless mask of zero!\n");
+ }
+ for (i = 0; i < 4; i++) { /* For all four LEDS */
+ if (mask & (1 << i)) { /* Only masked values */
+ if (value & (1 << i)) { /* On - so gpio is hi */
+ if (debug >= 4) {
+ printk("Setting %d hi, ",
+ info.gpios[LED1_GREEN_IDX + i].gpio);
+ }
+ gpio_set_value(info.gpios[LED1_GREEN_IDX + i].gpio, 1);
+ }
+ else { /* Off - so gpio is lo */
+ if (debug >= 4) {
+ printk("Setting %d lo, ",
+ info.gpios[LED1_GREEN_IDX + i].gpio);
+ }
+ gpio_set_value(info.gpios[LED1_GREEN_IDX + i].gpio, 0);
+ }
+ }
+ }
+ if (debug >= 4) {
+ printk("\n");
+ }
+ break;
+ }
+ case 10003: {
+ gpio_set_value(info.gpios[GEN_OUT1_IDX].gpio, param & 1);
+ break;
+ }
+ case 10004: {
+ gpio_set_value(info.gpios[GEN_OUT2_IDX].gpio, param & 1);
+ break;
+ }
+ default:
+ {
+ printk(KERN_ERR "Invalid ioctl %d\n", ioctl);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int argus_ups_fasync(int fd, struct file *filp, int mode)
+{
+ printk(KERN_ERR "In argus_ups_fasync() fd:%d, filp:%p, mode:%d\n", fd, filp, mode);
+ return fasync_helper(fd, filp, mode, &info.async_queue);
+}
+
+static struct file_operations argus_ups_fops = { /* Only file operation is to kick watchdog via a write */
+ .owner = THIS_MODULE,
+ .llseek = NULL,
+ .read = NULL,
+ .unlocked_ioctl = argus_ups_ioctl,
+ .write = argus_ups_write,
+ .open = NULL,
+ .release = NULL,
+ .fasync = argus_ups_fasync,
+};
+
+#ifdef DEBUG_ARGUS
+static void remount_sb(struct super_block *sb)
+{
+ int flags = MS_RDONLY;
+ int result = sb->s_op->remount_fs(sb, &flags, "");
+ if (debug) {
+ printk("Processing superblock %p\n", sb);
+ printk("Remount operation returned %d\n", result);
+ }
+}
+#endif
+
+static void argus_ups_function(struct work_struct *ignored)
+{
+ static int testdata = 0; /* Data for test */
+ int i; /* Iterator */
+ testdata++;
+ if (!gpio_get_value(info.gpios[REQ_GPIO_IDX].gpio)) {
+ queue_delayed_work(argus_ups_workqueue, &argus_ups_work, HZ/100); /* Re-queue in 10mS*/
+ return;
+ }
+ printk(KERN_ERR "Request received\n");
+ if (debug) {
+ printk("Shutdown request received from UPS\n");
+ }
+ if (!shutdown) {
+ printk("Shutdown request ignored\n");
+ return;
+ }
+
+ if (debug) {
+ printk("Sending async kill SIGIO to %p\n", info.async_queue);
+ }
+ if (info.async_queue) { /* Try and tell usermode to halt system */
+ kill_fasync(&info.async_queue, SIGIO, POLL_IN);
+ }
+ gpio_set_value(info.gpios[LED1_GREEN_IDX].gpio, 0); /* Turn off green LED1 */
+ for (i = 0; i < 300; i++) { /* Toggle acknowledge at 10 Hz for 15 seconds */
+ if (debug >= 2) {
+ printk("Waiting for first shutdown request:%d\n", i);
+ }
+ gpio_set_value(info.gpios[ACK_GPIO_IDX].gpio, i & 1); /* Toggle acknowledge */
+ gpio_set_value(info.gpios[LED1_RED_IDX].gpio, i & 1); /* and LED1 red */
+ msleep(50); /* Wait in 50ms increments */
+ }
+
+ {
+ char *argv[] = { "/sbin/halt", NULL };
+ static char *envp[] = {
+ "HOME=/",
+ "TERM=linux",
+ "PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin", NULL };
+
+ call_usermodehelper( argv[0], argv, envp, UMH_WAIT_PROC );
+ }
+ for (i = 0; i < 300; i++) { /* Toggle acknowledge at 10 Hz for 15 more seconds */
+ if (debug >= 2) {
+ printk("Waiting for second shutdown request:%d\n", i);
+ }
+ gpio_set_value(info.gpios[ACK_GPIO_IDX].gpio, i & 1); /* Toggle acknowledge */
+ gpio_set_value(info.gpios[LED1_RED_IDX].gpio, i & 1); /* and LED1 red */
+ msleep(50); /* Wait in 50ms increments */
+ }
+ printk(KERN_ERR "Usermode failed to halt system\n");
+ kernel_halt(); /* Last resort - may give some oopss */
+}
+
+
+static int argus_ups_probe(struct platform_device *pdev) /* Entry point */
+{
+ struct pinctrl *pinctrl;
+ struct device_node *pnode = pdev->dev.of_node;
+ int i;
+ int ret;
+ printk("Init UPS module - debug=%d, shutdown=%d\n",
+ debug, shutdown);
+ platform_set_drvdata(pdev, &info);
+ info.pdev = pdev;
+ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+ if (IS_ERR(pinctrl)) {
+ dev_warn(&pdev->dev,
+ "pins are not configured from the driver\n");
+ return -1;
+ }
+ ret = of_property_read_u32(pnode, "debug", &debug);
+ if (ret != 0) {
+ dev_err(&pdev->dev, "Unable to read debug parameter\n");
+ }
+ else {
+ printk("Debug parameter read from DT:%d\n", debug);
+ }
+
+ ret = of_property_read_u32(pnode, "shutdown", &shutdown);
+ if (ret != 0) {
+ dev_err(&pdev->dev, "Unable to read shutdown parameter\n");
+ }
+ else {
+ printk("Shutdown parameter read from DT:%d\n", shutdown);
+ }
+
+ ret = of_gpio_count(pnode);
+
+ if (ret != N_GPIOS) {
+ printk(KERN_ERR "Wrong number of gpios");
+ return -1;
+ }
+
+ for (i = 0; i < of_gpio_count(pnode); i++) {
+ ret = of_get_gpio_flags(pnode, i, NULL);
+ if (debug) {
+ printk("GPIO#%d:%d\n", i, ret);
+ }
+ if (IS_ERR_VALUE(ret)) {
+ dev_err(&pdev->dev, "unable to get GPIO %d\n", i);
+ goto err_no_gpio;
+ }
+ info.gpios[i].gpio = ret;
+ }
+
+
+ ret = alloc_chrdev_region(&argus_ups_dev, 0, 2, "argus_ups");
+ argus_ups_major = MAJOR(argus_ups_dev);
+ if (ret) {
+ printk(KERN_ERR "Error %d adding argus_ups\n", ret);
+ return -1;
+ }
+ if (debug) {
+ printk("argus_ups major: %d\n", argus_ups_major);
+ }
+ argus_ups_cdev = cdev_alloc(); /* Make this a character device */
+ argus_ups_cdev->ops = &argus_ups_fops; /* File operations */
+ argus_ups_cdev->owner = THIS_MODULE; /* Top level device */
+ ret = cdev_add(argus_ups_cdev, argus_ups_dev, 1); /* Add it to the kernel */
+ if (ret) {
+ printk(KERN_ERR "cdev_add returned %d\n", ret);
+ unregister_chrdev_region(0, 1);
+ return -1;
+ }
+ ret = gpio_request_array(info.gpios, N_GPIOS);
+ if (ret) {
+ printk(KERN_ERR "Error %d requesting GPIOs\n", ret);
+ unregister_chrdev_region(0, 1);
+ return -1;
+ }
+
+ argus_ups_class = class_create(THIS_MODULE, "argus_ups"); /* /sys/class entry for udev */
+ if (IS_ERR(argus_ups_class)) {
+ printk(KERN_ERR "Error creating argus_ups_class\n");
+ unregister_chrdev_region(0, 1);
+ return -1;
+ }
+ device_create(argus_ups_class, NULL, MKDEV(argus_ups_major, 0), NULL, "argus_ups");
+ argus_ups_workqueue = create_singlethread_workqueue("argus_ups");
+ INIT_DELAYED_WORK(&argus_ups_work, argus_ups_function);
+ queue_delayed_work(argus_ups_workqueue, &argus_ups_work, 0); /* Start work immediately */
+
+ return 0;
+err_no_gpio:
+ return ret;
+
+}
+
+
+static void argus_ups_cleanup(void)
+{
+ printk("Module cleanup called\n");
+ while (cancel_delayed_work(&argus_ups_work) == 0) {
+ flush_workqueue(argus_ups_workqueue); /* Make sure all work is completed */
+ }
+ destroy_workqueue(argus_ups_workqueue);
+ gpio_free_array(info.gpios, N_GPIOS);
+ device_destroy(argus_ups_class, argus_ups_dev);
+ class_destroy(argus_ups_class);
+ unregister_chrdev_region(argus_ups_dev, 1);
+ cdev_del(argus_ups_cdev);
+}
+
+
+
+static int argus_ups_remove(struct platform_device *pdev)
+{
+ printk("In argus_ups_remove()\n");
+ argus_ups_cleanup();
+ printk("After cleanup\n");
+ return 0;
+}
+
+#define ARGUS_UPS_PM_OPS NULL
+
+struct platform_driver argus_ups_driver = {
+ .probe = argus_ups_probe,
+ .remove = argus_ups_remove,
+ .driver = {
+ .name = "argus-ups",
+ .owner = THIS_MODULE,
+ .pm = ARGUS_UPS_PM_OPS,
+ .of_match_table = argus_ups_of_ids,
+ },
+};
+
+
+static int __init argus_ups_init(void)
+{
+ return platform_driver_probe(&argus_ups_driver,
+ argus_ups_probe);
+}
+
+static void __exit argus_ups_exit(void)
+{
+ platform_driver_unregister(&argus_ups_driver);
+ printk("After driver unregister\n");
+}
+
+module_init(argus_ups_init);
+module_exit(argus_ups_exit);
+
+/*
+ * Get rid of taint message.
+ */
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("David Lambert"); /* Who wrote this module? */
+MODULE_DESCRIPTION("Argus UPS control"); /* What does this module do */
+MODULE_ALIAS("platform:argus-ups");
+MODULE_DEVICE_TABLE(of, argus_ups_of_ids);
diff --git b/drivers/misc/devovmgr.c b/drivers/misc/devovmgr.c
new file mode 100644
index 0000000..d5c8d1d
--- /dev/null
+++ b/drivers/misc/devovmgr.c
@@ -0,0 +1,1306 @@
+/*
+ * Device overlay manager
+ *
+ * Copyright (C) 2015 Konsulko Group
+ * Pantelis Antoniou <pantelis.antoniou@konsulko.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <linux/ctype.h>
+#include <linux/cpu.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <linux/spinlock.h>
+#include <linux/sizes.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/configfs.h>
+#include <linux/types.h>
+#include <linux/stat.h>
+#include <linux/limits.h>
+#include <linux/file.h>
+#include <linux/vmalloc.h>
+#include <linux/firmware.h>
+#include <linux/pci.h>
+#include <linux/usb.h>
+#include <linux/mod_devicetable.h>
+#include <linux/workqueue.h>
+#include <linux/firmware.h>
+
+enum dovmgr_type {
+ ITEM_PCI,
+ ITEM_USB
+};
+
+struct dovmgr_item;
+
+struct dovmgr_dev_item {
+ struct dovmgr_item *item;
+ struct list_head node;
+ struct device *dev;
+ const struct firmware *fw;
+ struct device_node *overlay;
+ int overlay_id;
+ struct work_struct work;
+};
+
+struct dovmgr_item {
+ struct config_item item;
+ char *path;
+ bool enable;
+ char *overlay_name;
+ struct mutex dev_item_mutex;
+ struct list_head dev_item_list;
+ enum dovmgr_type type;
+ union {
+ struct pci_device_id pci;
+ struct usb_device_id usb;
+ };
+};
+
+struct config_group dovmgr_pci_group;
+struct config_group dovmgr_usb_group;
+
+static inline struct dovmgr_item *to_dovmgr_item(struct config_item *cfsitem)
+{
+ if (!cfsitem)
+ return NULL;
+
+ return container_of(cfsitem, struct dovmgr_item, item);
+}
+
+static int dovmgr_notifier_action(struct config_group *group,
+ unsigned long action, struct device *dev,
+ int (*do_match)(struct dovmgr_item *item, struct device *dev),
+ int (*do_action)(struct dovmgr_item *item, unsigned long action,
+ struct device *dev))
+{
+ struct config_item *cfsitem;
+ struct dovmgr_item *item;
+ int ret;
+
+ /* only handle device notifiers */
+ if (action != BUS_NOTIFY_ADD_DEVICE &&
+ action != BUS_NOTIFY_DEL_DEVICE &&
+ action != BUS_NOTIFY_REMOVED_DEVICE)
+ return 0;
+
+ ret = 0;
+ list_for_each_entry(cfsitem, &group->cg_children, ci_entry) {
+ item = to_dovmgr_item(cfsitem);
+ if (!item->enable || !(*do_match)(item, dev))
+ continue;
+
+ ret = (*do_action)(item, action, dev);
+ if (ret != 0)
+ break;
+ }
+ return ret;
+}
+
+#if IS_ENABLED(CONFIG_PCI)
+/* copy of drivers/pci/pci.h */
+static inline const struct pci_device_id *
+pci_match_one_device(const struct pci_device_id *id, const struct pci_dev *dev)
+{
+ if ((id->vendor == PCI_ANY_ID || id->vendor == dev->vendor) &&
+ (id->device == PCI_ANY_ID || id->device == dev->device) &&
+ (id->subvendor == PCI_ANY_ID ||
+ id->subvendor == dev->subsystem_vendor) &&
+ (id->subdevice == PCI_ANY_ID ||
+ id->subdevice == dev->subsystem_device) &&
+ !((id->class ^ dev->class) & id->class_mask))
+ return id;
+ return NULL;
+}
+
+static int dovmgr_pci_item_match(struct dovmgr_item *item, struct device *dev)
+{
+ struct pci_dev *pdev;
+
+ BUG_ON(item->type != ITEM_PCI);
+ pdev = to_pci_dev(dev);
+
+ return pci_match_one_device(&item->pci, pdev) != NULL;
+}
+#endif
+
+#if IS_ENABLED(CONFIG_USB)
+/* in drivers/usb/core/driver.c */
+extern int usb_match_device(struct usb_device *dev,
+ const struct usb_device_id *id);
+
+static int dovmgr_usb_item_match(struct dovmgr_item *item, struct device *dev)
+{
+ struct usb_device *udev;
+
+ BUG_ON(item->type != ITEM_USB);
+ udev = to_usb_device(dev);
+
+ return usb_match_device(udev, &item->usb);
+}
+#endif
+
+static struct dovmgr_dev_item *dovmgr_lookup_dev_item(struct dovmgr_item *item,
+ struct device *dev)
+{
+ struct dovmgr_dev_item *ditem;
+
+ list_for_each_entry(ditem, &item->dev_item_list, node)
+ if (ditem->dev == dev)
+ return ditem;
+ return NULL;
+}
+
+static void dovmgr_item_work_func(struct work_struct *work)
+{
+ struct dovmgr_dev_item *ditem = container_of(work,
+ struct dovmgr_dev_item, work);
+ struct dovmgr_item *item = ditem->item;
+ struct device *dev;
+ struct device_node *np;
+ int err;
+
+ mutex_lock(&item->dev_item_mutex);
+
+ dev = ditem->dev;
+ np = dev->of_node;
+ if (!dev || !np || !item->overlay_name || ditem->overlay_id >= 0)
+ goto out_unlock;
+
+ pr_info("%s: %s %s\n", __func__,
+ kobject_name(&dev->kobj), of_node_full_name(np));
+
+ err = request_firmware_direct(&ditem->fw, item->overlay_name, dev);
+ if (err != 0) {
+ pr_err("%s: %s failed to load firmware '%s'\n", __func__,
+ kobject_name(&dev->kobj), item->overlay_name);
+ goto out_unlock;
+ }
+
+ of_fdt_unflatten_tree((void *)ditem->fw->data, &ditem->overlay);
+ if (ditem->overlay == NULL) {
+ pr_err("%s: %s failed to load firmware '%s'\n", __func__,
+ kobject_name(&dev->kobj), item->overlay_name);
+ goto out_release_fw;
+ }
+
+ /* mark it as detached */
+ of_node_set_flag(ditem->overlay, OF_DETACHED);
+
+ /* perform resolution */
+ err = of_resolve_phandles(ditem->overlay);
+ if (err != 0) {
+ pr_err("%s: %s failed to resolve tree\n", __func__,
+ kobject_name(&dev->kobj));
+ goto out_release_overlay;
+ }
+
+ err = of_overlay_create_target_root(ditem->overlay, np);
+ if (err < 0) {
+ pr_err("%s: %s failed to create overlay\n", __func__,
+ kobject_name(&dev->kobj));
+ goto out_release_overlay;
+ }
+ ditem->overlay_id = err;
+
+out_unlock:
+ mutex_unlock(&item->dev_item_mutex);
+ return;
+
+out_release_overlay:
+ /* TODO: free the overlay, we can't right now cause
+ * the unflatten method does not track it */
+ ditem->overlay = NULL;
+out_release_fw:
+ release_firmware(ditem->fw);
+ ditem->fw = NULL;
+ goto out_unlock;
+}
+
+/* dev item list mutex lock must be held */
+static int dovmgr_add_dev_item(struct dovmgr_item *item, struct device *dev)
+{
+ struct dovmgr_dev_item *ditem;
+
+ /* first make sure there's no duplicate */
+ if (dovmgr_lookup_dev_item(item, dev))
+ return -EEXIST;
+
+ /* add the device item */
+ ditem = kzalloc(sizeof(*ditem), GFP_KERNEL);
+ if (!ditem)
+ return -ENOMEM;
+ ditem->overlay_id = -1;
+ ditem->dev = get_device(dev);
+ INIT_WORK(&ditem->work, dovmgr_item_work_func);
+ ditem->item = item;
+
+ list_add_tail(&ditem->node, &item->dev_item_list);
+
+ pr_info("%s: added device %s from item's %s list\n", __func__,
+ kobject_name(&dev->kobj),
+ config_item_name(&item->item));
+
+ /* now schedule the overlay application */
+ if (item->overlay_name)
+ schedule_work(&ditem->work);
+
+ return 0;
+}
+
+static int dovmgr_remove_dev_item(struct dovmgr_item *item, struct device *dev)
+{
+ struct dovmgr_dev_item *ditem;
+
+ /* find it */
+ ditem = dovmgr_lookup_dev_item(item, dev);
+ if (!ditem)
+ return -ENODEV;
+
+ if (work_pending(&ditem->work))
+ cancel_work_sync(&ditem->work);
+
+ if (ditem->overlay_id >= 0) {
+ of_overlay_destroy(ditem->overlay_id);
+ ditem->overlay_id = -1;
+
+ }
+
+ if (ditem->overlay) {
+ /* TODO: free the overlay, we can't right now cause
+ * the unflatten method does not track it */
+ ditem->overlay = NULL;
+ }
+
+ if (ditem->fw) {
+ /* TODO release_firmware(ditem->fw); */
+ release_firmware(ditem->fw);
+ ditem->fw = NULL;
+ }
+
+ put_device(ditem->dev);
+ list_del(&ditem->node);
+
+ kfree(ditem);
+
+ pr_info("%s: removed device %s from item's %s list\n", __func__,
+ kobject_name(&dev->kobj),
+ config_item_name(&item->item));
+
+ return 0;
+}
+
+static int dovmgr_item_notify(struct dovmgr_item *item,
+ unsigned long action, struct device *dev)
+{
+ int ret;
+
+ ret = 0;
+ mutex_lock(&item->dev_item_mutex);
+
+ switch (action) {
+ case BUS_NOTIFY_ADD_DEVICE:
+ pr_info("%s: BUS_NOTIFY_ADD_DEVICE for %s\n", __func__,
+ kobject_name(&dev->kobj));
+
+ ret = dovmgr_add_dev_item(item, dev);
+ if (ret != 0)
+ goto out_unlock;
+
+ break;
+
+ case BUS_NOTIFY_DEL_DEVICE:
+ pr_info("%s: BUS_NOTIFY_DEL_DEVICE for %s\n", __func__,
+ kobject_name(&dev->kobj));
+ break;
+
+ case BUS_NOTIFY_REMOVED_DEVICE:
+ pr_info("%s: BUS_NOTIFY_REMOVE_DEVICE for %s\n", __func__,
+ kobject_name(&dev->kobj));
+
+ ret = dovmgr_remove_dev_item(item, dev);
+ if (ret != 0)
+ goto out_unlock;
+
+ break;
+ }
+
+out_unlock:
+ mutex_unlock(&item->dev_item_mutex);
+
+ return ret;
+}
+
+#if IS_ENABLED(CONFIG_PCI)
+static int dovmgr_pci_add_iterator(struct device *dev, void *data)
+{
+ struct dovmgr_item *item = data;
+
+ /* do add match */
+ if (!item->enable || !dovmgr_pci_item_match(item, dev))
+ return 0;
+
+ pr_info("%s: dev=%s\n", __func__, kobject_name(&dev->kobj));
+
+ return dovmgr_item_notify(item, BUS_NOTIFY_ADD_DEVICE, dev);
+}
+
+static int dovmgr_pci_removed_iterator(struct device *dev, void *data)
+{
+ struct dovmgr_item *item = data;
+
+ /* do add match */
+ if (item->enable || !dovmgr_pci_item_match(item, dev))
+ return 0;
+
+ pr_info("%s: dev=%s\n", __func__, kobject_name(&dev->kobj));
+
+ return dovmgr_item_notify(item, BUS_NOTIFY_REMOVED_DEVICE, dev);
+}
+#endif
+
+#if IS_ENABLED(CONFIG_USB)
+static int dovmgr_usb_add_iterator(struct device *dev, void *data)
+{
+ struct dovmgr_item *item = data;
+
+ /* do add match */
+ if (item->enable || !dovmgr_usb_item_match(item, dev))
+ return 0;
+
+ pr_info("%s: dev=%s\n", __func__, kobject_name(&dev->kobj));
+
+ return dovmgr_item_notify(item, BUS_NOTIFY_ADD_DEVICE, dev);
+}
+
+static int dovmgr_usb_removed_iterator(struct device *dev, void *data)
+{
+ struct dovmgr_item *item = data;
+
+ /* do add match */
+ if (!item->enable || !dovmgr_usb_item_match(item, dev))
+ return 0;
+
+ pr_info("%s: dev=%s\n", __func__, kobject_name(&dev->kobj));
+
+ return dovmgr_item_notify(item, BUS_NOTIFY_REMOVED_DEVICE, dev);
+}
+#endif
+
+static int dovmgr_item_set_enable(struct dovmgr_item *item, bool new_enable)
+{
+ int ret;
+
+ if (new_enable == item->enable)
+ return 0;
+
+ item->enable = new_enable;
+ switch (item->type) {
+#if IS_ENABLED(CONFIG_PCI)
+ case ITEM_PCI:
+ ret = bus_for_each_dev(&pci_bus_type, NULL, item,
+ new_enable ? dovmgr_pci_add_iterator :
+ dovmgr_pci_removed_iterator);
+ if (ret != 0)
+ return ret;
+ break;
+#endif
+#if IS_ENABLED(CONFIG_USB)
+ case ITEM_USB:
+ ret = bus_for_each_dev(&usb_bus_type, NULL, item,
+ new_enable ? dovmgr_usb_add_iterator :
+ dovmgr_usb_removed_iterator);
+ if (ret != 0)
+ return ret;
+ break;
+#endif
+ default:
+ break;
+ }
+ return 0;
+}
+
+
+static ssize_t dovmgr_item_str_show(struct dovmgr_item *item,
+ char *page, char **strp)
+{
+ return snprintf(page, PAGE_SIZE, "%s\n",
+ *strp ? *strp : "");
+}
+
+static ssize_t dovmgr_item_str_store(struct dovmgr_item *item,
+ const char *page, size_t count, char **strp)
+{
+ const char *s;
+ int len;
+
+ /* copy to path buffer (and make sure it's always zero terminated */
+ len = strnlen(page, PAGE_SIZE);
+ if (len >= PAGE_SIZE)
+ return -EINVAL;
+ s = page + len;
+ while (len > 0 && *--s == '\n')
+ len--;
+ if (len == 0)
+ return -EINVAL;
+
+ if (*strp)
+ kfree(*strp);
+ *strp = kmalloc(len + 1, GFP_KERNEL);
+ if (!*strp)
+ return -ENOMEM;
+ memcpy(*strp, page, len);
+ (*strp)[len + 1] = '\0';
+
+ return count;
+}
+
+static ssize_t dovmgr_item_path_show(struct config_item *citem, char *page)
+{
+ struct dovmgr_item *item = to_dovmgr_item(citem);
+ return dovmgr_item_str_show(item, page, &item->path);
+}
+
+static ssize_t dovmgr_item_path_store(struct config_item *citem,
+ const char *page, size_t count)
+{
+ struct dovmgr_item *item = to_dovmgr_item(citem);
+ return dovmgr_item_str_store(item, page, count, &item->path);
+}
+
+static ssize_t dovmgr_item_enable_show(struct config_item *citem, char *page)
+{
+ struct dovmgr_item *item = to_dovmgr_item(citem);
+ return snprintf(page, PAGE_SIZE, "%u\n", !!item->enable);
+}
+
+static ssize_t dovmgr_item_enable_store(struct config_item *citem,
+ const char *page, size_t count)
+{
+ struct dovmgr_item *item = to_dovmgr_item(citem);
+ int ret;
+ unsigned int val;
+
+ ret = kstrtouint(page, 0, &val);
+ if (ret != 0)
+ return ret;
+
+ ret = dovmgr_item_set_enable(item, !!val);
+ if (ret != 0)
+ return ret;
+
+ return count;
+}
+
+static ssize_t dovmgr_item_overlay_show(struct config_item *citem, char *page)
+{
+ struct dovmgr_item *item = to_dovmgr_item(citem);
+ ssize_t ret;
+
+ mutex_lock(&item->dev_item_mutex);
+ ret = snprintf(page, PAGE_SIZE, "%s\n", item->overlay_name ?
+ item->overlay_name : "");
+ mutex_unlock(&item->dev_item_mutex);
+ return ret;
+};
+
+
+static ssize_t dovmgr_item_overlay_store(struct config_item *citem,
+ const char *page, size_t count)
+{
+ struct dovmgr_item *item = to_dovmgr_item(citem);
+ ssize_t ret;
+
+ mutex_lock(&item->dev_item_mutex);
+ kfree(item->overlay_name);
+ item->overlay_name = kstrndup(page, PAGE_SIZE, GFP_KERNEL);
+ if (!item->overlay_name)
+ ret = -ENOMEM;
+ else
+ ret = count;
+ mutex_unlock(&item->dev_item_mutex);
+ return ret;
+}
+
+static ssize_t dovmgr_item_status_show(struct config_item *citem, char *page)
+{
+ struct dovmgr_item *item = to_dovmgr_item(citem);
+ struct dovmgr_dev_item *ditem;
+ char *p, *e;
+ int len;
+
+ p = page;
+ e = page + PAGE_SIZE;
+
+ mutex_lock(&item->dev_item_mutex);
+ list_for_each_entry(ditem, &item->dev_item_list, node) {
+ len = snprintf(p, e - p, "%s:%s:%d\n",
+ kobject_name(&ditem->dev->kobj),
+ of_node_full_name(ditem->dev->of_node),
+ ditem->overlay_id);
+ p += len;
+ if (p >= e - 1)
+ break;
+ }
+ mutex_unlock(&item->dev_item_mutex);
+
+ return p - page;
+}
+
+CONFIGFS_ATTR(dovmgr_item_, path);
+CONFIGFS_ATTR_RO(dovmgr_item_, status);
+CONFIGFS_ATTR(dovmgr_item_, enable);
+CONFIGFS_ATTR(dovmgr_item_, overlay);
+
+#if IS_ENABLED(CONFIG_PCI)
+static ssize_t dovmgr_item_pci_device_show(struct config_item *citem,
+ char *page)
+{
+ struct dovmgr_item *item = to_dovmgr_item(citem);
+ return snprintf(page, PAGE_SIZE, "0x%04x\n", item->pci.device);
+}
+
+static ssize_t dovmgr_item_pci_device_store(struct config_item *citem,
+ const char *page, size_t count)
+{
+ struct dovmgr_item *item = to_dovmgr_item(citem);
+ int ret;
+ unsigned int val;
+
+ ret = kstrtouint(page, 0, &val);
+ if (ret != 0)
+ return ret;
+ item->pci.device = val;
+ return count;
+}
+
+static ssize_t dovmgr_item_pci_vendor_show(struct config_item *citem,
+ char *page)
+{
+ struct dovmgr_item *item = to_dovmgr_item(citem);
+ return snprintf(page, PAGE_SIZE, "0x%04x\n", item->pci.vendor);
+}
+
+static ssize_t dovmgr_item_pci_vendor_store(struct config_item *citem,
+ const char *page, size_t count)
+{
+ struct dovmgr_item *item = to_dovmgr_item(citem);
+ int ret;
+ unsigned int val;
+
+ /* cannot modify when item is enabled */
+ if (item->enable)
+ return -EBUSY;
+
+ ret = kstrtouint(page, 0, &val);
+ if (ret != 0)
+ return ret;
+ item->pci.vendor = val;
+ return count;
+}
+
+static ssize_t dovmgr_item_pci_subdevice_show(struct config_item *citem,
+ char *page)
+{
+ struct dovmgr_item *item = to_dovmgr_item(citem);
+ return snprintf(page, PAGE_SIZE, "0x%08x\n", item->pci.subdevice);
+}
+
+static ssize_t dovmgr_item_pci_subdevice_store(struct config_item *citem,
+ const char *page, size_t count)
+{
+ struct dovmgr_item *item = to_dovmgr_item(citem);
+ int ret;
+ unsigned int val;
+
+ /* cannot modify when item is enabled */
+ if (item->enable)
+ return -EBUSY;
+
+ ret = kstrtouint(page, 0, &val);
+ if (ret != 0)
+ return ret;
+ item->pci.subdevice = val;
+ return count;
+}
+
+static ssize_t dovmgr_item_pci_subvendor_show(struct config_item *citem,
+ char *page)
+{
+ struct dovmgr_item *item = to_dovmgr_item(citem);
+ return snprintf(page, PAGE_SIZE, "0x%08x\n", item->pci.subvendor);
+}
+
+static ssize_t dovmgr_item_pci_subvendor_store(struct config_item *citem,
+ const char *page, size_t count)
+{
+ struct dovmgr_item *item = to_dovmgr_item(citem);
+ int ret;
+ unsigned int val;
+
+ /* cannot modify when item is enabled */
+ if (item->enable)
+ return -EBUSY;
+
+ ret = kstrtouint(page, 0, &val);
+ if (ret != 0)
+ return ret;
+ item->pci.subvendor = val;
+ return count;
+}
+
+static ssize_t dovmgr_item_pci_class_show(struct config_item *citem, char *page)
+{
+ struct dovmgr_item *item = to_dovmgr_item(citem);
+ return snprintf(page, PAGE_SIZE, "0x%04x\n", item->pci.class);
+}
+
+static ssize_t dovmgr_item_pci_class_store(struct config_item *citem,
+ const char *page, size_t count)
+{
+ struct dovmgr_item *item = to_dovmgr_item(citem);
+ int ret;
+ unsigned int val;
+
+ /* cannot modify when item is enabled */
+ if (item->enable)
+ return -EBUSY;
+
+ ret = kstrtouint(page, 0, &val);
+ if (ret != 0)
+ return ret;
+ item->pci.class = val;
+ return count;
+}
+
+static ssize_t dovmgr_item_pci_class_mask_show(struct config_item *citem,
+ char *page)
+{
+ struct dovmgr_item *item = to_dovmgr_item(citem);
+ return snprintf(page, PAGE_SIZE, "0x%04x\n", item->pci.class_mask);
+}
+
+static ssize_t dovmgr_item_pci_class_mask_store(struct config_item *citem,
+ const char *page, size_t count)
+{
+ struct dovmgr_item *item = to_dovmgr_item(citem);
+ int ret;
+ unsigned int val;
+
+ /* cannot modify when item is enabled */
+ if (item->enable)
+ return -EBUSY;
+
+ ret = kstrtouint(page, 0, &val);
+ if (ret != 0)
+ return ret;
+ item->pci.class_mask = val;
+ return count;
+}
+
+CONFIGFS_ATTR(dovmgr_item_pci_, device);
+CONFIGFS_ATTR(dovmgr_item_pci_, vendor);
+CONFIGFS_ATTR(dovmgr_item_pci_, subdevice);
+CONFIGFS_ATTR(dovmgr_item_pci_, subvendor);
+CONFIGFS_ATTR(dovmgr_item_pci_, class);
+CONFIGFS_ATTR(dovmgr_item_pci_, class_mask);
+#endif
+
+#if IS_ENABLED(CONFIG_USB)
+static ssize_t dovmgr_item_usb_idProduct_show(struct config_item *citem,
+ char *page)
+{
+ struct dovmgr_item *item = to_dovmgr_item(citem);
+ return snprintf(page, PAGE_SIZE, "0x%04x\n",
+ item->usb.idProduct);
+}
+
+static ssize_t dovmgr_item_usb_idProduct_store(struct config_item *citem,
+ const char *page, size_t count)
+{
+ struct dovmgr_item *item = to_dovmgr_item(citem);
+ int ret;
+ unsigned int val;
+
+ /* cannot modify when item is enabled */
+ if (item->enable)
+ return -EBUSY;
+
+ ret = kstrtouint(page, 0, &val);
+ if (ret != 0)
+ return ret;
+ item->usb.idProduct = val;
+ return count;
+}
+
+static ssize_t dovmgr_item_usb_idVendor_show(struct config_item *citem,
+ char *page)
+{
+ struct dovmgr_item *item = to_dovmgr_item(citem);
+ return snprintf(page, PAGE_SIZE, "0x%04x\n",
+ item->usb.idVendor);
+}
+
+static ssize_t dovmgr_item_usb_idVendor_store(struct config_item *citem,
+ const char *page, size_t count)
+{
+ struct dovmgr_item *item = to_dovmgr_item(citem);
+ int ret;
+ unsigned int val;
+
+ /* cannot modify when item is enabled */
+ if (item->enable)
+ return -EBUSY;
+
+ ret = kstrtouint(page, 0, &val);
+ if (ret != 0)
+ return ret;
+ item->usb.idVendor = val;
+ return count;
+}
+
+CONFIGFS_ATTR(dovmgr_item_usb_, idProduct);
+CONFIGFS_ATTR(dovmgr_item_usb_, idVendor);
+#endif
+
+#if IS_ENABLED(CONFIG_PCI)
+static struct configfs_attribute *dovmgr_pci_attrs[] = {
+ &dovmgr_item_attr_path,
+ &dovmgr_item_attr_status,
+ &dovmgr_item_attr_enable,
+ &dovmgr_item_attr_overlay,
+ &dovmgr_item_pci_attr_device,
+ &dovmgr_item_pci_attr_vendor,
+ &dovmgr_item_pci_attr_subdevice,
+ &dovmgr_item_pci_attr_subvendor,
+ &dovmgr_item_pci_attr_class,
+ &dovmgr_item_pci_attr_class_mask,
+ NULL,
+};
+#endif
+
+#if IS_ENABLED(CONFIG_USB)
+static struct configfs_attribute *dovmgr_usb_attrs[] = {
+ &dovmgr_item_attr_path,
+ &dovmgr_item_attr_enable,
+ &dovmgr_item_attr_status,
+ &dovmgr_item_attr_overlay,
+ &dovmgr_item_usb_attr_idVendor,
+ &dovmgr_item_usb_attr_idProduct,
+ NULL,
+};
+#endif
+
+static void dovmgr_release(struct config_item *cfsitem)
+{
+ struct dovmgr_item *item = to_dovmgr_item(cfsitem);
+
+ /* disable item (this removes the overlay and all) */
+ dovmgr_item_set_enable(item, false);
+
+ kfree(item->path);
+ kfree(item);
+}
+
+static struct configfs_item_operations dovmgr_item_ops = {
+ .release = dovmgr_release,
+};
+
+#if IS_ENABLED(CONFIG_PCI)
+static struct config_item_type dovmgr_pci_item_type = {
+ .ct_item_ops = &dovmgr_item_ops,
+ .ct_attrs = dovmgr_pci_attrs,
+ .ct_owner = THIS_MODULE,
+};
+#endif
+
+#if IS_ENABLED(CONFIG_USB)
+static struct config_item_type dovmgr_usb_item_type = {
+ .ct_item_ops = &dovmgr_item_ops,
+ .ct_attrs = dovmgr_usb_attrs,
+ .ct_owner = THIS_MODULE,
+};
+#endif
+
+static struct config_item *dovmgr_group_make_item(
+ struct config_group *group, const char *name,
+ enum dovmgr_type type)
+{
+ struct dovmgr_item *item;
+ struct config_item_type *item_type;
+
+ switch (type) {
+#if IS_ENABLED(CONFIG_PCI)
+ case ITEM_PCI:
+ item_type = &dovmgr_pci_item_type;
+ break;
+#endif
+#if IS_ENABLED(CONFIG_USB)
+ case ITEM_USB:
+ item_type = &dovmgr_usb_item_type;
+ break;
+#endif
+ default:
+ return ERR_PTR(-EINVAL);
+ };
+
+ item = kzalloc(sizeof(*item), GFP_KERNEL);
+ if (!item)
+ return ERR_PTR(-ENOMEM);
+
+ item->type = type;
+ item->enable = false;
+ mutex_init(&item->dev_item_mutex);
+ INIT_LIST_HEAD(&item->dev_item_list);
+
+ switch (type) {
+#if IS_ENABLED(CONFIG_PCI)
+ case ITEM_PCI:
+ /* default for matching device/vendor */
+ item->pci.vendor = PCI_ANY_ID;
+ item->pci.device = PCI_ANY_ID;
+ item->pci.subvendor = PCI_ANY_ID;
+ item->pci.subdevice = PCI_ANY_ID;
+ item->pci.class = 0;
+ item->pci.class_mask = 0;
+ break;
+#endif
+#if IS_ENABLED(CONFIG_USB)
+ case ITEM_USB:
+ /* default */
+ item->usb.match_flags = USB_DEVICE_ID_MATCH_DEVICE;
+ break;
+#endif
+ default:
+ return ERR_PTR(-EINVAL);
+ };
+
+ config_item_init_type_name(&item->item, name, item_type);
+ return &item->item;
+}
+
+#if IS_ENABLED(CONFIG_PCI)
+static struct config_item *dovmgr_group_pci_make_item(
+ struct config_group *group, const char *name)
+{
+ return dovmgr_group_make_item(group, name, ITEM_PCI);
+}
+#endif
+
+#if IS_ENABLED(CONFIG_USB)
+static struct config_item *dovmgr_group_usb_make_item(
+ struct config_group *group, const char *name)
+{
+ return dovmgr_group_make_item(group, name, ITEM_USB);
+}
+#endif
+
+static void dovmgr_group_drop_item(struct config_group *group,
+ struct config_item *cfsitem)
+{
+ struct dovmgr_item *item = to_dovmgr_item(cfsitem);
+
+ switch (item->type) {
+#if IS_ENABLED(CONFIG_PCI)
+ case ITEM_PCI:
+ break;
+#endif
+#if IS_ENABLED(CONFIG_USB)
+ case ITEM_USB:
+ break;
+#endif
+ default:
+ break;
+ }
+ config_item_put(&item->item);
+}
+
+#if IS_ENABLED(CONFIG_PCI)
+static struct configfs_group_operations dovmgr_pci_group_ops = {
+ .make_item = dovmgr_group_pci_make_item,
+ .drop_item = dovmgr_group_drop_item,
+};
+
+static struct config_item_type dovmgr_pci_type = {
+ .ct_group_ops = &dovmgr_pci_group_ops,
+ .ct_owner = THIS_MODULE,
+};
+#endif
+
+#if IS_ENABLED(CONFIG_USB)
+static struct configfs_group_operations dovmgr_usb_group_ops = {
+ .make_item = dovmgr_group_usb_make_item,
+ .drop_item = dovmgr_group_drop_item,
+};
+
+static struct config_item_type dovmgr_usb_type = {
+ .ct_group_ops = &dovmgr_usb_group_ops,
+ .ct_owner = THIS_MODULE,
+};
+#endif
+
+static struct configfs_group_operations dovmgr_ops = {
+ /* empty - we don't allow anything to be created */
+};
+
+static struct config_item_type dovmgr_type = {
+ .ct_group_ops = &dovmgr_ops,
+ .ct_owner = THIS_MODULE,
+};
+
+struct config_group *dovmgr_def_groups[] = {
+#if IS_ENABLED(CONFIG_PCI)
+ &dovmgr_pci_group,
+#endif
+#if IS_ENABLED(CONFIG_USB)
+ &dovmgr_usb_group,
+#endif
+ NULL
+};
+
+static struct configfs_subsystem dovmgr_subsys = {
+ .su_group = {
+ .cg_item = {
+ .ci_namebuf = "dovmgr",
+ .ci_type = &dovmgr_type,
+ },
+ .default_groups = dovmgr_def_groups,
+ },
+ .su_mutex = __MUTEX_INITIALIZER(dovmgr_subsys.su_mutex),
+};
+
+#if IS_ENABLED(CONFIG_PCI)
+static int pci_dev_instantiate(struct pci_dev *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device *bus_dev;
+ struct of_changeset cset;
+ struct device_node *np, *npb;
+ int ret;
+
+ npb = NULL;
+
+ /* already instantiated */
+ if (dev->of_node) {
+ pr_debug("%s: dev=%s of_node=%s\n", __func__,
+ kobject_name(&dev->kobj),
+ of_node_full_name(dev->of_node));
+ return 0;
+ }
+
+ bus_dev = &pdev->bus->dev;
+
+ pr_debug("%s: %s: %02x:%02x.%02x - node %s%s\n", __func__,
+ kobject_name(&dev->kobj),
+ pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
+ bus_dev->of_node ? of_node_full_name(bus_dev->of_node) : "<NULL>",
+ pci_is_bridge(pdev) ? " bridge" : "");
+
+ /* to create the node, the bus must be present */
+ if (!bus_dev->of_node) {
+ pr_err("%s: No node for %s because no bus device node\n",
+ __func__, kobject_name(&dev->kobj));
+ return 0;
+ }
+
+ of_changeset_init(&cset);
+
+ np = of_changeset_create_device_node(&cset, bus_dev->of_node,
+ "%s/pci-%04x-%02x-%02x.%d",
+ of_node_full_name(bus_dev->of_node),
+ pci_domain_nr(pdev->bus), pdev->bus->number,
+ PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
+ if (IS_ERR(np)) {
+ ret = PTR_ERR(np);
+ goto out_cset_fail;
+ }
+
+ ret = of_changeset_add_property_stringf(&cset, np, "compatible",
+ "pciclass,%04x", (pdev->class >> 8) & 0xffffff);
+ if (ret != 0)
+ goto out_cset_fail;
+
+ ret = of_changeset_add_property_u32(&cset, np, "vendor",
+ pdev->vendor);
+ if (ret != 0)
+ goto out_cset_fail;
+
+ ret = of_changeset_add_property_u32(&cset, np, "device",
+ pdev->device);
+ if (ret != 0)
+ goto out_cset_fail;
+
+ ret = of_changeset_add_property_string(&cset, np, "status", "okay");
+ if (ret != 0)
+ goto out_cset_fail;
+
+ ret = of_changeset_add_property_bool(&cset, np, "auto-generated");
+ if (ret != 0)
+ goto out_cset_fail;
+
+ ret = of_changeset_attach_node(&cset, np);
+ if (ret != 0)
+ goto out_cset_fail;
+
+ /* are we creating a bridge; swell */
+ npb = NULL;
+ if (pci_is_bridge(pdev) && !pdev->subordinate->dev.of_node) {
+
+ pr_debug("%s: %s: bus->dev=%s subordinate=%s\n", __func__,
+ kobject_name(&dev->kobj),
+ kobject_name(&pdev->bus->dev.kobj),
+ kobject_name(&pdev->subordinate->dev.kobj));
+
+ npb = of_changeset_create_device_node(&cset, bus_dev->of_node,
+ "%s/pci-%04x-%02x",
+ of_node_full_name(bus_dev->of_node),
+ pci_domain_nr(pdev->subordinate),
+ pdev->subordinate->number);
+ if (IS_ERR(npb)) {
+ ret = PTR_ERR(npb);
+ goto out_cset_fail;
+ }
+
+ ret = of_changeset_add_property_string(&cset, npb, "compatible", "generic,pci-bus");
+ if (ret != 0)
+ goto out_cset_fail;
+
+ ret = of_changeset_add_property_string(&cset, npb, "device_type", "pci");
+ if (ret != 0)
+ goto out_cset_fail;
+
+ ret = of_changeset_add_property_string(&cset, npb, "status", "okay");
+ if (ret != 0)
+ goto out_cset_fail;
+
+ ret = of_changeset_add_property_bool(&cset, npb, "auto-generated");
+ if (ret != 0)
+ goto out_cset_fail;
+
+ ret = of_changeset_attach_node(&cset, npb);
+ if (ret != 0)
+ goto out_cset_fail;
+ }
+
+ ret = of_changeset_apply(&cset);
+ if (ret != 0)
+ goto out_cset_fail;
+
+ /* permanently commit */
+ of_changeset_destroy(&cset);
+
+ /* bind the node to the device */
+ dev->of_node = np;
+ ret = sysfs_create_link(&dev->kobj, &dev->of_node->kobj,
+ "of_node");
+ if (ret)
+ pr_warn("%s: %s Error %d creating of_node link\n",
+ __func__, kobject_name(&dev->kobj), ret);
+
+ if (npb) {
+ pdev->subordinate->dev.of_node = npb;
+ ret = sysfs_create_link(&pdev->subordinate->dev.kobj, &npb->kobj,
+ "of_node");
+ if (ret)
+ pr_warn("%s: %s Error %d creating of_node link\n",
+ __func__, kobject_name(&dev->kobj), ret);
+ }
+
+
+ return 0;
+
+out_cset_fail:
+ pr_err("%s: %s Failed to apply changeset (err=%d)\n", __func__,
+ kobject_name(&dev->kobj), ret);
+ of_changeset_destroy(&cset);
+ return ret;
+}
+
+static int pci_dev_uninstantiate(struct pci_dev *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np, *npb;
+ struct of_changeset cset;
+ int ret;
+
+ /* device node must exist */
+ np = dev->of_node;
+ if (!np)
+ return 0;
+
+ /* and the auto-generated property */
+ if (!of_property_read_bool(np, "auto-generated"))
+ return 0;
+
+ of_changeset_init(&cset);
+
+ ret = of_changeset_detach_node(&cset, np);
+ if (ret != 0)
+ goto out_cset_fail;
+
+ npb = NULL;
+ if (pci_is_bridge(pdev))
+ npb = pdev->subordinate->dev.of_node;
+
+ if (npb != NULL) {
+ ret = of_changeset_detach_node(&cset, npb);
+ if (ret != 0)
+ goto out_cset_fail;
+ }
+
+ ret = of_changeset_apply(&cset);
+ if (ret != 0)
+ goto out_cset_fail;
+
+ dev->of_node = NULL;
+ if (npb != NULL)
+ pdev->subordinate->dev.of_node = NULL;
+
+ pr_debug("%s: %s: %02x:%02x.%02x\n", __func__,
+ kobject_name(&dev->kobj),
+ pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
+
+ /* TODO iterate over the properties and free */
+
+ return 0;
+
+out_cset_fail:
+ of_changeset_destroy(&cset);
+
+ return ret;
+}
+
+static int dovmgr_pci_notify(struct notifier_block *nb,
+ unsigned long action, void *arg)
+{
+ int ret;
+
+ if (action == BUS_NOTIFY_ADD_DEVICE)
+ pci_dev_instantiate(to_pci_dev(arg));
+
+ ret = dovmgr_notifier_action(&dovmgr_pci_group, action, arg,
+ dovmgr_pci_item_match, dovmgr_item_notify);
+
+ if (action == BUS_NOTIFY_REMOVED_DEVICE)
+ pci_dev_uninstantiate(to_pci_dev(arg));
+
+ return ret;
+}
+
+static struct notifier_block dovmgr_pci_notifier = {
+ .notifier_call = dovmgr_pci_notify,
+};
+
+static int pci_instantiate_iterator(struct device *dev, void *data)
+{
+ return pci_dev_instantiate(to_pci_dev(dev));
+}
+
+static int dovmgr_pci_init(void)
+{
+ int ret;
+
+ config_group_init_type_name(&dovmgr_pci_group, "pci", &dovmgr_pci_type);
+ ret = bus_register_notifier(&pci_bus_type, &dovmgr_pci_notifier);
+ if (ret != 0) {
+ pr_err("%s: bus_register_notifier() failed\n", __func__);
+ return ret;
+ }
+
+ ret = bus_for_each_dev(&pci_bus_type, NULL, NULL,
+ pci_instantiate_iterator);
+ if (ret != 0) {
+ pr_err("%s: bus_for_each_dev() failed\n", __func__);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void dovmgr_pci_cleanup(void)
+{
+ bus_unregister_notifier(&pci_bus_type, &dovmgr_pci_notifier);
+}
+#endif
+
+#if IS_ENABLED(CONFIG_USB)
+static int dovmgr_usb_notify(struct notifier_block *nb,
+ unsigned long action, void *arg)
+{
+ return dovmgr_notifier_action(&dovmgr_usb_group, action, arg,
+ dovmgr_usb_item_match, dovmgr_item_notify);
+}
+
+static struct notifier_block dovmgr_usb_notifier = {
+ .notifier_call = dovmgr_usb_notify,
+};
+
+static int dovmgr_usb_init(void)
+{
+ int ret;
+
+ config_group_init_type_name(&dovmgr_usb_group, "usb", &dovmgr_usb_type);
+ ret = bus_register_notifier(&usb_bus_type, &dovmgr_usb_notifier);
+ if (ret != 0) {
+ pr_err("%s: bus_register_notifier() failed\n", __func__);
+ return ret;
+ }
+ return 0;
+}
+
+static void dovmgr_usb_cleanup(void)
+{
+ bus_unregister_notifier(&usb_bus_type, &dovmgr_usb_notifier);
+}
+#endif
+
+static int __init dovmgr_init(void)
+{
+ int ret;
+
+ config_group_init(&dovmgr_subsys.su_group);
+#if IS_ENABLED(CONFIG_PCI)
+ configfs_add_default_group(&dovmgr_pci_group,
+ &dovmgr_subsys.su_group);
+#endif
+#if IS_ENABLED(CONFIG_USB)
+ configfs_add_default_group(&dovmgr_usb_group,
+ &dovmgr_subsys.su_group);
+#endif
+
+#if IS_ENABLED(CONFIG_PCI)
+ ret = dovmgr_pci_init();
+ if (ret != 0)
+ goto err_no_pci_init;
+#endif
+#if IS_ENABLED(CONFIG_USB)
+ ret = dovmgr_usb_init();
+ if (ret != 0)
+ goto err_no_usb_init;
+#endif
+
+ ret = configfs_register_subsystem(&dovmgr_subsys);
+ if (ret != 0) {
+ pr_err("%s: failed to register subsys\n", __func__);
+ goto err_no_configfs;
+ }
+ pr_info("%s: OK\n", __func__);
+ return 0;
+
+err_no_configfs:
+#if IS_ENABLED(CONFIG_USB)
+ dovmgr_usb_cleanup();
+err_no_usb_init:
+#endif
+#if IS_ENABLED(CONFIG_PCI)
+ dovmgr_pci_cleanup();
+err_no_pci_init:
+#endif
+ return ret;
+}
+late_initcall(dovmgr_init);
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index 051b147..3cdf8e1 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -593,7 +593,6 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
struct at24_data *at24;
int err;
unsigned i, num_addresses;
- u8 test_byte;
if (client->dev.platform_data) {
chip = *(struct at24_platform_data *)client->dev.platform_data;
@@ -744,18 +743,6 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
}
}
- i2c_set_clientdata(client, at24);
-
- /*
- * Perform a one-byte test read to verify that the
- * chip is functional.
- */
- err = at24_read(at24, 0, &test_byte, 1);
- if (err) {
- err = -ENODEV;
- goto err_clients;
- }
-
at24->nvmem_config.name = dev_name(&client->dev);
at24->nvmem_config.dev = &client->dev;
at24->nvmem_config.read_only = !writable;
@@ -777,6 +764,8 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
goto err_clients;
}
+ i2c_set_clientdata(client, at24);
+
dev_info(&client->dev, "%u byte %s EEPROM, %s, %u bytes/write\n",
chip.byte_len, client->name,
writable ? "writable" : "read-only", at24->write_max);
diff --git b/drivers/misc/tieqep.c b/drivers/misc/tieqep.c
new file mode 100644
index 0000000..bb69ad4
--- /dev/null
+++ b/drivers/misc/tieqep.c
@@ -0,0 +1,754 @@
+/*
+ * TI eQEP driver for AM33xx devices
+ *
+ * Copyright (C) 2013 Nathaniel R. Lewis - http://teknoman117.wordpress.com/
+ * Copyright (C) 2015 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * sysfs entries
+ * - position = absolute - current position; relative - last latched value
+ * - mode => 0 - absolute; 1 - relative
+ * - period => sampling period for the hardware
+ * - enable => 0 - eQEP disabled, 1 - eQEP enabled
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/input.h>
+
+/* eQEP register offsets from its base IO address */
+#define QPOSCNT 0x0000
+#define QPOSINIT 0x0004
+#define QPOSMAX 0x0008
+#define QPOSCMP 0x000C
+#define QPOSILAT 0x0010
+#define QPOSSLAT 0x0014
+#define QPOSLAT 0x0018
+#define QUTMR 0x001C
+#define QUPRD 0x0020
+#define QWDTMR 0x0024
+#define QWDPRD 0x0026
+#define QDECCTL 0x0028
+#define QEPCTL 0x002A
+#define QCAPCTL 0x002C
+#define QPOSCTL 0x002E
+#define QEINT 0x0030
+#define QFLG 0x0032
+#define QCLR 0x0034
+#define QFRC 0x0036
+#define QEPSTS 0x0038
+#define QCTMR 0x003A
+#define QCPRD 0x003C
+#define QCTMRLAT 0x003E
+#define QCPRDLAT 0x0040
+#define QREVID 0x005C
+
+#if 0 /* if you wanted another way to modify IP registers... */
+typedef volatile u32 REG32;
+typedef volatile u16 REG16;
+struct EQEP_REGS {
+ REG32 q_poscnt; /* 0x00 position counter */
+ REG32 q_posinit; /* 0x04 position counter initialization */
+ REG32 q_posmax; /* 0x08 maximum position count */
+ REG32 q_poscmp; /* 0x0C position compare */
+ REG32 q_posilat; /* 0x10 index position latch */
+ REG32 q_posslat; /* 0x14 strobe position latch */
+ REG32 q_poslat; /* 0x18 position counter latch */
+ REG32 q_utmr; /* 0x1C unit timer */
+ REG32 q_uprd; /* 0x20 unit period */
+ REG16 q_wdtmr; /* 0x24 watchdog timer */
+ REG16 q_wdprd; /* 0x26 watchdog period */
+ REG16 q_decctl; /* 0x28 decoder control */
+ REG16 q_epctl; /* 0x2A control register */
+ REG16 q_capctl; /* 0x2C capture control */
+ REG16 q_posctl; /* 0x2E position compare control */
+ REG16 q_eint; /* 0x30 interrupt enable */
+ REG16 q_flg; /* 0x32 interrupt flag */
+ REG16 q_clr; /* 0x34 interrupt clear */
+ REG16 q_frc; /* 0x36 interrupt force */
+ REG16 q_epsts; /* 0x38 status */
+ REG16 q_ctmr; /* 0x3A capture timer */
+ REG16 q_cprd; /* 0x3C capture period */
+ REG16 q_ctmrlat; /* 0x3E capture timer latch */
+ REG16 q_prdlat; /* 0x40 capture period latch */
+ char q_fill1[0x5c-0x40];
+ REG32 q_revid; /* 0x5C revision id */
+};
+#endif
+
+
+/* Bits for the QDECTL register */
+#define QSRC1 (1 << 15)
+#define QSRC0 (1 << 14)
+#define SOEN (1 << 13)
+#define SPSEL (1 << 12)
+#define XCR (1 << 11)
+#define SWAP (1 << 10)
+#define IGATE (1 << 9)
+#define QAP (1 << 8)
+#define QBP (1 << 7)
+#define QIP (1 << 6)
+#define QSP (1 << 5)
+
+/* Bits for the QEPCTL register */
+#define FREESOFT1 (1 << 15)
+#define FREESOFT0 (1 << 14)
+#define PCRM1 (1 << 13)
+#define PCRM0 (1 << 12)
+#define SEI1 (1 << 11)
+#define SEI0 (1 << 10)
+#define IEI1 (1 << 9)
+#define IEI0 (1 << 8)
+#define SWI (1 << 7)
+#define SEL (1 << 6)
+#define IEL1 (1 << 5)
+#define IEL0 (1 << 4)
+#define PHEN (1 << 3)
+#define QCLM (1 << 2)
+#define UTE (1 << 1)
+#define WDE (1 << 0)
+
+/* Bits for the QCAPCTL register */
+#define CEN (1 << 15)
+#define CCPS2 (1 << 6)
+#define CCPS0 (1 << 5)
+#define CCPS1 (1 << 4)
+#define UPPS3 (1 << 3)
+#define UPPS2 (1 << 2)
+#define UPPS1 (1 << 1)
+#define UPPS0 (1 << 0)
+
+/* Bits for the QPOSCTL register */
+#define PCSHDW (1 << 15)
+#define PCLOAD (1 << 14)
+#define PCPOL (1 << 13)
+#define PCE (1 << 12)
+#define PCSPW11 (1 << 11)
+#define PCSPW10 (1 << 10)
+#define PCSPW9 (1 << 9)
+#define PCSPW8 (1 << 8)
+#define PCSPW7 (1 << 7)
+#define PCSPW6 (1 << 6)
+#define PCSPW5 (1 << 5)
+#define PCSPW4 (1 << 4)
+#define PCSPW3 (1 << 3)
+#define PCSPW2 (1 << 2)
+#define PCSPW1 (1 << 1)
+#define PCSPW0 (1 << 0)
+
+/* Bits for the interrupt registers */
+#define EQEP_INTERRUPT_MASK 0x0FFF
+#define UTOF (1 << 11)
+
+/* Bits to control the clock in the PWMSS subsystem */
+#define PWMSS_EQEPCLK_EN BIT(4)
+#define PWMSS_EQEPCLK_STOP_REQ BIT(5)
+#define PWMSS_EQEPCLK_EN_ACK BIT(4)
+
+/*
+ * Modes for the eQEP unit
+ * Absolute - the position entry represents the current position of the encoder.
+ * Poll this value and it will be notified every period nanoseconds
+ * Relative - the position entry represents the last latched position of the encoder
+ * This value is latched every period nanoseconds and the internal counter
+ * is subsequenty reset
+ */
+#define TIEQEP_MODE_ABSOLUTE 0
+#define TIEQEP_MODE_RELATIVE 1
+
+/* Structure defining the characteristics of the eQEP unit */
+struct eqep_chip
+{
+ /* Platform device for this eQEP unit */
+ struct platform_device *pdev;
+
+ /* Pointer to the base of the memory of the eQEP unit */
+ void __iomem *mmio_base;
+
+ /* SYSCLKOUT to the eQEP unit */
+ u32 clk_rate;
+
+ /* IRQ for the eQEP unit */
+ u16 irq;
+
+ /* Mode of the eQEP unit */
+ u8 op_mode;
+
+ /* work stuct for the notify userspace work */
+ struct work_struct notify_work;
+
+ /* Backup for driver suspension */
+ u16 prior_qepctl;
+ u16 prior_qeint;
+};
+
+/* Notify userspace work */
+static void notify_handler(struct work_struct *work)
+{
+ /* Get a reference to the eQEP driver */
+ struct eqep_chip *eqep = container_of(work, struct eqep_chip, notify_work);
+
+ /* Notify the userspace */
+ sysfs_notify(&eqep->pdev->dev.kobj, NULL, "position");
+}
+
+/* eQEP Interrupt handler */
+static irqreturn_t eqep_irq_handler(int irq, void *dev_id)
+{
+ /* Get the instance information */
+ struct platform_device *pdev = dev_id;
+ struct eqep_chip *eqep = platform_get_drvdata(pdev);
+
+ /* Get the interrupt flags */
+ u16 iflags = readw(eqep->mmio_base + QFLG) & EQEP_INTERRUPT_MASK;
+
+ /* Check the interrupt source(s) */
+ if (iflags & UTOF) {
+ /* Handle the unit timer overflow interrupt by notifying any potential pollers */
+ schedule_work(&eqep->notify_work);
+ }
+
+ /* Clear interrupt flags (write back triggered flags to the clear register) */
+ writew(iflags, eqep->mmio_base + QCLR);
+
+ /* Return that the IRQ was handled successfully */
+ return IRQ_HANDLED;
+}
+
+/* Function to read whether the eQEP unit is enabled or disabled */
+static ssize_t eqep_get_enabled(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ /* Get the instance structure */
+ struct eqep_chip *eqep = dev_get_drvdata(dev);
+ u16 enabled = 0;
+
+ /* Increment the device usage count and run pm_runtime_resume() */
+ pm_runtime_get_sync(dev);
+
+ /* Read the qep control register and mask all but the enabled bit */
+ enabled = readw(eqep->mmio_base + QEPCTL) & PHEN;
+
+ /* Return the target in string format */
+ return sprintf(buf, "%u\n", (enabled) ? 1 : 0);
+}
+
+/* Function to set if the eQEP is enabled */
+static ssize_t eqep_set_enabled(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ /* Get the instance structure */
+ int rc;
+ u16 val;
+ u8 enabled;
+ struct eqep_chip *eqep = dev_get_drvdata(dev);
+
+ /* Convert the input string to an 8 bit uint */
+ if ((rc = kstrtou8(buf, 0, &enabled)))
+ return rc;
+
+ /* Increment the device usage count and run pm_runtime_resume() */
+ pm_runtime_get_sync(dev);
+ /* Get the existing state of QEPCTL */
+ val = readw(eqep->mmio_base + QEPCTL);
+
+ /* If we passed a number that is not 0, enable the eQEP */
+ if (enabled)
+ /* Enable the eQEP (Set PHEN in QEPCTL) */
+ val |= PHEN;
+ else
+ /* Disable the eQEP (Clear PHEN in QEPCTL) */
+ val &= ~PHEN;
+
+ /* Write flags back to control register */
+ writew(val, eqep->mmio_base + QEPCTL);
+
+ /* Return buffer length consumed (all) */
+ return count;
+}
+
+/* Function to read the current position of the eQEP */
+static ssize_t eqep_get_position(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct eqep_chip *eqep = dev_get_drvdata(dev);
+
+ s32 position = 0;
+ /* Increment the device usage count and run pm_runtime_resume() */
+ pm_runtime_get_sync(dev);
+
+ if (eqep->op_mode == TIEQEP_MODE_ABSOLUTE) {
+ position = readl(eqep->mmio_base + QPOSCNT);
+ } else if (eqep->op_mode == TIEQEP_MODE_RELATIVE) {
+ /* in relative mode, use the last latched value of the eQEP hardware */
+ position = readl(eqep->mmio_base + QPOSLAT);
+ dev_dbg(dev, "get_position:0x%08x\n", position);
+ }
+
+ return sprintf(buf, "%d\n", position);
+}
+
+/* Function to set the position of the eQEP hardware */
+static ssize_t eqep_set_position(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ int rc;
+ s32 position;
+ struct eqep_chip *eqep = dev_get_drvdata(dev);
+
+ if ((rc = kstrtos32(buf, 0, &position)))
+ return rc;
+
+ /* Increment the device usage count and run pm_runtime_resume() */
+ pm_runtime_get_sync(dev);
+ /*
+ * If we are in absolute mode, set the position of the encoder,
+ * discard relative mode because thats pointless
+ */
+ if (eqep->op_mode == TIEQEP_MODE_ABSOLUTE) {
+ /* If absolute mode, set the current value of the eQEP hardware */
+ writel(position, eqep->mmio_base + QPOSCNT);
+ }
+
+ /* Return buffer length consumed (all) */
+ return count;
+}
+
+/* Function to read the period of the unit time event timer */
+static ssize_t eqep_get_timer_period(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct eqep_chip *eqep = dev_get_drvdata(dev);
+ u64 period;
+
+ /* Increment the device usage count and run pm_runtime_resume() */
+ pm_runtime_get_sync(dev);
+ /* Convert from counts per interrupt back into period_ns */
+ period = readl(eqep->mmio_base + QUPRD);
+ period = period * NSEC_PER_SEC;
+ do_div(period, eqep->clk_rate);
+
+ /* Otherwise write out the data */
+ return sprintf(buf, "%llu\n", period);
+}
+
+/* Function to set the unit timer period. 0 = off, greater than zero sets the period */
+static ssize_t eqep_set_timer_period(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ int rc;
+ u16 tmp;
+ u64 period;
+
+ struct eqep_chip *eqep = dev_get_drvdata(dev);
+
+ if ((rc = kstrtou64(buf, 0, &period)))
+ return rc;
+
+ /* Increment the device usage count and run pm_runtime_resume() */
+ pm_runtime_get_sync(dev);
+ /* Disable the unit timer before modifying its period register */
+ tmp = readw(eqep->mmio_base + QEPCTL);
+ tmp &= ~(UTE | QCLM);
+ writew(tmp, eqep->mmio_base + QEPCTL);
+
+ /* Zero the unit timer counter register */
+ writel(0, eqep->mmio_base + QUTMR);
+
+ /* If the timer is enabled (a non-zero period has been passed) */
+ if (period) {
+ /* update the period */
+ period = period * eqep->clk_rate;
+ do_div(period, NSEC_PER_SEC);
+
+ dev_dbg(dev, "eqep_set_timer_period:%llu\n", period);
+
+ writel(period, eqep->mmio_base + QUPRD);
+
+ /* Enable unit timer, and latch QPOSLAT to QPOSCNT on timer expiration */
+ tmp |= UTE | QCLM;
+ writew(tmp, eqep->mmio_base + QEPCTL);
+ }
+
+ return count;
+}
+
+/* Function to read the mode of the eQEP hardware */
+static ssize_t eqep_get_mode(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct eqep_chip *eqep = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%u\n", eqep->op_mode);
+}
+
+/* Function to set the mode of the eQEP hardware */
+static ssize_t eqep_set_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ int rc;
+ u16 val;
+ u8 tmp_mode;
+ struct eqep_chip *eqep = dev_get_drvdata(dev);
+
+ if ((rc = kstrtou8(buf, 0, &tmp_mode)))
+ return rc;
+
+ dev_dbg(dev, "eqep_set_mode:%d\n", tmp_mode);
+
+ /* Increment the device usage count and run pm_runtime_resume() */
+ pm_runtime_get_sync(dev);
+ val = readw(eqep->mmio_base + QEPCTL);
+
+ if (tmp_mode == TIEQEP_MODE_ABSOLUTE) {
+ /*
+ * In absolute mode, don't reset the hardware based on time,
+ * so disable the unit timer position reset (Set PCRM[1:0] = 0)
+ */
+ val &= ~(PCRM1 | PCRM0);
+
+ eqep->op_mode = TIEQEP_MODE_ABSOLUTE;
+ } else if (tmp_mode == TIEQEP_MODE_RELATIVE) {
+ /*
+ * In relative mode, latch the value of the eQEP hardware on the
+ * overflow of the unit timer. So enable the unit timer position reset
+ * (Set PCRM[1:0] = 3)
+ */
+ val |= PCRM1 | PCRM0;
+
+ eqep->op_mode = TIEQEP_MODE_RELATIVE;
+ }
+
+ writew(val, eqep->mmio_base + QEPCTL);
+
+ return count;
+}
+
+/* Bind read/write functions to sysfs entries */
+static DEVICE_ATTR(enabled, 0644, eqep_get_enabled, eqep_set_enabled);
+static DEVICE_ATTR(position, 0644, eqep_get_position, eqep_set_position);
+static DEVICE_ATTR(period, 0644, eqep_get_timer_period, eqep_set_timer_period);
+static DEVICE_ATTR(mode, 0644, eqep_get_mode, eqep_set_mode);
+
+/* Array holding all of the sysfs entries */
+static const struct attribute *eqep_attrs[] = {
+ &dev_attr_enabled.attr,
+ &dev_attr_position.attr,
+ &dev_attr_period.attr,
+ &dev_attr_mode.attr,
+ NULL,
+};
+
+/* Driver function group */
+static const struct attribute_group eqep_device_attr_group = {
+ .attrs = (struct attribute **) eqep_attrs,
+};
+
+/* Driver compatibility list */
+static struct of_device_id eqep_of_match[] =
+{
+ { .compatible = "ti,am33xx-eqep" },
+ { }
+};
+
+/* Register our compatibilities for device trees */
+MODULE_DEVICE_TABLE(of, eqep_of_match);
+
+/* Create an instance of the eQEP driver */
+static int eqep_probe(struct platform_device *pdev)
+{
+ struct resource *r;
+ struct clk *clk;
+ struct eqep_chip *eqep;
+ struct pinctrl *pinctrl;
+
+ u64 period;
+ u16 status;
+ u32 value;
+
+ dev_info(&pdev->dev, "ver. 1.0\n");
+
+ /* Select pins provided through the device tree */
+ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+ if (IS_ERR(pinctrl))
+ {
+ dev_warn(&pdev->dev, "unable to select pin group\n");
+ }
+
+ /* Allocate a eqep_driver object */
+ eqep = devm_kzalloc(&pdev->dev, sizeof(struct eqep_chip), GFP_KERNEL);
+ if (!eqep) {
+ dev_err(&pdev->dev, "failed to allocate memory\n");
+ return -ENOMEM;
+ }
+
+ /* Get a handle to the system clock object */
+ clk = devm_clk_get(pdev->dev.parent, "fck");
+ if (IS_ERR(clk)) {
+ dev_err(&pdev->dev, "failed to get clock\n");
+ return PTR_ERR(clk);
+ }
+
+ /* Get the frequency of the system clock */
+ eqep->clk_rate = clk_get_rate(clk);
+ if (!eqep->clk_rate) {
+ dev_err(&pdev->dev, "failed to get clock rate\n");
+ return -EINVAL;
+ }
+
+ /* Get a resource containing the IRQ for this eQEP controller */
+ r = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (unlikely(!r)) {
+ dev_err(&pdev->dev, "Invalid IRQ resource\n");
+ return -ENODEV;
+ }
+
+ /* Store the irq */
+ eqep->irq = r->start;
+
+ /* Get a resource containing the requested (from DT) memory address and range of eQEP controller */
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!r) {
+ dev_err(&pdev->dev, "no memory resource defined\n");
+ return -ENODEV;
+ }
+
+ /* Remap the eQEP controller memory into our own memory space */
+ eqep->mmio_base = devm_ioremap_resource(&pdev->dev, r);
+ if (IS_ERR(eqep->mmio_base))
+ return PTR_ERR(eqep->mmio_base);
+
+ /* Store the platform device in our eQEP data structure for later usage */
+ eqep->pdev = pdev;
+
+ /* Subscribe to the eQEP interrupt */
+ if (request_irq(eqep->irq, eqep_irq_handler, IRQF_IRQPOLL, "eqep_interrupt", pdev))
+ {
+ dev_err(&pdev->dev, "unable to request irq for eQEP\n");
+ return -ENODEV;
+ }
+
+ /* Register controls to sysfs */
+ if (sysfs_create_group(&pdev->dev.kobj, &eqep_device_attr_group))
+ {
+ dev_err(&pdev->dev, "sysfs creation failed\n");
+ return -EINVAL;
+ }
+
+ /* set QDECCTL */
+ status = 0; /* default to Quadrature count mode, QSRC1 & QSRC0 = 0 */
+
+ /* set QSRC1 & QSRC0 bits, one of 4 count_modes. */
+ if (!of_property_read_u32(pdev->dev.of_node, "count_mode", &value) && value <= 3) {
+ status |= value << 14;
+
+ /*
+ * in count up or count down mode, count on rising edge only
+ * not on both edges.
+ */
+ if (value >= 2)
+ status |= XCR;
+ }
+ dev_info(&pdev->dev, "count_mode:%d\n", value);
+
+ /* Should we invert the qa input */
+ if (!of_property_read_u32(pdev->dev.of_node, "invert_qa", &value))
+ status = value ? status | QAP : status & ~QAP;
+ dev_info(&pdev->dev, "invert_qa:%d\n", value);
+
+ /* Should we invert the qb input */
+ if (!of_property_read_u32(pdev->dev.of_node, "invert_qb", &value))
+ status = value ? status | QBP : status & ~QBP;
+ dev_info(&pdev->dev, "invert_qb:%d\n", value);
+
+ /* Should we invert the index input */
+ if (!of_property_read_u32(pdev->dev.of_node, "invert_qi", &value))
+ status = value ? status | QIP : status & ~QIP;
+ dev_info(&pdev->dev, "invert_qi:%d\n", value);
+
+ /* Should we invert the strobe input */
+ if (!of_property_read_u32(pdev->dev.of_node, "invert_qs", &value))
+ status = value ? status | QSP : status & ~QSP;
+ dev_info(&pdev->dev, "invert_qs:%d\n", value);
+
+ /* Should we swap the cha and chb inputs */
+ if (!of_property_read_u32(pdev->dev.of_node, "swap_inputs", &value))
+ status = value ? status | SWAP : status & ~SWAP;
+ dev_info(&pdev->dev, "swap_inputs:%d\n", value);
+
+ dev_info(&pdev->dev, "QDECCTL:0x%04x\n", status);
+
+ /* Write the decoder control settings back to the control register */
+ writew(status, eqep->mmio_base + QDECCTL);
+
+ writel( 0, eqep->mmio_base + QPOSINIT);
+ writel(~0, eqep->mmio_base + QPOSMAX);
+ writel( 0, eqep->mmio_base + QPOSCNT);
+
+ dev_info(&pdev->dev, "QPOSINIT:0x%08x\n", readl(eqep->mmio_base + QPOSINIT));
+ dev_info(&pdev->dev, "QPOSMAX:0x%08x\n", readl(eqep->mmio_base + QPOSMAX));
+ dev_info(&pdev->dev, "QPOSCNT:0x%08x\n", readl(eqep->mmio_base + QPOSCNT));
+
+ status = UTOF; /* Enable Unit Time Period interrupt. */
+ if (!of_property_read_u32(pdev->dev.of_node, "omit_interrupt", &value) && value) {
+ status = 0; /* no interrupt */
+ }
+ writew(status, eqep->mmio_base + QEINT);
+ dev_info(&pdev->dev, "omit_interrupt:%d\n", value);
+ dev_info(&pdev->dev, "QEINT:0x%04x\n", status);
+
+ /* Calculate the timer ticks per second */
+ period = 1000000000;
+ period = period * eqep->clk_rate;
+ do_div(period, NSEC_PER_SEC);
+
+ /* Set this period into the unit timer period register */
+ writel(period, eqep->mmio_base + QUPRD);
+ dev_info(&pdev->dev, "QUPRD:0x%08x\n", (u32) period);
+
+ /*
+ * Enable the eQEP with basic position counting turned on
+ * PHEN - Quadrature position counter enable bit
+ * UTE - unit timer enable
+ * QCLM - latch QPOSLAT to QPOSCNT upon unit timer overflow
+ * IEL0 - Latch QPOSILAT on index signal. Rising or falling, IEL[1:0] = 0 is reserved
+ * SWI - Software initialization of position count register, i.e. set QPOSCNT <= QPOSINIT,
+ * but this bit was not being reset by hardware as advertised in TRM,
+ * (so omit & clear QPOSCNT manually elsewhere?)
+ */
+ status = PHEN | UTE | QCLM | IEL0 | SWI;
+ writew(status, eqep->mmio_base + QEPCTL);
+ dev_info(&pdev->dev, "QEPCTL:0x%04x write\n", status);
+ dev_info(&pdev->dev, "QEPCTL:0x%04x read\n", readw(eqep->mmio_base + QEPCTL));
+
+ /* We default to absolute mode */
+ eqep->op_mode = TIEQEP_MODE_ABSOLUTE;
+
+ /* Enable the power management runtime */
+ pm_runtime_enable(&pdev->dev);
+
+ /* Increment the device usage count and run pm_runtime_resume() */
+ pm_runtime_get_sync(&pdev->dev);
+
+ /* Initialize the notify work struture */
+ INIT_WORK(&eqep->notify_work, notify_handler);
+
+ /* Decrement the device usage count (twice) and run pm_runtime_idle() if zero */
+ pm_runtime_put_sync(&pdev->dev);
+
+ /* Set the platform driver data to the data object we've been creating for the eQEP unit */
+ platform_set_drvdata(pdev, eqep);
+
+ /* Success! */
+ dev_info(&pdev->dev, "irq:%d, clk_rate:%u\n", eqep->irq, eqep->clk_rate);
+ return 0;
+}
+
+/* Remove an instance of the eQEP driver */
+static int eqep_remove(struct platform_device *pdev)
+{
+ /* Get the eQEP driver data from the platform device structure */
+ struct eqep_chip *eqep = platform_get_drvdata(pdev);
+
+ /* Cancel work */
+ cancel_work_sync(&eqep->notify_work);
+
+ /* Unmap from sysfs */
+ sysfs_remove_group(&pdev->dev.kobj, &eqep_device_attr_group);
+
+ /* Release important assets */
+ free_irq(eqep->irq, pdev);
+
+ /* Increment the device usage count and run pm_runtime_resume() */
+ pm_runtime_get_sync(&pdev->dev);
+
+ /* Decrement the device usage count (twice) and run pm_runtime_idle() if zero */
+ pm_runtime_put_sync(&pdev->dev);
+ pm_runtime_put_sync(&pdev->dev);
+
+ /* Disable the runtime power management of this device */
+ pm_runtime_disable(&pdev->dev);
+
+ /* Return success */
+ return 0;
+}
+
+/* Power management suspend device */
+static int eqep_suspend(struct device *dev)
+{
+ /* Get the eqep driver information */
+ struct eqep_chip *eqep = dev_get_drvdata(dev);
+ u16 tmp;
+
+ /* Shut down interrupts */
+ eqep->prior_qeint = readw(eqep->mmio_base + QEINT);
+ tmp = eqep->prior_qeint & ~UTOF;
+ writew(tmp, eqep->mmio_base + QEINT);
+
+ /* Get the existing state of QEPCTL */
+ eqep->prior_qepctl = readw(eqep->mmio_base + QEPCTL);
+
+ /* Disable eQEP controller */
+ writew(eqep->prior_qepctl & ~PHEN, eqep->mmio_base + QEPCTL);
+
+ /* Decrement the device usage count and run pm_runtime_idle() if zero */
+ pm_runtime_put_sync(dev);
+
+ /* Return success */
+ return 0;
+}
+
+/* Power management wake device back up */
+static int eqep_resume(struct device *dev)
+{
+ /* Get the eqep driver information */
+ struct eqep_chip *eqep = dev_get_drvdata(dev);
+
+ /* Restore interrupt enabled register */
+ writew(eqep->prior_qeint, eqep->mmio_base + QEINT);
+
+ /* Restore prior qep control register */
+ writew(eqep->prior_qepctl, eqep->mmio_base + QEPCTL);
+
+ /* Increment the device usage count and run pm_runtime_resume() */
+ pm_runtime_get_sync(dev);
+
+ /* Success */
+ return 0;
+}
+
+/* create pm functions object */
+static SIMPLE_DEV_PM_OPS(eqep_pm_ops, eqep_suspend, eqep_resume);
+
+/* Platform driver information */
+static struct platform_driver eqep_driver = {
+ .driver = {
+ .name = "eqep",
+ .owner = THIS_MODULE,
+ .pm = &eqep_pm_ops,
+ .of_match_table = eqep_of_match,
+ },
+ .probe = eqep_probe,
+ .remove = eqep_remove,
+};
+
+/* Register this platform driver */
+module_platform_driver(eqep_driver);
+
+/* Module information */
+MODULE_DESCRIPTION("TI eQEP driver");
+MODULE_AUTHOR("Nathaniel R. Lewis");
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/tsl2550.c b/drivers/misc/tsl2550.c
index 87a1337..eb57610 100644
--- a/drivers/misc/tsl2550.c
+++ b/drivers/misc/tsl2550.c
@@ -177,7 +177,7 @@ static int tsl2550_calculate_lux(u8 ch0, u8 ch1)
} else
lux = 0;
else
- return -EAGAIN;
+ return 0;
/* LUX range check */
return lux > TSL2550_MAX_LUX ? TSL2550_MAX_LUX : lux;
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 709a872..288cb38 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -36,6 +36,7 @@
#include <linux/compat.h>
#include <linux/pm_runtime.h>
#include <linux/idr.h>
+#include <linux/of.h>
#include <linux/mmc/ioctl.h>
#include <linux/mmc/card.h>
@@ -2219,13 +2220,20 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
{
struct mmc_blk_data *md;
int devidx, ret;
+ int mindynidx = max(0, of_alias_get_highest_id("mmc") + 1);
+ int reqidx = card->host->index;
again:
if (!ida_pre_get(&mmc_blk_ida, GFP_KERNEL))
return ERR_PTR(-ENOMEM);
spin_lock(&mmc_blk_lock);
- ret = ida_get_new(&mmc_blk_ida, &devidx);
+ ret = ida_get_new_above(&mmc_blk_ida, reqidx, &devidx);
+ if (!ret && devidx < mindynidx && devidx != reqidx) {
+ // requested index in use, fall back to dynamic
+ ida_remove(&mmc_blk_ida, devidx);
+ ret = ida_get_new_above(&mmc_blk_ida, mindynidx, &devidx);
+ }
spin_unlock(&mmc_blk_lock);
if (ret == -EAGAIN)
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
index 98f25ff..9c211c5 100644
--- a/drivers/mmc/core/host.c
+++ b/drivers/mmc/core/host.c
@@ -346,6 +346,8 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
{
int err;
struct mmc_host *host;
+ int mindynidx = max(0, of_alias_get_highest_id("mmc") + 1);
+ int reqidx = dev->of_node ? of_alias_get_id(dev->of_node, "mmc") : -1;
host = kzalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
if (!host)
@@ -361,7 +363,16 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
}
spin_lock(&mmc_host_lock);
- err = ida_get_new(&mmc_host_ida, &host->index);
+ if (reqidx >= 0) {
+ err = ida_get_new_above(&mmc_host_ida, reqidx, &host->index);
+ if (!err && host->index != reqidx) {
+ // requested index in use, fall back to dynamic
+ ida_remove(&mmc_host_ida, host->index);
+ reqidx = -1;
+ }
+ }
+ if (reqidx < 0)
+ err = ida_get_new_above(&mmc_host_ida, mindynidx, &host->index);
spin_unlock(&mmc_host_lock);
if (err == -EAGAIN) {
diff --git a/drivers/net/ethernet/allwinner/Kconfig b/drivers/net/ethernet/allwinner/Kconfig
index 47da7e7..060569c 100644
--- a/drivers/net/ethernet/allwinner/Kconfig
+++ b/drivers/net/ethernet/allwinner/Kconfig
@@ -33,4 +33,17 @@ config SUN4I_EMAC
To compile this driver as a module, choose M here. The module
will be called sun4i-emac.
+config SUN8I_EMAC
+ tristate "Allwinner sun8i EMAC support"
+ depends on ARCH_SUNXI || COMPILE_TEST
+ depends on OF
+ select MII
+ select PHYLIB
+ ---help---
+ This driver support the sun8i EMAC ethernet driver present on
+ H3/A83T/A64 Allwinner SoCs.
+
+ To compile this driver as a module, choose M here. The module
+ will be called sun8i-emac.
+
endif # NET_VENDOR_ALLWINNER
diff --git a/drivers/net/ethernet/allwinner/Makefile b/drivers/net/ethernet/allwinner/Makefile
index 03129f7..8bd1693 100644
--- a/drivers/net/ethernet/allwinner/Makefile
+++ b/drivers/net/ethernet/allwinner/Makefile
@@ -3,3 +3,4 @@
#
obj-$(CONFIG_SUN4I_EMAC) += sun4i-emac.o
+obj-$(CONFIG_SUN8I_EMAC) += sun8i-emac.o
diff --git b/drivers/net/ethernet/allwinner/sun8i-emac.c b/drivers/net/ethernet/allwinner/sun8i-emac.c
new file mode 100644
index 0000000..fc0c1dd
--- /dev/null
+++ b/drivers/net/ethernet/allwinner/sun8i-emac.c
@@ -0,0 +1,2129 @@
+/*
+ * sun8i-emac driver
+ *
+ * Copyright (C) 2015-2016 Corentin LABBE <clabbe.montjoie@gmail.com>
+ *
+ * This is the driver for Allwinner Ethernet MAC found in H3/A83T/A64 SoC
+ *
+ * TODO:
+ * - MAC filtering
+ * - Jumbo frame
+ * - features rx-all (NETIF_F_RXALL_BIT)
+ */
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/etherdevice.h>
+#include <linux/interrupt.h>
+#include <linux/iopoll.h>
+#include <linux/mii.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/of_device.h>
+#include <linux/of_mdio.h>
+#include <linux/of_net.h>
+#include <linux/phy.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+#include <linux/scatterlist.h>
+#include <linux/skbuff.h>
+
+#define SUN8I_EMAC_BASIC_CTL0 0x00
+#define SUN8I_EMAC_BASIC_CTL1 0x04
+#define SUN8I_EMAC_INT_STA 0x08
+#define SUN8I_EMAC_INT_EN 0x0C
+#define SUN8I_EMAC_TX_CTL0 0x10
+#define SUN8I_EMAC_TX_CTL1 0x14
+#define SUN8I_EMAC_TX_FLOW_CTL 0x1C
+#define SUN8I_EMAC_RX_CTL0 0x24
+#define SUN8I_EMAC_RX_CTL1 0x28
+#define SUN8I_EMAC_RX_FRM_FLT 0x38
+#define SUN8I_EMAC_MDIO_CMD 0x48
+#define SUN8I_EMAC_MDIO_DATA 0x4C
+#define SUN8I_EMAC_TX_DMA_STA 0xB0
+#define SUN8I_EMAC_TX_CUR_DESC 0xB4
+#define SUN8I_EMAC_TX_CUR_BUF 0xB8
+#define SUN8I_EMAC_RX_DMA_STA 0xC0
+
+#define MDIO_CMD_MII_BUSY BIT(0)
+#define MDIO_CMD_MII_WRITE BIT(1)
+#define MDIO_CMD_MII_PHY_REG_ADDR_MASK GENMASK(8, 4)
+#define MDIO_CMD_MII_PHY_REG_ADDR_SHIFT 4
+#define MDIO_CMD_MII_PHY_ADDR_MASK GENMASK(16, 12)
+#define MDIO_CMD_MII_PHY_ADDR_SHIFT 12
+
+#define SUN8I_EMAC_MACADDR_HI 0x50
+#define SUN8I_EMAC_MACADDR_LO 0x54
+
+#define SUN8I_EMAC_RX_DESC_LIST 0x34
+#define SUN8I_EMAC_TX_DESC_LIST 0x20
+
+#define SUN8I_EMAC_RX_DO_CRC BIT(27)
+#define SUN8I_EMAC_RX_STRIP_FCS BIT(28)
+
+#define SUN8I_COULD_BE_USED_BY_DMA BIT(31)
+
+/* Used in RX_CTL1*/
+#define RX_DMA_EN BIT(30)
+#define RX_DMA_START BIT(31)
+/* Used in TX_CTL1*/
+#define TX_DMA_EN BIT(30)
+#define TX_DMA_START BIT(31)
+
+/* Used in RX_CTL0 */
+#define RX_RECEIVER_EN BIT(31)
+/* Used in TX_CTL0 */
+#define TX_TRANSMITTER_EN BIT(31)
+
+/* Basic CTL0 */
+#define BCTL0_FD BIT(0)
+#define BCTL0_SPEED_10 2
+#define BCTL0_SPEED_100 3
+#define BCTL0_SPEED_MASK GENMASK(3, 2)
+#define BCTL0_SPEED_SHIFT 2
+
+#define FLOW_RX 1
+#define FLOW_TX 2
+
+#define RX_INT BIT(8)
+#define TX_INT BIT(0)
+
+/* Bits used in frame RX status */
+#define DSC_RX_FIRST BIT(9)
+#define DSC_RX_LAST BIT(8)
+
+/* Bits used in frame TX ctl */
+#define SUN8I_EMAC_MAGIC_TX_BIT BIT(24)
+#define SUN8I_EMAC_TX_DO_CRC (BIT(27) | BIT(28))
+#define DSC_TX_FIRST BIT(29)
+#define DSC_TX_LAST BIT(30)
+#define SUN8I_EMAC_WANT_INT BIT(31)
+
+enum emac_variant {
+ NONE_EMAC,/* for be sure that variant is non-0 if set */
+ A83T_EMAC,
+ H3_EMAC,
+ A64_EMAC,
+};
+
+static const char const estats_str[][ETH_GSTRING_LEN] = {
+ /* errors */
+ "rx_payload_error",
+ "rx_CRC_error",
+ "rx_phy_error",
+ "rx_length_error",
+ "rx_col_error",
+ "rx_header_error",
+ "rx_overflow_error",
+ "rx_saf_error",
+ "rx_daf_error",
+ "rx_buf_error",
+ /* misc infos */
+ "tx_stop_queue",
+ "rx_dma_ua",
+ "rx_dma_stop",
+ "tx_dma_ua",
+ "tx_dma_stop",
+ "rx_hw_csum",
+ "tx_hw_csum",
+ /* interrupts */
+ "rx_int",
+ "tx_int",
+ "rx_early_int",
+ "tx_early_int",
+ "tx_underflow_int",
+ /* debug */
+ "tx_used_desc",
+ "napi_schedule",
+ "napi_underflow",
+};
+
+struct sun8i_emac_stats {
+ u64 rx_payload_error;
+ u64 rx_crc_error;
+ u64 rx_phy_error;
+ u64 rx_length_error;
+ u64 rx_col_error;
+ u64 rx_header_error;
+ u64 rx_overflow_error;
+ u64 rx_saf_fail;
+ u64 rx_daf_fail;
+ u64 rx_buf_error;
+
+ u64 tx_stop_queue;
+ u64 rx_dma_ua;
+ u64 rx_dma_stop;
+ u64 tx_dma_ua;
+ u64 tx_dma_stop;
+ u64 rx_hw_csum;
+ u64 tx_hw_csum;
+
+ u64 rx_int;
+ u64 tx_int;
+ u64 rx_early_int;
+ u64 tx_early_int;
+ u64 tx_underflow_int;
+
+ u64 tx_used_desc;
+ u64 napi_schedule;
+ u64 napi_underflow;
+};
+
+/* The datasheet said that each descriptor can transfers up to 4096bytes
+ * But latter, a register documentation reduce that value to 2048
+ * Anyway using 2048 cause strange behaviours and even BSP driver use 2047
+ */
+#define DESC_BUF_MAX 2044
+#if (DESC_BUF_MAX < (ETH_FRAME_LEN + 4))
+#error "DESC_BUF_MAX must be set at minimum to ETH_FRAME_LEN + 4"
+#endif
+
+/* MAGIC value for knowing if a descriptor is available or not */
+#define DCLEAN (BIT(16) | BIT(14) | BIT(12) | BIT(10) | BIT(9))
+
+/* struct dma_desc - Structure of DMA descriptor used by the hardware
+ * @status: Status of the frame written by HW, so RO for the
+ * driver (except for BIT(31) which is R/W)
+ * @ctl: Information on the frame written by the driver (INT, len,...)
+ * @buf_addr: physical address of the frame data
+ * @next: physical address of next dma_desc
+ */
+struct dma_desc {
+ u32 status;
+ u32 ctl;
+ u32 buf_addr;
+ u32 next;
+};
+
+/* Describe how data from skb are DMA mapped (used in txinfo map member) */
+#define MAP_SINGLE 1
+#define MAP_PAGE 2
+
+/* Structure for storing information about data in TX ring buffer */
+struct txinfo {
+ struct sk_buff *skb;
+ int map;
+};
+
+struct sun8i_emac_priv {
+ void __iomem *base;
+ void __iomem *syscon;
+ int irq;
+ struct device *dev;
+ struct net_device *ndev;
+ struct mii_bus *mdio;
+ struct napi_struct napi;
+ spinlock_t tx_lock;/* control the access of transmit descriptors */
+ int duplex;
+ int speed;
+ int link;
+ int phy_interface;
+ enum emac_variant variant;
+ struct device_node *phy_node;
+ struct clk *ahb_clk;
+ struct clk *ephy_clk;
+ bool use_internal_phy;
+
+ struct reset_control *rst;
+ struct reset_control *rst_ephy;
+
+ struct dma_desc *dd_rx;
+ dma_addr_t dd_rx_phy;
+ struct dma_desc *dd_tx;
+ dma_addr_t dd_tx_phy;
+ struct sk_buff **rx_skb;
+ struct txinfo *txl;
+
+ int nbdesc_tx;
+ int nbdesc_rx;
+ int tx_slot;
+ int tx_dirty;
+ int rx_dirty;
+ struct sun8i_emac_stats estats;
+ u32 msg_enable;
+ int flow_ctrl;
+ int pause;
+};
+
+static irqreturn_t sun8i_emac_dma_interrupt(int irq, void *dev_id);
+
+static void rb_inc(int *p, const int max)
+{
+ (*p)++;
+ (*p) %= max;
+}
+
+/* Return the number of contiguous free descriptors
+ * starting from tx_slot
+ */
+static int rb_tx_numfreedesc(struct net_device *ndev)
+{
+ struct sun8i_emac_priv *priv = netdev_priv(ndev);
+
+ if (priv->tx_slot < priv->tx_dirty)
+ return priv->tx_dirty - priv->tx_slot;
+
+ return (priv->nbdesc_tx - priv->tx_slot) + priv->tx_dirty;
+}
+
+/* Allocate a skb in a DMA descriptor
+ *
+ * @i index of slot to fill
+*/
+static int sun8i_emac_rx_skb(struct net_device *ndev, int i)
+{
+ struct sun8i_emac_priv *priv = netdev_priv(ndev);
+ struct dma_desc *ddesc;
+ struct sk_buff *skb;
+
+ ddesc = priv->dd_rx + i;
+
+ ddesc->ctl = 0;
+
+ skb = netdev_alloc_skb_ip_align(ndev, DESC_BUF_MAX);
+ if (!skb)
+ return -ENOMEM;
+
+ /* should not happen */
+ if (unlikely(priv->rx_skb[i]))
+ dev_warn(priv->dev, "BUG: Leaking a skbuff\n");
+
+ priv->rx_skb[i] = skb;
+
+ ddesc->buf_addr = dma_map_single(priv->dev, skb->data,
+ DESC_BUF_MAX, DMA_FROM_DEVICE);
+ if (dma_mapping_error(priv->dev, ddesc->buf_addr)) {
+ dev_err(priv->dev, "ERROR: Cannot map RX buffer for DMA\n");
+ dev_kfree_skb(skb);
+ return -EFAULT;
+ }
+ ddesc->ctl |= DESC_BUF_MAX;
+ wmb();/* SUN8I_COULD_BE_USED_BY_DMA must be the last value written */
+ ddesc->status = SUN8I_COULD_BE_USED_BY_DMA;
+
+ return 0;
+}
+
+static void sun8i_emac_stop_tx(struct net_device *ndev)
+{
+ struct sun8i_emac_priv *priv = netdev_priv(ndev);
+ u32 v;
+
+ netif_stop_queue(ndev);
+
+ v = readl(priv->base + SUN8I_EMAC_TX_CTL0);
+ v &= ~TX_TRANSMITTER_EN;/*Disable transmitter after current reception*/
+ writel(v, priv->base + SUN8I_EMAC_TX_CTL0);
+ v = readl(priv->base + SUN8I_EMAC_TX_CTL1);
+ v &= ~TX_DMA_EN; /* Stop TX DMA */
+ writel(v, priv->base + SUN8I_EMAC_TX_CTL1);
+}
+
+static void sun8i_emac_stop_rx(struct net_device *ndev)
+{
+ struct sun8i_emac_priv *priv = netdev_priv(ndev);
+ u32 v;
+
+ v = readl(priv->base + SUN8I_EMAC_RX_CTL0);
+ v &= ~RX_RECEIVER_EN; /* Disable receiver after current reception */
+ writel(v, priv->base + SUN8I_EMAC_RX_CTL0);
+ v = readl(priv->base + SUN8I_EMAC_RX_CTL1);
+ v &= ~RX_DMA_EN; /* Stop RX DMA */
+ writel(v, priv->base + SUN8I_EMAC_RX_CTL1);
+}
+
+static void sun8i_emac_start_rx(struct net_device *ndev)
+{
+ struct sun8i_emac_priv *priv = netdev_priv(ndev);
+ u32 v;
+
+ v = readl(priv->base + SUN8I_EMAC_RX_CTL0);
+ v |= RX_RECEIVER_EN;/* Enable receiver */
+ writel(v, priv->base + SUN8I_EMAC_RX_CTL0);
+
+ v = readl(priv->base + SUN8I_EMAC_RX_CTL1);
+ v |= RX_DMA_START;
+ v |= RX_DMA_EN;
+ writel(v, priv->base + SUN8I_EMAC_RX_CTL1);
+}
+
+static void sun8i_emac_start_tx(struct net_device *ndev)
+{
+ struct sun8i_emac_priv *priv = netdev_priv(ndev);
+ u32 v;
+
+ v = readl(priv->base + SUN8I_EMAC_TX_CTL0);
+ v |= TX_TRANSMITTER_EN;
+ writel(v, priv->base + SUN8I_EMAC_TX_CTL0);
+
+ v = readl(priv->base + SUN8I_EMAC_TX_CTL1);
+ v |= TX_DMA_START;
+ v |= TX_DMA_EN;
+ writel(v, priv->base + SUN8I_EMAC_TX_CTL1);
+}
+
+/* Set MAC address for slot index
+ * @addr: the MAC address to set
+ * @index: The index of slot where to set address.
+ * The slot 0 is the main MACaddr
+ */
+static void sun8i_emac_set_macaddr(struct sun8i_emac_priv *priv,
+ const u8 *addr, int index)
+{
+ u32 v;
+
+ dev_info(priv->dev, "device MAC address slot %d %02x:%02x:%02x:%02x:%02x:%02x\n",
+ index, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
+
+ v = (addr[5] << 8) | addr[4];
+ writel(v, priv->base + SUN8I_EMAC_MACADDR_HI + index * 8);
+ v = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0];
+ writel(v, priv->base + SUN8I_EMAC_MACADDR_LO + index * 8);
+}
+
+static void sun8i_emac_set_link_mode(struct sun8i_emac_priv *priv)
+{
+ u32 v;
+
+ v = readl(priv->base + SUN8I_EMAC_BASIC_CTL0);
+
+ if (priv->duplex)
+ v |= BCTL0_FD;
+ else
+ v &= ~BCTL0_FD;
+
+ v &= ~BCTL0_SPEED_MASK;
+ switch (priv->speed) {
+ case 1000:
+ break;
+ case 100:
+ v |= BCTL0_SPEED_100 << BCTL0_SPEED_SHIFT;
+ break;
+ case 10:
+ v |= BCTL0_SPEED_10 << BCTL0_SPEED_SHIFT;
+ break;
+ }
+
+ writel(v, priv->base + SUN8I_EMAC_BASIC_CTL0);
+}
+
+static void sun8i_emac_flow_ctrl(struct sun8i_emac_priv *priv, int duplex,
+ int fc)
+{
+ u32 flow = 0;
+
+ netif_dbg(priv, link, priv->ndev, "%s %d %d\n", __func__,
+ duplex, fc);
+
+ flow = readl(priv->base + SUN8I_EMAC_RX_CTL0);
+ if (fc & FLOW_RX)
+ flow |= BIT(16);
+ else
+ flow &= ~BIT(16);
+ writel(flow, priv->base + SUN8I_EMAC_RX_CTL0);
+
+ flow = readl(priv->base + SUN8I_EMAC_TX_FLOW_CTL);
+ if (fc & FLOW_TX)
+ flow |= BIT(0);
+ else
+ flow &= ~BIT(0);
+ writel(flow, priv->base + SUN8I_EMAC_TX_FLOW_CTL);
+}
+
+/* Grab a frame into a skb from descriptor number i */
+static int sun8i_emac_rx_from_ddesc(struct net_device *ndev, int i)
+{
+ struct sk_buff *skb;
+ struct sun8i_emac_priv *priv = netdev_priv(ndev);
+ struct dma_desc *ddesc = priv->dd_rx + i;
+ int frame_len;
+ int rxcsum_done = 0;
+
+ if (ndev->features & NETIF_F_RXCSUM)
+ rxcsum_done = 1;
+
+ /* bit0/bit7 work only on IPv4/IPv6 TCP traffic,
+ * (not on ARP for example) so we dont raise rx_errors/discard frame
+ */
+ /* the checksum or length of received frame's payload is wrong*/
+ if (ddesc->status & BIT(0)) {
+ priv->estats.rx_payload_error++;
+ rxcsum_done = 0;
+ }
+ /* RX_CRC_ERR */
+ if (ddesc->status & BIT(1)) {
+ priv->ndev->stats.rx_errors++;
+ priv->ndev->stats.rx_crc_errors++;
+ priv->estats.rx_crc_error++;
+ goto discard_frame;
+ }
+ /* RX_PHY_ERR */
+ if ((ddesc->status & BIT(3))) {
+ priv->ndev->stats.rx_errors++;
+ priv->estats.rx_phy_error++;
+ goto discard_frame;
+ }
+ /* RX_LENGTH_ERR */
+ if ((ddesc->status & BIT(4))) {
+ priv->ndev->stats.rx_errors++;
+ priv->ndev->stats.rx_length_errors++;
+ priv->estats.rx_length_error++;
+ goto discard_frame;
+ }
+ /* RX_COL_ERR */
+ if ((ddesc->status & BIT(6))) {
+ priv->ndev->stats.rx_errors++;
+ priv->estats.rx_col_error++;
+ goto discard_frame;
+ }
+ /* RX_HEADER_ERR */
+ if ((ddesc->status & BIT(7))) {
+ priv->estats.rx_header_error++;
+ rxcsum_done = 0;
+ }
+ /* RX_OVERFLOW_ERR */
+ if ((ddesc->status & BIT(11))) {
+ priv->ndev->stats.rx_over_errors++;
+ priv->estats.rx_overflow_error++;
+ goto discard_frame;
+ }
+ /* RX_NO_ENOUGTH_BUF_ERR */
+ if ((ddesc->status & BIT(14))) {
+ priv->ndev->stats.rx_errors++;
+ priv->estats.rx_buf_error++;
+ goto discard_frame;
+ }
+
+ /* BIT(9) is for the first frame, not having it is bad since we do not
+ * handle Jumbo frame
+ */
+ if ((ddesc->status & DSC_RX_FIRST) == 0) {
+ dev_warn_ratelimited(priv->dev, "BUG: Non-first frame received. This should not happen\n");
+ goto discard_frame;
+ }
+ frame_len = (ddesc->status >> 16) & 0x3FFF;
+ if (!(ndev->features & NETIF_F_RXFCS))
+ frame_len -= ETH_FCS_LEN;
+
+ skb = priv->rx_skb[i];
+
+ netif_dbg(priv, rx_status, priv->ndev,
+ "%s from %02d %pad len=%d status=%x st=%x\n",
+ __func__, i, &ddesc, frame_len, ddesc->status, ddesc->ctl);
+
+ skb_put(skb, frame_len);
+
+ dma_unmap_single(priv->dev, ddesc->buf_addr, DESC_BUF_MAX,
+ DMA_FROM_DEVICE);
+ skb->protocol = eth_type_trans(skb, priv->ndev);
+ if (rxcsum_done) {
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ priv->estats.rx_hw_csum++;
+ } else {
+ skb->ip_summed = CHECKSUM_PARTIAL;
+ }
+
+ priv->ndev->stats.rx_packets++;
+ priv->ndev->stats.rx_bytes += frame_len;
+ priv->rx_skb[i] = NULL;
+
+ /* this frame is not the last */
+ if ((ddesc->status & DSC_RX_LAST) == 0) {
+ dev_warn(priv->dev, "Multi frame not implemented currlen=%d\n",
+ frame_len);
+ }
+
+ sun8i_emac_rx_skb(ndev, i);
+ napi_gro_receive(&priv->napi, skb);
+
+ return 0;
+ /* If the frame need to be dropped, we simply reuse the buffer */
+discard_frame:
+ ddesc->ctl = DESC_BUF_MAX;
+ wmb();/* SUN8I_COULD_BE_USED_BY_DMA must be the last value written */
+ ddesc->status = SUN8I_COULD_BE_USED_BY_DMA;
+ return 0;
+}
+
+/* iterate over dma_desc for finding completed xmit.
+ * Called from interrupt context, so no need to spinlock tx
+ *
+ * The problem is: how to know that a descriptor is sent and not just in
+ * preparation.
+ * Need to have status=0 and st set but this is the state of first frame just
+ * before setting the own-by-DMA bit.
+ * The solution is to used the artificial value DCLEAN.
+ */
+static int sun8i_emac_complete_xmit(struct net_device *ndev, int budget)
+{
+ struct sun8i_emac_priv *priv = netdev_priv(ndev);
+ struct dma_desc *ddesc;
+ int frame_len;
+ int work = 0;
+
+ spin_lock(&priv->tx_lock);
+ do {
+ ddesc = priv->dd_tx + priv->tx_dirty;
+
+ if (ddesc->status & SUN8I_COULD_BE_USED_BY_DMA)
+ goto xmit_end;
+
+ if (ddesc->status == DCLEAN)
+ goto xmit_end;
+
+ if (ddesc->status == 0 && !ddesc->ctl) {
+ dev_err(priv->dev, "BUG: reached the void %d %d\n",
+ priv->tx_dirty, priv->tx_slot);
+ goto xmit_end;
+ }
+
+ /* TX_UNDERFLOW_ERR */
+ if (ddesc->status & BIT(1))
+ priv->ndev->stats.tx_errors++;
+ /* TX_DEFER_ERR */
+ if (ddesc->status & BIT(2))
+ priv->ndev->stats.tx_errors++;
+ /* BIT 6:3 numbers of collisions */
+ if (ddesc->status & 0x78)
+ priv->ndev->stats.collisions +=
+ (ddesc->status & 0x78) >> 3;
+ /* TX_COL_ERR_1 */
+ if (ddesc->status & BIT(8))
+ priv->ndev->stats.tx_errors++;
+ /* TX_COL_ERR_0 */
+ if (ddesc->status & BIT(9))
+ priv->ndev->stats.tx_errors++;
+ /* TX_CRS_ERR */
+ if (ddesc->status & BIT(10))
+ priv->ndev->stats.tx_carrier_errors++;
+ /* TX_PAYLOAD_ERR */
+ if (ddesc->status & BIT(12))
+ priv->ndev->stats.tx_errors++;
+ /* TX_LENGTH_ERR */
+ if (ddesc->status & BIT(14))
+ priv->ndev->stats.tx_errors++;
+ /* TX_HEADER_ERR */
+ if (ddesc->status & BIT(16))
+ priv->ndev->stats.tx_errors++;
+ frame_len = ddesc->ctl & 0x3FFF;
+ if (priv->txl[priv->tx_dirty].map == MAP_SINGLE)
+ dma_unmap_single(priv->dev, ddesc->buf_addr,
+ frame_len, DMA_TO_DEVICE);
+ else
+ dma_unmap_page(priv->dev, ddesc->buf_addr,
+ frame_len, DMA_TO_DEVICE);
+ /* we can free skb only on last frame */
+ if (priv->txl[priv->tx_dirty].skb && (ddesc->ctl & DSC_TX_LAST))
+ dev_kfree_skb_irq(priv->txl[priv->tx_dirty].skb);
+
+ priv->txl[priv->tx_dirty].skb = NULL;
+ priv->txl[priv->tx_dirty].map = 0;
+ ddesc->ctl = 0;
+ wmb(); /* setting to DCLEAN is the last value to be set */
+ ddesc->status = DCLEAN;
+ work++;
+
+ rb_inc(&priv->tx_dirty, priv->nbdesc_tx);
+ ddesc = priv->dd_tx + priv->tx_dirty;
+ } while (ddesc->ctl && !(ddesc->status & SUN8I_COULD_BE_USED_BY_DMA));
+
+ if (netif_queue_stopped(ndev) &&
+ rb_tx_numfreedesc(ndev) > MAX_SKB_FRAGS + 1)
+ netif_wake_queue(ndev);
+xmit_end:
+ spin_unlock(&priv->tx_lock);
+ return work;
+}
+
+static int sun8i_emac_poll(struct napi_struct *napi, int budget)
+{
+ struct sun8i_emac_priv *priv =
+ container_of(napi, struct sun8i_emac_priv, napi);
+ struct net_device *ndev = priv->ndev;
+ int worked;
+ struct dma_desc *ddesc;
+
+ priv->estats.napi_schedule++;
+ worked = sun8i_emac_complete_xmit(ndev, budget);
+
+ ddesc = priv->dd_rx + priv->rx_dirty;
+ while (!(ddesc->status & SUN8I_COULD_BE_USED_BY_DMA) &&
+ worked < budget) {
+ sun8i_emac_rx_from_ddesc(ndev, priv->rx_dirty);
+ worked++;
+ rb_inc(&priv->rx_dirty, priv->nbdesc_rx);
+ ddesc = priv->dd_rx + priv->rx_dirty;
+ };
+ if (worked < budget) {
+ priv->estats.napi_underflow++;
+ napi_complete(&priv->napi);
+ writel(RX_INT | TX_INT, priv->base + SUN8I_EMAC_INT_EN);
+ }
+ return worked;
+}
+
+static int sun8i_mdio_read(struct mii_bus *bus, int phy_addr, int phy_reg)
+{
+ struct net_device *ndev = bus->priv;
+ struct sun8i_emac_priv *priv = netdev_priv(ndev);
+ int err;
+ u32 reg;
+
+ err = readl_poll_timeout(priv->base + SUN8I_EMAC_MDIO_CMD, reg,
+ !(reg & MDIO_CMD_MII_BUSY), 100, 10000);
+ if (err) {
+ dev_err(priv->dev, "%s timeout %x\n", __func__, reg);
+ return err;
+ }
+
+ reg &= ~MDIO_CMD_MII_WRITE;
+ reg &= ~MDIO_CMD_MII_PHY_REG_ADDR_MASK;
+ reg |= (phy_reg << MDIO_CMD_MII_PHY_REG_ADDR_SHIFT) &
+ MDIO_CMD_MII_PHY_REG_ADDR_MASK;
+
+ reg &= ~MDIO_CMD_MII_PHY_ADDR_MASK;
+
+ reg |= (phy_addr << MDIO_CMD_MII_PHY_ADDR_SHIFT) &
+ MDIO_CMD_MII_PHY_ADDR_MASK;
+
+ reg |= MDIO_CMD_MII_BUSY;
+
+ writel(reg, priv->base + SUN8I_EMAC_MDIO_CMD);
+
+ err = readl_poll_timeout(priv->base + SUN8I_EMAC_MDIO_CMD, reg,
+ !(reg & MDIO_CMD_MII_BUSY), 100, 10000);
+
+ if (err) {
+ dev_err(priv->dev, "%s timeout %x\n", __func__, reg);
+ return err;
+ }
+
+ return readl(priv->base + SUN8I_EMAC_MDIO_DATA);
+}
+
+static int sun8i_mdio_write(struct mii_bus *bus, int phy_addr, int phy_reg,
+ u16 data)
+{
+ struct net_device *ndev = bus->priv;
+ struct sun8i_emac_priv *priv = netdev_priv(ndev);
+ u32 reg;
+ int err;
+
+ err = readl_poll_timeout(priv->base + SUN8I_EMAC_MDIO_CMD, reg,
+ !(reg & MDIO_CMD_MII_BUSY), 100, 10000);
+ if (err) {
+ dev_err(priv->dev, "%s timeout %x\n", __func__, reg);
+ return err;
+ }
+
+ reg &= ~MDIO_CMD_MII_PHY_REG_ADDR_MASK;
+ reg |= (phy_reg << MDIO_CMD_MII_PHY_REG_ADDR_SHIFT) &
+ MDIO_CMD_MII_PHY_REG_ADDR_MASK;
+
+ reg &= ~MDIO_CMD_MII_PHY_ADDR_MASK;
+ reg |= (phy_addr << MDIO_CMD_MII_PHY_ADDR_SHIFT) &
+ MDIO_CMD_MII_PHY_ADDR_MASK;
+
+ reg |= MDIO_CMD_MII_WRITE;
+ reg |= MDIO_CMD_MII_BUSY;
+
+ writel(reg, priv->base + SUN8I_EMAC_MDIO_CMD);
+ writel(data, priv->base + SUN8I_EMAC_MDIO_DATA);
+ dev_dbg(priv->dev, "%s %d %d %x %x\n", __func__, phy_addr, phy_reg,
+ reg, data);
+
+ err = readl_poll_timeout(priv->base + SUN8I_EMAC_MDIO_CMD, reg,
+ !(reg & MDIO_CMD_MII_BUSY), 100, 10000);
+ if (err) {
+ dev_err(priv->dev, "%s timeout %x\n", __func__, reg);
+ return err;
+ }
+
+ return 0;
+}
+
+static int sun8i_emac_mdio_register(struct net_device *ndev)
+{
+ struct sun8i_emac_priv *priv = netdev_priv(ndev);
+ struct mii_bus *bus;
+ int ret;
+
+ bus = mdiobus_alloc();
+ if (!bus) {
+ netdev_err(ndev, "Failed to allocate a new mdio bus\n");
+ return -ENOMEM;
+ }
+
+ bus->name = dev_name(priv->dev);
+ bus->read = &sun8i_mdio_read;
+ bus->write = &sun8i_mdio_write;
+ snprintf(bus->id, MII_BUS_ID_SIZE, "%s-%x", bus->name, priv->dev->id);
+
+ bus->parent = priv->dev;
+ bus->priv = ndev;
+
+ ret = of_mdiobus_register(bus, priv->dev->of_node);
+ if (ret) {
+ netdev_err(ndev, "Could not register a MDIO bus: %d\n", ret);
+ mdiobus_free(bus);
+ return ret;
+ }
+
+ priv->mdio = bus;
+
+ return 0;
+}
+
+static void sun8i_emac_mdio_unregister(struct net_device *ndev)
+{
+ struct sun8i_emac_priv *priv = netdev_priv(ndev);
+
+ mdiobus_unregister(priv->mdio);
+ mdiobus_free(priv->mdio);
+}
+
+/* Run within phydev->lock */
+static void sun8i_emac_adjust_link(struct net_device *ndev)
+{
+ struct sun8i_emac_priv *priv = netdev_priv(ndev);
+ struct phy_device *phydev = ndev->phydev;
+ int new_state = 0;
+
+ netif_dbg(priv, link, priv->ndev,
+ "%s link=%x duplex=%x speed=%x\n", __func__,
+ phydev->link, phydev->duplex, phydev->speed);
+ if (!phydev)
+ return;
+
+ if (phydev->link) {
+ if (phydev->duplex != priv->duplex) {
+ new_state = 1;
+ priv->duplex = phydev->duplex;
+ }
+ if (phydev->pause)
+ sun8i_emac_flow_ctrl(priv, phydev->duplex,
+ priv->flow_ctrl);
+
+ if (phydev->speed != priv->speed) {
+ new_state = 1;
+ priv->speed = phydev->speed;
+ }
+
+ if (priv->link == 0) {
+ new_state = 1;
+ priv->link = phydev->link;
+ }
+
+ netif_dbg(priv, link, priv->ndev,
+ "%s new=%d link=%d pause=%d\n",
+ __func__, new_state, priv->link, phydev->pause);
+ if (new_state)
+ sun8i_emac_set_link_mode(priv);
+ } else if (priv->link != phydev->link) {
+ new_state = 1;
+ priv->link = 0;
+ priv->speed = 0;
+ priv->duplex = -1;
+ }
+
+ if (new_state)
+ phy_print_status(phydev);
+}
+
+/* H3 specific bits for EPHY */
+#define H3_EPHY_ADDR_SHIFT 20
+#define H3_EPHY_LED_POL BIT(17) /* 1: active low, 0: active high */
+#define H3_EPHY_SHUTDOWN BIT(16) /* 1: shutdown, 0: power up */
+#define H3_EPHY_SELECT BIT(15) /* 1: internal PHY, 0: external PHY */
+#define H3_EPHY_DEFAULT_VALUE 0x58000
+#define H3_EPHY_DEFAULT_MASK GENMASK(31, 15)
+
+/* H3/A64 specific bits */
+#define SC_RMII_EN BIT(13) /* 1: enable RMII (overrides EPIT) */
+
+/* Generic system control EMAC_CLK bits */
+#define SC_ETXDC_MASK GENMASK(2, 0)
+#define SC_ETXDC_SHIFT 10
+#define SC_ERXDC_MASK GENMASK(4, 0)
+#define SC_ERXDC_SHIFT 5
+#define SC_EPIT BIT(2) /* 1: RGMII, 0: MII */
+#define SC_ETCS_MASK GENMASK(1, 0)
+#define SC_ETCS_MII 0x0
+#define SC_ETCS_EXT_GMII 0x1
+#define SC_ETCS_INT_GMII 0x2
+
+static int sun8i_emac_set_syscon_ephy(struct net_device *ndev, u32 *reg)
+{
+ struct sun8i_emac_priv *priv = netdev_priv(ndev);
+ struct device_node *node = priv->dev->of_node;
+ int ret;
+
+ *reg &= ~H3_EPHY_DEFAULT_MASK;
+ *reg |= H3_EPHY_DEFAULT_VALUE;
+
+ if (!priv->use_internal_phy) {
+ /* switch to external PHY interface */
+ *reg &= ~H3_EPHY_SELECT;
+ return 0;
+ }
+
+ if (priv->phy_interface != PHY_INTERFACE_MODE_MII) {
+ netdev_warn(ndev,
+ "Internal PHY requested, forcing MII mode.\n");
+ priv->phy_interface = PHY_INTERFACE_MODE_MII;
+ }
+
+ *reg |= H3_EPHY_SELECT;
+ *reg &= ~H3_EPHY_SHUTDOWN;
+
+ if (of_property_read_bool(node, "allwinner,leds-active-low"))
+ *reg |= H3_EPHY_LED_POL;
+
+ ret = of_mdio_parse_addr(priv->dev, priv->phy_node);
+ if (ret < 0) {
+ netdev_err(ndev, "Could not parse MDIO addr\n");
+ return ret;
+ }
+
+ /* of_mdio_parse_addr returns a valid (0 ~ 31) PHY
+ * address. No need to mask it again.
+ */
+ *reg |= ret << H3_EPHY_ADDR_SHIFT;
+
+ return 0;
+}
+
+static int sun8i_emac_set_syscon(struct net_device *ndev)
+{
+ struct sun8i_emac_priv *priv = netdev_priv(ndev);
+ struct device_node *node = priv->dev->of_node;
+ int ret;
+ u32 reg, val;
+
+ reg = readl(priv->syscon);
+
+ if (priv->variant == H3_EMAC) {
+ ret = sun8i_emac_set_syscon_ephy(ndev, ®);
+ if (ret)
+ return ret;
+ }
+
+ if (!of_property_read_u32(node, "allwinner,tx-delay", &val)) {
+ if (val <= SC_ETXDC_MASK) {
+ reg &= ~(SC_ETXDC_MASK << SC_ETXDC_SHIFT);
+ reg |= (val << SC_ETXDC_SHIFT);
+ } else {
+ netdev_warn(ndev, "Invalid TX clock delay: %d\n", val);
+ }
+ }
+
+ if (!of_property_read_u32(node, "allwinner,rx-delay", &val)) {
+ if (val <= SC_ERXDC_MASK) {
+ reg &= ~(SC_ERXDC_MASK << SC_ERXDC_SHIFT);
+ reg |= (val << SC_ERXDC_SHIFT);
+ } else {
+ netdev_warn(ndev, "Invalid RX clock delay: %d\n", val);
+ }
+ }
+
+ /* Clear interface mode bits */
+ reg &= ~(SC_ETCS_MASK | SC_EPIT);
+ if (priv->variant == H3_EMAC || priv->variant == A64_EMAC)
+ reg &= ~SC_RMII_EN;
+
+ switch (priv->phy_interface) {
+ case PHY_INTERFACE_MODE_MII:
+ /* default */
+ break;
+ case PHY_INTERFACE_MODE_RGMII:
+ reg |= SC_EPIT | SC_ETCS_INT_GMII;
+ break;
+ case PHY_INTERFACE_MODE_RMII:
+ if (priv->variant == H3_EMAC || priv->variant == A64_EMAC) {
+ reg |= SC_RMII_EN | SC_ETCS_EXT_GMII;
+ break;
+ }
+ /* RMII not supported on A83T */
+ default:
+ netdev_err(ndev, "Unsupported interface mode: %s",
+ phy_modes(priv->phy_interface));
+ return -EINVAL;
+ }
+
+ writel(reg, priv->syscon);
+
+ return 0;
+}
+
+static void sun8i_emac_unset_syscon(struct net_device *ndev)
+{
+ struct sun8i_emac_priv *priv = netdev_priv(ndev);
+ u32 reg = 0;
+
+ if (priv->variant == H3_EMAC)
+ reg = H3_EPHY_DEFAULT_VALUE;
+
+ writel(reg, priv->syscon);
+}
+
+/* Set Management Data Clock, must be call after device reset */
+static void sun8i_emac_set_mdc(struct net_device *ndev)
+{
+ struct sun8i_emac_priv *priv = netdev_priv(ndev);
+ unsigned long rate;
+ u32 reg;
+
+ rate = clk_get_rate(priv->ahb_clk);
+ if (rate > 160000000)
+ reg = 0x3 << 20; /* AHB / 128 */
+ else if (rate > 80000000)
+ reg = 0x2 << 20; /* AHB / 64 */
+ else if (rate > 40000000)
+ reg = 0x1 << 20; /* AHB / 32 */
+ else
+ reg = 0x0 << 20; /* AHB / 16 */
+ netif_dbg(priv, link, ndev, "MDC auto : %x\n", reg);
+ writel(reg, priv->base + SUN8I_EMAC_MDIO_CMD);
+}
+
+/* "power" the device, by enabling clk/reset/regulators */
+static int sun8i_emac_power(struct net_device *ndev)
+{
+ struct sun8i_emac_priv *priv = netdev_priv(ndev);
+ int ret;
+
+ ret = clk_prepare_enable(priv->ahb_clk);
+ if (ret) {
+ netdev_err(ndev, "Could not enable AHB clock\n");
+ return ret;
+ }
+
+ if (priv->rst) {
+ ret = reset_control_deassert(priv->rst);
+ if (ret) {
+ netdev_err(ndev, "Could not deassert reset\n");
+ goto err_reset;
+ }
+ }
+
+ if (priv->ephy_clk) {
+ ret = clk_prepare_enable(priv->ephy_clk);
+ if (ret) {
+ netdev_err(ndev, "Could not enable EPHY clock\n");
+ goto err_ephy_clk;
+ }
+ }
+
+ if (priv->rst_ephy) {
+ ret = reset_control_deassert(priv->rst_ephy);
+ if (ret) {
+ netdev_err(ndev, "Could not deassert EPHY reset\n");
+ goto err_ephy_reset;
+ }
+ }
+
+ return 0;
+
+err_ephy_reset:
+ if (priv->ephy_clk)
+ clk_disable_unprepare(priv->ephy_clk);
+err_ephy_clk:
+ if (priv->rst)
+ reset_control_assert(priv->rst);
+err_reset:
+ clk_disable_unprepare(priv->ahb_clk);
+ return ret;
+}
+
+/* "Unpower" the device, disabling clocks and regulators, asserting reset */
+static void sun8i_emac_unpower(struct net_device *ndev)
+{
+ struct sun8i_emac_priv *priv = netdev_priv(ndev);
+
+ if (priv->rst_ephy)
+ reset_control_assert(priv->rst_ephy);
+
+ if (priv->ephy_clk)
+ clk_disable_unprepare(priv->ephy_clk);
+
+ if (priv->rst)
+ reset_control_assert(priv->rst);
+
+ clk_disable_unprepare(priv->ahb_clk);
+}
+
+static int sun8i_emac_init(struct net_device *ndev)
+{
+ struct sun8i_emac_priv *priv = netdev_priv(ndev);
+ struct device_node *node = priv->dev->of_node;
+ const u8 *addr;
+
+ /* Try to get MAC address from DT, or assign a random one */
+ addr = of_get_mac_address(node);
+ if (addr)
+ ether_addr_copy(ndev->dev_addr, addr);
+ else
+ eth_hw_addr_random(ndev);
+
+ priv->phy_interface = of_get_phy_mode(node);
+ if (priv->phy_interface < 0) {
+ netdev_err(ndev, "PHY interface mode node unspecified\n");
+ return priv->phy_interface;
+ }
+
+ return sun8i_emac_power(ndev);
+}
+
+static void sun8i_emac_uninit(struct net_device *ndev)
+{
+ struct sun8i_emac_priv *priv = netdev_priv(ndev);
+
+ mdiobus_unregister(priv->mdio);
+
+ sun8i_emac_unpower(ndev);
+}
+
+static int sun8i_emac_mdio_probe(struct net_device *ndev)
+{
+ struct sun8i_emac_priv *priv = netdev_priv(ndev);
+ struct phy_device *phydev = NULL;
+
+ phydev = of_phy_connect(ndev, priv->phy_node, &sun8i_emac_adjust_link,
+ 0, priv->phy_interface);
+
+ if (!phydev) {
+ netdev_err(ndev, "Could not attach to PHY\n");
+ return -ENODEV;
+ }
+
+ phy_attached_info(phydev);
+
+ /* mask with MAC supported features */
+ phydev->supported &= PHY_GBIT_FEATURES;
+ phydev->advertising = phydev->supported;
+
+ priv->link = 0;
+ priv->speed = 0;
+ priv->duplex = -1;
+
+ return 0;
+}
+
+/* Allocate both RX and TX ring buffer and init them
+ * This function also write the startbase of thoses ring in the device.
+ * All structures that help managing thoses rings are also handled
+ * by this functions (rx_skb/txl)
+ */
+static int sun8i_emac_alloc_rings(struct net_device *ndev)
+{
+ struct sun8i_emac_priv *priv = netdev_priv(ndev);
+ struct dma_desc *ddesc;
+ int err, i;
+
+ priv->rx_skb = kcalloc(priv->nbdesc_rx, sizeof(struct sk_buff *),
+ GFP_KERNEL);
+ if (!priv->rx_skb) {
+ err = -ENOMEM;
+ goto rx_skb_error;
+ }
+ priv->txl = kcalloc(priv->nbdesc_tx, sizeof(struct txinfo), GFP_KERNEL);
+ if (!priv->txl) {
+ err = -ENOMEM;
+ goto tx_error;
+ }
+
+ /* allocate/init RX ring */
+ priv->dd_rx = dma_zalloc_coherent(priv->dev,
+ priv->nbdesc_rx * sizeof(struct dma_desc),
+ &priv->dd_rx_phy, GFP_KERNEL);
+ if (!priv->dd_rx) {
+ dev_err(priv->dev, "ERROR: cannot allocate DMA RX buffer");
+ err = -ENOMEM;
+ goto dma_rx_error;
+ }
+ ddesc = priv->dd_rx;
+ for (i = 0; i < priv->nbdesc_rx; i++) {
+ sun8i_emac_rx_skb(ndev, i);
+ ddesc->next = (u32)priv->dd_rx_phy + (i + 1)
+ * sizeof(struct dma_desc);
+ ddesc++;
+ }
+ /* last descriptor point back to first one */
+ ddesc--;
+ ddesc->next = (u32)priv->dd_rx_phy;
+
+ /* allocate/init TX ring */
+ priv->dd_tx = dma_zalloc_coherent(priv->dev,
+ priv->nbdesc_tx * sizeof(struct dma_desc),
+ &priv->dd_tx_phy, GFP_KERNEL);
+ if (!priv->dd_tx) {
+ dev_err(priv->dev, "ERROR: cannot allocate DMA TX buffer");
+ err = -ENOMEM;
+ goto dma_tx_error;
+ }
+ ddesc = priv->dd_tx;
+ for (i = 0; i < priv->nbdesc_tx; i++) {
+ ddesc->status = DCLEAN;
+ ddesc->ctl = 0;
+ ddesc->next = (u32)(priv->dd_tx_phy + (i + 1)
+ * sizeof(struct dma_desc));
+ ddesc++;
+ }
+ /* last descriptor point back to first one */
+ ddesc--;
+ ddesc->next = (u32)priv->dd_tx_phy;
+ i--;
+
+ priv->tx_slot = 0;
+ priv->tx_dirty = 0;
+ priv->rx_dirty = 0;
+
+ /* write start of RX ring descriptor */
+ writel(priv->dd_rx_phy, priv->base + SUN8I_EMAC_RX_DESC_LIST);
+ /* write start of TX ring descriptor */
+ writel(priv->dd_tx_phy, priv->base + SUN8I_EMAC_TX_DESC_LIST);
+
+ return 0;
+dma_tx_error:
+ dma_free_coherent(priv->dev, priv->nbdesc_rx * sizeof(struct dma_desc),
+ priv->dd_rx, priv->dd_rx_phy);
+dma_rx_error:
+ kfree(priv->txl);
+tx_error:
+ kfree(priv->rx_skb);
+rx_skb_error:
+ return err;
+}
+
+static int sun8i_emac_open(struct net_device *ndev)
+{
+ struct sun8i_emac_priv *priv = netdev_priv(ndev);
+ int err;
+ u32 v;
+
+ err = request_irq(priv->irq, sun8i_emac_dma_interrupt, 0,
+ dev_name(priv->dev), ndev);
+ if (err) {
+ dev_err(priv->dev, "Cannot request IRQ: %d\n", err);
+ return err;
+ }
+
+ /* Set interface mode (and configure internal PHY on H3) */
+ err = sun8i_emac_set_syscon(ndev);
+ if (err)
+ goto err_irq;
+
+ /* Do SOFT RST */
+ v = readl(priv->base + SUN8I_EMAC_BASIC_CTL1);
+ writel(v | 0x01, priv->base + SUN8I_EMAC_BASIC_CTL1);
+
+ err = readl_poll_timeout(priv->base + SUN8I_EMAC_BASIC_CTL1, v,
+ !(v & 0x01), 100, 10000);
+ if (err) {
+ dev_err(priv->dev, "EMAC reset timeout\n");
+ err = -EFAULT;
+ goto err_syscon;
+ }
+
+ sun8i_emac_set_mdc(ndev);
+
+ err = sun8i_emac_mdio_register(ndev);
+ if (err)
+ goto err_syscon;
+
+ err = sun8i_emac_mdio_probe(ndev);
+ if (err)
+ goto err_syscon;
+
+ /* DMA */
+ v = (8 << 24);/* burst len */
+ writel(v, priv->base + SUN8I_EMAC_BASIC_CTL1);
+
+ writel(RX_INT | TX_INT, priv->base + SUN8I_EMAC_INT_EN);
+
+ v = readl(priv->base + SUN8I_EMAC_RX_CTL0);
+ /* CHECK_CRC */
+ if (ndev->features & NETIF_F_RXCSUM)
+ v |= SUN8I_EMAC_RX_DO_CRC;
+ else
+ v &= ~SUN8I_EMAC_RX_DO_CRC;
+ /* STRIP_FCS */
+ if (ndev->features & NETIF_F_RXFCS)
+ v &= ~SUN8I_EMAC_RX_STRIP_FCS;
+ else
+ v |= SUN8I_EMAC_RX_STRIP_FCS;
+ writel(v, priv->base + SUN8I_EMAC_RX_CTL0);
+
+ v = readl(priv->base + SUN8I_EMAC_TX_CTL1);
+ /* TX_MD Transmission starts after a full frame located in TX DMA FIFO*/
+ v |= BIT(1);
+ /* Undocumented bit (called TX_NEXT_FRM in BSP), the original comment is
+ * "Operating on second frame increase the performance
+ * especially when transmit store-and-forward is used."
+ */
+ v |= BIT(2);
+ writel(v, priv->base + SUN8I_EMAC_TX_CTL1);
+
+ v = readl(priv->base + SUN8I_EMAC_RX_CTL1);
+ /* RX_MD RX DMA reads data from RX DMA FIFO to host memory after a
+ * complete frame has been written to RX DMA FIFO
+ */
+ v |= BIT(1);
+ writel(v, priv->base + SUN8I_EMAC_RX_CTL1);
+
+ sun8i_emac_set_macaddr(priv, ndev->dev_addr, 0);
+
+ err = sun8i_emac_alloc_rings(ndev);
+ if (err) {
+ netdev_err(ndev, "Fail to allocate rings\n");
+ goto err_mdio;
+ }
+
+ phy_start(ndev->phydev);
+
+ sun8i_emac_start_rx(ndev);
+ sun8i_emac_start_tx(ndev);
+
+ netif_napi_add(ndev, &priv->napi, sun8i_emac_poll, 64);
+ napi_enable(&priv->napi);
+ netif_start_queue(ndev);
+
+ return 0;
+err_mdio:
+ phy_disconnect(ndev->phydev);
+err_syscon:
+ sun8i_emac_unset_syscon(ndev);
+err_irq:
+ free_irq(priv->irq, ndev);
+ return err;
+}
+
+/* Clean the TX ring of any accepted skb for xmit */
+static void sun8i_emac_tx_clean(struct net_device *ndev)
+{
+ struct sun8i_emac_priv *priv = netdev_priv(ndev);
+ int i;
+ struct dma_desc *ddesc;
+ int frame_len;
+
+ spin_lock(&priv->tx_lock);
+
+ for (i = 0; i < priv->nbdesc_tx; i++) {
+ if (priv->txl[i].skb) {
+ ddesc = priv->dd_tx + i;
+ frame_len = ddesc->ctl & 0x3FFF;
+ switch (priv->txl[i].map) {
+ case MAP_SINGLE:
+ dma_unmap_single(priv->dev, ddesc->buf_addr,
+ frame_len, DMA_TO_DEVICE);
+ break;
+ case MAP_PAGE:
+ dma_unmap_page(priv->dev, ddesc->buf_addr,
+ frame_len, DMA_TO_DEVICE);
+ break;
+ default:
+ dev_err(priv->dev, "Trying to free an empty slot\n");
+ continue;
+ }
+ dev_kfree_skb_any(priv->txl[i].skb);
+ priv->txl[i].skb = NULL;
+ ddesc->ctl = 0;
+ ddesc->status = DCLEAN;
+ }
+ }
+ priv->tx_slot = 0;
+ priv->tx_dirty = 0;
+
+ spin_unlock(&priv->tx_lock);
+}
+
+/* Clean the RX ring */
+static void sun8i_emac_rx_clean(struct net_device *ndev)
+{
+ struct sun8i_emac_priv *priv = netdev_priv(ndev);
+ int i;
+ struct dma_desc *ddesc;
+
+ /* clean RX ring */
+ for (i = 0; i < priv->nbdesc_rx; i++)
+ if (priv->rx_skb[i]) {
+ ddesc = priv->dd_rx + i;
+ dma_unmap_single(priv->dev, ddesc->buf_addr,
+ DESC_BUF_MAX, DMA_FROM_DEVICE);
+ dev_kfree_skb_any(priv->rx_skb[i]);
+ priv->rx_skb[i] = NULL;
+ }
+}
+
+static int sun8i_emac_stop(struct net_device *ndev)
+{
+ struct sun8i_emac_priv *priv = netdev_priv(ndev);
+
+ napi_disable(&priv->napi);
+
+ sun8i_emac_stop_tx(ndev);
+ sun8i_emac_stop_rx(ndev);
+
+ phy_stop(ndev->phydev);
+ phy_disconnect(ndev->phydev);
+
+ sun8i_emac_mdio_unregister(ndev);
+
+ sun8i_emac_unset_syscon(ndev);
+
+ free_irq(priv->irq, ndev);
+
+ sun8i_emac_rx_clean(ndev);
+ sun8i_emac_tx_clean(ndev);
+
+ kfree(priv->rx_skb);
+ kfree(priv->txl);
+
+ dma_free_coherent(priv->dev, priv->nbdesc_rx * sizeof(struct dma_desc),
+ priv->dd_rx, priv->dd_rx_phy);
+ dma_free_coherent(priv->dev, priv->nbdesc_tx * sizeof(struct dma_desc),
+ priv->dd_tx, priv->dd_tx_phy);
+
+ return 0;
+}
+
+static netdev_tx_t sun8i_emac_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+ struct sun8i_emac_priv *priv = netdev_priv(ndev);
+ struct dma_desc *ddesc;
+ struct dma_desc *first;
+ int i = 0, rbd_first;
+ unsigned int len, fraglen, tlen;
+ u32 v;
+ int n;
+ int nf;
+ const skb_frag_t *frag;
+ int do_csum = 0;
+
+ if (skb_put_padto(skb, ETH_ZLEN))
+ return NETDEV_TX_OK;
+ len = skb_headlen(skb);
+
+ n = skb_shinfo(skb)->nr_frags;
+
+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ do_csum = 1;
+ priv->estats.tx_hw_csum++;
+ }
+ netif_dbg(priv, tx_queued, ndev, "%s len=%u skblen=%u %x\n", __func__,
+ len, skb->len,
+ (skb->ip_summed == CHECKSUM_PARTIAL));
+
+ spin_lock(&priv->tx_lock);
+
+ /* check for contigous space
+ * We need at least 1(skb->data) + n(numfrags) + 1(one clean slot)
+ */
+ if (rb_tx_numfreedesc(ndev) < n + 2) {
+ dev_err_ratelimited(priv->dev, "BUG!: TX is full %d %d\n",
+ priv->tx_dirty, priv->tx_slot);
+ netif_stop_queue(ndev);
+ spin_unlock(&priv->tx_lock);
+ return NETDEV_TX_BUSY;
+ }
+ i = priv->tx_slot;
+
+ ddesc = priv->dd_tx + i;
+ first = priv->dd_tx + i;
+ rbd_first = i;
+
+ priv->tx_slot = (i + 1 + n) % priv->nbdesc_tx;
+
+ ddesc->buf_addr = dma_map_single(priv->dev, skb->data, len,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(priv->dev, ddesc->buf_addr)) {
+ dev_err(priv->dev, "ERROR: Cannot map buffer for DMA\n");
+ goto xmit_error;
+ }
+ priv->txl[i].map = MAP_SINGLE;
+ priv->txl[i].skb = skb;
+
+ tlen = len;
+ ddesc->ctl = len;
+ /* Undocumented bit that make it works
+ * Without it, packets never be sent on H3 SoC
+ */
+ ddesc->ctl |= SUN8I_EMAC_MAGIC_TX_BIT;
+ if (do_csum)
+ ddesc->ctl |= SUN8I_EMAC_TX_DO_CRC;
+
+ /* handle fragmented skb, one descriptor per fragment */
+ for (nf = 0; nf < n; nf++) {
+ frag = &skb_shinfo(skb)->frags[nf];
+ rb_inc(&i, priv->nbdesc_tx);
+ priv->txl[i].skb = skb;
+ ddesc = priv->dd_tx + i;
+ fraglen = skb_frag_size(frag);
+ ddesc->ctl = fraglen;
+ tlen += fraglen,
+ ddesc->ctl |= SUN8I_EMAC_MAGIC_TX_BIT;
+ if (do_csum)
+ ddesc->ctl |= SUN8I_EMAC_TX_DO_CRC;
+
+ ddesc->buf_addr = skb_frag_dma_map(priv->dev, frag, 0,
+ fraglen, DMA_TO_DEVICE);
+ if (dma_mapping_error(priv->dev, ddesc->buf_addr)) {
+ dev_err(priv->dev, "Cannot map buffer for DMA\n");
+ goto xmit_error;
+ }
+ priv->txl[i].map = MAP_PAGE;
+ ddesc->status = SUN8I_COULD_BE_USED_BY_DMA;
+ }
+
+ /* frame end */
+ ddesc->ctl |= DSC_TX_LAST;
+ /* We want an interrupt after transmission */
+ ddesc->ctl |= SUN8I_EMAC_WANT_INT;
+
+ rb_inc(&i, priv->nbdesc_tx);
+
+ /* frame begin */
+ first->ctl |= DSC_TX_FIRST;
+ wmb();/* SUN8I_COULD_BE_USED_BY_DMA must be the last value written */
+ first->status = SUN8I_COULD_BE_USED_BY_DMA;
+ priv->tx_slot = i;
+
+ /* Trying to optimize this (recording DMA start/stop) seems
+ * to lead to errors. So we always start DMA.
+ */
+ v = readl(priv->base + SUN8I_EMAC_TX_CTL1);
+ v |= TX_DMA_START;
+ v |= TX_DMA_EN;
+ writel(v, priv->base + SUN8I_EMAC_TX_CTL1);
+
+ if (rb_tx_numfreedesc(ndev) < MAX_SKB_FRAGS + 1) {
+ netif_stop_queue(ndev);
+ priv->estats.tx_stop_queue++;
+ }
+ priv->estats.tx_used_desc = rb_tx_numfreedesc(ndev);
+ priv->ndev->stats.tx_packets++;
+ priv->ndev->stats.tx_bytes += tlen;
+
+ spin_unlock(&priv->tx_lock);
+
+ return NETDEV_TX_OK;
+
+xmit_error:
+ /* destroy skb and return TX OK Documentation/DMA-API-HOWTO.txt */
+ /* clean descritors from rbd_first to i */
+ ddesc->ctl = 0;
+ wmb(); /* setting to DCLEAN is the last value to be set */
+ ddesc->status = DCLEAN;
+ do {
+ ddesc = priv->dd_tx + rbd_first;
+ ddesc->ctl = 0;
+ wmb(); /* setting to DCLEAN is the last value to be set */
+ ddesc->status = DCLEAN;
+ rb_inc(&rbd_first, priv->nbdesc_tx);
+ } while (rbd_first != i);
+ spin_unlock(&priv->tx_lock);
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+}
+
+static int sun8i_emac_change_mtu(struct net_device *ndev, int new_mtu)
+{
+ struct sun8i_emac_priv *priv = netdev_priv(ndev);
+ int max_mtu;
+
+ dev_info(priv->dev, "%s set MTU to %d\n", __func__, new_mtu);
+
+ if (netif_running(ndev)) {
+ dev_err(priv->dev, "%s: must be stopped to change its MTU\n",
+ ndev->name);
+ return -EBUSY;
+ }
+
+ max_mtu = SKB_MAX_HEAD(NET_SKB_PAD + NET_IP_ALIGN);
+
+ if ((new_mtu < 68) || (new_mtu > max_mtu)) {
+ dev_err(priv->dev, "%s: invalid MTU, max MTU is: %d\n",
+ ndev->name, max_mtu);
+ return -EINVAL;
+ }
+
+ ndev->mtu = new_mtu;
+ netdev_update_features(ndev);
+ return 0;
+}
+
+static netdev_features_t sun8i_emac_fix_features(struct net_device *ndev,
+ netdev_features_t features)
+{
+ struct sun8i_emac_priv *priv = netdev_priv(ndev);
+
+ netif_dbg(priv, drv, ndev, "%s %llx\n", __func__, features);
+ return features;
+}
+
+static int sun8i_emac_set_features(struct net_device *ndev,
+ netdev_features_t features)
+{
+ struct sun8i_emac_priv *priv = netdev_priv(ndev);
+ u32 v;
+
+ v = readl(priv->base + SUN8I_EMAC_BASIC_CTL0);
+ if (features & NETIF_F_LOOPBACK && netif_running(ndev)) {
+ netif_info(priv, hw, ndev, "Set loopback features");
+ v |= BIT(1);
+ } else {
+ netif_info(priv, hw, ndev, "Unset loopback features");
+ v &= ~BIT(1);
+ }
+ writel(v, priv->base + SUN8I_EMAC_BASIC_CTL0);
+
+ v = readl(priv->base + SUN8I_EMAC_RX_CTL0);
+ if (features & NETIF_F_RXCSUM) {
+ v |= SUN8I_EMAC_RX_DO_CRC;
+ netif_info(priv, hw, ndev, "Doing RX CRC check by hardware");
+ } else {
+ v &= ~SUN8I_EMAC_RX_DO_CRC;
+ netif_info(priv, hw, ndev, "No RX CRC check by hardware");
+ }
+ if (features & NETIF_F_RXFCS) {
+ v &= ~SUN8I_EMAC_RX_STRIP_FCS;
+ netif_info(priv, hw, ndev, "Keep FCS");
+ } else {
+ v |= SUN8I_EMAC_RX_STRIP_FCS;
+ netif_info(priv, hw, ndev, "Strip FCS");
+ }
+ writel(v, priv->base + SUN8I_EMAC_RX_CTL0);
+
+ netif_dbg(priv, drv, ndev, "%s %llx %x\n", __func__, features, v);
+
+ return 0;
+}
+
+static void sun8i_emac_set_rx_mode(struct net_device *ndev)
+{
+ struct sun8i_emac_priv *priv = netdev_priv(ndev);
+ u32 v = 0;
+ int i = 0;
+ struct netdev_hw_addr *ha;
+
+ /* Receive all multicast frames */
+ v |= BIT(16);
+ /* Receive all control frames */
+ v |= BIT(13);
+ if (ndev->flags & IFF_PROMISC)
+ v |= BIT(1);
+ if (netdev_uc_count(ndev) > 7) {
+ v |= BIT(1);
+ } else {
+ netdev_for_each_uc_addr(ha, ndev) {
+ i++;
+ sun8i_emac_set_macaddr(priv, ha->addr, i);
+ }
+ }
+ writel(v, priv->base + SUN8I_EMAC_RX_FRM_FLT);
+}
+
+static void sun8i_emac_tx_timeout(struct net_device *ndev)
+{
+ struct sun8i_emac_priv *priv = netdev_priv(ndev);
+
+ netdev_err(ndev, "%s\n", __func__);
+
+ sun8i_emac_stop_tx(ndev);
+
+ sun8i_emac_tx_clean(ndev);
+
+ /* write start of tx ring descriptor */
+ writel(priv->dd_tx_phy, priv->base + SUN8I_EMAC_TX_DESC_LIST);
+
+ sun8i_emac_start_tx(ndev);
+
+ netdev_reset_queue(ndev);
+
+ ndev->stats.tx_errors++;
+ netif_wake_queue(ndev);
+}
+
+static int sun8i_emac_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
+{
+ struct phy_device *phydev = ndev->phydev;
+
+ if (!netif_running(ndev))
+ return -EINVAL;
+
+ if (!phydev)
+ return -ENODEV;
+
+ return phy_mii_ioctl(phydev, rq, cmd);
+}
+
+static int sun8i_emac_check_if_running(struct net_device *ndev)
+{
+ if (!netif_running(ndev))
+ return -EINVAL;
+ return 0;
+}
+
+static int sun8i_emac_get_sset_count(struct net_device *ndev, int sset)
+{
+ switch (sset) {
+ case ETH_SS_STATS:
+ return ARRAY_SIZE(estats_str);
+ }
+ return -EOPNOTSUPP;
+}
+
+static int sun8i_emac_ethtool_get_settings(struct net_device *ndev,
+ struct ethtool_cmd *cmd)
+{
+ struct phy_device *phy = ndev->phydev;
+ struct sun8i_emac_priv *priv = netdev_priv(ndev);
+
+ if (!phy) {
+ netdev_err(ndev, "%s: %s: PHY is not registered\n",
+ __func__, ndev->name);
+ return -ENODEV;
+ }
+
+ if (!netif_running(ndev)) {
+ dev_err(priv->dev, "interface disabled: we cannot track link speed / duplex setting\n");
+ return -EBUSY;
+ }
+
+ return phy_ethtool_gset(phy, cmd);
+}
+
+static int sun8i_emac_ethtool_set_settings(struct net_device *ndev,
+ struct ethtool_cmd *cmd)
+{
+ struct phy_device *phy = ndev->phydev;
+
+ return phy_ethtool_sset(phy, cmd);
+}
+
+static void sun8i_emac_ethtool_getdrvinfo(struct net_device *ndev,
+ struct ethtool_drvinfo *info)
+{
+ strlcpy(info->driver, "sun8i_emac", sizeof(info->driver));
+ strcpy(info->version, "00");
+ info->fw_version[0] = '\0';
+}
+
+static void sun8i_emac_ethtool_stats(struct net_device *ndev,
+ struct ethtool_stats *dummy, u64 *data)
+{
+ struct sun8i_emac_priv *priv = netdev_priv(ndev);
+
+ memcpy(data, &priv->estats,
+ sun8i_emac_get_sset_count(ndev, ETH_SS_STATS) * sizeof(u64));
+}
+
+static void sun8i_emac_ethtool_strings(struct net_device *dev, u32 stringset,
+ u8 *buffer)
+{
+ switch (stringset) {
+ case ETH_SS_STATS:
+ memcpy(buffer, &estats_str, sizeof(estats_str));
+ break;
+ }
+}
+
+static u32 sun8i_emac_ethtool_getmsglevel(struct net_device *ndev)
+{
+ struct sun8i_emac_priv *priv = netdev_priv(ndev);
+
+ return priv->msg_enable;
+}
+
+static void sun8i_emac_ethtool_setmsglevel(struct net_device *ndev, u32 level)
+{
+ struct sun8i_emac_priv *priv = netdev_priv(ndev);
+
+ priv->msg_enable = level;
+}
+
+static void sun8i_emac_get_pauseparam(struct net_device *ndev,
+ struct ethtool_pauseparam *pause)
+{
+ struct sun8i_emac_priv *priv = netdev_priv(ndev);
+
+ pause->rx_pause = 0;
+ pause->tx_pause = 0;
+ pause->autoneg = ndev->phydev->autoneg;
+
+ if (priv->flow_ctrl & FLOW_RX)
+ pause->rx_pause = 1;
+ if (priv->flow_ctrl & FLOW_TX)
+ pause->tx_pause = 1;
+}
+
+static int sun8i_emac_set_pauseparam(struct net_device *ndev,
+ struct ethtool_pauseparam *pause)
+{
+ struct sun8i_emac_priv *priv = netdev_priv(ndev);
+ struct phy_device *phy = ndev->phydev;
+ int new_pause = 0;
+ int ret = 0;
+
+ if (pause->rx_pause)
+ new_pause |= FLOW_RX;
+ if (pause->tx_pause)
+ new_pause |= FLOW_TX;
+
+ priv->flow_ctrl = new_pause;
+ phy->autoneg = pause->autoneg;
+
+ if (phy->autoneg) {
+ if (netif_running(ndev))
+ ret = phy_start_aneg(phy);
+ } else {
+ sun8i_emac_flow_ctrl(priv, phy->duplex, priv->flow_ctrl);
+ }
+ return ret;
+}
+
+static void sun8i_emac_ethtool_get_ringparam(struct net_device *ndev,
+ struct ethtool_ringparam *ring)
+{
+ struct sun8i_emac_priv *priv = netdev_priv(ndev);
+
+ ring->rx_pending = priv->nbdesc_rx;
+ ring->tx_pending = priv->nbdesc_tx;
+}
+
+static int sun8i_emac_ethtool_set_ringparam(struct net_device *ndev,
+ struct ethtool_ringparam *ring)
+{
+ struct sun8i_emac_priv *priv = netdev_priv(ndev);
+ int err;
+
+ if (ring->rx_max_pending || ring->rx_mini_max_pending ||
+ ring->rx_jumbo_max_pending || ring->rx_mini_pending ||
+ ring->rx_jumbo_pending || ring->tx_max_pending)
+ return -EINVAL;
+
+ if (ring->tx_pending < MAX_SKB_FRAGS + 1) {
+ netdev_err(ndev, "The number of TX descriptors is too low");
+ return -EINVAL;
+ }
+
+ sun8i_emac_stop_tx(ndev);
+ sun8i_emac_stop_rx(ndev);
+
+ sun8i_emac_rx_clean(ndev);
+ sun8i_emac_tx_clean(ndev);
+
+ kfree(priv->rx_skb);
+ kfree(priv->txl);
+
+ dma_free_coherent(priv->dev, priv->nbdesc_rx * sizeof(struct dma_desc),
+ priv->dd_rx, priv->dd_rx_phy);
+ dma_free_coherent(priv->dev, priv->nbdesc_tx * sizeof(struct dma_desc),
+ priv->dd_tx, priv->dd_tx_phy);
+
+ priv->nbdesc_rx = ring->rx_pending;
+ priv->nbdesc_tx = ring->tx_pending;
+ err = sun8i_emac_alloc_rings(ndev);
+ if (err) {
+ /* Fatal error, we cannot re start */
+ netdev_err(ndev, "Fail to allocate rings\n");
+ return -EFAULT;
+ }
+
+ sun8i_emac_start_rx(ndev);
+ sun8i_emac_start_tx(ndev);
+
+ netif_start_queue(ndev);
+
+ netdev_info(ndev, "Ring Param settings: rx: %d, tx %d\n",
+ ring->rx_pending, ring->tx_pending);
+ return 0;
+}
+
+static const struct ethtool_ops sun8i_emac_ethtool_ops = {
+ .begin = sun8i_emac_check_if_running,
+ .get_settings = sun8i_emac_ethtool_get_settings,
+ .set_settings = sun8i_emac_ethtool_set_settings,
+ .get_link = ethtool_op_get_link,
+ .get_pauseparam = sun8i_emac_get_pauseparam,
+ .set_pauseparam = sun8i_emac_set_pauseparam,
+ .get_ethtool_stats = sun8i_emac_ethtool_stats,
+ .get_strings = sun8i_emac_ethtool_strings,
+ .get_sset_count = sun8i_emac_get_sset_count,
+ .get_drvinfo = sun8i_emac_ethtool_getdrvinfo,
+ .get_msglevel = sun8i_emac_ethtool_getmsglevel,
+ .set_msglevel = sun8i_emac_ethtool_setmsglevel,
+ .get_ringparam = sun8i_emac_ethtool_get_ringparam,
+ .set_ringparam = sun8i_emac_ethtool_set_ringparam,
+};
+
+static const struct net_device_ops sun8i_emac_netdev_ops = {
+ .ndo_init = sun8i_emac_init,
+ .ndo_uninit = sun8i_emac_uninit,
+ .ndo_open = sun8i_emac_open,
+ .ndo_start_xmit = sun8i_emac_xmit,
+ .ndo_stop = sun8i_emac_stop,
+ .ndo_change_mtu = sun8i_emac_change_mtu,
+ .ndo_fix_features = sun8i_emac_fix_features,
+ .ndo_set_features = sun8i_emac_set_features,
+ .ndo_set_rx_mode = sun8i_emac_set_rx_mode,
+ .ndo_tx_timeout = sun8i_emac_tx_timeout,
+ .ndo_do_ioctl = sun8i_emac_ioctl,
+ .ndo_set_mac_address = eth_mac_addr,
+};
+
+static irqreturn_t sun8i_emac_dma_interrupt(int irq, void *dev_id)
+{
+ struct net_device *ndev = dev_id;
+ struct sun8i_emac_priv *priv = netdev_priv(ndev);
+ u32 v, u;
+
+ v = readl(priv->base + SUN8I_EMAC_INT_STA);
+
+ /* When this bit is asserted, a frame transmission is completed. */
+ if (v & BIT(0)) {
+ priv->estats.tx_int++;
+ writel(0, priv->base + SUN8I_EMAC_INT_EN);
+ napi_schedule(&priv->napi);
+ }
+
+ /* When this bit is asserted, the TX DMA FSM is stopped. */
+ if (v & BIT(1))
+ priv->estats.tx_dma_stop++;
+
+ /* When this asserted, the TX DMA can not acquire next TX descriptor
+ * and TX DMA FSM is suspended.
+ */
+ if (v & BIT(2))
+ priv->estats.tx_dma_ua++;
+
+ if (v & BIT(3))
+ netif_dbg(priv, intr, ndev, "Unhandled interrupt TX TIMEOUT\n");
+
+ if (v & BIT(4)) {
+ netif_dbg(priv, intr, ndev, "Unhandled interrupt TX underflow\n");
+ priv->estats.tx_underflow_int++;
+ }
+
+ /* When this bit asserted , the frame is transmitted to FIFO totally. */
+ if (v & BIT(5)) {
+ netif_dbg(priv, intr, ndev, "Unhandled interrupt TX_EARLY_INT\n");
+ priv->estats.tx_early_int++;
+ }
+
+ /* When this bit is asserted, a frame reception is completed */
+ if (v & BIT(8)) {
+ priv->estats.rx_int++;
+ writel(0, priv->base + SUN8I_EMAC_INT_EN);
+ napi_schedule(&priv->napi);
+ }
+
+ /* When this asserted, the RX DMA can not acquire next TX descriptor
+ * and RX DMA FSM is suspended.
+ */
+ if (v & BIT(9)) {
+ u = readl(priv->base + SUN8I_EMAC_RX_CTL1);
+ netif_info(priv, intr, ndev, "Re-run RX DMA %x\n", u);
+ writel(u | RX_DMA_START, priv->base + SUN8I_EMAC_RX_CTL1);
+ priv->estats.rx_dma_ua++;
+ }
+
+ if (v & BIT(10)) {
+ netif_dbg(priv, intr, ndev, "Unhandled interrupt RX_DMA_STOPPED_INT\n");
+ priv->estats.rx_dma_stop++;
+ }
+ if (v & BIT(11))
+ netif_dbg(priv, intr, ndev, "Unhandled interrupt RX_TIMEOUT\n");
+ if (v & BIT(12))
+ netif_dbg(priv, intr, ndev, "Unhandled interrupt RX OVERFLOW\n");
+ if (v & BIT(13)) {
+ netif_dbg(priv, intr, ndev, "Unhandled interrupt RX EARLY\n");
+ priv->estats.rx_early_int++;
+ }
+ if (v & BIT(16))
+ netif_dbg(priv, intr, ndev, "Unhandled interrupt RGMII\n");
+
+ /* the datasheet state those register as read-only
+ * but nothing work(freeze) without writing to it
+ */
+ writel(v & 0x3FFF, priv->base + SUN8I_EMAC_INT_STA);
+
+ return IRQ_HANDLED;
+}
+
+static int sun8i_emac_probe(struct platform_device *pdev)
+{
+ struct device_node *node = pdev->dev.of_node;
+ struct sun8i_emac_priv *priv;
+ struct net_device *ndev;
+ struct resource *res;
+ int ret;
+
+ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+ if (ret) {
+ dev_err(&pdev->dev, "No suitable DMA available\n");
+ return ret;
+ }
+
+ ndev = alloc_etherdev(sizeof(*priv));
+ if (!ndev)
+ return -ENOMEM;
+
+ SET_NETDEV_DEV(ndev, &pdev->dev);
+ priv = netdev_priv(ndev);
+ platform_set_drvdata(pdev, ndev);
+
+ priv->variant = (enum emac_variant)of_device_get_match_data(&pdev->dev);
+ if (!priv->variant) {
+ dev_err(&pdev->dev, "Missing sun8i-emac variant\n");
+ return -EINVAL;
+ }
+
+ priv->phy_node = of_parse_phandle(node, "phy", 0);
+ if (!priv->phy_node) {
+ netdev_err(ndev, "No associated PHY\n");
+ return -ENODEV;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ priv->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(priv->base)) {
+ ret = PTR_ERR(priv->base);
+ dev_err(&pdev->dev, "Cannot request MMIO: %d\n", ret);
+ return ret;
+ }
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "syscon");
+ priv->syscon = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(priv->syscon)) {
+ ret = PTR_ERR(priv->syscon);
+ dev_err(&pdev->dev,
+ "Cannot map system control registers: %d\n", ret);
+ return ret;
+ }
+
+ priv->ahb_clk = devm_clk_get(&pdev->dev, "ahb");
+ if (IS_ERR(priv->ahb_clk)) {
+ ret = PTR_ERR(priv->ahb_clk);
+ dev_err(&pdev->dev, "Cannot get AHB clock err=%d\n", ret);
+ goto probe_err;
+ }
+
+ priv->rst = devm_reset_control_get_optional(&pdev->dev, "ahb");
+ if (IS_ERR(priv->rst)) {
+ ret = PTR_ERR(priv->rst);
+ if (ret == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ dev_info(&pdev->dev, "No MAC reset control found %d\n", ret);
+ priv->rst = NULL;
+ }
+
+ if (priv->variant == H3_EMAC)
+ priv->use_internal_phy = of_property_read_bool(node,
+ "allwinner,use-internal-phy");
+
+ if (priv->use_internal_phy) {
+ priv->ephy_clk = devm_clk_get(&pdev->dev, "ephy");
+ if (IS_ERR(priv->ephy_clk)) {
+ ret = PTR_ERR(priv->ephy_clk);
+ dev_err(&pdev->dev, "Cannot get EPHY clock err=%d\n",
+ ret);
+ goto probe_err;
+ }
+
+ priv->rst_ephy = devm_reset_control_get_optional(&pdev->dev,
+ "ephy");
+ if (IS_ERR(priv->rst_ephy)) {
+ ret = PTR_ERR(priv->rst_ephy);
+ if (ret == -EPROBE_DEFER)
+ goto probe_err;
+ dev_info(&pdev->dev,
+ "No EPHY reset control found %d\n", ret);
+ priv->rst_ephy = NULL;
+ }
+ }
+
+ priv->irq = platform_get_irq(pdev, 0);
+ if (priv->irq < 0) {
+ ret = priv->irq;
+ dev_err(&pdev->dev, "Cannot claim IRQ: %d\n", ret);
+ goto probe_err;
+ }
+
+ spin_lock_init(&priv->tx_lock);
+
+ ndev->netdev_ops = &sun8i_emac_netdev_ops;
+ ndev->ethtool_ops = &sun8i_emac_ethtool_ops;
+
+ priv->ndev = ndev;
+ priv->dev = &pdev->dev;
+
+ ndev->hw_features = NETIF_F_SG | NETIF_F_HIGHDMA;
+ ndev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
+ NETIF_F_RXCSUM;
+ ndev->features |= ndev->hw_features;
+ ndev->hw_features |= NETIF_F_RXFCS;
+ ndev->hw_features |= NETIF_F_RXALL;
+ ndev->hw_features |= NETIF_F_LOOPBACK;
+ ndev->priv_flags |= IFF_UNICAST_FLT;
+
+ ndev->watchdog_timeo = msecs_to_jiffies(5000);
+ netif_carrier_off(ndev);
+
+ /* Benched on OPIPC with 100M, setting more than 256 does not give any
+ * perf boost
+ */
+ priv->nbdesc_rx = 128;
+ priv->nbdesc_tx = 256;
+
+ ret = register_netdev(ndev);
+ if (ret) {
+ dev_err(&pdev->dev, "ERROR: Register %s failed\n", ndev->name);
+ goto probe_err;
+ }
+
+ return 0;
+
+probe_err:
+ free_netdev(ndev);
+ return ret;
+}
+
+static int sun8i_emac_remove(struct platform_device *pdev)
+{
+ struct net_device *ndev = platform_get_drvdata(pdev);
+
+ unregister_netdev(ndev);
+ platform_set_drvdata(pdev, NULL);
+ free_netdev(ndev);
+
+ return 0;
+}
+
+static const struct of_device_id sun8i_emac_of_match_table[] = {
+ { .compatible = "allwinner,sun8i-a83t-emac",
+ .data = (void *)A83T_EMAC },
+ { .compatible = "allwinner,sun8i-h3-emac",
+ .data = (void *)H3_EMAC },
+ { .compatible = "allwinner,sun50i-a64-emac",
+ .data = (void *)A64_EMAC },
+ {}
+};
+MODULE_DEVICE_TABLE(of, sun8i_emac_of_match_table);
+
+static struct platform_driver sun8i_emac_driver = {
+ .probe = sun8i_emac_probe,
+ .remove = sun8i_emac_remove,
+ .driver = {
+ .name = "sun8i-emac",
+ .of_match_table = sun8i_emac_of_match_table,
+ },
+};
+
+module_platform_driver(sun8i_emac_driver);
+
+MODULE_DESCRIPTION("sun8i Ethernet driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("LABBE Corentin <clabbe.montjoie@gmail.com");
diff --git a/drivers/net/ethernet/ti/davinci_mdio.c b/drivers/net/ethernet/ti/davinci_mdio.c
index 33df340..425856f 100644
--- a/drivers/net/ethernet/ti/davinci_mdio.c
+++ b/drivers/net/ethernet/ti/davinci_mdio.c
@@ -106,6 +106,10 @@ struct davinci_mdio_data {
u32 clk_div;
};
+#if IS_ENABLED(CONFIG_OF)
+static void davinci_mdio_update_dt_from_phymask(u32 phy_mask);
+#endif
+
static void davinci_mdio_init_clk(struct davinci_mdio_data *data)
{
u32 mdio_in, div, mdio_out_khz, access_time;
@@ -171,6 +175,12 @@ static int davinci_mdio_reset(struct mii_bus *bus)
/* restrict mdio bus to live phys only */
dev_info(data->dev, "detected phy mask %x\n", ~phy_mask);
phy_mask = ~phy_mask;
+
+ #if IS_ENABLED(CONFIG_OF)
+ if (of_machine_is_compatible("ti,am335x-bone"))
+ davinci_mdio_update_dt_from_phymask(phy_mask);
+ #endif
+
} else {
/* desperately scan all phys */
dev_warn(data->dev, "no live phy, scanning all\n");
@@ -334,6 +344,93 @@ static int davinci_mdio_probe_dt(struct mdio_platform_data *data,
return 0;
}
+static void davinci_mdio_update_dt_from_phymask(u32 phy_mask)
+{
+ int i, len, skip;
+ u32 addr;
+ __be32 *old_phy_p, *phy_id_p;
+ struct property *phy_id_property = NULL;
+ struct device_node *node_p, *slave_p;
+
+ addr = 0;
+
+ for (i = 0; i < PHY_MAX_ADDR; i++) {
+ if ((phy_mask & (1 << i)) == 0) {
+ addr = (u32) i;
+ break;
+ }
+ }
+
+ for_each_compatible_node(node_p, NULL, "ti,cpsw") {
+ for_each_node_by_name(slave_p, "slave") {
+
+#if IS_ENABLED(CONFIG_OF_OVERLAY)
+ skip = 1;
+ // Hack, the overlay fixup "slave" doesn't have phy-mode...
+ old_phy_p = (__be32 *) of_get_property(slave_p, "phy-mode", &len);
+
+ if (len != (sizeof(__be32 *) * 1))
+ {
+ skip = 0;
+ }
+
+ if (skip) {
+#endif
+
+ old_phy_p = (__be32 *) of_get_property(slave_p, "phy_id", &len);
+
+ if (len != (sizeof(__be32 *) * 2))
+ goto err_out;
+
+ if (old_phy_p) {
+
+ phy_id_property = kzalloc(sizeof(*phy_id_property), GFP_KERNEL);
+
+ if (! phy_id_property)
+ goto err_out;
+
+ phy_id_property->length = len;
+ phy_id_property->name = kstrdup("phy_id", GFP_KERNEL);
+ phy_id_property->value = kzalloc(len, GFP_KERNEL);
+
+ if (! phy_id_property->name)
+ goto err_out;
+
+ if (! phy_id_property->value)
+ goto err_out;
+
+ memcpy(phy_id_property->value, old_phy_p, len);
+
+ phy_id_p = (__be32 *) phy_id_property->value + 1;
+
+ *phy_id_p = cpu_to_be32(addr);
+
+ of_update_property(slave_p, phy_id_property);
+ pr_info("davinci_mdio: dt: updated phy_id[%d] from phy_mask[%x]\n", addr, phy_mask);
+
+ ++addr;
+ }
+#if IS_ENABLED(CONFIG_OF_OVERLAY)
+ }
+#endif
+ }
+ }
+
+ return;
+
+err_out:
+
+ if (phy_id_property) {
+ if (phy_id_property->name)
+ kfree(phy_id_property->name);
+
+ if (phy_id_property->value)
+ kfree(phy_id_property->value);
+
+ if (phy_id_property)
+ kfree(phy_id_property);
+ }
+}
#endif
#if IS_ENABLED(CONFIG_OF)
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index ba7b034..7d4169e 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -112,4 +112,11 @@ config OF_OVERLAY
config OF_NUMA
bool
+config OF_CONFIGFS
+ bool "Device Tree Overlay ConfigFS interface"
+ select CONFIGFS_FS
+ depends on OF_OVERLAY
+ help
+ Enable a simple user-space driven DT overlay interface.
+
endif # OF
diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index d7efd9d..aa5ef9d 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -1,4 +1,5 @@
obj-y = base.o device.o platform.o
+obj-$(CONFIG_OF_CONFIGFS) += configfs.o
obj-$(CONFIG_OF_DYNAMIC) += dynamic.o
obj-$(CONFIG_OF_FLATTREE) += fdt.o
obj-$(CONFIG_OF_EARLY_FLATTREE) += fdt_address.o
diff --git a/drivers/of/base.c b/drivers/of/base.c
index a0bccb5..4e9df30 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -30,6 +30,7 @@
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/proc_fs.h>
+#include <linux/rhashtable.h>
#include "of_private.h"
@@ -44,6 +45,18 @@ static const char *of_stdout_options;
struct kset *of_kset;
+const struct rhashtable_params of_phandle_ht_params = {
+ .key_offset = offsetof(struct device_node, phandle), /* base offset */
+ .key_len = sizeof(phandle),
+ .head_offset = offsetof(struct device_node, ht_node),
+ .automatic_shrinking = true,
+};
+
+struct rhashtable *of_phandle_ht;
+
+/* default is false */
+bool of_phandle_ht_is_disabled;
+
/*
* Used to protect the of_aliases, to hold off addition of nodes to sysfs.
* This mutex must be held whenever modifications are being made to the
@@ -163,13 +176,19 @@ int __of_add_property_sysfs(struct device_node *np, struct property *pp)
return rc;
}
-int __of_attach_node_sysfs(struct device_node *np)
+int __of_attach_node_post(struct device_node *np)
{
const char *name;
struct kobject *parent;
struct property *pp;
int rc;
+ if (of_phandle_ht_available()) {
+ rc = of_phandle_ht_insert(np);
+ WARN(rc, "insert to phandle hash fail @%s\n",
+ of_node_full_name(np));
+ }
+
if (!IS_ENABLED(CONFIG_SYSFS))
return 0;
@@ -201,6 +220,18 @@ int __of_attach_node_sysfs(struct device_node *np)
void __init of_core_init(void)
{
struct device_node *np;
+ int ret;
+
+ of_phandle_ht = kzalloc(sizeof(*of_phandle_ht), GFP_KERNEL);
+ if (!of_phandle_ht) {
+ pr_warn("devicetree: Failed to allocate hashtable\n");
+ return;
+ }
+ ret = rhashtable_init(of_phandle_ht, &of_phandle_ht_params);
+ if (ret) {
+ pr_warn("devicetree: Failed to initialize hashtable\n");
+ return;
+ }
/* Create the kset, and register existing nodes */
mutex_lock(&of_mutex);
@@ -211,12 +242,16 @@ void __init of_core_init(void)
return;
}
for_each_of_allnodes(np)
- __of_attach_node_sysfs(np);
+ __of_attach_node_post(np);
mutex_unlock(&of_mutex);
/* Symlink in /proc as required by userspace ABI */
if (of_root)
proc_symlink("device-tree", NULL, "/sys/firmware/devicetree/base");
+
+ ret = of_overlay_init();
+ if (ret != 0)
+ pr_warn("of_init: of_overlay_init failed!\n");
}
static struct property *__of_find_property(const struct device_node *np,
@@ -1100,9 +1135,14 @@ struct device_node *of_find_node_by_phandle(phandle handle)
return NULL;
raw_spin_lock_irqsave(&devtree_lock, flags);
- for_each_of_allnodes(np)
- if (np->phandle == handle)
- break;
+ /* when we're ready use the hash table (and not disabled) */
+ if (of_phandle_ht_available() && !of_phandle_ht_is_disabled)
+ np = of_phandle_ht_lookup(handle);
+ else { /* fallback */
+ for_each_of_allnodes(np)
+ if (np->phandle == handle)
+ break;
+ }
of_node_get(np);
raw_spin_unlock_irqrestore(&devtree_lock, flags);
return np;
diff --git b/drivers/of/configfs.c b/drivers/of/configfs.c
new file mode 100644
index 0000000..c7e999c
--- /dev/null
+++ b/drivers/of/configfs.c
@@ -0,0 +1,307 @@
+/*
+ * Configfs entries for device-tree
+ *
+ * Copyright (C) 2013 - Pantelis Antoniou <panto@antoniou-consulting.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <linux/ctype.h>
+#include <linux/cpu.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <linux/spinlock.h>
+#include <linux/sizes.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/configfs.h>
+#include <linux/types.h>
+#include <linux/stat.h>
+#include <linux/limits.h>
+#include <linux/file.h>
+#include <linux/vmalloc.h>
+#include <linux/firmware.h>
+
+#include "of_private.h"
+
+struct cfs_overlay_item {
+ struct config_item item;
+
+ char path[PATH_MAX];
+
+ const struct firmware *fw;
+ struct device_node *overlay;
+ int ov_id;
+
+ void *dtbo;
+ int dtbo_size;
+};
+
+static int create_overlay(struct cfs_overlay_item *overlay, void *blob)
+{
+ int err;
+
+ /* unflatten the tree */
+ of_fdt_unflatten_tree(blob, NULL, &overlay->overlay);
+ if (overlay->overlay == NULL) {
+ pr_err("%s: failed to unflatten tree\n", __func__);
+ err = -EINVAL;
+ goto out_err;
+ }
+ pr_debug("%s: unflattened OK\n", __func__);
+
+ /* mark it as detached */
+ of_node_set_flag(overlay->overlay, OF_DETACHED);
+
+ /* perform resolution */
+ err = of_resolve_phandles(overlay->overlay);
+ if (err != 0) {
+ pr_err("%s: Failed to resolve tree\n", __func__);
+ goto out_err;
+ }
+ pr_debug("%s: resolved OK\n", __func__);
+
+ err = of_overlay_create(overlay->overlay);
+ if (err < 0) {
+ pr_err("%s: Failed to create overlay (err=%d)\n",
+ __func__, err);
+ goto out_err;
+ }
+ overlay->ov_id = err;
+
+out_err:
+ return err;
+}
+
+static inline struct cfs_overlay_item *to_cfs_overlay_item(
+ struct config_item *item)
+{
+ return item ? container_of(item, struct cfs_overlay_item, item) : NULL;
+}
+
+static ssize_t cfs_overlay_item_path_show(struct config_item *item, char *page)
+{
+ return sprintf(page, "%s\n", to_cfs_overlay_item(item)->path);
+}
+
+static ssize_t cfs_overlay_item_path_store(struct config_item *item,
+ const char *page, size_t count)
+{
+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item);
+ const char *p = page;
+ char *s;
+ int err;
+
+ /* if it's set do not allow changes */
+ if (overlay->path[0] != '\0' || overlay->dtbo_size > 0)
+ return -EPERM;
+
+ /* copy to path buffer (and make sure it's always zero terminated */
+ count = snprintf(overlay->path, sizeof(overlay->path) - 1, "%s", p);
+ overlay->path[sizeof(overlay->path) - 1] = '\0';
+
+ /* strip trailing newlines */
+ s = overlay->path + strlen(overlay->path);
+ while (s > overlay->path && *--s == '\n')
+ *s = '\0';
+
+ pr_debug("%s: path is '%s'\n", __func__, overlay->path);
+
+ err = request_firmware(&overlay->fw, overlay->path, NULL);
+ if (err != 0)
+ goto out_err;
+
+ err = create_overlay(overlay, (void *)overlay->fw->data);
+ if (err < 0)
+ goto out_err;
+
+ return count;
+
+out_err:
+
+ release_firmware(overlay->fw);
+ overlay->fw = NULL;
+
+ overlay->path[0] = '\0';
+ return err;
+}
+
+static ssize_t cfs_overlay_item_status_show(struct config_item *item,
+ char *page)
+{
+ return sprintf(page, "%s\n", to_cfs_overlay_item(item)->ov_id >= 0 ?
+ "applied" : "unapplied");
+}
+
+CONFIGFS_ATTR(cfs_overlay_item_, path);
+CONFIGFS_ATTR_RO(cfs_overlay_item_, status);
+
+static struct configfs_attribute *cfs_overlay_attrs[] = {
+ &cfs_overlay_item_attr_path,
+ &cfs_overlay_item_attr_status,
+ NULL,
+};
+
+ssize_t cfs_overlay_item_dtbo_read(struct config_item *item, void *buf,
+ size_t max_count)
+{
+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item);
+
+ pr_debug("%s: buf=%p max_count=%u\n", __func__,
+ buf, max_count);
+
+ if (overlay->dtbo == NULL)
+ return 0;
+
+ /* copy if buffer provided */
+ if (buf != NULL) {
+ /* the buffer must be large enough */
+ if (overlay->dtbo_size > max_count)
+ return -ENOSPC;
+
+ memcpy(buf, overlay->dtbo, overlay->dtbo_size);
+ }
+
+ return overlay->dtbo_size;
+}
+
+ssize_t cfs_overlay_item_dtbo_write(struct config_item *item, const void *buf,
+ size_t count)
+{
+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item);
+ int err;
+
+ /* if it's set do not allow changes */
+ if (overlay->path[0] != '\0' || overlay->dtbo_size > 0)
+ return -EPERM;
+
+ /* copy the contents */
+ overlay->dtbo = kmemdup(buf, count, GFP_KERNEL);
+ if (overlay->dtbo == NULL)
+ return -ENOMEM;
+
+ overlay->dtbo_size = count;
+
+ err = create_overlay(overlay, overlay->dtbo);
+ if (err < 0)
+ goto out_err;
+
+ return count;
+
+out_err:
+ kfree(overlay->dtbo);
+ overlay->dtbo = NULL;
+ overlay->dtbo_size = 0;
+
+ return err;
+}
+
+CONFIGFS_BIN_ATTR(cfs_overlay_item_, dtbo, NULL, SZ_1M);
+
+static struct configfs_bin_attribute *cfs_overlay_bin_attrs[] = {
+ &cfs_overlay_item_attr_dtbo,
+ NULL,
+};
+
+static void cfs_overlay_release(struct config_item *item)
+{
+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item);
+
+ if (overlay->ov_id >= 0)
+ of_overlay_destroy(overlay->ov_id);
+ if (overlay->fw)
+ release_firmware(overlay->fw);
+ /* kfree with NULL is safe */
+ kfree(overlay->dtbo);
+ kfree(overlay);
+}
+
+static struct configfs_item_operations cfs_overlay_item_ops = {
+ .release = cfs_overlay_release,
+};
+
+static struct config_item_type cfs_overlay_type = {
+ .ct_item_ops = &cfs_overlay_item_ops,
+ .ct_attrs = cfs_overlay_attrs,
+ .ct_bin_attrs = cfs_overlay_bin_attrs,
+ .ct_owner = THIS_MODULE,
+};
+
+static struct config_item *cfs_overlay_group_make_item(
+ struct config_group *group, const char *name)
+{
+ struct cfs_overlay_item *overlay;
+
+ overlay = kzalloc(sizeof(*overlay), GFP_KERNEL);
+ if (!overlay)
+ return ERR_PTR(-ENOMEM);
+ overlay->ov_id = -1;
+
+ config_item_init_type_name(&overlay->item, name, &cfs_overlay_type);
+ return &overlay->item;
+}
+
+static void cfs_overlay_group_drop_item(struct config_group *group,
+ struct config_item *item)
+{
+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item);
+
+ config_item_put(&overlay->item);
+}
+
+static struct configfs_group_operations overlays_ops = {
+ .make_item = cfs_overlay_group_make_item,
+ .drop_item = cfs_overlay_group_drop_item,
+};
+
+static struct config_item_type overlays_type = {
+ .ct_group_ops = &overlays_ops,
+ .ct_owner = THIS_MODULE,
+};
+
+static struct configfs_group_operations of_cfs_ops = {
+ /* empty - we don't allow anything to be created */
+};
+
+static struct config_item_type of_cfs_type = {
+ .ct_group_ops = &of_cfs_ops,
+ .ct_owner = THIS_MODULE,
+};
+
+struct config_group of_cfs_overlay_group;
+
+static struct configfs_subsystem of_cfs_subsys = {
+ .su_group = {
+ .cg_item = {
+ .ci_namebuf = "device-tree",
+ .ci_type = &of_cfs_type,
+ },
+ },
+ .su_mutex = __MUTEX_INITIALIZER(of_cfs_subsys.su_mutex),
+};
+
+static int __init of_cfs_init(void)
+{
+ int ret;
+
+ pr_info("%s\n", __func__);
+
+ config_group_init(&of_cfs_subsys.su_group);
+ config_group_init_type_name(&of_cfs_overlay_group, "overlays",
+ &overlays_type);
+ configfs_add_default_group(&of_cfs_overlay_group,
+ &of_cfs_subsys.su_group);
+
+ ret = configfs_register_subsystem(&of_cfs_subsys);
+ if (ret != 0) {
+ pr_err("%s: failed to register subsys\n", __func__);
+ goto out;
+ }
+ pr_info("%s: OK\n", __func__);
+out:
+ return ret;
+}
+late_initcall(of_cfs_init);
diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c
index 888fdbc..2a89b17 100644
--- a/drivers/of/dynamic.c
+++ b/drivers/of/dynamic.c
@@ -13,6 +13,7 @@
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/proc_fs.h>
+#include <linux/rhashtable.h>
#include "of_private.h"
@@ -43,9 +44,16 @@ void of_node_put(struct device_node *node)
}
EXPORT_SYMBOL(of_node_put);
-void __of_detach_node_sysfs(struct device_node *np)
+void __of_detach_node_post(struct device_node *np)
{
struct property *pp;
+ int rc;
+
+ if (of_phandle_ht_available()) {
+ rc = of_phandle_ht_remove(np);
+ WARN(rc, "remove from phandle hash fail @%s\n",
+ of_node_full_name(np));
+ }
if (!IS_ENABLED(CONFIG_SYSFS))
return;
@@ -253,7 +261,7 @@ int of_attach_node(struct device_node *np)
__of_attach_node(np);
raw_spin_unlock_irqrestore(&devtree_lock, flags);
- __of_attach_node_sysfs(np);
+ __of_attach_node_post(np);
mutex_unlock(&of_mutex);
of_reconfig_notify(OF_RECONFIG_ATTACH_NODE, &rd);
@@ -306,7 +314,7 @@ int of_detach_node(struct device_node *np)
__of_detach_node(np);
raw_spin_unlock_irqrestore(&devtree_lock, flags);
- __of_detach_node_sysfs(np);
+ __of_detach_node_post(np);
mutex_unlock(&of_mutex);
of_reconfig_notify(OF_RECONFIG_DETACH_NODE, &rd);
@@ -397,8 +405,9 @@ struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags)
}
/**
- * __of_node_dup() - Duplicate or create an empty device node dynamically.
- * @fmt: Format string (plus vargs) for new full name of the device node
+ * __of_node_dupv() - Duplicate or create an empty device node dynamically.
+ * @fmt: Format string for new full name of the device node
+ * @vargs: va_list containing the arugments for the node full name
*
* Create an device tree node, either by duplicating an empty node or by allocating
* an empty one suitable for further modification. The node data are
@@ -406,17 +415,15 @@ struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags)
* OF_DETACHED bits set. Returns the newly allocated node or NULL on out of
* memory error.
*/
-struct device_node *__of_node_dup(const struct device_node *np, const char *fmt, ...)
+struct device_node *__of_node_dupv(const struct device_node *np,
+ const char *fmt, va_list vargs)
{
- va_list vargs;
struct device_node *node;
node = kzalloc(sizeof(*node), GFP_KERNEL);
if (!node)
return NULL;
- va_start(vargs, fmt);
node->full_name = kvasprintf(GFP_KERNEL, fmt, vargs);
- va_end(vargs);
if (!node->full_name) {
kfree(node);
return NULL;
@@ -448,6 +455,24 @@ struct device_node *__of_node_dup(const struct device_node *np, const char *fmt,
return NULL;
}
+/**
+ * __of_node_dup() - Duplicate or create an empty device node dynamically.
+ * @fmt: Format string (plus vargs) for new full name of the device node
+ *
+ * See: __of_node_dupv()
+ */
+struct device_node *__of_node_dup(const struct device_node *np,
+ const char *fmt, ...)
+{
+ va_list vargs;
+ struct device_node *node;
+
+ va_start(vargs, fmt);
+ node = __of_node_dupv(np, fmt, vargs);
+ va_end(vargs);
+ return node;
+}
+
static void __of_changeset_entry_destroy(struct of_changeset_entry *ce)
{
of_node_put(ce->np);
@@ -614,10 +639,10 @@ static int __of_changeset_entry_apply(struct of_changeset_entry *ce)
switch (ce->action) {
case OF_RECONFIG_ATTACH_NODE:
- __of_attach_node_sysfs(ce->np);
+ __of_attach_node_post(ce->np);
break;
case OF_RECONFIG_DETACH_NODE:
- __of_detach_node_sysfs(ce->np);
+ __of_detach_node_post(ce->np);
break;
case OF_RECONFIG_ADD_PROPERTY:
/* ignore duplicate names */
@@ -813,3 +838,295 @@ int of_changeset_action(struct of_changeset *ocs, unsigned long action,
return 0;
}
EXPORT_SYMBOL_GPL(of_changeset_action);
+
+/* changeset helpers */
+
+/**
+ * of_changeset_create_device_node - Create an empty device node
+ *
+ * @ocs: changeset pointer
+ * @parent: parent device node
+ * @fmt: format string for the node's full_name
+ * @args: argument list for the format string
+ *
+ * Create an empty device node, marking it as detached and allocated.
+ *
+ * Returns a device node on success, an error encoded pointer otherwise
+ */
+struct device_node *of_changeset_create_device_nodev(
+ struct of_changeset *ocs, struct device_node *parent,
+ const char *fmt, va_list vargs)
+{
+ struct device_node *node;
+
+ node = __of_node_dupv(NULL, fmt, vargs);
+ if (!node)
+ return ERR_PTR(-ENOMEM);
+
+ node->parent = parent;
+ return node;
+}
+EXPORT_SYMBOL_GPL(of_changeset_create_device_nodev);
+
+/**
+ * of_changeset_create_device_node - Create an empty device node
+ *
+ * @ocs: changeset pointer
+ * @parent: parent device node
+ * @fmt: Format string for the node's full_name
+ * ... Arguments
+ *
+ * Create an empty device node, marking it as detached and allocated.
+ *
+ * Returns a device node on success, an error encoded pointer otherwise
+ */
+__printf(3, 4) struct device_node *
+of_changeset_create_device_node(struct of_changeset *ocs,
+ struct device_node *parent, const char *fmt, ...)
+{
+ va_list vargs;
+ struct device_node *node;
+
+ va_start(vargs, fmt);
+ node = of_changeset_create_device_nodev(ocs, parent, fmt, vargs);
+ va_end(vargs);
+ return node;
+}
+EXPORT_SYMBOL_GPL(of_changeset_create_device_node);
+
+/**
+ * __of_changeset_add_property_copy - Create/update a new property copying
+ * name & value
+ *
+ * @ocs: changeset pointer
+ * @np: device node pointer
+ * @name: name of the property
+ * @value: pointer to the value data
+ * @length: length of the value in bytes
+ * @update: True on update operation
+ *
+ * Adds/updates a property to the changeset by making copies of the name & value
+ * entries. The @update parameter controls whether an add or update takes place.
+ *
+ * Returns zero on success, a negative error value otherwise.
+ */
+int __of_changeset_add_update_property_copy(struct of_changeset *ocs,
+ struct device_node *np, const char *name, const void *value,
+ int length, bool update)
+{
+ struct property *prop;
+ char *new_name;
+ void *new_value;
+ int ret = -ENOMEM;
+
+ prop = kzalloc(sizeof(*prop), GFP_KERNEL);
+ if (!prop)
+ return -ENOMEM;
+
+ new_name = kstrdup(name, GFP_KERNEL);
+ if (!new_name)
+ goto out_err;
+
+ /*
+ * NOTE: There is no check for zero length value.
+ * In case of a boolean property, this will allocate a value
+ * of zero bytes. We do this to work around the use
+ * of of_get_property() calls on boolean values.
+ */
+ new_value = kmemdup(value, length, GFP_KERNEL);
+ if (!new_value)
+ goto out_err;
+
+ of_property_set_flag(prop, OF_DYNAMIC);
+
+ prop->name = new_name;
+ prop->value = new_value;
+ prop->length = length;
+
+ if (!update)
+ ret = of_changeset_add_property(ocs, np, prop);
+ else
+ ret = of_changeset_update_property(ocs, np, prop);
+
+ if (!ret)
+ return 0;
+
+out_err:
+ kfree(prop->value);
+ kfree(prop->name);
+ kfree(prop);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(__of_changeset_add_update_property_copy);
+
+/**
+ * of_changeset_add_property_stringf - Create a new formatted string property
+ *
+ * @ocs: changeset pointer
+ * @np: device node pointer
+ * @name: name of the property
+ * @fmt: format of string property
+ * ... arguments of the format string
+ *
+ * Adds a string property to the changeset by making copies of the name
+ * and the formatted value.
+ *
+ * Returns zero on success, a negative error value otherwise.
+ */
+__printf(4, 5) int of_changeset_add_property_stringf(
+ struct of_changeset *ocs, struct device_node *np,
+ const char *name, const char *fmt, ...)
+{
+ va_list vargs;
+ int ret;
+
+ va_start(vargs, fmt);
+ ret = __of_changeset_add_update_property_stringv(ocs, np, name, fmt,
+ vargs, false);
+ va_end(vargs);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(of_changeset_add_property_stringf);
+
+/**
+ * of_changeset_update_property_stringf - Update formatted string property
+ *
+ * @ocs: changeset pointer
+ * @np: device node pointer
+ * @name: name of the property
+ * @fmt: format of string property
+ * ... arguments of the format string
+ *
+ * Updates a string property to the changeset by making copies of the name
+ * and the formatted value.
+ *
+ * Returns zero on success, a negative error value otherwise.
+ */
+int of_changeset_update_property_stringf(
+ struct of_changeset *ocs, struct device_node *np,
+ const char *name, const char *fmt, ...)
+{
+ va_list vargs;
+ int ret;
+
+ va_start(vargs, fmt);
+ ret = __of_changeset_add_update_property_stringv(ocs, np, name, fmt,
+ vargs, true);
+ va_end(vargs);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(of_changeset_update_property_stringf);
+
+/**
+ * __of_changeset_add_update_property_string_list - Create/update a string
+ * list property
+ *
+ * @ocs: changeset pointer
+ * @np: device node pointer
+ * @name: name of the property
+ * @strs: pointer to the string list
+ * @count: string count
+ * @update: True on update operation
+ *
+ * Adds a string list property to the changeset.
+ *
+ * Returns zero on success, a negative error value otherwise.
+ */
+int __of_changeset_add_update_property_string_list(
+ struct of_changeset *ocs, struct device_node *np,
+ const char *name, const char **strs, int count, bool update)
+{
+ int total = 0, i, ret;
+ char *value, *s;
+
+ for (i = 0; i < count; i++) {
+ /* check if it's NULL */
+ if (!strs[i])
+ return -EINVAL;
+ total += strlen(strs[i]) + 1;
+ }
+
+ value = kmalloc(total, GFP_KERNEL);
+ if (!value)
+ return -ENOMEM;
+
+ for (i = 0, s = value; i < count; i++) {
+ /* no need to check for NULL, check above */
+ strcpy(s, strs[i]);
+ s += strlen(strs[i]) + 1;
+ }
+
+ ret = __of_changeset_add_update_property_copy(ocs, np, name, value,
+ total, update);
+
+ kfree(value);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(__of_changeset_add_update_property_string_list);
+
+static struct device_node *
+__of_changeset_node_move_one(struct of_changeset *ocs,
+ struct device_node *np, struct device_node *new_parent)
+{
+ struct device_node *np2;
+ const char *unitname;
+ int err;
+
+ err = of_changeset_detach_node(ocs, np);
+ if (err)
+ return ERR_PTR(err);
+
+ unitname = strrchr(np->full_name, '/');
+ if (!unitname)
+ unitname = np->full_name;
+
+ np2 = __of_node_dup(np, "%s/%s",
+ new_parent->full_name, unitname);
+ if (!np2)
+ return ERR_PTR(-ENOMEM);
+ np2->parent = new_parent;
+
+ err = of_changeset_attach_node(ocs, np2);
+ if (err)
+ return ERR_PTR(err);
+
+ return np2;
+}
+
+/**
+ * of_changeset_node_move_to - Moves a subtree to a new place in
+ * the tree
+ *
+ * @ocs: changeset pointer
+ * @np: device node pointer to be moved
+ * @to: device node of the new parent
+ *
+ * Moves a subtree to a new place in the tree.
+ * Note that a move is a safe operation because the phandles
+ * remain valid.
+ *
+ * Returns zero on success, a negative error value otherwise.
+ */
+int of_changeset_node_move(struct of_changeset *ocs,
+ struct device_node *np, struct device_node *new_parent)
+{
+ struct device_node *npc, *nppc;
+
+ /* move the root first */
+ nppc = __of_changeset_node_move_one(ocs, np, new_parent);
+ if (IS_ERR(nppc))
+ return PTR_ERR(nppc);
+
+ /* move the subtrees next */
+ for_each_child_of_node(np, npc) {
+ nppc = __of_changeset_node_move_one(ocs, npc, nppc);
+ if (IS_ERR(nppc)) {
+ of_node_put(npc);
+ return PTR_ERR(nppc);
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(of_changeset_node_move);
diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h
index 18bbb45..2f906dd 100644
--- a/drivers/of/of_private.h
+++ b/drivers/of/of_private.h
@@ -79,9 +79,9 @@ extern void __of_update_property_sysfs(struct device_node *np,
struct property *newprop, struct property *oldprop);
extern void __of_attach_node(struct device_node *np);
-extern int __of_attach_node_sysfs(struct device_node *np);
+extern int __of_attach_node_post(struct device_node *np);
extern void __of_detach_node(struct device_node *np);
-extern void __of_detach_node_sysfs(struct device_node *np);
+extern void __of_detach_node_post(struct device_node *np);
extern void __of_sysfs_remove_bin_file(struct device_node *np,
struct property *prop);
@@ -95,4 +95,46 @@ extern void __of_sysfs_remove_bin_file(struct device_node *np,
#define for_each_transaction_entry_reverse(_oft, _te) \
list_for_each_entry_reverse(_te, &(_oft)->te_list, node)
+#if defined(CONFIG_OF_OVERLAY)
+extern int of_overlay_init(void);
+#else
+static inline int of_overlay_init(void)
+{
+ return 0;
+}
+#endif
+
+extern const struct rhashtable_params of_phandle_ht_params;
+extern struct rhashtable *of_phandle_ht;
+
+/* for unittest use */
+extern bool of_phandle_ht_is_disabled;
+
+static inline bool of_phandle_ht_available(void)
+{
+ return of_phandle_ht != NULL;
+}
+
+static inline int of_phandle_ht_insert(struct device_node *np)
+{
+ if (!np || !np->phandle)
+ return 0;
+ return rhashtable_insert_fast(of_phandle_ht,
+ &np->ht_node, of_phandle_ht_params);
+}
+
+static inline int of_phandle_ht_remove(struct device_node *np)
+{
+ if (!np || !np->phandle)
+ return 0;
+ return rhashtable_remove_fast(of_phandle_ht,
+ &np->ht_node, of_phandle_ht_params);
+}
+
+static inline struct device_node *of_phandle_ht_lookup(phandle handle)
+{
+ return rhashtable_lookup_fast(of_phandle_ht,
+ &handle, of_phandle_ht_params);
+}
+
#endif /* _LINUX_OF_PRIVATE_H */
diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
index 318dbb5..27e5c21 100644
--- a/drivers/of/overlay.c
+++ b/drivers/of/overlay.c
@@ -22,11 +22,28 @@
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/idr.h>
+#include <linux/sysfs.h>
+#include <linux/atomic.h>
#include "of_private.h"
+/* fwd. decl */
+struct of_overlay;
+struct of_overlay_info;
+
+/* an attribute for each fragment */
+struct fragment_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct kobject *kobj, struct fragment_attribute *fattr,
+ char *buf);
+ ssize_t (*store)(struct kobject *kobj, struct fragment_attribute *fattr,
+ const char *buf, size_t count);
+ struct of_overlay_info *ovinfo;
+};
+
/**
* struct of_overlay_info - Holds a single overlay info
+ * @info: info node that contains the target and overlay
* @target: target of the overlay operation
* @overlay: pointer to the overlay contents node
*
@@ -34,8 +51,13 @@
* records.
*/
struct of_overlay_info {
+ struct of_overlay *ov;
+ struct device_node *info;
struct device_node *target;
struct device_node *overlay;
+ struct attribute_group attr_group;
+ struct attribute *attrs[2];
+ struct fragment_attribute target_attr;
};
/**
@@ -52,11 +74,26 @@ struct of_overlay {
struct list_head node;
int count;
struct of_overlay_info *ovinfo_tab;
+ const struct attribute_group **attr_groups;
struct of_changeset cset;
+ struct kobject kobj;
+ int target_index;
+ struct device_node *target_root;
};
+/* master enable switch; once set to 0 can't be re-enabled */
+static atomic_t ov_enable = ATOMIC_INIT(1);
+
+static int __init of_overlay_disable_setup(char *str __always_unused)
+{
+ atomic_set(&ov_enable, 0);
+ return 1;
+}
+__setup("of_overlay_disable", of_overlay_disable_setup);
+
static int of_overlay_apply_one(struct of_overlay *ov,
struct device_node *target, const struct device_node *overlay);
+static int overlay_removal_is_ok(struct of_overlay *ov);
static int of_overlay_apply_single_property(struct of_overlay *ov,
struct device_node *target, struct property *prop)
@@ -187,30 +224,92 @@ static int of_overlay_apply(struct of_overlay *ov)
/*
* Find the target node using a number of different strategies
- * in order of preference
+ * in order of preference. Respects the target index if available.
*
* "target" property containing the phandle of the target
* "target-path" property containing the path of the target
*/
-static struct device_node *find_target_node(struct device_node *info_node)
+static struct device_node *find_target_node(struct of_overlay *ov,
+ struct device_node *info_node, int index)
{
+ struct device_node *target = NULL, *np;
const char *path;
+ char *newpath;
u32 val;
int ret;
/* first try to go by using the target as a phandle */
- ret = of_property_read_u32(info_node, "target", &val);
- if (ret == 0)
- return of_find_node_by_phandle(val);
+ ret = of_property_read_u32_index(info_node, "target", index, &val);
+ if (ret == 0) {
+ target = of_find_node_by_phandle(val);
+ if (!target) {
+ pr_err("%s: Could not find target phandle 0x%x\n",
+ __func__, val);
+ return NULL;
+ }
+ goto check_root;
+ }
- /* now try to locate by path */
- ret = of_property_read_string(info_node, "target-path", &path);
- if (ret == 0)
- return of_find_node_by_path(path);
+ /* failed, try to locate by path */
+ ret = of_property_read_string_index(info_node, "target-path", index,
+ &path);
+ if (ret == 0) {
+
+ if (!ov->target_root) {
+ target = of_find_node_by_path(path);
+ if (!target)
+ pr_err("%s: Could not find target path \"%s\"\n",
+ __func__, path);
+ return target;
+ }
+
+ /* remove preceding '/' from path; relative path */
+ if (*path == '/') {
+ while (*path == '/')
+ path++;
+
+ newpath = kasprintf(GFP_KERNEL, "%s%s%s",
+ of_node_full_name(ov->target_root),
+ *path ? "/" : "", path);
+ if (!newpath) {
+ pr_err("%s: Could not allocate \"%s%s%s\"\n",
+ __func__,
+ of_node_full_name(ov->target_root),
+ *path ? "/" : "", path);
+ return NULL;
+ }
+ target = of_find_node_by_path(newpath);
+ kfree(newpath);
- pr_err("Failed to find target for node %p (%s)\n",
- info_node, info_node->name);
+ return target;
+ }
+ /* target is an alias, need to check */
+ target = of_find_node_by_path(path);
+ if (!target) {
+ pr_err("%s: Could not find alias \"%s\"\n",
+ __func__, path);
+ return NULL;
+ }
+ goto check_root;
+ }
+
+ return NULL;
+
+check_root:
+ if (!ov->target_root)
+ return target;
+
+ /* got a target, but we have to check it's under target root */
+ for (np = target; np; np = np->parent) {
+ if (np == ov->target_root)
+ return target;
+ }
+ pr_err("%s: target \"%s\" not under target_root \"%s\"\n",
+ __func__, of_node_full_name(target),
+ of_node_full_name(ov->target_root));
+ /* target is not under target_root */
+ of_node_put(target);
return NULL;
}
@@ -235,10 +334,12 @@ static int of_fill_overlay_info(struct of_overlay *ov,
if (ovinfo->overlay == NULL)
goto err_fail;
- ovinfo->target = find_target_node(info_node);
+ ovinfo->target = find_target_node(ov, info_node, ov->target_index);
if (ovinfo->target == NULL)
goto err_fail;
+ ovinfo->info = of_node_get(info_node);
+
return 0;
err_fail:
@@ -249,6 +350,17 @@ static int of_fill_overlay_info(struct of_overlay *ov,
return -EINVAL;
}
+static ssize_t target_show(struct kobject *kobj,
+ struct fragment_attribute *fattr, char *buf)
+{
+ struct of_overlay_info *ovinfo = fattr->ovinfo;
+
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ of_node_full_name(ovinfo->target));
+}
+
+static const struct fragment_attribute target_template_attr = __ATTR_RO(target);
+
/**
* of_build_overlay_info() - Build an overlay info array
* @ov Overlay to build
@@ -266,7 +378,7 @@ static int of_build_overlay_info(struct of_overlay *ov,
{
struct device_node *node;
struct of_overlay_info *ovinfo;
- int cnt, err;
+ int i, cnt, err;
/* worst case; every child is a node */
cnt = 0;
@@ -287,14 +399,45 @@ static int of_build_overlay_info(struct of_overlay *ov,
/* if nothing filled, return error */
if (cnt == 0) {
- kfree(ovinfo);
- return -ENODEV;
+ err = -ENODEV;
+ goto err_free_ovinfo;
}
ov->count = cnt;
ov->ovinfo_tab = ovinfo;
+ ov->attr_groups = kcalloc(cnt + 1,
+ sizeof(struct attribute_group *), GFP_KERNEL);
+ if (ov->attr_groups == NULL) {
+ err = -ENOMEM;
+ goto err_free_ovinfo;
+ }
+
+ for (i = 0; i < cnt; i++) {
+ ovinfo = &ov->ovinfo_tab[i];
+
+ ov->attr_groups[i] = &ovinfo->attr_group;
+
+ ovinfo->target_attr = target_template_attr;
+ /* make lockdep happy */
+ sysfs_attr_init(&ovinfo->target_attr.attr);
+ ovinfo->target_attr.ovinfo = ovinfo;
+
+ ovinfo->attrs[0] = &ovinfo->target_attr.attr;
+ ovinfo->attrs[1] = NULL;
+
+ /* NOTE: direct reference to the full_name */
+ ovinfo->attr_group.name = kbasename(ovinfo->info->full_name);
+ ovinfo->attr_group.attrs = ovinfo->attrs;
+
+ }
+ ov->attr_groups[i] = NULL;
+
return 0;
+
+err_free_ovinfo:
+ kfree(ovinfo);
+ return err;
}
/**
@@ -311,46 +454,201 @@ static int of_free_overlay_info(struct of_overlay *ov)
struct of_overlay_info *ovinfo;
int i;
+ /* free attribute groups space */
+ kfree(ov->attr_groups);
+
/* do it in reverse */
for (i = ov->count - 1; i >= 0; i--) {
ovinfo = &ov->ovinfo_tab[i];
of_node_put(ovinfo->target);
of_node_put(ovinfo->overlay);
+ of_node_put(ovinfo->info);
}
kfree(ov->ovinfo_tab);
return 0;
}
+static int of_overlay_add_symbols(
+ struct device_node *tree,
+ struct of_overlay *ov)
+{
+ struct of_overlay_info *ovinfo;
+ struct device_node *root_sym = NULL;
+ struct device_node *child = NULL;
+ struct property *prop;
+ const char *path, *s;
+ char *new_path;
+ int i, len, err;
+
+ /* both may fail (if no fixups are required) */
+ root_sym = of_find_node_by_path("/__symbols__");
+ child = of_get_child_by_name(tree, "__symbols__");
+
+ err = 0;
+ /* do nothing if either is NULL */
+ if (!root_sym || !child)
+ goto out;
+
+ for_each_property_of_node(child, prop) {
+
+ /* skip properties added automatically */
+ if (of_prop_cmp(prop->name, "name") == 0)
+ continue;
+
+ err = of_property_read_string(child,
+ prop->name, &path);
+ if (err != 0) {
+ pr_err("Could not find symbol '%s'\n", prop->name);
+ continue;
+ }
+
+ /* now find fragment index */
+ s = path;
+
+ /* compare paths to find fragment index */
+ for (i = 0, ovinfo = NULL, len = -1; i < ov->count; i++) {
+ ovinfo = &ov->ovinfo_tab[i];
+
+ pr_debug("#%d: overlay->name=%s target->name=%s\n",
+ i, ovinfo->overlay->full_name,
+ ovinfo->target->full_name);
+
+ len = strlen(ovinfo->overlay->full_name);
+ if (strncasecmp(path, ovinfo->overlay->full_name,
+ len) == 0 && path[len] == '/')
+ break;
+ }
+
+ if (i >= ov->count)
+ continue;
+
+ pr_debug("found target at #%d\n", i);
+ new_path = kasprintf(GFP_KERNEL, "%s%s",
+ ovinfo->target->full_name,
+ path + len);
+ if (!new_path) {
+ pr_err("Failed to allocate propname for \"%s\"\n",
+ prop->name);
+ err = -ENOMEM;
+ break;
+ }
+
+ err = of_changeset_add_property_string(&ov->cset, root_sym,
+ prop->name, new_path);
+
+ /* free always */
+ kfree(new_path);
+
+ if (err) {
+ pr_err("Failed to add property for \"%s\"\n",
+ prop->name);
+ break;
+ }
+ }
+
+out:
+ of_node_put(child);
+ of_node_put(root_sym);
+
+ return err;
+}
+
static LIST_HEAD(ov_list);
static DEFINE_IDR(ov_idr);
-/**
- * of_overlay_create() - Create and apply an overlay
- * @tree: Device node containing all the overlays
- *
- * Creates and applies an overlay while also keeping track
- * of the overlay in a list. This list can be used to prevent
- * illegal overlay removals.
- *
- * Returns the id of the created overlay, or a negative error number
- */
-int of_overlay_create(struct device_node *tree)
+static inline struct of_overlay *kobj_to_overlay(struct kobject *kobj)
+{
+ return container_of(kobj, struct of_overlay, kobj);
+}
+
+void of_overlay_release(struct kobject *kobj)
+{
+ struct of_overlay *ov = kobj_to_overlay(kobj);
+
+ of_node_put(ov->target_root);
+ kfree(ov);
+}
+
+static ssize_t enable_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&ov_enable));
+}
+
+static ssize_t enable_store(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf, size_t count)
+{
+ int ret;
+ bool new_enable;
+
+ ret = strtobool(buf, &new_enable);
+ if (ret != 0)
+ return ret;
+ /* if we've disabled it, no going back */
+ if (atomic_read(&ov_enable) == 0)
+ return -EPERM;
+ atomic_set(&ov_enable, (int)new_enable);
+ return count;
+}
+
+static struct kobj_attribute enable_attr = __ATTR_RW(enable);
+
+static const struct attribute *overlay_global_attrs[] = {
+ &enable_attr.attr,
+ NULL
+};
+
+static ssize_t can_remove_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct of_overlay *ov = kobj_to_overlay(kobj);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", overlay_removal_is_ok(ov));
+}
+
+static struct kobj_attribute can_remove_attr = __ATTR_RO(can_remove);
+
+static struct attribute *overlay_attrs[] = {
+ &can_remove_attr.attr,
+ NULL
+};
+
+static struct kobj_type of_overlay_ktype = {
+ .release = of_overlay_release,
+ .sysfs_ops = &kobj_sysfs_ops, /* default kobj sysfs ops */
+ .default_attrs = overlay_attrs,
+};
+
+static struct kset *ov_kset;
+
+static int __of_overlay_create(struct device_node *tree,
+ int target_index, struct device_node *target_root)
{
struct of_overlay *ov;
int err, id;
+ /* administratively disabled */
+ if (!atomic_read(&ov_enable))
+ return -EPERM;
+
/* allocate the overlay structure */
ov = kzalloc(sizeof(*ov), GFP_KERNEL);
if (ov == NULL)
return -ENOMEM;
ov->id = -1;
+ ov->target_index = target_index;
+ ov->target_root = of_node_get(target_root);
+
INIT_LIST_HEAD(&ov->node);
of_changeset_init(&ov->cset);
+ /* initialize kobject */
+ kobject_init(&ov->kobj, &of_overlay_ktype);
+
mutex_lock(&of_mutex);
id = idr_alloc(&ov_idr, ov, 0, 0, GFP_KERNEL);
@@ -373,19 +671,44 @@ int of_overlay_create(struct device_node *tree)
if (err)
goto err_abort_trans;
+ err = of_overlay_add_symbols(tree, ov);
+ if (err) {
+ pr_err("%s: of_overlay_add_symbols() failed for tree@%s\n",
+ __func__, tree->full_name);
+ goto err_abort_trans;
+ }
+
/* apply the changeset */
err = __of_changeset_apply(&ov->cset);
if (err)
goto err_revert_overlay;
+ ov->kobj.kset = ov_kset;
+ err = kobject_add(&ov->kobj, NULL, "%d", id);
+ if (err != 0) {
+ pr_err("%s: kobject_add() failed for tree@%s\n",
+ __func__, tree->full_name);
+ goto err_cancel_overlay;
+ }
+
+ err = sysfs_create_groups(&ov->kobj, ov->attr_groups);
+ if (err != 0) {
+ pr_err("%s: sysfs_create_groups() failed for tree@%s\n",
+ __func__, tree->full_name);
+ goto err_remove_kobj;
+ }
+
/* add to the tail of the overlay list */
list_add_tail(&ov->node, &ov_list);
mutex_unlock(&of_mutex);
return id;
-
+err_remove_kobj:
+ kobject_put(&ov->kobj);
+err_cancel_overlay:
+ of_changeset_revert(&ov->cset);
err_revert_overlay:
err_abort_trans:
of_free_overlay_info(ov);
@@ -393,13 +716,66 @@ int of_overlay_create(struct device_node *tree)
idr_remove(&ov_idr, ov->id);
err_destroy_trans:
of_changeset_destroy(&ov->cset);
+ of_node_put(ov->target_root);
kfree(ov);
mutex_unlock(&of_mutex);
return err;
}
+
+/**
+ * of_overlay_create() - Create and apply an overlay
+ * @tree: Device node containing all the overlays
+ *
+ * Creates and applies an overlay while also keeping track
+ * of the overlay in a list. This list can be used to prevent
+ * illegal overlay removals.
+ *
+ * Returns the id of the created overlay, or a negative error number
+ */
+int of_overlay_create(struct device_node *tree)
+{
+ return __of_overlay_create(tree, 0, NULL);
+}
EXPORT_SYMBOL_GPL(of_overlay_create);
+/**
+ * of_overlay_create_target_index() - Create and apply an overlay
+ * @tree: Device node containing all the overlays
+ * @index: Index to use in the target properties
+ *
+ * Creates and applies an overlay while also keeping track
+ * of the overlay in a list. This list can be used to prevent
+ * illegal overlay removals.
+ *
+ * Returns the id of the created overlay, or a negative error number
+ */
+int of_overlay_create_target_index(struct device_node *tree, int index)
+{
+ return __of_overlay_create(tree, index, NULL);
+}
+EXPORT_SYMBOL_GPL(of_overlay_create_target_index);
+
+/**
+ * of_overlay_create_target_root() - Create and apply an overlay
+ * under which will be limited to target_root
+ * @tree: Device node containing all the overlays
+ * @target_root: Target root for the overlay.
+ *
+ * Creates and applies an overlay while also keeping track
+ * of the overlay in a list. This list can be used to prevent
+ * illegal overlay removals. The overlay is only allowed to
+ * target nodes under the target_root node.
+ *
+ * Returns the id of the created overlay, or an negative error number
+ */
+int of_overlay_create_target_root(struct device_node *tree,
+ struct device_node *target_root)
+{
+ return __of_overlay_create(tree, 0, target_root);
+}
+EXPORT_SYMBOL_GPL(of_overlay_create_target_root);
+
/* check whether the given node, lies under the given tree */
static int overlay_subtree_check(struct device_node *tree,
struct device_node *dn)
@@ -500,11 +876,13 @@ int of_overlay_destroy(int id)
list_del(&ov->node);
+ sysfs_remove_groups(&ov->kobj, ov->attr_groups);
__of_changeset_revert(&ov->cset);
of_free_overlay_info(ov);
idr_remove(&ov_idr, id);
of_changeset_destroy(&ov->cset);
- kfree(ov);
+
+ kobject_put(&ov->kobj);
err = 0;
@@ -534,7 +912,7 @@ int of_overlay_destroy_all(void)
__of_changeset_revert(&ov->cset);
of_free_overlay_info(ov);
idr_remove(&ov_idr, ov->id);
- kfree(ov);
+ kobject_put(&ov->kobj);
}
mutex_unlock(&of_mutex);
@@ -542,3 +920,18 @@ int of_overlay_destroy_all(void)
return 0;
}
EXPORT_SYMBOL_GPL(of_overlay_destroy_all);
+
+/* called from of_init() */
+int of_overlay_init(void)
+{
+ int rc;
+
+ ov_kset = kset_create_and_add("overlays", NULL, &of_kset->kobj);
+ if (!ov_kset)
+ return -ENOMEM;
+
+ rc = sysfs_create_files(&ov_kset->kobj, overlay_global_attrs);
+ WARN(rc, "%s: error adding global attributes\n", __func__);
+
+ return rc;
+}
diff --git a/drivers/of/unittest-data/testcases.dts b/drivers/of/unittest-data/testcases.dts
index 12f7c3d..a6ded1b 100644
--- a/drivers/of/unittest-data/testcases.dts
+++ b/drivers/of/unittest-data/testcases.dts
@@ -75,5 +75,15 @@
target = <0x00000000>;
};
};
+ overlay16 {
+ fragment@0 {
+ target = <0x00000000 0x00000004>;
+ };
+ };
+ overlay18 {
+ fragment@0 {
+ target = <0x00000000>;
+ };
+ };
};
}; };
diff --git a/drivers/of/unittest-data/tests-overlay.dtsi b/drivers/of/unittest-data/tests-overlay.dtsi
index 02ba56c..170b04d 100644
--- a/drivers/of/unittest-data/tests-overlay.dtsi
+++ b/drivers/of/unittest-data/tests-overlay.dtsi
@@ -110,6 +110,30 @@
};
};
};
+
+ unittest16: test-unittest16 {
+ compatible = "unittest";
+ status = "disabled";
+ reg = <16>;
+ };
+
+ unittest17: test-unittest17 {
+ compatible = "unittest";
+ status = "disabled";
+ reg = <17>;
+ };
+
+ unittest18: test-unittest18 {
+ compatible = "unittest";
+ status = "disabled";
+ reg = <18>;
+ };
+
+ unittest19: test-unittest19 {
+ compatible = "unittest";
+ status = "disabled";
+ reg = <19>;
+ };
};
};
@@ -325,5 +349,44 @@
};
};
+ /* test enable using indirect functionality */
+ overlay16 {
+ fragment@0 {
+ target = <&unittest17>, <&unittest16>;
+ __overlay__ {
+ status = "okay";
+ };
+ };
+ };
+
+ /* test enable using target root (relative path) */
+ overlay17 {
+ fragment@0 {
+ target-path = "/";
+ __overlay__ {
+ status = "okay";
+ };
+ };
+ };
+
+ /* test enable using target phandle */
+ overlay18 {
+ fragment@0 {
+ target = <&unittest18>;
+ __overlay__ {
+ status = "okay";
+ };
+ };
+ };
+
+ /* test trying to enable out of root (should fail) */
+ overlay19 {
+ fragment@0 {
+ target = <&unittest19>;
+ __overlay__ {
+ status = "okay";
+ };
+ };
+ };
};
};
diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c
index 53c83d6..b560ae7 100644
--- a/drivers/of/unittest.c
+++ b/drivers/of/unittest.c
@@ -24,6 +24,9 @@
#include <linux/bitops.h>
+#include <linux/timekeeping.h>
+#include <linux/random.h>
+
#include "of_private.h"
static struct unittest_results {
@@ -542,6 +545,59 @@ static void __init of_unittest_changeset(void)
#endif
}
+static void __init of_unittest_changeset_helper(void)
+{
+#ifdef CONFIG_OF_DYNAMIC
+ struct device_node *n1, *n2, *n21, *parent, *np;
+ struct of_changeset chgset;
+
+ of_changeset_init(&chgset);
+
+ parent = of_find_node_by_path("/testcase-data/changeset");
+
+ unittest(parent, "testcase setup failure\n");
+ n1 = of_changeset_create_device_node(&chgset,
+ parent, "/testcase-data/changeset/n1");
+ unittest(n1, "testcase setup failure\n");
+ n2 = of_changeset_create_device_node(&chgset,
+ parent, "/testcase-data/changeset/n2");
+ unittest(n2, "testcase setup failure\n");
+ n21 = of_changeset_create_device_node(&chgset, n2, "%s/%s",
+ "/testcase-data/changeset/n2", "n21");
+ unittest(n21, "testcase setup failure\n");
+
+ unittest(!of_changeset_add_property_string(&chgset, parent,
+ "prop-add", "foo"), "fail add prop\n");
+
+ unittest(!of_changeset_attach_node(&chgset, n1), "fail n1 attach\n");
+ unittest(!of_changeset_attach_node(&chgset, n2), "fail n2 attach\n");
+ unittest(!of_changeset_attach_node(&chgset, n21), "fail n21 attach\n");
+
+ unittest(!of_changeset_apply(&chgset), "apply failed\n");
+
+ /* Make sure node names are constructed correctly */
+ np = of_find_node_by_path("/testcase-data/changeset/n1");
+ unittest(np, "'%s' not added\n", n1->full_name);
+ of_node_put(np);
+
+ /* Make sure node names are constructed correctly */
+ np = of_find_node_by_path("/testcase-data/changeset/n2");
+ unittest(np, "'%s' not added\n", n2->full_name);
+ of_node_put(np);
+
+ np = of_find_node_by_path("/testcase-data/changeset/n2/n21");
+ unittest(np, "'%s' not added\n", n21->full_name);
+ of_node_put(np);
+
+ unittest(!of_changeset_revert(&chgset), "revert failed\n");
+
+ of_changeset_destroy(&chgset);
+
+ of_node_put(parent);
+#endif
+}
+
+
static void __init of_unittest_parse_interrupts(void)
{
struct device_node *np;
@@ -877,7 +933,7 @@ static int attach_node_and_children(struct device_node *np)
of_node_clear_flag(np, OF_DETACHED);
raw_spin_unlock_irqrestore(&devtree_lock, flags);
- __of_attach_node_sysfs(np);
+ __of_attach_node_post(np);
mutex_unlock(&of_mutex);
while (child) {
@@ -935,7 +991,7 @@ static int __init unittest_data_add(void)
if (!of_root) {
of_root = unittest_data_node;
for_each_of_allnodes(np)
- __of_attach_node_sysfs(np);
+ __of_attach_node_post(np);
of_aliases = of_find_node_by_path("/aliases");
of_chosen = of_find_node_by_path("/chosen");
return 0;
@@ -1854,6 +1910,273 @@ static inline void of_unittest_overlay_i2c_15(void) { }
#endif
+static void of_unittest_overlay_16(void)
+{
+ int ret;
+ int overlay_nr = 16;
+ int unittest_nr = 16;
+ enum overlay_type ovtype = PDEV_OVERLAY;
+ int before = 0;
+ int after = 1;
+ struct device_node *np = NULL;
+ int id = -1;
+
+ /* unittest device must not be in before state */
+ if (of_unittest_device_exists(unittest_nr, ovtype) != before) {
+ unittest(0, "overlay @\"%s\" with device @\"%s\" %s\n",
+ overlay_path(overlay_nr),
+ unittest_path(unittest_nr, ovtype),
+ !before ? "enabled" : "disabled");
+ return;
+ }
+
+ np = of_find_node_by_path(overlay_path(overlay_nr));
+ if (np == NULL) {
+ unittest(0, "could not find overlay node @\"%s\"\n",
+ overlay_path(overlay_nr));
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* unittest16 is at index #1 */
+ ret = of_overlay_create_target_index(np, 1);
+ if (ret < 0) {
+ unittest(0, "could not create overlay from \"%s\"\n",
+ overlay_path(overlay_nr));
+ goto out;
+ }
+ id = ret;
+ of_unittest_track_overlay(id);
+
+ ret = 0;
+
+out:
+ of_node_put(np);
+
+ if (ret)
+ return;
+
+ /* unittest device must be to set to after state */
+ if (of_unittest_device_exists(unittest_nr, ovtype) != after) {
+ unittest(0, "overlay @\"%s\" failed to create @\"%s\" %s\n",
+ overlay_path(overlay_nr),
+ unittest_path(unittest_nr, ovtype),
+ !after ? "enabled" : "disabled");
+ return;
+ }
+
+ unittest(1, "overlay test %d passed\n", 16);
+}
+
+static void of_unittest_overlay_17(void)
+{
+ int ret;
+ int overlay_nr = 17;
+ int unittest_nr = 17;
+ enum overlay_type ovtype = PDEV_OVERLAY;
+ int before = 0;
+ int after = 1;
+ const char *root_path;
+ struct device_node *np = NULL, *target_root = NULL;
+ int id = -1;
+
+ /* unittest device must not be in before state */
+ if (of_unittest_device_exists(unittest_nr, ovtype) != before) {
+ unittest(0, "overlay @\"%s\" with device @\"%s\" %s\n",
+ overlay_path(overlay_nr),
+ unittest_path(unittest_nr, ovtype),
+ !before ? "enabled" : "disabled");
+ return;
+ }
+
+ np = of_find_node_by_path(overlay_path(overlay_nr));
+ if (np == NULL) {
+ unittest(0, "could not find overlay node @\"%s\"\n",
+ overlay_path(overlay_nr));
+ ret = -EINVAL;
+ goto out;
+ }
+
+ root_path = "/testcase-data/overlay-node/test-bus/test-unittest17";
+ target_root = of_find_node_by_path(root_path);
+ if (!target_root) {
+ unittest(0, "could not find target_root node @\"%s\"\n",
+ root_path);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = of_overlay_create_target_root(np, target_root);
+ of_node_put(target_root);
+
+ if (ret < 0) {
+ unittest(0, "could not create overlay from \"%s\"\n",
+ overlay_path(overlay_nr));
+ goto out;
+ }
+ id = ret;
+ of_unittest_track_overlay(id);
+
+ ret = 0;
+
+out:
+ of_node_put(np);
+
+ if (ret)
+ return;
+
+ /* unittest device must be to set to after state */
+ if (of_unittest_device_exists(unittest_nr, ovtype) != after) {
+ unittest(0, "overlay @\"%s\" failed to create @\"%s\" %s\n",
+ overlay_path(overlay_nr),
+ unittest_path(unittest_nr, ovtype),
+ !after ? "enabled" : "disabled");
+ return;
+ }
+
+ unittest(1, "overlay test %d passed\n", 17);
+}
+
+static void of_unittest_overlay_18(void)
+{
+ int ret;
+ int overlay_nr = 18;
+ int unittest_nr = 18;
+ enum overlay_type ovtype = PDEV_OVERLAY;
+ int before = 0;
+ int after = 1;
+ const char *root_path;
+ struct device_node *np = NULL, *target_root = NULL;
+ int id = -1;
+
+ /* unittest device must not be in before state */
+ if (of_unittest_device_exists(unittest_nr, ovtype) != before) {
+ unittest(0, "overlay @\"%s\" with device @\"%s\" %s\n",
+ overlay_path(overlay_nr),
+ unittest_path(unittest_nr, ovtype),
+ !before ? "enabled" : "disabled");
+ return;
+ }
+
+ np = of_find_node_by_path(overlay_path(overlay_nr));
+ if (np == NULL) {
+ unittest(0, "could not find overlay node @\"%s\"\n",
+ overlay_path(overlay_nr));
+ ret = -EINVAL;
+ goto out;
+ }
+
+ root_path = "/testcase-data/overlay-node/test-bus/test-unittest18";
+ target_root = of_find_node_by_path(root_path);
+ if (!target_root) {
+ unittest(0, "could not find target_root node @\"%s\"\n",
+ root_path);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = of_overlay_create_target_root(np, target_root);
+ of_node_put(target_root);
+
+ if (ret < 0) {
+ unittest(0, "could not create overlay from \"%s\"\n",
+ overlay_path(overlay_nr));
+ goto out;
+ }
+ id = ret;
+ of_unittest_track_overlay(id);
+
+ ret = 0;
+
+out:
+ of_node_put(np);
+
+ if (ret)
+ return;
+
+ /* unittest device must be to set to after state */
+ if (of_unittest_device_exists(unittest_nr, ovtype) != after) {
+ unittest(0, "overlay @\"%s\" failed to create @\"%s\" %s\n",
+ overlay_path(overlay_nr),
+ unittest_path(unittest_nr, ovtype),
+ !after ? "enabled" : "disabled");
+ return;
+ }
+
+ unittest(1, "overlay test %d passed\n", 18);
+}
+
+static void of_unittest_overlay_19(void)
+{
+ int ret;
+ int overlay_nr = 19;
+ int unittest_nr = 19;
+ enum overlay_type ovtype = PDEV_OVERLAY;
+ int before = 0;
+ int after = 0;
+ const char *root_path;
+ struct device_node *np = NULL, *target_root = NULL;
+ int id = -1;
+
+ /* unittest device must not be in before state */
+ if (of_unittest_device_exists(unittest_nr, ovtype) != before) {
+ unittest(0, "overlay @\"%s\" with device @\"%s\" %s\n",
+ overlay_path(overlay_nr),
+ unittest_path(unittest_nr, ovtype),
+ !before ? "enabled" : "disabled");
+ return;
+ }
+
+ np = of_find_node_by_path(overlay_path(overlay_nr));
+ if (np == NULL) {
+ unittest(0, "could not find overlay node @\"%s\"\n",
+ overlay_path(overlay_nr));
+ ret = -EINVAL;
+ goto out;
+ }
+
+ root_path = "/testcase-data/overlay-node/test-bus/test-unittest19";
+ target_root = of_find_node_by_path(root_path);
+ if (!target_root) {
+ unittest(0, "could not find target_root node @\"%s\"\n",
+ root_path);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = of_overlay_create_target_root(np, target_root);
+ of_node_put(target_root);
+
+ if (ret >= 0) {
+ unittest(0, "created overlay from \"%s\" while we shouldn't\n",
+ overlay_path(overlay_nr));
+ id = ret;
+ of_unittest_track_overlay(id);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = 0;
+
+out:
+ of_node_put(np);
+
+ if (ret)
+ return;
+
+ /* unittest device must be to set to after state */
+ if (of_unittest_device_exists(unittest_nr, ovtype) != after) {
+ unittest(0, "overlay @\"%s\" failed to create @\"%s\" %s\n",
+ overlay_path(overlay_nr),
+ unittest_path(unittest_nr, ovtype),
+ !after ? "enabled" : "disabled");
+ return;
+ }
+
+ unittest(1, "overlay test %d passed\n", 16);
+}
+
+
static void __init of_unittest_overlay(void)
{
struct device_node *bus_np = NULL;
@@ -1904,6 +2227,12 @@ static void __init of_unittest_overlay(void)
of_unittest_overlay_10();
of_unittest_overlay_11();
+ of_unittest_overlay_16();
+
+ of_unittest_overlay_17();
+ of_unittest_overlay_18();
+ of_unittest_overlay_19();
+
#if IS_BUILTIN(CONFIG_I2C)
if (unittest(of_unittest_overlay_i2c_init() == 0, "i2c init failed\n"))
goto out;
@@ -1926,6 +2255,70 @@ static void __init of_unittest_overlay(void)
static inline void __init of_unittest_overlay(void) { }
#endif
+#define PHANDLE_LOOKUPS 1000
+
+static void __init of_unittest_phandle_hash(void)
+{
+ struct device_node *node;
+ phandle max_phandle;
+ u32 ph;
+ unsigned long flags;
+ int i, j, total;
+ ktime_t start, end;
+ s64 dur[2];
+ int dec, frac;
+
+ /* test only available when hashing is available */
+ if (!of_phandle_ht_available()) {
+ pr_warn("phandle hash test requires hash to be initialized\n");
+ return;
+ }
+
+ /* find the maximum phandle of the tree */
+ raw_spin_lock_irqsave(&devtree_lock, flags);
+ max_phandle = 0;
+ total = 0;
+ for_each_of_allnodes(node) {
+ if (node->phandle != (phandle)-1U &&
+ node->phandle > max_phandle)
+ max_phandle = node->phandle;
+ total++;
+ }
+ raw_spin_unlock_irqrestore(&devtree_lock, flags);
+ max_phandle++;
+
+ pr_debug("phandle: max-phandle #%u, #%d total nodes\n",
+ (u32)max_phandle, total);
+
+ /* perform random lookups using the hash */
+ for (j = 0; j < 2; j++) {
+
+ /* disabled for pass #0, enabled for pass #1 */
+ of_phandle_ht_is_disabled = j == 0;
+
+ start = ktime_get_raw();
+ for (i = 0; i < PHANDLE_LOOKUPS; i++) {
+ ph = prandom_u32() % max_phandle;
+ node = of_find_node_by_phandle(ph);
+ of_node_put(node);
+ }
+ end = ktime_get_raw();
+
+ dur[j] = ktime_to_us(end) - ktime_to_us(start);
+ pr_debug("#%d lookups in %lld us (%s)\n",
+ PHANDLE_LOOKUPS, dur[j],
+ j == 0 ? "original" : "hashed");
+ }
+
+ unittest(dur[0] > dur[1], "Non hashing phandles are faster!?");
+
+ dec = (int)div64_s64(dur[0] * 10 + 5, dur[1]);
+ frac = dec % 10;
+ dec /= 10;
+ pr_info("the hash method is %d.%d times faster than the original\n",
+ dec, frac);
+}
+
static int __init of_unittest(void)
{
struct device_node *np;
@@ -1954,11 +2347,13 @@ static int __init of_unittest(void)
of_unittest_property_string();
of_unittest_property_copy();
of_unittest_changeset();
+ of_unittest_changeset_helper();
of_unittest_parse_interrupts();
of_unittest_parse_interrupts_extended();
of_unittest_match_node();
of_unittest_platform_populate();
of_unittest_overlay();
+ of_unittest_phandle_hash();
/* Double check linkage after removing testcase data */
of_unittest_check_tree_linkage();
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 0e75d94..f8cef83 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -179,6 +179,18 @@ config PINCTRL_ST
select PINCONF
select GPIOLIB_IRQCHIP
+config PINCTRL_TI_IODELAY
+ bool "TI IODelay Module pinconf driver"
+ depends on OF
+ select PINCONF
+ select GENERIC_PINCONF
+ select REGMAP_MMIO
+ help
+ Say Y here to support Texas Instruments' IODelay pinconf driver.
+ IODelay module is used for the DRA7 SoC family. This driver is in
+ addition to PINCTRL_SINGLE which controls the mux.
+
+
config PINCTRL_TZ1090
bool "Toumaz Xenif TZ1090 pin control driver"
depends on SOC_TZ1090
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 11bad37..23e118e 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o
obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o
obj-$(CONFIG_PINCTRL_SIRF) += sirf/
obj-$(CONFIG_ARCH_TEGRA) += tegra/
+obj-$(CONFIG_PINCTRL_TI_IODELAY)+= pinctrl-ti-iodelay.o
obj-$(CONFIG_PINCTRL_TZ1090) += pinctrl-tz1090.o
obj-$(CONFIG_PINCTRL_TZ1090_PDC) += pinctrl-tz1090-pdc.o
obj-$(CONFIG_PINCTRL_U300) += pinctrl-u300.o
diff --git b/drivers/pinctrl/pinctrl-ti-iodelay.c b/drivers/pinctrl/pinctrl-ti-iodelay.c
new file mode 100644
index 0000000..8d33414
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-ti-iodelay.c
@@ -0,0 +1,968 @@
+/*
+ * Support for configuration of IO Delay module found on Texas Instruments SoCs
+ * such as DRA7
+ *
+ * Copyright (C) 2015 Texas Instruments, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#define IODELAY_REG_NAME_LEN ((sizeof(u32) * 2) + 3)
+#define DRIVER_NAME "ti-io-delay"
+/* Should I change this? Abuse? */
+#define IODELAY_MUX_PINS_NAME "pinctrl-single,pins"
+
+/* Device tree match, populated later */
+static const struct of_device_id ti_iodelay_of_match[];
+
+/**
+ * struct ti_iodelay_conf_vals - Description of each configuration parameters.
+ * @offset: Configuration register offset
+ * @a_delay: Agnostic Delay (in ps)
+ * @g_delay: Gnostic Delay (in ps)
+ */
+struct ti_iodelay_conf_vals {
+ u16 offset;
+ u16 a_delay;
+ u16 g_delay;
+};
+
+/**
+ * struct ti_iodelay_reg_data - Describes the registers for the IOdelay instance
+ * @signature_mask: Conf reg- mask for the signature bits
+ * @signature_value: Conf reg- signature value to be written (see TRM)
+ * @lock_mask: Conf reg- mask for the lock bits
+ * @lock_val: Conf reg- lock value for the lock bits (see TRM)
+ * @unlock_val: Conf reg- unlock value for the lock bits (see TRM)
+ * @binary_data_coarse_mask: Conf reg- coarse mask (see TRM)
+ * @binary_data_fine_mask: Conf reg- fine mask (see TRM)
+ * @reg_refclk_offset: Refclk register offset
+ * @refclk_period_mask: Refclk mask
+ * @reg_coarse_offset: Coarse register configuration offset
+ * @coarse_delay_count_mask: Coarse delay count mask
+ * @coarse_ref_count_mask: Coarse ref count mask
+ * @reg_fine_offset: Fine register configuration offset
+ * @fine_delay_count_mask: Fine delay count mask
+ * @fine_ref_count_mask: Fine ref count mask
+ * @reg_global_lock_offset: Global(for the IOdelay module) lock register offset
+ * @global_lock_mask: Lock mask
+ * @global_unlock_val: unlock value
+ * @global_lock_val: lock value
+ * @reg_start_offset: Where does the configuration registers start?
+ * @regmap_config: Regmap configuration for the IODelay region
+ */
+struct ti_iodelay_reg_data {
+ u32 signature_mask;
+ u32 signature_value;
+ u32 lock_mask;
+ u32 lock_val;
+ u32 unlock_val;
+ u32 binary_data_coarse_mask;
+ u32 binary_data_fine_mask;
+
+ u32 reg_refclk_offset;
+ u32 refclk_period_mask;
+
+ u32 reg_coarse_offset;
+ u32 coarse_delay_count_mask;
+ u32 coarse_ref_count_mask;
+
+ u32 reg_fine_offset;
+ u32 fine_delay_count_mask;
+ u32 fine_ref_count_mask;
+
+ u32 reg_global_lock_offset;
+ u32 global_lock_mask;
+ u32 global_unlock_val;
+ u32 global_lock_val;
+
+ u32 reg_start_offset;
+
+ struct regmap_config *regmap_config;
+};
+
+/**
+ * struct ti_iodelay_reg_values - Computed io_reg configuration values (see TRM)
+ * @coarse_ref_count: Coarse reference count
+ * @coarse_delay_count: Coarse delay count
+ * @fine_ref_count: Fine reference count
+ * @fine_delay_count: Fine Delay count
+ * @ref_clk_period: Reference Clock period
+ * @cdpe: Coarse delay parameter
+ * @fdpe: Fine delay parameter
+ */
+struct ti_iodelay_reg_values {
+ u16 coarse_ref_count;
+ u16 coarse_delay_count;
+
+ u16 fine_ref_count;
+ u16 fine_delay_count;
+
+ u16 ref_clk_period;
+
+ u32 cdpe;
+ u32 fdpe;
+};
+
+/**
+ * struct ti_iodelay_pin_name - name of the pins
+ * @name: name
+ */
+struct ti_iodelay_pin_name {
+ char name[IODELAY_REG_NAME_LEN];
+};
+
+/**
+ * struct ti_iodelay_pingroup - Structure that describes one group
+ * @np: Node pointer (device tree)
+ * @name: Name of the group
+ * @map: pinctrl map allocated for the group
+ * @vals: configuration values allocated for the group (from dt)
+ * @nvals: number of configuration values allocated
+ * @config: pinconf "Config" - currently a dummy value
+ * @node: list node to next group
+ */
+struct ti_iodelay_pingroup {
+ struct device_node *np;
+ const char *name;
+ struct pinctrl_map *map;
+ struct ti_iodelay_conf_vals *vals;
+ int nvals;
+ unsigned long config;
+ struct list_head node;
+};
+
+/**
+ * struct ti_iodelay_device - Represents information for a IOdelay instance
+ * @dev: device pointer
+ * @reg_base: Remapped virtual address
+ * @regmap: Regmap for this IOdelay instance
+ * @pctl: Pinctrl device
+ * @desc: pinctrl descriptor for pctl
+ * @pa: pinctrl pin wise description
+ * @names: names of the pins
+ * @groups: list of pinconf groups for iodelay instance
+ * @ngroups: number of groups in the list
+ * @mutex: mutex to protect group list modification
+ * @reg_data: Register definition data for the IODelay instance
+ * @reg_init_conf_values: Initial configuration values.
+ */
+struct ti_iodelay_device {
+ struct device *dev;
+ void __iomem *reg_base;
+ struct regmap *regmap;
+
+ struct pinctrl_dev *pctl;
+ struct pinctrl_desc desc;
+ struct pinctrl_pin_desc *pa;
+ struct ti_iodelay_pin_name *names;
+
+ struct list_head groups;
+ int ngroups;
+ struct mutex mutex; /* list protection */
+
+ const struct ti_iodelay_reg_data *reg_data;
+ struct ti_iodelay_reg_values reg_init_conf_values;
+};
+
+/*--- IOdelay configuration stuff ----*/
+
+/**
+ * ti_iodelay_extract() - extract bits for a field
+ * @val: register value
+ * @mask: Mask
+ *
+ * Return: extracted value which is appropriately shifted
+ */
+static inline u32 ti_iodelay_extract(u32 val, u32 mask)
+{
+ return (val & mask) >> __ffs(mask);
+}
+
+/**
+ * ti_iodelay_compute_dpe() - Compute equation for delay parameter
+ * @period: Period to use
+ * @ref: Reference Count
+ * @delay: Delay count
+ * @delay_m: Delay multiplier
+ *
+ * Return: Computed delay parameter
+ */
+static inline u32 ti_iodelay_compute_dpe(u16 period, u16 ref, u16 delay,
+ u16 delay_m)
+{
+ u64 m, d;
+
+ /* Handle overflow conditions */
+ m = 10 * (u64)period * (u64)ref;
+ d = 2 * (u64)delay * (u64)delay_m;
+
+ /* Truncate result back to 32 bits */
+ return div64_u64(m, d);
+}
+
+/**
+ * ti_iodelay_pinconf_set() - Configure the pin configuration
+ * @iod: IODelay device
+ * @val: Configuration value
+ *
+ * Update the configuration register as per TRM and lockup once done.
+ * *IMPORTANT NOTE* SoC TRM does recommend doing iodelay programmation only
+ * while in Isolation. But, then, isolation also implies that every pin
+ * on the SoC(including DDR) will be isolated out. The only benefit being
+ * a glitchless configuration, However, the intent of this driver is purely
+ * to support a "glitchy" configuration where applicable.
+ *
+ * Return: 0 in case of success, else appropriate error value
+ */
+static int ti_iodelay_pinconf_set(struct ti_iodelay_device *iod,
+ struct ti_iodelay_conf_vals *val)
+{
+ const struct ti_iodelay_reg_data *reg = iod->reg_data;
+ struct ti_iodelay_reg_values *ival = &iod->reg_init_conf_values;
+ struct device *dev = iod->dev;
+ u32 g_delay_coarse, g_delay_fine;
+ u32 a_delay_coarse, a_delay_fine;
+ u32 c_elements, f_elements;
+ u32 total_delay;
+ u32 reg_mask, reg_val, tmp_val;
+ int r;
+
+ /* NOTE: Truncation is expected in all division below */
+ g_delay_coarse = val->g_delay / 920;
+ g_delay_fine = ((val->g_delay % 920) * 10) / 60;
+
+ a_delay_coarse = val->a_delay / ival->cdpe;
+ a_delay_fine = ((val->a_delay % ival->cdpe) * 10) / ival->fdpe;
+
+ c_elements = g_delay_coarse + a_delay_coarse;
+ f_elements = (g_delay_fine + a_delay_fine) / 10;
+
+ if (f_elements > 22) {
+ total_delay = c_elements * ival->cdpe + f_elements * ival->fdpe;
+ c_elements = total_delay / ival->cdpe;
+ f_elements = (total_delay % ival->cdpe) / ival->fdpe;
+ }
+
+ reg_mask = reg->signature_mask;
+ reg_val = reg->signature_value << __ffs(reg->signature_mask);
+
+ reg_mask |= reg->binary_data_coarse_mask;
+ tmp_val = c_elements << __ffs(reg->binary_data_coarse_mask);
+ if (tmp_val & ~reg->binary_data_coarse_mask) {
+ dev_err(dev, "Masking overflow of coarse elements %08x\n",
+ tmp_val);
+ tmp_val &= reg->binary_data_coarse_mask;
+ }
+ reg_val |= tmp_val;
+
+ reg_mask |= reg->binary_data_fine_mask;
+ tmp_val = f_elements << __ffs(reg->binary_data_fine_mask);
+ if (tmp_val & ~reg->binary_data_fine_mask) {
+ dev_err(dev, "Masking overflow of fine elements %08x\n",
+ tmp_val);
+ tmp_val &= reg->binary_data_fine_mask;
+ }
+ reg_val |= tmp_val;
+
+ /*
+ * NOTE: we leave the iodelay values unlocked - this is to work around
+ * situations such as those found with mmc mode change.
+ * However, this leaves open any unwarranted changes to padconf register
+ * impacting iodelay configuration. Use with care!
+ */
+ reg_mask |= reg->lock_mask;
+ reg_val |= reg->unlock_val << __ffs(reg->lock_mask);
+ r = regmap_update_bits(iod->regmap, val->offset, reg_mask, reg_val);
+
+ dev_dbg(dev, "Set reg 0x%x Delay(a=%d g=%d), Elements(C=%d F=%d)0x%x\n",
+ val->offset, val->a_delay, val->g_delay, c_elements,
+ f_elements, reg_val);
+
+ return r;
+}
+
+/**
+ * ti_iodelay_pinconf_init_dev() - Initialize IODelay device
+ * @iod: IODelay device
+ *
+ * Unlocks the IODelay region, computes the common parameters
+ *
+ * Return: 0 in case of success, else appropriate error value
+ */
+static int ti_iodelay_pinconf_init_dev(struct ti_iodelay_device *iod)
+{
+ const struct ti_iodelay_reg_data *reg = iod->reg_data;
+ struct device *dev = iod->dev;
+ struct ti_iodelay_reg_values *ival = &iod->reg_init_conf_values;
+ u32 val;
+ int r;
+
+ /* unlock the IOdelay region */
+ r = regmap_update_bits(iod->regmap, reg->reg_global_lock_offset,
+ reg->global_lock_mask, reg->global_unlock_val);
+ if (r)
+ return r;
+
+ /* Read up Recalibration sequence done by bootloader */
+ r = regmap_read(iod->regmap, reg->reg_refclk_offset, &val);
+ if (r)
+ return r;
+ ival->ref_clk_period = ti_iodelay_extract(val, reg->refclk_period_mask);
+ dev_dbg(dev, "refclk_period=0x%04x\n", ival->ref_clk_period);
+
+ r = regmap_read(iod->regmap, reg->reg_coarse_offset, &val);
+ if (r)
+ return r;
+ ival->coarse_ref_count =
+ ti_iodelay_extract(val, reg->coarse_ref_count_mask);
+ ival->coarse_delay_count =
+ ti_iodelay_extract(val, reg->coarse_delay_count_mask);
+ if (!ival->coarse_delay_count) {
+ dev_err(dev, "Invalid Coarse delay count (0) (reg=0x%08x)\n",
+ val);
+ return -EINVAL;
+ }
+ ival->cdpe = ti_iodelay_compute_dpe(ival->ref_clk_period,
+ ival->coarse_ref_count,
+ ival->coarse_delay_count, 88);
+ if (!ival->cdpe) {
+ dev_err(dev, "Invalid cdpe computed params = %d %d %d\n",
+ ival->ref_clk_period, ival->coarse_ref_count,
+ ival->coarse_delay_count);
+ return -EINVAL;
+ }
+ dev_dbg(iod->dev, "coarse: ref=0x%04x delay=0x%04x cdpe=0x%08x\n",
+ ival->coarse_ref_count, ival->coarse_delay_count, ival->cdpe);
+
+ r = regmap_read(iod->regmap, reg->reg_fine_offset, &val);
+ if (r)
+ return r;
+ ival->fine_ref_count =
+ ti_iodelay_extract(val, reg->fine_ref_count_mask);
+ ival->fine_delay_count =
+ ti_iodelay_extract(val, reg->fine_delay_count_mask);
+ if (!ival->fine_delay_count) {
+ dev_err(dev, "Invalid Fine delay count (0) (reg=0x%08x)\n",
+ val);
+ return -EINVAL;
+ }
+ ival->fdpe = ti_iodelay_compute_dpe(ival->ref_clk_period,
+ ival->fine_ref_count,
+ ival->fine_delay_count, 264);
+ if (!ival->fdpe) {
+ dev_err(dev, "Invalid fdpe(0) computed params = %d %d %d\n",
+ ival->ref_clk_period, ival->fine_ref_count,
+ ival->fine_delay_count);
+ return -EINVAL;
+ }
+ dev_dbg(iod->dev, "fine: ref=0x%04x delay=0x%04x fdpe=0x%08x\n",
+ ival->fine_ref_count, ival->fine_delay_count, ival->fdpe);
+
+ return 0;
+}
+
+/**
+ * ti_iodelay_pinconf_deinit_dev() - deinit the IOdelay device
+ * @iod: IODelay device
+ *
+ * Deinitialize the IODelay device (basically just lock the region back up.
+ */
+static void ti_iodelay_pinconf_deinit_dev(struct ti_iodelay_device *iod)
+{
+ const struct ti_iodelay_reg_data *reg = iod->reg_data;
+
+ /* lock the IOdelay region back again */
+ regmap_update_bits(iod->regmap, reg->reg_global_lock_offset,
+ reg->global_lock_mask, reg->global_lock_val);
+}
+
+/*--- Pinctrl/pinconf framework stuff ----*/
+
+/**
+ * ti_iodelay_get_group() - Find the group mapped by a group selector
+ * @iod: IODelay device
+ * @gselector: Group Selector
+ *
+ * Return: Corresponding group representing group selector in list of groups
+ * managed in IOdelay device OR NULL if not found.
+ */
+static struct ti_iodelay_pingroup *ti_iodelay_get_group(struct ti_iodelay_device
+ *iod,
+ unsigned gselector)
+{
+ struct ti_iodelay_pingroup *group;
+ int gid = 0;
+
+ list_for_each_entry(group, &iod->groups, node) {
+ if (gid == gselector)
+ return group;
+ gid++;
+ }
+
+ dev_err(iod->dev, "%s could not find pingroup %i\n", __func__,
+ gselector);
+ return NULL;
+}
+
+/**
+ * ti_iodelay_dt_node_to_map() - Map a device tree node to appropriate group
+ * @pctldev: pinctrl device representing IODelay device
+ * @np: Node Pointer (device tree)
+ * @map: Pinctrl Map returned back to pinctrl framework
+ * @num_maps: Number of maps (1)
+ *
+ * Maps the device tree description into a group of configuration parameters
+ * for IOdelay block entry.
+ *
+ * Return: 0 in case of success, else appropriate error value
+ */
+static int ti_iodelay_dt_node_to_map(struct pinctrl_dev *pctldev,
+ struct device_node *np,
+ struct pinctrl_map **map,
+ unsigned *num_maps)
+{
+ struct ti_iodelay_device *iod;
+ struct device *dev;
+ /* const char **pgnames; */
+ int ret = 0;
+ const __be32 *mux;
+ struct ti_iodelay_conf_vals *vals;
+ struct ti_iodelay_pingroup *group;
+ int size, index, idx, rows;
+ u32 offset, val;
+
+ iod = pinctrl_dev_get_drvdata(pctldev);
+ if (!iod)
+ return -EINVAL;
+ dev = iod->dev;
+
+ *map = devm_kzalloc(dev, sizeof(**map), GFP_KERNEL);
+ if (!*map)
+ return -ENOMEM;
+ *num_maps = 0;
+
+ group = devm_kzalloc(dev, sizeof(*group), GFP_KERNEL);
+ if (!group) {
+ ret = -ENOMEM;
+ goto free_map;
+ }
+
+ mux = of_get_property(np, IODELAY_MUX_PINS_NAME, &size);
+ if ((!mux) || (size < sizeof(*mux) * 2)) {
+ dev_err(dev, "bad data for mux %s\n", np->name);
+ ret = -EINVAL;
+ goto free_group;
+ }
+
+ size /= sizeof(*mux); /* Number of elements in array */
+ rows = size / 2;
+
+ vals = devm_kzalloc(dev, sizeof(*vals) * rows, GFP_KERNEL);
+ if (!vals) {
+ ret = -ENOMEM;
+ goto free_group;
+ }
+
+ index = 0;
+ idx = 0;
+ while (index < size) {
+ offset = be32_to_cpup(mux + index++);
+ val = be32_to_cpup(mux + index++);
+ vals[idx].offset = offset;
+ vals[idx].a_delay = val & 0xFFFF;
+ vals[idx].g_delay = (val & 0xFFFF0000) >> 16;
+ if (offset > iod->reg_data->regmap_config->max_register) {
+ dev_err(dev, "Invalid offset for %s 0x%x\n",
+ np->name, offset);
+ break;
+ }
+ dev_dbg(dev, "%s offset=%x a_delay = %d g_delay = %d\n",
+ np->name, vals[idx].offset, vals[idx].a_delay,
+ vals[idx].g_delay);
+ idx++;
+ }
+
+ group->name = np->name;
+ group->np = np;
+ group->vals = vals;
+ group->nvals = idx;
+ group->config = PIN_CONFIG_END;
+ group->map = *map;
+
+ /* Add to group list */
+ mutex_lock(&iod->mutex);
+ list_add_tail(&group->node, &iod->groups);
+ iod->ngroups++;
+ mutex_unlock(&iod->mutex);
+
+ (*map)->type = PIN_MAP_TYPE_CONFIGS_GROUP;
+ (*map)->data.configs.group_or_pin = np->name;
+ (*map)->data.configs.configs = &group->config;
+ (*map)->data.configs.num_configs = 1;
+ *num_maps = 1;
+
+ return 0;
+
+free_group:
+ devm_kfree(dev, group);
+free_map:
+ devm_kfree(dev, *map);
+ return ret;
+}
+
+/**
+ * ti_iodelay_dt_free_map() - Free map and resource alloted as per the map
+ * @pctldev: pinctrl device representing IODelay device
+ * @map: Map allocated by ti_iodelay_dt_node_to_map
+ * @num_maps: Num maps (1)
+ *
+ * Removes the group associated with the map and frees all resources allocated
+ * for the group.
+ */
+static void ti_iodelay_dt_free_map(struct pinctrl_dev *pctldev,
+ struct pinctrl_map *map, unsigned num_maps)
+{
+ struct ti_iodelay_device *iod;
+ struct device *dev;
+ struct ti_iodelay_pingroup *group;
+ bool found = false;
+
+ if (!map)
+ return;
+
+ iod = pinctrl_dev_get_drvdata(pctldev);
+ if (!iod)
+ return;
+ dev = iod->dev;
+
+ mutex_lock(&iod->mutex);
+ list_for_each_entry(group, &iod->groups, node) {
+ if (group->map == map) {
+ found = true;
+ list_del(&group->node);
+ iod->ngroups--;
+ break;
+ }
+ }
+ mutex_unlock(&iod->mutex);
+
+ /* If some freaky pinconf framework bug... */
+ if (!found)
+ return;
+
+ devm_kfree(dev, group->vals);
+ devm_kfree(dev, group);
+ devm_kfree(dev, map);
+}
+
+/**
+ * ti_iodelay_pinctrl_get_groups_count() - Get number of groups registered
+ * @pctldev: pinctrl device representing IODelay device
+ *
+ * Return: number of groups mapped on the IODelay
+ */
+static int ti_iodelay_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
+{
+ struct ti_iodelay_device *iod;
+ struct device *dev;
+
+ iod = pinctrl_dev_get_drvdata(pctldev);
+ dev = iod->dev;
+
+ return iod->ngroups;
+}
+
+/**
+ * ti_iodelay_pinctrl_get_group_name() - Get the group name
+ * @pctldev: pinctrl device representing IODelay device
+ * @gselector: group selector
+ *
+ * Return: name of the Group given a valid gselector, else NULL.
+ */
+static const char *ti_iodelay_pinctrl_get_group_name(struct pinctrl_dev
+ *pctldev,
+ unsigned gselector)
+{
+ struct ti_iodelay_device *iod;
+ struct device *dev;
+ struct ti_iodelay_pingroup *group;
+
+ iod = pinctrl_dev_get_drvdata(pctldev);
+ dev = iod->dev;
+
+ group = ti_iodelay_get_group(iod, gselector);
+ if (!group)
+ return NULL;
+
+ return group->name;
+}
+
+/**
+ * ti_iodelay_pinctrl_get_group_pins() - get group pins
+ * @pctldev: pinctrl device representing IODelay device
+ * @gselector: Group selector
+ * @pins: pointer to the pins
+ * @npins: number of pins
+ *
+ * Dummy implementation since we do not track pins, we track configurations
+ * Forced by pinctrl's pinctrl_check_ops()
+ *
+ * Return: -EINVAL
+ */
+static int ti_iodelay_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+ unsigned gselector,
+ const unsigned **pins,
+ unsigned *npins)
+{
+ /* Dummy implementation - we dont do pin mux */
+ return -EINVAL;
+}
+
+/**
+ * ti_iodelay_pinconf_group_get() - Get the group configuration
+ * @pctldev: pinctrl device representing IODelay device
+ * @gselector: Group selector
+ * @config: configuration returned
+ *
+ * Return: The configuration if the group is valid, else returns -EINVAL
+ */
+static int ti_iodelay_pinconf_group_get(struct pinctrl_dev *pctldev,
+ unsigned gselector,
+ unsigned long *config)
+{
+ struct ti_iodelay_device *iod;
+ struct device *dev;
+ struct ti_iodelay_pingroup *group;
+
+ iod = pinctrl_dev_get_drvdata(pctldev);
+ dev = iod->dev;
+ group = ti_iodelay_get_group(iod, gselector);
+
+ if (!group)
+ return -EINVAL;
+
+ *config = group->config;
+ return 0;
+}
+
+/**
+ * ti_iodelay_pinconf_group_set() - Configure the groups of pins
+ * @pctldev: pinctrl device representing IODelay device
+ * @gselector: Group selector
+ * @configs: Configurations
+ * @num_configs: Number of configurations
+ *
+ * Return: 0 if all went fine, else appropriate error value.
+ */
+static int ti_iodelay_pinconf_group_set(struct pinctrl_dev *pctldev,
+ unsigned gselector,
+ unsigned long *configs,
+ unsigned num_configs)
+{
+ struct ti_iodelay_device *iod;
+ struct device *dev;
+ struct ti_iodelay_pingroup *group;
+ int i;
+
+ iod = pinctrl_dev_get_drvdata(pctldev);
+ dev = iod->dev;
+ group = ti_iodelay_get_group(iod, gselector);
+
+ if (num_configs != 1) {
+ dev_err(dev, "Unsupported number of configurations %d\n",
+ num_configs);
+ return -EINVAL;
+ }
+
+ if (*configs != PIN_CONFIG_END) {
+ dev_err(dev, "Unsupported configuration\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < group->nvals; i++) {
+ if (ti_iodelay_pinconf_set(iod, &group->vals[i]))
+ return -ENOTSUPP;
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_DEBUG_FS
+/**
+ * ti_iodelay_pinconf_group_dbg_show() - show the group information
+ * @pctldev: Show the group information
+ * @s: Sequence file
+ * @gselector: group selector
+ *
+ * Provide the configuration information of the selected group
+ */
+static void ti_iodelay_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
+ struct seq_file *s,
+ unsigned gselector)
+{
+ struct ti_iodelay_device *iod;
+ struct device *dev;
+ struct ti_iodelay_pingroup *group;
+ int i;
+
+ iod = pinctrl_dev_get_drvdata(pctldev);
+ dev = iod->dev;
+ group = ti_iodelay_get_group(iod, gselector);
+ if (!group)
+ return;
+
+ for (i = 0; i < group->nvals; i++) {
+ struct ti_iodelay_conf_vals *val;
+ u32 reg = 0;
+
+ val = &group->vals[i];
+ regmap_read(iod->regmap, val->offset, ®),
+ seq_printf(s, "\n\t0x%08x = 0x%08x (%3d, %3d)",
+ val->offset, reg, val->a_delay, val->g_delay);
+ }
+}
+#endif
+
+static struct pinctrl_ops ti_iodelay_pinctrl_ops = {
+ .dt_node_to_map = ti_iodelay_dt_node_to_map,
+ .dt_free_map = ti_iodelay_dt_free_map,
+ .get_groups_count = ti_iodelay_pinctrl_get_groups_count,
+ .get_group_name = ti_iodelay_pinctrl_get_group_name,
+ .get_group_pins = ti_iodelay_pinctrl_get_group_pins,
+};
+
+static struct pinconf_ops ti_iodelay_pinctrl_pinconf_ops = {
+ .pin_config_group_get = ti_iodelay_pinconf_group_get,
+ .pin_config_group_set = ti_iodelay_pinconf_group_set,
+#ifdef CONFIG_DEBUG_FS
+ .pin_config_group_dbg_show = ti_iodelay_pinconf_group_dbg_show,
+#endif
+};
+
+/**
+ * ti_iodelay_alloc_pins() - Allocate structures needed for pins for IOdelay
+ * @dev: device pointer
+ * @iod: IODelay device
+ * @base_phy: Base Physical Address
+ *
+ * Return: 0 if all went fine, else appropriate error value.
+ */
+static int ti_iodelay_alloc_pins(struct device *dev,
+ struct ti_iodelay_device *iod, u32 base_phy)
+{
+ const struct ti_iodelay_reg_data *r = iod->reg_data;
+ struct pinctrl_pin_desc *pin;
+ struct ti_iodelay_pin_name *pn;
+ u32 phy_reg;
+ int nr_pins, i;
+
+ nr_pins = (r->regmap_config->max_register - r->reg_start_offset) / 4;
+
+ dev_dbg(dev, "Allocating %i pins\n", nr_pins);
+
+ iod->pa = devm_kzalloc(dev, sizeof(*iod->pa) * nr_pins, GFP_KERNEL);
+ if (!iod->pa)
+ return -ENOMEM;
+
+ iod->names =
+ devm_kzalloc(dev, sizeof(struct ti_iodelay_pin_name) * nr_pins,
+ GFP_KERNEL);
+ if (!iod->names)
+ return -ENOMEM;
+
+ iod->desc.pins = iod->pa;
+ iod->desc.npins = nr_pins;
+
+ phy_reg = r->reg_start_offset + base_phy;
+ pn = iod->names;
+ for (i = 0; i < nr_pins; i++, pn++, phy_reg += 4) {
+ pin = &iod->pa[i];
+ sprintf(pn->name, "%x.%d", phy_reg, i);
+ pin->number = i;
+ pin->name = pn->name;
+ }
+
+ return 0;
+}
+
+/**
+ * ti_iodelay_probe() - Standard probe
+ * @pdev: platform device
+ *
+ * Return: 0 if all went fine, else appropriate error value.
+ */
+static int ti_iodelay_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = of_node_get(dev->of_node);
+ const struct of_device_id *match;
+ struct resource *res;
+ struct ti_iodelay_device *iod;
+ int ret = 0;
+
+ if (!np) {
+ ret = -EINVAL;
+ dev_err(dev, "No OF node\n");
+ goto exit_out;
+ }
+
+ match = of_match_device(ti_iodelay_of_match, dev);
+ if (!match) {
+ ret = -EINVAL;
+ dev_err(dev, "No DATA match\n");
+ goto exit_out;
+ }
+
+ iod = devm_kzalloc(dev, sizeof(*iod), GFP_KERNEL);
+ if (!iod) {
+ ret = -ENOMEM;
+ goto exit_out;
+ }
+ iod->dev = dev;
+ iod->reg_data = match->data;
+
+ /* So far We can assume there is only 1 bank of registers */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(dev, "Missing MEM resource\n");
+ ret = -ENODEV;
+ goto exit_out;
+ }
+
+ iod->reg_base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(iod->reg_base)) {
+ ret = PTR_ERR(iod->reg_base);
+ goto exit_out;
+ }
+
+ iod->regmap = devm_regmap_init_mmio(dev, iod->reg_base,
+ iod->reg_data->regmap_config);
+ if (IS_ERR(iod->regmap)) {
+ dev_err(dev, "Regmap MMIO init failed.\n");
+ ret = PTR_ERR(iod->regmap);
+ goto exit_out;
+ }
+
+ if (ti_iodelay_pinconf_init_dev(iod))
+ goto exit_out;
+
+ ret = ti_iodelay_alloc_pins(dev, iod, res->start);
+ if (ret)
+ goto exit_out;
+
+ INIT_LIST_HEAD(&iod->groups);
+ mutex_init(&iod->mutex);
+
+ iod->desc.pctlops = &ti_iodelay_pinctrl_ops;
+ /* no pinmux ops - we are pinconf */
+ iod->desc.confops = &ti_iodelay_pinctrl_pinconf_ops;
+ iod->desc.name = dev_name(dev);
+ iod->desc.owner = THIS_MODULE;
+
+ iod->pctl = pinctrl_register(&iod->desc, dev, iod);
+ if (!iod->pctl) {
+ dev_err(dev, "Failed to register pinctrl\n");
+ ret = -ENODEV;
+ goto exit_out;
+ }
+
+ platform_set_drvdata(pdev, iod);
+
+exit_out:
+ of_node_put(np);
+ return ret;
+}
+
+/**
+ * ti_iodelay_remove() - standard remove
+ * @pdev: platform device
+ *
+ * Return: 0 if all went fine, else appropriate error value.
+ */
+static int ti_iodelay_remove(struct platform_device *pdev)
+{
+ struct ti_iodelay_device *iod = platform_get_drvdata(pdev);
+
+ if (!iod)
+ return 0;
+ if (iod->pctl)
+ pinctrl_unregister(iod->pctl);
+
+ ti_iodelay_pinconf_deinit_dev(iod);
+
+ /* Expect other allocations to be freed by devm */
+
+ return 0;
+}
+
+static struct regmap_config dra7_iodelay_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0xD1C,
+};
+
+static struct ti_iodelay_reg_data dra7_iodelay_data = {
+ .signature_mask = 0x0003F000,
+ .signature_value = 0x29,
+ .lock_mask = 0x00000400,
+ .lock_val = 1,
+ .unlock_val = 0,
+ .binary_data_coarse_mask = 0x000003E0,
+ .binary_data_fine_mask = 0x0000001F,
+
+ .reg_refclk_offset = 0x14,
+ .refclk_period_mask = 0xFFFF,
+
+ .reg_coarse_offset = 0x18,
+ .coarse_delay_count_mask = 0xFFFF0000,
+ .coarse_ref_count_mask = 0x0000FFFF,
+
+ .reg_fine_offset = 0x1C,
+ .fine_delay_count_mask = 0xFFFF0000,
+ .fine_ref_count_mask = 0x0000FFFF,
+
+ .reg_global_lock_offset = 0x2C,
+ .global_lock_mask = 0x0000FFFF,
+ .global_unlock_val = 0x0000AAAA,
+ .global_lock_val = 0x0000AAAB,
+
+ .reg_start_offset = 0x30,
+ .regmap_config = &dra7_iodelay_regmap_config,
+};
+
+static const struct of_device_id ti_iodelay_of_match[] = {
+ {.compatible = "ti,dra7-iodelay", .data = &dra7_iodelay_data},
+ { /* Hopefully no more.. */ },
+};
+MODULE_DEVICE_TABLE(of, ti_iodelay_of_match);
+
+static struct platform_driver ti_iodelay_driver = {
+ .probe = ti_iodelay_probe,
+ .remove = ti_iodelay_remove,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = DRIVER_NAME,
+ .of_match_table = ti_iodelay_of_match,
+ },
+};
+module_platform_driver(ti_iodelay_driver);
+
+MODULE_AUTHOR("Texas Instruments, Inc.");
+MODULE_DESCRIPTION("Pinconf driver for TI's IO Delay module");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c
index faf0389..f8e9e1c 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm.c
@@ -594,6 +594,10 @@ static void msm_gpio_irq_unmask(struct irq_data *d)
raw_spin_lock_irqsave(&pctrl->lock, flags);
+ val = readl(pctrl->regs + g->intr_status_reg);
+ val &= ~BIT(g->intr_status_bit);
+ writel(val, pctrl->regs + g->intr_status_reg);
+
val = readl(pctrl->regs + g->intr_cfg_reg);
val |= BIT(g->intr_enable_bit);
writel(val, pctrl->regs + g->intr_cfg_reg);
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 63454b5..c1bb046 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -1,3 +1,4 @@
source "drivers/power/avs/Kconfig"
source "drivers/power/reset/Kconfig"
source "drivers/power/supply/Kconfig"
+source "drivers/power/pwrseq/Kconfig"
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index ff35c71..7db8035 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -1,3 +1,4 @@
obj-$(CONFIG_POWER_AVS) += avs/
obj-$(CONFIG_POWER_RESET) += reset/
obj-$(CONFIG_POWER_SUPPLY) += supply/
+obj-$(CONFIG_POWER_SEQUENCE) += pwrseq/
diff --git b/drivers/power/pwrseq/Kconfig b/drivers/power/pwrseq/Kconfig
new file mode 100644
index 0000000..3859a67
--- /dev/null
+++ b/drivers/power/pwrseq/Kconfig
@@ -0,0 +1,19 @@
+#
+# Power Sequence library
+#
+
+config POWER_SEQUENCE
+ bool
+
+menu "Power Sequence Support"
+
+config PWRSEQ_GENERIC
+ bool "Generic power sequence control"
+ depends on OF
+ select POWER_SEQUENCE
+ help
+ It is used for drivers which needs to do power sequence
+ (eg, turn on clock, toggle reset gpio) before the related
+ devices can be found by hardware. This generic one can be
+ used for common power sequence control.
+endmenu
diff --git b/drivers/power/pwrseq/Makefile b/drivers/power/pwrseq/Makefile
new file mode 100644
index 0000000..ad82389
--- /dev/null
+++ b/drivers/power/pwrseq/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_POWER_SEQUENCE) += core.o
+obj-$(CONFIG_PWRSEQ_GENERIC) += pwrseq_generic.o
diff --git b/drivers/power/pwrseq/core.c b/drivers/power/pwrseq/core.c
new file mode 100644
index 0000000..9cb1223
--- /dev/null
+++ b/drivers/power/pwrseq/core.c
@@ -0,0 +1,191 @@
+/*
+ * core.c power sequence core file
+ *
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ * Author: Peter Chen <peter.chen@nxp.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 of
+ * the License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+#include <linux/power/pwrseq.h>
+
+static DEFINE_MUTEX(pwrseq_list_mutex);
+static LIST_HEAD(pwrseq_list);
+
+int pwrseq_get(struct device_node *np, struct pwrseq *p)
+{
+ if (p && p->get)
+ return p->get(np, p);
+
+ return -ENOTSUPP;
+}
+EXPORT_SYMBOL_GPL(pwrseq_get);
+
+int pwrseq_on(struct pwrseq *p)
+{
+ if (p && p->on)
+ return p->on(p);
+
+ return -ENOTSUPP;
+}
+EXPORT_SYMBOL_GPL(pwrseq_on);
+
+void pwrseq_off(struct pwrseq *p)
+{
+ if (p && p->off)
+ p->off(p);
+}
+EXPORT_SYMBOL_GPL(pwrseq_off);
+
+void pwrseq_put(struct pwrseq *p)
+{
+ if (p && p->put)
+ p->put(p);
+}
+EXPORT_SYMBOL_GPL(pwrseq_put);
+
+int pwrseq_suspend(struct pwrseq *p)
+{
+ if (p && p->suspend)
+ return p->suspend(p);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pwrseq_suspend);
+
+int pwrseq_resume(struct pwrseq *p)
+{
+ if (p && p->resume)
+ return p->resume(p);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pwrseq_resume);
+
+void pwrseq_register(struct pwrseq *pwrseq)
+{
+ mutex_lock(&pwrseq_list_mutex);
+ list_add(&pwrseq->node, &pwrseq_list);
+ mutex_unlock(&pwrseq_list_mutex);
+}
+EXPORT_SYMBOL_GPL(pwrseq_register);
+
+void pwrseq_unregister(struct pwrseq *pwrseq)
+{
+ mutex_lock(&pwrseq_list_mutex);
+ list_del(&pwrseq->node);
+ mutex_unlock(&pwrseq_list_mutex);
+}
+EXPORT_SYMBOL_GPL(pwrseq_unregister);
+
+static struct pwrseq *pwrseq_find_available_instance(struct device_node *np)
+{
+ struct pwrseq *pwrseq;
+
+ list_for_each_entry(pwrseq, &pwrseq_list, node) {
+ if (pwrseq->used)
+ continue;
+
+ /* compare compatible string for pwrseq node */
+ if (of_match_node(pwrseq->pwrseq_of_match_table, np)) {
+ pwrseq->used = true;
+ return pwrseq;
+ }
+
+ /* return generic pwrseq instance */
+ if (!strcmp(pwrseq->pwrseq_of_match_table->compatible,
+ "generic")) {
+ pr_debug("using generic pwrseq instance for %s\n",
+ np->full_name);
+ pwrseq->used = true;
+ return pwrseq;
+ }
+ }
+ pr_warn("Can't find any pwrseq instances for %s\n", np->full_name);
+
+ return NULL;
+}
+
+struct pwrseq *of_pwrseq_on(struct device_node *np)
+{
+ struct pwrseq *pwrseq;
+ int ret;
+
+ pwrseq = pwrseq_find_available_instance(np);
+ if (!pwrseq)
+ return ERR_PTR(-ENONET);
+
+ ret = pwrseq_get(np, pwrseq);
+ if (ret) {
+ /* Mark current pwrseq as unused */
+ pwrseq->used = false;
+ return ERR_PTR(ret);
+ }
+
+ ret = pwrseq_on(pwrseq);
+ if (ret)
+ goto pwr_put;
+
+ return pwrseq;
+
+pwr_put:
+ pwrseq_put(pwrseq);
+ return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(of_pwrseq_on);
+
+void of_pwrseq_off(struct pwrseq *pwrseq)
+{
+ pwrseq_off(pwrseq);
+ pwrseq_put(pwrseq);
+}
+EXPORT_SYMBOL_GPL(of_pwrseq_off);
+
+int of_pwrseq_on_list(struct device_node *np, struct list_head *head)
+{
+ struct pwrseq *pwrseq;
+ struct pwrseq_list_per_dev *pwrseq_list_node;
+
+ pwrseq = of_pwrseq_on(np);
+ if (IS_ERR(pwrseq))
+ return PTR_ERR(pwrseq);
+
+ pwrseq_list_node = kzalloc(sizeof(*pwrseq_list_node), GFP_KERNEL);
+ if (!pwrseq_list_node) {
+ of_pwrseq_off(pwrseq);
+ return -ENOMEM;
+ }
+ pwrseq_list_node->pwrseq = pwrseq;
+ list_add(&pwrseq_list_node->list, head);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(of_pwrseq_on_list);
+
+void of_pwrseq_off_list(struct list_head *head)
+{
+ struct pwrseq *pwrseq;
+ struct pwrseq_list_per_dev *pwrseq_list_node, *tmp_node;
+
+ list_for_each_entry_safe(pwrseq_list_node, tmp_node, head, list) {
+ pwrseq = pwrseq_list_node->pwrseq;
+ of_pwrseq_off(pwrseq);
+ list_del(&pwrseq_list_node->list);
+ kfree(pwrseq_list_node);
+ }
+}
+EXPORT_SYMBOL_GPL(of_pwrseq_off_list);
diff --git b/drivers/power/pwrseq/pwrseq_generic.c b/drivers/power/pwrseq/pwrseq_generic.c
new file mode 100644
index 0000000..d7a77f2
--- /dev/null
+++ b/drivers/power/pwrseq/pwrseq_generic.c
@@ -0,0 +1,183 @@
+/*
+ * pwrseq_generic.c Generic power sequence handling
+ *
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ * Author: Peter Chen <peter.chen@nxp.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 of
+ * the License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/slab.h>
+
+#include <linux/power/pwrseq.h>
+
+struct pwrseq_generic {
+ struct pwrseq pwrseq;
+ struct gpio_desc *gpiod_reset;
+ struct clk *clks[PWRSEQ_MAX_CLKS];
+ u32 duration_us;
+};
+
+#define to_generic_pwrseq(p) container_of(p, struct pwrseq_generic, pwrseq)
+
+static int pwrseq_generic_alloc_instance(void);
+static const struct of_device_id generic_id_table[] = {
+ { .compatible = "generic",},
+ { /* sentinel */ }
+};
+
+static void pwrseq_generic_put(struct pwrseq *pwrseq)
+{
+ struct pwrseq_generic *pwrseq_gen = to_generic_pwrseq(pwrseq);
+ int clk;
+
+ if (pwrseq_gen->gpiod_reset)
+ gpiod_put(pwrseq_gen->gpiod_reset);
+
+ for (clk = 0; clk < PWRSEQ_MAX_CLKS; clk++)
+ clk_put(pwrseq_gen->clks[clk]);
+
+ pwrseq_unregister(&pwrseq_gen->pwrseq);
+ kfree(pwrseq_gen);
+}
+
+static void pwrseq_generic_off(struct pwrseq *pwrseq)
+{
+ struct pwrseq_generic *pwrseq_gen = to_generic_pwrseq(pwrseq);
+ int clk;
+
+ for (clk = PWRSEQ_MAX_CLKS - 1; clk >= 0; clk--)
+ clk_disable_unprepare(pwrseq_gen->clks[clk]);
+}
+
+static int pwrseq_generic_on(struct pwrseq *pwrseq)
+{
+ struct pwrseq_generic *pwrseq_gen = to_generic_pwrseq(pwrseq);
+ int clk, ret = 0;
+ struct gpio_desc *gpiod_reset = pwrseq_gen->gpiod_reset;
+
+ for (clk = 0; clk < PWRSEQ_MAX_CLKS && pwrseq_gen->clks[clk]; clk++) {
+ ret = clk_prepare_enable(pwrseq_gen->clks[clk]);
+ if (ret) {
+ pr_err("Can't enable clock, ret=%d\n", ret);
+ goto err_disable_clks;
+ }
+ }
+
+ if (gpiod_reset) {
+ u32 duration_us = pwrseq_gen->duration_us;
+
+ if (duration_us <= 10)
+ udelay(10);
+ else
+ usleep_range(duration_us, duration_us + 100);
+ gpiod_set_value(gpiod_reset, 0);
+ }
+
+ return ret;
+
+err_disable_clks:
+ while (--clk >= 0)
+ clk_disable_unprepare(pwrseq_gen->clks[clk]);
+
+ return ret;
+}
+
+static int pwrseq_generic_get(struct device_node *np, struct pwrseq *pwrseq)
+{
+ struct pwrseq_generic *pwrseq_gen = to_generic_pwrseq(pwrseq);
+ enum of_gpio_flags flags;
+ int reset_gpio, clk, ret = 0;
+
+ for (clk = 0; clk < PWRSEQ_MAX_CLKS; clk++) {
+ pwrseq_gen->clks[clk] = of_clk_get(np, clk);
+ if (IS_ERR(pwrseq_gen->clks[clk])) {
+ ret = PTR_ERR(pwrseq_gen->clks[clk]);
+ if (ret != -ENOENT)
+ goto err_put_clks;
+ pwrseq_gen->clks[clk] = NULL;
+ break;
+ }
+ }
+
+ reset_gpio = of_get_named_gpio_flags(np, "reset-gpios", 0, &flags);
+ if (gpio_is_valid(reset_gpio)) {
+ unsigned long gpio_flags;
+
+ if (flags & OF_GPIO_ACTIVE_LOW)
+ gpio_flags = GPIOF_ACTIVE_LOW | GPIOF_OUT_INIT_LOW;
+ else
+ gpio_flags = GPIOF_OUT_INIT_HIGH;
+
+ ret = gpio_request_one(reset_gpio, gpio_flags,
+ "pwrseq-reset-gpios");
+ if (ret)
+ goto err_put_clks;
+
+ pwrseq_gen->gpiod_reset = gpio_to_desc(reset_gpio);
+ of_property_read_u32(np, "reset-duration-us",
+ &pwrseq_gen->duration_us);
+ } else if (reset_gpio == -ENOENT) {
+ ; /* no such gpio */
+ } else {
+ ret = reset_gpio;
+ pr_err("Failed to get reset gpio on %s, err = %d\n",
+ np->full_name, reset_gpio);
+ goto err_put_clks;
+ }
+
+ /* allocate new one for later pwrseq instance request */
+ ret = pwrseq_generic_alloc_instance();
+ if (ret)
+ goto err_put_gpio;
+
+ return 0;
+
+err_put_gpio:
+ if (pwrseq_gen->gpiod_reset)
+ gpiod_put(pwrseq_gen->gpiod_reset);
+err_put_clks:
+ while (--clk >= 0)
+ clk_put(pwrseq_gen->clks[clk]);
+ return ret;
+}
+
+static int pwrseq_generic_alloc_instance(void)
+{
+ struct pwrseq_generic *pwrseq_gen;
+
+ pwrseq_gen = kzalloc(sizeof(*pwrseq_gen), GFP_KERNEL);
+ if (!pwrseq_gen)
+ return -ENOMEM;
+
+ pwrseq_gen->pwrseq.pwrseq_of_match_table = generic_id_table;
+ pwrseq_gen->pwrseq.get = pwrseq_generic_get;
+ pwrseq_gen->pwrseq.on = pwrseq_generic_on;
+ pwrseq_gen->pwrseq.off = pwrseq_generic_off;
+ pwrseq_gen->pwrseq.put = pwrseq_generic_put;
+
+ pwrseq_register(&pwrseq_gen->pwrseq);
+ return 0;
+}
+
+static int __init pwrseq_generic_register(void)
+{
+ return pwrseq_generic_alloc_instance();
+}
+postcore_initcall(pwrseq_generic_register)
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index 2e05046..3c6dfad 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -751,11 +751,11 @@ static int spidev_probe(struct spi_device *spi)
* compatible string, it is a Linux implementation thing
* rather than a description of the hardware.
*/
- if (spi->dev.of_node && !of_match_device(spidev_dt_ids, &spi->dev)) {
- dev_err(&spi->dev, "buggy DT: spidev listed directly in DT\n");
- WARN_ON(spi->dev.of_node &&
- !of_match_device(spidev_dt_ids, &spi->dev));
- }
+// if (spi->dev.of_node && !of_match_device(spidev_dt_ids, &spi->dev)) {
+// dev_err(&spi->dev, "buggy DT: spidev listed directly in DT\n");
+// WARN_ON(spi->dev.of_node &&
+// !of_match_device(spidev_dt_ids, &spi->dev));
+// }
spidev_probe_acpi(spi);
diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
index 61ad6c3..f81da0e 100644
--- a/drivers/tty/serial/8250/8250_omap.c
+++ b/drivers/tty/serial/8250/8250_omap.c
@@ -1434,10 +1434,10 @@ static int __init omap8250_console_fixup(void)
}
add_preferred_console("ttyS", idx, options);
- pr_err("WARNING: Your 'console=ttyO%d' has been replaced by 'ttyS%d'\n",
+ pr_info("WARNING: Your 'console=ttyO%d' has been replaced by 'ttyS%d'\n",
idx, idx);
- pr_err("This ensures that you still see kernel messages. Please\n");
- pr_err("update your kernel commandline.\n");
+ pr_info("This ensures that you still see kernel messages. Please\n");
+ pr_info("update your kernel commandline.\n");
return 0;
}
console_initcall(omap8250_console_fixup);
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 0ee7c4c..1c4b477 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -1591,6 +1591,31 @@ static int serial_omap_probe_rs485(struct uart_omap_port *up,
return 0;
}
+static int serial_omap_of_get_port_line(struct device_node *np)
+{
+ unsigned long val;
+ const char *hwmod;
+ int ret;
+
+ /* first try the serial alias */
+ ret = of_alias_get_id(np, "serial");
+ if (ret >= 0)
+ return ret;
+
+ /* no? calculate it from hwmods */
+ ret = of_property_read_string(np, "ti,hwmods", &hwmod);
+ if (ret != 0 || strncmp(hwmod, "uart", 4) ||
+ kstrtoul(hwmod + 4, 10, &val))
+ return -ENODEV;
+
+ /* numbering of hwmods is +1 */
+ ret = (int)val - 1;
+ if (ret < 0)
+ return -ENODEV;
+
+ return ret;
+}
+
static int serial_omap_probe(struct platform_device *pdev)
{
struct omap_uart_port_info *omap_up_info = dev_get_platdata(&pdev->dev);
@@ -1608,7 +1633,10 @@ static int serial_omap_probe(struct platform_device *pdev)
return -EPROBE_DEFER;
wakeirq = irq_of_parse_and_map(pdev->dev.of_node, 1);
omap_up_info = of_get_uart_port_info(&pdev->dev);
- pdev->dev.platform_data = omap_up_info;
+ ret = platform_device_add_data(pdev, omap_up_info,
+ sizeof(*omap_up_info));
+ if (ret != 0)
+ return ret;
} else {
uartirq = platform_get_irq(pdev, 0);
if (uartirq < 0)
@@ -1634,7 +1662,7 @@ static int serial_omap_probe(struct platform_device *pdev)
up->port.ops = &serial_omap_pops;
if (pdev->dev.of_node)
- ret = of_alias_get_id(pdev->dev.of_node, "serial");
+ ret = serial_omap_of_get_port_line(pdev->dev.of_node);
else
ret = pdev->id;
diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig
index 52c98ce..05400bc 100644
--- a/drivers/uio/Kconfig
+++ b/drivers/uio/Kconfig
@@ -129,7 +129,7 @@ config UIO_PRUSS
select GENERIC_ALLOCATOR
depends on HAS_IOMEM && HAS_DMA
help
- PRUSS driver for OMAPL138/DA850/AM18XX devices
+ PRUSS driver for OMAPL138/DA850/AM18XX and AM33XX devices
PRUSS driver requires user space components, examples and user space
driver is available from below SVN repo - you may use anonymous login
diff --git a/drivers/uio/uio_pruss.c b/drivers/uio/uio_pruss.c
index ca9e2fa..6559752 100644
--- a/drivers/uio/uio_pruss.c
+++ b/drivers/uio/uio_pruss.c
@@ -19,6 +19,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/platform_device.h>
+#include <linux/of_gpio.h>
#include <linux/uio_driver.h>
#include <linux/platform_data/uio_pruss.h>
#include <linux/io.h>
@@ -27,6 +28,11 @@
#include <linux/sizes.h>
#include <linux/slab.h>
#include <linux/genalloc.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/err.h>
+#include <linux/pm_runtime.h>
#define DRV_NAME "pruss_uio"
#define DRV_VERSION "1.0"
@@ -106,10 +112,12 @@ static void pruss_cleanup(struct device *dev, struct uio_pruss_dev *gdev)
dma_free_coherent(dev, extram_pool_sz, gdev->ddr_vaddr,
gdev->ddr_paddr);
}
+#ifdef CONFIG_ARCH_DAVINCI_DA850
if (gdev->sram_vaddr)
gen_pool_free(gdev->sram_pool,
gdev->sram_vaddr,
sram_pool_sz);
+#endif
kfree(gdev->info);
clk_put(gdev->pruss_clk);
kfree(gdev);
@@ -120,9 +128,15 @@ static int pruss_probe(struct platform_device *pdev)
struct uio_info *p;
struct uio_pruss_dev *gdev;
struct resource *regs_prussio;
+ struct resource res;
struct device *dev = &pdev->dev;
int ret = -ENODEV, cnt = 0, len;
struct uio_pruss_pdata *pdata = dev_get_platdata(dev);
+ struct pinctrl *pinctrl;
+
+ int count;
+ struct device_node *child;
+ const char *pin_name;
gdev = kzalloc(sizeof(struct uio_pruss_dev), GFP_KERNEL);
if (!gdev)
@@ -133,7 +147,7 @@ static int pruss_probe(struct platform_device *pdev)
kfree(gdev);
return -ENOMEM;
}
-
+#ifdef CONFIG_ARCH_DAVINCI_DA850
/* Power on PRU in case its not done as part of boot-loader */
gdev->pruss_clk = clk_get(dev, "pruss");
if (IS_ERR(gdev->pruss_clk)) {
@@ -145,8 +159,25 @@ static int pruss_probe(struct platform_device *pdev)
} else {
clk_enable(gdev->pruss_clk);
}
+#endif
+
+ if (pdev->dev.of_node) {
+ pm_runtime_enable(&pdev->dev);
+ ret = pm_runtime_get_sync(&pdev->dev);
+ if (IS_ERR_VALUE(ret)) {
+ dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n");
+ return ret;
+ }
- regs_prussio = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ ret = of_address_to_resource(pdev->dev.of_node, 0, &res);
+ if (IS_ERR_VALUE(ret)) {
+ dev_err(&pdev->dev, "failed to parse DT reg\n");
+ return ret;
+ }
+ regs_prussio = &res;
+ }
+ else
+ regs_prussio = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!regs_prussio) {
dev_err(dev, "No PRUSS I/O resource specified\n");
goto out_free;
@@ -157,7 +188,50 @@ static int pruss_probe(struct platform_device *pdev)
goto out_free;
}
- if (pdata->sram_pool) {
+
+ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+ if (IS_ERR(pinctrl))
+ dev_warn(&pdev->dev,
+ "pins are not configured from the driver\n");
+ else{
+ count = of_get_child_count(pdev->dev.of_node);
+ if (!count){
+ dev_info(&pdev->dev, "No children\n");
+ return -ENODEV;
+ }
+ // Run through all children. They have lables for easy reference.
+ for_each_child_of_node(pdev->dev.of_node, child){
+ enum of_gpio_flags flags;
+ unsigned gpio;
+
+ count = of_gpio_count(child);
+
+ ret = of_property_count_strings(child, "pin-names");
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to get pin-names\n");
+ continue;
+ }
+ if(count != ret){
+ dev_err(&pdev->dev, "The number of gpios (%d) does not match"\
+ " the number of pin names (%d)\n", count, ret);
+ continue;
+ }
+
+ for(cnt=0; cnt<count; cnt++){
+ ret = of_property_read_string_index(child,
+ "pin-names", cnt, &pin_name);
+ if (ret != 0)
+ dev_err(&pdev->dev, "Error on pin-name #%d\n", cnt);
+ gpio = of_get_gpio_flags(child, cnt, &flags);
+ ret = devm_gpio_request_one(&pdev->dev, gpio, flags, pin_name);
+ if (ret < 0) {
+ dev_err(dev, "Failed to request GPIO %d (%s) flags: '%d', error %d\n",
+ gpio, pin_name, flags, ret);
+ }
+ }
+ }
+ }
+ if (pdata && pdata->sram_pool) {
gdev->sram_pool = pdata->sram_pool;
gdev->sram_vaddr =
(unsigned long)gen_pool_dma_alloc(gdev->sram_pool,
@@ -182,7 +256,17 @@ static int pruss_probe(struct platform_device *pdev)
goto out_free;
}
- gdev->pintc_base = pdata->pintc_base;
+ if (pdev->dev.of_node) {
+ ret = of_property_read_u32(pdev->dev.of_node,
+ "ti,pintc-offset",
+ &gdev->pintc_base);
+ if (ret < 0) {
+ dev_err(&pdev->dev,
+ "Can't parse ti,pintc-offset property\n");
+ goto out_free;
+ }
+ } else
+ gdev->pintc_base = pdata->pintc_base;
gdev->hostirq_start = platform_get_irq(pdev, 0);
for (cnt = 0, p = gdev->info; cnt < MAX_PRUSS_EVT; cnt++, p++) {
@@ -190,6 +274,7 @@ static int pruss_probe(struct platform_device *pdev)
p->mem[0].size = resource_size(regs_prussio);
p->mem[0].memtype = UIO_MEM_PHYS;
+#ifdef CONFIG_ARCH_DAVINCI_DA850
p->mem[1].addr = gdev->sram_paddr;
p->mem[1].size = sram_pool_sz;
p->mem[1].memtype = UIO_MEM_PHYS;
@@ -197,7 +282,11 @@ static int pruss_probe(struct platform_device *pdev)
p->mem[2].addr = gdev->ddr_paddr;
p->mem[2].size = extram_pool_sz;
p->mem[2].memtype = UIO_MEM_PHYS;
-
+#else
+ p->mem[1].addr = gdev->ddr_paddr;
+ p->mem[1].size = extram_pool_sz;
+ p->mem[1].memtype = UIO_MEM_PHYS;
+#endif
p->name = kasprintf(GFP_KERNEL, "pruss_evt%d", cnt);
p->version = DRV_VERSION;
@@ -227,11 +316,20 @@ static int pruss_remove(struct platform_device *dev)
return 0;
}
+static const struct of_device_id pruss_dt_ids[] = {
+ { .compatible = "ti,pruss-v1", .data = NULL, },
+ { .compatible = "ti,pruss-v2", .data = NULL, },
+ {},
+};
+MODULE_DEVICE_TABLE(of, pruss_dt_ids);
+
+
static struct platform_driver pruss_driver = {
.probe = pruss_probe,
.remove = pruss_remove,
.driver = {
.name = DRV_NAME,
+ .of_match_table = pruss_dt_ids,
},
};
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index 3dbb4a2..fdffc67 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -928,6 +928,16 @@ static int ci_hdrc_probe(struct platform_device *pdev)
return -ENODEV;
}
+ /*
+ * At device tree, we have no device node for chipidea core,
+ * the glue layer's node is the parent node for host and udc
+ * device. But in related driver, the parent device is chipidea
+ * core. So, in order to let the common driver get parent's node,
+ * we let the core's device node equals glue layer's node.
+ */
+ if (dev->parent && dev->parent->of_node)
+ dev->of_node = dev->parent->of_node;
+
if (ci->platdata->phy) {
ci->phy = ci->platdata->phy;
} else if (ci->platdata->usb_phy) {
@@ -938,11 +948,15 @@ static int ci_hdrc_probe(struct platform_device *pdev)
/* if both generic PHY and USB PHY layers aren't enabled */
if (PTR_ERR(ci->phy) == -ENOSYS &&
- PTR_ERR(ci->usb_phy) == -ENXIO)
- return -ENXIO;
+ PTR_ERR(ci->usb_phy) == -ENXIO) {
+ ret = -ENXIO;
+ goto clear_of_node;
+ }
- if (IS_ERR(ci->phy) && IS_ERR(ci->usb_phy))
- return -EPROBE_DEFER;
+ if (IS_ERR(ci->phy) && IS_ERR(ci->usb_phy)) {
+ ret = -EPROBE_DEFER;
+ goto clear_of_node;
+ }
if (IS_ERR(ci->phy))
ci->phy = NULL;
@@ -953,7 +967,7 @@ static int ci_hdrc_probe(struct platform_device *pdev)
ret = ci_usb_phy_init(ci);
if (ret) {
dev_err(dev, "unable to init phy: %d\n", ret);
- return ret;
+ goto clear_of_node;
}
ci->hw_bank.phys = res->start;
@@ -1059,6 +1073,8 @@ static int ci_hdrc_probe(struct platform_device *pdev)
ci_role_destroy(ci);
deinit_phy:
ci_usb_phy_exit(ci);
+clear_of_node:
+ dev->of_node = NULL;
return ret;
}
@@ -1077,6 +1093,7 @@ static int ci_hdrc_remove(struct platform_device *pdev)
ci_extcon_unregister(ci);
ci_role_destroy(ci);
ci_hdrc_enter_lpm(ci, true);
+ ci->dev->of_node = NULL;
ci_usb_phy_exit(ci);
return 0;
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index c28ccf1..fb54ce9 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -26,6 +26,7 @@
#include <linux/mutex.h>
#include <linux/random.h>
#include <linux/pm_qos.h>
+#include <linux/power/pwrseq.h>
#include <asm/uaccess.h>
#include <asm/byteorder.h>
@@ -1614,6 +1615,7 @@ static void hub_disconnect(struct usb_interface *intf)
hub->error = 0;
hub_quiesce(hub, HUB_DISCONNECT);
+ of_pwrseq_off_list(&hub->pwrseq_on_list);
mutex_lock(&usb_port_peer_mutex);
/* Avoid races with recursively_mark_NOTATTACHED() */
@@ -1641,12 +1643,41 @@ static void hub_disconnect(struct usb_interface *intf)
kref_put(&hub->kref, hub_release);
}
+#ifdef CONFIG_OF
+static int hub_of_pwrseq_on(struct usb_hub *hub)
+{
+ struct device *parent;
+ struct usb_device *hdev = hub->hdev;
+ struct device_node *np;
+ int ret;
+
+ if (hdev->parent)
+ parent = &hdev->dev;
+ else
+ parent = bus_to_hcd(hdev->bus)->self.controller;
+
+ for_each_child_of_node(parent->of_node, np) {
+ ret = of_pwrseq_on_list(np, &hub->pwrseq_on_list);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+#else
+static int hub_of_pwrseq_on(struct usb_hub *hub)
+{
+ return 0;
+}
+#endif
+
static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct usb_host_interface *desc;
struct usb_endpoint_descriptor *endpoint;
struct usb_device *hdev;
struct usb_hub *hub;
+ int ret = -ENODEV;
desc = intf->cur_altsetting;
hdev = interface_to_usbdev(intf);
@@ -1751,6 +1782,7 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
INIT_DELAYED_WORK(&hub->leds, led_work);
INIT_DELAYED_WORK(&hub->init_work, NULL);
INIT_WORK(&hub->events, hub_event);
+ INIT_LIST_HEAD(&hub->pwrseq_on_list);
usb_get_intf(intf);
usb_get_dev(hdev);
@@ -1764,11 +1796,14 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
if (id->driver_info & HUB_QUIRK_CHECK_PORT_AUTOSUSPEND)
hub->quirk_check_port_auto_suspend = 1;
- if (hub_configure(hub, endpoint) >= 0)
- return 0;
+ if (hub_configure(hub, endpoint) >= 0) {
+ ret = hub_of_pwrseq_on(hub);
+ if (!ret)
+ return 0;
+ }
hub_disconnect(intf);
- return -ENODEV;
+ return ret;
}
static int
diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
index 34c1a7e..cd86f91 100644
--- a/drivers/usb/core/hub.h
+++ b/drivers/usb/core/hub.h
@@ -78,6 +78,7 @@ struct usb_hub {
struct delayed_work init_work;
struct work_struct events;
struct usb_port **ports;
+ struct list_head pwrseq_on_list; /* powered pwrseq node list */
};
/**
diff --git a/firmware/am335x-bone-scale-data.bin b/firmware/am335x-bone-scale-data.bin
new file mode 100644
index 0000000000000000000000000000000000000000..1ce3c1c596d7a7f400b0cc89bda5a41eed2780c5
GIT binary patch
literal 73
pcmd-HXHZUIU{c}EWl|AfLZWk+R0P|Ad@#)bSHb~R0-{lr003gr3L5|b
literal 0
HcmV?d00001
diff --git a/firmware/am335x-evm-scale-data.bin b/firmware/am335x-evm-scale-data.bin
new file mode 100644
index 0000000000000000000000000000000000000000..a222389d233fa8f1c76ef35470b57284999c8df5
GIT binary patch
literal 17
Ucmd-HXJAiZVA55UX8=>$024d{B>(^b
literal 0
HcmV?d00001
diff --git a/firmware/am43x-evm-scale-data.bin b/firmware/am43x-evm-scale-data.bin
new file mode 100644
index 0000000000000000000000000000000000000000..2d71341089816be7989e6dc11b265d9194ac909e
GIT binary patch
literal 41
hcmd-HXAn+dU{VptW>OLB0@CSBDpG9>aG{wnApnMi2I2q!
literal 0
HcmV?d00001
diff --git b/include/dt-bindings/board/am335x-bbw-bbb-base.h b/include/dt-bindings/board/am335x-bbw-bbb-base.h
new file mode 100644
index 0000000..35f6d57
--- /dev/null
+++ b/include/dt-bindings/board/am335x-bbw-bbb-base.h
@@ -0,0 +1,103 @@
+/*
+ * This header provides constants for bbw/bbb pinctrl bindings.
+ *
+ * Copyright (C) 2014 Robert Nelson <robertcnelson@gmail.com>
+ *
+ * Numbers Based on: https://github.com/derekmolloy/boneDeviceTree/tree/master/docs
+ */
+
+#ifndef _DT_BINDINGS_BOARD_AM335X_BBW_BBB_BASE_H
+#define _DT_BINDINGS_BOARD_AM335X_BBW_BBB_BASE_H
+
+#define BONE_P8_03 0x018
+#define BONE_P8_04 0x01C
+
+#define BONE_P8_05 0x008
+#define BONE_P8_06 0x00C
+#define BONE_P8_07 0x090
+#define BONE_P8_08 0x094
+
+#define BONE_P8_09 0x09C
+#define BONE_P8_10 0x098
+#define BONE_P8_11 0x034
+#define BONE_P8_12 0x030
+
+#define BONE_P8_13 0x024
+#define BONE_P8_14 0x028
+#define BONE_P8_15 0x03C
+#define BONE_P8_16 0x038
+
+#define BONE_P8_17 0x02C
+#define BONE_P8_18 0x08C
+#define BONE_P8_19 0x020
+#define BONE_P8_20 0x084
+
+#define BONE_P8_21 0x080
+#define BONE_P8_22 0x014
+#define BONE_P8_23 0x010
+#define BONE_P8_24 0x004
+
+#define BONE_P8_25 0x000
+#define BONE_P8_26 0x07C
+#define BONE_P8_27 0x0E0
+#define BONE_P8_28 0x0E8
+
+#define BONE_P8_29 0x0E4
+#define BONE_P8_30 0x0EC
+#define BONE_P8_31 0x0D8
+#define BONE_P8_32 0x0DC
+
+#define BONE_P8_33 0x0D4
+#define BONE_P8_34 0x0CC
+#define BONE_P8_35 0x0D0
+#define BONE_P8_36 0x0C8
+
+#define BONE_P8_37 0x0C0
+#define BONE_P8_38 0x0C4
+#define BONE_P8_39 0x0B8
+#define BONE_P8_40 0x0BC
+
+#define BONE_P8_41 0x0B0
+#define BONE_P8_42 0x0B4
+#define BONE_P8_43 0x0A8
+#define BONE_P8_44 0x0AC
+
+#define BONE_P8_45 0x0A0
+#define BONE_P8_46 0x0A4
+
+#define BONE_P9_11 0x070
+#define BONE_P9_12 0x078
+
+#define BONE_P9_13 0x074
+#define BONE_P9_14 0x048
+#define BONE_P9_15 0x040
+#define BONE_P9_16 0x04C
+
+#define BONE_P9_17 0x15C
+#define BONE_P9_18 0x158
+#define BONE_P9_19 0x17C
+#define BONE_P9_20 0x178
+
+#define BONE_P9_21 0x154
+#define BONE_P9_22 0x150
+#define BONE_P9_23 0x044
+#define BONE_P9_24 0x184
+
+#define BONE_P9_25 0x1AC
+#define BONE_P9_26 0x180
+#define BONE_P9_27 0x1A4
+#define BONE_P9_28 0x19C
+
+#define BONE_P9_29 0x194
+#define BONE_P9_30 0x198
+#define BONE_P9_31 0x190
+
+/* Shared P21 of P11 */
+#define BONE_P9_41A 0x1B4
+#define BONE_P9_41B 0x1A8
+
+/* Shared P22 of P11 */
+#define BONE_P9_42A 0x164
+#define BONE_P9_42B 0x1A0
+
+#endif
diff --git b/include/dt-bindings/mfd/tps65217.h b/include/dt-bindings/mfd/tps65217.h
new file mode 100644
index 0000000..cafb9e6
--- /dev/null
+++ b/include/dt-bindings/mfd/tps65217.h
@@ -0,0 +1,26 @@
+/*
+ * This header provides macros for TI TPS65217 DT bindings.
+ *
+ * Copyright (C) 2016 Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __DT_BINDINGS_TPS65217_H__
+#define __DT_BINDINGS_TPS65217_H__
+
+#define TPS65217_IRQ_USB 0
+#define TPS65217_IRQ_AC 1
+#define TPS65217_IRQ_PB 2
+
+#endif
diff --git a/include/dt-bindings/pinctrl/dra.h b/include/dt-bindings/pinctrl/dra.h
index 5c75e80..5a60e3b 100644
--- a/include/dt-bindings/pinctrl/dra.h
+++ b/include/dt-bindings/pinctrl/dra.h
@@ -50,6 +50,8 @@
#define MODE_SELECT (1 << 8)
+#define MANUAL_MODE MODE_SELECT
+
#define PULL_ENA (0 << 16)
#define PULL_DIS (1 << 16)
#define PULL_UP (1 << 17)
@@ -73,5 +75,9 @@
*/
#define DRA7XX_CORE_IOPAD(pa, val) (((pa) & 0xffff) - 0x3400) (val)
+/* DRA7 IODELAY configuration parameters */
+#define A_DELAY(val) ((val) & 0xFFFF)
+#define G_DELAY(val) (((val) & 0xFFFF) << 16)
+
#endif
diff --git a/include/linux/mfd/tps65217.h b/include/linux/mfd/tps65217.h
index 4ccda89..3cbec4b 100644
--- a/include/linux/mfd/tps65217.h
+++ b/include/linux/mfd/tps65217.h
@@ -234,12 +234,11 @@ struct tps65217_bl_pdata {
int dft_brightness;
};
-enum tps65217_irq_type {
- TPS65217_IRQ_PB,
- TPS65217_IRQ_AC,
- TPS65217_IRQ_USB,
- TPS65217_NUM_IRQ
-};
+/* Interrupt numbers */
+#define TPS65217_IRQ_USB 0
+#define TPS65217_IRQ_AC 1
+#define TPS65217_IRQ_PB 2
+#define TPS65217_NUM_IRQ 3
/**
* struct tps65217_board - packages regulator init data
diff --git a/include/linux/of.h b/include/linux/of.h
index 299aeb1..725bd28 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -23,8 +23,10 @@
#include <linux/spinlock.h>
#include <linux/topology.h>
#include <linux/notifier.h>
+#include <linux/slab.h>
#include <linux/property.h>
#include <linux/list.h>
+#include <linux/rhashtable.h>
#include <asm/byteorder.h>
#include <asm/errno.h>
@@ -52,6 +54,7 @@ struct device_node {
phandle phandle;
const char *full_name;
struct fwnode_handle fwnode;
+ struct rhash_head ht_node;
struct property *properties;
struct property *deadprops; /* removed properties */
@@ -1184,6 +1187,8 @@ enum of_reconfig_change {
};
#ifdef CONFIG_OF_DYNAMIC
+#include <linux/slab.h>
+
extern int of_reconfig_notifier_register(struct notifier_block *);
extern int of_reconfig_notifier_unregister(struct notifier_block *);
extern int of_reconfig_notify(unsigned long, struct of_reconfig_data *rd);
@@ -1227,6 +1232,26 @@ static inline int of_changeset_update_property(struct of_changeset *ocs,
{
return of_changeset_action(ocs, OF_RECONFIG_UPDATE_PROPERTY, np, prop);
}
+
+struct device_node *of_changeset_create_device_nodev(
+ struct of_changeset *ocs, struct device_node *parent,
+ const char *fmt, va_list vargs);
+
+__printf(3, 4) struct device_node *
+of_changeset_create_device_node(struct of_changeset *ocs,
+ struct device_node *parent, const char *fmt, ...);
+
+int __of_changeset_add_update_property_copy(struct of_changeset *ocs,
+ struct device_node *np, const char *name, const void *value,
+ int length, bool update);
+
+int __of_changeset_add_update_property_string_list(
+ struct of_changeset *ocs, struct device_node *np,
+ const char *name, const char **strs, int count, bool update);
+
+int of_changeset_node_move(struct of_changeset *ocs,
+ struct device_node *np, struct device_node *new_parent);
+
#else /* CONFIG_OF_DYNAMIC */
static inline int of_reconfig_notifier_register(struct notifier_block *nb)
{
@@ -1246,8 +1271,323 @@ static inline int of_reconfig_get_state_change(unsigned long action,
{
return -EINVAL;
}
+
+static inline struct device_node *of_changeset_create_device_nodev(
+ struct of_changeset *ocs, struct device_node *parent,
+ const char *fmt, va_list vargs)
+{
+ return ERR_PTR(-EINVAL);
+}
+
+static inline __printf(3, 4) struct device_node *
+of_changeset_create_device_node(struct of_changeset *ocs,
+ struct device_node *parent, const char *fmt, ...)
+{
+ return ERR_PTR(-EINVAL);
+}
+
+static inline int __of_changeset_add_update_property_copy(
+ struct of_changeset *ocs, struct device_node *np,
+ const char *name, const void *value, int length, bool update)
+{
+ return -EINVAL;
+}
+
+static inline __printf(4, 5) int of_changeset_add_property_stringf(
+ struct of_changeset *ocs, struct device_node *np,
+ const char *name, const char *fmt, ...)
+{
+ return -EINVAL;
+}
+
+static inline int of_changeset_update_property_stringf(
+ struct of_changeset *ocs, struct device_node *np,
+ const char *name, const char *fmt, ...)
+{
+ return -EINVAL;
+}
+
+static inline int __of_changeset_add_update_property_string_list(
+ struct of_changeset *ocs, struct device_node *np,
+ const char *name, const char **strs, int count, bool update)
+{
+ return -EINVAL;
+}
+
+static inline int of_changeset_node_move(struct of_changeset *ocs,
+ struct device_node *np, struct device_node *new_parent)
+{
+ return -EINVAL;
+}
+
#endif /* CONFIG_OF_DYNAMIC */
+/**
+ * of_changeset_add_property_copy - Create a new property copying name & value
+ *
+ * @ocs: changeset pointer
+ * @np: device node pointer
+ * @name: name of the property
+ * @value: pointer to the value data
+ * @length: length of the value in bytes
+ *
+ * Adds a property to the changeset by making copies of the name & value
+ * entries.
+ *
+ * Returns zero on success, a negative error value otherwise.
+ */
+static inline int of_changeset_add_property_copy(struct of_changeset *ocs,
+ struct device_node *np, const char *name,
+ const void *value, int length)
+{
+ return __of_changeset_add_update_property_copy(ocs, np, name, value,
+ length, false);
+}
+
+/**
+ * of_changeset_update_property_copy - Update a property copying name & value
+ *
+ * @ocs: changeset pointer
+ * @np: device node pointer
+ * @name: name of the property
+ * @value: pointer to the value data
+ * @length: length of the value in bytes
+ *
+ * Update a property to the changeset by making copies of the name & value
+ * entries.
+ *
+ * Returns zero on success, a negative error value otherwise.
+ */
+static inline int of_changeset_update_property_copy(struct of_changeset *ocs,
+ struct device_node *np, const char *name,
+ const void *value, int length)
+{
+ return __of_changeset_add_update_property_copy(ocs, np, name, value,
+ length, true);
+}
+
+/**
+ * __of_changeset_add_update_property_string - Create/update a string property
+ *
+ * @ocs: changeset pointer
+ * @np: device node pointer
+ * @name: name of the property
+ * @str: string property value
+ * @update: True on update operation
+ *
+ * Adds/updates a string property to the changeset by making copies of the name
+ * and the given value. The @update parameter controls whether an add or
+ * update takes place.
+ *
+ * Returns zero on success, a negative error value otherwise.
+ */
+static inline int __of_changeset_add_update_property_string(
+ struct of_changeset *ocs, struct device_node *np, const char *name,
+ const char *str, bool update)
+{
+ return __of_changeset_add_update_property_copy(ocs, np, name, str,
+ strlen(str) + 1, update);
+}
+
+/**
+ * __of_changeset_add_update_property_stringv - Create/update a formatted
+ * string property
+ *
+ * @ocs: changeset pointer
+ * @np: device node pointer
+ * @name: name of the property
+ * @fmt: format of string property
+ * @vargs: arguments of the format string
+ * @update: True on update operation
+ *
+ * Adds/updates a string property to the changeset by making copies of the name
+ * and the formatted value. The @update parameter controls whether an add or
+ * update takes place.
+ *
+ * Returns zero on success, a negative error value otherwise.
+ */
+static inline int __of_changeset_add_update_property_stringv(
+ struct of_changeset *ocs, struct device_node *np, const char *name,
+ const char *fmt, va_list vargs, bool update)
+{
+ char *str;
+ int ret;
+
+ str = kvasprintf(GFP_KERNEL, fmt, vargs);
+ if (!str)
+ return -ENOMEM;
+ ret = __of_changeset_add_update_property_string(ocs, np, name, str,
+ update);
+ kfree(str);
+
+ return ret;
+}
+
+/**
+ * of_changeset_add_property_string_list - Create a new string list property
+ *
+ * @ocs: changeset pointer
+ * @np: device node pointer
+ * @name: name of the property
+ * @strs: pointer to the string list
+ * @count: string count
+ *
+ * Adds a string list property to the changeset.
+ *
+ * Returns zero on success, a negative error value otherwise.
+ */
+static inline int of_changeset_add_property_string_list(
+ struct of_changeset *ocs, struct device_node *np, const char *name,
+ const char **strs, int count)
+{
+ return __of_changeset_add_update_property_string_list(ocs, np, name,
+ strs, count, false);
+}
+
+/**
+ * of_changeset_update_property_string_list - Update string list property
+ *
+ * @ocs: changeset pointer
+ * @np: device node pointer
+ * @name: name of the property
+ * @strs: pointer to the string list
+ * @count: string count
+ *
+ * Updates a string list property to the changeset.
+ *
+ * Returns zero on success, a negative error value otherwise.
+ */
+static inline int of_changeset_update_property_string_list(
+ struct of_changeset *ocs, struct device_node *np,
+ const char *name, const char **strs, int count)
+{
+ return __of_changeset_add_update_property_string_list(ocs, np, name,
+ strs, count, true);
+}
+
+/**
+ * of_changeset_add_property_string - Adds a string property
+ *
+ * @ocs: changeset pointer
+ * @np: device node pointer
+ * @name: name of the property
+ * @str: string property
+ *
+ * Adds a string property to the changeset by making copies of the name
+ * and the string value.
+ *
+ * Returns zero on success, a negative error value otherwise.
+ */
+static inline int of_changeset_add_property_string(
+ struct of_changeset *ocs, struct device_node *np,
+ const char *name, const char *str)
+{
+ return __of_changeset_add_update_property_string(ocs, np, name, str,
+ false);
+}
+
+/**
+ * of_changeset_update_property_string - Update a string property
+ *
+ * @ocs: changeset pointer
+ * @np: device node pointer
+ * @name: name of the property
+ * @str: string property
+ *
+ * Updates a string property to the changeset by making copies of the name
+ * and the string value.
+ *
+ * Returns zero on success, a negative error value otherwise.
+ */
+static inline int of_changeset_update_property_string(
+ struct of_changeset *ocs, struct device_node *np,
+ const char *name, const char *str)
+{
+ return __of_changeset_add_update_property_string(ocs, np, name, str,
+ true);
+}
+
+/**
+ * of_changeset_add_property_u32 - Create a new u32 property
+ *
+ * @ocs: changeset pointer
+ * @np: device node pointer
+ * @name: name of the property
+ * @val: value in host endian format
+ *
+ * Adds a u32 property to the changeset.
+ *
+ * Returns zero on success, a negative error value otherwise.
+ */
+static inline int of_changeset_add_property_u32(struct of_changeset *ocs,
+ struct device_node *np, const char *name, u32 val)
+{
+ val = cpu_to_be32(val);
+ return __of_changeset_add_update_property_copy(ocs, np, name, &val,
+ sizeof(val), false);
+}
+
+/**
+ * of_changeset_update_property_u32 - Update u32 property
+ *
+ * @ocs: changeset pointer
+ * @np: device node pointer
+ * @name: name of the property
+ * @val: value in host endian format
+ *
+ * Updates a u32 property to the changeset.
+ *
+ * Returns zero on success, a negative error value otherwise.
+ */
+static inline int of_changeset_update_property_u32(
+ struct of_changeset *ocs, struct device_node *np,
+ const char *name, u32 val)
+{
+ val = cpu_to_be32(val);
+ return __of_changeset_add_update_property_copy(ocs, np, name, &val,
+ sizeof(val), true);
+}
+
+/**
+ * of_changeset_add_property_bool - Create a new u32 property
+ *
+ * @ocs: changeset pointer
+ * @np: device node pointer
+ * @name: name of the property
+ *
+ * Adds a bool property to the changeset. Note that there is
+ * no option to set the value to false, since the property
+ * existing sets it to true.
+ *
+ * Returns zero on success, a negative error value otherwise.
+ */
+static inline int of_changeset_add_property_bool(
+ struct of_changeset *ocs, struct device_node *np, const char *name)
+{
+ return __of_changeset_add_update_property_copy(ocs, np, name, "", 0,
+ false);
+}
+
+/**
+ * of_changeset_update_property_bool - Update a bool property
+ *
+ * @ocs: changeset pointer
+ * @np: device node pointer
+ * @name: name of the property
+ *
+ * Updates a property to the changeset. Note that there is
+ * no option to set the value to false, since the property
+ * existing sets it to true.
+ *
+ * Returns zero on success, a negative error value otherwise.
+ */
+static inline int of_changeset_update_property_bool(struct of_changeset *ocs,
+ struct device_node *np, const char *name)
+{
+ return __of_changeset_add_update_property_copy(ocs, np, name, "", 0,
+ true);
+}
+
/* CONFIG_OF_RESOLVE api */
extern int of_resolve_phandles(struct device_node *tree);
@@ -1273,6 +1613,10 @@ int of_overlay_create(struct device_node *tree);
int of_overlay_destroy(int id);
int of_overlay_destroy_all(void);
+int of_overlay_create_target_index(struct device_node *tree, int index);
+int of_overlay_create_target_root(struct device_node *tree,
+ struct device_node *target_root);
+
#else
static inline int of_overlay_create(struct device_node *tree)
@@ -1290,6 +1634,18 @@ static inline int of_overlay_destroy_all(void)
return -ENOTSUPP;
}
+static inline int of_overlay_create_target_index(struct device_node *tree,
+ int index)
+{
+ return -ENOTSUPP;
+}
+
+static inline int of_overlay_create_target_root(struct device_node *tree,
+ struct device_node *target_root)
+{
+ return -ENOTSUPP;
+}
+
#endif
#endif /* _LINUX_OF_H */
diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
index f6bc765..e9be0ec 100644
--- a/include/linux/pm_opp.h
+++ b/include/linux/pm_opp.h
@@ -17,14 +17,64 @@
#include <linux/err.h>
#include <linux/notifier.h>
+struct clk;
+struct regulator;
struct dev_pm_opp;
struct device;
-struct opp_table;
enum dev_pm_opp_event {
OPP_EVENT_ADD, OPP_EVENT_REMOVE, OPP_EVENT_ENABLE, OPP_EVENT_DISABLE,
};
+/**
+ * struct dev_pm_opp_supply - Power supply voltage/current values
+ * @u_volt: Target voltage in microvolts corresponding to this OPP
+ * @u_volt_min: Minimum voltage in microvolts corresponding to this OPP
+ * @u_volt_max: Maximum voltage in microvolts corresponding to this OPP
+ * @u_amp: Maximum current drawn by the device in microamperes
+ *
+ * This structure stores the voltage/current values for a single power supply.
+ */
+struct dev_pm_opp_supply {
+ unsigned long u_volt;
+ unsigned long u_volt_min;
+ unsigned long u_volt_max;
+ unsigned long u_amp;
+};
+
+/**
+ * struct dev_pm_opp_info - OPP freq/voltage/current values
+ * @rate: Target clk rate in hz
+ * @supplies: Array of voltage/current values for all power supplies
+ *
+ * This structure stores the freq/voltage/current values for a single OPP.
+ */
+struct dev_pm_opp_info {
+ unsigned long rate;
+ struct dev_pm_opp_supply *supplies;
+};
+
+/**
+ * struct dev_pm_set_opp_data - Set OPP data
+ * @old_opp: Old OPP info
+ * @new_opp: New OPP info
+ * @regulators: Array of regulator pointers
+ * @regulator_count: Number of regulators
+ * @clk: Pointer to clk
+ * @dev: Pointer to the struct device
+ *
+ * This structure contains all information required for setting an OPP.
+ */
+struct dev_pm_set_opp_data {
+ struct dev_pm_opp_info old_opp;
+ struct dev_pm_opp_info new_opp;
+
+ struct regulator **regulators;
+ unsigned int regulator_count;
+ struct clk *clk;
+ struct device *dev;
+};
+
#if defined(CONFIG_PM_OPP)
unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp);
@@ -63,8 +113,10 @@ int dev_pm_opp_set_supported_hw(struct device *dev, const u32 *versions,
void dev_pm_opp_put_supported_hw(struct device *dev);
int dev_pm_opp_set_prop_name(struct device *dev, const char *name);
void dev_pm_opp_put_prop_name(struct device *dev);
-struct opp_table *dev_pm_opp_set_regulator(struct device *dev, const char *name);
-void dev_pm_opp_put_regulator(struct opp_table *opp_table);
+int dev_pm_opp_set_regulators(struct device *dev, const char * const names[], unsigned int count);
+void dev_pm_opp_put_regulators(struct device *dev);
+int dev_pm_opp_register_set_opp_helper(struct device *dev, int (*set_opp)(struct dev_pm_set_opp_data *data));
+void dev_pm_opp_register_put_opp_helper(struct device *dev);
int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq);
int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev, const struct cpumask *cpumask);
int dev_pm_opp_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask);
@@ -164,6 +216,14 @@ static inline int dev_pm_opp_set_supported_hw(struct device *dev,
static inline void dev_pm_opp_put_supported_hw(struct device *dev) {}
+static inline int dev_pm_opp_register_set_opp_helper(struct device *dev,
+ int (*set_opp)(struct dev_pm_set_opp_data *data))
+{
+ return -ENOTSUPP;
+}
+
+static inline void dev_pm_opp_register_put_opp_helper(struct device *dev) {}
+
static inline int dev_pm_opp_set_prop_name(struct device *dev, const char *name)
{
return -ENOTSUPP;
@@ -171,12 +231,12 @@ static inline int dev_pm_opp_set_prop_name(struct device *dev, const char *name)
static inline void dev_pm_opp_put_prop_name(struct device *dev) {}
-static inline struct opp_table *dev_pm_opp_set_regulator(struct device *dev, const char *name)
+static inline int dev_pm_opp_set_regulators(struct device *dev, const char *names[], unsigned int count)
{
- return ERR_PTR(-ENOTSUPP);
+ return -ENOTSUPP;
}
-static inline void dev_pm_opp_put_regulator(struct opp_table *opp_table) {}
+static inline void dev_pm_opp_put_regulators(struct device *dev) {}
static inline int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq)
{
@@ -209,6 +269,7 @@ void dev_pm_opp_of_remove_table(struct device *dev);
int dev_pm_opp_of_cpumask_add_table(const struct cpumask *cpumask);
void dev_pm_opp_of_cpumask_remove_table(const struct cpumask *cpumask);
int dev_pm_opp_of_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask);
+struct device_node *dev_pm_opp_of_get_opp_desc_node(struct device *dev);
#else
static inline int dev_pm_opp_of_add_table(struct device *dev)
{
@@ -232,6 +293,11 @@ static inline int dev_pm_opp_of_get_sharing_cpus(struct device *cpu_dev, struct
{
return -ENOTSUPP;
}
+
+static inline struct device_node *dev_pm_opp_of_get_opp_desc_node(struct device *dev)
+{
+ return NULL;
+}
#endif
#endif /* __LINUX_OPP_H__ */
diff --git b/include/linux/power/pwrseq.h b/include/linux/power/pwrseq.h
new file mode 100644
index 0000000..4f37275
--- /dev/null
+++ b/include/linux/power/pwrseq.h
@@ -0,0 +1,72 @@
+#ifndef __LINUX_PWRSEQ_H
+#define __LINUX_PWRSEQ_H
+
+#include <linux/of.h>
+
+#define PWRSEQ_MAX_CLKS 3
+
+struct pwrseq {
+ const struct of_device_id *pwrseq_of_match_table;
+ struct list_head node;
+ int (*get)(struct device_node *np, struct pwrseq *p);
+ int (*on)(struct pwrseq *p);
+ void (*off)(struct pwrseq *p);
+ void (*put)(struct pwrseq *p);
+ int (*suspend)(struct pwrseq *p);
+ int (*resume)(struct pwrseq *p);
+ bool used;
+};
+
+/* used for power sequence instance list in one driver */
+struct pwrseq_list_per_dev {
+ struct pwrseq *pwrseq;
+ struct list_head list;
+};
+
+#if IS_ENABLED(CONFIG_POWER_SEQUENCE)
+int pwrseq_get(struct device_node *np, struct pwrseq *p);
+int pwrseq_on(struct pwrseq *p);
+void pwrseq_off(struct pwrseq *p);
+void pwrseq_put(struct pwrseq *p);
+int pwrseq_suspend(struct pwrseq *p);
+int pwrseq_resume(struct pwrseq *p);
+void pwrseq_register(struct pwrseq *pwrseq);
+void pwrseq_unregister(struct pwrseq *pwrseq);
+struct pwrseq *of_pwrseq_on(struct device_node *np);
+void of_pwrseq_off(struct pwrseq *pwrseq);
+int of_pwrseq_on_list(struct device_node *np, struct list_head *head);
+void of_pwrseq_off_list(struct list_head *head);
+#else
+static inline int pwrseq_get(struct device_node *np, struct pwrseq *p)
+{
+ return 0;
+}
+static inline int pwrseq_on(struct pwrseq *p)
+{
+ return 0;
+}
+static inline void pwrseq_off(struct pwrseq *p) {}
+static inline void pwrseq_put(struct pwrseq *p) {}
+static inline int pwrseq_suspend(struct pwrseq *p)
+{
+ return 0;
+}
+static inline int pwrseq_resume(struct pwrseq *p)
+{
+ return 0;
+}
+static inline void pwrseq_register(struct pwrseq *pwrseq) {}
+static inline void pwrseq_unregister(struct pwrseq *pwrseq) {}
+static inline struct pwrseq *of_pwrseq_on(struct device_node *np)
+{
+ return NULL;
+}
+void of_pwrseq_off(struct pwrseq *pwrseq) {}
+int of_pwrseq_on_list(struct device_node *np, struct list_head *head)
+{
+ return 0;
+}
+void of_pwrseq_off_list(struct list_head *head) {}
+#endif /* CONFIG_POWER_SEQUENCE */
+
+#endif /* __LINUX_PWRSEQ_H */
diff --git a/include/linux/rtmutex.h b/include/linux/rtmutex.h
index 294a8b4..30211c6 100644
--- a/include/linux/rtmutex.h
+++ b/include/linux/rtmutex.h
@@ -105,7 +105,6 @@ extern void __rt_mutex_init(struct rt_mutex *lock, const char *name);
extern void rt_mutex_destroy(struct rt_mutex *lock);
extern void rt_mutex_lock(struct rt_mutex *lock);
-extern int rt_mutex_lock_state(struct rt_mutex *lock, int state);
extern int rt_mutex_lock_interruptible(struct rt_mutex *lock);
extern int rt_mutex_lock_killable(struct rt_mutex *lock);
extern int rt_mutex_timed_lock(struct rt_mutex *lock,
diff --git a/include/linux/rwsem.h b/include/linux/rwsem.h
index aa2ac1f..8e1f44f 100644
--- a/include/linux/rwsem.h
+++ b/include/linux/rwsem.h
@@ -110,13 +110,6 @@ static inline int rwsem_is_contended(struct rw_semaphore *sem)
return !list_empty(&sem->wait_list);
}
-#endif /* !PREEMPT_RT_FULL */
-
-/*
- * The functions below are the same for all rwsem implementations including
- * the RT specific variant.
- */
-
/*
* lock for reading
*/
@@ -195,4 +188,6 @@ extern void up_read_non_owner(struct rw_semaphore *sem);
# define up_read_non_owner(sem) up_read(sem)
#endif
+#endif /* !PREEMPT_RT_FULL */
+
#endif /* _LINUX_RWSEM_H */
diff --git a/include/linux/rwsem_rt.h b/include/linux/rwsem_rt.h
index 2ffbf09..e26bd95 100644
--- a/include/linux/rwsem_rt.h
+++ b/include/linux/rwsem_rt.h
@@ -5,63 +5,163 @@
#error "Include rwsem.h"
#endif
-#include <linux/rtmutex.h>
-#include <linux/swait.h>
+/*
+ * RW-semaphores are a spinlock plus a reader-depth count.
+ *
+ * Note that the semantics are different from the usual
+ * Linux rw-sems, in PREEMPT_RT mode we do not allow
+ * multiple readers to hold the lock at once, we only allow
+ * a read-lock owner to read-lock recursively. This is
+ * better for latency, makes the implementation inherently
+ * fair and makes it simpler as well.
+ */
-#define READER_BIAS (1U << 31)
-#define WRITER_BIAS (1U << 30)
+#include <linux/rtmutex.h>
struct rw_semaphore {
- atomic_t readers;
- struct rt_mutex rtmutex;
+ struct rt_mutex lock;
+ int read_depth;
#ifdef CONFIG_DEBUG_LOCK_ALLOC
struct lockdep_map dep_map;
#endif
};
-#define __RWSEM_INITIALIZER(name) \
-{ \
- .readers = ATOMIC_INIT(READER_BIAS), \
- .rtmutex = __RT_MUTEX_INITIALIZER(name.rtmutex), \
- RW_DEP_MAP_INIT(name) \
-}
+#define __RWSEM_INITIALIZER(name) \
+ { .lock = __RT_MUTEX_INITIALIZER(name.lock), \
+ RW_DEP_MAP_INIT(name) }
#define DECLARE_RWSEM(lockname) \
struct rw_semaphore lockname = __RWSEM_INITIALIZER(lockname)
-extern void __rwsem_init(struct rw_semaphore *rwsem, const char *name,
- struct lock_class_key *key);
+extern void __rt_rwsem_init(struct rw_semaphore *rwsem, const char *name,
+ struct lock_class_key *key);
-#define __init_rwsem(sem, name, key) \
-do { \
- rt_mutex_init(&(sem)->rtmutex); \
- __rwsem_init((sem), (name), (key)); \
-} while (0)
+#define __rt_init_rwsem(sem, name, key) \
+ do { \
+ rt_mutex_init(&(sem)->lock); \
+ __rt_rwsem_init((sem), (name), (key));\
+ } while (0)
+
+#define __init_rwsem(sem, name, key) __rt_init_rwsem(sem, name, key)
-#define init_rwsem(sem) \
+# define rt_init_rwsem(sem) \
do { \
static struct lock_class_key __key; \
\
- __init_rwsem((sem), #sem, &__key); \
+ __rt_init_rwsem((sem), #sem, &__key); \
} while (0)
-static inline int rwsem_is_locked(struct rw_semaphore *sem)
+extern void rt_down_write(struct rw_semaphore *rwsem);
+extern int rt_down_write_killable(struct rw_semaphore *rwsem);
+extern void rt_down_read_nested(struct rw_semaphore *rwsem, int subclass);
+extern void rt_down_write_nested(struct rw_semaphore *rwsem, int subclass);
+extern int rt_down_write_killable_nested(struct rw_semaphore *rwsem,
+ int subclass);
+extern void rt_down_write_nested_lock(struct rw_semaphore *rwsem,
+ struct lockdep_map *nest);
+extern void rt__down_read(struct rw_semaphore *rwsem);
+extern void rt_down_read(struct rw_semaphore *rwsem);
+extern int rt_down_write_trylock(struct rw_semaphore *rwsem);
+extern int rt__down_read_trylock(struct rw_semaphore *rwsem);
+extern int rt_down_read_trylock(struct rw_semaphore *rwsem);
+extern void __rt_up_read(struct rw_semaphore *rwsem);
+extern void rt_up_read(struct rw_semaphore *rwsem);
+extern void rt_up_write(struct rw_semaphore *rwsem);
+extern void rt_downgrade_write(struct rw_semaphore *rwsem);
+
+#define init_rwsem(sem) rt_init_rwsem(sem)
+#define rwsem_is_locked(s) rt_mutex_is_locked(&(s)->lock)
+
+static inline int rwsem_is_contended(struct rw_semaphore *sem)
{
- return atomic_read(&sem->readers) != READER_BIAS;
+ /* rt_mutex_has_waiters() */
+ return !RB_EMPTY_ROOT(&sem->lock.waiters);
}
-static inline int rwsem_is_contended(struct rw_semaphore *sem)
+static inline void __down_read(struct rw_semaphore *sem)
+{
+ rt__down_read(sem);
+}
+
+static inline void down_read(struct rw_semaphore *sem)
+{
+ rt_down_read(sem);
+}
+
+static inline int __down_read_trylock(struct rw_semaphore *sem)
+{
+ return rt__down_read_trylock(sem);
+}
+
+static inline int down_read_trylock(struct rw_semaphore *sem)
+{
+ return rt_down_read_trylock(sem);
+}
+
+static inline void down_write(struct rw_semaphore *sem)
+{
+ rt_down_write(sem);
+}
+
+static inline int down_write_killable(struct rw_semaphore *sem)
+{
+ return rt_down_write_killable(sem);
+}
+
+static inline int down_write_trylock(struct rw_semaphore *sem)
{
- return atomic_read(&sem->readers) > 0;
+ return rt_down_write_trylock(sem);
}
-extern void __down_read(struct rw_semaphore *sem);
-extern int __down_read_trylock(struct rw_semaphore *sem);
-extern void __down_write(struct rw_semaphore *sem);
-extern int __must_check __down_write_killable(struct rw_semaphore *sem);
-extern int __down_write_trylock(struct rw_semaphore *sem);
-extern void __up_read(struct rw_semaphore *sem);
-extern void __up_write(struct rw_semaphore *sem);
-extern void __downgrade_write(struct rw_semaphore *sem);
+static inline void __up_read(struct rw_semaphore *sem)
+{
+ __rt_up_read(sem);
+}
+
+static inline void up_read(struct rw_semaphore *sem)
+{
+ rt_up_read(sem);
+}
+
+static inline void up_write(struct rw_semaphore *sem)
+{
+ rt_up_write(sem);
+}
+
+static inline void downgrade_write(struct rw_semaphore *sem)
+{
+ rt_downgrade_write(sem);
+}
+
+static inline void down_read_nested(struct rw_semaphore *sem, int subclass)
+{
+ return rt_down_read_nested(sem, subclass);
+}
+static inline void down_write_nested(struct rw_semaphore *sem, int subclass)
+{
+ rt_down_write_nested(sem, subclass);
+}
+
+static inline int down_write_killable_nested(struct rw_semaphore *sem,
+ int subclass)
+{
+ return rt_down_write_killable_nested(sem, subclass);
+}
+
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+static inline void down_write_nest_lock(struct rw_semaphore *sem,
+ struct rw_semaphore *nest_lock)
+{
+ rt_down_write_nested_lock(sem, &nest_lock->dep_map);
+}
+
+#else
+
+static inline void down_write_nest_lock(struct rw_semaphore *sem,
+ struct rw_semaphore *nest_lock)
+{
+ rt_down_write_nested_lock(sem, NULL);
+}
+#endif
#endif
diff --git a/kernel/locking/Makefile b/kernel/locking/Makefile
index 6ff9e80..5e27fb1 100644
--- a/kernel/locking/Makefile
+++ b/kernel/locking/Makefile
@@ -14,8 +14,8 @@ endif
ifneq ($(CONFIG_PREEMPT_RT_FULL),y)
obj-y += mutex.o
obj-$(CONFIG_DEBUG_MUTEXES) += mutex-debug.o
-endif
obj-y += rwsem.o
+endif
obj-$(CONFIG_LOCKDEP) += lockdep.o
ifeq ($(CONFIG_PROC_FS),y)
obj-$(CONFIG_LOCKDEP) += lockdep_proc.o
@@ -32,6 +32,6 @@ ifneq ($(CONFIG_PREEMPT_RT_FULL),y)
obj-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
obj-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem-xadd.o
endif
-obj-$(CONFIG_PREEMPT_RT_FULL) += rt.o rwsem-rt.o
+obj-$(CONFIG_PREEMPT_RT_FULL) += rt.o
obj-$(CONFIG_QUEUED_RWLOCKS) += qrwlock.o
obj-$(CONFIG_LOCK_TORTURE_TEST) += locktorture.o
diff --git a/kernel/locking/rt.c b/kernel/locking/rt.c
index 6284e3b..665754c 100644
--- a/kernel/locking/rt.c
+++ b/kernel/locking/rt.c
@@ -306,6 +306,173 @@ void __rt_rwlock_init(rwlock_t *rwlock, char *name, struct lock_class_key *key)
}
EXPORT_SYMBOL(__rt_rwlock_init);
+/*
+ * rw_semaphores
+ */
+
+void rt_up_write(struct rw_semaphore *rwsem)
+{
+ rwsem_release(&rwsem->dep_map, 1, _RET_IP_);
+ rt_mutex_unlock(&rwsem->lock);
+}
+EXPORT_SYMBOL(rt_up_write);
+
+void __rt_up_read(struct rw_semaphore *rwsem)
+{
+ if (--rwsem->read_depth == 0)
+ rt_mutex_unlock(&rwsem->lock);
+}
+
+void rt_up_read(struct rw_semaphore *rwsem)
+{
+ rwsem_release(&rwsem->dep_map, 1, _RET_IP_);
+ __rt_up_read(rwsem);
+}
+EXPORT_SYMBOL(rt_up_read);
+
+/*
+ * downgrade a write lock into a read lock
+ * - just wake up any readers at the front of the queue
+ */
+void rt_downgrade_write(struct rw_semaphore *rwsem)
+{
+ BUG_ON(rt_mutex_owner(&rwsem->lock) != current);
+ rwsem->read_depth = 1;
+}
+EXPORT_SYMBOL(rt_downgrade_write);
+
+int rt_down_write_trylock(struct rw_semaphore *rwsem)
+{
+ int ret = rt_mutex_trylock(&rwsem->lock);
+
+ if (ret)
+ rwsem_acquire(&rwsem->dep_map, 0, 1, _RET_IP_);
+ return ret;
+}
+EXPORT_SYMBOL(rt_down_write_trylock);
+
+void rt_down_write(struct rw_semaphore *rwsem)
+{
+ rwsem_acquire(&rwsem->dep_map, 0, 0, _RET_IP_);
+ rt_mutex_lock(&rwsem->lock);
+}
+EXPORT_SYMBOL(rt_down_write);
+
+int rt_down_write_killable(struct rw_semaphore *rwsem)
+{
+ int ret;
+
+ rwsem_acquire(&rwsem->dep_map, 0, 0, _RET_IP_);
+ ret = rt_mutex_lock_killable(&rwsem->lock);
+ if (ret)
+ rwsem_release(&rwsem->dep_map, 1, _RET_IP_);
+ return ret;
+}
+EXPORT_SYMBOL(rt_down_write_killable);
+
+int rt_down_write_killable_nested(struct rw_semaphore *rwsem, int subclass)
+{
+ int ret;
+
+ rwsem_acquire(&rwsem->dep_map, subclass, 0, _RET_IP_);
+ ret = rt_mutex_lock_killable(&rwsem->lock);
+ if (ret)
+ rwsem_release(&rwsem->dep_map, 1, _RET_IP_);
+ return ret;
+}
+EXPORT_SYMBOL(rt_down_write_killable_nested);
+
+void rt_down_write_nested(struct rw_semaphore *rwsem, int subclass)
+{
+ rwsem_acquire(&rwsem->dep_map, subclass, 0, _RET_IP_);
+ rt_mutex_lock(&rwsem->lock);
+}
+EXPORT_SYMBOL(rt_down_write_nested);
+
+void rt_down_write_nested_lock(struct rw_semaphore *rwsem,
+ struct lockdep_map *nest)
+{
+ rwsem_acquire_nest(&rwsem->dep_map, 0, 0, nest, _RET_IP_);
+ rt_mutex_lock(&rwsem->lock);
+}
+EXPORT_SYMBOL(rt_down_write_nested_lock);
+
+int rt__down_read_trylock(struct rw_semaphore *rwsem)
+{
+ struct rt_mutex *lock = &rwsem->lock;
+ int ret = 1;
+
+ /*
+ * recursive read locks succeed when current owns the rwsem,
+ * but not when read_depth == 0 which means that the rwsem is
+ * write locked.
+ */
+ if (rt_mutex_owner(lock) != current)
+ ret = rt_mutex_trylock(&rwsem->lock);
+ else if (!rwsem->read_depth)
+ ret = 0;
+
+ if (ret)
+ rwsem->read_depth++;
+ return ret;
+
+}
+
+int rt_down_read_trylock(struct rw_semaphore *rwsem)
+{
+ int ret;
+
+ ret = rt__down_read_trylock(rwsem);
+ if (ret)
+ rwsem_acquire(&rwsem->dep_map, 0, 1, _RET_IP_);
+
+ return ret;
+}
+EXPORT_SYMBOL(rt_down_read_trylock);
+
+void rt__down_read(struct rw_semaphore *rwsem)
+{
+ struct rt_mutex *lock = &rwsem->lock;
+
+ if (rt_mutex_owner(lock) != current)
+ rt_mutex_lock(&rwsem->lock);
+ rwsem->read_depth++;
+}
+EXPORT_SYMBOL(rt__down_read);
+
+static void __rt_down_read(struct rw_semaphore *rwsem, int subclass)
+{
+ rwsem_acquire_read(&rwsem->dep_map, subclass, 0, _RET_IP_);
+ rt__down_read(rwsem);
+}
+
+void rt_down_read(struct rw_semaphore *rwsem)
+{
+ __rt_down_read(rwsem, 0);
+}
+EXPORT_SYMBOL(rt_down_read);
+
+void rt_down_read_nested(struct rw_semaphore *rwsem, int subclass)
+{
+ __rt_down_read(rwsem, subclass);
+}
+EXPORT_SYMBOL(rt_down_read_nested);
+
+void __rt_rwsem_init(struct rw_semaphore *rwsem, const char *name,
+ struct lock_class_key *key)
+{
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+ /*
+ * Make sure we are not reinitializing a held lock:
+ */
+ debug_check_no_locks_freed((void *)rwsem, sizeof(*rwsem));
+ lockdep_init_map(&rwsem->dep_map, name, key, 0);
+#endif
+ rwsem->read_depth = 0;
+ rwsem->lock.save_state = 0;
+}
+EXPORT_SYMBOL(__rt_rwsem_init);
+
/**
* atomic_dec_and_mutex_lock - return holding mutex if we dec to 0
* @cnt: the atomic which we are to dec
diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c
index 674ad90..b397dac 100644
--- a/kernel/locking/rtmutex.c
+++ b/kernel/locking/rtmutex.c
@@ -1633,13 +1633,18 @@ __rt_mutex_slowlock(struct rt_mutex *lock, int state,
if (try_to_take_rt_mutex(lock, current, waiter))
break;
- if (timeout && !timeout->task) {
- ret = -ETIMEDOUT;
- break;
- }
- if (signal_pending_state(state, current)) {
- ret = -EINTR;
- break;
+ /*
+ * TASK_INTERRUPTIBLE checks for signals and
+ * timeout. Ignored otherwise.
+ */
+ if (unlikely(state == TASK_INTERRUPTIBLE)) {
+ /* Signal pending? */
+ if (signal_pending(current))
+ ret = -EINTR;
+ if (timeout && !timeout->task)
+ ret = -ETIMEDOUT;
+ if (ret)
+ break;
}
if (ww_ctx && ww_ctx->acquired > 0) {
@@ -1758,18 +1763,36 @@ static void ww_mutex_account_lock(struct rt_mutex *lock,
}
#endif
-int __sched rt_mutex_slowlock_locked(struct rt_mutex *lock, int state,
- struct hrtimer_sleeper *timeout,
- enum rtmutex_chainwalk chwalk,
- struct ww_acquire_ctx *ww_ctx,
- struct rt_mutex_waiter *waiter)
+/*
+ * Slow path lock function:
+ */
+static int __sched
+rt_mutex_slowlock(struct rt_mutex *lock, int state,
+ struct hrtimer_sleeper *timeout,
+ enum rtmutex_chainwalk chwalk,
+ struct ww_acquire_ctx *ww_ctx)
{
- int ret;
+ struct rt_mutex_waiter waiter;
+ unsigned long flags;
+ int ret = 0;
+
+ rt_mutex_init_waiter(&waiter, false);
+
+ /*
+ * Technically we could use raw_spin_[un]lock_irq() here, but this can
+ * be called in early boot if the cmpxchg() fast path is disabled
+ * (debug, no architecture support). In this case we will acquire the
+ * rtmutex with lock->wait_lock held. But we cannot unconditionally
+ * enable interrupts in that early boot case. So we need to use the
+ * irqsave/restore variants.
+ */
+ raw_spin_lock_irqsave(&lock->wait_lock, flags);
/* Try to acquire the lock again: */
if (try_to_take_rt_mutex(lock, current, NULL)) {
if (ww_ctx)
ww_mutex_account_lock(lock, ww_ctx);
+ raw_spin_unlock_irqrestore(&lock->wait_lock, flags);
return 0;
}
@@ -1779,13 +1802,13 @@ int __sched rt_mutex_slowlock_locked(struct rt_mutex *lock, int state,
if (unlikely(timeout))
hrtimer_start_expires(&timeout->timer, HRTIMER_MODE_ABS);
- ret = task_blocks_on_rt_mutex(lock, waiter, current, chwalk);
+ ret = task_blocks_on_rt_mutex(lock, &waiter, current, chwalk);
- if (likely(!ret)) {
+ if (likely(!ret))
/* sleep on the mutex */
- ret = __rt_mutex_slowlock(lock, state, timeout, waiter,
+ ret = __rt_mutex_slowlock(lock, state, timeout, &waiter,
ww_ctx);
- } else if (ww_ctx) {
+ else if (ww_ctx) {
/* ww_mutex received EDEADLK, let it become EALREADY */
ret = __mutex_lock_check_stamp(lock, ww_ctx);
BUG_ON(!ret);
@@ -1794,10 +1817,10 @@ int __sched rt_mutex_slowlock_locked(struct rt_mutex *lock, int state,
if (unlikely(ret)) {
__set_current_state(TASK_RUNNING);
if (rt_mutex_has_waiters(lock))
- remove_waiter(lock, waiter);
+ remove_waiter(lock, &waiter);
/* ww_mutex want to report EDEADLK/EALREADY, let them */
if (!ww_ctx)
- rt_mutex_handle_deadlock(ret, chwalk, waiter);
+ rt_mutex_handle_deadlock(ret, chwalk, &waiter);
} else if (ww_ctx) {
ww_mutex_account_lock(lock, ww_ctx);
}
@@ -1807,36 +1830,6 @@ int __sched rt_mutex_slowlock_locked(struct rt_mutex *lock, int state,
* unconditionally. We might have to fix that up.
*/
fixup_rt_mutex_waiters(lock);
- return ret;
-}
-
-/*
- * Slow path lock function:
- */
-static int __sched
-rt_mutex_slowlock(struct rt_mutex *lock, int state,
- struct hrtimer_sleeper *timeout,
- enum rtmutex_chainwalk chwalk,
- struct ww_acquire_ctx *ww_ctx)
-{
- struct rt_mutex_waiter waiter;
- unsigned long flags;
- int ret = 0;
-
- rt_mutex_init_waiter(&waiter, false);
-
- /*
- * Technically we could use raw_spin_[un]lock_irq() here, but this can
- * be called in early boot if the cmpxchg() fast path is disabled
- * (debug, no architecture support). In this case we will acquire the
- * rtmutex with lock->wait_lock held. But we cannot unconditionally
- * enable interrupts in that early boot case. So we need to use the
- * irqsave/restore variants.
- */
- raw_spin_lock_irqsave(&lock->wait_lock, flags);
-
- ret = rt_mutex_slowlock_locked(lock, state, timeout, chwalk, ww_ctx,
- &waiter);
raw_spin_unlock_irqrestore(&lock->wait_lock, flags);
@@ -2023,32 +2016,21 @@ rt_mutex_fastunlock(struct rt_mutex *lock,
}
/**
- * rt_mutex_lock_state - lock a rt_mutex with a given state
- *
- * @lock: The rt_mutex to be locked
- * @state: The state to set when blocking on the rt_mutex
- */
-int __sched rt_mutex_lock_state(struct rt_mutex *lock, int state)
-{
- might_sleep();
-
- return rt_mutex_fastlock(lock, state, NULL, rt_mutex_slowlock);
-}
-
-/**
* rt_mutex_lock - lock a rt_mutex
*
* @lock: the rt_mutex to be locked
*/
void __sched rt_mutex_lock(struct rt_mutex *lock)
{
- rt_mutex_lock_state(lock, TASK_UNINTERRUPTIBLE);
+ might_sleep();
+
+ rt_mutex_fastlock(lock, TASK_UNINTERRUPTIBLE, NULL, rt_mutex_slowlock);
}
EXPORT_SYMBOL_GPL(rt_mutex_lock);
/**
* rt_mutex_lock_interruptible - lock a rt_mutex interruptible
- **
+ *
* @lock: the rt_mutex to be locked
*
* Returns:
@@ -2057,10 +2039,20 @@ EXPORT_SYMBOL_GPL(rt_mutex_lock);
*/
int __sched rt_mutex_lock_interruptible(struct rt_mutex *lock)
{
- return rt_mutex_lock_state(lock, TASK_INTERRUPTIBLE);
+ might_sleep();
+
+ return rt_mutex_fastlock(lock, TASK_INTERRUPTIBLE, NULL, rt_mutex_slowlock);
}
EXPORT_SYMBOL_GPL(rt_mutex_lock_interruptible);
+/*
+ * Futex variant, must not use fastpath.
+ */
+int __sched rt_mutex_futex_trylock(struct rt_mutex *lock)
+{
+ return rt_mutex_slowtrylock(lock);
+}
+
/**
* rt_mutex_lock_killable - lock a rt_mutex killable
*
@@ -2070,20 +2062,15 @@ EXPORT_SYMBOL_GPL(rt_mutex_lock_interruptible);
* Returns:
* 0 on success
* -EINTR when interrupted by a signal
+ * -EDEADLK when the lock would deadlock (when deadlock detection is on)
*/
int __sched rt_mutex_lock_killable(struct rt_mutex *lock)
{
- return rt_mutex_lock_state(lock, TASK_KILLABLE);
-}
-EXPORT_SYMBOL_GPL(rt_mutex_lock_killable);
+ might_sleep();
-/*
- * Futex variant, must not use fastpath.
- */
-int __sched rt_mutex_futex_trylock(struct rt_mutex *lock)
-{
- return rt_mutex_slowtrylock(lock);
+ return rt_mutex_fastlock(lock, TASK_KILLABLE, NULL, rt_mutex_slowlock);
}
+EXPORT_SYMBOL_GPL(rt_mutex_lock_killable);
/**
* rt_mutex_timed_lock - lock a rt_mutex interruptible
diff --git a/kernel/locking/rtmutex_common.h b/kernel/locking/rtmutex_common.h
index 8198264..59be4bd 100644
--- a/kernel/locking/rtmutex_common.h
+++ b/kernel/locking/rtmutex_common.h
@@ -129,15 +129,6 @@ extern bool __rt_mutex_futex_unlock(struct rt_mutex *lock,
extern void rt_mutex_adjust_prio(struct task_struct *task);
-/* RW semaphore special interface */
-struct ww_acquire_ctx;
-
-int __sched rt_mutex_slowlock_locked(struct rt_mutex *lock, int state,
- struct hrtimer_sleeper *timeout,
- enum rtmutex_chainwalk chwalk,
- struct ww_acquire_ctx *ww_ctx,
- struct rt_mutex_waiter *waiter);
-
#ifdef CONFIG_DEBUG_RT_MUTEXES
# include "rtmutex-debug.h"
#else
diff --git a/kernel/locking/rwsem-rt.c a/kernel/locking/rwsem-rt.c
deleted file mode 100644
index 4a708ff..0000000
--- a/kernel/locking/rwsem-rt.c
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- */
-#include <linux/rwsem.h>
-#include <linux/sched.h>
-#include <linux/export.h>
-
-#include "rtmutex_common.h"
-
-/*
- * RT-specific reader/writer semaphores
- *
- * down_write()
- * 1) Lock sem->rtmutex
- * 2) Remove the reader BIAS to force readers into the slow path
- * 3) Wait until all readers have left the critical region
- * 4) Mark it write locked
- *
- * up_write()
- * 1) Remove the write locked marker
- * 2) Set the reader BIAS so readers can use the fast path again
- * 3) Unlock sem->rtmutex to release blocked readers
- *
- * down_read()
- * 1) Try fast path acquisition (reader BIAS is set)
- * 2) Take sem->rtmutex.wait_lock which protects the writelocked flag
- * 3) If !writelocked, acquire it for read
- * 4) If writelocked, block on sem->rtmutex
- * 5) unlock sem->rtmutex, goto 1)
- *
- * up_read()
- * 1) Try fast path release (reader count != 1)
- * 2) Wake the writer waiting in down_write()#3
- *
- * down_read()#3 has the consequence, that rw semaphores on RT are not writer
- * fair, but writers, which should be avoided in RT tasks (think mmap_sem),
- * are subject to the rtmutex priority/DL inheritance mechanism.
- *
- * It's possible to make the rw semaphores writer fair by keeping a list of
- * active readers. A blocked writer would force all newly incoming readers to
- * block on the rtmutex, but the rtmutex would have to be proxy locked for one
- * reader after the other. We can't use multi-reader inheritance because there
- * is no way to support that with SCHED_DEADLINE. Implementing the one by one
- * reader boosting/handover mechanism is a major surgery for a very dubious
- * value.
- *
- * The risk of writer starvation is there, but the pathological use cases
- * which trigger it are not necessarily the typical RT workloads.
- */
-
-void __rwsem_init(struct rw_semaphore *sem, const char *name,
- struct lock_class_key *key)
-{
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
- /*
- * Make sure we are not reinitializing a held semaphore:
- */
- debug_check_no_locks_freed((void *)sem, sizeof(*sem));
- lockdep_init_map(&sem->dep_map, name, key, 0);
-#endif
- atomic_set(&sem->readers, READER_BIAS);
-}
-EXPORT_SYMBOL(__rwsem_init);
-
-int __down_read_trylock(struct rw_semaphore *sem)
-{
- int r, old;
-
- /*
- * Increment reader count, if sem->readers < 0, i.e. READER_BIAS is
- * set.
- */
- for (r = atomic_read(&sem->readers); r < 0;) {
- old = atomic_cmpxchg(&sem->readers, r, r + 1);
- if (likely(old == r))
- return 1;
- r = old;
- }
- return 0;
-}
-
-void __sched __down_read(struct rw_semaphore *sem)
-{
- struct rt_mutex *m = &sem->rtmutex;
- struct rt_mutex_waiter waiter;
-
- if (__down_read_trylock(sem))
- return;
-
- might_sleep();
- raw_spin_lock_irq(&m->wait_lock);
- /*
- * Allow readers as long as the writer has not completely
- * acquired the semaphore for write.
- */
- if (atomic_read(&sem->readers) != WRITER_BIAS) {
- atomic_inc(&sem->readers);
- raw_spin_unlock_irq(&m->wait_lock);
- return;
- }
-
- /*
- * Call into the slow lock path with the rtmutex->wait_lock
- * held, so this can't result in the following race:
- *
- * Reader1 Reader2 Writer
- * down_read()
- * down_write()
- * rtmutex_lock(m)
- * swait()
- * down_read()
- * unlock(m->wait_lock)
- * up_read()
- * swake()
- * lock(m->wait_lock)
- * sem->writelocked=true
- * unlock(m->wait_lock)
- *
- * up_write()
- * sem->writelocked=false
- * rtmutex_unlock(m)
- * down_read()
- * down_write()
- * rtmutex_lock(m)
- * swait()
- * rtmutex_lock(m)
- *
- * That would put Reader1 behind the writer waiting on
- * Reader2 to call up_read() which might be unbound.
- */
- rt_mutex_init_waiter(&waiter, false);
- rt_mutex_slowlock_locked(m, TASK_UNINTERRUPTIBLE, NULL,
- RT_MUTEX_MIN_CHAINWALK, NULL,
- &waiter);
- /*
- * The slowlock() above is guaranteed to return with the rtmutex is
- * now held, so there can't be a writer active. Increment the reader
- * count and immediately drop the rtmutex again.
- */
- atomic_inc(&sem->readers);
- raw_spin_unlock_irq(&m->wait_lock);
- rt_mutex_unlock(m);
-
- debug_rt_mutex_free_waiter(&waiter);
-}
-
-void __up_read(struct rw_semaphore *sem)
-{
- struct rt_mutex *m = &sem->rtmutex;
- struct task_struct *tsk;
-
- /*
- * sem->readers can only hit 0 when a writer is waiting for the
- * active readers to leave the critical region.
- */
- if (!atomic_dec_and_test(&sem->readers))
- return;
-
- might_sleep();
- raw_spin_lock_irq(&m->wait_lock);
- /*
- * Wake the writer, i.e. the rtmutex owner. It might release the
- * rtmutex concurrently in the fast path (due to a signal), but to
- * clean up the rwsem it needs to acquire m->wait_lock. The worst
- * case which can happen is a spurious wakeup.
- */
- tsk = rt_mutex_owner(m);
- if (tsk)
- wake_up_process(tsk);
-
- raw_spin_unlock_irq(&m->wait_lock);
-}
-
-static void __up_write_unlock(struct rw_semaphore *sem, int bias,
- unsigned long flags)
-{
- struct rt_mutex *m = &sem->rtmutex;
-
- atomic_add(READER_BIAS - bias, &sem->readers);
- raw_spin_unlock_irqrestore(&m->wait_lock, flags);
- rt_mutex_unlock(m);
-}
-
-static int __sched __down_write_common(struct rw_semaphore *sem, int state)
-{
- struct rt_mutex *m = &sem->rtmutex;
- unsigned long flags;
-
- /* Take the rtmutex as a first step */
- if (rt_mutex_lock_state(m, state))
- return -EINTR;
-
- /* Force readers into slow path */
- atomic_sub(READER_BIAS, &sem->readers);
- might_sleep();
-
- set_current_state(state);
- for (;;) {
- raw_spin_lock_irqsave(&m->wait_lock, flags);
- /* Have all readers left the critical region? */
- if (!atomic_read(&sem->readers)) {
- atomic_set(&sem->readers, WRITER_BIAS);
- __set_current_state(TASK_RUNNING);
- raw_spin_unlock_irqrestore(&m->wait_lock, flags);
- return 0;
- }
-
- if (signal_pending_state(state, current)) {
- __set_current_state(TASK_RUNNING);
- __up_write_unlock(sem, 0, flags);
- return -EINTR;
- }
- raw_spin_unlock_irqrestore(&m->wait_lock, flags);
-
- if (atomic_read(&sem->readers) != 0) {
- schedule();
- set_current_state(state);
- }
- }
-}
-
-void __sched __down_write(struct rw_semaphore *sem)
-{
- __down_write_common(sem, TASK_UNINTERRUPTIBLE);
-}
-
-int __sched __down_write_killable(struct rw_semaphore *sem)
-{
- return __down_write_common(sem, TASK_KILLABLE);
-}
-
-int __down_write_trylock(struct rw_semaphore *sem)
-{
- struct rt_mutex *m = &sem->rtmutex;
- unsigned long flags;
-
- if (!rt_mutex_trylock(m))
- return 0;
-
- atomic_sub(READER_BIAS, &sem->readers);
-
- raw_spin_lock_irqsave(&m->wait_lock, flags);
- if (!atomic_read(&sem->readers)) {
- atomic_set(&sem->readers, WRITER_BIAS);
- raw_spin_unlock_irqrestore(&m->wait_lock, flags);
- return 1;
- }
- __up_write_unlock(sem, 0, flags);
- return 0;
-}
-
-void __up_write(struct rw_semaphore *sem)
-{
- struct rt_mutex *m = &sem->rtmutex;
- unsigned long flags;
-
- raw_spin_lock_irqsave(&m->wait_lock, flags);
- __up_write_unlock(sem, WRITER_BIAS, flags);
-}
-
-void __downgrade_write(struct rw_semaphore *sem)
-{
- struct rt_mutex *m = &sem->rtmutex;
- unsigned long flags;
-
- raw_spin_lock_irqsave(&m->wait_lock, flags);
- /* Release it and account current as reader */
- __up_write_unlock(sem, WRITER_BIAS - 1, flags);
-}
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 0967771..319e09d 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -35,6 +35,7 @@
#ifdef CONFIG_BLOCK
#include <linux/blkdev.h>
#endif
+#include <linux/of.h>
#include "../mm/internal.h" /* For the trace_print_flags arrays */
@@ -1470,6 +1471,141 @@ char *flags_string(char *buf, char *end, void *flags_ptr, const char *fmt)
return format_flags(buf, end, flags, names);
}
+/* helper method for calculating extends on first pass and filling in later */
+static noinline_for_stack
+void append_str(const char *str, int pass, int *lenp, char **bufp, char *end)
+{
+ int len;
+
+ len = strlen(str);
+ if (pass == 1)
+ *lenp += len;
+ else {
+ if (len > (end - *bufp))
+ len = end - *bufp;
+ memcpy(*bufp, str, len);
+ *bufp += len;
+ }
+}
+
+static noinline_for_stack
+char *device_node_string(char *buf, char *end, struct device_node *dn,
+ struct printf_spec spec, const char *fmt)
+{
+ char tbuf[sizeof("xxxxxxxxxx") + 1];
+ const char *fmtp, *p;
+ int len, ret, i, j, pass;
+ char c;
+
+ if (!IS_ENABLED(CONFIG_OF)) {
+ /* if OF is not enabled just print the pointer */
+ spec.flags |= SMALL;
+ if (spec.field_width == -1) {
+ spec.field_width = 2 * sizeof(void *);
+ spec.flags |= ZEROPAD;
+ }
+ spec.base = 16;
+ return number(buf, end, (unsigned long) dn, spec);
+ }
+
+ if ((unsigned long)dn < PAGE_SIZE)
+ return string(buf, end, "(null)", spec);
+
+ /* simple case without anything any more format specifiers */
+ if (fmt[1] == '\0' || isspace(fmt[1]))
+ fmt = "Of";
+
+ len = 0;
+
+ /* two passes; the first calculates length, the second fills in */
+ for (pass = 1; pass <= 2; pass++) {
+ if (pass == 2 && !(spec.flags & LEFT)) {
+ /* padding */
+ while (len < spec.field_width--) {
+ if (buf < end)
+ *buf = ' ';
+ ++buf;
+ }
+ }
+
+ for (fmtp = fmt + 1, j = 0; (c = *fmtp++) != '\0'; ) {
+
+ /* validate option */
+ if (c != 'f' && c != 'n' && c != 'p' && c != 'P' &&
+ c != 'F' && c != 'c' && c != 'C' && c != 'r')
+ continue;
+
+ /* handle separator */
+ if (j++ > 0)
+ append_str("|", pass, &len, &buf, end);
+
+ switch (c) {
+ case 'f': /* full_name */
+ append_str(of_node_full_name(dn), pass, &len,
+ &buf, end);
+ break;
+ case 'n': /* name */
+ append_str(dn->name, pass, &len, &buf, end);
+ break;
+ case 'p': /* phandle */
+ snprintf(tbuf, sizeof(tbuf), "%u",
+ (unsigned int)dn->phandle);
+ append_str(tbuf, pass, &len, &buf, end);
+ break;
+ case 'P': /* path-spec */
+ append_str(dn->name, pass, &len, &buf, end);
+ /* need to tack on the @ postfix */
+ p = strchr(of_node_full_name(dn), '@');
+ if (p)
+ append_str(p, pass, &len, &buf, end);
+ break;
+ case 'F': /* flags */
+ snprintf(tbuf, sizeof(tbuf), "%c%c%c%c",
+ of_node_check_flag(dn, OF_DYNAMIC) ?
+ 'D' : '-',
+ of_node_check_flag(dn, OF_DETACHED) ?
+ 'd' : '-',
+ of_node_check_flag(dn, OF_POPULATED) ?
+ 'P' : '-',
+ of_node_check_flag(dn,
+ OF_POPULATED_BUS) ? 'B' : '-');
+ append_str(tbuf, pass, &len, &buf, end);
+ break;
+ case 'c': /* major compatible string */
+ ret = of_property_read_string(dn, "compatible",
+ &p);
+ if (ret == 0)
+ append_str(p, pass, &len, &buf, end);
+ break;
+ case 'C': /* full compatible string */
+ i = 0;
+ while (of_property_read_string_index(dn,
+ "compatible", i, &p) == 0) {
+ append_str(i == 0 ? "\"" : "\",\"",
+ pass, &len, &buf, end);
+ append_str(p, pass, &len, &buf, end);
+ i++;
+ }
+ if (i > 0)
+ append_str("\"", pass, &len, &buf, end);
+ break;
+ case 'r': /* node reference count */
+ snprintf(tbuf, sizeof(tbuf), "%u",
+ atomic_read(&dn->kobj.kref.refcount));
+ append_str(tbuf, pass, &len, &buf, end);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ /* finish up */
+ while (buf < end && len < spec.field_width--)
+ *buf++ = ' ';
+
+ return buf;
+}
+
int kptr_restrict __read_mostly;
/*
@@ -1563,6 +1699,16 @@ int kptr_restrict __read_mostly;
* p page flags (see struct page) given as pointer to unsigned long
* g gfp flags (GFP_* and __GFP_*) given as pointer to gfp_t
* v vma flags (VM_*) given as pointer to unsigned long
+ * - 'O[fnpPcCFr]' For an DT device node
+ * Without any optional arguments prints the full_name
+ * f device node full_name
+ * n device node name
+ * p device node phandle
+ * P device node path spec (name + @unit)
+ * F device node flags
+ * c major compatible string
+ * C full compatible string
+ * r node reference count
*
* ** Please update also Documentation/printk-formats.txt when making changes **
*
@@ -1718,6 +1864,10 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
case 'G':
return flags_string(buf, end, ptr, fmt);
+
+ case 'O':
+ return device_node_string(buf, end, ptr, spec, fmt);
+
}
spec.flags |= SMALL;
if (spec.field_width == -1) {
diff --git a/localversion-rt a/localversion-rt
deleted file mode 100644
index 1199eba..0000000
--- a/localversion-rt
+++ /dev/null
@@ -1 +0,0 @@
--rt16
diff --git a/samples/seccomp/Makefile b/samples/seccomp/Makefile
index ae7ff6f..7659beb 100644
--- a/samples/seccomp/Makefile
+++ b/samples/seccomp/Makefile
@@ -20,6 +20,7 @@ bpf-direct-objs := bpf-direct.o
# Try to match the kernel target.
ifndef CROSS_COMPILE
ifndef CONFIG_64BIT
+ifndef CONFIG_ARM
# s390 has -m31 flag to build 31 bit binaries
ifndef CONFIG_S390
@@ -46,3 +47,4 @@ ifndef CONFIG_MIPS
always := $(hostprogs-y)
endif
endif
+endif
diff --git a/scripts/dtc/checks.c b/scripts/dtc/checks.c
index 386f956..38f548e 100644
--- a/scripts/dtc/checks.c
+++ b/scripts/dtc/checks.c
@@ -40,16 +40,11 @@ enum checkstatus {
struct check;
-typedef void (*tree_check_fn)(struct check *c, struct node *dt);
-typedef void (*node_check_fn)(struct check *c, struct node *dt, struct node *node);
-typedef void (*prop_check_fn)(struct check *c, struct node *dt,
- struct node *node, struct property *prop);
+typedef void (*check_fn)(struct check *c, struct dt_info *dti, struct node *node);
struct check {
const char *name;
- tree_check_fn tree_fn;
- node_check_fn node_fn;
- prop_check_fn prop_fn;
+ check_fn fn;
void *data;
bool warn, error;
enum checkstatus status;
@@ -58,57 +53,35 @@ struct check {
struct check **prereq;
};
-#define CHECK_ENTRY(nm, tfn, nfn, pfn, d, w, e, ...) \
- static struct check *nm##_prereqs[] = { __VA_ARGS__ }; \
- static struct check nm = { \
- .name = #nm, \
- .tree_fn = (tfn), \
- .node_fn = (nfn), \
- .prop_fn = (pfn), \
- .data = (d), \
- .warn = (w), \
- .error = (e), \
+#define CHECK_ENTRY(_nm, _fn, _d, _w, _e, ...) \
+ static struct check *_nm##_prereqs[] = { __VA_ARGS__ }; \
+ static struct check _nm = { \
+ .name = #_nm, \
+ .fn = (_fn), \
+ .data = (_d), \
+ .warn = (_w), \
+ .error = (_e), \
.status = UNCHECKED, \
- .num_prereqs = ARRAY_SIZE(nm##_prereqs), \
- .prereq = nm##_prereqs, \
+ .num_prereqs = ARRAY_SIZE(_nm##_prereqs), \
+ .prereq = _nm##_prereqs, \
};
-#define WARNING(nm, tfn, nfn, pfn, d, ...) \
- CHECK_ENTRY(nm, tfn, nfn, pfn, d, true, false, __VA_ARGS__)
-#define ERROR(nm, tfn, nfn, pfn, d, ...) \
- CHECK_ENTRY(nm, tfn, nfn, pfn, d, false, true, __VA_ARGS__)
-#define CHECK(nm, tfn, nfn, pfn, d, ...) \
- CHECK_ENTRY(nm, tfn, nfn, pfn, d, false, false, __VA_ARGS__)
-
-#define TREE_WARNING(nm, d, ...) \
- WARNING(nm, check_##nm, NULL, NULL, d, __VA_ARGS__)
-#define TREE_ERROR(nm, d, ...) \
- ERROR(nm, check_##nm, NULL, NULL, d, __VA_ARGS__)
-#define TREE_CHECK(nm, d, ...) \
- CHECK(nm, check_##nm, NULL, NULL, d, __VA_ARGS__)
-#define NODE_WARNING(nm, d, ...) \
- WARNING(nm, NULL, check_##nm, NULL, d, __VA_ARGS__)
-#define NODE_ERROR(nm, d, ...) \
- ERROR(nm, NULL, check_##nm, NULL, d, __VA_ARGS__)
-#define NODE_CHECK(nm, d, ...) \
- CHECK(nm, NULL, check_##nm, NULL, d, __VA_ARGS__)
-#define PROP_WARNING(nm, d, ...) \
- WARNING(nm, NULL, NULL, check_##nm, d, __VA_ARGS__)
-#define PROP_ERROR(nm, d, ...) \
- ERROR(nm, NULL, NULL, check_##nm, d, __VA_ARGS__)
-#define PROP_CHECK(nm, d, ...) \
- CHECK(nm, NULL, NULL, check_##nm, d, __VA_ARGS__)
-
-#ifdef __GNUC__
-static inline void check_msg(struct check *c, const char *fmt, ...) __attribute__((format (printf, 2, 3)));
-#endif
-static inline void check_msg(struct check *c, const char *fmt, ...)
+#define WARNING(_nm, _fn, _d, ...) \
+ CHECK_ENTRY(_nm, _fn, _d, true, false, __VA_ARGS__)
+#define ERROR(_nm, _fn, _d, ...) \
+ CHECK_ENTRY(_nm, _fn, _d, false, true, __VA_ARGS__)
+#define CHECK(_nm, _fn, _d, ...) \
+ CHECK_ENTRY(_nm, _fn, _d, false, false, __VA_ARGS__)
+
+static inline void PRINTF(3, 4) check_msg(struct check *c, struct dt_info *dti,
+ const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
if ((c->warn && (quiet < 1))
|| (c->error && (quiet < 2))) {
- fprintf(stderr, "%s (%s): ",
+ fprintf(stderr, "%s: %s (%s): ",
+ strcmp(dti->outname, "-") ? dti->outname : "<stdout>",
(c->error) ? "ERROR" : "Warning", c->name);
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
@@ -116,34 +89,28 @@ static inline void check_msg(struct check *c, const char *fmt, ...)
va_end(ap);
}
-#define FAIL(c, ...) \
- do { \
- TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__); \
- (c)->status = FAILED; \
- check_msg((c), __VA_ARGS__); \
+#define FAIL(c, dti, ...) \
+ do { \
+ TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__); \
+ (c)->status = FAILED; \
+ check_msg((c), dti, __VA_ARGS__); \
} while (0)
-static void check_nodes_props(struct check *c, struct node *dt, struct node *node)
+static void check_nodes_props(struct check *c, struct dt_info *dti, struct node *node)
{
struct node *child;
- struct property *prop;
TRACE(c, "%s", node->fullpath);
- if (c->node_fn)
- c->node_fn(c, dt, node);
-
- if (c->prop_fn)
- for_each_property(node, prop) {
- TRACE(c, "%s\t'%s'", node->fullpath, prop->name);
- c->prop_fn(c, dt, node, prop);
- }
+ if (c->fn)
+ c->fn(c, dti, node);
for_each_child(node, child)
- check_nodes_props(c, dt, child);
+ check_nodes_props(c, dti, child);
}
-static bool run_check(struct check *c, struct node *dt)
+static bool run_check(struct check *c, struct dt_info *dti)
{
+ struct node *dt = dti->dt;
bool error = false;
int i;
@@ -156,10 +123,10 @@ static bool run_check(struct check *c, struct node *dt)
for (i = 0; i < c->num_prereqs; i++) {
struct check *prq = c->prereq[i];
- error = error || run_check(prq, dt);
+ error = error || run_check(prq, dti);
if (prq->status != PASSED) {
c->status = PREREQ;
- check_msg(c, "Failed prerequisite '%s'",
+ check_msg(c, dti, "Failed prerequisite '%s'",
c->prereq[i]->name);
}
}
@@ -167,11 +134,8 @@ static bool run_check(struct check *c, struct node *dt)
if (c->status != UNCHECKED)
goto out;
- if (c->node_fn || c->prop_fn)
- check_nodes_props(c, dt, dt);
+ check_nodes_props(c, dti, dt);
- if (c->tree_fn)
- c->tree_fn(c, dt);
if (c->status == UNCHECKED)
c->status = PASSED;
@@ -189,13 +153,14 @@ static bool run_check(struct check *c, struct node *dt)
*/
/* A check which always fails, for testing purposes only */
-static inline void check_always_fail(struct check *c, struct node *dt)
+static inline void check_always_fail(struct check *c, struct dt_info *dti,
+ struct node *node)
{
- FAIL(c, "always_fail check");
+ FAIL(c, dti, "always_fail check");
}
-TREE_CHECK(always_fail, NULL);
+CHECK(always_fail, check_always_fail, NULL);
-static void check_is_string(struct check *c, struct node *root,
+static void check_is_string(struct check *c, struct dt_info *dti,
struct node *node)
{
struct property *prop;
@@ -206,15 +171,15 @@ static void check_is_string(struct check *c, struct node *root,
return; /* Not present, assumed ok */
if (!data_is_one_string(prop->val))
- FAIL(c, "\"%s\" property in %s is not a string",
+ FAIL(c, dti, "\"%s\" property in %s is not a string",
propname, node->fullpath);
}
#define WARNING_IF_NOT_STRING(nm, propname) \
- WARNING(nm, NULL, check_is_string, NULL, (propname))
+ WARNING(nm, check_is_string, (propname))
#define ERROR_IF_NOT_STRING(nm, propname) \
- ERROR(nm, NULL, check_is_string, NULL, (propname))
+ ERROR(nm, check_is_string, (propname))
-static void check_is_cell(struct check *c, struct node *root,
+static void check_is_cell(struct check *c, struct dt_info *dti,
struct node *node)
{
struct property *prop;
@@ -225,19 +190,19 @@ static void check_is_cell(struct check *c, struct node *root,
return; /* Not present, assumed ok */
if (prop->val.len != sizeof(cell_t))
- FAIL(c, "\"%s\" property in %s is not a single cell",
+ FAIL(c, dti, "\"%s\" property in %s is not a single cell",
propname, node->fullpath);
}
#define WARNING_IF_NOT_CELL(nm, propname) \
- WARNING(nm, NULL, check_is_cell, NULL, (propname))
+ WARNING(nm, check_is_cell, (propname))
#define ERROR_IF_NOT_CELL(nm, propname) \
- ERROR(nm, NULL, check_is_cell, NULL, (propname))
+ ERROR(nm, check_is_cell, (propname))
/*
* Structural check functions
*/
-static void check_duplicate_node_names(struct check *c, struct node *dt,
+static void check_duplicate_node_names(struct check *c, struct dt_info *dti,
struct node *node)
{
struct node *child, *child2;
@@ -247,12 +212,12 @@ static void check_duplicate_node_names(struct check *c, struct node *dt,
child2;
child2 = child2->next_sibling)
if (streq(child->name, child2->name))
- FAIL(c, "Duplicate node name %s",
+ FAIL(c, dti, "Duplicate node name %s",
child->fullpath);
}
-NODE_ERROR(duplicate_node_names, NULL);
+ERROR(duplicate_node_names, check_duplicate_node_names, NULL);
-static void check_duplicate_property_names(struct check *c, struct node *dt,
+static void check_duplicate_property_names(struct check *c, struct dt_info *dti,
struct node *node)
{
struct property *prop, *prop2;
@@ -262,40 +227,52 @@ static void check_duplicate_property_names(struct check *c, struct node *dt,
if (prop2->deleted)
continue;
if (streq(prop->name, prop2->name))
- FAIL(c, "Duplicate property name %s in %s",
+ FAIL(c, dti, "Duplicate property name %s in %s",
prop->name, node->fullpath);
}
}
}
-NODE_ERROR(duplicate_property_names, NULL);
+ERROR(duplicate_property_names, check_duplicate_property_names, NULL);
#define LOWERCASE "abcdefghijklmnopqrstuvwxyz"
#define UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
#define DIGITS "0123456789"
#define PROPNODECHARS LOWERCASE UPPERCASE DIGITS ",._+*#?-"
+#define PROPNODECHARSSTRICT LOWERCASE UPPERCASE DIGITS ",-"
-static void check_node_name_chars(struct check *c, struct node *dt,
+static void check_node_name_chars(struct check *c, struct dt_info *dti,
struct node *node)
{
int n = strspn(node->name, c->data);
if (n < strlen(node->name))
- FAIL(c, "Bad character '%c' in node %s",
+ FAIL(c, dti, "Bad character '%c' in node %s",
node->name[n], node->fullpath);
}
-NODE_ERROR(node_name_chars, PROPNODECHARS "@");
+ERROR(node_name_chars, check_node_name_chars, PROPNODECHARS "@");
-static void check_node_name_format(struct check *c, struct node *dt,
+static void check_node_name_chars_strict(struct check *c, struct dt_info *dti,
+ struct node *node)
+{
+ int n = strspn(node->name, c->data);
+
+ if (n < node->basenamelen)
+ FAIL(c, dti, "Character '%c' not recommended in node %s",
+ node->name[n], node->fullpath);
+}
+CHECK(node_name_chars_strict, check_node_name_chars_strict, PROPNODECHARSSTRICT);
+
+static void check_node_name_format(struct check *c, struct dt_info *dti,
struct node *node)
{
if (strchr(get_unitname(node), '@'))
- FAIL(c, "Node %s has multiple '@' characters in name",
+ FAIL(c, dti, "Node %s has multiple '@' characters in name",
node->fullpath);
}
-NODE_ERROR(node_name_format, NULL, &node_name_chars);
+ERROR(node_name_format, check_node_name_format, NULL, &node_name_chars);
-static void check_unit_address_vs_reg(struct check *c, struct node *dt,
- struct node *node)
+static void check_unit_address_vs_reg(struct check *c, struct dt_info *dti,
+ struct node *node)
{
const char *unitname = get_unitname(node);
struct property *prop = get_property(node, "reg");
@@ -308,26 +285,62 @@ static void check_unit_address_vs_reg(struct check *c, struct node *dt,
if (prop) {
if (!unitname[0])
- FAIL(c, "Node %s has a reg or ranges property, but no unit name",
+ FAIL(c, dti, "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",
+ FAIL(c, dti, "Node %s has a unit name, but no reg property",
node->fullpath);
}
}
-NODE_WARNING(unit_address_vs_reg, NULL);
+WARNING(unit_address_vs_reg, check_unit_address_vs_reg, NULL);
+
+static void check_property_name_chars(struct check *c, struct dt_info *dti,
+ struct node *node)
+{
+ struct property *prop;
+
+ for_each_property(node, prop) {
+ int n = strspn(prop->name, c->data);
+
+ if (n < strlen(prop->name))
+ FAIL(c, dti, "Bad character '%c' in property name \"%s\", node %s",
+ prop->name[n], prop->name, node->fullpath);
+ }
+}
+ERROR(property_name_chars, check_property_name_chars, PROPNODECHARS);
-static void check_property_name_chars(struct check *c, struct node *dt,
- struct node *node, struct property *prop)
+static void check_property_name_chars_strict(struct check *c,
+ struct dt_info *dti,
+ struct node *node)
{
- int n = strspn(prop->name, c->data);
+ struct property *prop;
+
+ for_each_property(node, prop) {
+ const char *name = prop->name;
+ int n = strspn(name, c->data);
+
+ if (n == strlen(prop->name))
+ continue;
+
+ /* Certain names are whitelisted */
+ if (streq(name, "device_type"))
+ continue;
- if (n < strlen(prop->name))
- FAIL(c, "Bad character '%c' in property name \"%s\", node %s",
- prop->name[n], prop->name, node->fullpath);
+ /*
+ * # is only allowed at the beginning of property names not counting
+ * the vendor prefix.
+ */
+ if (name[n] == '#' && ((n == 0) || (name[n-1] == ','))) {
+ name += n + 1;
+ n = strspn(name, c->data);
+ }
+ if (n < strlen(name))
+ FAIL(c, dti, "Character '%c' not recommended in property name \"%s\", node %s",
+ name[n], prop->name, node->fullpath);
+ }
}
-PROP_ERROR(property_name_chars, PROPNODECHARS);
+CHECK(property_name_chars_strict, check_property_name_chars_strict, PROPNODECHARSSTRICT);
#define DESCLABEL_FMT "%s%s%s%s%s"
#define DESCLABEL_ARGS(node,prop,mark) \
@@ -336,10 +349,11 @@ PROP_ERROR(property_name_chars, PROPNODECHARS);
((prop) ? (prop)->name : ""), \
((prop) ? "' in " : ""), (node)->fullpath
-static void check_duplicate_label(struct check *c, struct node *dt,
+static void check_duplicate_label(struct check *c, struct dt_info *dti,
const char *label, struct node *node,
struct property *prop, struct marker *mark)
{
+ struct node *dt = dti->dt;
struct node *othernode = NULL;
struct property *otherprop = NULL;
struct marker *othermark = NULL;
@@ -356,50 +370,49 @@ static void check_duplicate_label(struct check *c, struct node *dt,
return;
if ((othernode != node) || (otherprop != prop) || (othermark != mark))
- FAIL(c, "Duplicate label '%s' on " DESCLABEL_FMT
+ FAIL(c, dti, "Duplicate label '%s' on " DESCLABEL_FMT
" and " DESCLABEL_FMT,
label, DESCLABEL_ARGS(node, prop, mark),
DESCLABEL_ARGS(othernode, otherprop, othermark));
}
-static void check_duplicate_label_node(struct check *c, struct node *dt,
+static void check_duplicate_label_node(struct check *c, struct dt_info *dti,
struct node *node)
{
struct label *l;
+ struct property *prop;
for_each_label(node->labels, l)
- check_duplicate_label(c, dt, l->label, node, NULL, NULL);
-}
-static void check_duplicate_label_prop(struct check *c, struct node *dt,
- struct node *node, struct property *prop)
-{
- struct marker *m = prop->val.markers;
- struct label *l;
+ check_duplicate_label(c, dti, l->label, node, NULL, NULL);
- for_each_label(prop->labels, l)
- check_duplicate_label(c, dt, l->label, node, prop, NULL);
+ for_each_property(node, prop) {
+ struct marker *m = prop->val.markers;
- for_each_marker_of_type(m, LABEL)
- check_duplicate_label(c, dt, m->ref, node, prop, m);
+ for_each_label(prop->labels, l)
+ check_duplicate_label(c, dti, l->label, node, prop, NULL);
+
+ for_each_marker_of_type(m, LABEL)
+ check_duplicate_label(c, dti, m->ref, node, prop, m);
+ }
}
-ERROR(duplicate_label, NULL, check_duplicate_label_node,
- check_duplicate_label_prop, NULL);
+ERROR(duplicate_label, check_duplicate_label_node, NULL);
-static void check_explicit_phandles(struct check *c, struct node *root,
- struct node *node, struct property *prop)
+static cell_t check_phandle_prop(struct check *c, struct dt_info *dti,
+ struct node *node, const char *propname)
{
+ struct node *root = dti->dt;
+ struct property *prop;
struct marker *m;
- struct node *other;
cell_t phandle;
- if (!streq(prop->name, "phandle")
- && !streq(prop->name, "linux,phandle"))
- return;
+ prop = get_property(node, propname);
+ if (!prop)
+ return 0;
if (prop->val.len != sizeof(cell_t)) {
- FAIL(c, "%s has bad length (%d) %s property",
+ FAIL(c, dti, "%s has bad length (%d) %s property",
node->fullpath, prop->val.len, prop->name);
- return;
+ return 0;
}
m = prop->val.markers;
@@ -409,42 +422,65 @@ static void check_explicit_phandles(struct check *c, struct node *root,
/* "Set this node's phandle equal to some
* other node's phandle". That's nonsensical
* by construction. */ {
- FAIL(c, "%s in %s is a reference to another node",
+ FAIL(c, dti, "%s in %s is a reference to another node",
prop->name, node->fullpath);
- return;
}
/* But setting this node's phandle equal to its own
* phandle is allowed - that means allocate a unique
* phandle for this node, even if it's not otherwise
* referenced. The value will be filled in later, so
- * no further checking for now. */
- return;
+ * we treat it as having no phandle data for now. */
+ return 0;
}
phandle = propval_cell(prop);
if ((phandle == 0) || (phandle == -1)) {
- FAIL(c, "%s has bad value (0x%x) in %s property",
+ FAIL(c, dti, "%s has bad value (0x%x) in %s property",
node->fullpath, phandle, prop->name);
- return;
+ return 0;
}
- if (node->phandle && (node->phandle != phandle))
- FAIL(c, "%s has %s property which replaces existing phandle information",
- node->fullpath, prop->name);
+ return phandle;
+}
+
+static void check_explicit_phandles(struct check *c, struct dt_info *dti,
+ struct node *node)
+{
+ struct node *root = dti->dt;
+ struct node *other;
+ cell_t phandle, linux_phandle;
+
+ /* Nothing should have assigned phandles yet */
+ assert(!node->phandle);
+
+ phandle = check_phandle_prop(c, dti, node, "phandle");
+
+ linux_phandle = check_phandle_prop(c, dti, node, "linux,phandle");
+
+ if (!phandle && !linux_phandle)
+ /* No valid phandles; nothing further to check */
+ return;
+
+ if (linux_phandle && phandle && (phandle != linux_phandle))
+ FAIL(c, dti, "%s has mismatching 'phandle' and 'linux,phandle'"
+ " properties", node->fullpath);
+
+ if (linux_phandle && !phandle)
+ phandle = linux_phandle;
other = get_node_by_phandle(root, phandle);
if (other && (other != node)) {
- FAIL(c, "%s has duplicated phandle 0x%x (seen before at %s)",
+ FAIL(c, dti, "%s has duplicated phandle 0x%x (seen before at %s)",
node->fullpath, phandle, other->fullpath);
return;
}
node->phandle = phandle;
}
-PROP_ERROR(explicit_phandles, NULL);
+ERROR(explicit_phandles, check_explicit_phandles, NULL);
-static void check_name_properties(struct check *c, struct node *root,
+static void check_name_properties(struct check *c, struct dt_info *dti,
struct node *node)
{
struct property **pp, *prop = NULL;
@@ -460,7 +496,7 @@ static void check_name_properties(struct check *c, struct node *root,
if ((prop->val.len != node->basenamelen+1)
|| (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) {
- FAIL(c, "\"name\" property in %s is incorrect (\"%s\" instead"
+ FAIL(c, dti, "\"name\" property in %s is incorrect (\"%s\" instead"
" of base node name)", node->fullpath, prop->val.val);
} else {
/* The name property is correct, and therefore redundant.
@@ -472,60 +508,73 @@ static void check_name_properties(struct check *c, struct node *root,
}
}
ERROR_IF_NOT_STRING(name_is_string, "name");
-NODE_ERROR(name_properties, NULL, &name_is_string);
+ERROR(name_properties, check_name_properties, NULL, &name_is_string);
/*
* Reference fixup functions
*/
-static void fixup_phandle_references(struct check *c, struct node *dt,
- struct node *node, struct property *prop)
+static void fixup_phandle_references(struct check *c, struct dt_info *dti,
+ struct node *node)
{
- struct marker *m = prop->val.markers;
- struct node *refnode;
- cell_t phandle;
+ struct node *dt = dti->dt;
+ struct property *prop;
- for_each_marker_of_type(m, REF_PHANDLE) {
- assert(m->offset + sizeof(cell_t) <= prop->val.len);
+ for_each_property(node, prop) {
+ struct marker *m = prop->val.markers;
+ struct node *refnode;
+ cell_t phandle;
+
+ for_each_marker_of_type(m, REF_PHANDLE) {
+ assert(m->offset + sizeof(cell_t) <= prop->val.len);
+
+ refnode = get_node_by_ref(dt, m->ref);
+ if (! refnode) {
+ if (!(dti->dtsflags & DTSF_PLUGIN))
+ FAIL(c, dti, "Reference to non-existent node or "
+ "label \"%s\"\n", m->ref);
+ else /* mark the entry as unresolved */
+ *((fdt32_t *)(prop->val.val + m->offset)) =
+ cpu_to_fdt32(0xffffffff);
+ continue;
+ }
- refnode = get_node_by_ref(dt, m->ref);
- if (! refnode) {
- FAIL(c, "Reference to non-existent node or label \"%s\"\n",
- m->ref);
- continue;
+ phandle = get_node_phandle(dt, refnode);
+ *((fdt32_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle);
}
-
- phandle = get_node_phandle(dt, refnode);
- *((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle);
}
}
-ERROR(phandle_references, NULL, NULL, fixup_phandle_references, NULL,
+ERROR(phandle_references, fixup_phandle_references, NULL,
&duplicate_node_names, &explicit_phandles);
-static void fixup_path_references(struct check *c, struct node *dt,
- struct node *node, struct property *prop)
+static void fixup_path_references(struct check *c, struct dt_info *dti,
+ struct node *node)
{
- struct marker *m = prop->val.markers;
- struct node *refnode;
- char *path;
+ struct node *dt = dti->dt;
+ struct property *prop;
+
+ for_each_property(node, prop) {
+ struct marker *m = prop->val.markers;
+ struct node *refnode;
+ char *path;
- for_each_marker_of_type(m, REF_PATH) {
- assert(m->offset <= prop->val.len);
+ for_each_marker_of_type(m, REF_PATH) {
+ assert(m->offset <= prop->val.len);
- refnode = get_node_by_ref(dt, m->ref);
- if (!refnode) {
- FAIL(c, "Reference to non-existent node or label \"%s\"\n",
- m->ref);
- continue;
- }
+ refnode = get_node_by_ref(dt, m->ref);
+ if (!refnode) {
+ FAIL(c, dti, "Reference to non-existent node or label \"%s\"\n",
+ m->ref);
+ continue;
+ }
- path = refnode->fullpath;
- prop->val = data_insert_at_marker(prop->val, m, path,
- strlen(path) + 1);
+ path = refnode->fullpath;
+ prop->val = data_insert_at_marker(prop->val, m, path,
+ strlen(path) + 1);
+ }
}
}
-ERROR(path_references, NULL, NULL, fixup_path_references, NULL,
- &duplicate_node_names);
+ERROR(path_references, fixup_path_references, NULL, &duplicate_node_names);
/*
* Semantic checks
@@ -538,7 +587,7 @@ WARNING_IF_NOT_STRING(device_type_is_string, "device_type");
WARNING_IF_NOT_STRING(model_is_string, "model");
WARNING_IF_NOT_STRING(status_is_string, "status");
-static void fixup_addr_size_cells(struct check *c, struct node *dt,
+static void fixup_addr_size_cells(struct check *c, struct dt_info *dti,
struct node *node)
{
struct property *prop;
@@ -554,7 +603,7 @@ static void fixup_addr_size_cells(struct check *c, struct node *dt,
if (prop)
node->size_cells = propval_cell(prop);
}
-WARNING(addr_size_cells, NULL, fixup_addr_size_cells, NULL, NULL,
+WARNING(addr_size_cells, fixup_addr_size_cells, NULL,
&address_cells_is_cell, &size_cells_is_cell);
#define node_addr_cells(n) \
@@ -562,7 +611,7 @@ WARNING(addr_size_cells, NULL, fixup_addr_size_cells, NULL, NULL,
#define node_size_cells(n) \
(((n)->size_cells == -1) ? 1 : (n)->size_cells)
-static void check_reg_format(struct check *c, struct node *dt,
+static void check_reg_format(struct check *c, struct dt_info *dti,
struct node *node)
{
struct property *prop;
@@ -573,25 +622,25 @@ static void check_reg_format(struct check *c, struct node *dt,
return; /* No "reg", that's fine */
if (!node->parent) {
- FAIL(c, "Root node has a \"reg\" property");
+ FAIL(c, dti, "Root node has a \"reg\" property");
return;
}
if (prop->val.len == 0)
- FAIL(c, "\"reg\" property in %s is empty", node->fullpath);
+ FAIL(c, dti, "\"reg\" property in %s is empty", node->fullpath);
addr_cells = node_addr_cells(node->parent);
size_cells = node_size_cells(node->parent);
entrylen = (addr_cells + size_cells) * sizeof(cell_t);
if (!entrylen || (prop->val.len % entrylen) != 0)
- FAIL(c, "\"reg\" property in %s has invalid length (%d bytes) "
+ FAIL(c, dti, "\"reg\" property in %s has invalid length (%d bytes) "
"(#address-cells == %d, #size-cells == %d)",
node->fullpath, prop->val.len, addr_cells, size_cells);
}
-NODE_WARNING(reg_format, NULL, &addr_size_cells);
+WARNING(reg_format, check_reg_format, NULL, &addr_size_cells);
-static void check_ranges_format(struct check *c, struct node *dt,
+static void check_ranges_format(struct check *c, struct dt_info *dti,
struct node *node)
{
struct property *prop;
@@ -602,7 +651,7 @@ static void check_ranges_format(struct check *c, struct node *dt,
return;
if (!node->parent) {
- FAIL(c, "Root node has a \"ranges\" property");
+ FAIL(c, dti, "Root node has a \"ranges\" property");
return;
}
@@ -614,28 +663,28 @@ static void check_ranges_format(struct check *c, struct node *dt,
if (prop->val.len == 0) {
if (p_addr_cells != c_addr_cells)
- FAIL(c, "%s has empty \"ranges\" property but its "
+ FAIL(c, dti, "%s has empty \"ranges\" property but its "
"#address-cells (%d) differs from %s (%d)",
node->fullpath, c_addr_cells, node->parent->fullpath,
p_addr_cells);
if (p_size_cells != c_size_cells)
- FAIL(c, "%s has empty \"ranges\" property but its "
+ FAIL(c, dti, "%s has empty \"ranges\" property but its "
"#size-cells (%d) differs from %s (%d)",
node->fullpath, c_size_cells, node->parent->fullpath,
p_size_cells);
} else if ((prop->val.len % entrylen) != 0) {
- FAIL(c, "\"ranges\" property in %s has invalid length (%d bytes) "
+ FAIL(c, dti, "\"ranges\" property in %s has invalid length (%d bytes) "
"(parent #address-cells == %d, child #address-cells == %d, "
"#size-cells == %d)", node->fullpath, prop->val.len,
p_addr_cells, c_addr_cells, c_size_cells);
}
}
-NODE_WARNING(ranges_format, NULL, &addr_size_cells);
+WARNING(ranges_format, check_ranges_format, NULL, &addr_size_cells);
/*
* Style checks
*/
-static void check_avoid_default_addr_size(struct check *c, struct node *dt,
+static void check_avoid_default_addr_size(struct check *c, struct dt_info *dti,
struct node *node)
{
struct property *reg, *ranges;
@@ -650,31 +699,39 @@ static void check_avoid_default_addr_size(struct check *c, struct node *dt,
return;
if (node->parent->addr_cells == -1)
- FAIL(c, "Relying on default #address-cells value for %s",
+ FAIL(c, dti, "Relying on default #address-cells value for %s",
node->fullpath);
if (node->parent->size_cells == -1)
- FAIL(c, "Relying on default #size-cells value for %s",
+ FAIL(c, dti, "Relying on default #size-cells value for %s",
node->fullpath);
}
-NODE_WARNING(avoid_default_addr_size, NULL, &addr_size_cells);
+WARNING(avoid_default_addr_size, check_avoid_default_addr_size, NULL,
+ &addr_size_cells);
static void check_obsolete_chosen_interrupt_controller(struct check *c,
- struct node *dt)
+ struct dt_info *dti,
+ struct node *node)
{
+ struct node *dt = dti->dt;
struct node *chosen;
struct property *prop;
+ if (node != dt)
+ return;
+
+
chosen = get_node_by_path(dt, "/chosen");
if (!chosen)
return;
prop = get_property(chosen, "interrupt-controller");
if (prop)
- FAIL(c, "/chosen has obsolete \"interrupt-controller\" "
+ FAIL(c, dti, "/chosen has obsolete \"interrupt-controller\" "
"property");
}
-TREE_WARNING(obsolete_chosen_interrupt_controller, NULL);
+WARNING(obsolete_chosen_interrupt_controller,
+ check_obsolete_chosen_interrupt_controller, NULL);
static struct check *check_table[] = {
&duplicate_node_names, &duplicate_property_names,
@@ -689,6 +746,9 @@ static struct check *check_table[] = {
&address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell,
&device_type_is_string, &model_is_string, &status_is_string,
+ &property_name_chars_strict,
+ &node_name_chars_strict,
+
&addr_size_cells, ®_format, &ranges_format,
&unit_address_vs_reg,
@@ -760,9 +820,8 @@ void parse_checks_option(bool warn, bool error, const char *arg)
die("Unrecognized check name \"%s\"\n", name);
}
-void process_checks(bool force, struct boot_info *bi)
+void process_checks(bool force, struct dt_info *dti)
{
- struct node *dt = bi->dt;
int i;
int error = 0;
@@ -770,7 +829,7 @@ void process_checks(bool force, struct boot_info *bi)
struct check *c = check_table[i];
if (c->warn || c->error)
- error = error || run_check(c, dt);
+ error = error || run_check(c, dti);
}
if (error) {
diff --git a/scripts/dtc/data.c b/scripts/dtc/data.c
index 8cae237..aa37a16 100644
--- a/scripts/dtc/data.c
+++ b/scripts/dtc/data.c
@@ -171,9 +171,9 @@ struct data data_merge(struct data d1, struct data d2)
struct data data_append_integer(struct data d, uint64_t value, int bits)
{
uint8_t value_8;
- uint16_t value_16;
- uint32_t value_32;
- uint64_t value_64;
+ fdt16_t value_16;
+ fdt32_t value_32;
+ fdt64_t value_64;
switch (bits) {
case 8:
@@ -197,14 +197,14 @@ struct data data_append_integer(struct data d, uint64_t value, int bits)
}
}
-struct data data_append_re(struct data d, const struct fdt_reserve_entry *re)
+struct data data_append_re(struct data d, uint64_t address, uint64_t size)
{
- struct fdt_reserve_entry bere;
+ struct fdt_reserve_entry re;
- bere.address = cpu_to_fdt64(re->address);
- bere.size = cpu_to_fdt64(re->size);
+ re.address = cpu_to_fdt64(address);
+ re.size = cpu_to_fdt64(size);
- return data_append_data(d, &bere, sizeof(bere));
+ return data_append_data(d, &re, sizeof(re));
}
struct data data_append_cell(struct data d, cell_t word)
diff --git a/scripts/dtc/dtc-lexer.l b/scripts/dtc/dtc-lexer.l
index 790fbf6..fd825eb 100644
--- a/scripts/dtc/dtc-lexer.l
+++ b/scripts/dtc/dtc-lexer.l
@@ -62,7 +62,8 @@ static int dts_version = 1;
static void push_input_file(const char *filename);
static bool pop_input_file(void);
-static void lexical_error(const char *fmt, ...);
+static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
+
%}
%%
@@ -121,6 +122,11 @@ static void lexical_error(const char *fmt, ...);
return DT_V1;
}
+<*>"/plugin/" {
+ DPRINT("Keyword: /plugin/\n");
+ return DT_PLUGIN;
+ }
+
<*>"/memreserve/" {
DPRINT("Keyword: /memreserve/\n");
BEGIN_DEFAULT();
@@ -184,16 +190,16 @@ static void lexical_error(const char *fmt, ...);
if (d.len == 1) {
lexical_error("Empty character literal");
yylval.integer = 0;
- return DT_CHAR_LITERAL;
- }
-
- yylval.integer = (unsigned char)d.val[0];
+ } else {
+ yylval.integer = (unsigned char)d.val[0];
- if (d.len > 2)
- lexical_error("Character literal has %d"
- " characters instead of 1",
- d.len - 1);
+ if (d.len > 2)
+ lexical_error("Character literal has %d"
+ " characters instead of 1",
+ d.len - 1);
+ }
+ data_free(d);
return DT_CHAR_LITERAL;
}
diff --git a/scripts/dtc/dtc-lexer.lex.c_shipped b/scripts/dtc/dtc-lexer.lex.c_shipped
index ba525c2..c37d7ff 100644
--- a/scripts/dtc/dtc-lexer.lex.c_shipped
+++ b/scripts/dtc/dtc-lexer.lex.c_shipped
@@ -8,8 +8,8 @@
#define FLEX_SCANNER
#define YY_FLEX_MAJOR_VERSION 2
-#define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 39
+#define YY_FLEX_MINOR_VERSION 6
+#define YY_FLEX_SUBMINOR_VERSION 1
#if YY_FLEX_SUBMINOR_VERSION > 0
#define FLEX_BETA
#endif
@@ -88,25 +88,13 @@ typedef unsigned int flex_uint32_t;
#endif /* ! FLEXINT_H */
-#ifdef __cplusplus
-
-/* The "const" storage-class-modifier is valid. */
-#define YY_USE_CONST
-
-#else /* ! __cplusplus */
-
-/* C99 requires __STDC__ to be defined as 1. */
-#if defined (__STDC__)
-
-#define YY_USE_CONST
-
-#endif /* defined (__STDC__) */
-#endif /* ! __cplusplus */
-
-#ifdef YY_USE_CONST
+/* TODO: this is always defined, so inline it */
#define yyconst const
+
+#if defined(__GNUC__) && __GNUC__ >= 3
+#define yynoreturn __attribute__((__noreturn__))
#else
-#define yyconst
+#define yynoreturn
#endif
/* Returned upon end-of-file. */
@@ -167,7 +155,7 @@ typedef struct yy_buffer_state *YY_BUFFER_STATE;
typedef size_t yy_size_t;
#endif
-extern yy_size_t yyleng;
+extern int yyleng;
extern FILE *yyin, *yyout;
@@ -206,12 +194,12 @@ struct yy_buffer_state
/* Size of input buffer in bytes, not including room for EOB
* characters.
*/
- yy_size_t yy_buf_size;
+ int yy_buf_size;
/* Number of characters read into yy_ch_buf, not including EOB
* characters.
*/
- yy_size_t yy_n_chars;
+ int yy_n_chars;
/* Whether we "own" the buffer - i.e., we know we created it,
* and can realloc() it to grow it, and should free() it to
@@ -234,7 +222,7 @@ struct yy_buffer_state
int yy_bs_lineno; /**< The line count. */
int yy_bs_column; /**< The column count. */
-
+
/* Whether to try to fill the input buffer when we reach the
* end of it.
*/
@@ -262,7 +250,7 @@ struct yy_buffer_state
/* Stack of input buffers. */
static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
-static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
+static YY_BUFFER_STATE * yy_buffer_stack = NULL; /**< Stack as an array. */
/* We provide macros for accessing buffer states in case in the
* future we want to put the buffer states in a more general
@@ -281,11 +269,11 @@ static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
/* yy_hold_char holds the character lost when yytext is formed. */
static char yy_hold_char;
-static yy_size_t yy_n_chars; /* number of characters read into yy_ch_buf */
-yy_size_t yyleng;
+static int yy_n_chars; /* number of characters read into yy_ch_buf */
+int yyleng;
/* Points to current character in buffer. */
-static char *yy_c_buf_p = (char *) 0;
+static char *yy_c_buf_p = NULL;
static int yy_init = 0; /* whether we need to initialize */
static int yy_start = 0; /* start state number */
@@ -310,7 +298,7 @@ static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file );
YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size );
YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str );
-YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,yy_size_t len );
+YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len );
void *yyalloc (yy_size_t );
void *yyrealloc (void *,yy_size_t );
@@ -342,12 +330,12 @@ void yyfree (void * );
/* Begin user sect3 */
-#define yywrap() 1
+#define yywrap() (/*CONSTCOND*/1)
#define YY_SKIP_YYWRAP
typedef unsigned char YY_CHAR;
-FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+FILE *yyin = NULL, *yyout = NULL;
typedef int yy_state_type;
@@ -356,25 +344,28 @@ extern int yylineno;
int yylineno = 1;
extern char *yytext;
+#ifdef yytext_ptr
+#undef yytext_ptr
+#endif
#define yytext_ptr yytext
static yy_state_type yy_get_previous_state (void );
static yy_state_type yy_try_NUL_trans (yy_state_type current_state );
static int yy_get_next_buffer (void );
-static void yy_fatal_error (yyconst char msg[] );
+static void yynoreturn yy_fatal_error (yyconst char* msg );
/* Done after the current pattern has been matched and before the
* corresponding action - sets up yytext.
*/
#define YY_DO_BEFORE_ACTION \
(yytext_ptr) = yy_bp; \
- yyleng = (size_t) (yy_cp - yy_bp); \
+ yyleng = (int) (yy_cp - yy_bp); \
(yy_hold_char) = *yy_cp; \
*yy_cp = '\0'; \
(yy_c_buf_p) = yy_cp;
-#define YY_NUM_RULES 30
-#define YY_END_OF_BUFFER 31
+#define YY_NUM_RULES 31
+#define YY_END_OF_BUFFER 32
/* This struct is not used in this scanner,
but its presence is necessary. */
struct yy_trans_info
@@ -382,28 +373,29 @@ struct yy_trans_info
flex_int32_t yy_verify;
flex_int32_t yy_nxt;
};
-static yyconst flex_int16_t yy_accept[159] =
+static yyconst flex_int16_t yy_accept[166] =
{ 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 31, 29,
- 18, 18, 29, 29, 29, 29, 29, 29, 29, 29,
- 29, 29, 29, 29, 29, 29, 15, 16, 16, 29,
- 16, 10, 10, 18, 26, 0, 3, 0, 27, 12,
- 0, 0, 11, 0, 0, 0, 0, 0, 0, 0,
- 21, 23, 25, 24, 22, 0, 9, 28, 0, 0,
- 0, 14, 14, 16, 16, 16, 10, 10, 10, 0,
- 12, 0, 11, 0, 0, 0, 20, 0, 0, 0,
- 0, 0, 0, 0, 0, 16, 10, 10, 10, 0,
- 13, 19, 0, 0, 0, 0, 0, 0, 0, 0,
-
- 0, 16, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 16, 6, 0, 0, 0, 0, 0, 0, 2,
- 0, 0, 0, 0, 0, 0, 0, 0, 4, 17,
- 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
- 5, 8, 0, 0, 0, 0, 7, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 32, 30,
+ 19, 19, 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 16, 17, 17, 30,
+ 17, 11, 11, 19, 27, 0, 3, 0, 28, 13,
+ 0, 0, 12, 0, 0, 0, 0, 0, 0, 0,
+ 0, 22, 24, 26, 25, 23, 0, 10, 29, 0,
+ 0, 0, 15, 15, 17, 17, 17, 11, 11, 11,
+ 0, 13, 0, 12, 0, 0, 0, 21, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 17, 11, 11,
+ 11, 0, 14, 20, 0, 0, 0, 0, 0, 0,
+
+ 0, 0, 0, 0, 17, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 17, 7, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 4, 18, 0, 0, 5, 2,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 6, 9, 0,
+ 0, 0, 0, 8, 0
} ;
-static yyconst flex_int32_t yy_ec[256] =
+static yyconst YY_CHAR yy_ec[256] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
4, 4, 4, 1, 1, 1, 1, 1, 1, 1,
@@ -416,9 +408,9 @@ static yyconst flex_int32_t yy_ec[256] =
22, 22, 22, 22, 24, 22, 22, 25, 22, 22,
1, 26, 27, 1, 22, 1, 21, 28, 29, 30,
- 31, 21, 22, 22, 32, 22, 22, 33, 34, 35,
- 36, 37, 22, 38, 39, 40, 41, 42, 22, 25,
- 43, 22, 44, 45, 46, 1, 1, 1, 1, 1,
+ 31, 21, 32, 22, 33, 22, 22, 34, 35, 36,
+ 37, 38, 22, 39, 40, 41, 42, 43, 22, 25,
+ 44, 22, 45, 46, 47, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -435,163 +427,165 @@ static yyconst flex_int32_t yy_ec[256] =
1, 1, 1, 1, 1
} ;
-static yyconst flex_int32_t yy_meta[47] =
+static yyconst YY_CHAR yy_meta[48] =
{ 0,
1, 1, 1, 1, 1, 1, 2, 3, 1, 2,
2, 2, 4, 5, 5, 5, 6, 1, 1, 1,
7, 8, 8, 8, 8, 1, 1, 7, 7, 7,
7, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 3, 1, 4
+ 8, 8, 8, 8, 3, 1, 4
} ;
-static yyconst flex_int16_t yy_base[173] =
+static yyconst flex_uint16_t yy_base[180] =
{ 0,
- 0, 383, 34, 382, 65, 381, 37, 105, 387, 391,
- 54, 111, 367, 110, 109, 109, 112, 41, 366, 104,
- 367, 338, 124, 117, 0, 144, 391, 0, 121, 0,
- 135, 155, 140, 179, 391, 160, 391, 379, 391, 0,
- 368, 141, 391, 167, 370, 376, 346, 103, 342, 345,
- 391, 391, 391, 391, 391, 358, 391, 391, 175, 342,
- 338, 391, 355, 0, 185, 339, 184, 347, 346, 0,
- 0, 322, 175, 357, 175, 363, 352, 324, 330, 323,
- 332, 326, 201, 324, 329, 322, 391, 333, 181, 309,
- 391, 341, 340, 313, 320, 338, 178, 311, 146, 317,
-
- 314, 315, 335, 331, 303, 300, 309, 299, 308, 188,
- 336, 335, 391, 305, 320, 281, 283, 271, 203, 288,
- 281, 271, 266, 264, 245, 242, 208, 104, 391, 391,
- 244, 218, 204, 219, 206, 224, 201, 212, 204, 229,
- 215, 208, 207, 200, 219, 391, 233, 221, 200, 181,
- 391, 391, 149, 122, 86, 41, 391, 391, 245, 251,
- 259, 263, 267, 273, 280, 284, 292, 300, 304, 310,
- 318, 326
+ 0, 393, 35, 392, 66, 391, 38, 107, 397, 401,
+ 55, 113, 377, 112, 111, 111, 114, 42, 376, 106,
+ 377, 347, 126, 120, 0, 147, 401, 0, 124, 0,
+ 137, 158, 170, 163, 401, 153, 401, 389, 401, 0,
+ 378, 120, 401, 131, 380, 386, 355, 139, 351, 355,
+ 351, 401, 401, 401, 401, 401, 367, 401, 401, 185,
+ 350, 346, 401, 364, 0, 185, 347, 189, 356, 355,
+ 0, 0, 330, 180, 366, 141, 372, 361, 332, 338,
+ 331, 341, 334, 326, 205, 331, 337, 329, 401, 341,
+ 167, 316, 401, 349, 348, 320, 328, 346, 180, 318,
+
+ 324, 209, 324, 320, 322, 342, 338, 309, 306, 315,
+ 305, 315, 312, 192, 342, 341, 401, 293, 306, 282,
+ 268, 252, 255, 203, 285, 282, 272, 268, 252, 233,
+ 232, 239, 208, 107, 401, 401, 238, 211, 401, 211,
+ 212, 208, 228, 203, 215, 207, 233, 222, 212, 211,
+ 203, 227, 401, 237, 225, 204, 185, 401, 401, 149,
+ 128, 88, 42, 401, 401, 253, 259, 267, 271, 275,
+ 281, 288, 292, 300, 308, 312, 318, 326, 334
} ;
-static yyconst flex_int16_t yy_def[173] =
+static yyconst flex_int16_t yy_def[180] =
{ 0,
- 158, 1, 1, 3, 158, 5, 1, 1, 158, 158,
- 158, 158, 158, 159, 160, 161, 158, 158, 158, 158,
- 162, 158, 158, 158, 163, 162, 158, 164, 165, 164,
- 164, 158, 158, 158, 158, 159, 158, 159, 158, 166,
- 158, 161, 158, 161, 167, 168, 158, 158, 158, 158,
- 158, 158, 158, 158, 158, 162, 158, 158, 158, 158,
- 158, 158, 162, 164, 165, 164, 158, 158, 158, 169,
- 166, 170, 161, 167, 167, 168, 158, 158, 158, 158,
- 158, 158, 158, 158, 158, 164, 158, 158, 169, 170,
- 158, 158, 158, 158, 158, 158, 158, 158, 158, 158,
-
- 158, 164, 158, 158, 158, 158, 158, 158, 158, 171,
- 158, 164, 158, 158, 158, 158, 158, 158, 171, 158,
- 171, 158, 158, 158, 158, 158, 158, 158, 158, 158,
- 158, 158, 158, 158, 158, 158, 158, 158, 158, 158,
- 172, 158, 158, 158, 172, 158, 172, 158, 158, 158,
- 158, 158, 158, 158, 158, 158, 158, 0, 158, 158,
- 158, 158, 158, 158, 158, 158, 158, 158, 158, 158,
- 158, 158
+ 165, 1, 1, 3, 165, 5, 1, 1, 165, 165,
+ 165, 165, 165, 166, 167, 168, 165, 165, 165, 165,
+ 169, 165, 165, 165, 170, 169, 165, 171, 172, 171,
+ 171, 165, 165, 165, 165, 166, 165, 166, 165, 173,
+ 165, 168, 165, 168, 174, 175, 165, 165, 165, 165,
+ 165, 165, 165, 165, 165, 165, 169, 165, 165, 165,
+ 165, 165, 165, 169, 171, 172, 171, 165, 165, 165,
+ 176, 173, 177, 168, 174, 174, 175, 165, 165, 165,
+ 165, 165, 165, 165, 165, 165, 165, 171, 165, 165,
+ 176, 177, 165, 165, 165, 165, 165, 165, 165, 165,
+
+ 165, 165, 165, 165, 171, 165, 165, 165, 165, 165,
+ 165, 165, 165, 178, 165, 171, 165, 165, 165, 165,
+ 165, 165, 165, 178, 165, 178, 165, 165, 165, 165,
+ 165, 165, 165, 165, 165, 165, 165, 165, 165, 165,
+ 165, 165, 165, 165, 165, 165, 165, 179, 165, 165,
+ 165, 179, 165, 179, 165, 165, 165, 165, 165, 165,
+ 165, 165, 165, 165, 0, 165, 165, 165, 165, 165,
+ 165, 165, 165, 165, 165, 165, 165, 165, 165
} ;
-static yyconst flex_int16_t yy_nxt[438] =
+static yyconst flex_uint16_t yy_nxt[449] =
{ 0,
10, 11, 12, 11, 13, 14, 10, 15, 16, 10,
10, 10, 17, 10, 10, 10, 10, 18, 19, 20,
21, 21, 21, 21, 21, 10, 10, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 10, 22, 10, 24, 25, 25, 25,
- 32, 33, 33, 157, 26, 34, 34, 34, 51, 52,
- 27, 26, 26, 26, 26, 10, 11, 12, 11, 13,
- 14, 28, 15, 16, 28, 28, 28, 24, 28, 28,
- 28, 10, 18, 19, 20, 29, 29, 29, 29, 29,
- 30, 10, 29, 29, 29, 29, 29, 29, 29, 29,
-
- 29, 29, 29, 29, 29, 29, 29, 29, 10, 22,
- 10, 23, 34, 34, 34, 37, 39, 43, 32, 33,
- 33, 45, 54, 55, 46, 59, 45, 64, 156, 46,
- 64, 64, 64, 79, 44, 38, 59, 57, 134, 47,
- 135, 48, 80, 49, 47, 50, 48, 99, 61, 43,
- 50, 110, 41, 67, 67, 67, 60, 63, 63, 63,
- 57, 155, 68, 69, 63, 37, 44, 66, 67, 67,
- 67, 63, 63, 63, 63, 73, 59, 68, 69, 70,
- 34, 34, 34, 43, 75, 38, 154, 92, 83, 83,
- 83, 64, 44, 120, 64, 64, 64, 67, 67, 67,
-
- 44, 57, 99, 68, 69, 107, 68, 69, 120, 127,
- 108, 153, 152, 121, 83, 83, 83, 133, 133, 133,
- 146, 133, 133, 133, 146, 140, 140, 140, 121, 141,
- 140, 140, 140, 151, 141, 158, 150, 149, 148, 144,
- 147, 143, 142, 139, 147, 36, 36, 36, 36, 36,
- 36, 36, 36, 40, 138, 137, 136, 40, 40, 42,
- 42, 42, 42, 42, 42, 42, 42, 56, 56, 56,
- 56, 62, 132, 62, 64, 131, 130, 64, 129, 64,
- 64, 65, 128, 158, 65, 65, 65, 65, 71, 127,
- 71, 71, 74, 74, 74, 74, 74, 74, 74, 74,
-
- 76, 76, 76, 76, 76, 76, 76, 76, 89, 126,
- 89, 90, 125, 90, 90, 124, 90, 90, 119, 119,
- 119, 119, 119, 119, 119, 119, 145, 145, 145, 145,
- 145, 145, 145, 145, 123, 122, 59, 59, 118, 117,
- 116, 115, 114, 113, 45, 112, 108, 111, 109, 106,
- 105, 104, 46, 103, 91, 87, 102, 101, 100, 98,
- 97, 96, 95, 94, 93, 77, 75, 91, 88, 87,
- 86, 57, 85, 84, 57, 82, 81, 78, 77, 75,
- 72, 158, 58, 57, 53, 35, 158, 31, 23, 23,
- 9, 158, 158, 158, 158, 158, 158, 158, 158, 158,
-
- 158, 158, 158, 158, 158, 158, 158, 158, 158, 158,
- 158, 158, 158, 158, 158, 158, 158, 158, 158, 158,
- 158, 158, 158, 158, 158, 158, 158, 158, 158, 158,
- 158, 158, 158, 158, 158, 158, 158
+ 21, 21, 21, 21, 10, 22, 10, 24, 25, 25,
+ 25, 32, 33, 33, 164, 26, 34, 34, 34, 52,
+ 53, 27, 26, 26, 26, 26, 10, 11, 12, 11,
+ 13, 14, 28, 15, 16, 28, 28, 28, 24, 28,
+ 28, 28, 10, 18, 19, 20, 29, 29, 29, 29,
+ 29, 30, 10, 29, 29, 29, 29, 29, 29, 29,
+
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 10, 22, 10, 23, 34, 34, 34, 37, 39, 43,
+ 32, 33, 33, 45, 55, 56, 46, 60, 43, 45,
+ 65, 163, 46, 65, 65, 65, 44, 38, 60, 74,
+ 58, 47, 141, 48, 142, 44, 49, 47, 50, 48,
+ 76, 51, 62, 94, 50, 41, 44, 51, 37, 61,
+ 64, 64, 64, 58, 34, 34, 34, 64, 162, 80,
+ 67, 68, 68, 68, 64, 64, 64, 64, 38, 81,
+ 69, 70, 71, 68, 68, 68, 60, 161, 43, 69,
+ 70, 65, 69, 70, 65, 65, 65, 125, 85, 85,
+
+ 85, 58, 68, 68, 68, 44, 102, 110, 125, 133,
+ 102, 69, 70, 111, 114, 160, 159, 126, 85, 85,
+ 85, 140, 140, 140, 140, 140, 140, 153, 126, 147,
+ 147, 147, 153, 148, 147, 147, 147, 158, 148, 165,
+ 157, 156, 155, 151, 150, 149, 146, 154, 145, 144,
+ 143, 139, 154, 36, 36, 36, 36, 36, 36, 36,
+ 36, 40, 138, 137, 136, 40, 40, 42, 42, 42,
+ 42, 42, 42, 42, 42, 57, 57, 57, 57, 63,
+ 135, 63, 65, 134, 165, 65, 133, 65, 65, 66,
+ 132, 131, 66, 66, 66, 66, 72, 130, 72, 72,
+
+ 75, 75, 75, 75, 75, 75, 75, 75, 77, 77,
+ 77, 77, 77, 77, 77, 77, 91, 129, 91, 92,
+ 128, 92, 92, 127, 92, 92, 124, 124, 124, 124,
+ 124, 124, 124, 124, 152, 152, 152, 152, 152, 152,
+ 152, 152, 60, 60, 123, 122, 121, 120, 119, 118,
+ 117, 45, 116, 111, 115, 113, 112, 109, 108, 107,
+ 46, 106, 93, 89, 105, 104, 103, 101, 100, 99,
+ 98, 97, 96, 95, 78, 76, 93, 90, 89, 88,
+ 58, 87, 86, 58, 84, 83, 82, 79, 78, 76,
+ 73, 165, 59, 58, 54, 35, 165, 31, 23, 23,
+
+ 9, 165, 165, 165, 165, 165, 165, 165, 165, 165,
+ 165, 165, 165, 165, 165, 165, 165, 165, 165, 165,
+ 165, 165, 165, 165, 165, 165, 165, 165, 165, 165,
+ 165, 165, 165, 165, 165, 165, 165, 165, 165, 165,
+ 165, 165, 165, 165, 165, 165, 165, 165
} ;
-static yyconst flex_int16_t yy_chk[438] =
+static yyconst flex_int16_t yy_chk[449] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 3, 3, 3, 3,
- 7, 7, 7, 156, 3, 11, 11, 11, 18, 18,
- 3, 3, 3, 3, 3, 5, 5, 5, 5, 5,
+ 1, 1, 1, 1, 1, 1, 1, 3, 3, 3,
+ 3, 7, 7, 7, 163, 3, 11, 11, 11, 18,
+ 18, 3, 3, 3, 3, 3, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 8, 12, 12, 12, 14, 15, 16, 8, 8,
- 8, 17, 20, 20, 17, 23, 24, 29, 155, 24,
- 29, 29, 29, 48, 16, 14, 31, 29, 128, 17,
- 128, 17, 48, 17, 24, 17, 24, 99, 24, 42,
- 24, 99, 15, 33, 33, 33, 23, 26, 26, 26,
- 26, 154, 33, 33, 26, 36, 42, 31, 32, 32,
- 32, 26, 26, 26, 26, 44, 59, 32, 32, 32,
- 34, 34, 34, 73, 75, 36, 153, 75, 59, 59,
- 59, 65, 44, 110, 65, 65, 65, 67, 67, 67,
-
- 73, 65, 83, 89, 89, 97, 67, 67, 119, 127,
- 97, 150, 149, 110, 83, 83, 83, 133, 133, 133,
- 141, 127, 127, 127, 145, 136, 136, 136, 119, 136,
- 140, 140, 140, 148, 140, 147, 144, 143, 142, 139,
- 141, 138, 137, 135, 145, 159, 159, 159, 159, 159,
- 159, 159, 159, 160, 134, 132, 131, 160, 160, 161,
- 161, 161, 161, 161, 161, 161, 161, 162, 162, 162,
- 162, 163, 126, 163, 164, 125, 124, 164, 123, 164,
- 164, 165, 122, 121, 165, 165, 165, 165, 166, 120,
- 166, 166, 167, 167, 167, 167, 167, 167, 167, 167,
-
- 168, 168, 168, 168, 168, 168, 168, 168, 169, 118,
- 169, 170, 117, 170, 170, 116, 170, 170, 171, 171,
- 171, 171, 171, 171, 171, 171, 172, 172, 172, 172,
- 172, 172, 172, 172, 115, 114, 112, 111, 109, 108,
- 107, 106, 105, 104, 103, 102, 101, 100, 98, 96,
- 95, 94, 93, 92, 90, 88, 86, 85, 84, 82,
- 81, 80, 79, 78, 77, 76, 74, 72, 69, 68,
- 66, 63, 61, 60, 56, 50, 49, 47, 46, 45,
+ 5, 5, 5, 8, 12, 12, 12, 14, 15, 16,
+ 8, 8, 8, 17, 20, 20, 17, 23, 42, 24,
+ 29, 162, 24, 29, 29, 29, 16, 14, 31, 44,
+ 29, 17, 134, 17, 134, 42, 17, 24, 17, 24,
+ 76, 17, 24, 76, 24, 15, 44, 24, 36, 23,
+ 26, 26, 26, 26, 34, 34, 34, 26, 161, 48,
+ 31, 32, 32, 32, 26, 26, 26, 26, 36, 48,
+ 32, 32, 32, 33, 33, 33, 60, 160, 74, 91,
+ 91, 66, 33, 33, 66, 66, 66, 114, 60, 60,
+
+ 60, 66, 68, 68, 68, 74, 85, 99, 124, 133,
+ 102, 68, 68, 99, 102, 157, 156, 114, 85, 85,
+ 85, 133, 133, 133, 140, 140, 140, 148, 124, 143,
+ 143, 143, 152, 143, 147, 147, 147, 155, 147, 154,
+ 151, 150, 149, 146, 145, 144, 142, 148, 141, 138,
+ 137, 132, 152, 166, 166, 166, 166, 166, 166, 166,
+ 166, 167, 131, 130, 129, 167, 167, 168, 168, 168,
+ 168, 168, 168, 168, 168, 169, 169, 169, 169, 170,
+ 128, 170, 171, 127, 126, 171, 125, 171, 171, 172,
+ 123, 122, 172, 172, 172, 172, 173, 121, 173, 173,
+
+ 174, 174, 174, 174, 174, 174, 174, 174, 175, 175,
+ 175, 175, 175, 175, 175, 175, 176, 120, 176, 177,
+ 119, 177, 177, 118, 177, 177, 178, 178, 178, 178,
+ 178, 178, 178, 178, 179, 179, 179, 179, 179, 179,
+ 179, 179, 116, 115, 113, 112, 111, 110, 109, 108,
+ 107, 106, 105, 104, 103, 101, 100, 98, 97, 96,
+ 95, 94, 92, 90, 88, 87, 86, 84, 83, 82,
+ 81, 80, 79, 78, 77, 75, 73, 70, 69, 67,
+ 64, 62, 61, 57, 51, 50, 49, 47, 46, 45,
41, 38, 22, 21, 19, 13, 9, 6, 4, 2,
- 158, 158, 158, 158, 158, 158, 158, 158, 158, 158,
- 158, 158, 158, 158, 158, 158, 158, 158, 158, 158,
- 158, 158, 158, 158, 158, 158, 158, 158, 158, 158,
- 158, 158, 158, 158, 158, 158, 158, 158, 158, 158,
- 158, 158, 158, 158, 158, 158, 158
+ 165, 165, 165, 165, 165, 165, 165, 165, 165, 165,
+ 165, 165, 165, 165, 165, 165, 165, 165, 165, 165,
+ 165, 165, 165, 165, 165, 165, 165, 165, 165, 165,
+ 165, 165, 165, 165, 165, 165, 165, 165, 165, 165,
+ 165, 165, 165, 165, 165, 165, 165, 165
} ;
static yy_state_type yy_last_accepting_state;
@@ -661,8 +655,9 @@ static int dts_version = 1;
static void push_input_file(const char *filename);
static bool pop_input_file(void);
-static void lexical_error(const char *fmt, ...);
-#line 666 "dtc-lexer.lex.c"
+static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
+
+#line 661 "dtc-lexer.lex.c"
#define INITIAL 0
#define BYTESTRING 1
@@ -698,19 +693,19 @@ void yyset_extra (YY_EXTRA_TYPE user_defined );
FILE *yyget_in (void );
-void yyset_in (FILE * in_str );
+void yyset_in (FILE * _in_str );
FILE *yyget_out (void );
-void yyset_out (FILE * out_str );
+void yyset_out (FILE * _out_str );
-yy_size_t yyget_leng (void );
+ int yyget_leng (void );
char *yyget_text (void );
int yyget_lineno (void );
-void yyset_lineno (int line_number );
+void yyset_lineno (int _line_number );
/* Macros after this point can all be overridden by user definitions in
* section 1.
@@ -724,6 +719,10 @@ extern int yywrap (void );
#endif
#endif
+#ifndef YY_NO_UNPUT
+
+#endif
+
#ifndef yytext_ptr
static void yy_flex_strncpy (char *,yyconst char *,int );
#endif
@@ -757,7 +756,7 @@ static int input (void );
/* This used to be an fputs(), but since the string might contain NUL's,
* we now use fwrite().
*/
-#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
+#define ECHO do { if (fwrite( yytext, (size_t) yyleng, 1, yyout )) {} } while (0)
#endif
/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
@@ -781,7 +780,7 @@ static int input (void );
else \
{ \
errno=0; \
- while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+ while ( (result = (int) fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
{ \
if( errno != EINTR) \
{ \
@@ -836,7 +835,7 @@ extern int yylex (void);
/* Code executed at the end of each rule. */
#ifndef YY_BREAK
-#define YY_BREAK break;
+#define YY_BREAK /*LINTED*/break;
#endif
#define YY_RULE_SETUP \
@@ -849,9 +848,9 @@ extern int yylex (void);
*/
YY_DECL
{
- register yy_state_type yy_current_state;
- register char *yy_cp, *yy_bp;
- register int yy_act;
+ yy_state_type yy_current_state;
+ char *yy_cp, *yy_bp;
+ int yy_act;
if ( !(yy_init) )
{
@@ -880,11 +879,11 @@ YY_DECL
}
{
-#line 68 "dtc-lexer.l"
+#line 69 "dtc-lexer.l"
-#line 886 "dtc-lexer.lex.c"
+#line 885 "dtc-lexer.lex.c"
- while ( 1 ) /* loops until end-of-file is reached */
+ while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */
{
yy_cp = (yy_c_buf_p);
@@ -901,7 +900,7 @@ YY_DECL
yy_match:
do
{
- register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ;
+ YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ;
if ( yy_accept[yy_current_state] )
{
(yy_last_accepting_state) = yy_current_state;
@@ -910,13 +909,13 @@ yy_match:
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 159 )
+ if ( yy_current_state >= 166 )
yy_c = yy_meta[(unsigned int) yy_c];
}
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
++yy_cp;
}
- while ( yy_current_state != 158 );
+ while ( yy_current_state != 165 );
yy_cp = (yy_last_accepting_cpos);
yy_current_state = (yy_last_accepting_state);
@@ -939,7 +938,7 @@ do_action: /* This label is used only to access EOF actions. */
case 1:
/* rule 1 can match eol */
YY_RULE_SETUP
-#line 69 "dtc-lexer.l"
+#line 70 "dtc-lexer.l"
{
char *name = strchr(yytext, '\"') + 1;
yytext[yyleng-1] = '\0';
@@ -949,7 +948,7 @@ YY_RULE_SETUP
case 2:
/* rule 2 can match eol */
YY_RULE_SETUP
-#line 75 "dtc-lexer.l"
+#line 76 "dtc-lexer.l"
{
char *line, *fnstart, *fnend;
struct data fn;
@@ -983,7 +982,7 @@ case YY_STATE_EOF(INITIAL):
case YY_STATE_EOF(BYTESTRING):
case YY_STATE_EOF(PROPNODENAME):
case YY_STATE_EOF(V1):
-#line 104 "dtc-lexer.l"
+#line 105 "dtc-lexer.l"
{
if (!pop_input_file()) {
yyterminate();
@@ -993,7 +992,7 @@ case YY_STATE_EOF(V1):
case 3:
/* rule 3 can match eol */
YY_RULE_SETUP
-#line 110 "dtc-lexer.l"
+#line 111 "dtc-lexer.l"
{
DPRINT("String: %s\n", yytext);
yylval.data = data_copy_escape_string(yytext+1,
@@ -1003,7 +1002,7 @@ YY_RULE_SETUP
YY_BREAK
case 4:
YY_RULE_SETUP
-#line 117 "dtc-lexer.l"
+#line 118 "dtc-lexer.l"
{
DPRINT("Keyword: /dts-v1/\n");
dts_version = 1;
@@ -1013,25 +1012,33 @@ YY_RULE_SETUP
YY_BREAK
case 5:
YY_RULE_SETUP
-#line 124 "dtc-lexer.l"
+#line 125 "dtc-lexer.l"
+{
+ DPRINT("Keyword: /plugin/\n");
+ return DT_PLUGIN;
+ }
+ YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 130 "dtc-lexer.l"
{
DPRINT("Keyword: /memreserve/\n");
BEGIN_DEFAULT();
return DT_MEMRESERVE;
}
YY_BREAK
-case 6:
+case 7:
YY_RULE_SETUP
-#line 130 "dtc-lexer.l"
+#line 136 "dtc-lexer.l"
{
DPRINT("Keyword: /bits/\n");
BEGIN_DEFAULT();
return DT_BITS;
}
YY_BREAK
-case 7:
+case 8:
YY_RULE_SETUP
-#line 136 "dtc-lexer.l"
+#line 142 "dtc-lexer.l"
{
DPRINT("Keyword: /delete-property/\n");
DPRINT("<PROPNODENAME>\n");
@@ -1039,9 +1046,9 @@ YY_RULE_SETUP
return DT_DEL_PROP;
}
YY_BREAK
-case 8:
+case 9:
YY_RULE_SETUP
-#line 143 "dtc-lexer.l"
+#line 149 "dtc-lexer.l"
{
DPRINT("Keyword: /delete-node/\n");
DPRINT("<PROPNODENAME>\n");
@@ -1049,9 +1056,9 @@ YY_RULE_SETUP
return DT_DEL_NODE;
}
YY_BREAK
-case 9:
+case 10:
YY_RULE_SETUP
-#line 150 "dtc-lexer.l"
+#line 156 "dtc-lexer.l"
{
DPRINT("Label: %s\n", yytext);
yylval.labelref = xstrdup(yytext);
@@ -1059,9 +1066,9 @@ YY_RULE_SETUP
return DT_LABEL;
}
YY_BREAK
-case 10:
+case 11:
YY_RULE_SETUP
-#line 157 "dtc-lexer.l"
+#line 163 "dtc-lexer.l"
{
char *e;
DPRINT("Integer Literal: '%s'\n", yytext);
@@ -1084,10 +1091,10 @@ YY_RULE_SETUP
return DT_LITERAL;
}
YY_BREAK
-case 11:
-/* rule 11 can match eol */
+case 12:
+/* rule 12 can match eol */
YY_RULE_SETUP
-#line 179 "dtc-lexer.l"
+#line 185 "dtc-lexer.l"
{
struct data d;
DPRINT("Character literal: %s\n", yytext);
@@ -1096,31 +1103,31 @@ YY_RULE_SETUP
if (d.len == 1) {
lexical_error("Empty character literal");
yylval.integer = 0;
- return DT_CHAR_LITERAL;
- }
+ } else {
+ yylval.integer = (unsigned char)d.val[0];
- yylval.integer = (unsigned char)d.val[0];
-
- if (d.len > 2)
- lexical_error("Character literal has %d"
- " characters instead of 1",
- d.len - 1);
+ if (d.len > 2)
+ lexical_error("Character literal has %d"
+ " characters instead of 1",
+ d.len - 1);
+ }
+ data_free(d);
return DT_CHAR_LITERAL;
}
YY_BREAK
-case 12:
+case 13:
YY_RULE_SETUP
-#line 200 "dtc-lexer.l"
+#line 206 "dtc-lexer.l"
{ /* label reference */
DPRINT("Ref: %s\n", yytext+1);
yylval.labelref = xstrdup(yytext+1);
return DT_REF;
}
YY_BREAK
-case 13:
+case 14:
YY_RULE_SETUP
-#line 206 "dtc-lexer.l"
+#line 212 "dtc-lexer.l"
{ /* new-style path reference */
yytext[yyleng-1] = '\0';
DPRINT("Ref: %s\n", yytext+2);
@@ -1128,27 +1135,27 @@ YY_RULE_SETUP
return DT_REF;
}
YY_BREAK
-case 14:
+case 15:
YY_RULE_SETUP
-#line 213 "dtc-lexer.l"
+#line 219 "dtc-lexer.l"
{
yylval.byte = strtol(yytext, NULL, 16);
DPRINT("Byte: %02x\n", (int)yylval.byte);
return DT_BYTE;
}
YY_BREAK
-case 15:
+case 16:
YY_RULE_SETUP
-#line 219 "dtc-lexer.l"
+#line 225 "dtc-lexer.l"
{
DPRINT("/BYTESTRING\n");
BEGIN_DEFAULT();
return ']';
}
YY_BREAK
-case 16:
+case 17:
YY_RULE_SETUP
-#line 225 "dtc-lexer.l"
+#line 231 "dtc-lexer.l"
{
DPRINT("PropNodeName: %s\n", yytext);
yylval.propnodename = xstrdup((yytext[0] == '\\') ?
@@ -1157,75 +1164,75 @@ YY_RULE_SETUP
return DT_PROPNODENAME;
}
YY_BREAK
-case 17:
+case 18:
YY_RULE_SETUP
-#line 233 "dtc-lexer.l"
+#line 239 "dtc-lexer.l"
{
DPRINT("Binary Include\n");
return DT_INCBIN;
}
YY_BREAK
-case 18:
-/* rule 18 can match eol */
-YY_RULE_SETUP
-#line 238 "dtc-lexer.l"
-/* eat whitespace */
- YY_BREAK
case 19:
/* rule 19 can match eol */
YY_RULE_SETUP
-#line 239 "dtc-lexer.l"
-/* eat C-style comments */
+#line 244 "dtc-lexer.l"
+/* eat whitespace */
YY_BREAK
case 20:
/* rule 20 can match eol */
YY_RULE_SETUP
-#line 240 "dtc-lexer.l"
-/* eat C++-style comments */
+#line 245 "dtc-lexer.l"
+/* eat C-style comments */
YY_BREAK
case 21:
+/* rule 21 can match eol */
YY_RULE_SETUP
-#line 242 "dtc-lexer.l"
-{ return DT_LSHIFT; };
+#line 246 "dtc-lexer.l"
+/* eat C++-style comments */
YY_BREAK
case 22:
YY_RULE_SETUP
-#line 243 "dtc-lexer.l"
-{ return DT_RSHIFT; };
+#line 248 "dtc-lexer.l"
+{ return DT_LSHIFT; };
YY_BREAK
case 23:
YY_RULE_SETUP
-#line 244 "dtc-lexer.l"
-{ return DT_LE; };
+#line 249 "dtc-lexer.l"
+{ return DT_RSHIFT; };
YY_BREAK
case 24:
YY_RULE_SETUP
-#line 245 "dtc-lexer.l"
-{ return DT_GE; };
+#line 250 "dtc-lexer.l"
+{ return DT_LE; };
YY_BREAK
case 25:
YY_RULE_SETUP
-#line 246 "dtc-lexer.l"
-{ return DT_EQ; };
+#line 251 "dtc-lexer.l"
+{ return DT_GE; };
YY_BREAK
case 26:
YY_RULE_SETUP
-#line 247 "dtc-lexer.l"
-{ return DT_NE; };
+#line 252 "dtc-lexer.l"
+{ return DT_EQ; };
YY_BREAK
case 27:
YY_RULE_SETUP
-#line 248 "dtc-lexer.l"
-{ return DT_AND; };
+#line 253 "dtc-lexer.l"
+{ return DT_NE; };
YY_BREAK
case 28:
YY_RULE_SETUP
-#line 249 "dtc-lexer.l"
-{ return DT_OR; };
+#line 254 "dtc-lexer.l"
+{ return DT_AND; };
YY_BREAK
case 29:
YY_RULE_SETUP
-#line 251 "dtc-lexer.l"
+#line 255 "dtc-lexer.l"
+{ return DT_OR; };
+ YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 257 "dtc-lexer.l"
{
DPRINT("Char: %c (\\x%02x)\n", yytext[0],
(unsigned)yytext[0]);
@@ -1241,12 +1248,12 @@ YY_RULE_SETUP
return yytext[0];
}
YY_BREAK
-case 30:
+case 31:
YY_RULE_SETUP
-#line 266 "dtc-lexer.l"
+#line 272 "dtc-lexer.l"
ECHO;
YY_BREAK
-#line 1250 "dtc-lexer.lex.c"
+#line 1257 "dtc-lexer.lex.c"
case YY_END_OF_BUFFER:
{
@@ -1388,9 +1395,9 @@ ECHO;
*/
static int yy_get_next_buffer (void)
{
- register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
- register char *source = (yytext_ptr);
- register int number_to_move, i;
+ char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+ char *source = (yytext_ptr);
+ int number_to_move, i;
int ret_val;
if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
@@ -1419,7 +1426,7 @@ static int yy_get_next_buffer (void)
/* Try to read more data. */
/* First move last chars to start of buffer. */
- number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
+ number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr) - 1);
for ( i = 0; i < number_to_move; ++i )
*(dest++) = *(source++);
@@ -1432,7 +1439,7 @@ static int yy_get_next_buffer (void)
else
{
- yy_size_t num_to_read =
+ int num_to_read =
YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
while ( num_to_read <= 0 )
@@ -1446,7 +1453,7 @@ static int yy_get_next_buffer (void)
if ( b->yy_is_our_buffer )
{
- yy_size_t new_size = b->yy_buf_size * 2;
+ int new_size = b->yy_buf_size * 2;
if ( new_size <= 0 )
b->yy_buf_size += b->yy_buf_size / 8;
@@ -1459,7 +1466,7 @@ static int yy_get_next_buffer (void)
}
else
/* Can't grow it, we don't own it. */
- b->yy_ch_buf = 0;
+ b->yy_ch_buf = NULL;
if ( ! b->yy_ch_buf )
YY_FATAL_ERROR(
@@ -1501,9 +1508,9 @@ static int yy_get_next_buffer (void)
else
ret_val = EOB_ACT_CONTINUE_SCAN;
- if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+ if (((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
/* Extend the array by 50%, plus the number we really need. */
- yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
+ int new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size );
if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
@@ -1522,15 +1529,15 @@ static int yy_get_next_buffer (void)
static yy_state_type yy_get_previous_state (void)
{
- register yy_state_type yy_current_state;
- register char *yy_cp;
+ yy_state_type yy_current_state;
+ char *yy_cp;
yy_current_state = (yy_start);
yy_current_state += YY_AT_BOL();
for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
{
- register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
if ( yy_accept[yy_current_state] )
{
(yy_last_accepting_state) = yy_current_state;
@@ -1539,10 +1546,10 @@ static int yy_get_next_buffer (void)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 159 )
+ if ( yy_current_state >= 166 )
yy_c = yy_meta[(unsigned int) yy_c];
}
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
}
return yy_current_state;
@@ -1555,10 +1562,10 @@ static int yy_get_next_buffer (void)
*/
static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state )
{
- register int yy_is_jam;
- register char *yy_cp = (yy_c_buf_p);
+ int yy_is_jam;
+ char *yy_cp = (yy_c_buf_p);
- register YY_CHAR yy_c = 1;
+ YY_CHAR yy_c = 1;
if ( yy_accept[yy_current_state] )
{
(yy_last_accepting_state) = yy_current_state;
@@ -1567,15 +1574,19 @@ static int yy_get_next_buffer (void)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 159 )
+ if ( yy_current_state >= 166 )
yy_c = yy_meta[(unsigned int) yy_c];
}
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
- yy_is_jam = (yy_current_state == 158);
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
+ yy_is_jam = (yy_current_state == 165);
return yy_is_jam ? 0 : yy_current_state;
}
+#ifndef YY_NO_UNPUT
+
+#endif
+
#ifndef YY_NO_INPUT
#ifdef __cplusplus
static int yyinput (void)
@@ -1600,7 +1611,7 @@ static int yy_get_next_buffer (void)
else
{ /* need more input */
- yy_size_t offset = (yy_c_buf_p) - (yytext_ptr);
+ int offset = (yy_c_buf_p) - (yytext_ptr);
++(yy_c_buf_p);
switch ( yy_get_next_buffer( ) )
@@ -1624,7 +1635,7 @@ static int yy_get_next_buffer (void)
case EOB_ACT_END_OF_FILE:
{
if ( yywrap( ) )
- return EOF;
+ return 0;
if ( ! (yy_did_buffer_switch_on_eof) )
YY_NEW_FILE;
@@ -1727,7 +1738,7 @@ static void yy_load_buffer_state (void)
if ( ! b )
YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
- b->yy_buf_size = size;
+ b->yy_buf_size = (yy_size_t)size;
/* yy_ch_buf has to be 2 characters longer than the size given because
* we need to put in 2 end-of-buffer characters.
@@ -1874,7 +1885,7 @@ void yypop_buffer_state (void)
*/
static void yyensure_buffer_stack (void)
{
- yy_size_t num_to_alloc;
+ int num_to_alloc;
if (!(yy_buffer_stack)) {
@@ -1882,15 +1893,15 @@ static void yyensure_buffer_stack (void)
* scanner will even need a stack. We use 2 instead of 1 to avoid an
* immediate realloc on the next call.
*/
- num_to_alloc = 1;
+ num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */
(yy_buffer_stack) = (struct yy_buffer_state**)yyalloc
(num_to_alloc * sizeof(struct yy_buffer_state*)
);
if ( ! (yy_buffer_stack) )
YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
-
+
memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
-
+
(yy_buffer_stack_max) = num_to_alloc;
(yy_buffer_stack_top) = 0;
return;
@@ -1899,7 +1910,7 @@ static void yyensure_buffer_stack (void)
if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
/* Increase the buffer to prepare for a possible push. */
- int grow_size = 8 /* arbitrary grow size */;
+ yy_size_t grow_size = 8 /* arbitrary grow size */;
num_to_alloc = (yy_buffer_stack_max) + grow_size;
(yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc
@@ -1919,7 +1930,7 @@ static void yyensure_buffer_stack (void)
* @param base the character buffer
* @param size the size in bytes of the character buffer
*
- * @return the newly allocated buffer state object.
+ * @return the newly allocated buffer state object.
*/
YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size )
{
@@ -1929,7 +1940,7 @@ YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size )
base[size-2] != YY_END_OF_BUFFER_CHAR ||
base[size-1] != YY_END_OF_BUFFER_CHAR )
/* They forgot to leave room for the EOB's. */
- return 0;
+ return NULL;
b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) );
if ( ! b )
@@ -1938,7 +1949,7 @@ YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size )
b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
b->yy_buf_pos = b->yy_ch_buf = base;
b->yy_is_our_buffer = 0;
- b->yy_input_file = 0;
+ b->yy_input_file = NULL;
b->yy_n_chars = b->yy_buf_size;
b->yy_is_interactive = 0;
b->yy_at_bol = 1;
@@ -1961,7 +1972,7 @@ YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size )
YY_BUFFER_STATE yy_scan_string (yyconst char * yystr )
{
- return yy_scan_bytes(yystr,strlen(yystr) );
+ return yy_scan_bytes(yystr,(int) strlen(yystr) );
}
/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
@@ -1971,15 +1982,15 @@ YY_BUFFER_STATE yy_scan_string (yyconst char * yystr )
*
* @return the newly allocated buffer state object.
*/
-YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len )
+YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len )
{
YY_BUFFER_STATE b;
char *buf;
yy_size_t n;
- yy_size_t i;
+ int i;
/* Get memory for full buffer, including space for trailing EOB's. */
- n = _yybytes_len + 2;
+ n = (yy_size_t) (_yybytes_len + 2);
buf = (char *) yyalloc(n );
if ( ! buf )
YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
@@ -2005,9 +2016,9 @@ YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len
#define YY_EXIT_FAILURE 2
#endif
-static void yy_fatal_error (yyconst char* msg )
+static void yynoreturn yy_fatal_error (yyconst char* msg )
{
- (void) fprintf( stderr, "%s\n", msg );
+ (void) fprintf( stderr, "%s\n", msg );
exit( YY_EXIT_FAILURE );
}
@@ -2035,7 +2046,7 @@ static void yy_fatal_error (yyconst char* msg )
*/
int yyget_lineno (void)
{
-
+
return yylineno;
}
@@ -2058,7 +2069,7 @@ FILE *yyget_out (void)
/** Get the length of the current token.
*
*/
-yy_size_t yyget_leng (void)
+int yyget_leng (void)
{
return yyleng;
}
@@ -2073,29 +2084,29 @@ char *yyget_text (void)
}
/** Set the current line number.
- * @param line_number
+ * @param _line_number line number
*
*/
-void yyset_lineno (int line_number )
+void yyset_lineno (int _line_number )
{
- yylineno = line_number;
+ yylineno = _line_number;
}
/** Set the input stream. This does not discard the current
* input buffer.
- * @param in_str A readable stream.
+ * @param _in_str A readable stream.
*
* @see yy_switch_to_buffer
*/
-void yyset_in (FILE * in_str )
+void yyset_in (FILE * _in_str )
{
- yyin = in_str ;
+ yyin = _in_str ;
}
-void yyset_out (FILE * out_str )
+void yyset_out (FILE * _out_str )
{
- yyout = out_str ;
+ yyout = _out_str ;
}
int yyget_debug (void)
@@ -2103,9 +2114,9 @@ int yyget_debug (void)
return yy_flex_debug;
}
-void yyset_debug (int bdebug )
+void yyset_debug (int _bdebug )
{
- yy_flex_debug = bdebug ;
+ yy_flex_debug = _bdebug ;
}
static int yy_init_globals (void)
@@ -2114,10 +2125,10 @@ static int yy_init_globals (void)
* This function is called from yylex_destroy(), so don't allocate here.
*/
- (yy_buffer_stack) = 0;
+ (yy_buffer_stack) = NULL;
(yy_buffer_stack_top) = 0;
(yy_buffer_stack_max) = 0;
- (yy_c_buf_p) = (char *) 0;
+ (yy_c_buf_p) = NULL;
(yy_init) = 0;
(yy_start) = 0;
@@ -2126,8 +2137,8 @@ static int yy_init_globals (void)
yyin = stdin;
yyout = stdout;
#else
- yyin = (FILE *) 0;
- yyout = (FILE *) 0;
+ yyin = NULL;
+ yyout = NULL;
#endif
/* For future reference: Set errno on error, since we are called by
@@ -2165,7 +2176,8 @@ int yylex_destroy (void)
#ifndef yytext_ptr
static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
{
- register int i;
+
+ int i;
for ( i = 0; i < n; ++i )
s1[i] = s2[i];
}
@@ -2174,7 +2186,7 @@ static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
#ifdef YY_NEED_STRLEN
static int yy_flex_strlen (yyconst char * s )
{
- register int n;
+ int n;
for ( n = 0; s[n]; ++n )
;
@@ -2184,11 +2196,12 @@ static int yy_flex_strlen (yyconst char * s )
void *yyalloc (yy_size_t size )
{
- return (void *) malloc( size );
+ return malloc(size);
}
void *yyrealloc (void * ptr, yy_size_t size )
{
+
/* The cast to (char *) in the following accommodates both
* implementations that use char* generic pointers, and those
* that use void* generic pointers. It works with the latter
@@ -2196,17 +2209,17 @@ void *yyrealloc (void * ptr, yy_size_t size )
* any pointer type to void*, and deal with argument conversions
* as though doing an assignment.
*/
- return (void *) realloc( (char *) ptr, size );
+ return realloc(ptr, size);
}
void yyfree (void * ptr )
{
- free( (char *) ptr ); /* see yyrealloc() for (char *) cast */
+ free( (char *) ptr ); /* see yyrealloc() for (char *) cast */
}
#define YYTABLES_NAME "yytables"
-#line 265 "dtc-lexer.l"
+#line 272 "dtc-lexer.l"
diff --git a/scripts/dtc/dtc-parser.tab.c_shipped b/scripts/dtc/dtc-parser.tab.c_shipped
index 31cec50..0a7a5ed 100644
--- a/scripts/dtc/dtc-parser.tab.c_shipped
+++ b/scripts/dtc/dtc-parser.tab.c_shipped
@@ -1,8 +1,8 @@
-/* A Bison parser, made by GNU Bison 3.0.2. */
+/* A Bison parser, made by GNU Bison 3.0.4. */
/* Bison implementation for Yacc-like parsers in C
- Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc.
+ Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -44,7 +44,7 @@
#define YYBISON 1
/* Bison version. */
-#define YYBISON_VERSION "3.0.2"
+#define YYBISON_VERSION "3.0.4"
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
@@ -65,6 +65,7 @@
#line 20 "dtc-parser.y" /* yacc.c:339 */
#include <stdio.h>
+#include <inttypes.h>
#include "dtc.h"
#include "srcpos.h"
@@ -77,10 +78,10 @@ extern void yyerror(char const *s);
treesource_error = true; \
} while (0)
-extern struct boot_info *the_boot_info;
+extern struct dt_info *parser_output;
extern bool treesource_error;
-#line 84 "dtc-parser.tab.c" /* yacc.c:339 */
+#line 85 "dtc-parser.tab.c" /* yacc.c:339 */
# ifndef YY_NULLPTR
# if defined __cplusplus && 201103L <= __cplusplus
@@ -116,35 +117,36 @@ extern int yydebug;
enum yytokentype
{
DT_V1 = 258,
- DT_MEMRESERVE = 259,
- DT_LSHIFT = 260,
- DT_RSHIFT = 261,
- DT_LE = 262,
- DT_GE = 263,
- DT_EQ = 264,
- DT_NE = 265,
- DT_AND = 266,
- DT_OR = 267,
- DT_BITS = 268,
- DT_DEL_PROP = 269,
- DT_DEL_NODE = 270,
- DT_PROPNODENAME = 271,
- DT_LITERAL = 272,
- DT_CHAR_LITERAL = 273,
- DT_BYTE = 274,
- DT_STRING = 275,
- DT_LABEL = 276,
- DT_REF = 277,
- DT_INCBIN = 278
+ DT_PLUGIN = 259,
+ DT_MEMRESERVE = 260,
+ DT_LSHIFT = 261,
+ DT_RSHIFT = 262,
+ DT_LE = 263,
+ DT_GE = 264,
+ DT_EQ = 265,
+ DT_NE = 266,
+ DT_AND = 267,
+ DT_OR = 268,
+ DT_BITS = 269,
+ DT_DEL_PROP = 270,
+ DT_DEL_NODE = 271,
+ DT_PROPNODENAME = 272,
+ DT_LITERAL = 273,
+ DT_CHAR_LITERAL = 274,
+ DT_BYTE = 275,
+ DT_STRING = 276,
+ DT_LABEL = 277,
+ DT_REF = 278,
+ DT_INCBIN = 279
};
#endif
/* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE YYSTYPE;
+
union YYSTYPE
{
-#line 38 "dtc-parser.y" /* yacc.c:355 */
+#line 39 "dtc-parser.y" /* yacc.c:355 */
char *propnodename;
char *labelref;
@@ -162,9 +164,12 @@ union YYSTYPE
struct node *nodelist;
struct reserve_info *re;
uint64_t integer;
+ unsigned int flags;
-#line 167 "dtc-parser.tab.c" /* yacc.c:355 */
+#line 170 "dtc-parser.tab.c" /* yacc.c:355 */
};
+
+typedef union YYSTYPE YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define YYSTYPE_IS_DECLARED 1
#endif
@@ -192,7 +197,7 @@ int yyparse (void);
/* Copy the second part of user declarations. */
-#line 196 "dtc-parser.tab.c" /* yacc.c:358 */
+#line 201 "dtc-parser.tab.c" /* yacc.c:358 */
#ifdef short
# undef short
@@ -434,23 +439,23 @@ union yyalloc
#endif /* !YYCOPY_NEEDED */
/* YYFINAL -- State number of the termination state. */
-#define YYFINAL 4
+#define YYFINAL 6
/* YYLAST -- Last index in YYTABLE. */
-#define YYLAST 136
+#define YYLAST 138
/* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS 47
+#define YYNTOKENS 48
/* YYNNTS -- Number of nonterminals. */
-#define YYNNTS 28
+#define YYNNTS 30
/* YYNRULES -- Number of rules. */
-#define YYNRULES 80
+#define YYNRULES 84
/* YYNSTATES -- Number of states. */
-#define YYNSTATES 144
+#define YYNSTATES 149
/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
by yylex, with out-of-bounds checking. */
#define YYUNDEFTOK 2
-#define YYMAXUTOK 278
+#define YYMAXUTOK 279
#define YYTRANSLATE(YYX) \
((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -462,16 +467,16 @@ static const yytype_uint8 yytranslate[] =
0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 46, 2, 2, 2, 44, 40, 2,
- 32, 34, 43, 41, 33, 42, 2, 25, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 37, 24,
- 35, 28, 29, 36, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 47, 2, 2, 2, 45, 41, 2,
+ 33, 35, 44, 42, 34, 43, 2, 26, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 38, 25,
+ 36, 29, 30, 37, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 30, 2, 31, 39, 2, 2, 2, 2, 2,
+ 2, 31, 2, 32, 40, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 26, 38, 27, 45, 2, 2, 2,
+ 2, 2, 2, 27, 39, 28, 46, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
@@ -486,22 +491,22 @@ static const yytype_uint8 yytranslate[] =
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
};
#if YYDEBUG
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_uint16 yyrline[] =
{
- 0, 104, 104, 113, 116, 123, 127, 135, 139, 144,
- 155, 165, 180, 188, 191, 198, 202, 206, 210, 218,
- 222, 226, 230, 234, 250, 260, 268, 271, 275, 282,
- 298, 303, 322, 336, 343, 344, 345, 352, 356, 357,
- 361, 362, 366, 367, 371, 372, 376, 377, 381, 382,
- 386, 387, 388, 392, 393, 394, 395, 396, 400, 401,
- 402, 406, 407, 408, 412, 413, 422, 431, 435, 436,
- 437, 438, 443, 446, 450, 458, 461, 465, 473, 477,
- 481
+ 0, 109, 109, 117, 121, 128, 129, 139, 142, 149,
+ 153, 161, 165, 170, 181, 191, 206, 214, 217, 224,
+ 228, 232, 236, 244, 248, 252, 256, 260, 276, 286,
+ 294, 297, 301, 308, 324, 329, 348, 362, 369, 370,
+ 371, 378, 382, 383, 387, 388, 392, 393, 397, 398,
+ 402, 403, 407, 408, 412, 413, 414, 418, 419, 420,
+ 421, 422, 426, 427, 428, 432, 433, 434, 438, 439,
+ 448, 457, 461, 462, 463, 464, 469, 472, 476, 484,
+ 487, 491, 499, 503, 507
};
#endif
@@ -510,19 +515,20 @@ static const yytype_uint16 yyrline[] =
First, the terminals, then, starting at YYNTOKENS, nonterminals. */
static const char *const yytname[] =
{
- "$end", "error", "$undefined", "DT_V1", "DT_MEMRESERVE", "DT_LSHIFT",
- "DT_RSHIFT", "DT_LE", "DT_GE", "DT_EQ", "DT_NE", "DT_AND", "DT_OR",
- "DT_BITS", "DT_DEL_PROP", "DT_DEL_NODE", "DT_PROPNODENAME", "DT_LITERAL",
- "DT_CHAR_LITERAL", "DT_BYTE", "DT_STRING", "DT_LABEL", "DT_REF",
- "DT_INCBIN", "';'", "'/'", "'{'", "'}'", "'='", "'>'", "'['", "']'",
- "'('", "','", "')'", "'<'", "'?'", "':'", "'|'", "'^'", "'&'", "'+'",
- "'-'", "'*'", "'%'", "'~'", "'!'", "$accept", "sourcefile",
- "memreserves", "memreserve", "devicetree", "nodedef", "proplist",
- "propdef", "propdata", "propdataprefix", "arrayprefix", "integer_prim",
- "integer_expr", "integer_trinary", "integer_or", "integer_and",
- "integer_bitor", "integer_bitxor", "integer_bitand", "integer_eq",
- "integer_rela", "integer_shift", "integer_add", "integer_mul",
- "integer_unary", "bytestring", "subnodes", "subnode", YY_NULLPTR
+ "$end", "error", "$undefined", "DT_V1", "DT_PLUGIN", "DT_MEMRESERVE",
+ "DT_LSHIFT", "DT_RSHIFT", "DT_LE", "DT_GE", "DT_EQ", "DT_NE", "DT_AND",
+ "DT_OR", "DT_BITS", "DT_DEL_PROP", "DT_DEL_NODE", "DT_PROPNODENAME",
+ "DT_LITERAL", "DT_CHAR_LITERAL", "DT_BYTE", "DT_STRING", "DT_LABEL",
+ "DT_REF", "DT_INCBIN", "';'", "'/'", "'{'", "'}'", "'='", "'>'", "'['",
+ "']'", "'('", "','", "')'", "'<'", "'?'", "':'", "'|'", "'^'", "'&'",
+ "'+'", "'-'", "'*'", "'%'", "'~'", "'!'", "$accept", "sourcefile",
+ "header", "headers", "memreserves", "memreserve", "devicetree",
+ "nodedef", "proplist", "propdef", "propdata", "propdataprefix",
+ "arrayprefix", "integer_prim", "integer_expr", "integer_trinary",
+ "integer_or", "integer_and", "integer_bitor", "integer_bitxor",
+ "integer_bitand", "integer_eq", "integer_rela", "integer_shift",
+ "integer_add", "integer_mul", "integer_unary", "bytestring", "subnodes",
+ "subnode", YY_NULLPTR
};
#endif
@@ -533,16 +539,16 @@ static const yytype_uint16 yytoknum[] =
{
0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
- 275, 276, 277, 278, 59, 47, 123, 125, 61, 62,
- 91, 93, 40, 44, 41, 60, 63, 58, 124, 94,
- 38, 43, 45, 42, 37, 126, 33
+ 275, 276, 277, 278, 279, 59, 47, 123, 125, 61,
+ 62, 91, 93, 40, 44, 41, 60, 63, 58, 124,
+ 94, 38, 43, 45, 42, 37, 126, 33
};
# endif
-#define YYPACT_NINF -81
+#define YYPACT_NINF -44
#define yypact_value_is_default(Yystate) \
- (!!((Yystate) == (-81)))
+ (!!((Yystate) == (-44)))
#define YYTABLE_NINF -1
@@ -553,21 +559,21 @@ static const yytype_uint16 yytoknum[] =
STATE-NUM. */
static const yytype_int8 yypact[] =
{
- 16, -11, 21, 10, -81, 25, 10, 19, 10, -81,
- -81, -9, 25, -81, 2, 51, -81, -9, -9, -9,
- -81, 1, -81, -6, 50, 14, 28, 29, 36, 3,
- 58, 44, -3, -81, 47, -81, -81, 65, 68, 2,
- 2, -81, -81, -81, -81, -9, -9, -9, -9, -9,
- -9, -9, -9, -9, -9, -9, -9, -9, -9, -9,
- -9, -9, -9, -9, -81, 63, 69, 2, -81, -81,
- 50, 57, 14, 28, 29, 36, 3, 3, 58, 58,
- 58, 58, 44, 44, -3, -3, -81, -81, -81, 79,
- 80, -8, 63, -81, 72, 63, -81, -81, -9, 76,
- 77, -81, -81, -81, -81, -81, 78, -81, -81, -81,
- -81, -81, 35, 4, -81, -81, -81, -81, 86, -81,
- -81, -81, 73, -81, -81, 33, 71, 84, 39, -81,
- -81, -81, -81, -81, 41, -81, -81, -81, 25, -81,
- 74, 25, 75, -81
+ 14, 27, 61, 14, 8, 18, -44, -44, 37, 8,
+ 40, 8, 64, -44, -44, -12, 37, -44, 50, 52,
+ -44, -44, -12, -12, -12, -44, 51, -44, -4, 78,
+ 53, 54, 55, 17, 2, 30, 38, -3, -44, 66,
+ -44, -44, 70, 72, 50, 50, -44, -44, -44, -44,
+ -12, -12, -12, -12, -12, -12, -12, -12, -12, -12,
+ -12, -12, -12, -12, -12, -12, -12, -12, -12, -44,
+ 3, 73, 50, -44, -44, 78, 59, 53, 54, 55,
+ 17, 2, 2, 30, 30, 30, 30, 38, 38, -3,
+ -3, -44, -44, -44, 82, 83, 44, 3, -44, 74,
+ 3, -44, -44, -12, 76, 79, -44, -44, -44, -44,
+ -44, 80, -44, -44, -44, -44, -44, -10, 36, -44,
+ -44, -44, -44, 85, -44, -44, -44, 75, -44, -44,
+ 21, 71, 88, -6, -44, -44, -44, -44, -44, 11,
+ -44, -44, -44, 37, -44, 77, 37, 81, -44
};
/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
@@ -575,37 +581,37 @@ static const yytype_int8 yypact[] =
means the default is an error. */
static const yytype_uint8 yydefact[] =
{
- 0, 0, 0, 3, 1, 0, 0, 0, 3, 34,
- 35, 0, 0, 6, 0, 2, 4, 0, 0, 0,
- 68, 0, 37, 38, 40, 42, 44, 46, 48, 50,
- 53, 60, 63, 67, 0, 13, 7, 0, 0, 0,
- 0, 69, 70, 71, 36, 0, 0, 0, 0, 0,
+ 0, 0, 0, 5, 7, 3, 1, 6, 0, 0,
+ 0, 7, 0, 38, 39, 0, 0, 10, 0, 2,
+ 8, 4, 0, 0, 0, 72, 0, 41, 42, 44,
+ 46, 48, 50, 52, 54, 57, 64, 67, 71, 0,
+ 17, 11, 0, 0, 0, 0, 73, 74, 75, 40,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 5, 75, 0, 0, 10, 8,
- 41, 0, 43, 45, 47, 49, 51, 52, 56, 57,
- 55, 54, 58, 59, 61, 62, 65, 64, 66, 0,
- 0, 0, 0, 14, 0, 75, 11, 9, 0, 0,
- 0, 16, 26, 78, 18, 80, 0, 77, 76, 39,
- 17, 79, 0, 0, 12, 25, 15, 27, 0, 19,
- 28, 22, 0, 72, 30, 0, 0, 0, 0, 33,
- 32, 20, 31, 29, 0, 73, 74, 21, 0, 24,
- 0, 0, 0, 23
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,
+ 79, 0, 0, 14, 12, 45, 0, 47, 49, 51,
+ 53, 55, 56, 60, 61, 59, 58, 62, 63, 65,
+ 66, 69, 68, 70, 0, 0, 0, 0, 18, 0,
+ 79, 15, 13, 0, 0, 0, 20, 30, 82, 22,
+ 84, 0, 81, 80, 43, 21, 83, 0, 0, 16,
+ 29, 19, 31, 0, 23, 32, 26, 0, 76, 34,
+ 0, 0, 0, 0, 37, 36, 24, 35, 33, 0,
+ 77, 78, 25, 0, 28, 0, 0, 0, 27
};
/* YYPGOTO[NTERM-NUM]. */
static const yytype_int8 yypgoto[] =
{
- -81, -81, 100, 104, -81, -38, -81, -80, -81, -81,
- -81, -5, 66, 13, -81, 70, 67, 81, 64, 82,
- 37, 27, 34, 38, -14, -81, 22, 24
+ -44, -44, -44, 103, 99, 104, -44, -43, -44, -21,
+ -44, -44, -44, -8, 63, 9, -44, 65, 67, 68,
+ 69, 62, 26, 4, 22, 23, -19, -44, 20, 28
};
/* YYDEFGOTO[NTERM-NUM]. */
static const yytype_int16 yydefgoto[] =
{
- -1, 2, 7, 8, 15, 36, 65, 93, 112, 113,
- 125, 20, 21, 22, 23, 24, 25, 26, 27, 28,
- 29, 30, 31, 32, 33, 128, 94, 95
+ -1, 2, 3, 4, 10, 11, 19, 41, 70, 98,
+ 117, 118, 130, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 133, 99, 100
};
/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If
@@ -613,87 +619,87 @@ static const yytype_int16 yydefgoto[] =
number is the opposite. If YYTABLE_NINF, syntax error. */
static const yytype_uint8 yytable[] =
{
- 12, 68, 69, 41, 42, 43, 45, 34, 9, 10,
- 53, 54, 104, 3, 5, 107, 101, 118, 35, 1,
- 102, 4, 61, 11, 119, 120, 121, 122, 35, 97,
- 46, 6, 55, 17, 123, 44, 18, 19, 56, 124,
- 62, 63, 9, 10, 14, 51, 52, 86, 87, 88,
- 9, 10, 48, 103, 129, 130, 115, 11, 135, 116,
- 136, 47, 131, 57, 58, 11, 37, 49, 117, 50,
- 137, 64, 38, 39, 138, 139, 40, 89, 90, 91,
- 78, 79, 80, 81, 92, 59, 60, 66, 76, 77,
- 67, 82, 83, 96, 98, 99, 100, 84, 85, 106,
- 110, 111, 114, 126, 134, 127, 133, 141, 16, 143,
- 13, 109, 71, 74, 72, 70, 105, 108, 0, 0,
- 132, 0, 0, 0, 0, 0, 0, 0, 0, 73,
- 0, 0, 75, 140, 0, 0, 142
+ 16, 73, 74, 46, 47, 48, 13, 14, 39, 50,
+ 58, 59, 120, 8, 140, 121, 141, 1, 94, 95,
+ 96, 15, 12, 66, 122, 97, 142, 56, 57, 102,
+ 9, 22, 60, 51, 23, 24, 62, 63, 61, 13,
+ 14, 67, 68, 134, 135, 143, 144, 91, 92, 93,
+ 123, 136, 5, 108, 15, 13, 14, 124, 125, 126,
+ 127, 6, 83, 84, 85, 86, 18, 128, 42, 106,
+ 15, 40, 129, 107, 43, 44, 109, 40, 45, 112,
+ 64, 65, 81, 82, 87, 88, 49, 89, 90, 21,
+ 52, 69, 53, 71, 54, 72, 55, 103, 101, 104,
+ 105, 115, 111, 131, 116, 119, 7, 138, 132, 139,
+ 20, 146, 114, 17, 76, 75, 148, 80, 0, 77,
+ 113, 78, 137, 79, 0, 110, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 145, 0, 0, 147
};
static const yytype_int16 yycheck[] =
{
- 5, 39, 40, 17, 18, 19, 12, 12, 17, 18,
- 7, 8, 92, 24, 4, 95, 24, 13, 26, 3,
- 28, 0, 25, 32, 20, 21, 22, 23, 26, 67,
- 36, 21, 29, 42, 30, 34, 45, 46, 35, 35,
- 43, 44, 17, 18, 25, 9, 10, 61, 62, 63,
- 17, 18, 38, 91, 21, 22, 21, 32, 19, 24,
- 21, 11, 29, 5, 6, 32, 15, 39, 33, 40,
- 31, 24, 21, 22, 33, 34, 25, 14, 15, 16,
- 53, 54, 55, 56, 21, 41, 42, 22, 51, 52,
- 22, 57, 58, 24, 37, 16, 16, 59, 60, 27,
- 24, 24, 24, 17, 20, 32, 35, 33, 8, 34,
- 6, 98, 46, 49, 47, 45, 92, 95, -1, -1,
- 125, -1, -1, -1, -1, -1, -1, -1, -1, 48,
- -1, -1, 50, 138, -1, -1, 141
+ 8, 44, 45, 22, 23, 24, 18, 19, 16, 13,
+ 8, 9, 22, 5, 20, 25, 22, 3, 15, 16,
+ 17, 33, 4, 26, 34, 22, 32, 10, 11, 72,
+ 22, 43, 30, 37, 46, 47, 6, 7, 36, 18,
+ 19, 44, 45, 22, 23, 34, 35, 66, 67, 68,
+ 14, 30, 25, 96, 33, 18, 19, 21, 22, 23,
+ 24, 0, 58, 59, 60, 61, 26, 31, 16, 25,
+ 33, 27, 36, 29, 22, 23, 97, 27, 26, 100,
+ 42, 43, 56, 57, 62, 63, 35, 64, 65, 25,
+ 12, 25, 39, 23, 40, 23, 41, 38, 25, 17,
+ 17, 25, 28, 18, 25, 25, 3, 36, 33, 21,
+ 11, 34, 103, 9, 51, 50, 35, 55, -1, 52,
+ 100, 53, 130, 54, -1, 97, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 143, -1, -1, 146
};
/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
symbol of state STATE-NUM. */
static const yytype_uint8 yystos[] =
{
- 0, 3, 48, 24, 0, 4, 21, 49, 50, 17,
- 18, 32, 58, 50, 25, 51, 49, 42, 45, 46,
- 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
- 68, 69, 70, 71, 58, 26, 52, 15, 21, 22,
- 25, 71, 71, 71, 34, 12, 36, 11, 38, 39,
- 40, 9, 10, 7, 8, 29, 35, 5, 6, 41,
- 42, 25, 43, 44, 24, 53, 22, 22, 52, 52,
- 62, 59, 63, 64, 65, 66, 67, 67, 68, 68,
- 68, 68, 69, 69, 70, 70, 71, 71, 71, 14,
- 15, 16, 21, 54, 73, 74, 24, 52, 37, 16,
- 16, 24, 28, 52, 54, 74, 27, 54, 73, 60,
- 24, 24, 55, 56, 24, 21, 24, 33, 13, 20,
- 21, 22, 23, 30, 35, 57, 17, 32, 72, 21,
- 22, 29, 58, 35, 20, 19, 21, 31, 33, 34,
- 58, 33, 58, 34
+ 0, 3, 49, 50, 51, 25, 0, 51, 5, 22,
+ 52, 53, 4, 18, 19, 33, 61, 53, 26, 54,
+ 52, 25, 43, 46, 47, 61, 62, 63, 64, 65,
+ 66, 67, 68, 69, 70, 71, 72, 73, 74, 61,
+ 27, 55, 16, 22, 23, 26, 74, 74, 74, 35,
+ 13, 37, 12, 39, 40, 41, 10, 11, 8, 9,
+ 30, 36, 6, 7, 42, 43, 26, 44, 45, 25,
+ 56, 23, 23, 55, 55, 65, 62, 66, 67, 68,
+ 69, 70, 70, 71, 71, 71, 71, 72, 72, 73,
+ 73, 74, 74, 74, 15, 16, 17, 22, 57, 76,
+ 77, 25, 55, 38, 17, 17, 25, 29, 55, 57,
+ 77, 28, 57, 76, 63, 25, 25, 58, 59, 25,
+ 22, 25, 34, 14, 21, 22, 23, 24, 31, 36,
+ 60, 18, 33, 75, 22, 23, 30, 61, 36, 21,
+ 20, 22, 32, 34, 35, 61, 34, 61, 35
};
/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
static const yytype_uint8 yyr1[] =
{
- 0, 47, 48, 49, 49, 50, 50, 51, 51, 51,
- 51, 51, 52, 53, 53, 54, 54, 54, 54, 55,
- 55, 55, 55, 55, 55, 55, 56, 56, 56, 57,
- 57, 57, 57, 57, 58, 58, 58, 59, 60, 60,
- 61, 61, 62, 62, 63, 63, 64, 64, 65, 65,
- 66, 66, 66, 67, 67, 67, 67, 67, 68, 68,
- 68, 69, 69, 69, 70, 70, 70, 70, 71, 71,
- 71, 71, 72, 72, 72, 73, 73, 73, 74, 74,
- 74
+ 0, 48, 49, 50, 50, 51, 51, 52, 52, 53,
+ 53, 54, 54, 54, 54, 54, 55, 56, 56, 57,
+ 57, 57, 57, 58, 58, 58, 58, 58, 58, 58,
+ 59, 59, 59, 60, 60, 60, 60, 60, 61, 61,
+ 61, 62, 63, 63, 64, 64, 65, 65, 66, 66,
+ 67, 67, 68, 68, 69, 69, 69, 70, 70, 70,
+ 70, 70, 71, 71, 71, 72, 72, 72, 73, 73,
+ 73, 73, 74, 74, 74, 74, 75, 75, 75, 76,
+ 76, 76, 77, 77, 77
};
/* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */
static const yytype_uint8 yyr2[] =
{
- 0, 2, 4, 0, 2, 4, 2, 2, 3, 4,
- 3, 4, 5, 0, 2, 4, 2, 3, 2, 2,
- 3, 4, 2, 9, 5, 2, 0, 2, 2, 3,
- 1, 2, 2, 2, 1, 1, 3, 1, 1, 5,
- 1, 3, 1, 3, 1, 3, 1, 3, 1, 3,
- 1, 3, 3, 1, 3, 3, 3, 3, 3, 3,
- 1, 3, 3, 1, 3, 3, 3, 1, 1, 2,
- 2, 2, 0, 2, 2, 0, 2, 2, 2, 3,
- 2
+ 0, 2, 3, 2, 4, 1, 2, 0, 2, 4,
+ 2, 2, 3, 4, 3, 4, 5, 0, 2, 4,
+ 2, 3, 2, 2, 3, 4, 2, 9, 5, 2,
+ 0, 2, 2, 3, 1, 2, 2, 2, 1, 1,
+ 3, 1, 1, 5, 1, 3, 1, 3, 1, 3,
+ 1, 3, 1, 3, 1, 3, 3, 1, 3, 3,
+ 3, 3, 3, 3, 1, 3, 3, 1, 3, 3,
+ 3, 1, 1, 2, 2, 2, 0, 2, 2, 0,
+ 2, 2, 2, 3, 2
};
@@ -1463,80 +1469,106 @@ yyreduce:
switch (yyn)
{
case 2:
-#line 105 "dtc-parser.y" /* yacc.c:1646 */
+#line 110 "dtc-parser.y" /* yacc.c:1646 */
{
- the_boot_info = build_boot_info((yyvsp[-1].re), (yyvsp[0].node),
- guess_boot_cpuid((yyvsp[0].node)));
+ parser_output = build_dt_info((yyvsp[-2].flags), (yyvsp[-1].re), (yyvsp[0].node),
+ guess_boot_cpuid((yyvsp[0].node)));
}
-#line 1472 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1478 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
case 3:
-#line 113 "dtc-parser.y" /* yacc.c:1646 */
+#line 118 "dtc-parser.y" /* yacc.c:1646 */
{
- (yyval.re) = NULL;
+ (yyval.flags) = DTSF_V1;
}
-#line 1480 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1486 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
case 4:
-#line 117 "dtc-parser.y" /* yacc.c:1646 */
+#line 122 "dtc-parser.y" /* yacc.c:1646 */
+ {
+ (yyval.flags) = DTSF_V1 | DTSF_PLUGIN;
+ }
+#line 1494 "dtc-parser.tab.c" /* yacc.c:1646 */
+ break;
+
+ case 6:
+#line 130 "dtc-parser.y" /* yacc.c:1646 */
+ {
+ if ((yyvsp[0].flags) != (yyvsp[-1].flags))
+ ERROR(&(yylsp[0]), "Header flags don't match earlier ones");
+ (yyval.flags) = (yyvsp[-1].flags);
+ }
+#line 1504 "dtc-parser.tab.c" /* yacc.c:1646 */
+ break;
+
+ case 7:
+#line 139 "dtc-parser.y" /* yacc.c:1646 */
+ {
+ (yyval.re) = NULL;
+ }
+#line 1512 "dtc-parser.tab.c" /* yacc.c:1646 */
+ break;
+
+ case 8:
+#line 143 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.re) = chain_reserve_entry((yyvsp[-1].re), (yyvsp[0].re));
}
-#line 1488 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1520 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 5:
-#line 124 "dtc-parser.y" /* yacc.c:1646 */
+ case 9:
+#line 150 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.re) = build_reserve_entry((yyvsp[-2].integer), (yyvsp[-1].integer));
}
-#line 1496 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1528 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 6:
-#line 128 "dtc-parser.y" /* yacc.c:1646 */
+ case 10:
+#line 154 "dtc-parser.y" /* yacc.c:1646 */
{
add_label(&(yyvsp[0].re)->labels, (yyvsp[-1].labelref));
(yyval.re) = (yyvsp[0].re);
}
-#line 1505 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1537 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 7:
-#line 136 "dtc-parser.y" /* yacc.c:1646 */
+ case 11:
+#line 162 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.node) = name_node((yyvsp[0].node), "");
}
-#line 1513 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1545 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 8:
-#line 140 "dtc-parser.y" /* yacc.c:1646 */
+ case 12:
+#line 166 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.node) = merge_nodes((yyvsp[-2].node), (yyvsp[0].node));
}
-#line 1521 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1553 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 9:
-#line 145 "dtc-parser.y" /* yacc.c:1646 */
+ case 13:
+#line 171 "dtc-parser.y" /* yacc.c:1646 */
{
struct node *target = get_node_by_ref((yyvsp[-3].node), (yyvsp[-1].labelref));
- add_label(&target->labels, (yyvsp[-2].labelref));
- if (target)
+ if (target) {
+ add_label(&target->labels, (yyvsp[-2].labelref));
merge_nodes(target, (yyvsp[0].node));
- else
+ } else
ERROR(&(yylsp[-1]), "Label or path %s not found", (yyvsp[-1].labelref));
(yyval.node) = (yyvsp[-3].node);
}
-#line 1536 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1568 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 10:
-#line 156 "dtc-parser.y" /* yacc.c:1646 */
+ case 14:
+#line 182 "dtc-parser.y" /* yacc.c:1646 */
{
struct node *target = get_node_by_ref((yyvsp[-2].node), (yyvsp[-1].labelref));
@@ -1546,11 +1578,11 @@ yyreduce:
ERROR(&(yylsp[-1]), "Label or path %s not found", (yyvsp[-1].labelref));
(yyval.node) = (yyvsp[-2].node);
}
-#line 1550 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1582 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 11:
-#line 166 "dtc-parser.y" /* yacc.c:1646 */
+ case 15:
+#line 192 "dtc-parser.y" /* yacc.c:1646 */
{
struct node *target = get_node_by_ref((yyvsp[-3].node), (yyvsp[-1].labelref));
@@ -1562,100 +1594,100 @@ yyreduce:
(yyval.node) = (yyvsp[-3].node);
}
-#line 1566 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1598 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 12:
-#line 181 "dtc-parser.y" /* yacc.c:1646 */
+ case 16:
+#line 207 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.node) = build_node((yyvsp[-3].proplist), (yyvsp[-2].nodelist));
}
-#line 1574 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1606 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 13:
-#line 188 "dtc-parser.y" /* yacc.c:1646 */
+ case 17:
+#line 214 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.proplist) = NULL;
}
-#line 1582 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1614 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 14:
-#line 192 "dtc-parser.y" /* yacc.c:1646 */
+ case 18:
+#line 218 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.proplist) = chain_property((yyvsp[0].prop), (yyvsp[-1].proplist));
}
-#line 1590 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1622 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 15:
-#line 199 "dtc-parser.y" /* yacc.c:1646 */
+ case 19:
+#line 225 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.prop) = build_property((yyvsp[-3].propnodename), (yyvsp[-1].data));
}
-#line 1598 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1630 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 16:
-#line 203 "dtc-parser.y" /* yacc.c:1646 */
+ case 20:
+#line 229 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.prop) = build_property((yyvsp[-1].propnodename), empty_data);
}
-#line 1606 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1638 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 17:
-#line 207 "dtc-parser.y" /* yacc.c:1646 */
+ case 21:
+#line 233 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.prop) = build_property_delete((yyvsp[-1].propnodename));
}
-#line 1614 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1646 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 18:
-#line 211 "dtc-parser.y" /* yacc.c:1646 */
+ case 22:
+#line 237 "dtc-parser.y" /* yacc.c:1646 */
{
add_label(&(yyvsp[0].prop)->labels, (yyvsp[-1].labelref));
(yyval.prop) = (yyvsp[0].prop);
}
-#line 1623 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1655 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 19:
-#line 219 "dtc-parser.y" /* yacc.c:1646 */
+ case 23:
+#line 245 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.data) = data_merge((yyvsp[-1].data), (yyvsp[0].data));
}
-#line 1631 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1663 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 20:
-#line 223 "dtc-parser.y" /* yacc.c:1646 */
+ case 24:
+#line 249 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.data) = data_merge((yyvsp[-2].data), (yyvsp[-1].array).data);
}
-#line 1639 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1671 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 21:
-#line 227 "dtc-parser.y" /* yacc.c:1646 */
+ case 25:
+#line 253 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.data) = data_merge((yyvsp[-3].data), (yyvsp[-1].data));
}
-#line 1647 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1679 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 22:
-#line 231 "dtc-parser.y" /* yacc.c:1646 */
+ case 26:
+#line 257 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.data) = data_add_marker((yyvsp[-1].data), REF_PATH, (yyvsp[0].labelref));
}
-#line 1655 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1687 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 23:
-#line 235 "dtc-parser.y" /* yacc.c:1646 */
+ case 27:
+#line 261 "dtc-parser.y" /* yacc.c:1646 */
{
FILE *f = srcfile_relative_open((yyvsp[-5].data).val, NULL);
struct data d;
@@ -1671,11 +1703,11 @@ yyreduce:
(yyval.data) = data_merge((yyvsp[-8].data), d);
fclose(f);
}
-#line 1675 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1707 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 24:
-#line 251 "dtc-parser.y" /* yacc.c:1646 */
+ case 28:
+#line 277 "dtc-parser.y" /* yacc.c:1646 */
{
FILE *f = srcfile_relative_open((yyvsp[-1].data).val, NULL);
struct data d = empty_data;
@@ -1685,43 +1717,43 @@ yyreduce:
(yyval.data) = data_merge((yyvsp[-4].data), d);
fclose(f);
}
-#line 1689 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1721 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 25:
-#line 261 "dtc-parser.y" /* yacc.c:1646 */
+ case 29:
+#line 287 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.data) = data_add_marker((yyvsp[-1].data), LABEL, (yyvsp[0].labelref));
}
-#line 1697 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1729 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 26:
-#line 268 "dtc-parser.y" /* yacc.c:1646 */
+ case 30:
+#line 294 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.data) = empty_data;
}
-#line 1705 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1737 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 27:
-#line 272 "dtc-parser.y" /* yacc.c:1646 */
+ case 31:
+#line 298 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.data) = (yyvsp[-1].data);
}
-#line 1713 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1745 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 28:
-#line 276 "dtc-parser.y" /* yacc.c:1646 */
+ case 32:
+#line 302 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.data) = data_add_marker((yyvsp[-1].data), LABEL, (yyvsp[0].labelref));
}
-#line 1721 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1753 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 29:
-#line 283 "dtc-parser.y" /* yacc.c:1646 */
+ case 33:
+#line 309 "dtc-parser.y" /* yacc.c:1646 */
{
unsigned long long bits;
@@ -1737,20 +1769,20 @@ yyreduce:
(yyval.array).data = empty_data;
(yyval.array).bits = bits;
}
-#line 1741 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1773 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 30:
-#line 299 "dtc-parser.y" /* yacc.c:1646 */
+ case 34:
+#line 325 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.array).data = empty_data;
(yyval.array).bits = 32;
}
-#line 1750 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1782 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 31:
-#line 304 "dtc-parser.y" /* yacc.c:1646 */
+ case 35:
+#line 330 "dtc-parser.y" /* yacc.c:1646 */
{
if ((yyvsp[-1].array).bits < 64) {
uint64_t mask = (1ULL << (yyvsp[-1].array).bits) - 1;
@@ -1769,11 +1801,11 @@ yyreduce:
(yyval.array).data = data_append_integer((yyvsp[-1].array).data, (yyvsp[0].integer), (yyvsp[-1].array).bits);
}
-#line 1773 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1805 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 32:
-#line 323 "dtc-parser.y" /* yacc.c:1646 */
+ case 36:
+#line 349 "dtc-parser.y" /* yacc.c:1646 */
{
uint64_t val = ~0ULL >> (64 - (yyvsp[-1].array).bits);
@@ -1787,129 +1819,129 @@ yyreduce:
(yyval.array).data = data_append_integer((yyvsp[-1].array).data, val, (yyvsp[-1].array).bits);
}
-#line 1791 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1823 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 33:
-#line 337 "dtc-parser.y" /* yacc.c:1646 */
+ case 37:
+#line 363 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.array).data = data_add_marker((yyvsp[-1].array).data, LABEL, (yyvsp[0].labelref));
}
-#line 1799 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1831 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 36:
-#line 346 "dtc-parser.y" /* yacc.c:1646 */
+ case 40:
+#line 372 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.integer) = (yyvsp[-1].integer);
}
-#line 1807 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1839 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 39:
-#line 357 "dtc-parser.y" /* yacc.c:1646 */
+ case 43:
+#line 383 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = (yyvsp[-4].integer) ? (yyvsp[-2].integer) : (yyvsp[0].integer); }
-#line 1813 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1845 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 41:
-#line 362 "dtc-parser.y" /* yacc.c:1646 */
+ case 45:
+#line 388 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = (yyvsp[-2].integer) || (yyvsp[0].integer); }
-#line 1819 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1851 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 43:
-#line 367 "dtc-parser.y" /* yacc.c:1646 */
+ case 47:
+#line 393 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = (yyvsp[-2].integer) && (yyvsp[0].integer); }
-#line 1825 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1857 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 45:
-#line 372 "dtc-parser.y" /* yacc.c:1646 */
+ case 49:
+#line 398 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = (yyvsp[-2].integer) | (yyvsp[0].integer); }
-#line 1831 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1863 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 47:
-#line 377 "dtc-parser.y" /* yacc.c:1646 */
+ case 51:
+#line 403 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = (yyvsp[-2].integer) ^ (yyvsp[0].integer); }
-#line 1837 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1869 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 49:
-#line 382 "dtc-parser.y" /* yacc.c:1646 */
+ case 53:
+#line 408 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = (yyvsp[-2].integer) & (yyvsp[0].integer); }
-#line 1843 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1875 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 51:
-#line 387 "dtc-parser.y" /* yacc.c:1646 */
+ case 55:
+#line 413 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = (yyvsp[-2].integer) == (yyvsp[0].integer); }
-#line 1849 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1881 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 52:
-#line 388 "dtc-parser.y" /* yacc.c:1646 */
+ case 56:
+#line 414 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = (yyvsp[-2].integer) != (yyvsp[0].integer); }
-#line 1855 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1887 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 54:
-#line 393 "dtc-parser.y" /* yacc.c:1646 */
+ case 58:
+#line 419 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = (yyvsp[-2].integer) < (yyvsp[0].integer); }
-#line 1861 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1893 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 55:
-#line 394 "dtc-parser.y" /* yacc.c:1646 */
+ case 59:
+#line 420 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = (yyvsp[-2].integer) > (yyvsp[0].integer); }
-#line 1867 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1899 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 56:
-#line 395 "dtc-parser.y" /* yacc.c:1646 */
+ case 60:
+#line 421 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = (yyvsp[-2].integer) <= (yyvsp[0].integer); }
-#line 1873 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1905 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 57:
-#line 396 "dtc-parser.y" /* yacc.c:1646 */
+ case 61:
+#line 422 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = (yyvsp[-2].integer) >= (yyvsp[0].integer); }
-#line 1879 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1911 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 58:
-#line 400 "dtc-parser.y" /* yacc.c:1646 */
+ case 62:
+#line 426 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = (yyvsp[-2].integer) << (yyvsp[0].integer); }
-#line 1885 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1917 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 59:
-#line 401 "dtc-parser.y" /* yacc.c:1646 */
+ case 63:
+#line 427 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = (yyvsp[-2].integer) >> (yyvsp[0].integer); }
-#line 1891 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1923 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 61:
-#line 406 "dtc-parser.y" /* yacc.c:1646 */
+ case 65:
+#line 432 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = (yyvsp[-2].integer) + (yyvsp[0].integer); }
-#line 1897 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1929 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 62:
-#line 407 "dtc-parser.y" /* yacc.c:1646 */
+ case 66:
+#line 433 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = (yyvsp[-2].integer) - (yyvsp[0].integer); }
-#line 1903 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1935 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 64:
-#line 412 "dtc-parser.y" /* yacc.c:1646 */
+ case 68:
+#line 438 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = (yyvsp[-2].integer) * (yyvsp[0].integer); }
-#line 1909 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1941 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 65:
-#line 414 "dtc-parser.y" /* yacc.c:1646 */
+ case 69:
+#line 440 "dtc-parser.y" /* yacc.c:1646 */
{
if ((yyvsp[0].integer) != 0) {
(yyval.integer) = (yyvsp[-2].integer) / (yyvsp[0].integer);
@@ -1918,11 +1950,11 @@ yyreduce:
(yyval.integer) = 0;
}
}
-#line 1922 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1954 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 66:
-#line 423 "dtc-parser.y" /* yacc.c:1646 */
+ case 70:
+#line 449 "dtc-parser.y" /* yacc.c:1646 */
{
if ((yyvsp[0].integer) != 0) {
(yyval.integer) = (yyvsp[-2].integer) % (yyvsp[0].integer);
@@ -1931,103 +1963,103 @@ yyreduce:
(yyval.integer) = 0;
}
}
-#line 1935 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1967 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 69:
-#line 436 "dtc-parser.y" /* yacc.c:1646 */
+ case 73:
+#line 462 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = -(yyvsp[0].integer); }
-#line 1941 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1973 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 70:
-#line 437 "dtc-parser.y" /* yacc.c:1646 */
+ case 74:
+#line 463 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = ~(yyvsp[0].integer); }
-#line 1947 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1979 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 71:
-#line 438 "dtc-parser.y" /* yacc.c:1646 */
+ case 75:
+#line 464 "dtc-parser.y" /* yacc.c:1646 */
{ (yyval.integer) = !(yyvsp[0].integer); }
-#line 1953 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1985 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 72:
-#line 443 "dtc-parser.y" /* yacc.c:1646 */
+ case 76:
+#line 469 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.data) = empty_data;
}
-#line 1961 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 1993 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 73:
-#line 447 "dtc-parser.y" /* yacc.c:1646 */
+ case 77:
+#line 473 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.data) = data_append_byte((yyvsp[-1].data), (yyvsp[0].byte));
}
-#line 1969 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 2001 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 74:
-#line 451 "dtc-parser.y" /* yacc.c:1646 */
+ case 78:
+#line 477 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.data) = data_add_marker((yyvsp[-1].data), LABEL, (yyvsp[0].labelref));
}
-#line 1977 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 2009 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 75:
-#line 458 "dtc-parser.y" /* yacc.c:1646 */
+ case 79:
+#line 484 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.nodelist) = NULL;
}
-#line 1985 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 2017 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 76:
-#line 462 "dtc-parser.y" /* yacc.c:1646 */
+ case 80:
+#line 488 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.nodelist) = chain_node((yyvsp[-1].node), (yyvsp[0].nodelist));
}
-#line 1993 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 2025 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 77:
-#line 466 "dtc-parser.y" /* yacc.c:1646 */
+ case 81:
+#line 492 "dtc-parser.y" /* yacc.c:1646 */
{
ERROR(&(yylsp[0]), "Properties must precede subnodes");
YYERROR;
}
-#line 2002 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 2034 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 78:
-#line 474 "dtc-parser.y" /* yacc.c:1646 */
+ case 82:
+#line 500 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.node) = name_node((yyvsp[0].node), (yyvsp[-1].propnodename));
}
-#line 2010 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 2042 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 79:
-#line 478 "dtc-parser.y" /* yacc.c:1646 */
+ case 83:
+#line 504 "dtc-parser.y" /* yacc.c:1646 */
{
(yyval.node) = name_node(build_node_delete(), (yyvsp[-1].propnodename));
}
-#line 2018 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 2050 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
- case 80:
-#line 482 "dtc-parser.y" /* yacc.c:1646 */
+ case 84:
+#line 508 "dtc-parser.y" /* yacc.c:1646 */
{
add_label(&(yyvsp[0].node)->labels, (yyvsp[-1].labelref));
(yyval.node) = (yyvsp[0].node);
}
-#line 2027 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 2059 "dtc-parser.tab.c" /* yacc.c:1646 */
break;
-#line 2031 "dtc-parser.tab.c" /* yacc.c:1646 */
+#line 2063 "dtc-parser.tab.c" /* yacc.c:1646 */
default: break;
}
/* User semantic actions sometimes alter yychar, and that requires
@@ -2262,7 +2294,7 @@ yyreturn:
#endif
return yyresult;
}
-#line 488 "dtc-parser.y" /* yacc.c:1906 */
+#line 514 "dtc-parser.y" /* yacc.c:1906 */
void yyerror(char const *s)
diff --git a/scripts/dtc/dtc-parser.tab.h_shipped b/scripts/dtc/dtc-parser.tab.h_shipped
index 30867c6..6aa512c 100644
--- a/scripts/dtc/dtc-parser.tab.h_shipped
+++ b/scripts/dtc/dtc-parser.tab.h_shipped
@@ -1,8 +1,8 @@
-/* A Bison parser, made by GNU Bison 3.0.2. */
+/* A Bison parser, made by GNU Bison 3.0.4. */
/* Bison interface for Yacc-like parsers in C
- Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc.
+ Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -46,35 +46,36 @@ extern int yydebug;
enum yytokentype
{
DT_V1 = 258,
- DT_MEMRESERVE = 259,
- DT_LSHIFT = 260,
- DT_RSHIFT = 261,
- DT_LE = 262,
- DT_GE = 263,
- DT_EQ = 264,
- DT_NE = 265,
- DT_AND = 266,
- DT_OR = 267,
- DT_BITS = 268,
- DT_DEL_PROP = 269,
- DT_DEL_NODE = 270,
- DT_PROPNODENAME = 271,
- DT_LITERAL = 272,
- DT_CHAR_LITERAL = 273,
- DT_BYTE = 274,
- DT_STRING = 275,
- DT_LABEL = 276,
- DT_REF = 277,
- DT_INCBIN = 278
+ DT_PLUGIN = 259,
+ DT_MEMRESERVE = 260,
+ DT_LSHIFT = 261,
+ DT_RSHIFT = 262,
+ DT_LE = 263,
+ DT_GE = 264,
+ DT_EQ = 265,
+ DT_NE = 266,
+ DT_AND = 267,
+ DT_OR = 268,
+ DT_BITS = 269,
+ DT_DEL_PROP = 270,
+ DT_DEL_NODE = 271,
+ DT_PROPNODENAME = 272,
+ DT_LITERAL = 273,
+ DT_CHAR_LITERAL = 274,
+ DT_BYTE = 275,
+ DT_STRING = 276,
+ DT_LABEL = 277,
+ DT_REF = 278,
+ DT_INCBIN = 279
};
#endif
/* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE YYSTYPE;
+
union YYSTYPE
{
-#line 38 "dtc-parser.y" /* yacc.c:1909 */
+#line 39 "dtc-parser.y" /* yacc.c:1909 */
char *propnodename;
char *labelref;
@@ -92,9 +93,12 @@ union YYSTYPE
struct node *nodelist;
struct reserve_info *re;
uint64_t integer;
+ unsigned int flags;
-#line 97 "dtc-parser.tab.h" /* yacc.c:1909 */
+#line 99 "dtc-parser.tab.h" /* yacc.c:1909 */
};
+
+typedef union YYSTYPE YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define YYSTYPE_IS_DECLARED 1
#endif
diff --git a/scripts/dtc/dtc-parser.y b/scripts/dtc/dtc-parser.y
index 000873f..ca3f500 100644
--- a/scripts/dtc/dtc-parser.y
+++ b/scripts/dtc/dtc-parser.y
@@ -19,6 +19,7 @@
*/
%{
#include <stdio.h>
+#include <inttypes.h>
#include "dtc.h"
#include "srcpos.h"
@@ -31,7 +32,7 @@ extern void yyerror(char const *s);
treesource_error = true; \
} while (0)
-extern struct boot_info *the_boot_info;
+extern struct dt_info *parser_output;
extern bool treesource_error;
%}
@@ -52,9 +53,11 @@ extern bool treesource_error;
struct node *nodelist;
struct reserve_info *re;
uint64_t integer;
+ unsigned int flags;
}
%token DT_V1
+%token DT_PLUGIN
%token DT_MEMRESERVE
%token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR
%token DT_BITS
@@ -71,6 +74,8 @@ extern bool treesource_error;
%type <data> propdata
%type <data> propdataprefix
+%type <flags> header
+%type <flags> headers
%type <re> memreserve
%type <re> memreserves
%type <array> arrayprefix
@@ -101,10 +106,31 @@ extern bool treesource_error;
%%
sourcefile:
- DT_V1 ';' memreserves devicetree
+ headers memreserves devicetree
{
- the_boot_info = build_boot_info($3, $4,
- guess_boot_cpuid($4));
+ parser_output = build_dt_info($1, $2, $3,
+ guess_boot_cpuid($3));
+ }
+ ;
+
+header:
+ DT_V1 ';'
+ {
+ $$ = DTSF_V1;
+ }
+ | DT_V1 ';' DT_PLUGIN ';'
+ {
+ $$ = DTSF_V1 | DTSF_PLUGIN;
+ }
+ ;
+
+headers:
+ header
+ | header headers
+ {
+ if ($2 != $1)
+ ERROR(&@2, "Header flags don't match earlier ones");
+ $$ = $1;
}
;
@@ -145,10 +171,10 @@ devicetree:
{
struct node *target = get_node_by_ref($1, $3);
- add_label(&target->labels, $2);
- if (target)
+ if (target) {
+ add_label(&target->labels, $2);
merge_nodes(target, $4);
- else
+ } else
ERROR(&@3, "Label or path %s not found", $3);
$$ = $1;
}
diff --git a/scripts/dtc/dtc.c b/scripts/dtc/dtc.c
index 5fa23c4..f5eed9d 100644
--- a/scripts/dtc/dtc.c
+++ b/scripts/dtc/dtc.c
@@ -30,7 +30,16 @@ int quiet; /* Level of quietness */
int reservenum; /* Number of memory reservation slots */
int minsize; /* Minimum blob size */
int padsize; /* Additional padding to blob */
+int alignsize; /* Additional padding to blob accroding to the alignsize */
int phandle_format = PHANDLE_BOTH; /* Use linux,phandle or phandle properties */
+int generate_symbols; /* enable symbols & fixup support */
+int generate_fixups; /* suppress generation of fixups on symbol support */
+int auto_label_aliases; /* auto generate labels -> aliases */
+
+static int is_power_of_2(int x)
+{
+ return (x > 0) && ((x & (x - 1)) == 0);
+}
static void fill_fullpaths(struct node *tree, const char *prefix)
{
@@ -53,7 +62,7 @@ static void fill_fullpaths(struct node *tree, const char *prefix)
#define FDT_VERSION(version) _FDT_VERSION(version)
#define _FDT_VERSION(version) #version
static const char usage_synopsis[] = "dtc [options] <input file>";
-static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:fb:i:H:sW:E:hv";
+static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@Ahv";
static struct option const usage_long_opts[] = {
{"quiet", no_argument, NULL, 'q'},
{"in-format", a_argument, NULL, 'I'},
@@ -64,6 +73,7 @@ static struct option const usage_long_opts[] = {
{"reserve", a_argument, NULL, 'R'},
{"space", a_argument, NULL, 'S'},
{"pad", a_argument, NULL, 'p'},
+ {"align", a_argument, NULL, 'a'},
{"boot-cpu", a_argument, NULL, 'b'},
{"force", no_argument, NULL, 'f'},
{"include", a_argument, NULL, 'i'},
@@ -71,6 +81,8 @@ static struct option const usage_long_opts[] = {
{"phandle", a_argument, NULL, 'H'},
{"warning", a_argument, NULL, 'W'},
{"error", a_argument, NULL, 'E'},
+ {"symbols", no_argument, NULL, '@'},
+ {"auto-alias", no_argument, NULL, 'A'},
{"help", no_argument, NULL, 'h'},
{"version", no_argument, NULL, 'v'},
{NULL, no_argument, NULL, 0x0},
@@ -91,6 +103,7 @@ static const char * const usage_opts_help[] = {
"\n\tMake space for <number> reserve map entries (for dtb and asm output)",
"\n\tMake the blob at least <bytes> long (extra space)",
"\n\tAdd padding to the blob of <bytes> long (extra space)",
+ "\n\tMake the blob align to the <bytes> (extra space)",
"\n\tSet the physical boot cpu",
"\n\tTry to produce output even if the input tree has errors",
"\n\tAdd a path to search for include files",
@@ -101,6 +114,8 @@ static const char * const usage_opts_help[] = {
"\t\tboth - Both \"linux,phandle\" and \"phandle\" properties",
"\n\tEnable/disable warnings (prefix with \"no-\")",
"\n\tEnable/disable errors (prefix with \"no-\")",
+ "\n\tEnable generation of symbols",
+ "\n\tEnable auto-alias of labels",
"\n\tPrint this help and exit",
"\n\tPrint version and exit",
NULL,
@@ -123,7 +138,7 @@ static const char *guess_type_by_name(const char *fname, const char *fallback)
static const char *guess_input_format(const char *fname, const char *fallback)
{
struct stat statbuf;
- uint32_t magic;
+ fdt32_t magic;
FILE *f;
if (stat(fname, &statbuf) != 0)
@@ -144,8 +159,7 @@ static const char *guess_input_format(const char *fname, const char *fallback)
}
fclose(f);
- magic = fdt32_to_cpu(magic);
- if (magic == FDT_MAGIC)
+ if (fdt32_to_cpu(magic) == FDT_MAGIC)
return "dtb";
return guess_type_by_name(fname, fallback);
@@ -153,7 +167,7 @@ static const char *guess_input_format(const char *fname, const char *fallback)
int main(int argc, char *argv[])
{
- struct boot_info *bi;
+ struct dt_info *dti;
const char *inform = NULL;
const char *outform = NULL;
const char *outname = "-";
@@ -169,6 +183,7 @@ int main(int argc, char *argv[])
reservenum = 0;
minsize = 0;
padsize = 0;
+ alignsize = 0;
while ((opt = util_getopt_long()) != EOF) {
switch (opt) {
@@ -196,6 +211,12 @@ int main(int argc, char *argv[])
case 'p':
padsize = strtol(optarg, NULL, 0);
break;
+ case 'a':
+ alignsize = strtol(optarg, NULL, 0);
+ if (!is_power_of_2(alignsize))
+ die("Invalid argument \"%d\" to -a option\n",
+ alignsize);
+ break;
case 'f':
force = true;
break;
@@ -234,6 +255,13 @@ int main(int argc, char *argv[])
parse_checks_option(false, true, optarg);
break;
+ case '@':
+ generate_symbols = 1;
+ break;
+ case 'A':
+ auto_label_aliases = 1;
+ break;
+
case 'h':
usage(NULL);
default:
@@ -272,27 +300,45 @@ int main(int argc, char *argv[])
}
}
if (streq(inform, "dts"))
- bi = dt_from_source(arg);
+ dti = dt_from_source(arg);
else if (streq(inform, "fs"))
- bi = dt_from_fs(arg);
+ dti = dt_from_fs(arg);
else if(streq(inform, "dtb"))
- bi = dt_from_blob(arg);
+ dti = dt_from_blob(arg);
else
die("Unknown input format \"%s\"\n", inform);
+ dti->outname = outname;
+
if (depfile) {
fputc('\n', depfile);
fclose(depfile);
}
if (cmdline_boot_cpuid != -1)
- bi->boot_cpuid_phys = cmdline_boot_cpuid;
+ dti->boot_cpuid_phys = cmdline_boot_cpuid;
+
+ fill_fullpaths(dti->dt, "");
+ process_checks(force, dti);
+
+ /* on a plugin, generate by default */
+ if (dti->dtsflags & DTSF_PLUGIN) {
+ generate_fixups = 1;
+ }
- fill_fullpaths(bi->dt, "");
- process_checks(force, bi);
+ if (auto_label_aliases)
+ generate_label_tree(dti, "aliases", false);
+
+ if (generate_symbols)
+ generate_label_tree(dti, "__symbols__", true);
+
+ if (generate_fixups) {
+ generate_fixups_tree(dti, "__fixups__");
+ generate_local_fixups_tree(dti, "__local_fixups__");
+ }
if (sort)
- sort_tree(bi);
+ sort_tree(dti);
if (streq(outname, "-")) {
outf = stdout;
@@ -304,11 +350,11 @@ int main(int argc, char *argv[])
}
if (streq(outform, "dts")) {
- dt_to_source(outf, bi);
+ dt_to_source(outf, dti);
} else if (streq(outform, "dtb")) {
- dt_to_blob(outf, bi, outversion);
+ dt_to_blob(outf, dti, outversion);
} else if (streq(outform, "asm")) {
- dt_to_asm(outf, bi, outversion);
+ dt_to_asm(outf, dti, outversion);
} else if (streq(outform, "null")) {
/* do nothing */
} else {
diff --git a/scripts/dtc/dtc.h b/scripts/dtc/dtc.h
index 56212c8..403b79d 100644
--- a/scripts/dtc/dtc.h
+++ b/scripts/dtc/dtc.h
@@ -43,7 +43,6 @@
#define debug(...)
#endif
-
#define DEFAULT_FDT_VERSION 17
/*
@@ -53,7 +52,11 @@ extern int quiet; /* Level of quietness */
extern int reservenum; /* Number of memory reservation slots */
extern int minsize; /* Minimum blob size */
extern int padsize; /* Additional padding to blob */
+extern int alignsize; /* Additional padding to blob accroding to the alignsize */
extern int phandle_format; /* Use linux,phandle or phandle properties */
+extern int generate_symbols; /* generate symbols for nodes with labels */
+extern int generate_fixups; /* generate fixups */
+extern int auto_label_aliases; /* auto generate labels -> aliases */
#define PHANDLE_LEGACY 0x1
#define PHANDLE_EPAPR 0x2
@@ -110,7 +113,7 @@ struct data data_insert_at_marker(struct data d, struct marker *m,
struct data data_merge(struct data d1, struct data d2);
struct data data_append_cell(struct data d, cell_t word);
struct data data_append_integer(struct data d, uint64_t word, int bits);
-struct data data_append_re(struct data d, const struct fdt_reserve_entry *re);
+struct data data_append_re(struct data d, uint64_t address, uint64_t size);
struct data data_append_addr(struct data d, uint64_t addr);
struct data data_append_byte(struct data d, uint8_t byte);
struct data data_append_zeroes(struct data d, int len);
@@ -201,6 +204,8 @@ void delete_property(struct property *prop);
void add_child(struct node *parent, struct node *child);
void delete_node_by_name(struct node *parent, char *name);
void delete_node(struct node *node);
+void append_to_property(struct node *node,
+ char *name, const void *data, int len);
const char *get_unitname(struct node *node);
struct property *get_property(struct node *node, const char *propname);
@@ -221,7 +226,7 @@ uint32_t guess_boot_cpuid(struct node *tree);
/* Boot info (tree plus memreserve information */
struct reserve_info {
- struct fdt_reserve_entry re;
+ uint64_t address, size;
struct reserve_info *next;
@@ -235,35 +240,45 @@ struct reserve_info *add_reserve_entry(struct reserve_info *list,
struct reserve_info *new);
-struct boot_info {
+struct dt_info {
+ unsigned int dtsflags;
struct reserve_info *reservelist;
- struct node *dt; /* the device tree */
uint32_t boot_cpuid_phys;
+ struct node *dt; /* the device tree */
+ const char *outname; /* filename being written to, "-" for stdout */
};
-struct boot_info *build_boot_info(struct reserve_info *reservelist,
- struct node *tree, uint32_t boot_cpuid_phys);
-void sort_tree(struct boot_info *bi);
+/* DTS version flags definitions */
+#define DTSF_V1 0x0001 /* /dts-v1/ */
+#define DTSF_PLUGIN 0x0002 /* /plugin/ */
+
+struct dt_info *build_dt_info(unsigned int dtsflags,
+ struct reserve_info *reservelist,
+ struct node *tree, uint32_t boot_cpuid_phys);
+void sort_tree(struct dt_info *dti);
+void generate_label_tree(struct dt_info *dti, char *name, bool allocph);
+void generate_fixups_tree(struct dt_info *dti, char *name);
+void generate_local_fixups_tree(struct dt_info *dti, char *name);
/* Checks */
void parse_checks_option(bool warn, bool error, const char *arg);
-void process_checks(bool force, struct boot_info *bi);
+void process_checks(bool force, struct dt_info *dti);
/* Flattened trees */
-void dt_to_blob(FILE *f, struct boot_info *bi, int version);
-void dt_to_asm(FILE *f, struct boot_info *bi, int version);
+void dt_to_blob(FILE *f, struct dt_info *dti, int version);
+void dt_to_asm(FILE *f, struct dt_info *dti, int version);
-struct boot_info *dt_from_blob(const char *fname);
+struct dt_info *dt_from_blob(const char *fname);
/* Tree source */
-void dt_to_source(FILE *f, struct boot_info *bi);
-struct boot_info *dt_from_source(const char *f);
+void dt_to_source(FILE *f, struct dt_info *dti);
+struct dt_info *dt_from_source(const char *f);
/* FS trees */
-struct boot_info *dt_from_fs(const char *dirname);
+struct dt_info *dt_from_fs(const char *dirname);
#endif /* _DTC_H */
diff --git a/scripts/dtc/flattree.c b/scripts/dtc/flattree.c
index ec14954..fcf7154 100644
--- a/scripts/dtc/flattree.c
+++ b/scripts/dtc/flattree.c
@@ -49,7 +49,7 @@ static struct version_info {
struct emitter {
void (*cell)(void *, cell_t);
- void (*string)(void *, char *, int);
+ void (*string)(void *, const char *, int);
void (*align)(void *, int);
void (*data)(void *, struct data);
void (*beginnode)(void *, struct label *labels);
@@ -64,7 +64,7 @@ static void bin_emit_cell(void *e, cell_t val)
*dtbuf = data_append_cell(*dtbuf, val);
}
-static void bin_emit_string(void *e, char *str, int len)
+static void bin_emit_string(void *e, const char *str, int len)
{
struct data *dtbuf = e;
@@ -144,22 +144,14 @@ static void asm_emit_cell(void *e, cell_t val)
(val >> 8) & 0xff, val & 0xff);
}
-static void asm_emit_string(void *e, char *str, int len)
+static void asm_emit_string(void *e, const char *str, int len)
{
FILE *f = e;
- char c = 0;
- if (len != 0) {
- /* XXX: ewww */
- c = str[len];
- str[len] = '\0';
- }
-
- fprintf(f, "\t.string\t\"%s\"\n", str);
-
- if (len != 0) {
- str[len] = c;
- }
+ if (len != 0)
+ fprintf(f, "\t.string\t\"%.*s\"\n", len, str);
+ else
+ fprintf(f, "\t.string\t\"%s\"\n", str);
}
static void asm_emit_align(void *e, int a)
@@ -179,7 +171,7 @@ static void asm_emit_data(void *e, struct data d)
emit_offset_label(f, m->ref, m->offset);
while ((d.len - off) >= sizeof(uint32_t)) {
- asm_emit_cell(e, fdt32_to_cpu(*((uint32_t *)(d.val+off))));
+ asm_emit_cell(e, fdt32_to_cpu(*((fdt32_t *)(d.val+off))));
off += sizeof(uint32_t);
}
@@ -318,17 +310,16 @@ static struct data flatten_reserve_list(struct reserve_info *reservelist,
{
struct reserve_info *re;
struct data d = empty_data;
- static struct fdt_reserve_entry null_re = {0,0};
int j;
for (re = reservelist; re; re = re->next) {
- d = data_append_re(d, &re->re);
+ d = data_append_re(d, re->address, re->size);
}
/*
* Add additional reserved slots if the user asked for them.
*/
for (j = 0; j < reservenum; j++) {
- d = data_append_re(d, &null_re);
+ d = data_append_re(d, 0, 0);
}
return d;
@@ -366,7 +357,7 @@ static void make_fdt_header(struct fdt_header *fdt,
fdt->size_dt_struct = cpu_to_fdt32(dtsize);
}
-void dt_to_blob(FILE *f, struct boot_info *bi, int version)
+void dt_to_blob(FILE *f, struct dt_info *dti, int version)
{
struct version_info *vi = NULL;
int i;
@@ -384,29 +375,36 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version)
if (!vi)
die("Unknown device tree blob version %d\n", version);
- flatten_tree(bi->dt, &bin_emitter, &dtbuf, &strbuf, vi);
+ flatten_tree(dti->dt, &bin_emitter, &dtbuf, &strbuf, vi);
bin_emit_cell(&dtbuf, FDT_END);
- reservebuf = flatten_reserve_list(bi->reservelist, vi);
+ reservebuf = flatten_reserve_list(dti->reservelist, vi);
/* Make header */
make_fdt_header(&fdt, vi, reservebuf.len, dtbuf.len, strbuf.len,
- bi->boot_cpuid_phys);
+ dti->boot_cpuid_phys);
/*
* If the user asked for more space than is used, adjust the totalsize.
*/
if (minsize > 0) {
padlen = minsize - fdt32_to_cpu(fdt.totalsize);
- if ((padlen < 0) && (quiet < 1))
- fprintf(stderr,
- "Warning: blob size %d >= minimum size %d\n",
- fdt32_to_cpu(fdt.totalsize), minsize);
+ if (padlen < 0) {
+ padlen = 0;
+ if (quiet < 1)
+ fprintf(stderr,
+ "Warning: blob size %d >= minimum size %d\n",
+ fdt32_to_cpu(fdt.totalsize), minsize);
+ }
}
if (padsize > 0)
padlen = padsize;
+ if (alignsize > 0)
+ padlen = ALIGN(fdt32_to_cpu(fdt.totalsize) + padlen, alignsize)
+ - fdt32_to_cpu(fdt.totalsize);
+
if (padlen > 0) {
int tsize = fdt32_to_cpu(fdt.totalsize);
tsize += padlen;
@@ -460,7 +458,7 @@ static void dump_stringtable_asm(FILE *f, struct data strbuf)
}
}
-void dt_to_asm(FILE *f, struct boot_info *bi, int version)
+void dt_to_asm(FILE *f, struct dt_info *dti, int version)
{
struct version_info *vi = NULL;
int i;
@@ -500,7 +498,7 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version)
if (vi->flags & FTF_BOOTCPUID) {
fprintf(f, "\t/* boot_cpuid_phys */\n");
- asm_emit_cell(f, bi->boot_cpuid_phys);
+ asm_emit_cell(f, dti->boot_cpuid_phys);
}
if (vi->flags & FTF_STRTABSIZE) {
@@ -530,18 +528,18 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version)
* Use .long on high and low halfs of u64s to avoid .quad
* as it appears .quad isn't available in some assemblers.
*/
- for (re = bi->reservelist; re; re = re->next) {
+ for (re = dti->reservelist; re; re = re->next) {
struct label *l;
for_each_label(re->labels, l) {
fprintf(f, "\t.globl\t%s\n", l->label);
fprintf(f, "%s:\n", l->label);
}
- ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.address >> 32));
+ ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->address >> 32));
ASM_EMIT_BELONG(f, "0x%08x",
- (unsigned int)(re->re.address & 0xffffffff));
- ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.size >> 32));
- ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.size & 0xffffffff));
+ (unsigned int)(re->address & 0xffffffff));
+ ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->size >> 32));
+ ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->size & 0xffffffff));
}
for (i = 0; i < reservenum; i++) {
fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n");
@@ -550,7 +548,7 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version)
fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n");
emit_label(f, symprefix, "struct_start");
- flatten_tree(bi->dt, &asm_emitter, f, &strbuf, vi);
+ flatten_tree(dti->dt, &asm_emitter, f, &strbuf, vi);
fprintf(f, "\t/* FDT_END */\n");
asm_emit_cell(f, FDT_END);
@@ -572,6 +570,8 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version)
if (padsize > 0) {
fprintf(f, "\t.space\t%d, 0\n", padsize);
}
+ if (alignsize > 0)
+ asm_emit_align(f, alignsize);
emit_label(f, symprefix, "blob_abs_end");
data_free(strbuf);
@@ -600,7 +600,7 @@ static void flat_read_chunk(struct inbuf *inb, void *p, int len)
static uint32_t flat_read_word(struct inbuf *inb)
{
- uint32_t val;
+ fdt32_t val;
assert(((inb->ptr - inb->base) % sizeof(val)) == 0);
@@ -709,13 +709,15 @@ static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb)
* First pass, count entries.
*/
while (1) {
+ uint64_t address, size;
+
flat_read_chunk(inb, &re, sizeof(re));
- re.address = fdt64_to_cpu(re.address);
- re.size = fdt64_to_cpu(re.size);
- if (re.size == 0)
+ address = fdt64_to_cpu(re.address);
+ size = fdt64_to_cpu(re.size);
+ if (size == 0)
break;
- new = build_reserve_entry(re.address, re.size);
+ new = build_reserve_entry(address, size);
reservelist = add_reserve_entry(reservelist, new);
}
@@ -797,13 +799,18 @@ static struct node *unflatten_tree(struct inbuf *dtbuf,
}
} while (val != FDT_END_NODE);
+ if (node->name != flatname) {
+ free(flatname);
+ }
+
return node;
}
-struct boot_info *dt_from_blob(const char *fname)
+struct dt_info *dt_from_blob(const char *fname)
{
FILE *f;
+ fdt32_t magic_buf, totalsize_buf;
uint32_t magic, totalsize, version, size_dt, boot_cpuid_phys;
uint32_t off_dt, off_str, off_mem_rsvmap;
int rc;
@@ -820,7 +827,7 @@ struct boot_info *dt_from_blob(const char *fname)
f = srcfile_relative_open(fname, NULL);
- rc = fread(&magic, sizeof(magic), 1, f);
+ rc = fread(&magic_buf, sizeof(magic_buf), 1, f);
if (ferror(f))
die("Error reading DT blob magic number: %s\n",
strerror(errno));
@@ -831,11 +838,11 @@ struct boot_info *dt_from_blob(const char *fname)
die("Mysterious short read reading magic number\n");
}
- magic = fdt32_to_cpu(magic);
+ magic = fdt32_to_cpu(magic_buf);
if (magic != FDT_MAGIC)
die("Blob has incorrect magic number\n");
- rc = fread(&totalsize, sizeof(totalsize), 1, f);
+ rc = fread(&totalsize_buf, sizeof(totalsize_buf), 1, f);
if (ferror(f))
die("Error reading DT blob size: %s\n", strerror(errno));
if (rc < 1) {
@@ -845,7 +852,7 @@ struct boot_info *dt_from_blob(const char *fname)
die("Mysterious short read reading blob size\n");
}
- totalsize = fdt32_to_cpu(totalsize);
+ totalsize = fdt32_to_cpu(totalsize_buf);
if (totalsize < FDT_V1_SIZE)
die("DT blob size (%d) is too small\n", totalsize);
@@ -929,5 +936,5 @@ struct boot_info *dt_from_blob(const char *fname)
fclose(f);
- return build_boot_info(reservelist, tree, boot_cpuid_phys);
+ return build_dt_info(DTSF_V1, reservelist, tree, boot_cpuid_phys);
}
diff --git a/scripts/dtc/fstree.c b/scripts/dtc/fstree.c
index 6d1beec..ae7d06c 100644
--- a/scripts/dtc/fstree.c
+++ b/scripts/dtc/fstree.c
@@ -79,13 +79,12 @@ static struct node *read_fstree(const char *dirname)
return tree;
}
-struct boot_info *dt_from_fs(const char *dirname)
+struct dt_info *dt_from_fs(const char *dirname)
{
struct node *tree;
tree = read_fstree(dirname);
tree = name_node(tree, "");
- return build_boot_info(NULL, tree, guess_boot_cpuid(tree));
+ return build_dt_info(DTSF_V1, NULL, tree, guess_boot_cpuid(tree));
}
-
diff --git a/scripts/dtc/libfdt/Makefile.libfdt b/scripts/dtc/libfdt/Makefile.libfdt
index 09c322e..098b3f3 100644
--- a/scripts/dtc/libfdt/Makefile.libfdt
+++ b/scripts/dtc/libfdt/Makefile.libfdt
@@ -7,5 +7,5 @@ LIBFDT_soname = libfdt.$(SHAREDLIB_EXT).1
LIBFDT_INCLUDES = fdt.h libfdt.h libfdt_env.h
LIBFDT_VERSION = version.lds
LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c fdt_empty_tree.c \
- fdt_addresses.c
+ fdt_addresses.c fdt_overlay.c
LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)
diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c
index 50cce86..3d00d2e 100644
--- a/scripts/dtc/libfdt/fdt_ro.c
+++ b/scripts/dtc/libfdt/fdt_ro.c
@@ -88,6 +88,32 @@ static int _fdt_string_eq(const void *fdt, int stroffset,
return (strlen(p) == len) && (memcmp(p, s, len) == 0);
}
+uint32_t fdt_get_max_phandle(const void *fdt)
+{
+ uint32_t max_phandle = 0;
+ int offset;
+
+ for (offset = fdt_next_node(fdt, -1, NULL);;
+ offset = fdt_next_node(fdt, offset, NULL)) {
+ uint32_t phandle;
+
+ if (offset == -FDT_ERR_NOTFOUND)
+ return max_phandle;
+
+ if (offset < 0)
+ return (uint32_t)-1;
+
+ phandle = fdt_get_phandle(fdt, offset);
+ if (phandle == (uint32_t)-1)
+ continue;
+
+ if (phandle > max_phandle)
+ max_phandle = phandle;
+ }
+
+ return 0;
+}
+
int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
{
FDT_CHECK_HEADER(fdt);
@@ -545,7 +571,7 @@ int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property)
list = fdt_getprop(fdt, nodeoffset, property, &length);
if (!list)
- return -length;
+ return length;
end = list + length;
@@ -571,7 +597,7 @@ int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property,
list = fdt_getprop(fdt, nodeoffset, property, &length);
if (!list)
- return -length;
+ return length;
len = strlen(string) + 1;
end = list + length;
diff --git a/scripts/dtc/libfdt/fdt_rw.c b/scripts/dtc/libfdt/fdt_rw.c
index 8be02b1..3fd5847 100644
--- a/scripts/dtc/libfdt/fdt_rw.c
+++ b/scripts/dtc/libfdt/fdt_rw.c
@@ -191,17 +191,13 @@ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size)
int fdt_del_mem_rsv(void *fdt, int n)
{
struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n);
- int err;
FDT_RW_CHECK_HEADER(fdt);
if (n >= fdt_num_mem_rsv(fdt))
return -FDT_ERR_NOTFOUND;
- err = _fdt_splice_mem_rsv(fdt, re, 1, 0);
- if (err)
- return err;
- return 0;
+ return _fdt_splice_mem_rsv(fdt, re, 1, 0);
}
static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name,
@@ -287,7 +283,8 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name,
if (err)
return err;
- memcpy(prop->data, val, len);
+ if (len)
+ memcpy(prop->data, val, len);
return 0;
}
diff --git a/scripts/dtc/libfdt/fdt_strerror.c b/scripts/dtc/libfdt/fdt_strerror.c
index e6c3cee..9677a18 100644
--- a/scripts/dtc/libfdt/fdt_strerror.c
+++ b/scripts/dtc/libfdt/fdt_strerror.c
@@ -69,6 +69,7 @@ static struct fdt_errtabent fdt_errtable[] = {
FDT_ERRTABENT(FDT_ERR_BADOFFSET),
FDT_ERRTABENT(FDT_ERR_BADPATH),
+ FDT_ERRTABENT(FDT_ERR_BADPHANDLE),
FDT_ERRTABENT(FDT_ERR_BADSTATE),
FDT_ERRTABENT(FDT_ERR_TRUNCATED),
@@ -76,6 +77,11 @@ static struct fdt_errtabent fdt_errtable[] = {
FDT_ERRTABENT(FDT_ERR_BADVERSION),
FDT_ERRTABENT(FDT_ERR_BADSTRUCTURE),
FDT_ERRTABENT(FDT_ERR_BADLAYOUT),
+ FDT_ERRTABENT(FDT_ERR_INTERNAL),
+ FDT_ERRTABENT(FDT_ERR_BADNCELLS),
+ FDT_ERRTABENT(FDT_ERR_BADVALUE),
+ FDT_ERRTABENT(FDT_ERR_BADOVERLAY),
+ FDT_ERRTABENT(FDT_ERR_NOPHANDLES),
};
#define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0]))
diff --git a/scripts/dtc/libfdt/fdt_wip.c b/scripts/dtc/libfdt/fdt_wip.c
index c5bbb68..6aaab39 100644
--- a/scripts/dtc/libfdt/fdt_wip.c
+++ b/scripts/dtc/libfdt/fdt_wip.c
@@ -55,21 +55,42 @@
#include "libfdt_internal.h"
+int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,
+ const char *name, int namelen,
+ uint32_t idx, const void *val,
+ int len)
+{
+ void *propval;
+ int proplen;
+
+ propval = fdt_getprop_namelen_w(fdt, nodeoffset, name, namelen,
+ &proplen);
+ if (!propval)
+ return proplen;
+
+ if (proplen < (len + idx))
+ return -FDT_ERR_NOSPACE;
+
+ memcpy((char *)propval + idx, val, len);
+ return 0;
+}
+
int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
const void *val, int len)
{
- void *propval;
+ const void *propval;
int proplen;
- propval = fdt_getprop_w(fdt, nodeoffset, name, &proplen);
+ propval = fdt_getprop(fdt, nodeoffset, name, &proplen);
if (! propval)
return proplen;
if (proplen != len)
return -FDT_ERR_NOSPACE;
- memcpy(propval, val, len);
- return 0;
+ return fdt_setprop_inplace_namelen_partial(fdt, nodeoffset, name,
+ strlen(name), 0,
+ val, len);
}
static void _fdt_nop_region(void *start, int len)
diff --git a/scripts/dtc/libfdt/libfdt.h b/scripts/dtc/libfdt/libfdt.h
index 59ca339..9e71bb9 100644
--- a/scripts/dtc/libfdt/libfdt.h
+++ b/scripts/dtc/libfdt/libfdt.h
@@ -61,7 +61,7 @@
#define FDT_ERR_NOTFOUND 1
/* FDT_ERR_NOTFOUND: The requested node or property does not exist */
#define FDT_ERR_EXISTS 2
- /* FDT_ERR_EXISTS: Attemped to create a node or property which
+ /* FDT_ERR_EXISTS: Attempted to create a node or property which
* already exists */
#define FDT_ERR_NOSPACE 3
/* FDT_ERR_NOSPACE: Operation needed to expand the device
@@ -79,8 +79,10 @@
* (e.g. missing a leading / for a function which requires an
* absolute path) */
#define FDT_ERR_BADPHANDLE 6
- /* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle
- * value. phandle values of 0 and -1 are not permitted. */
+ /* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle.
+ * This can be caused either by an invalid phandle property
+ * length, or the phandle value was either 0 or -1, which are
+ * not permitted. */
#define FDT_ERR_BADSTATE 7
/* FDT_ERR_BADSTATE: Function was passed an incomplete device
* tree created by the sequential-write functions, which is
@@ -126,7 +128,16 @@
* value. For example: a property expected to contain a string list
* is not NUL-terminated within the length of its value. */
-#define FDT_ERR_MAX 15
+#define FDT_ERR_BADOVERLAY 16
+ /* FDT_ERR_BADOVERLAY: The device tree overlay, while
+ * correctly structured, cannot be applied due to some
+ * unexpected or missing value, property or node. */
+
+#define FDT_ERR_NOPHANDLES 17
+ /* FDT_ERR_NOPHANDLES: The device tree doesn't have any
+ * phandle available anymore without causing an overflow */
+
+#define FDT_ERR_MAX 17
/**********************************************************************/
/* Low-level functions (you probably don't need these) */
@@ -168,27 +179,55 @@ int fdt_first_subnode(const void *fdt, int offset);
*/
int fdt_next_subnode(const void *fdt, int offset);
+/**
+ * fdt_for_each_subnode - iterate over all subnodes of a parent
+ *
+ * @node: child node (int, lvalue)
+ * @fdt: FDT blob (const void *)
+ * @parent: parent node (int)
+ *
+ * This is actually a wrapper around a for loop and would be used like so:
+ *
+ * fdt_for_each_subnode(node, fdt, parent) {
+ * Use node
+ * ...
+ * }
+ *
+ * if ((node < 0) && (node != -FDT_ERR_NOT_FOUND)) {
+ * Error handling
+ * }
+ *
+ * Note that this is implemented as a macro and @node is used as
+ * iterator in the loop. The parent variable be constant or even a
+ * literal.
+ *
+ */
+#define fdt_for_each_subnode(node, fdt, parent) \
+ for (node = fdt_first_subnode(fdt, parent); \
+ node >= 0; \
+ node = fdt_next_subnode(fdt, node))
+
/**********************************************************************/
/* General functions */
/**********************************************************************/
#define fdt_get_header(fdt, field) \
(fdt32_to_cpu(((const struct fdt_header *)(fdt))->field))
-#define fdt_magic(fdt) (fdt_get_header(fdt, magic))
+#define fdt_magic(fdt) (fdt_get_header(fdt, magic))
#define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize))
#define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct))
#define fdt_off_dt_strings(fdt) (fdt_get_header(fdt, off_dt_strings))
#define fdt_off_mem_rsvmap(fdt) (fdt_get_header(fdt, off_mem_rsvmap))
#define fdt_version(fdt) (fdt_get_header(fdt, version))
-#define fdt_last_comp_version(fdt) (fdt_get_header(fdt, last_comp_version))
-#define fdt_boot_cpuid_phys(fdt) (fdt_get_header(fdt, boot_cpuid_phys))
-#define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings))
+#define fdt_last_comp_version(fdt) (fdt_get_header(fdt, last_comp_version))
+#define fdt_boot_cpuid_phys(fdt) (fdt_get_header(fdt, boot_cpuid_phys))
+#define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings))
#define fdt_size_dt_struct(fdt) (fdt_get_header(fdt, size_dt_struct))
#define __fdt_set_hdr(name) \
static inline void fdt_set_##name(void *fdt, uint32_t val) \
{ \
- struct fdt_header *fdth = (struct fdt_header*)fdt; \
+ struct fdt_header *fdth = (struct fdt_header *)fdt; \
fdth->name = cpu_to_fdt32(val); \
}
__fdt_set_hdr(magic);
@@ -259,6 +298,21 @@ int fdt_move(const void *fdt, void *buf, int bufsize);
const char *fdt_string(const void *fdt, int stroffset);
/**
+ * fdt_get_max_phandle - retrieves the highest phandle in a tree
+ * @fdt: pointer to the device tree blob
+ *
+ * fdt_get_max_phandle retrieves the highest phandle in the given
+ * device tree. This will ignore badly formatted phandles, or phandles
+ * with a value of 0 or -1.
+ *
+ * returns:
+ * the highest phandle on success
+ * 0, if no phandle was found in the device tree
+ * -1, if an error occurred
+ */
+uint32_t fdt_get_max_phandle(const void *fdt);
+
+/**
* fdt_num_mem_rsv - retrieve the number of memory reserve map entries
* @fdt: pointer to the device tree blob
*
@@ -318,8 +372,9 @@ int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
* returns:
* structure block offset of the requested subnode (>=0), on success
* -FDT_ERR_NOTFOUND, if the requested subnode does not exist
- * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE tag
- * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE
+ * tag
+ * -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE,
* -FDT_ERR_BADSTRUCTURE,
@@ -351,7 +406,8 @@ int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen);
* address).
*
* returns:
- * structure block offset of the node with the requested path (>=0), on success
+ * structure block offset of the node with the requested path (>=0), on
+ * success
* -FDT_ERR_BADPATH, given path does not begin with '/' or is invalid
* -FDT_ERR_NOTFOUND, if the requested node does not exist
* -FDT_ERR_BADMAGIC,
@@ -375,10 +431,12 @@ int fdt_path_offset(const void *fdt, const char *path);
*
* returns:
* pointer to the node's name, on success
- * If lenp is non-NULL, *lenp contains the length of that name (>=0)
+ * If lenp is non-NULL, *lenp contains the length of that name
+ * (>=0)
* NULL, on error
* if lenp is non-NULL *lenp contains an error code (<0):
- * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE
+ * tag
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE, standard meanings
@@ -427,6 +485,33 @@ int fdt_first_property_offset(const void *fdt, int nodeoffset);
int fdt_next_property_offset(const void *fdt, int offset);
/**
+ * fdt_for_each_property_offset - iterate over all properties of a node
+ *
+ * @property_offset: property offset (int, lvalue)
+ * @fdt: FDT blob (const void *)
+ * @node: node offset (int)
+ *
+ * This is actually a wrapper around a for loop and would be used like so:
+ *
+ * fdt_for_each_property_offset(property, fdt, node) {
+ * Use property
+ * ...
+ * }
+ *
+ * if ((property < 0) && (property != -FDT_ERR_NOT_FOUND)) {
+ * Error handling
+ * }
+ *
+ * Note that this is implemented as a macro and property is used as
+ * iterator in the loop. The node variable can be constant or even a
+ * literal.
+ */
+#define fdt_for_each_property_offset(property, fdt, node) \
+ for (property = fdt_first_property_offset(fdt, node); \
+ property >= 0; \
+ property = fdt_next_property_offset(fdt, property))
+
+/**
* fdt_get_property_by_offset - retrieve the property at a given offset
* @fdt: pointer to the device tree blob
* @offset: offset of the property to retrieve
@@ -490,7 +575,8 @@ const struct fdt_property *fdt_get_property_namelen(const void *fdt,
* NULL, on error
* if lenp is non-NULL, *lenp contains an error code (<0):
* -FDT_ERR_NOTFOUND, node does not have named property
- * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE
+ * tag
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE,
@@ -554,6 +640,13 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
*/
const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
const char *name, int namelen, int *lenp);
+static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset,
+ const char *name, int namelen,
+ int *lenp)
+{
+ return (void *)(uintptr_t)fdt_getprop_namelen(fdt, nodeoffset, name,
+ namelen, lenp);
+}
/**
* fdt_getprop - retrieve the value of a given property
@@ -575,7 +668,8 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
* NULL, on error
* if lenp is non-NULL, *lenp contains an error code (<0):
* -FDT_ERR_NOTFOUND, node does not have named property
- * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE
+ * tag
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE,
@@ -617,7 +711,7 @@ const char *fdt_get_alias_namelen(const void *fdt,
const char *name, int namelen);
/**
- * fdt_get_alias - retreive the path referenced by a given alias
+ * fdt_get_alias - retrieve the path referenced by a given alias
* @fdt: pointer to the device tree blob
* @name: name of the alias th look up
*
@@ -647,7 +741,7 @@ const char *fdt_get_alias(const void *fdt, const char *name);
* 0, on success
* buf contains the absolute path of the node at
* nodeoffset, as a NUL-terminated string.
- * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
* -FDT_ERR_NOSPACE, the path of the given node is longer than (bufsize-1)
* characters and will not fit in the given buffer.
* -FDT_ERR_BADMAGIC,
@@ -677,11 +771,11 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen);
* structure from the start to nodeoffset.
*
* returns:
-
* structure block offset of the node at node offset's ancestor
* of depth supernodedepth (>=0), on success
- * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
-* -FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of nodeoffset
+ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ * -FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of
+ * nodeoffset
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE,
@@ -703,7 +797,7 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
*
* returns:
* depth of the node at nodeoffset (>=0), on success
- * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE,
@@ -726,7 +820,7 @@ int fdt_node_depth(const void *fdt, int nodeoffset);
* returns:
* structure block offset of the parent of the node at nodeoffset
* (>=0), on success
- * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE,
@@ -766,7 +860,7 @@ int fdt_parent_offset(const void *fdt, int nodeoffset);
* on success
* -FDT_ERR_NOTFOUND, no node matching the criterion exists in the
* tree after startoffset
- * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE,
@@ -813,7 +907,7 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle);
* 1, if the node has a 'compatible' property, but it does not list
* the given string
* -FDT_ERR_NOTFOUND, if the given node has no 'compatible' property
- * -FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag
+ * -FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE,
@@ -850,7 +944,7 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset,
* on success
* -FDT_ERR_NOTFOUND, no node matching the criterion exists in the
* tree after startoffset
- * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE,
@@ -960,7 +1054,8 @@ const char *fdt_stringlist_get(const void *fdt, int nodeoffset,
* returns:
* 0 <= n < FDT_MAX_NCELLS, on success
* 2, if the node has no #address-cells property
- * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid #address-cells property
+ * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid
+ * #address-cells property
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE,
@@ -980,7 +1075,8 @@ int fdt_address_cells(const void *fdt, int nodeoffset);
* returns:
* 0 <= n < FDT_MAX_NCELLS, on success
* 2, if the node has no #address-cells property
- * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid #size-cells property
+ * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid
+ * #size-cells property
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE,
@@ -995,6 +1091,27 @@ int fdt_size_cells(const void *fdt, int nodeoffset);
/**********************************************************************/
/**
+ * fdt_setprop_inplace_namelen_partial - change a property's value,
+ * but not its size
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @namelen: number of characters of name to consider
+ * @idx: index of the property to change in the array
+ * @val: pointer to data to replace the property value with
+ * @len: length of the property value
+ *
+ * Identical to fdt_setprop_inplace(), but modifies the given property
+ * starting from the given index, and using only the first characters
+ * of the name. It is useful when you want to manipulate only one value of
+ * an array and you have a string that doesn't end with \0.
+ */
+int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,
+ const char *name, int namelen,
+ uint32_t idx, const void *val,
+ int len);
+
+/**
* fdt_setprop_inplace - change a property's value, but not its size
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose property to change
@@ -1410,6 +1527,36 @@ static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
#define fdt_setprop_string(fdt, nodeoffset, name, str) \
fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
+
+/**
+ * fdt_setprop_empty - set a property to an empty value
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ *
+ * fdt_setprop_empty() sets the value of the named property in the
+ * given node to an empty (zero length) value, or creates a new empty
+ * property if it does not already exist.
+ *
+ * This function may insert or delete data from the blob, and will
+ * therefore change the offsets of some existing nodes.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ * contain the new property value
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+#define fdt_setprop_empty(fdt, nodeoffset, name) \
+ fdt_setprop((fdt), (nodeoffset), (name), NULL, 0)
+
/**
* fdt_appendprop - append to or create a property
* @fdt: pointer to the device tree blob
@@ -1604,9 +1751,11 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
* change the offsets of some existing nodes.
* returns:
- * structure block offset of the created nodeequested subnode (>=0), on success
+ * structure block offset of the created nodeequested subnode (>=0), on
+ * success
* -FDT_ERR_NOTFOUND, if the requested subnode does not exist
- * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE
+ * tag
* -FDT_ERR_EXISTS, if the node at parentoffset already has a subnode of
* the given name
* -FDT_ERR_NOSPACE, if there is insufficient free space in the
@@ -1644,6 +1793,37 @@ int fdt_add_subnode(void *fdt, int parentoffset, const char *name);
*/
int fdt_del_node(void *fdt, int nodeoffset);
+/**
+ * fdt_overlay_apply - Applies a DT overlay on a base DT
+ * @fdt: pointer to the base device tree blob
+ * @fdto: pointer to the device tree overlay blob
+ *
+ * fdt_overlay_apply() will apply the given device tree overlay on the
+ * given base device tree.
+ *
+ * Expect the base device tree to be modified, even if the function
+ * returns an error.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, there's not enough space in the base device tree
+ * -FDT_ERR_NOTFOUND, the overlay points to some inexistant nodes or
+ * properties in the base DT
+ * -FDT_ERR_BADPHANDLE,
+ * -FDT_ERR_BADOVERLAY,
+ * -FDT_ERR_NOPHANDLES,
+ * -FDT_ERR_INTERNAL,
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADOFFSET,
+ * -FDT_ERR_BADPATH,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_overlay_apply(void *fdt, void *fdto);
+
/**********************************************************************/
/* Debugging / informational functions */
/**********************************************************************/
diff --git a/scripts/dtc/libfdt/libfdt_env.h b/scripts/dtc/libfdt/libfdt_env.h
index 9dea97d..952056c 100644
--- a/scripts/dtc/libfdt/libfdt_env.h
+++ b/scripts/dtc/libfdt/libfdt_env.h
@@ -54,19 +54,20 @@
#include <stddef.h>
#include <stdint.h>
+#include <stdlib.h>
#include <string.h>
#ifdef __CHECKER__
-#define __force __attribute__((force))
-#define __bitwise __attribute__((bitwise))
+#define FDT_FORCE __attribute__((force))
+#define FDT_BITWISE __attribute__((bitwise))
#else
-#define __force
-#define __bitwise
+#define FDT_FORCE
+#define FDT_BITWISE
#endif
-typedef uint16_t __bitwise fdt16_t;
-typedef uint32_t __bitwise fdt32_t;
-typedef uint64_t __bitwise fdt64_t;
+typedef uint16_t FDT_BITWISE fdt16_t;
+typedef uint32_t FDT_BITWISE fdt32_t;
+typedef uint64_t FDT_BITWISE fdt64_t;
#define EXTRACT_BYTE(x, n) ((unsigned long long)((uint8_t *)&x)[n])
#define CPU_TO_FDT16(x) ((EXTRACT_BYTE(x, 0) << 8) | EXTRACT_BYTE(x, 1))
@@ -79,29 +80,29 @@ typedef uint64_t __bitwise fdt64_t;
static inline uint16_t fdt16_to_cpu(fdt16_t x)
{
- return (__force uint16_t)CPU_TO_FDT16(x);
+ return (FDT_FORCE uint16_t)CPU_TO_FDT16(x);
}
static inline fdt16_t cpu_to_fdt16(uint16_t x)
{
- return (__force fdt16_t)CPU_TO_FDT16(x);
+ return (FDT_FORCE fdt16_t)CPU_TO_FDT16(x);
}
static inline uint32_t fdt32_to_cpu(fdt32_t x)
{
- return (__force uint32_t)CPU_TO_FDT32(x);
+ return (FDT_FORCE uint32_t)CPU_TO_FDT32(x);
}
static inline fdt32_t cpu_to_fdt32(uint32_t x)
{
- return (__force fdt32_t)CPU_TO_FDT32(x);
+ return (FDT_FORCE fdt32_t)CPU_TO_FDT32(x);
}
static inline uint64_t fdt64_to_cpu(fdt64_t x)
{
- return (__force uint64_t)CPU_TO_FDT64(x);
+ return (FDT_FORCE uint64_t)CPU_TO_FDT64(x);
}
static inline fdt64_t cpu_to_fdt64(uint64_t x)
{
- return (__force fdt64_t)CPU_TO_FDT64(x);
+ return (FDT_FORCE fdt64_t)CPU_TO_FDT64(x);
}
#undef CPU_TO_FDT64
#undef CPU_TO_FDT32
diff --git a/scripts/dtc/livetree.c b/scripts/dtc/livetree.c
index e229b84..3673de0 100644
--- a/scripts/dtc/livetree.c
+++ b/scripts/dtc/livetree.c
@@ -204,7 +204,7 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
}
}
- /* if no collision occured, add child to the old node. */
+ /* if no collision occurred, add child to the old node. */
if (new_child)
add_child(old_node, new_child);
}
@@ -242,7 +242,7 @@ void delete_property_by_name(struct node *node, char *name)
struct property *prop = node->proplist;
while (prop) {
- if (!strcmp(prop->name, name)) {
+ if (streq(prop->name, name)) {
delete_property(prop);
return;
}
@@ -275,7 +275,7 @@ void delete_node_by_name(struct node *parent, char *name)
struct node *node = parent->children;
while (node) {
- if (!strcmp(node->name, name)) {
+ if (streq(node->name, name)) {
delete_node(node);
return;
}
@@ -296,14 +296,31 @@ void delete_node(struct node *node)
delete_labels(&node->labels);
}
+void append_to_property(struct node *node,
+ char *name, const void *data, int len)
+{
+ struct data d;
+ struct property *p;
+
+ p = get_property(node, name);
+ if (p) {
+ d = data_append_data(p->val, data, len);
+ p->val = d;
+ } else {
+ d = data_append_data(empty_data, data, len);
+ p = build_property(name, d);
+ add_property(node, p);
+ }
+}
+
struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)
{
struct reserve_info *new = xmalloc(sizeof(*new));
memset(new, 0, sizeof(*new));
- new->re.address = address;
- new->re.size = size;
+ new->address = address;
+ new->size = size;
return new;
}
@@ -335,17 +352,19 @@ struct reserve_info *add_reserve_entry(struct reserve_info *list,
return list;
}
-struct boot_info *build_boot_info(struct reserve_info *reservelist,
- struct node *tree, uint32_t boot_cpuid_phys)
+struct dt_info *build_dt_info(unsigned int dtsflags,
+ struct reserve_info *reservelist,
+ struct node *tree, uint32_t boot_cpuid_phys)
{
- struct boot_info *bi;
+ struct dt_info *dti;
- bi = xmalloc(sizeof(*bi));
- bi->reservelist = reservelist;
- bi->dt = tree;
- bi->boot_cpuid_phys = boot_cpuid_phys;
+ dti = xmalloc(sizeof(*dti));
+ dti->dtsflags = dtsflags;
+ dti->reservelist = reservelist;
+ dti->dt = tree;
+ dti->boot_cpuid_phys = boot_cpuid_phys;
- return bi;
+ return dti;
}
/*
@@ -374,7 +393,7 @@ struct property *get_property(struct node *node, const char *propname)
cell_t propval_cell(struct property *prop)
{
assert(prop->val.len == sizeof(cell_t));
- return fdt32_to_cpu(*((cell_t *)prop->val.val));
+ return fdt32_to_cpu(*((fdt32_t *)prop->val.val));
}
struct property *get_property_by_label(struct node *tree, const char *label,
@@ -580,24 +599,24 @@ static int cmp_reserve_info(const void *ax, const void *bx)
a = *((const struct reserve_info * const *)ax);
b = *((const struct reserve_info * const *)bx);
- if (a->re.address < b->re.address)
+ if (a->address < b->address)
return -1;
- else if (a->re.address > b->re.address)
+ else if (a->address > b->address)
return 1;
- else if (a->re.size < b->re.size)
+ else if (a->size < b->size)
return -1;
- else if (a->re.size > b->re.size)
+ else if (a->size > b->size)
return 1;
else
return 0;
}
-static void sort_reserve_entries(struct boot_info *bi)
+static void sort_reserve_entries(struct dt_info *dti)
{
struct reserve_info *ri, **tbl;
int n = 0, i = 0;
- for (ri = bi->reservelist;
+ for (ri = dti->reservelist;
ri;
ri = ri->next)
n++;
@@ -607,14 +626,14 @@ static void sort_reserve_entries(struct boot_info *bi)
tbl = xmalloc(n * sizeof(*tbl));
- for (ri = bi->reservelist;
+ for (ri = dti->reservelist;
ri;
ri = ri->next)
tbl[i++] = ri;
qsort(tbl, n, sizeof(*tbl), cmp_reserve_info);
- bi->reservelist = tbl[0];
+ dti->reservelist = tbl[0];
for (i = 0; i < (n-1); i++)
tbl[i]->next = tbl[i+1];
tbl[n-1]->next = NULL;
@@ -704,8 +723,258 @@ static void sort_node(struct node *node)
sort_node(c);
}
-void sort_tree(struct boot_info *bi)
+void sort_tree(struct dt_info *dti)
+{
+ sort_reserve_entries(dti);
+ sort_node(dti->dt);
+}
+
+/* utility helper to avoid code duplication */
+static struct node *build_and_name_child_node(struct node *parent, char *name)
+{
+ struct node *node;
+
+ node = build_node(NULL, NULL);
+ name_node(node, xstrdup(name));
+ add_child(parent, node);
+
+ return node;
+}
+
+static struct node *build_root_node(struct node *dt, char *name)
+{
+ struct node *an;
+
+ an = get_subnode(dt, name);
+ if (!an)
+ an = build_and_name_child_node(dt, name);
+
+ if (!an)
+ die("Could not build root node /%s\n", name);
+
+ return an;
+}
+
+static bool any_label_tree(struct dt_info *dti, struct node *node)
+{
+ struct node *c;
+
+ if (node->labels)
+ return true;
+
+ for_each_child(node, c)
+ if (any_label_tree(dti, c))
+ return true;
+
+ return false;
+}
+
+static void generate_label_tree_internal(struct dt_info *dti,
+ struct node *an, struct node *node,
+ bool allocph)
{
- sort_reserve_entries(bi);
- sort_node(bi->dt);
+ struct node *dt = dti->dt;
+ struct node *c;
+ struct property *p;
+ struct label *l;
+
+ /* if there are labels */
+ if (node->labels) {
+
+ /* now add the label in the node */
+ for_each_label(node->labels, l) {
+
+ /* check whether the label already exists */
+ p = get_property(an, l->label);
+ if (p) {
+ fprintf(stderr, "WARNING: label %s already"
+ " exists in /%s", l->label,
+ an->name);
+ continue;
+ }
+
+ /* insert it */
+ p = build_property(l->label,
+ data_copy_mem(node->fullpath,
+ strlen(node->fullpath) + 1));
+ add_property(an, p);
+ }
+
+ /* force allocation of a phandle for this node */
+ if (allocph)
+ (void)get_node_phandle(dt, node);
+ }
+
+ for_each_child(node, c)
+ generate_label_tree_internal(dti, an, c, allocph);
+}
+
+static bool any_fixup_tree(struct dt_info *dti, struct node *node)
+{
+ struct node *c;
+ struct property *prop;
+ struct marker *m;
+
+ for_each_property(node, prop) {
+ m = prop->val.markers;
+ for_each_marker_of_type(m, REF_PHANDLE) {
+ if (!get_node_by_ref(dti->dt, m->ref))
+ return true;
+ }
+ }
+
+ for_each_child(node, c) {
+ if (any_fixup_tree(dti, c))
+ return true;
+ }
+
+ return false;
+}
+
+static void add_fixup_entry(struct dt_info *dti, struct node *fn,
+ struct node *node, struct property *prop,
+ struct marker *m)
+{
+ char *entry;
+
+ /* m->ref can only be a REF_PHANDLE, but check anyway */
+ assert(m->type == REF_PHANDLE);
+
+ /* there shouldn't be any ':' in the arguments */
+ if (strchr(node->fullpath, ':') || strchr(prop->name, ':'))
+ die("arguments should not contain ':'\n");
+
+ xasprintf(&entry, "%s:%s:%u",
+ node->fullpath, prop->name, m->offset);
+ append_to_property(fn, m->ref, entry, strlen(entry) + 1);
+
+ free(entry);
+}
+
+static void generate_fixups_tree_internal(struct dt_info *dti,
+ struct node *fn,
+ struct node *node)
+{
+ struct node *dt = dti->dt;
+ struct node *c;
+ struct property *prop;
+ struct marker *m;
+ struct node *refnode;
+
+ for_each_property(node, prop) {
+ m = prop->val.markers;
+ for_each_marker_of_type(m, REF_PHANDLE) {
+ refnode = get_node_by_ref(dt, m->ref);
+ if (!refnode)
+ add_fixup_entry(dti, fn, node, prop, m);
+ }
+ }
+
+ for_each_child(node, c)
+ generate_fixups_tree_internal(dti, fn, c);
+}
+
+static bool any_local_fixup_tree(struct dt_info *dti, struct node *node)
+{
+ struct node *c;
+ struct property *prop;
+ struct marker *m;
+
+ for_each_property(node, prop) {
+ m = prop->val.markers;
+ for_each_marker_of_type(m, REF_PHANDLE) {
+ if (get_node_by_ref(dti->dt, m->ref))
+ return true;
+ }
+ }
+
+ for_each_child(node, c) {
+ if (any_local_fixup_tree(dti, c))
+ return true;
+ }
+
+ return false;
+}
+
+static void add_local_fixup_entry(struct dt_info *dti,
+ struct node *lfn, struct node *node,
+ struct property *prop, struct marker *m,
+ struct node *refnode)
+{
+ struct node *wn, *nwn; /* local fixup node, walk node, new */
+ fdt32_t value_32;
+ char **compp;
+ int i, depth;
+
+ /* walk back retreiving depth */
+ depth = 0;
+ for (wn = node; wn; wn = wn->parent)
+ depth++;
+
+ /* allocate name array */
+ compp = xmalloc(sizeof(*compp) * depth);
+
+ /* store names in the array */
+ for (wn = node, i = depth - 1; wn; wn = wn->parent, i--)
+ compp[i] = wn->name;
+
+ /* walk the path components creating nodes if they don't exist */
+ for (wn = lfn, i = 1; i < depth; i++, wn = nwn) {
+ /* if no node exists, create it */
+ nwn = get_subnode(wn, compp[i]);
+ if (!nwn)
+ nwn = build_and_name_child_node(wn, compp[i]);
+ }
+
+ free(compp);
+
+ value_32 = cpu_to_fdt32(m->offset);
+ append_to_property(wn, prop->name, &value_32, sizeof(value_32));
+}
+
+static void generate_local_fixups_tree_internal(struct dt_info *dti,
+ struct node *lfn,
+ struct node *node)
+{
+ struct node *dt = dti->dt;
+ struct node *c;
+ struct property *prop;
+ struct marker *m;
+ struct node *refnode;
+
+ for_each_property(node, prop) {
+ m = prop->val.markers;
+ for_each_marker_of_type(m, REF_PHANDLE) {
+ refnode = get_node_by_ref(dt, m->ref);
+ if (refnode)
+ add_local_fixup_entry(dti, lfn, node, prop, m, refnode);
+ }
+ }
+
+ for_each_child(node, c)
+ generate_local_fixups_tree_internal(dti, lfn, c);
+}
+
+void generate_label_tree(struct dt_info *dti, char *name, bool allocph)
+{
+ if (!any_label_tree(dti, dti->dt))
+ return;
+ generate_label_tree_internal(dti, build_root_node(dti->dt, name),
+ dti->dt, allocph);
+}
+
+void generate_fixups_tree(struct dt_info *dti, char *name)
+{
+ if (!any_fixup_tree(dti, dti->dt))
+ return;
+ generate_fixups_tree_internal(dti, build_root_node(dti->dt, name),
+ dti->dt);
+}
+
+void generate_local_fixups_tree(struct dt_info *dti, char *name)
+{
+ if (!any_local_fixup_tree(dti, dti->dt))
+ return;
+ generate_local_fixups_tree_internal(dti, build_root_node(dti->dt, name),
+ dti->dt);
}
diff --git a/scripts/dtc/srcpos.c b/scripts/dtc/srcpos.c
index f534c22..9d38459 100644
--- a/scripts/dtc/srcpos.c
+++ b/scripts/dtc/srcpos.c
@@ -246,46 +246,27 @@ srcpos_copy(struct srcpos *pos)
return pos_new;
}
-
-
-void
-srcpos_dump(struct srcpos *pos)
-{
- printf("file : \"%s\"\n",
- pos->file ? (char *) pos->file : "<no file>");
- printf("first_line : %d\n", pos->first_line);
- printf("first_column: %d\n", pos->first_column);
- printf("last_line : %d\n", pos->last_line);
- printf("last_column : %d\n", pos->last_column);
- printf("file : %s\n", pos->file->name);
-}
-
-
char *
srcpos_string(struct srcpos *pos)
{
const char *fname = "<no-file>";
char *pos_str;
- int rc;
- if (pos)
+ if (pos->file && pos->file->name)
fname = pos->file->name;
if (pos->first_line != pos->last_line)
- rc = asprintf(&pos_str, "%s:%d.%d-%d.%d", fname,
- pos->first_line, pos->first_column,
- pos->last_line, pos->last_column);
+ xasprintf(&pos_str, "%s:%d.%d-%d.%d", fname,
+ pos->first_line, pos->first_column,
+ pos->last_line, pos->last_column);
else if (pos->first_column != pos->last_column)
- rc = asprintf(&pos_str, "%s:%d.%d-%d", fname,
- pos->first_line, pos->first_column,
- pos->last_column);
+ xasprintf(&pos_str, "%s:%d.%d-%d", fname,
+ pos->first_line, pos->first_column,
+ pos->last_column);
else
- rc = asprintf(&pos_str, "%s:%d.%d", fname,
- pos->first_line, pos->first_column);
-
- if (rc == -1)
- die("Couldn't allocate in srcpos string");
+ xasprintf(&pos_str, "%s:%d.%d", fname,
+ pos->first_line, pos->first_column);
return pos_str;
}
diff --git a/scripts/dtc/srcpos.h b/scripts/dtc/srcpos.h
index f81827b..7caca82 100644
--- a/scripts/dtc/srcpos.h
+++ b/scripts/dtc/srcpos.h
@@ -22,6 +22,7 @@
#include <stdio.h>
#include <stdbool.h>
+#include "util.h"
struct srcfile_state {
FILE *f;
@@ -105,14 +106,11 @@ extern struct srcpos srcpos_empty;
extern void srcpos_update(struct srcpos *pos, const char *text, int len);
extern struct srcpos *srcpos_copy(struct srcpos *pos);
extern char *srcpos_string(struct srcpos *pos);
-extern void srcpos_dump(struct srcpos *pos);
-
-extern void srcpos_verror(struct srcpos *pos, const char *prefix,
- const char *fmt, va_list va)
- __attribute__((format(printf, 3, 0)));
-extern void srcpos_error(struct srcpos *pos, const char *prefix,
- const char *fmt, ...)
- __attribute__((format(printf, 3, 4)));
+
+extern void PRINTF(3, 0) srcpos_verror(struct srcpos *pos, const char *prefix,
+ const char *fmt, va_list va);
+extern void PRINTF(3, 4) srcpos_error(struct srcpos *pos, const char *prefix,
+ const char *fmt, ...);
extern void srcpos_set_line(char *f, int l);
diff --git a/scripts/dtc/treesource.c b/scripts/dtc/treesource.c
index a55d1d1..2461a3d 100644
--- a/scripts/dtc/treesource.c
+++ b/scripts/dtc/treesource.c
@@ -25,12 +25,12 @@ extern FILE *yyin;
extern int yyparse(void);
extern YYLTYPE yylloc;
-struct boot_info *the_boot_info;
+struct dt_info *parser_output;
bool treesource_error;
-struct boot_info *dt_from_source(const char *fname)
+struct dt_info *dt_from_source(const char *fname)
{
- the_boot_info = NULL;
+ parser_output = NULL;
treesource_error = false;
srcfile_push(fname);
@@ -43,7 +43,7 @@ struct boot_info *dt_from_source(const char *fname)
if (treesource_error)
die("Syntax error parsing input tree\n");
- return the_boot_info;
+ return parser_output;
}
static void write_prefix(FILE *f, int level)
@@ -137,7 +137,7 @@ static void write_propval_string(FILE *f, struct data val)
static void write_propval_cells(FILE *f, struct data val)
{
void *propend = val.val + val.len;
- cell_t *cp = (cell_t *)val.val;
+ fdt32_t *cp = (fdt32_t *)val.val;
struct marker *m = val.markers;
fprintf(f, "<");
@@ -263,22 +263,22 @@ static void write_tree_source_node(FILE *f, struct node *tree, int level)
}
-void dt_to_source(FILE *f, struct boot_info *bi)
+void dt_to_source(FILE *f, struct dt_info *dti)
{
struct reserve_info *re;
fprintf(f, "/dts-v1/;\n\n");
- for (re = bi->reservelist; re; re = re->next) {
+ for (re = dti->reservelist; re; re = re->next) {
struct label *l;
for_each_label(re->labels, l)
fprintf(f, "%s: ", l->label);
fprintf(f, "/memreserve/\t0x%016llx 0x%016llx;\n",
- (unsigned long long)re->re.address,
- (unsigned long long)re->re.size);
+ (unsigned long long)re->address,
+ (unsigned long long)re->size);
}
- write_tree_source_node(f, bi->dt, 0);
+ write_tree_source_node(f, dti->dt, 0);
}
diff --git a/scripts/dtc/util.c b/scripts/dtc/util.c
index fb124ee..9953c32 100644
--- a/scripts/dtc/util.c
+++ b/scripts/dtc/util.c
@@ -46,6 +46,36 @@ char *xstrdup(const char *s)
return d;
}
+/* based in part from (3) vsnprintf */
+int xasprintf(char **strp, const char *fmt, ...)
+{
+ int n, size = 128; /* start with 128 bytes */
+ char *p;
+ va_list ap;
+
+ /* initial pointer is NULL making the fist realloc to be malloc */
+ p = NULL;
+ while (1) {
+ p = xrealloc(p, size);
+
+ /* Try to print in the allocated space. */
+ va_start(ap, fmt);
+ n = vsnprintf(p, size, fmt, ap);
+ va_end(ap);
+
+ /* If that worked, return the string. */
+ if (n > -1 && n < size)
+ break;
+ /* Else try again with more space. */
+ if (n > -1) /* glibc 2.1 */
+ size = n + 1; /* precisely what is needed */
+ else /* glibc 2.0 */
+ size *= 2; /* twice the old size */
+ }
+ *strp = p;
+ return strlen(p);
+}
+
char *join_path(const char *path, const char *name)
{
int lenp = strlen(path);
@@ -366,7 +396,7 @@ void utilfdt_print_data(const char *data, int len)
} while (s < data + len);
} else if ((len % 4) == 0) {
- const uint32_t *cell = (const uint32_t *)data;
+ const fdt32_t *cell = (const fdt32_t *)data;
printf(" = <");
for (i = 0, len /= 4; i < len; i++)
@@ -382,15 +412,16 @@ void utilfdt_print_data(const char *data, int len)
}
}
-void util_version(void)
+void NORETURN util_version(void)
{
printf("Version: %s\n", DTC_VERSION);
exit(0);
}
-void util_usage(const char *errmsg, const char *synopsis,
- const char *short_opts, struct option const long_opts[],
- const char * const opts_help[])
+void NORETURN util_usage(const char *errmsg, const char *synopsis,
+ const char *short_opts,
+ struct option const long_opts[],
+ const char * const opts_help[])
{
FILE *fp = errmsg ? stderr : stdout;
const char a_arg[] = "<arg>";
diff --git a/scripts/dtc/util.h b/scripts/dtc/util.h
index f800b60..ad5f411 100644
--- a/scripts/dtc/util.h
+++ b/scripts/dtc/util.h
@@ -25,9 +25,17 @@
* USA
*/
+#ifdef __GNUC__
+#define PRINTF(i, j) __attribute__((format (printf, i, j)))
+#define NORETURN __attribute__((noreturn))
+#else
+#define PRINTF(i, j)
+#define NORETURN
+#endif
+
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
-static inline void __attribute__((noreturn)) die(const char *str, ...)
+static inline void NORETURN PRINTF(1, 2) die(const char *str, ...)
{
va_list ap;
@@ -53,12 +61,14 @@ static inline void *xrealloc(void *p, size_t len)
void *new = realloc(p, len);
if (!new)
- die("realloc() failed (len=%d)\n", len);
+ die("realloc() failed (len=%zd)\n", len);
return new;
}
extern char *xstrdup(const char *s);
+
+extern int PRINTF(2, 3) xasprintf(char **strp, const char *fmt, ...);
extern char *join_path(const char *path, const char *name);
/**
@@ -187,7 +197,7 @@ void utilfdt_print_data(const char *data, int len);
/**
* Show source version and exit
*/
-void util_version(void) __attribute__((noreturn));
+void NORETURN util_version(void);
/**
* Show usage and exit
@@ -201,9 +211,10 @@ void util_version(void) __attribute__((noreturn));
* @param long_opts The structure of long options
* @param opts_help An array of help strings (should align with long_opts)
*/
-void util_usage(const char *errmsg, const char *synopsis,
- const char *short_opts, struct option const long_opts[],
- const char * const opts_help[]) __attribute__((noreturn));
+void NORETURN util_usage(const char *errmsg, const char *synopsis,
+ const char *short_opts,
+ struct option const long_opts[],
+ const char * const opts_help[]);
/**
* Show usage and exit
diff --git a/scripts/dtc/version_gen.h b/scripts/dtc/version_gen.h
index ad9b05a..859564e 100644
--- a/scripts/dtc/version_gen.h
+++ b/scripts/dtc/version_gen.h
@@ -1 +1 @@
-#define DTC_VERSION "DTC 1.4.1-g53bf130b"
+#define DTC_VERSION "DTC 1.4.4"
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index c67667b..0f40b09 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -135,6 +135,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_TAS5086 if I2C
select SND_SOC_TAS571X if I2C
select SND_SOC_TAS5720 if I2C
+ select SND_SOC_TDM
select SND_SOC_TFA9879 if I2C
select SND_SOC_TLV320AIC23_I2C if I2C
select SND_SOC_TLV320AIC23_SPI if SPI_MASTER
@@ -812,6 +813,9 @@ config SND_SOC_TAS5720
Enable support for Texas Instruments TAS5720L/M high-efficiency mono
Class-D audio power amplifiers.
+config SND_SOC_TDM
+ tristate "Generic TDM codec"
+
config SND_SOC_TFA9879
tristate "NXP Semiconductors TFA9879 amplifier"
depends on I2C
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 958cd49..ea82c79 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -142,6 +142,7 @@ snd-soc-sti-sas-objs := sti-sas.o
snd-soc-tas5086-objs := tas5086.o
snd-soc-tas571x-objs := tas571x.o
snd-soc-tas5720-objs := tas5720.o
+snd-soc-tdm-objs := tdm.o
snd-soc-tfa9879-objs := tfa9879.o
snd-soc-tlv320aic23-objs := tlv320aic23.o
snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o
@@ -363,6 +364,7 @@ obj-$(CONFIG_SND_SOC_TAS2552) += snd-soc-tas2552.o
obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o
obj-$(CONFIG_SND_SOC_TAS571X) += snd-soc-tas571x.o
obj-$(CONFIG_SND_SOC_TAS5720) += snd-soc-tas5720.o
+obj-$(CONFIG_SND_SOC_TDM) += snd-soc-tdm.o
obj-$(CONFIG_SND_SOC_TFA9879) += snd-soc-tfa9879.o
obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o
obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o
diff --git a/sound/soc/codecs/spdif_transmitter.c b/sound/soc/codecs/spdif_transmitter.c
index ee36753..b682f12 100644
--- a/sound/soc/codecs/spdif_transmitter.c
+++ b/sound/soc/codecs/spdif_transmitter.c
@@ -27,7 +27,9 @@
#define STUB_RATES SNDRV_PCM_RATE_8000_192000
#define STUB_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
SNDRV_PCM_FMTBIT_S20_3LE | \
- SNDRV_PCM_FMTBIT_S24_LE)
+ SNDRV_PCM_FMTBIT_S24_3LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
+ SNDRV_PCM_FMTBIT_S32_LE)
static const struct snd_soc_dapm_widget dit_widgets[] = {
SND_SOC_DAPM_OUTPUT("spdif-out"),
diff --git b/sound/soc/codecs/tdm.c b/sound/soc/codecs/tdm.c
new file mode 100644
index 0000000..b8fb3b8
--- /dev/null
+++ b/sound/soc/codecs/tdm.c
@@ -0,0 +1,112 @@
+/*
+ * ALSA SoC generic TDM codec driver
+ *
+ * Author: Matthijs van Duin <matthijsvanduin@gmail.com>
+ * Copyright: (C) 2016 Dutch & Dutch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * TODO Allow customization via device tree.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/slab.h>
+#include <sound/soc.h>
+#include <sound/pcm.h>
+#include <sound/initval.h>
+#include <linux/of.h>
+
+#define DRV_NAME "tdm-audio"
+
+/* As far as I can tell the LE/3LE/BE/3BE suffix merely indicates how the data
+ * was represented in memory, so why would the codec care? On the other hand,
+ * how do you indicate the bit-endianness on wire? */
+
+#define TDM_FORMATS (SNDRV_PCM_FMTBIT_S8 | \
+ SNDRV_PCM_FMTBIT_U8 | \
+ SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_U16_LE | \
+ SNDRV_PCM_FMTBIT_S20_3LE | \
+ SNDRV_PCM_FMTBIT_U20_3LE | \
+ SNDRV_PCM_FMTBIT_S24_3LE | \
+ SNDRV_PCM_FMTBIT_U24_3LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
+ SNDRV_PCM_FMTBIT_U24_LE | \
+ SNDRV_PCM_FMTBIT_S32_LE | \
+ SNDRV_PCM_FMTBIT_U32_LE)
+
+static const struct snd_soc_dapm_widget tdm_audio_widgets[] = {
+ SND_SOC_DAPM_OUTPUT("Sink"),
+ SND_SOC_DAPM_INPUT("Source"),
+};
+
+static const struct snd_soc_dapm_route tdm_audio_routes[] = {
+ { "Sink", NULL, "Playback" },
+ { "Capture", NULL, "Source" },
+};
+
+static struct snd_soc_codec_driver soc_codec_tdm_audio = {
+ .component_driver = {
+ .dapm_widgets = tdm_audio_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(tdm_audio_widgets),
+ .dapm_routes = tdm_audio_routes,
+ .num_dapm_routes = ARRAY_SIZE(tdm_audio_routes),
+ },
+};
+
+static struct snd_soc_dai_driver tdm_audio_dai = {
+ .name = "tdm_audio",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 16,
+ .rates = SNDRV_PCM_RATE_CONTINUOUS,
+ .formats = TDM_FORMATS,
+ },
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 16,
+ .rates = SNDRV_PCM_RATE_CONTINUOUS,
+ .formats = TDM_FORMATS,
+ },
+};
+
+static int tdm_audio_probe(struct platform_device *pdev)
+{
+ return snd_soc_register_codec(&pdev->dev, &soc_codec_tdm_audio,
+ &tdm_audio_dai, 1);
+}
+
+static int tdm_audio_remove(struct platform_device *pdev)
+{
+ snd_soc_unregister_codec(&pdev->dev);
+ return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id tdm_audio_dt_ids[] = {
+ { .compatible = "linux,tdm-audio", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, tdm_audio_dt_ids);
+#endif
+
+static struct platform_driver tdm_audio_driver = {
+ .probe = tdm_audio_probe,
+ .remove = tdm_audio_remove,
+ .driver = {
+ .name = DRV_NAME,
+ .of_match_table = of_match_ptr(tdm_audio_dt_ids),
+ },
+};
+
+module_platform_driver(tdm_audio_driver);
+
+MODULE_AUTHOR("Matthijs van Duin <matthijs@dutchdutch.com>");
+MODULE_DESCRIPTION("Generic TDM codec driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
index 3c5a980..35e441c 100644
--- a/sound/soc/davinci/davinci-mcasp.c
+++ b/sound/soc/davinci/davinci-mcasp.c
@@ -151,6 +151,8 @@ static void mcasp_set_ctl_reg(struct davinci_mcasp *mcasp, u32 ctl_reg, u32 val)
mcasp_set_bits(mcasp, ctl_reg, val);
/* programming GBLCTL needs to read back from GBLCTL and verfiy */
+ ctl_reg = DAVINCI_MCASP_GBLCTL_REG;
+
/* loop count is to avoid the lock-up */
for (i = 0; i < 1000; i++) {
if ((mcasp_get_reg(mcasp, ctl_reg) & val) == val)
@@ -572,6 +574,12 @@ static int __davinci_mcasp_set_clkdiv(struct davinci_mcasp *mcasp, int div_id,
* tdm_slot width by dividing the the ratio by the
* number of configured tdm slots.
*/
+ if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE) {
+ if (div != 128)
+ dev_warn(mcasp->dev,
+ "%s(): BCLK/LRCLK %d requested, must be 128 for DIT mode", __func__, div);
+ break;
+ }
mcasp->slot_width = div / mcasp->tdm_slots;
if (div % mcasp->tdm_slots)
dev_warn(mcasp->dev,
@@ -696,56 +704,59 @@ static int davinci_mcasp_set_tdm_slot(struct snd_soc_dai *dai,
}
static int davinci_config_channel_size(struct davinci_mcasp *mcasp,
- int sample_width)
+ u32 sample_width)
{
- u32 fmt;
- u32 tx_rotate = (sample_width / 4) & 0x7;
- u32 mask = (1ULL << sample_width) - 1;
- u32 slot_width = sample_width;
+ u32 mask, tx_rotate, rx_rotate;
+ u32 slot_width, fmt;
/*
- * For captured data we should not rotate, inversion and masking is
- * enoguh to get the data to the right position:
- * Format data from bus after reverse (XRBUF)
- * S16_LE: |LSB|MSB|xxx|xxx| |xxx|xxx|MSB|LSB|
- * S24_3LE: |LSB|DAT|MSB|xxx| |xxx|MSB|DAT|LSB|
- * S24_LE: |LSB|DAT|MSB|xxx| |xxx|MSB|DAT|LSB|
- * S32_LE: |LSB|DAT|DAT|MSB| |MSB|DAT|DAT|LSB|
+ * Sample data is always right-justified. Apply mask and rotate right
+ * to left-justified. For receive the steps are in reverse order (but
+ * still rotates right).
*/
- u32 rx_rotate = 0;
+ mask = GENMASK(sample_width, 0);
+ mcasp_set_reg(mcasp, DAVINCI_MCASP_TXMASK_REG, mask);
+ mcasp_set_reg(mcasp, DAVINCI_MCASP_RXMASK_REG, mask);
+
+ tx_rotate = sample_width;
+ rx_rotate = -sample_width;
/*
- * Setting the tdm slot width either with set_clkdiv() or
- * set_tdm_slot() allows us to for example send 32 bits per
- * channel to the codec, while only 16 of them carry audio
- * payload.
+ * For big-endian formats (everything except DIT), McASP needs the slot
+ * data to be left-aligned for transmit, whereas received slot data is
+ * delivered right-aligned:
+ *
+ * +-----------------------------------------------+---------------+
+ * <--shift-out- slot data | |
+ * +-----------------------------------------------+---------------+
+ *
+ * +---------------+-----------------------------------------------+
+ * | | slot data <--shift-in--
+ * +---------------+-----------------------------------------------+
+ *
+ * For little-endian formats (DIT only) the reverse is true.
*/
- if (mcasp->slot_width) {
- /*
- * When we have more bclk then it is needed for the
- * data, we need to use the rotation to move the
- * received samples to have correct alignment.
- */
- slot_width = mcasp->slot_width;
- rx_rotate = (slot_width - sample_width) / 4;
+ if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE) {
+ tx_rotate -= 24;
+ slot_width = 32;
+ fmt = 0; /* little endian */
+ } else {
+ slot_width = mcasp->slot_width ?: sample_width;
+ rx_rotate += slot_width;
+ fmt = TXORD; /* big endian */
}
/* mapping of the XSSZ bit-field as described in the datasheet */
- fmt = (slot_width >> 1) - 1;
+ fmt |= TXSSZ((slot_width >> 1) - 1);
- if (mcasp->op_mode != DAVINCI_MCASP_DIT_MODE) {
- mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, RXSSZ(fmt),
- RXSSZ(0x0F));
- mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXSSZ(fmt),
- TXSSZ(0x0F));
- mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXROT(tx_rotate),
- TXROT(7));
- mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, RXROT(rx_rotate),
- RXROT(7));
- mcasp_set_reg(mcasp, DAVINCI_MCASP_RXMASK_REG, mask);
- }
+ tx_rotate = TXROT((tx_rotate & 31) >> 2);
+ rx_rotate = TXROT((rx_rotate & 31) >> 2);
- mcasp_set_reg(mcasp, DAVINCI_MCASP_TXMASK_REG, mask);
+ if (!mcasp->dat_port)
+ fmt |= TXSEL;
+
+ mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, fmt | tx_rotate, 0xffff);
+ mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, fmt | rx_rotate, 0xffff);
return 0;
}
@@ -866,7 +877,6 @@ static int mcasp_i2s_hw_param(struct davinci_mcasp *mcasp, int stream,
int total_slots;
int active_serializers;
u32 mask = 0;
- u32 busel = 0;
total_slots = mcasp->tdm_slots;
@@ -902,17 +912,12 @@ static int mcasp_i2s_hw_param(struct davinci_mcasp *mcasp, int stream,
}
mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, TX_ASYNC);
- if (!mcasp->dat_port)
- busel = TXSEL;
-
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
mcasp_set_reg(mcasp, DAVINCI_MCASP_TXTDM_REG, mask);
- mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, busel | TXORD);
mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG,
FSXMOD(total_slots), FSXMOD(0x1FF));
} else if (stream == SNDRV_PCM_STREAM_CAPTURE) {
mcasp_set_reg(mcasp, DAVINCI_MCASP_RXTDM_REG, mask);
- mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, busel | RXORD);
mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG,
FSRMOD(total_slots), FSRMOD(0x1FF));
/*
@@ -935,23 +940,13 @@ static int mcasp_dit_hw_param(struct davinci_mcasp *mcasp,
u32 cs_value = 0;
u8 *cs_bytes = (u8*) &cs_value;
- /* Set the TX format : 24 bit right rotation, 32 bit slot, Pad 0
- and LSB first */
- mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXROT(6) | TXSSZ(15));
-
/* Set TX frame synch : DIT Mode, 1 bit width, internal, rising edge */
mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG, AFSXE | FSXMOD(0x180));
/* Set the TX tdm : for all the slots */
mcasp_set_reg(mcasp, DAVINCI_MCASP_TXTDM_REG, 0xFFFFFFFF);
- /* Set the TX clock controls : div = 1 and internal */
- mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE | TX_ASYNC);
-
- mcasp_clr_bits(mcasp, DAVINCI_MCASP_XEVTCTL_REG, TXDATADMADIS);
-
- /* Only 44100 and 48000 are valid, both have the same setting */
- mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXDIV(3));
+ mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, TX_ASYNC);
/* Enable the DIT */
mcasp_set_bits(mcasp, DAVINCI_MCASP_TXDITCTL_REG, DITEN);
@@ -1049,6 +1044,15 @@ static int davinci_mcasp_calc_clk_div(struct davinci_mcasp *mcasp,
return error_ppm;
}
+static uint mcasp_clocks_per_slot(struct davinci_mcasp *mcasp, uint width)
+{
+ if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE)
+ return 64;
+ if (mcasp->slot_width)
+ return mcasp->slot_width;
+ return width;
+}
+
static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *cpu_dai)
@@ -1068,12 +1072,9 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
* the machine driver, we need to calculate the ratio.
*/
if (mcasp->bclk_master && mcasp->bclk_div == 0 && mcasp->sysclk_freq) {
- int slots = mcasp->tdm_slots;
- int rate = params_rate(params);
- int sbits = params_width(params);
-
- if (mcasp->slot_width)
- sbits = mcasp->slot_width;
+ uint slots = mcasp->tdm_slots;
+ uint rate = params_rate(params);
+ uint sbits = mcasp_clocks_per_slot(mcasp, params_width(params));
davinci_mcasp_calc_clk_div(mcasp, rate * sbits * slots, true);
}
@@ -1103,11 +1104,13 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
word_length = 16;
break;
- case SNDRV_PCM_FORMAT_U24_3LE:
- case SNDRV_PCM_FORMAT_S24_3LE:
- word_length = 24;
+ case SNDRV_PCM_FORMAT_U20_3LE:
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ word_length = 20;
break;
+ case SNDRV_PCM_FORMAT_U24_3LE:
+ case SNDRV_PCM_FORMAT_S24_3LE:
case SNDRV_PCM_FORMAT_U24_LE:
case SNDRV_PCM_FORMAT_S24_LE:
word_length = 24;
@@ -1169,14 +1172,11 @@ static int davinci_mcasp_hw_rule_rate(struct snd_pcm_hw_params *params,
struct davinci_mcasp_ruledata *rd = rule->private;
struct snd_interval *ri =
hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
- int sbits = params_width(params);
- int slots = rd->mcasp->tdm_slots;
+ uint sbits = mcasp_clocks_per_slot(rd->mcasp, params_width(params));
+ uint slots = rd->mcasp->tdm_slots;
struct snd_interval range;
int i;
- if (rd->mcasp->slot_width)
- sbits = rd->mcasp->slot_width;
-
snd_interval_any(&range);
range.empty = 1;
@@ -1223,8 +1223,7 @@ static int davinci_mcasp_hw_rule_format(struct snd_pcm_hw_params *params,
uint sbits = snd_pcm_format_width(i);
int ppm;
- if (rd->mcasp->slot_width)
- sbits = rd->mcasp->slot_width;
+ sbits = mcasp_clocks_per_slot(rd->mcasp, sbits);
ppm = davinci_mcasp_calc_clk_div(rd->mcasp,
sbits * slots * rate,
@@ -1834,7 +1833,9 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
mcasp->op_mode = pdata->op_mode;
/* sanity check for tdm slots parameter */
- if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE) {
+ if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE) {
+ mcasp->tdm_slots = 2;
+ } else {
if (pdata->tdm_slots < 2) {
dev_err(&pdev->dev, "invalid tdm slots: %d\n",
pdata->tdm_slots);
diff --git a/sound/soc/davinci/davinci-mcasp.h b/sound/soc/davinci/davinci-mcasp.h
index afddc80..ecc33cb 100644
--- a/sound/soc/davinci/davinci-mcasp.h
+++ b/sound/soc/davinci/davinci-mcasp.h
@@ -82,12 +82,12 @@
/* Serializer n Control Register */
#define DAVINCI_MCASP_XRSRCTL_BASE_REG 0x180
#define DAVINCI_MCASP_XRSRCTL_REG(n) (DAVINCI_MCASP_XRSRCTL_BASE_REG + \
- (n << 2))
+ ((n) << 2))
/* Transmit Buffer for Serializer n */
-#define DAVINCI_MCASP_TXBUF_REG(n) (0x200 + (n << 2))
+#define DAVINCI_MCASP_TXBUF_REG(n) (0x200 + ((n) << 2))
/* Receive Buffer for Serializer n */
-#define DAVINCI_MCASP_RXBUF_REG(n) (0x280 + (n << 2))
+#define DAVINCI_MCASP_RXBUF_REG(n) (0x280 + ((n) << 2))
/* McASP FIFO Registers */
#define DAVINCI_MCASP_V2_AFIFO_BASE (0x1010)
@@ -109,7 +109,7 @@
/*
* DAVINCI_MCASP_PFUNC_REG - Pin Function / GPIO Enable Register Bits
*/
-#define AXR(n) (1<<n)
+#define AXR(n) (1<<(n))
#define PFUNC_AMUTE BIT(25)
#define ACLKX BIT(26)
#define AHCLKX BIT(27)
@@ -121,7 +121,7 @@
/*
* DAVINCI_MCASP_PDIR_REG - Pin Direction Register Bits
*/
-#define AXR(n) (1<<n)
+#define AXR(n) (1<<(n))
#define PDIR_AMUTE BIT(25)
#define ACLKX BIT(26)
#define AHCLKX BIT(27)
@@ -142,22 +142,22 @@
*/
#define TXROT(val) (val)
#define TXSEL BIT(3)
-#define TXSSZ(val) (val<<4)
-#define TXPBIT(val) (val<<8)
-#define TXPAD(val) (val<<13)
+#define TXSSZ(val) ((val)<<4)
+#define TXPBIT(val) ((val)<<8)
+#define TXPAD(val) ((val)<<13)
#define TXORD BIT(15)
-#define FSXDLY(val) (val<<16)
+#define FSXDLY(val) ((val)<<16)
/*
* DAVINCI_MCASP_RXFMT_REG - Receive Bitstream Format Register Bits
*/
#define RXROT(val) (val)
#define RXSEL BIT(3)
-#define RXSSZ(val) (val<<4)
-#define RXPBIT(val) (val<<8)
-#define RXPAD(val) (val<<13)
+#define RXSSZ(val) ((val)<<4)
+#define RXPBIT(val) ((val)<<8)
+#define RXPAD(val) ((val)<<13)
#define RXORD BIT(15)
-#define FSRDLY(val) (val<<16)
+#define FSRDLY(val) ((val)<<16)
/*
* DAVINCI_MCASP_TXFMCTL_REG - Transmit Frame Control Register Bits
@@ -165,7 +165,7 @@
#define FSXPOL BIT(0)
#define AFSXE BIT(1)
#define FSXDUR BIT(4)
-#define FSXMOD(val) (val<<7)
+#define FSXMOD(val) ((val)<<7)
/*
* DAVINCI_MCASP_RXFMCTL_REG - Receive Frame Control Register Bits
@@ -173,7 +173,7 @@
#define FSRPOL BIT(0)
#define AFSRE BIT(1)
#define FSRDUR BIT(4)
-#define FSRMOD(val) (val<<7)
+#define FSRMOD(val) ((val)<<7)
/*
* DAVINCI_MCASP_ACLKXCTL_REG - Transmit Clock Control Register Bits
@@ -229,17 +229,17 @@
*/
#define LBEN BIT(0)
#define LBORD BIT(1)
-#define LBGENMODE(val) (val<<2)
+#define LBGENMODE(val) ((val)<<2)
/*
* DAVINCI_MCASP_TXTDMSLOT_REG - Transmit TDM Slot Register configuration
*/
-#define TXTDMS(n) (1<<n)
+#define TXTDMS(n) (1<<(n))
/*
* DAVINCI_MCASP_RXTDMSLOT_REG - Receive TDM Slot Register configuration
*/
-#define RXTDMS(n) (1<<n)
+#define RXTDMS(n) (1<<(n))
/*
* DAVINCI_MCASP_GBLCTL_REG - Global Control Register Bits