Merge "Merge android-4.9.109 (a4230be) into msm-4.9"
diff --git a/Documentation/devicetree/bindings/arm/msm/msm_ipc_router_fifo_xprt.txt b/Documentation/devicetree/bindings/arm/msm/msm_ipc_router_fifo_xprt.txt
new file mode 100644
index 0000000..a6fd56c2
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/msm_ipc_router_fifo_xprt.txt
@@ -0,0 +1,25 @@
+Qualcomm Technologies, Inc. IPC Router FIFO Transport
+
+Required properties:
+- compatible: should be "qcom,ipcr_fifo_xprt"
+- reg: the irq register to raise an interrupt
+- interrupts: the receiving interrupt line
+- qcom,ipc-shm: Reference to shared memory phandle
+
+Example:
+
+ fifo_vipc_irq@176 {
+ compatible = "qcom,ipcr-fifo-xprt";
+ reg = <0x176>;
+ interrupts = <0x0 0x142 0x1>;
+ qcom,ipc-shm = <&ipc-shm>;
+ };
+
+ ipc-shm: shared-buffer@85af7000 {
+ compatible = "qcom,hypervisor-shared-memory";
+ phandle = <0x1e4>;
+ reg = <0x0 0x85af7000 0x0 0x9000>;
+ label = "ipc_shm";
+ qcom,tx-is-first;
+ };
+
diff --git a/Documentation/devicetree/bindings/arm/msm/msm_ipc_router_glink_xprt.txt b/Documentation/devicetree/bindings/arm/msm/msm_ipc_router_glink_xprt.txt
index c5d052c..07f971e 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm_ipc_router_glink_xprt.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm_ipc_router_glink_xprt.txt
@@ -19,6 +19,8 @@
that subsystem.
-qcom,dynamic-wakeup-source: Boolean property to indicate that G-Link
transport supports dynamic wakeup source
+-qcom,low-latency-xprt: Boolean property to indicate that G-Link
+ transport is low latency trasport.
Example:
qcom,ipc_router_modem_xprt {
diff --git a/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt b/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
index 90bc368..c4ada7c 100644
--- a/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
+++ b/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
@@ -86,7 +86,8 @@
compatible devices:
qcom,sdm845-llcc,
- qcom,sdm670-llcc
+ qcom,sdm670-llcc,
+ qcom,qcs605-llcc
Example:
diff --git a/Documentation/devicetree/bindings/arm/msm/rpm_stats.txt b/Documentation/devicetree/bindings/arm/msm/rpm_stats.txt
index 02dab4c..7fe9e5d 100644
--- a/Documentation/devicetree/bindings/arm/msm/rpm_stats.txt
+++ b/Documentation/devicetree/bindings/arm/msm/rpm_stats.txt
@@ -24,10 +24,16 @@
Value type: <prop-encoded-array>
Definition: Provides labels for the reg property.
+- qcom,num-records:
+ Usage: optional
+ Value type: <u32>
+ Definition: Specifies number of records to read from RPM RAM.
+
EXAMPLE:
qcom,rpm-stats@c000000 {
compatible = "qcom,rpm-stats";
reg = <0xC000000 0x1000>, <0x3F0000 0x4>;
reg-names = "phys_addr_base", "offset_addr";
+ qcom,num-records = <3>;
};
diff --git a/Documentation/devicetree/bindings/cnss/cnss-wlan.txt b/Documentation/devicetree/bindings/cnss/cnss-wlan.txt
index ea3afc7..06a60e2 100644
--- a/Documentation/devicetree/bindings/cnss/cnss-wlan.txt
+++ b/Documentation/devicetree/bindings/cnss/cnss-wlan.txt
@@ -13,6 +13,7 @@
Required properties:
- compatible: "qcom,cnss" for QCA6174 device
"qcom,cnss-qca6290" for QCA6290 device
+ "qcom,cnss-qca6390" for QCA6390 device
- wlan-en-gpio: WLAN_EN GPIO signal specified by the chip specifications
- vdd-wlan-supply: phandle to the regulator device tree node
- pinctrl-names: Names corresponding to the numbered pinctrl states
diff --git a/Documentation/devicetree/bindings/input/touchscreen/git9xx/gt9xx.txt b/Documentation/devicetree/bindings/input/touchscreen/git9xx/gt9xx.txt
new file mode 100644
index 0000000..ba61a2f
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/git9xx/gt9xx.txt
@@ -0,0 +1,99 @@
+Goodix GT9xx series touch controller
+
+Required properties:
+
+ - compatible : Should be "goodix,gt9xx"
+ - reg : I2C slave address of the device.
+ - interrupt-parent : Parent of interrupt.
+ - interrupts : Configuration of touch panel controller interrupt
+ GPIO.
+ - goodix,product-id : Product identification of the controller.
+ - interrupt-gpios : Interrupt gpio which is to provide interrupts to
+ host, same as "interrupts" node.
+ - reset-gpios : Reset gpio to control the reset of chip.
+ - goodix,display-coords : Display coordinates in pixels. It is a four
+ tuple consisting of min x, min y, max x and
+ max y values.
+
+Optional properties:
+
+ - avdd-supply : Power supply needed to power up the device, this is
+ for fixed voltage external regulator.
+ - vdd-supply : Power supply needed to power up the device, when use
+ external regulator, do not add this property.
+ - vcc-i2c-supply : Power source required to power up i2c bus.
+ GT9xx series can provide 1.8V from internal
+ LDO, add this properties base on hardware
+ design.
+ - goodix,panel-coords : Panel coordinates for the chip in pixels.
+ It is a four tuple consisting of min x,
+ min y, max x and max y values.
+ - goodix,i2c-pull-up : To specify pull up is required.
+ - goodix,force-update : To specify force update is allowed.
+ - goodix,enable-power-off : Power off touchscreen during suspend.
+ - goodix,button-map : Button map of key codes. The number of key codes
+ depend on panel.
+ - goodix,cfg-data0 : Touch screen controller config data group 0. Ask vendor
+ to provide that.
+ Driver supports maximum six config groups. If more than one
+ groups are defined, driver will select config group depending
+ on hardware configuration. If only config group 0 is defined,
+ it will be used for all hardware configurations.
+ Touch screen controller will use its onchip default config data
+ if this property is not present.
+ - goodix,cfg-data1 : Touch screen controller config data group 1. Ask vendor
+ to provide that.
+ - goodix,cfg-data2 : Touch screen controller config data group 2. Ask vendor
+ to provide that.
+ - goodix,cfg-data3 : Touch screen controller config data group 3. Ask vendor
+ to provide that.
+ - goodix,cfg-data4 : Touch screen controller config data group 4. Ask vendor
+ to provide that.
+ - goodix,cfg-data5 : Touch screen controller config data group 5. Ask vendor
+ to provide that.
+ - goodix,fw-name : Touch screen controller firmware file name.
+ - goodix,slide-wakeup : To specify slide-wakeup property is enabled or not.
+ - goodix,dbl-clk-wakeup : To specify dbl-clk-wakeup property is enabled or not.
+ - goodix,change-x2y : To specify change-x2y property is enabled or not.
+ - goodix,driver-send-cfg : To specify driver-send-cfg property is enabled or not.
+ - goodix,have-touch-key : To specify have-touch-key property is enabled or not.
+ - goodix,with-pen : To specify with-pen property is enabled or not.
+Example:
+i2c@f9927000 {
+ goodix@5d {
+ compatible = "goodix,gt9xx";
+ reg = <0x5d>;
+ interrupt-parent = <&msmgpio>;
+ interrupts = <17 0x2008>;
+ reset-gpios = <&msmgpio 16 0x00>;
+ interrupt-gpios = <&msmgpio 17 0x00>;
+ avdd-supply = <&tp_power>;
+ goodix,panel-coords = <0 0 720 1200>;
+ goodix,display-coords = <0 0 720 1080>;
+ goodix,button-map= <158 102 139>;
+ goodix,product-id = "915";
+ goodix,cfg-data0 = [
+ 41 D0 02 00 05 0A 05 01 01 08
+ 12 58 50 41 03 05 00 00 00 00
+ 00 00 00 00 00 00 00 8C 2E 0E
+ 28 24 73 13 00 00 00 83 03 1D
+ 40 02 00 00 00 03 64 32 00 00
+ 00 1A 38 94 C0 02 00 00 00 04
+ 9E 1C 00 8D 20 00 7A 26 00 6D
+ 2C 00 60 34 00 60 10 38 68 00
+ F0 50 35 FF FF 27 00 00 00 00
+ 00 01 1B 14 0C 14 00 00 01 00
+ 00 00 00 00 00 00 00 00 00 00
+ 00 00 02 04 06 08 0A 0C 0E 10
+ 12 14 16 18 1A 1C FF FF FF FF
+ FF FF FF FF FF FF FF FF FF FF
+ FF FF 00 02 04 06 08 0A 0C 0F
+ 10 12 13 14 16 18 1C 1D 1E 1F
+ 20 21 22 24 26 28 29 2A FF FF
+ FF FF FF FF FF FF FF 22 22 22
+ 22 22 22 FF 07 01];
+ goodix,fw_name = "gtp_fw.bin";
+ goodix,have-touch-key;
+ goodix,driver-send-cfg;
+ };
+};
diff --git a/Documentation/devicetree/bindings/input/touchscreen/himax.txt b/Documentation/devicetree/bindings/input/touchscreen/himax.txt
deleted file mode 100644
index b54c859..0000000
--- a/Documentation/devicetree/bindings/input/touchscreen/himax.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-Himax touch controller
-
-Required properties:
-
- - compatible : Should be "himax,hxcommon"
- - reg : i2c slave address of the device.
- - interrupt-parent : parent of interrupt.
- - himax,irq-gpio : irq gpio.
- - himax,reset-gpio : reset gpio.
- - vdd-supply : Power supply needed to power up the device.
- - avdd-supply : Power source required to power up i2c bus.
- - himax,panel-coords : panel coordinates for the chip in pixels.
- It is a four tuple consisting of min x,
- min y, max x and max y values.
- - himax,display-coords : display coordinates in pixels. It is a four
- tuple consisting of min x, min y, max x and
- max y values
-
-Optional properties:
- - himax,3v3-gpio : gpio acting as 3.3 v supply.
- - report_type : Multi-touch protocol type. Default 0.
- 0 for protocol A, 1 for protocol B.
diff --git a/Documentation/devicetree/bindings/input/touchscreen/himax_i2c_ts.txt b/Documentation/devicetree/bindings/input/touchscreen/himax_i2c_ts.txt
new file mode 100644
index 0000000..9889f55
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/himax_i2c_ts.txt
@@ -0,0 +1,57 @@
+Himax touch controller
+
+Required properties:
+
+ - compatible : should be "himax,hxcommon"
+ - reg : i2c slave address of the device
+ - interrupt-parent : parent of interrupt
+ - interrupts : touch sample interrupt to indicate presense or release
+ of fingers on the panel.
+ - himax,irq-gpio : irq gpio
+ - himax,reset-gpio : reset gpio
+
+Optional property:
+ - vdd-supply : Analog power supply needed to power device
+ - vcc_i2c-supply : Power source required to pull up i2c bus
+ - himax,i2c-pull-up : specify to indicate pull up is needed
+ - himax,disable-gpios : specify to disable gpios in suspend (power saving)
+ - himax,button-map : virtual key code mappings to be used
+ - himax,x-flip : modify orientation of the x axis
+ - himax,y-flip : modify orientation of the y axis
+ - himax,panel-coords : touch panel min x, min y, max x and
+ max y resolution
+ - himax,display-coords : display min x, min y, max x and
+ max y resolution
+ - himax,reset-delay : reset delay for controller (ms), default 100
+ - himax,fw-image-name : name of firmware .img file in /etc/firmware
+ - himax,power-down : fully power down regulators in suspend
+ - himax,do-lockdown : perform one time lockdown procedure
+
+Example:
+ i2c@f9927000 { /* BLSP1 QUP5 */
+ cell-index = <5>;
+ compatible = "himax,hxcommon";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg-names = "qup_phys_addr";
+ reg = <0xf9927000 0x1000>;
+ interrupt-names = "qup_err_intr";
+ interrupts = <0 99 0>;
+ gpios = <&msmgpio 19 0>, /* SCL */
+ <&msmgpio 18 0>; /* SDA */
+ qcom,i2c-bus-freq = <100000>;
+ qcom,i2c-src-freq = <19200000>;
+
+ himax_ts@20 {
+ compatible = "himax,hxcommon"
+ reg = <0x20>;
+ interrupt-parent = <&tlmm>;
+ interrupts = <255 0x2008>;
+ vdd-supply = <&pm8994_l15>;
+ avdd-supply = <&pm8994_l22>;
+ himax,panel-coords = <0 720 0 1440>;
+ himax,display-coords = <0 720 0 1440>;
+ himax,irq-gpio = <&tlmm 255 0x2008>;
+ himax,rst-gpio = <&tlmm 8 0x00>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/net/qcom-ssdk.txt b/Documentation/devicetree/bindings/net/qcom-ssdk.txt
index b72215d..9624edb 100644
--- a/Documentation/devicetree/bindings/net/qcom-ssdk.txt
+++ b/Documentation/devicetree/bindings/net/qcom-ssdk.txt
@@ -21,15 +21,15 @@
compatible = "qcom,ess-switch-qca83xx";
qcom,switch-access-mode = "mdio";
qcom,ar8327-initvals = <
- 0x0000c 0x7600000 /* PAD6_MODE */
+ 0x00004 0x7600000 /* PAD0_MODE */
0x00008 0x0 /* PAD5_MODE */
0x000e4 0xaa545 /* MAC_POWER_SEL */
0x000e0 0xc74164de /* SGMII_CTRL */
0x0007c 0x4e /* PORT0_STATUS */
0x00094 0x4e /* PORT6_STATUS */
>;
- qcom,link-intr-gpio = <2>;
- qcom,switch-cpu-bmp = <0x40>; /* cpu port bitmap */
+ qcom,link-intr-gpio = <84>;
+ qcom,switch-cpu-bmp = <0x01>; /* cpu port bitmap */
qcom,switch-lan-bmp = <0x3e>; /* lan port bitmap */
qcom,switch-wan-bmp = <0x0>; /* wan port bitmap */
};
diff --git a/Documentation/devicetree/bindings/platform/msm/ipa.txt b/Documentation/devicetree/bindings/platform/msm/ipa.txt
index 917c2d0..7652aa4 100644
--- a/Documentation/devicetree/bindings/platform/msm/ipa.txt
+++ b/Documentation/devicetree/bindings/platform/msm/ipa.txt
@@ -87,6 +87,8 @@
need to be unlocked by TZ.
- qcom,ipa-uc-monitor-holb: Boolean context flag to indicate whether
monitoring of holb via IPA uc is required.
+- qcom,wlan-ce-db-over-pcie: Boolean context flag to represent WLAN CE DB
+ over pcie bus or not.
IPA pipe sub nodes (A2 static pipes configurations):
diff --git a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen3.txt b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen3.txt
index 3d054f3..cc4a38a 100644
--- a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen3.txt
+++ b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen3.txt
@@ -296,6 +296,17 @@
This should be defined in the ascending order and in the
range of 0-100. Array limit is set to 3.
+- qcom,ki-coeff-low-dischg
+ Usage: optional
+ Value type: <prop-encoded-array>
+ Definition: Array of ki coefficient values for low discharge current
+ during discharge. These values will be applied when the
+ monotonic SOC goes below the SOC threshold specified under
+ qcom,ki-coeff-soc-dischg. Array limit is set to 3. This
+ property should be specified if qcom,ki-coeff-soc-dischg
+ is specified to make it fully functional. Value has no
+ unit. Allowed range is 0 to 62200 in micro units.
+
- qcom,ki-coeff-med-dischg
Usage: optional
Value type: <prop-encoded-array>
@@ -325,13 +336,6 @@
discharging. If not specified, a value of 0 will be set.
Allowed range is from 245 to 62256.
-- qcom,ki-coeff-low-dischg
- Usage: optional
- Value type: <u32>
- Definition: Ki coefficient value for low discharge current during
- discharging. Value has no unit. Allowed range is 0-62200
- in micro units.
-
- qcom,ki-coeff-hi-chg
Usage: optional
Value type: <u32>
diff --git a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-qg.txt b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-qg.txt
index 0da71a3..83f964d 100644
--- a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-qg.txt
+++ b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-qg.txt
@@ -295,6 +295,13 @@
attempted by QG. If not defined the value defaults
to 10%.
+- qcom,esr-chg-min-ibat-ua
+ Usage: optional
+ Value type: <int>
+ Definition: Minimun charge current (IBAT) in uA at which ESR will
+ be attempted. If not specified the default value is
+ in -450mA.
+
- qcom,qg-ext-sns
Usage: optional
Value type: <bool>
diff --git a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb5.txt b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb5.txt
index 8ee2749..0b6daab 100644
--- a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb5.txt
+++ b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb5.txt
@@ -107,6 +107,27 @@
then charge inhibit will be disabled by default.
Allowed values are: 50, 100, 200, 300.
+- qcom,chg-term-src
+ Usage: optional
+ Value type: <u32>
+ Definition: Specify either the ADC or analog comparators to be used in order
+ to set threshold values for charge termination current.
+ 0 - Unspecified
+ 1 - Select ADC comparator
+ 2 - Select ANALOG comparator
+
+- qcom,chg-term-current-ma
+ Usage: optional
+ Value type: <u32>
+ Definition: When ADC comparator is selected as qcom,chg-term-src, this
+ parameter should be set to the desired upper threshold.
+
+- qcom,chg-term-base-current-ma
+ Usage: optional
+ Value type: <u32>
+ Definition: When ADC comparator is selected as qcom,chg-term-src, this
+ parameter should be set to the desired lower threshold.
+
- qcom,auto-recharge-soc
Usage: optional
Value type: <u32>
@@ -201,6 +222,25 @@
Definition: Phandle for the VADC node, it is used to obtain USBIN_V
and USBIN_I readings on PMIC632 based platform.
+- qcom,hw-die-temp-mitigation
+ Usage: optional
+ Value type: bool
+ Definition: Boolean flag which when present enables h/w based thermal
+ mitigation.
+
+- qcom,hw-connector-mitigation
+ Usage: optional
+ Value type: bool
+ Definition: Boolean flag which when present enables h/w based
+ connector temperature mitigation.
+
+- qcom,connector-internal-pull-kohm
+ Usage: optional
+ Value type: <u32>
+ Definition: Specifies internal pull-up configuration to be applied to
+ connector THERM, only valid values are (0/30/100/400).
+ If not specified 100K is used as default pull-up.
+
=============================================
Second Level Nodes - SMB5 Charger Peripherals
=============================================
diff --git a/Documentation/devicetree/bindings/power/supply/qcom/smb1355-charger.txt b/Documentation/devicetree/bindings/power/supply/qcom/smb1355-charger.txt
index 4f12ec0..528c285 100644
--- a/Documentation/devicetree/bindings/power/supply/qcom/smb1355-charger.txt
+++ b/Documentation/devicetree/bindings/power/supply/qcom/smb1355-charger.txt
@@ -51,6 +51,18 @@
stacked one after the other and thus all the charge current
(FCC) flows through main. In a non-stacked configuration each
charger controls the charge current (FCC) separately.
+
+- qcom,die-temp-threshold-degc
+ Usage: optional
+ Value type: <u32>
+ Definition: Specifies DIE temp threshold beyond which h/w starts mitigation.
+ If not sepcified, 90 degrees centigrade is used.
+
+- qcom,hw-die-temp-mitigation
+ Usage: optional
+ Value type: bool
+ Definition: Boolean property to enable h/w controlled die temp mitigation.
+
================================================
Second Level Nodes - SMB1355 Charger Peripherals
================================================
diff --git a/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt b/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt
index 803df6f..6fae8b0 100644
--- a/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt
@@ -61,6 +61,12 @@
in conjunction with "hw-ctrl-addr".
- qcom,toggle-sw-collapse-in-disable: If set, SW_COLLAPSE bit is toggled
in disable call.
+ - qcom,en-few-wait-val: Input value for EN_FEW_WAIT controls state transition
+ delay after receiving ack signal (gds_enf_ack) from the
+ longest en_few power switch chain.
+ - qcom,en-rest-wait-val: Input value for EN_REST_WAIT controls state transition
+ delay after receiving ack signal (gds_enr_ack) from the
+ longest en_rest power switch chain.
Example:
gdsc_oxili_gx: qcom,gdsc@fd8c4024 {
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index 20cb25b..6c9d8253 100644
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -3290,3 +3290,97 @@
qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrRight",
"SpkrLeft", "SpkrRight";
}
+
+* QCS605 IPcamera ASoC Machine driver
+
+Required properties:
+- compatible : "qcom,qcs605-asoc-snd-tavil"
+- qcom,model : The user-visible name of this sound card.
+- qcom,audio-routing : A list of the connections between audio components.
+- qcom,msm-gpios : Lists down all the gpio sets that are supported.
+- qcom,pinctrl-names : Lists all the possible combinations of the gpio sets
+mentioned in qcom,msm-gpios.
+- pinctrl-names : The combinations of gpio sets from above that are supported in
+the flavor.
+- pinctrl-# : Pinctrl states as mentioned in pinctrl-names.
+
+Optional properties:
+- qcom,wsa-disable : Boolean. Disables WSA speaker dailinks from sound node.
+- qcom,msm-spk-ext-pa : GPIO which enables external speaker pa.
+- qcom,msm-mclk-freq : This property is used to inform machine driver about
+mclk frequency needs to be configured for internal and external PA.
+- asoc-platform: This is phandle list containing the references to platform device
+ nodes that are used as part of the sound card dai-links.
+- asoc-platform-names: This property contains list of platform names. The order of
+ the platform names should match to that of the phandle order
+ given in "asoc-platform".
+- asoc-cpu: This is phandle list containing the references to cpu dai device nodes
+ that are used as part of the sound card dai-links.
+- asoc-cpu-names: This property contains list of cpu dai names. The order of the
+ cpu dai names should match to that of the phandle order given.
+- asoc-codec: This is phandle list containing the references to codec dai device
+ nodes that are used as part of the sound card dai-links.
+- asoc-codec-names: This property contains list of codec dai names. The order of the
+ codec dai names should match to that of the phandle order given
+ in "asoc-codec".
+- qcom,wsa-max-devs : Maximum number of WSA881x devices present in the target
+- qcom,wsa-devs : List of phandles for all possible WSA881x devices supported for the target
+- qcom,wsa-aux-dev-prefix : Name prefix with Left/Right configuration for WSA881x device
+- qcom,cdc-dmic-gpios : phandle for Digital mic clk and data gpios.
+- qcom,cdc-sdw-gpios : phandle for soundwire clk and data gpios.
+- qcom,pri-mi2s-gpios : phandle for primary MI2S clk, word select and data gpios.
+- qcom,sec-mi2s-gpios : phandle for secondary MI2S clk, word select and data gpios.
+- qcom,tert-mi2s-gpios : phandle for tertiary MI2S clk, word select and data gpios.
+- qcom,quat-mi2s-gpios : phandle for quaternary MI2S clk, word select and data gpios.
+- qcom,quin-mi2s-gpios : phandle for quinary MI2S clk, word select and data gpios.
+
+Example:
+ sound {
+ compatible = "qcom,qcs605-asoc-snd-tavil";
+ qcom,model = "qcs605-tavil-snd-card";
+ qcom,audio-routing =
+ "RX_BIAS", "INT_MCLK0",
+ "SPK_RX_BIAS", "INT_MCLK0",
+ "DMIC1", "DIGITAL_REGULATOR",
+ "DIGITAL_REGULATOR", "Digital Mic1",
+ "DMIC2", "DIGITAL_REGULATOR",
+ "DIGITAL_REGULATOR", "Digital Mic2",
+ "DMIC3", "DIGITAL_REGULATOR",
+ "DIGITAL_REGULATOR", "Digital Mic3",
+ "DMIC4", "DIGITAL_REGULATOR",
+ "DIGITAL_REGULATOR", "Digital Mic4",
+ "SpkrLeft IN", "SPK1 OUT",
+ "SpkrRight IN", "SPK2 OUT";
+
+ qcom,msm-mi2s-master = <1>, <1>, <1>, <1>, <1>;
+ qcom,msm-mclk-freq = <9600000>;
+ qcom,msm-gpios =
+ "slim",
+ "us_eu_gpio";
+ qcom,pinctrl-names =
+ "all_off",
+ "slim_act",
+ "us_eu_gpio_act",
+ "slim_us_eu_gpio_act";
+ pinctrl-names =
+ "all_off",
+ "slim_act",
+ "us_eu_gpio_act",
+ "slim_us_eu_gpio_act";
+ pinctrl-0 = <&cdc_slim_lines_sus &cross_conn_det_sus>;
+ pinctrl-1 = <&cdc_slim_lines_act &cross_conn_det_sus>;
+ pinctrl-2 = <&cdc_slim_lines_sus &cross_conn_det_act>;
+ pinctrl-3 = <&cdc_slim_lines_act &cross_conn_det_act>;
+ qcom,cdc-dmic-gpios = <&cdc_dmic_gpios>;
+
+ asoc-codec = <&stub_codec>, <&msm_digital_codec>,
+ <&msm_sdw_codec>;
+ asoc-codec-names = "msm-stub-codec.1", "msm-dig-codec",
+ "msm_sdw_codec";
+
+ qcom,wsa-max-devs = <2>;
+ qcom,wsa-devs = <&wsa881x_211_en>, <&wsa881x_212_en>,
+ <&wsa881x_213_en>, <&wsa881x_214_en>;
+ qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrRight",
+ "SpkrLeft", "SpkrRight";
+ }
diff --git a/Documentation/devicetree/bindings/spi/qcom,spi-geni-qcom.txt b/Documentation/devicetree/bindings/spi/qcom,spi-geni-qcom.txt
index 866d004..8b6d5a2 100644
--- a/Documentation/devicetree/bindings/spi/qcom,spi-geni-qcom.txt
+++ b/Documentation/devicetree/bindings/spi/qcom,spi-geni-qcom.txt
@@ -28,6 +28,7 @@
Optional properties:
- qcom,rt: Specifies if the framework worker thread for this
controller device should have "real-time" priority.
+- qcom,disable-autosuspend: Specifies to disable runtime PM auto suspend.
SPI slave nodes must be children of the SPI master node and can contain
properties described in Documentation/devicetree/bindings/spi/spi-bus.txt
diff --git a/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt b/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt
index 5c09077..70b6fb5 100644
--- a/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt
+++ b/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt
@@ -40,7 +40,24 @@
receive.
SPI slave nodes must be children of the SPI master node and can contain
-properties described in Documentation/devicetree/bindings/spi/spi-bus.txt
+the following properties.
+
+Required properties:
+- compatible: Should contain:
+ "qcom,spi-msm-slave" for external slave control
+
+- reg: Chip select address of device.
+
+- spi-max-frequency: Maximum SPI clocking speed of device in Hz.
+
+Optional properties:
+- spi-cpol: Empty property indicating device requires
+ inverse clock polarity (CPOL) mode.
+- spi-cpha: Empty property indicating device requires
+ shifted clock phase (CPHA) mode.
+
+Other optional properties described in
+Documentation/devicetree/bindings/spi/spi-bus.txt
Example:
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index a22edb5..ed51a77 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -123,13 +123,13 @@
hannstar HannStar Display Corporation
haoyu Haoyu Microelectronic Co. Ltd.
hardkernel Hardkernel Co., Ltd
-himax Himax Technologies, Inc.
hisilicon Hisilicon Limited.
hit Hitachi Ltd.
hitex Hitex Development Tools
holt Holt Integrated Circuits, Inc.
honeywell Honeywell
hp Hewlett Packard
+himax Himax Coroporation
i2se I2SE GmbH
ibm International Business Machines (IBM)
idt Integrated Device Technologies, Inc.
diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt
index 206c9b0..3cab335 100644
--- a/Documentation/sysctl/vm.txt
+++ b/Documentation/sysctl/vm.txt
@@ -64,6 +64,7 @@
- vfs_cache_pressure
- watermark_scale_factor
- zone_reclaim_mode
+- want_old_faultaround_pte
==============================================================
@@ -891,4 +892,25 @@
node unless explicitly overridden by memory policies or cpuset
configurations.
+=============================================================
+
+want_old_faultaround_pte:
+
+By default faultaround code produces young pte. When want_old_faultaround_pte is
+set to 1, faultaround produces old ptes.
+
+During sparse file access faultaround gets more pages mapped and when all of
+them are young (default), under memory pressure, this makes vmscan swap out anon
+pages instead, or to drop other page cache pages which otherwise stay resident.
+Setting want_old_faultaround_pte to 1 avoids this.
+
+Making the faultaround ptes old can result in performance regression on some
+architectures. This is due to cycles spent in micro-faults which would take page
+walk to set young bit in the pte. One such known test that shows a regression on
+x86 is unixbench shell8. Set want_old_faultaround_pte to 1 on architectures
+which does not show this regression or if the workload shows overall performance
+benefit with old faultaround ptes.
+
+The default value is 0.
+
============ End of Document =================================
diff --git a/arch/arm/boot/dts/qcom/msm-arm-smmu-sdxpoorwills.dtsi b/arch/arm/boot/dts/qcom/msm-arm-smmu-sdxpoorwills.dtsi
index 580df55..a9b17a0 100644
--- a/arch/arm/boot/dts/qcom/msm-arm-smmu-sdxpoorwills.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-arm-smmu-sdxpoorwills.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
@@ -21,6 +21,8 @@
reg-names = "base", "tcu-base";
#iommu-cells = <2>;
qcom,use-3-lvl-tables;
+ qcom,no-asid-retention;
+ qcom,disable-atos;
#global-interrupts = <1>;
#size-cells = <1>;
#address-cells = <1>;
@@ -100,5 +102,6 @@
* the apps_smmu device.
*/
iommus = <&apps_smmu 0x1a0 0x0>;
+ status = "disabled";
};
};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-cdp-256.dts b/arch/arm/boot/dts/qcom/sdxpoorwills-cdp-256.dts
index 04f11ce..fa858c3 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-cdp-256.dts
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-cdp-256.dts
@@ -20,3 +20,7 @@
"qcom,sdxpoorwills", "qcom,cdp";
qcom,board-id = <1 0x0>;
};
+
+&blsp1_uart2b_hs {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-cdp-256.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-cdp-256.dtsi
index 0f9c8bc..fc56a50 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-cdp-256.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-cdp-256.dtsi
@@ -11,6 +11,7 @@
*/
#include "sdxpoorwills-cdp.dtsi"
+#include "sdxpoorwills-memory-256.dtsi"
&soc {
vreg_sd_mmc: vreg_sd_mmc {
@@ -21,3 +22,11 @@
&sdhc_1 {
cd-gpios = <&tlmm 21 0x1>;
};
+
+&soc {
+ bluetooth: bt_qca6174 {
+ compatible = "qca,qca6174";
+ qca,bt-reset-gpio = <&pmxpoorwills_gpios 4 0>; /* BT_EN */
+ qca,bt-vdd-pa-supply = <&vreg_wlan>;
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-mtp.dts b/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-mtp.dts
index 5fd7042..243fdaf 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-mtp.dts
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-mtp.dts
@@ -28,3 +28,7 @@
&cnss_sdio {
status = "okay";
};
+
+&blsp1_uart2b_hs {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-mtp.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-mtp.dtsi
index b60225a..252fb04 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-mtp.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-mtp.dtsi
@@ -36,3 +36,11 @@
/delete-property/ qcom,devfreq,freq-table;
/delete-property/ cd-gpios;
};
+
+&soc {
+ bluetooth: bt_qca6174 {
+ compatible = "qca,qca6174";
+ qca,bt-reset-gpio = <&pmxpoorwills_gpios 4 0>; /* BT_EN */
+ qca,bt-vdd-pa-supply = <&vreg_wlan>;
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-ion.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-ion.dtsi
index a09b149..6957063 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-ion.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-ion.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
@@ -26,5 +26,17 @@
memory-region = <&audio_mem>;
qcom,ion-heap-type = "DMA";
};
+
+ qcom,ion-heap@27 { /* QSEECOM HEAP */
+ reg = <27>;
+ memory-region = <&qseecom_mem>;
+ qcom,ion-heap-type = "DMA";
+ };
+
+ qcom,ion-heap@19 { /* QSEECOM TA HEAP */
+ reg = <19>;
+ memory-region = <&qseecom_ta_mem>;
+ qcom,ion-heap-type = "DMA";
+ };
};
};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-memory-256.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-memory-256.dtsi
new file mode 100644
index 0000000..0c21814
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-memory-256.dtsi
@@ -0,0 +1,19 @@
+/* Copyright (c) 2018, 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.
+ */
+
+&peripheral2_mem {
+ reg = <0x8fe00000 0x200000>;
+};
+
+&mss_mem {
+ reg = <0x87000000 0x8300000>;
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-mtp-256.dts b/arch/arm/boot/dts/qcom/sdxpoorwills-mtp-256.dts
index 2377d79c..a774c8b 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-mtp-256.dts
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-mtp-256.dts
@@ -20,3 +20,7 @@
"qcom,sdxpoorwills", "qcom,mtp";
qcom,board-id = <8 0x0>;
};
+
+&blsp1_uart2b_hs {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-mtp-256.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-mtp-256.dtsi
index 7412031..297af52 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-mtp-256.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-mtp-256.dtsi
@@ -11,6 +11,7 @@
*/
#include "sdxpoorwills-mtp.dtsi"
+#include "sdxpoorwills-memory-256.dtsi"
&soc {
vreg_sd_mmc: vreg_sd_mmc {
@@ -21,3 +22,11 @@
&sdhc_1 {
cd-gpios = <&tlmm 21 0x1>;
};
+
+&soc {
+ bluetooth: bt_qca6174 {
+ compatible = "qca,qca6174";
+ qca,bt-reset-gpio = <&pmxpoorwills_gpios 4 0>; /* BT_EN */
+ qca,bt-vdd-pa-supply = <&vreg_wlan>;
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-mtp.dts b/arch/arm/boot/dts/qcom/sdxpoorwills-mtp.dts
index ae3de38..3ae5b2c 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-mtp.dts
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-mtp.dts
@@ -20,3 +20,7 @@
"qcom,sdxpoorwills", "qcom,mtp";
qcom,board-id = <8 0x102>;
};
+
+&qcom_seecom {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-pm.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-pm.dtsi
index 505f242..2c227b3 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-pm.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-pm.dtsi
@@ -97,6 +97,7 @@
compatible = "qcom,rpm-stats";
reg = <0xC300000 0x1000>, <0xC370004 0x4>;
reg-names = "phys_addr_base", "offset_addr";
+ qcom,num-records = <3>;
};
qcom,rpmh-master-stats@b211200 {
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-ttp.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-ttp.dtsi
index 7f49b6d..fa8f3a4 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-ttp.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-ttp.dtsi
@@ -12,3 +12,12 @@
#include "sdxpoorwills-mtp.dtsi"
+&vbus_detect {
+ status = "okay";
+};
+
+&usb {
+ status = "okay";
+ qcom,connector-type-uAB;
+ extcon = <0>, <0>, <0>, <&vbus_detect>;
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-usb.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-usb.dtsi
index 9f74227..642a541 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-usb.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-usb.dtsi
@@ -44,8 +44,8 @@
clock-names = "core_clk", "iface_clk", "utmi_clk", "sleep_clk",
"cfg_ahb_clk", "xo";
- qcom,core-clk-rate = <133333333>;
- qcom,core-clk-rate-hs = <66666667>;
+ qcom,core-clk-rate = <120000000>; /* MAX SVS */
+ qcom,core-clk-rate-hs = <75000000>; /* MAX LOW SVS */
resets = <&clock_gcc GCC_USB30_BCR>;
reset-names = "core_reset";
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
index d1b2050..ef001fb 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
@@ -18,6 +18,7 @@
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
#include <dt-bindings/clock/qcom,aop-qmp.h>
+#include <dt-bindings/msm/msm-bus-ids.h>
#define MHZ_TO_MBPS(mhz, w) ((mhz * 1000000 * w) / (1024 * 1024))
@@ -35,7 +36,7 @@
peripheral2_mem: peripheral2_region@8fe00000 {
compatible = "removed-dma-pool";
no-map;
- reg = <0x8fe00000 0x200000>;
+ reg = <0x8fe00000 0xe00000>;
label = "peripheral2_mem";
};
@@ -64,7 +65,7 @@
mss_mem: mss_region@87400000 {
compatible = "removed-dma-pool";
no-map;
- reg = <0x87400000 0x8300000>;
+ reg = <0x87000000 0x8700000>;
label = "mss_mem";
};
@@ -79,6 +80,20 @@
reusable;
size = <0x400000>;
};
+
+ qseecom_mem: qseecom_region@0 {
+ compatible = "shared-dma-pool";
+ reusable;
+ alignment = <0x400000>;
+ size = <0x1400000>;
+ };
+
+ qseecom_ta_mem: qseecom_ta_region@0 {
+ compatible = "shared-dma-pool";
+ reusable;
+ alignment = <0x400000>;
+ size = <0x1000000>;
+ };
};
cpus {
@@ -920,38 +935,49 @@
qcom,mhi-event-ring-id-limits = <9 10>; /* start and end */
qcom,modem-cfg-emb-pipe-flt;
qcom,use-ipa-pm;
+ qcom,wlan-ce-db-over-pcie;
qcom,arm-smmu;
qcom,smmu-fast-map;
qcom,bandwidth-vote-for-ipa;
qcom,msm-bus,name = "ipa";
qcom,msm-bus,num-cases = <5>;
- qcom,msm-bus,num-paths = <4>;
+ qcom,msm-bus,num-paths = <5>;
qcom,msm-bus,vectors-KBps =
/* No vote */
- <90 512 0 0>,
- <90 585 0 0>,
- <1 676 0 0>,
- <143 777 0 0>,
+ <MSM_BUS_MASTER_IPA MSM_BUS_SLAVE_SNOC_MEM_NOC_GC 0 0>,
+ <MSM_BUS_MASTER_SNOC_GC_MEM_NOC MSM_BUS_SLAVE_EBI_CH0 0 0>,
+ <MSM_BUS_MASTER_IPA MSM_BUS_SLAVE_OCIMEM 0 0>,
+ <MSM_BUS_MASTER_AMPSS_M0 MSM_BUS_SLAVE_IPA_CFG 0 0>,
+ <MSM_BUS_MASTER_IPA_CORE MSM_BUS_SLAVE_IPA_CORE 0 0>,
+
/* SVS2 */
- <90 512 900000 1800000>,
- <90 585 300000 600000>,
- <1 676 90000 179000>, /*gcc_config_noc_clk_src */
- <143 777 0 120>, /* IB defined for IPA2X_clk in MHz*/
+ <MSM_BUS_MASTER_IPA MSM_BUS_SLAVE_SNOC_MEM_NOC_GC 240000 480000>,
+ <MSM_BUS_MASTER_SNOC_GC_MEM_NOC MSM_BUS_SLAVE_EBI_CH0 900000 1800000>,
+ <MSM_BUS_MASTER_IPA MSM_BUS_SLAVE_OCIMEM 300000 600000>,
+ <MSM_BUS_MASTER_AMPSS_M0 MSM_BUS_SLAVE_IPA_CFG 90000 179000>,
+ <MSM_BUS_MASTER_IPA_CORE MSM_BUS_SLAVE_IPA_CORE 0 120>,
+
/* SVS */
- <90 512 1530000 3060000>,
- <90 585 400000 800000>,
- <1 676 100000 199000>,
- <143 777 0 250>, /* IB defined for IPA2X_clk in MHz*/
+ <MSM_BUS_MASTER_IPA MSM_BUS_SLAVE_SNOC_MEM_NOC_GC 360000 720000>,
+ <MSM_BUS_MASTER_SNOC_GC_MEM_NOC MSM_BUS_SLAVE_EBI_CH0 1530000 3060000>,
+ <MSM_BUS_MASTER_IPA MSM_BUS_SLAVE_OCIMEM 400000 800000>,
+ <MSM_BUS_MASTER_AMPSS_M0 MSM_BUS_SLAVE_IPA_CFG 100000 199000>,
+ <MSM_BUS_MASTER_IPA_CORE MSM_BUS_SLAVE_IPA_CORE 0 250>,
+
/* NOMINAL */
- <90 512 2592000 5184000>,
- <90 585 800000 1600000>,
- <1 676 200000 399000>,
- <143 777 0 440>, /* IB defined for IPA2X_clk in MHz*/
+ <MSM_BUS_MASTER_IPA MSM_BUS_SLAVE_SNOC_MEM_NOC_GC 780000 1560000>,
+ <MSM_BUS_MASTER_SNOC_GC_MEM_NOC MSM_BUS_SLAVE_EBI_CH0 2592000 5184000>,
+ <MSM_BUS_MASTER_IPA MSM_BUS_SLAVE_OCIMEM 800000 1600000>,
+ <MSM_BUS_MASTER_AMPSS_M0 MSM_BUS_SLAVE_IPA_CFG 200000 399000>,
+ <MSM_BUS_MASTER_IPA_CORE MSM_BUS_SLAVE_IPA_CORE 0 440>,
+
/* TURBO */
- <90 512 2592000 5184000>,
- <90 585 960000 1920000>,
- <1 676 266000 531000>,
- <143 777 0 500>; /* IB defined for IPA clk in MHz*/
+ <MSM_BUS_MASTER_IPA MSM_BUS_SLAVE_SNOC_MEM_NOC_GC 960000 1920000>,
+ <MSM_BUS_MASTER_SNOC_GC_MEM_NOC MSM_BUS_SLAVE_EBI_CH0 2592000 5184000>,
+ <MSM_BUS_MASTER_IPA MSM_BUS_SLAVE_OCIMEM 960000 1920000>,
+ <MSM_BUS_MASTER_AMPSS_M0 MSM_BUS_SLAVE_IPA_CFG 266000 531000>,
+ <MSM_BUS_MASTER_IPA_CORE MSM_BUS_SLAVE_IPA_CORE 0 500>;
+
qcom,bus-vector-names = "MIN", "SVS2", "SVS", "NOMINAL",
"TURBO";
qcom,throughput-threshold = <310 600 1000>;
@@ -1140,6 +1166,33 @@
clock-names = "iface_clk";
};
+ qcom_seecom: qseecom@90000000{
+ compatible = "qcom,qseecom";
+ reg = <0x90000000 0x600000>;
+ reg-names = "secapp-region";
+ qcom,hlos-num-ce-hw-instances = <1>;
+ qcom,hlos-ce-hw-instance = <0>;
+ qcom,qsee-ce-hw-instance = <0>;
+ qcom,no-clock-support;
+ qcom,msm-bus,name = "qseecom-noc";
+ qcom,msm-bus,num-cases = <4>;
+ qcom,msm-bus,num-paths = <1>;
+ clocks = <&clock_gcc GCC_CE1_CLK>,
+ <&clock_gcc GCC_CE1_CLK>,
+ <&clock_gcc GCC_CE1_AHB_CLK>,
+ <&clock_gcc GCC_CE1_AXI_CLK>;
+ qcom,msm-bus,vectors-KBps =
+ <125 512 0 0>,
+ <125 512 20000 40000>,
+ <125 512 30000 80000>,
+ <125 512 40000 100000>;
+ clock-names = "core_clk_src", "core_clk",
+ "iface_clk", "bus_clk";
+ qcom,ce-opp-freq = <171430000>;
+ qcom,qsee-reentrancy-support = <2>;
+ status = "disabled";
+ };
+
qcom_cedev: qcedev@1de0000 {
compatible = "qcom,qcedev";
reg = <0x1de0000 0x20000>,
@@ -1268,6 +1321,7 @@
emac_hw: qcom,emac@00020000 {
compatible = "qcom,emac-dwc-eqos";
qcom,arm-smmu;
+ emac-core-version = <1>;
reg = <0x20000 0x10000>,
<0x36000 0x100>,
<0x3900000 0x300000>;
@@ -1305,6 +1359,8 @@
vreg_emac_phy-supply = <&vreg_emac_phy>;
vreg_rgmii_io_pads-supply = <&vreg_rgmii_io_pads>;
gdsc_emac-supply = <&gdsc_emac>;
+ mboxes = <&qmp_aop 0>;
+ mbox-names = "emac_aop";
io-macro-info {
io-macro-bypass-mode = <0>;
io-interface = "rgmii";
@@ -1323,15 +1379,15 @@
compatible = "qcom,ess-switch-qca83xx";
qcom,switch-access-mode = "mdio";
qcom,ar8327-initvals = <
- 0x0000c 0x7600000 /* PAD6_MODE */
+ 0x00004 0x7600000 /* PAD0_MODE */
0x00008 0x0 /* PAD5_MODE */
0x000e4 0xaa545 /* MAC_POWER_SEL */
0x000e0 0xc74164de /* SGMII_CTRL */
0x0007c 0x4e /* PORT0_STATUS */
0x00094 0x4e /* PORT6_STATUS */
>;
- qcom,link-intr-gpio = <2>;
- qcom,switch-cpu-bmp = <0x40>; /* cpu port bitmap */
+ qcom,link-intr-gpio = <84>;
+ qcom,switch-cpu-bmp = <0x01>; /* cpu port bitmap */
qcom,switch-lan-bmp = <0x3e>; /* lan port bitmap */
qcom,switch-wan-bmp = <0x0>; /* wan port bitmap */
};
diff --git a/arch/arm/configs/msm8909-perf_defconfig b/arch/arm/configs/msm8909-perf_defconfig
index e21e912..d907a0d 100644
--- a/arch/arm/configs/msm8909-perf_defconfig
+++ b/arch/arm/configs/msm8909-perf_defconfig
@@ -1,4 +1,5 @@
CONFIG_LOCALVERSION="-perf"
+CONFIG_POSIX_MQUEUE=y
# CONFIG_AUDITSYSCALL is not set
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
@@ -9,8 +10,6 @@
CONFIG_TASK_IO_ACCOUNTING=y
CONFIG_RCU_EXPERT=y
CONFIG_RCU_FAST_NO_HZ=y
-CONFIG_RCU_NOCB_CPU=y
-CONFIG_RCU_NOCB_CPU_ALL=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_CPU_MAX_BUF_SHIFT=17
@@ -26,8 +25,6 @@
CONFIG_SCHED_TUNE=y
CONFIG_DEFAULT_USE_ENERGY_AWARE=y
CONFIG_BLK_DEV_INITRD=y
-# CONFIG_RD_BZIP2 is not set
-# CONFIG_RD_LZMA is not set
# CONFIG_RD_XZ is not set
# CONFIG_RD_LZO is not set
# CONFIG_RD_LZ4 is not set
@@ -38,7 +35,7 @@
CONFIG_EMBEDDED=y
# CONFIG_COMPAT_BRK is not set
CONFIG_PROFILING=y
-CONFIG_OPROFILE=y
+CONFIG_OPROFILE=m
CONFIG_CC_STACKPROTECTOR_REGULAR=y
CONFIG_ARCH_MMAP_RND_BITS=16
CONFIG_MODULES=y
@@ -55,7 +52,6 @@
CONFIG_SCHED_MC=y
CONFIG_PREEMPT=y
CONFIG_AEABI=y
-CONFIG_HIGHMEM=y
CONFIG_ARM_MODULE_PLTS=y
CONFIG_CMA=y
CONFIG_ZSMALLOC=y
@@ -67,7 +63,6 @@
CONFIG_CPU_IDLE=y
CONFIG_VFP=y
CONFIG_NEON=y
-CONFIG_KERNEL_MODE_NEON=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
CONFIG_PM_AUTOSLEEP=y
CONFIG_PM_WAKELOCKS=y
@@ -88,7 +83,6 @@
CONFIG_IP_PNP_DHCP=y
CONFIG_INET_AH=y
CONFIG_INET_ESP=y
-CONFIG_INET_IPCOMP=y
CONFIG_INET_DIAG_DESTROY=y
CONFIG_IPV6_ROUTER_PREF=y
CONFIG_IPV6_ROUTE_INFO=y
@@ -118,14 +112,12 @@
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
+CONFIG_NETFILTER_XT_TARGET_CT=y
CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
CONFIG_NETFILTER_XT_TARGET_HARDIDLETIMER=y
-CONFIG_NETFILTER_XT_TARGET_LOG=y
CONFIG_NETFILTER_XT_TARGET_MARK=y
CONFIG_NETFILTER_XT_TARGET_NFLOG=y
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
-CONFIG_NETFILTER_XT_TARGET_NOTRACK=y
-CONFIG_NETFILTER_XT_TARGET_TEE=y
CONFIG_NETFILTER_XT_TARGET_TPROXY=y
CONFIG_NETFILTER_XT_TARGET_TRACE=y
CONFIG_NETFILTER_XT_TARGET_SECMARK=y
@@ -157,6 +149,8 @@
CONFIG_NETFILTER_XT_MATCH_TIME=y
CONFIG_NETFILTER_XT_MATCH_U32=y
CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_NF_DUP_IPV4=y
+CONFIG_NF_LOG_IPV4=y
CONFIG_IP_NF_IPTABLES=y
CONFIG_IP_NF_MATCH_AH=y
CONFIG_IP_NF_MATCH_ECN=y
@@ -175,6 +169,8 @@
CONFIG_IP_NF_ARPFILTER=y
CONFIG_IP_NF_ARP_MANGLE=y
CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_NF_DUP_IPV6=y
+CONFIG_NF_LOG_IPV6=y
CONFIG_IP6_NF_IPTABLES=y
CONFIG_IP6_NF_MATCH_RPFILTER=y
CONFIG_IP6_NF_FILTER=y
@@ -191,11 +187,8 @@
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_HTB=y
CONFIG_NET_SCH_PRIO=y
-CONFIG_NET_SCH_MULTIQ=y
-CONFIG_NET_SCH_INGRESS=y
CONFIG_NET_CLS_FW=y
CONFIG_NET_CLS_U32=y
-CONFIG_CLS_U32_MARK=y
CONFIG_NET_CLS_FLOW=y
CONFIG_NET_EMATCH=y
CONFIG_NET_EMATCH_CMP=y
@@ -216,7 +209,6 @@
CONFIG_CFG80211=y
CONFIG_CFG80211_INTERNAL_REGDB=y
CONFIG_RFKILL=y
-CONFIG_NFC_NQ=y
CONFIG_IPC_ROUTER=y
CONFIG_IPC_ROUTER_SECURITY=y
CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
@@ -227,27 +219,17 @@
CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_HDCP_QSEECOM=y
CONFIG_QSEECOM=y
-CONFIG_UID_SYS_STATS=y
CONFIG_MEMORY_STATE_TIME=y
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_SG=y
CONFIG_CHR_DEV_SCH=y
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
CONFIG_SCSI_SCAN_ASYNC=y
-CONFIG_SCSI_UFSHCD=y
-CONFIG_SCSI_UFSHCD_PLATFORM=y
-CONFIG_SCSI_UFS_QCOM=y
-CONFIG_SCSI_UFS_QCOM_ICE=y
-CONFIG_SCSI_UFSHCD_CMD_LOGGING=y
CONFIG_MD=y
CONFIG_BLK_DEV_DM=y
-CONFIG_DM_DEBUG=y
CONFIG_DM_CRYPT=y
CONFIG_DM_UEVENT=y
CONFIG_DM_VERITY=y
-CONFIG_DM_VERITY_FEC=y
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
CONFIG_TUN=y
@@ -268,23 +250,19 @@
CONFIG_CNSS_SDIO=y
CONFIG_CLD_HL_SDIO_CORE=y
CONFIG_INPUT_EVDEV=y
-CONFIG_INPUT_EVBUG=y
+CONFIG_INPUT_EVBUG=m
CONFIG_KEYBOARD_GPIO=y
CONFIG_INPUT_JOYSTICK=y
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_QPNP_POWER_ON=y
CONFIG_INPUT_UINPUT=y
-CONFIG_SERIAL_MSM=y
-CONFIG_SERIAL_MSM_CONSOLE=y
CONFIG_SERIAL_MSM_SMD=y
CONFIG_DIAG_CHAR=y
CONFIG_DIAG_USES_SMD=y
CONFIG_HW_RANDOM=y
-CONFIG_HW_RANDOM_MSM_LEGACY=y
CONFIG_MSM_SMD_PKT=y
CONFIG_MSM_ADSPRPC=y
-CONFIG_MSM_RDBG=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_MSM_V2=y
CONFIG_SPI=y
@@ -346,10 +324,8 @@
CONFIG_MSM_ISPIF=y
CONFIG_QCOM_KGSL=y
CONFIG_FB=y
-CONFIG_FB_VIRTUAL=y
CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_BACKLIGHT_CLASS_DEVICE=y
-CONFIG_LOGO=y
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_DYNAMIC_MINORS=y
@@ -375,10 +351,6 @@
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_MSM=y
CONFIG_USB_STORAGE=y
-CONFIG_USB_DWC3=y
-CONFIG_USB_DWC3_GADGET=y
-CONFIG_NOP_USB_XCEIV=y
-CONFIG_DUAL_ROLE_USB_INTF=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_DEBUG_FILES=y
CONFIG_USB_GADGET_DEBUG_FS=y
@@ -386,8 +358,6 @@
CONFIG_USB_CI13XXX_MSM=y
CONFIG_USB_CONFIGFS=y
CONFIG_USB_CONFIGFS_SERIAL=y
-CONFIG_USB_CONFIGFS_NCM=y
-CONFIG_USB_CONFIGFS_RMNET_BAM=y
CONFIG_USB_CONFIGFS_MASS_STORAGE=y
CONFIG_USB_CONFIGFS_F_FS=y
CONFIG_USB_CONFIGFS_UEVENT=y
@@ -400,7 +370,6 @@
CONFIG_MMC_CLKGATE=y
CONFIG_MMC_BLOCK_MINORS=32
CONFIG_MMC_BLOCK_DEFERRED_RESUME=y
-CONFIG_MMC_TEST=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MMC_SDHCI_MSM=y
@@ -420,8 +389,6 @@
CONFIG_ANDROID_LOW_MEMORY_KILLER=y
CONFIG_ION=y
CONFIG_ION_MSM=y
-CONFIG_IPA=y
-CONFIG_RMNET_IPA=y
CONFIG_SPS=y
CONFIG_SPS_SUPPORT_NDP_BAM=y
CONFIG_QPNP_REVID=y
@@ -443,23 +410,16 @@
CONFIG_MSM_SMEM=y
CONFIG_MSM_SMD=y
CONFIG_MSM_SMD_DEBUG=y
-CONFIG_MSM_GLINK=y
CONFIG_MSM_TZ_SMMU=y
-CONFIG_MSM_GLINK_LOOPBACK_SERVER=y
-CONFIG_MSM_GLINK_SMEM_NATIVE_XPRT=y
-CONFIG_MSM_GLINK_SPI_XPRT=y
CONFIG_TRACER_PKT=y
CONFIG_MSM_SMP2P=y
CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
-CONFIG_MSM_IPC_ROUTER_GLINK_XPRT=y
CONFIG_MSM_QMI_INTERFACE=y
-CONFIG_MSM_GLINK_PKT=y
CONFIG_MSM_SUBSYSTEM_RESTART=y
CONFIG_MSM_PIL=y
CONFIG_MSM_PIL_SSR_GENERIC=y
CONFIG_MSM_PIL_MSS_QDSP6V5=y
CONFIG_MSM_EVENT_TIMER=y
-CONFIG_QTI_RPM_STATS_LOG=y
CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
CONFIG_MSM_BAM_DMUX=y
CONFIG_CNSS_CRYPTO=y
@@ -468,58 +428,30 @@
CONFIG_QTI_MPM=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_STM=y
CONFIG_SENSORS_SSC=y
CONFIG_MSM_TZ_LOG=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_SECURITY=y
CONFIG_QUOTA=y
CONFIG_QUOTA_NETLINK_INTERFACE=y
CONFIG_FUSE_FS=y
-CONFIG_MSDOS_FS=y
CONFIG_VFAT_FS=y
CONFIG_TMPFS=y
-CONFIG_ECRYPT_FS=y
-CONFIG_ECRYPT_FS_MESSAGING=y
CONFIG_SDCARD_FS=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y
CONFIG_PRINTK_TIME=y
CONFIG_DEBUG_INFO=y
CONFIG_FRAME_WARN=2048
-CONFIG_PAGE_OWNER=y
-CONFIG_PAGE_OWNER_ENABLE_DEFAULT=y
CONFIG_MAGIC_SYSRQ=y
-CONFIG_LOCKUP_DETECTOR=y
-# CONFIG_DETECT_HUNG_TASK is not set
CONFIG_WQ_WATCHDOG=y
CONFIG_PANIC_TIMEOUT=5
CONFIG_PANIC_ON_SCHED_BUG=y
CONFIG_PANIC_ON_RT_THROTTLING=y
-CONFIG_SCHEDSTATS=y
-CONFIG_SCHED_STACK_END_CHECK=y
# CONFIG_DEBUG_PREEMPT is not set
-# CONFIG_FTRACE is not set
-CONFIG_LKDTM=y
-CONFIG_PANIC_ON_DATA_CORRUPTION=y
-# CONFIG_ARM_UNWIND is not set
-CONFIG_PID_IN_CONTEXTIDR=y
+CONFIG_FUNCTION_TRACER=y
CONFIG_DEBUG_SET_MODULE_RONX=y
-CONFIG_CORESIGHT=y
-CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y
-CONFIG_CORESIGHT_SINK_TPIU=y
-CONFIG_CORESIGHT_SOURCE_ETM3X=y
-CONFIG_CORESIGHT_REMOTE_ETM=y
-CONFIG_CORESIGHT_REMOTE_ETM_DEFAULT_ENABLE=0
-CONFIG_CORESIGHT_QCOM_REPLICATOR=y
-CONFIG_CORESIGHT_DBGUI=y
-CONFIG_CORESIGHT_STM=y
-CONFIG_CORESIGHT_TPDA=y
-CONFIG_CORESIGHT_TPDM=y
-CONFIG_CORESIGHT_CTI=y
-CONFIG_CORESIGHT_EVENT=y
-CONFIG_CORESIGHT_HWEVENT=y
CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
CONFIG_SECURITY=y
CONFIG_LSM_MMAP_MIN_ADDR=4096
@@ -538,10 +470,4 @@
CONFIG_CRYPTO_DEV_QCEDEV=y
CONFIG_CRYPTO_DEV_OTA_CRYPTO=y
CONFIG_CRYPTO_DEV_QCOM_ICE=y
-CONFIG_ARM_CRYPTO=y
-CONFIG_CRYPTO_SHA1_ARM_NEON=y
-CONFIG_CRYPTO_SHA2_ARM_CE=y
-CONFIG_CRYPTO_AES_ARM_BS=y
-CONFIG_CRYPTO_AES_ARM_CE=y
-CONFIG_XZ_DEC=y
CONFIG_QMI_ENCDEC=y
diff --git a/arch/arm/configs/msm8909_defconfig b/arch/arm/configs/msm8909_defconfig
index 8c3b56b..a87599f 100644
--- a/arch/arm/configs/msm8909_defconfig
+++ b/arch/arm/configs/msm8909_defconfig
@@ -1,3 +1,4 @@
+CONFIG_POSIX_MQUEUE=y
# CONFIG_AUDITSYSCALL is not set
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
@@ -372,12 +373,8 @@
CONFIG_USB_EHCI_MSM=y
CONFIG_USB_ACM=y
CONFIG_USB_STORAGE=y
-CONFIG_USB_DWC3=y
-CONFIG_USB_DWC3_GADGET=y
CONFIG_USB_SERIAL=y
CONFIG_USB_EHSET_TEST_FIXTURE=y
-CONFIG_NOP_USB_XCEIV=y
-CONFIG_DUAL_ROLE_USB_INTF=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_DEBUG_FILES=y
CONFIG_USB_GADGET_DEBUG_FS=y
@@ -507,7 +504,6 @@
CONFIG_DEBUG_OBJECTS_WORK=y
CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y
-CONFIG_SLUB_DEBUG_ON=y
CONFIG_DEBUG_KMEMLEAK=y
CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=4000
CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y
diff --git a/arch/arm/configs/msm8909w-perf_defconfig b/arch/arm/configs/msm8909w-perf_defconfig
index 7994ad8..3094af9 100644
--- a/arch/arm/configs/msm8909w-perf_defconfig
+++ b/arch/arm/configs/msm8909w-perf_defconfig
@@ -1,6 +1,5 @@
# CONFIG_FHANDLE is not set
CONFIG_AUDIT=y
-# CONFIG_AUDITSYSCALL is not set
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_IRQ_TIME_ACCOUNTING=y
@@ -28,12 +27,17 @@
CONFIG_DEFAULT_USE_ENERGY_AWARE=y
CONFIG_RELAY=y
CONFIG_BLK_DEV_INITRD=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_RD_XZ is not set
+# CONFIG_RD_LZO is not set
+# CONFIG_RD_LZ4 is not set
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_KALLSYMS_ALL=y
CONFIG_BPF_SYSCALL=y
CONFIG_EMBEDDED=y
CONFIG_PROFILING=y
-CONFIG_OPROFILE=y
+CONFIG_OPROFILE=m
CONFIG_CC_STACKPROTECTOR_REGULAR=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
@@ -182,11 +186,8 @@
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_HTB=y
CONFIG_NET_SCH_PRIO=y
-CONFIG_NET_SCH_MULTIQ=y
-CONFIG_NET_SCH_INGRESS=y
CONFIG_NET_CLS_FW=y
CONFIG_NET_CLS_U32=y
-CONFIG_CLS_U32_MARK=y
CONFIG_NET_CLS_FLOW=y
CONFIG_NET_EMATCH=y
CONFIG_NET_EMATCH_CMP=y
@@ -225,19 +226,15 @@
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_SG=y
CONFIG_CHR_DEV_SCH=y
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
CONFIG_SCSI_SCAN_ASYNC=y
CONFIG_SCSI_UFSHCD=y
CONFIG_SCSI_UFSHCD_PLATFORM=y
CONFIG_SCSI_UFS_QCOM=y
-CONFIG_SCSI_UFSHCD_CMD_LOGGING=y
CONFIG_MD=y
CONFIG_BLK_DEV_DM=y
CONFIG_DM_CRYPT=y
CONFIG_DM_UEVENT=y
CONFIG_DM_VERITY=y
-CONFIG_DM_VERITY_FEC=y
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
CONFIG_TUN=y
@@ -336,27 +333,11 @@
CONFIG_FB_MSM_MDSS_MDP3=y
CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_BACKLIGHT_CLASS_DEVICE=y
-CONFIG_LOGO=y
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_DYNAMIC_MINORS=y
CONFIG_SND_SOC=y
CONFIG_UHID=y
-CONFIG_HID_A4TECH=y
-CONFIG_HID_APPLE=y
-CONFIG_HID_BELKIN=y
-CONFIG_HID_CHERRY=y
-CONFIG_HID_CHICONY=y
-CONFIG_HID_CYPRESS=y
-CONFIG_HID_ELECOM=y
-CONFIG_HID_EZKEY=y
-CONFIG_HID_KENSINGTON=y
-CONFIG_HID_LOGITECH=y
-CONFIG_HID_MAGICMOUSE=y
-CONFIG_HID_MICROSOFT=y
-CONFIG_HID_MONTEREY=y
-CONFIG_HID_MULTITOUCH=y
-CONFIG_DUAL_ROLE_USB_INTF=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_DEBUG_FILES=y
CONFIG_USB_GADGET_DEBUG_FS=y
@@ -364,9 +345,6 @@
CONFIG_USB_CI13XXX_MSM=y
CONFIG_USB_CONFIGFS=y
CONFIG_USB_CONFIGFS_SERIAL=y
-CONFIG_USB_CONFIGFS_ACM=y
-CONFIG_USB_CONFIGFS_NCM=y
-CONFIG_USB_CONFIGFS_ECM=y
CONFIG_USB_CONFIGFS_RMNET_BAM=y
CONFIG_USB_CONFIGFS_EEM=y
CONFIG_USB_CONFIGFS_MASS_STORAGE=y
@@ -451,6 +429,7 @@
CONFIG_MSM_EVENT_TIMER=y
CONFIG_QTI_RPM_STATS_LOG=y
CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
+CONFIG_MEM_SHARE_QMI_SERVICE=y
CONFIG_MSM_BAM_DMUX=y
CONFIG_MSM_GLINK_BGCOM_XPRT=y
CONFIG_MSM_BGCOM_INTERFACE=y
@@ -488,23 +467,15 @@
CONFIG_PRINTK_TIME=y
CONFIG_DEBUG_INFO=y
CONFIG_FRAME_WARN=2048
-CONFIG_PAGE_OWNER=y
-CONFIG_PAGE_OWNER_ENABLE_DEFAULT=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_LOCKUP_DETECTOR=y
-# CONFIG_DETECT_HUNG_TASK is not set
+CONFIG_PAGE_EXTENSION=y
+CONFIG_PANIC_ON_RECURSIVE_FAULT=y
CONFIG_WQ_WATCHDOG=y
CONFIG_PANIC_TIMEOUT=5
CONFIG_PANIC_ON_SCHED_BUG=y
CONFIG_PANIC_ON_RT_THROTTLING=y
-CONFIG_SCHEDSTATS=y
-CONFIG_SCHED_STACK_END_CHECK=y
# CONFIG_DEBUG_PREEMPT is not set
CONFIG_IPC_LOGGING=y
-CONFIG_LKDTM=y
-CONFIG_PANIC_ON_DATA_CORRUPTION=y
-# CONFIG_ARM_UNWIND is not set
-CONFIG_PID_IN_CONTEXTIDR=y
+CONFIG_DEBUG_USER=y
CONFIG_DEBUG_SET_MODULE_RONX=y
CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
CONFIG_SECURITY=y
diff --git a/arch/arm/configs/msm8909w_defconfig b/arch/arm/configs/msm8909w_defconfig
index c99d05f..2e545d8 100644
--- a/arch/arm/configs/msm8909w_defconfig
+++ b/arch/arm/configs/msm8909w_defconfig
@@ -26,6 +26,7 @@
CONFIG_SCHED_AUTOGROUP=y
CONFIG_SCHED_TUNE=y
CONFIG_DEFAULT_USE_ENERGY_AWARE=y
+CONFIG_RELAY=y
CONFIG_BLK_DEV_INITRD=y
# CONFIG_RD_BZIP2 is not set
# CONFIG_RD_LZMA is not set
@@ -36,7 +37,6 @@
CONFIG_KALLSYMS_ALL=y
CONFIG_BPF_SYSCALL=y
CONFIG_EMBEDDED=y
-# CONFIG_SLUB_DEBUG is not set
CONFIG_PROFILING=y
CONFIG_OPROFILE=m
CONFIG_CC_STACKPROTECTOR_REGULAR=y
@@ -323,8 +323,9 @@
CONFIG_FB_MSM_MDSS_SPI_PANEL=y
CONFIG_FB_MSM_MDSS_MDP3=y
CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
CONFIG_BACKLIGHT_CLASS_DEVICE=y
-CONFIG_LOGO=y
+# CONFIG_BACKLIGHT_GENERIC is not set
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_DYNAMIC_MINORS=y
@@ -357,7 +358,6 @@
CONFIG_MMC_CLKGATE=y
CONFIG_MMC_BLOCK_MINORS=32
CONFIG_MMC_BLOCK_DEFERRED_RESUME=y
-CONFIG_MMC_TEST=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MMC_SDHCI_MSM=y
@@ -421,6 +421,7 @@
CONFIG_MSM_EVENT_TIMER=y
CONFIG_QTI_RPM_STATS_LOG=y
CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
+CONFIG_MEM_SHARE_QMI_SERVICE=y
CONFIG_MSM_BAM_DMUX=y
CONFIG_MSM_GLINK_BGCOM_XPRT=y
CONFIG_MSM_BGCOM_INTERFACE=y
@@ -455,27 +456,25 @@
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y
CONFIG_PRINTK_TIME=y
+CONFIG_MESSAGE_LOGLEVEL_DEFAULT=6
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_INFO=y
CONFIG_FRAME_WARN=2048
CONFIG_PAGE_OWNER=y
CONFIG_PAGE_OWNER_ENABLE_DEFAULT=y
-CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_PAGEALLOC=y
+CONFIG_SLUB_DEBUG_PANIC_ON=y
CONFIG_DEBUG_PAGEALLOC_ENABLE_DEFAULT=y
-CONFIG_DEBUG_KMEMLEAK=y
-CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=4000
-CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y
CONFIG_DEBUG_STACK_USAGE=y
CONFIG_DEBUG_MEMORY_INIT=y
CONFIG_LOCKUP_DETECTOR=y
# CONFIG_DETECT_HUNG_TASK is not set
CONFIG_WQ_WATCHDOG=y
-CONFIG_PANIC_TIMEOUT=5
+CONFIG_PANIC_ON_OOPS=y
+CONFIG_PANIC_TIMEOUT=-1
CONFIG_PANIC_ON_SCHED_BUG=y
CONFIG_PANIC_ON_RT_THROTTLING=y
CONFIG_SCHEDSTATS=y
-CONFIG_SCHED_STACK_END_CHECK=y
CONFIG_DEBUG_SPINLOCK=y
CONFIG_DEBUG_MUTEXES=y
CONFIG_DEBUG_ATOMIC_SLEEP=y
@@ -488,12 +487,9 @@
CONFIG_QCOM_RTB=y
CONFIG_QCOM_RTB_SEPARATE_CPUS=y
CONFIG_FUNCTION_TRACER=y
-CONFIG_IRQSOFF_TRACER=y
-CONFIG_PREEMPT_TRACER=y
-CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_TRACER_SNAPSHOT=y
+CONFIG_TRACER_SNAPSHOT_PER_CPU_SWAP=y
CONFIG_CPU_FREQ_SWITCH_PROFILER=y
-CONFIG_LKDTM=y
-CONFIG_MEMTEST=y
CONFIG_PANIC_ON_DATA_CORRUPTION=y
CONFIG_DEBUG_USER=y
CONFIG_PID_IN_CONTEXTIDR=y
@@ -507,8 +503,6 @@
CONFIG_CORESIGHT_QCOM_REPLICATOR=y
CONFIG_CORESIGHT_DBGUI=y
CONFIG_CORESIGHT_STM=y
-CONFIG_CORESIGHT_TPDA=y
-CONFIG_CORESIGHT_TPDM=y
CONFIG_CORESIGHT_CTI=y
CONFIG_CORESIGHT_EVENT=y
CONFIG_CORESIGHT_HWEVENT=y
diff --git a/arch/arm/configs/msm8937-perf_defconfig b/arch/arm/configs/msm8937-perf_defconfig
index ec018d8..040ce14 100644
--- a/arch/arm/configs/msm8937-perf_defconfig
+++ b/arch/arm/configs/msm8937-perf_defconfig
@@ -341,7 +341,6 @@
CONFIG_SPI_SPIDEV=y
CONFIG_SLIMBUS_MSM_NGD=y
CONFIG_SPMI=y
-CONFIG_SPMI_MSM_PMIC_ARB_DEBUG=y
CONFIG_PINCTRL_MSM8937=y
CONFIG_PINCTRL_MSM8917=y
CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
@@ -382,10 +381,7 @@
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_PROXY_CONSUMER=y
CONFIG_REGULATOR_CPR=y
-CONFIG_REGULATOR_CPR4_APSS=y
-CONFIG_REGULATOR_CPRH_KBSS=y
CONFIG_REGULATOR_MEM_ACC=y
-CONFIG_REGULATOR_MSM_GFX_LDO=y
CONFIG_REGULATOR_QPNP_LABIBB=y
CONFIG_REGULATOR_QPNP_LCDB=y
CONFIG_REGULATOR_QPNP=y
@@ -400,9 +396,7 @@
CONFIG_USB_VIDEO_CLASS=y
CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_MSM_CAMERA=y
-CONFIG_MSM_CAMERA_DEBUG=y
CONFIG_MSMB_CAMERA=y
-CONFIG_MSMB_CAMERA_DEBUG=y
CONFIG_MSM_CAMERA_SENSOR=y
CONFIG_MSM_CPP=y
CONFIG_MSM_CCI=y
@@ -568,7 +562,6 @@
CONFIG_MSM_PIL=y
CONFIG_MSM_PIL_SSR_GENERIC=y
CONFIG_MSM_PIL_MSS_QDSP6V5=y
-CONFIG_ICNSS=y
CONFIG_MSM_PERFORMANCE=y
CONFIG_MSM_EVENT_TIMER=y
CONFIG_MSM_AVTIMER=y
@@ -592,6 +585,7 @@
CONFIG_PWM=y
CONFIG_PWM_QPNP=y
CONFIG_PWM_QTI_LPG=y
+CONFIG_QCOM_SHOW_RESUME_IRQ=y
CONFIG_QTI_MPM=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
@@ -599,8 +593,12 @@
CONFIG_MSM_TZ_LOG=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_SECURITY=y
+CONFIG_EXT4_ENCRYPTION=y
+CONFIG_EXT4_FS_ENCRYPTION=y
+CONFIG_EXT4_FS_ICE_ENCRYPTION=y
CONFIG_F2FS_FS=y
CONFIG_F2FS_FS_SECURITY=y
+CONFIG_F2FS_FS_ENCRYPTION=y
CONFIG_QUOTA=y
CONFIG_QUOTA_NETLINK_INTERFACE=y
CONFIG_QFMT_V2=y
@@ -634,13 +632,13 @@
CONFIG_CORESIGHT_CTI=y
CONFIG_CORESIGHT_EVENT=y
CONFIG_CORESIGHT_HWEVENT=y
+CONFIG_PFK=y
CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
CONFIG_SECURITY=y
CONFIG_LSM_MMAP_MIN_ADDR=4096
CONFIG_HARDENED_USERCOPY=y
CONFIG_SECURITY_SELINUX=y
CONFIG_SECURITY_SMACK=y
-CONFIG_CRYPTO_CTR=y
CONFIG_CRYPTO_XCBC=y
CONFIG_CRYPTO_MD4=y
CONFIG_CRYPTO_TWOFISH=y
diff --git a/arch/arm/configs/msm8937_defconfig b/arch/arm/configs/msm8937_defconfig
index 2fb806d..a33bdbd 100644
--- a/arch/arm/configs/msm8937_defconfig
+++ b/arch/arm/configs/msm8937_defconfig
@@ -348,7 +348,6 @@
CONFIG_SPI_SPIDEV=y
CONFIG_SLIMBUS_MSM_NGD=y
CONFIG_SPMI=y
-CONFIG_SPMI_MSM_PMIC_ARB_DEBUG=y
CONFIG_PINCTRL_MSM8937=y
CONFIG_PINCTRL_MSM8917=y
CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
@@ -389,10 +388,7 @@
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_PROXY_CONSUMER=y
CONFIG_REGULATOR_CPR=y
-CONFIG_REGULATOR_CPR4_APSS=y
-CONFIG_REGULATOR_CPRH_KBSS=y
CONFIG_REGULATOR_MEM_ACC=y
-CONFIG_REGULATOR_MSM_GFX_LDO=y
CONFIG_REGULATOR_QPNP_LABIBB=y
CONFIG_REGULATOR_QPNP_LCDB=y
CONFIG_REGULATOR_QPNP=y
@@ -565,7 +561,6 @@
CONFIG_MSM_L2_SPM=y
CONFIG_MSM_BOOT_STATS=y
CONFIG_MSM_CORE_HANG_DETECT=y
-CONFIG_MSM_GLADIATOR_HANG_DETECT=y
CONFIG_QCOM_WATCHDOG_V2=y
CONFIG_QCOM_MEMORY_DUMP_V2=y
CONFIG_MSM_DEBUG_LAR_UNLOCK=y
@@ -586,7 +581,6 @@
CONFIG_MSM_PIL=y
CONFIG_MSM_PIL_SSR_GENERIC=y
CONFIG_MSM_PIL_MSS_QDSP6V5=y
-CONFIG_ICNSS=y
CONFIG_MSM_PERFORMANCE=y
CONFIG_MSM_EVENT_TIMER=y
CONFIG_MSM_AVTIMER=y
@@ -619,8 +613,12 @@
CONFIG_MSM_TZ_LOG=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_SECURITY=y
+CONFIG_EXT4_ENCRYPTION=y
+CONFIG_EXT4_FS_ENCRYPTION=y
+CONFIG_EXT4_FS_ICE_ENCRYPTION=y
CONFIG_F2FS_FS=y
CONFIG_F2FS_FS_SECURITY=y
+CONFIG_F2FS_FS_ENCRYPTION=y
CONFIG_QUOTA=y
CONFIG_QUOTA_NETLINK_INTERFACE=y
CONFIG_QFMT_V2=y
@@ -650,7 +648,6 @@
CONFIG_DEBUG_OBJECTS_WORK=y
CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y
-CONFIG_SLUB_DEBUG_ON=y
CONFIG_DEBUG_KMEMLEAK=y
CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=4000
CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y
@@ -701,13 +698,13 @@
CONFIG_CORESIGHT_CTI=y
CONFIG_CORESIGHT_EVENT=y
CONFIG_CORESIGHT_HWEVENT=y
+CONFIG_PFK=y
CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
CONFIG_SECURITY=y
CONFIG_LSM_MMAP_MIN_ADDR=4096
CONFIG_HARDENED_USERCOPY=y
CONFIG_SECURITY_SELINUX=y
CONFIG_SECURITY_SMACK=y
-CONFIG_CRYPTO_CTR=y
CONFIG_CRYPTO_XCBC=y
CONFIG_CRYPTO_MD4=y
CONFIG_CRYPTO_TWOFISH=y
diff --git a/arch/arm/configs/msm8953-perf_defconfig b/arch/arm/configs/msm8953-perf_defconfig
index 1f94d63..3d716a6 100644
--- a/arch/arm/configs/msm8953-perf_defconfig
+++ b/arch/arm/configs/msm8953-perf_defconfig
@@ -64,6 +64,7 @@
CONFIG_PREEMPT=y
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
+CONFIG_ARM_MODULE_PLTS=y
CONFIG_CMA=y
CONFIG_CMA_DEBUGFS=y
CONFIG_ZSMALLOC=y
@@ -309,10 +310,9 @@
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_FT5X06=y
CONFIG_TOUCHSCREEN_GEN_VKEYS=y
-CONFIG_TOUCHSCREEN_HIMAX_CHIPSET=y
-CONFIG_TOUCHSCREEN_HIMAX_I2C=y
-CONFIG_TOUCHSCREEN_HIMAX_DEBUG=y
-CONFIG_HMX_DB=y
+CONFIG_TOUCHSCREEN_GT9XX_v28=y
+CONFIG_TOUCHSCREEN_GT9XX_UPDATE=y
+CONFIG_TOUCHSCREEN_GT9XX_TOOL=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_HBTP_INPUT=y
CONFIG_INPUT_QPNP_POWER_ON=y
@@ -604,6 +604,8 @@
CONFIG_EXT4_ENCRYPTION=y
CONFIG_EXT4_FS_ENCRYPTION=y
CONFIG_EXT4_FS_ICE_ENCRYPTION=y
+CONFIG_F2FS_FS=y
+CONFIG_F2FS_FS_SECURITY=y
CONFIG_QUOTA=y
CONFIG_QUOTA_NETLINK_INTERFACE=y
CONFIG_QFMT_V2=y
diff --git a/arch/arm/configs/msm8953_defconfig b/arch/arm/configs/msm8953_defconfig
index b1f5cb9..34f9122 100644
--- a/arch/arm/configs/msm8953_defconfig
+++ b/arch/arm/configs/msm8953_defconfig
@@ -67,6 +67,7 @@
CONFIG_PREEMPT=y
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
+CONFIG_ARM_MODULE_PLTS=y
CONFIG_CMA=y
CONFIG_CMA_DEBUGFS=y
CONFIG_ZSMALLOC=y
@@ -314,10 +315,9 @@
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_FT5X06=y
CONFIG_TOUCHSCREEN_GEN_VKEYS=y
-CONFIG_TOUCHSCREEN_HIMAX_CHIPSET=y
-CONFIG_TOUCHSCREEN_HIMAX_I2C=y
-CONFIG_TOUCHSCREEN_HIMAX_DEBUG=y
-CONFIG_HMX_DB=y
+CONFIG_TOUCHSCREEN_GT9XX_v28=y
+CONFIG_TOUCHSCREEN_GT9XX_UPDATE=y
+CONFIG_TOUCHSCREEN_GT9XX_TOOL=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_HBTP_INPUT=y
CONFIG_INPUT_QPNP_POWER_ON=y
@@ -567,7 +567,6 @@
CONFIG_MSM_L2_SPM=y
CONFIG_MSM_BOOT_STATS=y
CONFIG_MSM_CORE_HANG_DETECT=y
-CONFIG_MSM_GLADIATOR_HANG_DETECT=y
CONFIG_QCOM_WATCHDOG_V2=y
CONFIG_QCOM_MEMORY_DUMP_V2=y
CONFIG_MSM_DEBUG_LAR_UNLOCK=y
@@ -622,6 +621,8 @@
CONFIG_EXT4_ENCRYPTION=y
CONFIG_EXT4_FS_ENCRYPTION=y
CONFIG_EXT4_FS_ICE_ENCRYPTION=y
+CONFIG_F2FS_FS=y
+CONFIG_F2FS_FS_SECURITY=y
CONFIG_QUOTA=y
CONFIG_QUOTA_NETLINK_INTERFACE=y
CONFIG_QFMT_V2=y
diff --git a/arch/arm/configs/sdm670_defconfig b/arch/arm/configs/sdm670_defconfig
new file mode 100644
index 0000000..082a53a
--- /dev/null
+++ b/arch/arm/configs/sdm670_defconfig
@@ -0,0 +1,622 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_FHANDLE is not set
+CONFIG_AUDIT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IRQ_TIME_ACCOUNTING=y
+CONFIG_SCHED_WALT=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+CONFIG_RCU_EXPERT=y
+CONFIG_RCU_FAST_NO_HZ=y
+CONFIG_RCU_NOCB_CPU=y
+CONFIG_RCU_NOCB_CPU_ALL=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_CPU_MAX_BUF_SHIFT=17
+CONFIG_CGROUP_DEBUG=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_SCHEDTUNE=y
+CONFIG_BLK_CGROUP=y
+CONFIG_DEBUG_BLK_CGROUP=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_CGROUP_BPF=y
+CONFIG_SCHED_CORE_CTL=y
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_SCHED_AUTOGROUP=y
+CONFIG_SCHED_TUNE=y
+CONFIG_DEFAULT_USE_ENERGY_AWARE=y
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_RD_XZ is not set
+# CONFIG_RD_LZO is not set
+# CONFIG_RD_LZ4 is not set
+CONFIG_KALLSYMS_ALL=y
+CONFIG_BPF_SYSCALL=y
+# CONFIG_AIO is not set
+# CONFIG_MEMBARRIER is not set
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_PROFILING=y
+CONFIG_CC_STACKPROTECTOR_REGULAR=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SIG=y
+CONFIG_MODULE_SIG_FORCE=y
+CONFIG_MODULE_SIG_SHA512=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_CFQ_GROUP_IOSCHED=y
+CONFIG_ARCH_QCOM=y
+CONFIG_ARCH_SDM670=y
+CONFIG_PCI_MSM=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=8
+CONFIG_ARM_PSCI=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
+CONFIG_ARM_MODULE_PLTS=y
+CONFIG_CLEANCACHE=y
+CONFIG_CMA=y
+CONFIG_CMA_DEBUGFS=y
+CONFIG_ZSMALLOC=y
+CONFIG_BALANCE_ANON_FILE_RECLAIM=y
+CONFIG_SECCOMP=y
+CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE=y
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_BOOST=y
+CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_KERNEL_MODE_NEON=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_WAKELOCKS_LIMIT=0
+# CONFIG_PM_WAKELOCKS_GC is not set
+CONFIG_PM_DEBUG=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_XFRM_STATISTICS=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=y
+CONFIG_INET_DIAG_DESTROY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_NETFILTER=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
+CONFIG_NETFILTER_XT_TARGET_HARDIDLETIMER=y
+CONFIG_NETFILTER_XT_TARGET_LOG=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFLOG=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=y
+CONFIG_NETFILTER_XT_TARGET_TEE=y
+CONFIG_NETFILTER_XT_TARGET_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_TRACE=y
+CONFIG_NETFILTER_XT_TARGET_SECMARK=y
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_DSCP=y
+CONFIG_NETFILTER_XT_MATCH_ESP=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+# CONFIG_NETFILTER_XT_MATCH_L2TP is not set
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_RPFILTER=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_SECURITY=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_MATCH_RPFILTER=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
+CONFIG_BRIDGE_NF_EBTABLES=y
+CONFIG_BRIDGE_EBT_BROUTE=y
+CONFIG_L2TP=y
+CONFIG_L2TP_DEBUGFS=y
+CONFIG_L2TP_V3=y
+CONFIG_L2TP_IP=y
+CONFIG_L2TP_ETH=y
+CONFIG_BRIDGE=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_SCH_PRIO=y
+CONFIG_NET_SCH_MULTIQ=y
+CONFIG_NET_SCH_INGRESS=y
+CONFIG_NET_CLS_FW=y
+CONFIG_NET_CLS_U32=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_FLOW=y
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_CMP=y
+CONFIG_NET_EMATCH_NBYTE=y
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_EMATCH_META=y
+CONFIG_NET_EMATCH_TEXT=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_GACT=y
+CONFIG_NET_ACT_MIRRED=y
+CONFIG_NET_ACT_SKBEDIT=y
+CONFIG_DNS_RESOLVER=y
+CONFIG_RMNET_DATA=y
+CONFIG_RMNET_DATA_FC=y
+CONFIG_RMNET_DATA_DEBUG_PKT=y
+CONFIG_BT=y
+CONFIG_MSM_BT_POWER=y
+CONFIG_CFG80211=y
+CONFIG_CFG80211_INTERNAL_REGDB=y
+# CONFIG_CFG80211_CRDA_SUPPORT is not set
+CONFIG_RFKILL=y
+CONFIG_IPC_ROUTER=y
+CONFIG_IPC_ROUTER_SECURITY=y
+CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
+CONFIG_AQT_REGMAP=y
+CONFIG_REGMAP_ALLOW_WRITE_DEBUGFS=y
+CONFIG_DMA_CMA=y
+CONFIG_ZRAM=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_QSEECOM=y
+CONFIG_UID_SYS_STATS=y
+CONFIG_MEMORY_STATE_TIME=y
+CONFIG_QPNP_MISC=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_SCSI_UFSHCD=y
+CONFIG_SCSI_UFSHCD_PLATFORM=y
+CONFIG_SCSI_UFS_QCOM=y
+CONFIG_SCSI_UFS_QCOM_ICE=y
+CONFIG_SCSI_UFSHCD_CMD_LOGGING=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_CRYPT=y
+CONFIG_DM_REQ_CRYPT=y
+CONFIG_DM_UEVENT=y
+CONFIG_DM_VERITY=y
+CONFIG_DM_VERITY_FEC=y
+CONFIG_NETDEVICES=y
+CONFIG_BONDING=y
+CONFIG_DUMMY=y
+CONFIG_TUN=y
+CONFIG_PPP=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_MPPE=y
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPPOE=y
+CONFIG_PPPOL2TP=y
+CONFIG_PPPOLAC=y
+CONFIG_PPPOPNS=y
+CONFIG_PPP_ASYNC=y
+CONFIG_PPP_SYNC_TTY=y
+CONFIG_USB_USBNET=y
+CONFIG_WCNSS_MEM_PRE_ALLOC=y
+CONFIG_CLD_LL_CORE=y
+CONFIG_CNSS_GENL=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_QPNP_POWER_ON=y
+CONFIG_INPUT_UINPUT=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_MSM_GENI=y
+CONFIG_SERIAL_MSM_GENI_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_MSM_LEGACY=y
+CONFIG_MSM_ADSPRPC=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_QCOM_GENI=y
+CONFIG_SPI=y
+CONFIG_SPI_QUP=y
+CONFIG_SPI_QCOM_GENI=y
+CONFIG_SPI_SPIDEV=y
+CONFIG_SLIMBUS_MSM_NGD=y
+CONFIG_SPMI=y
+CONFIG_SPMI_MSM_PMIC_ARB_DEBUG=y
+CONFIG_PINCTRL_SDM670=y
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_RESET_QCOM=y
+CONFIG_QCOM_DLOAD_MODE=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_QPNP_FG_GEN3=y
+CONFIG_SMB1355_SLAVE_CHARGER=y
+CONFIG_QPNP_SMB2=y
+CONFIG_QPNP_QNOVO=y
+CONFIG_SMB1390_CHARGE_PUMP=y
+CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
+CONFIG_THERMAL=y
+CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE=y
+CONFIG_THERMAL_GOV_STEP_WISE=y
+CONFIG_THERMAL_GOV_LOW_LIMITS=y
+CONFIG_CPU_THERMAL=y
+CONFIG_DEVFREQ_THERMAL=y
+CONFIG_QCOM_SPMI_TEMP_ALARM=y
+CONFIG_THERMAL_QPNP=y
+CONFIG_THERMAL_QPNP_ADC_TM=y
+CONFIG_THERMAL_TSENS=y
+CONFIG_MSM_BCL_PERIPHERAL_CTL=y
+CONFIG_QTI_THERMAL_LIMITS_DCVS=y
+CONFIG_MFD_I2C_PMIC=y
+CONFIG_MFD_SPMI_PMIC=y
+CONFIG_MFD_SYSCON=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_PROXY_CONSUMER=y
+CONFIG_REGULATOR_QPNP_LABIBB=y
+CONFIG_REGULATOR_QPNP_LCDB=y
+CONFIG_REGULATOR_QPNP_OLEDB=y
+CONFIG_REGULATOR_QPNP=y
+CONFIG_REGULATOR_REFGEN=y
+CONFIG_REGULATOR_RPMH=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_ADV_DEBUG=y
+CONFIG_VIDEO_FIXED_MINOR_RANGES=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_MSM_SDE_ROTATOR=y
+CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y
+CONFIG_QCOM_KGSL=y
+CONFIG_DRM=y
+CONFIG_DRM_SDE_EVTLOG_DEBUG=y
+CONFIG_DRM_SDE_RSC=y
+CONFIG_DRM_LT_LT9611=y
+CONFIG_FB_VIRTUAL=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_DYNAMIC_MINORS=y
+CONFIG_SND_USB_AUDIO=y
+CONFIG_SND_USB_AUDIO_QMI=y
+CONFIG_SND_SOC=y
+CONFIG_UHID=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_MICROSOFT=y
+CONFIG_USB=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_DWC3=y
+CONFIG_USB_DWC3_MSM=y
+CONFIG_USB_ISP1760=y
+CONFIG_USB_ISP1760_HOST_ROLE=y
+CONFIG_USB_PD_POLICY=y
+CONFIG_QPNP_USB_PDPHY=y
+CONFIG_USB_EHSET_TEST_FIXTURE=y
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_DUAL_ROLE_USB_INTF=y
+CONFIG_USB_MSM_SSPHY_QMP=y
+CONFIG_MSM_QUSB_PHY=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_VBUS_DRAW=500
+CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_NCM=y
+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
+CONFIG_USB_CONFIGFS_F_FS=y
+CONFIG_USB_CONFIGFS_F_MTP=y
+CONFIG_USB_CONFIGFS_F_PTP=y
+CONFIG_USB_CONFIGFS_F_ACC=y
+CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y
+CONFIG_USB_CONFIGFS_UEVENT=y
+CONFIG_USB_CONFIGFS_F_MIDI=y
+CONFIG_USB_CONFIGFS_F_HID=y
+CONFIG_USB_CONFIGFS_F_DIAG=y
+CONFIG_USB_CONFIGFS_F_CDEV=y
+CONFIG_USB_CONFIGFS_F_CCID=y
+CONFIG_USB_CONFIGFS_F_GSI=y
+CONFIG_USB_CONFIGFS_F_QDSS=y
+CONFIG_MMC=y
+CONFIG_MMC_CLKGATE=y
+CONFIG_MMC_BLOCK_MINORS=32
+CONFIG_MMC_BLOCK_DEFERRED_RESUME=y
+CONFIG_MMC_TEST=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_MSM=y
+CONFIG_MMC_SDHCI_MSM_ICE=y
+CONFIG_MMC_CQ_HCI=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_QPNP=y
+CONFIG_LEDS_QPNP_FLASH_V2=y
+CONFIG_LEDS_QPNP_WLED=y
+CONFIG_LEDS_QPNP_HAPTICS=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_EDAC=y
+CONFIG_EDAC_MM_EDAC=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_QPNP=y
+CONFIG_DMADEVICES=y
+CONFIG_UIO=y
+CONFIG_UIO_MSM_SHAREDMEM=y
+CONFIG_STAGING=y
+CONFIG_ASHMEM=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_ION=y
+CONFIG_ION_MSM=y
+CONFIG_GSI=y
+CONFIG_IPA3=y
+CONFIG_RMNET_IPA3=y
+CONFIG_RNDIS_IPA=y
+CONFIG_IPA_UT=y
+CONFIG_SPS=y
+CONFIG_SPS_SUPPORT_NDP_BAM=y
+CONFIG_QPNP_COINCELL=y
+CONFIG_QPNP_REVID=y
+CONFIG_USB_BAM=y
+CONFIG_QCOM_GENI_SE=y
+CONFIG_MSM_GCC_SDM845=y
+CONFIG_MSM_VIDEOCC_SDM845=y
+CONFIG_MSM_CAMCC_SDM845=y
+CONFIG_MSM_DISPCC_SDM845=y
+CONFIG_CLOCK_QPNP_DIV=y
+CONFIG_MSM_CLK_RPMH=y
+CONFIG_CLOCK_CPU_OSM=y
+CONFIG_MSM_GPUCC_SDM845=y
+CONFIG_MSM_CLK_AOP_QMP=y
+CONFIG_QCOM_MDSS_PLL=y
+CONFIG_REMOTE_SPINLOCK_MSM=y
+CONFIG_MSM_QMP=y
+CONFIG_ARM_SMMU=y
+CONFIG_QCOM_LAZY_MAPPING=y
+CONFIG_IOMMU_DEBUG=y
+CONFIG_IOMMU_DEBUG_TRACKING=y
+CONFIG_IOMMU_TESTS=y
+CONFIG_QCOM_CPUSS_DUMP=y
+CONFIG_QCOM_RUN_QUEUE_STATS=y
+CONFIG_QCOM_LLCC=y
+CONFIG_QCOM_SDM670_LLCC=y
+CONFIG_QCOM_LLCC_PERFMON=m
+CONFIG_MSM_SERVICE_LOCATOR=y
+CONFIG_MSM_SERVICE_NOTIFIER=y
+CONFIG_MSM_BOOT_STATS=y
+CONFIG_MSM_CORE_HANG_DETECT=y
+CONFIG_MSM_GLADIATOR_HANG_DETECT=y
+CONFIG_MSM_GLADIATOR_ERP=y
+CONFIG_QCOM_EUD=y
+CONFIG_QCOM_WATCHDOG_V2=y
+CONFIG_QPNP_PBS=y
+CONFIG_QCOM_MEMORY_DUMP_V2=y
+CONFIG_QCOM_BUS_SCALING=y
+CONFIG_QCOM_BUS_CONFIG_RPMH=y
+CONFIG_QCOM_SECURE_BUFFER=y
+CONFIG_QCOM_EARLY_RANDOM=y
+CONFIG_MSM_SMEM=y
+CONFIG_MSM_GLINK=y
+CONFIG_MSM_GLINK_LOOPBACK_SERVER=y
+CONFIG_MSM_GLINK_SMEM_NATIVE_XPRT=y
+CONFIG_MSM_GLINK_SPI_XPRT=y
+CONFIG_MSM_SPCOM=y
+CONFIG_MSM_SPSS_UTILS=y
+CONFIG_TRACER_PKT=y
+CONFIG_QTI_RPMH_API=y
+CONFIG_MSM_SMP2P=y
+CONFIG_MSM_IPC_ROUTER_GLINK_XPRT=y
+CONFIG_MSM_QMI_INTERFACE=y
+CONFIG_MSM_GLINK_PKT=y
+CONFIG_MSM_SUBSYSTEM_RESTART=y
+CONFIG_MSM_PIL=y
+CONFIG_MSM_SYSMON_GLINK_COMM=y
+CONFIG_MSM_PIL_SSR_GENERIC=y
+CONFIG_MSM_PIL_MSS_QDSP6V5=y
+CONFIG_ICNSS=y
+CONFIG_ICNSS_DEBUG=y
+CONFIG_QCOM_COMMAND_DB=y
+CONFIG_MSM_PERFORMANCE=y
+CONFIG_MSM_CDSP_LOADER=y
+CONFIG_QCOM_SMCINVOKE=y
+CONFIG_MSM_EVENT_TIMER=y
+CONFIG_MSM_QBT1000=y
+CONFIG_QCOM_DCC_V2=y
+CONFIG_QTI_RPM_STATS_LOG=y
+CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
+CONFIG_QMP_DEBUGFS_CLIENT=y
+CONFIG_MSM_REMOTEQDSS=y
+CONFIG_QCOM_BIMC_BWMON=y
+CONFIG_DEVFREQ_GOV_QCOM_CACHE_HWMON=y
+CONFIG_QCOM_DEVFREQ_DEVBW=y
+CONFIG_EXTCON_USB_GPIO=y
+CONFIG_IIO=y
+CONFIG_QCOM_RRADC=y
+CONFIG_PWM=y
+CONFIG_PWM_QPNP=y
+CONFIG_ARM_GIC_V3_ACL=y
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_SENSORS_SSC=y
+CONFIG_MSM_TZ_LOG=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+CONFIG_FUSE_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_ECRYPT_FS=y
+CONFIG_ECRYPT_FS_MESSAGING=y
+# CONFIG_NETWORK_FILESYSTEMS is not set
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_DEBUG_INFO=y
+CONFIG_PAGE_OWNER=y
+CONFIG_PAGE_OWNER_ENABLE_DEFAULT=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_PAGEALLOC=y
+CONFIG_SLUB_DEBUG_PANIC_ON=y
+CONFIG_DEBUG_PAGEALLOC_ENABLE_DEFAULT=y
+CONFIG_DEBUG_OBJECTS=y
+CONFIG_DEBUG_OBJECTS_FREE=y
+CONFIG_DEBUG_OBJECTS_TIMERS=y
+CONFIG_DEBUG_OBJECTS_WORK=y
+CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
+CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y
+CONFIG_SLUB_DEBUG_ON=y
+CONFIG_DEBUG_KMEMLEAK=y
+CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=4000
+CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y
+CONFIG_DEBUG_STACK_USAGE=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_LOCKUP_DETECTOR=y
+CONFIG_WQ_WATCHDOG=y
+CONFIG_PANIC_TIMEOUT=5
+CONFIG_PANIC_ON_SCHED_BUG=y
+CONFIG_PANIC_ON_RT_THROTTLING=y
+CONFIG_SCHEDSTATS=y
+CONFIG_SCHED_STACK_END_CHECK=y
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_ATOMIC_SLEEP=y
+CONFIG_DEBUG_LIST=y
+CONFIG_FAULT_INJECTION=y
+CONFIG_FAIL_PAGE_ALLOC=y
+CONFIG_FAULT_INJECTION_DEBUG_FS=y
+CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y
+CONFIG_IPC_LOGGING=y
+CONFIG_QCOM_RTB=y
+CONFIG_QCOM_RTB_SEPARATE_CPUS=y
+CONFIG_FUNCTION_TRACER=y
+CONFIG_IRQSOFF_TRACER=y
+CONFIG_PREEMPT_TRACER=y
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_CPU_FREQ_SWITCH_PROFILER=y
+CONFIG_LKDTM=y
+CONFIG_MEMTEST=y
+CONFIG_PANIC_ON_DATA_CORRUPTION=y
+CONFIG_PID_IN_CONTEXTIDR=y
+CONFIG_CORESIGHT=y
+CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y
+CONFIG_CORESIGHT_REMOTE_ETM=y
+CONFIG_CORESIGHT_REMOTE_ETM_DEFAULT_ENABLE=0
+CONFIG_CORESIGHT_QCOM_REPLICATOR=y
+CONFIG_CORESIGHT_STM=y
+CONFIG_CORESIGHT_TPDA=y
+CONFIG_CORESIGHT_TPDM=y
+CONFIG_CORESIGHT_CTI=y
+CONFIG_CORESIGHT_HWEVENT=y
+CONFIG_CORESIGHT_DUMMY=y
+CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
+CONFIG_SECURITY=y
+CONFIG_HARDENED_USERCOPY=y
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SMACK=y
+CONFIG_CRYPTO_XCBC=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_ANSI_CPRNG=y
+CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y
+CONFIG_CRYPTO_DEV_QCRYPTO=y
+CONFIG_CRYPTO_DEV_QCEDEV=y
+CONFIG_CRYPTO_DEV_QCOM_ICE=y
+CONFIG_XZ_DEC=y
diff --git a/arch/arm/configs/sdxpoorwills-perf_defconfig b/arch/arm/configs/sdxpoorwills-perf_defconfig
index cab3796..d5930a7 100644
--- a/arch/arm/configs/sdxpoorwills-perf_defconfig
+++ b/arch/arm/configs/sdxpoorwills-perf_defconfig
@@ -182,6 +182,7 @@
CONFIG_MTD_UBI=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
+CONFIG_QSEECOM=y
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_SG=y
@@ -298,6 +299,8 @@
CONFIG_USB_STORAGE_CYPRESS_ATACB=y
CONFIG_USB_DWC3=y
CONFIG_USB_DWC3_MSM=y
+CONFIG_USB_EHSET_TEST_FIXTURE=y
+CONFIG_USB_LINK_LAYER_TEST=y
CONFIG_NOP_USB_XCEIV=y
CONFIG_USB_MSM_SSPHY_QMP=y
CONFIG_MSM_HSUSB_PHY=y
diff --git a/arch/arm/configs/sdxpoorwills_defconfig b/arch/arm/configs/sdxpoorwills_defconfig
index bd429ee..f5abbb4 100644
--- a/arch/arm/configs/sdxpoorwills_defconfig
+++ b/arch/arm/configs/sdxpoorwills_defconfig
@@ -176,6 +176,7 @@
CONFIG_MTD_UBI=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
+CONFIG_QSEECOM=y
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_SG=y
@@ -299,6 +300,7 @@
CONFIG_USB_DWC3=y
CONFIG_USB_DWC3_MSM=y
CONFIG_USB_EHSET_TEST_FIXTURE=y
+CONFIG_USB_LINK_LAYER_TEST=y
CONFIG_NOP_USB_XCEIV=y
CONFIG_USB_MSM_SSPHY_QMP=y
CONFIG_MSM_HSUSB_PHY=y
diff --git a/arch/arm/include/asm/arch_gicv3.h b/arch/arm/include/asm/arch_gicv3.h
index 4d1065c..e65712e 100644
--- a/arch/arm/include/asm/arch_gicv3.h
+++ b/arch/arm/include/asm/arch_gicv3.h
@@ -25,6 +25,7 @@
#include <asm/cp15.h>
#define ICC_EOIR1 __ACCESS_CP15(c12, 0, c12, 1)
+#define ICC_HPPIR1 __ACCESS_CP15(c12, 0, c12, 2)
#define ICC_DIR __ACCESS_CP15(c12, 0, c11, 1)
#define ICC_IAR1 __ACCESS_CP15(c12, 0, c12, 0)
#define ICC_SGI1R __ACCESS_CP15_64(0, c12)
@@ -140,6 +141,7 @@
CPUIF_MAP(ICH_AP1R0, ICH_AP1R0_EL2)
CPUIF_MAP(ICC_HSRE, ICC_SRE_EL2)
CPUIF_MAP(ICC_SRE, ICC_SRE_EL1)
+CPUIF_MAP(ICC_HPPIR1, ICC_HPPIR1_EL1)
CPUIF_MAP_LO_HI(ICH_LR15, ICH_LRC15, ICH_LR15_EL2)
CPUIF_MAP_LO_HI(ICH_LR14, ICH_LRC14, ICH_LR14_EL2)
@@ -184,6 +186,15 @@
return irqstat;
}
+static inline u32 gic_read_hppir(void)
+{
+ u32 irqstat = read_sysreg(ICC_HPPIR1);
+
+ dsb(sy);
+
+ return irqstat;
+}
+
static inline void gic_write_pmr(u32 val)
{
write_sysreg(val, ICC_PMR);
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c
index 4f14b5c..c2b440b 100644
--- a/arch/arm/kernel/module.c
+++ b/arch/arm/kernel/module.c
@@ -40,8 +40,15 @@
#ifdef CONFIG_MMU
void *module_alloc(unsigned long size)
{
- void *p = __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,
- GFP_KERNEL, PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE,
+ gfp_t gfp_mask = GFP_KERNEL;
+ void *p;
+
+ /* Silence the initial allocation */
+ if (IS_ENABLED(CONFIG_ARM_MODULE_PLTS))
+ gfp_mask |= __GFP_NOWARN;
+
+ p = __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,
+ gfp_mask, PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE,
__builtin_return_address(0));
if (!IS_ENABLED(CONFIG_ARM_MODULE_PLTS) || p)
return p;
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index a03a99a..3b2f4ce 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -239,15 +239,13 @@
return 0;
}
-static DECLARE_COMPLETION(cpu_died);
-
/*
* called on the thread which is asking for a CPU to be shutdown -
* waits until shutdown has completed, or it is timed out.
*/
void __cpu_die(unsigned int cpu)
{
- if (!wait_for_completion_timeout(&cpu_died, msecs_to_jiffies(5000))) {
+ if (!cpu_wait_death(cpu, 5)) {
pr_err("CPU%u: cpu didn't die\n", cpu);
return;
}
@@ -293,7 +291,7 @@
* this returns, power and/or clocks can be removed at any point
* from this CPU and its cache by platform_cpu_kill().
*/
- complete(&cpu_died);
+ (void)cpu_report_death();
/*
* Ensure that the cache lines associated with that completion are
diff --git a/arch/arm/mach-qcom/Kconfig b/arch/arm/mach-qcom/Kconfig
index da48623..d96863e 100644
--- a/arch/arm/mach-qcom/Kconfig
+++ b/arch/arm/mach-qcom/Kconfig
@@ -177,6 +177,40 @@
select CPU_FREQ_QCOM
select COMMON_CLK_MSM
+config ARCH_SDM670
+ bool "Enable Support for SDM670"
+ select CPU_V7
+ select CLKDEV_LOOKUP
+ select HAVE_CLK
+ select HAVE_CLK_PREPARE
+ select PM_OPP
+ select SOC_BUS
+ select MSM_IRQ
+ select THERMAL_WRITABLE_TRIPS
+ select ARM_GIC_V3
+ select ARM_AMBA
+ select SPARSE_IRQ
+ select MULTI_IRQ_HANDLER
+ select HAVE_ARM_ARCH_TIMER
+ select MAY_HAVE_SPARSE_IRQ
+ select COMMON_CLK
+ select COMMON_CLK_QCOM
+ select QCOM_GDSC
+ select PINCTRL_MSM_TLMM
+ select PCI
+ select USE_PINCTRL_IRQ
+ select MSM_PM if PM
+ select QMI_ENCDEC
+ select CPU_FREQ
+ select PM_DEVFREQ
+ select MSM_DEVFREQ_DEVBW
+ select DEVFREQ_SIMPLE_DEV
+ select DEVFREQ_GOV_MSM_BW_HWMON
+ select MSM_BIMC_BWMON
+ select MSM_QDSP6V2_CODECS
+ select MSM_AUDIO_QDSP6V2 if SND_SOC
+ select GENERIC_IRQ_MIGRATION
+
config ARCH_MDM9650
bool "MDM9650"
select ARM_GIC
diff --git a/arch/arm/mach-qcom/Makefile b/arch/arm/mach-qcom/Makefile
index 2f26f39..3ef169f 100644
--- a/arch/arm/mach-qcom/Makefile
+++ b/arch/arm/mach-qcom/Makefile
@@ -12,3 +12,4 @@
obj-$(CONFIG_ARCH_MDM9650) += board-9650.o
obj-$(CONFIG_ARCH_MDM9607) += board-9607.o
obj-$(CONFIG_ARCH_SDM632) += board-sdm632.o
+obj-$(CONFIG_ARCH_SDM670) += board-sdm670.o
diff --git a/arch/arm/mach-qcom/board-sdm670.c b/arch/arm/mach-qcom/board-sdm670.c
new file mode 100644
index 0000000..c77a3ff
--- /dev/null
+++ b/arch/arm/mach-qcom/board-sdm670.c
@@ -0,0 +1,33 @@
+/* Copyright (c) 2018, 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.
+ */
+
+#include <linux/kernel.h>
+#include "board-dt.h"
+#include <asm/mach/map.h>
+#include <asm/mach/arch.h>
+
+static const char *sdm670_dt_match[] __initconst = {
+ "qcom,sdm670",
+ "qcom,qcs605",
+ NULL
+};
+
+static void __init sdm670_init(void)
+{
+ board_dt_populate(NULL);
+}
+
+DT_MACHINE_START(SDM670_DT,
+ "Qualcomm Technologies, Inc. SDM670 (Flattened Device Tree)")
+ .init_machine = sdm670_init,
+ .dt_compat = sdm670_dt_match,
+MACHINE_END
diff --git a/arch/arm/mach-qcom/platsmp.c b/arch/arm/mach-qcom/platsmp.c
index 803804d..3be4cae 100644
--- a/arch/arm/mach-qcom/platsmp.c
+++ b/arch/arm/mach-qcom/platsmp.c
@@ -25,7 +25,7 @@
#ifdef CONFIG_MSM_PM_LEGACY
#include <soc/qcom/pm-legacy.h>
#endif
-
+#include <soc/qcom/scm-boot.h>
#define MSM_APCS_IDR 0x0B011030
/* Base Address of APC IPC block */
@@ -434,10 +434,19 @@
static void __init qcom_smp_prepare_cpus(unsigned int max_cpus)
{
- int cpu;
+ int cpu, map;
+ u32 aff0_mask = 0;
+ u32 aff1_mask = 0;
+ u32 aff2_mask = 0;
- if (qcom_scm_set_cold_boot_addr(secondary_startup_arm,
- cpu_present_mask)) {
+ for_each_present_cpu(cpu) {
+ map = cpu_logical_map(cpu);
+ aff0_mask |= BIT(MPIDR_AFFINITY_LEVEL(map, 0));
+ aff1_mask |= BIT(MPIDR_AFFINITY_LEVEL(map, 1));
+ aff2_mask |= BIT(MPIDR_AFFINITY_LEVEL(map, 2));
+ }
+ if (scm_set_boot_addr_mc(virt_to_phys(secondary_startup_arm),
+ aff0_mask, aff1_mask, aff2_mask, SCM_FLAG_COLDBOOT_MC)) {
for_each_present_cpu(cpu) {
if (cpu == smp_processor_id())
continue;
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index f216025..e346cf3 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -2610,7 +2610,7 @@
}
if (__arm_iommu_attach_device(dev, mapping)) {
- pr_warn("Failed to attached device %s to IOMMU_mapping\n",
+ pr_debug("Failed to attached device %s to IOMMU_mapping\n",
dev_name(dev));
arm_iommu_release_mapping(mapping);
return false;
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 9c01a31..f72ce30 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -15,7 +15,24 @@
select ARCH_HAS_KCOV
select ARCH_HAS_SG_CHAIN
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
+ select ARCH_INLINE_READ_LOCK if !PREEMPT
+ select ARCH_INLINE_READ_LOCK_BH if !PREEMPT
+ select ARCH_INLINE_READ_LOCK_IRQ if !PREEMPT
+ select ARCH_INLINE_READ_LOCK_IRQSAVE if !PREEMPT
+ select ARCH_INLINE_READ_UNLOCK if !PREEMPT
+ select ARCH_INLINE_READ_UNLOCK_BH if !PREEMPT
+ select ARCH_INLINE_READ_UNLOCK_IRQ if !PREEMPT
+ select ARCH_INLINE_READ_UNLOCK_IRQRESTORE if !PREEMPT
+ select ARCH_INLINE_WRITE_LOCK if !PREEMPT
+ select ARCH_INLINE_WRITE_LOCK_BH if !PREEMPT
+ select ARCH_INLINE_WRITE_LOCK_IRQ if !PREEMPT
+ select ARCH_INLINE_WRITE_LOCK_IRQSAVE if !PREEMPT
+ select ARCH_INLINE_WRITE_UNLOCK if !PREEMPT
+ select ARCH_INLINE_WRITE_UNLOCK_BH if !PREEMPT
+ select ARCH_INLINE_WRITE_UNLOCK_IRQ if !PREEMPT
+ select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE if !PREEMPT
select ARCH_USE_CMPXCHG_LOCKREF
+ select ARCH_USE_QUEUED_RWLOCKS
select ARCH_SUPPORTS_LTO_CLANG
select ARCH_SUPPORTS_ATOMIC_RMW
select ARCH_SUPPORTS_NUMA_BALANCING
@@ -112,6 +129,7 @@
select SPARSE_IRQ
select SYSCTL_EXCEPTION_TRACE
select THREAD_INFO_IN_TASK
+ select ARCH_SUPPORTS_SPECULATIVE_PAGE_FAULT
help
ARM 64-bit (AArch64) Linux support.
diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
index 3ad1c0e..8b0cb9f 100644
--- a/arch/arm64/boot/dts/qcom/Makefile
+++ b/arch/arm64/boot/dts/qcom/Makefile
@@ -150,6 +150,7 @@
qcs605-mtp-overlay.dtbo \
qcs605-360camera-overlay.dtbo \
qcs605-external-codec-mtp-overlay.dtbo \
+ qcs605-lc-ipcamera-overlay.dtbo \
qcs605-lc-mtp-overlay.dtbo \
qcs605-lc-cdp-overlay.dtbo \
sdm710-cdp-overlay.dtbo \
@@ -211,6 +212,7 @@
qcs605-mtp-overlay.dtbo-base := qcs605.dtb
qcs605-external-codec-mtp-overlay.dtbo-base := qcs605.dtb
qcs605-lc-mtp-overlay.dtbo-base := qcs605-lc.dtb
+qcs605-lc-ipcamera-overlay.dtbo-base := qcs605-lc.dtb
qcs605-360camera-overlay.dtbo-base := qcs605.dtb
qcs605-lc-cdp-overlay.dtbo-base := qcs605-lc-cdp-base.dtb
sdm710-cdp-overlay.dtbo-base := sdm710.dtb
@@ -271,6 +273,7 @@
qcs605-mtp.dtb \
qcs605-cdp.dtb \
qcs605-external-codec-mtp.dtb \
+ qcs605-lc-ipcamera.dtb \
qcs605-lc-mtp.dtb \
qcs605-lc-cdp.dtb \
sdm710-mtp.dtb \
@@ -296,6 +299,13 @@
endif
ifeq ($(CONFIG_BUILD_ARM64_DT_OVERLAY),y)
+dtbo-$(CONFIG_ARCH_MSM8917) += msm8917-mtp-overlay.dtbo \
+ msm8917-qrd-overlay.dtbo \
+ msm8917-cdp-overlay.dtbo \
+ msm8917-cdp-ext-codec-overlay.dtbo \
+ msm8917-cdp-ml-touch-overlay.dtbo \
+ msm8917-rcm-overlay.dtbo
+
dtbo-$(CONFIG_ARCH_MSM8953) += msm8953-mtp-overlay.dtbo \
msm8953-cdp-overlay.dtbo \
msm8953-rcm-overlay.dtbo \
@@ -334,6 +344,33 @@
sdm429-cdp-overlay.dtbo \
sdm429-qrd-overlay.dtbo
+msm8917-mtp-overlay.dtbo-base := msm8917-pmi8950.dtb \
+ msm8917-pmi8937.dtb \
+ msm8917-pmi8940.dtb
+
+msm8917-qrd-overlay.dtbo-base := msm8917-pmi8937.dtb
+
+msm8917-cdp-ext-codec-overlay.dtbo-base := msm8917-pmi8950.dtb
+
+msm8917-cdp-ml-touch-overlay.dtbo-base := msm8917-pmi8950.dtb
+
+msm8917-cdp-overlay.dtbo-base := msm8917-pmi8950.dtb \
+ msm8917-pmi8937.dtb \
+ msm8917-pmi8940.dtb
+
+msm8917-rcm-overlay.dtbo-base := msm8917-pmi8950.dtb \
+ msm8917-pmi8937.dtb \
+ msm8917-pmi8940.dtb
+
+apq8017-mtp-overlay.dtbo-base := apq8017-pmi8950.dtb \
+ apq8017-pmi8937.dtb
+
+apq8017-cdp-overlay.dtbo-base := apq8017-pmi8950.dtb \
+ apq8017-pmi8937.dtb
+
+apq8017-cdp-wcd-rome-overlay.dtbo-base := apq8017-pmi8950.dtb \
+ apq8017-pmi8937.dtb
+
msm8953-mtp-overlay.dtbo-base := sdm450.dtb \
msm8953.dtb \
apq8053.dtb \
@@ -468,7 +505,8 @@
apq8009-mtp-wcd9326-refboard.dtb \
apq8009-robot-som-refboard.dtb \
apq8009-dragon.dtb \
- apq8009-lat-v1.0.dtb
+ apq8009-lat-v1.0.dtb \
+ sdw3100-msm8909w-1gb-wtp.dtb
dtb-$(CONFIG_ARCH_SDM450) += sdm450-rcm.dtb \
sdm450-cdp.dtb \
diff --git a/arch/arm64/boot/dts/qcom/apq8009-dragon.dts b/arch/arm64/boot/dts/qcom/apq8009-dragon.dts
index ba12854..041563b 100644
--- a/arch/arm64/boot/dts/qcom/apq8009-dragon.dts
+++ b/arch/arm64/boot/dts/qcom/apq8009-dragon.dts
@@ -211,6 +211,7 @@
&pm8916_chg {
status = "ok";
+ qcom,use-default-batt-values;
};
&pm8916_bms {
diff --git a/arch/arm64/boot/dts/qcom/apq8009-mtp-wcd9326-refboard.dts b/arch/arm64/boot/dts/qcom/apq8009-mtp-wcd9326-refboard.dts
index 2afd5ac..71082c8 100644
--- a/arch/arm64/boot/dts/qcom/apq8009-mtp-wcd9326-refboard.dts
+++ b/arch/arm64/boot/dts/qcom/apq8009-mtp-wcd9326-refboard.dts
@@ -195,14 +195,6 @@
<79 512 2048000 4096000>; /* MAX */
};
- vbus_otg_supply: vbus_otg_supply {
- compatible = "regulator-fixed";
- regulator-name = "vbus_otg";
- status = "ok";
- enable-active-high;
- gpio = <&pm8916_gpios 3 0>;
- };
-
usb_detect: qcom,gpio-usbdetect {
compatible = "qcom,gpio-usbdetect";
interrupt-parent = <&msm_gpio>;
@@ -325,12 +317,18 @@
qcom,iterm-ma = <200>;
qcom,recharge-thresh-mv = <100>;
qcom,thermal-mitigation = <1500 700 600 0>;
- regulator-name = "smb1360_otg_vreg";
status= "okay";
+ smb1360_vbus: qcom,smb1360-vbus {
+ regulator-name = "qcom,smb1360-vbus";
+ };
};
};
&usb_otg {
+ interrupts = <0 134 0>, <0 140 0>, <0 136 0>;
+ interrupt-names = "core_irq", "async_irq", "phy_irq";
+ qcom,hsusb-otg-mode = <3>;
+ vbus_otg-supply = <&smb1360_vbus>;
extcon = <&smb1360_otg_supply>;
};
diff --git a/arch/arm64/boot/dts/qcom/apq8009-robot-pronto-refboard.dts b/arch/arm64/boot/dts/qcom/apq8009-robot-pronto-refboard.dts
new file mode 100644
index 0000000..0ac8a31
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8009-robot-pronto-refboard.dts
@@ -0,0 +1,380 @@
+/* Copyright (c) 2016-2018, 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.
+ */
+
+/dts-v1/;
+
+#include "msm8909-mtp.dtsi"
+#include "8909-pm8916.dtsi"
+#include "msm8909-pm8916-mtp.dtsi"
+#include "apq8009-audio-external_codec.dtsi"
+#include "apq8009-memory.dtsi"
+#include <dt-bindings/pinctrl/qcom,pmic-mpp.h>
+#include "msm8909-pm8916-camera.dtsi"
+#include "msm8909-pm8916-camera-sensor-robot.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. APQ8009 Robot-pronto RefBoard";
+ compatible = "qcom,apq8009-mtp", "qcom,apq8009", "qcom,mtp";
+ qcom,msm-id = <265 2>;
+ qcom,board-id= <8 0xE>;
+};
+
+&audio_codec_mtp {
+ status = "disabled";
+};
+
+&pm8916_gpios {
+ nfc_clk {
+ nfc_clk_default: nfc_clk_default {
+ status = "okay";
+ };
+ };
+};
+
+&msm_gpio {
+ hsuart_active: default {
+ mux {
+ pins = "gpio20", "gpio21", "gpio111", "gpio112";
+ function = "blsp_uart2";
+ };
+
+ config {
+ pins = "gpio20", "gpio21", "gpio111", "gpio112";
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+
+ hsuart_sleep: sleep {
+ mux {
+ pins = "gpio20", "gpio21", "gpio111", "gpio112";
+ function = "blsp_uart2";
+ };
+
+ config {
+ pins = "gpio20", "gpio21", "gpio111", "gpio112";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ usb_vbus_detect: usb_vbus_detect {
+ mux {
+ pins = "gpio97";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio97";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ usb_id_detect: usb_id_detect {
+ mux {
+ pins = "gpio110";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio110";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+};
+
+&soc {
+ ext_codec: sound-9335 {
+ qcom,audio-routing =
+ "AIF4 VI", "MCLK",
+ "RX_BIAS", "MCLK",
+ "MADINPUT", "MCLK",
+ "AMIC2", "MIC BIAS2",
+ "MIC BIAS2", "Headset Mic",
+ "DMIC0", "MIC BIAS1",
+ "MIC BIAS1", "Digital Mic0",
+ "DMIC1", "MIC BIAS1",
+ "MIC BIAS1", "Digital Mic1",
+ "DMIC2", "MIC BIAS3",
+ "MIC BIAS3", "Digital Mic2",
+ "DMIC3", "MIC BIAS3",
+ "MIC BIAS3", "Digital Mic3",
+ "SpkrLeft IN", "SPK1 OUT",
+ "SpkrRight IN", "SPK2 OUT";
+
+ qcom,msm-gpios =
+ "us_eu_gpio";
+ qcom,pinctrl-names =
+ "all_off",
+ "us_eu_gpio_act";
+ pinctrl-names =
+ "all_off",
+ "us_eu_gpio_act";
+ pinctrl-0 = <&cross_conn_det_sus>;
+ pinctrl-1 = <&cross_conn_det_act>;
+ qcom,pri-mi2s-gpios = <&cdc_pri_mi2s_gpios>;
+ qcom,quat-mi2s-gpios = <&cdc_quat_mi2s_gpios>;
+
+ qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrRight",
+ "SpkrLeft", "SpkrRight";
+ };
+
+ i2c@78b9000 {
+ synaptics@20 {
+ status = "disabled";
+ };
+ };
+
+ blsp1_uart2_hs: uart@78b0000 {
+ compatible = "qcom,msm-hsuart-v14";
+ reg = <0x78b0000 0x200>,
+ <0x7884000 0x1f000>;
+ reg-names = "core_mem", "bam_mem";
+ interrupt-names = "core_irq", "bam_irq", "wakeup_irq";
+ #address-cells = <0>;
+ interrupt-parent = <&blsp1_uart2_hs>;
+ interrupts = <0 1 2>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0xffffffff>;
+ interrupt-map = <0 &intc 0 108 0
+ 1 &intc 0 238 0
+ 2 &msm_gpio 21 0>;
+ qcom,inject-rx-on-wakeup;
+ qcom,rx-char-to-inject = <0xfd>;
+ qcom,master-id = <86>;
+ clock-names = "core_clk", "iface_clk";
+ clocks = <&clock_gcc clk_gcc_blsp1_uart2_apps_clk>,
+ <&clock_gcc clk_gcc_blsp1_ahb_clk>;
+ pinctrl-names = "sleep", "default";
+ pinctrl-0 = <&hsuart_sleep>;
+ pinctrl-1 = <&hsuart_active>;
+ qcom,bam-tx-ep-pipe-index = <2>;
+ qcom,bam-rx-ep-pipe-index = <3>;
+ qcom,msm-bus,name = "blsp1_uart2_hs";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <86 512 0 0>,
+ <86 512 500 800>;
+ status = "ok";
+ };
+
+ bluetooth: bt_qca9379 {
+ compatible = "qca,qca9379";
+ qca,bt-reset-gpio = <&msm_gpio 47 0>; /* BT_EN */
+ };
+
+ cnss_sdio: qcom,cnss_sdio {
+ compatible = "qcom,cnss_sdio";
+ subsys-name = "AR6320";
+ /**
+ * There is no vdd-wlan on board and this is not for DSRC.
+ * IO and XTAL share the same vreg.
+ **/
+ vdd-wlan-io-supply = <&pm8916_l5>;
+ qcom,cap-tsf-gpio = <&msm_gpio 42 1>;
+ qcom,wlan-ramdump-dynamic = <0x200000>;
+ qcom,msm-bus,name = "msm-cnss";
+ qcom,msm-bus,num-cases = <4>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <79 512 0 0>, /* No vote */
+ <79 512 6250 200000>, /* 50 Mbps */
+ <79 512 25000 200000>, /* 200 Mbps */
+ <79 512 2048000 4096000>; /* MAX */
+ };
+
+ usb_detect: qcom,gpio-usbdetect {
+ compatible = "qcom,gpio-usbdetect";
+ interrupt-parent = <&msm_gpio>;
+ interrupts = <97 0>;
+ interrupt-names = "vbus_det_irq";
+ pinctrl-names = "usb_vbus_detect", "usb_id_detect";
+ pinctrl-0 = <&usb_vbus_detect>;
+ pinctrl-1 = <&usb_id_detect>;
+ qcom,gpio-mode-sel = <&msm_gpio 97 0>;
+ qcom,id-det-gpio = <&msm_gpio 110 0>;
+ qcom,dpdm_switch_gpio = <&pm8916_gpios 3 0>;
+ };
+
+ i2c@78b8000 {
+ wcd9xxx_codec@d {
+ status = "okay";
+ qcom,wcd-rst-gpio-node = <&wcd_rst_gpio>;
+ };
+ };
+
+ cdc_pri_mi2s_gpios: msm_cdc_pinctrl_pri {
+ compatible = "qcom,msm-cdc-pinctrl";
+ pinctrl-names = "aud_active", "aud_sleep";
+ pinctrl-0 = <&pri_mi2s_active &pri_mi2s_ws_active
+ &pri_mi2s_dout_active &pri_mi2s_din_active>;
+ pinctrl-1 = <&pri_mi2s_sleep &pri_mi2s_ws_sleep
+ &pri_mi2s_dout_sleep &pri_mi2s_din_sleep>;
+ };
+
+ cdc_quat_mi2s_gpios: msm_cdc_pinctrl_quat {
+ compatible = "qcom,msm-cdc-pinctrl";
+ pinctrl-names = "aud_active", "aud_sleep";
+ pinctrl-0 = <&quat_mi2s_active &quat_mi2s_din_active>;
+ pinctrl-1 = <&quat_mi2s_sleep &quat_mi2s_din_sleep>;
+ };
+
+ wcd_rst_gpio: wcd_gpio_ctrl {
+ compatible = "qcom,msm-cdc-pinctrl";
+ pinctrl-names = "aud_active", "aud_sleep";
+ pinctrl-0 = <&cdc_reset_active>;
+ pinctrl-1 = <&cdc_reset_sleep>;
+ };
+};
+
+&wcnss {
+ status = "disabled";
+};
+
+&msm_gpio {
+ sdc2_wlan_gpio_on: sdc2_wlan_gpio_on {
+ mux {
+ pins = "gpio43";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio43";
+ drive-strength = <10>;
+ bias-pull-up;
+ output-high;
+ };
+ };
+
+ sdc2_wlan_gpio_off: sdc2_wlan_gpio_off {
+ mux {
+ pins = "gpio43";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio43";
+ drive-strength = <2>;
+ bias-disable;
+ output-low;
+ };
+ };
+};
+
+&sdhc_2 {
+ /delete-property/cd-gpios;
+ #address-cells = <0>;
+ interrupt-parent = <&sdhc_2>;
+ interrupts = <0 1 2>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0xffffffff>;
+ interrupt-map = <0 &intc 0 125 0
+ 1 &intc 0 221 0
+ 2 &msm_gpio 38 0>;
+ interrupt-names = "hc_irq", "pwr_irq", "sdiowakeup_irq";
+
+ qcom,vdd-voltage-level = <1800000 2950000>;
+ qcom,vdd-current-level = <15000 400000>;
+
+ qcom,vdd-io-voltage-level = <1800000 1800000>;
+ qcom,vdd-io-current-level = <200 50000>;
+ qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>;
+ qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
+
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on
+ &sdc2_wlan_gpio_on>;
+ pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off
+ &sdc2_wlan_gpio_off>;
+ qcom,nonremovable;
+ qcom,core_3_0v_support;
+ status = "ok";
+};
+
+&i2c_4 {
+ status= "okay";
+ smb1360_otg_supply: smb1360-chg-fg@14 {
+ compatible = "qcom,smb1360-chg-fg";
+ reg = <0x14>;
+ interrupt-parent = <&msm_gpio>;
+ interrupts = <58 8>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&smb_int_default>;
+ qcom,charging-disabled;
+ qcom,empty-soc-disabled;
+ qcom,chg-inhibit-disabled;
+ qcom,float-voltage-mv = <4200>;
+ qcom,iterm-ma = <200>;
+ qcom,recharge-thresh-mv = <100>;
+ qcom,thermal-mitigation = <1500 700 600 0>;
+ status= "okay";
+ smb1360_vbus: qcom,smb1360-vbus {
+ regulator-name = "qcom,smb1360-vbus";
+ };
+ };
+};
+
+&usb_otg {
+ interrupts = <0 134 0>, <0 140 0>, <0 136 0>;
+ interrupt-names = "core_irq", "async_irq", "phy_irq";
+ qcom,hsusb-otg-mode = <3>;
+ vbus_otg-supply = <&smb1360_vbus>;
+ extcon = <&smb1360_otg_supply>;
+};
+
+&mdss_fb0 {
+ status = "disabled";
+ /delete-node/ qcom,cont-splash-memory;
+};
+
+&mdss_mdp {
+ status = "disabled";
+};
+
+&mdss_dsi0_pll {
+ status = "disabled";
+};
+
+&mdss_dsi0 {
+ status = "disabled";
+};
+
+&i2c_1 {
+ status = "disabled";
+};
+
+&i2c_2 {
+ status = "disabled";
+};
+
+&i2c_5 {
+ status = "disabled";
+};
+
+&spi_0 {
+ status = "disabled";
+};
+
+&wcd_rst_gpio {
+ status = "okay";
+};
+
+&ext_codec {
+ status = "okay";
+};
+
+&blsp1_uart2_hs {
+ status = "disabled";
+};
+
+/delete-node/ &cont_splash_mem;
diff --git a/arch/arm64/boot/dts/qcom/apq8009-robot-som-refboard.dts b/arch/arm64/boot/dts/qcom/apq8009-robot-som-refboard.dts
index 1314129..ab711dd 100644
--- a/arch/arm64/boot/dts/qcom/apq8009-robot-som-refboard.dts
+++ b/arch/arm64/boot/dts/qcom/apq8009-robot-som-refboard.dts
@@ -17,6 +17,8 @@
#include "8909-pm8916.dtsi"
#include "msm8909-pm8916-mtp.dtsi"
#include "apq8009-audio-external_codec.dtsi"
+#include "msm8909-pm8916-camera.dtsi"
+#include "msm8909-pm8916-camera-sensor-robot-som.dtsi"
/ {
model = "Qualcomm Technologies, Inc. APQ8009 Robot SOM refboard";
@@ -25,37 +27,147 @@
qcom,board-id = <8 0x15>;
};
+&audio_codec_mtp {
+ status = "disabled";
+};
+
+&i2c_4 {
+ status= "okay";
+};
+
+&pm8916_gpios {
+ wcd_vdd_en { /* GPIO 4 */
+ wcd_vdd_en_active: wcd_vdd_en_active {
+ status = "ok";
+ pins = "gpio4";
+ function = "normal";
+ output-high;
+ qcom,drive-strength = <2>;
+ };
+ wcd_vdd_en_sleep: wcd_vdd_en_sleep {
+ status = "ok";
+ pins = "gpio4";
+ function = "normal";
+ output-low;
+ qcom,drive-strength = <2>;
+ };
+
+ };
+};
+
&soc {
- ext-codec {
- qcom,msm-mbhc-hphl-swh = <0>;
+ ext_codec: sound-9335 {
+ compatible = "qcom,apq8009-audio-i2s-codec";
+ qcom,model = "apq8009-tashalite-snd-card-tdm";
+
qcom,audio-routing =
"AIF4 VI", "MCLK",
"RX_BIAS", "MCLK",
"MADINPUT", "MCLK",
- "AMIC2", "MIC BIAS2",
- "MIC BIAS2", "Headset Mic",
- "DMIC0", "MIC BIAS1",
- "MIC BIAS1", "Digital Mic0",
- "DMIC1", "MIC BIAS1",
- "MIC BIAS1", "Digital Mic1",
- "DMIC2", "MIC BIAS3",
- "MIC BIAS3", "Digital Mic2",
- "DMIC3", "MIC BIAS3",
- "MIC BIAS3", "Digital Mic3",
"SpkrLeft IN", "SPK1 OUT",
"SpkrRight IN", "SPK2 OUT";
+
+ qcom,tdm-i2s-switch-enable = <&msm_gpio 88 0>;
+ qcom,pri-mi2s-gpios = <&cdc_pri_mi2s_gpios>;
+ qcom,quat-mi2s-gpios = <&cdc_quat_tdm_gpios>;
};
- sound-9335 {
- status = "disabled";
+ clock_audio: audio_ext_clk {
+ compatible = "qcom,audio-ref-clk";
+ qcom,codec-mclk-clk-freq = <9600000>;
+ qcom,lpass-clock = <1>;
+ reg = <0x07702004 0x4>;
+ pinctrl-names = "sleep", "active";
+ pinctrl-0 = <&i2s_mclk_sleep>;
+ pinctrl-1 = <&i2s_mclk_active>;
+ #clock-cells = <1>;
};
i2c@78b8000 {
wcd9xxx_codec@d {
- status = "disabled";
+ status = "okay";
+ compatible = "qcom,tasha-i2c-pgd";
+ reg = <0x0d>;
+
+ interrupt-parent = <&wcd9xxx_intc>;
+ interrupts = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+ 17 18 19 20 21 22 23 24 25 26 27 28 29
+ 30>;
+
+ qcom,wcd-rst-gpio-node = <&wcd_rst_gpio>;
+
+ qcom,has-buck-vsel-gpio;
+ qcom,buck-vsel-gpio-node = <&wcd_vdd_gpio>;
+ swr_master {
+ compatible = "qcom,swr-wcd";
+ qcom,swr-num-dev = <2>;
+ #address-cells = <2>;
+ #size-cells = <0>;
+
+ wsa881x_211:wsa881x@21170211 {
+ compatible = "qcom,wsa881x";
+ reg = <0x00 0x21170211>;
+ qcom,spkr-sd-n-node = <&wsa_spkr>;
+ };
+
+ wsa881x_212:wsa881x@21170212 {
+ compatible = "qcom,wsa881x";
+ reg = <0x00 0x21170212>;
+ qcom,spkr-sd-n-node = <&wsa_spkr>;
+ };
+
+ wsa881x_213:wsa881x@21170213 {
+ compatible = "qcom,wsa881x";
+ reg = <0x00 0x21170213>;
+ qcom,spkr-sd-n-node = <&wsa_spkr>;
+ };
+
+ wsa881x_214:wsa881x@21170214 {
+ compatible = "qcom,wsa881x";
+ reg = <0x00 0x21170214>;
+ qcom,spkr-sd-n-node = <&wsa_spkr>;
+ };
+ };
};
};
+ cdc_pri_mi2s_gpios: msm_cdc_pinctrl_pri {
+ compatible = "qcom,msm-cdc-pinctrl";
+ pinctrl-names = "aud_active", "aud_sleep";
+ pinctrl-0 = <&pri_mi2s_active &pri_mi2s_ws_active
+ &pri_mi2s_dout_active &pri_mi2s_din_active>;
+ pinctrl-1 = <&pri_mi2s_sleep &pri_mi2s_ws_sleep
+ &pri_mi2s_dout_sleep &pri_mi2s_din_sleep>;
+ };
+
+ cdc_quat_tdm_gpios: msm_cdc_pinctrl_quat {
+ compatible = "qcom,msm-cdc-pinctrl";
+ pinctrl-names = "aud_active", "aud_sleep";
+ pinctrl-0 = <&quat_mi2s_active &quat_mi2s_din_active>;
+ pinctrl-1 = <&quat_mi2s_sleep &quat_mi2s_din_sleep>;
+ };
+
+ wcd_rst_gpio: wcd_gpio_ctrl {
+ compatible = "qcom,msm-cdc-pinctrl";
+ pinctrl-names = "aud_active", "aud_sleep";
+ pinctrl-0 = <&cdc_reset1_active>;
+ pinctrl-1 = <&cdc_reset1_sleep>;
+ };
+
+ wcd_vdd_gpio: wcd_vdd_gpio_ctrl {
+ compatible = "qcom,msm-cdc-pinctrl";
+ pinctrl-names = "aud_active", "aud_sleep";
+ pinctrl-0 = <&wcd_vdd_en_active>;
+ pinctrl-1 = <&wcd_vdd_en_sleep>;
+ };
+
+ wsa_spkr: msm_cdc_pinctrll {
+ compatible = "qcom,msm-cdc-pinctrl";
+ pinctrl-names = "aud_active", "aud_sleep";
+ pinctrl-0 = <&spkr_en_active>;
+ pinctrl-1 = <&spkr_en_sleep>;
+ };
+
vph_pwr_vreg: vph_pwr_vreg {
compatible = "regulator-fixed";
status = "ok";
@@ -63,6 +175,23 @@
regulator-always-on;
};
+ otg_vreg_5p0: otg_vreg_5p0 {
+ compatible = "regulator-fixed";
+ regulator-name = "sbc_vreg_5p0";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ status = "ok";
+ enable-active-low;
+ vin-supply = <&vph_pwr_vreg>;
+ };
+
+ vbus_otg_vreg: vbus_otg_vreg {
+ compatible = "regulator-fixed";
+ regulator-name = "vbus_otg_vreg";
+ gpio = <&msm_gpio 74 0>;
+ vin-supply = <&otg_vreg_5p0>;
+ };
+
mdss_mdp: qcom,mdss_mdp@1a00000 {
status = "disabled";
};
@@ -90,6 +219,44 @@
<79 512 25000 200000>, /* 200 Mbps */
<79 512 2048000 4096000>; /* MAX */
};
+
+ gpio_keys {
+ status = "disable";
+ };
+
+ spi@78ba000 {
+ reg = <0x78ba000 0x600>;
+ spi-max-frequency = <50000000>;
+ status = "okay";
+
+ spi@0 {
+ compatible = "qcom,spi-msm-slave";
+ reg = <0>;
+ spi-max-frequency = <50000000>;
+ };
+ };
+};
+
+&i2c_1 {
+ status = "okay";
+ icm20602@68 {
+ compatible = "invensense,icm20602";
+ reg = <0x68>;
+ interrupt-parent = <&msm_gpio>;
+ interrupts = <12 0>;
+ invensense,icm20602-gpio = <&msm_gpio 12 0x0>;
+ vdd-ldo-supply = <&pm8916_l6>;
+ interrupt-names = "icm20602_irq";
+ pinctrl-names = "imu_active","imu_suspend";
+ pinctrl-0 = <&imu_int_active>;
+ pinctrl-1 = <&imu_int_suspend>;
+ status = "ok";
+ };
+ vl53l0x@29 {
+ compatible = "st,stmvl53l0";
+ reg = <0x29>;
+ status = "ok";
+ };
};
&wcnss {
@@ -133,7 +300,7 @@
interrupt-map-mask = <0xffffffff>;
interrupt-map = <0 &intc 0 125 0
1 &intc 0 221 0
- 2 &msm_gpio 38 0>;
+ 2 &msm_gpio 40 0x1>;
interrupt-names = "hc_irq", "pwr_irq", "sdiowakeup_irq";
qcom,vdd-voltage-level = <1800000 2950000>;
@@ -159,8 +326,8 @@
interrupt-names = "core_irq", "async_irq", "phy_irq";
qcom,hsusb-otg-mode = <3>;
qcom,switch-vbus-w-id;
- vbus_otg-supply = <&vph_pwr_vreg>;
- extcon = <&pm8916_chg>;
+ qcom,phy-id-high-as-peripheral;
+ vbus_otg-supply = <&vbus_otg_vreg>;
};
&external_image_mem {
@@ -195,3 +362,12 @@
status = "ok";
};
};
+
+
+&wcd_rst_gpio {
+ status = "okay";
+};
+
+&ext_codec {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8017-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/apq8017-cdp-overlay.dts
new file mode 100644
index 0000000..6c8bef4
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8017-cdp-overlay.dts
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include "msm8917-cdp.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. APQ8017-CDP";
+ qcom,board-id = <1 0>;
+};
+
+&mdss_fb0 {
+ /delete-node/ qcom,cont-splash-memory;
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8017-cdp-wcd-rome-overlay.dts b/arch/arm64/boot/dts/qcom/apq8017-cdp-wcd-rome-overlay.dts
new file mode 100644
index 0000000..055c457
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8017-cdp-wcd-rome-overlay.dts
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include "msm8917-cdp.dtsi"
+#include "apq8017-rome.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. APQ8017-CDP \
+ with WCD codec/Rome card";
+ qcom,board-id = <1 2>;
+};
+
+&blsp1_uart1 {
+ status = "ok";
+};
+
+&sdhc_2 {
+ /* device core power supply */
+ /delete-property/vdd-supply;
+ /delete-property/qcom,vdd-voltage-level;
+ /delete-property/qcom,vdd-current-level;
+
+ /* device communication power supply */
+ vdd-io-supply = <&pm8937_l5>;
+ qcom,vdd-io-always-on;
+ qcom,vdd-io-voltage-level = <1800000 1800000>;
+ qcom,vdd-io-current-level = <200 325000>;
+
+ qcom,core_3_0v_support;
+ qcom,nonremovable;
+
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on
+ &sdc2_wlan_gpio_active>;
+ pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off
+ &sdc2_wlan_gpio_sleep>;
+
+ #address-cells = <0>;
+ interrupt-parent = <&sdhc_2>;
+ interrupts = <0 1 2>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0xffffffff>;
+ interrupt-map = <0 &intc 0 125 0
+ 1 &intc 0 221 0
+ 2 &tlmm 124 0x4>;
+ interrupt-names = "hc_irq", "pwr_irq", "sdiowakeup_irq";
+
+ /delete-property/cd-gpios;
+ /delete-property/qcom,devfreq,freq-table;
+
+ status = "ok";
+
+};
+
+&modem_mem {
+ reg = <0x0 0x86800000 0x0 0x1500000>;
+};
+
+&adsp_fw_mem {
+ reg = <0x0 0x87d00000 0x0 0x1100000>;
+};
+
+&wcnss_fw_mem {
+ reg = <0x0 0x88e00000 0x0 0x700000>;
+};
+
+&secure_mem {
+ status = "disabled";
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8017-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/apq8017-mtp-overlay.dts
new file mode 100644
index 0000000..23bbb0f
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8017-mtp-overlay.dts
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include "msm8917-mtp.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. APQ8017-MTP";
+ qcom,board-id = <8 0>;
+};
+
+&blsp1_uart1 {
+ status = "ok";
+};
+
+&vendor {
+ mtp_batterydata: qcom,battery-data {
+ qcom,batt-id-range-pct = <15>;
+ #include "batterydata-itech-3000mah.dtsi"
+ #include "batterydata-ascent-3450mAh.dtsi"
+ };
+};
+
+&qpnp_fg {
+ qcom,battery-data = <&mtp_batterydata>;
+};
+
+&qpnp_smbcharger {
+ qcom,battery-data = <&mtp_batterydata>;
+};
+
+&i2c_2 {
+ /* DSI_TO_HDMI I2C configuration */
+ adv7533@39 {
+ compatible = "adv7533";
+ reg = <0x39>;
+ instance_id = <0>;
+ adi,video-mode = <3>; /* 3 = 1080p */
+ adi,main-addr = <0x39>;
+ adi,cec-dsi-addr = <0x3C>;
+ adi,enable-audio;
+ adi,irq-gpio = <&tlmm 0x29 0x2002>;
+ adi,power-down-gpio = <&tlmm 0x7D 0x0>;
+ adi,switch-gpio = <&pm8937_gpios 0x8 0x1>;
+ pinctrl-names = "pmx_adv7533_active",
+ "pmx_adv7533_suspend";
+ pinctrl-0 = <&adv7533_int_active>;
+ pinctrl-1 = <&adv7533_int_suspend>;
+ };
+};
+
+&mdss_dsi {
+ hw-config = "single_dsi";
+};
+
+&mdss_dsi0 {
+ qcom,dsi-pref-prim-pan = <&dsi_adv7533_1080p>;
+ qcom,platform-intf-mux-gpio = <&tlmm 115 0>;
+ status = "ok";
+ qcom,bridge-index = <0>;
+ qcom,pluggable;
+};
+
+&dsi_adv7533_1080p {
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8017-pmi8937.dts b/arch/arm64/boot/dts/qcom/apq8017-pmi8937.dts
new file mode 100644
index 0000000..c060461
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8017-pmi8937.dts
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/dts-v1/;
+
+#include "apq8017.dtsi"
+#include "msm8917-pmi8937.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. MSM8917 + PMI8937 SOC";
+ compatible = "qcom,msm8917";
+ qcom,pmic-id = <0x10019 0x020037 0x0 0x0>;
+ qcom,pmic-name = "PMI8937";
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8017-pmi8950.dts b/arch/arm64/boot/dts/qcom/apq8017-pmi8950.dts
new file mode 100644
index 0000000..5fc2b60
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8017-pmi8950.dts
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/dts-v1/;
+
+#include "apq8017.dtsi"
+#include "msm8917-pmi8950.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. MSM8917 + PMI8950 SOC ";
+ compatible = "qcom,msm8917";
+ qcom,pmic-id = <0x10019 0x010011 0x0 0x0>;
+ qcom,pmic-name = "PMI8950";
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8053-dragon-memory.dtsi b/arch/arm64/boot/dts/qcom/apq8053-dragon-memory.dtsi
new file mode 100644
index 0000000..a26926a
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8053-dragon-memory.dtsi
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+&modem_mem {
+ reg = <0x0 0x86c00000 0x0 0x1800000>;
+};
+
+&adsp_fw_mem {
+ reg = <0x0 0x88400000 0x0 0x1100000>;
+};
+
+&wcnss_fw_mem {
+ reg = <0x0 0x89500000 0x0 0x700000>;
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8053-ipc.dts b/arch/arm64/boot/dts/qcom/apq8053-ipc.dts
index 3381b2a..5004d71 100644
--- a/arch/arm64/boot/dts/qcom/apq8053-ipc.dts
+++ b/arch/arm64/boot/dts/qcom/apq8053-ipc.dts
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018, 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
@@ -15,7 +15,8 @@
#include "apq8053.dtsi"
#include "msm8953-ipc.dtsi"
-
+#include "pmi8950.dtsi"
+#include "msm8953-pmi8950.dtsi"
/ {
model = "Qualcomm Technologies, Inc. APQ8053 + PMI8950 IPC";
compatible = "qcom,apq8053-ipc", "qcom,apq8053", "qcom,ipc";
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.0.dts b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.0.dts
index 55d8b7b..9961a97 100644
--- a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.0.dts
+++ b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.0.dts
@@ -25,3 +25,8 @@
&blsp2_uart0 {
status = "okay";
};
+
+&blsp2_uart1 { /* UART6 */
+ status = "okay";
+};
+
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.2.dts b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.2.dts
index ecc4fea..599f3ef 100644
--- a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.2.dts
+++ b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.2.dts
@@ -25,3 +25,12 @@
&blsp2_uart0 {
status = "okay";
};
+
+&i2c_3 {
+ status = "okay";
+ /delete-node/ himax_ts@48;
+ gt9xx-i2c@14 {
+ status = "okay";
+ };
+};
+
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon.dtsi b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon.dtsi
index bd48f09..f7a2026 100644
--- a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon.dtsi
+++ b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon.dtsi
@@ -16,6 +16,7 @@
#include "apq8053-camera-sensor-dragon.dtsi"
#include "pmi8950.dtsi"
#include "msm8953-pmi8950.dtsi"
+#include "apq8053-dragon-memory.dtsi"
&soc {
vreg_5p0: vreg_5p0 {
@@ -103,6 +104,25 @@
pinctrl-1 = <&sec_tlmm_lines_sus>;
};
+ gpio_keys {
+ compatible = "gpio-keys";
+ input-name = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&gpio_key_active>;
+ vol_up {
+ label = "volume_up";
+ gpios = <&tlmm 85 0x1>;
+ linux,input-type = <1>;
+ linux,code = <115>;
+ debounce-interval = <15>;
+ linux,can-disable;
+ gpio-key,wakeup;
+ };
+ };
+
+ qcom,rmnet-ipa {
+ status = "disabled";
+ };
};
&firmware {
@@ -203,6 +223,79 @@
himax,irq-gpio = <&tlmm 65 0x2008>;
report_type = <1>;
};
+
+ gt9xx-i2c@14 {
+ compatible = "goodix,gt9xx";
+ reg = <0x14>;
+ vdd_ana-supply = <&pm8953_l10>;
+ vcc_i2c-supply = <&pm8953_l6>;
+ interrupt-parent = <&tlmm>;
+ interrupts = <65 0x2008>;
+ pinctrl-names = "gdix_ts_int_default", "gdix_ts_int_output_low",
+ "gdix_ts_int_output_high", "gdix_ts_int_input",
+ "gdix_ts_rst_default", "gdix_ts_rst_output_low",
+ "gdix_ts_rst_output_high", "gdix_ts_rst_input";
+ pinctrl-0 = <&ts_int_default>;
+ pinctrl-1 = <&ts_int_output_low>;
+ pinctrl-2 = <&ts_int_output_high>;
+ pinctrl-3 = <&ts_int_input>;
+ pinctrl-4 = <&ts_rst_default>;
+ pinctrl-5 = <&ts_rst_output_low>;
+ pinctrl-6 = <&ts_rst_output_high>;
+ pinctrl-7 = <&ts_rst_input>;
+
+ reset-gpios = <&tlmm 64 0x00>;
+ irq-gpios = <&tlmm 65 0x2008>;
+ irq-flags = <2>;
+
+ touchscreen-max-id = <11>;
+ touchscreen-size-x = <1200>;
+ touchscreen-size-y = <1920>;
+ touchscreen-max-w = <1024>;
+ touchscreen-max-p = <1024>;
+
+ goodix,type-a-report = <0>;
+ goodix,driver-send-cfg = <1>;
+ goodix,wakeup-with-reset = <0>;
+ goodix,resume-in-workqueue = <0>;
+ goodix,int-sync = <1>;
+ goodix,swap-x2y = <0>;
+ goodix,esd-protect = <1>;
+ goodix,pen-suppress-finger = <0>;
+ goodix,auto-update = <1>;
+ goodix,auto-update-cfg = <0>;
+ goodix,power-off-sleep = <0>;
+
+ goodix,cfg-group0 = [
+ 5A B0 04 80 07 0A 35 10 22 08 32 0D 50 3C 0A 04
+ 01 01 00 B4 11 11 44 15 19 1B 14 95 35 FF 3A 3C
+ 39 13 00 00 00 98 03 1C 00 00 00 00 03 00 00 00
+ 00 80 0A 37 46 40 E5 52 23 28 00 04 81 38 00 7F
+ 3B 00 7D 3E 00 7C 41 00 7A 44 0C 7A 00 50 33 50
+ 0B 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 55 00 01 00 00 02 00 00 00
+ 1D 1C 1B 1A 19 18 17 16 15 14 13 12 11 10 0F 0E
+ 0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 00 2A 29
+ 28 27 26 25 24 23 22 21 20 1F 1E 1D 1C 1B 19 18
+ 17 16 15 14 13 12 11 10 0F 0E 0D 0C 0B 0A 09 08
+ 07 06 05 04 03 02 01 00 08 01
+ ];
+
+ goodix,cfg-group2 = [
+ 5B B0 04 80 07 0A 35 10 22 08 32 0D 50 32 0A 04
+ 01 01 00 B4 11 11 44 2B 31 36 28 95 35 FF 3E 40
+ 39 13 00 00 00 DA 03 1C 00 00 00 00 03 00 00 00
+ 00 80 0A 32 42 40 E5 52 23 28 00 04 7D 33 00 7D
+ 36 00 7E 39 00 7F 3C 00 80 40 0C 80 00 50 33 50
+ 0B 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 55 00 01 00 00 02 00 00 00
+ 1D 1C 1B 1A 19 18 17 16 15 14 13 12 11 10 0F 0E
+ 0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 00 2A 29
+ 28 27 26 25 24 23 22 21 20 1F 1E 1D 1C 1B 19 18
+ 17 16 15 14 13 12 11 10 0F 0E 0D 0C 0B 0A 09 08
+ 07 06 05 04 03 02 01 00 81 01
+ ];
+ };
};
&soc {
@@ -319,7 +412,7 @@
pins = "gpio75";
drive-strength = <10>;
bias-pull-up;
- output-low;
+ output-high;
};
};
sdc2_wlan_gpio_off: sdc2_wlan_gpio_off {
@@ -358,14 +451,6 @@
};
&spmi_bus {
- qcom,pm8953@0 {
- qcom,power-on@800 {
- qcom,resin-gpiobase = <1019>;
- qcom,pon_2 {
- /delete-property/ linux,code;
- };
- };
- };
qcom,pmi8950@2 {
qcom,leds@a100 {
compatible = "qcom,leds-qpnp";
@@ -495,3 +580,11 @@
status = "okay";
};
};
+
+&ipa_hw {
+ status = "disabled";
+};
+
+&msm_gpu {
+ /delete-node/ qcom,gpu-mempools;
+};
diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-hx83112a-truly-singlemipi-fhd-video.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-hx83112a-truly-singlemipi-fhd-video.dtsi
new file mode 100644
index 0000000..e065f00
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-hx83112a-truly-singlemipi-fhd-video.dtsi
@@ -0,0 +1,157 @@
+/* Copyright (c) 2018, 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.
+ */
+
+&mdss_mdp {
+ dsi_hx83112a_truly_video: qcom,mdss_dsi_hx83112a_truly_video {
+ qcom,mdss-dsi-panel-name =
+ "hx83112a video mode dsi truly panel";
+ qcom,mdss-dsi-panel-type = "dsi_video_mode";
+
+ qcom,mdss-dsi-virtual-channel-id = <0>;
+ qcom,mdss-dsi-stream = <0>;
+ qcom,mdss-dsi-h-left-border = <0>;
+ qcom,mdss-dsi-h-right-border = <0>;
+ qcom,mdss-dsi-v-top-border = <0>;
+ qcom,mdss-dsi-v-bottom-border = <0>;
+ qcom,mdss-dsi-bpp = <24>;
+ qcom,mdss-dsi-color-order = "rgb_swap_rgb";
+ qcom,mdss-dsi-underflow-color = <0xff>;
+ qcom,mdss-dsi-border-color = <0>;
+ qcom,mdss-dsi-h-sync-pulse = <0>;
+ qcom,mdss-dsi-traffic-mode = "non_burst_sync_event";
+ qcom,mdss-dsi-lane-map = "lane_map_0123";
+ qcom,mdss-dsi-bllp-eof-power-mode;
+ qcom,mdss-dsi-bllp-power-mode;
+ qcom,mdss-dsi-tx-eot-append;
+ qcom,mdss-dsi-lane-0-state;
+ qcom,mdss-dsi-lane-1-state;
+ qcom,mdss-dsi-lane-2-state;
+ qcom,mdss-dsi-lane-3-state;
+ qcom,mdss-dsi-dma-trigger = "trigger_sw";
+ qcom,mdss-dsi-mdp-trigger = "none";
+ qcom,mdss-dsi-lp11-init;
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,mdss-dsi-reset-sequence = <1 10>, <0 10>, <1 10>;
+
+ qcom,mdss-dsi-display-timings {
+ timing@0 {
+ qcom,mdss-dsi-panel-width = <1080>;
+ qcom,mdss-dsi-panel-height = <2160>;
+ qcom,mdss-dsi-h-front-porch = <42>;
+ qcom,mdss-dsi-h-back-porch = <42>;
+ qcom,mdss-dsi-h-pulse-width = <10>;
+ qcom,mdss-dsi-h-sync-skew = <0>;
+ qcom,mdss-dsi-v-back-porch = <15>;
+ qcom,mdss-dsi-v-front-porch = <10>;
+ qcom,mdss-dsi-v-pulse-width = <3>;
+ qcom,mdss-dsi-panel-framerate = <60>;
+ qcom,mdss-dsi-on-command = [
+ 39 01 00 00 00 00 04 B9 83 11 2A
+ 39 01 00 00 00 00 09 B1 08 29 29 00 00 4F 54
+ 33
+ 39 01 00 00 00 00 11 B2 00 02 00 80 70 00 08
+ 26 FC 01 00 03 15 A3 87 09
+ 39 01 00 00 00 00 02 BD 02
+ 39 01 00 00 00 00 02 BD 00
+ 39 01 00 00 00 00 03 D2 2C 2C
+ 39 01 00 00 00 00 1C B4 01 CE 01 CE 01 CE 0A
+ CE 0A CE 0A CE 00 FF 00 FF 00 00 22 23 00
+ 28 0A 13 14 00 8A
+ 39 01 00 00 00 00 02 BD 02
+ 39 01 00 00 00 00 0A B4 00 92 12 22 88 12 12
+ 00 53
+ 39 01 00 00 00 00 02 BD 00
+ 39 01 00 00 00 00 04 B6 82 82 E3
+ 39 01 00 00 00 00 02 CC 08
+ 39 01 00 00 00 00 2B D3 40 00 00 00 00 01 01
+ 0A 0A 07 07 00 08 09 09 09 09 32 10 09 00
+ 09 32 21 0A 00 0A 32 10 08 00 00 00 00 00
+ 00 00 00 00 0B 08 82
+ 39 01 00 00 00 00 02 BD 01
+ 39 01 00 00 00 00 09 D3 00 00 19 00 00 0A 00
+ 81
+ 39 01 00 00 00 00 02 BD 00
+ 39 01 00 00 00 00 31 D5 18 18 18 18 18 18 18
+ 18 31 31 30 30 2F 2F 31 31 30 30 2F 2F C0
+ 18 40 40 01 00 07 06 05 04 03 02 21 20 18
+ 18 19 19 18 18 03 03 18 18 18 18 18 18
+ 39 01 00 00 00 00 31 D6 18 18 18 18 18 18 18
+ 18 31 31 30 30 2F 2F 31 31 30 30 2F 2F C0
+ 18 40 40 02 03 04 05 06 07 00 01 20 21 18
+ 18 18 18 19 19 20 20 18 18 18 18 18 18
+ 39 01 00 00 00 00 19 D8 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00
+ 39 01 00 00 00 00 02 BD 01
+ 39 01 00 00 00 00 19 D8 AA AA AA AA AA AA AA
+ AA AA AA AA AA AA AA AA AA AA AA AA AA AA
+ AA AA AA
+ 39 01 00 00 00 00 02 BD 02
+ 39 01 00 00 00 00 0D D8 AF FF FA AA BA AA AA
+ FF FA AA BA AA
+ 39 01 00 00 00 00 02 BD 03
+ 39 01 00 00 00 00 19 D8 AA AA AA AA AA AA AA
+ AA AA AA AA AA AA AA AA AA AA AA AA AA AA
+ AA AA AA
+ 39 01 00 00 00 00 02 BD 00
+ 39 01 00 00 00 00 18 E7 0E 0E 1E 6A 1D 6A 00
+ 32 02 02 00 00 02 02 02 05 14 14 32 B9 23
+ B9 08
+ 39 01 00 00 00 00 02 BD 01
+ 39 01 00 00 00 00 0A E7 02 00 98 01 9A 0D A8
+ 0E 01
+ 39 01 00 00 00 00 02 BD 02
+ 39 01 00 00 00 00 1E E7 00 00 08 00 01 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 04 00 00 00 00 02 00
+ 39 01 00 00 00 00 02 BD 00
+ 39 01 00 00 00 00 02 C1 01
+ 39 01 00 00 00 00 02 BD 01
+ 39 01 00 00 00 00 3A C1 FF F7 F0 E9 E2 DB D4
+ C6 BF B8 B1 AB A5 9F 99 94 8E 8A 85 7C 74
+ 6C 65 5F 58 52 4B 47 42 3C 37 31 2C 27 22
+ 1C 18 12 0D 08 05 04 02 01 00 27 B9 BE 54
+ C6 B8 9C 37 43 3D E5 00
+ 39 01 00 00 00 00 02 BD 02
+ 39 01 00 00 00 00 3A C1 FF F7 F0 E9 E2 DB D4
+ C6 BF B8 B1 AB A5 9F 99 94 8E 8A 85 7C 74
+ 6C 65 5F 58 52 4B 47 42 3C 37 31 2C 27 22
+ 1C 18 12 0D 08 05 04 02 01 00 27 B9 BE 54
+ C6 B8 9C 37 43 3D E5 00
+ 39 01 00 00 00 00 02 BD 03
+ 39 01 00 00 00 00 3A C1 FF F7 F0 E9 E2 DB D4
+ C6 BF B8 B1 AB A5 9F 99 94 8E 8A 85 7C 74
+ 6C 65 5F 58 52 4B 47 42 3C 37 31 2C 27 22
+ 1C 18 12 0D 08 05 04 02 01 00 27 B9 BE 54
+ C6 B8 9C 37 43 3D E5 00
+ 39 01 00 00 00 00 02 BD 00
+ 39 01 00 00 00 00 02 E9 C3
+ 39 01 00 00 00 00 03 CB 92 01
+ 39 01 00 00 00 00 02 E9 3F
+ 39 01 00 00 00 00 07 C7 70 00 04 E0 33 00
+ 39 01 00 00 00 00 03 51 0F FF
+ 39 01 00 00 00 00 02 53 24
+ 39 01 00 00 00 00 02 55 00
+ 15 01 00 00 00 00 02 35 00
+ 05 01 00 00 96 00 02 11 00
+ 05 01 00 00 32 00 02 29 00];
+ qcom,mdss-dsi-off-command = [
+ 05 01 00 00 32 00 02 28 00
+ 05 01 00 00 96 00 02 10 00];
+ qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+ qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
+ };
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-hx8399c-hd-plus-video.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-hx8399c-hd-plus-video.dtsi
index 91bf722..89c5178 100644
--- a/arch/arm64/boot/dts/qcom/dsi-panel-hx8399c-hd-plus-video.dtsi
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-hx8399c-hd-plus-video.dtsi
@@ -20,13 +20,13 @@
qcom,mdss-dsi-stream = <0>;
qcom,mdss-dsi-panel-width = <720>;
qcom,mdss-dsi-panel-height = <1440>;
- qcom,mdss-dsi-h-front-porch = <24>;
- qcom,mdss-dsi-h-back-porch = <24>;
+ qcom,mdss-dsi-h-front-porch = <48>;
+ qcom,mdss-dsi-h-back-porch = <48>;
qcom,mdss-dsi-h-pulse-width = <16>;
qcom,mdss-dsi-h-sync-skew = <0>;
qcom,mdss-dsi-v-back-porch = <40>;
- qcom,mdss-dsi-v-front-porch = <36>;
- qcom,mdss-dsi-v-pulse-width = <2>;
+ qcom,mdss-dsi-v-front-porch = <60>;
+ qcom,mdss-dsi-v-pulse-width = <4>;
qcom,mdss-dsi-h-left-border = <0>;
qcom,mdss-dsi-h-right-border = <0>;
qcom,mdss-dsi-v-top-border = <0>;
diff --git a/arch/arm64/boot/dts/qcom/fg-gen3-batterydata-mlp466076-3250mah.dtsi b/arch/arm64/boot/dts/qcom/fg-gen3-batterydata-mlp466076-3250mah.dtsi
new file mode 100644
index 0000000..09c21ed
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/fg-gen3-batterydata-mlp466076-3250mah.dtsi
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+qcom,mlp466076_3250mah_averaged_masterslave_jun15th2018 {
+ /* #mlp466076_3250mAh_averaged_MasterSlave_Jun15th2018 */
+ qcom,max-voltage-uv = <4400000>;
+ qcom,nom-batt-capacity-mah = <3250>;
+ qcom,fastchg-current-ma = <6000>;
+ qcom,jeita-fcc-ranges = <0 150 650000
+ 151 450 4875000
+ 451 550 1625000>;
+ qcom,jeita-fv-ranges = <0 150 4150000
+ 151 450 4400000
+ 451 550 4150000>;
+ qcom,batt-id-kohm = <133>;
+ qcom,battery-beta = <4250>;
+ qcom,fg-cc-cv-threshold-mv = <4390>;
+ qcom,battery-type = "mlp466076_3250mah_jun15th2018";
+ qcom,checksum = <0x8905>;
+ qcom,gui-version = "PM660GUI - 0.0.0.45";
+ qcom,fg-profile-data = [
+ 5E 21 D2 0D
+ E3 0B 04 05
+ EC 1C 8B 01
+ 4F 05 31 03
+ 80 18 D2 22
+ C2 45 73 52
+ 90 00 00 00
+ 13 00 00 00
+ 00 00 82 C3
+ A3 CC 92 BC
+ 2F 00 08 00
+ 14 DA CE E5
+ B0 04 41 02
+ C5 F4 C4 12
+ 0C 07 3F 32
+ 2B 06 09 20
+ 27 00 14 00
+ 4C 20 E0 04
+ 1A 0B A1 05
+ C4 1C E7 02
+ 3E 0C 02 12
+ 9D 18 4C 23
+ DC 44 15 5A
+ 70 00 00 00
+ 10 00 00 00
+ 00 00 F6 07
+ 1D CB 02 B4
+ 20 00 00 00
+ 5B E3 CE E5
+ C8 05 54 01
+ A6 06 BD FB
+ 35 F4 47 23
+ C5 33 CC FF
+ 07 10 00 00
+ 38 0D 66 46
+ 20 00 40 00
+ 61 01 0A FA
+ FF 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ ];
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8909-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/msm8909-pinctrl.dtsi
index eda92c5..c69e699 100644
--- a/arch/arm64/boot/dts/qcom/msm8909-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8909-pinctrl.dtsi
@@ -545,6 +545,33 @@
};
};
+ imu {
+ imu_int_active: imu_int_active{
+ mux {
+ pins = "gpio12";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio12";
+ drive-strength = <6>;
+ bias-pull-up;
+ };
+ };
+
+ imu_int_suspend: imu_int_suspend{
+ mux {
+ pins = "gpio12";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio12";
+ drive-strength = <6>;
+ bias-pull-up;
+ };
+ };
+
+ };
+
nfc {
nfcw_int_active: nfcw_int_active {
mux {
@@ -1917,6 +1944,32 @@
};
};
+ cdc_reset1_ctrl {
+ cdc_reset1_sleep: cdc_reset1_sleep {
+ mux {
+ pins = "gpio23";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio23";
+ drive-strength = <16>;
+ bias-disable;
+ output-low;
+ };
+ };
+ cdc_reset1_active:cdc_reset1_active {
+ mux {
+ pins = "gpio23";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio23";
+ drive-strength = <16>;
+ bias-pull-down;
+ output-high;
+ };
+ };
+ };
cdc-dmic-lines {
cdc_dmic0_clk_act: dmic0_clk_on {
@@ -2219,5 +2272,32 @@
};
};
+ spkr_en {
+ label = "spkr_en";
+ spkr_en_active: spkr_en_active {
+ mux {
+ pins = "gpio72";
+ function = "gpio";
+ };
+ configs {
+ pins = "gpio72";
+ drive-strength = <8>; /* 8 MA */
+ output-high;
+ };
+ };
+ spkr_en_sleep: spkr_en_sleep {
+ mux {
+ pins = "gpio72";
+ function = "gpio";
+ };
+ configs {
+ pins = "gpio72";
+ drive-strength = <2>; /* 2 MA */
+ input-enable; /* PULL DOWN */
+ };
+ };
+ };
+
+
};
};
diff --git a/arch/arm64/boot/dts/qcom/msm8909-pm8916-camera-sensor-robot-som.dtsi b/arch/arm64/boot/dts/qcom/msm8909-pm8916-camera-sensor-robot-som.dtsi
new file mode 100644
index 0000000..9c0e539
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8909-pm8916-camera-sensor-robot-som.dtsi
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2017-2018, 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_3 {
+ status = "ok";
+};
+
+&i2c_3 {
+ qcom,camera@0 {
+ cell-index = <0>;
+ compatible = "qcom,camera";
+ reg = <0x2>;
+ qcom,csiphy-sd-index = <0>;
+ qcom,csid-sd-index = <0>;
+ qcom,mount-angle = <90>;
+ cam_vdig-supply = <&pm8916_l2>;
+ cam_vana-supply = <&pm8916_l17>;
+ cam_vio-supply = <&pm8916_l6>;
+ qcom,cam-vreg-type = <0 0 0>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+ qcom,cam-vreg-min-voltage = <1200000 1800000 2850000>;
+ qcom,cam-vreg-max-voltage = <1200000 1800000 2850000>;
+ qcom,cam-vreg-op-mode = <200000 0 80000>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk0_default
+ &cam_sensor_rear_default>;
+ pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep>;
+ gpios = <&msm_gpio 26 0>,
+ <&msm_gpio 35 0>,
+ <&msm_gpio 34 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,sensor-position = <0>;
+ qcom,sensor-mode = <0>;
+ status = "ok";
+ clocks = <&clock_gcc clk_mclk0_clk_src>,
+ <&clock_gcc clk_gcc_camss_mclk0_clk>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <24000000 0>;
+ };
+
+ qcom,camera@1 {
+ cell-index = <1>;
+ compatible = "qcom,camera";
+ reg = <0x1>;
+ qcom,csiphy-sd-index = <0>;
+ qcom,csid-sd-index = <1>;
+ qcom,mount-angle = <90>;
+ cam_vana-supply = <&pm8916_l17>;
+ cam_vio-supply = <&pm8916_l6>;
+ qcom,cam-vreg-name = "cam_vio","cam_vana";
+ qcom,cam-vreg-min-voltage = <1800000 2850000>;
+ qcom,cam-vreg-max-voltage = <1800000 2850000>;
+ qcom,cam-vreg-op-mode = <0 80000>;
+ qcom,cam-vreg-type = <0 0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk0_default
+ &cam_sensor_rear_default>;
+ pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep>;
+ gpios = <&msm_gpio 26 0>,
+ <&msm_gpio 91 0>;
+ qcom,gpio-reset = <1>;
+
+ qcom,gpio-req-tbl-num = <0 1>;
+ qcom,gpio-req-tbl-flags = <1 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+ "CAM_RESET";
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <0>;
+ status = "ok";
+ clocks = <&clock_gcc clk_mclk0_clk_src>,
+ <&clock_gcc clk_gcc_camss_mclk0_clk>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <24000000 0>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8909-pm8916-camera-sensor-robot.dtsi b/arch/arm64/boot/dts/qcom/msm8909-pm8916-camera-sensor-robot.dtsi
index 6f6655a..ce12d33 100644
--- a/arch/arm64/boot/dts/qcom/msm8909-pm8916-camera-sensor-robot.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8909-pm8916-camera-sensor-robot.dtsi
@@ -16,6 +16,95 @@
};
&i2c_3 {
+ otp_eeprom: qcom,msm_eeprom@6e{
+ status = "ok";
+ cell-index = <0>;
+ reg = <0x6e>;
+ compatible = "msm_eeprom";
+ qcom,eeprom-name = "sunny_imx241_otp";
+ qcom,slave-addr = <0x6e>;
+ qcom,i2c-freq-mode = <1>;
+
+ cam_vdig-supply = <&pm8916_l2>;
+ cam_vio-supply = <&pm8916_l6>;
+ cam_vana-supply = <&pm8916_l17>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+ qcom,cam-vreg-min-voltage = <1200000 1800000 2850000>;
+ qcom,cam-vreg-max-voltage = <1200000 1800000 2850000>;
+ qcom,cam-vreg-op-mode = <200000 0 80000>;
+ qcom,cam-vreg-type = <0 0 0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk0_default
+ &cam_sensor_rear_default>;
+ pinctrl-1 = <&cam_sensor_mclk0_sleep
+ &cam_sensor_rear_sleep>;
+ gpios = <&msm_gpio 26 0>,
+ <&msm_gpio 35 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-req-tbl-num = <0 1>;
+ qcom,gpio-req-tbl-flags = <1 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK", "CAM_RESET";
+
+ qcom,cam-power-seq-type = "sensor_vreg",
+ "sensor_vreg",
+ "sensor_vreg",
+ "sensor_gpio",
+ "sensor_clk",
+ "sensor_i2c_mux";
+ qcom,cam-power-seq-val = "cam_vana",
+ "cam_vdig",
+ "cam_vio",
+ "sensor_gpio_reset",
+ "sensor_cam_mclk",
+ "none";
+ qcom,cam-power-seq-cfg-val = <2850000 1200000
+ 1800000 1 24000000 0>;
+ qcom,cam-power-seq-delay = <1 1 1 1 1 0>;
+
+ clocks = <&clock_gcc clk_mclk0_clk_src>,
+ <&clock_gcc clk_gcc_camss_mclk0_clk>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <24000000 0>;
+
+ qcom,num-blocks = <12>;
+ qcom,page0 = <1 0x34C5 2 0x02 1 1>;
+ qcom,poll0 = <0 0x0 2 0 1 1>;
+ qcom,mem0 = <0 0x0 2 0 1 0>;
+ qcom,page1 = <1 0x34C9 2 0x02 1 10>;
+ qcom,poll1 = <0 0x0 2 0 1 1>;
+ qcom,mem1 = <8 0x3510 2 0 1 0>;
+ qcom,page2 = <1 0x34C5 2 0x03 1 1>;
+ qcom,poll2 = <0 0x0 2 0 1 1>;
+ qcom,mem2 = <0 0x0 2 0 1 0>;
+ qcom,page3 = <1 0x34C9 2 0x03 1 10>;
+ qcom,poll3 = <0 0x0 2 0 1 1>;
+ qcom,mem3 = <8 0x3518 2 0 1 0>;
+ qcom,page4 = <1 0x34C5 2 0x06 1 1>;
+ qcom,poll4 = <0 0x0 2 0 1 1>;
+ qcom,mem4 = <0 0x0 2 0 1 0>;
+ qcom,page5 = <1 0x34C9 2 0x06 1 10>;
+ qcom,poll5 = <0 0x0 2 0 1 1>;
+ qcom,mem5 = <8 0x3530 2 0 1 0>;
+ qcom,page6 = <1 0x34C5 2 0x07 1 1>;
+ qcom,poll6 = <0 0x0 2 0 1 1>;
+ qcom,mem6 = <0 0x0 2 0 1 0>;
+ qcom,page7 = <1 0x34C9 2 0x07 1 10>;
+ qcom,poll7 = <0 0x0 2 0 1 1>;
+ qcom,mem7 = <8 0x3538 2 0 1 0>;
+ qcom,page8 = <1 0x34C5 2 0x0A 1 1>;
+ qcom,poll8 = <0 0x0 2 0 1 1>;
+ qcom,mem8 = <0 0x0 2 0 1 0>;
+ qcom,page9 = <1 0x34C9 2 0x0A 1 10>;
+ qcom,poll9 = <0 0x0 2 0 1 1>;
+ qcom,mem9 = <8 0x3550 2 0 1 0>;
+ qcom,page10 = <1 0x34C5 2 0x0B 1 1>;
+ qcom,poll10 = <0 0x0 2 0 1 1>;
+ qcom,mem10 = <0 0x0 2 0 1 0>;
+ qcom,page11 = <1 0x34C9 2 0x0B 1 10>;
+ qcom,poll11 = <0 0x0 2 0 1 1>;
+ qcom,mem11 = <8 0x3558 2 0 1 0>;
+ };
+
qcom,camera@0 {
cell-index = <0>;
compatible = "qcom,camera";
@@ -26,6 +115,7 @@
cam_vdig-supply = <&pm8916_l2>;
cam_vana-supply = <&pm8916_l17>;
cam_vio-supply = <&pm8916_l6>;
+ qcom,cam-vreg-type = <0 0 0>;
qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
qcom,cam-vreg-min-voltage = <1200000 1800000 2850000>;
qcom,cam-vreg-max-voltage = <1200000 1800000 2850000>;
@@ -46,6 +136,7 @@
"CAM_STANDBY";
qcom,sensor-position = <0>;
qcom,sensor-mode = <0>;
+ qcom,eeprom-src = <&otp_eeprom>;
status = "ok";
clocks = <&clock_gcc clk_mclk0_clk_src>,
<&clock_gcc clk_gcc_camss_mclk0_clk>;
@@ -66,6 +157,7 @@
qcom,cam-vreg-min-voltage = <1800000 2850000>;
qcom,cam-vreg-max-voltage = <1800000 2850000>;
qcom,cam-vreg-op-mode = <0 80000>;
+ qcom,cam-vreg-type = <0 0>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk0_default
&cam_sensor_rear_default>;
diff --git a/arch/arm64/boot/dts/qcom/msm8909.dtsi b/arch/arm64/boot/dts/qcom/msm8909.dtsi
index 8984360..1e3e497 100644
--- a/arch/arm64/boot/dts/qcom/msm8909.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8909.dtsi
@@ -839,6 +839,7 @@
qcom,hsusb-otg-otg-control = <2>; /* PMIC */
qcom,dp-manual-pullup;
qcom,phy-dvdd-always-on;
+ qcom,hsusb-otg-delay-lpm;
qcom,hsusb-otg-mpm-dpsehv-int = <49>;
qcom,hsusb-otg-mpm-dmsehv-int = <58>;
@@ -1352,7 +1353,7 @@
clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>,
<&clock_gcc clk_gcc_blsp1_qup1_i2c_apps_clk>;
clock-names = "iface_clk", "core_clk";
- qcom,clk-freq-out = <100000>;
+ qcom,clk-freq-out = <400000>;
qcom,clk-freq-in = <19200000>;
pinctrl-names = "i2c_active", "i2c_sleep";
pinctrl-0 = <&i2c_1_active>;
diff --git a/arch/arm64/boot/dts/qcom/msm8917-camera-sensor-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8917-camera-sensor-mtp.dtsi
new file mode 100644
index 0000000..23c0987
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-camera-sensor-mtp.dtsi
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) 2015-2018, 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.
+ */
+
+&cci {
+ actuator0: qcom,actuator@0 {
+ cell-index = <0>;
+ reg = <0x0>;
+ compatible = "qcom,actuator";
+ qcom,cci-master = <0>;
+ cam_vaf-supply = <&pm8937_l17>;
+ qcom,cam-vreg-name = "cam_vaf";
+ qcom,cam-vreg-min-voltage = <2850000>;
+ qcom,cam-vreg-max-voltage = <2850000>;
+ qcom,cam-vreg-op-mode = <80000>;
+ };
+
+ actuator1: qcom,actuator@1 {
+ cell-index = <1>;
+ reg = <0x1>;
+ compatible = "qcom,actuator";
+ qcom,cci-master = <0>;
+ cam_vaf-supply = <&pm8937_l17>;
+ qcom,cam-vreg-name = "cam_vaf";
+ qcom,cam-vreg-min-voltage = <2850000>;
+ qcom,cam-vreg-max-voltage = <2850000>;
+ qcom,cam-vreg-op-mode = <80000>;
+ };
+
+ eeprom0: qcom,eeprom@0 {
+ cell-index = <0>;
+ compatible = "qcom,eeprom";
+ qcom,cci-master = <0>;
+ reg = <0x0>;
+ cam_vdig-supply = <&pm8937_l23>;
+ cam_vana-supply = <&pm8937_l22>;
+ cam_vio-supply = <&pm8937_l6>;
+ cam_vaf-supply = <&pm8937_l17>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vana", "cam_vio",
+ "cam_vaf";
+ qcom,cam-vreg-min-voltage = <1200000 0 2800000 2850000>;
+ qcom,cam-vreg-max-voltage = <1200000 0 2800000 2850000>;
+ qcom,cam-vreg-op-mode = <200000 0 80000 100000>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk0_default
+ &cam_sensor_rear_default>;
+ pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep>;
+ gpios = <&tlmm 26 0>,
+ <&tlmm 36 0>,
+ <&tlmm 35 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_MCLK0",
+ "CAM_RESET0",
+ "CAM_STANDBY0";
+ status = "ok";
+ clocks = <&clock_gcc clk_mclk0_clk_src>,
+ <&clock_gcc clk_gcc_camss_mclk0_clk>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <19200000 0>;
+ };
+
+ eeprom1: qcom,eeprom@1 {
+ cell-index = <1>;
+ reg = <0x1>;
+ qcom,eeprom-name = "sunny_8865";
+ compatible = "qcom,eeprom";
+ qcom,slave-addr = <0x6c>;
+ qcom,cci-master = <0>;
+ qcom,num-blocks = <8>;
+
+ qcom,page0 = <1 0x0100 2 0x01 1 1>;
+ qcom,poll0 = <0 0x0 2 0x0 1 0>;
+ qcom,mem0 = <0 0x0 2 0x0 1 0>;
+
+ qcom,page1 = <1 0x5002 2 0x00 1 0>;
+ qcom,poll1 = <0 0x0 2 0x0 1 0>;
+ qcom,mem1 = <0 0x0 2 0x0 1 0>;
+
+ qcom,page2 = <1 0x3d84 2 0xc0 1 0>;
+ qcom,poll2 = <0 0x0 2 0x0 1 0>;
+ qcom,mem2 = <0 0x0 2 0x0 1 0>;
+
+ qcom,page3 = <1 0x3d88 2 0x70 1 0>;
+ qcom,poll3 = <0 0x0 2 0x0 1 0>;
+ qcom,mem3 = <0 0x0 2 0x0 1 0>;
+
+ qcom,page4 = <1 0x3d89 2 0x10 1 0>;
+ qcom,poll4 = <0 0x0 2 0x0 1 0>;
+ qcom,mem4 = <0 0x0 2 0x0 1 0>;
+
+ qcom,page5 = <1 0x3d8a 2 0x70 1 0>;
+ qcom,poll5 = <0 0x0 2 0x0 1 0>;
+ qcom,mem5 = <0 0x0 2 0x0 1 0>;
+
+ qcom,page6 = <1 0x3d8b 2 0xf4 1 0>;
+ qcom,poll6 = <0 0x0 2 0x0 1 0>;
+ qcom,mem6 = <0 0x0 2 0x0 1 0>;
+
+ qcom,page7 = <1 0x3d81 2 0x01 1 10>;
+ qcom,poll7 = <0 0x0 2 0x0 1 1>;
+ qcom,mem7 = <1536 0x7010 2 0 1 0>;
+
+ cam_vdig-supply = <&pm8937_l23>;
+ cam_vana-supply = <&pm8937_l22>;
+ cam_vio-supply = <&pm8937_l6>;
+ cam_vaf-supply = <&pm8937_l17>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_vaf";
+ qcom,cam-vreg-min-voltage = <1200000 0 2800000 2850000>;
+ qcom,cam-vreg-max-voltage = <1200000 0 2800000 2850000>;
+ qcom,cam-vreg-op-mode = <105000 0 80000 100000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk2_default
+ &cam_sensor_front1_default>;
+ pinctrl-1 = <&cam_sensor_mclk2_sleep &cam_sensor_front1_sleep>;
+ gpios = <&tlmm 28 0>,
+ <&tlmm 40 0>,
+ <&tlmm 39 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_MCLK2",
+ "CAM_RESET2",
+ "CAM_STANDBY2";
+ qcom,cam-power-seq-type = "sensor_vreg", "sensor_vreg",
+ "sensor_vreg",
+ "sensor_gpio", "sensor_gpio" , "sensor_clk";
+ qcom,cam-power-seq-val = "cam_vdig", "cam_vana", "cam_vio",
+ "sensor_gpio_reset", "sensor_gpio_standby",
+ "sensor_cam_mclk";
+ qcom,cam-power-seq-cfg-val = <1 1 1 1 1 24000000>;
+ qcom,cam-power-seq-delay = <1 1 1 30 30 5>;
+ status = "ok";
+ clocks = <&clock_gcc clk_mclk2_clk_src>,
+ <&clock_gcc clk_gcc_camss_mclk2_clk>;
+ clock-names = "cam_src_clk", "cam_clk";
+ };
+
+ qcom,camera@0 {
+ cell-index = <0>;
+ compatible = "qcom,camera";
+ reg = <0x0>;
+ qcom,csiphy-sd-index = <0>;
+ qcom,csid-sd-index = <0>;
+ qcom,mount-angle = <270>;
+ qcom,led-flash-src = <&led_flash0>;
+ qcom,eeprom-src = <&eeprom0>;
+ qcom,actuator-src = <&actuator0>;
+ cam_vana-supply = <&pm8937_l22>;
+ cam_vio-supply = <&pm8937_l6>;
+ cam_vaf-supply = <&pm8937_l17>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vaf";
+ qcom,cam-vreg-min-voltage = <0 2800000 2850000>;
+ qcom,cam-vreg-max-voltage = <0 2800000 2850000>;
+ qcom,cam-vreg-op-mode = <0 80000 100000>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk0_default
+ &cam_sensor_rear_default
+ &cam_sensor_rear_vdig>;
+ pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep
+ &cam_sensor_rear_vdig_sleep>;
+ gpios = <&tlmm 26 0>,
+ <&tlmm 36 0>,
+ <&tlmm 35 0>,
+ <&tlmm 62 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-standby = <2>;
+ qcom,gpio-vdig = <3>;
+ qcom,gpio-req-tbl-num = <0 1 2 3>;
+ qcom,gpio-req-tbl-flags = <1 0 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK0",
+ "CAM_RESET0",
+ "CAM_STANDBY0",
+ "CAM_VDIG";
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <0>;
+ status = "ok";
+ clocks = <&clock_gcc clk_mclk0_clk_src>,
+ <&clock_gcc clk_gcc_camss_mclk0_clk>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <24000000 0>;
+ };
+
+ qcom,camera@1 {
+ cell-index = <1>;
+ compatible = "qcom,camera";
+ reg = <0x1>;
+ qcom,csiphy-sd-index = <1>;
+ qcom,csid-sd-index = <1>;
+ qcom,mount-angle = <90>;
+ cam_vdig-supply = <&pm8937_l23>;
+ cam_vana-supply = <&pm8937_l22>;
+ cam_vio-supply = <&pm8937_l6>;
+ cam_vaf-supply = <&pm8937_l17>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_vaf";
+ qcom,cam-vreg-min-voltage = <1200000 0 2800000 2850000>;
+ qcom,cam-vreg-max-voltage = <1200000 0 2800000 2850000>;
+ qcom,cam-vreg-op-mode = <200000 0 80000 100000>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk1_default
+ &cam_sensor_front_default>;
+ pinctrl-1 = <&cam_sensor_mclk1_sleep
+ &cam_sensor_front_sleep>;
+ gpios = <&tlmm 27 0>,
+ <&tlmm 38 0>,
+ <&tlmm 50 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_MCLK1",
+ "CAM_RESET1",
+ "CAM_STANDBY1";
+ qcom,sensor-position = <0x100>;
+ qcom,sensor-mode = <1>;
+ qcom,cci-master = <1>;
+ clocks = <&clock_gcc clk_mclk1_clk_src>,
+ <&clock_gcc clk_gcc_camss_mclk1_clk>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <24000000 0>;
+ };
+
+ qcom,camera@2 {
+ cell-index = <2>;
+ compatible = "qcom,camera";
+ reg = <0x02>;
+ qcom,csiphy-sd-index = <1>;
+ qcom,csid-sd-index = <1>;
+ qcom,mount-angle = <90>;
+ qcom,eeprom-src = <&eeprom1>;
+ qcom,actuator-src = <&actuator1>;
+ cam_vdig-supply = <&pm8937_l23>;
+ cam_vana-supply = <&pm8937_l22>;
+ cam_vio-supply = <&pm8937_l6>;
+ cam_vaf-supply = <&pm8937_l17>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_vaf";
+ qcom,cam-vreg-min-voltage = <1200000 0 2800000 2850000>;
+ qcom,cam-vreg-max-voltage = <1200000 0 2800000 2850000>;
+ qcom,cam-vreg-op-mode = <105000 0 80000 100000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk2_default
+ &cam_sensor_front1_default>;
+ pinctrl-1 = <&cam_sensor_mclk2_sleep
+ &cam_sensor_front1_sleep>;
+ gpios = <&tlmm 28 0>,
+ <&tlmm 40 0>,
+ <&tlmm 39 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_MCLK2",
+ "CAM_RESET2",
+ "CAM_STANDBY2";
+ qcom,sensor-position = <1>;
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <0>;
+ status = "ok";
+ clocks = <&clock_gcc clk_mclk2_clk_src>,
+ <&clock_gcc clk_gcc_camss_mclk2_clk>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <24000000 0>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-cdp-ext-codec-overlay.dts b/arch/arm64/boot/dts/qcom/msm8917-cdp-ext-codec-overlay.dts
new file mode 100644
index 0000000..7dba042
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-cdp-ext-codec-overlay.dts
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include "msm8917-cdp.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. MSM8917 External Audio Codec CDP";
+ qcom,board-id = <1 1>;
+};
+
+&pm8937_gpios {
+ gpio@c000 {
+ status = "ok";
+ qcom,mode = <1>;
+ qcom,pull = <5>;
+ qcom,vin-sel = <0>;
+ qcom,src-sel = <2>;
+ qcom,master-en = <1>;
+ qcom,out-strength = <2>;
+ };
+
+ gpio@c600 {
+ status = "ok";
+ qcom,mode = <1>;
+ qcom,pull = <5>;
+ qcom,vin-sel = <0>;
+ qcom,src-sel = <0>;
+ qcom,master-en = <1>;
+ qcom,out-strength = <2>;
+ };
+};
+
+&slim_msm {
+ status = "okay";
+};
+
+&wcd9xxx_intc {
+ status = "okay";
+};
+
+&clock_audio {
+ status = "okay";
+};
+
+&wcd9335 {
+ status = "okay";
+};
+
+&wcd_rst_gpio {
+ status = "okay";
+};
+
+&ext_codec {
+ status = "okay";
+};
+
+&int_codec {
+ status = "disabled";
+};
+
+&wsa881x_i2c_f {
+ status = "disabled";
+};
+
+&wsa881x_i2c_45 {
+ status = "disabled";
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-cdp-mirror-lake-touch.dtsi b/arch/arm64/boot/dts/qcom/msm8917-cdp-mirror-lake-touch.dtsi
index 1f19e20..178af9d 100644
--- a/arch/arm64/boot/dts/qcom/msm8917-cdp-mirror-lake-touch.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8917-cdp-mirror-lake-touch.dtsi
@@ -11,16 +11,14 @@
* GNU General Public License for more details.
*/
-#include "msm8917-pinctrl.dtsi"
/* #include "msm8917-camera-sensor-cdp.dtsi"*/
&soc {
gpio_keys {
compatible = "gpio-keys";
input-name = "gpio-keys";
- pinctrl-names = "tlmm_gpio_key_active", "tlmm_gpio_key_suspend";
+ pinctrl-names = "default";
pinctrl-0 = <&gpio_key_active>;
- pinctrl-1 = <&gpio_key_suspend>;
camera_focus {
label = "camera_focus";
@@ -28,6 +26,8 @@
linux,input-type = <1>;
linux,code = <0x210>;
debounce-interval = <15>;
+ linux,can-disable;
+ gpio-key,wakeup;
};
camera_snapshot {
@@ -36,6 +36,8 @@
linux,input-type = <1>;
linux,code = <0x2fe>;
debounce-interval = <15>;
+ linux,can-disable;
+ gpio-key,wakeup;
};
vol_up {
@@ -44,6 +46,8 @@
linux,input-type = <1>;
linux,code = <115>;
debounce-interval = <15>;
+ linux,can-disable;
+ gpio-key,wakeup;
};
home {
@@ -52,6 +56,8 @@
linux,input-type = <1>;
linux,code = <102>;
debounce-interval = <15>;
+ linux,can-disable;
+ gpio-key,wakeup;
};
};
@@ -106,151 +112,25 @@
pinctrl-names = "default";
pinctrl-0 = <&uart_console_active>;
};
-
-#include "msm8937-mdss-panels.dtsi"
-
-&mdss_mdp {
- qcom,mdss-pref-prim-intf = "dsi";
-};
-
-&mdss_dsi {
- hw-config = "single_dsi";
-};
-
-&mdss_dsi0 {
- qcom,dsi-pref-prim-pan = <&dsi_truly_720_vid>;
- pinctrl-names = "mdss_default", "mdss_sleep";
- pinctrl-0 = <&mdss_dsi_active &mdss_te_active>;
- pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>;
-
- qcom,platform-te-gpio = <&tlmm 24 0>;
- qcom,platform-reset-gpio = <&tlmm 60 0>;
- qcom,platform-bklight-en-gpio = <&tlmm 98 0>;
-};
-
-&dsi_truly_720_vid {
- qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
- qcom,mdss-dsi-pan-enable-dynamic-fps;
- qcom,mdss-dsi-pan-fps-update = "dfps_immediate_porch_mode_vfp";
-};
-
-&dsi_truly_720_cmd {
- qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
- qcom,ulps-enabled;
- qcom,partial-update-enabled;
- qcom,panel-roi-alignment = <2 2 2 2 2 2>;
-};
-
-&dsi_icn9706_720_1440_vid {
- qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
- qcom,mdss-dsi-pan-enable-dynamic-fps;
- qcom,mdss-dsi-pan-fps-update = "dfps_immediate_porch_mode_vfp";
-};
-
-&tlmm {
- tlmm_gpio_key {
- gpio_key_active: gpio_key_active {
- mux {
- pins = "gpio86", "gpio91", "gpio127", "gpio128";
- function = "gpio";
- };
-
- config {
- pins = "gpio86", "gpio91", "gpio127", "gpio128";
- };
- };
-
- gpio_key_suspend: gpio_key_suspend {
- mux {
- pins = "gpio86", "gpio91", "gpio127", "gpio128";
- function = "gpio";
- };
-
- config {
- pins = "gpio86", "gpio91", "gpio127", "gpio128";
- };
- };
- };
-};
-
-&sdhc_1 {
- /* device core power supply */
- vdd-supply = <&pm8937_l8>;
- qcom,vdd-voltage-level = <2900000 2900000>;
- qcom,vdd-current-level = <200 570000>;
-
- /* device communication power supply */
- vdd-io-supply = <&pm8937_l5>;
- qcom,vdd-io-always-on;
- qcom,vdd-io-lpm-sup;
- qcom,vdd-io-voltage-level = <1800000 1800000>;
- qcom,vdd-io-current-level = <200 325000>;
-
- pinctrl-names = "active", "sleep";
- pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on &sdc1_rclk_on>;
- pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off &sdc1_rclk_off>;
-
- qcom,clk-rates = <400000 20000000 25000000 50000000 100000000 192000000
- 384000000>;
- qcom,nonremovable;
- qcom,bus-speed-mode = "HS400_1p8v", "HS200_1p8v", "DDR_1p8v";
-
- status = "ok";
-};
-
-&sdhc_2 {
- /* device core power supply */
- vdd-supply = <&pm8937_l11>;
- qcom,vdd-voltage-level = <2950000 2950000>;
- qcom,vdd-current-level = <15000 800000>;
-
- /* device communication power supply */
- vdd-io-supply = <&pm8937_l12>;
- qcom,vdd-io-voltage-level = <1800000 2950000>;
- qcom,vdd-io-current-level = <200 22000>;
-
- pinctrl-names = "active", "sleep";
- pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>;
- pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off>;
-
- #address-cells = <0>;
- interrupt-parent = <&sdhc_2>;
- interrupts = <0 1 2>;
- #interrupt-cells = <1>;
- interrupt-map-mask = <0xffffffff>;
- interrupt-map = <0 &intc 0 125 0
- 1 &intc 0 221 0
- 2 &tlmm 67 0>;
- interrupt-names = "hc_irq", "pwr_irq", "status_irq";
- cd-gpios = <&tlmm 67 0x1>;
-
- qcom,clk-rates = <400000 20000000 25000000 50000000 100000000
- 200000000>;
- qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
-
- status = "ok";
-};
-
&i2c_3 {
status = "okay";
synaptics@22 {
- compatible = "synaptics,dsx";
+ compatible = "synaptics,dsx-i2c";
reg = <0x22>;
interrupt-parent = <&tlmm>;
interrupts = <65 0x2008>;
- avdd-supply = <&pm8937_l10>;
- vdd-supply = <&pm8937_l5>;
- synaptics,vdd-voltage = <1880000 1880000>;
- synaptics,avdd-voltage = <3008000 3008000>;
- synaptics,vdd-current = <40000>;
- synaptics,avdd-current = <20000>;
+ vdd_ana-supply = <&pm8937_l10>;
+ vcc_i2c-supply = <&pm8937_l5>;
+ synaptics,pwr-reg-name = "vdd_ana";
+ synaptics,bus-reg-name = "vcc_i2c";
pinctrl-names = "pmx_ts_active","pmx_ts_suspend";
pinctrl-0 = <&ts_int_active &ts_reset_active>;
pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
- synaptics,display-coords = <0 0 719 1439>;
- synaptics,panel-coords = <0 0 719 1439>;
- synaptics,reset-gpio = <&tlmm 64 0x00>;
synaptics,irq-gpio = <&tlmm 65 0x2008>;
- synaptics,disable-gpios;
+ synaptics,irq-on-state = <0>;
+ synaptics,irq-flags = <0x2008>;
+ synaptics,power-delay-ms = <200>;
+ synaptics,reset-delay-ms = <200>;
+ synaptics,resume-in-workqueue;
};
};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-cdp-ml-touch-overlay.dts b/arch/arm64/boot/dts/qcom/msm8917-cdp-ml-touch-overlay.dts
new file mode 100644
index 0000000..377eda4
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-cdp-ml-touch-overlay.dts
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/msm-clocks-8952.h>
+#include "msm8917-cdp.dtsi"
+#include "msm8917-cdp-mirror-lake-touch.dtsi"
+#include "msm8917-audio-cdp.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. MSM8917-CDP ML Touch";
+ qcom,board-id = <1 4>;
+};
+
+&soc {
+ led_flash0: qcom,camera-flash {
+ cell-index = <0>;
+ compatible = "qcom,camera-flash";
+ qcom,flash-type = <1>;
+ qcom,flash-source = <&pmi8950_flash0 &pmi8950_flash1>;
+ qcom,torch-source = <&pmi8950_torch0 &pmi8950_torch1>;
+ qcom,switch-source = <&pmi8950_switch>;
+ };
+
+ bluetooth: bt_qca6174 {
+ compatible = "qca,qca6174";
+ qca,bt-reset-gpio = <&tlmm 129 0>; /* BT_EN */
+ };
+};
+
+&qpnp_smbcharger {
+ /delete-property/ dpdm-supply;
+};
+
+&pm8937_gpios {
+ gpio@c400 {
+ qcom,mode = <0>;
+ qcom,output-type = <0>;
+ qcom,pull = <0>;
+ qcom,vin-sel = <2>;
+ qcom,out-strength = <3>;
+ qcom,src-sel = <0>;
+ qcom,master-en = <1>;
+ status = "okay";
+ };
+};
+
+&i2c_5 { /* BLSP2 QUP1 */
+ nq@28 {
+ compatible = "qcom,nq-nci";
+ reg = <0x28>;
+ qcom,nq-irq = <&tlmm 17 0x00>;
+ qcom,nq-ven = <&tlmm 16 0x00>;
+ qcom,nq-firm = <&tlmm 130 0x00>;
+ qcom,nq-clkreq = <&pm8937_gpios 5 0x00>;
+ interrupt-parent = <&tlmm>;
+ qcom,clk-src = "BBCLK2";
+ interrupts = <17 0>;
+ interrupt-names = "nfc_irq";
+ pinctrl-names = "nfc_active", "nfc_suspend";
+ pinctrl-0 = <&nfc_int_active &nfc_disable_active>;
+ pinctrl-1 = <&nfc_int_suspend &nfc_disable_suspend>;
+ clocks = <&clock_gcc clk_bb_clk2_pin>;
+ clock-names = "ref_clk";
+ };
+};
+
+&mdss_dsi0 {
+ lab-supply = <&lab_regulator>;
+ ibb-supply = <&ibb_regulator>;
+};
+
+&labibb {
+ status = "ok";
+ qpnp,qpnp-labibb-mode = "lcd";
+};
+
+&ibb_regulator {
+ qcom,qpnp-ibb-discharge-resistor = <32>;
+};
+
+&dsi_panel_pwr_supply {
+ qcom,panel-supply-entry@2 {
+ reg = <2>;
+ qcom,supply-name = "lab";
+ qcom,supply-min-voltage = <4600000>;
+ qcom,supply-max-voltage = <6000000>;
+ qcom,supply-enable-load = <100000>;
+ qcom,supply-disable-load = <100>;
+ };
+
+ qcom,panel-supply-entry@3 {
+ reg = <3>;
+ qcom,supply-name = "ibb";
+ qcom,supply-min-voltage = <4600000>;
+ qcom,supply-max-voltage = <6000000>;
+ qcom,supply-enable-load = <100000>;
+ qcom,supply-disable-load = <100>;
+ qcom,supply-post-on-sleep = <20>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/msm8917-cdp-overlay.dts
new file mode 100644
index 0000000..c695324
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-cdp-overlay.dts
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include "msm8917-cdp.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. MSM8917-CDP";
+ qcom,board-id = <1 0>,
+ <1 4>,
+ <1 1>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-cdp.dtsi b/arch/arm64/boot/dts/qcom/msm8917-cdp.dtsi
index fde4847..6a2fecd 100644
--- a/arch/arm64/boot/dts/qcom/msm8917-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8917-cdp.dtsi
@@ -10,16 +10,13 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
-#include "msm8917-pinctrl.dtsi"
-/* #include "msm8917-camera-sensor-cdp.dtsi"*/
&soc {
gpio_keys {
compatible = "gpio-keys";
input-name = "gpio-keys";
- pinctrl-names = "tlmm_gpio_key_active","tlmm_gpio_key_suspend";
+ pinctrl-names = "default";
pinctrl-0 = <&gpio_key_active>;
- pinctrl-1 = <&gpio_key_suspend>;
camera_focus {
label = "camera_focus";
@@ -27,6 +24,8 @@
linux,input-type = <1>;
linux,code = <0x210>;
debounce-interval = <15>;
+ linux,can-disable;
+ gpio-key,wakeup;
};
camera_snapshot {
@@ -35,6 +34,8 @@
linux,input-type = <1>;
linux,code = <0x2fe>;
debounce-interval = <15>;
+ linux,can-disable;
+ gpio-key,wakeup;
};
vol_up {
@@ -43,6 +44,8 @@
linux,input-type = <1>;
linux,code = <115>;
debounce-interval = <15>;
+ linux,can-disable;
+ gpio-key,wakeup;
};
home {
@@ -51,6 +54,8 @@
linux,input-type = <1>;
linux,code = <102>;
debounce-interval = <15>;
+ linux,can-disable;
+ gpio-key,wakeup;
};
};
@@ -119,6 +124,12 @@
qcom,panel-roi-alignment = <2 2 2 2 2 2>;
};
+&dsi_icn9706_720_1440_vid {
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+ qcom,mdss-dsi-pan-enable-dynamic-fps;
+ qcom,mdss-dsi-pan-fps-update = "dfps_immediate_porch_mode_vfp";
+};
+
&tlmm {
tlmm_gpio_key {
gpio_key_active: gpio_key_active {
diff --git a/arch/arm64/boot/dts/qcom/msm8917-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/msm8917-mtp-overlay.dts
new file mode 100644
index 0000000..920bcae
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-mtp-overlay.dts
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/clock/msm-clocks-8952.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "msm8917-mtp.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. MSM8917-MTP";
+ qcom,board-id = <8 0>;
+};
+
+&blsp1_uart1 {
+ status = "ok";
+};
+
+&vendor {
+ mtp_batterydata: qcom,battery-data {
+ qcom,batt-id-range-pct = <15>;
+ #include "batterydata-itech-3000mah.dtsi"
+ #include "batterydata-ascent-3450mAh.dtsi"
+ };
+};
+
+&qpnp_fg {
+ qcom,battery-data = <&mtp_batterydata>;
+};
+
+&qpnp_smbcharger {
+ qcom,battery-data = <&mtp_batterydata>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8917-mtp.dtsi
index 164b781..7f35e1e 100644
--- a/arch/arm64/boot/dts/qcom/msm8917-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8917-mtp.dtsi
@@ -11,7 +11,7 @@
* GNU General Public License for more details.
*/
-#include "msm8917-pinctrl.dtsi"
+#include "msm8917-camera-sensor-mtp.dtsi"
&blsp1_uart2 {
status = "ok";
@@ -80,6 +80,43 @@
qcom,dig-vtg-min = <1800000>;
qcom,dig-vtg-max = <1800000>;
};
+
+ gpio_keys {
+ compatible = "gpio-keys";
+ input-name = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&gpio_key_active>;
+
+ camera_focus {
+ label = "camera_focus";
+ gpios = <&tlmm 128 0x1>;
+ linux,input-type = <1>;
+ linux,code = <0x210>;
+ debounce-interval = <15>;
+ linux,can-disable;
+ gpio-key,wakeup;
+ };
+
+ camera_snapshot {
+ label = "camera_snapshot";
+ gpios = <&tlmm 127 0x1>;
+ linux,input-type = <1>;
+ linux,code = <0x2fe>;
+ debounce-interval = <15>;
+ linux,can-disable;
+ gpio-key,wakeup;
+ };
+
+ vol_up {
+ label = "volume_up";
+ gpios = <&tlmm 91 0x1>;
+ linux,input-type = <1>;
+ linux,code = <115>;
+ debounce-interval = <15>;
+ linux,can-disable;
+ gpio-key,wakeup;
+ };
+ };
};
#include "msm8937-mdss-panels.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/msm8917-pmi8937.dts b/arch/arm64/boot/dts/qcom/msm8917-pmi8937.dts
new file mode 100644
index 0000000..635705b
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-pmi8937.dts
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/dts-v1/;
+
+#include "msm8917.dtsi"
+#include "msm8917-pmi8937.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. MSM8917 + PMI8937 SOC";
+ compatible = "qcom,msm8917";
+ qcom,pmic-id = <0x10019 0x020037 0x0 0x0>;
+ qcom,pmic-name = "PMI8937";
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-pmi8937.dtsi b/arch/arm64/boot/dts/qcom/msm8917-pmi8937.dtsi
index 91a290f..55e8e21 100644
--- a/arch/arm64/boot/dts/qcom/msm8917-pmi8937.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8917-pmi8937.dtsi
@@ -22,3 +22,14 @@
&usb_otg {
extcon = <&qpnp_smbcharger>;
};
+
+&soc {
+ led_flash0: qcom,camera-flash {
+ cell-index = <0>;
+ compatible = "qcom,camera-flash";
+ qcom,flash-type = <1>;
+ qcom,flash-source = <&pmi8937_flash0 &pmi8937_flash1>;
+ qcom,torch-source = <&pmi8937_torch0 &pmi8937_torch1>;
+ qcom,switch-source = <&pmi8937_switch>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-pmi8940.dts b/arch/arm64/boot/dts/qcom/msm8917-pmi8940.dts
new file mode 100644
index 0000000..e4017c7
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-pmi8940.dts
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/dts-v1/;
+
+#include "msm8917.dtsi"
+#include "msm8917-pmi8940.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. MSM8917 + PMI8940 SOC";
+ compatible = "qcom,msm8917";
+ qcom,pmic-id = <0x10019 0x020040 0x0 0x0>;
+ qcom,pmic-name = "PMI8940";
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-pmi8940.dtsi b/arch/arm64/boot/dts/qcom/msm8917-pmi8940.dtsi
index 90226da..9b9cd47 100644
--- a/arch/arm64/boot/dts/qcom/msm8917-pmi8940.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8917-pmi8940.dtsi
@@ -22,3 +22,14 @@
&usb_otg {
extcon = <&qpnp_smbcharger>;
};
+
+&soc {
+ led_flash0: qcom,camera-flash {
+ cell-index = <0>;
+ compatible = "qcom,camera-flash";
+ qcom,flash-type = <1>;
+ qcom,flash-source = <&pmi8940_flash0 &pmi8940_flash1>;
+ qcom,torch-source = <&pmi8940_torch0 &pmi8940_torch1>;
+ qcom,switch-source = <&pmi8940_switch>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-pmi8950-cdp-mirror-lake-touch.dts b/arch/arm64/boot/dts/qcom/msm8917-pmi8950-cdp-mirror-lake-touch.dts
index ea6b24a..ae35baf 100644
--- a/arch/arm64/boot/dts/qcom/msm8917-pmi8950-cdp-mirror-lake-touch.dts
+++ b/arch/arm64/boot/dts/qcom/msm8917-pmi8950-cdp-mirror-lake-touch.dts
@@ -14,6 +14,8 @@
/dts-v1/;
#include "msm8917.dtsi"
+#include "msm8917-pmi8950.dtsi"
+#include "msm8917-cdp.dtsi"
#include "msm8917-pmi8950-cdp-mirror-lake-touch.dtsi"
/ {
diff --git a/arch/arm64/boot/dts/qcom/msm8917-pmi8950-cdp-mirror-lake-touch.dtsi b/arch/arm64/boot/dts/qcom/msm8917-pmi8950-cdp-mirror-lake-touch.dtsi
index 4701101..6415241 100644
--- a/arch/arm64/boot/dts/qcom/msm8917-pmi8950-cdp-mirror-lake-touch.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8917-pmi8950-cdp-mirror-lake-touch.dtsi
@@ -11,7 +11,6 @@
* GNU General Public License for more details.
*/
-#include "pmi8950.dtsi"
#include "msm8917-cdp-mirror-lake-touch.dtsi"
#include "msm8917-audio-cdp.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/msm8917-pmi8950.dts b/arch/arm64/boot/dts/qcom/msm8917-pmi8950.dts
new file mode 100644
index 0000000..4a904c6
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-pmi8950.dts
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/dts-v1/;
+
+#include "msm8917.dtsi"
+#include "msm8917-pmi8950.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. MSM8917 + PMI8950 SOC ";
+ compatible = "qcom,msm8917";
+ qcom,pmic-id = <0x10019 0x010011 0x0 0x0>;
+ qcom,pmic-name = "PMI8950";
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-qrd-overlay.dts b/arch/arm64/boot/dts/qcom/msm8917-qrd-overlay.dts
new file mode 100644
index 0000000..6517757
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-qrd-overlay.dts
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/msm-clocks-8952.h>
+#include "msm8917-qrd.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. MSM8917-QRD SKU5";
+ qcom,board-id = <0x1000b 0>;
+};
+
+&vendor{
+ qrd_batterydata: qcom,battery-data {
+ qcom,batt-id-range-pct = <15>;
+ #include "batterydata-qrd-sku2-4v35-2590mah.dtsi"
+ };
+};
+
+&qpnp_smbcharger {
+ qcom,battery-data = <&qrd_batterydata>;
+};
+
+&qpnp_fg {
+ qcom,battery-data = <&qrd_batterydata>;
+};
+
+&mdss_mdp {
+ qcom,mdss-pref-prim-intf = "dsi";
+};
+
+&mdss_dsi {
+ hw-config = "single_dsi";
+};
+
+&mdss_dsi0 {
+ qcom,dsi-pref-prim-pan = <&dsi_hx8394f_720p_video>;
+ pinctrl-names = "mdss_default", "mdss_sleep";
+ pinctrl-0 = <&mdss_dsi_active>;
+ pinctrl-1 = <&mdss_dsi_suspend>;
+
+ qcom,platform-reset-gpio = <&tlmm 60 0>;
+};
+
+&dsi_hx8394f_720p_video {
+ qcom,esd-check-enabled;
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
+
+&soc {
+ i2c@78b7000 {
+ status = "ok";
+ focaltech@38 {
+ compatible = "focaltech,5x06";
+ reg = <0x38>;
+ interrupt-parent = <&tlmm>;
+ interrupts = <65 0x2>;
+ vdd-supply = <&pm8937_l10>;
+ vcc_i2c-supply = <&pm8937_l5>;
+ /* pins used by touchscreen */
+ pinctrl-names = "pmx_ts_active",
+ "pmx_ts_suspend",
+ "pmx_ts_release";
+ pinctrl-0 = <&ts_int_active &ts_reset_active>;
+ pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
+ pinctrl-2 = <&ts_release>;
+ focaltech,name = "ft5436";
+ focaltech,family-id = <0x06>;
+ focaltech,reset-gpio = <&tlmm 64 0x0>;
+ focaltech,irq-gpio = <&tlmm 65 0x2008>;
+ focaltech,display-coords = <0 0 720 1280>;
+ focaltech,panel-coords = <0 0 720 1400>;
+ focaltech,button-map= <139 102 158>;
+ focaltech,no-force-update;
+ focaltech,i2c-pull-up;
+ focaltech,group-id = <1>;
+ focaltech,hard-reset-delay-ms = <20>;
+ focaltech,soft-reset-delay-ms = <200>;
+ focaltech,num-max-touches = <5>;
+ focaltech,fw-delay-aa-ms = <30>;
+ focaltech,fw-delay-55-ms = <30>;
+ focaltech,fw-upgrade-id1 = <0x79>;
+ focaltech,fw-upgrade-id2 = <0x08>;
+ focaltech,fw-delay-readid-ms = <10>;
+ focaltech,fw-delay-era-flsh-ms = <2000>;
+ focaltech,fw-auto-cal;
+ focaltech,ignore-id-check;
+ focaltech,resume-in-workqueue;
+ };
+ };
+
+ gen-vkeys {
+ compatible = "qcom,gen-vkeys";
+ label = "ft5x06_ts";
+ qcom,disp-maxx = <720>;
+ qcom,disp-maxy = <1280>;
+ qcom,panel-maxx = <720>;
+ qcom,panel-maxy = <1400>;
+ qcom,key-codes = <139 172 158>;
+ qcom,y-offset = <0>;
+ };
+
+ led_flash0: qcom,camera-flash {
+ cell-index = <0>;
+ compatible = "qcom,camera-flash";
+ qcom,flash-type = <1>;
+ qcom,flash-source = <&pmi8937_flash0>;
+ qcom,torch-source = <&pmi8937_torch0>;
+ qcom,switch-source = <&pmi8937_switch>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-qrd.dtsi b/arch/arm64/boot/dts/qcom/msm8917-qrd.dtsi
index 431a5e5..d5fd1ff 100644
--- a/arch/arm64/boot/dts/qcom/msm8917-qrd.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8917-qrd.dtsi
@@ -10,9 +10,8 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
-
-#include "msm8917-pinctrl.dtsi"
#include "msm8917-camera-sensor-qrd.dtsi"
+#include "msm8937-mdss-panels.dtsi"
&blsp1_uart2 {
status = "ok";
@@ -88,9 +87,8 @@
gpio_keys {
compatible = "gpio-keys";
input-name = "gpio-keys";
- pinctrl-names = "tlmm_gpio_key_active","tlmm_gpio_key_suspend";
+ pinctrl-names = "default";
pinctrl-0 = <&gpio_key_active>;
- pinctrl-1 = <&gpio_key_suspend>;
vol_up {
label = "volume_up";
@@ -98,6 +96,8 @@
linux,input-type = <1>;
linux,code = <115>;
debounce-interval = <15>;
+ linux,can-disable;
+ gpio-key,wakeup;
};
};
};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-rcm-overlay.dts b/arch/arm64/boot/dts/qcom/msm8917-rcm-overlay.dts
new file mode 100644
index 0000000..fdf98db
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-rcm-overlay.dts
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include "msm8917-cdp.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. MSM8917-RCM";
+ qcom,board-id = <21 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917.dtsi b/arch/arm64/boot/dts/qcom/msm8917.dtsi
index c4b1ec3..cc51694 100644
--- a/arch/arm64/boot/dts/qcom/msm8917.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8917.dtsi
@@ -53,6 +53,11 @@
firmware: firmware {
android {
compatible = "android,firmware";
+ vbmeta {
+ compatible = "android,vbmeta";
+ parts = "vbmeta,boot,system,vendor,dtbo,recovery";
+ };
+
fstab {
compatible = "android,fstab";
vendor {
@@ -60,7 +65,7 @@
dev = "/dev/block/platform/soc/7824900.sdhci/by-name/vendor";
type = "ext4";
mnt_flags = "ro,barrier=1,discard";
- fsmgr_flags = "wait";
+ fsmgr_flags = "wait,avb";
status = "ok";
};
system {
@@ -68,7 +73,7 @@
dev = "/dev/block/platform/soc/7824900.sdhci/by-name/system";
type = "ext4";
mnt_flags = "ro,barrier=1,discard";
- fsmgr_flags = "wait";
+ fsmgr_flags = "wait,avb";
status = "ok";
};
};
@@ -1640,6 +1645,10 @@
qcom,has-vsys-adc-channel;
qcom,wcnss-adc_tm = <&pm8937_adc_tm>;
};
+
+ ssc_sensors: qcom,msm-ssc-sensors {
+ compatible = "qcom,msm-ssc-sensors";
+ };
};
#include "pm8937-rpm-regulator.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/msm8953-ext-codec-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/msm8953-ext-codec-mtp-overlay.dts
index 67ed197..1b09b3c 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-ext-codec-mtp-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/msm8953-ext-codec-mtp-overlay.dts
@@ -35,6 +35,13 @@
qcom,battery-data = <&mtp_batterydata>;
};
+&pmi_haptic{
+ qcom,lra-auto-res-mode="qwd";
+ qcom,lra-high-z="opt1";
+ qcom,lra-res-cal-period = <0>;
+ qcom,wave-play-rate-us = <4165>;
+};
+
&qpnp_smbcharger {
qcom,battery-data = <&mtp_batterydata>;
qcom,chg-led-sw-controls;
diff --git a/arch/arm64/boot/dts/qcom/msm8953-ipc.dts b/arch/arm64/boot/dts/qcom/msm8953-ipc.dts
index 89a54af..43c6441 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-ipc.dts
+++ b/arch/arm64/boot/dts/qcom/msm8953-ipc.dts
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018, 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
@@ -15,11 +15,11 @@
#include "msm8953.dtsi"
#include "msm8953-ipc.dtsi"
-
+#include "pmi8950.dtsi"
+#include "msm8953-pmi8950.dtsi"
/ {
model = "Qualcomm Technologies, Inc. MSM8953 + PMI8950 IPC";
compatible = "qcom,msm8953-ipc", "qcom,msm8953", "qcom,ipc";
qcom,board-id= <12 0>;
qcom,pmic-id = <0x010016 0x010011 0x0 0x0>;
};
-
diff --git a/arch/arm64/boot/dts/qcom/msm8953-mdss-panels.dtsi b/arch/arm64/boot/dts/qcom/msm8953-mdss-panels.dtsi
index a80b4fe..7bc181c 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-mdss-panels.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-mdss-panels.dtsi
@@ -124,6 +124,12 @@
24 1f 08 09 05 03 04 a0
24 1f 08 09 05 03 04 a0
24 1c 08 09 05 03 04 a0];
+ qcom,mdss-dsi-h-front-porch = <52>;
+ qcom,mdss-dsi-h-back-porch = <48>;
+ qcom,mdss-dsi-h-pulse-width = <8>;
+ qcom,mdss-dsi-v-back-porch = <8>;
+ qcom,mdss-dsi-v-front-porch = <8>;
+ qcom,mdss-dsi-v-pulse-width = <4>;
qcom,esd-check-enabled;
qcom,mdss-dsi-panel-status-check-mode = "reg_read";
qcom,mdss-dsi-panel-status-command = [06 01 00 01 00 00 01 0a];
diff --git a/arch/arm64/boot/dts/qcom/msm8953-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/msm8953-mtp-overlay.dts
index e4897bc..00614b2 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-mtp-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/msm8953-mtp-overlay.dts
@@ -33,6 +33,13 @@
qcom,battery-data = <&mtp_batterydata>;
};
+&pmi_haptic{
+ qcom,lra-auto-res-mode="qwd";
+ qcom,lra-high-z="opt1";
+ qcom,lra-res-cal-period = <0>;
+ qcom,wave-play-rate-us = <4165>;
+};
+
&qpnp_smbcharger {
qcom,battery-data = <&mtp_batterydata>;
qcom,chg-led-sw-controls;
diff --git a/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi
index e8de4ef..c58d82e 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi
@@ -599,6 +599,32 @@
};
};
+ blsp2_uart1_active: blsp2_uart1_active {
+ mux {
+ pins = "gpio20", "gpio21", "gpio22", "gpio23";
+ function = "blsp_uart6";
+ };
+
+ config {
+ pins = "gpio20", "gpio21", "gpio22", "gpio23";
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+
+ blsp2_uart1_sleep: blsp2_uart1_sleep {
+ mux {
+ pins = "gpio20", "gpio21", "gpio22", "gpio23";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio20", "gpio21", "gpio22", "gpio23";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
/* SDC pin type */
sdc1_clk_on: sdc1_clk_on {
config {
@@ -1374,6 +1400,163 @@
};
};
+ spi6 {
+ spi6_default: spi6_default {
+ /* active state */
+ mux {
+ /* MOSI, MISO, CLK */
+ pins = "gpio20", "gpio21", "gpio23";
+ function = "blsp_spi6";
+ };
+
+ config {
+ pins = "gpio20", "gpio21", "gpio23";
+ drive-strength = <12>; /* 12 MA */
+ bias-disable = <0>; /* No PULL */
+ };
+ };
+
+ spi6_sleep: spi6_sleep {
+ /* suspended state */
+ mux {
+ /* MOSI, MISO, CLK */
+ pins = "gpio20", "gpio21", "gpio23";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio20", "gpio21", "gpio23";
+ drive-strength = <2>; /* 2 MA */
+ bias-pull-down; /* PULL Down */
+ };
+ };
+
+ spi6_cs0_active: cs0_active {
+ /* CS */
+ mux {
+ pins = "gpio22";
+ function = "blsp_spi6";
+ };
+
+ config {
+ pins = "gpio22";
+ drive-strength = <2>;
+ bias-disable = <0>;
+ };
+ };
+
+ spi6_cs0_sleep: cs0_sleep {
+ /* CS */
+ mux {
+ pins = "gpio22";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio22";
+ drive-strength = <2>;
+ bias-disable = <0>;
+ };
+ };
+ };
+
+ /* add pingrp for touchscreen */
+ ts_int_default: ts_int_default {
+ mux {
+ pins = "gpio65";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio65";
+ drive-strength = <16>;
+ /*bias-pull-up;*/
+ input-enable;
+ bias-disable;
+ };
+ };
+
+ ts_int_output_high: ts_int_output_high {
+ mux {
+ pins = "gpio65";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio65";
+ output-high;
+ };
+ };
+
+ ts_int_output_low: ts_int_output_low {
+ mux {
+ pins = "gpio65";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio65";
+ output-low;
+ };
+ };
+
+ ts_int_input: ts_int_input {
+ mux {
+ pins = "gpio65";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio65";
+ input-enable;
+ bias-disable;
+ };
+ };
+
+ ts_rst_default: ts_rst_default {
+ mux {
+ pins = "gpio64";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio64";
+ drive-strength = <16>;
+ /*bias-pull-up;*/
+ input-enable;
+ bias-disable;
+ };
+ };
+
+ ts_rst_output_high: ts_rst_output_high {
+ mux {
+ pins = "gpio64";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio64";
+ output-high;
+ };
+ };
+
+ ts_rst_output_low: ts_rst_output_low {
+ mux {
+ pins = "gpio64";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio64";
+ output-low;
+ };
+ };
+
+ ts_rst_input: ts_rst_input {
+ mux {
+ pins = "gpio64";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio64";
+ input-enable;
+ bias-disable;
+ };
+ };
+
/* add pingrp for touchscreen */
pmx_ts_int_active {
ts_int_active: ts_int_active {
diff --git a/arch/arm64/boot/dts/qcom/msm8953.dtsi b/arch/arm64/boot/dts/qcom/msm8953.dtsi
index c3178e0..3ab3b2b 100644
--- a/arch/arm64/boot/dts/qcom/msm8953.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953.dtsi
@@ -179,6 +179,7 @@
i2c3 = &i2c_3;
i2c5 = &i2c_5;
spi3 = &spi_3;
+ spi6 = &spi_6;
};
soc: soc {
@@ -613,6 +614,42 @@
status = "disabled";
};
+ blsp2_uart1: uart@7af0000 {
+ compatible = "qcom,msm-hsuart-v14";
+ reg = <0x7af0000 0x200>,
+ <0x7ac4000 0x1f000>;
+ reg-names = "core_mem", "bam_mem";
+
+ interrupt-names = "core_irq", "bam_irq", "wakeup_irq";
+ #address-cells = <0>;
+ interrupt-parent = <&blsp2_uart1>;
+ interrupts = <0 1 2>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0xffffffff>;
+ interrupt-map = <0 &intc 0 307 0
+ 1 &intc 0 239 0
+ 2 &tlmm 21 0>;
+
+ qcom,inject-rx-on-wakeup;
+ qcom,rx-char-to-inject = <0xFD>;
+ qcom,master-id = <84>;
+ clock-names = "core_clk", "iface_clk";
+ clocks = <&clock_gcc clk_gcc_blsp2_uart2_apps_clk>,
+ <&clock_gcc clk_gcc_blsp2_ahb_clk>;
+ pinctrl-names = "sleep", "default";
+ pinctrl-0 = <&blsp2_uart1_sleep>;
+ pinctrl-1 = <&blsp2_uart1_active>;
+ qcom,bam-tx-ep-pipe-index = <2>;
+ qcom,bam-rx-ep-pipe-index = <3>;
+ qcom,msm-bus,name = "blsp2_uart1";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <84 512 0 0>,
+ <84 512 500 800>;
+ status = "disabled";
+ };
+
blsp1_serial1: serial@78b0000 {
compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
reg = <0x78b0000 0x200>;
@@ -664,6 +701,33 @@
qcom,master-id = <86>;
status = "disabled";
};
+
+ spi_6: spi@7af6000 { /* BLSP2 QUP2 */
+ compatible = "qcom,spi-qup-v2";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg-names = "spi_physical", "spi_bam_physical";
+ reg = <0x7af6000 0x600>,
+ <0x7ac4000 0x1f000>;
+ interrupt-names = "spi_irq", "spi_bam_irq";
+ interrupts = <0 300 0>, <0 239 0>;
+ spi-max-frequency = <19200000>;
+ pinctrl-names = "spi_default", "spi_sleep";
+ pinctrl-0 = <&spi6_default &spi6_cs0_active>;
+ pinctrl-1 = <&spi6_sleep &spi6_cs0_sleep>;
+ clocks = <&clock_gcc clk_gcc_blsp2_ahb_clk>,
+ <&clock_gcc clk_gcc_blsp2_qup2_spi_apps_clk>;
+ clock-names = "iface_clk", "core_clk";
+ qcom,infinite-mode = <0>;
+ qcom,use-bam;
+ qcom,use-pinctrl;
+ qcom,ver-reg-exists;
+ qcom,bam-consumer-pipe-index = <6>;
+ qcom,bam-producer-pipe-index = <7>;
+ qcom,master-id = <84>;
+ status = "disabled";
+ };
+
i2c_1: i2c@78b5000 { /* BLSP1 QUP1 */
compatible = "qcom,i2c-msm-v2";
#address-cells = <1>;
@@ -1464,8 +1528,10 @@
sdhc_1: sdhci@7824900 {
compatible = "qcom,sdhci-msm";
- reg = <0x7824900 0x500>, <0x7824000 0x800>, <0x7824e00 0x200>;
- reg-names = "hc_mem", "core_mem", "cmdq_mem";
+ reg = <0x7824900 0x500>, <0x7824000 0x800>, <0x7824e00 0x200>,
+ <0x0119d000 0x4>;
+ reg-names = "hc_mem", "core_mem", "cmdq_mem",
+ "tlmm_mem";
interrupts = <0 123 0>, <0 138 0>;
interrupt-names = "hc_irq", "pwr_irq";
diff --git a/arch/arm64/boot/dts/qcom/pmi632.dtsi b/arch/arm64/boot/dts/qcom/pmi632.dtsi
index fb26ab6..d175b80 100644
--- a/arch/arm64/boot/dts/qcom/pmi632.dtsi
+++ b/arch/arm64/boot/dts/qcom/pmi632.dtsi
@@ -289,20 +289,20 @@
pmi632_gpios: pinctrl@c000 {
compatible = "qcom,spmi-gpio";
reg = <0xc000 0x800>;
- interrupts = <0x2 0xc1 0 IRQ_TYPE_NONE>,
+ interrupts = <0x2 0xc0 0 IRQ_TYPE_NONE>,
+ <0x2 0xc1 0 IRQ_TYPE_NONE>,
<0x2 0xc2 0 IRQ_TYPE_NONE>,
<0x2 0xc3 0 IRQ_TYPE_NONE>,
<0x2 0xc4 0 IRQ_TYPE_NONE>,
<0x2 0xc5 0 IRQ_TYPE_NONE>,
<0x2 0xc6 0 IRQ_TYPE_NONE>,
<0x2 0xc7 0 IRQ_TYPE_NONE>;
- interrupt-names = "pmi632_gpio2", "pmi632_gpio3",
- "pmi632_gpio4", "pmi632_gpio5",
- "pmi632_gpio6", "pmi632_gpio7",
- "pmi632_gpio8";
+ interrupt-names = "pmi632_gpio1", "pmi632_gpio2",
+ "pmi632_gpio3", "pmi632_gpio4",
+ "pmi632_gpio5", "pmi632_gpio6",
+ "pmi632_gpio7", "pmi632_gpio8";
gpio-controller;
#gpio-cells = <2>;
- qcom,gpios-disallowed = <1>;
};
pmi632_charger: qcom,qpnp-smb5 {
@@ -318,6 +318,9 @@
qcom,flash-disable-soc = <10>;
qcom,sw-jeita-enable;
qcom,step-charging-enable;
+ qcom,hw-die-temp-mitigation;
+ qcom,hw-connector-mitigation;
+ qcom,connector-internal-pull-kohm = <100>;
qcom,thermal-mitigation
= <3000000 2500000 2000000 1500000
@@ -394,7 +397,7 @@
interrupts =
<0x2 0x13 0x0 IRQ_TYPE_EDGE_BOTH>,
<0x2 0x13 0x1 IRQ_TYPE_EDGE_BOTH>,
- <0x2 0x13 0x2 IRQ_TYPE_EDGE_BOTH>,
+ <0x2 0x13 0x2 IRQ_TYPE_EDGE_RISING>,
<0x2 0x13 0x3 IRQ_TYPE_EDGE_BOTH>,
<0x2 0x13 0x4 IRQ_TYPE_EDGE_BOTH>,
<0x2 0x13 0x5 IRQ_TYPE_EDGE_BOTH>,
diff --git a/arch/arm64/boot/dts/qcom/qcs605-external-codec-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/qcs605-external-codec-mtp-overlay.dts
index 44fae6a..76088af 100644
--- a/arch/arm64/boot/dts/qcom/qcs605-external-codec-mtp-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/qcs605-external-codec-mtp-overlay.dts
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2018, 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
@@ -32,3 +32,47 @@
<0x0001001b 0x0102001a 0x0 0x0>,
<0x0001001b 0x0201011a 0x0 0x0>;
};
+
+&cam_cci {
+ /delete-node/ qcom,cam-sensor@1;
+ qcom,cam-sensor@1 {
+ cell-index = <1>;
+ compatible = "qcom,cam-sensor";
+ reg = <0x1>;
+ csiphy-sd-index = <1>;
+ sensor-position-roll = <90>;
+ sensor-position-pitch = <0>;
+ sensor-position-yaw = <180>;
+ eeprom-src = <&eeprom_rear_aux>;
+ cam_vio-supply = <&camera_vio_ldo>;
+ cam_vana-supply = <&camera_vana_ldo>;
+ cam_vdig-supply = <&camera_ldo>;
+ cam_clk-supply = <&titan_top_gdsc>;
+ regulator-names = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_clk";
+ rgltr-cntrl-support;
+ rgltr-min-voltage = <1352000 1800000 2850000 0>;
+ rgltr-max-voltage = <1352000 1800000 2850000 0>;
+ rgltr-load-current = <105000 0 80000 0>;
+ gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk0_active
+ &cam_sensor_rear2_active>;
+ pinctrl-1 = <&cam_sensor_mclk0_suspend
+ &cam_sensor_rear2_suspend>;
+ gpios = <&tlmm 13 0>,
+ <&tlmm 28 0>;
+ gpio-reset = <1>;
+ gpio-req-tbl-num = <0 1>;
+ gpio-req-tbl-flags = <1 0>;
+ gpio-req-tbl-label = "CAMIF_MCLK0",
+ "CAM_RESET1";
+ sensor-mode = <0>;
+ cci-master = <1>;
+ status = "ok";
+ clocks = <&clock_camcc CAM_CC_MCLK0_CLK>;
+ clock-names = "cam_clk";
+ clock-cntl-level = "turbo";
+ clock-rates = <24000000>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs605-external-codec-mtp.dts b/arch/arm64/boot/dts/qcom/qcs605-external-codec-mtp.dts
index abc3f2d..47ea8f3 100644
--- a/arch/arm64/boot/dts/qcom/qcs605-external-codec-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/qcs605-external-codec-mtp.dts
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2018, 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
@@ -26,3 +26,47 @@
<0x0001001b 0x0102001a 0x0 0x0>,
<0x0001001b 0x0201011a 0x0 0x0>;
};
+
+&cam_cci {
+ /delete-node/ qcom,cam-sensor@1;
+ qcom,cam-sensor@1 {
+ cell-index = <1>;
+ compatible = "qcom,cam-sensor";
+ reg = <0x1>;
+ csiphy-sd-index = <1>;
+ sensor-position-roll = <90>;
+ sensor-position-pitch = <0>;
+ sensor-position-yaw = <180>;
+ eeprom-src = <&eeprom_rear_aux>;
+ cam_vio-supply = <&camera_vio_ldo>;
+ cam_vana-supply = <&camera_vana_ldo>;
+ cam_vdig-supply = <&camera_ldo>;
+ cam_clk-supply = <&titan_top_gdsc>;
+ regulator-names = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_clk";
+ rgltr-cntrl-support;
+ rgltr-min-voltage = <1352000 1800000 2850000 0>;
+ rgltr-max-voltage = <1352000 1800000 2850000 0>;
+ rgltr-load-current = <105000 0 80000 0>;
+ gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk0_active
+ &cam_sensor_rear2_active>;
+ pinctrl-1 = <&cam_sensor_mclk0_suspend
+ &cam_sensor_rear2_suspend>;
+ gpios = <&tlmm 13 0>,
+ <&tlmm 28 0>;
+ gpio-reset = <1>;
+ gpio-req-tbl-num = <0 1>;
+ gpio-req-tbl-flags = <1 0>;
+ gpio-req-tbl-label = "CAMIF_MCLK0",
+ "CAM_RESET1";
+ sensor-mode = <0>;
+ cci-master = <1>;
+ status = "ok";
+ clocks = <&clock_camcc CAM_CC_MCLK0_CLK>;
+ clock-names = "cam_clk";
+ clock-cntl-level = "turbo";
+ clock-rates = <24000000>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera-audio.dtsi b/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera-audio.dtsi
new file mode 100644
index 0000000..ab82fe6
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera-audio.dtsi
@@ -0,0 +1,360 @@
+/*
+ * Copyright (c) 2017-2018, 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.
+ */
+#include "sdm670-wcd.dtsi"
+#include "sdm670-wsa881x.dtsi"
+#include "sdm670-lpi.dtsi"
+#include <dt-bindings/clock/qcom,audio-ext-clk.h>
+
+&tavil_snd {
+ qcom,msm-mi2s-master = <1>, <1>, <1>, <1>, <1>;
+ qcom,audio-routing =
+ "AIF4 VI", "MCLK",
+ "RX_BIAS", "MCLK",
+ "MADINPUT", "MCLK",
+ "hifi amp", "LINEOUT1",
+ "hifi amp", "LINEOUT2",
+ "AMIC2", "MIC BIAS2",
+ "MIC BIAS2", "Headset Mic",
+ "AMIC3", "MIC BIAS2",
+ "MIC BIAS2", "ANCRight Headset Mic",
+ "AMIC4", "MIC BIAS2",
+ "MIC BIAS2", "ANCLeft Headset Mic",
+ "AMIC5", "MIC BIAS3",
+ "MIC BIAS3", "Handset Mic",
+ "DMIC0", "MIC BIAS1",
+ "MIC BIAS1", "Digital Mic0",
+ "DMIC1", "MIC BIAS1",
+ "MIC BIAS1", "Digital Mic1",
+ "DMIC2", "MIC BIAS3",
+ "MIC BIAS3", "Digital Mic2",
+ "DMIC3", "MIC BIAS3",
+ "MIC BIAS3", "Digital Mic3",
+ "DMIC4", "MIC BIAS4",
+ "MIC BIAS4", "Digital Mic4",
+ "DMIC5", "MIC BIAS4",
+ "MIC BIAS4", "Digital Mic5",
+ "SpkrLeft IN", "SPK1 OUT",
+ "SpkrRight IN", "SPK2 OUT";
+
+ qcom,msm-mbhc-hphl-swh = <1>;
+ qcom,msm-mbhc-gnd-swh = <1>;
+ qcom,hph-en0-gpio = <&tavil_hph_en0>;
+ qcom,hph-en1-gpio = <&tavil_hph_en1>;
+ qcom,msm-mclk-freq = <9600000>;
+ asoc-codec = <&stub_codec>, <&ext_disp_audio_codec>;
+ asoc-codec-names = "msm-stub-codec.1", "msm-ext-disp-audio-codec-rx";
+ qcom,wsa-max-devs = <2>;
+ qcom,wsa-devs = <&wsa881x_0211>, <&wsa881x_0212>,
+ <&wsa881x_0213>, <&wsa881x_0214>;
+ qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrRight",
+ "SpkrLeft", "SpkrRight";
+};
+
+&tasha_snd {
+ qcom,msm-mi2s-master = <1>, <1>, <1>, <1>, <1>;
+ qcom,audio-routing =
+ "AIF4 VI", "MCLK",
+ "RX_BIAS", "MCLK",
+ "MADINPUT", "MCLK",
+ "hifi amp", "LINEOUT1",
+ "hifi amp", "LINEOUT2",
+ "AMIC2", "MIC BIAS2",
+ "MIC BIAS2", "Headset Mic",
+ "AMIC3", "MIC BIAS2",
+ "MIC BIAS2", "ANCRight Headset Mic",
+ "AMIC4", "MIC BIAS2",
+ "MIC BIAS2", "ANCLeft Headset Mic",
+ "AMIC5", "MIC BIAS3",
+ "MIC BIAS3", "Handset Mic",
+ "DMIC0", "MIC BIAS1",
+ "MIC BIAS1", "Digital Mic0",
+ "DMIC1", "MIC BIAS1",
+ "MIC BIAS1", "Digital Mic1",
+ "DMIC2", "MIC BIAS3",
+ "MIC BIAS3", "Digital Mic2",
+ "DMIC3", "MIC BIAS3",
+ "MIC BIAS3", "Digital Mic3",
+ "DMIC4", "MIC BIAS4",
+ "MIC BIAS4", "Digital Mic4",
+ "DMIC5", "MIC BIAS4",
+ "MIC BIAS4", "Digital Mic5",
+ "SpkrLeft IN", "SPK1 OUT",
+ "SpkrRight IN", "SPK2 OUT";
+
+ qcom,msm-mbhc-hphl-swh = <0>;
+ qcom,msm-mbhc-gnd-swh = <0>;
+ qcom,msm-mclk-freq = <9600000>;
+ asoc-codec = <&stub_codec>;
+ asoc-codec-names = "msm-stub-codec.1";
+ qcom,wsa-max-devs = <2>;
+ qcom,wsa-devs = <&wsa881x_211>, <&wsa881x_212>,
+ <&wsa881x_213>, <&wsa881x_214>;
+ qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrRight",
+ "SpkrLeft", "SpkrRight";
+};
+
+&soc {
+ wcd_usbc_analog_en1_gpio: msm_cdc_pinctrl_usbc_audio_en1 {
+ compatible = "qcom,msm-cdc-pinctrl";
+ pinctrl-names = "aud_active", "aud_sleep";
+ pinctrl-0 = <&wcd_usbc_analog_en1_active>;
+ pinctrl-1 = <&wcd_usbc_analog_en1_idle>;
+ };
+
+ cdc_pdm_gpios: cdc_pdm_pinctrl {
+ compatible = "qcom,msm-cdc-pinctrl";
+ pinctrl-names = "aud_active", "aud_sleep";
+ pinctrl-0 = <&cdc_pdm_clk_active &cdc_pdm_sync_active
+ &cdc_pdm_rx0_active &cdc_pdm_rx1_2_active
+ &cdc_pdm_2_gpios_active>;
+ pinctrl-1 = <&cdc_pdm_clk_sleep &cdc_pdm_sync_sleep
+ &cdc_pdm_rx0_sleep &cdc_pdm_rx1_2_sleep
+ &cdc_pdm_2_gpios_sleep>;
+ qcom,lpi-gpios;
+ };
+
+ cdc_comp_gpios: cdc_comp_pinctrl {
+ compatible = "qcom,msm-cdc-pinctrl";
+ pinctrl-names = "aud_active", "aud_sleep";
+ pinctrl-0 = <&cdc_rx0_comp_active &cdc_rx1_comp_active>;
+ pinctrl-1 = <&cdc_rx0_comp_sleep &cdc_rx1_comp_sleep>;
+ qcom,lpi-gpios;
+ };
+
+ cdc_dmic_gpios: cdc_dmic_pinctrl {
+ compatible = "qcom,msm-cdc-pinctrl";
+ pinctrl-names = "aud_active", "aud_sleep";
+ pinctrl-0 = <&cdc_dmic12_gpios_active
+ &cdc_dmic34_gpios_active>;
+ pinctrl-1 = <&cdc_dmic12_gpios_sleep
+ &cdc_dmic34_gpios_sleep>;
+ qcom,lpi-gpios;
+ };
+
+ cdc_sdw_gpios: sdw_clk_data_pinctrl {
+ compatible = "qcom,msm-cdc-pinctrl";
+ pinctrl-names = "aud_active", "aud_sleep";
+ pinctrl-0 = <&sdw_clk_active &sdw_data_active>;
+ pinctrl-1 = <&sdw_clk_sleep &sdw_data_sleep>;
+ };
+
+ wsa_spkr_en1: wsa_spkr_en1_pinctrl {
+ compatible = "qcom,msm-cdc-pinctrl";
+ pinctrl-names = "aud_active", "aud_sleep";
+ pinctrl-0 = <&spkr_1_sd_n_active>;
+ pinctrl-1 = <&spkr_1_sd_n_sleep>;
+ };
+
+ wsa_spkr_en2: wsa_spkr_en2_pinctrl {
+ compatible = "qcom,msm-cdc-pinctrl";
+ pinctrl-names = "aud_active", "aud_sleep";
+ pinctrl-0 = <&spkr_2_sd_n_active>;
+ pinctrl-1 = <&spkr_2_sd_n_sleep>;
+ };
+
+ msm_sdw_codec: msm-sdw-codec@62ec1000 {
+ status = "okay";
+ compatible = "qcom,msm-sdw-codec";
+ reg = <0x62ec1000 0x0>;
+ interrupts = <0 88 0>;
+ interrupt-names = "swr_master_irq";
+ qcom,cdc-sdw-gpios = <&cdc_sdw_gpios>;
+
+ swr_master {
+ compatible = "qcom,swr-wcd";
+ #address-cells = <2>;
+ #size-cells = <0>;
+
+ wsa881x_211_en: wsa881x_en@20170211 {
+ compatible = "qcom,wsa881x";
+ reg = <0x0 0x20170211>;
+ qcom,spkr-sd-n-node = <&wsa_spkr_en1>;
+ };
+
+ wsa881x_212_en: wsa881x_en@20170212 {
+ compatible = "qcom,wsa881x";
+ reg = <0x0 0x20170212>;
+ qcom,spkr-sd-n-node = <&wsa_spkr_en2>;
+ };
+
+ wsa881x_213_en: wsa881x_en@21170213 {
+ compatible = "qcom,wsa881x";
+ reg = <0x0 0x21170213>;
+ qcom,spkr-sd-n-node = <&wsa_spkr_en1>;
+ };
+
+ wsa881x_214_en: wsa881x_en@21170214 {
+ compatible = "qcom,wsa881x";
+ reg = <0x0 0x21170214>;
+ qcom,spkr-sd-n-node = <&wsa_spkr_en2>;
+ };
+ };
+ };
+
+ wcd9xxx_intc: wcd9xxx-irq {
+ status = "disabled";
+ compatible = "qcom,wcd9xxx-irq";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ interrupt-parent = <&tlmm>;
+ qcom,gpio-connect = <&tlmm 80 0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&wcd_intr_default>;
+ };
+
+ clock_audio_native: audio_ext_clk_native {
+ status = "disabled";
+ compatible = "qcom,audio-ref-clk";
+ #clock-cells = <1>;
+ qcom,lpass-mclk-id = <0x116>;
+ qcom,codec-mclk-clk-freq = <11289600>;
+ qcom,audio-ref-clk-gpio = <&lpi_tlmm 19 0>;
+ pinctrl-names = "sleep", "active";
+ pinctrl-0 = <&lpi_mclk0_sleep>;
+ pinctrl-1 = <&lpi_mclk0_active>;
+ };
+
+ clock_audio: audio_ext_clk {
+ status = "disabled";
+ compatible = "qcom,audio-ref-clk";
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&tasha_mclk_default>;
+ pinctrl-1 = <&tasha_mclk_default>;
+ qcom,audio-ref-clk-gpio = <&pm660_gpios 3 0>;
+ clock-names = "osr_clk";
+ clocks = <&pm660_div_clk>;
+ qcom,node_has_rpm_clock;
+ #clock-cells = <1>;
+ };
+
+ clock_audio_lnbb: audio_ext_clk_lnbb {
+ status = "disabled";
+ compatible = "qcom,audio-ref-clk";
+ clock-names = "osr_clk";
+ clocks = <&clock_rpmh RPMH_LN_BB_CLK2>;
+ qcom,node_has_rpm_clock;
+ #clock-cells = <1>;
+ };
+
+ wcd_rst_gpio: msm_cdc_pinctrl@64 {
+ status = "disabled";
+ compatible = "qcom,msm-cdc-pinctrl";
+ pinctrl-names = "aud_active", "aud_sleep";
+ pinctrl-0 = <&lpi_cdc_reset_active>;
+ pinctrl-1 = <&lpi_cdc_reset_sleep>;
+ qcom,lpi-gpios;
+ };
+
+ wdsp_mgr: qcom,wcd-dsp-mgr {
+ compatible = "qcom,wcd-dsp-mgr";
+ qcom,wdsp-components = <&wcd934x_cdc 0>,
+ <&wcd_spi_0 1>,
+ <&glink_spi_xprt_wdsp 2>;
+ qcom,img-filename = "cpe_9340";
+ };
+
+ wdsp_glink: qcom,wcd-dsp-glink {
+ compatible = "qcom,wcd-dsp-glink";
+ };
+
+ tert_mi2s_gpios: tert_mi2s_pinctrl {
+ status = "disabled";
+ compatible = "qcom,msm-cdc-pinctrl";
+ pinctrl-names = "aud_active", "aud_sleep";
+ pinctrl-0 = <&ter_i2s_data0_active &ter_i2s_data1_active
+ &ter_i2s_sck_active>;
+ pinctrl-1 = <&ter_i2s_data0_sleep &ter_i2s_data1_sleep
+ &ter_i2s_sck_sleep>;
+ };
+};
+
+&slim_aud {
+ wcd9335: tasha_codec {
+ status = "disabled";
+ compatible = "qcom,tasha-slim-pgd";
+ elemental-addr = [00 01 a0 01 17 02];
+
+ interrupt-parent = <&wcd9xxx_intc>;
+ interrupts = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+ 17 18 19 20 21 22 23 24 25 26 27 28 29
+ 30>;
+
+ qcom,wcd-rst-gpio-node = <&wcd_rst_gpio>;
+
+ clock-names = "wcd_clk", "wcd_native_clk";
+ clocks = <&clock_audio AUDIO_PMI_CLK>,
+ <&clock_audio_native AUDIO_LPASS_MCLK>;
+
+ cdc-vdd-mic-bias-supply = <&pm660l_bob>;
+ qcom,cdc-vdd-mic-bias-voltage = <3312000 3312000>;
+ qcom,cdc-vdd-mic-bias-current = <30400>;
+
+ qcom,cdc-static-supplies = "cdc-vdd-mic-bias";
+
+ qcom,cdc-micbias1-mv = <1800>;
+ qcom,cdc-micbias2-mv = <1800>;
+ qcom,cdc-micbias3-mv = <1800>;
+ qcom,cdc-micbias4-mv = <1800>;
+
+ qcom,cdc-mclk-clk-rate = <9600000>;
+ qcom,cdc-slim-ifd = "tasha-slim-ifd";
+ qcom,cdc-slim-ifd-elemental-addr = [00 00 a0 01 17 02];
+ qcom,cdc-dmic-sample-rate = <4800000>;
+ qcom,cdc-mad-dmic-rate = <600000>;
+ };
+
+ wcd934x_cdc: tavil_codec {
+ status = "disabled";
+ compatible = "qcom,tavil-slim-pgd";
+ elemental-addr = [00 01 50 02 17 02];
+
+ interrupt-parent = <&wcd9xxx_intc>;
+ interrupts = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+ 17 18 19 20 21 22 23 24 25 26 27 28 29
+ 30 31>;
+
+ qcom,wcd-rst-gpio-node = <&wcd_rst_gpio>;
+
+ clock-names = "wcd_clk";
+ clocks = <&clock_audio_lnbb AUDIO_PMIC_LNBB_CLK>;
+
+ cdc-vdd-mic-bias-supply = <&pm660l_bob>;
+ qcom,cdc-vdd-mic-bias-voltage = <3312000 3312000>;
+ qcom,cdc-vdd-mic-bias-current = <30400>;
+
+ qcom,cdc-static-supplies = "cdc-vdd-mic-bias";
+
+ qcom,cdc-micbias1-mv = <1800>;
+ qcom,cdc-micbias2-mv = <1800>;
+ qcom,cdc-micbias3-mv = <1800>;
+ qcom,cdc-micbias4-mv = <1800>;
+
+ qcom,cdc-mclk-clk-rate = <9600000>;
+ qcom,cdc-slim-ifd = "tavil-slim-ifd";
+ qcom,cdc-slim-ifd-elemental-addr = [00 00 50 02 17 02];
+ qcom,cdc-dmic-sample-rate = <4800000>;
+ qcom,cdc-mad-dmic-rate = <600000>;
+
+ qcom,wdsp-cmpnt-dev-name = "tavil_codec";
+
+ wcd_spi_0: wcd_spi {
+ compatible = "qcom,wcd-spi-v2";
+ qcom,master-bus-num = <0>;
+ qcom,chip-select = <0>;
+ qcom,max-frequency = <24000000>;
+ qcom,mem-base-addr = <0x100000>;
+ };
+ };
+};
+
+
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera-overlay.dts b/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera-overlay.dts
new file mode 100644
index 0000000..c7912d6
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera-overlay.dts
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "qcs605-lc-ipcamera.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. QC605 LC Groot + PM8005 IPC";
+ compatible = "qcom,qcs605-mtp", "qcom,qcs605", "qcom,mtp";
+ qcom,msm-id = <347 0x0>;
+ qcom,board-id = <8 6>;
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera.dts b/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera.dts
new file mode 100644
index 0000000..90dcd7b
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera.dts
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+
+/dts-v1/;
+
+#include "qcs605-lc.dtsi"
+#include "qcs605-lc-ipcamera.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. QC605 LC Groot + PM8005 IPC";
+ compatible = "qcom,qcs605-mtp", "qcom,qcs605", "qcom,mtp";
+ qcom,board-id = <8 6>;
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera.dtsi b/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera.dtsi
new file mode 100644
index 0000000..d6d9a17
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera.dtsi
@@ -0,0 +1,196 @@
+/* Copyright (c) 2017-2018, 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.
+ */
+
+#include "qcs605-lc-pmic-overlay.dtsi"
+#include "qcs605-lc-camera-sensor-mtp.dtsi"
+#include "qcs605-lc-ipcamera-audio.dtsi"
+
+&qupv3_se9_2uart {
+ status = "disabled";
+};
+
+&qupv3_se12_2uart {
+ status = "ok";
+};
+
+&sdhc_1 {
+ vdd-supply = <&pm660_l19>;
+ qcom,vdd-voltage-level = <2960000 2960000>;
+ qcom,vdd-current-level = <0 570000>;
+
+ vdd-io-supply = <&pm660_l8>;
+ qcom,vdd-io-always-on;
+ qcom,vdd-io-lpm-sup;
+ qcom,vdd-io-voltage-level = <1800000 1800000>;
+ qcom,vdd-io-current-level = <0 325000>;
+
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on &sdc1_rclk_on>;
+ pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off &sdc1_rclk_off>;
+
+ status = "ok";
+};
+
+&tlmm {
+ sdc2_cd_on: cd_on {
+ mux {
+ pins = "gpio116";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio116";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+
+ sdc2_cd_off: cd_off {
+ mux {
+ pins = "gpio116";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio116";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+};
+
+&sdhc_2 {
+ /* VDD external regulator is enabled/disabled by pm660_l18 regulator */
+ vdd-io-supply = <&pm660_l18>;
+ qcom,vdd-io-voltage-level = <1800000 2960000>;
+ qcom,vdd-io-current-level = <0 22000>;
+
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>;
+ pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_off>;
+
+ cd-gpios = <&tlmm 116 0x1>;
+
+ status = "ok";
+};
+
+&usb0 {
+ dwc3@a600000 {
+ dr_mode = "host";
+ };
+};
+
+&icnss {
+ status = "disabled";
+};
+
+&msm_sdw_codec {
+ status = "disabled";
+};
+
+&cdc_pdm_gpios {
+ status = "disabled";
+};
+
+&cdc_comp_gpios {
+ status = "disabled";
+};
+
+&cdc_dmic_gpios {
+ status = "disabled";
+};
+
+&cdc_sdw_gpios {
+ status = "disabled";
+};
+
+&wsa_spkr_en1 {
+ status = "disabled";
+};
+
+&wsa_spkr_en2 {
+ status = "disabled";
+};
+
+&qupv3_se8_spi {
+ status = "okay";
+};
+
+&wcd9xxx_intc {
+ status = "okay";
+};
+
+&wdsp_mgr {
+ status = "okay";
+};
+
+&wdsp_glink {
+ status = "okay";
+};
+
+&slim_aud {
+ status = "okay";
+};
+
+&dai_slim {
+ status = "okay";
+};
+
+&wcd934x_cdc {
+ status = "okay";
+};
+
+&clock_audio_lnbb {
+ status = "okay";
+};
+
+&tavil_snd {
+ status = "okay";
+ compatible = "qcom,qcs605-asoc-snd-tavil";
+ qcom,model = "qcs605-tavil-snd-card";
+ qcom,audio-routing =
+ "AIF4 VI", "MCLK",
+ "RX_BIAS", "MCLK",
+ "MADINPUT", "MCLK",
+ "DMIC0", "MIC BIAS1",
+ "MIC BIAS1", "Digital Mic0",
+ "DMIC1", "MIC BIAS1",
+ "MIC BIAS1", "Digital Mic1",
+ "DMIC2", "MIC BIAS3",
+ "MIC BIAS3", "Digital Mic2",
+ "DMIC3", "MIC BIAS3",
+ "MIC BIAS3", "Digital Mic3",
+ "SpkrLeft IN", "SPK1 OUT";
+ qcom,wsa-max-devs = <1>;
+ qcom,wsa-devs = <&wsa881x_0211>, <&wsa881x_0213>;
+ qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrLeft";
+};
+
+&soc {
+ wcd_rst_gpio1: msm_cdc_pinctrl@11 {
+ compatible = "qcom,msm-cdc-pinctrl";
+ qcom,cdc-rst-n-gpio = <&tlmm 11 0>;
+ pinctrl-names = "aud_active", "aud_sleep";
+ pinctrl-0 = <&cdc_reset_active>;
+ pinctrl-1 = <&cdc_reset_sleep>;
+ };
+};
+
+&wcd934x_cdc {
+ /delete-property/ cdc-vdd-mic-bias-supply;
+ /delete-property/ qcom,cdc-static-supplies;
+ qcom,wcd-rst-gpio-node = <&wcd_rst_gpio1>;
+};
+
+&wcd9335 {
+ /delete-property/ cdc-vdd-mic-bias-supply;
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc.dtsi b/arch/arm64/boot/dts/qcom/qcs605-lc.dtsi
index f8dde39..7e15752 100644
--- a/arch/arm64/boot/dts/qcom/qcs605-lc.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc.dtsi
@@ -212,6 +212,11 @@
vdd_gfx-supply = <&pm8005_s3_level>;
};
+&gpu_cx_gdsc {
+ /delete-property/ parent-supply;
+ parent-supply = <&pm8005_s1_level>;
+};
+
&gpu_gx_gdsc {
/delete-property/ parent-supply;
parent-supply = <&pm8005_s3_level>;
diff --git a/arch/arm64/boot/dts/qcom/qcs605-pm660-pm8005-regulator.dtsi b/arch/arm64/boot/dts/qcom/qcs605-pm660-pm8005-regulator.dtsi
index 382ba65..8efb7c1 100644
--- a/arch/arm64/boot/dts/qcom/qcs605-pm660-pm8005-regulator.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs605-pm660-pm8005-regulator.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
@@ -102,7 +102,8 @@
pm8005_s1_level: regulator-pm8005-s1-level {
regulator-name = "pm8005_s1_level";
qcom,set = <RPMH_REGULATOR_SET_ALL>;
- regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
+ regulator-min-microvolt
+ = <RPMH_REGULATOR_LEVEL_RETENTION>;
regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
qcom,min-dropout-voltage-level = <(-1)>;
};
@@ -110,7 +111,8 @@
pm8005_s1_level_ao: regulator-pm8005-s1-level-ao {
regulator-name = "pm8005_s1_level_ao";
qcom,set = <RPMH_REGULATOR_SET_ACTIVE>;
- regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
+ regulator-min-microvolt
+ = <RPMH_REGULATOR_LEVEL_RETENTION>;
regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
qcom,min-dropout-voltage-level = <(-1)>;
};
diff --git a/arch/arm64/boot/dts/qcom/qcs605.dtsi b/arch/arm64/boot/dts/qcom/qcs605.dtsi
index 16ae8de..61ea299 100644
--- a/arch/arm64/boot/dts/qcom/qcs605.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs605.dtsi
@@ -76,6 +76,10 @@
};
};
+&llcc {
+ compatible = "qcom,qcs605-llcc";
+};
+
&ipa_hw {
status = "disabled";
};
@@ -90,8 +94,8 @@
lmh-dcvs-00 {
trips {
active-config {
- temperature = <105000>;
- hysteresis = <40000>;
+ temperature = <100000>;
+ hysteresis = <35000>;
};
};
};
@@ -99,8 +103,8 @@
lmh-dcvs-01 {
trips {
active-config {
- temperature = <105000>;
- hysteresis = <40000>;
+ temperature = <100000>;
+ hysteresis = <35000>;
};
};
};
diff --git a/arch/arm64/boot/dts/qcom/sda670-hdk.dtsi b/arch/arm64/boot/dts/qcom/sda670-hdk.dtsi
index 5b1ed9c..fcffd44 100644
--- a/arch/arm64/boot/dts/qcom/sda670-hdk.dtsi
+++ b/arch/arm64/boot/dts/qcom/sda670-hdk.dtsi
@@ -17,6 +17,10 @@
/delete-property/ qcom,dsi-display-active;
};
+&qrd_batterydata {
+ #include "fg-gen3-batterydata-mlp466076-3250mah.dtsi"
+};
+
&dsi_hx8399_truly_cmd {
qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
@@ -32,6 +36,29 @@
qcom,dsi-display-active;
};
+&tavil_snd {
+ qcom,model = "sdm670-tavil-hdk-snd-card";
+ com,audio-routing =
+ "AIF4 VI", "MCLK",
+ "RX_BIAS", "MCLK",
+ "MADINPUT", "MCLK",
+ "AMIC2", "MIC BIAS2",
+ "MIC BIAS2", "Headset Mic",
+ "DMIC0", "MIC BIAS1",
+ "MIC BIAS1", "Digital Mic0",
+ "DMIC1", "MIC BIAS1",
+ "MIC BIAS1", "Digital Mic1",
+ "DMIC3", "MIC BIAS3",
+ "MIC BIAS3", "Digital Mic3",
+ "DMIC4", "MIC BIAS4",
+ "MIC BIAS4", "Digital Mic4",
+ "SpkrLeft IN", "SPK1 OUT";
+
+ qcom,wsa-max-devs = <1>;
+ qcom,wsa-devs = <&wsa881x_0211>, <&wsa881x_0213>;
+ qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrLeft";
+};
+
&ufsphy_mem {
compatible = "qcom,ufs-phy-qmp-v3";
@@ -57,3 +84,46 @@
status = "ok";
};
+
+&qusb_phy0 {
+ qcom,qusb-phy-host-init-seq =
+ /* <value reg_offset> */
+ <0x23 0x210 /* PWR_CTRL1 */
+ 0x03 0x04 /* PLL_ANALOG_CONTROLS_TWO */
+ 0x7c 0x18c /* PLL_CLOCK_INVERTERS */
+ 0x80 0x2c /* PLL_CMODE */
+ 0x0a 0x184 /* PLL_LOCK_DELAY */
+ 0x19 0xb4 /* PLL_DIGITAL_TIMERS_TWO */
+ 0x40 0x194 /* PLL_BIAS_CONTROL_1 */
+ 0x20 0x198 /* PLL_BIAS_CONTROL_2 */
+ 0x21 0x214 /* PWR_CTRL2 */
+ 0x00 0x220 /* IMP_CTRL1 */
+ 0x58 0x224 /* IMP_CTRL2 */
+ 0x77 0x240 /* TUNE1 */
+ 0x29 0x244 /* TUNE2 */
+ 0xca 0x248 /* TUNE3 */
+ 0x04 0x24c /* TUNE4 */
+ 0x03 0x250 /* TUNE5 */
+ 0x00 0x23c /* CHG_CTRL2 */
+ 0x22 0x210>; /* PWR_CTRL1 */
+ qcom,qusb-phy-init-seq =
+ /* <value reg_offset> */
+ <0x23 0x210 /* PWR_CTRL1 */
+ 0x03 0x04 /* PLL_ANALOG_CONTROLS_TWO */
+ 0x7c 0x18c /* PLL_CLOCK_INVERTERS */
+ 0x80 0x2c /* PLL_CMODE */
+ 0x0a 0x184 /* PLL_LOCK_DELAY */
+ 0x19 0xb4 /* PLL_DIGITAL_TIMERS_TWO */
+ 0x40 0x194 /* PLL_BIAS_CONTROL_1 */
+ 0x20 0x198 /* PLL_BIAS_CONTROL_2 */
+ 0x21 0x214 /* PWR_CTRL2 */
+ 0x25 0x220 /* IMP_CTRL1 */
+ 0x58 0x224 /* IMP_CTRL2 */
+ 0x65 0x240 /* TUNE1 */
+ 0x29 0x244 /* TUNE2 */
+ 0xca 0x248 /* TUNE3 */
+ 0x04 0x24c /* TUNE4 */
+ 0x03 0x250 /* TUNE5 */
+ 0x00 0x23c /* CHG_CTRL2 */
+ 0x22 0x210>; /* PWR_CTRL1 */
+};
diff --git a/arch/arm64/boot/dts/qcom/sda670.dtsi b/arch/arm64/boot/dts/qcom/sda670.dtsi
index d19aac3..0861718 100644
--- a/arch/arm64/boot/dts/qcom/sda670.dtsi
+++ b/arch/arm64/boot/dts/qcom/sda670.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2018, 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
@@ -17,3 +17,13 @@
model = "Qualcomm Technologies, Inc. SDA670";
qcom,msm-id = <337 0x0>;
};
+
+&soc {
+ qcom,rmnet-ipa {
+ status="disabled";
+ };
+};
+
+&ipa_hw {
+ status="disabled";
+};
diff --git a/arch/arm64/boot/dts/qcom/sda845-svr.dtsi b/arch/arm64/boot/dts/qcom/sda845-svr.dtsi
index 1062ca6..f6bf107d 100644
--- a/arch/arm64/boot/dts/qcom/sda845-svr.dtsi
+++ b/arch/arm64/boot/dts/qcom/sda845-svr.dtsi
@@ -270,6 +270,13 @@
qcom,init-voltage = <3312000>;
};
+&pm8998_l19 {
+ regulator-min-microvolt = <3104000>;
+ regulator-max-microvolt = <3104000>;
+ qcom,init-voltage = <3104000>;
+};
+
+
&ufsphy_mem {
compatible = "qcom,ufs-phy-qmp-v3";
diff --git a/arch/arm64/boot/dts/qcom/sdm429.dtsi b/arch/arm64/boot/dts/qcom/sdm429.dtsi
index b52ee2d..65f7b5e 100644
--- a/arch/arm64/boot/dts/qcom/sdm429.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm429.dtsi
@@ -69,8 +69,8 @@
target-dev = <&cpubw>;
cpu-to-dev-map =
< 960000 2929 >,
- < 1305600 5126 >,
- < 1497600 5859 >,
+ < 1305600 5053 >,
+ < 1497600 5712 >,
< 1708800 6445 >,
< 1804800 7104 >,
< 1958400 7104 >;
@@ -91,7 +91,7 @@
target-dev = <&mincpubw>;
cpu-to-dev-map =
< 1305600 2929 >,
- < 1804800 5859 >;
+ < 1804800 5712 >;
};
};
};
@@ -222,4 +222,7 @@
&msm_gpu {
/* Update GPU chip ID*/
qcom,chipid = <0x05000400>;
+
+ /* disable mem pools */
+ /delete-node/qcom,gpu-mempools;
};
diff --git a/arch/arm64/boot/dts/qcom/sdm439-camera-sensor-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdm439-camera-sensor-cdp.dtsi
index eae8c56..2987d67 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-camera-sensor-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439-camera-sensor-cdp.dtsi
@@ -30,7 +30,7 @@
cell-index = <1>;
reg = <0x1>;
compatible = "qcom,actuator";
- qcom,cci-master = <0>;
+ qcom,cci-master = <1>;
cam_vaf-supply = <&pm8953_l17>;
qcom,cam-vreg-name = "cam_vaf";
qcom,cam-vreg-min-voltage = <2850000>;
@@ -156,6 +156,43 @@
qcom,clock-rates = <19200000 0>;
};
+ eeprom2: qcom,eeprom@2 {
+ cell-index = <2>;
+ compatible = "qcom,eeprom";
+ qcom,cci-master = <1>;
+ reg = <0x2>;
+ cam_vdig-supply = <&pm8953_l3>;
+ cam_vana-supply = <&pm8953_l22>;
+ cam_vio-supply = <&pm8953_l6>;
+ cam_vaf-supply = <&pm8953_l17>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_vaf";
+ qcom,cam-vreg-min-voltage = <1200000 0 2800000 2850000>;
+ qcom,cam-vreg-max-voltage = <1200000 0 2800000 2850000>;
+ qcom,cam-vreg-op-mode = <105000 0 80000 100000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk2_default
+ &cam_sensor_front1_default>;
+ pinctrl-1 = <&cam_sensor_mclk2_sleep
+ &cam_sensor_front1_sleep>;
+ gpios = <&tlmm 28 0>,
+ <&tlmm 40 0>,
+ <&tlmm 39 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_MCLK2",
+ "CAM_RESET2",
+ "CAM_STANDBY2";
+ status = "ok";
+ clocks = <&clock_gcc clk_mclk2_clk_src>,
+ <&clock_gcc clk_gcc_camss_mclk2_clk>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <19200000 0>;
+ };
+
qcom,camera@0 {
cell-index = <0>;
compatible = "qcom,camera";
@@ -249,9 +286,9 @@
qcom,csiphy-sd-index = <1>;
qcom,csid-sd-index = <1>;
qcom,mount-angle = <90>;
- qcom,eeprom-src = <&eeprom1>;
+ qcom,eeprom-src = <&eeprom2>;
qcom,actuator-src = <&actuator1>;
- cam_vdig-supply = <&pm8953_l23>;
+ cam_vdig-supply = <&pm8953_l3>;
cam_vana-supply = <&pm8953_l22>;
cam_vio-supply = <&pm8953_l6>;
cam_vaf-supply = <&pm8953_l17>;
@@ -278,7 +315,7 @@
"CAM_STANDBY2";
qcom,sensor-position = <1>;
qcom,sensor-mode = <0>;
- qcom,cci-master = <0>;
+ qcom,cci-master = <1>;
status = "ok";
clocks = <&clock_gcc clk_mclk2_clk_src>,
<&clock_gcc clk_gcc_camss_mclk2_clk>;
diff --git a/arch/arm64/boot/dts/qcom/sdm439-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdm439-cdp.dtsi
index 6ecd0dd..cef5534 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439-cdp.dtsi
@@ -233,7 +233,7 @@
&dsi_hx8399c_hd_vid {
/delete-property/ qcom,mdss-dsi-panel-timings;
- qcom,mdss-dsi-panel-timings-phy-12nm = [08 06 0a 02 00 04 02 08];
+ qcom,mdss-dsi-panel-timings-phy-12nm = [09 06 0a 02 00 05 02 08];
qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_pwm";
qcom,mdss-dsi-bl-pmic-pwm-frequency = <100>;
@@ -568,3 +568,27 @@
qcom,mdss-dsi-pwm-gpio = <&pm8953_gpios 8 0>;
/delete-node/ qcom,mdss-dsi-display-timings;
};
+
+&dsi_truly_1080_vid {
+ /delete-property/ qcom,mdss-dsi-panel-timings;
+ qcom,mdss-dsi-panel-timings-phy-12nm = [17 0a 0f 06 02 08 06 0e];
+ qcom,mdss-dsi-t-clk-post = <0x02>;
+ qcom,mdss-dsi-t-clk-pre = <0x2d>;
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_pwm";
+ qcom,mdss-dsi-bl-pmic-pwm-frequency = <100>;
+ qcom,mdss-dsi-bl-pmic-bank-select = <0>;
+ qcom,mdss-dsi-pwm-gpio = <&pm8953_gpios 8 0>;
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
+
+&dsi_truly_1080_cmd {
+ /delete-property/ qcom,mdss-dsi-panel-timings;
+ qcom,mdss-dsi-panel-timings-phy-12nm = [17 0a 0f 06 02 08 06 0e];
+ qcom,mdss-dsi-t-clk-post = <0x02>;
+ qcom,mdss-dsi-t-clk-pre = <0x2d>;
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_pwm";
+ qcom,mdss-dsi-bl-pmic-pwm-frequency = <100>;
+ qcom,mdss-dsi-bl-pmic-bank-select = <0>;
+ qcom,mdss-dsi-pwm-gpio = <&pm8953_gpios 8 0>;
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm439-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm439-mtp.dtsi
index a940515..913d079 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439-mtp.dtsi
@@ -208,7 +208,7 @@
&dsi_hx8399c_hd_vid {
/delete-property/ qcom,mdss-dsi-panel-timings;
- qcom,mdss-dsi-panel-timings-phy-12nm = [08 06 0a 02 00 04 02 08];
+ qcom,mdss-dsi-panel-timings-phy-12nm = [09 06 0a 02 00 05 02 08];
qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_pwm";
qcom,mdss-dsi-bl-pmic-pwm-frequency = <100>;
@@ -544,6 +544,30 @@
/delete-node/ qcom,mdss-dsi-display-timings;
};
+&dsi_truly_1080_vid {
+ /delete-property/ qcom,mdss-dsi-panel-timings;
+ qcom,mdss-dsi-panel-timings-phy-12nm = [17 0a 0f 06 02 08 06 0e];
+ qcom,mdss-dsi-t-clk-post = <0x02>;
+ qcom,mdss-dsi-t-clk-pre = <0x2d>;
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_pwm";
+ qcom,mdss-dsi-bl-pmic-pwm-frequency = <100>;
+ qcom,mdss-dsi-bl-pmic-bank-select = <0>;
+ qcom,mdss-dsi-pwm-gpio = <&pm8953_gpios 8 0>;
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
+
+&dsi_truly_1080_cmd {
+ /delete-property/ qcom,mdss-dsi-panel-timings;
+ qcom,mdss-dsi-panel-timings-phy-12nm = [17 0a 0f 06 02 08 06 0e];
+ qcom,mdss-dsi-t-clk-post = <0x02>;
+ qcom,mdss-dsi-t-clk-pre = <0x2d>;
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_pwm";
+ qcom,mdss-dsi-bl-pmic-pwm-frequency = <100>;
+ qcom,mdss-dsi-bl-pmic-bank-select = <0>;
+ qcom,mdss-dsi-pwm-gpio = <&pm8953_gpios 8 0>;
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
+
&i2c_2 {
#include "smb1355.dtsi"
};
@@ -565,6 +589,15 @@
bias-disable; /* no-pull */
};
};
+
+ pmi632_ctm {
+ /* Disable GPIO1 for h/w base mitigation */
+ pmi632_ctm_default: pmi632_ctm_default {
+ pins = "gpio1";
+ bias-high-impedance; /* disable the GPIO */
+ bias-disable; /* no-pull */
+ };
+ };
};
&tlmm {
@@ -585,7 +618,7 @@
&smb1355_0 {
pinctrl-names = "default";
pinctrl-0 = <&smb_int_default
- &smb_en_default &pmi632_sense_default>;
+ &smb_en_default &pmi632_sense_default &pmi632_ctm_default>;
interrupt-parent = <&tlmm>;
interrupts = <61 IRQ_TYPE_LEVEL_LOW>;
smb1355_charger_0: qcom,smb1355-charger@1000 {
@@ -593,13 +626,15 @@
/delete-property/ io-channels;
/delete-property/ io-channels-names;
qcom,parallel-mode = <1>;
+ qcom,disable-ctm;
+ qcom,hw-die-temp-mitigation;
};
};
&smb1355_1 {
pinctrl-names = "default";
pinctrl-0 = <&smb_int_default
- &smb_en_default &pmi632_sense_default>;
+ &smb_en_default &pmi632_sense_default &pmi632_ctm_default>;
interrupt-parent = <&tlmm>;
interrupts = <61 IRQ_TYPE_LEVEL_LOW>;
smb1355_charger_1: qcom,smb1355-charger@1000 {
@@ -607,5 +642,7 @@
/delete-property/ io-channels;
/delete-property/ io-channels-names;
qcom,parallel-mode = <1>;
+ qcom,disable-ctm;
+ qcom,hw-die-temp-mitigation;
};
};
diff --git a/arch/arm64/boot/dts/qcom/sdm439-qrd.dtsi b/arch/arm64/boot/dts/qcom/sdm439-qrd.dtsi
index ac31fc8..20562d1 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-qrd.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439-qrd.dtsi
@@ -115,7 +115,7 @@
pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>;
pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off>;
- cd-gpios = <&tlmm 67 0x1>;
+ cd-gpios = <&tlmm 67 0x0>;
qcom,clk-rates = <400000 20000000 25000000 50000000 100000000
200000000>;
@@ -323,7 +323,7 @@
&dsi_hx8399c_hd_vid {
/delete-property/ qcom,mdss-dsi-panel-timings;
- qcom,mdss-dsi-panel-timings-phy-12nm = [08 06 0a 02 00 04 02 08];
+ qcom,mdss-dsi-panel-timings-phy-12nm = [09 06 0a 02 00 05 02 08];
qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_pwm";
qcom,mdss-dsi-bl-pmic-pwm-frequency = <100>;
@@ -371,6 +371,15 @@
bias-disable; /* no-pull */
};
};
+
+ pmi632_ctm {
+ /* Disable GPIO1 for h/w base mitigation */
+ pmi632_ctm_default: pmi632_ctm_default {
+ pins = "gpio1";
+ bias-high-impedance; /* disable the GPIO */
+ bias-disable; /* no-pull */
+ };
+ };
};
&tlmm {
@@ -391,7 +400,7 @@
&smb1355_0 {
pinctrl-names = "default";
pinctrl-0 = <&smb_int_default
- &smb_en_default &pmi632_sense_default>;
+ &smb_en_default &pmi632_sense_default &pmi632_ctm_default>;
interrupt-parent = <&tlmm>;
interrupts = <61 IRQ_TYPE_LEVEL_LOW>;
smb1355_charger_0: qcom,smb1355-charger@1000 {
@@ -399,13 +408,15 @@
/delete-property/ io-channels;
/delete-property/ io-channels-names;
qcom,parallel-mode = <1>;
+ qcom,disable-ctm;
+ qcom,hw-die-temp-mitigation;
};
};
&smb1355_1 {
pinctrl-names = "default";
pinctrl-0 = <&smb_int_default
- &smb_en_default &pmi632_sense_default>;
+ &smb_en_default &pmi632_sense_default &pmi632_ctm_default>;
interrupt-parent = <&tlmm>;
interrupts = <61 IRQ_TYPE_LEVEL_LOW>;
smb1355_charger_1: qcom,smb1355-charger@1000 {
@@ -413,5 +424,12 @@
/delete-property/ io-channels;
/delete-property/ io-channels-names;
qcom,parallel-mode = <1>;
+ qcom,disable-ctm;
+ qcom,hw-die-temp-mitigation;
};
};
+
+&pmi632_charger {
+ qcom,thermal-mitigation = <4200000 3500000 3000000 2500000
+ 2000000 1500000 1000000 500000>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm439-regulator.dtsi b/arch/arm64/boot/dts/qcom/sdm439-regulator.dtsi
index 414e8fe..42c3e83 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-regulator.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439-regulator.dtsi
@@ -477,17 +477,22 @@
qcom,cpr-quotient-adjustment =
<66 77 66>, /* SVSP/NOM/TUR:30/35/30 mV */
- <(-74) (-57) (-30)>, /* SVSP/NOM/TUR:-34/-26/-14 mV */
+ <(-74) 0 (-30)>, /* SVSP/NOM/TUR:-34/0/-14 mV */
<0 0 0>;
qcom,cpr-floor-to-ceiling-max-range =
- <50000 50000 50000 65000 65000>,
- <50000 50000 50000 65000 65000>,
- <50000 50000 50000 65000 65000>;
+ <50000 50000 65000 65000 65000>,
+ <50000 50000 65000 65000 65000>,
+ <50000 50000 65000 65000 65000>;
qcom,cpr-voltage-ceiling-override =
<(-1) (-1) 810000 845000 885000 960000 960000>;
+ qcom,cpr-virtual-corner-quotient-adjustment =
+ <0 0 0 0 0>,
+ <0 0 (-22) 0 0>, /* NOMP: -10 mV */
+ <0 0 0 0 0>;
+
qcom,cpr-enable;
};
diff --git a/arch/arm64/boot/dts/qcom/sdm439.dtsi b/arch/arm64/boot/dts/qcom/sdm439.dtsi
index be05b6e..9067bc9 100644
--- a/arch/arm64/boot/dts/qcom/sdm439.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439.dtsi
@@ -78,9 +78,9 @@
< 2929 /* 384 MHz */ >, /* SVS */
< 3221 /* 422.4 MHz */ >,
< 4248 /* 556.8 MHz */ >,
- < 5126 /* 662.4 MHz */ >, /* SVS+ */
- < 5859 /* 748.8 MHz */ >, /* NOM */
- < 6152 /* 806.4 MHz */ >, /* NOM+ */
+ < 5053 /* 662.4 MHz */ >, /* SVS+ */
+ < 5712 /* 748.8 MHz */ >, /* NOM */
+ < 6079 /* 796.8 MHz */ >, /* NOM+ */
< 6445 /* 844.8 MHz */ >,
< 7104 /* 931.2 MHz */ >; /* TURBO */
};
@@ -98,9 +98,9 @@
< 2929 /* 384 MHz */ >, /* SVS */
< 3221 /* 422.4 MHz */ >,
< 4248 /* 556.8 MHz */ >,
- < 5126 /* 662.4 MHz */ >, /* SVS+ */
- < 5859 /* 748.8 MHz */ >, /* NOM */
- < 6152 /* 806.4 MHz */ >, /* NOM+ */
+ < 5053 /* 662.4 MHz */ >, /* SVS+ */
+ < 5712 /* 748.8 MHz */ >, /* NOM */
+ < 6079 /* 796.8 MHz */ >, /* NOM+ */
< 6445 /* 844.8 MHz */ >,
< 7104 /* 931.2 MHz */ >; /* TURBO */
};
@@ -124,16 +124,16 @@
cpubw-cpufreq {
target-dev = <&cpubw>;
cpu-to-dev-map-0 =
- < 1305600 5126 >,
- < 1497600 5859 >,
+ < 1305600 5053 >,
+ < 1497600 5712 >,
< 1708800 6445 >,
< 1804800 7104 >,
< 1958400 7104 >;
cpu-to-dev-map-4 =
< 768000 2929 >,
- < 998400 5126 >,
- < 1171200 5859 >,
- < 1305600 6152 >,
+ < 998400 5053 >,
+ < 1171200 5712 >,
+ < 1305600 6079 >,
< 1459200 7104 >;
};
@@ -158,10 +158,10 @@
target-dev = <&mincpubw>;
cpu-to-dev-map-0 =
< 1305600 2929 >,
- < 1804800 5859 >;
+ < 1804800 5712 >;
cpu-to-dev-map-4 =
< 1171200 2929 >,
- < 1459200 5859 >;
+ < 1459200 5712 >;
};
};
};
diff --git a/arch/arm64/boot/dts/qcom/sdm450-pmi632-mtp-s3.dtsi b/arch/arm64/boot/dts/qcom/sdm450-pmi632-mtp-s3.dtsi
index 07d2e08..5db626b 100644
--- a/arch/arm64/boot/dts/qcom/sdm450-pmi632-mtp-s3.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm450-pmi632-mtp-s3.dtsi
@@ -68,6 +68,15 @@
bias-disable; /* no-pull */
};
};
+
+ pmi632_ctm {
+ /* Disable GPIO1 for h/w base mitigation */
+ pmi632_ctm_default: pmi632_ctm_default {
+ pins = "gpio1";
+ bias-high-impedance; /* disable the GPIO */
+ bias-disable; /* no-pull */
+ };
+ };
};
&tlmm {
@@ -88,7 +97,7 @@
&smb1355_0 {
pinctrl-names = "default";
pinctrl-0 = <&smb_int_default
- &smb_en_default &pmi632_sense_default>;
+ &smb_en_default &pmi632_sense_default &pmi632_ctm_default>;
interrupt-parent = <&tlmm>;
interrupts = <59 IRQ_TYPE_LEVEL_LOW>;
smb1355_charger_0: qcom,smb1355-charger@1000 {
@@ -96,13 +105,15 @@
/delete-property/ io-channels;
/delete-property/ io-channels-names;
qcom,parallel-mode = <1>;
+ qcom,disable-ctm;
+ qcom,hw-die-temp-mitigation;
};
};
&smb1355_1 {
pinctrl-names = "default";
pinctrl-0 = <&smb_int_default
- &smb_en_default &pmi632_sense_default>;
+ &smb_en_default &pmi632_sense_default &pmi632_ctm_default>;
interrupt-parent = <&tlmm>;
interrupts = <59 IRQ_TYPE_LEVEL_LOW>;
smb1355_charger_1: qcom,smb1355-charger@1000 {
@@ -110,5 +121,7 @@
/delete-property/ io-channels;
/delete-property/ io-channels-names;
qcom,parallel-mode = <1>;
+ qcom,disable-ctm;
+ qcom,hw-die-temp-mitigation;
};
};
diff --git a/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dtsi b/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dtsi
index a2bd5cd..8671877 100644
--- a/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dtsi
@@ -198,6 +198,15 @@
bias-disable; /* no-pull */
};
};
+
+ pmi632_ctm {
+ /* Disable GPIO1 for h/w base mitigation */
+ pmi632_ctm_default: pmi632_ctm_default {
+ pins = "gpio1";
+ bias-high-impedance; /* disable the GPIO */
+ bias-disable; /* no-pull */
+ };
+ };
};
&tlmm {
@@ -218,7 +227,7 @@
&smb1355_0 {
pinctrl-names = "default";
pinctrl-0 = <&smb_int_default
- &smb_en_default &pmi632_sense_default>;
+ &smb_en_default &pmi632_sense_default &pmi632_ctm_default>;
interrupt-parent = <&tlmm>;
interrupts = <59 IRQ_TYPE_LEVEL_LOW>;
smb1355_charger_0: qcom,smb1355-charger@1000 {
@@ -226,13 +235,15 @@
/delete-property/ io-channels;
/delete-property/ io-channels-names;
qcom,parallel-mode = <1>;
+ qcom,disable-ctm;
+ qcom,hw-die-temp-mitigation;
};
};
&smb1355_1 {
pinctrl-names = "default";
pinctrl-0 = <&smb_int_default
- &smb_en_default &pmi632_sense_default>;
+ &smb_en_default &pmi632_sense_default &pmi632_ctm_default>;
interrupt-parent = <&tlmm>;
interrupts = <59 IRQ_TYPE_LEVEL_LOW>;
smb1355_charger_1: qcom,smb1355-charger@1000 {
@@ -240,5 +251,12 @@
/delete-property/ io-channels;
/delete-property/ io-channels-names;
qcom,parallel-mode = <1>;
+ qcom,disable-ctm;
+ qcom,hw-die-temp-mitigation;
};
};
+
+&pmi632_charger {
+ qcom,thermal-mitigation = <4200000 3500000 3000000 2500000
+ 2000000 1500000 1000000 500000>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm632-qrd.dtsi b/arch/arm64/boot/dts/qcom/sdm632-qrd.dtsi
index cefc078..6a07bfe 100644
--- a/arch/arm64/boot/dts/qcom/sdm632-qrd.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm632-qrd.dtsi
@@ -18,3 +18,8 @@
qcom,redrive-voltage-level = <0 1800000 1900000>;
qcom,redrive-load = <105000>;
};
+
+&pmi632_charger {
+ qcom,thermal-mitigation = <4200000 3500000 3000000 2500000
+ 2000000 1500000 1000000 500000>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm670-camera.dtsi b/arch/arm64/boot/dts/qcom/sdm670-camera.dtsi
index 348ba6f..237152d 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-camera.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-camera.dtsi
@@ -338,17 +338,17 @@
iova-mem-region-io {
/* IO region is approximately 3 GB */
iova-region-name = "io";
- iova-region-start = <0xd911000>;
- iova-region-len = <0xd26ef000>;
+ iova-region-start = <0xda00000>;
+ iova-region-len = <0xd2500000>;
iova-region-id = <0x3>;
status = "ok";
};
iova-mem-qdss-region {
- /* qdss region is approximately 64K */
+ /* qdss region is approximately 1MB */
iova-region-name = "qdss";
iova-region-start = <0xd900000>;
- iova-region-len = <0x10000>;
+ iova-region-len = <0x100000>;
iova-region-id = <0x5>;
qdss-phy-addr = <0x16790000>;
status = "ok";
@@ -911,6 +911,9 @@
cam_ipe0: qcom,ipe0 {
cell-index = <0>;
compatible = "qcom,cam-ipe";
+ reg = <0xac87000 0x3000>;
+ reg-names = "ipe0_top";
+ reg-cam-base = <0x87000>;
regulator-names = "ipe0-vdd";
ipe0-vdd-supply = <&ipe_0_gdsc>;
clock-names = "ipe_0_ahb_clk",
@@ -938,6 +941,9 @@
cam_ipe1: qcom,ipe1 {
cell-index = <1>;
compatible = "qcom,cam-ipe";
+ reg = <0xac91000 0x3000>;
+ reg-names = "ipe1_top";
+ reg-cam-base = <0x91000>;
regulator-names = "ipe1-vdd";
ipe1-vdd-supply = <&ipe_1_gdsc>;
clock-names = "ipe_1_ahb_clk",
@@ -965,6 +971,9 @@
cam_bps: qcom,bps {
cell-index = <0>;
compatible = "qcom,cam-bps";
+ reg = <0xac6f000 0x3000>;
+ reg-names = "bps_top";
+ reg-cam-base = <0x6f000>;
regulator-names = "bps-vdd";
bps-vdd-supply = <&bps_gdsc>;
clock-names = "bps_ahb_clk",
diff --git a/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi
index 0461429..0453cee 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi
@@ -1490,6 +1490,34 @@
};
};
+ cdc_reset_ctrl {
+ cdc_reset_sleep: cdc_reset_sleep {
+ mux {
+ pins = "gpio11";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio11";
+ drive-strength = <2>;
+ bias-disable;
+ output-low;
+ };
+ };
+
+ cdc_reset_active:cdc_reset_active {
+ mux {
+ pins = "gpio11";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio11";
+ drive-strength = <8>;
+ bias-pull-down;
+ output-high;
+ };
+ };
+ };
+
/* WSA speaker reset pins */
spkr_1_sd_n {
spkr_1_sd_n_sleep: spkr_1_sd_n_sleep {
diff --git a/arch/arm64/boot/dts/qcom/sdm670-qrd-sku1.dtsi b/arch/arm64/boot/dts/qcom/sdm670-qrd-sku1.dtsi
index 2c1cde6..ecd389b 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-qrd-sku1.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-qrd-sku1.dtsi
@@ -10,5 +10,5 @@
* GNU General Public License for more details.
*/
-#include "sdm670-qrd.dtsi"
#include "sdm670-audio-overlay.dtsi"
+#include "sdm670-qrd.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/sdm670-qrd-sku2-overlay.dts b/arch/arm64/boot/dts/qcom/sdm670-qrd-sku2-overlay.dts
index d5edb36..2968ecc 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-qrd-sku2-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sdm670-qrd-sku2-overlay.dts
@@ -13,6 +13,11 @@
/dts-v1/;
/plugin/;
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
#include "sdm670-qrd-sku2.dtsi"
/ {
diff --git a/arch/arm64/boot/dts/qcom/sdm670-qrd-sku2.dtsi b/arch/arm64/boot/dts/qcom/sdm670-qrd-sku2.dtsi
index cdb652e..0f23216 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-qrd-sku2.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-qrd-sku2.dtsi
@@ -9,8 +9,8 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
-#include "sdm670-qrd.dtsi"
#include "sdm670-audio-overlay.dtsi"
+#include "sdm670-qrd.dtsi"
&dsi_dual_nt36850_truly_cmd_display {
/delete-property/ qcom,dsi-display-active;
diff --git a/arch/arm64/boot/dts/qcom/sdm670-regulator.dtsi b/arch/arm64/boot/dts/qcom/sdm670-regulator.dtsi
index 9d3f37d..3efadcb 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-regulator.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-regulator.dtsi
@@ -133,7 +133,8 @@
pm660l_s3_level: regulator-pm660l-s3-level {
regulator-name = "pm660l_s3_level";
qcom,set = <RPMH_REGULATOR_SET_ALL>;
- regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
+ regulator-min-microvolt
+ = <RPMH_REGULATOR_LEVEL_RETENTION>;
regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
qcom,min-dropout-voltage-level = <(-1)>;
};
@@ -141,7 +142,8 @@
pm660l_s3_level_ao: regulator-pm660l-s3-level-ao {
regulator-name = "pm660l_s3_level_ao";
qcom,set = <RPMH_REGULATOR_SET_ACTIVE>;
- regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
+ regulator-min-microvolt
+ = <RPMH_REGULATOR_LEVEL_RETENTION>;
regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
qcom,min-dropout-voltage-level = <(-1)>;
};
diff --git a/arch/arm64/boot/dts/qcom/sdm670-sde-display.dtsi b/arch/arm64/boot/dts/qcom/sdm670-sde-display.dtsi
index 395e88c..5d62c5a 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-sde-display.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-sde-display.dtsi
@@ -27,6 +27,7 @@
#include "dsi-panel-rm67195-amoled-fhd-cmd.dtsi"
#include "dsi-panel-nt36850-truly-dualmipi-wqhd-cmd.dtsi"
#include "dsi-panel-hx8399-truly-singlemipi-fhd-video.dtsi"
+#include "dsi-panel-hx83112a-truly-singlemipi-fhd-video.dtsi"
#include <dt-bindings/clock/mdss-10nm-pll-clk.h>
&soc {
@@ -489,7 +490,30 @@
ibb-supply = <&lcdb_ncp_vreg>;
};
- ext_dsi_bridge_display: qcom,dsi-display@17 {
+ dsi_hx83112a_truly_video_display: qcom,dsi-display@17 {
+ compatible = "qcom,dsi-display";
+ label = "dsi_hx83112a_truly_video_display";
+ qcom,display-type = "primary";
+
+ qcom,dsi-ctrl = <&mdss_dsi0>;
+ qcom,dsi-phy = <&mdss_dsi_phy0>;
+ clocks = <&mdss_dsi0_pll BYTECLK_MUX_0_CLK>,
+ <&mdss_dsi0_pll PCLK_MUX_0_CLK>;
+ clock-names = "src_byte_clk", "src_pixel_clk";
+
+ pinctrl-names = "panel_active", "panel_suspend";
+ pinctrl-0 = <&sde_dsi_active &sde_te_active>;
+ pinctrl-1 = <&sde_dsi_suspend &sde_te_suspend>;
+ qcom,platform-te-gpio = <&tlmm 10 0>;
+ qcom,platform-reset-gpio = <&tlmm 75 0>;
+
+ qcom,dsi-panel = <&dsi_hx83112a_truly_video>;
+ vddio-supply = <&pm660_l11>;
+ lab-supply = <&lcdb_ldo_vreg>;
+ ibb-supply = <&lcdb_ncp_vreg>;
+ };
+
+ ext_dsi_bridge_display: qcom,dsi-display@18 {
compatible = "qcom,dsi-display";
label = "ext_dsi_bridge_display";
qcom,display-type = "primary";
@@ -561,7 +585,7 @@
qcom,mdss-dsi-display-timings {
timing@0{
qcom,mdss-dsi-panel-phy-timings = [00 1c 07 07 23 21 07
- 07 05 03 04 00];
+ 07 05 02 04 00];
qcom,display-topology = <2 0 2>,
<1 0 2>;
qcom,default-topology-index = <0>;
@@ -583,7 +607,7 @@
qcom,mdss-dsi-display-timings {
timing@0{
qcom,mdss-dsi-panel-phy-timings = [00 1c 07 07 23 21 07
- 07 05 03 04 00];
+ 07 05 02 04 00];
qcom,display-topology = <2 0 2>,
<1 0 2>;
qcom,default-topology-index = <0>;
@@ -607,7 +631,7 @@
qcom,mdss-dsi-display-timings {
timing@0{
qcom,mdss-dsi-panel-phy-timings = [00 15 05 05 20 1f 05
- 05 03 03 04 00];
+ 05 03 02 04 00];
qcom,display-topology = <1 1 1>,
<2 2 1>, /* dsc merge */
<2 1 1>; /* 3d mux */
@@ -634,7 +658,7 @@
qcom,mdss-dsi-display-timings {
timing@0{
qcom,mdss-dsi-panel-phy-timings = [00 15 05 05 20 1f 05
- 04 03 03 04 00];
+ 04 03 02 04 00];
qcom,display-topology = <1 1 1>,
<2 2 1>, /* dsc merge */
<2 1 1>; /* 3d mux */
@@ -649,7 +673,7 @@
qcom,mdss-dsi-display-timings {
timing@0{
qcom,mdss-dsi-panel-phy-timings = [00 1c 07 07 23 21 07
- 07 05 03 04 00];
+ 07 05 02 04 00];
qcom,display-topology = <1 0 1>,
<2 0 1>;
qcom,default-topology-index = <0>;
@@ -663,7 +687,7 @@
qcom,mdss-dsi-display-timings {
timing@0{
qcom,mdss-dsi-panel-phy-timings = [00 1c 07 07 23 21 07
- 07 05 03 04 00];
+ 07 05 02 04 00];
qcom,display-topology = <2 0 2>,
<1 0 2>;
qcom,default-topology-index = <0>;
@@ -682,7 +706,7 @@
qcom,panel-roi-alignment = <720 40 720 40 720 40>;
qcom,partial-update-enabled = "single_roi";
qcom,mdss-dsi-panel-phy-timings = [00 1a 06 06 22 20 07
- 07 04 03 04 00];
+ 07 04 02 04 00];
};
timing@1{
qcom,display-topology = <1 0 1>,
@@ -691,7 +715,7 @@
qcom,panel-roi-alignment = <540 40 540 40 540 40>;
qcom,partial-update-enabled = "single_roi";
qcom,mdss-dsi-panel-phy-timings = [00 1a 06 06 22 20 07
- 07 04 03 04 00];
+ 07 04 02 04 00];
};
timing@2{
qcom,display-topology = <1 0 1>,
@@ -700,7 +724,7 @@
qcom,panel-roi-alignment = <360 40 360 40 360 40>;
qcom,partial-update-enabled = "single_roi";
qcom,mdss-dsi-panel-phy-timings = [00 1a 06 06 22 20 07
- 07 04 03 04 00];
+ 07 04 02 04 00];
};
};
};
@@ -711,20 +735,20 @@
qcom,mdss-dsi-display-timings {
timing@0{
qcom,mdss-dsi-panel-phy-timings = [00 24 09 09 26 24 09
- 09 06 03 04 00];
+ 09 06 02 04 00];
qcom,display-topology = <2 0 2>;
qcom,default-topology-index = <0>;
};
timing@1{
qcom,mdss-dsi-panel-phy-timings = [00 1c 07 07 23 21 07
- 07 05 03 04 00];
+ 07 05 02 04 00];
qcom,display-topology = <2 0 2>,
<1 0 2>;
qcom,default-topology-index = <0>;
};
timing@2{
qcom,mdss-dsi-panel-phy-timings = [00 18 06 06 21 20 06
- 06 04 03 04 00];
+ 06 04 02 04 00];
qcom,display-topology = <2 0 2>;
qcom,default-topology-index = <0>;
};
@@ -737,13 +761,13 @@
qcom,mdss-dsi-display-timings {
timing@0 { /* 1080p */
qcom,mdss-dsi-panel-phy-timings = [00 1A 06 06 22 20 07
- 07 04 03 04 00];
+ 07 04 02 04 00];
qcom,display-topology = <1 1 1>;
qcom,default-topology-index = <0>;
};
timing@1 { /* qhd */
qcom,mdss-dsi-panel-phy-timings = [00 15 05 05 20 1f 05
- 05 03 03 04 00];
+ 05 03 02 04 00];
qcom,display-topology = <1 1 1>,
<2 2 1>, /* dsc merge */
<2 1 1>; /* 3d mux */
@@ -758,13 +782,13 @@
qcom,mdss-dsi-display-timings {
timing@0 { /* qhd */
qcom,mdss-dsi-panel-phy-timings = [00 1c 07 07 23 21 07
- 07 05 03 04 00];
+ 07 05 02 04 00];
qcom,display-topology = <2 2 2>;
qcom,default-topology-index = <0>;
};
timing@1 { /* 4k */
qcom,mdss-dsi-panel-phy-timings = [00 18 06 06 21 20 06
- 06 04 03 04 00];
+ 06 04 02 04 00];
qcom,display-topology = <2 2 2>;
qcom,default-topology-index = <0>;
};
@@ -777,7 +801,7 @@
qcom,mdss-dsi-display-timings {
timing@0 {
qcom,mdss-dsi-panel-phy-timings = [00 1c 07 07 23 21 07
- 07 05 03 04 00];
+ 07 05 02 04 00];
qcom,display-topology = <2 0 2>,
<1 0 2>;
qcom,default-topology-index = <0>;
@@ -792,7 +816,7 @@
qcom,mdss-dsi-display-timings {
timing@0 {
qcom,mdss-dsi-panel-phy-timings = [00 1c 07 07 23 21 07
- 07 05 03 04 00];
+ 07 05 02 04 00];
qcom,display-topology = <2 0 2>,
<1 0 2>;
qcom,default-topology-index = <0>;
@@ -808,7 +832,7 @@
qcom,mdss-dsi-display-timings {
timing@0 {
qcom,mdss-dsi-panel-phy-timings = [00 1c 05 06 0b 0c
- 05 07 05 03 04 00];
+ 05 07 05 02 04 00];
qcom,display-topology = <1 0 1>;
qcom,default-topology-index = <0>;
};
@@ -826,7 +850,7 @@
qcom,mdss-dsi-display-timings {
timing@0 {
qcom,mdss-dsi-panel-phy-timings = [00 1c 05 06 0b 0c
- 05 07 05 03 04 00];
+ 05 07 05 02 04 00];
qcom,display-topology = <1 0 1>;
qcom,default-topology-index = <0>;
};
@@ -841,7 +865,7 @@
qcom,mdss-dsi-display-timings {
timing@0 {
qcom,mdss-dsi-panel-phy-timings = [00 1c 08 07 23 22
- 07 07 05 03 04 00];
+ 07 07 05 02 04 00];
qcom,display-topology = <1 0 1>;
qcom,default-topology-index = <0>;
};
@@ -862,7 +886,7 @@
qcom,mdss-dsi-display-timings {
timing@0{
qcom,mdss-dsi-panel-phy-timings = [00 1f 08 08 24 23 08
- 08 05 03 04 00];
+ 08 05 02 04 00];
qcom,display-topology = <2 0 2>,
<1 0 2>;
qcom,default-topology-index = <0>;
@@ -881,14 +905,39 @@
qcom,esd-check-enabled;
qcom,mdss-dsi-panel-status-check-mode = "reg_read";
qcom,mdss-dsi-panel-status-command = [06 01 00 01 00 00 01 0a];
- qcom,mdss-dsi-panel-status-command-state = "dsi_lp_mode";
+ qcom,mdss-dsi-panel-status-command-state = "dsi_hs_mode";
qcom,mdss-dsi-panel-status-value = <0x9d 0x9d 0x9d 0x9d>;
qcom,mdss-dsi-panel-on-check-value = <0x9d 0x9d 0x9d 0x9d>;
qcom,mdss-dsi-panel-status-read-length = <4>;
qcom,mdss-dsi-display-timings {
timing@0 {
qcom,mdss-dsi-panel-phy-timings = [00 1f 08 08 24 22 08
- 08 05 03 04 00];
+ 08 05 02 04 00];
+ qcom,display-topology = <1 0 1>;
+ qcom,default-topology-index = <0>;
+ };
+ };
+};
+
+&dsi_hx83112a_truly_video {
+ qcom,mdss-dsi-t-clk-post = <0x0E>;
+ qcom,mdss-dsi-t-clk-pre = <0x30>;
+
+ qcom,mdss-dsi-min-refresh-rate = <55>;
+ qcom,mdss-dsi-max-refresh-rate = <60>;
+ qcom,mdss-dsi-pan-enable-dynamic-fps;
+ qcom,esd-check-enabled;
+ qcom,mdss-dsi-panel-status-check-mode = "reg_read";
+ qcom,mdss-dsi-panel-status-command = [06 01 00 01 00 00 01 0a];
+ qcom,mdss-dsi-panel-status-command-state = "dsi_hs_mode";
+ qcom,mdss-dsi-panel-status-value = <0x9d 0x9d 0x9d 0x9d>;
+ qcom,mdss-dsi-panel-on-check-value = <0x9d 0x9d 0x9d 0x9d>;
+ qcom,mdss-dsi-panel-status-read-length = <4>;
+
+ qcom,mdss-dsi-display-timings {
+ timing@0 {
+ qcom,mdss-dsi-panel-phy-timings = [00 1f 08 08 24 22 08
+ 08 05 02 04 00];
qcom,display-topology = <1 0 1>;
qcom,default-topology-index = <0>;
};
diff --git a/arch/arm64/boot/dts/qcom/sdm670.dtsi b/arch/arm64/boot/dts/qcom/sdm670.dtsi
index c962b42..575e448 100644
--- a/arch/arm64/boot/dts/qcom/sdm670.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670.dtsi
@@ -2969,6 +2969,7 @@
};
&gpu_cx_gdsc {
+ parent-supply = <&pm660l_s3_level>;
status = "ok";
};
diff --git a/arch/arm64/boot/dts/qcom/sdm710-qrd-overlay.dts b/arch/arm64/boot/dts/qcom/sdm710-qrd-overlay.dts
index 08c3433..91139ba 100644
--- a/arch/arm64/boot/dts/qcom/sdm710-qrd-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sdm710-qrd-overlay.dts
@@ -13,6 +13,11 @@
/dts-v1/;
/plugin/;
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
#include "sdm670-qrd-sku1.dtsi"
/ {
diff --git a/arch/arm64/boot/dts/qcom/sdm710-qrd-sku2-overlay.dts b/arch/arm64/boot/dts/qcom/sdm710-qrd-sku2-overlay.dts
index 91891ba..526fe6b 100644
--- a/arch/arm64/boot/dts/qcom/sdm710-qrd-sku2-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sdm710-qrd-sku2-overlay.dts
@@ -13,6 +13,11 @@
/dts-v1/;
/plugin/;
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
#include "sdm670-qrd-sku2.dtsi"
/ {
diff --git a/arch/arm64/boot/dts/qcom/sdm710-qrd.dts b/arch/arm64/boot/dts/qcom/sdm710-qrd.dts
index 4eb414f..af0c717 100644
--- a/arch/arm64/boot/dts/qcom/sdm710-qrd.dts
+++ b/arch/arm64/boot/dts/qcom/sdm710-qrd.dts
@@ -14,8 +14,8 @@
/dts-v1/;
#include "sdm710.dtsi"
-#include "sdm670-qrd.dtsi"
#include "sdm670-audio-overlay.dtsi"
+#include "sdm670-qrd.dtsi"
/ {
model = "Qualcomm Technologies, Inc. SDM710 PM660 + PM660L QRD";
diff --git a/arch/arm64/boot/dts/qcom/sdm845-670-usb-common.dtsi b/arch/arm64/boot/dts/qcom/sdm845-670-usb-common.dtsi
index bf09b67..9b88356 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-670-usb-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-670-usb-common.dtsi
@@ -404,6 +404,7 @@
snps,hird-threshold = /bits/ 8 <0x10>;
snps,usb3_lpm_capable;
usb-core-id = <1>;
+ dr_mode = "host";
};
};
@@ -429,7 +430,8 @@
0x254 /* QUSB2PHY_TEST1 */
0x198 /* PLL_BIAS_CONTROL_2 */
0x228 /* QUSB2PHY_SQ_CTRL1 */
- 0x22c>; /* QUSB2PHY_SQ_CTRL2 */
+ 0x22c /* QUSB2PHY_SQ_CTRL2 */
+ 0x27c>; /* QUSB2PHY_DEBUG_CTRL1 */
qcom,qusb-phy-init-seq =
/* <value reg_offset> */
diff --git a/arch/arm64/boot/dts/qcom/sdm845-audio.dtsi b/arch/arm64/boot/dts/qcom/sdm845-audio.dtsi
index 944c1dd..b5c1ded 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-audio.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-audio.dtsi
@@ -27,7 +27,9 @@
qcom,clk-div = <192>;
qcom,clk-mult = <10>;
};
+};
+&audio_apr {
snd_934x: sound-tavil {
compatible = "qcom,sdm845-asoc-snd-tavil";
qcom,model = "sdm845-tavil-snd-card";
diff --git a/arch/arm64/boot/dts/qcom/sdm845-camera.dtsi b/arch/arm64/boot/dts/qcom/sdm845-camera.dtsi
index 2e2de74..e77dcc3 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-camera.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-camera.dtsi
@@ -311,17 +311,17 @@
iova-mem-region-io {
/* IO region is approximately 3 GB */
iova-region-name = "io";
- iova-region-start = <0xd911000>;
- iova-region-len = <0xd26ef000>;
+ iova-region-start = <0xda00000>;
+ iova-region-len = <0xd2500000>;
iova-region-id = <0x3>;
status = "ok";
};
iova-mem-qdss-region {
- /* qdss region is approximately 64K */
+ /* qdss region is approximately 1MB */
iova-region-name = "qdss";
iova-region-start = <0xd900000>;
- iova-region-len = <0x10000>;
+ iova-region-len = <0x100000>;
iova-region-id = <0x5>;
qdss-phy-addr = <0x16790000>;
status = "ok";
@@ -881,6 +881,9 @@
cam_ipe0: qcom,ipe0 {
cell-index = <0>;
compatible = "qcom,cam-ipe";
+ reg = <0xac87000 0x3000>;
+ reg-names = "ipe0_top";
+ reg-cam-base = <0x87000>;
regulator-names = "ipe0-vdd";
ipe0-vdd-supply = <&ipe_0_gdsc>;
clock-names = "ipe_0_ahb_clk",
@@ -908,6 +911,9 @@
cam_ipe1: qcom,ipe1 {
cell-index = <1>;
compatible = "qcom,cam-ipe";
+ reg = <0xac91000 0x3000>;
+ reg-names = "ipe1_top";
+ reg-cam-base = <0x91000>;
regulator-names = "ipe1-vdd";
ipe1-vdd-supply = <&ipe_1_gdsc>;
clock-names = "ipe_1_ahb_clk",
@@ -935,6 +941,9 @@
cam_bps: qcom,bps {
cell-index = <0>;
compatible = "qcom,cam-bps";
+ reg = <0xac6f000 0x3000>;
+ reg-names = "bps_top";
+ reg-cam-base = <0x6f000>;
regulator-names = "bps-vdd";
bps-vdd-supply = <&bps_gdsc>;
clock-names = "bps_ahb_clk",
diff --git a/arch/arm64/boot/dts/qcom/sdm845-cdp-audio-overlay.dtsi b/arch/arm64/boot/dts/qcom/sdm845-cdp-audio-overlay.dtsi
index 68f2e51..99798ff 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-cdp-audio-overlay.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-cdp-audio-overlay.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2018, 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
@@ -13,9 +13,7 @@
#include "sdm845-audio-overlay.dtsi"
-&soc {
- sound-tavil {
- qcom,us-euro-gpios = <&tavil_us_euro_sw>;
- };
+&snd_934x {
+ qcom,us-euro-gpios = <&tavil_us_euro_sw>;
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-interposer-pm660.dtsi b/arch/arm64/boot/dts/qcom/sdm845-interposer-pm660.dtsi
index d6be6d4..0a02bfb 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-interposer-pm660.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-interposer-pm660.dtsi
@@ -265,6 +265,10 @@
/delete-property/ vdd_mx-supply;
};
+&gpu_cx_gdsc {
+ /delete-property/ parent-supply;
+};
+
&gpu_gx_gdsc {
/delete-property/ parent-supply;
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
index 812a313..274a862 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
@@ -341,22 +341,13 @@
};
&usb1 {
- status = "okay";
extcon = <&extcon_usb1>;
};
-&qusb_phy1 {
- status = "okay";
-};
-
&ext_5v_boost {
status = "ok";
};
-&usb_qmp_phy {
- status = "okay";
-};
-
&pm8998_vadc {
chan@83 {
label = "vph_pwr";
diff --git a/arch/arm64/boot/dts/qcom/sdm845-qrd-audio-overlay.dtsi b/arch/arm64/boot/dts/qcom/sdm845-qrd-audio-overlay.dtsi
index 361fa2f..ed75507 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-qrd-audio-overlay.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-qrd-audio-overlay.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2018, 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
@@ -13,21 +13,19 @@
#include "sdm845-audio-overlay.dtsi"
-&soc {
- sound-tavil {
- qcom,model = "sdm845-tavil-qrd-snd-card";
+&snd_934x {
+ qcom,model = "sdm845-tavil-qrd-snd-card";
- qcom,wsa-max-devs = <1>;
- qcom,wsa-devs = <&wsa881x_0211>, <&wsa881x_0213>;
- qcom,wsa-aux-dev-prefix = "SpkrRight", "SpkrRight";
+ qcom,wsa-max-devs = <1>;
+ qcom,wsa-devs = <&wsa881x_0211>, <&wsa881x_0213>;
+ qcom,wsa-aux-dev-prefix = "SpkrRight", "SpkrRight";
- qcom,msm-mbhc-usbc-audio-supported = <1>;
+ qcom,msm-mbhc-usbc-audio-supported = <1>;
- qcom,usbc-analog-en2-gpio = <&tlmm 51 0>;
- pinctrl-names = "aud_active", "aud_sleep";
- pinctrl-0 = <&wcd_usbc_analog_en2_active>;
- pinctrl-1 = <&wcd_usbc_analog_en2_idle>;
- };
+ qcom,usbc-analog-en2-gpio = <&tlmm 51 0>;
+ pinctrl-names = "aud_active", "aud_sleep";
+ pinctrl-0 = <&wcd_usbc_analog_en2_active>;
+ pinctrl-1 = <&wcd_usbc_analog_en2_idle>;
};
&us_euro_sw_wcd_active {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-regulator.dtsi b/arch/arm64/boot/dts/qcom/sdm845-regulator.dtsi
index ec8665b..34beda4 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-regulator.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-regulator.dtsi
@@ -142,7 +142,8 @@
pm8998_s9_level: regulator-s9-level {
regulator-name = "pm8998_s9_level";
qcom,set = <RPMH_REGULATOR_SET_ALL>;
- regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
+ regulator-min-microvolt
+ = <RPMH_REGULATOR_LEVEL_RETENTION>;
regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
qcom,min-dropout-voltage-level = <(-1)>;
};
@@ -150,7 +151,8 @@
pm8998_s9_level_ao: regulator-s9-level-ao {
regulator-name = "pm8998_s9_level_ao";
qcom,set = <RPMH_REGULATOR_SET_ACTIVE>;
- regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
+ regulator-min-microvolt
+ = <RPMH_REGULATOR_LEVEL_RETENTION>;
regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
qcom,min-dropout-voltage-level = <(-1)>;
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-v2-camera.dtsi b/arch/arm64/boot/dts/qcom/sdm845-v2-camera.dtsi
index 97cb981..c9669d9 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-v2-camera.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-v2-camera.dtsi
@@ -248,17 +248,17 @@
iova-mem-region-io {
/* IO region is approximately 3 GB */
iova-region-name = "io";
- iova-region-start = <0xd911000>;
- iova-region-len = <0xd26ef000>;
+ iova-region-start = <0xda00000>;
+ iova-region-len = <0xd2500000>;
iova-region-id = <0x3>;
status = "ok";
};
iova-mem-qdss-region {
- /* qdss region is approximately 64K */
+ /* qdss region is approximately 1MB */
iova-region-name = "qdss";
iova-region-start = <0xd900000>;
- iova-region-len = <0x10000>;
+ iova-region-len = <0x100000>;
iova-region-id = <0x5>;
qdss-phy-addr = <0x16790000>;
status = "ok";
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index 26b0385..4efab0b 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -1550,6 +1550,7 @@
qcom,firmware-name = "modem";
qcom,pil-self-auth;
qcom,sysmon-id = <0>;
+ qcom,minidump-id = <3>;
qcom,ssctl-instance-id = <0x12>;
qcom,override-acc;
qcom,signal-aop;
@@ -2375,6 +2376,7 @@
qcom,xprt-version = <1>;
qcom,fragmented-data;
qcom,dynamic-wakeup-source;
+ qcom,low-latency-xprt;
};
qcom,ipc_router_cdsp_xprt {
@@ -4057,9 +4059,12 @@
&mdss_core_gdsc {
status = "ok";
+ qcom,en-few-wait-val = <6>;
+ qcom,en-rest-wait-val = <5>;
};
&gpu_cx_gdsc {
+ parent-supply = <&pm8998_s9_level>;
status = "ok";
};
diff --git a/arch/arm64/boot/dts/qcom/sdw3100-msm8909w-1gb-wtp.dts b/arch/arm64/boot/dts/qcom/sdw3100-msm8909w-1gb-wtp.dts
new file mode 100644
index 0000000..e3bdfd9
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdw3100-msm8909w-1gb-wtp.dts
@@ -0,0 +1,355 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/dts-v1/;
+
+#include "msm8909-mtp.dtsi"
+#include "msm8909w-gpu.dtsi"
+#include "msm8909w.dtsi"
+#include "msm8909w-bg-memory.dtsi"
+#include "8909w-pm660.dtsi"
+#include "msm8909-audio-bg_codec.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. MSM8909W BG 1GB WTP SDW3100";
+ compatible = "qcom,msm8909-mtp", "qcom,msm8909", "qcom,mtp";
+ qcom,msm-id = <245 0>,
+ <258 0>,
+ <275 0>,
+ <300 0>;
+ qcom,board-id = <8 0xf>;
+ qcom,pmic-id = <0x0001001b 0x0 0x0 0x0>,
+ <0x0001011b 0x0 0x0 0x0>;
+};
+
+&soc {
+ i2c@78b9000 { /* BLSP1 QUP5 */
+ synaptics@20 {
+ compatible = "synaptics,dsx-i2c";
+ reg = <0x20>;
+ interrupt-parent = <&msm_gpio>;
+ interrupts = <98 0x2008>;
+ vdd_ana-supply = <&pm660_l18>;
+ vcc_i2c-supply = <&pm660_l13>;
+ synaptics,pwr-reg-name = "vdd_ana";
+ synaptics,bus-reg-name = "vcc_i2c";
+ pinctrl-names = "pmx_ts_active", "pmx_ts_suspend",
+ "pmx_ts_release";
+ pinctrl-0 = <&ts_int_active &ts_reset_active>;
+ pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
+ pinctrl-2 = <&ts_release>;
+ synaptics,irq-gpio = <&msm_gpio 98 0x2008>;
+ synaptics,irq-on-state = <0>;
+ synaptics,irq-flags = <0x2008>;
+ synaptics,power-delay-ms = <200>;
+ synaptics,reset-delay-ms = <200>;
+ synaptics,max-y-for-2d = <389>;
+ synaptics,bus-lpm-cur-uA = <450>;
+ synaptics,do-not-disable-regulators;
+ synaptics,wakeup-gestures-en;
+ synaptics,resume-in-workqueue;
+ synaptics,x-flip;
+ synaptics,y-flip;
+ /delete-property/ synaptics,reset-gpio;
+ /delete-property/ synaptics,display-coords;
+ /delete-property/ synaptics,panel-coords;
+ /delete-property/ synaptics,power-down;
+ /delete-property/ synaptics,disable-gpios;
+ /delete-property/ synaptics,is_wake;
+ };
+
+ /delete-node/ it7260@46;
+ };
+
+ qcom,blackghost {
+ compatible = "qcom,pil-blackghost";
+
+ qcom,pil-force-shutdown;
+ qcom,firmware-name = "bg-wear";
+ /* GPIO inputs from blackghost */
+ qcom,bg2ap-status-gpio = <&msm_gpio 97 0>;
+ qcom,bg2ap-errfatal-gpio = <&msm_gpio 95 0>;
+ /* GPIO output to blackghost */
+ qcom,ap2bg-status-gpio = <&msm_gpio 17 0>;
+ qcom,ap2bg-errfatal-gpio = <&msm_gpio 23 0>;
+ };
+
+ qcom,msm-ssc-sensors {
+ compatible = "qcom,msm-ssc-sensors";
+ };
+
+ qcom,glink-bgcom-xprt-bg {
+ compatible = "qcom,glink-bgcom-xprt";
+ label = "bg";
+ qcom,qos-config = <&glink_qos_bg>;
+ qcom,ramp-time = <0x10>,
+ <0x20>,
+ <0x30>,
+ <0x40>;
+ };
+
+ glink_qos_bg: qcom,glink-qos-config-bg {
+ compatible = "qcom,glink-qos-config";
+ qcom,flow-info = <0x80 0x0>,
+ <0x70 0x1>,
+ <0x60 0x2>,
+ <0x50 0x3>;
+ qcom,mtu-size = <0x800>;
+ qcom,tput-stats-cycle = <0xa>;
+ };
+
+ qcom,glink_pkt {
+ compatible = "qcom,glinkpkt";
+
+ qcom,glinkpkt-bg-daemon {
+ qcom,glinkpkt-transport = "bgcom";
+ qcom,glinkpkt-edge = "bg";
+ qcom,glinkpkt-ch-name = "bg-daemon";
+ qcom,glinkpkt-dev-name = "glink_pkt_bg_daemon";
+ };
+
+ qcom,glinkpkt-bg-display-ctrl {
+ qcom,glinkpkt-transport = "bgcom";
+ qcom,glinkpkt-edge = "bg";
+ qcom,glinkpkt-ch-name = "display-ctrl";
+ qcom,glinkpkt-dev-name = "glink_pkt_bg_display_ctrl";
+ };
+
+ qcom,glinkpkt-bg-display-data {
+ qcom,glinkpkt-transport = "bgcom";
+ qcom,glinkpkt-edge = "bg";
+ qcom,glinkpkt-ch-name = "display-data";
+ qcom,glinkpkt-dev-name = "glink_pkt_bg_display_data";
+ };
+
+ qcom,glinkpkt-bg-rsb-ctrl {
+ qcom,glinkpkt-transport = "bgcom";
+ qcom,glinkpkt-edge = "bg";
+ qcom,glinkpkt-ch-name = "RSB_CTRL";
+ qcom,glinkpkt-dev-name = "glink_pkt_bg_rsb_ctrl";
+ };
+ };
+
+ spi@78B8000 { /* BLSP1 QUP4 */
+ status = "ok";
+ qcom,bg-spi {
+ compatible = "qcom,bg-spi";
+ reg = <0>;
+ spi-max-frequency = <16000000>;
+ interrupt-parent = <&msm_gpio>;
+ qcom,irq-gpio = <&msm_gpio 110 1>;
+ };
+ };
+
+ qcom,msm-thermal {
+ vdd-dig-supply = <&pm660_s2_floor_corner>;
+
+ msm_thermal_freq: qcom,vdd-apps-rstr {
+ qcom,vdd-rstr-reg = "vdd-apps";
+ qcom,levels = <1094400>;
+ qcom,freq-req;
+ };
+ };
+
+ qcom,bg-rsb {
+ compatible = "qcom,bg-rsb";
+ vdd-ldo1-supply = <&pm660_l11>;
+ vdd-ldo2-supply = <&pm660_l15>;
+ };
+
+ qcom,bg-daemon {
+ compatible = "qcom,bg-daemon";
+ qcom,bg-reset-gpio = <&pm660_gpios 5 0>;
+ ssr-reg1-supply = <&pm660_l3>;
+ ssr-reg2-supply = <&pm660_l9>;
+ };
+
+ qcom,bcl {
+ compatible = "qcom,bcl";
+ qcom,bcl-enable;
+ qcom,bcl-framework-interface;
+ qcom,bcl-freq-control-list = <&CPU0 &CPU1 &CPU2 &CPU3>;
+ qcom,bcl-hotplug-list = <&CPU2 &CPU3>;
+ qcom,bcl-soc-hotplug-list = <&CPU2 &CPU3>;
+ qcom,ibat-monitor {
+ qcom,low-threshold-uamp = <1000000>;
+ qcom,high-threshold-uamp = <2000000>;
+ qcom,mitigation-freq-khz = <1094400>;
+ qcom,vph-high-threshold-uv = <3500000>;
+ qcom,vph-low-threshold-uv = <3200000>;
+ qcom,soc-low-threshold = <10>;
+ qcom,thermal-handle = <&msm_thermal_freq>;
+ };
+ };
+};
+
+&audio_codec_mtp {
+ status = "disabled";
+};
+
+&audio_codec_bg {
+ status = "ok";
+};
+
+&bg_cdc {
+ status = "ok";
+ vdd-spkr-supply = <&pm660_l11>;
+};
+
+&i2c_1 {
+ status = "okay";
+ nq@28 {
+ compatible = "qcom,nq-nci";
+ reg = <0x28>;
+ qcom,nq-irq = <&msm_gpio 50 0x00>;
+ qcom,nq-ven = <&msm_gpio 36 0x00>;
+ qcom,nq-firm = <&msm_gpio 38 0x00>;
+ qcom,nq-esepwr = <&msm_gpio 49 0x00>;
+ qcom,nq-clkreq = <&pm660_gpios 4 0x00>;
+ qcom,clk-src = "BBCLK3";
+ interrupt-parent = <&msm_gpio>;
+ interrupts = <50 0>;
+ interrupt-names = "nfc_irq";
+ pinctrl-names = "nfc_active","nfc_suspend";
+ pinctrl-0 = <&nfcw_int_active &nfcw_disable_active
+ &nfc_clk_default>;
+ pinctrl-1 = <&nfcw_int_suspend &nfcw_disable_suspend>;
+ clocks = <&clock_rpm clk_bb_clk3_pin>;
+ clock-names = "ref_clk";
+ };
+};
+
+&spi_0 {
+ status = "disabled";
+};
+
+&i2c_3 {
+ status = "disabled";
+};
+
+&i2c_4 {
+ status = "disabled";
+};
+
+&i2c_2 {
+ status = "disabled";
+};
+
+&sdc1_clk_off {
+ config {
+ pins = "sdc1_clk";
+ bias-disable; /* NO pull */
+ drive-strength = <2>; /* 2 MA */
+ output-low;
+ };
+};
+
+&sdc1_cmd_off {
+ config {
+ pins = "sdc1_cmd";
+ bias-disable; /* NO pull */
+ drive-strength = <2>; /* 2 MA */
+ output-low;
+ };
+};
+
+&sdc1_data_off {
+ config {
+ pins = "sdc1_data";
+ bias-disable; /* NO pull */
+ drive-strength = <2>; /* 2 MA */
+ output-low;
+ };
+};
+
+&sdhc_2 {
+ status = "disabled";
+};
+
+&blsp1_uart1 {
+ status = "ok";
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart_console_sleep>;
+};
+
+/* Pinctrl dt nodes for interrupt & reset gpio for Synaptics touch controller */
+&ts_int_active {
+ mux {
+ pins = "gpio98";
+ };
+
+ config {
+ pins = "gpio98";
+ };
+};
+
+&ts_int_suspend {
+ mux {
+ pins = "gpio98";
+ };
+
+ config {
+ pins = "gpio98";
+ /delete-property/ bias-pull-down;
+ bias-disable; /* No PULL */
+ };
+};
+
+&ts_reset_active {
+ mux {
+ pins = "gpio16";
+ };
+
+ config {
+ pins = "gpio16";
+ };
+};
+
+&ts_reset_suspend {
+ mux {
+ pins = "gpio16";
+ };
+
+ config {
+ pins = "gpio16";
+ };
+};
+
+&ts_release {
+ mux {
+ pins = "gpio98", "gpio16";
+ };
+
+ config {
+ pins = "gpio98", "gpio16";
+ };
+};
+
+&spi4_cs0_active {
+ mux {
+ pins = "gpio14";
+ function = "blsp_spi4";
+ };
+ config {
+ pins = "gpio14";
+ drive-strength = <2>;
+ bias-disable; /* No PULL */
+ output-high;
+ };
+};
+
+&mdss_dsi0 {
+ qcom,dsi-pref-prim-pan = <&dsi_auo_390p_cmd>;
+ qcom,platform-bklight-en-gpio = <&msm_gpio 52 0>;
+ qcom,platform-enable-gpio = <&msm_gpio 59 0>;
+};
diff --git a/arch/arm64/configs/msm8937-perf_defconfig b/arch/arm64/configs/msm8937-perf_defconfig
index 3f161f4..bf35544 100644
--- a/arch/arm64/configs/msm8937-perf_defconfig
+++ b/arch/arm64/configs/msm8937-perf_defconfig
@@ -340,7 +340,6 @@
CONFIG_SPI_SPIDEV=y
CONFIG_SLIMBUS_MSM_NGD=y
CONFIG_SPMI=y
-CONFIG_SPMI_MSM_PMIC_ARB_DEBUG=y
CONFIG_PINCTRL_MSM8937=y
CONFIG_PINCTRL_MSM8917=y
CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
@@ -379,10 +378,7 @@
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_CPR=y
-CONFIG_REGULATOR_CPR4_APSS=y
-CONFIG_REGULATOR_CPRH_KBSS=y
CONFIG_REGULATOR_MEM_ACC=y
-CONFIG_REGULATOR_MSM_GFX_LDO=y
CONFIG_REGULATOR_QPNP_LABIBB=y
CONFIG_REGULATOR_QPNP_LCDB=y
CONFIG_REGULATOR_QPNP=y
@@ -395,9 +391,7 @@
CONFIG_VIDEO_V4L2_SUBDEV_API=y
CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_MSM_CAMERA=y
-CONFIG_MSM_CAMERA_DEBUG=y
CONFIG_MSMB_CAMERA=y
-CONFIG_MSMB_CAMERA_DEBUG=y
CONFIG_MSM_CAMERA_SENSOR=y
CONFIG_MSM_CPP=y
CONFIG_MSM_CCI=y
@@ -566,7 +560,6 @@
CONFIG_MSM_PIL=y
CONFIG_MSM_PIL_SSR_GENERIC=y
CONFIG_MSM_PIL_MSS_QDSP6V5=y
-CONFIG_ICNSS=y
CONFIG_MSM_PERFORMANCE=y
CONFIG_MSM_EVENT_TIMER=y
CONFIG_MSM_AVTIMER=y
@@ -598,6 +591,9 @@
CONFIG_MSM_TZ_LOG=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_SECURITY=y
+CONFIG_EXT4_ENCRYPTION=y
+CONFIG_EXT4_FS_ENCRYPTION=y
+CONFIG_EXT4_FS_ICE_ENCRYPTION=y
CONFIG_F2FS_FS=y
CONFIG_F2FS_FS_SECURITY=y
CONFIG_QUOTA=y
@@ -629,12 +625,12 @@
CONFIG_CORESIGHT_CTI=y
CONFIG_CORESIGHT_EVENT=y
CONFIG_CORESIGHT_HWEVENT=y
+CONFIG_PFK=y
CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
CONFIG_SECURITY=y
CONFIG_HARDENED_USERCOPY=y
CONFIG_SECURITY_SELINUX=y
CONFIG_SECURITY_SMACK=y
-CONFIG_CRYPTO_CTR=y
CONFIG_CRYPTO_XCBC=y
CONFIG_CRYPTO_MD4=y
CONFIG_CRYPTO_TWOFISH=y
diff --git a/arch/arm64/configs/msm8937_defconfig b/arch/arm64/configs/msm8937_defconfig
index 25ad0bc..ba390c4 100644
--- a/arch/arm64/configs/msm8937_defconfig
+++ b/arch/arm64/configs/msm8937_defconfig
@@ -348,7 +348,6 @@
CONFIG_SPI_SPIDEV=y
CONFIG_SLIMBUS_MSM_NGD=y
CONFIG_SPMI=y
-CONFIG_SPMI_MSM_PMIC_ARB_DEBUG=y
CONFIG_PINCTRL_MSM8937=y
CONFIG_PINCTRL_MSM8917=y
CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
@@ -387,10 +386,7 @@
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_CPR=y
-CONFIG_REGULATOR_CPR4_APSS=y
-CONFIG_REGULATOR_CPRH_KBSS=y
CONFIG_REGULATOR_MEM_ACC=y
-CONFIG_REGULATOR_MSM_GFX_LDO=y
CONFIG_REGULATOR_QPNP_LABIBB=y
CONFIG_REGULATOR_QPNP_LCDB=y
CONFIG_REGULATOR_QPNP=y
@@ -563,7 +559,6 @@
CONFIG_QCOM_SCM=y
CONFIG_MSM_BOOT_STATS=y
CONFIG_MSM_CORE_HANG_DETECT=y
-CONFIG_MSM_GLADIATOR_HANG_DETECT=y
CONFIG_QCOM_WATCHDOG_V2=y
CONFIG_QCOM_MEMORY_DUMP_V2=y
CONFIG_MSM_DEBUG_LAR_UNLOCK=y
@@ -584,7 +579,6 @@
CONFIG_MSM_PIL=y
CONFIG_MSM_PIL_SSR_GENERIC=y
CONFIG_MSM_PIL_MSS_QDSP6V5=y
-CONFIG_ICNSS=y
CONFIG_MSM_PERFORMANCE=y
CONFIG_MSM_EVENT_TIMER=y
CONFIG_MSM_AVTIMER=y
@@ -616,6 +610,9 @@
CONFIG_MSM_TZ_LOG=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_SECURITY=y
+CONFIG_EXT4_ENCRYPTION=y
+CONFIG_EXT4_FS_ENCRYPTION=y
+CONFIG_EXT4_FS_ICE_ENCRYPTION=y
CONFIG_F2FS_FS=y
CONFIG_F2FS_FS_SECURITY=y
CONFIG_QUOTA=y
@@ -646,7 +643,6 @@
CONFIG_DEBUG_OBJECTS_WORK=y
CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y
-CONFIG_SLUB_DEBUG_ON=y
CONFIG_DEBUG_KMEMLEAK=y
CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=4000
CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y
@@ -695,12 +691,12 @@
CONFIG_CORESIGHT_CTI=y
CONFIG_CORESIGHT_EVENT=y
CONFIG_CORESIGHT_HWEVENT=y
+CONFIG_PFK=y
CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
CONFIG_SECURITY=y
CONFIG_HARDENED_USERCOPY=y
CONFIG_SECURITY_SELINUX=y
CONFIG_SECURITY_SMACK=y
-CONFIG_CRYPTO_CTR=y
CONFIG_CRYPTO_XCBC=y
CONFIG_CRYPTO_MD4=y
CONFIG_CRYPTO_TWOFISH=y
diff --git a/arch/arm64/configs/msm8953-perf_defconfig b/arch/arm64/configs/msm8953-perf_defconfig
index 9ac93aa..eeb1d74 100644
--- a/arch/arm64/configs/msm8953-perf_defconfig
+++ b/arch/arm64/configs/msm8953-perf_defconfig
@@ -604,6 +604,11 @@
CONFIG_MSM_TZ_LOG=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_SECURITY=y
+CONFIG_EXT4_ENCRYPTION=y
+CONFIG_EXT4_FS_ENCRYPTION=y
+CONFIG_EXT4_FS_ICE_ENCRYPTION=y
+CONFIG_F2FS_FS=y
+CONFIG_F2FS_FS_SECURITY=y
CONFIG_QUOTA=y
CONFIG_QUOTA_NETLINK_INTERFACE=y
CONFIG_QFMT_V2=y
@@ -633,12 +638,12 @@
CONFIG_CORESIGHT_CTI=y
CONFIG_CORESIGHT_EVENT=y
CONFIG_CORESIGHT_HWEVENT=y
+CONFIG_PFK=y
CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
CONFIG_SECURITY=y
CONFIG_HARDENED_USERCOPY=y
CONFIG_SECURITY_SELINUX=y
CONFIG_SECURITY_SMACK=y
-CONFIG_CRYPTO_CTR=y
CONFIG_CRYPTO_XCBC=y
CONFIG_CRYPTO_MD4=y
CONFIG_CRYPTO_TWOFISH=y
diff --git a/arch/arm64/configs/msm8953_defconfig b/arch/arm64/configs/msm8953_defconfig
index 63dce91..d0783cd 100644
--- a/arch/arm64/configs/msm8953_defconfig
+++ b/arch/arm64/configs/msm8953_defconfig
@@ -571,7 +571,6 @@
CONFIG_QCOM_SCM=y
CONFIG_MSM_BOOT_STATS=y
CONFIG_MSM_CORE_HANG_DETECT=y
-CONFIG_MSM_GLADIATOR_HANG_DETECT=y
CONFIG_QCOM_WATCHDOG_V2=y
CONFIG_QCOM_MEMORY_DUMP_V2=y
CONFIG_MSM_DEBUG_LAR_UNLOCK=y
@@ -624,6 +623,11 @@
CONFIG_MSM_TZ_LOG=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_SECURITY=y
+CONFIG_EXT4_ENCRYPTION=y
+CONFIG_EXT4_FS_ENCRYPTION=y
+CONFIG_EXT4_FS_ICE_ENCRYPTION=y
+CONFIG_F2FS_FS=y
+CONFIG_F2FS_FS_SECURITY=y
CONFIG_QUOTA=y
CONFIG_QUOTA_NETLINK_INTERFACE=y
CONFIG_QFMT_V2=y
@@ -701,12 +705,12 @@
CONFIG_CORESIGHT_CTI=y
CONFIG_CORESIGHT_EVENT=y
CONFIG_CORESIGHT_HWEVENT=y
+CONFIG_PFK=y
CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
CONFIG_SECURITY=y
CONFIG_HARDENED_USERCOPY=y
CONFIG_SECURITY_SELINUX=y
CONFIG_SECURITY_SMACK=y
-CONFIG_CRYPTO_CTR=y
CONFIG_CRYPTO_XCBC=y
CONFIG_CRYPTO_MD4=y
CONFIG_CRYPTO_TWOFISH=y
diff --git a/arch/arm64/configs/sdm670-perf_defconfig b/arch/arm64/configs/sdm670-perf_defconfig
index 956bcc5..ac21b63 100644
--- a/arch/arm64/configs/sdm670-perf_defconfig
+++ b/arch/arm64/configs/sdm670-perf_defconfig
@@ -513,6 +513,7 @@
CONFIG_QCOM_RUN_QUEUE_STATS=y
CONFIG_QCOM_LLCC=y
CONFIG_QCOM_SDM670_LLCC=y
+CONFIG_QCOM_QCS605_LLCC=y
CONFIG_QCOM_LLCC_PERFMON=m
CONFIG_MSM_SERVICE_LOCATOR=y
CONFIG_MSM_SERVICE_NOTIFIER=y
@@ -579,11 +580,14 @@
CONFIG_QCOM_QFPROM=y
CONFIG_SENSORS_SSC=y
CONFIG_MSM_TZ_LOG=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_SECURITY=y
CONFIG_EXT4_ENCRYPTION=y
+CONFIG_EXT4_FS_ENCRYPTION=y
+CONFIG_EXT4_FS_ICE_ENCRYPTION=y
+CONFIG_F2FS_FS=y
+CONFIG_F2FS_FS_SECURITY=y
+CONFIG_F2FS_FS_ENCRYPTION=y
CONFIG_QUOTA=y
CONFIG_QUOTA_NETLINK_INTERFACE=y
CONFIG_QFMT_V2=y
@@ -615,12 +619,14 @@
CONFIG_CORESIGHT_EVENT=y
CONFIG_CORESIGHT_HWEVENT=y
CONFIG_CORESIGHT_DUMMY=y
+CONFIG_PFK=y
CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
CONFIG_SECURITY=y
CONFIG_HARDENED_USERCOPY=y
CONFIG_FORTIFY_SOURCE=y
CONFIG_SECURITY_SELINUX=y
CONFIG_SECURITY_SMACK=y
+CONFIG_CRYPTO_GCM=y
CONFIG_CRYPTO_XCBC=y
CONFIG_CRYPTO_MD4=y
CONFIG_CRYPTO_TWOFISH=y
diff --git a/arch/arm64/configs/sdm670_defconfig b/arch/arm64/configs/sdm670_defconfig
index f6895a5..9a6da1f 100644
--- a/arch/arm64/configs/sdm670_defconfig
+++ b/arch/arm64/configs/sdm670_defconfig
@@ -313,6 +313,8 @@
CONFIG_INPUT_UINPUT=y
# CONFIG_SERIO_SERPORT is not set
# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVMEM is not set
+# CONFIG_DEVKMEM is not set
CONFIG_SERIAL_MSM_GENI=y
CONFIG_SERIAL_MSM_GENI_CONSOLE=y
CONFIG_DIAG_CHAR=y
@@ -525,6 +527,7 @@
CONFIG_QCOM_RUN_QUEUE_STATS=y
CONFIG_QCOM_LLCC=y
CONFIG_QCOM_SDM670_LLCC=y
+CONFIG_QCOM_QCS605_LLCC=y
CONFIG_QCOM_LLCC_PERFMON=m
CONFIG_MSM_SERVICE_LOCATOR=y
CONFIG_MSM_SERVICE_NOTIFIER=y
@@ -597,11 +600,14 @@
CONFIG_QCOM_QFPROM=y
CONFIG_SENSORS_SSC=y
CONFIG_MSM_TZ_LOG=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_SECURITY=y
CONFIG_EXT4_ENCRYPTION=y
+CONFIG_EXT4_FS_ENCRYPTION=y
+CONFIG_EXT4_FS_ICE_ENCRYPTION=y
+CONFIG_F2FS_FS=y
+CONFIG_F2FS_FS_SECURITY=y
+CONFIG_F2FS_FS_ENCRYPTION=y
CONFIG_QUOTA=y
CONFIG_QUOTA_NETLINK_INTERFACE=y
CONFIG_QFMT_V2=y
@@ -675,12 +681,14 @@
CONFIG_CORESIGHT_TGU=y
CONFIG_CORESIGHT_HWEVENT=y
CONFIG_CORESIGHT_DUMMY=y
+CONFIG_PFK=y
CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
CONFIG_SECURITY=y
CONFIG_HARDENED_USERCOPY=y
CONFIG_FORTIFY_SOURCE=y
CONFIG_SECURITY_SELINUX=y
CONFIG_SECURITY_SMACK=y
+CONFIG_CRYPTO_GCM=y
CONFIG_CRYPTO_XCBC=y
CONFIG_CRYPTO_MD4=y
CONFIG_CRYPTO_TWOFISH=y
diff --git a/arch/arm64/configs/sdm845-perf_defconfig b/arch/arm64/configs/sdm845-perf_defconfig
index e35e571..0c54182 100644
--- a/arch/arm64/configs/sdm845-perf_defconfig
+++ b/arch/arm64/configs/sdm845-perf_defconfig
@@ -520,6 +520,7 @@
CONFIG_QCOM_EUD=y
CONFIG_QCOM_WATCHDOG_V2=y
CONFIG_QCOM_MEMORY_DUMP_V2=y
+CONFIG_QCOM_MINIDUMP=y
CONFIG_QCOM_BUS_SCALING=y
CONFIG_QCOM_BUS_CONFIG_RPMH=y
CONFIG_QCOM_SECURE_BUFFER=y
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 28196b1..fd38814 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -27,6 +27,7 @@
generic-y += poll.h
generic-y += preempt.h
generic-y += resource.h
+generic-y += qrwlock.h
generic-y += rwsem.h
generic-y += segment.h
generic-y += sembuf.h
diff --git a/arch/arm64/include/asm/spinlock.h b/arch/arm64/include/asm/spinlock.h
index b15a5ab..53c0f54 100644
--- a/arch/arm64/include/asm/spinlock.h
+++ b/arch/arm64/include/asm/spinlock.h
@@ -186,169 +186,7 @@
}
#define arch_spin_is_contended arch_spin_is_contended
-/*
- * Write lock implementation.
- *
- * Write locks set bit 31. Unlocking, is done by writing 0 since the lock is
- * exclusively held.
- *
- * The memory barriers are implicit with the load-acquire and store-release
- * instructions.
- */
-
-static inline void arch_write_lock(arch_rwlock_t *rw)
-{
- unsigned int tmp;
-
- asm volatile(ARM64_LSE_ATOMIC_INSN(
- /* LL/SC */
- " sevl\n"
- "1: wfe\n"
- "2: ldaxr %w0, %1\n"
- " cbnz %w0, 1b\n"
- " stxr %w0, %w2, %1\n"
- " cbnz %w0, 2b\n"
- __nops(1),
- /* LSE atomics */
- "1: mov %w0, wzr\n"
- "2: casa %w0, %w2, %1\n"
- " cbz %w0, 3f\n"
- " ldxr %w0, %1\n"
- " cbz %w0, 2b\n"
- " wfe\n"
- " b 1b\n"
- "3:")
- : "=&r" (tmp), "+Q" (rw->lock)
- : "r" (0x80000000)
- : "memory");
-}
-
-static inline int arch_write_trylock(arch_rwlock_t *rw)
-{
- unsigned int tmp;
-
- asm volatile(ARM64_LSE_ATOMIC_INSN(
- /* LL/SC */
- "1: ldaxr %w0, %1\n"
- " cbnz %w0, 2f\n"
- " stxr %w0, %w2, %1\n"
- " cbnz %w0, 1b\n"
- "2:",
- /* LSE atomics */
- " mov %w0, wzr\n"
- " casa %w0, %w2, %1\n"
- __nops(2))
- : "=&r" (tmp), "+Q" (rw->lock)
- : "r" (0x80000000)
- : "memory");
-
- return !tmp;
-}
-
-static inline void arch_write_unlock(arch_rwlock_t *rw)
-{
- asm volatile(ARM64_LSE_ATOMIC_INSN(
- " stlr wzr, %0",
- " swpl wzr, wzr, %0")
- : "=Q" (rw->lock) :: "memory");
-}
-
-/* write_can_lock - would write_trylock() succeed? */
-#define arch_write_can_lock(x) ((x)->lock == 0)
-
-/*
- * Read lock implementation.
- *
- * It exclusively loads the lock value, increments it and stores the new value
- * back if positive and the CPU still exclusively owns the location. If the
- * value is negative, the lock is already held.
- *
- * During unlocking there may be multiple active read locks but no write lock.
- *
- * The memory barriers are implicit with the load-acquire and store-release
- * instructions.
- *
- * Note that in UNDEFINED cases, such as unlocking a lock twice, the LL/SC
- * and LSE implementations may exhibit different behaviour (although this
- * will have no effect on lockdep).
- */
-static inline void arch_read_lock(arch_rwlock_t *rw)
-{
- unsigned int tmp, tmp2;
-
- asm volatile(
- " sevl\n"
- ARM64_LSE_ATOMIC_INSN(
- /* LL/SC */
- "1: wfe\n"
- "2: ldaxr %w0, %2\n"
- " add %w0, %w0, #1\n"
- " tbnz %w0, #31, 1b\n"
- " stxr %w1, %w0, %2\n"
- " cbnz %w1, 2b\n"
- __nops(1),
- /* LSE atomics */
- "1: wfe\n"
- "2: ldxr %w0, %2\n"
- " adds %w1, %w0, #1\n"
- " tbnz %w1, #31, 1b\n"
- " casa %w0, %w1, %2\n"
- " sbc %w0, %w1, %w0\n"
- " cbnz %w0, 2b")
- : "=&r" (tmp), "=&r" (tmp2), "+Q" (rw->lock)
- :
- : "cc", "memory");
-}
-
-static inline void arch_read_unlock(arch_rwlock_t *rw)
-{
- unsigned int tmp, tmp2;
-
- asm volatile(ARM64_LSE_ATOMIC_INSN(
- /* LL/SC */
- "1: ldxr %w0, %2\n"
- " sub %w0, %w0, #1\n"
- " stlxr %w1, %w0, %2\n"
- " cbnz %w1, 1b",
- /* LSE atomics */
- " movn %w0, #0\n"
- " staddl %w0, %2\n"
- __nops(2))
- : "=&r" (tmp), "=&r" (tmp2), "+Q" (rw->lock)
- :
- : "memory");
-}
-
-static inline int arch_read_trylock(arch_rwlock_t *rw)
-{
- unsigned int tmp, tmp2;
-
- asm volatile(ARM64_LSE_ATOMIC_INSN(
- /* LL/SC */
- " mov %w1, #1\n"
- "1: ldaxr %w0, %2\n"
- " add %w0, %w0, #1\n"
- " tbnz %w0, #31, 2f\n"
- " stxr %w1, %w0, %2\n"
- " cbnz %w1, 1b\n"
- "2:",
- /* LSE atomics */
- " ldr %w0, %2\n"
- " adds %w1, %w0, #1\n"
- " tbnz %w1, #31, 1f\n"
- " casa %w0, %w1, %2\n"
- " sbc %w1, %w1, %w0\n"
- __nops(1)
- "1:")
- : "=&r" (tmp), "=&r" (tmp2), "+Q" (rw->lock)
- :
- : "cc", "memory");
-
- return !tmp2;
-}
-
-/* read_can_lock - would read_trylock() succeed? */
-#define arch_read_can_lock(x) ((x)->lock < 0x80000000)
+#include <asm/qrwlock.h>
#define arch_read_lock_flags(lock, flags) arch_read_lock(lock)
#define arch_write_lock_flags(lock, flags) arch_write_lock(lock)
diff --git a/arch/arm64/include/asm/spinlock_types.h b/arch/arm64/include/asm/spinlock_types.h
index 55be59a..6b85601 100644
--- a/arch/arm64/include/asm/spinlock_types.h
+++ b/arch/arm64/include/asm/spinlock_types.h
@@ -36,10 +36,6 @@
#define __ARCH_SPIN_LOCK_UNLOCKED { 0 , 0 }
-typedef struct {
- volatile unsigned int lock;
-} arch_rwlock_t;
-
-#define __ARCH_RW_LOCK_UNLOCKED { 0 }
+#include <asm-generic/qrwlock_types.h>
#endif
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 6befc9c..c1d02d1 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -253,14 +253,12 @@
#define VM_FAULT_BADMAP 0x010000
#define VM_FAULT_BADACCESS 0x020000
-static int __do_page_fault(struct mm_struct *mm, unsigned long addr,
+static int __do_page_fault(struct vm_area_struct *vma, unsigned long addr,
unsigned int mm_flags, unsigned long vm_flags,
struct task_struct *tsk)
{
- struct vm_area_struct *vma;
int fault;
- vma = find_vma(mm, addr);
fault = VM_FAULT_BADMAP;
if (unlikely(!vma))
goto out;
@@ -318,6 +316,7 @@
int fault, sig, code;
unsigned long vm_flags = VM_READ | VM_WRITE;
unsigned int mm_flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
+ struct vm_area_struct *vma = NULL;
if (notify_page_fault(regs, esr))
return 0;
@@ -356,6 +355,14 @@
}
/*
+ * let's try a speculative page fault without grabbing the
+ * mmap_sem.
+ */
+ fault = handle_speculative_fault(mm, addr, mm_flags, &vma);
+ if (fault != VM_FAULT_RETRY)
+ goto done;
+
+ /*
* As per x86, we may deadlock here. However, since the kernel only
* validly references user space from well defined areas of the code,
* we can bug out early if this is from code which shouldn't.
@@ -377,19 +384,44 @@
#endif
}
- fault = __do_page_fault(mm, addr, mm_flags, vm_flags, tsk);
+ if (!vma || !can_reuse_spf_vma(vma, addr))
+ vma = find_vma(mm, addr);
- /*
- * If we need to retry but a fatal signal is pending, handle the
- * signal first. We do not need to release the mmap_sem because it
- * would already be released in __lock_page_or_retry in mm/filemap.c.
- */
- if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) {
- if (!user_mode(regs))
- goto no_context;
- return 0;
+ fault = __do_page_fault(vma, addr, mm_flags, vm_flags, tsk);
+ if (fault & VM_FAULT_RETRY) {
+ /*
+ * If we need to retry but a fatal signal is pending, handle the
+ * signal first. We do not need to release the mmap_sem because
+ * it would already be released in __lock_page_or_retry in
+ * mm/filemap.c.
+ */
+
+ if (fatal_signal_pending(current)) {
+ if (!user_mode(regs))
+ goto no_context;
+ return 0;
+ }
+
+ /*
+ * Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk of
+ * starvation.
+ */
+ if (mm_flags & FAULT_FLAG_ALLOW_RETRY) {
+ mm_flags &= ~FAULT_FLAG_ALLOW_RETRY;
+ mm_flags |= FAULT_FLAG_TRIED;
+
+ /*
+ * Do not try to reuse this vma and fetch it
+ * again since we will release the mmap_sem.
+ */
+ vma = NULL;
+ goto retry;
+ }
}
+ up_read(&mm->mmap_sem);
+done:
+
/*
* Major/minor page fault accounting is only done on the initial
* attempt. If we go through a retry, it is extremely likely that the
@@ -407,19 +439,8 @@
perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, regs,
addr);
}
- if (fault & VM_FAULT_RETRY) {
- /*
- * Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk of
- * starvation.
- */
- mm_flags &= ~FAULT_FLAG_ALLOW_RETRY;
- mm_flags |= FAULT_FLAG_TRIED;
- goto retry;
- }
}
- up_read(&mm->mmap_sem);
-
/*
* Handle the "normal" case first - VM_FAULT_MAJOR
*/
diff --git a/drivers/bluetooth/bluetooth-power.c b/drivers/bluetooth/bluetooth-power.c
index 7f7c942..0574e44 100644
--- a/drivers/bluetooth/bluetooth-power.c
+++ b/drivers/bluetooth/bluetooth-power.c
@@ -666,7 +666,7 @@
bluetooth_power_rfkill_remove(pdev);
- if (bt_power_pdata->bt_chip_pwd->reg)
+ if (bt_power_pdata->bt_chip_pwd)
regulator_put(bt_power_pdata->bt_chip_pwd->reg);
kfree(bt_power_pdata);
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index d52c80c..6aa60b1 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -1179,8 +1179,6 @@
hlist_del_init(&ctx->hn);
hlist_add_head(&ctx->hn, &clst->interrupted);
spin_unlock(&ctx->fl->hlock);
- /* free the cache on power collapse */
- fastrpc_buf_list_free(ctx->fl);
}
static void context_free(struct smq_invoke_ctx *ctx)
@@ -3514,8 +3512,16 @@
pdr->domain_list[i].name,
pdr->domain_list[i].instance_id,
&spd->pdrnb, &curr_state);
- if (IS_ERR(spd->pdrhandle))
+ if (IS_ERR(spd->pdrhandle)) {
pr_err("ADSPRPC: Unable to register notifier\n");
+ } else if (curr_state ==
+ SERVREG_NOTIF_SERVICE_STATE_UP_V01) {
+ pr_info("ADSPRPC: STATE_UP_V01 received\n");
+ spd->ispdup = 1;
+ } else if (curr_state ==
+ SERVREG_NOTIF_SERVICE_STATE_UNINIT_V01) {
+ pr_info("ADSPRPC: STATE_UNINIT_V01 received\n");
+ }
break;
}
}
diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c
index c20dd2e..44cf56c 100644
--- a/drivers/char/diag/diag_masks.c
+++ b/drivers/char/diag/diag_masks.c
@@ -195,10 +195,11 @@
}
mask_info->update_buf = temp;
mask_info->update_buf_len = header_len + mask_size;
+ buf = temp;
}
memcpy(buf, &ctrl_pkt, header_len);
- if (mask_size > 0)
+ if (mask_size > 0 && mask_size <= LOG_MASK_SIZE)
memcpy(buf + header_len, mask->ptr, mask_size);
mutex_unlock(&mask->lock);
@@ -297,9 +298,16 @@
} else {
mask_info->update_buf = temp;
mask_info->update_buf_len = temp_len;
+ buf = temp;
}
}
- memcpy(buf + sizeof(header), mask_info->ptr, num_bytes);
+ if (num_bytes > 0 && num_bytes < mask_info->mask_len)
+ memcpy(buf + sizeof(header), mask_info->ptr, num_bytes);
+ else {
+ pr_err("diag: num_bytes(%d) is not satisfying length condition\n",
+ num_bytes);
+ goto err;
+ }
write_len += num_bytes;
break;
default:
@@ -415,6 +423,7 @@
} else {
mask_info->update_buf = temp;
mask_info->update_buf_len = temp_len;
+ buf = temp;
pr_debug("diag: In %s, successfully reallocated msg_mask update buffer to len: %d\n",
__func__, mask_info->update_buf_len);
}
@@ -922,10 +931,12 @@
mask_info->status = (req->rt_mask) ? DIAG_CTRL_MASK_ALL_ENABLED :
DIAG_CTRL_MASK_ALL_DISABLED;
for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) {
- mutex_lock(&mask->lock);
- memset(mask->ptr, req->rt_mask,
- mask->range * sizeof(uint32_t));
- mutex_unlock(&mask->lock);
+ if (mask && mask->ptr) {
+ mutex_lock(&mask->lock);
+ memset(mask->ptr, req->rt_mask,
+ mask->range * sizeof(uint32_t));
+ mutex_unlock(&mask->lock);
+ }
}
mutex_unlock(&driver->msg_mask_lock);
mutex_unlock(&mask_info->lock);
@@ -1337,6 +1348,8 @@
mutex_lock(&mask_info->lock);
for (i = 0; i < MAX_EQUIP_ID && !status; i++, mask++) {
+ if (!mask || !mask->ptr)
+ continue;
if (mask->equip_id != req->equip_id)
continue;
mutex_lock(&mask->lock);
@@ -1464,9 +1477,11 @@
return -EINVAL;
}
for (i = 0; i < MAX_EQUIP_ID; i++, mask++) {
- mutex_lock(&mask->lock);
- memset(mask->ptr, 0, mask->range);
- mutex_unlock(&mask->lock);
+ if (mask && mask->ptr) {
+ mutex_lock(&mask->lock);
+ memset(mask->ptr, 0, mask->range);
+ mutex_unlock(&mask->lock);
+ }
}
mask_info->status = DIAG_CTRL_MASK_ALL_DISABLED;
mutex_unlock(&driver->md_session_lock);
diff --git a/drivers/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c
index 6f81bfd..ac4394b 100644
--- a/drivers/char/diag/diagfwd_cntl.c
+++ b/drivers/char/diag/diagfwd_cntl.c
@@ -528,9 +528,8 @@
header = (struct diag_ctrl_last_event_report *)ptr;
event_size = ((header->event_last_id / 8) + 1);
if (event_size >= driver->event_mask_size) {
- DIAG_LOG(DIAG_DEBUG_CONTROL,
- "diag: In %s, receiving event mask size more that Apps can handle\n",
- __func__);
+ DIAG_LOG(DIAG_DEBUG_MASKS,
+ "diag: receiving event mask size more that Apps can handle\n");
temp = krealloc(driver->event_mask->ptr, event_size,
GFP_KERNEL);
if (!temp) {
@@ -669,6 +668,10 @@
mask_ptr = (struct diag_msg_mask_t *)msg_mask.ptr;
found = 0;
for (j = 0; j < driver->msg_mask_tbl_count; j++, mask_ptr++) {
+ if (!mask_ptr || !ssid_range) {
+ found = 1;
+ break;
+ }
if (mask_ptr->ssid_first != ssid_range->ssid_first)
continue;
mutex_lock(&mask_ptr->lock);
@@ -687,6 +690,8 @@
new_size = (driver->msg_mask_tbl_count + 1) *
sizeof(struct diag_msg_mask_t);
+ DIAG_LOG(DIAG_DEBUG_MASKS,
+ "diag: receiving msg mask size more that Apps can handle\n");
temp = krealloc(msg_mask.ptr, new_size, GFP_KERNEL);
if (!temp) {
pr_err("diag: In %s, Unable to add new ssid table to msg mask, ssid first: %d, last: %d\n",
@@ -695,6 +700,7 @@
continue;
}
msg_mask.ptr = temp;
+ mask_ptr = (struct diag_msg_mask_t *)msg_mask.ptr;
err = diag_create_msg_mask_table_entry(mask_ptr, ssid_range);
if (err) {
pr_err("diag: In %s, Unable to create a new msg mask table entry, first: %d last: %d err: %d\n",
@@ -741,6 +747,10 @@
num_items = range->ssid_last - range->ssid_first + 1;
for (i = 0; i < driver->bt_msg_mask_tbl_count; i++, build_mask++) {
+ if (!build_mask) {
+ found = 1;
+ break;
+ }
if (build_mask->ssid_first != range->ssid_first)
continue;
found = 1;
@@ -751,7 +761,8 @@
__func__);
}
dest_ptr = build_mask->ptr;
- for (j = 0; j < build_mask->range; j++, mask_ptr++, dest_ptr++)
+ for (j = 0; (j < build_mask->range) && mask_ptr && dest_ptr;
+ j++, mask_ptr++, dest_ptr++)
*(uint32_t *)dest_ptr |= *mask_ptr;
mutex_unlock(&build_mask->lock);
break;
@@ -759,8 +770,12 @@
if (found)
goto end;
+
new_size = (driver->bt_msg_mask_tbl_count + 1) *
sizeof(struct diag_msg_mask_t);
+ DIAG_LOG(DIAG_DEBUG_MASKS,
+ "diag: receiving build time mask size more that Apps can handle\n");
+
temp = krealloc(driver->build_time_mask->ptr, new_size, GFP_KERNEL);
if (!temp) {
pr_err("diag: In %s, unable to create a new entry for build time mask\n",
@@ -768,6 +783,7 @@
goto end;
}
driver->build_time_mask->ptr = temp;
+ build_mask = (struct diag_msg_mask_t *)driver->build_time_mask->ptr;
err = diag_create_msg_mask_table_entry(build_mask, range);
if (err) {
pr_err("diag: In %s, Unable to create a new msg mask table entry, err: %d\n",
diff --git a/drivers/clk/msm/clock-gcc-8952.c b/drivers/clk/msm/clock-gcc-8952.c
index d471138..47619f5 100644
--- a/drivers/clk/msm/clock-gcc-8952.c
+++ b/drivers/clk/msm/clock-gcc-8952.c
@@ -4505,6 +4505,7 @@
vdd_hf_pll.num_levels = VDD_HF_PLL_NUM_439;
vdd_hf_pll.cur_level = VDD_HF_PLL_NUM_439;
+ gpll3_clk_src.test_ctl_hi_val = 0x400000;
gpll3_clk_src.vco_tbl = p_vco;
gpll3_clk_src.num_vco = ARRAY_SIZE(p_vco);
gpll3_clk_src.c.fmax[VDD_DIG_LOW] = 800000000;
diff --git a/drivers/clk/qcom/gcc-sdxpoorwills.c b/drivers/clk/qcom/gcc-sdxpoorwills.c
index b52002f..a27bd19 100644
--- a/drivers/clk/qcom/gcc-sdxpoorwills.c
+++ b/drivers/clk/qcom/gcc-sdxpoorwills.c
@@ -143,11 +143,6 @@
.parent_names = (const char *[]){ "bi_tcxo" },
.num_parents = 1,
.ops = &clk_trion_fixed_pll_ops,
- VDD_CX_FMAX_MAP4(
- MIN, 615000000,
- LOW, 1066000000,
- LOW_L1, 1600000000,
- NOMINAL, 2000000000),
},
},
};
@@ -757,7 +752,7 @@
static const struct freq_tbl ftbl_gcc_usb30_master_clk_src[] = {
F(50000000, P_GPLL0_OUT_EVEN, 6, 0, 0),
F(75000000, P_GPLL0_OUT_EVEN, 4, 0, 0),
- F(100000000, P_GPLL0_OUT_MAIN, 6, 0, 0),
+ F(120000000, P_GPLL0_OUT_MAIN, 5, 0, 0),
F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0),
F(240000000, P_GPLL0_OUT_MAIN, 2.5, 0, 0),
{ }
@@ -777,7 +772,7 @@
VDD_CX_FMAX_MAP5(
MIN, 50000000,
LOWER, 75000000,
- LOW, 100000000,
+ LOW, 120000000,
NOMINAL, 200000000,
HIGH, 240000000),
},
diff --git a/drivers/clk/qcom/gdsc-regulator.c b/drivers/clk/qcom/gdsc-regulator.c
index 0899138..0d7ed80 100644
--- a/drivers/clk/qcom/gdsc-regulator.c
+++ b/drivers/clk/qcom/gdsc-regulator.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018, 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
@@ -34,6 +34,10 @@
#define PWR_ON_MASK BIT(31)
#define CLK_DIS_WAIT_MASK (0xF << 12)
#define CLK_DIS_WAIT_SHIFT (12)
+#define EN_FEW_WAIT_MASK (0xF << 16)
+#define EN_FEW_WAIT_SHIFT (16)
+#define EN_REST_WAIT_MASK (0xF << 20)
+#define EN_REST_WAIT_SHIFT (20)
#define SW_OVERRIDE_MASK BIT(2)
#define HW_CONTROL_MASK BIT(1)
#define SW_COLLAPSE_MASK BIT(0)
@@ -535,6 +539,7 @@
struct resource *res;
struct gdsc *sc;
uint32_t regval, clk_dis_wait_val = 0;
+ uint32_t en_few_wait_val, en_rest_wait_val;
bool retain_mem, retain_periph, support_hw_trigger, prop_val;
int i, ret;
u32 timeout;
@@ -681,6 +686,22 @@
regval |= clk_dis_wait_val;
}
+ if (!of_property_read_u32(pdev->dev.of_node, "qcom,en-few-wait-val",
+ &en_few_wait_val)) {
+ en_few_wait_val <<= EN_FEW_WAIT_SHIFT;
+
+ regval &= ~(EN_FEW_WAIT_MASK);
+ regval |= en_few_wait_val;
+ }
+
+ if (!of_property_read_u32(pdev->dev.of_node, "qcom,en-rest-wait-val",
+ &en_rest_wait_val)) {
+ en_rest_wait_val <<= EN_REST_WAIT_SHIFT;
+
+ regval &= ~(EN_REST_WAIT_MASK);
+ regval |= en_rest_wait_val;
+ }
+
regmap_write(sc->regmap, REG_OFFSET, regval);
sc->no_status_check_on_disable =
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index b55205b..f474e70 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1506,6 +1506,9 @@
policy->freq_table = NULL;
}
+ blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
+ CPUFREQ_STOP, policy);
+
unlock:
up_write(&policy->rwsem);
return 0;
diff --git a/drivers/cpuidle/lpm-levels-legacy.c b/drivers/cpuidle/lpm-levels-legacy.c
index 006a5ef..26cb52a 100644
--- a/drivers/cpuidle/lpm-levels-legacy.c
+++ b/drivers/cpuidle/lpm-levels-legacy.c
@@ -643,9 +643,11 @@
cpumask_copy(&cpumask, cpumask_of(cpu));
nextcpu = level->disable_dynamic_routing ? NULL : &cpumask;
- if (sys_pm_ops && sys_pm_ops->enter)
- if ((sys_pm_ops->enter(nextcpu)))
- return -EBUSY;
+ if (sys_pm_ops && sys_pm_ops->enter) {
+ ret = sys_pm_ops->enter(nextcpu);
+ if (ret)
+ goto failed_set_mode;
+ }
if (cluster->no_saw_devices && !use_psci)
msm_spm_set_rpm_hs(true);
diff --git a/drivers/cpuidle/lpm-levels-of-legacy.c b/drivers/cpuidle/lpm-levels-of-legacy.c
index bf74124..8782850 100644
--- a/drivers/cpuidle/lpm-levels-of-legacy.c
+++ b/drivers/cpuidle/lpm-levels-of-legacy.c
@@ -863,8 +863,11 @@
continue;
key = "qcom,pm-cluster-level";
if (!of_node_cmp(n->name, key)) {
- if (parse_cluster_level(n, c))
+ if (parse_cluster_level(n, c)) {
+ of_node_put(n);
goto failed_parse_cluster;
+ }
+ of_node_put(n);
continue;
}
@@ -877,14 +880,16 @@
__func__);
child = parse_cluster(n, c);
- if (!child)
+ if (!child) {
+ of_node_put(n);
goto failed_parse_cluster;
+ }
- of_node_put(n);
list_add(&child->list, &c->child);
cpumask_or(&c->child_cpus, &c->child_cpus,
&child->child_cpus);
c->aff_level = child->aff_level + 1;
+ of_node_put(n);
continue;
}
@@ -898,10 +903,13 @@
if (get_cpumask_for_node(node, &c->child_cpus))
goto failed_parse_cluster;
- if (parse_cpu_levels(n, c))
+ if (parse_cpu_levels(n, c)) {
+ of_node_put(n);
goto failed_parse_cluster;
+ }
c->aff_level = 1;
+ of_node_put(n);
for_each_cpu(i, &c->child_cpus) {
per_cpu(max_residency, i) = devm_kzalloc(
diff --git a/drivers/cpuidle/lpm-levels.c b/drivers/cpuidle/lpm-levels.c
index c7ec868..e692f660 100644
--- a/drivers/cpuidle/lpm-levels.c
+++ b/drivers/cpuidle/lpm-levels.c
@@ -1777,6 +1777,7 @@
.driver = {
.name = "lpm-levels",
.owner = THIS_MODULE,
+ .suppress_bind_attrs = true,
.of_match_table = lpm_mtch_tbl,
},
};
diff --git a/drivers/devfreq/devfreq_devbw.c b/drivers/devfreq/devfreq_devbw.c
index 5c7959c..5bc4db4 100644
--- a/drivers/devfreq/devfreq_devbw.c
+++ b/drivers/devfreq/devfreq_devbw.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, 2018, 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
@@ -258,6 +258,7 @@
.driver = {
.name = "devbw",
.of_match_table = devbw_match_table,
+ .suppress_bind_attrs = true,
},
};
diff --git a/drivers/devfreq/devfreq_simple_dev.c b/drivers/devfreq/devfreq_simple_dev.c
index b0757b6..8566e98 100644
--- a/drivers/devfreq/devfreq_simple_dev.c
+++ b/drivers/devfreq/devfreq_simple_dev.c
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2014-2015, 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2015, 2017-2018, 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
@@ -212,6 +213,7 @@
.driver = {
.name = "devfreq-simple-dev",
.of_match_table = devfreq_simple_match_table,
+ .suppress_bind_attrs = true,
},
};
module_platform_driver(devfreq_clock_driver);
diff --git a/drivers/devfreq/governor_cpufreq.c b/drivers/devfreq/governor_cpufreq.c
index 03ec792..3c7fc8b 100644
--- a/drivers/devfreq/governor_cpufreq.c
+++ b/drivers/devfreq/governor_cpufreq.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2015, 2018, 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
@@ -182,14 +182,14 @@
struct cpufreq_policy *policy = data;
switch (event) {
- case CPUFREQ_CREATE_POLICY:
+ case CPUFREQ_START:
mutex_lock(&state_lock);
add_policy(policy);
update_all_devfreqs();
mutex_unlock(&state_lock);
break;
- case CPUFREQ_REMOVE_POLICY:
+ case CPUFREQ_STOP:
mutex_lock(&state_lock);
if (state[policy->cpu]) {
state[policy->cpu]->on = false;
diff --git a/drivers/dma/qcom/gpi.c b/drivers/dma/qcom/gpi.c
index 065b765..fff2ae9 100644
--- a/drivers/dma/qcom/gpi.c
+++ b/drivers/dma/qcom/gpi.c
@@ -2564,22 +2564,6 @@
return arm_iommu_create_mapping(&platform_bus_type, base, size);
}
-static int gpi_dma_mask(struct gpi_dev *gpi_dev)
-{
- int mask = 64;
-
- if (gpi_dev->smmu_cfg && !(gpi_dev->smmu_cfg & GPI_SMMU_S1_BYPASS)) {
- unsigned long addr;
-
- addr = gpi_dev->iova_base + gpi_dev->iova_size + 1;
- mask = find_last_bit(&addr, 64);
- }
-
- GPI_LOG(gpi_dev, "Setting dma mask to %d\n", mask);
-
- return dma_set_mask(gpi_dev->dev, DMA_BIT_MASK(mask));
-}
-
static int gpi_smmu_init(struct gpi_dev *gpi_dev)
{
struct dma_iommu_mapping *mapping = NULL;
@@ -2643,9 +2627,10 @@
}
}
- ret = gpi_dma_mask(gpi_dev);
+ GPI_LOG(gpi_dev, "Setting dma mask to 64\n");
+ ret = dma_set_mask(gpi_dev->dev, DMA_BIT_MASK(64));
if (ret) {
- GPI_ERR(gpi_dev, "Error setting dma_mask, ret:%d\n", ret);
+ GPI_ERR(gpi_dev, "Error setting dma_mask to 64, ret:%d\n", ret);
goto error_set_mask;
}
diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c b/drivers/gpu/drm/msm/dp/dp_debug.c
index 78bea02..359655a 100644
--- a/drivers/gpu/drm/msm/dp/dp_debug.c
+++ b/drivers/gpu/drm/msm/dp/dp_debug.c
@@ -669,7 +669,7 @@
struct sde_connector *c_conn;
struct sde_connector_state *c_state;
struct dp_debug_private *debug = file->private_data;
- char buf[SZ_1K];
+ char buf[SZ_512];
size_t len = 0;
if (!debug)
@@ -683,7 +683,7 @@
c_state = to_sde_connector_state(connector->state);
/* Leave room for termination char */
- len = min_t(size_t, count, SZ_1K - 1);
+ len = min_t(size_t, count, SZ_512 - 1);
if (copy_from_user(buf, user_buff, len))
goto end;
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index 1b92261..d9839e7 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -1488,6 +1488,7 @@
.driver = {
.name = "msm-dp-display",
.of_match_table = dp_dt_match,
+ .suppress_bind_attrs = true,
},
};
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c
index a457070..011e3b8 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c
@@ -69,6 +69,7 @@
ctrl->ops.get_hw_version = dsi_ctrl_hw_cmn_get_hw_version;
ctrl->ops.wait_for_cmd_mode_mdp_idle =
dsi_ctrl_hw_cmn_wait_for_cmd_mode_mdp_idle;
+ ctrl->ops.set_continuous_clk = dsi_ctrl_hw_cmn_set_continuous_clk;
switch (version) {
case DSI_CTRL_VERSION_1_4:
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h
index 9a923aa..c55bbe0 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h
@@ -224,4 +224,6 @@
/* Definitions specific to 2.2 DSI controller hardware */
bool dsi_ctrl_hw_22_get_cont_splash_status(struct dsi_ctrl_hw *ctrl);
+void dsi_ctrl_hw_cmn_set_continuous_clk(struct dsi_ctrl_hw *ctrl, bool enable);
+
#endif /* _DSI_CATALOG_H_ */
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
index 92e08e0..31c3b1a 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
@@ -1239,9 +1239,10 @@
}
}
- if (dsi_ctrl->hw.ops.mask_error_intr)
+ if (dsi_ctrl->hw.ops.mask_error_intr &&
+ !dsi_ctrl->esd_check_underway)
dsi_ctrl->hw.ops.mask_error_intr(&dsi_ctrl->hw,
- BIT(DSI_FIFO_OVERFLOW), false);
+ BIT(DSI_FIFO_OVERFLOW), false);
dsi_ctrl->hw.ops.reset_cmd_fifo(&dsi_ctrl->hw);
/*
@@ -1272,6 +1273,7 @@
.type = MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE,
.tx_len = 2,
.tx_buf = tx,
+ .flags = rx_msg->flags,
};
rc = dsi_message_tx(dsi_ctrl, &msg, flags);
@@ -1797,6 +1799,7 @@
.driver = {
.name = "drm_dsi_ctrl",
.of_match_table = msm_dsi_of_match,
+ .suppress_bind_attrs = true,
},
};
@@ -2601,6 +2604,16 @@
mutex_unlock(&dsi_ctrl->ctrl_lock);
}
+void dsi_ctrl_set_continuous_clk(struct dsi_ctrl *dsi_ctrl, bool enable)
+{
+ if (!dsi_ctrl)
+ return;
+
+ mutex_lock(&dsi_ctrl->ctrl_lock);
+ dsi_ctrl->hw.ops.set_continuous_clk(&dsi_ctrl->hw, enable);
+ mutex_unlock(&dsi_ctrl->ctrl_lock);
+}
+
int dsi_ctrl_soft_reset(struct dsi_ctrl *dsi_ctrl)
{
if (!dsi_ctrl)
@@ -2886,7 +2899,8 @@
dsi_ctrl->cell_index);
}
}
- if (dsi_ctrl->hw.ops.mask_error_intr)
+ if (dsi_ctrl->hw.ops.mask_error_intr &&
+ !dsi_ctrl->esd_check_underway)
dsi_ctrl->hw.ops.mask_error_intr(&dsi_ctrl->hw,
BIT(DSI_FIFO_OVERFLOW), false);
@@ -3384,7 +3398,8 @@
return misr;
}
-void dsi_ctrl_mask_error_status_interrupts(struct dsi_ctrl *dsi_ctrl)
+void dsi_ctrl_mask_error_status_interrupts(struct dsi_ctrl *dsi_ctrl, u32 idx,
+ bool mask_enable)
{
if (!dsi_ctrl || !dsi_ctrl->hw.ops.error_intr_ctrl
|| !dsi_ctrl->hw.ops.clear_error_status) {
@@ -3397,9 +3412,23 @@
* register
*/
mutex_lock(&dsi_ctrl->ctrl_lock);
- dsi_ctrl->hw.ops.error_intr_ctrl(&dsi_ctrl->hw, false);
- dsi_ctrl->hw.ops.clear_error_status(&dsi_ctrl->hw,
+ if (idx & BIT(DSI_ERR_INTR_ALL)) {
+ /*
+ * The behavior of mask_enable is different in ctrl register
+ * and mask register and hence mask_enable is manipulated for
+ * selective error interrupt masking vs total error interrupt
+ * masking.
+ */
+
+ dsi_ctrl->hw.ops.error_intr_ctrl(&dsi_ctrl->hw, !mask_enable);
+ dsi_ctrl->hw.ops.clear_error_status(&dsi_ctrl->hw,
DSI_ERROR_INTERRUPT_COUNT);
+ } else {
+ dsi_ctrl->hw.ops.mask_error_intr(&dsi_ctrl->hw, idx,
+ mask_enable);
+ dsi_ctrl->hw.ops.clear_error_status(&dsi_ctrl->hw,
+ DSI_ERROR_INTERRUPT_COUNT);
+ }
mutex_unlock(&dsi_ctrl->ctrl_lock);
}
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h
index 6ac7dd7..61c6116 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h
@@ -221,6 +221,7 @@
* @cmd_buffer_size: Size of command buffer.
* @vaddr: CPU virtual address of cmd buffer.
* @secure_mode: Indicates if secure-session is in progress
+ * @esd_check_underway: Indicates if esd status check is in progress
* @debugfs_root: Root for debugfs entries.
* @misr_enable: Frame MISR enable/disable
* @misr_cache: Cached Frame MISR value
@@ -266,6 +267,7 @@
u32 cmd_len;
void *vaddr;
bool secure_mode;
+ bool esd_check_underway;
/* Debug Information */
struct dentry *debugfs_root;
@@ -743,8 +745,11 @@
* dsi_ctrl_mask_error_status_interrupts() - API to mask dsi ctrl error status
* interrupts
* @dsi_ctrl: DSI controller handle.
+ * @idx: id indicating which interrupts to enable/disable.
+ * @mask_enable: boolean to enable/disable masking.
*/
-void dsi_ctrl_mask_error_status_interrupts(struct dsi_ctrl *dsi_ctrl);
+void dsi_ctrl_mask_error_status_interrupts(struct dsi_ctrl *dsi_ctrl, u32 idx,
+ bool mask_enable);
/**
* dsi_ctrl_irq_update() - Put a irq vote to process DSI error
@@ -772,4 +777,10 @@
*/
int dsi_ctrl_wait_for_cmd_mode_mdp_idle(struct dsi_ctrl *dsi_ctrl);
+/**
+ * dsi_ctrl_set_continuous_clk() - API to set/unset force clock lane HS request.
+ * @dsi_ctrl: DSI controller handle.
+ * @enable: variable to control continuous clock.
+ */
+void dsi_ctrl_set_continuous_clk(struct dsi_ctrl *dsi_ctrl, bool enable);
#endif /* _DSI_CTRL_H_ */
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h
index 73aab3f..348ef36 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h
@@ -158,7 +158,7 @@
* @DSI_EINT_DLN0_ESC_ENTRY_ERR: Incorrect LP Rx escape entry.
* @DSI_EINT_DLN0_ESC_SYNC_ERR: LP Rx data is not byte aligned.
* @DSI_EINT_DLN0_LP_CONTROL_ERR: Incorrect LP Rx state sequence.
- * @DSI_EINT_PENDING_HS_TX_TIMEOUT: Pending High-speed transfer timeout.
+ * @DSI_EINT_PANEL_SPECIFIC_ERR: DSI Protocol violation error.
* @DSI_EINT_INTERLEAVE_OP_CONTENTION: Interleave operation contention.
* @DSI_EINT_CMD_DMA_FIFO_UNDERFLOW: Command mode DMA FIFO underflow.
* @DSI_EINT_CMD_MDP_FIFO_UNDERFLOW: Command MDP FIFO underflow (failed to
@@ -179,7 +179,6 @@
* @DSI_EINT_DLN1_LP1_CONTENTION: PHY level contention while lane 1 high.
* @DSI_EINT_DLN2_LP1_CONTENTION: PHY level contention while lane 2 high.
* @DSI_EINT_DLN3_LP1_CONTENTION: PHY level contention while lane 3 high.
- * @DSI_EINT_PANEL_SPECIFIC_ERR: DSI Protocol violation error.
*/
enum dsi_error_int_index {
DSI_EINT_RDBK_SINGLE_ECC_ERR = 0,
@@ -194,7 +193,7 @@
DSI_EINT_DLN0_ESC_ENTRY_ERR = 9,
DSI_EINT_DLN0_ESC_SYNC_ERR = 10,
DSI_EINT_DLN0_LP_CONTROL_ERR = 11,
- DSI_EINT_PENDING_HS_TX_TIMEOUT = 12,
+ DSI_EINT_PANEL_SPECIFIC_ERR = 12,
DSI_EINT_INTERLEAVE_OP_CONTENTION = 13,
DSI_EINT_CMD_DMA_FIFO_UNDERFLOW = 14,
DSI_EINT_CMD_MDP_FIFO_UNDERFLOW = 15,
@@ -214,7 +213,6 @@
DSI_EINT_DLN1_LP1_CONTENTION = 29,
DSI_EINT_DLN2_LP1_CONTENTION = 30,
DSI_EINT_DLN3_LP1_CONTENTION = 31,
- DSI_EINT_PANEL_SPECIFIC_ERR = 32,
DSI_ERROR_INTERRUPT_COUNT
};
@@ -233,7 +231,7 @@
* @DSI_DLN0_ESC_ENTRY_ERR: Incorrect LP Rx escape entry.
* @DSI_DLN0_ESC_SYNC_ERR: LP Rx data is not byte aligned.
* @DSI_DLN0_LP_CONTROL_ERR: Incorrect LP Rx state sequence.
- * @DSI_PENDING_HS_TX_TIMEOUT: Pending High-speed transfer timeout.
+ * @DSI_PANEL_SPECIFIC_ERR: DSI Protocol violation.
* @DSI_INTERLEAVE_OP_CONTENTION: Interleave operation contention.
* @DSI_CMD_DMA_FIFO_UNDERFLOW: Command mode DMA FIFO underflow.
* @DSI_CMD_MDP_FIFO_UNDERFLOW: Command MDP FIFO underflow (failed to
@@ -254,7 +252,6 @@
* @DSI_DLN1_LP1_CONTENTION: PHY level contention while lane 1 is high.
* @DSI_DLN2_LP1_CONTENTION: PHY level contention while lane 2 is high.
* @DSI_DLN3_LP1_CONTENTION: PHY level contention while lane 3 is high.
- * @DSI_PANEL_SPECIFIC_ERR: DSI Protocol violation.
*/
enum dsi_error_int_type {
DSI_RDBK_SINGLE_ECC_ERR = BIT(DSI_EINT_RDBK_SINGLE_ECC_ERR),
@@ -269,7 +266,7 @@
DSI_DLN0_ESC_ENTRY_ERR = BIT(DSI_EINT_DLN0_ESC_ENTRY_ERR),
DSI_DLN0_ESC_SYNC_ERR = BIT(DSI_EINT_DLN0_ESC_SYNC_ERR),
DSI_DLN0_LP_CONTROL_ERR = BIT(DSI_EINT_DLN0_LP_CONTROL_ERR),
- DSI_PENDING_HS_TX_TIMEOUT = BIT(DSI_EINT_PENDING_HS_TX_TIMEOUT),
+ DSI_PANEL_SPECIFIC_ERR = BIT(DSI_EINT_PANEL_SPECIFIC_ERR),
DSI_INTERLEAVE_OP_CONTENTION = BIT(DSI_EINT_INTERLEAVE_OP_CONTENTION),
DSI_CMD_DMA_FIFO_UNDERFLOW = BIT(DSI_EINT_CMD_DMA_FIFO_UNDERFLOW),
DSI_CMD_MDP_FIFO_UNDERFLOW = BIT(DSI_EINT_CMD_MDP_FIFO_UNDERFLOW),
@@ -289,7 +286,6 @@
DSI_DLN1_LP1_CONTENTION = BIT(DSI_EINT_DLN1_LP1_CONTENTION),
DSI_DLN2_LP1_CONTENTION = BIT(DSI_EINT_DLN2_LP1_CONTENTION),
DSI_DLN3_LP1_CONTENTION = BIT(DSI_EINT_DLN3_LP1_CONTENTION),
- DSI_PANEL_SPECIFIC_ERR = BIT(DSI_EINT_PANEL_SPECIFIC_ERR),
};
/**
@@ -807,6 +803,13 @@
* @ctrl: Pointer to the controller host hardware.
*/
int (*wait_for_cmd_mode_mdp_idle)(struct dsi_ctrl_hw *ctrl);
+
+ /**
+ * hw.ops.set_continuous_clk() - Set continuous clock
+ * @ctrl: Pointer to the controller host hardware.
+ * @enable: Bool to control continuous clock request.
+ */
+ void (*set_continuous_clk)(struct dsi_ctrl_hw *ctrl, bool enable);
};
/*
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c
index 6dde454..7c58c43 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c
@@ -1420,17 +1420,20 @@
reg = DSI_R32(ctrl, 0x10c);
if (idx & BIT(DSI_FIFO_OVERFLOW)) {
- if (en)
- reg |= (0xf << 16);
- else
- reg &= ~(0xf << 16);
+ if (en) {
+ reg |= (0x1f << 16);
+ reg |= BIT(9);
+ } else {
+ reg &= ~(0x1f << 16);
+ reg &= ~BIT(9);
+ }
}
if (idx & BIT(DSI_FIFO_UNDERFLOW)) {
if (en)
- reg |= (0xf << 26);
+ reg |= (0x1b << 26);
else
- reg &= ~(0xf << 26);
+ reg &= ~(0x1b << 26);
}
if (idx & BIT(DSI_LP_Rx_TIMEOUT)) {
@@ -1493,3 +1496,16 @@
return rc;
}
+
+void dsi_ctrl_hw_cmn_set_continuous_clk(struct dsi_ctrl_hw *ctrl, bool enable)
+{
+ u32 reg = 0;
+
+ reg = DSI_R32(ctrl, DSI_LANE_CTRL);
+ if (enable)
+ reg |= BIT(28);
+ else
+ reg &= ~BIT(28);
+ DSI_W32(ctrl, DSI_LANE_CTRL, reg);
+ wmb(); /* make sure request is set */
+}
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h b/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h
index 6540182..3b2ef70 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h
@@ -404,6 +404,7 @@
* @ignore_rx_eot: Ignore Rx EOT packets if set to true.
* @append_tx_eot: Append EOT packets for forward transmissions if set to
* true.
+ * @force_hs_clk_lane: Send continuous clock to the panel.
*/
struct dsi_host_common_cfg {
enum dsi_pixel_format dst_format;
@@ -422,6 +423,7 @@
u32 t_clk_pre;
bool ignore_rx_eot;
bool append_tx_eot;
+ bool force_hs_clk_lane;
};
/**
@@ -598,6 +600,7 @@
DSI_FIFO_OVERFLOW = 1,
DSI_FIFO_UNDERFLOW,
DSI_LP_Rx_TIMEOUT,
+ DSI_ERR_INTR_ALL,
};
#endif /* _DSI_DEFS_H_ */
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
index f0311fd..d58a746 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
@@ -48,15 +48,19 @@
static char dsi_display_primary[MAX_CMDLINE_PARAM_LEN];
static char dsi_display_secondary[MAX_CMDLINE_PARAM_LEN];
static struct dsi_display_boot_param boot_displays[MAX_DSI_ACTIVE_DISPLAY];
-static struct device_node *default_active_node;
+static struct device_node *primary_active_node;
+static struct device_node *secondary_active_node;
+
static const struct of_device_id dsi_display_dt_match[] = {
{.compatible = "qcom,dsi-display"},
{}
};
-static struct dsi_display *main_display;
+static struct dsi_display *primary_display;
+static struct dsi_display *secondary_display;
-static void dsi_display_mask_ctrl_error_interrupts(struct dsi_display *display)
+static void dsi_display_mask_ctrl_error_interrupts(struct dsi_display *display,
+ u32 mask, bool enable)
{
int i;
struct dsi_display_ctrl *ctrl;
@@ -69,7 +73,25 @@
ctrl = &display->ctrl[i];
if (!ctrl)
continue;
- dsi_ctrl_mask_error_status_interrupts(ctrl->ctrl);
+ dsi_ctrl_mask_error_status_interrupts(ctrl->ctrl, mask, enable);
+ }
+}
+
+static void dsi_display_set_ctrl_esd_check_flag(struct dsi_display *display,
+ bool enable)
+{
+ int i;
+ struct dsi_display_ctrl *ctrl;
+
+ if (!display)
+ return;
+
+ for (i = 0; (i < display->ctrl_count) &&
+ (i < MAX_DSI_CTRLS_PER_DISPLAY); i++) {
+ ctrl = &display->ctrl[i];
+ if (!ctrl)
+ continue;
+ ctrl->ctrl->esd_check_underway = enable;
}
}
@@ -668,10 +690,6 @@
}
}
exit:
- /* mask only error interrupts */
- if (rc <= 0)
- dsi_display_mask_ctrl_error_interrupts(display);
-
dsi_display_cmd_engine_disable(display);
done:
return rc;
@@ -712,6 +730,7 @@
struct dsi_panel *panel;
u32 status_mode;
int rc = 0x1;
+ u32 mask;
if (!dsi_display || !dsi_display->panel)
return -EINVAL;
@@ -727,6 +746,12 @@
}
SDE_EVT32(SDE_EVTLOG_FUNC_ENTRY);
+ /* Prevent another ESD check,when ESD recovery is underway */
+ if (atomic_read(&panel->esd_recovery_pending)) {
+ dsi_panel_release_panel_lock(panel);
+ return rc;
+ }
+
if (te_check_override && gpio_is_valid(dsi_display->disp_te_gpio))
status_mode = ESD_MODE_PANEL_TE;
else
@@ -735,6 +760,11 @@
dsi_display_clk_ctrl(dsi_display->dsi_clk_handle,
DSI_ALL_CLKS, DSI_CLK_ON);
+ /* Mask error interrupts before attempting ESD read */
+ mask = BIT(DSI_FIFO_OVERFLOW) | BIT(DSI_FIFO_UNDERFLOW);
+ dsi_display_set_ctrl_esd_check_flag(dsi_display, true);
+ dsi_display_mask_ctrl_error_interrupts(dsi_display, mask, true);
+
if (status_mode == ESD_MODE_REG_READ) {
rc = dsi_display_status_reg_read(dsi_display);
} else if (status_mode == ESD_MODE_SW_BTA) {
@@ -746,6 +776,16 @@
panel->esd_config.esd_enabled = false;
}
+ /* Unmask error interrupts */
+ if (rc > 0) {
+ dsi_display_set_ctrl_esd_check_flag(dsi_display, false);
+ dsi_display_mask_ctrl_error_interrupts(dsi_display, mask,
+ false);
+ } else {
+ /* Handle Panel failures during display disable sequence */
+ atomic_set(&panel->esd_recovery_pending, 1);
+ }
+
dsi_display_clk_ctrl(dsi_display->dsi_clk_handle,
DSI_ALL_CLKS, DSI_CLK_OFF);
dsi_panel_release_panel_lock(panel);
@@ -769,8 +809,8 @@
cmd->msg.tx_len = ((cmd_buf[5] << 8) | (cmd_buf[6]));
if (cmd->msg.tx_len > payload_len) {
- pr_err("Incorrect payload length tx_len %ld, payload_len %d\n",
- cmd->msg.tx_len, payload_len);
+ pr_err("Incorrect payload length tx_len %zu, payload_len %d\n",
+ cmd->msg.tx_len, payload_len);
return -EINVAL;
}
@@ -835,6 +875,21 @@
return rc;
}
+static void _dsi_display_continuous_clk_ctrl(struct dsi_display *display,
+ bool enable)
+{
+ int i;
+ struct dsi_display_ctrl *ctrl;
+
+ if (!display || !display->panel->host_config.force_hs_clk_lane)
+ return;
+
+ for (i = 0; i < display->ctrl_count; i++) {
+ ctrl = &display->ctrl[i];
+ dsi_ctrl_set_continuous_clk(ctrl->ctrl, enable);
+ }
+}
+
int dsi_display_soft_reset(void *display)
{
struct dsi_display *dsi_display;
@@ -2019,11 +2074,9 @@
boot_displays[i].name[j] = *(disp_buf + j);
boot_displays[i].name[j] = '\0';
- if (i == DSI_PRIMARY) {
+ if (i == DSI_PRIMARY)
boot_displays[i].is_primary = true;
- /* Currently, secondary DSI display is not supported */
- boot_displays[i].boot_disp_en = true;
- }
+ boot_displays[i].boot_disp_en = true;
}
return 0;
}
@@ -2046,6 +2099,8 @@
for (i = 0; i < MAX_DSI_ACTIVE_DISPLAY; i++) {
node = boot_displays[i].node;
+ if (!node)
+ continue;
ctrl_count = of_count_phandle_with_args(node, "qcom,dsi-ctrl",
NULL);
@@ -2087,11 +2142,12 @@
pr_err("index = %d\n", index);
- if (boot_displays[index].node)
- return boot_displays[index].node;
- else if ((index == (MAX_DSI_ACTIVE_DISPLAY - 1))
- && (default_active_node))
- return default_active_node;
+ if ((index == DSI_PRIMARY)
+ && (primary_active_node))
+ return primary_active_node;
+ else if ((index == DSI_SECONDARY)
+ && (secondary_active_node))
+ return secondary_active_node;
else
return NULL;
}
@@ -2734,7 +2790,7 @@
static ssize_t dsi_host_transfer(struct mipi_dsi_host *host,
const struct mipi_dsi_msg *msg)
{
- struct dsi_display *display = to_dsi_display(host);
+ struct dsi_display *display;
int rc = 0, ret = 0;
if (!host || !msg) {
@@ -2742,6 +2798,14 @@
return 0;
}
+ display = to_dsi_display(host);
+
+ /* Avoid sending DCS commands when ESD recovery is pending */
+ if (atomic_read(&display->panel->esd_recovery_pending)) {
+ pr_debug("ESD recovery pending\n");
+ return 0;
+ }
+
rc = dsi_display_clk_ctrl(display->dsi_clk_handle,
DSI_ALL_CLKS, DSI_CLK_ON);
if (rc) {
@@ -3040,6 +3104,12 @@
if ((clk & DSI_LINK_CLK) && (new_state == DSI_CLK_OFF) &&
(l_type && DSI_LINK_LP_CLK)) {
/*
+ * If continuous clock is enabled then disable it
+ * before entering into ULPS Mode.
+ */
+ if (display->panel->host_config.force_hs_clk_lane)
+ _dsi_display_continuous_clk_ctrl(display, false);
+ /*
* If ULPS feature is enabled, enter ULPS first.
* However, when blanking the panel, we should enter ULPS
* only if ULPS during suspend feature is enabled.
@@ -3170,6 +3240,9 @@
goto error;
}
}
+
+ if (display->panel->host_config.force_hs_clk_lane)
+ _dsi_display_continuous_clk_ctrl(display, true);
}
/* enable dsi to serve irqs */
@@ -4641,6 +4714,7 @@
.driver = {
.name = "msm-dsi-display",
.of_match_table = dsi_display_dt_match,
+ .suppress_bind_attrs = true,
},
};
@@ -4648,8 +4722,7 @@
{
int rc = 0;
struct dsi_display *display;
- static bool display_from_cmdline, boot_displays_parsed;
- static bool comp_add_success;
+ static bool boot_displays_parsed;
static struct device_node *primary_np, *secondary_np;
if (!pdev || !pdev->dev.of_node) {
@@ -4678,55 +4751,53 @@
display->cmdline_topology = NO_OVERRIDE;
display->cmdline_timing = 0;
- if ((!display_from_cmdline) &&
- (boot_displays[DSI_PRIMARY].boot_disp_en)) {
- display->is_active = dsi_display_name_compare(pdev->dev.of_node,
- display->name, DSI_PRIMARY);
- if (display->is_active) {
- if (comp_add_success) {
- (void)_dsi_display_dev_deinit(main_display);
- component_del(&main_display->pdev->dev,
- &dsi_display_comp_ops);
- mutex_lock(&dsi_display_list_lock);
- list_del(&main_display->list);
- mutex_unlock(&dsi_display_list_lock);
- comp_add_success = false;
- default_active_node = NULL;
- pr_debug("removed the existing comp ops\n");
- }
- /*
- * Need to add component for
- * the secondary DSI display
- * when more than one DSI display
- * is supported.
- */
- pr_debug("cmdline primary dsi: %s\n",
- display->name);
- display_from_cmdline = true;
- dsi_display_parse_cmdline_topology(display,
- DSI_PRIMARY);
- primary_np = pdev->dev.of_node;
+ if (boot_displays[DSI_PRIMARY].boot_disp_en && !primary_np &&
+ dsi_display_name_compare(pdev->dev.of_node,
+ display->name, DSI_PRIMARY)) {
+ if (primary_display) {
+ (void)_dsi_display_dev_deinit(primary_display);
+ component_del(&primary_display->pdev->dev,
+ &dsi_display_comp_ops);
+ mutex_lock(&dsi_display_list_lock);
+ list_del(&primary_display->list);
+ mutex_unlock(&dsi_display_list_lock);
+ primary_active_node = NULL;
+ pr_debug("removed the existing comp ops\n");
}
+ /*
+ * Need to add component for
+ * the secondary DSI display
+ * when more than one DSI display
+ * is supported.
+ */
+ pr_debug("cmdline primary dsi: %s\n", display->name);
+ display->is_active = true;
+ dsi_display_parse_cmdline_topology(display, DSI_PRIMARY);
+ primary_np = pdev->dev.of_node;
}
- if (boot_displays[DSI_SECONDARY].boot_disp_en) {
- if (!secondary_np) {
- if (dsi_display_name_compare(pdev->dev.of_node,
- display->name, DSI_SECONDARY)) {
- pr_debug("cmdline secondary dsi: %s\n",
- display->name);
- secondary_np = pdev->dev.of_node;
- if (primary_np) {
- if (validate_dsi_display_selection()) {
- display->is_active = true;
- dsi_display_parse_cmdline_topology
- (display, DSI_SECONDARY);
- } else {
- boot_displays[DSI_SECONDARY]
- .boot_disp_en = false;
- }
- }
+ if (boot_displays[DSI_SECONDARY].boot_disp_en && !secondary_np &&
+ dsi_display_name_compare(pdev->dev.of_node,
+ display->name, DSI_SECONDARY)) {
+ pr_debug("cmdline secondary dsi: %s\n", display->name);
+ if (validate_dsi_display_selection()) {
+ if (secondary_display) {
+ (void)_dsi_display_dev_deinit(
+ secondary_display);
+ component_del(&secondary_display->pdev->dev,
+ &dsi_display_comp_ops);
+ mutex_lock(&dsi_display_list_lock);
+ list_del(&secondary_display->list);
+ mutex_unlock(&dsi_display_list_lock);
+ secondary_active_node = NULL;
+ pr_debug("removed the existing comp ops\n");
}
+ display->is_active = true;
+ dsi_display_parse_cmdline_topology(display,
+ DSI_SECONDARY);
+ secondary_np = pdev->dev.of_node;
+ } else {
+ boot_displays[DSI_SECONDARY].boot_disp_en = false;
}
}
display->display_type = of_get_property(pdev->dev.of_node,
@@ -4741,12 +4812,18 @@
list_add(&display->list, &dsi_display_list);
mutex_unlock(&dsi_display_list_lock);
- if (!display_from_cmdline)
+ if (!strcmp(display->display_type, "primary") && !primary_np)
+ display->is_active = of_property_read_bool(pdev->dev.of_node,
+ "qcom,dsi-display-active");
+ else if (strcmp(display->display_type, "primary") && !secondary_np)
display->is_active = of_property_read_bool(pdev->dev.of_node,
"qcom,dsi-display-active");
if (display->is_active) {
- main_display = display;
+ if (!strcmp(display->display_type, "primary"))
+ primary_display = display;
+ else
+ secondary_display = display;
rc = _dsi_display_dev_init(display);
if (rc) {
pr_err("device init failed, rc=%d\n", rc);
@@ -4757,10 +4834,11 @@
if (rc)
pr_err("component add failed, rc=%d\n", rc);
- comp_add_success = true;
pr_debug("Component_add success: %s\n", display->name);
- if (!display_from_cmdline)
- default_active_node = pdev->dev.of_node;
+ if (!strcmp(display->display_type, "primary"))
+ primary_active_node = pdev->dev.of_node;
+ else
+ secondary_active_node = pdev->dev.of_node;
}
return rc;
}
@@ -5844,6 +5922,8 @@
mode = display->panel->cur_mode;
+ dsi_display_set_ctrl_esd_check_flag(display, false);
+
if (mode->dsi_mode_flags & DSI_MODE_FLAG_DMS) {
if (display->is_cont_splash_enabled) {
pr_err("DMS is not supposed to be set on first frame\n");
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
index 6b5bfb4..250314b 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
@@ -139,8 +139,12 @@
return;
}
- if (!c_bridge || !c_bridge->display)
+ if (!c_bridge || !c_bridge->display || !c_bridge->display->panel) {
pr_err("Incorrect bridge details\n");
+ return;
+ }
+
+ atomic_set(&c_bridge->display->panel->esd_recovery_pending, 0);
/* By this point mode should have been validated through mode_fixup */
rc = dsi_display_set_mode(c_bridge->display,
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
index dab85f4..1880ad1 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
@@ -377,7 +377,7 @@
if (r_config->sequence[i].sleep_ms)
usleep_range(r_config->sequence[i].sleep_ms * 1000,
- r_config->sequence[i].sleep_ms * 1000);
+ (r_config->sequence[i].sleep_ms * 1000) + 100);
}
if (gpio_is_valid(panel->bl_config.en_gpio)) {
@@ -1076,6 +1076,8 @@
host->append_tx_eot = of_property_read_bool(of_node,
"qcom,mdss-dsi-tx-eot-append");
+ host->force_hs_clk_lane = of_property_read_bool(of_node,
+ "qcom,mdss-dsi-force-clock-lane-hs");
return 0;
}
@@ -3720,11 +3722,14 @@
mutex_lock(&panel->panel_lock);
- rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_OFF);
- if (rc) {
- pr_err("[%s] failed to send DSI_CMD_SET_OFF cmds, rc=%d\n",
- panel->name, rc);
- goto error;
+ /* Avoid sending panel off commands when ESD recovery is underway */
+ if (!atomic_read(&panel->esd_recovery_pending)) {
+ rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_OFF);
+ if (rc) {
+ pr_err("[%s] failed to send DSI_CMD_SET_OFF cmds, rc=%d\n",
+ panel->name, rc);
+ goto error;
+ }
}
panel->panel_initialized = false;
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h
index c0ecb7f..f6a9c60 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h
@@ -180,6 +180,7 @@
bool ulps_enabled;
bool ulps_suspend_enabled;
bool allow_phy_power_off;
+ atomic_t esd_recovery_pending;
bool panel_initialized;
bool te_using_watchdog_timer;
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_calc.c b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_calc.c
index e52a0f2..fdfaa5d 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_calc.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_calc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018, 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
@@ -532,7 +532,7 @@
/* local vars */
int rc = 0;
u32 h_total, v_total;
- u64 inter_num;
+ u32 inter_num;
u32 num_of_lanes = 0;
u32 bpp;
u64 x, y;
@@ -561,7 +561,7 @@
x = mult_frac(v_total * h_total, inter_num, num_of_lanes);
y = rounddown(x, 1);
- clk_params.bitclk_mbps = rounddown(mult_frac(y, 1, 1000000), 1);
+ clk_params.bitclk_mbps = rounddown(DIV_ROUND_UP_ULL(y, 1000000), 1);
clk_params.escclk_numer = esc_clk_mhz;
clk_params.escclk_denom = esc_clk_mmss_cc_prediv;
clk_params.tlpx_numer_ns = tlpx_numer;
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_calc.h b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_calc.h
index bae6d05..86ef6f3 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_calc.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_calc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2018, 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
@@ -105,6 +105,9 @@
struct phy_timing_desc *desc);
};
+#define roundup64(x, y) \
+ ({ u64 _tmp = (x)+(y)-1; do_div(_tmp, y); _tmp * y; })
+
/* DSI PHY timing functions for 14nm */
void dsi_phy_hw_v2_0_get_default_phy_params(struct phy_clk_params *params);
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_v2_0.c b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_v2_0.c
index d3fb091..45f7577 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_v2_0.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_v2_0.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018, 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
@@ -31,7 +31,7 @@
s64 rec_temp2, rec_temp3;
rec_temp2 = (rec_temp1 - (11 * mult));
- rec_temp3 = roundup(div_s64(rec_temp2, 8), mult);
+ rec_temp3 = roundup64(div_s64(rec_temp2, 8), mult);
return (div_s64(rec_temp3, mult) - 3);
}
@@ -42,7 +42,7 @@
rec_temp1 = temp_mul + frac + (3 * mult);
rec_temp2 = div_s64(rec_temp1, 8);
- rec_temp3 = roundup(rec_temp2, mult);
+ rec_temp3 = roundup64(rec_temp2, mult);
return div_s64(rec_temp3, mult);
}
@@ -62,7 +62,7 @@
s64 rec_temp2, rec_temp3, rec_min;
rec_temp2 = temp1 - (11 * mult);
- rec_temp3 = roundup((rec_temp2 / 8), mult);
+ rec_temp3 = roundup64((rec_temp2 / 8), mult);
rec_min = rec_temp3 - (3 * mult);
return div_s64(rec_min, mult);
}
@@ -80,7 +80,8 @@
rec_temp1 = ((t->mipi_max * clk_params->bitclk_mbps) +
(3 * clk_params->tlpx_numer_ns));
- t->rec_max = (rec_temp1 / (8 * clk_params->tlpx_numer_ns));
+ t->rec_max = DIV_ROUND_UP_ULL(rec_temp1,
+ (8 * clk_params->tlpx_numer_ns));
}
void dsi_phy_hw_v2_0_update_timing_params(
@@ -112,7 +113,7 @@
else
timing->lane[i][4] = desc->hs_rqst.reg_value;
- timing->lane[i][5] = 0x3;
+ timing->lane[i][5] = 0x2;
timing->lane[i][6] = 0x4;
timing->lane[i][7] = 0xA0;
pr_debug("[%d][%d %d %d %d %d]\n", i, timing->lane[i][0],
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_v3_0.c b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_v3_0.c
index c97c87d..c0e9d44 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_v3_0.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_v3_0.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018, 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
@@ -32,7 +32,7 @@
s64 rec_temp2, rec_temp3;
rec_temp2 = (rec_temp1 - mult);
- rec_temp3 = roundup(div_s64(rec_temp2, 8), mult);
+ rec_temp3 = roundup64(div_s64(rec_temp2, 8), mult);
return (div_s64(rec_temp3, mult) - 1);
}
@@ -43,7 +43,7 @@
rec_temp1 = temp_mul + frac;
rec_temp2 = div_s64(rec_temp1, 8);
- rec_temp3 = roundup(rec_temp2, mult);
+ rec_temp3 = roundup64(rec_temp2, mult);
return (div_s64(rec_temp3, mult) - 1);
}
@@ -59,7 +59,7 @@
{
s64 rec_temp2, rec_min;
- rec_temp2 = roundup((temp1 / 8), mult);
+ rec_temp2 = roundup64((temp1 / 8), mult);
rec_min = rec_temp2 - (1 * mult);
return div_s64(rec_min, mult);
}
@@ -92,7 +92,7 @@
timing->lane_v3[6] = desc->hs_prepare.reg_value;
timing->lane_v3[7] = desc->hs_trail.reg_value;
timing->lane_v3[8] = desc->hs_rqst.reg_value;
- timing->lane_v3[9] = 0x03;
+ timing->lane_v3[9] = 0x02;
timing->lane_v3[10] = 0x04;
timing->lane_v3[11] = 0x00;
diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c
index ec572f8..e457322 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.c
+++ b/drivers/gpu/drm/msm/dsi/dsi.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015, 2018 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
@@ -169,6 +169,7 @@
.driver = {
.name = "msm_dsi",
.of_match_table = dt_match,
+ .suppress_bind_attrs = true,
},
};
diff --git a/drivers/gpu/drm/msm/edp/edp.c b/drivers/gpu/drm/msm/edp/edp.c
index 2c9d116..3a0f180 100644
--- a/drivers/gpu/drm/msm/edp/edp.c
+++ b/drivers/gpu/drm/msm/edp/edp.c
@@ -128,6 +128,7 @@
.driver = {
.name = "msm_edp",
.of_match_table = dt_match,
+ .suppress_bind_attrs = true,
},
};
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
index 6279084..b8f5469 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014, 2016, 2018 The Linux Foundation. All rights reserved.
* Copyright (C) 2013 Red Hat
* Author: Rob Clark <robdclark@gmail.com>
*
@@ -646,6 +646,7 @@
.driver = {
.name = "hdmi_msm",
.of_match_table = msm_hdmi_dt_match,
+ .suppress_bind_attrs = true,
},
};
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
index f05d760..46b60b1 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014, 2016-2018 The Linux Foundation. All rights reserved.
* Copyright (C) 2013 Red Hat
* Author: Rob Clark <robdclark@gmail.com>
*
@@ -827,6 +827,7 @@
.driver = {
.name = "msm_mdp",
.of_match_table = mdp5_dt_match,
+ .suppress_bind_attrs = true,
},
};
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 9eb62fe..0f565d3 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -1994,6 +1994,7 @@
.name = "msm_drm",
.of_match_table = dt_match,
.pm = &msm_pm_ops,
+ .suppress_bind_attrs = true,
},
};
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index fcdddb3..978aba2 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -158,6 +158,7 @@
CRTC_PROP_CAPTURE_OUTPUT,
CRTC_PROP_ENABLE_SUI_ENHANCEMENT,
+ CRTC_PROP_IDLE_PC_STATE,
/* total # of properties */
CRTC_PROP_COUNT
diff --git a/drivers/gpu/drm/msm/msm_fb.c b/drivers/gpu/drm/msm/msm_fb.c
index a1c9d82..0c9c13c 100644
--- a/drivers/gpu/drm/msm/msm_fb.c
+++ b/drivers/gpu/drm/msm/msm_fb.c
@@ -151,8 +151,8 @@
}
dma_buf_begin_cpu_access(bo->dma_buf, DMA_BIDIRECTIONAL);
msm_fb->vaddr[i] = dma_buf_kmap(bo->dma_buf, 0);
- DRM_INFO("FB[%u]: vaddr[%d]:%ux%u:0x%llx\n", fb->base.id, i,
- fb->width, fb->height, (u64) msm_fb->vaddr[i]);
+ DRM_INFO("FB[%u]: vaddr[%d]:%ux%u\n", fb->base.id, i,
+ fb->width, fb->height);
}
return 0;
diff --git a/drivers/gpu/drm/msm/msm_smmu.c b/drivers/gpu/drm/msm/msm_smmu.c
index 85867b2..ccd5e20 100644
--- a/drivers/gpu/drm/msm/msm_smmu.c
+++ b/drivers/gpu/drm/msm/msm_smmu.c
@@ -636,6 +636,7 @@
.driver = {
.name = "msmdrm_smmu",
.of_match_table = msm_smmu_dt_match,
+ .suppress_bind_attrs = true,
},
};
diff --git a/drivers/gpu/drm/msm/sde/sde_color_processing.c b/drivers/gpu/drm/msm/sde/sde_color_processing.c
index 47ff024..8680449b 100644
--- a/drivers/gpu/drm/msm/sde/sde_color_processing.c
+++ b/drivers/gpu/drm/msm/sde/sde_color_processing.c
@@ -282,7 +282,8 @@
return 0;
}
- ret = copy_from_user(blob_ptr->data, (void *)val, blob_ptr->length);
+ ret = copy_from_user(blob_ptr->data, u64_to_user_ptr(val),
+ blob_ptr->length);
if (ret) {
DRM_ERROR("failed to get the property info ret %d", ret);
ret = -EFAULT;
@@ -1135,7 +1136,8 @@
if (!sde_crtc->num_mixers ||
sde_crtc->num_mixers > ARRAY_SIZE(sde_crtc->mixers)) {
DRM_INFO("Invalid mixer config act cnt %d max cnt %ld\n",
- sde_crtc->num_mixers, ARRAY_SIZE(sde_crtc->mixers));
+ sde_crtc->num_mixers,
+ (long int)ARRAY_SIZE(sde_crtc->mixers));
ret = -EPERM;
goto exit;
}
@@ -1295,6 +1297,33 @@
/* placeholder for operations needed during resume */
}
+void sde_cp_crtc_clear(struct drm_crtc *crtc)
+{
+ struct sde_crtc *sde_crtc = NULL;
+ unsigned long flags;
+
+ if (!crtc) {
+ DRM_ERROR("crtc %pK\n", crtc);
+ return;
+ }
+ sde_crtc = to_sde_crtc(crtc);
+ if (!sde_crtc) {
+ DRM_ERROR("sde_crtc %pK\n", sde_crtc);
+ return;
+ }
+
+ mutex_lock(&sde_crtc->crtc_cp_lock);
+ list_del_init(&sde_crtc->active_list);
+ list_del_init(&sde_crtc->dirty_list);
+ list_del_init(&sde_crtc->ad_active);
+ list_del_init(&sde_crtc->ad_dirty);
+ mutex_unlock(&sde_crtc->crtc_cp_lock);
+
+ spin_lock_irqsave(&sde_crtc->spin_lock, flags);
+ list_del_init(&sde_crtc->user_event_list);
+ spin_unlock_irqrestore(&sde_crtc->spin_lock, flags);
+}
+
static void dspp_pcc_install_property(struct drm_crtc *crtc)
{
char feature_name[256];
@@ -1990,11 +2019,10 @@
struct sde_crtc *crtc;
struct drm_event event;
struct drm_msm_hist *hist_data;
- struct drm_msm_hist tmp_hist_data;
struct msm_drm_private *priv;
struct sde_kms *kms;
int ret;
- u32 i, j;
+ u32 i;
if (!crtc_drm) {
DRM_ERROR("invalid crtc %pK\n", crtc_drm);
@@ -2026,6 +2054,7 @@
/* read histogram data into blob */
hist_data = (struct drm_msm_hist *)crtc->hist_blob->data;
+ memset(hist_data->data, 0, sizeof(hist_data->data));
for (i = 0; i < crtc->num_mixers; i++) {
hw_dspp = crtc->mixers[i].hw_dspp;
if (!hw_dspp || !hw_dspp->ops.read_histogram) {
@@ -2035,14 +2064,7 @@
kms->core_client, false);
return;
}
- if (!i) {
- hw_dspp->ops.read_histogram(hw_dspp, hist_data);
- } else {
- /* Merge hist data for DSPP0 and DSPP1 */
- hw_dspp->ops.read_histogram(hw_dspp, &tmp_hist_data);
- for (j = 0; j < HIST_V_SIZE; j++)
- hist_data->data[j] += tmp_hist_data.data[j];
- }
+ hw_dspp->ops.read_histogram(hw_dspp, hist_data);
}
sde_power_resource_enable(&priv->phandle, kms->core_client,
diff --git a/drivers/gpu/drm/msm/sde/sde_color_processing.h b/drivers/gpu/drm/msm/sde/sde_color_processing.h
index 620db26..fb8ee1f 100644
--- a/drivers/gpu/drm/msm/sde/sde_color_processing.h
+++ b/drivers/gpu/drm/msm/sde/sde_color_processing.h
@@ -116,6 +116,12 @@
void sde_cp_crtc_resume(struct drm_crtc *crtc);
/**
+ * sde_cp_crtc_clear: Clear the active list and dirty list of crtc features
+ * @crtc: Pointer to crtc.
+ */
+void sde_cp_crtc_clear(struct drm_crtc *crtc);
+
+/**
* sde_cp_ad_interrupt: Api to enable/disable ad interrupt
* @crtc: Pointer to crtc.
* @en: Variable to enable/disable interrupt.
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c
index ab1d86b..9d7d1e0 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.c
+++ b/drivers/gpu/drm/msm/sde/sde_connector.c
@@ -1106,7 +1106,7 @@
goto end;
}
- rc = copy_to_user((uint64_t __user *)val, &fence_fd,
+ rc = copy_to_user((uint64_t __user *)(uintptr_t)val, &fence_fd,
sizeof(uint64_t));
if (rc) {
SDE_ERROR("copy to user failed rc:%d\n", rc);
@@ -1117,7 +1117,8 @@
}
break;
case CONNECTOR_PROP_ROI_V1:
- rc = _sde_connector_set_roi_v1(c_conn, c_state, (void *)val);
+ rc = _sde_connector_set_roi_v1(c_conn, c_state,
+ (void *)(uintptr_t)val);
if (rc)
SDE_ERROR_CONN(c_conn, "invalid roi_v1, rc: %d\n", rc);
break;
@@ -1140,7 +1141,7 @@
if (idx == CONNECTOR_PROP_HDR_METADATA) {
rc = _sde_connector_set_ext_hdr_info(c_conn,
- c_state, (void *)val);
+ c_state, (void *)(uintptr_t)val);
if (rc)
SDE_ERROR_CONN(c_conn, "cannot set hdr info %d\n", rc);
}
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c
index 34a3d5f..8af8298 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.c
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.c
@@ -641,7 +641,7 @@
static int _sde_debugfs_fps_status_show(struct seq_file *s, void *data)
{
struct sde_crtc *sde_crtc;
- unsigned int fps_int, fps_float;
+ u64 fps_int, fps_float;
ktime_t current_time_us;
u64 fps, diff_us;
@@ -670,7 +670,7 @@
fps_int = (unsigned int) sde_crtc->fps_info.measured_fps;
fps_float = do_div(fps_int, 10);
- seq_printf(s, "fps: %d.%d\n", fps_int, fps_float);
+ seq_printf(s, "fps: %llu.%llu\n", fps_int, fps_float);
return 0;
}
@@ -3689,6 +3689,7 @@
struct sde_kms *sde_kms;
struct sde_crtc_state *cstate;
bool is_error, reset_req;
+ enum sde_crtc_idle_pc_state idle_pc_state;
if (!crtc) {
SDE_ERROR("invalid argument\n");
@@ -3719,6 +3720,8 @@
is_error = _sde_crtc_prepare_for_kickoff_rot(dev, crtc);
+ idle_pc_state = sde_crtc_get_property(cstate, CRTC_PROP_IDLE_PC_STATE);
+
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
struct sde_encoder_kickoff_params params = { 0 };
@@ -3734,6 +3737,10 @@
crtc->state);
if (sde_encoder_prepare_for_kickoff(encoder, ¶ms))
reset_req = true;
+
+ if (idle_pc_state != IDLE_PC_NONE)
+ sde_encoder_control_idle_pc(encoder,
+ (idle_pc_state == IDLE_PC_ENABLE) ? true : false);
}
/*
@@ -4233,6 +4240,13 @@
sde_encoder_register_frame_event_callback(encoder, NULL, NULL);
cstate->rsc_client = NULL;
cstate->rsc_update = false;
+
+ /*
+ * reset idle power-collapse to original state during suspend;
+ * user-mode will change the state on resume, if required
+ */
+ if (sde_kms->catalog->has_idle_pc)
+ sde_encoder_control_idle_pc(encoder, true);
}
if (sde_crtc->power_event)
@@ -4918,6 +4932,8 @@
sde_crtc = to_sde_crtc(crtc);
cstate = to_sde_crtc_state(crtc_state);
+ sde_cp_crtc_clear(crtc);
+
for (prop_idx = 0; prop_idx < CRTC_PROP_COUNT; prop_idx++) {
uint64_t val = cstate->property_values[prop_idx].value;
uint64_t def;
@@ -4974,6 +4990,12 @@
{CAPTURE_DSPP_OUT, "capture_pp_out"},
};
+ static const struct drm_prop_enum_list e_idle_pc_state[] = {
+ {IDLE_PC_NONE, "idle_pc_none"},
+ {IDLE_PC_ENABLE, "idle_pc_enable"},
+ {IDLE_PC_DISABLE, "idle_pc_disable"},
+ };
+
SDE_DEBUG("\n");
if (!crtc || !catalog) {
@@ -5053,6 +5075,12 @@
"enable_sui_enhancement", 0, 0, U64_MAX, 0,
CRTC_PROP_ENABLE_SUI_ENHANCEMENT);
+ if (catalog->has_idle_pc)
+ msm_property_install_enum(&sde_crtc->property_info,
+ "idle_pc_state", 0x0, 0, e_idle_pc_state,
+ ARRAY_SIZE(e_idle_pc_state),
+ CRTC_PROP_IDLE_PC_STATE);
+
if (catalog->has_cwb_support)
msm_property_install_enum(&sde_crtc->property_info,
"capture_mode", 0, 0, e_cwb_data_points,
@@ -5268,14 +5296,16 @@
_sde_crtc_set_input_fence_timeout(cstate);
break;
case CRTC_PROP_DIM_LAYER_V1:
- _sde_crtc_set_dim_layer_v1(cstate, (void __user *)val);
+ _sde_crtc_set_dim_layer_v1(cstate,
+ (void __user *)(uintptr_t)val);
break;
case CRTC_PROP_ROI_V1:
- ret = _sde_crtc_set_roi_v1(state, (void __user *)val);
+ ret = _sde_crtc_set_roi_v1(state,
+ (void __user *)(uintptr_t)val);
break;
case CRTC_PROP_DEST_SCALER:
ret = _sde_crtc_set_dest_scaler(sde_crtc, cstate,
- (void __user *)val);
+ (void __user *)(uintptr_t)val);
break;
case CRTC_PROP_DEST_SCALER_LUT_ED:
case CRTC_PROP_DEST_SCALER_LUT_CIR:
@@ -5307,7 +5337,7 @@
goto exit;
}
- ret = copy_to_user((uint64_t __user *)val, &fence_fd,
+ ret = copy_to_user((uint64_t __user *)(uintptr_t)val, &fence_fd,
sizeof(uint64_t));
if (ret) {
SDE_ERROR("copy to user failed rc:%d\n", ret);
@@ -5554,8 +5584,8 @@
if (sde_crtc->vblank_cb_count) {
ktime_t diff = ktime_sub(ktime_get(), sde_crtc->vblank_cb_time);
- s64 diff_ms = ktime_to_ms(diff);
- s64 fps = diff_ms ? DIV_ROUND_CLOSEST(
+ u32 diff_ms = ktime_to_ms(diff);
+ u64 fps = diff_ms ? DIV_ROUND_CLOSEST(
sde_crtc->vblank_cb_count * 1000, diff_ms) : 0;
seq_printf(s,
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.h b/drivers/gpu/drm/msm/sde/sde_crtc.h
index 99177b1..709a51f 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.h
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.h
@@ -59,6 +59,18 @@
};
/**
+ * enum sde_crtc_idle_pc_state: states of idle power collapse
+ * @IDLE_PC_NONE: no-op
+ * @IDLE_PC_ENABLE: enable idle power-collapse
+ * @IDLE_PC_DISABLE: disable idle power-collapse
+ */
+enum sde_crtc_idle_pc_state {
+ IDLE_PC_NONE,
+ IDLE_PC_ENABLE,
+ IDLE_PC_DISABLE,
+};
+
+/**
* @connectors : Currently associated drm connectors for retire event
* @num_connectors: Number of associated drm connectors for retire event
* @list: event list
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c
index 73864b6..a6643bb 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.c
@@ -200,7 +200,8 @@
* @disp_info: local copy of msm_display_info struct
* @misr_enable: misr enable/disable status
* @misr_frame_count: misr frame count before start capturing the data
- * @idle_pc_supported: indicate if idle power collaps is supported
+ * @idle_pc_enabled: indicate if idle power collapse is enabled
+ * currently. This can be controlled by user-mode
* @rc_lock: resource control mutex lock to protect
* virt encoder over various state changes
* @rc_state: resource controller state
@@ -250,7 +251,7 @@
bool misr_enable;
u32 misr_frame_count;
- bool idle_pc_supported;
+ bool idle_pc_enabled;
struct mutex rc_lock;
enum sde_enc_rc_states rc_state;
struct kthread_delayed_work delayed_off_work;
@@ -1922,6 +1923,25 @@
&sde_enc->input_event_work);
}
+void sde_encoder_control_idle_pc(struct drm_encoder *drm_enc, bool enable)
+{
+ struct sde_encoder_virt *sde_enc;
+
+ if (!drm_enc) {
+ SDE_ERROR("invalid encoder\n");
+ return;
+ }
+ sde_enc = to_sde_encoder_virt(drm_enc);
+
+ /* return early if there is no state change */
+ if (sde_enc->idle_pc_enabled == enable)
+ return;
+
+ sde_enc->idle_pc_enabled = enable;
+
+ SDE_DEBUG("idle-pc state:%d\n", sde_enc->idle_pc_enabled);
+ SDE_EVT32(sde_enc->idle_pc_enabled);
+}
static int sde_encoder_resource_control(struct drm_encoder *drm_enc,
u32 sw_event)
@@ -1948,7 +1968,7 @@
* when idle_pc is not supported, process only KICKOFF, STOP and MODESET
* events and return early for other events (ie wb display).
*/
- if (!sde_enc->idle_pc_supported &&
+ if (!sde_enc->idle_pc_enabled &&
(sw_event != SDE_ENC_RC_EVENT_KICKOFF &&
sw_event != SDE_ENC_RC_EVENT_PRE_MODESET &&
sw_event != SDE_ENC_RC_EVENT_POST_MODESET &&
@@ -1956,9 +1976,9 @@
sw_event != SDE_ENC_RC_EVENT_PRE_STOP))
return 0;
- SDE_DEBUG_ENC(sde_enc, "sw_event:%d, idle_pc_supported:%d\n", sw_event,
- sde_enc->idle_pc_supported);
- SDE_EVT32_VERBOSE(DRMID(drm_enc), sw_event, sde_enc->idle_pc_supported,
+ SDE_DEBUG_ENC(sde_enc, "sw_event:%d, idle_pc:%d\n",
+ sw_event, sde_enc->idle_pc_enabled);
+ SDE_EVT32_VERBOSE(DRMID(drm_enc), sw_event, sde_enc->idle_pc_enabled,
sde_enc->rc_state, SDE_EVTLOG_FUNC_ENTRY);
switch (sw_event) {
@@ -2348,7 +2368,7 @@
break;
}
- SDE_EVT32_VERBOSE(DRMID(drm_enc), sw_event, sde_enc->idle_pc_supported,
+ SDE_EVT32_VERBOSE(DRMID(drm_enc), sw_event, sde_enc->idle_pc_enabled,
sde_enc->rc_state, SDE_EVTLOG_FUNC_EXIT);
return 0;
}
@@ -4483,7 +4503,7 @@
if ((disp_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE) ||
(disp_info->capabilities & MSM_DISPLAY_CAP_VID_MODE))
- sde_enc->idle_pc_supported = sde_kms->catalog->has_idle_pc;
+ sde_enc->idle_pc_enabled = sde_kms->catalog->has_idle_pc;
mutex_lock(&sde_enc->enc_lock);
for (i = 0; i < disp_info->num_of_h_tiles && !ret; i++) {
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.h b/drivers/gpu/drm/msm/sde/sde_encoder.h
index 42b9e58..c40db41 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.h
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.h
@@ -257,4 +257,11 @@
*/
int sde_encoder_in_clone_mode(struct drm_encoder *enc);
+/**
+ * sde_encoder_control_idle_pc - control enable/disable of idle power collapse
+ * @drm_enc: Pointer to drm encoder structure
+ * @enable: enable/disable flag
+ */
+void sde_encoder_control_idle_pc(struct drm_encoder *enc, bool enable);
+
#endif /* __SDE_ENCODER_H__ */
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
index d363d62..74bf518 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
@@ -40,6 +40,20 @@
#define POLL_TIME_USEC_FOR_LN_CNT 500
#define MAX_POLL_CNT 10
+static bool _sde_encoder_phys_is_ppsplit(struct sde_encoder_phys *phys_enc)
+{
+ enum sde_rm_topology_name topology;
+
+ if (!phys_enc)
+ return false;
+
+ topology = sde_connector_get_topology_name(phys_enc->connector);
+ if (topology == SDE_RM_TOPOLOGY_PPSPLIT)
+ return true;
+
+ return false;
+}
+
static bool sde_encoder_phys_vid_is_master(
struct sde_encoder_phys *phys_enc)
{
@@ -313,12 +327,14 @@
if (!phys_enc->sde_kms->splash_data.cont_splash_en) {
SDE_EVT32(DRMID(phys_enc->parent), f.enable, f.fetch_start);
- phys_enc->hw_ctl->ops.get_bitmask_intf(
- phys_enc->hw_ctl, &flush_mask,
- vid_enc->hw_intf->idx);
- phys_enc->hw_ctl->ops.update_pending_flush(
- phys_enc->hw_ctl, flush_mask);
-
+ if (!_sde_encoder_phys_is_ppsplit(phys_enc) ||
+ sde_encoder_phys_vid_is_master(phys_enc)) {
+ phys_enc->hw_ctl->ops.get_bitmask_intf(
+ phys_enc->hw_ctl, &flush_mask,
+ vid_enc->hw_intf->idx);
+ phys_enc->hw_ctl->ops.update_pending_flush(
+ phys_enc->hw_ctl, flush_mask);
+ }
spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags);
vid_enc->hw_intf->ops.setup_rot_start(vid_enc->hw_intf, &f);
spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags);
@@ -496,20 +512,6 @@
phys_enc);
}
-static bool _sde_encoder_phys_is_ppsplit(struct sde_encoder_phys *phys_enc)
-{
- enum sde_rm_topology_name topology;
-
- if (!phys_enc)
- return false;
-
- topology = sde_connector_get_topology_name(phys_enc->connector);
- if (topology == SDE_RM_TOPOLOGY_PPSPLIT)
- return true;
-
- return false;
-}
-
static bool _sde_encoder_phys_is_dual_ctl(struct sde_encoder_phys *phys_enc)
{
enum sde_rm_topology_name topology;
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_color_processing_v1_7.c b/drivers/gpu/drm/msm/sde/sde_hw_color_processing_v1_7.c
index c7989cd..61076cf 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_color_processing_v1_7.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_color_processing_v1_7.c
@@ -951,8 +951,9 @@
offset = ctx->cap->sblk->hist.base + PA_HIST_DATA_DSPP_OFF;
offset_ctl = ctx->cap->sblk->hist.base + PA_HIST_CTRL_DSPP_OFF;
+ /* collect hist data for given DSPPs */
for (i = 0; i < HIST_V_SIZE; i++)
- hist_data->data[i] = SDE_REG_READ(&ctx->hw, offset + i * 4) &
+ hist_data->data[i] += SDE_REG_READ(&ctx->hw, offset + i * 4) &
REG_MASK(24);
/* unlock hist buffer */
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1.c b/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1.c
index 02d593b..a88f513 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1.c
@@ -187,7 +187,7 @@
*decode_sel |= BIT(21);
break;
default:
- DRM_ERROR("block not supported %zx\n", BIT(i));
+ DRM_ERROR("block not supported %zx\n", (size_t)BIT(i));
break;
}
}
@@ -292,7 +292,7 @@
if (cfg->wrap_size < WRAP_MIN_SIZE || cfg->wrap_size > WRAP_MAX_SIZE) {
DRM_ERROR("invalid wrap sz %d min %d max %zd\n",
- cfg->wrap_size, WRAP_MIN_SIZE, WRAP_MAX_SIZE);
+ cfg->wrap_size, WRAP_MIN_SIZE, (size_t)WRAP_MAX_SIZE);
rc = -EINVAL;
}
@@ -319,7 +319,7 @@
if ((SIZE_DWORD(cfg->data_size)) > MAX_DWORDS_SZ ||
NOT_WORD_ALIGNED(cfg->data_size)) {
DRM_ERROR("Invalid data size %d max %zd align %x\n",
- cfg->data_size, MAX_DWORDS_SZ,
+ cfg->data_size, (size_t)MAX_DWORDS_SZ,
NOT_WORD_ALIGNED(cfg->data_size));
return -EINVAL;
}
@@ -327,7 +327,7 @@
if (cfg->blk_offset > MAX_RELATIVE_OFF ||
NOT_WORD_ALIGNED(cfg->blk_offset)) {
DRM_ERROR("invalid offset %d max %zd align %x\n",
- cfg->blk_offset, MAX_RELATIVE_OFF,
+ cfg->blk_offset, (size_t)MAX_RELATIVE_OFF,
NOT_WORD_ALIGNED(cfg->blk_offset));
return -EINVAL;
}
@@ -391,7 +391,7 @@
if (cfg->dma_buf->iova & GUARD_BYTES || !cfg->dma_buf->vaddr) {
DRM_ERROR("iova not aligned to %zx iova %x kva %pK",
- ADDR_ALIGN, cfg->dma_buf->iova,
+ (size_t)ADDR_ALIGN, cfg->dma_buf->iova,
cfg->dma_buf->vaddr);
return -EINVAL;
}
@@ -449,8 +449,8 @@
(WRITE_TRIGGER);
if (cfg->dma_buf->iova & GUARD_BYTES) {
- DRM_ERROR("Address is not aligned to %zx iova %x", ADDR_ALIGN,
- cfg->dma_buf->iova);
+ DRM_ERROR("Address is not aligned to %zx iova %x",
+ (size_t)ADDR_ALIGN, cfg->dma_buf->iova);
return -EINVAL;
}
@@ -462,7 +462,8 @@
if (SIZE_DWORD(cfg->dma_buf->index) > MAX_DWORDS_SZ ||
!cfg->dma_buf->index) {
DRM_ERROR("invalid dword size %zd max %zd\n",
- SIZE_DWORD(cfg->dma_buf->index), MAX_DWORDS_SZ);
+ (size_t)SIZE_DWORD(cfg->dma_buf->index),
+ (size_t)MAX_DWORDS_SZ);
return -EINVAL;
}
return 0;
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_rot.c b/drivers/gpu/drm/msm/sde/sde_hw_rot.c
index facec3d..9767832 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_rot.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_rot.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
@@ -567,9 +567,14 @@
}
/* adjust bw for scaling */
- if (data->dst_rect_h)
- *prefill_bw = mult_frac(data->prefill_bw, data->crtc_h,
+ if (data->dst_rect_h) {
+ u64 temp;
+
+ temp = DIV_ROUND_UP_ULL(data->prefill_bw,
data->dst_rect_h);
+ *prefill_bw = temp * data->crtc_h;
+ }
+
return 0;
}
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_sspp.c b/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
index 356f9ef..10ed954 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
@@ -865,8 +865,9 @@
}
if (cfg->time) {
- ts_bytes = mult_frac(TS_CLK * 1000000ULL, cfg->size,
- cfg->time);
+ u64 temp = DIV_ROUND_UP_ULL(TS_CLK * 1000000ULL, cfg->time);
+
+ ts_bytes = temp * cfg->size;
if (ts_bytes > SSPP_TRAFFIC_SHAPER_BPC_MAX)
ts_bytes = SSPP_TRAFFIC_SHAPER_BPC_MAX;
}
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c
index c2fffef..9a4c785 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.c
+++ b/drivers/gpu/drm/msm/sde/sde_kms.c
@@ -1686,6 +1686,16 @@
drm_for_each_crtc(crtc, dev)
sde_crtc_timeline_status(crtc);
+ if (mutex_is_locked(&dev->mode_config.mutex)) {
+ /*
+ *Probably locked from last close dumping status anyway
+ */
+ SDE_ERROR("dumping conn_timeline without mode_config lock\n");
+ drm_for_each_connector(conn, dev)
+ sde_conn_timeline_status(conn);
+ return;
+ }
+
mutex_lock(&dev->mode_config.mutex);
drm_for_each_connector(conn, dev)
sde_conn_timeline_status(conn);
@@ -3293,6 +3303,22 @@
goto power_error;
}
+ sde_kms->splash_data.resource_handoff_pending = true;
+
+ rc = _sde_kms_mmu_init(sde_kms);
+ if (rc) {
+ SDE_ERROR("sde_kms_mmu_init failed: %d\n", rc);
+ goto power_error;
+ }
+
+ /* Initialize reg dma block which is a singleton */
+ rc = sde_reg_dma_init(sde_kms->reg_dma, sde_kms->catalog,
+ sde_kms->dev);
+ if (rc) {
+ SDE_ERROR("failed: reg dma init failed\n");
+ goto power_error;
+ }
+
sde_dbg_init_dbg_buses(sde_kms->core_rev);
rm = &sde_kms->rm;
@@ -3322,21 +3348,6 @@
&sde_kms->splash_data,
sde_kms->catalog);
- sde_kms->splash_data.resource_handoff_pending = true;
-
- /* Initialize reg dma block which is a singleton */
- rc = sde_reg_dma_init(sde_kms->reg_dma, sde_kms->catalog,
- sde_kms->dev);
- if (rc) {
- SDE_ERROR("failed: reg dma init failed\n");
- goto power_error;
- }
-
- rc = _sde_kms_mmu_init(sde_kms);
- if (rc) {
- SDE_ERROR("sde_kms_mmu_init failed: %d\n", rc);
- goto power_error;
- }
sde_kms->hw_mdp = sde_rm_get_mdp(&sde_kms->rm);
if (IS_ERR_OR_NULL(sde_kms->hw_mdp)) {
rc = PTR_ERR(sde_kms->hw_mdp);
diff --git a/drivers/gpu/drm/msm/sde/sde_plane.c b/drivers/gpu/drm/msm/sde/sde_plane.c
index dc55ad5..be6e756 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.c
+++ b/drivers/gpu/drm/msm/sde/sde_plane.c
@@ -831,7 +831,6 @@
input_fence = pstate->input_fence;
if (input_fence) {
- psde->is_error = false;
prefix = sde_sync_get_name_prefix(input_fence);
rc = sde_sync_wait(input_fence, wait_ms);
@@ -971,8 +970,15 @@
ret = sde_format_populate_layout(aspace, fb, &pipe_cfg->layout);
if (ret == -EAGAIN)
SDE_DEBUG_PLANE(psde, "not updating same src addrs\n");
- else if (ret)
+ else if (ret) {
SDE_ERROR_PLANE(psde, "failed to get format layout, %d\n", ret);
+
+ /*
+ * Force solid fill color on error. This is to prevent
+ * smmu faults during secure session transition.
+ */
+ psde->is_error = true;
+ }
else if (psde->pipe_hw->ops.setup_sourceaddress) {
SDE_EVT32_VERBOSE(psde->pipe_hw->idx,
pipe_cfg->layout.width,
@@ -1088,6 +1094,12 @@
&& (src_w == dst_w))
return;
+ SDE_DEBUG_PLANE(psde,
+ "setting bilinear: src:%dx%d dst:%dx%d chroma:%dx%d fmt:%x\n",
+ src_w, src_h, dst_w, dst_h,
+ chroma_subsmpl_v, chroma_subsmpl_h,
+ fmt->base.pixel_format);
+
scale_cfg->dst_width = dst_w;
scale_cfg->dst_height = dst_h;
scale_cfg->y_rgb_filter_cfg = SDE_SCALE_BIL;
@@ -2055,19 +2067,19 @@
return;
fbo = sde_crtc_res_get(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
- (u64) &rstate->rot_hw->base);
+ (u64)(uintptr_t) &rstate->rot_hw->base);
fb = sde_crtc_res_get(cstate, SDE_CRTC_RES_ROT_OUT_FB,
- (u64) &rstate->rot_hw->base);
+ (u64)(uintptr_t) &rstate->rot_hw->base);
if (fb && fbo) {
SDE_DEBUG("plane%d.%d get fb/fbo\n", plane->base.id,
rstate->sequence_id);
} else if (fbo) {
sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
- (u64) &rstate->rot_hw->base);
+ (u64)(uintptr_t) &rstate->rot_hw->base);
fbo = NULL;
} else if (fb) {
sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
- (u64) &rstate->rot_hw->base);
+ (u64)(uintptr_t) &rstate->rot_hw->base);
fb = NULL;
}
@@ -2136,7 +2148,7 @@
}
ret = sde_crtc_res_add(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
- (u64) &new_rstate->rot_hw->base,
+ (u64)(uintptr_t) &new_rstate->rot_hw->base,
new_rstate->out_fbo, &fbo_res_ops);
if (ret) {
SDE_ERROR("failed to add crtc resource\n");
@@ -2154,7 +2166,7 @@
new_rstate->out_fb->base.id);
ret = sde_crtc_res_add(cstate, SDE_CRTC_RES_ROT_OUT_FB,
- (u64) &new_rstate->rot_hw->base,
+ (u64)(uintptr_t) &new_rstate->rot_hw->base,
new_rstate->out_fb, &fb_res_ops);
if (ret) {
SDE_ERROR("failed to add crtc resource %d\n", ret);
@@ -2197,12 +2209,12 @@
msm_framebuffer_cleanup(new_state->fb, new_pstate->aspace);
error_prepare_input_buffer:
sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
- (u64) &new_rstate->rot_hw->base);
+ (u64)(uintptr_t) &new_rstate->rot_hw->base);
error_create_fb_res:
new_rstate->out_fb = NULL;
error_create_fb:
sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
- (u64) &new_rstate->rot_hw->base);
+ (u64)(uintptr_t) &new_rstate->rot_hw->base);
error_create_fbo_res:
new_rstate->out_fbo = NULL;
error_create_fbo:
@@ -2252,10 +2264,10 @@
msm_framebuffer_cleanup(old_rstate->out_fb,
old_pstate->aspace);
sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
- (u64) &old_rstate->rot_hw->base);
+ (u64)(uintptr_t) &old_rstate->rot_hw->base);
old_rstate->out_fb = NULL;
sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
- (u64) &old_rstate->rot_hw->base);
+ (u64)(uintptr_t) &old_rstate->rot_hw->base);
old_rstate->out_fbo = NULL;
}
@@ -2318,7 +2330,7 @@
state->fb ? state->fb->base.id : -1);
hw_blk = sde_crtc_res_get(cstate, SDE_HW_BLK_ROT,
- (u64) state->fb);
+ (u64)(uintptr_t) state->fb);
if (!hw_blk) {
SDE_ERROR("plane%d.%d no available rotator, fb %d\n",
plane->base.id, rstate->sequence_id,
@@ -2334,7 +2346,7 @@
SDE_ERROR("plane%d.%d invalid rotator ops\n",
plane->base.id, rstate->sequence_id);
sde_crtc_res_put(cstate,
- SDE_HW_BLK_ROT, (u64) state->fb);
+ SDE_HW_BLK_ROT, (u64)(uintptr_t) state->fb);
rstate->rot_hw = NULL;
return -EINVAL;
}
@@ -2385,10 +2397,10 @@
rstate->sequence_id, fb_id);
sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
- (u64) &rstate->rot_hw->base);
+ (u64)(uintptr_t) &rstate->rot_hw->base);
rstate->out_fb = NULL;
sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
- (u64) &rstate->rot_hw->base);
+ (u64)(uintptr_t) &rstate->rot_hw->base);
rstate->out_fbo = NULL;
}
@@ -3029,7 +3041,7 @@
state->fb ? state->fb->base.id : -1);
hw_blk = sde_crtc_res_get(cstate, SDE_HW_BLK_ROT,
- (u64) state->fb);
+ (u64)(uintptr_t) state->fb);
if (!hw_blk) {
SDE_ERROR("plane%d.%d no available rotator, fb %d\n",
plane->base.id, rstate->sequence_id,
@@ -3574,17 +3586,16 @@
ret = -EINVAL;
/* decimation validation */
- } else if (deci_w || deci_h) {
- if ((deci_w > psde->pipe_sblk->maxhdeciexp) ||
- (deci_h > psde->pipe_sblk->maxvdeciexp)) {
- SDE_ERROR_PLANE(psde,
- "too much decimation requested\n");
- ret = -EINVAL;
- } else if (fmt->fetch_mode != SDE_FETCH_LINEAR) {
- SDE_ERROR_PLANE(psde,
- "decimation requires linear fetch\n");
- ret = -EINVAL;
- }
+ } else if ((deci_w || deci_h)
+ && ((deci_w > psde->pipe_sblk->maxhdeciexp)
+ || (deci_h > psde->pipe_sblk->maxvdeciexp))) {
+ SDE_ERROR_PLANE(psde, "too much decimation requested\n");
+ ret = -EINVAL;
+
+ } else if ((deci_w || deci_h)
+ && (fmt->fetch_mode != SDE_FETCH_LINEAR)) {
+ SDE_ERROR_PLANE(psde, "decimation requires linear fetch\n");
+ ret = -EINVAL;
} else if (!(psde->features & SDE_SSPP_SCALER) &&
((src.w != dst.w) || (src.h != dst.h))) {
@@ -4666,19 +4677,20 @@
_sde_plane_set_input_fence(psde, pstate, val);
break;
case PLANE_PROP_CSC_V1:
- _sde_plane_set_csc_v1(psde, (void *)val);
+ _sde_plane_set_csc_v1(psde,
+ (void *)(uintptr_t)val);
break;
case PLANE_PROP_SCALER_V1:
_sde_plane_set_scaler_v1(psde, pstate,
- (void *)val);
+ (void *)(uintptr_t)val);
break;
case PLANE_PROP_SCALER_V2:
_sde_plane_set_scaler_v2(psde, pstate,
- (void *)val);
+ (void *)(uintptr_t)val);
break;
case PLANE_PROP_EXCL_RECT_V1:
_sde_plane_set_excl_rect_v1(psde, pstate,
- (void *)val);
+ (void *)(uintptr_t)val);
break;
default:
/* nothing to do */
diff --git a/drivers/gpu/drm/msm/sde/sde_wb.c b/drivers/gpu/drm/msm/sde/sde_wb.c
index 71c8b63..61588bd9 100644
--- a/drivers/gpu/drm/msm/sde/sde_wb.c
+++ b/drivers/gpu/drm/msm/sde/sde_wb.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2018, 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
@@ -816,6 +816,7 @@
.driver = {
.name = "sde_wb",
.of_match_table = dt_match,
+ .suppress_bind_attrs = true,
},
};
diff --git a/drivers/gpu/drm/msm/sde_dbg.c b/drivers/gpu/drm/msm/sde_dbg.c
index 758cc53..2e1422f 100644
--- a/drivers/gpu/drm/msm/sde_dbg.c
+++ b/drivers/gpu/drm/msm/sde_dbg.c
@@ -2129,7 +2129,8 @@
if (in_log)
dev_info(sde_dbg_base.dev, "%s: start_offset 0x%lx len 0x%zx\n",
- dump_name, addr - base_addr, len_bytes);
+ dump_name, (unsigned long)(addr - base_addr),
+ len_bytes);
len_align = (len_bytes + REG_DUMP_ALIGN - 1) / REG_DUMP_ALIGN;
len_padded = len_align * REG_DUMP_ALIGN;
@@ -2147,7 +2148,7 @@
dev_info(sde_dbg_base.dev,
"%s: start_addr:0x%pK len:0x%x reg_offset=0x%lx\n",
dump_name, dump_addr, len_padded,
- addr - base_addr);
+ (unsigned long)(addr - base_addr));
} else {
in_mem = 0;
pr_err("dump_mem: kzalloc fails!\n");
@@ -2173,7 +2174,8 @@
if (in_log)
dev_info(sde_dbg_base.dev,
"0x%lx : %08x %08x %08x %08x\n",
- addr - base_addr, x0, x4, x8, xc);
+ (unsigned long)(addr - base_addr),
+ x0, x4, x8, xc);
if (dump_addr) {
dump_addr[i * 4] = x0;
diff --git a/drivers/gpu/drm/msm/sde_io_util.c b/drivers/gpu/drm/msm/sde_io_util.c
index d5a438e..f830010 100644
--- a/drivers/gpu/drm/msm/sde_io_util.c
+++ b/drivers/gpu/drm/msm/sde_io_util.c
@@ -1,4 +1,5 @@
-/* Copyright (c) 2012-2015, 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2015, 2017, 2018, 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
@@ -230,7 +231,7 @@
need_sleep = !regulator_is_enabled(in_vreg[i].vreg);
if (in_vreg[i].pre_on_sleep && need_sleep)
usleep_range(in_vreg[i].pre_on_sleep * 1000,
- in_vreg[i].pre_on_sleep * 1000);
+ (in_vreg[i].pre_on_sleep * 1000) + 10);
rc = regulator_set_load(in_vreg[i].vreg,
in_vreg[i].enable_load);
if (rc < 0) {
@@ -242,7 +243,7 @@
rc = regulator_enable(in_vreg[i].vreg);
if (in_vreg[i].post_on_sleep && need_sleep)
usleep_range(in_vreg[i].post_on_sleep * 1000,
- in_vreg[i].post_on_sleep * 1000);
+ (in_vreg[i].post_on_sleep * 1000) + 10);
if (rc < 0) {
DEV_ERR("%pS->%s: %s enable failed\n",
__builtin_return_address(0), __func__,
@@ -254,13 +255,13 @@
for (i = num_vreg-1; i >= 0; i--) {
if (in_vreg[i].pre_off_sleep)
usleep_range(in_vreg[i].pre_off_sleep * 1000,
- in_vreg[i].pre_off_sleep * 1000);
+ (in_vreg[i].pre_off_sleep * 1000) + 10);
regulator_set_load(in_vreg[i].vreg,
in_vreg[i].disable_load);
regulator_disable(in_vreg[i].vreg);
if (in_vreg[i].post_off_sleep)
usleep_range(in_vreg[i].post_off_sleep * 1000,
- in_vreg[i].post_off_sleep * 1000);
+ (in_vreg[i].post_off_sleep * 1000) + 10);
}
}
return rc;
@@ -272,13 +273,13 @@
for (i--; i >= 0; i--) {
if (in_vreg[i].pre_off_sleep)
usleep_range(in_vreg[i].pre_off_sleep * 1000,
- in_vreg[i].pre_off_sleep * 1000);
+ (in_vreg[i].pre_off_sleep * 1000) + 10);
regulator_set_load(in_vreg[i].vreg,
in_vreg[i].disable_load);
regulator_disable(in_vreg[i].vreg);
if (in_vreg[i].post_off_sleep)
usleep_range(in_vreg[i].post_off_sleep * 1000,
- in_vreg[i].post_off_sleep * 1000);
+ (in_vreg[i].post_off_sleep * 1000) + 10);
}
return rc;
diff --git a/drivers/gpu/drm/msm/sde_rsc.c b/drivers/gpu/drm/msm/sde_rsc.c
index 6626cb33..721e278 100644
--- a/drivers/gpu/drm/msm/sde_rsc.c
+++ b/drivers/gpu/drm/msm/sde_rsc.c
@@ -1454,6 +1454,7 @@
.driver = {
.name = "sde_rsc",
.of_match_table = dt_match,
+ .suppress_bind_attrs = true,
},
};
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 8e21958..fbf298d 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -1873,8 +1873,11 @@
ret = gpudev->oob_set(adreno_dev, OOB_PERFCNTR_SET_MASK,
OOB_PERFCNTR_CHECK_MASK,
OOB_PERFCNTR_CLEAR_MASK);
- if (ret)
+ if (ret) {
+ adreno_set_gpu_fault(adreno_dev, ADRENO_GMU_FAULT);
+ adreno_dispatcher_schedule(KGSL_DEVICE(adreno_dev));
kgsl_active_count_put(KGSL_DEVICE(adreno_dev));
+ }
}
return ret;
diff --git a/drivers/gpu/msm/adreno_a6xx_preempt.c b/drivers/gpu/msm/adreno_a6xx_preempt.c
index 6c8e664..132fb02 100644
--- a/drivers/gpu/msm/adreno_a6xx_preempt.c
+++ b/drivers/gpu/msm/adreno_a6xx_preempt.c
@@ -49,8 +49,13 @@
OOB_PREEMPTION_SET_MASK,
OOB_PREEMPTION_CHECK_MASK,
OOB_PREEMPTION_CLEAR_MASK);
- if (status)
+ if (status) {
+ adreno_set_gpu_fault(adreno_dev,
+ ADRENO_GMU_FAULT);
+ adreno_dispatcher_schedule(
+ KGSL_DEVICE(adreno_dev));
return;
+ }
}
}
diff --git a/drivers/hwmon/qpnp-adc-voltage.c b/drivers/hwmon/qpnp-adc-voltage.c
index 7e6af65..1ed92d6 100644
--- a/drivers/hwmon/qpnp-adc-voltage.c
+++ b/drivers/hwmon/qpnp-adc-voltage.c
@@ -162,6 +162,10 @@
#define QPNP_VADC_HC1_CONV_TIME_MAX_US 214
#define QPNP_VADC_HC1_ERR_COUNT 1600
+#define QPNP_VADC_CAL_DELAY_CTL_1 0x3744
+#define QPNP_VADC_CAL_DELAY_MEAS_SLOW 0x73
+#define QPNP_VADC_CAL_DELAY_MEAS_DEFAULT 0x3
+
struct qpnp_vadc_mode_state {
bool meas_int_mode;
bool meas_int_request_in_queue;
@@ -489,7 +493,8 @@
struct qpnp_vadc_result *result)
{
int rc = 0, scale_type, amux_prescaling, dt_index = 0, calib_type = 0;
- struct qpnp_adc_amux_properties amux_prop;
+ u8 val = QPNP_VADC_CAL_DELAY_MEAS_SLOW;
+ struct qpnp_adc_amux_properties amux_prop, conv;
if (qpnp_vadc_is_valid(vadc))
return -EPROBE_DEFER;
@@ -525,6 +530,31 @@
goto fail_unlock;
}
+ if (channel == VADC_USB_IN_V_DIV_16_PM5 &&
+ vadc->adc->adc_prop->is_pmic_5) {
+ rc = regmap_bulk_write(vadc->adc->regmap,
+ QPNP_VADC_CAL_DELAY_CTL_1, &val, 1);
+ if (rc < 0) {
+ pr_err("qpnp adc write cal_delay failed with %d\n", rc);
+ return rc;
+ }
+ msleep(20);
+
+ conv.amux_channel = VADC_VREF_GND;
+ conv.decimation = DECIMATION_TYPE2;
+ conv.mode_sel = ADC_OP_NORMAL_MODE << QPNP_VADC_OP_MODE_SHIFT;
+ conv.hw_settle_time = ADC_CHANNEL_HW_SETTLE_DELAY_0US;
+ conv.fast_avg_setup = ADC_FAST_AVG_SAMPLE_1;
+ conv.cal_val = ADC_HC_ABS_CAL;
+
+ rc = qpnp_vadc_hc_configure(vadc, &conv);
+ if (rc) {
+ pr_err("qpnp_vadc configure failed with %d\n", rc);
+ goto fail_unlock;
+ }
+
+ }
+
amux_prop.decimation =
vadc->adc->adc_channels[dt_index].adc_decimation;
amux_prop.calib_type = vadc->adc->adc_channels[dt_index].calib_type;
@@ -561,6 +591,18 @@
}
}
+ val = QPNP_VADC_CAL_DELAY_MEAS_DEFAULT;
+
+ if (channel == VADC_USB_IN_V_DIV_16_PM5 &&
+ vadc->adc->adc_prop->is_pmic_5) {
+ rc = regmap_bulk_write(vadc->adc->regmap,
+ QPNP_VADC_CAL_DELAY_CTL_1, &val, 1);
+ if (rc < 0) {
+ pr_err("qpnp adc write cal_delay failed with %d\n", rc);
+ return rc;
+ }
+ }
+
rc = qpnp_vadc_hc_read_data(vadc, &result->adc_code);
if (rc) {
pr_err("qpnp vadc read adc code failed with %d\n", rc);
diff --git a/drivers/hwtracing/coresight/coresight-csr.c b/drivers/hwtracing/coresight/coresight-csr.c
index 9069530..0252203 100644
--- a/drivers/hwtracing/coresight/coresight-csr.c
+++ b/drivers/hwtracing/coresight/coresight-csr.c
@@ -21,6 +21,7 @@
#include <linux/of.h>
#include <linux/coresight.h>
#include <linux/clk.h>
+#include <linux/mutex.h>
#include "coresight-priv.h"
@@ -88,6 +89,8 @@
};
static LIST_HEAD(csr_list);
+static DEFINE_MUTEX(csr_lock);
+
#define to_csr_drvdata(c) container_of(c, struct csr_drvdata, csr)
void msm_qdss_csr_enable_bam_to_usb(struct coresight_csr *csr)
@@ -236,12 +239,15 @@
struct coresight_csr *coresight_csr_get(const char *name)
{
struct coresight_csr *csr;
-
+ mutex_lock(&csr_lock);
list_for_each_entry(csr, &csr_list, link) {
- if (!strcmp(csr->name, name))
+ if (!strcmp(csr->name, name)) {
+ mutex_unlock(&csr_lock);
return csr;
+ }
}
+ mutex_unlock(&csr_lock);
return ERR_PTR(-EINVAL);
}
EXPORT_SYMBOL(coresight_csr_get);
@@ -391,7 +397,10 @@
spin_lock_init(&drvdata->spin_lock);
drvdata->csr.name = ((struct coresight_platform_data *)
(pdev->dev.platform_data))->name;
+
+ mutex_lock(&csr_lock);
list_add_tail(&drvdata->csr.link, &csr_list);
+ mutex_unlock(&csr_lock);
dev_info(dev, "CSR initialized: %s\n", drvdata->csr.name);
return 0;
@@ -399,12 +408,13 @@
static int csr_remove(struct platform_device *pdev)
{
- unsigned long flags;
struct csr_drvdata *drvdata = platform_get_drvdata(pdev);
- spin_lock_irqsave(&drvdata->spin_lock, flags);
+ mutex_lock(&csr_lock);
+ list_del(&drvdata->csr.link);
+ mutex_unlock(&csr_lock);
+
coresight_unregister(drvdata->csdev);
- spin_unlock_irqrestore(&drvdata->spin_lock, flags);
return 0;
}
diff --git a/drivers/hwtracing/coresight/coresight-remote-etm.c b/drivers/hwtracing/coresight/coresight-remote-etm.c
index 54e897d..f4512e5 100644
--- a/drivers/hwtracing/coresight/coresight-remote-etm.c
+++ b/drivers/hwtracing/coresight/coresight-remote-etm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2018, 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
@@ -362,6 +362,10 @@
{
struct remote_etm_drvdata *drvdata = platform_get_drvdata(pdev);
+ qmi_svc_event_notifier_unregister(CORESIGHT_QMI_SVC_ID,
+ CORESIGHT_QMI_VERSION,
+ drvdata->inst_id,
+ &drvdata->nb);
coresight_unregister(drvdata->csdev);
return 0;
}
diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c
index bc4af98..c712866 100644
--- a/drivers/i2c/busses/i2c-qcom-geni.c
+++ b/drivers/i2c/busses/i2c-qcom-geni.c
@@ -799,6 +799,7 @@
return ret;
}
+ gi2c->i2c_rsc.ctrl_dev = gi2c->dev;
gi2c->i2c_rsc.se_clk = devm_clk_get(&pdev->dev, "se-clk");
if (IS_ERR(gi2c->i2c_rsc.se_clk)) {
ret = PTR_ERR(gi2c->i2c_rsc.se_clk);
diff --git a/drivers/iio/imu/inv_icm20602/inv_icm20602_core.c b/drivers/iio/imu/inv_icm20602/inv_icm20602_core.c
index 7dda14e..bf8e968 100644
--- a/drivers/iio/imu/inv_icm20602/inv_icm20602_core.c
+++ b/drivers/iio/imu/inv_icm20602/inv_icm20602_core.c
@@ -31,6 +31,9 @@
#include "inv_icm20602_iio.h"
#include <linux/regulator/consumer.h>
+
+static struct regulator *reg_ldo;
+
/* Attribute of icm20602 device init show */
static ssize_t inv_icm20602_init_show(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -384,19 +387,19 @@
int ret = 0;
if (enable) {
- ret = regulator_set_voltage(st->reg_ldo,
+ ret = regulator_set_voltage(reg_ldo,
ICM20602_LDO_VTG_MIN_UV, ICM20602_LDO_VTG_MAX_UV);
if (ret)
pr_err("Failed to request LDO voltage.\n");
- ret = regulator_enable(st->reg_ldo);
+ ret = regulator_enable(reg_ldo);
if (ret)
pr_err("Failed to enable LDO %d\n", ret);
} else {
- ret = regulator_disable(st->reg_ldo);
+ ret = regulator_disable(reg_ldo);
+ regulator_set_load(reg_ldo, 0);
if (ret)
pr_err("Failed to disable LDO %d\n", ret);
- regulator_set_load(st->reg_ldo, 0);
}
return MPU_SUCCESS;
@@ -405,14 +408,13 @@
static int icm20602_init_regulators(struct inv_icm20602_state *st)
{
struct regulator *reg;
-
reg = regulator_get(&st->client->dev, "vdd-ldo");
if (IS_ERR_OR_NULL(reg)) {
pr_err("Unable to get regulator for LDO\n");
return -MPU_FAIL;
}
- st->reg_ldo = reg;
+ reg_ldo = reg;
return MPU_SUCCESS;
}
diff --git a/drivers/iio/imu/inv_icm20602/inv_icm20602_iio.h b/drivers/iio/imu/inv_icm20602/inv_icm20602_iio.h
index b369ae4..36f8e9c 100644
--- a/drivers/iio/imu/inv_icm20602/inv_icm20602_iio.h
+++ b/drivers/iio/imu/inv_icm20602/inv_icm20602_iio.h
@@ -41,8 +41,8 @@
#define INV20602_SMD_IRQ_TRIGGER 1
#endif
-#define ICM20602_LDO_VTG_MIN_UV 3300000
-#define ICM20602_LDO_VTG_MAX_UV 3300000
+#define ICM20602_LDO_VTG_MIN_UV 1800000
+#define ICM20602_LDO_VTG_MAX_UV 1800000
#define INV_ICM20602_TIME_STAMP_TOR 5
#define ICM20602_PACKAGE_SIZE 14
@@ -220,7 +220,6 @@
struct struct_icm20602_data *data_push;
enum inv_devices chip_type;
int gpio;
- struct regulator *reg_ldo;
DECLARE_KFIFO(timestamps, long long, TIMESTAMP_FIFO_SIZE);
};
diff --git a/drivers/input/misc/vl53l0x/stmvl53l0x_module.c b/drivers/input/misc/vl53l0x/stmvl53l0x_module.c
index 99cbc11..34508b2 100644
--- a/drivers/input/misc/vl53l0x/stmvl53l0x_module.c
+++ b/drivers/input/misc/vl53l0x/stmvl53l0x_module.c
@@ -963,8 +963,10 @@
struct vl_data *data = dev_get_drvdata(dev);
struct VL_RangingMeasurementData_t Measure;
+ if (data->enable_ps_sensor == 0)
+ return -ENODEV;
papi_func_tbl->PerformSingleRangingMeasurement(data, &Measure);
- return snprintf(buf, 4, "%d\n", Measure.RangeMilliMeter);
+ return snprintf(buf, 7, "%d\n", Measure.RangeMilliMeter);
}
/* DEVICE_ATTR(name,mode,show,store) */
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 6c4156a..ea37a9f 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -1279,6 +1279,18 @@
If unsure, say N.
+config TOUCHSCREEN_GT9XX_v28
+ bool "Goodix touchpanel GT9xx_v28 series"
+ depends on I2C
+ help
+ Say Y here if you have a Goodix GT9xx_v28 touchscreen.
+ Gt9xx controllers are multi touch controllers which can
+ report 5 touches at a time.
+
+ If unsure, say N.
+
+source "drivers/input/touchscreen/gt9xx_v2.8/Kconfig"
+
config TOUCHSCREEN_HIMAX_CHIPSET
bool "Himax touchpanel CHIPSET"
depends on I2C
@@ -1287,8 +1299,7 @@
HIMAX controllers are multi touch controllers which can
report 10 touches at a time.
- If unsure, say N.
+ If unsure, say N.
source "drivers/input/touchscreen/hxchipset/Kconfig"
-
endif
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index a5952ca..acd4045 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -104,4 +104,5 @@
obj-$(CONFIG_TOUCHSCREEN_COLIBRI_VF50) += colibri-vf50-ts.o
obj-$(CONFIG_TOUCHSCREEN_ROHM_BU21023) += rohm_bu21023.o
obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_touch/
+obj-$(CONFIG_TOUCHSCREEN_GT9XX_v28) += gt9xx_v2.8/
obj-$(CONFIG_TOUCHSCREEN_HIMAX_CHIPSET) += hxchipset/
diff --git a/drivers/input/touchscreen/gt9xx_v2.8/Kconfig b/drivers/input/touchscreen/gt9xx_v2.8/Kconfig
new file mode 100644
index 0000000..7046cc9
--- /dev/null
+++ b/drivers/input/touchscreen/gt9xx_v2.8/Kconfig
@@ -0,0 +1,36 @@
+#
+# Goodix GT9xx Touchscreen driver
+#
+config TOUCHSCREEN_GT9XX_v28
+ bool "Goodix touchpanel GT9xx series"
+ depends on I2C
+ help
+ Enable this for support Goodix GT9xx_v28 driver.
+
+ Say Y here if you have a Goodix GT9xx touchscreen
+ controller.
+
+ If unsure, say N.
+
+config TOUCHSCREEN_GT9XX_UPDATE
+ tristate "Goodix GT9xx touch controller auto update support"
+ depends on TOUCHSCREEN_GT9XX_v28
+ help
+ Enable this for support firmware update.
+
+ Say Y here if you want update touch controller
+ firmware.
+
+ If unsure, say N.
+
+config TOUCHSCREEN_GT9XX_TOOL
+ tristate "Goodix GT9xx Tools for debuging"
+ depends on TOUCHSCREEN_GT9XX_v28
+ help
+ This implement interface support for Goodix GT9xx
+ touchscreen debug.
+
+ Say Y here if you want to have a Android app debug interface
+ to your system.
+
+ If unsure, say N.
diff --git a/drivers/input/touchscreen/gt9xx_v2.8/Makefile b/drivers/input/touchscreen/gt9xx_v2.8/Makefile
new file mode 100644
index 0000000..6c1c404
--- /dev/null
+++ b/drivers/input/touchscreen/gt9xx_v2.8/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the Goodix gt9xx touchscreen driver.
+#
+#subdir-ccflags-y += -DDEBUG
+obj-$(CONFIG_TOUCHSCREEN_GT9XX_v28) += gt9xx.o
+obj-$(CONFIG_TOUCHSCREEN_GT9XX_UPDATE) += gt9xx_update.o
+obj-$(CONFIG_TOUCHSCREEN_GT9XX_TOOL) += goodix_tool.o
diff --git a/drivers/input/touchscreen/gt9xx_v2.8/goodix_tool.c b/drivers/input/touchscreen/gt9xx_v2.8/goodix_tool.c
new file mode 100644
index 0000000..7db5ae2
--- /dev/null
+++ b/drivers/input/touchscreen/gt9xx_v2.8/goodix_tool.c
@@ -0,0 +1,529 @@
+/*
+ * Goodix GT9xx touchscreen driver
+ *
+ * Copyright (C) 2016 - 2017 Goodix. Ltd.
+ *
+ * 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 a reference
+ * to you, when you are integrating the GOODiX's CTP IC into your system,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ */
+
+#include "gt9xx.h"
+
+#define DATA_LENGTH_UINT 512
+#define CMD_HEAD_LENGTH (sizeof(struct st_cmd_head) - sizeof(u8 *))
+static char procname[20] = {0};
+
+#pragma pack(1)
+struct st_cmd_head {
+ u8 wr; /*write read flag 0:R 1:W 2:PID 3:*/
+ u8 flag; /*0:no need flag/int 1: need flag 2:need int*/
+ u8 flag_addr[2]; /*flag address*/
+ u8 flag_val; /*flag val*/
+ u8 flag_relation; /*flag_val:flag 0:not equal 1:equal 2:> 3:<*/
+ u16 circle; /*polling cycle*/
+ u8 times; /*plling times*/
+ u8 retry; /*I2C retry times*/
+ u16 delay; /*delay before read or after write*/
+ u16 data_len; /*data length*/
+ u8 addr_len; /*address length*/
+ u8 addr[2]; /*address*/
+ u8 res[3]; /*reserved*/
+ u8 *data; }; /*data pointer*/
+#pragma pack()
+struct st_cmd_head cmd_head;
+
+static struct i2c_client *gt_client;
+static struct proc_dir_entry *goodix_proc_entry;
+
+static ssize_t goodix_tool_read(struct file *, char __user *, size_t, loff_t *);
+static ssize_t goodix_tool_write(struct file *, const char __user *,
+ size_t, loff_t *);
+static const struct file_operations gtp_proc_ops = {
+ .owner = THIS_MODULE,
+ .read = goodix_tool_read,
+ .write = goodix_tool_write,
+};
+
+/* static s32 goodix_tool_write(struct file *filp,
+ * const char __user *buff, unsigned long len, void *data);
+ */
+/*static s32 goodix_tool_read( char *page, char
+ **start, off_t off, int count, int *eof, void *data );
+ */
+static s32 (*tool_i2c_read)(u8 *, u16);
+static s32 (*tool_i2c_write)(u8 *, u16);
+
+static s32 DATA_LENGTH = (s32)0;
+static s8 IC_TYPE[16] = "GT9XX";
+
+static void tool_set_proc_name(char *procname)
+{
+ snprintf(procname, 20, "gmnode"); /* modify for moto */
+}
+
+static s32 tool_i2c_read_no_extra(u8 *buf, u16 len)
+{
+ s32 ret = -1;
+ s32 i = 0;
+ struct goodix_ts_data *ts = i2c_get_clientdata(i2c_connect_client);
+
+ for (i = 0; i < cmd_head.retry; i++) {
+ ret = gtp_i2c_read(ts->client, buf, len + GTP_ADDR_LENGTH);
+ if (ret > 0)
+ break;
+ }
+ return ret;
+}
+
+static s32 tool_i2c_write_no_extra(u8 *buf, u16 len)
+{
+ s32 ret = -1;
+ s32 i = 0;
+ struct goodix_ts_data *ts = i2c_get_clientdata(i2c_connect_client);
+
+ for (i = 0; i < cmd_head.retry; i++) {
+ ret = gtp_i2c_write(ts->client, buf, len);
+ if (ret > 0)
+ break;
+ }
+
+ return ret;
+}
+
+static s32 tool_i2c_read_with_extra(u8 *buf, u16 len)
+{
+ s32 ret = -1;
+ u8 pre[2] = {0x0f, 0xff};
+ u8 end[2] = {0x80, 0x00};
+
+ tool_i2c_write_no_extra(pre, 2);
+ ret = tool_i2c_read_no_extra(buf, len);
+ tool_i2c_write_no_extra(end, 2);
+
+ return ret;
+}
+
+static s32 tool_i2c_write_with_extra(u8 *buf, u16 len)
+{
+ s32 ret = -1;
+ u8 pre[2] = {0x0f, 0xff};
+ u8 end[2] = {0x80, 0x00};
+
+ tool_i2c_write_no_extra(pre, 2);
+ ret = tool_i2c_write_no_extra(buf, len);
+ tool_i2c_write_no_extra(end, 2);
+
+ return ret;
+}
+
+static void register_i2c_func(void)
+{
+ /* if (!strcmp(IC_TYPE, "GT818", 5)
+ * || !strcmp(IC_TYPE, "GT816", 5)
+ * || !strcmp(IC_TYPE, "GT811", 5)
+ * || !strcmp(IC_TYPE, "GT818F", 6)
+ * || !strcmp(IC_TYPE, "GT827", 5)
+ * || !strcmp(IC_TYPE,"GT828", 5)
+ * || !strcmp(IC_TYPE, "GT813", 5))
+ */
+ if (strcmp(IC_TYPE, "GT8110") &&
+ strcmp(IC_TYPE, "GT8105") &&
+ strcmp(IC_TYPE, "GT801") &&
+ strcmp(IC_TYPE, "GT800") &&
+ strcmp(IC_TYPE, "GT801PLUS") &&
+ strcmp(IC_TYPE, "GT811") &&
+ strcmp(IC_TYPE, "GTxxx") &&
+ strcmp(IC_TYPE, "GT9XX")) {
+ tool_i2c_read = tool_i2c_read_with_extra;
+ tool_i2c_write = tool_i2c_write_with_extra;
+ dev_dbg(>_client->dev, "I2C function: with pre and end cmd!");
+ } else {
+ tool_i2c_read = tool_i2c_read_no_extra;
+ tool_i2c_write = tool_i2c_write_no_extra;
+ dev_info(>_client->dev, "I2C function: without pre and end cmd!");
+ }
+}
+
+static void unregister_i2c_func(void)
+{
+ tool_i2c_read = NULL;
+ tool_i2c_write = NULL;
+ dev_info(>_client->dev, "I2C function: unregister i2c transfer function!");
+}
+
+s32 init_wr_node(struct i2c_client *client)
+{
+ s32 i;
+
+ gt_client = client;
+ memset(&cmd_head, 0, sizeof(cmd_head));
+ cmd_head.data = NULL;
+
+ i = 6;
+ while ((!cmd_head.data) && i) {
+ cmd_head.data = kzalloc(i * DATA_LENGTH_UINT, GFP_KERNEL);
+ if (cmd_head.data)
+ break;
+ i--;
+ }
+ if (i) {
+ DATA_LENGTH = i * DATA_LENGTH_UINT - GTP_ADDR_LENGTH;
+ dev_info(>_client->dev,
+ "Alloc memory size:%d.", DATA_LENGTH);
+ } else {
+ dev_err(>_client->dev, "Apply for memory failed.");
+ return FAIL;
+ }
+
+ cmd_head.addr_len = 2;
+ cmd_head.retry = 5;
+
+ register_i2c_func();
+
+ tool_set_proc_name(procname);
+ goodix_proc_entry = proc_create(procname, 0664, NULL, >p_proc_ops);
+ if (!goodix_proc_entry) {
+ dev_err(>_client->dev, "Couldn't create proc entry!");
+ return FAIL;
+ }
+
+ dev_info(>_client->dev, "Create proc entry success!");
+ return SUCCESS;
+}
+
+void uninit_wr_node(void)
+{
+ kfree(cmd_head.data);
+ cmd_head.data = NULL;
+ unregister_i2c_func();
+ remove_proc_entry(procname, NULL);
+}
+
+static u8 relation(u8 src, u8 dst, u8 rlt)
+{
+ u8 ret = 0;
+
+ switch (rlt) {
+ case 0:
+ ret = (src != dst) ? true : false;
+ break;
+
+ case 1:
+ ret = (src == dst) ? true : false;
+ dev_dbg(>_client->dev,
+ "equal:src:0x%02x dst:0x%02x ret:%d.",
+ src, dst, (s32)ret);
+ break;
+
+ case 2:
+ ret = (src > dst) ? true : false;
+ break;
+
+ case 3:
+ ret = (src < dst) ? true : false;
+ break;
+
+ case 4:
+ ret = (src & dst) ? true : false;
+ break;
+
+ case 5:
+ ret = (!(src | dst)) ? true : false;
+ break;
+
+ default:
+ ret = false;
+ break;
+ }
+
+ return ret;
+}
+
+/*******************************************************
+ * Function:
+ * Comfirm function.
+ * Input:
+ * None.
+ * Output:
+ * Return write length.
+ ********************************************************/
+static u8 comfirm(void)
+{
+ s32 i = 0;
+ u8 buf[32];
+
+ memcpy(buf, cmd_head.flag_addr, cmd_head.addr_len);
+
+ for (i = 0; i < cmd_head.times; i++) {
+ if (tool_i2c_read(buf, 1) <= 0) {
+ dev_err(>_client->dev, "Read flag data failed!");
+ return FAIL;
+ }
+ if (true == relation(buf[GTP_ADDR_LENGTH],
+ cmd_head.flag_val, cmd_head.flag_relation)) {
+ dev_dbg(>_client->dev, "value at flag addr:0x%02x.",
+ buf[GTP_ADDR_LENGTH]);
+ dev_dbg(>_client->dev, "flag value:0x%02x.",
+ cmd_head.flag_val);
+ break;
+ }
+
+ msleep(cmd_head.circle);
+ }
+
+ if (i >= cmd_head.times) {
+ dev_err(>_client->dev, "Can't get the continue flag!");
+ return FAIL;
+ }
+
+ return SUCCESS;
+}
+
+ssize_t goodix_tool_write(struct file *filp, const char __user *buff,
+ size_t len, loff_t *off)
+{
+ s32 ret = 0;
+ struct goodix_ts_data *ts = i2c_get_clientdata(gt_client);
+
+ ret = copy_from_user(&cmd_head, buff, CMD_HEAD_LENGTH);
+ if (ret) {
+ dev_err(>_client->dev, "copy_from_user failed.");
+ return -EPERM;
+ }
+
+ dev_dbg(>_client->dev, "[Operation]wr: %02X", cmd_head.wr);
+ dev_dbg(>_client->dev,
+ "[Flag]flag: %02X,addr: %02X%02X,value: %02X,relation: %02X",
+ cmd_head.flag, cmd_head.flag_addr[0],
+ cmd_head.flag_addr[1], cmd_head.flag_val,
+ cmd_head.flag_relation);
+ dev_dbg(>_client->dev,
+ "[Retry]circle: %d,times: %d,retry: %d, delay: %d",
+ (s32)cmd_head.circle,
+ (s32)cmd_head.times, (s32)cmd_head.retry,
+ (s32)cmd_head.delay);
+
+ if (cmd_head.wr == 1) {
+ if (cmd_head.data_len > DATA_LENGTH) {
+ dev_err(>_client->dev,
+ "Tool write failed data too long");
+ return -EPERM;
+ }
+ ret = copy_from_user(&cmd_head.data[GTP_ADDR_LENGTH],
+ &buff[CMD_HEAD_LENGTH],
+ cmd_head.data_len);
+ if (ret) {
+ dev_err(>_client->dev, "copy_from_user failed.");
+ return -EPERM;
+ }
+ memcpy(&cmd_head.data[GTP_ADDR_LENGTH - cmd_head.addr_len],
+ cmd_head.addr, cmd_head.addr_len);
+
+ GTP_DEBUG_ARRAY(cmd_head.data, cmd_head.data_len +
+ cmd_head.addr_len);
+
+ if (cmd_head.flag == 1) {
+ if (comfirm() == FAIL) {
+ dev_err(>_client->dev,
+ "[WRITE]Comfirm fail!");
+ return -EPERM;
+ }
+ } else if (cmd_head.flag == 2) {
+ /*Need interrupt!*/
+ }
+ if (tool_i2c_write(&cmd_head.data[GTP_ADDR_LENGTH -
+ cmd_head.addr_len], cmd_head.data_len +
+ cmd_head.addr_len) <= 0) {
+ dev_err(>_client->dev, "[WRITE]Write data failed!");
+ return -EPERM;
+ }
+
+ GTP_DEBUG_ARRAY(&cmd_head.data[GTP_ADDR_LENGTH -
+ cmd_head.addr_len],
+ cmd_head.data_len + cmd_head.addr_len);
+ if (cmd_head.delay)
+ msleep(cmd_head.delay);
+ } else if (cmd_head.wr == 3) {
+ if (cmd_head.data_len > DATA_LENGTH) {
+ dev_err(>_client->dev,
+ "Tool write failed data too long");
+ return -EPERM;
+ }
+ ret = copy_from_user(&cmd_head.data[0], &buff[CMD_HEAD_LENGTH],
+ cmd_head.data_len);
+ if (ret) {
+ dev_err(>_client->dev, "copy_from_user failed.");
+ return -EPERM;
+ }
+ memcpy(IC_TYPE, cmd_head.data, cmd_head.data_len);
+
+ register_i2c_func();
+ } else if (cmd_head.wr == 5) {
+ /*memcpy(IC_TYPE, cmd_head.data, cmd_head.data_len);*/
+ } else if (cmd_head.wr == 7) {/*disable irq!*/
+ gtp_work_control_enable(i2c_get_clientdata(gt_client), false);
+
+ if (ts->pdata->esd_protect)
+ gtp_esd_off(ts);
+ } else if (cmd_head.wr == 9) {/*enable irq!*/
+ gtp_work_control_enable(i2c_get_clientdata(gt_client), true);
+
+ if (ts->pdata->esd_protect)
+ gtp_esd_on(ts);
+ } else if (cmd_head.wr == 17) {
+ if (cmd_head.data_len > DATA_LENGTH) {
+ dev_err(>_client->dev,
+ "Tool write failed data too long");
+ return -EPERM;
+ }
+ ret = copy_from_user(&cmd_head.data[GTP_ADDR_LENGTH],
+ &buff[CMD_HEAD_LENGTH],
+ cmd_head.data_len);
+ if (ret) {
+ dev_dbg(>_client->dev, "copy_from_user failed.");
+ return -EPERM;
+ }
+ if (cmd_head.data[GTP_ADDR_LENGTH]) {
+ dev_info(>_client->dev, "gtp enter rawdiff.");
+ set_bit(RAW_DATA_MODE, &ts->flags);
+ } else {
+ clear_bit(RAW_DATA_MODE, &ts->flags);
+ dev_info(>_client->dev, "gtp leave rawdiff.");
+ }
+ } else if (cmd_head.wr == 19) {
+ /* add new command: reset guitar */
+ gtp_reset_guitar(gt_client, 20);
+ }
+#ifdef CONFIG_TOUCHSCREEN_GT9XX_UPDATE
+ else if (cmd_head.wr == 11) {/*Enter update mode!*/
+ if (gup_enter_update_mode(gt_client) == FAIL)
+ return -EPERM;
+ } else if (cmd_head.wr == 13) {/*Leave update mode!*/
+ gup_leave_update_mode(gt_client);
+ } else if (cmd_head.wr == 15) {/*Update firmware!*/
+ show_len = 0;
+ total_len = 0;
+ if (cmd_head.data_len > DATA_LENGTH) {
+ dev_err(>_client->dev,
+ "Tool write failed data too long");
+ return -EPERM;
+ }
+ memset(cmd_head.data, 0, DATA_LENGTH);
+ ret = copy_from_user(cmd_head.data,
+ &buff[CMD_HEAD_LENGTH],
+ cmd_head.data_len);
+ if (ret) {
+ dev_dbg(>_client->dev, "copy_from_user failed.");
+ return -EPERM;
+ }
+
+ if (gup_update_proc((void *)cmd_head.data) == FAIL)
+ return -EPERM;
+ }
+#endif
+
+ return len;
+}
+
+/*******************************************************
+ * Function:
+ * Goodix tool read function.
+ * Input:
+ * standard proc read function param.
+ * Output:
+ * Return read length.
+ ********************************************************/
+ssize_t goodix_tool_read(struct file *file, char __user *page,
+ size_t size, loff_t *ppos)
+{
+ s32 ret = 0;
+
+ if (*ppos) {
+ /* ADB call again
+ * dev_dbg(>_client->dev, "[HEAD]wr: %d", cmd_head.wr);
+ * dev_dbg(>_client->dev,
+ * "[PARAM]size: %d, *ppos: %d", size, (int)*ppos);
+ * dev_dbg(>_client->dev,
+ * "[TOOL_READ]ADB call again, return it.");
+ */
+ *ppos = 0;
+ return 0;
+ }
+
+ if (cmd_head.wr % 2) {
+ return -EPERM;
+ } else if (!cmd_head.wr) {
+ u16 len, data_len, loc, addr;
+
+ if (cmd_head.flag == 1) {
+ if (comfirm() == FAIL) {
+ dev_err(>_client->dev, "[READ]Comfirm fail!");
+ return -EPERM;
+ }
+ } else if (cmd_head.flag == 2) {
+ /*Need interrupt!*/
+ }
+
+ if (cmd_head.delay)
+ msleep(cmd_head.delay);
+
+ data_len = cmd_head.data_len;
+ addr = (cmd_head.addr[0] << 8) + cmd_head.addr[1];
+ loc = 0;
+
+ while (data_len > 0) {
+ len = data_len > DATA_LENGTH ? DATA_LENGTH : data_len;
+ cmd_head.data[0] = (addr >> 8) & 0xFF;
+ cmd_head.data[1] = (addr & 0xFF);
+ if (tool_i2c_read(cmd_head.data, len) <= 0) {
+ dev_err(>_client->dev, "[READ]Read data failed!");
+ return -EPERM;
+ }
+ ret = simple_read_from_buffer(&page[loc], size, ppos,
+ &cmd_head.data[GTP_ADDR_LENGTH], len);
+ if (ret < 0)
+ return ret;
+ loc += len;
+ addr += len;
+ data_len -= len;
+ }
+ return cmd_head.data_len;
+ } else if (cmd_head.wr == 2) {
+ ret = simple_read_from_buffer(page, size, ppos,
+ IC_TYPE, sizeof(IC_TYPE));
+ return ret;
+ }
+#ifdef CONFIG_TOUCHSCREEN_GT9XX_UPDATE
+ else if (cmd_head.wr == 4) {
+ u8 progress_buf[4];
+
+ progress_buf[0] = show_len >> 8;
+ progress_buf[1] = show_len & 0xff;
+ progress_buf[2] = total_len >> 8;
+ progress_buf[3] = total_len & 0xff;
+
+ ret = simple_read_from_buffer(page, size, ppos,
+ progress_buf, 4);
+ return ret;
+ }
+#endif
+ else if (cmd_head.wr == 6) {
+ /*Read error code!*/
+ } else if (cmd_head.wr == 8) { /*Read driver version*/
+ ret = simple_read_from_buffer(page, size, ppos,
+ GTP_DRIVER_VERSION,
+ strlen(GTP_DRIVER_VERSION));
+ return ret;
+ }
+
+ return -EPERM;
+}
diff --git a/drivers/input/touchscreen/gt9xx_v2.8/gt9xx.c b/drivers/input/touchscreen/gt9xx_v2.8/gt9xx.c
new file mode 100644
index 0000000..03328d0
--- /dev/null
+++ b/drivers/input/touchscreen/gt9xx_v2.8/gt9xx.c
@@ -0,0 +1,2678 @@
+/*
+ * Goodix GT9xx touchscreen driver
+ *
+ * Copyright (C) 2016 - 2017 Goodix. Ltd.
+ *
+ * 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 a reference
+ * to you, when you are integrating the GOODiX's CTP IC into your system,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ */
+
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/input/mt.h>
+#include "gt9xx.h"
+
+#define GOODIX_VTG_MIN_UV 2600000
+#define GOODIX_VTG_MAX_UV 3300000
+#define GOODIX_I2C_VTG_MIN_UV 1800000
+#define GOODIX_I2C_VTG_MAX_UV 1800000
+
+#define DELAY_FOR_DISCHARGING 35
+#define GOODIX_COORDS_ARR_SIZE 4
+#define PROP_NAME_SIZE 24
+#define I2C_MAX_TRANSFER_SIZE 255
+#define GTP_PEN_BUTTON1 BTN_STYLUS
+#define GTP_PEN_BUTTON2 BTN_STYLUS2
+
+static const char *goodix_ts_name = "goodix-ts";
+static const char *goodix_input_phys = "input/ts";
+struct i2c_client *i2c_connect_client;
+static struct proc_dir_entry *gtp_config_proc;
+
+enum doze {
+ DOZE_DISABLED = 0,
+ DOZE_ENABLED = 1,
+ DOZE_WAKEUP = 2,
+};
+
+static enum doze doze_status = DOZE_DISABLED;
+
+static int gtp_i2c_test(struct i2c_client *client);
+static int gtp_enter_doze(struct goodix_ts_data *ts);
+
+static int gtp_unregister_powermanager(struct goodix_ts_data *ts);
+static int gtp_register_powermanager(struct goodix_ts_data *ts);
+
+static int gtp_esd_init(struct goodix_ts_data *ts);
+static void gtp_esd_check_func(struct work_struct *);
+static int gtp_init_ext_watchdog(struct i2c_client *client);
+
+/*
+ * return: 2 - ok, < 0 - i2c transfer error
+ */
+int gtp_i2c_read(struct i2c_client *client, u8 *buf, int len)
+{
+ unsigned int transfer_length = 0;
+ unsigned int pos = 0, address = (buf[0] << 8) + buf[1];
+ unsigned char get_buf[64], addr_buf[2];
+ int retry, r = 2;
+ struct i2c_msg msgs[] = {
+ {
+ .addr = client->addr,
+ .flags = !I2C_M_RD,
+ .buf = &addr_buf[0],
+ .len = GTP_ADDR_LENGTH,
+ }, {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ }
+ };
+
+ len -= GTP_ADDR_LENGTH;
+ if (likely(len < sizeof(get_buf))) {
+ /* code optimize, use stack memory */
+ msgs[1].buf = &get_buf[0];
+ } else {
+ msgs[1].buf = kzalloc(len > I2C_MAX_TRANSFER_SIZE
+ ? I2C_MAX_TRANSFER_SIZE : len, GFP_KERNEL);
+ if (!msgs[1].buf)
+ return -ENOMEM;
+ }
+
+ while (pos != len) {
+ if (unlikely(len - pos > I2C_MAX_TRANSFER_SIZE))
+ transfer_length = I2C_MAX_TRANSFER_SIZE;
+ else
+ transfer_length = len - pos;
+ msgs[0].buf[0] = (address >> 8) & 0xFF;
+ msgs[0].buf[1] = address & 0xFF;
+ msgs[1].len = transfer_length;
+ for (retry = 0; retry < RETRY_MAX_TIMES; retry++) {
+ if (likely(i2c_transfer(client->adapter,
+ msgs, 2) == 2)) {
+ memcpy(&buf[2 + pos], msgs[1].buf,
+ transfer_length);
+ pos += transfer_length;
+ address += transfer_length;
+ break;
+ }
+ dev_dbg(&client->dev, "I2c read retry[%d]:0x%x\n",
+ retry + 1, address);
+ usleep_range(2000, 2100);
+ }
+ if (unlikely(retry == RETRY_MAX_TIMES)) {
+ dev_err(&client->dev,
+ "I2c read failed,dev:%02x,reg:%04x,size:%u\n",
+ client->addr, address, len);
+ r = -EAGAIN;
+ goto read_exit;
+ }
+ }
+read_exit:
+ if (len >= sizeof(get_buf))
+ kfree(msgs[1].buf);
+ return r;
+}
+
+/*******************************************************
+ * Function:
+ * Write data to the i2c slave device.
+ * Input:
+ * client: i2c device.
+ * buf[0~1]: write start address.
+ * buf[2~len-1]: data buffer
+ * len: GTP_ADDR_LENGTH + write bytes count
+ * Output:
+ * numbers of i2c_msgs to transfer:
+ * 1: succeed, otherwise: failed
+ *********************************************************/
+int gtp_i2c_write(struct i2c_client *client, u8 *buf, int len)
+
+{
+ unsigned int pos = 0, transfer_length = 0;
+ unsigned int address = (buf[0] << 8) + buf[1];
+ unsigned char put_buf[64];
+ int retry, r = 1;
+ struct i2c_msg msg = {
+ .addr = client->addr,
+ .flags = !I2C_M_RD,
+ };
+
+ if (likely(len < sizeof(put_buf))) {
+ /* code optimize,use stack memory*/
+ msg.buf = &put_buf[0];
+ } else {
+ msg.buf = kmalloc(len > I2C_MAX_TRANSFER_SIZE
+ ? I2C_MAX_TRANSFER_SIZE : len, GFP_KERNEL);
+ if (!msg.buf)
+ return -ENOMEM;
+ }
+
+ len -= GTP_ADDR_LENGTH;
+ while (pos != len) {
+ if (unlikely(len - pos > I2C_MAX_TRANSFER_SIZE
+ - GTP_ADDR_LENGTH))
+ transfer_length = I2C_MAX_TRANSFER_SIZE
+ - GTP_ADDR_LENGTH;
+ else
+ transfer_length = len - pos;
+ msg.buf[0] = (unsigned char)((address >> 8) & 0xFF);
+ msg.buf[1] = (unsigned char)(address & 0xFF);
+ msg.len = transfer_length + 2;
+ memcpy(&msg.buf[2], &buf[2 + pos], transfer_length);
+ for (retry = 0; retry < RETRY_MAX_TIMES; retry++) {
+ if (likely(i2c_transfer(client->adapter,
+ &msg, 1) == 1)) {
+ pos += transfer_length;
+ address += transfer_length;
+ break;
+ }
+ dev_dbg(&client->dev, "I2C write retry[%d]\n",
+ retry + 1);
+ usleep_range(2000, 2100);
+ }
+ if (unlikely(retry == RETRY_MAX_TIMES)) {
+ dev_err(&client->dev,
+ "I2c write failed,dev:%02x,reg:%04x,size:%u\n",
+ client->addr, address, len);
+ r = -EAGAIN;
+ goto write_exit;
+ }
+ }
+write_exit:
+ if (len + GTP_ADDR_LENGTH >= sizeof(put_buf))
+ kfree(msg.buf);
+ return r;
+}
+
+/*******************************************************
+ * Function:
+ * i2c read twice, compare the results
+ * Input:
+ * client: i2c device
+ * addr: operate address
+ * rxbuf: read data to store, if compare successful
+ * len: bytes to read
+ * Output:
+ * FAIL: read failed
+ * SUCCESS: read successful
+ *********************************************************/
+s32 gtp_i2c_read_dbl_check(struct i2c_client *client,
+ u16 addr, u8 *rxbuf, int len)
+{
+ u8 buf[16] = {0};
+ u8 confirm_buf[16] = {0};
+ u8 retry = 0;
+
+ if (len + 2 > sizeof(buf)) {
+ dev_warn(&client->dev,
+ "%s, only support length less then %zu\n",
+ __func__, sizeof(buf) - 2);
+ return FAIL;
+ }
+ while (retry++ < 3) {
+ memset(buf, 0xAA, 16);
+ buf[0] = (u8)(addr >> 8);
+ buf[1] = (u8)(addr & 0xFF);
+ gtp_i2c_read(client, buf, len + 2);
+
+ memset(confirm_buf, 0xAB, 16);
+ confirm_buf[0] = (u8)(addr >> 8);
+ confirm_buf[1] = (u8)(addr & 0xFF);
+ gtp_i2c_read(client, confirm_buf, len + 2);
+
+ if (!memcmp(buf, confirm_buf, len + 2)) {
+ memcpy(rxbuf, confirm_buf + 2, len);
+ return SUCCESS;
+ }
+ }
+ dev_err(&client->dev,
+ "I2C read 0x%04X, %d bytes, double check failed!\n",
+ addr, len);
+
+ return FAIL;
+}
+
+/*******************************************************
+ * Function:
+ * Send config.
+ * Input:
+ * client: i2c device.
+ * Output:
+ * result of i2c write operation.
+ * 1: succeed, otherwise
+ * 0: Not executed
+ * < 0: failed
+ *********************************************************/
+s32 gtp_send_cfg(struct i2c_client *client)
+{
+ s32 ret, i;
+ u8 check_sum;
+ s32 retry = 0;
+ struct goodix_ts_data *ts = i2c_get_clientdata(client);
+ struct goodix_config_data *cfg = &ts->pdata->config;
+
+ if (!cfg->length || !ts->pdata->driver_send_cfg) {
+ dev_info(&ts->client->dev,
+ "No config data or error occurred in panel_init\n");
+ return 0;
+ }
+
+ check_sum = 0;
+ for (i = GTP_ADDR_LENGTH; i < cfg->length; i++)
+ check_sum += cfg->data[i];
+ cfg->data[cfg->length] = (~check_sum) + 1;
+
+ dev_info(&ts->client->dev, "Driver send config\n");
+ for (retry = 0; retry < RETRY_MAX_TIMES; retry++) {
+ ret = gtp_i2c_write(client, cfg->data,
+ GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH);
+ if (ret > 0)
+ break;
+ }
+
+ return ret;
+}
+
+/*******************************************************
+ * Function:
+ * Control enable or disable of work thread.
+ * Input:
+ * ts: goodix i2c_client private data
+ * enable: enable var.
+ *********************************************************/
+void gtp_work_control_enable(struct goodix_ts_data *ts, bool enable)
+{
+ if (enable) {
+ set_bit(REPORT_THREAD_ENABLED, &ts->flags);
+ dev_dbg(&ts->client->dev, "Input report thread enabled!\n");
+ } else {
+ clear_bit(REPORT_THREAD_ENABLED, &ts->flags);
+ dev_dbg(&ts->client->dev, "Input report thread disabled!\n");
+ }
+}
+
+static int gtp_gesture_handler(struct goodix_ts_data *ts)
+{
+ u8 doze_buf[3] = {GTP_REG_DOZE_BUF >> 8, GTP_REG_DOZE_BUF & 0xFF};
+ int ret;
+
+ ret = gtp_i2c_read(ts->client, doze_buf, 3);
+ if (ret < 0) {
+ dev_err(&ts->client->dev, "Failed read doze buf");
+ return -EINVAL;
+ }
+
+ dev_dbg(&ts->client->dev, "0x814B = 0x%02X", doze_buf[2]);
+ if ((doze_buf[2] == 'a') || (doze_buf[2] == 'b') ||
+ (doze_buf[2] == 'c') || (doze_buf[2] == 'd') ||
+ (doze_buf[2] == 'e') || (doze_buf[2] == 'g') ||
+ (doze_buf[2] == 'h') || (doze_buf[2] == 'm') ||
+ (doze_buf[2] == 'o') || (doze_buf[2] == 'q') ||
+ (doze_buf[2] == 's') || (doze_buf[2] == 'v') ||
+ (doze_buf[2] == 'w') || (doze_buf[2] == 'y') ||
+ (doze_buf[2] == 'z') || (doze_buf[2] == 0x5E) ||
+ (doze_buf[2] == 0xAA) || (doze_buf[2] == 0xAB) ||
+ (doze_buf[2] == 0xBA) || (doze_buf[2] == 0xBB) ||
+ (doze_buf[2] == 0xCC)) {
+ doze_status = DOZE_WAKEUP;
+ input_report_key(ts->input_dev, KEY_POWER, 1);
+ input_sync(ts->input_dev);
+ input_report_key(ts->input_dev, KEY_POWER, 0);
+ input_sync(ts->input_dev);
+ /* clear 0x814B */
+ doze_buf[2] = 0x00;
+ gtp_i2c_write(ts->client, doze_buf, 3);
+ } else {
+ /* clear 0x814B */
+ doze_buf[2] = 0x00;
+ gtp_i2c_write(ts->client, doze_buf, 3);
+ gtp_enter_doze(ts);
+ }
+ return 0;
+}
+
+/*
+ * return touch state register value
+ * pen event id fixed with 9 and set tool type TOOL_PEN
+ *
+ */
+static u8 gtp_get_points(struct goodix_ts_data *ts,
+ struct goodix_point_t *points,
+ u8 *key_value)
+{
+ int ret;
+ int i;
+ u8 *coor_data = NULL;
+ u8 finger_state = 0;
+ u8 touch_num = 0;
+ u8 end_cmd[3] = { GTP_READ_COOR_ADDR >> 8,
+ GTP_READ_COOR_ADDR & 0xFF, 0 };
+ u8 point_data[2 + 1 + 8 * GTP_MAX_TOUCH_ID + 1] = {
+ GTP_READ_COOR_ADDR >> 8, GTP_READ_COOR_ADDR & 0xFF };
+
+ ret = gtp_i2c_read(ts->client, point_data, 12);
+ if (ret < 0) {
+ dev_err(&ts->client->dev,
+ "I2C transfer error. errno:%d\n ", ret);
+ return 0;
+ }
+ finger_state = point_data[GTP_ADDR_LENGTH];
+ if (finger_state == 0x00)
+ return 0;
+
+ touch_num = finger_state & 0x0f;
+ if ((finger_state & MASK_BIT_8) == 0 ||
+ touch_num > ts->pdata->max_touch_id) {
+ dev_err(&ts->client->dev,
+ "Invalid touch state: 0x%x", finger_state);
+ finger_state = 0;
+ goto exit_get_point;
+ }
+
+ if (touch_num > 1) {
+ u8 buf[8 * GTP_MAX_TOUCH_ID] = {
+ (GTP_READ_COOR_ADDR + 10) >> 8,
+ (GTP_READ_COOR_ADDR + 10) & 0xff };
+
+ ret = gtp_i2c_read(ts->client, buf, 2 + 8 * (touch_num - 1));
+ if (ret < 0) {
+ dev_err(&ts->client->dev, "I2C error. %d\n", ret);
+ finger_state = 0;
+ goto exit_get_point;
+ }
+ memcpy(&point_data[12], &buf[2], 8 * (touch_num - 1));
+ }
+
+ /* panel have touch key */
+ /* 0x20_UPKEY 0X10_DOWNKEY 0X40_ALLKEYDOWN */
+ *key_value = point_data[3 + 8 * touch_num];
+
+ memset(points, 0, sizeof(*points) * GTP_MAX_TOUCH_ID);
+ for (i = 0; i < touch_num; i++) {
+ coor_data = &point_data[i * 8 + 3];
+ points[i].id = coor_data[0];
+ points[i].x = coor_data[1] | (coor_data[2] << 8);
+ points[i].y = coor_data[3] | (coor_data[4] << 8);
+ points[i].w = coor_data[5] | (coor_data[6] << 8);
+ /* if pen hover points[].p must set to zero */
+ points[i].p = coor_data[5] | (coor_data[6] << 8);
+
+ if (ts->pdata->swap_x2y)
+ GTP_SWAP(points[i].x, points[i].y);
+
+ dev_dbg(&ts->client->dev, "[%d][%d %d %d]\n",
+ points[i].id, points[i].x, points[i].y, points[i].p);
+
+ /* pen device coordinate */
+ if (points[i].id & 0x80) {
+ points[i].tool_type = GTP_TOOL_PEN;
+ points[i].id = 10;
+ if (ts->pdata->pen_suppress_finger) {
+ points[0] = points[i];
+ memset(++points, 0, sizeof(*points) *
+ (GTP_MAX_TOUCH_ID - 1));
+ finger_state &= 0xf0;
+ finger_state |= 0x01;
+ break;
+ }
+ } else {
+ points[i].tool_type = GTP_TOOL_FINGER;
+ }
+ }
+
+exit_get_point:
+ if (!test_bit(RAW_DATA_MODE, &ts->flags)) {
+ ret = gtp_i2c_write(ts->client, end_cmd, 3);
+ if (ret < 0)
+ dev_info(&ts->client->dev, "I2C write end_cmd error!");
+ }
+ return finger_state;
+}
+
+static void gtp_type_a_report(struct goodix_ts_data *ts, u8 touch_num,
+ struct goodix_point_t *points)
+{
+ int i;
+ u16 cur_touch = 0;
+ static u16 pre_touch;
+ static u8 pre_pen_id;
+
+ if (touch_num)
+ input_report_key(ts->input_dev, BTN_TOUCH, 1);
+
+ for (i = 0; i < ts->pdata->max_touch_id; i++) {
+ if (touch_num && i == points->id) {
+ input_report_abs(ts->input_dev,
+ ABS_MT_TRACKING_ID, points->id);
+
+ if (points->tool_type == GTP_TOOL_PEN) {
+ input_report_key(ts->input_dev,
+ BTN_TOOL_PEN, true);
+ pre_pen_id = points->id;
+ } else {
+ input_report_key(ts->input_dev,
+ BTN_TOOL_FINGER, true);
+ }
+ input_report_abs(ts->input_dev, ABS_MT_POSITION_X,
+ points->x);
+ input_report_abs(ts->input_dev, ABS_MT_POSITION_Y,
+ points->y);
+ input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,
+ points->w);
+ input_report_abs(ts->input_dev, ABS_MT_PRESSURE,
+ points->p);
+ input_mt_sync(ts->input_dev);
+
+ cur_touch |= 0x01 << points->id;
+ points++;
+ } else if (pre_touch & 0x01 << i) {
+ if (pre_pen_id == i) {
+ input_report_key(ts->input_dev,
+ BTN_TOOL_PEN, false);
+/* valid id will < 10, so id to 0xff to indicate a invalid state */
+ pre_pen_id = 0xff;
+ } else {
+ input_report_key(ts->input_dev,
+ BTN_TOOL_FINGER, false);
+ }
+ }
+ }
+
+ pre_touch = cur_touch;
+ if (!pre_touch) {
+ input_mt_sync(ts->input_dev);
+ input_report_key(ts->input_dev, BTN_TOUCH, 0);
+ }
+ input_sync(ts->input_dev);
+}
+
+static void gtp_mt_slot_report(struct goodix_ts_data *ts, u8 touch_num,
+ struct goodix_point_t *points)
+{
+ int i;
+ u16 cur_touch = 0;
+ static u16 pre_touch;
+ static u8 pre_pen_id;
+
+ for (i = 0; i < ts->pdata->max_touch_id; i++) {
+ if (touch_num && i == points->id) {
+ input_mt_slot(ts->input_dev, points->id);
+
+ if (points->tool_type == GTP_TOOL_PEN) {
+ input_mt_report_slot_state(ts->input_dev,
+ MT_TOOL_PEN, true);
+ pre_pen_id = points->id;
+ } else {
+ input_mt_report_slot_state(ts->input_dev,
+ MT_TOOL_FINGER, true);
+ }
+ input_report_abs(ts->input_dev, ABS_MT_POSITION_X,
+ points->x);
+ input_report_abs(ts->input_dev, ABS_MT_POSITION_Y,
+ points->y);
+ input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,
+ points->w);
+ input_report_abs(ts->input_dev, ABS_MT_PRESSURE,
+ points->p);
+
+ cur_touch |= 0x01 << points->id;
+ points++;
+ } else if (pre_touch & 0x01 << i) {
+ input_mt_slot(ts->input_dev, i);
+ if (pre_pen_id == i) {
+ input_mt_report_slot_state(ts->input_dev,
+ MT_TOOL_PEN, false);
+ /* valid id will < 10, so set id to 0xff to
+ * indicate a invalid state
+ */
+ pre_pen_id = 0xff;
+ } else {
+ input_mt_report_slot_state(ts->input_dev,
+ MT_TOOL_FINGER, false);
+ }
+ }
+ }
+
+ pre_touch = cur_touch;
+ /* report BTN_TOUCH event */
+ input_mt_sync_frame(ts->input_dev);
+ input_sync(ts->input_dev);
+}
+
+/*******************************************************
+ * Function:
+ * Goodix touchscreen sensor report function
+ * Input:
+ * ts: goodix tp private data
+ * Output:
+ * None.
+ *********************************************************/
+static void gtp_work_func(struct goodix_ts_data *ts)
+{
+ u8 point_state = 0;
+ u8 key_value = 0;
+ s32 i = 0;
+ s32 ret = -1;
+ static u8 pre_key;
+ struct goodix_point_t points[GTP_MAX_TOUCH_ID];
+
+ if (test_bit(PANEL_RESETTING, &ts->flags))
+ return;
+ if (!test_bit(REPORT_THREAD_ENABLED, &ts->flags))
+ return;
+
+ /* gesture event */
+ if (ts->pdata->slide_wakeup && test_bit(DOZE_MODE, &ts->flags)) {
+ ret = gtp_gesture_handler(ts);
+ if (ret)
+ dev_err(&ts->client->dev,
+ "Failed handler gesture event %d\n", ret);
+ return;
+ }
+
+ point_state = gtp_get_points(ts, points, &key_value);
+ if (!point_state) {
+ dev_dbg(&ts->client->dev, "Invalid finger points\n");
+ return;
+ }
+
+ /* touch key event */
+ if (key_value & 0xf0 || pre_key & 0xf0) {
+ /* pen button */
+ switch (key_value) {
+ case 0x40:
+ input_report_key(ts->input_dev, GTP_PEN_BUTTON1, 1);
+ input_report_key(ts->input_dev, GTP_PEN_BUTTON2, 1);
+ break;
+ case 0x10:
+ input_report_key(ts->input_dev, GTP_PEN_BUTTON1, 1);
+ input_report_key(ts->input_dev, GTP_PEN_BUTTON2, 0);
+ dev_dbg(&ts->client->dev, "pen button1 down\n");
+ break;
+ case 0x20:
+ input_report_key(ts->input_dev, GTP_PEN_BUTTON1, 0);
+ input_report_key(ts->input_dev, GTP_PEN_BUTTON2, 1);
+ break;
+ default:
+ input_report_key(ts->input_dev, GTP_PEN_BUTTON1, 0);
+ input_report_key(ts->input_dev, GTP_PEN_BUTTON2, 0);
+ dev_dbg(&ts->client->dev, "button1 up\n");
+ break;
+ }
+ input_sync(ts->input_dev);
+ pre_key = key_value;
+ } else if (key_value & 0x0f || pre_key & 0x0f) {
+ /* panel key */
+ for (i = 0; i < ts->pdata->key_nums; i++) {
+ if ((pre_key | key_value) & (0x01 << i))
+ input_report_key(ts->input_dev,
+ ts->pdata->key_map[i],
+ key_value & (0x01 << i));
+ }
+ input_sync(ts->input_dev);
+ pre_key = key_value;
+ }
+
+ if (!ts->pdata->type_a_report)
+ gtp_mt_slot_report(ts, point_state & 0x0f, points);
+ else
+ gtp_type_a_report(ts, point_state & 0x0f, points);
+}
+
+/*******************************************************
+ * Function:
+ * Timer interrupt service routine for polling mode.
+ * Input:
+ * timer: timer struct pointer
+ * Output:
+ * Timer work mode.
+ * HRTIMER_NORESTART:
+ * no restart mode
+ *********************************************************/
+static enum hrtimer_restart gtp_timer_handler(struct hrtimer *timer)
+{
+ struct goodix_ts_data *ts =
+ container_of(timer, struct goodix_ts_data, timer);
+
+ gtp_work_func(ts);
+ hrtimer_start(&ts->timer, ktime_set(0, (GTP_POLL_TIME + 6) * 1000000),
+ HRTIMER_MODE_REL);
+
+ return HRTIMER_NORESTART;
+}
+
+static irqreturn_t gtp_irq_handler(int irq, void *dev_id)
+{
+ struct goodix_ts_data *ts = dev_id;
+
+ gtp_work_func(ts);
+ return IRQ_HANDLED;
+}
+
+void gtp_int_output(struct goodix_ts_data *ts, int level)
+{
+ if (!ts->pdata->int_sync)
+ return;
+
+ if (level == 0) {
+ if (ts->pinctrl.pinctrl)
+ pinctrl_select_state(ts->pinctrl.pinctrl,
+ ts->pinctrl.int_out_low);
+ else if (gpio_is_valid(ts->pdata->irq_gpio))
+ gpio_direction_output(ts->pdata->irq_gpio, 0);
+ else
+ dev_err(&ts->client->dev,
+ "Failed set int pin output low\n");
+ } else {
+ if (ts->pinctrl.pinctrl)
+ pinctrl_select_state(ts->pinctrl.pinctrl,
+ ts->pinctrl.int_out_high);
+ else if (gpio_is_valid(ts->pdata->irq_gpio))
+ gpio_direction_output(ts->pdata->irq_gpio, 1);
+ else
+ dev_err(&ts->client->dev,
+ "Failed set int pin output high\n");
+ }
+}
+
+void gtp_int_sync(struct goodix_ts_data *ts, s32 ms)
+{
+ if (!ts->pdata->int_sync)
+ return;
+
+ if (ts->pinctrl.pinctrl) {
+ gtp_int_output(ts, 0);
+ msleep(ms);
+ pinctrl_select_state(ts->pinctrl.pinctrl,
+ ts->pinctrl.int_input);
+ } else if (gpio_is_valid(ts->pdata->irq_gpio)) {
+ gpio_direction_output(ts->pdata->irq_gpio, 0);
+ msleep(ms);
+ gpio_direction_input(ts->pdata->irq_gpio);
+ } else {
+ dev_err(&ts->client->dev, "Failed sync int pin\n");
+ }
+}
+
+void gtp_rst_output(struct goodix_ts_data *ts, int level)
+{
+ if (level == 0) {
+ if (ts->pinctrl.pinctrl)
+ pinctrl_select_state(ts->pinctrl.pinctrl,
+ ts->pinctrl.rst_out_low);
+ else if (gpio_is_valid(ts->pdata->rst_gpio))
+ gpio_direction_output(ts->pdata->rst_gpio, 0);
+ else
+ dev_err(&ts->client->dev,
+ "Failed set rst pin output low\n");
+ } else {
+ if (ts->pinctrl.pinctrl)
+ pinctrl_select_state(ts->pinctrl.pinctrl,
+ ts->pinctrl.rst_out_high);
+ else if (gpio_is_valid(ts->pdata->rst_gpio))
+ gpio_direction_output(ts->pdata->rst_gpio, 1);
+ else
+ dev_err(&ts->client->dev,
+ "Failed set rst pin output high\n");
+ }
+}
+
+void gtp_rst_input(struct goodix_ts_data *ts)
+{
+ if (ts->pinctrl.pinctrl)
+ pinctrl_select_state(ts->pinctrl.pinctrl,
+ ts->pinctrl.rst_input);
+ else if (gpio_is_valid(ts->pdata->rst_gpio))
+ gpio_direction_input(ts->pdata->rst_gpio);
+ else
+ dev_err(&ts->client->dev,
+ "Failed set rst pin input\n");
+}
+
+/*******************************************************
+ * Function:
+ * Reset chip. Control the reset pin and int-pin(if
+ * defined),
+ * Input:
+ * client: i2c device.
+ * ms: reset time in millisecond
+ * Output:
+ * None.
+ *******************************************************/
+void gtp_reset_guitar(struct i2c_client *client, s32 ms)
+{
+ struct goodix_ts_data *ts = i2c_get_clientdata(client);
+
+ dev_info(&client->dev, "Guitar reset");
+ set_bit(PANEL_RESETTING, &ts->flags);
+ if (!gpio_is_valid(ts->pdata->rst_gpio)) {
+ dev_warn(&client->dev, "reset failed no valid reset gpio");
+ return;
+ }
+
+ gtp_rst_output(ts, 0);
+ usleep_range(ms * 1000, ms * 1000 + 100); /* T2: > 10ms */
+
+ gtp_int_output(ts, client->addr == 0x14);
+
+ usleep_range(2000, 3000); /* T3: > 100us (2ms)*/
+ gtp_rst_output(ts, 1);
+
+ usleep_range(6000, 7000); /* T4: > 5ms */
+ gtp_rst_input(ts);
+
+ gtp_int_sync(ts, 50);
+ if (ts->pdata->esd_protect)
+ gtp_init_ext_watchdog(client);
+
+ clear_bit(PANEL_RESETTING, &ts->flags);
+}
+
+/*******************************************************
+ * Function:
+ * Enter doze mode for sliding wakeup.
+ * Input:
+ * ts: goodix tp private data
+ * Output:
+ * 1: succeed, otherwise failed
+ *******************************************************/
+static int gtp_enter_doze(struct goodix_ts_data *ts)
+{
+ int ret = -1;
+ int retry = 0;
+ u8 i2c_control_buf[3] = { (u8)(GTP_REG_COMMAND >> 8),
+ (u8)GTP_REG_COMMAND, 8 };
+
+ /* resend doze command
+ * if (test_and_set_bit(DOZE_MODE, &ts->flags)) {
+ * dev_info(&ts->client->dev, "Already in doze mode\n");
+ * return SUCCESS;
+ * }
+ */
+ set_bit(DOZE_MODE, &ts->flags);
+ dev_dbg(&ts->client->dev, "Entering gesture mode.");
+ while (retry++ < 5) {
+ i2c_control_buf[0] = (u8)(GTP_REG_COMMAND_CHECK >> 8);
+ i2c_control_buf[1] = (u8)GTP_REG_COMMAND_CHECK;
+ ret = gtp_i2c_write(ts->client, i2c_control_buf, 3);
+ if (ret < 0) {
+ dev_dbg(&ts->client->dev,
+ "failed to set doze flag into 0x8046, %d\n",
+ retry);
+ continue;
+ }
+ i2c_control_buf[0] = (u8)(GTP_REG_COMMAND >> 8);
+ i2c_control_buf[1] = (u8)GTP_REG_COMMAND;
+ ret = gtp_i2c_write(ts->client, i2c_control_buf, 3);
+ if (ret > 0) {
+ dev_dbg(&ts->client->dev, "Gesture mode enabled\n");
+ return ret;
+ }
+ usleep_range(10000, 11000);
+ }
+
+ dev_err(&ts->client->dev, "Failed enter doze mode\n");
+ clear_bit(DOZE_MODE, &ts->flags);
+ return ret;
+}
+
+static s8 gtp_enter_sleep(struct goodix_ts_data *ts)
+{
+ s8 ret = -1;
+ s8 retry = 0;
+ u8 i2c_control_buf[3] = { (u8)(GTP_REG_COMMAND >> 8),
+ (u8)GTP_REG_COMMAND, 5 };
+
+ gtp_int_output(ts, 0);
+ usleep_range(5000, 6000);
+
+ while (retry++ < 5) {
+ ret = gtp_i2c_write(ts->client, i2c_control_buf, 3);
+ if (ret > 0) {
+ dev_info(&ts->client->dev, "Enter sleep mode\n");
+
+ return ret;
+ }
+ usleep_range(10000, 11000);
+ }
+ dev_err(&ts->client->dev, "Failed send sleep cmd\n");
+
+ return ret;
+}
+
+static int gtp_wakeup_sleep(struct goodix_ts_data *ts)
+{
+ u8 retry = 0;
+ int ret = -1;
+
+ while (retry++ < 10) {
+ gtp_int_output(ts, 1);
+ usleep_range(5000, 6000);
+
+ ret = gtp_i2c_test(ts->client);
+ if (!ret) {
+ dev_dbg(&ts->client->dev, "Success wakeup sleep\n");
+
+ gtp_int_sync(ts, 25);
+ if (ts->pdata->esd_protect)
+ gtp_init_ext_watchdog(ts->client);
+
+ return ret;
+ }
+ gtp_reset_guitar(ts->client, 20);
+ }
+
+ dev_err(&ts->client->dev, "Failed wakeup from sleep mode\n");
+ return -EINVAL;
+}
+
+static int gtp_find_valid_cfg_data(struct goodix_ts_data *ts)
+{
+ int ret = -1;
+ u8 sensor_id = 0;
+ struct goodix_config_data *cfg = &ts->pdata->config;
+
+ /* if defined CONFIG_OF, parse config data from dtsi
+ * else parse config data form header file.
+ */
+ cfg->length = 0;
+
+#ifndef CONFIG_OF
+ u8 cfg_info_group0[] = CTP_CFG_GROUP0;
+ u8 cfg_info_group1[] = CTP_CFG_GROUP1;
+ u8 cfg_info_group2[] = CTP_CFG_GROUP2;
+ u8 cfg_info_group3[] = CTP_CFG_GROUP3;
+ u8 cfg_info_group4[] = CTP_CFG_GROUP4;
+ u8 cfg_info_group5[] = CTP_CFG_GROUP5;
+
+ u8 *send_cfg_buf[] = { cfg_info_group0, cfg_info_group1,
+ cfg_info_group2, cfg_info_group3,
+ cfg_info_group4, cfg_info_group5 };
+ u8 cfg_info_len[] = { CFG_GROUP_LEN(cfg_info_group0),
+ CFG_GROUP_LEN(cfg_info_group1),
+ CFG_GROUP_LEN(cfg_info_group2),
+ CFG_GROUP_LEN(cfg_info_group3),
+ CFG_GROUP_LEN(cfg_info_group4),
+ CFG_GROUP_LEN(cfg_info_group5)};
+
+ dev_dbg(&ts->client->dev,
+ "Config Groups\' Lengths: %d, %d, %d, %d, %d, %d",
+ cfg_info_len[0], cfg_info_len[1], cfg_info_len[2],
+ cfg_info_len[3], cfg_info_len[4], cfg_info_len[5]);
+#endif
+
+ /* read sensor id */
+ ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_SENSOR_ID,
+ &sensor_id, 1);
+ if (ret != SUCCESS || sensor_id >= 0x06) {
+ dev_err(&ts->client->dev,
+ "Failed get valid sensor_id(0x%02X), No Config Sent\n",
+ sensor_id);
+ return -EINVAL;
+ }
+
+ dev_dbg(&ts->client->dev, "Sensor_ID: %d", sensor_id);
+ /* parse config data */
+#ifdef CONFIG_OF
+ dev_dbg(&ts->client->dev, "Get config data from device tree\n");
+ ret = gtp_parse_dt_cfg(&ts->client->dev,
+ &cfg->data[GTP_ADDR_LENGTH],
+ &cfg->length, sensor_id);
+ if (ret < 0) {
+ dev_err(&ts->client->dev,
+ "Failed to parse config data form device tree\n");
+ cfg->length = 0;
+ return -EPERM;
+ }
+#else
+ dev_dbg(&ts->client->dev, "Get config data from header file\n");
+ if ((!cfg_info_len[1]) && (!cfg_info_len[2]) &&
+ (!cfg_info_len[3]) && (!cfg_info_len[4]) &&
+ (!cfg_info_len[5])) {
+ sensor_id = 0;
+ }
+ cfg->length = cfg_info_len[sensor_id];
+ memset(&cfg->data[GTP_ADDR_LENGTH], 0, GTP_CONFIG_MAX_LENGTH);
+ memcpy(&cfg->data[GTP_ADDR_LENGTH], send_cfg_buf[sensor_id],
+ cfg->length);
+#endif
+
+ if (cfg->length < GTP_CONFIG_MIN_LENGTH) {
+ dev_err(&ts->client->dev,
+ "Failed get valid config data with sensor id %d\n",
+ sensor_id);
+ cfg->length = 0;
+ return -EPERM;
+ }
+
+ dev_info(&ts->client->dev, "Config group%d used,length: %d\n",
+ sensor_id, cfg->length);
+
+ return 0;
+}
+
+/*******************************************************
+ * Function:
+ * Get valid config data from dts or .h file.
+ * Read firmware version info and judge firmware
+ * working state
+ * Input:
+ * ts: goodix private data
+ * Output:
+ * Executive outcomes.
+ * 0: succeed, otherwise: failed
+ *******************************************************/
+static s32 gtp_init_panel(struct goodix_ts_data *ts)
+{
+ s32 ret = -1;
+ u8 opr_buf[16] = {0};
+ u8 drv_cfg_version = 0;
+ u8 flash_cfg_version = 0;
+ struct goodix_config_data *cfg = &ts->pdata->config;
+
+ if (!ts->pdata->driver_send_cfg) {
+ dev_info(&ts->client->dev, "Driver set not send config\n");
+ cfg->length = GTP_CONFIG_MAX_LENGTH;
+ ret = gtp_i2c_read(ts->client,
+ cfg->data, cfg->length +
+ GTP_ADDR_LENGTH);
+ if (ret < 0)
+ dev_err(&ts->client->dev, "Read origin Config Failed\n");
+
+ return 0;
+ }
+
+ gtp_find_valid_cfg_data(ts);
+
+ /* check firmware */
+ ret = gtp_i2c_read_dbl_check(ts->client, 0x41E4, opr_buf, 1);
+ if (ret == SUCCESS) {
+ if (opr_buf[0] != 0xBE) {
+ set_bit(FW_ERROR, &ts->flags);
+ dev_err(&ts->client->dev,
+ "Firmware error, no config sent!\n");
+ return -EINVAL;
+ }
+ }
+
+ ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_CONFIG_DATA,
+ &opr_buf[0], 1);
+ if (ret == SUCCESS) {
+ dev_dbg(&ts->client->dev,
+ "Config Version: %d; IC Config Version: %d\n",
+ cfg->data[GTP_ADDR_LENGTH], opr_buf[0]);
+ flash_cfg_version = opr_buf[0];
+ drv_cfg_version = cfg->data[GTP_ADDR_LENGTH];
+
+ if (flash_cfg_version < 120 &&
+ flash_cfg_version > drv_cfg_version)
+ cfg->data[GTP_ADDR_LENGTH] = 0x00;
+ } else {
+ dev_err(&ts->client->dev,
+ "Failed to get ic config version!No config sent\n");
+ return -EPERM;
+ }
+
+ ret = gtp_send_cfg(ts->client);
+ if (ret < 0)
+ dev_err(&ts->client->dev, "Send config error\n");
+ else
+ usleep_range(10000, 11000); /* 10 ms */
+
+ /* restore config version */
+ cfg->data[GTP_ADDR_LENGTH] = drv_cfg_version;
+
+ return 0;
+}
+
+static ssize_t gtp_config_read_proc(struct file *file, char __user *page,
+ size_t size, loff_t *ppos)
+{
+ int i, ret;
+ char *ptr;
+ size_t data_len = 0;
+ char temp_data[GTP_CONFIG_MAX_LENGTH + 2] = {
+ (u8)(GTP_REG_CONFIG_DATA >> 8),
+ (u8)GTP_REG_CONFIG_DATA };
+ struct goodix_ts_data *ts = i2c_get_clientdata(i2c_connect_client);
+ struct goodix_config_data *cfg = &ts->pdata->config;
+
+ ptr = kzalloc(4096, GFP_KERNEL);
+ if (!ptr)
+ return -ENOMEM;
+
+ data_len += snprintf(ptr + data_len, 4096 - data_len,
+ "====init value====\n");
+ for (i = 0 ; i < GTP_CONFIG_MAX_LENGTH ; i++) {
+ data_len += snprintf(ptr + data_len, 4096 - data_len,
+ "0x%02X ", cfg->data[i + 2]);
+
+ if (i % 8 == 7)
+ data_len += snprintf(ptr + data_len,
+ 4096 - data_len, "\n");
+ }
+ data_len += snprintf(ptr + data_len, 4096 - data_len, "\n");
+
+ data_len += snprintf(ptr + data_len, 4096 - data_len,
+ "====real value====\n");
+ ret = gtp_i2c_read(i2c_connect_client, temp_data,
+ GTP_CONFIG_MAX_LENGTH + 2);
+ if (ret < 0) {
+ data_len += snprintf(ptr + data_len, 4096 - data_len,
+ "Failed read real config data\n");
+ } else {
+ for (i = 0; i < GTP_CONFIG_MAX_LENGTH; i++) {
+ data_len += snprintf(ptr + data_len, 4096 - data_len,
+ "0x%02X ", temp_data[i + 2]);
+
+ if (i % 8 == 7)
+ data_len += snprintf(ptr + data_len,
+ 4096 - data_len, "\n");
+ }
+ }
+
+ data_len = simple_read_from_buffer(page, size, ppos, ptr, data_len);
+ kfree(ptr);
+ ptr = NULL;
+ return data_len;
+}
+
+int gtp_ascii_to_array(const u8 *src_buf, int src_len, u8 *dst_buf)
+{
+ int i, ret;
+ int cfg_len = 0;
+ long val;
+ char temp_buf[5];
+
+ for (i = 0; i < src_len;) {
+ if (src_buf[i] == ' ' || src_buf[i] == '\r' ||
+ src_buf[i] == '\n') {
+ i++;
+ continue;
+ }
+
+ temp_buf[0] = src_buf[i];
+ temp_buf[1] = src_buf[i + 1];
+ temp_buf[2] = src_buf[i + 2];
+ temp_buf[3] = src_buf[i + 3];
+ temp_buf[4] = '\0';
+ if (!kstrtol(temp_buf, 16, &val)) {
+ if (cfg_len < GTP_CONFIG_MAX_LENGTH) {
+ dst_buf[cfg_len++] = val & 0xFF;
+ i += 5;
+ } else {
+ ret = -2;
+ goto convert_failed;
+ }
+ } else {
+ ret = -3;
+ goto convert_failed;
+ }
+ }
+ return cfg_len;
+
+convert_failed:
+ return ret;
+}
+
+static ssize_t gtp_config_write_proc(struct file *filp,
+ const char __user *buffer,
+ size_t count, loff_t *off)
+{
+ u8 *temp_buf;
+ u8 *file_config;
+ int file_cfg_len;
+ s32 ret = 0, i;
+ struct goodix_ts_data *ts = i2c_get_clientdata(i2c_connect_client);
+
+ dev_dbg(&ts->client->dev, "write count %zu\n", count);
+
+ if (count > PAGE_SIZE) {
+ dev_err(&ts->client->dev, "config to long %zu\n", count);
+ return -EFAULT;
+ }
+
+ temp_buf = kzalloc(count, GFP_KERNEL);
+ if (!temp_buf)
+ return -ENOMEM;
+
+ file_config = kzalloc(GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH,
+ GFP_KERNEL);
+ if (!file_config) {
+ kfree(temp_buf);
+ return -ENOMEM;
+ }
+ file_config[0] = GTP_REG_CONFIG_DATA >> 8;
+ file_config[1] = GTP_REG_CONFIG_DATA & 0xff;
+
+ if (copy_from_user(temp_buf, buffer, count)) {
+ dev_err(&ts->client->dev, "Failed copy from user\n");
+ ret = -EFAULT;
+ goto send_cfg_err;
+ }
+
+ file_cfg_len = gtp_ascii_to_array(temp_buf, (int)count,
+ &file_config[GTP_ADDR_LENGTH]);
+ if (file_cfg_len < 0) {
+ dev_err(&ts->client->dev, "failed covert ascii to hex");
+ ret = -EFAULT;
+ goto send_cfg_err;
+ }
+
+ GTP_DEBUG_ARRAY(file_config + GTP_ADDR_LENGTH, file_cfg_len);
+
+ i = 0;
+ while (i++ < 5) {
+ ret = gtp_i2c_write(ts->client, file_config, file_cfg_len + 2);
+ if (ret > 0) {
+ dev_info(&ts->client->dev, "Send config SUCCESS.");
+ break;
+ }
+ dev_err(&ts->client->dev, "Send config i2c error.");
+ ret = -EFAULT;
+ goto send_cfg_err;
+ }
+
+ ret = count;
+send_cfg_err:
+ kfree(temp_buf);
+ kfree(file_config);
+ return ret;
+}
+
+static const struct file_operations config_proc_ops = {
+ .owner = THIS_MODULE,
+ .read = gtp_config_read_proc,
+ .write = gtp_config_write_proc,
+};
+
+static ssize_t gtp_workmode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ size_t data_len = 0;
+ struct goodix_ts_data *data = dev_get_drvdata(dev);
+
+ if (test_bit(DOZE_MODE, &data->flags))
+ data_len = scnprintf(buf, PAGE_SIZE, "%s\n",
+ "doze_mode");
+ else if (test_bit(SLEEP_MODE, &data->flags))
+ data_len = scnprintf(buf, PAGE_SIZE, "%s\n",
+ "sleep_mode");
+ else
+ data_len = scnprintf(buf, PAGE_SIZE, "%s\n",
+ "normal_mode");
+
+ return data_len;
+}
+static DEVICE_ATTR(workmode, 0444, gtp_workmode_show, NULL);
+
+#ifdef CONFIG_TOUCHSCREEN_GT9XX_UPDATE
+#define FW_NAME_MAX_LEN 80
+static ssize_t gtp_dofwupdate_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct goodix_ts_data *ts = dev_get_drvdata(dev);
+ char update_file_name[FW_NAME_MAX_LEN];
+ int retval;
+
+ if (count > FW_NAME_MAX_LEN) {
+ dev_info(&ts->client->dev, "FW filename is too long\n");
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ strlcpy(update_file_name, buf, count);
+
+ ts->force_update = true;
+ retval = gup_update_proc(update_file_name);
+ if (retval == FAIL)
+ dev_err(&ts->client->dev, "Fail to update GTP firmware.\n");
+ else
+ dev_info(&ts->client->dev, "Update success\n");
+
+ return count;
+
+exit:
+ return retval;
+}
+static DEVICE_ATTR(dofwupdate, 0664, NULL, gtp_dofwupdate_store);
+#endif
+
+static ssize_t gtp_productinfo_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct goodix_ts_data *data = dev_get_drvdata(dev);
+ struct goodix_fw_info *fw_info = &data->fw_info;
+
+ return scnprintf(buf, PAGE_SIZE, "GT%s_%x_%d\n",
+ fw_info->pid, fw_info->version, fw_info->sensor_id);
+}
+static DEVICE_ATTR(productinfo, 0444, gtp_productinfo_show, NULL);
+
+static ssize_t gtp_drv_irq_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long value = 0;
+ int err = 0;
+ struct goodix_ts_data *data = dev_get_drvdata(dev);
+
+ err = kstrtoul(buf, 10, &value);
+ if (err < 0) {
+ dev_err(dev, "Failed to convert value\n");
+ return -EINVAL;
+ }
+
+ switch (value) {
+ case 0:
+ /* Disable irq */
+ gtp_work_control_enable(data, false);
+ break;
+ case 1:
+ /* Enable irq */
+ gtp_work_control_enable(data, true);
+ break;
+ default:
+ dev_err(dev, "Invalid value\n");
+ return -EINVAL;
+ }
+
+ return count;
+}
+
+static ssize_t gtp_drv_irq_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct goodix_ts_data *data = dev_get_drvdata(dev);
+
+ return scnprintf(buf, PAGE_SIZE, "%s\n",
+ test_bit(REPORT_THREAD_ENABLED, &data->flags)
+ ? "enabled" : "disabled");
+}
+static DEVICE_ATTR(drv_irq, 0664, gtp_drv_irq_show, gtp_drv_irq_store);
+
+static ssize_t gtp_reset_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct goodix_ts_data *data = dev_get_drvdata(dev);
+
+ if ('1' != buf[0]) {
+ dev_err(dev, "Invalid argument for reset\n");
+ return -EINVAL;
+ }
+
+ gtp_reset_guitar(data->client, 20);
+
+ return count;
+}
+static DEVICE_ATTR(reset, 0220, NULL, gtp_reset_store);
+
+static struct attribute *gtp_attrs[] = {
+ &dev_attr_workmode.attr,
+ &dev_attr_productinfo.attr,
+
+#ifdef CONFIG_TOUCHSCREEN_GT9XX_UPDATE
+ &dev_attr_dofwupdate.attr,
+#endif
+
+ &dev_attr_drv_irq.attr,
+ &dev_attr_reset.attr,
+ NULL
+};
+
+static const struct attribute_group gtp_attr_group = {
+ .attrs = gtp_attrs,
+};
+
+static int gtp_create_file(struct goodix_ts_data *ts)
+{
+ int ret;
+ struct i2c_client *client = ts->client;
+
+ /* Create proc file system */
+ gtp_config_proc = NULL;
+ gtp_config_proc = proc_create(GT91XX_CONFIG_PROC_FILE, 0664,
+ NULL, &config_proc_ops);
+ if (!gtp_config_proc)
+ dev_err(&client->dev, "create_proc_entry %s failed\n",
+ GT91XX_CONFIG_PROC_FILE);
+ else
+ dev_info(&client->dev, "create proc entry %s success\n",
+ GT91XX_CONFIG_PROC_FILE);
+
+ ret = sysfs_create_group(&client->dev.kobj, >p_attr_group);
+ if (ret) {
+ dev_err(&client->dev, "Failure create sysfs group %d\n", ret);
+ /*TODO: debug change */
+ goto exit_free_config_proc;
+ }
+ return 0;
+
+exit_free_config_proc:
+ remove_proc_entry(GT91XX_CONFIG_PROC_FILE, gtp_config_proc);
+ return -ENODEV;
+}
+
+s32 gtp_get_fw_info(struct i2c_client *client, struct goodix_fw_info *fw_info)
+{
+ s32 ret = -1;
+ u8 buf[8] = {GTP_REG_VERSION >> 8, GTP_REG_VERSION & 0xff};
+
+ ret = gtp_i2c_read(client, buf, sizeof(buf));
+ if (ret < 0) {
+ dev_err(&client->dev, "Failed read fw_info\n");
+ return ret;
+ }
+
+ /* product id */
+ memset(fw_info, 0, sizeof(*fw_info));
+
+ if (buf[5] == 0x00) {
+ memcpy(fw_info->pid, buf + GTP_ADDR_LENGTH, 3);
+ dev_info(&client->dev, "IC Version: %c%c%c_%02X%02X\n",
+ buf[2], buf[3], buf[4], buf[7], buf[6]);
+ } else {
+ memcpy(fw_info->pid, buf + GTP_ADDR_LENGTH, 4);
+ dev_info(&client->dev, "IC Version: %c%c%c%c_%02X%02X\n",
+ buf[2], buf[3], buf[4], buf[5], buf[7], buf[6]);
+ }
+
+ /* current firmware version */
+ fw_info->version = (buf[7] << 8) | buf[6];
+
+ /* read sensor id */
+ fw_info->sensor_id = 0xff;
+ ret = gtp_i2c_read_dbl_check(client, GTP_REG_SENSOR_ID,
+ &fw_info->sensor_id, 1);
+ if (ret != SUCCESS || fw_info->sensor_id >= 0x06) {
+ dev_err(&client->dev,
+ "Failed get valid sensor_id(0x%02X), No Config Sent\n",
+ fw_info->sensor_id);
+
+ fw_info->sensor_id = 0xff;
+ }
+
+ return ret;
+}
+
+static int gtp_i2c_test(struct i2c_client *client)
+{
+ u8 test[3] = {GTP_REG_CONFIG_DATA >> 8, GTP_REG_CONFIG_DATA & 0xff};
+ u8 retry = 0;
+ int ret = -1;
+
+ while (retry++ < 3) {
+ ret = gtp_i2c_read(client, test, 3);
+ if (ret == 2)
+ return 0;
+
+ dev_err(&client->dev, "GTP i2c test failed time %d\n", retry);
+ usleep_range(10000, 11000); /* 10 ms */
+ }
+
+ return -EAGAIN;
+}
+
+static int gtp_pinctrl_init(struct goodix_ts_data *ts)
+{
+ struct goodix_pinctrl *pinctrl = &ts->pinctrl;
+
+ pinctrl->pinctrl = devm_pinctrl_get(&ts->client->dev);
+ if (IS_ERR_OR_NULL(pinctrl->pinctrl)) {
+ dev_info(&ts->client->dev, "No pinctrl found\n");
+ pinctrl->pinctrl = NULL;
+ return 0;
+ }
+
+ /* INT pinctrl */
+ pinctrl->int_default = pinctrl_lookup_state(pinctrl->pinctrl,
+ "gdix_ts_int_default");
+ if (IS_ERR_OR_NULL(pinctrl->int_default)) {
+ dev_info(&ts->client->dev,
+ "Failed get pinctrl state:INT default state\n");
+ goto exit_pinctrl_init;
+ }
+
+ pinctrl->int_out_high = pinctrl_lookup_state(pinctrl->pinctrl,
+ "gdix_ts_int_output_high");
+ if (IS_ERR_OR_NULL(pinctrl->int_out_high)) {
+ dev_info(&ts->client->dev,
+ "Failed get pinctrl state:INT output_high\n");
+ goto exit_pinctrl_init;
+ }
+
+ pinctrl->int_out_low = pinctrl_lookup_state(pinctrl->pinctrl,
+ "gdix_ts_int_output_low");
+ if (IS_ERR_OR_NULL(pinctrl->int_out_low)) {
+ dev_info(&ts->client->dev,
+ "Failed get pinctrl state:INT output_low\n");
+ goto exit_pinctrl_init;
+ }
+
+ pinctrl->int_input = pinctrl_lookup_state(pinctrl->pinctrl,
+ "gdix_ts_int_input");
+ if (IS_ERR_OR_NULL(pinctrl->int_input)) {
+ dev_info(&ts->client->dev,
+ "Failed get pinctrl state:int-input\n");
+ goto exit_pinctrl_init;
+ }
+ dev_info(&ts->client->dev, "Success init INT pinctrl\n");
+
+ /* RST pinctrl */
+ pinctrl->rst_default = pinctrl_lookup_state(pinctrl->pinctrl,
+ "gdix_ts_rst_default");
+ if (IS_ERR_OR_NULL(pinctrl->rst_default)) {
+ dev_info(&ts->client->dev,
+ "Failed get pinctrl state:RST default state\n");
+ goto exit_pinctrl_init;
+ }
+
+ pinctrl->rst_out_high = pinctrl_lookup_state(pinctrl->pinctrl,
+ "gdix_ts_rst_output_high");
+ if (IS_ERR_OR_NULL(pinctrl->rst_out_high)) {
+ dev_info(&ts->client->dev,
+ "Failed get pinctrl state:RST output_high\n");
+ goto exit_pinctrl_init;
+ }
+
+ pinctrl->rst_out_low = pinctrl_lookup_state(pinctrl->pinctrl,
+ "gdix_ts_rst_output_low");
+ if (IS_ERR_OR_NULL(pinctrl->rst_out_low)) {
+ dev_info(&ts->client->dev,
+ "Failed get pinctrl state:RST output_low\n");
+ goto exit_pinctrl_init;
+ }
+
+ pinctrl->rst_input = pinctrl_lookup_state(pinctrl->pinctrl,
+ "gdix_ts_rst_input");
+ if (IS_ERR_OR_NULL(pinctrl->rst_input)) {
+ dev_info(&ts->client->dev,
+ "Failed get pinctrl state:rst-input\n");
+ goto exit_pinctrl_init;
+ }
+ dev_info(&ts->client->dev, "Success init RST pinctrl\n");
+
+ return 0;
+exit_pinctrl_init:
+ devm_pinctrl_put(pinctrl->pinctrl);
+ pinctrl->pinctrl = NULL;
+ pinctrl->int_default = NULL;
+ pinctrl->int_out_high = NULL;
+ pinctrl->int_out_low = NULL;
+ pinctrl->int_input = NULL;
+ pinctrl->rst_default = NULL;
+ pinctrl->rst_out_high = NULL;
+ pinctrl->rst_out_low = NULL;
+ pinctrl->rst_input = NULL;
+ return -EINVAL;
+}
+
+static void gtp_pinctrl_deinit(struct goodix_ts_data *ts)
+{
+ if (ts->pinctrl.pinctrl)
+ devm_pinctrl_put(ts->pinctrl.pinctrl);
+}
+
+static int gtp_request_io_port(struct goodix_ts_data *ts)
+{
+ int ret = 0;
+
+ if (gpio_is_valid(ts->pdata->irq_gpio)) {
+ ret = gpio_request(ts->pdata->irq_gpio, "goodix_ts_int");
+ if (ret < 0) {
+ dev_err(&ts->client->dev,
+ "Failed to request GPIO:%d, ERRNO:%d\n",
+ (s32)ts->pdata->irq_gpio, ret);
+ return -ENODEV;
+ }
+
+ gpio_direction_input(ts->pdata->irq_gpio);
+ dev_info(&ts->client->dev, "Success request irq-gpio\n");
+ }
+
+ if (gpio_is_valid(ts->pdata->rst_gpio)) {
+ ret = gpio_request(ts->pdata->rst_gpio, "goodix_ts_rst");
+ if (ret < 0) {
+ dev_err(&ts->client->dev,
+ "Failed to request GPIO:%d, ERRNO:%d\n",
+ (s32)ts->pdata->rst_gpio, ret);
+
+ if (gpio_is_valid(ts->pdata->irq_gpio))
+ gpio_free(ts->pdata->irq_gpio);
+
+ return -ENODEV;
+ }
+
+ gpio_direction_input(ts->pdata->rst_gpio);
+ dev_info(&ts->client->dev, "Success request rst-gpio\n");
+ }
+
+ return 0;
+}
+
+/*******************************************************
+ * Function:
+ * Request interrupt if define irq pin, else use hrtimer
+ * as interrupt source
+ * Input:
+ * ts: private data.
+ * Output:
+ * Executive outcomes.
+ * 0: succeed, -1: failed.
+ *******************************************************/
+static int gtp_request_irq(struct goodix_ts_data *ts)
+{
+ int ret = -1;
+
+ /* use irq */
+ if (gpio_is_valid(ts->pdata->irq_gpio) || ts->client->irq > 0) {
+ if (gpio_is_valid(ts->pdata->irq_gpio))
+ ts->client->irq = gpio_to_irq(ts->pdata->irq_gpio);
+
+ dev_info(&ts->client->dev, "INT num %d, trigger type:%d\n",
+ ts->client->irq, ts->pdata->irq_flags);
+ ret = request_threaded_irq(ts->client->irq, NULL,
+ gtp_irq_handler,
+ ts->pdata->irq_flags | IRQF_ONESHOT,
+ ts->client->name,
+ ts);
+ if (ret < 0) {
+ dev_err(&ts->client->dev,
+ "Failed to request irq %d\n", ts->client->irq);
+ return ret;
+ }
+ } else { /* use hrtimer */
+ dev_info(&ts->client->dev, "No hardware irq, use hrtimer\n");
+ hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ ts->timer.function = gtp_timer_handler;
+ hrtimer_start(&ts->timer,
+ ktime_set(0, (GTP_POLL_TIME + 6) * 1000000),
+ HRTIMER_MODE_REL);
+ set_bit(HRTIMER_USED, &ts->flags);
+ ret = 0;
+ }
+ return ret;
+}
+
+static s8 gtp_request_input_dev(struct goodix_ts_data *ts)
+{
+ s8 ret = -1;
+ u8 index = 0;
+
+ ts->input_dev = input_allocate_device();
+ if (!ts->input_dev) {
+ dev_err(&ts->client->dev, "Failed to allocate input device\n");
+ return -ENOMEM;
+ }
+
+ ts->input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY)
+ | BIT_MASK(EV_ABS);
+ if (!ts->pdata->type_a_report) {
+ input_mt_init_slots(ts->input_dev, 16, INPUT_MT_DIRECT);
+ dev_info(&ts->client->dev, "Use slot report protocol\n");
+ } else {
+ __set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit);
+ __set_bit(BTN_TOUCH, ts->input_dev->keybit);
+ dev_info(&ts->client->dev, "Use type A report protocol\n");
+ }
+
+ input_set_capability(ts->input_dev, EV_KEY, GTP_PEN_BUTTON1);
+ input_set_capability(ts->input_dev, EV_KEY, GTP_PEN_BUTTON2);
+
+ /* touch key register */
+ for (index = 0; index < ts->pdata->key_nums; index++)
+ input_set_capability(ts->input_dev, EV_KEY,
+ ts->pdata->key_map[index]);
+
+ if (ts->pdata->slide_wakeup)
+ input_set_capability(ts->input_dev, EV_KEY, KEY_POWER);
+
+ if (ts->pdata->swap_x2y)
+ GTP_SWAP(ts->pdata->abs_size_x, ts->pdata->abs_size_y);
+
+ input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, 0,
+ ts->pdata->abs_size_x, 0, 0);
+ input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, 0,
+ ts->pdata->abs_size_y, 0, 0);
+ input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0,
+ ts->pdata->max_touch_width, 0, 0);
+ input_set_abs_params(ts->input_dev, ABS_MT_PRESSURE, 0,
+ ts->pdata->max_touch_pressure, 0, 0);
+ input_set_abs_params(ts->input_dev, ABS_MT_TRACKING_ID, 0,
+ ts->pdata->max_touch_id, 0, 0);
+ if (!ts->pdata->type_a_report) {
+ input_set_abs_params(ts->input_dev, ABS_MT_TOOL_TYPE,
+ 0, MT_TOOL_MAX, 0, 0);
+ } else {
+ __set_bit(BTN_TOOL_PEN, ts->input_dev->keybit);
+ __set_bit(BTN_TOOL_FINGER, ts->input_dev->keybit);
+ }
+
+ ts->input_dev->name = goodix_ts_name;
+ ts->input_dev->phys = goodix_input_phys;
+ ts->input_dev->id.bustype = BUS_I2C;
+ ts->input_dev->id.vendor = 0xDEAD;
+ ts->input_dev->id.product = 0xBEEF;
+ ts->input_dev->id.version = 10427;
+
+ ret = input_register_device(ts->input_dev);
+ if (ret) {
+ dev_err(&ts->client->dev, "Register %s input device failed\n",
+ ts->input_dev->name);
+ input_free_device(ts->input_dev);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+/*
+ * Devices Tree support
+ */
+#ifdef CONFIG_OF
+static void gtp_parse_dt_coords(struct device *dev,
+ struct goodix_ts_platform_data *pdata)
+{
+ struct device_node *np = dev->of_node;
+ int ret;
+
+ ret = of_property_read_u32(np, "touchscreen-max-id",
+ &pdata->max_touch_id);
+ if (ret || pdata->max_touch_id > GTP_MAX_TOUCH_ID) {
+ dev_info(dev, "Unset touchscreen-max-id, use default\n");
+ pdata->max_touch_id = GTP_MAX_TOUCH_ID;
+ }
+
+ ret = of_property_read_u32(np, "touchscreen-size-x",
+ &pdata->abs_size_x);
+ if (ret) {
+ dev_info(dev, "Unset touchscreen-size-x, use default\n");
+ pdata->abs_size_x = GTP_DEFAULT_MAX_X;
+ }
+
+ ret = of_property_read_u32(np, "touchscreen-size-y",
+ &pdata->abs_size_y);
+ if (ret) {
+ dev_info(dev, "Unset touchscreen-size-y, use default\n");
+ pdata->abs_size_y = GTP_DEFAULT_MAX_Y;
+ }
+
+ ret = of_property_read_u32(np, "touchscreen-max-w",
+ &pdata->max_touch_width);
+ if (ret) {
+ dev_info(dev, "Unset touchscreen-max-w, use default\n");
+ pdata->max_touch_width = GTP_DEFAULT_MAX_WIDTH;
+ }
+
+ ret = of_property_read_u32(np, "touchscreen-max-p",
+ &pdata->max_touch_pressure);
+ if (ret) {
+ dev_info(dev, "Unset touchscreen-max-p, use default\n");
+ pdata->max_touch_pressure = GTP_DEFAULT_MAX_PRESSURE;
+ }
+ dev_info(dev, "touch input parameters is [id x y w p]<%d %d %d %d %d>\n",
+ pdata->max_touch_id, pdata->abs_size_x, pdata->abs_size_y,
+ pdata->max_touch_width, pdata->max_touch_pressure);
+}
+
+static int gtp_parse_dt(struct device *dev,
+ struct goodix_ts_platform_data *pdata)
+{
+ int ret;
+ u32 key_nums;
+ struct property *prop;
+ u32 key_map[MAX_KEY_NUMS];
+ struct device_node *np = dev->of_node;
+
+ gtp_parse_dt_coords(dev, pdata);
+
+ ret = of_property_read_u32(np, "irq-flags",
+ &pdata->irq_flags);
+ if (ret) {
+ dev_info(dev,
+ "Failed get int-trigger-type from dts,set default\n");
+ pdata->irq_flags = GTP_DEFAULT_INT_TRIGGER;
+ }
+ of_property_read_u32(np, "goodix,int-sync", &pdata->int_sync);
+ if (pdata->int_sync)
+ dev_info(dev, "int-sync enabled\n");
+
+ of_property_read_u32(np, "goodix,driver-send-cfg",
+ &pdata->driver_send_cfg);
+ if (pdata->driver_send_cfg)
+ dev_info(dev, "driver-send-cfg enabled\n");
+
+ of_property_read_u32(np, "goodix,swap-x2y", &pdata->swap_x2y);
+ if (pdata->swap_x2y)
+ dev_info(dev, "swap-x2y enabled\n");
+
+ of_property_read_u32(np, "goodix,slide-wakeup", &pdata->slide_wakeup);
+ if (pdata->slide_wakeup)
+ dev_info(dev, "slide-wakeup enabled\n");
+
+ of_property_read_u32(np, "goodix,auto-update", &pdata->auto_update);
+ if (pdata->auto_update)
+ dev_info(dev, "auto-update enabled\n");
+
+ of_property_read_u32(np, "goodix,auto-update-cfg",
+ &pdata->auto_update_cfg);
+ if (pdata->auto_update_cfg)
+ dev_info(dev, "auto-update-cfg enabled\n");
+
+ of_property_read_u32(np, "goodix,esd-protect", &pdata->esd_protect);
+ if (pdata->esd_protect)
+ dev_info(dev, "esd-protect enabled\n");
+
+ of_property_read_u32(np, "goodix,type-a-report",
+ &pdata->type_a_report);
+ if (pdata->type_a_report)
+ dev_info(dev, "type-a-report enabled\n");
+
+ of_property_read_u32(np, "goodix,resume-in-workqueue",
+ &pdata->resume_in_workqueue);
+ if (pdata->resume_in_workqueue)
+ dev_info(dev, "resume-in-workqueue enabled\n");
+
+ of_property_read_u32(np, "goodix,power-off-sleep",
+ &pdata->power_off_sleep);
+ if (pdata->power_off_sleep)
+ dev_info(dev, "power-off-sleep enabled\n");
+
+ of_property_read_u32(np, "goodix,pen-suppress-finger",
+ &pdata->pen_suppress_finger);
+ if (pdata->pen_suppress_finger)
+ dev_info(dev, "pen-suppress-finger enabled\n");
+
+ prop = of_find_property(np, "touchscreen-key-map", NULL);
+ if (prop) {
+ key_nums = prop->length / sizeof(key_map[0]);
+ key_nums = key_nums > MAX_KEY_NUMS ? MAX_KEY_NUMS : key_nums;
+
+ dev_dbg(dev, "key nums %d\n", key_nums);
+ ret = of_property_read_u32_array(np,
+ "touchscreen-key-map", key_map,
+ key_nums);
+ if (ret) {
+ dev_err(dev, "Unable to read key codes\n");
+ pdata->key_nums = 0;
+ memset(pdata->key_map, 0,
+ MAX_KEY_NUMS * sizeof(pdata->key_map[0]));
+ }
+ pdata->key_nums = key_nums;
+ memcpy(pdata->key_map, key_map,
+ key_nums * sizeof(pdata->key_map[0]));
+ dev_info(dev, "key-map is [%x %x %x %x]\n",
+ pdata->key_map[0], pdata->key_map[1],
+ pdata->key_map[2], pdata->key_map[3]);
+ }
+
+ pdata->irq_gpio = of_get_named_gpio(np, "irq-gpios", 0);
+ if (!gpio_is_valid(pdata->irq_gpio))
+ dev_err(dev, "No valid irq gpio");
+
+ pdata->rst_gpio = of_get_named_gpio(np, "reset-gpios", 0);
+ if (!gpio_is_valid(pdata->rst_gpio))
+ dev_err(dev, "No valid rst gpio");
+
+ return 0;
+}
+
+/*******************************************************
+ * Function:
+ * parse config data from devices tree.
+ * Input:
+ * dev: device that this driver attached.
+ * cfg: pointer of the config array.
+ * cfg_len: pointer of the config length.
+ * sid: sensor id.
+ * Output:
+ * Executive outcomes.
+ * 0-succeed, -1-faileds.
+ *******************************************************/
+int gtp_parse_dt_cfg(struct device *dev, u8 *cfg, int *cfg_len, u8 sid)
+{
+ struct device_node *np = dev->of_node;
+ struct property *prop;
+ char cfg_name[18];
+ int ret;
+
+ snprintf(cfg_name, sizeof(cfg_name), "goodix,cfg-group%d", sid);
+ prop = of_find_property(np, cfg_name, cfg_len);
+ if (!prop || !prop->value || *cfg_len == 0 ||
+ *cfg_len > GTP_CONFIG_MAX_LENGTH) {
+ *cfg_len = 0;
+ ret = -EPERM;/* failed */
+ } else {
+ memcpy(cfg, prop->value, *cfg_len);
+ ret = 0;
+ }
+
+ return ret;
+}
+
+#endif
+
+static int gtp_power_on(struct goodix_ts_data *ts)
+{
+ int ret = 0;
+
+ if (ts->vdd_ana) {
+ ret = regulator_set_voltage(ts->vdd_ana, GOODIX_VTG_MIN_UV,
+ GOODIX_VTG_MAX_UV);
+ if (ret) {
+ dev_err(&ts->client->dev,
+ "Regulator set_vtg failed vdd ret=%d\n",
+ ret);
+ goto err_set_vtg_vdd_ana;
+ }
+ ret = regulator_enable(ts->vdd_ana);
+ if (ret) {
+ dev_err(&ts->client->dev,
+ "Regulator vdd enable failed ret=%d\n",
+ ret);
+ goto err_enable_vdd_ana;
+ }
+ }
+
+ if (ts->vcc_i2c) {
+ ret = regulator_set_voltage(ts->vcc_i2c, GOODIX_I2C_VTG_MIN_UV,
+ GOODIX_I2C_VTG_MAX_UV);
+ if (ret) {
+ dev_err(&ts->client->dev,
+ "Regulator set_vtg failed vcc_i2c ret=%d\n",
+ ret);
+ goto err_set_vtg_vcc_i2c;
+ }
+ ret = regulator_enable(ts->vcc_i2c);
+ if (ret) {
+ dev_err(&ts->client->dev,
+ "Regulator vcc_i2c enable failed ret=%d\n",
+ ret);
+ goto err_enable_vcc_i2c;
+ }
+ }
+ clear_bit(POWER_OFF_MODE, &ts->flags);
+ return 0;
+
+err_enable_vcc_i2c:
+ if (ts->vcc_i2c)
+ regulator_set_voltage(ts->vcc_i2c, 0, GOODIX_I2C_VTG_MAX_UV);
+err_set_vtg_vcc_i2c:
+ if (ts->vdd_ana)
+ regulator_disable(ts->vdd_ana);
+err_enable_vdd_ana:
+ if (ts->vdd_ana)
+ regulator_set_voltage(ts->vdd_ana, 0, GOODIX_VTG_MAX_UV);
+err_set_vtg_vdd_ana:
+ set_bit(POWER_OFF_MODE, &ts->flags);
+ return ret;
+}
+
+static int gtp_power_off(struct goodix_ts_data *ts)
+{
+ int ret = 0;
+
+ if (ts->vcc_i2c) {
+ set_bit(POWER_OFF_MODE, &ts->flags);
+ ret = regulator_set_voltage(ts->vcc_i2c, 0,
+ GOODIX_I2C_VTG_MAX_UV);
+ if (ret < 0) {
+ dev_err(&ts->client->dev,
+ "Regulator vcc_i2c set_vtg failed ret=%d\n",
+ ret);
+ goto err_set_vtg_vcc_i2c;
+ }
+ ret = regulator_disable(ts->vcc_i2c);
+ if (ret) {
+ dev_err(&ts->client->dev,
+ "Regulator vcc_i2c disable failed ret=%d\n",
+ ret);
+ goto err_disable_vcc_i2c;
+ }
+ dev_info(&ts->client->dev,
+ "Regulator vcc_i2c disabled\n");
+ }
+
+ if (ts->vdd_ana) {
+ set_bit(POWER_OFF_MODE, &ts->flags);
+ ret = regulator_set_voltage(ts->vdd_ana, 0, GOODIX_VTG_MAX_UV);
+ if (ret < 0) {
+ dev_err(&ts->client->dev,
+ "Regulator vdd set_vtg failed ret=%d\n",
+ ret);
+ goto err_set_vtg_vdd_ana;
+ }
+ ret = regulator_disable(ts->vdd_ana);
+ if (ret) {
+ dev_err(&ts->client->dev,
+ "Regulator vdd disable failed ret=%d\n",
+ ret);
+ goto err_disable_vdd_ana;
+ }
+ dev_info(&ts->client->dev,
+ "Regulator vdd_ana disabled\n");
+ }
+ return ret;
+
+err_disable_vdd_ana:
+ if (ts->vdd_ana)
+ regulator_set_voltage(ts->vdd_ana, GOODIX_VTG_MIN_UV,
+ GOODIX_VTG_MAX_UV);
+err_set_vtg_vdd_ana:
+ if (ts->vcc_i2c)
+ ret = regulator_enable(ts->vcc_i2c);
+err_disable_vcc_i2c:
+ if (ts->vcc_i2c)
+ regulator_set_voltage(ts->vcc_i2c, GOODIX_I2C_VTG_MIN_UV,
+ GOODIX_I2C_VTG_MAX_UV);
+err_set_vtg_vcc_i2c:
+ clear_bit(POWER_OFF_MODE, &ts->flags);
+ return ret;
+}
+
+static int gtp_power_init(struct goodix_ts_data *ts)
+{
+ int ret;
+
+ ts->vdd_ana = regulator_get(&ts->client->dev, "vdd_ana");
+ if (IS_ERR(ts->vdd_ana)) {
+ ts->vdd_ana = NULL;
+ ret = PTR_ERR(ts->vdd_ana);
+ dev_info(&ts->client->dev,
+ "Regulator get failed vdd ret=%d\n", ret);
+ }
+
+ ts->vcc_i2c = regulator_get(&ts->client->dev, "vcc_i2c");
+ if (IS_ERR(ts->vcc_i2c)) {
+ ts->vcc_i2c = NULL;
+ ret = PTR_ERR(ts->vcc_i2c);
+ dev_info(&ts->client->dev,
+ "Regulator get failed vcc_i2c ret=%d\n", ret);
+ }
+ return 0;
+}
+
+static int gtp_power_deinit(struct goodix_ts_data *ts)
+{
+ if (ts->vdd_ana)
+ regulator_put(ts->vdd_ana);
+ if (ts->vcc_i2c)
+ regulator_put(ts->vcc_i2c);
+
+ return 0;
+}
+
+static void gtp_shutdown(struct i2c_client *client)
+{
+ struct goodix_ts_data *data = i2c_get_clientdata(client);
+
+ if (!data->init_done)
+ return;
+
+ gtp_work_control_enable(data, false);
+ gtp_power_off(data);
+}
+
+static int gtp_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+ int ret = -1;
+ struct goodix_ts_data *ts;
+ struct goodix_ts_platform_data *pdata;
+
+ /* do NOT remove these logs */
+ dev_info(&client->dev, "GTP Driver Version: %s\n", GTP_DRIVER_VERSION);
+ dev_info(&client->dev, "GTP I2C Address: 0x%02x\n", client->addr);
+
+ i2c_connect_client = client;
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ dev_err(&client->dev, "Failed check I2C functionality");
+ return -ENODEV;
+ }
+
+ ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL);
+ if (!ts)
+ return -ENOMEM;
+
+ pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata) {
+ devm_kfree(&client->dev, ts);
+ return -EINVAL;
+ }
+
+ ts->init_done = false;
+
+#ifdef CONFIG_OF
+ if (client->dev.of_node) {
+ ret = gtp_parse_dt(&client->dev, pdata);
+ if (ret) {
+ dev_err(&client->dev, "Failed parse dts\n");
+ goto exit_free_client_data;
+ }
+ }
+#else
+ /* set parameters at here if you platform doesn't DTS */
+ pdata->rst_gpio = GTP_RST_PORT;
+ pdata->irq_gpio = GTP_INT_PORT;
+ pdata->slide_wakeup = false;
+ pdata->auto_update = true;
+ pdata->auto_update_cfg = false;
+ pdata->type_a_report = false;
+ pdata->esd_protect = false;
+ pdata->max_touch_id = GTP_MAX_TOUCH_ID;
+ pdata->abs_size_x = GTP_DEFAULT_MAX_X;
+ pdata->abs_size_y = GTP_DEFAULT_MAX_Y;
+ pdata->max_touch_width = GTP_DEFAULT_MAX_WIDTH;
+ pdata->max_touch_pressure = GTP_DEFAULT_MAX_PRESSURE;
+#endif
+
+ ts->client = client;
+ ts->pdata = pdata;
+
+ i2c_set_clientdata(client, ts);
+
+ ret = gtp_power_init(ts);
+ if (ret) {
+ dev_err(&client->dev, "Failed get regulator\n");
+ ret = -EINVAL;
+ goto exit_free_client_data;
+ }
+
+ ret = gtp_pinctrl_init(ts);
+ if (ret < 0) {
+ /* if define pinctrl must define the following state
+ * to let int-pin work normally: default, int_output_high,
+ * int_output_low, int_input
+ */
+ dev_err(&client->dev, "Failed get wanted pinctrl state\n");
+ goto exit_deinit_power;
+ }
+
+ ret = gtp_request_io_port(ts);
+ if (ret < 0) {
+ dev_err(&client->dev, "Failed request IO port\n");
+ goto exit_pinctrl;
+ }
+
+ /*wait for discharging power, which from i2c pull-up flow backward*/
+ gtp_rst_output(ts, 0);
+ msleep(DELAY_FOR_DISCHARGING);
+
+ ret = gtp_power_on(ts);
+ if (ret) {
+ dev_err(&client->dev, "Failed power on device\n");
+ ret = -EINVAL;
+ goto exit_free_io_port;
+ }
+
+ gtp_reset_guitar(ts->client, 20);
+
+ ret = gtp_i2c_test(client);
+ if (ret) {
+ dev_err(&client->dev, "Failed communicate with IC use I2C\n");
+ goto exit_power_off;
+ }
+
+ dev_info(&client->dev, "I2C Addr is %x\n", client->addr);
+
+ ret = gtp_get_fw_info(client, &ts->fw_info);
+ if (ret < 0) {
+ dev_err(&client->dev, "Failed read FW version\n");
+ goto exit_power_off;
+ }
+
+ pdata->config.data[0] = GTP_REG_CONFIG_DATA >> 8;
+ pdata->config.data[1] = GTP_REG_CONFIG_DATA & 0xff;
+ ret = gtp_init_panel(ts);
+ if (ret < 0)
+ dev_info(&client->dev, "Panel un-initialize\n");
+
+#ifdef CONFIG_TOUCHSCREEN_GT9XX_UPDATE
+ if (ts->pdata->auto_update) {
+ ret = gup_init_update_proc(ts);
+ if (ret < 0)
+ dev_err(&client->dev, "Failed create update thread\n");
+ }
+#endif
+
+ ret = gtp_request_input_dev(ts);
+ if (ret < 0) {
+ dev_err(&client->dev, "Failed request input device\n");
+ goto exit_power_off;
+ }
+
+ mutex_init(&ts->lock);
+
+ ret = gtp_request_irq(ts);
+ if (ret < 0) {
+ dev_err(&client->dev, "Failed create work thread");
+ goto exit_unreg_input_dev;
+ }
+ gtp_work_control_enable(ts, false);
+ if (ts->pdata->slide_wakeup) {
+ dev_info(&client->dev, "slide wakeup enabled\n");
+ ret = enable_irq_wake(client->irq);
+ if (ret < 0)
+ dev_err(&client->dev, "Failed set irq wake\n");
+ }
+
+ gtp_register_powermanager(ts);
+
+ ret = gtp_create_file(ts);
+ if (ret) {
+ dev_info(&client->dev, "Failed create attributes file");
+ goto exit_powermanager;
+ }
+
+#ifdef CONFIG_TOUCHSCREEN_GT9XX_TOOL
+ init_wr_node(client);/*TODO judge return value */
+#endif
+
+ gtp_esd_init(ts);
+ gtp_esd_on(ts);
+ /* probe init finished */
+ ts->init_done = true;
+ gtp_work_control_enable(ts, true);
+
+ return 0;
+
+exit_powermanager:
+ gtp_unregister_powermanager(ts);
+exit_unreg_input_dev:
+ input_unregister_device(ts->input_dev);
+exit_power_off:
+ gtp_power_off(ts);
+exit_free_io_port:
+ if (gpio_is_valid(ts->pdata->rst_gpio))
+ gpio_free(ts->pdata->rst_gpio);
+ if (gpio_is_valid(ts->pdata->irq_gpio))
+ gpio_free(ts->pdata->irq_gpio);
+exit_pinctrl:
+ gtp_pinctrl_deinit(ts);
+exit_deinit_power:
+ gtp_power_deinit(ts);
+exit_free_client_data:
+ devm_kfree(&client->dev, pdata);
+ devm_kfree(&client->dev, ts);
+ i2c_set_clientdata(client, NULL);
+
+ return ret;
+}
+
+static int gtp_drv_remove(struct i2c_client *client)
+{
+ struct goodix_ts_data *ts = i2c_get_clientdata(client);
+
+ gtp_work_control_enable(ts, false);
+ gtp_unregister_powermanager(ts);
+
+ remove_proc_entry(GT91XX_CONFIG_PROC_FILE, gtp_config_proc);
+
+ sysfs_remove_group(&client->dev.kobj, >p_attr_group);
+
+#ifdef CONFIG_TOUCHSCREEN_GT9XX_TOOL
+ uninit_wr_node();
+#endif
+
+ if (ts->pdata->esd_protect)
+ gtp_esd_off(ts);
+
+ /* TODO: how to judge a irq numbers validity */
+ if (ts->client->irq)
+ free_irq(client->irq, ts);
+ else
+ hrtimer_cancel(&ts->timer);
+
+ if (gpio_is_valid(ts->pdata->rst_gpio))
+ gpio_free(ts->pdata->rst_gpio);
+
+ if (gpio_is_valid(ts->pdata->irq_gpio))
+ gpio_free(ts->pdata->irq_gpio);
+
+ gtp_power_off(ts);
+ gtp_power_deinit(ts);
+ gtp_pinctrl_deinit(ts);
+ dev_info(&client->dev, "goodix ts driver removed");
+ i2c_set_clientdata(client, NULL);
+ input_unregister_device(ts->input_dev);
+ mutex_destroy(&ts->lock);
+
+ devm_kfree(&client->dev, ts->pdata);
+ devm_kfree(&client->dev, ts);
+
+ return 0;
+}
+
+static void gtp_suspend(struct goodix_ts_data *ts)
+{
+ int ret = -1;
+
+ if (test_bit(FW_UPDATE_RUNNING, &ts->flags)) {
+ dev_warn(&ts->client->dev,
+ "Fw upgrade in progress, can't go to suspend\n");
+ return;
+ }
+
+ if (test_and_set_bit(SLEEP_MODE, &ts->flags)) {
+ dev_info(&ts->client->dev, "Already in suspend state\n");
+ return;
+ }
+
+ dev_dbg(&ts->client->dev, "Try enter suspend mode\n");
+
+ gtp_esd_off(ts);
+ gtp_work_control_enable(ts, false);
+ if (ts->pdata->slide_wakeup) {
+ ret = gtp_enter_doze(ts);
+ gtp_work_control_enable(ts, true);
+ } else if (ts->pdata->power_off_sleep) {
+ /*TODO: power off routine */
+ gtp_power_off(ts);
+ ret = SUCCESS;
+ } else {
+ ret = gtp_enter_sleep(ts);
+ }
+
+ if (ret < 0)
+ dev_err(&ts->client->dev, "Failed enter suspend\n");
+
+ /* to avoid waking up while not sleeping */
+ /* delay 48 + 10ms to ensure reliability */
+ msleep(GTP_58_DLY_MS);
+}
+
+static int gtp_gesture_wakeup(struct goodix_ts_data *ts)
+{
+ int ret;
+ int retry = 10;
+
+ do {
+ gtp_reset_guitar(ts->client, 10);
+ ret = gtp_i2c_test(ts->client);
+ if (!ret)
+ break;
+ } while (--retry);
+
+ if (!retry)
+ ret = -EIO;
+
+ clear_bit(DOZE_MODE, &ts->flags);
+ return ret;
+}
+
+static void gtp_resume(struct goodix_ts_data *ts)
+{
+ int ret = 0;
+
+ if (test_bit(FW_UPDATE_RUNNING, &ts->flags)) {
+ dev_info(&ts->client->dev,
+ "Fw upgrade in progress, can't do resume\n");
+ return;
+ }
+
+ if (!test_bit(SLEEP_MODE, &ts->flags)) {
+ dev_dbg(&ts->client->dev, "Already in awake state\n");
+ return;
+ }
+
+ dev_info(&ts->client->dev, "Try resume from sleep mode\n");
+
+ gtp_work_control_enable(ts, false);
+
+ if (ts->pdata->slide_wakeup && test_bit(DOZE_MODE, &ts->flags)) {
+ ret = gtp_gesture_wakeup(ts);
+ if (ret)
+ dev_warn(&ts->client->dev, "Failed wake up from gesture mode\n");
+ } else if (ts->pdata->power_off_sleep) {
+ ret = gtp_power_on(ts);
+ if (ret) {
+ dev_warn(&ts->client->dev, "Failed wake up from gesture mode\n");
+ } else {
+ gtp_reset_guitar(ts->client, 20);
+ ret = gtp_i2c_test(ts->client);
+ if (ret)
+ dev_warn(&ts->client->dev,
+ "I2C communicate failed after power on\n");
+ }
+ } else {
+ ret = gtp_wakeup_sleep(ts);
+ if (ret)
+ dev_warn(&ts->client->dev,
+ "Failed wakeup from sleep mode\n");
+ }
+
+ if (ret)
+ dev_warn(&ts->client->dev, "Later resume failed\n");
+ else
+ gtp_esd_on(ts);
+
+ clear_bit(SLEEP_MODE, &ts->flags);
+ gtp_work_control_enable(ts, true);
+}
+
+#if defined(CONFIG_FB)
+static void fb_notify_resume_work(struct work_struct *work)
+{
+ struct goodix_ts_data *ts =
+ container_of(work, struct goodix_ts_data, fb_notify_work);
+ dev_info(&ts->client->dev, "try resume in workqueue\n");
+ gtp_resume(ts);
+}
+
+/* frame buffer notifier block control the suspend/resume procedure */
+static int gtp_fb_notifier_callback(struct notifier_block *noti,
+ unsigned long event, void *data)
+{
+ struct fb_event *ev_data = data;
+ struct goodix_ts_data *ts = container_of(noti,
+ struct goodix_ts_data, notifier);
+ int *blank;
+
+ if (ev_data && ev_data->data && event == FB_EVENT_BLANK && ts) {
+ blank = ev_data->data;
+ if (*blank == FB_BLANK_UNBLANK ||
+ *blank == FB_BLANK_NORMAL) {
+ dev_dbg(&ts->client->dev, "ts_resume");
+ if (ts->pdata->resume_in_workqueue)
+ schedule_work(&ts->fb_notify_work);
+ else
+ gtp_resume(ts);
+ } else if (*blank == FB_BLANK_POWERDOWN) {
+ dev_dbg(&ts->client->dev, "ts_suspend");
+ if (ts->pdata->resume_in_workqueue)
+ flush_work(&ts->fb_notify_work);
+ gtp_suspend(ts);
+ }
+ }
+
+ return 0;
+}
+
+#elif defined(CONFIG_PM)
+static int gtp_pm_suspend(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct goodix_ts_data *ts = i2c_get_clientdata(client);
+
+ if (ts) {
+ dev_dbg(&ts->client->dev, "Suspend by i2c pm.");
+ gtp_suspend(ts);
+ }
+
+ return 0;
+}
+
+static int gtp_pm_resume(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct goodix_ts_data *ts = i2c_get_clientdata(client);
+
+ if (ts) {
+ dev_dbg(&ts->client->dev, "Resume by i2c pm.");
+ gtp_resume(ts);
+ }
+
+ return 0;
+}
+
+static const struct dev_pm_ops gtp_pm_ops = {
+ .suspend = gtp_pm_suspend,
+ .resume = gtp_pm_resume,
+};
+
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+static void gtp_early_suspend(struct early_suspend *h)
+{
+ struct goodix_ts_data *ts = container_of(h,
+ struct goodix_ts_data, early_suspend);
+
+ if (ts) {
+ dev_dbg(&ts->client->dev, "Suspend by earlysuspend module.");
+ gtp_suspend(ts);
+ }
+}
+
+static void gtp_late_resume(struct early_suspend *h)
+{
+ struct goodix_ts_data *ts = container_of(h,
+ struct goodix_ts_data, early_suspend);
+
+ if (ts) {
+ dev_dbg(&ts->client->dev, "Resume by earlysuspend module.");
+ gtp_resume(ts);
+ }
+}
+#endif
+
+static int gtp_register_powermanager(struct goodix_ts_data *ts)
+{
+ int ret;
+#if defined(CONFIG_FB)
+ INIT_WORK(&ts->fb_notify_work, fb_notify_resume_work);
+ ts->notifier.notifier_call = gtp_fb_notifier_callback;
+ ret = fb_register_client(&ts->notifier);
+ if (ret)
+ dev_err(&ts->client->dev,
+ "Unable to register fb_notifier: %d\n", ret);
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+ ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+ ts->early_suspend.suspend = goodix_ts_early_suspend;
+ ts->early_suspend.resume = goodix_ts_late_resume;
+ register_early_suspend(&ts->early_suspend);
+#endif
+
+ return ret;
+}
+
+static int gtp_unregister_powermanager(struct goodix_ts_data *ts)
+{
+#if defined(CONFIG_FB)
+ fb_unregister_client(&ts->notifier);
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+ unregister_early_suspend(&ts->early_suspend);
+#endif
+
+ return 0;
+}
+
+/*******************************************************
+ * Function:
+ * Initialize external watchdog for esd protect
+ * Input:
+ * client: i2c device.
+ * Output:
+ * result of i2c write operation.
+ * 0: succeed, otherwise: failed
+ ********************************************************/
+static int gtp_init_ext_watchdog(struct i2c_client *client)
+{
+ int ret;
+ u8 opr_buffer[3] = { (u8)(GTP_REG_ESD_CHECK >> 8),
+ (u8)GTP_REG_ESD_CHECK,
+ (u8)GTP_ESD_CHECK_VALUE };
+
+ dev_dbg(&client->dev, "[Esd]Init external watchdog\n");
+ ret = gtp_i2c_write(client, opr_buffer, 3);
+ if (ret == 1)
+ return 0;
+
+ dev_err(&client->dev, "Failed init ext watchdog\n");
+ return -EINVAL;
+}
+
+static void gtp_esd_check_func(struct work_struct *work)
+{
+ s32 i;
+ s32 ret = -1;
+ u8 esd_buf[5] = { (u8)(GTP_REG_COMMAND >> 8), (u8)GTP_REG_COMMAND };
+ struct delayed_work *dwork = to_delayed_work(work);
+ struct goodix_ts_esd *ts_esd = container_of(dwork, struct goodix_ts_esd,
+ delayed_work);
+ struct goodix_ts_data *ts = container_of(ts_esd, struct goodix_ts_data,
+ ts_esd);
+
+ if (test_bit(SLEEP_MODE, &ts->flags) ||
+ test_bit(FW_UPDATE_RUNNING, &ts->flags)) {
+ dev_dbg(&ts->client->dev,
+ "Esd cancled by power_suspend or fw_update!");
+ return;
+ }
+
+ if (ts_esd->esd_on == false)
+ return;
+
+ for (i = 0; i < 3; i++) {
+ ret = gtp_i2c_read(ts->client, esd_buf, 4);
+ if (ret < 0)
+ continue;
+
+ dev_dbg(&ts->client->dev,
+ "[Esd]0x8040 = 0x%02X, 0x8041 = 0x%02X",
+ esd_buf[2], esd_buf[3]);
+ if (esd_buf[2] == (u8)GTP_ESD_CHECK_VALUE ||
+ esd_buf[3] != (u8)GTP_ESD_CHECK_VALUE) {
+ gtp_i2c_read(ts->client, esd_buf, 4);
+ if (ret < 0)
+ continue;
+
+ if (esd_buf[2] == (u8)GTP_ESD_CHECK_VALUE ||
+ esd_buf[3] != (u8)GTP_ESD_CHECK_VALUE) {
+ i = 3;
+ break;
+ }
+ } else {
+ /* IC works normally, Write 0x8040 0xAA, feed the dog */
+ esd_buf[2] = (u8)GTP_ESD_CHECK_VALUE;
+ gtp_i2c_write(ts->client, esd_buf, 3);
+ break;
+ }
+ }
+ if (i >= 3) {
+ dev_err(&ts->client->dev, "IC working abnormally! Reset IC\n");
+ esd_buf[0] = 0x42;
+ esd_buf[1] = 0x26;
+ esd_buf[2] = 0x01;
+ esd_buf[3] = 0x01;
+ esd_buf[4] = 0x01;
+ gtp_i2c_write(ts->client, esd_buf, 5);
+ /* TODO: Is power off really need? */
+ msleep(GTP_50_DLY_MS);
+ gtp_power_off(ts);
+ msleep(GTP_20_DLY_MS);
+ gtp_power_on(ts);
+ msleep(GTP_20_DLY_MS);
+
+ gtp_reset_guitar(ts->client, 50);
+ msleep(GTP_50_DLY_MS);
+ gtp_send_cfg(ts->client);
+ }
+
+ if (ts_esd->esd_on == true && !test_bit(SLEEP_MODE, &ts->flags)) {
+ schedule_delayed_work(&ts_esd->delayed_work, 2 * HZ);
+ dev_dbg(&ts->client->dev, "ESD work rescheduled\n");
+ }
+}
+
+static int gtp_esd_init(struct goodix_ts_data *ts)
+{
+ struct goodix_ts_esd *ts_esd = &ts->ts_esd;
+
+ INIT_DELAYED_WORK(&ts_esd->delayed_work, gtp_esd_check_func);
+ mutex_init(&ts_esd->mutex);
+ ts_esd->esd_on = false;
+
+ return 0;
+}
+
+void gtp_esd_on(struct goodix_ts_data *ts)
+{
+ struct goodix_ts_esd *ts_esd = &ts->ts_esd;
+
+ if (!ts->pdata->esd_protect)
+ return;
+ mutex_lock(&ts_esd->mutex);
+ if (ts_esd->esd_on == false) {
+ ts_esd->esd_on = true;
+ schedule_delayed_work(&ts_esd->delayed_work, 2 * HZ);
+ dev_info(&ts->client->dev, "ESD on");
+ }
+ mutex_unlock(&ts_esd->mutex);
+}
+
+void gtp_esd_off(struct goodix_ts_data *ts)
+{
+ struct goodix_ts_esd *ts_esd = &ts->ts_esd;
+
+ if (!ts->pdata->esd_protect)
+ return;
+ mutex_lock(&ts_esd->mutex);
+ if (ts_esd->esd_on == true) {
+ ts_esd->esd_on = false;
+ cancel_delayed_work_sync(&ts_esd->delayed_work);
+ dev_info(&ts->client->dev, "ESD off");
+ }
+ mutex_unlock(&ts_esd->mutex);
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id gtp_match_table[] = {
+ {.compatible = "goodix,gt9xx",},
+ { },
+};
+#endif
+
+static const struct i2c_device_id gtp_device_id[] = {
+ { GTP_I2C_NAME, 0 },
+ { }
+};
+
+static struct i2c_driver goodix_ts_driver = {
+ .probe = gtp_probe,
+ .remove = gtp_drv_remove,
+ .id_table = gtp_device_id,
+ .shutdown = gtp_shutdown,
+ .driver = {
+ .name = GTP_I2C_NAME,
+ .owner = THIS_MODULE,
+#ifdef CONFIG_OF
+ .of_match_table = gtp_match_table,
+#endif
+#if !defined(CONFIG_FB) && defined(CONFIG_PM)
+ .pm = >p_pm_ops,
+#endif
+ },
+};
+
+static int __init gtp_init(void)
+{
+ s32 ret;
+
+ pr_info("Gt9xx driver installing..\n");
+ ret = i2c_add_driver(&goodix_ts_driver);
+
+ return ret;
+}
+
+static void __exit gtp_exit(void)
+{
+ pr_info("Gt9xx driver exited\n");
+ i2c_del_driver(&goodix_ts_driver);
+}
+
+module_init(gtp_init);
+module_exit(gtp_exit);
+
+MODULE_DESCRIPTION("GT9 serials touch controller Driver");
+MODULE_LICENSE("GPL v2");
+
diff --git a/drivers/input/touchscreen/gt9xx_v2.8/gt9xx.h b/drivers/input/touchscreen/gt9xx_v2.8/gt9xx.h
new file mode 100644
index 0000000..78fa338
--- /dev/null
+++ b/drivers/input/touchscreen/gt9xx_v2.8/gt9xx.h
@@ -0,0 +1,375 @@
+/*
+ * Goodix GT9xx touchscreen driver
+ *
+ * Copyright (C) 2016 - 2017 Goodix. Ltd.
+ *
+ * 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 a reference
+ * to you, when you are integrating the GOODiX's CTP IC into your system,
+ * 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.
+ *
+ * Version: 2.8.0.2
+ * Release Date: 2017/12/14
+ */
+
+#ifndef _GOODIX_GT9XX_H_
+#define _GOODIX_GT9XX_H_
+
+#include <linux/kernel.h>
+#include <linux/hrtimer.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/proc_fs.h>
+#include <linux/string.h>
+#include <linux/uaccess.h>
+#include <linux/vmalloc.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/regulator/consumer.h>
+#include <linux/major.h>
+#include <linux/kdev_t.h>
+#ifdef CONFIG_OF
+#include <linux/of_gpio.h>
+#endif
+#ifdef CONFIG_FB
+#include <linux/notifier.h>
+#include <linux/fb.h>
+#endif
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+#include <linux/usb.h>
+#include <linux/power_supply.h>
+
+#define GTP_TOOL_PEN 1
+#define GTP_TOOL_FINGER 2
+
+#define MAX_KEY_NUMS 4
+#define GTP_CONFIG_MAX_LENGTH 240
+#define GTP_ADDR_LENGTH 2
+
+/***************************PART1:ON/OFF define*******************************/
+#define GTP_DEBUG_ON 1
+#define GTP_DEBUG_ARRAY_ON 0
+#define GTP_DEBUG_FUNC_ON 0
+
+struct goodix_point_t {
+ int id;
+ int x;
+ int y;
+ int w;
+ int p;
+ int tool_type;
+};
+
+struct goodix_config_data {
+ int length;
+ u8 data[GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH];
+};
+
+struct goodix_ts_platform_data {
+ int irq_gpio;
+ int rst_gpio;
+ u32 irq_flags;
+ u32 abs_size_x;
+ u32 abs_size_y;
+ u32 max_touch_id;
+ u32 max_touch_width;
+ u32 max_touch_pressure;
+ u32 key_map[MAX_KEY_NUMS];
+ u32 key_nums;
+ u32 int_sync;
+ u32 driver_send_cfg;
+ u32 swap_x2y;
+ u32 slide_wakeup;
+ u32 auto_update;
+ u32 auto_update_cfg;
+ u32 esd_protect;
+ u32 type_a_report;
+ u32 power_off_sleep;
+ u32 resume_in_workqueue;
+ u32 pen_suppress_finger;
+ struct goodix_config_data config;
+};
+
+struct goodix_ts_esd {
+ struct delayed_work delayed_work;
+ struct mutex mutex;
+ bool esd_on;
+};
+
+enum {
+ REPORT_THREAD_ENABLED = 0,
+ HRTIMER_USED,
+ FW_ERROR,
+
+ DOZE_MODE,
+ SLEEP_MODE,
+ POWER_OFF_MODE,
+ RAW_DATA_MODE,
+
+ FW_UPDATE_RUNNING,
+ PANEL_RESETTING
+};
+
+struct goodix_pinctrl {
+ struct pinctrl *pinctrl;
+ struct pinctrl_state *int_default;
+ struct pinctrl_state *int_out_high;
+ struct pinctrl_state *int_out_low;
+ struct pinctrl_state *int_input;
+ struct pinctrl_state *rst_default;
+ struct pinctrl_state *rst_out_high;
+ struct pinctrl_state *rst_out_low;
+ struct pinctrl_state *rst_input;
+};
+
+struct goodix_fw_info {
+ u8 pid[6];
+ u16 version;
+ u8 sensor_id;
+};
+
+struct goodix_ts_data {
+ unsigned long flags; /* This member record the device status */
+
+ struct goodix_ts_esd ts_esd;
+ struct i2c_client *client;
+ struct input_dev *input_dev;
+ struct input_dev *pen_dev;
+ struct goodix_ts_platform_data *pdata;
+ /* use pinctrl control int-pin output low or high */
+ struct goodix_pinctrl pinctrl;
+ struct hrtimer timer;
+ struct mutex lock;
+ struct notifier_block ps_notif;
+ struct regulator *vdd_ana;
+ struct regulator *vcc_i2c;
+#if defined(CONFIG_FB)
+ struct notifier_block notifier;
+ struct work_struct fb_notify_work;
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+ struct early_suspend early_suspend;
+#endif
+ struct goodix_fw_info fw_info;
+ bool force_update;
+ bool init_done;
+};
+
+/************************* PART2:TODO define *******************************/
+/* STEP_1(REQUIRED): Define Configuration Information Group(s)
+ * Sensor_ID Map:
+ * sensor_opt1 sensor_opt2 Sensor_ID
+ * GND GND 0
+ * VDDIO GND 1
+ * NC GND 2
+ * GND NC/300K 3
+ * VDDIO NC/300K 4
+ * NC NC/300K 5
+ */
+/* TODO: define your own default or for Sensor_ID == 0 config here.
+ * The predefined one is just a sample config,
+ * which is not suitable for your tp in most cases.
+ */
+#define CTP_CFG_GROUP0 {\
+ 0x41, 0xD0, 0x02, 0x00, 0x05, 0x0A, 0x34, \
+ 0x00, 0x01, 0x08, 0x28, 0x05, 0x50, 0x32, \
+ 0x03, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x17, 0x19, 0x1E, 0x14, 0x8C, \
+ 0x2D, 0x0E, 0x3C, 0x3E, 0x82, 0x0A, 0x82, \
+ 0x0A, 0x00, 0x99, 0x33, 0x1D, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x2B, 0x19, 0x64, 0x94, 0xC0, 0x02, \
+ 0x08, 0x00, 0x00, 0x04, 0xF2, 0x1C, 0x00, \
+ 0xB9, 0x26, 0x00, 0x93, 0x32, 0x00, 0x77, \
+ 0x42, 0x00, 0x62, 0x57, 0x00, 0x62, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0xFF, 0x65, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x19, 0x46, 0x00, 0x00, 0x00, 0x00, 0x32, \
+ 0x1C, 0x1A, 0x18, 0x16, 0x14, 0x12, 0x10, \
+ 0x0E, 0x0C, 0x0A, 0x08, 0x06, 0x04, 0x02, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x02, 0x04, 0x06, 0x08, \
+ 0x0A, 0x0C, 0x0F, 0x10, 0x12, 0x13, 0x14, \
+ 0x18, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, \
+ 0x22, 0x24, 0x26, 0x28, 0x29, 0x2A, 0xFF, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0xB8, 0x01\
+}
+
+/* TODO: define your config for Sensor_ID == 1 here, if needed */
+#define CTP_CFG_GROUP1 {\
+}
+
+/* TODO: define your config for Sensor_ID == 2 here, if needed */
+#define CTP_CFG_GROUP2 {\
+}
+
+/* TODO: define your config for Sensor_ID == 3 here, if needed */
+#define CTP_CFG_GROUP3 {\
+}
+/* TODO: define your config for Sensor_ID == 4 here, if needed */
+#define CTP_CFG_GROUP4 {\
+}
+
+/* TODO: define your config for Sensor_ID == 5 here, if needed */
+#define CTP_CFG_GROUP5 {\
+}
+
+/* STEP_2(REQUIRED): Customize your I/O ports & I/O operations */
+#define GTP_RST_PORT 64 /* EXYNOS4_GPX2(0) */
+#define GTP_INT_PORT 65 /* EXYNOS4_GPX2(1) */
+
+#define GTP_GPIO_AS_INPUT(pin) (gpio_direction_input(pin))
+#define GTP_GPIO_AS_INT(pin) (GTP_GPIO_AS_INPUT(pin))
+#define GTP_GPIO_GET_VALUE(pin) gpio_get_value(pin)
+#define GTP_GPIO_OUTPUT(pin, level) gpio_direction_output(pin, level)
+#define GTP_GPIO_REQUEST(pin, label) gpio_request(pin, label)
+#define GTP_GPIO_FREE(pin) gpio_free(pin)
+
+/* STEP_3(optional): Specify your special config info if needed */
+#define GTP_DEFAULT_MAX_X 720 /* default coordinate max values */
+#define GTP_DEFAULT_MAX_Y 1080
+#define GTP_DEFAULT_MAX_WIDTH 1024
+#define GTP_DEFAULT_MAX_PRESSURE 1024
+#define GTP_DEFAULT_INT_TRIGGER 1 /* 1 rising, 2 falling */
+#define GTP_MAX_TOUCH_ID 16
+
+/* STEP_4(optional): If keys are available and reported as keys,
+ * config your key info here
+ */
+#define GTP_KEY_TAB {KEY_MENU, KEY_HOME, KEY_BACK, KEY_HOMEPAGE, \
+ KEY_F1, KEY_F2, KEY_F3}
+
+/**************************PART3:OTHER define*******************************/
+#define GTP_DRIVER_VERSION "V2.8.0.2<2017/12/14>"
+#define GTP_I2C_NAME "goodix-ts"
+#define GT91XX_CONFIG_PROC_FILE "gt9xx_config"
+#define GTP_POLL_TIME 10
+#define GTP_CONFIG_MIN_LENGTH 186
+#define GTP_ESD_CHECK_VALUE 0xAA
+#define RETRY_MAX_TIMES 5
+#define PEN_TRACK_ID 9
+#define MASK_BIT_8 0x80
+#define FAIL 0
+#define SUCCESS 1
+
+/* Registers define */
+#define GTP_REG_COMMAND 0x8040
+#define GTP_REG_ESD_CHECK 0x8041
+#define GTP_REG_COMMAND_CHECK 0x8046
+#define GTP_REG_CONFIG_DATA 0x8047
+#define GTP_REG_VERSION 0x8140
+#define GTP_REG_SENSOR_ID 0x814A
+#define GTP_REG_DOZE_BUF 0x814B
+#define GTP_READ_COOR_ADDR 0x814E
+
+/* Sleep time define */
+#define GTP_1_DLY_MS 1
+#define GTP_2_DLY_MS 2
+#define GTP_10_DLY_MS 10
+#define GTP_20_DLY_MS 20
+#define GTP_50_DLY_MS 50
+#define GTP_58_DLY_MS 58
+#define GTP_100_DLY_MS 100
+#define GTP_500_DLY_MS 500
+#define GTP_1000_DLY_MS 1000
+#define GTP_3000_DLY_MS 3000
+
+#define RESOLUTION_LOC 3
+#define TRIGGER_LOC 8
+
+#define CFG_GROUP_LEN(p_cfg_grp) ARRAY_SIZE(p_cfg_grp)
+/* Log define */
+#define GTP_DEBUG(fmt, arg...) \
+do { \
+ if (GTP_DEBUG_ON) {\
+ pr_info("<<-GTP-DEBUG->> [%d]"fmt"\n", __LINE__, ##arg);\
+ } \
+} while (0)
+#define GTP_DEBUG_ARRAY(array, num) \
+do { \
+ s32 i;\
+ u8 *a = array;\
+ if (GTP_DEBUG_ARRAY_ON) {\
+ pr_warn("<<-GTP-DEBUG-ARRAY->>\n");\
+ for (i = 0; i < (num); i++) {\
+ pr_warn("%02x ", (a)[i]);\
+ if ((i + 1) % 10 == 0) {\
+ pr_warn("\n");\
+ } \
+ } \
+ pr_warn("\n");\
+ } \
+} while (0)
+#define GTP_DEBUG_FUNC() \
+do {\
+ if (GTP_DEBUG_FUNC_ON) {\
+ pr_warn("<<-GTP-FUNC->> Func:%s@Line:%d\n", \
+ __func__, __LINE__);\
+ } \
+} while (0)
+#define GTP_SWAP(x, y) \
+do {\
+ typeof(x) z = x;\
+ x = y;\
+ y = z;\
+} while (0)
+
+/******************************End of Part III********************************/
+#ifdef CONFIG_OF
+extern int gtp_parse_dt_cfg(struct device *dev, u8 *cfg, int *cfg_len, u8 sid);
+#endif
+
+extern void gtp_reset_guitar(struct i2c_client *client, s32 ms);
+extern void gtp_int_sync(struct goodix_ts_data *ts, s32 ms);
+extern void gtp_esd_on(struct goodix_ts_data *ts);
+extern void gtp_esd_off(struct goodix_ts_data *ts);
+extern void gtp_work_control_enable(struct goodix_ts_data *ts, bool enable);
+
+#ifdef CONFIG_TOUCHSCREEN_GT9XX_UPDATE
+extern u16 show_len;
+extern u16 total_len;
+extern u8 gup_init_update_proc(struct goodix_ts_data *ts);
+extern s32 gup_update_proc(void *dir);
+extern s32 gup_enter_update_mode(struct i2c_client *client);
+extern void gup_leave_update_mode(struct i2c_client *client);
+#endif
+
+#ifdef CONFIG_TOUCHSCREEN_GT9XX_TOOL
+extern s32 init_wr_node(struct i2c_client *client);
+extern void uninit_wr_node(void);
+#endif
+
+/*********** For gt9xx_update Start *********/
+extern struct i2c_client *i2c_connect_client;
+extern void gtp_reset_guitar(struct i2c_client *client, s32 ms);
+extern void gtp_int_output(struct goodix_ts_data *ts, int level);
+extern void gtp_rst_output(struct goodix_ts_data *ts, int level);
+extern void gtp_rst_input(struct goodix_ts_data *ts);
+extern s32 gtp_send_cfg(struct i2c_client *client);
+extern s32 gtp_get_fw_info(struct i2c_client *client,
+ struct goodix_fw_info *fw_info);
+extern s32 gtp_i2c_read_dbl_check(struct i2c_client *client,
+ u16 addr, u8 *rxbuf, int len);
+extern int gtp_i2c_read(struct i2c_client *client, u8 *buf, int len);
+extern int gtp_i2c_write(struct i2c_client *client, u8 *buf, int len);
+extern s32 gtp_fw_startup(struct i2c_client *client);
+extern int gtp_ascii_to_array(const u8 *src_buf, int src_len, u8 *dst_buf);
+/*********** For gt9xx_update End *********/
+
+#endif /* _GOODIX_GT9XX_H_ */
diff --git a/drivers/input/touchscreen/gt9xx_v2.8/gt9xx_update.c b/drivers/input/touchscreen/gt9xx_v2.8/gt9xx_update.c
new file mode 100644
index 0000000..7a428a3
--- /dev/null
+++ b/drivers/input/touchscreen/gt9xx_v2.8/gt9xx_update.c
@@ -0,0 +1,2090 @@
+/*
+ * Goodix GT9xx touchscreen driver
+ *
+ * Copyright (C) 2016 - 2017 Goodix. Ltd.
+ *
+ * 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 a reference
+ * to you, when you are integrating the GOODiX's CTP IC into your system,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ */
+
+#include <linux/kthread.h>
+#include "gt9xx.h"
+
+#include <linux/namei.h>
+#include <linux/mount.h>
+#include <linux/firmware.h>
+#include <linux/ctype.h>
+
+#define GUP_REG_HW_INFO 0x4220
+#define GUP_REG_FW_MSG 0x41E4
+#define GUP_REG_PID_VID 0x8140
+
+#define FIRMWARE_NAME_LEN_MAX 256
+#define GOODIX_FIRMWARE_FILE_NAME "goodix_firmware.bin"
+#define GOODIX_CONFIG_FILE_NAME "goodix_config.cfg"
+
+#define FW_HEAD_LENGTH 14
+#define FW_SECTION_LENGTH 0x2000 /* 8K */
+#define FW_DSP_ISP_LENGTH 0x1000 /* 4K */
+#define FW_DSP_LENGTH 0x1000 /* 4K */
+#define FW_BOOT_LENGTH 0x800 /* 2K */
+#define FW_SS51_LENGTH (4 * FW_SECTION_LENGTH) /* 32K */
+#define FW_BOOT_ISP_LENGTH 0x800 /* 2k */
+#define FW_GLINK_LENGTH 0x3000 /* 12k */
+#define FW_GWAKE_LENGTH (4 * FW_SECTION_LENGTH) /* 32k */
+
+#define DELAY_FOR_SENDCFG 500
+#define PACK_SIZE 256
+#define MAX_FRAME_CHECK_TIME 5
+
+#define _bRW_MISCTL__SRAM_BANK 0x4048
+#define _bRW_MISCTL__MEM_CD_EN 0x4049
+#define _bRW_MISCTL__CACHE_EN 0x404B
+#define _bRW_MISCTL__TMR0_EN 0x40B0
+#define _rRW_MISCTL__SWRST_B0_ 0x4180
+#define _bWO_MISCTL__CPU_SWRST_PULSE 0x4184
+#define _rRW_MISCTL__BOOTCTL_B0_ 0x4190
+#define _rRW_MISCTL__BOOT_OPT_B0_ 0x4218
+#define _rRW_MISCTL__BOOT_CTL_ 0x5094
+
+#pragma pack(1)
+struct st_fw_head {
+ u8 hw_info[4]; /* hardware info */
+ u8 pid[8]; /* product id */
+ u16 vid; /* version id */
+};
+#pragma pack()
+
+struct st_update_msg {
+ u8 fw_damaged;
+ u8 fw_flag;
+ const u8 *fw_data;
+ struct file *cfg_file;
+ struct st_fw_head ic_fw_msg;
+ u32 fw_total_len;
+ u32 fw_burned_len;
+ const struct firmware *fw;
+} update_msg;
+
+struct st_update_msg update_msg;
+
+u16 show_len;
+u16 total_len;
+
+static u8 gup_burn_fw_gwake_section(struct i2c_client *client,
+ u8 *fw_section, u16 start_addr,
+ u32 len, u8 bank_cmd);
+
+static s32 gup_init_panel(struct goodix_ts_data *ts)
+{
+ s32 ret = 0;
+ u8 opr_buf[16];
+ u8 sensor_id = 0;
+ u8 drv_cfg_version;
+ u8 flash_cfg_version;
+ struct goodix_config_data *cfg = &ts->pdata->config;
+
+ if (cfg->length < GTP_CONFIG_MIN_LENGTH) {
+ dev_err(&ts->client->dev,
+ "No valid config with sensor_ID(%d) ",
+ sensor_id);
+
+ return -EPERM;
+ }
+
+ ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_CONFIG_DATA,
+ &opr_buf[0], 1);
+ if (ret == SUCCESS) {
+ dev_dbg(&ts->client->dev,
+ "CFG_GROUP%d Config Version: %d, IC Config Version: %d",
+ sensor_id, cfg->data[GTP_ADDR_LENGTH], opr_buf[0]);
+
+ flash_cfg_version = opr_buf[0];
+ drv_cfg_version = cfg->data[GTP_ADDR_LENGTH];
+
+ if (flash_cfg_version < 90 &&
+ flash_cfg_version > drv_cfg_version)
+ cfg->data[GTP_ADDR_LENGTH] = 0x00;
+ } else {
+ dev_err(&ts->client->dev,
+ "Failed to get ic config version!No config sent!");
+ return -EPERM;
+ }
+
+ ret = gtp_send_cfg(ts->client);
+ if (ret < 0)
+ dev_err(&ts->client->dev, "Send config error.");
+ else
+ usleep_range(10000, 11000);
+
+ /* restore config vrsion */
+ cfg->data[GTP_ADDR_LENGTH] = drv_cfg_version;
+
+ return 0;
+}
+
+
+static u8 gup_get_ic_msg(struct i2c_client *client, u16 addr, u8 *msg, s32 len)
+{
+ s32 i = 0;
+
+ msg[0] = (addr >> 8) & 0xff;
+ msg[1] = addr & 0xff;
+
+ for (i = 0; i < 5; i++) {
+ if (gtp_i2c_read(client, msg, GTP_ADDR_LENGTH + len) > 0)
+ break;
+ }
+
+ if (i >= 5) {
+ dev_err(&client->dev,
+ "Read data from 0x%02x%02x failed!",
+ msg[0], msg[1]);
+ return FAIL;
+ }
+
+ return SUCCESS;
+}
+
+static u8 gup_set_ic_msg(struct i2c_client *client, u16 addr, u8 val)
+{
+ s32 i = 0;
+ u8 msg[3];
+
+ msg[0] = (addr >> 8) & 0xff;
+ msg[1] = addr & 0xff;
+ msg[2] = val;
+
+ for (i = 0; i < 5; i++) {
+ if (gtp_i2c_write(client, msg, GTP_ADDR_LENGTH + 1) > 0)
+ break;
+ }
+
+ if (i >= 5) {
+ dev_err(&client->dev,
+ "Set data to 0x%02x%02x failed!", msg[0], msg[1]);
+ return FAIL;
+ }
+
+ return SUCCESS;
+}
+
+static u8 gup_get_ic_fw_msg(struct i2c_client *client)
+{
+ s32 ret = -1;
+ u8 retry = 0;
+ u8 buf[16];
+ u8 i;
+
+ /* step1:get hardware info */
+ ret = gtp_i2c_read_dbl_check(client, GUP_REG_HW_INFO,
+ &buf[GTP_ADDR_LENGTH], 4);
+ if (ret == FAIL) {
+ dev_err(&client->dev, "[get_ic_fw_msg]get hw_info failed,exit");
+ return FAIL;
+ }
+
+ /* buf[2~5]: 00 06 90 00
+ * hw_info: 00 90 06 00
+ */
+ for (i = 0; i < 4; i++)
+ update_msg.ic_fw_msg.hw_info[i] = buf[GTP_ADDR_LENGTH + 3 - i];
+ dev_dbg(&client->dev,
+ "IC Hardware info:%02x%02x%02x%02x",
+ update_msg.ic_fw_msg.hw_info[0],
+ update_msg.ic_fw_msg.hw_info[1],
+ update_msg.ic_fw_msg.hw_info[2],
+ update_msg.ic_fw_msg.hw_info[3]);
+ /* step2:get firmware message */
+ for (retry = 0; retry < 2; retry++) {
+ ret = gup_get_ic_msg(client, GUP_REG_FW_MSG, buf, 1);
+ if (ret == FAIL) {
+ dev_err(&client->dev, "Read firmware message fail.");
+ return ret;
+ }
+
+ update_msg.fw_damaged = buf[GTP_ADDR_LENGTH];
+ if ((update_msg.fw_damaged != 0xBE) && (!retry)) {
+ dev_info(&client->dev, "The check sum in ic is error.");
+ dev_info(&client->dev, "The IC will be updated by force.");
+ continue;
+ }
+ break;
+ }
+ dev_dbg(&client->dev,
+ "IC force update flag:0x%x", update_msg.fw_damaged);
+
+ /* step3:get pid & vid */
+ ret = gtp_i2c_read_dbl_check(client, GUP_REG_PID_VID,
+ &buf[GTP_ADDR_LENGTH], 6);
+ if (ret == FAIL) {
+ dev_err(&client->dev, "[get_ic_fw_msg]get pid & vid failed,exit");
+ return FAIL;
+ }
+
+ memset(update_msg.ic_fw_msg.pid, 0, sizeof(update_msg.ic_fw_msg.pid));
+ memcpy(update_msg.ic_fw_msg.pid, &buf[GTP_ADDR_LENGTH], 4);
+ dev_dbg(&client->dev, "IC Product id:%s", update_msg.ic_fw_msg.pid);
+
+ /* GT9XX PID MAPPING */
+ /*|-----FLASH-----RAM-----|
+ *|------918------918-----|
+ *|------968------968-----|
+ *|------913------913-----|
+ *|------913P-----913P----|
+ *|------927------927-----|
+ *|------927P-----927P----|
+ *|------9110-----9110----|
+ *|------9110P----9111----|
+ */
+ if (update_msg.ic_fw_msg.pid[0] != 0) {
+ if (!memcmp(update_msg.ic_fw_msg.pid, "9111", 4)) {
+ dev_dbg(&client->dev, "IC Mapping Product id:%s",
+ update_msg.ic_fw_msg.pid);
+ memcpy(update_msg.ic_fw_msg.pid, "9110P", 5);
+ }
+ }
+
+ update_msg.ic_fw_msg.vid = buf[GTP_ADDR_LENGTH + 4] +
+ (buf[GTP_ADDR_LENGTH + 5] << 8);
+ dev_dbg(&client->dev, "IC version id:%04x", update_msg.ic_fw_msg.vid);
+
+ return SUCCESS;
+}
+
+s32 gup_enter_update_mode(struct i2c_client *client)
+{
+ s32 ret = -1;
+ s32 retry = 0;
+ u8 rd_buf[3];
+
+ struct goodix_ts_data *ts = i2c_get_clientdata(client);
+
+ /* step1:RST output low last at least 2ms */
+ if (!gpio_is_valid(ts->pdata->rst_gpio)) {
+ dev_err(&ts->client->dev, "update failed, no rst pin\n");
+ return FAIL;
+ }
+ gtp_rst_output(ts, 0);
+ usleep_range(2000, 3000);
+
+ /* step2:select I2C slave addr,INT:0--0xBA;1--0x28. */
+ gtp_int_output(ts, client->addr == 0x14);
+ usleep_range(2000, 3000);
+
+ /* step3:RST output high reset guitar */
+ gtp_rst_output(ts, 1);
+
+ /* 20121211 modify start */
+ usleep_range(5000, 6000);
+ while (retry++ < 200) {
+ /* step4:Hold ss51 & dsp */
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C);
+ if (ret <= 0) {
+ dev_dbg(&client->dev,
+ "Hold ss51 & dsp I2C error,retry:%d",
+ retry);
+ continue;
+ }
+
+ /* step5:Confirm hold */
+ ret = gup_get_ic_msg(client, _rRW_MISCTL__SWRST_B0_, rd_buf, 1);
+ if (ret <= 0) {
+ dev_dbg(&client->dev,
+ "Hold ss51 & dsp I2C error,retry:%d",
+ retry);
+ continue;
+ }
+ if (rd_buf[GTP_ADDR_LENGTH] == 0x0C) {
+ dev_dbg(&client->dev, "Hold ss51 & dsp confirm SUCCESS");
+ break;
+ }
+ dev_dbg(&client->dev,
+ "Hold ss51 & dsp confirm 0x4180 failed,value:%d",
+ rd_buf[GTP_ADDR_LENGTH]);
+ }
+ if (retry >= 200) {
+ dev_err(&client->dev, "Enter update Hold ss51 failed.");
+ return FAIL;
+ }
+
+ /* step6:DSP_CK and DSP_ALU_CK PowerOn */
+ ret = gup_set_ic_msg(client, 0x4010, 0x00);
+
+ /* 20121211 modify end */
+ return ret;
+}
+
+void gup_leave_update_mode(struct i2c_client *client)
+{
+ struct goodix_ts_data *ts = i2c_get_clientdata(client);
+
+ if (ts->pdata->int_sync && ts->pinctrl.pinctrl)
+ pinctrl_select_state(ts->pinctrl.pinctrl,
+ ts->pinctrl.int_input);
+ else if (ts->pdata->int_sync && gpio_is_valid(ts->pdata->irq_gpio))
+ gpio_direction_input(ts->pdata->irq_gpio);
+ dev_dbg(&client->dev, "[leave_update_mode]reset chip.");
+ gtp_reset_guitar(i2c_connect_client, 20);
+}
+
+static u8 gup_enter_update_judge(struct i2c_client *client,
+ struct st_fw_head *fw_head)
+{
+ u16 u16_tmp;
+ s32 i = 0;
+ u32 fw_len = 0;
+ s32 pid_cmp_len = 0;
+
+ u16_tmp = fw_head->vid;
+ fw_head->vid = (u16)(u16_tmp>>8) + (u16)(u16_tmp<<8);
+
+ dev_info(&client->dev, "FILE HARDWARE INFO:%*ph\n", 4,
+ &fw_head->hw_info[0]);
+ dev_info(&client->dev, "FILE PID:%s\n", fw_head->pid);
+ dev_info(&client->dev, "FILE VID:%04x\n", fw_head->vid);
+
+ dev_info(&client->dev, "IC HARDWARE INFO:%*ph\n", 4,
+ &update_msg.ic_fw_msg.hw_info[0]);
+ dev_info(&client->dev, "IC PID:%s\n", update_msg.ic_fw_msg.pid);
+ dev_info(&client->dev, "IC VID:%04x\n", update_msg.ic_fw_msg.vid);
+
+ if (!memcmp(fw_head->pid, "9158", 4) &&
+ !memcmp(update_msg.ic_fw_msg.pid, "915S", 4)) {
+ dev_info(&client->dev, "Update GT915S to GT9158 directly!");
+ return SUCCESS;
+ }
+ /* First two conditions */
+ if (!memcmp(fw_head->hw_info, update_msg.ic_fw_msg.hw_info,
+ sizeof(update_msg.ic_fw_msg.hw_info))) {
+ fw_len = 42 * 1024;
+ } else {
+ fw_len = fw_head->hw_info[3];
+ fw_len += (((u32)fw_head->hw_info[2]) << 8);
+ fw_len += (((u32)fw_head->hw_info[1]) << 16);
+ fw_len += (((u32)fw_head->hw_info[0]) << 24);
+ }
+ if (update_msg.fw_total_len != fw_len) {
+ dev_err(&client->dev,
+ "Inconsistent firmware size, Update aborted!");
+ dev_err(&client->dev,
+ " Default size: %d(%dK), actual size: %d(%dK)",
+ fw_len, fw_len/1024, update_msg.fw_total_len,
+ update_msg.fw_total_len/1024);
+ return FAIL;
+ }
+ dev_info(&client->dev, "Firmware length:%d(%dK)",
+ update_msg.fw_total_len,
+ update_msg.fw_total_len/1024);
+
+ if (update_msg.fw_damaged != 0xBE) {
+ dev_info(&client->dev, "FW chksum error,need enter update.");
+ return SUCCESS;
+ }
+
+ /* 20130523 start */
+ if (strlen(update_msg.ic_fw_msg.pid) < 3) {
+ dev_info(&client->dev, "Illegal IC pid, need enter update");
+ return SUCCESS;
+ }
+
+ /* check pid legality */
+ for (i = 0; i < 3; i++) {
+ if (!isdigit(update_msg.ic_fw_msg.pid[i])) {
+ dev_info(&client->dev,
+ "Illegal IC pid, need enter update");
+ return SUCCESS;
+ }
+ }
+ /* 20130523 end */
+
+ pid_cmp_len = strlen(fw_head->pid);
+ if (pid_cmp_len < strlen(update_msg.ic_fw_msg.pid))
+ pid_cmp_len = strlen(update_msg.ic_fw_msg.pid);
+
+ if ((!memcmp(fw_head->pid, update_msg.ic_fw_msg.pid, pid_cmp_len)) ||
+ (!memcmp(update_msg.ic_fw_msg.pid, "91XX", 4)) ||
+ (!memcmp(fw_head->pid, "91XX", 4))) {
+ if (!memcmp(fw_head->pid, "91XX", 4))
+ dev_dbg(&client->dev,
+ "Force none same pid update mode.");
+ else
+ dev_dbg(&client->dev, "Get the same pid.");
+
+ /* The third condition */
+ if (fw_head->vid != update_msg.ic_fw_msg.vid) {
+ dev_info(&client->dev, "Need enter update.");
+ return SUCCESS;
+ }
+ dev_err(&client->dev, "File VID == Ic VID, update aborted!");
+ } else {
+ dev_err(&client->dev, "File PID != Ic PID, update aborted!");
+ }
+
+ return FAIL;
+}
+
+static int gup_update_config(struct i2c_client *client)
+{
+ s32 ret = 0;
+ s32 i = 0;
+ s32 file_cfg_len = 0;
+ u8 *file_config;
+ const struct firmware *fw_cfg;
+
+ struct goodix_ts_data *ts = i2c_get_clientdata(client);
+
+ ret = request_firmware(&fw_cfg, GOODIX_CONFIG_FILE_NAME,
+ &client->dev);
+ if (ret < 0) {
+ dev_err(&client->dev,
+ "Cannot get config file - %s (%d)\n",
+ GOODIX_CONFIG_FILE_NAME, ret);
+ return -EFAULT;
+ }
+ if (!fw_cfg || !fw_cfg->data || fw_cfg->size > PAGE_SIZE) {
+ dev_err(&client->dev, "config file illegal");
+ ret = -EFAULT;
+ goto cfg_fw_err;
+ }
+
+ dev_dbg(&client->dev, "config firmware file len:%zu", fw_cfg->size);
+
+ file_config = kzalloc(GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH,
+ GFP_KERNEL);
+ if (!file_config) {
+ ret = -ENOMEM;
+ goto cfg_fw_err;
+ }
+ file_config[0] = GTP_REG_CONFIG_DATA >> 8;
+ file_config[1] = GTP_REG_CONFIG_DATA & 0xff;
+ file_cfg_len = gtp_ascii_to_array(fw_cfg->data, fw_cfg->size,
+ &file_config[GTP_ADDR_LENGTH]);
+ if (file_cfg_len < 0) {
+ dev_err(&client->dev, "failed covert ascii to hex");
+ ret = -EFAULT;
+ goto update_cfg_file_failed;
+ }
+
+ GTP_DEBUG_ARRAY(file_config + GTP_ADDR_LENGTH, file_cfg_len);
+
+ i = 0;
+ while (i++ < 5) {
+ ret = gtp_i2c_write(client, file_config, file_cfg_len + 2);
+ if (ret > 0) {
+ dev_info(&client->dev, "Send config SUCCESS.");
+ msleep(DELAY_FOR_SENDCFG);
+ break;
+ }
+ dev_err(&ts->client->dev, "Send config i2c error.");
+ }
+
+update_cfg_file_failed:
+ kfree(file_config);
+cfg_fw_err:
+ release_firmware(fw_cfg);
+ return ret;
+}
+
+static u8 gup_check_firmware_name(struct i2c_client *client,
+ u8 **path_p)
+{
+ u8 len;
+ u8 *fname;
+
+ if (!(*path_p)) {
+ *path_p = GOODIX_FIRMWARE_FILE_NAME;
+ return 0;
+ }
+
+ len = strnlen(*path_p, FIRMWARE_NAME_LEN_MAX);
+ if (len >= FIRMWARE_NAME_LEN_MAX) {
+ dev_err(&client->dev, "firmware name too long!");
+ return -EINVAL;
+ }
+
+ fname = strrchr(*path_p, '/');
+ if (fname) {
+ fname = fname + 1;
+ *path_p = fname;
+ }
+
+ return 0;
+}
+
+static u8 gup_get_update_file(struct i2c_client *client,
+ struct st_fw_head *fw_head, u8 *path)
+{
+ s32 ret = 0;
+ s32 i = 0;
+ s32 fw_checksum = 0;
+ struct goodix_ts_data *ts = i2c_get_clientdata(client);
+
+ if (ts->pdata->auto_update_cfg) {
+ ret = gup_update_config(client);
+ if (ret <= 0)
+ dev_err(&client->dev, "Update config failed.");
+ }
+
+ ret = gup_check_firmware_name(client, &path);
+ if (ret < 0)
+ return FAIL;
+
+ ret = request_firmware(&update_msg.fw, path, &client->dev);
+ if (ret < 0) {
+ dev_err(&client->dev, "Failed get firmware:%d\n", ret);
+ return FAIL;
+ }
+
+ dev_info(&client->dev, "FW File: %s size=%zu",
+ path, update_msg.fw->size);
+ update_msg.fw_data = update_msg.fw->data;
+ update_msg.fw_total_len = update_msg.fw->size;
+
+ if (update_msg.fw_total_len <
+ FW_HEAD_LENGTH + FW_SECTION_LENGTH * 4 + FW_DSP_ISP_LENGTH +
+ FW_DSP_LENGTH + FW_BOOT_LENGTH) {
+ dev_err(&client->dev,
+ "INVALID bin file(size: %d), update aborted.",
+ update_msg.fw_total_len);
+ goto invalied_fw;
+ }
+
+ update_msg.fw_total_len -= FW_HEAD_LENGTH;
+
+ dev_dbg(&client->dev, "Bin firmware actual size: %d(%dK)",
+ update_msg.fw_total_len, update_msg.fw_total_len/1024);
+
+ memcpy(fw_head, update_msg.fw_data, FW_HEAD_LENGTH);
+
+ /* check firmware legality */
+ fw_checksum = 0;
+ for (i = 0; i < update_msg.fw_total_len; i += 2) {
+ u16 temp;
+
+ temp = (update_msg.fw_data[FW_HEAD_LENGTH + i] << 8) +
+ update_msg.fw_data[FW_HEAD_LENGTH + i + 1];
+ fw_checksum += temp;
+ }
+
+ dev_dbg(&client->dev, "firmware checksum:%x", fw_checksum&0xFFFF);
+ if (fw_checksum & 0xFFFF) {
+ dev_err(&client->dev, "Illegal firmware file.");
+ goto invalied_fw;
+ }
+
+ return SUCCESS;
+
+invalied_fw:
+ update_msg.fw_data = NULL;
+ update_msg.fw_total_len = 0;
+ release_firmware(update_msg.fw);
+ return FAIL;
+}
+
+static u8 gup_burn_proc(struct i2c_client *client, u8 *burn_buf,
+ u16 start_addr, u16 total_length)
+{
+ s32 ret = 0;
+ u16 burn_addr = start_addr;
+ u16 frame_length = 0;
+ u16 burn_length = 0;
+ u8 wr_buf[PACK_SIZE + GTP_ADDR_LENGTH];
+ u8 rd_buf[PACK_SIZE + GTP_ADDR_LENGTH];
+ u8 retry = 0;
+
+ dev_dbg(&client->dev, "Begin burn %dk data to addr 0x%x",
+ total_length / 1024, start_addr);
+ while (burn_length < total_length) {
+ dev_dbg(&client->dev,
+ "B/T:%04d/%04d", burn_length, total_length);
+ frame_length = ((total_length - burn_length)
+ > PACK_SIZE) ? PACK_SIZE : (total_length - burn_length);
+ wr_buf[0] = (u8)(burn_addr>>8);
+ rd_buf[0] = wr_buf[0];
+ wr_buf[1] = (u8)burn_addr;
+ rd_buf[1] = wr_buf[1];
+ memcpy(&wr_buf[GTP_ADDR_LENGTH],
+ &burn_buf[burn_length], frame_length);
+
+ for (retry = 0; retry < MAX_FRAME_CHECK_TIME; retry++) {
+ ret = gtp_i2c_write(client,
+ wr_buf, GTP_ADDR_LENGTH + frame_length);
+ if (ret <= 0) {
+ dev_err(&client->dev,
+ "Write frame data i2c error.");
+ continue;
+ }
+ ret = gtp_i2c_read(client, rd_buf,
+ GTP_ADDR_LENGTH + frame_length);
+ if (ret <= 0) {
+ dev_err(&client->dev,
+ "Read back frame data i2c error.");
+ continue;
+ }
+ if (memcmp(&wr_buf[GTP_ADDR_LENGTH],
+ &rd_buf[GTP_ADDR_LENGTH], frame_length)) {
+ dev_err(&client->dev,
+ "Check frame data fail,not equal.");
+ dev_dbg(&client->dev, "write array:");
+ GTP_DEBUG_ARRAY(&wr_buf[GTP_ADDR_LENGTH],
+ frame_length);
+ dev_dbg(&client->dev, "read array:");
+ GTP_DEBUG_ARRAY(&rd_buf[GTP_ADDR_LENGTH],
+ frame_length);
+ continue;
+ } else {
+ /* dev_dbg(&client->dev,
+ * "Check frame data success.");
+ */
+ break;
+ }
+ }
+ if (retry >= MAX_FRAME_CHECK_TIME) {
+ dev_err(&client->dev,
+ "Burn frame data time out,exit.");
+ return FAIL;
+ }
+ burn_length += frame_length;
+ burn_addr += frame_length;
+ }
+
+ return SUCCESS;
+}
+
+static u8 gup_load_section_file(u8 *buf, u32 offset, u16 length, u8 set_or_end)
+{
+ if (!update_msg.fw_data ||
+ update_msg.fw_total_len < FW_HEAD_LENGTH + offset + length) {
+ pr_err("<<-GTP->> cannot load section data. fw_len=%d read end=%d\n",
+ update_msg.fw_total_len,
+ FW_HEAD_LENGTH + offset + length);
+ return FAIL;
+ }
+
+ if (set_or_end == SEEK_SET) {
+ memcpy(buf, &update_msg.fw_data[FW_HEAD_LENGTH + offset],
+ length);
+ } else {
+ /* seek end */
+ memcpy(buf, &update_msg.fw_data[update_msg.fw_total_len +
+ FW_HEAD_LENGTH - offset], length);
+ }
+
+ return SUCCESS;
+}
+
+static u8 gup_recall_check(struct i2c_client *client, u8 *chk_src,
+ u16 start_rd_addr, u16 chk_length)
+{
+ u8 rd_buf[PACK_SIZE + GTP_ADDR_LENGTH];
+ s32 ret = 0;
+ u16 recall_addr = start_rd_addr;
+ u16 recall_length = 0;
+ u16 frame_length = 0;
+
+ while (recall_length < chk_length) {
+ frame_length = ((chk_length - recall_length)
+ > PACK_SIZE) ? PACK_SIZE :
+ (chk_length - recall_length);
+ ret = gup_get_ic_msg(client, recall_addr, rd_buf, frame_length);
+ if (ret <= 0) {
+ dev_err(&client->dev, "recall i2c error,exit");
+ return FAIL;
+ }
+
+ if (memcmp(&rd_buf[GTP_ADDR_LENGTH],
+ &chk_src[recall_length], frame_length)) {
+ dev_err(&client->dev, "Recall frame data fail,not equal.");
+ dev_dbg(&client->dev, "chk_src array:");
+ GTP_DEBUG_ARRAY(&chk_src[recall_length], frame_length);
+ dev_dbg(&client->dev, "recall array:");
+ GTP_DEBUG_ARRAY(&rd_buf[GTP_ADDR_LENGTH], frame_length);
+ return FAIL;
+ }
+
+ recall_length += frame_length;
+ recall_addr += frame_length;
+ }
+ dev_dbg(&client->dev,
+ "Recall check %dk firmware success.",
+ (chk_length/1024));
+
+ return SUCCESS;
+}
+
+static u8 gup_burn_fw_section(struct i2c_client *client, u8 *fw_section,
+ u16 start_addr, u8 bank_cmd)
+{
+ s32 ret = 0;
+ u8 rd_buf[5];
+
+ /* step1:hold ss51 & dsp */
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C);
+ if (ret <= 0) {
+ dev_err(&client->dev, "[burn_fw_section]hold ss51 & dsp fail.");
+ return FAIL;
+ }
+
+ /* step2:set scramble */
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00);
+ if (ret <= 0) {
+ dev_err(&client->dev, "[burn_fw_section]set scramble fail.");
+ return FAIL;
+ }
+
+ /* step3:select bank */
+ ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK,
+ (bank_cmd >> 4)&0x0F);
+ if (ret <= 0) {
+ dev_err(&client->dev,
+ "[burn_fw_section]select bank %d fail.",
+ (bank_cmd >> 4)&0x0F);
+ return FAIL;
+ }
+
+ /* step4:enable accessing code */
+ ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x01);
+ if (ret <= 0) {
+ dev_err(&client->dev,
+ "[burn_fw_section]enable accessing code fail.");
+ return FAIL;
+ }
+
+ /* step5:burn 8k fw section */
+ ret = gup_burn_proc(client, fw_section, start_addr, FW_SECTION_LENGTH);
+ if (ret == FAIL) {
+ dev_err(&client->dev,
+ "[burn_fw_section]burn fw_section fail.");
+ return FAIL;
+ }
+
+ /* step6:hold ss51 & release dsp */
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x04);
+ if (ret <= 0) {
+ dev_err(&client->dev,
+ "[burn_fw_section]hold ss51 & release dsp fail.");
+ return FAIL;
+ }
+ /* must delay */
+ usleep_range(1000, 2000);
+
+ /* step7:send burn cmd to move data to flash from sram */
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, bank_cmd&0x0f);
+ if (ret <= 0) {
+ dev_err(&client->dev, "[burn_fw_section]send burn cmd fail.");
+ return FAIL;
+ }
+ dev_dbg(&client->dev,
+ "[burn_fw_section]Wait for the burn is complete......");
+ do {
+ ret = gup_get_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, rd_buf, 1);
+ if (ret <= 0) {
+ dev_err(&client->dev,
+ "[burn_fw_section]Get burn state fail");
+ return FAIL;
+ }
+ usleep_range(10000, 11000);
+ /* dev_dbg(&client->dev, "[burn_fw_section]Get burn state:%d.",
+ * rd_buf[GTP_ADDR_LENGTH]);
+ */
+ } while (rd_buf[GTP_ADDR_LENGTH]);
+
+ /* step8:select bank */
+ ret = gup_set_ic_msg(client,
+ _bRW_MISCTL__SRAM_BANK, (bank_cmd >> 4) & 0x0F);
+ if (ret <= 0) {
+ dev_err(&client->dev,
+ "[burn_fw_section]select bank %d fail.",
+ (bank_cmd >> 4)&0x0F);
+ return FAIL;
+ }
+
+ /* step9:enable accessing code */
+ ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x01);
+ if (ret <= 0) {
+ dev_err(&client->dev,
+ "[burn_fw_section]enable accessing code fail.");
+ return FAIL;
+ }
+
+ /* step10:recall 8k fw section */
+ ret = gup_recall_check(client,
+ fw_section, start_addr, FW_SECTION_LENGTH);
+ if (ret == FAIL) {
+ dev_err(&client->dev,
+ "[burn_fw_section]recall check %dk firmware fail.",
+ FW_SECTION_LENGTH / 1024);
+ return FAIL;
+ }
+
+ /* step11:disable accessing code */
+ ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x00);
+ if (ret <= 0) {
+ dev_err(&client->dev,
+ "[burn_fw_section]disable accessing code fail.");
+ return FAIL;
+ }
+
+ return SUCCESS;
+}
+
+static u8 gup_burn_dsp_isp(struct i2c_client *client)
+{
+ s32 ret = 0;
+ u8 *fw_dsp_isp = NULL;
+ u8 retry = 0;
+
+ dev_info(&client->dev, "[burn_dsp_isp]Begin burn dsp isp---->>");
+
+ /* step1:alloc memory */
+ dev_dbg(&client->dev, "[burn_dsp_isp]step1:alloc memory");
+ while (retry++ < 5) {
+ fw_dsp_isp = kzalloc(FW_DSP_ISP_LENGTH, GFP_KERNEL);
+ if (fw_dsp_isp == NULL) {
+ continue;
+ } else {
+ dev_info(&client->dev,
+ "[burn_dsp_isp]Alloc %dk byte memory success.",
+ FW_DSP_ISP_LENGTH / 1024);
+ break;
+ }
+ }
+ if (retry >= 5) {
+ dev_err(&client->dev, "[burn_dsp_isp]Alloc memory fail,exit.");
+ return FAIL;
+ }
+
+ /* step2:load dsp isp file data */
+ dev_dbg(&client->dev, "[burn_dsp_isp]step2:load dsp isp file data");
+ ret = gup_load_section_file(fw_dsp_isp,
+ FW_DSP_ISP_LENGTH, FW_DSP_ISP_LENGTH, SEEK_END);
+ if (ret == FAIL) {
+ dev_err(&client->dev,
+ "[burn_dsp_isp]load firmware dsp_isp fail.");
+ goto exit_burn_dsp_isp;
+ }
+
+ /* step3:disable wdt,clear cache enable */
+ dev_dbg(&client->dev,
+ "[burn_dsp_isp]step3:disable wdt,clear cache enable");
+ ret = gup_set_ic_msg(client, _bRW_MISCTL__TMR0_EN, 0x00);
+ if (ret <= 0) {
+ dev_err(&client->dev, "[burn_dsp_isp]disable wdt fail.");
+ ret = FAIL;
+ goto exit_burn_dsp_isp;
+ }
+ ret = gup_set_ic_msg(client, _bRW_MISCTL__CACHE_EN, 0x00);
+ if (ret <= 0) {
+ dev_err(&client->dev,
+ "[burn_dsp_isp]clear cache enable fail.");
+ ret = FAIL;
+ goto exit_burn_dsp_isp;
+ }
+
+ /* step4:hold ss51 & dsp */
+ dev_dbg(&client->dev, "[burn_dsp_isp]step4:hold ss51 & dsp");
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C);
+ if (ret <= 0) {
+ dev_err(&client->dev, "[burn_dsp_isp]hold ss51 & dsp fail.");
+ ret = FAIL;
+ goto exit_burn_dsp_isp;
+ }
+
+ /* step5:set boot from sram */
+ dev_dbg(&client->dev, "[burn_dsp_isp]step5:set boot from sram");
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOTCTL_B0_, 0x02);
+ if (ret <= 0) {
+ dev_err(&client->dev, "[burn_dsp_isp]set boot from sram fail");
+ ret = FAIL;
+ goto exit_burn_dsp_isp;
+ }
+
+ /* step6:software reboot */
+ dev_dbg(&client->dev, "[burn_dsp_isp]step6:software reboot");
+ ret = gup_set_ic_msg(client, _bWO_MISCTL__CPU_SWRST_PULSE, 0x01);
+ if (ret <= 0) {
+ dev_err(&client->dev, "[burn_dsp_isp]software reboot fail.");
+ ret = FAIL;
+ goto exit_burn_dsp_isp;
+ }
+
+ /* step7:select bank2 */
+ dev_dbg(&client->dev, "[burn_dsp_isp]step7:select bank2");
+ ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, 0x02);
+ if (ret <= 0) {
+ dev_err(&client->dev, "[burn_dsp_isp]select bank2 fail");
+ ret = FAIL;
+ goto exit_burn_dsp_isp;
+ }
+
+ /* step8:enable accessing code */
+ dev_dbg(&client->dev, "[burn_dsp_isp]step8:enable accessing code");
+ ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x01);
+ if (ret <= 0) {
+ dev_err(&client->dev,
+ "[burn_dsp_isp]enable accessing code fail.");
+ ret = FAIL;
+ goto exit_burn_dsp_isp;
+ }
+
+ /* step9:burn 4k dsp_isp */
+ dev_dbg(&client->dev, "[burn_dsp_isp]step9:burn 4k dsp_isp");
+ ret = gup_burn_proc(client, fw_dsp_isp, 0xC000, FW_DSP_ISP_LENGTH);
+ if (ret == FAIL) {
+ dev_err(&client->dev, "[burn_dsp_isp]burn dsp_isp fail.");
+ goto exit_burn_dsp_isp;
+ }
+
+ /* step10:set scramble */
+ dev_dbg(&client->dev, "[burn_dsp_isp]step10:set scramble");
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00);
+ if (ret <= 0) {
+ dev_err(&client->dev, "[burn_dsp_isp]set scramble fail.");
+ ret = FAIL;
+ goto exit_burn_dsp_isp;
+ }
+ update_msg.fw_burned_len += FW_DSP_ISP_LENGTH;
+ dev_dbg(&client->dev, "[burn_dsp_isp]Burned length:%d",
+ update_msg.fw_burned_len);
+ ret = SUCCESS;
+
+exit_burn_dsp_isp:
+ kfree(fw_dsp_isp);
+
+ return ret;
+}
+
+static u8 gup_burn_fw_ss51(struct i2c_client *client)
+{
+ u8 *fw_ss51 = NULL;
+ u8 retry = 0;
+ s32 ret = 0;
+
+ dev_info(&client->dev, "[burn_fw_ss51]Begin burn ss51 firmware---->>");
+
+ /* step1:alloc memory */
+ dev_dbg(&client->dev, "[burn_fw_ss51]step1:alloc memory");
+ while (retry++ < 5) {
+ fw_ss51 = kzalloc(FW_SECTION_LENGTH, GFP_KERNEL);
+ if (fw_ss51 == NULL) {
+ continue;
+ } else {
+ dev_dbg(&client->dev,
+ "[burn_fw_ss51]Alloc %dk byte memory success.",
+ (FW_SECTION_LENGTH / 1024));
+ break;
+ }
+ }
+ if (retry >= 5) {
+ dev_err(&client->dev, "[burn_fw_ss51]Alloc memory fail,exit.");
+ return FAIL;
+ }
+
+ dev_info(&client->dev, "[burn_fw_ss51]Reset first 8K of ss51 to 0xFF.");
+ dev_dbg(&client->dev, "[burn_fw_ss51]step2: reset bank0 0xC000~0xD000");
+ memset(fw_ss51, 0xFF, FW_SECTION_LENGTH);
+
+ /* step3:clear control flag */
+ dev_dbg(&client->dev, "[burn_fw_ss51]step3:clear control flag");
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x00);
+ if (ret <= 0) {
+ dev_err(&client->dev, "[burn_fw_ss51]clear control flag fail.");
+ ret = FAIL;
+ goto exit_burn_fw_ss51;
+ }
+
+ /* step4:burn ss51 firmware section 1 */
+ dev_dbg(&client->dev,
+ "[burn_fw_ss51]step4:burn ss51 firmware section 1");
+ ret = gup_burn_fw_section(client, fw_ss51, 0xC000, 0x01);
+ if (ret == FAIL) {
+ dev_err(&client->dev,
+ "[burn_fw_ss51]burn ss51 firmware section 1 fail.");
+ goto exit_burn_fw_ss51;
+ }
+
+ /* step5:load ss51 firmware section 2 file data */
+ dev_dbg(&client->dev,
+ "[burn_fw_ss51]step5:load ss51 firmware section 2 file data");
+ ret = gup_load_section_file(fw_ss51,
+ FW_SECTION_LENGTH, FW_SECTION_LENGTH, SEEK_SET);
+ if (ret == FAIL) {
+ dev_err(&client->dev,
+ "[burn_fw_ss51]load ss51 firmware section 2 fail.");
+ goto exit_burn_fw_ss51;
+ }
+
+ /* step6:burn ss51 firmware section 2 */
+ dev_dbg(&client->dev,
+ "[burn_fw_ss51]step6:burn ss51 firmware section 2");
+ ret = gup_burn_fw_section(client, fw_ss51, 0xE000, 0x02);
+ if (ret == FAIL) {
+ dev_err(&client->dev,
+ "[burn_fw_ss51]burn ss51 firmware section 2 fail.");
+ goto exit_burn_fw_ss51;
+ }
+
+ /* step7:load ss51 firmware section 3 file data */
+ dev_dbg(&client->dev,
+ "[burn_fw_ss51]step7:load ss51 firmware section 3 file data");
+ ret = gup_load_section_file(fw_ss51,
+ 2 * FW_SECTION_LENGTH, FW_SECTION_LENGTH, SEEK_SET);
+ if (ret == FAIL) {
+ dev_err(&client->dev,
+ "[burn_fw_ss51]load ss51 firmware section 3 fail.");
+ goto exit_burn_fw_ss51;
+ }
+
+ /* step8:burn ss51 firmware section 3 */
+ dev_dbg(&client->dev,
+ "[burn_fw_ss51]step8:burn ss51 firmware section 3");
+ ret = gup_burn_fw_section(client, fw_ss51, 0xC000, 0x13);
+ if (ret == FAIL) {
+ dev_err(&client->dev,
+ "[burn_fw_ss51]burn ss51 firmware section 3 fail.");
+ goto exit_burn_fw_ss51;
+ }
+
+ /* step9:load ss51 firmware section 4 file data */
+ dev_dbg(&client->dev,
+ "[burn_fw_ss51]step9:load ss51 firmware section 4 file data");
+ ret = gup_load_section_file(fw_ss51,
+ 3 * FW_SECTION_LENGTH, FW_SECTION_LENGTH, SEEK_SET);
+ if (ret == FAIL) {
+ dev_err(&client->dev,
+ "[burn_fw_ss51]load ss51 firmware section 4 fail.");
+ goto exit_burn_fw_ss51;
+ }
+
+ /* step10:burn ss51 firmware section 4 */
+ dev_dbg(&client->dev,
+ "[burn_fw_ss51]step10:burn ss51 firmware section 4");
+ ret = gup_burn_fw_section(client, fw_ss51, 0xE000, 0x14);
+ if (ret == FAIL) {
+ dev_err(&client->dev,
+ "[burn_fw_ss51]burn ss51 firmware section 4 fail.");
+ goto exit_burn_fw_ss51;
+ }
+
+ update_msg.fw_burned_len += (FW_SECTION_LENGTH*4);
+ dev_dbg(&client->dev, "[burn_fw_ss51]Burned length:%d",
+ update_msg.fw_burned_len);
+ ret = SUCCESS;
+
+exit_burn_fw_ss51:
+ kfree(fw_ss51);
+ return ret;
+}
+
+static u8 gup_burn_fw_dsp(struct i2c_client *client)
+{
+ s32 ret = 0;
+ u8 *fw_dsp = NULL;
+ u8 retry = 0;
+ u8 rd_buf[5];
+
+ dev_info(&client->dev, "[burn_fw_dsp]Begin burn dsp firmware---->>");
+ /* step1:alloc memory */
+ dev_dbg(&client->dev, "[burn_fw_dsp]step1:alloc memory");
+ while (retry++ < 5) {
+ fw_dsp = kzalloc(FW_DSP_LENGTH, GFP_KERNEL);
+ if (fw_dsp == NULL) {
+ continue;
+ } else {
+ dev_dbg(&client->dev,
+ "[burn_fw_dsp]Alloc %dk byte memory success.",
+ FW_SECTION_LENGTH / 1024);
+ break;
+ }
+ }
+ if (retry >= 5) {
+ dev_err(&client->dev, "[burn_fw_dsp]Alloc memory fail,exit.");
+ return FAIL;
+ }
+
+ /* step2:load firmware dsp */
+ dev_dbg(&client->dev, "[burn_fw_dsp]step2:load firmware dsp");
+ ret = gup_load_section_file(fw_dsp,
+ 4 * FW_SECTION_LENGTH, FW_DSP_LENGTH, SEEK_SET);
+ if (ret == FAIL) {
+ dev_err(&client->dev, "[burn_fw_dsp]load firmware dsp fail.");
+ goto exit_burn_fw_dsp;
+ }
+
+ /* step3:select bank3 */
+ dev_dbg(&client->dev, "[burn_fw_dsp]step3:select bank3");
+ ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, 0x03);
+ if (ret <= 0) {
+ dev_err(&client->dev, "[burn_fw_dsp]select bank3 fail.");
+ ret = FAIL;
+ goto exit_burn_fw_dsp;
+ }
+
+ /* step4:hold ss51 & dsp */
+ dev_dbg(&client->dev, "[burn_fw_dsp]step4:hold ss51 & dsp");
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C);
+ if (ret <= 0) {
+ dev_err(&client->dev, "[burn_fw_dsp]hold ss51 & dsp fail.");
+ ret = FAIL;
+ goto exit_burn_fw_dsp;
+ }
+
+ /* step5:set scramble */
+ dev_dbg(&client->dev, "[burn_fw_dsp]step5:set scramble");
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00);
+ if (ret <= 0) {
+ dev_err(&client->dev, "[burn_fw_dsp]set scramble fail.");
+ ret = FAIL;
+ goto exit_burn_fw_dsp;
+ }
+
+ /* step6:release ss51 & dsp */
+ dev_dbg(&client->dev, "[burn_fw_dsp]step6:release ss51 & dsp");
+ ret = gup_set_ic_msg(
+ client, _rRW_MISCTL__SWRST_B0_, 0x04);/* 20121211 */
+ if (ret <= 0) {
+ dev_err(&client->dev, "[burn_fw_dsp]release ss51 & dsp fail.");
+ ret = FAIL;
+ goto exit_burn_fw_dsp;
+ }
+ /* must delay */
+ usleep_range(1000, 1100);
+
+ /* step7:burn 4k dsp firmware */
+ dev_dbg(&client->dev, "[burn_fw_dsp]step7:burn 4k dsp firmware");
+ ret = gup_burn_proc(client, fw_dsp, 0x9000, FW_DSP_LENGTH);
+ if (ret == FAIL) {
+ dev_err(&client->dev, "[burn_fw_dsp]burn fw_section fail.");
+ goto exit_burn_fw_dsp;
+ }
+
+ /* step8:send burn cmd to move data to flash from sram */
+ dev_dbg(&client->dev,
+ "[burn_fw_dsp]step8:send burn cmd to move data to flash from sram");
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x05);
+ if (ret <= 0) {
+ dev_err(&client->dev, "[burn_fw_dsp]send burn cmd fail.");
+ goto exit_burn_fw_dsp;
+ }
+ dev_dbg(&client->dev, "[burn_fw_dsp]Wait for the burn is complete......");
+ do {
+ ret = gup_get_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, rd_buf, 1);
+ if (ret <= 0) {
+ dev_err(&client->dev, "[burn_fw_dsp]Get burn state fail");
+ goto exit_burn_fw_dsp;
+ }
+ usleep_range(10000, 11000);
+ /* dev_dbg(&client->dev, "[burn_fw_dsp]Get burn state:%d.",
+ * rd_buf[GTP_ADDR_LENGTH]);
+ */
+ } while (rd_buf[GTP_ADDR_LENGTH]);
+
+ /* step9:recall check 4k dsp firmware */
+ dev_dbg(&client->dev,
+ "[burn_fw_dsp]step9:recall check 4k dsp firmware");
+ ret = gup_recall_check(client, fw_dsp, 0x9000, FW_DSP_LENGTH);
+ if (ret == FAIL) {
+ dev_err(&client->dev,
+ "[burn_fw_dsp]recall check 4k dsp firmware fail.");
+ goto exit_burn_fw_dsp;
+ }
+
+ update_msg.fw_burned_len += FW_DSP_LENGTH;
+ dev_dbg(&client->dev, "[burn_fw_dsp]Burned length:%d",
+ update_msg.fw_burned_len);
+ ret = SUCCESS;
+
+exit_burn_fw_dsp:
+ kfree(fw_dsp);
+
+ return ret;
+}
+
+static u8 gup_burn_fw_boot(struct i2c_client *client)
+{
+ s32 ret = 0;
+ u8 *fw_boot = NULL;
+ u8 retry = 0;
+ u8 rd_buf[5];
+
+ dev_info(&client->dev,
+ "[burn_fw_boot]Begin burn bootloader firmware---->>");
+
+ /* step1:Alloc memory */
+ dev_dbg(&client->dev, "[burn_fw_boot]step1:Alloc memory");
+ while (retry++ < 5) {
+ fw_boot = kzalloc(FW_BOOT_LENGTH, GFP_KERNEL);
+ if (fw_boot == NULL) {
+ continue;
+ } else {
+ dev_dbg(&client->dev,
+ "[burn_fw_boot]Alloc %dk byte memory success.",
+ FW_BOOT_LENGTH / 1024);
+ break;
+ }
+ }
+ if (retry >= 5) {
+ dev_err(&client->dev, "[burn_fw_boot]Alloc memory fail,exit.");
+ return FAIL;
+ }
+
+ /* step2:load firmware bootloader */
+ dev_dbg(&client->dev, "[burn_fw_boot]step2:load firmware bootloader");
+ ret = gup_load_section_file(fw_boot,
+ (4 * FW_SECTION_LENGTH + FW_DSP_LENGTH), FW_BOOT_LENGTH, SEEK_SET);
+ if (ret == FAIL) {
+ dev_err(&client->dev,
+ "[burn_fw_boot]load firmware bootcode fail.");
+ goto exit_burn_fw_boot;
+ }
+
+ /* step3:hold ss51 & dsp */
+ dev_dbg(&client->dev, "[burn_fw_boot]step3:hold ss51 & dsp");
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C);
+ if (ret <= 0) {
+ dev_err(&client->dev, "[burn_fw_boot]hold ss51 & dsp fail.");
+ ret = FAIL;
+ goto exit_burn_fw_boot;
+ }
+
+ /* step4:set scramble */
+ dev_dbg(&client->dev, "[burn_fw_boot]step4:set scramble");
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00);
+ if (ret <= 0) {
+ dev_err(&client->dev, "[burn_fw_boot]set scramble fail.");
+ ret = FAIL;
+ goto exit_burn_fw_boot;
+ }
+
+ /* step5:hold ss51 & release dsp */
+ dev_dbg(&client->dev, "[burn_fw_boot]step5:hold ss51 & release dsp");
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x04);
+ /* 20121211 */
+ if (ret <= 0) {
+ dev_err(&client->dev, "[burn_fw_boot]release ss51 & dsp fail");
+ ret = FAIL;
+ goto exit_burn_fw_boot;
+ }
+ /* must delay */
+ usleep_range(1000, 1100);
+
+ /* step6:select bank3 */
+ dev_dbg(&client->dev, "[burn_fw_boot]step6:select bank3");
+ ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, 0x03);
+ if (ret <= 0) {
+ dev_err(&client->dev, "[burn_fw_boot]select bank3 fail.");
+ ret = FAIL;
+ goto exit_burn_fw_boot;
+ }
+
+ /* step6:burn 2k bootloader firmware */
+ dev_dbg(&client->dev,
+ "[burn_fw_boot]step6:burn 2k bootloader firmware");
+ ret = gup_burn_proc(client, fw_boot, 0x9000, FW_BOOT_LENGTH);
+ if (ret == FAIL) {
+ dev_err(&client->dev, "[burn_fw_boot]burn fw_boot fail.");
+ goto exit_burn_fw_boot;
+ }
+
+ /* step7:send burn cmd to move data to flash from sram */
+ dev_dbg(&client->dev,
+ "[burn_fw_boot]step7:send burn cmd to move data to flash from sram");
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x06);
+ if (ret <= 0) {
+ dev_err(&client->dev, "[burn_fw_boot]send burn cmd fail.");
+ goto exit_burn_fw_boot;
+ }
+ dev_dbg(&client->dev,
+ "[burn_fw_boot]Wait for the burn is complete......");
+ do {
+ ret = gup_get_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, rd_buf, 1);
+ if (ret <= 0) {
+ dev_err(&client->dev,
+ "[burn_fw_boot]Get burn state fail");
+ goto exit_burn_fw_boot;
+ }
+ usleep_range(10000, 11000);
+ /* dev_dbg(&client->dev, "[burn_fw_boot]Get burn state:%d.",
+ * rd_buf[GTP_ADDR_LENGTH]);
+ */
+ } while (rd_buf[GTP_ADDR_LENGTH]);
+
+ /* step8:recall check 2k bootloader firmware */
+ dev_dbg(&client->dev,
+ "[burn_fw_boot]step8:recall check 2k bootloader firmware");
+ ret = gup_recall_check(client, fw_boot, 0x9000, FW_BOOT_LENGTH);
+ if (ret == FAIL) {
+ dev_err(&client->dev,
+ "[burn_fw_boot]recall check 2k bootcode firmware fail");
+ goto exit_burn_fw_boot;
+ }
+
+ update_msg.fw_burned_len += FW_BOOT_LENGTH;
+ dev_dbg(&client->dev, "[burn_fw_boot]Burned length:%d",
+ update_msg.fw_burned_len);
+ ret = SUCCESS;
+
+exit_burn_fw_boot:
+ kfree(fw_boot);
+
+ return ret;
+}
+static u8 gup_burn_fw_boot_isp(struct i2c_client *client)
+{
+ s32 ret = 0;
+ u8 *fw_boot_isp = NULL;
+ u8 retry = 0;
+ u8 rd_buf[5];
+
+ if (update_msg.fw_burned_len >= update_msg.fw_total_len) {
+ dev_dbg(&client->dev, "No need to upgrade the boot_isp code!");
+ return SUCCESS;
+ }
+ dev_info(&client->dev,
+ "[burn_fw_boot_isp]Begin burn boot_isp firmware---->>");
+
+ /* step1:Alloc memory */
+ dev_dbg(&client->dev, "[burn_fw_boot_isp]step1:Alloc memory");
+ while (retry++ < 5) {
+ fw_boot_isp = kzalloc(FW_BOOT_ISP_LENGTH, GFP_KERNEL);
+ if (fw_boot_isp == NULL) {
+ continue;
+ } else {
+ dev_dbg(&client->dev,
+ "[burn_fw_boot_isp]Alloc %dk byte memory success.",
+ (FW_BOOT_ISP_LENGTH/1024));
+ break;
+ }
+ }
+ if (retry >= 5) {
+ dev_err(&client->dev,
+ "[burn_fw_boot_isp]Alloc memory fail,exit.");
+ return FAIL;
+ }
+
+ /* step2:load firmware bootloader */
+ dev_dbg(&client->dev,
+ "[burn_fw_boot_isp]step2:load firmware bootloader isp");
+ /* ret = gup_load_section_file(fw_boot_isp,
+ * (4*FW_SECTION_LENGTH+FW_DSP_LENGTH +
+ * FW_BOOT_LENGTH+FW_DSP_ISP_LENGTH), FW_BOOT_ISP_LENGTH, SEEK_SET);
+ */
+ ret = gup_load_section_file(fw_boot_isp,
+ (update_msg.fw_burned_len - FW_DSP_ISP_LENGTH),
+ FW_BOOT_ISP_LENGTH, SEEK_SET);
+ if (ret == FAIL) {
+ dev_err(&client->dev,
+ "[burn_fw_boot_isp]load firmware boot_isp fail.");
+ goto exit_burn_fw_boot_isp;
+ }
+
+ /* step3:hold ss51 & dsp */
+ dev_dbg(&client->dev, "[burn_fw_boot_isp]step3:hold ss51 & dsp");
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C);
+ if (ret <= 0) {
+ dev_err(&client->dev, "[burn_fw_boot_isp]hold ss51 & dsp fail");
+ ret = FAIL;
+ goto exit_burn_fw_boot_isp;
+ }
+
+ /* step4:set scramble */
+ dev_dbg(&client->dev, "[burn_fw_boot_isp]step4:set scramble");
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00);
+ if (ret <= 0) {
+ dev_err(&client->dev, "[burn_fw_boot_isp]set scramble fail.");
+ ret = FAIL;
+ goto exit_burn_fw_boot_isp;
+ }
+
+
+ /* step5:hold ss51 & release dsp */
+ dev_dbg(&client->dev,
+ "[burn_fw_boot_isp]step5:hold ss51 & release dsp");
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x04);
+ /* 20121211 */
+ if (ret <= 0) {
+ dev_err(&client->dev,
+ "[burn_fw_boot_isp]release ss51 & dsp fail.");
+ ret = FAIL;
+ goto exit_burn_fw_boot_isp;
+ }
+ /* must delay */
+ usleep_range(1000, 2000);
+
+ /* step6:select bank3 */
+ dev_dbg(&client->dev, "[burn_fw_boot_isp]step6:select bank3");
+ ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, 0x03);
+ if (ret <= 0) {
+ dev_err(&client->dev, "[burn_fw_boot_isp]select bank3 fail.");
+ ret = FAIL;
+ goto exit_burn_fw_boot_isp;
+ }
+
+ /* step7:burn 2k bootload_isp firmware */
+ dev_dbg(&client->dev,
+ "[burn_fw_boot_isp]step7:burn 2k bootloader firmware");
+ ret = gup_burn_proc(client, fw_boot_isp, 0x9000, FW_BOOT_ISP_LENGTH);
+ if (ret == FAIL) {
+ dev_err(&client->dev,
+ "[burn_fw_boot_isp]burn fw_section fail.");
+ goto exit_burn_fw_boot_isp;
+ }
+
+ /* step7:send burn cmd to move data to flash from sram */
+ dev_dbg(&client->dev,
+ "[burn_fw_boot_isp]step8:send burn cmd to move data to flash from sram");
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x07);
+ if (ret <= 0) {
+ dev_err(&client->dev, "[burn_fw_boot_isp]send burn cmd fail.");
+ goto exit_burn_fw_boot_isp;
+ }
+ dev_dbg(&client->dev,
+ "[burn_fw_boot_isp]Wait for the burn is complete......");
+ do {
+ ret = gup_get_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, rd_buf, 1);
+ if (ret <= 0) {
+ dev_err(&client->dev,
+ "[burn_fw_boot_isp]Get burn state fail");
+ goto exit_burn_fw_boot_isp;
+ }
+ usleep_range(10000, 11000);
+ /* dev_dbg(&client->dev, "[burn_fw_boot_isp]Get
+ * burn state:%d.", rd_buf[GTP_ADDR_LENGTH]);
+ */
+ } while (rd_buf[GTP_ADDR_LENGTH]);
+
+ /* step8:recall check 2k bootload_isp firmware */
+ dev_dbg(&client->dev,
+ "[burn_fw_boot_isp]step9:recall check 2k bootloader firmware");
+ ret = gup_recall_check(client, fw_boot_isp, 0x9000, FW_BOOT_ISP_LENGTH);
+ if (ret == FAIL) {
+ dev_err(&client->dev,
+ "[burn_fw_boot_isp]recall check 2k bootcode_isp firmware fail.");
+ goto exit_burn_fw_boot_isp;
+ }
+
+ update_msg.fw_burned_len += FW_BOOT_ISP_LENGTH;
+ dev_dbg(&client->dev,
+ "[burn_fw_boot_isp]Burned length:%d", update_msg.fw_burned_len);
+ ret = SUCCESS;
+
+exit_burn_fw_boot_isp:
+ kfree(fw_boot_isp);
+
+ return ret;
+}
+
+static u8 gup_burn_fw_link(struct i2c_client *client)
+{
+ u8 *fw_link = NULL;
+ u8 retry = 0;
+ s32 ret = 0;
+ u32 offset;
+
+ if (update_msg.fw_burned_len >= update_msg.fw_total_len) {
+ dev_dbg(&client->dev, "No need to upgrade the link code!");
+ return SUCCESS;
+ }
+ dev_info(&client->dev, "[burn_fw_link]Begin burn link firmware---->>");
+
+ /* step1:Alloc memory */
+ dev_dbg(&client->dev, "[burn_fw_link]step1:Alloc memory");
+ while (retry++ < 5) {
+ fw_link = kzalloc(FW_SECTION_LENGTH, GFP_KERNEL);
+ if (fw_link == NULL) {
+ continue;
+ } else {
+ dev_dbg(&client->dev,
+ "[burn_fw_link]Alloc %dk byte memory success.",
+ (FW_SECTION_LENGTH/1024));
+ break;
+ }
+ }
+ if (retry >= 5) {
+ dev_err(&client->dev, "[burn_fw_link]Alloc memory fail,exit.");
+ return FAIL;
+ }
+
+ /* step2:load firmware link section 1 */
+ dev_dbg(&client->dev,
+ "[burn_fw_link]step2:load firmware link section 1");
+ offset = update_msg.fw_burned_len - FW_DSP_ISP_LENGTH;
+ ret = gup_load_section_file(
+ fw_link, offset, FW_SECTION_LENGTH, SEEK_SET);
+ if (ret == FAIL) {
+ dev_err(&client->dev,
+ "[burn_fw_link]load firmware link section 1 fail.");
+ goto exit_burn_fw_link;
+ }
+
+ /* step3:burn link firmware section 1 */
+ dev_dbg(&client->dev,
+ "[burn_fw_link]step3:burn link firmware section 1");
+ ret = gup_burn_fw_gwake_section(
+ client, fw_link, 0x9000, FW_SECTION_LENGTH, 0x38);
+
+ if (ret == FAIL) {
+ dev_err(&client->dev,
+ "[burn_fw_link]burn link firmware section 1 fail.");
+ goto exit_burn_fw_link;
+ }
+
+ /* step4:load link firmware section 2 file data */
+ dev_dbg(&client->dev,
+ "[burn_fw_link]step4:load link firmware section 2 file data");
+ offset += FW_SECTION_LENGTH;
+ ret = gup_load_section_file(
+ fw_link, offset, FW_GLINK_LENGTH - FW_SECTION_LENGTH, SEEK_SET);
+
+ if (ret == FAIL) {
+ dev_err(&client->dev,
+ "[burn_fw_link]load link firmware section 2 fail.");
+ goto exit_burn_fw_link;
+ }
+
+ /* step5:burn link firmware section 2 */
+ dev_dbg(&client->dev,
+ "[burn_fw_link]step4:burn link firmware section 2");
+ ret = gup_burn_fw_gwake_section(client,
+ fw_link, 0x9000, FW_GLINK_LENGTH - FW_SECTION_LENGTH, 0x39);
+
+ if (ret == FAIL) {
+ dev_err(&client->dev,
+ "[burn_fw_link]burn link firmware section 2 fail.");
+ goto exit_burn_fw_link;
+ }
+
+ update_msg.fw_burned_len += FW_GLINK_LENGTH;
+ dev_dbg(&client->dev,
+ "[burn_fw_link]Burned length:%d", update_msg.fw_burned_len);
+ ret = SUCCESS;
+
+exit_burn_fw_link:
+ kfree(fw_link);
+
+ return ret;
+}
+
+static u8 gup_burn_fw_gwake_section(struct i2c_client *client,
+ u8 *fw_section, u16 start_addr, u32 len, u8 bank_cmd)
+{
+ s32 ret = 0;
+ u8 rd_buf[5];
+
+ /* step1:hold ss51 & dsp */
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C);
+ if (ret <= 0) {
+ dev_err(&client->dev,
+ "[burn_fw_app_section]hold ss51 & dsp fail.");
+ return FAIL;
+ }
+
+ /* step2:set scramble */
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00);
+ if (ret <= 0) {
+ dev_err(&client->dev,
+ "[burn_fw_app_section]set scramble fail.");
+ return FAIL;
+ }
+
+ /* step3:hold ss51 & release dsp */
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x04);
+ if (ret <= 0) {
+ dev_err(&client->dev,
+ "[burn_fw_app_section]hold ss51 & release dsp fail.");
+ return FAIL;
+ }
+ /* must delay */
+ usleep_range(1000, 2000);
+
+ /* step4:select bank */
+ ret = gup_set_ic_msg(
+ client, _bRW_MISCTL__SRAM_BANK, (bank_cmd >> 4)&0x0F);
+ if (ret <= 0) {
+ dev_err(&client->dev,
+ "[burn_fw_section]select bank %d fail.",
+ (bank_cmd >> 4)&0x0F);
+ return FAIL;
+ }
+
+ /* step5:burn fw section */
+ ret = gup_burn_proc(client, fw_section, start_addr, len);
+ if (ret == FAIL) {
+ dev_err(&client->dev,
+ "[burn_fw_app_section]burn fw_section fail.");
+ return FAIL;
+ }
+
+ /* step6:send burn cmd to move data to flash from sram */
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, bank_cmd&0x0F);
+ if (ret <= 0) {
+ dev_err(&client->dev,
+ "[burn_fw_app_section]send burn cmd fail.");
+ return FAIL;
+ }
+ dev_dbg(&client->dev,
+ "[burn_fw_section]Wait for the burn is complete......");
+ do {
+ ret = gup_get_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, rd_buf, 1);
+ if (ret <= 0) {
+ dev_err(&client->dev,
+ "[burn_fw_app_section]Get burn state fail");
+ return FAIL;
+ }
+ usleep_range(10000, 11000);
+ /* dev_dbg(&client->dev, "[burn_fw_app_section]Get burn state:%d."
+ * rd_buf[GTP_ADDR_LENGTH]);
+ */
+ } while (rd_buf[GTP_ADDR_LENGTH]);
+
+ /* step7:recall fw section */
+ ret = gup_recall_check(client, fw_section, start_addr, len);
+ if (ret == FAIL) {
+ dev_err(&client->dev,
+ "[burn_fw_app_section]recall check %dk firmware fail.",
+ len/1024);
+ return FAIL;
+ }
+
+ return SUCCESS;
+}
+
+static u8 gup_burn_fw_gwake(struct i2c_client *client)
+{
+ u8 *fw_gwake = NULL;
+ u8 retry = 0;
+ s32 ret = 0;
+ u16 start_index = 4*FW_SECTION_LENGTH +
+ FW_DSP_LENGTH + FW_BOOT_LENGTH +
+ FW_BOOT_ISP_LENGTH + FW_GLINK_LENGTH;/* 32 + 4 + 2 + 4 = 42K */
+ /* u16 start_index; */
+
+ if (start_index >= update_msg.fw_total_len) {
+ dev_dbg(&client->dev, "No need to upgrade the gwake code!");
+ return SUCCESS;
+ }
+ /* start_index = update_msg.fw_burned_len - FW_DSP_ISP_LENGTH; */
+ dev_info(&client->dev,
+ "[burn_fw_gwake]Begin burn gwake firmware---->>");
+
+ /* step1:alloc memory */
+ dev_dbg(&client->dev, "[burn_fw_gwake]step1:alloc memory");
+ while (retry++ < 5) {
+ fw_gwake =
+ kzalloc(FW_SECTION_LENGTH, GFP_KERNEL);
+ if (fw_gwake == NULL) {
+ continue;
+ } else {
+ dev_dbg(&client->dev,
+ "[burn_fw_gwake]Alloc %dk byte memory success.",
+ (FW_SECTION_LENGTH/1024));
+ break;
+ }
+ }
+ if (retry >= 5) {
+ dev_err(&client->dev, "[burn_fw_gwake]Alloc memory fail,exit.");
+ return FAIL;
+ }
+
+ /* clear control flag */
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x00);
+ if (ret <= 0) {
+ dev_err(&client->dev,
+ "[burn_fw_finish]clear control flag fail.");
+ goto exit_burn_fw_gwake;
+ }
+
+ /* step2:load app_code firmware section 1 file data */
+ dev_dbg(&client->dev,
+ "[burn_fw_gwake]step2:load app_code firmware section 1 file data");
+ ret = gup_load_section_file(fw_gwake,
+ start_index, FW_SECTION_LENGTH, SEEK_SET);
+ if (ret == FAIL) {
+ dev_err(&client->dev,
+ "[burn_fw_gwake]load app_code firmware section 1 fail.");
+ goto exit_burn_fw_gwake;
+ }
+
+ /* step3:burn app_code firmware section 1 */
+ dev_dbg(&client->dev,
+ "[burn_fw_gwake]step3:burn app_code firmware section 1");
+ ret = gup_burn_fw_gwake_section(client,
+ fw_gwake, 0x9000, FW_SECTION_LENGTH, 0x3A);
+ if (ret == FAIL) {
+ dev_err(&client->dev,
+ "[burn_fw_gwake]burn app_code firmware section 1 fail.");
+ goto exit_burn_fw_gwake;
+ }
+
+ /* step5:load app_code firmware section 2 file data */
+ dev_dbg(&client->dev,
+ "[burn_fw_gwake]step5:load app_code firmware section 2 file data");
+ ret = gup_load_section_file(
+ fw_gwake, start_index+FW_SECTION_LENGTH, FW_SECTION_LENGTH, SEEK_SET);
+ if (ret == FAIL) {
+ dev_err(&client->dev,
+ "[burn_fw_gwake]load app_code firmware section 2 fail.");
+ goto exit_burn_fw_gwake;
+ }
+
+ /* step6:burn app_code firmware section 2 */
+ dev_dbg(&client->dev,
+ "[burn_fw_gwake]step6:burn app_code firmware section 2");
+ ret = gup_burn_fw_gwake_section(client,
+ fw_gwake, 0x9000, FW_SECTION_LENGTH, 0x3B);
+ if (ret == FAIL) {
+ dev_err(&client->dev,
+ "[burn_fw_gwake]burn app_code firmware section 2 fail.");
+ goto exit_burn_fw_gwake;
+ }
+
+ /* step7:load app_code firmware section 3 file data */
+ dev_dbg(&client->dev,
+ "[burn_fw_gwake]step7:load app_code firmware section 3 file data");
+ ret = gup_load_section_file(
+ fw_gwake, start_index + 2*FW_SECTION_LENGTH,
+ FW_SECTION_LENGTH, SEEK_SET);
+ if (ret == FAIL) {
+ dev_err(&client->dev,
+ "[burn_fw_gwake]load app_code firmware section 3 fail.");
+ goto exit_burn_fw_gwake;
+ }
+
+ /* step8:burn app_code firmware section 3 */
+ dev_dbg(&client->dev,
+ "[burn_fw_gwake]step8:burn app_code firmware section 3");
+ ret = gup_burn_fw_gwake_section(
+ client, fw_gwake, 0x9000, FW_SECTION_LENGTH, 0x3C);
+ if (ret == FAIL) {
+ dev_err(&client->dev,
+ "[burn_fw_gwake]burn app_code firmware section 3 fail.");
+ goto exit_burn_fw_gwake;
+ }
+
+ /* step9:load app_code firmware section 4 file data */
+ dev_dbg(&client->dev,
+ "[burn_fw_gwake]step9:load app_code firmware section 4 file data");
+ ret = gup_load_section_file(fw_gwake,
+ start_index + 3*FW_SECTION_LENGTH, FW_SECTION_LENGTH, SEEK_SET);
+ if (ret == FAIL) {
+ dev_err(&client->dev,
+ "[burn_fw_gwake]load app_code firmware section 4 fail.");
+ goto exit_burn_fw_gwake;
+ }
+
+ /* step10:burn app_code firmware section 4 */
+ dev_dbg(&client->dev,
+ "[burn_fw_gwake]step10:burn app_code firmware section 4");
+ ret = gup_burn_fw_gwake_section(
+ client, fw_gwake, 0x9000, FW_SECTION_LENGTH, 0x3D);
+ if (ret == FAIL) {
+ dev_err(&client->dev,
+ "[burn_fw_gwake]burn app_code firmware section 4 fail.");
+ goto exit_burn_fw_gwake;
+ }
+
+ /* update_msg.fw_burned_len += FW_GWAKE_LENGTH; */
+ dev_dbg(&client->dev,
+ "[burn_fw_gwake]Burned length:%d", update_msg.fw_burned_len);
+ ret = SUCCESS;
+
+exit_burn_fw_gwake:
+ kfree(fw_gwake);
+
+ return ret;
+}
+
+static u8 gup_burn_fw_finish(struct i2c_client *client)
+{
+ u8 *fw_ss51 = NULL;
+ u8 retry = 0;
+ s32 ret = 0;
+
+ dev_info(&client->dev,
+ "[burn_fw_finish]burn first 8K of ss51 and finish update.");
+ /* step1:alloc memory */
+ dev_dbg(&client->dev, "[burn_fw_finish]step1:alloc memory");
+ while (retry++ < 5) {
+ fw_ss51 = kzalloc(FW_SECTION_LENGTH, GFP_KERNEL);
+ if (fw_ss51 == NULL) {
+ continue;
+ } else {
+ dev_dbg(&client->dev,
+ "[burn_fw_finish]Alloc %dk byte memory success.",
+ (FW_SECTION_LENGTH/1024));
+ break;
+ }
+ }
+ if (retry >= 5) {
+ dev_err(&client->dev,
+ "[burn_fw_finish]Alloc memory fail,exit.");
+ return FAIL;
+ }
+
+ dev_dbg(&client->dev, "[burn_fw_finish]step2: burn ss51 first 8K.");
+ ret = gup_load_section_file(fw_ss51, 0, FW_SECTION_LENGTH, SEEK_SET);
+ if (ret == FAIL) {
+ dev_err(&client->dev,
+ "[burn_fw_finish]load ss51 firmware section 1 fail.");
+ goto exit_burn_fw_finish;
+ }
+
+ dev_dbg(&client->dev, "[burn_fw_finish]step3:clear control flag");
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x00);
+ if (ret <= 0) {
+ dev_err(&client->dev,
+ "[burn_fw_finish]clear control flag fail.");
+ goto exit_burn_fw_finish;
+ }
+
+ dev_dbg(&client->dev,
+ "[burn_fw_finish]step4:burn ss51 firmware section 1");
+ ret = gup_burn_fw_section(client, fw_ss51, 0xC000, 0x01);
+ if (ret == FAIL) {
+ dev_err(&client->dev,
+ "[burn_fw_finish]burn ss51 firmware section 1 fail.");
+ goto exit_burn_fw_finish;
+ }
+
+ /* step11:enable download DSP code */
+ dev_dbg(&client->dev,
+ "[burn_fw_finish]step5:enable download DSP code ");
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x99);
+ if (ret <= 0) {
+ dev_err(&client->dev,
+ "[burn_fw_finish]enable download DSP code fail.");
+ goto exit_burn_fw_finish;
+ }
+
+ /* step12:release ss51 & hold dsp */
+ dev_dbg(&client->dev, "[burn_fw_finish]step6:release ss51 & hold dsp");
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x08);
+ if (ret <= 0) {
+ dev_err(&client->dev,
+ "[burn_fw_finish]release ss51 & hold dsp fail.");
+ goto exit_burn_fw_finish;
+ }
+
+ if (fw_ss51 != NULL)
+ kfree(fw_ss51);
+ return SUCCESS;
+
+exit_burn_fw_finish:
+ if (fw_ss51 != NULL)
+ kfree(fw_ss51);
+
+ return FAIL;
+}
+
+/* return 0 can update, else no update condition */
+static int gup_update_condition_check(struct goodix_ts_data *ts)
+{
+ if (test_bit(SLEEP_MODE, &ts->flags)) {
+ dev_info(&ts->client->dev, "Update abort, tp in sleep mode\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+s32 gup_update_proc(void *dir)
+{
+ s32 ret = 0;
+ s32 update_ret = FAIL;
+ u8 retry = 0;
+ struct st_fw_head fw_head;
+ struct goodix_ts_data *ts = NULL;
+
+ ts = i2c_get_clientdata(i2c_connect_client);
+
+ dev_dbg(&ts->client->dev, "[update_proc]Begin update ......\n");
+
+ show_len = 1;
+ total_len = 100;
+
+ ret = gup_update_condition_check(ts);
+ if (ret) {
+ dev_warn(&ts->client->dev, "Update start failed\n");
+ return FAIL;
+ }
+
+ if (test_and_set_bit(FW_UPDATE_RUNNING, &ts->flags)) {
+ dev_warn(&ts->client->dev, "FW update may already running\n");
+ return FAIL;
+ }
+
+ ret = gup_get_update_file(i2c_connect_client, &fw_head, (u8 *)dir);
+ if (ret == FAIL) {
+ dev_err(&ts->client->dev,
+ "Failed get valied firmware data\n");
+ clear_bit(FW_UPDATE_RUNNING, &ts->flags);
+ return FAIL;
+ }
+
+ gtp_work_control_enable(ts, false);
+ gtp_esd_off(ts);
+
+ ret = gup_get_ic_fw_msg(i2c_connect_client);
+ if (ret == FAIL) {
+ dev_err(&ts->client->dev, "[update_proc]get ic message fail.");
+ goto file_fail;
+ }
+
+ if (ts->force_update || dir) {
+ dev_dbg(&ts->client->dev, "Enter force update.");
+ } else {
+ ret = gup_enter_update_judge(i2c_connect_client, &fw_head);
+ if (ret == FAIL) {
+ dev_err(&ts->client->dev,
+ "[update_proc]Doesn't meet update condition\n");
+ goto file_fail;
+ }
+ }
+
+ ret = gup_enter_update_mode(ts->client);
+ if (ret == FAIL) {
+ dev_err(&ts->client->dev,
+ "[update_proc]enter update mode fail.");
+ goto update_fail;
+ }
+
+ while (retry++ < 5) {
+ show_len = 10;
+ total_len = 100;
+ update_msg.fw_burned_len = 0;
+ ret = gup_burn_dsp_isp(i2c_connect_client);
+ if (ret == FAIL) {
+ dev_err(&ts->client->dev,
+ "[update_proc]burn dsp isp fail.");
+ continue;
+ }
+
+ show_len = 20;
+ ret = gup_burn_fw_gwake(i2c_connect_client);
+ if (ret == FAIL) {
+ dev_err(&ts->client->dev,
+ "[update_proc]burn app_code firmware fail.");
+ continue;
+ }
+
+ show_len = 30;
+ ret = gup_burn_fw_ss51(i2c_connect_client);
+ if (ret == FAIL) {
+ dev_err(&ts->client->dev,
+ "[update_proc]burn ss51 firmware fail.");
+ continue;
+ }
+
+ show_len = 40;
+ ret = gup_burn_fw_dsp(i2c_connect_client);
+ if (ret == FAIL) {
+ dev_err(&ts->client->dev,
+ "[update_proc]burn dsp firmware fail.");
+ continue;
+ }
+
+ show_len = 50;
+ ret = gup_burn_fw_boot(i2c_connect_client);
+ if (ret == FAIL) {
+ dev_err(&ts->client->dev,
+ "[update_proc]burn bootloader firmware fail.");
+ continue;
+ }
+ show_len = 60;
+
+ ret = gup_burn_fw_boot_isp(i2c_connect_client);
+ if (ret == FAIL) {
+ dev_err(&ts->client->dev,
+ "[update_proc]burn boot_isp firmware fail.");
+ continue;
+ }
+
+ show_len = 70;
+ ret = gup_burn_fw_link(i2c_connect_client);
+ if (ret == FAIL) {
+ dev_err(&ts->client->dev,
+ "[update_proc]burn link firmware fail.");
+ continue;
+ }
+
+ show_len = 80;
+ ret = gup_burn_fw_finish(i2c_connect_client);
+ if (ret == FAIL) {
+ dev_err(&ts->client->dev,
+ "[update_proc]burn finish fail.");
+ continue;
+ }
+ show_len = 90;
+ dev_info(&ts->client->dev, "[update_proc]UPDATE SUCCESS.");
+ retry = 0;
+ break;
+ }
+
+ if (retry >= 5) {
+ dev_err(&ts->client->dev,
+ "[update_proc]retry timeout,UPDATE FAIL.");
+ update_ret = FAIL;
+ } else {
+ update_ret = SUCCESS;
+ }
+
+update_fail:
+ dev_dbg(&ts->client->dev, "[update_proc]leave update mode.");
+ gup_leave_update_mode(i2c_connect_client);
+
+ msleep(GTP_100_DLY_MS);
+
+ if (update_ret == SUCCESS) {
+ dev_info(&ts->client->dev,
+ "firmware error auto update, resent config!\n");
+ gup_init_panel(ts);
+ }
+ gtp_get_fw_info(ts->client, &ts->fw_info);
+
+file_fail:
+
+ update_msg.fw_data = NULL;
+ update_msg.fw_total_len = 0;
+ release_firmware(update_msg.fw);
+
+ clear_bit(FW_UPDATE_RUNNING, &ts->flags);
+ gtp_work_control_enable(ts, true);
+ gtp_esd_on(ts);
+ total_len = 100;
+ ts->force_update = false;
+ if (update_ret == SUCCESS) {
+ show_len = 100;
+ clear_bit(FW_ERROR, &ts->flags);
+ return SUCCESS;
+ }
+
+ show_len = 200;
+ return FAIL;
+}
+
+u8 gup_init_update_proc(struct goodix_ts_data *ts)
+{
+ struct task_struct *thread = NULL;
+
+ dev_info(&ts->client->dev, "Ready to run update thread.");
+
+ thread = kthread_run(gup_update_proc,
+ (void *)NULL, "guitar_update");
+
+ if (IS_ERR(thread)) {
+ dev_err(&ts->client->dev,
+ "Failed to create update thread.\n");
+ return -EPERM;
+ }
+
+ return 0;
+}
diff --git a/drivers/input/touchscreen/hxchipset/HX83100_Amber_0901_030B.i b/drivers/input/touchscreen/hxchipset/HX83100_Amber_0901_030B.i
deleted file mode 100644
index e69de29..0000000
--- a/drivers/input/touchscreen/hxchipset/HX83100_Amber_0901_030B.i
+++ /dev/null
diff --git a/drivers/input/touchscreen/hxchipset/HX_CRC_124.i b/drivers/input/touchscreen/hxchipset/HX_CRC_124.i
deleted file mode 100644
index e69de29..0000000
--- a/drivers/input/touchscreen/hxchipset/HX_CRC_124.i
+++ /dev/null
diff --git a/drivers/input/touchscreen/hxchipset/HX_CRC_128.i b/drivers/input/touchscreen/hxchipset/HX_CRC_128.i
deleted file mode 100644
index e69de29..0000000
--- a/drivers/input/touchscreen/hxchipset/HX_CRC_128.i
+++ /dev/null
diff --git a/drivers/input/touchscreen/hxchipset/HX_CRC_60.i b/drivers/input/touchscreen/hxchipset/HX_CRC_60.i
deleted file mode 100644
index e69de29..0000000
--- a/drivers/input/touchscreen/hxchipset/HX_CRC_60.i
+++ /dev/null
diff --git a/drivers/input/touchscreen/hxchipset/HX_CRC_64.i b/drivers/input/touchscreen/hxchipset/HX_CRC_64.i
deleted file mode 100644
index e69de29..0000000
--- a/drivers/input/touchscreen/hxchipset/HX_CRC_64.i
+++ /dev/null
diff --git a/drivers/input/touchscreen/hxchipset/Kconfig b/drivers/input/touchscreen/hxchipset/Kconfig
index ebf3aa4..3dc5a02 100644
--- a/drivers/input/touchscreen/hxchipset/Kconfig
+++ b/drivers/input/touchscreen/hxchipset/Kconfig
@@ -3,19 +3,44 @@
#
config TOUCHSCREEN_HIMAX_I2C
- tristate "HIMAX chipset i2c touchscreen"
- depends on TOUCHSCREEN_HIMAX_CHIPSET
- help
+ tristate "HIMAX chipset i2c touchscreen"
+ depends on TOUCHSCREEN_HIMAX_CHIPSET
+ help
+ Say Y here to enable support for HIMAX CHIPSET over I2C based touchscreens.
+ If unsure, say N.
+
+ To compile this driver as a module,
This enables support for HIMAX CHIPSET over I2C based touchscreens.
config TOUCHSCREEN_HIMAX_DEBUG
- tristate "HIMAX debug function"
- depends on TOUCHSCREEN_HIMAX_I2C
- help
+ tristate "HIMAX debug function"
+ depends on TOUCHSCREEN_HIMAX_I2C
+ help
+ Say Y here to enable support for HIMAX debug function.
+
+ If unsure, say N.
+
+ To compile this driver as a module,
This enables support for HIMAX debug function.
+config TOUCHSCREEN_HIMAX_ITO_TEST
+ tristate "HIMAX driver test over Dragon Board"
+ depends on TOUCHSCREEN_HIMAX_I2C
+ help
+ Say Y here to enable support for HIMAX driver test over Dragon Board.
+
+ If unsure, say N.
+
+ To compile this driver as a module,
+ this enables support for HIMAX driver test over Dragon Board.
+
config HMX_DB
tristate "HIMAX driver test over Dragon Board"
depends on TOUCHSCREEN_HIMAX_I2C
help
- This enables support for HIMAX driver test over Dragon Board.
+ Say Y here to enable support for HIMAX driver test over Dragon Board.
+
+ If unsure, say N.
+
+ To compile this driver as a module,
+ this enables support for HIMAX driver test over Dragon Board.
diff --git a/drivers/input/touchscreen/hxchipset/Makefile b/drivers/input/touchscreen/hxchipset/Makefile
index 509d491..522907a 100644
--- a/drivers/input/touchscreen/hxchipset/Makefile
+++ b/drivers/input/touchscreen/hxchipset/Makefile
@@ -1,3 +1,4 @@
# Makefile for the Himax touchscreen drivers.
obj-$(CONFIG_TOUCHSCREEN_HIMAX_I2C) += himax_platform.o himax_ic.o himax_common.o himax_debug.o
+obj-$(CONFIG_TOUCHSCREEN_HIMAX_ITO_TEST) += himax_ito_test.o
\ No newline at end of file
diff --git a/drivers/input/touchscreen/hxchipset/himax_common.c b/drivers/input/touchscreen/hxchipset/himax_common.c
index 417b0c0..d4bc5be 100644
--- a/drivers/input/touchscreen/hxchipset/himax_common.c
+++ b/drivers/input/touchscreen/hxchipset/himax_common.c
@@ -1,4 +1,4 @@
-/* Himax Android Driver Sample Code for Himax chipset
+ /* Himax Android Driver Sample Code for Himax chipset
*
* Copyright (C) 2015 Himax Corporation.
*
@@ -21,107 +21,32 @@
#define FRAME_COUNT 5
#if defined(HX_AUTO_UPDATE_FW)
- static unsigned char i_CTPM_FW[]=
- {
- #include "HX83100_Amber_0901_030B.i"
- };
+ char *i_CTPM_firmware_name = "HX83100_Amber_0B01_030E.bin";
+ const struct firmware *i_CTPM_FW = NULL;
#endif
-#ifdef HX_ESD_WORKAROUND
- extern void HX_report_ESD_event(void);
- unsigned char ESD_00_counter = 0;
- unsigned char ESD_00_Flag = 0;
-#endif
-
-//static int tpd_keys_local[HX_KEY_MAX_COUNT] = HX_KEY_ARRAY; // for Virtual key array
+/*static int tpd_keys_local[HX_KEY_MAX_COUNT] = HX_KEY_ARRAY;
+// for Virtual key array */
struct himax_ts_data *private_ts;
-struct himax_ic_data* ic_data;
+struct himax_ic_data *ic_data;
-static int HX_TOUCH_INFO_POINT_CNT;
+static int HX_TOUCH_INFO_POINT_CNT;
-#ifdef HX_AUTO_UPDATE_FW
-extern unsigned long FW_VER_MAJ_FLASH_ADDR;
-extern unsigned long FW_VER_MIN_FLASH_ADDR;
-extern unsigned long CFG_VER_MAJ_FLASH_ADDR;
-extern unsigned long CFG_VER_MIN_FLASH_ADDR;
-#endif
-extern unsigned long FW_VER_MAJ_FLASH_LENG;
-extern unsigned long FW_VER_MIN_FLASH_LENG;
-extern unsigned long CFG_VER_MAJ_FLASH_LENG;
-extern unsigned long CFG_VER_MIN_FLASH_LENG;
-extern unsigned char IC_TYPE;
-extern unsigned char IC_CHECKSUM;
-
-#if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG)
-extern int himax_touch_proc_init(void);
-extern void himax_touch_proc_deinit(void);
-//PROC-START
-#ifdef HX_TP_PROC_FLASH_DUMP
-extern void himax_ts_flash_func(void);
-extern void setFlashBuffer(void);
-extern bool getFlashDumpGoing(void);
-extern uint8_t getSysOperation(void);
-extern void setSysOperation(uint8_t operation);
-#endif
-
-#ifdef HX_TP_PROC_HITOUCH
-extern bool hitouch_is_connect;
-#endif
-
-#ifdef HX_TP_PROC_DIAG
- extern int touch_monitor_stop_flag;
- extern int touch_monitor_stop_limit;
- extern void himax_ts_diag_func(void);
- extern int16_t *getMutualBuffer(void);
- extern int16_t *getMutualNewBuffer(void);
- extern int16_t *getMutualOldBuffer(void);
- extern int16_t *getSelfBuffer(void);
- extern uint8_t getXChannel(void);
- extern uint8_t getYChannel(void);
- extern uint8_t getDiagCommand(void);
- extern void setXChannel(uint8_t x);
- extern void setYChannel(uint8_t y);
- extern void setMutualBuffer(void);
- extern void setMutualNewBuffer(void);
- extern void setMutualOldBuffer(void);
- extern uint8_t coordinate_dump_enable;
- extern struct file *coordinate_fn;
- extern uint8_t diag_coor[128];
-#ifdef HX_TP_PROC_2T2R
- extern int16_t *getMutualBuffer_2(void);
- extern uint8_t getXChannel_2(void);
- extern uint8_t getYChannel_2(void);
- extern void setXChannel_2(uint8_t x);
- extern void setYChannel_2(uint8_t y);
- extern void setMutualBuffer_2(void);
-#endif
-#endif
-//PROC-END
-#endif
-
-extern int himax_parse_dt(struct himax_ts_data *ts,
- struct himax_i2c_platform_data *pdata);
-extern int himax_ts_pinctrl_init(struct himax_ts_data *ts);
-
-static uint8_t vk_press;
-static uint8_t AA_press;
-static uint8_t EN_NoiseFilter;
-static uint8_t Last_EN_NoiseFilter;
-static int hx_point_num; // for himax_ts_work_func use
-static int p_point_num = 0xFFFF;
-static int tpd_key;
-static int tpd_key_old;
-static int probe_fail_flag;
-static bool config_load;
+static uint8_t vk_press = 0x00;
+static uint8_t AA_press = 0x00;
+static uint8_t EN_NoiseFilter = 0x00;
+static int hx_point_num; /*for himax_ts_work_func use*/
+static int p_point_num = 0xFFFF;
+static int tpd_key = 0x00;
+static int tpd_key_old = 0x00;
+static int probe_fail_flag;
+static bool config_load;
static struct himax_config *config_selected;
-//static int iref_number = 11;
-//static bool iref_found = false;
+/*static int iref_number = 11;*/
+/*static bool iref_found = false;*/
-#ifdef HX_USB_DETECT2
-extern bool USB_Flag;
-#endif
#if defined(CONFIG_FB)
int fb_notifier_callback(struct notifier_block *self,
@@ -134,6 +59,7 @@
int himax_input_register(struct himax_ts_data *ts)
{
int ret;
+
ts->input_dev = input_allocate_device();
if (ts->input_dev == NULL) {
ret = -ENOMEM;
@@ -175,25 +101,36 @@
set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit);
if (ts->protocol_type == PROTOCOL_TYPE_A) {
- //ts->input_dev->mtsize = ts->nFinger_support;
+ /*ts->input_dev->mtsize = ts->nFinger_support;*/
input_set_abs_params(ts->input_dev, ABS_MT_TRACKING_ID,
0, 3, 0, 0);
} else {/* PROTOCOL_TYPE_B */
set_bit(MT_TOOL_FINGER, ts->input_dev->keybit);
- input_mt_init_slots(ts->input_dev, ts->nFinger_support,0);
+ input_mt_init_slots(ts->input_dev, ts->nFinger_support, 0);
}
I("input_set_abs_params: mix_x %d, max_x %d, min_y %d, max_y %d\n",
- ts->pdata->abs_x_min, ts->pdata->abs_x_max, ts->pdata->abs_y_min, ts->pdata->abs_y_max);
+ ts->pdata->abs_x_min, ts->pdata->abs_x_max,
+ ts->pdata->abs_y_min, ts->pdata->abs_y_max);
- input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X,ts->pdata->abs_x_min, ts->pdata->abs_x_max, ts->pdata->abs_x_fuzz, 0);
- input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y,ts->pdata->abs_y_min, ts->pdata->abs_y_max, ts->pdata->abs_y_fuzz, 0);
- input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR,ts->pdata->abs_pressure_min, ts->pdata->abs_pressure_max, ts->pdata->abs_pressure_fuzz, 0);
- input_set_abs_params(ts->input_dev, ABS_MT_PRESSURE,ts->pdata->abs_pressure_min, ts->pdata->abs_pressure_max, ts->pdata->abs_pressure_fuzz, 0);
- input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR,ts->pdata->abs_width_min, ts->pdata->abs_width_max, ts->pdata->abs_pressure_fuzz, 0);
+ input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X,
+ ts->pdata->abs_x_min, ts->pdata->abs_x_max, ts->pdata->abs_x_fuzz, 0);
+ input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y,
+ ts->pdata->abs_y_min, ts->pdata->abs_y_max, ts->pdata->abs_y_fuzz, 0);
+ input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR,
+ ts->pdata->abs_pressure_min, ts->pdata->abs_pressure_max,
+ ts->pdata->abs_pressure_fuzz, 0);
+ input_set_abs_params(ts->input_dev, ABS_MT_PRESSURE,
+ ts->pdata->abs_pressure_min, ts->pdata->abs_pressure_max,
+ ts->pdata->abs_pressure_fuzz, 0);
+ input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR,
+ ts->pdata->abs_width_min, ts->pdata->abs_width_max,
+ ts->pdata->abs_pressure_fuzz, 0);
-// input_set_abs_params(ts->input_dev, ABS_MT_AMPLITUDE, 0, ((ts->pdata->abs_pressure_max << 16) | ts->pdata->abs_width_max), 0, 0);
-// input_set_abs_params(ts->input_dev, ABS_MT_POSITION, 0, (BIT(31) | (ts->pdata->abs_x_max << 16) | ts->pdata->abs_y_max), 0, 0);
+/*input_set_abs_params(ts->input_dev, ABS_MT_AMPLITUDE, 0,
+((ts->pdata->abs_pressure_max << 16) | ts->pdata->abs_width_max), 0, 0);*/
+/*input_set_abs_params(ts->input_dev, ABS_MT_POSITION, 0,
+(BIT(31) | (ts->pdata->abs_x_max << 16) | ts->pdata->abs_y_max), 0, 0);*/
return input_register_device(ts->input_dev);
}
@@ -201,87 +138,103 @@
static void calcDataSize(uint8_t finger_num)
{
struct himax_ts_data *ts_data = private_ts;
+
ts_data->coord_data_size = 4 * finger_num;
- ts_data->area_data_size = ((finger_num / 4) + (finger_num % 4 ? 1 : 0)) * 4;
- ts_data->raw_data_frame_size = 128 - ts_data->coord_data_size - ts_data->area_data_size - 4 - 4 - 1;
- ts_data->raw_data_nframes = ((uint32_t)ts_data->x_channel * ts_data->y_channel +
- ts_data->x_channel + ts_data->y_channel) / ts_data->raw_data_frame_size +
- (((uint32_t)ts_data->x_channel * ts_data->y_channel +
- ts_data->x_channel + ts_data->y_channel) % ts_data->raw_data_frame_size)? 1 : 0;
- I("%s: coord_data_size: %d, area_data_size:%d, raw_data_frame_size:%d, raw_data_nframes:%d", __func__, ts_data->coord_data_size, ts_data->area_data_size, ts_data->raw_data_frame_size, ts_data->raw_data_nframes);
+ ts_data->area_data_size = ((finger_num / 4) +
+ (finger_num % 4 ? 1 : 0)) * 4;
+ ts_data->raw_data_frame_size = 128 -
+ ts_data->coord_data_size -
+ ts_data->area_data_size - 4 - 4 - 1;
+
+ ts_data->raw_data_nframes =
+ ((uint32_t)ts_data->x_channel *
+ ts_data->y_channel + ts_data->x_channel + ts_data->y_channel) /
+ ts_data->raw_data_frame_size + (((uint32_t)ts_data->x_channel *
+ ts_data->y_channel + ts_data->x_channel + ts_data->y_channel) %
+ ts_data->raw_data_frame_size) ? 1 : 0;
+
+ I("%s: coord_data_size: %d, area_data_size:%d",
+ __func__, ts_data->coord_data_size, ts_data->area_data_size);
+ I("raw_data_frame_size:%d, raw_data_nframes:%d",
+ ts_data->raw_data_frame_size, ts_data->raw_data_nframes);
}
static void calculate_point_number(void)
{
- HX_TOUCH_INFO_POINT_CNT = ic_data->HX_MAX_PT * 4 ;
+ HX_TOUCH_INFO_POINT_CNT = ic_data->HX_MAX_PT * 4;
- if ( (ic_data->HX_MAX_PT % 4) == 0)
- HX_TOUCH_INFO_POINT_CNT += (ic_data->HX_MAX_PT / 4) * 4 ;
+ if ((ic_data->HX_MAX_PT % 4) == 0)
+ HX_TOUCH_INFO_POINT_CNT += (ic_data->HX_MAX_PT / 4) * 4;
else
- HX_TOUCH_INFO_POINT_CNT += ((ic_data->HX_MAX_PT / 4) +1) * 4 ;
+ HX_TOUCH_INFO_POINT_CNT += ((ic_data->HX_MAX_PT / 4) + 1) * 4;
}
-#if 0
+/*#if 0*/
+#ifdef HX_EN_CHECK_PATCH
static int himax_read_Sensor_ID(struct i2c_client *client)
-{
- uint8_t val_high[1], val_low[1], ID0=0, ID1=0;
+{
+ uint8_t val_high[1], val_low[1], ID0 = 0, ID1 = 0;
char data[3];
const int normalRetry = 10;
int sensor_id;
-
- data[0] = 0x56; data[1] = 0x02; data[2] = 0x02;/*ID pin PULL High*/
- i2c_himax_master_write(client, &data[0],3,normalRetry);
- usleep_range(1000, 2000);
- //read id pin high
+ data[0] = 0x56; data[1] = 0x02;
+ data[2] = 0x02;/*ID pin PULL High*/
+ i2c_himax_master_write(client, &data[0], 3, normalRetry);
+ usleep(1000);
+
+ /*read id pin high*/
i2c_himax_read(client, 0x57, val_high, 1, normalRetry);
- data[0] = 0x56; data[1] = 0x01; data[2] = 0x01;/*ID pin PULL Low*/
- i2c_himax_master_write(client, &data[0],3,normalRetry);
- usleep_range(1000, 2000);
+ data[0] = 0x56; data[1] = 0x01;
+ data[2] = 0x01;/*ID pin PULL Low*/
+ i2c_himax_master_write(client, &data[0], 3, normalRetry);
+ usleep(1000);
- //read id pin low
+ /*read id pin low*/
i2c_himax_read(client, 0x57, val_low, 1, normalRetry);
- if((val_high[0] & 0x01) ==0)
- ID0=0x02;/*GND*/
- else if((val_low[0] & 0x01) ==0)
- ID0=0x01;/*Floating*/
+ if ((val_high[0] & 0x01) == 0)
+ ID0 = 0x02;/*GND*/
+ else if ((val_low[0] & 0x01) == 0)
+ ID0 = 0x01;/*Floating*/
else
- ID0=0x04;/*VCC*/
-
- if((val_high[0] & 0x02) ==0)
- ID1=0x02;/*GND*/
- else if((val_low[0] & 0x02) ==0)
- ID1=0x01;/*Floating*/
+ ID0 = 0x04;/*VCC*/
+
+ if ((val_high[0] & 0x02) == 0)
+ ID1 = 0x02;/*GND*/
+ else if ((val_low[0] & 0x02) == 0)
+ ID1 = 0x01;/*Floating*/
else
- ID1=0x04;/*VCC*/
- if((ID0==0x04)&&(ID1!=0x04))
- {
- data[0] = 0x56; data[1] = 0x02; data[2] = 0x01;/*ID pin PULL High,Low*/
- i2c_himax_master_write(client, &data[0],3,normalRetry);
- usleep_range(1000, 2000);
+ ID1 = 0x04;/*VCC*/
+ if ((ID0 == 0x04) && (ID1 != 0x04)) {
+ data[0] = 0x56; data[1] = 0x02;
+ data[2] = 0x01;/*ID pin PULL High,Low*/
+ i2c_himax_master_write(client,
+ &data[0], 3, normalRetry);
+ usleep(1000);
- }
- else if((ID0!=0x04)&&(ID1==0x04))
- {
- data[0] = 0x56; data[1] = 0x01; data[2] = 0x02;/*ID pin PULL Low,High*/
- i2c_himax_master_write(client, &data[0],3,normalRetry);
- usleep_range(1000, 2000);
+ } else if ((ID0 != 0x04) && (ID1 == 0x04)) {
+ data[0] = 0x56; data[1] = 0x01;
+ data[2] = 0x02;/*ID pin PULL Low,High*/
+ i2c_himax_master_write(client,
+ &data[0], 3, normalRetry);
+ usleep(1000);
- }
- else if((ID0==0x04)&&(ID1==0x04))
- {
- data[0] = 0x56; data[1] = 0x02; data[2] = 0x02;/*ID pin PULL High,High*/
- i2c_himax_master_write(client, &data[0],3,normalRetry);
- usleep_range(1000, 2000);
+ } else if ((ID0 == 0x04) && (ID1 == 0x04)) {
+ data[0] = 0x56; data[1] = 0x02;
+ data[2] = 0x02;/*ID pin PULL High,High*/
+ i2c_himax_master_write(client,
+ &data[0], 3, normalRetry);
+ usleep(1000);
- }
- sensor_id=(ID1<<4)|ID0;
+ }
+ sensor_id = (ID1<<4)|ID0;
data[0] = 0xE4; data[1] = sensor_id;
- i2c_himax_master_write(client, &data[0],2,normalRetry);/*Write to MCU*/
- usleep_range(1000, 2000);
+ i2c_himax_master_write(client,
+ &data[0], 2, normalRetry);/*Write to MCU*/
+ usleep(1000);
return sensor_id;
@@ -290,125 +243,173 @@
static void himax_power_on_initCMD(struct i2c_client *client)
{
I("%s:\n", __func__);
-
himax_touch_information(client);
-
- //himax_sense_on(private_ts->client, 0x01);//1=Flash, 0=SRAM
+ /*himax_sense_on(private_ts->client, 0x01);//1=Flash, 0=SRAM */
}
#ifdef HX_AUTO_UPDATE_FW
static int i_update_FW(void)
{
int upgrade_times = 0;
- unsigned char* ImageBuffer = i_CTPM_FW;
- int fullFileLength = sizeof(i_CTPM_FW);
+ int fullFileLength = 0;
int i_FW_VER = 0, i_CFG_VER = 0;
- uint8_t ret = -1, result = 0;
-// uint8_t tmp_addr[4];
-// uint8_t tmp_data[4];
+ int ret = -1, result = 0;
+ /*uint8_t tmp_addr[4];*/
+ /*uint8_t tmp_data[4];*/
int CRC_from_FW = 0;
int CRC_Check_result = 0;
- i_FW_VER = i_CTPM_FW[FW_VER_MAJ_FLASH_ADDR]<<8 |i_CTPM_FW[FW_VER_MIN_FLASH_ADDR];
- i_CFG_VER = i_CTPM_FW[CFG_VER_MAJ_FLASH_ADDR]<<8 |i_CTPM_FW[CFG_VER_MIN_FLASH_ADDR];
+ ret = himax_load_CRC_bin_file(private_ts->client);
+ if (ret < 0) {
+ E("%s: himax_load_CRC_bin_file fail Error Code=%d.\n",
+ __func__, ret);
+ ret = -1;
+ return ret;
+ }
+ I("file name = %s\n", i_CTPM_firmware_name);
+ ret = request_firmware(&i_CTPM_FW,
+ i_CTPM_firmware_name, private_ts->dev);
+ if (ret < 0) {
+ E("%s,fail in line%d error code=%d\n",
+ __func__, __LINE__, ret);
+ ret = -2;
+ return ret;
+ }
- I("%s: i_fullFileLength = %d\n", __func__,fullFileLength);
+ if (i_CTPM_FW == NULL) {
+ I("%s: i_CTPM_FW = NULL\n", __func__);
+ ret = -3;
+ return ret;
+ }
+ fullFileLength = i_CTPM_FW->size;
+
+ i_FW_VER = i_CTPM_FW->data[FW_VER_MAJ_FLASH_ADDR]<<8
+ | i_CTPM_FW->data[FW_VER_MIN_FLASH_ADDR];
+ i_CFG_VER = i_CTPM_FW->data[CFG_VER_MAJ_FLASH_ADDR]<<8
+ | i_CTPM_FW->data[CFG_VER_MIN_FLASH_ADDR];
+
+ I("%s: i_fullFileLength = %d\n", __func__, fullFileLength);
himax_sense_off(private_ts->client);
msleep(500);
- CRC_from_FW = himax_check_CRC(private_ts->client,fw_image_64k);
- CRC_Check_result = Calculate_CRC_with_AP(ImageBuffer, CRC_from_FW,fw_image_64k);
- I("%s: Check sum result = %d\n", __func__,CRC_Check_result);
- //I("%s: ic_data->vendor_fw_ver = %X, i_FW_VER = %X,\n", __func__,ic_data->vendor_fw_ver, i_FW_VER);
- //I("%s: ic_data->vendor_config_ver = %X, i_CFG_VER = %X,\n", __func__,ic_data->vendor_config_ver, i_CFG_VER);
-
- if ((CRC_Check_result == 0)|| ( ic_data->vendor_fw_ver < i_FW_VER ) || ( ic_data->vendor_config_ver < i_CFG_VER ))
- {
- himax_int_enable(private_ts->client->irq,0);
+ CRC_from_FW = himax_check_CRC(private_ts->client, fw_image_64k);
+ CRC_Check_result =
+ Calculate_CRC_with_AP((unsigned char *)i_CTPM_FW->data,
+ CRC_from_FW, fw_image_64k);
+ I("%s: Check sum result = %d\n", __func__, CRC_Check_result);
+ /*I("%s: ic_data->vendor_fw_ver = %X, i_FW_VER = %X,\n",
+ __func__, ic_data->vendor_fw_ver, i_FW_VER);*/
+ /*I("%s: ic_data->vendor_config_ver = %X, i_CFG_VER = %X,\n",
+ __func__, ic_data->vendor_config_ver, i_CFG_VER);*/
+
+ if ((CRC_Check_result == 0) ||
+ (ic_data->vendor_fw_ver < i_FW_VER) ||
+ (ic_data->vendor_config_ver < i_CFG_VER)) {
+ himax_int_enable(private_ts->client->irq, 0);
update_retry:
- if(fullFileLength == FW_SIZE_60k){
- ret = fts_ctpm_fw_upgrade_with_sys_fs_60k(private_ts->client,ImageBuffer,fullFileLength,false);
- }else if (fullFileLength == FW_SIZE_64k){
- ret = fts_ctpm_fw_upgrade_with_sys_fs_64k(private_ts->client,ImageBuffer,fullFileLength,false);
- }else if (fullFileLength == FW_SIZE_124k){
- ret = fts_ctpm_fw_upgrade_with_sys_fs_124k(private_ts->client,ImageBuffer,fullFileLength,false);
- }else if (fullFileLength == FW_SIZE_128k){
- ret = fts_ctpm_fw_upgrade_with_sys_fs_128k(private_ts->client,ImageBuffer,fullFileLength,false);
- }
- if(ret == 0){
- upgrade_times++;
- E("%s: TP upgrade error, upgrade_times = %d\n", __func__, upgrade_times);
- if(upgrade_times < 3)
- goto update_retry;
- else
- {
- himax_sense_on(private_ts->client, 0x01);
- msleep(120);
-#ifdef HX_ESD_WORKAROUND
- HX_ESD_RESET_ACTIVATE = 1;
-#endif
- result = -1;//upgrade fail
- }
- }
- else if(ret == 1){
-/*
- // 1. Set DDREG_Req = 1 (0x9000_0020 = 0x0000_0001) (Lock register R/W from driver)
- tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
- tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x01;
- himax_register_write(private_ts->client, tmp_addr, 1, tmp_data);
-
- // 2. Write driver initial code condition
- // write value from AHB I2C : 0x8001_C603 = 0x000000FF
- tmp_addr[3] = 0x80; tmp_addr[2] = 0x01; tmp_addr[1] = 0xC6; tmp_addr[0] = 0x03;
- tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0xFF;
- himax_register_write(private_ts->client, tmp_addr, 1, tmp_data);
-
- // 1. Set DDREG_Req = 0 (0x9000_0020 = 0x0000_0001) (Lock register R/W from driver)
- tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
- tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
- himax_register_write(private_ts->client, tmp_addr, 1, tmp_data);
-*/
+ if (fullFileLength == FW_SIZE_60k) {
+ ret = fts_ctpm_fw_upgrade_with_sys_fs_60k
+ (private_ts->client,
+ (unsigned char *)i_CTPM_FW->data,
+ fullFileLength, false);
+ } else if (fullFileLength == FW_SIZE_64k) {
+ ret = fts_ctpm_fw_upgrade_with_sys_fs_64k
+ (private_ts->client,
+ (unsigned char *)i_CTPM_FW->data,
+ fullFileLength, false);
+ } else if (fullFileLength == FW_SIZE_124k) {
+ ret = fts_ctpm_fw_upgrade_with_sys_fs_124k
+ (private_ts->client,
+ (unsigned char *)i_CTPM_FW->data,
+ fullFileLength, false);
+ } else if (fullFileLength == FW_SIZE_128k) {
+ ret = fts_ctpm_fw_upgrade_with_sys_fs_128k
+ (private_ts->client,
+ (unsigned char *)i_CTPM_FW->data,
+ fullFileLength, false);
+ }
+ if (ret == 0) {
+ upgrade_times++;
+ E("%s: TP upgrade error, upgrade_times = %d\n",
+ __func__, upgrade_times);
+ if (upgrade_times < 3)
+ goto update_retry;
+ else {
himax_sense_on(private_ts->client, 0x01);
msleep(120);
#ifdef HX_ESD_WORKAROUND
HX_ESD_RESET_ACTIVATE = 1;
#endif
-
- ic_data->vendor_fw_ver = i_FW_VER;
- ic_data->vendor_config_ver = i_CFG_VER;
- result = 1;//upgrade success
- I("%s: TP upgrade OK\n", __func__);
+ result = -1;/*upgrade fail*/
}
+ } else if (ret == 1) {
+ /*
+ // 1. Set DDREG_Req = 1 (0x9000_0020 = 0x0000_0001)
+ (Lock register R/W from driver)
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = 0x01;
+ himax_register_write(private_ts->client,
+ tmp_addr, 1, tmp_data);
- himax_int_enable(private_ts->client->irq,1);
- return result;
- }
- else
- {
+ // 2. Write driver initial code condition
+ //write value from AHB I2C:0x8001_C603 = 0x000000FF
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x01;
+ tmp_addr[1] = 0xC6; tmp_addr[0] = 0x03;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = 0xFF;
+ himax_register_write(private_ts->client,
+ tmp_addr, 1, tmp_data);
+
+ // 1. Set DDREG_Req = 0(0x9000_0020 = 0x0000_0001)
+ (Lock register R/W from driver)
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ himax_register_write(private_ts->client,
+ tmp_addr, 1, tmp_data);
+ */
himax_sense_on(private_ts->client, 0x01);
- return 0;//NO upgrade
+ msleep(120);
+#ifdef HX_ESD_WORKAROUND
+ HX_ESD_RESET_ACTIVATE = 1;
+#endif
+
+ ic_data->vendor_fw_ver = i_FW_VER;
+ ic_data->vendor_config_ver = i_CFG_VER;
+ result = 1;/*upgrade success*/
+ I("%s: TP upgrade OK\n", __func__);
}
+
+ himax_int_enable(private_ts->client->irq, 1);
+ return result;
+
+ } else {
+ himax_sense_on(private_ts->client, 0x01);
+ return 0;/*NO upgrade*/
+ }
}
-#endif
+#endif
#ifdef HX_RST_PIN_FUNC
-void himax_HW_reset(uint8_t loadconfig,uint8_t int_off)
+void himax_HW_reset(uint8_t loadconfig, uint8_t int_off)
{
struct himax_ts_data *ts = private_ts;
int ret = 0;
return;
if (ts->rst_gpio) {
- if(int_off)
- {
- if (ts->use_irq)
- himax_int_enable(private_ts->client->irq,0);
- else {
- hrtimer_cancel(&ts->timer);
- ret = cancel_work_sync(&ts->work);
- }
+ if (int_off) {
+ if (ts->use_irq)
+ himax_int_enable(private_ts->client->irq, 0);
+ else {
+ hrtimer_cancel(&ts->timer);
+ ret = cancel_work_sync(&ts->work);
}
+ }
I("%s: Now reset the Touch chip.\n", __func__);
@@ -417,51 +418,51 @@
himax_rst_gpio_set(ts->rst_gpio, 1);
msleep(20);
- if(loadconfig)
- himax_loadSensorConfig(private_ts->client,private_ts->pdata);
+ if (loadconfig)
+ himax_loadSensorConfig(private_ts->client,
+ private_ts->pdata);
- if(int_off)
- {
- if (ts->use_irq)
- himax_int_enable(private_ts->client->irq,1);
- else
- hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
- }
+ if (int_off) {
+ if (ts->use_irq)
+ himax_int_enable(private_ts->client->irq, 1);
+ else
+ hrtimer_start(&ts->timer,
+ ktime_set(1, 0), HRTIMER_MODE_REL);
+ }
}
}
#endif
-int himax_loadSensorConfig(struct i2c_client *client, struct himax_i2c_platform_data *pdata)
+int himax_loadSensorConfig(struct i2c_client *client,
+struct himax_i2c_platform_data *pdata)
{
+ int err = -1;
if (!client) {
E("%s: Necessary parameters client are null!\n", __func__);
- return -EINVAL;
+ return err;
}
-
- if(config_load == false)
- {
- config_selected = kzalloc(sizeof(*config_selected), GFP_KERNEL);
- if (config_selected == NULL) {
- E("%s: alloc config_selected fail!\n", __func__);
- return -ENOMEM;
- }
+ if (config_load == false) {
+ config_selected = kzalloc(sizeof(*config_selected), GFP_KERNEL);
+ if (config_selected == NULL) {
+ E("%s: alloc config_selected fail!\n", __func__);
+ return err;
}
+ }
+ himax_power_on_initCMD(client);
- himax_power_on_initCMD(client);
-
- himax_int_enable(client->irq,0);
- himax_read_FW_ver(client);
+ himax_int_enable(client->irq, 0);
+ himax_read_FW_ver(client);
#ifdef HX_RST_PIN_FUNC
- himax_HW_reset(true,false);
+ himax_HW_reset(true, false);
#endif
- himax_int_enable(client->irq,1);
- I("FW_VER : %X \n",ic_data->vendor_fw_ver);
+ himax_int_enable(client->irq, 1);
+ I("FW_VER : %X\n", ic_data->vendor_fw_ver);
- ic_data->vendor_sensor_id=0x2602;
- I("sensor_id=%x.\n",ic_data->vendor_sensor_id);
+ ic_data->vendor_sensor_id = 0x2602;
+ I("sensor_id=%x.\n", ic_data->vendor_sensor_id);
- himax_sense_on(private_ts->client, 0x01);//1=Flash, 0=SRAM
+ himax_sense_on(private_ts->client, 0x01);/*1=Flash, 0=SRAM*/
msleep(120);
#ifdef HX_ESD_WORKAROUND
HX_ESD_RESET_ACTIVATE = 1;
@@ -474,47 +475,49 @@
#ifdef HX_ESD_WORKAROUND
void ESD_HW_REST(void)
{
- I("START_Himax TP: ESD - Reset\n");
-
+ I("START_Himax TP: ESD - Reset\n");
+
HX_report_ESD_event();
ESD_00_counter = 0;
ESD_00_Flag = 0;
- /*************************************/
- if (private_ts->protocol_type == PROTOCOL_TYPE_A)
+ /*************************************/
+ if (private_ts->protocol_type == PROTOCOL_TYPE_A)
input_mt_sync(private_ts->input_dev);
- input_report_key(private_ts->input_dev, BTN_TOUCH, 0);
- input_sync(private_ts->input_dev);
- /*************************************/
+ input_report_key(private_ts->input_dev, BTN_TOUCH, 0);
+ input_sync(private_ts->input_dev);
+ /*************************************/
I("END_Himax TP: ESD - Reset\n");
}
#endif
#ifdef HX_HIGH_SENSE
-void himax_set_HSEN_func(struct i2c_client *client,uint8_t HSEN_enable)
+void himax_set_HSEN_func(struct i2c_client *client, uint8_t HSEN_enable)
{
uint8_t tmp_data[4];
- if(HSEN_enable)
- {
+ if (HSEN_enable) {
I(" %s in", __func__);
- HSEN_bit_retry:
- himax_set_HSEN_enable(client,HSEN_enable);
+HSEN_bit_retry:
+ himax_set_HSEN_enable(client, HSEN_enable);
msleep(20);
- himax_get_HSEN_enable(client,tmp_data);
- I("%s: Read HSEN bit data[0]=%x data[1]=%x data[2]=%x data[3]=%x\n", __func__
- ,tmp_data[0],tmp_data[1],tmp_data[2],tmp_data[3]);
- if(tmp_data[0]!= 0x01)
- {
- I("%s: retry HSEN bit write data[0]=%x \n",__func__,tmp_data[0]);
- goto HSEN_bit_retry;
- }
+ himax_get_HSEN_enable(client, tmp_data);
+ I("%s: Read HSEN bit data[0]=%x data[1]=%x",
+ __func__, tmp_data[0], tmp_data[1]);
+ I("data[2]=%x data[3]=%x\n",
+ tmp_data[2], tmp_data[3]);
+
+ if (tmp_data[0] != 0x01) {
+ I("%s: retry HSEN bit write data[0]=%x\n",
+ __func__, tmp_data[0]);
+ goto HSEN_bit_retry;
+ }
}
}
static void himax_HSEN_func(struct work_struct *work)
{
- struct himax_ts_data *ts = container_of(work, struct himax_ts_data,
- hsen_work.work);
+ struct himax_ts_data *ts =
+ container_of(work, struct himax_ts_data, hsen_work.work);
himax_set_HSEN_func(ts->client, ts->HSEN_enable);
}
@@ -525,9 +528,10 @@
#ifdef HX_GESTURE_TRACK
static void gest_pt_log_coordinate(int rx, int tx)
{
- //driver report x y with range 0 - 255 , we scale it up to x/y pixel
- gest_pt_x[gest_pt_cnt] = rx*(ic_data->HX_X_RES)/255;
- gest_pt_y[gest_pt_cnt] = tx*(ic_data->HX_Y_RES)/255;
+ /*driver report x y with range 0 - 255*/
+ /* And we scale it up to x/y coordinates*/
+ gest_pt_x[gest_pt_cnt] = rx * (ic_data->HX_X_RES) / 255;
+ gest_pt_y[gest_pt_cnt] = tx * (ic_data->HX_Y_RES) / 255;
}
#endif
static int himax_parse_wake_event(struct himax_ts_data *ts)
@@ -535,145 +539,143 @@
uint8_t buf[64];
unsigned char check_sum_cal = 0;
#ifdef HX_GESTURE_TRACK
- int tmp_max_x=0x00,tmp_min_x=0xFFFF,tmp_max_y=0x00,tmp_min_y=0xFFFF;
+ int tmp_max_x = 0x00, tmp_min_x = 0xFFFF,
+ tmp_max_y = 0x00, tmp_min_y = 0xFFFF;
int gest_len;
#endif
- int i=0, check_FC = 0, gesture_flag = 0;
+ int i = 0, check_FC = 0, gesture_flag = 0;
himax_burst_enable(ts->client, 0);
- himax_read_event_stack(ts->client,buf,56);
+ himax_read_event_stack(ts->client, buf, 56);
- for(i=0;i<GEST_PTLG_ID_LEN;i++)
- {
- if (check_FC==0)
- {
- if((buf[0]!=0x00)&&((buf[0]<=0x0F)||(buf[0]==0x80)))
- {
+ for (i = 0 ; i < GEST_PTLG_ID_LEN ; i++) {
+ if (check_FC == 0) {
+ if ((buf[0] != 0x00) &&
+ ((buf[0] <= 0x0F) || (buf[0] == 0x80))) {
check_FC = 1;
gesture_flag = buf[i];
- }
- else
- {
+ } else {
check_FC = 0;
- I("ID START at %x , value = %x skip the event\n", i, buf[i]);
+ I("ID START at %x,value = %x skip event\n",
+ i, buf[i]);
break;
}
- }
- else
- {
- if(buf[i]!=gesture_flag)
- {
+ } else {
+ if (buf[i] != gesture_flag) {
check_FC = 0;
- I("ID NOT the same %x != %x So STOP parse event\n", buf[i], gesture_flag);
+ I("ID NOT same %x != %x So STOP parse event\n",
+ buf[i], gesture_flag);
break;
}
}
I("0x%2.2X ", buf[i]);
if (i % 8 == 7)
- I("\n");
+ I("\n");
}
- I("Himax gesture_flag= %x\n",gesture_flag );
+ I("Himax gesture_flag= %x\n", gesture_flag);
I("Himax check_FC is %d\n", check_FC);
if (check_FC == 0)
return 0;
- if(buf[GEST_PTLG_ID_LEN] != GEST_PTLG_HDR_ID1 ||
- buf[GEST_PTLG_ID_LEN+1] != GEST_PTLG_HDR_ID2)
+ if (buf[GEST_PTLG_ID_LEN] != GEST_PTLG_HDR_ID1
+ || buf[GEST_PTLG_ID_LEN+1] != GEST_PTLG_HDR_ID2)
return 0;
- for(i=0;i<(GEST_PTLG_ID_LEN+GEST_PTLG_HDR_LEN);i++)
- {
- I("P[%x]=0x%2.2X \n", i, buf[i]);
- I("checksum=0x%2.2X \n", check_sum_cal);
+ for (i = 0 ; i < (GEST_PTLG_ID_LEN + GEST_PTLG_HDR_LEN) ; i++) {
+ I("P[%x]=0x%2.2X\n", i, buf[i]);
+ I("checksum=0x%2.2X\n", check_sum_cal);
check_sum_cal += buf[i];
}
- if ((check_sum_cal != 0x00) )
- {
- I(" %s : check_sum_cal: 0x%02X\n",__func__ ,check_sum_cal);
+ if ((check_sum_cal != 0x00)) {
+ I(" %s : check_sum_cal: 0x%02X\n", __func__ , check_sum_cal);
return 0;
}
#ifdef HX_GESTURE_TRACK
- if(buf[GEST_PTLG_ID_LEN] == GEST_PTLG_HDR_ID1 &&
- buf[GEST_PTLG_ID_LEN+1] == GEST_PTLG_HDR_ID2)
- {
- gest_len = buf[GEST_PTLG_ID_LEN+2];
-
- I("gest_len = %d ",gest_len);
-
+ if (buf[GEST_PTLG_ID_LEN] == GEST_PTLG_HDR_ID1
+ && buf[GEST_PTLG_ID_LEN+1] == GEST_PTLG_HDR_ID2) {
+ gest_len = buf[GEST_PTLG_ID_LEN + 2];
+ I("gest_len = %d ", gest_len);
i = 0;
gest_pt_cnt = 0;
- I("gest doornidate start \n %s",__func__);
- while(i<(gest_len+1)/2)
- {
- gest_pt_log_coordinate(buf[GEST_PTLG_ID_LEN+4+i*2],buf[GEST_PTLG_ID_LEN+4+i*2+1]);
+ I("gest doornidate start\n %s", __func__);
+ while (i < (gest_len + 1) / 2) {
+ gest_pt_log_coordinate
+ (buf[GEST_PTLG_ID_LEN + 4 + i * 2],
+ buf[GEST_PTLG_ID_LEN + 4 + i * 2 + 1]);
i++;
- I("gest_pt_x[%d]=%d \n",gest_pt_cnt,gest_pt_x[gest_pt_cnt]);
- I("gest_pt_y[%d]=%d \n",gest_pt_cnt,gest_pt_y[gest_pt_cnt]);
+ I("gest_pt_x[%d]=%d\n",
+ gest_pt_cnt, gest_pt_x[gest_pt_cnt]);
+ I("gest_pt_y[%d]=%d\n",
+ gest_pt_cnt, gest_pt_y[gest_pt_cnt]);
- gest_pt_cnt +=1;
+ gest_pt_cnt += 1;
}
- if(gest_pt_cnt)
- {
- for(i=0; i<gest_pt_cnt; i++)
- {
- if(tmp_max_x<gest_pt_x[i])
- tmp_max_x=gest_pt_x[i];
- if(tmp_min_x>gest_pt_x[i])
- tmp_min_x=gest_pt_x[i];
- if(tmp_max_y<gest_pt_y[i])
- tmp_max_y=gest_pt_y[i];
- if(tmp_min_y>gest_pt_y[i])
- tmp_min_y=gest_pt_y[i];
- }
- I("gest_point x_min= %d, x_max= %d, y_min= %d, y_max= %d\n",tmp_min_x,tmp_max_x,tmp_min_y,tmp_max_y);
- gest_start_x=gest_pt_x[0];
- gn_gesture_coor[0] = gest_start_x;
- gest_start_y=gest_pt_y[0];
- gn_gesture_coor[1] = gest_start_y;
- gest_end_x=gest_pt_x[gest_pt_cnt-1];
- gn_gesture_coor[2] = gest_end_x;
- gest_end_y=gest_pt_y[gest_pt_cnt-1];
- gn_gesture_coor[3] = gest_end_y;
- gest_width = tmp_max_x - tmp_min_x;
- gn_gesture_coor[4] = gest_width;
- gest_height = tmp_max_y - tmp_min_y;
- gn_gesture_coor[5] = gest_height;
- gest_mid_x = (tmp_max_x + tmp_min_x)/2;
- gn_gesture_coor[6] = gest_mid_x;
- gest_mid_y = (tmp_max_y + tmp_min_y)/2;
- gn_gesture_coor[7] = gest_mid_y;
- gn_gesture_coor[8] = gest_mid_x;//gest_up_x
- gn_gesture_coor[9] = gest_mid_y-gest_height/2;//gest_up_y
- gn_gesture_coor[10] = gest_mid_x;//gest_down_x
- gn_gesture_coor[11] = gest_mid_y+gest_height/2; //gest_down_y
- gn_gesture_coor[12] = gest_mid_x-gest_width/2; //gest_left_x
- gn_gesture_coor[13] = gest_mid_y; //gest_left_y
- gn_gesture_coor[14] = gest_mid_x+gest_width/2; //gest_right_x
- gn_gesture_coor[15] = gest_mid_y; //gest_right_y
-
+ if (gest_pt_cnt) {
+ for (i = 0 ; i < gest_pt_cnt ; i++) {
+ if (tmp_max_x < gest_pt_x[i])
+ tmp_max_x = gest_pt_x[i];
+ if (tmp_min_x > gest_pt_x[i])
+ tmp_min_x = gest_pt_x[i];
+ if (tmp_max_y < gest_pt_y[i])
+ tmp_max_y = gest_pt_y[i];
+ if (tmp_min_y > gest_pt_y[i])
+ tmp_min_y = gest_pt_y[i];
}
+ I("gest_point x_min= %d, x_max= %d\n",
+ tmp_min_x, tmp_max_x);
+ I("y_min= %d, y_max= %d\n",
+ tmp_min_y, tmp_max_y);
+ gest_start_x = gest_pt_x[0];
+ gn_gesture_coor[0] = gest_start_x;
+ gest_start_y = gest_pt_y[0];
+ gn_gesture_coor[1] = gest_start_y;
+ gest_end_x = gest_pt_x[gest_pt_cnt - 1];
+ gn_gesture_coor[2] = gest_end_x;
+ gest_end_y = gest_pt_y[gest_pt_cnt - 1];
+ gn_gesture_coor[3] = gest_end_y;
+ gest_width = tmp_max_x - tmp_min_x;
+ gn_gesture_coor[4] = gest_width;
+ gest_height = tmp_max_y - tmp_min_y;
+ gn_gesture_coor[5] = gest_height;
+ gest_mid_x = (tmp_max_x + tmp_min_x) / 2;
+ gn_gesture_coor[6] = gest_mid_x;
+ gest_mid_y = (tmp_max_y + tmp_min_y) / 2;
+ gn_gesture_coor[7] = gest_mid_y;
+ /*gest_up_x*/
+ gn_gesture_coor[8] = gest_mid_x;
+ /*gest_up_y*/
+ gn_gesture_coor[9] = gest_mid_y - gest_height / 2;
+ /*gest_down_x*/
+ gn_gesture_coor[10] = gest_mid_x;
+ /*gest_down_y*/
+ gn_gesture_coor[11] = gest_mid_y + gest_height / 2;
+ /*gest_left_x*/
+ gn_gesture_coor[12] = gest_mid_x - gest_width / 2;
+ /*gest_left_y*/
+ gn_gesture_coor[13] = gest_mid_y;
+ /*gest_right_x*/
+ gn_gesture_coor[14] = gest_mid_x + gest_width / 2;
+ /*gest_right_y*/
+ gn_gesture_coor[15] = gest_mid_y;
+
+ }
}
#endif
- if(gesture_flag != 0x80)
- {
- if(!ts->gesture_cust_en[gesture_flag])
- {
- I("%s NOT report customer key \n ",__func__);
- return 0;//NOT report customer key
- }
- }
- else
- {
- if(!ts->gesture_cust_en[0])
- {
- I("%s NOT report report double click \n",__func__);
- return 0;//NOT report power key
- }
+ if (gesture_flag != 0x80) {
+ if (!ts->gesture_cust_en[gesture_flag]) {
+ I("%s NOT report customer key\n ", __func__);
+ return 0;/*NOT report customer key*/
+ }
+ } else {
+ if (!ts->gesture_cust_en[0]) {
+ I("%s NOT report report double click\n", __func__);
+ return 0;/*NOT report power key*/
+ }
}
- if(gesture_flag == 0x80)
+ if (gesture_flag == 0x80)
return EV_GESTURE_PWR;
else
return gesture_flag;
@@ -685,225 +687,242 @@
ret_event = himax_parse_wake_event(private_ts);
switch (ret_event) {
- case EV_GESTURE_PWR:
- KEY_EVENT = KEY_POWER;
+ case EV_GESTURE_PWR:
+ KEY_EVENT = KEY_POWER;
break;
- case EV_GESTURE_01:
- KEY_EVENT = KEY_CUST_01;
+ case EV_GESTURE_01:
+ KEY_EVENT = KEY_CUST_01;
break;
- case EV_GESTURE_02:
- KEY_EVENT = KEY_CUST_02;
+ case EV_GESTURE_02:
+ KEY_EVENT = KEY_CUST_02;
break;
- case EV_GESTURE_03:
- KEY_EVENT = KEY_CUST_03;
+ case EV_GESTURE_03:
+ KEY_EVENT = KEY_CUST_03;
break;
- case EV_GESTURE_04:
- KEY_EVENT = KEY_CUST_04;
+ case EV_GESTURE_04:
+ KEY_EVENT = KEY_CUST_04;
break;
- case EV_GESTURE_05:
- KEY_EVENT = KEY_CUST_05;
+ case EV_GESTURE_05:
+ KEY_EVENT = KEY_CUST_05;
break;
- case EV_GESTURE_06:
- KEY_EVENT = KEY_CUST_06;
+ case EV_GESTURE_06:
+ KEY_EVENT = KEY_CUST_06;
break;
- case EV_GESTURE_07:
- KEY_EVENT = KEY_CUST_07;
+ case EV_GESTURE_07:
+ KEY_EVENT = KEY_CUST_07;
break;
- case EV_GESTURE_08:
- KEY_EVENT = KEY_CUST_08;
+ case EV_GESTURE_08:
+ KEY_EVENT = KEY_CUST_08;
break;
- case EV_GESTURE_09:
- KEY_EVENT = KEY_CUST_09;
+ case EV_GESTURE_09:
+ KEY_EVENT = KEY_CUST_09;
break;
- case EV_GESTURE_10:
- KEY_EVENT = KEY_CUST_10;
+ case EV_GESTURE_10:
+ KEY_EVENT = KEY_CUST_10;
break;
- case EV_GESTURE_11:
- KEY_EVENT = KEY_CUST_11;
+ case EV_GESTURE_11:
+ KEY_EVENT = KEY_CUST_11;
break;
- case EV_GESTURE_12:
- KEY_EVENT = KEY_CUST_12;
+ case EV_GESTURE_12:
+ KEY_EVENT = KEY_CUST_12;
break;
- case EV_GESTURE_13:
- KEY_EVENT = KEY_CUST_13;
+ case EV_GESTURE_13:
+ KEY_EVENT = KEY_CUST_13;
break;
- case EV_GESTURE_14:
- KEY_EVENT = KEY_CUST_14;
+ case EV_GESTURE_14:
+ KEY_EVENT = KEY_CUST_14;
break;
- case EV_GESTURE_15:
- KEY_EVENT = KEY_CUST_15;
+ case EV_GESTURE_15:
+ KEY_EVENT = KEY_CUST_15;
break;
}
- if(ret_event)
- {
- I(" %s SMART WAKEUP KEY event %x press\n",__func__,KEY_EVENT);
- input_report_key(private_ts->input_dev, KEY_EVENT, 1);
- input_sync(private_ts->input_dev);
- //msleep(100);
- I(" %s SMART WAKEUP KEY event %x release\n",__func__,KEY_EVENT);
- input_report_key(private_ts->input_dev, KEY_EVENT, 0);
- input_sync(private_ts->input_dev);
- FAKE_POWER_KEY_SEND=true;
+ if (ret_event) {
+ I(" %s SMART WAKEUP KEY event %x press\n",
+ __func__, KEY_EVENT);
+ input_report_key(private_ts->input_dev, KEY_EVENT, 1);
+ input_sync(private_ts->input_dev);
+ /*msleep(100);*/
+ I(" %s SMART WAKEUP KEY event %x release\n",
+ __func__, KEY_EVENT);
+ input_report_key(private_ts->input_dev, KEY_EVENT, 0);
+ input_sync(private_ts->input_dev);
+ FAKE_POWER_KEY_SEND = true;
#ifdef HX_GESTURE_TRACK
- I("gest_start_x= %d, gest_start_y= %d, gest_end_x= %d, gest_end_y= %d\n",gest_start_x,gest_start_y,
- gest_end_x,gest_end_y);
- I("gest_width= %d, gest_height= %d, gest_mid_x= %d, gest_mid_y= %d\n",gest_width,gest_height,
- gest_mid_x,gest_mid_y);
- I("gest_up_x= %d, gest_up_y= %d, gest_down_x= %d, gest_down_y= %d\n",gn_gesture_coor[8],gn_gesture_coor[9],
- gn_gesture_coor[10],gn_gesture_coor[11]);
- I("gest_left_x= %d, gest_left_y= %d, gest_right_x= %d, gest_right_y= %d\n",gn_gesture_coor[12],gn_gesture_coor[13],
- gn_gesture_coor[14],gn_gesture_coor[15]);
+ I("gest_start_x= %d, gest_start_y= %d\n",
+ gest_start_x, gest_start_y);
+ I("gest_end_x= %d, gest_end_y= %d\n",
+ gest_end_x, gest_end_y);
+ I("gest_width= %d, gest_height= %d\n",
+ gest_width, gest_height);
+ I("gest_mid_x= %d, gest_mid_y= %d\n",
+ gest_mid_x, gest_mid_y);
+ I("gest_up_x= %d, gest_up_y= %d\n",
+ gn_gesture_coor[8], gn_gesture_coor[9]);
+ I("gest_down_x= %d, gest_down_y= %d\n",
+ gn_gesture_coor[10], gn_gesture_coor[11]);
+ I("gest_left_x= %d, gest_left_y= %d\n",
+ gn_gesture_coor[12], gn_gesture_coor[13]);
+ I("gest_right_x= %d, gest_right_y= %d\n",
+ gn_gesture_coor[14], gn_gesture_coor[15]);
#endif
- }
+ }
}
#endif
-static void himax_ts_button_func(int tp_key_index,struct himax_ts_data *ts)
+static void himax_ts_button_func(int tp_key_index, struct himax_ts_data *ts)
{
uint16_t x_position = 0, y_position = 0;
-if ( tp_key_index != 0x00)
- {
- I("virtual key index =%x\n",tp_key_index);
- if ( tp_key_index == 0x01) {
+
+ if (tp_key_index != 0x00) {
+ I("virtual key index =%x\n", tp_key_index);
+ if (tp_key_index == 0x01) {
vk_press = 1;
I("back key pressed\n");
- if (ts->pdata->virtual_key)
- {
- if (ts->button[0].index) {
- x_position = (ts->button[0].x_range_min + ts->button[0].x_range_max) / 2;
- y_position = (ts->button[0].y_range_min + ts->button[0].y_range_max) / 2;
- }
- if (ts->protocol_type == PROTOCOL_TYPE_A) {
- input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, 0);
- input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,
- 100);
- input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR,
- 100);
- input_report_abs(ts->input_dev, ABS_MT_PRESSURE,
- 100);
- input_report_abs(ts->input_dev, ABS_MT_POSITION_X,
- x_position);
- input_report_abs(ts->input_dev, ABS_MT_POSITION_Y,
- y_position);
- input_mt_sync(ts->input_dev);
- } else if (ts->protocol_type == PROTOCOL_TYPE_B) {
- input_mt_slot(ts->input_dev, 0);
- input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER,
- 1);
- input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,
- 100);
- input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR,
- 100);
- input_report_abs(ts->input_dev, ABS_MT_PRESSURE,
- 100);
- input_report_abs(ts->input_dev, ABS_MT_POSITION_X,
- x_position);
- input_report_abs(ts->input_dev, ABS_MT_POSITION_Y,
- y_position);
- }
+ if (ts->pdata->virtual_key) {
+ if (ts->button[0].index) {
+ x_position = (ts->button[0].x_range_min
+ + ts->button[0].x_range_max) / 2;
+ y_position = (ts->button[0].y_range_min
+ + ts->button[0].y_range_max) / 2;
}
- else
- input_report_key(ts->input_dev, KEY_BACK, 1);
- }
- else if ( tp_key_index == 0x02) {
+ if (ts->protocol_type == PROTOCOL_TYPE_A) {
+ input_report_abs(ts->input_dev,
+ ABS_MT_TRACKING_ID, 0);
+ input_report_abs(ts->input_dev,
+ ABS_MT_TOUCH_MAJOR, 100);
+ input_report_abs(ts->input_dev,
+ ABS_MT_WIDTH_MAJOR, 100);
+ input_report_abs(ts->input_dev,
+ ABS_MT_PRESSURE, 100);
+ input_report_abs(ts->input_dev,
+ ABS_MT_POSITION_X, x_position);
+ input_report_abs(ts->input_dev,
+ ABS_MT_POSITION_Y, y_position);
+ input_mt_sync(ts->input_dev);
+ } else if (ts->protocol_type
+ == PROTOCOL_TYPE_B) {
+ input_mt_slot(ts->input_dev, 0);
+
+ input_mt_report_slot_state
+ (ts->input_dev, MT_TOOL_FINGER, 1);
+
+ input_report_abs(ts->input_dev,
+ ABS_MT_TOUCH_MAJOR, 100);
+ input_report_abs(ts->input_dev,
+ ABS_MT_WIDTH_MAJOR, 100);
+ input_report_abs(ts->input_dev,
+ ABS_MT_PRESSURE, 100);
+ input_report_abs(ts->input_dev,
+ ABS_MT_POSITION_X, x_position);
+ input_report_abs(ts->input_dev,
+ ABS_MT_POSITION_Y, y_position);
+ }
+ } else
+ input_report_key(ts->input_dev, KEY_BACK, 1);
+ } else if (tp_key_index == 0x02) {
vk_press = 1;
I("home key pressed\n");
- if (ts->pdata->virtual_key)
- {
- if (ts->button[1].index) {
- x_position = (ts->button[1].x_range_min + ts->button[1].x_range_max) / 2;
- y_position = (ts->button[1].y_range_min + ts->button[1].y_range_max) / 2;
- }
- if (ts->protocol_type == PROTOCOL_TYPE_A) {
- input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, 0);
- input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,
- 100);
- input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR,
- 100);
- input_report_abs(ts->input_dev, ABS_MT_PRESSURE,
- 100);
- input_report_abs(ts->input_dev, ABS_MT_POSITION_X,
- x_position);
- input_report_abs(ts->input_dev, ABS_MT_POSITION_Y,
- y_position);
- input_mt_sync(ts->input_dev);
- } else if (ts->protocol_type == PROTOCOL_TYPE_B) {
- input_mt_slot(ts->input_dev, 0);
- input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER,
- 1);
- input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,
- 100);
- input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR,
- 100);
- input_report_abs(ts->input_dev, ABS_MT_PRESSURE,
- 100);
- input_report_abs(ts->input_dev, ABS_MT_POSITION_X,
- x_position);
- input_report_abs(ts->input_dev, ABS_MT_POSITION_Y,
- y_position);
- }
+ if (ts->pdata->virtual_key) {
+ if (ts->button[1].index) {
+ x_position = (ts->button[1].x_range_min
+ + ts->button[1].x_range_max) / 2;
+ y_position = (ts->button[1].y_range_min
+ + ts->button[1].y_range_max) / 2;
}
- else
- input_report_key(ts->input_dev, KEY_HOME, 1);
- }
- else if ( tp_key_index == 0x04) {
+ if (ts->protocol_type == PROTOCOL_TYPE_A) {
+ input_report_abs(ts->input_dev,
+ ABS_MT_TRACKING_ID, 0);
+ input_report_abs(ts->input_dev,
+ ABS_MT_TOUCH_MAJOR, 100);
+ input_report_abs(ts->input_dev,
+ ABS_MT_WIDTH_MAJOR, 100);
+ input_report_abs(ts->input_dev,
+ ABS_MT_PRESSURE, 100);
+ input_report_abs(ts->input_dev,
+ ABS_MT_POSITION_X, x_position);
+ input_report_abs(ts->input_dev,
+ ABS_MT_POSITION_Y, y_position);
+ input_mt_sync(ts->input_dev);
+ } else if (ts->protocol_type
+ == PROTOCOL_TYPE_B) {
+ input_mt_slot(ts->input_dev, 0);
+
+ input_mt_report_slot_state
+ (ts->input_dev, MT_TOOL_FINGER, 1);
+
+ input_report_abs(ts->input_dev,
+ ABS_MT_TOUCH_MAJOR, 100);
+ input_report_abs(ts->input_dev,
+ ABS_MT_WIDTH_MAJOR, 100);
+ input_report_abs(ts->input_dev,
+ ABS_MT_PRESSURE, 100);
+ input_report_abs(ts->input_dev,
+ ABS_MT_POSITION_X, x_position);
+ input_report_abs(ts->input_dev,
+ ABS_MT_POSITION_Y, y_position);
+ }
+ } else
+ input_report_key(ts->input_dev, KEY_HOME, 1);
+ } else if (tp_key_index == 0x04) {
vk_press = 1;
I("APP_switch key pressed\n");
- if (ts->pdata->virtual_key)
- {
- if (ts->button[2].index) {
- x_position = (ts->button[2].x_range_min + ts->button[2].x_range_max) / 2;
- y_position = (ts->button[2].y_range_min + ts->button[2].y_range_max) / 2;
- }
- if (ts->protocol_type == PROTOCOL_TYPE_A) {
- input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, 0);
- input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,
- 100);
- input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR,
- 100);
- input_report_abs(ts->input_dev, ABS_MT_PRESSURE,
- 100);
- input_report_abs(ts->input_dev, ABS_MT_POSITION_X,
- x_position);
- input_report_abs(ts->input_dev, ABS_MT_POSITION_Y,
- y_position);
- input_mt_sync(ts->input_dev);
- } else if (ts->protocol_type == PROTOCOL_TYPE_B) {
- input_mt_slot(ts->input_dev, 0);
- input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER,
- 1);
- input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,
- 100);
- input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR,
- 100);
- input_report_abs(ts->input_dev, ABS_MT_PRESSURE,
- 100);
- input_report_abs(ts->input_dev, ABS_MT_POSITION_X,
- x_position);
- input_report_abs(ts->input_dev, ABS_MT_POSITION_Y,
- y_position);
- }
+ if (ts->pdata->virtual_key) {
+ if (ts->button[2].index) {
+ x_position = (ts->button[2].x_range_min
+ + ts->button[2].x_range_max) / 2;
+ y_position = (ts->button[2].y_range_min
+ + ts->button[2].y_range_max) / 2;
}
- else
- input_report_key(ts->input_dev, KEY_F10, 1);
+ if (ts->protocol_type == PROTOCOL_TYPE_A) {
+ input_report_abs(ts->input_dev,
+ ABS_MT_TRACKING_ID, 0);
+ input_report_abs(ts->input_dev,
+ ABS_MT_TOUCH_MAJOR, 100);
+ input_report_abs(ts->input_dev,
+ ABS_MT_WIDTH_MAJOR, 100);
+ input_report_abs(ts->input_dev,
+ ABS_MT_PRESSURE, 100);
+ input_report_abs(ts->input_dev,
+ ABS_MT_POSITION_X, x_position);
+ input_report_abs(ts->input_dev,
+ ABS_MT_POSITION_Y, y_position);
+ input_mt_sync(ts->input_dev);
+ } else if (ts->protocol_type ==
+ PROTOCOL_TYPE_B) {
+ input_mt_slot(ts->input_dev, 0);
+
+ input_mt_report_slot_state
+ (ts->input_dev, MT_TOOL_FINGER, 1);
+
+ input_report_abs(ts->input_dev,
+ ABS_MT_TOUCH_MAJOR, 100);
+ input_report_abs(ts->input_dev,
+ ABS_MT_WIDTH_MAJOR, 100);
+ input_report_abs(ts->input_dev,
+ ABS_MT_PRESSURE, 100);
+ input_report_abs(ts->input_dev,
+ ABS_MT_POSITION_X, x_position);
+ input_report_abs(ts->input_dev,
+ ABS_MT_POSITION_Y, y_position);
+ }
+ } else
+ input_report_key(ts->input_dev, KEY_F10, 1);
}
input_sync(ts->input_dev);
- }
-else/*tp_key_index =0x00*/
- {
+ } else {/*tp_key_index =0x00*/
I("virtual key released\n");
vk_press = 0;
if (ts->protocol_type == PROTOCOL_TYPE_A) {
input_mt_sync(ts->input_dev);
- }
- else if (ts->protocol_type == PROTOCOL_TYPE_B) {
+ } else if (ts->protocol_type == PROTOCOL_TYPE_B) {
input_mt_slot(ts->input_dev, 0);
- input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 0);
+ input_mt_report_slot_state(ts->input_dev,
+ MT_TOOL_FINGER, 0);
}
input_report_key(ts->input_dev, KEY_BACK, 0);
input_report_key(ts->input_dev, KEY_HOME, 0);
input_report_key(ts->input_dev, KEY_F10, 0);
- input_sync(ts->input_dev);
+ input_sync(ts->input_dev);
}
}
@@ -915,8 +934,8 @@
uint8_t finger_on = 0;
int32_t loop_i;
uint16_t check_sum_cal = 0;
- int raw_cnt_max ;
- int raw_cnt_rmd ;
+ int raw_cnt_max;
+ int raw_cnt_rmd;
int hx_touch_info_size;
uint8_t coordInfoSize = ts->coord_data_size + ts->area_data_size + 4;
@@ -924,121 +943,111 @@
int16_t *mutual_data;
int16_t *self_data;
uint8_t diag_cmd;
- int i;
- int mul_num;
- int self_num;
+ int i;
+ int mul_num;
+ int self_num;
int RawDataLen = 0;
- //coordinate dump start
- char coordinate_char[15+(ic_data->HX_MAX_PT+5)*2*5+2];
- //coordinate dump end
+ /*coordinate dump start*/
+ char coordinate_char[15 + (ic_data->HX_MAX_PT + 5) * 2 * 5 + 2];
+ struct timeval t;
+ struct tm broken;
+ /*coordinate dump end*/
#endif
memset(buf, 0x00, sizeof(buf));
memset(hw_reset_check, 0x00, sizeof(hw_reset_check));
- raw_cnt_max = ic_data->HX_MAX_PT/4;
- raw_cnt_rmd = ic_data->HX_MAX_PT%4;
-
+ raw_cnt_max = ic_data->HX_MAX_PT / 4;
+ raw_cnt_rmd = ic_data->HX_MAX_PT % 4;
#if defined(HX_USB_DETECT2)
himax_cable_detect_func();
#endif
- if (raw_cnt_rmd != 0x00) //more than 4 fingers
- {
- RawDataLen = cal_data_len(raw_cnt_rmd, ic_data->HX_MAX_PT, raw_cnt_max);
- hx_touch_info_size = (ic_data->HX_MAX_PT+raw_cnt_max+2)*4;
- }
- else //less than 4 fingers
- {
- RawDataLen = cal_data_len(raw_cnt_rmd, ic_data->HX_MAX_PT, raw_cnt_max);
- hx_touch_info_size = (ic_data->HX_MAX_PT+raw_cnt_max+1)*4;
+ if (raw_cnt_rmd != 0x00) { /*more than 4 fingers*/
+ RawDataLen = cal_data_len(raw_cnt_rmd,
+ ic_data->HX_MAX_PT, raw_cnt_max);
+ hx_touch_info_size = (ic_data->HX_MAX_PT + raw_cnt_max + 2) * 4;
+ } else { /*less than 4 fingers*/
+ RawDataLen = cal_data_len(raw_cnt_rmd,
+ ic_data->HX_MAX_PT, raw_cnt_max);
+ hx_touch_info_size = (ic_data->HX_MAX_PT + raw_cnt_max + 1) * 4;
}
#ifdef HX_TP_PROC_DIAG
diag_cmd = getDiagCommand();
- if( diag_cmd ){
+ if (diag_cmd) {
ret = read_event_stack(ts->client, buf, 128);
- }
- else{
- if(touch_monitor_stop_flag != 0){
+ } else {
+ if (touch_monitor_stop_flag != 0) {
ret = read_event_stack(ts->client, buf, 128);
- touch_monitor_stop_flag-- ;
- }
- else{
- ret = read_event_stack(ts->client, buf, hx_touch_info_size);
+ touch_monitor_stop_flag--;
+ } else {
+ ret = read_event_stack(ts->client,
+ buf, hx_touch_info_size);
}
}
if (!ret)
#else
- if(!read_event_stack(ts->client, buf, hx_touch_info_size))
-#endif
- {
- E("%s: can't read data from chip!\n", __func__);
- goto err_workqueue_out;
- }
+ if (!read_event_stack(ts->client, buf, hx_touch_info_size))
+#endif
+ {
+ E("%s: can't read data from chip!\n", __func__);
+ goto err_workqueue_out;
+ }
post_read_event_stack(ts->client);
#ifdef HX_ESD_WORKAROUND
- for(i = 0; i < hx_touch_info_size; i++)
- {
- if(buf[i] == 0xED)/*case 1 ESD recovery flow*/
- {
+ for (i = 0; i < hx_touch_info_size; i++) {
+ if (buf[i] == 0xED) { /*case 1 ESD recovery flow*/
check_sum_cal = 1;
- }else if(buf[i] == 0x00)
- {
+ } else if (buf[i] == 0x00) {
ESD_00_Flag = 1;
- }
- else
- {
+ } else {
check_sum_cal = 0;
ESD_00_counter = 0;
- ESD_00_Flag = 0;
+ ESD_00_Flag = 0;
i = hx_touch_info_size;
break;
- }
+ }
}
- if (ESD_00_Flag == 1){
- ESD_00_counter ++;
- }
- if (ESD_00_counter > 1){
+ if (ESD_00_Flag == 1)
+ ESD_00_counter++;
+ if (ESD_00_counter > 1)
check_sum_cal = 2;
- }
-
- if (check_sum_cal == 2 && HX_ESD_RESET_ACTIVATE == 0)
- {
- I("[HIMAX TP MSG]: ESD event checked - ALL Zero.\n");
- ESD_HW_REST();
- return;
- }
-
- if (check_sum_cal == 1 && HX_ESD_RESET_ACTIVATE == 0)
- {
- I("[HIMAX TP MSG]: ESD event checked - ALL 0xED.\n");
+ if (check_sum_cal == 2 && HX_ESD_RESET_ACTIVATE == 0) {
+ I("[HIMAX TP MSG]: ESD event checked - ALL Zero.\n");
ESD_HW_REST();
return;
}
- else if (HX_ESD_RESET_ACTIVATE)
- {
+ if (check_sum_cal == 1 && HX_ESD_RESET_ACTIVATE == 0) {
+ I("[HIMAX TP MSG]: ESD event checked - ALL 0xED.\n");
+ ESD_HW_REST();
+ return;
+ } else if (HX_ESD_RESET_ACTIVATE) {
#ifdef HX_SMART_WAKEUP
- queue_delayed_work(ts->himax_smwp_wq, &ts->smwp_work, msecs_to_jiffies(50));
+ queue_delayed_work(ts->himax_smwp_wq,
+ &ts->smwp_work, msecs_to_jiffies(50));
#endif
#ifdef HX_HIGH_SENSE
- queue_delayed_work(ts->himax_hsen_wq, &ts->hsen_work, msecs_to_jiffies(50));
+ queue_delayed_work(ts->himax_hsen_wq,
+ &ts->hsen_work, msecs_to_jiffies(50));
#endif
- HX_ESD_RESET_ACTIVATE = 0;/*drop 1st interrupts after chip reset*/
- I("[HIMAX TP MSG]:%s: Back from reset, ready to serve.\n", __func__);
+/*drop 1st interrupts after chip reset*/
+ HX_ESD_RESET_ACTIVATE = 0;
+ I("[HIMAX TP MSG]:%s: Back from reset,ready to serve.\n",
+ __func__);
}
#endif
- for (loop_i = 0, check_sum_cal = 0; loop_i < hx_touch_info_size; loop_i++)
+ for (loop_i = 0, check_sum_cal = 0;
+ loop_i < hx_touch_info_size; loop_i++)
check_sum_cal += buf[loop_i];
-
- if ((check_sum_cal % 0x100 != 0) )
- {
- I("[HIMAX TP MSG] checksum fail : check_sum_cal: 0x%02X\n", check_sum_cal);
+
+ if ((check_sum_cal % 0x100 != 0)) {
+ I("[HIMAX TP MSG] checksum fail : check_sum_cal: 0x%02X\n",
+ check_sum_cal);
return;
}
-
if (ts->debug_log_level & BIT(0)) {
I("%s: raw data:\n", __func__);
for (loop_i = 0; loop_i < hx_touch_info_size; loop_i++) {
@@ -1048,260 +1057,289 @@
}
}
- //touch monitor raw data fetch
+ /*touch monitor raw data fetch*/
#ifdef HX_TP_PROC_DIAG
diag_cmd = getDiagCommand();
- if (diag_cmd >= 1 && diag_cmd <= 6)
- {
- //Check 124th byte CRC
- if(!diag_check_sum(hx_touch_info_size, buf))
- {
+ if (diag_cmd >= 1 && diag_cmd <= 6) {
+ /*Check 124th byte CRC*/
+ if (!diag_check_sum(hx_touch_info_size, buf))
goto bypass_checksum_failed_packet;
- }
-#ifdef HX_TP_PROC_2T2R
- if(Is_2T2R && diag_cmd == 4)
- {
- mutual_data = getMutualBuffer_2();
- self_data = getSelfBuffer();
- // initiallize the block number of mutual and self
+#ifdef HX_TP_PROC_2T2R
+ if (Is_2T2R && diag_cmd == 4) {
+ mutual_data = getMutualBuffer_2();
+ self_data = getSelfBuffer();
+
+ /* initiallize the block number of mutual and self*/
mul_num = getXChannel_2() * getYChannel_2();
#ifdef HX_EN_SEL_BUTTON
- self_num = getXChannel_2() + getYChannel_2() + ic_data->HX_BT_NUM;
+ self_num = getXChannel_2() +
+ getYChannel_2() + ic_data->HX_BT_NUM;
#else
self_num = getXChannel_2() + getYChannel_2();
#endif
- }
- else
-#endif
+ } else
+#endif
{
mutual_data = getMutualBuffer();
- self_data = getSelfBuffer();
+ self_data = getSelfBuffer();
- // initiallize the block number of mutual and self
+ /* initiallize the block number of mutual and self*/
mul_num = getXChannel() * getYChannel();
#ifdef HX_EN_SEL_BUTTON
- self_num = getXChannel() + getYChannel() + ic_data->HX_BT_NUM;
+ self_num = getXChannel() +
+ getYChannel() + ic_data->HX_BT_NUM;
#else
self_num = getXChannel() + getYChannel();
#endif
}
- diag_parse_raw_data(hx_touch_info_size, RawDataLen, mul_num, self_num, buf, diag_cmd, mutual_data, self_data);
+ diag_parse_raw_data(hx_touch_info_size,
+ RawDataLen, mul_num, self_num, buf,
+ diag_cmd, mutual_data, self_data);
- }
- else if (diag_cmd == 7)
- {
+ } else if (diag_cmd == 7) {
memcpy(&(diag_coor[0]), &buf[0], 128);
}
- //coordinate dump start
- if (coordinate_dump_enable == 1)
- {
- for(i=0; i<(15 + (ic_data->HX_MAX_PT+5)*2*5); i++)
- {
+ /*coordinate dump start*/
+ if (coordinate_dump_enable == 1) {
+ for (i = 0; i < (15 + (ic_data->
+ HX_MAX_PT + 5) * 2 * 5);
+ i++) {
coordinate_char[i] = 0x20;
}
- coordinate_char[15 + (ic_data->HX_MAX_PT+5)*2*5] = 0xD;
- coordinate_char[15 + (ic_data->HX_MAX_PT+5)*2*5 + 1] = 0xA;
+ coordinate_char[15 +
+ (ic_data->HX_MAX_PT + 5) * 2 * 5] = 0xD;
+ coordinate_char[15 +
+ (ic_data->HX_MAX_PT + 5) * 2 * 5 + 1] = 0xA;
}
- //coordinate dump end
+ /*coordinate dump end*/
bypass_checksum_failed_packet:
#endif
- EN_NoiseFilter = (buf[HX_TOUCH_INFO_POINT_CNT+2]>>3);
- //I("EN_NoiseFilter=%d\n",EN_NoiseFilter);
- EN_NoiseFilter = EN_NoiseFilter & 0x01;
- //I("EN_NoiseFilter2=%d\n",EN_NoiseFilter);
+ EN_NoiseFilter = (buf[HX_TOUCH_INFO_POINT_CNT + 2] >> 3);
+ /*I("EN_NoiseFilter=%d\n",EN_NoiseFilter);*/
+ EN_NoiseFilter = EN_NoiseFilter & 0x01;
+ /*I("EN_NoiseFilter2=%d\n",EN_NoiseFilter);*/
#if defined(HX_EN_SEL_BUTTON) || defined(HX_EN_MUT_BUTTON)
- tpd_key = (buf[HX_TOUCH_INFO_POINT_CNT+2]>>4);
- if (tpd_key == 0x0F)/*All (VK+AA)leave*/
- {
- tpd_key = 0x00;
- }
- //I("[DEBUG] tpd_key: %x\r\n", tpd_key);
-#else
+ tpd_key = (buf[HX_TOUCH_INFO_POINT_CNT + 2] >> 4);
+ if (tpd_key == 0x0F) {/*All (VK+AA)leave*/
tpd_key = 0x00;
+ }
+ /*I("[DEBUG] tpd_key: %x\r\n", tpd_key);*/
+#else
+ tpd_key = 0x00;
#endif
- p_point_num = hx_point_num;
+ p_point_num = hx_point_num;
- if (buf[HX_TOUCH_INFO_POINT_CNT] == 0xff)
- hx_point_num = 0;
- else
- hx_point_num= buf[HX_TOUCH_INFO_POINT_CNT] & 0x0f;
+ if (buf[HX_TOUCH_INFO_POINT_CNT] == 0xff)
+ hx_point_num = 0;
+ else
+ hx_point_num = buf[HX_TOUCH_INFO_POINT_CNT] & 0x0f;
- // Touch Point information
- if (hx_point_num != 0 ) {
- if(vk_press == 0x00)
- {
- uint16_t old_finger = ts->pre_finger_mask;
- ts->pre_finger_mask = 0;
- finger_num = buf[coordInfoSize - 4] & 0x0F;
- finger_on = 1;
- AA_press = 1;
- for (loop_i = 0; loop_i < ts->nFinger_support; loop_i++) {
- int base = loop_i * 4;
- int x = buf[base] << 8 | buf[base + 1];
- int y = (buf[base + 2] << 8 | buf[base + 3]);
- int w = buf[(ts->nFinger_support * 4) + loop_i];
- if(x >= 0 && x <= ts->pdata->abs_x_max && y >= 0 && y <= ts->pdata->abs_y_max){
- finger_num--;
+ /* Touch Point information*/
+ if ((hx_point_num != 0) && (vk_press == 0x00)) {
+ uint16_t old_finger = ts->pre_finger_mask;
- if ((ts->debug_log_level & BIT(3)) > 0)
- {
- if (old_finger >> loop_i == 0)
- {
- if (ts->useScreenRes)
- {
- I("status: Screen:F:%02d Down, X:%d, Y:%d, W:%d, N:%d\n",
- loop_i+1, x * ts->widthFactor >> SHIFTBITS,
- y * ts->heightFactor >> SHIFTBITS, w, EN_NoiseFilter);
- }
- else
- {
- I("status: Raw:F:%02d Down, X:%d, Y:%d, W:%d, N:%d\n",
- loop_i+1, x, y, w, EN_NoiseFilter);
- }
- }
- }
+ ts->pre_finger_mask = 0;
+ finger_num = buf[coordInfoSize - 4] & 0x0F;
+ finger_on = 1;
+ AA_press = 1;
+ for (i = 0; i < ts->nFinger_support; i++) {
+ int base = i * 4;
+ int x = buf[base] << 8 | buf[base + 1];
+ int y = (buf[base + 2] << 8 | buf[base + 3]);
+ int w = buf[(ts->nFinger_support * 4) + i];
- if (ts->protocol_type == PROTOCOL_TYPE_B)
- {
- input_mt_slot(ts->input_dev, loop_i);
- }
-
- input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, w);
- input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, w);
- input_report_abs(ts->input_dev, ABS_MT_PRESSURE, w);
- input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x);
- input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y);
-
- if (ts->protocol_type == PROTOCOL_TYPE_A)
- {
- input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, loop_i);
- input_mt_sync(ts->input_dev);
- }
- else
- {
- ts->last_slot = loop_i;
- input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 1);
- }
-
- if (!ts->first_pressed)
- {
- ts->first_pressed = 1;
- I("S1@%d, %d\n", x, y);
- }
-
- ts->pre_finger_data[loop_i][0] = x;
- ts->pre_finger_data[loop_i][1] = y;
-
-
- if (ts->debug_log_level & BIT(1))
- I("Finger %d=> X:%d, Y:%d W:%d, Z:%d, F:%d, N:%d\n",
- loop_i + 1, x, y, w, w, loop_i + 1, EN_NoiseFilter);
-
- ts->pre_finger_mask = ts->pre_finger_mask + (1 << loop_i);
-
- } else {
- if (ts->protocol_type == PROTOCOL_TYPE_B)
- {
- input_mt_slot(ts->input_dev, loop_i);
- input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 0);
- }
-
- if (loop_i == 0 && ts->first_pressed == 1)
- {
- ts->first_pressed = 2;
- I("E1@%d, %d\n",
- ts->pre_finger_data[0][0] , ts->pre_finger_data[0][1]);
- }
- if ((ts->debug_log_level & BIT(3)) > 0)
- {
- if (old_finger >> loop_i == 1)
- {
- if (ts->useScreenRes)
- {
- I("status: Screen:F:%02d Up, X:%d, Y:%d, N:%d\n",
- loop_i+1, ts->pre_finger_data[loop_i][0] * ts->widthFactor >> SHIFTBITS,
- ts->pre_finger_data[loop_i][1] * ts->heightFactor >> SHIFTBITS, Last_EN_NoiseFilter);
- }
- else
- {
- I("status: Raw:F:%02d Up, X:%d, Y:%d, N:%d\n",
- loop_i+1, ts->pre_finger_data[loop_i][0],
- ts->pre_finger_data[loop_i][1], Last_EN_NoiseFilter);
- }
- }
- }
- }
- }
-
- }else if ((tpd_key_old != 0x00)&&(tpd_key == 0x00)) {
- //temp_x[0] = 0xFFFF;
- //temp_y[0] = 0xFFFF;
- //temp_x[1] = 0xFFFF;
- //temp_y[1] = 0xFFFF;
- himax_ts_button_func(tpd_key,ts);
- finger_on = 0;
+ if (x >= 0 && x <= ts->pdata->abs_x_max
+ && y >= 0 && y <= ts->pdata->abs_y_max) {
+ finger_num--;
+ if ((((ts->debug_log_level & BIT(3)) > 0)
+ && (old_finger >> i == 0))
+ && (ts->useScreenRes)) {
+ I("status:Screen:F:%02d", i + 1);
+ I("Down,X:%d,Y:%d,W:%d,N:%d\n",
+ x * ts->widthFactor >> SHIFTBITS,
+ y * ts->heightFactor >> SHIFTBITS,
+ w, EN_NoiseFilter);
+ } else if ((((ts->debug_log_level & BIT(3)) > 0)
+ && (old_finger >> i == 0))
+ && !(ts->useScreenRes)) {
+ I("status:Raw:F:%02d", i + 1);
+ I("Down,X:%d,Y:%d,W:%d,N:%d\n",
+ x, y, w, EN_NoiseFilter);
}
- input_report_key(ts->input_dev, BTN_TOUCH, finger_on);
- input_sync(ts->input_dev);
- } else if (hx_point_num == 0){
- if(AA_press)
- {
- // leave event
- finger_on = 0;
- AA_press = 0;
- if (ts->protocol_type == PROTOCOL_TYPE_A)
+
+ if (ts->protocol_type == PROTOCOL_TYPE_B)
+ input_mt_slot(ts->input_dev, i);
+
+ input_report_abs(ts->input_dev,
+ ABS_MT_TOUCH_MAJOR, w);
+ input_report_abs(ts->input_dev,
+ ABS_MT_WIDTH_MAJOR, w);
+ input_report_abs(ts->input_dev,
+ ABS_MT_PRESSURE, w);
+ input_report_abs(ts->input_dev,
+ ABS_MT_POSITION_X, x);
+ input_report_abs(ts->input_dev,
+ ABS_MT_POSITION_Y, y);
+
+ if (ts->protocol_type == PROTOCOL_TYPE_A) {
+ input_report_abs(ts->input_dev,
+ ABS_MT_TRACKING_ID, i);
input_mt_sync(ts->input_dev);
-
- for (loop_i = 0; loop_i < ts->nFinger_support; loop_i++) {
- if (((ts->pre_finger_mask >> loop_i) & 1) == 1) {
- if (ts->protocol_type == PROTOCOL_TYPE_B) {
- input_mt_slot(ts->input_dev, loop_i);
- input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 0);
- }
- }
- }
- if (ts->pre_finger_mask > 0) {
- for (loop_i = 0; loop_i < ts->nFinger_support && (ts->debug_log_level & BIT(3)) > 0; loop_i++) {
- if (((ts->pre_finger_mask >> loop_i) & 1) == 1) {
- if (ts->useScreenRes) {
- I("status:%X, Screen:F:%02d Up, X:%d, Y:%d, N:%d\n", 0, loop_i+1, ts->pre_finger_data[loop_i][0] * ts->widthFactor >> SHIFTBITS,
- ts->pre_finger_data[loop_i][1] * ts->heightFactor >> SHIFTBITS, Last_EN_NoiseFilter);
- } else {
- I("status:%X, Raw:F:%02d Up, X:%d, Y:%d, N:%d\n",0, loop_i+1, ts->pre_finger_data[loop_i][0],ts->pre_finger_data[loop_i][1], Last_EN_NoiseFilter);
- }
- }
- }
- ts->pre_finger_mask = 0;
+ } else {
+ ts->last_slot = i;
+ input_mt_report_slot_state
+ (ts->input_dev,
+ MT_TOOL_FINGER, 1);
}
- if (ts->first_pressed == 1) {
+ if (!ts->first_pressed) {
+ ts->first_pressed = 1;
+ I("S1@%d, %d\n", x, y);
+ }
+
+ ts->pre_finger_data[i][0] = x;
+ ts->pre_finger_data[i][1] = y;
+
+ if (ts->debug_log_level & BIT(1)) {
+ I("Finger %d=> X:%d,Y:%d,W:%d,",
+ i + 1, x, y, w);
+ I("Z:%d,F:%d,N:%d\n",
+ w, i + 1, EN_NoiseFilter);
+ }
+ ts->pre_finger_mask =
+ ts->pre_finger_mask + (1 << i);
+
+ } else {
+ if (ts->protocol_type == PROTOCOL_TYPE_B) {
+ input_mt_slot(ts->input_dev, i);
+ input_mt_report_slot_state
+ (ts->input_dev, MT_TOOL_FINGER, 0);
+ }
+ if (i == 0 && ts->first_pressed == 1) {
ts->first_pressed = 2;
- I("E1@%d, %d\n",ts->pre_finger_data[0][0] , ts->pre_finger_data[0][1]);
+ I("E1@%d, %d\n",
+ ts->pre_finger_data[0][0],
+ ts->pre_finger_data[0][1]);
}
-
- if (ts->debug_log_level & BIT(1))
- I("All Finger leave\n");
-
+ if ((((ts->debug_log_level & BIT(3)) > 0)
+ && (old_finger >> i == 1))
+ && (ts->useScreenRes)) {
+ I("status:Screen:F:%02d,Up,X:%d,Y:%d\n",
+ i + 1, ts->pre_finger_data[i][0]
+ * ts->widthFactor >> SHIFTBITS,
+ ts->pre_finger_data[i][1]
+ * ts->heightFactor >> SHIFTBITS);
+ } else if ((((ts->debug_log_level & BIT(3)) > 0)
+ && (old_finger >> i == 1))
+ && !(ts->useScreenRes)) {
+ I("status:Raw:F:%02d,Up,X:%d,Y:%d\n",
+ i + 1, ts->pre_finger_data[i][0],
+ ts->pre_finger_data[i][1]);
+ }
}
- else if (tpd_key != 0x00) {
- himax_ts_button_func(tpd_key,ts);
- finger_on = 1;
- }
- else if ((tpd_key_old != 0x00)&&(tpd_key == 0x00)) {
- himax_ts_button_func(tpd_key,ts);
- finger_on = 0;
- }
- input_report_key(ts->input_dev, BTN_TOUCH, finger_on);
- input_sync(ts->input_dev);
}
- tpd_key_old = tpd_key;
- Last_EN_NoiseFilter = EN_NoiseFilter;
+ input_report_key(ts->input_dev, BTN_TOUCH, finger_on);
+ input_sync(ts->input_dev);
+ } else if ((hx_point_num != 0)
+ && ((tpd_key_old != 0x00) && (tpd_key == 0x00))) {
+ /*temp_x[0] = 0xFFFF;*/
+ /*temp_y[0] = 0xFFFF;*/
+ /*temp_x[1] = 0xFFFF;*/
+ /*temp_y[1] = 0xFFFF;*/
+ himax_ts_button_func(tpd_key, ts);
+ finger_on = 0;
+ input_report_key(ts->input_dev, BTN_TOUCH, finger_on);
+ input_sync(ts->input_dev);
+ } else if (hx_point_num == 0) {
+ if (AA_press) {
+ /*leave event*/
+ finger_on = 0;
+ AA_press = 0;
+ if (ts->protocol_type == PROTOCOL_TYPE_A)
+ input_mt_sync(ts->input_dev);
+
+ for (i = 0 ; i < ts->nFinger_support ; i++) {
+ if ((((ts->pre_finger_mask >> i) & 1) == 1)
+ && (ts->protocol_type == PROTOCOL_TYPE_B)) {
+ input_mt_slot(ts->input_dev, i);
+ input_mt_report_slot_state
+ (ts->input_dev, MT_TOOL_FINGER, 0);
+ }
+ }
+ if (ts->pre_finger_mask > 0) {
+ for (i = 0; i < ts->nFinger_support
+ && (ts->debug_log_level & BIT(3)) > 0; i++) {
+ if ((((ts->pre_finger_mask
+ >> i) & 1) == 1)
+ && (ts->useScreenRes)) {
+ I("status:%X,", 0);
+ I("Screen:F:%02d,", i + 1);
+ I("Up,X:%d,Y:%d\n",
+ ts->pre_finger_data[i][0]
+ * ts->widthFactor >> SHIFTBITS,
+ ts->pre_finger_data[i][1]
+ * ts->heightFactor >> SHIFTBITS
+ );
+ } else if ((((ts->pre_finger_mask
+ >> i) & 1) == 1)
+ && !(ts->useScreenRes)) {
+ I("status:%X,", 0);
+ I("Screen:F:%02d,", i + 1);
+ I("Up,X:%d,Y:%d\n",
+ ts->pre_finger_data[i][0],
+ ts->pre_finger_data[i][1]);
+ }
+ }
+ ts->pre_finger_mask = 0;
+ }
+
+ if (ts->first_pressed == 1) {
+ ts->first_pressed = 2;
+ I("E1@%d, %d\n", ts->pre_finger_data[0][0],
+ ts->pre_finger_data[0][1]);
+ }
+
+ if (ts->debug_log_level & BIT(1))
+ I("All Finger leave\n");
+
+#ifdef HX_TP_PROC_DIAG
+ /*coordinate dump start*/
+ if (coordinate_dump_enable == 1) {
+ do_gettimeofday(&t);
+ time_to_tm(t.tv_sec, 0, &broken);
+ snprintf(&coordinate_char[0], 15,
+ "%2d:%2d:%2d:%lu,", broken.tm_hour,
+ broken.tm_min, broken.tm_sec,
+ t.tv_usec / 1000);
+
+ snprintf(&coordinate_char[15], 10,
+ "Touch up!");
+
+ coordinate_fn->f_op->write
+ (coordinate_fn, &coordinate_char[0],
+ 15 + (ic_data->HX_MAX_PT + 5)
+ * 2 * sizeof(char) * 5 + 2,
+ &coordinate_fn->f_pos);
+ }
+ /*coordinate dump end*/
+#endif
+ } else if (tpd_key != 0x00) {
+ himax_ts_button_func(tpd_key, ts);
+ finger_on = 1;
+ } else if ((tpd_key_old != 0x00) && (tpd_key == 0x00)) {
+ himax_ts_button_func(tpd_key, ts);
+ finger_on = 0;
+ }
+ input_report_key(ts->input_dev, BTN_TOUCH, finger_on);
+ input_sync(ts->input_dev);
+ }
+ tpd_key_old = tpd_key;
workqueue_out:
return;
@@ -1310,7 +1348,7 @@
I("%s: Now reset the Touch chip.\n", __func__);
#ifdef HX_RST_PIN_FUNC
- himax_HW_reset(true,false);
+ himax_HW_reset(true, false);
#endif
goto workqueue_out;
@@ -1329,6 +1367,7 @@
static void himax_cable_tp_status_handler_func(int connect_status)
{
struct himax_ts_data *ts;
+
I("Touch: cable change to %d\n", connect_status);
ts = private_ts;
if (ts->cable_config) {
@@ -1342,18 +1381,23 @@
ts->usb_connected = 0x00;
}
- i2c_himax_master_write(ts->client, ts->cable_config,
- sizeof(ts->cable_config), HIMAX_I2C_RETRY_TIMES);
+ i2c_himax_master_write(ts->client,
+ ts->cable_config,
+ sizeof(ts->cable_config),
+ HIMAX_I2C_RETRY_TIMES);
- I("%s: Cable status change: 0x%2.2X\n", __func__, ts->cable_config[1]);
+ I("%s: Cable status change: 0x%2.2X\n",
+ __func__, ts->cable_config[1]);
} else
- I("%s: Cable status is the same as previous one, ignore.\n", __func__);
+ I("%s: Cable status is same, ignore.\n",
+ __func__);
} else {
if (connect_status)
ts->usb_connected = 0x01;
else
ts->usb_connected = 0x00;
- I("%s: Cable status remembered: 0x%2.2X\n", __func__, ts->usb_connected);
+ I("%s: Cable status remembered: 0x%2.2X\n",
+ __func__, ts->usb_connected);
}
}
}
@@ -1373,16 +1417,20 @@
struct himax_ts_data *ts;
u32 connect_status = 0;
- connect_status = USB_Flag;//upmu_is_chr_det();
+ connect_status = USB_Flag;/*upmu_is_chr_det();*/
ts = private_ts;
- //I("Touch: cable status=%d, cable_config=%p, usb_connected=%d \n", connect_status,ts->cable_config, ts->usb_connected);
+ /*I("Touch: cable status=%d, cable_config=%p,
+ usb_connected=%d\n", connect_status,
+ ts->cable_config, ts->usb_connected);*/
+
if (ts->cable_config) {
if ((!!connect_status) != ts->usb_connected) {
- //notify USB plug/unplug
- // 0x9008_8060 ==> 0x0000_0000/0001
- tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x60;
- tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00;
-
+ /*notify USB plug/unplug*/
+ /*0x9008_8060 ==> 0x0000_0000/0001*/
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x08;
+ tmp_addr[1] = 0x80; tmp_addr[0] = 0x60;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00;
if (!!connect_status) {
tmp_data[0] = 0x01;
ts->usb_connected = 0x01;
@@ -1393,10 +1441,13 @@
himax_flash_write_burst(ts->client, tmp_addr, tmp_data);
- I("%s: Cable status change: 0x%2.2X\n", __func__, ts->usb_connected);
- }
- //else
- //I("%s: Cable status is the same as previous one, ignore.\n", __func__);
+ I("%s: Cable status change: 0x%2.2X\n",
+ __func__, ts->usb_connected);
+ }
+ /*else*/
+ /*I("%s: Cable status is the same as previous one,
+ ignore.\n", __func__);*/
+
}
}
#endif
@@ -1417,52 +1468,52 @@
#endif
#ifdef HX_SMART_WAKEUP
-void himax_set_SMWP_func(struct i2c_client *client,uint8_t SMWP_enable)
+void himax_set_SMWP_func(struct i2c_client *client, uint8_t SMWP_enable)
{
uint8_t tmp_data[4];
- if(SMWP_enable)
- {
- SMWP_bit_retry:
+ if (SMWP_enable) {
+SMWP_bit_retry:
himax_set_SMWP_enable(client, SMWP_enable);
msleep(20);
- himax_get_SMWP_enable(client,tmp_data);
- I("%s: Read SMWP bit data[0]=%x data[1]=%x data[2]=%x data[3]=%x\n", __func__
- ,tmp_data[0],tmp_data[1],tmp_data[2],tmp_data[3]);
- if(tmp_data[0]!= 0x01)
- {
- I("%s: retry SMWP bit write data[0]=%x \n",__func__,tmp_data[0]);
- goto SMWP_bit_retry;
- }
+ himax_get_SMWP_enable(client, tmp_data);
+I("%s: Read SMWP bit data[0]=%x data[1]=%x data[2]=%x data[3]=%x\n",
+__func__, tmp_data[0], tmp_data[1], tmp_data[2], tmp_data[3]);
+
+ if (tmp_data[0] != 0x01) {
+ I("%s: retry SMWP bit write data[0]=%x\n",
+ __func__, tmp_data[0]);
+ goto SMWP_bit_retry;
+ }
}
}
static void himax_SMWP_work(struct work_struct *work)
{
- struct himax_ts_data *ts = container_of(work, struct himax_ts_data,
- smwp_work.work);
+ struct himax_ts_data *ts =
+ container_of(work, struct himax_ts_data, smwp_work.work);
I(" %s in", __func__);
- himax_set_SMWP_func(ts->client,ts->SMWP_enable);
+ himax_set_SMWP_func(ts->client, ts->SMWP_enable);
}
#endif
-#ifdef HX_TP_PROC_FLASH_DUMP
+#ifdef HX_TP_PROC_FLASH_DUMP
static void himax_ts_flash_work_func(struct work_struct *work)
{
himax_ts_flash_func();
}
#endif
-#ifdef HX_TP_PROC_DIAG
+#ifdef HX_TP_PROC_DIAG
static void himax_ts_diag_work_func(struct work_struct *work)
{
himax_ts_diag_func();
}
#endif
-void himax_ts_init(struct himax_ts_data *ts)
+bool himax_ts_init(struct himax_ts_data *ts)
{
int ret = 0, err = 0;
struct himax_i2c_platform_data *pdata;
@@ -1476,15 +1527,14 @@
/* Set pinctrl in active state */
if (ts->ts_pinctrl) {
ret = pinctrl_select_state(ts->ts_pinctrl,
- ts->pinctrl_state_active);
- if (ret < 0) {
- E("Failed to set pin in active state %d",ret);
- }
+ ts->pinctrl_state_active);
+ if (ret < 0)
+ E("Failed to set pin in active state %d", ret);
}
himax_burst_enable(client, 0);
- //Get Himax IC Type / FW information / Calculate the point number
+ /*Get Himax IC Type / FW information / Calculate the point number */
if (himax_check_chip_version(ts->client) == false) {
E("Himax chip doesn NOT EXIST");
goto err_ic_package_failed;
@@ -1496,10 +1546,9 @@
if (pdata->virtual_key)
ts->button = pdata->virtual_key;
-#ifdef HX_TP_PROC_FLASH_DUMP
+#ifdef HX_TP_PROC_FLASH_DUMP
ts->flash_wq = create_singlethread_workqueue("himax_flash_wq");
- if (!ts->flash_wq)
- {
+ if (!ts->flash_wq) {
E("%s: create flash workqueue failed\n", __func__);
err = -ENOMEM;
goto err_create_wq_failed;
@@ -1511,10 +1560,9 @@
setFlashBuffer();
#endif
-#ifdef HX_TP_PROC_DIAG
+#ifdef HX_TP_PROC_DIAG
ts->himax_diag_wq = create_singlethread_workqueue("himax_diag");
- if (!ts->himax_diag_wq)
- {
+ if (!ts->himax_diag_wq) {
E("%s: create diag workqueue failed\n", __func__);
err = -ENOMEM;
goto err_create_wq_failed;
@@ -1526,40 +1574,42 @@
#ifdef HX_AUTO_UPDATE_FW
I(" %s in", __func__);
- if(i_update_FW() == false)
- I("NOT Have new FW=NOT UPDATE=\n");
+ if (i_update_FW() <= 0)
+ I("FW NOT UPDATE=\n");
else
I("Have new FW=UPDATE=\n");
#endif
- //Himax Power On and Load Config
+ /*Himax Power On and Load Config*/
if (himax_loadSensorConfig(client, pdata) < 0) {
- E("%s: Load Sesnsor configuration failed, unload driver.\n", __func__);
+ E("%s: Load Sesnsor config failed,unload driver.\n",
+ __func__);
goto err_detect_failed;
}
calculate_point_number();
#ifdef HX_TP_PROC_DIAG
- setXChannel(ic_data->HX_RX_NUM); // X channel
- setYChannel(ic_data->HX_TX_NUM); // Y channel
+ setXChannel(ic_data->HX_RX_NUM); /*X channel*/
+ setYChannel(ic_data->HX_TX_NUM); /*Y channel*/
setMutualBuffer();
setMutualNewBuffer();
setMutualOldBuffer();
if (getMutualBuffer() == NULL) {
E("%s: mutual buffer allocate fail failed\n", __func__);
- return;
+ return false;
}
#ifdef HX_TP_PROC_2T2R
- if(Is_2T2R){
- setXChannel_2(ic_data->HX_RX_NUM_2); // X channel
- setYChannel_2(ic_data->HX_TX_NUM_2); // Y channel
+ if (Is_2T2R) {
+ setXChannel_2(ic_data->HX_RX_NUM_2); /*X channel*/
+ setYChannel_2(ic_data->HX_TX_NUM_2); /*Y channel*/
setMutualBuffer_2();
if (getMutualBuffer_2() == NULL) {
- E("%s: mutual buffer 2 allocate fail failed\n", __func__);
- return;
+ E("%s: mutual buffer 2 allocate fail failed\n",
+ __func__);
+ return false;
}
}
#endif
@@ -1572,7 +1622,7 @@
ts->x_channel = ic_data->HX_RX_NUM;
ts->y_channel = ic_data->HX_TX_NUM;
ts->nFinger_support = ic_data->HX_MAX_PT;
- //calculate the i2c data size
+ /*calculate the i2c data size*/
calcDataSize(ts->nFinger_support);
I("%s: calcDataSize complete\n", __func__);
#ifdef CONFIG_OF
@@ -1584,14 +1634,13 @@
pdata->cable_config[1] = 0x00;
#endif
ts->suspended = false;
-#if defined(HX_USB_DETECT)||defined(HX_USB_DETECT2)
+#if defined(HX_USB_DETECT) || defined(HX_USB_DETECT2)
ts->usb_connected = 0x00;
ts->cable_config = pdata->cable_config;
#endif
ts->protocol_type = pdata->protocol_type;
I("%s: Use Protocol Type %c\n", __func__,
ts->protocol_type == PROTOCOL_TYPE_A ? 'A' : 'B');
-
ret = himax_input_register(ts);
if (ret) {
E("%s: Unable to register %s input device\n",
@@ -1599,8 +1648,9 @@
goto err_input_register_device_failed;
}
#ifdef HX_SMART_WAKEUP
- ts->SMWP_enable=0;
- wake_lock_init(&ts->ts_SMWP_wake_lock, WAKE_LOCK_SUSPEND, HIMAX_common_NAME);
+ ts->SMWP_enable = 0;
+ wakeup_source_init(&ts->ts_SMWP_wake_lock,
+ WAKE_LOCK_SUSPEND, HIMAX_common_NAME);
ts->himax_smwp_wq = create_singlethread_workqueue("HMX_SMWP_WORK");
if (!ts->himax_smwp_wq) {
@@ -1611,7 +1661,7 @@
INIT_DELAYED_WORK(&ts->smwp_work, himax_SMWP_work);
#endif
#ifdef HX_HIGH_SENSE
- ts->HSEN_enable=0;
+ ts->HSEN_enable = 0;
ts->himax_hsen_wq = create_singlethread_workqueue("HMX_HSEN_WORK");
if (!ts->himax_hsen_wq) {
E(" allocate himax_hsen_wq failed\n");
@@ -1633,7 +1683,7 @@
err = himax_ts_register_interrupt(ts->client);
if (err)
goto err_register_interrupt_failed;
- return;
+ return true;
err_register_interrupt_failed:
#ifdef HX_HIGH_SENSE
@@ -1641,26 +1691,26 @@
#endif
#ifdef HX_SMART_WAKEUP
err_smwp_wq_failed:
- wake_lock_destroy(&ts->ts_SMWP_wake_lock);
+ wakeup_source_trash(&ts->ts_SMWP_wake_lock);
#endif
err_input_register_device_failed:
input_free_device(ts->input_dev);
err_detect_failed:
-#ifdef HX_TP_PROC_FLASH_DUMP
+#ifdef HX_TP_PROC_FLASH_DUMP
err_create_wq_failed:
#endif
err_ic_package_failed:
-
-return;
+return false;
}
-int himax_chip_common_probe(struct i2c_client *client, const struct i2c_device_id *id)
+int himax_chip_common_probe(struct i2c_client *client,
+const struct i2c_device_id *id)
{
int err = 0;
struct himax_ts_data *ts;
struct himax_i2c_platform_data *pdata;
- //Check I2C functionality
+ /*Check I2C functionality*/
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
E("%s: i2c check functionality error\n", __func__);
err = -ENODEV;
@@ -1677,6 +1727,7 @@
i2c_set_clientdata(client, ts);
ts->client = client;
ts->dev = &client->dev;
+ mutex_init(&ts->rw_lock);
pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
if (pdata == NULL) { /*Allocate Platform data space*/
@@ -1691,7 +1742,8 @@
}
#ifdef CONFIG_OF
- if (client->dev.of_node) { /*DeviceTree Init Platform_data*/
+ /*DeviceTree Init Platform_data*/
+ if (client->dev.of_node) {
err = himax_parse_dt(ts, pdata);
if (err < 0) {
I(" pdata is NULL for DT\n");
@@ -1704,12 +1756,11 @@
ts->rst_gpio = pdata->gpio_reset;
#endif
-himax_gpio_power_config(ts->client, pdata);
+ himax_gpio_power_config(ts->client, pdata);
err = himax_ts_pinctrl_init(ts);
- if (err || ts->ts_pinctrl == NULL) {
+ if (err || ts->ts_pinctrl == NULL)
E(" Pinctrl init failed\n");
- }
#ifndef CONFIG_OF
if (pdata->power) {
@@ -1736,7 +1787,7 @@
}
#endif
- return 0;
+ return 0;
#ifdef CONFIG_FB
err_fb_notif_wq_create:
@@ -1783,8 +1834,10 @@
himax_touch_proc_deinit();
#endif
#ifdef CONFIG_FB
- if (fb_unregister_client(&ts->fb_notif))
- dev_err(&client->dev, "Error occurred while unregistering fb_notifier.\n");
+ if (fb_unregister_client(&ts->fb_notif)) {
+ dev_err(&client->dev,
+ "Error occurred while unregistering fb_notifier.\n");
+ }
#endif
if (!ts->use_irq)
@@ -1810,7 +1863,7 @@
}
}
#ifdef HX_SMART_WAKEUP
- wake_lock_destroy(&ts->ts_SMWP_wake_lock);
+ wakeup_source_trash(&ts->ts_SMWP_wake_lock);
#endif
kfree(ts);
@@ -1822,38 +1875,36 @@
{
int ret;
- if(ts->suspended)
- {
- I("%s: Already suspended. Skipped. \n", __func__);
+ if (ts->suspended) {
+ I("%s: Already suspended. Skipped.\n", __func__);
return 0;
- }
- else
- {
+
+ } else {
ts->suspended = true;
- I("%s: enter \n", __func__);
+ I("%s: enter\n", __func__);
}
#ifdef HX_TP_PROC_FLASH_DUMP
- if (getFlashDumpGoing())
- {
- I("[himax] %s: Flash dump is going, reject suspend\n",__func__);
+ if (getFlashDumpGoing()) {
+ I("[himax] %s: Flash dump is going,reject suspend\n",
+ __func__);
return 0;
}
#endif
#ifdef HX_TP_PROC_HITOUCH
- if(hitouch_is_connect)
- {
- I("[himax] %s: Hitouch connect, reject suspend\n",__func__);
+ if (hitouch_is_connect) {
+ I("[himax] %s: Hitouch connect,reject suspend\n",
+ __func__);
return 0;
}
#endif
#ifdef HX_SMART_WAKEUP
- if(ts->SMWP_enable)
- {
+ if (ts->SMWP_enable) {
atomic_set(&ts->suspend_mode, 1);
ts->pre_finger_mask = 0;
- FAKE_POWER_KEY_SEND=false;
- I("[himax] %s: SMART_WAKEUP enable, reject suspend\n",__func__);
+ FAKE_POWER_KEY_SEND = false;
+ I("[himax] %s: SMART_WAKEUP enable,reject suspend\n",
+ __func__);
return 0;
}
#endif
@@ -1864,19 +1915,18 @@
if (!ts->use_irq) {
ret = cancel_work_sync(&ts->work);
if (ret)
- himax_int_enable(ts->client->irq,1);
+ himax_int_enable(ts->client->irq, 1);
}
- //ts->first_pressed = 0;
+ /*ts->first_pressed = 0;*/
atomic_set(&ts->suspend_mode, 1);
ts->pre_finger_mask = 0;
if (ts->ts_pinctrl) {
ret = pinctrl_select_state(ts->ts_pinctrl,
ts->pinctrl_state_suspend);
- if (ret < 0) {
+ if (ret < 0)
E("Failed to get idle pinctrl state %d\n", ret);
- }
}
if (ts->pdata->powerOff3V3 && ts->pdata->power)
@@ -1889,20 +1939,16 @@
{
int retval;
- I("%s: enter \n", __func__);
+ I("%s: enter\n", __func__);
if (ts->pdata->powerOff3V3 && ts->pdata->power)
ts->pdata->power(1);
-
-
- /*************************************/
+
if (ts->protocol_type == PROTOCOL_TYPE_A)
- input_mt_sync(ts->input_dev);
+ input_mt_sync(ts->input_dev);
input_report_key(ts->input_dev, BTN_TOUCH, 0);
input_sync(ts->input_dev);
- /*************************************/
-
-
+
if (ts->ts_pinctrl) {
retval = pinctrl_select_state(ts->ts_pinctrl,
ts->pinctrl_state_active);
@@ -1914,7 +1960,7 @@
atomic_set(&ts->suspend_mode, 0);
- himax_int_enable(ts->client->irq,1);
+ himax_int_enable(ts->client->irq, 1);
ts->suspended = false;
#if defined(HX_USB_DETECT2)
@@ -1922,10 +1968,12 @@
himax_cable_detect_func();
#endif
#ifdef HX_SMART_WAKEUP
- queue_delayed_work(ts->himax_smwp_wq, &ts->smwp_work, msecs_to_jiffies(1000));
+ queue_delayed_work(ts->himax_smwp_wq,
+ &ts->smwp_work, msecs_to_jiffies(1000));
#endif
#ifdef HX_HIGH_SENSE
- queue_delayed_work(ts->himax_hsen_wq, &ts->hsen_work, msecs_to_jiffies(1000));
+ queue_delayed_work(ts->himax_hsen_wq,
+ &ts->hsen_work, msecs_to_jiffies(1000));
#endif
return 0;
err_pinctrl_select_resume:
diff --git a/drivers/input/touchscreen/hxchipset/himax_common.h b/drivers/input/touchscreen/hxchipset/himax_common.h
index 27ce9aa..c4e24ba 100644
--- a/drivers/input/touchscreen/hxchipset/himax_common.h
+++ b/drivers/input/touchscreen/hxchipset/himax_common.h
@@ -16,9 +16,13 @@
#ifndef HIMAX_COMMON_H
#define HIMAX_COMMON_H
+#include "himax_platform.h"
+
#include <asm/segment.h>
-#include <asm/uaccess.h>
-#include <asm/atomic.h>
+/*#include <asm/uaccess.h>*/
+/*#include <asm/atomic.h>*/
+#include <linux/uaccess.h>
+#include <linux/atomic.h>
#include <linux/delay.h>
#include <linux/i2c.h>
@@ -36,7 +40,6 @@
#include <linux/buffer_head.h>
#include <linux/seq_file.h>
#include <linux/proc_fs.h>
-#include "himax_platform.h"
#if defined(CONFIG_FB)
#include <linux/notifier.h>
@@ -48,7 +51,7 @@
#ifdef CONFIG_OF
#include <linux/of_gpio.h>
#endif
-#define HIMAX_DRIVER_VER "0.2.4.0"
+#define HIMAX_DRIVER_VER "0.3.1.0"
#define FLASH_DUMP_FILE "/data/user/Flash_Dump.bin"
#define DIAG_COORDINATE_FILE "/sdcard/Coordinate_Dump.csv"
@@ -62,39 +65,39 @@
#define HX_TP_PROC_SELF_TEST
#define HX_TP_PROC_RESET
#define HX_TP_PROC_SENSE_ON_OFF
-//#define HX_TP_PROC_2T2R
+/*#define HX_TP_PROC_2T2R*/
int himax_touch_proc_init(void);
void himax_touch_proc_deinit(void);
#endif
-//===========Himax Option function=============
-//#define HX_RST_PIN_FUNC
-//#define HX_AUTO_UPDATE_FW
-//#define HX_HIGH_SENSE
-//#define HX_SMART_WAKEUP
-//#define HX_USB_DETECT
-//#define HX_ESD_WORKAROUND
-//#define HX_USB_DETECT2
+/*===========Himax Option function=============*/
+/*#define HX_RST_PIN_FUNC*/
+#define HX_AUTO_UPDATE_FW
+/*#define HX_HIGH_SENSE*/
+/*#define HX_SMART_WAKEUP*/
+/*#define HX_USB_DETECT*/
+/*#define HX_ESD_WORKAROUND*/
+/*#define HX_USB_DETECT2*/
+/*#define HX_EN_SEL_BUTTON*//* Support Self Virtual key ,default is close*/
+#define HX_EN_MUT_BUTTON/* Support Mutual Virtual Key ,default is close*/
+/*#define HX_EN_CHECK_PATCH*/
-//#define HX_EN_SEL_BUTTON // Support Self Virtual key ,default is close
-#define HX_EN_MUT_BUTTON // Support Mutual Virtual Key ,default is close
+#define HX_KEY_MAX_COUNT 4
+#define DEFAULT_RETRY_CNT 3
-#define HX_KEY_MAX_COUNT 4
-#define DEFAULT_RETRY_CNT 3
-
-#define HX_VKEY_0 KEY_BACK
-#define HX_VKEY_1 KEY_HOME
-#define HX_VKEY_2 KEY_RESERVED
-#define HX_VKEY_3 KEY_RESERVED
-#define HX_KEY_ARRAY {HX_VKEY_0, HX_VKEY_1, HX_VKEY_2, HX_VKEY_3}
+#define HX_VKEY_0 KEY_BACK
+#define HX_VKEY_1 KEY_HOME
+#define HX_VKEY_2 KEY_RESERVED
+#define HX_VKEY_3 KEY_RESERVED
+#define HX_KEY_ARRAY {HX_VKEY_0, HX_VKEY_1, HX_VKEY_2, HX_VKEY_3}
#define SHIFTBITS 5
-//#define FLASH_SIZE 131072
-#define FW_SIZE_60k 61440
-#define FW_SIZE_64k 65536
-#define FW_SIZE_124k 126976
-#define FW_SIZE_128k 131072
+/*#define FLASH_SIZE 131072*/
+#define FW_SIZE_60k 61440
+#define FW_SIZE_64k 65536
+#define FW_SIZE_124k 126976
+#define FW_SIZE_128k 131072
struct himax_ic_data {
int vendor_fw_ver;
@@ -183,12 +186,12 @@
bool suspended;
bool probe_done;
struct mutex fb_mutex;
+ struct mutex rw_lock;
atomic_t suspend_mode;
uint8_t x_channel;
uint8_t y_channel;
uint8_t useScreenRes;
uint8_t diag_command;
-
uint8_t protocol_type;
uint8_t first_pressed;
uint8_t coord_data_size;
@@ -198,11 +201,9 @@
uint8_t nFinger_support;
uint8_t irq_enabled;
uint8_t diag_self[50];
-
uint16_t finger_pressed;
uint16_t last_slot;
uint16_t pre_finger_mask;
-
uint32_t debug_log_level;
uint32_t widthFactor;
uint32_t heightFactor;
@@ -214,20 +215,20 @@
uint32_t pl_x_max;
uint32_t pl_y_min;
uint32_t pl_y_max;
-
+
int use_irq;
int (*power)(int on);
int pre_finger_data[10][2];
-
+
struct device *dev;
struct workqueue_struct *himax_wq;
struct work_struct work;
struct input_dev *input_dev;
struct hrtimer timer;
struct i2c_client *client;
- struct himax_i2c_platform_data *pdata;
+ struct himax_i2c_platform_data *pdata;
struct himax_virtual_key *button;
-
+
#if defined(CONFIG_FB)
struct notifier_block fb_notif;
#elif defined(CONFIG_HAS_EARLYSUSPEND)
@@ -235,8 +236,8 @@
#endif
#ifdef HX_TP_PROC_FLASH_DUMP
- struct workqueue_struct *flash_wq;
- struct work_struct flash_work;
+ struct workqueue_struct *flash_wq;
+ struct work_struct flash_work;
#endif
#ifdef HX_RST_PIN_FUNC
@@ -250,7 +251,7 @@
#ifdef HX_SMART_WAKEUP
uint8_t SMWP_enable;
uint8_t gesture_cust_en[16];
- struct wake_lock ts_SMWP_wake_lock;
+ struct wakeup_source ts_SMWP_wake_lock;
struct workqueue_struct *himax_smwp_wq;
struct delayed_work smwp_work;
#endif
@@ -261,7 +262,7 @@
struct delayed_work hsen_work;
#endif
-#if defined(HX_USB_DETECT)||defined(HX_USB_DETECT2)
+#if defined(HX_USB_DETECT) || defined(HX_USB_DETECT2)
uint8_t usb_connected;
uint8_t *cable_config;
#endif
@@ -273,30 +274,30 @@
struct pinctrl_state *pinctrl_state_release;
};
-#define HX_CMD_NOP 0x00
-#define HX_CMD_SETMICROOFF 0x35
-#define HX_CMD_SETROMRDY 0x36
-#define HX_CMD_TSSLPIN 0x80
-#define HX_CMD_TSSLPOUT 0x81
-#define HX_CMD_TSSOFF 0x82
-#define HX_CMD_TSSON 0x83
-#define HX_CMD_ROE 0x85
-#define HX_CMD_RAE 0x86
-#define HX_CMD_RLE 0x87
-#define HX_CMD_CLRES 0x88
-#define HX_CMD_TSSWRESET 0x9E
-#define HX_CMD_SETDEEPSTB 0xD7
-#define HX_CMD_SET_CACHE_FUN 0xDD
-#define HX_CMD_SETIDLE 0xF2
-#define HX_CMD_SETIDLEDELAY 0xF3
-#define HX_CMD_SELFTEST_BUFFER 0x8D
+#define HX_CMD_NOP 0x00
+#define HX_CMD_SETMICROOFF 0x35
+#define HX_CMD_SETROMRDY 0x36
+#define HX_CMD_TSSLPIN 0x80
+#define HX_CMD_TSSLPOUT 0x81
+#define HX_CMD_TSSOFF 0x82
+#define HX_CMD_TSSON 0x83
+#define HX_CMD_ROE 0x85
+#define HX_CMD_RAE 0x86
+#define HX_CMD_RLE 0x87
+#define HX_CMD_CLRES 0x88
+#define HX_CMD_TSSWRESET 0x9E
+#define HX_CMD_SETDEEPSTB 0xD7
+#define HX_CMD_SET_CACHE_FUN 0xDD
+#define HX_CMD_SETIDLE 0xF2
+#define HX_CMD_SETIDLEDELAY 0xF3
+#define HX_CMD_SELFTEST_BUFFER 0x8D
#define HX_CMD_MANUALMODE 0x42
-#define HX_CMD_FLASH_ENABLE 0x43
+#define HX_CMD_FLASH_ENABLE 0x43
#define HX_CMD_FLASH_SET_ADDRESS 0x44
#define HX_CMD_FLASH_WRITE_REGISTER 0x45
#define HX_CMD_FLASH_SET_COMMAND 0x47
#define HX_CMD_FLASH_WRITE_BUFFER 0x48
-#define HX_CMD_FLASH_PAGE_ERASE 0x4D
+#define HX_CMD_FLASH_PAGE_ERASE 0x4D
#define HX_CMD_FLASH_SECTOR_ERASE 0x4E
#define HX_CMD_CB 0xCB
#define HX_CMD_EA 0xEA
@@ -311,7 +312,7 @@
};
#ifdef HX_HIGH_SENSE
-void himax_set_HSEN_func(struct i2c_client *client,uint8_t HSEN_enable);
+void himax_set_HSEN_func(struct i2c_client *client, uint8_t HSEN_enable);
#endif
#ifdef HX_SMART_WAKEUP
@@ -319,18 +320,18 @@
#define GEST_PTLG_HDR_LEN (4)
#define GEST_PTLG_HDR_ID1 (0xCC)
#define GEST_PTLG_HDR_ID2 (0x44)
-#define GEST_PT_MAX_NUM (128)
+#define GEST_PT_MAX_NUM (128)
#ifdef HX_GESTURE_TRACK
static int gest_pt_cnt;
static int gest_pt_x[GEST_PT_MAX_NUM];
static int gest_pt_y[GEST_PT_MAX_NUM];
-static int gest_start_x,gest_start_y,gest_end_x,gest_end_y;
-static int gest_width,gest_height,gest_mid_x,gest_mid_y;
+static int gest_start_x, gest_start_y, gest_end_x, gest_end_y;
+static int gest_width, gest_height, gest_mid_x, gest_mid_y;
static int gn_gesture_coor[16];
#endif
-void himax_set_SMWP_func(struct i2c_client *client,uint8_t SMWP_enable);
+void himax_set_SMWP_func(struct i2c_client *client, uint8_t SMWP_enable);
extern bool FAKE_POWER_KEY_SEND;
enum gesture_event_type {
@@ -380,16 +381,91 @@
int himax_input_register(struct himax_ts_data *ts);
#endif
-extern int himax_chip_common_probe(struct i2c_client *client, const struct i2c_device_id *id);
-extern int himax_chip_common_remove(struct i2c_client *client);
-extern int himax_chip_common_suspend(struct himax_ts_data *ts);
-extern int himax_chip_common_resume(struct himax_ts_data *ts);
-int himax_loadSensorConfig(struct i2c_client *client, struct himax_i2c_platform_data *pdata);
+int himax_chip_common_probe(struct i2c_client *client,
+const struct i2c_device_id *id);
+int himax_chip_common_remove(struct i2c_client *client);
+int himax_chip_common_suspend(struct himax_ts_data *ts);
+int himax_chip_common_resume(struct himax_ts_data *ts);
+int himax_loadSensorConfig(struct i2c_client *client,
+struct himax_i2c_platform_data *pdata);
#ifdef HX_USB_DETECT2
-//extern kal_bool upmu_is_chr_det(void);
+/*extern kal_bool upmu_is_chr_det(void);*/
void himax_cable_detect_func(void);
#endif
+#ifdef HX_AUTO_UPDATE_FW
+extern unsigned long FW_VER_MAJ_FLASH_ADDR;
+extern unsigned long FW_VER_MIN_FLASH_ADDR;
+extern unsigned long CFG_VER_MAJ_FLASH_ADDR;
+extern unsigned long CFG_VER_MIN_FLASH_ADDR;
+#endif
+extern unsigned long FW_VER_MAJ_FLASH_LENG;
+extern unsigned long FW_VER_MIN_FLASH_LENG;
+extern unsigned long CFG_VER_MAJ_FLASH_LENG;
+extern unsigned long CFG_VER_MIN_FLASH_LENG;
+extern unsigned char IC_TYPE;
+extern unsigned char IC_CHECKSUM;
+
+#if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG)
+extern int himax_touch_proc_init(void);
+extern void himax_touch_proc_deinit(void);
+/*PROC-START*/
+#ifdef HX_TP_PROC_FLASH_DUMP
+extern void himax_ts_flash_func(void);
+extern void setFlashBuffer(void);
+extern bool getFlashDumpGoing(void);
+extern uint8_t getSysOperation(void);
+extern void setSysOperation(uint8_t operation);
+#endif
+
+#ifdef HX_TP_PROC_HITOUCH
+extern bool hitouch_is_connect;
+#endif
+
+#ifdef HX_TP_PROC_DIAG
+ extern int touch_monitor_stop_flag;
+
+ extern int touch_monitor_stop_limit;
+
+ extern void himax_ts_diag_func(void);
+
+ extern int16_t *getMutualBuffer(void);
+ extern int16_t *getMutualNewBuffer(void);
+ extern int16_t *getMutualOldBuffer(void);
+ extern int16_t *getSelfBuffer(void);
+ extern uint8_t getXChannel(void);
+ extern uint8_t getYChannel(void);
+ extern uint8_t getDiagCommand(void);
+ extern void setXChannel(uint8_t x);
+ extern void setYChannel(uint8_t y);
+ extern void setMutualBuffer(void);
+ extern void setMutualNewBuffer(void);
+ extern void setMutualOldBuffer(void);
+ extern uint8_t coordinate_dump_enable;
+ extern struct file *coordinate_fn;
+ extern uint8_t diag_coor[128];
+#ifdef HX_TP_PROC_2T2R
+ extern int16_t *getMutualBuffer_2(void);
+ extern uint8_t getXChannel_2(void);
+ extern uint8_t getYChannel_2(void);
+ extern void setXChannel_2(uint8_t x);
+ extern void setYChannel_2(uint8_t y);
+ extern void setMutualBuffer_2(void);
+#endif
+#endif
+/*PROC-END*/
+#endif
+
+#ifdef HX_USB_DETECT2
+ extern bool USB_Flag;
+#endif
+#ifdef HX_ESD_WORKAROUND
+ extern void HX_report_ESD_event(void);
+ unsigned char ESD_00_counter = 0;
+ unsigned char ESD_00_Flag = 0;
+#endif
+bool himax_ts_init(struct himax_ts_data *ts);
+
#endif
diff --git a/drivers/input/touchscreen/hxchipset/himax_debug.c b/drivers/input/touchscreen/hxchipset/himax_debug.c
index f8bee11..a5bdbf2 100644
--- a/drivers/input/touchscreen/hxchipset/himax_debug.c
+++ b/drivers/input/touchscreen/hxchipset/himax_debug.c
@@ -16,32 +16,16 @@
#include "himax_debug.h"
#include "himax_ic.h"
-//struct himax_debug_data* debug_data;
-
-extern struct himax_ic_data* ic_data;
-extern struct himax_ts_data *private_ts;
-extern unsigned char IC_TYPE;
-extern unsigned char IC_CHECKSUM;
-extern int himax_input_register(struct himax_ts_data *ts);
-#ifdef QCT
-extern irqreturn_t himax_ts_thread(int irq, void *ptr);
-#endif
-#ifdef MTK
-#ifdef CONFIG_OF_TOUCH
-extern irqreturn_t tpd_eint_interrupt_handler(int irq, void *desc);
-#else
-extern void tpd_eint_interrupt_handler(void);
-#endif
-#endif
+/*struct himax_debug_data* debug_data;*/
#ifdef HX_TP_PROC_DIAG
#ifdef HX_TP_PROC_2T2R
-int HX_RX_NUM_2 = 0;
-int HX_TX_NUM_2 = 0;
+int HX_RX_NUM_2;
+int HX_TX_NUM_2;
#endif
-int touch_monitor_stop_flag = 0;
+int touch_monitor_stop_flag;
int touch_monitor_stop_limit = 5;
-uint8_t g_diag_arr_num = 0;
+uint8_t g_diag_arr_num;
#endif
#ifdef HX_ESD_WORKAROUND
@@ -52,11 +36,11 @@
bool FAKE_POWER_KEY_SEND;
#endif
-//=============================================================================================================
-//
-// Segment : Himax PROC Debug Function
-//
-//=============================================================================================================
+/*========================================================
+
+Segment : Himax PROC Debug Function
+
+==========================================================*/
#if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG)
static ssize_t himax_vendor_read(struct file *file, char *buf,
@@ -65,33 +49,26 @@
ssize_t ret = 0;
char *temp_buf;
- if(!HX_PROC_SEND_FLAG)
- {
+ if (!HX_PROC_SEND_FLAG) {
temp_buf = kzalloc(len, GFP_KERNEL);
- if (!temp_buf) {
- HX_PROC_SEND_FLAG=0;
- return ret;
- }
+ ret += snprintf(temp_buf, len,
+ "%s_FW:%#x_CFG:%#x_SensorId:%#x\n",
+ HIMAX_common_NAME, ic_data->vendor_fw_ver,
+ ic_data->vendor_config_ver, ic_data->vendor_sensor_id);
- ret += snprintf(temp_buf, len, "%s_FW:%#x_CFG:%#x_SensorId:%#x\n", HIMAX_common_NAME,
- ic_data->vendor_fw_ver, ic_data->vendor_config_ver, ic_data->vendor_sensor_id);
- HX_PROC_SEND_FLAG=1;
+ HX_PROC_SEND_FLAG = 1;
if (copy_to_user(buf, temp_buf, len))
- {
I("%s,here:%d\n", __func__, __LINE__);
- }
kfree(temp_buf);
- }
- else
- HX_PROC_SEND_FLAG=0;
+ } else
+ HX_PROC_SEND_FLAG = 0;
return ret;
}
-static const struct file_operations himax_proc_vendor_ops =
-{
+const struct file_operations himax_proc_vendor_ops = {
.owner = THIS_MODULE,
.read = himax_vendor_read,
};
@@ -107,29 +84,21 @@
if (!HX_PROC_SEND_FLAG) {
temp_buf = kzalloc(len, GFP_KERNEL);
- if (!temp_buf) {
- HX_PROC_SEND_FLAG=0;
- return ret;
- }
- ret += snprintf(temp_buf, len, "attn = %x\n", himax_int_gpio_read(ts_data->pdata->gpio_irq));
+ ret += snprintf(temp_buf, len, "attn = %x\n",
+ himax_int_gpio_read(ts_data->pdata->gpio_irq));
if (copy_to_user(buf, temp_buf, len))
- {
I("%s,here:%d\n", __func__, __LINE__);
- }
kfree(temp_buf);
HX_PROC_SEND_FLAG = 1;
- }
- else
- HX_PROC_SEND_FLAG=0;
+ } else
+ HX_PROC_SEND_FLAG = 0;
return ret;
}
-
-static const struct file_operations himax_proc_attn_ops =
-{
+const struct file_operations himax_proc_attn_ops = {
.owner = THIS_MODULE,
.read = himax_attn_read,
};
@@ -143,23 +112,16 @@
if (!HX_PROC_SEND_FLAG) {
temp_buf = kzalloc(len, GFP_KERNEL);
- if (!temp_buf) {
- HX_PROC_SEND_FLAG=0;
- return ret;
- }
- ret += snprintf(temp_buf, len, "%d ", ts->irq_enabled);
- ret += snprintf(temp_buf+ret, len-ret, "\n");
+ ret += snprintf(temp_buf, len-1, "%d ", ts->irq_enabled);
+ ret += snprintf(temp_buf, 1, "\n");
if (copy_to_user(buf, temp_buf, len))
- {
I("%s,here:%d\n", __func__, __LINE__);
- }
kfree(temp_buf);
HX_PROC_SEND_FLAG = 1;
- }
- else
- HX_PROC_SEND_FLAG=0;
+ } else
+ HX_PROC_SEND_FLAG = 0;
return ret;
}
@@ -167,18 +129,15 @@
size_t len, loff_t *pos)
{
struct himax_ts_data *ts = private_ts;
- char buf_tmp[12]= {0};
- int value, ret=0;
+ char buf_tmp[12] = {0};
+ int value, ret = 0;
- if (len >= 12)
- {
+ if (len >= 12) {
I("%s: no command exceeds 12 chars.\n", __func__);
return -EFAULT;
}
if (copy_from_user(buf_tmp, buff, len))
- {
return -EFAULT;
- }
if (buf_tmp[0] == '0')
value = false;
@@ -188,36 +147,43 @@
return -EINVAL;
if (value) {
- if(ic_data->HX_INT_IS_EDGE)
- {
+ if (ic_data->HX_INT_IS_EDGE) {
#ifdef MTK
#ifdef CONFIG_OF_TOUCH
- himax_int_enable(ts->client->irq,1);
+ himax_int_enable(ts->client->irq, 1);
#else
- //mt_eint_set_sens(CUST_EINT_TOUCH_PANEL_NUM, CUST_EINT_TOUCH_PANEL_TYPE);
- //mt_eint_set_hw_debounce(CUST_EINT_TOUCH_PANEL_NUM, CUST_EINT_TOUCH_PANEL_DEBOUNCE_CN);
- mt_eint_registration(ts->client->irq, EINTF_TRIGGER_FALLING, tpd_eint_interrupt_handler, 1);
+ /*mt_eint_set_sens(CUST_EINT_TOUCH_PANEL_NUM,
+ CUST_EINT_TOUCH_PANEL_TYPE);
+ mt_eint_set_hw_debounce(CUST_EINT_TOUCH_PANEL_NUM,
+ CUST_EINT_TOUCH_PANEL_DEBOUNCE_CN);*/
+ mt_eint_registration(ts->client->irq,
+ EINTF_TRIGGER_FALLING, tpd_eint_interrupt_handler, 1);
#endif
#endif
#ifdef QCT
- ret = request_threaded_irq(ts->client->irq, NULL, himax_ts_thread,
- IRQF_TRIGGER_FALLING | IRQF_ONESHOT, ts->client->name, ts);
+ ret = request_threaded_irq(ts->client->irq,
+ NULL, himax_ts_thread,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ ts->client->name, ts);
#endif
- }
- else
- {
+ } else {
#ifdef MTK
#ifdef CONFIG_OF_TOUCH
- himax_int_enable(ts->client->irq,1);
+ himax_int_enable(ts->client->irq, 1);
#else
- //mt_eint_set_sens(CUST_EINT_TOUCH_PANEL_NUM, CUST_EINT_TOUCH_PANEL_TYPE);
- //mt_eint_set_hw_debounce(CUST_EINT_TOUCH_PANEL_NUM, CUST_EINT_TOUCH_PANEL_DEBOUNCE_CN);
- mt_eint_registration(ts->client->irq, EINTF_TRIGGER_LOW, tpd_eint_interrupt_handler, 1);
+ /*mt_eint_set_sens(CUST_EINT_TOUCH_PANEL_NUM,
+ CUST_EINT_TOUCH_PANEL_TYPE);
+ mt_eint_set_hw_debounce(CUST_EINT_TOUCH_PANEL_NUM,
+ CUST_EINT_TOUCH_PANEL_DEBOUNCE_CN);*/
+ mt_eint_registration(ts->client->irq,
+ EINTF_TRIGGER_LOW, tpd_eint_interrupt_handler, 1);
#endif
#endif
#ifdef QCT
- ret = request_threaded_irq(ts->client->irq, NULL, himax_ts_thread,
- IRQF_TRIGGER_LOW | IRQF_ONESHOT, ts->client->name, ts);
+ ret = request_threaded_irq(ts->client->irq,
+ NULL, himax_ts_thread,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+ ts->client->name, ts);
#endif
}
if (ret == 0) {
@@ -225,7 +191,7 @@
irq_enable_count = 1;
}
} else {
- himax_int_enable(ts->client->irq,0);
+ himax_int_enable(ts->client->irq, 0);
free_irq(ts->client->irq, ts);
ts->irq_enabled = 0;
}
@@ -233,8 +199,7 @@
return len;
}
-static const struct file_operations himax_proc_int_en_ops =
-{
+const struct file_operations himax_proc_int_en_ops = {
.owner = THIS_MODULE,
.read = himax_int_en_read,
.write = himax_int_en_write,
@@ -249,26 +214,19 @@
if (!HX_PROC_SEND_FLAG) {
temp_buf = kzalloc(len, GFP_KERNEL);
- if (!temp_buf) {
- HX_PROC_SEND_FLAG=0;
- return ret;
- }
- ret += snprintf(temp_buf, len, "%d ", ts->pdata->abs_x_min);
- ret += snprintf(temp_buf+ret, len-ret, "%d ", ts->pdata->abs_x_max);
- ret += snprintf(temp_buf+ret, len-ret, "%d ", ts->pdata->abs_y_min);
- ret += snprintf(temp_buf+ret, len-ret, "%d ", ts->pdata->abs_y_max);
- ret += snprintf(temp_buf+ret, len-ret, "\n");
+ ret += snprintf(temp_buf, len, "%d ", ts->pdata->abs_x_min);
+ ret += snprintf(temp_buf, len, "%d ", ts->pdata->abs_x_max);
+ ret += snprintf(temp_buf, len, "%d ", ts->pdata->abs_y_min);
+ ret += snprintf(temp_buf, len, "%d ", ts->pdata->abs_y_max);
+ ret += snprintf(temp_buf, len, "\n");
if (copy_to_user(buf, temp_buf, len))
- {
I("%s,here:%d\n", __func__, __LINE__);
- }
kfree(temp_buf);
HX_PROC_SEND_FLAG = 1;
- }
- else
- HX_PROC_SEND_FLAG=0;
+ } else
+ HX_PROC_SEND_FLAG = 0;
return ret;
}
@@ -283,17 +241,14 @@
int layout[4] = {0};
char buf[80] = {0};
- if (len >= 80)
- {
+ if (len >= 80) {
I("%s: no command exceeds 80 chars.\n", __func__);
return -EFAULT;
}
if (copy_from_user(buf, buff, len))
- {
return -EFAULT;
- }
- for (i = 0; i < 20; i++) {
+ for (i = 0 ; i < 20 ; i++) {
if (buf[i] == ',' || buf[i] == '\n') {
memset(buf_tmp, 0x0, sizeof(buf_tmp));
if (i - j <= 5)
@@ -310,20 +265,24 @@
}
}
if (k == 4) {
- ts->pdata->abs_x_min=layout[0];
- ts->pdata->abs_x_max=layout[1];
- ts->pdata->abs_y_min=layout[2];
- ts->pdata->abs_y_max=layout[3];
- I("%d, %d, %d, %d\n",ts->pdata->abs_x_min, ts->pdata->abs_x_max, ts->pdata->abs_y_min, ts->pdata->abs_y_max);
+ ts->pdata->abs_x_min = layout[0];
+ ts->pdata->abs_x_max = layout[1];
+ ts->pdata->abs_y_min = layout[2];
+ ts->pdata->abs_y_max = layout[3];
+ I("%d, %d, %d, %d\n", ts->pdata->abs_x_min,
+ ts->pdata->abs_x_max, ts->pdata->abs_y_min,
+ ts->pdata->abs_y_max);
input_unregister_device(ts->input_dev);
himax_input_register(ts);
- } else
- I("ERR@%d, %d, %d, %d\n",ts->pdata->abs_x_min, ts->pdata->abs_x_max, ts->pdata->abs_y_min, ts->pdata->abs_y_max);
+ } else {
+ I("ERR@%d, %d, %d, %d\n", ts->pdata->abs_x_min,
+ ts->pdata->abs_x_max, ts->pdata->abs_y_min,
+ ts->pdata->abs_y_max);
+ }
return len;
}
-static const struct file_operations himax_proc_layout_ops =
-{
+const struct file_operations himax_proc_layout_ops = {
.owner = THIS_MODULE,
.read = himax_layout_read,
.write = himax_layout_write,
@@ -335,26 +294,21 @@
struct himax_ts_data *ts_data;
size_t ret = 0;
char *temp_buf;
+
ts_data = private_ts;
if (!HX_PROC_SEND_FLAG) {
temp_buf = kzalloc(len, GFP_KERNEL);
- if (!temp_buf) {
- HX_PROC_SEND_FLAG=0;
- return ret;
- }
- ret += snprintf(temp_buf, len, "%d\n", ts_data->debug_log_level);
+ ret += snprintf(temp_buf, len, "%d\n",
+ ts_data->debug_log_level);
if (copy_to_user(buf, temp_buf, len))
- {
I("%s,here:%d\n", __func__, __LINE__);
- }
kfree(temp_buf);
HX_PROC_SEND_FLAG = 1;
- }
- else
- HX_PROC_SEND_FLAG=0;
+ } else
+ HX_PROC_SEND_FLAG = 0;
return ret;
}
@@ -365,29 +319,26 @@
struct himax_ts_data *ts;
char buf_tmp[11];
int i;
+
ts = private_ts;
- if (len >= 12)
- {
+ if (len >= 12) {
I("%s: no command exceeds 12 chars.\n", __func__);
return -EFAULT;
}
if (copy_from_user(buf_tmp, buff, len))
- {
return -EFAULT;
- }
ts->debug_log_level = 0;
- for(i=0; i<len-1; i++)
- {
- if( buf_tmp[i]>='0' && buf_tmp[i]<='9' )
- ts->debug_log_level |= (buf_tmp[i]-'0');
- else if( buf_tmp[i]>='A' && buf_tmp[i]<='F' )
- ts->debug_log_level |= (buf_tmp[i]-'A'+10);
- else if( buf_tmp[i]>='a' && buf_tmp[i]<='f' )
- ts->debug_log_level |= (buf_tmp[i]-'a'+10);
+ for (i = 0 ; i < len - 1 ; i++) {
+ if (buf_tmp[i] >= '0' && buf_tmp[i] <= '9')
+ ts->debug_log_level |= (buf_tmp[i] - '0');
+ else if (buf_tmp[i] >= 'A' && buf_tmp[i] <= 'F')
+ ts->debug_log_level |= (buf_tmp[i]-'A' + 10);
+ else if (buf_tmp[i] >= 'a' && buf_tmp[i] <= 'f')
+ ts->debug_log_level |= (buf_tmp[i] - 'a' + 10);
- if(i!=len-2)
+ if (i != len - 2)
ts->debug_log_level <<= 4;
}
@@ -395,8 +346,12 @@
if (ts->pdata->screenWidth > 0 && ts->pdata->screenHeight > 0 &&
(ts->pdata->abs_x_max - ts->pdata->abs_x_min) > 0 &&
(ts->pdata->abs_y_max - ts->pdata->abs_y_min) > 0) {
- ts->widthFactor = (ts->pdata->screenWidth << SHIFTBITS)/(ts->pdata->abs_x_max - ts->pdata->abs_x_min);
- ts->heightFactor = (ts->pdata->screenHeight << SHIFTBITS)/(ts->pdata->abs_y_max - ts->pdata->abs_y_min);
+ ts->widthFactor =
+ (ts->pdata->screenWidth << SHIFTBITS)
+ / (ts->pdata->abs_x_max - ts->pdata->abs_x_min);
+ ts->heightFactor =
+ (ts->pdata->screenHeight << SHIFTBITS)
+ / (ts->pdata->abs_y_max - ts->pdata->abs_y_min);
if (ts->widthFactor > 0 && ts->heightFactor > 0)
ts->useScreenRes = 1;
else {
@@ -415,8 +370,7 @@
return len;
}
-static const struct file_operations himax_proc_debug_level_ops =
-{
+const struct file_operations himax_proc_debug_level_ops = {
.owner = THIS_MODULE,
.read = himax_debug_level_read,
.write = himax_debug_level_write,
@@ -433,35 +387,33 @@
memset(data, 0x00, sizeof(data));
- I("himax_register_show: %x,%x,%x,%x\n", register_command[0],register_command[1],register_command[2],register_command[3]);
- if(!HX_PROC_SEND_FLAG)
- {
+ I("himax_register_show: %x,%x,%x,%x\n", register_command[0],
+ register_command[1], register_command[2], register_command[3]);
+
+ if (!HX_PROC_SEND_FLAG) {
temp_buf = kzalloc(len, GFP_KERNEL);
- if (!temp_buf) {
- HX_PROC_SEND_FLAG=0;
- return ret;
- }
- himax_register_read(private_ts->client, register_command, 1, data);
+ himax_register_read(private_ts->client,
+ register_command, 1, data);
- ret += snprintf(temp_buf, len, "command: %x,%x,%x,%x\n", register_command[0],register_command[1],register_command[2],register_command[3]);
+ ret += snprintf(temp_buf, len, "command: %x,%x,%x,%x\n",
+ register_command[0], register_command[1],
+ register_command[2], register_command[3]);
- for (loop_i = 0; loop_i < 128; loop_i++) {
- ret += snprintf(temp_buf+ret, len-ret, "0x%2.2X ", data[loop_i]);
+ for (loop_i = 0 ; loop_i < 128 ; loop_i++) {
+ ret += snprintf(temp_buf + ret,
+ sizeof(data[loop_i]), "0x%2.2X ", data[loop_i]);
if ((loop_i % 16) == 15)
- ret += snprintf(temp_buf+ret, len-ret, "\n");
+ ret += snprintf(temp_buf + ret, 1, "\n");
}
- ret += snprintf(temp_buf+ret, len-ret, "\n");
- HX_PROC_SEND_FLAG=1;
+ ret += snprintf(temp_buf + ret, len, "\n");
+ HX_PROC_SEND_FLAG = 1;
if (copy_to_user(buf, temp_buf, len))
- {
I("%s,here:%d\n", __func__, __LINE__);
- }
kfree(temp_buf);
- }
- else
- HX_PROC_SEND_FLAG=0;
+ } else
+ HX_PROC_SEND_FLAG = 0;
return ret;
}
@@ -475,40 +427,48 @@
uint8_t write_da[128];
char buf[80] = {0};
- if (len >= 80)
- {
+ if (len >= 80) {
I("%s: no command exceeds 80 chars.\n", __func__);
return -EFAULT;
}
if (copy_from_user(buf, buff, len))
- {
return -EFAULT;
- }
memset(buf_tmp, 0x0, sizeof(buf_tmp));
memset(write_da, 0x0, sizeof(write_da));
- I("himax %s \n",buf);
+ I("himax %s\n", buf);
if ((buf[0] == 'r' || buf[0] == 'w') && buf[1] == ':') {
if (buf[2] == 'x') {
memcpy(buf_tmp, buf + 3, 8);
- if (!kstrtoul(buf_tmp, 16, &result))
- {
- register_command[0] = (uint8_t)result;
- register_command[1] = (uint8_t)(result >> 8);
- register_command[2] = (uint8_t)(result >> 16);
- register_command[3] = (uint8_t)(result >> 24);
- }
+ if (!kstrtoul(buf_tmp, 16, &result)) {
+ register_command[0] =
+ (uint8_t)result;
+ register_command[1] =
+ (uint8_t)(result >> 8);
+ register_command[2] =
+ (uint8_t)(result >> 16);
+ register_command[3] =
+ (uint8_t)(result >> 24);
+ }
base = 11;
- I("CMD: %x,%x,%x,%x\n", register_command[0],register_command[1],register_command[2],register_command[3]);
+ I("CMD: %x,%x,%x,%x\n", register_command[0],
+ register_command[1], register_command[2],
+ register_command[3]);
- for (loop_i = 0; loop_i < 128 && (base+10)<80; loop_i++) {
+ for (loop_i = 0 ; loop_i < 128 ; loop_i++) {
if (buf[base] == '\n') {
if (buf[0] == 'w') {
- himax_register_write(private_ts->client, register_command, 1, write_da);
- I("CMD: %x, %x, %x, %x, len=%d\n", write_da[0], write_da[1],write_da[2],write_da[3],length);
+ himax_register_write
+ (private_ts->client,
+ register_command
+ , 1, write_da);
+ I("CMD:%x, %x, %x, %x,len=%d\n",
+ write_da[0], write_da[1],
+ write_da[2], write_da[3],
+ length);
}
I("\n");
return len;
@@ -518,12 +478,16 @@
buf_tmp[11] = '\0';
memcpy(buf_tmp, buf + base + 2, 8);
if (!kstrtoul(buf_tmp, 16, &result)) {
- write_da[loop_i] = (uint8_t)result;
- write_da[loop_i+1] = (uint8_t)(result >> 8);
- write_da[loop_i+2] = (uint8_t)(result >> 16);
- write_da[loop_i+3] = (uint8_t)(result >> 24);
+ write_da[loop_i] =
+ (uint8_t)result;
+ write_da[loop_i+1] =
+ (uint8_t)(result >> 8);
+ write_da[loop_i+2] =
+ (uint8_t)(result >> 16);
+ write_da[loop_i+3] =
+ (uint8_t)(result >> 24);
}
- length+=4;
+ length += 4;
}
base += 10;
}
@@ -532,8 +496,7 @@
return len;
}
-static const struct file_operations himax_proc_register_ops =
-{
+const struct file_operations himax_proc_register_ops = {
.owner = THIS_MODULE,
.read = himax_proc_register_read,
.write = himax_proc_register_write,
@@ -579,15 +542,18 @@
}
void setMutualBuffer(void)
{
- diag_mutual = kzalloc(x_channel * y_channel * sizeof(int16_t), GFP_KERNEL);
+ diag_mutual = kzalloc
+ (x_channel * y_channel * sizeof(int16_t), GFP_KERNEL);
}
void setMutualNewBuffer(void)
{
- diag_mutual_new = kzalloc(x_channel * y_channel * sizeof(int16_t), GFP_KERNEL);
+ diag_mutual_new = kzalloc
+ (x_channel * y_channel * sizeof(int16_t), GFP_KERNEL);
}
void setMutualOldBuffer(void)
{
- diag_mutual_old = kzalloc(x_channel * y_channel * sizeof(int16_t), GFP_KERNEL);
+ diag_mutual_old = kzalloc
+ (x_channel * y_channel * sizeof(int16_t), GFP_KERNEL);
}
#ifdef HX_TP_PROC_2T2R
@@ -613,94 +579,82 @@
}
void setMutualBuffer_2(void)
{
- diag_mutual_2 = kzalloc(x_channel_2 * y_channel_2 * sizeof(int16_t), GFP_KERNEL);
+ diag_mutual_2 = kzalloc
+ (x_channel_2 * y_channel_2 * sizeof(int16_t), GFP_KERNEL);
}
#endif
static ssize_t himax_diag_arrange_write(struct file *file, const char *buff,
size_t len, loff_t *pos)
{
- //struct himax_ts_data *ts = private_ts;
+ /*struct himax_ts_data *ts = private_ts;*/
char buf[80] = {0};
- if (len >= 80)
- {
+ if (len >= 80) {
I("%s: no command exceeds 80 chars.\n", __func__);
return -EFAULT;
}
if (copy_from_user(buf, buff, len))
- {
return -EFAULT;
- }
g_diag_arr_num = buf[0] - '0';
- I("%s: g_diag_arr_num = %d \n", __func__,g_diag_arr_num);
+ I("%s: g_diag_arr_num = %d\n", __func__, g_diag_arr_num);
return len;
}
-static const struct file_operations himax_proc_diag_arrange_ops =
-{
+const struct file_operations himax_proc_diag_arrange_ops = {
.owner = THIS_MODULE,
.write = himax_diag_arrange_write,
};
-static void himax_diag_arrange_print(struct seq_file *s, int i, int j, int transpose)
+static void himax_diag_arrange_print
+(struct seq_file *s, int i, int j, int transpose)
{
- if(transpose)
- seq_printf(s, "%6d", diag_mutual[ j + i*x_channel]);
+ if (transpose)
+ seq_printf(s, "%6d", diag_mutual[j + i * x_channel]);
else
- seq_printf(s, "%6d", diag_mutual[ i + j*x_channel]);
+ seq_printf(s, "%6d", diag_mutual[i + j * x_channel]);
}
-static void himax_diag_arrange_inloop(struct seq_file *s, int in_init,bool transpose, int j)
+static void himax_diag_arrange_inloop
+(struct seq_file *s, int in_init, bool transpose, int j)
{
int i;
int in_max = 0;
- if(transpose)
+ if (transpose)
in_max = y_channel;
else
in_max = x_channel;
- if (in_init > 0)
- {
- for(i = in_init-1;i >= 0;i--)
- {
+ if (in_init > 0) {
+ for (i = in_init - 1 ; i >= 0 ; i--)
himax_diag_arrange_print(s, i, j, transpose);
- }
- }
- else
- {
- for (i = 0; i < in_max; i++)
- {
+ } else {
+ for (i = 0 ; i < in_max ; i++)
himax_diag_arrange_print(s, i, j, transpose);
- }
}
}
-static void himax_diag_arrange_outloop(struct seq_file *s, int transpose, int out_init, int in_init)
+static void himax_diag_arrange_outloop
+(struct seq_file *s, int transpose, int out_init, int in_init)
{
int j;
int out_max = 0;
- if(transpose)
+ if (transpose)
out_max = x_channel;
else
out_max = y_channel;
- if(out_init > 0)
- {
- for(j = out_init-1;j >= 0;j--)
- {
+ if (out_init > 0) {
+ for (j = out_init - 1 ; j >= 0 ; j--) {
himax_diag_arrange_inloop(s, in_init, transpose, j);
seq_printf(s, " %5d\n", diag_self[j]);
}
- }
- else
- {
- for(j = 0;j < out_max;j++)
- {
+ } else {
+ for (j = 0 ; j < out_max ; j++) {
himax_diag_arrange_inloop(s, in_init, transpose, j);
seq_printf(s, " %5d\n", diag_self[j]);
}
@@ -709,33 +663,35 @@
static void himax_diag_arrange(struct seq_file *s)
{
- int bit2,bit1,bit0;
+ int bit2, bit1, bit0;
int i;
bit2 = g_diag_arr_num >> 2;
bit1 = g_diag_arr_num >> 1 & 0x1;
bit0 = g_diag_arr_num & 0x1;
- if (g_diag_arr_num < 4)
- {
- himax_diag_arrange_outloop(s, bit2, bit1 * y_channel, bit0 * x_channel);
- for (i = y_channel; i < x_channel + y_channel; i++) {
+ if (g_diag_arr_num < 4) {
+ himax_diag_arrange_outloop(s,
+ bit2, bit1 * y_channel, bit0 * x_channel);
+
+ for (i = y_channel ; i < x_channel + y_channel ; i++)
seq_printf(s, "%6d", diag_self[i]);
- }
- }
- else
- {
- himax_diag_arrange_outloop(s, bit2, bit1 * x_channel, bit0 * y_channel);
- for (i = x_channel; i < x_channel + y_channel; i++) {
+
+ } else {
+ himax_diag_arrange_outloop(s,
+ bit2, bit1 * x_channel, bit0 * y_channel);
+
+ for (i = x_channel ; i < x_channel + y_channel ; i++)
seq_printf(s, "%6d", diag_self[i]);
- }
+
}
}
static void *himax_diag_seq_start(struct seq_file *s, loff_t *pos)
{
- if (*pos>=1) return NULL;
- return (void *)((unsigned long) *pos+1);
+ if (*pos >= 1)
+ return NULL;
+ return (void *)((unsigned long) *pos + 1);
}
static void *himax_diag_seq_next(struct seq_file *s, void *v, loff_t *pos)
@@ -748,87 +704,96 @@
static int himax_diag_seq_read(struct seq_file *s, void *v)
{
size_t count = 0;
- int32_t loop_i;//,loop_j
+ int32_t loop_i;/*loop_j*/
uint16_t mutual_num, self_num, width;
#ifdef HX_TP_PROC_2T2R
- if(Is_2T2R && diag_command == 4)
- {
+ if (Is_2T2R && diag_command == 4) {
mutual_num = x_channel_2 * y_channel_2;
- self_num = x_channel_2 + y_channel_2; //don't add KEY_COUNT
+ /*don't add KEY_COUNT*/
+ self_num = x_channel_2 + y_channel_2;
width = x_channel_2;
- seq_printf(s, "ChannelStart: %4d, %4d\n\n", x_channel_2, y_channel_2);
- }
- else
+ seq_printf(s, "ChannelStart: %4d, %4d\n\n",
+ x_channel_2, y_channel_2);
+ } else
#endif
{
mutual_num = x_channel * y_channel;
- self_num = x_channel + y_channel; //don't add KEY_COUNT
+ /*don't add KEY_COUNT*/
+ self_num = x_channel + y_channel;
width = x_channel;
- seq_printf(s, "ChannelStart: %4d, %4d\n\n", x_channel, y_channel);
+ seq_printf(s, "ChannelStart: %4d, %4d\n\n",
+ x_channel, y_channel);
}
- // start to show out the raw data in adb shell
+ /* start to show out the raw data in adb shell*/
if (diag_command >= 1 && diag_command <= 6) {
if (diag_command <= 3) {
himax_diag_arrange(s);
- seq_printf(s, "\n\n");
+ seq_puts(s, "\n\n");
#ifdef HX_EN_SEL_BUTTON
- seq_printf(s, "\n");
- for (loop_i = 0; loop_i < HX_BT_NUM; loop_i++)
- seq_printf(s, "%6d", diag_self[HX_RX_NUM + HX_TX_NUM + loop_i]);
+ seq_putc(s, '\n');
+ for (loop_i = 0 ; loop_i < HX_BT_NUM ; loop_i++)
+ seq_printf(s, "%6d",
+ diag_self[HX_RX_NUM + HX_TX_NUM + loop_i]);
#endif
#ifdef HX_TP_PROC_2T2R
- }else if(Is_2T2R && diag_command == 4 ) {
- for (loop_i = 0; loop_i < mutual_num; loop_i++) {
+ } else if (Is_2T2R && diag_command == 4) {
+ for (loop_i = 0 ; loop_i < mutual_num ; loop_i++) {
seq_printf(s, "%4d", diag_mutual_2[loop_i]);
if ((loop_i % width) == (width - 1))
- seq_printf(s, " %6d\n", diag_self[width + loop_i/width]);
+ seq_printf(s, " %6d\n",
+ diag_self[width + loop_i / width]);
}
- seq_printf(s, "\n");
- for (loop_i = 0; loop_i < width; loop_i++) {
+ seq_putc(s, '\n');
+ for (loop_i = 0 ; loop_i < width ; loop_i++) {
seq_printf(s, "%6d", diag_self[loop_i]);
if (((loop_i) % width) == (width - 1))
- seq_printf(s, "\n");
+ seq_putc(s, '\n');
}
#ifdef HX_EN_SEL_BUTTON
- seq_printf(s, "\n");
- for (loop_i = 0; loop_i < HX_BT_NUM; loop_i++)
- seq_printf(s, "%4d", diag_self[HX_RX_NUM_2 + HX_TX_NUM_2 + loop_i]);
+ seq_putc(s, '\n');
+ for (loop_i = 0 ; loop_i < HX_BT_NUM ; loop_i++) {
+ seq_printf(s, "%4d",
+ diag_self[HX_RX_NUM_2 + HX_TX_NUM_2 + loop_i]);
+ }
#endif
#endif
} else if (diag_command > 4) {
- for (loop_i = 0; loop_i < self_num; loop_i++) {
+ for (loop_i = 0 ; loop_i < self_num ; loop_i++) {
seq_printf(s, "%4d", diag_self[loop_i]);
- if (((loop_i - mutual_num) % width) == (width - 1))
- seq_printf(s, "\n");
+ if (((loop_i - mutual_num) % width)
+ == (width - 1)) {
+ seq_putc(s, '\n');
+ }
}
} else {
- for (loop_i = 0; loop_i < mutual_num; loop_i++) {
+ for (loop_i = 0 ; loop_i < mutual_num ; loop_i++) {
seq_printf(s, "%4d", diag_mutual[loop_i]);
if ((loop_i % width) == (width - 1))
- seq_printf(s, "\n");
+ seq_putc(s, '\n');
}
}
- seq_printf(s, "ChannelEnd");
- seq_printf(s, "\n");
+ seq_puts(s, "ChannelEnd");
+ seq_putc(s, '\n');
} else if (diag_command == 7) {
- for (loop_i = 0; loop_i < 128 ;loop_i++) {
+ for (loop_i = 0; loop_i < 128 ; loop_i++) {
if ((loop_i % 16) == 0)
- seq_printf(s, "LineStart:");
+ seq_puts(s, "LineStart:");
seq_printf(s, "%4d", diag_coor[loop_i]);
if ((loop_i % 16) == 15)
- seq_printf(s, "\n");
+ seq_putc(s, '\n');
}
- } else if (diag_command == 9 || diag_command == 91 || diag_command == 92){
+ } else if (diag_command == 9 ||
+ diag_command == 91 || diag_command == 92) {
+
himax_diag_arrange(s);
- seq_printf(s, "\n");
+ seq_putc(s, '\n');
}
return count;
}
-static const struct seq_operations himax_diag_seq_ops =
-{
+const struct seq_operations himax_diag_seq_ops = {
.start = himax_diag_seq_start,
.next = himax_diag_seq_next,
.stop = himax_diag_seq_stop,
@@ -838,25 +803,24 @@
{
return seq_open(file, &himax_diag_seq_ops);
};
-bool DSRAM_Flag;
+bool DSRAM_Flag = false;
-//DSRAM thread
+/*DSRAM thread*/
void himax_ts_diag_func(void)
{
- int i=0, j=0;
+ int i = 0, j = 0;
unsigned int index = 0;
int total_size = ic_data->HX_TX_NUM * ic_data->HX_RX_NUM * 2;
uint8_t info_data[total_size];
- int16_t *mutual_data = NULL;
+ int16_t *mutual_data = NULL;
int16_t *mutual_data_new = NULL;
int16_t *mutual_data_old = NULL;
int16_t new_data;
himax_burst_enable(private_ts->client, 1);
- if(diag_command == 9 || diag_command == 91)
- {
+ if (diag_command == 9 || diag_command == 91) {
mutual_data = getMutualBuffer();
- }else if(diag_command == 92){
+ } else if (diag_command == 92) {
mutual_data = getMutualBuffer();
mutual_data_new = getMutualNewBuffer();
mutual_data_old = getMutualOldBuffer();
@@ -864,49 +828,63 @@
himax_get_DSRAM_data(private_ts->client, info_data);
index = 0;
- for (i = 0; i < ic_data->HX_TX_NUM; i++)
- {
- for (j = 0; j < ic_data->HX_RX_NUM; j++)
- {
- new_data = (short)(info_data[index + 1] << 8 | info_data[index]);
- if(diag_command == 9){
- mutual_data[i*ic_data->HX_RX_NUM+j] = new_data;
- }else if(diag_command == 91){ //Keep max data for 100 frame
- if(mutual_data[i * ic_data->HX_RX_NUM + j] < new_data)
- mutual_data[i * ic_data->HX_RX_NUM + j] = new_data;
- }else if(diag_command == 92){ //Cal data for [N]-[N-1] frame
- mutual_data_new[i * ic_data->HX_RX_NUM + j] = new_data;
- mutual_data[i * ic_data->HX_RX_NUM + j] = mutual_data_new[i * ic_data->HX_RX_NUM + j] - mutual_data_old[i * ic_data->HX_RX_NUM + j];
+ for (i = 0 ; i < ic_data->HX_TX_NUM ; i++) {
+ for (j = 0 ; j < ic_data->HX_RX_NUM ; j++) {
+ new_data = (short)(info_data[index + 1]
+ << 8 | info_data[index]);
+ if (diag_command == 9) {
+ mutual_data[i * ic_data->HX_RX_NUM + j]
+ = new_data;
+ /*Keep max data for 100 frame*/
+ } else if (diag_command == 91) {
+ if (mutual_data[i * ic_data->HX_RX_NUM + j]
+ < new_data) {
+ mutual_data[i * ic_data->HX_RX_NUM + j]
+ = new_data;
+ }
+ /*Cal data for [N]-[N-1] frame*/
+ } else if (diag_command == 92) {
+ mutual_data_new[i * ic_data->HX_RX_NUM + j]
+ = new_data;
+
+ mutual_data[i * ic_data->HX_RX_NUM + j] =
+ mutual_data_new[i * ic_data->HX_RX_NUM + j] -
+ mutual_data_old[i * ic_data->HX_RX_NUM + j];
}
index += 2;
}
}
- if(diag_command == 92){
- memcpy(mutual_data_old,mutual_data_new,x_channel * y_channel * sizeof(int16_t)); //copy N data to N-1 array
+ /*copy N data to N-1 array*/
+ if (diag_command == 92) {
+ memcpy(mutual_data_old, mutual_data_new,
+ x_channel * y_channel * sizeof(int16_t));
}
+
diag_max_cnt++;
- if(diag_command == 9 || diag_command == 92){
- queue_delayed_work(private_ts->himax_diag_wq, &private_ts->himax_diag_delay_wrok, 1/10*HZ);
- }else if(diag_command == 91){
- if(diag_max_cnt > 100) //count for 100 frame
- {
- //Clear DSRAM flag
+ if (diag_command == 9 || diag_command == 92) {
+ queue_delayed_work(private_ts->himax_diag_wq,
+ &private_ts->himax_diag_delay_wrok, 1/10*HZ);
+ } else if (diag_command == 91) {
+ if (diag_max_cnt > 100) {/*count for 100 frame*/
+ /*Clear DSRAM flag*/
DSRAM_Flag = false;
- //Enable ISR
- himax_int_enable(private_ts->client->irq,1);
+ /*Enable ISR*/
+ himax_int_enable(private_ts->client->irq, 1);
- //=====================================
- // test result command : 0x8002_0324 ==> 0x00
- //=====================================
+ /*=====================================
+ test result command : 0x8002_0324 ==> 0x00
+ =====================================*/
himax_diag_register_set(private_ts->client, 0x00);
- }else{
- queue_delayed_work(private_ts->himax_diag_wq, &private_ts->himax_diag_delay_wrok, 1/10*HZ);
+ } else {
+ queue_delayed_work(private_ts->himax_diag_wq,
+ &private_ts->himax_diag_delay_wrok, 1 / 10 * HZ);
}
}
}
-static ssize_t himax_diag_write(struct file *filp, const char __user *buff, size_t len, loff_t *data)
+static ssize_t himax_diag_write
+(struct file *filp, const char __user *buff, size_t len, loff_t *data)
{
char messages[80] = {0};
@@ -915,67 +893,66 @@
memset(receive, 0x00, sizeof(receive));
- if (len >= 80)
- {
+ if (len >= 80) {
I("%s: no command exceeds 80 chars.\n", __func__);
return -EFAULT;
}
if (copy_from_user(messages, buff, len))
- {
return -EFAULT;
- }
- if (messages[1] == 0x0A){
- diag_command =messages[0] - '0';
- }else{
- diag_command =(messages[0] - '0')*10 + (messages[1] - '0');
- }
- I("[Himax]diag_command=0x%x\n",diag_command);
- if (diag_command < 0x04){
- if(DSRAM_Flag)
- {
- //1. Clear DSRAM flag
+ if (messages[1] == 0x0A)
+ diag_command = messages[0] - '0';
+ else
+ diag_command = (messages[0] - '0') * 10 + (messages[1] - '0');
+
+
+ I("[Himax]diag_command=0x%x\n", diag_command);
+ if (diag_command < 0x04) {
+ if (DSRAM_Flag) {
+ /*1. Clear DSRAM flag*/
DSRAM_Flag = false;
- //2. Stop DSRAM thread
- cancel_delayed_work_sync(&private_ts->himax_diag_delay_wrok);
+ /*2. Stop DSRAM thread*/
+ cancel_delayed_work_sync
+ (&private_ts->himax_diag_delay_wrok);
- //3. Enable ISR
- himax_int_enable(private_ts->client->irq,1);
+ /*3. Enable ISR*/
+ himax_int_enable(private_ts->client->irq, 1);
}
command[0] = diag_command;
himax_diag_register_set(private_ts->client, command[0]);
- }
- //coordinate dump start
- else if (diag_command == 0x08) {
- E("%s: coordinate_dump_file_create error\n", __func__);
- }
- else if (diag_command == 0x09 || diag_command == 91 || diag_command == 92){
+ /*coordinate dump start*/
+ } else if (diag_command == 0x09 ||
+ diag_command == 91 || diag_command == 92) {
+
diag_max_cnt = 0;
- memset(diag_mutual, 0x00, x_channel * y_channel * sizeof(int16_t)); //Set data 0 everytime
+ /*Set data 0 everytime*/
+ memset(diag_mutual, 0x00,
+ x_channel * y_channel * sizeof(int16_t));
- //1. Disable ISR
- himax_int_enable(private_ts->client->irq,0);
+ /*1. Disable ISR*/
+ himax_int_enable(private_ts->client->irq, 0);
- //2. Start DSRAM thread
- //himax_diag_register_set(private_ts->client, 0x0A);
+ /*2. Start DSRAM thread*/
+ /*himax_diag_register_set(private_ts->client, 0x0A);*/
- queue_delayed_work(private_ts->himax_diag_wq, &private_ts->himax_diag_delay_wrok, 2*HZ/100);
+ queue_delayed_work(private_ts->himax_diag_wq,
+ &private_ts->himax_diag_delay_wrok, 2 * HZ / 100);
I("%s: Start get raw data in DSRAM\n", __func__);
- //3. Set DSRAM flag
+ /*3. Set DSRAM flag*/
DSRAM_Flag = true;
- }else{
+ } else {
command[0] = 0x00;
himax_diag_register_set(private_ts->client, command[0]);
- E("[Himax]Diag command error!diag_command=0x%x\n",diag_command);
+ E("[Himax]Diag command error!diag_command=0x%x\n",
+ diag_command);
}
return len;
}
-static const struct file_operations himax_proc_diag_ops =
-{
+const struct file_operations himax_proc_diag_ops = {
.owner = THIS_MODULE,
.open = himax_diag_proc_open,
.read = seq_read,
@@ -989,23 +966,20 @@
{
char buf_tmp[12];
- if (len >= 12)
- {
+ if (len >= 12) {
I("%s: no command exceeds 12 chars.\n", __func__);
return -EFAULT;
}
if (copy_from_user(buf_tmp, buff, len))
- {
return -EFAULT;
- }
- //if (buf_tmp[0] == '1')
- // ESD_HW_REST();
+
+ /*if (buf_tmp[0] == '1')
+ ESD_HW_REST();*/
return len;
}
-static const struct file_operations himax_proc_reset_ops =
-{
+const struct file_operations himax_proc_reset_ops = {
.owner = THIS_MODULE,
.write = himax_reset_write,
};
@@ -1018,291 +992,263 @@
size_t count = 0;
char *temp_buf;
- if(!HX_PROC_SEND_FLAG)
- {
+ if (!HX_PROC_SEND_FLAG) {
temp_buf = kzalloc(len, GFP_KERNEL);
- if (!temp_buf){
- HX_PROC_SEND_FLAG=0;
- return count;
- }
-
- if (debug_level_cmd == 't')
- {
- if (fw_update_complete)
- count += snprintf(temp_buf+count, len-count, "FW Update Complete ");
- else
- {
- count += snprintf(temp_buf+count, len-count, "FW Update Fail ");
- }
- }
- else if (debug_level_cmd == 'h')
- {
- if (handshaking_result == 0)
- {
- count += snprintf(temp_buf+count, len-count, "Handshaking Result = %d (MCU Running)\n", handshaking_result);
- }
- else if (handshaking_result == 1)
- {
- count += snprintf(temp_buf+count, len-count, "Handshaking Result = %d (MCU Stop)\n", handshaking_result);
- }
- else if (handshaking_result == 2)
- {
- count += snprintf(temp_buf+count, len-count, "Handshaking Result = %d (I2C Error)\n", handshaking_result);
- }
- else
- {
- count += snprintf(temp_buf+count, len-count, "Handshaking Result = error\n");
- }
- }
- else if (debug_level_cmd == 'v')
- {
- count += snprintf(temp_buf+count, len-count, "FW_VER = ");
- count += snprintf(temp_buf+count, len-count, "0x%2.2X\n", ic_data->vendor_fw_ver);
- count += snprintf(temp_buf+count, len-count, "CONFIG_VER = ");
- count += snprintf(temp_buf+count, len-count, "0x%2.2X\n", ic_data->vendor_config_ver);
- count += snprintf(temp_buf+count, len-count, "\n");
- }
- else if (debug_level_cmd == 'd')
- {
- count += snprintf(temp_buf+count, len-count, "Himax Touch IC Information :\n");
- if (IC_TYPE == HX_85XX_D_SERIES_PWON)
- {
- count += snprintf(temp_buf+count, len-count, "IC Type : D\n");
- }
- else if (IC_TYPE == HX_85XX_E_SERIES_PWON)
- {
- count += snprintf(temp_buf+count, len-count, "IC Type : E\n");
- }
- else if (IC_TYPE == HX_85XX_ES_SERIES_PWON)
- {
- count += snprintf(temp_buf+count, len-count, "IC Type : ES\n");
- }
- else if (IC_TYPE == HX_85XX_F_SERIES_PWON)
- {
- count += snprintf(temp_buf+count, len-count, "IC Type : F\n");
- }
- else
- {
- count += snprintf(temp_buf+count, len-count, "IC Type error.\n");
+ if (debug_level_cmd == 't') {
+ if (fw_update_complete) {
+ count += snprintf(temp_buf, len,
+ "FW Update Complete ");
+ } else {
+ count += snprintf(temp_buf, len,
+ "FW Update Fail ");
}
- if (IC_CHECKSUM == HX_TP_BIN_CHECKSUM_SW)
- {
- count += snprintf(temp_buf+count, len-count, "IC Checksum : SW\n");
+ } else if (debug_level_cmd == 'h') {
+ if (handshaking_result == 0) {
+ count += snprintf(temp_buf, len,
+ "Handshaking Result = %d (MCU Running)\n",
+ handshaking_result);
+ } else if (handshaking_result == 1) {
+ count += snprintf(temp_buf, len,
+ "Handshaking Result = %d (MCU Stop)\n",
+ handshaking_result);
+ } else if (handshaking_result == 2) {
+ count += snprintf(temp_buf, len,
+ "Handshaking Result = %d (I2C Error)\n",
+ handshaking_result);
+ } else {
+ count += snprintf(temp_buf, len,
+ "Handshaking Result = error\n");
}
- else if (IC_CHECKSUM == HX_TP_BIN_CHECKSUM_HW)
- {
- count += snprintf(temp_buf+count, len-count, "IC Checksum : HW\n");
+ } else if (debug_level_cmd == 'v') {
+ count += snprintf(temp_buf + count, len,
+ "FW_VER = ");
+ count += snprintf(temp_buf + count, len,
+ "0x%2.2X\n", ic_data->vendor_fw_ver);
+ count += snprintf(temp_buf + count, len,
+ "CONFIG_VER = ");
+ count += snprintf(temp_buf + count, len,
+ "0x%2.2X\n", ic_data->vendor_config_ver);
+ count += snprintf(temp_buf + count, len,
+ "\n");
+ } else if (debug_level_cmd == 'd') {
+ count += snprintf(temp_buf + count, len,
+ "Himax Touch IC Information :\n");
+ if (IC_TYPE == HX_85XX_D_SERIES_PWON) {
+ count += snprintf(temp_buf + count, len,
+ "IC Type : D\n");
+ } else if (IC_TYPE == HX_85XX_E_SERIES_PWON) {
+ count += snprintf(temp_buf + count, len,
+ "IC Type : E\n");
+ } else if (IC_TYPE == HX_85XX_ES_SERIES_PWON) {
+ count += snprintf(temp_buf + count, len,
+ "IC Type : ES\n");
+ } else if (IC_TYPE == HX_85XX_F_SERIES_PWON) {
+ count += snprintf(temp_buf + count, len,
+ "IC Type : F\n");
+ } else {
+ count += snprintf(temp_buf + count, len,
+ "IC Type error.\n");
}
- else if (IC_CHECKSUM == HX_TP_BIN_CHECKSUM_CRC)
- {
- count += snprintf(temp_buf+count, len-count, "IC Checksum : CRC\n");
+ if (IC_CHECKSUM == HX_TP_BIN_CHECKSUM_SW) {
+ count += snprintf(temp_buf + count, len,
+ "IC Checksum : SW\n");
+ } else if (IC_CHECKSUM == HX_TP_BIN_CHECKSUM_HW) {
+ count += snprintf(temp_buf + count, len,
+ "IC Checksum : HW\n");
+ } else if (IC_CHECKSUM == HX_TP_BIN_CHECKSUM_CRC) {
+ count += snprintf(temp_buf + count, len,
+ "IC Checksum : CRC\n");
+ } else {
+ count += snprintf(temp_buf + count, len,
+ "IC Checksum error.\n");
}
- else
- {
- count += snprintf(temp_buf+count, len-count, "IC Checksum error.\n");
+ if (ic_data->HX_INT_IS_EDGE) {
+ count += snprintf(temp_buf + count, len,
+ "Interrupt : EDGE TIRGGER\n");
+ } else {
+ count += snprintf(temp_buf + count, len,
+ "Interrupt : LEVEL TRIGGER\n");
}
-
- if (ic_data->HX_INT_IS_EDGE)
- {
- count += snprintf(temp_buf+count, len-count, "Interrupt : EDGE TIRGGER\n");
- }
- else
- {
- count += snprintf(temp_buf+count, len-count, "Interrupt : LEVEL TRIGGER\n");
- }
-
- count += snprintf(temp_buf+count, len-count, "RX Num : %d\n", ic_data->HX_RX_NUM);
- count += snprintf(temp_buf+count, len-count, "TX Num : %d\n", ic_data->HX_TX_NUM);
- count += snprintf(temp_buf+count, len-count, "BT Num : %d\n", ic_data->HX_BT_NUM);
- count += snprintf(temp_buf+count, len-count, "X Resolution : %d\n", ic_data->HX_X_RES);
- count += snprintf(temp_buf+count, len-count, "Y Resolution : %d\n", ic_data->HX_Y_RES);
- count += snprintf(temp_buf+count, len-count, "Max Point : %d\n", ic_data->HX_MAX_PT);
- count += snprintf(temp_buf+count, len-count, "XY reverse : %d\n", ic_data->HX_XY_REVERSE);
+ count += snprintf(temp_buf + count, len,
+ "RX Num : %d\n", ic_data->HX_RX_NUM);
+ count += snprintf(temp_buf + count, len,
+ "TX Num : %d\n", ic_data->HX_TX_NUM);
+ count += snprintf(temp_buf + count, len,
+ "BT Num : %d\n", ic_data->HX_BT_NUM);
+ count += snprintf(temp_buf + count, len,
+ "X Resolution : %d\n", ic_data->HX_X_RES);
+ count += snprintf(temp_buf + count, len,
+ "Y Resolution : %d\n", ic_data->HX_Y_RES);
+ count += snprintf(temp_buf + count, len,
+ "Max Point : %d\n", ic_data->HX_MAX_PT);
+ count += snprintf(temp_buf + count, len,
+ "XY reverse : %d\n", ic_data->HX_XY_REVERSE);
#ifdef HX_TP_PROC_2T2R
- if(Is_2T2R)
- {
- count += snprintf(temp_buf+count, len-count, "2T2R panel\n");
- count += snprintf(temp_buf+count, len-count, "RX Num_2 : %d\n", HX_RX_NUM_2);
- count += snprintf(temp_buf+count, len-count, "TX Num_2 : %d\n", HX_TX_NUM_2);
+ if (Is_2T2R) {
+ count += snprintf(temp_buf + count, len,
+ "2T2R panel\n");
+ count += snprintf(temp_buf + count, len,
+ "RX Num_2 : %d\n", HX_RX_NUM_2);
+ count += snprintf(temp_buf + count, len,
+ "TX Num_2 : %d\n", HX_TX_NUM_2);
}
#endif
- }
- else if (debug_level_cmd == 'i')
- {
- count += snprintf(temp_buf+count, len-count, "Himax Touch Driver Version:\n");
- count += snprintf(temp_buf+count, len-count, "%s\n", HIMAX_DRIVER_VER);
+ } else if (debug_level_cmd == 'i') {
+ count += snprintf(temp_buf + count, len,
+ "Himax Touch Driver Version:\n");
+ count += snprintf(temp_buf + count, len,
+ "%s\n", HIMAX_DRIVER_VER);
}
if (copy_to_user(buf, temp_buf, len))
- {
I("%s,here:%d\n", __func__, __LINE__);
- }
kfree(temp_buf);
- HX_PROC_SEND_FLAG=1;
- }
- else
- HX_PROC_SEND_FLAG=0;
+ HX_PROC_SEND_FLAG = 1;
+ } else
+ HX_PROC_SEND_FLAG = 0;
return count;
}
static ssize_t himax_debug_write(struct file *file, const char *buff,
size_t len, loff_t *pos)
{
- const struct firmware *fw = NULL;
- unsigned char *fw_data = NULL;
+ int result = 0;
char fileName[128];
char buf[80] = {0};
- int result;
+ const struct firmware *fw = NULL;
- if (len >= 80)
- {
+ if (len >= 80) {
I("%s: no command exceeds 80 chars.\n", __func__);
return -EFAULT;
}
if (copy_from_user(buf, buff, len))
- {
return -EFAULT;
- }
- if ( buf[0] == 'h') //handshaking
- {
+ if (buf[0] == 'h') {/*handshaking*/
debug_level_cmd = buf[0];
- himax_int_enable(private_ts->client->irq,0);
+ himax_int_enable(private_ts->client->irq, 0);
- handshaking_result = himax_hand_shaking(private_ts->client); //0:Running, 1:Stop, 2:I2C Fail
+ /*0:Running, 1:Stop, 2:I2C Fail*/
+ handshaking_result = himax_hand_shaking(private_ts->client);
- himax_int_enable(private_ts->client->irq,1);
+ himax_int_enable(private_ts->client->irq, 1);
return len;
- }
-
- else if ( buf[0] == 'v') //firmware version
- {
+ } else if (buf[0] == 'v') { /*firmware version*/
debug_level_cmd = buf[0];
- himax_int_enable(private_ts->client->irq,0);
+ himax_int_enable(private_ts->client->irq, 0);
#ifdef HX_RST_PIN_FUNC
- himax_HW_reset(false,false);
+ himax_HW_reset(false, false);
#endif
himax_read_FW_ver(private_ts->client);
- //himax_check_chip_version();
+ /*himax_check_chip_version();*/
#ifdef HX_RST_PIN_FUNC
- himax_HW_reset(true,false);
+ himax_HW_reset(true, false);
#endif
- himax_int_enable(private_ts->client->irq,1);
+ himax_int_enable(private_ts->client->irq, 1);
return len;
- }
+ } else if (buf[0] == 'd') { /*ic information*/
- else if ( buf[0] == 'd') //ic information
- {
debug_level_cmd = buf[0];
return len;
- }
+ } else if (buf[0] == 'i') {/*driver version*/
- else if ( buf[0] == 'i') //driver version
- {
debug_level_cmd = buf[0];
return len;
- }
+ } else if (buf[0] == 't') {
- else if (buf[0] == 't')
- {
+ himax_int_enable(private_ts->client->irq, 0);
+ debug_level_cmd = buf[0];
+ fw_update_complete = false;
- himax_int_enable(private_ts->client->irq,0);
-
- debug_level_cmd = buf[0];
- fw_update_complete = false;
-
- memset(fileName, 0, 128);
- // parse the file name
- snprintf(fileName, len-4, "%s", &buf[4]);
- I("%s: upgrade from file(%s) start!\n", __func__, fileName);
- // open file
- result = request_firmware(&fw, fileName, private_ts->dev);
- if (result) {
- E("%s: open firmware file failed\n", __func__);
- goto firmware_upgrade_done;
- //return len;
+ result = himax_load_CRC_bin_file(private_ts->client);
+ if (result < 0) {
+ E("%s: himax_load_CRC_bin_file fail Error Code=%d.\n",
+ __func__, result);
+ return result;
}
- I("%s: FW len %d\n", __func__, fw->size);
- fw_data = (unsigned char *)fw->data;
+ memset(fileName, 0, 128);
+/* parse the file name*/
+ snprintf(fileName, len-4, "%s", &buf[4]);
+ I("%s: upgrade from file(%s) start!\n", __func__, fileName);
+ result = request_firmware(&fw, fileName, private_ts->dev);
+ if (result < 0) {
+ I("fail to request_firmware fwpath: %s (ret:%d)\n",
+ fileName, result);
+ return result;
+ }
+ I("%s: FW image: %02X, %02X, %02X, %02X ret=%d\n", __func__,
+ fw->data[0], fw->data[1], fw->data[2], fw->data[3], result);
+ if (result >= 0) {
+ /*start to upgrade*/
+ himax_int_enable(private_ts->client->irq, 0);
- I("%s: FW image,len %d: %02X, %02X, %02X, %02X\n", __func__, result, upgrade_fw[0], upgrade_fw[1], upgrade_fw[2], upgrade_fw[3]);
-
- if (fw_data != NULL)
- {
- // start to upgrade
- himax_int_enable(private_ts->client->irq,0);
-
- if ((buf[1] == '6') && (buf[2] == '0'))
- {
- if (fts_ctpm_fw_upgrade_with_sys_fs_60k(private_ts->client,upgrade_fw, result, false) == 0)
- {
- E("%s: TP upgrade error, line: %d\n", __func__, __LINE__);
+ if ((buf[1] == '6') && (buf[2] == '0')) {
+ if (fts_ctpm_fw_upgrade_with_sys_fs_60k
+ (private_ts->client, (unsigned char *)fw->data,
+ fw->size, false) == 0) {
+ E("%s: TP upgrade error, line: %d\n",
+ __func__, __LINE__);
fw_update_complete = false;
- }
- else
- {
- I("%s: TP upgrade OK, line: %d\n", __func__, __LINE__);
+ } else {
+ I("%s: TP upgrade OK, line: %d\n",
+ __func__, __LINE__);
fw_update_complete = true;
}
- }
- else if ((buf[1] == '6') && (buf[2] == '4'))
- {
- if (fts_ctpm_fw_upgrade_with_sys_fs_64k(private_ts->client,upgrade_fw, result, false) == 0)
- {
- E("%s: TP upgrade error, line: %d\n", __func__, __LINE__);
+ } else if ((buf[1] == '6') && (buf[2] == '4')) {
+ if (fts_ctpm_fw_upgrade_with_sys_fs_64k
+ (private_ts->client, (unsigned char *)fw->data,
+ fw->size, false) == 0) {
+ E("%s: TP upgrade error, line: %d\n",
+ __func__, __LINE__);
fw_update_complete = false;
- }
- else
- {
- I("%s: TP upgrade OK, line: %d\n", __func__, __LINE__);
+ } else {
+ I("%s: TP upgrade OK, line: %d\n",
+ __func__, __LINE__);
fw_update_complete = true;
}
- }
- else if ((buf[1] == '2') && (buf[2] == '4'))
- {
- if (fts_ctpm_fw_upgrade_with_sys_fs_124k(private_ts->client,upgrade_fw, result, false) == 0)
- {
- E("%s: TP upgrade error, line: %d\n", __func__, __LINE__);
+ } else if ((buf[1] == '2') && (buf[2] == '4')) {
+ if (fts_ctpm_fw_upgrade_with_sys_fs_124k
+ (private_ts->client, (unsigned char *)fw->data,
+ fw->size, false) == 0) {
+ E("%s: TP upgrade error, line: %d\n",
+ __func__, __LINE__);
fw_update_complete = false;
- }
- else
- {
- I("%s: TP upgrade OK, line: %d\n", __func__, __LINE__);
+ } else {
+ I("%s: TP upgrade OK, line: %d\n",
+ __func__, __LINE__);
fw_update_complete = true;
}
- }
- else if ((buf[1] == '2') && (buf[2] == '8'))
- {
- if (fts_ctpm_fw_upgrade_with_sys_fs_128k(private_ts->client,upgrade_fw, result, false) == 0)
- {
- E("%s: TP upgrade error, line: %d\n", __func__, __LINE__);
+ } else if ((buf[1] == '2') && (buf[2] == '8')) {
+ if (fts_ctpm_fw_upgrade_with_sys_fs_128k
+ (private_ts->client, (unsigned char *)fw->data,
+ fw->size, false) == 0) {
+ E("%s: TP upgrade error, line: %d\n",
+ __func__, __LINE__);
fw_update_complete = false;
- }
- else
- {
- I("%s: TP upgrade OK, line: %d\n", __func__, __LINE__);
+ } else {
+ I("%s: TP upgrade OK, line: %d\n",
+ __func__, __LINE__);
fw_update_complete = true;
}
- }
- else
- {
- E("%s: Flash command fail: %d\n", __func__, __LINE__);
+ } else {
+ E("%s: Flash command fail: %d\n",
+ __func__, __LINE__);
fw_update_complete = false;
}
release_firmware(fw);
goto firmware_upgrade_done;
- //return count;
+ /*return count;*/
}
}
- firmware_upgrade_done:
+firmware_upgrade_done:
#ifdef HX_RST_PIN_FUNC
- himax_HW_reset(true,false);
+ himax_HW_reset(true, false);
#endif
himax_sense_on(private_ts->client, 0x01);
@@ -1310,16 +1256,15 @@
#ifdef HX_ESD_WORKAROUND
HX_ESD_RESET_ACTIVATE = 1;
#endif
- himax_int_enable(private_ts->client->irq,1);
+ himax_int_enable(private_ts->client->irq, 1);
- //todo himax_chip->tp_firmware_upgrade_proceed = 0;
- //todo himax_chip->suspend_state = 0;
- //todo enable_irq(himax_chip->irq);
+ /*todo himax_chip->tp_firmware_upgrade_proceed = 0;
+ todo himax_chip->suspend_state = 0;
+ todo enable_irq(himax_chip->irq);*/
return len;
}
-static const struct file_operations himax_proc_debug_ops =
-{
+const struct file_operations himax_proc_debug_ops = {
.owner = THIS_MODULE,
.read = himax_debug_read,
.write = himax_debug_write,
@@ -1376,9 +1321,9 @@
void setFlashBuffer(void)
{
- flash_buffer = kzalloc(Flash_Size * sizeof(uint8_t), GFP_KERNEL);
- if (flash_buffer)
- memset(flash_buffer,0x00,Flash_Size);
+ flash_buffer = kzalloc
+ (Flash_Size * sizeof(uint8_t), GFP_KERNEL);
+ memset(flash_buffer, 0x00, Flash_Size);
}
void setSysOperation(uint8_t operation)
@@ -1389,7 +1334,8 @@
static void setFlashDumpProgress(uint8_t progress)
{
flash_progress = progress;
- //I("setFlashDumpProgress : progress = %d ,flash_progress = %d \n",progress,flash_progress);
+ /*I("setFlashDumpProgress : progress = %d ,
+ flash_progress = %d\n",progress,flash_progress);*/
}
static void setFlashDumpComplete(uint8_t status)
@@ -1432,130 +1378,113 @@
{
int ret = 0;
int loop_i;
- uint8_t local_flash_read_step=0;
+ uint8_t local_flash_read_step = 0;
uint8_t local_flash_complete = 0;
uint8_t local_flash_progress = 0;
uint8_t local_flash_command = 0;
uint8_t local_flash_fail = 0;
char *temp_buf;
+
local_flash_complete = getFlashDumpComplete();
local_flash_progress = getFlashDumpProgress();
local_flash_command = getFlashCommand();
local_flash_fail = getFlashDumpFail();
- I("flash_progress = %d \n",local_flash_progress);
- if(!HX_PROC_SEND_FLAG)
- {
+ I("flash_progress = %d\n", local_flash_progress);
+ if (!HX_PROC_SEND_FLAG) {
temp_buf = kzalloc(len, GFP_KERNEL);
- if (!temp_buf) {
- HX_PROC_SEND_FLAG=0;
- return ret;
- }
-
- if (local_flash_fail)
- {
- ret += snprintf(temp_buf+ret, len-ret, "FlashStart:Fail \n");
- ret += snprintf(temp_buf+ret, len-ret, "FlashEnd");
- ret += snprintf(temp_buf+ret, len-ret, "\n");
+ if (local_flash_fail) {
+ ret += snprintf(temp_buf + ret, len,
+ "FlashStart:Fail\n");
+ ret += snprintf(temp_buf + ret, len,
+ "FlashEnd");
+ ret += snprintf(temp_buf + ret, len,
+ "\n");
if (copy_to_user(buf, temp_buf, len))
- {
I("%s,here:%d\n", __func__, __LINE__);
- }
kfree(temp_buf);
HX_PROC_SEND_FLAG = 1;
return ret;
}
- if (!local_flash_complete)
- {
- ret += snprintf(temp_buf+ret, len-ret, "FlashStart:Ongoing:0x%2.2x \n",flash_progress);
- ret += snprintf(temp_buf+ret, len-ret, "FlashEnd");
- ret += snprintf(temp_buf+ret, len-ret, "\n");
+ if (!local_flash_complete) {
+ ret += snprintf(temp_buf+ret, len,
+ "FlashStart:Ongoing:0x%2.2x\n", flash_progress);
+ ret += snprintf(temp_buf + ret, len, "FlashEnd");
+ ret += snprintf(temp_buf + ret, len, "\n");
if (copy_to_user(buf, temp_buf, len))
- {
I("%s,here:%d\n", __func__, __LINE__);
- }
kfree(temp_buf);
HX_PROC_SEND_FLAG = 1;
return ret;
}
- if (local_flash_command == 1 && local_flash_complete)
- {
- ret += snprintf(temp_buf+ret, len-ret, "FlashStart:Complete \n");
- ret += snprintf(temp_buf+ret, len-ret, "FlashEnd");
- ret += snprintf(temp_buf+ret, len-ret, "\n");
+ if (local_flash_command == 1 && local_flash_complete) {
+ ret += snprintf(temp_buf+ret, len,
+ "FlashStart:Complete\n");
+ ret += snprintf(temp_buf + ret, len, "FlashEnd");
+ ret += snprintf(temp_buf + ret, len, "\n");
if (copy_to_user(buf, temp_buf, len))
- {
I("%s,here:%d\n", __func__, __LINE__);
- }
kfree(temp_buf);
HX_PROC_SEND_FLAG = 1;
return ret;
}
- if (local_flash_command == 3 && local_flash_complete)
- {
- ret += snprintf(temp_buf+ret, len-ret, "FlashStart: \n");
- for(loop_i = 0; loop_i < 128; loop_i++)
- {
- ret += snprintf(temp_buf+ret, len-ret, "x%2.2x", flash_buffer[loop_i]);
+ if (local_flash_command == 3 && local_flash_complete) {
+ ret += snprintf(temp_buf+ret, len, "FlashStart:\n");
+ for (loop_i = 0 ; loop_i < 128 ; loop_i++) {
+ ret += snprintf(temp_buf + ret, len,
+ "x%2.2x", flash_buffer[loop_i]);
if ((loop_i % 16) == 15)
- {
- ret += snprintf(temp_buf+ret, len-ret, "\n");
- }
+ ret += snprintf(temp_buf + ret, len,
+ "\n");
}
- ret += snprintf(temp_buf+ret, len-ret, "FlashEnd");
- ret += snprintf(temp_buf+ret, len-ret, "\n");
+ ret += snprintf(temp_buf + ret, len, "FlashEnd");
+ ret += snprintf(temp_buf + ret, len, "\n");
if (copy_to_user(buf, temp_buf, len))
- {
I("%s,here:%d\n", __func__, __LINE__);
- }
kfree(temp_buf);
HX_PROC_SEND_FLAG = 1;
return ret;
}
- //flash command == 0 , report the data
+ /*flash command == 0 , report the data*/
local_flash_read_step = getFlashReadStep();
- ret += snprintf(temp_buf+ret, len-ret, "FlashStart:%2.2x \n",local_flash_read_step);
+ ret += snprintf(temp_buf + ret, len,
+ "FlashStart:%2.2x\n", local_flash_read_step);
- for (loop_i = 0; loop_i < 1024; loop_i++)
- {
- ret += snprintf(temp_buf+ret, len-ret, "x%2.2X", flash_buffer[local_flash_read_step*1024 + loop_i]);
+ for (loop_i = 0 ; loop_i < 1024 ; loop_i++) {
+ ret += snprintf(temp_buf + ret, len, "x%2.2X",
+ flash_buffer[local_flash_read_step * 1024 + loop_i]);
if ((loop_i % 16) == 15)
- {
- ret += snprintf(temp_buf+ret, len-ret, "\n");
- }
+ ret += snprintf(temp_buf + ret, len, "\n");
}
- ret += snprintf(temp_buf+ret, len-ret, "FlashEnd");
- ret += snprintf(temp_buf+ret, len-ret, "\n");
+ ret += snprintf(temp_buf + ret, len, "FlashEnd");
+ ret += snprintf(temp_buf + ret, len, "\n");
if (copy_to_user(buf, temp_buf, len))
- {
I("%s,here:%d\n", __func__, __LINE__);
- }
kfree(temp_buf);
HX_PROC_SEND_FLAG = 1;
- }
- else
- HX_PROC_SEND_FLAG=0;
+ } else
+ HX_PROC_SEND_FLAG = 0;
return ret;
}
-static ssize_t himax_proc_flash_write(struct file *file, const char *buff,
- size_t len, loff_t *pos)
+static ssize_t himax_proc_flash_write(struct file *file,
+const char *buff, size_t len, loff_t *pos)
{
char buf_tmp[6];
unsigned long result = 0;
@@ -1563,85 +1492,74 @@
int base = 0;
char buf[80] = {0};
- if (len >= 80)
- {
+ if (len >= 80) {
I("%s: no command exceeds 80 chars.\n", __func__);
return -EFAULT;
}
if (copy_from_user(buf, buff, len))
- {
return -EFAULT;
- }
memset(buf_tmp, 0x0, sizeof(buf_tmp));
I("%s: buf[0] = %s\n", __func__, buf);
- if (getSysOperation() == 1)
- {
+ if (getSysOperation() == 1) {
E("%s: PROC is busy , return!\n", __func__);
return len;
}
- if (buf[0] == '0')
- {
+ if (buf[0] == '0') {
setFlashCommand(0);
- if (buf[1] == ':' && buf[2] == 'x')
- {
+ if (buf[1] == ':' && buf[2] == 'x') {
memcpy(buf_tmp, buf + 3, 2);
I("%s: read_Step = %s\n", __func__, buf_tmp);
- if (!kstrtoul(buf_tmp, 16, &result))
- {
- I("%s: read_Step = %lu \n", __func__, result);
+ if (!kstrtoul(buf_tmp, 16, &result)) {
+ I("%s: read_Step = %lu\n", __func__, result);
setFlashReadStep(result);
}
}
- }
- else if (buf[0] == '1')// 1_60,1_64,1_24,1_28 for flash size 60k,64k,124k,128k
- {
+ /* 1_60,1_64,1_24,1_28 for flash size 60k,64k,124k,128k*/
+ } else if (buf[0] == '1') {
+
setSysOperation(1);
setFlashCommand(1);
setFlashDumpProgress(0);
setFlashDumpComplete(0);
setFlashDumpFail(0);
- if ((buf[1] == '_' ) && (buf[2] == '6' )){
- if (buf[3] == '0'){
+ if ((buf[1] == '_') && (buf[2] == '6')) {
+ if (buf[3] == '0')
Flash_Size = FW_SIZE_60k;
- }else if (buf[3] == '4'){
+ else if (buf[3] == '4')
Flash_Size = FW_SIZE_64k;
- }
- }else if ((buf[1] == '_' ) && (buf[2] == '2' )){
- if (buf[3] == '4'){
+
+ } else if ((buf[1] == '_') && (buf[2] == '2')) {
+ if (buf[3] == '4')
Flash_Size = FW_SIZE_124k;
- }else if (buf[3] == '8'){
+ else if (buf[3] == '8')
Flash_Size = FW_SIZE_128k;
- }
}
queue_work(private_ts->flash_wq, &private_ts->flash_work);
- }
- else if (buf[0] == '2') // 2_60,2_64,2_24,2_28 for flash size 60k,64k,124k,128k
- {
+ /* 2_60,2_64,2_24,2_28 for flash size 60k,64k,124k,128k*/
+ } else if (buf[0] == '2') {
setSysOperation(1);
setFlashCommand(2);
setFlashDumpProgress(0);
setFlashDumpComplete(0);
setFlashDumpFail(0);
- if ((buf[1] == '_' ) && (buf[2] == '6' )){
- if (buf[3] == '0'){
+ if ((buf[1] == '_') && (buf[2] == '6')) {
+ if (buf[3] == '0')
Flash_Size = FW_SIZE_60k;
- }else if (buf[3] == '4'){
+ else if (buf[3] == '4')
Flash_Size = FW_SIZE_64k;
- }
- }else if ((buf[1] == '_' ) && (buf[2] == '2' )){
- if (buf[3] == '4'){
+
+ } else if ((buf[1] == '_') && (buf[2] == '2')) {
+ if (buf[3] == '4')
Flash_Size = FW_SIZE_124k;
- }else if (buf[3] == '8'){
+ else if (buf[3] == '8')
Flash_Size = FW_SIZE_128k;
- }
+
}
queue_work(private_ts->flash_wq, &private_ts->flash_work);
- }
- else if (buf[0] == '3')
- {
+ } else if (buf[0] == '3') {
setSysOperation(1);
setFlashCommand(3);
setFlashDumpProgress(0);
@@ -1650,20 +1568,14 @@
memcpy(buf_tmp, buf + 3, 2);
if (!kstrtoul(buf_tmp, 16, &result))
- {
setFlashDumpSector(result);
- }
memcpy(buf_tmp, buf + 7, 2);
if (!kstrtoul(buf_tmp, 16, &result))
- {
setFlashDumpPage(result);
- }
queue_work(private_ts->flash_wq, &private_ts->flash_work);
- }
- else if (buf[0] == '4')
- {
+ } else if (buf[0] == '4') {
I("%s: command 4 enter.\n", __func__);
setSysOperation(1);
setFlashCommand(4);
@@ -1673,40 +1585,29 @@
memcpy(buf_tmp, buf + 3, 2);
if (!kstrtoul(buf_tmp, 16, &result))
- {
setFlashDumpSector(result);
- }
else
- {
E("%s: command 4 , sector error.\n", __func__);
return len;
- }
+
memcpy(buf_tmp, buf + 7, 2);
if (!kstrtoul(buf_tmp, 16, &result))
- {
setFlashDumpPage(result);
- }
else
- {
E("%s: command 4 , page error.\n", __func__);
return len;
- }
base = 11;
I("=========Himax flash page buffer start=========\n");
- for(loop_i=0;loop_i<128 && base<80;loop_i++)
- {
+ for (loop_i = 0 ; loop_i < 128 ; loop_i++) {
memcpy(buf_tmp, buf + base, 2);
- if (!kstrtoul(buf_tmp, 16, &result))
- {
+ if (!kstrtoul(buf_tmp, 16, &result)) {
flash_buffer[loop_i] = result;
- I("%d ",flash_buffer[loop_i]);
+ I("%d ", flash_buffer[loop_i]);
if (loop_i % 16 == 15)
- {
I("\n");
- }
}
base += 3;
}
@@ -1717,8 +1618,7 @@
return len;
}
-static const struct file_operations himax_proc_flash_ops =
-{
+const struct file_operations himax_proc_flash_ops = {
.owner = THIS_MODULE,
.read = himax_proc_flash_read,
.write = himax_proc_flash_write,
@@ -1728,31 +1628,44 @@
{
uint8_t local_flash_command = 0;
- himax_int_enable(private_ts->client->irq,0);
+ himax_int_enable(private_ts->client->irq, 0);
setFlashDumpGoing(true);
- //sector = getFlashDumpSector();
- //page = getFlashDumpPage();
+ /*sector = getFlashDumpSector();*/
+ /*page = getFlashDumpPage();*/
local_flash_command = getFlashCommand();
msleep(100);
- I("%s: local_flash_command = %d enter.\n", __func__,local_flash_command);
+ I("%s: local_flash_command = %d enter.\n",
+ __func__, local_flash_command);
- if ((local_flash_command == 1 || local_flash_command == 2)|| (local_flash_command==0x0F))
- {
- himax_flash_dump_func(private_ts->client, local_flash_command,Flash_Size, flash_buffer);
+ if ((local_flash_command == 1 || local_flash_command == 2)
+ || (local_flash_command == 0x0F)) {
+ himax_flash_dump_func(private_ts->client,
+ local_flash_command, Flash_Size, flash_buffer);
}
+
I("Complete~~~~~~~~~~~~~~~~~~~~~~~\n");
- if (local_flash_command == 2)
- {
- E("Flash dump failed\n");
+ if (local_flash_command == 2) {
+ struct file *fn;
+ struct filename *vts_name;
+
+ vts_name = getname_kernel(FLASH_DUMP_FILE);
+ fn = file_open_name(vts_name, O_CREAT | O_WRONLY, 0);
+ if (!IS_ERR(fn)) {
+ I("%s create file and ready to write\n", __func__);
+ fn->f_op->write(fn, flash_buffer,
+ Flash_Size * sizeof(uint8_t), &fn->f_pos);
+
+ filp_close(fn, NULL);
+ }
}
- himax_int_enable(private_ts->client->irq,1);
+ himax_int_enable(private_ts->client->irq, 1);
setFlashDumpGoing(false);
setFlashDumpComplete(1);
@@ -1761,7 +1674,7 @@
/* Flash_Dump_i2c_transfer_error:
- himax_int_enable(private_ts->client->irq,1);
+ himax_int_enable(private_ts->client->irq, 1);
setFlashDumpGoing(false);
setFlashDumpComplete(0);
setFlashDumpFail(1);
@@ -1776,53 +1689,47 @@
static ssize_t himax_self_test_read(struct file *file, char *buf,
size_t len, loff_t *pos)
{
- int val=0x00;
+ int val = 0x00;
int ret = 0;
char *temp_buf;
- I("%s: enter, %d \n", __func__, __LINE__);
- if(!HX_PROC_SEND_FLAG)
- {
+ I("%s:enter, %d\n", __func__, __LINE__);
+ if (!HX_PROC_SEND_FLAG) {
temp_buf = kzalloc(len, GFP_KERNEL);
- if (!temp_buf) {
- HX_PROC_SEND_FLAG=0;
- return ret;
- }
- himax_int_enable(private_ts->client->irq,0);//disable irq
+ himax_int_enable(private_ts->client->irq, 0);/*disable irq*/
val = himax_chip_self_test(private_ts->client);
#ifdef HX_ESD_WORKAROUND
HX_ESD_RESET_ACTIVATE = 1;
#endif
- himax_int_enable(private_ts->client->irq,1);//enable irq
+ himax_int_enable(private_ts->client->irq, 1);/*enable irq*/
if (val == 0x01) {
- ret += snprintf(temp_buf+ret, len-ret, "Self_Test Pass\n");
+ ret += snprintf(temp_buf + ret, len,
+ "Self_Test Pass\n");
} else {
- ret += snprintf(temp_buf+ret, len-ret, "Self_Test Fail\n");
+ ret += snprintf(temp_buf + ret, len,
+ "Self_Test Fail\n");
}
-
if (copy_to_user(buf, temp_buf, len))
- {
I("%s,here:%d\n", __func__, __LINE__);
- }
kfree(temp_buf);
HX_PROC_SEND_FLAG = 1;
- }
- else
- HX_PROC_SEND_FLAG=0;
+ } else
+ HX_PROC_SEND_FLAG = 0;
return ret;
}
/*
-static ssize_t himax_chip_self_test_store(struct device *dev,struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t himax_chip_self_test_store(struct device *dev,
+struct device_attribute *attr, const char *buf, size_t count)
{
char buf_tmp[2];
unsigned long result = 0;
memset(buf_tmp, 0x0, sizeof(buf_tmp));
memcpy(buf_tmp, buf, 2);
- if(!kstrtoul(buf_tmp, 16, &result))
+ if (!kstrtoul(buf_tmp, 16, &result))
{
sel_type = (uint8_t)result;
}
@@ -1831,8 +1738,7 @@
}
*/
-static const struct file_operations himax_proc_self_test_ops =
-{
+const struct file_operations himax_proc_self_test_ops = {
.owner = THIS_MODULE,
.read = himax_self_test_read,
};
@@ -1844,42 +1750,33 @@
{
char buf[80] = {0};
- if (len >= 80)
- {
+ if (len >= 80) {
I("%s: no command exceeds 80 chars.\n", __func__);
return -EFAULT;
}
if (copy_from_user(buf, buff, len))
- {
return -EFAULT;
- }
- if(buf[0] == '0')
- {
+ if (buf[0] == '0') {
himax_sense_off(private_ts->client);
- I("Sense off \n");
- }
- else if(buf[0] == '1')
- {
- if(buf[1] == '1'){
+ I("Sense off\n");
+ } else if (buf[0] == '1') {
+ if (buf[1] == '1') {
himax_sense_on(private_ts->client, 0x01);
- I("Sense on re-map off, run flash \n");
- }else if(buf[1] == '0'){
+ I("Sense on re-map off, run flash\n");
+ } else if (buf[1] == '0') {
himax_sense_on(private_ts->client, 0x00);
- I("Sense on re-map on, run sram \n");
- }else{
- I("Do nothing \n");
+ I("Sense on re-map on, run sram\n");
+ } else {
+ I("Do nothing\n");
}
- }
- else
- {
- I("Do nothing \n");
+ } else {
+ I("Do nothing\n");
}
return len;
}
-static const struct file_operations himax_proc_sense_on_off_ops =
-{
+const struct file_operations himax_proc_sense_on_off_ops = {
.owner = THIS_MODULE,
.write = himax_sense_on_off_write,
};
@@ -1893,25 +1790,18 @@
size_t count = 0;
char *temp_buf;
- if(!HX_PROC_SEND_FLAG)
- {
+ if (!HX_PROC_SEND_FLAG) {
temp_buf = kzalloc(len, GFP_KERNEL);
- if (!temp_buf) {
- HX_PROC_SEND_FLAG=0;
- return count;
- }
count = snprintf(temp_buf, len, "%d\n", ts->HSEN_enable);
- HX_PROC_SEND_FLAG=1;
+ HX_PROC_SEND_FLAG = 1;
if (copy_to_user(buf, temp_buf, len))
- {
I("%s,here:%d\n", __func__, __LINE__);
- }
+
kfree(temp_buf);
- }
- else
- HX_PROC_SEND_FLAG=0;
+ } else
+ HX_PROC_SEND_FLAG = 0;
return count;
}
@@ -1922,22 +1812,17 @@
char buf[80] = {0};
- if (len >= 80)
- {
+ if (len >= 80) {
I("%s: no command exceeds 80 chars.\n", __func__);
return -EFAULT;
}
if (copy_from_user(buf, buff, len))
- {
return -EFAULT;
- }
- if (buf[0] == '0'){
+ if (buf[0] == '0')
ts->HSEN_enable = 0;
- }
- else if (buf[0] == '1'){
+ else if (buf[0] == '1')
ts->HSEN_enable = 1;
- }
else
return -EINVAL;
@@ -1948,8 +1833,7 @@
return len;
}
-static const struct file_operations himax_proc_HSEN_ops =
-{
+const struct file_operations himax_proc_HSEN_ops = {
.owner = THIS_MODULE,
.read = himax_HSEN_read,
.write = himax_HSEN_write,
@@ -1964,25 +1848,17 @@
struct himax_ts_data *ts = private_ts;
char *temp_buf;
- if(!HX_PROC_SEND_FLAG)
- {
+ if (!HX_PROC_SEND_FLAG) {
temp_buf = kzalloc(len, GFP_KERNEL);
- if (!temp_buf) {
- HX_PROC_SEND_FLAG=0;
- return count;
- }
- count = snprintf(temp_buf, len, "%d\n", ts->SMWP_enable);
+ count = snprintf(temp_buf, "%d\n", len, ts->SMWP_enable);
if (copy_to_user(buf, temp_buf, len))
- {
I("%s,here:%d\n", __func__, __LINE__);
- }
kfree(temp_buf);
- HX_PROC_SEND_FLAG=1;
- }
- else
- HX_PROC_SEND_FLAG=0;
+ HX_PROC_SEND_FLAG = 1;
+ } else
+ HX_PROC_SEND_FLAG = 0;
return count;
}
@@ -1993,25 +1869,17 @@
struct himax_ts_data *ts = private_ts;
char buf[80] = {0};
- if (len >= 80)
- {
+ if (len >= 80) {
I("%s: no command exceeds 80 chars.\n", __func__);
return -EFAULT;
}
if (copy_from_user(buf, buff, len))
- {
return -EFAULT;
- }
-
if (buf[0] == '0')
- {
ts->SMWP_enable = 0;
- }
else if (buf[0] == '1')
- {
ts->SMWP_enable = 1;
- }
else
return -EINVAL;
@@ -2022,41 +1890,33 @@
return len;
}
-static const struct file_operations himax_proc_SMWP_ops =
-{
+const struct file_operations himax_proc_SMWP_ops = {
.owner = THIS_MODULE,
.read = himax_SMWP_read,
.write = himax_SMWP_write,
};
-static ssize_t himax_GESTURE_read(struct file *file, char *buf,
- size_t len, loff_t *pos)
+static ssize_t himax_GESTURE_read(struct file *file,
+char *buf, size_t len, loff_t *pos)
{
struct himax_ts_data *ts = private_ts;
- int i =0;
+ int i = 0;
int ret = 0;
char *temp_buf;
- if(!HX_PROC_SEND_FLAG)
- {
+ if (!HX_PROC_SEND_FLAG) {
temp_buf = kzalloc(len, GFP_KERNEL);
- if (!temp_buf) {
- HX_PROC_SEND_FLAG=0;
- return ret;
- }
- for(i=0;i<16;i++)
- ret += snprintf(temp_buf+ret, len-ret, "ges_en[%d]=%d\n", i, ts->gesture_cust_en[i]);
+ for (i = 0 ; i < 16 ; i++)
+ ret += snprintf(temp_buf + ret, len,
+ "ges_en[%d]=%d\n", i, ts->gesture_cust_en[i]);
+
HX_PROC_SEND_FLAG = 1;
if (copy_to_user(buf, temp_buf, len))
- {
I("%s,here:%d\n", __func__, __LINE__);
- }
kfree(temp_buf);
HX_PROC_SEND_FLAG = 1;
- }
- else
- {
+ } else {
HX_PROC_SEND_FLAG = 0;
ret = 0;
}
@@ -2067,35 +1927,30 @@
size_t len, loff_t *pos)
{
struct himax_ts_data *ts = private_ts;
- int i =0;
+ int i = 0;
char buf[80] = {0};
- if (len >= 80)
- {
+ if (len >= 80) {
I("%s: no command exceeds 80 chars.\n", __func__);
return -EFAULT;
}
if (copy_from_user(buf, buff, len))
- {
return -EFAULT;
- }
- I("himax_GESTURE_store= %s \n",buf);
- for (i=0;i<16;i++)
- {
+ I("himax_GESTURE_store= %s\n", buf);
+ for (i = 0 ; i < 16 ; i++) {
if (buf[i] == '0')
- ts->gesture_cust_en[i]= 0;
+ ts->gesture_cust_en[i] = 0;
else if (buf[i] == '1')
- ts->gesture_cust_en[i]= 1;
+ ts->gesture_cust_en[i] = 1;
else
- ts->gesture_cust_en[i]= 0;
- I("gesture en[%d]=%d \n", i, ts->gesture_cust_en[i]);
+ ts->gesture_cust_en[i] = 0;
+ I("gesture en[%d]=%d\n", i, ts->gesture_cust_en[i]);
}
return len;
}
-static const struct file_operations himax_proc_Gesture_ops =
-{
+const struct file_operations himax_proc_Gesture_ops = {
.owner = THIS_MODULE,
.read = himax_GESTURE_read,
.write = himax_GESTURE_write,
@@ -2104,202 +1959,223 @@
int himax_touch_proc_init(void)
{
- himax_touch_proc_dir = proc_mkdir( HIMAX_PROC_TOUCH_FOLDER, NULL);
- if (himax_touch_proc_dir == NULL)
- {
+ himax_touch_proc_dir = proc_mkdir(HIMAX_PROC_TOUCH_FOLDER, NULL);
+ if (himax_touch_proc_dir == NULL) {
E(" %s: himax_touch_proc_dir file create failed!\n", __func__);
return -ENOMEM;
}
- himax_proc_debug_level_file = proc_create(HIMAX_PROC_DEBUG_LEVEL_FILE, (S_IWUSR|S_IRUGO), himax_touch_proc_dir, &himax_proc_debug_level_ops);
- if (himax_proc_debug_level_file == NULL)
- {
+ himax_proc_debug_level_file = proc_create(HIMAX_PROC_DEBUG_LEVEL_FILE,
+ (S_IWUSR | S_IRUGO), himax_touch_proc_dir, &himax_proc_debug_level_ops);
+
+ if (himax_proc_debug_level_file == NULL) {
E(" %s: proc debug_level file create failed!\n", __func__);
goto fail_1;
}
- himax_proc_vendor_file = proc_create(HIMAX_PROC_VENDOR_FILE, (S_IRUGO),himax_touch_proc_dir, &himax_proc_vendor_ops);
- if(himax_proc_vendor_file == NULL)
- {
+ himax_proc_vendor_file = proc_create(HIMAX_PROC_VENDOR_FILE,
+ (S_IRUGO), himax_touch_proc_dir, &himax_proc_vendor_ops);
+
+ if (himax_proc_vendor_file == NULL) {
E(" %s: proc vendor file create failed!\n", __func__);
goto fail_2;
}
- himax_proc_attn_file = proc_create(HIMAX_PROC_ATTN_FILE, (S_IRUGO),himax_touch_proc_dir, &himax_proc_attn_ops);
- if(himax_proc_attn_file == NULL)
- {
+ himax_proc_attn_file = proc_create(HIMAX_PROC_ATTN_FILE,
+ (S_IRUGO), himax_touch_proc_dir, &himax_proc_attn_ops);
+
+ if (himax_proc_attn_file == NULL) {
E(" %s: proc attn file create failed!\n", __func__);
goto fail_3;
}
- himax_proc_int_en_file = proc_create(HIMAX_PROC_INT_EN_FILE, (S_IWUSR|S_IRUGO), himax_touch_proc_dir, &himax_proc_int_en_ops);
- if(himax_proc_int_en_file == NULL)
- {
+ himax_proc_int_en_file = proc_create(HIMAX_PROC_INT_EN_FILE,
+ (S_IWUSR | S_IRUGO), himax_touch_proc_dir, &himax_proc_int_en_ops);
+
+ if (himax_proc_int_en_file == NULL) {
E(" %s: proc int en file create failed!\n", __func__);
goto fail_4;
}
- himax_proc_layout_file = proc_create(HIMAX_PROC_LAYOUT_FILE, (S_IWUSR|S_IRUGO), himax_touch_proc_dir, &himax_proc_layout_ops);
- if(himax_proc_layout_file == NULL)
- {
+ himax_proc_layout_file = proc_create(HIMAX_PROC_LAYOUT_FILE,
+ (S_IWUSR | S_IRUGO), himax_touch_proc_dir, &himax_proc_layout_ops);
+
+ if (himax_proc_layout_file == NULL) {
E(" %s: proc layout file create failed!\n", __func__);
goto fail_5;
}
#ifdef HX_TP_PROC_RESET
- himax_proc_reset_file = proc_create(HIMAX_PROC_RESET_FILE, (S_IWUSR), himax_touch_proc_dir, &himax_proc_reset_ops);
- if(himax_proc_reset_file == NULL)
- {
+ himax_proc_reset_file = proc_create(HIMAX_PROC_RESET_FILE,
+ (S_IWUSR), himax_touch_proc_dir, &himax_proc_reset_ops);
+
+ if (himax_proc_reset_file == NULL) {
E(" %s: proc reset file create failed!\n", __func__);
goto fail_6;
}
#endif
#ifdef HX_TP_PROC_DIAG
- himax_proc_diag_file = proc_create(HIMAX_PROC_DIAG_FILE, (S_IWUSR|S_IRUGO), himax_touch_proc_dir, &himax_proc_diag_ops);
- if(himax_proc_diag_file == NULL)
- {
+ himax_proc_diag_file = proc_create(HIMAX_PROC_DIAG_FILE,
+ (S_IWUSR | S_IRUGO), himax_touch_proc_dir, &himax_proc_diag_ops);
+
+ if (himax_proc_diag_file == NULL) {
E(" %s: proc diag file create failed!\n", __func__);
goto fail_7;
}
- himax_proc_diag_arrange_file = proc_create(HIMAX_PROC_DIAG_ARR_FILE, (S_IWUSR|S_IRUGO), himax_touch_proc_dir, &himax_proc_diag_arrange_ops);
- if(himax_proc_diag_arrange_file == NULL)
- {
+ himax_proc_diag_arrange_file = proc_create(HIMAX_PROC_DIAG_ARR_FILE,
+ (S_IWUSR | S_IRUGO),
+ himax_touch_proc_dir, &himax_proc_diag_arrange_ops);
+
+ if (himax_proc_diag_arrange_file == NULL) {
E(" %s: proc diag file create failed!\n", __func__);
goto fail_7_1;
}
#endif
#ifdef HX_TP_PROC_REGISTER
- himax_proc_register_file = proc_create(HIMAX_PROC_REGISTER_FILE, (S_IWUSR|S_IRUGO), himax_touch_proc_dir, &himax_proc_register_ops);
- if(himax_proc_register_file == NULL)
- {
+ himax_proc_register_file = proc_create(HIMAX_PROC_REGISTER_FILE,
+ (S_IWUSR | S_IRUGO), himax_touch_proc_dir, &himax_proc_register_ops);
+
+ if (himax_proc_register_file == NULL) {
E(" %s: proc register file create failed!\n", __func__);
goto fail_8;
}
#endif
#ifdef HX_TP_PROC_DEBUG
- himax_proc_debug_file = proc_create(HIMAX_PROC_DEBUG_FILE, (S_IWUSR|S_IRUGO), himax_touch_proc_dir, &himax_proc_debug_ops);
- if(himax_proc_debug_file == NULL)
- {
+ himax_proc_debug_file = proc_create(HIMAX_PROC_DEBUG_FILE,
+ (S_IWUSR | S_IRUGO), himax_touch_proc_dir, &himax_proc_debug_ops);
+
+ if (himax_proc_debug_file == NULL) {
E(" %s: proc debug file create failed!\n", __func__);
goto fail_9;
}
#endif
#ifdef HX_TP_PROC_FLASH_DUMP
- himax_proc_flash_dump_file = proc_create(HIMAX_PROC_FLASH_DUMP_FILE, (S_IWUSR|S_IRUGO), himax_touch_proc_dir, &himax_proc_flash_ops);
- if(himax_proc_flash_dump_file == NULL)
- {
+ himax_proc_flash_dump_file = proc_create(HIMAX_PROC_FLASH_DUMP_FILE,
+ (S_IWUSR | S_IRUGO), himax_touch_proc_dir, &himax_proc_flash_ops);
+
+ if (himax_proc_flash_dump_file == NULL) {
E(" %s: proc flash dump file create failed!\n", __func__);
goto fail_10;
}
#endif
#ifdef HX_TP_PROC_SELF_TEST
- himax_proc_self_test_file = proc_create(HIMAX_PROC_SELF_TEST_FILE, (S_IRUGO), himax_touch_proc_dir, &himax_proc_self_test_ops);
- if(himax_proc_self_test_file == NULL)
- {
+ himax_proc_self_test_file = proc_create(HIMAX_PROC_SELF_TEST_FILE,
+ (S_IRUGO), himax_touch_proc_dir, &himax_proc_self_test_ops);
+
+ if (himax_proc_self_test_file == NULL) {
E(" %s: proc self_test file create failed!\n", __func__);
goto fail_11;
}
#endif
#ifdef HX_HIGH_SENSE
- himax_proc_HSEN_file = proc_create(HIMAX_PROC_HSEN_FILE, (S_IWUSR|S_IRUGO|S_IWUGO), himax_touch_proc_dir, &himax_proc_HSEN_ops);
- if(himax_proc_HSEN_file == NULL)
- {
+ himax_proc_HSEN_file = proc_create(HIMAX_PROC_HSEN_FILE,
+ (S_IWUSR | S_IRUGO | S_IWUGO),
+ himax_touch_proc_dir, &himax_proc_HSEN_ops);
+
+ if (himax_proc_HSEN_file == NULL) {
E(" %s: proc HSEN file create failed!\n", __func__);
goto fail_12;
}
#endif
#ifdef HX_SMART_WAKEUP
- himax_proc_SMWP_file = proc_create(HIMAX_PROC_SMWP_FILE, (S_IWUSR|S_IRUGO|S_IWUGO), himax_touch_proc_dir, &himax_proc_SMWP_ops);
- if(himax_proc_SMWP_file == NULL)
- {
+ himax_proc_SMWP_file = proc_create(HIMAX_PROC_SMWP_FILE,
+ (S_IWUSR | S_IRUGO | S_IWUGO),
+ himax_touch_proc_dir, &himax_proc_SMWP_ops);
+
+ if (himax_proc_SMWP_file == NULL) {
E(" %s: proc SMWP file create failed!\n", __func__);
goto fail_13;
}
- himax_proc_GESTURE_file = proc_create(HIMAX_PROC_GESTURE_FILE, (S_IWUSR|S_IRUGO|S_IWUGO), himax_touch_proc_dir, &himax_proc_Gesture_ops);
- if(himax_proc_GESTURE_file == NULL)
- {
+
+ himax_proc_GESTURE_file = proc_create(HIMAX_PROC_GESTURE_FILE,
+ (S_IWUSR | S_IRUGO | S_IWUGO),
+ himax_touch_proc_dir, &himax_proc_Gesture_ops);
+
+ if (himax_proc_GESTURE_file == NULL) {
E(" %s: proc GESTURE file create failed!\n", __func__);
goto fail_14;
}
#endif
#ifdef HX_TP_PROC_SENSE_ON_OFF
- himax_proc_SENSE_ON_OFF_file = proc_create(HIMAX_PROC_SENSE_ON_OFF_FILE, (S_IWUSR|S_IRUGO|S_IWUGO), himax_touch_proc_dir, &himax_proc_sense_on_off_ops);
- if(himax_proc_SENSE_ON_OFF_file == NULL)
- {
+ himax_proc_SENSE_ON_OFF_file = proc_create(HIMAX_PROC_SENSE_ON_OFF_FILE,
+ (S_IWUSR | S_IRUGO | S_IWUGO),
+ himax_touch_proc_dir, &himax_proc_sense_on_off_ops);
+
+ if (himax_proc_SENSE_ON_OFF_file == NULL) {
E(" %s: proc SENSE_ON_OFF file create failed!\n", __func__);
goto fail_15;
}
#endif
- return 0 ;
+ return 0;
#ifdef HX_TP_PROC_SENSE_ON_OFF
- fail_15:
+fail_15:
#endif
#ifdef HX_SMART_WAKEUP
- remove_proc_entry( HIMAX_PROC_GESTURE_FILE, himax_touch_proc_dir );
- fail_14:
- remove_proc_entry( HIMAX_PROC_SMWP_FILE, himax_touch_proc_dir );
- fail_13:
+ remove_proc_entry(HIMAX_PROC_GESTURE_FILE, himax_touch_proc_dir);
+fail_14:
+ remove_proc_entry(HIMAX_PROC_SMWP_FILE, himax_touch_proc_dir);
+fail_13:
#endif
#ifdef HX_HIGH_SENSE
- remove_proc_entry( HIMAX_PROC_HSEN_FILE, himax_touch_proc_dir );
- fail_12:
+ remove_proc_entry(HIMAX_PROC_HSEN_FILE, himax_touch_proc_dir);
+fail_12:
#endif
#ifdef HX_TP_PROC_SELF_TEST
- remove_proc_entry( HIMAX_PROC_SELF_TEST_FILE, himax_touch_proc_dir );
- fail_11:
+ remove_proc_entry(HIMAX_PROC_SELF_TEST_FILE, himax_touch_proc_dir);
+fail_11:
#endif
#ifdef HX_TP_PROC_FLASH_DUMP
- remove_proc_entry( HIMAX_PROC_FLASH_DUMP_FILE, himax_touch_proc_dir );
- fail_10:
+ remove_proc_entry(HIMAX_PROC_FLASH_DUMP_FILE, himax_touch_proc_dir);
+fail_10:
#endif
#ifdef HX_TP_PROC_DEBUG
- remove_proc_entry( HIMAX_PROC_DEBUG_FILE, himax_touch_proc_dir );
- fail_9:
+ remove_proc_entry(HIMAX_PROC_DEBUG_FILE, himax_touch_proc_dir);
+fail_9:
#endif
#ifdef HX_TP_PROC_REGISTER
- remove_proc_entry( HIMAX_PROC_REGISTER_FILE, himax_touch_proc_dir );
- fail_8:
+ remove_proc_entry(HIMAX_PROC_REGISTER_FILE, himax_touch_proc_dir);
+fail_8:
#endif
#ifdef HX_TP_PROC_DIAG
- remove_proc_entry( HIMAX_PROC_DIAG_FILE, himax_touch_proc_dir );
- fail_7:
- remove_proc_entry( HIMAX_PROC_DIAG_ARR_FILE, himax_touch_proc_dir );
- fail_7_1:
+ remove_proc_entry(HIMAX_PROC_DIAG_FILE, himax_touch_proc_dir);
+fail_7:
+ remove_proc_entry(HIMAX_PROC_DIAG_ARR_FILE, himax_touch_proc_dir);
+fail_7_1:
#endif
#ifdef HX_TP_PROC_RESET
- remove_proc_entry( HIMAX_PROC_RESET_FILE, himax_touch_proc_dir );
- fail_6:
+ remove_proc_entry(HIMAX_PROC_RESET_FILE, himax_touch_proc_dir);
+fail_6:
#endif
- remove_proc_entry( HIMAX_PROC_LAYOUT_FILE, himax_touch_proc_dir );
- fail_5: remove_proc_entry( HIMAX_PROC_INT_EN_FILE, himax_touch_proc_dir );
- fail_4: remove_proc_entry( HIMAX_PROC_ATTN_FILE, himax_touch_proc_dir );
- fail_3: remove_proc_entry( HIMAX_PROC_VENDOR_FILE, himax_touch_proc_dir );
- fail_2: remove_proc_entry( HIMAX_PROC_DEBUG_LEVEL_FILE, himax_touch_proc_dir );
- fail_1: remove_proc_entry( HIMAX_PROC_TOUCH_FOLDER, NULL );
+ remove_proc_entry(HIMAX_PROC_LAYOUT_FILE, himax_touch_proc_dir);
+fail_5: remove_proc_entry(HIMAX_PROC_INT_EN_FILE, himax_touch_proc_dir);
+fail_4: remove_proc_entry(HIMAX_PROC_ATTN_FILE, himax_touch_proc_dir);
+fail_3: remove_proc_entry(HIMAX_PROC_VENDOR_FILE, himax_touch_proc_dir);
+fail_2: remove_proc_entry(HIMAX_PROC_DEBUG_LEVEL_FILE, himax_touch_proc_dir);
+fail_1: remove_proc_entry(HIMAX_PROC_TOUCH_FOLDER, NULL);
return -ENOMEM;
}
void himax_touch_proc_deinit(void)
{
#ifdef HX_TP_PROC_SENSE_ON_OFF
- remove_proc_entry( HIMAX_PROC_SENSE_ON_OFF_FILE, himax_touch_proc_dir );
+ remove_proc_entry(HIMAX_PROC_SENSE_ON_OFF_FILE, himax_touch_proc_dir);
#endif
#ifdef HX_SMART_WAKEUP
- remove_proc_entry( HIMAX_PROC_GESTURE_FILE, himax_touch_proc_dir );
- remove_proc_entry( HIMAX_PROC_SMWP_FILE, himax_touch_proc_dir );
+ remove_proc_entry(HIMAX_PROC_GESTURE_FILE, himax_touch_proc_dir);
+ remove_proc_entry(HIMAX_PROC_SMWP_FILE, himax_touch_proc_dir);
#endif
#ifdef HX_DOT_VIEW
- remove_proc_entry( HIMAX_PROC_HSEN_FILE, himax_touch_proc_dir );
+ remove_proc_entry(HIMAX_PROC_HSEN_FILE, himax_touch_proc_dir);
#endif
#ifdef HX_TP_PROC_SELF_TEST
remove_proc_entry(HIMAX_PROC_SELF_TEST_FILE, himax_touch_proc_dir);
@@ -2308,7 +2184,7 @@
remove_proc_entry(HIMAX_PROC_FLASH_DUMP_FILE, himax_touch_proc_dir);
#endif
#ifdef HX_TP_PROC_DEBUG
- remove_proc_entry( HIMAX_PROC_DEBUG_FILE, himax_touch_proc_dir );
+ remove_proc_entry(HIMAX_PROC_DEBUG_FILE, himax_touch_proc_dir);
#endif
#ifdef HX_TP_PROC_REGISTER
remove_proc_entry(HIMAX_PROC_REGISTER_FILE, himax_touch_proc_dir);
@@ -2317,13 +2193,13 @@
remove_proc_entry(HIMAX_PROC_DIAG_FILE, himax_touch_proc_dir);
#endif
#ifdef HX_TP_PROC_RESET
- remove_proc_entry( HIMAX_PROC_RESET_FILE, himax_touch_proc_dir );
+ remove_proc_entry(HIMAX_PROC_RESET_FILE, himax_touch_proc_dir);
#endif
- remove_proc_entry( HIMAX_PROC_LAYOUT_FILE, himax_touch_proc_dir );
- remove_proc_entry( HIMAX_PROC_INT_EN_FILE, himax_touch_proc_dir );
- remove_proc_entry( HIMAX_PROC_ATTN_FILE, himax_touch_proc_dir );
- remove_proc_entry( HIMAX_PROC_VENDOR_FILE, himax_touch_proc_dir );
- remove_proc_entry( HIMAX_PROC_DEBUG_LEVEL_FILE, himax_touch_proc_dir );
- remove_proc_entry( HIMAX_PROC_TOUCH_FOLDER, NULL );
+ remove_proc_entry(HIMAX_PROC_LAYOUT_FILE, himax_touch_proc_dir);
+ remove_proc_entry(HIMAX_PROC_INT_EN_FILE, himax_touch_proc_dir);
+ remove_proc_entry(HIMAX_PROC_ATTN_FILE, himax_touch_proc_dir);
+ remove_proc_entry(HIMAX_PROC_VENDOR_FILE, himax_touch_proc_dir);
+ remove_proc_entry(HIMAX_PROC_DEBUG_LEVEL_FILE, himax_touch_proc_dir);
+ remove_proc_entry(HIMAX_PROC_TOUCH_FOLDER, NULL);
}
#endif
diff --git a/drivers/input/touchscreen/hxchipset/himax_debug.h b/drivers/input/touchscreen/hxchipset/himax_debug.h
index 91a7ae2..7a24a17 100644
--- a/drivers/input/touchscreen/hxchipset/himax_debug.h
+++ b/drivers/input/touchscreen/hxchipset/himax_debug.h
@@ -17,7 +17,7 @@
#include "himax_common.h"
#if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG)
- #define HIMAX_PROC_TOUCH_FOLDER "android_touch"
+ #define HIMAX_PROC_TOUCH_FOLDER "android_touch"
#define HIMAX_PROC_DEBUG_LEVEL_FILE "debug_level"
#define HIMAX_PROC_VENDOR_FILE "vendor"
#define HIMAX_PROC_ATTN_FILE "attn"
@@ -33,60 +33,76 @@
uint8_t HX_PROC_SEND_FLAG;
-extern int himax_touch_proc_init(void);
-extern void himax_touch_proc_deinit(void);
-bool getFlashDumpGoing(void);
+ extern int himax_touch_proc_init(void);
+ extern void himax_touch_proc_deinit(void);
+ bool getFlashDumpGoing(void);
+
+ extern struct himax_ic_data *ic_data;
+ extern struct himax_ts_data *private_ts;
+ extern unsigned char IC_TYPE;
+ extern unsigned char IC_CHECKSUM;
+
+#ifdef QCT
+ extern irqreturn_t himax_ts_thread(int irq, void *ptr);
+#endif
+#ifdef MTK
+#ifdef CONFIG_OF_TOUCH
+ extern irqreturn_t tpd_eint_interrupt_handler(int irq, void *desc);
+#else
+ extern void tpd_eint_interrupt_handler(void);
+#endif
+#endif
#ifdef HX_TP_PROC_REGISTER
#define HIMAX_PROC_REGISTER_FILE "register"
- struct proc_dir_entry *himax_proc_register_file;
+ struct proc_dir_entry *himax_proc_register_file = NULL;
uint8_t register_command[4];
#endif
#ifdef HX_TP_PROC_DIAG
#define HIMAX_PROC_DIAG_FILE "diag"
- struct proc_dir_entry *himax_proc_diag_file;
+ struct proc_dir_entry *himax_proc_diag_file = NULL;
#define HIMAX_PROC_DIAG_ARR_FILE "diag_arr"
- struct proc_dir_entry *himax_proc_diag_arrange_file;
+ struct proc_dir_entry *himax_proc_diag_arrange_file = NULL;
#ifdef HX_TP_PROC_2T2R
static bool Is_2T2R;
static uint8_t x_channel_2;
static uint8_t y_channel_2;
static uint8_t *diag_mutual_2;
-
- int16_t *getMutualBuffer_2(void);
- uint8_t getXChannel_2(void);
- uint8_t getYChannel_2(void);
-
- void setMutualBuffer_2(void);
- void setXChannel_2(uint8_t x);
- void setYChannel_2(uint8_t y);
-#endif
- uint8_t x_channel;
- uint8_t y_channel;
- int16_t *diag_mutual;
- int16_t *diag_mutual_new;
- int16_t *diag_mutual_old;
- uint8_t diag_max_cnt;
- int diag_command;
- uint8_t diag_coor[128];// = {0xFF};
+ int16_t *getMutualBuffer_2(void);
+ uint8_t getXChannel_2(void);
+ uint8_t getYChannel_2(void);
+
+ void setMutualBuffer_2(void);
+ void setXChannel_2(uint8_t x);
+ void setYChannel_2(uint8_t y);
+#endif
+ uint8_t x_channel = 0;
+ uint8_t y_channel = 0;
+ int16_t *diag_mutual = NULL;
+ int16_t *diag_mutual_new = NULL;
+ int16_t *diag_mutual_old = NULL;
+ uint8_t diag_max_cnt = 0;
+
+ int diag_command = 0;
+ uint8_t diag_coor[128];/* = {0xFF};*/
int16_t diag_self[100] = {0};
int16_t *getMutualBuffer(void);
int16_t *getMutualNewBuffer(void);
int16_t *getMutualOldBuffer(void);
int16_t *getSelfBuffer(void);
- uint8_t getDiagCommand(void);
- uint8_t getXChannel(void);
- uint8_t getYChannel(void);
-
- void setMutualBuffer(void);
- void setMutualNewBuffer(void);
- void setMutualOldBuffer(void);
- void setXChannel(uint8_t x);
- void setYChannel(uint8_t y);
+ uint8_t getDiagCommand(void);
+ uint8_t getXChannel(void);
+ uint8_t getYChannel(void);
+
+ void setMutualBuffer(void);
+ void setMutualNewBuffer(void);
+ void setMutualOldBuffer(void);
+ void setXChannel(uint8_t x);
+ void setYChannel(uint8_t y);
uint8_t coordinate_dump_enable = 0;
struct file *coordinate_fn;
#endif
@@ -106,24 +122,24 @@
struct proc_dir_entry *himax_proc_flash_dump_file = NULL;
static int Flash_Size = 131072;
- static uint8_t *flash_buffer = NULL;
- static uint8_t flash_command = 0;
- static uint8_t flash_read_step = 0;
- static uint8_t flash_progress = 0;
- static uint8_t flash_dump_complete = 0;
- static uint8_t flash_dump_fail = 0;
- static uint8_t sys_operation = 0;
- static uint8_t flash_dump_sector = 0;
- static uint8_t flash_dump_page = 0;
- static bool flash_dump_going = false;
+ static uint8_t *flash_buffer;
+ static uint8_t flash_command;
+ static uint8_t flash_read_step;
+ static uint8_t flash_progress;
+ static uint8_t flash_dump_complete;
+ static uint8_t flash_dump_fail;
+ static uint8_t sys_operation;
+ static uint8_t flash_dump_sector;
+ static uint8_t flash_dump_page;
+ static bool flash_dump_going;
static uint8_t getFlashCommand(void);
static uint8_t getFlashDumpComplete(void);
static uint8_t getFlashDumpFail(void);
static uint8_t getFlashDumpProgress(void);
static uint8_t getFlashReadStep(void);
- //static uint8_t getFlashDumpSector(void);
- //static uint8_t getFlashDumpPage(void);
+ /*static uint8_t getFlashDumpSector(void);*/
+ /*static uint8_t getFlashDumpPage(void);*/
void setFlashBuffer(void);
uint8_t getSysOperation(void);
@@ -150,8 +166,8 @@
#ifdef HX_TP_PROC_RESET
#define HIMAX_PROC_RESET_FILE "reset"
-extern void himax_HW_reset(uint8_t loadconfig,uint8_t int_off);
-struct proc_dir_entry *himax_proc_reset_file = NULL;
+extern void himax_HW_reset(uint8_t loadconfig, uint8_t int_off);
+struct proc_dir_entry *himax_proc_reset_file;
#endif
#ifdef HX_HIGH_SENSE
@@ -165,16 +181,16 @@
#endif
#ifdef HX_RST_PIN_FUNC
- void himax_HW_reset(uint8_t loadconfig,uint8_t int_off);
+ void himax_HW_reset(uint8_t loadconfig, uint8_t int_off);
#endif
#ifdef HX_SMART_WAKEUP
#define HIMAX_PROC_SMWP_FILE "SMWP"
-struct proc_dir_entry *himax_proc_SMWP_file = NULL;
+struct proc_dir_entry *himax_proc_SMWP_file;
#define HIMAX_PROC_GESTURE_FILE "GESTURE"
-struct proc_dir_entry *himax_proc_GESTURE_file = NULL;
-uint8_t HX_SMWP_EN = 0;
-//extern bool FAKE_POWER_KEY_SEND;
+struct proc_dir_entry *himax_proc_GESTURE_file;
+uint8_t HX_SMWP_EN;
+/*extern bool FAKE_POWER_KEY_SEND;*/
#endif
#endif
diff --git a/drivers/input/touchscreen/hxchipset/himax_ic.c b/drivers/input/touchscreen/hxchipset/himax_ic.c
index 6ad8dc0..e2934c2 100644
--- a/drivers/input/touchscreen/hxchipset/himax_ic.c
+++ b/drivers/input/touchscreen/hxchipset/himax_ic.c
@@ -15,45 +15,31 @@
#include "himax_ic.h"
-static unsigned char i_TP_CRC_FW_128K[]=
-{
- #include "HX_CRC_128.i"
-};
-static unsigned char i_TP_CRC_FW_64K[]=
-{
- #include "HX_CRC_64.i"
-};
-static unsigned char i_TP_CRC_FW_124K[]=
-{
- #include "HX_CRC_124.i"
-};
-static unsigned char i_TP_CRC_FW_60K[]=
-{
- #include "HX_CRC_60.i"
-};
+const struct firmware *i_TP_CRC_FW_128K;
+const struct firmware *i_TP_CRC_FW_64K;
+const struct firmware *i_TP_CRC_FW_124K;
+const struct firmware *i_TP_CRC_FW_60K;
+unsigned long FW_VER_MAJ_FLASH_ADDR;
+unsigned long FW_VER_MAJ_FLASH_LENG;
+unsigned long FW_VER_MIN_FLASH_ADDR;
+unsigned long FW_VER_MIN_FLASH_LENG;
+unsigned long CFG_VER_MAJ_FLASH_ADDR;
+unsigned long CFG_VER_MAJ_FLASH_LENG;
+unsigned long CFG_VER_MIN_FLASH_ADDR;
+unsigned long CFG_VER_MIN_FLASH_LENG;
-unsigned long FW_VER_MAJ_FLASH_ADDR;
-unsigned long FW_VER_MAJ_FLASH_LENG;
-unsigned long FW_VER_MIN_FLASH_ADDR;
-unsigned long FW_VER_MIN_FLASH_LENG;
-unsigned long CFG_VER_MAJ_FLASH_ADDR;
-unsigned long CFG_VER_MAJ_FLASH_LENG;
-unsigned long CFG_VER_MIN_FLASH_ADDR;
-unsigned long CFG_VER_MIN_FLASH_LENG;
+unsigned char IC_TYPE;
+unsigned char IC_CHECKSUM;
-unsigned char IC_TYPE = 0;
-unsigned char IC_CHECKSUM = 0;
-
-extern struct himax_ic_data* ic_data;
-
-int himax_hand_shaking(struct i2c_client *client) //0:Running, 1:Stop, 2:I2C Fail
+ /*0:Running, 1:Stop, 2:I2C Fail*/
+int himax_hand_shaking(struct i2c_client *client)
{
int ret, result;
uint8_t hw_reset_check[1];
uint8_t hw_reset_check_2[1];
uint8_t buf0[2];
- uint8_t IC_STATUS_CHECK = 0xAA;
+ uint8_t IC_STATUS_CHECK = 0xAA;
memset(hw_reset_check, 0x00, sizeof(hw_reset_check));
memset(hw_reset_check_2, 0x00, sizeof(hw_reset_check_2));
@@ -67,45 +53,50 @@
IC_STATUS_CHECK = 0xAA;
}
- ret = i2c_himax_master_write(client, buf0, 2, HIMAX_I2C_RETRY_TIMES);
+ ret = i2c_himax_master_write(client,
+ buf0, 2, HIMAX_I2C_RETRY_TIMES);
if (ret < 0) {
- E("[Himax]:write 0xF2 failed line: %d \n",__LINE__);
+ E("[Himax]:write 0xF2 failed line: %d\n", __LINE__);
goto work_func_send_i2c_msg_fail;
}
- msleep(50);
-
+ msleep(50);
+
buf0[0] = 0xF2;
buf0[1] = 0x00;
- ret = i2c_himax_master_write(client, buf0, 2, HIMAX_I2C_RETRY_TIMES);
+ ret = i2c_himax_master_write(client,
+ buf0, 2, HIMAX_I2C_RETRY_TIMES);
if (ret < 0) {
- E("[Himax]:write 0x92 failed line: %d \n",__LINE__);
+ E("[Himax]:write 0x92 failed line: %d\n", __LINE__);
goto work_func_send_i2c_msg_fail;
}
- usleep_range(2000, 4000);
-
- ret = i2c_himax_read(client, 0xD1, hw_reset_check, 1, HIMAX_I2C_RETRY_TIMES);
+ usleep_range(1999, 2000);
+
+ ret = i2c_himax_read(client, 0xD1,
+ hw_reset_check, 1, HIMAX_I2C_RETRY_TIMES);
if (ret < 0) {
- E("[Himax]:i2c_himax_read 0xD1 failed line: %d \n",__LINE__);
+ E("[Himax]:i2c_himax_read 0xD1 failed line: %d\n", __LINE__);
goto work_func_send_i2c_msg_fail;
}
-
- if ((IC_STATUS_CHECK != hw_reset_check[0])) {
- usleep_range(2000, 4000);
- ret = i2c_himax_read(client, 0xD1, hw_reset_check_2, 1, HIMAX_I2C_RETRY_TIMES);
+
+ if (IC_STATUS_CHECK != hw_reset_check[0]) {
+ usleep_range(1999, 2000);
+ ret = i2c_himax_read(client, 0xD1,
+ hw_reset_check_2, 1, HIMAX_I2C_RETRY_TIMES);
if (ret < 0) {
- E("[Himax]:i2c_himax_read 0xD1 failed line: %d \n",__LINE__);
+ E("[Himax]:i2c_himax_read 0xD1 failed line: %d\n",
+ __LINE__);
goto work_func_send_i2c_msg_fail;
}
-
- if (hw_reset_check[0] == hw_reset_check_2[0]) {
- result = 1;
- } else {
- result = 0;
- }
+
+ if (hw_reset_check[0] == hw_reset_check_2[0])
+ result = 1;
+ else
+ result = 0;
+
} else {
- result = 0;
+ result = 0;
}
-
+
return result;
work_func_send_i2c_msg_fail:
@@ -117,66 +108,71 @@
uint8_t tmp_addr[4];
uint8_t tmp_data[4];
- if(diag_command != 0)
+ if (diag_command != 0)
diag_command = diag_command + 5;
- tmp_addr[3] = 0x80; tmp_addr[2] = 0x02; tmp_addr[1] = 0x01; tmp_addr[0] = 0x80;
- tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = diag_command;
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x02;
+ tmp_addr[1] = 0x01; tmp_addr[0] = 0x80;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = diag_command;
himax_flash_write_burst(client, tmp_addr, tmp_data);
}
-void himax_flash_dump_func(struct i2c_client *client, uint8_t local_flash_command, int Flash_Size, uint8_t *flash_buffer)
+void himax_flash_dump_func(struct i2c_client *client,
+uint8_t local_flash_command, int Flash_Size, uint8_t *flash_buffer)
{
- //struct himax_ts_data *ts = container_of(work, struct himax_ts_data, flash_work);
-
-// uint8_t sector = 0;
-// uint8_t page = 0;
+ /*struct himax_ts_data *ts =
+ container_of(work, struct himax_ts_data, flash_work);*/
+ /*uint8_t sector = 0;*/
+ /*uint8_t page = 0;*/
uint8_t tmp_addr[4];
uint8_t tmp_data[4];
uint8_t out_buffer[20];
- uint8_t in_buffer[260] = {0};
+ uint8_t in_buffer[260];
int page_prog_start = 0;
int i = 0;
himax_sense_off(client);
himax_burst_enable(client, 0);
/*=============Dump Flash Start=============*/
- //=====================================
- // SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
- //=====================================
- tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
- tmp_data[3] = 0x00; tmp_data[2] = 0x02; tmp_data[1] = 0x07; tmp_data[0] = 0x80;
+ /*=====================================*/
+ /* SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780*/
+ /*=====================================*/
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x02;
+ tmp_data[1] = 0x07; tmp_data[0] = 0x80;
himax_flash_write_burst(client, tmp_addr, tmp_data);
- for (page_prog_start = 0; page_prog_start < Flash_Size; page_prog_start = page_prog_start + 256)
- {
- //=================================
- // SPI Transfer Control
- // Set 256 bytes page read : 0x8000_0020 ==> 0x6940_02FF
- // Set read start address : 0x8000_0028 ==> 0x0000_0000
- // Set command : 0x8000_0024 ==> 0x0000_003B
- //=================================
- tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
- tmp_data[3] = 0x69; tmp_data[2] = 0x40; tmp_data[1] = 0x02; tmp_data[0] = 0xFF;
+ for (page_prog_start = 0 ; page_prog_start < Flash_Size;
+ page_prog_start = page_prog_start + 256) {
+ /*=====================================
+ SPI Transfer Control
+ Set 256 bytes page read : 0x8000_0020 ==> 0x6940_02FF
+ Set read start address : 0x8000_0028 ==> 0x0000_0000
+ Set command : 0x8000_0024 ==> 0x0000_003B
+ =====================================*/
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+ tmp_data[3] = 0x69; tmp_data[2] = 0x40;
+ tmp_data[1] = 0x02; tmp_data[0] = 0xFF;
himax_flash_write_burst(client, tmp_addr, tmp_data);
- tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x28;
- if (page_prog_start < 0x100)
- {
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x28;
+ if (page_prog_start < 0x100) {
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = (uint8_t)page_prog_start;
- }
- else if (page_prog_start >= 0x100 && page_prog_start < 0x10000)
- {
+ } else if (page_prog_start >= 0x100
+ && page_prog_start < 0x10000) {
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = (uint8_t)(page_prog_start >> 8);
tmp_data[0] = (uint8_t)page_prog_start;
- }
- else if (page_prog_start >= 0x10000 && page_prog_start < 0x1000000)
- {
+ } else if (page_prog_start >= 0x10000
+ && page_prog_start < 0x1000000) {
tmp_data[3] = 0x00;
tmp_data[2] = (uint8_t)(page_prog_start >> 16);
tmp_data[1] = (uint8_t)(page_prog_start >> 8);
@@ -184,43 +180,46 @@
}
himax_flash_write_burst(client, tmp_addr, tmp_data);
- tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
- tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x3B;
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = 0x3B;
himax_flash_write_burst(client, tmp_addr, tmp_data);
- //==================================
- // AHB_I2C Burst Read
- // Set SPI data register : 0x8000_002C ==> 0x00
- //==================================
+ /*=====================================
+ AHB_I2C Burst Read
+ Set SPI data register : 0x8000_002C ==> 0x00
+ =====================================*/
out_buffer[0] = 0x2C;
out_buffer[1] = 0x00;
out_buffer[2] = 0x00;
out_buffer[3] = 0x80;
- i2c_himax_write(client, 0x00 ,out_buffer, 4, 3);
+ i2c_himax_write(client, 0x00, out_buffer, 4, 3);
- //==================================
- // Read access : 0x0C ==> 0x00
- //==================================
+ /*=====================================
+ Read access : 0x0C ==> 0x00
+ =====================================*/
out_buffer[0] = 0x00;
- i2c_himax_write(client, 0x0C ,out_buffer, 1, 3);
+ i2c_himax_write(client, 0x0C, out_buffer, 1, 3);
- //==================================
- // Read 128 bytes two times
- //==================================
- i2c_himax_read(client, 0x08 ,in_buffer, 128, 3);
- for (i = 0; i < 128; i++)
- flash_buffer[i + page_prog_start] = in_buffer[i];
+ /*=====================================
+ Read 128 bytes two times
+ =====================================*/
+ i2c_himax_read(client, 0x08, in_buffer, 128, 3);
+ for (i = 0 ; i < 128 ; i++)
+ flash_buffer[i + page_prog_start]
+ = in_buffer[i];
- i2c_himax_read(client, 0x08 ,in_buffer, 128, 3);
- for (i = 0; i < 128; i++)
- flash_buffer[(i + 128) + page_prog_start] = in_buffer[i];
+ i2c_himax_read(client, 0x08 , in_buffer, 128, 3);
+ for (i = 0 ; i < 128 ; i++)
+ flash_buffer[(i + 128) + page_prog_start]
+ = in_buffer[i];
I("%s:Verify Progress: %x\n", __func__, page_prog_start);
}
/*=============Dump Flash End=============*/
- //msleep(100);
- /*
+ /*//msleep(100);
for( i=0 ; i<8 ;i++)
{
for(j=0 ; j<64 ; j++)
@@ -239,7 +238,7 @@
{
uint8_t tmp_addr[4];
uint8_t tmp_data[128];
- int pf_value=0x00;
+ int pf_value = 0x00;
uint8_t test_result_id = 0;
int j;
@@ -249,19 +248,24 @@
himax_interface_on(client);
himax_sense_off(client);
- //Set criteria
+ /*Set criteria*/
himax_burst_enable(client, 1);
- tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x94;
- tmp_data[3] = 0x14; tmp_data[2] = 0xC8; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
- tmp_data[7] = 0x13; tmp_data[6] = 0x60; tmp_data[5] = 0x0A; tmp_data[4] = 0x99;
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x08;
+ tmp_addr[1] = 0x80; tmp_addr[0] = 0x94;
+ tmp_data[3] = 0x14; tmp_data[2] = 0xC8;
+ tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ tmp_data[7] = 0x13; tmp_data[6] = 0x60;
+ tmp_data[5] = 0x0A; tmp_data[4] = 0x99;
- himax_flash_write_burst_lenth(client, tmp_addr, tmp_data, 8);
+ himax_flash_write_burst_length(client, tmp_addr, tmp_data, 8);
- //start selftest
- // 0x9008_805C ==> 0x0000_0001
- tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x5C;
- tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x01;
+ /*start selftest*/
+ /* 0x9008_805C ==> 0x0000_0001*/
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x08;
+ tmp_addr[1] = 0x80; tmp_addr[0] = 0x5C;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = 0x01;
himax_flash_write_burst(client, tmp_addr, tmp_data);
himax_sense_on(client, 1);
@@ -271,19 +275,21 @@
himax_sense_off(client);
msleep(20);
- //=====================================
- // Read test result ID : 0x9008_8078 ==> 0xA/0xB/0xC/0xF
- //=====================================
- tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
- tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x78;
+ /*=====================================
+ Read test result ID : 0x9008_8078 ==> 0xA/0xB/0xC/0xF
+ =====================================*/
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x08;
+ tmp_addr[1] = 0x80; tmp_addr[0] = 0x78;
himax_register_read(client, tmp_addr, 1, tmp_data);
test_result_id = tmp_data[0];
- I("%s: check test result, test_result_id=%x, test_result=%x\n", __func__
- ,test_result_id,tmp_data[0]);
+ I("%s: check test result, test_result_id=%x, test_result=%x\n",
+ __func__ , test_result_id, tmp_data[0]);
- if (test_result_id==0xF) {
+ if (test_result_id == 0xF) {
I("[Himax]: self-test pass\n");
pf_value = 0x1;
} else {
@@ -292,22 +298,28 @@
}
himax_burst_enable(client, 1);
- for (j = 0;j < 10; j++){
- tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
- tmp_addr[3] = 0x90; tmp_addr[2] = 0x06; tmp_addr[1] = 0x00; tmp_addr[0] = 0x0C;
+ for (j = 0 ; j < 10 ; j++) {
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x06;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x0C;
himax_register_read(client, tmp_addr, 1, tmp_data);
I("[Himax]: 9006000C = %d\n", tmp_data[0]);
- if (tmp_data[0] != 0){
- tmp_data[3] = 0x90; tmp_data[2] = 0x06; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
- if ( i2c_himax_write(client, 0x00 ,tmp_data, 4, HIMAX_I2C_RETRY_TIMES) < 0) {
- E("%s: i2c access fail!\n", __func__);
- }
- tmp_data[0] = 0x00;
- if ( i2c_himax_write(client, 0x0C ,tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
- E("%s: i2c access fail!\n", __func__);
- }
- i2c_himax_read(client, 0x08, tmp_data, 124,HIMAX_I2C_RETRY_TIMES);
- }else{
+ if (tmp_data[0] != 0) {
+ tmp_data[3] = 0x90; tmp_data[2] = 0x06;
+ tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ if (i2c_himax_write(client, 0x00,
+ tmp_data, 4, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ }
+ tmp_data[0] = 0x00;
+ if (i2c_himax_write(client, 0x0C,
+ tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ }
+ i2c_himax_read(client, 0x08,
+ tmp_data, 124, HIMAX_I2C_RETRY_TIMES);
+ } else {
break;
}
}
@@ -324,15 +336,18 @@
uint8_t tmp_data[4];
himax_burst_enable(client, 0);
- tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x50;
- tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = HSEN_enable;
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x08;
+ tmp_addr[1] = 0x80; tmp_addr[0] = 0x50;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = HSEN_enable;
himax_flash_write_burst(client, tmp_addr, tmp_data);
}
-void himax_get_HSEN_enable(struct i2c_client *client,uint8_t *tmp_data)
+void himax_get_HSEN_enable(struct i2c_client *client, uint8_t *tmp_data)
{
uint8_t tmp_addr[4];
- tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x50;
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x08;
+ tmp_addr[1] = 0x80; tmp_addr[0] = 0x50;
himax_register_read(client, tmp_addr, 1, tmp_data);
}
@@ -341,206 +356,232 @@
uint8_t tmp_addr[4];
uint8_t tmp_data[4];
- tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x54;
- tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = SMWP_enable;
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x08;
+ tmp_addr[1] = 0x80; tmp_addr[0] = 0x54;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = SMWP_enable;
himax_flash_write_burst(client, tmp_addr, tmp_data);
}
-void himax_get_SMWP_enable(struct i2c_client *client,uint8_t *tmp_data)
+void himax_get_SMWP_enable(struct i2c_client *client,
+uint8_t *tmp_data)
{
uint8_t tmp_addr[4];
- tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x54;
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x08;
+ tmp_addr[1] = 0x80; tmp_addr[0] = 0x54;
himax_register_read(client, tmp_addr, 1, tmp_data);
}
int himax_burst_enable(struct i2c_client *client, uint8_t auto_add_4_byte)
{
uint8_t tmp_data[4];
+ int err = -1;
tmp_data[0] = 0x31;
- if ( i2c_himax_write(client, 0x13 ,tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+
+ if (i2c_himax_write(client, 0x13,
+ tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
- return -EBUSY;
+ return err;
}
-
+
tmp_data[0] = (0x10 | auto_add_4_byte);
- if ( i2c_himax_write(client, 0x0D ,tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ if (i2c_himax_write(client, 0x0D,
+ tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
- return -EBUSY;
+ return err;
}
return 0;
}
-void himax_register_read(struct i2c_client *client, uint8_t *read_addr, int read_length, uint8_t *read_data)
+void himax_register_read(struct i2c_client *client,
+uint8_t *read_addr, int read_length, uint8_t *read_data)
{
uint8_t tmp_data[4];
int i = 0;
int address = 0;
- if(read_length>256)
- {
+ if (read_length > 256) {
E("%s: read len over 256!\n", __func__);
return;
}
if (read_length > 1)
himax_burst_enable(client, 1);
else
- himax_burst_enable(client, 0);
- address = (read_addr[3] << 24) + (read_addr[2] << 16) + (read_addr[1] << 8) + read_addr[0];
+ himax_burst_enable(client, 0);
+
+ address = (read_addr[3] << 24) +
+ (read_addr[2] << 16) +
+ (read_addr[1] << 8) +
+ read_addr[0];
+
i = address;
- tmp_data[0] = (uint8_t)i;
- tmp_data[1] = (uint8_t)(i >> 8);
- tmp_data[2] = (uint8_t)(i >> 16);
- tmp_data[3] = (uint8_t)(i >> 24);
- if ( i2c_himax_write(client, 0x00 ,tmp_data, 4, HIMAX_I2C_RETRY_TIMES) < 0) {
- E("%s: i2c access fail!\n", __func__);
- return;
- }
- tmp_data[0] = 0x00;
- if ( i2c_himax_write(client, 0x0C ,tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
- E("%s: i2c access fail!\n", __func__);
- return;
- }
-
- if ( i2c_himax_read(client, 0x08 ,read_data, read_length * 4, HIMAX_I2C_RETRY_TIMES) < 0) {
- E("%s: i2c access fail!\n", __func__);
- return;
- }
+ tmp_data[0] = (uint8_t)i;
+ tmp_data[1] = (uint8_t)(i >> 8);
+ tmp_data[2] = (uint8_t)(i >> 16);
+ tmp_data[3] = (uint8_t)(i >> 24);
+ if (i2c_himax_write(client, 0x00,
+ tmp_data, 4, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
+ }
+ tmp_data[0] = 0x00;
+ if (i2c_himax_write(client, 0x0C,
+ tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
+ }
+ if (i2c_himax_read(client, 0x08,
+ read_data, read_length * 4, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
+ }
if (read_length > 1)
himax_burst_enable(client, 0);
}
-void himax_flash_read(struct i2c_client *client, uint8_t *reg_byte, uint8_t *read_data)
+void himax_flash_read(struct i2c_client *client,
+uint8_t *reg_byte, uint8_t *read_data)
{
- uint8_t tmpbyte[2];
-
- if ( i2c_himax_write(client, 0x00 ,®_byte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ uint8_t tmpbyte[2];
+
+ if (i2c_himax_write(client, 0x00,
+ ®_byte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
- if ( i2c_himax_write(client, 0x01 ,®_byte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ if (i2c_himax_write(client, 0x01,
+ ®_byte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
- if ( i2c_himax_write(client, 0x02 ,®_byte[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ if (i2c_himax_write(client, 0x02,
+ ®_byte[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
- if ( i2c_himax_write(client, 0x03 ,®_byte[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ if (i2c_himax_write(client, 0x03,
+ ®_byte[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
- tmpbyte[0] = 0x00;
- if ( i2c_himax_write(client, 0x0C ,&tmpbyte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ tmpbyte[0] = 0x00;
+ if (i2c_himax_write(client, 0x0C,
+ &tmpbyte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
- if ( i2c_himax_read(client, 0x08 ,&read_data[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ if (i2c_himax_read(client, 0x08,
+ &read_data[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
- if ( i2c_himax_read(client, 0x09 ,&read_data[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ if (i2c_himax_read(client, 0x09,
+ &read_data[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
- if ( i2c_himax_read(client, 0x0A ,&read_data[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ if (i2c_himax_read(client, 0x0A,
+ &read_data[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
- if ( i2c_himax_read(client, 0x0B ,&read_data[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ if (i2c_himax_read(client, 0x0B,
+ &read_data[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
- if ( i2c_himax_read(client, 0x18 ,&tmpbyte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ if (i2c_himax_read(client, 0x18,
+ &tmpbyte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
- }// No bus request
+ } /* No bus request*/
- if ( i2c_himax_read(client, 0x0F ,&tmpbyte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ if (i2c_himax_read(client, 0x0F,
+ &tmpbyte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
- }// idle state
+ } /* idle state*/
}
-void himax_flash_write_burst(struct i2c_client *client, uint8_t * reg_byte, uint8_t * write_data)
+void himax_flash_write_burst(struct i2c_client *client,
+uint8_t *reg_byte, uint8_t *write_data)
{
- uint8_t data_byte[8];
+ uint8_t data_byte[8];
int i = 0, j = 0;
- for (i = 0; i < 4; i++)
- {
- data_byte[i] = reg_byte[i];
- }
- for (j = 4; j < 8; j++)
- {
- data_byte[j] = write_data[j-4];
- }
-
- if ( i2c_himax_write(client, 0x00 ,data_byte, 8, HIMAX_I2C_RETRY_TIMES) < 0) {
- E("%s: i2c access fail!\n", __func__);
- return;
- }
+ for (i = 0 ; i < 4; i++)
+ data_byte[i] = reg_byte[i];
-}
+ for (j = 4 ; j < 8; j++)
+ data_byte[j] = write_data[j-4];
-int himax_flash_write_burst_lenth(struct i2c_client *client, uint8_t *reg_byte, uint8_t *write_data, int length)
-{
- uint8_t data_byte[256];
- int i = 0, j = 0;
-
- for (i = 0; i < 4; i++)
- {
- data_byte[i] = reg_byte[i];
- }
- for (j = 4; j < length + 4; j++)
- {
- data_byte[j] = write_data[j - 4];
- }
-
- if ( i2c_himax_write(client, 0x00 ,data_byte, length + 4, HIMAX_I2C_RETRY_TIMES) < 0) {
- E("%s: i2c access fail!\n", __func__);
- return -EBUSY;
+ if (i2c_himax_write(client, 0x00,
+ data_byte, 8, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
}
- return 0;
}
-int himax_register_write(struct i2c_client *client, uint8_t *write_addr, int write_length, uint8_t *write_data)
+int himax_flash_write_burst_length(struct i2c_client *client,
+uint8_t *reg_byte, uint8_t *write_data, int length)
{
- int i =0, address = 0;
- int ret = 0;
+ uint8_t data_byte[256];
+ int i = 0, j = 0, err = -1;
- address = (write_addr[3] << 24) + (write_addr[2] << 16) + (write_addr[1] << 8) + write_addr[0];
+ for (i = 0 ; i < 4 ; i++)
+ data_byte[i] = reg_byte[i];
- for (i = address; i < address + write_length * 4; i = i + 4)
- {
- if (write_length > 1)
- {
+ for (j = 4 ; j < length + 4 ; j++)
+ data_byte[j] = write_data[j - 4];
+
+ if (i2c_himax_write(client, 0x00,
+ data_byte, length + 4, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return err;
+ }
+ return 0;
+}
+
+int himax_register_write(struct i2c_client *client,
+uint8_t *write_addr, int write_length, uint8_t *write_data)
+{
+ int i = 0, address = 0;
+ int ret = 0, err = -1;
+
+ address = (write_addr[3] << 24) +
+ (write_addr[2] << 16) +
+ (write_addr[1] << 8) +
+ write_addr[0];
+
+ for (i = address ; i < address + write_length * 4;
+ i = i + 4) {
+ if (write_length > 1) {
ret = himax_burst_enable(client, 1);
- if(ret)
- return ret;
- }
- else
- {
+ if (ret)
+ return err;
+ } else {
ret = himax_burst_enable(client, 0);
- if(ret)
- return ret;
+ if (ret)
+ return err;
}
- ret = himax_flash_write_burst_lenth(client, write_addr, write_data, write_length * 4);
- if(ret < 0)
- return ret;
+ ret = himax_flash_write_burst_length(client,
+ write_addr, write_data, write_length * 4);
+ if (ret < 0)
+ return err;
}
return 0;
@@ -550,50 +591,62 @@
{
uint8_t wdt_off = 0x00;
uint8_t tmp_addr[4];
- uint8_t tmp_data[5];
+ uint8_t tmp_data[5];
himax_burst_enable(client, 0);
- while(wdt_off == 0x00)
- {
- // 0x9000_800C ==> 0x0000_AC53
- tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x80; tmp_addr[0] = 0x0C;
- tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0xAC; tmp_data[0] = 0x53;
+ while (wdt_off == 0x00) {
+ /* 0x9000_800C ==> 0x0000_AC53*/
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x80; tmp_addr[0] = 0x0C;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+ tmp_data[1] = 0xAC; tmp_data[0] = 0x53;
himax_flash_write_burst(client, tmp_addr, tmp_data);
- //=====================================
- // Read Watch Dog disable password : 0x9000_800C ==> 0x0000_AC53
- //=====================================
- tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x80; tmp_addr[0] = 0x0C;
+ /*=====================================*/
+ /* Read Watch Dog disable password :
+ 0x9000_800C ==> 0x0000_AC53 */
+ /*=====================================*/
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x80; tmp_addr[0] = 0x0C;
himax_register_read(client, tmp_addr, 1, tmp_data);
-
- //Check WDT
- if (tmp_data[0] == 0x53 && tmp_data[1] == 0xAC && tmp_data[2] == 0x00 && tmp_data[3] == 0x00)
+
+ /*Check WDT*/
+ if (tmp_data[0] == 0x53 && tmp_data[1] == 0xAC
+ && tmp_data[2] == 0x00 && tmp_data[3] == 0x00)
wdt_off = 0x01;
else
wdt_off = 0x00;
}
- // VCOM //0x9008_806C ==> 0x0000_0001
- tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x6C;
- tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x01;
+ /* VCOM //0x9008_806C ==> 0x0000_0001*/
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x08;
+ tmp_addr[1] = 0x80; tmp_addr[0] = 0x6C;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = 0x01;
himax_flash_write_burst(client, tmp_addr, tmp_data);
msleep(20);
- // 0x9000_0010 ==> 0x0000_00DA
- tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
- tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0xDA;
+ /* 0x9000_0010 ==> 0x0000_00DA*/
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = 0xDA;
himax_flash_write_burst(client, tmp_addr, tmp_data);
- //=====================================
- // Read CPU clock off password : 0x9000_0010 ==> 0x0000_00DA
- //=====================================
- tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
- tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
+ /*=====================================
+ Read CPU clock off password : 0x9000_0010 ==> 0x0000_00DA
+ =====================================*/
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
himax_register_read(client, tmp_addr, 1, tmp_data);
- I("%s: CPU clock off password data[0]=%x data[1]=%x data[2]=%x data[3]=%x\n", __func__
- ,tmp_data[0],tmp_data[1],tmp_data[2],tmp_data[3]);
+ I("%s: CPU clock off password data[0]=%x",
+ __func__, tmp_data[0]);
+ I(" data[1]=%x data[2]=%x data[3]=%x\n",
+ tmp_data[1], tmp_data[2], tmp_data[3]);
}
@@ -602,11 +655,12 @@
uint8_t tmp_addr[4];
uint8_t tmp_data[5];
- //===========================================
- // Any Cmd for ineterface on : 0x9000_0000 ==> 0x0000_0000
- //===========================================
- tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x00;
- himax_flash_read(client, tmp_addr, tmp_data); //avoid RD/WR fail
+ /*=====================================
+ Any Cmd for ineterface on : 0x9000_0000 ==> 0x0000_0000
+ =====================================*/
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x00;
+ himax_flash_read(client, tmp_addr, tmp_data); /*avoid RD/WR fail*/
}
bool wait_wip(struct i2c_client *client, int Timing)
@@ -614,55 +668,64 @@
uint8_t tmp_addr[4];
uint8_t tmp_data[4];
uint8_t in_buffer[10];
- //uint8_t out_buffer[20];
+ /*uint8_t out_buffer[20];*/
int retry_cnt = 0;
- //=====================================
- // SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
- //=====================================
- tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
- tmp_data[3] = 0x00; tmp_data[2] = 0x02; tmp_data[1] = 0x07; tmp_data[0] = 0x80;
+ /*=====================================
+ SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
+ =====================================*/
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x02;
+ tmp_data[1] = 0x07; tmp_data[0] = 0x80;
himax_flash_write_burst(client, tmp_addr, tmp_data);
in_buffer[0] = 0x01;
- do
- {
- //=====================================
- // SPI Transfer Control : 0x8000_0020 ==> 0x4200_0003
- //=====================================
- tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
- tmp_data[3] = 0x42; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x03;
+ do {
+ /*=====================================
+ SPI Transfer Control : 0x8000_0020 ==> 0x4200_0003
+ =====================================*/
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+ tmp_data[3] = 0x42; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = 0x03;
himax_flash_write_burst(client, tmp_addr, tmp_data);
- //=====================================
- // SPI Command : 0x8000_0024 ==> 0x0000_0005
- // read 0x8000_002C for 0x01, means wait success
- //=====================================
- tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
- tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x05;
+ /*=====================================
+ SPI Command : 0x8000_0024 ==> 0x0000_0005
+ read 0x8000_002C for 0x01, means wait success
+ =====================================*/
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = 0x05;
himax_flash_write_burst(client, tmp_addr, tmp_data);
- in_buffer[0] = in_buffer[1] = in_buffer[2] = in_buffer[3] = 0xFF;
- tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x2C;
+ in_buffer[0] = in_buffer[1] =
+ in_buffer[2] = in_buffer[3] = 0xFF;
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x2C;
himax_register_read(client, tmp_addr, 1, in_buffer);
-
+
if ((in_buffer[0] & 0x01) == 0x00)
return true;
retry_cnt++;
-
- if (in_buffer[0] != 0x00 || in_buffer[1] != 0x00 || in_buffer[2] != 0x00 || in_buffer[3] != 0x00)
- I("%s:Wait wip retry_cnt:%d, buffer[0]=%d, buffer[1]=%d, buffer[2]=%d, buffer[3]=%d \n", __func__,
- retry_cnt,in_buffer[0],in_buffer[1],in_buffer[2],in_buffer[3]);
- if (retry_cnt > 100)
- {
+ if (in_buffer[0] != 0x00 || in_buffer[1] != 0x00
+ || in_buffer[2] != 0x00 || in_buffer[3] != 0x00){
+ I("%s:Wait wip retry_cnt:%d, buffer[0]=%d, ",
+ __func__, retry_cnt, in_buffer[0]);
+ I("buffer[1]=%d, buffer[2]=%d, buffer[3]=%d\n",
+ in_buffer[1], in_buffer[2], in_buffer[3]);
+ }
+ if (retry_cnt > 100) {
E("%s: Wait wip error!\n", __func__);
- return false;
- }
+ return false;
+ }
msleep(Timing);
- }while ((in_buffer[0] & 0x01) == 0x01);
+ } while ((in_buffer[0] & 0x01) == 0x01);
return true;
}
@@ -673,74 +736,93 @@
himax_interface_on(client);
himax_burst_enable(client, 0);
- //CPU reset
- // 0x9000_0014 ==> 0x0000_00CA
- tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x14;
- tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0xCA;
+ /*CPU reset*/
+ /* 0x9000_0014 ==> 0x0000_00CA*/
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x14;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = 0xCA;
himax_flash_write_burst(client, tmp_addr, tmp_data);
- //=====================================
- // Read pull low CPU reset signal : 0x9000_0014 ==> 0x0000_00CA
- //=====================================
- tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
- tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x14;
+ /*=====================================
+ Read pull low CPU reset signal : 0x9000_0014 ==> 0x0000_00CA
+ =====================================*/
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x14;
himax_register_read(client, tmp_addr, 1, tmp_data);
- I("%s: check pull low CPU reset signal data[0]=%x data[1]=%x data[2]=%x data[3]=%x\n", __func__
- ,tmp_data[0],tmp_data[1],tmp_data[2],tmp_data[3]);
+ I("%s: check pull low CPU reset signal data[0]=%x data[1]=%x ",
+ __func__, tmp_data[0], tmp_data[1]);
+ I("data[2]=%x data[3]=%x\n",
+ tmp_data[2], tmp_data[3]);
- // 0x9000_0014 ==> 0x0000_0000
- tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x14;
- tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ /* 0x9000_0014 ==> 0x0000_0000*/
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x14;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = 0x00;
himax_flash_write_burst(client, tmp_addr, tmp_data);
- //=====================================
- // Read revert pull low CPU reset signal : 0x9000_0014 ==> 0x0000_0000
- //=====================================
- tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
- tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x14;
+ /*=====================================
+ Read revert pull low CPU reset signal : 0x9000_0014 ==> 0x0000_0000
+ =====================================*/
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x14;
himax_register_read(client, tmp_addr, 1, tmp_data);
- I("%s: revert pull low CPU reset signal data[0]=%x data[1]=%x data[2]=%x data[3]=%x\n", __func__
- ,tmp_data[0],tmp_data[1],tmp_data[2],tmp_data[3]);
+ I("%s: revert pull low CPU reset signal data[0]=%x data[1]=%x ",
+ __func__, tmp_data[0], tmp_data[1]);
+ I("data[2]=%x data[3]=%x\n",
+ tmp_data[2], tmp_data[3]);
- //=====================================
- // Reset TCON
- //=====================================
- tmp_addr[3] = 0x80; tmp_addr[2] = 0x02; tmp_addr[1] = 0x01; tmp_addr[0] = 0xE0;
- tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
- himax_flash_write_burst(client, tmp_addr, tmp_data);
- usleep_range(10000, 20000);
- tmp_addr[3] = 0x80; tmp_addr[2] = 0x02; tmp_addr[1] = 0x01; tmp_addr[0] = 0xE0;
- tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x01;
- himax_flash_write_burst(client, tmp_addr, tmp_data);
+ /*=====================================
+ Reset TCON
+ =====================================*/
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x02;
+ tmp_addr[1] = 0x01; tmp_addr[0] = 0xE0;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
+ usleep_range(9999, 10000);
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x02;
+ tmp_addr[1] = 0x01; tmp_addr[0] = 0xE0;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = 0x01;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
- if (FlashMode == 0x00) //SRAM
- {
- //=====================================
- // Re-map
- //=====================================
- tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x00;
- tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0xF1;
- himax_flash_write_burst_lenth(client, tmp_addr, tmp_data, 4);
+ if (FlashMode == 0x00) { /*SRAM*/
+ /*=====================================
+ Re-map
+ =====================================*/
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x00;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = 0xF1;
+ himax_flash_write_burst_length(client, tmp_addr, tmp_data, 4);
I("%s:83100_Chip_Re-map ON\n", __func__);
- }
- else
- {
- //=====================================
- // Re-map off
- //=====================================
- tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x00;
- tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
- himax_flash_write_burst_lenth(client, tmp_addr, tmp_data, 4);
+ } else {
+ /*=====================================
+ Re-map off
+ =====================================*/
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x00;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ himax_flash_write_burst_length(client, tmp_addr, tmp_data, 4);
I("%s:83100_Chip_Re-map OFF\n", __func__);
}
- //=====================================
- // CPU clock on
- //=====================================
- tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
- tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
- himax_flash_write_burst_lenth(client, tmp_addr, tmp_data, 4);
+ /*=====================================
+ CPU clock on
+ =====================================*/
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ himax_flash_write_burst_length(client, tmp_addr, tmp_data, 4);
}
@@ -751,36 +833,45 @@
himax_burst_enable(client, 0);
- //=====================================
- // SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
- //=====================================
- tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
- tmp_data[3] = 0x00; tmp_data[2] = 0x02; tmp_data[1] = 0x07; tmp_data[0] = 0x80;
+ /*=====================================
+ SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
+ =====================================*/
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x02;
+ tmp_data[1] = 0x07; tmp_data[0] = 0x80;
himax_flash_write_burst(client, tmp_addr, tmp_data);
- //=====================================
- // Chip Erase
- // Write Enable : 1. 0x8000_0020 ==> 0x4700_0000
- // 2. 0x8000_0024 ==> 0x0000_0006
- //=====================================
- tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
- tmp_data[3] = 0x47; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ /*=====================================
+ Chip Erase
+ Write Enable :
+ 1. 0x8000_0020 ==> 0x4700_0000
+ 2. 0x8000_0024 ==> 0x0000_0006
+ =====================================*/
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+ tmp_data[3] = 0x47; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = 0x00;
himax_flash_write_burst(client, tmp_addr, tmp_data);
- tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
- tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x06;
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = 0x06;
himax_flash_write_burst(client, tmp_addr, tmp_data);
- //=====================================
- // Chip Erase
- // Erase Command : 0x8000_0024 ==> 0x0000_00C7
- //=====================================
- tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
- tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0xC7;
+ /*=====================================
+ Chip Erase
+ Erase Command : 0x8000_0024 ==> 0x0000_00C7
+ =====================================*/
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = 0xC7;
himax_flash_write_burst(client, tmp_addr, tmp_data);
-
+
msleep(2000);
-
+
if (!wait_wip(client, 100))
E("%s:83100_Chip_Erase Fail\n", __func__);
@@ -793,53 +884,64 @@
himax_burst_enable(client, 0);
- //=====================================
- // SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
- //=====================================
- tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
- tmp_data[3] = 0x00; tmp_data[2] = 0x02; tmp_data[1] = 0x07; tmp_data[0] = 0x80;
+ /*=====================================
+ SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
+ =====================================*/
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x02;
+ tmp_data[1] = 0x07; tmp_data[0] = 0x80;
himax_flash_write_burst(client, tmp_addr, tmp_data);
- //=====================================
- // Chip Erase
- // Write Enable : 1. 0x8000_0020 ==> 0x4700_0000
- // 2. 0x8000_0024 ==> 0x0000_0006
- //=====================================
- tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
- tmp_data[3] = 0x47; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ /*=====================================
+ Chip Erase
+ Write Enable :
+ 1. 0x8000_0020 ==> 0x4700_0000
+ 2. 0x8000_0024 ==> 0x0000_0006
+ =====================================*/
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+ tmp_data[3] = 0x47; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = 0x00;
himax_flash_write_burst(client, tmp_addr, tmp_data);
- tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
- tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x06;
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = 0x06;
himax_flash_write_burst(client, tmp_addr, tmp_data);
- //=====================================
- // Block Erase
- // Erase Command : 0x8000_0028 ==> 0x0000_0000 //SPI addr
- // 0x8000_0020 ==> 0x6700_0000 //control
- // 0x8000_0024 ==> 0x0000_0052 //BE
- //=====================================
- tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x28;
- tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ /*=====================================
+ Block Erase
+ Erase Command :
+ 0x8000_0028 ==> 0x0000_0000 //SPI addr
+ 0x8000_0020 ==> 0x6700_0000 //control
+ 0x8000_0024 ==> 0x0000_0052 //BE
+ =====================================*/
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x28;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = 0x00;
himax_flash_write_burst(client, tmp_addr, tmp_data);
-
- tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
- tmp_data[3] = 0x67; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+ tmp_data[3] = 0x67; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = 0x00;
himax_flash_write_burst(client, tmp_addr, tmp_data);
-
- tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
- tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x52;
+
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = 0x52;
himax_flash_write_burst(client, tmp_addr, tmp_data);
msleep(1000);
- if (!wait_wip(client, 100))
- {
+ if (!wait_wip(client, 100)) {
E("%s:83100_Erase Fail\n", __func__);
return false;
- }
- else
- {
+ } else {
return true;
}
@@ -853,97 +955,110 @@
himax_burst_enable(client, 0);
- //=====================================
- // SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
- //=====================================
- tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
- tmp_data[3] = 0x00; tmp_data[2] = 0x02; tmp_data[1] = 0x07; tmp_data[0] = 0x80;
+ /*=====================================
+ SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
+ =====================================*/
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x02;
+ tmp_data[1] = 0x07; tmp_data[0] = 0x80;
himax_flash_write_burst(client, tmp_addr, tmp_data);
- for (page_prog_start = start_addr; page_prog_start < start_addr + 0x0F000; page_prog_start = page_prog_start + 0x1000)
- {
- //=====================================
- // Chip Erase
- // Write Enable : 1. 0x8000_0020 ==> 0x4700_0000
- // 2. 0x8000_0024 ==> 0x0000_0006
- //=====================================
- tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
- tmp_data[3] = 0x47; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
- himax_flash_write_burst(client, tmp_addr, tmp_data);
+ for (page_prog_start = start_addr;
+ page_prog_start < start_addr + 0x0F000;
+ page_prog_start = page_prog_start + 0x1000) {
+ /*=====================================
+ Chip Erase
+ Write Enable :
+ 1. 0x8000_0020 ==> 0x4700_0000
+ 2. 0x8000_0024 ==> 0x0000_0006
+ =====================================*/
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+ tmp_data[3] = 0x47; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
- tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
- tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x06;
- himax_flash_write_burst(client, tmp_addr, tmp_data);
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = 0x06;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
- //=====================================
- // Sector Erase
- // Erase Command : 0x8000_0028 ==> 0x0000_0000 //SPI addr
- // 0x8000_0020 ==> 0x6700_0000 //control
- // 0x8000_0024 ==> 0x0000_0020 //SE
- //=====================================
- tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x28;
- if (page_prog_start < 0x100)
- {
- tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = (uint8_t)page_prog_start;
- }
- else if (page_prog_start >= 0x100 && page_prog_start < 0x10000)
- {
- tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = (uint8_t)(page_prog_start >> 8); tmp_data[0] = (uint8_t)page_prog_start;
- }
- else if (page_prog_start >= 0x10000 && page_prog_start < 0x1000000)
- {
- tmp_data[3] = 0x00; tmp_data[2] = (uint8_t)(page_prog_start >> 16); tmp_data[1] = (uint8_t)(page_prog_start >> 8); tmp_data[0] = (uint8_t)page_prog_start;
- }
- himax_flash_write_burst(client, tmp_addr, tmp_data);
+ /*=====================================
+ Sector Erase
+ Erase Command :
+ 0x8000_0028 ==> 0x0000_0000 //SPI addr
+ 0x8000_0020 ==> 0x6700_0000 //control
+ 0x8000_0024 ==> 0x0000_0020 //SE
+ =====================================*/
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x28;
+ if (page_prog_start < 0x100) {
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00;
+ tmp_data[0] = (uint8_t)page_prog_start;
+ } else if (page_prog_start >= 0x100
+ && page_prog_start < 0x10000) {
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+ tmp_data[1] = (uint8_t)(page_prog_start >> 8);
+ tmp_data[0] = (uint8_t)page_prog_start;
+ } else if (page_prog_start >= 0x10000
+ && page_prog_start < 0x1000000) {
+ tmp_data[3] = 0x00;
+ tmp_data[2] = (uint8_t)(page_prog_start >> 16);
+ tmp_data[1] = (uint8_t)(page_prog_start >> 8);
+ tmp_data[0] = (uint8_t)page_prog_start;
+ }
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
- tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
- tmp_data[3] = 0x67; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
- himax_flash_write_burst(client, tmp_addr, tmp_data);
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+ tmp_data[3] = 0x67; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
- tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
- tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x20;
- himax_flash_write_burst(client, tmp_addr, tmp_data);
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = 0x20;
+ himax_flash_write_burst(client, tmp_addr, tmp_data);
- msleep(200);
+ msleep(200);
- if (!wait_wip(client, 100))
- {
- E("%s:83100_Erase Fail\n", __func__);
- return false;
- }
- }
- return true;
+ if (!wait_wip(client, 100)) {
+ E("%s:83100_Erase Fail\n", __func__);
+ return false;
+ }
+ }
+ return true;
}
void himax_sram_write(struct i2c_client *client, uint8_t *FW_content)
{
int i = 0;
uint8_t tmp_addr[4];
- uint8_t tmp_data[128];
- int FW_length = 0x4000; // 0x4000 = 16K bin file
-
- //himax_sense_off(client);
+ uint8_t tmp_data[64];
+ int FW_length = 0x4000; /* 0x4000 = 16K bin file */
- for (i = 0; i < FW_length; i = i + 128)
- {
+ /*himax_sense_off(client);*/
+
+ for (i = 0; i < FW_length; i = i + 64) {
himax_burst_enable(client, 1);
- if (i < 0x100)
- {
- tmp_addr[3] = 0x08;
- tmp_addr[2] = 0x00;
- tmp_addr[1] = 0x00;
+ if (i < 0x100) {
+ tmp_addr[3] = 0x08;
+ tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00;
tmp_addr[0] = i;
- }
- else if (i >= 0x100 && i < 0x10000)
- {
- tmp_addr[3] = 0x08;
- tmp_addr[2] = 0x00;
- tmp_addr[1] = (i >> 8);
+ } else if (i >= 0x100 && i < 0x10000) {
+ tmp_addr[3] = 0x08;
+ tmp_addr[2] = 0x00;
+ tmp_addr[1] = (i >> 8);
tmp_addr[0] = i;
}
- memcpy(&tmp_data[0], &FW_content[i], 128);
- himax_flash_write_burst_lenth(client, tmp_addr, tmp_data, 128);
+ memcpy(&tmp_data[0], &FW_content[i], 64);
+ himax_flash_write_burst_length(client, tmp_addr, tmp_data, 64);
}
@@ -951,182 +1066,197 @@
E("%s:83100_Sram_Write Fail\n", __func__);
}
-bool himax_sram_verify(struct i2c_client *client, uint8_t *FW_File, int FW_Size)
+bool himax_sram_verify(struct i2c_client *client,
+uint8_t *FW_File, int FW_Size)
{
int i = 0;
uint8_t out_buffer[20];
uint8_t in_buffer[128];
uint8_t *get_fw_content;
- get_fw_content = kzalloc(0x4000*sizeof(uint8_t), GFP_KERNEL);
- if (!get_fw_content)
- return false;
+ get_fw_content = kzalloc(0x4000 * sizeof(uint8_t), GFP_KERNEL);
- for (i = 0; i < 0x4000; i = i + 128)
- {
+ for (i = 0 ; i < 0x4000 ; i = i + 128) {
himax_burst_enable(client, 1);
- //==================================
- // AHB_I2C Burst Read
- //==================================
- if (i < 0x100)
- {
- out_buffer[3] = 0x08;
- out_buffer[2] = 0x00;
- out_buffer[1] = 0x00;
+ /*=====================================
+ AHB_I2C Burst Read
+ =====================================*/
+ if (i < 0x100) {
+ out_buffer[3] = 0x08;
+ out_buffer[2] = 0x00;
+ out_buffer[1] = 0x00;
out_buffer[0] = i;
- }
- else if (i >= 0x100 && i < 0x10000)
- {
- out_buffer[3] = 0x08;
- out_buffer[2] = 0x00;
- out_buffer[1] = (i >> 8);
+ } else if (i >= 0x100 && i < 0x10000) {
+ out_buffer[3] = 0x08;
+ out_buffer[2] = 0x00;
+ out_buffer[1] = (i >> 8);
out_buffer[0] = i;
}
- if ( i2c_himax_write(client, 0x00 ,out_buffer, 4, HIMAX_I2C_RETRY_TIMES) < 0) {
+ if (i2c_himax_write(client, 0x00, out_buffer,
+ 4, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return false;
}
- out_buffer[0] = 0x00;
- if ( i2c_himax_write(client, 0x0C ,out_buffer, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ out_buffer[0] = 0x00;
+ if (i2c_himax_write(client, 0x0C, out_buffer,
+ 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return false;
}
- if ( i2c_himax_read(client, 0x08 ,in_buffer, 128, HIMAX_I2C_RETRY_TIMES) < 0) {
+ if (i2c_himax_read(client, 0x08, in_buffer,
+ 128, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return false;
}
memcpy(&get_fw_content[i], &in_buffer[0], 128);
}
- for (i = 0; i < FW_Size; i++)
- {
- if (FW_File[i] != get_fw_content[i])
- {
- E("%s: fail! SRAM[%x]=%x NOT CRC_ifile=%x\n", __func__,i,get_fw_content[i],FW_File[i]);
- return false;
- }
+ for (i = 0 ; i < FW_Size ; i++) {
+ if (FW_File[i] != get_fw_content[i]) {
+ E("%s: fail! SRAM[%x]=%x NOT CRC_ifile=%x\n",
+ __func__, i, get_fw_content[i], FW_File[i]);
+ return false;
}
+ }
kfree(get_fw_content);
return true;
}
-void himax_flash_programming(struct i2c_client *client, uint8_t *FW_content, int FW_Size)
+void himax_flash_programming(struct i2c_client *client,
+uint8_t *FW_content, int FW_Size)
{
int page_prog_start = 0;
int program_length = 48;
int i = 0, j = 0, k = 0;
uint8_t tmp_addr[4];
uint8_t tmp_data[4];
- uint8_t buring_data[256]; // Read for flash data, 128K
- // 4 bytes for 0x80002C padding
+ /* // Read for flash data, 128K //4 bytes for 0x80002C padding */
+ uint8_t buring_data[256];
- //himax_interface_on(client);
+ /*himax_interface_on(client);*/
himax_burst_enable(client, 0);
- //=====================================
- // SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
- //=====================================
- tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
- tmp_data[3] = 0x00; tmp_data[2] = 0x02; tmp_data[1] = 0x07; tmp_data[0] = 0x80;
+ /*=====================================
+ SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
+ =====================================*/
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x02;
+ tmp_data[1] = 0x07; tmp_data[0] = 0x80;
himax_flash_write_burst(client, tmp_addr, tmp_data);
- for (page_prog_start = 0; page_prog_start < FW_Size; page_prog_start = page_prog_start + 256)
- {
- //msleep(5);
- //=====================================
- // Write Enable : 1. 0x8000_0020 ==> 0x4700_0000
- // 2. 0x8000_0024 ==> 0x0000_0006
- //=====================================
- tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
- tmp_data[3] = 0x47; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ for (page_prog_start = 0 ; page_prog_start < FW_Size;
+ page_prog_start = page_prog_start + 256) {
+ /*msleep(5);*/
+ /*=====================================
+ Write Enable :
+ 1. 0x8000_0020 ==> 0x4700_0000
+ 2. 0x8000_0024 ==> 0x0000_0006
+ =====================================*/
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+ tmp_data[3] = 0x47; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = 0x00;
himax_flash_write_burst(client, tmp_addr, tmp_data);
- tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
- tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x06;
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = 0x06;
himax_flash_write_burst(client, tmp_addr, tmp_data);
- //=================================
- // SPI Transfer Control
- // Set 256 bytes page write : 0x8000_0020 ==> 0x610F_F000
- // Set read start address : 0x8000_0028 ==> 0x0000_0000
- //=================================
- tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
- tmp_data[3] = 0x61; tmp_data[2] = 0x0F; tmp_data[1] = 0xF0; tmp_data[0] = 0x00;
- // data bytes should be 0x6100_0000 + ((word_number)*4-1)*4096 = 0x6100_0000 + 0xFF000 = 0x610F_F000
- // Programmable size = 1 page = 256 bytes, word_number = 256 byte / 4 = 64
+ /*=====================================
+ SPI Transfer Control
+ Set 256 bytes page write : 0x8000_0020 ==> 0x610F_F000
+ Set read start address : 0x8000_0028 ==> 0x0000_0000
+ =====================================*/
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+ tmp_data[3] = 0x61; tmp_data[2] = 0x0F;
+ tmp_data[1] = 0xF0; tmp_data[0] = 0x00;
+ /*data bytes should be 0x6100_0000 +
+ ((word_number)*4-1)*4096 = 0x6100_0000 +
+ 0xFF000 = 0x610F_F000
+ Programmable size = 1 page = 256 bytes,
+ word_number = 256 byte / 4 = 64*/
himax_flash_write_burst(client, tmp_addr, tmp_data);
- tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x28;
- //tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; // Flash start address 1st : 0x0000_0000
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x28;
+ /* tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ // Flash start address 1st : 0x0000_0000 */
- if (page_prog_start < 0x100)
- {
- tmp_data[3] = 0x00;
- tmp_data[2] = 0x00;
- tmp_data[1] = 0x00;
+ if (page_prog_start < 0x100) {
+ tmp_data[3] = 0x00;
+ tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00;
+ tmp_data[0] = (uint8_t)page_prog_start;
+ } else if (page_prog_start >= 0x100
+ && page_prog_start < 0x10000) {
+ tmp_data[3] = 0x00;
+ tmp_data[2] = 0x00;
+ tmp_data[1] = (uint8_t)(page_prog_start >> 8);
+ tmp_data[0] = (uint8_t)page_prog_start;
+ } else if (page_prog_start >= 0x10000
+ && page_prog_start < 0x1000000) {
+ tmp_data[3] = 0x00;
+ tmp_data[2] = (uint8_t)(page_prog_start >> 16);
+ tmp_data[1] = (uint8_t)(page_prog_start >> 8);
tmp_data[0] = (uint8_t)page_prog_start;
}
- else if (page_prog_start >= 0x100 && page_prog_start < 0x10000)
- {
- tmp_data[3] = 0x00;
- tmp_data[2] = 0x00;
- tmp_data[1] = (uint8_t)(page_prog_start >> 8);
- tmp_data[0] = (uint8_t)page_prog_start;
- }
- else if (page_prog_start >= 0x10000 && page_prog_start < 0x1000000)
- {
- tmp_data[3] = 0x00;
- tmp_data[2] = (uint8_t)(page_prog_start >> 16);
- tmp_data[1] = (uint8_t)(page_prog_start >> 8);
- tmp_data[0] = (uint8_t)page_prog_start;
- }
-
+
himax_flash_write_burst(client, tmp_addr, tmp_data);
-
- //=================================
- // Send 16 bytes data : 0x8000_002C ==> 16 bytes data
- //=================================
+ /*=====================================
+ Send 16 bytes data : 0x8000_002C ==> 16 bytes data
+ =====================================*/
buring_data[0] = 0x2C;
buring_data[1] = 0x00;
buring_data[2] = 0x00;
buring_data[3] = 0x80;
-
- for (i = /*0*/page_prog_start, j = 0; i < 16 + page_prog_start/**/; i++, j++) /// <------ bin file
- {
+
+ for (i = /*0*/page_prog_start, j = 0;
+ i < 16 + page_prog_start/**/;
+ i++, j++) { /* <------ bin file*/
+
buring_data[j + 4] = FW_content[i];
}
-
- if ( i2c_himax_write(client, 0x00 ,buring_data, 20, HIMAX_I2C_RETRY_TIMES) < 0) {
+ if (i2c_himax_write(client, 0x00, buring_data,
+ 20, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
- //=================================
- // Write command : 0x8000_0024 ==> 0x0000_0002
- //=================================
- tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
- tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x02;
+ /*=====================================
+ Write command : 0x8000_0024 ==> 0x0000_0002
+ =====================================*/
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = 0x02;
himax_flash_write_burst(client, tmp_addr, tmp_data);
- //=================================
- // Send 240 bytes data : 0x8000_002C ==> 240 bytes data
- //=================================
+ /*=====================================
+ Send 240 bytes data : 0x8000_002C ==> 240 bytes data
+ =====================================*/
- for (j = 0; j < 5; j++)
- {
- for (i = (page_prog_start + 16 + (j * 48)), k = 0; i < (page_prog_start + 16 + (j * 48)) + program_length; i++, k++) /// <------ bin file
- {
- buring_data[k+4] = FW_content[i];//(byte)i;
+ for (j = 0; j < 5; j++) {
+ for (i = (page_prog_start + 16 + (j * 48)), k = 0;
+ i < (page_prog_start + 16 + (j * 48)) + program_length;
+ i++, k++) { /*<------ bin file*/
+ buring_data[k+4] = FW_content[i];/*(byte)i;*/
}
- if ( i2c_himax_write(client, 0x00 ,buring_data, program_length+4, HIMAX_I2C_RETRY_TIMES) < 0) {
+ if (i2c_himax_write(client, 0x00, buring_data,
+ program_length + 4,
+ HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
@@ -1145,52 +1275,61 @@
uint8_t ret_data = 0x00;
int i = 0;
int ret = 0;
+
himax_sense_off(client);
- for (i = 0; i < 5; i++)
- {
- // 1. Set DDREG_Req = 1 (0x9000_0020 = 0x0000_0001) (Lock register R/W from driver)
- tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
- tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x01;
+
+ for (i = 0 ; i < 5 ; i++) {
+ /* 1. Set DDREG_Req = 1 (0x9000_0020 = 0x0000_0001)
+ (Lock register R/W from driver) */
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = 0x01;
ret = himax_register_write(client, tmp_addr, 1, tmp_data);
- if(ret)
+ if (ret)
return false;
- // 2. Set bank as 0 (0x8001_BD01 = 0x0000_0000)
- tmp_addr[3] = 0x80; tmp_addr[2] = 0x01; tmp_addr[1] = 0xBD; tmp_addr[0] = 0x01;
- tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ /* 2. Set bank as 0 (0x8001_BD01 = 0x0000_0000)*/
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x01;
+ tmp_addr[1] = 0xBD; tmp_addr[0] = 0x01;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = 0x00;
ret = himax_register_write(client, tmp_addr, 1, tmp_data);
- if(ret)
+ if (ret)
return false;
- // 3. Read driver ID register RF4H 1 byte (0x8001_F401)
- // Driver register RF4H 1 byte value = 0x84H, read back value will become 0x84848484
- tmp_addr[3] = 0x80; tmp_addr[2] = 0x01; tmp_addr[1] = 0xF4; tmp_addr[0] = 0x01;
+ /* 3. Read driver ID register RF4H 1 byte (0x8001_F401)
+ // Driver register RF4H 1 byte value = 0x84H,
+ read back value will become 0x84848484 */
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x01;
+ tmp_addr[1] = 0xF4; tmp_addr[0] = 0x01;
himax_register_read(client, tmp_addr, 1, tmp_data);
ret_data = tmp_data[0];
I("%s:Read driver IC ID = %X\n", __func__, ret_data);
- if (ret_data == 0x84)
- {
+ if (ret_data == 0x84) {
IC_TYPE = HX_83100_SERIES_PWON;
- //himax_sense_on(client, 0x01);
+ /*himax_sense_on(client, 0x01);*/
ret_data = true;
break;
- }
- else
- {
+
+ } else {
ret_data = false;
E("%s:Read driver ID register Fail:\n", __func__);
}
}
- // 4. After read finish, set DDREG_Req = 0 (0x9000_0020 = 0x0000_0000) (Unlock register R/W from driver)
- tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
- tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ /* 4. After read finish, set DDREG_Req = 0
+ (0x9000_0020 = 0x0000_0000) (Unlock register R/W from driver)*/
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = 0x00;
himax_register_write(client, tmp_addr, 1, tmp_data);
- //himax_sense_on(client, 0x01);
+ /*himax_sense_on(client, 0x01);*/
return ret_data;
}
-#if 1
+/*#if 1*/
int himax_check_CRC(struct i2c_client *client, int mode)
{
bool burnFW_success = false;
@@ -1200,52 +1339,70 @@
int CRC_value = 0;
memset(tmp_data, 0x00, sizeof(tmp_data));
+ if (i_TP_CRC_FW_60K == NULL) {
+ I("%s: i_TP_CRC_FW_60K = NULL\n", __func__);
+ return 0;
+ } else if (i_TP_CRC_FW_64K == NULL) {
+ I("%s: i_TP_CRC_FW_64K = NULL\n", __func__);
+ return 0;
+ } else if (i_TP_CRC_FW_124K == NULL) {
+ I("%s: i_TP_CRC_FW_124K = NULL\n", __func__);
+ return 0;
+ } else if (i_TP_CRC_FW_128K == NULL) {
+ I("%s: i_TP_CRC_FW_128K = NULL\n", __func__);
+ return 0;
+ }
- if (1)
- {
- if(mode == fw_image_60k)
- {
- himax_sram_write(client, (i_TP_CRC_FW_60K));
- burnFW_success = himax_sram_verify(client, i_TP_CRC_FW_60K, 0x4000);
+ if (1) {
+ if (mode == fw_image_60k) {
+ himax_sram_write(client,
+ (unsigned char *)i_TP_CRC_FW_60K->data);
+ burnFW_success = himax_sram_verify(client,
+ (unsigned char *)i_TP_CRC_FW_60K->data, 0x4000);
+ } else if (mode == fw_image_64k) {
+ himax_sram_write(client,
+ (unsigned char *)i_TP_CRC_FW_64K->data);
+ burnFW_success = himax_sram_verify(client,
+ (unsigned char *)i_TP_CRC_FW_64K->data, 0x4000);
+ } else if (mode == fw_image_124k) {
+ himax_sram_write(client,
+ (unsigned char *)i_TP_CRC_FW_124K->data);
+ burnFW_success = himax_sram_verify(client,
+ (unsigned char *)i_TP_CRC_FW_124K->data, 0x4000);
+ } else if (mode == fw_image_128k) {
+ himax_sram_write(client,
+ (unsigned char *)i_TP_CRC_FW_128K->data);
+ burnFW_success = himax_sram_verify(client,
+ (unsigned char *)i_TP_CRC_FW_128K->data, 0x4000);
}
- else if(mode == fw_image_64k)
- {
- himax_sram_write(client, (i_TP_CRC_FW_64K));
- burnFW_success = himax_sram_verify(client, i_TP_CRC_FW_64K, 0x4000);
- }
- else if(mode == fw_image_124k)
- {
- himax_sram_write(client, (i_TP_CRC_FW_124K));
- burnFW_success = himax_sram_verify(client, i_TP_CRC_FW_124K, 0x4000);
- }
- else if(mode == fw_image_128k)
- {
- himax_sram_write(client, (i_TP_CRC_FW_128K));
- burnFW_success = himax_sram_verify(client, i_TP_CRC_FW_128K, 0x4000);
- }
- if (burnFW_success)
- {
- I("%s: Start to do CRC FW mode=%d \n", __func__,mode);
- himax_sense_on(client, 0x00); // run CRC firmware
+ if (burnFW_success) {
+ I("%s: Start to do CRC FW mode=%d\n", __func__, mode);
+ himax_sense_on(client, 0x00); /* run CRC firmware*/
- while(true)
- {
+ while (true) {
msleep(100);
-
- tmp_addr[3] = 0x90;
- tmp_addr[2] = 0x08;
- tmp_addr[1] = 0x80;
+ tmp_addr[3] = 0x90;
+ tmp_addr[2] = 0x08;
+ tmp_addr[1] = 0x80;
tmp_addr[0] = 0x94;
- himax_register_read(client, tmp_addr, 1, tmp_data);
+ himax_register_read(client,
+ tmp_addr, 1, tmp_data);
- I("%s: CRC from firmware is %x, %x, %x, %x \n", __func__,tmp_data[3],
- tmp_data[2],tmp_data[1],tmp_data[0]);
-
- if (tmp_data[3] == 0xFF && tmp_data[2] == 0xFF && tmp_data[1] == 0xFF && tmp_data[0] == 0xFF)
- {
- }
- else
+ I("%s: CRC from firmware is %x, %x, %x, %x\n",
+ __func__, tmp_data[3], tmp_data[2],
+ tmp_data[1], tmp_data[0]);
+/*
+ if (tmp_data[3] == 0xFF && tmp_data[2] == 0xFF
+ && tmp_data[1] == 0xFF && tmp_data[0] == 0xFF) {
+ } else
break;
+ */
+ if (!(tmp_data[3] == 0xFF
+ && tmp_data[2] == 0xFF
+ && tmp_data[1] == 0xFF
+ && tmp_data[0] == 0xFF)) {
+ break;
+ }
}
CRC_value = tmp_data[3];
@@ -1259,30 +1416,32 @@
tmp_value = tmp_data[0] << 24;
CRC_value += tmp_value;
- I("%s: CRC Value is %x \n", __func__, CRC_value);
+ I("%s: CRC Value is %x\n", __func__, CRC_value);
- //Close Remapping
- //=====================================
- // Re-map close
- //=====================================
- tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x00;
- tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
- himax_flash_write_burst_lenth(client, tmp_addr, tmp_data, 4);
- return CRC_value;
- }
- else
- {
+ /*Close Remapping*/
+ /*=====================================
+ Re-map close
+ =====================================*/
+ tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x00;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+ himax_flash_write_burst_length(client,
+ tmp_addr, tmp_data, 4);
+ return CRC_value;
+
+ } else {
E("%s: SRAM write fail\n", __func__);
return 0;
- }
- }
- else
- I("%s: NO CRC Check File \n", __func__);
+ }
+ } else
+ I("%s: NO CRC Check File\n", __func__);
return 0;
}
-bool Calculate_CRC_with_AP(unsigned char *FW_content , int CRC_from_FW, int mode)
+bool Calculate_CRC_with_AP(unsigned char *FW_content,
+int CRC_from_FW, int mode)
{
uint8_t tmp_data[4];
int i, j;
@@ -1291,42 +1450,35 @@
int CRC = 0xFFFFFFFF;
int PolyNomial = 0x82F63B78;
int length = 0;
-
+
if (mode == fw_image_128k)
length = 0x8000;
else if (mode == fw_image_124k)
length = 0x7C00;
else if (mode == fw_image_64k)
length = 0x4000;
- else //if (mode == fw_image_60k)
+ else /*if (mode == fw_image_60k)*/
length = 0x3C00;
- for (i = 0; i < length; i++)
- {
- fw_data = FW_content[i * 4 ];
-
- for (j = 1; j < 4; j++)
- {
+ for (i = 0 ; i < length ; i++) {
+ fw_data = FW_content[i * 4];
+
+ for (j = 1 ; j < 4 ; j++) {
fw_data_2 = FW_content[i * 4 + j];
fw_data += (fw_data_2) << (8 * j);
}
CRC = fw_data ^ CRC;
- for (j = 0; j < 32; j++)
- {
+ for (j = 0 ; j < 32 ; j++) {
if ((CRC % 2) != 0)
- {
- CRC = ((CRC >> 1) & 0x7FFFFFFF) ^ PolyNomial;
- }
+ CRC = ((CRC >> 1) & 0x7FFFFFFF) ^ PolyNomial;
else
- {
- CRC = (((CRC >> 1) ^ 0x7FFFFFFF)& 0x7FFFFFFF);
- }
+ CRC = (((CRC >> 1) ^ 0x7FFFFFFF) & 0x7FFFFFFF);
}
}
- I("%s: CRC calculate from bin file is %x \n", __func__, CRC);
+ I("%s: CRC calculate from bin file is %x\n", __func__, CRC);
tmp_data[0] = (uint8_t)(CRC >> 24);
tmp_data[1] = (uint8_t)(CRC >> 16);
@@ -1334,58 +1486,129 @@
tmp_data[3] = (uint8_t) CRC;
CRC = tmp_data[0];
- CRC += tmp_data[1] << 8;
+ CRC += tmp_data[1] << 8;
CRC += tmp_data[2] << 16;
CRC += tmp_data[3] << 24;
- I("%s: CRC calculate from bin file REVERSE %x \n", __func__, CRC);
- I("%s: CRC calculate from FWis %x \n", __func__, CRC_from_FW);
+ I("%s: CRC calculate from bin file REVERSE %x\n", __func__, CRC);
+ I("%s: CRC calculate from FWis %x\n", __func__, CRC_from_FW);
if (CRC_from_FW == CRC)
return true;
else
return false;
}
-#endif
+/*#endif*/
-int fts_ctpm_fw_upgrade_with_sys_fs_60k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref)
+int himax_load_CRC_bin_file(struct i2c_client *client)
+{
+ int err = 0;
+ char *CRC_60_firmware_name = "HX_CRC_60.bin";
+ char *CRC_64_firmware_name = "HX_CRC_64.bin";
+ char *CRC_124_firmware_name = "HX_CRC_124.bin";
+ char *CRC_128_firmware_name = "HX_CRC_128.bin";
+
+ I("%s,Entering\n", __func__);
+ if (i_TP_CRC_FW_60K == NULL) {
+ I("load file name = %s\n", CRC_60_firmware_name);
+ err = request_firmware(&i_TP_CRC_FW_60K,
+ CRC_60_firmware_name, private_ts->dev);
+ if (err < 0) {
+ E("%s,fail in line%d error code=%d\n",
+ __func__, __LINE__, err);
+ err = -1;
+ goto request_60k_fw_fail;
+ }
+ } else
+ I("%s already load i_TP_CRC_FW_60K\n", __func__);
+
+ if (i_TP_CRC_FW_64K == NULL) {
+ I("load file name = %s\n", CRC_64_firmware_name);
+ err = request_firmware(&i_TP_CRC_FW_64K,
+ CRC_64_firmware_name, private_ts->dev);
+ if (err < 0) {
+ E("%s,fail in line%d error code=%d\n",
+ __func__, __LINE__, err);
+ err = -2;
+ goto request_64k_fw_fail;
+ }
+ } else
+ I("%s already load i_TP_CRC_FW_64K\n", __func__);
+
+ if (i_TP_CRC_FW_124K == NULL) {
+ I("load file name = %s\n", CRC_124_firmware_name);
+ err = request_firmware(&i_TP_CRC_FW_124K,
+ CRC_124_firmware_name, private_ts->dev);
+ if (err < 0) {
+ E("%s,fail in line%d error code=%d\n",
+ __func__, __LINE__, err);
+ err = -3;
+ goto request_124k_fw_fail;
+ }
+ } else
+ I("%s already load i_TP_CRC_FW_124K\n", __func__);
+
+ if (i_TP_CRC_FW_128K == NULL) {
+ I("load file name = %s\n", CRC_128_firmware_name);
+ err = request_firmware(&i_TP_CRC_FW_128K,
+ CRC_128_firmware_name, private_ts->dev);
+ if (err < 0) {
+ E("%s,fail in line%d error code=%d\n",
+ __func__, __LINE__, err);
+ err = -4;
+ goto request_128k_fw_fail;
+ }
+ } else
+ I("%s already load i_TP_CRC_FW_128K\n", __func__);
+
+ return err;
+
+request_128k_fw_fail:
+ release_firmware(i_TP_CRC_FW_124K);
+request_124k_fw_fail:
+ release_firmware(i_TP_CRC_FW_64K);
+request_64k_fw_fail:
+ release_firmware(i_TP_CRC_FW_60K);
+request_60k_fw_fail:
+ return err;
+}
+int fts_ctpm_fw_upgrade_with_sys_fs_60k(struct i2c_client *client,
+unsigned char *fw, int len, bool change_iref)
{
int CRC_from_FW = 0;
int burnFW_success = 0;
- if (len != 0x10000) //64k
- {
- E("%s: The file size is not 64K bytes\n", __func__);
- return false;
- }
+ if (len != 0x10000) {/*64k*/
+ E("%s: The file size is not 64K bytes\n", __func__);
+ return false;
+ }
himax_sense_off(client);
msleep(500);
himax_interface_on(client);
- if (!himax_sector_erase(client, 0x00000))
- {
- E("%s:Sector erase fail!Please restart the IC.\n", __func__);
- return false;
- }
+ if (!himax_sector_erase(client, 0x00000)) {
+ E("%s:Sector erase fail!Please restart the IC.\n", __func__);
+ return false;
+ }
himax_flash_programming(client, fw, 0x0F000);
- //burnFW_success = himax_83100_Verify(fw, len);
- //if(burnFW_success==false)
- // return burnFW_success;
+ /*burnFW_success = himax_83100_Verify(fw, len);
+ if(burnFW_success==false)
+ return burnFW_success;*/
- CRC_from_FW = himax_check_CRC(client,fw_image_60k);
- burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW,fw_image_60k);
- //himax_sense_on(client, 0x01);
+ CRC_from_FW = himax_check_CRC(client, fw_image_60k);
+ burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW, fw_image_60k);
+ /*himax_sense_on(client, 0x01);*/
return burnFW_success;
}
-int fts_ctpm_fw_upgrade_with_sys_fs_64k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref)
+int fts_ctpm_fw_upgrade_with_sys_fs_64k(struct i2c_client *client,
+unsigned char *fw, int len, bool change_iref)
{
int CRC_from_FW = 0;
int burnFW_success = 0;
- if (len != 0x10000) //64k
- {
- E("%s: The file size is not 64K bytes\n", __func__);
- return false;
+ if (len != 0x10000) { /*64k*/
+ E("%s: The file size is not 64K bytes\n", __func__);
+ return false;
}
himax_sense_off(client);
msleep(500);
@@ -1393,62 +1616,58 @@
himax_chip_erase(client);
himax_flash_programming(client, fw, len);
- //burnFW_success = himax_83100_Verify(fw, len);
- //if(burnFW_success==false)
- // return burnFW_success;
+ /*burnFW_success = himax_83100_Verify(fw, len);
+ if(burnFW_success==false)
+ return burnFW_success;*/
- CRC_from_FW = himax_check_CRC(client,fw_image_64k);
- burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW,fw_image_64k);
- //himax_sense_on(client, 0x01);
+ CRC_from_FW = himax_check_CRC(client, fw_image_64k);
+ burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW, fw_image_64k);
+ /*himax_sense_on(client, 0x01);*/
return burnFW_success;
}
-int fts_ctpm_fw_upgrade_with_sys_fs_124k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref)
+int fts_ctpm_fw_upgrade_with_sys_fs_124k(struct i2c_client *client,
+unsigned char *fw, int len, bool change_iref)
{
int CRC_from_FW = 0;
int burnFW_success = 0;
- if (len != 0x20000) //128k
- {
- E("%s: The file size is not 128K bytes\n", __func__);
- return false;
+ if (len != 0x20000) { /*128k*/
+ E("%s: The file size is not 128K bytes\n", __func__);
+ return false;
}
himax_sense_off(client);
msleep(500);
himax_interface_on(client);
- if (!himax_block_erase(client))
- {
- E("%s:Block erase fail!Please restart the IC.\n", __func__);
- return false;
- }
-
- if (!himax_sector_erase(client, 0x10000))
- {
- E("%s:Sector erase fail!Please restart the IC.\n", __func__);
- return false;
- }
+ if (!himax_block_erase(client)) {
+ E("%s:Block erase fail!Please restart the IC.\n", __func__);
+ return false;
+ }
+ if (!himax_sector_erase(client, 0x10000)) {
+ E("%s:Sector erase fail!Please restart the IC.\n", __func__);
+ return false;
+ }
himax_flash_programming(client, fw, 0x1F000);
+ /*burnFW_success = himax_83100_Verify(fw, len);
+ if(burnFW_success==false)
+ return burnFW_success;*/
- //burnFW_success = himax_83100_Verify(fw, len);
- //if(burnFW_success==false)
- // return burnFW_success;
-
- CRC_from_FW = himax_check_CRC(client,fw_image_124k);
- burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW,fw_image_124k);
- //himax_sense_on(client, 0x01);
+ CRC_from_FW = himax_check_CRC(client, fw_image_124k);
+ burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW, fw_image_124k);
+ /*himax_sense_on(client, 0x01);*/
return burnFW_success;
}
-int fts_ctpm_fw_upgrade_with_sys_fs_128k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref)
+int fts_ctpm_fw_upgrade_with_sys_fs_128k(struct i2c_client *client,
+unsigned char *fw, int len, bool change_iref)
{
int CRC_from_FW = 0;
int burnFW_success = 0;
- if (len != 0x20000) //128k
- {
- E("%s: The file size is not 128K bytes\n", __func__);
- return false;
+ if (len != 0x20000) { /*128k*/
+ E("%s: The file size is not 128K bytes\n", __func__);
+ return false;
}
himax_sense_off(client);
msleep(500);
@@ -1457,13 +1676,13 @@
himax_flash_programming(client, fw, len);
- //burnFW_success = himax_83100_Verify(fw, len);
- //if(burnFW_success==false)
- // return burnFW_success;
+ /*burnFW_success = himax_83100_Verify(fw, len);
+ if(burnFW_success==false)
+ return burnFW_success;*/
- CRC_from_FW = himax_check_CRC(client,fw_image_128k);
- burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW,fw_image_128k);
- //himax_sense_on(client, 0x01);
+ CRC_from_FW = himax_check_CRC(client, fw_image_128k);
+ burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW, fw_image_128k);
+ /*himax_sense_on(client, 0x01); */
return burnFW_success;
}
@@ -1472,10 +1691,9 @@
uint8_t cmd[4];
char data[12] = {0};
- I("%s:IC_TYPE =%d\n", __func__,IC_TYPE);
+ I("%s:IC_TYPE =%d\n", __func__, IC_TYPE);
- if(IC_TYPE == HX_83100_SERIES_PWON)
- {
+ if (IC_TYPE == HX_83100_SERIES_PWON) {
cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x00; cmd[0] = 0xF8;
himax_register_read(client, cmd, 1, data);
@@ -1486,11 +1704,11 @@
cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x00; cmd[0] = 0xFC;
himax_register_read(client, cmd, 1, data);
- if((data[1] & 0x04) == 0x04) {
+ if ((data[1] & 0x04) == 0x04)
ic_data->HX_XY_REVERSE = true;
- } else {
+ else
ic_data->HX_XY_REVERSE = false;
- }
+
ic_data->HX_Y_RES = data[3]*256;
cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x01; cmd[0] = 0x00;
himax_register_read(client, cmd, 1, data);
@@ -1498,32 +1716,35 @@
ic_data->HX_X_RES = data[1]*256 + data[2];
cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x00; cmd[0] = 0x8C;
himax_register_read(client, cmd, 1, data);
- if((data[0] & 0x01) == 1) {
+ if ((data[0] & 0x01) == 1)
ic_data->HX_INT_IS_EDGE = true;
- } else {
+ else
ic_data->HX_INT_IS_EDGE = false;
- }
- if (ic_data->HX_RX_NUM > 40)
+
+ if (ic_data->HX_RX_NUM > 40)
ic_data->HX_RX_NUM = 29;
- if (ic_data->HX_TX_NUM > 20)
+ if (ic_data->HX_TX_NUM > 20)
ic_data->HX_TX_NUM = 16;
- if (ic_data->HX_MAX_PT > 10)
+ if (ic_data->HX_MAX_PT > 10)
ic_data->HX_MAX_PT = 10;
- if (ic_data->HX_Y_RES > 2000)
+ if (ic_data->HX_Y_RES > 2000)
ic_data->HX_Y_RES = 1280;
- if (ic_data->HX_X_RES > 2000)
+ if (ic_data->HX_X_RES > 2000)
ic_data->HX_X_RES = 720;
#ifdef HX_EN_MUT_BUTTON
cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x00; cmd[0] = 0xE8;
himax_register_read(client, cmd, 1, data);
ic_data->HX_BT_NUM = data[3];
#endif
- I("%s:HX_RX_NUM =%d,HX_TX_NUM =%d,HX_MAX_PT=%d \n", __func__,ic_data->HX_RX_NUM,ic_data->HX_TX_NUM,ic_data->HX_MAX_PT);
- I("%s:HX_XY_REVERSE =%d,HX_Y_RES =%d,HX_X_RES=%d \n", __func__,ic_data->HX_XY_REVERSE,ic_data->HX_Y_RES,ic_data->HX_X_RES);
- I("%s:HX_INT_IS_EDGE =%d \n", __func__,ic_data->HX_INT_IS_EDGE);
- }
- else
- {
+ I("%s:HX_RX_NUM =%d,HX_TX_NUM =%d,HX_MAX_PT=%d\n",
+ __func__, ic_data->HX_RX_NUM,
+ ic_data->HX_TX_NUM, ic_data->HX_MAX_PT);
+ I("%s:HX_XY_REVERSE =%d,HX_Y_RES =%d,HX_X_RES=%d\n",
+ __func__, ic_data->HX_XY_REVERSE,
+ ic_data->HX_Y_RES, ic_data->HX_X_RES);
+ I("%s:HX_INT_IS_EDGE =%d\n",
+ __func__, ic_data->HX_INT_IS_EDGE);
+ } else {
ic_data->HX_RX_NUM = 0;
ic_data->HX_TX_NUM = 0;
ic_data->HX_BT_NUM = 0;
@@ -1538,35 +1759,34 @@
void himax_read_FW_ver(struct i2c_client *client)
{
uint8_t cmd[4];
- uint8_t data[64] = {0};
+ uint8_t data[64];
- //=====================================
- // Read FW version : 0x0000_E303
- //=====================================
+ /*=====================================
+ Read FW version : 0x0000_E303
+ =====================================*/
cmd[3] = 0x00; cmd[2] = 0x00; cmd[1] = 0xE3; cmd[0] = 0x00;
himax_register_read(client, cmd, 1, data);
- ic_data->vendor_config_ver = data[3]<<8;
+ ic_data->vendor_config_ver = data[3] << 8;
cmd[3] = 0x00; cmd[2] = 0x00; cmd[1] = 0xE3; cmd[0] = 0x04;
himax_register_read(client, cmd, 1, data);
ic_data->vendor_config_ver = data[0] | ic_data->vendor_config_ver;
- I("CFG_VER : %X \n",ic_data->vendor_config_ver);
+ I("CFG_VER : %X\n", ic_data->vendor_config_ver);
cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x00; cmd[0] = 0x28;
himax_register_read(client, cmd, 1, data);
ic_data->vendor_fw_ver = data[0]<<8 | data[1];
- I("FW_VER : %X \n",ic_data->vendor_fw_ver);
+ I("FW_VER : %X\n", ic_data->vendor_fw_ver);
-
- return;
}
bool himax_ic_package_check(struct i2c_client *client)
{
-#if 0
+/*#if 0*/
+#ifdef HX_EN_CHECK_PATCH
uint8_t cmd[3];
uint8_t data[3];
@@ -1574,260 +1794,284 @@
memset(data, 0x00, sizeof(data));
if (i2c_himax_read(client, 0xD1, cmd, 3, HIMAX_I2C_RETRY_TIMES) < 0)
- return false ;
+ return false;
if (i2c_himax_read(client, 0x31, data, 3, HIMAX_I2C_RETRY_TIMES) < 0)
return false;
- if((data[0] == 0x85 && data[1] == 0x29))
- {
- IC_TYPE = HX_85XX_F_SERIES_PWON;
- IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC;
- //Himax: Set FW and CFG Flash Address
- FW_VER_MAJ_FLASH_ADDR = 64901; //0xFD85
- FW_VER_MAJ_FLASH_LENG = 1;
- FW_VER_MIN_FLASH_ADDR = 64902; //0xFD86
- FW_VER_MIN_FLASH_LENG = 1;
- CFG_VER_MAJ_FLASH_ADDR = 64928; //0xFDA0
- CFG_VER_MAJ_FLASH_LENG = 12;
- CFG_VER_MIN_FLASH_ADDR = 64940; //0xFDAC
- CFG_VER_MIN_FLASH_LENG = 12;
- I("Himax IC package 852x F\n");
- }
- if((data[0] == 0x85 && data[1] == 0x30) || (cmd[0] == 0x05 && cmd[1] == 0x85 && cmd[2] == 0x29))
- {
- IC_TYPE = HX_85XX_E_SERIES_PWON;
- IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC;
- //Himax: Set FW and CFG Flash Address
- FW_VER_MAJ_FLASH_ADDR = 133; //0x0085
- FW_VER_MAJ_FLASH_LENG = 1;
- FW_VER_MIN_FLASH_ADDR = 134; //0x0086
- FW_VER_MIN_FLASH_LENG = 1;
- CFG_VER_MAJ_FLASH_ADDR = 160; //0x00A0
- CFG_VER_MAJ_FLASH_LENG = 12;
- CFG_VER_MIN_FLASH_ADDR = 172; //0x00AC
- CFG_VER_MIN_FLASH_LENG = 12;
- I("Himax IC package 852x E\n");
- }
- else if((data[0] == 0x85 && data[1] == 0x31))
- {
- IC_TYPE = HX_85XX_ES_SERIES_PWON;
- IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC;
- //Himax: Set FW and CFG Flash Address
- FW_VER_MAJ_FLASH_ADDR = 133; //0x0085
- FW_VER_MAJ_FLASH_LENG = 1;
- FW_VER_MIN_FLASH_ADDR = 134; //0x0086
- FW_VER_MIN_FLASH_LENG = 1;
- CFG_VER_MAJ_FLASH_ADDR = 160; //0x00A0
- CFG_VER_MAJ_FLASH_LENG = 12;
- CFG_VER_MIN_FLASH_ADDR = 172; //0x00AC
- CFG_VER_MIN_FLASH_LENG = 12;
- I("Himax IC package 852x ES\n");
- }
- else if ((data[0] == 0x85 && data[1] == 0x28) || (cmd[0] == 0x04 && cmd[1] == 0x85 &&
- (cmd[2] == 0x26 || cmd[2] == 0x27 || cmd[2] == 0x28))) {
- IC_TYPE = HX_85XX_D_SERIES_PWON;
- IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC;
- //Himax: Set FW and CFG Flash Address
- FW_VER_MAJ_FLASH_ADDR = 133; // 0x0085
- FW_VER_MAJ_FLASH_LENG = 1;
- FW_VER_MIN_FLASH_ADDR = 134; // 0x0086
- FW_VER_MIN_FLASH_LENG = 1;
- CFG_VER_MAJ_FLASH_ADDR = 160; // 0x00A0
+ if ((data[0] == 0x85 && data[1] == 0x29)) {
+ IC_TYPE = HX_85XX_F_SERIES_PWON;
+ IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC;
+ /*Himax: Set FW and CFG Flash Address*/
+ FW_VER_MAJ_FLASH_ADDR = 64901; /*0xFD85*/
+ FW_VER_MAJ_FLASH_LENG = 1;
+ FW_VER_MIN_FLASH_ADDR = 64902; /*0xFD86*/
+ FW_VER_MIN_FLASH_LENG = 1;
+ CFG_VER_MAJ_FLASH_ADDR = 64928; /*0xFDA0*/
CFG_VER_MAJ_FLASH_LENG = 12;
- CFG_VER_MIN_FLASH_ADDR = 172; // 0x00AC
+ CFG_VER_MIN_FLASH_ADDR = 64940; /*0xFDAC*/
+ CFG_VER_MIN_FLASH_LENG = 12;
+ I("Himax IC package 852x F\n");
+ }
+ if ((data[0] == 0x85 && data[1] == 0x30)
+ || (cmd[0] == 0x05 && cmd[1] == 0x85 && cmd[2] == 0x29)) {
+ IC_TYPE = HX_85XX_E_SERIES_PWON;
+ IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC;
+ /*Himax: Set FW and CFG Flash Address*/
+ FW_VER_MAJ_FLASH_ADDR = 133; /*0x0085*/
+ FW_VER_MAJ_FLASH_LENG = 1;
+ FW_VER_MIN_FLASH_ADDR = 134; /*0x0086*/
+ FW_VER_MIN_FLASH_LENG = 1;
+ CFG_VER_MAJ_FLASH_ADDR = 160; /*0x00A0*/
+ CFG_VER_MAJ_FLASH_LENG = 12;
+ CFG_VER_MIN_FLASH_ADDR = 172; /*0x00AC*/
+ CFG_VER_MIN_FLASH_LENG = 12;
+ I("Himax IC package 852x E\n");
+ } else if ((data[0] == 0x85 && data[1] == 0x31)) {
+ IC_TYPE = HX_85XX_ES_SERIES_PWON;
+ IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC;
+ /*Himax: Set FW and CFG Flash Address*/
+ FW_VER_MAJ_FLASH_ADDR = 133; /*0x0085*/
+ FW_VER_MAJ_FLASH_LENG = 1;
+ FW_VER_MIN_FLASH_ADDR = 134; /*0x0086*/
+ FW_VER_MIN_FLASH_LENG = 1;
+ CFG_VER_MAJ_FLASH_ADDR = 160; /*0x00A0*/
+ CFG_VER_MAJ_FLASH_LENG = 12;
+ CFG_VER_MIN_FLASH_ADDR = 172; /*0x00AC*/
+ CFG_VER_MIN_FLASH_LENG = 12;
+ I("Himax IC package 852x ES\n");
+ } else if ((data[0] == 0x85 && data[1] == 0x28)
+ || (cmd[0] == 0x04 && cmd[1] == 0x85
+ && (cmd[2] == 0x26 || cmd[2] == 0x27
+ || cmd[2] == 0x28))) {
+ IC_TYPE = HX_85XX_D_SERIES_PWON;
+ IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC;
+ /*Himax: Set FW and CFG Flash Address*/
+ FW_VER_MAJ_FLASH_ADDR = 133; /*0x0085*/
+ FW_VER_MAJ_FLASH_LENG = 1;
+ FW_VER_MIN_FLASH_ADDR = 134; /*0x0086*/
+ FW_VER_MIN_FLASH_LENG = 1;
+ CFG_VER_MAJ_FLASH_ADDR = 160; /*0x00A0*/
+ CFG_VER_MAJ_FLASH_LENG = 12;
+ CFG_VER_MIN_FLASH_ADDR = 172; /* 0x00AC*/
CFG_VER_MIN_FLASH_LENG = 12;
I("Himax IC package 852x D\n");
- } else if ((data[0] == 0x85 && data[1] == 0x23) || (cmd[0] == 0x03 && cmd[1] == 0x85 &&
- (cmd[2] == 0x26 || cmd[2] == 0x27 || cmd[2] == 0x28 || cmd[2] == 0x29))) {
- IC_TYPE = HX_85XX_C_SERIES_PWON;
- IC_CHECKSUM = HX_TP_BIN_CHECKSUM_SW;
- //Himax: Set FW and CFG Flash Address
- FW_VER_MAJ_FLASH_ADDR = 133; // 0x0085
- FW_VER_MAJ_FLASH_LENG = 1;
- FW_VER_MIN_FLASH_ADDR = 134; // 0x0086
- FW_VER_MIN_FLASH_LENG = 1;
- CFG_VER_MAJ_FLASH_ADDR = 135; // 0x0087
+ } else if ((data[0] == 0x85 && data[1] == 0x23) ||
+ (cmd[0] == 0x03 && cmd[1] == 0x85 &&
+ (cmd[2] == 0x26 || cmd[2] == 0x27 ||
+ cmd[2] == 0x28 || cmd[2] == 0x29))) {
+ IC_TYPE = HX_85XX_C_SERIES_PWON;
+ IC_CHECKSUM = HX_TP_BIN_CHECKSUM_SW;
+ /*Himax: Set FW and CFG Flash Address*/
+ FW_VER_MAJ_FLASH_ADDR = 133; /*0x0085*/
+ FW_VER_MAJ_FLASH_LENG = 1;
+ FW_VER_MIN_FLASH_ADDR = 134; /*0x0086*/
+ FW_VER_MIN_FLASH_LENG = 1;
+ CFG_VER_MAJ_FLASH_ADDR = 135; /*0x0087*/
CFG_VER_MAJ_FLASH_LENG = 12;
- CFG_VER_MIN_FLASH_ADDR = 147; // 0x0093
+ CFG_VER_MIN_FLASH_ADDR = 147; /*0x0093*/
CFG_VER_MIN_FLASH_LENG = 12;
I("Himax IC package 852x C\n");
} else if ((data[0] == 0x85 && data[1] == 0x26) ||
- (cmd[0] == 0x02 && cmd[1] == 0x85 &&
- (cmd[2] == 0x19 || cmd[2] == 0x25 || cmd[2] == 0x26))) {
+ (cmd[0] == 0x02 && cmd[1] == 0x85 &&
+ (cmd[2] == 0x19 || cmd[2] == 0x25 || cmd[2] == 0x26))) {
IC_TYPE = HX_85XX_B_SERIES_PWON;
IC_CHECKSUM = HX_TP_BIN_CHECKSUM_SW;
- //Himax: Set FW and CFG Flash Address
- FW_VER_MAJ_FLASH_ADDR = 133; // 0x0085
- FW_VER_MAJ_FLASH_LENG = 1;
- FW_VER_MIN_FLASH_ADDR = 728; // 0x02D8
- FW_VER_MIN_FLASH_LENG = 1;
- CFG_VER_MAJ_FLASH_ADDR = 692; // 0x02B4
+ /*Himax: Set FW and CFG Flash Address*/
+ FW_VER_MAJ_FLASH_ADDR = 133; /*0x0085*/
+ FW_VER_MAJ_FLASH_LENG = 1;
+ FW_VER_MIN_FLASH_ADDR = 728; /*0x02D8*/
+ FW_VER_MIN_FLASH_LENG = 1;
+ CFG_VER_MAJ_FLASH_ADDR = 692; /*0x02B4*/
CFG_VER_MAJ_FLASH_LENG = 3;
- CFG_VER_MIN_FLASH_ADDR = 704; // 0x02C0
+ CFG_VER_MIN_FLASH_ADDR = 704; /*0x02C0*/
CFG_VER_MIN_FLASH_LENG = 3;
I("Himax IC package 852x B\n");
} else if ((data[0] == 0x85 && data[1] == 0x20) || (cmd[0] == 0x01 &&
- cmd[1] == 0x85 && cmd[2] == 0x19)) {
+ cmd[1] == 0x85 && cmd[2] == 0x19)) {
IC_TYPE = HX_85XX_A_SERIES_PWON;
IC_CHECKSUM = HX_TP_BIN_CHECKSUM_SW;
I("Himax IC package 852x A\n");
} else {
E("Himax IC package incorrect!!\n");
- }*/
+ }
#else
- IC_TYPE = HX_83100_SERIES_PWON;
- IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC;
- //Himax: Set FW and CFG Flash Address
- FW_VER_MAJ_FLASH_ADDR = 57384; //0xE028
- FW_VER_MAJ_FLASH_LENG = 1;
- FW_VER_MIN_FLASH_ADDR = 57385; //0xE029
- FW_VER_MIN_FLASH_LENG = 1;
- CFG_VER_MAJ_FLASH_ADDR = 58115; //0xE303
- CFG_VER_MAJ_FLASH_LENG = 1;
- CFG_VER_MIN_FLASH_ADDR = 58116; //0xE304
- CFG_VER_MIN_FLASH_LENG = 1;
+ IC_TYPE = HX_83100_SERIES_PWON;
+ IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC;
+ /*Himax: Set FW and CFG Flash Address*/
+ FW_VER_MAJ_FLASH_ADDR = 57384; /*0xE028*/
+ FW_VER_MAJ_FLASH_LENG = 1;
+ FW_VER_MIN_FLASH_ADDR = 57385; /*0xE029*/
+ FW_VER_MIN_FLASH_LENG = 1;
+ CFG_VER_MAJ_FLASH_ADDR = 58115; /*0xE303*/
+ CFG_VER_MAJ_FLASH_LENG = 1;
+ CFG_VER_MIN_FLASH_ADDR = 58116; /*0xE304*/
+ CFG_VER_MIN_FLASH_LENG = 1;
I("Himax IC package 83100_in\n");
#endif
return true;
}
-void himax_read_event_stack(struct i2c_client *client, uint8_t *buf, uint8_t length)
+void himax_read_event_stack(struct i2c_client *client,
+uint8_t *buf, uint8_t length)
{
uint8_t cmd[4];
- cmd[3] = 0x90; cmd[2] = 0x06; cmd[1] = 0x00; cmd[0] = 0x00;
- if ( i2c_himax_write(client, 0x00 ,cmd, 4, HIMAX_I2C_RETRY_TIMES) < 0) {
- E("%s: i2c access fail!\n", __func__);
+ cmd[3] = 0x90; cmd[2] = 0x06;
+ cmd[1] = 0x00; cmd[0] = 0x00;
+ if (i2c_himax_write(client, 0x00,
+ cmd, 4, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
}
- cmd[0] = 0x00;
- if ( i2c_himax_write(client, 0x0C ,cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
- E("%s: i2c access fail!\n", __func__);
+ cmd[0] = 0x00;
+ if (i2c_himax_write(client, 0x0C,
+ cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
}
- i2c_himax_read(client, 0x08, buf, length, HIMAX_I2C_RETRY_TIMES);
+ i2c_himax_read(client, 0x08,
+ buf, length, HIMAX_I2C_RETRY_TIMES);
}
-#if 0
-static void himax_83100_Flash_Write(uint8_t * reg_byte, uint8_t * write_data)
+/*#if 0*/
+#ifdef HX_EN_CHECK_PATCH
+static void himax_83100_Flash_Write(uint8_t *reg_byte, uint8_t *write_data)
{
uint8_t tmpbyte[2];
- if ( i2c_himax_write(private_ts->client, 0x00 ,®_byte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ if (i2c_himax_write(private_ts->client, 0x00,
+ ®_byte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
- if ( i2c_himax_write(private_ts->client, 0x01 ,®_byte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ if (i2c_himax_write(private_ts->client, 0x01,
+ ®_byte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
- if ( i2c_himax_write(private_ts->client, 0x02 ,®_byte[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ if (i2c_himax_write(private_ts->client, 0x02,
+ ®_byte[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
- if ( i2c_himax_write(private_ts->client, 0x03 ,®_byte[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ if (i2c_himax_write(private_ts->client,
+ 0x03, ®_byte[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
- if ( i2c_himax_write(private_ts->client, 0x04 ,&write_data[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ if (i2c_himax_write(private_ts->client,
+ 0x04, &write_data[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
- if ( i2c_himax_write(private_ts->client, 0x05 ,&write_data[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ if (i2c_himax_write(private_ts->client,
+ 0x05, &write_data[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
- if ( i2c_himax_write(private_ts->client, 0x06 ,&write_data[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ if (i2c_himax_write(private_ts->client,
+ 0x06, &write_data[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
- if ( i2c_himax_write(private_ts->client, 0x07 ,&write_data[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ if (i2c_himax_write(private_ts->client,
+ 0x07, &write_data[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
- if (isBusrtOn == false)
- {
- tmpbyte[0] = 0x01;
- if ( i2c_himax_write(private_ts->client, 0x0C ,&tmpbyte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
- E("%s: i2c access fail!\n", __func__);
- return;
+ if (isBusrtOn == false) {
+ tmpbyte[0] = 0x01;
+ if (i2c_himax_write(private_ts->client,
+ 0x0C, &tmpbyte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
}
- }
+ }
}
#endif
-#if 0
-static void himax_83100_Flash_Burst_Write(uint8_t * reg_byte, uint8_t * write_data)
+/*#if 0*/
+#ifdef HX_EN_CHECK_PATCH
+static void himax_83100_Flash_Burst_Write
+(uint8_t *reg_byte, uint8_t *write_data)
{
- //uint8_t tmpbyte[2];
+ /*uint8_t tmpbyte[2];*/
int i = 0;
- if ( i2c_himax_write(private_ts->client, 0x00 ,®_byte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ if (i2c_himax_write(private_ts->client, 0x00,
+ ®_byte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
- if ( i2c_himax_write(private_ts->client, 0x01 ,®_byte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ if (i2c_himax_write(private_ts->client, 0x01,
+ ®_byte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
- if ( i2c_himax_write(private_ts->client, 0x02 ,®_byte[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ if (i2c_himax_write(private_ts->client, 0x02,
+ ®_byte[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
- if ( i2c_himax_write(private_ts->client, 0x03 ,®_byte[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ if (i2c_himax_write(private_ts->client, 0x03,
+ ®_byte[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
- // Write 256 bytes with continue burst mode
- for (i = 0; i < 256; i = i + 4)
+ /*Write 256 bytes with continue burst mode*/
+ for (i = 0 ; i < 256 ; i = i + 4) {
+ if (i2c_himax_write(private_ts->client,
+ 0x04, &write_data[i], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
+ }
+
+ if (i2c_himax_write(private_ts->client, 0x05,
+ &write_data[i+1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
+ }
+
+ if (i2c_himax_write(private_ts->client, 0x06,
+ &write_data[i+2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
+ }
+
+ if (i2c_himax_write(private_ts->client, 0x07,
+ &write_data[i+3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
+ }
+ }
+
+ /*if (isBusrtOn == false)
{
- if ( i2c_himax_write(private_ts->client, 0x04 ,&write_data[i], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
- E("%s: i2c access fail!\n", __func__);
- return;
- }
-
- if ( i2c_himax_write(private_ts->client, 0x05 ,&write_data[i+1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
- E("%s: i2c access fail!\n", __func__);
- return;
- }
-
- if ( i2c_himax_write(private_ts->client, 0x06 ,&write_data[i+2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
- E("%s: i2c access fail!\n", __func__);
- return;
- }
-
- if ( i2c_himax_write(private_ts->client, 0x07 ,&write_data[i+3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
- E("%s: i2c access fail!\n", __func__);
- return;
- }
- }
-
- //if (isBusrtOn == false)
- //{
- // tmpbyte[0] = 0x01;
- // if ( i2c_himax_write(private_ts->client, 0x0C ,&tmpbyte[0], 1, 3) < 0) {
- // E("%s: i2c access fail!\n", __func__);
- // return;
- // }
- //}
+ tmpbyte[0] = 0x01;
+ if (i2c_himax_write(private_ts->client,
+ 0x0C, &tmpbyte[0], 1, 3) < 0) {
+ E("%s: i2c access fail!\n", __func__);
+ return;
+ }*/
}
#endif
-#if 0
+/*#if 0*/
+#ifdef HX_EN_CHECK_PATCH
static bool himax_83100_Verify(uint8_t *FW_File, int FW_Size)
{
uint8_t tmp_addr[4];
@@ -1835,49 +2079,51 @@
uint8_t out_buffer[20];
uint8_t in_buffer[260];
- int fail_addr=0, fail_cnt=0;
+ int fail_addr = 0, fail_cnt = 0;
int page_prog_start = 0;
int i = 0;
himax_interface_on(private_ts->client);
himax_burst_enable(private_ts->client, 0);
- //=====================================
- // SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
- //=====================================
- tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
- tmp_data[3] = 0x00; tmp_data[2] = 0x02; tmp_data[1] = 0x07; tmp_data[0] = 0x80;
+ /*=====================================
+ SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
+ =====================================*/
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x02;
+ tmp_data[1] = 0x07; tmp_data[0] = 0x80;
himax_83100_Flash_Write(tmp_addr, tmp_data);
- for (page_prog_start = 0; page_prog_start < FW_Size; page_prog_start = page_prog_start + 256)
- {
- //=================================
- // SPI Transfer Control
- // Set 256 bytes page read : 0x8000_0020 ==> 0x6940_02FF
- // Set read start address : 0x8000_0028 ==> 0x0000_0000
- // Set command : 0x8000_0024 ==> 0x0000_003B
- //=================================
- tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
- tmp_data[3] = 0x69; tmp_data[2] = 0x40; tmp_data[1] = 0x02; tmp_data[0] = 0xFF;
+ for (page_prog_start = 0; page_prog_start < FW_Size;
+ page_prog_start = page_prog_start + 256) {
+ /*=====================================
+ SPI Transfer Control
+ Set 256 bytes page read : 0x8000_0020 ==> 0x6940_02FF
+ Set read start address : 0x8000_0028 ==> 0x0000_0000
+ Set command : 0x8000_0024 ==> 0x0000_003B
+ =====================================*/
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+ tmp_data[3] = 0x69; tmp_data[2] = 0x40;
+ tmp_data[1] = 0x02; tmp_data[0] = 0xFF;
himax_83100_Flash_Write(tmp_addr, tmp_data);
- tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x28;
- if (page_prog_start < 0x100)
- {
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x28;
+ if (page_prog_start < 0x100) {
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = (uint8_t)page_prog_start;
- }
- else if (page_prog_start >= 0x100 && page_prog_start < 0x10000)
- {
+ } else if (page_prog_start >= 0x100
+ && page_prog_start < 0x10000) {
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = (uint8_t)(page_prog_start >> 8);
tmp_data[0] = (uint8_t)page_prog_start;
- }
- else if (page_prog_start >= 0x10000 && page_prog_start < 0x1000000)
- {
+ } else if (page_prog_start >= 0x10000
+ && page_prog_start < 0x1000000) {
tmp_data[3] = 0x00;
tmp_data[2] = (uint8_t)(page_prog_start >> 16);
tmp_data[1] = (uint8_t)(page_prog_start >> 8);
@@ -1885,65 +2131,73 @@
}
himax_83100_Flash_Write(tmp_addr, tmp_data);
- tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
- tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x3B;
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x00; tmp_data[0] = 0x3B;
himax_83100_Flash_Write(tmp_addr, tmp_data);
- //==================================
- // AHB_I2C Burst Read
- // Set SPI data register : 0x8000_002C ==> 0x00
- //==================================
+ /*==================================
+ AHB_I2C Burst Read
+ Set SPI data register : 0x8000_002C ==> 0x00
+ ==================================*/
out_buffer[0] = 0x2C;
out_buffer[1] = 0x00;
out_buffer[2] = 0x00;
out_buffer[3] = 0x80;
- i2c_himax_write(private_ts->client, 0x00 ,out_buffer, 4, HIMAX_I2C_RETRY_TIMES);
+ i2c_himax_write(private_ts->client, 0x00,
+ out_buffer, 4, HIMAX_I2C_RETRY_TIMES);
- //==================================
- // Read access : 0x0C ==> 0x00
- //==================================
+ /*==================================
+ Read access : 0x0C ==> 0x00
+ ==================================*/
out_buffer[0] = 0x00;
- i2c_himax_write(private_ts->client, 0x0C ,out_buffer, 1, HIMAX_I2C_RETRY_TIMES);
+ i2c_himax_write(private_ts->client, 0x0C,
+ out_buffer, 1, HIMAX_I2C_RETRY_TIMES);
- //==================================
- // Read 128 bytes two times
- //==================================
- i2c_himax_read(private_ts->client, 0x08 ,in_buffer, 128, HIMAX_I2C_RETRY_TIMES);
+ /*==================================
+ Read 128 bytes two times
+ ==================================*/
+ i2c_himax_read(private_ts->client, 0x08,
+ in_buffer, 128, HIMAX_I2C_RETRY_TIMES);
for (i = 0; i < 128; i++)
flash_buffer[i + page_prog_start] = in_buffer[i];
- i2c_himax_read(private_ts->client, 0x08 ,in_buffer, 128, HIMAX_I2C_RETRY_TIMES);
+ i2c_himax_read(private_ts->client, 0x08,
+ in_buffer, 128, HIMAX_I2C_RETRY_TIMES);
for (i = 0; i < 128; i++)
- flash_buffer[(i + 128) + page_prog_start] = in_buffer[i];
+ flash_buffer[(i + 128)
+ + page_prog_start] = in_buffer[i];
- //tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x2C;
- //himax_register_read(tmp_addr, 32, out in_buffer);
- //for (int i = 0; i < 128; i++)
- // flash_buffer[i + page_prog_start] = in_buffer[i];
- //tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x2C;
- //himax_register_read(tmp_addr, 32, out in_buffer);
- //for (int i = 0; i < 128; i++)
- // flash_buffer[i + page_prog_start] = in_buffer[i];
-
+ /*tmp_addr[3] = 0x80;
+ tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x2C;
+ himax_register_read(tmp_addr, 32, out in_buffer);
+ for (int i = 0; i < 128; i++)
+ flash_buffer[i + page_prog_start] = in_buffer[i];
+ tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x00; tmp_addr[0] = 0x2C;
+ himax_register_read(tmp_addr, 32, out in_buffer);
+ for (int i = 0; i < 128; i++)
+ flash_buffer[i + page_prog_start] = in_buffer[i];
+ */
I("%s:Verify Progress: %x\n", __func__, page_prog_start);
}
fail_cnt = 0;
- for (i = 0; i < FW_Size; i++)
- {
- if (FW_File[i] != flash_buffer[i])
- {
+ for (i = 0; i < FW_Size; i++) {
+ if (FW_File[i] != flash_buffer[i]) {
if (fail_cnt == 0)
fail_addr = i;
fail_cnt++;
- //E("%s Fail Block:%x\n", __func__, i);
- //return false;
+ /*E("%s Fail Block:%x\n", __func__, i);
+ return false;*/
}
}
- if (fail_cnt > 0)
- {
- E("%s:Start Fail Block:%x and fail block count=%x\n" , __func__,fail_addr,fail_cnt);
+ if (fail_cnt > 0) {
+ E("%s:Start Fail Block:%x and fail block count=%x\n",
+ __func__, fail_addr, fail_cnt);
return false;
}
@@ -1959,56 +2213,60 @@
int cnt = 0;
unsigned char tmp_addr[4];
unsigned char tmp_data[4];
- uint8_t max_i2c_size = 32;
+ uint8_t max_i2c_size = 32;
int total_size = ic_data->HX_TX_NUM * ic_data->HX_RX_NUM * 2;
int total_size_4bytes = total_size / 4;
int total_read_times = 0;
unsigned long address = 0x08000468;
- tmp_addr[3] = 0x08; tmp_addr[2] = 0x00; tmp_addr[1] = 0x04; tmp_addr[0] = 0x64;
- tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x5A; tmp_data[0] = 0xA5;
+
+ tmp_addr[3] = 0x08; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x04; tmp_addr[0] = 0x64;
+ tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+ tmp_data[1] = 0x5A; tmp_data[0] = 0xA5;
himax_flash_write_burst(client, tmp_addr, tmp_data);
- do
- {
+ do {
cnt++;
himax_register_read(client, tmp_addr, 1, tmp_data);
- usleep_range(10000, 20000);
+ usleep_range(9999, 10000);
} while ((tmp_data[1] != 0xA5 || tmp_data[0] != 0x5A) && cnt < 100);
- tmp_addr[3] = 0x08; tmp_addr[2] = 0x00; tmp_addr[1] = 0x04; tmp_addr[0] = 0x68;
- if (total_size_4bytes % max_i2c_size == 0)
- {
+ tmp_addr[3] = 0x08; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x04; tmp_addr[0] = 0x68;
+ if (total_size_4bytes % max_i2c_size == 0)
total_read_times = total_size_4bytes / max_i2c_size;
- }
else
- {
total_read_times = total_size_4bytes / max_i2c_size + 1;
- }
- for (i = 0; i < (total_read_times); i++)
- {
- if ( total_size_4bytes >= max_i2c_size)
- {
- himax_register_read(client, tmp_addr, max_i2c_size, &info_data[i*max_i2c_size*4]);
+
+ for (i = 0 ; i < (total_read_times) ; i++) {
+ if (total_size_4bytes >= max_i2c_size) {
+ himax_register_read(client, tmp_addr,
+ max_i2c_size,
+ &info_data[i*max_i2c_size*4]);
total_size_4bytes = total_size_4bytes - max_i2c_size;
+ } else {
+ himax_register_read(client, tmp_addr,
+ total_size_4bytes % max_i2c_size,
+ &info_data[i*max_i2c_size*4]);
}
- else
- {
- himax_register_read(client, tmp_addr, total_size_4bytes % max_i2c_size, &info_data[i*max_i2c_size*4]);
- }
- address += max_i2c_size*4;
- tmp_addr[1] = (uint8_t)((address>>8)&0x00FF);
- tmp_addr[0] = (uint8_t)((address)&0x00FF);
+ address += max_i2c_size * 4;
+ tmp_addr[1] = (uint8_t)((address>>8) & 0x00FF);
+ tmp_addr[0] = (uint8_t)((address) & 0x00FF);
}
- tmp_addr[3] = 0x08; tmp_addr[2] = 0x00; tmp_addr[1] = 0x04; tmp_addr[0] = 0x64;
- tmp_data[3] = 0x11; tmp_data[2] = 0x22; tmp_data[1] = 0x33; tmp_data[0] = 0x44;
+ tmp_addr[3] = 0x08; tmp_addr[2] = 0x00;
+ tmp_addr[1] = 0x04; tmp_addr[0] = 0x64;
+ tmp_data[3] = 0x11; tmp_data[2] = 0x22;
+ tmp_data[1] = 0x33; tmp_data[0] = 0x44;
himax_flash_write_burst(client, tmp_addr, tmp_data);
}
-//ts_work
-int cal_data_len(int raw_cnt_rmd, int HX_MAX_PT, int raw_cnt_max){
+/*ts_work*/
+int cal_data_len(int raw_cnt_rmd, int HX_MAX_PT, int raw_cnt_max)
+{
int RawDataLen;
- if (raw_cnt_rmd != 0x00) {
- RawDataLen = 124 - ((HX_MAX_PT+raw_cnt_max+3)*4) - 1;
- }else{
- RawDataLen = 124 - ((HX_MAX_PT+raw_cnt_max+2)*4) - 1;
- }
+
+ if (raw_cnt_rmd != 0x00)
+ RawDataLen = 124 - ((HX_MAX_PT + raw_cnt_max + 3) * 4) - 1;
+ else
+ RawDataLen = 124 - ((HX_MAX_PT + raw_cnt_max + 2) * 4) - 1;
+
return RawDataLen;
}
@@ -2016,40 +2274,40 @@
{
uint8_t cmd[4];
- if(length > 56)
+ if (length > 56)
length = 124;
- //=====================
- //AHB I2C Burst Read
- //=====================
+ /*=====================
+ AHB I2C Burst Read
+ =====================*/
cmd[0] = 0x31;
- if ( i2c_himax_write(client, 0x13 ,cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ if (i2c_himax_write(client, 0x13, cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
goto err_workqueue_out;
}
cmd[0] = 0x10;
- if ( i2c_himax_write(client, 0x0D ,cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ if (i2c_himax_write(client, 0x0D, cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
goto err_workqueue_out;
}
- //=====================
- //Read event stack
- //=====================
+ /*=====================
+ Read event stack
+ =====================*/
cmd[3] = 0x90; cmd[2] = 0x06; cmd[1] = 0x00; cmd[0] = 0x00;
- if ( i2c_himax_write(client, 0x00 ,cmd, 4, HIMAX_I2C_RETRY_TIMES) < 0) {
+ if (i2c_himax_write(client, 0x00, cmd, 4, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
goto err_workqueue_out;
}
cmd[0] = 0x00;
- if ( i2c_himax_write(client, 0x0C ,cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+ if (i2c_himax_write(client, 0x0C, cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
goto err_workqueue_out;
}
- i2c_himax_read(client, 0x08, buf, length,HIMAX_I2C_RETRY_TIMES);
+ i2c_himax_read(client, 0x08, buf, length, HIMAX_I2C_RETRY_TIMES);
return 1;
-
- err_workqueue_out:
+
+err_workqueue_out:
return 0;
}
@@ -2057,62 +2315,67 @@
{
return 1;
}
-bool diag_check_sum( uint8_t hx_touch_info_size, uint8_t *buf) //return checksum value
+bool diag_check_sum(uint8_t hx_touch_info_size,
+uint8_t *buf) /*return checksum value*/
{
uint16_t check_sum_cal = 0;
int i;
- //Check 124th byte CRC
- for (i = hx_touch_info_size, check_sum_cal = 0; i < 124; i=i+2)
- {
- check_sum_cal += (buf[i+1]*256 + buf[i]);
- }
- if (check_sum_cal % 0x10000 != 0)
- {
- I("%s: diag check sum fail! check_sum_cal=%X, hx_touch_info_size=%d, \n",__func__,check_sum_cal, hx_touch_info_size);
+ /*Check 124th byte CRC*/
+ for (i = hx_touch_info_size, check_sum_cal = 0 ; i < 124 ; i = i + 2)
+ check_sum_cal += (buf[i + 1] * 256 + buf[i]);
+
+ if (check_sum_cal % 0x10000 != 0) {
+ I("%s:diag chksum fail!check_sum_cal=%X,hx_touchinfo_sz=%d,\n",
+ __func__, check_sum_cal, hx_touch_info_size);
return 0;
}
return 1;
}
-
-void diag_parse_raw_data(int hx_touch_info_size, int RawDataLen, int mul_num, int self_num, uint8_t *buf, uint8_t diag_cmd, int16_t *mutual_data, int16_t *self_data)
+void diag_parse_raw_data(int hx_touch_info_size,
+int RawDataLen, int mul_num, int self_num, uint8_t *buf,
+uint8_t diag_cmd, int16_t *mutual_data, int16_t *self_data)
{
int RawDataLen_word;
int index = 0;
- int temp1, temp2,i;
-
- if (buf[hx_touch_info_size] == 0x3A && buf[hx_touch_info_size+1] == 0xA3 && buf[hx_touch_info_size+2] > 0 && buf[hx_touch_info_size+3] == diag_cmd+5 )
- {
- RawDataLen_word = RawDataLen/2;
- index = (buf[hx_touch_info_size+2] - 1) * RawDataLen_word;
- //I("Header[%d]: %x, %x, %x, %x, mutual: %d, self: %d\n", index, buf[56], buf[57], buf[58], buf[59], mul_num, self_num);
- for (i = 0; i < RawDataLen_word; i++)
- {
+ int temp1, temp2, i;
+
+ if (buf[hx_touch_info_size] == 0x3A &&
+ buf[hx_touch_info_size + 1] == 0xA3 &&
+ buf[hx_touch_info_size + 2] > 0 &&
+ buf[hx_touch_info_size + 3] == diag_cmd + 5) {
+ RawDataLen_word = RawDataLen / 2;
+ index = (buf[hx_touch_info_size + 2] - 1) * RawDataLen_word;
+ /*I("Header[%d]: %x, %x, %x, %x, mutual: %d, self: %d\n",
+ index, buf[56], buf[57], buf[58], buf[59], mul_num, self_num);*/
+ for (i = 0; i < RawDataLen_word; i++) {
temp1 = index + i;
- if (temp1 < mul_num)
- { //mutual
- mutual_data[index + i] = buf[i*2 + hx_touch_info_size+4+1]*256 + buf[i*2 + hx_touch_info_size+4]; //4: RawData Header, 1:HSB
- }
- else
- {//self
+ if (temp1 < mul_num) { /*mutual*/
+ /*4: RawData Header, 1:HSB */
+ mutual_data[index + i]
+ = buf[i*2 + hx_touch_info_size + 4 + 1]
+ * 256
+ + buf[i * 2 + hx_touch_info_size + 4];
+ } else { /*self*/
temp1 = i + index;
temp2 = self_num + mul_num;
-
- if (temp1 >= temp2)
- {
- break;
- }
- self_data[i+index-mul_num] = buf[i*2 + hx_touch_info_size+4]; //4: RawData Header
- self_data[i+index-mul_num+1] = buf[i*2 + hx_touch_info_size+4+1];
+ if (temp1 >= temp2)
+ break;
+
+ /*4: RawData Header*/
+ self_data[i + index - mul_num]
+ = buf[i * 2 + hx_touch_info_size + 4];
+ self_data[i + index - mul_num + 1]
+ = buf[i * 2 + hx_touch_info_size + 4 + 1];
}
}
- }
- else
- {
+ } else {
I("[HIMAX TP MSG]%s: header format is wrong!\n", __func__);
- I("Header[%d]: %x, %x, %x, %x, mutual: %d, self: %d\n", index, buf[56], buf[57], buf[58], buf[59], mul_num, self_num);
+ I("Header[%d]: %x, %x, %x, %x, mutual: %d, self: %d\n",
+ index, buf[56], buf[57], buf[58], buf[59],
+ mul_num, self_num);
}
}
diff --git a/drivers/input/touchscreen/hxchipset/himax_ic.h b/drivers/input/touchscreen/hxchipset/himax_ic.h
index 18cd12b..ce7d0d4 100644
--- a/drivers/input/touchscreen/hxchipset/himax_ic.h
+++ b/drivers/input/touchscreen/hxchipset/himax_ic.h
@@ -18,7 +18,6 @@
#include <linux/slab.h>
-
#define HX_85XX_A_SERIES_PWON 1
#define HX_85XX_B_SERIES_PWON 2
#define HX_85XX_C_SERIES_PWON 3
@@ -40,43 +39,110 @@
};
int himax_hand_shaking(struct i2c_client *client);
-void himax_set_SMWP_enable(struct i2c_client *client,uint8_t SMWP_enable);
-void himax_get_SMWP_enable(struct i2c_client *client,uint8_t *tmp_data);
-void himax_set_HSEN_enable(struct i2c_client *client,uint8_t HSEN_enable);
-void himax_get_HSEN_enable(struct i2c_client *client,uint8_t *tmp_data);
+void himax_set_SMWP_enable(struct i2c_client *client, uint8_t SMWP_enable);
+void himax_get_SMWP_enable(struct i2c_client *client, uint8_t *tmp_data);
+void himax_set_HSEN_enable(struct i2c_client *client, uint8_t HSEN_enable);
+void himax_get_HSEN_enable(struct i2c_client *client, uint8_t *tmp_data);
void himax_diag_register_set(struct i2c_client *client, uint8_t diag_command);
-void himax_flash_dump_func(struct i2c_client *client, uint8_t local_flash_command, int Flash_Size, uint8_t *flash_buffer);
+
+void himax_flash_dump_func(struct i2c_client *client,
+uint8_t local_flash_command, int Flash_Size, uint8_t *flash_buffer);
+
int himax_chip_self_test(struct i2c_client *client);
-int himax_burst_enable(struct i2c_client *client, uint8_t auto_add_4_byte); ////himax_83100_BURST_INC0_EN
-void himax_register_read(struct i2c_client *client, uint8_t *read_addr, int read_length, uint8_t *read_data); ////RegisterRead83100
-void himax_flash_read(struct i2c_client *client, uint8_t *reg_byte, uint8_t *read_data); ////himax_83100_Flash_Read
-void himax_flash_write_burst(struct i2c_client *client, uint8_t * reg_byte, uint8_t * write_data); ////himax_83100_Flash_Write_Burst
-int himax_flash_write_burst_lenth(struct i2c_client *client, uint8_t *reg_byte, uint8_t *write_data, int length); ////himax_83100_Flash_Write_Burst_lenth
-int himax_register_write(struct i2c_client *client, uint8_t *write_addr, int write_length, uint8_t *write_data); ////RegisterWrite83100
-void himax_sense_off(struct i2c_client *client); ////himax_83100_SenseOff
-void himax_interface_on(struct i2c_client *client); ////himax_83100_Interface_on
+
+/*himax_83100_BURST_INC0_EN*/
+int himax_burst_enable(struct i2c_client *client, uint8_t auto_add_4_byte);
+
+/*RegisterRead83100*/
+void himax_register_read(struct i2c_client *client,
+ uint8_t *read_addr, int read_length, uint8_t *read_data);
+
+/*himax_83100_Flash_Read*/
+void himax_flash_read(struct i2c_client *client,
+ uint8_t *reg_byte, uint8_t *read_data);
+
+/*himax_83100_Flash_Write_Burst*/
+void himax_flash_write_burst(struct i2c_client *client,
+ uint8_t *reg_byte, uint8_t *write_data);
+
+/*himax_83100_Flash_Write_Burst_length*/
+int himax_flash_write_burst_length(struct i2c_client *client,
+ uint8_t *reg_byte, uint8_t *write_data, int length);
+
+/*RegisterWrite83100*/
+int himax_register_write(struct i2c_client *client,
+ uint8_t *write_addr, int write_length, uint8_t *write_data);
+
+/*himax_83100_SenseOff*/
+void himax_sense_off(struct i2c_client *client);
+/*himax_83100_Interface_on*/
+void himax_interface_on(struct i2c_client *client);
bool wait_wip(struct i2c_client *client, int Timing);
-void himax_sense_on(struct i2c_client *client, uint8_t FlashMode); ////himax_83100_SenseOn
-void himax_chip_erase(struct i2c_client *client); ////himax_83100_Chip_Erase
-bool himax_block_erase(struct i2c_client *client); ////himax_83100_Block_Erase
-bool himax_sector_erase(struct i2c_client *client, int start_addr); ////himax_83100_Sector_Erase
-void himax_sram_write(struct i2c_client *client, uint8_t *FW_content); ////himax_83100_Sram_Write
-bool himax_sram_verify(struct i2c_client *client, uint8_t *FW_File, int FW_Size); ////himax_83100_Sram_Verify
-void himax_flash_programming(struct i2c_client *client, uint8_t *FW_content, int FW_Size); ////himax_83100_Flash_Programming
-bool himax_check_chip_version(struct i2c_client *client); ////himax_83100_CheckChipVersion
-int himax_check_CRC(struct i2c_client *client, int mode); ////himax_83100_Check_CRC
-bool Calculate_CRC_with_AP(unsigned char *FW_content , int CRC_from_FW, int mode);
-int fts_ctpm_fw_upgrade_with_sys_fs_60k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref);
-int fts_ctpm_fw_upgrade_with_sys_fs_64k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref);
-int fts_ctpm_fw_upgrade_with_sys_fs_124k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref);
-int fts_ctpm_fw_upgrade_with_sys_fs_128k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref);
+
+/*himax_83100_SenseOn*/
+void himax_sense_on(struct i2c_client *client,
+ uint8_t FlashMode);
+
+/*himax_83100_Chip_Erase*/
+void himax_chip_erase(struct i2c_client *client);
+/*himax_83100_Block_Erase*/
+bool himax_block_erase(struct i2c_client *client);
+
+/*himax_83100_Sector_Erase*/
+bool himax_sector_erase(struct i2c_client *client, int start_addr);
+
+/*himax_83100_Sram_Write*/
+void himax_sram_write(struct i2c_client *client, uint8_t *FW_content);
+
+/*himax_83100_Sram_Verify*/
+bool himax_sram_verify(struct i2c_client *client,
+ uint8_t *FW_File, int FW_Size);
+
+/*himax_83100_Flash_Programming*/
+void himax_flash_programming(struct i2c_client *client,
+ uint8_t *FW_content, int FW_Size);
+
+/*himax_83100_CheckChipVersion*/
+bool himax_check_chip_version(struct i2c_client *client);
+
+/*himax_83100_Check_CRC*/
+int himax_check_CRC(struct i2c_client *client, int mode);
+
+bool Calculate_CRC_with_AP(unsigned char *FW_content,
+ int CRC_from_FW, int mode);
+
+int fts_ctpm_fw_upgrade_with_sys_fs_60k(struct i2c_client *client,
+ unsigned char *fw, int len, bool change_iref);
+
+int fts_ctpm_fw_upgrade_with_sys_fs_64k(struct i2c_client *client,
+ unsigned char *fw, int len, bool change_iref);
+
+int fts_ctpm_fw_upgrade_with_sys_fs_124k(struct i2c_client *client,
+ unsigned char *fw, int len, bool change_iref);
+
+int fts_ctpm_fw_upgrade_with_sys_fs_128k(struct i2c_client *client,
+ unsigned char *fw, int len, bool change_iref);
+
void himax_touch_information(struct i2c_client *client);
void himax_read_FW_ver(struct i2c_client *client);
bool himax_ic_package_check(struct i2c_client *client);
-void himax_read_event_stack(struct i2c_client *client, uint8_t *buf, uint8_t length);
+
+void himax_read_event_stack(struct i2c_client *client,
+ uint8_t *buf, uint8_t length);
+
int cal_data_len(int raw_cnt_rmd, int HX_MAX_PT, int raw_cnt_max);
bool read_event_stack(struct i2c_client *client, uint8_t *buf_ts, int length);
bool post_read_event_stack(struct i2c_client *client);
-bool diag_check_sum( uint8_t hx_touch_info_size, uint8_t *buf_ts); //return checksum value
-void diag_parse_raw_data(int hx_touch_info_size, int RawDataLen, int mul_num, int self_num, uint8_t *buf_ts, uint8_t diag_cmd, int16_t *mutual_data, int16_t *self_data);
-void himax_get_DSRAM_data(struct i2c_client *client, uint8_t *info_data);
\ No newline at end of file
+
+/*return checksum value*/
+bool diag_check_sum(uint8_t hx_touch_info_size, uint8_t *buf_ts);
+
+void diag_parse_raw_data(int hx_touch_info_size, int RawDataLen,
+ int mul_num, int self_num, uint8_t *buf_ts,
+ uint8_t diag_cmd, int16_t *mutual_data, int16_t *self_data);
+
+void himax_get_DSRAM_data(struct i2c_client *client, uint8_t *info_data);
+extern struct himax_ts_data *private_ts;
+extern struct himax_ic_data *ic_data;
+
+int himax_load_CRC_bin_file(struct i2c_client *client);
diff --git a/drivers/input/touchscreen/hxchipset/himax_platform.c b/drivers/input/touchscreen/hxchipset/himax_platform.c
index 7e8a1d6..309bb5e 100644
--- a/drivers/input/touchscreen/hxchipset/himax_platform.c
+++ b/drivers/input/touchscreen/hxchipset/himax_platform.c
@@ -16,6 +16,13 @@
#include "himax_platform.h"
#include "himax_common.h"
+#if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG)
+#define D(x...) pr_info("[HXTP][DEBUG] " x)
+#define I(x...) pr_info("[HXTP][INFO] " x)
+#define W(x...) pr_info("[HXTP][WARNING] " x)
+#define E(x...) pr_info("[HXTP][ERROR] " x)
+#endif
+
int irq_enable_count = 0;
#ifdef HX_SMART_WAKEUP
#define TS_WAKE_LOCK_TIMEOUT (2 * HZ)
@@ -25,16 +32,7 @@
#define PINCTRL_STATE_SUSPEND "pmx_ts_suspend"
#define PINCTRL_STATE_RELEASE "pmx_ts_release"
-extern struct himax_ic_data* ic_data;
-extern void himax_ts_work(struct himax_ts_data *ts);
-extern enum hrtimer_restart himax_ts_timer_func(struct hrtimer *timer);
-extern int himax_ts_init(struct himax_ts_data *ts);
-
-extern int tp_rst_gpio;
-
-#ifdef HX_TP_PROC_DIAG
-extern uint8_t getDiagCommand(void);
-#endif
+/*extern int himax_ts_init(struct himax_ts_data *ts);*/
void himax_vk_parser(struct device_node *dt,
struct himax_i2c_platform_data *pdata)
@@ -49,30 +47,34 @@
if (node == NULL) {
I(" DT-No vk info in DT");
return;
+
} else {
while ((pp = of_get_next_child(node, pp)))
cnt++;
if (!cnt)
return;
- vk = kzalloc(cnt * (sizeof *vk), GFP_KERNEL);
- if (!vk)
- return;
+ vk = kcalloc(cnt, sizeof(*vk), GFP_KERNEL);
pp = NULL;
while ((pp = of_get_next_child(node, pp))) {
if (of_property_read_u32(pp, "idx", &data) == 0)
vk[i].index = data;
- if (of_property_read_u32_array(pp, "range", coords, 4) == 0) {
- vk[i].x_range_min = coords[0], vk[i].x_range_max = coords[1];
- vk[i].y_range_min = coords[2], vk[i].y_range_max = coords[3];
+ if (of_property_read_u32_array(pp, "range",
+ coords, 4) == 0) {
+ vk[i].x_range_min = coords[0],
+ vk[i].x_range_max = coords[1];
+ vk[i].y_range_min = coords[2],
+ vk[i].y_range_max = coords[3];
} else
I(" range faile");
i++;
}
pdata->virtual_key = vk;
for (i = 0; i < cnt; i++)
- I(" vk[%d] idx:%d x_min:%d, y_max:%d", i,pdata->virtual_key[i].index,
- pdata->virtual_key[i].x_range_min, pdata->virtual_key[i].y_range_max);
+ I(" vk[%d] idx:%d x_min:%d, y_max:%d",
+ i, pdata->virtual_key[i].index,
+ pdata->virtual_key[i].x_range_min,
+ pdata->virtual_key[i].y_range_max);
}
}
@@ -89,25 +91,31 @@
if (prop) {
coords_size = prop->length / sizeof(u32);
if (coords_size != 4)
- D(" %s:Invalid panel coords size %d", __func__, coords_size);
+ D(" %s:Invalid panel coords size %d",
+ __func__, coords_size);
}
- if (of_property_read_u32_array(dt, "himax,panel-coords", coords, coords_size) == 0) {
+ if (of_property_read_u32_array(dt, "himax,panel-coords",
+ coords, coords_size) == 0) {
pdata->abs_x_min = coords[0], pdata->abs_x_max = coords[1];
pdata->abs_y_min = coords[2], pdata->abs_y_max = coords[3];
- I(" DT-%s:panel-coords = %d, %d, %d, %d\n", __func__, pdata->abs_x_min,
- pdata->abs_x_max, pdata->abs_y_min, pdata->abs_y_max);
+ I(" DT-%s:panel-coords = %d, %d, %d, %d\n",
+ __func__, pdata->abs_x_min, pdata->abs_x_max,
+ pdata->abs_y_min, pdata->abs_y_max);
}
prop = of_find_property(dt, "himax,display-coords", NULL);
if (prop) {
coords_size = prop->length / sizeof(u32);
if (coords_size != 4)
- D(" %s:Invalid display coords size %d", __func__, coords_size);
+ D(" %s:Invalid display coords size %d",
+ __func__, coords_size);
}
- rc = of_property_read_u32_array(dt, "himax,display-coords", coords, coords_size);
+ rc = of_property_read_u32_array(dt, "himax,display-coords",
+ coords, coords_size);
if (rc && (rc != -EINVAL)) {
- D(" %s:Fail to read display-coords %d\n", __func__, rc);
+ D(" %s:Fail to read display-coords %d\n",
+ __func__, rc);
return rc;
}
pdata->screenWidth = coords[1];
@@ -116,19 +124,19 @@
pdata->screenHeight);
pdata->gpio_irq = of_get_named_gpio(dt, "himax,irq-gpio", 0);
- if (!gpio_is_valid(pdata->gpio_irq)) {
+ if (!gpio_is_valid(pdata->gpio_irq))
I(" DT:gpio_irq value is not valid\n");
- }
pdata->gpio_reset = of_get_named_gpio(dt, "himax,rst-gpio", 0);
- if (!gpio_is_valid(pdata->gpio_reset)) {
+ if (!gpio_is_valid(pdata->gpio_reset))
I(" DT:gpio_rst value is not valid\n");
- }
+
pdata->gpio_3v3_en = of_get_named_gpio(dt, "himax,3v3-gpio", 0);
- if (!gpio_is_valid(pdata->gpio_3v3_en)) {
+ if (!gpio_is_valid(pdata->gpio_3v3_en))
I(" DT:gpio_3v3_en value is not valid\n");
- }
- I(" DT:gpio_irq=%d, gpio_rst=%d, gpio_3v3_en=%d", pdata->gpio_irq, pdata->gpio_reset, pdata->gpio_3v3_en);
+
+ I(" DT:gpio_irq=%d, gpio_rst=%d, gpio_3v3_en=%d",
+ pdata->gpio_irq, pdata->gpio_reset, pdata->gpio_3v3_en);
if (of_property_read_u32(dt, "report_type", &data) == 0) {
pdata->protocol_type = data;
@@ -140,7 +148,8 @@
return 0;
}
-int i2c_himax_read(struct i2c_client *client, uint8_t command, uint8_t *data, uint8_t length, uint8_t toRetry)
+int i2c_himax_read(struct i2c_client *client,
+uint8_t command, uint8_t *data, uint8_t length, uint8_t toRetry)
{
int retry;
struct i2c_msg msg[] = {
@@ -157,7 +166,7 @@
.buf = data,
}
};
-
+ mutex_lock(&private_ts->rw_lock);
for (retry = 0; retry < toRetry; retry++) {
if (i2c_transfer(client->adapter, msg, 2) == 2)
break;
@@ -166,13 +175,16 @@
if (retry == toRetry) {
E("%s: i2c_read_block retry over %d\n",
__func__, toRetry);
+ mutex_unlock(&private_ts->rw_lock);
return -EIO;
}
+ mutex_unlock(&private_ts->rw_lock);
return 0;
}
-int i2c_himax_write(struct i2c_client *client, uint8_t command, uint8_t *data, uint8_t length, uint8_t toRetry)
+int i2c_himax_write(struct i2c_client *client,
+uint8_t command, uint8_t *data, uint8_t length, uint8_t toRetry)
{
int retry/*, loop_i*/;
uint8_t buf[length + 1];
@@ -188,7 +200,7 @@
buf[0] = command;
memcpy(buf+1, data, length);
-
+ mutex_lock(&private_ts->rw_lock);
for (retry = 0; retry < toRetry; retry++) {
if (i2c_transfer(client->adapter, msg, 1) == 1)
break;
@@ -198,13 +210,16 @@
if (retry == toRetry) {
E("%s: i2c_write_block retry over %d\n",
__func__, toRetry);
+ mutex_unlock(&private_ts->rw_lock);
return -EIO;
}
+ mutex_unlock(&private_ts->rw_lock);
return 0;
}
-int i2c_himax_read_command(struct i2c_client *client, uint8_t length, uint8_t *data, uint8_t *readlength, uint8_t toRetry)
+int i2c_himax_read_command(struct i2c_client *client,
+uint8_t length, uint8_t *data, uint8_t *readlength, uint8_t toRetry)
{
int retry;
struct i2c_msg msg[] = {
@@ -215,7 +230,7 @@
.buf = data,
}
};
-
+ mutex_lock(&private_ts->rw_lock);
for (retry = 0; retry < toRetry; retry++) {
if (i2c_transfer(client->adapter, msg, 1) == 1)
break;
@@ -224,17 +239,21 @@
if (retry == toRetry) {
E("%s: i2c_read_block retry over %d\n",
__func__, toRetry);
+ mutex_unlock(&private_ts->rw_lock);
return -EIO;
}
+ mutex_unlock(&private_ts->rw_lock);
return 0;
}
-int i2c_himax_write_command(struct i2c_client *client, uint8_t command, uint8_t toRetry)
+int i2c_himax_write_command(struct i2c_client *client,
+uint8_t command, uint8_t toRetry)
{
return i2c_himax_write(client, command, NULL, 0, toRetry);
}
-int i2c_himax_master_write(struct i2c_client *client, uint8_t *data, uint8_t length, uint8_t toRetry)
+int i2c_himax_master_write(struct i2c_client *client,
+uint8_t *data, uint8_t length, uint8_t toRetry)
{
int retry/*, loop_i*/;
uint8_t buf[length];
@@ -249,7 +268,7 @@
};
memcpy(buf, data, length);
-
+ mutex_lock(&private_ts->rw_lock);
for (retry = 0; retry < toRetry; retry++) {
if (i2c_transfer(client->adapter, msg, 1) == 1)
break;
@@ -259,8 +278,10 @@
if (retry == toRetry) {
E("%s: i2c_write_block retry over %d\n",
__func__, toRetry);
+ mutex_unlock(&private_ts->rw_lock);
return -EIO;
}
+ mutex_unlock(&private_ts->rw_lock);
return 0;
}
@@ -287,62 +308,51 @@
}
#if defined(CONFIG_HMX_DB)
-static int himax_regulator_configure(struct i2c_client *client,struct himax_i2c_platform_data *pdata)
+static int himax_regulator_configure(struct i2c_client *client,
+struct himax_i2c_platform_data *pdata)
{
- int retval;
- pdata->vcc_dig = regulator_get(&client->dev,
- "vdd");
- if (IS_ERR(pdata->vcc_dig))
- {
- E("%s: Failed to get regulator vdd\n",
- __func__);
- retval = PTR_ERR(pdata->vcc_dig);
- return retval;
- }
- pdata->vcc_ana = regulator_get(&client->dev,
- "avdd");
- if (IS_ERR(pdata->vcc_ana))
- {
- E("%s: Failed to get regulator avdd\n",
- __func__);
- retval = PTR_ERR(pdata->vcc_ana);
- regulator_put(pdata->vcc_ana);
- return retval;
- }
+ int retval;
- return 0;
+ pdata->vcc_dig = regulator_get(&client->dev, "vdd");
+ if (IS_ERR(pdata->vcc_dig)) {
+ E("%s: Failed to get regulator vdd\n", __func__);
+ retval = PTR_ERR(pdata->vcc_dig);
+ return retval;
+ }
+ pdata->vcc_ana = regulator_get(&client->dev, "avdd");
+ if (IS_ERR(pdata->vcc_ana)) {
+ E("%s: Failed to get regulator avdd\n", __func__);
+ retval = PTR_ERR(pdata->vcc_ana);
+ regulator_put(pdata->vcc_ana);
+ return retval;
+ }
+
+ return 0;
};
-static int himax_power_on(struct himax_i2c_platform_data *pdata, bool on)
+static int himax_power_on(struct himax_i2c_platform_data *pdata,
+bool on)
{
- int retval;
+ int retval;
- if (on)
- {
- retval = regulator_enable(pdata->vcc_dig);
- if (retval)
- {
- E("%s: Failed to enable regulator vdd\n",
- __func__);
- return retval;
- }
- msleep(100);
- retval = regulator_enable(pdata->vcc_ana);
- if (retval)
- {
- E("%s: Failed to enable regulator avdd\n",
- __func__);
- regulator_disable(pdata->vcc_dig);
- return retval;
- }
- }
- else
- {
- regulator_disable(pdata->vcc_dig);
- regulator_disable(pdata->vcc_ana);
- }
-
- return 0;
+ if (on) {
+ retval = regulator_enable(pdata->vcc_dig);
+ if (retval) {
+ E("%s: Failed to enable regulator vdd\n", __func__);
+ return retval;
+ }
+ msleep(100);
+ retval = regulator_enable(pdata->vcc_ana);
+ if (retval) {
+ E("%s: Failed to enable regulator avdd\n", __func__);
+ regulator_disable(pdata->vcc_dig);
+ return retval;
+ }
+ } else {
+ regulator_disable(pdata->vcc_dig);
+ regulator_disable(pdata->vcc_ana);
+ }
+ return 0;
}
int himax_ts_pinctrl_init(struct himax_ts_data *ts)
@@ -353,41 +363,35 @@
ts->ts_pinctrl = devm_pinctrl_get(&(ts->client->dev));
if (IS_ERR_OR_NULL(ts->ts_pinctrl)) {
retval = PTR_ERR(ts->ts_pinctrl);
- dev_dbg(&ts->client->dev,
- "Target does not use pinctrl %d\n", retval);
+ dev_dbg(&ts->client->dev, "Target does not use pinctrl %d\n",
+ retval);
goto err_pinctrl_get;
}
- ts->pinctrl_state_active
- = pinctrl_lookup_state(ts->ts_pinctrl,
- PINCTRL_STATE_ACTIVE);
+ ts->pinctrl_state_active = pinctrl_lookup_state(ts->ts_pinctrl,
+ PINCTRL_STATE_ACTIVE);
if (IS_ERR_OR_NULL(ts->pinctrl_state_active)) {
retval = PTR_ERR(ts->pinctrl_state_active);
- dev_err(&ts->client->dev,
- "Can not lookup %s pinstate %d\n",
- PINCTRL_STATE_ACTIVE, retval);
+ dev_err(&ts->client->dev, "Can not lookup %s pinstate %d\n",
+ PINCTRL_STATE_ACTIVE, retval);
goto err_pinctrl_lookup;
}
- ts->pinctrl_state_suspend
- = pinctrl_lookup_state(ts->ts_pinctrl,
- PINCTRL_STATE_SUSPEND);
+ ts->pinctrl_state_suspend = pinctrl_lookup_state(ts->ts_pinctrl,
+ PINCTRL_STATE_SUSPEND);
if (IS_ERR_OR_NULL(ts->pinctrl_state_suspend)) {
retval = PTR_ERR(ts->pinctrl_state_suspend);
- dev_err(&ts->client->dev,
- "Can not lookup %s pinstate %d\n",
- PINCTRL_STATE_SUSPEND, retval);
+ dev_err(&ts->client->dev, "Can not lookup %s pinstate %d\n",
+ PINCTRL_STATE_SUSPEND, retval);
goto err_pinctrl_lookup;
}
- ts->pinctrl_state_release
- = pinctrl_lookup_state(ts->ts_pinctrl,
- PINCTRL_STATE_RELEASE);
+ ts->pinctrl_state_release = pinctrl_lookup_state(ts->ts_pinctrl,
+ PINCTRL_STATE_RELEASE);
if (IS_ERR_OR_NULL(ts->pinctrl_state_release)) {
retval = PTR_ERR(ts->pinctrl_state_release);
- dev_dbg(&ts->client->dev,
- "Can not lookup %s pinstate %d\n",
- PINCTRL_STATE_RELEASE, retval);
+ dev_dbg(&ts->client->dev, "Can not lookup %s pinstate %d\n",
+ PINCTRL_STATE_RELEASE, retval);
}
return 0;
@@ -399,187 +403,163 @@
return retval;
}
-int himax_gpio_power_config(struct i2c_client *client,struct himax_i2c_platform_data *pdata)
+int himax_gpio_power_config(struct i2c_client *client,
+struct himax_i2c_platform_data *pdata)
{
- int error;
+ int error;
- error = himax_regulator_configure(client, pdata);
- if (error)
- {
- E("Failed to intialize hardware\n");
- goto err_regulator_not_on;
- }
+ error = himax_regulator_configure(client, pdata);
+ if (error) {
+ E("Failed to initialize hardware\n");
+ goto err_regulator_not_on;
+ }
#ifdef HX_RST_PIN_FUNC
- if (gpio_is_valid(pdata->gpio_reset))
- {
- /* configure touchscreen reset out gpio */
- error = gpio_request(pdata->gpio_reset, "hmx_reset_gpio");
- if (error)
- {
- E("unable to request gpio [%d]\n",
- pdata->gpio_reset);
- goto err_regulator_on;
- }
-
- error = gpio_direction_output(pdata->gpio_reset, 0);
- if (error)
- {
- E("unable to set direction for gpio [%d]\n",
- pdata->gpio_reset);
- goto err_gpio_reset_req;
- }
- }
+ if (gpio_is_valid(pdata->gpio_reset)) {
+ /* configure touchscreen reset out gpio */
+ error = gpio_request(pdata->gpio_reset, "hmx_reset_gpio");
+ if (error) {
+ E("unable to request gpio [%d]\n",
+ pdata->gpio_reset);
+ goto err_regulator_on;
+ }
+ error = gpio_direction_output(pdata->gpio_reset, 0);
+ if (error) {
+ E("unable to set direction for gpio [%d]\n",
+ pdata->gpio_reset);
+ goto err_gpio_reset_req;
+ }
+ }
#endif
- error = himax_power_on(pdata, true);
- if (error)
- {
- E("Failed to power on hardware\n");
- goto err_gpio_reset_req;
- }
+ error = himax_power_on(pdata, true);
+ if (error) {
+ E("Failed to power on hardware\n");
+ goto err_gpio_reset_req;
+ }
#ifdef HX_IRQ_PIN_FUNC
- if (gpio_is_valid(pdata->gpio_irq))
- {
- /* configure touchscreen irq gpio */
- error = gpio_request(pdata->gpio_irq, "hmx_gpio_irq");
- if (error)
- {
- E("unable to request gpio [%d]\n",
- pdata->gpio_irq);
- goto err_power_on;
- }
- error = gpio_direction_input(pdata->gpio_irq);
- if (error)
- {
- E("unable to set direction for gpio [%d]\n",
- pdata->gpio_irq);
- goto err_gpio_irq_req;
- }
- client->irq = gpio_to_irq(pdata->gpio_irq);
- }
- else
- {
- E("irq gpio not provided\n");
- goto err_power_on;
- }
+ /* configure touchscreen irq gpio */
+ if (gpio_is_valid(pdata->gpio_irq)) {
+ error = gpio_request(pdata->gpio_irq, "hmx_gpio_irq");
+ if (error) {
+ E("unable to request gpio [%d]\n", pdata->gpio_irq);
+ goto err_power_on;
+ }
+ error = gpio_direction_input(pdata->gpio_irq);
+ if (error) {
+ E("unable to set direction for gpio [%d]\n",
+ pdata->gpio_irq);
+ goto err_gpio_irq_req;
+ }
+ client->irq = gpio_to_irq(pdata->gpio_irq);
+ } else {
+ E("irq gpio not provided\n");
+ goto err_power_on;
+ }
#endif
-
- msleep(20);
+ msleep(20);
#ifdef HX_RST_PIN_FUNC
- if (gpio_is_valid(pdata->gpio_reset))
- {
- error = gpio_direction_output(pdata->gpio_reset, 1);
- if (error)
- {
- E("unable to set direction for gpio [%d]\n",
- pdata->gpio_reset);
- goto err_gpio_irq_req;
- }
- }
+ if (gpio_is_valid(pdata->gpio_reset)) {
+ error = gpio_direction_output(pdata->gpio_reset, 1);
+ if (error) {
+ E("unable to set direction for gpio [%d]\n",
+ pdata->gpio_reset);
+ goto err_gpio_irq_req;
+ }
+ }
#endif
- return 0;
+ return 0;
#ifdef HX_RST_PIN_FUNC
- err_gpio_irq_req:
+err_gpio_irq_req:
#endif
#ifdef HX_IRQ_PIN_FUNC
- if (gpio_is_valid(pdata->gpio_irq))
- gpio_free(pdata->gpio_irq);
- err_power_on:
+ if (gpio_is_valid(pdata->gpio_irq))
+ gpio_free(pdata->gpio_irq);
+err_power_on:
#endif
- himax_power_on(pdata, false);
- err_gpio_reset_req:
+ himax_power_on(pdata, false);
+err_gpio_reset_req:
#ifdef HX_RST_PIN_FUNC
- if (gpio_is_valid(pdata->gpio_reset))
- gpio_free(pdata->gpio_reset);
- err_regulator_on:
+ if (gpio_is_valid(pdata->gpio_reset))
+ gpio_free(pdata->gpio_reset);
+err_regulator_on:
#endif
- err_regulator_not_on:
+err_regulator_not_on:
- return error;
+ return error;
}
#else
-int himax_gpio_power_config(struct i2c_client *client,struct himax_i2c_platform_data *pdata)
+int himax_gpio_power_config(struct i2c_client *client,
+struct himax_i2c_platform_data *pdata)
{
- int error=0;
-
-#ifdef HX_RST_PIN_FUNC
- if (pdata->gpio_reset >= 0)
- {
- error = gpio_request(pdata->gpio_reset, "himax-reset");
- if (error < 0)
- {
- E("%s: request reset pin failed\n", __func__);
- return error;
- }
- error = gpio_direction_output(pdata->gpio_reset, 0);
- if (error)
- {
- E("unable to set direction for gpio [%d]\n",
- pdata->gpio_reset);
- return error;
- }
- }
-#endif
- if (pdata->gpio_3v3_en >= 0)
- {
- error = gpio_request(pdata->gpio_3v3_en, "himax-3v3_en");
- if (error < 0)
- {
- E("%s: request 3v3_en pin failed\n", __func__);
- return error;
- }
- gpio_direction_output(pdata->gpio_3v3_en, 1);
- I("3v3_en pin =%d\n", gpio_get_value(pdata->gpio_3v3_en));
- }
+ int error = 0;
-#ifdef HX_IRQ_PIN_FUNC
- if (gpio_is_valid(pdata->gpio_irq))
- {
- /* configure touchscreen irq gpio */
- error = gpio_request(pdata->gpio_irq, "himax_gpio_irq");
- if (error)
- {
- E("unable to request gpio [%d]\n",pdata->gpio_irq);
- return error;
- }
- error = gpio_direction_input(pdata->gpio_irq);
- if (error)
- {
- E("unable to set direction for gpio [%d]\n",pdata->gpio_irq);
- return error;
- }
- client->irq = gpio_to_irq(pdata->gpio_irq);
- }
- else
- {
- E("irq gpio not provided\n");
+#ifdef HX_RST_PIN_FUNC
+ if (pdata->gpio_reset >= 0) {
+ error = gpio_request(pdata->gpio_reset, "himax-reset");
+ if (error < 0) {
+ E("%s: request reset pin failed\n", __func__);
return error;
}
-#endif
-
- msleep(20);
-
-#ifdef HX_RST_PIN_FUNC
- if (pdata->gpio_reset >= 0)
- {
- error = gpio_direction_output(pdata->gpio_reset, 1);
- if (error)
- {
- E("unable to set direction for gpio [%d]\n",
- pdata->gpio_reset);
- return error;
- }
+ error = gpio_direction_output(pdata->gpio_reset, 0);
+ if (error) {
+ E("unable to set direction for gpio [%d]\n",
+ pdata->gpio_reset);
+ return error;
}
- msleep(20);
+ }
#endif
-
+ if (pdata->gpio_3v3_en >= 0) {
+ error = gpio_request(pdata->gpio_3v3_en, "himax-3v3_en");
+ if (error < 0) {
+ E("%s: request 3v3_en pin failed\n", __func__);
+ return error;
+ }
+ gpio_direction_output(pdata->gpio_3v3_en, 1);
+ I("3v3_en pin =%d\n", gpio_get_value(pdata->gpio_3v3_en));
+ }
+
+#ifdef HX_IRQ_PIN_FUNC
+ if (gpio_is_valid(pdata->gpio_irq)) {
+ /* configure touchscreen irq gpio */
+ error = gpio_request(pdata->gpio_irq, "himax_gpio_irq");
+ if (error) {
+ E("unable to request gpio [%d]\n", pdata->gpio_irq);
+ return error;
+ }
+ error = gpio_direction_input(pdata->gpio_irq);
+ if (error) {
+ E("unable to set direction for gpio [%d]\n",
+ pdata->gpio_irq);
+ return error;
+ }
+ client->irq = gpio_to_irq(pdata->gpio_irq);
+ } else {
+ E("irq gpio not provided\n");
return error;
}
#endif
+ msleep(20);
+
+#ifdef HX_RST_PIN_FUNC
+ if (pdata->gpio_reset >= 0) {
+ error = gpio_direction_output(pdata->gpio_reset, 1);
+ if (error) {
+ E("unable to set direction for gpio [%d]\n",
+ pdata->gpio_reset);
+ return error;
+ }
+ }
+ msleep(20);
+#endif
+
+ return error;
+}
+#endif
+
static void himax_ts_isr_func(struct himax_ts_data *ts)
{
himax_ts_work(ts);
@@ -595,34 +575,40 @@
if (ts->debug_log_level & BIT(2)) {
getnstimeofday(&timeStart);
- usleep_range(5000, 7000);
- //I(" Irq start time = %ld.%06ld s\n",
- // timeStart.tv_sec, timeStart.tv_nsec/1000);
+ usleep_range(4999, 5000);
+ /*I(" Irq start time = %ld.%06ld s\n",
+ timeStart.tv_sec, timeStart.tv_nsec/1000);*/
}
#ifdef HX_SMART_WAKEUP
- if (atomic_read(&ts->suspend_mode)&&(!FAKE_POWER_KEY_SEND)&&(ts->SMWP_enable)&&(!diag_cmd)) {
- wake_lock_timeout(&ts->ts_SMWP_wake_lock, TS_WAKE_LOCK_TIMEOUT);
+ if (atomic_read(&ts->suspend_mode)
+ && (!FAKE_POWER_KEY_SEND)
+ && (ts->SMWP_enable)
+ && (!diag_cmd)) {
+ __pm_wakeup_event(&ts->ts_SMWP_wake_lock, TS_WAKE_LOCK_TIMEOUT);
msleep(200);
himax_wake_check_func();
return IRQ_HANDLED;
}
#endif
himax_ts_isr_func((struct himax_ts_data *)ptr);
- if(ts->debug_log_level & BIT(2)) {
- getnstimeofday(&timeEnd);
- timeDelta.tv_nsec = (timeEnd.tv_sec*1000000000+timeEnd.tv_nsec)
- -(timeStart.tv_sec*1000000000+timeStart.tv_nsec);
- //I("Irq finish time = %ld.%06ld s\n",
- // timeEnd.tv_sec, timeEnd.tv_nsec/1000);
- //I("Touch latency = %ld us\n", timeDelta.tv_nsec/1000);
+ if (ts->debug_log_level & BIT(2)) {
+ getnstimeofday(&timeEnd);
+ timeDelta.tv_nsec
+ = (timeEnd.tv_sec * 1000000000 + timeEnd.tv_nsec)
+ - (timeStart.tv_sec * 1000000000 + timeStart.tv_nsec);
+ /*I("Irq finish time = %ld.%06ld s\n",
+ timeEnd.tv_sec, timeEnd.tv_nsec/1000);
+ I("Touch latency = %ld us\n", timeDelta.tv_nsec/1000);*/
}
return IRQ_HANDLED;
}
static void himax_ts_work_func(struct work_struct *work)
{
- struct himax_ts_data *ts = container_of(work, struct himax_ts_data, work);
+ struct himax_ts_data *ts =
+ container_of(work, struct himax_ts_data, work);
+
himax_ts_work(ts);
}
@@ -634,24 +620,26 @@
int ret = 0;
ts->irq_enabled = 0;
- //Work functon
+ /*Work functon*/
if (client->irq) {/*INT mode*/
ts->use_irq = 1;
- if(ic_data->HX_INT_IS_EDGE)
- {
- I("%s edge triiger falling\n ",__func__);
- ret = request_threaded_irq(client->irq, NULL, himax_ts_thread,IRQF_TRIGGER_FALLING | IRQF_ONESHOT, client->name, ts);
- }
- else
- {
- I("%s level trigger low\n ",__func__);
- ret = request_threaded_irq(client->irq, NULL, himax_ts_thread,IRQF_TRIGGER_LOW | IRQF_ONESHOT, client->name, ts);
+ if (ic_data->HX_INT_IS_EDGE) {
+ I("%s edge triiger falling\n ", __func__);
+ ret = request_threaded_irq(client->irq,
+ NULL, himax_ts_thread, IRQF_TRIGGER_FALLING
+ | IRQF_ONESHOT, client->name, ts);
+ } else {
+ I("%s level trigger low\n ", __func__);
+ ret = request_threaded_irq(client->irq,
+ NULL, himax_ts_thread, IRQF_TRIGGER_LOW
+ | IRQF_ONESHOT, client->name, ts);
}
if (ret == 0) {
ts->irq_enabled = 1;
irq_enable_count = 1;
tp_irq = client->irq;
- I("%s: irq enabled at qpio: %d\n", __func__, client->irq);
+ I("%s: irq enabled at qpio: %d\n",
+ __func__, client->irq);
#ifdef HX_SMART_WAKEUP
irq_set_irq_wake(client->irq, 1);
#endif
@@ -662,8 +650,8 @@
} else {
I("%s: client->irq is empty, use polling mode.\n", __func__);
}
-
- if (!ts->use_irq) {/*if use polling mode need to disable HX_ESD_WORKAROUND function*/
+ /*if use polling mode need to disable HX_ESD_WORKAROUND function*/
+ if (!ts->use_irq) {
ts->himax_wq = create_singlethread_workqueue("himax_touch");
INIT_WORK(&ts->work, himax_ts_work_func);
@@ -680,7 +668,7 @@
{
struct himax_ts_data *ts = dev_get_drvdata(dev);
- I("%s: enter \n", __func__);
+ I("%s: enter\n", __func__);
himax_chip_common_suspend(ts);
return 0;
@@ -690,7 +678,7 @@
{
struct himax_ts_data *ts = dev_get_drvdata(dev);
- I("%s: enter \n", __func__);
+ I("%s: enter\n", __func__);
himax_chip_common_resume(ts);
return 0;
@@ -702,23 +690,28 @@
{
struct fb_event *evdata = data;
int *blank;
- struct himax_ts_data *ts=
- container_of(self, struct himax_ts_data, fb_notif);
+ struct himax_ts_data *ts
+ = container_of(self, struct himax_ts_data, fb_notif);
+ int ERR = 1;
I(" %s\n", __func__);
- if (evdata && evdata->data && event == FB_EVENT_BLANK && ts &&
- ts->client) {
+ if (evdata && evdata->data && event
+ == FB_EVENT_BLANK && ts && ts->client) {
blank = evdata->data;
mutex_lock(&ts->fb_mutex);
switch (*blank) {
case FB_BLANK_UNBLANK:
if (!ts->probe_done) {
- himax_ts_init(ts);
- ts->probe_done = true;
- } else {
+ if (himax_ts_init(ts) == true) {
+ I("himax_ts_init return OK\n");
+ ts->probe_done = true;
+ } else {
+ I("himax_ts_init return Fail\n");
+ return -ERR;
+ }
+ } else
himax_common_resume(&ts->client->dev);
- }
break;
case FB_BLANK_POWERDOWN:
@@ -748,7 +741,7 @@
};
#ifdef CONFIG_OF
-static const struct of_device_id himax_match_table[] = {
+static struct of_device_id himax_match_table[] = {
{.compatible = "himax,hxcommon" },
{},
};
@@ -770,16 +763,10 @@
},
};
-static void __init himax_common_init_async(void *unused, async_cookie_t cookie)
-{
- I("%s:Enter \n", __func__);
- i2c_add_driver(&himax_common_driver);
-}
-
static int __init himax_common_init(void)
{
I("Himax common touch panel driver init\n");
- async_schedule(himax_common_init_async, NULL);
+ i2c_add_driver(&himax_common_driver);
return 0;
}
@@ -792,5 +779,5 @@
module_exit(himax_common_exit);
MODULE_DESCRIPTION("Himax_common driver");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/input/touchscreen/hxchipset/himax_platform.h b/drivers/input/touchscreen/hxchipset/himax_platform.h
index 1223685..6871e53 100644
--- a/drivers/input/touchscreen/hxchipset/himax_platform.h
+++ b/drivers/input/touchscreen/hxchipset/himax_platform.h
@@ -22,6 +22,7 @@
#include <linux/types.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
+
#if defined(CONFIG_HMX_DB)
#include <linux/regulator/consumer.h>
#endif
@@ -31,15 +32,11 @@
#define HIMAX_I2C_RETRY_TIMES 10
#if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG)
-#define D(x...) pr_debug("[HXTP] " x)
-#define I(x...) pr_info("[HXTP] " x)
-#define W(x...) pr_warning("[HXTP][WARNING] " x)
-#define E(x...) pr_err("[HXTP][ERROR] " x)
-#define DIF(x...) \
-do {\
- if (debug_flag) \
- pr_debug("[HXTP][DEBUG] " x) \
-} while(0)
+#define D(x...) pr_info("[HXTP][DEBUG] " x)
+#define I(x...) pr_info("[HXTP][INFO] " x)
+#define W(x...) pr_info("[HXTP][WARNING] " x)
+#define E(x...) pr_info("[HXTP][ERROR] " x)
+#define DIF(x...) do { if (debug_flag) pr_info("[HXTP][DEBUG] " x) } while (0)
#else
#define D(x...)
#define I(x...)
@@ -53,24 +50,24 @@
#define HX_VTG_MIN_UV 2700000
#define HX_VTG_MAX_UV 3300000
#define HX_ACTIVE_LOAD_UA 15000
-#define HX_LPM_LOAD_UA 10
+#define HX_LPM_LOAD_UA 10
/* Digital voltage @1.8 V */
#define HX_VTG_DIG_MIN_UV 1800000
#define HX_VTG_DIG_MAX_UV 1800000
#define HX_ACTIVE_LOAD_DIG_UA 10000
-#define HX_LPM_LOAD_DIG_UA 10
+#define HX_LPM_LOAD_DIG_UA 10
#define HX_I2C_VTG_MIN_UV 1800000
#define HX_I2C_VTG_MAX_UV 1800000
-#define HX_I2C_LOAD_UA 10000
-#define HX_I2C_LPM_LOAD_UA 10
+#define HX_I2C_LOAD_UA 10000
+#define HX_I2C_LPM_LOAD_UA 10
#endif
-#define HIMAX_common_NAME "himax_tp"
+#define HIMAX_common_NAME "himax_tp"
#define HIMAX_I2C_ADDR 0x48
#define INPUT_DEV_NAME "himax-touchscreen"
-struct himax_i2c_platform_data {
+struct himax_i2c_platform_data {
int abs_x_min;
int abs_x_max;
int abs_x_fuzz;
@@ -108,28 +105,53 @@
int irq_gpio;
u32 irq_gpio_flags;
- struct regulator *vcc_ana; //For Dragon Board
- struct regulator *vcc_dig; //For Dragon Board
- struct regulator *vcc_i2c; //For Dragon Board
-#endif
+ struct regulator *vcc_ana; /*For Dragon Board*/
+ struct regulator *vcc_dig; /*For Dragon Board*/
+ struct regulator *vcc_i2c; /*For Dragon Board*/
+#endif
};
extern int irq_enable_count;
-extern int i2c_himax_read(struct i2c_client *client, uint8_t command, uint8_t *data, uint8_t length, uint8_t toRetry);
-extern int i2c_himax_write(struct i2c_client *client, uint8_t command, uint8_t *data, uint8_t length, uint8_t toRetry);
-extern int i2c_himax_write_command(struct i2c_client *client, uint8_t command, uint8_t toRetry);
-extern int i2c_himax_master_write(struct i2c_client *client, uint8_t *data, uint8_t length, uint8_t toRetry);
-extern int i2c_himax_read_command(struct i2c_client *client, uint8_t length, uint8_t *data, uint8_t *readlength, uint8_t toRetry);
-extern void himax_int_enable(int irqnum, int enable);
-extern int himax_ts_register_interrupt(struct i2c_client *client);
-extern void himax_rst_gpio_set(int pinnum, uint8_t value);
-extern uint8_t himax_int_gpio_read(int pinnum);
+int i2c_himax_read(struct i2c_client *client,
+ uint8_t command, uint8_t *data, uint8_t length, uint8_t toRetry);
-extern int himax_gpio_power_config(struct i2c_client *client,struct himax_i2c_platform_data *pdata);
+int i2c_himax_write(struct i2c_client *client,
+ uint8_t command, uint8_t *data, uint8_t length, uint8_t toRetry);
+
+int i2c_himax_write_command(struct i2c_client *client,
+ uint8_t command, uint8_t toRetry);
+
+int i2c_himax_master_write(struct i2c_client *client,
+ uint8_t *data, uint8_t length, uint8_t toRetry);
+
+int i2c_himax_read_command(struct i2c_client *client,
+ uint8_t length, uint8_t *data, uint8_t *readlength, uint8_t toRetry);
+
+void himax_int_enable(int irqnum, int enable);
+int himax_ts_register_interrupt(struct i2c_client *client);
+void himax_rst_gpio_set(int pinnum, uint8_t value);
+uint8_t himax_int_gpio_read(int pinnum);
+
+int himax_gpio_power_config(struct i2c_client *client,
+ struct himax_i2c_platform_data *pdata);
#if defined(CONFIG_FB)
-extern int fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data);
+extern int fb_notifier_callback(struct notifier_block *self,
+ unsigned long event, void *data);
#endif
+extern struct himax_ts_data *private_ts;
+extern struct himax_ic_data *ic_data;
+extern void himax_ts_work(struct himax_ts_data *ts);
+extern enum hrtimer_restart himax_ts_timer_func(struct hrtimer *timer);
+extern int tp_rst_gpio;
+
+#ifdef HX_TP_PROC_DIAG
+extern uint8_t getDiagCommand(void);
+#endif
+
+int himax_parse_dt(struct himax_ts_data *ts,
+ struct himax_i2c_platform_data *pdata);
+int himax_ts_pinctrl_init(struct himax_ts_data *ts);
#endif
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index d52b534..c1a07a5 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -60,7 +60,7 @@
config IOMMU_IO_PGTABLE_FAST
bool "Fast ARMv7/v8 Long Descriptor Format"
- select IOMMU_IO_PGTABLE
+ depends on ARM64_DMA_USE_IOMMU || ARM_DMA_USE_IOMMU
help
Enable support for a subset of the ARM long descriptor pagetable
format. This allocator achieves fast performance by
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index c3376df..3359afb 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -376,6 +376,7 @@
u32 mair[2];
struct arm_smmu_cfg *cfg;
u32 actlr;
+ bool has_actlr;
u32 attributes;
};
@@ -1776,7 +1777,8 @@
}
/* ACTLR (implementation defined) */
- writel_relaxed(cb->actlr, cb_base + ARM_SMMU_CB_ACTLR);
+ if (cb->has_actlr)
+ writel_relaxed(cb->actlr, cb_base + ARM_SMMU_CB_ACTLR);
/* SCTLR */
reg = SCTLR_CFCFG | SCTLR_CFIE | SCTLR_CFRE | SCTLR_AFE | SCTLR_TRE;
@@ -3775,6 +3777,7 @@
ACTLR_QCOM_OSH << ACTLR_QCOM_OSH_SHIFT |
ACTLR_QCOM_NSH << ACTLR_QCOM_NSH_SHIFT;
cb->actlr = val;
+ cb->has_actlr = true;
}
/* Program implementation defined registers */
@@ -5526,6 +5529,7 @@
return;
cb->actlr = iommudata->actlr;
+ cb->has_actlr = true;
/*
* Prefetch only works properly if the start and end of all
* buffers in the page table are aligned to 16 Kb.
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 5b284ab..08fcdbf 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -228,16 +228,21 @@
void __iomem *base = gic_data.dist_base;
int reg, i;
+ bitmap_zero(irqs_restore, MAX_IRQ);
+
for (reg = SAVED_ICFGR; reg < NUM_SAVED_GICD_REGS; reg++) {
for_each_spi_irq_word(i, reg) {
saved_spi_regs_start[reg][i] =
read_spi_word_offset(base, reg, i);
+ changed_spi_regs_start[reg][i] = 0;
}
}
- for (i = 32; i < IRQ_NR_BOUND(gic_data.irq_nr); i++)
+ for (i = 32; i < IRQ_NR_BOUND(gic_data.irq_nr); i++) {
gic_data.saved_spi_router[i] =
gic_read_irouter(base + GICD_IROUTER + i * 8);
+ gic_data.changed_spi_router[i] = 0;
+ }
}
static void _gicd_check_reg(enum gicd_save_restore_reg reg)
@@ -336,7 +341,7 @@
}
#define _gic_v3_dist_restore_isenabler() \
- _gic_v3_dist_restore_set_reg(GICD_ISENABLER)
+ _gic_v3_dist_restore_reg(SAVED_IS_ENABLER)
#define _gic_v3_dist_restore_ispending() \
_gic_v3_dist_restore_set_reg(GICD_ISPENDR)
@@ -414,7 +419,7 @@
*
* 5. Set pending for the interrupt.
*
- * 6. Enable interrupt and wait for its completion.
+ * 6. Restore Enable bit of interrupt and wait for its completion.
*
*/
void gic_v3_dist_restore(void)
diff --git a/drivers/mailbox/qcom-rpmh-mailbox.c b/drivers/mailbox/qcom-rpmh-mailbox.c
index c81fe52..57329f7 100644
--- a/drivers/mailbox/qcom-rpmh-mailbox.c
+++ b/drivers/mailbox/qcom-rpmh-mailbox.c
@@ -695,9 +695,10 @@
}
/* sanity check to ensure the seq is same */
for (j = 1; j < len; j++) {
- WARN((tcs->cmd_addr[i + j] != cmd[j].addr),
- "Message does not match previous sequence.\n");
+ if (tcs->cmd_addr[i + j] != cmd[j].addr) {
+ pr_debug("Message does not match previous sequence.\n");
return -EINVAL;
+ }
}
found = true;
break;
@@ -725,12 +726,12 @@
do {
slot = bitmap_find_next_zero_area(tcs->slots, MAX_TCS_SLOTS,
n, msg->num_payload, 0);
- if (slot == MAX_TCS_SLOTS)
+ if (slot >= MAX_TCS_SLOTS)
break;
n += tcs->ncpt;
} while (slot + msg->num_payload - 1 >= n);
- return (slot != MAX_TCS_SLOTS) ? slot : -ENOMEM;
+ return (slot < MAX_TCS_SLOTS) ? slot : -ENOMEM;
}
static int tcs_mbox_write(struct mbox_chan *chan, struct tcs_mbox_msg *msg,
@@ -1311,6 +1312,7 @@
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = rsc_drv_match,
+ .suppress_bind_attrs = true,
},
};
diff --git a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c
index a15ccdc..d3c39f9 100644
--- a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
@@ -1884,7 +1884,7 @@
}
rc = cam_req_mgr_workq_create("cam_fd_worker", CAM_FD_WORKQ_NUM_TASK,
- &g_fd_hw_mgr.work, CRM_WORKQ_USAGE_IRQ);
+ &g_fd_hw_mgr.work, CRM_WORKQ_USAGE_IRQ, 0);
if (rc) {
CAM_ERR(CAM_FD, "Unable to create a worker, rc=%d", rc);
goto detach_smmu;
diff --git a/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_intf.h b/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_intf.h
index 2c364e01..4256064 100644
--- a/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_intf.h
+++ b/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_intf.h
@@ -153,4 +153,10 @@
int cam_hfi_resume(struct hfi_mem_info *hfi_mem,
void __iomem *icp_base, bool debug);
+/**
+ * cam_hfi_queue_dump() - utility function to dump hfi queues
+ */
+void cam_hfi_queue_dump(void);
+
+
#endif /* _HFI_INTF_H_ */
diff --git a/drivers/media/platform/msm/camera/cam_icp/hfi.c b/drivers/media/platform/msm/camera/cam_icp/hfi.c
index a0752f5..de72e85 100644
--- a/drivers/media/platform/msm/camera/cam_icp/hfi.c
+++ b/drivers/media/platform/msm/camera/cam_icp/hfi.c
@@ -47,6 +47,49 @@
static DEFINE_MUTEX(hfi_cmd_q_mutex);
static DEFINE_MUTEX(hfi_msg_q_mutex);
+void cam_hfi_queue_dump(void)
+{
+ struct hfi_qtbl *qtbl;
+ struct hfi_qtbl_hdr *qtbl_hdr;
+ struct hfi_q_hdr *cmd_q_hdr, *msg_q_hdr;
+ struct hfi_mem_info *hfi_mem = NULL;
+ uint32_t *read_q, *read_ptr;
+ int i;
+
+ hfi_mem = &g_hfi->map;
+ if (!hfi_mem) {
+ CAM_ERR(CAM_HFI, "Unable to dump queues hfi memory is NULL");
+ return;
+ }
+
+ qtbl = (struct hfi_qtbl *)hfi_mem->qtbl.kva;
+ qtbl_hdr = &qtbl->q_tbl_hdr;
+ CAM_INFO(CAM_HFI,
+ "qtbl: version = %x size = %u num q = %u qhdr_size = %u",
+ qtbl_hdr->qtbl_version, qtbl_hdr->qtbl_size,
+ qtbl_hdr->qtbl_num_q, qtbl_hdr->qtbl_qhdr_size);
+
+ cmd_q_hdr = &qtbl->q_hdr[Q_CMD];
+ CAM_INFO(CAM_HFI, "cmd: size = %u r_idx = %u w_idx = %u addr = %x",
+ cmd_q_hdr->qhdr_q_size, cmd_q_hdr->qhdr_read_idx,
+ cmd_q_hdr->qhdr_write_idx, hfi_mem->cmd_q.iova);
+ read_q = (uint32_t *)g_hfi->map.cmd_q.kva;
+ read_ptr = (uint32_t *)(read_q + 0);
+ CAM_INFO(CAM_HFI, "CMD Q START");
+ for (i = 0; i < ICP_CMD_Q_SIZE_IN_BYTES >> BYTE_WORD_SHIFT; i++)
+ CAM_INFO(CAM_HFI, "Word: %d Data: 0x%08x ", i, read_ptr[i]);
+
+ msg_q_hdr = &qtbl->q_hdr[Q_MSG];
+ CAM_INFO(CAM_HFI, "msg: size = %u r_idx = %u w_idx = %u addr = %x",
+ msg_q_hdr->qhdr_q_size, msg_q_hdr->qhdr_read_idx,
+ msg_q_hdr->qhdr_write_idx, hfi_mem->msg_q.iova);
+ read_q = (uint32_t *)g_hfi->map.msg_q.kva;
+ read_ptr = (uint32_t *)(read_q + 0);
+ CAM_INFO(CAM_HFI, "MSG Q START");
+ for (i = 0; i < ICP_MSG_Q_SIZE_IN_BYTES >> BYTE_WORD_SHIFT; i++)
+ CAM_INFO(CAM_HFI, "Word: %d Data: 0x%08x ", i, read_ptr[i]);
+}
+
int hfi_write_cmd(void *cmd_ptr)
{
uint32_t size_in_words, empty_space, new_write_idx, read_idx, temp;
@@ -92,7 +135,8 @@
(q->qhdr_q_size - (q->qhdr_write_idx - read_idx)) :
(read_idx - q->qhdr_write_idx);
if (empty_space <= size_in_words) {
- CAM_ERR(CAM_HFI, "failed");
+ CAM_ERR(CAM_HFI, "failed: empty space %u, size_in_words %u",
+ empty_space, size_in_words);
rc = -EIO;
goto err;
}
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
index 16e97ea..3c5690d 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
@@ -1833,7 +1833,7 @@
rc = hfi_read_message(icp_hw_mgr.msg_buf, Q_MSG, &read_len);
if (rc) {
- CAM_DBG(CAM_ICP, "Unable to read msg q");
+ CAM_DBG(CAM_ICP, "Unable to read msg q rc %d", rc);
} else {
read_len = read_len << BYTE_WORD_SHIFT;
msg_ptr = (uint32_t *)icp_hw_mgr.msg_buf;
@@ -2323,6 +2323,7 @@
if (!rem_jiffies) {
rc = -ETIMEDOUT;
CAM_ERR(CAM_ICP, "FW timeout/err in abort handle command");
+ cam_hfi_queue_dump();
}
kfree(abort_cmd);
@@ -2379,6 +2380,7 @@
if (icp_hw_mgr.a5_debug_type ==
HFI_DEBUG_MODE_QUEUE)
cam_icp_mgr_process_dbg_buf();
+ cam_hfi_queue_dump();
}
kfree(destroy_cmd);
return rc;
@@ -2680,6 +2682,7 @@
if (!rem_jiffies) {
rc = -ETIMEDOUT;
CAM_ERR(CAM_ICP, "FW response timed out %d", rc);
+ cam_hfi_queue_dump();
}
CAM_DBG(CAM_ICP, "Done Waiting for INIT DONE Message");
@@ -2858,8 +2861,10 @@
struct hfi_cmd_work_data *task_data;
struct hfi_cmd_ipebps_async *hfi_cmd;
struct cam_hw_update_entry *hw_update_entries;
+ struct icp_frame_info *frame_info = NULL;
- request_id = *(uint64_t *)config_args->priv;
+ frame_info = (struct icp_frame_info *)config_args->priv;
+ request_id = frame_info->request_id;
hw_update_entries = config_args->hw_update_entries;
CAM_DBG(CAM_ICP, "req_id = %lld %pK", request_id, config_args->priv);
@@ -2881,6 +2886,82 @@
return rc;
}
+static int cam_icp_mgr_send_config_io(struct cam_icp_hw_ctx_data *ctx_data,
+ uint32_t io_buf_addr)
+{
+ int rc = 0;
+ struct hfi_cmd_work_data *task_data;
+ struct hfi_cmd_ipebps_async ioconfig_cmd;
+ unsigned long rem_jiffies;
+ int timeout = 5000;
+ struct crm_workq_task *task;
+ uint32_t size_in_words;
+
+ task = cam_req_mgr_workq_get_task(icp_hw_mgr.cmd_work);
+ if (!task)
+ return -ENOMEM;
+
+ ioconfig_cmd.size = sizeof(struct hfi_cmd_ipebps_async);
+ ioconfig_cmd.pkt_type = HFI_CMD_IPEBPS_ASYNC_COMMAND_INDIRECT;
+ if (ctx_data->icp_dev_acquire_info->dev_type == CAM_ICP_RES_TYPE_BPS)
+ ioconfig_cmd.opcode = HFI_IPEBPS_CMD_OPCODE_BPS_CONFIG_IO;
+ else
+ ioconfig_cmd.opcode = HFI_IPEBPS_CMD_OPCODE_IPE_CONFIG_IO;
+
+ reinit_completion(&ctx_data->wait_complete);
+
+ ioconfig_cmd.num_fw_handles = 1;
+ ioconfig_cmd.fw_handles[0] = ctx_data->fw_handle;
+ ioconfig_cmd.payload.indirect = io_buf_addr;
+ ioconfig_cmd.user_data1 = (uint64_t)ctx_data;
+ ioconfig_cmd.user_data2 = (uint64_t)0x0;
+ task_data = (struct hfi_cmd_work_data *)task->payload;
+ task_data->data = (void *)&ioconfig_cmd;
+ task_data->request_id = 0;
+ task_data->type = ICP_WORKQ_TASK_MSG_TYPE;
+ task->process_cb = cam_icp_mgr_process_cmd;
+ size_in_words = (*(uint32_t *)task_data->data) >> 2;
+ CAM_INFO(CAM_ICP, "size_in_words %u", size_in_words);
+ rc = cam_req_mgr_workq_enqueue_task(task, &icp_hw_mgr,
+ CRM_TASK_PRIORITY_0);
+ if (rc)
+ return rc;
+
+ rem_jiffies = wait_for_completion_timeout(&ctx_data->wait_complete,
+ msecs_to_jiffies((timeout)));
+ if (!rem_jiffies) {
+ rc = -ETIMEDOUT;
+ CAM_ERR(CAM_ICP, "FW response timed out %d", rc);
+ cam_hfi_queue_dump();
+ }
+
+ return rc;
+}
+
+static int cam_icp_mgr_send_recfg_io(struct cam_icp_hw_ctx_data *ctx_data,
+ struct hfi_cmd_ipebps_async *ioconfig_cmd, uint64_t req_id)
+{
+ int rc = 0;
+ struct hfi_cmd_work_data *task_data;
+ struct crm_workq_task *task;
+
+ task = cam_req_mgr_workq_get_task(icp_hw_mgr.cmd_work);
+ if (!task)
+ return -ENOMEM;
+
+ task_data = (struct hfi_cmd_work_data *)task->payload;
+ task_data->data = (void *)ioconfig_cmd;
+ task_data->request_id = req_id;
+ task_data->type = ICP_WORKQ_TASK_CMD_TYPE;
+ task->process_cb = cam_icp_mgr_process_cmd;
+ rc = cam_req_mgr_workq_enqueue_task(task, &icp_hw_mgr,
+ CRM_TASK_PRIORITY_0);
+ if (rc)
+ return rc;
+
+ return rc;
+}
+
static int cam_icp_mgr_config_hw(void *hw_mgr_priv, void *config_hw_args)
{
int rc = 0;
@@ -2889,6 +2970,7 @@
struct cam_icp_hw_mgr *hw_mgr = hw_mgr_priv;
struct cam_hw_config_args *config_args = config_hw_args;
struct cam_icp_hw_ctx_data *ctx_data = NULL;
+ struct icp_frame_info *frame_info = NULL;
if (!hw_mgr || !config_args) {
CAM_ERR(CAM_ICP, "Invalid arguments %pK %pK",
@@ -2912,11 +2994,23 @@
return -EINVAL;
}
- req_id = *(uint64_t *)config_args->priv;
+ frame_info = (struct icp_frame_info *)config_args->priv;
+ req_id = frame_info->request_id;
idx = cam_icp_clk_idx_from_req_id(ctx_data, req_id);
ctx_data->hfi_frame_process.fw_process_flag[idx] = true;
cam_icp_mgr_ipe_bps_clk_update(hw_mgr, ctx_data, idx);
+ CAM_DBG(CAM_ICP, "req_id %llu, io config %llu", req_id,
+ frame_info->io_config);
+
+ if (frame_info->io_config != 0) {
+ CAM_INFO(CAM_ICP, "Send recfg io");
+ rc = cam_icp_mgr_send_recfg_io(ctx_data,
+ &frame_info->hfi_cfg_io_cmd, req_id);
+ if (rc)
+ CAM_ERR(CAM_ICP, "Fail to send reconfig io cmd");
+ }
+
rc = cam_icp_mgr_enqueue_config(hw_mgr, config_args);
if (rc)
goto config_err;
@@ -3147,7 +3241,9 @@
struct icp_cmd_generic_blob *blob;
struct cam_icp_hw_ctx_data *ctx_data;
uint32_t index;
+ size_t io_buf_size;
int rc = 0;
+ uint64_t pResource;
if (!blob_data || (blob_size == 0)) {
CAM_ERR(CAM_ICP, "Invalid blob info %pK %d", blob_data,
@@ -3176,6 +3272,28 @@
clk_info->compressed_bw);
break;
+ case CAM_ICP_CMD_GENERIC_BLOB_CFG_IO:
+ CAM_DBG(CAM_ICP, "CAM_ICP_CMD_GENERIC_BLOB_CFG_IO");
+ pResource = *((uint32_t *)blob_data);
+ if (copy_from_user(&ctx_data->icp_dev_io_info,
+ (void __user *)pResource,
+ sizeof(struct cam_icp_acquire_dev_info))) {
+ CAM_ERR(CAM_ICP, "Failed in copy from user");
+ return -EFAULT;
+ }
+ CAM_DBG(CAM_ICP, "buf handle %d",
+ ctx_data->icp_dev_io_info.io_config_cmd_handle);
+ rc = cam_mem_get_io_buf(
+ ctx_data->icp_dev_io_info.io_config_cmd_handle,
+ icp_hw_mgr.iommu_hdl,
+ blob->io_buf_addr, &io_buf_size);
+ if (rc)
+ CAM_ERR(CAM_ICP, "Failed in blob update");
+ else
+ CAM_DBG(CAM_ICP, "io buf addr %llu",
+ *blob->io_buf_addr);
+ break;
+
default:
CAM_WARN(CAM_ICP, "Invalid blob type %d", blob_type);
break;
@@ -3186,7 +3304,8 @@
static int cam_icp_process_generic_cmd_buffer(
struct cam_packet *packet,
struct cam_icp_hw_ctx_data *ctx_data,
- int32_t index)
+ int32_t index,
+ uint64_t *io_buf_addr)
{
int i, rc = 0;
struct cam_cmd_buf_desc *cmd_desc = NULL;
@@ -3194,6 +3313,7 @@
cmd_generic_blob.ctx = ctx_data;
cmd_generic_blob.frame_info_idx = index;
+ cmd_generic_blob.io_buf_addr = io_buf_addr;
cmd_desc = (struct cam_cmd_buf_desc *)
((uint32_t *) &packet->payload + packet->cmd_buf_offset/4);
@@ -3213,6 +3333,28 @@
return rc;
}
+static int cam_icp_mgr_process_cfg_io_cmd(
+ struct cam_icp_hw_ctx_data *ctx_data,
+ struct hfi_cmd_ipebps_async *ioconfig_cmd,
+ uint64_t request_id,
+ uint64_t io_config)
+{
+ ioconfig_cmd->size = sizeof(struct hfi_cmd_ipebps_async);
+ ioconfig_cmd->pkt_type = HFI_CMD_IPEBPS_ASYNC_COMMAND_INDIRECT;
+ if (ctx_data->icp_dev_acquire_info->dev_type == CAM_ICP_RES_TYPE_BPS)
+ ioconfig_cmd->opcode = HFI_IPEBPS_CMD_OPCODE_BPS_CONFIG_IO;
+ else
+ ioconfig_cmd->opcode = HFI_IPEBPS_CMD_OPCODE_IPE_CONFIG_IO;
+
+ ioconfig_cmd->num_fw_handles = 1;
+ ioconfig_cmd->fw_handles[0] = ctx_data->fw_handle;
+ ioconfig_cmd->payload.indirect = io_config;
+ ioconfig_cmd->user_data1 = (uint64_t)ctx_data;
+ ioconfig_cmd->user_data2 = request_id;
+
+ return 0;
+}
+
static int cam_icp_mgr_update_hfi_frame_process(
struct cam_icp_hw_ctx_data *ctx_data,
struct cam_packet *packet,
@@ -3220,6 +3362,7 @@
int32_t *idx)
{
int32_t index, rc;
+ struct hfi_cmd_ipebps_async *hfi_cmd = NULL;
index = find_first_zero_bit(ctx_data->hfi_frame_process.bitmap,
ctx_data->hfi_frame_process.bits);
@@ -3231,15 +3374,27 @@
ctx_data->hfi_frame_process.request_id[index] =
packet->header.request_id;
- rc = cam_icp_process_generic_cmd_buffer(packet, ctx_data, index);
+ ctx_data->hfi_frame_process.frame_info[index].request_id =
+ packet->header.request_id;
+ ctx_data->hfi_frame_process.frame_info[index].io_config = 0;
+ rc = cam_icp_process_generic_cmd_buffer(packet, ctx_data, index,
+ &ctx_data->hfi_frame_process.frame_info[index].io_config);
if (rc) {
clear_bit(index, ctx_data->hfi_frame_process.bitmap);
ctx_data->hfi_frame_process.request_id[index] = -1;
return rc;
}
+
+ if (ctx_data->hfi_frame_process.frame_info[index].io_config) {
+ hfi_cmd = (struct hfi_cmd_ipebps_async *)&ctx_data->
+ hfi_frame_process.frame_info[index].hfi_cfg_io_cmd;
+ rc = cam_icp_mgr_process_cfg_io_cmd(ctx_data, hfi_cmd,
+ packet->header.request_id, ctx_data->
+ hfi_frame_process.frame_info[index].io_config);
+ }
*idx = index;
- return 0;
+ return rc;
}
static int cam_icp_mgr_prepare_hw_update(void *hw_mgr_priv,
@@ -3320,7 +3475,7 @@
prepare_args->num_hw_update_entries = 1;
prepare_args->hw_update_entries[0].addr = (uint64_t)hfi_cmd;
- prepare_args->priv = &ctx_data->hfi_frame_process.request_id[idx];
+ prepare_args->priv = &ctx_data->hfi_frame_process.frame_info[idx];
CAM_DBG(CAM_ICP, "X: req id = %lld ctx_id = %u",
packet->header.request_id, ctx_data->ctx_id);
@@ -3584,53 +3739,6 @@
return rc;
}
-static int cam_icp_mgr_send_config_io(struct cam_icp_hw_ctx_data *ctx_data,
- uint32_t io_buf_addr)
-{
- int rc = 0;
- struct hfi_cmd_work_data *task_data;
- struct hfi_cmd_ipebps_async ioconfig_cmd;
- unsigned long rem_jiffies;
- int timeout = 5000;
- struct crm_workq_task *task;
-
- task = cam_req_mgr_workq_get_task(icp_hw_mgr.cmd_work);
- if (!task)
- return -ENOMEM;
-
- ioconfig_cmd.size = sizeof(struct hfi_cmd_ipebps_async);
- ioconfig_cmd.pkt_type = HFI_CMD_IPEBPS_ASYNC_COMMAND_INDIRECT;
- if (ctx_data->icp_dev_acquire_info->dev_type == CAM_ICP_RES_TYPE_BPS)
- ioconfig_cmd.opcode = HFI_IPEBPS_CMD_OPCODE_BPS_CONFIG_IO;
- else
- ioconfig_cmd.opcode = HFI_IPEBPS_CMD_OPCODE_IPE_CONFIG_IO;
-
- reinit_completion(&ctx_data->wait_complete);
- ioconfig_cmd.num_fw_handles = 1;
- ioconfig_cmd.fw_handles[0] = ctx_data->fw_handle;
- ioconfig_cmd.payload.indirect = io_buf_addr;
- ioconfig_cmd.user_data1 = (uint64_t)ctx_data;
- ioconfig_cmd.user_data2 = (uint64_t)0x0;
- task_data = (struct hfi_cmd_work_data *)task->payload;
- task_data->data = (void *)&ioconfig_cmd;
- task_data->request_id = 0;
- task_data->type = ICP_WORKQ_TASK_CMD_TYPE;
- task->process_cb = cam_icp_mgr_process_cmd;
- rc = cam_req_mgr_workq_enqueue_task(task, &icp_hw_mgr,
- CRM_TASK_PRIORITY_0);
- if (rc)
- return rc;
-
- rem_jiffies = wait_for_completion_timeout(&ctx_data->wait_complete,
- msecs_to_jiffies((timeout)));
- if (!rem_jiffies) {
- rc = -ETIMEDOUT;
- CAM_ERR(CAM_ICP, "FW response timed out %d", rc);
- }
-
- return rc;
-}
-
static int cam_icp_mgr_create_handle(uint32_t dev_type,
struct cam_icp_hw_ctx_data *ctx_data)
{
@@ -3665,6 +3773,7 @@
if (!rem_jiffies) {
rc = -ETIMEDOUT;
CAM_ERR(CAM_ICP, "FW response timed out %d", rc);
+ cam_hfi_queue_dump();
}
if (ctx_data->fw_handle == 0) {
@@ -3710,6 +3819,7 @@
if (!rem_jiffies) {
rc = -ETIMEDOUT;
CAM_ERR(CAM_ICP, "FW response timed out %d", rc);
+ cam_hfi_queue_dump();
}
return rc;
@@ -3843,6 +3953,8 @@
icp_dev_acquire_info = ctx_data->icp_dev_acquire_info;
+ CAM_DBG(CAM_ICP, "acquire io buf handle %d",
+ icp_dev_acquire_info->io_config_cmd_handle);
rc = cam_mem_get_io_buf(
icp_dev_acquire_info->io_config_cmd_handle,
hw_mgr->iommu_hdl,
@@ -4134,21 +4246,22 @@
int i;
rc = cam_req_mgr_workq_create("icp_command_queue", ICP_WORKQ_NUM_TASK,
- &icp_hw_mgr.cmd_work, CRM_WORKQ_USAGE_NON_IRQ);
+ &icp_hw_mgr.cmd_work, CRM_WORKQ_USAGE_NON_IRQ,
+ 0);
if (rc) {
CAM_ERR(CAM_ICP, "unable to create a command worker");
goto cmd_work_failed;
}
rc = cam_req_mgr_workq_create("icp_message_queue", ICP_WORKQ_NUM_TASK,
- &icp_hw_mgr.msg_work, CRM_WORKQ_USAGE_IRQ);
+ &icp_hw_mgr.msg_work, CRM_WORKQ_USAGE_IRQ, 0);
if (rc) {
CAM_ERR(CAM_ICP, "unable to create a message worker");
goto msg_work_failed;
}
rc = cam_req_mgr_workq_create("icp_timer_queue", ICP_WORKQ_NUM_TASK,
- &icp_hw_mgr.timer_work, CRM_WORKQ_USAGE_IRQ);
+ &icp_hw_mgr.timer_work, CRM_WORKQ_USAGE_IRQ, 0);
if (rc) {
CAM_ERR(CAM_ICP, "unable to create a timer worker");
goto timer_work_failed;
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h
index 8746ee2..3e3c0e0 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h
@@ -126,6 +126,19 @@
};
/**
+ * struct icp_frame_info
+ * @request_id: request id
+ * @io_config: the address of io config
+ * @hfi_cfg_io_cmd: command struct to be sent to hfi
+ */
+struct icp_frame_info {
+ uint64_t request_id;
+ uint64_t io_config;
+ struct hfi_cmd_ipebps_async hfi_cfg_io_cmd;
+};
+
+
+/**
* struct hfi_frame_process_info
* @hfi_frame_cmd: Frame process command info
* @bitmap: Bitmap for hfi_frame_cmd
@@ -136,6 +149,7 @@
* @out_resource: Out sync info
* @fw_process_flag: Frame process flag
* @clk_info: Clock information for a request
+ * @frame_info: information needed to process request
*/
struct hfi_frame_process_info {
struct hfi_cmd_ipebps_async hfi_frame_cmd[CAM_FRAME_CMD_MAX];
@@ -149,6 +163,7 @@
uint32_t in_free_resource[CAM_FRAME_CMD_MAX];
uint32_t fw_process_flag[CAM_FRAME_CMD_MAX];
struct cam_icp_clk_bw_request clk_info[CAM_FRAME_CMD_MAX];
+ struct icp_frame_info frame_info[CAM_FRAME_CMD_MAX];
};
/**
@@ -189,6 +204,7 @@
* @clk_info: Current clock info of a context
* @watch_dog: watchdog timer handle
* @watch_dog_reset_counter: Counter for watch dog reset
+ * @icp_dev_io_info: io config resource
*/
struct cam_icp_hw_ctx_data {
void *context_priv;
@@ -208,16 +224,19 @@
struct cam_ctx_clk_info clk_info;
struct cam_req_mgr_timer *watch_dog;
uint32_t watch_dog_reset_counter;
+ struct cam_icp_acquire_dev_info icp_dev_io_info;
};
/**
* struct icp_cmd_generic_blob
* @ctx: Current context info
* @frame_info_idx: Index used for frame process info
+ * @io_buf_addr: pointer to io buffer address
*/
struct icp_cmd_generic_blob {
struct cam_icp_hw_ctx_data *ctx;
uint32_t frame_info_idx;
+ uint64_t *io_buf_addr;
};
/**
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
index c1aa501..e5c54d6 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
@@ -225,6 +225,8 @@
CAM_ERR(CAM_ISP, "Can not start HW resources");
goto err;
}
+ CAM_DBG(CAM_ISP, "Start HW %d Res %d", hw_intf->hw_idx,
+ isp_hw_res->hw_res[i]->res_id);
} else {
CAM_ERR(CAM_ISP, "function null");
goto err;
@@ -366,7 +368,8 @@
isp_res = hw_mgr_res->hw_res[i];
if (isp_res->hw_intf->hw_idx != base_idx)
continue;
-
+ CAM_DBG(CAM_ISP, "base_idx %d res_id %d cnt %u",
+ base_idx, isp_res->res_id, cnt);
stop_res[cnt] = isp_res;
cnt++;
}
@@ -483,8 +486,8 @@
"Add split id = %d for base idx = %d num_base=%d",
split_id, base_idx, ctx->num_base);
} else {
- /*Check if base index is alreay exist in the list */
- for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) {
+ /*Check if base index already exists in the list */
+ for (i = 0; i < ctx->num_base; i++) {
if (ctx->base[i].idx == base_idx) {
if (split_id != CAM_ISP_HW_SPLIT_MAX &&
ctx->base[i].split_id ==
@@ -495,7 +498,7 @@
}
}
- if (i == CAM_IFE_HW_NUM_MAX) {
+ if (i == ctx->num_base) {
ctx->base[ctx->num_base].split_id = split_id;
ctx->base[ctx->num_base].idx = base_idx;
ctx->num_base++;
@@ -845,7 +848,8 @@
}
ife_src_res->hw_res[i] = vfe_acquire.vfe_in.rsrc_node;
CAM_DBG(CAM_ISP,
- "acquire success res type :0x%x res id:0x%x",
+ "acquire success IFE:%d res type :0x%x res id:0x%x",
+ hw_intf->hw_idx,
ife_src_res->hw_res[i]->res_type,
ife_src_res->hw_res[i]->res_id);
@@ -871,29 +875,75 @@
static int cam_ife_mgr_acquire_cid_res(
struct cam_ife_hw_mgr_ctx *ife_ctx,
struct cam_isp_in_port_info *in_port,
- uint32_t *cid_res_id,
+ struct cam_ife_hw_mgr_res **cid_res,
enum cam_ife_pix_path_res_id csid_path)
{
int rc = -1;
int i, j;
struct cam_ife_hw_mgr *ife_hw_mgr;
- struct cam_ife_hw_mgr_res *cid_res;
struct cam_hw_intf *hw_intf;
+ struct cam_ife_hw_mgr_res *cid_res_temp, *cid_res_iterator;
struct cam_csid_hw_reserve_resource_args csid_acquire;
+ uint32_t acquired_cnt = 0;
ife_hw_mgr = ife_ctx->hw_mgr;
+ *cid_res = NULL;
- rc = cam_ife_hw_mgr_get_res(&ife_ctx->free_res_list, &cid_res);
+ rc = cam_ife_hw_mgr_get_res(&ife_ctx->free_res_list, cid_res);
if (rc) {
CAM_ERR(CAM_ISP, "No more free hw mgr resource");
- goto err;
+ goto end;
}
- cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_cid, &cid_res);
+
+ cid_res_temp = *cid_res;
csid_acquire.res_type = CAM_ISP_RESOURCE_CID;
csid_acquire.in_port = in_port;
csid_acquire.res_id = csid_path;
+ CAM_DBG(CAM_ISP, "path %d", csid_path);
+ /* Try acquiring CID resource from previously acquired HW */
+ list_for_each_entry(cid_res_iterator, &ife_ctx->res_list_ife_cid,
+ list) {
+
+ for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
+ if (!cid_res_iterator->hw_res[i])
+ continue;
+
+ hw_intf = cid_res_iterator->hw_res[i]->hw_intf;
+ rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
+ &csid_acquire, sizeof(csid_acquire));
+ if (rc) {
+ CAM_DBG(CAM_ISP,
+ "No ife cid resource from hw %d",
+ hw_intf->hw_idx);
+ continue;
+ }
+
+ cid_res_temp->hw_res[acquired_cnt++] =
+ csid_acquire.node_res;
+
+ CAM_DBG(CAM_ISP,
+ "acquired csid(%s)=%d CID rsrc successfully",
+ (i == 0) ? "left" : "right",
+ hw_intf->hw_idx);
+
+ if (in_port->usage_type && acquired_cnt == 1 &&
+ csid_path == CAM_IFE_PIX_PATH_RES_IPP)
+ /* Continue to acquire Right */
+ continue;
+
+ if (acquired_cnt)
+ /*
+ * If successfully acquired CID from
+ * previously acquired HW, skip the next
+ * part
+ */
+ goto acquire_successful;
+ }
+ }
+
+ /* Acquire Left if not already acquired */
for (i = 0; i < CAM_IFE_CSID_HW_NUM_MAX; i++) {
if (!ife_hw_mgr->csid_devices[i])
continue;
@@ -903,31 +953,45 @@
sizeof(csid_acquire));
if (rc)
continue;
- else
+ else {
+ cid_res_temp->hw_res[acquired_cnt++] =
+ csid_acquire.node_res;
break;
+ }
}
if (i == CAM_IFE_CSID_HW_NUM_MAX || !csid_acquire.node_res) {
- CAM_ERR(CAM_ISP, "Can not acquire ife csid rdi resource");
- goto err;
+ CAM_ERR(CAM_ISP, "Can not acquire ife cid resource for path %d",
+ csid_path);
+ goto put_res;
}
- cid_res->res_type = CAM_IFE_HW_MGR_RES_CID;
- cid_res->res_id = csid_acquire.node_res->res_id;
- cid_res->is_dual_vfe = in_port->usage_type;
- cid_res->hw_res[0] = csid_acquire.node_res;
- cid_res->hw_res[1] = NULL;
- /* CID(DT_ID) value of acquire device, require for path */
- *cid_res_id = csid_acquire.node_res->res_id;
+acquire_successful:
+ CAM_DBG(CAM_ISP, "CID left acquired success is_dual %d",
+ in_port->usage_type);
- if (cid_res->is_dual_vfe) {
+ cid_res_temp->res_type = CAM_IFE_HW_MGR_RES_CID;
+ /* CID(DT_ID) value of acquire device, require for path */
+ cid_res_temp->res_id = csid_acquire.node_res->res_id;
+ cid_res_temp->is_dual_vfe = in_port->usage_type;
+ cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_cid, cid_res);
+
+ /*
+ * Acquire Right if not already acquired.
+ * Dual IFE for RDI is not currently supported.
+ */
+ if (cid_res_temp->is_dual_vfe && csid_path
+ == CAM_IFE_PIX_PATH_RES_IPP && acquired_cnt == 1) {
csid_acquire.node_res = NULL;
csid_acquire.res_type = CAM_ISP_RESOURCE_CID;
csid_acquire.in_port = in_port;
- for (j = i + 1; j < CAM_IFE_CSID_HW_NUM_MAX; j++) {
+ for (j = 0; j < CAM_IFE_CSID_HW_NUM_MAX; j++) {
if (!ife_hw_mgr->csid_devices[j])
continue;
+ if (j == cid_res_temp->hw_res[0]->hw_intf->hw_idx)
+ continue;
+
hw_intf = ife_hw_mgr->csid_devices[j];
rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
&csid_acquire, sizeof(csid_acquire));
@@ -940,16 +1004,20 @@
if (j == CAM_IFE_CSID_HW_NUM_MAX) {
CAM_ERR(CAM_ISP,
"Can not acquire ife csid rdi resource");
- goto err;
+ goto end;
}
- cid_res->hw_res[1] = csid_acquire.node_res;
+ cid_res_temp->hw_res[1] = csid_acquire.node_res;
+ CAM_DBG(CAM_ISP, "CID right acquired success is_dual %d",
+ in_port->usage_type);
}
- cid_res->parent = &ife_ctx->res_list_ife_in;
+ cid_res_temp->parent = &ife_ctx->res_list_ife_in;
ife_ctx->res_list_ife_in.child[
- ife_ctx->res_list_ife_in.num_children++] = cid_res;
+ ife_ctx->res_list_ife_in.num_children++] = cid_res_temp;
return 0;
-err:
+put_res:
+ cam_ife_hw_mgr_put_res(&ife_ctx->free_res_list, cid_res);
+end:
return rc;
}
@@ -966,35 +1034,25 @@
struct cam_ife_hw_mgr_res *csid_res;
struct cam_ife_hw_mgr_res *cid_res;
struct cam_hw_intf *hw_intf;
- uint32_t cid_res_id;
struct cam_csid_hw_reserve_resource_args csid_acquire;
+ ife_hw_mgr = ife_ctx->hw_mgr;
/* get cid resource */
- rc = cam_ife_mgr_acquire_cid_res(ife_ctx, in_port, &cid_res_id,
+ rc = cam_ife_mgr_acquire_cid_res(ife_ctx, in_port, &cid_res,
CAM_IFE_PIX_PATH_RES_IPP);
if (rc) {
CAM_ERR(CAM_ISP, "Acquire IFE CID resource Failed");
- goto err;
+ goto end;
}
- ife_hw_mgr = ife_ctx->hw_mgr;
-
rc = cam_ife_hw_mgr_get_res(&ife_ctx->free_res_list, &csid_res);
if (rc) {
CAM_ERR(CAM_ISP, "No more free hw mgr resource");
- goto err;
+ goto end;
}
- cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_csid, &csid_res);
-
- csid_acquire.res_type = CAM_ISP_RESOURCE_PIX_PATH;
- csid_acquire.res_id = CAM_IFE_PIX_PATH_RES_IPP;
- csid_acquire.cid = cid_res_id;
- csid_acquire.in_port = in_port;
- csid_acquire.out_port = in_port->data;
csid_res->res_type = CAM_ISP_RESOURCE_PIX_PATH;
csid_res->res_id = CAM_IFE_PIX_PATH_RES_IPP;
- csid_res->is_dual_vfe = in_port->usage_type;
if (in_port->usage_type)
csid_res->is_dual_vfe = 1;
@@ -1003,66 +1061,60 @@
csid_acquire.sync_mode = CAM_ISP_HW_SYNC_NONE;
}
- list_for_each_entry(cid_res, &ife_ctx->res_list_ife_cid,
- list) {
- if (cid_res->res_id != cid_res_id)
- continue;
+ /* IPP resource needs to be from same HW as CID resource */
+ for (i = 0; i <= csid_res->is_dual_vfe; i++) {
+ CAM_DBG(CAM_ISP, "i %d is_dual %d", i, csid_res->is_dual_vfe);
+ csid_acquire.res_type = CAM_ISP_RESOURCE_PIX_PATH;
+ csid_acquire.res_id = CAM_IFE_PIX_PATH_RES_IPP;
+ csid_acquire.cid = cid_res->hw_res[i]->res_id;
+ csid_acquire.in_port = in_port;
+ csid_acquire.out_port = in_port->data;
+ csid_acquire.node_res = NULL;
- for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
- if (!cid_res->hw_res[i])
- continue;
+ hw_intf = cid_res->hw_res[i]->hw_intf;
- hw_intf = ife_hw_mgr->csid_devices[
- cid_res->hw_res[i]->hw_intf->hw_idx];
-
- csid_acquire.node_res = NULL;
- if (csid_res->is_dual_vfe) {
- if (i == CAM_ISP_HW_SPLIT_LEFT) {
- master_idx = hw_intf->hw_idx;
- csid_acquire.sync_mode =
- CAM_ISP_HW_SYNC_MASTER;
- } else {
- if (master_idx == -1) {
- CAM_ERR(CAM_ISP,
- "No Master found");
- goto err;
- }
- csid_acquire.sync_mode =
- CAM_ISP_HW_SYNC_SLAVE;
- csid_acquire.master_idx = master_idx;
+ if (csid_res->is_dual_vfe) {
+ if (i == CAM_ISP_HW_SPLIT_LEFT) {
+ master_idx = hw_intf->hw_idx;
+ csid_acquire.sync_mode =
+ CAM_ISP_HW_SYNC_MASTER;
+ } else {
+ if (master_idx == -1) {
+ CAM_ERR(CAM_ISP,
+ "No Master found");
+ goto put_res;
}
+ csid_acquire.sync_mode =
+ CAM_ISP_HW_SYNC_SLAVE;
+ csid_acquire.master_idx = master_idx;
}
-
- rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
- &csid_acquire, sizeof(csid_acquire));
- if (rc) {
- CAM_ERR(CAM_ISP,
- "Cannot acquire ife csid ipp resource");
- goto err;
- }
-
- csid_res->hw_res[i] = csid_acquire.node_res;
- CAM_DBG(CAM_ISP,
- "acquired csid(%s)=%d ipp rsrc successfully",
- (i == 0) ? "left" : "right",
- hw_intf->hw_idx);
-
}
- if (i == CAM_IFE_CSID_HW_NUM_MAX) {
+ rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
+ &csid_acquire, sizeof(csid_acquire));
+ if (rc) {
CAM_ERR(CAM_ISP,
- "Can not acquire ife csid ipp resource");
- goto err;
+ "Cannot acquire ife csid ipp resource");
+ goto put_res;
}
- csid_res->parent = cid_res;
- cid_res->child[cid_res->num_children++] = csid_res;
+ csid_res->hw_res[i] = csid_acquire.node_res;
+ CAM_DBG(CAM_ISP,
+ "acquired csid(%s)=%d ipp rsrc successfully",
+ (i == 0) ? "left" : "right",
+ hw_intf->hw_idx);
}
+ cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_csid, &csid_res);
+
+ csid_res->parent = cid_res;
+ cid_res->child[cid_res->num_children++] = csid_res;
CAM_DBG(CAM_ISP, "acquire res %d", csid_acquire.res_id);
return 0;
-err:
+put_res:
+ cam_ife_hw_mgr_put_res(&ife_ctx->free_res_list, &csid_res);
+end:
return rc;
}
@@ -1099,111 +1151,88 @@
struct cam_ife_hw_mgr_ctx *ife_ctx,
struct cam_isp_in_port_info *in_port)
{
- int rc = -1;
- int i, j;
+ int rc = -EINVAL;
+ int i;
struct cam_ife_hw_mgr *ife_hw_mgr;
struct cam_ife_hw_mgr_res *csid_res;
struct cam_ife_hw_mgr_res *cid_res;
struct cam_hw_intf *hw_intf;
struct cam_isp_out_port_info *out_port;
- uint32_t cid_res_id;
struct cam_csid_hw_reserve_resource_args csid_acquire;
+ enum cam_ife_pix_path_res_id path_type;
ife_hw_mgr = ife_ctx->hw_mgr;
for (i = 0; i < in_port->num_out_res; i++) {
out_port = &in_port->data[i];
- if (!cam_ife_hw_mgr_is_rdi_res(out_port->res_type))
+ path_type = cam_ife_hw_mgr_get_ife_csid_rdi_res_type(
+ out_port->res_type);
+ if (path_type == CAM_IFE_PIX_PATH_RES_MAX)
continue;
- /* get cid resource */
- rc = cam_ife_mgr_acquire_cid_res(ife_ctx,
- in_port, &cid_res_id,
- cam_ife_hw_mgr_get_ife_csid_rdi_res_type(
- out_port->res_type));
- if (rc) {
- CAM_ERR(CAM_ISP,
- "Acquire IFE CID resource Failed");
- goto err;
+ /* get cid resource */
+ rc = cam_ife_mgr_acquire_cid_res(ife_ctx, in_port, &cid_res,
+ path_type);
+ if (rc) {
+ CAM_ERR(CAM_ISP, "Acquire IFE CID resource Failed");
+ goto end;
}
+ /* For each RDI we need CID + PATH resource */
rc = cam_ife_hw_mgr_get_res(&ife_ctx->free_res_list,
&csid_res);
if (rc) {
CAM_ERR(CAM_ISP, "No more free hw mgr resource");
- goto err;
+ goto end;
}
- cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_csid, &csid_res);
-
- /*
- * no need to check since we are doing one to one mapping
- * between the csid rdi type and out port rdi type
- */
memset(&csid_acquire, 0, sizeof(csid_acquire));
- csid_acquire.res_id =
- cam_ife_hw_mgr_get_ife_csid_rdi_res_type(
- out_port->res_type);
+ csid_acquire.res_id = path_type;
csid_acquire.res_type = CAM_ISP_RESOURCE_PIX_PATH;
- csid_acquire.cid = cid_res_id;
+ csid_acquire.cid = cid_res->hw_res[0]->res_id;
csid_acquire.in_port = in_port;
csid_acquire.out_port = out_port;
csid_acquire.sync_mode = CAM_ISP_HW_SYNC_NONE;
+ csid_acquire.node_res = NULL;
- list_for_each_entry(cid_res, &ife_ctx->res_list_ife_cid,
- list) {
- if (cid_res->res_id != cid_res_id)
- continue;
+ hw_intf = cid_res->hw_res[0]->hw_intf;
+ rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
+ &csid_acquire, sizeof(csid_acquire));
+ if (rc) {
+ CAM_ERR(CAM_ISP,
+ "CSID Path reserve failed hw=%d rc=%d cid=%d",
+ hw_intf->hw_idx, rc,
+ cid_res->hw_res[0]->res_id);
- for (j = 0; j < CAM_ISP_HW_SPLIT_MAX; j++) {
- if (!cid_res->hw_res[j])
- continue;
-
- csid_acquire.node_res = NULL;
-
- hw_intf = ife_hw_mgr->csid_devices[
- cid_res->hw_res[j]->hw_intf->hw_idx];
- rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
- &csid_acquire, sizeof(csid_acquire));
- if (rc) {
- CAM_DBG(CAM_ISP,
- "CSID Path reserve failed hw=%d rc=%d",
- hw_intf->hw_idx, rc);
- continue;
- }
-
- /* RDI does not need Dual ISP. Break */
- break;
- }
-
- if (j == CAM_ISP_HW_SPLIT_MAX &&
- csid_acquire.node_res == NULL) {
- CAM_ERR(CAM_ISP,
- "acquire csid rdi rsrc failed, cid %d",
- cid_res_id);
- goto err;
- }
-
- csid_res->res_type = CAM_ISP_RESOURCE_PIX_PATH;
- csid_res->res_id = csid_acquire.res_id;
- csid_res->is_dual_vfe = 0;
- csid_res->hw_res[0] = csid_acquire.node_res;
- csid_res->hw_res[1] = NULL;
- CAM_DBG(CAM_ISP, "acquire res %d",
- csid_acquire.res_id);
- csid_res->parent = cid_res;
- cid_res->child[cid_res->num_children++] =
- csid_res;
-
- /* Done with cid_res_id. Break */
- break;
+ goto put_res;
}
+
+ if (csid_acquire.node_res == NULL) {
+ CAM_ERR(CAM_ISP, "Acquire CSID RDI rsrc failed");
+
+ goto put_res;
+ }
+
+ csid_res->res_type = (enum cam_ife_hw_mgr_res_type)
+ CAM_ISP_RESOURCE_PIX_PATH;
+ csid_res->res_id = csid_acquire.res_id;
+ csid_res->is_dual_vfe = 0;
+ csid_res->hw_res[0] = csid_acquire.node_res;
+ csid_res->hw_res[1] = NULL;
+ CAM_DBG(CAM_ISP, "acquire res %d",
+ csid_acquire.res_id);
+ csid_res->parent = cid_res;
+ cid_res->child[cid_res->num_children++] =
+ csid_res;
+ cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_csid, &csid_res);
}
return 0;
-err:
+put_res:
+ cam_ife_hw_mgr_put_res(&ife_ctx->free_res_list, &csid_res);
+end:
return rc;
}
@@ -1870,6 +1899,24 @@
*/
if (i == ctx->num_base)
master_base_idx = ctx->base[0].idx;
+ CAM_DBG(CAM_ISP, "Stopping master CSID idx %d", master_base_idx);
+
+ /* Stop the master CSID path first */
+ cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_csid,
+ master_base_idx, CAM_CSID_HALT_AT_FRAME_BOUNDARY);
+
+ /* stop rest of the CSID paths */
+ for (i = 0; i < ctx->num_base; i++) {
+ if (ctx->base[i].idx == master_base_idx)
+ continue;
+ CAM_DBG(CAM_ISP, "Stopping CSID idx %d i %d master %d",
+ ctx->base[i].idx, i, master_base_idx);
+
+ cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_csid,
+ ctx->base[i].idx, CAM_CSID_HALT_AT_FRAME_BOUNDARY);
+ }
+
+ CAM_DBG(CAM_ISP, "Stopping master CID idx %d", master_base_idx);
/* Stop the master CIDs first */
cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_cid,
@@ -1877,26 +1924,14 @@
/* stop rest of the CIDs */
for (i = 0; i < ctx->num_base; i++) {
- if (i == master_base_idx)
+ if (ctx->base[i].idx == master_base_idx)
continue;
+ CAM_DBG(CAM_ISP, "Stopping CID idx %d i %d master %d",
+ ctx->base[i].idx, i, master_base_idx);
cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_cid,
ctx->base[i].idx, csid_halt_type);
}
- /* Stop the master CSID path first */
- cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_csid,
- master_base_idx, csid_halt_type);
-
- /* stop rest of the CSID paths */
- for (i = 0; i < ctx->num_base; i++) {
- if (i == master_base_idx)
- continue;
-
- cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_csid,
- ctx->base[i].idx, csid_halt_type);
- }
-
-
/* Deinit IFE CID */
list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_cid, list) {
CAM_DBG(CAM_ISP, "%s: Going to DeInit IFE CID\n", __func__);
@@ -4218,7 +4253,7 @@
/* Create Worker for ife_hw_mgr with 10 tasks */
rc = cam_req_mgr_workq_create("cam_ife_worker", 10,
- &g_ife_hw_mgr.workq, CRM_WORKQ_USAGE_NON_IRQ);
+ &g_ife_hw_mgr.workq, CRM_WORKQ_USAGE_NON_IRQ, 0);
if (rc < 0) {
CAM_ERR(CAM_ISP, "Unable to create worker");
goto end;
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c
index e869e2b..1444911 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c
@@ -70,6 +70,12 @@
hw_entry[num_ent].handle = kmd_buf_info->handle;
hw_entry[num_ent].len = get_base.cmd.used_bytes;
hw_entry[num_ent].offset = kmd_buf_info->offset;
+ CAM_DBG(CAM_ISP,
+ "num_ent=%d handle=0x%x, len=%u, offset=%u",
+ num_ent,
+ hw_entry[num_ent].handle,
+ hw_entry[num_ent].len,
+ hw_entry[num_ent].offset);
kmd_buf_info->used_bytes += get_base.cmd.used_bytes;
kmd_buf_info->offset += get_base.cmd.used_bytes;
@@ -184,6 +190,16 @@
return -EINVAL;
}
+ cmd_update.cmd_type = hw_cmd_type;
+ cmd_update.cmd.cmd_buf_addr = cmd_buf_addr;
+ cmd_update.cmd.size = kmd_buf_remain_size;
+ cmd_update.cmd.used_bytes = 0;
+ cmd_update.data = cmd_update_data;
+ CAM_DBG(CAM_ISP, "cmd_type %u cmd buffer 0x%pK, size %d",
+ cmd_update.cmd_type,
+ cmd_update.cmd.cmd_buf_addr,
+ cmd_update.cmd.size);
+
for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
if (!hw_mgr_res->hw_res[i])
continue;
@@ -193,14 +209,7 @@
res = hw_mgr_res->hw_res[i];
cmd_update.res = res;
- cmd_update.cmd_type = hw_cmd_type;
- cmd_update.cmd.cmd_buf_addr = cmd_buf_addr;
- cmd_update.cmd.size = kmd_buf_remain_size;
- cmd_update.data = cmd_update_data;
- CAM_DBG(CAM_ISP, "cmd buffer 0x%pK, size %d",
- cmd_update.cmd.cmd_buf_addr,
- cmd_update.cmd.size);
rc = res->hw_intf->hw_ops.process_cmd(
res->hw_intf->hw_priv,
cmd_update.cmd_type, &cmd_update,
@@ -280,6 +289,12 @@
hw_entry[num_ent].handle =
cmd_desc[i].mem_handle;
hw_entry[num_ent].offset = cmd_desc[i].offset;
+ CAM_DBG(CAM_ISP,
+ "Meta_Left num_ent=%d handle=0x%x, len=%u, offset=%u",
+ num_ent,
+ hw_entry[num_ent].handle,
+ hw_entry[num_ent].len,
+ hw_entry[num_ent].offset);
if (cmd_meta_data ==
CAM_ISP_PACKET_META_DMI_LEFT)
@@ -295,6 +310,12 @@
hw_entry[num_ent].handle =
cmd_desc[i].mem_handle;
hw_entry[num_ent].offset = cmd_desc[i].offset;
+ CAM_DBG(CAM_ISP,
+ "Meta_Right num_ent=%d handle=0x%x, len=%u, offset=%u",
+ num_ent,
+ hw_entry[num_ent].handle,
+ hw_entry[num_ent].len,
+ hw_entry[num_ent].offset);
if (cmd_meta_data ==
CAM_ISP_PACKET_META_DMI_RIGHT)
@@ -308,7 +329,12 @@
hw_entry[num_ent].handle =
cmd_desc[i].mem_handle;
hw_entry[num_ent].offset = cmd_desc[i].offset;
-
+ CAM_DBG(CAM_ISP,
+ "Meta_Common num_ent=%d handle=0x%x, len=%u, offset=%u",
+ num_ent,
+ hw_entry[num_ent].handle,
+ hw_entry[num_ent].len,
+ hw_entry[num_ent].offset);
if (cmd_meta_data == CAM_ISP_PACKET_META_DMI_COMMON)
hw_entry[num_ent].flags = 0x1;
@@ -647,6 +673,12 @@
prepare->hw_update_entries[num_ent].len = io_cfg_used_bytes;
prepare->hw_update_entries[num_ent].offset =
kmd_buf_info->offset;
+ CAM_DBG(CAM_ISP,
+ "num_ent=%d handle=0x%x, len=%u, offset=%u",
+ num_ent,
+ prepare->hw_update_entries[num_ent].handle,
+ prepare->hw_update_entries[num_ent].len,
+ prepare->hw_update_entries[num_ent].offset);
num_ent++;
kmd_buf_info->used_bytes += io_cfg_used_bytes;
@@ -741,6 +773,12 @@
prepare->hw_update_entries[num_ent].len = reg_update_size;
prepare->hw_update_entries[num_ent].offset =
kmd_buf_info->offset;
+ CAM_DBG(CAM_ISP,
+ "num_ent=%d handle=0x%x, len=%u, offset=%u",
+ num_ent,
+ prepare->hw_update_entries[num_ent].handle,
+ prepare->hw_update_entries[num_ent].len,
+ prepare->hw_update_entries[num_ent].offset);
num_ent++;
kmd_buf_info->used_bytes += reg_update_size;
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
index 3edae4a..29b9e11 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
@@ -20,6 +20,7 @@
#include "cam_soc_util.h"
#include "cam_io_util.h"
#include "cam_debug_util.h"
+#include "cam_cpas_api.h"
/* Timeout value in msec */
#define IFE_CSID_TIMEOUT 1000
@@ -286,67 +287,49 @@
}
static int cam_ife_csid_cid_get(struct cam_ife_csid_hw *csid_hw,
- struct cam_isp_resource_node **res, int32_t vc, uint32_t dt,
- uint32_t res_type)
+ struct cam_isp_resource_node **res, int32_t vc, uint32_t dt)
{
- int rc = 0;
struct cam_ife_csid_cid_data *cid_data;
- uint32_t i = 0, j = 0;
+ uint32_t i = 0;
+ *res = NULL;
+
+ /* Return already reserved CID if the VC/DT matches */
for (i = 0; i < CAM_IFE_CSID_CID_RES_MAX; i++) {
if (csid_hw->cid_res[i].res_state >=
CAM_ISP_RESOURCE_STATE_RESERVED) {
cid_data = (struct cam_ife_csid_cid_data *)
csid_hw->cid_res[i].res_priv;
- if (res_type == CAM_ISP_IFE_IN_RES_TPG) {
- if (cid_data->tpg_set) {
- cid_data->cnt++;
- *res = &csid_hw->cid_res[i];
- break;
- }
- } else {
- if (cid_data->vc == vc && cid_data->dt == dt) {
- cid_data->cnt++;
- *res = &csid_hw->cid_res[i];
- break;
- }
+ if (cid_data->vc == vc && cid_data->dt == dt) {
+ cid_data->cnt++;
+ *res = &csid_hw->cid_res[i];
+ return 0;
}
}
}
- if (i == CAM_IFE_CSID_CID_RES_MAX) {
- if (res_type == CAM_ISP_IFE_IN_RES_TPG) {
- CAM_ERR(CAM_ISP, "CSID:%d TPG CID not available",
- csid_hw->hw_intf->hw_idx);
- rc = -EINVAL;
- }
-
- for (j = 0; j < CAM_IFE_CSID_CID_RES_MAX; j++) {
- if (csid_hw->cid_res[j].res_state ==
- CAM_ISP_RESOURCE_STATE_AVAILABLE) {
- cid_data = (struct cam_ife_csid_cid_data *)
- csid_hw->cid_res[j].res_priv;
- cid_data->vc = vc;
- cid_data->dt = dt;
- cid_data->cnt = 1;
- csid_hw->cid_res[j].res_state =
- CAM_ISP_RESOURCE_STATE_RESERVED;
- *res = &csid_hw->cid_res[j];
- CAM_DBG(CAM_ISP, "CSID:%d CID %d allocated",
- csid_hw->hw_intf->hw_idx,
- csid_hw->cid_res[j].res_id);
- break;
- }
- }
-
- if (j == CAM_IFE_CSID_CID_RES_MAX) {
- CAM_ERR(CAM_ISP, "CSID:%d Free cid is not available",
- csid_hw->hw_intf->hw_idx);
- rc = -EINVAL;
+ for (i = 0; i < CAM_IFE_CSID_CID_RES_MAX; i++) {
+ if (csid_hw->cid_res[i].res_state ==
+ CAM_ISP_RESOURCE_STATE_AVAILABLE) {
+ cid_data = (struct cam_ife_csid_cid_data *)
+ csid_hw->cid_res[i].res_priv;
+ cid_data->vc = vc;
+ cid_data->dt = dt;
+ cid_data->cnt = 1;
+ csid_hw->cid_res[i].res_state =
+ CAM_ISP_RESOURCE_STATE_RESERVED;
+ *res = &csid_hw->cid_res[i];
+ CAM_DBG(CAM_ISP, "CSID:%d CID %d allocated",
+ csid_hw->hw_intf->hw_idx,
+ csid_hw->cid_res[i].res_id);
+ return 0;
}
}
- return rc;
+ CAM_ERR(CAM_ISP, "CSID:%d Free cid is not available",
+ csid_hw->hw_intf->hw_idx);
+
+ return -EINVAL;
}
@@ -547,6 +530,7 @@
{
int rc = 0;
struct cam_ife_csid_cid_data *cid_data;
+ uint32_t camera_hw_version;
CAM_DBG(CAM_ISP,
"CSID:%d res_sel:0x%x Lane type:%d lane_num:%d dt:%d vc:%d",
@@ -614,12 +598,40 @@
goto end;
}
- if (cid_reserv->in_port->res_type == CAM_ISP_IFE_IN_RES_PHY_3 &&
- csid_hw->hw_intf->hw_idx != 2) {
+ if (csid_hw->csi2_reserve_cnt == UINT_MAX) {
+ CAM_ERR(CAM_ISP,
+ "CSID%d reserve cnt reached max",
+ csid_hw->hw_intf->hw_idx);
rc = -EINVAL;
goto end;
}
+ rc = cam_cpas_get_cpas_hw_version(&camera_hw_version);
+ if (rc) {
+ CAM_ERR(CAM_ISP, "Failed to get HW version rc:%d", rc);
+ goto end;
+ }
+ CAM_DBG(CAM_ISP, "HW version: %d", camera_hw_version);
+
+ switch (camera_hw_version) {
+ case CAM_CPAS_TITAN_NONE:
+ case CAM_CPAS_TITAN_MAX:
+ CAM_ERR(CAM_ISP, "Invalid HW version: %d", camera_hw_version);
+ break;
+ case CAM_CPAS_TITAN_170_V100:
+ case CAM_CPAS_TITAN_170_V110:
+ case CAM_CPAS_TITAN_170_V120:
+ if (cid_reserv->in_port->res_type == CAM_ISP_IFE_IN_RES_PHY_3 &&
+ csid_hw->hw_intf->hw_idx != 2) {
+ rc = -EINVAL;
+ goto end;
+ }
+ break;
+ default:
+ break;
+ }
+ CAM_DBG(CAM_ISP, "Reserve_cnt %u", csid_hw->csi2_reserve_cnt);
+
if (csid_hw->csi2_reserve_cnt) {
/* current configure res type should match requested res type */
if (csid_hw->res_type != cid_reserv->in_port->res_type) {
@@ -652,12 +664,53 @@
}
}
+ switch (cid_reserv->res_id) {
+ case CAM_IFE_PIX_PATH_RES_IPP:
+ if (csid_hw->ipp_res.res_state !=
+ CAM_ISP_RESOURCE_STATE_AVAILABLE) {
+ CAM_DBG(CAM_ISP,
+ "CSID:%d IPP resource not available",
+ csid_hw->hw_intf->hw_idx);
+ rc = -EINVAL;
+ goto end;
+ }
+ break;
+ case CAM_IFE_PIX_PATH_RES_RDI_0:
+ case CAM_IFE_PIX_PATH_RES_RDI_1:
+ case CAM_IFE_PIX_PATH_RES_RDI_2:
+ case CAM_IFE_PIX_PATH_RES_RDI_3:
+ if (csid_hw->rdi_res[cid_reserv->res_id].res_state !=
+ CAM_ISP_RESOURCE_STATE_AVAILABLE) {
+ CAM_ERR(CAM_ISP,
+ "CSID:%d RDI:%d resource not available",
+ csid_hw->hw_intf->hw_idx,
+ cid_reserv->res_id);
+ rc = -EINVAL;
+ goto end;
+ }
+ break;
+ default:
+ CAM_ERR(CAM_ISP, "CSID%d: Invalid csid path",
+ csid_hw->hw_intf->hw_idx);
+ rc = -EINVAL;
+ goto end;
+ }
+
+ rc = cam_ife_csid_cid_get(csid_hw,
+ &cid_reserv->node_res,
+ cid_reserv->in_port->vc,
+ cid_reserv->in_port->dt);
+ if (rc) {
+ CAM_ERR(CAM_ISP, "CSID:%d CID Reserve failed res_type %d",
+ csid_hw->hw_intf->hw_idx,
+ cid_reserv->in_port->res_type);
+ goto end;
+ }
+ cid_data = (struct cam_ife_csid_cid_data *)
+ cid_reserv->node_res->res_priv;
+
if (!csid_hw->csi2_reserve_cnt) {
csid_hw->res_type = cid_reserv->in_port->res_type;
- /* Take the first CID resource*/
- csid_hw->cid_res[0].res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
- cid_data = (struct cam_ife_csid_cid_data *)
- csid_hw->cid_res[0].res_priv;
csid_hw->csi2_rx_cfg.lane_cfg =
cid_reserv->in_port->lane_cfg;
@@ -699,71 +752,13 @@
csid_hw->csi2_rx_cfg.phy_sel =
(cid_reserv->in_port->res_type & 0xFF) - 1;
}
-
- cid_data->vc = cid_reserv->in_port->vc;
- cid_data->dt = cid_reserv->in_port->dt;
- cid_data->cnt = 1;
- cid_reserv->node_res = &csid_hw->cid_res[0];
- csid_hw->csi2_reserve_cnt++;
-
- CAM_DBG(CAM_ISP,
- "CSID:%d CID :%d resource acquired successfully",
- csid_hw->hw_intf->hw_idx,
- cid_reserv->node_res->res_id);
- } else {
- switch (cid_reserv->res_id) {
- case CAM_IFE_PIX_PATH_RES_IPP:
- if (csid_hw->ipp_res.res_state !=
- CAM_ISP_RESOURCE_STATE_AVAILABLE) {
- CAM_DBG(CAM_ISP,
- "CSID:%d IPP resource not available",
- csid_hw->hw_intf->hw_idx);
- rc = -EINVAL;
- goto end;
- }
- break;
- case CAM_IFE_PIX_PATH_RES_RDI_0:
- case CAM_IFE_PIX_PATH_RES_RDI_1:
- case CAM_IFE_PIX_PATH_RES_RDI_2:
- case CAM_IFE_PIX_PATH_RES_RDI_3:
- if (csid_hw->rdi_res[cid_reserv->res_id].res_state !=
- CAM_ISP_RESOURCE_STATE_AVAILABLE) {
- CAM_DBG(CAM_ISP,
- "CSID:%d RDI:%d resource not available",
- csid_hw->hw_intf->hw_idx,
- cid_reserv->res_id);
- rc = -EINVAL;
- goto end;
- }
- break;
- default:
- CAM_ERR(CAM_ISP, "CSID%d: Invalid csid path",
- csid_hw->hw_intf->hw_idx);
- rc = -EINVAL;
- goto end;
- }
-
- rc = cam_ife_csid_cid_get(csid_hw,
- &cid_reserv->node_res,
- cid_reserv->in_port->vc,
- cid_reserv->in_port->dt,
- cid_reserv->in_port->res_type);
- /* if success then increment the reserve count */
- if (!rc) {
- if (csid_hw->csi2_reserve_cnt == UINT_MAX) {
- CAM_ERR(CAM_ISP,
- "CSID%d reserve cnt reached max",
- csid_hw->hw_intf->hw_idx);
- rc = -EINVAL;
- } else {
- csid_hw->csi2_reserve_cnt++;
- CAM_DBG(CAM_ISP, "CSID:%d CID:%d acquired",
- csid_hw->hw_intf->hw_idx,
- cid_reserv->node_res->res_id);
- }
- }
}
+ csid_hw->csi2_reserve_cnt++;
+ CAM_DBG(CAM_ISP, "CSID:%d CID:%d acquired",
+ csid_hw->hw_intf->hw_idx,
+ cid_reserv->node_res->res_id);
+
end:
return rc;
}
@@ -2415,12 +2410,24 @@
return -EINVAL;
}
csid_stop = (struct cam_csid_hw_stop_args *) stop_args;
+
+ if (!csid_stop->num_res) {
+ CAM_ERR(CAM_ISP, "CSID: Invalid args");
+ return -EINVAL;
+ }
+
csid_hw_info = (struct cam_hw_info *)hw_priv;
csid_hw = (struct cam_ife_csid_hw *)csid_hw_info->core_info;
+ CAM_DBG(CAM_ISP, "CSID:%d num_res %d",
+ csid_hw->hw_intf->hw_idx,
+ csid_stop->num_res);
/* Stop the resource first */
for (i = 0; i < csid_stop->num_res; i++) {
res = csid_stop->node_res[i];
+ CAM_DBG(CAM_ISP, "CSID:%d res_type %d res_id %d",
+ csid_hw->hw_intf->hw_idx,
+ res->res_type, res->res_id);
switch (res->res_type) {
case CAM_ISP_RESOURCE_CID:
if (csid_hw->res_type == CAM_ISP_IFE_IN_RES_TPG)
@@ -2777,6 +2784,7 @@
{
int rc = -EINVAL;
uint32_t i;
+ uint32_t num_paths;
struct cam_ife_csid_path_cfg *path_data;
struct cam_ife_csid_cid_data *cid_data;
struct cam_hw_info *csid_hw_info;
@@ -2828,8 +2836,10 @@
ife_csid_hw->hw_intf->hw_ops.write = cam_ife_csid_write;
ife_csid_hw->hw_intf->hw_ops.process_cmd = cam_ife_csid_process_cmd;
- /*Initialize the CID resoure */
- for (i = 0; i < CAM_IFE_CSID_CID_RES_MAX; i++) {
+ num_paths = ife_csid_hw->csid_info->csid_reg->cmn_reg->no_pix +
+ ife_csid_hw->csid_info->csid_reg->cmn_reg->no_rdis;
+ /* Initialize the CID resource */
+ for (i = 0; i < num_paths; i++) {
ife_csid_hw->cid_res[i].res_type = CAM_ISP_RESOURCE_CID;
ife_csid_hw->cid_res[i].res_id = i;
ife_csid_hw->cid_res[i].res_state =
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
index 97d076a..fdeee54 100644
--- a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
@@ -1171,7 +1171,7 @@
"jpeg_command_queue",
CAM_JPEG_WORKQ_NUM_TASK,
&g_jpeg_hw_mgr.work_process_frame,
- CRM_WORKQ_USAGE_NON_IRQ);
+ CRM_WORKQ_USAGE_NON_IRQ, 0);
if (rc) {
CAM_ERR(CAM_JPEG, "unable to create a worker %d", rc);
goto work_process_frame_failed;
@@ -1181,7 +1181,7 @@
"jpeg_message_queue",
CAM_JPEG_WORKQ_NUM_TASK,
&g_jpeg_hw_mgr.work_process_irq_cb,
- CRM_WORKQ_USAGE_IRQ);
+ CRM_WORKQ_USAGE_IRQ, 0);
if (rc) {
CAM_ERR(CAM_JPEG, "unable to create a worker %d", rc);
goto work_process_irq_cb_failed;
diff --git a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c
index a60661e..0f34c9f 100644
--- a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c
@@ -989,7 +989,8 @@
CAM_DBG(CAM_LRME, "Create submit workq for %s", buf);
rc = cam_req_mgr_workq_create(buf,
CAM_LRME_WORKQ_NUM_TASK,
- &hw_device->work, CRM_WORKQ_USAGE_NON_IRQ);
+ &hw_device->work, CRM_WORKQ_USAGE_NON_IRQ,
+ 0);
if (rc) {
CAM_ERR(CAM_LRME,
"Unable to create a worker, rc=%d", rc);
diff --git a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_dev.c b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_dev.c
index da42c84..ec392f5 100644
--- a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_dev.c
+++ b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_dev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
@@ -28,8 +28,6 @@
#include "cam_mem_mgr_api.h"
#include "cam_smmu_api.h"
-#define CAM_LRME_HW_WORKQ_NUM_TASK 30
-
static int cam_lrme_hw_dev_util_cdm_acquire(struct cam_lrme_core *lrme_core,
struct cam_hw_info *lrme_hw)
{
@@ -122,7 +120,7 @@
rc = cam_req_mgr_workq_create("cam_lrme_hw_worker",
CAM_LRME_HW_WORKQ_NUM_TASK,
- &lrme_core->work, CRM_WORKQ_USAGE_IRQ);
+ &lrme_core->work, CRM_WORKQ_USAGE_IRQ, 0);
if (rc) {
CAM_ERR(CAM_LRME, "Unable to create a workq, rc=%d", rc);
goto free_memory;
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
index 4602d6c..060aaf2 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
@@ -2324,6 +2324,7 @@
int cam_req_mgr_link(struct cam_req_mgr_link_info *link_info)
{
int rc = 0;
+ int wq_flag = 0;
char buf[128];
struct cam_create_dev_hdl root_dev;
struct cam_req_mgr_core_session *cam_session;
@@ -2394,8 +2395,9 @@
/* Create worker for current link */
snprintf(buf, sizeof(buf), "%x-%x",
link_info->session_hdl, link->link_hdl);
+ wq_flag = CAM_WORKQ_FLAG_HIGH_PRIORITY | CAM_WORKQ_FLAG_SERIAL;
rc = cam_req_mgr_workq_create(buf, CRM_WORKQ_NUM_TASKS,
- &link->workq, CRM_WORKQ_USAGE_NON_IRQ);
+ &link->workq, CRM_WORKQ_USAGE_NON_IRQ, wq_flag);
if (rc < 0) {
CAM_ERR(CAM_CRM, "FATAL: unable to create worker");
__cam_req_mgr_destroy_link_info(link);
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_workq.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_workq.c
index 066efd6..3798ef8 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_workq.c
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_workq.c
@@ -178,9 +178,10 @@
}
int cam_req_mgr_workq_create(char *name, int32_t num_tasks,
- struct cam_req_mgr_core_workq **workq, enum crm_workq_context in_irq)
+ struct cam_req_mgr_core_workq **workq, enum crm_workq_context in_irq,
+ int flags)
{
- int32_t i;
+ int32_t i, wq_flags = 0, max_active_tasks = 0;
struct crm_workq_task *task;
struct cam_req_mgr_core_workq *crm_workq = NULL;
char buf[128] = "crm_workq-";
@@ -192,10 +193,17 @@
if (crm_workq == NULL)
return -ENOMEM;
+ wq_flags |= WQ_UNBOUND;
+ if (flags & CAM_WORKQ_FLAG_HIGH_PRIORITY)
+ wq_flags |= WQ_HIGHPRI;
+
+ if (flags & CAM_WORKQ_FLAG_SERIAL)
+ max_active_tasks = 1;
+
strlcat(buf, name, sizeof(buf));
CAM_DBG(CAM_CRM, "create workque crm_workq-%s", name);
crm_workq->job = alloc_workqueue(buf,
- WQ_HIGHPRI | WQ_UNBOUND, 0, NULL);
+ wq_flags, max_active_tasks, NULL);
if (!crm_workq->job) {
kfree(crm_workq);
return -ENOMEM;
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_workq.h b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_workq.h
index eb3b804..af76ae46 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_workq.h
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_workq.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2018, 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
@@ -23,6 +23,15 @@
#include "cam_req_mgr_core.h"
+/* Flag to create a high priority workq */
+#define CAM_WORKQ_FLAG_HIGH_PRIORITY (1 << 0)
+
+/* This flag ensures only one task from a given
+ * workq will execute at any given point on any
+ * given CPU.
+ */
+#define CAM_WORKQ_FLAG_SERIAL (1 << 1)
+
/* Task priorities, lower the number higher the priority*/
enum crm_task_priority {
CRM_TASK_PRIORITY_0,
@@ -101,11 +110,14 @@
* @num_task : Num_tasks to be allocated for workq
* @workq : Double pointer worker
* @in_irq : Set to one if workq might be used in irq context
+ * @flags : Bitwise OR of Flags for workq behavior.
+ * e.g. CAM_REQ_MGR_WORKQ_HIGH_PRIORITY | CAM_REQ_MGR_WORKQ_SERIAL
* This function will allocate and create workqueue and pass
* the workq pointer to caller.
*/
int cam_req_mgr_workq_create(char *name, int32_t num_tasks,
- struct cam_req_mgr_core_workq **workq, enum crm_workq_context in_irq);
+ struct cam_req_mgr_core_workq **workq, enum crm_workq_context in_irq,
+ int flags);
/**
* cam_req_mgr_workq_destroy()
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c
index a34d70c..da8ff21 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c
@@ -53,6 +53,7 @@
free_power_settings:
kfree(power_info->power_setting);
+ power_info->power_setting = NULL;
return rc;
}
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_dev.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_dev.c
index 96fdfeb..733c9e8 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_dev.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_dev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
@@ -252,6 +252,8 @@
a_ctrl->io_master_info.cci_client = NULL;
kfree(power_info->power_setting);
kfree(power_info->power_down_setting);
+ power_info->power_setting = NULL;
+ power_info->power_down_setting = NULL;
kfree(a_ctrl->soc_info.soc_private);
kfree(a_ctrl->i2c_data.per_frame);
a_ctrl->i2c_data.per_frame = NULL;
@@ -284,6 +286,8 @@
kfree(power_info->power_setting);
kfree(power_info->power_down_setting);
kfree(a_ctrl->soc_info.soc_private);
+ power_info->power_setting = NULL;
+ power_info->power_down_setting = NULL;
a_ctrl->soc_info.soc_private = NULL;
kfree(a_ctrl);
return rc;
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.c
index 9b74826..f0efd4c 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.c
@@ -191,25 +191,11 @@
int cam_flash_off(struct cam_flash_ctrl *flash_ctrl)
{
- int i = 0;
-
if (!flash_ctrl) {
CAM_ERR(CAM_FLASH, "Flash control Null");
return -EINVAL;
}
- for (i = 0; i < flash_ctrl->flash_num_sources; i++)
- if (flash_ctrl->flash_trigger[i])
- cam_res_mgr_led_trigger_event(
- flash_ctrl->flash_trigger[i],
- LED_OFF);
-
- for (i = 0; i < flash_ctrl->torch_num_sources; i++)
- if (flash_ctrl->torch_trigger[i])
- cam_res_mgr_led_trigger_event(
- flash_ctrl->torch_trigger[i],
- LED_OFF);
-
if (flash_ctrl->switch_trigger)
cam_res_mgr_led_trigger_event(flash_ctrl->switch_trigger,
LED_SWITCH_OFF);
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.c
index dfcb9fc..6f77e0e 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.c
@@ -55,6 +55,7 @@
free_power_settings:
kfree(power_info->power_setting);
+ power_info->power_setting = NULL;
return rc;
}
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_dev.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_dev.c
index d742acf..5d16a4e 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_dev.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_dev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
@@ -240,6 +240,8 @@
kfree(power_info->power_setting);
kfree(power_info->power_down_setting);
+ power_info->power_setting = NULL;
+ power_info->power_down_setting = NULL;
kfree(o_ctrl->soc_info.soc_private);
kfree(o_ctrl);
@@ -341,6 +343,8 @@
kfree(power_info->power_setting);
kfree(power_info->power_down_setting);
+ power_info->power_setting = NULL;
+ power_info->power_down_setting = NULL;
kfree(o_ctrl->soc_info.soc_private);
kfree(o_ctrl->io_master_info.cci_client);
kfree(o_ctrl);
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
index 2133932..6fe051a 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
@@ -599,7 +599,8 @@
} else {
CAM_ERR(CAM_SENSOR, "Invalid Command Type: %d",
cmd->handle_type);
- return -EINVAL;
+ rc = -EINVAL;
+ goto release_mutex;
}
pu = power_info->power_setting;
@@ -653,7 +654,7 @@
}
CAM_INFO(CAM_SENSOR,
- "Probe Succees,slot:%d,slave_addr:0x%x,sensor_id:0x%x",
+ "Probe success,slot:%d,slave_addr:0x%x,sensor_id:0x%x",
s_ctrl->soc_info.index,
s_ctrl->sensordata->slave_info.sensor_slave_addr,
s_ctrl->sensordata->slave_info.sensor_id);
diff --git a/drivers/media/platform/msm/camera/cam_sync/cam_sync.c b/drivers/media/platform/msm/camera/cam_sync/cam_sync.c
index 517b7df..55896f4 100644
--- a/drivers/media/platform/msm/camera/cam_sync/cam_sync.c
+++ b/drivers/media/platform/msm/camera/cam_sync/cam_sync.c
@@ -46,6 +46,7 @@
}
*sync_obj = idx;
+ CAM_DBG(CAM_SYNC, "sync_obj: %i", *sync_obj);
spin_unlock_bh(&sync_dev->row_spinlocks[idx]);
return rc;
@@ -170,21 +171,24 @@
INIT_LIST_HEAD(&sync_list);
if (sync_obj >= CAM_SYNC_MAX_OBJS || sync_obj <= 0) {
- CAM_ERR(CAM_SYNC, "Error: Out of range sync obj");
+ CAM_ERR(CAM_SYNC, "Error: Out of range sync obj (0 <= %d < %d)",
+ sync_obj, CAM_SYNC_MAX_OBJS);
return -EINVAL;
}
row = sync_dev->sync_table + sync_obj;
+ spin_lock_bh(&sync_dev->row_spinlocks[sync_obj]);
if (row->state == CAM_SYNC_STATE_INVALID) {
+ spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]);
CAM_ERR(CAM_SYNC,
"Error: accessing an uninitialized sync obj = %d",
sync_obj);
return -EINVAL;
}
- spin_lock_bh(&sync_dev->row_spinlocks[sync_obj]);
if (row->type == CAM_SYNC_TYPE_GROUP) {
spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]);
- CAM_ERR(CAM_SYNC, "Error: Signaling a GROUP sync object = %d",
+ CAM_ERR(CAM_SYNC,
+ "Error: Signaling a GROUP sync object = %d",
sync_obj);
return -EINVAL;
}
@@ -368,6 +372,7 @@
int cam_sync_destroy(int32_t sync_obj)
{
+ CAM_DBG(CAM_SYNC, "sync_obj: %i", sync_obj);
return cam_sync_deinit_object(sync_dev->sync_table, sync_obj);
}
diff --git a/drivers/media/platform/msm/camera/cam_sync/cam_sync_util.c b/drivers/media/platform/msm/camera/cam_sync/cam_sync_util.c
index ed69829..43bce51 100644
--- a/drivers/media/platform/msm/camera/cam_sync/cam_sync_util.c
+++ b/drivers/media/platform/msm/camera/cam_sync/cam_sync_util.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
@@ -51,8 +51,9 @@
init_completion(&row->signaled);
INIT_LIST_HEAD(&row->callback_list);
INIT_LIST_HEAD(&row->user_payload_list);
- CAM_DBG(CAM_SYNC, "Sync object Initialised: sync_id:%u row_state:%u ",
- row->sync_id, row->state);
+ CAM_DBG(CAM_SYNC,
+ "row name:%s sync_id:%i [idx:%u] row_state:%u ",
+ row->name, row->sync_id, idx, row->state);
return 0;
}
@@ -74,9 +75,11 @@
* counts of error, active and success states of all children objects
*/
for (i = 0; i < num_objs; i++) {
+ spin_lock_bh(&sync_dev->row_spinlocks[sync_objs[i]]);
child_row = table + sync_objs[i];
switch (child_row->state) {
case CAM_SYNC_STATE_SIGNALED_ERROR:
+ spin_unlock_bh(&sync_dev->row_spinlocks[sync_objs[i]]);
return CAM_SYNC_STATE_SIGNALED_ERROR;
case CAM_SYNC_STATE_SIGNALED_SUCCESS:
success_count++;
@@ -87,8 +90,10 @@
default:
CAM_ERR(CAM_SYNC,
"Invalid state of child object during merge");
+ spin_unlock_bh(&sync_dev->row_spinlocks[sync_objs[i]]);
return CAM_SYNC_STATE_SIGNALED_ERROR;
}
+ spin_unlock_bh(&sync_dev->row_spinlocks[sync_objs[i]]);
}
if (active_count)
@@ -209,12 +214,16 @@
if (!table || idx <= 0 || idx >= CAM_SYNC_MAX_OBJS)
return -EINVAL;
+ CAM_DBG(CAM_SYNC,
+ "row name:%s sync_id:%i [idx:%u] row_state:%u",
+ row->name, row->sync_id, idx, row->state);
+
spin_lock_bh(&sync_dev->row_spinlocks[idx]);
if (row->state == CAM_SYNC_STATE_INVALID) {
+ spin_unlock_bh(&sync_dev->row_spinlocks[idx]);
CAM_ERR(CAM_SYNC,
"Error: accessing an uninitialized sync obj: idx = %d",
idx);
- spin_unlock_bh(&sync_dev->row_spinlocks[idx]);
return -EINVAL;
}
row->state = CAM_SYNC_STATE_INVALID;
@@ -252,9 +261,9 @@
spin_lock_bh(&sync_dev->row_spinlocks[child_info->sync_id]);
if (child_row->state == CAM_SYNC_STATE_INVALID) {
+ list_del_init(&child_info->list);
spin_unlock_bh(&sync_dev->row_spinlocks[
child_info->sync_id]);
- list_del_init(&child_info->list);
kfree(child_info);
continue;
}
@@ -262,9 +271,8 @@
cam_sync_util_cleanup_parents_list(child_row,
SYNC_LIST_CLEAN_ONE, idx);
- spin_unlock_bh(&sync_dev->row_spinlocks[child_info->sync_id]);
-
list_del_init(&child_info->list);
+ spin_unlock_bh(&sync_dev->row_spinlocks[child_info->sync_id]);
kfree(child_info);
}
@@ -277,9 +285,9 @@
spin_lock_bh(&sync_dev->row_spinlocks[parent_info->sync_id]);
if (parent_row->state == CAM_SYNC_STATE_INVALID) {
+ list_del_init(&parent_info->list);
spin_unlock_bh(&sync_dev->row_spinlocks[
parent_info->sync_id]);
- list_del_init(&parent_info->list);
kfree(parent_info);
continue;
}
@@ -287,9 +295,8 @@
cam_sync_util_cleanup_children_list(parent_row,
SYNC_LIST_CLEAN_ONE, idx);
- spin_unlock_bh(&sync_dev->row_spinlocks[parent_info->sync_id]);
-
list_del_init(&parent_info->list);
+ spin_unlock_bh(&sync_dev->row_spinlocks[parent_info->sync_id]);
kfree(parent_info);
}
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_packet_util.c b/drivers/media/platform/msm/camera/cam_utils/cam_packet_util.c
index 30ab075..db2629d 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_packet_util.c
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_packet_util.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
@@ -171,6 +171,24 @@
patch_desc[i].dst_buf_hdl, patch_desc[i].dst_offset,
patch_desc[i].src_buf_hdl, patch_desc[i].src_offset);
+ if (patch_desc[i].src_offset >= src_buf_size) {
+ CAM_ERR_RATE_LIMIT(CAM_UTIL,
+ "Inval src offset:0x%x src len:0x%x reqid:%lld",
+ patch_desc[i].src_offset,
+ (unsigned int)src_buf_size,
+ packet->header.request_id);
+ return -EINVAL;
+ }
+
+ if (patch_desc[i].dst_offset >= dst_buf_len) {
+ CAM_ERR_RATE_LIMIT(CAM_UTIL,
+ "Inval dst offset:0x%x dst len:0x%x reqid:%lld",
+ patch_desc[i].dst_offset,
+ (unsigned int)dst_buf_len,
+ packet->header.request_id);
+ return -EINVAL;
+ }
+
dst_cpu_addr = (uint32_t *)((uint8_t *)dst_cpu_addr +
patch_desc[i].dst_offset);
temp += patch_desc[i].src_offset;
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
index 0b84327..3832d63 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
@@ -3847,7 +3847,7 @@
int msm_isp_update_axi_stream(struct vfe_device *vfe_dev, void *arg)
{
- int rc = 0, i;
+ int rc = 0, i, j, k;
struct msm_vfe_axi_stream *stream_info;
struct msm_vfe_axi_stream_update_cmd *update_cmd = arg;
struct msm_vfe_axi_stream_cfg_update_info *update_info = NULL;
@@ -3884,7 +3884,9 @@
update_cmd->update_type !=
UPDATE_STREAM_REMOVE_BUFQ &&
update_cmd->update_type !=
- UPDATE_STREAM_SW_FRAME_DROP) {
+ UPDATE_STREAM_SW_FRAME_DROP &&
+ update_cmd->update_type !=
+ UPDATE_STREAM_REQUEST_FRAMES_VER2) {
pr_err("%s: Invalid stream state %d, update cmd %d\n",
__func__, stream_info->state,
stream_info->stream_id);
@@ -4126,8 +4128,16 @@
}
vfe_idx = msm_isp_get_vfe_idx_for_stream(
vfe_dev, stream_info);
- msm_isp_stream_axi_cfg_update(vfe_dev, stream_info,
- update_info);
+ for (j = 0; j < stream_info->num_planes; j++) {
+ stream_info->plane_cfg[vfe_idx][j] =
+ update_info->plane_cfg[j];
+ for (k = 0; k < stream_info->num_isp; k++) {
+ vfe_dev = stream_info->vfe_dev[k];
+ vfe_dev->hw_info->vfe_ops.axi_ops.
+ cfg_wm_reg(vfe_dev,
+ stream_info, j);
+ }
+ }
}
break;
}
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util_32.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util_32.c
index 55a10ca..b5a6f44 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util_32.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util_32.c
@@ -25,12 +25,16 @@
struct msm_vfe_axi_shared_data *axi_data,
struct msm_vfe32_axi_stream_request_cmd *stream_cfg_cmd)
{
- uint32_t i = stream_cfg_cmd->stream_src;
+ int i, rc = -1;
- if (i >= VFE_AXI_SRC_MAX) {
- pr_err("%s:%d invalid stream_src %d\n", __func__, __LINE__,
- stream_cfg_cmd->stream_src);
- return -EINVAL;
+ for (i = 0; i < MAX_NUM_STREAM; i++) {
+ if (axi_data->stream_info[i].state == AVAILABLE)
+ break;
+ }
+
+ if (i == MAX_NUM_STREAM) {
+ pr_err("%s: No free stream\n", __func__);
+ return rc;
}
if ((axi_data->stream_handle_cnt << 8) == 0)
@@ -1602,6 +1606,8 @@
vfe_dev->hw_info->vfe_ops.core_ops.reg_update(vfe_dev, 0xF);
msm_isp_update_camif_output_count(vfe_dev, stream_cfg_cmd);
msm_isp_update_rdi_output_count(vfe_dev, stream_cfg_cmd);
+ /*Configure UB*/
+ vfe_dev->hw_info->vfe_ops.axi_ops.cfg_ub(vfe_dev);
if (camif_update == ENABLE_CAMIF) {
atomic_set(&vfe_dev->error_info.overflow_state,
NO_OVERFLOW);
@@ -1735,7 +1741,6 @@
{
int rc = 0;
struct msm_vfe_axi_stream_cfg_cmd *stream_cfg_cmd = arg;
- struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
enum msm_isp_camif_update_state camif_update;
rc = msm_isp_axi_check_stream_state(vfe_dev, stream_cfg_cmd);
@@ -1744,10 +1749,6 @@
return rc;
}
- if (axi_data->num_active_stream == 0) {
- /*Configure UB*/
- vfe_dev->hw_info->vfe_ops.axi_ops.cfg_ub(vfe_dev);
- }
camif_update = msm_isp_get_camif_update_state(vfe_dev, stream_cfg_cmd);
if (stream_cfg_cmd->cmd == START_STREAM) {
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
index b589afa..e671122 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
@@ -410,8 +410,12 @@
pr_err("%s: Fetch engine config failed\n", __func__);
return -EINVAL;
}
- for (i = 0; i < stream_info->num_planes; i++)
+ for (i = 0; i < stream_info->num_planes; i++) {
+ vfe_dev->hw_info->vfe_ops.axi_ops.enable_wm(
+ vfe_dev->vfe_base,
+ stream_info->wm[vfe_idx][i], 1);
wm_reload_mask |= (1 << stream_info->wm[vfe_idx][i]);
+ }
vfe_dev->hw_info->vfe_ops.core_ops.reg_update(vfe_dev,
VFE_SRC_MAX);
vfe_dev->hw_info->vfe_ops.axi_ops.reload_wm(vfe_dev,
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_dev.c b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_dev.c
index 7d37d7e..0811efb 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_dev.c
+++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_dev.c
@@ -32,6 +32,8 @@
#define MSM_JPEG_NAME "jpeg"
#define DEV_NAME_LEN 10
+static char devname[DEV_NAME_LEN];
+
static int msm_jpeg_open(struct inode *inode, struct file *filp)
{
int rc = 0;
@@ -159,7 +161,6 @@
struct msm_jpeg_device *msm_jpeg_device_p;
const struct of_device_id *device_id;
const struct msm_jpeg_priv_data *priv_data;
- char devname[DEV_NAME_LEN];
msm_jpeg_device_p = kzalloc(sizeof(struct msm_jpeg_device), GFP_ATOMIC);
if (!msm_jpeg_device_p) {
diff --git a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c
index 0cfddb3..276c76e 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c
@@ -58,6 +58,7 @@
#define MBPS 1000000
#define SNPS_INTERPHY_OFFSET 0x800
#define SET_THE_BIT(x) (0x1 << x)
+#define SNPS_MAX_DATA_RATE_PER_LANE 2500000000ULL
#undef CDBG
#define CDBG(fmt, args...) pr_debug(fmt, ##args)
@@ -185,7 +186,15 @@
void __iomem *csiphybase;
csiphybase = csiphy_dev->base;
+
+ if (csiphy_params->data_rate >
+ SNPS_MAX_DATA_RATE_PER_LANE * num_lanes) {
+ pr_err("unsupported data rate\n");
+ return -EINVAL;
+ }
+
local_data_rate = csiphy_params->data_rate;
+
if (mode == TWO_LANE_PHY_A)
offset = 0x0;
else if (mode == TWO_LANE_PHY_B)
@@ -208,15 +217,6 @@
diff = diff_i;
}
- if (i == (sizeof(snps_v100_freq_values)/
- sizeof(snps_v100_freq_values[0]))) {
- if (local_data_rate >
- snps_v100_freq_values[--i].default_bit_rate) {
- pr_err("unsupported data rate\n");
- return -EINVAL;
- }
- }
-
csiphy_dev->snps_programmed_data_rate = csiphy_params->data_rate;
if (mode == TWO_LANE_PHY_A) {
@@ -1706,10 +1706,8 @@
CDBG("%s:%d called\n", __func__, __LINE__);
if (csiphy_dev->csiphy_state == CSIPHY_POWER_UP) {
- pr_err("%s: csiphy invalid state %d\n", __func__,
+ pr_err("%s: csiphy current state %d\n", __func__,
csiphy_dev->csiphy_state);
- rc = -EINVAL;
- return rc;
}
CDBG("%s:%d called\n", __func__, __LINE__);
diff --git a/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c b/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c
index cd16236..f4305ea 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c
@@ -788,11 +788,101 @@
.core = &msm_eeprom_subdev_core_ops,
};
+static int msm_eeprom_get_dt_data(struct msm_eeprom_ctrl_t *e_ctrl)
+{
+ int rc = 0, i = 0;
+ struct msm_eeprom_board_info *eb_info;
+ struct msm_camera_power_ctrl_t *power_info =
+ &e_ctrl->eboard_info->power_info;
+ struct device_node *of_node = NULL;
+ struct msm_camera_gpio_conf *gconf = NULL;
+ int8_t gpio_array_size = 0;
+ uint16_t *gpio_array = NULL;
+
+ eb_info = e_ctrl->eboard_info;
+ if (e_ctrl->eeprom_device_type == MSM_CAMERA_SPI_DEVICE)
+ of_node = e_ctrl->i2c_client.
+ spi_client->spi_master->dev.of_node;
+ else if (e_ctrl->eeprom_device_type == MSM_CAMERA_PLATFORM_DEVICE)
+ of_node = e_ctrl->pdev->dev.of_node;
+ else if (e_ctrl->eeprom_device_type == MSM_CAMERA_I2C_DEVICE)
+ of_node = e_ctrl->i2c_client.client->dev.of_node;
+
+ if (!of_node) {
+ pr_err("%s: %d of_node is NULL\n", __func__, __LINE__);
+ return -ENOMEM;
+ }
+ rc = msm_camera_get_dt_vreg_data(of_node, &power_info->cam_vreg,
+ &power_info->num_vreg);
+ if (rc < 0)
+ return rc;
+
+ if (e_ctrl->userspace_probe == 0) {
+ rc = msm_camera_get_dt_power_setting_data(of_node,
+ power_info->cam_vreg, power_info->num_vreg,
+ power_info);
+ if (rc < 0)
+ goto ERROR1;
+ }
+
+ power_info->gpio_conf = kzalloc(sizeof(struct msm_camera_gpio_conf),
+ GFP_KERNEL);
+ if (!power_info->gpio_conf) {
+ rc = -ENOMEM;
+ goto ERROR2;
+ }
+ gconf = power_info->gpio_conf;
+ gpio_array_size = of_gpio_count(of_node);
+ CDBG("%s gpio count %d\n", __func__, gpio_array_size);
+
+ if (gpio_array_size > 0) {
+ gpio_array = kcalloc(gpio_array_size, sizeof(uint16_t),
+ GFP_KERNEL);
+ if (!gpio_array)
+ goto ERROR3;
+ for (i = 0; i < gpio_array_size; i++) {
+ gpio_array[i] = of_get_gpio(of_node, i);
+ CDBG("%s gpio_array[%d] = %d\n", __func__, i,
+ gpio_array[i]);
+ }
+
+ rc = msm_camera_get_dt_gpio_req_tbl(of_node, gconf,
+ gpio_array, gpio_array_size);
+ if (rc < 0) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ goto ERROR4;
+ }
+
+ rc = msm_camera_init_gpio_pin_tbl(of_node, gconf,
+ gpio_array, gpio_array_size);
+ if (rc < 0) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ goto ERROR4;
+ }
+ kfree(gpio_array);
+ }
+
+ return rc;
+ERROR4:
+ kfree(gpio_array);
+ERROR3:
+ kfree(power_info->gpio_conf);
+ERROR2:
+ kfree(power_info->cam_vreg);
+ERROR1:
+ kfree(power_info->power_setting);
+ return rc;
+}
+
static int msm_eeprom_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int rc = 0;
+ uint32_t temp = 0;
struct msm_eeprom_ctrl_t *e_ctrl = NULL;
+ struct msm_eeprom_board_info *eb_info = NULL;
+ struct device_node *of_node = client->dev.of_node;
+ struct msm_camera_power_ctrl_t *power_info = NULL;
CDBG("%s E\n", __func__);
@@ -804,41 +894,122 @@
e_ctrl = kzalloc(sizeof(*e_ctrl), GFP_KERNEL);
if (!e_ctrl)
return -ENOMEM;
+
e_ctrl->eeprom_v4l2_subdev_ops = &msm_eeprom_subdev_ops;
e_ctrl->eeprom_mutex = &msm_eeprom_mutex;
- CDBG("%s client = 0x%pK\n", __func__, client);
- e_ctrl->eboard_info = (struct msm_eeprom_board_info *)(id->driver_data);
- if (!e_ctrl->eboard_info) {
- pr_err("%s:%d board info NULL\n", __func__, __LINE__);
- rc = -EINVAL;
- goto ectrl_free;
- }
- e_ctrl->i2c_client.client = client;
+
e_ctrl->cal_data.mapdata = NULL;
e_ctrl->cal_data.map = NULL;
e_ctrl->userspace_probe = 0;
- e_ctrl->is_supported = 1;
-
+ e_ctrl->is_supported = 0;
+ if (!of_node) {
+ pr_err("%s dev.of_node NULL\n", __func__);
+ rc = -EINVAL;
+ goto ectrl_free;
+ }
/* Set device type as I2C */
e_ctrl->eeprom_device_type = MSM_CAMERA_I2C_DEVICE;
e_ctrl->i2c_client.i2c_func_tbl = &msm_eeprom_qup_func_tbl;
- if (e_ctrl->eboard_info->i2c_slaveaddr != 0)
- e_ctrl->i2c_client.client->addr =
- e_ctrl->eboard_info->i2c_slaveaddr;
+ e_ctrl->eboard_info = kzalloc(sizeof(
+ struct msm_eeprom_board_info), GFP_KERNEL);
+ if (!e_ctrl->eboard_info) {
+ rc = -ENOMEM;
+ goto ectrl_free;
+ }
+ eb_info = e_ctrl->eboard_info;
+ power_info = &eb_info->power_info;
+ e_ctrl->i2c_client.client = client;
+ power_info->dev = &client->dev;
/*Get clocks information*/
rc = msm_camera_i2c_dev_get_clk_info(
&e_ctrl->i2c_client.client->dev,
- &e_ctrl->eboard_info->power_info.clk_info,
- &e_ctrl->eboard_info->power_info.clk_ptr,
- &e_ctrl->eboard_info->power_info.clk_info_size);
+ &power_info->clk_info,
+ &power_info->clk_ptr,
+ &power_info->clk_info_size);
if (rc < 0) {
pr_err("failed: msm_camera_get_clk_info rc %d", rc);
- goto ectrl_free;
+ goto board_free;
}
- /*IMPLEMENT READING PART*/
+ rc = of_property_read_u32(of_node, "cell-index",
+ &e_ctrl->subdev_id);
+ CDBG("cell-index %d, rc %d\n", e_ctrl->subdev_id, rc);
+ if (rc < 0) {
+ pr_err("failed rc %d\n", rc);
+ goto board_free;
+ }
+
+ rc = of_property_read_string(of_node, "qcom,eeprom-name",
+ &eb_info->eeprom_name);
+ CDBG("%s qcom,eeprom-name %s, rc %d\n", __func__,
+ eb_info->eeprom_name, rc);
+ if (rc < 0) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ e_ctrl->userspace_probe = 1;
+ }
+
+ rc = msm_eeprom_get_dt_data(e_ctrl);
+ if (rc < 0)
+ goto board_free;
+
+ if (e_ctrl->userspace_probe == 0) {
+ rc = of_property_read_u32(of_node, "qcom,slave-addr",
+ &temp);
+ if (rc < 0) {
+ pr_err("%s failed rc %d\n", __func__, rc);
+ goto board_free;
+ }
+
+ rc = of_property_read_u32(of_node, "qcom,i2c-freq-mode",
+ &e_ctrl->i2c_freq_mode);
+ CDBG("qcom,i2c_freq_mode %d, rc %d\n",
+ e_ctrl->i2c_freq_mode, rc);
+ if (rc < 0) {
+ pr_err("%s qcom,i2c-freq-mode read fail. Setting to 0 %d\n",
+ __func__, rc);
+ e_ctrl->i2c_freq_mode = 0;
+ }
+ if (e_ctrl->i2c_freq_mode >= I2C_MAX_MODES) {
+ pr_err("%s:%d invalid i2c_freq_mode = %d\n",
+ __func__, __LINE__, e_ctrl->i2c_freq_mode);
+ e_ctrl->i2c_freq_mode = 0;
+ }
+ eb_info->i2c_slaveaddr = temp;
+ CDBG("qcom,slave-addr = 0x%X\n", eb_info->i2c_slaveaddr);
+ eb_info->i2c_freq_mode = e_ctrl->i2c_freq_mode;
+
+ rc = msm_eeprom_parse_memory_map(of_node, &e_ctrl->cal_data);
+ if (rc < 0)
+ goto board_free;
+
+ rc = msm_camera_power_up(power_info, e_ctrl->eeprom_device_type,
+ &e_ctrl->i2c_client);
+ if (rc) {
+ pr_err("failed rc %d\n", rc);
+ goto memdata_free;
+ }
+
+ rc = read_eeprom_memory(e_ctrl, &e_ctrl->cal_data);
+ if (rc < 0) {
+ pr_err("%s read_eeprom_memory failed\n", __func__);
+ goto power_down;
+ }
+ CDBG("%s cal_data: %*ph\n", __func__,
+ e_ctrl->cal_data.num_data, e_ctrl->cal_data.mapdata);
+
+ e_ctrl->is_supported |= msm_eeprom_match_crc(&e_ctrl->cal_data);
+
+ rc = msm_camera_power_down(power_info,
+ e_ctrl->eeprom_device_type, &e_ctrl->i2c_client);
+ if (rc) {
+ pr_err("failed rc %d\n", rc);
+ goto memdata_free;
+ }
+ } else
+ e_ctrl->is_supported = 1;
+
/* Initialize sub device */
v4l2_i2c_subdev_init(&e_ctrl->msm_sd.sd,
e_ctrl->i2c_client.client,
@@ -846,12 +1017,23 @@
v4l2_set_subdevdata(&e_ctrl->msm_sd.sd, e_ctrl);
e_ctrl->msm_sd.sd.internal_ops = &msm_eeprom_internal_ops;
e_ctrl->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+ snprintf(e_ctrl->msm_sd.sd.name,
+ ARRAY_SIZE(e_ctrl->msm_sd.sd.name), "msm_eeprom");
media_entity_pads_init(&e_ctrl->msm_sd.sd.entity, 0, NULL);
e_ctrl->msm_sd.sd.entity.function = MSM_CAMERA_SUBDEV_EEPROM;
msm_sd_register(&e_ctrl->msm_sd);
- CDBG("%s success result=%d X\n", __func__, rc);
+ e_ctrl->is_supported = (e_ctrl->is_supported << 1) | 1;
+ pr_err("%s success result=%d X\n", __func__, rc);
return rc;
+power_down:
+ msm_camera_power_down(power_info, e_ctrl->eeprom_device_type,
+ &e_ctrl->i2c_client);
+memdata_free:
+ kfree(e_ctrl->cal_data.mapdata);
+ kfree(e_ctrl->cal_data.map);
+board_free:
+ kfree(e_ctrl->eboard_info);
ectrl_free:
kfree(e_ctrl);
probe_failure:
@@ -961,91 +1143,6 @@
return 0;
}
-static int msm_eeprom_get_dt_data(struct msm_eeprom_ctrl_t *e_ctrl)
-{
- int rc = 0, i = 0;
- struct msm_eeprom_board_info *eb_info;
- struct msm_camera_power_ctrl_t *power_info =
- &e_ctrl->eboard_info->power_info;
- struct device_node *of_node = NULL;
- struct msm_camera_gpio_conf *gconf = NULL;
- int8_t gpio_array_size = 0;
- uint16_t *gpio_array = NULL;
-
- eb_info = e_ctrl->eboard_info;
- if (e_ctrl->eeprom_device_type == MSM_CAMERA_SPI_DEVICE)
- of_node = e_ctrl->i2c_client.
- spi_client->spi_master->dev.of_node;
- else if (e_ctrl->eeprom_device_type == MSM_CAMERA_PLATFORM_DEVICE)
- of_node = e_ctrl->pdev->dev.of_node;
-
- if (!of_node) {
- pr_err("%s: %d of_node is NULL\n", __func__, __LINE__);
- return -ENOMEM;
- }
- rc = msm_camera_get_dt_vreg_data(of_node, &power_info->cam_vreg,
- &power_info->num_vreg);
- if (rc < 0)
- return rc;
-
- if (e_ctrl->userspace_probe == 0) {
- rc = msm_camera_get_dt_power_setting_data(of_node,
- power_info->cam_vreg, power_info->num_vreg,
- power_info);
- if (rc < 0)
- goto ERROR1;
- }
-
- power_info->gpio_conf = kzalloc(sizeof(struct msm_camera_gpio_conf),
- GFP_KERNEL);
- if (!power_info->gpio_conf) {
- rc = -ENOMEM;
- goto ERROR2;
- }
- gconf = power_info->gpio_conf;
- gpio_array_size = of_gpio_count(of_node);
- CDBG("%s gpio count %d\n", __func__, gpio_array_size);
-
- if (gpio_array_size > 0) {
- gpio_array = kcalloc(gpio_array_size, sizeof(uint16_t),
- GFP_KERNEL);
- if (!gpio_array)
- goto ERROR3;
- for (i = 0; i < gpio_array_size; i++) {
- gpio_array[i] = of_get_gpio(of_node, i);
- CDBG("%s gpio_array[%d] = %d\n", __func__, i,
- gpio_array[i]);
- }
-
- rc = msm_camera_get_dt_gpio_req_tbl(of_node, gconf,
- gpio_array, gpio_array_size);
- if (rc < 0) {
- pr_err("%s failed %d\n", __func__, __LINE__);
- goto ERROR4;
- }
-
- rc = msm_camera_init_gpio_pin_tbl(of_node, gconf,
- gpio_array, gpio_array_size);
- if (rc < 0) {
- pr_err("%s failed %d\n", __func__, __LINE__);
- goto ERROR4;
- }
- kfree(gpio_array);
- }
-
- return rc;
-ERROR4:
- kfree(gpio_array);
-ERROR3:
- kfree(power_info->gpio_conf);
-ERROR2:
- kfree(power_info->cam_vreg);
-ERROR1:
- kfree(power_info->power_setting);
- return rc;
-}
-
-
static int msm_eeprom_cmm_dts(struct msm_eeprom_board_info *eb_info,
struct device_node *of_node)
{
diff --git a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c
index 7832181..4bc13d0 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c
@@ -513,7 +513,7 @@
int c, end;
struct msm_sensor_power_setting pd_tmp;
- pr_err("Generating power_down_setting");
+ pr_err("Generating power_down_setting\n");
#ifdef CONFIG_COMPAT
if (is_compat_task()) {
@@ -603,7 +603,7 @@
/* Print power setting */
for (i = 0; i < size_down; i++) {
- CDBG("DOWN seq_type %d seq_val %d config_val %ld delay %d",
+ CDBG("DOWN seq_type %d seq_val %d config_val %ld delay %d\n",
pd[i].seq_type, pd[i].seq_val,
pd[i].config_val, pd[i].delay);
}
@@ -657,7 +657,7 @@
/* Print power setting */
for (i = 0; i < size; i++) {
- CDBG("UP seq_type %d seq_val %d config_val %ld delay %d",
+ CDBG("UP seq_type %d seq_val %d config_val %ld delay %d\n",
pu[i].seq_type, pu[i].seq_val,
pu[i].config_val, pu[i].delay);
}
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c
index 48ef46c..c0566a3 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c
@@ -3733,6 +3733,7 @@
.name = SDE_ROTATOR_DRV_NAME,
.of_match_table = sde_rotator_dt_match,
.pm = &sde_rotator_pm_ops,
+ .suppress_bind_attrs = true,
},
};
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c
index 84efd3d..eeca9f3 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c
@@ -1496,7 +1496,7 @@
(fmt->bits[C0_G_Y] << 0);
/* alpha control */
- if (fmt->bits[C3_ALPHA] || fmt->alpha_enable) {
+ if (fmt->alpha_enable || (!fmt->is_yuv && (fmt->unpack_count == 4))) {
dst_format |= BIT(8);
if (!fmt->alpha_enable) {
dst_format |= BIT(14);
diff --git a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
index 42bf1ba..5c82704 100644
--- a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
@@ -711,6 +711,10 @@
sysfs_remove_group(&pdev->dev.kobj, &msm_vidc_core_attr_group);
dev_set_drvdata(&pdev->dev, NULL);
mutex_destroy(&core->lock);
+
+ mutex_lock(&vidc_driver->lock);
+ list_del(&core->list);
+ mutex_unlock(&vidc_driver->lock);
kfree(core);
return rc;
}
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index d77ea21..b878971 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -6724,6 +6724,7 @@
struct msm_vidc_buffer *temp;
bool found = false;
int i = 0;
+ u32 planes[VIDEO_MAX_PLANES] = {0};
mutex_lock(&inst->flush_lock);
mutex_lock(&inst->registeredbufs.lock);
@@ -6737,6 +6738,10 @@
}
}
if (found) {
+ /* save device_addr */
+ for (i = 0; i < mbuf->vvb.vb2_buf.num_planes; i++)
+ planes[i] = mbuf->smem[i].device_addr;
+
/* send RBR event to client */
msm_vidc_queue_rbr_event(inst,
mbuf->vvb.vb2_buf.planes[0].m.fd,
@@ -6755,6 +6760,7 @@
if (!mbuf->smem[0].refcount) {
list_del(&mbuf->list);
kref_put_mbuf(mbuf);
+ mbuf = NULL;
}
} else {
print_vidc_buffer(VIDC_ERR, "mbuf not found", inst, mbuf);
@@ -6772,8 +6778,8 @@
*/
found = false;
list_for_each_entry(temp, &inst->registeredbufs.list, list) {
- if (msm_comm_compare_vb2_plane(inst, mbuf,
- &temp->vvb.vb2_buf, 0)) {
+ if (msm_comm_compare_device_plane(temp, planes, 0)) {
+ mbuf = temp;
found = true;
break;
}
@@ -6793,9 +6799,11 @@
/* don't queue the buffer */
found = false;
}
- /* clear DEFERRED flag, if any, as the buffer is going to be queued */
- if (found)
+ /* clear required flags as the buffer is going to be queued */
+ if (found) {
mbuf->flags &= ~MSM_VIDC_FLAG_DEFERRED;
+ mbuf->flags &= ~MSM_VIDC_FLAG_RBR_PENDING;
+ }
unlock:
mutex_unlock(&inst->registeredbufs.lock);
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 07ae56f..bf87ed2 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -8792,11 +8792,11 @@
&qseecom.registered_kclient_list_head, list) {
/* Break the loop if client handle is NULL */
- if (!kclient->handle)
- goto exit_free_kclient;
-
- if (list_empty(&kclient->list))
- goto exit_free_kc_handle;
+ if (!kclient->handle) {
+ list_del(&kclient->list);
+ kzfree(kclient);
+ break;
+ }
list_del(&kclient->list);
mutex_lock(&app_access_lock);
@@ -8809,11 +8809,6 @@
}
}
-exit_free_kc_handle:
- kzfree(kclient->handle);
-exit_free_kclient:
- kzfree(kclient);
-
spin_unlock_irqrestore(&qseecom.registered_kclient_list_lock, flags);
if (qseecom.qseos_version > QSEEE_VERSION_00)
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 7d24213..1119292 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -5239,19 +5239,50 @@
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_msm_host *msm_host = pltfm_host->priv;
struct sdhci_msm_pltfm_data *pdata = msm_host->pdata;
+ int nr_groups = msm_host->pdata->pm_qos_data.cpu_group_map.nr_groups;
+ int i;
int dead = (readl_relaxed(host->ioaddr + SDHCI_INT_STATUS) ==
0xffffffff);
- pr_debug("%s: %s\n", dev_name(&pdev->dev), __func__);
+ pr_debug("%s: %s Enter\n", dev_name(&pdev->dev), __func__);
if (!gpio_is_valid(msm_host->pdata->status_gpio))
device_remove_file(&pdev->dev, &msm_host->polling);
+
+ device_remove_file(&pdev->dev, &msm_host->auto_cmd21_attr);
device_remove_file(&pdev->dev, &msm_host->msm_bus_vote.max_bus_bw);
pm_runtime_disable(&pdev->dev);
+ if (msm_host->pm_qos_group_enable) {
+ struct sdhci_msm_pm_qos_group *group;
+
+ for (i = 0; i < nr_groups; i++)
+ cancel_delayed_work_sync(
+ &msm_host->pm_qos[i].unvote_work);
+
+ device_remove_file(&msm_host->pdev->dev,
+ &msm_host->pm_qos_group_enable_attr);
+ device_remove_file(&msm_host->pdev->dev,
+ &msm_host->pm_qos_group_status_attr);
+
+ for (i = 0; i < nr_groups; i++) {
+ group = &msm_host->pm_qos[i];
+ pm_qos_remove_request(&group->req);
+ }
+ }
+
+ if (msm_host->pm_qos_irq.enabled) {
+ cancel_delayed_work_sync(&msm_host->pm_qos_irq.unvote_work);
+ device_remove_file(&pdev->dev,
+ &msm_host->pm_qos_irq.enable_attr);
+ device_remove_file(&pdev->dev,
+ &msm_host->pm_qos_irq.status_attr);
+ pm_qos_remove_request(&msm_host->pm_qos_irq.req);
+ }
+
if (msm_host->pm_qos_wq)
destroy_workqueue(msm_host->pm_qos_wq);
+
sdhci_remove_host(host, dead);
- sdhci_pltfm_free(pdev);
sdhci_msm_vreg_init(&pdev->dev, msm_host->pdata, false);
@@ -5262,6 +5293,9 @@
sdhci_msm_bus_cancel_work_and_set_vote(host, 0);
sdhci_msm_bus_unregister(msm_host);
}
+
+ sdhci_pltfm_free(pdev);
+
return 0;
}
diff --git a/drivers/net/wireless/cnss2/Kconfig b/drivers/net/wireless/cnss2/Kconfig
index daa343e..209d315 100644
--- a/drivers/net/wireless/cnss2/Kconfig
+++ b/drivers/net/wireless/cnss2/Kconfig
@@ -16,6 +16,16 @@
features, enabling kernel panic for certain cases to aid the
debugging, and enabling any other debug mechanisms.
+config CNSS2_QMI
+ bool "CNSS2 Platform Driver QMI support"
+ depends on CNSS2
+ ---help---
+ CNSS2 platform driver uses QMI framework to communicate with WLAN
+ firmware. It sends and receives boot handshake messages to WLAN
+ firmware, which includes hardware and software capabilities and
+ configurations. It also sends WLAN on/off control message to
+ firmware over QMI channel.
+
config CNSS_ASYNC
bool "Enable/disable CNSS platform driver asynchronous probe"
depends on CNSS2
@@ -38,3 +48,27 @@
during system pm.
This config flag controls the feature per target based. The feature
requires CNSS driver support.
+
+config CNSS_QCA6290
+ bool "Enable CNSS QCA6290 chipset specific changes"
+ ---help---
+ This enables the changes from WLAN host driver that are specific to
+ CNSS QCA6290 chipset.
+ These changes are needed to support the new hardware architecture
+ for CNSS QCA6290 chipset.
+
+config CNSS_QCA6390
+ bool "Enable CNSS QCA6390 chipset specific changes"
+ ---help---
+ This enables the changes from WLAN host driver that are specific to
+ CNSS QCA6390 chipset.
+ These changes are needed to support the new hardware architecture
+ for CNSS QCA6390 chipset.
+
+config CNSS_EMULATION
+ bool "Enable specific changes for emulation hardware"
+ ---help---
+ This enables the changes from WLAN drivers that are specific to
+ emulation hardware.
+ These changes are needed for WLAN drivers to support and meet the
+ requirement of emulation hardware.
diff --git a/drivers/net/wireless/cnss2/Makefile b/drivers/net/wireless/cnss2/Makefile
index 318076f..fe0f595 100644
--- a/drivers/net/wireless/cnss2/Makefile
+++ b/drivers/net/wireless/cnss2/Makefile
@@ -5,5 +5,4 @@
cnss2-y += debug.o
cnss2-y += pci.o
cnss2-y += power.o
-cnss2-y += qmi.o
-cnss2-y += wlan_firmware_service_v01.o
+cnss2-$(CONFIG_CNSS2_QMI) += qmi.o wlan_firmware_service_v01.o
diff --git a/drivers/net/wireless/cnss2/bus.c b/drivers/net/wireless/cnss2/bus.c
index c35d661..6a8e67c 100644
--- a/drivers/net/wireless/cnss2/bus.c
+++ b/drivers/net/wireless/cnss2/bus.c
@@ -218,7 +218,7 @@
switch (plat_priv->bus_type) {
case CNSS_BUS_PCI:
- return cnss_bus_call_driver_remove(plat_priv->bus_priv);
+ return cnss_pci_call_driver_remove(plat_priv->bus_priv);
default:
cnss_pr_err("Unsupported bus type: %d\n",
plat_priv->bus_type);
diff --git a/drivers/net/wireless/cnss2/bus.h b/drivers/net/wireless/cnss2/bus.h
index 532438a..91356e9 100644
--- a/drivers/net/wireless/cnss2/bus.h
+++ b/drivers/net/wireless/cnss2/bus.h
@@ -24,6 +24,9 @@
#define QCA6290_DEVICE_ID 0x1100
#define QCA6290_EMULATION_VENDOR_ID 0x168C
#define QCA6290_EMULATION_DEVICE_ID 0xABCD
+#define QCA6390_VENDOR_ID 0x17CB
+#define QCA6390_EMULATION_DEVICE_ID 0x0108
+#define QCA6390_DEVICE_ID 0x1101
enum cnss_dev_bus_type cnss_get_dev_bus_type(struct device *dev);
enum cnss_dev_bus_type cnss_get_bus_type(unsigned long device_id);
diff --git a/drivers/net/wireless/cnss2/debug.c b/drivers/net/wireless/cnss2/debug.c
index b1fbbd8..53a4620 100644
--- a/drivers/net/wireless/cnss2/debug.c
+++ b/drivers/net/wireless/cnss2/debug.c
@@ -147,6 +147,8 @@
return -ENODEV;
pci_priv = plat_priv->bus_priv;
+ if (!pci_priv)
+ return -ENODEV;
len = min(count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, len))
@@ -304,10 +306,6 @@
if (kstrtou32(token, 0, &data_len))
return -EINVAL;
- if (data_len == 0 ||
- data_len > QMI_WLFW_MAX_ATHDIAG_DATA_SIZE_V01)
- return -EINVAL;
-
mutex_lock(&plat_priv->dev_lock);
kfree(plat_priv->diag_reg_read_buf);
plat_priv->diag_reg_read_buf = NULL;
diff --git a/drivers/net/wireless/cnss2/debug.h b/drivers/net/wireless/cnss2/debug.h
index f31fdfe..bf2e755 100644
--- a/drivers/net/wireless/cnss2/debug.h
+++ b/drivers/net/wireless/cnss2/debug.h
@@ -26,23 +26,23 @@
} while (0)
#define cnss_pr_err(_fmt, ...) do { \
- pr_err("cnss: " _fmt, ##__VA_ARGS__); \
- cnss_ipc_log_string("ERR: " _fmt, ##__VA_ARGS__); \
+ printk("%scnss: " _fmt, KERN_ERR, ##__VA_ARGS__); \
+ cnss_ipc_log_string("%scnss: " _fmt, "", ##__VA_ARGS__);\
} while (0)
#define cnss_pr_warn(_fmt, ...) do { \
- pr_warn("cnss: " _fmt, ##__VA_ARGS__); \
- cnss_ipc_log_string("WRN: " _fmt, ##__VA_ARGS__); \
+ printk("%scnss: " _fmt, KERN_WARNING, ##__VA_ARGS__); \
+ cnss_ipc_log_string("%scnss: " _fmt, "", ##__VA_ARGS__);\
} while (0)
#define cnss_pr_info(_fmt, ...) do { \
- pr_info("cnss: " _fmt, ##__VA_ARGS__); \
- cnss_ipc_log_string("INF: " _fmt, ##__VA_ARGS__); \
+ printk("%scnss: " _fmt, KERN_INFO, ##__VA_ARGS__); \
+ cnss_ipc_log_string("%scnss: " _fmt, "", ##__VA_ARGS__);\
} while (0)
#define cnss_pr_dbg(_fmt, ...) do { \
- pr_debug("cnss: " _fmt, ##__VA_ARGS__); \
- cnss_ipc_log_string("DBG: " _fmt, ##__VA_ARGS__); \
+ printk("%scnss: " _fmt, KERN_DEBUG, ##__VA_ARGS__); \
+ cnss_ipc_log_string("%scnss: " _fmt, "", ##__VA_ARGS__);\
} while (0)
#ifdef CONFIG_CNSS2_DEBUG
diff --git a/drivers/net/wireless/cnss2/main.c b/drivers/net/wireless/cnss2/main.c
index 76ad51c..b2c0d09 100644
--- a/drivers/net/wireless/cnss2/main.c
+++ b/drivers/net/wireless/cnss2/main.c
@@ -248,8 +248,6 @@
const char *host_version)
{
struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
- struct wlfw_wlan_cfg_req_msg_v01 req;
- u32 i;
int ret = 0;
if (plat_priv->device_id == QCA6174_DEVICE_ID)
@@ -269,48 +267,7 @@
if (mode == CNSS_WALTEST || mode == CNSS_CCPM)
goto skip_cfg;
- memset(&req, 0, sizeof(req));
-
- req.host_version_valid = 1;
- strlcpy(req.host_version, host_version,
- QMI_WLFW_MAX_STR_LEN_V01 + 1);
-
- req.tgt_cfg_valid = 1;
- if (config->num_ce_tgt_cfg > QMI_WLFW_MAX_NUM_CE_V01)
- req.tgt_cfg_len = QMI_WLFW_MAX_NUM_CE_V01;
- else
- req.tgt_cfg_len = config->num_ce_tgt_cfg;
- for (i = 0; i < req.tgt_cfg_len; i++) {
- req.tgt_cfg[i].pipe_num = config->ce_tgt_cfg[i].pipe_num;
- req.tgt_cfg[i].pipe_dir = config->ce_tgt_cfg[i].pipe_dir;
- req.tgt_cfg[i].nentries = config->ce_tgt_cfg[i].nentries;
- req.tgt_cfg[i].nbytes_max = config->ce_tgt_cfg[i].nbytes_max;
- req.tgt_cfg[i].flags = config->ce_tgt_cfg[i].flags;
- }
-
- req.svc_cfg_valid = 1;
- if (config->num_ce_svc_pipe_cfg > QMI_WLFW_MAX_NUM_SVC_V01)
- req.svc_cfg_len = QMI_WLFW_MAX_NUM_SVC_V01;
- else
- req.svc_cfg_len = config->num_ce_svc_pipe_cfg;
- for (i = 0; i < req.svc_cfg_len; i++) {
- req.svc_cfg[i].service_id = config->ce_svc_cfg[i].service_id;
- req.svc_cfg[i].pipe_dir = config->ce_svc_cfg[i].pipe_dir;
- req.svc_cfg[i].pipe_num = config->ce_svc_cfg[i].pipe_num;
- }
-
- req.shadow_reg_v2_valid = 1;
- if (config->num_shadow_reg_v2_cfg >
- QMI_WLFW_MAX_NUM_SHADOW_REG_V2_V01)
- req.shadow_reg_v2_len = QMI_WLFW_MAX_NUM_SHADOW_REG_V2_V01;
- else
- req.shadow_reg_v2_len = config->num_shadow_reg_v2_cfg;
-
- memcpy(req.shadow_reg_v2, config->shadow_reg_v2_cfg,
- sizeof(struct wlfw_shadow_reg_v2_cfg_s_v01)
- * req.shadow_reg_v2_len);
-
- ret = cnss_wlfw_wlan_cfg_send_sync(plat_priv, &req);
+ ret = cnss_wlfw_wlan_cfg_send_sync(plat_priv, config, host_version);
if (ret)
goto out;
@@ -331,7 +288,7 @@
if (qmi_bypass)
return 0;
- return cnss_wlfw_wlan_mode_send_sync(plat_priv, QMI_WLFW_OFF_V01);
+ return cnss_wlfw_wlan_mode_send_sync(plat_priv, CNSS_OFF);
}
EXPORT_SYMBOL(cnss_wlan_disable);
@@ -350,13 +307,6 @@
if (plat_priv->device_id == QCA6174_DEVICE_ID)
return 0;
- if (!output || data_len == 0 || data_len > QMI_WLFW_MAX_DATA_SIZE_V01) {
- cnss_pr_err("Invalid parameters for athdiag read: output %p, data_len %u\n",
- output, data_len);
- ret = -EINVAL;
- goto out;
- }
-
if (!test_bit(CNSS_FW_READY, &plat_priv->driver_state)) {
cnss_pr_err("Invalid state for athdiag read: 0x%lx\n",
plat_priv->driver_state);
@@ -386,13 +336,6 @@
if (plat_priv->device_id == QCA6174_DEVICE_ID)
return 0;
- if (!input || data_len == 0 || data_len > QMI_WLFW_MAX_DATA_SIZE_V01) {
- cnss_pr_err("Invalid parameters for athdiag write: input %p, data_len %u\n",
- input, data_len);
- ret = -EINVAL;
- goto out;
- }
-
if (!test_bit(CNSS_FW_READY, &plat_priv->driver_state)) {
cnss_pr_err("Invalid state for athdiag write: 0x%lx\n",
plat_priv->driver_state);
@@ -491,10 +434,10 @@
if (enable_waltest) {
ret = cnss_wlfw_wlan_mode_send_sync(plat_priv,
- QMI_WLFW_WALTEST_V01);
+ CNSS_WALTEST);
} else if (test_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state)) {
ret = cnss_wlfw_wlan_mode_send_sync(plat_priv,
- QMI_WLFW_CALIBRATION_V01);
+ CNSS_CALIBRATION);
} else if (test_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state) ||
test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state)) {
ret = cnss_bus_call_driver_probe(plat_priv);
@@ -625,6 +568,12 @@
return ret;
}
+unsigned int cnss_get_boot_timeout(struct device *dev)
+{
+ return cnss_get_qmi_timeout();
+}
+EXPORT_SYMBOL(cnss_get_boot_timeout);
+
int cnss_power_up(struct device *dev)
{
int ret = 0;
@@ -647,7 +596,7 @@
if (plat_priv->device_id == QCA6174_DEVICE_ID)
goto out;
- timeout = cnss_get_qmi_timeout();
+ timeout = cnss_get_boot_timeout(dev);
reinit_completion(&plat_priv->power_up_complete);
ret = wait_for_completion_timeout(&plat_priv->power_up_complete,
@@ -1101,7 +1050,7 @@
static int cnss_cold_boot_cal_done_hdlr(struct cnss_plat_data *plat_priv)
{
plat_priv->cal_done = true;
- cnss_wlfw_wlan_mode_send_sync(plat_priv, QMI_WLFW_OFF_V01);
+ cnss_wlfw_wlan_mode_send_sync(plat_priv, CNSS_OFF);
cnss_bus_dev_shutdown(plat_priv);
clear_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state);
@@ -1435,6 +1384,8 @@
break;
case QCA6290_EMULATION_DEVICE_ID:
case QCA6290_DEVICE_ID:
+ case QCA6390_EMULATION_DEVICE_ID:
+ case QCA6390_DEVICE_ID:
ret = cnss_register_ramdump_v2(plat_priv);
break;
default:
@@ -1453,6 +1404,8 @@
break;
case QCA6290_EMULATION_DEVICE_ID:
case QCA6290_DEVICE_ID:
+ case QCA6390_EMULATION_DEVICE_ID:
+ case QCA6390_DEVICE_ID:
cnss_unregister_ramdump_v2(plat_priv);
break;
default:
@@ -1523,6 +1476,8 @@
switch (plat_priv->device_id) {
case QCA6290_EMULATION_DEVICE_ID:
case QCA6290_DEVICE_ID:
+ case QCA6390_EMULATION_DEVICE_ID:
+ case QCA6390_DEVICE_ID:
break;
default:
cnss_pr_err("Not supported for device ID 0x%lx\n",
@@ -1585,6 +1540,7 @@
static const struct platform_device_id cnss_platform_id_table[] = {
{ .name = "qca6174", .driver_data = QCA6174_DEVICE_ID, },
{ .name = "qca6290", .driver_data = QCA6290_DEVICE_ID, },
+ { .name = "qca6390", .driver_data = QCA6390_DEVICE_ID, },
};
static const struct of_device_id cnss_of_match_table[] = {
@@ -1594,6 +1550,9 @@
{
.compatible = "qcom,cnss-qca6290",
.data = (void *)&cnss_platform_id_table[1]},
+ {
+ .compatible = "qcom,cnss-qca6390",
+ .data = (void *)&cnss_platform_id_table[2]},
{ },
};
MODULE_DEVICE_TABLE(of, cnss_of_match_table);
diff --git a/drivers/net/wireless/cnss2/main.h b/drivers/net/wireless/cnss2/main.h
index 509974a0..a2f346a 100644
--- a/drivers/net/wireless/cnss2/main.h
+++ b/drivers/net/wireless/cnss2/main.h
@@ -24,6 +24,8 @@
#include "qmi.h"
#define MAX_NO_OF_MAC_ADDR 4
+#define QMI_WLFW_MAX_TIMESTAMP_LEN 32
+#define QMI_WLFW_MAX_NUM_MEM_SEG 32
#define CNSS_EVENT_SYNC BIT(0)
#define CNSS_EVENT_UNINTERRUPTIBLE BIT(1)
@@ -110,6 +112,33 @@
u32 type;
};
+struct wlfw_rf_chip_info {
+ u32 chip_id;
+ u32 chip_family;
+};
+
+struct wlfw_rf_board_info {
+ u32 board_id;
+};
+
+struct wlfw_soc_info {
+ u32 soc_id;
+};
+
+struct wlfw_fw_version_info {
+ u32 fw_version;
+ char fw_build_timestamp[QMI_WLFW_MAX_TIMESTAMP_LEN + 1];
+};
+
+enum cnss_mem_type {
+ CNSS_MEM_TYPE_MSA,
+ CNSS_MEM_TYPE_DDR,
+ CNSS_MEM_BDF,
+ CNSS_MEM_M3,
+ CNSS_MEM_CAL_V01,
+ CNSS_MEM_DPD_V01,
+};
+
enum cnss_fw_dump_type {
CNSS_FW_IMAGE,
CNSS_FW_RDDM,
@@ -202,12 +231,12 @@
struct qmi_handle *qmi_wlfw_clnt;
struct work_struct qmi_recv_msg_work;
struct notifier_block qmi_wlfw_clnt_nb;
- struct wlfw_rf_chip_info_s_v01 chip_info;
- struct wlfw_rf_board_info_s_v01 board_info;
- struct wlfw_soc_info_s_v01 soc_info;
- struct wlfw_fw_version_info_s_v01 fw_version_info;
+ struct wlfw_rf_chip_info chip_info;
+ struct wlfw_rf_board_info board_info;
+ struct wlfw_soc_info soc_info;
+ struct wlfw_fw_version_info fw_version_info;
u32 fw_mem_seg_len;
- struct cnss_fw_mem fw_mem[QMI_WLFW_MAX_NUM_MEM_SEG_V01];
+ struct cnss_fw_mem fw_mem[QMI_WLFW_MAX_NUM_MEM_SEG];
struct cnss_fw_mem m3_mem;
struct cnss_pin_connect_result pin_result;
struct dentry *root_dentry;
@@ -220,6 +249,7 @@
u32 diag_reg_read_len;
u8 *diag_reg_read_buf;
bool cal_done;
+ char firmware_name[13];
};
struct cnss_plat_data *cnss_get_plat_priv(struct platform_device *plat_dev);
diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c
index e1704fb..161e68e 100644
--- a/drivers/net/wireless/cnss2/pci.c
+++ b/drivers/net/wireless/cnss2/pci.c
@@ -44,6 +44,7 @@
#define MAX_M3_FILE_NAME_LENGTH 13
#define DEFAULT_M3_FILE_NAME "m3.bin"
+#define DEFAULT_FW_FILE_NAME "amss.bin"
#define WAKE_MSI_NAME "WAKE"
@@ -432,7 +433,7 @@
goto power_off;
}
- timeout = cnss_get_qmi_timeout();
+ timeout = cnss_get_boot_timeout(&pci_priv->pci_dev->dev);
ret = cnss_pci_start_mhi(pci_priv);
if (ret) {
@@ -569,6 +570,8 @@
break;
case QCA6290_EMULATION_DEVICE_ID:
case QCA6290_DEVICE_ID:
+ case QCA6390_EMULATION_DEVICE_ID:
+ case QCA6390_DEVICE_ID:
ret = cnss_qca6290_powerup(pci_priv);
break;
default:
@@ -595,6 +598,8 @@
break;
case QCA6290_EMULATION_DEVICE_ID:
case QCA6290_DEVICE_ID:
+ case QCA6390_EMULATION_DEVICE_ID:
+ case QCA6390_DEVICE_ID:
ret = cnss_qca6290_shutdown(pci_priv);
break;
default:
@@ -621,6 +626,8 @@
break;
case QCA6290_EMULATION_DEVICE_ID:
case QCA6290_DEVICE_ID:
+ case QCA6390_EMULATION_DEVICE_ID:
+ case QCA6390_DEVICE_ID:
cnss_qca6290_crash_shutdown(pci_priv);
break;
default:
@@ -647,6 +654,8 @@
break;
case QCA6290_EMULATION_DEVICE_ID:
case QCA6290_DEVICE_ID:
+ case QCA6390_EMULATION_DEVICE_ID:
+ case QCA6390_DEVICE_ID:
ret = cnss_qca6290_ramdump(pci_priv);
break;
default:
@@ -1705,7 +1714,7 @@
cnss_pr_dbg("Collect remote heap dump segment\n");
for (i = 0; i < plat_priv->fw_mem_seg_len; i++) {
- if (fw_mem[i].type == QMI_WLFW_MEM_TYPE_DDR_V01) {
+ if (fw_mem[i].type == CNSS_MEM_TYPE_DDR) {
dump_seg->address = fw_mem[i].pa;
dump_seg->v_address = fw_mem[i].va;
dump_seg->size = fw_mem[i].size;
@@ -1838,6 +1847,8 @@
mhi_ctrl->bus = pci_dev->bus->number;
mhi_ctrl->slot = PCI_SLOT(pci_dev->devfn);
+ mhi_ctrl->fw_image = plat_priv->firmware_name;
+
mhi_ctrl->regs = pci_priv->bar;
cnss_pr_dbg("BAR starts at %pa\n",
&pci_resource_start(pci_priv->pci_dev, PCI_BAR_NUM));
@@ -1863,6 +1874,9 @@
mhi_ctrl->runtime_put = cnss_mhi_pm_runtime_put_noidle;
mhi_ctrl->rddm_size = pci_priv->plat_priv->ramdump_info_v2.ramdump_size;
+ mhi_ctrl->sbl_size = SZ_512K;
+ mhi_ctrl->seg_len = SZ_512K;
+ mhi_ctrl->fbc_download = true;
mhi_ctrl->log_buf = ipc_log_context_create(CNSS_IPC_LOG_PAGES,
"cnss-mhi", 0);
@@ -1916,7 +1930,10 @@
return 0;
break;
case CNSS_MHI_TRIGGER_RDDM:
- return 0;
+ if (test_bit(CNSS_MHI_POWER_ON, &pci_priv->mhi_state) &&
+ !test_bit(CNSS_MHI_TRIGGER_RDDM, &pci_priv->mhi_state))
+ return 0;
+ break;
default:
cnss_pr_err("Unhandled MHI state: %s(%d)\n",
cnss_mhi_state_to_str(mhi_state), mhi_state);
@@ -2109,6 +2126,8 @@
cnss_set_pci_priv(pci_dev, pci_priv);
plat_priv->device_id = pci_dev->device;
plat_priv->bus_priv = pci_priv;
+ snprintf(plat_priv->firmware_name, sizeof(plat_priv->firmware_name),
+ DEFAULT_FW_FILE_NAME);
ret = cnss_register_subsys(plat_priv);
if (ret)
@@ -2163,6 +2182,8 @@
break;
case QCA6290_EMULATION_DEVICE_ID:
case QCA6290_DEVICE_ID:
+ case QCA6390_EMULATION_DEVICE_ID:
+ case QCA6390_DEVICE_ID:
ret = cnss_pci_enable_msi(pci_priv);
if (ret)
goto disable_bus;
@@ -2215,6 +2236,8 @@
switch (pci_dev->device) {
case QCA6290_EMULATION_DEVICE_ID:
case QCA6290_DEVICE_ID:
+ case QCA6390_EMULATION_DEVICE_ID:
+ case QCA6390_DEVICE_ID:
cnss_pci_unregister_mhi(pci_priv);
cnss_pci_disable_msi(pci_priv);
break;
@@ -2238,6 +2261,9 @@
{ QCA6290_EMULATION_VENDOR_ID, QCA6290_EMULATION_DEVICE_ID,
PCI_ANY_ID, PCI_ANY_ID },
{ QCA6290_VENDOR_ID, QCA6290_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
+ { QCA6390_VENDOR_ID, QCA6390_EMULATION_DEVICE_ID, PCI_ANY_ID,
+ PCI_ANY_ID },
+ { QCA6390_VENDOR_ID, QCA6390_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
{ 0 }
};
MODULE_DEVICE_TABLE(pci, cnss_pci_id_table);
diff --git a/drivers/net/wireless/cnss2/qmi.c b/drivers/net/wireless/cnss2/qmi.c
index 222a131..3fbad1f 100644
--- a/drivers/net/wireless/cnss2/qmi.c
+++ b/drivers/net/wireless/cnss2/qmi.c
@@ -51,24 +51,24 @@
CNSS_BDF_ELF,
};
-static char *cnss_qmi_mode_to_str(enum wlfw_driver_mode_enum_v01 mode)
+static char *cnss_qmi_mode_to_str(enum cnss_driver_mode mode)
{
switch (mode) {
- case QMI_WLFW_MISSION_V01:
+ case CNSS_MISSION:
return "MISSION";
- case QMI_WLFW_FTM_V01:
+ case CNSS_FTM:
return "FTM";
- case QMI_WLFW_EPPING_V01:
+ case CNSS_EPPING:
return "EPPING";
- case QMI_WLFW_WALTEST_V01:
+ case CNSS_WALTEST:
return "WALTEST";
- case QMI_WLFW_OFF_V01:
+ case CNSS_OFF:
return "OFF";
- case QMI_WLFW_CCPM_V01:
+ case CNSS_CCPM:
return "CCPM";
- case QMI_WLFW_QVIT_V01:
+ case CNSS_QVIT:
return "QVIT";
- case QMI_WLFW_CALIBRATION_V01:
+ case CNSS_CALIBRATION:
return "CALIBRATION";
default:
return "UNKNOWN";
@@ -464,16 +464,23 @@
goto out;
}
- if (resp.chip_info_valid)
- plat_priv->chip_info = resp.chip_info;
+ if (resp.chip_info_valid) {
+ plat_priv->chip_info.chip_id = resp.chip_info.chip_id;
+ plat_priv->chip_info.chip_family = resp.chip_info.chip_family;
+ }
if (resp.board_info_valid)
- plat_priv->board_info = resp.board_info;
+ plat_priv->board_info.board_id = resp.board_info.board_id;
else
plat_priv->board_info.board_id = 0xFF;
if (resp.soc_info_valid)
- plat_priv->soc_info = resp.soc_info;
- if (resp.fw_version_info_valid)
- plat_priv->fw_version_info = resp.fw_version_info;
+ plat_priv->soc_info.soc_id = resp.soc_info.soc_id;
+ if (resp.fw_version_info_valid) {
+ plat_priv->fw_version_info.fw_version =
+ resp.fw_version_info.fw_version;
+ strlcpy(plat_priv->fw_version_info.fw_build_timestamp,
+ resp.fw_version_info.fw_build_timestamp,
+ QMI_WLFW_MAX_TIMESTAMP_LEN + 1);
+ }
cnss_pr_dbg("Target capability: chip_id: 0x%x, chip_family: 0x%x, board_id: 0x%x, soc_id: 0x%x, fw_version: 0x%x, fw_build_timestamp: %s",
plat_priv->chip_info.chip_id,
@@ -515,17 +522,17 @@
BDF_FILE_NAME_PREFIX "%02x",
plat_priv->board_info.board_id);
+ if (bdf_bypass) {
+ cnss_pr_info("bdf_bypass is enabled, sending dummy BDF\n");
+ temp = filename;
+ remaining = MAX_BDF_FILE_NAME;
+ goto bypass_bdf;
+ }
+
ret = request_firmware(&fw_entry, filename, &plat_priv->plat_dev->dev);
if (ret) {
cnss_pr_err("Failed to load BDF: %s\n", filename);
- if (bdf_bypass) {
- cnss_pr_info("bdf_bypass is enabled, sending dummy BDF\n");
- temp = filename;
- remaining = MAX_BDF_FILE_NAME;
- goto bypass_bdf;
- } else {
- goto err_req_fw;
- }
+ goto err_req_fw;
}
temp = fw_entry->data;
@@ -655,7 +662,7 @@
}
int cnss_wlfw_wlan_mode_send_sync(struct cnss_plat_data *plat_priv,
- enum wlfw_driver_mode_enum_v01 mode)
+ enum cnss_driver_mode mode)
{
struct wlfw_wlan_mode_req_msg_v01 req;
struct wlfw_wlan_mode_resp_msg_v01 resp;
@@ -668,7 +675,7 @@
cnss_pr_dbg("Sending mode message, mode: %s(%d), state: 0x%lx\n",
cnss_qmi_mode_to_str(mode), mode, plat_priv->driver_state);
- if (mode == QMI_WLFW_OFF_V01 &&
+ if (mode == CNSS_OFF &&
test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state)) {
cnss_pr_dbg("Recovery is in progress, ignore mode off request.\n");
return 0;
@@ -693,7 +700,7 @@
sizeof(req), &resp_desc, &resp, sizeof(resp),
QMI_WLFW_TIMEOUT_MS);
if (ret < 0) {
- if (mode == QMI_WLFW_OFF_V01 && ret == -ENETRESET) {
+ if (mode == CNSS_OFF && ret == -ENETRESET) {
cnss_pr_dbg("WLFW service is disconnected while sending mode off request.\n");
return 0;
}
@@ -712,17 +719,19 @@
return 0;
out:
- if (mode != QMI_WLFW_OFF_V01)
+ if (mode != CNSS_OFF)
CNSS_ASSERT(0);
return ret;
}
int cnss_wlfw_wlan_cfg_send_sync(struct cnss_plat_data *plat_priv,
- struct wlfw_wlan_cfg_req_msg_v01 *data)
+ struct cnss_wlan_enable_cfg *config,
+ const char *host_version)
{
struct wlfw_wlan_cfg_req_msg_v01 req;
struct wlfw_wlan_cfg_resp_msg_v01 resp;
struct msg_desc req_desc, resp_desc;
+ u32 i;
int ret = 0;
cnss_pr_dbg("Sending WLAN config message, state: 0x%lx\n",
@@ -734,7 +743,44 @@
memset(&req, 0, sizeof(req));
memset(&resp, 0, sizeof(resp));
- memcpy(&req, data, sizeof(req));
+ req.host_version_valid = 1;
+ strlcpy(req.host_version, host_version,
+ QMI_WLFW_MAX_STR_LEN_V01 + 1);
+
+ req.tgt_cfg_valid = 1;
+ if (config->num_ce_tgt_cfg > QMI_WLFW_MAX_NUM_CE_V01)
+ req.tgt_cfg_len = QMI_WLFW_MAX_NUM_CE_V01;
+ else
+ req.tgt_cfg_len = config->num_ce_tgt_cfg;
+ for (i = 0; i < req.tgt_cfg_len; i++) {
+ req.tgt_cfg[i].pipe_num = config->ce_tgt_cfg[i].pipe_num;
+ req.tgt_cfg[i].pipe_dir = config->ce_tgt_cfg[i].pipe_dir;
+ req.tgt_cfg[i].nentries = config->ce_tgt_cfg[i].nentries;
+ req.tgt_cfg[i].nbytes_max = config->ce_tgt_cfg[i].nbytes_max;
+ req.tgt_cfg[i].flags = config->ce_tgt_cfg[i].flags;
+ }
+
+ req.svc_cfg_valid = 1;
+ if (config->num_ce_svc_pipe_cfg > QMI_WLFW_MAX_NUM_SVC_V01)
+ req.svc_cfg_len = QMI_WLFW_MAX_NUM_SVC_V01;
+ else
+ req.svc_cfg_len = config->num_ce_svc_pipe_cfg;
+ for (i = 0; i < req.svc_cfg_len; i++) {
+ req.svc_cfg[i].service_id = config->ce_svc_cfg[i].service_id;
+ req.svc_cfg[i].pipe_dir = config->ce_svc_cfg[i].pipe_dir;
+ req.svc_cfg[i].pipe_num = config->ce_svc_cfg[i].pipe_num;
+ }
+
+ req.shadow_reg_v2_valid = 1;
+ if (config->num_shadow_reg_v2_cfg >
+ QMI_WLFW_MAX_NUM_SHADOW_REG_V2_V01)
+ req.shadow_reg_v2_len = QMI_WLFW_MAX_NUM_SHADOW_REG_V2_V01;
+ else
+ req.shadow_reg_v2_len = config->num_shadow_reg_v2_cfg;
+
+ memcpy(req.shadow_reg_v2, config->shadow_reg_v2_cfg,
+ sizeof(struct wlfw_shadow_reg_v2_cfg_s_v01)
+ * req.shadow_reg_v2_len);
req_desc.max_msg_len = WLFW_WLAN_CFG_REQ_MSG_V01_MAX_MSG_LEN;
req_desc.msg_id = QMI_WLFW_WLAN_CFG_REQ_V01;
@@ -781,6 +827,12 @@
if (!plat_priv->qmi_wlfw_clnt)
return -EINVAL;
+ if (!data || data_len == 0 || data_len > QMI_WLFW_MAX_DATA_SIZE_V01) {
+ cnss_pr_err("Invalid parameters for athdiag read: data %p, data_len %u\n",
+ data, data_len);
+ return -EINVAL;
+ }
+
cnss_pr_dbg("athdiag read: state 0x%lx, offset %x, mem_type %x, data_len %u\n",
plat_priv->driver_state, offset, mem_type, data_len);
@@ -847,6 +899,12 @@
if (!plat_priv->qmi_wlfw_clnt)
return -EINVAL;
+ if (!data || data_len == 0 || data_len > QMI_WLFW_MAX_DATA_SIZE_V01) {
+ cnss_pr_err("Invalid parameters for athdiag write: data %p, data_len %u\n",
+ data, data_len);
+ return -EINVAL;
+ }
+
cnss_pr_dbg("athdiag write: state 0x%lx, offset %x, mem_type %x, data_len %u, data %p\n",
plat_priv->driver_state, offset, mem_type, data_len, data);
@@ -990,7 +1048,6 @@
return QMI_WLFW_TIMEOUT_MS;
}
-EXPORT_SYMBOL(cnss_get_qmi_timeout);
int cnss_wlfw_server_arrive(struct cnss_plat_data *plat_priv)
{
diff --git a/drivers/net/wireless/cnss2/qmi.h b/drivers/net/wireless/cnss2/qmi.h
index 70d8d40..a48263e 100644
--- a/drivers/net/wireless/cnss2/qmi.h
+++ b/drivers/net/wireless/cnss2/qmi.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2018, 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
@@ -13,12 +13,14 @@
#ifndef _CNSS_QMI_H
#define _CNSS_QMI_H
-#include "wlan_firmware_service_v01.h"
-
struct cnss_plat_data;
+#ifdef CONFIG_CNSS2_QMI
+#include "wlan_firmware_service_v01.h"
+
int cnss_qmi_init(struct cnss_plat_data *plat_priv);
void cnss_qmi_deinit(struct cnss_plat_data *plat_priv);
+unsigned int cnss_get_qmi_timeout(void);
int cnss_wlfw_server_arrive(struct cnss_plat_data *plat_priv);
int cnss_wlfw_server_exit(struct cnss_plat_data *plat_priv);
int cnss_wlfw_respond_mem_send_sync(struct cnss_plat_data *plat_priv);
@@ -26,9 +28,10 @@
int cnss_wlfw_bdf_dnld_send_sync(struct cnss_plat_data *plat_priv);
int cnss_wlfw_m3_dnld_send_sync(struct cnss_plat_data *plat_priv);
int cnss_wlfw_wlan_mode_send_sync(struct cnss_plat_data *plat_priv,
- enum wlfw_driver_mode_enum_v01 mode);
+ enum cnss_driver_mode mode);
int cnss_wlfw_wlan_cfg_send_sync(struct cnss_plat_data *plat_priv,
- struct wlfw_wlan_cfg_req_msg_v01 *data);
+ struct cnss_wlan_enable_cfg *config,
+ const char *host_version);
int cnss_wlfw_athdiag_read_send_sync(struct cnss_plat_data *plat_priv,
u32 offset, u32 mem_type,
u32 data_len, u8 *data);
@@ -37,5 +40,91 @@
u32 data_len, u8 *data);
int cnss_wlfw_ini_send_sync(struct cnss_plat_data *plat_priv,
u8 fw_log_mode);
+#else
+#define QMI_WLFW_TIMEOUT_MS 10000
+
+static inline int cnss_qmi_init(struct cnss_plat_data *plat_priv)
+{
+ return 0;
+}
+
+static inline void cnss_qmi_deinit(struct cnss_plat_data *plat_priv)
+{
+}
+
+static inline unsigned int cnss_get_qmi_timeout(void)
+{
+ return QMI_WLFW_TIMEOUT_MS;
+}
+
+static inline int cnss_wlfw_server_arrive(struct cnss_plat_data *plat_priv)
+{
+ return 0;
+}
+
+static inline int cnss_wlfw_server_exit(struct cnss_plat_data *plat_priv)
+{
+ return 0;
+}
+
+static inline
+int cnss_wlfw_respond_mem_send_sync(struct cnss_plat_data *plat_priv)
+{
+ return 0;
+}
+
+static inline int cnss_wlfw_tgt_cap_send_sync(struct cnss_plat_data *plat_priv)
+{
+ return 0;
+}
+
+static inline int cnss_wlfw_bdf_dnld_send_sync(struct cnss_plat_data *plat_priv)
+{
+ return 0;
+}
+
+static inline int cnss_wlfw_m3_dnld_send_sync(struct cnss_plat_data *plat_priv)
+{
+ return 0;
+}
+
+static inline
+int cnss_wlfw_wlan_mode_send_sync(struct cnss_plat_data *plat_priv,
+ enum cnss_driver_mode mode)
+{
+ return 0;
+}
+
+static inline
+int cnss_wlfw_wlan_cfg_send_sync(struct cnss_plat_data *plat_priv,
+ struct cnss_wlan_enable_cfg *config,
+ const char *host_version)
+{
+ return 0;
+}
+
+static inline
+int cnss_wlfw_athdiag_read_send_sync(struct cnss_plat_data *plat_priv,
+ u32 offset, u32 mem_type,
+ u32 data_len, u8 *data)
+{
+ return 0;
+}
+
+static inline
+int cnss_wlfw_athdiag_write_send_sync(struct cnss_plat_data *plat_priv,
+ u32 offset, u32 mem_type,
+ u32 data_len, u8 *data)
+{
+ return 0;
+}
+
+static inline
+int cnss_wlfw_ini_send_sync(struct cnss_plat_data *plat_priv,
+ u8 fw_log_mode)
+{
+ return 0;
+}
+#endif /* CONFIG_CNSS2_QMI */
#endif /* _CNSS_QMI_H */
diff --git a/drivers/platform/msm/gsi/gsi.c b/drivers/platform/msm/gsi/gsi.c
index 2c29538..5d8b12b 100644
--- a/drivers/platform/msm/gsi/gsi.c
+++ b/drivers/platform/msm/gsi/gsi.c
@@ -2788,27 +2788,21 @@
return -GSI_STATUS_UNSUPPORTED_OP;
}
+ spin_lock_irqsave(&gsi_ctx->slock, flags);
if (curr == GSI_CHAN_MODE_CALLBACK &&
mode == GSI_CHAN_MODE_POLL) {
- spin_lock_irqsave(&gsi_ctx->slock, flags);
__gsi_config_ieob_irq(gsi_ctx->per.ee, 1 << ctx->evtr->id, 0);
- spin_unlock_irqrestore(&gsi_ctx->slock, flags);
- spin_lock_irqsave(&ctx->ring.slock, flags);
atomic_set(&ctx->poll_mode, mode);
- spin_unlock_irqrestore(&ctx->ring.slock, flags);
ctx->stats.callback_to_poll++;
}
if (curr == GSI_CHAN_MODE_POLL &&
mode == GSI_CHAN_MODE_CALLBACK) {
- spin_lock_irqsave(&ctx->ring.slock, flags);
atomic_set(&ctx->poll_mode, mode);
- spin_unlock_irqrestore(&ctx->ring.slock, flags);
- spin_lock_irqsave(&gsi_ctx->slock, flags);
__gsi_config_ieob_irq(gsi_ctx->per.ee, 1 << ctx->evtr->id, ~0);
- spin_unlock_irqrestore(&gsi_ctx->slock, flags);
ctx->stats.poll_to_callback++;
}
+ spin_unlock_irqrestore(&gsi_ctx->slock, flags);
return GSI_STATUS_SUCCESS;
}
diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c b/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c
index 8b998fe..704308f 100644
--- a/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c
+++ b/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c
@@ -2952,6 +2952,7 @@
int i;
unsigned long flags;
int res;
+ struct ipa3_usb_pm_context *pm_ctx;
pr_debug("entry\n");
ipa3_usb_ctx = kzalloc(sizeof(struct ipa3_usb_context), GFP_KERNEL);
@@ -2971,19 +2972,13 @@
ipa3_usb_ctx->dl_data_pending = false;
mutex_init(&ipa3_usb_ctx->general_mutex);
- if (ipa_pm_is_used()) {
- struct ipa3_usb_pm_context *pm_ctx;
-
- pm_ctx =
- &ipa3_usb_ctx->ttype_ctx[IPA_USB_TRANSPORT_TETH].pm_ctx;
- pm_ctx->hdl = ~0;
- pm_ctx->remote_wakeup_work =
- &ipa3_usb_notify_remote_wakeup_work;
- pm_ctx = &ipa3_usb_ctx->ttype_ctx[IPA_USB_TRANSPORT_DPL].pm_ctx;
- pm_ctx->hdl = ~0;
- pm_ctx->remote_wakeup_work =
- &ipa3_usb_dpl_notify_remote_wakeup_work;
- }
+ /* init PM related members */
+ pm_ctx = &ipa3_usb_ctx->ttype_ctx[IPA_USB_TRANSPORT_TETH].pm_ctx;
+ pm_ctx->hdl = ~0;
+ pm_ctx->remote_wakeup_work = &ipa3_usb_notify_remote_wakeup_work;
+ pm_ctx = &ipa3_usb_ctx->ttype_ctx[IPA_USB_TRANSPORT_DPL].pm_ctx;
+ pm_ctx->hdl = ~0;
+ pm_ctx->remote_wakeup_work = &ipa3_usb_dpl_notify_remote_wakeup_work;
for (i = 0; i < IPA_USB_TRANSPORT_MAX; i++) {
ipa3_usb_ctx->ttype_ctx[i].rm_ctx.prod_valid = false;
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa.c b/drivers/platform/msm/ipa/ipa_v2/ipa.c
index 10468f3..6f9afa6 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa.c
@@ -3938,11 +3938,8 @@
}
ipa_ctx->logbuf = ipc_log_context_create(IPA_IPC_LOG_PAGES, "ipa", 0);
- if (ipa_ctx->logbuf == NULL) {
- IPAERR("failed to get logbuf\n");
- result = -ENOMEM;
- goto fail_logbuf;
- }
+ if (ipa_ctx->logbuf == NULL)
+ IPADBG("failed to create IPC log, continue...\n");
ipa_ctx->pdev = ipa_dev;
ipa_ctx->uc_pdev = ipa_dev;
@@ -4488,7 +4485,6 @@
kfree(ipa_ctx->ctrl);
fail_mem_ctrl:
ipc_log_context_destroy(ipa_ctx->logbuf);
-fail_logbuf:
kfree(ipa_ctx);
ipa_ctx = NULL;
fail_mem_ctx:
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c
index c2f7aae..7d315a4 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c
@@ -1903,7 +1903,7 @@
ipc_log_context_create(IPA_IPC_LOG_PAGES,
"ipa_low", 0);
if (ipa_ipc_low_buff == NULL)
- IPAERR("failed to get logbuf_low\n");
+ IPADBG("failed to get logbuf_low\n");
}
ipa_ctx->logbuf_low = ipa_ipc_low_buff;
} else {
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c
index 2b94f0e..8a773e4 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c
@@ -5018,7 +5018,7 @@
ipa3_ctx->logbuf = ipc_log_context_create(IPA_IPC_LOG_PAGES, "ipa", 0);
if (ipa3_ctx->logbuf == NULL)
- IPAERR("failed to create IPC log, continue...\n");
+ IPADBG("failed to create IPC log, continue...\n");
/* ipa3_ctx->pdev and ipa3_ctx->uc_pdev will be set in the smmu probes*/
ipa3_ctx->master_pdev = ipa_pdev;
@@ -5041,6 +5041,7 @@
ipa3_ctx->apply_rg10_wa = resource_p->apply_rg10_wa;
ipa3_ctx->gsi_ch20_wa = resource_p->gsi_ch20_wa;
ipa3_ctx->use_ipa_pm = resource_p->use_ipa_pm;
+ ipa3_ctx->wdi_over_pcie = resource_p->wdi_over_pcie;
ipa3_ctx->ipa3_active_clients_logging.log_rdy = false;
ipa3_ctx->ipa_config_is_mhi = resource_p->ipa_mhi_dynamic_config;
ipa3_ctx->mhi_evid_limits[0] = resource_p->mhi_evid_limits[0];
@@ -5872,6 +5873,12 @@
return result;
}
+ ipa_drv_res->wdi_over_pcie =
+ of_property_read_bool(pdev->dev.of_node,
+ "qcom,wlan-ce-db-over-pcie");
+ IPADBG("Is wdi_over_pcie ? (%s)\n",
+ ipa_drv_res->wdi_over_pcie ? "Yes":"No");
+
/*
* If we're on emulator, get its interrupt controller's mem
* start and size
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c
index 5bcd49e..cfac126 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c
@@ -63,7 +63,15 @@
IPADBG("Enabling data path\n");
if (IPA_CLIENT_IS_CONS(ep->client)) {
memset(&holb_cfg, 0, sizeof(holb_cfg));
- holb_cfg.en = IPA_HOLB_TMR_DIS;
+ /*
+ * Set HOLB on USB DPL CONS to avoid IPA stall
+ * if DPL client is not pulling the data
+ * on other end from IPA hw.
+ */
+ if (ep->client == IPA_CLIENT_USB_DPL_CONS)
+ holb_cfg.en = IPA_HOLB_TMR_EN;
+ else
+ holb_cfg.en = IPA_HOLB_TMR_DIS;
holb_cfg.tmr_val = 0;
res = ipa3_cfg_ep_holb(clnt_hdl, &holb_cfg);
}
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
index 10abdcf..3728a43 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
@@ -2089,7 +2089,7 @@
"ipa_low", 0);
}
if (ipa_ipc_low_buff == NULL)
- IPAERR("failed to get logbuf_low\n");
+ IPADBG("failed to get logbuf_low\n");
ipa3_ctx->logbuf_low = ipa_ipc_low_buff;
} else {
ipa3_ctx->logbuf_low = NULL;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_hw_stats.c b/drivers/platform/msm/ipa/ipa_v3/ipa_hw_stats.c
index 547c9da..5e398cc 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_hw_stats.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_hw_stats.c
@@ -231,6 +231,9 @@
IPADBG_LOW("offset = %d size = %d\n", offset.offset, offset.size);
+ if (offset.size == 0)
+ return 0;
+
mem.size = offset.size;
mem.base = dma_alloc_coherent(ipa3_ctx->pdev,
mem.size,
@@ -541,6 +544,9 @@
IPADBG_LOW("offset = %d size = %d\n", offset.offset, offset.size);
+ if (offset.size == 0)
+ return 0;
+
mem.size = offset.size;
mem.base = dma_alloc_coherent(ipa3_ctx->pdev,
mem.size,
@@ -1099,6 +1105,11 @@
IPADBG_LOW("offset = %d size = %d\n", offset.offset, offset.size);
+ if (offset.size == 0) {
+ ret = 0;
+ goto free_offset;
+ }
+
mem.size = offset.size;
mem.base = dma_alloc_coherent(ipa3_ctx->pdev,
mem.size,
@@ -1368,6 +1379,9 @@
IPADBG_LOW("offset = %d size = %d\n", offset.offset, offset.size);
+ if (offset.size == 0)
+ return 0;
+
mem.size = offset.size;
mem.base = dma_alloc_coherent(ipa3_ctx->pdev,
mem.size,
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
index c860bd0..43f4c74 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
@@ -1604,6 +1604,7 @@
struct mutex ipa_cne_evt_lock;
bool use_ipa_pm;
bool vlan_mode_iface[IPA_VLAN_IF_MAX];
+ bool wdi_over_pcie;
};
struct ipa3_plat_drv_res {
@@ -1638,6 +1639,7 @@
struct ipa_tz_unlock_reg_info *ipa_tz_unlock_reg;
bool use_ipa_pm;
struct ipa_pm_init_params pm_init;
+ bool wdi_over_pcie;
};
/**
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_ntn.c b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_ntn.c
index f4068bf..2401166 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_ntn.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_ntn.c
@@ -508,6 +508,8 @@
result = -EFAULT;
goto fail_smmu_map_dl;
}
+
+ IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
IPADBG("client %d (ep: %d) connected\n", in->dl.client,
ipa_ep_idx_dl);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c
index 13d2511..3cbc0c6 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c
@@ -756,16 +756,21 @@
return -EINVAL;
}
- if (IPA_CLIENT_IS_CONS(in->sys.client)) {
- if (in->u.dl.comp_ring_base_pa % IPA_WDI_RING_ALIGNMENT ||
- in->u.dl.ce_ring_base_pa % IPA_WDI_RING_ALIGNMENT) {
- IPAERR("alignment failure on TX\n");
- return -EINVAL;
- }
- } else {
- if (in->u.ul.rdy_ring_base_pa % IPA_WDI_RING_ALIGNMENT) {
- IPAERR("alignment failure on RX\n");
- return -EINVAL;
+ if (!in->smmu_enabled) {
+ if (IPA_CLIENT_IS_CONS(in->sys.client)) {
+ if (in->u.dl.comp_ring_base_pa %
+ IPA_WDI_RING_ALIGNMENT ||
+ in->u.dl.ce_ring_base_pa %
+ IPA_WDI_RING_ALIGNMENT) {
+ IPAERR("alignment failure on TX\n");
+ return -EINVAL;
+ }
+ } else {
+ if (in->u.ul.rdy_ring_base_pa %
+ IPA_WDI_RING_ALIGNMENT) {
+ IPAERR("alignment failure on RX\n");
+ return -EINVAL;
+ }
}
}
@@ -795,43 +800,73 @@
cmd.size = sizeof(*tx_2);
else
cmd.size = sizeof(*tx);
- IPADBG("comp_ring_base_pa=0x%pa\n",
- &in->u.dl.comp_ring_base_pa);
- IPADBG("comp_ring_size=%d\n", in->u.dl.comp_ring_size);
- IPADBG("ce_ring_base_pa=0x%pa\n", &in->u.dl.ce_ring_base_pa);
- IPADBG("ce_ring_size=%d\n", in->u.dl.ce_ring_size);
- IPADBG("ce_ring_doorbell_pa=0x%pa\n",
- &in->u.dl.ce_door_bell_pa);
- IPADBG("num_tx_buffers=%d\n", in->u.dl.num_tx_buffers);
+ if (in->smmu_enabled) {
+ IPADBG("comp_ring_size=%d\n",
+ in->u.dl_smmu.comp_ring_size);
+ IPADBG("ce_ring_size=%d\n", in->u.dl_smmu.ce_ring_size);
+ IPADBG("ce_ring_doorbell_pa=0x%pa\n",
+ &in->u.dl_smmu.ce_door_bell_pa);
+ IPADBG("num_tx_buffers=%d\n",
+ in->u.dl_smmu.num_tx_buffers);
+ } else {
+ IPADBG("comp_ring_base_pa=0x%pa\n",
+ &in->u.dl.comp_ring_base_pa);
+ IPADBG("comp_ring_size=%d\n", in->u.dl.comp_ring_size);
+ IPADBG("ce_ring_base_pa=0x%pa\n",
+ &in->u.dl.ce_ring_base_pa);
+ IPADBG("ce_ring_size=%d\n", in->u.dl.ce_ring_size);
+ IPADBG("ce_ring_doorbell_pa=0x%pa\n",
+ &in->u.dl.ce_door_bell_pa);
+ IPADBG("num_tx_buffers=%d\n", in->u.dl.num_tx_buffers);
+ }
} else {
if (ipa3_ctx->ipa_wdi2)
cmd.size = sizeof(*rx_2);
else
cmd.size = sizeof(*rx);
- IPADBG("rx_ring_base_pa=0x%pa\n",
- &in->u.ul.rdy_ring_base_pa);
- IPADBG("rx_ring_size=%d\n",
- in->u.ul.rdy_ring_size);
- IPADBG("rx_ring_rp_pa=0x%pa\n",
- &in->u.ul.rdy_ring_rp_pa);
- IPADBG("rx_comp_ring_base_pa=0x%pa\n",
- &in->u.ul.rdy_comp_ring_base_pa);
- IPADBG("rx_comp_ring_size=%d\n",
- in->u.ul.rdy_comp_ring_size);
- IPADBG("rx_comp_ring_wp_pa=0x%pa\n",
- &in->u.ul.rdy_comp_ring_wp_pa);
- ipa3_ctx->uc_ctx.rdy_ring_base_pa =
- in->u.ul.rdy_ring_base_pa;
- ipa3_ctx->uc_ctx.rdy_ring_rp_pa =
- in->u.ul.rdy_ring_rp_pa;
- ipa3_ctx->uc_ctx.rdy_ring_size =
- in->u.ul.rdy_ring_size;
- ipa3_ctx->uc_ctx.rdy_comp_ring_base_pa =
- in->u.ul.rdy_comp_ring_base_pa;
- ipa3_ctx->uc_ctx.rdy_comp_ring_wp_pa =
- in->u.ul.rdy_comp_ring_wp_pa;
- ipa3_ctx->uc_ctx.rdy_comp_ring_size =
- in->u.ul.rdy_comp_ring_size;
+ if (in->smmu_enabled) {
+ IPADBG("rx_ring_size=%d\n",
+ in->u.ul_smmu.rdy_ring_size);
+ IPADBG("rx_ring_rp_pa=0x%pa\n",
+ &in->u.ul_smmu.rdy_ring_rp_pa);
+ IPADBG("rx_comp_ring_size=%d\n",
+ in->u.ul_smmu.rdy_comp_ring_size);
+ IPADBG("rx_comp_ring_wp_pa=0x%pa\n",
+ &in->u.ul_smmu.rdy_comp_ring_wp_pa);
+ ipa3_ctx->uc_ctx.rdy_ring_rp_pa =
+ in->u.ul_smmu.rdy_ring_rp_pa;
+ ipa3_ctx->uc_ctx.rdy_ring_size =
+ in->u.ul_smmu.rdy_ring_size;
+ ipa3_ctx->uc_ctx.rdy_comp_ring_wp_pa =
+ in->u.ul_smmu.rdy_comp_ring_wp_pa;
+ ipa3_ctx->uc_ctx.rdy_comp_ring_size =
+ in->u.ul_smmu.rdy_comp_ring_size;
+ } else {
+ IPADBG("rx_ring_base_pa=0x%pa\n",
+ &in->u.ul.rdy_ring_base_pa);
+ IPADBG("rx_ring_size=%d\n",
+ in->u.ul.rdy_ring_size);
+ IPADBG("rx_ring_rp_pa=0x%pa\n",
+ &in->u.ul.rdy_ring_rp_pa);
+ IPADBG("rx_comp_ring_base_pa=0x%pa\n",
+ &in->u.ul.rdy_comp_ring_base_pa);
+ IPADBG("rx_comp_ring_size=%d\n",
+ in->u.ul.rdy_comp_ring_size);
+ IPADBG("rx_comp_ring_wp_pa=0x%pa\n",
+ &in->u.ul.rdy_comp_ring_wp_pa);
+ ipa3_ctx->uc_ctx.rdy_ring_base_pa =
+ in->u.ul.rdy_ring_base_pa;
+ ipa3_ctx->uc_ctx.rdy_ring_rp_pa =
+ in->u.ul.rdy_ring_rp_pa;
+ ipa3_ctx->uc_ctx.rdy_ring_size =
+ in->u.ul.rdy_ring_size;
+ ipa3_ctx->uc_ctx.rdy_comp_ring_base_pa =
+ in->u.ul.rdy_comp_ring_base_pa;
+ ipa3_ctx->uc_ctx.rdy_comp_ring_wp_pa =
+ in->u.ul.rdy_comp_ring_wp_pa;
+ ipa3_ctx->uc_ctx.rdy_comp_ring_size =
+ in->u.ul.rdy_comp_ring_size;
+ }
}
cmd.base = dma_alloc_coherent(ipa3_ctx->uc_pdev, cmd.size,
@@ -945,10 +980,11 @@
tx->comp_ring_size = len;
len = in->smmu_enabled ? in->u.dl_smmu.ce_ring_size :
in->u.dl.ce_ring_size;
- IPADBG("TX CE ring smmu_en=%d ring_size=%d %d\n",
+ IPADBG("TX CE ring smmu_en=%d ring_size=%d %d 0x%lx\n",
in->smmu_enabled,
in->u.dl_smmu.ce_ring_size,
- in->u.dl.ce_ring_size);
+ in->u.dl.ce_ring_size,
+ va);
if (ipa_create_uc_smmu_mapping(IPA_WDI_CE_RING_RES,
in->smmu_enabled,
in->u.dl.ce_ring_base_pa,
@@ -975,8 +1011,19 @@
result = -ENOMEM;
goto uc_timeout;
}
- tx->ce_ring_doorbell_pa = va;
- tx->num_tx_buffers = in->u.dl.num_tx_buffers;
+
+ IPADBG("CE doorbell pa: 0x%pa va:0x%lx\n", &pa, va);
+ IPADBG("Is wdi_over_pcie ? (%s)\n",
+ ipa3_ctx->wdi_over_pcie ? "Yes":"No");
+
+ if (ipa3_ctx->wdi_over_pcie)
+ tx->ce_ring_doorbell_pa = pa;
+ else
+ tx->ce_ring_doorbell_pa = va;
+
+ tx->num_tx_buffers = in->smmu_enabled ?
+ in->u.dl_smmu.num_tx_buffers :
+ in->u.dl.num_tx_buffers;
tx->ipa_pipe_number = ipa_ep_idx;
}
out->uc_door_bell_pa = ipa3_ctx->ipa_wrapper_base +
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c
index d015b22..3569760 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2018, 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
@@ -1570,6 +1570,12 @@
goto bail_free_fltrt;
}
+ /* create an IPC buffer for the registers dump */
+ ipahal_ctx->regdumpbuf = ipc_log_context_create(IPAHAL_IPC_LOG_PAGES,
+ "ipa_regs", 0);
+ if (ipahal_ctx->regdumpbuf == NULL)
+ IPAHAL_ERR("failed to create IPA regdump log, continue...\n");
+
ipahal_debugfs_init();
return 0;
@@ -1577,6 +1583,8 @@
bail_free_fltrt:
ipahal_fltrt_destroy();
bail_free_ctx:
+ if (ipahal_ctx->regdumpbuf)
+ ipc_log_context_destroy(ipahal_ctx->regdumpbuf);
kfree(ipahal_ctx);
ipahal_ctx = NULL;
bail_err_exit:
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h
index d46f13c..816bc58 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h
@@ -46,23 +46,6 @@
IPAHAL_DRV_NAME " %s:%d " fmt, ## args); \
} while (0)
-#define IPAHAL_DBG_REG(fmt, args...) \
- do { \
- pr_err(fmt, ## args); \
- IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \
- " %s:%d " fmt, ## args); \
- IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
- " %s:%d " fmt, ## args); \
- } while (0)
-
-#define IPAHAL_DBG_REG_IPC_ONLY(fmt, args...) \
- do { \
- IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \
- " %s:%d " fmt, ## args); \
- IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
- " %s:%d " fmt, ## args); \
- } while (0)
-
#define IPAHAL_ERR_RL(fmt, args...) \
do { \
pr_err_ratelimited_ipa(IPAHAL_DRV_NAME " %s:%d " fmt, \
@@ -73,9 +56,24 @@
IPAHAL_DRV_NAME " %s:%d " fmt, ## args); \
} while (0)
+#define IPAHAL_DBG_REG(fmt, args...) \
+ do { \
+ pr_err(fmt, ## args); \
+ IPA_IPC_LOGGING(ipahal_ctx->regdumpbuf, \
+ " %s:%d " fmt, ## args); \
+ } while (0)
+
+#define IPAHAL_DBG_REG_IPC_ONLY(fmt, args...) \
+ do { \
+ IPA_IPC_LOGGING(ipahal_ctx->regdumpbuf, \
+ " %s:%d " fmt, ## args); \
+ } while (0)
+
#define IPAHAL_MEM_ALLOC(__size, __is_atomic_ctx) \
(kzalloc((__size), ((__is_atomic_ctx) ? GFP_ATOMIC : GFP_KERNEL)))
+#define IPAHAL_IPC_LOG_PAGES 50
+
/*
* struct ipahal_context - HAL global context data
* @hw_type: IPA H/W type/version.
@@ -92,6 +90,7 @@
struct dentry *dent;
struct device *ipa_pdev;
struct ipa_mem_buffer empty_fltrt_tbl;
+ void *regdumpbuf;
};
extern struct ipahal_context *ipahal_ctx;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
index 2dbea95..88998ce 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
@@ -2237,7 +2237,7 @@
0x00000CC0, 0x70, 10, 23, 1},
};
-int ipahal_print_all_regs(bool print_to_dmesg)
+void ipahal_print_all_regs(bool print_to_dmesg)
{
int i, j;
@@ -2247,7 +2247,7 @@
if ((ipahal_ctx->hw_type < IPA_HW_v4_0) ||
(ipahal_ctx->hw_type >= IPA_HW_MAX)) {
IPAHAL_ERR("invalid IPA HW type (%d)\n", ipahal_ctx->hw_type);
- return -EINVAL;
+ return;
}
for (i = 0; i < IPA_REG_MAX ; i++) {
@@ -2267,11 +2267,17 @@
ipahal_read_reg_n(i, j));
}
- for (; j < ipahal_reg_objs[ipahal_ctx->hw_type][i].n_end; j++)
- IPAHAL_DBG_REG("%s_%u=0x%x\n", ipahal_reg_name_str(i),
- j, ipahal_read_reg_n(i, j));
+ for (; j < ipahal_reg_objs[ipahal_ctx->hw_type][i].n_end; j++) {
+ if (print_to_dmesg)
+ IPAHAL_DBG_REG("%s_%u=0x%x\n",
+ ipahal_reg_name_str(i),
+ j, ipahal_read_reg_n(i, j));
+ else
+ IPAHAL_DBG_REG_IPC_ONLY("%s_%u=0x%x\n",
+ ipahal_reg_name_str(i),
+ j, ipahal_read_reg_n(i, j));
+ }
}
- return 0;
}
/*
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h
index fdf4fd1..c1c86a3 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h
@@ -524,7 +524,7 @@
};
-int ipahal_print_all_regs(bool print_to_dmesg);
+void ipahal_print_all_regs(bool print_to_dmesg);
/*
* ipahal_reg_name_str() - returns string that represent the register
diff --git a/drivers/platform/msm/mhi_dev/mhi.c b/drivers/platform/msm/mhi_dev/mhi.c
index 3e577cf..3e245cc 100644
--- a/drivers/platform/msm/mhi_dev/mhi.c
+++ b/drivers/platform/msm/mhi_dev/mhi.c
@@ -1494,6 +1494,7 @@
enum mhi_dev_state state;
enum mhi_dev_event event = 0;
bool mhi_reset = false;
+ uint32_t bhi_imgtxdb = 0;
mutex_lock(&mhi_ctx->mhi_lock);
/* Check for interrupts */
@@ -1531,6 +1532,10 @@
pr_err("error sending SM event\n");
goto fail;
}
+
+ rc = mhi_dev_mmio_read(mhi, BHI_IMGTXDB, &bhi_imgtxdb);
+ mhi_log(MHI_MSG_VERBOSE,
+ "BHI_IMGTXDB = 0x%x\n", bhi_imgtxdb);
}
if (int_value & MHI_MMIO_CTRL_CRDB_STATUS_MSK) {
@@ -1889,6 +1894,7 @@
(struct mhi_dev_client_cb_reason *cb))
{
int rc = 0;
+ int i = 0;
struct mhi_dev_channel *ch;
struct platform_device *pdev;
@@ -1912,6 +1918,38 @@
goto exit;
}
+ /* Pre allocate event requests */
+ ch->ereqs = kcalloc(MHI_MAX_EVT_REQ, sizeof(*ch->ereqs), GFP_KERNEL);
+ if (!ch->ereqs) {
+ rc = -ENOMEM;
+ goto free_client;
+ }
+ /* pre allocate buffers to queue transfer completion events */
+ ch->tr_events = kcalloc(MHI_MAX_EVT_REQ,
+ MAX_TR_EVENTS * sizeof(*ch->tr_events),
+ GFP_KERNEL);
+ if (!ch->tr_events) {
+ rc = -ENOMEM;
+ goto free_ereqs;
+ }
+
+ /*
+ * Organize the above allocated event request block and
+ * completion event block into linked lists. Each event
+ * request includes a pointer to a block of MAX_TR_EVENTS
+ * completion events.
+ */
+ INIT_LIST_HEAD(&mhi_ctx->ch[chan_id].event_req_buffers);
+ for (i = 0; i < MHI_MAX_EVT_REQ; ++i) {
+ ch->ereqs[i].tr_events = ch->tr_events + i * MAX_TR_EVENTS;
+ list_add_tail(&ch->ereqs[i].list,
+ &mhi_ctx->ch[chan_id].event_req_buffers);
+ }
+ mhi_ctx->ch[chan_id].curr_ereq =
+ container_of(mhi_ctx->ch[chan_id].event_req_buffers.next,
+ struct event_req, list);
+ list_del_init(&mhi_ctx->ch[chan_id].curr_ereq->list);
+
ch->active_client = (*handle_client);
(*handle_client)->channel = ch;
(*handle_client)->event_trigger = mhi_dev_client_cb_reason;
@@ -1924,6 +1962,13 @@
else if (ch->state == MHI_DEV_CH_STOPPED)
ch->state = MHI_DEV_CH_PENDING_START;
+ goto exit;
+
+free_ereqs:
+ kfree(ch->ereqs);
+ ch->ereqs = NULL;
+free_client:
+ kfree(*handle_client);
exit:
mutex_unlock(&ch->ch_lock);
return rc;
@@ -1957,14 +2002,12 @@
mhi_log(MHI_MSG_ERROR,
"Trying to close an active channel (%d)\n",
ch->ch_id);
- mutex_unlock(&ch->ch_lock);
rc = -EAGAIN;
goto exit;
} else if (ch->tre_loc) {
mhi_log(MHI_MSG_ERROR,
"Trying to close channel (%d) when a TRE is active",
ch->ch_id);
- mutex_unlock(&ch->ch_lock);
rc = -EAGAIN;
goto exit;
}
@@ -1972,6 +2015,10 @@
ch->state = MHI_DEV_CH_CLOSED;
ch->active_client = NULL;
+ kfree(ch->ereqs);
+ kfree(ch->tr_events);
+ ch->ereqs = NULL;
+ ch->tr_events = NULL;
kfree(handle);
exit:
mutex_unlock(&ch->ch_lock);
@@ -2678,40 +2725,8 @@
if (!mhi->ch)
return -ENOMEM;
-
- for (i = 0; i < mhi->cfg.channels; i++) {
+ for (i = 0; i < mhi->cfg.channels; i++)
mutex_init(&mhi->ch[i].ch_lock);
- if (i == MHI_CLIENT_IP_SW_4_OUT || i == MHI_CLIENT_IP_SW_4_IN) {
- int nreq = 0;
-
- INIT_LIST_HEAD(&mhi->ch[i].event_req_buffers);
- while (nreq < MHI_MAX_EVT_REQ) {
- struct event_req *ereq;
- /* Pre allocate event requests */
- ereq = kzalloc(sizeof(struct event_req),
- GFP_KERNEL);
- if (!ereq)
- return -ENOMEM;
-
- /* pre allocate buffers to queue
- * transfer completion events
- */
- ereq->tr_events = kzalloc(RING_ELEMENT_TYPE_SZ*
- MAX_TR_EVENTS, GFP_KERNEL);
- if (!ereq->tr_events) {
- kfree(ereq);
- return -ENOMEM;
- }
- list_add_tail(&ereq->list,
- &mhi->ch[i].event_req_buffers);
- nreq++;
- }
- mhi->ch[i].curr_ereq =
- container_of(mhi->ch[i].event_req_buffers.next,
- struct event_req, list);
- list_del_init(&mhi->ch[i].curr_ereq->list);
- }
- }
spin_lock_init(&mhi->lock);
mhi->mmio_backup = devm_kzalloc(&pdev->dev,
diff --git a/drivers/platform/msm/mhi_dev/mhi.h b/drivers/platform/msm/mhi_dev/mhi.h
index 2cc7809..3559021 100644
--- a/drivers/platform/msm/mhi_dev/mhi.h
+++ b/drivers/platform/msm/mhi_dev/mhi.h
@@ -484,7 +484,13 @@
struct mutex ch_lock;
/* client which the current inbound/outbound message is for */
struct mhi_dev_client *active_client;
-
+ /*
+ * Pointer to event request structs used to temporarily store
+ * completion events and meta data before sending them to host
+ */
+ struct event_req *ereqs;
+ /* Pointer to completion event buffers */
+ union mhi_dev_ring_element_type *tr_events;
struct list_head event_req_buffers;
struct event_req *curr_ereq;
@@ -704,7 +710,9 @@
MHI_CLIENT_SMCT_IN = 45,
MHI_CLIENT_IP_SW_4_OUT = 46,
MHI_CLIENT_IP_SW_4_IN = 47,
- MHI_MAX_SOFTWARE_CHANNELS = 48,
+ MHI_CLIENT_ADB_OUT = 48,
+ MHI_CLIENT_ADB_IN = 49,
+ MHI_MAX_SOFTWARE_CHANNELS,
MHI_CLIENT_TEST_OUT = 60,
MHI_CLIENT_TEST_IN = 61,
MHI_CLIENT_RESERVED_1_LOWER = 62,
diff --git a/drivers/platform/msm/mhi_dev/mhi_hwio.h b/drivers/platform/msm/mhi_dev/mhi_hwio.h
index 09a0118..936cac7 100644
--- a/drivers/platform/msm/mhi_dev/mhi_hwio.h
+++ b/drivers/platform/msm/mhi_dev/mhi_hwio.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, 2017-2018 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015, 2017-2018, 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
@@ -192,4 +192,6 @@
#define BHI_EXECENV_MASK 0xFFFFFFFF
#define BHI_EXECENV_SHIFT 0
+#define BHI_IMGTXDB (0x218)
+
#endif
diff --git a/drivers/platform/msm/mhi_dev/mhi_sm.c b/drivers/platform/msm/mhi_dev/mhi_sm.c
index af05c9e..917b258 100644
--- a/drivers/platform/msm/mhi_dev/mhi_sm.c
+++ b/drivers/platform/msm/mhi_dev/mhi_sm.c
@@ -398,15 +398,18 @@
break;
case EP_PCIE_EVENT_PM_D3_HOT:
res = ((curr_mstate == MHI_DEV_M3_STATE ||
- curr_mstate == MHI_DEV_READY_STATE) &&
+ curr_mstate == MHI_DEV_READY_STATE ||
+ curr_mstate == MHI_DEV_RESET_STATE) &&
curr_dstate != MHI_SM_EP_PCIE_LINK_DISABLE);
break;
case EP_PCIE_EVENT_PM_D3_COLD:
res = (curr_dstate == MHI_SM_EP_PCIE_D3_HOT_STATE ||
- curr_dstate == MHI_SM_EP_PCIE_D3_COLD_STATE);
+ curr_dstate == MHI_SM_EP_PCIE_D3_COLD_STATE ||
+ curr_dstate == MHI_SM_EP_PCIE_D0_STATE);
break;
case EP_PCIE_EVENT_PM_RST_DEAST:
res = (curr_dstate == MHI_SM_EP_PCIE_D0_STATE ||
+ curr_dstate == MHI_SM_EP_PCIE_D3_HOT_STATE ||
curr_dstate == MHI_SM_EP_PCIE_D3_COLD_STATE);
break;
case EP_PCIE_EVENT_PM_D0:
diff --git a/drivers/platform/msm/mhi_dev/mhi_uci.c b/drivers/platform/msm/mhi_dev/mhi_uci.c
index febc867..52d324e 100644
--- a/drivers/platform/msm/mhi_dev/mhi_uci.c
+++ b/drivers/platform/msm/mhi_dev/mhi_uci.c
@@ -29,15 +29,18 @@
#include <uapi/linux/mhi.h>
#include "mhi.h"
-#define MHI_DEV_NODE_NAME_LEN 13
-#define MHI_MAX_NR_OF_CLIENTS 23
#define MHI_SOFTWARE_CLIENT_START 0
#define MHI_SOFTWARE_CLIENT_LIMIT (MHI_MAX_SOFTWARE_CHANNELS/2)
#define MHI_UCI_IPC_LOG_PAGES (100)
+/* Max number of MHI write request structures (used in async writes) */
+#define MAX_UCI_WR_REQ 10
#define MAX_NR_TRBS_PER_CHAN 9
#define MHI_QTI_IFACE_ID 4
-#define DEVICE_NAME "mhi"
+#define DEVICE_NAME "mhi"
+#define MAX_DEVICE_NAME_SIZE 80
+
+#define MHI_UCI_ASYNC_READ_TIMEOUT msecs_to_jiffies(100)
enum uci_dbg_level {
UCI_DBG_VERBOSE = 0x0,
@@ -72,6 +75,8 @@
enum mhi_chan_dir dir;
/* need to register mhi channel state change callback */
bool register_cb;
+ /* Name of char device */
+ char *device_name;
};
/* UCI channel attributes table */
@@ -81,119 +86,144 @@
TRB_MAX_DATA_SIZE,
MAX_NR_TRBS_PER_CHAN,
MHI_DIR_OUT,
- false
+ false,
+ NULL
},
{
MHI_CLIENT_LOOPBACK_IN,
TRB_MAX_DATA_SIZE,
MAX_NR_TRBS_PER_CHAN,
MHI_DIR_IN,
- false
+ false,
+ NULL
},
{
MHI_CLIENT_SAHARA_OUT,
TRB_MAX_DATA_SIZE,
MAX_NR_TRBS_PER_CHAN,
MHI_DIR_OUT,
- false
+ false,
+ NULL
},
{
MHI_CLIENT_SAHARA_IN,
TRB_MAX_DATA_SIZE,
MAX_NR_TRBS_PER_CHAN,
MHI_DIR_IN,
- false
+ false,
+ NULL
},
{
MHI_CLIENT_EFS_OUT,
TRB_MAX_DATA_SIZE,
MAX_NR_TRBS_PER_CHAN,
MHI_DIR_OUT,
- false
+ false,
+ NULL
},
{
MHI_CLIENT_EFS_IN,
TRB_MAX_DATA_SIZE,
MAX_NR_TRBS_PER_CHAN,
MHI_DIR_IN,
- false
+ false,
+ NULL
},
{
MHI_CLIENT_MBIM_OUT,
TRB_MAX_DATA_SIZE,
MAX_NR_TRBS_PER_CHAN,
MHI_DIR_OUT,
- false
+ false,
+ NULL
},
{
MHI_CLIENT_MBIM_IN,
TRB_MAX_DATA_SIZE,
MAX_NR_TRBS_PER_CHAN,
MHI_DIR_IN,
- false
+ false,
+ NULL
},
{
MHI_CLIENT_QMI_OUT,
TRB_MAX_DATA_SIZE,
MAX_NR_TRBS_PER_CHAN,
MHI_DIR_OUT,
- false
+ false,
+ NULL
},
{
MHI_CLIENT_QMI_IN,
TRB_MAX_DATA_SIZE,
MAX_NR_TRBS_PER_CHAN,
MHI_DIR_IN,
- false
+ false,
+ NULL
},
{
MHI_CLIENT_IP_CTRL_0_OUT,
TRB_MAX_DATA_SIZE,
MAX_NR_TRBS_PER_CHAN,
MHI_DIR_OUT,
- false
+ false,
+ NULL
},
{
MHI_CLIENT_IP_CTRL_0_IN,
TRB_MAX_DATA_SIZE,
MAX_NR_TRBS_PER_CHAN,
MHI_DIR_IN,
- false
+ false,
+ NULL
},
{
MHI_CLIENT_IP_CTRL_1_OUT,
TRB_MAX_DATA_SIZE,
MAX_NR_TRBS_PER_CHAN,
MHI_DIR_OUT,
- false
+ false,
+ NULL
},
{
MHI_CLIENT_IP_CTRL_1_IN,
TRB_MAX_DATA_SIZE,
MAX_NR_TRBS_PER_CHAN,
MHI_DIR_IN,
- false
+ false,
+ NULL
},
{
MHI_CLIENT_DUN_OUT,
TRB_MAX_DATA_SIZE,
MAX_NR_TRBS_PER_CHAN,
MHI_DIR_OUT,
- false
+ false,
+ NULL
},
{
MHI_CLIENT_DUN_IN,
TRB_MAX_DATA_SIZE,
MAX_NR_TRBS_PER_CHAN,
MHI_DIR_IN,
- false
+ false,
+ NULL
},
- { /* Must be the last */
- MHI_CLIENT_INVALID,
- 0,
- 0,
- MHI_DIR_INVALID,
- false
+ {
+ MHI_CLIENT_ADB_OUT,
+ TRB_MAX_DATA_SIZE,
+ MAX_NR_TRBS_PER_CHAN,
+ MHI_DIR_OUT,
+ true,
+ NULL
+ },
+ {
+ MHI_CLIENT_ADB_IN,
+ TRB_MAX_DATA_SIZE,
+ MAX_NR_TRBS_PER_CHAN,
+ MHI_DIR_IN,
+ true,
+ "android_adb"
},
};
@@ -227,6 +257,13 @@
struct mhi_uci_ctxt_t *uci_ctxt;
struct mutex in_chan_lock;
struct mutex out_chan_lock;
+ spinlock_t wr_req_lock;
+ unsigned int f_flags;
+ struct mhi_req *wreqs;
+ struct list_head wr_req_list;
+ struct completion read_done;
+ int (*send)(struct uci_client*, void*, u32);
+ int (*read)(struct uci_client*, struct mhi_req*, int*);
};
struct mhi_uci_ctxt_t {
@@ -301,8 +338,11 @@
client_handle->in_chan);
return -EINVAL;
}
- buf_size = in_chan_attr->max_packet_size;
+ /* Init the completion event for read */
+ init_completion(&client_handle->read_done);
+
+ buf_size = in_chan_attr->max_packet_size;
for (i = 0; i < (in_chan_attr->nr_trbs); i++) {
data_loc = kmalloc(buf_size, GFP_KERNEL);
if (!data_loc) {
@@ -322,48 +362,129 @@
return rc;
}
-static int mhi_uci_send_packet(struct mhi_dev_client **client_handle, void *buf,
- u32 size, u32 is_uspace_buf)
+static void mhi_uci_write_completion_cb(void *req)
{
- void *data_loc = NULL;
- uintptr_t memcpy_result = 0;
- u32 data_inserted_so_far = 0;
+ struct mhi_req *ureq = req;
struct uci_client *uci_handle;
+ unsigned long flags;
+
+ uci_handle = (struct uci_client *)ureq->context;
+ kfree(ureq->buf);
+ ureq->buf = NULL;
+
+ spin_lock_irqsave(&uci_handle->wr_req_lock, flags);
+ list_add_tail(&ureq->list, &uci_handle->wr_req_list);
+ spin_unlock_irqrestore(&uci_handle->wr_req_lock, flags);
+}
+
+static void mhi_uci_read_completion_cb(void *req)
+{
+ struct mhi_req *ureq = req;
+ struct uci_client *uci_handle;
+
+ uci_handle = (struct uci_client *)ureq->context;
+ complete(&uci_handle->read_done);
+}
+
+static int mhi_uci_send_sync(struct uci_client *uci_handle,
+ void *data_loc, u32 size)
+{
struct mhi_req ureq;
+ int ret_val;
-
- uci_handle = container_of(client_handle, struct uci_client,
- out_handle);
-
- if (!client_handle || !buf ||
- !size || !uci_handle)
- return -EINVAL;
-
- if (is_uspace_buf) {
- data_loc = kmalloc(size, GFP_KERNEL);
- if (!data_loc) {
- uci_log(UCI_DBG_ERROR,
- "Failed to allocate memory 0x%x\n",
- size);
- return -ENOMEM;
- }
- memcpy_result = copy_from_user(data_loc, buf, size);
- if (memcpy_result)
- goto error_memcpy;
- } else {
- data_loc = buf;
- }
- ureq.client = *client_handle;
+ ureq.client = uci_handle->out_handle;
ureq.buf = data_loc;
ureq.len = size;
ureq.chan = uci_handle->out_chan;
ureq.mode = IPA_DMA_SYNC;
- data_inserted_so_far = mhi_dev_write_channel(&ureq);
+ ret_val = mhi_dev_write_channel(&ureq);
+
+ kfree(data_loc);
+ return ret_val;
+}
+
+static int mhi_uci_send_async(struct uci_client *uci_handle,
+ void *data_loc, u32 size)
+{
+ int bytes_to_write;
+ struct mhi_req *ureq;
+
+ uci_log(UCI_DBG_VERBOSE,
+ "Got async write for ch %d of size %d\n",
+ uci_handle->out_chan, size);
+
+ spin_lock_irq(&uci_handle->wr_req_lock);
+ if (list_empty(&uci_handle->wr_req_list)) {
+ uci_log(UCI_DBG_ERROR, "Write request pool empty\n");
+ spin_unlock_irq(&uci_handle->wr_req_lock);
+ return -ENOMEM;
+ }
+ ureq = container_of(uci_handle->wr_req_list.next,
+ struct mhi_req, list);
+ list_del_init(&ureq->list);
+ spin_unlock_irq(&uci_handle->wr_req_lock);
+
+ ureq->client = uci_handle->out_handle;
+ ureq->context = uci_handle;
+ ureq->buf = data_loc;
+ ureq->len = size;
+ ureq->chan = uci_handle->out_chan;
+ ureq->mode = IPA_DMA_ASYNC;
+ ureq->client_cb = mhi_uci_write_completion_cb;
+ ureq->snd_cmpl = 1;
+
+ bytes_to_write = mhi_dev_write_channel(ureq);
+ if (bytes_to_write != size)
+ goto error_async_transfer;
+
+ return bytes_to_write;
+
+error_async_transfer:
+ kfree(data_loc);
+ ureq->buf = NULL;
+ spin_lock_irq(&uci_handle->wr_req_lock);
+ list_add_tail(&ureq->list, &uci_handle->wr_req_list);
+ spin_unlock_irq(&uci_handle->wr_req_lock);
+
+ return bytes_to_write;
+}
+
+static int mhi_uci_send_packet(struct mhi_dev_client **client_handle,
+ const char __user *buf, u32 size)
+{
+ void *data_loc;
+ unsigned long memcpy_result;
+ struct uci_client *uci_handle;
+
+ if (!client_handle || !buf || !size)
+ return -EINVAL;
+
+ if (size > TRB_MAX_DATA_SIZE) {
+ uci_log(UCI_DBG_ERROR,
+ "Too big write size: %d, max supported size is %d\n",
+ size, TRB_MAX_DATA_SIZE);
+ return -EFBIG;
+ }
+
+ uci_handle = container_of(client_handle, struct uci_client,
+ out_handle);
+ data_loc = kmalloc(size, GFP_KERNEL);
+ if (!data_loc) {
+ uci_log(UCI_DBG_ERROR,
+ "Failed to allocate kernel buf for user requested size 0x%x\n",
+ size);
+ return -ENOMEM;
+ }
+ memcpy_result = copy_from_user(data_loc, buf, size);
+ if (memcpy_result)
+ goto error_memcpy;
+
+ return uci_handle->send(uci_handle, data_loc, size);
error_memcpy:
kfree(data_loc);
- return data_inserted_so_far;
+ return -EFAULT;
}
static unsigned int mhi_uci_ctrl_poll(struct file *file, poll_table *wait)
@@ -421,6 +542,119 @@
return mask;
}
+static int mhi_uci_alloc_write_reqs(struct uci_client *client)
+{
+ int i;
+
+ client->wreqs = kcalloc(MAX_UCI_WR_REQ,
+ sizeof(struct mhi_req),
+ GFP_KERNEL);
+ if (!client->wreqs) {
+ uci_log(UCI_DBG_ERROR, "Write reqs alloc failed\n");
+ return -ENOMEM;
+ }
+
+ INIT_LIST_HEAD(&client->wr_req_list);
+ for (i = 0; i < MAX_UCI_WR_REQ; ++i)
+ list_add_tail(&client->wreqs[i].list, &client->wr_req_list);
+
+ uci_log(UCI_DBG_INFO,
+ "UCI write reqs allocation successful\n");
+ return 0;
+}
+
+static int mhi_uci_read_async(struct uci_client *uci_handle,
+ struct mhi_req *ureq, int *bytes_avail)
+{
+ int ret_val = 0;
+ unsigned long compl_ret;
+
+ uci_log(UCI_DBG_ERROR,
+ "Async read for ch %d\n", uci_handle->in_chan);
+
+ ureq->mode = IPA_DMA_ASYNC;
+ ureq->client_cb = mhi_uci_read_completion_cb;
+ ureq->snd_cmpl = 1;
+ ureq->context = uci_handle;
+
+ reinit_completion(&uci_handle->read_done);
+
+ *bytes_avail = mhi_dev_read_channel(ureq);
+ uci_log(UCI_DBG_VERBOSE, "buf_size = 0x%x bytes_read = 0x%x\n",
+ ureq->len, *bytes_avail);
+ if (*bytes_avail < 0) {
+ uci_log(UCI_DBG_ERROR, "Failed to read channel ret %d\n",
+ *bytes_avail);
+ return -EIO;
+ }
+
+ if (*bytes_avail > 0) {
+ uci_log(UCI_DBG_VERBOSE,
+ "Waiting for async read completion!\n");
+ compl_ret =
+ wait_for_completion_interruptible_timeout(
+ &uci_handle->read_done,
+ MHI_UCI_ASYNC_READ_TIMEOUT);
+
+ if (compl_ret == -ERESTARTSYS) {
+ uci_log(UCI_DBG_ERROR, "Exit signal caught\n");
+ return compl_ret;
+ } else if (compl_ret == 0) {
+ uci_log(UCI_DBG_ERROR, "Read timed out for ch %d\n",
+ uci_handle->in_chan);
+ return -EIO;
+ }
+ uci_log(UCI_DBG_VERBOSE,
+ "wk up Read completed on ch %d\n", ureq->chan);
+
+ uci_handle->pkt_loc = (void *)ureq->buf;
+ uci_handle->pkt_size = ureq->actual_len;
+
+ uci_log(UCI_DBG_VERBOSE,
+ "Got pkt of sz 0x%x at adr %pK, ch %d\n",
+ uci_handle->pkt_size,
+ ureq->buf, ureq->chan);
+ } else {
+ uci_handle->pkt_loc = NULL;
+ uci_handle->pkt_size = 0;
+ }
+
+ return ret_val;
+}
+
+static int mhi_uci_read_sync(struct uci_client *uci_handle,
+ struct mhi_req *ureq, int *bytes_avail)
+{
+ int ret_val = 0;
+
+ ureq->mode = IPA_DMA_SYNC;
+ *bytes_avail = mhi_dev_read_channel(ureq);
+
+ uci_log(UCI_DBG_VERBOSE, "buf_size = 0x%x bytes_read = 0x%x\n",
+ ureq->len, *bytes_avail);
+
+ if (*bytes_avail < 0) {
+ uci_log(UCI_DBG_ERROR, "Failed to read channel ret %d\n",
+ *bytes_avail);
+ return -EIO;
+ }
+
+ if (*bytes_avail > 0) {
+ uci_handle->pkt_loc = (void *)ureq->buf;
+ uci_handle->pkt_size = ureq->actual_len;
+
+ uci_log(UCI_DBG_VERBOSE,
+ "Got pkt of sz 0x%x at adr %pK, ch %d\n",
+ uci_handle->pkt_size,
+ ureq->buf, ureq->chan);
+ } else {
+ uci_handle->pkt_loc = NULL;
+ uci_handle->pkt_size = 0;
+ }
+
+ return ret_val;
+}
+
static int open_client_mhi_channels(struct uci_client *uci_client)
{
int rc = 0;
@@ -431,16 +665,27 @@
uci_client->in_chan);
mutex_lock(&uci_client->out_chan_lock);
mutex_lock(&uci_client->in_chan_lock);
+
+ /* Allocate write requests for async operations */
+ if (!(uci_client->f_flags & O_SYNC)) {
+ rc = mhi_uci_alloc_write_reqs(uci_client);
+ if (rc)
+ goto handle_not_rdy_err;
+ uci_client->send = mhi_uci_send_async;
+ uci_client->read = mhi_uci_read_async;
+ } else {
+ uci_client->send = mhi_uci_send_sync;
+ uci_client->read = mhi_uci_read_sync;
+ }
+
uci_log(UCI_DBG_DBG,
"Initializing inbound chan %d.\n",
uci_client->in_chan);
-
rc = mhi_init_read_chan(uci_client, uci_client->in_chan);
- if (rc < 0) {
+ if (rc < 0)
uci_log(UCI_DBG_ERROR,
"Failed to init inbound 0x%x, ret 0x%x\n",
uci_client->in_chan, rc);
- }
rc = mhi_dev_open_channel(uci_client->out_chan,
&uci_client->out_handle,
@@ -451,7 +696,6 @@
rc = mhi_dev_open_channel(uci_client->in_chan,
&uci_client->in_handle,
uci_ctxt.event_notifier);
-
if (rc < 0) {
uci_log(UCI_DBG_ERROR,
"Failed to open chan %d, ret 0x%x\n",
@@ -506,6 +750,7 @@
return -ENOMEM;
}
uci_handle->uci_ctxt = &uci_ctxt;
+ uci_handle->f_flags = file_handle->f_flags;
if (!atomic_read(&uci_handle->mhi_chans_open)) {
uci_log(UCI_DBG_INFO,
"Opening channels client %d\n",
@@ -540,6 +785,8 @@
if (atomic_read(&uci_handle->mhi_chans_open)) {
atomic_set(&uci_handle->mhi_chans_open, 0);
+ if (!(uci_handle->f_flags & O_SYNC))
+ kfree(uci_handle->wreqs);
mutex_lock(&uci_handle->out_chan_lock);
rc = mhi_dev_close_channel(uci_handle->out_handle);
wake_up(&uci_handle->write_wq);
@@ -675,7 +922,6 @@
struct mutex *mutex;
ssize_t bytes_copied = 0;
u32 addr_offset = 0;
- void *local_buf = NULL;
struct mhi_req ureq;
if (!file || !ubuf || !uspace_buf_size ||
@@ -691,44 +937,19 @@
ureq.client = client_handle;
ureq.buf = uci_handle->in_buf_list[0].addr;
ureq.len = uci_handle->in_buf_list[0].buf_size;
- ureq.mode = IPA_DMA_SYNC;
+
uci_log(UCI_DBG_VERBOSE, "Client attempted read on chan %d\n",
ureq.chan);
do {
if (!uci_handle->pkt_loc &&
- !atomic_read(&uci_ctxt.mhi_disabled)) {
-
- bytes_avail = mhi_dev_read_channel(&ureq);
-
- uci_log(UCI_DBG_VERBOSE,
- "reading from mhi_core local_buf = %p",
- local_buf);
- uci_log(UCI_DBG_VERBOSE,
- "buf_size = 0x%x bytes_read = 0x%x\n",
- ureq.len, bytes_avail);
-
- if (bytes_avail < 0) {
- uci_log(UCI_DBG_ERROR,
- "Failed to read channel ret %d\n",
- bytes_avail);
- ret_val = -EIO;
+ !atomic_read(&uci_ctxt.mhi_disabled)) {
+ ret_val = uci_handle->read(uci_handle, &ureq,
+ &bytes_avail);
+ if (ret_val)
goto error;
- }
-
- if (bytes_avail > 0) {
- uci_handle->pkt_loc = (void *) ureq.buf;
- uci_handle->pkt_size = ureq.actual_len;
-
+ if (bytes_avail > 0)
*bytes_pending = (loff_t)uci_handle->pkt_size;
- uci_log(UCI_DBG_VERBOSE,
- "Got pkt of sz 0x%x at adr %p, ch %d\n",
- uci_handle->pkt_size,
- ureq.buf, ureq.chan);
- } else {
- uci_handle->pkt_loc = 0;
- uci_handle->pkt_size = 0;
- }
}
if (bytes_avail == 0) {
@@ -737,7 +958,10 @@
"No data read_data_ready %d, chan %d\n",
atomic_read(&uci_handle->read_data_ready),
ureq.chan);
-
+ if (uci_handle->f_flags & (O_NONBLOCK | O_NDELAY)) {
+ ret_val = -EAGAIN;
+ goto error;
+ }
ret_val = wait_event_interruptible(uci_handle->read_wq,
(!mhi_dev_channel_isempty(client_handle)));
@@ -841,10 +1065,10 @@
mutex_lock(&uci_handle->out_chan_lock);
while (!ret_val) {
ret_val = mhi_uci_send_packet(&uci_handle->out_handle,
- (void *)buf, count, 1);
+ buf, count);
if (ret_val < 0) {
uci_log(UCI_DBG_ERROR,
- "Error while writing data to MHI, chan %d, buf %p, size %d\n",
+ "Error while writing data to MHI, chan %d, buf %pK, size %d\n",
chan, (void *)buf, count);
ret_val = -EIO;
break;
@@ -854,6 +1078,8 @@
"No descriptors available, did we poll, chan %d?\n",
chan);
mutex_unlock(&uci_handle->out_chan_lock);
+ if (uci_handle->f_flags & (O_NONBLOCK | O_NDELAY))
+ return -EAGAIN;
ret_val = wait_event_interruptible(uci_handle->write_wq,
!mhi_dev_channel_isempty(
uci_handle->out_handle));
@@ -870,31 +1096,6 @@
return ret_val;
}
-static int uci_init_client_attributes(struct mhi_uci_ctxt_t *uci_ctxt)
-{
- u32 i;
- u32 index;
- struct uci_client *client;
- const struct chan_attr *chan_attrib;
-
- for (i = 0; i < ARRAY_SIZE(uci_chan_attr_table); i += 2) {
- chan_attrib = &uci_chan_attr_table[i];
- if (chan_attrib->chan_id == MHI_CLIENT_INVALID)
- break;
- index = CHAN_TO_CLIENT(i);
- client = &uci_ctxt->client_handles[index];
- client->out_chan_attr = chan_attrib;
- client->in_chan_attr = ++chan_attrib;
- client->in_buf_list =
- kcalloc(chan_attrib->nr_trbs,
- sizeof(struct mhi_dev_iov),
- GFP_KERNEL);
- if (!client->in_buf_list)
- return -ENOMEM;
- }
- return 0;
-}
-
void uci_ctrl_update(struct mhi_dev_client_cb_reason *reason)
{
struct uci_ctrl *uci_ctrl_handle = NULL;
@@ -939,12 +1140,11 @@
{
init_waitqueue_head(&mhi_client->read_wq);
init_waitqueue_head(&mhi_client->write_wq);
- mhi_client->out_chan = index * 2 + 1;
- mhi_client->in_chan = index * 2;
mhi_client->client_index = index;
mutex_init(&mhi_client->in_chan_lock);
mutex_init(&mhi_client->out_chan_lock);
+ spin_lock_init(&mhi_client->wr_req_lock);
uci_log(UCI_DBG_DBG, "Registering chan %d.\n", mhi_client->out_chan);
return 0;
@@ -1014,6 +1214,111 @@
#endif
};
+static int uci_device_create(struct uci_client *client)
+{
+ int r;
+ int n;
+ ssize_t dst_size;
+ unsigned int client_index;
+ static char device_name[MAX_DEVICE_NAME_SIZE];
+
+ client_index = CHAN_TO_CLIENT(client->out_chan);
+ if (uci_ctxt.client_handles[client_index].dev)
+ return -EEXIST;
+
+ cdev_init(&uci_ctxt.cdev[client_index], &mhi_uci_client_fops);
+ uci_ctxt.cdev[client_index].owner = THIS_MODULE;
+ r = cdev_add(&uci_ctxt.cdev[client_index],
+ uci_ctxt.start_ctrl_nr + client_index, 1);
+ if (IS_ERR_VALUE(r)) {
+ uci_log(UCI_DBG_ERROR,
+ "Failed to add cdev for client %d, ret 0x%x\n",
+ client_index, r);
+ return r;
+ }
+ if (!client->in_chan_attr->device_name) {
+ n = snprintf(device_name, sizeof(device_name),
+ DEVICE_NAME "_pipe_%d", CLIENT_TO_CHAN(client_index));
+ if (n >= sizeof(device_name)) {
+ uci_log(UCI_DBG_ERROR, "Device name buf too short\n");
+ r = -E2BIG;
+ goto error;
+ }
+ } else {
+ dst_size = strscpy(device_name,
+ client->in_chan_attr->device_name,
+ sizeof(device_name));
+ if (dst_size <= 0) {
+ uci_log(UCI_DBG_ERROR, "Device name buf too short\n");
+ r = dst_size;
+ goto error;
+ }
+ }
+
+ uci_ctxt.client_handles[client_index].dev =
+ device_create(uci_ctxt.mhi_uci_class, NULL,
+ uci_ctxt.start_ctrl_nr + client_index,
+ NULL, device_name);
+ if (IS_ERR(uci_ctxt.client_handles[client_index].dev)) {
+ uci_log(UCI_DBG_ERROR,
+ "Failed to create device for client %d\n",
+ client_index);
+ r = -EIO;
+ goto error;
+ }
+
+ uci_log(UCI_DBG_INFO,
+ "Created device with class 0x%pK and ctrl number %d\n",
+ uci_ctxt.mhi_uci_class,
+ uci_ctxt.start_ctrl_nr + client_index);
+
+ return 0;
+
+error:
+ cdev_del(&uci_ctxt.cdev[client_index]);
+ return r;
+}
+
+static void mhi_uci_client_cb(struct mhi_dev_client_cb_data *cb_data)
+{
+ struct uci_client *client = cb_data->user_data;
+
+ uci_log(UCI_DBG_VERBOSE, " Rcvd MHI cb for channel %d, state %d\n",
+ cb_data->channel, cb_data->ctrl_info);
+
+ if (cb_data->ctrl_info == MHI_STATE_CONNECTED)
+ uci_device_create(client);
+}
+
+static int uci_init_client_attributes(struct mhi_uci_ctxt_t *uci_ctxt)
+{
+ u32 i;
+ u32 index;
+ struct uci_client *client;
+ const struct chan_attr *chan_attrib;
+
+ for (i = 0; i < ARRAY_SIZE(uci_chan_attr_table); i += 2) {
+ chan_attrib = &uci_chan_attr_table[i];
+ index = CHAN_TO_CLIENT(chan_attrib->chan_id);
+ client = &uci_ctxt->client_handles[index];
+ client->out_chan_attr = chan_attrib;
+ client->in_chan_attr = ++chan_attrib;
+ client->in_chan = index * 2;
+ client->out_chan = index * 2 + 1;
+ client->in_buf_list =
+ kcalloc(chan_attrib->nr_trbs,
+ sizeof(struct mhi_dev_iov),
+ GFP_KERNEL);
+ if (!client->in_buf_list)
+ return -ENOMEM;
+ /* Register callback with MHI if requested */
+ if (client->out_chan_attr->register_cb)
+ mhi_register_state_cb(mhi_uci_client_cb, client,
+ client->out_chan);
+ }
+ return 0;
+}
+
int mhi_uci_init(void)
{
u32 i = 0;
@@ -1086,28 +1391,16 @@
mhi_client = &uci_ctxt.client_handles[i];
if (!mhi_client->in_chan_attr)
continue;
- cdev_init(&uci_ctxt.cdev[i], &mhi_uci_client_fops);
- uci_ctxt.cdev[i].owner = THIS_MODULE;
- r = cdev_add(&uci_ctxt.cdev[i],
- uci_ctxt.start_ctrl_nr + i, 1);
- if (IS_ERR_VALUE(r)) {
- uci_log(UCI_DBG_ERROR,
- "Failed to add cdev %d, ret 0x%x\n",
- i, r);
- goto failed_char_add;
- }
-
- uci_ctxt.client_handles[i].dev =
- device_create(uci_ctxt.mhi_uci_class, NULL,
- uci_ctxt.start_ctrl_nr + i,
- NULL, DEVICE_NAME "_pipe_%d",
- i * 2);
- if (IS_ERR(uci_ctxt.client_handles[i].dev)) {
- uci_log(UCI_DBG_ERROR,
- "Failed to add cdev %d\n", i);
- cdev_del(&uci_ctxt.cdev[i]);
+ /*
+ * Delay device node creation until the callback for
+ * this client's channels is called by the MHI driver,
+ * if one is registered.
+ */
+ if (mhi_client->in_chan_attr->register_cb)
+ continue;
+ ret_val = uci_device_create(mhi_client);
+ if (ret_val)
goto failed_device_create;
- }
}
/* Control node */
@@ -1144,7 +1437,6 @@
return 0;
-failed_char_add:
failed_device_create:
while (--i >= 0) {
cdev_del(&uci_ctxt.cdev[i]);
diff --git a/drivers/platform/msm/qcom-geni-se.c b/drivers/platform/msm/qcom-geni-se.c
index ed4b837..267ed8d 100644
--- a/drivers/platform/msm/qcom-geni-se.c
+++ b/drivers/platform/msm/qcom-geni-se.c
@@ -675,9 +675,9 @@
geni_se_dev->cur_ab,
geni_se_dev->cur_ib);
GENI_SE_DBG(geni_se_dev->log_ctx, false, NULL,
- "%s: %lu:%lu (%lu:%lu) %d\n", __func__,
- geni_se_dev->cur_ab, geni_se_dev->cur_ib,
- rsc->ab, rsc->ib, bus_bw_update);
+ "%s: %s: cur_ab_ib(%lu:%lu) req_ab_ib(%lu:%lu) %d\n",
+ __func__, dev_name(rsc->ctrl_dev), geni_se_dev->cur_ab,
+ geni_se_dev->cur_ib, rsc->ab, rsc->ib, bus_bw_update);
mutex_unlock(&geni_se_dev->geni_dev_lock);
return ret;
}
@@ -773,9 +773,9 @@
geni_se_dev->cur_ab,
geni_se_dev->cur_ib);
GENI_SE_DBG(geni_se_dev->log_ctx, false, NULL,
- "%s: %lu:%lu (%lu:%lu) %d\n", __func__,
- geni_se_dev->cur_ab, geni_se_dev->cur_ib,
- rsc->ab, rsc->ib, bus_bw_update);
+ "%s: %s: cur_ab_ib(%lu:%lu) req_ab_ib(%lu:%lu) %d\n",
+ __func__, dev_name(rsc->ctrl_dev), geni_se_dev->cur_ab,
+ geni_se_dev->cur_ib, rsc->ab, rsc->ib, bus_bw_update);
mutex_unlock(&geni_se_dev->geni_dev_lock);
return ret;
}
diff --git a/drivers/platform/msm/sps/sps.c b/drivers/platform/msm/sps/sps.c
index 6e54fbf..05a8c66 100644
--- a/drivers/platform/msm/sps/sps.c
+++ b/drivers/platform/msm/sps/sps.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2018, 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
@@ -1020,8 +1020,6 @@
"sps:%s:BAMs are still registered", __func__);
sps_map_de_init();
-
- kfree(sps);
}
sps_mem_de_init();
@@ -3006,6 +3004,7 @@
.name = SPS_DRV_NAME,
.owner = THIS_MODULE,
.of_match_table = msm_sps_match,
+ .suppress_bind_attrs = true,
},
.remove = msm_sps_remove,
};
diff --git a/drivers/power/reset/msm-poweroff.c b/drivers/power/reset/msm-poweroff.c
index 1a28e56..0b8c212 100644
--- a/drivers/power/reset/msm-poweroff.c
+++ b/drivers/power/reset/msm-poweroff.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2018, 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
@@ -56,8 +56,14 @@
/* Download mode master kill-switch */
static void __iomem *msm_ps_hold;
static phys_addr_t tcsr_boot_misc_detect;
+/* Runtime could be only changed value once.
+ * There is no API from TZ to re-enable the registers.
+ * So the SDI cannot be re-enabled when it already by-passed.
+ */
static int download_mode = 1;
static struct kobject dload_kobj;
+static void scm_disable_sdi(void);
+
#ifdef CONFIG_QCOM_DLOAD_MODE
#define EDL_MODE_PROP "qcom,msm-imem-emergency_download_mode"
@@ -201,7 +207,10 @@
return 0;
}
#else
-#define set_dload_mode(x) do {} while (0)
+static void set_dload_mode(int on)
+{
+ return;
+}
static void enable_emergency_dload_mode(void)
{
@@ -214,6 +223,26 @@
}
#endif
+static void scm_disable_sdi(void)
+{
+ int ret;
+ struct scm_desc desc = {
+ .args[0] = 1,
+ .args[1] = 0,
+ .arginfo = SCM_ARGS(2),
+ };
+
+ /* Needed to bypass debug image on some chips */
+ if (!is_scm_armv8())
+ ret = scm_call_atomic2(SCM_SVC_BOOT,
+ SCM_WDOG_DEBUG_BOOT_PART, 1, 0);
+ else
+ ret = scm_call2_atomic(SCM_SIP_FNID(SCM_SVC_BOOT,
+ SCM_WDOG_DEBUG_BOOT_PART), &desc);
+ if (ret)
+ pr_err("Failed to disable secure wdog debug: %d\n", ret);
+}
+
void msm_set_restart_mode(int mode)
{
restart_mode = mode;
@@ -366,13 +395,6 @@
static void do_msm_restart(enum reboot_mode reboot_mode, const char *cmd)
{
- int ret;
- struct scm_desc desc = {
- .args[0] = 1,
- .args[1] = 0,
- .arginfo = SCM_ARGS(2),
- };
-
pr_notice("Going down for restart now\n");
msm_restart_prepare(cmd);
@@ -387,16 +409,7 @@
msm_trigger_wdog_bite();
#endif
- /* Needed to bypass debug image on some chips */
- if (!is_scm_armv8())
- ret = scm_call_atomic2(SCM_SVC_BOOT,
- SCM_WDOG_DEBUG_BOOT_PART, 1, 0);
- else
- ret = scm_call2_atomic(SCM_SIP_FNID(SCM_SVC_BOOT,
- SCM_WDOG_DEBUG_BOOT_PART), &desc);
- if (ret)
- pr_err("Failed to disable secure wdog debug: %d\n", ret);
-
+ scm_disable_sdi();
halt_spmi_pmic_arbiter();
deassert_ps_hold();
@@ -405,27 +418,11 @@
static void do_msm_poweroff(void)
{
- int ret;
- struct scm_desc desc = {
- .args[0] = 1,
- .args[1] = 0,
- .arginfo = SCM_ARGS(2),
- };
-
pr_notice("Powering off the SoC\n");
-#ifdef CONFIG_QCOM_DLOAD_MODE
+
set_dload_mode(0);
-#endif
+ scm_disable_sdi();
qpnp_pon_system_pwr_off(PON_POWER_OFF_SHUTDOWN);
- /* Needed to bypass debug image on some chips */
- if (!is_scm_armv8())
- ret = scm_call_atomic2(SCM_SVC_BOOT,
- SCM_WDOG_DEBUG_BOOT_PART, 1, 0);
- else
- ret = scm_call2_atomic(SCM_SIP_FNID(SCM_SVC_BOOT,
- SCM_WDOG_DEBUG_BOOT_PART), &desc);
- if (ret)
- pr_err("Failed to disable wdog debug: %d\n", ret);
halt_spmi_pmic_arbiter();
deassert_ps_hold();
@@ -677,6 +674,8 @@
scm_deassert_ps_hold_supported = true;
set_dload_mode(download_mode);
+ if (!download_mode)
+ scm_disable_sdi();
return 0;
diff --git a/drivers/power/supply/power_supply_sysfs.c b/drivers/power/supply/power_supply_sysfs.c
index cd76a09..8281c41 100644
--- a/drivers/power/supply/power_supply_sysfs.c
+++ b/drivers/power/supply/power_supply_sysfs.c
@@ -338,6 +338,7 @@
POWER_SUPPLY_ATTR(esr_actual),
POWER_SUPPLY_ATTR(esr_nominal),
POWER_SUPPLY_ATTR(soh),
+ POWER_SUPPLY_ATTR(qc_opti_disable),
/* Local extensions of type int64_t */
POWER_SUPPLY_ATTR(charge_counter_ext),
/* Properties of type `const char *' */
diff --git a/drivers/power/supply/qcom/battery.c b/drivers/power/supply/qcom/battery.c
index e8d91ae..899cd31 100644
--- a/drivers/power/supply/qcom/battery.c
+++ b/drivers/power/supply/qcom/battery.c
@@ -79,6 +79,7 @@
struct wakeup_source *pl_ws;
struct notifier_block nb;
bool pl_disable;
+ int taper_entry_fv;
};
struct pl_data *the_chip;
@@ -452,6 +453,7 @@
int eff_fcc_ua;
int total_fcc_ua, master_fcc_ua, slave_fcc_ua = 0;
+ chip->taper_entry_fv = get_effective_result(chip->fv_votable);
chip->taper_work_running = true;
while (true) {
if (get_effective_result(chip->pl_disable_votable)) {
@@ -498,7 +500,25 @@
vote(chip->fcc_votable, TAPER_STEPPER_VOTER,
true, eff_fcc_ua);
} else {
- pl_dbg(chip, PR_PARALLEL, "master is fast charging; waiting for next taper\n");
+ /*
+ * Due to reduction of float voltage in JEITA condition
+ * taper charging can be initiated at a lower FV. On
+ * removal of JEITA condition, FV readjusts itself.
+ * However, once taper charging is initiated, it doesn't
+ * exits until parallel chaging is disabled due to which
+ * FCC doesn't scale back to its original value, leading
+ * to slow charging thereafter.
+ * Check if FV increases in comparison to FV at which
+ * taper charging was initiated, and if yes, exit taper
+ * charging.
+ */
+ if (get_effective_result(chip->fv_votable) >
+ chip->taper_entry_fv) {
+ pl_dbg(chip, PR_PARALLEL, "Float voltage increased. Exiting taper\n");
+ goto done;
+ } else {
+ pl_dbg(chip, PR_PARALLEL, "master is fast charging; waiting for next taper\n");
+ }
}
/* wait for the charger state to deglitch after FCC change */
msleep(PL_TAPER_WORK_DELAY_MS);
@@ -997,6 +1017,16 @@
/* handle fast/taper charge entry */
if (pval.intval == POWER_SUPPLY_CHARGE_TYPE_TAPER
|| pval.intval == POWER_SUPPLY_CHARGE_TYPE_FAST) {
+ /*
+ * Undo parallel charging termination if entered taper in
+ * reduced float voltage condition due to jeita mitigation.
+ */
+ if (pval.intval == POWER_SUPPLY_CHARGE_TYPE_FAST &&
+ (chip->taper_entry_fv <
+ get_effective_result(chip->fv_votable))) {
+ vote(chip->pl_disable_votable, TAPER_END_VOTER,
+ false, 0);
+ }
pl_dbg(chip, PR_PARALLEL, "chg_state enabling parallel\n");
vote(chip->pl_disable_votable, CHG_STATE_VOTER, false, 0);
chip->charge_type = pval.intval;
diff --git a/drivers/power/supply/qcom/fg-alg.c b/drivers/power/supply/qcom/fg-alg.c
index 4003679..f3f2c66 100644
--- a/drivers/power/supply/qcom/fg-alg.c
+++ b/drivers/power/supply/qcom/fg-alg.c
@@ -803,9 +803,31 @@
i, soc_per_step, msoc_this_step, msoc_next_step,
ibatt_this_step, t_predicted_this_step, ttf_slope,
t_predicted_cv, t_predicted = 0, charge_type = 0,
- float_volt_uv = 0;
+ float_volt_uv = 0, valid = 0, charge_status = 0;
s64 delta_ms;
+ rc = ttf->get_ttf_param(ttf->data, TTF_VALID, &valid);
+ if (rc < 0) {
+ pr_err("failed to get ttf_valid rc=%d\n", rc);
+ return rc;
+ }
+
+ if (!valid) {
+ *val = -EINVAL;
+ return 0;
+ }
+
+ rc = ttf->get_ttf_param(ttf->data, TTF_CHG_STATUS, &charge_status);
+ if (rc < 0) {
+ pr_err("failed to get charge-status rc=%d\n", rc);
+ return rc;
+ }
+
+ if (charge_status != POWER_SUPPLY_STATUS_CHARGING) {
+ *val = -EINVAL;
+ return 0;
+ }
+
rc = ttf->get_ttf_param(ttf->data, TTF_MSOC, &msoc);
if (rc < 0) {
pr_err("failed to get msoc rc=%d\n", rc);
@@ -1103,7 +1125,30 @@
*/
int ttf_get_time_to_empty(struct ttf *ttf, int *val)
{
- int rc, ibatt_avg, msoc, act_cap_mah, divisor;
+ int rc, ibatt_avg, msoc, act_cap_mah, divisor, valid = 0,
+ charge_status = 0;
+
+ rc = ttf->get_ttf_param(ttf->data, TTF_VALID, &valid);
+ if (rc < 0) {
+ pr_err("failed to get ttf_valid rc=%d\n", rc);
+ return rc;
+ }
+
+ if (!valid) {
+ *val = -EINVAL;
+ return 0;
+ }
+
+ rc = ttf->get_ttf_param(ttf->data, TTF_CHG_STATUS, &charge_status);
+ if (rc < 0) {
+ pr_err("failed to get charge-status rc=%d\n", rc);
+ return rc;
+ }
+
+ if (charge_status == POWER_SUPPLY_STATUS_CHARGING) {
+ *val = -EINVAL;
+ return 0;
+ }
rc = ttf_circ_buf_median(&ttf->ibatt, &ibatt_avg);
if (rc < 0) {
@@ -1136,6 +1181,10 @@
divisor = ibatt_avg * divisor / 100;
divisor = max(100, divisor);
*val = act_cap_mah * msoc * HOURS_TO_SECONDS / divisor;
+
+ pr_debug("TTF: ibatt_avg=%d msoc=%d act_cap_mah=%d TTE=%d\n",
+ ibatt_avg, msoc, act_cap_mah, *val);
+
return 0;
}
diff --git a/drivers/power/supply/qcom/fg-alg.h b/drivers/power/supply/qcom/fg-alg.h
index 70183ba..22e9c2b 100644
--- a/drivers/power/supply/qcom/fg-alg.h
+++ b/drivers/power/supply/qcom/fg-alg.h
@@ -76,6 +76,7 @@
TTF_VFLOAT,
TTF_CHG_TYPE,
TTF_CHG_STATUS,
+ TTF_VALID,
};
struct ttf_circ_buf {
diff --git a/drivers/power/supply/qcom/fg-core.h b/drivers/power/supply/qcom/fg-core.h
index f73e647..09c3640 100644
--- a/drivers/power/supply/qcom/fg-core.h
+++ b/drivers/power/supply/qcom/fg-core.h
@@ -311,10 +311,10 @@
int esr_meas_curr_ma;
int bmd_en_delay_ms;
int ki_coeff_full_soc_dischg;
- int ki_coeff_low_dischg;
int ki_coeff_hi_chg;
int jeita_thresholds[NUM_JEITA_LEVELS];
int ki_coeff_soc[KI_COEFF_SOC_LEVELS];
+ int ki_coeff_low_dischg[KI_COEFF_SOC_LEVELS];
int ki_coeff_med_dischg[KI_COEFF_SOC_LEVELS];
int ki_coeff_hi_dischg[KI_COEFF_SOC_LEVELS];
int slope_limit_coeffs[SLOPE_LIMIT_NUM_COEFFS];
@@ -335,7 +335,7 @@
bool started[BUCKET_COUNT];
u16 count[BUCKET_COUNT];
u8 last_soc[BUCKET_COUNT];
- int id;
+ char counter[BUCKET_COUNT * 8];
struct mutex lock;
};
diff --git a/drivers/power/supply/qcom/qg-core.h b/drivers/power/supply/qcom/qg-core.h
index f21b2a8..91279c0 100644
--- a/drivers/power/supply/qcom/qg-core.h
+++ b/drivers/power/supply/qcom/qg-core.h
@@ -54,6 +54,7 @@
int esr_qual_i_ua;
int esr_qual_v_uv;
int esr_disable_soc;
+ int esr_min_ibat_ua;
bool hold_soc_while_full;
bool linearize_soc;
bool cl_disable;
@@ -142,6 +143,8 @@
int batt_soc;
int cc_soc;
int full_soc;
+ int sys_soc;
+ int last_adj_ssoc;
struct alarm alarm_timer;
u32 sdam_data[SDAM_MAX];
diff --git a/drivers/power/supply/qcom/qg-reg.h b/drivers/power/supply/qcom/qg-reg.h
index e0f400d..894e076 100644
--- a/drivers/power/supply/qcom/qg-reg.h
+++ b/drivers/power/supply/qcom/qg-reg.h
@@ -41,6 +41,9 @@
#define QG_DATA_CTL1_REG 0x41
#define MASTER_HOLD_OR_CLR_BIT BIT(0)
+#define QG_DATA_CTL2_REG 0x42
+#define BURST_AVG_HOLD_FOR_READ_BIT BIT(0)
+
#define QG_MODE_CTL1_REG 0x43
#define PARALLEL_IBAT_SENSE_EN_BIT BIT(7)
@@ -97,6 +100,8 @@
#define QG_LAST_ADC_V_DATA0_REG 0xC0
#define QG_LAST_ADC_I_DATA0_REG 0xC2
+#define QG_LAST_BURST_AVG_I_DATA0_REG 0xC6
+
#define QG_LAST_S3_SLEEP_V_DATA0_REG 0xCC
/* SDAM offsets */
diff --git a/drivers/power/supply/qcom/qg-soc.c b/drivers/power/supply/qcom/qg-soc.c
index af8b158..12e19a5 100644
--- a/drivers/power/supply/qcom/qg-soc.c
+++ b/drivers/power/supply/qcom/qg-soc.c
@@ -17,15 +17,19 @@
#include <linux/module.h>
#include <linux/power_supply.h>
#include <uapi/linux/qg.h>
+#include <uapi/linux/qg-profile.h>
#include "fg-alg.h"
#include "qg-sdam.h"
#include "qg-core.h"
#include "qg-reg.h"
#include "qg-util.h"
#include "qg-defs.h"
+#include "qg-soc.h"
#define DEFAULT_UPDATE_TIME_MS 64000
#define SOC_SCALE_HYST_MS 2000
+#define VBAT_LOW_HYST_UV 50000
+#define FULL_SOC 100
static int qg_delta_soc_interval_ms = 20000;
module_param_named(
@@ -37,6 +41,39 @@
soc_cold_interval_ms, qg_delta_soc_cold_interval_ms, int, 0600
);
+int qg_adjust_sys_soc(struct qpnp_qg *chip)
+{
+ int soc, vbat_uv, rc;
+ int vcutoff_uv = chip->dt.vbatt_cutoff_mv * 1000;
+
+ chip->sys_soc = CAP(QG_MIN_SOC, QG_MAX_SOC, chip->sys_soc);
+
+ if (chip->sys_soc == QG_MIN_SOC) {
+ /* Hold SOC to 1% of VBAT has not dropped below cutoff */
+ rc = qg_get_battery_voltage(chip, &vbat_uv);
+ if (!rc && vbat_uv >= (vcutoff_uv + VBAT_LOW_HYST_UV))
+ soc = 1;
+ else
+ soc = 0;
+ } else if (chip->sys_soc == QG_MAX_SOC) {
+ soc = FULL_SOC;
+ } else if (chip->sys_soc >= (QG_MAX_SOC - 100)) {
+ /* Hold SOC to 100% if we are dropping from 100 to 99 */
+ if (chip->last_adj_ssoc == FULL_SOC)
+ soc = FULL_SOC;
+ else /* Hold SOC at 99% until we hit 100% */
+ soc = FULL_SOC - 1;
+ } else {
+ soc = DIV_ROUND_CLOSEST(chip->sys_soc, 100);
+ }
+
+ qg_dbg(chip, QG_DEBUG_SOC, "last_adj_sys_soc=%d adj_sys_soc=%d\n",
+ chip->last_adj_ssoc, soc);
+ chip->last_adj_ssoc = soc;
+
+ return soc;
+}
+
static void get_next_update_time(struct qpnp_qg *chip)
{
int soc_points = 0, batt_temp = 0;
diff --git a/drivers/power/supply/qcom/qg-soc.h b/drivers/power/supply/qcom/qg-soc.h
index 3b4eb60..cd64bd5 100644
--- a/drivers/power/supply/qcom/qg-soc.h
+++ b/drivers/power/supply/qcom/qg-soc.h
@@ -16,5 +16,6 @@
int qg_scale_soc(struct qpnp_qg *chip, bool force_soc);
int qg_soc_init(struct qpnp_qg *chip);
void qg_soc_exit(struct qpnp_qg *chip);
+int qg_adjust_sys_soc(struct qpnp_qg *chip);
#endif /* __QG_SOC_H__ */
diff --git a/drivers/power/supply/qcom/qg-util.c b/drivers/power/supply/qcom/qg-util.c
index 824d914..a3e045e 100644
--- a/drivers/power/supply/qcom/qg-util.c
+++ b/drivers/power/supply/qcom/qg-util.c
@@ -332,3 +332,60 @@
return rc;
}
+
+int qg_get_battery_current(struct qpnp_qg *chip, int *ibat_ua)
+{
+ int rc = 0, last_ibat = 0;
+
+ if (chip->battery_missing) {
+ *ibat_ua = 0;
+ return 0;
+ }
+
+ /* hold data */
+ rc = qg_masked_write(chip, chip->qg_base + QG_DATA_CTL2_REG,
+ BURST_AVG_HOLD_FOR_READ_BIT,
+ BURST_AVG_HOLD_FOR_READ_BIT);
+ if (rc < 0) {
+ pr_err("Failed to hold burst-avg data rc=%d\n", rc);
+ goto release;
+ }
+
+ rc = qg_read(chip, chip->qg_base + QG_LAST_BURST_AVG_I_DATA0_REG,
+ (u8 *)&last_ibat, 2);
+ if (rc < 0) {
+ pr_err("Failed to read LAST_BURST_AVG_I reg, rc=%d\n", rc);
+ goto release;
+ }
+
+ last_ibat = sign_extend32(last_ibat, 15);
+ *ibat_ua = I_RAW_TO_UA(last_ibat);
+
+release:
+ /* release */
+ qg_masked_write(chip, chip->qg_base + QG_DATA_CTL2_REG,
+ BURST_AVG_HOLD_FOR_READ_BIT, 0);
+ return rc;
+}
+
+int qg_get_battery_voltage(struct qpnp_qg *chip, int *vbat_uv)
+{
+ int rc = 0;
+ u64 last_vbat = 0;
+
+ if (chip->battery_missing) {
+ *vbat_uv = 3700000;
+ return 0;
+ }
+
+ rc = qg_read(chip, chip->qg_base + QG_LAST_ADC_V_DATA0_REG,
+ (u8 *)&last_vbat, 2);
+ if (rc < 0) {
+ pr_err("Failed to read LAST_ADV_V reg, rc=%d\n", rc);
+ return rc;
+ }
+
+ *vbat_uv = V_RAW_TO_UV(last_vbat);
+
+ return rc;
+}
diff --git a/drivers/power/supply/qcom/qg-util.h b/drivers/power/supply/qcom/qg-util.h
index bb17afb..5dd6c85 100644
--- a/drivers/power/supply/qcom/qg-util.h
+++ b/drivers/power/supply/qcom/qg-util.h
@@ -25,5 +25,7 @@
bool is_parallel_enabled(struct qpnp_qg *chip);
int qg_write_monotonic_soc(struct qpnp_qg *chip, int msoc);
int qg_get_battery_temp(struct qpnp_qg *chip, int *batt_temp);
+int qg_get_battery_current(struct qpnp_qg *chip, int *ibat_ua);
+int qg_get_battery_voltage(struct qpnp_qg *chip, int *vbat_uv);
#endif
diff --git a/drivers/power/supply/qcom/qpnp-fg-gen3.c b/drivers/power/supply/qcom/qpnp-fg-gen3.c
index eaf138c..36521a1 100644
--- a/drivers/power/supply/qcom/qpnp-fg-gen3.c
+++ b/drivers/power/supply/qcom/qpnp-fg-gen3.c
@@ -1653,11 +1653,13 @@
mutex_unlock(&chip->cl.lock);
}
+#define KI_COEFF_LOW_DISCHG_DEFAULT 800
#define KI_COEFF_MED_DISCHG_DEFAULT 1500
#define KI_COEFF_HI_DISCHG_DEFAULT 2200
static int fg_adjust_ki_coeff_dischg(struct fg_chip *chip)
{
int rc, i, msoc;
+ int ki_coeff_low = KI_COEFF_LOW_DISCHG_DEFAULT;
int ki_coeff_med = KI_COEFF_MED_DISCHG_DEFAULT;
int ki_coeff_hi = KI_COEFF_HI_DISCHG_DEFAULT;
u8 val;
@@ -1674,12 +1676,24 @@
if (chip->charge_status == POWER_SUPPLY_STATUS_DISCHARGING) {
for (i = KI_COEFF_SOC_LEVELS - 1; i >= 0; i--) {
if (msoc < chip->dt.ki_coeff_soc[i]) {
+ ki_coeff_low = chip->dt.ki_coeff_low_dischg[i];
ki_coeff_med = chip->dt.ki_coeff_med_dischg[i];
ki_coeff_hi = chip->dt.ki_coeff_hi_dischg[i];
}
}
}
+ fg_encode(chip->sp, FG_SRAM_KI_COEFF_LOW_DISCHG, ki_coeff_low, &val);
+ rc = fg_sram_write(chip,
+ chip->sp[FG_SRAM_KI_COEFF_LOW_DISCHG].addr_word,
+ chip->sp[FG_SRAM_KI_COEFF_LOW_DISCHG].addr_byte, &val,
+ chip->sp[FG_SRAM_KI_COEFF_LOW_DISCHG].len,
+ FG_IMA_DEFAULT);
+ if (rc < 0) {
+ pr_err("Error in writing ki_coeff_low, rc=%d\n", rc);
+ return rc;
+ }
+
fg_encode(chip->sp, FG_SRAM_KI_COEFF_MED_DISCHG, ki_coeff_med, &val);
rc = fg_sram_write(chip,
chip->sp[FG_SRAM_KI_COEFF_MED_DISCHG].addr_word,
@@ -1702,8 +1716,8 @@
return rc;
}
- fg_dbg(chip, FG_STATUS, "Wrote ki_coeff_med %d ki_coeff_hi %d\n",
- ki_coeff_med, ki_coeff_hi);
+ fg_dbg(chip, FG_STATUS, "Wrote ki_coeff_low %d ki_coeff_med %d ki_coeff_hi %d\n",
+ ki_coeff_low, ki_coeff_med, ki_coeff_hi);
return 0;
}
@@ -2707,20 +2721,29 @@
mutex_unlock(&chip->cyc_ctr.lock);
}
-static int fg_get_cycle_count(struct fg_chip *chip)
+static const char *fg_get_cycle_count(struct fg_chip *chip)
{
- int count;
+ int i, len = 0;
+ char *buf;
if (!chip->cyc_ctr.en)
- return 0;
+ return NULL;
- if ((chip->cyc_ctr.id <= 0) || (chip->cyc_ctr.id > BUCKET_COUNT))
- return -EINVAL;
-
+ buf = chip->cyc_ctr.counter;
mutex_lock(&chip->cyc_ctr.lock);
- count = chip->cyc_ctr.count[chip->cyc_ctr.id - 1];
+ for (i = 0; i < BUCKET_COUNT; i++) {
+ if (sizeof(chip->cyc_ctr.counter) - len < 8) {
+ pr_err("Invalid length %d\n", len);
+ mutex_unlock(&chip->cyc_ctr.lock);
+ return NULL;
+ }
+
+ len += snprintf(buf+len, 8, "%d ", chip->cyc_ctr.count[i]);
+ }
mutex_unlock(&chip->cyc_ctr.lock);
- return count;
+
+ buf[len] = '\0';
+ return buf;
}
static void status_change_work(struct work_struct *work)
@@ -3847,11 +3870,8 @@
case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
pval->intval = chip->bp.float_volt_uv;
break;
- case POWER_SUPPLY_PROP_CYCLE_COUNT:
- pval->intval = fg_get_cycle_count(chip);
- break;
- case POWER_SUPPLY_PROP_CYCLE_COUNT_ID:
- pval->intval = chip->cyc_ctr.id;
+ case POWER_SUPPLY_PROP_CYCLE_COUNTS:
+ pval->strval = fg_get_cycle_count(chip);
break;
case POWER_SUPPLY_PROP_CHARGE_NOW_RAW:
rc = fg_get_charge_raw(chip, &pval->intval);
@@ -3917,15 +3937,6 @@
int rc = 0;
switch (psp) {
- case POWER_SUPPLY_PROP_CYCLE_COUNT_ID:
- if ((pval->intval > 0) && (pval->intval <= BUCKET_COUNT)) {
- chip->cyc_ctr.id = pval->intval;
- } else {
- pr_err("rejecting invalid cycle_count_id = %d\n",
- pval->intval);
- return -EINVAL;
- }
- break;
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
rc = fg_set_constant_chg_voltage(chip, pval->intval);
break;
@@ -4008,7 +4019,6 @@
enum power_supply_property psp)
{
switch (psp) {
- case POWER_SUPPLY_PROP_CYCLE_COUNT_ID:
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
case POWER_SUPPLY_PROP_CC_STEP:
case POWER_SUPPLY_PROP_CC_STEP_SEL:
@@ -4080,8 +4090,7 @@
POWER_SUPPLY_PROP_BATTERY_TYPE,
POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
- POWER_SUPPLY_PROP_CYCLE_COUNT,
- POWER_SUPPLY_PROP_CYCLE_COUNT_ID,
+ POWER_SUPPLY_PROP_CYCLE_COUNTS,
POWER_SUPPLY_PROP_CHARGE_NOW_RAW,
POWER_SUPPLY_PROP_CHARGE_NOW,
POWER_SUPPLY_PROP_CHARGE_FULL,
@@ -4382,21 +4391,6 @@
}
}
- if (chip->dt.ki_coeff_low_dischg != -EINVAL) {
- fg_encode(chip->sp, FG_SRAM_KI_COEFF_LOW_DISCHG,
- chip->dt.ki_coeff_low_dischg, &val);
- rc = fg_sram_write(chip,
- chip->sp[FG_SRAM_KI_COEFF_LOW_DISCHG].addr_word,
- chip->sp[FG_SRAM_KI_COEFF_LOW_DISCHG].addr_byte,
- &val, chip->sp[FG_SRAM_KI_COEFF_LOW_DISCHG].len,
- FG_IMA_DEFAULT);
- if (rc < 0) {
- pr_err("Error in writing ki_coeff_low_dischg, rc=%d\n",
- rc);
- return rc;
- }
- }
-
if (chip->dt.ki_coeff_hi_chg != -EINVAL) {
fg_encode(chip->sp, FG_SRAM_KI_COEFF_HI_CHG,
chip->dt.ki_coeff_hi_chg, &val);
@@ -4878,16 +4872,22 @@
if (!rc)
chip->dt.ki_coeff_hi_chg = temp;
- chip->dt.ki_coeff_low_dischg = -EINVAL;
- rc = of_property_read_u32(node, "qcom,ki-coeff-low-dischg", &temp);
- if (!rc)
- chip->dt.ki_coeff_low_dischg = temp;
+ if (!of_find_property(node, "qcom,ki-coeff-soc-dischg", NULL) ||
+ (!of_find_property(node, "qcom,ki-coeff-low-dischg", NULL) &&
+ !of_find_property(node, "qcom,ki-coeff-med-dischg", NULL) &&
+ !of_find_property(node, "qcom,ki-coeff-hi-dischg", NULL)))
+ return 0;
rc = fg_parse_dt_property_u32_array(node, "qcom,ki-coeff-soc-dischg",
chip->dt.ki_coeff_soc, KI_COEFF_SOC_LEVELS);
if (rc < 0)
return rc;
+ rc = fg_parse_dt_property_u32_array(node, "qcom,ki-coeff-low-dischg",
+ chip->dt.ki_coeff_low_dischg, KI_COEFF_SOC_LEVELS);
+ if (rc < 0)
+ return rc;
+
rc = fg_parse_dt_property_u32_array(node, "qcom,ki-coeff-med-dischg",
chip->dt.ki_coeff_med_dischg, KI_COEFF_SOC_LEVELS);
if (rc < 0)
@@ -4905,9 +4905,9 @@
return -EINVAL;
}
- if (chip->dt.ki_coeff_med_dischg[i] < 0 ||
- chip->dt.ki_coeff_med_dischg[i] > KI_COEFF_MAX) {
- pr_err("Error in ki_coeff_med_dischg values\n");
+ if (chip->dt.ki_coeff_low_dischg[i] < 0 ||
+ chip->dt.ki_coeff_low_dischg[i] > KI_COEFF_MAX) {
+ pr_err("Error in ki_coeff_low_dischg values\n");
return -EINVAL;
}
@@ -4916,6 +4916,12 @@
pr_err("Error in ki_coeff_med_dischg values\n");
return -EINVAL;
}
+
+ if (chip->dt.ki_coeff_hi_dischg[i] < 0 ||
+ chip->dt.ki_coeff_hi_dischg[i] > KI_COEFF_MAX) {
+ pr_err("Error in ki_coeff_hi_dischg values\n");
+ return -EINVAL;
+ }
}
chip->ki_coeff_dischg_en = true;
return 0;
@@ -5175,8 +5181,6 @@
}
chip->cyc_ctr.en = of_property_read_bool(node, "qcom,cycle-counter-en");
- if (chip->cyc_ctr.en)
- chip->cyc_ctr.id = 1;
chip->dt.force_load_profile = of_property_read_bool(node,
"qcom,fg-force-load-profile");
diff --git a/drivers/power/supply/qcom/qpnp-qg.c b/drivers/power/supply/qcom/qpnp-qg.c
index e86d2af..39869c1 100644
--- a/drivers/power/supply/qcom/qpnp-qg.c
+++ b/drivers/power/supply/qcom/qpnp-qg.c
@@ -45,12 +45,12 @@
debug_mask, qg_debug_mask, int, 0600
);
-static int qg_esr_mod_count = 10;
+static int qg_esr_mod_count = 30;
module_param_named(
esr_mod_count, qg_esr_mod_count, int, 0600
);
-static int qg_esr_count = 5;
+static int qg_esr_count = 3;
module_param_named(
esr_count, qg_esr_count, int, 0600
);
@@ -452,13 +452,11 @@
}
#define MIN_FIFO_FULL_TIME_MS 12000
-static int process_rt_fifo_data(struct qpnp_qg *chip,
- bool update_vbat_low, bool update_smb)
+static int process_rt_fifo_data(struct qpnp_qg *chip, bool update_smb)
{
int rc = 0;
ktime_t now = ktime_get();
s64 time_delta;
- u8 fifo_length;
/*
* Reject the FIFO read event if there are back-to-back requests
@@ -467,11 +465,10 @@
*/
time_delta = ktime_ms_delta(now, chip->last_user_update_time);
- qg_dbg(chip, QG_DEBUG_FIFO, "time_delta=%lld ms update_vbat_low=%d update_smb=%d\n",
- time_delta, update_vbat_low, update_smb);
+ qg_dbg(chip, QG_DEBUG_FIFO, "time_delta=%lld ms update_smb=%d\n",
+ time_delta, update_smb);
- if (time_delta > MIN_FIFO_FULL_TIME_MS || update_vbat_low
- || update_smb) {
+ if (time_delta > MIN_FIFO_FULL_TIME_MS || update_smb) {
rc = qg_master_hold(chip, true);
if (rc < 0) {
pr_err("Failed to hold master, rc=%d\n", rc);
@@ -484,20 +481,6 @@
goto done;
}
- if (update_vbat_low) {
- /* change FIFO length */
- fifo_length = chip->vbat_low ?
- chip->dt.s2_vbat_low_fifo_length :
- chip->dt.s2_fifo_length;
- rc = qg_update_fifo_length(chip, fifo_length);
- if (rc < 0)
- goto done;
-
- qg_dbg(chip, QG_DEBUG_STATUS,
- "FIFO length updated to %d vbat_low=%d\n",
- fifo_length, chip->vbat_low);
- }
-
if (update_smb) {
rc = qg_masked_write(chip, chip->qg_base +
QG_MODE_CTL1_REG, PARALLEL_IBAT_SENSE_EN_BIT,
@@ -539,60 +522,67 @@
static int qg_vbat_low_wa(struct qpnp_qg *chip)
{
int rc, i, temp = 0;
- u32 vbat_low_uv = 0;
+ u32 vbat_low_uv = 0, fifo_length = 0;
- rc = qg_get_battery_temp(chip, &temp);
- if (rc < 0) {
- pr_err("Failed to read batt_temp rc=%d\n", rc);
- temp = 250;
- }
+ if ((chip->wa_flags & QG_VBAT_LOW_WA) && chip->vbat_low) {
+ rc = qg_get_battery_temp(chip, &temp);
+ if (rc < 0) {
+ pr_err("Failed to read batt_temp rc=%d\n", rc);
+ temp = 250;
+ }
- vbat_low_uv = 1000 * ((temp < chip->dt.cold_temp_threshold) ?
- chip->dt.vbatt_low_cold_mv :
- chip->dt.vbatt_low_mv);
- vbat_low_uv += VBAT_LOW_HYST_UV;
-
- if (!(chip->wa_flags & QG_VBAT_LOW_WA) || !chip->vbat_low)
- return 0;
-
- /*
- * PMI632 1.0 does not generate a falling VBAT_LOW IRQ.
- * To exit from VBAT_LOW config, check if any of the FIFO
- * averages is > vbat_low threshold and reconfigure the
- * FIFO length to normal.
- */
- for (i = 0; i < chip->kdata.fifo_length; i++) {
- if (chip->kdata.fifo[i].v > vbat_low_uv) {
- rc = qg_master_hold(chip, true);
- if (rc < 0) {
- pr_err("Failed to hold master, rc=%d\n", rc);
- goto done;
- }
- rc = qg_update_fifo_length(chip,
- chip->dt.s2_fifo_length);
- if (rc < 0)
- goto done;
-
- rc = qg_master_hold(chip, false);
- if (rc < 0) {
- pr_err("Failed to release master, rc=%d\n", rc);
- goto done;
- }
- /* FIFOs restarted */
- chip->last_fifo_update_time = ktime_get();
-
- chip->vbat_low = false;
- pr_info("Exit VBAT_LOW vbat_avg=%duV vbat_low=%duV updated fifo_length=%d\n",
+ vbat_low_uv = 1000 * ((temp < chip->dt.cold_temp_threshold) ?
+ chip->dt.vbatt_low_cold_mv :
+ chip->dt.vbatt_low_mv);
+ vbat_low_uv += VBAT_LOW_HYST_UV;
+ /*
+ * PMI632 1.0 does not generate a falling VBAT_LOW IRQ.
+ * To exit from VBAT_LOW config, check if any of the FIFO
+ * averages is > vbat_low threshold and reconfigure the
+ * FIFO length to normal.
+ */
+ for (i = 0; i < chip->kdata.fifo_length; i++) {
+ if (chip->kdata.fifo[i].v > vbat_low_uv) {
+ chip->vbat_low = false;
+ pr_info("Exit VBAT_LOW vbat_avg=%duV vbat_low=%duV updated fifo_length=%d\n",
chip->kdata.fifo[i].v, vbat_low_uv,
chip->dt.s2_fifo_length);
- break;
+ break;
+ }
}
}
- return 0;
+ rc = get_fifo_length(chip, &fifo_length, false);
+ if (rc < 0) {
+ pr_err("Failed to get FIFO length, rc=%d\n", rc);
+ return rc;
+ }
+ if (chip->vbat_low && fifo_length == chip->dt.s2_vbat_low_fifo_length)
+ return 0;
+
+ if (!chip->vbat_low && fifo_length == chip->dt.s2_fifo_length)
+ return 0;
+
+ rc = qg_master_hold(chip, true);
+ if (rc < 0) {
+ pr_err("Failed to hold master, rc=%d\n", rc);
+ goto done;
+ }
+
+ fifo_length = chip->vbat_low ? chip->dt.s2_vbat_low_fifo_length :
+ chip->dt.s2_fifo_length;
+
+ rc = qg_update_fifo_length(chip, fifo_length);
+ if (rc < 0)
+ goto done;
+
+ qg_dbg(chip, QG_DEBUG_STATUS, "FIFO length updated to %d vbat_low=%d\n",
+ fifo_length, chip->vbat_low);
done:
qg_master_hold(chip, false);
+ /* FIFOs restarted */
+ chip->last_fifo_update_time = ktime_get();
return rc;
}
@@ -854,7 +844,7 @@
static int qg_esr_estimate(struct qpnp_qg *chip)
{
- int rc, i, ibat;
+ int rc, i, ibat = 0;
u8 esr_done_count, reg0 = 0, reg1 = 0;
bool is_charging = false;
@@ -862,13 +852,17 @@
return 0;
/*
- * Charge - enable ESR estimation only during fast-charging.
+ * Charge - enable ESR estimation if IBAT > MIN_IBAT.
* Discharge - enable ESR estimation only if enabled via DT.
*/
+ rc = qg_get_battery_current(chip, &ibat);
+ if (rc < 0)
+ return rc;
if (chip->charge_status == POWER_SUPPLY_STATUS_CHARGING &&
- chip->charge_type != POWER_SUPPLY_CHARGE_TYPE_FAST) {
+ ibat > chip->dt.esr_min_ibat_ua) {
qg_dbg(chip, QG_DEBUG_ESR,
- "Skip ESR, Not in fast-charge (CC)\n");
+ "Skip CHG ESR, Fails IBAT ibat(%d) min_ibat(%d)\n",
+ ibat, chip->dt.esr_min_ibat_ua);
return 0;
}
@@ -1002,6 +996,8 @@
pr_err("Failed to release master, rc=%d\n", rc);
goto done;
}
+ /* FIFOs restarted */
+ chip->last_fifo_update_time = ktime_get();
if (chip->esr_avg) {
chip->kdata.param[QG_ESR].data = chip->esr_avg;
@@ -1033,11 +1029,23 @@
if (chip->udata.param[QG_FULL_SOC].valid)
chip->full_soc = chip->udata.param[QG_FULL_SOC].data;
- if (chip->udata.param[QG_SOC].valid) {
- qg_dbg(chip, QG_DEBUG_SOC, "udata SOC=%d last SOC=%d\n",
- chip->udata.param[QG_SOC].data, chip->catch_up_soc);
+ if (chip->udata.param[QG_SOC].valid ||
+ chip->udata.param[QG_SYS_SOC].valid) {
- chip->catch_up_soc = chip->udata.param[QG_SOC].data;
+ qg_dbg(chip, QG_DEBUG_SOC, "udata update: QG_SOC=%d QG_SYS_SOC=%d last_catchup_soc=%d\n",
+ chip->udata.param[QG_SOC].valid ?
+ chip->udata.param[QG_SOC].data : -EINVAL,
+ chip->udata.param[QG_SYS_SOC].valid ?
+ chip->udata.param[QG_SYS_SOC].data : -EINVAL,
+ chip->catch_up_soc);
+
+ if (chip->udata.param[QG_SYS_SOC].valid) {
+ chip->sys_soc = chip->udata.param[QG_SYS_SOC].data;
+ chip->catch_up_soc = qg_adjust_sys_soc(chip);
+ } else {
+ chip->catch_up_soc = chip->udata.param[QG_SOC].data;
+ }
+
qg_scale_soc(chip, false);
/* update parameters to SDAM */
@@ -1168,10 +1176,6 @@
chip->vbat_low = !!(status & VBAT_LOW_INT_RT_STS_BIT);
- rc = process_rt_fifo_data(chip, true, false);
- if (rc < 0)
- pr_err("Failed to process RT FIFO data, rc=%d\n", rc);
-
qg_dbg(chip, QG_DEBUG_IRQ, "VBAT_LOW = %d\n", chip->vbat_low);
done:
mutex_unlock(&chip->data_lock);
@@ -1508,69 +1512,6 @@
return DEFAULT_BATT_TYPE;
}
-static int qg_get_battery_current(struct qpnp_qg *chip, int *ibat_ua)
-{
- int rc = 0, last_ibat = 0;
- u32 fifo_length = 0;
-
- if (chip->battery_missing) {
- *ibat_ua = 0;
- return 0;
- }
-
- if (chip->parallel_enabled) {
- /* read the last real-time FIFO */
- rc = get_fifo_length(chip, &fifo_length, true);
- if (rc < 0) {
- pr_err("Failed to read RT FIFO length, rc=%d\n", rc);
- return rc;
- }
- fifo_length = (fifo_length == 0) ? 0 : fifo_length - 1;
- fifo_length *= 2;
- rc = qg_read(chip, chip->qg_base + QG_I_FIFO0_DATA0_REG +
- fifo_length, (u8 *)&last_ibat, 2);
- if (rc < 0) {
- pr_err("Failed to read FIFO_I_%d reg, rc=%d\n",
- fifo_length / 2, rc);
- return rc;
- }
- } else {
- rc = qg_read(chip, chip->qg_base + QG_LAST_ADC_I_DATA0_REG,
- (u8 *)&last_ibat, 2);
- if (rc < 0) {
- pr_err("Failed to read LAST_ADV_I reg, rc=%d\n", rc);
- return rc;
- }
- }
-
- last_ibat = sign_extend32(last_ibat, 15);
- *ibat_ua = I_RAW_TO_UA(last_ibat);
-
- return rc;
-}
-
-static int qg_get_battery_voltage(struct qpnp_qg *chip, int *vbat_uv)
-{
- int rc = 0;
- u64 last_vbat = 0;
-
- if (chip->battery_missing) {
- *vbat_uv = 3700000;
- return 0;
- }
-
- rc = qg_read(chip, chip->qg_base + QG_LAST_ADC_V_DATA0_REG,
- (u8 *)&last_vbat, 2);
- if (rc < 0) {
- pr_err("Failed to read LAST_ADV_V reg, rc=%d\n", rc);
- return rc;
- }
-
- *vbat_uv = V_RAW_TO_UV(last_vbat);
-
- return rc;
-}
-
#define DEBUG_BATT_SOC 67
#define BATT_MISSING_SOC 50
#define EMPTY_SOC 0
@@ -1614,10 +1555,10 @@
if (!chip)
return -ENODEV;
- if (chip->battery_missing || !chip->profile_loaded)
- return -ENODEV;
-
switch (param) {
+ case TTF_VALID:
+ *val = (!chip->battery_missing && chip->profile_loaded);
+ break;
case TTF_MSOC:
rc = qg_get_battery_capacity(chip, val);
break;
@@ -1985,7 +1926,7 @@
if (!chip->dt.qg_ext_sense)
update_smb = true;
- rc = process_rt_fifo_data(chip, false, update_smb);
+ rc = process_rt_fifo_data(chip, update_smb);
if (rc < 0)
pr_err("Failed to process RT FIFO data, rc=%d\n", rc);
@@ -2526,6 +2467,7 @@
qg_dbg(chip, QG_DEBUG_PROFILE, "Battery Missing!\n");
chip->battery_missing = true;
chip->profile_loaded = false;
+ chip->soc_reporting_ready = true;
} else {
/* battery present */
rc = get_batt_id_ohm(chip, &chip->batt_id_ohm);
@@ -2534,11 +2476,14 @@
chip->profile_loaded = false;
} else {
rc = qg_load_battery_profile(chip);
- if (rc < 0)
+ if (rc < 0) {
pr_err("Failed to load battery-profile rc=%d\n",
rc);
- else
+ chip->profile_loaded = false;
+ chip->soc_reporting_ready = true;
+ } else {
chip->profile_loaded = true;
+ }
}
}
@@ -2665,7 +2610,7 @@
return rc;
}
- chip->pon_soc = chip->catch_up_soc = chip->msoc = soc;
+ chip->last_adj_ssoc = chip->catch_up_soc = chip->msoc = soc;
chip->kdata.param[QG_PON_OCV_UV].data = ocv_uv;
chip->kdata.param[QG_PON_OCV_UV].valid = true;
@@ -3111,6 +3056,7 @@
#define DEFAULT_ESR_QUAL_CURRENT_UA 130000
#define DEFAULT_ESR_QUAL_VBAT_UV 7000
#define DEFAULT_ESR_DISABLE_SOC 1000
+#define ESR_CHG_MIN_IBAT_UA (-450000)
static int qg_parse_dt(struct qpnp_qg *chip)
{
int rc = 0;
@@ -3329,6 +3275,12 @@
else
chip->dt.esr_disable_soc = temp * 100;
+ rc = of_property_read_u32(node, "qcom,esr-chg-min-ibat-ua", &temp);
+ if (rc < 0)
+ chip->dt.esr_min_ibat_ua = ESR_CHG_MIN_IBAT_UA;
+ else
+ chip->dt.esr_min_ibat_ua = (int)temp;
+
chip->dt.qg_ext_sense = of_property_read_bool(node, "qcom,qg-ext-sns");
/* Capacity learning params*/
@@ -3408,9 +3360,6 @@
return 0;
cancel_delayed_work_sync(&chip->ttf->ttf_work);
- /* disable GOOD_OCV IRQ in sleep */
- vote(chip->good_ocv_irq_disable_votable,
- QG_INIT_STATE_IRQ_DISABLE, true, 0);
chip->suspend_data = false;
@@ -3483,10 +3432,6 @@
if (!chip->profile_loaded)
return 0;
- /* enable GOOD_OCV IRQ when awake */
- vote(chip->good_ocv_irq_disable_votable,
- QG_INIT_STATE_IRQ_DISABLE, false, 0);
-
rc = qg_read(chip, chip->qg_base + QG_STATUS2_REG, &status2, 1);
if (rc < 0) {
pr_err("Failed to read status2 register, rc=%d\n", rc);
@@ -3505,10 +3450,10 @@
return rc;
}
- chip->kdata.param[QG_GOOD_OCV_UV].data = ocv_uv;
- chip->kdata.param[QG_GOOD_OCV_UV].valid = true;
/* Clear suspend data as there has been a GOOD OCV */
memset(&chip->kdata, 0, sizeof(chip->kdata));
+ chip->kdata.param[QG_GOOD_OCV_UV].data = ocv_uv;
+ chip->kdata.param[QG_GOOD_OCV_UV].valid = true;
chip->suspend_data = false;
qg_dbg(chip, QG_DEBUG_PM, "GOOD OCV @ resume good_ocv=%d uV\n",
@@ -3577,9 +3522,41 @@
return 0;
}
+static int qpnp_qg_suspend(struct device *dev)
+{
+ struct qpnp_qg *chip = dev_get_drvdata(dev);
+
+ /* skip if profile is not loaded */
+ if (!chip->profile_loaded)
+ return 0;
+
+ /* disable GOOD_OCV IRQ in sleep */
+ vote(chip->good_ocv_irq_disable_votable,
+ QG_INIT_STATE_IRQ_DISABLE, true, 0);
+
+ return 0;
+}
+
+static int qpnp_qg_resume(struct device *dev)
+{
+ struct qpnp_qg *chip = dev_get_drvdata(dev);
+
+ /* skip if profile is not loaded */
+ if (!chip->profile_loaded)
+ return 0;
+
+ /* enable GOOD_OCV IRQ when active */
+ vote(chip->good_ocv_irq_disable_votable,
+ QG_INIT_STATE_IRQ_DISABLE, false, 0);
+
+ return 0;
+}
+
static const struct dev_pm_ops qpnp_qg_pm_ops = {
.suspend_noirq = qpnp_qg_suspend_noirq,
.resume_noirq = qpnp_qg_resume_noirq,
+ .suspend = qpnp_qg_suspend,
+ .resume = qpnp_qg_resume,
};
static int qpnp_qg_probe(struct platform_device *pdev)
@@ -3619,6 +3596,7 @@
chip->maint_soc = -EINVAL;
chip->batt_soc = INT_MIN;
chip->cc_soc = INT_MIN;
+ chip->sys_soc = INT_MIN;
chip->full_soc = QG_SOC_FULL;
chip->chg_iterm_ma = INT_MIN;
chip->soh = -EINVAL;
diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c
index 29bc0cb..122c0869 100644
--- a/drivers/power/supply/qcom/qpnp-smb5.c
+++ b/drivers/power/supply/qcom/qpnp-smb5.c
@@ -61,7 +61,7 @@
},
.icl_stat = {
.name = "input current limit status",
- .reg = AICL_ICL_STATUS_REG,
+ .reg = ICL_STATUS_REG,
.min_u = 0,
.max_u = 3000000,
.step_u = 50000,
@@ -95,6 +95,22 @@
.step_u = 400,
.set_proc = smblib_set_chg_freq,
},
+ .aicl_5v_threshold = {
+ .name = "AICL 5V threshold",
+ .reg = USBIN_5V_AICL_THRESHOLD_REG,
+ .min_u = 4000,
+ .max_u = 4700,
+ .step_u = 100,
+ },
+ .aicl_cont_threshold = {
+ .name = "AICL CONT threshold",
+ .reg = USBIN_CONT_AICL_THRESHOLD_REG,
+ .min_u = 4000,
+ .max_u = 8800,
+ .step_u = 100,
+ .get_proc = smblib_get_aicl_cont_threshold,
+ .set_proc = smblib_set_aicl_cont_threshold,
+ },
};
static struct smb_params smb5_pm855b_params = {
@@ -164,6 +180,22 @@
.step_u = 400,
.set_proc = NULL,
},
+ .aicl_5v_threshold = {
+ .name = "AICL 5V threshold",
+ .reg = USBIN_5V_AICL_THRESHOLD_REG,
+ .min_u = 4000,
+ .max_u = 4700,
+ .step_u = 100,
+ },
+ .aicl_cont_threshold = {
+ .name = "AICL CONT threshold",
+ .reg = USBIN_CONT_AICL_THRESHOLD_REG,
+ .min_u = 4000,
+ .max_u = 1180,
+ .step_u = 100,
+ .get_proc = smblib_get_aicl_cont_threshold,
+ .set_proc = smblib_set_aicl_cont_threshold,
+ },
};
struct smb_dt_props {
@@ -178,6 +210,9 @@
int wd_bark_time;
int batt_profile_fcc_ua;
int batt_profile_fv_uv;
+ int term_current_src;
+ int term_current_thresh_hi_ma;
+ int term_current_thresh_lo_ma;
};
struct smb5 {
@@ -206,6 +241,13 @@
USBIN_VOLTAGE,
};
+enum {
+ BAT_THERM = 0,
+ MISC_THERM,
+ CONN_THERM,
+ SMB_THERM,
+};
+
#define PMI632_MAX_ICL_UA 3000000
static int smb5_chg_config_init(struct smb5 *chip)
{
@@ -240,6 +282,7 @@
break;
case PMI632_SUBTYPE:
chip->chg.smb_version = PMI632_SUBTYPE;
+ chg->wa_flags |= WEAK_ADAPTER_WA;
chg->param = smb5_pmi632_params;
chg->use_extcon = true;
chg->name = "pmi632_charger";
@@ -266,6 +309,53 @@
return rc;
}
+#define PULL_NO_PULL 0
+#define PULL_30K 30
+#define PULL_100K 100
+#define PULL_400K 400
+static int get_valid_pullup(int pull_up)
+{
+ int pull;
+
+ /* pull up can only be 0/30K/100K/400K) */
+ switch (pull_up) {
+ case PULL_NO_PULL:
+ pull = INTERNAL_PULL_NO_PULL;
+ break;
+ case PULL_30K:
+ pull = INTERNAL_PULL_30K_PULL;
+ break;
+ case PULL_100K:
+ pull = INTERNAL_PULL_100K_PULL;
+ break;
+ case PULL_400K:
+ pull = INTERNAL_PULL_400K_PULL;
+ break;
+ default:
+ pull = INTERNAL_PULL_100K_PULL;
+ }
+
+ return pull;
+}
+
+#define INTERNAL_PULL_UP_MASK 0x3
+static int smb5_configure_internal_pull(struct smb_charger *chg, int type,
+ int pull)
+{
+ int rc;
+ int shift = type * 2;
+ u8 mask = INTERNAL_PULL_UP_MASK << shift;
+ u8 val = pull << shift;
+
+ rc = smblib_masked_write(chg, BATIF_ADC_INTERNAL_PULL_UP_REG,
+ mask, val);
+ if (rc < 0)
+ dev_err(chg->dev,
+ "Couldn't configure ADC pull-up reg rc=%d\n", rc);
+
+ return rc;
+}
+
#define MICRO_1P5A 1500000
#define MICRO_1PA 1000000
#define MICRO_P1A 100000
@@ -321,6 +411,18 @@
chg->otg_cl_ua = (chip->chg.smb_version == PMI632_SUBTYPE) ?
MICRO_1PA : MICRO_1P5A;
+ rc = of_property_read_u32(node, "qcom,chg-term-src",
+ &chip->dt.term_current_src);
+ if (rc < 0)
+ chip->dt.term_current_src = ITERM_SRC_UNSPECIFIED;
+
+ rc = of_property_read_u32(node, "qcom,chg-term-current-ma",
+ &chip->dt.term_current_thresh_hi_ma);
+
+ if (chip->dt.term_current_src == ITERM_SRC_ADC)
+ rc = of_property_read_u32(node, "qcom,chg-term-base-current-ma",
+ &chip->dt.term_current_thresh_lo_ma);
+
if (of_find_property(node, "qcom,thermal-mitigation", &byte_len)) {
chg->thermal_mitigation = devm_kzalloc(chg->dev, byte_len,
GFP_KERNEL);
@@ -387,14 +489,25 @@
if (rc < 0)
chg->otg_delay_ms = OTG_DEFAULT_DEGLITCH_TIME_MS;
+ chg->hw_die_temp_mitigation = of_property_read_bool(node,
+ "qcom,hw-die-temp-mitigation");
+
+ chg->hw_connector_mitigation = of_property_read_bool(node,
+ "qcom,hw-connector-mitigation");
+
+ chg->connector_pull_up = -EINVAL;
+ of_property_read_u32(node, "qcom,connector-internal-pull-kohm",
+ &chg->connector_pull_up);
+
return 0;
}
static int smb5_get_adc_data(struct smb_charger *chg, int channel,
union power_supply_propval *val)
{
- int rc;
+ int rc = 0;
struct qpnp_vadc_result result;
+ u8 reg;
if (!chg->vadc_dev) {
if (of_find_property(chg->dev->of_node, "qcom,chg-vadc",
@@ -418,30 +531,58 @@
if (IS_ERR(chg->vadc_dev))
return PTR_ERR(chg->vadc_dev);
+ mutex_lock(&chg->vadc_lock);
+
switch (channel) {
case USBIN_VOLTAGE:
+ /* Store ADC channel config */
+ rc = smblib_read(chg, BATIF_ADC_CHANNEL_EN_REG, ®);
+ if (rc < 0) {
+ dev_err(chg->dev,
+ "Couldn't read ADC config rc=%d\n", rc);
+ goto done;
+ }
+
+ /* Disable all ADC channels except IBAT channel */
+ rc = smblib_write(chg, BATIF_ADC_CHANNEL_EN_REG,
+ IBATT_CHANNEL_EN_BIT);
+ if (rc < 0) {
+ dev_err(chg->dev,
+ "Couldn't write ADC config rc=%d\n", rc);
+ goto done;
+ }
+
rc = qpnp_vadc_read(chg->vadc_dev, VADC_USB_IN_V_DIV_16_PM5,
&result);
- if (rc < 0) {
+ if (rc < 0)
pr_err("Failed to read USBIN_V over vadc, rc=%d\n", rc);
- return rc;
- }
- val->intval = result.physical;
+ else
+ val->intval = result.physical;
+
+ /* Restore ADC channel config */
+ rc |= smblib_write(chg, BATIF_ADC_CHANNEL_EN_REG, reg);
+ if (rc < 0)
+ dev_err(chg->dev,
+ "Couldn't write ADC config rc=%d\n", rc);
+
break;
case USBIN_CURRENT:
rc = qpnp_vadc_read(chg->vadc_dev, VADC_USB_IN_I_PM5, &result);
if (rc < 0) {
pr_err("Failed to read USBIN_I over vadc, rc=%d\n", rc);
- return rc;
+ goto done;
}
val->intval = result.physical;
break;
default:
pr_debug("Invalid channel\n");
- return -EINVAL;
+ rc = -EINVAL;
+ break;
}
- return 0;
+done:
+ mutex_unlock(&chg->vadc_lock);
+ return rc;
}
@@ -471,9 +612,11 @@
POWER_SUPPLY_PROP_SDP_CURRENT_MAX,
POWER_SUPPLY_PROP_CONNECTOR_TYPE,
POWER_SUPPLY_PROP_VOLTAGE_MAX,
+ POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
POWER_SUPPLY_PROP_SCOPE,
POWER_SUPPLY_PROP_VOLTAGE_NOW,
POWER_SUPPLY_PROP_HVDCP_OPTI_ALLOWED,
+ POWER_SUPPLY_PROP_QC_OPTI_DISABLE,
};
static int smb5_usb_get_prop(struct power_supply *psy,
@@ -507,6 +650,9 @@
case POWER_SUPPLY_PROP_VOLTAGE_MAX:
rc = smblib_get_prop_usb_voltage_max(chg, val);
break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+ rc = smblib_get_prop_usb_voltage_max_design(chg, val);
+ break;
case POWER_SUPPLY_PROP_PD_CURRENT_MAX:
val->intval = get_client_vote(chg->usb_icl_votable, PD_VOTER);
break;
@@ -602,6 +748,13 @@
case POWER_SUPPLY_PROP_HVDCP_OPTI_ALLOWED:
val->intval = !chg->flash_active;
break;
+ case POWER_SUPPLY_PROP_QC_OPTI_DISABLE:
+ if (chg->hw_die_temp_mitigation)
+ val->intval = POWER_SUPPLY_QC_THERMAL_BALANCE_DISABLE
+ | POWER_SUPPLY_QC_INOV_THERMAL_DISABLE;
+ if (chg->hw_connector_mitigation)
+ val->intval |= POWER_SUPPLY_QC_CTM_DISABLE;
+ break;
default:
pr_err("get prop %d is not supported in usb\n", psp);
rc = -EINVAL;
@@ -909,6 +1062,10 @@
pr_err("Failed to force 5V\n");
else
chg->pulse_cnt = 0;
+ } else {
+ /* USB absent & flash not-active - vote 100mA */
+ vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER,
+ true, SDP_100_MA);
}
pr_debug("flash active VBUS 5V restriction %s\n",
@@ -1075,6 +1232,7 @@
POWER_SUPPLY_PROP_VOLTAGE_MAX,
POWER_SUPPLY_PROP_CURRENT_NOW,
POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
+ POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT,
POWER_SUPPLY_PROP_TEMP,
POWER_SUPPLY_PROP_TECHNOLOGY,
POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED,
@@ -1151,6 +1309,9 @@
val->intval = get_client_vote(chg->fcc_votable,
BATT_PROFILE_VOTER);
break;
+ case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
+ rc = smblib_get_prop_batt_iterm(chg, val);
+ break;
case POWER_SUPPLY_PROP_TEMP:
rc = smblib_get_prop_batt_temp(chg, val);
break;
@@ -1262,7 +1423,7 @@
rc = smblib_set_prop_ship_mode(chg, val);
break;
case POWER_SUPPLY_PROP_RERUN_AICL:
- rc = smblib_rerun_aicl(chg);
+ rc = smblib_run_aicl(chg, RERUN_AICL);
break;
case POWER_SUPPLY_PROP_DP_DM:
if (!chg->flash_active)
@@ -1534,6 +1695,113 @@
return rc;
}
+static int smb5_configure_mitigation(struct smb_charger *chg)
+{
+ int rc;
+ u8 chan = 0;
+
+ if (!chg->hw_die_temp_mitigation && !chg->hw_connector_mitigation)
+ return 0;
+
+ if (chg->hw_die_temp_mitigation) {
+ rc = smblib_write(chg, MISC_THERMREG_SRC_CFG_REG,
+ THERMREG_CONNECTOR_ADC_SRC_EN_BIT
+ | THERMREG_DIE_ADC_SRC_EN_BIT
+ | THERMREG_DIE_CMP_SRC_EN_BIT);
+ if (rc < 0) {
+ dev_err(chg->dev,
+ "Couldn't configure THERM_SRC reg rc=%d\n", rc);
+ return rc;
+ };
+
+ chan = DIE_TEMP_CHANNEL_EN_BIT;
+ }
+
+ if (chg->hw_connector_mitigation)
+ chan |= CONN_THM_CHANNEL_EN_BIT;
+
+ rc = smblib_masked_write(chg, BATIF_ADC_CHANNEL_EN_REG,
+ CONN_THM_CHANNEL_EN_BIT | DIE_TEMP_CHANNEL_EN_BIT,
+ chan);
+ if (rc < 0) {
+ dev_err(chg->dev, "Couldn't enable ADC channel rc=%d\n", rc);
+ return rc;
+ }
+
+ return 0;
+}
+
+static int smb5_configure_iterm_thresholds_adc(struct smb5 *chip)
+{
+ u8 *buf;
+ int rc = 0;
+ s16 raw_hi_thresh, raw_lo_thresh;
+ struct smb_charger *chg = &chip->chg;
+
+ if (chip->dt.term_current_thresh_hi_ma < -10000 ||
+ chip->dt.term_current_thresh_hi_ma > 10000 ||
+ chip->dt.term_current_thresh_lo_ma < -10000 ||
+ chip->dt.term_current_thresh_lo_ma > 10000) {
+ dev_err(chg->dev, "ITERM threshold out of range rc=%d\n", rc);
+ return -EINVAL;
+ }
+
+ /*
+ * Conversion:
+ * raw (A) = (scaled_mA * ADC_CHG_TERM_MASK) / (10 * 1000)
+ * Note: raw needs to be converted to big-endian format.
+ */
+
+ if (chip->dt.term_current_thresh_hi_ma) {
+ raw_hi_thresh = ((chip->dt.term_current_thresh_hi_ma *
+ ADC_CHG_TERM_MASK) / 10000);
+ raw_hi_thresh = sign_extend32(raw_hi_thresh, 15);
+ buf = (u8 *)&raw_hi_thresh;
+ raw_hi_thresh = buf[1] | (buf[0] << 8);
+
+ rc = smblib_batch_write(chg, CHGR_ADC_ITERM_UP_THD_MSB_REG,
+ (u8 *)&raw_hi_thresh, 2);
+ if (rc < 0) {
+ dev_err(chg->dev, "Couldn't configure ITERM threshold HIGH rc=%d\n",
+ rc);
+ return rc;
+ }
+ }
+
+ if (chip->dt.term_current_thresh_lo_ma) {
+ raw_lo_thresh = ((chip->dt.term_current_thresh_lo_ma *
+ ADC_CHG_TERM_MASK) / 10000);
+ raw_lo_thresh = sign_extend32(raw_lo_thresh, 15);
+ buf = (u8 *)&raw_lo_thresh;
+ raw_lo_thresh = buf[1] | (buf[0] << 8);
+
+ rc = smblib_batch_write(chg, CHGR_ADC_ITERM_LO_THD_MSB_REG,
+ (u8 *)&raw_lo_thresh, 2);
+ if (rc < 0) {
+ dev_err(chg->dev, "Couldn't configure ITERM threshold LOW rc=%d\n",
+ rc);
+ return rc;
+ }
+ }
+
+ return rc;
+}
+
+static int smb5_configure_iterm_thresholds(struct smb5 *chip)
+{
+ int rc = 0;
+
+ switch (chip->dt.term_current_src) {
+ case ITERM_SRC_ADC:
+ rc = smb5_configure_iterm_thresholds_adc(chip);
+ break;
+ default:
+ break;
+ }
+
+ return rc;
+}
+
static int smb5_init_hw(struct smb5 *chip)
{
struct smb_charger *chg = &chip->chg;
@@ -1553,6 +1821,12 @@
smblib_get_charge_param(chg, &chg->param.usb_icl,
&chg->default_icl_ua);
+ smblib_get_charge_param(chg, &chg->param.aicl_5v_threshold,
+ &chg->default_aicl_5v_threshold_mv);
+ chg->aicl_5v_threshold_mv = chg->default_aicl_5v_threshold_mv;
+ smblib_get_charge_param(chg, &chg->param.aicl_cont_threshold,
+ &chg->default_aicl_cont_threshold_mv);
+ chg->aicl_cont_threshold_mv = chg->default_aicl_cont_threshold_mv;
/* Use SW based VBUS control, disable HW autonomous mode */
rc = smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
@@ -1640,6 +1914,13 @@
return rc;
}
+ /* configure temperature mitigation */
+ rc = smb5_configure_mitigation(chg);
+ if (rc < 0) {
+ dev_err(chg->dev, "Couldn't configure mitigation rc=%d\n", rc);
+ return rc;
+ }
+
/* vote 0mA on usb_icl for non battery platforms */
vote(chg->usb_icl_votable,
DEFAULT_VOTER, chip->dt.no_battery, 0);
@@ -1704,6 +1985,14 @@
return rc;
}
+ /* set termination current threshold values */
+ rc = smb5_configure_iterm_thresholds(chip);
+ if (rc < 0) {
+ pr_err("Couldn't configure ITERM thresholds rc=%d\n",
+ rc);
+ return rc;
+ }
+
/* configure float charger options */
switch (chip->dt.float_option) {
case FLOAT_DCP:
@@ -1850,6 +2139,17 @@
return rc;
}
+ if (chg->connector_pull_up != -EINVAL) {
+ rc = smb5_configure_internal_pull(chg, CONN_THERM,
+ get_valid_pullup(chg->connector_pull_up));
+ if (rc < 0) {
+ dev_err(chg->dev,
+ "Couldn't configure CONN_THERM pull-up rc=%d\n",
+ rc);
+ return rc;
+ }
+ }
+
return rc;
}
@@ -2020,6 +2320,8 @@
[USBIN_UV_IRQ] = {
.name = "usbin-uv",
.handler = usbin_uv_irq_handler,
+ .wake = true,
+ .storm_data = {true, 3000, 5},
},
[USBIN_OV_IRQ] = {
.name = "usbin-ov",
@@ -2396,6 +2698,7 @@
chg->irq_info = smb5_irqs;
chg->die_health = -EINVAL;
chg->otg_present = false;
+ mutex_init(&chg->vadc_lock);
chg->regmap = dev_get_regmap(chg->dev->parent, NULL);
if (!chg->regmap) {
diff --git a/drivers/power/supply/qcom/qpnp-smbcharger.c b/drivers/power/supply/qcom/qpnp-smbcharger.c
index 40cfd9c..e9e080d 100644
--- a/drivers/power/supply/qcom/qpnp-smbcharger.c
+++ b/drivers/power/supply/qcom/qpnp-smbcharger.c
@@ -632,6 +632,18 @@
mutex_unlock(&chip->pm_lock);
};
+static bool is_bms_psy_present(struct smbchg_chip *chip)
+{
+ if (chip->bms_psy)
+ return true;
+
+ if (chip->bms_psy_name)
+ chip->bms_psy = power_supply_get_by_name(
+ (char *)chip->bms_psy_name);
+
+ return chip->bms_psy ? true : false;
+}
+
enum pwr_path_type {
UNKNOWN = 0,
PWR_PATH_BATTERY = 1,
@@ -3748,17 +3760,11 @@
static void smbchg_external_power_changed(struct power_supply *psy)
{
struct smbchg_chip *chip = power_supply_get_drvdata(psy);
- union power_supply_propval prop = {0,};
- int rc, current_limit = 0, soc;
- enum power_supply_type usb_supply_type;
- char *usb_type_name = "null";
-
- if (chip->bms_psy_name)
- chip->bms_psy =
- power_supply_get_by_name((char *)chip->bms_psy_name);
+ int rc, soc;
smbchg_aicl_deglitch_wa_check(chip);
- if (chip->bms_psy) {
+
+ if (is_bms_psy_present(chip)) {
check_battery_type(chip);
soc = get_prop_batt_capacity(chip);
if (chip->previous_soc != soc) {
@@ -3773,37 +3779,8 @@
rc);
}
- rc = power_supply_get_property(chip->usb_psy,
- POWER_SUPPLY_PROP_CHARGING_ENABLED, &prop);
- if (rc == 0)
- vote(chip->usb_suspend_votable, POWER_SUPPLY_EN_VOTER,
- !prop.intval, 0);
-
- current_limit = chip->usb_current_max / 1000;
-
- /* Override if type-c charger used */
- if (chip->typec_current_ma > 500 &&
- current_limit < chip->typec_current_ma)
- current_limit = chip->typec_current_ma;
-
- read_usb_type(chip, &usb_type_name, &usb_supply_type);
-
- if (usb_supply_type != POWER_SUPPLY_TYPE_USB)
- goto skip_current_for_non_sdp;
-
- pr_smb(PR_MISC, "usb type = %s current_limit = %d\n",
- usb_type_name, current_limit);
-
- rc = vote(chip->usb_icl_votable, PSY_ICL_VOTER, true,
- current_limit);
- if (rc < 0)
- pr_err("Couldn't update USB PSY ICL vote rc=%d\n", rc);
-
-skip_current_for_non_sdp:
+ /* adjust vfloat */
smbchg_vfloat_adjust_check(chip);
-
- if (chip->batt_psy)
- power_supply_changed(chip->batt_psy);
}
static int smbchg_otg_regulator_enable(struct regulator_dev *rdev)
@@ -5754,6 +5731,21 @@
}
}
+static int smbchg_set_sdp_current(struct smbchg_chip *chip, int current_ma)
+{
+ if (chip->usb_supply_type == POWER_SUPPLY_TYPE_USB) {
+ /* Override if type-c charger used */
+ if (chip->typec_current_ma > 500 &&
+ current_ma < chip->typec_current_ma) {
+ current_ma = chip->typec_current_ma;
+ }
+ pr_smb(PR_MISC, "from USB current_ma = %d\n", current_ma);
+ vote(chip->usb_icl_votable, PSY_ICL_VOTER, true, current_ma);
+ }
+
+ return 0;
+}
+
static int smbchg_usb_get_property(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
@@ -5762,7 +5754,12 @@
switch (psp) {
case POWER_SUPPLY_PROP_CURRENT_MAX:
- val->intval = chip->usb_current_max;
+ case POWER_SUPPLY_PROP_SDP_CURRENT_MAX:
+ if (chip->usb_icl_votable)
+ val->intval = get_client_vote(chip->usb_icl_votable,
+ PSY_ICL_VOTER) * 1000;
+ else
+ val->intval = 0;
break;
case POWER_SUPPLY_PROP_PRESENT:
val->intval = chip->usb_present;
@@ -5792,17 +5789,16 @@
struct smbchg_chip *chip = power_supply_get_drvdata(psy);
switch (psp) {
- case POWER_SUPPLY_PROP_CURRENT_MAX:
- chip->usb_current_max = val->intval;
- break;
case POWER_SUPPLY_PROP_ONLINE:
chip->usb_online = val->intval;
break;
+ case POWER_SUPPLY_PROP_CURRENT_MAX:
+ case POWER_SUPPLY_PROP_SDP_CURRENT_MAX:
+ smbchg_set_sdp_current(chip, val->intval / 1000);
default:
return -EINVAL;
}
- power_supply_changed(psy);
return 0;
}
@@ -5812,6 +5808,7 @@
{
switch (psp) {
case POWER_SUPPLY_PROP_CURRENT_MAX:
+ case POWER_SUPPLY_PROP_SDP_CURRENT_MAX:
return 1;
default:
break;
@@ -5833,6 +5830,7 @@
POWER_SUPPLY_PROP_TYPE,
POWER_SUPPLY_PROP_REAL_TYPE,
POWER_SUPPLY_PROP_HEALTH,
+ POWER_SUPPLY_PROP_SDP_CURRENT_MAX,
};
#define CHARGE_OUTPUT_VTG_RATIO 840
@@ -7685,19 +7683,19 @@
#define SMBCHG_LITE_MISC_SUBTYPE 0x57
static int smbchg_request_irq(struct smbchg_chip *chip,
struct device_node *child,
- int irq_num, char *irq_name,
+ int *irq_num, char *irq_name,
irqreturn_t (irq_handler)(int irq, void *_chip),
int flags)
{
int rc;
- irq_num = of_irq_get_byname(child, irq_name);
- if (irq_num < 0) {
+ *irq_num = of_irq_get_byname(child, irq_name);
+ if (*irq_num < 0) {
dev_err(chip->dev, "Unable to get %s irqn", irq_name);
rc = -ENXIO;
}
rc = devm_request_threaded_irq(chip->dev,
- irq_num, NULL, irq_handler, flags, irq_name,
+ *irq_num, NULL, irq_handler, flags, irq_name,
chip);
if (rc < 0) {
dev_err(chip->dev, "Unable to request %s irq: %dn",
@@ -7739,26 +7737,28 @@
case SMBCHG_CHGR_SUBTYPE:
case SMBCHG_LITE_CHGR_SUBTYPE:
rc = smbchg_request_irq(chip, child,
- chip->chg_error_irq, "chg-error",
+ &chip->chg_error_irq, "chg-error",
chg_error_handler, flags);
if (rc < 0)
return rc;
- rc = smbchg_request_irq(chip, child, chip->taper_irq,
+ rc = smbchg_request_irq(chip, child, &chip->taper_irq,
"chg-taper-thr", taper_handler,
(IRQF_TRIGGER_RISING | IRQF_ONESHOT));
if (rc < 0)
return rc;
disable_irq_nosync(chip->taper_irq);
- rc = smbchg_request_irq(chip, child, chip->chg_term_irq,
+ rc = smbchg_request_irq(chip, child,
+ &chip->chg_term_irq,
"chg-tcc-thr", chg_term_handler,
(IRQF_TRIGGER_RISING | IRQF_ONESHOT));
if (rc < 0)
return rc;
- rc = smbchg_request_irq(chip, child, chip->recharge_irq,
+ rc = smbchg_request_irq(chip, child,
+ &chip->recharge_irq,
"chg-rechg-thr", recharge_handler, flags);
if (rc < 0)
return rc;
- rc = smbchg_request_irq(chip, child, chip->fastchg_irq,
+ rc = smbchg_request_irq(chip, child, &chip->fastchg_irq,
"chg-p2f-thr", fastchg_handler, flags);
if (rc < 0)
return rc;
@@ -7768,32 +7768,33 @@
break;
case SMBCHG_BAT_IF_SUBTYPE:
case SMBCHG_LITE_BAT_IF_SUBTYPE:
- rc = smbchg_request_irq(chip, child, chip->batt_hot_irq,
+ rc = smbchg_request_irq(chip, child,
+ &chip->batt_hot_irq,
"batt-hot", batt_hot_handler, flags);
if (rc < 0)
return rc;
rc = smbchg_request_irq(chip, child,
- chip->batt_warm_irq,
+ &chip->batt_warm_irq,
"batt-warm", batt_warm_handler, flags);
if (rc < 0)
return rc;
rc = smbchg_request_irq(chip, child,
- chip->batt_cool_irq,
+ &chip->batt_cool_irq,
"batt-cool", batt_cool_handler, flags);
if (rc < 0)
return rc;
rc = smbchg_request_irq(chip, child,
- chip->batt_cold_irq,
+ &chip->batt_cold_irq,
"batt-cold", batt_cold_handler, flags);
if (rc < 0)
return rc;
rc = smbchg_request_irq(chip, child,
- chip->batt_missing_irq,
+ &chip->batt_missing_irq,
"batt-missing", batt_pres_handler, flags);
if (rc < 0)
return rc;
rc = smbchg_request_irq(chip, child,
- chip->vbat_low_irq,
+ &chip->vbat_low_irq,
"batt-low", vbat_low_handler, flags);
if (rc < 0)
return rc;
@@ -7808,24 +7809,24 @@
case SMBCHG_USB_CHGPTH_SUBTYPE:
case SMBCHG_LITE_USB_CHGPTH_SUBTYPE:
rc = smbchg_request_irq(chip, child,
- chip->usbin_uv_irq,
+ &chip->usbin_uv_irq,
"usbin-uv", usbin_uv_handler,
flags | IRQF_EARLY_RESUME);
if (rc < 0)
return rc;
rc = smbchg_request_irq(chip, child,
- chip->usbin_ov_irq,
+ &chip->usbin_ov_irq,
"usbin-ov", usbin_ov_handler, flags);
if (rc < 0)
return rc;
rc = smbchg_request_irq(chip, child,
- chip->src_detect_irq,
+ &chip->src_detect_irq,
"usbin-src-det",
src_detect_handler, flags);
if (rc < 0)
return rc;
rc = smbchg_request_irq(chip, child,
- chip->aicl_done_irq,
+ &chip->aicl_done_irq,
"aicl-done",
aicl_done_handler,
(IRQF_TRIGGER_RISING | IRQF_ONESHOT));
@@ -7834,18 +7835,18 @@
if (chip->schg_version != QPNP_SCHG_LITE) {
rc = smbchg_request_irq(chip, child,
- chip->otg_fail_irq, "otg-fail",
+ &chip->otg_fail_irq, "otg-fail",
otg_fail_handler, flags);
if (rc < 0)
return rc;
rc = smbchg_request_irq(chip, child,
- chip->otg_oc_irq, "otg-oc",
+ &chip->otg_oc_irq, "otg-oc",
otg_oc_handler,
(IRQF_TRIGGER_RISING | IRQF_ONESHOT));
if (rc < 0)
return rc;
rc = smbchg_request_irq(chip, child,
- chip->usbid_change_irq, "usbid-change",
+ &chip->usbid_change_irq, "usbid-change",
usbid_change_handler,
(IRQF_TRIGGER_FALLING | IRQF_ONESHOT));
if (rc < 0)
@@ -7864,7 +7865,7 @@
break;
case SMBCHG_DC_CHGPTH_SUBTYPE:
case SMBCHG_LITE_DC_CHGPTH_SUBTYPE:
- rc = smbchg_request_irq(chip, child, chip->dcin_uv_irq,
+ rc = smbchg_request_irq(chip, child, &chip->dcin_uv_irq,
"dcin-uv", dcin_uv_handler, flags);
if (rc < 0)
return rc;
@@ -7872,16 +7873,17 @@
break;
case SMBCHG_MISC_SUBTYPE:
case SMBCHG_LITE_MISC_SUBTYPE:
- rc = smbchg_request_irq(chip, child, chip->power_ok_irq,
+ rc = smbchg_request_irq(chip, child,
+ &chip->power_ok_irq,
"power-ok", power_ok_handler, flags);
if (rc < 0)
return rc;
- rc = smbchg_request_irq(chip, child, chip->chg_hot_irq,
+ rc = smbchg_request_irq(chip, child, &chip->chg_hot_irq,
"temp-shutdown", chg_hot_handler, flags);
if (rc < 0)
return rc;
rc = smbchg_request_irq(chip, child,
- chip->wdog_timeout_irq, "wdog-timeout",
+ &chip->wdog_timeout_irq, "wdog-timeout",
wdog_timeout_handler, flags);
if (rc < 0)
return rc;
@@ -7892,19 +7894,19 @@
break;
case SMBCHG_LITE_OTG_SUBTYPE:
rc = smbchg_request_irq(chip, child,
- chip->usbid_change_irq, "usbid-change",
+ &chip->usbid_change_irq, "usbid-change",
usbid_change_handler,
(IRQF_TRIGGER_FALLING | IRQF_ONESHOT));
if (rc < 0)
return rc;
rc = smbchg_request_irq(chip, child,
- chip->otg_oc_irq, "otg-oc",
+ &chip->otg_oc_irq, "otg-oc",
otg_oc_handler,
(IRQF_TRIGGER_RISING | IRQF_ONESHOT));
if (rc < 0)
return rc;
rc = smbchg_request_irq(chip, child,
- chip->otg_fail_irq, "otg-fail",
+ &chip->otg_fail_irq, "otg-fail",
otg_fail_handler, flags);
if (rc < 0)
return rc;
diff --git a/drivers/power/supply/qcom/schgm-flash.c b/drivers/power/supply/qcom/schgm-flash.c
index eed70d3..3bbbdbf 100644
--- a/drivers/power/supply/qcom/schgm-flash.c
+++ b/drivers/power/supply/qcom/schgm-flash.c
@@ -101,6 +101,11 @@
}
}
+bool is_flash_active(struct smb_charger *chg)
+{
+ return chg->flash_active ? true : false;
+}
+
int schgm_flash_get_vreg_ok(struct smb_charger *chg, int *val)
{
int rc, vreg_state;
@@ -147,6 +152,29 @@
return 0;
}
+void schgm_flash_torch_priority(struct smb_charger *chg, enum torch_mode mode)
+{
+ int rc;
+ u8 reg;
+
+ /*
+ * If torch is configured in default BOOST mode, skip any update in the
+ * mode configuration.
+ */
+ if (chg->headroom_mode == FIXED_MODE)
+ return;
+
+ if ((mode != TORCH_BOOST_MODE) && (mode != TORCH_BUCK_MODE))
+ return;
+
+ reg = mode;
+ rc = smblib_masked_write(chg, SCHGM_TORCH_PRIORITY_CONTROL_REG,
+ TORCH_PRIORITY_CONTROL_BIT, reg);
+ if (rc < 0)
+ pr_err("Couldn't configure Torch priority control rc=%d\n",
+ rc);
+}
+
int schgm_flash_init(struct smb_charger *chg)
{
int rc;
@@ -190,7 +218,7 @@
reg = (chg->headroom_mode == FIXED_MODE)
? TORCH_PRIORITY_CONTROL_BIT : 0;
- rc = smblib_write(chg, SCHGM_TORCH_PRIORITY_CONTROL, reg);
+ rc = smblib_write(chg, SCHGM_TORCH_PRIORITY_CONTROL_REG, reg);
if (rc < 0) {
pr_err("Couldn't force 5V boost in torch mode rc=%d\n",
rc);
diff --git a/drivers/power/supply/qcom/schgm-flash.h b/drivers/power/supply/qcom/schgm-flash.h
index b6fff6c..aaa5932 100644
--- a/drivers/power/supply/qcom/schgm-flash.h
+++ b/drivers/power/supply/qcom/schgm-flash.h
@@ -37,7 +37,7 @@
#define SCHGM_FLASH_CONTROL_REG (SCHGM_FLASH_BASE + 0x60)
#define SOC_LOW_FOR_FLASH_EN_BIT BIT(7)
-#define SCHGM_TORCH_PRIORITY_CONTROL (SCHGM_FLASH_BASE + 0x63)
+#define SCHGM_TORCH_PRIORITY_CONTROL_REG (SCHGM_FLASH_BASE + 0x63)
#define TORCH_PRIORITY_CONTROL_BIT BIT(0)
#define SCHGM_SOC_BASED_FLASH_DERATE_TH_CFG_REG (SCHGM_FLASH_BASE + 0x67)
@@ -45,8 +45,15 @@
#define SCHGM_SOC_BASED_FLASH_DISABLE_TH_CFG_REG \
(SCHGM_FLASH_BASE + 0x68)
+enum torch_mode {
+ TORCH_BUCK_MODE = 0,
+ TORCH_BOOST_MODE,
+};
+
int schgm_flash_get_vreg_ok(struct smb_charger *chg, int *val);
+void schgm_flash_torch_priority(struct smb_charger *chg, enum torch_mode mode);
int schgm_flash_init(struct smb_charger *chg);
+bool is_flash_active(struct smb_charger *chg);
irqreturn_t schgm_flash_default_irq_handler(int irq, void *data);
irqreturn_t schgm_flash_ilim2_irq_handler(int irq, void *data);
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c
index 612c3dd..5b94ff2 100644
--- a/drivers/power/supply/qcom/smb-lib.c
+++ b/drivers/power/supply/qcom/smb-lib.c
@@ -4757,6 +4757,7 @@
{
int rc;
u8 stat4, stat5;
+ bool lock = false;
struct smb_charger *chg = container_of(work, struct smb_charger,
rdstd_cc2_detach_work);
@@ -4819,9 +4820,28 @@
rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
EXIT_SNK_BASED_ON_CC_BIT, 0);
smblib_reg_block_restore(chg, cc2_detach_settings);
- mutex_lock(&chg->lock);
+
+ /*
+ * Mutex acquisition deadlock can happen while cancelling this work
+ * during pd_hard_reset from the function smblib_cc2_sink_removal_exit
+ * which is called in the same lock context that we try to acquire in
+ * this work routine.
+ * Check if this work is running during pd_hard_reset and use trylock
+ * instead of mutex_lock to prevent any deadlock if mutext is already
+ * held.
+ */
+ if (chg->pd_hard_reset) {
+ if (mutex_trylock(&chg->lock))
+ lock = true;
+ } else {
+ mutex_lock(&chg->lock);
+ lock = true;
+ }
+
smblib_usb_typec_change(chg);
- mutex_unlock(&chg->lock);
+
+ if (lock)
+ mutex_unlock(&chg->lock);
return;
rerun:
diff --git a/drivers/power/supply/qcom/smb1355-charger.c b/drivers/power/supply/qcom/smb1355-charger.c
index 1d99ccb..2671d6b 100644
--- a/drivers/power/supply/qcom/smb1355-charger.c
+++ b/drivers/power/supply/qcom/smb1355-charger.c
@@ -80,8 +80,12 @@
#define BATIF_CFG_SMISC_BATID_REG (BATIF_BASE + 0x73)
#define CFG_SMISC_RBIAS_EXT_CTRL_BIT BIT(2)
-#define SMB2CHGS_BATIF_ENG_SMISC_DIETEMP (BATIF_BASE + 0xC0)
+#define SMB2CHG_BATIF_ENG_SMISC_DIETEMP (BATIF_BASE + 0xC0)
#define TDIE_COMPARATOR_THRESHOLD GENMASK(5, 0)
+#define DIE_LOW_RANGE_BASE_DEGC 34
+#define DIE_LOW_RANGE_DELTA 16
+#define DIE_LOW_RANGE_MAX_DEGC 97
+#define DIE_LOW_RANGE_SHIFT 4
#define BATIF_ENG_SCMISC_SPARE1_REG (BATIF_BASE + 0xC2)
#define EXT_BIAS_PIN_BIT BIT(2)
@@ -91,13 +95,10 @@
#define VALLEY_COMPARATOR_EN_BIT BIT(0)
#define TEMP_COMP_STATUS_REG (MISC_BASE + 0x07)
-#define SKIN_TEMP_RST_HOT_BIT BIT(6)
-#define SKIN_TEMP_UB_HOT_BIT BIT(5)
-#define SKIN_TEMP_LB_HOT_BIT BIT(4)
-#define DIE_TEMP_TSD_HOT_BIT BIT(3)
-#define DIE_TEMP_RST_HOT_BIT BIT(2)
-#define DIE_TEMP_UB_HOT_BIT BIT(1)
-#define DIE_TEMP_LB_HOT_BIT BIT(0)
+#define TEMP_RST_HOT_BIT BIT(2)
+#define TEMP_UB_HOT_BIT BIT(1)
+#define TEMP_LB_HOT_BIT BIT(0)
+#define SKIN_TEMP_SHIFT 4
#define MISC_RT_STS_REG (MISC_BASE + 0x10)
#define HARD_ILIMIT_RT_STS_BIT BIT(5)
@@ -223,6 +224,8 @@
bool disable_ctm;
int pl_mode;
int pl_batfet_mode;
+ bool hw_die_temp_mitigation;
+ u32 die_temp_threshold;
};
struct smb1355 {
@@ -250,6 +253,11 @@
struct votable *irq_disable_votable;
};
+enum {
+ CONNECTOR_TEMP = 0,
+ DIE_TEMP,
+};
+
static bool is_secure(struct smb1355 *chip, int addr)
{
if (addr == CLOCK_REQUEST_REG)
@@ -379,8 +387,7 @@
u8 temp_stat;
for (i = 0; i < BIT(5); i++) {
- rc = smb1355_masked_write(chip,
- SMB2CHGS_BATIF_ENG_SMISC_DIETEMP,
+ rc = smb1355_masked_write(chip, SMB2CHG_BATIF_ENG_SMISC_DIETEMP,
TDIE_COMPARATOR_THRESHOLD, i);
if (rc < 0) {
pr_err("Couldn't set temp comp threshold rc=%d\n", rc);
@@ -399,7 +406,7 @@
continue;
}
- if (!(temp_stat & DIE_TEMP_UB_HOT_BIT)) {
+ if (!(temp_stat & TEMP_UB_HOT_BIT)) {
/* found the temp */
break;
}
@@ -465,6 +472,7 @@
return 0;
}
+#define DEFAULT_DIE_TEMP_LOW_THRESHOLD 90
static int smb1355_parse_dt(struct smb1355 *chip)
{
struct device_node *node = chip->dev->of_node;
@@ -495,6 +503,15 @@
if (of_property_read_bool(node, "qcom,stacked-batfet"))
chip->dt.pl_batfet_mode = POWER_SUPPLY_PL_STACKED_BATFET;
+ chip->dt.hw_die_temp_mitigation = of_property_read_bool(node,
+ "qcom,hw-die-temp-mitigation");
+
+ chip->dt.die_temp_threshold = DEFAULT_DIE_TEMP_LOW_THRESHOLD;
+ of_property_read_u32(node, "qcom,die-temp-threshold-degc",
+ &chip->dt.die_temp_threshold);
+ if (chip->dt.die_temp_threshold > DIE_LOW_RANGE_MAX_DEGC)
+ chip->dt.die_temp_threshold = DIE_LOW_RANGE_MAX_DEGC;
+
return 0;
}
@@ -520,6 +537,7 @@
POWER_SUPPLY_PROP_MIN_ICL,
POWER_SUPPLY_PROP_CURRENT_MAX,
POWER_SUPPLY_PROP_SET_SHIP_MODE,
+ POWER_SUPPLY_PROP_DIE_HEALTH,
};
static int smb1355_get_prop_batt_charge_type(struct smb1355 *chip,
@@ -546,10 +564,13 @@
return rc;
}
-static int smb1355_get_prop_connector_health(struct smb1355 *chip)
+static int smb1355_get_prop_health(struct smb1355 *chip, int type)
{
u8 temp;
- int rc;
+ int rc, shift;
+
+ /* Connector-temp uses skin-temp configuration */
+ shift = (type == CONNECTOR_TEMP) ? SKIN_TEMP_SHIFT : 0;
rc = smb1355_read(chip, TEMP_COMP_STATUS_REG, &temp);
if (rc < 0) {
@@ -557,13 +578,13 @@
return POWER_SUPPLY_HEALTH_UNKNOWN;
}
- if (temp & SKIN_TEMP_RST_HOT_BIT)
+ if (temp & (TEMP_RST_HOT_BIT << shift))
return POWER_SUPPLY_HEALTH_OVERHEAT;
- if (temp & SKIN_TEMP_UB_HOT_BIT)
+ if (temp & (TEMP_UB_HOT_BIT << shift))
return POWER_SUPPLY_HEALTH_HOT;
- if (temp & SKIN_TEMP_LB_HOT_BIT)
+ if (temp & (TEMP_LB_HOT_BIT << shift))
return POWER_SUPPLY_HEALTH_WARM;
return POWER_SUPPLY_HEALTH_COOL;
@@ -614,7 +635,17 @@
val->intval = chip->die_temp_deciDegC;
break;
case POWER_SUPPLY_PROP_CHARGER_TEMP_MAX:
- rc = smb1355_get_prop_charger_temp_max(chip, val);
+ /*
+ * In case of h/w controlled die_temp mitigation,
+ * die_temp/die_temp_max can not be reported as this
+ * requires run time manipulation of DIE_TEMP low
+ * threshold which will interfere with h/w mitigation
+ * scheme.
+ */
+ if (chip->dt.hw_die_temp_mitigation)
+ val->intval = -EINVAL;
+ else
+ rc = smb1355_get_prop_charger_temp_max(chip, val);
break;
case POWER_SUPPLY_PROP_INPUT_SUSPEND:
val->intval = chip->disabled;
@@ -635,10 +666,14 @@
break;
case POWER_SUPPLY_PROP_CONNECTOR_HEALTH:
if (chip->c_health == -EINVAL)
- val->intval = smb1355_get_prop_connector_health(chip);
+ val->intval = smb1355_get_prop_health(chip,
+ CONNECTOR_TEMP);
else
val->intval = chip->c_health;
break;
+ case POWER_SUPPLY_PROP_DIE_HEALTH:
+ val->intval = smb1355_get_prop_health(chip, DIE_TEMP);
+ break;
case POWER_SUPPLY_PROP_PARALLEL_BATFET_MODE:
val->intval = chip->dt.pl_batfet_mode;
break;
@@ -708,13 +743,16 @@
}
chip->die_temp_deciDegC = -EINVAL;
- if (disable) {
- chip->exit_die_temp = true;
- cancel_delayed_work_sync(&chip->die_temp_work);
- } else {
- /* start the work to measure temperature */
- chip->exit_die_temp = false;
- schedule_delayed_work(&chip->die_temp_work, 0);
+ /* Only enable temperature measurement for s/w based mitigation */
+ if (!chip->dt.hw_die_temp_mitigation) {
+ if (disable) {
+ chip->exit_die_temp = true;
+ cancel_delayed_work_sync(&chip->die_temp_work);
+ } else {
+ /* start the work to measure temperature */
+ chip->exit_die_temp = false;
+ schedule_delayed_work(&chip->die_temp_work, 0);
+ }
}
if (chip->irq_disable_votable)
@@ -978,6 +1016,7 @@
static int smb1355_init_hw(struct smb1355 *chip)
{
int rc;
+ u8 val, range;
/* request clock always on */
rc = smb1355_clk_request(chip, true);
@@ -1045,13 +1084,35 @@
return rc;
}
+ /* Configure DIE temp Low threshold */
+ if (chip->dt.hw_die_temp_mitigation) {
+ range = (chip->dt.die_temp_threshold - DIE_LOW_RANGE_BASE_DEGC)
+ / (DIE_LOW_RANGE_DELTA);
+ val = (chip->dt.die_temp_threshold
+ - ((range * DIE_LOW_RANGE_DELTA)
+ + DIE_LOW_RANGE_BASE_DEGC))
+ % DIE_LOW_RANGE_DELTA;
+
+ rc = smb1355_masked_write(chip, SMB2CHG_BATIF_ENG_SMISC_DIETEMP,
+ TDIE_COMPARATOR_THRESHOLD,
+ (range << DIE_LOW_RANGE_SHIFT) | val);
+ if (rc < 0) {
+ pr_err("Couldn't set temp comp threshold rc=%d\n", rc);
+ return rc;
+ }
+ }
+
/*
- * Enable thermal Die temperature comparator source and disable hw
- * mitigation for skin/die
+ * Enable thermal Die temperature comparator source and
+ * enable hardware controlled current adjustment for die temp
+ * if charger is configured in h/w controlled die temp mitigation.
*/
+ val = THERMREG_DIE_CMP_SRC_EN_BIT;
+ if (!chip->dt.hw_die_temp_mitigation)
+ val |= BYP_THERM_CHG_CURR_ADJUST_BIT;
rc = smb1355_masked_write(chip, MISC_THERMREG_SRC_CFG_REG,
THERMREG_DIE_CMP_SRC_EN_BIT | BYP_THERM_CHG_CURR_ADJUST_BIT,
- THERMREG_DIE_CMP_SRC_EN_BIT | BYP_THERM_CHG_CURR_ADJUST_BIT);
+ val);
if (rc < 0) {
pr_err("Couldn't set Skin temperature comparator src rc=%d\n",
rc);
@@ -1062,8 +1123,9 @@
* Disable hysterisis for die temperature. This is so that sw can run
* stepping scheme quickly
*/
+ val = chip->dt.hw_die_temp_mitigation ? DIE_TEMP_COMP_HYST_BIT : 0;
rc = smb1355_masked_write(chip, BATIF_ENG_SCMISC_SPARE1_REG,
- DIE_TEMP_COMP_HYST_BIT, 0);
+ DIE_TEMP_COMP_HYST_BIT, val);
if (rc < 0) {
pr_err("Couldn't disable hyst. for die rc=%d\n", rc);
return rc;
diff --git a/drivers/power/supply/qcom/smb1360-charger-fg.c b/drivers/power/supply/qcom/smb1360-charger-fg.c
index ed9c610..4e98ec7 100644
--- a/drivers/power/supply/qcom/smb1360-charger-fg.c
+++ b/drivers/power/supply/qcom/smb1360-charger-fg.c
@@ -3424,8 +3424,8 @@
chip->otg_vreg.rdesc.owner = THIS_MODULE;
chip->otg_vreg.rdesc.type = REGULATOR_VOLTAGE;
chip->otg_vreg.rdesc.ops = &smb1360_otg_reg_ops;
- chip->otg_vreg.rdesc.of_match = chip->dev->of_node->name;
- chip->otg_vreg.rdesc.name = chip->dev->of_node->name;
+ chip->otg_vreg.rdesc.of_match = "qcom,smb1360-vbus";
+ chip->otg_vreg.rdesc.name = "qcom,smb1360-vbus";
cfg.dev = chip->dev;
cfg.driver_data = chip;
diff --git a/drivers/power/supply/qcom/smb138x-charger.c b/drivers/power/supply/qcom/smb138x-charger.c
index 86ecda5..e03e0a8 100644
--- a/drivers/power/supply/qcom/smb138x-charger.c
+++ b/drivers/power/supply/qcom/smb138x-charger.c
@@ -117,6 +117,11 @@
try_sink_enabled, __try_sink_enabled, int, 0600
);
+static int __audio_headset_drp_wait_ms = 100;
+ module_param_named(
+ audio_headset_drp_wait_ms, __audio_headset_drp_wait_ms, int, 0600
+);
+
static irqreturn_t smb138x_handle_slave_chg_state_change(int irq, void *data)
{
struct smb_irq_data *irq_data = data;
@@ -1786,6 +1791,7 @@
chip->chg.try_sink_enabled = &__try_sink_enabled;
chip->chg.irq_info = smb138x_irqs;
chip->chg.name = "SMB";
+ chip->chg.audio_headset_drp_wait_ms = &__audio_headset_drp_wait_ms;
chip->chg.regmap = dev_get_regmap(chip->chg.dev->parent, NULL);
if (!chip->chg.regmap) {
diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c
index d79e12b..be0832e 100644
--- a/drivers/power/supply/qcom/smb5-lib.c
+++ b/drivers/power/supply/qcom/smb5-lib.c
@@ -22,8 +22,10 @@
#include "smb5-lib.h"
#include "smb5-reg.h"
#include "battery.h"
+#include "schgm-flash.h"
#include "step-chg-jeita.h"
#include "storm-watch.h"
+#include "schgm-flash.h"
#define smblib_err(chg, fmt, ...) \
pr_err("%s: %s: " fmt, chg->name, \
@@ -320,6 +322,25 @@
return result;
}
+#define AICL_RANGE2_MIN_MV 5600
+#define AICL_RANGE2_STEP_DELTA_MV 200
+#define AICL_RANGE2_OFFSET 16
+int smblib_get_aicl_cont_threshold(struct smb_chg_param *param, u8 val_raw)
+{
+ int base = param->min_u;
+ u8 reg = val_raw;
+ int step = param->step_u;
+
+
+ if (val_raw >= AICL_RANGE2_OFFSET) {
+ reg = val_raw - AICL_RANGE2_OFFSET;
+ base = AICL_RANGE2_MIN_MV;
+ step = AICL_RANGE2_STEP_DELTA_MV;
+ }
+
+ return base + (reg * step);
+}
+
/********************
* REGISTER SETTERS *
********************/
@@ -539,6 +560,29 @@
return rc;
}
+int smblib_set_aicl_cont_threshold(struct smb_chg_param *param,
+ int val_u, u8 *val_raw)
+{
+ int base = param->min_u;
+ int offset = 0;
+ int step = param->step_u;
+
+ if (val_u > param->max_u)
+ val_u = param->max_u;
+ if (val_u < param->min_u)
+ val_u = param->min_u;
+
+ if (val_u >= AICL_RANGE2_MIN_MV) {
+ base = AICL_RANGE2_MIN_MV;
+ step = AICL_RANGE2_STEP_DELTA_MV;
+ offset = AICL_RANGE2_OFFSET;
+ };
+
+ *val_raw = ((val_u - base) / step) + offset;
+
+ return 0;
+}
+
/********************
* HELPER FUNCTIONS *
********************/
@@ -705,7 +749,6 @@
return 0;
}
-#define SDP_100_MA 100000
static void smblib_uusb_removal(struct smb_charger *chg)
{
int rc;
@@ -730,7 +773,8 @@
/* reset both usbin current and voltage votes */
vote(chg->pl_enable_votable_indirect, USBIN_I_VOTER, false, 0);
vote(chg->pl_enable_votable_indirect, USBIN_V_VOTER, false, 0);
- vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, SDP_100_MA);
+ vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true,
+ is_flash_active(chg) ? SDP_CURRENT_UA : SDP_100_MA);
vote(chg->usb_icl_votable, SW_QC3_VOTER, false, 0);
/* reconfigure allowed voltage for HVDCP */
@@ -960,7 +1004,7 @@
/* Re-run AICL */
if (chg->real_charger_type != POWER_SUPPLY_TYPE_USB)
- rc = smblib_rerun_aicl(chg);
+ rc = smblib_run_aicl(chg, RERUN_AICL);
out:
return rc;
}
@@ -1469,6 +1513,45 @@
return rc;
}
+int smblib_get_prop_batt_iterm(struct smb_charger *chg,
+ union power_supply_propval *val)
+{
+ int rc, temp;
+ u8 stat, buf[2];
+
+ /*
+ * Currently, only ADC comparator-based termination is supported,
+ * hence read only the threshold corresponding to ADC source.
+ * Proceed only if CHGR_ITERM_USE_ANALOG_BIT is 0.
+ */
+ rc = smblib_read(chg, CHGR_ENG_CHARGING_CFG_REG, &stat);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't read CHGR_ENG_CHARGING_CFG_REG rc=%d\n",
+ rc);
+ return rc;
+ }
+
+ if (stat & CHGR_ITERM_USE_ANALOG_BIT) {
+ val->intval = -EINVAL;
+ return 0;
+ }
+
+ rc = smblib_batch_read(chg, CHGR_ADC_ITERM_UP_THD_MSB_REG, buf, 2);
+
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't read CHGR_ADC_ITERM_UP_THD_MSB_REG rc=%d\n",
+ rc);
+ return rc;
+ }
+
+ temp = buf[1] | (buf[0] << 8);
+ temp = sign_extend32(temp, 15);
+ temp = DIV_ROUND_CLOSEST(temp * 10000, ADC_CHG_TERM_MASK);
+ val->intval = temp;
+
+ return rc;
+}
+
int smblib_get_prop_batt_temp(struct smb_charger *chg,
union power_supply_propval *val)
{
@@ -1615,7 +1698,7 @@
return 0;
}
-int smblib_rerun_aicl(struct smb_charger *chg)
+int smblib_run_aicl(struct smb_charger *chg, int type)
{
int rc;
u8 stat;
@@ -1633,8 +1716,8 @@
smblib_dbg(chg, PR_MISC, "re-running AICL\n");
- rc = smblib_masked_write(chg, AICL_CMD_REG, RERUN_AICL_BIT,
- RERUN_AICL_BIT);
+ stat = (type == RERUN_AICL) ? RERUN_AICL_BIT : RESTART_AICL_BIT;
+ rc = smblib_masked_write(chg, AICL_CMD_REG, stat, stat);
if (rc < 0)
smblib_err(chg, "Couldn't write to AICL_CMD_REG rc=%d\n",
rc);
@@ -1894,6 +1977,28 @@
switch (chg->real_charger_type) {
case POWER_SUPPLY_TYPE_USB_HVDCP:
case POWER_SUPPLY_TYPE_USB_HVDCP_3:
+ if (chg->smb_version == PMI632_SUBTYPE)
+ val->intval = MICRO_9V;
+ else
+ val->intval = MICRO_12V;
+ break;
+ case POWER_SUPPLY_TYPE_USB_PD:
+ val->intval = chg->voltage_max_uv;
+ break;
+ default:
+ val->intval = MICRO_5V;
+ break;
+ }
+
+ return 0;
+}
+
+int smblib_get_prop_usb_voltage_max_design(struct smb_charger *chg,
+ union power_supply_propval *val)
+{
+ switch (chg->real_charger_type) {
+ case POWER_SUPPLY_TYPE_USB_HVDCP:
+ case POWER_SUPPLY_TYPE_USB_HVDCP_3:
case POWER_SUPPLY_TYPE_USB_PD:
if (chg->smb_version == PMI632_SUBTYPE)
val->intval = MICRO_9V;
@@ -1961,6 +2066,8 @@
return POWER_SUPPLY_TYPEC_SOURCE_MEDIUM;
case SNK_RP_3P0_BIT:
return POWER_SUPPLY_TYPEC_SOURCE_HIGH;
+ case SNK_RP_SHORT_BIT:
+ return POWER_SUPPLY_TYPEC_NON_COMPLIANT;
default:
break;
}
@@ -2109,7 +2216,7 @@
int rc;
u8 stat;
- rc = smblib_read(chg, TEMP_RANGE_STATUS_REG, &stat);
+ rc = smblib_read(chg, MISC_TEMP_RANGE_STATUS_REG, &stat);
if (rc < 0) {
smblib_err(chg, "Couldn't read TEMP_RANGE_STATUS_REG rc=%d\n",
rc);
@@ -2137,13 +2244,6 @@
return 0;
}
-#define SDP_CURRENT_UA 500000
-#define CDP_CURRENT_UA 1500000
-#define DCP_CURRENT_UA 1500000
-#define HVDCP_CURRENT_UA 3000000
-#define TYPEC_DEFAULT_CURRENT_UA 900000
-#define TYPEC_MEDIUM_CURRENT_UA 1500000
-#define TYPEC_HIGH_CURRENT_UA 3000000
static int get_rp_based_dcp_current(struct smb_charger *chg, int typec_mode)
{
int rp_ua;
@@ -2183,6 +2283,7 @@
int usb_current)
{
int rc = 0, rp_ua, typec_mode;
+ union power_supply_propval val = {0, };
if (chg->real_charger_type == POWER_SUPPLY_TYPE_USB_FLOAT) {
if (usb_current == -ETIMEDOUT) {
@@ -2237,8 +2338,16 @@
return rc;
}
} else {
- rc = vote(chg->usb_icl_votable, USB_PSY_VOTER,
- true, usb_current);
+ rc = smblib_get_prop_usb_present(chg, &val);
+ if (!rc && !val.intval)
+ return 0;
+
+ /* if flash is active force 500mA */
+ if ((usb_current < SDP_CURRENT_UA) && is_flash_active(chg))
+ usb_current = SDP_CURRENT_UA;
+
+ rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, true,
+ usb_current);
if (rc < 0) {
pr_err("Couldn't vote ICL USB_PSY_VOTER rc=%d\n", rc);
return rc;
@@ -2666,13 +2775,79 @@
return IRQ_HANDLED;
}
+#define AICL_STEP_MV 200
+#define MAX_AICL_THRESHOLD_MV 4800
irqreturn_t usbin_uv_irq_handler(int irq, void *data)
{
struct smb_irq_data *irq_data = data;
struct smb_charger *chg = irq_data->parent_data;
struct storm_watch *wdata;
+ int rc;
smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s\n", irq_data->name);
+
+ if ((chg->wa_flags & WEAK_ADAPTER_WA)
+ && is_storming(&irq_data->storm_data)) {
+
+ if (chg->aicl_max_reached) {
+ smblib_dbg(chg, PR_MISC,
+ "USBIN_UV storm at max AICL threshold\n");
+ return IRQ_HANDLED;
+ }
+
+ smblib_dbg(chg, PR_MISC, "USBIN_UV storm at threshold %d\n",
+ chg->aicl_5v_threshold_mv);
+
+ /* suspend USBIN before updating AICL threshold */
+ vote(chg->usb_icl_votable, AICL_THRESHOLD_VOTER, true, 0);
+
+ /* delay for VASHDN deglitch */
+ msleep(20);
+
+ if (chg->aicl_5v_threshold_mv > MAX_AICL_THRESHOLD_MV) {
+ /* reached max AICL threshold */
+ chg->aicl_max_reached = true;
+ goto unsuspend_input;
+ }
+
+ /* Increase AICL threshold by 200mV */
+ rc = smblib_set_charge_param(chg, &chg->param.aicl_5v_threshold,
+ chg->aicl_5v_threshold_mv + AICL_STEP_MV);
+ if (rc < 0)
+ dev_err(chg->dev,
+ "Error in setting AICL threshold rc=%d\n", rc);
+ else
+ chg->aicl_5v_threshold_mv += AICL_STEP_MV;
+
+ rc = smblib_set_charge_param(chg,
+ &chg->param.aicl_cont_threshold,
+ chg->aicl_cont_threshold_mv + AICL_STEP_MV);
+ if (rc < 0)
+ dev_err(chg->dev,
+ "Error in setting AICL threshold rc=%d\n", rc);
+ else
+ chg->aicl_cont_threshold_mv += AICL_STEP_MV;
+
+unsuspend_input:
+ if (chg->smb_version == PMI632_SUBTYPE)
+ schgm_flash_torch_priority(chg, TORCH_BOOST_MODE);
+
+ if (chg->aicl_max_reached) {
+ smblib_dbg(chg, PR_MISC,
+ "Reached max AICL threshold resctricting ICL to 100mA\n");
+ vote(chg->usb_icl_votable, AICL_THRESHOLD_VOTER,
+ true, USBIN_100MA);
+ smblib_run_aicl(chg, RESTART_AICL);
+ } else {
+ smblib_run_aicl(chg, RESTART_AICL);
+ vote(chg->usb_icl_votable, AICL_THRESHOLD_VOTER,
+ false, 0);
+ }
+
+ wdata = &chg->irq_info[USBIN_UV_IRQ].irq_data->storm_data;
+ reset_storm_count(wdata);
+ }
+
if (!chg->irq_info[SWITCHER_POWER_OK_IRQ].irq_data)
return IRQ_HANDLED;
@@ -2691,6 +2866,24 @@
struct smb_charger *chg = irq_data->parent_data;
if (chg->mode == PARALLEL_MASTER) {
+ /*
+ * Ignore if change in ICL is due to DIE temp mitigation.
+ * This is to prevent any further ICL split.
+ */
+ if (chg->hw_die_temp_mitigation) {
+ rc = smblib_read(chg, MISC_DIE_TEMP_STATUS_REG, &stat);
+ if (rc < 0) {
+ smblib_err(chg,
+ "Couldn't read DIE_TEMP rc=%d\n", rc);
+ return IRQ_HANDLED;
+ }
+ if (stat & (DIE_TEMP_UB_BIT | DIE_TEMP_LB_BIT)) {
+ smblib_dbg(chg, PR_PARALLEL,
+ "skip ICL change DIE_TEMP %x\n", stat);
+ return IRQ_HANDLED;
+ }
+ }
+
rc = smblib_read(chg, AICL_STATUS_REG, &stat);
if (rc < 0) {
smblib_err(chg, "Couldn't read AICL_STATUS rc=%d\n",
@@ -2804,6 +2997,33 @@
}
}
+ if (chg->wa_flags & WEAK_ADAPTER_WA) {
+ chg->aicl_5v_threshold_mv =
+ chg->default_aicl_5v_threshold_mv;
+ chg->aicl_cont_threshold_mv =
+ chg->default_aicl_cont_threshold_mv;
+
+ smblib_set_charge_param(chg,
+ &chg->param.aicl_5v_threshold,
+ chg->aicl_5v_threshold_mv);
+ smblib_set_charge_param(chg,
+ &chg->param.aicl_cont_threshold,
+ chg->aicl_cont_threshold_mv);
+ chg->aicl_max_reached = false;
+
+ if (chg->smb_version == PMI632_SUBTYPE)
+ schgm_flash_torch_priority(chg,
+ TORCH_BUCK_MODE);
+
+ data = chg->irq_info[USBIN_UV_IRQ].irq_data;
+ if (data) {
+ wdata = &data->storm_data;
+ reset_storm_count(wdata);
+ }
+ vote(chg->usb_icl_votable, AICL_THRESHOLD_VOTER,
+ false, 0);
+ }
+
rc = smblib_request_dpdm(chg, false);
if (rc < 0)
smblib_err(chg, "Couldn't disable DPDM rc=%d\n", rc);
@@ -2988,9 +3208,12 @@
* enumeration is done.
*/
if (!is_client_vote_enabled(chg->usb_icl_votable,
- USB_PSY_VOTER))
+ USB_PSY_VOTER)) {
+ /* if flash is active force 500mA */
vote(chg->usb_icl_votable, USB_PSY_VOTER, true,
- SDP_100_MA);
+ is_flash_active(chg) ?
+ SDP_CURRENT_UA : SDP_100_MA);
+ }
vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, false, 0);
break;
case POWER_SUPPLY_TYPE_USB_CDP:
@@ -3195,7 +3418,8 @@
cancel_delayed_work_sync(&chg->pl_enable_work);
/* reset input current limit voters */
- vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, SDP_100_MA);
+ vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true,
+ is_flash_active(chg) ? SDP_CURRENT_UA : SDP_100_MA);
vote(chg->usb_icl_votable, PD_VOTER, false, 0);
vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0);
vote(chg->usb_icl_votable, DCP_VOTER, false, 0);
diff --git a/drivers/power/supply/qcom/smb5-lib.h b/drivers/power/supply/qcom/smb5-lib.h
index 7c02468..5be985e 100644
--- a/drivers/power/supply/qcom/smb5-lib.h
+++ b/drivers/power/supply/qcom/smb5-lib.h
@@ -67,12 +67,23 @@
#define WBC_VOTER "WBC_VOTER"
#define HW_LIMIT_VOTER "HW_LIMIT_VOTER"
#define FORCE_RECHARGE_VOTER "FORCE_RECHARGE_VOTER"
+#define AICL_THRESHOLD_VOTER "AICL_THRESHOLD_VOTER"
#define BOOST_BACK_STORM_COUNT 3
#define WEAK_CHG_STORM_COUNT 8
#define VBAT_TO_VRAW_ADC(v) div_u64((u64)v * 1000000UL, 194637UL)
+#define SDP_100_MA 100000
+#define SDP_CURRENT_UA 500000
+#define CDP_CURRENT_UA 1500000
+#define DCP_CURRENT_UA 1500000
+#define HVDCP_CURRENT_UA 3000000
+#define TYPEC_DEFAULT_CURRENT_UA 900000
+#define TYPEC_MEDIUM_CURRENT_UA 1500000
+#define TYPEC_HIGH_CURRENT_UA 3000000
+#define ADC_CHG_TERM_MASK 32767
+
enum smb_mode {
PARALLEL_MASTER = 0,
PARALLEL_SLAVE,
@@ -87,6 +98,12 @@
enum {
BOOST_BACK_WA = BIT(0),
+ WEAK_ADAPTER_WA = BIT(1),
+};
+
+enum {
+ RERUN_AICL = BIT(0),
+ RESTART_AICL = BIT(1),
};
enum smb_irq_index {
@@ -172,6 +189,12 @@
SUSPEND_INPUT = 4,
};
+enum chg_term_config_src {
+ ITERM_SRC_UNSPECIFIED,
+ ITERM_SRC_ADC,
+ ITERM_SRC_ANALOG
+};
+
struct smb_irq_info {
const char *name;
const irq_handler_t handler;
@@ -239,6 +262,8 @@
struct smb_chg_param jeita_cc_comp_hot;
struct smb_chg_param jeita_cc_comp_cold;
struct smb_chg_param freq_switcher;
+ struct smb_chg_param aicl_5v_threshold;
+ struct smb_chg_param aicl_cont_threshold;
};
struct parallel_params {
@@ -277,6 +302,7 @@
/* locks */
struct mutex lock;
struct mutex ps_change_lock;
+ struct mutex vadc_lock;
/* power supplies */
struct power_supply *batt_psy;
@@ -360,6 +386,14 @@
int auto_recharge_soc;
bool jeita_configured;
enum sink_src_mode sink_src_mode;
+ bool hw_die_temp_mitigation;
+ bool hw_connector_mitigation;
+ int connector_pull_up;
+ int aicl_5v_threshold_mv;
+ int default_aicl_5v_threshold_mv;
+ int aicl_cont_threshold_mv;
+ int default_aicl_cont_threshold_mv;
+ bool aicl_max_reached;
/* workaround flag */
u32 wa_flags;
@@ -394,7 +428,7 @@
int smblib_get_charge_param(struct smb_charger *chg,
struct smb_chg_param *param, int *val_u);
int smblib_get_usb_suspend(struct smb_charger *chg, int *suspend);
-
+int smblib_get_aicl_cont_threshold(struct smb_chg_param *param, u8 val_raw);
int smblib_enable_charging(struct smb_charger *chg, bool enable);
int smblib_set_charge_param(struct smb_charger *chg,
struct smb_chg_param *param, int val_u);
@@ -411,6 +445,8 @@
int val_u, u8 *val_raw);
int smblib_set_prop_boost_current(struct smb_charger *chg,
const union power_supply_propval *val);
+int smblib_set_aicl_cont_threshold(struct smb_chg_param *param,
+ int val_u, u8 *val_raw);
int smblib_vbus_regulator_enable(struct regulator_dev *rdev);
int smblib_vbus_regulator_disable(struct regulator_dev *rdev);
int smblib_vbus_regulator_is_enabled(struct regulator_dev *rdev);
@@ -459,6 +495,8 @@
union power_supply_propval *val);
int smblib_get_prop_batt_current_now(struct smb_charger *chg,
union power_supply_propval *val);
+int smblib_get_prop_batt_iterm(struct smb_charger *chg,
+ union power_supply_propval *val);
int smblib_get_prop_batt_temp(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_get_prop_batt_charge_counter(struct smb_charger *chg,
@@ -492,6 +530,8 @@
union power_supply_propval *val);
int smblib_get_prop_usb_voltage_max(struct smb_charger *chg,
union power_supply_propval *val);
+int smblib_get_prop_usb_voltage_max_design(struct smb_charger *chg,
+ union power_supply_propval *val);
int smblib_get_prop_typec_cc_orientation(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_get_prop_typec_power_role(struct smb_charger *chg,
@@ -528,7 +568,7 @@
union power_supply_propval *val);
int smblib_dp_dm(struct smb_charger *chg, int val);
int smblib_disable_hw_jeita(struct smb_charger *chg, bool disable);
-int smblib_rerun_aicl(struct smb_charger *chg);
+int smblib_run_aicl(struct smb_charger *chg, int type);
int smblib_set_icl_current(struct smb_charger *chg, int icl_ua);
int smblib_get_icl_current(struct smb_charger *chg, int *icl_ua);
int smblib_get_charge_current(struct smb_charger *chg, int *total_current_ua);
diff --git a/drivers/power/supply/qcom/smb5-reg.h b/drivers/power/supply/qcom/smb5-reg.h
index d1548c3..e9c4a0f 100644
--- a/drivers/power/supply/qcom/smb5-reg.h
+++ b/drivers/power/supply/qcom/smb5-reg.h
@@ -73,6 +73,11 @@
#define CHGR_FAST_CHARGE_CURRENT_CFG_REG (CHGR_BASE + 0x61)
+#define CHGR_ADC_ITERM_UP_THD_MSB_REG (CHGR_BASE + 0x67)
+#define CHGR_ADC_ITERM_UP_THD_LSB_REG (CHGR_BASE + 0x68)
+#define CHGR_ADC_ITERM_LO_THD_MSB_REG (CHGR_BASE + 0x69)
+#define CHGR_ADC_ITERM_LO_THD_LSB_REG (CHGR_BASE + 0x6A)
+
#define CHGR_NO_SAMPLE_TERM_RCHG_CFG_REG (CHGR_BASE + 0x6B)
#define NO_OF_SAMPLE_FOR_RCHG_SHIFT 2
#define NO_OF_SAMPLE_FOR_RCHG GENMASK(3, 2)
@@ -102,11 +107,15 @@
#define JEITA_CCCOMP_CFG_COLD_REG (CHGR_BASE + 0x93)
#define CHGR_JEITA_THRESHOLD_BASE_REG(i) (CHGR_BASE + 0x94 + (i * 4))
+
+#define CHGR_ENG_CHARGING_CFG_REG (CHGR_BASE + 0xC0)
+#define CHGR_ITERM_USE_ANALOG_BIT BIT(3)
+
/********************************
* DCDC Peripheral Registers *
********************************/
#define ICL_MAX_STATUS_REG (DCDC_BASE + 0x06)
-
+#define ICL_STATUS_REG (DCDC_BASE + 0x07)
#define AICL_ICL_STATUS_REG (DCDC_BASE + 0x08)
#define AICL_STATUS_REG (DCDC_BASE + 0x0A)
@@ -146,6 +155,19 @@
#define SHIP_MODE_REG (BATIF_BASE + 0x40)
#define SHIP_MODE_EN_BIT BIT(0)
+#define BATIF_ADC_CHANNEL_EN_REG (BATIF_BASE + 0x82)
+#define IBATT_CHANNEL_EN_BIT BIT(6)
+#define CONN_THM_CHANNEL_EN_BIT BIT(4)
+#define DIE_TEMP_CHANNEL_EN_BIT BIT(2)
+
+#define BATIF_ADC_INTERNAL_PULL_UP_REG (BATIF_BASE + 0x86)
+#define INTERNAL_PULL_UP_CONN_THM_MASK GENMASK(5, 4)
+#define CONN_THM_SHIFT 4
+#define INTERNAL_PULL_NO_PULL 0x00
+#define INTERNAL_PULL_30K_PULL 0x01
+#define INTERNAL_PULL_100K_PULL 0x02
+#define INTERNAL_PULL_400K_PULL 0x03
+
/********************************
* USBIN Peripheral Registers *
********************************/
@@ -238,6 +260,8 @@
#define USBIN_AICL_OPTIONS_CFG_REG (USBIN_BASE + 0x80)
#define USBIN_AICL_ADC_EN_BIT BIT(3)
+#define USBIN_5V_AICL_THRESHOLD_REG (USBIN_BASE + 0x81)
+#define USBIN_CONT_AICL_THRESHOLD_REG (USBIN_BASE + 0x84)
/********************************
* DCIN Peripheral Registers *
********************************/
@@ -252,10 +276,11 @@
* TYPEC Peripheral Registers *
********************************/
#define TYPE_C_SNK_STATUS_REG (TYPEC_BASE + 0x06)
-#define DETECTED_SRC_TYPE_MASK GENMASK(3, 1)
+#define DETECTED_SRC_TYPE_MASK GENMASK(3, 0)
#define SNK_RP_STD_BIT BIT(3)
#define SNK_RP_1P5_BIT BIT(2)
#define SNK_RP_3P0_BIT BIT(1)
+#define SNK_RP_SHORT_BIT BIT(0)
#define TYPE_C_SRC_STATUS_REG (TYPEC_BASE + 0x08)
#define DETECTED_SNK_TYPE_MASK GENMASK(4, 0)
@@ -333,7 +358,7 @@
/********************************
* MISC Peripheral Registers *
********************************/
-#define TEMP_RANGE_STATUS_REG (MISC_BASE + 0x06)
+#define MISC_TEMP_RANGE_STATUS_REG (MISC_BASE + 0x06)
#define THERM_REG_ACTIVE_BIT BIT(6)
#define TLIM_BIT BIT(5)
#define TEMP_RANGE_MASK GENMASK(4, 1)
@@ -343,10 +368,17 @@
#define TEMP_BELOW_RANGE_BIT BIT(1)
#define THERMREG_DISABLED_BIT BIT(0)
+#define MISC_DIE_TEMP_STATUS_REG (MISC_BASE + 0x07)
+#define DIE_TEMP_SHDN_BIT BIT(3)
+#define DIE_TEMP_RST_BIT BIT(2)
+#define DIE_TEMP_UB_BIT BIT(1)
+#define DIE_TEMP_LB_BIT BIT(0)
+
#define BARK_BITE_WDOG_PET_REG (MISC_BASE + 0x43)
#define BARK_BITE_WDOG_PET_BIT BIT(0)
#define AICL_CMD_REG (MISC_BASE + 0x44)
+#define RESTART_AICL_BIT BIT(1)
#define RERUN_AICL_BIT BIT(0)
#define MISC_SMB_EN_CMD_REG (MISC_BASE + 0x48)
@@ -366,6 +398,16 @@
#define BARK_WDOG_TIMEOUT_MASK GENMASK(3, 2)
#define BITE_WDOG_TIMEOUT_MASK GENMASK(1, 0)
+#define MISC_THERMREG_SRC_CFG_REG (MISC_BASE + 0x70)
+#define THERMREG_SW_ICL_ADJUST_BIT BIT(7)
+#define DIE_ADC_SEL_BIT BIT(6)
+#define THERMREG_SMB_ADC_SRC_EN_BIT BIT(5)
+#define THERMREG_CONNECTOR_ADC_SRC_EN_BIT BIT(4)
+#define SKIN_ADC_CFG_BIT BIT(3)
+#define THERMREG_SKIN_ADC_SRC_EN_BIT BIT(2)
+#define THERMREG_DIE_ADC_SRC_EN_BIT BIT(1)
+#define THERMREG_DIE_CMP_SRC_EN_BIT BIT(0)
+
#define MISC_SMB_CFG_REG (MISC_BASE + 0x90)
#define SMB_EN_SEL_BIT BIT(4)
#define CP_EN_POLARITY_CFG_BIT BIT(3)
diff --git a/drivers/power/supply/qcom/step-chg-jeita.c b/drivers/power/supply/qcom/step-chg-jeita.c
index 2d147d4..3b4b275 100644
--- a/drivers/power/supply/qcom/step-chg-jeita.c
+++ b/drivers/power/supply/qcom/step-chg-jeita.c
@@ -349,17 +349,46 @@
int i;
*new_index = -EINVAL;
- /* first find the matching index without hysteresis */
- for (i = 0; i < MAX_STEP_CHG_ENTRIES; i++)
+
+ /*
+ * If the threshold is lesser than the minimum allowed range,
+ * return -ENODATA.
+ */
+ if (threshold < range[0].low_threshold)
+ return -ENODATA;
+
+ /* First try to find the matching index without hysteresis */
+ for (i = 0; i < MAX_STEP_CHG_ENTRIES; i++) {
+ if (!range[i].high_threshold && !range[i].low_threshold) {
+ /* First invalid table entry; exit loop */
+ break;
+ }
+
if (is_between(range[i].low_threshold,
range[i].high_threshold, threshold)) {
*new_index = i;
*val = range[i].value;
+ break;
+ }
+ }
+
+ /*
+ * If nothing was found, the threshold exceeds the max range for sure
+ * as the other case where it is lesser than the min range is handled
+ * at the very beginning of this function. Therefore, clip it to the
+ * max allowed range value, which is the one corresponding to the last
+ * valid entry in the battery profile data array.
+ */
+ if (*new_index == -EINVAL) {
+ if (i == 0) {
+ /* Battery profile data array is completely invalid */
+ return -ENODATA;
}
- /* if nothing was found, return -ENODATA */
- if (*new_index == -EINVAL)
- return -ENODATA;
+ *new_index = (i - 1);
+ *val = range[*new_index].value;
+ }
+
/*
* If we don't have a current_index return this
* newfound value. There is no hysterisis from out of range
diff --git a/drivers/regulator/qpnp-lcdb-regulator.c b/drivers/regulator/qpnp-lcdb-regulator.c
index cc01399..4e8d6f9 100644
--- a/drivers/regulator/qpnp-lcdb-regulator.c
+++ b/drivers/regulator/qpnp-lcdb-regulator.c
@@ -218,6 +218,7 @@
struct regmap *regmap;
struct pmic_revid_data *pmic_rev_id;
u32 base;
+ u32 wa_flags;
int sc_irq;
/* TTW params */
@@ -288,6 +289,10 @@
LCDB_SETTING_MAX,
};
+enum lcdb_wa_flags {
+ NCP_SCP_DISABLE_WA = BIT(0),
+};
+
static u32 soft_start_us[] = {
0,
500,
@@ -747,9 +752,7 @@
return rc;
}
- /* execute the below for rev1.1 */
- if (lcdb->pmic_rev_id->rev3 == PM660L_V1P1_REV3 &&
- lcdb->pmic_rev_id->rev4 == PM660L_V1P1_REV4) {
+ if (lcdb->wa_flags & NCP_SCP_DISABLE_WA) {
/*
* delay to make sure that the MID pin – ie the
* output of the LCDB boost – returns to 0V
@@ -1914,11 +1917,27 @@
return 0;
}
+static void qpnp_lcdb_pmic_config(struct qpnp_lcdb *lcdb)
+{
+ switch (lcdb->pmic_rev_id->pmic_subtype) {
+ case PM660L_SUBTYPE:
+ if (lcdb->pmic_rev_id->rev4 < PM660L_V2P0_REV4)
+ lcdb->wa_flags |= NCP_SCP_DISABLE_WA;
+ break;
+ default:
+ break;
+ }
+
+ pr_debug("LCDB wa_flags = 0x%2x\n", lcdb->wa_flags);
+}
+
static int qpnp_lcdb_hw_init(struct qpnp_lcdb *lcdb)
{
int rc = 0;
u8 val = 0;
+ qpnp_lcdb_pmic_config(lcdb);
+
rc = qpnp_lcdb_init_bst(lcdb);
if (rc < 0) {
pr_err("Failed to initialize BOOST rc=%d\n", rc);
@@ -1937,8 +1956,7 @@
return rc;
}
- if (lcdb->sc_irq >= 0 &&
- lcdb->pmic_rev_id->pmic_subtype != PM660L_SUBTYPE) {
+ if (lcdb->sc_irq >= 0 && !(lcdb->wa_flags & NCP_SCP_DISABLE_WA)) {
lcdb->sc_count = 0;
rc = devm_request_threaded_irq(lcdb->dev, lcdb->sc_irq,
NULL, qpnp_lcdb_sc_irq_handler, IRQF_ONESHOT,
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index c6cfd18..0d72cd0 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -10239,7 +10239,15 @@
* racing during clock frequency scaling sequence.
*/
if (ufshcd_is_auto_hibern8_supported(hba)) {
+ /*
+ * Scaling prepare acquires the rw_sem: lock
+ * h8 may sleep in case of errors.
+ * e.g. link_recovery. Hence, release the rw_sem
+ * before hibern8.
+ */
+ up_write(&hba->lock);
ret = ufshcd_uic_hibern8_enter(hba);
+ down_write(&hba->lock);
if (ret)
/* link will be bad state so no need to scale_up_gear */
return ret;
@@ -10370,6 +10378,8 @@
hba->clk_scaling.is_allowed = value;
+ flush_work(&hba->eh_work);
+
if (value) {
ufshcd_resume_clkscaling(hba);
} else {
diff --git a/drivers/slimbus/slim-msm-ngd.c b/drivers/slimbus/slim-msm-ngd.c
index 26dfd3f..34be230 100644
--- a/drivers/slimbus/slim-msm-ngd.c
+++ b/drivers/slimbus/slim-msm-ngd.c
@@ -214,6 +214,8 @@
dsp);
struct pd_qmi_client_data *reg;
+ /* Resetting the log level */
+ SLIM_RST_LOGLVL(dev);
SLIM_INFO(dev, "SLIM DSP SSR/PDR notify cb:0x%lx, type:%d\n",
code, dsp->dom_t);
switch (code) {
diff --git a/drivers/slimbus/slim-msm.c b/drivers/slimbus/slim-msm.c
index 24a3ccf..1cc5d84 100644
--- a/drivers/slimbus/slim-msm.c
+++ b/drivers/slimbus/slim-msm.c
@@ -182,8 +182,12 @@
if (!ctrl_dev->iommu_desc.cb_dev)
return 0;
- if (!IS_ERR_OR_NULL(ctrl_dev->iommu_desc.iommu_map))
- return 0;
+ if (!IS_ERR_OR_NULL(ctrl_dev->iommu_desc.iommu_map)) {
+ arm_iommu_detach_device(ctrl_dev->iommu_desc.cb_dev);
+ arm_iommu_release_mapping(ctrl_dev->iommu_desc.iommu_map);
+ ctrl_dev->iommu_desc.iommu_map = NULL;
+ SLIM_INFO(ctrl_dev, "NGD IOMMU Dettach complete\n");
+ }
dev = ctrl_dev->iommu_desc.cb_dev;
iommu_map = arm_iommu_create_mapping(&platform_bus_type,
@@ -1300,12 +1304,6 @@
msm_slim_disconn_pipe_port(dev, i);
}
- if (!IS_ERR_OR_NULL(dev->iommu_desc.iommu_map)) {
- arm_iommu_detach_device(dev->iommu_desc.cb_dev);
- arm_iommu_release_mapping(dev->iommu_desc.iommu_map);
- dev->iommu_desc.iommu_map = NULL;
- }
-
if (dereg) {
for (i = 0; i < dev->port_nums; i++) {
if (dev->pipes[i].connected)
@@ -1706,6 +1704,11 @@
struct qmi_handle *handle;
struct slimbus_select_inst_req_msg_v01 req;
+ if (dev->qmi.handle || dev->qmi.task) {
+ pr_err("%s: Destroying stale QMI client handle\n", __func__);
+ msm_slim_qmi_exit(dev);
+ }
+
kthread_init_worker(&dev->qmi.kworker);
init_completion(&dev->qmi.defer_comp);
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 3ecca59..52d9f65 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -52,6 +52,14 @@
can start using the LLCC slices.
Say yes here to enable llcc driver for SDM670.
+config QCOM_QCS605_LLCC
+ tristate "Qualcomm Technologies, Inc. QCS605 LLCC driver"
+ depends on QCOM_LLCC
+ help
+ This provides Last level cache controller driver for QCS605.
+ This driver provides data required to configure LLCC, so that clients
+ can start using the LLCC slices.
+ Say yes here to enable llcc driver for QCS605.
config QCOM_LLCC_AMON
tristate "Qualcomm Technologies, Inc. LLCC Activity Monitor(AMON) driver"
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index 0b71121..1da8346 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -7,6 +7,7 @@
obj-$(CONFIG_QCOM_LLCC) += llcc-core.o llcc-slice.o
obj-$(CONFIG_QCOM_SDM845_LLCC) += llcc-sdm845.o
obj-$(CONFIG_QCOM_SDM670_LLCC) += llcc-sdm670.o
+obj-$(CONFIG_QCOM_QCS605_LLCC) += llcc-qcs605.o
obj-$(CONFIG_QCOM_LLCC_PERFMON) += llcc_perfmon.o
obj-$(CONFIG_QCOM_LLCC_AMON) += llcc-amon.o
obj-$(CONFIG_QPNP_PBS) += qpnp-pbs.o
diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c
index b8e9268..49719de 100644
--- a/drivers/soc/qcom/icnss.c
+++ b/drivers/soc/qcom/icnss.c
@@ -3525,6 +3525,7 @@
int atomic_ctx = 1;
int s1_bypass = 1;
int fast = 1;
+ int stall_disable = 1;
int ret = 0;
icnss_pr_dbg("Initializing SMMU\n");
@@ -3568,6 +3569,16 @@
goto set_attr_fail;
}
icnss_pr_dbg("SMMU FAST map set\n");
+
+ ret = iommu_domain_set_attr(mapping->domain,
+ DOMAIN_ATTR_CB_STALL_DISABLE,
+ &stall_disable);
+ if (ret < 0) {
+ icnss_pr_err("Set stall disable map attribute failed, err = %d\n",
+ ret);
+ goto set_attr_fail;
+ }
+ icnss_pr_dbg("SMMU STALL DISABLE map set\n");
}
ret = arm_iommu_attach_device(&priv->pdev->dev, mapping);
diff --git a/drivers/soc/qcom/ipc_router_glink_xprt.c b/drivers/soc/qcom/ipc_router_glink_xprt.c
index c93e0e1..fbb8046 100644
--- a/drivers/soc/qcom/ipc_router_glink_xprt.c
+++ b/drivers/soc/qcom/ipc_router_glink_xprt.c
@@ -23,6 +23,7 @@
#include <linux/skbuff.h>
#include <linux/delay.h>
#include <linux/sched.h>
+#include <linux/kthread.h>
#include <soc/qcom/glink.h>
#include <soc/qcom/subsystem_restart.h>
@@ -74,6 +75,7 @@
* @xprt_option: XPRT specific options to be handled by IPC Router.
* @disable_pil_loading: Disable PIL Loading of the subsystem.
* @dynamic_wakeup_source: Dynamic wakeup source for this subsystem.
+ * @low_latency_xprt: Flag to indicate low latency transport.
*/
struct ipc_router_glink_xprt {
struct list_head list;
@@ -85,7 +87,6 @@
char notify_rx_ws_name[IPC_RTR_WS_NAME_LEN];
struct msm_ipc_router_xprt xprt;
void *ch_hndl;
- struct workqueue_struct *xprt_wq;
struct wakeup_source notify_rxv_ws;
struct rw_semaphore ss_reset_rwlock;
int ss_reset;
@@ -98,17 +99,21 @@
uint32_t cur_md_intents_cnt;
uint32_t cur_hi_intents_cnt;
bool dynamic_wakeup_source;
+ bool low_latency_xprt;
+
+ struct kthread_worker kworker;
+ struct task_struct *task;
};
struct ipc_router_glink_xprt_work {
struct ipc_router_glink_xprt *glink_xprtp;
- struct work_struct work;
+ struct kthread_work kwork;
};
struct queue_rx_intent_work {
struct ipc_router_glink_xprt *glink_xprtp;
size_t intent_size;
- struct work_struct work;
+ struct kthread_work kwork;
};
struct read_work {
@@ -117,12 +122,12 @@
size_t iovec_size;
void * (*vbuf_provider)(void *iovec, size_t offset, size_t *size);
void * (*pbuf_provider)(void *iovec, size_t offset, size_t *size);
- struct work_struct work;
+ struct kthread_work kwork;
};
-static void glink_xprt_read_data(struct work_struct *work);
-static void glink_xprt_open_event(struct work_struct *work);
-static void glink_xprt_close_event(struct work_struct *work);
+static void glink_xprt_read_data(struct kthread_work *work);
+static void glink_xprt_open_event(struct kthread_work *work);
+static void glink_xprt_close_event(struct kthread_work *work);
/**
* ipc_router_glink_xprt_config - Config. Info. of each GLINK XPRT
@@ -135,6 +140,7 @@
* @xprt_version: IPC Router header version supported by this XPRT.
* @disable_pil_loading:Disable PIL Loading of the subsystem.
* @dynamic_wakeup_source: Dynamic wakeup source for this subsystem.
+ * @low_latency_xprt: Flag to indicate low latency transport.
*/
struct ipc_router_glink_xprt_config {
char ch_name[GLINK_NAME_SIZE];
@@ -147,6 +153,7 @@
unsigned int xprt_option;
bool disable_pil_loading;
bool dynamic_wakeup_source;
+ bool low_latency_xprt;
};
#define MODULE_NAME "ipc_router_glink_xprt"
@@ -311,6 +318,14 @@
return glink_xprtp->dynamic_wakeup_source;
}
+static bool ipc_router_glink_xprt_latency_info(struct msm_ipc_router_xprt *xprt)
+{
+ struct ipc_router_glink_xprt *glink_xprtp =
+ container_of(xprt, struct ipc_router_glink_xprt, xprt);
+
+ return glink_xprtp->low_latency_xprt;
+}
+
static struct rr_packet *glink_xprt_copy_data(struct read_work *rx_work)
{
void *buf, *pbuf, *dest_buf;
@@ -352,11 +367,11 @@
return pkt;
}
-static void glink_xprt_read_data(struct work_struct *work)
+static void glink_xprt_read_data(struct kthread_work *work)
{
struct rr_packet *pkt;
struct read_work *rx_work =
- container_of(work, struct read_work, work);
+ container_of(work, struct read_work, kwork);
struct ipc_router_glink_xprt *glink_xprtp = rx_work->glink_xprtp;
bool reuse_intent = false;
@@ -387,10 +402,10 @@
__pm_relax(&glink_xprtp->notify_rxv_ws);
}
-static void glink_xprt_open_event(struct work_struct *work)
+static void glink_xprt_open_event(struct kthread_work *work)
{
struct ipc_router_glink_xprt_work *xprt_work =
- container_of(work, struct ipc_router_glink_xprt_work, work);
+ container_of(work, struct ipc_router_glink_xprt_work, kwork);
struct ipc_router_glink_xprt *glink_xprtp = xprt_work->glink_xprtp;
int i;
@@ -409,10 +424,10 @@
kfree(xprt_work);
}
-static void glink_xprt_close_event(struct work_struct *work)
+static void glink_xprt_close_event(struct kthread_work *work)
{
struct ipc_router_glink_xprt_work *xprt_work =
- container_of(work, struct ipc_router_glink_xprt_work, work);
+ container_of(work, struct ipc_router_glink_xprt_work, kwork);
struct ipc_router_glink_xprt *glink_xprtp = xprt_work->glink_xprtp;
init_completion(&glink_xprtp->sft_close_complete);
@@ -424,11 +439,11 @@
kfree(xprt_work);
}
-static void glink_xprt_qrx_intent_worker(struct work_struct *work)
+static void glink_xprt_qrx_intent_worker(struct kthread_work *work)
{
size_t sz;
struct queue_rx_intent_work *qrx_intent_work =
- container_of(work, struct queue_rx_intent_work, work);
+ container_of(work, struct queue_rx_intent_work, kwork);
struct ipc_router_glink_xprt *glink_xprtp =
qrx_intent_work->glink_xprtp;
uint32_t *cnt = NULL;
@@ -501,8 +516,8 @@
rx_work->pbuf_provider = pbuf_provider;
if (!glink_xprtp->dynamic_wakeup_source)
__pm_stay_awake(&glink_xprtp->notify_rxv_ws);
- INIT_WORK(&rx_work->work, glink_xprt_read_data);
- queue_work(glink_xprtp->xprt_wq, &rx_work->work);
+ kthread_init_work(&rx_work->kwork, glink_xprt_read_data);
+ kthread_queue_work(&glink_xprtp->kworker, &rx_work->kwork);
}
static void glink_xprt_notify_tx_done(void *handle, const void *priv,
@@ -535,8 +550,9 @@
}
qrx_intent_work->glink_xprtp = glink_xprtp;
qrx_intent_work->intent_size = sz;
- INIT_WORK(&qrx_intent_work->work, glink_xprt_qrx_intent_worker);
- queue_work(glink_xprtp->xprt_wq, &qrx_intent_work->work);
+ kthread_init_work(&qrx_intent_work->kwork,
+ glink_xprt_qrx_intent_worker);
+ kthread_queue_work(&glink_xprtp->kworker, &qrx_intent_work->kwork);
return true;
}
@@ -565,8 +581,8 @@
return;
}
xprt_work->glink_xprtp = glink_xprtp;
- INIT_WORK(&xprt_work->work, glink_xprt_open_event);
- queue_work(glink_xprtp->xprt_wq, &xprt_work->work);
+ kthread_init_work(&xprt_work->kwork, glink_xprt_open_event);
+ kthread_queue_work(&glink_xprtp->kworker, &xprt_work->kwork);
break;
case GLINK_LOCAL_DISCONNECTED:
@@ -587,8 +603,8 @@
return;
}
xprt_work->glink_xprtp = glink_xprtp;
- INIT_WORK(&xprt_work->work, glink_xprt_close_event);
- queue_work(glink_xprtp->xprt_wq, &xprt_work->work);
+ kthread_init_work(&xprt_work->kwork, glink_xprt_close_event);
+ kthread_queue_work(&glink_xprtp->kworker, &xprt_work->kwork);
break;
}
}
@@ -712,6 +728,7 @@
{
struct ipc_router_glink_xprt *glink_xprtp;
char xprt_wq_name[GLINK_NAME_SIZE];
+ struct sched_param param = {.sched_priority = 1};
glink_xprtp = kzalloc(sizeof(struct ipc_router_glink_xprt), GFP_KERNEL);
if (IS_ERR_OR_NULL(glink_xprtp)) {
@@ -729,6 +746,8 @@
glink_xprt_config->disable_pil_loading;
glink_xprtp->dynamic_wakeup_source =
glink_xprt_config->dynamic_wakeup_source;
+ glink_xprtp->low_latency_xprt =
+ glink_xprt_config->low_latency_xprt;
if (!glink_xprtp->disable_pil_loading)
strlcpy(glink_xprtp->pil_edge, glink_xprt_config->pil_edge,
@@ -752,6 +771,7 @@
glink_xprtp->xprt.close = ipc_router_glink_xprt_close;
glink_xprtp->xprt.sft_close_done = glink_xprt_sft_close_done;
glink_xprtp->xprt.get_ws_info = ipc_router_glink_xprt_get_ws_info;
+ glink_xprtp->xprt.get_latency_info = ipc_router_glink_xprt_latency_info;
glink_xprtp->xprt.priv = NULL;
init_rwsem(&glink_xprtp->ss_reset_rwlock);
@@ -760,15 +780,20 @@
scnprintf(xprt_wq_name, GLINK_NAME_SIZE, "%s_%s_%s",
glink_xprtp->ch_name, glink_xprtp->edge,
glink_xprtp->transport);
- glink_xprtp->xprt_wq = create_singlethread_workqueue(xprt_wq_name);
- if (IS_ERR_OR_NULL(glink_xprtp->xprt_wq)) {
- IPC_RTR_ERR("%s:%s:%s:%s wq alloc failed\n",
- __func__, glink_xprt_config->ch_name,
- glink_xprt_config->edge,
- glink_xprt_config->transport);
+ kthread_init_worker(&glink_xprtp->kworker);
+ glink_xprtp->task = kthread_run(kthread_worker_fn,
+ &glink_xprtp->kworker,
+ "%s", xprt_wq_name);
+ if (IS_ERR(glink_xprtp->task)) {
+ IPC_RTR_ERR("%s:%s task alloc failed\n",
+ __func__, xprt_wq_name);
kfree(glink_xprtp);
return -EFAULT;
}
+
+ if (glink_xprtp->low_latency_xprt)
+ sched_setscheduler(glink_xprtp->task, SCHED_FIFO, ¶m);
+
scnprintf(glink_xprtp->notify_rx_ws_name, IPC_RTR_WS_NAME_LEN,
"%s_%s_rx", glink_xprtp->ch_name, glink_xprtp->edge);
wakeup_source_init(&glink_xprtp->notify_rxv_ws,
@@ -853,6 +878,9 @@
glink_xprt_config->dynamic_wakeup_source =
of_property_read_bool(node, key);
+ key = "qcom,low-latency-xprt";
+ glink_xprt_config->low_latency_xprt =
+ of_property_read_bool(node, key);
return 0;
error:
diff --git a/drivers/soc/qcom/jtagv8-etm.c b/drivers/soc/qcom/jtagv8-etm.c
index 23cbb7b..45511ce 100644
--- a/drivers/soc/qcom/jtagv8-etm.c
+++ b/drivers/soc/qcom/jtagv8-etm.c
@@ -1480,6 +1480,27 @@
etmdata->os_lock_present = false;
}
+static bool coresight_authstatus_enabled(void __iomem *addr)
+{
+ int ret;
+ unsigned int auth_val;
+
+ if (!addr)
+ return false;
+
+ auth_val = readl_relaxed(addr + TRCAUTHSTATUS);
+
+ if ((BMVAL(auth_val, 0, 1) == 0x2) ||
+ (BMVAL(auth_val, 2, 3) == 0x2) ||
+ (BMVAL(auth_val, 4, 5) == 0x2) ||
+ (BMVAL(auth_val, 6, 7) == 0x2))
+ ret = false;
+ else
+ ret = true;
+
+ return ret;
+}
+
static void etm_init_arch_data(void *info)
{
uint32_t val;
@@ -1487,6 +1508,9 @@
ETM_UNLOCK(etmdata);
+ if (!coresight_authstatus_enabled(etmdata->base))
+ goto out;
+
etm_os_lock_init(etmdata);
val = etm_readl(etmdata, TRCIDR1);
@@ -1505,6 +1529,7 @@
etmdata->nr_seq_state = BMVAL(val, 25, 27);
etmdata->nr_cntr = BMVAL(val, 28, 30);
+out:
ETM_LOCK(etmdata);
}
diff --git a/drivers/soc/qcom/llcc-qcs605.c b/drivers/soc/qcom/llcc-qcs605.c
new file mode 100644
index 0000000..d3d3390
--- /dev/null
+++ b/drivers/soc/qcom/llcc-qcs605.c
@@ -0,0 +1,106 @@
+/* Copyright (c) 2018, 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/soc/qcom/llcc-qcom.h>
+
+/*
+ * SCT entry contains of the following parameters
+ * name: Name of the client's use case for which the llcc slice is used
+ * uid: Unique id for the client's use case
+ * slice_id: llcc slice id for each client
+ * max_cap: The maximum capacity of the cache slice provided in KB
+ * priority: Priority of the client used to select victim line for replacement
+ * fixed_size: Determine of the slice has a fixed capacity
+ * bonus_ways: Bonus ways to be used by any slice, bonus way is used only if
+ * it't not a reserved way.
+ * res_ways: Reserved ways for the cache slice, the reserved ways cannot be used
+ * by any other client than the one its assigned to.
+ * cache_mode: Each slice operates as a cache, this controls the mode of the
+ * slice normal or TCM
+ * probe_target_ways: Determines what ways to probe for access hit. When
+ * configured to 1 only bonus and reseved ways are probed.
+ * when configured to 0 all ways in llcc are probed.
+ * dis_cap_alloc: Disable capacity based allocation for a client
+ * retain_on_pc: If this bit is set and client has maitained active vote
+ * then the ways assigned to this client are not flushed on power
+ * collapse.
+ * activate_on_init: Activate the slice immidiately after the SCT is programmed
+ */
+#define SCT_ENTRY(n, uid, sid, mc, p, fs, bway, rway, cmod, ptw, dca, rp, a) \
+ { \
+ .name = n, \
+ .usecase_id = uid, \
+ .slice_id = sid, \
+ .max_cap = mc, \
+ .priority = p, \
+ .fixed_size = fs, \
+ .bonus_ways = bway, \
+ .res_ways = rway, \
+ .cache_mode = cmod, \
+ .probe_target_ways = ptw, \
+ .dis_cap_alloc = dca, \
+ .retain_on_pc = rp, \
+ .activate_on_init = a, \
+ }
+
+static struct llcc_slice_config qcs605_data[] = {
+ SCT_ENTRY("cpuss", 1, 1, 512, 1, 0, 0xF, 0x0, 0, 0, 1, 1, 1),
+ SCT_ENTRY("vidsc0", 2, 2, 256, 2, 1, 0x3, 0x0, 0, 0, 1, 1, 0),
+ SCT_ENTRY("vidsc1", 3, 3, 256, 2, 1, 0x3, 0x0, 0, 0, 1, 1, 0),
+ SCT_ENTRY("voice", 5, 5, 512, 1, 0, 0xF, 0x0, 0, 0, 1, 1, 0),
+ SCT_ENTRY("audio", 6, 6, 512, 1, 0, 0xF, 0x0, 0, 0, 1, 1, 0),
+ SCT_ENTRY("modem", 8, 8, 512, 1, 0, 0xF, 0x0, 0, 0, 1, 1, 0),
+ SCT_ENTRY("compute", 10, 10, 512, 1, 0, 0xF, 0x0, 0, 0, 1, 1, 0),
+ SCT_ENTRY("gpu", 12, 12, 512, 1, 0, 0xF, 0x0, 0, 0, 1, 1, 0),
+ SCT_ENTRY("mmuhwt", 13, 13, 512, 1, 0, 0xF, 0x0, 0, 0, 1, 0, 1),
+ SCT_ENTRY("audiohw", 22, 22, 512, 1, 1, 0xF, 0x0, 0, 0, 1, 1, 0),
+};
+
+static int qcs605_qcom_llcc_probe(struct platform_device *pdev)
+{
+ return qcom_llcc_probe(pdev, qcs605_data,
+ ARRAY_SIZE(qcs605_data));
+}
+
+static const struct of_device_id qcs605_qcom_llcc_of_match[] = {
+ { .compatible = "qcom,qcs605-llcc", },
+ { },
+};
+
+static struct platform_driver qcs605_qcom_llcc_driver = {
+ .driver = {
+ .name = "qcs605-llcc",
+ .owner = THIS_MODULE,
+ .of_match_table = qcs605_qcom_llcc_of_match,
+ },
+ .probe = qcs605_qcom_llcc_probe,
+ .remove = qcom_llcc_remove,
+};
+
+static int __init qcs605_init_qcom_llcc_init(void)
+{
+ return platform_driver_register(&qcs605_qcom_llcc_driver);
+}
+module_init(qcs605_init_qcom_llcc_init);
+
+static void __exit qcs605_exit_qcom_llcc_exit(void)
+{
+ platform_driver_unregister(&qcs605_qcom_llcc_driver);
+}
+module_exit(qcs605_exit_qcom_llcc_exit);
+
+MODULE_DESCRIPTION("QTI qcs605 LLCC driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/soc/qcom/msm_bus/msm_bus_fabric_adhoc.c b/drivers/soc/qcom/msm_bus/msm_bus_fabric_adhoc.c
index ee9b7af..eb54119 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_fabric_adhoc.c
+++ b/drivers/soc/qcom/msm_bus/msm_bus_fabric_adhoc.c
@@ -971,10 +971,8 @@
bus_node = kzalloc(sizeof(struct msm_bus_node_device_type), GFP_KERNEL);
if (!bus_node) {
- MSM_BUS_ERR("%s:Bus node alloc failed\n", __func__);
- kfree(bus_dev);
- bus_dev = NULL;
- goto exit_device_init;
+ ret = -ENOMEM;
+ goto err_device_init;
}
bus_dev = &bus_node->dev;
device_initialize(bus_dev);
@@ -982,47 +980,37 @@
node_info = devm_kzalloc(bus_dev,
sizeof(struct msm_bus_node_info_type), GFP_KERNEL);
if (!node_info) {
- MSM_BUS_ERR("%s:Bus node info alloc failed\n", __func__);
- devm_kfree(bus_dev, bus_node);
- kfree(bus_dev);
- bus_dev = NULL;
- goto exit_device_init;
+ ret = -ENOMEM;
+ goto err_put_device;
}
bus_node->node_info = node_info;
bus_node->ap_owned = pdata->ap_owned;
bus_dev->of_node = pdata->of_node;
- if (msm_bus_copy_node_info(pdata, bus_dev) < 0) {
- devm_kfree(bus_dev, bus_node);
- devm_kfree(bus_dev, node_info);
- kfree(bus_dev);
- bus_dev = NULL;
- goto exit_device_init;
- }
+ ret = msm_bus_copy_node_info(pdata, bus_dev);
+ if (ret)
+ goto err_put_device;
bus_dev->bus = &msm_bus_type;
dev_set_name(bus_dev, bus_node->node_info->name);
ret = device_add(bus_dev);
- if (ret < 0) {
+ if (ret) {
MSM_BUS_ERR("%s: Error registering device %d",
__func__, pdata->node_info->id);
- devm_kfree(bus_dev, bus_node);
- devm_kfree(bus_dev, node_info->dev_connections);
- devm_kfree(bus_dev, node_info->connections);
- devm_kfree(bus_dev, node_info->black_connections);
- devm_kfree(bus_dev, node_info->black_listed_connections);
- devm_kfree(bus_dev, node_info);
- kfree(bus_dev);
- bus_dev = NULL;
- goto exit_device_init;
+ goto err_put_device;
}
device_create_file(bus_dev, &dev_attr_bw);
INIT_LIST_HEAD(&bus_node->devlist);
-
-exit_device_init:
return bus_dev;
+
+err_put_device:
+ put_device(bus_dev);
+ bus_dev = NULL;
+ kfree(bus_node);
+err_device_init:
+ return ERR_PTR(ret);
}
static int msm_bus_setup_dev_conn(struct device *bus_dev, void *data)
@@ -1169,10 +1157,10 @@
node_dev = msm_bus_device_init(&pdata->info[i]);
- if (!node_dev) {
+ if (IS_ERR(node_dev)) {
MSM_BUS_ERR("%s: Error during dev init for %d",
__func__, pdata->info[i].node_info->id);
- ret = -ENXIO;
+ ret = PTR_ERR(node_dev);
goto exit_device_probe;
}
diff --git a/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c b/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c
index c00749c..5a28e98 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c
+++ b/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c
@@ -1471,7 +1471,7 @@
struct device *bus_dev = NULL;
struct msm_bus_node_device_type *bus_node = NULL;
struct msm_bus_node_info_type *node_info = NULL;
- int ret = 0, i = 0;
+ int ret = -ENODEV, i = 0;
/**
* Init here so we can use devm calls
@@ -1479,10 +1479,8 @@
bus_node = kzalloc(sizeof(struct msm_bus_node_device_type), GFP_KERNEL);
if (!bus_node) {
- MSM_BUS_ERR("%s:Bus node alloc failed\n", __func__);
- kfree(bus_dev);
- bus_dev = NULL;
- goto exit_device_init;
+ ret = -ENOMEM;
+ goto err_device_init;
}
bus_dev = &bus_node->dev;
device_initialize(bus_dev);
@@ -1490,11 +1488,8 @@
node_info = devm_kzalloc(bus_dev,
sizeof(struct msm_bus_node_info_type), GFP_KERNEL);
if (!node_info) {
- MSM_BUS_ERR("%s:Bus node info alloc failed\n", __func__);
- devm_kfree(bus_dev, bus_node);
- kfree(bus_dev);
- bus_dev = NULL;
- goto exit_device_init;
+ ret = -ENOMEM;
+ goto err_put_device;
}
bus_node->node_info = node_info;
@@ -1505,8 +1500,10 @@
bus_node->qos_bcms = devm_kzalloc(bus_dev,
(sizeof(struct qos_bcm_type) *
bus_node->num_qos_bcms), GFP_KERNEL);
- if (!bus_node->qos_bcms)
- goto exit_device_init;
+ if (!bus_node->qos_bcms) {
+ ret = -ENOMEM;
+ goto err_put_device;
+ }
for (i = 0; i < bus_node->num_qos_bcms; i++) {
bus_node->qos_bcms[i].qos_bcm_id =
pdata->qos_bcms[i].qos_bcm_id;
@@ -1519,36 +1516,29 @@
bus_dev->of_node = pdata->of_node;
- if (msm_bus_copy_node_info(pdata, bus_dev) < 0) {
- devm_kfree(bus_dev, bus_node);
- devm_kfree(bus_dev, node_info);
- kfree(bus_dev);
- bus_dev = NULL;
- goto exit_device_init;
- }
+ ret = msm_bus_copy_node_info(pdata, bus_dev);
+ if (ret)
+ goto err_put_device;
bus_dev->bus = &msm_bus_type;
dev_set_name(bus_dev, bus_node->node_info->name);
ret = device_add(bus_dev);
- if (ret < 0) {
+ if (ret) {
MSM_BUS_ERR("%s: Error registering device %d",
__func__, pdata->node_info->id);
- devm_kfree(bus_dev, bus_node);
- devm_kfree(bus_dev, node_info->dev_connections);
- devm_kfree(bus_dev, node_info->connections);
- devm_kfree(bus_dev, node_info->black_connections);
- devm_kfree(bus_dev, node_info->black_listed_connections);
- devm_kfree(bus_dev, node_info);
- kfree(bus_dev);
- bus_dev = NULL;
- goto exit_device_init;
+ goto err_put_device;
}
device_create_file(bus_dev, &dev_attr_bw);
INIT_LIST_HEAD(&bus_node->devlist);
-
-exit_device_init:
return bus_dev;
+
+err_put_device:
+ put_device(bus_dev);
+ bus_dev = NULL;
+ kfree(bus_node);
+err_device_init:
+ return ERR_PTR(ret);
}
static int msm_bus_setup_dev_conn(struct device *bus_dev, void *data)
@@ -1736,10 +1726,10 @@
node_dev = msm_bus_device_init(&pdata->info[i]);
- if (!node_dev) {
+ if (IS_ERR(node_dev)) {
MSM_BUS_ERR("%s: Error during dev init for %d",
__func__, pdata->info[i].node_info->id);
- ret = -ENXIO;
+ ret = PTR_ERR(node_dev);
goto exit_device_probe;
}
diff --git a/drivers/soc/qcom/msm_glink_pkt.c b/drivers/soc/qcom/msm_glink_pkt.c
index 9a9b4df..4559f11 100644
--- a/drivers/soc/qcom/msm_glink_pkt.c
+++ b/drivers/soc/qcom/msm_glink_pkt.c
@@ -29,6 +29,7 @@
#include <asm/ioctls.h>
#include <linux/mm.h>
#include <linux/of.h>
+#include <linux/vmalloc.h>
#include <linux/ipc_logging.h>
#include <linux/termios.h>
@@ -397,7 +398,10 @@
GLINK_PKT_INFO("%s(): priv[%p] pkt_priv[%p] ptr[%p]\n",
__func__, priv, pkt_priv, ptr);
/* Free Tx buffer allocated in glink_pkt_write */
- kfree(ptr);
+ if (is_vmalloc_addr(ptr))
+ vfree_atomic(ptr);
+ else
+ kfree(ptr);
}
/**
@@ -775,8 +779,10 @@
__func__, devp->i, count);
data = kzalloc(count, GFP_KERNEL);
if (!data) {
- GLINK_PKT_ERR("%s buffer allocation failed\n", __func__);
- return -ENOMEM;
+ if (!strcmp(devp->open_cfg.edge, "bg"))
+ data = vzalloc(count);
+ if (!data)
+ return -ENOMEM;
}
ret = copy_from_user(data, buf, count);
@@ -784,14 +790,20 @@
GLINK_PKT_ERR(
"%s copy_from_user failed ret[%d] on dev id:%d size %zu\n",
__func__, ret, devp->i, count);
- kfree(data);
+ if (is_vmalloc_addr(data))
+ vfree_atomic(data);
+ else
+ kfree(data);
return -EFAULT;
}
ret = glink_tx(devp->handle, data, data, count, GLINK_TX_REQ_INTENT);
if (ret) {
GLINK_PKT_ERR("%s glink_tx failed ret[%d]\n", __func__, ret);
- kfree(data);
+ if (is_vmalloc_addr(data))
+ vfree_atomic(data);
+ else
+ kfree(data);
return ret;
}
diff --git a/drivers/soc/qcom/msm_smem.c b/drivers/soc/qcom/msm_smem.c
index 1bbd751..959aab9 100644
--- a/drivers/soc/qcom/msm_smem.c
+++ b/drivers/soc/qcom/msm_smem.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2018, 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
@@ -26,6 +26,7 @@
#include <soc/qcom/subsystem_notif.h>
#include <soc/qcom/subsystem_restart.h>
#include <soc/qcom/ramdump.h>
+#include <soc/qcom/scm.h>
#include <soc/qcom/smem.h>
@@ -1085,12 +1086,15 @@
void *handle;
struct restart_notifier_block *nb;
- if (smem_dev)
- smem_ramdump_dev = create_ramdump_device("smem", smem_dev);
- if (IS_ERR_OR_NULL(smem_ramdump_dev)) {
- LOG_ERR("%s: Unable to create smem ramdump device.\n",
- __func__);
- smem_ramdump_dev = NULL;
+ if (scm_is_secure_device()) {
+ if (smem_dev)
+ smem_ramdump_dev = create_ramdump_device("smem",
+ smem_dev);
+ if (IS_ERR_OR_NULL(smem_ramdump_dev)) {
+ LOG_ERR("%s: Unable to create smem ramdump device.\n",
+ __func__);
+ smem_ramdump_dev = NULL;
+ }
}
for (i = 0; i < ARRAY_SIZE(restart_notifiers); i++) {
diff --git a/drivers/soc/qcom/qmp-debugfs-client.c b/drivers/soc/qcom/qmp-debugfs-client.c
index d7a473e..a327e031 100644
--- a/drivers/soc/qcom/qmp-debugfs-client.c
+++ b/drivers/soc/qcom/qmp-debugfs-client.c
@@ -116,8 +116,8 @@
.driver = {
.name = "debugfs-qmp-client",
.owner = THIS_MODULE,
+ .suppress_bind_attrs = true,
.of_match_table = aop_qmp_match_tbl,
},
};
-
builtin_platform_driver(aop_qmp_msg_driver);
diff --git a/drivers/soc/qcom/rpm-smd.c b/drivers/soc/qcom/rpm-smd.c
index c29cfcb..675551a 100644
--- a/drivers/soc/qcom/rpm-smd.c
+++ b/drivers/soc/qcom/rpm-smd.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2018, 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
@@ -2138,6 +2138,7 @@
.driver = {
.name = "rpm-smd",
.owner = THIS_MODULE,
+ .suppress_bind_attrs = true,
.of_match_table = msm_rpm_match_table,
},
};
diff --git a/drivers/soc/qcom/rpm_stats.c b/drivers/soc/qcom/rpm_stats.c
index a39856b..e7d9fac5 100644
--- a/drivers/soc/qcom/rpm_stats.c
+++ b/drivers/soc/qcom/rpm_stats.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2018, 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
@@ -11,6 +11,8 @@
*
*/
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
#include <linux/init.h>
#include <linux/io.h>
#include <linux/kernel.h>
@@ -36,6 +38,7 @@
struct msm_rpmstats_platform_data {
phys_addr_t phys_addr_base;
u32 phys_size;
+ u32 num_records;
};
struct msm_rpmstats_private_data {
@@ -43,7 +46,7 @@
u32 num_records;
u32 read_idx;
u32 len;
- char buf[320];
+ char buf[480];
struct msm_rpmstats_platform_data *platform_data;
};
@@ -61,6 +64,7 @@
};
struct msm_rpmstats_kobj_attr {
+ struct kobject *kobj;
struct kobj_attribute ka;
struct msm_rpmstats_platform_data *pd;
};
@@ -175,29 +179,32 @@
{
struct msm_rpmstats_private_data prvdata;
struct msm_rpmstats_platform_data *pdata = NULL;
+ ssize_t length;
pdata = GET_PDATA_OF_ATTR(attr);
prvdata.reg_base = ioremap_nocache(pdata->phys_addr_base,
pdata->phys_size);
if (!prvdata.reg_base) {
- pr_err("%s: ERROR could not ioremap start=%pa, len=%u\n",
- __func__, &pdata->phys_addr_base,
- pdata->phys_size);
+ pr_err("ERROR could not ioremap start=%pa, len=%u\n",
+ &pdata->phys_addr_base, pdata->phys_size);
return -EBUSY;
}
prvdata.read_idx = prvdata.len = 0;
prvdata.platform_data = pdata;
- prvdata.num_records = RPM_STATS_NUM_REC;
+ prvdata.num_records = pdata->num_records;
if (prvdata.read_idx < prvdata.num_records)
prvdata.len = msm_rpmstats_copy_stats(&prvdata);
- return snprintf(buf, prvdata.len, "%s", prvdata.buf);
+ length = scnprintf(buf, prvdata.len, "%s", prvdata.buf);
+ iounmap(prvdata.reg_base);
+ return length;
}
-static int msm_rpmstats_create_sysfs(struct msm_rpmstats_platform_data *pd)
+static int msm_rpmstats_create_sysfs(struct platform_device *pdev,
+ struct msm_rpmstats_platform_data *pd)
{
struct kobject *rpmstats_kobj = NULL;
struct msm_rpmstats_kobj_attr *rpms_ka = NULL;
@@ -205,7 +212,7 @@
rpmstats_kobj = kobject_create_and_add("system_sleep", power_kobj);
if (!rpmstats_kobj) {
- pr_err("%s: Cannot create rpmstats kobject\n", __func__);
+ pr_err("Cannot create rpmstats kobject\n");
ret = -ENOMEM;
goto fail;
}
@@ -217,6 +224,8 @@
goto fail;
}
+ rpms_ka->kobj = rpmstats_kobj;
+
sysfs_attr_init(&rpms_ka->ka.attr);
rpms_ka->pd = pd;
rpms_ka->ka.attr.mode = 0444;
@@ -225,6 +234,7 @@
rpms_ka->ka.store = NULL;
ret = sysfs_create_file(rpmstats_kobj, &rpms_ka->ka.attr);
+ platform_set_drvdata(pdev, rpms_ka);
fail:
return ret;
@@ -233,28 +243,27 @@
static int msm_rpmstats_probe(struct platform_device *pdev)
{
struct msm_rpmstats_platform_data *pdata;
- struct msm_rpmstats_platform_data *pd;
struct resource *res = NULL, *offset = NULL;
u32 offset_addr = 0;
void __iomem *phys_ptr = NULL;
+ char *key;
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
- "phys_addr_base");
+ key = "phys_addr_base";
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, key);
if (!res)
return -EINVAL;
- offset = platform_get_resource_byname(pdev, IORESOURCE_MEM,
- "offset_addr");
+ key = "offset_addr";
+ offset = platform_get_resource_byname(pdev, IORESOURCE_MEM, key);
if (offset) {
/* Remap the rpm-stats pointer */
phys_ptr = ioremap_nocache(offset->start, SZ_4);
if (!phys_ptr) {
- pr_err("%s: Failed to ioremap address: %x\n",
- __func__, offset_addr);
+ pr_err("Failed to ioremap offset address\n");
return -ENODEV;
}
offset_addr = readl_relaxed(phys_ptr);
@@ -264,14 +273,33 @@
pdata->phys_addr_base = res->start + offset_addr;
pdata->phys_size = resource_size(res);
- if (pdev->dev.platform_data)
- pd = pdev->dev.platform_data;
+ key = "qcom,num-records";
+ if (of_property_read_u32(pdev->dev.of_node, key, &pdata->num_records))
+ pdata->num_records = RPM_STATS_NUM_REC;
- msm_rpmstats_create_sysfs(pdata);
+ msm_rpmstats_create_sysfs(pdev, pdata);
return 0;
}
+static int msm_rpmstats_remove(struct platform_device *pdev)
+{
+ struct msm_rpmstats_kobj_attr *rpms_ka;
+
+ if (!pdev)
+ return -EINVAL;
+
+ rpms_ka = (struct msm_rpmstats_kobj_attr *)
+ platform_get_drvdata(pdev);
+
+ sysfs_remove_file(rpms_ka->kobj, &rpms_ka->ka.attr);
+ kobject_put(rpms_ka->kobj);
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+
static const struct of_device_id rpm_stats_table[] = {
{ .compatible = "qcom,rpm-stats" },
{ },
@@ -279,6 +307,7 @@
static struct platform_driver msm_rpmstats_driver = {
.probe = msm_rpmstats_probe,
+ .remove = msm_rpmstats_remove,
.driver = {
.name = "msm_rpm_stat",
.owner = THIS_MODULE,
diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c
index 036990c..4f3c264 100644
--- a/drivers/soc/qcom/rpmh.c
+++ b/drivers/soc/qcom/rpmh.c
@@ -258,21 +258,28 @@
switch (state) {
case RPMH_ACTIVE_ONLY_STATE:
case RPMH_AWAKE_STATE:
- if (req->sleep_val != UINT_MAX)
+ if (req->sleep_val != UINT_MAX) {
req->wake_val = cmd->data;
+ rpm->dirty = true;
+ }
break;
case RPMH_WAKE_ONLY_STATE:
- req->wake_val = cmd->data;
+ if (req->wake_val != cmd->data) {
+ req->wake_val = cmd->data;
+ rpm->dirty = true;
+ }
break;
case RPMH_SLEEP_STATE:
- req->sleep_val = cmd->data;
+ if (req->sleep_val != cmd->data) {
+ req->sleep_val = cmd->data;
+ rpm->dirty = true;
+ }
break;
default:
break;
};
unlock:
- rpm->dirty = true;
spin_unlock_irqrestore(&rpm->lock, flags);
return req;
diff --git a/drivers/soc/qcom/rpmh_master_stat.c b/drivers/soc/qcom/rpmh_master_stat.c
index 3a77ed8..80589de 100644
--- a/drivers/soc/qcom/rpmh_master_stat.c
+++ b/drivers/soc/qcom/rpmh_master_stat.c
@@ -265,6 +265,7 @@
kobject_put(prvdata->kobj);
platform_set_drvdata(pdev, NULL);
iounmap(rpmh_unit_base);
+ rpmh_unit_base = NULL;
return 0;
}
diff --git a/drivers/soc/qcom/service-notifier.c b/drivers/soc/qcom/service-notifier.c
index dc45b20..eb3a3b9 100644
--- a/drivers/soc/qcom/service-notifier.c
+++ b/drivers/soc/qcom/service-notifier.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2018, 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
@@ -98,6 +98,7 @@
*/
struct qmi_client_info {
int instance_id;
+ char service_path[SERVREG_NOTIF_NAME_LENGTH];
enum pd_subsys_state subsys_state;
struct work_struct svc_arrive;
struct work_struct svc_exit;
@@ -390,7 +391,8 @@
mutex_lock(¬if_add_lock);
mutex_lock(&service_list_lock);
list_for_each_entry(service_notif, &service_list, list) {
- if (service_notif->instance_id == data->instance_id) {
+ if (service_notif->instance_id == data->instance_id && !strcmp
+ (service_notif->service_path, data->service_path)) {
enum pd_subsys_state state = ROOT_PD_UP;
rc = register_notif_listener(service_notif, data,
&curr_state);
@@ -424,7 +426,8 @@
mutex_lock(¬if_add_lock);
mutex_lock(&service_list_lock);
list_for_each_entry(service_notif, &service_list, list) {
- if (service_notif->instance_id == data->instance_id) {
+ if (service_notif->instance_id == data->instance_id && !strcmp
+ (data->service_path, service_notif->service_path)) {
rc = service_notif_queue_notification(service_notif,
SERVREG_NOTIF_SERVICE_STATE_DOWN_V01,
&state);
@@ -534,7 +537,8 @@
*/
mutex_lock(&qmi_list_lock);
list_for_each_entry(tmp, &qmi_client_list, list) {
- if (tmp->instance_id == instance_id) {
+ if (tmp->instance_id == instance_id && !strcmp
+ (tmp->service_path, service_path)) {
if (tmp->service_connected) {
rc = register_notif_listener(service_notif, tmp,
curr_state);
@@ -560,6 +564,8 @@
}
qmi_data->instance_id = instance_id;
+ strlcpy(qmi_data->service_path, service_path,
+ ARRAY_SIZE(service_notif->service_path));
init_rwsem(&qmi_data->qmi_client_handle_rwlock);
qmi_data->clnt_handle = NULL;
qmi_data->notifier.notifier_call = service_event_notify;
@@ -680,7 +686,8 @@
int rc = 0;
list_for_each_entry(tmp, &qmi_client_list, list) {
- if (tmp->instance_id == instance_id) {
+ if (tmp->instance_id == instance_id && !strcmp
+ (tmp->service_path, service_path)) {
if (tmp->service_connected) {
pr_info("Restarting service %s, instance-id %d\n",
service_path, instance_id);
diff --git a/drivers/soc/qcom/spcom.c b/drivers/soc/qcom/spcom.c
index d568014..f2597e3 100644
--- a/drivers/soc/qcom/spcom.c
+++ b/drivers/soc/qcom/spcom.c
@@ -2764,7 +2764,7 @@
ret = spcom_register_chardev();
if (ret) {
pr_err("create character device failed.\n");
- goto fail_reg_chardev;
+ goto fail_while_chardev_reg;
}
link_info.glink_link_state_notif_cb = spcom_link_state_notif_cb;
@@ -2802,6 +2802,7 @@
fail_reg_chardev:
pr_err("Failed to init driver.\n");
spcom_unregister_chrdev();
+fail_while_chardev_reg:
kfree(dev);
spcom_dev = NULL;
diff --git a/drivers/soc/qcom/system_pm.c b/drivers/soc/qcom/system_pm.c
index 1befdcf..9ef685b 100644
--- a/drivers/soc/qcom/system_pm.c
+++ b/drivers/soc/qcom/system_pm.c
@@ -106,6 +106,7 @@
.probe = sys_pm_probe,
.driver = {
.name = KBUILD_MODNAME,
+ .suppress_bind_attrs = true,
.of_match_table = sys_pm_drv_match,
},
};
diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c
index 880fda4..22884ae 100644
--- a/drivers/spi/spi-geni-qcom.c
+++ b/drivers/spi/spi-geni-qcom.c
@@ -155,6 +155,7 @@
int num_xfers;
void *ipc;
bool shared_se;
+ bool dis_autosuspend;
};
static struct spi_master *get_spi_master(struct device *dev)
@@ -747,7 +748,7 @@
static int spi_geni_prepare_transfer_hardware(struct spi_master *spi)
{
struct spi_geni_master *mas = spi_master_get_devdata(spi);
- int ret = 0;
+ int ret = 0, count = 0;
u32 max_speed = spi->cur_msg->spi->max_speed_hz;
struct se_geni_rsc *rsc = &mas->spi_rsc;
@@ -774,7 +775,12 @@
} else {
ret = 0;
}
-
+ if (mas->dis_autosuspend) {
+ count = atomic_read(&mas->dev->power.usage_count);
+ if (count <= 0)
+ GENI_SE_ERR(mas->ipc, false, NULL,
+ "resume usage count mismatch:%d", count);
+ }
if (unlikely(!mas->setup)) {
int proto = get_se_proto(mas->base);
unsigned int major;
@@ -863,6 +869,9 @@
mas->shared_se =
(geni_read_reg(mas->base, GENI_IF_FIFO_DISABLE_RO) &
FIFO_IF_DISABLE);
+ if (mas->dis_autosuspend)
+ GENI_SE_DBG(mas->ipc, false, mas->dev,
+ "Auto Suspend is disabled\n");
}
exit_prepare_transfer_hardware:
return ret;
@@ -871,7 +880,7 @@
static int spi_geni_unprepare_transfer_hardware(struct spi_master *spi)
{
struct spi_geni_master *mas = spi_master_get_devdata(spi);
-
+ int count = 0;
if (mas->shared_se) {
struct se_geni_rsc *rsc;
int ret = 0;
@@ -884,8 +893,16 @@
"%s: Error %d pinctrl_select_state\n", __func__, ret);
}
- pm_runtime_mark_last_busy(mas->dev);
- pm_runtime_put_autosuspend(mas->dev);
+ if (mas->dis_autosuspend) {
+ pm_runtime_put_sync(mas->dev);
+ count = atomic_read(&mas->dev->power.usage_count);
+ if (count < 0)
+ GENI_SE_ERR(mas->ipc, false, NULL,
+ "suspend usage count mismatch:%d", count);
+ } else {
+ pm_runtime_mark_last_busy(mas->dev);
+ pm_runtime_put_autosuspend(mas->dev);
+ }
return 0;
}
@@ -1350,6 +1367,7 @@
goto spi_geni_probe_err;
}
+ geni_mas->spi_rsc.ctrl_dev = geni_mas->dev;
rsc->geni_pinctrl = devm_pinctrl_get(&pdev->dev);
if (IS_ERR_OR_NULL(rsc->geni_pinctrl)) {
dev_err(&pdev->dev, "No pinctrl config specified!\n");
@@ -1411,7 +1429,9 @@
rt_pri = of_property_read_bool(pdev->dev.of_node, "qcom,rt");
if (rt_pri)
spi->rt = true;
-
+ geni_mas->dis_autosuspend =
+ of_property_read_bool(pdev->dev.of_node,
+ "qcom,disable-autosuspend");
geni_mas->phys_addr = res->start;
geni_mas->size = resource_size(res);
geni_mas->base = devm_ioremap(&pdev->dev, res->start,
@@ -1451,8 +1471,11 @@
init_completion(&geni_mas->tx_cb);
init_completion(&geni_mas->rx_cb);
pm_runtime_set_suspended(&pdev->dev);
- pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTO_SUSPEND_DELAY);
- pm_runtime_use_autosuspend(&pdev->dev);
+ if (!geni_mas->dis_autosuspend) {
+ pm_runtime_set_autosuspend_delay(&pdev->dev,
+ SPI_AUTO_SUSPEND_DELAY);
+ pm_runtime_use_autosuspend(&pdev->dev);
+ }
pm_runtime_enable(&pdev->dev);
ret = spi_register_master(spi);
if (ret) {
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index 2e05046..c7d3fa9 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -696,6 +696,7 @@
static const struct of_device_id spidev_dt_ids[] = {
{ .compatible = "rohm,dh2228fv" },
{ .compatible = "lineartechnology,ltc2488" },
+ { .compatible = "qcom,spi-msm-slave" },
{},
};
MODULE_DEVICE_TABLE(of, spidev_dt_ids);
diff --git a/drivers/thermal/msm-tsens.c b/drivers/thermal/msm-tsens.c
index 6241ef6..a4c89e0 100644
--- a/drivers/thermal/msm-tsens.c
+++ b/drivers/thermal/msm-tsens.c
@@ -220,6 +220,10 @@
static int tsens_tm_remove(struct platform_device *pdev)
{
+ struct tsens_device *tmdev = platform_get_drvdata(pdev);
+
+ if (tmdev)
+ list_del(&tmdev->list);
platform_set_drvdata(pdev, NULL);
return 0;
@@ -278,6 +282,7 @@
.name = "msm-tsens",
.owner = THIS_MODULE,
.of_match_table = tsens_table,
+ .suppress_bind_attrs = true,
},
};
diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c
index 4e895ee..6352d54 100644
--- a/drivers/tty/serial/msm_geni_serial.c
+++ b/drivers/tty/serial/msm_geni_serial.c
@@ -1242,56 +1242,30 @@
unsigned int xmit_size;
unsigned int fifo_width_bytes =
(uart_console(uport) ? 1 : (msm_port->tx_fifo_width >> 3));
- unsigned int geni_m_irq_en;
int temp_tail = 0;
xmit_size = uart_circ_chars_pending(xmit);
tx_fifo_status = geni_read_reg_nolog(uport->membase,
SE_GENI_TX_FIFO_STATUS);
/* Both FIFO and framework buffer are drained */
- if ((xmit_size == msm_port->xmit_size) && !tx_fifo_status) {
- /*
- * This will balance out the power vote put in during start_tx
- * allowing the device to suspend.
- */
- if (!uart_console(uport)) {
- IPC_LOG_MSG(msm_port->ipc_log_misc,
- "%s.Power Off.\n", __func__);
- msm_geni_serial_power_off(uport);
- }
- msm_port->xmit_size = 0;
- uart_circ_clear(xmit);
+ if (!xmit_size && !tx_fifo_status) {
msm_geni_serial_stop_tx(uport);
goto exit_handle_tx;
}
- xmit_size -= msm_port->xmit_size;
-
- if (!uart_console(uport)) {
- geni_m_irq_en = geni_read_reg_nolog(uport->membase,
- SE_GENI_M_IRQ_EN);
- geni_m_irq_en &= ~(M_TX_FIFO_WATERMARK_EN);
- geni_write_reg_nolog(0, uport->membase,
- SE_GENI_TX_WATERMARK_REG);
- geni_write_reg_nolog(geni_m_irq_en, uport->membase,
- SE_GENI_M_IRQ_EN);
- }
avail_fifo_bytes = (msm_port->tx_fifo_depth - msm_port->tx_wm) *
fifo_width_bytes;
- temp_tail = (xmit->tail + msm_port->xmit_size) & (UART_XMIT_SIZE - 1);
+ temp_tail = xmit->tail & (UART_XMIT_SIZE - 1);
+
if (xmit_size > (UART_XMIT_SIZE - temp_tail))
xmit_size = (UART_XMIT_SIZE - temp_tail);
if (xmit_size > avail_fifo_bytes)
xmit_size = avail_fifo_bytes;
-
if (!xmit_size)
goto exit_handle_tx;
msm_geni_serial_setup_tx(uport, xmit_size);
-
bytes_remaining = xmit_size;
- dump_ipc(msm_port->ipc_log_tx, "Tx", (char *)&xmit->buf[temp_tail], 0,
- xmit_size);
while (i < xmit_size) {
unsigned int tx_bytes;
unsigned int buf = 0;
@@ -1304,17 +1278,18 @@
buf |= (xmit->buf[temp_tail + c] << (c * 8));
geni_write_reg_nolog(buf, uport->membase, SE_GENI_TX_FIFOn);
i += tx_bytes;
- temp_tail = (temp_tail + tx_bytes) & (UART_XMIT_SIZE - 1);
- uport->icount.tx += tx_bytes;
bytes_remaining -= tx_bytes;
+ uport->icount.tx += tx_bytes;
+ temp_tail += tx_bytes;
/* Ensure FIFO write goes through */
wmb();
}
+ xmit->tail = temp_tail & (UART_XMIT_SIZE - 1);
if (uart_console(uport))
msm_geni_serial_poll_cancel_tx(uport);
- msm_port->xmit_size += xmit_size;
exit_handle_tx:
- uart_write_wakeup(uport);
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(uport);
return ret;
}
@@ -2427,6 +2402,8 @@
if (ret)
goto exit_geni_serial_probe;
+ dev_port->serial_rsc.ctrl_dev = &pdev->dev;
+
if (of_property_read_u32(pdev->dev.of_node, "qcom,wakeup-byte",
&wake_char)) {
dev_dbg(&pdev->dev, "No Wakeup byte specified\n");
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
index 876679a..f794741 100644
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -763,18 +763,21 @@
return;
if (dev->rawdescriptors) {
- for (i = 0; i < dev->descriptor.bNumConfigurations; i++)
+ for (i = 0; i < dev->descriptor.bNumConfigurations &&
+ i < USB_MAXCONFIG; i++)
kfree(dev->rawdescriptors[i]);
kfree(dev->rawdescriptors);
dev->rawdescriptors = NULL;
}
- for (c = 0; c < dev->descriptor.bNumConfigurations; c++) {
+ for (c = 0; c < dev->descriptor.bNumConfigurations &&
+ c < USB_MAXCONFIG; c++) {
struct usb_host_config *cf = &dev->config[c];
kfree(cf->string);
- for (i = 0; i < cf->desc.bNumInterfaces; i++) {
+ for (i = 0; i < cf->desc.bNumInterfaces &&
+ i < USB_MAXINTERFACES; i++) {
if (cf->intf_cache[i])
kref_put(&cf->intf_cache[i]->ref,
usb_release_interface_cache);
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index bf1baf6..2c30660 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -3748,7 +3748,6 @@
mdwc->hs_phy->flags &= ~PHY_HOST_MODE;
of_platform_depopulate(&pdev->dev);
- dbg_event(0xFF, "Remov put", 0);
pm_runtime_disable(mdwc->dev);
pm_runtime_barrier(mdwc->dev);
pm_runtime_put_sync(mdwc->dev);
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index f878b8d1..e6c89a3 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1971,7 +1971,7 @@
if (dwc3_gadget_is_suspended(dwc)) {
pr_debug("USB bus is suspended. Scheduling wakeup and returning -EAGAIN.\n");
dwc3_gadget_wakeup(&dwc->gadget);
- return -EAGAIN;
+ return -EACCES;
}
if (dwc->revision < DWC3_REVISION_220A) {
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 3de95d5..6f8a04e 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -490,11 +490,17 @@
spin_lock_irqsave(&func->config->cdev->lock, flags);
ret = usb_func_wakeup_int(func);
- if (ret == -EAGAIN) {
+ if (ret == -EACCES) {
DBG(func->config->cdev,
"Function wakeup for %s could not complete due to suspend state. Delayed until after bus resume.\n",
func->name ? func->name : "");
ret = 0;
+ func->func_wakeup_pending = 1;
+ } else if (ret == -EAGAIN) {
+ DBG(func->config->cdev,
+ "Function wakeup for %s sent.\n",
+ func->name ? func->name : "");
+ ret = 0;
} else if (ret < 0 && ret != -ENOTSUPP) {
ERROR(func->config->cdev,
"Failed to wake function %s from suspend state. ret=%d. Canceling USB request.\n",
@@ -524,7 +530,12 @@
gadget = func->config->cdev->gadget;
if (func->func_is_suspended && func->func_wakeup_allowed) {
ret = usb_gadget_func_wakeup(gadget, func->intf_id);
- if (ret == -EAGAIN) {
+ if (ret == -EACCES) {
+ pr_debug("bus suspended func wakeup for %s delayed until bus resume.\n",
+ func->name ? func->name : "");
+ func->func_wakeup_pending = 1;
+ ret = -EAGAIN;
+ } else if (ret == -EAGAIN) {
pr_debug("bus suspended func wakeup for %s delayed until bus resume.\n",
func->name ? func->name : "");
} else if (ret < 0 && ret != -ENOTSUPP) {
@@ -2471,22 +2482,24 @@
spin_lock_irqsave(&cdev->lock, flags);
if (cdev->config) {
list_for_each_entry(f, &cdev->config->functions, list) {
- ret = usb_func_wakeup_int(f);
- if (ret) {
- if (ret == -EAGAIN) {
- ERROR(f->config->cdev,
- "Function wakeup for %s could not complete due to suspend state.\n",
- f->name ? f->name : "");
- break;
- } else if (ret != -ENOTSUPP) {
- ERROR(f->config->cdev,
- "Failed to wake function %s from suspend state. ret=%d. Canceling USB request.\n",
- f->name ? f->name : "",
- ret);
+ if (f->func_wakeup_pending) {
+ ret = usb_func_wakeup_int(f);
+ if (ret) {
+ if (ret == -EAGAIN) {
+ ERROR(f->config->cdev,
+ "Function wakeup for %s could not complete due to suspend state.\n",
+ f->name ? f->name : "");
+ } else if (ret != -ENOTSUPP) {
+ ERROR(f->config->cdev,
+ "Failed to wake function %s from suspend state. ret=%d. Canceling USB request.\n",
+ f->name ? f->name : "",
+ ret);
+ }
}
+ f->func_wakeup_pending = 0;
}
- if (f->resume)
+ if (gadget->speed != USB_SPEED_SUPER && f->resume)
f->resume(f);
}
diff --git a/drivers/usb/gadget/function/f_cdev.c b/drivers/usb/gadget/function/f_cdev.c
index a7166e2..afa62e8 100644
--- a/drivers/usb/gadget/function/f_cdev.c
+++ b/drivers/usb/gadget/function/f_cdev.c
@@ -349,6 +349,23 @@
return container_of(cser, struct f_cdev, port_usb);
}
+static unsigned int convert_uart_sigs_to_acm(unsigned int uart_sig)
+{
+ unsigned int acm_sig = 0;
+
+ /* should this needs to be in calling functions ??? */
+ uart_sig &= (TIOCM_RI | TIOCM_CD | TIOCM_DSR);
+
+ if (uart_sig & TIOCM_RI)
+ acm_sig |= ACM_CTRL_RI;
+ if (uart_sig & TIOCM_CD)
+ acm_sig |= ACM_CTRL_DCD;
+ if (uart_sig & TIOCM_DSR)
+ acm_sig |= ACM_CTRL_DSR;
+
+ return acm_sig;
+}
+
static unsigned int convert_acm_sigs_to_uart(unsigned int acm_sig)
{
unsigned int uart_sig = 0;
@@ -1333,6 +1350,12 @@
if (cser->serial_state & TIOCM_RI)
result |= TIOCM_RI;
+
+ if (cser->serial_state & TIOCM_DSR)
+ result |= TIOCM_DSR;
+
+ if (cser->serial_state & TIOCM_CTS)
+ result |= TIOCM_CTS;
return result;
}
@@ -1373,6 +1396,24 @@
}
}
+ if (set & TIOCM_DSR)
+ cser->serial_state |= TIOCM_DSR;
+
+ if (clear & TIOCM_DSR)
+ cser->serial_state &= ~TIOCM_DSR;
+
+ if (set & TIOCM_CTS) {
+ if (cser->send_break) {
+ cser->serial_state |= TIOCM_CTS;
+ status = cser->send_break(cser, 0);
+ }
+ }
+ if (clear & TIOCM_CTS) {
+ if (cser->send_break) {
+ cser->serial_state &= ~TIOCM_CTS;
+ status = cser->send_break(cser, 1);
+ }
+ }
return status;
}
@@ -1423,7 +1464,9 @@
{
int temp;
struct f_cdev *port = fport;
+ struct cserial *cser;
+ cser = &port->port_usb;
if (!port) {
pr_err("port is null\n");
return;
@@ -1439,6 +1482,17 @@
port->cbits_to_modem = temp;
port->cbits_updated = true;
+ /* if DTR is high, update latest modem info to laptop */
+ if (port->cbits_to_modem & TIOCM_DTR) {
+ unsigned int result;
+ unsigned int cbits_to_laptop;
+
+ result = f_cdev_tiocmget(port);
+ cbits_to_laptop = convert_uart_sigs_to_acm(result);
+ if (cser->send_modem_ctrl_bits)
+ cser->send_modem_ctrl_bits(cser, cbits_to_laptop);
+ }
+
wake_up(&port->read_wq);
}
@@ -1488,8 +1542,10 @@
void usb_cser_disconnect(struct f_cdev *port)
{
+ struct cserial *cser;
unsigned long flags;
+ cser = &port->port_usb;
usb_cser_stop_io(port);
/* lower DTR to modem */
@@ -1497,6 +1553,7 @@
spin_lock_irqsave(&port->port_lock, flags);
port->is_connected = false;
+ cser->notify_modem = NULL;
port->nbytes_from_host = port->nbytes_to_host = 0;
port->nbytes_to_port_bridge = 0;
spin_unlock_irqrestore(&port->port_lock, flags);
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index b9c19d4..6fe4fc5 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -997,7 +997,6 @@
struct ffs_epfile *epfile = file->private_data;
struct usb_request *req;
struct ffs_ep *ep;
- struct ffs_data *ffs = epfile->ffs;
char *data = NULL;
ssize_t ret, data_len = -EINVAL;
int halt;
@@ -1096,7 +1095,7 @@
data_len = usb_ep_align_maybe(gadget, ep->ep, data_len);
spin_unlock_irq(&epfile->ffs->eps_lock);
- extra_buf_alloc = ffs->gadget->extra_buf_alloc;
+ extra_buf_alloc = gadget->extra_buf_alloc;
if (!io_data->read)
data = kmalloc(data_len + extra_buf_alloc,
GFP_KERNEL);
diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c
index 7170dc9..0c4baf2 100644
--- a/drivers/usb/gadget/function/f_gsi.c
+++ b/drivers/usb/gadget/function/f_gsi.c
@@ -24,6 +24,16 @@
module_param(qti_packet_debug, bool, 0644);
MODULE_PARM_DESC(qti_packet_debug, "Print QTI Packet's Raw Data");
+/* initial value, changed by "ifconfig usb0 hw ether xx:xx:xx:xx:xx:xx" */
+static char *gsi_dev_addr;
+module_param(gsi_dev_addr, charp, 0644);
+MODULE_PARM_DESC(gsi_dev_addr, "QC Device Ethernet Address");
+
+/* this address is invisible to ifconfig */
+static char *gsi_host_addr;
+module_param(gsi_host_addr, charp, 0644);
+MODULE_PARM_DESC(gsi_host_addr, "QC Host Ethernet Address");
+
static struct workqueue_struct *ipa_usb_wq;
static struct f_gsi *__gsi[USB_PROT_MAX];
static void *ipc_log_ctxt;
@@ -211,26 +221,23 @@
return ret;
}
-static void debugfs_rw_timer_func(unsigned long arg)
+static void gsi_rw_timer_func(unsigned long arg)
{
- struct f_gsi *gsi;
-
- gsi = (struct f_gsi *)arg;
+ struct f_gsi *gsi = (struct f_gsi *)arg;
if (!atomic_read(&gsi->connected)) {
- log_event_dbg("%s: gsi not connected..del timer\n", __func__);
- gsi->debugfs_rw_enable = 0;
- del_timer(&gsi->debugfs_rw_timer);
+ log_event_dbg("%s: gsi not connected.. bail-out\n", __func__);
+ gsi->debugfs_rw_timer_enable = 0;
return;
}
log_event_dbg("%s: calling gsi_wakeup_host\n", __func__);
gsi_wakeup_host(gsi);
- if (gsi->debugfs_rw_enable) {
+ if (gsi->debugfs_rw_timer_enable) {
log_event_dbg("%s: re-arm the timer\n", __func__);
- mod_timer(&gsi->debugfs_rw_timer,
- jiffies + msecs_to_jiffies(gsi->debugfs_rw_interval));
+ mod_timer(&gsi->gsi_rw_timer,
+ jiffies + msecs_to_jiffies(gsi->gsi_rw_timer_interval));
}
}
@@ -279,7 +286,7 @@
goto err;
}
- if (gsi->debugfs_rw_enable == !!input) {
+ if (gsi->debugfs_rw_timer_enable == !!input) {
if (!!input)
log_event_dbg("%s: RW already enabled\n", __func__);
else
@@ -287,21 +294,14 @@
goto err;
}
- gsi->debugfs_rw_enable = !!input;
- if (gsi->debugfs_rw_enable) {
- init_timer(&gsi->debugfs_rw_timer);
- gsi->debugfs_rw_timer.data = (unsigned long) gsi;
- gsi->debugfs_rw_timer.function = debugfs_rw_timer_func;
+ gsi->debugfs_rw_timer_enable = !!input;
- /* Use default remote wakeup timer interval if it is not set */
- if (!gsi->debugfs_rw_interval)
- gsi->debugfs_rw_interval = DEFAULT_RW_TIMER_INTERVAL;
- gsi->debugfs_rw_timer.expires = jiffies +
- msecs_to_jiffies(gsi->debugfs_rw_interval);
- add_timer(&gsi->debugfs_rw_timer);
+ if (gsi->debugfs_rw_timer_enable) {
+ mod_timer(&gsi->gsi_rw_timer, jiffies +
+ msecs_to_jiffies(gsi->gsi_rw_timer_interval));
log_event_dbg("%s: timer initialized\n", __func__);
} else {
- del_timer_sync(&gsi->debugfs_rw_timer);
+ del_timer_sync(&gsi->gsi_rw_timer);
log_event_dbg("%s: timer deleted\n", __func__);
}
@@ -320,7 +320,7 @@
return 0;
}
- seq_printf(s, "%d\n", gsi->debugfs_rw_enable);
+ seq_printf(s, "%d\n", gsi->debugfs_rw_timer_enable);
return 0;
}
@@ -368,7 +368,7 @@
goto err;
}
- gsi->debugfs_rw_interval = timer_val;
+ gsi->gsi_rw_timer_interval = timer_val;
err:
return count;
}
@@ -376,7 +376,6 @@
static int usb_gsi_rw_timer_show(struct seq_file *s, void *unused)
{
struct f_gsi *gsi;
- unsigned int timer_interval;
gsi = get_connected_gsi();
if (!gsi) {
@@ -384,11 +383,7 @@
return 0;
}
- timer_interval = DEFAULT_RW_TIMER_INTERVAL;
- if (gsi->debugfs_rw_interval)
- timer_interval = gsi->debugfs_rw_interval;
-
- seq_printf(s, "%ums\n", timer_interval);
+ seq_printf(s, "%ums\n", gsi->gsi_rw_timer_interval);
return 0;
}
@@ -2435,6 +2430,9 @@
atomic_set(&gsi->connected, 0);
+ del_timer(&gsi->gsi_rw_timer);
+ gsi->debugfs_rw_timer_enable = 0;
+
if (gsi->prot_id == USB_PROT_RNDIS_IPA)
rndis_uninit(gsi->params);
@@ -2505,6 +2503,16 @@
post_event(&gsi->d_port, EVT_SUSPEND);
queue_work(gsi->d_port.ipa_usb_wq, &gsi->d_port.usb_ipa_w);
log_event_dbg("gsi suspended");
+
+ /*
+ * If host suspended bus without receiving notification request then
+ * initiate remote-wakeup. As driver won't be able to do it later since
+ * notification request is already queued.
+ */
+ if (gsi->c_port.notify_req_queued && usb_gsi_remote_wakeup_allowed(f)) {
+ mod_timer(&gsi->gsi_rw_timer, jiffies + msecs_to_jiffies(2000));
+ log_event_dbg("%s: pending response, arm rw_timer\n", __func__);
+ }
}
static void gsi_resume(struct usb_function *f)
@@ -2522,6 +2530,10 @@
f->func_is_suspended)
return;
+ /* Keep timer enabled if user enabled using debugfs */
+ if (!gsi->debugfs_rw_timer_enable)
+ del_timer(&gsi->gsi_rw_timer);
+
if (gsi->c_port.notify && !gsi->c_port.notify->desc)
config_ep_by_speed(cdev->gadget, f, gsi->c_port.notify);
@@ -2553,6 +2565,11 @@
static int gsi_get_status(struct usb_function *f)
{
unsigned int remote_wakeup_en_status = f->func_wakeup_allowed ? 1 : 0;
+ struct f_gsi *gsi = func_to_gsi(f);
+
+ /* Disable function remote wake-up for DPL interface */
+ if (gsi->prot_id == USB_PROT_DIAG_IPA)
+ return 0;
return (remote_wakeup_en_status << FUNC_WAKEUP_ENABLE_SHIFT) |
(1 << FUNC_WAKEUP_CAPABLE_SHIFT);
@@ -2595,10 +2612,6 @@
struct usb_function *f = &gsi->function;
int status;
- /* maybe allocate device-global string IDs */
- if (info->string_defs[0].id != 0)
- goto skip_string_id_alloc;
-
if (info->ctrl_str_idx >= 0 && info->ctrl_desc) {
/* ctrl interface label */
status = usb_string_id(cdev);
@@ -2635,7 +2648,6 @@
info->cdc_eth_desc->iMACAddress = status;
}
-skip_string_id_alloc:
if (info->ctrl_desc)
info->ctrl_desc->bInterfaceNumber = gsi->ctrl_id;
@@ -2812,6 +2824,26 @@
wake_up_interruptible(&gsi->d_port.wait_for_ipa_ready);
}
+static void gsi_get_ether_addr(const char *str, u8 *dev_addr)
+{
+ if (str) {
+ unsigned int i;
+
+ for (i = 0; i < ETH_ALEN; i++) {
+ unsigned char num;
+
+ if ((*str == '.') || (*str == ':'))
+ str++;
+ num = hex_to_bin(*str++) << 4;
+ num |= hex_to_bin(*str++);
+ dev_addr[i] = num;
+ }
+ if (is_valid_ether_addr(dev_addr))
+ return;
+ }
+ random_ether_addr(dev_addr);
+}
+
static int gsi_bind(struct usb_configuration *c, struct usb_function *f)
{
struct usb_composite_dev *cdev = c->cdev;
@@ -2819,6 +2851,7 @@
struct f_gsi *gsi = func_to_gsi(f);
struct rndis_params *params;
struct net_device *net;
+ struct gsi_opts *opts;
char *name = NULL;
int status;
__u8 class;
@@ -2884,11 +2917,15 @@
rndis_set_param_medium(gsi->params, RNDIS_MEDIUM_802_3, 0);
/* export host's Ethernet address in CDC format */
- random_ether_addr(gsi->d_port.ipa_init_params.device_ethaddr);
- random_ether_addr(gsi->d_port.ipa_init_params.host_ethaddr);
+ gsi_get_ether_addr(gsi_dev_addr,
+ gsi->d_port.ipa_init_params.device_ethaddr);
+
+ gsi_get_ether_addr(gsi_host_addr,
+ gsi->d_port.ipa_init_params.host_ethaddr);
+
log_event_dbg("setting host_ethaddr=%pM, device_ethaddr = %pM",
- gsi->d_port.ipa_init_params.host_ethaddr,
- gsi->d_port.ipa_init_params.device_ethaddr);
+ gsi->d_port.ipa_init_params.host_ethaddr,
+ gsi->d_port.ipa_init_params.device_ethaddr);
memcpy(gsi->ethaddr, &gsi->d_port.ipa_init_params.host_ethaddr,
ETH_ALEN);
rndis_set_host_mac(gsi->params, gsi->ethaddr);
@@ -3022,18 +3059,15 @@
info.notify_buf_len = sizeof(struct usb_cdc_notification);
mbim_gsi_desc.wMaxSegmentSize = cpu_to_le16(0x800);
- /*
- * If MBIM is bound in a config other than the first, tell
- * Windows about it by returning the num as a string in the
- * OS descriptor's subCompatibleID field. Windows only supports
- * up to config #4.
- */
- if (c->bConfigurationValue >= 2 &&
- c->bConfigurationValue <= 4) {
- log_event_dbg("MBIM in configuration %d",
- c->bConfigurationValue);
- mbim_gsi_ext_config_desc.function.subCompatibleID[0] =
- c->bConfigurationValue + '0';
+ if (cdev->use_os_string) {
+ f->os_desc_table = kzalloc(sizeof(*f->os_desc_table),
+ GFP_KERNEL);
+ if (!f->os_desc_table)
+ return -ENOMEM;
+ opts = container_of(f->fi, struct gsi_opts, func_inst);
+ f->os_desc_n = 1;
+ f->os_desc_table[0].os_desc = &opts->os_desc;
+ f->os_desc_table[0].if_id = gsi->data_id;
}
break;
case USB_PROT_RMNET_IPA:
@@ -3097,11 +3131,15 @@
info.notify_buf_len = GSI_CTRL_NOTIFY_BUFF_LEN;
/* export host's Ethernet address in CDC format */
- random_ether_addr(gsi->d_port.ipa_init_params.device_ethaddr);
- random_ether_addr(gsi->d_port.ipa_init_params.host_ethaddr);
+ gsi_get_ether_addr(gsi_dev_addr,
+ gsi->d_port.ipa_init_params.device_ethaddr);
+
+ gsi_get_ether_addr(gsi_host_addr,
+ gsi->d_port.ipa_init_params.host_ethaddr);
+
log_event_dbg("setting host_ethaddr=%pM, device_ethaddr = %pM",
- gsi->d_port.ipa_init_params.host_ethaddr,
- gsi->d_port.ipa_init_params.device_ethaddr);
+ gsi->d_port.ipa_init_params.host_ethaddr,
+ gsi->d_port.ipa_init_params.device_ethaddr);
snprintf(gsi->ethaddr, sizeof(gsi->ethaddr),
"%02X%02X%02X%02X%02X%02X",
@@ -3219,6 +3257,7 @@
dereg_rndis:
rndis_deregister(gsi->params);
+ kfree(f->os_desc_table);
fail:
return status;
}
@@ -3250,8 +3289,11 @@
rndis_deregister(gsi->params);
}
- if (gsi->prot_id == USB_PROT_MBIM_IPA)
- mbim_gsi_ext_config_desc.function.subCompatibleID[0] = 0;
+ if (gsi->prot_id == USB_PROT_MBIM_IPA) {
+ kfree(f->os_desc_table);
+ f->os_desc_table = NULL;
+ f->os_desc_n = 0;
+ }
if (gadget_is_superspeed(c->cdev->gadget)) {
usb_free_descriptors(f->ss_descriptors);
@@ -3354,6 +3396,9 @@
gsi->d_port.ipa_usb_wq = ipa_usb_wq;
+ gsi->gsi_rw_timer_interval = DEFAULT_RW_TIMER_INTERVAL;
+ setup_timer(&gsi->gsi_rw_timer, gsi_rw_timer_func, (unsigned long) gsi);
+
return gsi;
}
@@ -3571,6 +3616,8 @@
int name_len, prot_id, ret = 0;
struct gsi_opts *opts;
struct f_gsi *gsi;
+ struct usb_os_desc *descs[1];
+ char *names[1];
opts = container_of(fi, struct gsi_opts, func_inst);
@@ -3588,6 +3635,15 @@
if (prot_id == USB_PROT_RNDIS_IPA)
config_group_init_type_name(&opts->func_inst.group, "",
&gsi_func_rndis_type);
+ if (prot_id == IPA_USB_MBIM) {
+ opts->os_desc.ext_compat_id = opts->ext_compat_id;
+ INIT_LIST_HEAD(&opts->os_desc.ext_prop);
+ descs[0] = &opts->os_desc;
+ names[0] = "MBIM";
+ opts->interf_group = usb_os_desc_prepare_interf_dir(
+ &opts->func_inst.group, 1,
+ descs, names, THIS_MODULE);
+ }
gsi = opts->gsi = __gsi[prot_id];
opts->gsi->prot_id = prot_id;
@@ -3602,8 +3658,11 @@
{
struct gsi_opts *opts = container_of(f, struct gsi_opts, func_inst);
- if (opts && opts->gsi && opts->gsi->c_port.ctrl_device.fops)
- misc_deregister(&opts->gsi->c_port.ctrl_device);
+ if (opts) {
+ if (opts->gsi && opts->gsi->c_port.ctrl_device.fops)
+ misc_deregister(&opts->gsi->c_port.ctrl_device);
+ kfree(opts->interf_group);
+ }
kfree(opts);
}
diff --git a/drivers/usb/gadget/function/f_gsi.h b/drivers/usb/gadget/function/f_gsi.h
index cd146a0..5231213 100644
--- a/drivers/usb/gadget/function/f_gsi.h
+++ b/drivers/usb/gadget/function/f_gsi.h
@@ -29,6 +29,7 @@
#include <linux/timer.h>
#include "u_ether.h"
+#include "configfs.h"
#define GSI_RMNET_CTRL_NAME "rmnet_ctrl"
#define GSI_MBIM_CTRL_NAME "android_mbim"
@@ -278,10 +279,12 @@
struct gsi_data_port d_port;
struct gsi_ctrl_port c_port;
bool rmnet_dtr_status;
+
/* To test remote wakeup using debugfs */
- struct timer_list debugfs_rw_timer;
- u8 debugfs_rw_enable;
- u16 debugfs_rw_interval;
+ struct timer_list gsi_rw_timer;
+ u8 debugfs_rw_timer_enable;
+ u16 gsi_rw_timer_interval;
+
bool host_supports_flow_control;
};
@@ -306,6 +309,11 @@
struct gsi_opts {
struct usb_function_instance func_inst;
struct f_gsi *gsi;
+
+ /* os desc support */
+ struct config_group *interf_group;
+ char ext_compat_id[16];
+ struct usb_os_desc os_desc;
};
static inline struct gsi_opts *to_gsi_opts(struct config_item *item)
@@ -1057,50 +1065,6 @@
NULL,
};
-/* Microsoft OS Descriptors */
-
-/*
- * We specify our own bMS_VendorCode byte which Windows will use
- * as the bRequest value in subsequent device get requests.
- */
-#define MBIM_VENDOR_CODE 0xA5
-
-/* Microsoft Extended Configuration Descriptor Header Section */
-struct mbim_gsi_ext_config_desc_header {
- __le32 dwLength;
- __u16 bcdVersion;
- __le16 wIndex;
- __u8 bCount;
- __u8 reserved[7];
-};
-
-/* Microsoft Extended Configuration Descriptor Function Section */
-struct mbim_gsi_ext_config_desc_function {
- __u8 bFirstInterfaceNumber;
- __u8 bInterfaceCount;
- __u8 compatibleID[8];
- __u8 subCompatibleID[8];
- __u8 reserved[6];
-};
-
-/* Microsoft Extended Configuration Descriptor */
-static struct {
- struct mbim_gsi_ext_config_desc_header header;
- struct mbim_gsi_ext_config_desc_function function;
-} mbim_gsi_ext_config_desc = {
- .header = {
- .dwLength = cpu_to_le32(sizeof(mbim_gsi_ext_config_desc)),
- .bcdVersion = cpu_to_le16(0x0100),
- .wIndex = cpu_to_le16(4),
- .bCount = 1,
- },
- .function = {
- .bFirstInterfaceNumber = 0,
- .bInterfaceCount = 1,
- .compatibleID = { 'A', 'L', 'T', 'R', 'C', 'F', 'G' },
- /* .subCompatibleID = DYNAMIC */
- },
-};
/* ecm device descriptors */
#define ECM_QC_LOG2_STATUS_INTERVAL_MSEC 5
#define ECM_QC_STATUS_BYTECOUNT 16 /* 8 byte header + data */
diff --git a/drivers/usb/gadget/function/f_ncm.c b/drivers/usb/gadget/function/f_ncm.c
index 6f3b623..373c31a 100644
--- a/drivers/usb/gadget/function/f_ncm.c
+++ b/drivers/usb/gadget/function/f_ncm.c
@@ -1634,7 +1634,8 @@
{
int value = -EOPNOTSUPP;
- if (ctrl->bRequestType == 0x40 && ctrl->bRequest == 0xF0) {
+ if (ctrl->bRequestType == 0x40 && ctrl->bRequest == 0xF0
+ && _ncm_setup_desc) {
_ncm_setup_desc->minor = (uint8_t)(ctrl->wValue >> 8);
_ncm_setup_desc->major = (uint8_t)(ctrl->wValue & 0xFF);
schedule_work(&_ncm_setup_desc->work);
diff --git a/drivers/usb/gadget/function/u_serial.c b/drivers/usb/gadget/function/u_serial.c
index 2ec28c8..22a6755 100644
--- a/drivers/usb/gadget/function/u_serial.c
+++ b/drivers/usb/gadget/function/u_serial.c
@@ -1305,10 +1305,14 @@
}
tty_port_init(&port->port);
+ tty_buffer_set_limit(&port->port, 8388608);
spin_lock_init(&port->port_lock);
init_waitqueue_head(&port->drain_wait);
init_waitqueue_head(&port->close_wait);
+ pr_debug("%s open:ttyGS%d and set 8388608, avail:%d\n", __func__,
+ port_num, tty_buffer_space_avail(&port->port));
+
tasklet_init(&port->push, gs_rx_push, (unsigned long) port);
INIT_LIST_HEAD(&port->read_pool);
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 9cba037..ccad0be 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -3661,6 +3661,7 @@
del_timer_sync(&virt_dev->eps[i].stop_cmd_timer);
}
+ virt_dev->udev = NULL;
spin_lock_irqsave(&xhci->lock, flags);
/* Don't disable the slot if the host controller is dead. */
state = readl(&xhci->op_regs->status);
diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c
index 6685f05..2c0c0ed 100644
--- a/drivers/usb/pd/policy_engine.c
+++ b/drivers/usb/pd/policy_engine.c
@@ -374,7 +374,6 @@
struct rx_msg *rx_ext_msg;
u32 received_pdos[PD_MAX_DATA_OBJ];
- u32 received_ado;
u16 src_cap_id;
u8 selected_pdo;
u8 requested_pdo;
@@ -443,6 +442,7 @@
u8 src_cap_ext_db[PD_SRC_CAP_EXT_DB_LEN];
bool send_get_pps_status;
u32 pps_status_db;
+ bool send_get_status;
u8 status_db[PD_STATUS_DB_LEN];
bool send_get_battery_cap;
u8 get_battery_cap_db;
@@ -2252,7 +2252,7 @@
pd->send_pr_swap = false;
ret = pd_send_msg(pd, MSG_PR_SWAP, NULL, 0, SOP_MSG);
if (ret) {
- dev_err(&pd->dev, "Error sending PR Swap\n");
+ usbpd_err(&pd->dev, "Error sending PR Swap\n");
usbpd_set_state(pd, PE_SRC_SEND_SOFT_RESET);
break;
}
@@ -2263,7 +2263,7 @@
pd->send_dr_swap = false;
ret = pd_send_msg(pd, MSG_DR_SWAP, NULL, 0, SOP_MSG);
if (ret) {
- dev_err(&pd->dev, "Error sending DR Swap\n");
+ usbpd_err(&pd->dev, "Error sending DR Swap\n");
usbpd_set_state(pd, PE_SRC_SEND_SOFT_RESET);
break;
}
@@ -2552,8 +2552,7 @@
ret = pd_send_msg(pd, MSG_GET_SOURCE_CAP_EXTENDED, NULL,
0, SOP_MSG);
if (ret) {
- dev_err(&pd->dev,
- "Error sending get_src_cap_ext\n");
+ usbpd_err(&pd->dev, "Error sending get_src_cap_ext\n");
usbpd_set_state(pd, PE_SNK_SEND_SOFT_RESET);
break;
}
@@ -2572,8 +2571,7 @@
ret = pd_send_msg(pd, MSG_GET_PPS_STATUS, NULL,
0, SOP_MSG);
if (ret) {
- dev_err(&pd->dev,
- "Error sending get_pps_status\n");
+ usbpd_err(&pd->dev, "Error sending get_pps_status\n");
usbpd_set_state(pd, PE_SNK_SEND_SOFT_RESET);
break;
}
@@ -2588,23 +2586,32 @@
sizeof(pd->pps_status_db));
complete(&pd->is_ready);
} else if (IS_DATA(rx_msg, MSG_ALERT)) {
- if (rx_msg->data_len != sizeof(pd->received_ado)) {
+ u32 ado;
+
+ if (rx_msg->data_len != sizeof(ado)) {
usbpd_err(&pd->dev, "Invalid ado\n");
break;
}
- memcpy(&pd->received_ado, rx_msg->payload,
- sizeof(pd->received_ado));
- ret = pd_send_msg(pd, MSG_GET_STATUS, NULL,
- 0, SOP_MSG);
+ memcpy(&ado, rx_msg->payload, sizeof(ado));
+ usbpd_dbg(&pd->dev, "Received Alert 0x%08x\n", ado);
+
+ /*
+ * Don't send Get_Status right away so we can coalesce
+ * multiple Alerts. 150ms should be enough to not get
+ * in the way of any other AMS that might happen.
+ */
+ pd->send_get_status = true;
+ kick_sm(pd, 150);
+ } else if (pd->send_get_status && is_sink_tx_ok(pd)) {
+ pd->send_get_status = false;
+ ret = pd_send_msg(pd, MSG_GET_STATUS, NULL, 0, SOP_MSG);
if (ret) {
- dev_err(&pd->dev,
- "Error sending get_status\n");
+ usbpd_err(&pd->dev, "Error sending get_status\n");
usbpd_set_state(pd, PE_SNK_SEND_SOFT_RESET);
break;
}
kick_sm(pd, SENDER_RESPONSE_TIME);
- } else if (rx_msg &&
- IS_EXT(rx_msg, MSG_STATUS)) {
+ } else if (rx_msg && IS_EXT(rx_msg, MSG_STATUS)) {
if (rx_msg->data_len != PD_STATUS_DB_LEN) {
usbpd_err(&pd->dev, "Invalid status db\n");
break;
@@ -2617,8 +2624,7 @@
ret = pd_send_ext_msg(pd, MSG_GET_BATTERY_CAP,
&pd->get_battery_cap_db, 1, SOP_MSG);
if (ret) {
- dev_err(&pd->dev,
- "Error sending get_battery_cap\n");
+ usbpd_err(&pd->dev, "Error sending get_battery_cap\n");
usbpd_set_state(pd, PE_SNK_SEND_SOFT_RESET);
break;
}
@@ -2637,8 +2643,7 @@
ret = pd_send_ext_msg(pd, MSG_GET_BATTERY_STATUS,
&pd->get_battery_status_db, 1, SOP_MSG);
if (ret) {
- dev_err(&pd->dev,
- "Error sending get_battery_status\n");
+ usbpd_err(&pd->dev, "Error sending get_battery_status\n");
usbpd_set_state(pd, PE_SNK_SEND_SOFT_RESET);
break;
}
@@ -2668,7 +2673,7 @@
pd->send_pr_swap = false;
ret = pd_send_msg(pd, MSG_PR_SWAP, NULL, 0, SOP_MSG);
if (ret) {
- dev_err(&pd->dev, "Error sending PR Swap\n");
+ usbpd_err(&pd->dev, "Error sending PR Swap\n");
usbpd_set_state(pd, PE_SNK_SEND_SOFT_RESET);
break;
}
@@ -2679,7 +2684,7 @@
pd->send_dr_swap = false;
ret = pd_send_msg(pd, MSG_DR_SWAP, NULL, 0, SOP_MSG);
if (ret) {
- dev_err(&pd->dev, "Error sending DR Swap\n");
+ usbpd_err(&pd->dev, "Error sending DR Swap\n");
usbpd_set_state(pd, PE_SNK_SEND_SOFT_RESET);
break;
}
@@ -3297,9 +3302,9 @@
"explicit" : "implicit");
add_uevent_var(env, "ALT_MODE=%d", pd->vdm_state == MODE_ENTERED);
- add_uevent_var(env, "ADO=%08x", pd->received_ado);
- for (i = 0; i < PD_STATUS_DB_LEN; i++)
- add_uevent_var(env, "SDB%d=%08x", i, pd->status_db[i]);
+ add_uevent_var(env, "SDB=%02x %02x %02x %02x %02x", pd->status_db[0],
+ pd->status_db[1], pd->status_db[2], pd->status_db[3],
+ pd->status_db[4]);
return 0;
}
@@ -3690,12 +3695,40 @@
return ret;
for (i = 0; i < PD_SRC_CAP_EXT_DB_LEN; i++)
- len += snprintf(buf + len, PAGE_SIZE - len, "%d\n",
- pd->src_cap_ext_db[i]);
+ len += snprintf(buf + len, PAGE_SIZE - len, "%s0x%02x",
+ i ? " " : "", pd->src_cap_ext_db[i]);
+
+ buf[len++] = '\n';
+ buf[len] = '\0';
+
return len;
}
static DEVICE_ATTR_RO(get_src_cap_ext);
+static ssize_t get_status_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int i, ret, len = 0;
+ struct usbpd *pd = dev_get_drvdata(dev);
+
+ if (pd->spec_rev == USBPD_REV_20)
+ return -EINVAL;
+
+ ret = trigger_tx_msg(pd, &pd->send_get_status);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < PD_STATUS_DB_LEN; i++)
+ len += snprintf(buf + len, PAGE_SIZE - len, "%s0x%02x",
+ i ? " " : "", pd->status_db[i]);
+
+ buf[len++] = '\n';
+ buf[len] = '\0';
+
+ return len;
+}
+static DEVICE_ATTR_RO(get_status);
+
static ssize_t get_pps_status_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -3709,20 +3742,10 @@
if (ret)
return ret;
- return snprintf(buf, PAGE_SIZE, "%d\n", pd->pps_status_db);
+ return snprintf(buf, PAGE_SIZE, "0x%08x\n", pd->pps_status_db);
}
static DEVICE_ATTR_RO(get_pps_status);
-static ssize_t rx_ado_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct usbpd *pd = dev_get_drvdata(dev);
-
- /* dump the ADO as a hex string */
- return snprintf(buf, PAGE_SIZE, "%08x\n", pd->received_ado);
-}
-static DEVICE_ATTR_RO(rx_ado);
-
static ssize_t get_battery_cap_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
@@ -3751,8 +3774,12 @@
return -EINVAL;
for (i = 0; i < PD_BATTERY_CAP_DB_LEN; i++)
- len += snprintf(buf + len, PAGE_SIZE - len, "%d\n",
- pd->battery_cap_db[i]);
+ len += snprintf(buf + len, PAGE_SIZE - len, "%s0x%02x",
+ i ? " " : "", pd->battery_cap_db[i]);
+
+ buf[len++] = '\n';
+ buf[len] = '\0';
+
return len;
}
static DEVICE_ATTR_RW(get_battery_cap);
@@ -3783,7 +3810,7 @@
if (pd->get_battery_status_db == -EINVAL)
return -EINVAL;
- return snprintf(buf, PAGE_SIZE, "%d\n", pd->battery_sts_dobj);
+ return snprintf(buf, PAGE_SIZE, "0x%08x\n", pd->battery_sts_dobj);
}
static DEVICE_ATTR_RW(get_battery_status);
@@ -3807,8 +3834,8 @@
&dev_attr_rdo_h.attr,
&dev_attr_hard_reset.attr,
&dev_attr_get_src_cap_ext.attr,
+ &dev_attr_get_status.attr,
&dev_attr_get_pps_status.attr,
- &dev_attr_rx_ado.attr,
&dev_attr_get_battery_cap.attr,
&dev_attr_get_battery_status.attr,
NULL,
diff --git a/drivers/usb/pd/qpnp-pdphy.c b/drivers/usb/pd/qpnp-pdphy.c
index 2997976..a1b8a32 100644
--- a/drivers/usb/pd/qpnp-pdphy.c
+++ b/drivers/usb/pd/qpnp-pdphy.c
@@ -50,7 +50,7 @@
#define TX_SIZE_MASK 0xF
#define USB_PDPHY_TX_CONTROL 0x44
-#define TX_CONTROL_RETRY_COUNT (BIT(6) | BIT(5))
+#define TX_CONTROL_RETRY_COUNT(n) (((n) & 0x3) << 5)
#define TX_CONTROL_FRAME_TYPE (BIT(4) | BIT(3) | BIT(2))
#define TX_CONTROL_FRAME_TYPE_CABLE_RESET (0x1 << 2)
#define TX_CONTROL_SEND_SIGNAL BIT(1)
@@ -80,6 +80,9 @@
#define VDD_PDPHY_VOL_MAX 3088000 /* uV */
#define VDD_PDPHY_HPM_LOAD 3000 /* uA */
+/* Message Spec Rev field */
+#define PD_MSG_HDR_REV(hdr) (((hdr) >> 6) & 3)
+
/* timers */
#define RECEIVER_RESPONSE_TIME 15 /* tReceiverResponse */
#define HARD_RESET_COMPLETE_TIME 5 /* tHardResetComplete */
@@ -437,12 +440,12 @@
if (ret)
return ret;
- ret = wait_event_interruptible_timeout(pdphy->tx_waitq,
+ ret = wait_event_interruptible_hrtimeout(pdphy->tx_waitq,
pdphy->tx_status != -EINPROGRESS,
- msecs_to_jiffies(HARD_RESET_COMPLETE_TIME));
- if (ret <= 0) {
+ ms_to_ktime(HARD_RESET_COMPLETE_TIME));
+ if (ret) {
dev_err(pdphy->dev, "%s: failed ret %d", __func__, ret);
- return ret ? ret : -ETIMEDOUT;
+ return ret;
}
ret = pdphy_reg_write(pdphy, USB_PDPHY_TX_CONTROL, 0);
@@ -520,18 +523,24 @@
usleep_range(2, 3);
- val = TX_CONTROL_RETRY_COUNT | (sop << 2) | TX_CONTROL_SEND_MSG;
+ val = (sop << 2) | TX_CONTROL_SEND_MSG;
+
+ /* nRetryCount == 2 for PD 3.0, 3 for PD 2.0 */
+ if (PD_MSG_HDR_REV(hdr) == USBPD_REV_30)
+ val |= TX_CONTROL_RETRY_COUNT(2);
+ else
+ val |= TX_CONTROL_RETRY_COUNT(3);
ret = pdphy_reg_write(pdphy, USB_PDPHY_TX_CONTROL, val);
if (ret)
return ret;
- ret = wait_event_interruptible_timeout(pdphy->tx_waitq,
+ ret = wait_event_interruptible_hrtimeout(pdphy->tx_waitq,
pdphy->tx_status != -EINPROGRESS,
- msecs_to_jiffies(RECEIVER_RESPONSE_TIME));
- if (ret <= 0) {
+ ms_to_ktime(RECEIVER_RESPONSE_TIME));
+ if (ret) {
dev_err(pdphy->dev, "%s: failed ret %d", __func__, ret);
- return ret ? ret : -ETIMEDOUT;
+ return ret;
}
if (hdr && !pdphy->tx_status)
diff --git a/drivers/usb/phy/phy-msm-snps-hs.c b/drivers/usb/phy/phy-msm-snps-hs.c
index 28a9bf1..558a8aa 100644
--- a/drivers/usb/phy/phy-msm-snps-hs.c
+++ b/drivers/usb/phy/phy-msm-snps-hs.c
@@ -682,9 +682,6 @@
msm_hsphy_enable_clocks(phy, false);
msm_hsphy_enable_power(phy, false);
-
- kfree(phy);
-
return 0;
}
diff --git a/drivers/usb/phy/phy-msm-ssusb-qmp.c b/drivers/usb/phy/phy-msm-ssusb-qmp.c
index 1795d24..5b734be 100644
--- a/drivers/usb/phy/phy-msm-ssusb-qmp.c
+++ b/drivers/usb/phy/phy-msm-ssusb-qmp.c
@@ -1081,7 +1081,6 @@
usb_remove_phy(&phy->phy);
msm_ssphy_qmp_enable_clks(phy, false);
msm_ssusb_qmp_ldo_enable(phy, 0);
- kfree(phy);
return 0;
}
diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c
index b8f4907..44c917d 100644
--- a/drivers/usb/phy/phy-msm-usb.c
+++ b/drivers/usb/phy/phy-msm-usb.c
@@ -35,6 +35,7 @@
#include <linux/pm_wakeup.h>
#include <linux/reset.h>
#include <linux/extcon.h>
+#include <linux/power_supply.h>
#include <soc/qcom/scm.h>
#include <linux/usb.h>
@@ -1688,6 +1689,8 @@
}
disable_irq(motg->irq);
+ if (motg->phy_irq)
+ disable_irq(motg->phy_irq);
pm_stay_awake(&motg->pdev->dev);
/*
@@ -1806,6 +1809,8 @@
enable_irq(motg->async_int);
motg->async_int = 0;
}
+ if (motg->phy_irq)
+ enable_irq(motg->phy_irq);
enable_irq(motg->irq);
/* Enable ASYNC_IRQ only during LPM */
@@ -2837,11 +2842,11 @@
msm_otg_start_peripheral(otg, 0);
msm_otg_dbg_log_event(phy, "RT PM: B_PERI A PUT",
get_pm_runtime_counter(dev), 0);
+ /* Schedule work to finish cable disconnect processing*/
+ otg->state = OTG_STATE_B_IDLE;
/* _put for _get done on cable connect in B_IDLE */
pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
- /* Schedule work to finish cable disconnect processing*/
- otg->state = OTG_STATE_B_IDLE;
work = 1;
} else if (test_bit(A_BUS_SUSPEND, &motg->inputs)) {
pr_debug("a_bus_suspend\n");
@@ -3717,6 +3722,46 @@
return ret;
}
+static void msm_otg_handle_initial_extcon(struct msm_otg *motg)
+{
+ if (motg->extcon_vbus && extcon_get_cable_state_(motg->extcon_vbus,
+ EXTCON_USB))
+ msm_otg_vbus_notifier(&motg->vbus_nb, true, motg->extcon_vbus);
+
+ if (motg->extcon_id && extcon_get_cable_state_(motg->extcon_id,
+ EXTCON_USB_HOST))
+ msm_otg_id_notifier(&motg->id_nb, true, motg->extcon_id);
+}
+
+static void msm_otg_extcon_register_work(struct work_struct *w)
+{
+ struct msm_otg *motg = container_of(w, struct msm_otg,
+ extcon_register_work);
+
+ power_supply_unreg_notifier(&motg->psy_nb);
+
+ if (msm_otg_extcon_register(motg)) {
+ dev_err(&motg->pdev->dev, "failed to register extcon\n");
+ return;
+ }
+
+ msm_otg_handle_initial_extcon(motg);
+}
+
+static int msm_otg_psy_changed(struct notifier_block *nb, unsigned long evt,
+ void *ptr)
+{
+ struct msm_otg *motg = container_of(nb, struct msm_otg, psy_nb);
+
+ if (strcmp(((struct power_supply *)ptr)->desc->name, "usb") ||
+ evt != PSY_EVENT_PROP_CHANGED)
+ return 0;
+
+ queue_work(motg->otg_wq, &motg->extcon_register_work);
+
+ return 0;
+}
+
struct msm_otg_platform_data *msm_otg_dt_to_pdata(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
@@ -4266,6 +4311,7 @@
INIT_DELAYED_WORK(&motg->perf_vote_work, msm_otg_perf_vote_work);
INIT_DELAYED_WORK(&motg->sdp_check, check_for_sdp_connection);
INIT_WORK(&motg->notify_charger_work, msm_otg_notify_charger_work);
+ INIT_WORK(&motg->extcon_register_work, msm_otg_extcon_register_work);
motg->otg_wq = alloc_ordered_workqueue("k_otg", 0);
if (!motg->otg_wq) {
pr_err("%s: Unable to create workqueue otg_wq\n",
@@ -4474,21 +4520,20 @@
}
}
- psy = power_supply_get_by_name("usb");
- if (!psy)
- dev_warn(&pdev->dev, "Could not get usb power_supply\n");
-
+ /*
+ * Try to register extcon handle from probe; by this time USB psy may or
+ * may not have been registered. If this fails, then wait for the USB
+ * psy to get registered which will again try to register extcon via
+ * notifier call.
+ */
ret = msm_otg_extcon_register(motg);
- if (ret)
- goto put_psy;
-
- if (motg->extcon_vbus && extcon_get_cable_state_(motg->extcon_vbus,
- EXTCON_USB))
- msm_otg_vbus_notifier(&motg->vbus_nb, true, motg->extcon_vbus);
-
- if (motg->extcon_id && extcon_get_cable_state_(motg->extcon_id,
- EXTCON_USB_HOST))
- msm_otg_id_notifier(&motg->id_nb, true, motg->extcon_id);
+ if (ret) {
+ dev_dbg(&pdev->dev, "Registering PSY notifier for extcon\n");
+ motg->psy_nb.notifier_call = msm_otg_psy_changed;
+ power_supply_reg_notifier(&motg->psy_nb);
+ } else {
+ msm_otg_handle_initial_extcon(motg);
+ }
if (gpio_is_valid(motg->pdata->hub_reset_gpio)) {
ret = devm_gpio_request(&pdev->dev,
@@ -4528,11 +4573,6 @@
return 0;
-put_psy:
- if (psy)
- power_supply_put(psy);
- if (pdev->dev.of_node)
- msm_otg_setup_devices(pdev, motg->pdata->mode, false);
remove_cdev:
pm_runtime_disable(&pdev->dev);
device_remove_file(&pdev->dev, &dev_attr_dpdm_pulldown_enable);
@@ -4600,7 +4640,7 @@
return -EBUSY;
unregister_pm_notifier(&motg->pm_notify);
-
+ power_supply_unreg_notifier(&motg->psy_nb);
extcon_unregister_notifier(motg->extcon_id, EXTCON_USB_HOST,
&motg->id_nb);
extcon_unregister_notifier(motg->extcon_vbus, EXTCON_USB,
@@ -4618,6 +4658,7 @@
msm_otg_perf_vote_update(motg, false);
cancel_work_sync(&motg->sm_work);
cancel_work_sync(&motg->notify_charger_work);
+ cancel_work_sync(&motg->extcon_register_work);
destroy_workqueue(motg->otg_wq);
pm_runtime_resume(&pdev->dev);
diff --git a/fs/exec.c b/fs/exec.c
index 3e2de29..d27f5e9 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -306,7 +306,7 @@
vma->vm_start = vma->vm_end - PAGE_SIZE;
vma->vm_flags = VM_SOFTDIRTY | VM_STACK_FLAGS | VM_STACK_INCOMPLETE_SETUP;
vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
- INIT_LIST_HEAD(&vma->anon_vma_chain);
+ INIT_VMA(vma);
err = insert_vm_struct(mm, vma);
if (err)
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index c585e7e..4fc0895 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -1123,8 +1123,11 @@
goto out_mm;
}
for (vma = mm->mmap; vma; vma = vma->vm_next) {
- vma->vm_flags &= ~VM_SOFTDIRTY;
+ vm_write_begin(vma);
+ WRITE_ONCE(vma->vm_flags,
+ vma->vm_flags & ~VM_SOFTDIRTY);
vma_set_page_prot(vma);
+ vm_write_end(vma);
}
downgrade_write(&mm->mmap_sem);
break;
diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c
index 9d9c032..00b661d 100644
--- a/fs/userfaultfd.c
+++ b/fs/userfaultfd.c
@@ -499,8 +499,10 @@
vma = prev;
else
prev = vma;
- vma->vm_flags = new_flags;
+ vm_write_begin(vma);
+ WRITE_ONCE(vma->vm_flags, new_flags);
vma->vm_userfaultfd_ctx = NULL_VM_UFFD_CTX;
+ vm_write_end(vma);
}
up_write(&mm->mmap_sem);
mmput(mm);
@@ -895,8 +897,10 @@
* the next vma was merged into the current one and
* the current one has not been updated yet.
*/
- vma->vm_flags = new_flags;
+ vm_write_begin(vma);
+ WRITE_ONCE(vma->vm_flags, new_flags);
vma->vm_userfaultfd_ctx.ctx = ctx;
+ vm_write_end(vma);
skip:
prev = vma;
@@ -1033,8 +1037,10 @@
* the next vma was merged into the current one and
* the current one has not been updated yet.
*/
- vma->vm_flags = new_flags;
+ vm_write_begin(vma);
+ WRITE_ONCE(vma->vm_flags, new_flags);
vma->vm_userfaultfd_ctx = NULL_VM_UFFD_CTX;
+ vm_write_end(vma);
skip:
prev = vma;
diff --git a/include/asm-generic/atomic-long.h b/include/asm-generic/atomic-long.h
index 288cc9e..f2d97b7 100644
--- a/include/asm-generic/atomic-long.h
+++ b/include/asm-generic/atomic-long.h
@@ -243,4 +243,7 @@
#define atomic_long_inc_not_zero(l) \
ATOMIC_LONG_PFX(_inc_not_zero)((ATOMIC_LONG_PFX(_t) *)(l))
+#define atomic_long_cond_read_acquire(v, c) \
+ ATOMIC_LONG_PFX(_cond_read_acquire)((ATOMIC_LONG_PFX(_t) *)(v), (c))
+
#endif /* _ASM_GENERIC_ATOMIC_LONG_H */
diff --git a/include/asm-generic/qrwlock.h b/include/asm-generic/qrwlock.h
index 7d026bf..c39a93a 100644
--- a/include/asm-generic/qrwlock.h
+++ b/include/asm-generic/qrwlock.h
@@ -26,30 +26,17 @@
/*
* Writer states & reader shift and bias.
- *
- * | +0 | +1 | +2 | +3 |
- * ----+----+----+----+----+
- * LE | 78 | 56 | 34 | 12 | 0x12345678
- * ----+----+----+----+----+
- * | wr | rd |
- * +----+----+----+----+
- *
- * ----+----+----+----+----+
- * BE | 12 | 34 | 56 | 78 | 0x12345678
- * ----+----+----+----+----+
- * | rd | wr |
- * +----+----+----+----+
*/
-#define _QW_WAITING 1 /* A writer is waiting */
-#define _QW_LOCKED 0xff /* A writer holds the lock */
-#define _QW_WMASK 0xff /* Writer mask */
-#define _QR_SHIFT 8 /* Reader count shift */
+#define _QW_WAITING 0x100 /* A writer is waiting */
+#define _QW_LOCKED 0x0ff /* A writer holds the lock */
+#define _QW_WMASK 0x1ff /* Writer mask */
+#define _QR_SHIFT 9 /* Reader count shift */
#define _QR_BIAS (1U << _QR_SHIFT)
/*
* External function declarations
*/
-extern void queued_read_lock_slowpath(struct qrwlock *lock, u32 cnts);
+extern void queued_read_lock_slowpath(struct qrwlock *lock);
extern void queued_write_lock_slowpath(struct qrwlock *lock);
/**
@@ -118,7 +105,7 @@
return;
/* The slowpath will decrement the reader count, if necessary. */
- queued_read_lock_slowpath(lock, cnts);
+ queued_read_lock_slowpath(lock);
}
/**
@@ -147,22 +134,12 @@
}
/**
- * __qrwlock_write_byte - retrieve the write byte address of a queue rwlock
- * @lock : Pointer to queue rwlock structure
- * Return: the write byte address of a queue rwlock
- */
-static inline u8 *__qrwlock_write_byte(struct qrwlock *lock)
-{
- return (u8 *)lock + 3 * IS_BUILTIN(CONFIG_CPU_BIG_ENDIAN);
-}
-
-/**
* queued_write_unlock - release write lock of a queue rwlock
* @lock : Pointer to queue rwlock structure
*/
static inline void queued_write_unlock(struct qrwlock *lock)
{
- smp_store_release(__qrwlock_write_byte(lock), 0);
+ smp_store_release(&lock->wlocked, 0);
}
/*
diff --git a/include/asm-generic/qrwlock_types.h b/include/asm-generic/qrwlock_types.h
index 0abc6b6..8af752a 100644
--- a/include/asm-generic/qrwlock_types.h
+++ b/include/asm-generic/qrwlock_types.h
@@ -9,12 +9,23 @@
*/
typedef struct qrwlock {
- atomic_t cnts;
+ union {
+ atomic_t cnts;
+ struct {
+#ifdef __LITTLE_ENDIAN
+ u8 wlocked; /* Locked for write? */
+ u8 __lstate[3];
+#else
+ u8 __lstate[3];
+ u8 wlocked; /* Locked for write? */
+#endif
+ };
+ };
arch_spinlock_t wait_lock;
} arch_rwlock_t;
#define __ARCH_RW_LOCK_UNLOCKED { \
- .cnts = ATOMIC_INIT(0), \
+ { .cnts = ATOMIC_INIT(0), }, \
.wait_lock = __ARCH_SPIN_LOCK_UNLOCKED, \
}
diff --git a/include/linux/atomic.h b/include/linux/atomic.h
index e71835b..bc7dba0 100644
--- a/include/linux/atomic.h
+++ b/include/linux/atomic.h
@@ -627,6 +627,8 @@
}
#endif
+#define atomic_cond_read_acquire(v, c) smp_cond_load_acquire(&(v)->counter, (c))
+
#ifdef CONFIG_GENERIC_ATOMIC64
#include <asm-generic/atomic64.h>
#endif
@@ -1023,6 +1025,8 @@
}
#endif
+#define atomic64_cond_read_acquire(v, c) smp_cond_load_acquire(&(v)->counter, (c))
+
#include <asm-generic/atomic-long.h>
#endif /* _LINUX_ATOMIC_H */
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 45d5522..0fbce32 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -424,6 +424,7 @@
#define CPUFREQ_START (2)
#define CPUFREQ_CREATE_POLICY (3)
#define CPUFREQ_REMOVE_POLICY (4)
+#define CPUFREQ_STOP (5)
/* Govinfo Notifiers */
#define CPUFREQ_LOAD_CHANGE (0)
diff --git a/include/linux/hugetlb_inline.h b/include/linux/hugetlb_inline.h
index a4e7ca0..6cfdfca 100644
--- a/include/linux/hugetlb_inline.h
+++ b/include/linux/hugetlb_inline.h
@@ -7,7 +7,7 @@
static inline bool is_vm_hugetlb_page(struct vm_area_struct *vma)
{
- return !!(vma->vm_flags & VM_HUGETLB);
+ return !!(READ_ONCE(vma->vm_flags) & VM_HUGETLB);
}
#else
diff --git a/include/linux/ipc_router_xprt.h b/include/linux/ipc_router_xprt.h
index c4b7854..bba7179 100644
--- a/include/linux/ipc_router_xprt.h
+++ b/include/linux/ipc_router_xprt.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2018, 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
@@ -128,6 +128,7 @@
* @sft_close_done: Method to indicate to the XPRT that handling of reset
* event is complete.
* @get_ws_info: Method to get the wakeup soruce inforamtion of the XPRT
+ * @get_ws_info: Method to get the latency inforamtion of the XPRT.
*/
struct msm_ipc_router_xprt {
char *name;
@@ -147,6 +148,7 @@
int (*close)(struct msm_ipc_router_xprt *xprt);
void (*sft_close_done)(struct msm_ipc_router_xprt *xprt);
bool (*get_ws_info)(struct msm_ipc_router_xprt *xprt);
+ bool (*get_latency_info)(struct msm_ipc_router_xprt *xprt);
};
void msm_ipc_router_xprt_notify(struct msm_ipc_router_xprt *xprt,
diff --git a/include/linux/migrate.h b/include/linux/migrate.h
index ae8d475..df8e0b0 100644
--- a/include/linux/migrate.h
+++ b/include/linux/migrate.h
@@ -89,14 +89,14 @@
#ifdef CONFIG_NUMA_BALANCING
extern bool pmd_trans_migrating(pmd_t pmd);
extern int migrate_misplaced_page(struct page *page,
- struct vm_area_struct *vma, int node);
+ struct fault_env *fe, int node);
#else
static inline bool pmd_trans_migrating(pmd_t pmd)
{
return false;
}
static inline int migrate_misplaced_page(struct page *page,
- struct vm_area_struct *vma, int node)
+ struct fault_env *fe, int node)
{
return -EAGAIN; /* can't migrate now */
}
diff --git a/include/linux/mm.h b/include/linux/mm.h
index b328cca..9d5d808 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -284,6 +284,9 @@
#define FAULT_FLAG_USER 0x40 /* The fault originated in userspace */
#define FAULT_FLAG_REMOTE 0x80 /* faulting for non current tsk/mm */
#define FAULT_FLAG_INSTRUCTION 0x100 /* The fault was during an instruction fetch */
+/* Speculative fault, not holding mmap_sem */
+#define FAULT_FLAG_SPECULATIVE 0x200
+#define FAULT_FLAG_PREFAULT_OLD 0x400 /* Make faultaround ptes old */
/*
* vm_fault is filled by the the pagefault handler and passed to the vma's
@@ -300,7 +303,6 @@
gfp_t gfp_mask; /* gfp mask to be used for allocations */
pgoff_t pgoff; /* Logical page offset based on vma */
void __user *virtual_address; /* Faulting virtual address */
-
struct page *cow_page; /* Handler may choose to COW */
struct page *page; /* ->fault handlers should return a
* page here, unless VM_FAULT_NOPAGE
@@ -322,6 +324,7 @@
struct fault_env {
struct vm_area_struct *vma; /* Target VMA */
unsigned long address; /* Faulting virtual address */
+ unsigned long fault_address; /* Saved faulting virtual address */
unsigned int flags; /* FAULT_FLAG_xxx flags */
pmd_t *pmd; /* Pointer to pmd entry matching
* the 'address'
@@ -341,6 +344,17 @@
* page table to avoid allocation from
* atomic context.
*/
+ /*
+ * These entries are required when handling speculative page fault.
+ * This way the page handling is done using consistent field values.
+ */
+ unsigned long vma_flags;
+ pgprot_t vma_page_prot;
+#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
+ unsigned int sequence;
+ pmd_t orig_pmd; /* value of PMD at the time of fault */
+ pte_t orig_pte; /* Value of PTE at the time of fault */
+#endif
};
/*
@@ -623,9 +637,9 @@
* pte_mkwrite. But get_user_pages can cause write faults for mappings
* that do not have writing enabled, when used by access_process_vm.
*/
-static inline pte_t maybe_mkwrite(pte_t pte, struct vm_area_struct *vma)
+static inline pte_t maybe_mkwrite(pte_t pte, unsigned long vma_flags)
{
- if (likely(vma->vm_flags & VM_WRITE))
+ if (likely(vma_flags & VM_WRITE))
pte = pte_mkwrite(pte);
return pte;
}
@@ -1118,6 +1132,7 @@
#define VM_FAULT_DAX_LOCKED 0x1000 /* ->fault has locked DAX entry */
#define VM_FAULT_HWPOISON_LARGE_MASK 0xf000 /* encodes hpage index for large hwpoison */
+#define VM_FAULT_PTNOTSAME 0x4000 /* Page table entries have changed */
#define VM_FAULT_ERROR (VM_FAULT_OOM | VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV | \
VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE | \
@@ -1167,8 +1182,23 @@
pgoff_t last_index; /* Highest page->index to unmap */
};
-struct page *vm_normal_page(struct vm_area_struct *vma, unsigned long addr,
- pte_t pte);
+struct page *__vm_normal_page(struct vm_area_struct *vma, unsigned long addr,
+ pte_t pte, unsigned long vma_flags);
+static inline struct page *vm_normal_page(struct vm_area_struct *vma,
+ unsigned long addr, pte_t pte)
+{
+ return __vm_normal_page(vma, addr, pte, vma->vm_flags);
+}
+
+static inline void INIT_VMA(struct vm_area_struct *vma)
+{
+ INIT_LIST_HEAD(&vma->anon_vma_chain);
+#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
+ seqcount_init(&vma->vm_sequence);
+ atomic_set(&vma->vm_ref_count, 1);
+#endif
+}
+
struct page *vm_normal_page_pmd(struct vm_area_struct *vma, unsigned long addr,
pmd_t pmd);
@@ -1238,6 +1268,47 @@
unmap_mapping_range(mapping, holebegin, holelen, 0);
}
+#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
+static inline void vm_write_begin(struct vm_area_struct *vma)
+{
+ write_seqcount_begin(&vma->vm_sequence);
+}
+static inline void vm_write_begin_nested(struct vm_area_struct *vma,
+ int subclass)
+{
+ write_seqcount_begin_nested(&vma->vm_sequence, subclass);
+}
+static inline void vm_write_end(struct vm_area_struct *vma)
+{
+ write_seqcount_end(&vma->vm_sequence);
+}
+static inline void vm_raw_write_begin(struct vm_area_struct *vma)
+{
+ raw_write_seqcount_begin(&vma->vm_sequence);
+}
+static inline void vm_raw_write_end(struct vm_area_struct *vma)
+{
+ raw_write_seqcount_end(&vma->vm_sequence);
+}
+#else
+static inline void vm_write_begin(struct vm_area_struct *vma)
+{
+}
+static inline void vm_write_begin_nested(struct vm_area_struct *vma,
+ int subclass)
+{
+}
+static inline void vm_write_end(struct vm_area_struct *vma)
+{
+}
+static inline void vm_raw_write_begin(struct vm_area_struct *vma)
+{
+}
+static inline void vm_raw_write_end(struct vm_area_struct *vma)
+{
+}
+#endif /* CONFIG_SPECULATIVE_PAGE_FAULT */
+
extern void truncate_pagecache(struct inode *inode, loff_t new);
extern void truncate_setsize(struct inode *inode, loff_t newsize);
void pagecache_isize_extended(struct inode *inode, loff_t from, loff_t to);
@@ -1249,6 +1320,43 @@
#ifdef CONFIG_MMU
extern int handle_mm_fault(struct vm_area_struct *vma, unsigned long address,
unsigned int flags);
+
+#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
+extern int __handle_speculative_fault(struct mm_struct *mm,
+ unsigned long address,
+ unsigned int flags,
+ struct vm_area_struct **vma);
+static inline int handle_speculative_fault(struct mm_struct *mm,
+ unsigned long address,
+ unsigned int flags,
+ struct vm_area_struct **vma)
+{
+ /*
+ * Try speculative page fault for multithreaded user space task only.
+ */
+ if (!(flags & FAULT_FLAG_USER) || atomic_read(&mm->mm_users) == 1) {
+ *vma = NULL;
+ return VM_FAULT_RETRY;
+ }
+ return __handle_speculative_fault(mm, address, flags, vma);
+}
+extern bool can_reuse_spf_vma(struct vm_area_struct *vma,
+ unsigned long address);
+#else
+static inline int handle_speculative_fault(struct mm_struct *mm,
+ unsigned long address,
+ unsigned int flags,
+ struct vm_area_struct **vma)
+{
+ return VM_FAULT_RETRY;
+}
+static inline bool can_reuse_spf_vma(struct vm_area_struct *vma,
+ unsigned long address)
+{
+ return false;
+}
+#endif /* CONFIG_SPECULATIVE_PAGE_FAULT */
+
extern int fixup_user_fault(struct task_struct *tsk, struct mm_struct *mm,
unsigned long address, unsigned int fault_flags,
bool *unlocked);
@@ -1957,16 +2065,29 @@
extern int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin);
extern int __vma_adjust(struct vm_area_struct *vma, unsigned long start,
unsigned long end, pgoff_t pgoff, struct vm_area_struct *insert,
- struct vm_area_struct *expand);
+ struct vm_area_struct *expand, bool keep_locked);
static inline int vma_adjust(struct vm_area_struct *vma, unsigned long start,
unsigned long end, pgoff_t pgoff, struct vm_area_struct *insert)
{
- return __vma_adjust(vma, start, end, pgoff, insert, NULL);
+ return __vma_adjust(vma, start, end, pgoff, insert, NULL, false);
}
-extern struct vm_area_struct *vma_merge(struct mm_struct *,
+
+extern struct vm_area_struct *__vma_merge(struct mm_struct *mm,
struct vm_area_struct *prev, unsigned long addr, unsigned long end,
- unsigned long vm_flags, struct anon_vma *, struct file *, pgoff_t,
- struct mempolicy *, struct vm_userfaultfd_ctx, const char __user *);
+ unsigned long vm_flags, struct anon_vma *anon, struct file *file,
+ pgoff_t pgoff, struct mempolicy *mpol, struct vm_userfaultfd_ctx uff,
+ const char __user *user, bool keep_locked);
+
+static inline struct vm_area_struct *vma_merge(struct mm_struct *mm,
+ struct vm_area_struct *prev, unsigned long addr, unsigned long end,
+ unsigned long vm_flags, struct anon_vma *anon, struct file *file,
+ pgoff_t off, struct mempolicy *pol, struct vm_userfaultfd_ctx uff,
+ const char __user *user)
+{
+ return __vma_merge(mm, prev, addr, end, vm_flags, anon, file, off,
+ pol, uff, user, false);
+}
+
extern struct anon_vma *find_mergeable_anon_vma(struct vm_area_struct *);
extern int split_vma(struct mm_struct *,
struct vm_area_struct *, unsigned long addr, int new_below);
@@ -2465,6 +2586,8 @@
static inline void setup_nr_node_ids(void) {}
#endif
+extern int want_old_faultaround_pte;
+
#ifdef CONFIG_PROCESS_RECLAIM
struct reclaim_param {
struct vm_area_struct *vma;
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 5942478..cb2cc30 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -365,6 +365,10 @@
struct mempolicy *vm_policy; /* NUMA policy for the VMA */
#endif
struct vm_userfaultfd_ctx vm_userfaultfd_ctx;
+#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
+ seqcount_t vm_sequence;
+ atomic_t vm_ref_count; /* see vma_get(), vma_put() */
+#endif
};
struct core_thread {
@@ -403,6 +407,9 @@
struct mm_struct {
struct vm_area_struct *mmap; /* list of VMAs */
struct rb_root mm_rb;
+#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
+ rwlock_t mm_rb_lock;
+#endif
u32 vmacache_seqnum; /* per-thread vmacache */
#ifdef CONFIG_MMU
unsigned long (*get_unmapped_area) (struct file *filp,
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index 791c547..9dbf9c3 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -427,8 +427,8 @@
pgoff_t pgoff;
if (unlikely(is_vm_hugetlb_page(vma)))
return linear_hugepage_index(vma, address);
- pgoff = (address - vma->vm_start) >> PAGE_SHIFT;
- pgoff += vma->vm_pgoff;
+ pgoff = (address - READ_ONCE(vma->vm_start)) >> PAGE_SHIFT;
+ pgoff += READ_ONCE(vma->vm_pgoff);
return pgoff;
}
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 25d7806..9412480 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -131,6 +131,12 @@
POWER_SUPPLY_PD_PPS_ACTIVE,
};
+enum {
+ POWER_SUPPLY_QC_CTM_DISABLE = BIT(0),
+ POWER_SUPPLY_QC_THERMAL_BALANCE_DISABLE = BIT(1),
+ POWER_SUPPLY_QC_INOV_THERMAL_DISABLE = BIT(2),
+};
+
enum power_supply_property {
/* Properties of type `int' */
POWER_SUPPLY_PROP_STATUS = 0,
@@ -295,6 +301,7 @@
POWER_SUPPLY_PROP_ESR_ACTUAL,
POWER_SUPPLY_PROP_ESR_NOMINAL,
POWER_SUPPLY_PROP_SOH,
+ POWER_SUPPLY_PROP_QC_OPTI_DISABLE,
/* Local extensions of type int64_t */
POWER_SUPPLY_PROP_CHARGE_COUNTER_EXT,
/* Properties of type `const char *' */
diff --git a/include/linux/qcom-geni-se.h b/include/linux/qcom-geni-se.h
index b8dd63a..886b7d6 100644
--- a/include/linux/qcom-geni-se.h
+++ b/include/linux/qcom-geni-se.h
@@ -40,6 +40,7 @@
/**
* struct geni_se_rsc - GENI Serial Engine Resource
+ * @ctrl_dev Pointer to controller device.
* @wrapper_dev: Pointer to the parent QUPv3 core.
* @se_clk: Handle to the core serial engine clock.
* @m_ahb_clk: Handle to the primary AHB clock.
@@ -53,6 +54,7 @@
* @geni_gpi_sleep: Handle to the sleep pinctrl state.
*/
struct se_geni_rsc {
+ struct device *ctrl_dev;
struct device *wrapper_dev;
struct clk *se_clk;
struct clk *m_ahb_clk;
diff --git a/include/linux/rmap.h b/include/linux/rmap.h
index 71fd2b3..92a297c 100644
--- a/include/linux/rmap.h
+++ b/include/linux/rmap.h
@@ -168,8 +168,16 @@
unsigned long, bool);
void do_page_add_anon_rmap(struct page *, struct vm_area_struct *,
unsigned long, int);
-void page_add_new_anon_rmap(struct page *, struct vm_area_struct *,
- unsigned long, bool);
+void __page_add_new_anon_rmap(struct page *page, struct vm_area_struct *vma,
+ unsigned long address, bool compound);
+static inline void page_add_new_anon_rmap(struct page *page,
+ struct vm_area_struct *vma,
+ unsigned long address, bool compound)
+{
+ VM_BUG_ON_VMA(address < vma->vm_start || address >= vma->vm_end, vma);
+ __page_add_new_anon_rmap(page, vma, address, compound);
+}
+
void page_add_file_rmap(struct page *, bool);
void page_remove_rmap(struct page *, bool);
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 92d1fde..7b488ec 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -313,8 +313,14 @@
extern void add_page_to_unevictable_list(struct page *page);
-extern void lru_cache_add_active_or_unevictable(struct page *page,
- struct vm_area_struct *vma);
+extern void __lru_cache_add_active_or_unevictable(struct page *page,
+ unsigned long vma_flags);
+
+static inline void lru_cache_add_active_or_unevictable(struct page *page,
+ struct vm_area_struct *vma)
+{
+ return __lru_cache_add_active_or_unevictable(page, vma->vm_flags);
+}
/* linux/mm/vmscan.c */
extern unsigned long zone_reclaimable_pages(struct zone *zone);
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index d4f1759..2393c13 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -180,6 +180,8 @@
nominal mode.
* @sdp_check: SDP detection work in case of USB_FLOAT power supply
* @notify_charger_work: Charger notification work.
+ * @extcon_register_work: Extcon registration work.
+ * @psy_nb: Notification callback for PSY registration.
*/
struct msm_otg {
struct usb_phy phy;
@@ -313,6 +315,8 @@
struct delayed_work perf_vote_work;
struct delayed_work sdp_check;
struct work_struct notify_charger_work;
+ struct work_struct extcon_register_work;
+ struct notifier_block psy_nb;
};
struct ci13xxx_platform_data {
diff --git a/include/linux/vm_event_item.h b/include/linux/vm_event_item.h
index a9c2e4c..4c679792 100644
--- a/include/linux/vm_event_item.h
+++ b/include/linux/vm_event_item.h
@@ -99,6 +99,9 @@
VMACACHE_FIND_HITS,
VMACACHE_FULL_FLUSHES,
#endif
+#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
+ SPECULATIVE_PGFAULT,
+#endif
NR_VM_EVENT_ITEMS
};
diff --git a/include/net/cnss2.h b/include/net/cnss2.h
index 9dbf449..342907d 100644
--- a/include/net/cnss2.h
+++ b/include/net/cnss2.h
@@ -182,7 +182,7 @@
enum cnss_driver_mode mode,
const char *host_version);
extern int cnss_wlan_disable(struct device *dev, enum cnss_driver_mode mode);
-extern unsigned int cnss_get_qmi_timeout(void);
+extern unsigned int cnss_get_boot_timeout(struct device *dev);
extern int cnss_athdiag_read(struct device *dev, uint32_t offset,
uint32_t mem_type, uint32_t data_len,
uint8_t *output);
diff --git a/include/trace/events/pagefault.h b/include/trace/events/pagefault.h
new file mode 100644
index 0000000..a9643b3
--- /dev/null
+++ b/include/trace/events/pagefault.h
@@ -0,0 +1,88 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM pagefault
+
+#if !defined(_TRACE_PAGEFAULT_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_PAGEFAULT_H
+
+#include <linux/tracepoint.h>
+#include <linux/mm.h>
+
+DECLARE_EVENT_CLASS(spf,
+
+ TP_PROTO(unsigned long caller,
+ struct vm_area_struct *vma, unsigned long address),
+
+ TP_ARGS(caller, vma, address),
+
+ TP_STRUCT__entry(
+ __field(unsigned long, caller)
+ __field(unsigned long, vm_start)
+ __field(unsigned long, vm_end)
+ __field(unsigned long, address)
+ ),
+
+ TP_fast_assign(
+ __entry->caller = caller;
+ __entry->vm_start = vma->vm_start;
+ __entry->vm_end = vma->vm_end;
+ __entry->address = address;
+ ),
+
+ TP_printk("ip:%lx vma:%lx-%lx address:%lx",
+ __entry->caller, __entry->vm_start, __entry->vm_end,
+ __entry->address)
+);
+
+DEFINE_EVENT(spf, spf_pte_lock,
+
+ TP_PROTO(unsigned long caller,
+ struct vm_area_struct *vma, unsigned long address),
+
+ TP_ARGS(caller, vma, address)
+);
+
+DEFINE_EVENT(spf, spf_vma_changed,
+
+ TP_PROTO(unsigned long caller,
+ struct vm_area_struct *vma, unsigned long address),
+
+ TP_ARGS(caller, vma, address)
+);
+
+DEFINE_EVENT(spf, spf_vma_noanon,
+
+ TP_PROTO(unsigned long caller,
+ struct vm_area_struct *vma, unsigned long address),
+
+ TP_ARGS(caller, vma, address)
+);
+
+DEFINE_EVENT(spf, spf_vma_notsup,
+
+ TP_PROTO(unsigned long caller,
+ struct vm_area_struct *vma, unsigned long address),
+
+ TP_ARGS(caller, vma, address)
+);
+
+DEFINE_EVENT(spf, spf_vma_access,
+
+ TP_PROTO(unsigned long caller,
+ struct vm_area_struct *vma, unsigned long address),
+
+ TP_ARGS(caller, vma, address)
+);
+
+DEFINE_EVENT(spf, spf_pmd_changed,
+
+ TP_PROTO(unsigned long caller,
+ struct vm_area_struct *vma, unsigned long address),
+
+ TP_ARGS(caller, vma, address)
+);
+
+#endif /* _TRACE_PAGEFAULT_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h
index b355ebf..b3ec962 100644
--- a/include/trace/events/sched.h
+++ b/include/trace/events/sched.h
@@ -657,6 +657,10 @@
__field(unsigned int, capacity_orig )
__field(int, idle_state )
__field(u64, irqload )
+ __field(int, online )
+ __field(int, isolated )
+ __field(int, reserved )
+ __field(int, high_irq_load )
),
TP_fast_assign(
@@ -669,10 +673,14 @@
__entry->capacity_orig = capacity_orig_of(cpu);
__entry->idle_state = idle_get_state_idx(cpu_rq(cpu));
__entry->irqload = sched_irqload(cpu);
+ __entry->online = cpu_online(cpu);
+ __entry->isolated = cpu_isolated(cpu);
+ __entry->reserved = is_reserved(cpu);
+ __entry->high_irq_load = sched_cpu_high_irqload(cpu);
),
- TP_printk("cpu=%d nr_running=%d cpu_util=%ld cpu_util_cum=%ld capacity_curr=%u capacity=%u capacity_orig=%u idle_state=%d irqload=%llu",
- __entry->cpu, __entry->nr_running, __entry->cpu_util, __entry->cpu_util_cum, __entry->capacity_curr, __entry->capacity, __entry->capacity_orig, __entry->idle_state, __entry->irqload)
+ TP_printk("cpu=%d nr_running=%d cpu_util=%ld cpu_util_cum=%ld capacity_curr=%u capacity=%u capacity_orig=%u idle_state=%d irqload=%llu online=%u isolated=%u reserved=%u high_irq_load=%u",
+ __entry->cpu, __entry->nr_running, __entry->cpu_util, __entry->cpu_util_cum, __entry->capacity_curr, __entry->capacity, __entry->capacity_orig, __entry->idle_state, __entry->irqload, __entry->online, __entry->isolated, __entry->reserved, __entry->high_irq_load)
);
TRACE_EVENT(sched_energy_diff,
@@ -1637,10 +1645,11 @@
TP_PROTO(struct task_struct *tsk, bool prefer_idle,
unsigned long min_util, int start_cpu,
- int best_idle, int best_active, int target),
+ int best_idle, int best_active, int target,
+ int backup_cpu),
TP_ARGS(tsk, prefer_idle, min_util, start_cpu,
- best_idle, best_active, target),
+ best_idle, best_active, target, backup_cpu),
TP_STRUCT__entry(
__array( char, comm, TASK_COMM_LEN )
@@ -1651,6 +1660,7 @@
__field( int, best_idle )
__field( int, best_active )
__field( int, target )
+ __field( int, backup_cpu )
),
TP_fast_assign(
@@ -1662,14 +1672,16 @@
__entry->best_idle = best_idle;
__entry->best_active = best_active;
__entry->target = target;
+ __entry->backup_cpu = backup_cpu;
),
TP_printk("pid=%d comm=%s prefer_idle=%d start_cpu=%d "
- "best_idle=%d best_active=%d target=%d",
+ "best_idle=%d best_active=%d target=%d backup=%d",
__entry->pid, __entry->comm,
__entry->prefer_idle, __entry->start_cpu,
__entry->best_idle, __entry->best_active,
- __entry->target)
+ __entry->target,
+ __entry->backup_cpu)
);
TRACE_EVENT(sched_group_energy,
diff --git a/include/uapi/linux/qg.h b/include/uapi/linux/qg.h
index 40882a7..54aa362 100644
--- a/include/uapi/linux/qg.h
+++ b/include/uapi/linux/qg.h
@@ -20,7 +20,7 @@
QG_ESR_DISCHARGE_SF,
QG_FULL_SOC,
QG_CLEAR_LEARNT_DATA,
- QG_RESERVED_9,
+ QG_SYS_SOC,
QG_RESERVED_10,
QG_MAX,
};
@@ -33,6 +33,7 @@
#define QG_ESR_DISCHARGE_SF QG_ESR_DISCHARGE_SF
#define QG_FULL_SOC QG_FULL_SOC
#define QG_CLEAR_LEARNT_DATA QG_CLEAR_LEARNT_DATA
+#define QG_SYS_SOC QG_SYS_SOC
struct fifo_data {
unsigned int v;
diff --git a/include/uapi/media/cam_icp.h b/include/uapi/media/cam_icp.h
index cd2d2d2..680d05b 100644
--- a/include/uapi/media/cam_icp.h
+++ b/include/uapi/media/cam_icp.h
@@ -59,8 +59,9 @@
/* Command meta types */
#define CAM_ICP_CMD_META_GENERIC_BLOB 0x1
-/* Generic blon types */
+/* Generic blob types */
#define CAM_ICP_CMD_GENERIC_BLOB_CLK 0x1
+#define CAM_ICP_CMD_GENERIC_BLOB_CFG_IO 0x2
/**
* struct cam_icp_clk_bw_request
diff --git a/include/uapi/media/msm_media_info.h b/include/uapi/media/msm_media_info.h
index 3fd0c88..796d6d2 100644
--- a/include/uapi/media/msm_media_info.h
+++ b/include/uapi/media/msm_media_info.h
@@ -1261,8 +1261,11 @@
size = MSM_MEDIA_ALIGN(size, 4096);
/* Additional size to cover last row of non-aligned frame */
- size += MSM_MEDIA_ALIGN(width, w_alignment) * w_alignment;
- size = MSM_MEDIA_ALIGN(size, 4096);
+ if (width >= 2400 && height >= 2400) {
+ size += MSM_MEDIA_ALIGN(width, w_alignment) *
+ w_alignment;
+ size = MSM_MEDIA_ALIGN(size, 4096);
+ }
break;
case COLOR_FMT_P010:
uv_alignment = 4096;
@@ -1302,8 +1305,11 @@
size = MSM_MEDIA_ALIGN(size, 4096);
/* Additional size to cover last row of non-aligned frame */
- size += MSM_MEDIA_ALIGN(width, w_alignment) * w_alignment;
- size = MSM_MEDIA_ALIGN(size, 4096);
+ if (width >= 2400 && height >= 2400) {
+ size += MSM_MEDIA_ALIGN(width, w_alignment) *
+ w_alignment;
+ size = MSM_MEDIA_ALIGN(size, 4096);
+ }
break;
case COLOR_FMT_NV12_BPP10_UBWC:
y_ubwc_plane = MSM_MEDIA_ALIGN(y_stride * y_sclines, 4096);
diff --git a/kernel/fork.c b/kernel/fork.c
index 79fdfd8..965c091 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -614,7 +614,7 @@
if (!tmp)
goto fail_nomem;
*tmp = *mpnt;
- INIT_LIST_HEAD(&tmp->anon_vma_chain);
+ INIT_VMA(tmp);
retval = vma_dup_policy(mpnt, tmp);
if (retval)
goto fail_nomem_policy;
@@ -764,6 +764,9 @@
mm->mmap = NULL;
mm->mm_rb = RB_ROOT;
mm->vmacache_seqnum = 0;
+#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
+ rwlock_init(&mm->mm_rb_lock);
+#endif
atomic_set(&mm->mm_users, 1);
atomic_set(&mm->mm_count, 1);
init_rwsem(&mm->mmap_sem);
diff --git a/kernel/locking/qrwlock.c b/kernel/locking/qrwlock.c
index 19248dd..c7471c3 100644
--- a/kernel/locking/qrwlock.c
+++ b/kernel/locking/qrwlock.c
@@ -20,51 +20,14 @@
#include <linux/cpumask.h>
#include <linux/percpu.h>
#include <linux/hardirq.h>
+#include <linux/spinlock.h>
#include <asm/qrwlock.h>
-/*
- * This internal data structure is used for optimizing access to some of
- * the subfields within the atomic_t cnts.
- */
-struct __qrwlock {
- union {
- atomic_t cnts;
- struct {
-#ifdef __LITTLE_ENDIAN
- u8 wmode; /* Writer mode */
- u8 rcnts[3]; /* Reader counts */
-#else
- u8 rcnts[3]; /* Reader counts */
- u8 wmode; /* Writer mode */
-#endif
- };
- };
- arch_spinlock_t lock;
-};
-
-/**
- * rspin_until_writer_unlock - inc reader count & spin until writer is gone
- * @lock : Pointer to queue rwlock structure
- * @writer: Current queue rwlock writer status byte
- *
- * In interrupt context or at the head of the queue, the reader will just
- * increment the reader count & wait until the writer releases the lock.
- */
-static __always_inline void
-rspin_until_writer_unlock(struct qrwlock *lock, u32 cnts)
-{
- while ((cnts & _QW_WMASK) == _QW_LOCKED) {
- cpu_relax_lowlatency();
- cnts = atomic_read_acquire(&lock->cnts);
- }
-}
-
/**
* queued_read_lock_slowpath - acquire read lock of a queue rwlock
* @lock: Pointer to queue rwlock structure
- * @cnts: Current qrwlock lock value
*/
-void queued_read_lock_slowpath(struct qrwlock *lock, u32 cnts)
+void queued_read_lock_slowpath(struct qrwlock *lock)
{
/*
* Readers come here when they cannot get the lock without waiting
@@ -72,13 +35,11 @@
if (unlikely(in_interrupt())) {
/*
* Readers in interrupt context will get the lock immediately
- * if the writer is just waiting (not holding the lock yet).
- * The rspin_until_writer_unlock() function returns immediately
- * in this case. Otherwise, they will spin (with ACQUIRE
- * semantics) until the lock is available without waiting in
- * the queue.
+ * if the writer is just waiting (not holding the lock yet),
+ * so spin with ACQUIRE semantics until the lock is available
+ * without waiting in the queue.
*/
- rspin_until_writer_unlock(lock, cnts);
+ atomic_cond_read_acquire(&lock->cnts, !(VAL & _QW_LOCKED));
return;
}
atomic_sub(_QR_BIAS, &lock->cnts);
@@ -87,14 +48,14 @@
* Put the reader into the wait queue
*/
arch_spin_lock(&lock->wait_lock);
+ atomic_add(_QR_BIAS, &lock->cnts);
/*
* The ACQUIRE semantics of the following spinning code ensure
* that accesses can't leak upwards out of our subsequent critical
* section in the case that the lock is currently held for write.
*/
- cnts = atomic_fetch_add_acquire(_QR_BIAS, &lock->cnts);
- rspin_until_writer_unlock(lock, cnts);
+ atomic_cond_read_acquire(&lock->cnts, !(VAL & _QW_LOCKED));
/*
* Signal the next one in queue to become queue head
@@ -109,8 +70,6 @@
*/
void queued_write_lock_slowpath(struct qrwlock *lock)
{
- u32 cnts;
-
/* Put the writer into the wait queue */
arch_spin_lock(&lock->wait_lock);
@@ -119,30 +78,14 @@
(atomic_cmpxchg_acquire(&lock->cnts, 0, _QW_LOCKED) == 0))
goto unlock;
- /*
- * Set the waiting flag to notify readers that a writer is pending,
- * or wait for a previous writer to go away.
- */
- for (;;) {
- struct __qrwlock *l = (struct __qrwlock *)lock;
+ /* Set the waiting flag to notify readers that a writer is pending */
+ atomic_add(_QW_WAITING, &lock->cnts);
- if (!READ_ONCE(l->wmode) &&
- (cmpxchg_relaxed(&l->wmode, 0, _QW_WAITING) == 0))
- break;
-
- cpu_relax_lowlatency();
- }
-
- /* When no more readers, set the locked flag */
- for (;;) {
- cnts = atomic_read(&lock->cnts);
- if ((cnts == _QW_WAITING) &&
- (atomic_cmpxchg_acquire(&lock->cnts, _QW_WAITING,
- _QW_LOCKED) == _QW_WAITING))
- break;
-
- cpu_relax_lowlatency();
- }
+ /* When no more readers or writers, set the locked flag */
+ do {
+ atomic_cond_read_acquire(&lock->cnts, VAL == _QW_WAITING);
+ } while (atomic_cmpxchg_relaxed(&lock->cnts, _QW_WAITING,
+ _QW_LOCKED) != _QW_WAITING);
unlock:
arch_spin_unlock(&lock->wait_lock);
}
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index fb2e56c..b755eb8 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -2172,7 +2172,7 @@
rq = cpu_rq(task_cpu(p));
raw_spin_lock(&rq->lock);
old_load = task_load(p);
- wallclock = ktime_get_ns();
+ wallclock = sched_ktime_clock();
update_task_ravg(rq->curr, rq, TASK_UPDATE, wallclock, 0);
update_task_ravg(p, rq, TASK_WAKE, wallclock, 0);
raw_spin_unlock(&rq->lock);
@@ -2259,7 +2259,7 @@
trace_sched_waking(p);
if (!task_on_rq_queued(p)) {
- u64 wallclock = ktime_get_ns();
+ u64 wallclock = sched_ktime_clock();
update_task_ravg(rq->curr, rq, TASK_UPDATE, wallclock, 0);
update_task_ravg(p, rq, TASK_WAKE, wallclock, 0);
@@ -3261,7 +3261,7 @@
old_load = task_load(curr);
set_window_start(rq);
- wallclock = ktime_get_ns();
+ wallclock = sched_ktime_clock();
update_task_ravg(rq->curr, rq, TASK_UPDATE, wallclock, 0);
update_rq_clock(rq);
@@ -3633,7 +3633,7 @@
clear_preempt_need_resched();
rq->clock_skip_update = 0;
- wallclock = ktime_get_ns();
+ wallclock = sched_ktime_clock();
if (likely(prev != next)) {
if (!prev->on_rq)
prev->last_sleep_ts = wallclock;
@@ -9611,7 +9611,7 @@
rq = task_rq_lock(p, &rf);
/* rq->curr == p */
- wallclock = ktime_get_ns();
+ wallclock = sched_ktime_clock();
update_task_ravg(rq->curr, rq, TASK_UPDATE, wallclock, 0);
dequeue_task(rq, p, 0);
/*
diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
index 895c63f..b71f116 100644
--- a/kernel/sched/cpufreq_schedutil.c
+++ b/kernel/sched/cpufreq_schedutil.c
@@ -466,7 +466,7 @@
mutex_lock(&sg_policy->work_lock);
raw_spin_lock_irqsave(&sg_policy->update_lock, flags);
sugov_track_cycles(sg_policy, sg_policy->policy->cur,
- ktime_get_ns());
+ sched_ktime_clock());
raw_spin_unlock_irqrestore(&sg_policy->update_lock, flags);
__cpufreq_driver_target(sg_policy->policy, sg_policy->next_freq,
CPUFREQ_RELATION_L);
@@ -919,7 +919,7 @@
mutex_lock(&sg_policy->work_lock);
raw_spin_lock_irqsave(&sg_policy->update_lock, flags);
sugov_track_cycles(sg_policy, sg_policy->policy->cur,
- ktime_get_ns());
+ sched_ktime_clock());
raw_spin_unlock_irqrestore(&sg_policy->update_lock, flags);
cpufreq_policy_apply_limits(policy);
mutex_unlock(&sg_policy->work_lock);
diff --git a/kernel/sched/energy.c b/kernel/sched/energy.c
index 77d8361..01daf82 100644
--- a/kernel/sched/energy.c
+++ b/kernel/sched/energy.c
@@ -25,6 +25,7 @@
#include <linux/sched_energy.h>
#include <linux/stddef.h>
#include <linux/cpu.h>
+#include <linux/cpuset.h>
#include <linux/pm_opp.h>
#include <linux/platform_device.h>
@@ -49,6 +50,17 @@
}
}
+static int update_topology;
+
+/*
+ * Ideally this should be arch specific implementation,
+ * let's define here to help rebuild sched_domain with new capacities.
+ */
+int arch_update_cpu_topology(void)
+{
+ return update_topology;
+}
+
void init_sched_energy_costs(void)
{
struct device_node *cn, *cp;
@@ -273,8 +285,22 @@
kfree(max_frequencies);
- if (is_sge_valid)
+ if (is_sge_valid) {
+ /*
+ * Sched_domains might have built with default cpu capacity
+ * values on bootup.
+ *
+ * Let's rebuild them again with actual cpu capacities.
+ * And partition_sched_domain() expects update in cpu topology
+ * to rebuild the domains, so make it satisfied..
+ */
+ update_topology = 1;
+ rebuild_sched_domains();
+ update_topology = 0;
+
walt_sched_energy_populated_callback();
+ }
+
dev_info(&pdev->dev, "Sched-energy-costs capacity updated\n");
return 0;
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index b0e962b..a778843 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -6930,6 +6930,8 @@
int target_cpu = -1;
int cpu, i;
unsigned int active_cpus_count = 0;
+ int isolated_candidate = -1;
+ int prev_cpu = task_cpu(p);
*backup_cpu = -1;
@@ -6975,16 +6977,18 @@
unsigned long wake_util, new_util, min_capped_util;
cpumask_clear_cpu(i, &search_cpus);
- if (avoid_prev_cpu && i == task_cpu(p))
- continue;
-
- if (!cpu_online(i) || cpu_isolated(i) || is_reserved(i))
- continue;
-
- if (walt_cpu_high_irqload(i))
- continue;
trace_sched_cpu_util(i);
+ if (!cpu_online(i) || cpu_isolated(i))
+ continue;
+
+ isolated_candidate = i;
+
+ if (avoid_prev_cpu && i == prev_cpu)
+ continue;
+
+ if (walt_cpu_high_irqload(i) || is_reserved(i))
+ continue;
/*
* p's blocked utilization is still accounted for on prev_cpu
@@ -7054,7 +7058,8 @@
trace_sched_find_best_target(p,
prefer_idle, min_util,
cpu, best_idle_cpu,
- best_active_cpu, i);
+ best_active_cpu,
+ i, -1);
return i;
}
@@ -7231,7 +7236,7 @@
if (best_idle_cpu != -1 && !is_packing_eligible(p, target_cpu, fbt_env,
active_cpus_count, best_idle_cstate)) {
- if (target_cpu == task_cpu(p))
+ if (target_cpu == prev_cpu)
fbt_env->avoid_prev_cpu = true;
target_cpu = best_idle_cpu;
@@ -7267,9 +7272,31 @@
? best_active_cpu
: best_idle_cpu;
+ if (target_cpu == -1 && cpu_isolated(prev_cpu) &&
+ isolated_candidate != -1) {
+ target_cpu = isolated_candidate;
+ fbt_env->avoid_prev_cpu = true;
+ }
+
+ /*
+ * - It is possible for target and backup
+ * to select same CPU - if so, drop backup
+ *
+ * - The next step of energy evaluation includes
+ * prev_cpu. Drop target or backup if it is
+ * same as prev_cpu.
+ */
+ if (*backup_cpu == target_cpu || *backup_cpu == prev_cpu)
+ *backup_cpu = -1;
+
+ if (target_cpu == prev_cpu) {
+ target_cpu = *backup_cpu;
+ *backup_cpu = -1;
+ }
+
trace_sched_find_best_target(p, prefer_idle, min_util, cpu,
best_idle_cpu, best_active_cpu,
- target_cpu);
+ target_cpu, *backup_cpu);
schedstat_inc(p->se.statistics.nr_wakeups_fbt_count);
schedstat_inc(this_rq()->eas_stats.fbt_count);
@@ -9700,8 +9727,11 @@
if (busiest->group_type == group_imbalanced)
goto force_balance;
- /* SD_BALANCE_NEWIDLE trumps SMP nice when underutilized */
- if (env->idle == CPU_NEWLY_IDLE && group_has_capacity(env, local) &&
+ /*
+ * When dst_cpu is idle, prevent SMP nice and/or asymmetric group
+ * capacities from resulting in underutilization due to avg_load.
+ */
+ if (env->idle != CPU_NOT_IDLE && group_has_capacity(env, local) &&
busiest->group_no_capacity)
goto force_balance;
@@ -11811,7 +11841,7 @@
if (is_max_capacity_cpu(src_cpu))
return;
- wc = ktime_get_ns();
+ wc = sched_ktime_clock();
for_each_possible_cpu(i) {
struct rq *rq = cpu_rq(i);
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index d73dfae..e24df36 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -2234,8 +2234,13 @@
#endif /* CONFIG_IRQ_TIME_ACCOUNTING */
#ifdef CONFIG_SCHED_WALT
+u64 sched_ktime_clock(void);
void note_task_waking(struct task_struct *p, u64 wallclock);
#else /* CONFIG_SCHED_WALT */
+static inline u64 sched_ktime_clock(void)
+{
+ return 0;
+}
static inline void note_task_waking(struct task_struct *p, u64 wallclock) { }
#endif /* CONFIG_SCHED_WALT */
@@ -2276,7 +2281,7 @@
data = rcu_dereference_sched(*per_cpu_ptr(&cpufreq_update_util_data,
cpu_of(rq)));
if (data)
- data->func(data, ktime_get_ns(), flags);
+ data->func(data, sched_ktime_clock(), flags);
}
static inline void cpufreq_update_this_cpu(struct rq *rq, unsigned int flags)
diff --git a/kernel/sched/walt.c b/kernel/sched/walt.c
index 8bacb6f..4fe1181 100644
--- a/kernel/sched/walt.c
+++ b/kernel/sched/walt.c
@@ -19,6 +19,7 @@
* and Todd Kjos
*/
+#include <linux/syscore_ops.h>
#include <linux/cpufreq.h>
#include <linux/list_sort.h>
#include <linux/jiffies.h>
@@ -41,6 +42,8 @@
#define EARLY_DETECTION_DURATION 9500000
+static ktime_t ktime_last;
+static bool sched_ktime_suspended;
static struct cpu_cycle_counter_cb cpu_cycle_counter_cb;
static bool use_cycle_counter;
DEFINE_MUTEX(cluster_lock);
@@ -50,6 +53,37 @@
static struct irq_work walt_cpufreq_irq_work;
static struct irq_work walt_migration_irq_work;
+u64 sched_ktime_clock(void)
+{
+ if (unlikely(sched_ktime_suspended))
+ return ktime_to_ns(ktime_last);
+ return ktime_get_ns();
+}
+
+static void sched_resume(void)
+{
+ sched_ktime_suspended = false;
+}
+
+static int sched_suspend(void)
+{
+ ktime_last = ktime_get();
+ sched_ktime_suspended = true;
+ return 0;
+}
+
+static struct syscore_ops sched_syscore_ops = {
+ .resume = sched_resume,
+ .suspend = sched_suspend
+};
+
+static int __init sched_init_ops(void)
+{
+ register_syscore_ops(&sched_syscore_ops);
+ return 0;
+}
+late_initcall(sched_init_ops);
+
static void acquire_rq_locks_irqsave(const cpumask_t *cpus,
unsigned long *flags)
{
@@ -270,12 +304,7 @@
u64 old_window_start = rq->window_start;
delta = wallclock - rq->window_start;
- /* If the MPM global timer is cleared, set delta as 0 to avoid kernel BUG happening */
- if (delta < 0) {
- delta = 0;
- WARN_ONCE(1, "WALT wallclock appears to have gone backwards or reset\n");
- }
-
+ BUG_ON(delta < 0);
if (delta < sched_ravg_window)
return old_window_start;
@@ -363,10 +392,17 @@
if (!rq->window_start || sched_disable_window_stats)
return;
+ /*
+ * We don’t have to note down an irqstart event when cycle
+ * counter is not used.
+ */
+ if (!use_cycle_counter)
+ return;
+
if (is_idle_task(curr)) {
/* We're here without rq->lock held, IRQ disabled */
raw_spin_lock(&rq->lock);
- update_task_cpu_cycles(curr, cpu, ktime_get_ns());
+ update_task_cpu_cycles(curr, cpu, sched_ktime_clock());
raw_spin_unlock(&rq->lock);
}
}
@@ -427,7 +463,7 @@
cur_jiffies_ts = get_jiffies_64();
if (is_idle_task(curr))
- update_task_ravg(curr, rq, IRQ_UPDATE, ktime_get_ns(),
+ update_task_ravg(curr, rq, IRQ_UPDATE, sched_ktime_clock(),
delta);
nr_windows = cur_jiffies_ts - rq->irqload_ts;
@@ -764,7 +800,7 @@
if (sched_disable_window_stats)
goto done;
- wallclock = ktime_get_ns();
+ wallclock = sched_ktime_clock();
update_task_ravg(task_rq(p)->curr, task_rq(p),
TASK_UPDATE,
@@ -2051,7 +2087,7 @@
return;
}
- wallclock = ktime_get_ns();
+ wallclock = sched_ktime_clock();
p->ravg.mark_start = p->last_wake_ts = wallclock;
p->last_enqueued_ts = wallclock;
p->last_switch_out_ts = 0;
@@ -2453,7 +2489,7 @@
raw_spin_lock_irqsave(&rq->lock, flags);
update_task_ravg(rq->curr, rq, TASK_UPDATE,
- ktime_get_ns(), 0);
+ sched_ktime_clock(), 0);
raw_spin_unlock_irqrestore(&rq->lock, flags);
}
}
@@ -2603,7 +2639,7 @@
return;
}
- wallclock = ktime_get_ns();
+ wallclock = sched_ktime_clock();
/*
* wakeup of two or more related tasks could race with each other and
@@ -2630,7 +2666,7 @@
grp->preferred_cluster = best_cluster(grp,
combined_demand, group_boost);
- grp->last_update = ktime_get_ns();
+ grp->last_update = sched_ktime_clock();
trace_sched_set_preferred_cluster(grp, combined_demand);
}
@@ -2654,7 +2690,7 @@
* has passed since we last updated preference
*/
if (abs(new_load - old_load) > sched_ravg_window / 4 ||
- ktime_get_ns() - grp->last_update > sched_ravg_window)
+ sched_ktime_clock() - grp->last_update > sched_ravg_window)
return 1;
return 0;
@@ -3037,7 +3073,7 @@
bool new_task;
int i;
- wallclock = ktime_get_ns();
+ wallclock = sched_ktime_clock();
update_task_ravg(rq->curr, rq, TASK_UPDATE, wallclock, 0);
update_task_ravg(p, rq, TASK_UPDATE, wallclock, 0);
@@ -3145,8 +3181,9 @@
for_each_cpu(cpu, cpu_possible_mask)
raw_spin_lock(&cpu_rq(cpu)->lock);
- wc = ktime_get_ns();
+ wc = sched_ktime_clock();
walt_load_reported_window = atomic64_read(&walt_irq_work_lastq_ws);
+
for_each_sched_cluster(cluster) {
u64 aggr_grp_load = 0;
diff --git a/kernel/sched/walt.h b/kernel/sched/walt.h
index be06e7d4..cac925c 100644
--- a/kernel/sched/walt.h
+++ b/kernel/sched/walt.h
@@ -292,7 +292,7 @@
static inline void walt_update_last_enqueue(struct task_struct *p)
{
- p->last_enqueued_ts = ktime_get_ns();
+ p->last_enqueued_ts = sched_ktime_clock();
}
extern void walt_rotate_work_init(void);
extern void walt_rotation_checkpoint(int nr_big);
diff --git a/kernel/smpboot.c b/kernel/smpboot.c
index 10c5a3a..653cf6d 100644
--- a/kernel/smpboot.c
+++ b/kernel/smpboot.c
@@ -106,6 +106,7 @@
{
struct smpboot_thread_data *td = data;
struct smp_hotplug_thread *ht = td->ht;
+ unsigned long flags;
while (1) {
set_current_state(TASK_INTERRUPTIBLE);
@@ -157,9 +158,9 @@
* p->state = TASK_RUNNING;
* schedule();
*/
- raw_spin_lock(¤t->pi_lock);
+ raw_spin_lock_irqsave(¤t->pi_lock, flags);
__set_current_state(TASK_RUNNING);
- raw_spin_unlock(¤t->pi_lock);
+ raw_spin_unlock_irqrestore(¤t->pi_lock, flags);
preempt_enable();
if (ht->park && td->status == HP_THREAD_ACTIVE) {
BUG_ON(td->cpu != smp_processor_id());
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 09a1611..75ae656 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -1486,6 +1486,15 @@
.extra1 = &zero,
.extra2 = &one_hundred,
},
+ {
+ .procname = "want_old_faultaround_pte",
+ .data = &want_old_faultaround_pte,
+ .maxlen = sizeof(want_old_faultaround_pte),
+ .mode = 0644,
+ .proc_handler = proc_dointvec_minmax,
+ .extra1 = &zero,
+ .extra2 = &one,
+ },
#ifdef CONFIG_HUGETLB_PAGE
{
.procname = "nr_hugepages",
diff --git a/mm/Kconfig b/mm/Kconfig
index 051f7bc..b452197 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -638,6 +638,16 @@
information to userspace via debugfs.
If unsure, say N.
+config VMAP_LAZY_PURGING_FACTOR
+ int "multiplier to the size of purged vmap areas"
+ default "8" if ARM
+ default "32"
+ help
+ It is used as a multiplier to the max VA pages purged in a
+ single attempt. For 32-bit in order to reduce fragmentation
+ of vmalloc space, we decrease the default value to "8".
+
+
config GENERIC_EARLY_IOREMAP
bool
@@ -747,3 +757,25 @@
(addr, addr + size-bytes) of the process.
Any other vaule is ignored.
+
+config ARCH_SUPPORTS_SPECULATIVE_PAGE_FAULT
+ def_bool n
+
+config SPECULATIVE_PAGE_FAULT
+ bool "Speculative page faults"
+ default y
+ depends on ARCH_SUPPORTS_SPECULATIVE_PAGE_FAULT
+ depends on MMU && SMP
+ help
+ Try to handle user space page faults without holding the mmap_sem.
+
+ This should allow better concurrency for massively threaded process
+ since the page fault handler will not wait for other threads memory
+ layout change to be done, assuming that this change is done in another
+ part of the process's memory space. This type of page fault is named
+ speculative page fault.
+
+ If the speculative page fault fails because of a concurrency is
+ detected or because underlying PMD or PTE tables are not yet
+ allocating, it is failing its processing and a classic page fault
+ is then tried.
diff --git a/mm/filemap.c b/mm/filemap.c
index 211df83..b27d2ca 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -47,6 +47,8 @@
#include <asm/mman.h>
+int want_old_faultaround_pte = 1;
+
/*
* Shared mappings implemented 30.11.1994. It's not fully working yet,
* though.
@@ -2287,6 +2289,14 @@
if (fe->pte)
fe->pte += iter.index - last_pgoff;
last_pgoff = iter.index;
+
+ if (want_old_faultaround_pte) {
+ if (fe->address == fe->fault_address)
+ fe->flags &= ~FAULT_FLAG_PREFAULT_OLD;
+ else
+ fe->flags |= FAULT_FLAG_PREFAULT_OLD;
+ }
+
if (alloc_set_pte(fe, NULL, page))
goto unlock;
unlock_page(page);
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 7243728..a557862 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -958,8 +958,8 @@
for (i = 0; i < HPAGE_PMD_NR; i++, haddr += PAGE_SIZE) {
pte_t entry;
- entry = mk_pte(pages[i], vma->vm_page_prot);
- entry = maybe_mkwrite(pte_mkdirty(entry), vma);
+ entry = mk_pte(pages[i], fe->vma_page_prot);
+ entry = maybe_mkwrite(pte_mkdirty(entry), fe->vma_flags);
memcg = (void *)page_private(pages[i]);
set_page_private(pages[i], 0);
page_add_new_anon_rmap(pages[i], fe->vma, haddr, false);
@@ -1679,7 +1679,7 @@
entry = pte_swp_mksoft_dirty(entry);
} else {
entry = mk_pte(page + i, READ_ONCE(vma->vm_page_prot));
- entry = maybe_mkwrite(entry, vma);
+ entry = maybe_mkwrite(entry, vma->vm_flags);
if (!write)
entry = pte_wrprotect(entry);
if (!young)
diff --git a/mm/init-mm.c b/mm/init-mm.c
index 975e49f..4d21629 100644
--- a/mm/init-mm.c
+++ b/mm/init-mm.c
@@ -16,6 +16,9 @@
struct mm_struct init_mm = {
.mm_rb = RB_ROOT,
+#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
+ .mm_rb_lock = __RW_LOCK_UNLOCKED(init_mm.mm_rb_lock),
+#endif
.pgd = swapper_pg_dir,
.mm_users = ATOMIC_INIT(2),
.mm_count = ATOMIC_INIT(1),
diff --git a/mm/internal.h b/mm/internal.h
index 6aa1c51..d9ac6de 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -38,6 +38,26 @@
int do_swap_page(struct fault_env *fe, pte_t orig_pte);
+#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
+extern struct vm_area_struct *get_vma(struct mm_struct *mm,
+ unsigned long addr);
+extern void put_vma(struct vm_area_struct *vma);
+
+static inline bool vma_has_changed(struct fault_env *fe)
+{
+ int ret = RB_EMPTY_NODE(&fe->vma->vm_rb);
+ unsigned int seq = READ_ONCE(fe->vma->vm_sequence.sequence);
+
+ /*
+ * Matches both the wmb in write_seqlock_{begin,end}() and
+ * the wmb in vma_rb_erase().
+ */
+ smp_rmb();
+
+ return ret || seq != fe->sequence;
+}
+#endif /* CONFIG_SPECULATIVE_PAGE_FAULT */
+
void free_pgtables(struct mmu_gather *tlb, struct vm_area_struct *start_vma,
unsigned long floor, unsigned long ceiling);
diff --git a/mm/khugepaged.c b/mm/khugepaged.c
index 1df37ee..6b58aaf 100644
--- a/mm/khugepaged.c
+++ b/mm/khugepaged.c
@@ -887,6 +887,8 @@
.address = address,
.flags = FAULT_FLAG_ALLOW_RETRY,
.pmd = pmd,
+ .vma_flags = vma->vm_flags,
+ .vma_page_prot = vma->vm_page_prot,
};
/* we only decide to swapin, if there is enough young ptes */
@@ -1011,6 +1013,7 @@
if (mm_find_pmd(mm, address) != pmd)
goto out;
+ vm_write_begin(vma);
anon_vma_lock_write(vma->anon_vma);
pte = pte_offset_map(pmd, address);
@@ -1046,6 +1049,7 @@
pmd_populate(mm, pmd, pmd_pgtable(_pmd));
spin_unlock(pmd_ptl);
anon_vma_unlock_write(vma->anon_vma);
+ vm_write_end(vma);
result = SCAN_FAIL;
goto out;
}
@@ -1080,6 +1084,7 @@
set_pmd_at(mm, address, pmd, _pmd);
update_mmu_cache_pmd(vma, address, pmd);
spin_unlock(pmd_ptl);
+ vm_write_end(vma);
*hpage = NULL;
diff --git a/mm/madvise.c b/mm/madvise.c
index 59d1aae..ee7ad9b 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -135,8 +135,10 @@
/*
* vm_flags is protected by the mmap_sem held in write mode.
*/
- vma->vm_flags = new_flags;
+ vm_write_begin(vma);
+ WRITE_ONCE(vma->vm_flags, new_flags);
+ vm_write_end(vma);
out:
if (error == -ENOMEM)
error = -EAGAIN;
@@ -404,9 +406,11 @@
.private = tlb,
};
+ vm_write_begin(vma);
tlb_start_vma(tlb, vma);
walk_page_range(addr, end, &free_walk);
tlb_end_vma(tlb, vma);
+ vm_write_end(vma);
}
static int madvise_free_single_vma(struct vm_area_struct *vma,
diff --git a/mm/memory.c b/mm/memory.c
index cc6ab38..7a88700 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -75,6 +75,9 @@
#include "internal.h"
+#define CREATE_TRACE_POINTS
+#include <trace/events/pagefault.h>
+
#if defined(LAST_CPUPID_NOT_IN_PAGE_FLAGS) && !defined(CONFIG_COMPILE_TEST)
#warning Unfortunate NUMA and NUMA Balancing config, growing page-frame for last_cpupid.
#endif
@@ -549,7 +552,9 @@
* Hide vma from rmap and truncate_pagecache before freeing
* pgtables
*/
+ vm_write_begin(vma);
unlink_anon_vmas(vma);
+ vm_write_end(vma);
unlink_file_vma(vma);
if (is_vm_hugetlb_page(vma)) {
@@ -563,7 +568,9 @@
&& !is_vm_hugetlb_page(next)) {
vma = next;
next = vma->vm_next;
+ vm_write_begin(vma);
unlink_anon_vmas(vma);
+ vm_write_end(vma);
unlink_file_vma(vma);
}
free_pgd_range(tlb, addr, vma->vm_end,
@@ -689,7 +696,8 @@
if (page)
dump_page(page, "bad pte");
pr_alert("addr:%p vm_flags:%08lx anon_vma:%p mapping:%p index:%lx\n",
- (void *)addr, vma->vm_flags, vma->anon_vma, mapping, index);
+ (void *)addr, READ_ONCE(vma->vm_flags), vma->anon_vma,
+ mapping, index);
/*
* Choose text because data symbols depend on CONFIG_KALLSYMS_ALL=y
*/
@@ -703,7 +711,8 @@
}
/*
- * vm_normal_page -- This function gets the "struct page" associated with a pte.
+ * __vm_normal_page -- This function gets the "struct page" associated with
+ * a pte.
*
* "Special" mappings do not wish to be associated with a "struct page" (either
* it doesn't exist, or it exists but they don't want to touch it). In this
@@ -749,8 +758,8 @@
#else
# define HAVE_PTE_SPECIAL 0
#endif
-struct page *vm_normal_page(struct vm_area_struct *vma, unsigned long addr,
- pte_t pte)
+struct page *__vm_normal_page(struct vm_area_struct *vma, unsigned long addr,
+ pte_t pte, unsigned long vma_flags)
{
unsigned long pfn = pte_pfn(pte);
@@ -759,7 +768,7 @@
goto check_pfn;
if (vma->vm_ops && vma->vm_ops->find_special_page)
return vma->vm_ops->find_special_page(vma, addr);
- if (vma->vm_flags & (VM_PFNMAP | VM_MIXEDMAP))
+ if (vma_flags & (VM_PFNMAP | VM_MIXEDMAP))
return NULL;
if (!is_zero_pfn(pfn))
print_bad_pte(vma, addr, pte, NULL);
@@ -767,9 +776,13 @@
}
/* !HAVE_PTE_SPECIAL case follows: */
+ /*
+ * This part should never get called when CONFIG_SPECULATIVE_PAGE_FAULT
+ * is set. This is mainly because we can't rely on vm_start.
+ */
- if (unlikely(vma->vm_flags & (VM_PFNMAP|VM_MIXEDMAP))) {
- if (vma->vm_flags & VM_MIXEDMAP) {
+ if (unlikely(vma_flags & (VM_PFNMAP|VM_MIXEDMAP))) {
+ if (vma_flags & VM_MIXEDMAP) {
if (!pfn_valid(pfn))
return NULL;
goto out;
@@ -778,7 +791,7 @@
off = (addr - vma->vm_start) >> PAGE_SHIFT;
if (pfn == vma->vm_pgoff + off)
return NULL;
- if (!is_cow_mapping(vma->vm_flags))
+ if (!is_cow_mapping(vma_flags))
return NULL;
}
}
@@ -1285,6 +1298,7 @@
unsigned long next;
BUG_ON(addr >= end);
+ vm_write_begin(vma);
tlb_start_vma(tlb, vma);
pgd = pgd_offset(vma->vm_mm, addr);
do {
@@ -1294,6 +1308,7 @@
next = zap_pud_range(tlb, vma, pgd, addr, next, details);
} while (pgd++, addr = next, addr != end);
tlb_end_vma(tlb, vma);
+ vm_write_end(vma);
}
@@ -1961,6 +1976,145 @@
}
EXPORT_SYMBOL_GPL(apply_to_page_range);
+#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
+static bool pte_spinlock(struct mm_struct *mm,
+ struct fault_env *fe)
+{
+ bool ret = false;
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+ pmd_t pmdval;
+#endif
+
+ /* Check if vma is still valid */
+ if (!(fe->flags & FAULT_FLAG_SPECULATIVE)) {
+ fe->ptl = pte_lockptr(mm, fe->pmd);
+ spin_lock(fe->ptl);
+ return true;
+ }
+
+ local_irq_disable();
+ if (vma_has_changed(fe)) {
+ trace_spf_vma_changed(_RET_IP_, fe->vma, fe->address);
+ goto out;
+ }
+
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+ /*
+ * We check if the pmd value is still the same to ensure that there
+ * is not a huge collapse operation in progress in our back.
+ */
+ pmdval = READ_ONCE(*fe->pmd);
+ if (!pmd_same(pmdval, fe->orig_pmd)) {
+ trace_spf_pmd_changed(_RET_IP_, fe->vma, fe->address);
+ goto out;
+ }
+#endif
+
+ fe->ptl = pte_lockptr(mm, fe->pmd);
+ if (unlikely(!spin_trylock(fe->ptl))) {
+ trace_spf_pte_lock(_RET_IP_, fe->vma, fe->address);
+ goto out;
+ }
+
+ if (vma_has_changed(fe)) {
+ spin_unlock(fe->ptl);
+ trace_spf_vma_changed(_RET_IP_, fe->vma, fe->address);
+ goto out;
+ }
+
+ ret = true;
+out:
+ local_irq_enable();
+ return ret;
+}
+
+static bool pte_map_lock(struct mm_struct *mm,
+ struct fault_env *fe)
+{
+ bool ret = false;
+ pte_t *pte;
+ spinlock_t *ptl;
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+ pmd_t pmdval;
+#endif
+
+ if (!(fe->flags & FAULT_FLAG_SPECULATIVE)) {
+ fe->pte = pte_offset_map_lock(mm, fe->pmd,
+ fe->address, &fe->ptl);
+ return true;
+ }
+
+ /*
+ * The first vma_has_changed() guarantees the page-tables are still
+ * valid, having IRQs disabled ensures they stay around, hence the
+ * second vma_has_changed() to make sure they are still valid once
+ * we've got the lock. After that a concurrent zap_pte_range() will
+ * block on the PTL and thus we're safe.
+ */
+ local_irq_disable();
+ if (vma_has_changed(fe)) {
+ trace_spf_vma_changed(_RET_IP_, fe->vma, fe->address);
+ goto out;
+ }
+
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+ /*
+ * We check if the pmd value is still the same to ensure that there
+ * is not a huge collapse operation in progress in our back.
+ */
+ pmdval = READ_ONCE(*fe->pmd);
+ if (!pmd_same(pmdval, fe->orig_pmd)) {
+ trace_spf_pmd_changed(_RET_IP_, fe->vma, fe->address);
+ goto out;
+ }
+#endif
+
+ /*
+ * Same as pte_offset_map_lock() except that we call
+ * spin_trylock() in place of spin_lock() to avoid race with
+ * unmap path which may have the lock and wait for this CPU
+ * to invalidate TLB but this CPU has irq disabled.
+ * Since we are in a speculative patch, accept it could fail
+ */
+ ptl = pte_lockptr(mm, fe->pmd);
+ pte = pte_offset_map(fe->pmd, fe->address);
+ if (unlikely(!spin_trylock(ptl))) {
+ pte_unmap(pte);
+ trace_spf_pte_lock(_RET_IP_, fe->vma, fe->address);
+ goto out;
+ }
+
+ if (vma_has_changed(fe)) {
+ pte_unmap_unlock(pte, ptl);
+ trace_spf_vma_changed(_RET_IP_, fe->vma, fe->address);
+ goto out;
+ }
+
+ fe->pte = pte;
+ fe->ptl = ptl;
+ ret = true;
+out:
+ local_irq_enable();
+ return ret;
+}
+#else
+static inline bool pte_spinlock(struct mm_struct *mm,
+ struct fault_env *fe)
+{
+ fe->ptl = pte_lockptr(mm, fe->pmd);
+ spin_lock(fe->ptl);
+ return true;
+}
+
+static inline bool pte_map_lock(struct mm_struct *mm,
+ struct fault_env *fe)
+{
+ fe->pte = pte_offset_map_lock(mm, fe->pmd,
+ fe->address, &fe->ptl);
+ return true;
+}
+#endif /* CONFIG_SPECULATIVE_PAGE_FAULT */
+
/*
* handle_pte_fault chooses page fault handler according to an entry which was
* read non-atomically. Before making any commitment, on those architectures
@@ -1968,21 +2122,30 @@
* parts, do_swap_page must check under lock before unmapping the pte and
* proceeding (but do_wp_page is only called after already making such a check;
* and do_anonymous_page can safely check later on).
+ *
+ * pte_unmap_same() returns:
+ * 0 if the PTE are the same
+ * VM_FAULT_PTNOTSAME if the PTE are different
+ * VM_FAULT_RETRY if the VMA has changed in our back during
+ * a speculative page fault handling.
*/
-static inline int pte_unmap_same(struct mm_struct *mm, pmd_t *pmd,
- pte_t *page_table, pte_t orig_pte)
+static inline int pte_unmap_same(struct mm_struct *mm, struct fault_env *fe,
+ pte_t orig_pte)
{
- int same = 1;
+ int ret = 0;
+
#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
if (sizeof(pte_t) > sizeof(unsigned long)) {
- spinlock_t *ptl = pte_lockptr(mm, pmd);
- spin_lock(ptl);
- same = pte_same(*page_table, orig_pte);
- spin_unlock(ptl);
+ if (pte_spinlock(mm, fe)) {
+ if (!pte_same(*fe->pte, orig_pte))
+ ret = VM_FAULT_PTNOTSAME;
+ spin_unlock(fe->ptl);
+ } else
+ ret = VM_FAULT_RETRY;
}
#endif
- pte_unmap(page_table);
- return same;
+ pte_unmap(fe->pte);
+ return ret;
}
static inline void cow_user_page(struct page *dst, struct page *src, unsigned long va, struct vm_area_struct *vma)
@@ -2085,7 +2248,7 @@
flush_cache_page(vma, fe->address, pte_pfn(orig_pte));
entry = pte_mkyoung(orig_pte);
- entry = maybe_mkwrite(pte_mkdirty(entry), vma);
+ entry = maybe_mkwrite(pte_mkdirty(entry), fe->vma_flags);
if (ptep_set_access_flags(vma, fe->address, fe->pte, entry, 1))
update_mmu_cache(vma, fe->address, fe->pte);
pte_unmap_unlock(fe->pte, fe->ptl);
@@ -2145,24 +2308,25 @@
const unsigned long mmun_start = fe->address & PAGE_MASK;
const unsigned long mmun_end = mmun_start + PAGE_SIZE;
struct mem_cgroup *memcg;
+ int ret = VM_FAULT_OOM;
if (unlikely(anon_vma_prepare(vma)))
- goto oom;
+ goto out;
if (is_zero_pfn(pte_pfn(orig_pte))) {
new_page = alloc_zeroed_user_highpage_movable(vma, fe->address);
if (!new_page)
- goto oom;
+ goto out;
} else {
new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma,
fe->address);
if (!new_page)
- goto oom;
+ goto out;
cow_user_page(new_page, old_page, fe->address, vma);
}
if (mem_cgroup_try_charge(new_page, mm, GFP_KERNEL, &memcg, false))
- goto oom_free_new;
+ goto out_free_new;
__SetPageUptodate(new_page);
@@ -2171,7 +2335,10 @@
/*
* Re-check the pte - we dropped the lock
*/
- fe->pte = pte_offset_map_lock(mm, fe->pmd, fe->address, &fe->ptl);
+ if (!pte_map_lock(mm, fe)) {
+ ret = VM_FAULT_RETRY;
+ goto out_uncharge;
+ }
if (likely(pte_same(*fe->pte, orig_pte))) {
if (old_page) {
if (!PageAnon(old_page)) {
@@ -2183,8 +2350,8 @@
inc_mm_counter_fast(mm, MM_ANONPAGES);
}
flush_cache_page(vma, fe->address, pte_pfn(orig_pte));
- entry = mk_pte(new_page, vma->vm_page_prot);
- entry = maybe_mkwrite(pte_mkdirty(entry), vma);
+ entry = mk_pte(new_page, fe->vma_page_prot);
+ entry = maybe_mkwrite(pte_mkdirty(entry), fe->vma_flags);
/*
* Clear the pte entry and flush it first, before updating the
* pte with the new entry. This will avoid a race condition
@@ -2192,9 +2359,9 @@
* thread doing COW.
*/
ptep_clear_flush_notify(vma, fe->address, fe->pte);
- page_add_new_anon_rmap(new_page, vma, fe->address, false);
+ __page_add_new_anon_rmap(new_page, vma, fe->address, false);
mem_cgroup_commit_charge(new_page, memcg, false, false);
- lru_cache_add_active_or_unevictable(new_page, vma);
+ __lru_cache_add_active_or_unevictable(new_page, fe->vma_flags);
/*
* We call the notify macro here because, when using secondary
* mmu page tables (such as kvm shadow page tables), we want the
@@ -2245,7 +2412,7 @@
* Don't let another task, with possibly unlocked vma,
* keep the mlocked page.
*/
- if (page_copied && (vma->vm_flags & VM_LOCKED)) {
+ if (page_copied && (fe->vma_flags & VM_LOCKED)) {
lock_page(old_page); /* LRU manipulation */
if (PageMlocked(old_page))
munlock_vma_page(old_page);
@@ -2254,12 +2421,14 @@
put_page(old_page);
}
return page_copied ? VM_FAULT_WRITE : 0;
-oom_free_new:
+out_uncharge:
+ mem_cgroup_cancel_charge(new_page, memcg, false);
+out_free_new:
put_page(new_page);
-oom:
+out:
if (old_page)
put_page(old_page);
- return VM_FAULT_OOM;
+ return ret;
}
/*
@@ -2284,8 +2453,8 @@
ret = vma->vm_ops->pfn_mkwrite(vma, &vmf);
if (ret & VM_FAULT_ERROR)
return ret;
- fe->pte = pte_offset_map_lock(vma->vm_mm, fe->pmd, fe->address,
- &fe->ptl);
+ if (!pte_map_lock(vma->vm_mm, fe))
+ return VM_FAULT_RETRY;
/*
* We might have raced with another page fault while we
* released the pte_offset_map_lock.
@@ -2361,7 +2530,8 @@
struct vm_area_struct *vma = fe->vma;
struct page *old_page;
- old_page = vm_normal_page(vma, fe->address, orig_pte);
+ old_page = __vm_normal_page(vma, fe->address, orig_pte,
+ fe->vma_flags);
if (!old_page) {
/*
* VM_MIXEDMAP !pfn_valid() case, or VM_SOFTDIRTY clear on a
@@ -2370,7 +2540,7 @@
* We should not cow pages in a shared writeable mapping.
* Just mark the pages writable and/or call ops->pfn_mkwrite.
*/
- if ((vma->vm_flags & (VM_WRITE|VM_SHARED)) ==
+ if ((fe->vma_flags & (VM_WRITE|VM_SHARED)) ==
(VM_WRITE|VM_SHARED))
return wp_pfn_shared(fe, orig_pte);
@@ -2388,8 +2558,11 @@
get_page(old_page);
pte_unmap_unlock(fe->pte, fe->ptl);
lock_page(old_page);
- fe->pte = pte_offset_map_lock(vma->vm_mm, fe->pmd,
- fe->address, &fe->ptl);
+ if (!pte_map_lock(vma->vm_mm, fe)) {
+ unlock_page(old_page);
+ put_page(old_page);
+ return VM_FAULT_RETRY;
+ }
if (!pte_same(*fe->pte, orig_pte)) {
unlock_page(old_page);
pte_unmap_unlock(fe->pte, fe->ptl);
@@ -2413,7 +2586,7 @@
return wp_page_reuse(fe, orig_pte, old_page, 0, 0);
}
unlock_page(old_page);
- } else if (unlikely((vma->vm_flags & (VM_WRITE|VM_SHARED)) ==
+ } else if (unlikely((fe->vma_flags & (VM_WRITE|VM_SHARED)) ==
(VM_WRITE|VM_SHARED))) {
return wp_page_shared(fe, orig_pte, old_page);
}
@@ -2523,9 +2696,17 @@
int exclusive = 0;
int ret = 0;
- if (!pte_unmap_same(vma->vm_mm, fe->pmd, fe->pte, orig_pte))
+ ret = pte_unmap_same(vma->vm_mm, fe, orig_pte);
+ if (ret) {
+ /*
+ * If pte != orig_pte, this means another thread did the
+ * swap operation in our back.
+ * So nothing else to do.
+ */
+ if (ret == VM_FAULT_PTNOTSAME)
+ ret = 0;
goto out;
-
+ }
entry = pte_to_swp_entry(orig_pte);
if (unlikely(non_swap_entry(entry))) {
if (is_migration_entry(entry)) {
@@ -2545,11 +2726,16 @@
GFP_HIGHUSER_MOVABLE, vma, fe->address);
if (!page) {
/*
- * Back out if somebody else faulted in this pte
- * while we released the pte lock.
+ * Back out if the VMA has changed in our back during
+ * a speculative page fault or if somebody else
+ * faulted in this pte while we released the pte lock.
*/
- fe->pte = pte_offset_map_lock(vma->vm_mm, fe->pmd,
- fe->address, &fe->ptl);
+ if (!pte_map_lock(vma->vm_mm, fe)) {
+ delayacct_clear_flag(DELAYACCT_PF_SWAPIN);
+ ret = VM_FAULT_RETRY;
+ goto out;
+ }
+
if (likely(pte_same(*fe->pte, orig_pte)))
ret = VM_FAULT_OOM;
delayacct_clear_flag(DELAYACCT_PF_SWAPIN);
@@ -2603,10 +2789,13 @@
}
/*
- * Back out if somebody else already faulted in this pte.
+ * Back out if the VMA has changed in our back during a speculative
+ * page fault or if somebody else already faulted in this pte.
*/
- fe->pte = pte_offset_map_lock(vma->vm_mm, fe->pmd, fe->address,
- &fe->ptl);
+ if (!pte_map_lock(vma->vm_mm, fe)) {
+ ret = VM_FAULT_RETRY;
+ goto out_cancel_cgroup;
+ }
if (unlikely(!pte_same(*fe->pte, orig_pte)))
goto out_nomap;
@@ -2627,9 +2816,9 @@
inc_mm_counter_fast(vma->vm_mm, MM_ANONPAGES);
dec_mm_counter_fast(vma->vm_mm, MM_SWAPENTS);
- pte = mk_pte(page, vma->vm_page_prot);
+ pte = mk_pte(page, fe->vma_page_prot);
if ((fe->flags & FAULT_FLAG_WRITE) && reuse_swap_page(page, NULL)) {
- pte = maybe_mkwrite(pte_mkdirty(pte), vma);
+ pte = maybe_mkwrite(pte_mkdirty(pte), fe->vma_flags);
fe->flags &= ~FAULT_FLAG_WRITE;
ret |= VM_FAULT_WRITE;
exclusive = RMAP_EXCLUSIVE;
@@ -2643,14 +2832,14 @@
mem_cgroup_commit_charge(page, memcg, true, false);
activate_page(page);
} else { /* ksm created a completely new copy */
- page_add_new_anon_rmap(page, vma, fe->address, false);
+ __page_add_new_anon_rmap(page, vma, fe->address, false);
mem_cgroup_commit_charge(page, memcg, false, false);
- lru_cache_add_active_or_unevictable(page, vma);
+ __lru_cache_add_active_or_unevictable(page, fe->vma_flags);
}
swap_free(entry);
if (mem_cgroup_swap_full(page) ||
- (vma->vm_flags & VM_LOCKED) || PageMlocked(page))
+ (fe->vma_flags & VM_LOCKED) || PageMlocked(page))
try_to_free_swap(page);
unlock_page(page);
if (page != swapcache) {
@@ -2680,8 +2869,9 @@
out:
return ret;
out_nomap:
- mem_cgroup_cancel_charge(page, memcg, false);
pte_unmap_unlock(fe->pte, fe->ptl);
+out_cancel_cgroup:
+ mem_cgroup_cancel_charge(page, memcg, false);
out_page:
unlock_page(page);
out_release:
@@ -2703,10 +2893,11 @@
struct vm_area_struct *vma = fe->vma;
struct mem_cgroup *memcg;
struct page *page;
+ int ret = 0;
pte_t entry;
/* File mapping without ->vm_ops ? */
- if (vma->vm_flags & VM_SHARED)
+ if (fe->vma_flags & VM_SHARED)
return VM_FAULT_SIGBUS;
/*
@@ -2730,11 +2921,19 @@
if (!(fe->flags & FAULT_FLAG_WRITE) &&
!mm_forbids_zeropage(vma->vm_mm)) {
entry = pte_mkspecial(pfn_pte(my_zero_pfn(fe->address),
- vma->vm_page_prot));
- fe->pte = pte_offset_map_lock(vma->vm_mm, fe->pmd, fe->address,
- &fe->ptl);
+ fe->vma_page_prot));
+ if (!pte_map_lock(vma->vm_mm, fe))
+ return VM_FAULT_RETRY;
if (!pte_none(*fe->pte))
goto unlock;
+ /*
+ * Don't call the userfaultfd during the speculative path.
+ * We already checked for the VMA to not be managed through
+ * userfaultfd, but it may be set in our back once we have lock
+ * the pte. In such a case we can ignore it this time.
+ */
+ if (fe->flags & FAULT_FLAG_SPECULATIVE)
+ goto setpte;
/* Deliver the page fault to userland, check inside PT lock */
if (userfaultfd_missing(vma)) {
pte_unmap_unlock(fe->pte, fe->ptl);
@@ -2760,17 +2959,19 @@
*/
__SetPageUptodate(page);
- entry = mk_pte(page, vma->vm_page_prot);
- if (vma->vm_flags & VM_WRITE)
+ entry = mk_pte(page, fe->vma_page_prot);
+ if (fe->vma_flags & VM_WRITE)
entry = pte_mkwrite(pte_mkdirty(entry));
- fe->pte = pte_offset_map_lock(vma->vm_mm, fe->pmd, fe->address,
- &fe->ptl);
- if (!pte_none(*fe->pte))
+ if (!pte_map_lock(vma->vm_mm, fe)) {
+ ret = VM_FAULT_RETRY;
goto release;
+ }
+ if (!pte_none(*fe->pte))
+ goto unlock_and_release;
/* Deliver the page fault to userland, check inside PT lock */
- if (userfaultfd_missing(vma)) {
+ if (!(fe->flags & FAULT_FLAG_SPECULATIVE) && userfaultfd_missing(vma)) {
pte_unmap_unlock(fe->pte, fe->ptl);
mem_cgroup_cancel_charge(page, memcg, false);
put_page(page);
@@ -2778,9 +2979,9 @@
}
inc_mm_counter_fast(vma->vm_mm, MM_ANONPAGES);
- page_add_new_anon_rmap(page, vma, fe->address, false);
+ __page_add_new_anon_rmap(page, vma, fe->address, false);
mem_cgroup_commit_charge(page, memcg, false, false);
- lru_cache_add_active_or_unevictable(page, vma);
+ __lru_cache_add_active_or_unevictable(page, fe->vma_flags);
setpte:
set_pte_at(vma->vm_mm, fe->address, fe->pte, entry);
@@ -2788,11 +2989,13 @@
update_mmu_cache(vma, fe->address, fe->pte);
unlock:
pte_unmap_unlock(fe->pte, fe->ptl);
- return 0;
+ return ret;
+unlock_and_release:
+ pte_unmap_unlock(fe->pte, fe->ptl);
release:
mem_cgroup_cancel_charge(page, memcg, false);
put_page(page);
- goto unlock;
+ return ret;
oom_free_page:
put_page(page);
oom:
@@ -2897,8 +3100,9 @@
* pte_none() under vmf->ptl protection when we return to
* alloc_set_pte().
*/
- fe->pte = pte_offset_map_lock(vma->vm_mm, fe->pmd, fe->address,
- &fe->ptl);
+ if (!pte_map_lock(vma->vm_mm, fe))
+ return VM_FAULT_RETRY;
+
return 0;
}
@@ -2937,7 +3141,7 @@
for (i = 0; i < HPAGE_PMD_NR; i++)
flush_icache_page(vma, page + i);
- entry = mk_huge_pmd(page, vma->vm_page_prot);
+ entry = mk_huge_pmd(page, fe->vma_page_prot);
if (write)
entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma);
@@ -3005,15 +3209,19 @@
return VM_FAULT_NOPAGE;
flush_icache_page(vma, page);
- entry = mk_pte(page, vma->vm_page_prot);
+ entry = mk_pte(page, fe->vma_page_prot);
if (write)
- entry = maybe_mkwrite(pte_mkdirty(entry), vma);
+ entry = maybe_mkwrite(pte_mkdirty(entry), fe->vma_flags);
+
+ if (fe->flags & FAULT_FLAG_PREFAULT_OLD)
+ entry = pte_mkold(entry);
+
/* copy-on-write page */
- if (write && !(vma->vm_flags & VM_SHARED)) {
+ if (write && !(fe->vma_flags & VM_SHARED)) {
inc_mm_counter_fast(vma->vm_mm, MM_ANONPAGES);
- page_add_new_anon_rmap(page, vma, fe->address, false);
+ __page_add_new_anon_rmap(page, vma, fe->address, false);
mem_cgroup_commit_charge(page, memcg, false, false);
- lru_cache_add_active_or_unevictable(page, vma);
+ __lru_cache_add_active_or_unevictable(page, fe->vma_flags);
} else {
inc_mm_counter_fast(vma->vm_mm, mm_counter_file(page));
page_add_file_rmap(page, false);
@@ -3026,8 +3234,16 @@
return 0;
}
+/*
+ * If architecture emulates "accessed" or "young" bit without HW support,
+ * there is no much gain with fault_around.
+ */
static unsigned long fault_around_bytes __read_mostly =
- rounddown_pow_of_two(4096);
+#ifndef __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
+ PAGE_SIZE;
+#else
+ rounddown_pow_of_two(65536);
+#endif
#ifdef CONFIG_DEBUG_FS
static int fault_around_bytes_get(void *data, u64 *val)
@@ -3096,6 +3312,7 @@
pgoff_t end_pgoff;
int off, ret = 0;
+ fe->fault_address = address;
nr_pages = READ_ONCE(fault_around_bytes) >> PAGE_SHIFT;
mask = ~(nr_pages * PAGE_SIZE - 1) & PAGE_MASK;
@@ -3301,7 +3518,7 @@
return VM_FAULT_SIGBUS;
if (!(fe->flags & FAULT_FLAG_WRITE))
return do_read_fault(fe, pgoff);
- if (!(vma->vm_flags & VM_SHARED))
+ if (!(fe->vma_flags & VM_SHARED))
return do_cow_fault(fe, pgoff);
return do_shared_fault(fe, pgoff);
}
@@ -3341,22 +3558,22 @@
* page table entry is not accessible, so there would be no
* concurrent hardware modifications to the PTE.
*/
- fe->ptl = pte_lockptr(vma->vm_mm, fe->pmd);
- spin_lock(fe->ptl);
+ if (!pte_spinlock(vma->vm_mm, fe))
+ return VM_FAULT_RETRY;
if (unlikely(!pte_same(*fe->pte, pte))) {
pte_unmap_unlock(fe->pte, fe->ptl);
goto out;
}
/* Make it present again */
- pte = pte_modify(pte, vma->vm_page_prot);
+ pte = pte_modify(pte, fe->vma_page_prot);
pte = pte_mkyoung(pte);
if (was_writable)
pte = pte_mkwrite(pte);
set_pte_at(vma->vm_mm, fe->address, fe->pte, pte);
update_mmu_cache(vma, fe->address, fe->pte);
- page = vm_normal_page(vma, fe->address, pte);
+ page = __vm_normal_page(vma, fe->address, pte, fe->vma_flags);
if (!page) {
pte_unmap_unlock(fe->pte, fe->ptl);
return 0;
@@ -3383,7 +3600,7 @@
* Flag if the page is shared between multiple address spaces. This
* is later used when determining whether to group tasks together
*/
- if (page_mapcount(page) > 1 && (vma->vm_flags & VM_SHARED))
+ if (page_mapcount(page) > 1 && (fe->vma_flags & VM_SHARED))
flags |= TNF_SHARED;
last_cpupid = page_cpupid_last(page);
@@ -3397,7 +3614,7 @@
}
/* Migrate to the requested node */
- migrated = migrate_misplaced_page(page, vma, target_nid);
+ migrated = migrate_misplaced_page(page, fe, target_nid);
if (migrated) {
page_nid = target_nid;
flags |= TNF_MIGRATED;
@@ -3430,7 +3647,7 @@
fe->flags);
/* COW handled on pte level: split pmd */
- VM_BUG_ON_VMA(fe->vma->vm_flags & VM_SHARED, fe->vma);
+ VM_BUG_ON_VMA(fe->vma_flags & VM_SHARED, fe->vma);
split_huge_pmd(fe->vma, fe->pmd, fe->address);
return VM_FAULT_FALLBACK;
@@ -3458,17 +3675,26 @@
*/
static int handle_pte_fault(struct fault_env *fe)
{
- pte_t entry;
+ pte_t uninitialized_var(entry);
if (unlikely(pmd_none(*fe->pmd))) {
/*
+ * In the case of the speculative page fault handler we abort
+ * the speculative path immediately as the pmd is probably
+ * in the way to be converted in a huge one. We will try
+ * again holding the mmap_sem (which implies that the collapse
+ * operation is done).
+ */
+ if (fe->flags & FAULT_FLAG_SPECULATIVE)
+ return VM_FAULT_RETRY;
+ /*
* Leave __pte_alloc() until later: because vm_ops->fault may
* want to allocate huge page, and if we expose page table
* for an instant, it will be difficult to retract from
* concurrent faults and from rmap lookups.
*/
fe->pte = NULL;
- } else {
+ } else if (!(fe->flags & FAULT_FLAG_SPECULATIVE)) {
/* See comment in pte_alloc_one_map() */
if (pmd_devmap_trans_unstable(fe->pmd))
return 0;
@@ -3477,6 +3703,9 @@
* pmd from under us anymore at this point because we hold the
* mmap_sem read mode and khugepaged takes it in write mode.
* So now it's safe to run pte_offset_map().
+ * This is not applicable to the speculative page fault handler
+ * but in that case, the pte is fetched earlier in
+ * handle_speculative_fault().
*/
fe->pte = pte_offset_map(fe->pmd, fe->address);
@@ -3500,18 +3729,24 @@
if (!fe->pte) {
if (vma_is_anonymous(fe->vma))
return do_anonymous_page(fe);
+ else if (fe->flags & FAULT_FLAG_SPECULATIVE)
+ return VM_FAULT_RETRY;
else
return do_fault(fe);
}
+#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
+ if (fe->flags & FAULT_FLAG_SPECULATIVE)
+ entry = fe->orig_pte;
+#endif
if (!pte_present(entry))
return do_swap_page(fe, entry);
if (pte_protnone(entry) && vma_is_accessible(fe->vma))
return do_numa_page(fe, entry);
- fe->ptl = pte_lockptr(fe->vma->vm_mm, fe->pmd);
- spin_lock(fe->ptl);
+ if (!pte_spinlock(fe->vma->vm_mm, fe))
+ return VM_FAULT_RETRY;
if (unlikely(!pte_same(*fe->pte, entry)))
goto unlock;
if (fe->flags & FAULT_FLAG_WRITE) {
@@ -3551,6 +3786,8 @@
.vma = vma,
.address = address,
.flags = flags,
+ .vma_flags = vma->vm_flags,
+ .vma_page_prot = vma->vm_page_prot,
};
struct mm_struct *mm = vma->vm_mm;
pgd_t *pgd;
@@ -3570,7 +3807,9 @@
} else {
pmd_t orig_pmd = *fe.pmd;
int ret;
-
+#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
+ fe.sequence = raw_read_seqcount(&vma->vm_sequence);
+#endif
barrier();
if (pmd_trans_huge(orig_pmd) || pmd_devmap(orig_pmd)) {
if (pmd_protnone(orig_pmd) && vma_is_accessible(vma))
@@ -3591,6 +3830,247 @@
return handle_pte_fault(&fe);
}
+#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
+
+#ifndef __HAVE_ARCH_PTE_SPECIAL
+/* This is required by vm_normal_page() */
+#error "Speculative page fault handler requires __HAVE_ARCH_PTE_SPECIAL"
+#endif
+/*
+ * vm_normal_page() adds some processing which should be done while
+ * hodling the mmap_sem.
+ */
+
+/*
+ * Tries to handle the page fault in a speculative way, without grabbing the
+ * mmap_sem.
+ * When VM_FAULT_RETRY is returned, the vma pointer is valid and this vma must
+ * be checked later when the mmap_sem has been grabbed by calling
+ * can_reuse_spf_vma().
+ * This is needed as the returned vma is kept in memory until the call to
+ * can_reuse_spf_vma() is made.
+ */
+int __handle_speculative_fault(struct mm_struct *mm, unsigned long address,
+ unsigned int flags, struct vm_area_struct **vma)
+{
+ struct fault_env fe = {
+ .address = address,
+ };
+ pgd_t *pgd, pgdval;
+ pud_t *pud, pudval;
+ int seq, ret;
+
+ /* Clear flags that may lead to release the mmap_sem to retry */
+ flags &= ~(FAULT_FLAG_ALLOW_RETRY|FAULT_FLAG_KILLABLE);
+ flags |= FAULT_FLAG_SPECULATIVE;
+
+ *vma = get_vma(mm, address);
+ if (!*vma)
+ return VM_FAULT_RETRY;
+ fe.vma = *vma;
+
+ /* rmb <-> seqlock,vma_rb_erase() */
+ seq = raw_read_seqcount(&fe.vma->vm_sequence);
+ if (seq & 1) {
+ trace_spf_vma_changed(_RET_IP_, fe.vma, address);
+ return VM_FAULT_RETRY;
+ }
+
+ /*
+ * Can't call vm_ops service has we don't know what they would do
+ * with the VMA.
+ * This include huge page from hugetlbfs.
+ */
+ if (fe.vma->vm_ops) {
+ trace_spf_vma_notsup(_RET_IP_, fe.vma, address);
+ return VM_FAULT_RETRY;
+ }
+
+ /*
+ * __anon_vma_prepare() requires the mmap_sem to be held
+ * because vm_next and vm_prev must be safe. This can't be guaranteed
+ * in the speculative path.
+ */
+ if (unlikely(!fe.vma->anon_vma)) {
+ trace_spf_vma_notsup(_RET_IP_, fe.vma, address);
+ return VM_FAULT_RETRY;
+ }
+
+ fe.vma_flags = READ_ONCE(fe.vma->vm_flags);
+ fe.vma_page_prot = READ_ONCE(fe.vma->vm_page_prot);
+
+ /* Can't call userland page fault handler in the speculative path */
+ if (unlikely(fe.vma_flags & VM_UFFD_MISSING)) {
+ trace_spf_vma_notsup(_RET_IP_, fe.vma, address);
+ return VM_FAULT_RETRY;
+ }
+
+ if (fe.vma_flags & VM_GROWSDOWN || fe.vma_flags & VM_GROWSUP) {
+ /*
+ * This could be detected by the check address against VMA's
+ * boundaries but we want to trace it as not supported instead
+ * of changed.
+ */
+ trace_spf_vma_notsup(_RET_IP_, fe.vma, address);
+ return VM_FAULT_RETRY;
+ }
+
+ if (address < READ_ONCE(fe.vma->vm_start)
+ || READ_ONCE(fe.vma->vm_end) <= address) {
+ trace_spf_vma_changed(_RET_IP_, fe.vma, address);
+ return VM_FAULT_RETRY;
+ }
+
+ if (!arch_vma_access_permitted(fe.vma, flags & FAULT_FLAG_WRITE,
+ flags & FAULT_FLAG_INSTRUCTION,
+ flags & FAULT_FLAG_REMOTE))
+ goto out_segv;
+
+ /* This is one is required to check that the VMA has write access set */
+ if (flags & FAULT_FLAG_WRITE) {
+ if (unlikely(!(fe.vma_flags & VM_WRITE)))
+ goto out_segv;
+ } else if (unlikely(!(fe.vma_flags & (VM_READ|VM_EXEC|VM_WRITE))))
+ goto out_segv;
+
+#ifdef CONFIG_NUMA
+ struct mempolicy *pol;
+
+ /*
+ * MPOL_INTERLEAVE implies additional checks in
+ * mpol_misplaced() which are not compatible with the
+ *speculative page fault processing.
+ */
+ pol = __get_vma_policy(fe.vma, address);
+ if (!pol)
+ pol = get_task_policy(current);
+
+ if (pol && pol->mode == MPOL_INTERLEAVE) {
+ trace_spf_vma_notsup(_RET_IP_, fe.vma, address);
+ return VM_FAULT_RETRY;
+ }
+#endif
+
+ /*
+ * Do a speculative lookup of the PTE entry.
+ */
+ local_irq_disable();
+ pgd = pgd_offset(mm, address);
+ pgdval = READ_ONCE(*pgd);
+ if (pgd_none(pgdval) || unlikely(pgd_bad(pgdval)))
+ goto out_walk;
+
+ pud = pud_offset(pgd, address);
+ pudval = READ_ONCE(*pud);
+ if (pud_none(pudval) || unlikely(pud_bad(pudval)))
+ goto out_walk;
+
+ fe.pmd = pmd_offset(pud, address);
+ fe.orig_pmd = READ_ONCE(*fe.pmd);
+ /*
+ * pmd_none could mean that a hugepage collapse is in progress
+ * in our back as collapse_huge_page() mark it before
+ * invalidating the pte (which is done once the IPI is catched
+ * by all CPU and we have interrupt disabled).
+ * For this reason we cannot handle THP in a speculative way since we
+ * can't safely indentify an in progress collapse operation done in our
+ * back on that PMD.
+ * Regarding the order of the following checks, see comment in
+ * pmd_devmap_trans_unstable()
+ */
+ if (unlikely(pmd_devmap(fe.orig_pmd) ||
+ pmd_none(fe.orig_pmd) || pmd_trans_huge(fe.orig_pmd)))
+ goto out_walk;
+
+ /*
+ * The above does not allocate/instantiate page-tables because doing so
+ * would lead to the possibility of instantiating page-tables after
+ * free_pgtables() -- and consequently leaking them.
+ *
+ * The result is that we take at least one !speculative fault per PMD
+ * in order to instantiate it.
+ */
+
+ fe.pte = pte_offset_map(fe.pmd, address);
+ fe.orig_pte = READ_ONCE(*fe.pte);
+ barrier(); /* See comment in handle_pte_fault() */
+ if (pte_none(fe.orig_pte)) {
+ pte_unmap(fe.pte);
+ fe.pte = NULL;
+ }
+
+ fe.sequence = seq;
+ fe.flags = flags;
+
+ local_irq_enable();
+
+ /*
+ * We need to re-validate the VMA after checking the bounds, otherwise
+ * we might have a false positive on the bounds.
+ */
+ if (read_seqcount_retry(&fe.vma->vm_sequence, seq)) {
+ trace_spf_vma_changed(_RET_IP_, fe.vma, address);
+ return VM_FAULT_RETRY;
+ }
+
+ mem_cgroup_oom_enable();
+ ret = handle_pte_fault(&fe);
+ mem_cgroup_oom_disable();
+
+ /*
+ * If there is no need to retry, don't return the vma to the caller.
+ */
+ if (ret != VM_FAULT_RETRY) {
+ count_vm_event(SPECULATIVE_PGFAULT);
+ put_vma(fe.vma);
+ *vma = NULL;
+ }
+
+ /*
+ * The task may have entered a memcg OOM situation but
+ * if the allocation error was handled gracefully (no
+ * VM_FAULT_OOM), there is no need to kill anything.
+ * Just clean up the OOM state peacefully.
+ */
+ if (task_in_memcg_oom(current) && !(ret & VM_FAULT_OOM))
+ mem_cgroup_oom_synchronize(false);
+ return ret;
+
+out_walk:
+ trace_spf_vma_notsup(_RET_IP_, fe.vma, address);
+ local_irq_enable();
+ return VM_FAULT_RETRY;
+
+out_segv:
+ trace_spf_vma_access(_RET_IP_, fe.vma, address);
+ /*
+ * We don't return VM_FAULT_RETRY so the caller is not expected to
+ * retrieve the fetched VMA.
+ */
+ put_vma(fe.vma);
+ *vma = NULL;
+ return VM_FAULT_SIGSEGV;
+}
+
+/*
+ * This is used to know if the vma fetch in the speculative page fault handler
+ * is still valid when trying the regular fault path while holding the
+ * mmap_sem.
+ * The call to put_vma(vma) must be made after checking the vma's fields, as
+ * the vma may be freed by put_vma(). In such a case it is expected that false
+ * is returned.
+ */
+bool can_reuse_spf_vma(struct vm_area_struct *vma, unsigned long address)
+{
+ bool ret;
+
+ ret = !RB_EMPTY_NODE(&vma->vm_rb) &&
+ vma->vm_start <= address && address < vma->vm_end;
+ put_vma(vma);
+ return ret;
+}
+#endif /* CONFIG_SPECULATIVE_PAGE_FAULT */
+
/*
* By the time we get here, we already hold the mm semaphore
*
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index d0adeef..ecbe6ec 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -442,8 +442,11 @@
struct vm_area_struct *vma;
down_write(&mm->mmap_sem);
- for (vma = mm->mmap; vma; vma = vma->vm_next)
+ for (vma = mm->mmap; vma; vma = vma->vm_next) {
+ vm_write_begin(vma);
mpol_rebind_policy(vma->vm_policy, new, MPOL_REBIND_ONCE);
+ vm_write_end(vma);
+ }
up_write(&mm->mmap_sem);
}
@@ -601,9 +604,11 @@
{
int nr_updated;
+ vm_write_begin(vma);
nr_updated = change_protection(vma, addr, end, PAGE_NONE, 0, 1);
if (nr_updated)
count_vm_numa_events(NUMA_PTE_UPDATES, nr_updated);
+ vm_write_end(vma);
return nr_updated;
}
@@ -704,6 +709,7 @@
if (IS_ERR(new))
return PTR_ERR(new);
+ vm_write_begin(vma);
if (vma->vm_ops && vma->vm_ops->set_policy) {
err = vma->vm_ops->set_policy(vma, new);
if (err)
@@ -711,11 +717,17 @@
}
old = vma->vm_policy;
- vma->vm_policy = new; /* protected by mmap_sem */
+ /*
+ * The speculative page fault handler accesses this field without
+ * hodling the mmap_sem.
+ */
+ WRITE_ONCE(vma->vm_policy, new);
+ vm_write_end(vma);
mpol_put(old);
return 0;
err_out:
+ vm_write_end(vma);
mpol_put(new);
return err;
}
@@ -1586,23 +1598,28 @@
struct mempolicy *__get_vma_policy(struct vm_area_struct *vma,
unsigned long addr)
{
- struct mempolicy *pol = NULL;
+ struct mempolicy *pol;
- if (vma) {
- if (vma->vm_ops && vma->vm_ops->get_policy) {
- pol = vma->vm_ops->get_policy(vma, addr);
- } else if (vma->vm_policy) {
- pol = vma->vm_policy;
+ if (!vma)
+ return NULL;
- /*
- * shmem_alloc_page() passes MPOL_F_SHARED policy with
- * a pseudo vma whose vma->vm_ops=NULL. Take a reference
- * count on these policies which will be dropped by
- * mpol_cond_put() later
- */
- if (mpol_needs_cond_ref(pol))
- mpol_get(pol);
- }
+ if (vma->vm_ops && vma->vm_ops->get_policy)
+ return vma->vm_ops->get_policy(vma, addr);
+
+ /*
+ * This could be called without holding the mmap_sem in the
+ * speculative page fault handler's path.
+ */
+ pol = READ_ONCE(vma->vm_policy);
+ if (pol) {
+ /*
+ * shmem_alloc_page() passes MPOL_F_SHARED policy with
+ * a pseudo vma whose vma->vm_ops=NULL. Take a reference
+ * count on these policies which will be dropped by
+ * mpol_cond_put() later
+ */
+ if (mpol_needs_cond_ref(pol))
+ mpol_get(pol);
}
return pol;
diff --git a/mm/migrate.c b/mm/migrate.c
index eb1f043..595b456 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -241,7 +241,7 @@
/* Recheck VMA as permissions can change since migration started */
if (is_write_migration_entry(entry))
- pte = maybe_mkwrite(pte, vma);
+ pte = maybe_mkwrite(pte, vma->vm_flags);
#ifdef CONFIG_HUGETLB_PAGE
if (PageHuge(new)) {
@@ -1855,7 +1855,7 @@
* node. Caller is expected to have an elevated reference count on
* the page that will be dropped by this function before returning.
*/
-int migrate_misplaced_page(struct page *page, struct vm_area_struct *vma,
+int migrate_misplaced_page(struct page *page, struct fault_env *fe,
int node)
{
pg_data_t *pgdat = NODE_DATA(node);
@@ -1868,7 +1868,7 @@
* with execute permissions as they are probably shared libraries.
*/
if (page_mapcount(page) != 1 && page_is_file_cache(page) &&
- (vma->vm_flags & VM_EXEC))
+ (fe->vma_flags & VM_EXEC))
goto out;
/*
diff --git a/mm/mlock.c b/mm/mlock.c
index 9cdd063..f648acb 100644
--- a/mm/mlock.c
+++ b/mm/mlock.c
@@ -438,7 +438,9 @@
void munlock_vma_pages_range(struct vm_area_struct *vma,
unsigned long start, unsigned long end)
{
- vma->vm_flags &= VM_LOCKED_CLEAR_MASK;
+ vm_write_begin(vma);
+ WRITE_ONCE(vma->vm_flags, vma->vm_flags & VM_LOCKED_CLEAR_MASK);
+ vm_write_end(vma);
while (start < end) {
struct page *page;
@@ -563,10 +565,11 @@
* It's okay if try_to_unmap_one unmaps a page just after we
* set VM_LOCKED, populate_vma_page_range will bring it back.
*/
-
- if (lock)
- vma->vm_flags = newflags;
- else
+ if (lock) {
+ vm_write_begin(vma);
+ WRITE_ONCE(vma->vm_flags, newflags);
+ vm_write_end(vma);
+ } else
munlock_vma_pages_range(vma, start, end);
out:
diff --git a/mm/mmap.c b/mm/mmap.c
index 2ce3870..9ba15d8 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -160,6 +160,27 @@
}
}
+static void __free_vma(struct vm_area_struct *vma)
+{
+ if (vma->vm_file)
+ fput(vma->vm_file);
+ mpol_put(vma_policy(vma));
+ kmem_cache_free(vm_area_cachep, vma);
+}
+
+#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
+void put_vma(struct vm_area_struct *vma)
+{
+ if (atomic_dec_and_test(&vma->vm_ref_count))
+ __free_vma(vma);
+}
+#else
+static inline void put_vma(struct vm_area_struct *vma)
+{
+ __free_vma(vma);
+}
+#endif
+
/*
* Close a vm structure and free it, returning the next.
*/
@@ -170,10 +191,7 @@
might_sleep();
if (vma->vm_ops && vma->vm_ops->close)
vma->vm_ops->close(vma);
- if (vma->vm_file)
- fput(vma->vm_file);
- mpol_put(vma_policy(vma));
- kmem_cache_free(vm_area_cachep, vma);
+ put_vma(vma);
return next;
}
@@ -391,6 +409,14 @@
#define validate_mm(mm) do { } while (0)
#endif
+#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
+#define mm_rb_write_lock(mm) write_lock(&(mm)->mm_rb_lock)
+#define mm_rb_write_unlock(mm) write_unlock(&(mm)->mm_rb_lock)
+#else
+#define mm_rb_write_lock(mm) do { } while (0)
+#define mm_rb_write_unlock(mm) do { } while (0)
+#endif /* CONFIG_SPECULATIVE_PAGE_FAULT */
+
RB_DECLARE_CALLBACKS(static, vma_gap_callbacks, struct vm_area_struct, vm_rb,
unsigned long, rb_subtree_gap, vma_compute_subtree_gap)
@@ -409,26 +435,37 @@
}
static inline void vma_rb_insert(struct vm_area_struct *vma,
- struct rb_root *root)
+ struct mm_struct *mm)
{
+ struct rb_root *root = &mm->mm_rb;
+
/* All rb_subtree_gap values must be consistent prior to insertion */
validate_mm_rb(root, NULL);
rb_insert_augmented(&vma->vm_rb, root, &vma_gap_callbacks);
}
-static void __vma_rb_erase(struct vm_area_struct *vma, struct rb_root *root)
+static void __vma_rb_erase(struct vm_area_struct *vma, struct mm_struct *mm)
{
+ struct rb_root *root = &mm->mm_rb;
/*
* Note rb_erase_augmented is a fairly large inline function,
* so make sure we instantiate it only once with our desired
* augmented rbtree callbacks.
*/
+ mm_rb_write_lock(mm);
rb_erase_augmented(&vma->vm_rb, root, &vma_gap_callbacks);
+ mm_rb_write_unlock(mm); /* wmb */
+
+ /*
+ * Ensure the removal is complete before clearing the node.
+ * Matched by vma_has_changed()/handle_speculative_fault().
+ */
+ RB_CLEAR_NODE(&vma->vm_rb);
}
static __always_inline void vma_rb_erase_ignore(struct vm_area_struct *vma,
- struct rb_root *root,
+ struct mm_struct *mm,
struct vm_area_struct *ignore)
{
/*
@@ -436,21 +473,21 @@
* with the possible exception of the "next" vma being erased if
* next->vm_start was reduced.
*/
- validate_mm_rb(root, ignore);
+ validate_mm_rb(&mm->mm_rb, ignore);
- __vma_rb_erase(vma, root);
+ __vma_rb_erase(vma, mm);
}
static __always_inline void vma_rb_erase(struct vm_area_struct *vma,
- struct rb_root *root)
+ struct mm_struct *mm)
{
/*
* All rb_subtree_gap values must be consistent prior to erase,
* with the possible exception of the vma being erased.
*/
- validate_mm_rb(root, vma);
+ validate_mm_rb(&mm->mm_rb, vma);
- __vma_rb_erase(vma, root);
+ __vma_rb_erase(vma, mm);
}
/*
@@ -565,10 +602,12 @@
* immediately update the gap to the correct value. Finally we
* rebalance the rbtree after all augmented values have been set.
*/
+ mm_rb_write_lock(mm);
rb_link_node(&vma->vm_rb, rb_parent, rb_link);
vma->rb_subtree_gap = 0;
vma_gap_update(vma);
- vma_rb_insert(vma, &mm->mm_rb);
+ vma_rb_insert(vma, mm);
+ mm_rb_write_unlock(mm);
}
static void __vma_link_file(struct vm_area_struct *vma)
@@ -644,7 +683,7 @@
{
struct vm_area_struct *next;
- vma_rb_erase_ignore(vma, &mm->mm_rb, ignore);
+ vma_rb_erase_ignore(vma, mm, ignore);
next = vma->vm_next;
if (has_prev)
prev->vm_next = next;
@@ -678,7 +717,7 @@
*/
int __vma_adjust(struct vm_area_struct *vma, unsigned long start,
unsigned long end, pgoff_t pgoff, struct vm_area_struct *insert,
- struct vm_area_struct *expand)
+ struct vm_area_struct *expand, bool keep_locked)
{
struct mm_struct *mm = vma->vm_mm;
struct vm_area_struct *next = vma->vm_next, *orig_vma = vma;
@@ -690,6 +729,30 @@
long adjust_next = 0;
int remove_next = 0;
+ /*
+ * Why using vm_raw_write*() functions here to avoid lockdep's warning ?
+ *
+ * Locked is complaining about a theoretical lock dependency, involving
+ * 3 locks:
+ * mapping->i_mmap_rwsem --> vma->vm_sequence --> fs_reclaim
+ *
+ * Here are the major path leading to this dependency :
+ * 1. __vma_adjust() mmap_sem -> vm_sequence -> i_mmap_rwsem
+ * 2. move_vmap() mmap_sem -> vm_sequence -> fs_reclaim
+ * 3. __alloc_pages_nodemask() fs_reclaim -> i_mmap_rwsem
+ * 4. unmap_mapping_range() i_mmap_rwsem -> vm_sequence
+ *
+ * So there is no way to solve this easily, especially because in
+ * unmap_mapping_range() the i_mmap_rwsem is grab while the impacted
+ * VMAs are not yet known.
+ * However, the way the vm_seq is used is guarantying that we will
+ * never block on it since we just check for its value and never wait
+ * for it to move, see vma_has_changed() and handle_speculative_fault().
+ */
+ vm_raw_write_begin(vma);
+ if (next)
+ vm_raw_write_begin(next);
+
if (next && !insert) {
struct vm_area_struct *exporter = NULL, *importer = NULL;
@@ -770,8 +833,12 @@
importer->anon_vma = exporter->anon_vma;
error = anon_vma_clone(importer, exporter);
- if (error)
+ if (error) {
+ if (next && next != vma)
+ vm_raw_write_end(next);
+ vm_raw_write_end(vma);
return error;
+ }
}
}
again:
@@ -817,17 +884,18 @@
}
if (start != vma->vm_start) {
- vma->vm_start = start;
+ WRITE_ONCE(vma->vm_start, start);
start_changed = true;
}
if (end != vma->vm_end) {
- vma->vm_end = end;
+ WRITE_ONCE(vma->vm_end, end);
end_changed = true;
}
- vma->vm_pgoff = pgoff;
+ WRITE_ONCE(vma->vm_pgoff, pgoff);
if (adjust_next) {
- next->vm_start += adjust_next << PAGE_SHIFT;
- next->vm_pgoff += adjust_next;
+ WRITE_ONCE(next->vm_start,
+ next->vm_start + (adjust_next << PAGE_SHIFT));
+ WRITE_ONCE(next->vm_pgoff, next->vm_pgoff + adjust_next);
}
if (root) {
@@ -892,15 +960,13 @@
}
if (remove_next) {
- if (file) {
+ if (file)
uprobe_munmap(next, next->vm_start, next->vm_end);
- fput(file);
- }
if (next->anon_vma)
anon_vma_merge(vma, next);
mm->map_count--;
- mpol_put(vma_policy(next));
- kmem_cache_free(vm_area_cachep, next);
+ vm_raw_write_end(next);
+ put_vma(next);
/*
* In mprotect's case 6 (see comments on vma_merge),
* we must remove another next too. It would clutter
@@ -914,6 +980,8 @@
* "vma->vm_next" gap must be updated.
*/
next = vma->vm_next;
+ if (next)
+ vm_raw_write_begin(next);
} else {
/*
* For the scope of the comment "next" and
@@ -960,6 +1028,11 @@
if (insert && file)
uprobe_mmap(insert);
+ if (next && next != vma)
+ vm_raw_write_end(next);
+ if (!keep_locked)
+ vm_raw_write_end(vma);
+
validate_mm(mm);
return 0;
@@ -1099,13 +1172,13 @@
* parameter) may establish ptes with the wrong permissions of NNNN
* instead of the right permissions of XXXX.
*/
-struct vm_area_struct *vma_merge(struct mm_struct *mm,
+struct vm_area_struct *__vma_merge(struct mm_struct *mm,
struct vm_area_struct *prev, unsigned long addr,
unsigned long end, unsigned long vm_flags,
struct anon_vma *anon_vma, struct file *file,
pgoff_t pgoff, struct mempolicy *policy,
struct vm_userfaultfd_ctx vm_userfaultfd_ctx,
- const char __user *anon_name)
+ const char __user *anon_name, bool keep_locked)
{
pgoff_t pglen = (end - addr) >> PAGE_SHIFT;
struct vm_area_struct *area, *next;
@@ -1155,10 +1228,11 @@
/* cases 1, 6 */
err = __vma_adjust(prev, prev->vm_start,
next->vm_end, prev->vm_pgoff, NULL,
- prev);
+ prev, keep_locked);
} else /* cases 2, 5, 7 */
err = __vma_adjust(prev, prev->vm_start,
- end, prev->vm_pgoff, NULL, prev);
+ end, prev->vm_pgoff, NULL, prev,
+ keep_locked);
if (err)
return NULL;
khugepaged_enter_vma_merge(prev, vm_flags);
@@ -1176,10 +1250,12 @@
anon_name)) {
if (prev && addr < prev->vm_end) /* case 4 */
err = __vma_adjust(prev, prev->vm_start,
- addr, prev->vm_pgoff, NULL, next);
+ addr, prev->vm_pgoff, NULL, next,
+ keep_locked);
else { /* cases 3, 8 */
err = __vma_adjust(area, addr, next->vm_end,
- next->vm_pgoff - pglen, NULL, next);
+ next->vm_pgoff - pglen, NULL, next,
+ keep_locked);
/*
* In case 3 area is already equal to next and
* this is a noop, but in case 8 "area" has
@@ -1704,7 +1780,7 @@
vma->vm_flags = vm_flags;
vma->vm_page_prot = vm_get_page_prot(vm_flags);
vma->vm_pgoff = pgoff;
- INIT_LIST_HEAD(&vma->anon_vma_chain);
+ INIT_VMA(vma);
if (file) {
if (vm_flags & VM_DENYWRITE) {
@@ -1757,13 +1833,15 @@
out:
perf_event_mmap(vma);
+ vm_write_begin(vma);
vm_stat_account(mm, vm_flags, len >> PAGE_SHIFT);
if (vm_flags & VM_LOCKED) {
if (!((vm_flags & VM_SPECIAL) || is_vm_hugetlb_page(vma) ||
vma == get_gate_vma(current->mm)))
mm->locked_vm += (len >> PAGE_SHIFT);
else
- vma->vm_flags &= VM_LOCKED_CLEAR_MASK;
+ WRITE_ONCE(vma->vm_flags,
+ vma->vm_flags & VM_LOCKED_CLEAR_MASK);
}
if (file)
@@ -1776,9 +1854,10 @@
* then new mapped in-place (which must be aimed as
* a completely new data area).
*/
- vma->vm_flags |= VM_SOFTDIRTY;
+ WRITE_ONCE(vma->vm_flags, vma->vm_flags | VM_SOFTDIRTY);
vma_set_page_prot(vma);
+ vm_write_end(vma);
return addr;
@@ -2150,15 +2229,11 @@
EXPORT_SYMBOL(get_unmapped_area);
/* Look up the first VMA which satisfies addr < vm_end, NULL if none. */
-struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr)
+static struct vm_area_struct *__find_vma(struct mm_struct *mm,
+ unsigned long addr)
{
struct rb_node *rb_node;
- struct vm_area_struct *vma;
-
- /* Check the cache first. */
- vma = vmacache_find(mm, addr);
- if (likely(vma))
- return vma;
+ struct vm_area_struct *vma = NULL;
rb_node = mm->mm_rb.rb_node;
@@ -2176,13 +2251,40 @@
rb_node = rb_node->rb_right;
}
+ return vma;
+}
+
+struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr)
+{
+ struct vm_area_struct *vma;
+
+ /* Check the cache first. */
+ vma = vmacache_find(mm, addr);
+ if (likely(vma))
+ return vma;
+
+ vma = __find_vma(mm, addr);
if (vma)
vmacache_update(addr, vma);
return vma;
}
-
EXPORT_SYMBOL(find_vma);
+#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
+struct vm_area_struct *get_vma(struct mm_struct *mm, unsigned long addr)
+{
+ struct vm_area_struct *vma = NULL;
+
+ read_lock(&mm->mm_rb_lock);
+ vma = __find_vma(mm, addr);
+ if (vma)
+ atomic_inc(&vma->vm_ref_count);
+ read_unlock(&mm->mm_rb_lock);
+
+ return vma;
+}
+#endif
+
/*
* Same as find_vma, but also return a pointer to the previous VMA in *pprev.
*/
@@ -2412,8 +2514,8 @@
mm->locked_vm += grow;
vm_stat_account(mm, vma->vm_flags, grow);
anon_vma_interval_tree_pre_update_vma(vma);
- vma->vm_start = address;
- vma->vm_pgoff -= grow;
+ WRITE_ONCE(vma->vm_start, address);
+ WRITE_ONCE(vma->vm_pgoff, vma->vm_pgoff - grow);
anon_vma_interval_tree_post_update_vma(vma);
vma_gap_update(vma);
spin_unlock(&mm->page_table_lock);
@@ -2555,7 +2657,7 @@
insertion_point = (prev ? &prev->vm_next : &mm->mmap);
vma->vm_prev = NULL;
do {
- vma_rb_erase(vma, &mm->mm_rb);
+ vma_rb_erase(vma, mm);
mm->map_count--;
tail_vma = vma;
vma = vma->vm_next;
@@ -2595,7 +2697,7 @@
/* most fields are the same, copy all, and then fixup */
*new = *vma;
- INIT_LIST_HEAD(&new->anon_vma_chain);
+ INIT_VMA(new);
if (new_below)
new->vm_end = addr;
@@ -2952,7 +3054,7 @@
return -ENOMEM;
}
- INIT_LIST_HEAD(&vma->anon_vma_chain);
+ INIT_VMA(vma);
vma->vm_mm = mm;
vma->vm_start = addr;
vma->vm_end = addr + len;
@@ -3115,9 +3217,21 @@
if (find_vma_links(mm, addr, addr + len, &prev, &rb_link, &rb_parent))
return NULL; /* should never get here */
- new_vma = vma_merge(mm, prev, addr, addr + len, vma->vm_flags,
- vma->anon_vma, vma->vm_file, pgoff, vma_policy(vma),
- vma->vm_userfaultfd_ctx, vma_get_anon_name(vma));
+
+ /* There is 3 cases to manage here in
+ * AAAA AAAA AAAA AAAA
+ * PPPP.... PPPP......NNNN PPPP....NNNN PP........NN
+ * PPPPPPPP(A) PPPP..NNNNNNNN(B) PPPPPPPPPPPP(1) NULL
+ * PPPPPPPPNNNN(2)
+ * PPPPNNNNNNNN(3)
+ *
+ * new_vma == prev in case A,1,2
+ * new_vma == next in case B,3
+ */
+ new_vma = __vma_merge(mm, prev, addr, addr + len, vma->vm_flags,
+ vma->anon_vma, vma->vm_file, pgoff,
+ vma_policy(vma), vma->vm_userfaultfd_ctx,
+ vma_get_anon_name(vma), true);
if (new_vma) {
/*
* Source vma may have been merged into new_vma
@@ -3150,13 +3264,22 @@
new_vma->vm_pgoff = pgoff;
if (vma_dup_policy(vma, new_vma))
goto out_free_vma;
- INIT_LIST_HEAD(&new_vma->anon_vma_chain);
+ INIT_VMA(new_vma);
if (anon_vma_clone(new_vma, vma))
goto out_free_mempol;
if (new_vma->vm_file)
get_file(new_vma->vm_file);
if (new_vma->vm_ops && new_vma->vm_ops->open)
new_vma->vm_ops->open(new_vma);
+ /*
+ * As the VMA is linked right now, it may be hit by the
+ * speculative page fault handler. But we don't want it to
+ * to start mapping page in this area until the caller has
+ * potentially move the pte from the moved VMA. To prevent
+ * that we protect it right now, and let the caller unprotect
+ * it once the move is done.
+ */
+ vm_raw_write_begin(new_vma);
vma_link(mm, new_vma, prev, rb_link, rb_parent);
*need_rmap_locks = false;
}
@@ -3288,7 +3411,7 @@
if (unlikely(vma == NULL))
return ERR_PTR(-ENOMEM);
- INIT_LIST_HEAD(&vma->anon_vma_chain);
+ INIT_VMA(vma);
vma->vm_mm = mm;
vma->vm_start = addr;
vma->vm_end = addr + len;
diff --git a/mm/mprotect.c b/mm/mprotect.c
index 1f2c969..60b16418 100644
--- a/mm/mprotect.c
+++ b/mm/mprotect.c
@@ -329,12 +329,14 @@
* vm_flags and vm_page_prot are protected by the mmap_sem
* held in write mode.
*/
- vma->vm_flags = newflags;
+ vm_write_begin(vma);
+ WRITE_ONCE(vma->vm_flags, newflags);
dirty_accountable = vma_wants_writenotify(vma, vma->vm_page_prot);
vma_set_page_prot(vma);
change_protection(vma, start, end, vma->vm_page_prot,
dirty_accountable, 0);
+ vm_write_end(vma);
/*
* Private VM_LOCKED VMA becoming writable: trigger COW to avoid major
diff --git a/mm/mremap.c b/mm/mremap.c
index 1597671..2302762 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -289,6 +289,14 @@
if (!new_vma)
return -ENOMEM;
+ /* new_vma is returned protected by copy_vma, to prevent speculative
+ * page fault to be done in the destination area before we move the pte.
+ * Now, we must also protect the source VMA since we don't want pages
+ * to be mapped in our back while we are copying the PTEs.
+ */
+ if (vma != new_vma)
+ vm_raw_write_begin(vma);
+
moved_len = move_page_tables(vma, old_addr, new_vma, new_addr, old_len,
need_rmap_locks);
if (moved_len < old_len) {
@@ -305,6 +313,8 @@
*/
move_page_tables(new_vma, new_addr, vma, old_addr, moved_len,
true);
+ if (vma != new_vma)
+ vm_raw_write_end(vma);
vma = new_vma;
old_len = new_len;
old_addr = new_addr;
@@ -312,7 +322,10 @@
} else {
arch_remap(mm, old_addr, old_addr + old_len,
new_addr, new_addr + new_len);
+ if (vma != new_vma)
+ vm_raw_write_end(vma);
}
+ vm_raw_write_end(new_vma);
/* Conceal VM_ACCOUNT so old reservation is not undone */
if (vm_flags & VM_ACCOUNT) {
diff --git a/mm/nommu.c b/mm/nommu.c
index 44265e0..d033ee8 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -1243,7 +1243,7 @@
region->vm_flags = vm_flags;
region->vm_pgoff = pgoff;
- INIT_LIST_HEAD(&vma->anon_vma_chain);
+ INIT_VMA(vma);
vma->vm_flags = vm_flags;
vma->vm_pgoff = pgoff;
diff --git a/mm/rmap.c b/mm/rmap.c
index 4d19dd1..24470a6 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -1266,7 +1266,7 @@
}
/**
- * page_add_new_anon_rmap - add pte mapping to a new anonymous page
+ * __page_add_new_anon_rmap - add pte mapping to a new anonymous page
* @page: the page to add the mapping to
* @vma: the vm area in which the mapping is added
* @address: the user virtual address mapped
@@ -1276,12 +1276,11 @@
* This means the inc-and-test can be bypassed.
* Page does not have to be locked.
*/
-void page_add_new_anon_rmap(struct page *page,
+void __page_add_new_anon_rmap(struct page *page,
struct vm_area_struct *vma, unsigned long address, bool compound)
{
int nr = compound ? hpage_nr_pages(page) : 1;
- VM_BUG_ON_VMA(address < vma->vm_start || address >= vma->vm_end, vma);
__SetPageSwapBacked(page);
if (compound) {
VM_BUG_ON_PAGE(!PageTransHuge(page), page);
diff --git a/mm/swap.c b/mm/swap.c
index 6f22754..5827225 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -468,12 +468,12 @@
* directly back onto it's zone's unevictable list, it does NOT use a
* per cpu pagevec.
*/
-void lru_cache_add_active_or_unevictable(struct page *page,
- struct vm_area_struct *vma)
+void __lru_cache_add_active_or_unevictable(struct page *page,
+ unsigned long vma_flags)
{
VM_BUG_ON_PAGE(PageLRU(page), page);
- if (likely((vma->vm_flags & (VM_LOCKED | VM_SPECIAL)) != VM_LOCKED)) {
+ if (likely((vma_flags & (VM_LOCKED | VM_SPECIAL)) != VM_LOCKED)) {
SetPageActive(page);
lru_cache_add(page);
return;
diff --git a/mm/swap_state.c b/mm/swap_state.c
index 5ac5846..35f882d 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -467,6 +467,10 @@
* the readahead.
*
* Caller must hold down_read on the vma->vm_mm if vma is not NULL.
+ * This is needed to ensure the VMA will not be freed in our back. In the case
+ * of the speculative page fault handler, this cannot happen, even if we don't
+ * hold the mmap_sem. Callees are assumed to take care of reading VMA's fields
+ * using READ_ONCE() to read consistent values.
*/
struct page *swapin_readahead(swp_entry_t entry, gfp_t gfp_mask,
struct vm_area_struct *vma, unsigned long addr)
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index ed89128..6b5f0bc 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -543,7 +543,7 @@
}
}
- if (printk_ratelimit())
+ if (!(gfp_mask & __GFP_NOWARN) && printk_ratelimit())
pr_warn("vmap allocation for size %lu failed: use vmalloc=<size> to increase size\n",
size);
kfree(va);
@@ -657,7 +657,8 @@
log = fls(num_online_cpus());
- return log * (32UL * 1024 * 1024 / PAGE_SIZE);
+ return log * (1UL * CONFIG_VMAP_LAZY_PURGING_FACTOR *
+ 1024 * 1024 / PAGE_SIZE);
}
static atomic_t vmap_lazy_nr = ATOMIC_INIT(0);
diff --git a/mm/vmstat.c b/mm/vmstat.c
index 8bd62ed..3d128da 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -1088,7 +1088,10 @@
"vmacache_find_hits",
"vmacache_full_flushes",
#endif
-#endif /* CONFIG_VM_EVENTS_COUNTERS */
+#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
+ "speculative_pgfault"
+#endif
+#endif /* CONFIG_VM_EVENT_COUNTERS */
};
#endif /* CONFIG_PROC_FS || CONFIG_SYSFS || CONFIG_NUMA */
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 340a3db..59c1581 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -889,9 +889,12 @@
now = jiffies;
next = now + HZ;
- if (!(state & NUD_IN_TIMER))
- goto out;
-
+ if (!(state & NUD_IN_TIMER)) {
+ if (neigh_probe_enable && (state & NUD_STALE))
+ neigh_dbg(2, "neigh %pK is still alive\n", neigh);
+ else
+ goto out;
+ }
if (state & NUD_REACHABLE) {
if (time_before_eq(now,
neigh->confirmed + neigh->parms->reachable_time)) {
@@ -1182,7 +1185,10 @@
neigh_del_timer(neigh);
if (new & NUD_PROBE)
atomic_set(&neigh->probes, 0);
- if (new & NUD_IN_TIMER)
+ if (new & NUD_IN_TIMER || (
+ neigh_probe_enable &&
+ (neigh->tbl->family == AF_INET6) &&
+ (new & NUD_STALE)))
neigh_add_timer(neigh, (jiffies +
((new & NUD_REACHABLE) ?
neigh->parms->reachable_time :
diff --git a/net/core/sockev_nlmcast.c b/net/core/sockev_nlmcast.c
index 04f61fc..f238edb 100644
--- a/net/core/sockev_nlmcast.c
+++ b/net/core/sockev_nlmcast.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2015, 2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2015, 2018 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
@@ -36,6 +36,8 @@
static void _sockev_event(unsigned long event, __u8 *evstr, int buflen)
{
+ memset(evstr, 0, buflen);
+
switch (event) {
case SOCKEV_SOCKET:
strlcpy(evstr, "SOCKEV_SOCKET", buflen);
@@ -67,14 +69,17 @@
struct nlmsghdr *nlh;
struct sknlsockevmsg *smsg;
struct socket *sock;
+ struct sock *sk;
sock = (struct socket *)data;
- if (socknlmsgsk == 0)
- goto done;
- if ((!socknlmsgsk) || (!sock) || (!sock->sk))
+ if (!socknlmsgsk || !sock)
goto done;
- if (sock->sk->sk_family != AF_INET && sock->sk->sk_family != AF_INET6)
+ sk = sock->sk;
+ if (!sk)
+ goto done;
+
+ if (sk->sk_family != AF_INET && sk->sk_family != AF_INET6)
goto done;
if (event != SOCKEV_BIND && event != SOCKEV_LISTEN)
@@ -95,12 +100,11 @@
smsg = nlmsg_data(nlh);
smsg->pid = current->pid;
_sockev_event(event, smsg->event, sizeof(smsg->event));
- smsg->skfamily = sock->sk->sk_family;
- smsg->skstate = sock->sk->sk_state;
- smsg->skprotocol = sock->sk->sk_protocol;
- smsg->sktype = sock->sk->sk_type;
- smsg->skflags = sock->sk->sk_flags;
-
+ smsg->skfamily = sk->sk_family;
+ smsg->skstate = sk->sk_state;
+ smsg->skprotocol = sk->sk_protocol;
+ smsg->sktype = sk->sk_type;
+ smsg->skflags = sk->sk_flags;
nlmsg_notify(socknlmsgsk, skb, 0, SKNLGRP_SOCKEV, 0, GFP_KERNEL);
done:
return 0;
diff --git a/net/ipc_router/Kconfig b/net/ipc_router/Kconfig
index 9121667..20f94aa 100644
--- a/net/ipc_router/Kconfig
+++ b/net/ipc_router/Kconfig
@@ -33,3 +33,12 @@
The NODE defined here is used as the local NODE ID by IPC Router
core and publish the same NODE ID to other NODES present in the
network.
+
+config IPC_ROUTER_FIFO_XPRT
+ depends on IPC_ROUTER
+ bool "IPC Router FIFO Transport"
+ help
+ FIFO Transport Layer that enables IPC Router communication between
+ two virtual machines. When the Shared FIFO becomes available, this
+ layer registers the transport with IPC Router and enable message
+ exchange.
diff --git a/net/ipc_router/Makefile b/net/ipc_router/Makefile
index 501688e..63d33a5 100644
--- a/net/ipc_router/Makefile
+++ b/net/ipc_router/Makefile
@@ -5,3 +5,4 @@
obj-$(CONFIG_IPC_ROUTER) := ipc_router_core.o
obj-$(CONFIG_IPC_ROUTER) += ipc_router_socket.o
obj-$(CONFIG_IPC_ROUTER_SECURITY) += ipc_router_security.o
+obj-$(CONFIG_IPC_ROUTER_FIFO_XPRT) += ipc_router_fifo_xprt.o
diff --git a/net/ipc_router/ipc_router_core.c b/net/ipc_router/ipc_router_core.c
index 1a6b539..7c12a16 100644
--- a/net/ipc_router/ipc_router_core.c
+++ b/net/ipc_router/ipc_router_core.c
@@ -31,6 +31,7 @@
#include <linux/ipc_router.h>
#include <linux/ipc_router_xprt.h>
#include <linux/kref.h>
+#include <linux/kthread.h>
#include <soc/qcom/subsystem_notif.h>
#include <soc/qcom/subsystem_restart.h>
@@ -144,12 +145,14 @@
struct mutex tx_lock_lhb2; /* lock for xprt tx operations */
u32 need_len;
u32 abort_data_read;
- struct work_struct read_data;
- struct workqueue_struct *workqueue;
void *log_ctx;
struct kref ref;
struct completion ref_complete;
bool dynamic_ws;
+
+ struct kthread_worker kworker;
+ struct task_struct *task;
+ struct kthread_work read_data;
};
#define RT_HASH_SIZE 4
@@ -176,7 +179,7 @@
static DECLARE_RWSEM(routing_table_lock_lha3);
static int routing_table_inited;
-static void do_read_data(struct work_struct *work);
+static void do_read_data(struct kthread_work *work);
static LIST_HEAD(xprt_info_list);
static DECLARE_RWSEM(xprt_info_list_lock_lha5);
@@ -2758,7 +2761,7 @@
return rc;
}
-static void do_read_data(struct work_struct *work)
+static void do_read_data(struct kthread_work *work)
{
struct rr_header_v1 *hdr;
struct rr_packet *pkt = NULL;
@@ -4077,6 +4080,7 @@
static int msm_ipc_router_add_xprt(struct msm_ipc_router_xprt *xprt)
{
struct msm_ipc_router_xprt_info *xprt_info;
+ struct sched_param param = {.sched_priority = 1};
xprt_info = kmalloc(sizeof(*xprt_info), GFP_KERNEL);
if (!xprt_info)
@@ -4092,7 +4096,6 @@
wakeup_source_init(&xprt_info->ws, xprt->name);
xprt_info->need_len = 0;
xprt_info->abort_data_read = 0;
- INIT_WORK(&xprt_info->read_data, do_read_data);
INIT_LIST_HEAD(&xprt_info->list);
kref_init(&xprt_info->ref);
init_completion(&xprt_info->ref_complete);
@@ -4100,11 +4103,17 @@
if (xprt->get_ws_info)
xprt_info->dynamic_ws = xprt->get_ws_info(xprt);
- xprt_info->workqueue = create_singlethread_workqueue(xprt->name);
- if (!xprt_info->workqueue) {
+ kthread_init_work(&xprt_info->read_data, do_read_data);
+ kthread_init_worker(&xprt_info->kworker);
+ xprt_info->task = kthread_run(kthread_worker_fn,
+ &xprt_info->kworker,
+ "%s", xprt->name);
+ if (IS_ERR(xprt_info->task)) {
kfree(xprt_info);
return -ENOMEM;
}
+ if (xprt->get_latency_info && xprt->get_latency_info(xprt))
+ sched_setscheduler(xprt_info->task, SCHED_FIFO, ¶m);
xprt_info->log_ctx = ipc_router_get_log_ctx(xprt->name);
@@ -4144,8 +4153,9 @@
mutex_lock(&xprt_info->rx_lock_lhb2);
xprt_info->abort_data_read = 1;
mutex_unlock(&xprt_info->rx_lock_lhb2);
- flush_workqueue(xprt_info->workqueue);
- destroy_workqueue(xprt_info->workqueue);
+ kthread_flush_worker(&xprt_info->kworker);
+ kthread_stop(xprt_info->task);
+ xprt_info->task = NULL;
mutex_lock(&xprt_info->rx_lock_lhb2);
list_for_each_entry_safe(pkt, temp_pkt,
&xprt_info->pkt_list, list) {
@@ -4288,7 +4298,7 @@
}
}
mutex_unlock(&xprt_info->rx_lock_lhb2);
- queue_work(xprt_info->workqueue, &xprt_info->read_data);
+ kthread_queue_work(&xprt_info->kworker, &xprt_info->read_data);
}
/**
diff --git a/net/ipc_router/ipc_router_fifo_xprt.c b/net/ipc_router/ipc_router_fifo_xprt.c
new file mode 100644
index 0000000..c90534d
--- /dev/null
+++ b/net/ipc_router/ipc_router_fifo_xprt.c
@@ -0,0 +1,500 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/ipc_router_xprt.h>
+#include <linux/io.h>
+#include <linux/of_device.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/sched.h>
+#include <microvisor/microvisor.h>
+
+#define MODULE_NAME "ipc_router_fifo_xprt"
+#define XPRT_NAME_LEN 32
+
+#define FIFO_MAGIC_KEY 0x24495043 /* "$IPC" */
+#define FIFO_SIZE 0x4000
+#define FIFO_0_START 0x1000
+#define FIFO_1_START (FIFO_0_START + FIFO_SIZE)
+#define FIFO_MAGIC_IDX 0x0
+#define TAIL_0_IDX 0x1
+#define HEAD_0_IDX 0x2
+#define TAIL_1_IDX 0x3
+#define HEAD_1_IDX 0x4
+
+struct msm_ipc_pipe {
+ __le32 *tail;
+ __le32 *head;
+
+ void *fifo;
+ size_t length;
+};
+
+/**
+ * ipcr_fifo_xprt - IPC Router's FIFO XPRT structure
+ * @xprt: IPC Router XPRT structure to contain XPRT specific info.
+ * @tx_pipe: TX FIFO specific info.
+ * @rx_pipe: RX FIFO specific info.
+ * @fifo_xprt_wq: Workqueue to queue read & other XPRT related works.
+ * @in_pkt: Pointer to any partially read packet.
+ * @read_work: Read Work to perform read operation from SMD.
+ * @sft_close_complete: Variable to indicate completion of SSR handling
+ * by IPC Router.
+ * @xprt_version: IPC Router header version supported by this XPRT.
+ * @driver: Platform drivers register by this XPRT.
+ * @xprt_name: Name of the XPRT to be registered with IPC Router.
+ */
+struct ipcr_fifo_xprt {
+ struct msm_ipc_router_xprt xprt;
+ struct msm_ipc_pipe tx_pipe;
+ struct msm_ipc_pipe rx_pipe;
+ struct workqueue_struct *xprt_wq;
+ struct rr_packet *in_pkt;
+ struct delayed_work read_work;
+ struct completion sft_close_complete;
+ unsigned int xprt_version;
+ struct platform_driver driver;
+ char xprt_name[XPRT_NAME_LEN];
+ void *fifo_base;
+ size_t fifo_size;
+ int tx_fifo_idx;
+ okl4_kcap_t kcap;
+};
+
+static void xprt_read_data(struct work_struct *work);
+static void ipcr_fifo_raise_virq(struct ipcr_fifo_xprt *xprtp);
+
+static size_t fifo_rx_avail(struct msm_ipc_pipe *pipe)
+{
+ u32 head;
+ u32 tail;
+
+ head = le32_to_cpu(*pipe->head);
+ tail = le32_to_cpu(*pipe->tail);
+
+ if (head < tail)
+ return pipe->length - tail + head;
+
+ return head - tail;
+}
+
+static void fifo_rx_peak(struct msm_ipc_pipe *pipe,
+ void *data, unsigned int offset, size_t count)
+{
+ size_t len;
+ u32 tail;
+
+ tail = le32_to_cpu(*pipe->tail);
+ tail += offset;
+ if (tail >= pipe->length)
+ tail -= pipe->length;
+
+ len = min_t(size_t, count, pipe->length - tail);
+ if (len)
+ memcpy_fromio(data, pipe->fifo + tail, len);
+
+ if (len != count)
+ memcpy_fromio(data + len, pipe->fifo, (count - len));
+}
+
+static void fifo_rx_advance(struct msm_ipc_pipe *pipe, size_t count)
+{
+ u32 tail;
+
+ tail = le32_to_cpu(*pipe->tail);
+
+ tail += count;
+ if (tail > pipe->length)
+ tail -= pipe->length;
+
+ *pipe->tail = cpu_to_le32(tail);
+}
+
+static size_t fifo_tx_avail(struct msm_ipc_pipe *pipe)
+{
+ u32 head;
+ u32 tail;
+ u32 avail;
+
+ head = le32_to_cpu(*pipe->head);
+ tail = le32_to_cpu(*pipe->tail);
+
+ if (tail <= head)
+ avail = pipe->length - head + tail;
+ else
+ avail = tail - head;
+
+ return avail;
+}
+
+static void fifo_tx_write(struct msm_ipc_pipe *pipe,
+ const void *data, size_t count)
+{
+ size_t len;
+ u32 head;
+
+ head = le32_to_cpu(*pipe->head);
+
+ len = min_t(size_t, count, pipe->length - head);
+ if (len)
+ memcpy_toio(pipe->fifo + head, data, len);
+
+ if (len != count)
+ memcpy_toio(pipe->fifo, data + len, count - len);
+
+ head += count;
+ if (head >= pipe->length)
+ head -= pipe->length;
+
+ /* Ensure ordering of fifo and head update */
+ wmb();
+
+ *pipe->head = cpu_to_le32(head);
+}
+
+/**
+ * set_xprt_version() - Set IPC Router header version in the transport
+ * @xprt: Reference to the transport structure.
+ * @version: The version to be set in transport.
+ */
+static void set_xprt_version(struct msm_ipc_router_xprt *xprt,
+ unsigned int version)
+{
+ struct ipcr_fifo_xprt *xprtp;
+
+ if (!xprt)
+ return;
+ xprtp = container_of(xprt, struct ipcr_fifo_xprt, xprt);
+ xprtp->xprt_version = version;
+}
+
+static int get_xprt_version(struct msm_ipc_router_xprt *xprt)
+{
+ struct ipcr_fifo_xprt *xprtp;
+
+ if (!xprt)
+ return -EINVAL;
+ xprtp = container_of(xprt, struct ipcr_fifo_xprt, xprt);
+ return (int)xprtp->xprt_version;
+}
+
+static int get_xprt_option(struct msm_ipc_router_xprt *xprt)
+{
+ /* fragmented data is NOT supported */
+ return 0;
+}
+
+static int xprt_close(struct msm_ipc_router_xprt *xprt)
+{
+ return 0;
+}
+
+static void xprt_sft_close_done(struct msm_ipc_router_xprt *xprt)
+{
+ struct ipcr_fifo_xprt *xprtp;
+
+ if (!xprt)
+ return;
+
+ xprtp = container_of(xprt, struct ipcr_fifo_xprt, xprt);
+ complete_all(&xprtp->sft_close_complete);
+}
+
+static int xprt_write(void *data, uint32_t len,
+ struct msm_ipc_router_xprt *xprt)
+{
+ struct rr_packet *pkt = (struct rr_packet *)data;
+ struct sk_buff *skb;
+ struct ipcr_fifo_xprt *xprtp;
+
+ xprtp = container_of(xprt, struct ipcr_fifo_xprt, xprt);
+
+ if (!pkt)
+ return -EINVAL;
+
+ if (!len || pkt->length != len)
+ return -EINVAL;
+
+ /* TODO: FIFO write : check if we can write full packet at one shot */
+ if (skb_queue_len(pkt->pkt_fragment_q) != 1) {
+ pr_err("IPC router core is given fragmented data\n");
+ return -EINVAL;
+ }
+ if (fifo_tx_avail(&xprtp->tx_pipe) < len) {
+ pr_err("No Space in FIFO\n");
+ return -EAGAIN;
+ }
+
+ skb_queue_walk(pkt->pkt_fragment_q, skb) {
+ fifo_tx_write(&xprtp->tx_pipe, skb->data, skb->len);
+ }
+
+ ipcr_fifo_raise_virq(xprtp);
+
+ return len;
+}
+
+static void xprt_read_data(struct work_struct *work)
+{
+ void *data;
+ size_t hdr_len;
+ size_t rx_avail;
+ size_t pkt_len;
+ struct rr_header_v1 hdr;
+ struct sk_buff *ipc_rtr_pkt;
+ struct ipcr_fifo_xprt *xprtp;
+ struct delayed_work *rwork = to_delayed_work(work);
+
+ xprtp = container_of(rwork, struct ipcr_fifo_xprt, read_work);
+
+ hdr_len = sizeof(struct rr_header_v1);
+ while (1) {
+ rx_avail = fifo_rx_avail(&xprtp->rx_pipe);
+ if (!rx_avail)
+ break;
+
+ fifo_rx_peak(&xprtp->rx_pipe, &hdr, 0, hdr_len);
+ pkt_len = ipc_router_peek_pkt_size((char *)&hdr);
+
+ if (pkt_len < 0) {
+ pr_err("%s invalid pkt_len %zu\n", __func__, pkt_len);
+ break;
+ }
+ if (!xprtp->in_pkt) {
+ xprtp->in_pkt = create_pkt(NULL);
+ if (!xprtp->in_pkt)
+ break;
+ }
+ ipc_rtr_pkt = alloc_skb(pkt_len, GFP_KERNEL);
+ if (!ipc_rtr_pkt) {
+ release_pkt(xprtp->in_pkt);
+ xprtp->in_pkt = NULL;
+ break;
+ }
+ data = skb_put(ipc_rtr_pkt, pkt_len);
+ do {
+ rx_avail = fifo_rx_avail(&xprtp->rx_pipe);
+ if (rx_avail >= pkt_len) {
+ fifo_rx_peak(&xprtp->rx_pipe, data, 0, pkt_len);
+ fifo_rx_advance(&xprtp->rx_pipe, pkt_len);
+ break;
+ }
+ pr_debug("%s wait for FULL PKT [avail: len][%zu:%zu]\n",
+ __func__, rx_avail, pkt_len);
+ /* wait for complete packet written into FIFO */
+ msleep(20);
+ } while (1);
+
+ skb_queue_tail(xprtp->in_pkt->pkt_fragment_q, ipc_rtr_pkt);
+ xprtp->in_pkt->length = pkt_len;
+ msm_ipc_router_xprt_notify(&xprtp->xprt,
+ IPC_ROUTER_XPRT_EVENT_DATA,
+ (void *)xprtp->in_pkt);
+ release_pkt(xprtp->in_pkt);
+ xprtp->in_pkt = NULL;
+ }
+}
+
+static void ipcr_fifo_raise_virq(struct ipcr_fifo_xprt *xprtp)
+{
+ okl4_error_t err;
+ unsigned long payload = 0xffff;
+
+ err = _okl4_sys_vinterrupt_raise(xprtp->kcap, payload);
+}
+
+static irqreturn_t ipcr_fifo_virq_handler(int irq, void *dev_id)
+{
+ struct ipcr_fifo_xprt *xprtp = dev_id;
+
+ queue_delayed_work(xprtp->xprt_wq, &xprtp->read_work, 0);
+ return IRQ_HANDLED;
+}
+
+/**
+ * ipcr_fifo_config_init() - init FIFO xprt configs
+ *
+ * @return: 0 on success, standard Linux error codes on error.
+ *
+ * This function is called to initialize the FIFO XPRT pointer with
+ * the FIFO XPRT configurations either from device tree or static arrays.
+ */
+static int ipcr_fifo_config_init(struct ipcr_fifo_xprt *xprtp)
+{
+ __le32 *descs;
+
+ descs = xprtp->fifo_base;
+ descs[FIFO_MAGIC_IDX] = FIFO_MAGIC_KEY;
+
+ if (xprtp->tx_fifo_idx) {
+ xprtp->tx_pipe.tail = &descs[TAIL_0_IDX];
+ xprtp->tx_pipe.head = &descs[HEAD_0_IDX];
+ xprtp->tx_pipe.fifo = xprtp->fifo_base + FIFO_0_START;
+ xprtp->tx_pipe.length = FIFO_SIZE;
+
+ xprtp->rx_pipe.tail = &descs[TAIL_1_IDX];
+ xprtp->rx_pipe.head = &descs[HEAD_1_IDX];
+ xprtp->rx_pipe.fifo = xprtp->fifo_base + FIFO_1_START;
+ xprtp->rx_pipe.length = FIFO_SIZE;
+ } else {
+ xprtp->tx_pipe.tail = &descs[TAIL_1_IDX];
+ xprtp->tx_pipe.head = &descs[HEAD_1_IDX];
+ xprtp->tx_pipe.fifo = xprtp->fifo_base + FIFO_1_START;
+ xprtp->tx_pipe.length = FIFO_SIZE;
+
+ xprtp->rx_pipe.tail = &descs[TAIL_0_IDX];
+ xprtp->rx_pipe.head = &descs[HEAD_0_IDX];
+ xprtp->rx_pipe.fifo = xprtp->fifo_base + FIFO_0_START;
+ xprtp->rx_pipe.length = FIFO_SIZE;
+ }
+
+ /* Reset respective index */
+ *xprtp->tx_pipe.head = 0;
+ *xprtp->rx_pipe.tail = 0;
+
+ xprtp->xprt.link_id = 1;
+ xprtp->xprt_version = 1;
+
+ strlcpy(xprtp->xprt_name, "IPCR_FIFO_XPRT", XPRT_NAME_LEN);
+ xprtp->xprt.name = xprtp->xprt_name;
+
+ xprtp->xprt.set_version = set_xprt_version;
+ xprtp->xprt.get_version = get_xprt_version;
+ xprtp->xprt.get_option = get_xprt_option;
+ xprtp->xprt.read_avail = NULL;
+ xprtp->xprt.read = NULL;
+ xprtp->xprt.write_avail = NULL;
+ xprtp->xprt.write = xprt_write;
+ xprtp->xprt.close = xprt_close;
+ xprtp->xprt.sft_close_done = xprt_sft_close_done;
+ xprtp->xprt.priv = NULL;
+
+ xprtp->in_pkt = NULL;
+ xprtp->xprt_wq = create_singlethread_workqueue(xprtp->xprt_name);
+ if (!xprtp->xprt_wq)
+ return -EFAULT;
+
+ INIT_DELAYED_WORK(&xprtp->read_work, xprt_read_data);
+
+ msm_ipc_router_xprt_notify(&xprtp->xprt,
+ IPC_ROUTER_XPRT_EVENT_OPEN,
+ NULL);
+
+ if (fifo_rx_avail(&xprtp->rx_pipe))
+ queue_delayed_work(xprtp->xprt_wq, &xprtp->read_work, 0);
+
+ return 0;
+}
+
+/**
+ * ipcr_fifo_xprt_probe() - Probe an FIFO xprt
+ *
+ * @pdev: Platform device corresponding to FIFO xprt.
+ *
+ * @return: 0 on success, standard Linux error codes on error.
+ *
+ * This function is called when the underlying device tree driver registers
+ * a platform device, mapped to an FIFO transport.
+ */
+static int ipcr_fifo_xprt_probe(struct platform_device *pdev)
+{
+ int irq;
+ int ret;
+ struct resource *r;
+ struct device *parent;
+ struct ipcr_fifo_xprt *xprtp;
+ struct device_node *ipc_irq_np;
+ struct device_node *ipc_shm_np;
+ struct platform_device *ipc_shm_dev;
+
+ xprtp = devm_kzalloc(&pdev->dev, sizeof(*xprtp), GFP_KERNEL);
+ if (IS_ERR_OR_NULL(xprtp))
+ return -ENOMEM;
+
+ parent = &pdev->dev;
+ ipc_irq_np = parent->of_node;
+
+ irq = platform_get_irq(pdev, 0);
+
+ if (irq >= 0) {
+ ret = devm_request_irq(parent, irq, ipcr_fifo_virq_handler,
+ IRQF_TRIGGER_RISING, dev_name(parent),
+ xprtp);
+ if (ret < 0)
+ return -ENODEV;
+ }
+
+ /* this kcap is required to raise VIRQ */
+ ret = of_property_read_u32(ipc_irq_np, "reg", &xprtp->kcap);
+ if (ret < 0)
+ return -ENODEV;
+
+ ipc_shm_np = of_parse_phandle(ipc_irq_np, "qcom,ipc-shm", 0);
+ if (!ipc_shm_np)
+ return -ENODEV;
+
+ ipc_shm_dev = of_find_device_by_node(ipc_shm_np);
+ if (!ipc_shm_dev)
+ return -ENODEV;
+
+ r = platform_get_resource(ipc_shm_dev, IORESOURCE_MEM, 0);
+ if (!r) {
+ pr_err("%s failed to get shared FIFO\n", __func__);
+ return -ENODEV;
+ }
+
+ xprtp->tx_fifo_idx = of_property_read_bool(ipc_shm_np,
+ "qcom,tx-is-first");
+
+ xprtp->fifo_size = resource_size(r);
+ xprtp->fifo_base = devm_ioremap_nocache(&pdev->dev, r->start,
+ resource_size(r));
+ if (!xprtp->fifo_base) {
+ pr_err("%s ioreamp_nocache() failed\n", __func__);
+ return -ENOMEM;
+ }
+
+ ret = ipcr_fifo_config_init(xprtp);
+ if (ret) {
+ IPC_RTR_ERR("%s init failed ret[%d]\n", __func__, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct of_device_id ipcr_fifo_xprt_match_table[] = {
+ { .compatible = "qcom,ipcr-fifo-xprt" },
+ {},
+};
+
+static struct platform_driver ipcr_fifo_xprt_driver = {
+ .probe = ipcr_fifo_xprt_probe,
+ .driver = {
+ .name = MODULE_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = ipcr_fifo_xprt_match_table,
+ },
+};
+
+static int __init ipcr_fifo_xprt_init(void)
+{
+ int rc;
+
+ rc = platform_driver_register(&ipcr_fifo_xprt_driver);
+ if (rc) {
+ IPC_RTR_ERR("%s: driver register failed %d\n", __func__, rc);
+ return rc;
+ }
+
+ return 0;
+}
+
+module_init(ipcr_fifo_xprt_init);
+MODULE_DESCRIPTION("IPC Router FIFO XPRT");
+MODULE_LICENSE("GPL v2");
diff --git a/net/ipc_router/ipc_router_socket.c b/net/ipc_router/ipc_router_socket.c
index a758a09..4e53861 100644
--- a/net/ipc_router/ipc_router_socket.c
+++ b/net/ipc_router/ipc_router_socket.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2018, 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
@@ -146,6 +146,7 @@
return -EINVAL;
}
ctl_msg = (union rr_control_msg *)(temp->data);
+ memset(addr, 0x0, sizeof(*addr));
addr->family = AF_MSM_IPC;
addr->address.addrtype = MSM_IPC_ADDR_ID;
addr->address.addr.port_addr.node_id = ctl_msg->cli.node_id;
@@ -154,6 +155,7 @@
return offset;
}
if (addr && (hdr->type == IPC_ROUTER_CTRL_CMD_DATA)) {
+ memset(addr, 0x0, sizeof(*addr));
addr->family = AF_MSM_IPC;
addr->address.addrtype = MSM_IPC_ADDR_ID;
addr->address.addr.port_addr.node_id = hdr->src_node_id;
diff --git a/net/wireless/core.c b/net/wireless/core.c
index c88874f..0a67d80 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -949,6 +949,7 @@
nl80211_notify_iface(rdev, wdev, NL80211_CMD_DEL_INTERFACE);
list_del_rcu(&wdev->list);
+ synchronize_rcu();
rdev->devlist_generation++;
switch (wdev->iftype) {
diff --git a/net/wireless/db.txt b/net/wireless/db.txt
index f900f5c..d82f8b4 100644
--- a/net/wireless/db.txt
+++ b/net/wireless/db.txt
@@ -594,9 +594,9 @@
country JP: DFS-JP
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (20), AUTO-BW, NO-OUTDOOR
- (5250 - 5330 @ 80), (20), DFS, AUTO-BW, NO-OUTDOOR
- (5490 - 5710 @ 160), (20), DFS
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (26), DFS, AUTO-BW, NO-OUTDOOR
+ (5490 - 5710 @ 160), (26), DFS
# 60 gHz band channels 1-4
(57240 - 65880 @ 2160), (40)
@@ -622,8 +622,8 @@
country KR: DFS-ETSI
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (20), AUTO-BW
- (5250 - 5330 @ 80), (20), DFS, AUTO-BW
- (5490 - 5730 @ 160), (30), DFS
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
(5735 - 5835 @ 80), (30)
# 60 GHz band channels 1-4,
# ref: http://www.law.go.kr/%ED%96%89%EC%A0%95%EA%B7%9C%EC%B9%99/%EB%AC%B4%EC%84%A0%EC%84%A4%EB%B9%84%EA%B7%9C%EC%B9%99
@@ -896,9 +896,10 @@
country PA:
(2402 - 2472 @ 40), (36)
- (5170 - 5250 @ 80), (23), AUT0-BW
- (5250 - 5330 @ 80), (30), AUTO-BW
- (5735 - 5835 @ 80), (36)
+ (5170 - 5250 @ 80), (30), AUT0-BW
+ (5250 - 5330 @ 80), (24), AUTO-BW
+ (5490 - 5730 @ 160), (24),
+ (5735 - 5835 @ 80), (30)
country PE: DFS-FCC
(2402 - 2482 @ 40), (20)
@@ -993,7 +994,7 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5730 @ 80), (20), DFS
+ (5490 - 5730 @ 160), (20), DFS
(5735 - 5875 @ 80), (20)
country RE: DFS-ETSI
@@ -1167,10 +1168,10 @@
# disputable definitions there.
country UA: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (20), AUTO-BW
- (5250 - 5330 @ 80), (20), DFS, AUTO-BW
- (5490 - 5670 @ 160), (20), DFS
- (5735 - 5835 @ 80), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (24)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
(57240 - 65880 @ 2160), (20)
diff --git a/security/pfe/pfk_ice.c b/security/pfe/pfk_ice.c
index 16ed516..e1d0100 100644
--- a/security/pfe/pfk_ice.c
+++ b/security/pfe/pfk_ice.c
@@ -121,7 +121,7 @@
goto out;
}
- ret = scm_call2(smc_id, &desc);
+ ret = scm_call2_noretry(smc_id, &desc);
if (ret) {
pr_err("%s: Set Key Error: %d\n", __func__, ret);
@@ -134,7 +134,7 @@
smc_id = TZ_ES_INVALIDATE_ICE_KEY_ID;
desc.arginfo = TZ_ES_INVALIDATE_ICE_KEY_PARAM_ID;
desc.args[0] = index;
- ret1 = scm_call2(smc_id, &desc);
+ ret1 = scm_call2_noretry(smc_id, &desc);
if (ret1)
pr_err("%s: Invalidate Key Error: %d\n", __func__,
ret1);
@@ -175,7 +175,7 @@
return ret;
}
- ret = scm_call2(smc_id, &desc);
+ ret = scm_call2_noretry(smc_id, &desc);
if (ret) {
pr_err("%s: Error: 0x%x\n", __func__, ret);
diff --git a/sound/usb/usb_audio_qmi_svc.c b/sound/usb/usb_audio_qmi_svc.c
index ce1f0ad..fe29aed 100644
--- a/sound/usb/usb_audio_qmi_svc.c
+++ b/sound/usb/usb_audio_qmi_svc.c
@@ -110,8 +110,8 @@
unsigned long curr_xfer_buf_iova;
/* bit fields representing pcm card enabled */
unsigned long card_slot;
- /* cache event ring phys addr */
- u64 er_phys_addr;
+ /* indicate event ring mapped or not */
+ bool er_mapped;
};
static struct uaudio_qmi_dev *uaudio_qdev;
@@ -295,7 +295,7 @@
case MEM_EVENT_RING:
va = IOVA_BASE;
/* er already mapped */
- if (uaudio_qdev->er_phys_addr == pa)
+ if (uaudio_qdev->er_mapped)
map = false;
break;
case MEM_XFER_RING:
@@ -407,8 +407,8 @@
switch (mtype) {
case MEM_EVENT_RING:
- if (uaudio_qdev->er_phys_addr)
- uaudio_qdev->er_phys_addr = 0;
+ if (uaudio_qdev->er_mapped)
+ uaudio_qdev->er_mapped = false;
else
unmap = false;
break;
@@ -637,7 +637,7 @@
uaudio_qdev->sid);
resp->xhci_mem_info.evt_ring.pa = dma;
resp->xhci_mem_info.evt_ring.size = PAGE_SIZE;
- uaudio_qdev->er_phys_addr = xhci_pa;
+ uaudio_qdev->er_mapped = true;
resp->speed_info = get_speed_info(subs->dev->speed);
if (resp->speed_info == USB_AUDIO_DEVICE_SPEED_INVALID_V01)