Merge "power: qpnp-bms: Avoid deadlock in reset_vbat_monitoring"
diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
index fbe2d25..e3a6721 100644
--- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
@@ -135,6 +135,21 @@
qcom,usb2-power-budget = <500>;
};
+MSM HSUSB controller
+
+Required properties :
+- compatible : should be "qcom,ci13xxx_msm"
+
+Optional properties :
+- qcom,itc-level: value of 2^itc-level will be used for as the interrupt threshold
+ (ITC), when itc-level is between 0 to 6.
+
+Example MSM HSUSB controller device node :
+ msm_hsusb: qcom,ci13xxx_msm {
+ compatible = "qcom,ci13xxx_msm";
+ qcom,itc-level = <4>;
+};
+
ANDROID USB:
Required properties:
diff --git a/arch/arm/boot/dts/apq8084.dtsi b/arch/arm/boot/dts/apq8084.dtsi
index b39f569..e5f083a 100644
--- a/arch/arm/boot/dts/apq8084.dtsi
+++ b/arch/arm/boot/dts/apq8084.dtsi
@@ -190,6 +190,18 @@
compatible = "qcom,android-usb";
};
+ tsens: tsens@fc4a8000 {
+ compatible = "qcom,msm-tsens";
+ reg = <0xfc4a8000 0x2000>,
+ <0xfc4b8000 0x1000>;
+ reg-names = "tsens_physical", "tsens_eeprom_physical";
+ interrupts = <0 184 0>;
+ qcom,sensors = <11>;
+ qcom,slope = <3200 3200 3200 3200 3200 3200 3200 3200 3200
+ 3200 3200>;
+ qcom,calib-mode = "fuse_map1";
+ };
+
qcom,ocmem@fdd00000 {
compatible = "qcom,msm-ocmem";
reg = <0xfdd00000 0x2000>,
@@ -274,3 +286,67 @@
/include/ "msm-pma8084.dtsi"
/include/ "apq8084-regulator.dtsi"
+
+&pma8084_vadc {
+ chan@b0 {
+ label = "apq_therm";
+ reg = <0xb0>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@b3 {
+ label = "quiet_therm";
+ reg = <0xb3>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ };
+};
+
+&pma8084_adc_tm {
+ chan@8 {
+ label = "die_temp";
+ reg = <8>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <3>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <3>;
+ qcom,btm-channel-number = <0x48>;
+ };
+
+ chan@b0 {
+ label = "apq_therm";
+ reg = <0xb0>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <3>;
+ qcom,btm-channel-number = <0x68>;
+ qcom,thermal-node;
+ };
+
+ chan@b3 {
+ label = "quiet_therm";
+ reg = <0xb3>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <3>;
+ qcom,btm-channel-number = <0x70>;
+ qcom,thermal-node;
+ };
+};
diff --git a/arch/arm/boot/dts/msm-pm8110.dtsi b/arch/arm/boot/dts/msm-pm8110.dtsi
index 1877f40..0e446e2 100644
--- a/arch/arm/boot/dts/msm-pm8110.dtsi
+++ b/arch/arm/boot/dts/msm-pm8110.dtsi
@@ -22,6 +22,11 @@
#address-cells = <1>;
#size-cells = <1>;
+ qcom,revid@100 {
+ compatible = "qcom,qpnp-revid";
+ reg = <0x100 0x100>;
+ };
+
qcom,power-on@800 {
compatible = "qcom,qpnp-power-on";
reg = <0x800 0x100>;
diff --git a/arch/arm/boot/dts/msm-pm8226.dtsi b/arch/arm/boot/dts/msm-pm8226.dtsi
index d429f72..2008e1e 100644
--- a/arch/arm/boot/dts/msm-pm8226.dtsi
+++ b/arch/arm/boot/dts/msm-pm8226.dtsi
@@ -22,6 +22,11 @@
#address-cells = <1>;
#size-cells = <1>;
+ qcom,revid@100 {
+ compatible = "qcom,qpnp-revid";
+ reg = <0x100 0x100>;
+ };
+
qcom,power-on@800 {
compatible = "qcom,qpnp-power-on";
reg = <0x800 0x100>;
diff --git a/arch/arm/boot/dts/msm-pma8084.dtsi b/arch/arm/boot/dts/msm-pma8084.dtsi
index 30525aa..42c48f8 100644
--- a/arch/arm/boot/dts/msm-pma8084.dtsi
+++ b/arch/arm/boot/dts/msm-pma8084.dtsi
@@ -191,6 +191,76 @@
qcom,pin-num = <8>;
};
};
+
+ pma8084_vadc: vadc@3100 {
+ compatible = "qcom,qpnp-vadc";
+ reg = <0x3100 0x100>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <0x0 0x31 0x0>;
+ interrupt-names = "eoc-int-en-set";
+ qcom,adc-bit-resolution = <15>;
+ qcom,adc-vdd-reference = <1800>;
+
+ chan@8 {
+ label = "die_temp";
+ reg = <8>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <3>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@9 {
+ label = "ref_625mv";
+ reg = <9>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@a {
+ label = "ref_1250v";
+ reg = <0xa>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@c {
+ label = "ref_buf_625mv";
+ reg = <0xc>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+ };
+
+ pma8084_adc_tm: vadc@3400 {
+ compatible = "qcom,qpnp-adc-tm";
+ reg = <0x3400 0x100>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <0x0 0x34 0x0>,
+ <0x0 0x34 0x3>,
+ <0x0 0x34 0x4>;
+ interrupt-names = "eoc-int-en-set",
+ "high-thr-en-set",
+ "low-thr-en-set";
+ qcom,adc-bit-resolution = <15>;
+ qcom,adc-vdd-reference = <1800>;
+ };
};
qcom,pma8084@1 {
diff --git a/arch/arm/boot/dts/msm8226-cdp.dtsi b/arch/arm/boot/dts/msm8226-cdp.dtsi
index da9ad8c..2f3fae2 100644
--- a/arch/arm/boot/dts/msm8226-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8226-cdp.dtsi
@@ -167,8 +167,6 @@
qcom,vdd-current-level = <9000 800000>;
vdd-io-supply = <&pm8226_l21>;
- qcom,vdd-io-always-on;
- qcom,vdd-io-lpm-sup;
qcom,vdd-io-voltage-level = <1800000 2950000>;
qcom,vdd-io-current-level = <6 22000>;
@@ -204,8 +202,6 @@
qcom,vdd-current-level = <9000 800000>;
vdd-io-supply = <&pm8226_l21>;
- qcom,vdd-io-always-on;
- qcom,vdd-io-lpm-sup;
qcom,vdd-io-voltage-level = <1800000 2950000>;
qcom,vdd-io-current-level = <6 22000>;
diff --git a/arch/arm/boot/dts/msm8226-mtp.dtsi b/arch/arm/boot/dts/msm8226-mtp.dtsi
index bcd1c41..acab5e4 100644
--- a/arch/arm/boot/dts/msm8226-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8226-mtp.dtsi
@@ -173,8 +173,6 @@
qcom,vdd-current-level = <9000 800000>;
vdd-io-supply = <&pm8226_l21>;
- qcom,vdd-io-always-on;
- qcom,vdd-io-lpm-sup;
qcom,vdd-io-voltage-level = <1800000 2950000>;
qcom,vdd-io-current-level = <6 22000>;
@@ -207,8 +205,6 @@
qcom,vdd-current-level = <9000 800000>;
vdd-io-supply = <&pm8226_l21>;
- qcom,vdd-io-always-on;
- qcom,vdd-io-lpm-sup;
qcom,vdd-io-voltage-level = <1800000 2950000>;
qcom,vdd-io-current-level = <6 22000>;
diff --git a/arch/arm/boot/dts/msm8226-qrd.dtsi b/arch/arm/boot/dts/msm8226-qrd.dtsi
index fc9d9f9..7018c6a 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8226-qrd.dtsi
@@ -159,8 +159,6 @@
qcom,vdd-current-level = <9000 800000>;
vdd-io-supply = <&pm8226_l21>;
- qcom,vdd-io-always-on;
- qcom,vdd-io-lpm-sup;
qcom,vdd-io-voltage-level = <1800000 2950000>;
qcom,vdd-io-current-level = <6 22000>;
@@ -196,8 +194,6 @@
qcom,vdd-current-level = <9000 800000>;
vdd-io-supply = <&pm8226_l21>;
- qcom,vdd-io-always-on;
- qcom,vdd-io-lpm-sup;
qcom,vdd-io-voltage-level = <1800000 2950000>;
qcom,vdd-io-current-level = <6 22000>;
diff --git a/arch/arm/boot/dts/msm8610-camera-sensor-cdp-mtp.dtsi b/arch/arm/boot/dts/msm8610-camera-sensor-cdp-mtp.dtsi
index d057260..1b4a594 100644
--- a/arch/arm/boot/dts/msm8610-camera-sensor-cdp-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8610-camera-sensor-cdp-mtp.dtsi
@@ -113,4 +113,42 @@
qcom,cci-master = <0>;
status = "ok";
};
+
+ qcom,camera@78 {
+ compatible = "qcom,sp1628";
+ reg = <0x78>;
+ qcom,slave-id = <0x78 0x0 0x1628>;
+ qcom,csiphy-sd-index = <1>;
+ qcom,csid-sd-index = <1>;
+ qcom,mount-angle = <90>;
+ qcom,sensor-name = "sp1628";
+ cam_vdig-supply = <&pm8110_l2>;
+ cam_vana-supply = <&pm8110_l19>;
+ cam_vio-supply = <&pm8110_l14>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+ qcom,cam-vreg-type = <0 0 0>;
+ qcom,cam-vreg-min-voltage = <1200000 1800000 2850000>;
+ qcom,cam-vreg-max-voltage = <1200000 1800000 2850000>;
+ qcom,cam-vreg-op-mode = <200000 80000 80000>;
+ qcom,gpio-no-mux = <0>;
+ gpios = <&msmgpio 14 0>,
+ <&msmgpio 15 0>,
+ <&msmgpio 8 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-standby = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+ "CAM_RESET",
+ "CAM_STANDBY";
+ qcom,gpio-set-tbl-num = <1 1>;
+ qcom,gpio-set-tbl-flags = <0 2>;
+ qcom,gpio-set-tbl-delay = <1000 4000>;
+ qcom,csi-lane-assign = <0xe4>;
+ qcom,csi-lane-mask = <0x3>;
+ qcom,sensor-position = <1>;
+ qcom,sensor-mode = <1>;
+ qcom,cci-master = <0>;
+ };
+
};
diff --git a/arch/arm/boot/dts/msm8610-cdp.dts b/arch/arm/boot/dts/msm8610-cdp.dts
index bbdc2b8..6891b90 100644
--- a/arch/arm/boot/dts/msm8610-cdp.dts
+++ b/arch/arm/boot/dts/msm8610-cdp.dts
@@ -51,7 +51,7 @@
/* Object 6, Instance = 0 */
00 00 00 00 00 00
/* Object 38, Instance = 0 */
- 1D 01 00 0C 04 0D 00 00
+ 1D 02 00 0A 06 0D 00 00
/* Object 7, Instance = 0 */
20 08 32
/* Object 8, Instance = 0 */
@@ -59,7 +59,7 @@
/* Object 9, Instance = 0 */
83 00 00 13 0B 00 20 32 01 03
00 32 05 30 0A 05 0A 00 70 03
- FC 01 00 36 2F 2C 00 00 40 00
+ FC 01 00 36 2F D8 00 00 40 00
00 0A 00 00 02
/* Object 18, Instance = 0 */
00 00
diff --git a/arch/arm/boot/dts/msm8610-mdss.dtsi b/arch/arm/boot/dts/msm8610-mdss.dtsi
index af0e3e4..d0fc1dc 100644
--- a/arch/arm/boot/dts/msm8610-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8610-mdss.dtsi
@@ -20,8 +20,6 @@
mdss_fb0: qcom,mdss_fb_primary {
cell-index = <0>;
compatible = "qcom,mdss-fb";
- qcom,memory-reservation-type = "EBI1";
- qcom,memory-reservation-size = <0x300000>;
};
};
diff --git a/arch/arm/boot/dts/msm8610-mtp.dts b/arch/arm/boot/dts/msm8610-mtp.dts
index 9406a09..ddbe3a0 100644
--- a/arch/arm/boot/dts/msm8610-mtp.dts
+++ b/arch/arm/boot/dts/msm8610-mtp.dts
@@ -51,7 +51,7 @@
/* Object 6, Instance = 0 */
00 00 00 00 00 00
/* Object 38, Instance = 0 */
- 1D 01 00 0C 04 0D 00 00
+ 1D 02 00 0A 06 0D 00 00
/* Object 7, Instance = 0 */
20 08 32
/* Object 8, Instance = 0 */
@@ -59,7 +59,7 @@
/* Object 9, Instance = 0 */
83 00 00 13 0B 00 20 32 01 03
00 32 05 30 0A 05 0A 00 70 03
- FC 01 00 36 2F 2C 00 00 40 00
+ FC 01 00 36 2F D8 00 00 40 00
00 0A 00 00 02
/* Object 18, Instance = 0 */
00 00
diff --git a/arch/arm/boot/dts/msm8610-qrd-camera-sensor.dtsi b/arch/arm/boot/dts/msm8610-qrd-camera-sensor.dtsi
new file mode 100644
index 0000000..e3bd631
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-qrd-camera-sensor.dtsi
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ */
+
+&i2c {
+ qcom,camera@7d {
+ compatible = "qcom,hi256";
+ reg = <0x7d>;
+ qcom,slave-id = <0x40 0x04 0xc0>;
+ qcom,csiphy-sd-index = <0>;
+ qcom,csid-sd-index = <0>;
+ qcom,mount-angle = <270>;
+ qcom,sensor-name = "hi256";
+ cam_vdig-supply = <&pm8110_l2>;
+ cam_vana-supply = <&pm8110_l19>;
+ cam_vio-supply = <&pm8110_l14>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+ qcom,cam-vreg-type = <0 0 0>;
+ qcom,cam-vreg-min-voltage = <1200000 1800000 2850000>;
+ qcom,cam-vreg-max-voltage = <1200000 1800000 2850000>;
+ qcom,cam-vreg-op-mode = <200000 8000 80000>;
+ qcom,gpio-no-mux = <0>;
+ gpios = <&msmgpio 13 0>,
+ <&msmgpio 21 0>,
+ <&msmgpio 20 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-standby = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+ "CAM_RESET1",
+ "CAM_STANDBY";
+ qcom,csi-lane-assign = <0xe4>;
+ qcom,csi-lane-mask = <0x03>;
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <1>;
+ qcom,cci-master = <0>;
+ };
+
+
+};
+
diff --git a/arch/arm/boot/dts/msm8610-qrd.dts b/arch/arm/boot/dts/msm8610-qrd.dts
index 5f9365a..22e7aa0 100644
--- a/arch/arm/boot/dts/msm8610-qrd.dts
+++ b/arch/arm/boot/dts/msm8610-qrd.dts
@@ -14,6 +14,7 @@
/include/ "msm8610.dtsi"
/include/ "dsi-v2-panel-hx8379a-wvga-video.dtsi"
+/include/ "msm8610-qrd-camera-sensor.dtsi"
/ {
model = "Qualcomm MSM 8610 QRD";
@@ -157,6 +158,7 @@
qcom,id = <6>;
qcom,source-sel = <1>;
qcom,mode-ctrl = <0x61>;
+ qcom,mode = "manual";
};
};
@@ -171,6 +173,7 @@
qcom,id = <6>;
qcom,source-sel = <1>;
qcom,mode-ctrl = <0x10>;
+ qcom,mode = "manual";
};
};
};
@@ -265,3 +268,33 @@
status = "ok";
};
};
+
+&pm8110_gpios {
+ gpio@c000 { /* GPIO 1 */
+ };
+
+ gpio@c100 { /* GPIO 2 */
+ };
+
+ gpio@c200 { /* GPIO 3 */
+ };
+
+ gpio@c300 { /* GPIO 4 */
+ };
+};
+
+&pm8110_mpps {
+ mpp@a000 { /* MPP 1 */
+ };
+
+ mpp@a100 { /* MPP 2 */
+ status = "disabled";
+ };
+
+ mpp@a200 { /* MPP 3 */
+ status = "disabled";
+ };
+
+ mpp@a300 { /* MPP 4 */
+ };
+};
diff --git a/arch/arm/boot/dts/msm8974-fluid.dtsi b/arch/arm/boot/dts/msm8974-fluid.dtsi
index a822af5..3d2308d 100644
--- a/arch/arm/boot/dts/msm8974-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-fluid.dtsi
@@ -403,6 +403,10 @@
};
&pm8941_bms {
+ qcom,enable-fcc-learning;
+ qcom,min-fcc-learning-soc = <20>;
+ qcom,min-fcc-ocv-pc = <30>;
+ qcom,min-fcc-learning-samples = <5>;
status = "ok";
};
diff --git a/arch/arm/boot/dts/msm8974-mtp.dtsi b/arch/arm/boot/dts/msm8974-mtp.dtsi
index e798fc0..28111fa 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-mtp.dtsi
@@ -352,6 +352,10 @@
};
&pm8941_bms {
+ qcom,enable-fcc-learning;
+ qcom,min-fcc-learning-soc = <20>;
+ qcom,min-fcc-ocv-pc = <30>;
+ qcom,min-fcc-learning-samples = <5>;
status = "ok";
};
diff --git a/arch/arm/boot/dts/msm8974-regulator.dtsi b/arch/arm/boot/dts/msm8974-regulator.dtsi
index 2114686..7c191fc 100644
--- a/arch/arm/boot/dts/msm8974-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8974-regulator.dtsi
@@ -380,7 +380,7 @@
status = "okay";
pm8941_l19: regulator-l19 {
regulator-min-microvolt = <2900000>;
- regulator-max-microvolt = <2900000>;
+ regulator-max-microvolt = <3300000>;
qcom,init-voltage = <2900000>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index d617c27..f184a00 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -175,6 +175,11 @@
<87 512 40000 640000>;
};
+ msm_hsusb: qcom,ci13xxx_msm {
+ compatible = "qcom,ci13xxx_msm";
+ qcom,itc-level = <4>;
+ };
+
hsic_host: hsic@f9a15000 {
compatible = "qcom,hsic-host";
reg = <0xf9a15000 0x400>;
diff --git a/arch/arm/boot/dts/msmkrypton-sim.dts b/arch/arm/boot/dts/msmkrypton-sim.dts
index 1872a36..29f0df4 100644
--- a/arch/arm/boot/dts/msmkrypton-sim.dts
+++ b/arch/arm/boot/dts/msmkrypton-sim.dts
@@ -23,3 +23,13 @@
&uartdm3{
status = "ok";
};
+
+&spi_6 {
+ ethernet-switch@0 {
+ compatible = "simtec,ks8851";
+ reg = <0>;
+ interrupt-parent = <&msmgpio>;
+ spi-max-frequency = <19200000>;
+ interrupts = <75 0>;
+ };
+};
diff --git a/arch/arm/boot/dts/msmkrypton.dtsi b/arch/arm/boot/dts/msmkrypton.dtsi
index 4b032d8..7bbd528 100644
--- a/arch/arm/boot/dts/msmkrypton.dtsi
+++ b/arch/arm/boot/dts/msmkrypton.dtsi
@@ -117,4 +117,19 @@
interrupts = <0 109 0>;
status = "disabled";
};
+
+ spi_6: spi@f9928000 { /* BLSP1 QUP6 */
+ cell-index = <0>;
+ compatible = "qcom,spi-qup-v2";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0xf9928000 0x1000>;
+ interrupts = <0 100 0>;
+ spi-max-frequency = <19200000>;
+
+ gpios = <&msmgpio 23 0>, /* CLK */
+ <&msmgpio 21 0>, /* MISO */
+ <&msmgpio 20 0>; /* MOSI */
+ cs-gpios = <&msmgpio 22 0>;
+ };
};
diff --git a/arch/arm/configs/msm8226-perf_defconfig b/arch/arm/configs/msm8226-perf_defconfig
index 7420092..a9fc578 100644
--- a/arch/arm/configs/msm8226-perf_defconfig
+++ b/arch/arm/configs/msm8226-perf_defconfig
@@ -205,6 +205,15 @@
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_QSEECOM=y
+CONFIG_SCSI=y
+CONFIG_SCSI_TGT=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
CONFIG_MD=y
CONFIG_BLK_DEV_DM=y
CONFIG_DM_CRYPT=y
@@ -359,6 +368,7 @@
CONFIG_QPNP_PWM=y
CONFIG_QPNP_POWER_ON=y
CONFIG_QPNP_VIBRATOR=y
+CONFIG_QPNP_REVID=y
CONFIG_MSM_IOMMU_V1=y
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
@@ -399,3 +409,5 @@
CONFIG_CRYPTO_DEV_QCRYPTO=m
CONFIG_CRYPTO_DEV_QCE=y
CONFIG_CRYPTO_DEV_QCEDEV=m
+CONFIG_MOBICORE_SUPPORT=m
+CONFIG_MOBICORE_API=m
diff --git a/arch/arm/configs/msm8226_defconfig b/arch/arm/configs/msm8226_defconfig
index 3798987..623d8a3 100644
--- a/arch/arm/configs/msm8226_defconfig
+++ b/arch/arm/configs/msm8226_defconfig
@@ -205,6 +205,15 @@
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_QSEECOM=y
+CONFIG_SCSI=y
+CONFIG_SCSI_TGT=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
CONFIG_MD=y
CONFIG_BLK_DEV_DM=y
CONFIG_DM_CRYPT=y
@@ -384,6 +393,7 @@
CONFIG_QPNP_PWM=y
CONFIG_QPNP_POWER_ON=y
CONFIG_QPNP_VIBRATOR=y
+CONFIG_QPNP_REVID=y
CONFIG_MSM_IOMMU_V1=y
CONFIG_CORESIGHT=y
CONFIG_CORESIGHT_TMC=y
@@ -433,3 +443,5 @@
CONFIG_CRYPTO_DEV_QCRYPTO=m
CONFIG_CRYPTO_DEV_QCE=y
CONFIG_CRYPTO_DEV_QCEDEV=m
+CONFIG_MOBICORE_SUPPORT=m
+CONFIG_MOBICORE_API=m
diff --git a/arch/arm/configs/msm8610-perf_defconfig b/arch/arm/configs/msm8610-perf_defconfig
index fc34d53..2990091 100644
--- a/arch/arm/configs/msm8610-perf_defconfig
+++ b/arch/arm/configs/msm8610-perf_defconfig
@@ -271,6 +271,7 @@
CONFIG_VIDEO_V4L2_SUBDEV_API=y
# CONFIG_MSM_CAMERA is not set
CONFIG_OV8825=y
+CONFIG_HI256=y
CONFIG_MSM_CAMERA_SENSOR=y
CONFIG_MSM_CPP=y
CONFIG_MSM_CCI=y
@@ -280,6 +281,7 @@
CONFIG_MSM_ISPIF=y
CONFIG_MSMB_CAMERA=y
CONFIG_OV9724=y
+CONFIG_SP1628=y
CONFIG_MSMB_JPEG=y
CONFIG_MSM_VIDC_V4L2=y
CONFIG_MSM_WFD=y
@@ -348,6 +350,7 @@
CONFIG_QPNP_PWM=y
CONFIG_QPNP_POWER_ON=y
CONFIG_QPNP_VIBRATOR=y
+CONFIG_QPNP_REVID=y
CONFIG_MSM_IOMMU_V0=y
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index d3c8b77..64f9841 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -269,6 +269,7 @@
CONFIG_VIDEO_V4L2_SUBDEV_API=y
# CONFIG_MSM_CAMERA is not set
CONFIG_OV8825=y
+CONFIG_HI256=y
CONFIG_MSM_CAMERA_SENSOR=y
CONFIG_MSM_CCI=y
CONFIG_MSM_CSI20_HEADER=y
@@ -278,6 +279,7 @@
CONFIG_MSMB_CAMERA=y
CONFIG_MSM_CSI22_HEADER=y
CONFIG_OV9724=y
+CONFIG_SP1628=y
CONFIG_MSMB_JPEG=y
CONFIG_MSM_VIDC_V4L2=y
CONFIG_MSM_WFD=y
@@ -367,6 +369,7 @@
CONFIG_QPNP_PWM=y
CONFIG_QPNP_POWER_ON=y
CONFIG_QPNP_VIBRATOR=y
+CONFIG_QPNP_REVID=y
CONFIG_MSM_IOMMU_V0=y
CONFIG_CORESIGHT=y
CONFIG_CORESIGHT_TMC=y
diff --git a/arch/arm/configs/msmkrypton_defconfig b/arch/arm/configs/msmkrypton_defconfig
index 69bc36e..f073d2b 100644
--- a/arch/arm/configs/msmkrypton_defconfig
+++ b/arch/arm/configs/msmkrypton_defconfig
@@ -65,9 +65,28 @@
CONFIG_MTD_BLOCK=y
# CONFIG_MTD_MSM_NAND is not set
CONFIG_MTD_MSM_QPIC_NAND=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IPV6=y
+# CONFIG_WIRELESS is not set
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
# CONFIG_ANDROID_PMEM is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+CONFIG_KS8851=y
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_MSM_RMNET is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_WLAN is not set
# CONFIG_INPUT_MOUSEDEV is not set
CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_KEYBOARD is not set
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index cf10056..a70b300 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -573,6 +573,8 @@
local_fiq_disable();
local_irq_disable();
+ flush_cache_all();
+
while (1)
cpu_relax();
}
diff --git a/arch/arm/mach-msm/board-8084.c b/arch/arm/mach-msm/board-8084.c
index 67c05ba..7dc9a90 100644
--- a/arch/arm/mach-msm/board-8084.c
+++ b/arch/arm/mach-msm/board-8084.c
@@ -16,6 +16,7 @@
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/memory.h>
+#include <linux/msm_tsens.h>
#include <asm/hardware/gic.h>
#include <asm/mach/map.h>
#include <asm/mach/arch.h>
@@ -86,6 +87,7 @@
msm_init_modem_notifier_list();
msm_smd_init();
msm_clock_init(&msm8084_clock_init_data);
+ tsens_tm_init_driver();
}
static void __init apq8084_map_io(void)
diff --git a/arch/arm/mach-msm/board-krypton-gpiomux.c b/arch/arm/mach-msm/board-krypton-gpiomux.c
index 3d86ba7..ee38e5f 100644
--- a/arch/arm/mach-msm/board-krypton-gpiomux.c
+++ b/arch/arm/mach-msm/board-krypton-gpiomux.c
@@ -17,12 +17,37 @@
#include <mach/gpio.h>
#include <mach/gpiomux.h>
+#define KS8851_IRQ_GPIO 75
+
+#if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
+static struct gpiomux_setting gpio_eth_config = {
+ .pull = GPIOMUX_PULL_UP,
+ .drv = GPIOMUX_DRV_2MA,
+ .func = GPIOMUX_FUNC_GPIO,
+};
+
+static struct msm_gpiomux_config msm_eth_config[] = {
+ {
+ .gpio = KS8851_IRQ_GPIO,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gpio_eth_config,
+ }
+ },
+};
+#endif
+
static struct gpiomux_setting gpio_uart_config = {
.func = GPIOMUX_FUNC_1,
.drv = GPIOMUX_DRV_8MA,
.pull = GPIOMUX_PULL_NONE,
};
+static struct gpiomux_setting gpio_spi_config = {
+ .func = GPIOMUX_FUNC_2,
+ .drv = GPIOMUX_DRV_6MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
static struct msm_gpiomux_config msm_blsp_configs[] __initdata = {
{
.gpio = 8, /* BLSP1 UART TX */
@@ -36,6 +61,30 @@
[GPIOMUX_SUSPENDED] = &gpio_uart_config,
},
},
+ {
+ .gpio = 20, /* BLSP1 QUP6 SPI_DATA_MOSI */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gpio_spi_config,
+ },
+ },
+ {
+ .gpio = 21, /* BLSP1 QUP6 SPI_DATA_MISO */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gpio_spi_config,
+ },
+ },
+ {
+ .gpio = 23, /* BLSP1 QUP6 SPI_CLK */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gpio_spi_config,
+ },
+ },
+ {
+ .gpio = 22, /* BLSP1 QUP6 SPI_CS */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gpio_spi_config,
+ },
+ },
};
void __init msmkrypton_init_gpiomux(void)
@@ -49,4 +98,7 @@
}
msm_gpiomux_install(msm_blsp_configs, ARRAY_SIZE(msm_blsp_configs));
+#if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
+ msm_gpiomux_install(msm_eth_config, ARRAY_SIZE(msm_eth_config));
+#endif
}
diff --git a/arch/arm/mach-msm/board-krypton.c b/arch/arm/mach-msm/board-krypton.c
index ff7c8e0..b40fcfa 100644
--- a/arch/arm/mach-msm/board-krypton.c
+++ b/arch/arm/mach-msm/board-krypton.c
@@ -34,6 +34,9 @@
static struct clk_lookup msm_clocks_dummy[] = {
CLK_DUMMY("core_clk", BLSP1_UART_CLK, "f991f000.serial", OFF),
CLK_DUMMY("iface_clk", BLSP1_UART_CLK, "f991f000.serial", OFF),
+ CLK_DUMMY("core_clk", SPI_CLK, "f9928000.spi", OFF),
+ CLK_DUMMY("iface_clk", SPI_P_CLK, "f9928000.spi", OFF),
+
};
static struct clock_init_data msm_dummy_clock_init_data __initdata = {
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 3aef106..f8b2d0a 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -66,6 +66,15 @@
#define GPLL1_TEST_CTL_REG 0x0058
#define GPLL1_STATUS_REG 0x005C
+#define GPLL4_MODE_REG 0x1DC0
+#define GPLL4_L_REG 0x1DC4
+#define GPLL4_M_REG 0x1DC8
+#define GPLL4_N_REG 0x1DCC
+#define GPLL4_USER_CTL_REG 0x1DD0
+#define GPLL4_CONFIG_CTL_REG 0x1DD4
+#define GPLL4_TEST_CTL_REG 0x1DD8
+#define GPLL4_STATUS_REG 0x1DDC
+
#define MMPLL0_MODE_REG 0x0000
#define MMPLL0_L_REG 0x0004
#define MMPLL0_M_REG 0x0008
@@ -519,6 +528,7 @@
#define cxo_source_val 0
#define gpll0_source_val 1
#define gpll1_source_val 2
+#define gpll4_source_val 5
#define gnd_source_val 5
#define mmpll0_mm_source_val 1
#define mmpll1_mm_source_val 2
@@ -736,6 +746,21 @@
},
};
+static struct pll_vote_clk gpll4_clk_src = {
+ .en_reg = (void __iomem *)APCS_GPLL_ENA_VOTE_REG,
+ .en_mask = BIT(4),
+ .status_reg = (void __iomem *)GPLL4_STATUS_REG,
+ .status_mask = BIT(17),
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .parent = &cxo_clk_src.c,
+ .rate = 800000000,
+ .dbg_name = "gpll4_clk_src",
+ .ops = &clk_ops_pll_vote,
+ CLK_INIT(gpll4_clk_src.c),
+ },
+};
+
static struct pll_vote_clk mmpll0_clk_src = {
.en_reg = (void __iomem *)MMSS_PLL_VOTE_APCS_REG,
.en_mask = BIT(0),
@@ -1373,6 +1398,14 @@
F_END
};
+static struct clk_freq_tbl ftbl_gcc_ce1_v3_clk[] = {
+ F( 50000000, gpll0, 12, 0, 0),
+ F( 75000000, gpll0, 8, 0, 0),
+ F(100000000, gpll0, 6, 0, 0),
+ F(150000000, gpll0, 4, 0, 0),
+ F_END
+};
+
static struct rcg_clk ce1_clk_src = {
.cmd_rcgr_reg = CE1_CMD_RCGR,
.set_rate = set_rate_hid,
@@ -1393,6 +1426,14 @@
F_END
};
+static struct clk_freq_tbl ftbl_gcc_ce2_v3_clk[] = {
+ F( 50000000, gpll0, 12, 0, 0),
+ F( 75000000, gpll0, 8, 0, 0),
+ F(100000000, gpll0, 6, 0, 0),
+ F(150000000, gpll0, 4, 0, 0),
+ F_END
+};
+
static struct rcg_clk ce2_clk_src = {
.cmd_rcgr_reg = CE2_CMD_RCGR,
.set_rate = set_rate_hid,
@@ -1480,7 +1521,7 @@
},
};
-static struct clk_freq_tbl ftbl_gcc_sdcc1_2_apps_clk[] = {
+static struct clk_freq_tbl ftbl_gcc_sdcc1_4_apps_clk[] = {
F( 144000, cxo, 16, 3, 25),
F( 400000, cxo, 12, 1, 4),
F( 20000000, gpll0, 15, 1, 2),
@@ -1488,16 +1529,7 @@
F( 50000000, gpll0, 12, 0, 0),
F(100000000, gpll0, 6, 0, 0),
F(200000000, gpll0, 3, 0, 0),
- F_END
-};
-
-static struct clk_freq_tbl ftbl_gcc_sdcc3_4_apps_clk[] = {
- F( 144000, cxo, 16, 3, 25),
- F( 400000, cxo, 12, 1, 4),
- F( 20000000, gpll0, 15, 1, 2),
- F( 25000000, gpll0, 12, 1, 2),
- F( 50000000, gpll0, 12, 0, 0),
- F(100000000, gpll0, 6, 0, 0),
+ F(400000000, gpll4, 2, 0, 0),
F_END
};
@@ -1510,7 +1542,7 @@
static struct rcg_clk sdcc1_apps_clk_src = {
.cmd_rcgr_reg = SDCC1_APPS_CMD_RCGR,
.set_rate = set_rate_mnd,
- .freq_tbl = ftbl_gcc_sdcc1_2_apps_clk,
+ .freq_tbl = ftbl_gcc_sdcc1_4_apps_clk,
.current_freq = &rcg_dummy_freq,
.base = &virt_bases[GCC_BASE],
.c = {
@@ -1524,7 +1556,7 @@
static struct rcg_clk sdcc2_apps_clk_src = {
.cmd_rcgr_reg = SDCC2_APPS_CMD_RCGR,
.set_rate = set_rate_mnd,
- .freq_tbl = ftbl_gcc_sdcc1_2_apps_clk,
+ .freq_tbl = ftbl_gcc_sdcc1_4_apps_clk,
.current_freq = &rcg_dummy_freq,
.base = &virt_bases[GCC_BASE],
.c = {
@@ -1538,7 +1570,7 @@
static struct rcg_clk sdcc3_apps_clk_src = {
.cmd_rcgr_reg = SDCC3_APPS_CMD_RCGR,
.set_rate = set_rate_mnd,
- .freq_tbl = ftbl_gcc_sdcc3_4_apps_clk,
+ .freq_tbl = ftbl_gcc_sdcc1_4_apps_clk,
.current_freq = &rcg_dummy_freq,
.base = &virt_bases[GCC_BASE],
.c = {
@@ -1552,7 +1584,7 @@
static struct rcg_clk sdcc4_apps_clk_src = {
.cmd_rcgr_reg = SDCC4_APPS_CMD_RCGR,
.set_rate = set_rate_mnd,
- .freq_tbl = ftbl_gcc_sdcc3_4_apps_clk,
+ .freq_tbl = ftbl_gcc_sdcc1_4_apps_clk,
.current_freq = &rcg_dummy_freq,
.base = &virt_bases[GCC_BASE],
.c = {
@@ -2706,6 +2738,7 @@
F_MM(228570000, mmpll0, 3.5, 0, 0),
F_MM(266670000, mmpll0, 3, 0, 0),
F_MM(320000000, mmpll0, 2.5, 0, 0),
+ F_MM(465000000, mmpll3, 2, 0, 0),
F_END
};
@@ -2887,6 +2920,21 @@
F_END
};
+static struct clk_freq_tbl ftbl_camss_mclk0_3_v3_clk[] = {
+ F_MM( 4800000, cxo, 4, 0, 0),
+ F_MM( 6000000, gpll0, 10, 1, 10),
+ F_MM( 8000000, gpll0, 15, 1, 5),
+ F_MM( 9600000, cxo, 2, 0, 0),
+ F_MM(16000000, gpll0, 10, 1, 5),
+ F_MM(19200000, cxo, 1, 0, 0),
+ F_MM(24000000, gpll0, 5, 1, 5),
+ F_MM(32000000, mmpll0, 5, 1, 5),
+ F_MM(48000000, gpll0, 12.5, 0, 0),
+ F_MM(64000000, mmpll0, 12.5, 0, 0),
+ F_MM(66670000, gpll0, 9, 0, 0),
+ F_END
+};
+
static struct rcg_clk mclk0_clk_src = {
.cmd_rcgr_reg = MCLK0_CMD_RCGR,
.set_rate = set_rate_hid,
@@ -2995,6 +3043,7 @@
F_MM(150000000, gpll0, 4, 0, 0),
F_MM(266670000, mmpll0, 3, 0, 0),
F_MM(320000000, mmpll0, 2.5, 0, 0),
+ F_MM(465000000, mmpll3, 2, 0, 0),
F_END
};
@@ -4802,6 +4851,7 @@
CLK_LOOKUP("xo", cxo_pil_pronto_clk.c, "fb21b000.qcom,pronto"),
CLK_LOOKUP("xo", cxo_dwc3_clk.c, "msm_dwc3"),
CLK_LOOKUP("xo", cxo_ehci_host_clk.c, "msm_ehci_host"),
+ CLK_LOOKUP("pll", gpll4_clk_src.c, ""),
CLK_LOOKUP("measure", measure_clk.c, "debug"),
@@ -5538,6 +5588,67 @@
{&gcc_blsp2_qup6_i2c_apps_clk.c, &blsp2_qup6_i2c_apps_clk_src.c,},
};
+/* v1 to v2 clock changes */
+static void __init msm8974_v2_clock_override(void)
+{
+ int i;
+
+ mmpll3_clk_src.c.rate = 930000000;
+ mmpll1_clk_src.c.rate = 1167000000;
+ mmpll1_clk_src.c.fmax[VDD_DIG_NOMINAL] = 1167000000;
+
+ ocmemnoc_clk_src.freq_tbl = ftbl_ocmemnoc_v2_clk;
+ ocmemnoc_clk_src.c.fmax[VDD_DIG_NOMINAL] = 291750000;
+
+ axi_clk_src.freq_tbl = ftbl_mmss_axi_v2_clk;
+ axi_clk_src.c.fmax[VDD_DIG_NOMINAL] = 291750000;
+ axi_clk_src.c.fmax[VDD_DIG_HIGH] = 466800000;
+
+ vcodec0_clk_src.freq_tbl = ftbl_venus0_vcodec0_v2_clk;
+ vcodec0_clk_src.c.fmax[VDD_DIG_HIGH] = 465000000;
+
+ mdp_clk_src.c.fmax[VDD_DIG_NOMINAL] = 240000000;
+
+ /* The parent of each of the QUP I2C clocks is an RCG on V2 */
+ for (i = 0; i < ARRAY_SIZE(qup_i2c_clks); i++)
+ qup_i2c_clks[i][0]->parent = qup_i2c_clks[i][1];
+}
+
+/* v2 to v3 clock changes */
+static void __init msm8974_v3_clock_override(void)
+{
+ ce1_clk_src.c.fmax[VDD_DIG_LOW] = 75000000;
+ ce1_clk_src.c.fmax[VDD_DIG_NOMINAL] = 150000000;
+ ce1_clk_src.freq_tbl = ftbl_gcc_ce1_v3_clk;
+ ce2_clk_src.c.fmax[VDD_DIG_LOW] = 75000000;
+ ce2_clk_src.c.fmax[VDD_DIG_NOMINAL] = 150000000;
+ ce2_clk_src.freq_tbl = ftbl_gcc_ce2_v3_clk;
+
+ sdcc1_apps_clk_src.c.fmax[VDD_DIG_LOW] = 200000000;
+ sdcc1_apps_clk_src.c.fmax[VDD_DIG_NOMINAL] = 400000000;
+
+ vfe0_clk_src.c.fmax[VDD_DIG_LOW] = 150000000;
+ vfe0_clk_src.c.fmax[VDD_DIG_NOMINAL] = 320000000;
+ vfe0_clk_src.c.fmax[VDD_DIG_HIGH] = 465000000;
+ vfe1_clk_src.c.fmax[VDD_DIG_LOW] = 150000000;
+ vfe1_clk_src.c.fmax[VDD_DIG_NOMINAL] = 320000000;
+ vfe1_clk_src.c.fmax[VDD_DIG_HIGH] = 465000000;
+ cpp_clk_src.c.fmax[VDD_DIG_LOW] = 150000000;
+ cpp_clk_src.c.fmax[VDD_DIG_NOMINAL] = 320000000;
+ cpp_clk_src.c.fmax[VDD_DIG_HIGH] = 465000000;
+
+ mdp_clk_src.c.fmax[VDD_DIG_NOMINAL] = 266670000;
+
+ mclk0_clk_src.freq_tbl = ftbl_camss_mclk0_3_v3_clk;
+ mclk1_clk_src.freq_tbl = ftbl_camss_mclk0_3_v3_clk;
+ mclk2_clk_src.freq_tbl = ftbl_camss_mclk0_3_v3_clk;
+ mclk3_clk_src.freq_tbl = ftbl_camss_mclk0_3_v3_clk;
+ mclk0_clk_src.set_rate = set_rate_mnd;
+ mclk1_clk_src.set_rate = set_rate_mnd;
+ mclk2_clk_src.set_rate = set_rate_mnd;
+ mclk3_clk_src.set_rate = set_rate_mnd;
+}
+
static void __init msm8974_clock_pre_init(void)
{
virt_bases[GCC_BASE] = ioremap(GCC_CC_PHYS, GCC_CC_SIZE);
@@ -5566,30 +5677,11 @@
reg_init();
- /* v2 specific changes */
- if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 2) {
- int i;
-
- mmpll3_clk_src.c.rate = 930000000;
- mmpll1_clk_src.c.rate = 1167000000;
- mmpll1_clk_src.c.fmax[VDD_DIG_NOMINAL] = 1167000000;
-
- ocmemnoc_clk_src.freq_tbl = ftbl_ocmemnoc_v2_clk;
- ocmemnoc_clk_src.c.fmax[VDD_DIG_NOMINAL] = 291750000;
-
- axi_clk_src.freq_tbl = ftbl_mmss_axi_v2_clk;
- axi_clk_src.c.fmax[VDD_DIG_NOMINAL] = 291750000;
- axi_clk_src.c.fmax[VDD_DIG_HIGH] = 466800000;
-
- vcodec0_clk_src.freq_tbl = ftbl_venus0_vcodec0_v2_clk;
- vcodec0_clk_src.c.fmax[VDD_DIG_HIGH] = 465000000;
-
- mdp_clk_src.c.fmax[VDD_DIG_NOMINAL] = 240000000;
-
- /* The parent of each of the QUP I2C clocks is an RCG on V2 */
- for (i = 0; i < ARRAY_SIZE(qup_i2c_clks); i++)
- qup_i2c_clks[i][0]->parent = qup_i2c_clks[i][1];
- }
+ /* version specific changes */
+ if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) >= 2)
+ msm8974_v2_clock_override();
+ if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 3)
+ msm8974_v3_clock_override();
clk_ops_pixel_clock = clk_ops_pixel;
clk_ops_pixel_clock.set_rate = set_rate_pixel;
diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h
index 68cfb2e..eeda7ce 100644
--- a/arch/arm/mach-msm/include/mach/iommu.h
+++ b/arch/arm/mach-msm/include/mach/iommu.h
@@ -188,21 +188,31 @@
int attach_count;
};
-struct msm_iommu_context_regs {
- uint32_t far;
- uint32_t par;
- uint32_t fsr;
- uint32_t fsynr0;
- uint32_t fsynr1;
- uint32_t ttbr0;
- uint32_t ttbr1;
- uint32_t sctlr;
- uint32_t actlr;
- uint32_t prrr;
- uint32_t nmrr;
+enum dump_reg {
+ DUMP_REG_FAR0,
+ DUMP_REG_FAR1,
+ DUMP_REG_PAR0,
+ DUMP_REG_PAR1,
+ DUMP_REG_FSR,
+ DUMP_REG_FSYNR0,
+ DUMP_REG_FSYNR1,
+ DUMP_REG_TTBR0,
+ DUMP_REG_TTBR1,
+ DUMP_REG_SCTLR,
+ DUMP_REG_ACTLR,
+ DUMP_REG_PRRR,
+ DUMP_REG_NMRR,
+ MAX_DUMP_REGS,
};
-void print_ctx_regs(struct msm_iommu_context_regs *regs);
+#define COMBINE_DUMP_REG(upper, lower) (((u64) upper << 32) | lower)
+
+struct msm_iommu_context_reg {
+ uint32_t val;
+ bool valid;
+};
+
+void print_ctx_regs(struct msm_iommu_context_reg regs[]);
/*
* Interrupt handler for the IOMMU context fault interrupt. Hooking the
diff --git a/arch/arm/mach-msm/include/mach/qseecomi.h b/arch/arm/mach-msm/include/mach/qseecomi.h
index 3a997be..a4021d4 100644
--- a/arch/arm/mach-msm/include/mach/qseecomi.h
+++ b/arch/arm/mach-msm/include/mach/qseecomi.h
@@ -18,13 +18,13 @@
#define QSEECOM_KEY_ID_SIZE 32
-#define QSEOS_RESULT_FAIL_LOAD_KS -48
-#define QSEOS_RESULT_FAIL_SAVE_KS -49
-#define QSEOS_RESULT_FAIL_MAX_KEYS -50
-#define QSEOS_RESULT_FAIL_KEY_ID_EXISTS -51
-#define QSEOS_RESULT_FAIL_KEY_ID_DNE -52
-#define QSEOS_RESULT_FAIL_KS_OP -53
-#define QSEOS_RESULT_FAIL_CE_PIPE_INVALID -54
+#define QSEOS_RESULT_FAIL_LOAD_KS -57
+#define QSEOS_RESULT_FAIL_SAVE_KS -58
+#define QSEOS_RESULT_FAIL_MAX_KEYS -59
+#define QSEOS_RESULT_FAIL_KEY_ID_EXISTS -60
+#define QSEOS_RESULT_FAIL_KEY_ID_DNE -61
+#define QSEOS_RESULT_FAIL_KS_OP -62
+#define QSEOS_RESULT_FAIL_CE_PIPE_INVALID -63
enum qseecom_command_scm_resp_type {
QSEOS_APP_ID = 0xEE01,
diff --git a/arch/arm/mach-msm/subsystem_restart.c b/arch/arm/mach-msm/subsystem_restart.c
index a5e04cd..7b1a4c3 100644
--- a/arch/arm/mach-msm/subsystem_restart.c
+++ b/arch/arm/mach-msm/subsystem_restart.c
@@ -952,8 +952,8 @@
static irqreturn_t subsys_err_ready_intr_handler(int irq, void *subsys)
{
struct subsys_device *subsys_dev = subsys;
- pr_info("Error ready interrupt occured for %s\n",
- subsys_dev->desc->name);
+ dev_info(subsys_dev->desc->dev,
+ "Subsystem error monitoring/handling services are up\n");
if (subsys_dev->desc->is_not_loadable)
return IRQ_HANDLED;
diff --git a/drivers/gpu/ion/msm/ion_cp_common.c b/drivers/gpu/ion/msm/ion_cp_common.c
index 623a174..d315fc4 100644
--- a/drivers/gpu/ion/msm/ion_cp_common.c
+++ b/drivers/gpu/ion/msm/ion_cp_common.c
@@ -86,6 +86,8 @@
int nchunks;
int ret;
int i;
+ int chunk_list_len;
+ phys_addr_t chunk_list_phys;
if (usage < 0 || usage >= MAX_USAGE)
return -EINVAL;
@@ -97,15 +99,26 @@
}
nchunks = size / V2_CHUNK_SIZE;
+ chunk_list_len = sizeof(unsigned long)*nchunks;
- chunk_list = kmalloc(sizeof(unsigned long)*nchunks, GFP_KERNEL);
+ chunk_list = kmalloc(chunk_list_len, GFP_KERNEL);
if (!chunk_list)
return -ENOMEM;
+ chunk_list_phys = virt_to_phys(chunk_list);
for (i = 0; i < nchunks; i++)
chunk_list[i] = phy_base + i * V2_CHUNK_SIZE;
- ret = ion_cp_change_chunks_state(__pa(chunk_list),
+ /*
+ * Flush the chunk list before sending the memory to the
+ * secure environment to ensure the data is actually present
+ * in RAM
+ */
+ dmac_flush_range(chunk_list, chunk_list + chunk_list_len);
+ outer_flush_range(chunk_list_phys,
+ chunk_list_phys + chunk_list_len);
+
+ ret = ion_cp_change_chunks_state(chunk_list_phys,
nchunks, V2_CHUNK_SIZE, usage, lock);
kfree(chunk_list);
diff --git a/drivers/hwmon/epm_adc.c b/drivers/hwmon/epm_adc.c
index 51ffd21..a587ed2 100644
--- a/drivers/hwmon/epm_adc.c
+++ b/drivers/hwmon/epm_adc.c
@@ -937,7 +937,7 @@
return rc;
}
-static int epm_psoc_timestamp(struct epm_adc_drv *epm_adc,
+static int epm_psoc_get_timestamp(struct epm_adc_drv *epm_adc,
struct epm_psoc_system_time_stamp *psoc_timestamp)
{
struct spi_message m;
@@ -955,15 +955,51 @@
spi_message_init(&m);
spi_message_add_tail(&t, &m);
- if (psoc_timestamp->cmd == EPM_PSOC_SET_SYSTEM_TIMESTAMP_CMD) {
- tx_buf[0] = psoc_timestamp->cmd;
- tx_buf[1] = (psoc_timestamp->timestamp & 0xff000000) >> 24;
- tx_buf[2] = (psoc_timestamp->timestamp & 0xff0000) >> 16;
- tx_buf[3] = (psoc_timestamp->timestamp & 0xff00) >> 8;
- tx_buf[4] = (psoc_timestamp->timestamp & 0xff);
- } else if (psoc_timestamp->cmd == EPM_PSOC_GET_SYSTEM_TIMESTAMP_CMD) {
- tx_buf[0] = psoc_timestamp->cmd;
- }
+ psoc_timestamp->cmd = EPM_PSOC_GET_SYSTEM_TIMESTAMP_CMD;
+ tx_buf[0] = psoc_timestamp->cmd;
+
+ t.len = sizeof(tx_buf);
+ t.bits_per_word = EPM_ADC_ADS_SPI_BITS_PER_WORD;
+
+ rc = spi_sync(epm_adc->epm_spi_client, &m);
+ if (rc)
+ return rc;
+
+ rc = spi_sync(epm_adc->epm_spi_client, &m);
+ if (rc)
+ return rc;
+
+ psoc_timestamp->cmd = rx_buf[0];
+ psoc_timestamp->timestamp = rx_buf[1] << 24 | rx_buf[2] << 16 |
+ rx_buf[3] << 8 | rx_buf[4];
+
+ return rc;
+}
+
+static int epm_psoc_set_timestamp(struct epm_adc_drv *epm_adc,
+ struct epm_psoc_system_time_stamp *psoc_timestamp)
+{
+ struct spi_message m;
+ struct spi_transfer t;
+ char tx_buf[10], rx_buf[10];
+ int rc = 0;
+
+ spi_setup(epm_adc->epm_spi_client);
+
+ memset(&t, 0, sizeof t);
+ memset(tx_buf, 0, sizeof tx_buf);
+ memset(rx_buf, 0, sizeof tx_buf);
+ t.tx_buf = tx_buf;
+ t.rx_buf = rx_buf;
+ spi_message_init(&m);
+ spi_message_add_tail(&t, &m);
+
+ psoc_timestamp->cmd = EPM_PSOC_SET_SYSTEM_TIMESTAMP_CMD;
+ tx_buf[0] = psoc_timestamp->cmd;
+ tx_buf[1] = (psoc_timestamp->timestamp >> 24) & 0xff;
+ tx_buf[2] = (psoc_timestamp->timestamp >> 16) & 0xff;
+ tx_buf[3] = (psoc_timestamp->timestamp >> 8) & 0xff;
+ tx_buf[4] = (psoc_timestamp->timestamp & 0xff);
t.len = sizeof(tx_buf);
t.bits_per_word = EPM_ADC_ADS_SPI_BITS_PER_WORD;
@@ -1199,7 +1235,7 @@
if (rc)
return rc;
- rc = rx_buf[2];
+ rc = rx_buf[1];
return rc;
}
@@ -1378,6 +1414,26 @@
break;
}
case EPM_PSOC_ADC_GET_SYSTEM_TIMESTAMP:
+ {
+ struct epm_psoc_system_time_stamp psoc_timestamp;
+ int rc;
+
+ if (copy_from_user(&psoc_timestamp,
+ (void __user *)arg,
+ sizeof(struct epm_psoc_system_time_stamp)))
+ return -EFAULT;
+
+ rc = epm_psoc_get_timestamp(epm_adc, &psoc_timestamp);
+ if (rc) {
+ pr_err("PSOC get timestamp failed\n");
+ return -EINVAL;
+ }
+
+ if (copy_to_user((void __user *)arg, &psoc_timestamp,
+ sizeof(struct epm_psoc_system_time_stamp)))
+ return -EFAULT;
+ break;
+ }
case EPM_PSOC_ADC_SET_SYSTEM_TIMESTAMP:
{
struct epm_psoc_system_time_stamp psoc_timestamp;
@@ -1388,9 +1444,9 @@
sizeof(struct epm_psoc_system_time_stamp)))
return -EFAULT;
- rc = epm_psoc_timestamp(epm_adc, &psoc_timestamp);
+ rc = epm_psoc_set_timestamp(epm_adc, &psoc_timestamp);
if (rc) {
- pr_err("PSOC buffered measurement failed\n");
+ pr_err("PSOC set timestamp failed\n");
return -EINVAL;
}
diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c
index f46139f..97541ff 100644
--- a/drivers/input/misc/kxtj9.c
+++ b/drivers/input/misc/kxtj9.c
@@ -25,6 +25,7 @@
#include <linux/slab.h>
#include <linux/input/kxtj9.h>
#include <linux/input-polldev.h>
+#include <linux/regulator/consumer.h>
#define NAME "kxtj9"
#define G_MAX 8000
@@ -62,6 +63,11 @@
#define RES_CTRL_REG1 1
#define RES_INT_CTRL1 2
#define RESUME_ENTRIES 3
+/* POWER SUPPLY VOLTAGE RANGE */
+#define KXTJ9_VDD_MIN_UV 2000000
+#define KXTJ9_VDD_MAX_UV 3300000
+#define KXTJ9_VIO_MIN_UV 1750000
+#define KXTJ9_VIO_MAX_UV 1950000
/*
* The following table lists the maximum appropriate poll interval for each
@@ -92,6 +98,9 @@
u8 ctrl_reg1;
u8 data_ctrl;
u8 int_ctrl;
+ bool power_enabled;
+ struct regulator *vdd;
+ struct regulator *vio;
};
static int kxtj9_i2c_read(struct kxtj9_data *tj9, u8 addr, u8 *data, int len)
@@ -203,12 +212,130 @@
return 0;
}
-static int kxtj9_device_power_on(struct kxtj9_data *tj9)
+static int kxtj9_power_on(struct kxtj9_data *data, bool on)
{
- if (tj9->pdata.power_on)
- return tj9->pdata.power_on();
+ int rc = 0;
+
+ if (!on && data->power_enabled) {
+ rc = regulator_disable(data->vdd);
+ if (rc) {
+ dev_err(&data->client->dev,
+ "Regulator vdd disable failed rc=%d\n", rc);
+ return rc;
+ }
+
+ rc = regulator_disable(data->vio);
+ if (rc) {
+ dev_err(&data->client->dev,
+ "Regulator vio disable failed rc=%d\n", rc);
+ regulator_enable(data->vdd);
+ }
+ data->power_enabled = false;
+ } else if (on && !data->power_enabled) {
+ rc = regulator_enable(data->vdd);
+ if (rc) {
+ dev_err(&data->client->dev,
+ "Regulator vdd enable failed rc=%d\n", rc);
+ return rc;
+ }
+
+ rc = regulator_enable(data->vio);
+ if (rc) {
+ dev_err(&data->client->dev,
+ "Regulator vio enable failed rc=%d\n", rc);
+ regulator_disable(data->vdd);
+ }
+ data->power_enabled = true;
+ } else {
+ dev_warn(&data->client->dev,
+ "Power on=%d. enabled=%d\n",
+ on, data->power_enabled);
+ }
+
+ return rc;
+}
+
+static int kxtj9_power_init(struct kxtj9_data *data, bool on)
+{
+ int rc;
+
+ if (!on) {
+ if (regulator_count_voltages(data->vdd) > 0)
+ regulator_set_voltage(data->vdd, 0, KXTJ9_VDD_MAX_UV);
+
+ regulator_put(data->vdd);
+
+ if (regulator_count_voltages(data->vio) > 0)
+ regulator_set_voltage(data->vio, 0, KXTJ9_VIO_MAX_UV);
+
+ regulator_put(data->vio);
+ } else {
+ data->vdd = regulator_get(&data->client->dev, "vdd");
+ if (IS_ERR(data->vdd)) {
+ rc = PTR_ERR(data->vdd);
+ dev_err(&data->client->dev,
+ "Regulator get failed vdd rc=%d\n", rc);
+ return rc;
+ }
+
+ if (regulator_count_voltages(data->vdd) > 0) {
+ rc = regulator_set_voltage(data->vdd, KXTJ9_VDD_MIN_UV,
+ KXTJ9_VDD_MAX_UV);
+ if (rc) {
+ dev_err(&data->client->dev,
+ "Regulator set failed vdd rc=%d\n",
+ rc);
+ goto reg_vdd_put;
+ }
+ }
+
+ data->vio = regulator_get(&data->client->dev, "vio");
+ if (IS_ERR(data->vio)) {
+ rc = PTR_ERR(data->vio);
+ dev_err(&data->client->dev,
+ "Regulator get failed vio rc=%d\n", rc);
+ goto reg_vdd_set;
+ }
+
+ if (regulator_count_voltages(data->vio) > 0) {
+ rc = regulator_set_voltage(data->vio, KXTJ9_VIO_MIN_UV,
+ KXTJ9_VIO_MAX_UV);
+ if (rc) {
+ dev_err(&data->client->dev,
+ "Regulator set failed vio rc=%d\n", rc);
+ goto reg_vio_put;
+ }
+ }
+ }
return 0;
+
+reg_vio_put:
+ regulator_put(data->vio);
+reg_vdd_set:
+ if (regulator_count_voltages(data->vdd) > 0)
+ regulator_set_voltage(data->vdd, 0, KXTJ9_VDD_MAX_UV);
+reg_vdd_put:
+ regulator_put(data->vdd);
+ return rc;
+}
+static int kxtj9_device_power_on(struct kxtj9_data *tj9)
+{
+ int err = 0;
+ if (tj9->pdata.power_on) {
+ err = tj9->pdata.power_on();
+ } else {
+ err = kxtj9_power_on(tj9, true);
+ if (err) {
+ dev_err(&tj9->client->dev, "power on failed");
+ goto err_exit;
+ }
+ msleep(20);
+ }
+
+err_exit:
+ dev_dbg(&tj9->client->dev, "soft power on complete err=%d.\n", err);
+ return err;
}
static void kxtj9_device_power_off(struct kxtj9_data *tj9)
@@ -222,6 +349,11 @@
if (tj9->pdata.power_off)
tj9->pdata.power_off();
+ else
+ kxtj9_power_on(tj9, false);
+
+ dev_dbg(&tj9->client->dev, "soft power off complete.\n");
+ return ;
}
static int kxtj9_enable(struct kxtj9_data *tj9)
@@ -489,10 +621,6 @@
{
int retval;
- retval = kxtj9_device_power_on(tj9);
- if (retval < 0)
- return retval;
-
retval = i2c_smbus_read_byte_data(tj9->client, WHO_AM_I);
if (retval < 0) {
dev_err(&tj9->client->dev, "read err int source\n");
@@ -502,7 +630,6 @@
retval = (retval != 0x07 && retval != 0x08) ? -EIO : 0;
out:
- kxtj9_device_power_off(tj9);
return retval;
}
@@ -533,6 +660,7 @@
tj9->client = client;
tj9->pdata = *pdata;
+ tj9->power_enabled = false;
if (pdata->init) {
err = pdata->init();
@@ -540,10 +668,21 @@
goto err_free_mem;
}
+ err = kxtj9_power_init(tj9, true);
+ if (err < 0) {
+ dev_err(&tj9->client->dev, "power init failed! err=%d", err);
+ goto err_pdata_exit;
+ }
+
+ err = kxtj9_device_power_on(tj9);
+ if (err < 0) {
+ dev_err(&client->dev, "power on failed! err=%d\n", err);
+ goto err_power_deinit;
+ }
err = kxtj9_verify(tj9);
if (err < 0) {
dev_err(&client->dev, "device not recognized\n");
- goto err_pdata_exit;
+ goto err_power_off;
}
i2c_set_clientdata(client, tj9);
@@ -558,7 +697,7 @@
err = kxtj9_setup_input_device(tj9);
if (err)
- goto err_pdata_exit;
+ goto err_power_off;
err = request_threaded_irq(client->irq, NULL, kxtj9_isr,
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
@@ -577,20 +716,28 @@
} else {
err = kxtj9_setup_polled_device(tj9);
if (err)
- goto err_pdata_exit;
+ goto err_power_off;
}
+ dev_dbg(&client->dev, "%s: kxtj9_probe OK.\n", __func__);
+ kxtj9_device_power_off(tj9);
return 0;
err_free_irq:
free_irq(client->irq, tj9);
err_destroy_input:
input_unregister_device(tj9->input_dev);
+err_power_off:
+ kxtj9_device_power_off(tj9);
+err_power_deinit:
+ kxtj9_power_init(tj9, false);
err_pdata_exit:
if (tj9->pdata.exit)
tj9->pdata.exit();
err_free_mem:
kfree(tj9);
+
+ dev_err(&client->dev, "%s: kxtj9_probe err=%d\n", __func__, err);
return err;
}
@@ -606,6 +753,9 @@
kxtj9_teardown_polled_device(tj9);
}
+ kxtj9_device_power_off(tj9);
+ kxtj9_power_init(tj9, false);
+
if (tj9->pdata.exit)
tj9->pdata.exit();
diff --git a/drivers/input/touchscreen/ft5x06_ts.c b/drivers/input/touchscreen/ft5x06_ts.c
index efcace6..8dbac64 100644
--- a/drivers/input/touchscreen/ft5x06_ts.c
+++ b/drivers/input/touchscreen/ft5x06_ts.c
@@ -18,6 +18,7 @@
#include <linux/i2c.h>
#include <linux/input.h>
+#include <linux/input/mt.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
@@ -168,7 +169,15 @@
#define FT_REG_CAL 0x00
#define FT_CAL_MASK 0x70
-#define FT_DEBUG_DIR_NAME "ft_debug"
+#define FT_INFO_MAX_LEN 200
+
+#define FT_STORE_TS_INFO(buf, id, fw_ver) \
+ snprintf(buf, FT_INFO_MAX_LEN, \
+ "controller\t= focaltech\n" \
+ "model\t\t= 0x%x\n" \
+ "fw_ver\t\t= 0x%x\n", id, fw_ver)
+
+#define FT_DEBUG_DIR_NAME "ts_debug"
struct ts_event {
u16 x[CFG_MAX_TOUCH_POINTS]; /*x coordinate */
@@ -202,6 +211,7 @@
struct dentry *dir;
u16 addr;
bool suspended;
+ char *ts_info;
#if defined(CONFIG_FB)
struct notifier_block fb_notif;
#elif defined(CONFIG_HAS_EARLYSUSPEND)
@@ -298,17 +308,22 @@
event->pressure = 0;
}
- input_report_abs(data->input_dev, ABS_MT_POSITION_X,
- event->x[i]);
- input_report_abs(data->input_dev, ABS_MT_POSITION_Y,
- event->y[i]);
- input_report_abs(data->input_dev, ABS_MT_PRESSURE,
- event->pressure);
- input_report_abs(data->input_dev, ABS_MT_TRACKING_ID,
- event->finger_id[i]);
- input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR,
- event->pressure);
- input_mt_sync(data->input_dev);
+ input_mt_slot(data->input_dev, i);
+ input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER,
+ !!event->pressure);
+
+ if (event->pressure == FT_PRESS) {
+ input_report_abs(data->input_dev, ABS_MT_POSITION_X,
+ event->x[i]);
+ input_report_abs(data->input_dev, ABS_MT_POSITION_Y,
+ event->y[i]);
+ input_report_abs(data->input_dev, ABS_MT_PRESSURE,
+ event->pressure);
+ input_report_abs(data->input_dev, ABS_MT_TRACKING_ID,
+ event->finger_id[i]);
+ input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR,
+ event->pressure);
+ }
}
input_report_key(data->input_dev, BTN_TOUCH, !!fingerdown);
@@ -809,6 +824,7 @@
rc = -EIO;
}
+ FT_STORE_TS_INFO(data->ts_info, data->family_id, FT_FW_FILE_VER(fw));
rel_fw:
release_firmware(fw);
return rc;
@@ -1015,6 +1031,27 @@
DEFINE_SIMPLE_ATTRIBUTE(debug_suspend_fops, ft5x06_debug_suspend_get,
ft5x06_debug_suspend_set, "%lld\n");
+static int ft5x06_debug_dump_info(struct seq_file *m, void *v)
+{
+ struct ft5x06_ts_data *data = m->private;
+
+ seq_printf(m, "%s\n", data->ts_info);
+
+ return 0;
+}
+
+static int debugfs_dump_info_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, ft5x06_debug_dump_info, inode->i_private);
+}
+
+static const struct file_operations debug_dump_info_fops = {
+ .owner = THIS_MODULE,
+ .open = debugfs_dump_info_open,
+ .read = seq_read,
+ .release = single_release,
+};
+
#ifdef CONFIG_OF
static int ft5x06_get_dt_coords(struct device *dev, char *name,
struct ft5x06_ts_platform_data *pdata)
@@ -1130,7 +1167,7 @@
struct ft5x06_ts_platform_data *pdata;
struct ft5x06_ts_data *data;
struct input_dev *input_dev;
- struct dentry *dir, *temp;
+ struct dentry *temp;
u8 reg_value;
u8 reg_addr;
int err;
@@ -1188,12 +1225,11 @@
__set_bit(BTN_TOUCH, input_dev->keybit);
__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+ input_mt_init_slots(input_dev, CFG_MAX_TOUCH_POINTS);
input_set_abs_params(input_dev, ABS_MT_POSITION_X, pdata->x_min,
pdata->x_max, 0, 0);
input_set_abs_params(input_dev, ABS_MT_POSITION_Y, pdata->y_min,
pdata->y_max, 0, 0);
- input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0,
- CFG_MAX_TOUCH_POINTS, 0, 0);
input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, FT_PRESS, 0, 0);
input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, FT_PRESS, 0, 0);
@@ -1282,28 +1318,6 @@
data->family_id = reg_value;
- /*get some register information */
- reg_addr = FT_REG_FW_VER;
- err = ft5x06_i2c_read(client, ®_addr, 1, ®_value, 1);
- if (err < 0)
- dev_err(&client->dev, "version read failed");
-
- dev_info(&client->dev, "Firmware version = 0x%x\n", reg_value);
-
- reg_addr = FT_REG_POINT_RATE;
- ft5x06_i2c_read(client, ®_addr, 1, ®_value, 1);
- if (err < 0)
- dev_err(&client->dev, "report rate read failed");
-
- dev_info(&client->dev, "report rate = %dHz\n", reg_value * 10);
-
- reg_addr = FT_REG_THGROUP;
- err = ft5x06_i2c_read(client, ®_addr, 1, ®_value, 1);
- if (err < 0)
- dev_err(&client->dev, "threshold read failed");
-
- dev_dbg(&client->dev, "touch threshold = %d\n", reg_value * 4);
-
err = request_threaded_irq(client->irq, NULL,
ft5x06_ts_interrupt, pdata->irqflags,
client->dev.driver->name, data);
@@ -1330,14 +1344,14 @@
goto free_update_fw_sys;
}
- dir = debugfs_create_dir(FT_DEBUG_DIR_NAME, NULL);
- if (dir == NULL || IS_ERR(dir)) {
- pr_err("debugfs_create_dir failed: rc=%ld\n", PTR_ERR(dir));
- err = PTR_ERR(dir);
+ data->dir = debugfs_create_dir(FT_DEBUG_DIR_NAME, NULL);
+ if (data->dir == NULL || IS_ERR(data->dir)) {
+ pr_err("debugfs_create_dir failed(%ld)\n", PTR_ERR(data->dir));
+ err = PTR_ERR(data->dir);
goto free_force_update_fw_sys;
}
- temp = debugfs_create_file("addr", S_IRUSR | S_IWUSR, dir, data,
+ temp = debugfs_create_file("addr", S_IRUSR | S_IWUSR, data->dir, data,
&debug_addr_fops);
if (temp == NULL || IS_ERR(temp)) {
pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
@@ -1345,7 +1359,7 @@
goto free_debug_dir;
}
- temp = debugfs_create_file("data", S_IRUSR | S_IWUSR, dir, data,
+ temp = debugfs_create_file("data", S_IRUSR | S_IWUSR, data->dir, data,
&debug_data_fops);
if (temp == NULL || IS_ERR(temp)) {
pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
@@ -1353,14 +1367,52 @@
goto free_debug_dir;
}
- temp = debugfs_create_file("suspend", S_IRUSR | S_IWUSR, dir, data,
- &debug_suspend_fops);
+ temp = debugfs_create_file("suspend", S_IRUSR | S_IWUSR, data->dir,
+ data, &debug_suspend_fops);
if (temp == NULL || IS_ERR(temp)) {
pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
err = PTR_ERR(temp);
goto free_debug_dir;
}
+ temp = debugfs_create_file("dump_info", S_IRUSR | S_IWUSR, data->dir,
+ data, &debug_dump_info_fops);
+ if (temp == NULL || IS_ERR(temp)) {
+ pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
+ err = PTR_ERR(temp);
+ goto free_debug_dir;
+ }
+
+ data->ts_info = kzalloc(FT_INFO_MAX_LEN, GFP_KERNEL);
+ if (!data->ts_info) {
+ dev_err(&client->dev, "Not enough memory\n");
+ goto free_debug_dir;
+ }
+
+ /*get some register information */
+ reg_addr = FT_REG_POINT_RATE;
+ ft5x06_i2c_read(client, ®_addr, 1, ®_value, 1);
+ if (err < 0)
+ dev_err(&client->dev, "report rate read failed");
+
+ dev_info(&client->dev, "report rate = %dHz\n", reg_value * 10);
+
+ reg_addr = FT_REG_THGROUP;
+ err = ft5x06_i2c_read(client, ®_addr, 1, ®_value, 1);
+ if (err < 0)
+ dev_err(&client->dev, "threshold read failed");
+
+ dev_dbg(&client->dev, "touch threshold = %d\n", reg_value * 4);
+
+ reg_addr = FT_REG_FW_VER;
+ err = ft5x06_i2c_read(client, ®_addr, 1, ®_value, 1);
+ if (err < 0)
+ dev_err(&client->dev, "version read failed");
+
+ dev_info(&client->dev, "Firmware version = 0x%x\n", reg_value);
+
+ FT_STORE_TS_INFO(data->ts_info, data->family_id, reg_value);
+
#if defined(CONFIG_FB)
data->fb_notif.notifier_call = fb_notifier_callback;
@@ -1449,6 +1501,7 @@
ft5x06_power_init(data, false);
input_unregister_device(data->input_dev);
+ kfree(data->ts_info);
kfree(data);
return 0;
diff --git a/drivers/input/touchscreen/synaptics_fw_update.c b/drivers/input/touchscreen/synaptics_fw_update.c
index d51481f..349b020 100644
--- a/drivers/input/touchscreen/synaptics_fw_update.c
+++ b/drivers/input/touchscreen/synaptics_fw_update.c
@@ -304,10 +304,10 @@
};
static struct device_attribute attrs[] = {
- __ATTR(forceflash, S_IWUGO,
+ __ATTR(force_update_fw, S_IWUGO,
synaptics_rmi4_show_error,
fwu_sysfs_force_reflash_store),
- __ATTR(doreflash, S_IWUGO,
+ __ATTR(update_fw, S_IWUGO,
synaptics_rmi4_show_error,
fwu_sysfs_do_reflash_store),
__ATTR(writeconfig, S_IWUGO,
diff --git a/drivers/iommu/msm_iommu-v1.c b/drivers/iommu/msm_iommu-v1.c
index 653487b..a400b58 100644
--- a/drivers/iommu/msm_iommu-v1.c
+++ b/drivers/iommu/msm_iommu-v1.c
@@ -822,12 +822,18 @@
return 0;
}
-void print_ctx_regs(struct msm_iommu_context_regs *regs)
+void print_ctx_regs(struct msm_iommu_context_reg regs[])
{
- uint32_t fsr = regs->fsr;
+ uint32_t fsr = regs[DUMP_REG_FSR].val;
- pr_err("FAR = %08x PAR = %08x\n",
- regs->far, regs->par);
+ pr_err("FAR = %016llx\n",
+ COMBINE_DUMP_REG(
+ regs[DUMP_REG_FAR1].val,
+ regs[DUMP_REG_FAR0].val));
+ pr_err("PAR = %016llx\n",
+ COMBINE_DUMP_REG(
+ regs[DUMP_REG_PAR1].val,
+ regs[DUMP_REG_PAR0].val));
pr_err("FSR = %08x [%s%s%s%s%s%s%s%s%s]\n", fsr,
(fsr & 0x02) ? "TF " : "",
(fsr & 0x04) ? "AFF " : "",
@@ -840,31 +846,61 @@
(fsr & 0x80000000) ? "MULTI " : "");
pr_err("FSYNR0 = %08x FSYNR1 = %08x\n",
- regs->fsynr0, regs->fsynr1);
+ regs[DUMP_REG_FSYNR0].val, regs[DUMP_REG_FSYNR1].val);
pr_err("TTBR0 = %08x TTBR1 = %08x\n",
- regs->ttbr0, regs->ttbr1);
+ regs[DUMP_REG_TTBR0].val, regs[DUMP_REG_TTBR1].val);
pr_err("SCTLR = %08x ACTLR = %08x\n",
- regs->sctlr, regs->actlr);
+ regs[DUMP_REG_SCTLR].val, regs[DUMP_REG_ACTLR].val);
pr_err("PRRR = %08x NMRR = %08x\n",
- regs->prrr, regs->nmrr);
+ regs[DUMP_REG_PRRR].val, regs[DUMP_REG_NMRR].val);
}
static void __print_ctx_regs(void __iomem *base, int ctx, unsigned int fsr)
{
- struct msm_iommu_context_regs regs = {
- .far = GET_FAR(base, ctx),
- .par = GET_PAR(base, ctx),
- .fsr = fsr,
- .fsynr0 = GET_FSYNR0(base, ctx),
- .fsynr1 = GET_FSYNR1(base, ctx),
- .ttbr0 = GET_TTBR0(base, ctx),
- .ttbr1 = GET_TTBR1(base, ctx),
- .sctlr = GET_SCTLR(base, ctx),
- .actlr = GET_ACTLR(base, ctx),
- .prrr = GET_PRRR(base, ctx),
- .nmrr = GET_NMRR(base, ctx),
+ struct msm_iommu_context_reg regs[MAX_DUMP_REGS] = {
+ [DUMP_REG_FAR0] = {
+ .val = GET_FAR(base, ctx)
+ },
+ [DUMP_REG_FAR1] = {
+ /* TODO: make GET_FAR 64-bit and take this from that */
+ .val = 0
+ },
+ [DUMP_REG_PAR0] = {
+ .val = GET_PAR(base, ctx)
+ },
+ [DUMP_REG_PAR1] = {
+ /* TODO: make GET_PAR 64-bit and take this from that */
+ .val = 0
+ },
+ [DUMP_REG_FSR] = {
+ .val = fsr
+ },
+ [DUMP_REG_FSYNR0] = {
+ .val = GET_FSYNR0(base, ctx)
+ },
+ [DUMP_REG_FSYNR1] = {
+ .val = GET_FSYNR1(base, ctx)
+ },
+ [DUMP_REG_TTBR0] = {
+ .val = GET_TTBR0(base, ctx)
+ },
+ [DUMP_REG_TTBR1] = {
+ .val = GET_TTBR1(base, ctx)
+ },
+ [DUMP_REG_SCTLR] = {
+ .val = GET_SCTLR(base, ctx)
+ },
+ [DUMP_REG_ACTLR] = {
+ .val = GET_ACTLR(base, ctx)
+ },
+ [DUMP_REG_PRRR] = {
+ .val = GET_PRRR(base, ctx)
+ },
+ [DUMP_REG_NMRR] = {
+ .val = GET_NMRR(base, ctx)
+ },
};
- print_ctx_regs(®s);
+ print_ctx_regs(regs);
}
irqreturn_t msm_iommu_fault_handler_v2(int irq, void *dev_id)
diff --git a/drivers/iommu/msm_iommu_sec.c b/drivers/iommu/msm_iommu_sec.c
index a17a4e8..50f6df4 100644
--- a/drivers/iommu/msm_iommu_sec.c
+++ b/drivers/iommu/msm_iommu_sec.c
@@ -34,6 +34,7 @@
#include <mach/msm_iommu_priv.h>
#include <mach/iommu.h>
#include <mach/scm.h>
+#include <mach/memory.h>
/* bitmap of the page sizes currently supported */
#define MSM_IOMMU_PGSIZES (SZ_4K | SZ_64K | SZ_1M | SZ_16M)
@@ -77,37 +78,19 @@
unsigned int flags;
};
+#define NUM_DUMP_REGS 14
+/*
+ * some space to allow the number of registers returned by the secure
+ * environment to grow
+ */
+#define WIGGLE_ROOM (NUM_DUMP_REGS * 2)
+/* Each entry is a (reg_addr, reg_val) pair, hence the * 2 */
+#define SEC_DUMP_SIZE ((NUM_DUMP_REGS * 2) + WIGGLE_ROOM)
+
struct msm_scm_fault_regs_dump {
uint32_t dump_size;
- uint32_t fsr_addr;
- uint32_t fsr;
- uint32_t far0_addr;
- uint32_t far0;
- uint32_t far1_addr;
- uint32_t far1;
- uint32_t par0_addr;
- uint32_t par0;
- uint32_t par1_addr;
- uint32_t par1;
- uint32_t fsyn0_addr;
- uint32_t fsyn0;
- uint32_t fsyn1_addr;
- uint32_t fsyn1;
- uint32_t ttbr0_addr;
- uint32_t ttbr0;
- uint32_t ttbr1_addr;
- uint32_t ttbr1;
- uint32_t ttbcr_addr;
- uint32_t ttbcr;
- uint32_t sctlr_addr;
- uint32_t sctlr;
- uint32_t actlr_addr;
- uint32_t actlr;
- uint32_t prrr_addr;
- uint32_t prrr;
- uint32_t nmrr_addr;
- uint32_t nmrr;
-};
+ uint32_t dump_data[SEC_DUMP_SIZE];
+} __packed;
void msm_iommu_sec_set_access_ops(struct iommu_access_ops *access_ops)
{
@@ -135,6 +118,100 @@
ret = scm_call(SCM_SVC_UTIL, IOMMU_DUMP_SMMU_FAULT_REGS,
&req_info, sizeof(req_info), &resp, 1);
+ invalidate_caches((unsigned long) regs, sizeof(*regs),
+ (unsigned long)virt_to_phys(regs));
+
+ return ret;
+}
+
+static struct dump_regs_tbl {
+ /*
+ * To keep things context-bank-agnostic, we only store the CB
+ * register offset in `key'
+ */
+ unsigned long key;
+ const char *name;
+ int offset;
+} dump_regs_tbl[MAX_DUMP_REGS];
+
+#define EXTRACT_DUMP_REG_KEY(addr, ctx) (addr & ((1 << CTX_SHIFT) - 1))
+
+#define DUMP_REG_INIT(dump_reg, cb_reg) \
+ do { \
+ dump_regs_tbl[dump_reg].key = cb_reg; \
+ dump_regs_tbl[dump_reg].name = #cb_reg; \
+ } while (0)
+
+static void msm_iommu_sec_build_dump_regs_table(void)
+{
+ DUMP_REG_INIT(DUMP_REG_FAR0, CB_FAR);
+ DUMP_REG_INIT(DUMP_REG_FAR1, CB_FAR + 4);
+ DUMP_REG_INIT(DUMP_REG_PAR0, CB_PAR);
+ DUMP_REG_INIT(DUMP_REG_PAR1, CB_PAR + 4);
+ DUMP_REG_INIT(DUMP_REG_FSR, CB_FSR);
+ DUMP_REG_INIT(DUMP_REG_FSYNR0, CB_FSYNR0);
+ DUMP_REG_INIT(DUMP_REG_FSYNR1, CB_FSYNR1);
+ DUMP_REG_INIT(DUMP_REG_TTBR0, CB_TTBR0);
+ DUMP_REG_INIT(DUMP_REG_TTBR1, CB_TTBR1);
+ DUMP_REG_INIT(DUMP_REG_SCTLR, CB_SCTLR);
+ DUMP_REG_INIT(DUMP_REG_ACTLR, CB_ACTLR);
+ DUMP_REG_INIT(DUMP_REG_PRRR, CB_PRRR);
+ DUMP_REG_INIT(DUMP_REG_NMRR, CB_NMRR);
+}
+
+static int msm_iommu_reg_dump_to_regs(
+ struct msm_iommu_context_reg ctx_regs[],
+ struct msm_scm_fault_regs_dump *dump, int cb_num)
+{
+ int i, j, ret = 0;
+ const uint32_t nvals = (dump->dump_size / sizeof(uint32_t));
+ uint32_t *it = (uint32_t *) dump->dump_data;
+ const uint32_t * const end = ((uint32_t *) dump) + nvals;
+
+ for (i = 1; it < end; it += 2, i += 2) {
+ uint32_t addr = *it;
+ uint32_t val = *(it + 1);
+ struct msm_iommu_context_reg *reg = NULL;
+
+ for (j = 0; j < MAX_DUMP_REGS; ++j) {
+ if (dump_regs_tbl[j].key ==
+ EXTRACT_DUMP_REG_KEY(addr, cb_num)) {
+ reg = &ctx_regs[j];
+ break;
+ }
+ }
+
+ if (reg == NULL) {
+ pr_debug("Unknown register in secure CB dump: %x (%x)\n",
+ addr, EXTRACT_DUMP_REG_KEY(addr, cb_num));
+ continue;
+ }
+
+ if (reg->valid) {
+ WARN(1, "Invalid (repeated?) register in CB dump: %x\n",
+ addr);
+ continue;
+ }
+
+ reg->val = val;
+ reg->valid = true;
+ }
+
+ if (i != nvals) {
+ pr_err("Invalid dump! %d != %d\n", i, nvals);
+ ret = 1;
+ goto out;
+ }
+
+ for (i = 0; i < MAX_DUMP_REGS; ++i) {
+ if (!ctx_regs[i].valid) {
+ pr_err("Register missing from dump: %s, %lx\n",
+ dump_regs_tbl[i].name, dump_regs_tbl[i].key);
+ ret = 1;
+ }
+ }
+
+out:
return ret;
}
@@ -180,43 +257,40 @@
iommu_access_ops->iommu_clk_off(drvdata);
if (tmp) {
- pr_err("%s: Couldn't dump fault registers!\n", __func__);
+ pr_err("%s: Couldn't dump fault registers (%d) %s, ctx: %d\n",
+ __func__, tmp, drvdata->name, ctx_drvdata->num);
goto free_regs;
- } else if (regs->fsr) {
- struct msm_iommu_context_regs ctx_regs = {
- .far = regs->far0,
- .par = regs->par0,
- .fsr = regs->fsr,
- .fsynr0 = regs->fsyn0,
- .fsynr1 = regs->fsyn1,
- .ttbr0 = regs->ttbr0,
- .ttbr1 = regs->ttbr1,
- .sctlr = regs->sctlr,
- .actlr = regs->actlr,
- .prrr = regs->prrr,
- .nmrr = regs->nmrr,
- };
-
- if (!ctx_drvdata->attached_domain) {
- pr_err("Bad domain in interrupt handler\n");
- tmp = -ENOSYS;
- } else {
- tmp = report_iommu_fault(ctx_drvdata->attached_domain,
- &ctx_drvdata->pdev->dev,
- regs->far0, 0);
- }
-
- /* if the fault wasn't handled by someone else: */
- if (tmp == -ENOSYS) {
- pr_err("Unexpected IOMMU page fault from secure context bank!\n");
- pr_err("name = %s\n", drvdata->name);
- pr_err("context = %s (%d)\n", ctx_drvdata->name,
- ctx_drvdata->num);
- pr_err("Interesting registers:\n");
- print_ctx_regs(&ctx_regs);
- }
} else {
- ret = IRQ_NONE;
+ struct msm_iommu_context_reg ctx_regs[MAX_DUMP_REGS];
+ memset(ctx_regs, 0, sizeof(ctx_regs));
+ tmp = msm_iommu_reg_dump_to_regs(ctx_regs, regs,
+ ctx_drvdata->num);
+ if (!tmp && ctx_regs[DUMP_REG_FSR].val) {
+ if (!ctx_drvdata->attached_domain) {
+ pr_err("Bad domain in interrupt handler\n");
+ tmp = -ENOSYS;
+ } else {
+ tmp = report_iommu_fault(
+ ctx_drvdata->attached_domain,
+ &ctx_drvdata->pdev->dev,
+ COMBINE_DUMP_REG(
+ ctx_regs[DUMP_REG_FAR1].val,
+ ctx_regs[DUMP_REG_FAR0].val),
+ 0);
+ }
+
+ /* if the fault wasn't handled by someone else: */
+ if (tmp == -ENOSYS) {
+ pr_err("Unexpected IOMMU page fault from secure context bank!\n");
+ pr_err("name = %s\n", drvdata->name);
+ pr_err("context = %s (%d)\n", ctx_drvdata->name,
+ ctx_drvdata->num);
+ pr_err("Interesting registers:\n");
+ print_ctx_regs(ctx_regs);
+ }
+ } else {
+ ret = IRQ_NONE;
+ }
}
free_regs:
kfree(regs);
@@ -315,6 +389,8 @@
unsigned long va, phys_addr_t pa, size_t len)
{
struct msm_scm_map2_req map;
+ void *flush_va;
+ phys_addr_t flush_pa;
int ret = 0;
map.plist.list = virt_to_phys(&pa);
@@ -325,6 +401,13 @@
map.info.va = va;
map.info.size = len;
map.flags = IOMMU_TLBINVAL_FLAG;
+ flush_va = &pa;
+ flush_pa = virt_to_phys(&pa);
+
+ /*
+ * Ensure that the buffer is in RAM by the time it gets to TZ
+ */
+ clean_caches((unsigned long) flush_va, len, flush_pa);
if (scm_call(SCM_SVC_MP, IOMMU_SECURE_MAP2, &map, sizeof(map), &ret,
sizeof(ret)))
@@ -332,6 +415,9 @@
if (ret)
return -EINVAL;
+ /* Invalidate cache since TZ touched this address range */
+ invalidate_caches((unsigned long) flush_va, len, flush_pa);
+
return 0;
}
@@ -356,6 +442,7 @@
struct msm_scm_map2_req map;
unsigned int *pa_list = 0;
unsigned int pa, cnt;
+ void *flush_va;
unsigned int offset = 0, chunk_offset = 0;
int ret, scm_ret;
@@ -370,6 +457,7 @@
map.plist.list = virt_to_phys(&pa);
map.plist.list_size = 1;
map.plist.size = len;
+ flush_va = &pa;
} else {
sgiter = sg;
cnt = sg->length / SZ_1M;
@@ -400,8 +488,15 @@
map.plist.list = virt_to_phys(pa_list);
map.plist.list_size = cnt;
map.plist.size = SZ_1M;
+ flush_va = pa_list;
}
+ /*
+ * Ensure that the buffer is in RAM by the time it gets to TZ
+ */
+ clean_caches((unsigned long) flush_va,
+ map.plist.size * map.plist.list_size, virt_to_phys(flush_va));
+
ret = scm_call(SCM_SVC_MP, IOMMU_SECURE_MAP2, &map, sizeof(map),
&scm_ret, sizeof(scm_ret));
kfree(pa_list);
@@ -704,6 +799,9 @@
bus_set_iommu(&msm_iommu_sec_bus_type, &msm_iommu_ops);
ret = msm_iommu_sec_ptbl_init();
+ if (ret)
+ goto fail;
+ msm_iommu_sec_build_dump_regs_table();
fail:
return ret;
}
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index 6734da8..28e8092 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -1067,6 +1067,41 @@
wake_up_all(&cmdbuf->queue);
}
+static int dvb_dvr_external_input_only(struct dmxdev *dmxdev)
+{
+ struct dmx_caps caps;
+ int is_external_only;
+ int flags;
+ size_t tsp_size;
+
+ if (dmxdev->demux->get_tsp_size)
+ tsp_size = dmxdev->demux->get_tsp_size(dmxdev->demux);
+ else
+ tsp_size = 188;
+
+ /*
+ * For backward compatibility, default assumes that
+ * external only buffers are not supported.
+ */
+ flags = 0;
+ if (dmxdev->demux->get_caps) {
+ dmxdev->demux->get_caps(dmxdev->demux, &caps);
+
+ if (tsp_size == 188)
+ flags = caps.playback_188_tsp.flags;
+ else
+ flags = caps.playback_192_tsp.flags;
+ }
+
+ if (!(flags & DMX_BUFFER_INTERNAL_SUPPORT) &&
+ (flags & DMX_BUFFER_EXTERNAL_SUPPORT))
+ is_external_only = 1;
+ else
+ is_external_only = 0;
+
+ return is_external_only;
+}
+
static ssize_t dvb_dvr_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
@@ -1082,7 +1117,9 @@
return -EOPNOTSUPP;
if (((file->f_flags & O_ACCMODE) == O_RDONLY) ||
- (!src->data) || (!cmdbuf->data))
+ !src->data || !cmdbuf->data ||
+ (dvb_dvr_external_input_only(dmxdev) &&
+ (dmxdev->dvr_input_buffer_mode == DMX_BUFFER_MODE_INTERNAL)))
return -EINVAL;
if ((file->f_flags & O_NONBLOCK) &&
@@ -1238,7 +1275,7 @@
if (buf->size == size)
return 0;
- if ((!size) || (buffer_mode == DMX_BUFFER_MODE_EXTERNAL))
+ if (!size || (buffer_mode == DMX_BUFFER_MODE_EXTERNAL))
return -EINVAL;
newmem = vmalloc_user(size);
@@ -1282,10 +1319,6 @@
(mode != DMX_BUFFER_MODE_EXTERNAL))
return -EINVAL;
- if ((mode == DMX_BUFFER_MODE_INTERNAL) &&
- (dmxdev->capabilities & DMXDEV_CAP_EXTERNAL_BUFFS_ONLY))
- return -EINVAL;
-
if ((mode == DMX_BUFFER_MODE_EXTERNAL) &&
(!dmxdev->demux->map_buffer || !dmxdev->demux->unmap_buffer))
return -EINVAL;
@@ -1543,7 +1576,8 @@
if (buf->size == size)
return 0;
- if ((!size) || (dmxdevfilter->buffer_mode == DMX_BUFFER_MODE_EXTERNAL))
+ if (!size ||
+ (dmxdevfilter->buffer_mode == DMX_BUFFER_MODE_EXTERNAL))
return -EINVAL;
if (dmxdevfilter->state >= DMXDEV_STATE_GO)
return -EBUSY;
@@ -1580,10 +1614,6 @@
(mode != DMX_BUFFER_MODE_EXTERNAL))
return -EINVAL;
- if ((mode == DMX_BUFFER_MODE_INTERNAL) &&
- (dmxdev->capabilities & DMXDEV_CAP_EXTERNAL_BUFFS_ONLY))
- return -EINVAL;
-
if ((mode == DMX_BUFFER_MODE_EXTERNAL) &&
(!dmxdev->demux->map_buffer || !dmxdev->demux->unmap_buffer))
return -EINVAL;
@@ -1765,8 +1795,15 @@
int found_pid;
struct dmxdev_feed *feed;
struct dmxdev_feed *ts_feed = NULL;
+ struct dmx_caps caps;
+
+ if (!dmxdevfilter->dev->demux->get_caps)
+ return -EINVAL;
+
+ dmxdevfilter->dev->demux->get_caps(dmxdevfilter->dev->demux, &caps);
if (!idx_params ||
+ !(caps.caps & DMX_CAP_VIDEO_INDEXING) ||
(dmxdevfilter->state < DMXDEV_STATE_SET) ||
(dmxdevfilter->type != DMXDEV_TYPE_PES) ||
((dmxdevfilter->params.pes.output != DMX_OUT_TS_TAP) &&
@@ -1907,10 +1944,16 @@
int first_buffer;
struct dmxdev_feed *feed;
struct ts_insertion_buffer *ts_buffer;
+ struct dmx_caps caps;
+
+ if (!dmxdevfilter->dev->demux->get_caps)
+ return -EINVAL;
+
+ dmxdevfilter->dev->demux->get_caps(dmxdevfilter->dev->demux, &caps);
if (!params ||
!params->size ||
- !(dmxdevfilter->dev->capabilities & DMXDEV_CAP_TS_INSERTION) ||
+ !(caps.caps & DMX_CAP_TS_INSERTION) ||
(dmxdevfilter->state < DMXDEV_STATE_SET) ||
(dmxdevfilter->type != DMXDEV_TYPE_PES) ||
((dmxdevfilter->params.pes.output != DMX_OUT_TS_TAP) &&
@@ -1974,9 +2017,15 @@
int found_buffer;
struct dmxdev_feed *feed;
struct ts_insertion_buffer *ts_buffer, *tmp;
+ struct dmx_caps caps;
+
+ if (!dmxdevfilter->dev->demux->get_caps)
+ return -EINVAL;
+
+ dmxdevfilter->dev->demux->get_caps(dmxdevfilter->dev->demux, &caps);
if (!params ||
- !(dmxdevfilter->dev->capabilities & DMXDEV_CAP_TS_INSERTION) ||
+ !(caps.caps & DMX_CAP_TS_INSERTION) ||
(dmxdevfilter->state < DMXDEV_STATE_SET) ||
(dmxdevfilter->type != DMXDEV_TYPE_PES) ||
((dmxdevfilter->params.pes.output != DMX_OUT_TS_TAP) &&
@@ -2122,15 +2171,21 @@
enum dmx_playback_mode_t playback_mode)
{
struct dmxdev *dmxdev = dmxdevfilter->dev;
+ struct dmx_caps caps;
+
+ if (dmxdev->demux->get_caps)
+ dmxdev->demux->get_caps(dmxdev->demux, &caps);
+ else
+ caps.caps = 0;
if ((playback_mode != DMX_PB_MODE_PUSH) &&
(playback_mode != DMX_PB_MODE_PULL))
return -EINVAL;
if (((dmxdev->source < DMX_SOURCE_DVR0) ||
- !dmxdev->demux->set_playback_mode ||
- !(dmxdev->capabilities & DMXDEV_CAP_PULL_MODE)) &&
- (playback_mode == DMX_PB_MODE_PULL))
+ !dmxdev->demux->set_playback_mode ||
+ !(caps.caps & DMX_CAP_PULL_MODE)) &&
+ (playback_mode == DMX_PB_MODE_PULL))
return -EPERM;
if (dmxdevfilter->state == DMXDEV_STATE_GO)
@@ -3083,6 +3138,43 @@
return 0;
}
+static int dvb_filter_external_buffer_only(struct dmxdev *dmxdev,
+ struct dmxdev_filter *filter)
+{
+ struct dmx_caps caps;
+ int is_external_only;
+ int flags;
+
+ /*
+ * For backward compatibility, default assumes that
+ * external only buffers are not supported.
+ */
+ flags = 0;
+ if (dmxdev->demux->get_caps) {
+ dmxdev->demux->get_caps(dmxdev->demux, &caps);
+
+ if (filter->type == DMXDEV_TYPE_SEC)
+ flags = caps.section.flags;
+ else if (filter->params.pes.output == DMX_OUT_DECODER)
+ /* For decoder filters dmxdev buffer is not required */
+ flags = 0;
+ else if (filter->params.pes.output == DMX_OUT_TAP)
+ flags = caps.pes.flags;
+ else if (filter->dmx_tsp_format == DMX_TSP_FORMAT_188)
+ flags = caps.recording_188_tsp.flags;
+ else
+ flags = caps.recording_192_tsp.flags;
+ }
+
+ if (!(flags & DMX_BUFFER_INTERNAL_SUPPORT) &&
+ (flags & DMX_BUFFER_EXTERNAL_SUPPORT))
+ is_external_only = 1;
+ else
+ is_external_only = 0;
+
+ return is_external_only;
+}
+
static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
{
struct dmxdev *dmxdev = filter->dev;
@@ -3098,14 +3190,18 @@
if (!filter->buffer.data) {
if ((filter->buffer_mode == DMX_BUFFER_MODE_EXTERNAL) ||
- (dmxdev->capabilities & DMXDEV_CAP_EXTERNAL_BUFFS_ONLY))
+ dvb_filter_external_buffer_only(dmxdev, filter))
return -ENOMEM;
+
mem = vmalloc_user(filter->buffer.size);
if (!mem)
return -ENOMEM;
spin_lock_irq(&filter->dev->lock);
filter->buffer.data = mem;
spin_unlock_irq(&filter->dev->lock);
+ } else if ((filter->buffer_mode == DMX_BUFFER_MODE_INTERNAL) &&
+ dvb_filter_external_buffer_only(dmxdev, filter)) {
+ return -ENOMEM;
}
filter->eos_state = 0;
@@ -3577,10 +3673,13 @@
struct dmx_decoder_buffers *dec_buffs;
struct dmx_caps caps;
- if (NULL == dmxdev || NULL == filter || NULL == buffs)
+ if (!dmxdev || !filter || !buffs)
return -EINVAL;
dec_buffs = &filter->decoder_buffers;
+ if (!dmxdev->demux->get_caps)
+ return -EINVAL;
+
dmxdev->demux->get_caps(dmxdev->demux, &caps);
if ((buffs->buffers_size == 0) ||
diff --git a/drivers/media/dvb/dvb-core/dmxdev.h b/drivers/media/dvb/dvb-core/dmxdev.h
index 49e5e1b..4e306e8 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.h
+++ b/drivers/media/dvb/dvb-core/dmxdev.h
@@ -196,11 +196,6 @@
int filternum;
int capabilities;
#define DMXDEV_CAP_DUPLEX 0x01
-#define DMXDEV_CAP_PULL_MODE 0x02
-#define DMXDEV_CAP_INDEXING 0x04
-#define DMXDEV_CAP_EXTERNAL_BUFFS_ONLY 0x08
-#define DMXDEV_CAP_TS_INSERTION 0x10
-
enum dmx_playback_mode_t playback_mode;
dmx_source_t source;
diff --git a/drivers/media/platform/msm/camera_v2/Kconfig b/drivers/media/platform/msm/camera_v2/Kconfig
index 525a545..116fb72 100644
--- a/drivers/media/platform/msm/camera_v2/Kconfig
+++ b/drivers/media/platform/msm/camera_v2/Kconfig
@@ -137,6 +137,15 @@
hfr video at 60, 90 and 120 fps. This sensor driver does
not support auto focus.
+config HI256
+ bool "Hynix hi256 (YUV 2MP)"
+ depends on MSMB_CAMERA
+ ---help---
+ OmniVision 8 MP Bayer Sensor with auto focus.uses
+ 2 mipi lanes, preview config = 1632*1224 30 fps,
+ snapshot config = 3264 * 2448 at 18 fps.
+ 2 lanes max fps is 18, 4 lanes max fps is 24.
+
config MT9M114
bool "Sensor MT9M114 (YUV 1.26MP)"
depends on MSMB_CAMERA
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
index 84ba4d1..2ff70d3 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
@@ -32,6 +32,7 @@
#define VFE40_8974V1_VERSION 0x10000018
#define VFE40_8974V2_VERSION 0x1001001A
+#define VFE40_8974V3_VERSION 0x1001001B
#define VFE40_8x26_VERSION 0x20000013
#define VFE40_BURST_LEN 3
@@ -102,7 +103,8 @@
msm_camera_io_w(0xAAAAAAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_5);
msm_camera_io_w(0xAAAAAAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_6);
msm_camera_io_w(0x0002AAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_7);
- } else if (vfe_dev->vfe_hw_version == VFE40_8974V2_VERSION) {
+ } else if (vfe_dev->vfe_hw_version == VFE40_8974V2_VERSION ||
+ vfe_dev->vfe_hw_version == VFE40_8974V3_VERSION) {
msm_camera_io_w(0xAAA9AAA9, vfebase + VFE40_BUS_BDG_QOS_CFG_0);
msm_camera_io_w(0xAAA9AAA9, vfebase + VFE40_BUS_BDG_QOS_CFG_1);
msm_camera_io_w(0xAAA9AAA9, vfebase + VFE40_BUS_BDG_QOS_CFG_2);
@@ -231,6 +233,7 @@
msm_vfe40_init_vbif_parms_8974_v1(vfe_dev);
break;
case VFE40_8974V2_VERSION:
+ case VFE40_8974V3_VERSION:
msm_vfe40_init_vbif_parms_8974_v2(vfe_dev);
break;
case VFE40_8x26_VERSION:
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
index e74f1082..c79e8e3 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
@@ -698,11 +698,9 @@
iounmap(cpp_dev->cpp_hw_base);
msm_cam_clk_enable(&cpp_dev->pdev->dev, cpp_clk_info,
cpp_dev->cpp_clk, ARRAY_SIZE(cpp_clk_info), 0);
- if (0) {
- regulator_disable(cpp_dev->fs_cpp);
- regulator_put(cpp_dev->fs_cpp);
- cpp_dev->fs_cpp = NULL;
- }
+ regulator_disable(cpp_dev->fs_cpp);
+ regulator_put(cpp_dev->fs_cpp);
+ cpp_dev->fs_cpp = NULL;
msm_isp_update_bandwidth(ISP_CPP, 0, 0);
msm_isp_deinit_bandwidth_mgr(ISP_CPP);
}
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tsif.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tsif.c
index 29369de..ef3f57f 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tsif.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tsif.c
@@ -548,7 +548,8 @@
return -EINVAL;
}
- caps->caps = DMX_CAP_PULL_MODE | DMX_CAP_VIDEO_DECODER_DATA;
+ caps->caps = DMX_CAP_PULL_MODE | DMX_CAP_VIDEO_DECODER_DATA |
+ DMX_CAP_TS_INSERTION | DMX_CAP_VIDEO_INDEXING;
caps->num_decoders = MPQ_ADAPTER_MAX_NUM_OF_INTERFACES;
caps->num_demux_devices = CONFIG_DVB_MPQ_NUM_DMX_DEVICES;
caps->num_pid_filters = dvb_demux->feednum;
@@ -599,7 +600,6 @@
caps->playback_192_tsp.max_size = 0xFFFFFFFF;
caps->playback_192_tsp.size_alignment = 0;
caps->decoder.flags =
- DMX_BUFFER_CONTIGUOUS_MEM |
DMX_BUFFER_SECURED_IF_DECRYPTED |
DMX_BUFFER_EXTERNAL_SUPPORT |
DMX_BUFFER_INTERNAL_SUPPORT |
@@ -700,11 +700,7 @@
/* Now initailize the dmx-dev object */
mpq_demux->dmxdev.filternum = MPQ_MAX_DMX_FILES;
mpq_demux->dmxdev.demux = &mpq_demux->demux.dmx;
- mpq_demux->dmxdev.capabilities =
- DMXDEV_CAP_DUPLEX |
- DMXDEV_CAP_PULL_MODE |
- DMXDEV_CAP_INDEXING |
- DMXDEV_CAP_TS_INSERTION;
+ mpq_demux->dmxdev.capabilities = DMXDEV_CAP_DUPLEX;
mpq_demux->dmxdev.demux->set_source = mpq_dmx_set_source;
mpq_demux->dmxdev.demux->get_stc = mpq_tsif_dmx_get_stc;
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
index a2ce428..8e628f6 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
@@ -1614,7 +1614,8 @@
return -EINVAL;
}
- caps->caps = DMX_CAP_PULL_MODE | DMX_CAP_VIDEO_DECODER_DATA;
+ caps->caps = DMX_CAP_PULL_MODE | DMX_CAP_VIDEO_DECODER_DATA |
+ DMX_CAP_TS_INSERTION | DMX_CAP_VIDEO_INDEXING;
caps->num_decoders = MPQ_ADAPTER_MAX_NUM_OF_INTERFACES;
caps->num_demux_devices = CONFIG_DVB_MPQ_NUM_DMX_DEVICES;
caps->num_pid_filters = TSPP_MAX_PID_FILTER_NUM;
@@ -1623,9 +1624,9 @@
caps->section_filter_length = DMX_FILTER_SIZE;
caps->num_demod_inputs = TSIF_COUNT;
caps->num_memory_inputs = CONFIG_DVB_MPQ_NUM_DMX_DEVICES;
- caps->max_bitrate = 144;
- caps->demod_input_max_bitrate = 72;
- caps->memory_input_max_bitrate = 72;
+ caps->max_bitrate = 192;
+ caps->demod_input_max_bitrate = 96;
+ caps->memory_input_max_bitrate = 96;
/* Buffer requirements */
caps->section.flags =
@@ -1665,7 +1666,6 @@
caps->playback_192_tsp.max_size = 0xFFFFFFFF;
caps->playback_192_tsp.size_alignment = 0;
caps->decoder.flags =
- DMX_BUFFER_CONTIGUOUS_MEM |
DMX_BUFFER_SECURED_IF_DECRYPTED |
DMX_BUFFER_EXTERNAL_SUPPORT |
DMX_BUFFER_INTERNAL_SUPPORT |
@@ -1758,11 +1758,7 @@
/* Now initailize the dmx-dev object */
mpq_demux->dmxdev.filternum = MPQ_MAX_DMX_FILES;
mpq_demux->dmxdev.demux = &mpq_demux->demux.dmx;
- mpq_demux->dmxdev.capabilities =
- DMXDEV_CAP_DUPLEX |
- DMXDEV_CAP_PULL_MODE |
- DMXDEV_CAP_INDEXING |
- DMXDEV_CAP_TS_INSERTION;
+ mpq_demux->dmxdev.capabilities = DMXDEV_CAP_DUPLEX;
mpq_demux->dmxdev.demux->set_source = mpq_dmx_set_source;
mpq_demux->dmxdev.demux->get_stc = mpq_tspp_dmx_get_stc;
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v2.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v2.c
index 60e3cb4..1ab9da1 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v2.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v2.c
@@ -73,7 +73,7 @@
}
caps->caps = DMX_CAP_PULL_MODE | DMX_CAP_VIDEO_INDEXING |
- DMX_CAP_VIDEO_DECODER_DATA;
+ DMX_CAP_VIDEO_DECODER_DATA | DMX_CAP_TS_INSERTION;
caps->num_decoders = MPQ_ADAPTER_MAX_NUM_OF_INTERFACES;
caps->num_demux_devices = CONFIG_DVB_MPQ_NUM_DMX_DEVICES;
caps->num_pid_filters = TSPP_MAX_PID_FILTER_NUM;
@@ -140,11 +140,7 @@
/* Now initailize the dmx-dev object */
mpq_demux->dmxdev.filternum = MPQ_MAX_DMX_FILES;
mpq_demux->dmxdev.demux = &mpq_demux->demux.dmx;
- mpq_demux->dmxdev.capabilities =
- DMXDEV_CAP_DUPLEX |
- DMXDEV_CAP_PULL_MODE |
- DMXDEV_CAP_INDEXING |
- DMXDEV_CAP_TS_INSERTION;
+ mpq_demux->dmxdev.capabilities = DMXDEV_CAP_DUPLEX;
mpq_demux->dmxdev.demux->set_source = mpq_dmx_set_source;
mpq_demux->dmxdev.demux->get_caps = mpq_tspp_dmx_get_caps;
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
index ac2ecbb..a990f43 100644
--- a/drivers/mmc/core/bus.c
+++ b/drivers/mmc/core/bus.c
@@ -128,6 +128,16 @@
struct mmc_driver *drv = to_mmc_driver(dev->driver);
struct mmc_card *card = mmc_dev_to_card(dev);
+ if (!drv) {
+ pr_debug("%s: %s: drv is NULL\n", dev_name(dev), __func__);
+ return;
+ }
+
+ if (!card) {
+ pr_debug("%s: %s: card is NULL\n", dev_name(dev), __func__);
+ return;
+ }
+
if (drv->shutdown)
drv->shutdown(card);
}
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index c73bf01..c86eef8 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -512,19 +512,25 @@
int rc = 0;
unsigned long flags;
u32 wait_cnt;
+ bool prev_pwrsave, curr_pwrsave;
pr_debug("%s: Enter %s\n", mmc_hostname(mmc), __func__);
spin_lock_irqsave(&host->lock, flags);
-
+ prev_pwrsave = !!(readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC) &
+ CORE_CLK_PWRSAVE);
+ curr_pwrsave = prev_pwrsave;
/*
* Make sure that clock is always enabled when DLL
* tuning is in progress. Keeping PWRSAVE ON may
* turn off the clock. So let's disable the PWRSAVE
* here and re-enable it once tuning is completed.
*/
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC)
- & ~CORE_CLK_PWRSAVE),
- host->ioaddr + CORE_VENDOR_SPEC);
+ if (prev_pwrsave) {
+ writel_relaxed((readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC)
+ & ~CORE_CLK_PWRSAVE),
+ host->ioaddr + CORE_VENDOR_SPEC);
+ curr_pwrsave = false;
+ }
/* Write 1 to DLL_RST bit of DLL_CONFIG register */
writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
@@ -567,10 +573,18 @@
}
out:
- /* re-enable PWRSAVE */
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC) |
- CORE_CLK_PWRSAVE),
- host->ioaddr + CORE_VENDOR_SPEC);
+ /* Restore the correct PWRSAVE state */
+ if (prev_pwrsave ^ curr_pwrsave) {
+ u32 reg = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
+
+ if (prev_pwrsave)
+ reg |= CORE_CLK_PWRSAVE;
+ else
+ reg &= ~CORE_CLK_PWRSAVE;
+
+ writel_relaxed(reg, host->ioaddr + CORE_VENDOR_SPEC);
+ }
+
spin_unlock_irqrestore(&host->lock, flags);
pr_debug("%s: Exit %s\n", mmc_hostname(mmc), __func__);
return rc;
@@ -2405,6 +2419,7 @@
msm_host->mmc->caps2 |= MMC_CAP2_POWEROFF_NOTIFY;
msm_host->mmc->caps2 |= MMC_CAP2_CLK_SCALE;
msm_host->mmc->caps2 |= MMC_CAP2_STOP_REQUEST;
+ msm_host->mmc->caps2 |= MMC_CAP2_ASYNC_SDIO_IRQ_4BIT_MODE;
if (msm_host->pdata->nonremovable)
msm_host->mmc->caps |= MMC_CAP_NONREMOVABLE;
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index 6586299..0b4f0fe 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -706,7 +706,7 @@
static int __devinit
wcnss_wlan_ctrl_probe(struct platform_device *pdev)
{
- if (!penv)
+ if (!penv || !penv->triggered)
return -ENODEV;
penv->smd_channel_ready = 1;
@@ -761,7 +761,7 @@
{
int ret = 0;
- if (!penv)
+ if (!penv || !penv->triggered)
return -ENODEV;
ret = smd_named_open_on_edge(WCNSS_CTRL_CHANNEL, SMD_APPS_WCNSS,
@@ -1604,15 +1604,6 @@
goto fail_power;
}
- /* trigger initialization of the WCNSS */
- penv->pil = subsystem_get(WCNSS_PIL_DEVICE);
- if (IS_ERR(penv->pil)) {
- dev_err(&pdev->dev, "Peripheral Loader failed on WCNSS.\n");
- ret = PTR_ERR(penv->pil);
- penv->pil = NULL;
- goto fail_pil;
- }
-
/* allocate resources */
penv->mmio_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"wcnss_mmio");
@@ -1644,7 +1635,7 @@
if (!penv->msm_wcnss_base) {
ret = -ENOMEM;
pr_err("%s: ioremap wcnss physical failed\n", __func__);
- goto fail_wake;
+ goto fail_ioremap;
}
if (wcnss_hardware_type() == WCNSS_RIVA_HW) {
@@ -1652,20 +1643,20 @@
if (!penv->riva_ccu_base) {
ret = -ENOMEM;
pr_err("%s: ioremap wcnss physical failed\n", __func__);
- goto fail_ioremap;
+ goto fail_ioremap2;
}
} else {
penv->pronto_a2xb_base = ioremap(MSM_PRONTO_A2XB_BASE, SZ_512);
if (!penv->pronto_a2xb_base) {
ret = -ENOMEM;
pr_err("%s: ioremap wcnss physical failed\n", __func__);
- goto fail_ioremap;
+ goto fail_ioremap2;
}
penv->pronto_ccpu_base = ioremap(MSM_PRONTO_CCPU_BASE, SZ_512);
if (!penv->pronto_ccpu_base) {
ret = -ENOMEM;
pr_err("%s: ioremap wcnss physical failed\n", __func__);
- goto fail_ioremap2;
+ goto fail_ioremap3;
}
/* for reset FIQ */
res = platform_get_resource_byname(penv->pdev,
@@ -1673,31 +1664,45 @@
if (!res) {
dev_err(&pdev->dev, "insufficient irq mem resources\n");
ret = -ENOENT;
- goto fail_ioremap3;
+ goto fail_ioremap4;
}
penv->fiq_reg = ioremap_nocache(res->start, resource_size(res));
if (!penv->fiq_reg) {
pr_err("wcnss: %s: ioremap_nocache() failed fiq_reg addr:%pr\n",
__func__, &res->start);
ret = -ENOMEM;
- goto fail_ioremap3;
+ goto fail_ioremap4;
}
}
+ /* trigger initialization of the WCNSS */
+ penv->pil = subsystem_get(WCNSS_PIL_DEVICE);
+ if (IS_ERR(penv->pil)) {
+ dev_err(&pdev->dev, "Peripheral Loader failed on WCNSS.\n");
+ ret = PTR_ERR(penv->pil);
+ penv->pil = NULL;
+ goto fail_pil;
+ }
+
return 0;
+fail_pil:
+ if (penv->riva_ccu_base)
+ iounmap(penv->riva_ccu_base);
+ if (penv->fiq_reg)
+ iounmap(penv->fiq_reg);
+fail_ioremap4:
+ if (penv->pronto_ccpu_base)
+ iounmap(penv->pronto_ccpu_base);
fail_ioremap3:
- iounmap(penv->pronto_ccpu_base);
+ if (penv->pronto_a2xb_base)
+ iounmap(penv->pronto_a2xb_base);
fail_ioremap2:
- iounmap(penv->pronto_a2xb_base);
+ if (penv->msm_wcnss_base)
+ iounmap(penv->msm_wcnss_base);
fail_ioremap:
- iounmap(penv->msm_wcnss_base);
-fail_wake:
wake_lock_destroy(&penv->wcnss_wake_lock);
fail_res:
- if (penv->pil)
- subsystem_put(penv->pil);
-fail_pil:
wcnss_wlan_power(&pdev->dev, &penv->wlan_config,
WCNSS_WLAN_SWITCH_OFF);
fail_power:
diff --git a/drivers/platform/msm/ipa/a2_service.c b/drivers/platform/msm/ipa/a2_service.c
index 0d77741..8e79185 100644
--- a/drivers/platform/msm/ipa/a2_service.c
+++ b/drivers/platform/msm/ipa/a2_service.c
@@ -278,7 +278,8 @@
A2_MUX_COMPLETION_TIMEOUT);
a2_mux_ctx->wait_for_ack = 0;
if (unlikely(ret == 0)) {
- IPADBG("%s timeout previous ack\n", __func__);
+ IPAERR("%s previous ack from modem timed out\n",
+ __func__);
goto bail;
}
}
@@ -288,7 +289,7 @@
ret = wait_for_completion_timeout(&a2_mux_ctx->ul_wakeup_ack_completion,
A2_MUX_COMPLETION_TIMEOUT);
if (unlikely(ret == 0)) {
- IPADBG("%s timeout wakeup ack\n", __func__);
+ IPAERR("%s wakup ack from modem timed out\n", __func__);
goto bail;
}
INIT_COMPLETION(a2_mux_ctx->bam_connection_completion);
@@ -297,7 +298,7 @@
&a2_mux_ctx->bam_connection_completion,
A2_MUX_COMPLETION_TIMEOUT);
if (unlikely(ret == 0)) {
- IPADBG("%s timeout power on\n", __func__);
+ IPAERR("%s modem power on timed out\n", __func__);
goto bail;
}
}
@@ -450,7 +451,8 @@
&a2_mux_ctx->dl_wakeup_completion,
A2_MUX_COMPLETION_TIMEOUT);
if (unlikely(ret == 0)) {
- IPAERR("%s timeout A2 PROD\n", __func__);
+ IPAERR("%s timeout waiting for A2 PROD granted\n",
+ __func__);
BUG();
return;
}
@@ -475,8 +477,8 @@
&a2_mux_ctx->request_resource_completion,
A2_MUX_COMPLETION_TIMEOUT);
if (unlikely(ret == 0)) {
- IPADBG("%s timeout request A2 PROD resource\n",
- __func__);
+ IPAERR("%s timeout waiting for A2 PROD granted\n",
+ __func__);
BUG();
return;
}
diff --git a/drivers/platform/msm/ipa/ipa.c b/drivers/platform/msm/ipa/ipa.c
index f4ad172..1cbd514 100644
--- a/drivers/platform/msm/ipa/ipa.c
+++ b/drivers/platform/msm/ipa/ipa.c
@@ -50,7 +50,6 @@
#define IPA_AGGR_STR_IN_BYTES(str) \
(strnlen((str), IPA_AGGR_MAX_STR_LENGTH - 1) + 1)
-
static struct ipa_plat_drv_res ipa_res = {0, };
static struct of_device_id ipa_plat_drv_match[] = {
{
@@ -1735,6 +1734,22 @@
result = -ENOMEM;
goto fail_rt_tbl_cache;
}
+ ipa_ctx->tx_pkt_wrapper_cache =
+ kmem_cache_create("IPA TX PKT WRAPPER",
+ sizeof(struct ipa_tx_pkt_wrapper), 0, 0, NULL);
+ if (!ipa_ctx->tx_pkt_wrapper_cache) {
+ IPAERR(":ipa tx pkt wrapper cache create failed\n");
+ result = -ENOMEM;
+ goto fail_tx_pkt_wrapper_cache;
+ }
+ ipa_ctx->rx_pkt_wrapper_cache =
+ kmem_cache_create("IPA RX PKT WRAPPER",
+ sizeof(struct ipa_rx_pkt_wrapper), 0, 0, NULL);
+ if (!ipa_ctx->rx_pkt_wrapper_cache) {
+ IPAERR(":ipa rx pkt wrapper cache create failed\n");
+ result = -ENOMEM;
+ goto fail_rx_pkt_wrapper_cache;
+ }
ipa_ctx->tree_node_cache =
kmem_cache_create("IPA TREE", sizeof(struct ipa_tree_node), 0, 0,
NULL);
@@ -1803,8 +1818,6 @@
mutex_init(&ipa_ctx->lock);
mutex_init(&ipa_ctx->nat_mem.lock);
- skb_queue_head_init(&ipa_ctx->rx_list);
-
for (i = 0; i < IPA_A5_SYS_MAX; i++) {
INIT_LIST_HEAD(&ipa_ctx->sys[i].head_desc_list);
spin_lock_init(&ipa_ctx->sys[i].spinlock);
@@ -1818,15 +1831,15 @@
atomic_set(&ipa_ctx->sys[i].curr_polling_state, 0);
}
- ipa_ctx->rx_wq = alloc_workqueue("ipa rx wq", WQ_MEM_RECLAIM |
- WQ_CPU_INTENSIVE, 1);
+ ipa_ctx->rx_wq = create_singlethread_workqueue("ipa rx wq");
if (!ipa_ctx->rx_wq) {
IPAERR(":fail to create rx wq\n");
result = -ENOMEM;
goto fail_rx_wq;
}
- ipa_ctx->tx_wq = create_singlethread_workqueue("ipa tx wq");
+ ipa_ctx->tx_wq = alloc_workqueue("ipa tx wq", WQ_MEM_RECLAIM |
+ WQ_CPU_INTENSIVE, 2);
if (!ipa_ctx->tx_wq) {
IPAERR(":fail to create tx wq\n");
result = -ENOMEM;
@@ -1979,6 +1992,10 @@
fail_dma_pool:
kmem_cache_destroy(ipa_ctx->tree_node_cache);
fail_tree_node_cache:
+ kmem_cache_destroy(ipa_ctx->rx_pkt_wrapper_cache);
+fail_rx_pkt_wrapper_cache:
+ kmem_cache_destroy(ipa_ctx->tx_pkt_wrapper_cache);
+fail_tx_pkt_wrapper_cache:
kmem_cache_destroy(ipa_ctx->rt_tbl_cache);
fail_rt_tbl_cache:
kmem_cache_destroy(ipa_ctx->hdr_offset_cache);
diff --git a/drivers/platform/msm/ipa/ipa_client.c b/drivers/platform/msm/ipa/ipa_client.c
index ae59f37..5c343e8 100644
--- a/drivers/platform/msm/ipa/ipa_client.c
+++ b/drivers/platform/msm/ipa/ipa_client.c
@@ -9,7 +9,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
-
#include <linux/delay.h>
#include "ipa_i.h"
@@ -251,26 +250,6 @@
memset(&ipa_ctx->ep[ipa_ep_idx], 0, sizeof(struct ipa_ep_context));
- if (IPA_CLIENT_IS_CONS(in->client)) {
- ep->cmd = kzalloc(sizeof(struct ipa_ip_packet_init),
- GFP_KERNEL);
- if (!ep->cmd) {
- IPAERR("failed to alloc immediate command object\n");
- result = -ENOMEM;
- goto fail;
- }
- ep->cmd->destination_pipe_index = ipa_ep_idx;
- ep->dma_addr = dma_map_single(NULL, ep->cmd,
- sizeof(struct ipa_ip_packet_init),
- DMA_TO_DEVICE);
- if (ep->dma_addr == 0 || ep->dma_addr == ~0) {
- IPAERR("failed to DMA MAP pkt_init\n");
- result = -ENOMEM;
- kfree(ep->cmd);
- goto fail;
- }
- }
-
ep->valid = 1;
ep->client = in->client;
ep->client_notify = in->notify;
@@ -447,13 +426,6 @@
return -EPERM;
}
- if (IPA_CLIENT_IS_CONS(ep->client)) {
- dma_unmap_single(NULL, ep->dma_addr,
- sizeof(struct ipa_ip_packet_init),
- DMA_TO_DEVICE);
- kfree(ep->cmd);
- }
-
ipa_enable_data_path(clnt_hdl);
memset(&ipa_ctx->ep[clnt_hdl], 0, sizeof(struct ipa_ep_context));
diff --git a/drivers/platform/msm/ipa/ipa_dp.c b/drivers/platform/msm/ipa/ipa_dp.c
index c564922..38a1a9c 100644
--- a/drivers/platform/msm/ipa/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_dp.c
@@ -17,23 +17,21 @@
#include <linux/netdevice.h>
#include "ipa_i.h"
+
#define list_next_entry(pos, member) \
list_entry(pos->member.next, typeof(*pos), member)
+#define IPA_LAST_DESC_CNT 0xFFFF
#define POLLING_INACTIVITY_RX 40
-#define POLLING_MIN_SLEEP_RX 2350
-#define POLLING_MAX_SLEEP_RX 2450
-#define POLLING_INACTIVITY_TX 10
-#define POLLING_MIN_SLEEP_TX 100
-#define POLLING_MAX_SLEEP_TX 200
-#define RX_MAX_IND 40
+#define POLLING_MIN_SLEEP_RX 950
+#define POLLING_MAX_SLEEP_RX 1050
+#define POLLING_INACTIVITY_TX 40
+#define POLLING_MIN_SLEEP_TX 400
+#define POLLING_MAX_SLEEP_TX 500
static void replenish_rx_work_func(struct work_struct *work);
static struct delayed_work replenish_rx_work;
static void ipa_wq_handle_rx(struct work_struct *work);
static DECLARE_WORK(rx_work, ipa_wq_handle_rx);
-static void ipa_wq_handle_tx(struct work_struct *work);
-static DECLARE_WORK(tx_work, ipa_wq_handle_tx);
-
/**
* ipa_write_done() - this function will be (eventually) called when a Tx
* operation is complete
@@ -83,7 +81,7 @@
if (tx_pkt->callback)
tx_pkt->callback(tx_pkt->user1, tx_pkt->user2);
- kfree(tx_pkt);
+ kmem_cache_free(ipa_ctx->tx_pkt_wrapper_cache, tx_pkt);
}
int ipa_handle_tx_core(struct ipa_sys_context *sys, bool process_all,
@@ -121,13 +119,23 @@
IPADBG("--curr_cnt=%d\n", sys->len);
- if (tx_pkt->callback) {
+ if (unlikely(ipa_ctx->ipa_hw_type == IPA_HW_v1_0))
+ dma_pool_free(ipa_ctx->dma_pool,
+ tx_pkt->bounce,
+ tx_pkt->mem.phys_base);
+ else
dma_unmap_single(NULL, tx_pkt->mem.phys_base,
- tx_pkt->mem.size, DMA_TO_DEVICE);
- tx_pkt->callback(tx_pkt->user1, tx_pkt->user2);
- }
+ tx_pkt->mem.size,
+ DMA_TO_DEVICE);
- kfree(tx_pkt);
+ if (tx_pkt->callback)
+ tx_pkt->callback(tx_pkt->user1, tx_pkt->user2);
+
+ if (tx_pkt->cnt > 1 && tx_pkt->cnt != IPA_LAST_DESC_CNT)
+ dma_pool_free(ipa_ctx->dma_pool, tx_pkt->mult.base,
+ tx_pkt->mult.phys_base);
+
+ kmem_cache_free(ipa_ctx->tx_pkt_wrapper_cache, tx_pkt);
cnt++;
};
@@ -146,6 +154,11 @@
goto fail;
}
+ ret = sps_get_config(sys->ep->ep_hdl, &sys->ep->connect);
+ if (ret) {
+ IPAERR("sps_get_config() failed %d\n", ret);
+ goto fail;
+ }
sys->event.options = SPS_O_EOT;
ret = sps_register_event(sys->ep->ep_hdl, &sys->event);
if (ret) {
@@ -192,7 +205,9 @@
static void ipa_wq_handle_tx(struct work_struct *work)
{
- ipa_handle_tx(&ipa_ctx->sys[IPA_A5_LAN_WAN_OUT]);
+ struct ipa_tx_pkt_wrapper *tx_pkt;
+ tx_pkt = container_of(work, struct ipa_tx_pkt_wrapper, work);
+ ipa_handle_tx(tx_pkt->sys);
}
/**
@@ -225,7 +240,7 @@
if (unlikely(!in_atomic))
mem_flag = GFP_KERNEL;
- tx_pkt = kmalloc(sizeof(struct ipa_tx_pkt_wrapper), mem_flag);
+ tx_pkt = kmem_cache_zalloc(ipa_ctx->tx_pkt_wrapper_cache, mem_flag);
if (!tx_pkt) {
IPAERR("failed to alloc tx wrapper\n");
goto fail_mem_alloc;
@@ -281,11 +296,14 @@
IPADBG("sending cmd=%d pyld_len=%d sps_flags=%x\n",
desc->opcode, desc->len, sps_flags);
IPA_DUMP_BUFF(desc->pyld, dma_address, desc->len);
+ INIT_WORK(&tx_pkt->work, ipa_wq_write_done);
} else {
len = desc->len;
+ INIT_WORK(&tx_pkt->work, ipa_wq_handle_tx);
}
- INIT_WORK(&tx_pkt->work, ipa_wq_write_done);
+ if (unlikely(ipa_ctx->polling_mode))
+ INIT_WORK(&tx_pkt->work, ipa_wq_handle_tx);
spin_lock_irqsave(&sys->spinlock, irq_flags);
list_add_tail(&tx_pkt->link, &sys->head_desc_list);
@@ -309,12 +327,192 @@
else
dma_unmap_single(NULL, dma_address, desc->len, DMA_TO_DEVICE);
fail_dma_map:
- kfree(tx_pkt);
+ kmem_cache_free(ipa_ctx->tx_pkt_wrapper_cache, tx_pkt);
fail_mem_alloc:
return -EFAULT;
}
/**
+ * ipa_send() - Send multiple descriptors in one HW transaction
+ * @sys: system pipe context
+ * @num_desc: number of packets
+ * @desc: packets to send (may be immediate command or data)
+ * @in_atomic: whether caller is in atomic context
+ *
+ * This function is used for system-to-bam connection.
+ * - SPS driver expect struct sps_transfer which will contain all the data
+ * for a transaction
+ * - The sps_transfer struct will be pointing to bounce buffers for
+ * its DMA command (immediate command and data)
+ * - ipa_tx_pkt_wrapper will be used for each ipa
+ * descriptor (allocated from wrappers cache)
+ * - The wrapper struct will be configured for each ipa-desc payload and will
+ * contain information which will be later used by the user callbacks
+ * - each transfer will be made by calling to sps_transfer()
+ * - Each packet (command or data) that will be sent will also be saved in
+ * ipa_sys_context for later check that all data was sent
+ *
+ * Return codes: 0: success, -EFAULT: failure
+ */
+int ipa_send(struct ipa_sys_context *sys, u32 num_desc, struct ipa_desc *desc,
+ bool in_atomic)
+{
+ struct ipa_tx_pkt_wrapper *tx_pkt;
+ struct ipa_tx_pkt_wrapper *next_pkt;
+ struct sps_transfer transfer = { 0 };
+ struct sps_iovec *iovec;
+ unsigned long irq_flags;
+ dma_addr_t dma_addr;
+ int i = 0;
+ int j;
+ int result;
+ int fail_dma_wrap = 0;
+ uint size = num_desc * sizeof(struct sps_iovec);
+ u32 mem_flag = GFP_ATOMIC;
+
+ if (unlikely(!in_atomic))
+ mem_flag = GFP_KERNEL;
+
+ transfer.iovec = dma_pool_alloc(ipa_ctx->dma_pool, mem_flag, &dma_addr);
+ transfer.iovec_phys = dma_addr;
+ transfer.iovec_count = num_desc;
+ spin_lock_irqsave(&sys->spinlock, irq_flags);
+ if (!transfer.iovec) {
+ IPAERR("fail to alloc DMA mem for sps xfr buff\n");
+ goto failure_coherent;
+ }
+
+ for (i = 0; i < num_desc; i++) {
+ fail_dma_wrap = 0;
+ tx_pkt = kmem_cache_zalloc(ipa_ctx->tx_pkt_wrapper_cache,
+ mem_flag);
+ if (!tx_pkt) {
+ IPAERR("failed to alloc tx wrapper\n");
+ goto failure;
+ }
+ /*
+ * first desc of set is "special" as it holds the count and
+ * other info
+ */
+ if (i == 0) {
+ transfer.user = tx_pkt;
+ tx_pkt->mult.phys_base = dma_addr;
+ tx_pkt->mult.base = transfer.iovec;
+ tx_pkt->mult.size = size;
+ tx_pkt->cnt = num_desc;
+ }
+ INIT_WORK(&tx_pkt->work, ipa_wq_handle_tx);
+
+ iovec = &transfer.iovec[i];
+ iovec->flags = 0;
+
+ INIT_LIST_HEAD(&tx_pkt->link);
+ tx_pkt->type = desc[i].type;
+
+ tx_pkt->mem.base = desc[i].pyld;
+ tx_pkt->mem.size = desc[i].len;
+
+ if (unlikely(ipa_ctx->ipa_hw_type == IPA_HW_v1_0)) {
+ WARN_ON(tx_pkt->mem.size > 512);
+
+ /*
+ * Due to a HW limitation, we need to make sure that the
+ * packet does not cross a 1KB boundary
+ */
+ tx_pkt->bounce =
+ dma_pool_alloc(ipa_ctx->dma_pool,
+ mem_flag,
+ &tx_pkt->mem.phys_base);
+ if (!tx_pkt->bounce) {
+ tx_pkt->mem.phys_base = 0;
+ } else {
+ WARN_ON(!ipa_straddle_boundary(
+ (u32)tx_pkt->mem.phys_base,
+ (u32)tx_pkt->mem.phys_base +
+ tx_pkt->mem.size - 1, 1024));
+ memcpy(tx_pkt->bounce, tx_pkt->mem.base,
+ tx_pkt->mem.size);
+ }
+ } else {
+ tx_pkt->mem.phys_base =
+ dma_map_single(NULL, tx_pkt->mem.base,
+ tx_pkt->mem.size,
+ DMA_TO_DEVICE);
+ }
+ if (!tx_pkt->mem.phys_base) {
+ IPAERR("failed to alloc tx wrapper\n");
+ fail_dma_wrap = 1;
+ goto failure;
+ }
+
+ tx_pkt->sys = sys;
+ tx_pkt->callback = desc[i].callback;
+ tx_pkt->user1 = desc[i].user1;
+ tx_pkt->user2 = desc[i].user2;
+
+ /*
+ * Point the iovec to the bounce buffer and
+ * add this packet to system pipe context.
+ */
+ iovec->addr = tx_pkt->mem.phys_base;
+ list_add_tail(&tx_pkt->link, &sys->head_desc_list);
+
+ /*
+ * Special treatment for immediate commands, where the structure
+ * of the descriptor is different
+ */
+ if (desc[i].type == IPA_IMM_CMD_DESC) {
+ iovec->size = desc[i].opcode;
+ iovec->flags |= SPS_IOVEC_FLAG_IMME;
+ } else {
+ iovec->size = desc[i].len;
+ }
+
+ if (i == (num_desc - 1)) {
+ iovec->flags |= SPS_IOVEC_FLAG_EOT;
+ /* "mark" the last desc */
+ tx_pkt->cnt = IPA_LAST_DESC_CNT;
+ }
+ }
+
+ result = sps_transfer(sys->ep->ep_hdl, &transfer);
+ if (result) {
+ IPAERR("sps_transfer failed rc=%d\n", result);
+ goto failure;
+ }
+
+ spin_unlock_irqrestore(&sys->spinlock, irq_flags);
+ return 0;
+
+failure:
+ tx_pkt = transfer.user;
+ for (j = 0; j < i; j++) {
+ next_pkt = list_next_entry(tx_pkt, link);
+ list_del(&tx_pkt->link);
+ if (unlikely(ipa_ctx->ipa_hw_type == IPA_HW_v1_0))
+ dma_pool_free(ipa_ctx->dma_pool,
+ tx_pkt->bounce,
+ tx_pkt->mem.phys_base);
+ else
+ dma_unmap_single(NULL, tx_pkt->mem.phys_base,
+ tx_pkt->mem.size,
+ DMA_TO_DEVICE);
+ kmem_cache_free(ipa_ctx->tx_pkt_wrapper_cache, tx_pkt);
+ tx_pkt = next_pkt;
+ }
+ if (i < num_desc)
+ /* last desc failed */
+ if (fail_dma_wrap)
+ kmem_cache_free(ipa_ctx->tx_pkt_wrapper_cache, tx_pkt);
+ if (transfer.iovec_phys)
+ dma_pool_free(ipa_ctx->dma_pool, transfer.iovec,
+ transfer.iovec_phys);
+failure_coherent:
+ spin_unlock_irqrestore(&sys->spinlock, irq_flags);
+ return -EFAULT;
+}
+
+/**
* ipa_sps_irq_cmd_ack - callback function which will be called by SPS driver after an
* immediate command is complete.
* @user1: pointer to the descriptor of the transfer
@@ -345,6 +543,7 @@
*/
int ipa_send_cmd(u16 num_desc, struct ipa_desc *descr)
{
+ struct ipa_desc *desc;
int result = 0;
ipa_inc_client_enable_clks();
@@ -364,10 +563,22 @@
}
wait_for_completion(&descr->xfer_done);
} else {
- IPAERR("unsupported chaining multiple IC\n");
+ desc = &descr[num_desc - 1];
+ init_completion(&desc->xfer_done);
+
+ if (desc->callback || desc->user1)
+ WARN_ON(1);
+
+ desc->callback = ipa_sps_irq_cmd_ack;
+ desc->user1 = desc;
+ if (ipa_send(&ipa_ctx->sys[IPA_A5_CMD], num_desc,
+ descr, false)) {
+ IPAERR("fail to send multiple immediate command set\n");
result = -EFAULT;
goto bail;
}
+ wait_for_completion(&desc->xfer_done);
+ }
IPA_STATS_INC_IC_CNT(num_desc, descr, ipa_ctx->stats.imm_cmds);
bail:
@@ -386,13 +597,21 @@
static void ipa_sps_irq_tx_notify(struct sps_event_notify *notify)
{
struct ipa_sys_context *sys = &ipa_ctx->sys[IPA_A5_LAN_WAN_OUT];
+ struct ipa_tx_pkt_wrapper *tx_pkt;
int ret;
IPADBG("event %d notified\n", notify->event_id);
switch (notify->event_id) {
case SPS_EVENT_EOT:
+ tx_pkt = notify->data.transfer.user;
if (!atomic_read(&sys->curr_polling_state)) {
+ ret = sps_get_config(sys->ep->ep_hdl,
+ &sys->ep->connect);
+ if (ret) {
+ IPAERR("sps_get_config() failed %d\n", ret);
+ break;
+ }
sys->ep->connect.options = SPS_O_AUTO_ENABLE |
SPS_O_ACK_TRANSFERS | SPS_O_POLL;
ret = sps_set_config(sys->ep->ep_hdl,
@@ -402,7 +621,7 @@
break;
}
atomic_set(&sys->curr_polling_state, 1);
- queue_work(ipa_ctx->tx_wq, &tx_work);
+ queue_work(ipa_ctx->tx_wq, &tx_pkt->work);
}
break;
default:
@@ -435,47 +654,6 @@
}
}
-static void ipa_handle_tag_rsp(struct ipa_a5_mux_hdr *mux_hdr)
-{
- struct completion *compl;
- struct ipa_tree_node *node;
-
- /* retrieve the compl object from tag value */
- mux_hdr++;
- compl = (struct completion *) ntohl(*((u32 *)mux_hdr));
- IPADBG("%x %x %p\n", *(u32 *)mux_hdr, *((u32 *)mux_hdr + 1), compl);
-
- mutex_lock(&ipa_ctx->lock);
- node = ipa_search(&ipa_ctx->tag_tree, (u32)compl);
- if (node) {
- complete_all(compl);
- rb_erase(&node->node, &ipa_ctx->tag_tree);
- kmem_cache_free(ipa_ctx->tree_node_cache, node);
- } else {
- WARN_ON(1);
- }
- mutex_unlock(&ipa_ctx->lock);
-}
-
-static void ipa_dejitter(bool limit)
-{
- struct sk_buff *skb;
- int len = skb_queue_len(&ipa_ctx->rx_list);
- int i;
- void *cookie;
- ipa_notify_cb cb;
-
- if (limit && len >= RX_MAX_IND)
- len = RX_MAX_IND;
-
- for (i = len; i > 0; i--) {
- skb = __skb_dequeue(&ipa_ctx->rx_list);
- cb = (ipa_notify_cb)*(u32 *)&(skb->cb[0]);
- cookie = (void *)*(u32 *)&(skb->cb[4]);
- cb(cookie, IPA_RECEIVE, (unsigned long)skb);
- }
-}
-
/**
* ipa_handle_rx_core() - The core functionality of packet reception. This
* function is read from multiple code paths.
@@ -497,9 +675,13 @@
struct ipa_rx_pkt_wrapper *rx_pkt;
struct sk_buff *rx_skb;
struct sps_iovec iov;
+ unsigned int pull_len;
+ unsigned int padding;
int ret;
struct ipa_ep_context *ep;
int cnt = 0;
+ struct completion *compl;
+ struct ipa_tree_node *node;
unsigned int src_pipe;
while ((in_poll_state ? atomic_read(&sys->curr_polling_state) :
@@ -539,7 +721,7 @@
rx_skb->tail = rx_skb->data + rx_pkt->len;
rx_skb->len = rx_pkt->len;
rx_skb->truesize = rx_pkt->len + sizeof(struct sk_buff);
- kfree(rx_pkt);
+ kmem_cache_free(ipa_ctx->rx_pkt_wrapper_cache, rx_pkt);
mux_hdr = (struct ipa_a5_mux_hdr *)rx_skb->data;
@@ -554,9 +736,29 @@
IPA_STATS_INC_CNT(ipa_ctx->stats.rx_pkts);
IPA_STATS_EXCP_CNT(mux_hdr->flags, ipa_ctx->stats.rx_excp_pkts);
- if (mux_hdr->flags & IPA_A5_MUX_HDR_EXCP_FLAG_TAG) {
- if (ipa_ctx->ipa_hw_mode != IPA_HW_MODE_VIRTUAL)
- ipa_handle_tag_rsp(mux_hdr);
+ if (unlikely(mux_hdr->flags & IPA_A5_MUX_HDR_EXCP_FLAG_TAG)) {
+ if (ipa_ctx->ipa_hw_mode != IPA_HW_MODE_VIRTUAL) {
+ /* retrieve the compl object from tag value */
+ mux_hdr++;
+ compl = (struct completion *)
+ ntohl(*((u32 *)mux_hdr));
+ IPADBG("%x %x %p\n", *(u32 *)mux_hdr,
+ *((u32 *)mux_hdr + 1), compl);
+
+ mutex_lock(&ipa_ctx->lock);
+ node = ipa_search(&ipa_ctx->tag_tree,
+ (u32)compl);
+ if (node) {
+ complete_all(compl);
+ rb_erase(&node->node,
+ &ipa_ctx->tag_tree);
+ kmem_cache_free(
+ ipa_ctx->tree_node_cache, node);
+ } else {
+ WARN_ON(1);
+ }
+ mutex_unlock(&ipa_ctx->lock);
+ }
dev_kfree_skb(rx_skb);
ipa_replenish_rx_cache();
++cnt;
@@ -567,22 +769,38 @@
* Any packets arriving over AMPDU_TX should be dispatched
* to the regular WLAN RX data-path.
*/
- if (src_pipe == WLAN_AMPDU_TX_EP)
+ if (unlikely(src_pipe == WLAN_AMPDU_TX_EP))
src_pipe = WLAN_PROD_TX_EP;
- WARN_ON(src_pipe >= IPA_NUM_PIPES);
+ if (unlikely(src_pipe >= IPA_NUM_PIPES ||
+ !ipa_ctx->ep[src_pipe].valid ||
+ !ipa_ctx->ep[src_pipe].client_notify)) {
+ IPAERR("drop pipe=%d ep_valid=%d client_notify=%p\n",
+ src_pipe, ipa_ctx->ep[src_pipe].valid,
+ ipa_ctx->ep[src_pipe].client_notify);
+ dev_kfree_skb(rx_skb);
+ ipa_replenish_rx_cache();
+ ++cnt;
+ continue;
+ }
ep = &ipa_ctx->ep[src_pipe];
- IPADBG("pulling %d bytes from skb\n", ep->pull_len);
- skb_pull(rx_skb, ep->pull_len);
+ pull_len = sizeof(struct ipa_a5_mux_hdr);
+
+ /*
+ * IP packet starts on word boundary
+ * remove the MUX header and any padding and pass the frame to
+ * the client which registered a rx callback on the "src pipe"
+ */
+ padding = ep->cfg.hdr.hdr_len & 0x3;
+ if (padding)
+ pull_len += 4 - padding;
+
+ IPADBG("pulling %d bytes from skb\n", pull_len);
+ skb_pull(rx_skb, pull_len);
ipa_replenish_rx_cache();
- if (ep->client_notify) {
- __skb_queue_tail(&ipa_ctx->rx_list, rx_skb);
- *(u32 *)&(rx_skb->cb[0]) = (u32)ep->client_notify;
- *(u32 *)&(rx_skb->cb[4]) = (u32)ep->priv;
- } else {
- dev_kfree_skb(rx_skb);
- }
+ ep->client_notify(ep->priv, IPA_RECEIVE,
+ (unsigned long)(rx_skb));
cnt++;
};
@@ -601,6 +819,11 @@
goto fail;
}
+ ret = sps_get_config(sys->ep->ep_hdl, &sys->ep->connect);
+ if (ret) {
+ IPAERR("sps_get_config() failed %d\n", ret);
+ goto fail;
+ }
sys->event.options = SPS_O_EOT;
ret = sps_register_event(sys->ep->ep_hdl, &sys->event);
if (ret) {
@@ -647,6 +870,12 @@
switch (notify->event_id) {
case SPS_EVENT_EOT:
if (!atomic_read(&sys->curr_polling_state)) {
+ ret = sps_get_config(sys->ep->ep_hdl,
+ &sys->ep->connect);
+ if (ret) {
+ IPAERR("sps_get_config() failed %d\n", ret);
+ break;
+ }
sys->ep->connect.options = SPS_O_AUTO_ENABLE |
SPS_O_ACK_TRANSFERS | SPS_O_POLL;
ret = sps_set_config(sys->ep->ep_hdl,
@@ -696,10 +925,8 @@
} else {
inactive_cycles = 0;
}
- ipa_dejitter(true);
} while (inactive_cycles <= POLLING_INACTIVITY_RX);
- ipa_dejitter(false);
ipa_rx_switch_to_intr_mode(sys);
ipa_dec_client_disable_clks();
}
@@ -835,7 +1062,6 @@
break;
case 2:
sys_idx = ipa_ep_idx;
- ipa_ctx->sys[sys_idx].max_len = sys_in->desc_fifo_sz / 8 - 2;
INIT_DELAYED_WORK(&ipa_ctx->sys[sys_idx].switch_to_intr_work,
switch_to_intr_tx_work_func);
break;
@@ -950,87 +1176,9 @@
dev_kfree_skb(skb);
}
-static int ipa_send_two(struct sk_buff *skb, struct ipa_sys_context *sys,
- int dst_ep_idx)
+static void ipa_tx_cmd_comp(void *user1, void *user2)
{
- struct ipa_tx_pkt_wrapper *tx_pktc;
- struct ipa_tx_pkt_wrapper *tx_pktd;
- struct ipa_ep_context *ep = &ipa_ctx->ep[dst_ep_idx];
- unsigned long irq_flags;
- dma_addr_t dma_addrd;
- int rc = -ENOMEM;
-
- tx_pktc = kmalloc(sizeof(struct ipa_tx_pkt_wrapper), GFP_ATOMIC);
- if (!tx_pktc) {
- IPAERR("failed to alloc tx wrapper C\n");
- goto fail_mem_alloc_c;
- }
-
- tx_pktd = kmalloc(sizeof(struct ipa_tx_pkt_wrapper), GFP_ATOMIC);
- if (!tx_pktd) {
- IPAERR("failed to alloc tx wrapper D\n");
- goto fail_mem_alloc_d;
- }
-
- dma_addrd = dma_map_single(NULL, skb->data, skb->len, DMA_TO_DEVICE);
- if (!dma_addrd) {
- IPAERR("failed to DMA wrap\n");
- goto fail_dma_map_d;
- }
-
- INIT_LIST_HEAD(&tx_pktc->link);
- tx_pktc->callback = NULL;
-
- INIT_LIST_HEAD(&tx_pktd->link);
- tx_pktd->mem.phys_base = dma_addrd;
- tx_pktd->mem.base = skb->data;
- tx_pktd->mem.size = skb->len;
- tx_pktd->callback = ipa_tx_comp_usr_notify_release;
- tx_pktd->user1 = skb;
- tx_pktd->user2 = (void *)dst_ep_idx;
-
- spin_lock_irqsave(&sys->spinlock, irq_flags);
- if (sys->len >= sys->max_len)
- goto fail_oom;
- list_add_tail(&tx_pktc->link, &sys->head_desc_list);
- if (sps_transfer_one(sys->ep->ep_hdl, ep->dma_addr, IPA_IP_PACKET_INIT,
- tx_pktc, SPS_IOVEC_FLAG_IMME |
- SPS_IOVEC_FLAG_NO_SUBMIT))
- IPAERR("sps_transfer_one 0 failed\n");
- list_add_tail(&tx_pktd->link, &sys->head_desc_list);
- if (sps_transfer_one(sys->ep->ep_hdl, dma_addrd, skb->len, tx_pktd,
- SPS_IOVEC_FLAG_EOT | SPS_IOVEC_FLAG_INT))
- IPAERR("sps_transfer_one 1 failed\n");
- sys->len += 2;
- spin_unlock_irqrestore(&sys->spinlock, irq_flags);
- return 0;
-
-fail_oom:
- dma_unmap_single(NULL, dma_addrd, skb->len, DMA_TO_DEVICE);
-fail_dma_map_d:
- kfree(tx_pktd);
-fail_mem_alloc_d:
- kfree(tx_pktc);
-fail_mem_alloc_c:
- return rc;
-}
-
-static int ipa_send_data_hw_path(struct sk_buff *skb,
- struct ipa_sys_context *sys, int dst_ep_idx)
-{
- struct ipa_desc desc;
-
- desc.pyld = skb->data;
- desc.len = skb->len;
- desc.type = IPA_DATA_DESC_SKB;
- desc.callback = ipa_tx_comp_usr_notify_release;
- desc.user1 = skb;
- desc.user2 = (void *)dst_ep_idx;
-
- if (ipa_send_one(sys, &desc, true))
- return -EFAULT;
-
- return 0;
+ kfree(user1);
}
/**
@@ -1063,42 +1211,76 @@
int ipa_tx_dp(enum ipa_client_type dst, struct sk_buff *skb,
struct ipa_tx_meta *meta)
{
+ struct ipa_desc desc[2];
int ipa_ep_idx;
+ struct ipa_ip_packet_init *cmd;
+
+ memset(&desc, 0, 2 * sizeof(struct ipa_desc));
ipa_ep_idx = ipa_get_ep_mapping(ipa_ctx->mode, dst);
if (unlikely(ipa_ep_idx == -1)) {
IPAERR("dest EP does not exist.\n");
- goto fail;
+ goto fail_gen;
}
if (unlikely(ipa_ctx->ep[ipa_ep_idx].valid == 0)) {
IPAERR("dest EP not valid.\n");
- goto fail;
+ goto fail_gen;
}
if (IPA_CLIENT_IS_CONS(dst)) {
- if (ipa_send_two(skb, &ipa_ctx->sys[IPA_A5_LAN_WAN_OUT],
- ipa_ep_idx)) {
- IPAERR("fail to send pkt_init+skb dst=%d skb=%p\n",
- dst, skb);
- goto fail;
+ cmd = kzalloc(sizeof(struct ipa_ip_packet_init), GFP_ATOMIC);
+ if (!cmd) {
+ IPAERR("failed to alloc immediate command object\n");
+ goto fail_mem_alloc;
+ }
+
+ cmd->destination_pipe_index = ipa_ep_idx;
+ if (meta && meta->mbim_stream_id_valid)
+ cmd->metadata = meta->mbim_stream_id;
+ desc[0].opcode = IPA_IP_PACKET_INIT;
+ desc[0].pyld = cmd;
+ desc[0].len = sizeof(struct ipa_ip_packet_init);
+ desc[0].type = IPA_IMM_CMD_DESC;
+ desc[0].callback = ipa_tx_cmd_comp;
+ desc[0].user1 = cmd;
+ desc[1].pyld = skb->data;
+ desc[1].len = skb->len;
+ desc[1].type = IPA_DATA_DESC_SKB;
+ desc[1].callback = ipa_tx_comp_usr_notify_release;
+ desc[1].user1 = skb;
+ desc[1].user2 = (void *)ipa_ep_idx;
+
+ if (ipa_send(&ipa_ctx->sys[IPA_A5_LAN_WAN_OUT], 2, desc,
+ true)) {
+ IPAERR("fail to send immediate command\n");
+ goto fail_send;
}
IPA_STATS_INC_CNT(ipa_ctx->stats.imm_cmds[IPA_IP_PACKET_INIT]);
} else if (dst == IPA_CLIENT_A5_WLAN_AMPDU_PROD) {
- if (ipa_send_data_hw_path(skb,
- &ipa_ctx->sys[IPA_A5_WLAN_AMPDU_OUT],
- ipa_ep_idx)) {
- IPAERR("fail to send skb dst=%d skb=%p\n", dst, skb);
- goto fail;
+ desc[0].pyld = skb->data;
+ desc[0].len = skb->len;
+ desc[0].type = IPA_DATA_DESC_SKB;
+ desc[0].callback = ipa_tx_comp_usr_notify_release;
+ desc[0].user1 = skb;
+ desc[0].user2 = (void *)ipa_ep_idx;
+
+ if (ipa_send_one(&ipa_ctx->sys[IPA_A5_WLAN_AMPDU_OUT],
+ &desc[0], true)) {
+ IPAERR("fail to send skb\n");
+ goto fail_gen;
}
} else {
IPAERR("%d PROD is not supported.\n", dst);
- goto fail;
+ goto fail_gen;
}
return 0;
-fail:
+fail_send:
+ kfree(cmd);
+fail_mem_alloc:
+fail_gen:
return -EFAULT;
}
EXPORT_SYMBOL(ipa_tx_dp);
@@ -1134,7 +1316,8 @@
rx_len_cached = sys->len;
while (rx_len_cached < IPA_RX_POOL_CEIL) {
- rx_pkt = kmalloc(sizeof(struct ipa_rx_pkt_wrapper), flag);
+ rx_pkt = kmem_cache_zalloc(ipa_ctx->rx_pkt_wrapper_cache,
+ flag);
if (!rx_pkt) {
IPAERR("failed to alloc rx wrapper\n");
goto fail_kmem_cache_alloc;
@@ -1182,7 +1365,7 @@
fail_dma_mapping:
dev_kfree_skb(rx_pkt->skb);
fail_skb_alloc:
- kfree(rx_pkt);
+ kmem_cache_free(ipa_ctx->rx_pkt_wrapper_cache, rx_pkt);
fail_kmem_cache_alloc:
if (rx_len_cached == 0) {
IPA_STATS_INC_CNT(ipa_ctx->stats.rx_repl_repost);
@@ -1214,7 +1397,7 @@
dma_unmap_single(NULL, rx_pkt->dma_address, IPA_RX_SKB_SIZE,
DMA_FROM_DEVICE);
dev_kfree_skb(rx_pkt->skb);
- kfree(rx_pkt);
+ kmem_cache_free(ipa_ctx->rx_pkt_wrapper_cache, rx_pkt);
}
}
diff --git a/drivers/platform/msm/ipa/ipa_i.h b/drivers/platform/msm/ipa/ipa_i.h
index 790898a..8ad0b5a 100644
--- a/drivers/platform/msm/ipa/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_i.h
@@ -119,7 +119,6 @@
#define IPA_DFLT_HDR_NAME "ipa_excp_hdr"
#define IPA_INVALID_L4_PROTOCOL 0xFF
-
#define IPA_CLIENT_IS_PROD(x) (x >= IPA_CLIENT_PROD && x < IPA_CLIENT_CONS)
#define IPA_CLIENT_IS_CONS(x) (x >= IPA_CLIENT_CONS && x < IPA_CLIENT_MAX)
#define IPA_SETFIELD(val, shift, mask) (((val) << (shift)) & (mask))
@@ -364,9 +363,6 @@
bool desc_fifo_client_allocated;
bool data_fifo_client_allocated;
bool suspended;
- unsigned int pull_len;
- struct ipa_ip_packet_init *cmd;
- dma_addr_t dma_addr;
};
/**
@@ -382,7 +378,6 @@
struct ipa_sys_context {
struct list_head head_desc_list;
u32 len;
- u32 max_len;
spinlock_t spinlock;
struct sps_register_event event;
struct ipa_ep_context *ep;
@@ -641,6 +636,8 @@
struct kmem_cache *hdr_cache;
struct kmem_cache *hdr_offset_cache;
struct kmem_cache *rt_tbl_cache;
+ struct kmem_cache *tx_pkt_wrapper_cache;
+ struct kmem_cache *rx_pkt_wrapper_cache;
struct kmem_cache *tree_node_cache;
unsigned long rt_idx_bitmap[IPA_IP_MAX];
struct mutex lock;
@@ -687,7 +684,6 @@
/* featurize if memory footprint becomes a concern */
struct ipa_stats stats;
void *smem_pipe_mem;
- struct sk_buff_head rx_list;
};
/**
@@ -776,6 +772,8 @@
u32 *consumer_handle);
int ipa_send_one(struct ipa_sys_context *sys, struct ipa_desc *desc,
bool in_atomic);
+int ipa_send(struct ipa_sys_context *sys, u32 num_desc, struct ipa_desc *desc,
+ bool in_atomic);
int ipa_get_ep_mapping(enum ipa_operating_mode mode,
enum ipa_client_type client);
int ipa_get_client_mapping(enum ipa_operating_mode mode, int pipe_idx);
diff --git a/drivers/platform/msm/ipa/ipa_utils.c b/drivers/platform/msm/ipa/ipa_utils.c
index 912d93c..23de300 100644
--- a/drivers/platform/msm/ipa/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_utils.c
@@ -32,24 +32,6 @@
{ 19, -1, -1, -1, -1, 11, 15, 8, 6, 2, 1, 5, 14, 16, 17, 18, -1, 10, 9, 7, 3, 4 },
};
-static unsigned int ipa_calc_pull_len(u32 hdr_len)
-{
- unsigned int pull_len, padding;
-
- pull_len = sizeof(struct ipa_a5_mux_hdr);
-
- /*
- * IP packet starts on word boundary
- * remove the MUX header and any padding and pass the frame to
- * the client which registered a rx callback on the "src pipe"
- */
- padding = hdr_len & 0x3;
- if (padding)
- pull_len += 4 - padding;
-
- return pull_len;
-}
-
/**
* ipa_cfg_route() - configure IPA route
* @route: IPA route
@@ -769,9 +751,6 @@
ipa_write_reg(ipa_ctx->mmio,
IPA_ENDP_INIT_HDR_n_OFST_v2(clnt_hdl), val);
- if (IPA_CLIENT_IS_PROD(ep->client))
- ep->pull_len = ipa_calc_pull_len(ipa_ep_cfg->hdr_len);
-
return 0;
}
EXPORT_SYMBOL(ipa_cfg_ep_hdr);
diff --git a/drivers/spi/spi_qsd.c b/drivers/spi/spi_qsd.c
index e91e5d6..53aa475 100644
--- a/drivers/spi/spi_qsd.c
+++ b/drivers/spi/spi_qsd.c
@@ -14,6 +14,7 @@
* SPI driver for Qualcomm MSM platforms
*
*/
+
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -2604,11 +2605,12 @@
}
/**
- * msm_spi_dt_to_pdata: copy device-tree data to platfrom data struct
+ * msm_spi_dt_to_pdata: create pdata and read gpio config from device tree
*/
-struct msm_spi_platform_data *
-__init msm_spi_dt_to_pdata(struct platform_device *pdev)
+struct msm_spi_platform_data * __init msm_spi_dt_to_pdata(
+ struct platform_device *pdev, struct msm_spi *dd)
{
+ int i;
struct msm_spi_platform_data *pdata;
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
@@ -2618,22 +2620,36 @@
} else {
struct msm_spi_dt_to_pdata_map map[] = {
{"spi-max-frequency",
- &pdata->max_clock_speed, DT_SGST, DT_U32, 0},
+ &pdata->max_clock_speed, DT_SGST, DT_U32, 0},
{"qcom,infinite-mode",
- &pdata->infinite_mode, DT_OPT, DT_U32, 0},
+ &pdata->infinite_mode, DT_OPT, DT_U32, 0},
{"qcom,active-only",
- &pdata->active_only, DT_OPT, DT_BOOL, 0},
+ &pdata->active_only, DT_OPT, DT_BOOL, 0},
{"qcom,master-id",
- &pdata->master_id, DT_SGST, DT_U32, 0},
+ &pdata->master_id, DT_SGST, DT_U32, 0},
{"qcom,ver-reg-exists",
- &pdata->ver_reg_exists, DT_OPT, DT_BOOL, 0},
+ &pdata->ver_reg_exists, DT_OPT, DT_BOOL, 0},
{"qcom,use-bam",
- &pdata->use_bam, DT_OPT, DT_BOOL, 0},
+ &pdata->use_bam, DT_OPT, DT_BOOL, 0},
{"qcom,bam-consumer-pipe-index",
- &pdata->bam_consumer_pipe_index, DT_OPT, DT_U32, 0},
+ &pdata->bam_consumer_pipe_index, DT_OPT, DT_U32, 0},
{"qcom,bam-producer-pipe-index",
- &pdata->bam_producer_pipe_index, DT_OPT, DT_U32, 0},
- {NULL, NULL, 0, 0, 0},
+ &pdata->bam_producer_pipe_index, DT_OPT, DT_U32, 0},
+ {"qcom,gpio-clk",
+ &dd->spi_gpios[0], DT_OPT, DT_GPIO, -1},
+ {"qcom,gpio-miso",
+ &dd->spi_gpios[1], DT_OPT, DT_GPIO, -1},
+ {"qcom,gpio-mosi",
+ &dd->spi_gpios[2], DT_OPT, DT_GPIO, -1},
+ {"qcom,gpio-cs0",
+ &dd->cs_gpios[0].gpio_num, DT_OPT, DT_GPIO, -1},
+ {"qcom,gpio-cs1",
+ &dd->cs_gpios[1].gpio_num, DT_OPT, DT_GPIO, -1},
+ {"qcom,gpio-cs2",
+ &dd->cs_gpios[2].gpio_num, DT_OPT, DT_GPIO, -1},
+ {"qcom,gpio-cs3",
+ &dd->cs_gpios[3].gpio_num, DT_OPT, DT_GPIO, -1},
+ {NULL, NULL, 0, 0, 0},
};
if (msm_spi_dt_to_pdata_populate(pdev, pdata, map)) {
@@ -2655,6 +2671,10 @@
pdata->use_bam = false;
}
}
+
+ for (i = 0; i < ARRAY_SIZE(spi_cs_rsrcs); ++i)
+ dd->cs_gpios[i].valid = (dd->cs_gpios[i].gpio_num >= 0);
+
return pdata;
}
@@ -2714,7 +2734,6 @@
int clk_enabled = 0;
int pclk_enabled = 0;
struct msm_spi_platform_data *pdata;
- enum of_gpio_flags flags;
master = spi_alloc_master(&pdev->dev, sizeof(struct msm_spi));
if (!master) {
@@ -2734,7 +2753,7 @@
if (pdev->dev.of_node) {
dd->qup_ver = SPI_QUP_VERSION_BFAM;
master->dev.of_node = pdev->dev.of_node;
- pdata = msm_spi_dt_to_pdata(pdev);
+ pdata = msm_spi_dt_to_pdata(pdev, dd);
if (!pdata) {
rc = -ENOMEM;
goto err_probe_exit;
@@ -2746,18 +2765,6 @@
"using default bus_num %d\n", pdev->id);
else
master->bus_num = pdev->id = rc;
-
- for (i = 0; i < ARRAY_SIZE(spi_rsrcs); ++i) {
- dd->spi_gpios[i] = of_get_gpio_flags(pdev->dev.of_node,
- i, &flags);
- }
-
- for (i = 0; i < ARRAY_SIZE(spi_cs_rsrcs); ++i) {
- dd->cs_gpios[i].gpio_num = of_get_named_gpio_flags(
- pdev->dev.of_node, "cs-gpios",
- i, &flags);
- dd->cs_gpios[i].valid = 0;
- }
} else {
pdata = pdev->dev.platform_data;
dd->qup_ver = SPI_QUP_VERSION_NONE;
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index bb0b2fb..0cfd515 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -393,6 +393,7 @@
u32 recip;
u32 wValue;
u32 wIndex;
+ u32 reg;
int ret;
wValue = le16_to_cpu(ctrl->wValue);
@@ -413,6 +414,13 @@
return -EINVAL;
if (dwc->speed != DWC3_DSTS_SUPERSPEED)
return -EINVAL;
+
+ reg = dwc3_readl(dwc->regs, DWC3_DCTL);
+ if (set)
+ reg |= DWC3_DCTL_INITU1ENA;
+ else
+ reg &= ~DWC3_DCTL_INITU1ENA;
+ dwc3_writel(dwc->regs, DWC3_DCTL, reg);
break;
case USB_DEVICE_U2_ENABLE:
@@ -420,6 +428,13 @@
return -EINVAL;
if (dwc->speed != DWC3_DSTS_SUPERSPEED)
return -EINVAL;
+
+ reg = dwc3_readl(dwc->regs, DWC3_DCTL);
+ if (set)
+ reg |= DWC3_DCTL_INITU2ENA;
+ else
+ reg &= ~DWC3_DCTL_INITU2ENA;
+ dwc3_writel(dwc->regs, DWC3_DCTL, reg);
break;
case USB_DEVICE_LTM_ENABLE:
@@ -524,6 +539,7 @@
{
u32 cfg;
int ret;
+ u32 reg;
dwc->start_config_issued = false;
cfg = le16_to_cpu(ctrl->wValue);
@@ -538,6 +554,14 @@
/* if the cfg matches and the cfg is non zero */
if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) {
dwc->dev_state = DWC3_CONFIGURED_STATE;
+ /*
+ * Enable transition to U1/U2 state when
+ * nothing is pending from application.
+ */
+ reg = dwc3_readl(dwc->regs, DWC3_DCTL);
+ reg |= (DWC3_DCTL_ACCEPTU1ENA | DWC3_DCTL_ACCEPTU2ENA);
+ dwc3_writel(dwc->regs, DWC3_DCTL, reg);
+
dwc->resize_fifos = true;
dev_dbg(dwc->dev, "resize fifos flag SET\n");
}
diff --git a/drivers/usb/gadget/ci13xxx_msm.c b/drivers/usb/gadget/ci13xxx_msm.c
index 3cad3ce..8d8c30e 100644
--- a/drivers/usb/gadget/ci13xxx_msm.c
+++ b/drivers/usb/gadget/ci13xxx_msm.c
@@ -16,6 +16,8 @@
#define MSM_USB_BASE (udc->regs)
+#define CI13XXX_MSM_MAX_ITC_LEVEL 6
+
struct ci13xxx_udc_context {
int irq;
void __iomem *regs;
@@ -177,7 +179,7 @@
CI13XXX_ZERO_ITC |
CI13XXX_DISABLE_STREAMING |
CI13XXX_IS_OTG,
-
+ .nz_itc = 0,
.notify_event = ci13xxx_msm_notify_event,
};
@@ -230,10 +232,21 @@
static int ci13xxx_msm_probe(struct platform_device *pdev)
{
struct resource *res;
- int ret;
+ int ret, rc;
+ int itc_level = 0;
dev_dbg(&pdev->dev, "ci13xxx_msm_probe\n");
+ if (pdev->dev.of_node) {
+ rc = of_property_read_u32(pdev->dev.of_node, "qcom,itc-level",
+ &itc_level);
+ /* Acceptable values for nz_itc are: 0,1,2,4,8,16,32,64 */
+ if (itc_level > CI13XXX_MSM_MAX_ITC_LEVEL || rc)
+ ci13xxx_msm_udc_driver.nz_itc = 0;
+ else
+ ci13xxx_msm_udc_driver.nz_itc = 1 << itc_level;
+ }
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "failed to get platform resource mem\n");
@@ -313,9 +326,18 @@
writel_relaxed(val, USB_GENCONFIG);
}
+static const struct of_device_id ci13xx_msm_dt_match[] = {
+ { .compatible = "qcom,ci13xxx_msm",
+ },
+ {}
+};
+
static struct platform_driver ci13xxx_msm_driver = {
.probe = ci13xxx_msm_probe,
- .driver = { .name = "msm_hsusb", },
+ .driver = {
+ .name = "msm_hsusb",
+ .of_match_table = ci13xx_msm_dt_match,
+ },
.remove = ci13xxx_msm_remove,
};
MODULE_ALIAS("platform:msm_hsusb");
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 939eb6d..e7074a2 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -367,7 +367,10 @@
* 8 micro frames. If CPU can handle interrupts at faster rate, ITC
* can be set to lesser value to gain performance.
*/
- if (udc->udc_driver->flags & CI13XXX_ZERO_ITC)
+ if (udc->udc_driver->nz_itc)
+ hw_cwrite(CAP_USBCMD, USBCMD_ITC_MASK,
+ USBCMD_ITC(udc->udc_driver->nz_itc));
+ else if (udc->udc_driver->flags & CI13XXX_ZERO_ITC)
hw_cwrite(CAP_USBCMD, USBCMD_ITC_MASK, USBCMD_ITC(0));
if (hw_cread(CAP_USBMODE, USBMODE_CM) != USBMODE_CM_DEVICE) {
diff --git a/drivers/usb/gadget/ci13xxx_udc.h b/drivers/usb/gadget/ci13xxx_udc.h
index 4c5b38d..09404c8 100644
--- a/drivers/usb/gadget/ci13xxx_udc.h
+++ b/drivers/usb/gadget/ci13xxx_udc.h
@@ -129,6 +129,7 @@
struct ci13xxx_udc_driver {
const char *name;
unsigned long flags;
+ unsigned int nz_itc;
#define CI13XXX_REGS_SHARED BIT(0)
#define CI13XXX_REQUIRE_TRANSCEIVER BIT(1)
#define CI13XXX_PULLUP_ON_VBUS BIT(2)
diff --git a/drivers/usb/gadget/f_mtp.c b/drivers/usb/gadget/f_mtp.c
index 4586d80..a4192ca 100644
--- a/drivers/usb/gadget/f_mtp.c
+++ b/drivers/usb/gadget/f_mtp.c
@@ -558,17 +558,15 @@
struct mtp_dev *dev = fp->private_data;
struct usb_composite_dev *cdev = dev->cdev;
struct usb_request *req;
- int r = count, xfer;
+ int r = count, xfer, len;
int ret = 0;
DBG(cdev, "mtp_read(%d)\n", count);
- if (count > mtp_rx_req_len)
- return -EINVAL;
+ len = ALIGN(count, dev->ep_out->maxpacket);
- if (!IS_ALIGNED(count, dev->ep_out->maxpacket))
- DBG(cdev, "%s - count(%d) not multiple of mtu(%d)\n", __func__,
- count, dev->ep_out->maxpacket);
+ if (len > mtp_rx_req_len)
+ return -EINVAL;
/* we will block until we're online */
DBG(cdev, "mtp_read: waiting for online state\n");
@@ -591,7 +589,7 @@
requeue_req:
/* queue a request */
req = dev->rx_req[0];
- req->length = mtp_rx_req_len;
+ req->length = len;
dev->rx_done = 0;
ret = usb_ep_queue(dev->ep_out, req, GFP_KERNEL);
if (ret < 0) {
diff --git a/drivers/usb/gadget/u_bam.c b/drivers/usb/gadget/u_bam.c
index 9dd9978..edcafcc 100644
--- a/drivers/usb/gadget/u_bam.c
+++ b/drivers/usb/gadget/u_bam.c
@@ -848,6 +848,7 @@
d->rx_req->context = port;
d->rx_req->complete = gbam_endless_rx_complete;
d->rx_req->length = 0;
+ d->rx_req->no_interrupt = 1;
sps_params = (MSM_SPS_MODE | d->src_pipe_idx |
MSM_VENDOR_ID) & ~MSM_IS_FINITE_TRANSFER;
d->rx_req->udc_priv = sps_params;
@@ -863,6 +864,7 @@
d->tx_req->context = port;
d->tx_req->complete = gbam_endless_tx_complete;
d->tx_req->length = 0;
+ d->tx_req->no_interrupt = 1;
sps_params = (MSM_SPS_MODE | d->dst_pipe_idx |
MSM_VENDOR_ID) & ~MSM_IS_FINITE_TRANSFER;
d->tx_req->udc_priv = sps_params;
diff --git a/drivers/usb/gadget/u_bam_data.c b/drivers/usb/gadget/u_bam_data.c
index 5c7e52f..d470edf 100644
--- a/drivers/usb/gadget/u_bam_data.c
+++ b/drivers/usb/gadget/u_bam_data.c
@@ -296,6 +296,7 @@
d->rx_req->context = port;
d->rx_req->complete = bam_data_endless_rx_complete;
d->rx_req->length = 0;
+ d->rx_req->no_interrupt = 1;
sps_params = (SPS_PARAMS_SPS_MODE | d->src_pipe_idx |
MSM_VENDOR_ID) & ~SPS_PARAMS_TBE;
d->rx_req->udc_priv = sps_params;
@@ -306,6 +307,7 @@
d->tx_req->context = port;
d->tx_req->complete = bam_data_endless_tx_complete;
d->tx_req->length = 0;
+ d->tx_req->no_interrupt = 1;
sps_params = (SPS_PARAMS_SPS_MODE | d->dst_pipe_idx |
MSM_VENDOR_ID) & ~SPS_PARAMS_TBE;
d->tx_req->udc_priv = sps_params;
diff --git a/drivers/video/msm/mdss/dsi_io_v2.c b/drivers/video/msm/mdss/dsi_io_v2.c
index cbdd241..273fb54 100644
--- a/drivers/video/msm/mdss/dsi_io_v2.c
+++ b/drivers/video/msm/mdss/dsi_io_v2.c
@@ -437,5 +437,9 @@
void msm_dsi_phy_off(unsigned char *ctrl_base)
{
+ MIPI_OUTP(ctrl_base + DSI_DSIPHY_PLL_CTRL_5, 0x05f);
+ MIPI_OUTP(ctrl_base + DSI_DSIPHY_REGULATOR_CTRL_0, 0x02);
MIPI_OUTP(ctrl_base + DSI_DSIPHY_CTRL_0, 0x00);
+ MIPI_OUTP(ctrl_base + DSI_DSIPHY_CTRL_1, 0x7f);
+ MIPI_OUTP(ctrl_base + DSI_CLK_CTRL, 0);
}
diff --git a/drivers/video/msm/mdss/dsi_panel_v2.c b/drivers/video/msm/mdss/dsi_panel_v2.c
index bb5d3ca..5c164e4 100644
--- a/drivers/video/msm/mdss/dsi_panel_v2.c
+++ b/drivers/video/msm/mdss/dsi_panel_v2.c
@@ -34,6 +34,7 @@
int rst_gpio;
int disp_en_gpio;
int video_mode_gpio;
+ int te_gpio;
char bl_ctrl;
struct regulator *vddio_vreg;
@@ -190,6 +191,8 @@
gpio_set_value(panel_private->video_mode_gpio,
0);
}
+ if (gpio_is_valid(panel_private->te_gpio))
+ gpio_request(panel_private->te_gpio, "panel_te");
} else {
gpio_set_value(panel_private->rst_gpio, 0);
gpio_free(panel_private->rst_gpio);
@@ -202,6 +205,8 @@
if (gpio_is_valid(panel_private->video_mode_gpio))
gpio_free(panel_private->video_mode_gpio);
+ if (gpio_is_valid(panel_private->te_gpio))
+ gpio_free(panel_private->te_gpio);
dsi_panel_power(0);
}
}
@@ -233,16 +238,10 @@
pr_debug("%s:%d, debug info (mode) : %d\n", __func__, __LINE__,
mipi->mode);
- if (mipi->mode == DSI_VIDEO_MODE) {
- dsi_cmds_tx_v2(pdata, &panel_private->dsi_panel_tx_buf,
- panel_private->on_cmds_list->buf,
- panel_private->on_cmds_list->size);
- } else {
- pr_err("%s:%d, CMD MODE NOT SUPPORTED", __func__, __LINE__);
- return -EINVAL;
- }
- return 0;
+ return dsi_cmds_tx_v2(pdata, &panel_private->dsi_panel_tx_buf,
+ panel_private->on_cmds_list->buf,
+ panel_private->on_cmds_list->size);
}
static int dsi_panel_off(struct mdss_panel_data *pdata)
@@ -252,16 +251,10 @@
pr_debug("%s:%d, debug info\n", __func__, __LINE__);
- if (mipi->mode == DSI_VIDEO_MODE) {
- dsi_cmds_tx_v2(pdata, &panel_private->dsi_panel_tx_buf,
- panel_private->off_cmds_list->buf,
- panel_private->off_cmds_list->size);
- } else {
- pr_debug("%s:%d, CMD mode not supported", __func__, __LINE__);
- return -EINVAL;
- }
- return 0;
+ return dsi_cmds_tx_v2(pdata, &panel_private->dsi_panel_tx_buf,
+ panel_private->off_cmds_list->buf,
+ panel_private->off_cmds_list->size);
}
static int dsi_panel_parse_gpio(struct platform_device *pdev)
@@ -272,6 +265,8 @@
panel_private->rst_gpio = of_get_named_gpio(np, "qcom,rst-gpio", 0);
panel_private->video_mode_gpio = of_get_named_gpio(np,
"qcom,mode-selection-gpio", 0);
+ panel_private->te_gpio = of_get_named_gpio(np,
+ "qcom,te-gpio", 0);
return 0;
}
@@ -364,86 +359,9 @@
struct dsi_panel_common_pdata *panel_data)
{
struct device_node *np = pdev->dev.of_node;
- u32 res[6], tmp;
- int i, len, rc;
+ int i, len;
const char *data;
- rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-mode", &tmp);
- panel_data->panel_info.mipi.mode = (!rc ? tmp : DSI_VIDEO_MODE);
-
- rc = of_property_read_u32(np,
- "qcom,mdss-pan-dsi-h-pulse-mode", &tmp);
- panel_data->panel_info.mipi.pulse_mode_hsa_he = (!rc ? tmp : false);
-
- rc = of_property_read_u32_array(np,
- "qcom,mdss-pan-dsi-h-power-stop", res, 3);
- panel_data->panel_info.mipi.hbp_power_stop = (!rc ? res[0] : false);
- panel_data->panel_info.mipi.hsa_power_stop = (!rc ? res[1] : false);
- panel_data->panel_info.mipi.hfp_power_stop = (!rc ? res[2] : false);
-
- rc = of_property_read_u32_array(np,
- "qcom,mdss-pan-dsi-bllp-power-stop", res, 2);
- panel_data->panel_info.mipi.bllp_power_stop =
- (!rc ? res[0] : false);
- panel_data->panel_info.mipi.eof_bllp_power_stop =
- (!rc ? res[1] : false);
-
- rc = of_property_read_u32(np,
- "qcom,mdss-pan-dsi-traffic-mode", &tmp);
- panel_data->panel_info.mipi.traffic_mode =
- (!rc ? tmp : DSI_NON_BURST_SYNCH_PULSE);
-
- rc = of_property_read_u32(np,
- "qcom,mdss-pan-dsi-dst-format", &tmp);
- panel_data->panel_info.mipi.dst_format =
- (!rc ? tmp : DSI_VIDEO_DST_FORMAT_RGB888);
-
- rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-vc", &tmp);
- panel_data->panel_info.mipi.vc = (!rc ? tmp : 0);
-
- rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-rgb-swap", &tmp);
- panel_data->panel_info.mipi.rgb_swap = (!rc ? tmp : DSI_RGB_SWAP_RGB);
-
- rc = of_property_read_u32_array(np,
- "qcom,mdss-pan-dsi-data-lanes", res, 4);
- panel_data->panel_info.mipi.data_lane0 = (!rc ? res[0] : true);
- panel_data->panel_info.mipi.data_lane1 = (!rc ? res[1] : false);
- panel_data->panel_info.mipi.data_lane2 = (!rc ? res[2] : false);
- panel_data->panel_info.mipi.data_lane3 = (!rc ? res[3] : false);
-
- rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-dlane-swap", &tmp);
- panel_data->panel_info.mipi.dlane_swap = (!rc ? tmp : 0);
-
- rc = of_property_read_u32_array(np, "qcom,mdss-pan-dsi-t-clk", res, 2);
- panel_data->panel_info.mipi.t_clk_pre = (!rc ? res[0] : 0x24);
- panel_data->panel_info.mipi.t_clk_post = (!rc ? res[1] : 0x03);
-
- rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-stream", &tmp);
- panel_data->panel_info.mipi.stream = (!rc ? tmp : 0);
-
- rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-mdp-tr", &tmp);
- panel_data->panel_info.mipi.mdp_trigger =
- (!rc ? tmp : DSI_CMD_TRIGGER_SW);
- if (panel_data->panel_info.mipi.mdp_trigger > 6) {
- pr_err("%s:%d, Invalid mdp trigger. Forcing to sw trigger",
- __func__, __LINE__);
- panel_data->panel_info.mipi.mdp_trigger =
- DSI_CMD_TRIGGER_SW;
- }
-
- rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-dma-tr", &tmp);
- panel_data->panel_info.mipi.dma_trigger =
- (!rc ? tmp : DSI_CMD_TRIGGER_SW);
- if (panel_data->panel_info.mipi.dma_trigger > 6) {
- pr_err("%s:%d, Invalid dma trigger. Forcing to sw trigger",
- __func__, __LINE__);
- panel_data->panel_info.mipi.dma_trigger =
- DSI_CMD_TRIGGER_SW;
- }
-
- rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-frame-rate", &tmp);
- panel_data->panel_info.mipi.frame_rate = (!rc ? tmp : 60);
-
data = of_get_property(np, "qcom,panel-phy-regulatorSettings", &len);
if ((!data) || (len != 6)) {
pr_err("%s:%d, Unable to read Phy regulator settings",
@@ -713,6 +631,102 @@
return rc;
}
+static int dsi_panel_parse_host_cfg(struct platform_device *pdev,
+ struct dsi_panel_common_pdata *panel_data)
+{
+ struct device_node *np = pdev->dev.of_node;
+ u32 res[6], tmp;
+ int rc;
+
+ rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-mode", &tmp);
+ panel_data->panel_info.mipi.mode = (!rc ? tmp : DSI_VIDEO_MODE);
+
+ rc = of_property_read_u32(np,
+ "qcom,mdss-pan-dsi-h-pulse-mode", &tmp);
+ panel_data->panel_info.mipi.pulse_mode_hsa_he = (!rc ? tmp : false);
+
+ rc = of_property_read_u32_array(np,
+ "qcom,mdss-pan-dsi-h-power-stop", res, 3);
+ panel_data->panel_info.mipi.hbp_power_stop = (!rc ? res[0] : false);
+ panel_data->panel_info.mipi.hsa_power_stop = (!rc ? res[1] : false);
+ panel_data->panel_info.mipi.hfp_power_stop = (!rc ? res[2] : false);
+
+ rc = of_property_read_u32_array(np,
+ "qcom,mdss-pan-dsi-bllp-power-stop", res, 2);
+ panel_data->panel_info.mipi.bllp_power_stop =
+ (!rc ? res[0] : false);
+ panel_data->panel_info.mipi.eof_bllp_power_stop =
+ (!rc ? res[1] : false);
+
+ rc = of_property_read_u32(np,
+ "qcom,mdss-pan-dsi-traffic-mode", &tmp);
+ panel_data->panel_info.mipi.traffic_mode =
+ (!rc ? tmp : DSI_NON_BURST_SYNCH_PULSE);
+
+ rc = of_property_read_u32(np,
+ "qcom,mdss-pan-dsi-dst-format", &tmp);
+ panel_data->panel_info.mipi.dst_format =
+ (!rc ? tmp : DSI_VIDEO_DST_FORMAT_RGB888);
+
+ rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-vc", &tmp);
+ panel_data->panel_info.mipi.vc = (!rc ? tmp : 0);
+
+ rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-rgb-swap", &tmp);
+ panel_data->panel_info.mipi.rgb_swap = (!rc ? tmp : DSI_RGB_SWAP_RGB);
+
+ rc = of_property_read_u32_array(np,
+ "qcom,mdss-pan-dsi-data-lanes", res, 4);
+ panel_data->panel_info.mipi.data_lane0 = (!rc ? res[0] : true);
+ panel_data->panel_info.mipi.data_lane1 = (!rc ? res[1] : false);
+ panel_data->panel_info.mipi.data_lane2 = (!rc ? res[2] : false);
+ panel_data->panel_info.mipi.data_lane3 = (!rc ? res[3] : false);
+
+ rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-dlane-swap", &tmp);
+ panel_data->panel_info.mipi.dlane_swap = (!rc ? tmp : 0);
+
+ rc = of_property_read_u32_array(np, "qcom,mdss-pan-dsi-t-clk", res, 2);
+ panel_data->panel_info.mipi.t_clk_pre = (!rc ? res[0] : 0x24);
+ panel_data->panel_info.mipi.t_clk_post = (!rc ? res[1] : 0x03);
+
+ rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-stream", &tmp);
+ panel_data->panel_info.mipi.stream = (!rc ? tmp : 0);
+
+ rc = of_property_read_u32(np, "qcom,mdss-pan-te-sel", &tmp);
+ panel_data->panel_info.mipi.te_sel = (!rc ? tmp : 1);
+
+ rc = of_property_read_u32(np, "qcom,mdss-pan-insert-dcs-cmd", &tmp);
+ panel_data->panel_info.mipi.insert_dcs_cmd = (!rc ? tmp : 1);
+
+ rc = of_property_read_u32(np, "qcom,mdss-pan-wr-mem-continue", &tmp);
+ panel_data->panel_info.mipi.wr_mem_continue = (!rc ? tmp : 0x3c);
+ rc = of_property_read_u32(np, "qcom,mdss-pan-wr-mem-start", &tmp);
+ panel_data->panel_info.mipi.wr_mem_start = (!rc ? tmp : 0x2c);
+
+ rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-mdp-tr", &tmp);
+ panel_data->panel_info.mipi.mdp_trigger =
+ (!rc ? tmp : DSI_CMD_TRIGGER_SW);
+ if (panel_data->panel_info.mipi.mdp_trigger > 6) {
+ pr_err("%s:%d, Invalid mdp trigger. Forcing to sw trigger",
+ __func__, __LINE__);
+ panel_data->panel_info.mipi.mdp_trigger =
+ DSI_CMD_TRIGGER_SW;
+ }
+
+ rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-dma-tr", &tmp);
+ panel_data->panel_info.mipi.dma_trigger =
+ (!rc ? tmp : DSI_CMD_TRIGGER_SW);
+ if (panel_data->panel_info.mipi.dma_trigger > 6) {
+ pr_err("%s:%d, Invalid dma trigger. Forcing to sw trigger",
+ __func__, __LINE__);
+ panel_data->panel_info.mipi.dma_trigger =
+ DSI_CMD_TRIGGER_SW;
+ }
+
+ rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-frame-rate", &tmp);
+ panel_data->panel_info.mipi.frame_rate = (!rc ? tmp : 60);
+ return rc;
+}
+
static int dsi_panel_parse_dt(struct platform_device *pdev,
struct dsi_panel_common_pdata *panel_data,
char *bl_ctrl)
@@ -755,6 +769,12 @@
return rc;
}
+ rc = dsi_panel_parse_host_cfg(pdev, panel_data);
+ if (rc) {
+ pr_err("fail to parse DSI host configs\n");
+ return rc;
+ }
+
rc = dsi_panel_parse_init_cmds(pdev, panel_data);
if (rc) {
pr_err("fail to parse DSI init commands\n");
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c
index 98e7e29..67004d5 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.c
+++ b/drivers/video/msm/mdss/mdp3_ctrl.c
@@ -19,6 +19,7 @@
#include <linux/major.h>
#include <linux/module.h>
#include <linux/uaccess.h>
+#include <linux/delay.h>
#include "mdp3_ctrl.h"
#include "mdp3.h"
@@ -26,7 +27,6 @@
#define MDP_CORE_CLK_RATE 100000000
#define MDP_VSYNC_CLK_RATE 19200000
-#define VSYNC_PERIOD 16
static void mdp3_ctrl_pan_display(struct msm_fb_data_type *mfd);
static int mdp3_overlay_unset(struct msm_fb_data_type *mfd, int ndx);
@@ -120,16 +120,30 @@
mutex_lock(&mdp3_session->lock);
mdp3_session->dma->vsync_enable(mdp3_session->dma, arg);
+ if (enable && mdp3_session->status == 1 && !mdp3_session->intf->active)
+ mod_timer(&mdp3_session->vsync_timer,
+ jiffies + msecs_to_jiffies(mdp3_session->vsync_period));
+ else if (!enable)
+ del_timer(&mdp3_session->vsync_timer);
+
mutex_unlock(&mdp3_session->lock);
spin_lock_irqsave(&mdp3_session->vsync_lock, flag);
- if (enable)
- INIT_COMPLETION(mdp3_session->vsync_comp);
- else
- complete(&mdp3_session->vsync_comp);
+ INIT_COMPLETION(mdp3_session->vsync_comp);
spin_unlock_irqrestore(&mdp3_session->vsync_lock, flag);
return 0;
}
+void mdp3_vsync_timer_func(unsigned long arg)
+{
+ struct mdp3_session_data *session = (struct mdp3_session_data *)arg;
+ if (session->status == 1 && !session->intf->active) {
+ pr_debug("mdp3_vsync_timer_func trigger\n");
+ vsync_notify_handler(session);
+ mod_timer(&session->vsync_timer,
+ jiffies + msecs_to_jiffies(session->vsync_period));
+ }
+}
+
static int mdp3_ctrl_async_blit_req(struct msm_fb_data_type *mfd,
void __user *p)
{
@@ -183,14 +197,15 @@
mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
rc = wait_for_completion_interruptible(&mdp3_session->vsync_comp);
- if (rc < 0)
+ if (rc < 0) {
+ pr_debug("mdp3_vsync_show_event interrupted\n");
return rc;
-
+ }
spin_lock_irqsave(&mdp3_session->vsync_lock, flag);
vsync_ticks = ktime_to_ns(mdp3_session->vsync_time);
spin_unlock_irqrestore(&mdp3_session->vsync_lock, flag);
- pr_debug("fb%d vsync=%llu", mfd->index, vsync_ticks);
+ pr_debug("fb%d vsync=%llu\n", mfd->index, vsync_ticks);
rc = snprintf(buf, PAGE_SIZE, "VSYNC=%llu", vsync_ticks);
return rc;
}
@@ -442,10 +457,13 @@
goto on_error;
}
- rc = mdp3_session->dma->start(mdp3_session->dma, mdp3_session->intf);
- if (rc) {
- pr_err("fail to start the MDP display interface\n");
- goto on_error;
+ if (mfd->fbi->screen_base) {
+ rc = mdp3_session->dma->start(mdp3_session->dma,
+ mdp3_session->intf);
+ if (rc) {
+ pr_err("fail to start the MDP display interface\n");
+ goto on_error;
+ }
}
on_error:
@@ -640,7 +658,8 @@
data = mdp3_bufq_pop(&mdp3_session->bufq_in);
if (data) {
mdp3_session->dma->update(mdp3_session->dma,
- (void *)data->addr);
+ (void *)data->addr,
+ mdp3_session->intf);
mdp3_bufq_push(&mdp3_session->bufq_out, data);
}
@@ -686,8 +705,14 @@
goto pan_error;
}
- mdp3_session->dma->update(mdp3_session->dma,
- (void *)mfd->iova + offset);
+ if (mfd->fbi->screen_base) {
+ mdp3_session->dma->update(mdp3_session->dma,
+ (void *)mfd->iova + offset,
+ mdp3_session->intf);
+ } else {
+ pr_debug("mdp3_ctrl_pan_display no memory, stop interface");
+ mdp3_session->intf->stop(mdp3_session->intf);
+ }
pan_error:
mutex_unlock(&mdp3_session->lock);
}
@@ -725,8 +750,6 @@
struct msmfb_overlay_data ov_data;
int val;
- pr_debug("mdp3_ctrl_ioctl_handler\n");
-
mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
if (!mdp3_session)
return -ENODEV;
@@ -844,6 +867,10 @@
mdp3_bufq_init(&mdp3_session->bufq_in);
mdp3_bufq_init(&mdp3_session->bufq_out);
+ init_timer(&mdp3_session->vsync_timer);
+ mdp3_session->vsync_timer.function = mdp3_vsync_timer_func;
+ mdp3_session->vsync_timer.data = (u32)mdp3_session;
+ mdp3_session->vsync_period = 1000 / mfd->panel_info->mipi.frame_rate;
mfd->mdp.private1 = mdp3_session;
rc = sysfs_create_group(&dev->kobj, &vsync_fs_attr_group);
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.h b/drivers/video/msm/mdss/mdp3_ctrl.h
index fb3bd36..8d2a235 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.h
+++ b/drivers/video/msm/mdss/mdp3_ctrl.h
@@ -17,6 +17,7 @@
#include <linux/types.h>
#include <linux/mutex.h>
#include <linux/completion.h>
+#include <linux/timer.h>
#include "mdp3.h"
#include "mdp3_dma.h"
@@ -41,7 +42,9 @@
struct msm_fb_data_type *mfd;
ktime_t vsync_time;
spinlock_t vsync_lock;
+ struct timer_list vsync_timer;
struct completion vsync_comp;
+ int vsync_period;
struct mdp_overlay overlay;
struct mdp3_buffer_queue bufq_in;
struct mdp3_buffer_queue bufq_out;
diff --git a/drivers/video/msm/mdss/mdp3_dma.c b/drivers/video/msm/mdss/mdp3_dma.c
index 94ad9be..ea8d47d 100644
--- a/drivers/video/msm/mdss/mdp3_dma.c
+++ b/drivers/video/msm/mdss/mdp3_dma.c
@@ -415,7 +415,8 @@
return 0;
}
-static int mdp3_dmap_update(struct mdp3_dma *dma, void *buf)
+static int mdp3_dmap_update(struct mdp3_dma *dma, void *buf,
+ struct mdp3_intf *intf)
{
unsigned long flag;
int cb_type = MDP3_DMA_CALLBACK_TYPE_VSYNC;
@@ -424,15 +425,20 @@
if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
cb_type |= MDP3_DMA_CALLBACK_TYPE_DMA_DONE;
- wait_for_completion_killable(&dma->dma_comp);
+ if (intf->active)
+ wait_for_completion_killable(&dma->dma_comp);
}
-
spin_lock_irqsave(&dma->dma_lock, flag);
MDP3_REG_WRITE(MDP3_REG_DMA_P_IBUF_ADDR, (u32)buf);
dma->source_config.buf = buf;
if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD)
MDP3_REG_WRITE(MDP3_REG_DMA_P_START, 1);
+ if (!intf->active) {
+ pr_debug("mdp3_dmap_update start interface\n");
+ intf->start(intf);
+ }
+
wmb();
init_completion(&dma->vsync_comp);
spin_unlock_irqrestore(&dma->dma_lock, flag);
@@ -444,14 +450,16 @@
return 0;
}
-static int mdp3_dmas_update(struct mdp3_dma *dma, void *buf)
+static int mdp3_dmas_update(struct mdp3_dma *dma, void *buf,
+ struct mdp3_intf *intf)
{
unsigned long flag;
int cb_type = MDP3_DMA_CALLBACK_TYPE_VSYNC;
if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
cb_type |= MDP3_DMA_CALLBACK_TYPE_DMA_DONE;
- wait_for_completion_killable(&dma->dma_comp);
+ if (intf->active)
+ wait_for_completion_killable(&dma->dma_comp);
}
spin_lock_irqsave(&dma->dma_lock, flag);
@@ -459,6 +467,12 @@
dma->source_config.buf = buf;
if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD)
MDP3_REG_WRITE(MDP3_REG_DMA_S_START, 1);
+
+ if (!intf->active) {
+ pr_debug("mdp3_dmap_update start interface\n");
+ intf->start(intf);
+ }
+
wmb();
init_completion(&dma->vsync_comp);
spin_unlock_irqrestore(&dma->dma_lock, flag);
diff --git a/drivers/video/msm/mdss/mdp3_dma.h b/drivers/video/msm/mdss/mdp3_dma.h
index f86bea9..faaeee2 100644
--- a/drivers/video/msm/mdss/mdp3_dma.h
+++ b/drivers/video/msm/mdss/mdp3_dma.h
@@ -251,7 +251,7 @@
struct mdp3_dma_ccs *ccs,
struct mdp3_dma_lut *lut);
- int (*update)(struct mdp3_dma *dma, void *buf);
+ int (*update)(struct mdp3_dma *dma, void *buf, struct mdp3_intf *intf);
int (*update_cursor)(struct mdp3_dma *dma, int x, int y);
diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index 5d7a0c9..963d3fb 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -288,7 +288,8 @@
struct pp_sts_type *pp_sts,
struct mdp_sharp_cfg *sharp_config);
static int mdss_ad_init_checks(struct msm_fb_data_type *mfd);
-static struct mdss_ad_info *mdss_mdp_get_ad(struct msm_fb_data_type *mfd);
+static int mdss_mdp_get_ad(struct msm_fb_data_type *mfd,
+ struct mdss_ad_info **ad);
static int pp_update_ad_input(struct msm_fb_data_type *mfd);
static void pp_ad_vsync_handler(struct mdss_mdp_ctl *ctl, ktime_t t);
static void pp_ad_cfg_write(struct mdss_ad_info *ad);
@@ -2548,7 +2549,7 @@
hist_info = &mdss_pp_res->dspp_hist[dspp_num];
mutex_lock(&hist_info->hist_mutex);
for (j = 0; j < HIST_V_SIZE; j++)
- hist_concat[i] += hist_info->data[i];
+ hist_concat[j] += hist_info->data[j];
mutex_unlock(&hist_info->hist_mutex);
}
hist_data_addr = hist_concat;
@@ -2731,8 +2732,12 @@
}
mixer_num = mdss_mdp_get_ctl_mixers(mfd->index, mixer_id);
- if (!mixer_num || mixer_num > MDSS_AD_MAX_MIXERS) {
- pr_err("invalid mixer_num, %d", mixer_num);
+ if (!mixer_num) {
+ pr_debug("no mixers connected, %d", mixer_num);
+ return -EHOSTDOWN;
+ }
+ if (mixer_num > MDSS_AD_MAX_MIXERS) {
+ pr_warn("too many mixers, not supported, %d", mixer_num);
return ret;
}
@@ -2747,9 +2752,10 @@
return mixer_id[0];
}
-static struct mdss_ad_info *mdss_mdp_get_ad(struct msm_fb_data_type *mfd)
+static int mdss_mdp_get_ad(struct msm_fb_data_type *mfd,
+ struct mdss_ad_info **ret_ad)
{
- int ad_num;
+ int ad_num, ret = 0;
struct mdss_data_type *mdata;
struct mdss_ad_info *ad = NULL;
mdata = mfd_to_mdata(mfd);
@@ -2757,11 +2763,15 @@
ad_num = mdss_ad_init_checks(mfd);
if (ad_num >= 0)
ad = &mdata->ad_cfgs[ad_num];
- return ad;
+ else
+ ret = ad_num;
+ *ret_ad = ad;
+ return ret;
}
static int pp_update_ad_input(struct msm_fb_data_type *mfd)
{
+ int ret;
struct mdss_ad_info *ad;
struct mdss_ad_input input;
struct mdss_mdp_ctl *ctl;
@@ -2772,7 +2782,9 @@
if (!ctl)
return -EINVAL;
- ad = mdss_mdp_get_ad(mfd);
+ ret = mdss_mdp_get_ad(mfd, &ad);
+ if (ret)
+ return ret;
if (!ad || ad->cfg.mode == MDSS_AD_MODE_AUTO_BL)
return -EINVAL;
@@ -2795,9 +2807,9 @@
int lin_ret = -1, inv_ret = -1, ret = 0;
u32 ratio_temp, shift = 0;
- ad = mdss_mdp_get_ad(mfd);
- if (!ad)
- return -EINVAL;
+ ret = mdss_mdp_get_ad(mfd, &ad);
+ if (ret)
+ return ret;
mutex_lock(&ad->lock);
if (init_cfg->ops & MDP_PP_AD_INIT) {
@@ -2862,9 +2874,9 @@
struct mdss_mdp_ctl *ctl;
u32 bl;
- ad = mdss_mdp_get_ad(mfd);
- if (!ad)
- return -EINVAL;
+ ret = mdss_mdp_get_ad(mfd, &ad);
+ if (ret)
+ return ret;
mutex_lock(&ad->lock);
if ((!PP_AD_STATE_IS_INITCFG(ad->state) &&
@@ -3074,9 +3086,9 @@
char __iomem *base;
u32 bypass = MDSS_PP_AD_BYPASS_DEF, bl;
- ad = mdss_mdp_get_ad(mfd);
- if (!ad)
- return -EINVAL;
+ ret = mdss_mdp_get_ad(mfd, &ad);
+ if (ret)
+ return ret;
base = ad->base;
diff --git a/include/linux/dvb/dmx.h b/include/linux/dvb/dmx.h
index ce9e5b9..bd954ee 100644
--- a/include/linux/dvb/dmx.h
+++ b/include/linux/dvb/dmx.h
@@ -528,6 +528,9 @@
/* Indicates whether demux support sending data directly to subtitle decoder */
#define DMX_CAP_SUBTITLE_DECODER_DATA 0x10
+/* Indicates whether TS insertion is supported */
+#define DMX_CAP_TS_INSERTION 0x20
+
/* Number of decoders demux can output data to */
int num_decoders;
diff --git a/include/media/msmb_pproc.h b/include/media/msmb_pproc.h
index 6cd4995..8e9aedf 100644
--- a/include/media/msmb_pproc.h
+++ b/include/media/msmb_pproc.h
@@ -69,6 +69,7 @@
int bytes_per_pixel;
unsigned int source_address;
unsigned int destination_address;
+ unsigned int compl_destination_address;
unsigned int src_stride;
unsigned int dst_stride;
int rotate_270;
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 1a07d2e..3513fef 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -5890,6 +5890,7 @@
{
struct rq *rq = cpu_rq(cpu);
struct sched_domain *tmp;
+ unsigned long next_balance = rq->next_balance;
/* Remove the sched domains which do not contribute to scheduling. */
for (tmp = sd; tmp; ) {
@@ -5914,6 +5915,17 @@
sd->child = NULL;
}
+ for (tmp = sd; tmp; ) {
+ unsigned long interval;
+
+ interval = msecs_to_jiffies(tmp->balance_interval);
+ if (time_after(next_balance, tmp->last_balance + interval))
+ next_balance = tmp->last_balance + interval;
+
+ tmp = tmp->parent;
+ }
+ rq->next_balance = next_balance;
+
sched_domain_debug(sd, cpu);
rq_attach_root(rq, rd);
diff --git a/scripts/dtc/Makefile b/scripts/dtc/Makefile
index 6d1c6bb..2a48022 100644
--- a/scripts/dtc/Makefile
+++ b/scripts/dtc/Makefile
@@ -27,3 +27,5 @@
# dependencies on generated files need to be listed explicitly
$(obj)/dtc-lexer.lex.o: $(obj)/dtc-parser.tab.h
+# generated files need to be cleaned explicitly
+clean-files := dtc-lexer.lex.c dtc-parser.tab.c dtc-parser.tab.h
diff --git a/scripts/dtc/Makefile.dtc b/scripts/dtc/Makefile.dtc
index 6ddf9ec..bece49b 100644
--- a/scripts/dtc/Makefile.dtc
+++ b/scripts/dtc/Makefile.dtc
@@ -3,7 +3,16 @@
# This is not a complete Makefile of itself. Instead, it is designed to
# be easily embeddable into other systems of Makefiles.
#
-DTC_SRCS = dtc.c flattree.c fstree.c data.c livetree.c treesource.c srcpos.c \
- checks.c
+DTC_SRCS = \
+ checks.c \
+ data.c \
+ dtc.c \
+ flattree.c \
+ fstree.c \
+ livetree.c \
+ srcpos.c \
+ treesource.c \
+ util.c
+
DTC_GEN_SRCS = dtc-lexer.lex.c dtc-parser.tab.c
DTC_OBJS = $(DTC_SRCS:%.c=%.o) $(DTC_GEN_SRCS:%.c=%.o)
diff --git a/scripts/dtc/checks.c b/scripts/dtc/checks.c
index a662a00..ee96a25 100644
--- a/scripts/dtc/checks.c
+++ b/scripts/dtc/checks.c
@@ -31,12 +31,6 @@
#define TRACE(c, fmt, ...) do { } while (0)
#endif
-enum checklevel {
- IGNORE = 0,
- WARN = 1,
- ERROR = 2,
-};
-
enum checkstatus {
UNCHECKED = 0,
PREREQ,
@@ -57,14 +51,14 @@
node_check_fn node_fn;
prop_check_fn prop_fn;
void *data;
- enum checklevel level;
+ bool warn, error;
enum checkstatus status;
int inprogress;
int num_prereqs;
struct check **prereq;
};
-#define CHECK(nm, tfn, nfn, pfn, d, lvl, ...) \
+#define CHECK_ENTRY(nm, tfn, nfn, pfn, d, w, e, ...) \
static struct check *nm##_prereqs[] = { __VA_ARGS__ }; \
static struct check nm = { \
.name = #nm, \
@@ -72,20 +66,37 @@
.node_fn = (nfn), \
.prop_fn = (pfn), \
.data = (d), \
- .level = (lvl), \
+ .warn = (w), \
+ .error = (e), \
.status = UNCHECKED, \
.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_CHECK(nm, d, lvl, ...) \
- CHECK(nm, check_##nm, NULL, NULL, d, lvl, __VA_ARGS__)
-#define NODE_CHECK(nm, d, lvl, ...) \
- CHECK(nm, NULL, check_##nm, NULL, d, lvl, __VA_ARGS__)
-#define PROP_CHECK(nm, d, lvl, ...) \
- CHECK(nm, NULL, NULL, check_##nm, d, lvl, __VA_ARGS__)
-#define BATCH_CHECK(nm, lvl, ...) \
- CHECK(nm, NULL, NULL, NULL, NULL, lvl, __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)));
@@ -95,13 +106,13 @@
va_list ap;
va_start(ap, fmt);
- if ((c->level < WARN) || (c->level <= quiet))
- return; /* Suppress message */
-
- fprintf(stderr, "%s (%s): ",
- (c->level == ERROR) ? "ERROR" : "Warning", c->name);
- vfprintf(stderr, fmt, ap);
- fprintf(stderr, "\n");
+ if ((c->warn && (quiet < 1))
+ || (c->error && (quiet < 2))) {
+ fprintf(stderr, "%s (%s): ",
+ (c->error) ? "ERROR" : "Warning", c->name);
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\n");
+ }
}
#define FAIL(c, ...) \
@@ -167,7 +178,7 @@
out:
c->inprogress = 0;
- if ((c->status != PASSED) && (c->level == ERROR))
+ if ((c->status != PASSED) && (c->error))
error = 1;
return error;
}
@@ -176,6 +187,13 @@
* Utility check functions
*/
+/* A check which always fails, for testing purposes only */
+static inline void check_always_fail(struct check *c, struct node *dt)
+{
+ FAIL(c, "always_fail check");
+}
+TREE_CHECK(always_fail, NULL);
+
static void check_is_string(struct check *c, struct node *root,
struct node *node)
{
@@ -190,8 +208,10 @@
FAIL(c, "\"%s\" property in %s is not a string",
propname, node->fullpath);
}
-#define CHECK_IS_STRING(nm, propname, lvl) \
- CHECK(nm, NULL, check_is_string, NULL, (propname), (lvl))
+#define WARNING_IF_NOT_STRING(nm, propname) \
+ WARNING(nm, NULL, check_is_string, NULL, (propname))
+#define ERROR_IF_NOT_STRING(nm, propname) \
+ ERROR(nm, NULL, check_is_string, NULL, (propname))
static void check_is_cell(struct check *c, struct node *root,
struct node *node)
@@ -207,8 +227,10 @@
FAIL(c, "\"%s\" property in %s is not a single cell",
propname, node->fullpath);
}
-#define CHECK_IS_CELL(nm, propname, lvl) \
- CHECK(nm, NULL, check_is_cell, NULL, (propname), (lvl))
+#define WARNING_IF_NOT_CELL(nm, propname) \
+ WARNING(nm, NULL, check_is_cell, NULL, (propname))
+#define ERROR_IF_NOT_CELL(nm, propname) \
+ ERROR(nm, NULL, check_is_cell, NULL, (propname))
/*
* Structural check functions
@@ -227,20 +249,24 @@
FAIL(c, "Duplicate node name %s",
child->fullpath);
}
-NODE_CHECK(duplicate_node_names, NULL, ERROR);
+NODE_ERROR(duplicate_node_names, NULL);
static void check_duplicate_property_names(struct check *c, struct node *dt,
struct node *node)
{
struct property *prop, *prop2;
- for_each_property(node, prop)
- for (prop2 = prop->next; prop2; prop2 = prop2->next)
+ for_each_property(node, prop) {
+ for (prop2 = prop->next; prop2; prop2 = prop2->next) {
+ if (prop2->deleted)
+ continue;
if (streq(prop->name, prop2->name))
FAIL(c, "Duplicate property name %s in %s",
prop->name, node->fullpath);
+ }
+ }
}
-NODE_CHECK(duplicate_property_names, NULL, ERROR);
+NODE_ERROR(duplicate_property_names, NULL);
#define LOWERCASE "abcdefghijklmnopqrstuvwxyz"
#define UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
@@ -256,7 +282,7 @@
FAIL(c, "Bad character '%c' in node %s",
node->name[n], node->fullpath);
}
-NODE_CHECK(node_name_chars, PROPNODECHARS "@", ERROR);
+NODE_ERROR(node_name_chars, PROPNODECHARS "@");
static void check_node_name_format(struct check *c, struct node *dt,
struct node *node)
@@ -265,7 +291,7 @@
FAIL(c, "Node %s has multiple '@' characters in name",
node->fullpath);
}
-NODE_CHECK(node_name_format, NULL, ERROR, &node_name_chars);
+NODE_ERROR(node_name_format, NULL, &node_name_chars);
static void check_property_name_chars(struct check *c, struct node *dt,
struct node *node, struct property *prop)
@@ -276,7 +302,7 @@
FAIL(c, "Bad character '%c' in property name \"%s\", node %s",
prop->name[n], prop->name, node->fullpath);
}
-PROP_CHECK(property_name_chars, PROPNODECHARS, ERROR);
+PROP_ERROR(property_name_chars, PROPNODECHARS);
#define DESCLABEL_FMT "%s%s%s%s%s"
#define DESCLABEL_ARGS(node,prop,mark) \
@@ -331,8 +357,8 @@
for_each_marker_of_type(m, LABEL)
check_duplicate_label(c, dt, m->ref, node, prop, m);
}
-CHECK(duplicate_label, NULL, check_duplicate_label_node,
- check_duplicate_label_prop, NULL, ERROR);
+ERROR(duplicate_label, NULL, check_duplicate_label_node,
+ check_duplicate_label_prop, NULL);
static void check_explicit_phandles(struct check *c, struct node *root,
struct node *node, struct property *prop)
@@ -391,7 +417,7 @@
node->phandle = phandle;
}
-PROP_CHECK(explicit_phandles, NULL, ERROR);
+PROP_ERROR(explicit_phandles, NULL);
static void check_name_properties(struct check *c, struct node *root,
struct node *node)
@@ -420,8 +446,8 @@
free(prop);
}
}
-CHECK_IS_STRING(name_is_string, "name", ERROR);
-NODE_CHECK(name_properties, NULL, ERROR, &name_is_string);
+ERROR_IF_NOT_STRING(name_is_string, "name");
+NODE_ERROR(name_properties, NULL, &name_is_string);
/*
* Reference fixup functions
@@ -448,7 +474,7 @@
*((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle);
}
}
-CHECK(phandle_references, NULL, NULL, fixup_phandle_references, NULL, ERROR,
+ERROR(phandle_references, NULL, NULL, fixup_phandle_references, NULL,
&duplicate_node_names, &explicit_phandles);
static void fixup_path_references(struct check *c, struct node *dt,
@@ -473,19 +499,19 @@
strlen(path) + 1);
}
}
-CHECK(path_references, NULL, NULL, fixup_path_references, NULL, ERROR,
+ERROR(path_references, NULL, NULL, fixup_path_references, NULL,
&duplicate_node_names);
/*
* Semantic checks
*/
-CHECK_IS_CELL(address_cells_is_cell, "#address-cells", WARN);
-CHECK_IS_CELL(size_cells_is_cell, "#size-cells", WARN);
-CHECK_IS_CELL(interrupt_cells_is_cell, "#interrupt-cells", WARN);
+WARNING_IF_NOT_CELL(address_cells_is_cell, "#address-cells");
+WARNING_IF_NOT_CELL(size_cells_is_cell, "#size-cells");
+WARNING_IF_NOT_CELL(interrupt_cells_is_cell, "#interrupt-cells");
-CHECK_IS_STRING(device_type_is_string, "device_type", WARN);
-CHECK_IS_STRING(model_is_string, "model", WARN);
-CHECK_IS_STRING(status_is_string, "status", WARN);
+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,
struct node *node)
@@ -503,8 +529,8 @@
if (prop)
node->size_cells = propval_cell(prop);
}
-CHECK(addr_size_cells, NULL, fixup_addr_size_cells, NULL, NULL, WARN,
- &address_cells_is_cell, &size_cells_is_cell);
+WARNING(addr_size_cells, NULL, fixup_addr_size_cells, NULL, NULL,
+ &address_cells_is_cell, &size_cells_is_cell);
#define node_addr_cells(n) \
(((n)->addr_cells == -1) ? 2 : (n)->addr_cells)
@@ -538,7 +564,7 @@
"(#address-cells == %d, #size-cells == %d)",
node->fullpath, prop->val.len, addr_cells, size_cells);
}
-NODE_CHECK(reg_format, NULL, WARN, &addr_size_cells);
+NODE_WARNING(reg_format, NULL, &addr_size_cells);
static void check_ranges_format(struct check *c, struct node *dt,
struct node *node)
@@ -579,7 +605,7 @@
p_addr_cells, c_addr_cells, c_size_cells);
}
}
-NODE_CHECK(ranges_format, NULL, WARN, &addr_size_cells);
+NODE_WARNING(ranges_format, NULL, &addr_size_cells);
/*
* Style checks
@@ -606,7 +632,7 @@
FAIL(c, "Relying on default #size-cells value for %s",
node->fullpath);
}
-NODE_CHECK(avoid_default_addr_size, NULL, WARN, &addr_size_cells);
+NODE_WARNING(avoid_default_addr_size, NULL, &addr_size_cells);
static void check_obsolete_chosen_interrupt_controller(struct check *c,
struct node *dt)
@@ -623,7 +649,7 @@
FAIL(c, "/chosen has obsolete \"interrupt-controller\" "
"property");
}
-TREE_CHECK(obsolete_chosen_interrupt_controller, NULL, WARN);
+TREE_WARNING(obsolete_chosen_interrupt_controller, NULL);
static struct check *check_table[] = {
&duplicate_node_names, &duplicate_property_names,
@@ -642,8 +668,71 @@
&avoid_default_addr_size,
&obsolete_chosen_interrupt_controller,
+
+ &always_fail,
};
+static void enable_warning_error(struct check *c, bool warn, bool error)
+{
+ int i;
+
+ /* Raising level, also raise it for prereqs */
+ if ((warn && !c->warn) || (error && !c->error))
+ for (i = 0; i < c->num_prereqs; i++)
+ enable_warning_error(c->prereq[i], warn, error);
+
+ c->warn = c->warn || warn;
+ c->error = c->error || error;
+}
+
+static void disable_warning_error(struct check *c, bool warn, bool error)
+{
+ int i;
+
+ /* Lowering level, also lower it for things this is the prereq
+ * for */
+ if ((warn && c->warn) || (error && c->error)) {
+ for (i = 0; i < ARRAY_SIZE(check_table); i++) {
+ struct check *cc = check_table[i];
+ int j;
+
+ for (j = 0; j < cc->num_prereqs; j++)
+ if (cc->prereq[j] == c)
+ disable_warning_error(cc, warn, error);
+ }
+ }
+
+ c->warn = c->warn && !warn;
+ c->error = c->error && !error;
+}
+
+void parse_checks_option(bool warn, bool error, const char *optarg)
+{
+ int i;
+ const char *name = optarg;
+ bool enable = true;
+
+ if ((strncmp(optarg, "no-", 3) == 0)
+ || (strncmp(optarg, "no_", 3) == 0)) {
+ name = optarg + 3;
+ enable = false;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(check_table); i++) {
+ struct check *c = check_table[i];
+
+ if (streq(c->name, name)) {
+ if (enable)
+ enable_warning_error(c, warn, error);
+ else
+ disable_warning_error(c, warn, error);
+ return;
+ }
+ }
+
+ die("Unrecognized check name \"%s\"\n", name);
+}
+
void process_checks(int force, struct boot_info *bi)
{
struct node *dt = bi->dt;
@@ -653,7 +742,7 @@
for (i = 0; i < ARRAY_SIZE(check_table); i++) {
struct check *c = check_table[i];
- if (c->level != IGNORE)
+ if (c->warn || c->error)
error = error || run_check(c, dt);
}
diff --git a/scripts/dtc/data.c b/scripts/dtc/data.c
index fe555e8..4a40c5b 100644
--- a/scripts/dtc/data.c
+++ b/scripts/dtc/data.c
@@ -68,40 +68,6 @@
return d;
}
-static char get_oct_char(const char *s, int *i)
-{
- char x[4];
- char *endx;
- long val;
-
- x[3] = '\0';
- strncpy(x, s + *i, 3);
-
- val = strtol(x, &endx, 8);
-
- assert(endx > x);
-
- (*i) += endx - x;
- return val;
-}
-
-static char get_hex_char(const char *s, int *i)
-{
- char x[3];
- char *endx;
- long val;
-
- x[2] = '\0';
- strncpy(x, s + *i, 2);
-
- val = strtol(x, &endx, 16);
- if (!(endx > x))
- die("\\x used with no following hex digits\n");
-
- (*i) += endx - x;
- return val;
-}
-
struct data data_copy_escape_string(const char *s, int len)
{
int i = 0;
@@ -114,53 +80,10 @@
while (i < len) {
char c = s[i++];
- if (c != '\\') {
- q[d.len++] = c;
- continue;
- }
+ if (c == '\\')
+ c = get_escape_char(s, &i);
- c = s[i++];
- assert(c);
- switch (c) {
- case 'a':
- q[d.len++] = '\a';
- break;
- case 'b':
- q[d.len++] = '\b';
- break;
- case 't':
- q[d.len++] = '\t';
- break;
- case 'n':
- q[d.len++] = '\n';
- break;
- case 'v':
- q[d.len++] = '\v';
- break;
- case 'f':
- q[d.len++] = '\f';
- break;
- case 'r':
- q[d.len++] = '\r';
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- i--; /* need to re-read the first digit as
- * part of the octal value */
- q[d.len++] = get_oct_char(s, &i);
- break;
- case 'x':
- q[d.len++] = get_hex_char(s, &i);
- break;
- default:
- q[d.len++] = c;
- }
+ q[d.len++] = c;
}
q[d.len++] = '\0';
@@ -245,11 +168,33 @@
return d;
}
-struct data data_append_cell(struct data d, cell_t word)
+struct data data_append_integer(struct data d, uint64_t value, int bits)
{
- cell_t beword = cpu_to_fdt32(word);
+ uint8_t value_8;
+ uint16_t value_16;
+ uint32_t value_32;
+ uint64_t value_64;
- return data_append_data(d, &beword, sizeof(beword));
+ switch (bits) {
+ case 8:
+ value_8 = value;
+ return data_append_data(d, &value_8, 1);
+
+ case 16:
+ value_16 = cpu_to_fdt16(value);
+ return data_append_data(d, &value_16, 2);
+
+ case 32:
+ value_32 = cpu_to_fdt32(value);
+ return data_append_data(d, &value_32, 4);
+
+ case 64:
+ value_64 = cpu_to_fdt64(value);
+ return data_append_data(d, &value_64, 8);
+
+ default:
+ die("Invalid literal size (%d)\n", bits);
+ }
}
struct data data_append_re(struct data d, const struct fdt_reserve_entry *re)
@@ -262,11 +207,14 @@
return data_append_data(d, &bere, sizeof(bere));
}
+struct data data_append_cell(struct data d, cell_t word)
+{
+ return data_append_integer(d, word, sizeof(word) * 8);
+}
+
struct data data_append_addr(struct data d, uint64_t addr)
{
- uint64_t beaddr = cpu_to_fdt64(addr);
-
- return data_append_data(d, &beaddr, sizeof(beaddr));
+ return data_append_integer(d, addr, sizeof(addr) * 8);
}
struct data data_append_byte(struct data d, uint8_t byte)
diff --git a/scripts/dtc/dtc-lexer.l b/scripts/dtc/dtc-lexer.l
index e866ea5..254d5af 100644
--- a/scripts/dtc/dtc-lexer.l
+++ b/scripts/dtc/dtc-lexer.l
@@ -29,6 +29,7 @@
PATHCHAR ({PROPNODECHAR}|[/])
LABEL [a-zA-Z_][a-zA-Z0-9_]*
STRING \"([^\\"]|\\.)*\"
+CHAR_LITERAL '([^']|\\')*'
WS [[:space:]]
COMMENT "/*"([^*]|\*+[^*/])*\*+"/"
LINECOMMENT "//".*\n
@@ -70,6 +71,27 @@
push_input_file(name);
}
+<*>^"#"(line)?{WS}+[0-9]+{WS}+{STRING}({WS}+[0-9]+)? {
+ char *line, *tmp, *fn;
+ /* skip text before line # */
+ line = yytext;
+ while (!isdigit(*line))
+ line++;
+ /* skip digits in line # */
+ tmp = line;
+ while (!isspace(*tmp))
+ tmp++;
+ /* "NULL"-terminate line # */
+ *tmp = '\0';
+ /* start of filename */
+ fn = strchr(tmp + 1, '"') + 1;
+ /* strip trailing " from filename */
+ tmp = strchr(fn, '"');
+ *tmp = 0;
+ /* -1 since #line is the number of the next line */
+ srcpos_set_line(xstrdup(fn), atoi(line) - 1);
+ }
+
<*><<EOF>> {
if (!pop_input_file()) {
yyterminate();
@@ -96,6 +118,26 @@
return DT_MEMRESERVE;
}
+<*>"/bits/" {
+ DPRINT("Keyword: /bits/\n");
+ BEGIN_DEFAULT();
+ return DT_BITS;
+ }
+
+<*>"/delete-property/" {
+ DPRINT("Keyword: /delete-property/\n");
+ DPRINT("<PROPNODENAME>\n");
+ BEGIN(PROPNODENAME);
+ return DT_DEL_PROP;
+ }
+
+<*>"/delete-node/" {
+ DPRINT("Keyword: /delete-node/\n");
+ DPRINT("<PROPNODENAME>\n");
+ BEGIN(PROPNODENAME);
+ return DT_DEL_NODE;
+ }
+
<*>{LABEL}: {
DPRINT("Label: %s\n", yytext);
yylval.labelref = xstrdup(yytext);
@@ -103,12 +145,19 @@
return DT_LABEL;
}
-<V1>[0-9]+|0[xX][0-9a-fA-F]+ {
+<V1>([0-9]+|0[xX][0-9a-fA-F]+)(U|L|UL|LL|ULL)? {
yylval.literal = xstrdup(yytext);
DPRINT("Literal: '%s'\n", yylval.literal);
return DT_LITERAL;
}
+<*>{CHAR_LITERAL} {
+ yytext[yyleng-1] = '\0';
+ yylval.literal = xstrdup(yytext+1);
+ DPRINT("Character literal: %s\n", yylval.literal);
+ return DT_CHAR_LITERAL;
+ }
+
<*>\&{LABEL} { /* label reference */
DPRINT("Ref: %s\n", yytext+1);
yylval.labelref = xstrdup(yytext+1);
@@ -134,9 +183,10 @@
return ']';
}
-<PROPNODENAME>{PROPNODECHAR}+ {
+<PROPNODENAME>\\?{PROPNODECHAR}+ {
DPRINT("PropNodeName: %s\n", yytext);
- yylval.propnodename = xstrdup(yytext);
+ yylval.propnodename = xstrdup((yytext[0] == '\\') ?
+ yytext + 1 : yytext);
BEGIN_DEFAULT();
return DT_PROPNODENAME;
}
@@ -150,6 +200,15 @@
<*>{COMMENT}+ /* eat C-style comments */
<*>{LINECOMMENT}+ /* eat C++-style comments */
+<*>"<<" { return DT_LSHIFT; };
+<*>">>" { return DT_RSHIFT; };
+<*>"<=" { return DT_LE; };
+<*>">=" { return DT_GE; };
+<*>"==" { return DT_EQ; };
+<*>"!=" { return DT_NE; };
+<*>"&&" { return DT_AND; };
+<*>"||" { return DT_OR; };
+
<*>. {
DPRINT("Char: %c (\\x%02x)\n", yytext[0],
(unsigned)yytext[0]);
diff --git a/scripts/dtc/dtc-lexer.lex.c_shipped b/scripts/dtc/dtc-lexer.lex.c_shipped
index 8bbe128..a6c5fcd 100644
--- a/scripts/dtc/dtc-lexer.lex.c_shipped
+++ b/scripts/dtc/dtc-lexer.lex.c_shipped
@@ -1,5 +1,6 @@
+#line 2 "dtc-lexer.lex.c"
-#line 3 "scripts/dtc/dtc-lexer.lex.c_shipped"
+#line 4 "dtc-lexer.lex.c"
#define YY_INT_ALIGNED short int
@@ -53,7 +54,6 @@
typedef unsigned char flex_uint8_t;
typedef unsigned short int flex_uint16_t;
typedef unsigned int flex_uint32_t;
-#endif /* ! C99 */
/* Limits of integral types. */
#ifndef INT8_MIN
@@ -84,6 +84,8 @@
#define UINT32_MAX (4294967295U)
#endif
+#endif /* ! C99 */
+
#endif /* ! FLEXINT_H */
#ifdef __cplusplus
@@ -140,7 +142,15 @@
/* Size of default input buffer. */
#ifndef YY_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k.
+ * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
+ * Ditto for the __ia64__ case accordingly.
+ */
+#define YY_BUF_SIZE 32768
+#else
#define YY_BUF_SIZE 16384
+#endif /* __ia64__ */
#endif
/* The state buf must be large enough to hold one state per character in the main buffer.
@@ -362,8 +372,8 @@
*yy_cp = '\0'; \
(yy_c_buf_p) = yy_cp;
-#define YY_NUM_RULES 17
-#define YY_END_OF_BUFFER 18
+#define YY_NUM_RULES 30
+#define YY_END_OF_BUFFER 31
/* This struct is not used in this scanner,
but its presence is necessary. */
struct yy_trans_info
@@ -371,19 +381,25 @@
flex_int32_t yy_verify;
flex_int32_t yy_nxt;
};
-static yyconst flex_int16_t yy_accept[94] =
+static yyconst flex_int16_t yy_accept[161] =
{ 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 18, 16, 13, 13, 16, 16, 16, 16, 16, 16,
- 16, 10, 11, 11, 6, 6, 13, 0, 2, 0,
- 7, 0, 0, 0, 0, 0, 0, 0, 5, 0,
- 9, 9, 11, 11, 6, 0, 7, 0, 0, 0,
- 0, 15, 0, 0, 0, 0, 6, 0, 14, 0,
- 0, 0, 0, 0, 8, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 3, 12,
- 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
- 0, 4, 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, 19, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 16, 13, 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
} ;
static yyconst flex_int32_t yy_ec[256] =
@@ -391,17 +407,17 @@
1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 2, 1, 4, 5, 1, 1, 6, 1, 1,
- 1, 7, 5, 5, 8, 5, 9, 10, 11, 12,
- 12, 12, 12, 12, 12, 12, 12, 13, 1, 1,
- 1, 1, 5, 5, 14, 14, 14, 14, 14, 14,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 16, 15, 15,
- 1, 17, 18, 1, 15, 1, 14, 19, 20, 21,
+ 1, 2, 4, 5, 6, 1, 1, 7, 8, 1,
+ 1, 9, 10, 10, 11, 10, 12, 13, 14, 15,
+ 15, 15, 15, 15, 15, 15, 15, 16, 1, 17,
+ 18, 19, 10, 10, 20, 20, 20, 20, 20, 20,
+ 21, 21, 21, 21, 21, 22, 21, 21, 21, 21,
+ 21, 21, 21, 21, 23, 21, 21, 24, 21, 21,
+ 1, 25, 26, 1, 21, 1, 20, 27, 28, 29,
- 22, 14, 15, 15, 23, 15, 15, 24, 25, 26,
- 15, 15, 15, 27, 28, 29, 30, 31, 15, 16,
- 15, 15, 32, 1, 33, 1, 1, 1, 1, 1,
+ 30, 20, 21, 21, 31, 21, 21, 32, 33, 34,
+ 35, 36, 21, 37, 38, 39, 40, 41, 21, 24,
+ 42, 21, 43, 44, 45, 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,
@@ -418,112 +434,163 @@
1, 1, 1, 1, 1
} ;
-static yyconst flex_int32_t yy_meta[34] =
+static yyconst flex_int32_t yy_meta[46] =
{ 0,
- 1, 1, 1, 1, 2, 1, 2, 2, 3, 4,
- 4, 4, 5, 6, 7, 7, 1, 1, 6, 6,
- 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 8, 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, 1
} ;
-static yyconst flex_int16_t yy_base[106] =
+static yyconst flex_int16_t yy_base[175] =
{ 0,
- 0, 0, 237, 236, 25, 0, 47, 0, 30, 71,
- 244, 247, 82, 84, 84, 211, 95, 229, 218, 0,
- 111, 247, 0, 84, 83, 95, 106, 86, 247, 237,
- 0, 230, 231, 234, 207, 209, 212, 220, 247, 206,
- 247, 218, 0, 106, 116, 0, 0, 0, 223, 89,
- 226, 219, 199, 206, 200, 204, 0, 190, 213, 212,
- 202, 91, 178, 161, 247, 172, 144, 150, 140, 130,
- 140, 124, 128, 120, 138, 137, 123, 122, 247, 247,
- 134, 114, 132, 86, 135, 125, 90, 136, 247, 97,
- 29, 247, 247, 153, 156, 161, 165, 170, 176, 180,
+ 0, 388, 381, 40, 41, 386, 71, 385, 34, 44,
+ 390, 395, 60, 62, 371, 112, 111, 111, 111, 104,
+ 370, 106, 371, 342, 124, 119, 0, 144, 395, 0,
+ 123, 0, 159, 153, 165, 167, 395, 130, 395, 382,
+ 395, 0, 372, 122, 395, 157, 374, 379, 350, 21,
+ 346, 349, 395, 395, 395, 395, 395, 362, 395, 395,
+ 181, 346, 342, 395, 359, 0, 191, 343, 190, 351,
+ 350, 0, 0, 0, 173, 362, 177, 367, 357, 329,
+ 335, 328, 337, 331, 206, 329, 334, 327, 395, 338,
+ 170, 314, 346, 345, 318, 325, 343, 158, 316, 212,
- 187, 195, 200, 205, 212
+ 322, 319, 320, 395, 340, 336, 308, 305, 314, 304,
+ 295, 138, 208, 220, 395, 292, 305, 265, 264, 254,
+ 201, 222, 285, 275, 273, 270, 236, 235, 225, 115,
+ 395, 395, 252, 216, 216, 217, 214, 230, 209, 220,
+ 213, 239, 211, 217, 216, 209, 229, 395, 240, 225,
+ 206, 169, 395, 395, 116, 106, 99, 54, 395, 395,
+ 254, 260, 268, 272, 276, 282, 289, 293, 301, 309,
+ 313, 319, 327, 335
} ;
-static yyconst flex_int16_t yy_def[106] =
+static yyconst flex_int16_t yy_def[175] =
{ 0,
- 93, 1, 1, 1, 1, 5, 93, 7, 1, 1,
- 93, 93, 93, 93, 94, 95, 93, 96, 17, 97,
- 96, 93, 98, 99, 93, 93, 93, 94, 93, 94,
- 100, 93, 101, 102, 93, 93, 93, 96, 93, 93,
- 93, 96, 98, 99, 93, 103, 100, 104, 101, 101,
- 102, 93, 93, 93, 93, 93, 103, 104, 93, 93,
- 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
- 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
- 93, 93, 93, 93, 93, 105, 93, 105, 93, 105,
- 93, 93, 0, 93, 93, 93, 93, 93, 93, 93,
+ 160, 1, 1, 1, 1, 5, 160, 7, 1, 1,
+ 160, 160, 160, 160, 160, 161, 162, 163, 160, 160,
+ 160, 160, 164, 160, 160, 160, 165, 164, 160, 166,
+ 167, 166, 166, 160, 160, 160, 160, 161, 160, 161,
+ 160, 168, 160, 163, 160, 163, 169, 170, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 164, 160, 160,
+ 160, 160, 160, 160, 164, 166, 167, 166, 160, 160,
+ 160, 171, 168, 172, 163, 169, 169, 170, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 166, 160, 160,
+ 171, 172, 160, 160, 160, 160, 160, 160, 160, 160,
- 93, 93, 93, 93, 93
+ 160, 160, 166, 160, 160, 160, 160, 160, 160, 160,
+ 160, 173, 160, 166, 160, 160, 160, 160, 160, 160,
+ 173, 160, 173, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 174, 160, 160, 160, 174, 160, 174, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160, 160, 0,
+ 160, 160, 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160
} ;
-static yyconst flex_int16_t yy_nxt[281] =
+static yyconst flex_int16_t yy_nxt[441] =
{ 0,
- 12, 13, 14, 15, 12, 16, 12, 12, 17, 12,
- 12, 12, 12, 18, 18, 18, 12, 12, 18, 18,
- 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
- 18, 12, 12, 19, 20, 20, 20, 92, 21, 25,
- 26, 26, 22, 21, 21, 21, 21, 12, 13, 14,
- 15, 23, 16, 23, 23, 19, 23, 23, 23, 12,
- 24, 24, 24, 12, 12, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, 24, 24, 12, 12,
- 25, 26, 26, 27, 27, 27, 27, 29, 43, 29,
- 43, 43, 45, 45, 45, 50, 39, 59, 46, 93,
+ 12, 13, 14, 15, 16, 12, 17, 18, 12, 12,
+ 12, 19, 12, 12, 12, 12, 20, 21, 22, 23,
+ 23, 23, 23, 23, 12, 12, 23, 23, 23, 23,
+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 12, 24, 12, 25, 34, 35, 35, 25,
+ 81, 26, 26, 27, 27, 27, 34, 35, 35, 82,
+ 28, 36, 36, 36, 36, 159, 29, 28, 28, 28,
+ 28, 12, 13, 14, 15, 16, 30, 17, 18, 30,
+ 30, 30, 26, 30, 30, 30, 12, 20, 21, 22,
+ 31, 31, 31, 31, 31, 32, 12, 31, 31, 31,
- 30, 33, 30, 34, 45, 45, 45, 27, 27, 68,
- 43, 91, 43, 43, 69, 35, 87, 36, 39, 37,
- 42, 42, 42, 39, 42, 45, 45, 45, 89, 42,
- 42, 42, 42, 85, 85, 86, 85, 85, 86, 89,
- 84, 90, 83, 82, 81, 80, 79, 78, 77, 76,
- 75, 74, 90, 28, 28, 28, 28, 28, 28, 28,
- 28, 31, 31, 31, 38, 38, 38, 38, 41, 73,
- 41, 43, 72, 43, 71, 43, 43, 44, 33, 44,
- 44, 44, 44, 47, 69, 47, 47, 49, 49, 49,
- 49, 49, 49, 49, 49, 51, 51, 51, 51, 51,
+ 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+ 31, 31, 31, 12, 24, 12, 39, 41, 45, 47,
+ 53, 54, 48, 56, 57, 61, 61, 47, 66, 45,
+ 48, 66, 66, 66, 39, 46, 40, 49, 59, 50,
+ 158, 51, 122, 52, 157, 49, 46, 50, 136, 63,
+ 137, 52, 156, 43, 40, 62, 65, 65, 65, 59,
+ 61, 61, 123, 65, 75, 69, 69, 69, 36, 36,
+ 65, 65, 65, 65, 70, 71, 72, 69, 69, 69,
+ 45, 46, 61, 61, 109, 77, 70, 71, 93, 110,
+ 68, 70, 71, 85, 85, 85, 66, 46, 155, 66,
- 51, 51, 51, 57, 70, 57, 58, 58, 58, 67,
- 58, 58, 88, 88, 88, 88, 88, 88, 88, 88,
- 34, 66, 65, 64, 63, 62, 61, 60, 52, 50,
- 39, 56, 39, 55, 54, 53, 52, 50, 48, 93,
- 40, 39, 32, 93, 19, 19, 11, 93, 93, 93,
- 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
- 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
- 93, 93, 93, 93, 93, 93, 93, 93, 93, 93
+ 66, 66, 69, 69, 69, 122, 59, 100, 100, 61,
+ 61, 70, 71, 100, 100, 148, 112, 154, 85, 85,
+ 85, 61, 61, 129, 129, 123, 129, 129, 135, 135,
+ 135, 142, 142, 148, 143, 149, 153, 135, 135, 135,
+ 142, 142, 160, 143, 152, 151, 150, 146, 145, 144,
+ 141, 140, 139, 149, 38, 38, 38, 38, 38, 38,
+ 38, 38, 42, 138, 134, 133, 42, 42, 44, 44,
+ 44, 44, 44, 44, 44, 44, 58, 58, 58, 58,
+ 64, 132, 64, 66, 131, 130, 66, 160, 66, 66,
+ 67, 128, 127, 67, 67, 67, 67, 73, 126, 73,
+
+ 73, 76, 76, 76, 76, 76, 76, 76, 76, 78,
+ 78, 78, 78, 78, 78, 78, 78, 91, 125, 91,
+ 92, 124, 92, 92, 120, 92, 92, 121, 121, 121,
+ 121, 121, 121, 121, 121, 147, 147, 147, 147, 147,
+ 147, 147, 147, 119, 118, 117, 116, 115, 47, 114,
+ 110, 113, 111, 108, 107, 106, 48, 105, 104, 89,
+ 103, 102, 101, 99, 98, 97, 96, 95, 94, 79,
+ 77, 90, 89, 88, 59, 87, 86, 59, 84, 83,
+ 80, 79, 77, 74, 160, 60, 59, 55, 37, 160,
+ 33, 25, 26, 25, 11, 160, 160, 160, 160, 160,
+
+ 160, 160, 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160, 160, 160
} ;
-static yyconst flex_int16_t yy_chk[281] =
+static yyconst flex_int16_t yy_chk[441] =
{ 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, 5, 5, 5, 5, 91, 5, 9,
- 9, 9, 5, 5, 5, 5, 5, 7, 7, 7,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 4, 9, 9, 9, 10,
+ 50, 4, 5, 5, 5, 5, 10, 10, 10, 50,
+ 5, 13, 13, 14, 14, 158, 5, 5, 5, 5,
+ 5, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 10, 10, 10, 13, 13, 14, 14, 15, 24, 28,
- 24, 24, 25, 25, 25, 50, 24, 50, 25, 90,
- 15, 17, 28, 17, 26, 26, 26, 27, 27, 62,
- 44, 87, 44, 44, 62, 17, 84, 17, 44, 17,
- 21, 21, 21, 21, 21, 45, 45, 45, 86, 21,
- 21, 21, 21, 83, 83, 83, 85, 85, 85, 88,
- 82, 86, 81, 78, 77, 76, 75, 74, 73, 72,
- 71, 70, 88, 94, 94, 94, 94, 94, 94, 94,
- 94, 95, 95, 95, 96, 96, 96, 96, 97, 69,
- 97, 98, 68, 98, 67, 98, 98, 99, 66, 99,
- 99, 99, 99, 100, 64, 100, 100, 101, 101, 101,
- 101, 101, 101, 101, 101, 102, 102, 102, 102, 102,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 16, 17, 18, 19,
+ 20, 20, 19, 22, 22, 25, 25, 26, 31, 44,
+ 26, 31, 31, 31, 38, 18, 16, 19, 31, 19,
+ 157, 19, 112, 19, 156, 26, 44, 26, 130, 26,
+ 130, 26, 155, 17, 38, 25, 28, 28, 28, 28,
+ 33, 33, 112, 28, 46, 34, 34, 34, 36, 36,
+ 28, 28, 28, 28, 34, 34, 34, 35, 35, 35,
+ 75, 46, 61, 61, 98, 77, 35, 35, 77, 98,
+ 33, 91, 91, 61, 61, 61, 67, 75, 152, 67,
- 102, 102, 102, 103, 63, 103, 104, 104, 104, 61,
- 104, 104, 105, 105, 105, 105, 105, 105, 105, 105,
- 60, 59, 58, 56, 55, 54, 53, 52, 51, 49,
- 42, 40, 38, 37, 36, 35, 34, 33, 32, 30,
- 19, 18, 16, 11, 4, 3, 93, 93, 93, 93,
- 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
- 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
- 93, 93, 93, 93, 93, 93, 93, 93, 93, 93
+ 67, 67, 69, 69, 69, 121, 67, 85, 85, 113,
+ 113, 69, 69, 100, 100, 143, 100, 151, 85, 85,
+ 85, 114, 114, 122, 122, 121, 129, 129, 135, 135,
+ 135, 138, 138, 147, 138, 143, 150, 129, 129, 129,
+ 142, 142, 149, 142, 146, 145, 144, 141, 140, 139,
+ 137, 136, 134, 147, 161, 161, 161, 161, 161, 161,
+ 161, 161, 162, 133, 128, 127, 162, 162, 163, 163,
+ 163, 163, 163, 163, 163, 163, 164, 164, 164, 164,
+ 165, 126, 165, 166, 125, 124, 166, 123, 166, 166,
+ 167, 120, 119, 167, 167, 167, 167, 168, 118, 168,
+
+ 168, 169, 169, 169, 169, 169, 169, 169, 169, 170,
+ 170, 170, 170, 170, 170, 170, 170, 171, 117, 171,
+ 172, 116, 172, 172, 111, 172, 172, 173, 173, 173,
+ 173, 173, 173, 173, 173, 174, 174, 174, 174, 174,
+ 174, 174, 174, 110, 109, 108, 107, 106, 105, 103,
+ 102, 101, 99, 97, 96, 95, 94, 93, 92, 90,
+ 88, 87, 86, 84, 83, 82, 81, 80, 79, 78,
+ 76, 71, 70, 68, 65, 63, 62, 58, 52, 51,
+ 49, 48, 47, 43, 40, 24, 23, 21, 15, 11,
+ 8, 6, 3, 2, 160, 160, 160, 160, 160, 160,
+
+ 160, 160, 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160, 160, 160
} ;
static yy_state_type yy_last_accepting_state;
@@ -540,6 +607,7 @@
#define YY_MORE_ADJ 0
#define YY_RESTORE_YY_MORE_OFFSET
char *yytext;
+#line 1 "dtc-lexer.l"
/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
*
@@ -561,6 +629,10 @@
*/
#define YY_NO_INPUT 1
+
+
+
+#line 38 "dtc-lexer.l"
#include "dtc.h"
#include "srcpos.h"
#include "dtc-parser.tab.h"
@@ -588,6 +660,7 @@
static void push_input_file(const char *filename);
static int pop_input_file(void);
+#line 664 "dtc-lexer.lex.c"
#define INITIAL 0
#define INCLUDE 1
@@ -670,7 +743,12 @@
/* Amount of stuff to slurp up with each read. */
#ifndef YY_READ_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k */
+#define YY_READ_BUF_SIZE 16384
+#else
#define YY_READ_BUF_SIZE 8192
+#endif /* __ia64__ */
#endif
/* Copy whatever the last rule matched to the standard output. */
@@ -689,7 +767,7 @@
if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
{ \
int c = '*'; \
- unsigned n; \
+ size_t n; \
for ( n = 0; n < max_size && \
(c = getc( yyin )) != EOF && c != '\n'; ++n ) \
buf[n] = (char) c; \
@@ -761,6 +839,9 @@
#endif
#define YY_RULE_SETUP \
+ if ( yyleng > 0 ) \
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \
+ (yytext[yyleng - 1] == '\n'); \
YY_USER_ACTION
/** The main scanner function which does all the work.
@@ -771,6 +852,10 @@
register char *yy_cp, *yy_bp;
register int yy_act;
+#line 67 "dtc-lexer.l"
+
+#line 858 "dtc-lexer.lex.c"
+
if ( !(yy_init) )
{
(yy_init) = 1;
@@ -810,6 +895,7 @@
yy_bp = yy_cp;
yy_current_state = (yy_start);
+ yy_current_state += YY_AT_BOL();
yy_match:
do
{
@@ -822,13 +908,13 @@
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 >= 94 )
+ if ( yy_current_state >= 161 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
++yy_cp;
}
- while ( yy_current_state != 93 );
+ while ( yy_current_state != 160 );
yy_cp = (yy_last_accepting_cpos);
yy_current_state = (yy_last_accepting_state);
@@ -851,26 +937,54 @@
case 1:
/* rule 1 can match eol */
YY_RULE_SETUP
+#line 68 "dtc-lexer.l"
{
char *name = strchr(yytext, '\"') + 1;
yytext[yyleng-1] = '\0';
push_input_file(name);
}
YY_BREAK
+case 2:
+/* rule 2 can match eol */
+YY_RULE_SETUP
+#line 74 "dtc-lexer.l"
+{
+ char *line, *tmp, *fn;
+ /* skip text before line # */
+ line = yytext;
+ while (!isdigit(*line))
+ line++;
+ /* skip digits in line # */
+ tmp = line;
+ while (!isspace(*tmp))
+ tmp++;
+ /* "NULL"-terminate line # */
+ *tmp = '\0';
+ /* start of filename */
+ fn = strchr(tmp + 1, '"') + 1;
+ /* strip trailing " from filename */
+ tmp = strchr(fn, '"');
+ *tmp = 0;
+ /* -1 since #line is the number of the next line */
+ srcpos_set_line(xstrdup(fn), atoi(line) - 1);
+ }
+ YY_BREAK
case YY_STATE_EOF(INITIAL):
case YY_STATE_EOF(INCLUDE):
case YY_STATE_EOF(BYTESTRING):
case YY_STATE_EOF(PROPNODENAME):
case YY_STATE_EOF(V1):
+#line 95 "dtc-lexer.l"
{
if (!pop_input_file()) {
yyterminate();
}
}
YY_BREAK
-case 2:
-/* rule 2 can match eol */
+case 3:
+/* rule 3 can match eol */
YY_RULE_SETUP
+#line 101 "dtc-lexer.l"
{
DPRINT("String: %s\n", yytext);
yylval.data = data_copy_escape_string(yytext+1,
@@ -878,8 +992,9 @@
return DT_STRING;
}
YY_BREAK
-case 3:
+case 4:
YY_RULE_SETUP
+#line 108 "dtc-lexer.l"
{
DPRINT("Keyword: /dts-v1/\n");
dts_version = 1;
@@ -887,16 +1002,47 @@
return DT_V1;
}
YY_BREAK
-case 4:
+case 5:
YY_RULE_SETUP
+#line 115 "dtc-lexer.l"
{
DPRINT("Keyword: /memreserve/\n");
BEGIN_DEFAULT();
return DT_MEMRESERVE;
}
YY_BREAK
-case 5:
+case 6:
YY_RULE_SETUP
+#line 121 "dtc-lexer.l"
+{
+ DPRINT("Keyword: /bits/\n");
+ BEGIN_DEFAULT();
+ return DT_BITS;
+ }
+ YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 127 "dtc-lexer.l"
+{
+ DPRINT("Keyword: /delete-property/\n");
+ DPRINT("<PROPNODENAME>\n");
+ BEGIN(PROPNODENAME);
+ return DT_DEL_PROP;
+ }
+ YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 134 "dtc-lexer.l"
+{
+ DPRINT("Keyword: /delete-node/\n");
+ DPRINT("<PROPNODENAME>\n");
+ BEGIN(PROPNODENAME);
+ return DT_DEL_NODE;
+ }
+ YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 141 "dtc-lexer.l"
{
DPRINT("Label: %s\n", yytext);
yylval.labelref = xstrdup(yytext);
@@ -904,24 +1050,38 @@
return DT_LABEL;
}
YY_BREAK
-case 6:
+case 10:
YY_RULE_SETUP
+#line 148 "dtc-lexer.l"
{
yylval.literal = xstrdup(yytext);
DPRINT("Literal: '%s'\n", yylval.literal);
return DT_LITERAL;
}
YY_BREAK
-case 7:
+case 11:
+/* rule 11 can match eol */
YY_RULE_SETUP
+#line 154 "dtc-lexer.l"
+{
+ yytext[yyleng-1] = '\0';
+ yylval.literal = xstrdup(yytext+1);
+ DPRINT("Character literal: %s\n", yylval.literal);
+ return DT_CHAR_LITERAL;
+ }
+ YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 161 "dtc-lexer.l"
{ /* label reference */
DPRINT("Ref: %s\n", yytext+1);
yylval.labelref = xstrdup(yytext+1);
return DT_REF;
}
YY_BREAK
-case 8:
+case 13:
YY_RULE_SETUP
+#line 167 "dtc-lexer.l"
{ /* new-style path reference */
yytext[yyleng-1] = '\0';
DPRINT("Ref: %s\n", yytext+2);
@@ -929,55 +1089,104 @@
return DT_REF;
}
YY_BREAK
-case 9:
+case 14:
YY_RULE_SETUP
+#line 174 "dtc-lexer.l"
{
yylval.byte = strtol(yytext, NULL, 16);
DPRINT("Byte: %02x\n", (int)yylval.byte);
return DT_BYTE;
}
YY_BREAK
-case 10:
+case 15:
YY_RULE_SETUP
+#line 180 "dtc-lexer.l"
{
DPRINT("/BYTESTRING\n");
BEGIN_DEFAULT();
return ']';
}
YY_BREAK
-case 11:
+case 16:
YY_RULE_SETUP
+#line 186 "dtc-lexer.l"
{
DPRINT("PropNodeName: %s\n", yytext);
- yylval.propnodename = xstrdup(yytext);
+ yylval.propnodename = xstrdup((yytext[0] == '\\') ?
+ yytext + 1 : yytext);
BEGIN_DEFAULT();
return DT_PROPNODENAME;
}
YY_BREAK
-case 12:
+case 17:
YY_RULE_SETUP
+#line 194 "dtc-lexer.l"
{
DPRINT("Binary Include\n");
return DT_INCBIN;
}
YY_BREAK
-case 13:
-/* rule 13 can match eol */
+case 18:
+/* rule 18 can match eol */
YY_RULE_SETUP
+#line 199 "dtc-lexer.l"
/* eat whitespace */
YY_BREAK
-case 14:
-/* rule 14 can match eol */
+case 19:
+/* rule 19 can match eol */
YY_RULE_SETUP
+#line 200 "dtc-lexer.l"
/* eat C-style comments */
YY_BREAK
-case 15:
-/* rule 15 can match eol */
+case 20:
+/* rule 20 can match eol */
YY_RULE_SETUP
+#line 201 "dtc-lexer.l"
/* eat C++-style comments */
YY_BREAK
-case 16:
+case 21:
YY_RULE_SETUP
+#line 203 "dtc-lexer.l"
+{ return DT_LSHIFT; };
+ YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 204 "dtc-lexer.l"
+{ return DT_RSHIFT; };
+ YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 205 "dtc-lexer.l"
+{ return DT_LE; };
+ YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 206 "dtc-lexer.l"
+{ return DT_GE; };
+ YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 207 "dtc-lexer.l"
+{ return DT_EQ; };
+ YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 208 "dtc-lexer.l"
+{ return DT_NE; };
+ YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 209 "dtc-lexer.l"
+{ return DT_AND; };
+ YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 210 "dtc-lexer.l"
+{ return DT_OR; };
+ YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 212 "dtc-lexer.l"
{
DPRINT("Char: %c (\\x%02x)\n", yytext[0],
(unsigned)yytext[0]);
@@ -993,10 +1202,12 @@
return yytext[0];
}
YY_BREAK
-case 17:
+case 30:
YY_RULE_SETUP
+#line 227 "dtc-lexer.l"
ECHO;
YY_BREAK
+#line 1211 "dtc-lexer.lex.c"
case YY_END_OF_BUFFER:
{
@@ -1275,6 +1486,7 @@
register 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 )
{
@@ -1287,7 +1499,7 @@
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 >= 94 )
+ if ( yy_current_state >= 161 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
@@ -1315,11 +1527,11 @@
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 >= 94 )
+ if ( yy_current_state >= 161 )
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 == 93);
+ yy_is_jam = (yy_current_state == 160);
return yy_is_jam ? 0 : yy_current_state;
}
@@ -1394,6 +1606,8 @@
*(yy_c_buf_p) = '\0'; /* preserve yytext */
(yy_hold_char) = *++(yy_c_buf_p);
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n');
+
return c;
}
#endif /* ifndef YY_NO_INPUT */
@@ -1712,8 +1926,8 @@
/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
* scan from a @e copy of @a bytes.
- * @param bytes the byte buffer to scan
- * @param len the number of bytes in the buffer pointed to by @a bytes.
+ * @param yybytes the byte buffer to scan
+ * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
*
* @return the newly allocated buffer state object.
*/
@@ -1952,6 +2166,10 @@
#define YYTABLES_NAME "yytables"
+#line 227 "dtc-lexer.l"
+
+
+
static void push_input_file(const char *filename)
{
assert(filename);
@@ -1963,6 +2181,7 @@
yypush_buffer_state(yy_create_buffer(yyin,YY_BUF_SIZE));
}
+
static int pop_input_file(void)
{
if (srcfile_pop() == 0)
diff --git a/scripts/dtc/dtc-parser.tab.c_shipped b/scripts/dtc/dtc-parser.tab.c_shipped
index b05921e..4af5590 100644
--- a/scripts/dtc/dtc-parser.tab.c_shipped
+++ b/scripts/dtc/dtc-parser.tab.c_shipped
@@ -1,9 +1,10 @@
-/* A Bison parser, made by GNU Bison 2.4.3. */
+
+/* A Bison parser, made by GNU Bison 2.4.1. */
/* Skeleton implementation for Bison's Yacc-like parsers in C
- Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
- 2009, 2010 Free Software Foundation, Inc.
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ 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
@@ -45,7 +46,7 @@
#define YYBISON 1
/* Bison version. */
-#define YYBISON_VERSION "2.4.3"
+#define YYBISON_VERSION "2.4.1"
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
@@ -66,6 +67,8 @@
/* Copy the first part of user declarations. */
+/* Line 189 of yacc.c */
+#line 21 "dtc-parser.y"
#include <stdio.h>
@@ -82,12 +85,15 @@
extern int treesource_error;
static unsigned long long eval_literal(const char *s, int base, int bits);
+static unsigned char eval_char_literal(const char *s);
+/* Line 189 of yacc.c */
+#line 93 "dtc-parser.tab.c"
/* Enabling traces. */
#ifndef YYDEBUG
-# define YYDEBUG 1
+# define YYDEBUG 0
#endif
/* Enabling verbose error messages. */
@@ -112,14 +118,26 @@
enum yytokentype {
DT_V1 = 258,
DT_MEMRESERVE = 259,
- DT_PROPNODENAME = 260,
- DT_LITERAL = 261,
- DT_BASE = 262,
- DT_BYTE = 263,
- DT_STRING = 264,
- DT_LABEL = 265,
- DT_REF = 266,
- DT_INCBIN = 267
+ 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_BASE = 274,
+ DT_BYTE = 275,
+ DT_STRING = 276,
+ DT_LABEL = 277,
+ DT_REF = 278,
+ DT_INCBIN = 279
};
#endif
@@ -129,6 +147,8 @@
typedef union YYSTYPE
{
+/* Line 214 of yacc.c */
+#line 40 "dtc-parser.y"
char *propnodename;
char *literal;
@@ -137,16 +157,22 @@
uint8_t byte;
struct data data;
- uint64_t addr;
- cell_t cell;
+ struct {
+ struct data data;
+ int bits;
+ } array;
+
struct property *prop;
struct property *proplist;
struct node *node;
struct node *nodelist;
struct reserve_info *re;
+ uint64_t integer;
+/* Line 214 of yacc.c */
+#line 176 "dtc-parser.tab.c"
} YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
@@ -157,6 +183,8 @@
/* Copy the second part of user declarations. */
+/* Line 264 of yacc.c */
+#line 188 "dtc-parser.tab.c"
#ifdef short
# undef short
@@ -206,7 +234,7 @@
#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
#ifndef YY_
-# if defined YYENABLE_NLS && YYENABLE_NLS
+# if YYENABLE_NLS
# if ENABLE_NLS
# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
# define YY_(msgid) dgettext ("bison-runtime", msgid)
@@ -371,20 +399,20 @@
/* YYFINAL -- State number of the termination state. */
#define YYFINAL 4
/* YYLAST -- Last index in YYTABLE. */
-#define YYLAST 56
+#define YYLAST 133
/* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS 25
+#define YYNTOKENS 48
/* YYNNTS -- Number of nonterminals. */
-#define YYNNTS 16
+#define YYNNTS 28
/* YYNRULES -- Number of rules. */
-#define YYNRULES 39
+#define YYNRULES 79
/* YYNRULES -- Number of states. */
-#define YYNSTATES 67
+#define YYNSTATES 141
/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
#define YYUNDEFTOK 2
-#define YYMAXUTOK 267
+#define YYMAXUTOK 279
#define YYTRANSLATE(YYX) \
((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -395,16 +423,16 @@
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, 2, 2, 2, 2, 2, 2, 2,
- 22, 24, 2, 2, 23, 2, 2, 14, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 13,
- 18, 17, 19, 2, 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, 20, 2, 21, 2, 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, 15, 2, 16, 2, 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,
@@ -418,45 +446,68 @@
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, 1, 2, 3, 4,
- 5, 6, 7, 8, 9, 10, 11, 12
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
};
#if YYDEBUG
/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
YYRHS. */
-static const yytype_uint8 yyprhs[] =
+static const yytype_uint16 yyprhs[] =
{
- 0, 0, 3, 8, 9, 12, 17, 20, 22, 25,
- 29, 33, 39, 40, 43, 48, 51, 54, 57, 62,
- 67, 70, 80, 86, 89, 90, 93, 96, 97, 100,
- 103, 106, 108, 109, 112, 115, 116, 119, 122, 125
+ 0, 0, 3, 8, 9, 12, 17, 20, 23, 27,
+ 31, 36, 42, 43, 46, 51, 54, 58, 61, 64,
+ 68, 73, 76, 86, 92, 95, 96, 99, 102, 106,
+ 108, 111, 114, 117, 119, 121, 125, 127, 129, 135,
+ 137, 141, 143, 147, 149, 153, 155, 159, 161, 165,
+ 167, 171, 175, 177, 181, 185, 189, 193, 197, 201,
+ 203, 207, 211, 213, 217, 221, 225, 227, 229, 232,
+ 235, 238, 239, 242, 245, 246, 249, 252, 255, 259
};
/* YYRHS -- A `-1'-separated list of the rules' RHS. */
static const yytype_int8 yyrhs[] =
{
- 26, 0, -1, 3, 13, 27, 30, -1, -1, 28,
- 27, -1, 4, 29, 29, 13, -1, 10, 28, -1,
- 6, -1, 14, 31, -1, 30, 14, 31, -1, 30,
- 11, 31, -1, 15, 32, 39, 16, 13, -1, -1,
- 32, 33, -1, 5, 17, 34, 13, -1, 5, 13,
- -1, 10, 33, -1, 35, 9, -1, 35, 18, 36,
- 19, -1, 35, 20, 38, 21, -1, 35, 11, -1,
- 35, 12, 22, 9, 23, 29, 23, 29, 24, -1,
- 35, 12, 22, 9, 24, -1, 34, 10, -1, -1,
- 34, 23, -1, 35, 10, -1, -1, 36, 37, -1,
- 36, 11, -1, 36, 10, -1, 6, -1, -1, 38,
- 8, -1, 38, 10, -1, -1, 40, 39, -1, 40,
- 33, -1, 5, 31, -1, 10, 40, -1
+ 49, 0, -1, 3, 25, 50, 52, -1, -1, 51,
+ 50, -1, 4, 59, 59, 25, -1, 22, 51, -1,
+ 26, 53, -1, 52, 26, 53, -1, 52, 23, 53,
+ -1, 52, 15, 23, 25, -1, 27, 54, 74, 28,
+ 25, -1, -1, 54, 55, -1, 16, 29, 56, 25,
+ -1, 16, 25, -1, 14, 16, 25, -1, 22, 55,
+ -1, 57, 21, -1, 57, 58, 30, -1, 57, 31,
+ 73, 32, -1, 57, 23, -1, 57, 24, 33, 21,
+ 34, 59, 34, 59, 35, -1, 57, 24, 33, 21,
+ 35, -1, 56, 22, -1, -1, 56, 34, -1, 57,
+ 22, -1, 13, 17, 36, -1, 36, -1, 58, 59,
+ -1, 58, 23, -1, 58, 22, -1, 17, -1, 18,
+ -1, 33, 60, 35, -1, 61, -1, 62, -1, 62,
+ 37, 60, 38, 61, -1, 63, -1, 62, 12, 63,
+ -1, 64, -1, 63, 11, 64, -1, 65, -1, 64,
+ 39, 65, -1, 66, -1, 65, 40, 66, -1, 67,
+ -1, 66, 41, 67, -1, 68, -1, 67, 9, 68,
+ -1, 67, 10, 68, -1, 69, -1, 68, 36, 69,
+ -1, 68, 30, 69, -1, 68, 7, 69, -1, 68,
+ 8, 69, -1, 69, 5, 70, -1, 69, 6, 70,
+ -1, 70, -1, 70, 42, 71, -1, 70, 43, 71,
+ -1, 71, -1, 71, 44, 72, -1, 71, 26, 72,
+ -1, 71, 45, 72, -1, 72, -1, 59, -1, 43,
+ 72, -1, 46, 72, -1, 47, 72, -1, -1, 73,
+ 20, -1, 73, 22, -1, -1, 75, 74, -1, 75,
+ 55, -1, 16, 53, -1, 15, 16, 25, -1, 22,
+ 75, -1
};
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
static const yytype_uint16 yyrline[] =
{
- 0, 86, 86, 95, 98, 105, 109, 117, 124, 128,
- 132, 145, 153, 156, 163, 167, 171, 179, 183, 187,
- 191, 195, 212, 222, 230, 233, 237, 245, 248, 252,
- 257, 264, 272, 275, 279, 287, 290, 294, 302, 306
+ 0, 109, 109, 118, 121, 128, 132, 140, 144, 148,
+ 158, 172, 180, 183, 190, 194, 198, 202, 210, 214,
+ 218, 222, 226, 243, 253, 261, 264, 268, 275, 290,
+ 295, 315, 329, 336, 340, 344, 351, 355, 356, 360,
+ 361, 365, 366, 370, 371, 375, 376, 380, 381, 385,
+ 386, 387, 391, 392, 393, 394, 395, 399, 400, 401,
+ 405, 406, 407, 411, 412, 413, 414, 418, 419, 420,
+ 421, 426, 429, 433, 441, 444, 448, 456, 460, 464
};
#endif
@@ -465,13 +516,19 @@
First, the terminals, then, starting at YYNTOKENS, nonterminals. */
static const char *const yytname[] =
{
- "$end", "error", "$undefined", "DT_V1", "DT_MEMRESERVE",
- "DT_PROPNODENAME", "DT_LITERAL", "DT_BASE", "DT_BYTE", "DT_STRING",
- "DT_LABEL", "DT_REF", "DT_INCBIN", "';'", "'/'", "'{'", "'}'", "'='",
- "'<'", "'>'", "'['", "']'", "'('", "','", "')'", "$accept", "sourcefile",
- "memreserves", "memreserve", "addr", "devicetree", "nodedef", "proplist",
- "propdef", "propdata", "propdataprefix", "celllist", "cellval",
- "bytestring", "subnodes", "subnode", 0
+ "$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_BASE", "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", 0
};
#endif
@@ -481,27 +538,37 @@
static const yytype_uint16 yytoknum[] =
{
0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
- 265, 266, 267, 59, 47, 123, 125, 61, 60, 62,
- 91, 93, 40, 44, 41
+ 265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
+ 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
/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
static const yytype_uint8 yyr1[] =
{
- 0, 25, 26, 27, 27, 28, 28, 29, 30, 30,
- 30, 31, 32, 32, 33, 33, 33, 34, 34, 34,
- 34, 34, 34, 34, 35, 35, 35, 36, 36, 36,
- 36, 37, 38, 38, 38, 39, 39, 39, 40, 40
+ 0, 48, 49, 50, 50, 51, 51, 52, 52, 52,
+ 52, 53, 54, 54, 55, 55, 55, 55, 56, 56,
+ 56, 56, 56, 56, 56, 57, 57, 57, 58, 58,
+ 58, 58, 58, 59, 59, 59, 60, 61, 61, 62,
+ 62, 63, 63, 64, 64, 65, 65, 66, 66, 67,
+ 67, 67, 68, 68, 68, 68, 68, 69, 69, 69,
+ 70, 70, 70, 71, 71, 71, 71, 72, 72, 72,
+ 72, 73, 73, 73, 74, 74, 74, 75, 75, 75
};
/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
static const yytype_uint8 yyr2[] =
{
- 0, 2, 4, 0, 2, 4, 2, 1, 2, 3,
- 3, 5, 0, 2, 4, 2, 2, 2, 4, 4,
- 2, 9, 5, 2, 0, 2, 2, 0, 2, 2,
- 2, 1, 0, 2, 2, 0, 2, 2, 2, 2
+ 0, 2, 4, 0, 2, 4, 2, 2, 3, 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
};
/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
@@ -509,41 +576,59 @@
means the default is an error. */
static const yytype_uint8 yydefact[] =
{
- 0, 0, 0, 3, 1, 0, 0, 0, 3, 7,
- 0, 6, 0, 2, 4, 0, 12, 8, 0, 0,
- 5, 35, 10, 9, 0, 0, 13, 0, 35, 15,
- 24, 38, 16, 39, 0, 37, 36, 0, 0, 11,
- 23, 14, 25, 17, 26, 20, 0, 27, 32, 0,
- 0, 0, 0, 31, 30, 29, 18, 28, 33, 34,
- 19, 0, 22, 0, 0, 0, 21
+ 0, 0, 0, 3, 1, 0, 0, 0, 3, 33,
+ 34, 0, 0, 6, 0, 2, 4, 0, 0, 0,
+ 67, 0, 36, 37, 39, 41, 43, 45, 47, 49,
+ 52, 59, 62, 66, 0, 12, 7, 0, 0, 0,
+ 68, 69, 70, 35, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 5, 74, 0, 9, 8, 40, 0,
+ 42, 44, 46, 48, 50, 51, 55, 56, 54, 53,
+ 57, 58, 60, 61, 64, 63, 65, 0, 0, 0,
+ 0, 13, 0, 74, 10, 0, 0, 0, 15, 25,
+ 77, 17, 79, 0, 76, 75, 38, 16, 78, 0,
+ 0, 11, 24, 14, 26, 0, 18, 27, 21, 0,
+ 71, 29, 0, 0, 0, 0, 32, 31, 19, 30,
+ 28, 0, 72, 73, 20, 0, 23, 0, 0, 0,
+ 22
};
/* YYDEFGOTO[NTERM-NUM]. */
static const yytype_int8 yydefgoto[] =
{
- -1, 2, 7, 8, 10, 13, 17, 21, 26, 37,
- 38, 50, 57, 51, 27, 28
+ -1, 2, 7, 8, 15, 36, 64, 91, 109, 110,
+ 122, 20, 21, 22, 23, 24, 25, 26, 27, 28,
+ 29, 30, 31, 32, 33, 125, 92, 93
};
/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
STATE-NUM. */
-#define YYPACT_NINF -12
+#define YYPACT_NINF -78
static const yytype_int8 yypact[] =
{
- 10, -11, 18, -1, -12, 22, -1, 15, -1, -12,
- 22, -12, 20, 1, -12, 17, -12, -12, 20, 20,
- -12, 6, -12, -12, 21, 6, -12, 23, 6, -12,
- -12, -12, -12, -12, 28, -12, -12, -6, 13, -12,
- -12, -12, -12, -12, -12, -12, 24, -12, -12, 33,
- -5, 0, -4, -12, -12, -12, -12, -12, -12, -12,
- -12, 22, -12, 25, 22, 19, -12
+ 22, 11, 51, 10, -78, 23, 10, 2, 10, -78,
+ -78, -9, 23, -78, 30, 38, -78, -9, -9, -9,
+ -78, 35, -78, -6, 52, 29, 48, 49, 33, 3,
+ 71, 36, 0, -78, 64, -78, -78, 68, 30, 30,
+ -78, -78, -78, -78, -9, -9, -9, -9, -9, -9,
+ -9, -9, -9, -9, -9, -9, -9, -9, -9, -9,
+ -9, -9, -9, -78, 44, 67, -78, -78, 52, 55,
+ 29, 48, 49, 33, 3, 3, 71, 71, 71, 71,
+ 36, 36, 0, 0, -78, -78, -78, 78, 79, 42,
+ 44, -78, 69, 44, -78, -9, 73, 74, -78, -78,
+ -78, -78, -78, 75, -78, -78, -78, -78, -78, -7,
+ -1, -78, -78, -78, -78, 84, -78, -78, -78, 63,
+ -78, -78, 32, 66, 82, -3, -78, -78, -78, -78,
+ -78, 46, -78, -78, -78, 23, -78, 70, 23, 72,
+ -78
};
/* YYPGOTO[NTERM-NUM]. */
static const yytype_int8 yypgoto[] =
{
- -12, -12, 36, 39, -10, -12, 8, -12, 12, -12,
- -12, -12, -12, -12, 27, 31
+ -78, -78, 97, 100, -78, -37, -78, -77, -78, -78,
+ -78, -5, 65, 13, -78, 76, 77, 62, 80, 83,
+ 34, 20, 26, 28, -14, -78, 18, 24
};
/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
@@ -553,35 +638,59 @@
#define YYTABLE_NINF -1
static const yytype_uint8 yytable[] =
{
- 15, 53, 3, 5, 40, 54, 55, 41, 58, 6,
- 59, 24, 18, 1, 56, 19, 25, 42, 4, 61,
- 62, 60, 43, 44, 45, 46, 22, 23, 9, 12,
- 20, 47, 31, 48, 29, 16, 16, 32, 30, 34,
- 35, 39, 52, 66, 14, 11, 49, 0, 64, 0,
- 0, 63, 0, 0, 65, 36, 33
+ 12, 66, 67, 40, 41, 42, 44, 34, 9, 10,
+ 52, 53, 115, 101, 5, 112, 104, 132, 113, 133,
+ 116, 117, 118, 119, 11, 1, 60, 114, 14, 134,
+ 120, 45, 6, 54, 17, 121, 3, 18, 19, 55,
+ 9, 10, 50, 51, 61, 62, 84, 85, 86, 9,
+ 10, 4, 100, 37, 126, 127, 11, 35, 87, 88,
+ 89, 38, 128, 46, 39, 11, 90, 98, 47, 35,
+ 43, 99, 76, 77, 78, 79, 56, 57, 58, 59,
+ 135, 136, 80, 81, 74, 75, 82, 83, 48, 63,
+ 49, 65, 94, 95, 96, 97, 124, 103, 107, 108,
+ 111, 123, 130, 131, 138, 16, 13, 140, 106, 71,
+ 69, 105, 0, 0, 102, 0, 0, 129, 0, 0,
+ 68, 0, 0, 70, 0, 0, 0, 0, 72, 0,
+ 137, 0, 73, 139
};
-static const yytype_int8 yycheck[] =
+static const yytype_int16 yycheck[] =
{
- 10, 6, 13, 4, 10, 10, 11, 13, 8, 10,
- 10, 5, 11, 3, 19, 14, 10, 23, 0, 23,
- 24, 21, 9, 10, 11, 12, 18, 19, 6, 14,
- 13, 18, 24, 20, 13, 15, 15, 25, 17, 16,
- 28, 13, 9, 24, 8, 6, 22, -1, 23, -1,
- -1, 61, -1, -1, 64, 28, 25
+ 5, 38, 39, 17, 18, 19, 12, 12, 17, 18,
+ 7, 8, 13, 90, 4, 22, 93, 20, 25, 22,
+ 21, 22, 23, 24, 33, 3, 26, 34, 26, 32,
+ 31, 37, 22, 30, 43, 36, 25, 46, 47, 36,
+ 17, 18, 9, 10, 44, 45, 60, 61, 62, 17,
+ 18, 0, 89, 15, 22, 23, 33, 27, 14, 15,
+ 16, 23, 30, 11, 26, 33, 22, 25, 39, 27,
+ 35, 29, 52, 53, 54, 55, 5, 6, 42, 43,
+ 34, 35, 56, 57, 50, 51, 58, 59, 40, 25,
+ 41, 23, 25, 38, 16, 16, 33, 28, 25, 25,
+ 25, 17, 36, 21, 34, 8, 6, 35, 95, 47,
+ 45, 93, -1, -1, 90, -1, -1, 122, -1, -1,
+ 44, -1, -1, 46, -1, -1, -1, -1, 48, -1,
+ 135, -1, 49, 138
};
/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
symbol of state STATE-NUM. */
static const yytype_uint8 yystos[] =
{
- 0, 3, 26, 13, 0, 4, 10, 27, 28, 6,
- 29, 28, 14, 30, 27, 29, 15, 31, 11, 14,
- 13, 32, 31, 31, 5, 10, 33, 39, 40, 13,
- 17, 31, 33, 40, 16, 33, 39, 34, 35, 13,
- 10, 13, 23, 9, 10, 11, 12, 18, 20, 22,
- 36, 38, 9, 6, 10, 11, 19, 37, 8, 10,
- 21, 23, 24, 29, 23, 29, 24
+ 0, 3, 49, 25, 0, 4, 22, 50, 51, 17,
+ 18, 33, 59, 51, 26, 52, 50, 43, 46, 47,
+ 59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
+ 69, 70, 71, 72, 59, 27, 53, 15, 23, 26,
+ 72, 72, 72, 35, 12, 37, 11, 39, 40, 41,
+ 9, 10, 7, 8, 30, 36, 5, 6, 42, 43,
+ 26, 44, 45, 25, 54, 23, 53, 53, 63, 60,
+ 64, 65, 66, 67, 68, 68, 69, 69, 69, 69,
+ 70, 70, 71, 71, 72, 72, 72, 14, 15, 16,
+ 22, 55, 74, 75, 25, 38, 16, 16, 25, 29,
+ 53, 55, 75, 28, 55, 74, 61, 25, 25, 56,
+ 57, 25, 22, 25, 34, 13, 21, 22, 23, 24,
+ 31, 36, 58, 17, 33, 73, 22, 23, 30, 59,
+ 36, 21, 20, 22, 32, 34, 35, 59, 34, 59,
+ 35
};
#define yyerrok (yyerrstatus = 0)
@@ -596,18 +705,9 @@
/* Like YYERROR except do call yyerror. This remains here temporarily
to ease the transition to the new meaning of YYERROR, for GCC.
- Once GCC version 2 has supplanted version 1, this can go. However,
- YYFAIL appears to be in use. Nevertheless, it is formally deprecated
- in Bison 2.4.2's NEWS entry, where a plan to phase it out is
- discussed. */
+ Once GCC version 2 has supplanted version 1, this can go. */
#define YYFAIL goto yyerrlab
-#if defined YYFAIL
- /* This is here to suppress warnings from the GCC cpp's
- -Wunused-macros. Normally we don't worry about that warning, but
- some users do, and we want to make it easy for users to remove
- YYFAIL uses, which will produce warnings from Bison 2.5. */
-#endif
#define YYRECOVERING() (!!yyerrstatus)
@@ -664,7 +764,7 @@
we won't break user code: when these are the locations we know. */
#ifndef YY_LOCATION_PRINT
-# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
+# if YYLTYPE_IS_TRIVIAL
# define YY_LOCATION_PRINT(File, Loc) \
fprintf (File, "%d.%d-%d.%d", \
(Loc).first_line, (Loc).first_column, \
@@ -1403,6 +1503,8 @@
{
case 2:
+/* Line 1455 of yacc.c */
+#line 110 "dtc-parser.y"
{
the_boot_info = build_boot_info((yyvsp[(3) - (4)].re), (yyvsp[(4) - (4)].node),
guess_boot_cpuid((yyvsp[(4) - (4)].node)));
@@ -1411,6 +1513,8 @@
case 3:
+/* Line 1455 of yacc.c */
+#line 118 "dtc-parser.y"
{
(yyval.re) = NULL;
;}
@@ -1418,6 +1522,8 @@
case 4:
+/* Line 1455 of yacc.c */
+#line 122 "dtc-parser.y"
{
(yyval.re) = chain_reserve_entry((yyvsp[(1) - (2)].re), (yyvsp[(2) - (2)].re));
;}
@@ -1425,13 +1531,17 @@
case 5:
+/* Line 1455 of yacc.c */
+#line 129 "dtc-parser.y"
{
- (yyval.re) = build_reserve_entry((yyvsp[(2) - (4)].addr), (yyvsp[(3) - (4)].addr));
+ (yyval.re) = build_reserve_entry((yyvsp[(2) - (4)].integer), (yyvsp[(3) - (4)].integer));
;}
break;
case 6:
+/* Line 1455 of yacc.c */
+#line 133 "dtc-parser.y"
{
add_label(&(yyvsp[(2) - (2)].re)->labels, (yyvsp[(1) - (2)].labelref));
(yyval.re) = (yyvsp[(2) - (2)].re);
@@ -1440,27 +1550,26 @@
case 7:
- {
- (yyval.addr) = eval_literal((yyvsp[(1) - (1)].literal), 0, 64);
- ;}
- break;
-
- case 8:
-
+/* Line 1455 of yacc.c */
+#line 141 "dtc-parser.y"
{
(yyval.node) = name_node((yyvsp[(2) - (2)].node), "");
;}
break;
- case 9:
+ case 8:
+/* Line 1455 of yacc.c */
+#line 145 "dtc-parser.y"
{
(yyval.node) = merge_nodes((yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
;}
break;
- case 10:
+ case 9:
+/* Line 1455 of yacc.c */
+#line 149 "dtc-parser.y"
{
struct node *target = get_node_by_ref((yyvsp[(1) - (3)].node), (yyvsp[(2) - (3)].labelref));
@@ -1472,8 +1581,26 @@
;}
break;
+ case 10:
+
+/* Line 1455 of yacc.c */
+#line 159 "dtc-parser.y"
+ {
+ struct node *target = get_node_by_ref((yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].labelref));
+
+ if (!target)
+ print_error("label or path, '%s', not found", (yyvsp[(3) - (4)].labelref));
+ else
+ delete_node(target);
+
+ (yyval.node) = (yyvsp[(1) - (4)].node);
+ ;}
+ break;
+
case 11:
+/* Line 1455 of yacc.c */
+#line 173 "dtc-parser.y"
{
(yyval.node) = build_node((yyvsp[(2) - (5)].proplist), (yyvsp[(3) - (5)].nodelist));
;}
@@ -1481,6 +1608,8 @@
case 12:
+/* Line 1455 of yacc.c */
+#line 180 "dtc-parser.y"
{
(yyval.proplist) = NULL;
;}
@@ -1488,6 +1617,8 @@
case 13:
+/* Line 1455 of yacc.c */
+#line 184 "dtc-parser.y"
{
(yyval.proplist) = chain_property((yyvsp[(2) - (2)].prop), (yyvsp[(1) - (2)].proplist));
;}
@@ -1495,6 +1626,8 @@
case 14:
+/* Line 1455 of yacc.c */
+#line 191 "dtc-parser.y"
{
(yyval.prop) = build_property((yyvsp[(1) - (4)].propnodename), (yyvsp[(3) - (4)].data));
;}
@@ -1502,6 +1635,8 @@
case 15:
+/* Line 1455 of yacc.c */
+#line 195 "dtc-parser.y"
{
(yyval.prop) = build_property((yyvsp[(1) - (2)].propnodename), empty_data);
;}
@@ -1509,62 +1644,85 @@
case 16:
+/* Line 1455 of yacc.c */
+#line 199 "dtc-parser.y"
+ {
+ (yyval.prop) = build_property_delete((yyvsp[(2) - (3)].propnodename));
+ ;}
+ break;
+
+ case 17:
+
+/* Line 1455 of yacc.c */
+#line 203 "dtc-parser.y"
{
add_label(&(yyvsp[(2) - (2)].prop)->labels, (yyvsp[(1) - (2)].labelref));
(yyval.prop) = (yyvsp[(2) - (2)].prop);
;}
break;
- case 17:
+ case 18:
+/* Line 1455 of yacc.c */
+#line 211 "dtc-parser.y"
{
(yyval.data) = data_merge((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].data));
;}
break;
- case 18:
-
- {
- (yyval.data) = data_merge((yyvsp[(1) - (4)].data), (yyvsp[(3) - (4)].data));
- ;}
- break;
-
case 19:
+/* Line 1455 of yacc.c */
+#line 215 "dtc-parser.y"
{
- (yyval.data) = data_merge((yyvsp[(1) - (4)].data), (yyvsp[(3) - (4)].data));
+ (yyval.data) = data_merge((yyvsp[(1) - (3)].data), (yyvsp[(2) - (3)].array).data);
;}
break;
case 20:
+/* Line 1455 of yacc.c */
+#line 219 "dtc-parser.y"
{
- (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), REF_PATH, (yyvsp[(2) - (2)].labelref));
+ (yyval.data) = data_merge((yyvsp[(1) - (4)].data), (yyvsp[(3) - (4)].data));
;}
break;
case 21:
+/* Line 1455 of yacc.c */
+#line 223 "dtc-parser.y"
+ {
+ (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), REF_PATH, (yyvsp[(2) - (2)].labelref));
+ ;}
+ break;
+
+ case 22:
+
+/* Line 1455 of yacc.c */
+#line 227 "dtc-parser.y"
{
FILE *f = srcfile_relative_open((yyvsp[(4) - (9)].data).val, NULL);
struct data d;
- if ((yyvsp[(6) - (9)].addr) != 0)
- if (fseek(f, (yyvsp[(6) - (9)].addr), SEEK_SET) != 0)
+ if ((yyvsp[(6) - (9)].integer) != 0)
+ if (fseek(f, (yyvsp[(6) - (9)].integer), SEEK_SET) != 0)
print_error("Couldn't seek to offset %llu in \"%s\": %s",
- (unsigned long long)(yyvsp[(6) - (9)].addr),
+ (unsigned long long)(yyvsp[(6) - (9)].integer),
(yyvsp[(4) - (9)].data).val,
strerror(errno));
- d = data_copy_file(f, (yyvsp[(8) - (9)].addr));
+ d = data_copy_file(f, (yyvsp[(8) - (9)].integer));
(yyval.data) = data_merge((yyvsp[(1) - (9)].data), d);
fclose(f);
;}
break;
- case 22:
+ case 23:
+/* Line 1455 of yacc.c */
+#line 244 "dtc-parser.y"
{
FILE *f = srcfile_relative_open((yyvsp[(4) - (5)].data).val, NULL);
struct data d = empty_data;
@@ -1576,122 +1734,383 @@
;}
break;
- case 23:
-
- {
- (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
- ;}
- break;
-
case 24:
+/* Line 1455 of yacc.c */
+#line 254 "dtc-parser.y"
{
- (yyval.data) = empty_data;
+ (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
;}
break;
case 25:
+/* Line 1455 of yacc.c */
+#line 261 "dtc-parser.y"
{
- (yyval.data) = (yyvsp[(1) - (2)].data);
+ (yyval.data) = empty_data;
;}
break;
case 26:
+/* Line 1455 of yacc.c */
+#line 265 "dtc-parser.y"
{
- (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
+ (yyval.data) = (yyvsp[(1) - (2)].data);
;}
break;
case 27:
+/* Line 1455 of yacc.c */
+#line 269 "dtc-parser.y"
{
- (yyval.data) = empty_data;
+ (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
;}
break;
case 28:
+/* Line 1455 of yacc.c */
+#line 276 "dtc-parser.y"
{
- (yyval.data) = data_append_cell((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].cell));
+ (yyval.array).data = empty_data;
+ (yyval.array).bits = eval_literal((yyvsp[(2) - (3)].literal), 0, 7);
+
+ if (((yyval.array).bits != 8) &&
+ ((yyval.array).bits != 16) &&
+ ((yyval.array).bits != 32) &&
+ ((yyval.array).bits != 64))
+ {
+ print_error("Only 8, 16, 32 and 64-bit elements"
+ " are currently supported");
+ (yyval.array).bits = 32;
+ }
;}
break;
case 29:
+/* Line 1455 of yacc.c */
+#line 291 "dtc-parser.y"
{
- (yyval.data) = data_append_cell(data_add_marker((yyvsp[(1) - (2)].data), REF_PHANDLE,
- (yyvsp[(2) - (2)].labelref)), -1);
+ (yyval.array).data = empty_data;
+ (yyval.array).bits = 32;
;}
break;
case 30:
+/* Line 1455 of yacc.c */
+#line 296 "dtc-parser.y"
{
- (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
+ if ((yyvsp[(1) - (2)].array).bits < 64) {
+ uint64_t mask = (1ULL << (yyvsp[(1) - (2)].array).bits) - 1;
+ /*
+ * Bits above mask must either be all zero
+ * (positive within range of mask) or all one
+ * (negative and sign-extended). The second
+ * condition is true if when we set all bits
+ * within the mask to one (i.e. | in the
+ * mask), all bits are one.
+ */
+ if (((yyvsp[(2) - (2)].integer) > mask) && (((yyvsp[(2) - (2)].integer) | mask) != -1ULL))
+ print_error(
+ "integer value out of range "
+ "%016lx (%d bits)", (yyvsp[(1) - (2)].array).bits);
+ }
+
+ (yyval.array).data = data_append_integer((yyvsp[(1) - (2)].array).data, (yyvsp[(2) - (2)].integer), (yyvsp[(1) - (2)].array).bits);
;}
break;
case 31:
+/* Line 1455 of yacc.c */
+#line 316 "dtc-parser.y"
{
- (yyval.cell) = eval_literal((yyvsp[(1) - (1)].literal), 0, 32);
+ uint64_t val = ~0ULL >> (64 - (yyvsp[(1) - (2)].array).bits);
+
+ if ((yyvsp[(1) - (2)].array).bits == 32)
+ (yyvsp[(1) - (2)].array).data = data_add_marker((yyvsp[(1) - (2)].array).data,
+ REF_PHANDLE,
+ (yyvsp[(2) - (2)].labelref));
+ else
+ print_error("References are only allowed in "
+ "arrays with 32-bit elements.");
+
+ (yyval.array).data = data_append_integer((yyvsp[(1) - (2)].array).data, val, (yyvsp[(1) - (2)].array).bits);
;}
break;
case 32:
+/* Line 1455 of yacc.c */
+#line 330 "dtc-parser.y"
{
- (yyval.data) = empty_data;
+ (yyval.array).data = data_add_marker((yyvsp[(1) - (2)].array).data, LABEL, (yyvsp[(2) - (2)].labelref));
;}
break;
case 33:
+/* Line 1455 of yacc.c */
+#line 337 "dtc-parser.y"
{
- (yyval.data) = data_append_byte((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].byte));
+ (yyval.integer) = eval_literal((yyvsp[(1) - (1)].literal), 0, 64);
;}
break;
case 34:
+/* Line 1455 of yacc.c */
+#line 341 "dtc-parser.y"
{
- (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
+ (yyval.integer) = eval_char_literal((yyvsp[(1) - (1)].literal));
;}
break;
case 35:
+/* Line 1455 of yacc.c */
+#line 345 "dtc-parser.y"
+ {
+ (yyval.integer) = (yyvsp[(2) - (3)].integer);
+ ;}
+ break;
+
+ case 38:
+
+/* Line 1455 of yacc.c */
+#line 356 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (5)].integer) ? (yyvsp[(3) - (5)].integer) : (yyvsp[(5) - (5)].integer); ;}
+ break;
+
+ case 40:
+
+/* Line 1455 of yacc.c */
+#line 361 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) || (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+ case 42:
+
+/* Line 1455 of yacc.c */
+#line 366 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) && (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+ case 44:
+
+/* Line 1455 of yacc.c */
+#line 371 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) | (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+ case 46:
+
+/* Line 1455 of yacc.c */
+#line 376 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) ^ (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+ case 48:
+
+/* Line 1455 of yacc.c */
+#line 381 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) & (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+ case 50:
+
+/* Line 1455 of yacc.c */
+#line 386 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) == (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+ case 51:
+
+/* Line 1455 of yacc.c */
+#line 387 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) != (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+ case 53:
+
+/* Line 1455 of yacc.c */
+#line 392 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) < (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+ case 54:
+
+/* Line 1455 of yacc.c */
+#line 393 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) > (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+ case 55:
+
+/* Line 1455 of yacc.c */
+#line 394 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) <= (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+ case 56:
+
+/* Line 1455 of yacc.c */
+#line 395 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) >= (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+ case 57:
+
+/* Line 1455 of yacc.c */
+#line 399 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) << (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+ case 58:
+
+/* Line 1455 of yacc.c */
+#line 400 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) >> (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+ case 60:
+
+/* Line 1455 of yacc.c */
+#line 405 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) + (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+ case 61:
+
+/* Line 1455 of yacc.c */
+#line 406 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) - (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+ case 63:
+
+/* Line 1455 of yacc.c */
+#line 411 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) * (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+ case 64:
+
+/* Line 1455 of yacc.c */
+#line 412 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) / (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+ case 65:
+
+/* Line 1455 of yacc.c */
+#line 413 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) % (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+ case 68:
+
+/* Line 1455 of yacc.c */
+#line 419 "dtc-parser.y"
+ { (yyval.integer) = -(yyvsp[(2) - (2)].integer); ;}
+ break;
+
+ case 69:
+
+/* Line 1455 of yacc.c */
+#line 420 "dtc-parser.y"
+ { (yyval.integer) = ~(yyvsp[(2) - (2)].integer); ;}
+ break;
+
+ case 70:
+
+/* Line 1455 of yacc.c */
+#line 421 "dtc-parser.y"
+ { (yyval.integer) = !(yyvsp[(2) - (2)].integer); ;}
+ break;
+
+ case 71:
+
+/* Line 1455 of yacc.c */
+#line 426 "dtc-parser.y"
+ {
+ (yyval.data) = empty_data;
+ ;}
+ break;
+
+ case 72:
+
+/* Line 1455 of yacc.c */
+#line 430 "dtc-parser.y"
+ {
+ (yyval.data) = data_append_byte((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].byte));
+ ;}
+ break;
+
+ case 73:
+
+/* Line 1455 of yacc.c */
+#line 434 "dtc-parser.y"
+ {
+ (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
+ ;}
+ break;
+
+ case 74:
+
+/* Line 1455 of yacc.c */
+#line 441 "dtc-parser.y"
{
(yyval.nodelist) = NULL;
;}
break;
- case 36:
+ case 75:
+/* Line 1455 of yacc.c */
+#line 445 "dtc-parser.y"
{
(yyval.nodelist) = chain_node((yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].nodelist));
;}
break;
- case 37:
+ case 76:
+/* Line 1455 of yacc.c */
+#line 449 "dtc-parser.y"
{
print_error("syntax error: properties must precede subnodes");
YYERROR;
;}
break;
- case 38:
+ case 77:
+/* Line 1455 of yacc.c */
+#line 457 "dtc-parser.y"
{
(yyval.node) = name_node((yyvsp[(2) - (2)].node), (yyvsp[(1) - (2)].propnodename));
;}
break;
- case 39:
+ case 78:
+/* Line 1455 of yacc.c */
+#line 461 "dtc-parser.y"
+ {
+ (yyval.node) = name_node(build_node_delete(), (yyvsp[(2) - (3)].propnodename));
+ ;}
+ break;
+
+ case 79:
+
+/* Line 1455 of yacc.c */
+#line 465 "dtc-parser.y"
{
add_label(&(yyvsp[(2) - (2)].node)->labels, (yyvsp[(1) - (2)].labelref));
(yyval.node) = (yyvsp[(2) - (2)].node);
@@ -1700,6 +2119,8 @@
+/* Line 1455 of yacc.c */
+#line 2124 "dtc-parser.tab.c"
default: break;
}
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -1910,6 +2331,8 @@
+/* Line 1675 of yacc.c */
+#line 471 "dtc-parser.y"
void print_error(char const *fmt, ...)
@@ -1934,9 +2357,12 @@
errno = 0;
val = strtoull(s, &e, base);
- if (*e)
- print_error("bad characters in literal");
- else if ((errno == ERANGE)
+ if (*e) {
+ size_t uls = strspn(e, "UL");
+ if (e[uls])
+ print_error("bad characters in literal");
+ }
+ if ((errno == ERANGE)
|| ((bits < 64) && (val >= (1ULL << bits))))
print_error("literal out of range");
else if (errno != 0)
@@ -1944,3 +2370,29 @@
return val;
}
+static unsigned char eval_char_literal(const char *s)
+{
+ int i = 1;
+ char c = s[0];
+
+ if (c == '\0')
+ {
+ print_error("empty character literal");
+ return 0;
+ }
+
+ /*
+ * If the first character in the character literal is a \ then process
+ * the remaining characters as an escape encoding. If the first
+ * character is neither an escape or a terminator it should be the only
+ * character in the literal and will be returned.
+ */
+ if (c == '\\')
+ c = get_escape_char(s, &i);
+
+ if (s[i] != '\0')
+ print_error("malformed character literal");
+
+ return c;
+}
+
diff --git a/scripts/dtc/dtc-parser.tab.h_shipped b/scripts/dtc/dtc-parser.tab.h_shipped
index 4ee682b..9d2dce4 100644
--- a/scripts/dtc/dtc-parser.tab.h_shipped
+++ b/scripts/dtc/dtc-parser.tab.h_shipped
@@ -1,9 +1,10 @@
-/* A Bison parser, made by GNU Bison 2.4.3. */
+
+/* A Bison parser, made by GNU Bison 2.4.1. */
/* Skeleton interface for Bison's Yacc-like parsers in C
- Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
- 2009, 2010 Free Software Foundation, Inc.
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ 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
@@ -40,14 +41,26 @@
enum yytokentype {
DT_V1 = 258,
DT_MEMRESERVE = 259,
- DT_PROPNODENAME = 260,
- DT_LITERAL = 261,
- DT_BASE = 262,
- DT_BYTE = 263,
- DT_STRING = 264,
- DT_LABEL = 265,
- DT_REF = 266,
- DT_INCBIN = 267
+ 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_BASE = 274,
+ DT_BYTE = 275,
+ DT_STRING = 276,
+ DT_LABEL = 277,
+ DT_REF = 278,
+ DT_INCBIN = 279
};
#endif
@@ -57,6 +70,8 @@
typedef union YYSTYPE
{
+/* Line 1676 of yacc.c */
+#line 40 "dtc-parser.y"
char *propnodename;
char *literal;
@@ -65,16 +80,22 @@
uint8_t byte;
struct data data;
- uint64_t addr;
- cell_t cell;
+ struct {
+ struct data data;
+ int bits;
+ } array;
+
struct property *prop;
struct property *proplist;
struct node *node;
struct node *nodelist;
struct reserve_info *re;
+ uint64_t integer;
+/* Line 1676 of yacc.c */
+#line 99 "dtc-parser.tab.h"
} YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
diff --git a/scripts/dtc/dtc-parser.y b/scripts/dtc/dtc-parser.y
index 5e84a67..f412460 100644
--- a/scripts/dtc/dtc-parser.y
+++ b/scripts/dtc/dtc-parser.y
@@ -34,6 +34,7 @@
extern int treesource_error;
static unsigned long long eval_literal(const char *s, int base, int bits);
+static unsigned char eval_char_literal(const char *s);
%}
%union {
@@ -44,19 +45,28 @@
uint8_t byte;
struct data data;
- uint64_t addr;
- cell_t cell;
+ struct {
+ struct data data;
+ int bits;
+ } array;
+
struct property *prop;
struct property *proplist;
struct node *node;
struct node *nodelist;
struct reserve_info *re;
+ uint64_t integer;
}
%token DT_V1
%token DT_MEMRESERVE
+%token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR
+%token DT_BITS
+%token DT_DEL_PROP
+%token DT_DEL_NODE
%token <propnodename> DT_PROPNODENAME
%token <literal> DT_LITERAL
+%token <literal> DT_CHAR_LITERAL
%token <cbase> DT_BASE
%token <byte> DT_BYTE
%token <data> DT_STRING
@@ -68,9 +78,7 @@
%type <data> propdataprefix
%type <re> memreserve
%type <re> memreserves
-%type <addr> addr
-%type <data> celllist
-%type <cell> cellval
+%type <array> arrayprefix
%type <data> bytestring
%type <prop> propdef
%type <proplist> proplist
@@ -80,6 +88,21 @@
%type <node> subnode
%type <nodelist> subnodes
+%type <integer> integer_prim
+%type <integer> integer_unary
+%type <integer> integer_mul
+%type <integer> integer_add
+%type <integer> integer_shift
+%type <integer> integer_rela
+%type <integer> integer_eq
+%type <integer> integer_bitand
+%type <integer> integer_bitxor
+%type <integer> integer_bitor
+%type <integer> integer_and
+%type <integer> integer_or
+%type <integer> integer_trinary
+%type <integer> integer_expr
+
%%
sourcefile:
@@ -102,7 +125,7 @@
;
memreserve:
- DT_MEMRESERVE addr addr ';'
+ DT_MEMRESERVE integer_prim integer_prim ';'
{
$$ = build_reserve_entry($2, $3);
}
@@ -113,13 +136,6 @@
}
;
-addr:
- DT_LITERAL
- {
- $$ = eval_literal($1, 0, 64);
- }
- ;
-
devicetree:
'/' nodedef
{
@@ -139,6 +155,17 @@
print_error("label or path, '%s', not found", $2);
$$ = $1;
}
+ | devicetree DT_DEL_NODE DT_REF ';'
+ {
+ struct node *target = get_node_by_ref($1, $3);
+
+ if (!target)
+ print_error("label or path, '%s', not found", $3);
+ else
+ delete_node(target);
+
+ $$ = $1;
+ }
;
nodedef:
@@ -168,6 +195,10 @@
{
$$ = build_property($1, empty_data);
}
+ | DT_DEL_PROP DT_PROPNODENAME ';'
+ {
+ $$ = build_property_delete($2);
+ }
| DT_LABEL propdef
{
add_label(&$2->labels, $1);
@@ -180,9 +211,9 @@
{
$$ = data_merge($1, $2);
}
- | propdataprefix '<' celllist '>'
+ | propdataprefix arrayprefix '>'
{
- $$ = data_merge($1, $3);
+ $$ = data_merge($1, $2.data);
}
| propdataprefix '[' bytestring ']'
{
@@ -192,7 +223,7 @@
{
$$ = data_add_marker($1, REF_PATH, $2);
}
- | propdataprefix DT_INCBIN '(' DT_STRING ',' addr ',' addr ')'
+ | propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')'
{
FILE *f = srcfile_relative_open($4.val, NULL);
struct data d;
@@ -240,31 +271,154 @@
}
;
-celllist:
- /* empty */
+arrayprefix:
+ DT_BITS DT_LITERAL '<'
{
- $$ = empty_data;
+ $$.data = empty_data;
+ $$.bits = eval_literal($2, 0, 7);
+
+ if (($$.bits != 8) &&
+ ($$.bits != 16) &&
+ ($$.bits != 32) &&
+ ($$.bits != 64))
+ {
+ print_error("Only 8, 16, 32 and 64-bit elements"
+ " are currently supported");
+ $$.bits = 32;
+ }
}
- | celllist cellval
+ | '<'
{
- $$ = data_append_cell($1, $2);
+ $$.data = empty_data;
+ $$.bits = 32;
}
- | celllist DT_REF
+ | arrayprefix integer_prim
{
- $$ = data_append_cell(data_add_marker($1, REF_PHANDLE,
- $2), -1);
+ if ($1.bits < 64) {
+ uint64_t mask = (1ULL << $1.bits) - 1;
+ /*
+ * Bits above mask must either be all zero
+ * (positive within range of mask) or all one
+ * (negative and sign-extended). The second
+ * condition is true if when we set all bits
+ * within the mask to one (i.e. | in the
+ * mask), all bits are one.
+ */
+ if (($2 > mask) && (($2 | mask) != -1ULL))
+ print_error(
+ "integer value out of range "
+ "%016lx (%d bits)", $1.bits);
+ }
+
+ $$.data = data_append_integer($1.data, $2, $1.bits);
}
- | celllist DT_LABEL
+ | arrayprefix DT_REF
{
- $$ = data_add_marker($1, LABEL, $2);
+ uint64_t val = ~0ULL >> (64 - $1.bits);
+
+ if ($1.bits == 32)
+ $1.data = data_add_marker($1.data,
+ REF_PHANDLE,
+ $2);
+ else
+ print_error("References are only allowed in "
+ "arrays with 32-bit elements.");
+
+ $$.data = data_append_integer($1.data, val, $1.bits);
+ }
+ | arrayprefix DT_LABEL
+ {
+ $$.data = data_add_marker($1.data, LABEL, $2);
}
;
-cellval:
+integer_prim:
DT_LITERAL
{
- $$ = eval_literal($1, 0, 32);
+ $$ = eval_literal($1, 0, 64);
}
+ | DT_CHAR_LITERAL
+ {
+ $$ = eval_char_literal($1);
+ }
+ | '(' integer_expr ')'
+ {
+ $$ = $2;
+ }
+ ;
+
+integer_expr:
+ integer_trinary
+ ;
+
+integer_trinary:
+ integer_or
+ | integer_or '?' integer_expr ':' integer_trinary { $$ = $1 ? $3 : $5; }
+ ;
+
+integer_or:
+ integer_and
+ | integer_or DT_OR integer_and { $$ = $1 || $3; }
+ ;
+
+integer_and:
+ integer_bitor
+ | integer_and DT_AND integer_bitor { $$ = $1 && $3; }
+ ;
+
+integer_bitor:
+ integer_bitxor
+ | integer_bitor '|' integer_bitxor { $$ = $1 | $3; }
+ ;
+
+integer_bitxor:
+ integer_bitand
+ | integer_bitxor '^' integer_bitand { $$ = $1 ^ $3; }
+ ;
+
+integer_bitand:
+ integer_eq
+ | integer_bitand '&' integer_eq { $$ = $1 & $3; }
+ ;
+
+integer_eq:
+ integer_rela
+ | integer_eq DT_EQ integer_rela { $$ = $1 == $3; }
+ | integer_eq DT_NE integer_rela { $$ = $1 != $3; }
+ ;
+
+integer_rela:
+ integer_shift
+ | integer_rela '<' integer_shift { $$ = $1 < $3; }
+ | integer_rela '>' integer_shift { $$ = $1 > $3; }
+ | integer_rela DT_LE integer_shift { $$ = $1 <= $3; }
+ | integer_rela DT_GE integer_shift { $$ = $1 >= $3; }
+ ;
+
+integer_shift:
+ integer_shift DT_LSHIFT integer_add { $$ = $1 << $3; }
+ | integer_shift DT_RSHIFT integer_add { $$ = $1 >> $3; }
+ | integer_add
+ ;
+
+integer_add:
+ integer_add '+' integer_mul { $$ = $1 + $3; }
+ | integer_add '-' integer_mul { $$ = $1 - $3; }
+ | integer_mul
+ ;
+
+integer_mul:
+ integer_mul '*' integer_unary { $$ = $1 * $3; }
+ | integer_mul '/' integer_unary { $$ = $1 / $3; }
+ | integer_mul '%' integer_unary { $$ = $1 % $3; }
+ | integer_unary
+ ;
+
+integer_unary:
+ integer_prim
+ | '-' integer_unary { $$ = -$2; }
+ | '~' integer_unary { $$ = ~$2; }
+ | '!' integer_unary { $$ = !$2; }
;
bytestring:
@@ -303,6 +457,10 @@
{
$$ = name_node($2, $1);
}
+ | DT_DEL_NODE DT_PROPNODENAME ';'
+ {
+ $$ = name_node(build_node_delete(), $2);
+ }
| DT_LABEL subnode
{
add_label(&$2->labels, $1);
@@ -334,12 +492,41 @@
errno = 0;
val = strtoull(s, &e, base);
- if (*e)
- print_error("bad characters in literal");
- else if ((errno == ERANGE)
+ if (*e) {
+ size_t uls = strspn(e, "UL");
+ if (e[uls])
+ print_error("bad characters in literal");
+ }
+ if ((errno == ERANGE)
|| ((bits < 64) && (val >= (1ULL << bits))))
print_error("literal out of range");
else if (errno != 0)
print_error("bad literal");
return val;
}
+
+static unsigned char eval_char_literal(const char *s)
+{
+ int i = 1;
+ char c = s[0];
+
+ if (c == '\0')
+ {
+ print_error("empty character literal");
+ return 0;
+ }
+
+ /*
+ * If the first character in the character literal is a \ then process
+ * the remaining characters as an escape encoding. If the first
+ * character is neither an escape or a terminator it should be the only
+ * character in the literal and will be returned.
+ */
+ if (c == '\\')
+ c = get_escape_char(s, &i);
+
+ if (s[i] != '\0')
+ print_error("malformed character literal");
+
+ return c;
+}
diff --git a/scripts/dtc/dtc.c b/scripts/dtc/dtc.c
index 2ef5e2e..a375683 100644
--- a/scripts/dtc/dtc.c
+++ b/scripts/dtc/dtc.c
@@ -82,6 +82,8 @@
fprintf(stderr, "\t\tSet the physical boot cpu\n");
fprintf(stderr, "\t-f\n");
fprintf(stderr, "\t\tForce - try to produce output even if the input tree has errors\n");
+ fprintf(stderr, "\t-i\n");
+ fprintf(stderr, "\t\tAdd a path to search for include files\n");
fprintf(stderr, "\t-s\n");
fprintf(stderr, "\t\tSort nodes and properties before outputting (only useful for\n\t\tcomparing trees)\n");
fprintf(stderr, "\t-v\n");
@@ -91,6 +93,9 @@
fprintf(stderr, "\t\t\tlegacy - \"linux,phandle\" properties only\n");
fprintf(stderr, "\t\t\tepapr - \"phandle\" properties only\n");
fprintf(stderr, "\t\t\tboth - Both \"linux,phandle\" and \"phandle\" properties\n");
+ fprintf(stderr, "\t-W [no-]<checkname>\n");
+ fprintf(stderr, "\t-E [no-]<checkname>\n");
+ fprintf(stderr, "\t\t\tenable or disable warnings and errors\n");
exit(3);
}
@@ -113,7 +118,7 @@
minsize = 0;
padsize = 0;
- while ((opt = getopt(argc, argv, "hI:O:o:V:d:R:S:p:fcqb:vH:s"))
+ while ((opt = getopt(argc, argv, "hI:O:o:V:d:R:S:p:fqb:i:vH:sW:E:"))
!= EOF) {
switch (opt) {
case 'I':
@@ -149,6 +154,9 @@
case 'b':
cmdline_boot_cpuid = strtoll(optarg, NULL, 0);
break;
+ case 'i':
+ srcfile_add_search_path(optarg);
+ break;
case 'v':
printf("Version: %s\n", DTC_VERSION);
exit(0);
@@ -168,6 +176,14 @@
sort = 1;
break;
+ case 'W':
+ parse_checks_option(true, false, optarg);
+ break;
+
+ case 'E':
+ parse_checks_option(false, true, optarg);
+ break;
+
case 'h':
default:
usage();
@@ -188,9 +204,6 @@
if (minsize)
fprintf(stderr, "DTC: Use of \"-S\" is deprecated; it will be removed soon, use \"-p\" instead\n");
- fprintf(stderr, "DTC: %s->%s on file \"%s\"\n",
- inform, outform, arg);
-
if (depname) {
depfile = fopen(depname, "w");
if (!depfile)
diff --git a/scripts/dtc/dtc.h b/scripts/dtc/dtc.h
index f37c97e..3e42a07 100644
--- a/scripts/dtc/dtc.h
+++ b/scripts/dtc/dtc.h
@@ -25,6 +25,7 @@
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
+#include <stdbool.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>
@@ -109,6 +110,7 @@
const void *p, int len);
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_addr(struct data d, uint64_t addr);
struct data data_append_byte(struct data d, uint8_t byte);
@@ -126,11 +128,13 @@
/* Live trees */
struct label {
+ int deleted;
char *label;
struct label *next;
};
struct property {
+ int deleted;
char *name;
struct data val;
@@ -140,6 +144,7 @@
};
struct node {
+ int deleted;
char *name;
struct property *proplist;
struct node *children;
@@ -156,28 +161,47 @@
struct label *labels;
};
-#define for_each_label(l0, l) \
+#define for_each_label_withdel(l0, l) \
for ((l) = (l0); (l); (l) = (l)->next)
-#define for_each_property(n, p) \
+#define for_each_label(l0, l) \
+ for_each_label_withdel(l0, l) \
+ if (!(l)->deleted)
+
+#define for_each_property_withdel(n, p) \
for ((p) = (n)->proplist; (p); (p) = (p)->next)
-#define for_each_child(n, c) \
+#define for_each_property(n, p) \
+ for_each_property_withdel(n, p) \
+ if (!(p)->deleted)
+
+#define for_each_child_withdel(n, c) \
for ((c) = (n)->children; (c); (c) = (c)->next_sibling)
+#define for_each_child(n, c) \
+ for_each_child_withdel(n, c) \
+ if (!(c)->deleted)
+
void add_label(struct label **labels, char *label);
+void delete_labels(struct label **labels);
struct property *build_property(char *name, struct data val);
+struct property *build_property_delete(char *name);
struct property *chain_property(struct property *first, struct property *list);
struct property *reverse_properties(struct property *first);
struct node *build_node(struct property *proplist, struct node *children);
+struct node *build_node_delete(void);
struct node *name_node(struct node *node, char *name);
struct node *chain_node(struct node *first, struct node *list);
struct node *merge_nodes(struct node *old_node, struct node *new_node);
void add_property(struct node *node, struct property *prop);
+void delete_property_by_name(struct node *node, char *name);
+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);
const char *get_unitname(struct node *node);
struct property *get_property(struct node *node, const char *propname);
@@ -224,6 +248,7 @@
/* Checks */
+void parse_checks_option(bool warn, bool error, const char *optarg);
void process_checks(int force, struct boot_info *bi);
/* Flattened trees */
diff --git a/scripts/dtc/fdtdump.c b/scripts/dtc/fdtdump.c
new file mode 100644
index 0000000..207a46d
--- /dev/null
+++ b/scripts/dtc/fdtdump.c
@@ -0,0 +1,162 @@
+/*
+ * fdtdump.c - Contributed by Pantelis Antoniou <pantelis.antoniou AT gmail.com>
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <fdt.h>
+#include <libfdt_env.h>
+
+#include "util.h"
+
+#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
+#define PALIGN(p, a) ((void *)(ALIGN((unsigned long)(p), (a))))
+#define GET_CELL(p) (p += 4, *((const uint32_t *)(p-4)))
+
+static void print_data(const char *data, int len)
+{
+ int i;
+ const char *p = data;
+
+ /* no data, don't print */
+ if (len == 0)
+ return;
+
+ if (util_is_printable_string(data, len)) {
+ printf(" = \"%s\"", (const char *)data);
+ } else if ((len % 4) == 0) {
+ printf(" = <");
+ for (i = 0; i < len; i += 4)
+ printf("0x%08x%s", fdt32_to_cpu(GET_CELL(p)),
+ i < (len - 4) ? " " : "");
+ printf(">");
+ } else {
+ printf(" = [");
+ for (i = 0; i < len; i++)
+ printf("%02x%s", *p++, i < len - 1 ? " " : "");
+ printf("]");
+ }
+}
+
+static void dump_blob(void *blob)
+{
+ struct fdt_header *bph = blob;
+ uint32_t off_mem_rsvmap = fdt32_to_cpu(bph->off_mem_rsvmap);
+ uint32_t off_dt = fdt32_to_cpu(bph->off_dt_struct);
+ uint32_t off_str = fdt32_to_cpu(bph->off_dt_strings);
+ struct fdt_reserve_entry *p_rsvmap =
+ (struct fdt_reserve_entry *)((char *)blob + off_mem_rsvmap);
+ const char *p_struct = (const char *)blob + off_dt;
+ const char *p_strings = (const char *)blob + off_str;
+ uint32_t version = fdt32_to_cpu(bph->version);
+ uint32_t totalsize = fdt32_to_cpu(bph->totalsize);
+ uint32_t tag;
+ const char *p, *s, *t;
+ int depth, sz, shift;
+ int i;
+ uint64_t addr, size;
+
+ depth = 0;
+ shift = 4;
+
+ printf("/dts-v1/;\n");
+ printf("// magic:\t\t0x%x\n", fdt32_to_cpu(bph->magic));
+ printf("// totalsize:\t\t0x%x (%d)\n", totalsize, totalsize);
+ printf("// off_dt_struct:\t0x%x\n", off_dt);
+ printf("// off_dt_strings:\t0x%x\n", off_str);
+ printf("// off_mem_rsvmap:\t0x%x\n", off_mem_rsvmap);
+ printf("// version:\t\t%d\n", version);
+ printf("// last_comp_version:\t%d\n",
+ fdt32_to_cpu(bph->last_comp_version));
+ if (version >= 2)
+ printf("// boot_cpuid_phys:\t0x%x\n",
+ fdt32_to_cpu(bph->boot_cpuid_phys));
+
+ if (version >= 3)
+ printf("// size_dt_strings:\t0x%x\n",
+ fdt32_to_cpu(bph->size_dt_strings));
+ if (version >= 17)
+ printf("// size_dt_struct:\t0x%x\n",
+ fdt32_to_cpu(bph->size_dt_struct));
+ printf("\n");
+
+ for (i = 0; ; i++) {
+ addr = fdt64_to_cpu(p_rsvmap[i].address);
+ size = fdt64_to_cpu(p_rsvmap[i].size);
+ if (addr == 0 && size == 0)
+ break;
+
+ printf("/memreserve/ %llx %llx;\n",
+ (unsigned long long)addr, (unsigned long long)size);
+ }
+
+ p = p_struct;
+ while ((tag = fdt32_to_cpu(GET_CELL(p))) != FDT_END) {
+
+ /* printf("tag: 0x%08x (%d)\n", tag, p - p_struct); */
+
+ if (tag == FDT_BEGIN_NODE) {
+ s = p;
+ p = PALIGN(p + strlen(s) + 1, 4);
+
+ if (*s == '\0')
+ s = "/";
+
+ printf("%*s%s {\n", depth * shift, "", s);
+
+ depth++;
+ continue;
+ }
+
+ if (tag == FDT_END_NODE) {
+ depth--;
+
+ printf("%*s};\n", depth * shift, "");
+ continue;
+ }
+
+ if (tag == FDT_NOP) {
+ printf("%*s// [NOP]\n", depth * shift, "");
+ continue;
+ }
+
+ if (tag != FDT_PROP) {
+ fprintf(stderr, "%*s ** Unknown tag 0x%08x\n", depth * shift, "", tag);
+ break;
+ }
+ sz = fdt32_to_cpu(GET_CELL(p));
+ s = p_strings + fdt32_to_cpu(GET_CELL(p));
+ if (version < 16 && sz >= 8)
+ p = PALIGN(p, 8);
+ t = p;
+
+ p = PALIGN(p + sz, 4);
+
+ printf("%*s%s", depth * shift, "", s);
+ print_data(t, sz);
+ printf(";\n");
+ }
+}
+
+
+int main(int argc, char *argv[])
+{
+ char *buf;
+
+ if (argc < 2) {
+ fprintf(stderr, "supply input filename\n");
+ return 5;
+ }
+
+ buf = utilfdt_read(argv[1]);
+ if (buf)
+ dump_blob(buf);
+ else
+ return 10;
+
+ return 0;
+}
diff --git a/scripts/dtc/fdtget.c b/scripts/dtc/fdtget.c
new file mode 100644
index 0000000..c2fbab2
--- /dev/null
+++ b/scripts/dtc/fdtget.c
@@ -0,0 +1,366 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+ *
+ * Portions from U-Boot cmd_fdt.c (C) Copyright 2007
+ * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com
+ * Based on code written by:
+ * Pantelis Antoniou <pantelis.antoniou@gmail.com> and
+ * Matthew McClintock <msm@freescale.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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <assert.h>
+#include <ctype.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libfdt.h>
+
+#include "util.h"
+
+enum display_mode {
+ MODE_SHOW_VALUE, /* show values for node properties */
+ MODE_LIST_PROPS, /* list the properties for a node */
+ MODE_LIST_SUBNODES, /* list the subnodes of a node */
+};
+
+/* Holds information which controls our output and options */
+struct display_info {
+ int type; /* data type (s/i/u/x or 0 for default) */
+ int size; /* data size (1/2/4) */
+ enum display_mode mode; /* display mode that we are using */
+ const char *default_val; /* default value if node/property not found */
+};
+
+static void report_error(const char *where, int err)
+{
+ fprintf(stderr, "Error at '%s': %s\n", where, fdt_strerror(err));
+}
+
+/**
+ * Displays data of a given length according to selected options
+ *
+ * If a specific data type is provided in disp, then this is used. Otherwise
+ * we try to guess the data type / size from the contents.
+ *
+ * @param disp Display information / options
+ * @param data Data to display
+ * @param len Maximum length of buffer
+ * @return 0 if ok, -1 if data does not match format
+ */
+static int show_data(struct display_info *disp, const char *data, int len)
+{
+ int i, size;
+ const uint8_t *p = (const uint8_t *)data;
+ const char *s;
+ int value;
+ int is_string;
+ char fmt[3];
+
+ /* no data, don't print */
+ if (len == 0)
+ return 0;
+
+ is_string = (disp->type) == 's' ||
+ (!disp->type && util_is_printable_string(data, len));
+ if (is_string) {
+ if (data[len - 1] != '\0') {
+ fprintf(stderr, "Unterminated string\n");
+ return -1;
+ }
+ for (s = data; s - data < len; s += strlen(s) + 1) {
+ if (s != data)
+ printf(" ");
+ printf("%s", (const char *)s);
+ }
+ return 0;
+ }
+ size = disp->size;
+ if (size == -1) {
+ size = (len % 4) == 0 ? 4 : 1;
+ } else if (len % size) {
+ fprintf(stderr, "Property length must be a multiple of "
+ "selected data size\n");
+ return -1;
+ }
+ fmt[0] = '%';
+ fmt[1] = disp->type ? disp->type : 'd';
+ fmt[2] = '\0';
+ for (i = 0; i < len; i += size, p += size) {
+ if (i)
+ printf(" ");
+ value = size == 4 ? fdt32_to_cpu(*(const uint32_t *)p) :
+ size == 2 ? (*p << 8) | p[1] : *p;
+ printf(fmt, value);
+ }
+ return 0;
+}
+
+/**
+ * List all properties in a node, one per line.
+ *
+ * @param blob FDT blob
+ * @param node Node to display
+ * @return 0 if ok, or FDT_ERR... if not.
+ */
+static int list_properties(const void *blob, int node)
+{
+ const struct fdt_property *data;
+ const char *name;
+ int prop;
+
+ prop = fdt_first_property_offset(blob, node);
+ do {
+ /* Stop silently when there are no more properties */
+ if (prop < 0)
+ return prop == -FDT_ERR_NOTFOUND ? 0 : prop;
+ data = fdt_get_property_by_offset(blob, prop, NULL);
+ name = fdt_string(blob, fdt32_to_cpu(data->nameoff));
+ if (name)
+ puts(name);
+ prop = fdt_next_property_offset(blob, prop);
+ } while (1);
+}
+
+#define MAX_LEVEL 32 /* how deeply nested we will go */
+
+/**
+ * List all subnodes in a node, one per line
+ *
+ * @param blob FDT blob
+ * @param node Node to display
+ * @return 0 if ok, or FDT_ERR... if not.
+ */
+static int list_subnodes(const void *blob, int node)
+{
+ int nextoffset; /* next node offset from libfdt */
+ uint32_t tag; /* current tag */
+ int level = 0; /* keep track of nesting level */
+ const char *pathp;
+ int depth = 1; /* the assumed depth of this node */
+
+ while (level >= 0) {
+ tag = fdt_next_tag(blob, node, &nextoffset);
+ switch (tag) {
+ case FDT_BEGIN_NODE:
+ pathp = fdt_get_name(blob, node, NULL);
+ if (level <= depth) {
+ if (pathp == NULL)
+ pathp = "/* NULL pointer error */";
+ if (*pathp == '\0')
+ pathp = "/"; /* root is nameless */
+ if (level == 1)
+ puts(pathp);
+ }
+ level++;
+ if (level >= MAX_LEVEL) {
+ printf("Nested too deep, aborting.\n");
+ return 1;
+ }
+ break;
+ case FDT_END_NODE:
+ level--;
+ if (level == 0)
+ level = -1; /* exit the loop */
+ break;
+ case FDT_END:
+ return 1;
+ case FDT_PROP:
+ break;
+ default:
+ if (level <= depth)
+ printf("Unknown tag 0x%08X\n", tag);
+ return 1;
+ }
+ node = nextoffset;
+ }
+ return 0;
+}
+
+/**
+ * Show the data for a given node (and perhaps property) according to the
+ * display option provided.
+ *
+ * @param blob FDT blob
+ * @param disp Display information / options
+ * @param node Node to display
+ * @param property Name of property to display, or NULL if none
+ * @return 0 if ok, -ve on error
+ */
+static int show_data_for_item(const void *blob, struct display_info *disp,
+ int node, const char *property)
+{
+ const void *value = NULL;
+ int len, err = 0;
+
+ switch (disp->mode) {
+ case MODE_LIST_PROPS:
+ err = list_properties(blob, node);
+ break;
+
+ case MODE_LIST_SUBNODES:
+ err = list_subnodes(blob, node);
+ break;
+
+ default:
+ assert(property);
+ value = fdt_getprop(blob, node, property, &len);
+ if (value) {
+ if (show_data(disp, value, len))
+ err = -1;
+ else
+ printf("\n");
+ } else if (disp->default_val) {
+ puts(disp->default_val);
+ } else {
+ report_error(property, len);
+ err = -1;
+ }
+ break;
+ }
+
+ return err;
+}
+
+/**
+ * Run the main fdtget operation, given a filename and valid arguments
+ *
+ * @param disp Display information / options
+ * @param filename Filename of blob file
+ * @param arg List of arguments to process
+ * @param arg_count Number of arguments
+ * @param return 0 if ok, -ve on error
+ */
+static int do_fdtget(struct display_info *disp, const char *filename,
+ char **arg, int arg_count, int args_per_step)
+{
+ char *blob;
+ const char *prop;
+ int i, node;
+
+ blob = utilfdt_read(filename);
+ if (!blob)
+ return -1;
+
+ for (i = 0; i + args_per_step <= arg_count; i += args_per_step) {
+ node = fdt_path_offset(blob, arg[i]);
+ if (node < 0) {
+ if (disp->default_val) {
+ puts(disp->default_val);
+ continue;
+ } else {
+ report_error(arg[i], node);
+ return -1;
+ }
+ }
+ prop = args_per_step == 1 ? NULL : arg[i + 1];
+
+ if (show_data_for_item(blob, disp, node, prop))
+ return -1;
+ }
+ return 0;
+}
+
+static const char *usage_msg =
+ "fdtget - read values from device tree\n"
+ "\n"
+ "Each value is printed on a new line.\n\n"
+ "Usage:\n"
+ " fdtget <options> <dt file> [<node> <property>]...\n"
+ " fdtget -p <options> <dt file> [<node> ]...\n"
+ "Options:\n"
+ "\t-t <type>\tType of data\n"
+ "\t-p\t\tList properties for each node\n"
+ "\t-l\t\tList subnodes for each node\n"
+ "\t-d\t\tDefault value to display when the property is "
+ "missing\n"
+ "\t-h\t\tPrint this help\n\n"
+ USAGE_TYPE_MSG;
+
+static void usage(const char *msg)
+{
+ if (msg)
+ fprintf(stderr, "Error: %s\n\n", msg);
+
+ fprintf(stderr, "%s", usage_msg);
+ exit(2);
+}
+
+int main(int argc, char *argv[])
+{
+ char *filename = NULL;
+ struct display_info disp;
+ int args_per_step = 2;
+
+ /* set defaults */
+ memset(&disp, '\0', sizeof(disp));
+ disp.size = -1;
+ disp.mode = MODE_SHOW_VALUE;
+ for (;;) {
+ int c = getopt(argc, argv, "d:hlpt:");
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'h':
+ case '?':
+ usage(NULL);
+
+ case 't':
+ if (utilfdt_decode_type(optarg, &disp.type,
+ &disp.size))
+ usage("Invalid type string");
+ break;
+
+ case 'p':
+ disp.mode = MODE_LIST_PROPS;
+ args_per_step = 1;
+ break;
+
+ case 'l':
+ disp.mode = MODE_LIST_SUBNODES;
+ args_per_step = 1;
+ break;
+
+ case 'd':
+ disp.default_val = optarg;
+ break;
+ }
+ }
+
+ if (optind < argc)
+ filename = argv[optind++];
+ if (!filename)
+ usage("Missing filename");
+
+ argv += optind;
+ argc -= optind;
+
+ /* Allow no arguments, and silently succeed */
+ if (!argc)
+ return 0;
+
+ /* Check for node, property arguments */
+ if (args_per_step == 2 && (argc % 2))
+ usage("Must have an even number of arguments");
+
+ if (do_fdtget(&disp, filename, argv, argc, args_per_step))
+ return 1;
+ return 0;
+}
diff --git a/scripts/dtc/fdtput.c b/scripts/dtc/fdtput.c
new file mode 100644
index 0000000..f2197f5
--- /dev/null
+++ b/scripts/dtc/fdtput.c
@@ -0,0 +1,362 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <assert.h>
+#include <ctype.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libfdt.h>
+
+#include "util.h"
+
+/* These are the operations we support */
+enum oper_type {
+ OPER_WRITE_PROP, /* Write a property in a node */
+ OPER_CREATE_NODE, /* Create a new node */
+};
+
+struct display_info {
+ enum oper_type oper; /* operation to perform */
+ int type; /* data type (s/i/u/x or 0 for default) */
+ int size; /* data size (1/2/4) */
+ int verbose; /* verbose output */
+ int auto_path; /* automatically create all path components */
+};
+
+
+/**
+ * Report an error with a particular node.
+ *
+ * @param name Node name to report error on
+ * @param namelen Length of node name, or -1 to use entire string
+ * @param err Error number to report (-FDT_ERR_...)
+ */
+static void report_error(const char *name, int namelen, int err)
+{
+ if (namelen == -1)
+ namelen = strlen(name);
+ fprintf(stderr, "Error at '%1.*s': %s\n", namelen, name,
+ fdt_strerror(err));
+}
+
+/**
+ * Encode a series of arguments in a property value.
+ *
+ * @param disp Display information / options
+ * @param arg List of arguments from command line
+ * @param arg_count Number of arguments (may be 0)
+ * @param valuep Returns buffer containing value
+ * @param *value_len Returns length of value encoded
+ */
+static int encode_value(struct display_info *disp, char **arg, int arg_count,
+ char **valuep, int *value_len)
+{
+ char *value = NULL; /* holding area for value */
+ int value_size = 0; /* size of holding area */
+ char *ptr; /* pointer to current value position */
+ int len; /* length of this cell/string/byte */
+ int ival;
+ int upto; /* the number of bytes we have written to buf */
+ char fmt[3];
+
+ upto = 0;
+
+ if (disp->verbose)
+ fprintf(stderr, "Decoding value:\n");
+
+ fmt[0] = '%';
+ fmt[1] = disp->type ? disp->type : 'd';
+ fmt[2] = '\0';
+ for (; arg_count > 0; arg++, arg_count--, upto += len) {
+ /* assume integer unless told otherwise */
+ if (disp->type == 's')
+ len = strlen(*arg) + 1;
+ else
+ len = disp->size == -1 ? 4 : disp->size;
+
+ /* enlarge our value buffer by a suitable margin if needed */
+ if (upto + len > value_size) {
+ value_size = (upto + len) + 500;
+ value = realloc(value, value_size);
+ if (!value) {
+ fprintf(stderr, "Out of mmory: cannot alloc "
+ "%d bytes\n", value_size);
+ return -1;
+ }
+ }
+
+ ptr = value + upto;
+ if (disp->type == 's') {
+ memcpy(ptr, *arg, len);
+ if (disp->verbose)
+ fprintf(stderr, "\tstring: '%s'\n", ptr);
+ } else {
+ int *iptr = (int *)ptr;
+ sscanf(*arg, fmt, &ival);
+ if (len == 4)
+ *iptr = cpu_to_fdt32(ival);
+ else
+ *ptr = (uint8_t)ival;
+ if (disp->verbose) {
+ fprintf(stderr, "\t%s: %d\n",
+ disp->size == 1 ? "byte" :
+ disp->size == 2 ? "short" : "int",
+ ival);
+ }
+ }
+ }
+ *value_len = upto;
+ *valuep = value;
+ if (disp->verbose)
+ fprintf(stderr, "Value size %d\n", upto);
+ return 0;
+}
+
+static int store_key_value(void *blob, const char *node_name,
+ const char *property, const char *buf, int len)
+{
+ int node;
+ int err;
+
+ node = fdt_path_offset(blob, node_name);
+ if (node < 0) {
+ report_error(node_name, -1, node);
+ return -1;
+ }
+
+ err = fdt_setprop(blob, node, property, buf, len);
+ if (err) {
+ report_error(property, -1, err);
+ return -1;
+ }
+ return 0;
+}
+
+/**
+ * Create paths as needed for all components of a path
+ *
+ * Any components of the path that do not exist are created. Errors are
+ * reported.
+ *
+ * @param blob FDT blob to write into
+ * @param in_path Path to process
+ * @return 0 if ok, -1 on error
+ */
+static int create_paths(void *blob, const char *in_path)
+{
+ const char *path = in_path;
+ const char *sep;
+ int node, offset = 0;
+
+ /* skip leading '/' */
+ while (*path == '/')
+ path++;
+
+ for (sep = path; *sep; path = sep + 1, offset = node) {
+ /* equivalent to strchrnul(), but it requires _GNU_SOURCE */
+ sep = strchr(path, '/');
+ if (!sep)
+ sep = path + strlen(path);
+
+ node = fdt_subnode_offset_namelen(blob, offset, path,
+ sep - path);
+ if (node == -FDT_ERR_NOTFOUND) {
+ node = fdt_add_subnode_namelen(blob, offset, path,
+ sep - path);
+ }
+ if (node < 0) {
+ report_error(path, sep - path, node);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Create a new node in the fdt.
+ *
+ * This will overwrite the node_name string. Any error is reported.
+ *
+ * TODO: Perhaps create fdt_path_offset_namelen() so we don't need to do this.
+ *
+ * @param blob FDT blob to write into
+ * @param node_name Name of node to create
+ * @return new node offset if found, or -1 on failure
+ */
+static int create_node(void *blob, const char *node_name)
+{
+ int node = 0;
+ char *p;
+
+ p = strrchr(node_name, '/');
+ if (!p) {
+ report_error(node_name, -1, -FDT_ERR_BADPATH);
+ return -1;
+ }
+ *p = '\0';
+
+ if (p > node_name) {
+ node = fdt_path_offset(blob, node_name);
+ if (node < 0) {
+ report_error(node_name, -1, node);
+ return -1;
+ }
+ }
+
+ node = fdt_add_subnode(blob, node, p + 1);
+ if (node < 0) {
+ report_error(p + 1, -1, node);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int do_fdtput(struct display_info *disp, const char *filename,
+ char **arg, int arg_count)
+{
+ char *value;
+ char *blob;
+ int len, ret = 0;
+
+ blob = utilfdt_read(filename);
+ if (!blob)
+ return -1;
+
+ switch (disp->oper) {
+ case OPER_WRITE_PROP:
+ /*
+ * Convert the arguments into a single binary value, then
+ * store them into the property.
+ */
+ assert(arg_count >= 2);
+ if (disp->auto_path && create_paths(blob, *arg))
+ return -1;
+ if (encode_value(disp, arg + 2, arg_count - 2, &value, &len) ||
+ store_key_value(blob, *arg, arg[1], value, len))
+ ret = -1;
+ break;
+ case OPER_CREATE_NODE:
+ for (; ret >= 0 && arg_count--; arg++) {
+ if (disp->auto_path)
+ ret = create_paths(blob, *arg);
+ else
+ ret = create_node(blob, *arg);
+ }
+ break;
+ }
+ if (ret >= 0)
+ ret = utilfdt_write(filename, blob);
+
+ free(blob);
+ return ret;
+}
+
+static const char *usage_msg =
+ "fdtput - write a property value to a device tree\n"
+ "\n"
+ "The command line arguments are joined together into a single value.\n"
+ "\n"
+ "Usage:\n"
+ " fdtput <options> <dt file> <node> <property> [<value>...]\n"
+ " fdtput -c <options> <dt file> [<node>...]\n"
+ "Options:\n"
+ "\t-c\t\tCreate nodes if they don't already exist\n"
+ "\t-p\t\tAutomatically create nodes as needed for the node path\n"
+ "\t-t <type>\tType of data\n"
+ "\t-v\t\tVerbose: display each value decoded from command line\n"
+ "\t-h\t\tPrint this help\n\n"
+ USAGE_TYPE_MSG;
+
+static void usage(const char *msg)
+{
+ if (msg)
+ fprintf(stderr, "Error: %s\n\n", msg);
+
+ fprintf(stderr, "%s", usage_msg);
+ exit(2);
+}
+
+int main(int argc, char *argv[])
+{
+ struct display_info disp;
+ char *filename = NULL;
+
+ memset(&disp, '\0', sizeof(disp));
+ disp.size = -1;
+ disp.oper = OPER_WRITE_PROP;
+ for (;;) {
+ int c = getopt(argc, argv, "chpt:v");
+ if (c == -1)
+ break;
+
+ /*
+ * TODO: add options to:
+ * - delete property
+ * - delete node (optionally recursively)
+ * - rename node
+ * - pack fdt before writing
+ * - set amount of free space when writing
+ * - expand fdt if value doesn't fit
+ */
+ switch (c) {
+ case 'c':
+ disp.oper = OPER_CREATE_NODE;
+ break;
+ case 'h':
+ case '?':
+ usage(NULL);
+ case 'p':
+ disp.auto_path = 1;
+ break;
+ case 't':
+ if (utilfdt_decode_type(optarg, &disp.type,
+ &disp.size))
+ usage("Invalid type string");
+ break;
+
+ case 'v':
+ disp.verbose = 1;
+ break;
+ }
+ }
+
+ if (optind < argc)
+ filename = argv[optind++];
+ if (!filename)
+ usage("Missing filename");
+
+ argv += optind;
+ argc -= optind;
+
+ if (disp.oper == OPER_WRITE_PROP) {
+ if (argc < 1)
+ usage("Missing node");
+ if (argc < 2)
+ usage("Missing property");
+ }
+
+ if (do_fdtput(&disp, filename, argv, argc))
+ return 1;
+ return 0;
+}
diff --git a/scripts/dtc/flattree.c b/scripts/dtc/flattree.c
index 28d0b23..665dad7 100644
--- a/scripts/dtc/flattree.c
+++ b/scripts/dtc/flattree.c
@@ -263,6 +263,9 @@
struct node *child;
int seen_name_prop = 0;
+ if (tree->deleted)
+ return;
+
emit->beginnode(etarget, tree->labels);
if (vi->flags & FTF_FULLPATH)
diff --git a/scripts/dtc/libfdt/Makefile.libfdt b/scripts/dtc/libfdt/Makefile.libfdt
index 6c42acf..91126c0 100644
--- a/scripts/dtc/libfdt/Makefile.libfdt
+++ b/scripts/dtc/libfdt/Makefile.libfdt
@@ -3,6 +3,8 @@
# This is not a complete Makefile of itself. Instead, it is designed to
# be easily embeddable into other systems of Makefiles.
#
-LIBFDT_INCLUDES = fdt.h libfdt.h
-LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
+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
LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)
diff --git a/scripts/dtc/libfdt/fdt.c b/scripts/dtc/libfdt/fdt.c
index 2acaec5..e56833a 100644
--- a/scripts/dtc/libfdt/fdt.c
+++ b/scripts/dtc/libfdt/fdt.c
@@ -74,7 +74,7 @@
return 0;
}
-const void *fdt_offset_ptr(const void *fdt, int offset, int len)
+const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
{
const char *p;
@@ -90,42 +90,53 @@
return p;
}
-uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset)
+uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
{
const uint32_t *tagp, *lenp;
uint32_t tag;
+ int offset = startoffset;
const char *p;
- if (offset % FDT_TAGSIZE)
- return -1;
-
+ *nextoffset = -FDT_ERR_TRUNCATED;
tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
- if (! tagp)
+ if (!tagp)
return FDT_END; /* premature end */
tag = fdt32_to_cpu(*tagp);
offset += FDT_TAGSIZE;
+ *nextoffset = -FDT_ERR_BADSTRUCTURE;
switch (tag) {
case FDT_BEGIN_NODE:
/* skip name */
do {
p = fdt_offset_ptr(fdt, offset++, 1);
} while (p && (*p != '\0'));
- if (! p)
- return FDT_END;
+ if (!p)
+ return FDT_END; /* premature end */
break;
+
case FDT_PROP:
lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
- if (! lenp)
- return FDT_END;
- /* skip name offset, length and value */
- offset += 2*FDT_TAGSIZE + fdt32_to_cpu(*lenp);
+ if (!lenp)
+ return FDT_END; /* premature end */
+ /* skip-name offset, length and value */
+ offset += sizeof(struct fdt_property) - FDT_TAGSIZE
+ + fdt32_to_cpu(*lenp);
break;
+
+ case FDT_END:
+ case FDT_END_NODE:
+ case FDT_NOP:
+ break;
+
+ default:
+ return FDT_END;
}
- if (nextoffset)
- *nextoffset = FDT_TAGALIGN(offset);
+ if (!fdt_offset_ptr(fdt, startoffset, offset - startoffset))
+ return FDT_END; /* premature end */
+ *nextoffset = FDT_TAGALIGN(offset);
return tag;
}
@@ -138,6 +149,15 @@
return offset;
}
+int _fdt_check_prop_offset(const void *fdt, int offset)
+{
+ if ((offset < 0) || (offset % FDT_TAGSIZE)
+ || (fdt_next_tag(fdt, offset, &offset) != FDT_PROP))
+ return -FDT_ERR_BADOFFSET;
+
+ return offset;
+}
+
int fdt_next_node(const void *fdt, int offset, int *depth)
{
int nextoffset = 0;
@@ -162,15 +182,16 @@
break;
case FDT_END_NODE:
- if (depth)
- (*depth)--;
+ if (depth && ((--(*depth)) < 0))
+ return nextoffset;
break;
case FDT_END:
- return -FDT_ERR_NOTFOUND;
-
- default:
- return -FDT_ERR_BADSTRUCTURE;
+ if ((nextoffset >= 0)
+ || ((nextoffset == -FDT_ERR_TRUNCATED) && !depth))
+ return -FDT_ERR_NOTFOUND;
+ else
+ return nextoffset;
}
} while (tag != FDT_BEGIN_NODE);
diff --git a/scripts/dtc/libfdt/fdt_empty_tree.c b/scripts/dtc/libfdt/fdt_empty_tree.c
new file mode 100644
index 0000000..f72d13b
--- /dev/null
+++ b/scripts/dtc/libfdt/fdt_empty_tree.c
@@ -0,0 +1,84 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2012 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ * a) This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ * b) Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+int fdt_create_empty_tree(void *buf, int bufsize)
+{
+ int err;
+
+ err = fdt_create(buf, bufsize);
+ if (err)
+ return err;
+
+ err = fdt_finish_reservemap(buf);
+ if (err)
+ return err;
+
+ err = fdt_begin_node(buf, "");
+ if (err)
+ return err;
+
+ err = fdt_end_node(buf);
+ if (err)
+ return err;
+
+ err = fdt_finish(buf);
+ if (err)
+ return err;
+
+ return fdt_open_into(buf, buf, bufsize);
+}
+
diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c
index 22e6929..02b6d68 100644
--- a/scripts/dtc/libfdt/fdt_ro.c
+++ b/scripts/dtc/libfdt/fdt_ro.c
@@ -80,6 +80,14 @@
return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
}
+static int _fdt_string_eq(const void *fdt, int stroffset,
+ const char *s, int len)
+{
+ const char *p = fdt_string(fdt, stroffset);
+
+ return (strlen(p) == len) && (memcmp(p, s, len) == 0);
+}
+
int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
{
FDT_CHECK_HEADER(fdt);
@@ -97,6 +105,30 @@
return i;
}
+static int _nextprop(const void *fdt, int offset)
+{
+ uint32_t tag;
+ int nextoffset;
+
+ do {
+ tag = fdt_next_tag(fdt, offset, &nextoffset);
+
+ switch (tag) {
+ case FDT_END:
+ if (nextoffset >= 0)
+ return -FDT_ERR_BADSTRUCTURE;
+ else
+ return nextoffset;
+
+ case FDT_PROP:
+ return offset;
+ }
+ offset = nextoffset;
+ } while (tag == FDT_NOP);
+
+ return -FDT_ERR_NOTFOUND;
+}
+
int fdt_subnode_offset_namelen(const void *fdt, int offset,
const char *name, int namelen)
{
@@ -104,20 +136,16 @@
FDT_CHECK_HEADER(fdt);
- for (depth = 0, offset = fdt_next_node(fdt, offset, &depth);
- (offset >= 0) && (depth > 0);
- offset = fdt_next_node(fdt, offset, &depth)) {
- if (depth < 0)
- return -FDT_ERR_NOTFOUND;
- else if ((depth == 1)
- && _fdt_nodename_eq(fdt, offset, name, namelen))
+ for (depth = 0;
+ (offset >= 0) && (depth >= 0);
+ offset = fdt_next_node(fdt, offset, &depth))
+ if ((depth == 1)
+ && _fdt_nodename_eq(fdt, offset, name, namelen))
return offset;
- }
- if (offset < 0)
- return offset; /* error */
- else
+ if (depth < 0)
return -FDT_ERR_NOTFOUND;
+ return offset; /* error */
}
int fdt_subnode_offset(const void *fdt, int parentoffset,
@@ -134,8 +162,20 @@
FDT_CHECK_HEADER(fdt);
- if (*path != '/')
- return -FDT_ERR_BADPATH;
+ /* see if we have an alias */
+ if (*path != '/') {
+ const char *q = strchr(path, '/');
+
+ if (!q)
+ q = end;
+
+ p = fdt_get_alias_namelen(fdt, p, q - p);
+ if (!p)
+ return -FDT_ERR_BADPATH;
+ offset = fdt_path_offset(fdt, p);
+
+ p = q;
+ }
while (*p) {
const char *q;
@@ -178,93 +218,142 @@
return NULL;
}
+int fdt_first_property_offset(const void *fdt, int nodeoffset)
+{
+ int offset;
+
+ if ((offset = _fdt_check_node_offset(fdt, nodeoffset)) < 0)
+ return offset;
+
+ return _nextprop(fdt, offset);
+}
+
+int fdt_next_property_offset(const void *fdt, int offset)
+{
+ if ((offset = _fdt_check_prop_offset(fdt, offset)) < 0)
+ return offset;
+
+ return _nextprop(fdt, offset);
+}
+
+const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
+ int offset,
+ int *lenp)
+{
+ int err;
+ const struct fdt_property *prop;
+
+ if ((err = _fdt_check_prop_offset(fdt, offset)) < 0) {
+ if (lenp)
+ *lenp = err;
+ return NULL;
+ }
+
+ prop = _fdt_offset_ptr(fdt, offset);
+
+ if (lenp)
+ *lenp = fdt32_to_cpu(prop->len);
+
+ return prop;
+}
+
+const struct fdt_property *fdt_get_property_namelen(const void *fdt,
+ int offset,
+ const char *name,
+ int namelen, int *lenp)
+{
+ for (offset = fdt_first_property_offset(fdt, offset);
+ (offset >= 0);
+ (offset = fdt_next_property_offset(fdt, offset))) {
+ const struct fdt_property *prop;
+
+ if (!(prop = fdt_get_property_by_offset(fdt, offset, lenp))) {
+ offset = -FDT_ERR_INTERNAL;
+ break;
+ }
+ if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff),
+ name, namelen))
+ return prop;
+ }
+
+ if (lenp)
+ *lenp = offset;
+ return NULL;
+}
+
const struct fdt_property *fdt_get_property(const void *fdt,
int nodeoffset,
const char *name, int *lenp)
{
- uint32_t tag;
- const struct fdt_property *prop;
- int namestroff;
- int offset, nextoffset;
- int err;
-
- if (((err = fdt_check_header(fdt)) != 0)
- || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0))
- goto fail;
-
- nextoffset = err;
- do {
- offset = nextoffset;
-
- tag = fdt_next_tag(fdt, offset, &nextoffset);
- switch (tag) {
- case FDT_END:
- err = -FDT_ERR_TRUNCATED;
- goto fail;
-
- case FDT_BEGIN_NODE:
- case FDT_END_NODE:
- case FDT_NOP:
- break;
-
- case FDT_PROP:
- err = -FDT_ERR_BADSTRUCTURE;
- prop = fdt_offset_ptr(fdt, offset, sizeof(*prop));
- if (! prop)
- goto fail;
- namestroff = fdt32_to_cpu(prop->nameoff);
- if (strcmp(fdt_string(fdt, namestroff), name) == 0) {
- /* Found it! */
- int len = fdt32_to_cpu(prop->len);
- prop = fdt_offset_ptr(fdt, offset,
- sizeof(*prop)+len);
- if (! prop)
- goto fail;
-
- if (lenp)
- *lenp = len;
-
- return prop;
- }
- break;
-
- default:
- err = -FDT_ERR_BADSTRUCTURE;
- goto fail;
- }
- } while ((tag != FDT_BEGIN_NODE) && (tag != FDT_END_NODE));
-
- err = -FDT_ERR_NOTFOUND;
- fail:
- if (lenp)
- *lenp = err;
- return NULL;
+ return fdt_get_property_namelen(fdt, nodeoffset, name,
+ strlen(name), lenp);
}
-const void *fdt_getprop(const void *fdt, int nodeoffset,
- const char *name, int *lenp)
+const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
+ const char *name, int namelen, int *lenp)
{
const struct fdt_property *prop;
- prop = fdt_get_property(fdt, nodeoffset, name, lenp);
+ prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp);
if (! prop)
return NULL;
return prop->data;
}
+const void *fdt_getprop_by_offset(const void *fdt, int offset,
+ const char **namep, int *lenp)
+{
+ const struct fdt_property *prop;
+
+ prop = fdt_get_property_by_offset(fdt, offset, lenp);
+ if (!prop)
+ return NULL;
+ if (namep)
+ *namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
+ return prop->data;
+}
+
+const void *fdt_getprop(const void *fdt, int nodeoffset,
+ const char *name, int *lenp)
+{
+ return fdt_getprop_namelen(fdt, nodeoffset, name, strlen(name), lenp);
+}
+
uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
{
const uint32_t *php;
int len;
- php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len);
- if (!php || (len != sizeof(*php)))
- return 0;
+ /* FIXME: This is a bit sub-optimal, since we potentially scan
+ * over all the properties twice. */
+ php = fdt_getprop(fdt, nodeoffset, "phandle", &len);
+ if (!php || (len != sizeof(*php))) {
+ php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len);
+ if (!php || (len != sizeof(*php)))
+ return 0;
+ }
return fdt32_to_cpu(*php);
}
+const char *fdt_get_alias_namelen(const void *fdt,
+ const char *name, int namelen)
+{
+ int aliasoffset;
+
+ aliasoffset = fdt_path_offset(fdt, "/aliases");
+ if (aliasoffset < 0)
+ return NULL;
+
+ return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL);
+}
+
+const char *fdt_get_alias(const void *fdt, const char *name)
+{
+ return fdt_get_alias_namelen(fdt, name, strlen(name));
+}
+
int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
{
int pdepth = 0, p = 0;
@@ -279,9 +368,6 @@
for (offset = 0, depth = 0;
(offset >= 0) && (offset <= nodeoffset);
offset = fdt_next_node(fdt, offset, &depth)) {
- if (pdepth < depth)
- continue; /* overflowed buffer */
-
while (pdepth > depth) {
do {
p--;
@@ -289,14 +375,16 @@
pdepth--;
}
- name = fdt_get_name(fdt, offset, &namelen);
- if (!name)
- return namelen;
- if ((p + namelen + 1) <= buflen) {
- memcpy(buf + p, name, namelen);
- p += namelen;
- buf[p++] = '/';
- pdepth++;
+ if (pdepth >= depth) {
+ name = fdt_get_name(fdt, offset, &namelen);
+ if (!name)
+ return namelen;
+ if ((p + namelen + 1) <= buflen) {
+ memcpy(buf + p, name, namelen);
+ p += namelen;
+ buf[p++] = '/';
+ pdepth++;
+ }
}
if (offset == nodeoffset) {
@@ -306,7 +394,7 @@
if (p > 1) /* special case so that root path is "/", not "" */
p--;
buf[p] = '\0';
- return p;
+ return 0;
}
}
@@ -404,14 +492,31 @@
int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
{
+ int offset;
+
if ((phandle == 0) || (phandle == -1))
return -FDT_ERR_BADPHANDLE;
- phandle = cpu_to_fdt32(phandle);
- return fdt_node_offset_by_prop_value(fdt, -1, "linux,phandle",
- &phandle, sizeof(phandle));
+
+ FDT_CHECK_HEADER(fdt);
+
+ /* FIXME: The algorithm here is pretty horrible: we
+ * potentially scan each property of a node in
+ * fdt_get_phandle(), then if that didn't find what
+ * we want, we scan over them again making our way to the next
+ * node. Still it's the easiest to implement approach;
+ * performance can come later. */
+ for (offset = fdt_next_node(fdt, -1, NULL);
+ offset >= 0;
+ offset = fdt_next_node(fdt, offset, NULL)) {
+ if (fdt_get_phandle(fdt, offset) == phandle)
+ return offset;
+ }
+
+ return offset; /* error from fdt_next_node() */
}
-static int _stringlist_contains(const char *strlist, int listlen, const char *str)
+static int _fdt_stringlist_contains(const char *strlist, int listlen,
+ const char *str)
{
int len = strlen(str);
const char *p;
@@ -437,7 +542,7 @@
prop = fdt_getprop(fdt, nodeoffset, "compatible", &len);
if (!prop)
return len;
- if (_stringlist_contains(prop, len, compatible))
+ if (_fdt_stringlist_contains(prop, len, compatible))
return 0;
else
return 1;
diff --git a/scripts/dtc/libfdt/fdt_rw.c b/scripts/dtc/libfdt/fdt_rw.c
index 8e7ec4c..24437df 100644
--- a/scripts/dtc/libfdt/fdt_rw.c
+++ b/scripts/dtc/libfdt/fdt_rw.c
@@ -289,6 +289,33 @@
return 0;
}
+int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
+ const void *val, int len)
+{
+ struct fdt_property *prop;
+ int err, oldlen, newlen;
+
+ FDT_RW_CHECK_HEADER(fdt);
+
+ prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
+ if (prop) {
+ newlen = len + oldlen;
+ err = _fdt_splice_struct(fdt, prop->data,
+ FDT_TAGALIGN(oldlen),
+ FDT_TAGALIGN(newlen));
+ if (err)
+ return err;
+ prop->len = cpu_to_fdt32(newlen);
+ memcpy(prop->data + oldlen, val, len);
+ } else {
+ err = _fdt_add_property(fdt, nodeoffset, name, len, &prop);
+ if (err)
+ return err;
+ memcpy(prop->data, val, len);
+ }
+ return 0;
+}
+
int fdt_delprop(void *fdt, int nodeoffset, const char *name)
{
struct fdt_property *prop;
@@ -406,6 +433,8 @@
struct_size = 0;
while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END)
;
+ if (struct_size < 0)
+ return struct_size;
}
if (!_fdt_blocks_misordered(fdt, mem_rsv_size, struct_size)) {
diff --git a/scripts/dtc/libfdt/fdt_sw.c b/scripts/dtc/libfdt/fdt_sw.c
index 698329e..55ebebf 100644
--- a/scripts/dtc/libfdt/fdt_sw.c
+++ b/scripts/dtc/libfdt/fdt_sw.c
@@ -70,7 +70,7 @@
return err; \
}
-static void *_fdt_grab_space(void *fdt, int len)
+static void *_fdt_grab_space(void *fdt, size_t len)
{
int offset = fdt_size_dt_struct(fdt);
int spaceleft;
@@ -82,7 +82,7 @@
return NULL;
fdt_set_size_dt_struct(fdt, offset + len);
- return fdt_offset_ptr_w(fdt, offset, len);
+ return _fdt_offset_ptr_w(fdt, offset);
}
int fdt_create(void *buf, int bufsize)
@@ -237,18 +237,17 @@
while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) {
if (tag == FDT_PROP) {
struct fdt_property *prop =
- fdt_offset_ptr_w(fdt, offset, sizeof(*prop));
+ _fdt_offset_ptr_w(fdt, offset);
int nameoff;
- if (! prop)
- return -FDT_ERR_BADSTRUCTURE;
-
nameoff = fdt32_to_cpu(prop->nameoff);
nameoff += fdt_size_dt_strings(fdt);
prop->nameoff = cpu_to_fdt32(nameoff);
}
offset = nextoffset;
}
+ if (nextoffset < 0)
+ return nextoffset;
/* Finally, adjust the header */
fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
diff --git a/scripts/dtc/libfdt/fdt_wip.c b/scripts/dtc/libfdt/fdt_wip.c
index a4652c6..6025fa1 100644
--- a/scripts/dtc/libfdt/fdt_wip.c
+++ b/scripts/dtc/libfdt/fdt_wip.c
@@ -94,41 +94,14 @@
return 0;
}
-int _fdt_node_end_offset(void *fdt, int nodeoffset)
+int _fdt_node_end_offset(void *fdt, int offset)
{
- int level = 0;
- uint32_t tag;
- int offset, nextoffset;
+ int depth = 0;
- tag = fdt_next_tag(fdt, nodeoffset, &nextoffset);
- if (tag != FDT_BEGIN_NODE)
- return -FDT_ERR_BADOFFSET;
- do {
- offset = nextoffset;
- tag = fdt_next_tag(fdt, offset, &nextoffset);
+ while ((offset >= 0) && (depth >= 0))
+ offset = fdt_next_node(fdt, offset, &depth);
- switch (tag) {
- case FDT_END:
- return offset;
-
- case FDT_BEGIN_NODE:
- level++;
- break;
-
- case FDT_END_NODE:
- level--;
- break;
-
- case FDT_PROP:
- case FDT_NOP:
- break;
-
- default:
- return -FDT_ERR_BADSTRUCTURE;
- }
- } while (level >= 0);
-
- return nextoffset;
+ return offset;
}
int fdt_nop_node(void *fdt, int nodeoffset)
diff --git a/scripts/dtc/libfdt/libfdt.h b/scripts/dtc/libfdt/libfdt.h
index ff6246f..73f4975 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: Attempted to create a node or property which
+ /* FDT_ERR_EXISTS: Attemped to create a node or property which
* already exists */
#define FDT_ERR_NOSPACE 3
/* FDT_ERR_NOSPACE: Operation needed to expand the device
@@ -122,7 +122,7 @@
/* Low-level functions (you probably don't need these) */
/**********************************************************************/
-const void *fdt_offset_ptr(const void *fdt, int offset, int checklen);
+const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen);
static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen)
{
return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen);
@@ -156,7 +156,7 @@
#define __fdt_set_hdr(name) \
static inline void fdt_set_##name(void *fdt, uint32_t val) \
{ \
- struct fdt_header *fdth = fdt; \
+ struct fdt_header *fdth = (struct fdt_header*)fdt; \
fdth->name = cpu_to_fdt32(val); \
}
__fdt_set_hdr(magic);
@@ -343,6 +343,91 @@
const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp);
/**
+ * fdt_first_property_offset - find the offset of a node's first property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: structure block offset of a node
+ *
+ * fdt_first_property_offset() finds the first property of the node at
+ * the given structure block offset.
+ *
+ * returns:
+ * structure block offset of the property (>=0), on success
+ * -FDT_ERR_NOTFOUND, if the requested node has no properties
+ * -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings.
+ */
+int fdt_first_property_offset(const void *fdt, int nodeoffset);
+
+/**
+ * fdt_next_property_offset - step through a node's properties
+ * @fdt: pointer to the device tree blob
+ * @offset: structure block offset of a property
+ *
+ * fdt_next_property_offset() finds the property immediately after the
+ * one at the given structure block offset. This will be a property
+ * of the same node as the given property.
+ *
+ * returns:
+ * structure block offset of the next property (>=0), on success
+ * -FDT_ERR_NOTFOUND, if the given property is the last in its node
+ * -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_PROP tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings.
+ */
+int fdt_next_property_offset(const void *fdt, int offset);
+
+/**
+ * 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
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * fdt_get_property_by_offset() retrieves a pointer to the
+ * fdt_property structure within the device tree blob at the given
+ * offset. If lenp is non-NULL, the length of the property value is
+ * also returned, in the integer pointed to by lenp.
+ *
+ * returns:
+ * pointer to the structure representing the property
+ * if lenp is non-NULL, *lenp contains the length of the property
+ * value (>=0)
+ * NULL, on error
+ * if lenp is non-NULL, *lenp contains an error code (<0):
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
+ int offset,
+ int *lenp);
+
+/**
+ * fdt_get_property_namelen - find a property based on substring
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to find
+ * @name: name of the property to find
+ * @namelen: number of characters of name to consider
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * Identical to fdt_get_property_namelen(), but only examine the first
+ * namelen characters of name for matching the property name.
+ */
+const struct fdt_property *fdt_get_property_namelen(const void *fdt,
+ int nodeoffset,
+ const char *name,
+ int namelen, int *lenp);
+
+/**
* fdt_get_property - find a given property in a given node
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose property to find
@@ -380,6 +465,54 @@
}
/**
+ * fdt_getprop_by_offset - retrieve the value of a property at a given offset
+ * @fdt: pointer to the device tree blob
+ * @ffset: offset of the property to read
+ * @namep: pointer to a string variable (will be overwritten) or NULL
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * fdt_getprop_by_offset() retrieves a pointer to the value of the
+ * property at structure block offset 'offset' (this will be a pointer
+ * to within the device blob itself, not a copy of the value). If
+ * lenp is non-NULL, the length of the property value is also
+ * returned, in the integer pointed to by lenp. If namep is non-NULL,
+ * the property's namne will also be returned in the char * pointed to
+ * by namep (this will be a pointer to within the device tree's string
+ * block, not a new copy of the name).
+ *
+ * returns:
+ * pointer to the property's value
+ * if lenp is non-NULL, *lenp contains the length of the property
+ * value (>=0)
+ * if namep is non-NULL *namep contiains a pointer to the property
+ * name.
+ * NULL, on error
+ * if lenp is non-NULL, *lenp contains an error code (<0):
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+const void *fdt_getprop_by_offset(const void *fdt, int offset,
+ const char **namep, int *lenp);
+
+/**
+ * fdt_getprop_namelen - get property value based on substring
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to find
+ * @name: name of the property to find
+ * @namelen: number of characters of name to consider
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * Identical to fdt_getprop(), but only examine the first namelen
+ * characters of name for matching the property name.
+ */
+const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
+ const char *name, int namelen, int *lenp);
+
+/**
* fdt_getprop - retrieve the value of a given property
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose property to find
@@ -429,6 +562,32 @@
uint32_t fdt_get_phandle(const void *fdt, int nodeoffset);
/**
+ * fdt_get_alias_namelen - get alias based on substring
+ * @fdt: pointer to the device tree blob
+ * @name: name of the alias th look up
+ * @namelen: number of characters of name to consider
+ *
+ * Identical to fdt_get_alias(), but only examine the first namelen
+ * characters of name for matching the alias name.
+ */
+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: pointer to the device tree blob
+ * @name: name of the alias th look up
+ *
+ * fdt_get_alias() retrieves the value of a given alias. That is, the
+ * value of the property named 'name' in the node /aliases.
+ *
+ * returns:
+ * a pointer to the expansion of the alias named 'name', of it exists
+ * NULL, if the given alias or the /aliases node does not exist
+ */
+const char *fdt_get_alias(const void *fdt, const char *name);
+
+/**
* fdt_get_path - determine the full path of a node
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose path to find
@@ -693,17 +852,17 @@
const void *val, int len);
/**
- * fdt_setprop_inplace_cell - change the value of a single-cell property
+ * fdt_setprop_inplace_u32 - change the value of a 32-bit integer property
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose property to change
* @name: name of the property to change
- * @val: cell (32-bit integer) value to replace the property with
+ * @val: 32-bit integer value to replace the property with
*
- * fdt_setprop_inplace_cell() replaces the value of a given property
- * with the 32-bit integer cell value in val, converting val to
- * big-endian if necessary. This function cannot change the size of a
- * property, and so will only work if the property already exists and
- * has length 4.
+ * fdt_setprop_inplace_u32() replaces the value of a given property
+ * with the 32-bit integer value in val, converting val to big-endian
+ * if necessary. This function cannot change the size of a property,
+ * and so will only work if the property already exists and has length
+ * 4.
*
* This function will alter only the bytes in the blob which contain
* the given property value, and will not alter or move any other part
@@ -712,7 +871,7 @@
* returns:
* 0, on success
* -FDT_ERR_NOSPACE, if the property's length is not equal to 4
- * -FDT_ERR_NOTFOUND, node does not have the named property
+ * -FDT_ERR_NOTFOUND, node does not have the named property
* -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
@@ -720,14 +879,60 @@
* -FDT_ERR_BADSTRUCTURE,
* -FDT_ERR_TRUNCATED, standard meanings
*/
-static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset,
- const char *name, uint32_t val)
+static inline int fdt_setprop_inplace_u32(void *fdt, int nodeoffset,
+ const char *name, uint32_t val)
{
val = cpu_to_fdt32(val);
return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val));
}
/**
+ * fdt_setprop_inplace_u64 - change the value of a 64-bit integer property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 64-bit integer value to replace the property with
+ *
+ * fdt_setprop_inplace_u64() replaces the value of a given property
+ * with the 64-bit integer value in val, converting val to big-endian
+ * if necessary. This function cannot change the size of a property,
+ * and so will only work if the property already exists and has length
+ * 8.
+ *
+ * This function will alter only the bytes in the blob which contain
+ * the given property value, and will not alter or move any other part
+ * of the tree.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, if the property's length is not equal to 8
+ * -FDT_ERR_NOTFOUND, node does not have the named property
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+static inline int fdt_setprop_inplace_u64(void *fdt, int nodeoffset,
+ const char *name, uint64_t val)
+{
+ val = cpu_to_fdt64(val);
+ return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val));
+}
+
+/**
+ * fdt_setprop_inplace_cell - change the value of a single-cell property
+ *
+ * This is an alternative name for fdt_setprop_inplace_u32()
+ */
+static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset,
+ const char *name, uint32_t val)
+{
+ return fdt_setprop_inplace_u32(fdt, nodeoffset, name, val);
+}
+
+/**
* fdt_nop_property - replace a property with nop tags
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose property to nop
@@ -786,11 +991,20 @@
int fdt_finish_reservemap(void *fdt);
int fdt_begin_node(void *fdt, const char *name);
int fdt_property(void *fdt, const char *name, const void *val, int len);
-static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
+static inline int fdt_property_u32(void *fdt, const char *name, uint32_t val)
{
val = cpu_to_fdt32(val);
return fdt_property(fdt, name, &val, sizeof(val));
}
+static inline int fdt_property_u64(void *fdt, const char *name, uint64_t val)
+{
+ val = cpu_to_fdt64(val);
+ return fdt_property(fdt, name, &val, sizeof(val));
+}
+static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
+{
+ return fdt_property_u32(fdt, name, val);
+}
#define fdt_property_string(fdt, name, str) \
fdt_property(fdt, name, str, strlen(str)+1)
int fdt_end_node(void *fdt);
@@ -800,6 +1014,7 @@
/* Read-write functions */
/**********************************************************************/
+int fdt_create_empty_tree(void *buf, int bufsize);
int fdt_open_into(const void *fdt, void *buf, int bufsize);
int fdt_pack(void *fdt);
@@ -909,14 +1124,14 @@
const void *val, int len);
/**
- * fdt_setprop_cell - set a property to a single cell value
+ * fdt_setprop_u32 - set a property to a 32-bit integer
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose property to change
* @name: name of the property to change
* @val: 32-bit integer value for the property (native endian)
*
- * fdt_setprop_cell() sets the value of the named property in the
- * given node to the given cell value (converting to big-endian if
+ * fdt_setprop_u32() sets the value of the named property in the given
+ * node to the given 32-bit integer value (converting to big-endian if
* necessary), or creates a new property with that value if it does
* not already exist.
*
@@ -936,14 +1151,60 @@
* -FDT_ERR_BADLAYOUT,
* -FDT_ERR_TRUNCATED, standard meanings
*/
-static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
- uint32_t val)
+static inline int fdt_setprop_u32(void *fdt, int nodeoffset, const char *name,
+ uint32_t val)
{
val = cpu_to_fdt32(val);
return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val));
}
/**
+ * fdt_setprop_u64 - set a property to a 64-bit integer
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 64-bit integer value for the property (native endian)
+ *
+ * fdt_setprop_u64() sets the value of the named property in the given
+ * node to the given 64-bit integer value (converting to big-endian if
+ * necessary), or creates a new property with that value 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
+ */
+static inline int fdt_setprop_u64(void *fdt, int nodeoffset, const char *name,
+ uint64_t val)
+{
+ val = cpu_to_fdt64(val);
+ return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val));
+}
+
+/**
+ * fdt_setprop_cell - set a property to a single cell value
+ *
+ * This is an alternative name for fdt_setprop_u32()
+ */
+static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
+ uint32_t val)
+{
+ return fdt_setprop_u32(fdt, nodeoffset, name, val);
+}
+
+/**
* fdt_setprop_string - set a property to a string value
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose property to change
@@ -975,6 +1236,147 @@
fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
/**
+ * fdt_appendprop - append to or create a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to append to
+ * @val: pointer to data to append to the property value
+ * @len: length of the data to append to the property value
+ *
+ * fdt_appendprop() appends the value to the named property in the
+ * given node, creating the property if it does not already exist.
+ *
+ * This function may insert data into the blob, and will therefore
+ * change the offsets of some existing nodes.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ * contain the new property value
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
+ const void *val, int len);
+
+/**
+ * fdt_appendprop_u32 - append a 32-bit integer value to a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 32-bit integer value to append to the property (native endian)
+ *
+ * fdt_appendprop_u32() appends the given 32-bit integer value
+ * (converting to big-endian if necessary) to the value of the named
+ * property in the given node, or creates a new property with that
+ * value if it does not already exist.
+ *
+ * This function may insert data into 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
+ */
+static inline int fdt_appendprop_u32(void *fdt, int nodeoffset,
+ const char *name, uint32_t val)
+{
+ val = cpu_to_fdt32(val);
+ return fdt_appendprop(fdt, nodeoffset, name, &val, sizeof(val));
+}
+
+/**
+ * fdt_appendprop_u64 - append a 64-bit integer value to a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 64-bit integer value to append to the property (native endian)
+ *
+ * fdt_appendprop_u64() appends the given 64-bit integer value
+ * (converting to big-endian if necessary) to the value of the named
+ * property in the given node, or creates a new property with that
+ * value if it does not already exist.
+ *
+ * This function may insert data into 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
+ */
+static inline int fdt_appendprop_u64(void *fdt, int nodeoffset,
+ const char *name, uint64_t val)
+{
+ val = cpu_to_fdt64(val);
+ return fdt_appendprop(fdt, nodeoffset, name, &val, sizeof(val));
+}
+
+/**
+ * fdt_appendprop_cell - append a single cell value to a property
+ *
+ * This is an alternative name for fdt_appendprop_u32()
+ */
+static inline int fdt_appendprop_cell(void *fdt, int nodeoffset,
+ const char *name, uint32_t val)
+{
+ return fdt_appendprop_u32(fdt, nodeoffset, name, val);
+}
+
+/**
+ * fdt_appendprop_string - append a string to a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @str: string value to append to the property
+ *
+ * fdt_appendprop_string() appends the given string to the value of
+ * the named property in the given node, or creates a new property
+ * with that value if it does not already exist.
+ *
+ * This function may insert data into 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_appendprop_string(fdt, nodeoffset, name, str) \
+ fdt_appendprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
+
+/**
* fdt_delprop - delete a property
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose property to nop
diff --git a/scripts/dtc/libfdt/libfdt_env.h b/scripts/dtc/libfdt/libfdt_env.h
index 449bf60..213d7fb 100644
--- a/scripts/dtc/libfdt/libfdt_env.h
+++ b/scripts/dtc/libfdt/libfdt_env.h
@@ -5,19 +5,25 @@
#include <stdint.h>
#include <string.h>
-#define _B(n) ((unsigned long long)((uint8_t *)&x)[n])
+#define EXTRACT_BYTE(n) ((unsigned long long)((uint8_t *)&x)[n])
+static inline uint16_t fdt16_to_cpu(uint16_t x)
+{
+ return (EXTRACT_BYTE(0) << 8) | EXTRACT_BYTE(1);
+}
+#define cpu_to_fdt16(x) fdt16_to_cpu(x)
+
static inline uint32_t fdt32_to_cpu(uint32_t x)
{
- return (_B(0) << 24) | (_B(1) << 16) | (_B(2) << 8) | _B(3);
+ return (EXTRACT_BYTE(0) << 24) | (EXTRACT_BYTE(1) << 16) | (EXTRACT_BYTE(2) << 8) | EXTRACT_BYTE(3);
}
#define cpu_to_fdt32(x) fdt32_to_cpu(x)
static inline uint64_t fdt64_to_cpu(uint64_t x)
{
- return (_B(0) << 56) | (_B(1) << 48) | (_B(2) << 40) | (_B(3) << 32)
- | (_B(4) << 24) | (_B(5) << 16) | (_B(6) << 8) | _B(7);
+ return (EXTRACT_BYTE(0) << 56) | (EXTRACT_BYTE(1) << 48) | (EXTRACT_BYTE(2) << 40) | (EXTRACT_BYTE(3) << 32)
+ | (EXTRACT_BYTE(4) << 24) | (EXTRACT_BYTE(5) << 16) | (EXTRACT_BYTE(6) << 8) | EXTRACT_BYTE(7);
}
#define cpu_to_fdt64(x) fdt64_to_cpu(x)
-#undef _B
+#undef EXTRACT_BYTE
#endif /* _LIBFDT_ENV_H */
diff --git a/scripts/dtc/libfdt/libfdt_internal.h b/scripts/dtc/libfdt/libfdt_internal.h
index 46eb93e..381133b 100644
--- a/scripts/dtc/libfdt/libfdt_internal.h
+++ b/scripts/dtc/libfdt/libfdt_internal.h
@@ -62,8 +62,8 @@
return err; \
}
-uint32_t _fdt_next_tag(const void *fdt, int startoffset, int *nextoffset);
int _fdt_check_node_offset(const void *fdt, int offset);
+int _fdt_check_prop_offset(const void *fdt, int offset);
const char *_fdt_find_string(const char *strtab, int tabsize, const char *s);
int _fdt_node_end_offset(void *fdt, int nodeoffset);
diff --git a/scripts/dtc/livetree.c b/scripts/dtc/livetree.c
index 26d0e1e..b61465f 100644
--- a/scripts/dtc/livetree.c
+++ b/scripts/dtc/livetree.c
@@ -29,16 +29,27 @@
struct label *new;
/* Make sure the label isn't already there */
- for_each_label(*labels, new)
- if (streq(new->label, label))
+ for_each_label_withdel(*labels, new)
+ if (streq(new->label, label)) {
+ new->deleted = 0;
return;
+ }
new = xmalloc(sizeof(*new));
+ memset(new, 0, sizeof(*new));
new->label = label;
new->next = *labels;
*labels = new;
}
+void delete_labels(struct label **labels)
+{
+ struct label *label;
+
+ for_each_label(*labels, label)
+ label->deleted = 1;
+}
+
struct property *build_property(char *name, struct data val)
{
struct property *new = xmalloc(sizeof(*new));
@@ -51,6 +62,18 @@
return new;
}
+struct property *build_property_delete(char *name)
+{
+ struct property *new = xmalloc(sizeof(*new));
+
+ memset(new, 0, sizeof(*new));
+
+ new->name = name;
+ new->deleted = 1;
+
+ return new;
+}
+
struct property *chain_property(struct property *first, struct property *list)
{
assert(first->next == NULL);
@@ -91,6 +114,17 @@
return new;
}
+struct node *build_node_delete(void)
+{
+ struct node *new = xmalloc(sizeof(*new));
+
+ memset(new, 0, sizeof(*new));
+
+ new->deleted = 1;
+
+ return new;
+}
+
struct node *name_node(struct node *node, char *name)
{
assert(node->name == NULL);
@@ -106,8 +140,10 @@
struct node *new_child, *old_child;
struct label *l;
+ old_node->deleted = 0;
+
/* Add new node labels to old node */
- for_each_label(new_node->labels, l)
+ for_each_label_withdel(new_node->labels, l)
add_label(&old_node->labels, l->label);
/* Move properties from the new node to the old node. If there
@@ -118,14 +154,21 @@
new_node->proplist = new_prop->next;
new_prop->next = NULL;
+ if (new_prop->deleted) {
+ delete_property_by_name(old_node, new_prop->name);
+ free(new_prop);
+ continue;
+ }
+
/* Look for a collision, set new value if there is */
- for_each_property(old_node, old_prop) {
+ for_each_property_withdel(old_node, old_prop) {
if (streq(old_prop->name, new_prop->name)) {
/* Add new labels to old property */
- for_each_label(new_prop->labels, l)
+ for_each_label_withdel(new_prop->labels, l)
add_label(&old_prop->labels, l->label);
old_prop->val = new_prop->val;
+ old_prop->deleted = 0;
free(new_prop);
new_prop = NULL;
break;
@@ -146,8 +189,14 @@
new_child->parent = NULL;
new_child->next_sibling = NULL;
+ if (new_child->deleted) {
+ delete_node_by_name(old_node, new_child->name);
+ free(new_child);
+ continue;
+ }
+
/* Search for a collision. Merge if there is */
- for_each_child(old_node, old_child) {
+ for_each_child_withdel(old_node, old_child) {
if (streq(old_child->name, new_child->name)) {
merge_nodes(old_child, new_child);
new_child = NULL;
@@ -155,7 +204,7 @@
}
}
- /* if no collision occurred, add child to the old node. */
+ /* if no collision occured, add child to the old node. */
if (new_child)
add_child(old_node, new_child);
}
@@ -188,6 +237,25 @@
*p = prop;
}
+void delete_property_by_name(struct node *node, char *name)
+{
+ struct property *prop = node->proplist;
+
+ while (prop) {
+ if (!strcmp(prop->name, name)) {
+ delete_property(prop);
+ return;
+ }
+ prop = prop->next;
+ }
+}
+
+void delete_property(struct property *prop)
+{
+ prop->deleted = 1;
+ delete_labels(&prop->labels);
+}
+
void add_child(struct node *parent, struct node *child)
{
struct node **p;
@@ -202,6 +270,32 @@
*p = child;
}
+void delete_node_by_name(struct node *parent, char *name)
+{
+ struct node *node = parent->children;
+
+ while (node) {
+ if (!strcmp(node->name, name)) {
+ delete_node(node);
+ return;
+ }
+ node = node->next_sibling;
+ }
+}
+
+void delete_node(struct node *node)
+{
+ struct property *prop;
+ struct node *child;
+
+ node->deleted = 1;
+ for_each_child(node, child)
+ delete_node(child);
+ for_each_property(node, prop)
+ delete_property(prop);
+ delete_labels(&node->labels);
+}
+
struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)
{
struct reserve_info *new = xmalloc(sizeof(*new));
@@ -353,8 +447,11 @@
const char *p;
struct node *child;
- if (!path || ! (*path))
+ if (!path || ! (*path)) {
+ if (tree->deleted)
+ return NULL;
return tree;
+ }
while (path[0] == '/')
path++;
@@ -397,8 +494,11 @@
assert((phandle != 0) && (phandle != -1));
- if (tree->phandle == phandle)
+ if (tree->phandle == phandle) {
+ if (tree->deleted)
+ return NULL;
return tree;
+ }
for_each_child(tree, child) {
node = get_node_by_phandle(child, phandle);
@@ -535,7 +635,7 @@
int n = 0, i = 0;
struct property *prop, **tbl;
- for_each_property(node, prop)
+ for_each_property_withdel(node, prop)
n++;
if (n == 0)
@@ -543,7 +643,7 @@
tbl = xmalloc(n * sizeof(*tbl));
- for_each_property(node, prop)
+ for_each_property_withdel(node, prop)
tbl[i++] = prop;
qsort(tbl, n, sizeof(*tbl), cmp_prop);
@@ -571,7 +671,7 @@
int n = 0, i = 0;
struct node *subnode, **tbl;
- for_each_child(node, subnode)
+ for_each_child_withdel(node, subnode)
n++;
if (n == 0)
@@ -579,7 +679,7 @@
tbl = xmalloc(n * sizeof(*tbl));
- for_each_child(node, subnode)
+ for_each_child_withdel(node, subnode)
tbl[i++] = subnode;
qsort(tbl, n, sizeof(*tbl), cmp_subnode);
@@ -598,7 +698,7 @@
sort_properties(node);
sort_subnodes(node);
- for_each_child(node, c)
+ for_each_child_withdel(node, c)
sort_node(c);
}
diff --git a/scripts/dtc/srcpos.c b/scripts/dtc/srcpos.c
index 36a38e9..246ab4b 100644
--- a/scripts/dtc/srcpos.c
+++ b/scripts/dtc/srcpos.c
@@ -24,6 +24,15 @@
#include "dtc.h"
#include "srcpos.h"
+/* A node in our list of directories to search for source/include files */
+struct search_path {
+ struct search_path *next; /* next node in list, NULL for end */
+ const char *dirname; /* name of directory to search */
+};
+
+/* This is the list of directories that we search for source files */
+static struct search_path *search_path_head, **search_path_tail;
+
static char *dirname(const char *path)
{
@@ -47,6 +56,64 @@
#define MAX_SRCFILE_DEPTH (100)
static int srcfile_depth; /* = 0 */
+
+/**
+ * Try to open a file in a given directory.
+ *
+ * If the filename is an absolute path, then dirname is ignored. If it is a
+ * relative path, then we look in that directory for the file.
+ *
+ * @param dirname Directory to look in, or NULL for none
+ * @param fname Filename to look for
+ * @param fp Set to NULL if file did not open
+ * @return allocated filename on success (caller must free), NULL on failure
+ */
+static char *try_open(const char *dirname, const char *fname, FILE **fp)
+{
+ char *fullname;
+
+ if (!dirname || fname[0] == '/')
+ fullname = xstrdup(fname);
+ else
+ fullname = join_path(dirname, fname);
+
+ *fp = fopen(fullname, "r");
+ if (!*fp) {
+ free(fullname);
+ fullname = NULL;
+ }
+
+ return fullname;
+}
+
+/**
+ * Open a file for read access
+ *
+ * If it is a relative filename, we search the full search path for it.
+ *
+ * @param fname Filename to open
+ * @param fp Returns pointer to opened FILE, or NULL on failure
+ * @return pointer to allocated filename, which caller must free
+ */
+static char *fopen_any_on_path(const char *fname, FILE **fp)
+{
+ const char *cur_dir = NULL;
+ struct search_path *node;
+ char *fullname;
+
+ /* Try current directory first */
+ assert(fp);
+ if (current_srcfile)
+ cur_dir = current_srcfile->dir;
+ fullname = try_open(cur_dir, fname, fp);
+
+ /* Failing that, try each search path in turn */
+ for (node = search_path_head; !*fp && node; node = node->next)
+ fullname = try_open(node->dirname, fname, fp);
+
+ return fullname;
+}
+
FILE *srcfile_relative_open(const char *fname, char **fullnamep)
{
FILE *f;
@@ -56,13 +123,7 @@
f = stdin;
fullname = xstrdup("<stdin>");
} else {
- if (!current_srcfile || !current_srcfile->dir
- || (fname[0] == '/'))
- fullname = xstrdup(fname);
- else
- fullname = join_path(current_srcfile->dir, fname);
-
- f = fopen(fullname, "r");
+ fullname = fopen_any_on_path(fname, &f);
if (!f)
die("Couldn't open \"%s\": %s\n", fname,
strerror(errno));
@@ -119,6 +180,23 @@
return current_srcfile ? 1 : 0;
}
+void srcfile_add_search_path(const char *dirname)
+{
+ struct search_path *node;
+
+ /* Create the node */
+ node = xmalloc(sizeof(*node));
+ node->next = NULL;
+ node->dirname = xstrdup(dirname);
+
+ /* Add to the end of our list */
+ if (search_path_tail)
+ *search_path_tail = node;
+ else
+ search_path_head = node;
+ search_path_tail = &node->next;
+}
+
/*
* The empty source position.
*/
@@ -250,3 +328,9 @@
va_end(va);
}
+
+void srcpos_set_line(char *f, int l)
+{
+ current_srcfile->name = f;
+ current_srcfile->lineno = l;
+}
diff --git a/scripts/dtc/srcpos.h b/scripts/dtc/srcpos.h
index ce980ca..93a2712 100644
--- a/scripts/dtc/srcpos.h
+++ b/scripts/dtc/srcpos.h
@@ -33,10 +33,39 @@
extern FILE *depfile; /* = NULL */
extern struct srcfile_state *current_srcfile; /* = NULL */
+/**
+ * Open a source file.
+ *
+ * If the source file is a relative pathname, then it is searched for in the
+ * current directory (the directory of the last source file read) and after
+ * that in the search path.
+ *
+ * We work through the search path in order from the first path specified to
+ * the last.
+ *
+ * If the file is not found, then this function does not return, but calls
+ * die().
+ *
+ * @param fname Filename to search
+ * @param fullnamep If non-NULL, it is set to the allocated filename of the
+ * file that was opened. The caller is then responsible
+ * for freeing the pointer.
+ * @return pointer to opened FILE
+ */
FILE *srcfile_relative_open(const char *fname, char **fullnamep);
+
void srcfile_push(const char *fname);
int srcfile_pop(void);
+/**
+ * Add a new directory to the search path for input files
+ *
+ * The new path is added at the end of the list.
+ *
+ * @param dirname Directory to add
+ */
+void srcfile_add_search_path(const char *dirname);
+
struct srcpos {
int first_line;
int first_column;
@@ -84,4 +113,6 @@
extern void srcpos_warn(struct srcpos *pos, char const *, ...)
__attribute__((format(printf, 2, 3)));
+extern void srcpos_set_line(char *f, int l);
+
#endif /* _SRCPOS_H_ */
diff --git a/scripts/dtc/treesource.c b/scripts/dtc/treesource.c
index c09aafa..33eeba5 100644
--- a/scripts/dtc/treesource.c
+++ b/scripts/dtc/treesource.c
@@ -23,6 +23,7 @@
extern FILE *yyin;
extern int yyparse(void);
+extern YYLTYPE yylloc;
struct boot_info *the_boot_info;
int treesource_error;
@@ -34,6 +35,7 @@
srcfile_push(fname);
yyin = current_srcfile->f;
+ yylloc.file = current_srcfile;
if (yyparse() != 0)
die("Unable to parse input tree\n");
diff --git a/scripts/dtc/util.c b/scripts/dtc/util.c
index d7ac27d..2422c34 100644
--- a/scripts/dtc/util.c
+++ b/scripts/dtc/util.c
@@ -1,6 +1,10 @@
/*
+ * Copyright 2011 The Chromium Authors, All Rights Reserved.
* Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
*
+ * util_is_printable_string contributed by
+ * Pantelis Antoniou <pantelis.antoniou AT gmail.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
@@ -17,11 +21,18 @@
* USA
*/
+#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "libfdt.h"
#include "util.h"
char *xstrdup(const char *s)
@@ -57,3 +68,264 @@
memcpy(str+lenp, name, lenn+1);
return str;
}
+
+int util_is_printable_string(const void *data, int len)
+{
+ const char *s = data;
+ const char *ss;
+
+ /* zero length is not */
+ if (len == 0)
+ return 0;
+
+ /* must terminate with zero */
+ if (s[len - 1] != '\0')
+ return 0;
+
+ ss = s;
+ while (*s && isprint(*s))
+ s++;
+
+ /* not zero, or not done yet */
+ if (*s != '\0' || (s + 1 - ss) < len)
+ return 0;
+
+ return 1;
+}
+
+/*
+ * Parse a octal encoded character starting at index i in string s. The
+ * resulting character will be returned and the index i will be updated to
+ * point at the character directly after the end of the encoding, this may be
+ * the '\0' terminator of the string.
+ */
+static char get_oct_char(const char *s, int *i)
+{
+ char x[4];
+ char *endx;
+ long val;
+
+ x[3] = '\0';
+ strncpy(x, s + *i, 3);
+
+ val = strtol(x, &endx, 8);
+
+ assert(endx > x);
+
+ (*i) += endx - x;
+ return val;
+}
+
+/*
+ * Parse a hexadecimal encoded character starting at index i in string s. The
+ * resulting character will be returned and the index i will be updated to
+ * point at the character directly after the end of the encoding, this may be
+ * the '\0' terminator of the string.
+ */
+static char get_hex_char(const char *s, int *i)
+{
+ char x[3];
+ char *endx;
+ long val;
+
+ x[2] = '\0';
+ strncpy(x, s + *i, 2);
+
+ val = strtol(x, &endx, 16);
+ if (!(endx > x))
+ die("\\x used with no following hex digits\n");
+
+ (*i) += endx - x;
+ return val;
+}
+
+char get_escape_char(const char *s, int *i)
+{
+ char c = s[*i];
+ int j = *i + 1;
+ char val;
+
+ assert(c);
+ switch (c) {
+ case 'a':
+ val = '\a';
+ break;
+ case 'b':
+ val = '\b';
+ break;
+ case 't':
+ val = '\t';
+ break;
+ case 'n':
+ val = '\n';
+ break;
+ case 'v':
+ val = '\v';
+ break;
+ case 'f':
+ val = '\f';
+ break;
+ case 'r':
+ val = '\r';
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ j--; /* need to re-read the first digit as
+ * part of the octal value */
+ val = get_oct_char(s, &j);
+ break;
+ case 'x':
+ val = get_hex_char(s, &j);
+ break;
+ default:
+ val = c;
+ }
+
+ (*i) = j;
+ return val;
+}
+
+int utilfdt_read_err(const char *filename, char **buffp)
+{
+ int fd = 0; /* assume stdin */
+ char *buf = NULL;
+ off_t bufsize = 1024, offset = 0;
+ int ret = 0;
+
+ *buffp = NULL;
+ if (strcmp(filename, "-") != 0) {
+ fd = open(filename, O_RDONLY);
+ if (fd < 0)
+ return errno;
+ }
+
+ /* Loop until we have read everything */
+ buf = malloc(bufsize);
+ do {
+ /* Expand the buffer to hold the next chunk */
+ if (offset == bufsize) {
+ bufsize *= 2;
+ buf = realloc(buf, bufsize);
+ if (!buf) {
+ ret = ENOMEM;
+ break;
+ }
+ }
+
+ ret = read(fd, &buf[offset], bufsize - offset);
+ if (ret < 0) {
+ ret = errno;
+ break;
+ }
+ offset += ret;
+ } while (ret != 0);
+
+ /* Clean up, including closing stdin; return errno on error */
+ close(fd);
+ if (ret)
+ free(buf);
+ else
+ *buffp = buf;
+ return ret;
+}
+
+char *utilfdt_read(const char *filename)
+{
+ char *buff;
+ int ret = utilfdt_read_err(filename, &buff);
+
+ if (ret) {
+ fprintf(stderr, "Couldn't open blob from '%s': %s\n", filename,
+ strerror(ret));
+ return NULL;
+ }
+ /* Successful read */
+ return buff;
+}
+
+int utilfdt_write_err(const char *filename, const void *blob)
+{
+ int fd = 1; /* assume stdout */
+ int totalsize;
+ int offset;
+ int ret = 0;
+ const char *ptr = blob;
+
+ if (strcmp(filename, "-") != 0) {
+ fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+ if (fd < 0)
+ return errno;
+ }
+
+ totalsize = fdt_totalsize(blob);
+ offset = 0;
+
+ while (offset < totalsize) {
+ ret = write(fd, ptr + offset, totalsize - offset);
+ if (ret < 0) {
+ ret = -errno;
+ break;
+ }
+ offset += ret;
+ }
+ /* Close the file/stdin; return errno on error */
+ if (fd != 1)
+ close(fd);
+ return ret < 0 ? -ret : 0;
+}
+
+
+int utilfdt_write(const char *filename, const void *blob)
+{
+ int ret = utilfdt_write_err(filename, blob);
+
+ if (ret) {
+ fprintf(stderr, "Couldn't write blob to '%s': %s\n", filename,
+ strerror(ret));
+ }
+ return ret ? -1 : 0;
+}
+
+int utilfdt_decode_type(const char *fmt, int *type, int *size)
+{
+ int qualifier = 0;
+
+ if (!*fmt)
+ return -1;
+
+ /* get the conversion qualifier */
+ *size = -1;
+ if (strchr("hlLb", *fmt)) {
+ qualifier = *fmt++;
+ if (qualifier == *fmt) {
+ switch (*fmt++) {
+/* TODO: case 'l': qualifier = 'L'; break;*/
+ case 'h':
+ qualifier = 'b';
+ break;
+ }
+ }
+ }
+
+ /* we should now have a type */
+ if ((*fmt == '\0') || !strchr("iuxs", *fmt))
+ return -1;
+
+ /* convert qualifier (bhL) to byte size */
+ if (*fmt != 's')
+ *size = qualifier == 'b' ? 1 :
+ qualifier == 'h' ? 2 :
+ qualifier == 'l' ? 4 : -1;
+ *type = *fmt++;
+
+ /* that should be it! */
+ if (*fmt)
+ return -1;
+ return 0;
+}
diff --git a/scripts/dtc/util.h b/scripts/dtc/util.h
index 9cead84..c8eb45d 100644
--- a/scripts/dtc/util.h
+++ b/scripts/dtc/util.h
@@ -1,7 +1,10 @@
#ifndef _UTIL_H
#define _UTIL_H
+#include <stdarg.h>
+
/*
+ * Copyright 2011 The Chromium Authors, All Rights Reserved.
* Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
*
* This program is free software; you can redistribute it and/or
@@ -53,4 +56,98 @@
extern char *xstrdup(const char *s);
extern char *join_path(const char *path, const char *name);
+/**
+ * Check a string of a given length to see if it is all printable and
+ * has a valid terminator.
+ *
+ * @param data The string to check
+ * @param len The string length including terminator
+ * @return 1 if a valid printable string, 0 if not */
+int util_is_printable_string(const void *data, int len);
+
+/*
+ * Parse an escaped character starting at index i in string s. The resulting
+ * character will be returned and the index i will be updated to point at the
+ * character directly after the end of the encoding, this may be the '\0'
+ * terminator of the string.
+ */
+char get_escape_char(const char *s, int *i);
+
+/**
+ * Read a device tree file into a buffer. This will report any errors on
+ * stderr.
+ *
+ * @param filename The filename to read, or - for stdin
+ * @return Pointer to allocated buffer containing fdt, or NULL on error
+ */
+char *utilfdt_read(const char *filename);
+
+/**
+ * Read a device tree file into a buffer. Does not report errors, but only
+ * returns them. The value returned can be passed to strerror() to obtain
+ * an error message for the user.
+ *
+ * @param filename The filename to read, or - for stdin
+ * @param buffp Returns pointer to buffer containing fdt
+ * @return 0 if ok, else an errno value representing the error
+ */
+int utilfdt_read_err(const char *filename, char **buffp);
+
+
+/**
+ * Write a device tree buffer to a file. This will report any errors on
+ * stderr.
+ *
+ * @param filename The filename to write, or - for stdout
+ * @param blob Poiner to buffer containing fdt
+ * @return 0 if ok, -1 on error
+ */
+int utilfdt_write(const char *filename, const void *blob);
+
+/**
+ * Write a device tree buffer to a file. Does not report errors, but only
+ * returns them. The value returned can be passed to strerror() to obtain
+ * an error message for the user.
+ *
+ * @param filename The filename to write, or - for stdout
+ * @param blob Poiner to buffer containing fdt
+ * @return 0 if ok, else an errno value representing the error
+ */
+int utilfdt_write_err(const char *filename, const void *blob);
+
+/**
+ * Decode a data type string. The purpose of this string
+ *
+ * The string consists of an optional character followed by the type:
+ * Modifier characters:
+ * hh or b 1 byte
+ * h 2 byte
+ * l 4 byte, default
+ *
+ * Type character:
+ * s string
+ * i signed integer
+ * u unsigned integer
+ * x hex
+ *
+ * TODO: Implement ll modifier (8 bytes)
+ * TODO: Implement o type (octal)
+ *
+ * @param fmt Format string to process
+ * @param type Returns type found(s/d/u/x), or 0 if none
+ * @param size Returns size found(1,2,4,8) or 4 if none
+ * @return 0 if ok, -1 on error (no type given, or other invalid format)
+ */
+int utilfdt_decode_type(const char *fmt, int *type, int *size);
+
+/*
+ * This is a usage message fragment for the -t option. It is the format
+ * supported by utilfdt_decode_type.
+ */
+
+#define USAGE_TYPE_MSG \
+ "<type>\ts=string, i=int, u=unsigned, x=hex\n" \
+ "\tOptional modifier prefix:\n" \
+ "\t\thh or b=byte, h=2 byte, l=4 byte (default)\n";
+
#endif /* _UTIL_H */
diff --git a/sound/soc/codecs/msm8x10-wcd.c b/sound/soc/codecs/msm8x10-wcd.c
index 0ba1ec5..807cdad 100644
--- a/sound/soc/codecs/msm8x10-wcd.c
+++ b/sound/soc/codecs/msm8x10-wcd.c
@@ -683,9 +683,9 @@
kcontrol->private_value)->shift;
ucontrol->value.integer.value[0] =
- snd_soc_read(codec,
+ (snd_soc_read(codec,
(MSM8X10_WCD_A_CDC_IIR1_CTL + 64 * iir_idx)) &
- (1 << band_idx);
+ (1 << band_idx)) != 0;
dev_dbg(codec->dev, "%s: IIR #%d band #%d enable %d\n", __func__,
iir_idx, band_idx,
@@ -709,22 +709,54 @@
(1 << band_idx), (value << band_idx));
dev_dbg(codec->dev, "%s: IIR #%d band #%d enable %d\n", __func__,
- iir_idx, band_idx, value);
+ iir_idx, band_idx,
+ ((snd_soc_read(codec, (MSM8X10_WCD_A_CDC_IIR1_CTL + 64 * iir_idx)) &
+ (1 << band_idx)) != 0));
+
return 0;
}
static uint32_t get_iir_band_coeff(struct snd_soc_codec *codec,
int iir_idx, int band_idx,
int coeff_idx)
{
+ uint32_t value = 0;
+
/* Address does not automatically update if reading */
snd_soc_write(codec,
(MSM8X10_WCD_A_CDC_IIR1_COEF_B1_CTL + 64 * iir_idx),
- (band_idx * BAND_MAX + coeff_idx) & 0x1F);
+ ((band_idx * BAND_MAX + coeff_idx)
+ * sizeof(uint32_t)) & 0x7F);
+
+ value |= snd_soc_read(codec,
+ (MSM8X10_WCD_A_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx));
+
+ snd_soc_write(codec,
+ (MSM8X10_WCD_A_CDC_IIR1_COEF_B1_CTL + 64 * iir_idx),
+ ((band_idx * BAND_MAX + coeff_idx)
+ * sizeof(uint32_t) + 1) & 0x7F);
+
+ value |= (snd_soc_read(codec,
+ (MSM8X10_WCD_A_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx)) << 8);
+
+ snd_soc_write(codec,
+ (MSM8X10_WCD_A_CDC_IIR1_COEF_B1_CTL + 64 * iir_idx),
+ ((band_idx * BAND_MAX + coeff_idx)
+ * sizeof(uint32_t) + 2) & 0x7F);
+
+ value |= (snd_soc_read(codec,
+ (MSM8X10_WCD_A_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx)) << 16);
+
+ snd_soc_write(codec,
+ (MSM8X10_WCD_A_CDC_IIR1_COEF_B1_CTL + 64 * iir_idx),
+ ((band_idx * BAND_MAX + coeff_idx)
+ * sizeof(uint32_t) + 3) & 0x7F);
/* Mask bits top 2 bits since they are reserved */
- return ((snd_soc_read(codec,
- (MSM8X10_WCD_A_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx)) << 24)) &
- 0x3FFFFFFF;
+ value |= ((snd_soc_read(codec,
+ (MSM8X10_WCD_A_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx)) & 0x3f) << 24);
+
+ return value;
+
}
static int msm8x10_wcd_get_iir_band_audio_mixer(
@@ -768,13 +800,19 @@
static void set_iir_band_coeff(struct snd_soc_codec *codec,
int iir_idx, int band_idx,
- int coeff_idx, uint32_t value)
+ uint32_t value)
{
- /* Mask top 3 bits, 6-8 are reserved */
- /* Update address manually each time */
snd_soc_write(codec,
- (MSM8X10_WCD_A_CDC_IIR1_COEF_B1_CTL + 64 * iir_idx),
- (band_idx * BAND_MAX + coeff_idx) & 0x1F);
+ (MSM8X10_WCD_A_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx),
+ (value & 0xFF));
+
+ snd_soc_write(codec,
+ (MSM8X10_WCD_A_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx),
+ (value >> 8) & 0xFF);
+
+ snd_soc_write(codec,
+ (MSM8X10_WCD_A_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx),
+ (value >> 16) & 0xFF);
/* Mask top 2 bits, 7-8 are reserved */
snd_soc_write(codec,
@@ -793,15 +831,22 @@
int band_idx = ((struct soc_multi_mixer_control *)
kcontrol->private_value)->shift;
- set_iir_band_coeff(codec, iir_idx, band_idx, 0,
+ /* Mask top bit it is reserved */
+ /* Updates addr automatically for each B2 write */
+ snd_soc_write(codec,
+ (MSM8X10_WCD_A_CDC_IIR1_COEF_B1_CTL + 64 * iir_idx),
+ (band_idx * BAND_MAX * sizeof(uint32_t)) & 0x7F);
+
+
+ set_iir_band_coeff(codec, iir_idx, band_idx,
ucontrol->value.integer.value[0]);
- set_iir_band_coeff(codec, iir_idx, band_idx, 1,
+ set_iir_band_coeff(codec, iir_idx, band_idx,
ucontrol->value.integer.value[1]);
- set_iir_band_coeff(codec, iir_idx, band_idx, 2,
+ set_iir_band_coeff(codec, iir_idx, band_idx,
ucontrol->value.integer.value[2]);
- set_iir_band_coeff(codec, iir_idx, band_idx, 3,
+ set_iir_band_coeff(codec, iir_idx, band_idx,
ucontrol->value.integer.value[3]);
- set_iir_band_coeff(codec, iir_idx, band_idx, 4,
+ set_iir_band_coeff(codec, iir_idx, band_idx,
ucontrol->value.integer.value[4]);
dev_dbg(codec->dev, "%s: IIR #%d band #%d b0 = 0x%x\n"
@@ -1698,7 +1743,9 @@
{"RX3 MIX1", NULL, "RX3 MIX1 INP1"},
{"RX3 MIX1", NULL, "RX3 MIX1 INP2"},
{"RX1 MIX2", NULL, "RX1 MIX1"},
+ {"RX1 MIX2", NULL, "RX1 MIX2 INP1"},
{"RX2 MIX2", NULL, "RX2 MIX1"},
+ {"RX2 MIX2", NULL, "RX2 MIX2 INP1"},
{"RX1 MIX1 INP1", "RX1", "I2S RX1"},
{"RX1 MIX1 INP1", "RX2", "I2S RX2"},
@@ -1730,6 +1777,9 @@
{"RX3 MIX1 INP2", "RX3", "I2S RX3"},
{"RX3 MIX1 INP2", "IIR1", "IIR1"},
+ {"RX1 MIX2 INP1", "IIR1", "IIR1"},
+ {"RX2 MIX2 INP1", "IIR1", "IIR1"},
+
/* Decimator Inputs */
{"DEC1 MUX", "DMIC1", "DMIC1"},
{"DEC1 MUX", "DMIC2", "DMIC2"},
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index 4fd90f9..97803b3 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -2249,6 +2249,9 @@
SOC_SINGLE_EXT("SLIM_0_TX", MSM_BACKEND_DAI_AUXPCM_RX,
MSM_BACKEND_DAI_SLIMBUS_0_TX, 1, 0, msm_routing_get_port_mixer,
msm_routing_put_port_mixer),
+ SOC_SINGLE_EXT("SEC_AUX_PCM_UL_TX", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+ MSM_BACKEND_DAI_SEC_AUXPCM_TX, 1, 0, msm_routing_get_port_mixer,
+ msm_routing_put_port_mixer),
};
static const struct snd_kcontrol_new sec_auxpcm_rx_port_mixer_controls[] = {
@@ -2258,6 +2261,9 @@
SOC_SINGLE_EXT("SLIM_0_TX", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
MSM_BACKEND_DAI_SLIMBUS_0_TX, 1, 0, msm_routing_get_port_mixer,
msm_routing_put_port_mixer),
+ SOC_SINGLE_EXT("AUX_PCM_UL_TX", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+ MSM_BACKEND_DAI_SEC_AUXPCM_TX, 1, 0, msm_routing_get_port_mixer,
+ msm_routing_put_port_mixer),
};
static const struct snd_kcontrol_new sbus_1_rx_port_mixer_controls[] = {
@@ -3384,8 +3390,10 @@
{"AUXPCM_RX Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
{"AUXPCM_RX Port Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
+ {"AUXPCM_RX Port Mixer", "SEC_AUX_PCM_UL_TX", "SEC_AUX_PCM_TX"},
{"AUX_PCM_RX", NULL, "AUXPCM_RX Port Mixer"},
+ {"SEC_AUXPCM_RX Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
{"SEC_AUXPCM_RX Port Mixer", "SEC_AUX_PCM_UL_TX", "SEC_AUX_PCM_TX"},
{"SEC_AUXPCM_RX Port Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
{"SEC_AUX_PCM_RX", NULL, "SEC_AUXPCM_RX Port Mixer"},
diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c
index bdb0e13..a6ae357 100644
--- a/sound/soc/msm/qdsp6v2/q6adm.c
+++ b/sound/soc/msm/qdsp6v2/q6adm.c
@@ -1313,7 +1313,6 @@
{
struct avs_cmd_shared_mem_unmap_regions unmap_regions;
int ret = 0;
- int cmd_size = 0;
int index = 0;
pr_debug("%s\n", __func__);
@@ -1334,14 +1333,14 @@
unmap_regions.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
APR_HDR_LEN(APR_HDR_SIZE),
APR_PKT_VER);
- unmap_regions.hdr.pkt_size = cmd_size;
+ unmap_regions.hdr.pkt_size = sizeof(unmap_regions);
unmap_regions.hdr.src_port = 0;
unmap_regions.hdr.dest_port = atomic_read(&this_adm.copp_id[index]);
unmap_regions.hdr.token = port_id;
unmap_regions.hdr.opcode = ADM_CMD_SHARED_MEM_UNMAP_REGIONS;
unmap_regions.mem_map_handle = atomic_read(&this_adm.
mem_map_cal_handles[atomic_read(&this_adm.mem_map_cal_index)]);
- atomic_set(&this_adm.copp_stat[0], 0);
+ atomic_set(&this_adm.copp_stat[index], 0);
ret = apr_send_pkt(this_adm.apr, (uint32_t *) &unmap_regions);
if (ret < 0) {
pr_err("%s: mmap_regions op[0x%x]rc[%d]\n", __func__,
@@ -1351,11 +1350,16 @@
}
ret = wait_event_timeout(this_adm.wait[index],
- atomic_read(&this_adm.copp_stat[0]), 5 * HZ);
+ atomic_read(&this_adm.copp_stat[index]),
+ 5 * HZ);
if (!ret) {
- pr_err("%s: timeout. waited for memory_unmap\n", __func__);
+ pr_err("%s: timeout. waited for memory_unmap index %d\n",
+ __func__, index);
ret = -EINVAL;
goto fail_cmd;
+ } else {
+ pr_debug("%s: Unmap handle 0x%x succeeded\n", __func__,
+ unmap_regions.mem_map_handle);
}
fail_cmd:
return ret;